[BACK]Return to ubt.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Annotation of src/sys/dev/usb/ubt.c, Revision 1.63

1.63    ! dsainty     1: /*     $NetBSD: ubt.c,v 1.62 2019/05/05 03:17:54 mrg Exp $     */
1.1       augustss    2:
1.14      gdamore     3: /*-
                      4:  * Copyright (c) 2006 Itronix Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Written by Iain Hibbert for Itronix Inc.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. The name of Itronix Inc. may not be used to endorse
                     18:  *    or promote products derived from this software without specific
                     19:  *    prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     23:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     24:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
                     25:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     26:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     27:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
                     28:  * ON ANY THEORY OF LIABILITY, WHETHER IN
                     29:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     30:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     31:  * POSSIBILITY OF SUCH DAMAGE.
                     32:  */
1.1       augustss   33: /*
1.5       dsainty    34:  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
1.1       augustss   35:  * All rights reserved.
                     36:  *
                     37:  * This code is derived from software contributed to The NetBSD Foundation
1.5       dsainty    38:  * by Lennart Augustsson (lennart@augustsson.net) and
1.63    ! dsainty    39:  * David Sainty (dsainty@NetBSD.org).
1.1       augustss   40:  *
                     41:  * Redistribution and use in source and binary forms, with or without
                     42:  * modification, are permitted provided that the following conditions
                     43:  * are met:
                     44:  * 1. Redistributions of source code must retain the above copyright
                     45:  *    notice, this list of conditions and the following disclaimer.
                     46:  * 2. Redistributions in binary form must reproduce the above copyright
                     47:  *    notice, this list of conditions and the following disclaimer in the
                     48:  *    documentation and/or other materials provided with the distribution.
                     49:  *
                     50:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     51:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     52:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     53:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     54:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     55:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     56:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     57:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     58:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     59:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     60:  * POSSIBILITY OF SUCH DAMAGE.
                     61:  */
1.14      gdamore    62: /*
                     63:  * This driver originally written by Lennart Augustsson and David Sainty,
                     64:  * but was mostly rewritten for the NetBSD Bluetooth protocol stack by
                     65:  * Iain Hibbert for Itronix, Inc using the FreeBSD ng_ubt.c driver as a
                     66:  * reference.
                     67:  */
1.1       augustss   68:
                     69: #include <sys/cdefs.h>
1.63    ! dsainty    70: __KERNEL_RCSID(0, "$NetBSD: ubt.c,v 1.62 2019/05/05 03:17:54 mrg Exp $");
1.57      skrll      71:
                     72: #ifdef _KERNEL_OPT
                     73: #include "opt_usb.h"
                     74: #endif
1.1       augustss   75:
                     76: #include <sys/param.h>
1.14      gdamore    77: #include <sys/device.h>
                     78: #include <sys/ioctl.h>
1.1       augustss   79: #include <sys/kernel.h>
1.54      skrll      80: #include <sys/kmem.h>
1.14      gdamore    81: #include <sys/mbuf.h>
1.1       augustss   82: #include <sys/proc.h>
1.14      gdamore    83: #include <sys/sysctl.h>
                     84: #include <sys/systm.h>
1.1       augustss   85:
                     86: #include <dev/usb/usb.h>
                     87: #include <dev/usb/usbdi.h>
                     88: #include <dev/usb/usbdi_util.h>
                     89: #include <dev/usb/usbdevs.h>
                     90:
1.14      gdamore    91: #include <netbt/bluetooth.h>
                     92: #include <netbt/hci.h>
                     93:
                     94: /*******************************************************************************
                     95:  *
                     96:  *     debugging stuff
                     97:  */
                     98: #undef DPRINTF
                     99: #undef DPRINTFN
1.3       augustss  100:
1.1       augustss  101: #ifdef UBT_DEBUG
1.27      plunky    102: int    ubt_debug = 0;
1.14      gdamore   103:
1.40      plunky    104: #define DPRINTF(...)           do {            \
                    105:        if (ubt_debug) {                        \
                    106:                printf("%s: ", __func__);       \
                    107:                printf(__VA_ARGS__);            \
                    108:        }                                       \
1.14      gdamore   109: } while (/* CONSTCOND */0)
                    110:
1.40      plunky    111: #define DPRINTFN(n, ...)       do {            \
                    112:        if (ubt_debug > (n)) {                  \
                    113:                printf("%s: ", __func__);       \
                    114:                printf(__VA_ARGS__);            \
                    115:        }                                       \
1.14      gdamore   116: } while (/* CONSTCOND */0)
                    117:
                    118: SYSCTL_SETUP(sysctl_hw_ubt_debug_setup, "sysctl hw.ubt_debug setup")
                    119: {
                    120:
                    121:        sysctl_createv(NULL, 0, NULL, NULL,
                    122:                CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
                    123:                CTLTYPE_INT, "ubt_debug",
                    124:                SYSCTL_DESCR("ubt debug level"),
                    125:                NULL, 0,
                    126:                &ubt_debug, sizeof(ubt_debug),
                    127:                CTL_HW, CTL_CREATE, CTL_EOL);
                    128: }
1.1       augustss  129: #else
1.14      gdamore   130: #define DPRINTF(...)
                    131: #define DPRINTFN(...)
1.1       augustss  132: #endif
                    133:
1.14      gdamore   134: /*******************************************************************************
                    135:  *
                    136:  *     ubt softc structure
                    137:  *
                    138:  */
                    139:
                    140: /* buffer sizes */
1.1       augustss  141: /*
1.14      gdamore   142:  * NB: although ACL packets can extend to 65535 bytes, most devices
                    143:  * have max_acl_size at much less (largest I have seen is 384)
1.1       augustss  144:  */
1.14      gdamore   145: #define UBT_BUFSIZ_CMD         (HCI_CMD_PKT_SIZE - 1)
                    146: #define UBT_BUFSIZ_ACL         (2048 - 1)
                    147: #define UBT_BUFSIZ_EVENT       (HCI_EVENT_PKT_SIZE - 1)
                    148:
                    149: /* Transmit timeouts */
                    150: #define UBT_CMD_TIMEOUT                USBD_DEFAULT_TIMEOUT
                    151: #define UBT_ACL_TIMEOUT                USBD_DEFAULT_TIMEOUT
                    152:
                    153: /*
                    154:  * ISOC transfers
                    155:  *
                    156:  * xfer buffer size depends on the frame size, and the number
                    157:  * of frames per transfer is fixed, as each frame should be
                    158:  * 1ms worth of data. This keeps the rate that xfers complete
                    159:  * fairly constant. We use multiple xfers to keep the hardware
                    160:  * busy
                    161:  */
                    162: #define UBT_NXFERS             3       /* max xfers to queue */
                    163: #define UBT_NFRAMES            10      /* frames per xfer */
                    164:
                    165: struct ubt_isoc_xfer {
                    166:        struct ubt_softc        *softc;
1.54      skrll     167:        struct usbd_xfer        *xfer;
1.14      gdamore   168:        uint8_t                 *buf;
                    169:        uint16_t                 size[UBT_NFRAMES];
                    170:        int                      busy;
                    171: };
1.1       augustss  172:
                    173: struct ubt_softc {
1.39      dyoung    174:        device_t                 sc_dev;
1.54      skrll     175:        struct usbd_device      *sc_udev;
1.14      gdamore   176:        int                      sc_refcnt;
                    177:        int                      sc_dying;
1.29      plunky    178:        int                      sc_enabled;
1.14      gdamore   179:
                    180:        /* Control Interface */
1.54      skrll     181:        struct usbd_interface *  sc_iface0;
1.14      gdamore   182:
                    183:        /* Commands (control) */
1.54      skrll     184:        struct usbd_xfer        *sc_cmd_xfer;
1.14      gdamore   185:        uint8_t                 *sc_cmd_buf;
1.29      plunky    186:        int                      sc_cmd_busy;   /* write active */
                    187:        MBUFQ_HEAD()             sc_cmd_queue;  /* output queue */
1.14      gdamore   188:
                    189:        /* Events (interrupt) */
                    190:        int                      sc_evt_addr;   /* endpoint address */
1.54      skrll     191:        struct usbd_pipe        *sc_evt_pipe;
1.14      gdamore   192:        uint8_t                 *sc_evt_buf;
1.5       dsainty   193:
                    194:        /* ACL data (in) */
1.14      gdamore   195:        int                      sc_aclrd_addr; /* endpoint address */
1.54      skrll     196:        struct usbd_pipe        *sc_aclrd_pipe; /* read pipe */
                    197:        struct usbd_xfer        *sc_aclrd_xfer; /* read xfer */
1.14      gdamore   198:        uint8_t                 *sc_aclrd_buf;  /* read buffer */
                    199:        int                      sc_aclrd_busy; /* reading */
1.5       dsainty   200:
                    201:        /* ACL data (out) */
1.14      gdamore   202:        int                      sc_aclwr_addr; /* endpoint address */
1.54      skrll     203:        struct usbd_pipe        *sc_aclwr_pipe; /* write pipe */
                    204:        struct usbd_xfer        *sc_aclwr_xfer; /* write xfer */
1.14      gdamore   205:        uint8_t                 *sc_aclwr_buf;  /* write buffer */
1.29      plunky    206:        int                      sc_aclwr_busy; /* write active */
                    207:        MBUFQ_HEAD()             sc_aclwr_queue;/* output queue */
1.14      gdamore   208:
                    209:        /* ISOC interface */
1.54      skrll     210:        struct usbd_interface   *sc_iface1;     /* ISOC interface */
1.14      gdamore   211:        struct sysctllog        *sc_log;        /* sysctl log */
                    212:        int                      sc_config;     /* current config no */
                    213:        int                      sc_alt_config; /* no of alternates */
                    214:
                    215:        /* SCO data (in) */
                    216:        int                      sc_scord_addr; /* endpoint address */
1.54      skrll     217:        struct usbd_pipe        *sc_scord_pipe; /* read pipe */
1.14      gdamore   218:        int                      sc_scord_size; /* frame length */
                    219:        struct ubt_isoc_xfer     sc_scord[UBT_NXFERS];
                    220:        struct mbuf             *sc_scord_mbuf; /* current packet */
                    221:
                    222:        /* SCO data (out) */
                    223:        int                      sc_scowr_addr; /* endpoint address */
1.54      skrll     224:        struct usbd_pipe        *sc_scowr_pipe; /* write pipe */
1.14      gdamore   225:        int                      sc_scowr_size; /* frame length */
                    226:        struct ubt_isoc_xfer     sc_scowr[UBT_NXFERS];
                    227:        struct mbuf             *sc_scowr_mbuf; /* current packet */
1.29      plunky    228:        int                      sc_scowr_busy; /* write active */
                    229:        MBUFQ_HEAD()             sc_scowr_queue;/* output queue */
1.1       augustss  230:
1.14      gdamore   231:        /* Protocol structure */
1.29      plunky    232:        struct hci_unit         *sc_unit;
                    233:        struct bt_stats          sc_stats;
1.23      plunky    234:
                    235:        /* Successfully attached */
                    236:        int                      sc_ok;
1.14      gdamore   237: };
                    238:
                    239: /*******************************************************************************
                    240:  *
                    241:  * Bluetooth unit/USB callback routines
                    242:  *
                    243:  */
