> On 31 Jan 2018, at 12:39 am, Martin Pieuchot <[email protected]> wrote:
> 
> On 30/01/18(Tue) 16:37, David Gwynne wrote:
>>> [...] 
>>> bpfsdetach takes the reference to a bpf interface that bpfsattach
>>> returns. the manpage likely isnt clear. the diff below fixes it.
>>> 
>>> ive also added a bpf_tap_hdr function that lets you pass a header
>>> along with a flat buffer. internally it shoves them into mbufs, but
>>> the caller doesnt have to know that. it also doesnt have to allocate
>>> a temporary buffer to pass along.
>>> 
>>> ive also made usb_tap return early if bpf hasnt set the bpf pointer
>>> yet.
>> 
>> oops, this diff was stale and had bufs in bpf_tap_hdr.
> 
> Thanks David that's exactly what I needed!
> 
> Here's an updated diff that:
>  - fixes big-endian support in tcpdump(8)'s USBPCAP parser
>  - emits SETUP/DATA/STATUS stages for control transfers, that makes
>    Wireshark's parser happy.
> 
> I haven't implemented isochronous yet, but bulk/intr/ctrl can now be
> easily debugged with Wireshark.  Improving our tcpdump(8) parser would
> be the next step.
> 
> How should proceed, do you want to commit your bpf_tap_hdr(9) and the
> related doc?  That's obviously ok mpi@.

i put bpf_tap_hdr in. i left the DLT_USBPCAP bit of bpf.h out for you though.

im ok with the rest going in.

