Date: Thu, 28 May 2009 17:13:10 GMT From: Marko Zec <zec@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 162950 for review Message-ID: <200905281713.n4SHDAg8072243@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=162950 Change 162950 by zec@zec_amdx4 on 2009/05/28 17:13:07 Fix mysterious misintergations. Affected files ... .. //depot/projects/vimage-commit/src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h#5 edit .. //depot/projects/vimage-commit/src/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c#6 edit Differences ... ==== //depot/projects/vimage-commit/src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h#5 (text+ko) ==== @@ -3,7 +3,7 @@ */ /*- - * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin@yahoo.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,123 +27,102 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_ubt_var.h,v 1.5 2005/10/31 17:57:44 max Exp $ - * $FreeBSD: src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h,v 1.8 2008/07/11 17:13:43 emax Exp $ + * $Id: ng_ubt_var.h,v 1.2 2003/03/22 23:44:36 max Exp $ + * $FreeBSD: src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h,v 1.10 2009/05/27 16:34:08 thompsa Exp $ */ #ifndef _NG_UBT_VAR_H_ -#define _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) -/* pullup wrapper */ -#define NG_UBT_M_PULLUP(m, s) \ - do { \ - if ((m)->m_len < (s)) \ - (m) = m_pullup((m), (s)); \ - if ((m) == NULL) \ - NG_UBT_ALERT("%s: %s - m_pullup(%d) failed\n", \ - __func__, device_get_nameunit(sc->sc_dev), (s)); \ - } while (0) +#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__) -/* Debug printf's */ -#define NG_UBT_ALERT if (sc->sc_debug >= NG_UBT_ALERT_LEVEL) printf -#define NG_UBT_ERR if (sc->sc_debug >= NG_UBT_ERR_LEVEL) printf -#define NG_UBT_WARN if (sc->sc_debug >= NG_UBT_WARN_LEVEL) printf -#define NG_UBT_INFO if (sc->sc_debug >= NG_UBT_INFO_LEVEL) printf +#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 12 +#define UBT_HCI_REQUEST 0x20 +#define UBT_DEFAULT_QLEN 64 +#define UBT_ISOC_NFRAMES 32 /* should be factor of 8 */ -/* Isoc transfers */ -#define NG_UBT_NXFERS 3 /* max xfers to queue */ -#define NG_UBT_NFRAMES 10 /* frames per xfer */ +/* 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, -struct ubt_isoc_xfer { - usbd_xfer_handle xfer; /* isoc xfer */ - void *buffer; /* isoc buffer */ - uint16_t *frlen; /* isoc frame length */ - int active; /* is xfer active */ + UBT_N_TRANSFER, /* total number of transfers */ }; -typedef struct ubt_isoc_xfer ubt_isoc_xfer_t; -typedef struct ubt_isoc_xfer * ubt_isoc_xfer_p; /* USB device softc structure */ struct ubt_softc { + device_t sc_dev; /* for debug printf */ + /* State */ - ng_ubt_node_debug_ep sc_debug; /* debug level */ - uint32_t sc_flags; /* device flags */ -#define UBT_NEED_FRAME_TYPE (1 << 0) /* device required frame type */ -#define UBT_HAVE_FRAME_TYPE UBT_NEED_FRAME_TYPE -#define UBT_CMD_XMIT (1 << 1) /* CMD xmit in progress */ -#define UBT_ACL_XMIT (1 << 2) /* ACL xmit in progress */ -#define UBT_SCO_XMIT (1 << 3) /* SCO xmit in progress */ -#define UBT_EVT_RECV (1 << 4) /* EVN recv in progress */ -#define UBT_ACL_RECV (1 << 5) /* ACL recv in progress */ -#define UBT_SCO_RECV (1 << 6) /* SCO recv in progress */ + ng_ubt_node_debug_ep sc_debug; /* debug level */ - ng_ubt_node_stat_ep sc_stat; /* statistic */ -#define NG_UBT_STAT_PCKTS_SENT(s) (s).pckts_sent ++ -#define NG_UBT_STAT_BYTES_SENT(s, n) (s).bytes_sent += (n) -#define NG_UBT_STAT_PCKTS_RECV(s) (s).pckts_recv ++ -#define NG_UBT_STAT_BYTES_RECV(s, n) (s).bytes_recv += (n) -#define NG_UBT_STAT_OERROR(s) (s).oerrors ++ -#define NG_UBT_STAT_IERROR(s) (s).ierrors ++ -#define NG_UBT_STAT_RESET(s) bzero(&(s), sizeof((s))) + 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 */ - device_t sc_dev; /* pointer back to USB device */ - usbd_device_handle sc_udev; /* USB device handle */ + struct mtx sc_if_mtx; /* interfaces lock */ + struct usb2_xfer *sc_xfer[UBT_N_TRANSFER]; - usbd_interface_handle sc_iface0; /* USB interface 0 */ - usbd_interface_handle sc_iface1; /* USB interface 1 */ + struct mtx sc_ng_mtx; /* lock for shared NG data */ - /* Interrupt pipe (HCI events) */ - int sc_intr_ep; /* interrupt endpoint */ - usbd_pipe_handle sc_intr_pipe; /* interrupt pipe handle */ - usbd_xfer_handle sc_intr_xfer; /* intr xfer */ - struct mbuf *sc_intr_buffer; /* interrupt buffer */ + /* 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 */ - /* Control pipe (HCI commands) */ - usbd_xfer_handle sc_ctrl_xfer; /* control xfer handle */ - void *sc_ctrl_buffer; /* control buffer */ - struct ng_bt_mbufq sc_cmdq; /* HCI command queue */ -#define UBT_CTRL_BUFFER_SIZE \ - (sizeof(ng_hci_cmd_pkt_t) + NG_HCI_CMD_PKT_SIZE) + /* 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) - /* Bulk in pipe (ACL data) */ - int sc_bulk_in_ep; /* bulk-in enpoint */ - usbd_pipe_handle sc_bulk_in_pipe; /* bulk-in pipe */ - usbd_xfer_handle sc_bulk_in_xfer; /* bulk-in xfer */ - struct mbuf *sc_bulk_in_buffer; /* bulk-in buffer */ + /* SCO data */ + struct ng_bt_mbufq sc_scoq; /* SCO data queue */ + struct mbuf *sc_isoc_in_buffer; /* SCO reassembly buffer */ - /* Bulk out pipe (ACL data) */ - int sc_bulk_out_ep; /* bulk-out endpoint */ - usbd_pipe_handle sc_bulk_out_pipe; /* bulk-out pipe */ - usbd_xfer_handle sc_bulk_out_xfer; /* bulk-out xfer */ - void *sc_bulk_out_buffer; /* bulk-out buffer */ - struct ng_bt_mbufq sc_aclq; /* ACL data queue */ -#define UBT_BULK_BUFFER_SIZE \ - MCLBYTES /* XXX should be big enough to hold one frame */ + /* Netgraph specific */ + node_p sc_node; /* pointer back to node */ + hook_p sc_hook; /* upstream hook */ - /* Isoc. in pipe (SCO data) */ - struct mbuf *sc_isoc_in_buffer; - int sc_isoc_in_ep; /* isoc-in endpoint */ - usbd_pipe_handle sc_isoc_in_pipe; /* isoc-in pipe */ - ubt_isoc_xfer_t sc_isoc_in[NG_UBT_NXFERS]; /* isoc-in xfers */ + /* 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) */ - /* Isoc. out pipe (SCO data) */ - int sc_isoc_out_ep; /* isoc-out endpoint */ - usbd_pipe_handle sc_isoc_out_pipe; /* isoc-out pipe */ - ubt_isoc_xfer_t sc_isoc_out[NG_UBT_NXFERS]; /* isoc-out xfers */ - struct ng_bt_mbufq sc_scoq; /* SCO data queue */ - - int sc_isoc_size; /* max. size of isoc. packet */ -#define UBT_ISOC_BUFFER_SIZE \ - (sizeof(ng_hci_scodata_pkt_t) + NG_HCI_SCO_PKT_SIZE) - - /* Netgraph specific */ - node_p sc_node; /* pointer back to node */ - hook_p sc_hook; /* upstream hook */ + struct task sc_task; }; typedef struct ubt_softc ubt_softc_t; typedef struct ubt_softc * ubt_softc_p; ==== //depot/projects/vimage-commit/src/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c#6 (text+ko) ==== @@ -3,7 +3,7 @@ */ /*- - * Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * Copyright (c) 2003-2009 Maksim Yevmenkin <m_evmenkin@yahoo.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,489 +28,394 @@ * SUCH DAMAGE. * * $Id: ubtbcmfw.c,v 1.3 2003/10/10 19:15:08 max Exp $ - * $FreeBSD: src/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c,v 1.20 2009/04/17 22:13:41 ed Exp $ + * $FreeBSD: src/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c,v 1.22 2009/05/27 16:32:05 thompsa Exp $ */ -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/filio.h> -#include <sys/fcntl.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/poll.h> -#include <sys/proc.h> -#include <sys/sysctl.h> -#include <sys/uio.h> +#include "usbdevs.h" +#include <dev/usb/usb.h> +#include <dev/usb/usb_mfunc.h> +#include <dev/usb/usb_error.h> +#include <dev/usb/usb_ioctl.h> -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> +#define USB_DEBUG_VAR usb2_debug -#include "usbdevs.h" +#include <dev/usb/usb_core.h> +#include <dev/usb/usb_debug.h> +#include <dev/usb/usb_parse.h> +#include <dev/usb/usb_lookup.h> +#include <dev/usb/usb_util.h> +#include <dev/usb/usb_busdma.h> +#include <dev/usb/usb_mbuf.h> +#include <dev/usb/usb_dev.h> /* * Download firmware to BCM2033. */ -#define UBTBCMFW_CONFIG_NO 1 /* Config number */ -#define UBTBCMFW_IFACE_IDX 0 /* Control interface */ -#define UBTBCMFW_INTR_IN_EP 0x81 /* Fixed endpoint */ -#define UBTBCMFW_BULK_OUT_EP 0x02 /* Fixed endpoint */ -#define UBTBCMFW_INTR_IN UE_GET_ADDR(UBTBCMFW_INTR_IN_EP) -#define UBTBCMFW_BULK_OUT UE_GET_ADDR(UBTBCMFW_BULK_OUT_EP) +#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 { - device_t sc_dev; /* base device */ - usbd_device_handle sc_udev; /* USB device handle */ - struct cdev *sc_ctrl_dev; /* control device */ - struct cdev *sc_intr_in_dev; /* interrupt device */ - struct cdev *sc_bulk_out_dev; /* bulk device */ - usbd_pipe_handle sc_intr_in_pipe; /* interrupt pipe */ - usbd_pipe_handle sc_bulk_out_pipe; /* bulk out pipe */ - int sc_flags; -#define UBTBCMFW_CTRL_DEV (1 << 0) -#define UBTBCMFW_INTR_IN_DEV (1 << 1) -#define UBTBCMFW_BULK_OUT_DEV (1 << 2) - int sc_refcnt; - int sc_dying; + struct usb2_device *sc_udev; + struct mtx sc_mtx; + struct usb2_xfer *sc_xfer[UBTBCMFW_N_TRANSFER]; + struct usb2_fifo_sc sc_fifo; }; -typedef struct ubtbcmfw_softc *ubtbcmfw_softc_p; +/* + * 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 methods + * Device's config structure */ -#define UBTBCMFW_BSIZE 1024 +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, + .bufsize = UBTBCMFW_BSIZE, + .flags = { .pipe_bof = 1, .force_short_xfer = 1, + .proxy_buffer = 1, }, + .callback = &ubtbcmfw_write_callback, + }, -static d_open_t ubtbcmfw_open; -static d_close_t ubtbcmfw_close; -static d_read_t ubtbcmfw_read; -static d_write_t ubtbcmfw_write; -static d_ioctl_t ubtbcmfw_ioctl; -static d_poll_t ubtbcmfw_poll; - -static struct cdevsw ubtbcmfw_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = ubtbcmfw_open, - .d_close = ubtbcmfw_close, - .d_read = ubtbcmfw_read, - .d_write = ubtbcmfw_write, - .d_ioctl = ubtbcmfw_ioctl, - .d_poll = ubtbcmfw_poll, - .d_name = "ubtbcmfw", + [UBTBCMFW_INTR_DT_RD] = { + .type = UE_INTERRUPT, + .endpoint = 0x01, /* fixed */ + .direction = UE_DIR_IN, + .if_index = UBTBCMFW_IFACE_IDX, + .bufsize = UBTBCMFW_BSIZE, + .flags = { .pipe_bof = 1, .short_xfer_ok = 1, + .proxy_buffer = 1, }, + .callback = &ubtbcmfw_read_callback, + }, }; /* * Module */ -static device_probe_t ubtbcmfw_match; -static device_attach_t ubtbcmfw_attach; -static device_detach_t ubtbcmfw_detach; +static devclass_t ubtbcmfw_devclass; -static device_method_t ubtbcmfw_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ubtbcmfw_match), - DEVMETHOD(device_attach, ubtbcmfw_attach), - DEVMETHOD(device_detach, ubtbcmfw_detach), - - { 0, 0 } +static 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 = { - "ubtbcmfw", - ubtbcmfw_methods, - sizeof(struct ubtbcmfw_softc) +static driver_t ubtbcmfw_driver = +{ + .name = "ubtbcmfw", + .methods = ubtbcmfw_methods, + .size = sizeof(struct ubtbcmfw_softc), }; -static devclass_t ubtbcmfw_devclass; - +DRIVER_MODULE(ubtbcmfw, uhub, ubtbcmfw_driver, ubtbcmfw_devclass, NULL, 0); MODULE_DEPEND(ubtbcmfw, usb, 1, 1, 1); -DRIVER_MODULE(ubtbcmfw, uhub, ubtbcmfw_driver, ubtbcmfw_devclass, - usbd_driver_load, 0); /* * Probe for a USB Bluetooth device */ static int -ubtbcmfw_match(device_t self) +ubtbcmfw_probe(device_t dev) { -#define USB_PRODUCT_BROADCOM_BCM2033NF 0x2033 - struct usb_attach_arg *uaa = device_get_ivars(self); + 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->iface != NULL) - return (UMATCH_NONE); + if (uaa->usb_mode != USB_MODE_HOST) + return (ENXIO); - /* Match the boot device. */ - if (uaa->vendor == USB_VENDOR_BROADCOM && - uaa->product == USB_PRODUCT_BROADCOM_BCM2033NF) - return (UMATCH_VENDOR_PRODUCT); + if (uaa->info.bIfaceIndex != 0) + return (ENXIO); - return (UMATCH_NONE); -} + return (usb2_lookup_id_by_uaa(devs, sizeof(devs), uaa)); +} /* ubtbcmfw_probe */ /* * Attach the device */ static int -ubtbcmfw_attach(device_t self) +ubtbcmfw_attach(device_t dev) { - struct ubtbcmfw_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_interface_handle iface; - usbd_status err; + 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_dev = self; sc->sc_udev = uaa->device; - sc->sc_ctrl_dev = sc->sc_intr_in_dev = sc->sc_bulk_out_dev = NULL; - sc->sc_intr_in_pipe = sc->sc_bulk_out_pipe = NULL; - sc->sc_flags = sc->sc_refcnt = sc->sc_dying = 0; + device_set_usb2_desc(dev); - err = usbd_set_config_no(sc->sc_udev, UBTBCMFW_CONFIG_NO, 1); - if (err) { - printf("%s: setting config no failed. %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - goto bad; - } + mtx_init(&sc->sc_mtx, "ubtbcmfw lock", NULL, MTX_DEF | MTX_RECURSE); - err = usbd_device2interface_handle(sc->sc_udev, UBTBCMFW_IFACE_IDX, - &iface); - if (err) { - printf("%s: getting interface handle failed. %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - goto bad; + 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; } - /* Will be used as a bulk pipe */ - err = usbd_open_pipe(iface, UBTBCMFW_INTR_IN_EP, 0, - &sc->sc_intr_in_pipe); - if (err) { - printf("%s: open intr in failed. %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - goto bad; + 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, + UID_ROOT, GID_OPERATOR, 0644); + if (error != 0) { + device_printf(dev, "could not attach fifo. %s\n", + usb2_errstr(error)); + goto detach; } - err = usbd_open_pipe(iface, UBTBCMFW_BULK_OUT_EP, 0, - &sc->sc_bulk_out_pipe); - if (err) { - printf("%s: open bulk out failed. %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - goto bad; - } + return (0); /* success */ - /* Create device nodes */ - sc->sc_ctrl_dev = make_dev(&ubtbcmfw_cdevsw, - 0, UID_ROOT, GID_OPERATOR, 0644, - "%s", device_get_nameunit(sc->sc_dev)); - sc->sc_ctrl_dev->si_drv1 = sc; +detach: + ubtbcmfw_detach(dev); - sc->sc_intr_in_dev = make_dev(&ubtbcmfw_cdevsw, - UBTBCMFW_INTR_IN, UID_ROOT, GID_OPERATOR, 0644, - "%s.%d", device_get_nameunit(sc->sc_dev), UBTBCMFW_INTR_IN); - sc->sc_intr_in_dev->si_drv1 = sc; - - sc->sc_bulk_out_dev = make_dev(&ubtbcmfw_cdevsw, - UBTBCMFW_BULK_OUT, UID_ROOT, GID_OPERATOR, 0644, - "%s.%d", device_get_nameunit(sc->sc_dev), UBTBCMFW_BULK_OUT); - sc->sc_bulk_out_dev->si_drv1 = sc; - - return 0; -bad: - ubtbcmfw_detach(self); - return ENXIO; -} + return (ENXIO); /* failure */ +} /* ubtbcmfw_attach */ /* * Detach the device */ static int -ubtbcmfw_detach(device_t self) +ubtbcmfw_detach(device_t dev) { - struct ubtbcmfw_softc *sc = device_get_softc(self); + struct ubtbcmfw_softc *sc = device_get_softc(dev); - sc->sc_dying = 1; - if (-- sc->sc_refcnt >= 0) { - if (sc->sc_intr_in_pipe != NULL) - usbd_abort_pipe(sc->sc_intr_in_pipe); + usb2_fifo_detach(&sc->sc_fifo); - if (sc->sc_bulk_out_pipe != NULL) - usbd_abort_pipe(sc->sc_bulk_out_pipe); + usb2_transfer_unsetup(sc->sc_xfer, UBTBCMFW_N_TRANSFER); - usb_detach_wait(sc->sc_dev); - } - - /* Destroy device nodes */ - if (sc->sc_bulk_out_dev != NULL) { - destroy_dev(sc->sc_bulk_out_dev); - sc->sc_bulk_out_dev = NULL; - } - - if (sc->sc_intr_in_dev != NULL) { - destroy_dev(sc->sc_intr_in_dev); - sc->sc_intr_in_dev = NULL; - } - - if (sc->sc_ctrl_dev != NULL) { - destroy_dev(sc->sc_ctrl_dev); - sc->sc_ctrl_dev = NULL; - } - - /* Close pipes */ - if (sc->sc_intr_in_pipe != NULL) { - usbd_close_pipe(sc->sc_intr_in_pipe); - sc->sc_intr_in_pipe = NULL; - } - - if (sc->sc_bulk_out_pipe != NULL) { - usbd_close_pipe(sc->sc_bulk_out_pipe); - sc->sc_intr_in_pipe = NULL; - } + mtx_destroy(&sc->sc_mtx); return (0); -} +} /* ubtbcmfw_detach */ /* - * Open endpoint device - * XXX FIXME softc locking + * USB write callback */ -static int -ubtbcmfw_open(struct cdev *dev, int flag, int mode, struct thread *p) +static void +ubtbcmfw_write_callback(struct usb2_xfer *xfer) { - ubtbcmfw_softc_p sc = dev->si_drv1; - int error = 0; + struct ubtbcmfw_softc *sc = xfer->priv_sc; + struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_TX]; + uint32_t actlen; - if (sc->sc_dying) - return (ENXIO); - - switch (dev2unit(dev)) { - case USB_CONTROL_ENDPOINT: - if (!(sc->sc_flags & UBTBCMFW_CTRL_DEV)) - sc->sc_flags |= UBTBCMFW_CTRL_DEV; - else - error = EBUSY; + 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; - case UBTBCMFW_INTR_IN: - if (!(sc->sc_flags & UBTBCMFW_INTR_IN_DEV)) { - if (sc->sc_intr_in_pipe != NULL) - sc->sc_flags |= UBTBCMFW_INTR_IN_DEV; - else - error = ENXIO; - } else - error = EBUSY; + default: /* Error */ + if (xfer->error != USB_ERR_CANCELLED) { + /* try to clear stall first */ + xfer->flags.stall_pipe = 1; + goto setup_next; + } break; - - case UBTBCMFW_BULK_OUT: - if (!(sc->sc_flags & UBTBCMFW_BULK_OUT_DEV)) { - if (sc->sc_bulk_out_pipe != NULL) - sc->sc_flags |= UBTBCMFW_BULK_OUT_DEV; - else - error = ENXIO; - } else - error = EBUSY; - break; - - default: - error = ENXIO; - break; } +} /* ubtbcmfw_write_callback */ - return (error); -} - /* - * Close endpoint device - * XXX FIXME softc locking + * USB read callback */ -static int -ubtbcmfw_close(struct cdev *dev, int flag, int mode, struct thread *p) +static void +ubtbcmfw_read_callback(struct usb2_xfer *xfer) { - ubtbcmfw_softc_p sc = dev->si_drv1; + struct ubtbcmfw_softc *sc = xfer->priv_sc; + struct usb2_fifo *fifo = sc->sc_fifo.fp[USB_FIFO_RX]; - switch (dev2unit(dev)) { - case USB_CONTROL_ENDPOINT: - sc->sc_flags &= ~UBTBCMFW_CTRL_DEV; - break; + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + usb2_fifo_put_data(fifo, xfer->frbuffers, 0, xfer->actlen, 1); + /* FALLTHROUGH */ - case UBTBCMFW_INTR_IN: - if (sc->sc_intr_in_pipe != NULL) - usbd_abort_pipe(sc->sc_intr_in_pipe); - - sc->sc_flags &= ~UBTBCMFW_INTR_IN_DEV; + 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; - case UBTBCMFW_BULK_OUT: - if (sc->sc_bulk_out_pipe != NULL) - usbd_abort_pipe(sc->sc_bulk_out_pipe); - - sc->sc_flags &= ~UBTBCMFW_BULK_OUT_DEV; + 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 */ - return (0); -} - /* - * Read from the endpoint device - * XXX FIXME softc locking + * Called when we about to start read()ing from the device */ -static int -ubtbcmfw_read(struct cdev *dev, struct uio *uio, int flag) +static void +ubtbcmfw_start_read(struct usb2_fifo *fifo) { - ubtbcmfw_softc_p sc = dev->si_drv1; - u_int8_t buf[UBTBCMFW_BSIZE]; - usbd_xfer_handle xfer; - usbd_status err; - int n, tn, error = 0; + struct ubtbcmfw_softc *sc = fifo->priv_sc0; - if (sc->sc_dying) - return (ENXIO); + usb2_transfer_start(sc->sc_xfer[UBTBCMFW_INTR_DT_RD]); +} /* ubtbcmfw_start_read */ - if (dev2unit(dev) != UBTBCMFW_INTR_IN) - return (EOPNOTSUPP); - if (sc->sc_intr_in_pipe == NULL) - return (ENXIO); +/* + * Called when we about to stop reading (i.e. closing fifo) + */ - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == NULL) - return (ENOMEM); +static void +ubtbcmfw_stop_read(struct usb2_fifo *fifo) +{ + struct ubtbcmfw_softc *sc = fifo->priv_sc0; - sc->sc_refcnt ++; + usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_INTR_DT_RD]); +} /* ubtbcmfw_stop_read */ - while ((n = min(sizeof(buf), uio->uio_resid)) != 0) { - tn = n; - err = usbd_bulk_transfer(xfer, sc->sc_intr_in_pipe, - USBD_SHORT_XFER_OK, USBD_DEFAULT_TIMEOUT, - buf, &tn, "bcmrd"); - switch (err) { - case USBD_NORMAL_COMPLETION: - error = uiomove(buf, tn, uio); - break; +/* + * Called when we about to start write()ing to the device, poll()ing + * for write or flushing fifo + */ - case USBD_INTERRUPTED: - error = EINTR; - break; +static void +ubtbcmfw_start_write(struct usb2_fifo *fifo) +{ + struct ubtbcmfw_softc *sc = fifo->priv_sc0; - case USBD_TIMEOUT: - error = ETIMEDOUT; - break; + usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_DT_WR]); +} /* ubtbcmfw_start_write */ - default: - error = EIO; - break; - } +/* + * Called when we about to stop writing (i.e. closing fifo) + */ - if (error != 0 || tn < n) - break; - } +static void +ubtbcmfw_stop_write(struct usb2_fifo *fifo) +{ + struct ubtbcmfw_softc *sc = fifo->priv_sc0; - usbd_free_xfer(xfer); + usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_BULK_DT_WR]); +} /* ubtbcmfw_stop_write */ - if (-- sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - - return (error); -} - /* - * Write into the endpoint device - * XXX FIXME softc locking + * Called when fifo is open */ static int -ubtbcmfw_write(struct cdev *dev, struct uio *uio, int flag) +ubtbcmfw_open(struct usb2_fifo *fifo, int fflags) { - ubtbcmfw_softc_p sc = dev->si_drv1; - u_int8_t buf[UBTBCMFW_BSIZE]; - usbd_xfer_handle xfer; - usbd_status err; - int n, error = 0; + struct ubtbcmfw_softc *sc = fifo->priv_sc0; + struct usb2_xfer *xfer; - if (sc->sc_dying) - return (ENXIO); + /* + * f_open fifo method can only be called with either FREAD + * or FWRITE flag set at one time. + */ - if (dev2unit(dev) != UBTBCMFW_BULK_OUT) - return (EOPNOTSUPP); - if (sc->sc_bulk_out_pipe == NULL) - return (ENXIO); + 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 */ - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == NULL) + if (usb2_fifo_alloc_buffer(fifo, xfer->max_data_length, + UBTBCMFW_IFQ_MAXLEN) != 0) return (ENOMEM); - sc->sc_refcnt ++; + return (0); +} /* ubtbcmfw_open */ - while ((n = min(sizeof(buf), uio->uio_resid)) != 0) { - error = uiomove(buf, n, uio); - if (error != 0) - break; +/* + * Called when fifo is closed + */ - err = usbd_bulk_transfer(xfer, sc->sc_bulk_out_pipe, - 0, USBD_DEFAULT_TIMEOUT, buf, &n, "bcmwr"); - switch (err) { - case USBD_NORMAL_COMPLETION: - break; - - case USBD_INTERRUPTED: - error = EINTR; - break; +static void +ubtbcmfw_close(struct usb2_fifo *fifo, int fflags) +{ + if (fflags & (FREAD | FWRITE)) + usb2_fifo_free_buffer(fifo); +} /* ubtbcmfw_close */ - case USBD_TIMEOUT: - error = ETIMEDOUT; - break; - - default: - error = EIO; - break; - } - - if (error != 0) - break; - } - - usbd_free_xfer(xfer); - - if (-- sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - - return (error); -} - /* - * Process ioctl on the endpoint device - * XXX FIXME softc locking + * Process ioctl() on USB device */ static int -ubtbcmfw_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, - struct thread *p) +ubtbcmfw_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data, + int fflags) { - ubtbcmfw_softc_p sc = dev->si_drv1; + struct ubtbcmfw_softc *sc = fifo->priv_sc0; int error = 0; - if (sc->sc_dying) - return (ENXIO); - - if (dev2unit(dev) != USB_CONTROL_ENDPOINT) - return (EOPNOTSUPP); - - sc->sc_refcnt ++; - switch (cmd) { case USB_GET_DEVICE_DESC: - *(usb_device_descriptor_t *) data = - *usbd_get_device_descriptor(sc->sc_udev); + memcpy(data, usb2_get_device_descriptor(sc->sc_udev), + sizeof(struct usb2_device_descriptor)); break; default: @@ -518,42 +423,5 @@ break; } - if (-- sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -/* - * Poll the endpoint device - * XXX FIXME softc locking - */ - -static int -ubtbcmfw_poll(struct cdev *dev, int events, struct thread *p) -{ - ubtbcmfw_softc_p sc = dev->si_drv1; - int revents = 0; - >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905281713.n4SHDAg8072243>