Wireshark-dev: [Wireshark-dev] [PATCH] update wiretap and sub dissector

From: Paolo Abeni <paolo.abeni@xxxxxxxx>
Date: Tue, 23 Jan 2007 09:58:55 +0100
hello,

the attached patch update the usb dissector and wiretap to sync with
current libpcap for usb sniffing.

The data link type for usb capture has been changed (and is now
DLT_USB_LINUX 189). Each usb 'packet' is preceded by a linux specific
header in host byte order. The usb data and usb header are in little
endian byte order. 

The linux header is enforced in host byte order by the wiretap/libpcap
code: when a capture saved on by a host with different endianess is
loaded and the data link is of the capture is DLT_USB_LINUX, the linux
header fields are swapped.

Please give the endianess-related stuff a serious review, because I
can't test it across machine with different endianess.

If this patch is merged, must I update the wiki to reflect current
status? 

best regards,

Paolo

p.s. the patch is against svn revision 20530

 
 
 --
 Email.it, the professional e-mail, gratis per te: http://www.email.it/f
 
 Sponsor:
 Refill s.r.l. - Tutto per la tua stampante a prezzi incredibili: su cartucce, toner, inchiostri, carta speciale risparmi fino al 90%!
 Clicca qui: http://adv.email.it/cgi-bin/foclick.cgi?mid=5189&d=23-1
Index: epan/dissectors/packet-usb.c
===================================================================
--- epan/dissectors/packet-usb.c	(revision 20530)
+++ epan/dissectors/packet-usb.c	(working copy)
@@ -1,6 +1,5 @@
 /* Man this is suboptimal.
- * The USB Header and the setup data are BIG ENDIAN
- * but all the real usb data is LITTLE ENDIAN.
+ * The USB Header endianess is the host endianess and all the real usb data are LITTLE ENDIAN.
  */
 
 /* packet-usb.c
@@ -8,7 +7,7 @@
  * $Id$
  *
  * usb basic dissector
- * By Paolo Abeni <paolo.abeni@xxxxxxxxx>
+ * By Paolo Abeni <paolo.abeni@xxxxxxxx>
  * Ronnie Sahlberg 2006
  *
  * This program is free software; you can redistribute it and/or
@@ -43,9 +42,13 @@
 
 /* protocols and header fields */
 static int proto_usb = -1;
+static int hf_usb_urb_id = -1;
+static int hf_usb_bus_id = -1;
+static int hf_usb_transfer_type = -1;
 static int hf_usb_urb_type = -1;
 static int hf_usb_device_address = -1;
-static int hf_usb_setup = -1;
+static int hf_usb_data_flag = -1;
+static int hf_usb_setup_flag = -1;
 static int hf_usb_endpoint_number = -1;
 static int hf_usb_src_endpoint_number = -1;
 static int hf_usb_dst_endpoint_number = -1;
@@ -114,35 +117,6 @@
 static dissector_table_t usb_bulk_dissector_table;
 static dissector_table_t usb_control_dissector_table;
 
-
-typedef enum { 
-  URB_CONTROL_INPUT,
-  URB_CONTROL_OUTPUT,
-  URB_ISOCHRONOUS_INPUT,
-  URB_ISOCHRONOUS_OUTPUT,
-  URB_INTERRUPT_INPUT,
-  URB_INTERRUPT_OUTPUT,
-  URB_BULK_INPUT,
-  URB_BULK_OUTPUT,
-  URB_UNKNOWN
-} urb_type_t;
-
-typedef struct usb_header {
-  guint32 urb_type;  
-  guint32 device_address;
-  guint32 endpoint_number;
-  guint32 setup_packet;
-} usb_header_t;
-
-typedef struct usb_request {
-  guint8 bmRequestType;
-  guint8 bRequest;
-  guint16 wValue;
-  guint16 wIndex;
-  guint16 wLength;
-} usb_request_t;
-
-
 static const value_string usb_langid_vals[] = {
     {0x0000,	"no language specified"},
     {0x0409,	"English (United States)"},
@@ -172,16 +146,18 @@
 };
 
 
