Author: emax
Date: Wed Jan 28 20:06:02 2009
New Revision: 187866
URL: http://svn.freebsd.org/changeset/base/187866

Log:
  Update ubtbcmfw2 (aka usb2_bluetooth_fw) driver
  
  Reviewed by:  HPS

Modified:
  head/sys/dev/usb2/bluetooth/ubtbcmfw2.c

Modified: head/sys/dev/usb2/bluetooth/ubtbcmfw2.c
==============================================================================
--- head/sys/dev/usb2/bluetooth/ubtbcmfw2.c     Wed Jan 28 20:04:39 2009        
(r187865)
+++ head/sys/dev/usb2/bluetooth/ubtbcmfw2.c     Wed Jan 28 20:06:02 2009        
(r187866)
@@ -3,7 +3,7 @@
  */
 
 /*-
- * Copyright (c) 2003 Maksim Yevmenkin <m_evmen...@yahoo.com>
+ * Copyright (c) 2003-2009 Maksim Yevmenkin <m_evmen...@yahoo.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -54,107 +54,85 @@
 
 #define        UBTBCMFW_CONFIG_NO      1       /* Config number */
 #define        UBTBCMFW_IFACE_IDX      0       /* Control interface */
-#define        UBTBCMFW_T_MAX          4       /* units */
+
+#define        UBTBCMFW_BSIZE          1024
+#define        UBTBCMFW_IFQ_MAXLEN     2
 
 enum {
-       UBTBCMFW_BULK_DT_WR,
-       UBTBCMFW_BULK_DT_RD,
-       UBTBCMFW_BULK_CS_WR,
-       UBTBCMFW_BULK_CS_RD,
-       UBTBCMFW_N_TRANSFER = 4,
+       UBTBCMFW_BULK_DT_WR = 0,
+       UBTBCMFW_INTR_DT_RD,
+       UBTBCMFW_N_TRANSFER,
 };
 
 struct ubtbcmfw_softc {
-       struct usb2_fifo_sc sc_fifo;
-       struct mtx sc_mtx;
-
-       device_t sc_dev;
-       struct usb2_device *sc_udev;
-       struct usb2_xfer *sc_xfer[UBTBCMFW_N_TRANSFER];
-
-       uint8_t sc_flags;
-#define        UBTBCMFW_FLAG_WRITE_STALL 0x01
-#define        UBTBCMFW_FLAG_READ_STALL  0x02
+       struct usb2_device      *sc_udev;
+       struct mtx              sc_mtx;
+       struct usb2_xfer        *sc_xfer[UBTBCMFW_N_TRANSFER];
+       struct usb2_fifo_sc     sc_fifo;
 };
 
-#define        UBTBCMFW_BSIZE          1024
-#define        UBTBCMFW_IFQ_MAXLEN     2
-
-/* prototypes */
+/*
+ * Prototypes
+ */
 
