diff options
author | thompsa <thompsa@FreeBSD.org> | 2009-02-23 18:31:00 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2009-02-23 18:31:00 +0000 |
commit | 111a707d99983acd73c4212036000aa3e88425b6 (patch) | |
tree | 691e9b9009214e6138d3913e4c022c897e386667 /sys/dev/usb2/bluetooth | |
parent | 124e83aa64b26f6b00736a45c3e25dfda8c7060e (diff) | |
download | FreeBSD-src-111a707d99983acd73c4212036000aa3e88425b6.zip FreeBSD-src-111a707d99983acd73c4212036000aa3e88425b6.tar.gz |
Move the new USB stack into its new home.
Diffstat (limited to 'sys/dev/usb2/bluetooth')
-rw-r--r-- | sys/dev/usb2/bluetooth/TODO.TXT | 18 | ||||
-rw-r--r-- | sys/dev/usb2/bluetooth/ng_ubt2.c | 1720 | ||||
-rw-r--r-- | sys/dev/usb2/bluetooth/ng_ubt2_var.h | 131 | ||||
-rw-r--r-- | sys/dev/usb2/bluetooth/ubtbcmfw2.c | 431 | ||||
-rw-r--r-- | sys/dev/usb2/bluetooth/usb2_bluetooth.c | 31 | ||||
-rw-r--r-- | sys/dev/usb2/bluetooth/usb2_bluetooth.h | 30 |
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_ */ |