summaryrefslogtreecommitdiffstats
path: root/sys/netgraph
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2009-05-27 16:29:56 +0000
committerthompsa <thompsa@FreeBSD.org>2009-05-27 16:29:56 +0000
commit77ea8140da53162b03f0702d4d1203b1ade7095c (patch)
tree6d2db1181a316ff07083148521755dd05dc191e8 /sys/netgraph
parent896c73926fc3bf33749f691d39765d0e288e0df1 (diff)
downloadFreeBSD-src-77ea8140da53162b03f0702d4d1203b1ade7095c.zip
FreeBSD-src-77ea8140da53162b03f0702d4d1203b1ade7095c.tar.gz
Delete the bluetooth drivers for the old usb stack.
Diffstat (limited to 'sys/netgraph')
-rw-r--r--sys/netgraph/bluetooth/drivers/ubt/TODO36
-rw-r--r--sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c2344
-rw-r--r--sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h152
-rw-r--r--sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c559
4 files changed, 0 insertions, 3091 deletions
diff --git a/sys/netgraph/bluetooth/drivers/ubt/TODO b/sys/netgraph/bluetooth/drivers/ubt/TODO
deleted file mode 100644
index 7f840c9..0000000
--- a/sys/netgraph/bluetooth/drivers/ubt/TODO
+++ /dev/null
@@ -1,36 +0,0 @@
-$Id: TODO,v 1.1 2002/11/24 19:46:56 max Exp $
-$FreeBSD$
-
-1) SMP/Locking
-
- The code makes use of ng_send_fn() whenever possible. Just
- need to verify and make sure i did it right
-
- ** DONE. Seems to work **
-
-2) Review USB ATTACH function
-
- It is a bit ugly now. Probably need a better way to discover
- USB device configuration.
-
-2) Firmware upgrade
-
- According to Bluetooth spec device may present third interface
- to perform firmware upgrade. 3Com USB Bluetooth dongle has
- such interface. Need to implement set of Netgraph messages.
-
-3) Understand and fix isoc. USB transfers (SCO data)
-
- Currenty device reports that is got zero bytes and calls
- isoc_in_complete callback over and over again. Why?
- Also might need to setup at least two isoc. transfers in
- both directions and switch them on the fly. Just to ensure
- there at least one transfer at any time ready to run.
-
- ** DONE. Needs more testings **
-
-4) Currently interrupt transfers are done as bulk-in transfers
-
- Need to check if that is allowed.
-
- ** DONE. Seems to work **
diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c
deleted file mode 100644
index 5d2b4a2..0000000
--- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c
+++ /dev/null
@@ -1,2344 +0,0 @@
-/*
- * ng_ubt.c
- */
-
-/*-
- * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: ng_ubt.c,v 1.22 2005/10/31 17:57:44 max Exp $
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/endian.h>
-#include <sys/filio.h>
-#include <sys/fcntl.h>
-#include <sys/mbuf.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/poll.h>
-#include <sys/uio.h>
-#include <machine/bus.h>
-
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usbdivar.h>
-
-#include <netgraph/ng_message.h>
-#include <netgraph/netgraph.h>
-#include <netgraph/ng_parse.h>
-#include <netgraph/bluetooth/include/ng_bluetooth.h>
-#include <netgraph/bluetooth/include/ng_hci.h>
-#include <netgraph/bluetooth/include/ng_ubt.h>
-#include <netgraph/bluetooth/drivers/ubt/ng_ubt_var.h>
-
-#include "usbdevs.h"
-
-/*
- * USB methods
- */
-
-static device_probe_t ubt_match;
-static device_attach_t ubt_attach;
-static device_detach_t ubt_detach;
-
-static device_method_t ubt_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, ubt_match),
- DEVMETHOD(device_attach, ubt_attach),
- DEVMETHOD(device_detach, ubt_detach),
-
- { 0, 0 }
-};
-
-static driver_t ubt_driver = {
- "ubt",
- ubt_methods,
- sizeof(struct ubt_softc)
-};
-
-static devclass_t ubt_devclass;
-
-static int ubt_modevent (module_t, int, void *);
-
-static usbd_status ubt_request_start (ubt_softc_p);
-static void ubt_request_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_request_complete2 (node_p, hook_p, void *, int);
-
-static usbd_status ubt_intr_start (ubt_softc_p);
-static void ubt_intr_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_intr_complete2 (node_p, hook_p, void *, int);
-
-static usbd_status ubt_bulk_in_start (ubt_softc_p);
-static void ubt_bulk_in_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_bulk_in_complete2 (node_p, hook_p, void *, int);
-
-static usbd_status ubt_bulk_out_start (ubt_softc_p);
-static void ubt_bulk_out_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_bulk_out_complete2 (node_p, hook_p, void *, int);
-
-static usbd_status ubt_isoc_in_start_one (ubt_softc_p, int);
-static usbd_status ubt_isoc_in_start (ubt_softc_p);
-static void ubt_isoc_in_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_isoc_in_complete2 (node_p, hook_p, void *, int);
-
-static usbd_status ubt_isoc_out_start_one (ubt_softc_p, int);
-static usbd_status ubt_isoc_out_start (ubt_softc_p);
-static void ubt_isoc_out_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_isoc_out_complete2 (node_p, hook_p, void *, int);
-
-static void ubt_reset (ubt_softc_p);
-
-/*
- * Netgraph methods
- */
-
-static ng_constructor_t ng_ubt_constructor;
-static ng_shutdown_t ng_ubt_shutdown;
-static ng_newhook_t ng_ubt_newhook;
-static ng_connect_t ng_ubt_connect;
-static ng_disconnect_t ng_ubt_disconnect;
-static ng_rcvmsg_t ng_ubt_rcvmsg;
-static ng_rcvdata_t ng_ubt_rcvdata;
-
-/* Queue length */
-static const struct ng_parse_struct_field ng_ubt_node_qlen_type_fields[] =
-{
- { "queue", &ng_parse_int32_type, },
- { "qlen", &ng_parse_int32_type, },
- { NULL, }
-};
-static const struct ng_parse_type ng_ubt_node_qlen_type = {
- &ng_parse_struct_type,
- &ng_ubt_node_qlen_type_fields
-};
-
-/* Stat info */
-static const struct ng_parse_struct_field ng_ubt_node_stat_type_fields[] =
-{
- { "pckts_recv", &ng_parse_uint32_type, },
- { "bytes_recv", &ng_parse_uint32_type, },
- { "pckts_sent", &ng_parse_uint32_type, },
- { "bytes_sent", &ng_parse_uint32_type, },
- { "oerrors", &ng_parse_uint32_type, },
- { "ierrors", &ng_parse_uint32_type, },
- { NULL, }
-};
-static const struct ng_parse_type ng_ubt_node_stat_type = {
- &ng_parse_struct_type,
- &ng_ubt_node_stat_type_fields
-};
-
-/* Netgraph node command list */
-static const struct ng_cmdlist ng_ubt_cmdlist[] = {
-{
- NGM_UBT_COOKIE,
- NGM_UBT_NODE_SET_DEBUG,
- "set_debug",
- &ng_parse_uint16_type,
- NULL
-},
-{
- NGM_UBT_COOKIE,
- NGM_UBT_NODE_GET_DEBUG,
- "get_debug",
- NULL,
- &ng_parse_uint16_type
-},
-{
- NGM_UBT_COOKIE,
- NGM_UBT_NODE_SET_QLEN,
- "set_qlen",
- &ng_ubt_node_qlen_type,
- NULL
-},
-{
- NGM_UBT_COOKIE,
- NGM_UBT_NODE_GET_QLEN,
- "get_qlen",
- &ng_ubt_node_qlen_type,
- &ng_ubt_node_qlen_type
-},
-{
- NGM_UBT_COOKIE,
- NGM_UBT_NODE_GET_STAT,
- "get_stat",
- NULL,
- &ng_ubt_node_stat_type
-},
-{
- NGM_UBT_COOKIE,
- NGM_UBT_NODE_RESET_STAT,
- "reset_stat",
- NULL,
- NULL
-},
-{ 0, }
-};
-
-/* Netgraph node type */
-static struct ng_type typestruct = {
- .version = NG_ABI_VERSION,
- .name = NG_UBT_NODE_TYPE,
- .constructor = ng_ubt_constructor,
- .rcvmsg = ng_ubt_rcvmsg,
- .shutdown = ng_ubt_shutdown,
- .newhook = ng_ubt_newhook,
- .connect = ng_ubt_connect,
- .rcvdata = ng_ubt_rcvdata,
- .disconnect = ng_ubt_disconnect,
- .cmdlist = ng_ubt_cmdlist
-};
-
-/*
- * Module
- */
-
-DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, 0);
-MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
-MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
-MODULE_DEPEND(ubt, usb, 1, 1, 1);
-
-
-/****************************************************************************
- ****************************************************************************
- ** USB specific
- ****************************************************************************
- ****************************************************************************/
-
-/*
- * Load/Unload the driver module
- */
-
-static int
-ubt_modevent(module_t mod, int event, void *data)
-{
- int error;
-
- switch (event) {
- case MOD_LOAD:
- error = ng_newtype(&typestruct);
- if (error != 0)
- printf(
-"%s: Could not register Netgraph node type, error=%d\n",
- NG_UBT_NODE_TYPE, error);
- else
- error = usbd_driver_load(mod, event, data);
- break;
-
- case MOD_UNLOAD:
- error = ng_rmtype(&typestruct);
- if (error == 0)
- error = usbd_driver_load(mod, event, data);
- break;
-
- default:
- error = EOPNOTSUPP;
- break;
- }
-
- return (error);
-} /* ubt_modevent */
-
-/*
- * Probe for a USB Bluetooth device
- */
-
-static int
-ubt_match(device_t self)
-{
- /*
- * If for some reason device should not be attached then put
- * VendorID/ProductID pair into the list below. The format is
- * as follows:
- *
- * { VENDOR_ID, PRODUCT_ID },
- *
- * where VENDOR_ID and PRODUCT_ID are hex numbers.
- */
-
- static struct usb_devno const ubt_ignored_devices[] = {
- { USB_VENDOR_AVM, 0x2200 }, /* AVM USB Bluetooth-Adapter BlueFritz! v1.0 */
- { 0, 0 } /* This should be the last item in the list */
- };
-
- /*
- * If device violates Bluetooth specification and has bDeviceClass,
- * bDeviceSubClass and bDeviceProtocol set to wrong values then you
- * could try to put VendorID/ProductID pair into the list below.
- * Adding VendorID/ProductID pair into this list forces ng_ubt(4)
- * to attach to the broken device.
- */
-
- static struct usb_devno const ubt_broken_devices[] = {
- { USB_VENDOR_AVM, 0x3800 }, /* AVM USB Bluetooth-Adapter BlueFritz! v2.0 */
- { 0, 0 } /* This should be the last item in the list */
- };
-
- struct usb_attach_arg *uaa = device_get_ivars(self);
- usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
-
- if (uaa->iface == NULL ||
- usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
- return (UMATCH_NONE);
-
- if (dd->bDeviceClass == UDCLASS_WIRELESS &&
- dd->bDeviceSubClass == UDSUBCLASS_RF &&
- dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
- return (UMATCH_DEVCLASS_DEVSUBCLASS);
-
- if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
- return (UMATCH_VENDOR_PRODUCT);
-
- return (UMATCH_NONE);
-} /* ubt_match */
-
-/*
- * Attach the device
- */
-
-static int
-ubt_attach(device_t self)
-{
- struct ubt_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
- usb_config_descriptor_t *cd = NULL;
- usb_interface_descriptor_t *id = NULL;
- usb_endpoint_descriptor_t *ed = NULL;
- usbd_status error;
- int i, ai, alt_no, isoc_in, isoc_out,
- isoc_isize, isoc_osize;
-
- /* Get USB device info */
- sc->sc_dev = self;
- sc->sc_udev = uaa->device;
-
- /*
- * Initialize device softc structure
- */
-
- /* State */
- sc->sc_debug = NG_UBT_WARN_LEVEL;
- sc->sc_flags = 0;
- NG_UBT_STAT_RESET(sc->sc_stat);
-
- /* Interfaces */
- sc->sc_iface0 = sc->sc_iface1 = NULL;
-
- /* Interrupt pipe */
- sc->sc_intr_ep = -1;
- sc->sc_intr_pipe = NULL;
- sc->sc_intr_xfer = NULL;
- sc->sc_intr_buffer = NULL;
-
- /* Control pipe */
- sc->sc_ctrl_xfer = NULL;
- sc->sc_ctrl_buffer = NULL;
- NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
-
- /* Bulk-in pipe */
- sc->sc_bulk_in_ep = -1;
- sc->sc_bulk_in_pipe = NULL;
- sc->sc_bulk_in_xfer = NULL;
- sc->sc_bulk_in_buffer = NULL;
-
- /* Bulk-out pipe */
- sc->sc_bulk_out_ep = -1;
- sc->sc_bulk_out_pipe = NULL;
- sc->sc_bulk_out_xfer = NULL;
- sc->sc_bulk_out_buffer = NULL;
- NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
-
- /* Isoc-in pipe */
- sc->sc_isoc_in_buffer = NULL;
- sc->sc_isoc_in_ep = -1;
- sc->sc_isoc_in_pipe = NULL;
- bzero(&sc->sc_isoc_in, sizeof(sc->sc_isoc_in));
-
- /* Isoc-out pipe */
- sc->sc_isoc_out_ep = -1;
- sc->sc_isoc_out_pipe = NULL;
- bzero(&sc->sc_isoc_out, sizeof(sc->sc_isoc_out));
-
- sc->sc_isoc_size = -1;
- NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
-
- /* Netgraph part */
- sc->sc_node = NULL;
- sc->sc_hook = NULL;
-
- /*
- * XXX set configuration?
- *
- * Configure Bluetooth USB device. Discover all required USB interfaces
- * and endpoints.
- *
- * USB device must present two interfaces:
- * 1) Interface 0 that has 3 endpoints
- * 1) Interrupt endpoint to receive HCI events
- * 2) Bulk IN endpoint to receive ACL data
- * 3) Bulk OUT endpoint to send ACL data
- *
- * 2) Interface 1 then has 2 endpoints
- * 1) Isochronous IN endpoint to receive SCO data
- * 2) Isochronous OUT endpoint to send SCO data
- *
- * Interface 1 (with isochronous endpoints) has several alternate
- * configurations with different packet size.
- */
-
- /*
- * Interface 0
- */
-
- error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
- if (error || sc->sc_iface0 == NULL) {
- printf("%s: Could not get interface 0 handle. %s (%d), " \
- "handle=%p\n", device_get_nameunit(sc->sc_dev),
- usbd_errstr(error), error, sc->sc_iface0);
- goto bad;
- }
-
- id = usbd_get_interface_descriptor(sc->sc_iface0);
- if (id == NULL) {
- printf("%s: Could not get interface 0 descriptor\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- for (i = 0; i < id->bNumEndpoints; i ++) {
- ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
- if (ed == NULL) {
- printf("%s: Could not read endpoint descriptor for " \
- "interface 0, i=%d\n", device_get_nameunit(sc->sc_dev),
- i);
- goto bad;
- }
-
- switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
- case UE_BULK:
- if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
- sc->sc_bulk_in_ep = ed->bEndpointAddress;
- else
- sc->sc_bulk_out_ep = ed->bEndpointAddress;
- break;
-
- case UE_INTERRUPT:
- sc->sc_intr_ep = ed->bEndpointAddress;
- break;
- }
- }
-
- /* Check if we got everything we wanted on Interface 0 */
- if (sc->sc_intr_ep == -1) {
- printf("%s: Could not detect interrupt endpoint\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
- if (sc->sc_bulk_in_ep == -1) {
- printf("%s: Could not detect bulk-in endpoint\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
- if (sc->sc_bulk_out_ep == -1) {
- printf("%s: Could not detect bulk-out endpoint\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
- "bulk-out=%#x\n", device_get_nameunit(sc->sc_dev),
- sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
-
- /*
- * Interface 1
- */
-
- cd = usbd_get_config_descriptor(sc->sc_udev);
- if (cd == NULL) {
- printf("%s: Could not get device configuration descriptor\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
- if (error || sc->sc_iface1 == NULL) {
- printf("%s: Could not get interface 1 handle. %s (%d), " \
- "handle=%p\n", device_get_nameunit(sc->sc_dev),
- usbd_errstr(error), error, sc->sc_iface1);
- goto bad;
- }
-
- id = usbd_get_interface_descriptor(sc->sc_iface1);
- if (id == NULL) {
- printf("%s: Could not get interface 1 descriptor\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- /*
- * Scan all alternate configurations for interface 1
- */
-
- alt_no = -1;
-
- for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++) {
- error = usbd_set_interface(sc->sc_iface1, ai);
- if (error) {
- printf("%s: [SCAN] Could not set alternate " \
- "configuration %d for interface 1. %s (%d)\n",
- device_get_nameunit(sc->sc_dev), ai, usbd_errstr(error),
- error);
- goto bad;
- }
- id = usbd_get_interface_descriptor(sc->sc_iface1);
- if (id == NULL) {
- printf("%s: Could not get interface 1 descriptor for " \
- "alternate configuration %d\n",
- device_get_nameunit(sc->sc_dev), ai);
- goto bad;
- }
-
- isoc_in = isoc_out = -1;
- isoc_isize = isoc_osize = 0;
-
- for (i = 0; i < id->bNumEndpoints; i ++) {
- ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
- if (ed == NULL) {
- printf("%s: Could not read endpoint " \
- "descriptor for interface 1, " \
- "alternate configuration %d, i=%d\n",
- device_get_nameunit(sc->sc_dev), ai, i);
- goto bad;
- }
-
- if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
- continue;
-
- if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
- isoc_in = ed->bEndpointAddress;
- isoc_isize = UGETW(ed->wMaxPacketSize);
- } else {
- isoc_out = ed->bEndpointAddress;
- isoc_osize = UGETW(ed->wMaxPacketSize);
- }
- }
-
- /*
- * Make sure that configuration looks sane and if so
- * update current settings
- */
-
- if (isoc_in != -1 && isoc_out != -1 &&
- isoc_isize > 0 && isoc_osize > 0 &&
- isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
- sc->sc_isoc_in_ep = isoc_in;
- sc->sc_isoc_out_ep = isoc_out;
- sc->sc_isoc_size = isoc_isize;
- alt_no = ai;
- }
- }
-
- /* Check if we got everything we wanted on Interface 0 */
- if (sc->sc_isoc_in_ep == -1) {
- printf("%s: Could not detect isoc-in endpoint\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
- if (sc->sc_isoc_out_ep == -1) {
- printf("%s: Could not detect isoc-out endpoint\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
- if (sc->sc_isoc_size <= 0) {
- printf("%s: Invalid isoc. packet size=%d\n",
- device_get_nameunit(sc->sc_dev), sc->sc_isoc_size);
- goto bad;
- }
-
- error = usbd_set_interface(sc->sc_iface1, alt_no);
- if (error) {
- printf("%s: Could not set alternate configuration " \
- "%d for interface 1. %s (%d)\n",
- device_get_nameunit(sc->sc_dev),
- alt_no, usbd_errstr(error), error);
- goto bad;
- }
-
- /* Allocate USB transfer handles and buffers */
- sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
- if (sc->sc_ctrl_xfer == NULL) {
- printf("%s: Could not allocate control xfer handle\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
- sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer,
- UBT_CTRL_BUFFER_SIZE);
- if (sc->sc_ctrl_buffer == NULL) {
- printf("%s: Could not allocate control buffer\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
- if (sc->sc_intr_xfer == NULL) {
- printf("%s: Could not allocate interrupt xfer handle\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
- if (sc->sc_bulk_in_xfer == NULL) {
- printf("%s: Could not allocate bulk-in xfer handle\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
- if (sc->sc_bulk_out_xfer == NULL) {
- printf("%s: Could not allocate bulk-out xfer handle\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
- sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
- UBT_BULK_BUFFER_SIZE);
- if (sc->sc_bulk_out_buffer == NULL) {
- printf("%s: Could not allocate bulk-out buffer\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- /*
- * Allocate buffers for isoc. transfers
- */
-
- for (i = 0; i < NG_UBT_NXFERS; i++) {
- sc->sc_isoc_in[i].xfer = usbd_alloc_xfer(sc->sc_udev);
- if (sc->sc_isoc_in[i].xfer == NULL) {
- printf("%s: Could not allocate isoc-in xfer handle\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- sc->sc_isoc_in[i].buffer = usbd_alloc_buffer(
- sc->sc_isoc_in[i].xfer,
- NG_UBT_NFRAMES * sc->sc_isoc_size);
- if (sc->sc_isoc_in[i].buffer == NULL) {
- printf("%s: Could not allocate isoc-in buffer\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- sc->sc_isoc_in[i].frlen = malloc(
- sizeof(uint16_t) * NG_UBT_NFRAMES,
- M_USBDEV, M_NOWAIT);
- if (sc->sc_isoc_in[i].frlen == NULL) {
- printf("%s: Could not allocate isoc-in frame sizes buffer\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
- }
-
- for (i = 0; i < NG_UBT_NXFERS; i++) {
- sc->sc_isoc_out[i].xfer = usbd_alloc_xfer(sc->sc_udev);
- if (sc->sc_isoc_out[i].xfer == NULL) {
- printf("%s: Could not allocate isoc-out xfer handle\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- sc->sc_isoc_out[i].buffer = usbd_alloc_buffer(
- sc->sc_isoc_out[i].xfer,
- NG_UBT_NFRAMES * sc->sc_isoc_size);
- if (sc->sc_isoc_out[i].buffer == NULL) {
- printf("%s: Could not allocate isoc-out buffer\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- sc->sc_isoc_out[i].frlen = malloc(
- sizeof(uint16_t) * NG_UBT_NFRAMES,
- M_USBDEV, M_NOWAIT);
- if (sc->sc_isoc_out[i].frlen == NULL) {
- printf("%s: Could not allocate isoc-out frame sizes buffer\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
- }
-
- printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
- "isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
- device_get_nameunit(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
- sc->sc_isoc_out_ep, sc->sc_isoc_size, NG_UBT_NFRAMES,
- (NG_UBT_NFRAMES * sc->sc_isoc_size));
-
- /*
- * Open pipes
- */
-
- /* Interrupt */
- error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
- USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
- if (error != USBD_NORMAL_COMPLETION) {
- printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
- error);
- goto bad;
- }
-
- /* Bulk-in */
- error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
- USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
- if (error != USBD_NORMAL_COMPLETION) {
- printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
- error);
- goto bad;
- }
-
- /* Bulk-out */
- error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
- USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
- if (error != USBD_NORMAL_COMPLETION) {
- printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
- error);
- goto bad;
- }
-
- /* Isoc-in */
- error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
- USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
- if (error != USBD_NORMAL_COMPLETION) {
- printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
- error);
- goto bad;
- }
-
- /* Isoc-out */
- error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep,
- USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
- if (error != USBD_NORMAL_COMPLETION) {
- printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
- error);
- goto bad;
- }
-
- /* Create Netgraph node */
- if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
- printf("%s: Could not create Netgraph node\n",
- device_get_nameunit(sc->sc_dev));
- sc->sc_node = NULL;
- goto bad;
- }
-
- /* Name node */
- if (ng_name_node(sc->sc_node, device_get_nameunit(sc->sc_dev)) != 0) {
- printf("%s: Could not name Netgraph node\n",
- device_get_nameunit(sc->sc_dev));
- NG_NODE_UNREF(sc->sc_node);
- sc->sc_node = NULL;
- goto bad;
- }
-
- NG_NODE_SET_PRIVATE(sc->sc_node, sc);
- NG_NODE_FORCE_WRITER(sc->sc_node);
-
- /* Claim all interfaces on the device */
- for (i = 0; i < uaa->nifaces; i++)
- uaa->ifaces[i] = NULL;
-
- usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
- sc->sc_dev);
-
- return 0;
-bad:
- ubt_detach(self);
-
- return ENXIO;
-} /* ubt_attach */
-
-/*
- * Detach the device
- */
-
-static int
-ubt_detach(device_t self)
-{
- struct ubt_softc *sc = device_get_softc(self);
- int i;
-
- /* Destroy Netgraph node */
- if (sc->sc_node != NULL) {
- NG_NODE_SET_PRIVATE(sc->sc_node, NULL);
- ng_rmnode_self(sc->sc_node);
- sc->sc_node = NULL;
- }
-
- /* Close pipes */
- if (sc->sc_intr_pipe != NULL) {
- usbd_abort_pipe(sc->sc_intr_pipe);
- usbd_close_pipe(sc->sc_intr_pipe);
- sc->sc_intr_pipe = NULL;
- }
-
- if (sc->sc_bulk_in_pipe != NULL) {
- usbd_abort_pipe(sc->sc_bulk_in_pipe);
- usbd_close_pipe(sc->sc_bulk_in_pipe);
- sc->sc_bulk_in_pipe = NULL;
- }
- if (sc->sc_bulk_out_pipe != NULL) {
- usbd_abort_pipe(sc->sc_bulk_out_pipe);
- usbd_close_pipe(sc->sc_bulk_out_pipe);
- sc->sc_bulk_out_pipe = NULL;
- }
-
- if (sc->sc_isoc_in_pipe != NULL) {
- usbd_abort_pipe(sc->sc_isoc_in_pipe);
- usbd_close_pipe(sc->sc_isoc_in_pipe);
- sc->sc_isoc_in_pipe = NULL;
- }
- if (sc->sc_isoc_out_pipe != NULL) {
- usbd_abort_pipe(sc->sc_isoc_out_pipe);
- usbd_close_pipe(sc->sc_isoc_out_pipe);
- sc->sc_isoc_out_pipe = NULL;
- }
-
- /* Destroy USB transfer handles */
- if (sc->sc_ctrl_xfer != NULL) {
- usbd_free_xfer(sc->sc_ctrl_xfer);
- sc->sc_ctrl_xfer = NULL;
- }
-
- if (sc->sc_intr_xfer != NULL) {
- usbd_free_xfer(sc->sc_intr_xfer);
- sc->sc_intr_xfer = NULL;
- }
-
- if (sc->sc_bulk_in_xfer != NULL) {
- usbd_free_xfer(sc->sc_bulk_in_xfer);
- sc->sc_bulk_in_xfer = NULL;
- }
- if (sc->sc_bulk_out_xfer != NULL) {
- usbd_free_xfer(sc->sc_bulk_out_xfer);
- sc->sc_bulk_out_xfer = NULL;
- }
-
- for (i = 0; i < NG_UBT_NXFERS; i++) {
- if (sc->sc_isoc_in[i].xfer != NULL) {
- usbd_free_xfer(sc->sc_isoc_in[i].xfer);
- sc->sc_isoc_in[i].xfer = NULL;
- sc->sc_isoc_in[i].buffer = NULL;
- }
-
- if (sc->sc_isoc_in[i].frlen != NULL) {
- free(sc->sc_isoc_in[i].frlen, M_USBDEV);
- sc->sc_isoc_in[i].frlen = NULL;
- }
- }
-
- for (i = 0; i < NG_UBT_NXFERS; i++) {
- if (sc->sc_isoc_out[i].xfer != NULL) {
- usbd_free_xfer(sc->sc_isoc_out[i].xfer);
- sc->sc_isoc_out[i].xfer = NULL;
- sc->sc_isoc_out[i].buffer = NULL;
- }
-
- if (sc->sc_isoc_out[i].frlen != NULL) {
- free(sc->sc_isoc_out[i].frlen, M_USBDEV);
- sc->sc_isoc_out[i].frlen = NULL;
- }
- }
-
- NG_FREE_M(sc->sc_bulk_in_buffer);
- NG_FREE_M(sc->sc_isoc_in_buffer);
-
- /* Destroy queues */
- NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
- NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
- NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
-
- usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
-
- return (0);
-} /* ubt_detach */
-
-/*
- * Start USB control request (HCI command). Must be called with node locked
- */
-
-static usbd_status
-ubt_request_start(ubt_softc_p sc)
-{
- usb_device_request_t req;
- struct mbuf *m = NULL;
- usbd_status status;
-
- KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
-"%s: %s - Another control request is pending\n",
- __func__, device_get_nameunit(sc->sc_dev)));
-
- NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
- if (m == NULL) {
- NG_UBT_INFO(
-"%s: %s - HCI command queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
-
- return (USBD_NORMAL_COMPLETION);
- }
-
- /*
- * Check HCI command frame size and copy it back to
- * linear USB transfer buffer.
- */
-
- if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
- panic(
-"%s: %s - HCI command frame too big, size=%zd, len=%d\n",
- __func__, device_get_nameunit(sc->sc_dev), UBT_CTRL_BUFFER_SIZE,
- m->m_pkthdr.len);
-
- m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
-
- /* Initialize a USB control request and then schedule it */
- bzero(&req, sizeof(req));
- req.bmRequestType = UBT_HCI_REQUEST;
- USETW(req.wLength, m->m_pkthdr.len);
-
- NG_UBT_INFO(
-"%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
- __func__, device_get_nameunit(sc->sc_dev), req.bmRequestType,
- UGETW(req.wLength));
-
- usbd_setup_default_xfer(
- sc->sc_ctrl_xfer,
- sc->sc_udev,
- (usbd_private_handle) sc->sc_node,
- USBD_DEFAULT_TIMEOUT, /* XXX */
- &req,
- sc->sc_ctrl_buffer,
- m->m_pkthdr.len,
- USBD_NO_COPY,
- ubt_request_complete);
-
- NG_NODE_REF(sc->sc_node);
-
- status = usbd_transfer(sc->sc_ctrl_xfer);
- if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
- NG_UBT_ERR(
-"%s: %s - Could not start control request. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev),
- usbd_errstr(status), status);
-
- NG_NODE_UNREF(sc->sc_node);
-
- NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
- NG_UBT_STAT_OERROR(sc->sc_stat);
-
- /* XXX FIXME should we try to resubmit another request? */
- } else {
- NG_UBT_INFO(
-"%s: %s - Control request has been started\n",
- __func__, device_get_nameunit(sc->sc_dev));
-
- sc->sc_flags |= UBT_CMD_XMIT;
- status = USBD_NORMAL_COMPLETION;
- }
-
- NG_FREE_M(m);
-
- return (status);
-} /* ubt_request_start */
-
-/*
- * USB control request callback
- */
-
-static void
-ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
-{
- ng_send_fn((node_p) p, NULL, ubt_request_complete2, (void *) h, s);
- NG_NODE_UNREF((node_p) p);
-} /* ubt_request_complete */
-
-static void
-ubt_request_complete2(node_p node, hook_p hook, void *arg1, int arg2)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
- usbd_xfer_handle h = (usbd_xfer_handle) arg1;
- usbd_status s = (usbd_status) arg2;
-
- if (sc == NULL)
- return;
-
- KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
-"%s: %s - No control request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
-
- sc->sc_flags &= ~UBT_CMD_XMIT;
-
- if (s == USBD_CANCELLED) {
- NG_UBT_INFO(
-"%s: %s - Control request cancelled\n", __func__, device_get_nameunit(sc->sc_dev));
-
- return;
- }
-
- if (s != USBD_NORMAL_COMPLETION) {
- NG_UBT_ERR(
-"%s: %s - Control request failed. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
-
- if (s == USBD_STALLED)
- usbd_clear_endpoint_stall_async(h->pipe);
-
- NG_UBT_STAT_OERROR(sc->sc_stat);
- } else {
- NG_UBT_INFO(
-"%s: %s - Sent %d bytes to control pipe\n",
- __func__, device_get_nameunit(sc->sc_dev), h->actlen);
-
- NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
- NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
- }
-
- if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
- ubt_request_start(sc);
-} /* ubt_request_complete2 */
-
-/*
- * Start interrupt transfer. Must be called when node is locked
- */
-
-static usbd_status
-ubt_intr_start(ubt_softc_p sc)
-{
- struct mbuf *m = NULL;
- usbd_status status;
-
- KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
-"%s: %s - Another interrupt request is pending\n",
- __func__, device_get_nameunit(sc->sc_dev)));
-
- /* Allocate new mbuf cluster */
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return (USBD_NOMEM);
-
- MCLGET(m, M_DONTWAIT);
- if (!(m->m_flags & M_EXT)) {
- NG_FREE_M(m);
- return (USBD_NOMEM);
- }
-
- if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
- *mtod(m, uint8_t *) = NG_HCI_EVENT_PKT;
- m->m_pkthdr.len = m->m_len = 1;
- } else
- m->m_pkthdr.len = m->m_len = 0;
-
- /* Initialize a USB transfer and then schedule it */
- usbd_setup_xfer(
- sc->sc_intr_xfer,
- sc->sc_intr_pipe,
- (usbd_private_handle) sc->sc_node,
- (void *)(mtod(m, uint8_t *) + m->m_len),
- MCLBYTES - m->m_len,
- USBD_SHORT_XFER_OK,
- USBD_NO_TIMEOUT,
- ubt_intr_complete);
-
- NG_NODE_REF(sc->sc_node);
-
- status = usbd_transfer(sc->sc_intr_xfer);
- if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
- NG_UBT_ERR(
-"%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
- status);
-
- NG_NODE_UNREF(sc->sc_node);
-
- NG_FREE_M(m);
-
- return (status);
- }
-
- sc->sc_flags |= UBT_EVT_RECV;
- sc->sc_intr_buffer = m;
-
- return (USBD_NORMAL_COMPLETION);
-} /* ubt_intr_start */
-
-/*
- * Process interrupt from USB device (We got data from interrupt pipe)
- */
-
-static void
-ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
-{
- ng_send_fn((node_p) p, NULL, ubt_intr_complete2, (void *) h, s);
- NG_NODE_UNREF((node_p) p);
-} /* ubt_intr_complete */
-
-static void
-ubt_intr_complete2(node_p node, hook_p hook, void *arg1, int arg2)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
- usbd_xfer_handle h = (usbd_xfer_handle) arg1;
- usbd_status s = (usbd_status) arg2;
- struct mbuf *m = NULL;
- ng_hci_event_pkt_t *hdr = NULL;
- int error;
-
- if (sc == NULL)
- return;
-
- KASSERT((sc->sc_flags & UBT_EVT_RECV), (
-"%s: %s - No interrupt request is pending\n",
- __func__, device_get_nameunit(sc->sc_dev)));
-
- sc->sc_flags &= ~UBT_EVT_RECV;
-
- m = sc->sc_intr_buffer;
- sc->sc_intr_buffer = NULL;
-
- hdr = mtod(m, ng_hci_event_pkt_t *);
-
- if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
- NG_UBT_INFO(
-"%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
-
- NG_FREE_M(m);
- return;
- }
-
- if (s == USBD_CANCELLED) {
- NG_UBT_INFO(
-"%s: %s - Interrupt xfer cancelled\n", __func__, device_get_nameunit(sc->sc_dev));
-
- NG_FREE_M(m);
- return;
- }
-
- if (s != USBD_NORMAL_COMPLETION) {
- NG_UBT_WARN(
-"%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
-
- if (s == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
-
- NG_UBT_STAT_IERROR(sc->sc_stat);
- NG_FREE_M(m);
-
- return; /* XXX FIXME we should restart after some delay */
- }
-
- NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
- m->m_pkthdr.len += h->actlen;
- m->m_len += h->actlen;
-
- NG_UBT_INFO(
-"%s: %s - Got %d bytes from interrupt pipe\n",
- __func__, device_get_nameunit(sc->sc_dev), h->actlen);
-
- if (m->m_pkthdr.len < sizeof(*hdr)) {
- NG_FREE_M(m);
- goto done;
- }
-
- if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
- NG_UBT_INFO(
-"%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
- __func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len,
- hdr->length);
-
- NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
-
- NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
- if (error != 0)
- NG_UBT_STAT_IERROR(sc->sc_stat);
- } else {
- NG_UBT_ERR(
-"%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
- __func__, device_get_nameunit(sc->sc_dev), hdr->length,
- m->m_pkthdr.len);
-
- NG_UBT_STAT_IERROR(sc->sc_stat);
- NG_FREE_M(m);
- }
-done:
- ubt_intr_start(sc);
-} /* ubt_intr_complete2 */
-
-/*
- * Start bulk-in USB transfer (ACL data). Must be called when node is locked
- */
-
-static usbd_status
-ubt_bulk_in_start(ubt_softc_p sc)
-{
- struct mbuf *m = NULL;
- usbd_status status;
-
- KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
-"%s: %s - Another bulk-in request is pending\n",
- __func__, device_get_nameunit(sc->sc_dev)));
-
- /* Allocate new mbuf cluster */
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return (USBD_NOMEM);
-
- MCLGET(m, M_DONTWAIT);
- if (!(m->m_flags & M_EXT)) {
- NG_FREE_M(m);
- return (USBD_NOMEM);
- }
-
- if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
- *mtod(m, uint8_t *) = NG_HCI_ACL_DATA_PKT;
- m->m_pkthdr.len = m->m_len = 1;
- } else
- m->m_pkthdr.len = m->m_len = 0;
-
- /* Initialize a bulk-in USB transfer and then schedule it */
- usbd_setup_xfer(
- sc->sc_bulk_in_xfer,
- sc->sc_bulk_in_pipe,
- (usbd_private_handle) sc->sc_node,
- (void *)(mtod(m, uint8_t *) + m->m_len),
- MCLBYTES - m->m_len,
- USBD_SHORT_XFER_OK,
- USBD_NO_TIMEOUT,
- ubt_bulk_in_complete);
-
- NG_NODE_REF(sc->sc_node);
-
- status = usbd_transfer(sc->sc_bulk_in_xfer);
- if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
- NG_UBT_ERR(
-"%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
- status);
-
- NG_NODE_UNREF(sc->sc_node);
-
- NG_FREE_M(m);
-
- return (status);
- }
-
- sc->sc_flags |= UBT_ACL_RECV;
- sc->sc_bulk_in_buffer = m;
-
- return (USBD_NORMAL_COMPLETION);
-} /* ubt_bulk_in_start */
-
-/*
- * USB bulk-in transfer callback
- */
-
-static void
-ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
-{
- ng_send_fn((node_p) p, NULL, ubt_bulk_in_complete2, (void *) h, s);
- NG_NODE_UNREF((node_p) p);
-} /* ubt_bulk_in_complete */
-
-static void
-ubt_bulk_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
- usbd_xfer_handle h = (usbd_xfer_handle) arg1;
- usbd_status s = (usbd_status) arg2;
- struct mbuf *m = NULL;
- ng_hci_acldata_pkt_t *hdr = NULL;
- int len;
-
- if (sc == NULL)
- return;
-
- KASSERT((sc->sc_flags & UBT_ACL_RECV), (
-"%s: %s - No bulk-in request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
-
- sc->sc_flags &= ~UBT_ACL_RECV;
-
- m = sc->sc_bulk_in_buffer;
- sc->sc_bulk_in_buffer = NULL;
-
- hdr = mtod(m, ng_hci_acldata_pkt_t *);
-
- if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
- NG_UBT_INFO(
-"%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
-
- NG_FREE_M(m);
- return;
- }
-
- if (s == USBD_CANCELLED) {
- NG_UBT_INFO(
-"%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
- __func__, device_get_nameunit(sc->sc_dev), sc->sc_bulk_in_pipe);
-
- NG_FREE_M(m);
- return;
- }
-
- if (s != USBD_NORMAL_COMPLETION) {
- NG_UBT_WARN(
-"%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
-
- if (s == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
-
- NG_UBT_STAT_IERROR(sc->sc_stat);
- NG_FREE_M(m);
-
- return; /* XXX FIXME we should restart after some delay */
- }
-
- NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
- m->m_pkthdr.len += h->actlen;
- m->m_len += h->actlen;
-
- NG_UBT_INFO(
-"%s: %s - Got %d bytes from bulk-in pipe\n",
- __func__, device_get_nameunit(sc->sc_dev), h->actlen);
-
- if (m->m_pkthdr.len < sizeof(*hdr)) {
- NG_FREE_M(m);
- goto done;
- }
-
- len = le16toh(hdr->length);
- if (len == m->m_pkthdr.len - sizeof(*hdr)) {
- NG_UBT_INFO(
-"%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
- __func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len, len);
-
- NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
-
- NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
- if (len != 0)
- NG_UBT_STAT_IERROR(sc->sc_stat);
- } else {
- NG_UBT_ERR(
-"%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
- __func__, device_get_nameunit(sc->sc_dev), len,
- m->m_pkthdr.len);
-
- NG_UBT_STAT_IERROR(sc->sc_stat);
- NG_FREE_M(m);
- }
-done:
- ubt_bulk_in_start(sc);
-} /* ubt_bulk_in_complete2 */
-
-/*
- * Start bulk-out USB transfer. Must be called with node locked
- */
-
-static usbd_status
-ubt_bulk_out_start(ubt_softc_p sc)
-{
- struct mbuf *m = NULL;
- usbd_status status;
-
- KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
-"%s: %s - Another bulk-out request is pending\n",
- __func__, device_get_nameunit(sc->sc_dev)));
-
- NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
- if (m == NULL) {
- NG_UBT_INFO(
-"%s: %s - ACL data queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
-
- return (USBD_NORMAL_COMPLETION);
- }
-
- /*
- * Check ACL data frame size and copy it back to linear USB
- * transfer buffer.
- */
-
- if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
- panic(
-"%s: %s - ACL data frame too big, size=%d, len=%d\n",
- __func__, device_get_nameunit(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
- m->m_pkthdr.len);
-
- m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
-
- /* Initialize a bulk-out USB transfer and then schedule it */
- usbd_setup_xfer(
- sc->sc_bulk_out_xfer,
- sc->sc_bulk_out_pipe,
- (usbd_private_handle) sc->sc_node,
- sc->sc_bulk_out_buffer,
- m->m_pkthdr.len,
- USBD_NO_COPY,
- USBD_DEFAULT_TIMEOUT, /* XXX */
- ubt_bulk_out_complete);
-
- NG_NODE_REF(sc->sc_node);
-
- status = usbd_transfer(sc->sc_bulk_out_xfer);
- if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
- NG_UBT_ERR(
-"%s: %s - Could not start bulk-out transfer. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
- status);
-
- NG_NODE_UNREF(sc->sc_node);
-
- NG_BT_MBUFQ_DROP(&sc->sc_aclq);
- NG_UBT_STAT_OERROR(sc->sc_stat);
-
- /* XXX FIXME should we try to start another transfer? */
- } else {
- NG_UBT_INFO(
-"%s: %s - Bulk-out transfer has been started, len=%d\n",
- __func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len);
-
- sc->sc_flags |= UBT_ACL_XMIT;
- status = USBD_NORMAL_COMPLETION;
- }
-
- NG_FREE_M(m);
-
- return (status);
-} /* ubt_bulk_out_start */
-
-/*
- * USB bulk-out transfer callback
- */
-
-static void
-ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
-{
- ng_send_fn((node_p) p, NULL, ubt_bulk_out_complete2, (void *) h, s);
- NG_NODE_UNREF((node_p) p);
-} /* ubt_bulk_out_complete */
-
-static void
-ubt_bulk_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
- usbd_xfer_handle h = (usbd_xfer_handle) arg1;
- usbd_status s = (usbd_status) arg2;
-
- if (sc == NULL)
- return;
-
- KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
-"%s: %s - No bulk-out request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
-
- sc->sc_flags &= ~UBT_ACL_XMIT;
-
- if (s == USBD_CANCELLED) {
- NG_UBT_INFO(
-"%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
- __func__, device_get_nameunit(sc->sc_dev), sc->sc_bulk_out_pipe);
-
- return;
- }
-
- if (s != USBD_NORMAL_COMPLETION) {
- NG_UBT_WARN(
-"%s: %s - Bulk-out xfer failed. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
-
- if (s == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
-
- NG_UBT_STAT_OERROR(sc->sc_stat);
- } else {
- NG_UBT_INFO(
-"%s: %s - Sent %d bytes to bulk-out pipe\n",
- __func__, device_get_nameunit(sc->sc_dev), h->actlen);
-
- NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
- NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
- }
-
- if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
- ubt_bulk_out_start(sc);
-} /* ubt_bulk_out_complete2 */
-
-/*
- * Start non-active Isochronous-in USB transfer.
- * Must be called with node locked
- */
-
-static usbd_status
-ubt_isoc_in_start_one(ubt_softc_p sc, int idx)
-{
- usbd_status status;
- int i;
-
- for (i = 0; i < NG_UBT_NFRAMES; i++)
- sc->sc_isoc_in[idx].frlen[i] = sc->sc_isoc_size;
-
- usbd_setup_isoc_xfer(
- sc->sc_isoc_in[idx].xfer,
- sc->sc_isoc_in_pipe,
- (usbd_private_handle) sc->sc_node,
- sc->sc_isoc_in[idx].frlen,
- NG_UBT_NFRAMES,
- USBD_NO_COPY | USBD_SHORT_XFER_OK,
- ubt_isoc_in_complete);
-
- NG_NODE_REF(sc->sc_node);
-
- status = usbd_transfer(sc->sc_isoc_in[idx].xfer);
- if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
- NG_UBT_ERR(
-"%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev),
- usbd_errstr(status), status);
-
- NG_NODE_UNREF(sc->sc_node);
- } else
- sc->sc_isoc_in[idx].active = 1;
-
- return (status);
-}
-
-/*
- * (Re)Start all non-active Isochronous-in USB transfers.
- * Must be called with node locked.
- */
-
-static usbd_status
-ubt_isoc_in_start(ubt_softc_p sc)
-{
- int i;
-
- for (i = 0; i < NG_UBT_NXFERS; i++)
- if (!sc->sc_isoc_in[i].active)
- ubt_isoc_in_start_one(sc, i);
-
- return (USBD_NORMAL_COMPLETION);
-} /* ubt_isoc_in_start */
-
-/*
- * USB isochronous transfer callback
- */
-
-static void
-ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
-{
- ng_send_fn((node_p) p, NULL, ubt_isoc_in_complete2, (void *) h, s);
- NG_NODE_UNREF((node_p) p);
-} /* ubt_isoc_in_complete */
-
-static void
-ubt_isoc_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
- usbd_xfer_handle h = (usbd_xfer_handle) arg1;
- usbd_status s = (usbd_status) arg2;
- int i, idx, want, got;
- struct mbuf *m;
-
- if (sc == NULL)
- return;
-
- /* Find xfer */
- idx = -1;
- for (i = 0; i < NG_UBT_NXFERS; i++) {
- if (sc->sc_isoc_in[i].xfer == h) {
- idx = i;
- break;
- }
- }
- KASSERT(idx != -1, (
-"%s:%s - Could not find isoc-in request\n",
- __func__, device_get_nameunit(sc->sc_dev)));
- KASSERT(sc->sc_isoc_in[idx].active, (
-"%s: %s - Isoc-in request is not active\n",
- __func__, device_get_nameunit(sc->sc_dev)));
-
- sc->sc_isoc_in[idx].active = 0;
-
- if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
- NG_UBT_INFO(
-"%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
-
- return;
- }
-
- /* Process xfer */
- if (s == USBD_CANCELLED) {
- NG_UBT_INFO(
-"%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
- __func__, device_get_nameunit(sc->sc_dev), sc->sc_isoc_in_pipe);
-
- return;
- }
-
- if (s != USBD_NORMAL_COMPLETION) {
- NG_UBT_WARN(
-"%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
-
- if (s == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
-
- NG_UBT_STAT_IERROR(sc->sc_stat);
-
- return; /* XXX FIXME we should restart after some delay */
- }
-
- if (h->actlen <= 0)
- goto done;
-
- NG_UBT_INFO(
-"%s: %s - Got %d bytes from isoc-in pipe\n",
- __func__, device_get_nameunit(sc->sc_dev), h->actlen);
-
- /*
- * Re-assemble SCO HCI frame
- */
-
- m = sc->sc_isoc_in_buffer;
- sc->sc_isoc_in_buffer = NULL;
-
- for (i = 0; i < NG_UBT_NFRAMES; i ++) {
- uint8_t *frame = (uint8_t *) sc->sc_isoc_in[idx].buffer +
- (i * sc->sc_isoc_size);
-
- while (sc->sc_isoc_in[idx].frlen[i] > 0) {
- int error, frlen = sc->sc_isoc_in[idx].frlen[i];
-
- if (m == NULL) {
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL) {
- goto done; /* XXX out of sync! */
- }
-
- MCLGET(m, M_DONTWAIT);
- if (!(m->m_flags & M_EXT)) {
- NG_FREE_M(m);
- goto done; /* XXX out of sync! */
- }
-
- if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
- *mtod(m, uint8_t *) = NG_HCI_SCO_DATA_PKT;
- m->m_pkthdr.len = m->m_len = got = 1;
- } else {
- m->m_pkthdr.len = m->m_len = got = 0;
- }
-
- want = sizeof(ng_hci_scodata_pkt_t);
- } else {
- got = m->m_pkthdr.len;
- want = sizeof(ng_hci_scodata_pkt_t);
-
- if (got >= want)
- want += mtod(m, ng_hci_scodata_pkt_t *)->length;
- }
-
- if (got + frlen > want)
- frlen = want - got;
-
- if (!m_append(m, frlen, frame)) {
- NG_FREE_M(m);
- goto done; /* XXX out of sync! */
- }
-
- got += frlen;
- frame += frlen;
- sc->sc_isoc_in[idx].frlen[i] -= frlen;
-
- if (got != want)
- continue;
-
- if (want == sizeof(ng_hci_scodata_pkt_t))
- want += mtod(m, ng_hci_scodata_pkt_t *)->length;
-
- if (got != want)
- continue;
-
- NG_UBT_INFO(
-"%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
- __func__, device_get_nameunit(sc->sc_dev),
- m->m_pkthdr.len,
- mtod(m, ng_hci_scodata_pkt_t *)->length);
-
- NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
- NG_UBT_STAT_BYTES_RECV(sc->sc_stat, m->m_pkthdr.len);
-
- NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
- if (error != 0)
- NG_UBT_STAT_IERROR(sc->sc_stat);
- }
- }
-
- sc->sc_isoc_in_buffer = m;
-done:
- ubt_isoc_in_start_one(sc, idx);
-} /* ubt_isoc_in_complete2 */
-
-/*
- * Start non-active isochronous-out USB transfer.
- * Must be called with node locked
- */
-
-static usbd_status
-ubt_isoc_out_start_one(ubt_softc_p sc, int idx)
-{
- int len, maxlen, size, nframes;
- struct mbuf *m;
- uint8_t *buffer;
- usbd_status status;
-
- /*
- * Fill the transfer buffer with data from the queue,
- * putting any leftover back on the queue
- */
-
- len = 0;
- maxlen = NG_UBT_NFRAMES * sc->sc_isoc_size;
- m = NULL;
- buffer = sc->sc_isoc_out[idx].buffer;
-
- while (maxlen > 0) {
- if (m == NULL) {
- NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
- if (m == NULL)
- break;
- }
-
- if (m->m_pkthdr.len > 0) {
- size = MIN(m->m_pkthdr.len, maxlen);
-
- m_copydata(m, 0, size, buffer);
- m_adj(m, size);
-
- buffer += size;
- len += size;
- maxlen -= size;
- }
-
- if (m->m_pkthdr.len == 0) {
- NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
- NG_FREE_M(m);
- }
- }
-
- if (m != NULL)
- NG_BT_MBUFQ_PREPEND(&sc->sc_scoq, m);
-
- if (len == 0)
- return (USBD_NORMAL_COMPLETION); /* nothing to send */
-
- NG_UBT_STAT_BYTES_SENT(sc->sc_stat, len);
-
- /* Calculate number of isoc frames and sizes */
- for (nframes = 0; len > 0; nframes ++) {
- size = MIN(sc->sc_isoc_size, len);
- sc->sc_isoc_out[idx].frlen[nframes] = size;
- len -= size;
- }
-
- /* Initialize a isoc-out USB transfer and then schedule it */
- usbd_setup_isoc_xfer(
- sc->sc_isoc_out[idx].xfer,
- sc->sc_isoc_out_pipe,
- (usbd_private_handle) sc->sc_node,
- sc->sc_isoc_out[idx].frlen,
- nframes,
- USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
- ubt_isoc_out_complete);
-
- NG_NODE_REF(sc->sc_node);
- sc->sc_isoc_out[idx].active = 1;
-
- status = usbd_transfer(sc->sc_isoc_out[idx].xfer);
- if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
- NG_UBT_ERR(
-"%s: %s - Could not start isoc-out transfer. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev),
- usbd_errstr(status), status);
-
- sc->sc_isoc_out[idx].active = 0;
- NG_NODE_UNREF(sc->sc_node);
-
- NG_UBT_STAT_OERROR(sc->sc_stat);
- } else {
- NG_UBT_INFO(
-"%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
- __func__, device_get_nameunit(sc->sc_dev), nframes,
- sc->sc_isoc_size);
- status = USBD_NORMAL_COMPLETION;
- }
-
- return (status);
-}
-
-/*
- * Start all non-active isochronous-out USB transfer.
- * Must be called with node locked
- */
-
-static usbd_status
-ubt_isoc_out_start(ubt_softc_p sc)
-{
- int i;
-
- for (i = 0; i < NG_UBT_NXFERS; i++) {
- if (sc->sc_isoc_out[i].active)
- continue;
-
- ubt_isoc_out_start_one(sc, i);
- }
-
- return (USBD_NORMAL_COMPLETION);
-} /* ubt_isoc_out_start */
-
-/*
- * USB isoc-out. transfer callback
- */
-
-static void
-ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
-{
- ng_send_fn((node_p) p, NULL, ubt_isoc_out_complete2, (void *) h, s);
- NG_NODE_UNREF((node_p) p);
-} /* ubt_isoc_out_complete */
-
-static void
-ubt_isoc_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
- usbd_xfer_handle h = (usbd_xfer_handle) arg1;
- usbd_status s = (usbd_status) arg2;
- int i, idx;
-
- if (sc == NULL)
- return;
-
- /* Find xfer */
- idx = -1;
- for (i = 0; i < NG_UBT_NXFERS; i++) {
- if (sc->sc_isoc_out[i].xfer == h) {
- idx = i;
- break;
- }
- }
- KASSERT(idx != -1, (
-"%s:%s - Could not find isoc-out request\n",
- __func__, device_get_nameunit(sc->sc_dev)));
- KASSERT(sc->sc_isoc_out[idx].active, (
-"%s: %s - Isoc-out request is not active\n",
- __func__, device_get_nameunit(sc->sc_dev)));
-
- sc->sc_isoc_out[idx].active = 0;
-
- /* Process xfer */
- if (s == USBD_CANCELLED) {
- NG_UBT_INFO(
-"%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
- __func__, device_get_nameunit(sc->sc_dev),
- sc->sc_isoc_out_pipe);
-
- return;
- }
-
- if (s != USBD_NORMAL_COMPLETION) {
- NG_UBT_WARN(
-"%s: %s - Isoc-out xfer failed. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
-
- if (s == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
-
- NG_UBT_STAT_OERROR(sc->sc_stat);
- } else {
- NG_UBT_INFO(
-"%s: %s - Sent %d bytes to isoc-out pipe\n",
- __func__, device_get_nameunit(sc->sc_dev), h->actlen);
-
-/* XXX FIXME NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
- NG_UBT_STAT_PCKTS_SENT(sc->sc_stat); */
- }
-
- if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
- ubt_isoc_out_start(sc);
-} /* ubt_isoc_out_complete2 */
-
-/*
- * Abort transfers on all USB pipes
- */
-
-static void
-ubt_reset(ubt_softc_p sc)
-{
- /* Interrupt */
- if (sc->sc_intr_pipe != NULL)
- usbd_abort_pipe(sc->sc_intr_pipe);
-
- /* Bulk-in/out */
- if (sc->sc_bulk_in_pipe != NULL)
- usbd_abort_pipe(sc->sc_bulk_in_pipe);
- if (sc->sc_bulk_out_pipe != NULL)
- usbd_abort_pipe(sc->sc_bulk_out_pipe);
-
- /* Isoc-in/out */
- if (sc->sc_isoc_in_pipe != NULL)
- usbd_abort_pipe(sc->sc_isoc_in_pipe);
- if (sc->sc_isoc_out_pipe != NULL)
- usbd_abort_pipe(sc->sc_isoc_out_pipe);
-
- /* Cleanup queues */
- NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
- NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
- NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
-} /* ubt_reset */
-
-/****************************************************************************
- ****************************************************************************
- ** Netgraph specific
- ****************************************************************************
- ****************************************************************************/
-
-/*
- * Netgraph node constructor. Do not allow to create node of this type.
- */
-
-static int
-ng_ubt_constructor(node_p node)
-{
- return (EINVAL);
-} /* ng_ubt_constructor */
-
-/*
- * Netgraph node destructor. Destroy node only when device has been detached
- */
-
-static int
-ng_ubt_shutdown(node_p node)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
-
- /* Let old node go */
- NG_NODE_SET_PRIVATE(node, NULL);
- NG_NODE_UNREF(node);
-
- if (sc == NULL)
- goto done;
-
- /* Create Netgraph node */
- if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
- printf("%s: Could not create Netgraph node\n",
- device_get_nameunit(sc->sc_dev));
- sc->sc_node = NULL;
- goto done;
- }
-
- /* Name node */
- if (ng_name_node(sc->sc_node, device_get_nameunit(sc->sc_dev)) != 0) {
- printf("%s: Could not name Netgraph node\n",
- device_get_nameunit(sc->sc_dev));
- NG_NODE_UNREF(sc->sc_node);
- sc->sc_node = NULL;
- goto done;
- }
-
- NG_NODE_SET_PRIVATE(sc->sc_node, sc);
- NG_NODE_FORCE_WRITER(sc->sc_node);
-done:
- return (0);
-} /* ng_ubt_shutdown */
-
-/*
- * Create new hook. There can only be one.
- */
-
-static int
-ng_ubt_newhook(node_p node, hook_p hook, char const *name)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
-
- if (strcmp(name, NG_UBT_HOOK) != 0)
- return (EINVAL);
-
- if (sc->sc_hook != NULL)
- return (EISCONN);
-
- sc->sc_hook = hook;
-
- return (0);
-} /* ng_ubt_newhook */
-
-/*
- * Connect hook. Start incoming USB transfers
- */
-
-static int
-ng_ubt_connect(hook_p hook)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
- usbd_status status;
-
- NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
-
- /* Start intr transfer */
- status = ubt_intr_start(sc);
- if (status != USBD_NORMAL_COMPLETION) {
- NG_UBT_ALERT(
-"%s: %s - Could not start interrupt transfer. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
- status);
- goto fail;
- }
-
- /* Start bulk-in transfer */
- status = ubt_bulk_in_start(sc);
- if (status != USBD_NORMAL_COMPLETION) {
- NG_UBT_ALERT(
-"%s: %s - Could not start bulk-in transfer. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
- status);
- goto fail;
- }
-
- /* Start isoc-in transfer */
- status = ubt_isoc_in_start(sc);
- if (status != USBD_NORMAL_COMPLETION) {
- NG_UBT_ALERT(
-"%s: %s - Could not start isoc-in transfer. %s (%d)\n",
- __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
- status);
- goto fail;
- }
-
- return (0);
-fail:
- ubt_reset(sc);
- sc->sc_hook = NULL;
-
- return (ENXIO);
-} /* ng_ubt_connect */
-
-/*
- * Disconnect hook
- */
-
-static int
-ng_ubt_disconnect(hook_p hook)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
-
- if (sc != NULL) {
- if (hook != sc->sc_hook)
- return (EINVAL);
-
- ubt_reset(sc);
- sc->sc_hook = NULL;
- }
-
- return (0);
-} /* ng_ubt_disconnect */
-
-/*
- * Process control message
- */
-
-static int
-ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
- struct ng_mesg *msg = NULL, *rsp = NULL;
- struct ng_bt_mbufq *q = NULL;
- int error = 0, queue, qlen;
-
- if (sc == NULL) {
- NG_FREE_ITEM(item);
- return (EHOSTDOWN);
- }
-
- NGI_GET_MSG(item, msg);
-
- switch (msg->header.typecookie) {
- case NGM_GENERIC_COOKIE:
- switch (msg->header.cmd) {
- case NGM_TEXT_STATUS:
- NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT);
- if (rsp == NULL)
- error = ENOMEM;
- else
- snprintf(rsp->data, NG_TEXTRESPONSE,
- "Hook: %s\n" \
- "Flags: %#x\n" \
- "Debug: %d\n" \
- "CMD queue: [have:%d,max:%d]\n" \
- "ACL queue: [have:%d,max:%d]\n" \
- "SCO queue: [have:%d,max:%d]",
- (sc->sc_hook != NULL)? NG_UBT_HOOK : "",
- sc->sc_flags,
- sc->sc_debug,
- NG_BT_MBUFQ_LEN(&sc->sc_cmdq),
- sc->sc_cmdq.maxlen,
- NG_BT_MBUFQ_LEN(&sc->sc_aclq),
- sc->sc_aclq.maxlen,
- NG_BT_MBUFQ_LEN(&sc->sc_scoq),
- sc->sc_scoq.maxlen);
- break;
-
- default:
- error = EINVAL;
- break;
- }
- break;
-
- case NGM_UBT_COOKIE:
- switch (msg->header.cmd) {
- case NGM_UBT_NODE_SET_DEBUG:
- if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep))
- error = EMSGSIZE;
- else
- sc->sc_debug =
- *((ng_ubt_node_debug_ep *)(msg->data));
- break;
-
- case NGM_UBT_NODE_GET_DEBUG:
- NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
- M_NOWAIT);
- if (rsp == NULL)
- error = ENOMEM;
- else
- *((ng_ubt_node_debug_ep *)(rsp->data)) =
- sc->sc_debug;
- break;
-
- case NGM_UBT_NODE_SET_QLEN:
- if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep))
- error = EMSGSIZE;
- else {
- queue = ((ng_ubt_node_qlen_ep *)
- (msg->data))->queue;
- qlen = ((ng_ubt_node_qlen_ep *)
- (msg->data))->qlen;
-
- if (qlen <= 0) {
- error = EINVAL;
- break;
- }
-
- switch (queue) {
- case NGM_UBT_NODE_QUEUE_CMD:
- q = &sc->sc_cmdq;
- break;
-
- case NGM_UBT_NODE_QUEUE_ACL:
- q = &sc->sc_aclq;
- break;
-
- case NGM_UBT_NODE_QUEUE_SCO:
- q = &sc->sc_scoq;
- break;
-
- default:
- q = NULL;
- error = EINVAL;
- break;
- }
-
- if (q != NULL)
- q->maxlen = qlen;
- }
- break;
-
- case NGM_UBT_NODE_GET_QLEN:
- if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
- error = EMSGSIZE;
- break;
- }
-
- queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue;
- switch (queue) {
- case NGM_UBT_NODE_QUEUE_CMD:
- q = &sc->sc_cmdq;
- break;
-
- case NGM_UBT_NODE_QUEUE_ACL:
- q = &sc->sc_aclq;
- break;
-
- case NGM_UBT_NODE_QUEUE_SCO:
- q = &sc->sc_scoq;
- break;
-
- default:
- q = NULL;
- error = EINVAL;
- break;
- }
-
- if (q != NULL) {
- NG_MKRESPONSE(rsp, msg,
- sizeof(ng_ubt_node_qlen_ep), M_NOWAIT);
- if (rsp == NULL) {
- error = ENOMEM;
- break;
- }
-
- ((ng_ubt_node_qlen_ep *)(rsp->data))->queue =
- queue;
- ((ng_ubt_node_qlen_ep *)(rsp->data))->qlen =
- q->maxlen;
- }
- break;
-
- case NGM_UBT_NODE_GET_STAT:
- NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
- M_NOWAIT);
- if (rsp == NULL)
- error = ENOMEM;
- else
- bcopy(&sc->sc_stat, rsp->data,
- sizeof(ng_ubt_node_stat_ep));
- break;
-
- case NGM_UBT_NODE_RESET_STAT:
- NG_UBT_STAT_RESET(sc->sc_stat);
- break;
-
- default:
- error = EINVAL;
- break;
- }
- break;
-
- default:
- error = EINVAL;
- break;
- }
-
- NG_RESPOND_MSG(error, node, item, rsp);
- NG_FREE_MSG(msg);
-
- return (error);
-} /* ng_ubt_rcvmsg */
-
-/*
- * Process data
- */
-
-static int
-ng_ubt_rcvdata(hook_p hook, item_p item)
-{
- ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
- struct mbuf *m = NULL;
- usbd_status (*f)(ubt_softc_p) = NULL;
- struct ng_bt_mbufq *q = NULL;
- int b, error = 0;
-
- if (sc == NULL) {
- error = EHOSTDOWN;
- goto done;
- }
-
- if (hook != sc->sc_hook) {
- error = EINVAL;
- goto done;
- }
-
- /* Deatch mbuf and get HCI frame type */
- NGI_GET_M(item, m);
-
- /* Process HCI frame */
- switch (*mtod(m, uint8_t *)) { /* XXX call m_pullup ? */
- case NG_HCI_CMD_PKT:
- f = ubt_request_start;
- q = &sc->sc_cmdq;
- b = UBT_CMD_XMIT;
- break;
-
- case NG_HCI_ACL_DATA_PKT:
- f = ubt_bulk_out_start;
- q = &sc->sc_aclq;
- b = UBT_ACL_XMIT;
- break;
-
- case NG_HCI_SCO_DATA_PKT:
- f = ubt_isoc_out_start;
- q = &sc->sc_scoq;
- b = UBT_SCO_XMIT;
- break;
-
- default:
- NG_UBT_ERR(
-"%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
- __func__, device_get_nameunit(sc->sc_dev), *mtod(m, uint8_t *),
- m->m_pkthdr.len);
-
- NG_FREE_M(m);
- error = EINVAL;
-
- goto done;
- /* NOT REACHED */
- }
-
- /* Loose frame type, if required */
- if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
- m_adj(m, sizeof(uint8_t));
-
- if (NG_BT_MBUFQ_FULL(q)) {
- NG_UBT_ERR(
-"%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
- __func__, device_get_nameunit(sc->sc_dev),
- *mtod(m, uint8_t *), m->m_pkthdr.len);
-
- NG_FREE_M(m);
- } else
- NG_BT_MBUFQ_ENQUEUE(q, m);
-
- if (!(sc->sc_flags & b))
- if ((*f)(sc) != USBD_NORMAL_COMPLETION)
- error = EIO;
-done:
- NG_FREE_ITEM(item);
-
- return (error);
-} /* ng_ubt_rcvdata */
-
diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h
deleted file mode 100644
index 6fdce0e..0000000
--- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * ng_ubt_var.h
- */
-
-/*-
- * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: ng_ubt_var.h,v 1.5 2005/10/31 17:57:44 max Exp $
- * $FreeBSD$
- */
-
-#ifndef _NG_UBT_VAR_H_
-#define _NG_UBT_VAR_H_
-
-/* pullup wrapper */
-#define NG_UBT_M_PULLUP(m, s) \
- do { \
- if ((m)->m_len < (s)) \
- (m) = m_pullup((m), (s)); \
- if ((m) == NULL) \
- NG_UBT_ALERT("%s: %s - m_pullup(%d) failed\n", \
- __func__, device_get_nameunit(sc->sc_dev), (s)); \
- } while (0)
-
-/* Debug printf's */
-#define NG_UBT_ALERT if (sc->sc_debug >= NG_UBT_ALERT_LEVEL) printf
-#define NG_UBT_ERR if (sc->sc_debug >= NG_UBT_ERR_LEVEL) printf
-#define NG_UBT_WARN if (sc->sc_debug >= NG_UBT_WARN_LEVEL) printf
-#define NG_UBT_INFO if (sc->sc_debug >= NG_UBT_INFO_LEVEL) printf
-
-/* Bluetooth USB control request type */
-#define UBT_HCI_REQUEST 0x20
-#define UBT_DEFAULT_QLEN 12
-
-/* Isoc transfers */
-#define NG_UBT_NXFERS 3 /* max xfers to queue */
-#define NG_UBT_NFRAMES 10 /* frames per xfer */
-
-struct ubt_isoc_xfer {
- usbd_xfer_handle xfer; /* isoc xfer */
- void *buffer; /* isoc buffer */
- uint16_t *frlen; /* isoc frame length */
- int active; /* is xfer active */
-};
-typedef struct ubt_isoc_xfer ubt_isoc_xfer_t;
-typedef struct ubt_isoc_xfer * ubt_isoc_xfer_p;
-
-/* USB device softc structure */
-struct ubt_softc {
- /* State */
- ng_ubt_node_debug_ep sc_debug; /* debug level */
- uint32_t sc_flags; /* device flags */
-#define UBT_NEED_FRAME_TYPE (1 << 0) /* device required frame type */
-#define UBT_HAVE_FRAME_TYPE UBT_NEED_FRAME_TYPE
-#define UBT_CMD_XMIT (1 << 1) /* CMD xmit in progress */
-#define UBT_ACL_XMIT (1 << 2) /* ACL xmit in progress */
-#define UBT_SCO_XMIT (1 << 3) /* SCO xmit in progress */
-#define UBT_EVT_RECV (1 << 4) /* EVN recv in progress */
-#define UBT_ACL_RECV (1 << 5) /* ACL recv in progress */
-#define UBT_SCO_RECV (1 << 6) /* SCO recv in progress */
-
- ng_ubt_node_stat_ep sc_stat; /* statistic */
-#define NG_UBT_STAT_PCKTS_SENT(s) (s).pckts_sent ++
-#define NG_UBT_STAT_BYTES_SENT(s, n) (s).bytes_sent += (n)
-#define NG_UBT_STAT_PCKTS_RECV(s) (s).pckts_recv ++
-#define NG_UBT_STAT_BYTES_RECV(s, n) (s).bytes_recv += (n)
-#define NG_UBT_STAT_OERROR(s) (s).oerrors ++
-#define NG_UBT_STAT_IERROR(s) (s).ierrors ++
-#define NG_UBT_STAT_RESET(s) bzero(&(s), sizeof((s)))
-
- /* USB device specific */
- device_t sc_dev; /* pointer back to USB device */
- usbd_device_handle sc_udev; /* USB device handle */
-
- usbd_interface_handle sc_iface0; /* USB interface 0 */
- usbd_interface_handle sc_iface1; /* USB interface 1 */
-
- /* Interrupt pipe (HCI events) */
- int sc_intr_ep; /* interrupt endpoint */
- usbd_pipe_handle sc_intr_pipe; /* interrupt pipe handle */
- usbd_xfer_handle sc_intr_xfer; /* intr xfer */
- struct mbuf *sc_intr_buffer; /* interrupt buffer */
-
- /* Control pipe (HCI commands) */
- usbd_xfer_handle sc_ctrl_xfer; /* control xfer handle */
- void *sc_ctrl_buffer; /* control buffer */
- struct ng_bt_mbufq sc_cmdq; /* HCI command queue */
-#define UBT_CTRL_BUFFER_SIZE \
- (sizeof(ng_hci_cmd_pkt_t) + NG_HCI_CMD_PKT_SIZE)
-
- /* Bulk in pipe (ACL data) */
- int sc_bulk_in_ep; /* bulk-in enpoint */
- usbd_pipe_handle sc_bulk_in_pipe; /* bulk-in pipe */
- usbd_xfer_handle sc_bulk_in_xfer; /* bulk-in xfer */
- struct mbuf *sc_bulk_in_buffer; /* bulk-in buffer */
-
- /* Bulk out pipe (ACL data) */
- int sc_bulk_out_ep; /* bulk-out endpoint */
- usbd_pipe_handle sc_bulk_out_pipe; /* bulk-out pipe */
- usbd_xfer_handle sc_bulk_out_xfer; /* bulk-out xfer */
- void *sc_bulk_out_buffer; /* bulk-out buffer */
- struct ng_bt_mbufq sc_aclq; /* ACL data queue */
-#define UBT_BULK_BUFFER_SIZE \
- MCLBYTES /* XXX should be big enough to hold one frame */
-
- /* Isoc. in pipe (SCO data) */
- struct mbuf *sc_isoc_in_buffer;
- int sc_isoc_in_ep; /* isoc-in endpoint */
- usbd_pipe_handle sc_isoc_in_pipe; /* isoc-in pipe */
- ubt_isoc_xfer_t sc_isoc_in[NG_UBT_NXFERS]; /* isoc-in xfers */
-
- /* Isoc. out pipe (SCO data) */
- int sc_isoc_out_ep; /* isoc-out endpoint */
- usbd_pipe_handle sc_isoc_out_pipe; /* isoc-out pipe */
- ubt_isoc_xfer_t sc_isoc_out[NG_UBT_NXFERS]; /* isoc-out xfers */
- struct ng_bt_mbufq sc_scoq; /* SCO data queue */
-
- int sc_isoc_size; /* max. size of isoc. packet */
-#define UBT_ISOC_BUFFER_SIZE \
- (sizeof(ng_hci_scodata_pkt_t) + NG_HCI_SCO_PKT_SIZE)
-
- /* Netgraph specific */
- node_p sc_node; /* pointer back to node */
- hook_p sc_hook; /* upstream hook */
-};
-typedef struct ubt_softc ubt_softc_t;
-typedef struct ubt_softc * ubt_softc_p;
-
-#endif /* ndef _NG_UBT_VAR_H_ */
-
diff --git a/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c b/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c
deleted file mode 100644
index e4b06ab..0000000
--- a/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * ubtbcmfw.c
- */
-
-/*-
- * Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: ubtbcmfw.c,v 1.3 2003/10/10 19:15:08 max Exp $
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/filio.h>
-#include <sys/fcntl.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/poll.h>
-#include <sys/proc.h>
-#include <sys/sysctl.h>
-#include <sys/uio.h>
-
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-
-#include "usbdevs.h"
-
-/*
- * Download firmware to BCM2033.
- */
-
-#define UBTBCMFW_CONFIG_NO 1 /* Config number */
-#define UBTBCMFW_IFACE_IDX 0 /* Control interface */
-#define UBTBCMFW_INTR_IN_EP 0x81 /* Fixed endpoint */
-#define UBTBCMFW_BULK_OUT_EP 0x02 /* Fixed endpoint */
-#define UBTBCMFW_INTR_IN UE_GET_ADDR(UBTBCMFW_INTR_IN_EP)
-#define UBTBCMFW_BULK_OUT UE_GET_ADDR(UBTBCMFW_BULK_OUT_EP)
-
-struct ubtbcmfw_softc {
- device_t sc_dev; /* base device */
- usbd_device_handle sc_udev; /* USB device handle */
- struct cdev *sc_ctrl_dev; /* control device */
- struct cdev *sc_intr_in_dev; /* interrupt device */
- struct cdev *sc_bulk_out_dev; /* bulk device */
- usbd_pipe_handle sc_intr_in_pipe; /* interrupt pipe */
- usbd_pipe_handle sc_bulk_out_pipe; /* bulk out pipe */
- int sc_flags;
-#define UBTBCMFW_CTRL_DEV (1 << 0)
-#define UBTBCMFW_INTR_IN_DEV (1 << 1)
-#define UBTBCMFW_BULK_OUT_DEV (1 << 2)
- int sc_refcnt;
- int sc_dying;
-};
-
-typedef struct ubtbcmfw_softc *ubtbcmfw_softc_p;
-
-/*
- * Device methods
- */
-
-#define UBTBCMFW_BSIZE 1024
-
-static d_open_t ubtbcmfw_open;
-static d_close_t ubtbcmfw_close;
-static d_read_t ubtbcmfw_read;
-static d_write_t ubtbcmfw_write;
-static d_ioctl_t ubtbcmfw_ioctl;
-static d_poll_t ubtbcmfw_poll;
-
-static struct cdevsw ubtbcmfw_cdevsw = {
- .d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
- .d_open = ubtbcmfw_open,
- .d_close = ubtbcmfw_close,
- .d_read = ubtbcmfw_read,
- .d_write = ubtbcmfw_write,
- .d_ioctl = ubtbcmfw_ioctl,
- .d_poll = ubtbcmfw_poll,
- .d_name = "ubtbcmfw",
-};
-
-/*
- * Module
- */
-
-static device_probe_t ubtbcmfw_match;
-static device_attach_t ubtbcmfw_attach;
-static device_detach_t ubtbcmfw_detach;
-
-static device_method_t ubtbcmfw_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, ubtbcmfw_match),
- DEVMETHOD(device_attach, ubtbcmfw_attach),
- DEVMETHOD(device_detach, ubtbcmfw_detach),
-
- { 0, 0 }
-};
-
-static driver_t ubtbcmfw_driver = {
- "ubtbcmfw",
- ubtbcmfw_methods,
- sizeof(struct ubtbcmfw_softc)
-};
-
-static devclass_t ubtbcmfw_devclass;
-
-MODULE_DEPEND(ubtbcmfw, usb, 1, 1, 1);
-DRIVER_MODULE(ubtbcmfw, uhub, ubtbcmfw_driver, ubtbcmfw_devclass,
- usbd_driver_load, 0);
-
-/*
- * Probe for a USB Bluetooth device
- */
-
-static int
-ubtbcmfw_match(device_t self)
-{
-#define USB_PRODUCT_BROADCOM_BCM2033NF 0x2033
- struct usb_attach_arg *uaa = device_get_ivars(self);
-
- if (uaa->iface != NULL)
- return (UMATCH_NONE);
-
- /* Match the boot device. */
- if (uaa->vendor == USB_VENDOR_BROADCOM &&
- uaa->product == USB_PRODUCT_BROADCOM_BCM2033NF)
- return (UMATCH_VENDOR_PRODUCT);
-
- return (UMATCH_NONE);
-}
-
-/*
- * Attach the device
- */
-
-static int
-ubtbcmfw_attach(device_t self)
-{
- struct ubtbcmfw_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
- usbd_interface_handle iface;
- usbd_status err;
-
- sc->sc_dev = self;
- sc->sc_udev = uaa->device;
-
- sc->sc_ctrl_dev = sc->sc_intr_in_dev = sc->sc_bulk_out_dev = NULL;
- sc->sc_intr_in_pipe = sc->sc_bulk_out_pipe = NULL;
- sc->sc_flags = sc->sc_refcnt = sc->sc_dying = 0;
-
- err = usbd_set_config_no(sc->sc_udev, UBTBCMFW_CONFIG_NO, 1);
- if (err) {
- printf("%s: setting config no failed. %s\n",
- device_get_nameunit(sc->sc_dev), usbd_errstr(err));
- goto bad;
- }
-
- err = usbd_device2interface_handle(sc->sc_udev, UBTBCMFW_IFACE_IDX,
- &iface);
- if (err) {
- printf("%s: getting interface handle failed. %s\n",
- device_get_nameunit(sc->sc_dev), usbd_errstr(err));
- goto bad;
- }
-
- /* Will be used as a bulk pipe */
- err = usbd_open_pipe(iface, UBTBCMFW_INTR_IN_EP, 0,
- &sc->sc_intr_in_pipe);
- if (err) {
- printf("%s: open intr in failed. %s\n",
- device_get_nameunit(sc->sc_dev), usbd_errstr(err));
- goto bad;
- }
-
- err = usbd_open_pipe(iface, UBTBCMFW_BULK_OUT_EP, 0,
- &sc->sc_bulk_out_pipe);
- if (err) {
- printf("%s: open bulk out failed. %s\n",
- device_get_nameunit(sc->sc_dev), usbd_errstr(err));
- goto bad;
- }
-
- /* Create device nodes */
- sc->sc_ctrl_dev = make_dev(&ubtbcmfw_cdevsw,
- 0, UID_ROOT, GID_OPERATOR, 0644,
- "%s", device_get_nameunit(sc->sc_dev));
- sc->sc_ctrl_dev->si_drv1 = sc;
-
- sc->sc_intr_in_dev = make_dev(&ubtbcmfw_cdevsw,
- UBTBCMFW_INTR_IN, UID_ROOT, GID_OPERATOR, 0644,
- "%s.%d", device_get_nameunit(sc->sc_dev), UBTBCMFW_INTR_IN);
- sc->sc_intr_in_dev->si_drv1 = sc;
-
- sc->sc_bulk_out_dev = make_dev(&ubtbcmfw_cdevsw,
- UBTBCMFW_BULK_OUT, UID_ROOT, GID_OPERATOR, 0644,
- "%s.%d", device_get_nameunit(sc->sc_dev), UBTBCMFW_BULK_OUT);
- sc->sc_bulk_out_dev->si_drv1 = sc;
-
- return 0;
-bad:
- ubtbcmfw_detach(self);
- return ENXIO;
-}
-
-/*
- * Detach the device
- */
-
-static int
-ubtbcmfw_detach(device_t self)
-{
- struct ubtbcmfw_softc *sc = device_get_softc(self);
-
- sc->sc_dying = 1;
- if (-- sc->sc_refcnt >= 0) {
- if (sc->sc_intr_in_pipe != NULL)
- usbd_abort_pipe(sc->sc_intr_in_pipe);
-
- if (sc->sc_bulk_out_pipe != NULL)
- usbd_abort_pipe(sc->sc_bulk_out_pipe);
-
- usb_detach_wait(sc->sc_dev);
- }
-
- /* Destroy device nodes */
- if (sc->sc_bulk_out_dev != NULL) {
- destroy_dev(sc->sc_bulk_out_dev);
- sc->sc_bulk_out_dev = NULL;
- }
-
- if (sc->sc_intr_in_dev != NULL) {
- destroy_dev(sc->sc_intr_in_dev);
- sc->sc_intr_in_dev = NULL;
- }
-
- if (sc->sc_ctrl_dev != NULL) {
- destroy_dev(sc->sc_ctrl_dev);
- sc->sc_ctrl_dev = NULL;
- }
-
- /* Close pipes */
- if (sc->sc_intr_in_pipe != NULL) {
- usbd_close_pipe(sc->sc_intr_in_pipe);
- sc->sc_intr_in_pipe = NULL;
- }
-
- if (sc->sc_bulk_out_pipe != NULL) {
- usbd_close_pipe(sc->sc_bulk_out_pipe);
- sc->sc_intr_in_pipe = NULL;
- }
-
- return (0);
-}
-
-/*
- * Open endpoint device
- * XXX FIXME softc locking
- */
-
-static int
-ubtbcmfw_open(struct cdev *dev, int flag, int mode, struct thread *p)
-{
- ubtbcmfw_softc_p sc = dev->si_drv1;
- int error = 0;
-
- if (sc->sc_dying)
- return (ENXIO);
-
- switch (dev2unit(dev)) {
- case USB_CONTROL_ENDPOINT:
- if (!(sc->sc_flags & UBTBCMFW_CTRL_DEV))
- sc->sc_flags |= UBTBCMFW_CTRL_DEV;
- else
- error = EBUSY;
- break;
-
- case UBTBCMFW_INTR_IN:
- if (!(sc->sc_flags & UBTBCMFW_INTR_IN_DEV)) {
- if (sc->sc_intr_in_pipe != NULL)
- sc->sc_flags |= UBTBCMFW_INTR_IN_DEV;
- else
- error = ENXIO;
- } else
- error = EBUSY;
- break;
-
- case UBTBCMFW_BULK_OUT:
- if (!(sc->sc_flags & UBTBCMFW_BULK_OUT_DEV)) {
- if (sc->sc_bulk_out_pipe != NULL)
- sc->sc_flags |= UBTBCMFW_BULK_OUT_DEV;
- else
- error = ENXIO;
- } else
- error = EBUSY;
- break;
-
- default:
- error = ENXIO;
- break;
- }
-
- return (error);
-}
-
-/*
- * Close endpoint device
- * XXX FIXME softc locking
- */
-
-static int
-ubtbcmfw_close(struct cdev *dev, int flag, int mode, struct thread *p)
-{
- ubtbcmfw_softc_p sc = dev->si_drv1;
-
- switch (dev2unit(dev)) {
- case USB_CONTROL_ENDPOINT:
- sc->sc_flags &= ~UBTBCMFW_CTRL_DEV;
- break;
-
- case UBTBCMFW_INTR_IN:
- if (sc->sc_intr_in_pipe != NULL)
- usbd_abort_pipe(sc->sc_intr_in_pipe);
-
- sc->sc_flags &= ~UBTBCMFW_INTR_IN_DEV;
- break;
-
- case UBTBCMFW_BULK_OUT:
- if (sc->sc_bulk_out_pipe != NULL)
- usbd_abort_pipe(sc->sc_bulk_out_pipe);
-
- sc->sc_flags &= ~UBTBCMFW_BULK_OUT_DEV;
- break;
- }
-
- return (0);
-}
-
-/*
- * Read from the endpoint device
- * XXX FIXME softc locking
- */
-
-static int
-ubtbcmfw_read(struct cdev *dev, struct uio *uio, int flag)
-{
- ubtbcmfw_softc_p sc = dev->si_drv1;
- u_int8_t buf[UBTBCMFW_BSIZE];
- usbd_xfer_handle xfer;
- usbd_status err;
- int n, tn, error = 0;
-
- if (sc->sc_dying)
- return (ENXIO);
-
- if (dev2unit(dev) != UBTBCMFW_INTR_IN)
- return (EOPNOTSUPP);
- if (sc->sc_intr_in_pipe == NULL)
- return (ENXIO);
-
- xfer = usbd_alloc_xfer(sc->sc_udev);
- if (xfer == NULL)
- return (ENOMEM);
-
- sc->sc_refcnt ++;
-
- while ((n = min(sizeof(buf), uio->uio_resid)) != 0) {
- tn = n;
- err = usbd_bulk_transfer(xfer, sc->sc_intr_in_pipe,
- USBD_SHORT_XFER_OK, USBD_DEFAULT_TIMEOUT,
- buf, &tn, "bcmrd");
- switch (err) {
- case USBD_NORMAL_COMPLETION:
- error = uiomove(buf, tn, uio);
- break;
-
- case USBD_INTERRUPTED:
- error = EINTR;
- break;
-
- case USBD_TIMEOUT:
- error = ETIMEDOUT;
- break;
-
- default:
- error = EIO;
- break;
- }
-
- if (error != 0 || tn < n)
- break;
- }
-
- usbd_free_xfer(xfer);
-
- if (-- sc->sc_refcnt < 0)
- usb_detach_wakeup(sc->sc_dev);
-
- return (error);
-}
-
-/*
- * Write into the endpoint device
- * XXX FIXME softc locking
- */
-
-static int
-ubtbcmfw_write(struct cdev *dev, struct uio *uio, int flag)
-{
- ubtbcmfw_softc_p sc = dev->si_drv1;
- u_int8_t buf[UBTBCMFW_BSIZE];
- usbd_xfer_handle xfer;
- usbd_status err;
- int n, error = 0;
-
- if (sc->sc_dying)
- return (ENXIO);
-
- if (dev2unit(dev) != UBTBCMFW_BULK_OUT)
- return (EOPNOTSUPP);
- if (sc->sc_bulk_out_pipe == NULL)
- return (ENXIO);
-
- xfer = usbd_alloc_xfer(sc->sc_udev);
- if (xfer == NULL)
- return (ENOMEM);
-
- sc->sc_refcnt ++;
-
- while ((n = min(sizeof(buf), uio->uio_resid)) != 0) {
- error = uiomove(buf, n, uio);
- if (error != 0)
- break;
-
- err = usbd_bulk_transfer(xfer, sc->sc_bulk_out_pipe,
- 0, USBD_DEFAULT_TIMEOUT, buf, &n, "bcmwr");
- switch (err) {
- case USBD_NORMAL_COMPLETION:
- break;
-
- case USBD_INTERRUPTED:
- error = EINTR;
- break;
-
- case USBD_TIMEOUT:
- error = ETIMEDOUT;
- break;
-
- default:
- error = EIO;
- break;
- }
-
- if (error != 0)
- break;
- }
-
- usbd_free_xfer(xfer);
-
- if (-- sc->sc_refcnt < 0)
- usb_detach_wakeup(sc->sc_dev);
-
- return (error);
-}
-
-/*
- * Process ioctl on the endpoint device
- * XXX FIXME softc locking
- */
-
-static int
-ubtbcmfw_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
- struct thread *p)
-{
- ubtbcmfw_softc_p sc = dev->si_drv1;
- int error = 0;
-
- if (sc->sc_dying)
- return (ENXIO);
-
- if (dev2unit(dev) != USB_CONTROL_ENDPOINT)
- return (EOPNOTSUPP);
-
- sc->sc_refcnt ++;
-
- switch (cmd) {
- case USB_GET_DEVICE_DESC:
- *(usb_device_descriptor_t *) data =
- *usbd_get_device_descriptor(sc->sc_udev);
- break;
-
- default:
- error = EINVAL;
- break;
- }
-
- if (-- sc->sc_refcnt < 0)
- usb_detach_wakeup(sc->sc_dev);
-
- return (error);
-}
-
-/*
- * Poll the endpoint device
- * XXX FIXME softc locking
- */
-
-static int
-ubtbcmfw_poll(struct cdev *dev, int events, struct thread *p)
-{
- ubtbcmfw_softc_p sc = dev->si_drv1;
- int revents = 0;
-
- switch (dev2unit(dev)) {
- case UBTBCMFW_INTR_IN:
- if (sc->sc_intr_in_pipe != NULL)
- revents |= events & (POLLIN | POLLRDNORM);
- else
- revents = ENXIO;
- break;
-
- case UBTBCMFW_BULK_OUT:
- if (sc->sc_bulk_out_pipe != NULL)
- revents |= events & (POLLOUT | POLLWRNORM);
- else
- revents = ENXIO;
- break;
-
- default:
- revents = EOPNOTSUPP;
- break;
- }
-
- return (revents);
-}
OpenPOWER on IntegriCloud