+static const value_string usb_transfer_type_vals[] = {
+    {URB_CONTROL, "URB_CONTROL"},
+    {URB_ISOCHRONOUS,"URB_ISOCHRONOUS"},
+    {URB_INTERRUPT,"URB_INTERRUPT"},
+    {URB_BULK,"URB_BULK"},
+    {0, NULL}
+};
+
 static const value_string usb_urb_type_vals[] = {
-    {URB_CONTROL_INPUT, "URB_CONTROL_INPUT"},
-    {URB_CONTROL_OUTPUT,"URB_CONTROL_OUTPUT"},
-    {URB_ISOCHRONOUS_INPUT,"URB_ISOCHRONOUS_INPUT"},
-    {URB_ISOCHRONOUS_OUTPUT,"URB_ISOCHRONOUS_OUTPUT"},
-    {URB_INTERRUPT_INPUT,"URB_INTERRUPT_INPUT"},
-    {URB_INTERRUPT_OUTPUT,"URB_INTERRUPT_OUTPUT"},
-    {URB_BULK_INPUT,"URB_BULK_INPUT"},
-    {URB_BULK_OUTPUT,"URB_BULK_OUTPUT"},
-    {URB_UNKNOWN, "URB_UNKNOWN"},
+    {URB_SUBMIT, "URB_SUBMIT"},
+    {URB_COMPLETE,"URB_COMPLETE"},
+    {URB_ERROR,"URB_ERROR"},
     {0, NULL}
 };
 
@@ -295,7 +271,7 @@
 
     if(parent_tree){
         item=proto_tree_add_text(parent_tree, tvb, offset, 0, "DEVICE QUALIFIER DESCRIPTOR");
-	tree=proto_item_add_subtree(item, ett_descriptor_device);
+        tree=proto_item_add_subtree(item, ett_descriptor_device);
     }
 
     /* bLength */
@@ -350,7 +326,7 @@
 
     if(parent_tree){
         item=proto_tree_add_text(parent_tree, tvb, offset, 0, "DEVICE DESCRIPTOR");
-	tree=proto_item_add_subtree(item, ett_descriptor_device);
+        tree=proto_item_add_subtree(item, ett_descriptor_device);
     }
 
     /* bLength */
@@ -427,7 +403,7 @@
 
     if(parent_tree){
         item=proto_tree_add_text(parent_tree, tvb, offset, 0, "STRING DESCRIPTOR");
-	tree=proto_item_add_subtree(item, ett_descriptor_device);
+        tree=proto_item_add_subtree(item, ett_descriptor_device);
     }
 
     /* bLength */
@@ -473,7 +449,7 @@
 
     if(parent_tree){
         item=proto_tree_add_text(parent_tree, tvb, offset, 0, "INTERFACE DESCRIPTOR");
-	tree=proto_item_add_subtree(item, ett_descriptor_device);
+        tree=proto_item_add_subtree(item, ett_descriptor_device);
     }
 
     /* bLength */
@@ -546,7 +522,7 @@
 
     if(parent_tree){
         item=proto_tree_add_text(parent_tree, tvb, offset, 0, "ENDPOINT DESCRIPTOR");
-	tree=proto_item_add_subtree(item, ett_descriptor_device);
+        tree=proto_item_add_subtree(item, ett_descriptor_device);
     }
 
     /* bLength */
@@ -560,7 +536,7 @@
     /* bEndpointAddress */
     if(tree){
         endpoint_item=proto_tree_add_item(tree, hf_usb_bEndpointAddress, tvb, offset, 1, TRUE);
-	endpoint_tree=proto_item_add_subtree(endpoint_item, ett_configuration_bEndpointAddress);
+        endpoint_tree=proto_item_add_subtree(endpoint_item, ett_configuration_bEndpointAddress);
     }
     endpoint=tvb_get_guint8(tvb, offset)&0x0f;
     proto_tree_add_item(endpoint_tree, hf_usb_bEndpointAddress_direction, tvb, offset, 1, TRUE);
