The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/ubt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ubt.c,v 1.10 2004/01/04 05:47:43 dsainty Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Lennart Augustsson (lennart@augustsson.net) and
    9  * David Sainty (David.Sainty@dtsp.co.nz).
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *        This product includes software developed by the NetBSD
   22  *        Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 #include <sys/cdefs.h>
   41 __KERNEL_RCSID(0, "$NetBSD: ubt.c,v 1.10 2004/01/04 05:47:43 dsainty Exp $");
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/kernel.h>
   46 #include <sys/malloc.h>
   47 #include <sys/device.h>
   48 #include <sys/lock.h>
   49 #include <sys/ioctl.h>
   50 #include <sys/conf.h>
   51 #include <sys/file.h>
   52 #include <sys/poll.h>
   53 #include <sys/select.h>
   54 #include <sys/proc.h>
   55 
   56 #include <dev/usb/ubtreg.h>
   57 #include <dev/usb/usb.h>
   58 #include <dev/usb/usbdi.h>
   59 #include <dev/usb/usbdi_util.h>
   60 #include <dev/usb/usbdevs.h>
   61 
   62 #include <dev/bluetooth/bluetooth.h>
   63 
   64 #ifdef UBT_DEBUG
   65 #define DPRINTF(x)      if (ubtdebug) logprintf x
   66 #define DPRINTFN(n,x)   if (ubtdebug>(n)) logprintf x
   67 int     ubtdebug = 49;
   68 #else
   69 #define DPRINTF(x)
   70 #define DPRINTFN(n,x)
   71 #endif
   72 
   73 /*
   74  * Protocol related definitions
   75  */
   76 
   77 struct ubt_softc {
   78         USBBASEDEVICE           sc_dev;
   79         usbd_device_handle      sc_udev;
   80         usbd_interface_handle   sc_ctl_iface;
   81         usbd_interface_handle   sc_isoc_iface;
   82 
   83         /* Control */
   84         usbd_pipe_handle        sc_ctl_pipe;
   85         usbd_xfer_handle        sc_ctl_xfer;
   86         u_int8_t                *sc_ctl_buf;
   87 
   88         /* Events */
   89         int                     sc_evt_addr;
   90         usbd_pipe_handle        sc_evt_pipe;
   91         usbd_xfer_handle        sc_evt_xfer;
   92         u_int8_t                *sc_evt_buf;
   93 
   94         /* ACL data (in) */
   95         int                     sc_aclrd_addr;
   96         usbd_pipe_handle        sc_aclrd_pipe;
   97         usbd_xfer_handle        sc_aclrd_xfer;
   98         u_int8_t                *sc_aclrd_buf;
   99         int                     sc_aclrd_running;
  100 
  101         /* ACL data (out) */
  102         int                     sc_aclwr_addr;
  103         usbd_pipe_handle        sc_aclwr_pipe;
  104         usbd_xfer_handle        sc_aclwr_xfer;
  105         u_int8_t                *sc_aclwr_buf;
  106 
  107         struct device           *sc_child;
  108         struct btframe_callback_methods const *sc_cb;
  109 
  110         int                     sc_refcnt;
  111         char                    sc_dying;
  112 };
  113 
  114 static int ubt_open(void *h, int flag, int mode, usb_proc_ptr p);
  115 static int ubt_close(void *h, int flag, int mode, usb_proc_ptr p);
  116 
  117 static u_int8_t* ubt_alloc_control(void*, size_t, struct btframe_buffer**);
  118 static int ubt_send_control(void*, struct btframe_buffer*, size_t);
  119 
  120 static u_int8_t* ubt_alloc_acldata(void*, size_t, struct btframe_buffer**);
  121 static int ubt_send_acldata(void*, struct btframe_buffer*, size_t);
  122 
  123 static u_int8_t* ubt_alloc_scodata(void*, size_t, struct btframe_buffer**);
  124 static int ubt_send_scodata(void*, struct btframe_buffer*, size_t);
  125 
  126 static int ubt_splraise(void);
  127 
  128 static void ubt_event_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
  129 static void ubt_aclrd_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
  130 static void ubt_aclrd_request(struct ubt_softc *);
  131 
  132 static struct btframe_methods const ubt_methods = {
  133         ubt_open, ubt_close,
  134         {ubt_alloc_control, ubt_send_control},
  135         {ubt_alloc_acldata, ubt_send_acldata},
  136         {ubt_alloc_scodata, ubt_send_scodata},
  137         ubt_splraise
  138 };
  139 
  140 USB_DECLARE_DRIVER(ubt);
  141 
  142 USB_MATCH(ubt)
  143 {
  144         USB_MATCH_START(ubt, uaa);
  145         usb_interface_descriptor_t *id;
  146 
  147         DPRINTFN(50,("ubt_match\n"));
  148 
  149         if (uaa->iface == NULL)
  150                 return (UMATCH_NONE);
  151 
  152         id = usbd_get_interface_descriptor(uaa->iface);
  153         if (id != NULL &&
  154             id->bInterfaceClass == UICLASS_WIRELESS &&
  155             id->bInterfaceSubClass == UISUBCLASS_RF &&
  156             id->bInterfaceProtocol == UIPROTO_BLUETOOTH)
  157                 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
  158         return (UMATCH_NONE);
  159 }
  160 
  161 USB_ATTACH(ubt)
  162 {
  163         USB_ATTACH_START(ubt, sc, uaa);
  164         usbd_device_handle      dev = uaa->device;
  165         usbd_interface_handle   iface = uaa->iface;
  166         struct bt_attach_args   bt;
  167         usb_interface_descriptor_t const *id;
  168         char                    devinfo[1024];
  169         usb_endpoint_descriptor_t const *ed;
  170         u_int8_t                epcount;
  171         int                     i;
  172 
  173         DPRINTFN(10,("ubt_attach: sc=%p\n", sc));
  174 
  175         usbd_devinfo(dev, 0, devinfo);
  176         USB_ATTACH_SETUP;
  177         printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
  178 
  179         sc->sc_udev = dev;
  180         sc->sc_ctl_iface = iface;
  181 
  182         /*
  183          * The control interface comes before the isoc interface
  184          * according to the spec, so we find it first.
  185          */
  186         epcount = 0;
  187         (void)usbd_endpoint_count(iface, &epcount);
  188 
  189         sc->sc_evt_addr = -1;
  190         sc->sc_aclrd_addr = -1;
  191         sc->sc_aclwr_addr = -1;
  192 
  193         for (i = 0; i < epcount; i++) {
  194                 ed = usbd_interface2endpoint_descriptor(iface, i);
  195                 if (ed == NULL) {
  196                         printf("%s: couldn't get ep %d\n",
  197                             USBDEVNAME(sc->sc_dev), i);
  198                         USB_ATTACH_ERROR_RETURN;
  199                 }
  200 
  201                 DPRINTFN(10, ("%s: addr=%d attr=%d\n", __func__,
  202                               (int)ed->bEndpointAddress,
  203                               (int)ed->bmAttributes));
  204 
  205                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  206                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
  207                         sc->sc_evt_addr = ed->bEndpointAddress;
  208                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  209                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  210                         sc->sc_aclrd_addr = ed->bEndpointAddress;
  211                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  212                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  213                         sc->sc_aclwr_addr = ed->bEndpointAddress;
  214                 }
  215         }
  216 
  217         if (sc->sc_evt_addr == -1 ||
  218             sc->sc_aclrd_addr == -1 || sc->sc_aclwr_addr == -1) {
  219                 printf("%s: missing endpoint\n", USBDEVNAME(sc->sc_dev));
  220                 USB_ATTACH_ERROR_RETURN;
  221         }
  222 
  223         /* XXX works because isoc comes after ctl */
  224         /* Grab isoc interface as well. */
  225         for (i = 0; i < uaa->nifaces; i++) {
  226                 if (uaa->ifaces[i] == NULL)
  227                         continue;
  228                 id = usbd_get_interface_descriptor(uaa->ifaces[i]);
  229                 if (id != NULL &&
  230                     id->bInterfaceClass == UICLASS_WIRELESS &&
  231                     id->bInterfaceSubClass == UISUBCLASS_RF &&
  232                     id->bInterfaceProtocol == UIPROTO_BLUETOOTH) {
  233                         sc->sc_isoc_iface = uaa->ifaces[i];
  234                         uaa->ifaces[i] = NULL;
  235                 }
  236         }
  237 
  238         printf("%s: has%s isoc data\n", USBDEVNAME(sc->sc_dev),
  239                sc->sc_isoc_iface != NULL ? "" : " no");
  240 
  241         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  242                            USBDEV(sc->sc_dev));
  243 
  244         bt.bt_methods = &ubt_methods;
  245         bt.bt_cb = &sc->sc_cb;
  246         bt.bt_handle = sc;
  247 
  248         sc->sc_child = config_found(self, &bt, bt_print);
  249 
  250         USB_ATTACH_SUCCESS_RETURN;
  251 }
  252 
  253 static void
  254 ubt_abortdealloc(struct ubt_softc *sc)
  255 {
  256         DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
  257 
  258         if (sc->sc_evt_pipe != NULL) {
  259                 usbd_abort_pipe(sc->sc_evt_pipe);
  260                 usbd_close_pipe(sc->sc_evt_pipe);
  261                 sc->sc_evt_pipe = NULL;
  262         }
  263         if (sc->sc_evt_buf != NULL) {
  264                 free(sc->sc_evt_buf, M_USBDEV);
  265                 sc->sc_evt_buf = NULL;
  266         }
  267         if (sc->sc_aclrd_pipe != NULL) {
  268                 usbd_abort_pipe(sc->sc_aclrd_pipe);
  269                 usbd_close_pipe(sc->sc_aclrd_pipe);
  270                 sc->sc_aclrd_pipe = NULL;
  271         }
  272         if (sc->sc_aclwr_pipe != NULL) {
  273                 usbd_abort_pipe(sc->sc_aclwr_pipe);
  274                 usbd_close_pipe(sc->sc_aclwr_pipe);
  275                 sc->sc_aclwr_pipe = NULL;
  276         }
  277         if (sc->sc_aclrd_xfer != NULL) {
  278                 usbd_free_xfer(sc->sc_aclrd_xfer);
  279                 sc->sc_aclrd_xfer = NULL;
  280                 sc->sc_aclrd_buf = NULL;
  281         }
  282         if (sc->sc_aclwr_xfer != NULL) {
  283                 usbd_free_xfer(sc->sc_aclwr_xfer);
  284                 sc->sc_aclwr_xfer = NULL;
  285                 sc->sc_aclwr_buf = NULL;
  286         }
  287 }
  288 
  289 USB_DETACH(ubt)
  290 {
  291         USB_DETACH_START(ubt, sc);
  292         int s;
  293         int rv = 0;
  294 
  295         DPRINTF(("%s: sc=%p flags=%d\n", __func__, sc, flags));
  296 
  297         sc->sc_dying = 1;
  298 
  299         /* Abort all pipes.  Causes processes waiting for transfer to wake. */
  300         ubt_abortdealloc(sc);
  301 
  302         DPRINTFN(1, ("%s: waiting for USB detach\n", __func__));
  303         s = splusb();
  304         if (--sc->sc_refcnt >= 0) {
  305                 /* Wait for processes to go away. */
  306                 usb_detach_wait(USBDEV(sc->sc_dev));
  307         }
  308         splx(s);
  309         DPRINTFN(1, ("%s: USB detach complete\n", __func__));
  310 
  311         if (sc->sc_child != NULL) {
  312                 DPRINTFN(1, ("%s: waiting for child detach\n", __func__));
  313                 rv = config_detach(sc->sc_child, flags);
  314                 sc->sc_child = NULL;
  315                 DPRINTFN(1, ("%s: child detach complete\n", __func__));
  316         }
  317 
  318         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  319                            USBDEV(sc->sc_dev));
  320 
  321         DPRINTFN(1, ("%s: driver detached\n", __func__));
  322 
  323         return (rv);
  324 }
  325 
  326 int
  327 ubt_activate(device_ptr_t self, enum devact act)
  328 {
  329         struct ubt_softc *sc = (struct ubt_softc *)self;
  330         int error = 0;
  331 
  332         switch (act) {
  333         case DVACT_ACTIVATE:
  334                 return (EOPNOTSUPP);
  335                 break;
  336 
  337         case DVACT_DEACTIVATE:
  338                 sc->sc_dying = 1;
  339                 if (sc->sc_child != NULL)
  340                         error = config_deactivate(sc->sc_child);
  341                 break;
  342         }
  343         return (error);
  344 }
  345 
  346 static int
  347 ubt_open(void *h, int flag, int mode, usb_proc_ptr p)
  348 {
  349         struct ubt_softc *sc = h;
  350         int error;
  351         usbd_status err;
  352 
  353         DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
  354 
  355         sc->sc_evt_buf = malloc(BTHCI_EVENT_MAX_LEN, M_USBDEV, M_NOWAIT);
  356         if (sc->sc_evt_buf == NULL) {
  357                 error = ENOMEM;
  358                 goto bad0;
  359         }
  360 
  361         err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_evt_addr,
  362                                   USBD_SHORT_XFER_OK, &sc->sc_evt_pipe,
  363                                   sc, sc->sc_evt_buf, BTHCI_EVENT_MAX_LEN,
  364                                   ubt_event_cb, UBT_EVENT_EP_INTERVAL);
  365         if (err != USBD_NORMAL_COMPLETION) {
  366                 error = EIO;
  367                 goto bad1;
  368         }
  369 
  370         err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_aclrd_addr,
  371                              0, &sc->sc_aclrd_pipe);
  372         if (err != USBD_NORMAL_COMPLETION) {
  373                 error = EIO;
  374                 goto bad2;
  375         }
  376 
  377         err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_aclwr_addr,
  378                              0, &sc->sc_aclwr_pipe);
  379         if (err != USBD_NORMAL_COMPLETION) {
  380                 error = EIO;
  381                 goto bad3;
  382         }
  383 
  384         sc->sc_ctl_xfer = usbd_alloc_xfer(sc->sc_udev);
  385         if (sc->sc_ctl_xfer == NULL) {
  386                 error = ENOMEM;
  387                 goto bad4;
  388         }
  389         sc->sc_aclrd_xfer = usbd_alloc_xfer(sc->sc_udev);
  390         if (sc->sc_aclrd_xfer == NULL) {
  391                 error = ENOMEM;
  392                 goto bad5;
  393         }
  394         sc->sc_aclwr_xfer = usbd_alloc_xfer(sc->sc_udev);
  395         if (sc->sc_aclwr_xfer == NULL) {
  396                 error = ENOMEM;
  397                 goto bad6;
  398         }
  399 
  400         /* Buffers */
  401         sc->sc_ctl_buf = usbd_alloc_buffer(sc->sc_ctl_xfer,
  402                                            BTHCI_COMMAND_MAX_LEN);
  403         if (sc->sc_ctl_buf == NULL) {
  404                 error = ENOMEM;
  405                 goto bad7;
  406         }
  407         sc->sc_aclrd_buf = usbd_alloc_buffer(sc->sc_aclrd_xfer,
  408                                              BTHCI_ACL_DATA_MAX_LEN);
  409         if (sc->sc_aclrd_buf == NULL) {
  410                 error = ENOMEM;
  411                 goto bad7;
  412         }
  413         sc->sc_aclwr_buf = usbd_alloc_buffer(sc->sc_aclwr_xfer,
  414                                              BTHCI_ACL_DATA_MAX_LEN);
  415         if (sc->sc_aclwr_buf == NULL) {
  416                 error = ENOMEM;
  417                 goto bad7;
  418         }
  419 
  420         /* Start reading */
  421         ubt_aclrd_request(sc);
  422 
  423         return 0;
  424 
  425  bad7:
  426         usbd_free_xfer(sc->sc_aclwr_xfer);
  427         sc->sc_aclwr_xfer = NULL;
  428  bad6:
  429         usbd_free_xfer(sc->sc_aclrd_xfer);
  430         sc->sc_aclrd_xfer = NULL;
  431  bad5:
  432         usbd_free_xfer(sc->sc_ctl_xfer);
  433         sc->sc_ctl_xfer = NULL;
  434  bad4:
  435         usbd_close_pipe(sc->sc_aclwr_pipe);
  436         sc->sc_aclwr_pipe = NULL;
  437  bad3:
  438         usbd_close_pipe(sc->sc_aclrd_pipe);
  439         sc->sc_aclrd_pipe = NULL;
  440  bad2:
  441         usbd_close_pipe(sc->sc_evt_pipe);
  442         sc->sc_evt_pipe = NULL;
  443  bad1:
  444         free(sc->sc_evt_buf, M_USBDEV);
  445         sc->sc_evt_buf = NULL;
  446  bad0:
  447         return error;
  448 }
  449 
  450 static int
  451 ubt_close(void *h, int flag, int mode, usb_proc_ptr p)
  452 {
  453         struct ubt_softc *sc = h;
  454 
  455         DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
  456 
  457         ubt_abortdealloc(sc);
  458 
  459         return 0;
  460 }
  461 
  462 static u_int8_t*
  463 ubt_alloc_control(void *h, size_t len, struct btframe_buffer **buf)
  464 {
  465         struct ubt_softc *sc = h;
  466 
  467         /*
  468          * We should be catching this earlier, but at the moment a
  469          * user request can generate oversized allocations.
  470          */
  471         if (len > BTHCI_COMMAND_MAX_LEN)
  472                 return NULL;
  473 
  474         *buf = (struct btframe_buffer*)sc->sc_ctl_buf;
  475         return sc->sc_ctl_buf;
  476 }
  477 
  478 static int
  479 ubt_send_control(void *h, struct btframe_buffer *buf, size_t len)
  480 {
  481         struct ubt_softc *sc = h;
  482         usb_device_request_t req;
  483         usbd_status status;
  484 
  485         DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
  486 
  487 #ifdef DIAGNOSTIC
  488         if ((u_int8_t*)buf != sc->sc_ctl_buf)
  489                 panic("ubt_control() called with wrong buffer");
  490 #endif
  491 
  492         if (sc->sc_dying)
  493                 return EIO;
  494 
  495         if (len < BTHCI_COMMAND_MIN_LEN || len > BTHCI_COMMAND_MAX_LEN)
  496                 return EINVAL;
  497 
  498         sc->sc_refcnt++;
  499 
  500         memset(&req, 0, sizeof(req));
  501         req.bmRequestType = UT_WRITE_CLASS_DEVICE;
  502         USETW(req.wLength, len);
  503 
  504         usbd_setup_default_xfer(sc->sc_ctl_xfer,
  505                                 sc->sc_udev,
  506                                 sc,
  507                                 USBD_DEFAULT_TIMEOUT,
  508                                 &req, sc->sc_ctl_buf, len,
  509                                 USBD_SYNCHRONOUS | USBD_NO_COPY, NULL);
  510 
  511         status = usbd_transfer(sc->sc_ctl_xfer);
  512 
  513         if (--sc->sc_refcnt < 0)
  514                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  515 
  516         if (status != USBD_NORMAL_COMPLETION)
  517                 return EIO;
  518 
  519         return 0;
  520 }
  521 
  522 static u_int8_t*
  523 ubt_alloc_acldata(void *h, size_t len, struct btframe_buffer **buf)
  524 {
  525         struct ubt_softc *sc = h;
  526 
  527         /*
  528          * We should be catching this earlier, but at the moment a
  529          * user request can generate oversized allocations.
  530          */
  531         if (len > BTHCI_ACL_DATA_MAX_LEN)
  532                 return NULL;
  533 
  534         *buf = (struct btframe_buffer*)sc->sc_aclwr_buf;
  535         return sc->sc_aclwr_buf;
  536 }
  537 
  538 static int
  539 ubt_send_acldata(void *h, struct btframe_buffer *buf, size_t len)
  540 {
  541         struct ubt_softc *sc = h;
  542         usbd_status status;
  543 
  544         DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
  545 
  546 #ifdef DIAGNOSTIC
  547         if ((u_int8_t*)buf != sc->sc_aclwr_buf)
  548                 panic("ubt_sendacldata() called with wrong buffer");
  549 #endif
  550 
  551         if (sc->sc_dying)
  552                 return EIO;
  553 
  554         if (len < BTHCI_ACL_DATA_MIN_LEN || len > BTHCI_ACL_DATA_MAX_LEN)
  555                 return EINVAL;
  556 
  557         sc->sc_refcnt++;
  558 
  559         usbd_setup_xfer(sc->sc_aclwr_xfer,
  560                         sc->sc_aclwr_pipe,
  561                         (usbd_private_handle)sc,
  562                         sc->sc_aclwr_buf, len,
  563                         USBD_SYNCHRONOUS | USBD_NO_COPY,
  564                         USBD_DEFAULT_TIMEOUT,
  565                         NULL);
  566 
  567         status = usbd_transfer(sc->sc_aclwr_xfer);
  568 
  569         if (--sc->sc_refcnt < 0)
  570                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  571 
  572         if (status != USBD_NORMAL_COMPLETION)
  573                 return EIO;
  574 
  575         return 0;
  576 }
  577 
  578 static u_int8_t*
  579 ubt_alloc_scodata(void *h, size_t len, struct btframe_buffer **buf)
  580 {
  581         return NULL;
  582 }
  583 
  584 static int
  585 ubt_send_scodata(void *h, struct btframe_buffer *buf, size_t len)
  586 {
  587         struct ubt_softc *sc = h;
  588 
  589         DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
  590 
  591         if (sc->sc_dying)
  592                 return EIO;
  593 
  594         return ENXIO;
  595 }
  596 
  597 static void
  598 ubt_event_cb(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
  599 {
  600         struct ubt_softc *sc = h;
  601         void *buf;
  602         u_int32_t size;
  603 
  604         DPRINTFN(1,("%s: sc=%p status=%s\n", __func__, sc,
  605                     usbd_errstr(status)));
  606 
  607         if (status != USBD_NORMAL_COMPLETION || sc->sc_dying ||
  608             sc->sc_child == NULL)
  609                 return;
  610 
  611         usbd_get_xfer_status(xfer, NULL, &buf, &size, NULL);
  612 
  613         sc->sc_cb->bt_recveventdata(sc->sc_child, buf, (size_t)size);
  614 }
  615 
  616 static void
  617 ubt_aclrd_request(struct ubt_softc *sc)
  618 {
  619         usbd_status status;
  620         int s;
  621 
  622         DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
  623 
  624         if (sc->sc_dying)
  625                 return;
  626 
  627         s = splusb();
  628         if (sc->sc_aclrd_running) {
  629                 splx(s);
  630                 return;
  631         }
  632         sc->sc_aclrd_running = 1;
  633         splx(s);
  634 
  635         usbd_setup_xfer(sc->sc_aclrd_xfer, sc->sc_aclrd_pipe,
  636                         sc, sc->sc_aclrd_buf, BTHCI_ACL_DATA_MAX_LEN,
  637                         USBD_SHORT_XFER_OK | USBD_NO_COPY,
  638                         USBD_NO_TIMEOUT, ubt_aclrd_cb);
  639 
  640         status = usbd_transfer(sc->sc_aclrd_xfer);
  641 
  642         /* Cancellation is normal on device shutdown */
  643         if (status == USBD_IN_PROGRESS || status == USBD_CANCELLED)
  644                 return;
  645 
  646         DPRINTFN(1,("%s: read request failed: %s\n", __func__,
  647                     usbd_errstr(status)));
  648 
  649         sc->sc_aclrd_running = 0;
  650         /* XXX now what!? */
  651 }
  652 
  653 static void
  654 ubt_aclrd_cb(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
  655 {
  656         struct ubt_softc *sc = h;
  657         void *buf;
  658         u_int32_t size;
  659 
  660         DPRINTFN(1,("%s: sc=%p status=%s\n", __func__, sc,
  661                     usbd_errstr(status)));
  662 
  663         sc->sc_aclrd_running = 0;
  664 
  665         if (status != USBD_NORMAL_COMPLETION || sc->sc_dying ||
  666             sc->sc_child == NULL)
  667                 return;
  668 
  669         usbd_get_xfer_status(xfer, NULL, &buf, &size, NULL);
  670 
  671         sc->sc_cb->bt_recvacldata(sc->sc_child, buf, (size_t)size);
  672 
  673         /* Re-issue the request */
  674         if (!sc->sc_dying)
  675                 ubt_aclrd_request(sc);
  676 }
  677 
  678 static int
  679 ubt_splraise(void)
  680 {
  681         return splusb();
  682 }

Cache object: f7d7da8d107e88003fe7f030302e924a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.