1.39      dyoung    244: static int ubt_enable(device_t);
                    245: static void ubt_disable(device_t);
1.14      gdamore   246:
1.39      dyoung    247: static void ubt_xmit_cmd(device_t, struct mbuf *);
1.29      plunky    248: static void ubt_xmit_cmd_start(struct ubt_softc *);
1.54      skrll     249: static void ubt_xmit_cmd_complete(struct usbd_xfer *,
                    250:                                void *, usbd_status);
1.14      gdamore   251:
1.39      dyoung    252: static void ubt_xmit_acl(device_t, struct mbuf *);
1.29      plunky    253: static void ubt_xmit_acl_start(struct ubt_softc *);
1.54      skrll     254: static void ubt_xmit_acl_complete(struct usbd_xfer *,
                    255:                                void *, usbd_status);
1.14      gdamore   256:
1.39      dyoung    257: static void ubt_xmit_sco(device_t, struct mbuf *);
1.29      plunky    258: static void ubt_xmit_sco_start(struct ubt_softc *);
1.14      gdamore   259: static void ubt_xmit_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
1.54      skrll     260: static void ubt_xmit_sco_complete(struct usbd_xfer *,
                    261:                                void *, usbd_status);
1.5       dsainty   262:
1.54      skrll     263: static void ubt_recv_event(struct usbd_xfer *,
                    264:                                void *, usbd_status);
1.1       augustss  265:
1.14      gdamore   266: static void ubt_recv_acl_start(struct ubt_softc *);
1.54      skrll     267: static void ubt_recv_acl_complete(struct usbd_xfer *,
                    268:                                void *, usbd_status);
1.5       dsainty   269:
1.14      gdamore   270: static void ubt_recv_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
1.54      skrll     271: static void ubt_recv_sco_complete(struct usbd_xfer *,
                    272:                                void *, usbd_status);
1.6       dsainty   273:
1.39      dyoung    274: static void ubt_stats(device_t, struct bt_stats *, int);
1.29      plunky    275:
                    276: static const struct hci_if ubt_hci = {
                    277:        .enable = ubt_enable,
                    278:        .disable = ubt_disable,
                    279:        .output_cmd = ubt_xmit_cmd,
                    280:        .output_acl = ubt_xmit_acl,
                    281:        .output_sco = ubt_xmit_sco,
                    282:        .get_stats = ubt_stats,
1.54      skrll     283:        .ipl = IPL_SOFTUSB,
1.29      plunky    284: };
1.6       dsainty   285:
1.14      gdamore   286: /*******************************************************************************
                    287:  *
                    288:  * USB Autoconfig stuff
                    289:  *
                    290:  */
1.5       dsainty   291:
1.55      msaitoh   292: int    ubt_match(device_t, cfdata_t, void *);
                    293: void   ubt_attach(device_t, device_t, void *);
                    294: int    ubt_detach(device_t, int);
                    295: int    ubt_activate(device_t, enum devact);
1.62      mrg       296:
1.55      msaitoh   297: CFATTACH_DECL_NEW(ubt, sizeof(struct ubt_softc), ubt_match, ubt_attach,
                    298:     ubt_detach, ubt_activate);
1.1       augustss  299:
1.14      gdamore   300: static int ubt_set_isoc_config(struct ubt_softc *);
                    301: static int ubt_sysctl_config(SYSCTLFN_PROTO);
                    302: static void ubt_abortdealloc(struct ubt_softc *);
                    303:
1.15      plunky    304: /*
1.53      plunky    305:  * To match or ignore, add details to the ubt_dev list.
                    306:  * Use value of -1 to indicate a wildcard
                    307:  * To override another entry, add details earlier
1.15      plunky    308:  */
1.49      christos  309: const struct ubt_devno {
1.53      plunky    310:        int                     vendor;
                    311:        int                     product;
                    312:        int                     class;
                    313:        int                     subclass;
                    314:        int                     proto;
1.49      christos  315:        int                     match;
                    316: } ubt_dev[] = {
1.53      plunky    317:        {   /* ignore Broadcom 2033 without firmware */
                    318:            USB_VENDOR_BROADCOM,
                    319:            USB_PRODUCT_BROADCOM_BCM2033NF,
                    320:            -1,
                    321:            -1,
                    322:            -1,
                    323:            UMATCH_NONE
                    324:        },
                    325:        {   /* Apple Bluetooth Host Controller MacbookPro 7,1 */
                    326:            USB_VENDOR_APPLE,
                    327:            USB_PRODUCT_APPLE_BLUETOOTH_HOST_1,
                    328:            -1,
                    329:            -1,
                    330:            -1,
                    331:            UMATCH_VENDOR_PRODUCT
                    332:        },
                    333:        {   /* Apple Bluetooth Host Controller iMac 11,1 */
                    334:            USB_VENDOR_APPLE,
                    335:            USB_PRODUCT_APPLE_BLUETOOTH_HOST_2,
                    336:            -1,
                    337:            -1,
                    338:            -1,
                    339:            UMATCH_VENDOR_PRODUCT
                    340:        },
                    341:        {   /* Apple Bluetooth Host Controller MacBookPro 8,2 */
                    342:            USB_VENDOR_APPLE,
                    343:            USB_PRODUCT_APPLE_BLUETOOTH_HOST_3,
                    344:            -1,
                    345:            -1,
                    346:            -1,
                    347:            UMATCH_VENDOR_PRODUCT
                    348:        },
                    349:        {   /* Apple Bluetooth Host Controller MacBookAir 3,1 3,2*/
                    350:            USB_VENDOR_APPLE,
                    351:            USB_PRODUCT_APPLE_BLUETOOTH_HOST_4,
                    352:            -1,
                    353:            -1,
                    354:            -1,
                    355:            UMATCH_VENDOR_PRODUCT
                    356:        },
                    357:        {   /* Apple Bluetooth Host Controller MacBookAir 4,1 */
                    358:            USB_VENDOR_APPLE,
                    359:            USB_PRODUCT_APPLE_BLUETOOTH_HOST_5,
                    360:            -1,
                    361:            -1,
                    362:            -1,
                    363:            UMATCH_VENDOR_PRODUCT
                    364:        },
                    365:        {   /* Apple Bluetooth Host Controller MacMini 5,1 */
                    366:            USB_VENDOR_APPLE,
                    367:            USB_PRODUCT_APPLE_BLUETOOTH_HOST_6,
                    368:            -1,
                    369:            -1,
                    370:            -1,
                    371:            UMATCH_VENDOR_PRODUCT
                    372:        },
                    373:        {   /* Apple Bluetooth Host Controller MacBookAir 6,1 */
                    374:            USB_VENDOR_APPLE,
                    375:            USB_PRODUCT_APPLE_BLUETOOTH_HOST_7,
                    376:            -1,
                    377:            -1,
                    378:            -1,
                    379:            UMATCH_VENDOR_PRODUCT
                    380:        },
1.58      snj       381:        {   /* Apple Bluetooth Host Controller MacBookPro 9,2 */
                    382:            USB_VENDOR_APPLE,
                    383:            USB_PRODUCT_APPLE_BLUETOOTH_HOST_8,
                    384:            -1,
                    385:            -1,
                    386:            -1,
                    387:            UMATCH_VENDOR_PRODUCT
                    388:        },
1.53      plunky    389:        {   /* Broadcom chips with PatchRAM support */
                    390:            USB_VENDOR_BROADCOM,
                    391:            -1,
                    392:            UDCLASS_VENDOR,
                    393:            UDSUBCLASS_RF,
                    394:            UDPROTO_BLUETOOTH,
                    395:            UMATCH_VENDOR_DEVCLASS_DEVPROTO
                    396:        },
                    397:        {   /* Broadcom based device with PatchRAM support */
                    398:            USB_VENDOR_FOXCONN,
                    399:            -1,
                    400:            UDCLASS_VENDOR,
                    401:            UDSUBCLASS_RF,
                    402:            UDPROTO_BLUETOOTH,
                    403:            UMATCH_VENDOR_DEVCLASS_DEVPROTO
                    404:        },
                    405:        {   /* Broadcom based device with PatchRAM support */
                    406:            USB_VENDOR_LITEON,
                    407:            -1,
                    408:            UDCLASS_VENDOR,
                    409:            UDSUBCLASS_RF,
                    410:            UDPROTO_BLUETOOTH,
                    411:            UMATCH_VENDOR_DEVCLASS_DEVPROTO
                    412:        },
                    413:        {   /* Broadcom based device with PatchRAM support */
                    414:            USB_VENDOR_BELKIN,
                    415:            -1,
                    416:            UDCLASS_VENDOR,
                    417:            UDSUBCLASS_RF,
                    418:            UDPROTO_BLUETOOTH,
                    419:            UMATCH_VENDOR_DEVCLASS_DEVPROTO
                    420:        },
                    421:        {   /* Broadcom based device with PatchRAM support */
                    422:            USB_VENDOR_TOSHIBA,
                    423:            -1,
                    424:            UDCLASS_VENDOR,
                    425:            UDSUBCLASS_RF,
                    426:            UDPROTO_BLUETOOTH,
                    427:            UMATCH_VENDOR_DEVCLASS_DEVPROTO
                    428:        },
                    429:        {   /* Broadcom based device with PatchRAM support */
                    430:            USB_VENDOR_ASUSTEK,
                    431:            -1,
                    432:            UDCLASS_VENDOR,
                    433:            UDSUBCLASS_RF,
                    434:            UDPROTO_BLUETOOTH,
                    435:            UMATCH_VENDOR_DEVCLASS_DEVPROTO
                    436:        },
                    437:        {   /* Generic Bluetooth SIG compliant devices */
                    438:            -1,
                    439:            -1,
                    440:            UDCLASS_WIRELESS,
                    441:            UDSUBCLASS_RF,
                    442:            UDPROTO_BLUETOOTH,
                    443:            UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO
                    444:        },
1.15      plunky    445: };
                    446:
1.54      skrll     447: int
1.39      dyoung    448: ubt_match(device_t parent, cfdata_t match, void *aux)
1.1       augustss  449: {
1.39      dyoung    450:        struct usb_attach_arg *uaa = aux;
1.53      plunky    451:        size_t i;
1.1       augustss  452:
1.14      gdamore   453:        DPRINTFN(50, "ubt_match\n");
1.1       augustss  454:
1.53      plunky    455:        for (i = 0; i < __arraycount(ubt_dev); i++) {
1.56      msaitoh   456:                if (ubt_dev[i].vendor != -1
1.54      skrll     457:                    && ubt_dev[i].vendor != (int)uaa->uaa_vendor)
1.53      plunky    458:                        continue;
1.56      msaitoh   459:                if (ubt_dev[i].product != -1
1.54      skrll     460:                    && ubt_dev[i].product != (int)uaa->uaa_product)
1.53      plunky    461:                        continue;
1.56      msaitoh   462:                if (ubt_dev[i].class != -1
1.54      skrll     463:                    && ubt_dev[i].class != uaa->uaa_class)
1.53      plunky    464:                        continue;
1.56      msaitoh   465:                if (ubt_dev[i].subclass != -1
1.54      skrll     466:                    && ubt_dev[i].subclass != uaa->uaa_subclass)
1.53      plunky    467:                        continue;
1.56      msaitoh   468:                if (ubt_dev[i].proto != -1
1.54      skrll     469:                    && ubt_dev[i].proto != uaa->uaa_proto)
1.53      plunky    470:                        continue;
1.15      plunky    471:
1.53      plunky    472:                return ubt_dev[i].match;
                    473:        }
1.14      gdamore   474:
                    475:        return UMATCH_NONE;
1.1       augustss  476: }
                    477:
1.54      skrll     478: void
1.39      dyoung    479: ubt_attach(device_t parent, device_t self, void *aux)
1.1       augustss  480: {
1.39      dyoung    481:        struct ubt_softc *sc = device_private(self);
                    482:        struct usb_attach_arg *uaa = aux;
1.14      gdamore   483:        usb_config_descriptor_t *cd;
                    484:        usb_endpoint_descriptor_t *ed;
                    485:        const struct sysctlnode *node;
                    486:        char *devinfop;
                    487:        int err;
                    488:        uint8_t count, i;
1.1       augustss  489:
1.14      gdamore   490:        DPRINTFN(50, "ubt_attach: sc=%p\n", sc);
1.1       augustss  491:
1.32      cube      492:        sc->sc_dev = self;
1.54      skrll     493:        sc->sc_udev = uaa->uaa_device;
1.14      gdamore   494:
1.29      plunky    495:        MBUFQ_INIT(&sc->sc_cmd_queue);
                    496:        MBUFQ_INIT(&sc->sc_aclwr_queue);
                    497:        MBUFQ_INIT(&sc->sc_scowr_queue);
                    498:
1.37      plunky    499:        aprint_naive("\n");
                    500:        aprint_normal("\n");
                    501:
1.14      gdamore   502:        devinfop = usbd_devinfo_alloc(sc->sc_udev, 0);
1.32      cube      503:        aprint_normal_dev(self, "%s\n", devinfop);
1.12      augustss  504:        usbd_devinfo_free(devinfop);
1.1       augustss  505:
1.14      gdamore   506:        /*
1.23      plunky    507:         * Move the device into the configured state
1.14      gdamore   508:         */
1.23      plunky    509:        err = usbd_set_config_index(sc->sc_udev, 0, 1);
                    510:        if (err) {
1.56      msaitoh   511:                aprint_error_dev(self,
                    512:                    "failed to set configuration idx 0: %s\n",
1.32      cube      513:                    usbd_errstr(err));
1.14      gdamore   514:
1.39      dyoung    515:                return;
1.14      gdamore   516:        }
1.1       augustss  517:
1.5       dsainty   518:        /*
1.14      gdamore   519:         * Interface 0 must have 3 endpoints
                    520:         *      1) Interrupt endpoint to receive HCI events
                    521:         *      2) Bulk IN endpoint to receive ACL data
                    522:         *      3) Bulk OUT endpoint to send ACL data
1.3       augustss  523:         */
1.23      plunky    524:        err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
1.14      gdamore   525:        if (err) {
1.56      msaitoh   526:                aprint_error_dev(self,
                    527:                    "Could not get interface 0 handle %s (%d)\n",
                    528:                    usbd_errstr(err), err);
1.14      gdamore   529:
1.39      dyoung    530:                return;
1.14      gdamore   531:        }
1.5       dsainty   532:
                    533:        sc->sc_evt_addr = -1;
                    534:        sc->sc_aclrd_addr = -1;
                    535:        sc->sc_aclwr_addr = -1;
                    536:
1.14      gdamore   537:        count = 0;
1.23      plunky    538:        (void)usbd_endpoint_count(sc->sc_iface0, &count);
1.14      gdamore   539:
                    540:        for (i = 0 ; i < count ; i++) {
                    541:                int dir, type;
                    542:
1.23      plunky    543:                ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
1.1       augustss  544:                if (ed == NULL) {
1.32      cube      545:                        aprint_error_dev(self,
                    546:                            "could not read endpoint descriptor %d\n", i);
1.14      gdamore   547:
1.39      dyoung    548:                        return;
1.1       augustss  549:                }
1.5       dsainty   550:
1.14      gdamore   551:                dir = UE_GET_DIR(ed->bEndpointAddress);
                    552:                type = UE_GET_XFERTYPE(ed->bmAttributes);
1.5       dsainty   553:
1.14      gdamore   554:                if (dir == UE_DIR_IN && type == UE_INTERRUPT)
1.5       dsainty   555:                        sc->sc_evt_addr = ed->bEndpointAddress;
1.14      gdamore   556:                else if (dir == UE_DIR_IN && type == UE_BULK)
1.5       dsainty   557:                        sc->sc_aclrd_addr = ed->bEndpointAddress;
1.14      gdamore   558:                else if (dir == UE_DIR_OUT && type == UE_BULK)
1.5       dsainty   559:                        sc->sc_aclwr_addr = ed->bEndpointAddress;
1.1       augustss  560:        }
1.5       dsainty   561:
1.14      gdamore   562:        if (sc->sc_evt_addr == -1) {
1.32      cube      563:                aprint_error_dev(self,
                    564:                    "missing INTERRUPT endpoint on interface 0\n");
1.14      gdamore   565:
1.39      dyoung    566:                return;
1.14      gdamore   567:        }
                    568:        if (sc->sc_aclrd_addr == -1) {
1.32      cube      569:                aprint_error_dev(self,
                    570:                    "missing BULK IN endpoint on interface 0\n");
1.14      gdamore   571:
1.39      dyoung    572:                return;
1.14      gdamore   573:        }
                    574:        if (sc->sc_aclwr_addr == -1) {
1.32      cube      575:                aprint_error_dev(self,
                    576:                    "missing BULK OUT endpoint on interface 0\n");
1.14      gdamore   577:
1.39      dyoung    578:                return;
1.14      gdamore   579:        }
                    580:
                    581:        /*
                    582:         * Interface 1 must have 2 endpoints
                    583:         *      1) Isochronous IN endpoint to receive SCO data
                    584:         *      2) Isochronous OUT endpoint to send SCO data
                    585:         *
                    586:         * and will have several configurations, which can be selected
                    587:         * via a sysctl variable. We select config 0 to start, which
                    588:         * means that no SCO data will be available.
                    589:         */
1.23      plunky    590:        err = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
1.14      gdamore   591:        if (err) {
1.32      cube      592:                aprint_error_dev(self,
                    593:                    "Could not get interface 1 handle %s (%d)\n",
                    594:                    usbd_errstr(err), err);
1.14      gdamore   595:
1.39      dyoung    596:                return;
1.14      gdamore   597:        }
                    598:
                    599:        cd = usbd_get_config_descriptor(sc->sc_udev);
                    600:        if (cd == NULL) {
1.32      cube      601:                aprint_error_dev(self, "could not get config descriptor\n");
1.14      gdamore   602:
1.39      dyoung    603:                return;
1.14      gdamore   604:        }
                    605:
                    606:        sc->sc_alt_config = usbd_get_no_alts(cd, 1);
                    607:
                    608:        /* set initial config */
                    609:        err = ubt_set_isoc_config(sc);
                    610:        if (err) {
1.32      cube      611:                aprint_error_dev(self, "ISOC config failed\n");
1.14      gdamore   612:
1.39      dyoung    613:                return;
1.1       augustss  614:        }
                    615:
1.14      gdamore   616:        /* Attach HCI */
1.51      rmind     617:        sc->sc_unit = hci_attach_pcb(&ubt_hci, sc->sc_dev, 0);
1.14      gdamore   618:
1.55      msaitoh   619:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
1.14      gdamore   620:
                    621:        /* sysctl set-up for alternate configs */
                    622:        sysctl_createv(&sc->sc_log, 0, NULL, &node,
                    623:                0,
1.39      dyoung    624:                CTLTYPE_NODE, device_xname(sc->sc_dev),
1.14      gdamore   625:                SYSCTL_DESCR("ubt driver information"),
                    626:                NULL, 0,
                    627:                NULL, 0,
                    628:                CTL_HW,
                    629:                CTL_CREATE, CTL_EOL);
                    630:
                    631:        if (node != NULL) {
                    632:                sysctl_createv(&sc->sc_log, 0, NULL, NULL,
                    633:                        CTLFLAG_READWRITE,
                    634:                        CTLTYPE_INT, "config",
                    635:                        SYSCTL_DESCR("configuration number"),
                    636:                        ubt_sysctl_config, 0,
1.48      dsl       637:                        (void *)sc, 0,
1.14      gdamore   638:                        CTL_HW, node->sysctl_num,
                    639:                        CTL_CREATE, CTL_EOL);
                    640:
                    641:                sysctl_createv(&sc->sc_log, 0, NULL, NULL,
                    642:                        CTLFLAG_READONLY,
                    643:                        CTLTYPE_INT, "alt_config",
                    644:                        SYSCTL_DESCR("number of alternate configurations"),
                    645:                        NULL, 0,
                    646:                        &sc->sc_alt_config, sizeof(sc->sc_alt_config),
                    647:                        CTL_HW, node->sysctl_num,
                    648:                        CTL_CREATE, CTL_EOL);
                    649:
                    650:                sysctl_createv(&sc->sc_log, 0, NULL, NULL,
                    651:                        CTLFLAG_READONLY,
                    652:                        CTLTYPE_INT, "sco_rxsize",
                    653:                        SYSCTL_DESCR("max SCO receive size"),
                    654:                        NULL, 0,
                    655:                        &sc->sc_scord_size, sizeof(sc->sc_scord_size),
                    656:                        CTL_HW, node->sysctl_num,
                    657:                        CTL_CREATE, CTL_EOL);
                    658:
                    659:                sysctl_createv(&sc->sc_log, 0, NULL, NULL,
                    660:                        CTLFLAG_READONLY,
                    661:                        CTLTYPE_INT, "sco_txsize",
                    662:                        SYSCTL_DESCR("max SCO transmit size"),
                    663:                        NULL, 0,
                    664:                        &sc->sc_scowr_size, sizeof(sc->sc_scowr_size),
                    665:                        CTL_HW, node->sysctl_num,
                    666:                        CTL_CREATE, CTL_EOL);
                    667:        }
                    668:
1.23      plunky    669:        sc->sc_ok = 1;
1.46      plunky    670:
1.35      drochner  671:        if (!pmf_device_register(self, NULL, NULL))
                    672:                aprint_error_dev(self, "couldn't establish power handler\n");
1.46      plunky    673:
1.39      dyoung    674:        return;
1.14      gdamore   675: }
                    676:
1.54      skrll     677: int
1.39      dyoung    678: ubt_detach(device_t self, int flags)
1.14      gdamore   679: {
1.39      dyoung    680:        struct ubt_softc *sc = device_private(self);
1.14      gdamore   681:        int s;
                    682:
                    683:        DPRINTF("sc=%p flags=%d\n", sc, flags);
                    684:
1.46      plunky    685:        pmf_device_deregister(self);
1.30      christos  686:
1.14      gdamore   687:        sc->sc_dying = 1;
                    688:
1.23      plunky    689:        if (!sc->sc_ok)
                    690:                return 0;
                    691:
1.14      gdamore   692:        /* delete sysctl nodes */
                    693:        sysctl_teardown(&sc->sc_log);
                    694:
                    695:        /* Detach HCI interface */
1.29      plunky    696:        if (sc->sc_unit) {
1.51      rmind     697:                hci_detach_pcb(sc->sc_unit);
1.29      plunky    698:                sc->sc_unit = NULL;
                    699:        }
1.14      gdamore   700:
                    701:        /*
                    702:         * Abort all pipes. Causes processes waiting for transfer to wake.
                    703:         *
1.51      rmind     704:         * Actually, hci_detach_pcb() above will call ubt_disable() which
                    705:         * may call ubt_abortdealloc(), but lets be sure since doing it
                    706:         * twice wont cause an error.
1.14      gdamore   707:         */
                    708:        ubt_abortdealloc(sc);
                    709:
                    710:        /* wait for all processes to finish */
                    711:        s = splusb();
                    712:        if (sc->sc_refcnt-- > 0)
1.45      mrg       713:                usb_detach_waitold(sc->sc_dev);
1.14      gdamore   714:
                    715:        splx(s);
                    716:
1.55      msaitoh   717:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
1.14      gdamore   718:
                    719:        DPRINTFN(1, "driver detached\n");
                    720:
                    721:        return 0;
                    722: }
                    723:
                    724: int
1.39      dyoung    725: ubt_activate(device_t self, enum devact act)
1.14      gdamore   726: {
1.39      dyoung    727:        struct ubt_softc *sc = device_private(self);
1.14      gdamore   728:
1.25      plunky    729:        DPRINTFN(1, "sc=%p, act=%d\n", sc, act);
1.14      gdamore   730:
                    731:        switch (act) {
                    732:        case DVACT_DEACTIVATE:
                    733:                sc->sc_dying = 1;
1.38      dyoung    734:                return 0;
1.25      plunky    735:        default:
1.38      dyoung    736:                return EOPNOTSUPP;
1.14      gdamore   737:        }
                    738: }
                    739:
                    740: /* set ISOC configuration */
                    741: static int
                    742: ubt_set_isoc_config(struct ubt_softc *sc)
                    743: {
                    744:        usb_endpoint_descriptor_t *ed;
                    745:        int rd_addr, wr_addr, rd_size, wr_size;
                    746:        uint8_t count, i;
                    747:        int err;
                    748:
                    749:        err = usbd_set_interface(sc->sc_iface1, sc->sc_config);
1.17      plunky    750:        if (err != USBD_NORMAL_COMPLETION) {
1.54      skrll     751:                aprint_error_dev(sc->sc_dev,
1.32      cube      752:                    "Could not set config %d on ISOC interface. %s (%d)\n",
                    753:                    sc->sc_config, usbd_errstr(err), err);
1.14      gdamore   754:
1.17      plunky    755:                return err == USBD_IN_USE ? EBUSY : EIO;
1.14      gdamore   756:        }
                    757:
                    758:        /*
                    759:         * We wont get past the above if there are any pipes open, so no
                    760:         * need to worry about buf/xfer/pipe deallocation. If we get an
                    761:         * error after this, the frame quantities will be 0 and no SCO
                    762:         * data will be possible.
                    763:         */
                    764:
                    765:        sc->sc_scord_size = rd_size = 0;
                    766:        sc->sc_scord_addr = rd_addr = -1;
                    767:
                    768:        sc->sc_scowr_size = wr_size = 0;
                    769:        sc->sc_scowr_addr = wr_addr = -1;
                    770:
                    771:        count = 0;
                    772:        (void)usbd_endpoint_count(sc->sc_iface1, &count);
                    773:
                    774:        for (i = 0 ; i < count ; i++) {
                    775:                ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
                    776:                if (ed == NULL) {
1.32      cube      777:                        aprint_error_dev(sc->sc_dev,
                    778:                            "could not read endpoint descriptor %d\n", i);
1.14      gdamore   779:
                    780:                        return EIO;
                    781:                }
                    782:
                    783:                DPRINTFN(5, "%s: endpoint type %02x (%02x) addr %02x (%s)\n",
1.39      dyoung    784:                        device_xname(sc->sc_dev),
1.14      gdamore   785:                        UE_GET_XFERTYPE(ed->bmAttributes),
                    786:                        UE_GET_ISO_TYPE(ed->bmAttributes),
                    787:                        ed->bEndpointAddress,
                    788:                        UE_GET_DIR(ed->bEndpointAddress) ? "in" : "out");
                    789:
                    790:                if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
1.3       augustss  791:                        continue;
1.14      gdamore   792:
                    793:                if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
                    794:                        rd_addr = ed->bEndpointAddress;
                    795:                        rd_size = UGETW(ed->wMaxPacketSize);
                    796:                } else {
                    797:                        wr_addr = ed->bEndpointAddress;
                    798:                        wr_size = UGETW(ed->wMaxPacketSize);
1.3       augustss  799:                }
                    800:        }
                    801:
1.14      gdamore   802:        if (rd_addr == -1) {
1.32      cube      803:                aprint_error_dev(sc->sc_dev,
                    804:                    "missing ISOC IN endpoint on interface config %d\n",
                    805:                    sc->sc_config);
1.14      gdamore   806:
                    807:                return ENOENT;
                    808:        }
                    809:        if (wr_addr == -1) {
1.32      cube      810:                aprint_error_dev(sc->sc_dev,
                    811:                    "missing ISOC OUT endpoint on interface config %d\n",
                    812:                    sc->sc_config);
1.14      gdamore   813:
                    814:                return ENOENT;
                    815:        }
                    816:
                    817:        if (rd_size > MLEN) {
1.32      cube      818:                aprint_error_dev(sc->sc_dev, "rd_size=%d exceeds MLEN\n",
                    819:                    rd_size);
1.14      gdamore   820:
                    821:                return EOVERFLOW;
                    822:        }
1.3       augustss  823:
1.14      gdamore   824:        if (wr_size > MLEN) {
1.32      cube      825:                aprint_error_dev(sc->sc_dev, "wr_size=%d exceeds MLEN\n",
                    826:                    wr_size);
1.14      gdamore   827:
                    828:                return EOVERFLOW;
                    829:        }
                    830:
                    831:        sc->sc_scord_size = rd_size;
                    832:        sc->sc_scord_addr = rd_addr;
                    833:
                    834:        sc->sc_scowr_size = wr_size;
                    835:        sc->sc_scowr_addr = wr_addr;
                    836:
                    837:        return 0;
                    838: }
1.1       augustss  839:
1.14      gdamore   840: /* sysctl helper to set alternate configurations */
                    841: static int
                    842: ubt_sysctl_config(SYSCTLFN_ARGS)
                    843: {
                    844:        struct sysctlnode node;
                    845:        struct ubt_softc *sc;
                    846:        int t, error;
                    847:
                    848:        node = *rnode;
                    849:        sc = node.sysctl_data;
                    850:
                    851:        t = sc->sc_config;
                    852:        node.sysctl_data = &t;
                    853:        error = sysctl_lookup(SYSCTLFN_CALL(&node));
                    854:        if (error || newp == NULL)
                    855:                return error;
1.5       dsainty   856:
1.14      gdamore   857:        if (t < 0 || t >= sc->sc_alt_config)
                    858:                return EINVAL;
1.1       augustss  859:
1.18      plunky    860:        /* This may not change when the unit is enabled */
1.29      plunky    861:        if (sc->sc_enabled)
1.18      plunky    862:                return EBUSY;
                    863:
1.44      plunky    864:        KERNEL_LOCK(1, curlwp);
1.14      gdamore   865:        sc->sc_config = t;
1.44      plunky    866:        error = ubt_set_isoc_config(sc);
                    867:        KERNEL_UNLOCK_ONE(curlwp);
                    868:        return error;
1.1       augustss  869: }
                    870:
1.5       dsainty   871: static void
                    872: ubt_abortdealloc(struct ubt_softc *sc)
                    873: {
1.14      gdamore   874:        int i;
                    875:
                    876:        DPRINTFN(1, "sc=%p\n", sc);
1.5       dsainty   877:
1.14      gdamore   878:        /* Abort all pipes */
1.36      plunky    879:        usbd_abort_default_pipe(sc->sc_udev);
                    880:
1.5       dsainty   881:        if (sc->sc_evt_pipe != NULL) {
                    882:                usbd_abort_pipe(sc->sc_evt_pipe);
                    883:        }
1.14      gdamore   884:
1.5       dsainty   885:        if (sc->sc_aclrd_pipe != NULL) {
                    886:                usbd_abort_pipe(sc->sc_aclrd_pipe);
                    887:        }
1.14      gdamore   888:
1.5       dsainty   889:        if (sc->sc_aclwr_pipe != NULL) {
                    890:                usbd_abort_pipe(sc->sc_aclwr_pipe);
                    891:        }
1.14      gdamore   892:
                    893:        if (sc->sc_scord_pipe != NULL) {
                    894:                usbd_abort_pipe(sc->sc_scord_pipe);
                    895:        }
                    896:
                    897:        if (sc->sc_scowr_pipe != NULL) {
                    898:                usbd_abort_pipe(sc->sc_scowr_pipe);
                    899:        }
                    900:
                    901:        /* Free event buffer */
                    902:        if (sc->sc_evt_buf != NULL) {
1.54      skrll     903:                kmem_free(sc->sc_evt_buf, UBT_BUFSIZ_EVENT);
1.14      gdamore   904:                sc->sc_evt_buf = NULL;
                    905:        }
                    906:
                    907:        /* Free all xfers and xfer buffers (implicit) */
                    908:        if (sc->sc_cmd_xfer != NULL) {
1.54      skrll     909:                usbd_destroy_xfer(sc->sc_cmd_xfer);
1.14      gdamore   910:                sc->sc_cmd_xfer = NULL;
                    911:                sc->sc_cmd_buf = NULL;
                    912:        }
                    913:
1.5       dsainty   914:        if (sc->sc_aclrd_xfer != NULL) {
1.54      skrll     915:                usbd_destroy_xfer(sc->sc_aclrd_xfer);
1.5       dsainty   916:                sc->sc_aclrd_xfer = NULL;
                    917:                sc->sc_aclrd_buf = NULL;
                    918:        }
1.14      gdamore   919:
1.5       dsainty   920:        if (sc->sc_aclwr_xfer != NULL) {
1.54      skrll     921:                usbd_destroy_xfer(sc->sc_aclwr_xfer);
1.5       dsainty   922:                sc->sc_aclwr_xfer = NULL;
                    923:                sc->sc_aclwr_buf = NULL;
                    924:        }
                    925:
1.14      gdamore   926:        for (i = 0 ; i < UBT_NXFERS ; i++) {
                    927:                if (sc->sc_scord[i].xfer != NULL) {
1.54      skrll     928:                        usbd_destroy_xfer(sc->sc_scord[i].xfer);
1.14      gdamore   929:                        sc->sc_scord[i].xfer = NULL;
                    930:                        sc->sc_scord[i].buf = NULL;
                    931:                }
1.1       augustss  932:
1.14      gdamore   933:                if (sc->sc_scowr[i].xfer != NULL) {
1.54      skrll     934:                        usbd_destroy_xfer(sc->sc_scowr[i].xfer);
1.14      gdamore   935:                        sc->sc_scowr[i].xfer = NULL;
                    936:                        sc->sc_scowr[i].buf = NULL;
                    937:                }
1.1       augustss  938:        }
                    939:
1.54      skrll     940:        if (sc->sc_evt_pipe != NULL) {
                    941:                usbd_close_pipe(sc->sc_evt_pipe);
                    942:                sc->sc_evt_pipe = NULL;
                    943:        }
                    944:
                    945:        if (sc->sc_aclrd_pipe != NULL) {
                    946:                usbd_close_pipe(sc->sc_aclrd_pipe);
                    947:                sc->sc_aclrd_pipe = NULL;
                    948:        }
                    949:
                    950:        if (sc->sc_aclwr_pipe != NULL) {
                    951:                usbd_close_pipe(sc->sc_aclwr_pipe);
                    952:                sc->sc_aclwr_pipe = NULL;
                    953:        }
                    954:
                    955:        if (sc->sc_scord_pipe != NULL) {
                    956:                usbd_close_pipe(sc->sc_scord_pipe);
                    957:                sc->sc_scord_pipe = NULL;
                    958:        }
                    959:
                    960:        if (sc->sc_scowr_pipe != NULL) {
                    961:                usbd_close_pipe(sc->sc_scowr_pipe);
                    962:                sc->sc_scowr_pipe = NULL;
                    963:        }
                    964:
1.14      gdamore   965:        /* Free partial SCO packets */
                    966:        if (sc->sc_scord_mbuf != NULL) {
                    967:                m_freem(sc->sc_scord_mbuf);
                    968:                sc->sc_scord_mbuf = NULL;
1.1       augustss  969:        }
                    970:
1.14      gdamore   971:        if (sc->sc_scowr_mbuf != NULL) {
                    972:                m_freem(sc->sc_scowr_mbuf);
                    973:                sc->sc_scowr_mbuf = NULL;
1.1       augustss  974:        }
1.29      plunky    975:
                    976:        /* Empty mbuf queues */
                    977:        MBUFQ_DRAIN(&sc->sc_cmd_queue);
                    978:        MBUFQ_DRAIN(&sc->sc_aclwr_queue);
                    979:        MBUFQ_DRAIN(&sc->sc_scowr_queue);
1.5       dsainty   980: }
                    981:
1.14      gdamore   982: /*******************************************************************************
                    983:  *
                    984:  * Bluetooth Unit/USB callbacks
                    985:  *
                    986:  */
1.5       dsainty   987: static int
1.39      dyoung    988: ubt_enable(device_t self)
1.5       dsainty   989: {
1.39      dyoung    990:        struct ubt_softc *sc = device_private(self);
1.5       dsainty   991:        usbd_status err;
1.29      plunky    992:        int s, i, error;
1.5       dsainty   993:
1.14      gdamore   994:        DPRINTFN(1, "sc=%p\n", sc);
1.5       dsainty   995:
1.29      plunky    996:        if (sc->sc_enabled)
1.14      gdamore   997:                return 0;
                    998:
1.29      plunky    999:        s = splusb();
                   1000:
1.14      gdamore  1001:        /* Events */
1.54      skrll    1002:        sc->sc_evt_buf = kmem_alloc(UBT_BUFSIZ_EVENT, KM_SLEEP);
1.14      gdamore  1003:        err = usbd_open_pipe_intr(sc->sc_iface0,
                   1004:                                  sc->sc_evt_addr,
                   1005:                                  USBD_SHORT_XFER_OK,
                   1006:                                  &sc->sc_evt_pipe,
                   1007:                                  sc,
                   1008:                                  sc->sc_evt_buf,
                   1009:                                  UBT_BUFSIZ_EVENT,
                   1010:                                  ubt_recv_event,
1.21      drochner 1011:                                  USBD_DEFAULT_INTERVAL);
1.5       dsainty  1012:        if (err != USBD_NORMAL_COMPLETION) {
                   1013:                error = EIO;
1.14      gdamore  1014:                goto bad;
1.5       dsainty  1015:        }
                   1016:
1.14      gdamore  1017:        /* Commands */
1.54      skrll    1018:        struct usbd_pipe *pipe0 = usbd_get_pipe0(sc->sc_udev);
1.60      skrll    1019:        error = usbd_create_xfer(pipe0, UBT_BUFSIZ_CMD, USBD_FORCE_SHORT_XFER,
                   1020:            0, &sc->sc_cmd_xfer);
1.54      skrll    1021:        if (error)
1.14      gdamore  1022:                goto bad;
1.54      skrll    1023:        sc->sc_cmd_buf = usbd_get_buffer(sc->sc_cmd_xfer);
1.29      plunky   1024:        sc->sc_cmd_busy = 0;
1.5       dsainty  1025:
1.14      gdamore  1026:        /* ACL read */
                   1027:        err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclrd_addr,
                   1028:                                USBD_EXCLUSIVE_USE, &sc->sc_aclrd_pipe);
1.5       dsainty  1029:        if (err != USBD_NORMAL_COMPLETION) {
                   1030:                error = EIO;
1.14      gdamore  1031:                goto bad;
1.5       dsainty  1032:        }
1.54      skrll    1033:        error = usbd_create_xfer(sc->sc_aclrd_pipe, UBT_BUFSIZ_ACL,
1.60      skrll    1034:            0, 0, &sc->sc_aclrd_xfer);
1.54      skrll    1035:        if (error)
1.14      gdamore  1036:                goto bad;
1.54      skrll    1037:        sc->sc_aclrd_buf = usbd_get_buffer(sc->sc_aclrd_xfer);
1.14      gdamore  1038:        sc->sc_aclrd_busy = 0;
                   1039:        ubt_recv_acl_start(sc);
1.5       dsainty  1040:
1.14      gdamore  1041:        /* ACL write */
                   1042:        err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclwr_addr,
                   1043:                                USBD_EXCLUSIVE_USE, &sc->sc_aclwr_pipe);
                   1044:        if (err != USBD_NORMAL_COMPLETION) {
                   1045:                error = EIO;
                   1046:                goto bad;
1.5       dsainty  1047:        }
1.54      skrll    1048:        error = usbd_create_xfer(sc->sc_aclwr_pipe, UBT_BUFSIZ_ACL,
                   1049:            USBD_FORCE_SHORT_XFER, 0, &sc->sc_aclwr_xfer);
                   1050:        if (error)
1.14      gdamore  1051:                goto bad;
1.54      skrll    1052:        sc->sc_aclwr_buf = usbd_get_buffer(sc->sc_aclwr_xfer);
1.29      plunky   1053:        sc->sc_aclwr_busy = 0;
1.14      gdamore  1054:
                   1055:        /* SCO read */
                   1056:        if (sc->sc_scord_size > 0) {
                   1057:                err = usbd_open_pipe(sc->sc_iface1, sc->sc_scord_addr,
                   1058:                                        USBD_EXCLUSIVE_USE, &sc->sc_scord_pipe);
                   1059:                if (err != USBD_NORMAL_COMPLETION) {
                   1060:                        error = EIO;
                   1061:                        goto bad;
                   1062:                }
                   1063:
                   1064:                for (i = 0 ; i < UBT_NXFERS ; i++) {
1.54      skrll    1065:                        error = usbd_create_xfer(sc->sc_scord_pipe,
                   1066:                            sc->sc_scord_size * UBT_NFRAMES,
1.60      skrll    1067:                            0, UBT_NFRAMES,
1.54      skrll    1068:                            &sc->sc_scord[i].xfer);
                   1069:                        if (error)
1.14      gdamore  1070:                                goto bad;
1.54      skrll    1071:
                   1072:                        sc->sc_scord[i].buf =
                   1073:                            usbd_get_buffer(sc->sc_scord[i].xfer);
1.14      gdamore  1074:                        sc->sc_scord[i].softc = sc;
                   1075:                        sc->sc_scord[i].busy = 0;
                   1076:                        ubt_recv_sco_start1(sc, &sc->sc_scord[i]);
                   1077:                }
1.5       dsainty  1078:        }
                   1079:
1.14      gdamore  1080:        /* SCO write */
                   1081:        if (sc->sc_scowr_size > 0) {
                   1082:                err = usbd_open_pipe(sc->sc_iface1, sc->sc_scowr_addr,
                   1083:                                        USBD_EXCLUSIVE_USE, &sc->sc_scowr_pipe);
                   1084:                if (err != USBD_NORMAL_COMPLETION) {
                   1085:                        error = EIO;
                   1086:                        goto bad;
                   1087:                }
                   1088:
                   1089:                for (i = 0 ; i < UBT_NXFERS ; i++) {
1.54      skrll    1090:                        error = usbd_create_xfer(sc->sc_scowr_pipe,
                   1091:                            sc->sc_scowr_size * UBT_NFRAMES,
                   1092:                            USBD_FORCE_SHORT_XFER, UBT_NFRAMES,
                   1093:                            &sc->sc_scowr[i].xfer);
                   1094:                        if (error)
1.14      gdamore  1095:                                goto bad;
1.54      skrll    1096:                        sc->sc_scowr[i].buf =
                   1097:                            usbd_get_buffer(sc->sc_scowr[i].xfer);
1.14      gdamore  1098:                        sc->sc_scowr[i].softc = sc;
                   1099:                        sc->sc_scowr[i].busy = 0;
                   1100:                }
1.29      plunky   1101:
                   1102:                sc->sc_scowr_busy = 0;
1.14      gdamore  1103:        }
1.5       dsainty  1104:
1.29      plunky   1105:        sc->sc_enabled = 1;
                   1106:        splx(s);
1.5       dsainty  1107:        return 0;
                   1108:
1.14      gdamore  1109: bad:
                   1110:        ubt_abortdealloc(sc);
1.29      plunky   1111:        splx(s);
1.5       dsainty  1112:        return error;
                   1113: }
                   1114:
1.14      gdamore  1115: static void
1.39      dyoung   1116: ubt_disable(device_t self)
1.5       dsainty  1117: {
1.39      dyoung   1118:        struct ubt_softc *sc = device_private(self);
1.29      plunky   1119:        int s;
1.14      gdamore  1120:
                   1121:        DPRINTFN(1, "sc=%p\n", sc);
1.5       dsainty  1122:
1.29      plunky   1123:        if (sc->sc_enabled == 0)
1.14      gdamore  1124:                return;
1.5       dsainty  1125:
1.29      plunky   1126:        s = splusb();
1.5       dsainty  1127:        ubt_abortdealloc(sc);
                   1128:
1.29      plunky   1129:        sc->sc_enabled = 0;
                   1130:        splx(s);
1.5       dsainty  1131: }
                   1132:
