summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb2/bluetooth
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb2/bluetooth')
-rw-r--r--sys/dev/usb2/bluetooth/TODO.TXT18
-rw-r--r--sys/dev/usb2/bluetooth/ng_ubt2.c1720
-rw-r--r--sys/dev/usb2/bluetooth/ng_ubt2_var.h131
-rw-r--r--sys/dev/usb2/bluetooth/ubtbcmfw2.c431
-rw-r--r--sys/dev/usb2/bluetooth/usb2_bluetooth.c31
-rw-r--r--sys/dev/usb2/bluetooth/usb2_bluetooth.h30
6 files changed, 0 insertions, 2361 deletions
diff --git a/sys/dev/usb2/bluetooth/TODO.TXT b/sys/dev/usb2/bluetooth/TODO.TXT
deleted file mode 100644
index b0d6695..0000000
--- a/sys/dev/usb2/bluetooth/TODO.TXT
+++ /dev/null
@@ -1,18 +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
-
-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) Isochronous USB transfers (SCO data)
-
- Tried to fix isochrounous transfers, which are still disabled
- by default.
diff --git a/sys/dev/usb2/bluetooth/ng_ubt2.c b/sys/dev/usb2/bluetooth/ng_ubt2.c
deleted file mode 100644
index 3b1ba31..0000000
--- a/sys/dev/usb2/bluetooth/ng_ubt2.c
+++ /dev/null
@@ -1,1720 +0,0 @@
-/*
- * ng_ubt.c
- */
-
-/*-
- * Copyright (c) 2001-2009 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.16 2003/10/10 19:15:06 max Exp $
- * $FreeBSD$
- */
-
-/*
- * NOTE: ng_ubt2 driver has a split personality. On one side it is
- * a USB device driver and on the other it is a Netgraph node. This
- * driver will *NOT* create traditional /dev/ enties, only Netgraph
- * node.
- *
- * NOTE ON LOCKS USED: ng_ubt2 drives uses 2 locks (mutexes)
- *
- * 1) sc_if_mtx - lock for device's interface #0 and #1. This lock is used
- * by USB for any USB request going over device's interface #0 and #1,
- * i.e. interrupt, control, bulk and isoc. transfers.
- *
- * 2) sc_ng_mtx - this lock is used to protect shared (between USB, Netgraph
- * and Taskqueue) data, such as outgoing mbuf queues, task flags and hook
- * pointer. This lock *SHOULD NOT* be grabbed for a long time. In fact,
- * think of it as a spin lock.
- *
- * NOTE ON LOCKING STRATEGY: ng_ubt2 driver operates in 3 different contexts.
- *
- * 1) USB context. This is where all the USB related stuff happens. All
- * callbacks run in this context. All callbacks are called (by USB) with
- * appropriate interface lock held. It is (generally) allowed to grab
- * any additional locks.
- *
- * 2) Netgraph context. This is where all the Netgraph related stuff happens.
- * Since we mark node as WRITER, the Netgraph node will be "locked" (from
- * Netgraph point of view). Any variable that is only modified from the
- * Netgraph context does not require any additonal locking. It is generally
- * *NOT* allowed to grab *ANY* additional locks. Whatever you do, *DO NOT*
- * grab any lock in the Netgraph context that could cause de-scheduling of
- * the Netgraph thread for significant amount of time. In fact, the only
- * lock that is allowed in the Netgraph context is the sc_ng_mtx lock.
- * Also make sure that any code that is called from the Netgraph context
- * follows the rule above.
- *
- * 3) Taskqueue context. This is where ubt_task runs. Since we are generally
- * NOT allowed to grab any lock that could cause de-scheduling in the
- * Netgraph context, and, USB requires us to grab interface lock before
- * doing things with transfers, it is safer to transition from the Netgraph
- * context to the Taskqueue context before we can call into USB subsystem.
- *
- * So, to put everything together, the rules are as follows.
- * It is OK to call from the USB context or the Taskqueue context into
- * the Netgraph context (i.e. call NG_SEND_xxx functions). In other words
- * it is allowed to call into the Netgraph context with locks held.
- * Is it *NOT* OK to call from the Netgraph context into the USB context,
- * because USB requires us to grab interface locks, and, it is safer to
- * avoid it. So, to make things safer we set task flags to indicate which
- * actions we want to perform and schedule ubt_task which would run in the
- * Taskqueue context.
- * Is is OK to call from the Taskqueue context into the USB context,
- * and, ubt_task does just that (i.e. grabs appropriate interface locks
- * before calling into USB).
- * Access to the outgoing queues, task flags and hook pointer is
- * controlled by the sc_ng_mtx lock. It is an unavoidable evil. Again,
- * sc_ng_mtx should really be a spin lock (and it is very likely to an
- * equivalent of spin lock due to adaptive nature of freebsd mutexes).
- * All USB callbacks accept softc pointer as a private data. USB ensures
- * that this pointer is valid.
- */
-
-#include "usbdevs.h"
-#include <dev/usb2/include/usb2_standard.h>
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_error.h>
-
-#define USB_DEBUG_VAR usb2_debug
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_debug.h>
-#include <dev/usb2/core/usb2_parse.h>
-#include <dev/usb2/core/usb2_lookup.h>
-#include <dev/usb2/core/usb2_util.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_transfer.h>
-
-#include <sys/mbuf.h>
-#include <sys/taskqueue.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 <dev/usb2/bluetooth/usb2_bluetooth.h>
-#include <dev/usb2/bluetooth/ng_ubt2_var.h>
-
-static int ubt_modevent(module_t, int, void *);
-static device_probe_t ubt_probe;
-static device_attach_t ubt_attach;
-static device_detach_t ubt_detach;
-
-static void ubt_task_schedule(ubt_softc_p, int);
-static task_fn_t ubt_task;
-
-#define ubt_xfer_start(sc, i) usb2_transfer_start((sc)->sc_xfer[(i)])
-
-/* 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
-};
-
-/****************************************************************************
- ****************************************************************************
- ** USB specific
- ****************************************************************************
- ****************************************************************************/
-
-/* USB methods */
-static usb2_callback_t ubt_ctrl_write_callback;
-static usb2_callback_t ubt_intr_read_callback;
-static usb2_callback_t ubt_bulk_read_callback;
-static usb2_callback_t ubt_bulk_write_callback;
-static usb2_callback_t ubt_isoc_read_callback;
-static usb2_callback_t ubt_isoc_write_callback;
-
-static int ubt_fwd_mbuf_up(ubt_softc_p, struct mbuf **);
-static int ubt_isoc_read_one_frame(struct usb2_xfer *, int);
-
-/*
- * USB config
- *
- * The following desribes usb transfers that could be submitted on USB device.
- *
- * Interface 0 on the USB device must present the following endpoints
- * 1) Interrupt endpoint to receive HCI events
- * 2) Bulk IN endpoint to receive ACL data
- * 3) Bulk OUT endpoint to send ACL data
- *
- * Interface 1 on the USB device must present the following endpoints
- * 1) Isochronous IN endpoint to receive SCO data
- * 2) Isochronous OUT endpoint to send SCO data
- */
-
-static const struct usb2_config ubt_config[UBT_N_TRANSFER] =
-{
- /*
- * Interface #0
- */
-
- /* Outgoing bulk transfer - ACL packets */
- [UBT_IF_0_BULK_DT_WR] = {
- .type = UE_BULK,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_OUT,
- .if_index = 0,
- .mh.bufsize = UBT_BULK_WRITE_BUFFER_SIZE,
- .mh.flags = { .pipe_bof = 1, .force_short_xfer = 1, },
- .mh.callback = &ubt_bulk_write_callback,
- },
- /* Incoming bulk transfer - ACL packets */
- [UBT_IF_0_BULK_DT_RD] = {
- .type = UE_BULK,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_IN,
- .if_index = 0,
- .mh.bufsize = UBT_BULK_READ_BUFFER_SIZE,
- .mh.flags = { .pipe_bof = 1, .short_xfer_ok = 1, },
- .mh.callback = &ubt_bulk_read_callback,
- },
- /* Incoming interrupt transfer - HCI events */
- [UBT_IF_0_INTR_DT_RD] = {
- .type = UE_INTERRUPT,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_IN,
- .if_index = 0,
- .mh.flags = { .pipe_bof = 1, .short_xfer_ok = 1, },
- .mh.bufsize = UBT_INTR_BUFFER_SIZE,
- .mh.callback = &ubt_intr_read_callback,
- },
- /* Outgoing control transfer - HCI commands */
- [UBT_IF_0_CTRL_DT_WR] = {
- .type = UE_CONTROL,
- .endpoint = 0x00, /* control pipe */
- .direction = UE_DIR_ANY,
- .if_index = 0,
- .mh.bufsize = UBT_CTRL_BUFFER_SIZE,
- .mh.callback = &ubt_ctrl_write_callback,
- .mh.timeout = 5000, /* 5 seconds */
- },
-
- /*
- * Interface #1
- */
-
- /* Incoming isochronous transfer #1 - SCO packets */
- [UBT_IF_1_ISOC_DT_RD1] = {
- .type = UE_ISOCHRONOUS,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_IN,
- .if_index = 1,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UBT_ISOC_NFRAMES,
- .mh.flags = { .short_xfer_ok = 1, },
- .mh.callback = &ubt_isoc_read_callback,
- },
- /* Incoming isochronous transfer #2 - SCO packets */
- [UBT_IF_1_ISOC_DT_RD2] = {
- .type = UE_ISOCHRONOUS,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_IN,
- .if_index = 1,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UBT_ISOC_NFRAMES,
- .mh.flags = { .short_xfer_ok = 1, },
- .mh.callback = &ubt_isoc_read_callback,
- },
- /* Outgoing isochronous transfer #1 - SCO packets */
- [UBT_IF_1_ISOC_DT_WR1] = {
- .type = UE_ISOCHRONOUS,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_OUT,
- .if_index = 1,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UBT_ISOC_NFRAMES,
- .mh.flags = { .short_xfer_ok = 1, },
- .mh.callback = &ubt_isoc_write_callback,
- },
- /* Outgoing isochronous transfer #2 - SCO packets */
- [UBT_IF_1_ISOC_DT_WR2] = {
- .type = UE_ISOCHRONOUS,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_OUT,
- .if_index = 1,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UBT_ISOC_NFRAMES,
- .mh.flags = { .short_xfer_ok = 1, },
- .mh.callback = &ubt_isoc_write_callback,
- },
-};
-
-/*
- * If for some reason device should not be attached then put
- * VendorID/ProductID pair into the list below. The format is
- * as follows:
- *
- * { USB_VPI(VENDOR_ID, PRODUCT_ID, 0) },
- *
- * where VENDOR_ID and PRODUCT_ID are hex numbers.
- */
-
-static const struct usb2_device_id ubt_ignore_devs[] =
-{
- /* AVM USB Bluetooth-Adapter BlueFritz! v1.0 */
- { USB_VPI(USB_VENDOR_AVM, 0x2200, 0) },
-};
-
-/* List of supported bluetooth devices */
-static const struct usb2_device_id ubt_devs[] =
-{
- /* Generic Bluetooth class devices */
- { USB_IFACE_CLASS(UDCLASS_WIRELESS),
- USB_IFACE_SUBCLASS(UDSUBCLASS_RF),
- USB_IFACE_PROTOCOL(UDPROTO_BLUETOOTH) },
-
- /* AVM USB Bluetooth-Adapter BlueFritz! v2.0 */
- { USB_VPI(USB_VENDOR_AVM, 0x3800, 0) },
-};
-
-/*
- * Probe for a USB Bluetooth device.
- * USB context.
- */
-
-static int
-ubt_probe(device_t dev)
-{
- struct usb2_attach_arg *uaa = device_get_ivars(dev);
-
- if (uaa->usb2_mode != USB_MODE_HOST)
- return (ENXIO);
-
- if (uaa->info.bIfaceIndex != 0)
- return (ENXIO);
-
- if (uaa->use_generic == 0)
- return (ENXIO);
-
- if (usb2_lookup_id_by_uaa(ubt_ignore_devs,
- sizeof(ubt_ignore_devs), uaa) == 0)
- return (ENXIO);
-
- return (usb2_lookup_id_by_uaa(ubt_devs, sizeof(ubt_devs), uaa));
-} /* ubt_probe */
-
-/*
- * Attach the device.
- * USB context.
- */
-
-static int
-ubt_attach(device_t dev)
-{
- struct usb2_attach_arg *uaa = device_get_ivars(dev);
- struct ubt_softc *sc = device_get_softc(dev);
- struct usb2_endpoint_descriptor *ed;
- uint16_t wMaxPacketSize;
- uint8_t alt_index, i, j;
- uint8_t iface_index[2] = { 0, 1 };
-
- device_set_usb2_desc(dev);
-
- sc->sc_dev = dev;
- sc->sc_debug = NG_UBT_WARN_LEVEL;
-
- /*
- * Create Netgraph node
- */
-
- if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
- UBT_ALERT(sc, "could not create Netgraph node\n");
- return (ENXIO);
- }
-
- /* Name Netgraph node */
- if (ng_name_node(sc->sc_node, device_get_nameunit(dev)) != 0) {
- UBT_ALERT(sc, "could not name Netgraph node\n");
- NG_NODE_UNREF(sc->sc_node);
- return (ENXIO);
- }
- NG_NODE_SET_PRIVATE(sc->sc_node, sc);
- NG_NODE_FORCE_WRITER(sc->sc_node);
-
- /*
- * Initialize device softc structure
- */
-
- /* initialize locks */
- mtx_init(&sc->sc_ng_mtx, "ubt ng", NULL, MTX_DEF);
- mtx_init(&sc->sc_if_mtx, "ubt if", NULL, MTX_DEF | MTX_RECURSE);
-
- /* initialize packet queues */
- NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
- NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
- NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
-
- /* initialize glue task */
- TASK_INIT(&sc->sc_task, 0, ubt_task, sc);
-
- /*
- * 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.
- */
-
- /*
- * For interface #1 search alternate settings, and find
- * the descriptor with the largest wMaxPacketSize
- */
-
- wMaxPacketSize = 0;
- alt_index = 0;
- i = 0;
- j = 0;
-
- /* Search through all the descriptors looking for bidir mode */
- while (1) {
- uint16_t temp;
-
- ed = usb2_find_edesc(usb2_get_config_descriptor(uaa->device),
- 1, i, j);
- if (ed == NULL) {
- if (j != 0) {
- /* next interface */
- j = 0;
- i ++;
- continue;
- }
-
- break; /* end of interfaces */
- }
-
- temp = UGETW(ed->wMaxPacketSize);
- if (temp > wMaxPacketSize) {
- wMaxPacketSize = temp;
- alt_index = i;
- }
-
- j ++;
- }
-
- /* Set alt configuration on interface #1 only if we found it */
- if (wMaxPacketSize > 0 &&
- usb2_set_alt_interface_index(uaa->device, 1, alt_index)) {
- UBT_ALERT(sc, "could not set alternate setting %d " \
- "for interface 1!\n", alt_index);
- goto detach;
- }
-
- /* Setup transfers for both interfaces */
- if (usb2_transfer_setup(uaa->device, iface_index, sc->sc_xfer,
- ubt_config, UBT_N_TRANSFER, sc, &sc->sc_if_mtx)) {
- UBT_ALERT(sc, "could not allocate transfers\n");
- goto detach;
- }
-
- /* Claim all interfaces on the device */
- for (i = 1; usb2_get_iface(uaa->device, i) != NULL; i ++)
- usb2_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex);
-
- return (0); /* success */
-
-detach:
- ubt_detach(dev);
-
- return (ENXIO);
-} /* ubt_attach */
-
-/*
- * Detach the device.
- * USB context.
- */
-
-int
-ubt_detach(device_t dev)
-{
- struct ubt_softc *sc = device_get_softc(dev);
- node_p node = sc->sc_node;
-
- /* Destroy Netgraph node */
- if (node != NULL) {
- sc->sc_node = NULL;
- NG_NODE_REALLY_DIE(node);
- ng_rmnode_self(node);
- }
-
- /* Make sure ubt_task in gone */
- taskqueue_drain(taskqueue_swi, &sc->sc_task);
-
- /* Free USB transfers, if any */
- usb2_transfer_unsetup(sc->sc_xfer, UBT_N_TRANSFER);
-
- /* Destroy queues */
- UBT_NG_LOCK(sc);
- NG_BT_MBUFQ_DESTROY(&sc->sc_cmdq);
- NG_BT_MBUFQ_DESTROY(&sc->sc_aclq);
- NG_BT_MBUFQ_DESTROY(&sc->sc_scoq);
- UBT_NG_UNLOCK(sc);
-
- mtx_destroy(&sc->sc_if_mtx);
- mtx_destroy(&sc->sc_ng_mtx);
-
- return (0);
-} /* ubt_detach */
-
-/*
- * Called when outgoing control request (HCI command) has completed, i.e.
- * HCI command was sent to the device.
- * USB context.
- */
-
-static void
-ubt_ctrl_write_callback(struct usb2_xfer *xfer)
-{
- struct ubt_softc *sc = xfer->priv_sc;
- struct usb2_device_request req;
- struct mbuf *m;
-
- switch (USB_GET_STATE(xfer)) {
- case USB_ST_TRANSFERRED:
- UBT_INFO(sc, "sent %d bytes to control pipe\n", xfer->actlen);
- UBT_STAT_BYTES_SENT(sc, xfer->actlen);
- UBT_STAT_PCKTS_SENT(sc);
- /* FALLTHROUGH */
-
- case USB_ST_SETUP:
-send_next:
- /* Get next command mbuf, if any */
- UBT_NG_LOCK(sc);
- NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
- UBT_NG_UNLOCK(sc);
-
- if (m == NULL) {
- UBT_INFO(sc, "HCI command queue is empty\n");
- break; /* transfer complete */
- }
-
- /* 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);
-
- UBT_INFO(sc, "Sending control request, " \
- "bmRequestType=0x%02x, wLength=%d\n",
- req.bmRequestType, UGETW(req.wLength));
-
- usb2_copy_in(xfer->frbuffers, 0, &req, sizeof(req));
- usb2_m_copy_in(xfer->frbuffers + 1, 0, m, 0, m->m_pkthdr.len);
-
- xfer->frlengths[0] = sizeof(req);
- xfer->frlengths[1] = m->m_pkthdr.len;
- xfer->nframes = 2;
-
- NG_FREE_M(m);
-
- usb2_start_hardware(xfer);
- break;
-
- default: /* Error */
- if (xfer->error != USB_ERR_CANCELLED) {
- UBT_WARN(sc, "control transfer failed: %s\n",
- usb2_errstr(xfer->error));
-
- UBT_STAT_OERROR(sc);
- goto send_next;
- }
-
- /* transfer cancelled */
- break;
- }
-} /* ubt_ctrl_write_callback */
-
-/*
- * Called when incoming interrupt transfer (HCI event) has completed, i.e.
- * HCI event was received from the device.
- * USB context.
- */
-
-static void
-ubt_intr_read_callback(struct usb2_xfer *xfer)
-{
- struct ubt_softc *sc = xfer->priv_sc;
- struct mbuf *m;
- ng_hci_event_pkt_t *hdr;
-
- m = NULL;
-
- switch (USB_GET_STATE(xfer)) {
- case USB_ST_TRANSFERRED:
- /* Allocate a new mbuf */
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL) {
- UBT_STAT_IERROR(sc);
- goto submit_next;
- }
-
- MCLGET(m, M_DONTWAIT);
- if (!(m->m_flags & M_EXT)) {
- UBT_STAT_IERROR(sc);
- goto submit_next;
- }
-
- /* Add HCI packet type */
- *mtod(m, uint8_t *)= NG_HCI_EVENT_PKT;
- m->m_pkthdr.len = m->m_len = 1;
-
- if (xfer->actlen > MCLBYTES - 1)
- xfer->actlen = MCLBYTES - 1;
-
- usb2_copy_out(xfer->frbuffers, 0, mtod(m, uint8_t *) + 1,
- xfer->actlen);
- m->m_pkthdr.len += xfer->actlen;
- m->m_len += xfer->actlen;
-
- UBT_INFO(sc, "got %d bytes from interrupt pipe\n",
- xfer->actlen);
-
- /* Validate packet and send it up the stack */
- if (m->m_pkthdr.len < sizeof(*hdr)) {
- UBT_INFO(sc, "HCI event packet is too short\n");
-
- UBT_STAT_IERROR(sc);
- goto submit_next;
- }
-
- hdr = mtod(m, ng_hci_event_pkt_t *);
- if (hdr->length != (m->m_pkthdr.len - sizeof(*hdr))) {
- UBT_ERR(sc, "Invalid HCI event packet size, " \
- "length=%d, pktlen=%d\n",
- hdr->length, m->m_pkthdr.len);
-
- UBT_STAT_IERROR(sc);
- goto submit_next;
- }
-
- UBT_INFO(sc, "got complete HCI event frame, pktlen=%d, " \
- "length=%d\n", m->m_pkthdr.len, hdr->length);
-
- UBT_STAT_PCKTS_RECV(sc);
- UBT_STAT_BYTES_RECV(sc, m->m_pkthdr.len);
-
- ubt_fwd_mbuf_up(sc, &m);
- /* m == NULL at this point */
- /* FALLTHROUGH */
-
- case USB_ST_SETUP:
-submit_next:
- NG_FREE_M(m); /* checks for m != NULL */
-
- xfer->frlengths[0] = xfer->max_data_length;
- usb2_start_hardware(xfer);
- break;
-
- default: /* Error */
- if (xfer->error != USB_ERR_CANCELLED) {
- UBT_WARN(sc, "interrupt transfer failed: %s\n",
- usb2_errstr(xfer->error));
-
- /* Try to clear stall first */
- xfer->flags.stall_pipe = 1;
- goto submit_next;
- }
- /* transfer cancelled */
- break;
- }
-} /* ubt_intr_read_callback */
-
-/*
- * Called when incoming bulk transfer (ACL packet) has completed, i.e.
- * ACL packet was received from the device.
- * USB context.
- */
-
-static void
-ubt_bulk_read_callback(struct usb2_xfer *xfer)
-{
- struct ubt_softc *sc = xfer->priv_sc;
- struct mbuf *m;
- ng_hci_acldata_pkt_t *hdr;
- uint16_t len;
-
- m = NULL;
-
- switch (USB_GET_STATE(xfer)) {
- case USB_ST_TRANSFERRED:
- /* Allocate new mbuf */
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL) {
- UBT_STAT_IERROR(sc);
- goto submit_next;
- }
-
- MCLGET(m, M_DONTWAIT);
- if (!(m->m_flags & M_EXT)) {
- UBT_STAT_IERROR(sc);
- goto submit_next;
- }
-
- /* Add HCI packet type */
- *mtod(m, uint8_t *)= NG_HCI_ACL_DATA_PKT;
- m->m_pkthdr.len = m->m_len = 1;
-
- if (xfer->actlen > MCLBYTES - 1)
- xfer->actlen = MCLBYTES - 1;
-
- usb2_copy_out(xfer->frbuffers, 0, mtod(m, uint8_t *) + 1,
- xfer->actlen);
- m->m_pkthdr.len += xfer->actlen;
- m->m_len += xfer->actlen;
-
- UBT_INFO(sc, "got %d bytes from bulk-in pipe\n",
- xfer->actlen);
-
- /* Validate packet and send it up the stack */
- if (m->m_pkthdr.len < sizeof(*hdr)) {
- UBT_INFO(sc, "HCI ACL packet is too short\n");
-
- UBT_STAT_IERROR(sc);
- goto submit_next;
- }
-
- hdr = mtod(m, ng_hci_acldata_pkt_t *);
- len = le16toh(hdr->length);
- if (len != (m->m_pkthdr.len - sizeof(*hdr))) {
- UBT_ERR(sc, "Invalid ACL packet size, length=%d, " \
- "pktlen=%d\n", len, m->m_pkthdr.len);
-
- UBT_STAT_IERROR(sc);
- goto submit_next;
- }
-
- UBT_INFO(sc, "got complete ACL data packet, pktlen=%d, " \
- "length=%d\n", m->m_pkthdr.len, len);
-
- UBT_STAT_PCKTS_RECV(sc);
- UBT_STAT_BYTES_RECV(sc, m->m_pkthdr.len);
-
- ubt_fwd_mbuf_up(sc, &m);
- /* m == NULL at this point */
- /* FALLTHOUGH */
-
- case USB_ST_SETUP:
-submit_next:
- NG_FREE_M(m); /* checks for m != NULL */
-
- xfer->frlengths[0] = xfer->max_data_length;
- usb2_start_hardware(xfer);
- break;
-
- default: /* Error */
- if (xfer->error != USB_ERR_CANCELLED) {
- UBT_WARN(sc, "bulk-in transfer failed: %s\n",
- usb2_errstr(xfer->error));
-
- /* Try to clear stall first */
- xfer->flags.stall_pipe = 1;
- goto submit_next;
- }
- /* transfer cancelled */
- break;
- }
-} /* ubt_bulk_read_callback */
-
-/*
- * Called when outgoing bulk transfer (ACL packet) has completed, i.e.
- * ACL packet was sent to the device.
- * USB context.
- */
-
-static void
-ubt_bulk_write_callback(struct usb2_xfer *xfer)
-{
- struct ubt_softc *sc = xfer->priv_sc;
- struct mbuf *m;
-
- switch (USB_GET_STATE(xfer)) {
- case USB_ST_TRANSFERRED:
- UBT_INFO(sc, "sent %d bytes to bulk-out pipe\n", xfer->actlen);
- UBT_STAT_BYTES_SENT(sc, xfer->actlen);
- UBT_STAT_PCKTS_SENT(sc);
- /* FALLTHROUGH */
-
- case USB_ST_SETUP:
-send_next:
- /* Get next mbuf, if any */
- UBT_NG_LOCK(sc);
- NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
- UBT_NG_UNLOCK(sc);
-
- if (m == NULL) {
- UBT_INFO(sc, "ACL data queue is empty\n");
- break; /* transfer completed */
- }
-
- /*
- * Copy ACL data frame back to a linear USB transfer buffer
- * and schedule transfer
- */
-
- usb2_m_copy_in(xfer->frbuffers, 0, m, 0, m->m_pkthdr.len);
- xfer->frlengths[0] = m->m_pkthdr.len;
-
- UBT_INFO(sc, "bulk-out transfer has been started, len=%d\n",
- m->m_pkthdr.len);
-
- NG_FREE_M(m);
-
- usb2_start_hardware(xfer);
- break;
-
- default: /* Error */
- if (xfer->error != USB_ERR_CANCELLED) {
- UBT_WARN(sc, "bulk-out transfer failed: %s\n",
- usb2_errstr(xfer->error));
-
- UBT_STAT_OERROR(sc);
-
- /* try to clear stall first */
- xfer->flags.stall_pipe = 1;
- goto send_next;
- }
- /* transfer cancelled */
- break;
- }
-} /* ubt_bulk_write_callback */
-
-/*
- * Called when incoming isoc transfer (SCO packet) has completed, i.e.
- * SCO packet was received from the device.
- * USB context.
- */
-
-static void
-ubt_isoc_read_callback(struct usb2_xfer *xfer)
-{
- struct ubt_softc *sc = xfer->priv_sc;
- int n;
-
- switch (USB_GET_STATE(xfer)) {
- case USB_ST_TRANSFERRED:
- for (n = 0; n < xfer->nframes; n ++)
- if (ubt_isoc_read_one_frame(xfer, n) < 0)
- break;
- /* FALLTHROUGH */
-
- case USB_ST_SETUP:
-read_next:
- for (n = 0; n < xfer->nframes; n ++)
- xfer->frlengths[n] = xfer->max_frame_size;
-
- usb2_start_hardware(xfer);
- break;
-
- default: /* Error */
- if (xfer->error != USB_ERR_CANCELLED) {
- UBT_STAT_IERROR(sc);
- goto read_next;
- }
-
- /* transfer cancelled */
- break;
- }
-} /* ubt_isoc_read_callback */
-
-/*
- * Helper function. Called from ubt_isoc_read_callback() to read
- * SCO data from one frame.
- * USB context.
- */
-
-static int
-ubt_isoc_read_one_frame(struct usb2_xfer *xfer, int frame_no)
-{
- struct ubt_softc *sc = xfer->priv_sc;
- struct mbuf *m;
- int len, want, got;
-
- /* Get existing SCO reassembly buffer */
- m = sc->sc_isoc_in_buffer;
- sc->sc_isoc_in_buffer = NULL;
-
- /* While we have data in the frame */
- while ((len = xfer->frlengths[frame_no]) > 0) {
- if (m == NULL) {
- /* Start new reassembly buffer */
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL) {
- UBT_STAT_IERROR(sc);
- return (-1); /* XXX out of sync! */
- }
-
- MCLGET(m, M_DONTWAIT);
- if (!(m->m_flags & M_EXT)) {
- UBT_STAT_IERROR(sc);
- NG_FREE_M(m);
- return (-1); /* XXX out of sync! */
- }
-
- /* Expect SCO header */
- *mtod(m, uint8_t *) = NG_HCI_SCO_DATA_PKT;
- m->m_pkthdr.len = m->m_len = got = 1;
- want = sizeof(ng_hci_scodata_pkt_t);
- } else {
- /*
- * Check if we have SCO header and if so
- * adjust amount of data we want
- */
- got = m->m_pkthdr.len;
- want = sizeof(ng_hci_scodata_pkt_t);
-
- if (got >= want)
- want += mtod(m, ng_hci_scodata_pkt_t *)->length;
- }
-
- /* Append frame data to the SCO reassembly buffer */
- if (got + len > want)
- len = want - got;
-
- usb2_copy_out(xfer->frbuffers, frame_no * xfer->max_frame_size,
- mtod(m, uint8_t *) + m->m_pkthdr.len, len);
-
- m->m_pkthdr.len += len;
- m->m_len += len;
- xfer->frlengths[frame_no] -= len;
-
- /* Check if we got everything we wanted, if not - continue */
- if (got != want)
- continue;
-
- /* If we got here then we got complete SCO frame */
- UBT_INFO(sc, "got complete SCO data frame, pktlen=%d, " \
- "length=%d\n", m->m_pkthdr.len,
- mtod(m, ng_hci_scodata_pkt_t *)->length);
-
- UBT_STAT_PCKTS_RECV(sc);
- UBT_STAT_BYTES_RECV(sc, m->m_pkthdr.len);
-
- ubt_fwd_mbuf_up(sc, &m);
- /* m == NULL at this point */
- }
-
- /* Put SCO reassembly buffer back */
- sc->sc_isoc_in_buffer = m;
-
- return (0);
-} /* ubt_isoc_read_one_frame */
-
-/*
- * Called when outgoing isoc transfer (SCO packet) has completed, i.e.
- * SCO packet was sent to the device.
- * USB context.
- */
-
-static void
-ubt_isoc_write_callback(struct usb2_xfer *xfer)
-{
- struct ubt_softc *sc = xfer->priv_sc;
- struct mbuf *m;
- int n, space, offset;
-
- switch (USB_GET_STATE(xfer)) {
- case USB_ST_TRANSFERRED:
- UBT_INFO(sc, "sent %d bytes to isoc-out pipe\n", xfer->actlen);
- UBT_STAT_BYTES_SENT(sc, xfer->actlen);
- UBT_STAT_PCKTS_SENT(sc);
- /* FALLTHROUGH */
-
- case USB_ST_SETUP:
-send_next:
- offset = 0;
- space = xfer->max_frame_size * xfer->nframes;
- m = NULL;
-
- while (space > 0) {
- if (m == NULL) {
- UBT_NG_LOCK(sc);
- NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
- UBT_NG_UNLOCK(sc);
-
- if (m == NULL)
- break;
- }
-
- n = min(space, m->m_pkthdr.len);
- if (n > 0) {
- usb2_m_copy_in(xfer->frbuffers, offset, m,0, n);
- m_adj(m, n);
-
- offset += n;
- space -= n;
- }
-
- if (m->m_pkthdr.len == 0)
- NG_FREE_M(m); /* sets m = NULL */
- }
-
- /* Put whatever is left from mbuf back on queue */
- if (m != NULL) {
- UBT_NG_LOCK(sc);
- NG_BT_MBUFQ_PREPEND(&sc->sc_scoq, m);
- UBT_NG_UNLOCK(sc);
- }
-
- /*
- * Calculate sizes for isoc frames.
- * Note that offset could be 0 at this point (i.e. we have
- * nothing to send). That is fine, as we have isoc. transfers
- * going in both directions all the time. In this case it
- * would be just empty isoc. transfer.
- */
-
- for (n = 0; n < xfer->nframes; n ++) {
- xfer->frlengths[n] = min(offset, xfer->max_frame_size);
- offset -= xfer->frlengths[n];
- }
-
- usb2_start_hardware(xfer);
- break;
-
- default: /* Error */
- if (xfer->error != USB_ERR_CANCELLED) {
- UBT_STAT_OERROR(sc);
- goto send_next;
- }
-
- /* transfer cancelled */
- break;
- }
-}
-
-/*
- * Utility function to forward provided mbuf upstream (i.e. up the stack).
- * Modifies value of the mbuf pointer (sets it to NULL).
- * Save to call from any context.
- */
-
-static int
-ubt_fwd_mbuf_up(ubt_softc_p sc, struct mbuf **m)
-{
- hook_p hook;
- int error;
-
- /*
- * Close the race with Netgraph hook newhook/disconnect methods.
- * Save the hook pointer atomically. Two cases are possible:
- *
- * 1) The hook pointer is NULL. It means disconnect method got
- * there first. In this case we are done.
- *
- * 2) The hook pointer is not NULL. It means that hook pointer
- * could be either in valid or invalid (i.e. in the process
- * of disconnect) state. In any case grab an extra reference
- * to protect the hook pointer.
- *
- * It is ok to pass hook in invalid state to NG_SEND_DATA_ONLY() as
- * it checks for it. Drop extra reference after NG_SEND_DATA_ONLY().
- */
-
- UBT_NG_LOCK(sc);
- if ((hook = sc->sc_hook) != NULL)
- NG_HOOK_REF(hook);
- UBT_NG_UNLOCK(sc);
-
- if (hook == NULL) {
- NG_FREE_M(*m);
- return (ENETDOWN);
- }
-
- NG_SEND_DATA_ONLY(error, hook, *m);
- NG_HOOK_UNREF(hook);
-
- if (error != 0)
- UBT_STAT_IERROR(sc);
-
- return (error);
-} /* ubt_fwd_mbuf_up */
-
-/****************************************************************************
- ****************************************************************************
- ** Glue
- ****************************************************************************
- ****************************************************************************/
-
-/*
- * Schedule glue task. Should be called with sc_ng_mtx held.
- * Netgraph context.
- */
-
-static void
-ubt_task_schedule(ubt_softc_p sc, int action)
-{
- mtx_assert(&sc->sc_ng_mtx, MA_OWNED);
-
- /*
- * Try to handle corner case when "start all" and "stop all"
- * actions can both be set before task is executed.
- *
- * The rules are
- *
- * sc_task_flags action new sc_task_flags
- * ------------------------------------------------------
- * 0 start start
- * 0 stop stop
- * start start start
- * start stop stop
- * stop start stop|start
- * stop stop stop
- * stop|start start stop|start
- * stop|start stop stop
- */
-
- if (action != 0) {
- if ((action & UBT_FLAG_T_STOP_ALL) != 0)
- sc->sc_task_flags &= ~UBT_FLAG_T_START_ALL;
-
- sc->sc_task_flags |= action;
- }
-
- if (sc->sc_task_flags & UBT_FLAG_T_PENDING)
- return;
-
- if (taskqueue_enqueue(taskqueue_swi, &sc->sc_task) == 0) {
- sc->sc_task_flags |= UBT_FLAG_T_PENDING;
- return;
- }
-
- /* XXX: i think this should never happen */
-} /* ubt_task_schedule */
-
-/*
- * Glue task. Examines sc_task_flags and does things depending on it.
- * Taskqueue context.
- */
-
-static void
-ubt_task(void *context, int pending)
-{
- ubt_softc_p sc = context;
- int task_flags, i;
-
- UBT_NG_LOCK(sc);
- task_flags = sc->sc_task_flags;
- sc->sc_task_flags = 0;
- UBT_NG_UNLOCK(sc);
-
- /*
- * Stop all USB transfers synchronously.
- * Stop interface #0 and #1 transfers at the same time and in the
- * same loop. usb2_transfer_drain() will do appropriate locking.
- */
-
- if (task_flags & UBT_FLAG_T_STOP_ALL)
- for (i = 0; i < UBT_N_TRANSFER; i ++)
- usb2_transfer_drain(sc->sc_xfer[i]);
-
- /* Start incoming interrupt and bulk, and all isoc. USB transfers */
- if (task_flags & UBT_FLAG_T_START_ALL) {
- /*
- * Interface #0
- */
-
- mtx_lock(&sc->sc_if_mtx);
-
- ubt_xfer_start(sc, UBT_IF_0_INTR_DT_RD);
- ubt_xfer_start(sc, UBT_IF_0_BULK_DT_RD);
-
- /*
- * Interface #1
- * Start both read and write isoc. transfers by default.
- * Get them going all the time even if we have nothing
- * to send to avoid any delays.
- */
-
- ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_RD1);
- ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_RD2);
- ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_WR1);
- ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_WR2);
-
- mtx_unlock(&sc->sc_if_mtx);
- }
-
- /* Start outgoing control transfer */
- if (task_flags & UBT_FLAG_T_START_CTRL) {
- mtx_lock(&sc->sc_if_mtx);
- ubt_xfer_start(sc, UBT_IF_0_CTRL_DT_WR);
- mtx_unlock(&sc->sc_if_mtx);
- }
-
- /* Start outgoing bulk transfer */
- if (task_flags & UBT_FLAG_T_START_BULK) {
- mtx_lock(&sc->sc_if_mtx);
- ubt_xfer_start(sc, UBT_IF_0_BULK_DT_WR);
- mtx_unlock(&sc->sc_if_mtx);
- }
-} /* ubt_task */
-
-/****************************************************************************
- ****************************************************************************
- ** Netgraph specific
- ****************************************************************************
- ****************************************************************************/
-
-/*
- * Netgraph node constructor. Do not allow to create node of this type.
- * Netgraph context.
- */
-
-static int
-ng_ubt_constructor(node_p node)
-{
- return (EINVAL);
-} /* ng_ubt_constructor */
-
-/*
- * Netgraph node destructor. Destroy node only when device has been detached.
- * Netgraph context.
- */
-
-static int
-ng_ubt_shutdown(node_p node)
-{
- if (node->nd_flags & NGF_REALLY_DIE) {
- /*
- * We came here because the USB device is being
- * detached, so stop being persistant.
- */
- NG_NODE_SET_PRIVATE(node, NULL);
- NG_NODE_UNREF(node);
- } else
- NG_NODE_REVIVE(node); /* tell ng_rmnode we are persisant */
-
- return (0);
-} /* ng_ubt_shutdown */
-
-/*
- * Create new hook. There can only be one.
- * Netgraph context.
- */
-
-static int
-ng_ubt_newhook(node_p node, hook_p hook, char const *name)
-{
- struct ubt_softc *sc = NG_NODE_PRIVATE(node);
-
- if (strcmp(name, NG_UBT_HOOK) != 0)
- return (EINVAL);
-
- UBT_NG_LOCK(sc);
- if (sc->sc_hook != NULL) {
- UBT_NG_UNLOCK(sc);
-
- return (EISCONN);
- }
-
- sc->sc_hook = hook;
- UBT_NG_UNLOCK(sc);
-
- return (0);
-} /* ng_ubt_newhook */
-
-/*
- * Connect hook. Start incoming USB transfers.
- * Netgraph context.
- */
-
-static int
-ng_ubt_connect(hook_p hook)
-{
- struct ubt_softc *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
-
- NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
-
- UBT_NG_LOCK(sc);
- ubt_task_schedule(sc, UBT_FLAG_T_START_ALL);
- UBT_NG_UNLOCK(sc);
-
- return (0);
-} /* ng_ubt_connect */
-
-/*
- * Disconnect hook.
- * Netgraph context.
- */
-
-static int
-ng_ubt_disconnect(hook_p hook)
-{
- struct ubt_softc *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
-
- UBT_NG_LOCK(sc);
-
- if (hook != sc->sc_hook) {
- UBT_NG_UNLOCK(sc);
-
- return (EINVAL);
- }
-
- sc->sc_hook = NULL;
-
- /* Kick off task to stop all USB xfers */
- ubt_task_schedule(sc, UBT_FLAG_T_STOP_ALL);
-
- /* Drain queues */
- NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
- NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
- NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
-
- UBT_NG_UNLOCK(sc);
-
- return (0);
-} /* ng_ubt_disconnect */
-
-/*
- * Process control message.
- * Netgraph context.
- */
-
-static int
-ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
-{
- struct ubt_softc *sc = NG_NODE_PRIVATE(node);
- struct ng_mesg *msg, *rsp = NULL;
- struct ng_bt_mbufq *q;
- int error = 0, queue, qlen;
-
- 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;
- break;
- }
-
- snprintf(rsp->data, NG_TEXTRESPONSE,
- "Hook: %s\n" \
- "Task 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_task_flags,
- sc->sc_debug,
- sc->sc_cmdq.len,
- sc->sc_cmdq.maxlen,
- sc->sc_aclq.len,
- sc->sc_aclq.maxlen,
- sc->sc_scoq.len,
- 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;
- break;
- }
-
- 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;
- break;
- }
-
- *((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;
- break;
- }
-
- queue = ((ng_ubt_node_qlen_ep *) (msg->data))->queue;
- qlen = ((ng_ubt_node_qlen_ep *) (msg->data))->qlen;
-
- 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:
- error = EINVAL;
- goto done;
- /* NOT REACHED */
- }
-
- 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:
- error = EINVAL;
- goto done;
- /* NOT REACHED */
- }
-
- 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;
- break;
- }
-
- bcopy(&sc->sc_stat, rsp->data,
- sizeof(ng_ubt_node_stat_ep));
- break;
-
- case NGM_UBT_NODE_RESET_STAT:
- UBT_STAT_RESET(sc);
- break;
-
- default:
- error = EINVAL;
- break;
- }
- break;
-
- default:
- error = EINVAL;
- break;
- }
-done:
- NG_RESPOND_MSG(error, node, item, rsp);
- NG_FREE_MSG(msg);
-
- return (error);
-} /* ng_ubt_rcvmsg */
-
-/*
- * Process data.
- * Netgraph context.
- */
-
-static int
-ng_ubt_rcvdata(hook_p hook, item_p item)
-{
- struct ubt_softc *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
- struct mbuf *m;
- struct ng_bt_mbufq *q;
- int action, error = 0;
-
- if (hook != sc->sc_hook) {
- error = EINVAL;
- goto done;
- }
-
- /* Deatch mbuf and get HCI frame type */
- NGI_GET_M(item, m);
-
- /*
- * Minimal size of the HCI frame is 4 bytes: 1 byte frame type,
- * 2 bytes connection handle and at least 1 byte of length.
- * Panic on data frame that has size smaller than 4 bytes (it
- * should not happen)
- */
-
- if (m->m_pkthdr.len < 4)
- panic("HCI frame size is too small! pktlen=%d\n",
- m->m_pkthdr.len);
-
- /* Process HCI frame */
- switch (*mtod(m, uint8_t *)) { /* XXX call m_pullup ? */
- case NG_HCI_CMD_PKT:
- if (m->m_pkthdr.len - 1 > UBT_CTRL_BUFFER_SIZE)
- panic("HCI command frame size is too big! " \
- "buffer size=%zd, packet len=%d\n",
- UBT_CTRL_BUFFER_SIZE, m->m_pkthdr.len);
-
- q = &sc->sc_cmdq;
- action = UBT_FLAG_T_START_CTRL;
- break;
-
- case NG_HCI_ACL_DATA_PKT:
- if (m->m_pkthdr.len - 1 > UBT_BULK_WRITE_BUFFER_SIZE)
- panic("ACL data frame size is too big! " \
- "buffer size=%d, packet len=%d\n",
- UBT_BULK_WRITE_BUFFER_SIZE, m->m_pkthdr.len);
-
- q = &sc->sc_aclq;
- action = UBT_FLAG_T_START_BULK;
- break;
-
- case NG_HCI_SCO_DATA_PKT:
- q = &sc->sc_scoq;
- action = 0;
- break;
-
- default:
- UBT_ERR(sc, "Dropping unsupported HCI frame, type=0x%02x, " \
- "pktlen=%d\n", *mtod(m, uint8_t *), m->m_pkthdr.len);
-
- NG_FREE_M(m);
- error = EINVAL;
- goto done;
- /* NOT REACHED */
- }
-
- UBT_NG_LOCK(sc);
- if (NG_BT_MBUFQ_FULL(q)) {
- NG_BT_MBUFQ_DROP(q);
- UBT_NG_UNLOCK(sc);
-
- UBT_ERR(sc, "Dropping HCI frame 0x%02x, len=%d. Queue full\n",
- *mtod(m, uint8_t *), m->m_pkthdr.len);
-
- NG_FREE_M(m);
- } else {
- /* Loose HCI packet type, enqueue mbuf and kick off task */
- m_adj(m, sizeof(uint8_t));
- NG_BT_MBUFQ_ENQUEUE(q, m);
- ubt_task_schedule(sc, action);
- UBT_NG_UNLOCK(sc);
- }
-done:
- NG_FREE_ITEM(item);
-
- return (error);
-} /* ng_ubt_rcvdata */
-
-/****************************************************************************
- ****************************************************************************
- ** Module
- ****************************************************************************
- ****************************************************************************/
-
-/*
- * 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);
- break;
-
- case MOD_UNLOAD:
- error = ng_rmtype(&typestruct);
- break;
-
- default:
- error = EOPNOTSUPP;
- break;
- }
-
- return (error);
-} /* ubt_modevent */
-
-static devclass_t ubt_devclass;
-
-static device_method_t ubt_methods[] =
-{
- DEVMETHOD(device_probe, ubt_probe),
- DEVMETHOD(device_attach, ubt_attach),
- DEVMETHOD(device_detach, ubt_detach),
- { 0, 0 }
-};
-
-static driver_t ubt_driver =
-{
- .name = "ubt",
- .methods = ubt_methods,
- .size = sizeof(struct ubt_softc),
-};
-
-DRIVER_MODULE(ng_ubt, ushub, 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(ng_ubt, ng_hci, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION);
-MODULE_DEPEND(ng_ubt, usb2_bluetooth, 1, 1, 1);
-MODULE_DEPEND(ng_ubt, usb2_core, 1, 1, 1);
-
diff --git a/sys/dev/usb2/bluetooth/ng_ubt2_var.h b/sys/dev/usb2/bluetooth/ng_ubt2_var.h
deleted file mode 100644
index 721e2f1..0000000
--- a/sys/dev/usb2/bluetooth/ng_ubt2_var.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * ng_ubt_var.h
- */
-
-/*-
- * Copyright (c) 2001-2009 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.2 2003/03/22 23:44:36 max Exp $
- * $FreeBSD$
- */
-
-#ifndef _NG_UBT_VAR_H_
-#define _NG_UBT_VAR_H_ 1
-
-/* Debug printf's */
-#define UBT_DEBUG(level, sc, fmt, ...) \
-do { \
- if ((sc)->sc_debug >= (level)) \
- device_printf((sc)->sc_dev, "%s:%d: " fmt, \
- __FUNCTION__, __LINE__,## __VA_ARGS__); \
-} while (0)
-
-#define UBT_ALERT(...) UBT_DEBUG(NG_UBT_ALERT_LEVEL, __VA_ARGS__)
-#define UBT_ERR(...) UBT_DEBUG(NG_UBT_ERR_LEVEL, __VA_ARGS__)
-#define UBT_WARN(...) UBT_DEBUG(NG_UBT_WARN_LEVEL, __VA_ARGS__)
-#define UBT_INFO(...) UBT_DEBUG(NG_UBT_INFO_LEVEL, __VA_ARGS__)
-
-#define UBT_NG_LOCK(sc) mtx_lock(&(sc)->sc_ng_mtx)
-#define UBT_NG_UNLOCK(sc) mtx_unlock(&(sc)->sc_ng_mtx)
-
-/* Bluetooth USB control request type */
-#define UBT_HCI_REQUEST 0x20
-#define UBT_DEFAULT_QLEN 64
-#define UBT_ISOC_NFRAMES 32 /* should be factor of 8 */
-
-/* Bluetooth USB defines */
-enum {
- /* Interface #0 transfers */
- UBT_IF_0_BULK_DT_WR = 0,
- UBT_IF_0_BULK_DT_RD,
- UBT_IF_0_INTR_DT_RD,
- UBT_IF_0_CTRL_DT_WR,
-
- /* Interface #1 transfers */
- UBT_IF_1_ISOC_DT_RD1,
- UBT_IF_1_ISOC_DT_RD2,
- UBT_IF_1_ISOC_DT_WR1,
- UBT_IF_1_ISOC_DT_WR2,
-
- UBT_N_TRANSFER, /* total number of transfers */
-};
-
-/* USB device softc structure */
-struct ubt_softc {
- device_t sc_dev; /* for debug printf */
-
- /* State */
- ng_ubt_node_debug_ep sc_debug; /* debug level */
-
- ng_ubt_node_stat_ep sc_stat; /* statistic */
-#define UBT_STAT_PCKTS_SENT(sc) (sc)->sc_stat.pckts_sent ++
-#define UBT_STAT_BYTES_SENT(sc, n) (sc)->sc_stat.bytes_sent += (n)
-#define UBT_STAT_PCKTS_RECV(sc) (sc)->sc_stat.pckts_recv ++
-#define UBT_STAT_BYTES_RECV(sc, n) (sc)->sc_stat.bytes_recv += (n)
-#define UBT_STAT_OERROR(sc) (sc)->sc_stat.oerrors ++
-#define UBT_STAT_IERROR(sc) (sc)->sc_stat.ierrors ++
-#define UBT_STAT_RESET(sc) bzero(&(sc)->sc_stat, sizeof((sc)->sc_stat))
-
- /* USB device specific */
- struct mtx sc_if_mtx; /* interfaces lock */
- struct usb2_xfer *sc_xfer[UBT_N_TRANSFER];
-
- struct mtx sc_ng_mtx; /* lock for shared NG data */
-
- /* HCI commands */
- struct ng_bt_mbufq sc_cmdq; /* HCI command queue */
-#define UBT_CTRL_BUFFER_SIZE (sizeof(struct usb2_device_request) + \
- sizeof(ng_hci_cmd_pkt_t) + NG_HCI_CMD_PKT_SIZE)
-#define UBT_INTR_BUFFER_SIZE (MCLBYTES-1) /* reserve 1 byte for ID-tag */
-
- /* ACL data */
- struct ng_bt_mbufq sc_aclq; /* ACL data queue */
-#define UBT_BULK_READ_BUFFER_SIZE (MCLBYTES-1) /* reserve 1 byte for ID-tag */
-#define UBT_BULK_WRITE_BUFFER_SIZE (MCLBYTES)
-
- /* SCO data */
- struct ng_bt_mbufq sc_scoq; /* SCO data queue */
- struct mbuf *sc_isoc_in_buffer; /* SCO reassembly buffer */
-
- /* Netgraph specific */
- node_p sc_node; /* pointer back to node */
- hook_p sc_hook; /* upstream hook */
-
- /* Glue */
- int sc_task_flags; /* task flags */
-#define UBT_FLAG_T_PENDING (1 << 0) /* task pending */
-#define UBT_FLAG_T_STOP_ALL (1 << 1) /* stop all xfers */
-#define UBT_FLAG_T_START_ALL (1 << 2) /* start all read and isoc
- write xfers */
-#define UBT_FLAG_T_START_CTRL (1 << 3) /* start control xfer (write) */
-#define UBT_FLAG_T_START_BULK (1 << 4) /* start bulk xfer (write) */
-
- struct task sc_task;
-};
-typedef struct ubt_softc ubt_softc_t;
-typedef struct ubt_softc * ubt_softc_p;
-
-#endif /* ndef _NG_UBT_VAR_H_ */
-
diff --git a/sys/dev/usb2/bluetooth/ubtbcmfw2.c b/sys/dev/usb2/bluetooth/ubtbcmfw2.c
deleted file mode 100644
index 91735ed..0000000
--- a/sys/dev/usb2/bluetooth/ubtbcmfw2.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * ubtbcmfw.c
- */
-
-/*-
- * Copyright (c) 2003-2009 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 "usbdevs.h"
-#include <dev/usb2/include/usb2_standard.h>
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_error.h>
-#include <dev/usb2/include/usb2_ioctl.h>
-
-#define USB_DEBUG_VAR usb2_debug
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_debug.h>
-#include <dev/usb2/core/usb2_parse.h>
-#include <dev/usb2/core/usb2_lookup.h>
-#include <dev/usb2/core/usb2_util.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_mbuf.h>
-#include <dev/usb2/core/usb2_dev.h>
-
-/*
- * Download firmware to BCM2033.
- */
-
-#define UBTBCMFW_CONFIG_NO 1 /* Config number */
-#define UBTBCMFW_IFACE_IDX 0 /* Control interface */
-
-#define UBTBCMFW_BSIZE 1024
-#define UBTBCMFW_IFQ_MAXLEN 2
-
-enum {
- UBTBCMFW_BULK_DT_WR = 0,
- UBTBCMFW_INTR_DT_RD,
- UBTBCMFW_N_TRANSFER,
-};
-
-struct ubtbcmfw_softc {
- struct usb2_device *sc_udev;
- struct mtx sc_mtx;
- struct usb2_xfer *sc_xfer[UBTBCMFW_N_TRANSFER];
- struct usb2_fifo_sc sc_fifo;
-};
-
-/*
- * Prototypes
- */
-
-static device_probe_t ubtbcmfw_probe;
-static device_attach_t ubtbcmfw_attach;
-static device_detach_t ubtbcmfw_detach;
-
-static usb2_callback_t ubtbcmfw_write_callback;
-static usb2_callback_t ubtbcmfw_read_callback;
-
-static usb2_fifo_close_t ubtbcmfw_close;
-static usb2_fifo_cmd_t ubtbcmfw_start_read;
-static usb2_fifo_cmd_t ubtbcmfw_start_write;
-static usb2_fifo_cmd_t ubtbcmfw_stop_read;
-static usb2_fifo_cmd_t ubtbcmfw_stop_write;
-static usb2_fifo_ioctl_t ubtbcmfw_ioctl;
-static usb2_fifo_open_t ubtbcmfw_open;
-
-static struct usb2_fifo_methods ubtbcmfw_fifo_methods =
-{
- .f_close = &ubtbcmfw_close,
- .f_ioctl = &ubtbcmfw_ioctl,
- .f_open = &ubtbcmfw_open,
- .f_start_read = &ubtbcmfw_start_read,
- .f_start_write = &ubtbcmfw_start_write,
- .f_stop_read = &ubtbcmfw_stop_read,
- .f_stop_write = &ubtbcmfw_stop_write,
- .basename[0] = "ubtbcmfw",
- .basename[1] = "ubtbcmfw",
- .basename[2] = "ubtbcmfw",
- .postfix[0] = "",
- .postfix[1] = ".1",
- .postfix[2] = ".2",
-};
-
-/*
- * Device's config structure
- */
-
-static const struct usb2_config ubtbcmfw_config[UBTBCMFW_N_TRANSFER] =
-{
- [UBTBCMFW_BULK_DT_WR] = {
- .type = UE_BULK,
- .endpoint = 0x02, /* fixed */
- .direction = UE_DIR_OUT,
- .if_index = UBTBCMFW_IFACE_IDX,
- .mh.bufsize = UBTBCMFW_BSIZE,
- .mh.flags = { .pipe_bof = 1, .force_short_xfer = 1,
- .proxy_buffer = 1, },
- .mh.callback = &ubtbcmfw_write_callback,
- },
-
- [UBTBCMFW_INTR_DT_RD] = {
- .type = UE_INTERRUPT,
- .endpoint = 0x01, /* fixed */
- .direction = UE_DIR_IN,
- .if_index = UBTBCMFW_IFACE_IDX,
- .mh.bufsize = UBTBCMFW_BSIZE,
- .mh.flags = { .pipe_bof = 1, .short_xfer_ok = 1,
- .proxy_buffer = 1, },
- .mh.callback = &ubtbcmfw_read_callback,
- },
-};
-
-/*
- * Module
- */
-
-static devclass_t ubtbcmfw_devclass;
-
-static device_method_t ubtbcmfw_methods[] =
-{
- DEVMETHOD(device_probe, ubtbcmfw_probe),
- DEVMETHOD(device_attach, ubtbcmfw_attach),
- DEVMETHOD(device_detach, ubtbcmfw_detach),
- {0, 0}
-};
-
-static driver_t ubtbcmfw_driver =
-{
- .name = "ubtbcmfw",
- .methods = ubtbcmfw_methods,
- .size = sizeof(struct ubtbcmfw_softc),
-};
-
-DRIVER_MODULE(ubtbcmfw, ushub, ubtbcmfw_driver, ubtbcmfw_devclass, NULL, 0);
-MODULE_DEPEND(ubtbcmfw, usb2_bluetooth, 1, 1, 1);
-MODULE_DEPEND(ubtbcmfw, usb2_core, 1, 1, 1);
-
-/*
- * Probe for a USB Bluetooth device
- */
-
-static int
-ubtbcmfw_probe(device_t dev)
-{
- const struct usb2_device_id devs[] = {
- /* Broadcom BCM2033 devices only */
- { USB_VPI(USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM2033, 0) },
- };
-
- struct usb2_attach_arg *uaa = device_get_ivars(dev);
-
- if (uaa->usb2_mode != USB_MODE_HOST)
- return (ENXIO);
-
- if (uaa->info.bIfaceIndex != 0)
- return (ENXIO);
-
- return (usb2_lookup_id_by_uaa(devs, sizeof(devs), uaa));
-} /* ubtbcmfw_probe */
-
-/*
- * Attach the device
- */
-
-static int
-ubtbcmfw_attach(device_t dev)
-{
- struct usb2_attach_arg *uaa = device_get_ivars(dev);
- struct ubtbcmfw_softc *sc = device_get_softc(dev);
- uint8_t iface_index;
- int error;
-
- sc->sc_udev = uaa->device;
-
- device_set_usb2_desc(dev);
-
- mtx_init(&sc->sc_mtx, "ubtbcmfw lock", NULL, MTX_DEF | MTX_RECURSE);
-
- iface_index = UBTBCMFW_IFACE_IDX;
- error = usb2_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
- ubtbcmfw_config, UBTBCMFW_N_TRANSFER,
- sc, &sc->sc_mtx);
- if (error != 0) {
- device_printf(dev, "allocating USB transfers failed. %s\n",
- usb2_errstr(error));
- goto detach;
- }
-
- /* Set interface permissions */
- usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex,
- UID_ROOT, GID_OPERATOR, 0644);
-
- error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
- &ubtbcmfw_fifo_methods, &sc->sc_fifo,
- device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex);
- if (error != 0) {
- device_printf(dev, "could not attach fifo. %s\n",
- usb2_errstr(error));
- goto detach;
- }
-
- return (0); /* success */
-
-detach:
- ubtbcmfw_detach(dev);
-
- return (ENXIO); /* failure */
-} /* ubtbcmfw_attach */
-
-/*
- * Detach the device
- */
-
-static int
-ubtbcmfw_detach(device_t dev)
-{
- struct ubtbcmfw_softc *sc = device_get_softc(dev);
-
- usb2_fifo_detach(&sc->sc_fifo);
-
- usb2_transfer_unsetup(sc->sc_xfer, UBTBCMFW_N_TRANSFER);
-
- mtx_destroy(&sc->sc_mtx);
-
- return (0);
-} /* ubtbcmfw_detach */
-
-/*
- * USB write callback
- */
-
-static void
-ubtbcmfw_write_callback(struct usb2_xfer *xfer)
-{
- struct ubtbcmfw_softc *sc = xfer->priv_sc;
- struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_TX];
- uint32_t actlen;
-
- switch (USB_GET_STATE(xfer)) {
- case USB_ST_SETUP:
- case USB_ST_TRANSFERRED:
-setup_next:
- if (usb2_fifo_get_data(f, xfer->frbuffers, 0,
- xfer->max_data_length, &actlen, 0)) {
- xfer->frlengths[0] = actlen;
- usb2_start_hardware(xfer);
- }
- break;
-
- default: /* Error */
- if (xfer->error != USB_ERR_CANCELLED) {
- /* try to clear stall first */
- xfer->flags.stall_pipe = 1;
- goto setup_next;
- }
- break;
- }
-} /* ubtbcmfw_write_callback */
-
-/*
- * USB read callback
- */
-
-static void
-ubtbcmfw_read_callback(struct usb2_xfer *xfer)
-{
- struct ubtbcmfw_softc *sc = xfer->priv_sc;
- struct usb2_fifo *fifo = sc->sc_fifo.fp[USB_FIFO_RX];
-
- switch (USB_GET_STATE(xfer)) {
- case USB_ST_TRANSFERRED:
- usb2_fifo_put_data(fifo, xfer->frbuffers, 0, xfer->actlen, 1);
- /* FALLTHROUGH */
-
- case USB_ST_SETUP:
-setup_next:
- if (usb2_fifo_put_bytes_max(fifo) > 0) {
- xfer->frlengths[0] = xfer->max_data_length;
- usb2_start_hardware(xfer);
- }
- break;
-
- default: /* Error */
- if (xfer->error != USB_ERR_CANCELLED) {
- /* try to clear stall first */
- xfer->flags.stall_pipe = 1;
- goto setup_next;
- }
- break;
- }
-} /* ubtbcmfw_read_callback */
-
-/*
- * Called when we about to start read()ing from the device
- */
-
-static void
-ubtbcmfw_start_read(struct usb2_fifo *fifo)
-{
- struct ubtbcmfw_softc *sc = fifo->priv_sc0;
-
- usb2_transfer_start(sc->sc_xfer[UBTBCMFW_INTR_DT_RD]);
-} /* ubtbcmfw_start_read */
-
-/*
- * Called when we about to stop reading (i.e. closing fifo)
- */
-
-static void
-ubtbcmfw_stop_read(struct usb2_fifo *fifo)
-{
- struct ubtbcmfw_softc *sc = fifo->priv_sc0;
-
- usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_INTR_DT_RD]);
-} /* ubtbcmfw_stop_read */
-
-/*
- * Called when we about to start write()ing to the device, poll()ing
- * for write or flushing fifo
- */
-
-static void
-ubtbcmfw_start_write(struct usb2_fifo *fifo)
-{
- struct ubtbcmfw_softc *sc = fifo->priv_sc0;
-
- usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_DT_WR]);
-} /* ubtbcmfw_start_write */
-
-/*
- * Called when we about to stop writing (i.e. closing fifo)
- */
-
-static void
-ubtbcmfw_stop_write(struct usb2_fifo *fifo)
-{
- struct ubtbcmfw_softc *sc = fifo->priv_sc0;
-
- usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_BULK_DT_WR]);
-} /* ubtbcmfw_stop_write */
-
-/*
- * Called when fifo is open
- */
-
-static int
-ubtbcmfw_open(struct usb2_fifo *fifo, int fflags, struct thread *td)
-{
- struct ubtbcmfw_softc *sc = fifo->priv_sc0;
- struct usb2_xfer *xfer;
-
- /*
- * f_open fifo method can only be called with either FREAD
- * or FWRITE flag set at one time.
- */
-
- if (fflags & FREAD)
- xfer = sc->sc_xfer[UBTBCMFW_INTR_DT_RD];
- else if (fflags & FWRITE)
- xfer = sc->sc_xfer[UBTBCMFW_BULK_DT_WR];
- else
- return (EINVAL); /* should not happen */
-
- if (usb2_fifo_alloc_buffer(fifo, xfer->max_data_length,
- UBTBCMFW_IFQ_MAXLEN) != 0)
- return (ENOMEM);
-
- return (0);
-} /* ubtbcmfw_open */
-
-/*
- * Called when fifo is closed
- */
-
-static void
-ubtbcmfw_close(struct usb2_fifo *fifo, int fflags, struct thread *td)
-{
- if (fflags & (FREAD | FWRITE))
- usb2_fifo_free_buffer(fifo);
-} /* ubtbcmfw_close */
-
-/*
- * Process ioctl() on USB device
- */
-
-static int
-ubtbcmfw_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data,
- int fflags, struct thread *td)
-{
- struct ubtbcmfw_softc *sc = fifo->priv_sc0;
- int error = 0;
-
- switch (cmd) {
- case USB_GET_DEVICE_DESC:
- memcpy(data, usb2_get_device_descriptor(sc->sc_udev),
- sizeof(struct usb2_device_descriptor));
- break;
-
- default:
- error = EINVAL;
- break;
- }
-
- return (error);
-} /* ubtbcmfw_ioctl */
diff --git a/sys/dev/usb2/bluetooth/usb2_bluetooth.c b/sys/dev/usb2/bluetooth/usb2_bluetooth.c
deleted file mode 100644
index a8c9f54..0000000
--- a/sys/dev/usb2/bluetooth/usb2_bluetooth.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 Hans Petter Selasky. 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.
- */
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/bluetooth/usb2_bluetooth.h>
-
-MODULE_VERSION(usb2_bluetooth, 1);
-MODULE_DEPEND(usb2_bluetooth, usb2_core, 1, 1, 1);
diff --git a/sys/dev/usb2/bluetooth/usb2_bluetooth.h b/sys/dev/usb2/bluetooth/usb2_bluetooth.h
deleted file mode 100644
index b4b1761..0000000
--- a/sys/dev/usb2/bluetooth/usb2_bluetooth.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 Hans Petter Selasky. 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.
- */
-
-#ifndef _USB2_BLUETOOTH_H_
-#define _USB2_BLUETOOTH_H_
-
-#endif /* _USB2_BLUETOOTH_H_ */
OpenPOWER on IntegriCloud