@@ -644,7 +620,7 @@
 
     if(parent_tree){
         item=proto_tree_add_text(parent_tree, tvb, offset, 0, "CONFIGURATION DESCRIPTOR");
-	tree=proto_item_add_subtree(item, ett_descriptor_device);
+        tree=proto_item_add_subtree(item, ett_descriptor_device);
     }
 
     /* bLength */
@@ -852,8 +828,8 @@
 dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent)
 {
     int offset = 0;
-    int type, endpoint;
-    gboolean setup;
+    int type, endpoint, event;
+    guint8 setup_flag;
     proto_tree *tree = NULL;
     guint32 src_device, dst_device, tmp_addr;
     static usb_address_t src_addr, dst_addr; /* has to be static due to SET_ADDRESS */
@@ -869,102 +845,55 @@
     /* add usb hdr*/    
     if (parent) {
       proto_item *ti = NULL;
-      ti = proto_tree_add_protocol_format(parent, proto_usb, tvb, 0, sizeof(usb_header_t), "USB URB");
+      ti = proto_tree_add_protocol_format(parent, proto_usb, tvb, 0, sizeof(struct usb_request_hdr), "USB URB");
 
       tree = proto_item_add_subtree(ti, usb_hdr);
     }
 
-    
-    type = tvb_get_ntohl(tvb, offset);
-    proto_tree_add_item(tree, hf_usb_urb_type, tvb, offset, 4, FALSE);
-    offset += 4;
+    proto_tree_add_item(tree, hf_usb_urb_id, tvb, offset, 8, TRUE);
+    offset += 8;
+
+    event = tvb_get_guint8(tvb, offset);
+    proto_tree_add_item(tree, hf_usb_urb_type, tvb, offset, 1, TRUE);
+    offset += 1;
+
+    type = tvb_get_guint8(tvb, offset);
+    proto_tree_add_item(tree, hf_usb_transfer_type, tvb, offset, 1, TRUE);
+    offset += 1;
     if (check_col(pinfo->cinfo, COL_INFO)) {
         col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
             val_to_str(type, usb_urb_type_vals, "Unknown type %x"));
     }
 
-    proto_tree_add_item(tree, hf_usb_device_address, tvb, offset, 4, FALSE);
-    tmp_addr=tvb_get_ntohl(tvb, offset);
-    offset += 4;
+    proto_tree_add_item(tree, hf_usb_endpoint_number, tvb, offset, 1, TRUE);
+    endpoint=tvb_get_guint8(tvb, offset);
+    offset += 1;
 
-    proto_tree_add_item(tree, hf_usb_endpoint_number, tvb, offset, 4, FALSE);
-    endpoint=tvb_get_ntohl(tvb, offset);
-    offset += 4;
+    proto_tree_add_item(tree, hf_usb_device_address, tvb, offset, 1, TRUE);
+    tmp_addr=tvb_get_guint8(tvb, offset);
+    offset += 1;
 
-    /* check for setup hdr presence */
-    proto_tree_add_item(tree, hf_usb_setup, tvb, offset, 4, FALSE);
-    setup = tvb_get_ntohl(tvb, offset);
-    offset += 4;
+    proto_tree_add_item(tree, hf_usb_bus_id, tvb, offset, 2, TRUE);
+    offset += 2;
 
+    proto_tree_add_item(tree, hf_usb_setup_flag, tvb, offset, 1, TRUE);
+    setup_flag = tvb_get_guint8(tvb, offset);
+    offset += 26;
 
     /* set up addresses and ports */