1.14      gdamore  1133: static void
1.39      dyoung   1134: ubt_xmit_cmd(device_t self, struct mbuf *m)
1.5       dsainty  1135: {
1.39      dyoung   1136:        struct ubt_softc *sc = device_private(self);
1.29      plunky   1137:        int s;
                   1138:
                   1139:        KASSERT(sc->sc_enabled);
                   1140:
                   1141:        s = splusb();
                   1142:        MBUFQ_ENQUEUE(&sc->sc_cmd_queue, m);
                   1143:
                   1144:        if (sc->sc_cmd_busy == 0)
                   1145:                ubt_xmit_cmd_start(sc);
                   1146:
                   1147:        splx(s);
                   1148: }
                   1149:
                   1150: static void
                   1151: ubt_xmit_cmd_start(struct ubt_softc *sc)
                   1152: {
1.5       dsainty  1153:        usb_device_request_t req;
                   1154:        usbd_status status;
1.14      gdamore  1155:        struct mbuf *m;
                   1156:        int len;
1.5       dsainty  1157:
1.14      gdamore  1158:        if (sc->sc_dying)
                   1159:                return;
1.5       dsainty  1160:
1.29      plunky   1161:        if (MBUFQ_FIRST(&sc->sc_cmd_queue) == NULL)
1.14      gdamore  1162:                return;
1.6       dsainty  1163:
1.29      plunky   1164:        MBUFQ_DEQUEUE(&sc->sc_cmd_queue, m);
1.14      gdamore  1165:        KASSERT(m != NULL);
1.5       dsainty  1166:
1.14      gdamore  1167:        DPRINTFN(15, "%s: xmit CMD packet (%d bytes)\n",
1.39      dyoung   1168:                        device_xname(sc->sc_dev), m->m_pkthdr.len);
1.5       dsainty  1169:
                   1170:        sc->sc_refcnt++;
1.29      plunky   1171:        sc->sc_cmd_busy = 1;
1.14      gdamore  1172:
                   1173:        len = m->m_pkthdr.len - 1;
                   1174:        m_copydata(m, 1, len, sc->sc_cmd_buf);
                   1175:        m_freem(m);
1.5       dsainty  1176:
                   1177:        memset(&req, 0, sizeof(req));
                   1178:        req.bmRequestType = UT_WRITE_CLASS_DEVICE;
                   1179:        USETW(req.wLength, len);
                   1180:
1.14      gdamore  1181:        usbd_setup_default_xfer(sc->sc_cmd_xfer,
1.5       dsainty  1182:                                sc->sc_udev,
1.27      plunky   1183:                                sc,
1.14      gdamore  1184:                                UBT_CMD_TIMEOUT,
                   1185:                                &req,
                   1186:                                sc->sc_cmd_buf,
                   1187:                                len,
1.54      skrll    1188:                                USBD_FORCE_SHORT_XFER,
1.14      gdamore  1189:                                ubt_xmit_cmd_complete);
                   1190:
                   1191:        status = usbd_transfer(sc->sc_cmd_xfer);
                   1192:
                   1193:        KASSERT(status != USBD_NORMAL_COMPLETION);
                   1194:
                   1195:        if (status != USBD_IN_PROGRESS) {
                   1196:                DPRINTF("usbd_transfer status=%s (%d)\n",
                   1197:                        usbd_errstr(status), status);
                   1198:
                   1199:                sc->sc_refcnt--;
1.29      plunky   1200:                sc->sc_cmd_busy = 0;
1.14      gdamore  1201:        }
                   1202: }
                   1203:
                   1204: static void
1.54      skrll    1205: ubt_xmit_cmd_complete(struct usbd_xfer *xfer,
                   1206:                        void * h, usbd_status status)
1.14      gdamore  1207: {
1.27      plunky   1208:        struct ubt_softc *sc = h;
1.14      gdamore  1209:        uint32_t count;
1.5       dsainty  1210:
1.14      gdamore  1211:        DPRINTFN(15, "%s: CMD complete status=%s (%d)\n",
1.39      dyoung   1212:                        device_xname(sc->sc_dev), usbd_errstr(status), status);
1.5       dsainty  1213:
1.29      plunky   1214:        sc->sc_cmd_busy = 0;
1.14      gdamore  1215:
                   1216:        if (--sc->sc_refcnt < 0) {
                   1217:                DPRINTF("sc_refcnt=%d\n", sc->sc_refcnt);
1.45      mrg      1218:                usb_detach_wakeupold(sc->sc_dev);
1.14      gdamore  1219:                return;
                   1220:        }
1.5       dsainty  1221:
1.14      gdamore  1222:        if (sc->sc_dying) {
                   1223:                DPRINTF("sc_dying\n");
                   1224:                return;
                   1225:        }
1.5       dsainty  1226:
1.14      gdamore  1227:        if (status != USBD_NORMAL_COMPLETION) {
                   1228:                DPRINTF("status=%s (%d)\n",
                   1229:                        usbd_errstr(status), status);
1.5       dsainty  1230:
1.29      plunky   1231:                sc->sc_stats.err_tx++;
1.14      gdamore  1232:                return;
                   1233:        }
1.6       dsainty  1234:
1.14      gdamore  1235:        usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1.29      plunky   1236:        sc->sc_stats.cmd_tx++;
                   1237:        sc->sc_stats.byte_tx += count;
1.6       dsainty  1238:
1.29      plunky   1239:        ubt_xmit_cmd_start(sc);
1.6       dsainty  1240: }
                   1241:
1.14      gdamore  1242: static void
1.39      dyoung   1243: ubt_xmit_acl(device_t self, struct mbuf *m)
1.5       dsainty  1244: {
1.39      dyoung   1245:        struct ubt_softc *sc = device_private(self);
1.29      plunky   1246:        int s;
                   1247:
                   1248:        KASSERT(sc->sc_enabled);
                   1249:
                   1250:        s = splusb();
                   1251:        MBUFQ_ENQUEUE(&sc->sc_aclwr_queue, m);
                   1252:
                   1253:        if (sc->sc_aclwr_busy == 0)
                   1254:                ubt_xmit_acl_start(sc);
                   1255:
                   1256:        splx(s);
                   1257: }
                   1258:
                   1259: static void
                   1260: ubt_xmit_acl_start(struct ubt_softc *sc)
                   1261: {
1.14      gdamore  1262:        struct mbuf *m;
1.5       dsainty  1263:        usbd_status status;
1.14      gdamore  1264:        int len;
                   1265:
                   1266:        if (sc->sc_dying)
                   1267:                return;
                   1268:
1.29      plunky   1269:        if (MBUFQ_FIRST(&sc->sc_aclwr_queue) == NULL)
1.14      gdamore  1270:                return;
1.5       dsainty  1271:
1.14      gdamore  1272:        sc->sc_refcnt++;
1.29      plunky   1273:        sc->sc_aclwr_busy = 1;
1.14      gdamore  1274:
1.29      plunky   1275:        MBUFQ_DEQUEUE(&sc->sc_aclwr_queue, m);
1.14      gdamore  1276:        KASSERT(m != NULL);
1.5       dsainty  1277:
1.14      gdamore  1278:        DPRINTFN(15, "%s: xmit ACL packet (%d bytes)\n",
1.39      dyoung   1279:                        device_xname(sc->sc_dev), m->m_pkthdr.len);
1.14      gdamore  1280:
                   1281:        len = m->m_pkthdr.len - 1;
                   1282:        if (len > UBT_BUFSIZ_ACL) {
                   1283:                DPRINTF("%s: truncating ACL packet (%d => %d)!\n",
1.39      dyoung   1284:                        device_xname(sc->sc_dev), len, UBT_BUFSIZ_ACL);
1.6       dsainty  1285:
1.14      gdamore  1286:                len = UBT_BUFSIZ_ACL;
                   1287:        }
1.5       dsainty  1288:
1.14      gdamore  1289:        m_copydata(m, 1, len, sc->sc_aclwr_buf);
                   1290:        m_freem(m);
1.5       dsainty  1291:
1.29      plunky   1292:        sc->sc_stats.acl_tx++;
                   1293:        sc->sc_stats.byte_tx += len;
1.5       dsainty  1294:
                   1295:        usbd_setup_xfer(sc->sc_aclwr_xfer,
1.27      plunky   1296:                        sc,
1.14      gdamore  1297:                        sc->sc_aclwr_buf,
                   1298:                        len,
1.54      skrll    1299:                        USBD_FORCE_SHORT_XFER,
1.14      gdamore  1300:                        UBT_ACL_TIMEOUT,
                   1301:                        ubt_xmit_acl_complete);
1.5       dsainty  1302:
                   1303:        status = usbd_transfer(sc->sc_aclwr_xfer);
                   1304:
1.14      gdamore  1305:        KASSERT(status != USBD_NORMAL_COMPLETION);
                   1306:
                   1307:        if (status != USBD_IN_PROGRESS) {
                   1308:                DPRINTF("usbd_transfer status=%s (%d)\n",
                   1309:                        usbd_errstr(status), status);
                   1310:
                   1311:                sc->sc_refcnt--;
1.29      plunky   1312:                sc->sc_aclwr_busy = 0;
1.14      gdamore  1313:        }
                   1314: }
                   1315:
                   1316: static void
1.54      skrll    1317: ubt_xmit_acl_complete(struct usbd_xfer *xfer,
                   1318:                void * h, usbd_status status)
1.14      gdamore  1319: {
1.27      plunky   1320:        struct ubt_softc *sc = h;
1.14      gdamore  1321:
                   1322:        DPRINTFN(15, "%s: ACL complete status=%s (%d)\n",
1.39      dyoung   1323:                device_xname(sc->sc_dev), usbd_errstr(status), status);
1.14      gdamore  1324:
1.29      plunky   1325:        sc->sc_aclwr_busy = 0;
1.14      gdamore  1326:
                   1327:        if (--sc->sc_refcnt < 0) {
1.45      mrg      1328:                usb_detach_wakeupold(sc->sc_dev);
1.14      gdamore  1329:                return;
                   1330:        }
1.5       dsainty  1331:
1.14      gdamore  1332:        if (sc->sc_dying)
                   1333:                return;
1.5       dsainty  1334:
1.14      gdamore  1335:        if (status != USBD_NORMAL_COMPLETION) {
                   1336:                DPRINTF("status=%s (%d)\n",
                   1337:                        usbd_errstr(status), status);
                   1338:
1.29      plunky   1339:                sc->sc_stats.err_tx++;
1.14      gdamore  1340:
                   1341:                if (status == USBD_STALLED)
                   1342:                        usbd_clear_endpoint_stall_async(sc->sc_aclwr_pipe);
                   1343:                else
                   1344:                        return;
                   1345:        }
                   1346:
1.29      plunky   1347:        ubt_xmit_acl_start(sc);
1.14      gdamore  1348: }
                   1349:
                   1350: static void