-static device_probe_t ubtbcmfw_probe;
-static device_attach_t ubtbcmfw_attach;
-static device_detach_t ubtbcmfw_detach;
-
-static usb2_callback_t ubtbcmfw_write_callback;
-static usb2_callback_t ubtbcmfw_write_clear_stall_callback;
-static usb2_callback_t ubtbcmfw_read_callback;
-static usb2_callback_t ubtbcmfw_read_clear_stall_callback;
-
-static usb2_fifo_close_t ubtbcmfw_close;
-static usb2_fifo_cmd_t ubtbcmfw_start_read;
-static usb2_fifo_cmd_t ubtbcmfw_start_write;
-static usb2_fifo_cmd_t ubtbcmfw_stop_read;
-static usb2_fifo_cmd_t ubtbcmfw_stop_write;
-static usb2_fifo_ioctl_t ubtbcmfw_ioctl;
-static usb2_fifo_open_t ubtbcmfw_open;
-
-static struct usb2_fifo_methods ubtbcmfw_fifo_methods = {
-       .f_close = &ubtbcmfw_close,
-       .f_ioctl = &ubtbcmfw_ioctl,
-       .f_open = &ubtbcmfw_open,
-       .f_start_read = &ubtbcmfw_start_read,
-       .f_start_write = &ubtbcmfw_start_write,
-       .f_stop_read = &ubtbcmfw_stop_read,
-       .f_stop_write = &ubtbcmfw_stop_write,
-       .basename[0] = "ubtbcmfw",
-       .basename[1] = "ubtbcmfw",
-       .basename[2] = "ubtbcmfw",
-       .postfix[0] = "",
-       .postfix[1] = ".1",
-       .postfix[2] = ".2",
+static device_probe_t          ubtbcmfw_probe;
+static device_attach_t         ubtbcmfw_attach;
+static device_detach_t         ubtbcmfw_detach;
+
+static usb2_callback_t         ubtbcmfw_write_callback;
+static usb2_callback_t         ubtbcmfw_read_callback;
+
+static usb2_fifo_close_t       ubtbcmfw_close;
+static usb2_fifo_cmd_t         ubtbcmfw_start_read;
+static usb2_fifo_cmd_t         ubtbcmfw_start_write;
+static usb2_fifo_cmd_t         ubtbcmfw_stop_read;
+static usb2_fifo_cmd_t         ubtbcmfw_stop_write;
+static usb2_fifo_ioctl_t       ubtbcmfw_ioctl;
+static usb2_fifo_open_t                ubtbcmfw_open;
+
+static struct usb2_fifo_methods        ubtbcmfw_fifo_methods = 
+{
+       .f_close =              &ubtbcmfw_close,
+       .f_ioctl =              &ubtbcmfw_ioctl,
+       .f_open =               &ubtbcmfw_open,
+       .f_start_read =         &ubtbcmfw_start_read,
+       .f_start_write =        &ubtbcmfw_start_write,
+       .f_stop_read =          &ubtbcmfw_stop_read,
+       .f_stop_write =         &ubtbcmfw_stop_write,
+       .basename[0] =          "ubtbcmfw",
+       .basename[1] =          "ubtbcmfw",
+       .basename[2] =          "ubtbcmfw",
+       .postfix[0] =           "",
+       .postfix[1] =           ".1",
+       .postfix[2] =           ".2",
 };
 
-static const struct usb2_config ubtbcmfw_config[UBTBCMFW_T_MAX] = {
+/*
+ * Device's config structure
+ */
 
+static const struct usb2_config        ubtbcmfw_config[UBTBCMFW_N_TRANSFER] =
+{
        [UBTBCMFW_BULK_DT_WR] = {
-               .type = UE_BULK,
-               .endpoint = 0x02,       /* fixed */
-               .direction = UE_DIR_OUT,
-               .mh.bufsize = UBTBCMFW_BSIZE,
-               .mh.flags = {.pipe_bof = 1,.proxy_buffer = 1,},
-               .mh.callback = &ubtbcmfw_write_callback,
+               .type =         UE_BULK,
+               .endpoint =     0x02,   /* fixed */
+               .direction =    UE_DIR_OUT,
+               .if_index =     UBTBCMFW_IFACE_IDX,
+               .mh.bufsize =   UBTBCMFW_BSIZE,
+               .mh.flags =     { .pipe_bof = 1, .force_short_xfer = 1,
+                                 .proxy_buffer = 1, },
+               .mh.callback =  &ubtbcmfw_write_callback,
        },
 
-       [UBTBCMFW_BULK_DT_RD] = {
-               .type = UE_INTERRUPT,
-               .endpoint = 0x01,       /* fixed */
-               .direction = UE_DIR_IN,
-               .mh.bufsize = UBTBCMFW_BSIZE,
-               .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 
1,},
-               .mh.callback = &ubtbcmfw_read_callback,
-       },
-
-       [UBTBCMFW_BULK_CS_WR] = {
-               .type = UE_CONTROL,
-               .endpoint = 0x00,       /* Control pipe */
-               .direction = UE_DIR_ANY,
-               .mh.bufsize = sizeof(struct usb2_device_request),
-               .mh.flags = {},
-               .mh.callback = &ubtbcmfw_write_clear_stall_callback,
-               .mh.timeout = 1000,     /* 1 second */
-               .mh.interval = 50,      /* 50ms */
-       },
-
-       [UBTBCMFW_BULK_CS_RD] = {
-               .type = UE_CONTROL,
-               .endpoint = 0x00,       /* Control pipe */
-               .direction = UE_DIR_ANY,
-               .mh.bufsize = sizeof(struct usb2_device_request),
-               .mh.flags = {},
-               .mh.callback = &ubtbcmfw_read_clear_stall_callback,
-               .mh.timeout = 1000,     /* 1 second */
-               .mh.interval = 50,      /* 50ms */
+       [UBTBCMFW_INTR_DT_RD] = {
+               .type =         UE_INTERRUPT,
+               .endpoint =     0x01,   /* fixed */
+               .direction =    UE_DIR_IN,
+               .if_index =     UBTBCMFW_IFACE_IDX,
+               .mh.bufsize =   UBTBCMFW_BSIZE,
+               .mh.flags =     { .pipe_bof = 1, .short_xfer_ok = 1,
+                                 .proxy_buffer = 1, },
+               .mh.callback =  &ubtbcmfw_read_callback,
        },
 };
 
@@ -162,19 +140,21 @@ static const struct usb2_config ubtbcmfw
  * Module
  */
 
-static devclass_t ubtbcmfw_devclass;
+static devclass_t      ubtbcmfw_devclass;
 
-static device_method_t ubtbcmfw_methods[] = {
+static device_method_t ubtbcmfw_methods[] =
+{
        DEVMETHOD(device_probe, ubtbcmfw_probe),
        DEVMETHOD(device_attach, ubtbcmfw_attach),
        DEVMETHOD(device_detach, ubtbcmfw_detach),
        {0, 0}
 };
 
-static driver_t ubtbcmfw_driver = {
-       .name = "ubtbcmfw",
-       .methods = ubtbcmfw_methods,
-       .size = sizeof(struct ubtbcmfw_softc),
+static driver_t                ubtbcmfw_driver =
+{
+       .name =         "ubtbcmfw",
+       .methods =      ubtbcmfw_methods,
+       .size =         sizeof(struct ubtbcmfw_softc),
 };
 
 DRIVER_MODULE(ubtbcmfw, ushub, ubtbcmfw_driver, ubtbcmfw_devclass, NULL, 0);
@@ -188,21 +168,21 @@ MODULE_DEPEND(ubtbcmfw, usb2_core, 1, 1,
 static int
 ubtbcmfw_probe(device_t dev)
 {
-       struct usb2_attach_arg *uaa = device_get_ivars(dev);
+       const struct usb2_device_id     devs[] = {
+       /* Broadcom BCM2033 devices only */
+       { USB_VPI(USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM2033, 0) },
+       };
+
+       struct usb2_attach_arg  *uaa = device_get_ivars(dev);
 
-       if (uaa->usb2_mode != USB_MODE_HOST) {
+       if (uaa->usb2_mode != USB_MODE_HOST)
                return (ENXIO);
-       }
+
        if (uaa->info.bIfaceIndex != 0)
                return (ENXIO);
 
-       /* Match the boot device. */
-       if (uaa->info.idVendor == USB_VENDOR_BROADCOM &&
-           uaa->info.idProduct == USB_PRODUCT_BROADCOM_BCM2033)
-               return (0);
-
-       return (ENXIO);
-}
+       return (usb2_lookup_id_by_uaa(devs, sizeof(devs), uaa));
+} /* ubtbcmfw_probe */
 
 /*
  * Attach the device
@@ -211,15 +191,11 @@ ubtbcmfw_probe(device_t dev)
 static int
 ubtbcmfw_attach(device_t dev)
 {
-       struct usb2_attach_arg *uaa = device_get_ivars(dev);
-       struct ubtbcmfw_softc *sc = device_get_softc(dev);
-       int32_t err;
-       uint8_t iface_index;
+       struct usb2_attach_arg  *uaa = device_get_ivars(dev);
+       struct ubtbcmfw_softc   *sc = device_get_softc(dev);
+       uint8_t                 iface_index;
+       int                     error;
 
-       if (sc == NULL) {
-               return (ENOMEM);
-       }
-       sc->sc_dev = dev;
        sc->sc_udev = uaa->device;
 
        device_set_usb2_desc(dev);
@@ -227,30 +203,35 @@ ubtbcmfw_attach(device_t dev)
        mtx_init(&sc->sc_mtx, "ubtbcmfw lock", NULL, MTX_DEF | MTX_RECURSE);
 
        iface_index = UBTBCMFW_IFACE_IDX;
-       err = usb2_transfer_setup(uaa->device,
-           &iface_index, sc->sc_xfer, ubtbcmfw_config,
-           UBTBCMFW_T_MAX, sc, &sc->sc_mtx);
-       if (err) {
-               device_printf(dev, "allocating USB transfers "
-                   "failed, err=%s\n", usb2_errstr(err));
+       error = usb2_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
+                               ubtbcmfw_config, UBTBCMFW_N_TRANSFER,
+                               sc, &sc->sc_mtx);
+       if (error != 0) {
+               device_printf(dev, "allocating USB transfers failed. %s\n",
+                       usb2_errstr(error));
                goto detach;
        }
-       /* set interface permissions */
+
+       /* Set interface permissions */
        usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex,
-           UID_ROOT, GID_OPERATOR, 0644);
+               UID_ROOT, GID_OPERATOR, 0644);
 
-       err = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
-           &ubtbcmfw_fifo_methods, &sc->sc_fifo,
-           device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex);
-       if (err) {
+       error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
+                       &ubtbcmfw_fifo_methods, &sc->sc_fifo,
+                       device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex);
+       if (error != 0) {
+               device_printf(dev, "could not attach fifo. %s\n",
+                       usb2_errstr(error));
                goto detach;
        }
-       return (0);                     /* success */
+
+       return (0);     /* success */
 
 detach:
        ubtbcmfw_detach(dev);
-       return (ENOMEM);                /* failure */
-}
+
+       return (ENXIO); /* failure */
+} /* ubtbcmfw_attach */ 
 
 /*
  * Detach the device
@@ -259,191 +240,192 @@ detach:
 static int
 ubtbcmfw_detach(device_t dev)
 {
-       struct ubtbcmfw_softc *sc = device_get_softc(dev);
+       struct ubtbcmfw_softc   *sc = device_get_softc(dev);
 
        usb2_fifo_detach(&sc->sc_fifo);
 
-       usb2_transfer_unsetup(sc->sc_xfer, UBTBCMFW_T_MAX);
+       usb2_transfer_unsetup(sc->sc_xfer, UBTBCMFW_N_TRANSFER);
 
        mtx_destroy(&sc->sc_mtx);
 
        return (0);
-}
+} /* ubtbcmfw_detach */
+
+/*
+ * USB write callback
+ */
 
 static void
 ubtbcmfw_write_callback(struct usb2_xfer *xfer)
 {
-       struct ubtbcmfw_softc *sc = xfer->priv_sc;
-       struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_RX];
-       uint32_t actlen;
+       struct ubtbcmfw_softc   *sc = xfer->priv_sc;
+       struct usb2_fifo        *f = sc->sc_fifo.fp[USB_FIFO_TX];
+       uint32_t                actlen;
 
        switch (USB_GET_STATE(xfer)) {
-       case USB_ST_TRANSFERRED:
        case USB_ST_SETUP:
-               if (sc->sc_flags & UBTBCMFW_FLAG_WRITE_STALL) {
-                       usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_CS_WR]);
-                       return;
-               }
+       case USB_ST_TRANSFERRED:
+setup_next:
                if (usb2_fifo_get_data(f, xfer->frbuffers, 0,
-                   UBTBCMFW_BSIZE, &actlen, 0)) {
-
+                               xfer->max_data_length, &actlen, 0)) {
                        xfer->frlengths[0] = actlen;
                        usb2_start_hardware(xfer);
                }
