On 25/01/18(Thu) 14:55, Bryan Steele wrote:
> On Thu, Jan 25, 2018 at 07:00:43PM +0100, Martin Pieuchot wrote:
> > Diff below adds support for dumping USB transfers via bpf(4), including
> > the tcpdump(8) bits.
> > 
> > I'd like special review of the new bpf_tap(9) function I'm introducing:
> >   - is there a way to pass the header as a different buffer?
> >   - is _bpf_tap() the best way to share code with bpf_mtap(9)?
> > 
> > Concerning the kernel/userland interface, in looked at the existing
> > DLT_USB*, namely:
> >     - DLT_USB_FREEBSD (a.k.a DLT_USB)
> >     - DLT_USB_LINUX
> >     - DLT_USB_LINUX_MMAPPED
> >     - DLT_USBPCAP
> >     - DLT_USB_DARWIN
> > 
> > I decided to follow DLT_USBPCAP which is the most generic one beside
> > being originated from Windows.  Wireshark has some support for it
> > (currently untested) so it is a nice fit.
> > The current implementation is small and I'd like to continue developing
> > it in tree.
> > 
> > Here's an excerpt of what's happening when plugging a USB key: 
> > 
> >      # tcpdump -xXi usb0
> >      tcpdump: listening on usb0, link-type USBPCAP
> >      [...]
> >      18:56:26.261293 bus 0 > addr 5: ep0 ctrl 0
> >      
> >      18:56:26.261409 bus 0 < addr 5: ep0 ctrl 20
> >        0000: 1403 5300 6c00 6900 6d00 2000 4c00 6900  ..S.l.i.m. .L.i.
> >        0010: 6e00 6500                                n.e.
> >      
> >      18:56:26.261418 bus 0 > addr 5: ep0 ctrl 0
> >      
> >      18:56:26.261547 bus 0 < addr 5: ep0 ctrl 2
> >        0000: 2203                                     ".
> >      
> >      18:56:26.261552 bus 0 > addr 5: ep0 ctrl 0
> >      
> >      18:56:26.261746 bus 0 < addr 5: ep0 ctrl 34
> >        0000: 2203 3000 3700 3100 3000 3500 3900 3600  ".0.7.1.0.5.9.6.
> >        0010: 3100 4100 3400 3800 4400 3600 4100 3900  1.A.4.8.D.6.A.9.
> >        0020: 3500                                     5.
> >      
> >      18:56:26.261761 bus 0 > addr 5: ep2 bulk 31
> >        0000: 5553 4243 4c00 0000 0000 0000 0000 0600  USBCL...........
> >        0010: 0000 0000 0000 0000 0000 0000 0000 00    ...............
> > 
> > Ok to put it in tree?
> 
> 
> This looks really cool, hopefully might be useful for diagnosing the
> constantly reattaching issues I've been seeing with USB mouses..
> 
> Looks like you forgot to add print-usbpcap.c for tcpdump.

Indeed, full diff below.

Index: sys/net/bpf.c
===================================================================
RCS file: /cvs/src/sys/net/bpf.c,v
retrieving revision 1.166
diff -u -p -r1.166 bpf.c
--- sys/net/bpf.c       24 Jan 2018 00:25:17 -0000      1.166
+++ sys/net/bpf.c       25 Jan 2018 14:02:58 -0000
@@ -1226,35 +1226,24 @@ bpf_mcopy(const void *src_arg, void *dst
        }
 }
 
-/*
- * like bpf_mtap, but copy fn can be given. used by various bpf_mtap*
- */
 int