1.39      dyoung   1351: ubt_xmit_sco(device_t self, struct mbuf *m)
1.14      gdamore  1352: {
1.39      dyoung   1353:        struct ubt_softc *sc = device_private(self);
1.29      plunky   1354:        int s;
                   1355:
                   1356:        KASSERT(sc->sc_enabled);
                   1357:
                   1358:        s = splusb();
                   1359:        MBUFQ_ENQUEUE(&sc->sc_scowr_queue, m);
                   1360:
                   1361:        if (sc->sc_scowr_busy == 0)
                   1362:                ubt_xmit_sco_start(sc);
                   1363:
                   1364:        splx(s);
                   1365: }
                   1366:
                   1367: static void
                   1368: ubt_xmit_sco_start(struct ubt_softc *sc)
                   1369: {
1.14      gdamore  1370:        int i;
                   1371:
                   1372:        if (sc->sc_dying || sc->sc_scowr_size == 0)
                   1373:                return;
                   1374:
                   1375:        for (i = 0 ; i < UBT_NXFERS ; i++) {
                   1376:                if (sc->sc_scowr[i].busy)
                   1377:                        continue;
                   1378:
                   1379:                ubt_xmit_sco_start1(sc, &sc->sc_scowr[i]);
                   1380:        }
1.5       dsainty  1381: }
                   1382:
1.14      gdamore  1383: static void
                   1384: ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
1.6       dsainty  1385: {
1.14      gdamore  1386:        struct mbuf *m;
                   1387:        uint8_t *buf;
                   1388:        int num, len, size, space;
                   1389:
                   1390:        space = sc->sc_scowr_size * UBT_NFRAMES;
                   1391:        buf = isoc->buf;
                   1392:        len = 0;
                   1393:
                   1394:        /*
                   1395:         * Fill the request buffer with data from the queue,
                   1396:         * keeping any leftover packet on our private hook.
                   1397:         *
                   1398:         * Complete packets are passed back up to the stack
                   1399:         * for disposal, since we can't rely on the controller
                   1400:         * to tell us when it has finished with them.
                   1401:         */
                   1402:
                   1403:        m = sc->sc_scowr_mbuf;
                   1404:        while (space > 0) {
                   1405:                if (m == NULL) {
1.29      plunky   1406:                        MBUFQ_DEQUEUE(&sc->sc_scowr_queue, m);
1.14      gdamore  1407:                        if (m == NULL)
                   1408:                                break;
                   1409:
                   1410:                        m_adj(m, 1);    /* packet type */
                   1411:                }
                   1412:
                   1413:                if (m->m_pkthdr.len > 0) {
                   1414:                        size = MIN(m->m_pkthdr.len, space);
                   1415:
                   1416:                        m_copydata(m, 0, size, buf);
                   1417:                        m_adj(m, size);
                   1418:
                   1419:                        buf += size;
                   1420:                        len += size;
                   1421:                        space -= size;
                   1422:                }
                   1423:
                   1424:                if (m->m_pkthdr.len == 0) {
1.29      plunky   1425:                        sc->sc_stats.sco_tx++;
                   1426:                        if (!hci_complete_sco(sc->sc_unit, m))
                   1427:                                sc->sc_stats.err_tx++;
                   1428:
1.14      gdamore  1429:                        m = NULL;
                   1430:                }
                   1431:        }
                   1432:        sc->sc_scowr_mbuf = m;
                   1433:
                   1434:        DPRINTFN(15, "isoc=%p, len=%d, space=%d\n", isoc, len, space);
                   1435:
                   1436:        if (len == 0)   /* nothing to send */
                   1437:                return;
                   1438:
                   1439:        sc->sc_refcnt++;
1.29      plunky   1440:        sc->sc_scowr_busy = 1;
                   1441:        sc->sc_stats.byte_tx += len;
1.14      gdamore  1442:        isoc->busy = 1;
                   1443:
                   1444:        /*
                   1445:         * calculate number of isoc frames and sizes
                   1446:         */
                   1447:
                   1448:        for (num = 0 ; len > 0 ; num++) {
                   1449:                size = MIN(sc->sc_scowr_size, len);
                   1450:
                   1451:                isoc->size[num] = size;
                   1452:                len -= size;
                   1453:        }
                   1454:
                   1455:        usbd_setup_isoc_xfer(isoc->xfer,
                   1456:                             isoc,
                   1457:                             isoc->size,
                   1458:                             num,
1.54      skrll    1459:                             USBD_FORCE_SHORT_XFER,
1.14      gdamore  1460:                             ubt_xmit_sco_complete);
                   1461:
                   1462:        usbd_transfer(isoc->xfer);
1.6       dsainty  1463: }
                   1464:
1.14      gdamore  1465: static void
1.54      skrll    1466: ubt_xmit_sco_complete(struct usbd_xfer *xfer,
                   1467:                void * h, usbd_status status)
1.5       dsainty  1468: {
1.14      gdamore  1469:        struct ubt_isoc_xfer *isoc = h;
                   1470:        struct ubt_softc *sc;
                   1471:        int i;
                   1472:
                   1473:        KASSERT(xfer == isoc->xfer);
                   1474:        sc = isoc->softc;
                   1475:
                   1476:        DPRINTFN(15, "isoc=%p, status=%s (%d)\n",
                   1477:                isoc, usbd_errstr(status), status);
                   1478:
                   1479:        isoc->busy = 0;
                   1480:
                   1481:        for (i = 0 ; ; i++) {
                   1482:                if (i == UBT_NXFERS) {
1.29      plunky   1483:                        sc->sc_scowr_busy = 0;
1.14      gdamore  1484:                        break;
                   1485:                }
1.5       dsainty  1486:
1.14      gdamore  1487:                if (sc->sc_scowr[i].busy)
                   1488:                        break;
                   1489:        }
                   1490:
                   1491:        if (--sc->sc_refcnt < 0) {
1.45      mrg      1492:                usb_detach_wakeupold(sc->sc_dev);
1.14      gdamore  1493:                return;
                   1494:        }
1.5       dsainty  1495:
                   1496:        if (sc->sc_dying)
1.14      gdamore  1497:                return;
1.5       dsainty  1498:
1.14      gdamore  1499:        if (status != USBD_NORMAL_COMPLETION) {
                   1500:                DPRINTF("status=%s (%d)\n",
                   1501:                        usbd_errstr(status), status);
                   1502:
1.29      plunky   1503:                sc->sc_stats.err_tx++;
1.14      gdamore  1504:
                   1505:                if (status == USBD_STALLED)
                   1506:                        usbd_clear_endpoint_stall_async(sc->sc_scowr_pipe);
                   1507:                else
                   1508:                        return;
                   1509:        }
                   1510:
1.29      plunky   1511:        ubt_xmit_sco_start(sc);
1.14      gdamore  1512: }
                   1513:
                   1514: /*
                   1515:  * load incoming data into an mbuf with
                   1516:  * leading type byte
                   1517:  */
                   1518: static struct mbuf *
                   1519: ubt_mbufload(uint8_t *buf, int count, uint8_t type)
                   1520: {
                   1521:        struct mbuf *m;
                   1522:
                   1523:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1524:        if (m == NULL)
                   1525:                return NULL;
                   1526:
                   1527:        *mtod(m, uint8_t *) = type;
                   1528:        m->m_pkthdr.len = m->m_len = MHLEN;
                   1529:        m_copyback(m, 1, count, buf);   // (extends if necessary)
                   1530:        if (m->m_pkthdr.len != MAX(MHLEN, count + 1)) {
1.61      maxv     1531:                m_freem(m);
1.14      gdamore  1532:                return NULL;
                   1533:        }
                   1534:
                   1535:        m->m_pkthdr.len = count + 1;
                   1536:        m->m_len = MIN(MHLEN, m->m_pkthdr.len);
                   1537:
                   1538:        return m;
1.5       dsainty  1539: }
                   1540:
                   1541: static void
1.54      skrll    1542: ubt_recv_event(struct usbd_xfer *xfer, void * h, usbd_status status)
1.5       dsainty  1543: {
                   1544:        struct ubt_softc *sc = h;
1.14      gdamore  1545:        struct mbuf *m;
                   1546:        uint32_t count;
1.5       dsainty  1547:        void *buf;
                   1548:
1.14      gdamore  1549:        DPRINTFN(15, "sc=%p status=%s (%d)\n",
                   1550:                    sc, usbd_errstr(status), status);
1.5       dsainty  1551:
1.14      gdamore  1552:        if (status != USBD_NORMAL_COMPLETION || sc->sc_dying)
1.5       dsainty  1553:                return;
                   1554:
1.14      gdamore  1555:        usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL);
                   1556:
1.16      plunky   1557:        if (count < sizeof(hci_event_hdr_t) - 1) {
                   1558:                DPRINTF("dumped undersized event (count = %d)\n", count);
1.29      plunky   1559:                sc->sc_stats.err_rx++;
1.16      plunky   1560:                return;
                   1561:        }
                   1562:
1.29      plunky   1563:        sc->sc_stats.evt_rx++;
                   1564:        sc->sc_stats.byte_rx += count;
1.5       dsainty  1565:
1.14      gdamore  1566:        m = ubt_mbufload(buf, count, HCI_EVENT_PKT);
1.29      plunky   1567:        if (m == NULL || !hci_input_event(sc->sc_unit, m))
                   1568:                sc->sc_stats.err_rx++;
1.5       dsainty  1569: }
                   1570:
                   1571: static void
1.14      gdamore  1572: ubt_recv_acl_start(struct ubt_softc *sc)
1.5       dsainty  1573: {
                   1574:        usbd_status status;
                   1575:
1.14      gdamore  1576:        DPRINTFN(15, "sc=%p\n", sc);
1.5       dsainty  1577:
1.14      gdamore  1578:        if (sc->sc_aclrd_busy || sc->sc_dying) {
                   1579:                DPRINTF("sc_aclrd_busy=%d, sc_dying=%d\n",
                   1580:                        sc->sc_aclrd_busy,
                   1581:                        sc->sc_dying);
1.5       dsainty  1582:
                   1583:                return;
                   1584:        }
1.6       dsainty  1585:
1.14      gdamore  1586:        sc->sc_refcnt++;
                   1587:        sc->sc_aclrd_busy = 1;
                   1588:
                   1589:        usbd_setup_xfer(sc->sc_aclrd_xfer,
                   1590:                        sc,
                   1591:                        sc->sc_aclrd_buf,
                   1592:                        UBT_BUFSIZ_ACL,
1.54      skrll    1593:                        USBD_SHORT_XFER_OK,
1.14      gdamore  1594:                        USBD_NO_TIMEOUT,
                   1595:                        ubt_recv_acl_complete);
1.5       dsainty  1596:
                   1597:        status = usbd_transfer(sc->sc_aclrd_xfer);
1.9       dsainty  1598:
1.14      gdamore  1599:        KASSERT(status != USBD_NORMAL_COMPLETION);
1.5       dsainty  1600:
1.14      gdamore  1601:        if (status != USBD_IN_PROGRESS) {
                   1602:                DPRINTF("usbd_transfer status=%s (%d)\n",
                   1603:                        usbd_errstr(status), status);
1.5       dsainty  1604:
1.14      gdamore  1605:                sc->sc_refcnt--;
                   1606:                sc->sc_aclrd_busy = 0;
                   1607:        }
1.5       dsainty  1608: }
                   1609:
                   1610: static void
