Wireshark-dev: [Wireshark-dev] [REPOST][PATCH] update USB dissector (was: update wiretap and su

From: Paolo Abeni <paolo.abeni@xxxxxxxx>
Date: Tue, 30 Jan 2007 09:14:47 +0100
On Fri, 2007-01-26 at 23:39 -0500, Charles Lepple wrote:
> One problem is that the proto_tree_add_* calls set the little_endian
> flag to true regardless of the endianness of the host.

This is a bug. Thanks for pointing it out. The attached patch should
solve it. 

I renew the pledge for reviewing the endianess related stuff.

Thanks again and best regards,

Paolo



 
 
 --
 Email.it, the professional e-mail, gratis per te: http://www.email.it/f
 
 Sponsor:
 Grande Offerta di Benvenuto Cassine di Pietra:
* 36 bottiglie di ottimo vino veneto direttamente a casa tua!
* 
 Clicca qui: http://adv.email.it/cgi-bin/foclick.cgi?mid=3923&d=30-1
Index: epan/dissectors/packet-usb.c
===================================================================
--- epan/dissectors/packet-usb.c	(revision 20622)
+++ 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 is in host byte order, while all the real usb data is 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
@@ -41,11 +40,21 @@
 #include <string.h>
 #include "packet-usb.h"
 
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define HOST_BYTE_ORDER 1
+#else 
+#define HOST_BYTE_ORDER 0
+#endif
+
 /* 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 +123,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 +152,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 +277,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 +332,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 +409,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 +455,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 +528,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 +542,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 +626,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 +834,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 +851,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, HOST_BYTE_ORDER);
+    offset += 8;
+
+    event = tvb_get_guint8(tvb, offset);
+    proto_tree_add_item(tree, hf_usb_urb_type, tvb, offset, 1, HOST_BYTE_ORDER);
+    offset += 1;
+
+    type = tvb_get_guint8(tvb, offset);
+    proto_tree_add_item(tree, hf_usb_transfer_type, tvb, offset, 1, HOST_BYTE_ORDER);
+    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, HOST_BYTE_ORDER);
+    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, HOST_BYTE_ORDER);
+    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, HOST_BYTE_ORDER);
+    offset += 2;
 
+    proto_tree_add_item(tree, hf_usb_setup_flag, tvb, offset, 1, HOST_BYTE_ORDER);
+    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 +908,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 +925,6 @@
     }
     pinfo->usb_conv_info=usb_conv_info;
    
-
     /* request/response matching so we can keep track of transaction specific
      * data.
      */
@@ -1023,7 +956,7 @@
 
 
     switch(type){
-    case URB_BULK_INPUT:
+    case URB_BULK:
         {
         proto_item *item;
 
@@ -1040,25 +973,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 +987,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 +1072,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 +1110,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 +1397,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 20622)
+++ 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 20622)
+++ 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