-               return;
+               break;
 
-       default:                        /* Error */
+       default: /* Error */
                if (xfer->error != USB_ERR_CANCELLED) {
                        /* try to clear stall first */
-                       sc->sc_flags |= UBTBCMFW_FLAG_WRITE_STALL;
-                       usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_CS_WR]);
+                       xfer->flags.stall_pipe = 1;
+                       goto setup_next;
                }
-               return;
+               break;
        }
-}
-
-static void
-ubtbcmfw_write_clear_stall_callback(struct usb2_xfer *xfer)
-{
-       struct ubtbcmfw_softc *sc = xfer->priv_sc;
-       struct usb2_xfer *xfer_other = sc->sc_xfer[UBTBCMFW_BULK_DT_WR];
+} /* ubtbcmfw_write_callback */
 
-       if (usb2_clear_stall_callback(xfer, xfer_other)) {
-               DPRINTF("stall cleared\n");
-               sc->sc_flags &= ~UBTBCMFW_FLAG_WRITE_STALL;
-               usb2_transfer_start(xfer_other);
-       }
-}
+/*
+ * USB read callback
+ */
 
 static void
 ubtbcmfw_read_callback(struct usb2_xfer *xfer)
 {
-       struct ubtbcmfw_softc *sc = xfer->priv_sc;
-       struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_RX];
+       struct ubtbcmfw_softc   *sc = xfer->priv_sc;
+       struct usb2_fifo        *fifo = sc->sc_fifo.fp[USB_FIFO_RX];
 
        switch (USB_GET_STATE(xfer)) {
        case USB_ST_TRANSFERRED:
-               usb2_fifo_put_data(f, xfer->frbuffers,
-                   0, xfer->actlen, 1);
+               usb2_fifo_put_data(fifo, xfer->frbuffers, 0, xfer->actlen, 1);
+               /* FALLTHROUGH */
 
        case USB_ST_SETUP:
-               if (sc->sc_flags & UBTBCMFW_FLAG_READ_STALL) {
-                       usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_CS_RD]);
-                       return;
-               }
-               if (usb2_fifo_put_bytes_max(f) != 0) {
+setup_next:
+               if (usb2_fifo_put_bytes_max(fifo) > 0) {
                        xfer->frlengths[0] = xfer->max_data_length;
                        usb2_start_hardware(xfer);
                }
-               return;
+               break;
 
-       default:                        /* Error */
+       default: /* Error */
                if (xfer->error != USB_ERR_CANCELLED) {
                        /* try to clear stall first */
-                       sc->sc_flags |= UBTBCMFW_FLAG_READ_STALL;
-                       usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_CS_RD]);
+                       xfer->flags.stall_pipe = 1;
+                       goto setup_next;
                }