1.54      skrll    1611: ubt_recv_acl_complete(struct usbd_xfer *xfer,
                   1612:                void * h, usbd_status status)
1.5       dsainty  1613: {
                   1614:        struct ubt_softc *sc = h;
1.14      gdamore  1615:        struct mbuf *m;
                   1616:        uint32_t count;
1.5       dsainty  1617:        void *buf;
                   1618:
1.14      gdamore  1619:        DPRINTFN(15, "sc=%p status=%s (%d)\n",
                   1620:                        sc, usbd_errstr(status), status);
                   1621:
                   1622:        sc->sc_aclrd_busy = 0;
                   1623:
                   1624:        if (--sc->sc_refcnt < 0) {
                   1625:                DPRINTF("refcnt = %d\n", sc->sc_refcnt);
1.45      mrg      1626:                usb_detach_wakeupold(sc->sc_dev);
1.14      gdamore  1627:                return;
                   1628:        }
                   1629:
                   1630:        if (sc->sc_dying) {
                   1631:                DPRINTF("sc_dying\n");
                   1632:                return;
                   1633:        }
                   1634:
                   1635:        if (status != USBD_NORMAL_COMPLETION) {
                   1636:                DPRINTF("status=%s (%d)\n",
                   1637:                        usbd_errstr(status), status);
                   1638:
1.29      plunky   1639:                sc->sc_stats.err_rx++;
1.14      gdamore  1640:
                   1641:                if (status == USBD_STALLED)
                   1642:                        usbd_clear_endpoint_stall_async(sc->sc_aclrd_pipe);
                   1643:                else
                   1644:                        return;
                   1645:        } else {
                   1646:                usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL);
                   1647:
1.16      plunky   1648:                if (count < sizeof(hci_acldata_hdr_t) - 1) {
                   1649:                        DPRINTF("dumped undersized packet (%d)\n", count);
1.29      plunky   1650:                        sc->sc_stats.err_rx++;
1.16      plunky   1651:                } else {
1.29      plunky   1652:                        sc->sc_stats.acl_rx++;
                   1653:                        sc->sc_stats.byte_rx += count;
1.14      gdamore  1654:
1.16      plunky   1655:                        m = ubt_mbufload(buf, count, HCI_ACL_DATA_PKT);
1.29      plunky   1656:                        if (m == NULL || !hci_input_acl(sc->sc_unit, m))
                   1657:                                sc->sc_stats.err_rx++;
1.16      plunky   1658:                }
1.14      gdamore  1659:        }
1.5       dsainty  1660:
1.14      gdamore  1661:        /* and restart */
                   1662:        ubt_recv_acl_start(sc);
                   1663: }
                   1664:
                   1665: static void
                   1666: ubt_recv_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
                   1667: {
                   1668:        int i;
                   1669:
                   1670:        DPRINTFN(15, "sc=%p, isoc=%p\n", sc, isoc);
                   1671:
                   1672:        if (isoc->busy || sc->sc_dying || sc->sc_scord_size == 0) {
                   1673:                DPRINTF("%s%s%s\n",
                   1674:                        isoc->busy ? " busy" : "",
                   1675:                        sc->sc_dying ? " dying" : "",
                   1676:                        sc->sc_scord_size == 0 ? " size=0" : "");
1.5       dsainty  1677:
                   1678:                return;
1.14      gdamore  1679:        }
                   1680:
                   1681:        sc->sc_refcnt++;
                   1682:        isoc->busy = 1;
1.5       dsainty  1683:
1.14      gdamore  1684:        for (i = 0 ; i < UBT_NFRAMES ; i++)
                   1685:                isoc->size[i] = sc->sc_scord_size;
1.5       dsainty  1686:
1.14      gdamore  1687:        usbd_setup_isoc_xfer(isoc->xfer,
                   1688:                             isoc,
                   1689:                             isoc->size,
                   1690:                             UBT_NFRAMES,
1.54      skrll    1691:                             USBD_SHORT_XFER_OK,
1.14      gdamore  1692:                             ubt_recv_sco_complete);
1.5       dsainty  1693:
1.14      gdamore  1694:        usbd_transfer(isoc->xfer);
1.5       dsainty  1695: }
                   1696:
1.14      gdamore  1697: static void
1.54      skrll    1698: ubt_recv_sco_complete(struct usbd_xfer *xfer,
                   1699:                void * h, usbd_status status)
1.5       dsainty  1700: {
1.14      gdamore  1701:        struct ubt_isoc_xfer *isoc = h;
                   1702:        struct ubt_softc *sc;
                   1703:        struct mbuf *m;
                   1704:        uint32_t count;
                   1705:        uint8_t *ptr, *frame;
                   1706:        int i, size, got, want;
                   1707:
                   1708:        KASSERT(isoc != NULL);
                   1709:        KASSERT(isoc->xfer == xfer);
                   1710:
                   1711:        sc = isoc->softc;
                   1712:        isoc->busy = 0;
                   1713:
                   1714:        if (--sc->sc_refcnt < 0) {
                   1715:                DPRINTF("refcnt=%d\n", sc->sc_refcnt);
1.45      mrg      1716:                usb_detach_wakeupold(sc->sc_dev);
1.14      gdamore  1717:                return;
                   1718:        }
                   1719:
                   1720:        if (sc->sc_dying) {
                   1721:                DPRINTF("sc_dying\n");
                   1722:                return;
                   1723:        }
                   1724:
                   1725:        if (status != USBD_NORMAL_COMPLETION) {
                   1726:                DPRINTF("status=%s (%d)\n",
                   1727:                        usbd_errstr(status), status);
                   1728:
1.29      plunky   1729:                sc->sc_stats.err_rx++;
1.14      gdamore  1730:
                   1731:                if (status == USBD_STALLED) {
                   1732:                        usbd_clear_endpoint_stall_async(sc->sc_scord_pipe);
                   1733:                        goto restart;
                   1734:                }
                   1735:
                   1736:                return;
                   1737:        }
                   1738:
                   1739:        usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
                   1740:        if (count == 0)
                   1741:                goto restart;
                   1742:
                   1743:        DPRINTFN(15, "sc=%p, isoc=%p, count=%u\n",
                   1744:                        sc, isoc, count);
                   1745:
1.29      plunky   1746:        sc->sc_stats.byte_rx += count;
1.14      gdamore  1747:
                   1748:        /*
                   1749:         * Extract SCO packets from ISOC frames. The way we have it,
                   1750:         * no SCO packet can be bigger than MHLEN. This is unlikely
                   1751:         * to actually happen, but if we ran out of mbufs and lost
                   1752:         * sync then we may get spurious data that makes it seem that
                   1753:         * way, so we discard data that wont fit. This doesnt really
                   1754:         * help with the lost sync situation alas.
                   1755:         */
                   1756:
                   1757:        m = sc->sc_scord_mbuf;
                   1758:        if (m != NULL) {
                   1759:                sc->sc_scord_mbuf = NULL;
                   1760:                ptr = mtod(m, uint8_t *) + m->m_pkthdr.len;
                   1761:                got = m->m_pkthdr.len;
                   1762:                want = sizeof(hci_scodata_hdr_t);
                   1763:                if (got >= want)
                   1764:                        want += mtod(m, hci_scodata_hdr_t *)->length ;
                   1765:        } else {
                   1766:                ptr = NULL;
                   1767:                got = 0;
                   1768:                want = 0;
                   1769:        }
                   1770:
                   1771:        for (i = 0 ; i < UBT_NFRAMES ; i++) {
                   1772:                frame = isoc->buf + (i * sc->sc_scord_size);
                   1773:
                   1774:                while (isoc->size[i] > 0) {
                   1775:                        size = isoc->size[i];
                   1776:
                   1777:                        if (m == NULL) {
                   1778:                                MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1779:                                if (m == NULL) {
1.32      cube     1780:                                        aprint_error_dev(sc->sc_dev,
                   1781:                                            "out of memory (xfer halted)\n");
1.14      gdamore  1782:
1.29      plunky   1783:                                        sc->sc_stats.err_rx++;
1.14      gdamore  1784:                                        return;         /* lost sync */
                   1785:                                }
                   1786:
                   1787:                                ptr = mtod(m, uint8_t *);
                   1788:                                *ptr++ = HCI_SCO_DATA_PKT;
                   1789:                                got = 1;
                   1790:                                want = sizeof(hci_scodata_hdr_t);
                   1791:                        }
                   1792:
                   1793:                        if (got + size > want)
                   1794:                                size = want - got;
                   1795:
1.47      christos 1796:                        memcpy(ptr, frame, size);
1.14      gdamore  1797:
                   1798:                        ptr += size;
                   1799:                        got += size;
                   1800:                        frame += size;
                   1801:
                   1802:                        if (got == want) {
                   1803:                                /*
                   1804:                                 * If we only got a header, add the packet
                   1805:                                 * length to our want count. Send complete
                   1806:                                 * packets up to protocol stack.
                   1807:                                 */
1.47      christos 1808:                                if (want == sizeof(hci_scodata_hdr_t)) {
                   1809:                                        uint32_t len =
                   1810:                                            mtod(m, hci_scodata_hdr_t *)->length;
                   1811:                                        want += len;
                   1812:                                        if (len == 0 || want > MHLEN) {
                   1813:                                                aprint_error_dev(sc->sc_dev,
                   1814:                                                    "packet too large %u "
                   1815:                                                    "(lost sync)\n", len);
                   1816:                                                sc->sc_stats.err_rx++;
                   1817:                                                return;
                   1818:                                        }
                   1819:                                }
1.14      gdamore  1820:
                   1821:                                if (got == want) {
                   1822:                                        m->m_pkthdr.len = m->m_len = got;
1.29      plunky   1823:                                        sc->sc_stats.sco_rx++;
                   1824:                                        if (!hci_input_sco(sc->sc_unit, m))
                   1825:                                                sc->sc_stats.err_rx++;
1.54      skrll    1826:
1.14      gdamore  1827:                                        m = NULL;
                   1828:                                }
                   1829:                        }
                   1830:
                   1831:                        isoc->size[i] -= size;
                   1832:                }
                   1833:        }
                   1834:
                   1835:        if (m != NULL) {
                   1836:                m->m_pkthdr.len = m->m_len = got;
                   1837:                sc->sc_scord_mbuf = m;
                   1838:        }
                   1839:
                   1840: restart: /* and restart */
                   1841:        ubt_recv_sco_start1(sc, isoc);
1.1       augustss 1842: }
1.29      plunky   1843:
                   1844: void
1.39      dyoung   1845: ubt_stats(device_t self, struct bt_stats *dest, int flush)
1.29      plunky   1846: {
1.39      dyoung   1847:        struct ubt_softc *sc = device_private(self);
1.29      plunky   1848:        int s;
                   1849:
                   1850:        s = splusb();
                   1851:        memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
                   1852:
                   1853:        if (flush)
                   1854:                memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
                   1855:
                   1856:        splx(s);
                   1857: }

CVSweb <webmaster@jp.NetBSD.org>