> 
> 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     30 Jan 2018 12:35:59 -0000
> @@ -1291,6 +1291,45 @@ _bpf_mtap(caddr_t arg, const struct mbuf
> }
> 
> /*
> + * Incoming linkage from device drivers, where a data buffer should be
> + * prepended by an arbitrary header. In this situation we already have a
> + * way of representing a chain of memory buffers, ie, mbufs, so reuse
> + * the existing functionality by attaching the buffers to mbufs.
> + *
> + * Con up a minimal mbuf chain to pacify bpf by allocating (only) a
> + * struct m_hdr each for the header and data on the stack.
> + */
> +int
> +bpf_tap_hdr(caddr_t arg, const void *hdr, unsigned int hdrlen,
> +    const void *buf, unsigned int buflen, u_int direction)
> +{
> +     struct m_hdr mh, md;
> +     struct mbuf *m0 = NULL;
> +     struct mbuf **mp = &m0;
> +
> +     if (hdr != NULL) {
> +             mh.mh_flags = 0;
> +             mh.mh_next = NULL;
> +             mh.mh_len = hdrlen;
> +             mh.mh_data = (void *)hdr;
> +
> +             *mp = (struct mbuf *)&mh;
> +             mp = &mh.mh_next;
> +     }
> +
> +     if (buf != NULL) {
> +             md.mh_flags = 0;
> +             md.mh_next = NULL;
> +             md.mh_len = buflen;
> +             md.mh_data = (void *)buf;
> +
> +             *mp = (struct mbuf *)&md;
> +     }
> +
> +     return _bpf_mtap(arg, m0, direction, bpf_mcopy);
> +}
> +
> +/*
>  * Incoming linkage from device drivers, when packet is in an mbuf chain.
>  */
> int
> 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     30 Jan 2018 12:35:59 -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 */
> 
> @@ -311,6 +312,7 @@ int        bpf_mtap_hdr(caddr_t, caddr_t, u_in
>           void (*)(const void *, void *, size_t));
> int    bpf_mtap_af(caddr_t, u_int32_t, const struct mbuf *, u_int);
> int    bpf_mtap_ether(caddr_t, const struct mbuf *, u_int);
> +int   bpf_tap_hdr(caddr_t, const void *, u_int, const void *, u_int, u_int);
> void   bpfattach(caddr_t *, struct ifnet *, u_int, u_int);
> void   bpfdetach(struct ifnet *);
> void  *bpfsattach(caddr_t *, const char *, u_int, u_int);
> 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 30 Jan 2018 12:35:59 -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      30 Jan 2018 12:35:59 -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  30 Jan 2018 14:31:27 -0000
> @@ -0,0 +1,73 @@
> +/*
> + * 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_pkt_hdr *uph;
> +     u_int16_t hdrlen;
> +
> +     ts_print(&h->ts);
> +
> +     /* check length */
> +     if (caplen < sizeof(uint16_t)) {
> +             printf("[|usb]");
> +             goto out;
> +     }
> +     uph = (struct usbpcap_pkt_hdr *)p;
> +     hdrlen = letoh16(uph->uph_hlen);
> +     if (hdrlen < sizeof(*uph)) {
> +             printf("[usb: invalid header length %u!]", hdrlen);
> +             goto out;
> +     }
> +
> +     if (caplen < hdrlen) {
> +             printf("[|usb]");
> +             goto out;
> +     }
> +
> +     printf("bus %u %c addr %u: ep%u",
> +         letoh16(uph->uph_bus),
> +          ((uph->uph_info & USBPCAP_INFO_DIRECTION_IN) ? '<' : '>'),
> +         letoh16(uph->uph_devaddr), UE_GET_ADDR(uph->uph_epaddr));
> +
> +     if (uph->uph_xfertype < nitems(usbpcap_xfer_type))
> +             printf(" %s", usbpcap_xfer_type[uph->uph_xfertype]);
> +     else
> +             printf(" ??");
> +
> +     printf(" %u", letoh32(uph->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        30 Jan 2018 12:35:59 -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     30 Jan 2018 12:35:59 -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        30 Jan 2018 12:35:59 -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 30 Jan 2018 14:27:22 -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
> +     sc->sc_bus->bpfif = bpfsattach(&sc->sc_bus->bpf, sc->sc_dev.dv_xname,
> +         DLT_USBPCAP, sizeof(struct usbpcap_pkt_hdr));
> +#endif
> +
>       /* Make sure not to use tsleep() if we are cold booting. */
>       if (cold)
>               sc->sc_bus->use_polling++;
> @@ -973,5 +980,98 @@ usb_detach(struct device *self, int flag
>               sc->sc_bus->soft = NULL;
>       }
> 
> +#if NBPFILTER > 0
> +     bpfsdetach(sc->sc_bus->bpfif);
> +#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_ctl_hdr uch;
> +     struct usbpcap_pkt_hdr *uph = &uch.uch_hdr;
> +     unsigned int bpfdir;
> +     void *data = NULL;
> +     caddr_t bpf;
> +
> +     bpf = bus->bpf;
> +     if (bpf == NULL)
> +             return;
> +
> +     switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
> +     case UE_CONTROL:
> +             /* Control transfer headers include an extra byte. */
> +             uph->uph_hlen = htole16(sizeof(uch));
> +             uph->uph_xfertype = USBPCAP_TRANSFER_CONTROL;
> +             break;
> +     case UE_ISOCHRONOUS:
> +             uph->uph_hlen = htole16(sizeof(*uph));
> +             uph->uph_xfertype = USBPCAP_TRANSFER_ISOCHRONOUS;
> +             break;
> +     case UE_BULK:
> +             uph->uph_hlen = htole16(sizeof(*uph));
> +             uph->uph_xfertype = USBPCAP_TRANSFER_BULK;
> +             break;
> +     case UE_INTERRUPT:
> +             uph->uph_hlen = htole16(sizeof(*uph));
> +             uph->uph_xfertype = USBPCAP_TRANSFER_INTERRUPT;
> +             break;
> +     }
> +
> +     uph->uph_id = 0; /* not yet used */
> +     uph->uph_status = htole32(xfer->status);
> +     uph->uph_function = 0; /* not yet used */
> +     uph->uph_bus = htole32(sc->sc_dev.dv_unit);
> +     uph->uph_devaddr = htole16(xfer->device->address);
> +     uph->uph_epaddr = ed->bEndpointAddress;
> +     uph->uph_info = 0;
> +
> +     /* Outgoing control requests start with a STAGE dump. */
> +     if ((xfer->rqflags & URQ_REQUEST) && (dir == USBTAP_DIR_OUT)) {
> +             uch.uch_stage = USBPCAP_CONTROL_STAGE_SETUP;
> +             uph->uph_dlen = sizeof(usb_device_request_t);
> +             bpf_tap_hdr(bpf, uph, uph->uph_hlen, &xfer->request,
> +                 uph->uph_dlen, BPF_DIRECTION_OUT);
> +     }
> +
> +     if (dir == USBTAP_DIR_OUT) {
> +             bpfdir = BPF_DIRECTION_OUT;
> +             if (!usbd_xfer_isread(xfer)) {
> +                     data = KERNADDR(&xfer->dmabuf, 0);
> +                     uph->uph_dlen = xfer->length;
> +                     uch.uch_stage = USBPCAP_CONTROL_STAGE_DATA;
> +             } else {
> +                     data = NULL;
> +                     uph->uph_dlen = 0;
> +                     uch.uch_stage = USBPCAP_CONTROL_STAGE_STATUS;
> +             }
> +     } else { /* USBTAP_DIR_IN */
> +             bpfdir = BPF_DIRECTION_IN;
> +             uph->uph_info = USBPCAP_INFO_DIRECTION_IN;
> +             if (usbd_xfer_isread(xfer)) {
> +                     data = KERNADDR(&xfer->dmabuf, 0);
> +                     uph->uph_dlen = xfer->actlen;
> +                     uch.uch_stage = USBPCAP_CONTROL_STAGE_DATA;
> +             } else {
> +                     data = NULL;
> +                     uph->uph_dlen = 0;
> +                     uch.uch_stage = USBPCAP_CONTROL_STAGE_STATUS;
> +             }
> +     }
> +
> +     /* Dump bulk/intr/iso data, ctrl DATA or STATUS stage. */
> +     bpf_tap_hdr(bpf, uph, uph->uph_hlen, data, uph->uph_dlen, bpfdir);
> +
> +     /* Incoming control requests with DATA need a STATUS stage. */
> +     if ((xfer->rqflags & URQ_REQUEST) && (dir == USBTAP_DIR_IN) &&
> +         (uch.uch_stage == USBPCAP_CONTROL_STAGE_DATA)) {
> +             uch.uch_stage = USBPCAP_CONTROL_STAGE_STATUS;
> +             uph->uph_dlen = 0;
> +             bpf_tap_hdr(bpf, uph, uph->uph_hlen, NULL, 0, BPF_DIRECTION_IN);
> +     }
> +#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       30 Jan 2018 12:35:59 -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    30 Jan 2018 13:46:18 -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,10 @@ struct usbd_bus {
>       /* Filled by HC driver */
>       struct device           bdev; /* base device, host adapter */
>       struct usbd_bus_methods *methods;
> +#if NBPFILTER > 0
> +     void                    *bpfif;
> +     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 +262,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     30 Jan 2018 14:26:47 -0000
> @@ -0,0 +1,56 @@
> +/* $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_
> +
> +/*
> + * Common DLT_USBPCAP header.
> + */
> +struct usbpcap_pkt_hdr {
> +     uint16_t                uph_hlen;       /* header length */
> +     uint64_t                uph_id;         /* request ID */
> +     uint32_t                uph_status;     /* USB status code */
> +     uint16_t                uph_function;   /* stack function ID */
> +     uint8_t                 uph_info;       /* info flags */
> +#define USBPCAP_INFO_DIRECTION_IN    (1 << 0)/* from Device to Host */
> +
> +     uint16_t                uph_bus;        /* bus number */
> +     uint16_t                uph_devaddr;    /* device address */
> +     uint8_t                 uph_epaddr;     /* copy of bEndpointAddress */
> +     uint8_t                 uph_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                uph_dlen;       /* data length */
> +} __attribute__((packed));
> +
> +/*
> + * Header used when dumping control transfers.
> + */
> +struct usbpcap_ctl_hdr {
> +     struct usbpcap_pkt_hdr  uch_hdr;
> +     uint8_t                 uch_stage;
> +#define USBPCAP_CONTROL_STAGE_SETUP  0
> +#define USBPCAP_CONTROL_STAGE_DATA   1
> +#define USBPCAP_CONTROL_STAGE_STATUS 2
> +} __attribute__((packed));
> +
> +#endif /* _USBCAP_H_ */

Reply via email to