-               return;
+               break;
        }
-}
-
-static void
-ubtbcmfw_read_clear_stall_callback(struct usb2_xfer *xfer)
-{
-       struct ubtbcmfw_softc *sc = xfer->priv_sc;
-       struct usb2_xfer *xfer_other = sc->sc_xfer[UBTBCMFW_BULK_DT_RD];
+} /* ubtbcmfw_read_callback */
 
-       if (usb2_clear_stall_callback(xfer, xfer_other)) {
-               DPRINTF("stall cleared\n");
-               sc->sc_flags &= ~UBTBCMFW_FLAG_READ_STALL;
-               usb2_transfer_start(xfer_other);
-       }
-}
+/*
+ * Called when we about to start read()ing from the device
+ */
 
 static void
 ubtbcmfw_start_read(struct usb2_fifo *fifo)
 {
-       struct ubtbcmfw_softc *sc = fifo->priv_sc0;
+       struct ubtbcmfw_softc   *sc = fifo->priv_sc0;
 
-       usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_DT_RD]);
-}
+       usb2_transfer_start(sc->sc_xfer[UBTBCMFW_INTR_DT_RD]);
+} /* ubtbcmfw_start_read */
+
+/*
+ * Called when we about to stop reading (i.e. closing fifo)
+ */
 
 static void
 ubtbcmfw_stop_read(struct usb2_fifo *fifo)
 {
-       struct ubtbcmfw_softc *sc = fifo->priv_sc0;
+       struct ubtbcmfw_softc   *sc = fifo->priv_sc0;
+
+       usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_INTR_DT_RD]);
+} /* ubtbcmfw_stop_read */
 