-_bpf_mtap(caddr_t arg, const struct mbuf *m, u_int direction,
-    void (*cpfn)(const void *, void *, size_t))
+_bpf_tap(caddr_t arg, u_char *pkt, size_t pktlen, u_int direction,
+    void (*cpfn)(const void *, void *, size_t), int mfilter)
 {
        struct bpf_if *bp = (struct bpf_if *)arg;
        struct srp_ref sr;
        struct bpf_d *d;
-       size_t pktlen, slen;
-       const struct mbuf *m0;
+       size_t slen;
        struct timeval tv;
        int gottime = 0;
        int drop = 0;
 
-       if (m == NULL)
+       if (pkt == NULL)
                return (0);
 
-       if (cpfn == NULL)
-               cpfn = bpf_mcopy;
-
        if (bp == NULL)
                return (0);
 
-       pktlen = 0;
-       for (m0 = m; m0 != NULL; m0 = m0->m_next)
-               pktlen += m0->m_len;
-
        SRPL_FOREACH(d, &sr, &bp->bif_dlist, bd_next) {
                atomic_inc_long(&d->bd_rcount);
 
@@ -1268,7 +1257,11 @@ _bpf_mtap(caddr_t arg, const struct mbuf
                        bf = srp_enter(&bsr, &d->bd_rfilter);
                        if (bf != NULL)
                                fcode = bf->bf_insns;
-                       slen = bpf_mfilter(fcode, m, pktlen);
+                       if (mfilter) {
+                               const struct mbuf *m = (const struct mbuf *)pkt;
+                               slen = bpf_mfilter(fcode, m, pktlen);
+                       } else
+                               slen = bpf_filter(fcode, pkt, pktlen, pktlen);
                        srp_leave(&bsr);
                }
 
@@ -1277,8 +1270,7 @@ _bpf_mtap(caddr_t arg, const struct mbuf
                                microtime(&tv);
 
                        mtx_enter(&d->bd_mtx);
-                       bpf_catchpacket(d, (u_char *)m, pktlen, slen, cpfn,
-                           &tv);
+                       bpf_catchpacket(d, pkt, pktlen, slen, cpfn, &tv);
                        mtx_leave(&d->bd_mtx);
 
                        if (d->bd_fildrop)
@@ -1290,6 +1282,35 @@ _bpf_mtap(caddr_t arg, const struct mbuf
        return (drop);
 }
 
+int
+bpf_tap(caddr_t arg, u_char *pkt, size_t pktlen, u_int direction)
+{
+       return _bpf_tap(arg, pkt, pktlen, direction, bcopy, 0);
+}
+
+/*
+ * like bpf_mtap, but copy fn can be given. used by various bpf_mtap*
+ */
+int
+_bpf_mtap(caddr_t arg, const struct mbuf *m, u_int direction,
+    void (*cpfn)(const void *, void *, size_t))
+{
+       const struct mbuf *m0;
+       size_t pktlen;
+
+       if (m == NULL)
+               return (0);
+
+       if (cpfn == NULL)
+               cpfn = bpf_mcopy;
+
+       pktlen = 0;
+       for (m0 = m; m0 != NULL; m0 = m0->m_next)
+               pktlen += m0->m_len;
+
+       return _bpf_tap(arg, (u_char *)m, pktlen, direction, cpfn, 1);
+}
+
 /*
  * Incoming linkage from device drivers, when packet is in an mbuf chain.
  */
@@ -1790,7 +1811,7 @@ bpf_mbuf_copy(const struct mbuf *m, u_in
 
        for (;;) {
                count = min(m->m_len - off, len);
-               
+
                memcpy(cp, m->m_data + off, count);
                len -= count;
 
Index: sys/net/bpf.h
===================================================================
RCS file: /cvs/src/sys/net/bpf.h,v
retrieving revision 1.63
diff -u -p -r1.63 bpf.h
--- sys/net/bpf.h       24 Jan 2018 00:25:17 -0000      1.63
+++ sys/net/bpf.h       25 Jan 2018 16:06:35 -0000
@@ -201,6 +201,7 @@ struct bpf_hdr {
 #define DLT_USER13             160     /* Reserved for private use */
 #define DLT_USER14             161     /* Reserved for private use */
 #define DLT_USER15             162     /* Reserved for private use */
+#define DLT_USBPCAP            249     /* USBPcap */
 #define DLT_MPLS               219     /* MPLS Provider Edge header */
 #define DLT_OPENFLOW           267     /* in-kernel OpenFlow, by pcap */
 
@@ -306,6 +307,7 @@ struct ifnet;
 struct mbuf;
 
 int     bpf_validate(struct bpf_insn *, int);
+int     bpf_tap(caddr_t arg, u_char *, size_t, u_int);
 int     bpf_mtap(caddr_t, const struct mbuf *, u_int);
 int     bpf_mtap_hdr(caddr_t, caddr_t, u_int, const struct mbuf *, u_int,
            void (*)(const void *, void *, size_t));
Index: usr.sbin/tcpdump/Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/Makefile,v
retrieving revision 1.62
diff -u -p -r1.62 Makefile
--- usr.sbin/tcpdump/Makefile   30 Oct 2017 10:07:44 -0000      1.62
+++ usr.sbin/tcpdump/Makefile   25 Jan 2018 17:10:15 -0000
@@ -49,7 +49,7 @@ SRCS= tcpdump.c addrtoname.c privsep.c p
        print-etherip.c print-lwres.c print-lldp.c print-cdp.c print-pflog.c \
        print-pfsync.c pf_print_state.c print-ofp.c ofp_map.c \
        print-udpencap.c print-carp.c \
-       print-802_11.c print-iapp.c print-mpls.c print-slow.c \
+       print-802_11.c print-iapp.c print-mpls.c print-slow.c print-usbpcap.c \
        gmt2local.c savestr.c setsignal.c in_cksum.c
 
 # TCP OS Fingerprinting
Index: usr.sbin/tcpdump/interface.h
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/interface.h,v
retrieving revision 1.69
diff -u -p -r1.69 interface.h
--- usr.sbin/tcpdump/interface.h        16 Nov 2016 13:47:27 -0000      1.69
+++ usr.sbin/tcpdump/interface.h        25 Jan 2018 17:13:09 -0000
@@ -276,6 +276,8 @@ extern void slow_print(const u_char *, u
 extern void gtp_print(const u_char *, u_int, u_short, u_short);
 extern void ofp_print(const u_char *, u_int);
 extern void ofp_if_print(u_char *, const struct pcap_pkthdr *, const u_char *);
+extern void usbpcap_if_print(u_char *, const struct pcap_pkthdr *,
+    const u_char *);
 
 #ifdef INET6
 extern void ip6_print(const u_char *, u_int);
Index: usr.sbin/tcpdump/print-usbpcap.c
===================================================================
RCS file: usr.sbin/tcpdump/print-usbpcap.c
diff -N usr.sbin/tcpdump/print-usbpcap.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ usr.sbin/tcpdump/print-usbpcap.c    25 Jan 2018 17:44:57 -0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018 Martin Pieuchot <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbpcap.h>
+
+#include <pcap.h>
+
+#include "interface.h"
+
+#ifndef nitems
+#define nitems(_a)     (sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
+const char *usbpcap_xfer_type[] = {"isoc", "intr", "ctrl", "bulk"};
+
+void
+usbpcap_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
+{
+       u_int length = h->len;
+       u_int caplen = h->caplen;
+       const struct usbpcap_hdr *uph;
+
+       ts_print(&h->ts);
+
+       /* check length */
+       if (caplen < sizeof(uint16_t)) {
+               printf("[|usb]");
+               goto out;
+       }
+       uph = (struct usbpcap_hdr *)p;
+       if (uph->hlen < sizeof(*uph)) {
+               printf("[usb: invalid header length %u!]", uph->hlen);
+               goto out;
+       }
+
+       if (caplen < uph->hlen) {
+               printf("[|usb]");
+               goto out;
+       }
+
+       printf("bus %u %c addr %u: ep%u",
+           uph->bus, ((uph->info & USBPCAP_INFO_PDO_TO_FDO) ? '<' : '>'),
+           uph->devaddr, UE_GET_ADDR(uph->epaddr));
+
+       if (uph->xfertype < nitems(usbpcap_xfer_type))
+               printf(" %s", usbpcap_xfer_type[uph->xfertype]);
+       else
+               printf(" ??");
+
+       printf(" %u", uph->dlen);
+
+       if (xflag)
+               default_print(p + sizeof(*uph), length - sizeof(*uph));
+out:
+       putchar('\n');
+}
Index: usr.sbin/tcpdump/tcpdump.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/tcpdump.c,v
retrieving revision 1.81
diff -u -p -r1.81 tcpdump.c
--- usr.sbin/tcpdump/tcpdump.c  8 Dec 2017 17:04:15 -0000       1.81
+++ usr.sbin/tcpdump/tcpdump.c  25 Jan 2018 17:10:08 -0000
@@ -127,6 +127,7 @@ static struct printer printers[] = {
        { ieee802_11_if_print,          DLT_IEEE802_11 },
        { ieee802_11_radio_if_print,    DLT_IEEE802_11_RADIO },
        { ofp_if_print,                 DLT_OPENFLOW },
+       { usbpcap_if_print,             DLT_USBPCAP },
        { NULL,                         0 },
 };
 
Index: lib/libpcap/gencode.c
===================================================================
RCS file: /cvs/src/lib/libpcap/gencode.c,v
retrieving revision 1.46
diff -u -p -r1.46 gencode.c
--- lib/libpcap/gencode.c       20 Nov 2016 12:45:26 -0000      1.46
+++ lib/libpcap/gencode.c       25 Jan 2018 17:09:17 -0000
@@ -787,6 +787,8 @@ init_linktype(type)
                off_nl = 12;
                return;
 
+       case DLT_USBPCAP:
+               /* FALLTHROUGH */
        case DLT_RAW:
                off_linktype = -1;
                off_nl = 0;
Index: lib/libpcap/pcap.c
===================================================================
RCS file: /cvs/src/lib/libpcap/pcap.c,v
retrieving revision 1.20
diff -u -p -r1.20 pcap.c
--- lib/libpcap/pcap.c  16 Nov 2016 13:47:27 -0000      1.20
+++ lib/libpcap/pcap.c  25 Jan 2018 17:09:23 -0000
@@ -326,6 +326,7 @@ DLT_CHOICE(DLT_IEEE802_11, "IEEE 802.11 
 DLT_CHOICE(DLT_PFLOG, "Packet filter logging, by pcap people"),
 DLT_CHOICE(DLT_IEEE802_11_RADIO, "IEEE 802.11 plus WLAN header"),
 DLT_CHOICE(DLT_OPENFLOW, "OpenFlow"),
+DLT_CHOICE(DLT_USBPCAP, "USB"),
 #undef DLT_CHOICE
        { NULL, NULL, -1}
 };
Index: sys/dev/usb/usb.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb.c,v
retrieving revision 1.114
diff -u -p -r1.114 usb.c
--- sys/dev/usb/usb.c   29 Jul 2017 18:26:14 -0000      1.114
+++ sys/dev/usb/usb.c   25 Jan 2018 17:41:40 -0000
@@ -63,6 +63,8 @@
 #include <machine/bus.h>
 
 #include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+#include <dev/usb/usbpcap.h>
 
 #ifdef USB_DEBUG
 #define DPRINTF(x)     do { if (usbdebug) printf x; } while (0)
@@ -183,6 +185,11 @@ usb_attach(struct device *parent, struct
        }
        printf("\n");
 
+#if NBPFILTER > 0
+       bpfsattach(&sc->sc_bus->bpf, sc->sc_dev.dv_xname, DLT_USBPCAP,
+           sizeof(struct usbpcap_hdr));
+#endif
+
        /* Make sure not to use tsleep() if we are cold booting. */
        if (cold)
                sc->sc_bus->use_polling++;
@@ -973,5 +980,75 @@ usb_detach(struct device *self, int flag
                sc->sc_bus->soft = NULL;
        }
 
+#if NBPFILTER > 0
+       bpfsdetach(&sc->sc_bus->bpf);
+#endif
        return (0);
+}
+
+void
+usb_tap(struct usbd_bus *bus, struct usbd_xfer *xfer, uint8_t dir)
+{
+#if NBPFILTER > 0
+       struct usb_softc *sc = (struct usb_softc *)bus->usbctl;
+       usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc;
+       struct usbpcap_hdr *uph;
+       unsigned int bpfdir;
+       uint32_t len, dlen;
+       uint8_t *buf, info = 0;
+
+       if (dir == USBTAP_DIR_OUT) {
+               bpfdir = BPF_DIRECTION_OUT;
+               if (usbd_xfer_isread(xfer))
+                       dlen = 0;
+               else
+                       dlen = xfer->length;
+       } else { /* USBTAP_DIR_IN */
+               info = USBPCAP_INFO_PDO_TO_FDO;
+               bpfdir = BPF_DIRECTION_IN;
+               if (usbd_xfer_isread(xfer))
+                       dlen = xfer->actlen;
+               else
+                       dlen = 0;
+       }
+
+       len = sizeof(*uph) + dlen;
+
+       buf = malloc(len, M_TEMP, M_NOWAIT);
+       if (buf == NULL)
+               return;
+
+       uph = (struct usbpcap_hdr *)buf;
+       uph->hlen = htole32(sizeof(*uph));
+       uph->id = 0; /* not yet used */
+       uph->status = htole32(xfer->status);
+       uph->function = 0; /* not yet used */
+       uph->info = info;
+       uph->bus = htole32(sc->sc_dev.dv_unit);
+       uph->devaddr = htole16(xfer->device->address);
+       uph->epaddr = ed->bEndpointAddress;
+
+       switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
+       case UE_CONTROL:
+               uph->xfertype = USBPCAP_TRANSFER_CONTROL;
+               break;
+       case UE_ISOCHRONOUS:
+               uph->xfertype = USBPCAP_TRANSFER_ISOCHRONOUS;
+               break;
+       case UE_BULK:
+               uph->xfertype = USBPCAP_TRANSFER_BULK;
+               break;
+       case UE_INTERRUPT:
+               uph->xfertype = USBPCAP_TRANSFER_INTERRUPT;
+               break;
+       }
+
+       uph->dlen = dlen;
+       if (dlen)
+               memcpy(buf + sizeof(*uph), KERNADDR(&xfer->dmabuf, 0), dlen);
+
+       bpf_tap(bus->bpf, buf, len, bpfdir);
+
+       free(buf, M_TEMP, len);
+#endif
 }
Index: sys/dev/usb/usbdi.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdi.c,v
retrieving revision 1.96
diff -u -p -r1.96 usbdi.c
--- sys/dev/usb/usbdi.c 21 Sep 2017 07:44:06 -0000      1.96
+++ sys/dev/usb/usbdi.c 25 Jan 2018 16:59:55 -0000
@@ -320,6 +320,8 @@ usbd_transfer(struct usbd_xfer *xfer)
                usb_syncmem(&xfer->dmabuf, 0, xfer->length,
                    BUS_DMASYNC_PREREAD);
 
+       usb_tap(bus, xfer, USBTAP_DIR_OUT);
+
        err = pipe->methods->transfer(xfer);
 
        if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) {
@@ -715,7 +717,8 @@ void
 usb_transfer_complete(struct usbd_xfer *xfer)
 {
        struct usbd_pipe *pipe = xfer->pipe;
-       int polling = pipe->device->bus->use_polling;
+       struct usbd_bus *bus = pipe->device->bus;
+       int polling = bus->use_polling;
        int status, flags;
 
 #if 0
@@ -759,7 +762,7 @@ usb_transfer_complete(struct usbd_xfer *
        /* if we allocated the buffer in usbd_transfer() we free it here. */
        if (xfer->rqflags & URQ_AUTO_DMABUF) {
                if (!pipe->repeat) {
-                       usb_freemem(pipe->device->bus, &xfer->dmabuf);
+                       usb_freemem(bus, &xfer->dmabuf);
                        xfer->rqflags &= ~URQ_AUTO_DMABUF;
                }
        }
@@ -778,7 +781,7 @@ usb_transfer_complete(struct usbd_xfer *
            pipe->repeat, SIMPLEQ_FIRST(&pipe->queue)));
 
        /* Count completed transfers. */
-       ++pipe->device->bus->stats.uds_requests
+       ++bus->stats.uds_requests
                [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
 
        xfer->done = 1;
@@ -788,6 +791,8 @@ usb_transfer_complete(struct usbd_xfer *
                    xfer->actlen, xfer->length));
                xfer->status = USBD_SHORT_XFER;
        }
+
+       usb_tap(bus, xfer, USBTAP_DIR_IN);
 
        /*
         * We cannot dereference ``xfer'' after calling the callback as
Index: sys/dev/usb/usbdivar.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdivar.h,v
retrieving revision 1.72
diff -u -p -r1.72 usbdivar.h
--- sys/dev/usb/usbdivar.h      8 Apr 2017 02:57:25 -0000       1.72
+++ sys/dev/usb/usbdivar.h      25 Jan 2018 17:02:27 -0000
@@ -35,6 +35,11 @@
 #ifndef _USBDIVAR_H_
 #define _USBDIVAR_H_
 
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
 #include <sys/timeout.h>
 
 /* From usb_mem.h */
@@ -100,6 +105,9 @@ struct usbd_bus {
        /* Filled by HC driver */
        struct device           bdev; /* base device, host adapter */
        struct usbd_bus_methods *methods;
+#if NBPFILTER > 0
+       caddr_t                 bpf;
+#endif
        u_int32_t               pipe_size; /* size of a pipe struct */
        /* Filled by usb driver */
        struct usbd_device     *root_hub;
@@ -253,6 +261,10 @@ int                usbd_detach(struct usbd_device *, s
 void           usb_needs_explore(struct usbd_device *, int);
 void           usb_needs_reattach(struct usbd_device *);
 void           usb_schedsoftintr(struct usbd_bus *);
+void           usb_tap(struct usbd_bus *, struct usbd_xfer *, uint8_t);
+
+#define USBTAP_DIR_OUT 0
+#define USBTAP_DIR_IN  1
 
 #define        UHUB_UNK_CONFIGURATION  -1
 #define        UHUB_UNK_INTERFACE      -1
Index: sys/dev/usb/usbpcap.h
===================================================================
RCS file: sys/dev/usb/usbpcap.h
diff -N sys/dev/usb/usbpcap.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/dev/usb/usbpcap.h       25 Jan 2018 17:05:08 -0000
@@ -0,0 +1,45 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2018 Martin Pieuchot
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _USBCAP_H_
+#define _USBCAP_H_
+
+/*
+ * DLT_USBPCAP header.
+ */
+struct usbpcap_hdr {
+       uint16_t        hlen;           /* header length */
+       uint64_t        id;             /* request ID */
+       uint32_t        status;         /* USB status code */
+       uint16_t        function;       /* stack function ID */
+       uint8_t         info;           /* info flags */
+#define USBPCAP_INFO_PDO_TO_FDO  (1 << 0)
+
+       uint16_t        bus;            /* bus number */
+       uint16_t        devaddr;        /* device address */
+       uint8_t         epaddr;         /* endpoint's `bEndpointAddress' */
+       uint8_t         xfertype;       /* transfer type */
+#define USBPCAP_TRANSFER_ISOCHRONOUS 0
+#define USBPCAP_TRANSFER_INTERRUPT   1
+#define USBPCAP_TRANSFER_CONTROL     2
+#define USBPCAP_TRANSFER_BULK        3
+
+       uint32_t        dlen;           /* data length */
+} __attribute__((packed));
+
+#endif /* _USBCAP_H_ */

Reply via email to