-    switch(type){
-    case URB_BULK_INPUT:
-        /* Bulk input are responses if they contain payload data and
-         * requests otherwise.
-         */
-        if(tvb_length_remaining(tvb, offset)>0){
-            src_device=tmp_addr;
-            src_endpoint=endpoint;
-            dst_device=0xffffffff;
-            dst_endpoint=NO_ENDPOINT;
-            is_request=FALSE;
-        } else {
-            src_device=0xffffffff;
-            src_endpoint=NO_ENDPOINT;
-            dst_device=tmp_addr;
-            dst_endpoint=endpoint;
-            is_request=TRUE;
-        }
-        break;
-    case URB_BULK_OUTPUT:
-        /* Bulk output are requests if they contain payload data and
-         * responses otherwise.
-         */
-        if(tvb_length_remaining(tvb, offset)>0){
-            src_device=0xffffffff;
-            src_endpoint=NO_ENDPOINT;
-            dst_device=tmp_addr;
-            dst_endpoint=endpoint;
-            is_request=TRUE;
-        } else {
-            src_device=tmp_addr;
-            src_endpoint=endpoint;
-            dst_device=0xffffffff;
-            dst_endpoint=NO_ENDPOINT;
-            is_request=FALSE;
-        }
-        break;
-    case URB_CONTROL_INPUT:
-        /* CONTROL INPUT packets are requests if they contain a "setup"
-         * blob and responses othervise
-         */
-        if(setup){
-            src_device=0xffffffff;
-            src_endpoint=NO_ENDPOINT;
-            dst_device=tmp_addr;
-            dst_endpoint=endpoint;
-            is_request=TRUE;
-        } else {
-            src_device=tmp_addr;
-            src_endpoint=endpoint;
-            dst_device=0xffffffff;
-            dst_endpoint=NO_ENDPOINT;
-            is_request=FALSE;
-        }
-        break;
-    default:
-        /* dont know */
-        src_device=0xffffffff;
-        dst_device=0xffffffff;
-        src_endpoint=NO_ENDPOINT;
-        dst_endpoint=NO_ENDPOINT;
-        is_request=FALSE;
+    is_request = endpoint & URB_TRANSFER_IN;
+    if (is_request){
+        src_addr.device = src_device = tmp_addr;
+        src_addr.endpoint = src_endpoint = endpoint;
+        dst_addr.device = dst_device = 0xffffffff;
+        dst_addr.endpoint = dst_endpoint = NO_ENDPOINT;
+    } else {
+        src_addr.device = src_device = 0xffffffff;
+        src_addr.endpoint = src_endpoint = NO_ENDPOINT;
+        dst_addr.device = src_device = tmp_addr;
+        dst_addr.endpoint = src_endpoint = endpoint;
     }
-    src_addr.device = src_device;
-    src_addr.endpoint = src_endpoint;
-    dst_addr.device = dst_device;
-    dst_addr.endpoint = dst_endpoint;
+
     SET_ADDRESS(&pinfo->net_src, AT_USB, USB_ADDR_LEN, (char *)&src_addr);
     SET_ADDRESS(&pinfo->src, AT_USB, USB_ADDR_LEN, (char *)&src_addr);
     SET_ADDRESS(&pinfo->net_dst, AT_USB, USB_ADDR_LEN, (char *)&dst_addr);
@@ -973,7 +902,6 @@
     pinfo->srcport=src_endpoint;
     pinfo->destport=dst_endpoint;
 
-
     conversation=get_usb_conversation(pinfo, pinfo->srcport, pinfo->destport);
 
     usb_conv_info=get_usb_conv_info(conversation);
@@ -991,7 +919,6 @@
     }
     pinfo->usb_conv_info=usb_conv_info;
    
-
     /* request/response matching so we can keep track of transaction specific
      * data.
      */
@@ -1023,7 +950,7 @@
 
 
     switch(type){
-    case URB_BULK_INPUT:
+    case URB_BULK:
         {
         proto_item *item;
 
@@ -1040,25 +967,8 @@
         }
         }
         break;
