PERFORCE change 167527 for review
Bjoern A. Zeeb
bz at FreeBSD.org
Thu Aug 20 10:24:31 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=167527
Change 167527 by bz at bz_dumpster on 2009/08/20 10:24:04
IFC, re-integ -d
Affected files ...
.. //depot/projects/s390/contrib/file/magic2mime#5 branch
.. //depot/projects/s390/crypto/openssl/test/testfipsssl#3 branch
.. //depot/projects/s390/share/man/man4/bridge.4#5 branch
.. //depot/projects/s390/sys/cddl/compat/opensolaris/rpc/xdr.h#2 integrate
.. //depot/projects/s390/sys/cddl/compat/opensolaris/sys/acl.h#3 branch
.. //depot/projects/s390/sys/dev/usb/usbdi.h#7 branch
.. //depot/projects/s390/sys/dev/usb/usbdi_util.h#7 branch
.. //depot/projects/s390/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c#10 integrate
.. //depot/projects/s390/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h#5 integrate
.. //depot/projects/s390/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c#5 integrate
.. //depot/projects/s390/sys/sys/vimage.h#5 delete
.. //depot/projects/s390/tools/build/options/WITH_BIND_LIBS#2 integrate
.. //depot/projects/s390/usr.sbin/sysinstall/usb.c#3 branch
Differences ...
==== //depot/projects/s390/sys/cddl/compat/opensolaris/rpc/xdr.h#2 (text+ko) ====
@@ -1,112 +1,70 @@
/*
- * CDDL HEADER START
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
*
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
*
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
*
- * CDDL HEADER END
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
*
- * $FreeBSD: src/sys/cddl/compat/opensolaris/rpc/xdr.h,v 1.4 2008/04/22 07:42:59 jb Exp $
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
*/
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
-/* All Rights Reserved */
-
-/*
- * Portions of this source code were derived from Berkeley 4.3 BSD
- * under license from the Regents of the University of California.
- */
-
#ifndef _OPENSOLARIS_RPC_XDR_H_
#define _OPENSOLARIS_RPC_XDR_H_
#include_next <rpc/xdr.h>
#ifndef _KERNEL
-#include_next <rpc/xdr.h>
-/*
- * Strangely, my glibc version (2.3.6) doesn't have xdr_control(), so
- * we have to hack it in here (source taken from OpenSolaris).
- * By the way, it is assumed the xdrmem implementation is used.
- */
-
-#undef xdr_control
-#define xdr_control(a,b,c) xdrmem_control(a,b,c)
+#include <assert.h>
/*
- * These are the request arguments to XDR_CONTROL.
+ * Taken from sys/xdr/xdr_mem.c.
*
- * XDR_PEEK - returns the contents of the next XDR unit on the XDR stream.
- * XDR_SKIPBYTES - skips the next N bytes in the XDR stream.
- * XDR_RDMAGET - for xdr implementation over RDMA, gets private flags from
- * the XDR stream being moved over RDMA
- * XDR_RDMANOCHUNK - for xdr implementaion over RDMA, sets private flags in
- * the XDR stream moving over RDMA.
+ * FreeBSD's userland XDR doesn't implement control method (only the kernel),
+ * but OpenSolaris nvpair still depend on it, so we have to implement it here.
*/
-#define XDR_PEEK 2
-#define XDR_SKIPBYTES 3
-#define XDR_RDMAGET 4
-#define XDR_RDMASET 5
-
-/* FIXME: probably doesn't work */
static __inline bool_t
xdrmem_control(XDR *xdrs, int request, void *info)
{
xdr_bytesrec *xptr;
- int32_t *int32p;
- int len;
switch (request) {
-
case XDR_GET_BYTES_AVAIL:
xptr = (xdr_bytesrec *)info;
xptr->xc_is_last_record = TRUE;
xptr->xc_num_avail = xdrs->x_handy;
return (TRUE);
-
- case XDR_PEEK:
- /*
- * Return the next 4 byte unit in the XDR stream.
- */
- if (xdrs->x_handy < sizeof (int32_t))
- return (FALSE);
- int32p = (int32_t *)info;
- *int32p = (int32_t)ntohl((uint32_t)
- (*((int32_t *)(xdrs->x_private))));
- return (TRUE);
-
- case XDR_SKIPBYTES:
- /*
- * Skip the next N bytes in the XDR stream.
- */
- int32p = (int32_t *)info;
- len = RNDUP((int)(*int32p));
- if ((xdrs->x_handy -= len) < 0)
- return (FALSE);
- xdrs->x_private += len;
- return (TRUE);
-
+ default:
+ assert(!"unexpected request");
}
return (FALSE);
}
+
+#undef XDR_CONTROL
+#define XDR_CONTROL(xdrs, req, op) \
+ (((xdrs)->x_ops->x_control == NULL) ? \
+ xdrmem_control((xdrs), (req), (op)) : \
+ (*(xdrs)->x_ops->x_control)(xdrs, req, op))
+
#endif /* !_KERNEL */
#endif /* !_OPENSOLARIS_RPC_XDR_H_ */
==== //depot/projects/s390/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c#10 (text+ko) ====
@@ -3,7 +3,7 @@
*/
/*-
- * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin at yahoo.com>
+ * Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin at yahoo.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,29 +27,102 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ng_ubt.c,v 1.22 2005/10/31 17:57:44 max Exp $
- * $FreeBSD: src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c,v 1.36 2008/10/03 22:40:42 emax Exp $
+ * $Id: ng_ubt.c,v 1.16 2003/10/10 19:15:06 max Exp $
+ * $FreeBSD: src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c,v 1.44 2009/06/23 06:00:31 thompsa Exp $
+ */
+
+/*
+ * 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 <sys/stdint.h>
+#include <sys/stddef.h>
#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/endian.h>
-#include <sys/filio.h>
-#include <sys/fcntl.h>
-#include <sys/mbuf.h>
+#include <sys/linker_set.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/poll.h>
-#include <sys/uio.h>
-#include <machine/bus.h>
+#include <sys/priv.h>
+#include "usbdevs.h"
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usbdivar.h>
+
+#define USB_DEBUG_VAR usb_debug
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_busdma.h>
+
+#include <sys/mbuf.h>
+#include <sys/taskqueue.h>
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
@@ -59,73 +132,17 @@
#include <netgraph/bluetooth/include/ng_ubt.h>
#include <netgraph/bluetooth/drivers/ubt/ng_ubt_var.h>
-#include "usbdevs.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;
-/*
- * USB methods
- */
+static void ubt_task_schedule(ubt_softc_p, int);
+static task_fn_t ubt_task;
-static device_probe_t ubt_match;
-static device_attach_t ubt_attach;
-static device_detach_t ubt_detach;
+#define ubt_xfer_start(sc, i) usbd_transfer_start((sc)->sc_xfer[(i)])
-static device_method_t ubt_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, ubt_match),
- DEVMETHOD(device_attach, ubt_attach),
- DEVMETHOD(device_detach, ubt_detach),
-
- { 0, 0 }
-};
-
-static driver_t ubt_driver = {
- "ubt",
- ubt_methods,
- sizeof(struct ubt_softc)
-};
-
-static devclass_t ubt_devclass;
-
-static int ubt_modevent (module_t, int, void *);
-
-static usbd_status ubt_request_start (ubt_softc_p);
-static void ubt_request_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_request_complete2 (node_p, hook_p, void *, int);
-
-static usbd_status ubt_intr_start (ubt_softc_p);
-static void ubt_intr_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_intr_complete2 (node_p, hook_p, void *, int);
-
-static usbd_status ubt_bulk_in_start (ubt_softc_p);
-static void ubt_bulk_in_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_bulk_in_complete2 (node_p, hook_p, void *, int);
-
-static usbd_status ubt_bulk_out_start (ubt_softc_p);
-static void ubt_bulk_out_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_bulk_out_complete2 (node_p, hook_p, void *, int);
-
-static usbd_status ubt_isoc_in_start_one (ubt_softc_p, int);
-static usbd_status ubt_isoc_in_start (ubt_softc_p);
-static void ubt_isoc_in_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_isoc_in_complete2 (node_p, hook_p, void *, int);
-
-static usbd_status ubt_isoc_out_start_one (ubt_softc_p, int);
-static usbd_status ubt_isoc_out_start (ubt_softc_p);
-static void ubt_isoc_out_complete (usbd_xfer_handle,
- usbd_private_handle, usbd_status);
-static void ubt_isoc_out_complete2 (node_p, hook_p, void *, int);
-
-static void ubt_reset (ubt_softc_p);
-
-/*
- * Netgraph methods
- */
-
+/* Netgraph methods */
static ng_constructor_t ng_ubt_constructor;
static ng_shutdown_t ng_ubt_shutdown;
static ng_newhook_t ng_ubt_newhook;
@@ -141,7 +158,8 @@
{ "qlen", &ng_parse_int32_type, },
{ NULL, }
};
-static const struct ng_parse_type ng_ubt_node_qlen_type = {
+static const struct ng_parse_type ng_ubt_node_qlen_type =
+{
&ng_parse_struct_type,
&ng_ubt_node_qlen_type_fields
};
@@ -157,61 +175,64 @@
{ "ierrors", &ng_parse_uint32_type, },
{ NULL, }
};
-static const struct ng_parse_type ng_ubt_node_stat_type = {
+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[] = {
+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, }
+ {
+ 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,
+static struct ng_type typestruct =
+{
+ .version = NG_ABI_VERSION,
.name = NG_UBT_NODE_TYPE,
.constructor = ng_ubt_constructor,
.rcvmsg = ng_ubt_rcvmsg,
@@ -220,191 +241,250 @@
.connect = ng_ubt_connect,
.rcvdata = ng_ubt_rcvdata,
.disconnect = ng_ubt_disconnect,
- .cmdlist = ng_ubt_cmdlist
+ .cmdlist = ng_ubt_cmdlist
};
-/*
- * Module
- */
-
-DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, 0);
-MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
-MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
-MODULE_DEPEND(ubt, usb, 1, 1, 1);
-
-
/****************************************************************************
****************************************************************************
** USB specific
****************************************************************************
****************************************************************************/
+/* USB methods */
+static usb_callback_t ubt_ctrl_write_callback;
+static usb_callback_t ubt_intr_read_callback;
+static usb_callback_t ubt_bulk_read_callback;
+static usb_callback_t ubt_bulk_write_callback;
+static usb_callback_t ubt_isoc_read_callback;
+static usb_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 usb_xfer *, int);
+
/*
- * Load/Unload the driver module
+ * 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 int
-ubt_modevent(module_t mod, int event, void *data)
+static const struct usb_config ubt_config[UBT_N_TRANSFER] =
{
- int error;
+ /*
+ * 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,
+ .bufsize = UBT_BULK_WRITE_BUFFER_SIZE,
+ .flags = { .pipe_bof = 1, .force_short_xfer = 1, },
+ .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,
+ .bufsize = UBT_BULK_READ_BUFFER_SIZE,
+ .flags = { .pipe_bof = 1, .short_xfer_ok = 1, },
+ .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,
+ .flags = { .pipe_bof = 1, .short_xfer_ok = 1, },
+ .bufsize = UBT_INTR_BUFFER_SIZE,
+ .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,
+ .bufsize = UBT_CTRL_BUFFER_SIZE,
+ .callback = &ubt_ctrl_write_callback,
+ .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,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UBT_ISOC_NFRAMES,
+ .flags = { .short_xfer_ok = 1, },
+ .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,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UBT_ISOC_NFRAMES,
+ .flags = { .short_xfer_ok = 1, },
+ .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,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UBT_ISOC_NFRAMES,
+ .flags = { .short_xfer_ok = 1, },
+ .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,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UBT_ISOC_NFRAMES,
+ .flags = { .short_xfer_ok = 1, },
+ .callback = &ubt_isoc_write_callback,
+ },
+};
- switch (event) {
- case MOD_LOAD:
- error = ng_newtype(&typestruct);
- if (error != 0)
- printf(
-"%s: Could not register Netgraph node type, error=%d\n",
- NG_UBT_NODE_TYPE, error);
- else
- error = usbd_driver_load(mod, event, data);
- break;
+/*
+ * 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.
+ */
- case MOD_UNLOAD:
- error = ng_rmtype(&typestruct);
- if (error == 0)
- error = usbd_driver_load(mod, event, data);
- break;
+static const struct usb_device_id ubt_ignore_devs[] =
+{
+ /* AVM USB Bluetooth-Adapter BlueFritz! v1.0 */
+ { USB_VPI(USB_VENDOR_AVM, 0x2200, 0) },
+};
- default:
- error = EOPNOTSUPP;
- break;
- }
+/* List of supported bluetooth devices */
+static const struct usb_device_id ubt_devs[] =
+{
+ /* Generic Bluetooth class devices */
+ { USB_IFACE_CLASS(UDCLASS_WIRELESS),
+ USB_IFACE_SUBCLASS(UDSUBCLASS_RF),
+ USB_IFACE_PROTOCOL(UDPROTO_BLUETOOTH) },
- return (error);
-} /* ubt_modevent */
+ /* AVM USB Bluetooth-Adapter BlueFritz! v2.0 */
+ { USB_VPI(USB_VENDOR_AVM, 0x3800, 0) },
+};
/*
- * Probe for a USB Bluetooth device
+ * Probe for a USB Bluetooth device.
+ * USB context.
*/
static int
-ubt_match(device_t self)
+ubt_probe(device_t dev)
{
- /*
- * If for some reason device should not be attached then put
- * VendorID/ProductID pair into the list below. The format is
- * as follows:
- *
- * { VENDOR_ID, PRODUCT_ID },
- *
- * where VENDOR_ID and PRODUCT_ID are hex numbers.
- */
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
- static struct usb_devno const ubt_ignored_devices[] = {
- { USB_VENDOR_AVM, 0x2200 }, /* AVM USB Bluetooth-Adapter BlueFritz! v1.0 */
- { 0, 0 } /* This should be the last item in the list */
- };
+ if (uaa->usb_mode != USB_MODE_HOST)
+ return (ENXIO);
- /*
- * If device violates Bluetooth specification and has bDeviceClass,
- * bDeviceSubClass and bDeviceProtocol set to wrong values then you
- * could try to put VendorID/ProductID pair into the list below.
- * Adding VendorID/ProductID pair into this list forces ng_ubt(4)
- * to attach to the broken device.
- */
+ if (uaa->info.bIfaceIndex != 0)
+ return (ENXIO);
- static struct usb_devno const ubt_broken_devices[] = {
- { USB_VENDOR_AVM, 0x3800 }, /* AVM USB Bluetooth-Adapter BlueFritz! v2.0 */
- { 0, 0 } /* This should be the last item in the list */
- };
+ if (uaa->use_generic == 0)
+ return (ENXIO);
- struct usb_attach_arg *uaa = device_get_ivars(self);
- usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
+ if (usbd_lookup_id_by_uaa(ubt_ignore_devs,
+ sizeof(ubt_ignore_devs), uaa) == 0)
+ return (ENXIO);
- if (uaa->iface == NULL ||
- usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
- return (UMATCH_NONE);
-
- if (dd->bDeviceClass == UDCLASS_WIRELESS &&
- dd->bDeviceSubClass == UDSUBCLASS_RF &&
- dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
- return (UMATCH_DEVCLASS_DEVSUBCLASS);
+ return (usbd_lookup_id_by_uaa(ubt_devs, sizeof(ubt_devs), uaa));
+} /* ubt_probe */
- if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
- return (UMATCH_VENDOR_PRODUCT);
-
- return (UMATCH_NONE);
-} /* ubt_match */
-
/*
- * Attach the device
+ * Attach the device.
+ * USB context.
*/
static int
-ubt_attach(device_t self)
+ubt_attach(device_t dev)
{
- struct ubt_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
- usb_config_descriptor_t *cd = NULL;
- usb_interface_descriptor_t *id = NULL;
- usb_endpoint_descriptor_t *ed = NULL;
- usbd_status error;
- int i, ai, alt_no, isoc_in, isoc_out,
- isoc_isize, isoc_osize;
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ struct ubt_softc *sc = device_get_softc(dev);
+ struct usb_endpoint_descriptor *ed;
+ struct usb_interface_descriptor *id;
+ uint16_t wMaxPacketSize;
+ uint8_t alt_index, i, j;
+ uint8_t iface_index[2] = { 0, 1 };
+
+ device_set_usb_desc(dev);
- /* Get USB device info */
- sc->sc_dev = self;
- sc->sc_udev = uaa->device;
+ sc->sc_dev = dev;
+ sc->sc_debug = NG_UBT_WARN_LEVEL;
/*
- * Initialize device softc structure
+ * Create Netgraph node
*/
- /* State */
- sc->sc_debug = NG_UBT_WARN_LEVEL;
- sc->sc_flags = 0;
- NG_UBT_STAT_RESET(sc->sc_stat);
+ 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);
- /* Interfaces */
- sc->sc_iface0 = sc->sc_iface1 = NULL;
+ /*
+ * Initialize device softc structure
+ */
- /* Interrupt pipe */
- sc->sc_intr_ep = -1;
- sc->sc_intr_pipe = NULL;
- sc->sc_intr_xfer = NULL;
- sc->sc_intr_buffer = NULL;
+ /* 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);
- /* Control pipe */
- sc->sc_ctrl_xfer = NULL;
- sc->sc_ctrl_buffer = NULL;
+ /* initialize packet queues */
NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
-
- /* Bulk-in pipe */
- sc->sc_bulk_in_ep = -1;
- sc->sc_bulk_in_pipe = NULL;
- sc->sc_bulk_in_xfer = NULL;
- sc->sc_bulk_in_buffer = NULL;
-
- /* Bulk-out pipe */
- sc->sc_bulk_out_ep = -1;
- sc->sc_bulk_out_pipe = NULL;
- sc->sc_bulk_out_xfer = NULL;
- sc->sc_bulk_out_buffer = NULL;
NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
-
- /* Isoc-in pipe */
- sc->sc_isoc_in_buffer = NULL;
- sc->sc_isoc_in_ep = -1;
- sc->sc_isoc_in_pipe = NULL;
- bzero(&sc->sc_isoc_in, sizeof(sc->sc_isoc_in));
-
- /* Isoc-out pipe */
- sc->sc_isoc_out_ep = -1;
- sc->sc_isoc_out_pipe = NULL;
- bzero(&sc->sc_isoc_out, sizeof(sc->sc_isoc_out));
-
- sc->sc_isoc_size = -1;
NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
- /* Netgraph part */
- sc->sc_node = NULL;
- sc->sc_hook = NULL;
+ /* initialize glue task */
+ TASK_INIT(&sc->sc_task, 0, ubt_task, sc);
/*
- * XXX set configuration?
- *
- * Configure Bluetooth USB device. Discover all required USB interfaces
- * and endpoints.
+ * Configure Bluetooth USB device. Discover all required USB
+ * interfaces and endpoints.
*
* USB device must present two interfaces:
* 1) Interface 0 that has 3 endpoints
@@ -416,1523 +496,835 @@
* 1) Isochronous IN endpoint to receive SCO data
* 2) Isochronous OUT endpoint to send SCO data
*
- * Interface 1 (with isochronous endpoints) has several alternate
+ * Interface 1 (with isochronous endpoints) has several alternate
* configurations with different packet size.
*/
/*
- * Interface 0
+ * For interface #1 search alternate settings, and find
+ * the descriptor with the largest wMaxPacketSize
*/
- error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
- if (error || sc->sc_iface0 == NULL) {
- printf("%s: Could not get interface 0 handle. %s (%d), " \
- "handle=%p\n", device_get_nameunit(sc->sc_dev),
- usbd_errstr(error), error, sc->sc_iface0);
- goto bad;
- }
+ wMaxPacketSize = 0;
+ alt_index = 0;
+ i = 0;
+ j = 0;
+ ed = NULL;
- id = usbd_get_interface_descriptor(sc->sc_iface0);
- if (id == NULL) {
- printf("%s: Could not get interface 0 descriptor\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- for (i = 0; i < id->bNumEndpoints; i ++) {
- ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
- if (ed == NULL) {
- printf("%s: Could not read endpoint descriptor for " \
- "interface 0, i=%d\n", device_get_nameunit(sc->sc_dev),
- i);
- goto bad;
- }
-
- switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
- case UE_BULK:
- if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
- sc->sc_bulk_in_ep = ed->bEndpointAddress;
- else
- sc->sc_bulk_out_ep = ed->bEndpointAddress;
- break;
-
- case UE_INTERRUPT:
- sc->sc_intr_ep = ed->bEndpointAddress;
- break;
- }
- }
-
- /* Check if we got everything we wanted on Interface 0 */
- if (sc->sc_intr_ep == -1) {
- printf("%s: Could not detect interrupt endpoint\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
- if (sc->sc_bulk_in_ep == -1) {
- printf("%s: Could not detect bulk-in endpoint\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
- if (sc->sc_bulk_out_ep == -1) {
- printf("%s: Could not detect bulk-out endpoint\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
- "bulk-out=%#x\n", device_get_nameunit(sc->sc_dev),
- sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
-
- /*
- * Interface 1
+ /*
+ * Search through all the descriptors looking for the largest
+ * packet size:
*/
+ while ((ed = (struct usb_endpoint_descriptor *)usb_desc_foreach(
+ usbd_get_config_descriptor(uaa->device),
+ (struct usb_descriptor *)ed))) {
- cd = usbd_get_config_descriptor(sc->sc_udev);
- if (cd == NULL) {
- printf("%s: Could not get device configuration descriptor\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
- }
-
- error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
- if (error || sc->sc_iface1 == NULL) {
- printf("%s: Could not get interface 1 handle. %s (%d), " \
- "handle=%p\n", device_get_nameunit(sc->sc_dev),
- usbd_errstr(error), error, sc->sc_iface1);
- goto bad;
- }
-
- id = usbd_get_interface_descriptor(sc->sc_iface1);
- if (id == NULL) {
- printf("%s: Could not get interface 1 descriptor\n",
- device_get_nameunit(sc->sc_dev));
- goto bad;
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list