-       usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_BULK_CS_RD]);
-       usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_BULK_DT_RD]);
-}
+/*
+ * Called when we about to start write()ing to the device, poll()ing
+ * for write or flushing fifo
+ */
 
 static void
 ubtbcmfw_start_write(struct usb2_fifo *fifo)
 {
-       struct ubtbcmfw_softc *sc = fifo->priv_sc0;
+       struct ubtbcmfw_softc   *sc = fifo->priv_sc0;
 
        usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_DT_WR]);
-}
+} /* ubtbcmfw_start_write */
+
+/*
+ * Called when we about to stop writing (i.e. closing fifo)
+ */
 
 static void
 ubtbcmfw_stop_write(struct usb2_fifo *fifo)
 {
-       struct ubtbcmfw_softc *sc = fifo->priv_sc0;
+       struct ubtbcmfw_softc   *sc = fifo->priv_sc0;
 
-       usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_BULK_CS_WR]);
        usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_BULK_DT_WR]);
-}
+} /* ubtbcmfw_stop_write */
+
+/*
+ * Called when fifo is open
+ */
 
 static int
 ubtbcmfw_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
 {
-       struct ubtbcmfw_softc *sc = fifo->priv_sc0;
+       struct ubtbcmfw_softc   *sc = fifo->priv_sc0;
+       struct usb2_xfer        *xfer;
+
+       /*
+        * f_open fifo method can only be called with either FREAD
+        * or FWRITE flag set at one time.
+        */
+
+       if (fflags & FREAD)
+               xfer = sc->sc_xfer[UBTBCMFW_INTR_DT_RD];
+       else if (fflags & FWRITE)
+               xfer = sc->sc_xfer[UBTBCMFW_BULK_DT_WR];
+       else
+               return (EINVAL);        /* XXX can happen? */
+               
+       if (usb2_fifo_alloc_buffer(fifo, xfer->max_data_length,
+                       UBTBCMFW_IFQ_MAXLEN) != 0)
+               return (ENOMEM);
 
-       if (fflags & FREAD) {
-               if (usb2_fifo_alloc_buffer(fifo,
-                   sc->sc_xfer[UBTBCMFW_BULK_DT_RD]->max_data_length,
-                   UBTBCMFW_IFQ_MAXLEN)) {
-                       return (ENOMEM);
-               }
-       }
-       if (fflags & FWRITE) {
-               /* clear stall first */
-               mtx_lock(&sc->sc_mtx);
-               sc->sc_flags |= UBTBCMFW_FLAG_WRITE_STALL;
-               mtx_unlock(&sc->sc_mtx);
-               if (usb2_fifo_alloc_buffer(fifo,
-                   sc->sc_xfer[UBTBCMFW_BULK_DT_WR]->max_data_length,
-                   UBTBCMFW_IFQ_MAXLEN)) {
-                       return (ENOMEM);
-               }
-       }
        return (0);
-}
+} /* ubtbcmfw_open */
+
+/* 
+ * Called when fifo is closed
+ */
 
 static void
 ubtbcmfw_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
 {
-       if (fflags & (FREAD | FWRITE)) {
+       if (fflags & (FREAD | FWRITE))
                usb2_fifo_free_buffer(fifo);
-       }
-}
+} /* ubtbcmfw_close */
+
+/*
+ * Process ioctl() on USB device
+ */
 
 static int
 ubtbcmfw_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data,
     int fflags, struct thread *td)
 {
-       struct ubtbcmfw_softc *sc = fifo->priv_sc0;
-       int error = 0;
+       struct ubtbcmfw_softc   *sc = fifo->priv_sc0;
+       int                     error = 0;
 
        switch (cmd) {
        case USB_GET_DEVICE_DESC:
-               *(struct usb2_device_descriptor *)data =
-                   *usb2_get_device_descriptor(sc->sc_udev);
+               memcpy(data, usb2_get_device_descriptor(sc->sc_udev),
+                       sizeof(struct usb2_device_descriptor));
                break;
 
        default:
                error = EINVAL;
                break;
        }
+
        return (error);
-}
+} /* ubtbcmfw_ioctl */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to