-    case URB_BULK_OUTPUT:
+    case URB_CONTROL:
         {
-        proto_item *item;
-
-        item=proto_tree_add_uint(tree, hf_usb_bInterfaceClass, tvb, offset, 0, usb_conv_info->class);
-        PROTO_ITEM_SET_GENERATED(item);
-        if(tvb_length_remaining(tvb, offset)){
-            tvbuff_t *next_tvb;
-
-            pinfo->usb_conv_info=usb_conv_info;
-            next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_reported_length_remaining(tvb, offset));
-            if(dissector_try_port(usb_bulk_dissector_table, usb_conv_info->class, next_tvb, pinfo, parent)){
-                return;
-            }
-        }
-        }
-        break;
-    case URB_CONTROL_INPUT:
-        {
         const usb_setup_dissector_table_t *tmp;
         usb_setup_dissector dissector;
         proto_item *ti = NULL;
@@ -1071,7 +981,7 @@
             tvbuff_t *next_tvb;
 
             /* this is a request */
-            ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(usb_request_t), "URB setup");
+            ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(struct usb_request_hdr), "URB setup");
             setup_tree = proto_item_add_subtree(ti, usb_setup_hdr);
             usb_trans_info->requesttype=tvb_get_guint8(tvb, offset);        
             offset=dissect_usb_bmrequesttype(setup_tree, tvb, offset);
@@ -1156,33 +1066,35 @@
         break;
     default:
         /* dont know */
-	;
+        ;
     }
 
 
-    if (setup) {
+    if (setup_flag == 0) {
         proto_item *ti = NULL;
         proto_tree *setup_tree = NULL;
         guint8 requesttype, request;
 
-        ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(usb_request_t), "URB setup");
+        ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(struct usb_request_hdr), "URB setup");
         setup_tree = proto_item_add_subtree(ti, usb_setup_hdr);
 
 
         requesttype=tvb_get_guint8(tvb, offset);        
-	offset=dissect_usb_bmrequesttype(setup_tree, tvb, offset);
+        offset=dissect_usb_bmrequesttype(setup_tree, tvb, offset);
 
         request=tvb_get_guint8(tvb, offset);
-        proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, FALSE);
+        proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, TRUE);
         offset += 1;
 
-        proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, FALSE);
+        proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, TRUE);
         offset += 2;
-        proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, FALSE);
+        proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, TRUE);
         offset += 2;
-        proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, FALSE);
+        proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, TRUE);
         offset += 2;
     }
+    else
+        offset += 8;
     
     proto_tree_add_item(tree, hf_usb_data, tvb,
         offset, tvb_length_remaining(tvb, offset), FALSE);
@@ -1192,30 +1104,49 @@
 proto_register_usb(void)
 {
     static hf_register_info hf[] = {
-    
+
+        { &hf_usb_urb_id,
+        { "URB id", "usb.urb_id", FT_UINT64, BASE_DEC, 
+                NULL, 0x0,
+                "URB id", HFILL }},
+
+        { &hf_usb_bus_id,
+        { "URB bus id", "usb.bus_id", FT_UINT16, BASE_DEC, 
+                NULL, 0x0,
+                "URB bus id", HFILL }},
+
         { &hf_usb_urb_type,
-        { "URB type", "usb.urb_type", FT_UINT32, BASE_DEC, 
+        { "URB type", "usb.urb_type", FT_UINT8, BASE_DEC, 
                 VALS(usb_urb_type_vals), 0x0,
                 "URB type", HFILL }},
 
+        { &hf_usb_transfer_type,
+        { "URB transfer type", "usb.transfer_type", FT_UINT8, BASE_DEC, 
+                VALS(usb_transfer_type_vals), 0x0,
+                "URB transfer type", HFILL }},
+
         { &hf_usb_device_address,
-        { "Device", "usb.device_address", FT_UINT32, BASE_DEC, NULL, 0x0,
+        { "Device", "usb.device_address", FT_UINT8, BASE_DEC, NULL, 0x0,
                 "USB device address", HFILL }},
 
-        { &hf_usb_setup,
-        { "Setup", "usb.setup", FT_UINT32, BASE_DEC, NULL, 0x0,
-                 "USB setup", HFILL }},
+        { &hf_usb_data_flag,
+        { "Flags", "usb.data_flag", FT_UINT8, BASE_DEC, NULL, 0x0,
+                 "USB data flag", HFILL }},
 
+        { &hf_usb_setup_flag,
+        { "Flags", "usb.data_flag", FT_UINT8, BASE_DEC, NULL, 0x0,
+                 "USB data flag", HFILL }},
+
         { &hf_usb_endpoint_number,
-        { "Endpoint", "usb.endpoint_number", FT_UINT32, BASE_HEX, NULL, 0x0,
+        { "Endpoint", "usb.endpoint_number", FT_UINT8, BASE_HEX, NULL, 0x0,
                 "usb endpoint number", HFILL }},
 
         { &hf_usb_src_endpoint_number,
-        { "Src Endpoint", "usb.src.endpoint", FT_UINT32, BASE_HEX, NULL, 0x0,
+        { "Src Endpoint", "usb.src.endpoint", FT_UINT8, BASE_HEX, NULL, 0x0,
                 "src usb endpoint number", HFILL }},
 
         { &hf_usb_dst_endpoint_number,
-        { "Dst Endpoint", "usb.dst.endpoint", FT_UINT32, BASE_HEX, NULL, 0x0,
+        { "Dst Endpoint", "usb.dst.endpoint", FT_UINT8, BASE_HEX, NULL, 0x0,
                 "dst usb endpoint number", HFILL }},
 
         { &hf_usb_bmRequestType,
@@ -1460,5 +1391,5 @@
     dissector_handle_t usb_handle;
     usb_handle = create_dissector_handle(dissect_usb, proto_usb);
 
-    dissector_add("wtap_encap", WTAP_ENCAP_USB, usb_handle);
+    dissector_add("wtap_encap", WTAP_ENCAP_USB_LINUX, usb_handle);
 }
Index: wiretap/wtap.h
===================================================================
--- wiretap/wtap.h	(revision 20530)
+++ wiretap/wtap.h	(working copy)
@@ -182,16 +182,17 @@
 #define WTAP_ENCAP_JUNIPER_FRELAY               85
 #define WTAP_ENCAP_JUNIPER_CHDLC                86
 #define WTAP_ENCAP_JUNIPER_GGSN                 87
-#define WTAP_ENCAP_LINUX_LAPD			88
+#define WTAP_ENCAP_LINUX_LAPD                   88
 #define WTAP_ENCAP_CATAPULT_DCT2000             89
 #define WTAP_ENCAP_BER                          90
 #define WTAP_ENCAP_JUNIPER_VP                   91
-#define WTAP_ENCAP_USB				92
+#define WTAP_ENCAP_USB                          92
 #define WTAP_ENCAP_IEEE802_16_MAC_CPS		93
 #define WTAP_ENCAP_NETTL_RAW_TELNET		94
+#define WTAP_ENCAP_USB_LINUX                    95
 
 /* last WTAP_ENCAP_ value + 1 */
-#define WTAP_NUM_ENCAP_TYPES			95
+#define WTAP_NUM_ENCAP_TYPES			96
 
 /* File types that can be read by wiretap.
    We support writing some many of these file types, too, so we
@@ -275,6 +276,55 @@
  * of that.
  */
 
+#define URB_TRANSFER_IN   0x80
+
+/*
+ * possible transfer mode
+ */
+#define URB_ISOCHRONOUS   0x0
+#define URB_INTERRUPT     0x1
+#define URB_CONTROL       0x2
+#define URB_BULK          0x3
+
+/*
+ * possible event type
+ */
+#define URB_SUBMIT        'S'
+#define URB_COMPLETE      'C'
+#define URB_ERROR         'E'
+
+/*
+ * USB setup header as defined in USB specification 
+ */
+struct usb_request_hdr {
+    gint8 bmRequestType;
+    guint8 bRequest;
+    guint16 wValue;
+    guint16 wIndex;
+    guint16 wLength;
+};
+
+/*
+ * Header prepent by linux kernel to each USB event
+ */
+struct linux_usb_phdr {
+    guint64 id;             /* urb id, to link submission and completion events*/
+    guint8 event_type;      /* Submit ('S'), Completed ('C'), Error ('E')  */
+    guint8 transfer_type;   /* ISO (0), Intr, Control, Bulk (3) */
+    guint8 endpoint_number; /* Endpoint number and transfer direction */
+    guint8 device_address;
+    guint16 bus_id;
+    gint8 setup_flag;       /*if !=0 the urb setup header is not present*/
+    gint8 data_flag;        /*if !=0 no urb data is present*/
+    gint64 ts_sec;
+    gint32 ts_usec;
+    gint32 status;
+    guint32 urb_len;        /* whole len of urb this event refear to */
+    guint32 data_len;       /* amount of urb data really present in this event*/
+    struct usb_request_hdr setup; /* this is valid only if setup_flag is 0 */
+};
+    
+
 /* Packet "pseudo-header" information for Ethernet capture files. */
 struct eth_phdr {
 	gint	fcs_len;	/* Number of bytes of FCS - -1 means "unknown" */
Index: wiretap/libpcap.c
===================================================================
--- wiretap/libpcap.c	(revision 20530)
+++ wiretap/libpcap.c	(working copy)
@@ -143,6 +143,7 @@
 static void libpcap_close(wtap *wth);
 static gboolean libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
     const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
+static void libpcap_fixate_usb_hdr(guchar* pd, int caplen);
 
 /*
  * Either LBL NRG wasn't an adequate central registry (e.g., because of
@@ -416,7 +417,8 @@
 	{ 187, 		WTAP_ENCAP_BLUETOOTH_H4 },
 	/* IEEE 802.16 MAC Common Part Sublayer */
 	{ 188,		WTAP_ENCAP_IEEE802_16_MAC_CPS },
-
+        /* USB packets with linux specified header */
+	{ 189, 		WTAP_ENCAP_USB_LINUX },
 	/*
 	 * To repeat:
 	 *
@@ -1393,6 +1395,8 @@
 			}
 		}
 	}
+	if ((wth->file_encap == WTAP_ENCAP_USB_LINUX) && wth->capture.pcap->byte_swapped)
+		libpcap_fixate_usb_hdr(buffer_start_ptr(wth->frame_buffer), wth->phdr.caplen);
 
 	return TRUE;
 }
@@ -1499,6 +1503,8 @@
 				atm_guess_lane_type(pd, length, pseudo_header);
 		}
 	}
+	if ((wth->file_encap == WTAP_ENCAP_USB_LINUX) && wth->capture.pcap->byte_swapped)
+		libpcap_fixate_usb_hdr(pd, length);
 	return TRUE;
 }
 
@@ -1941,6 +1947,33 @@
 	return -1;
 }
 
+static 
+void libpcap_fixate_usb_hdr(guchar* pd, int caplen)
+{
+	struct linux_usb_phdr* phdr = (struct linux_usb_phdr*) pd;
+	if (caplen < 8)
+		return;
+	phdr->id = GUINT64_SWAP_LE_BE(phdr->id);
+	if (caplen < 14)
+		return;
+	phdr->bus_id = GUINT16_SWAP_LE_BE(phdr->bus_id);
+	if (caplen < 24)
+		return;
+	phdr->ts_sec = GUINT64_SWAP_LE_BE(phdr->ts_sec);
+	if (caplen < 28)
+		return;
+	phdr->ts_usec = GUINT32_SWAP_LE_BE(phdr->ts_usec);
+	if (caplen < 32)
+		return;
+	phdr->status = GUINT32_SWAP_LE_BE(phdr->status);
+	if (caplen < 36)
+		return;
+	phdr->urb_len = GUINT32_SWAP_LE_BE(phdr->urb_len);
+	if (caplen < 40)
+		return;
+	phdr->data_len = GUINT32_SWAP_LE_BE(phdr->data_len);
+}
+
 #ifdef HAVE_PCAP_H
 /*
  * Given a Wiretap encapsulation type, and raw packet data and the packet