From owner-svn-src-all@FreeBSD.ORG Wed Jan 28 20:06:02 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8E761106567F; Wed, 28 Jan 2009 20:06:02 +0000 (UTC) (envelope-from emax@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7AB6C8FC23; Wed, 28 Jan 2009 20:06:02 +0000 (UTC) (envelope-from emax@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n0SK621c032131; Wed, 28 Jan 2009 20:06:02 GMT (envelope-from emax@svn.freebsd.org) Received: (from emax@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n0SK62pa032130; Wed, 28 Jan 2009 20:06:02 GMT (envelope-from emax@svn.freebsd.org) Message-Id: <200901282006.n0SK62pa032130@svn.freebsd.org> From: Maksim Yevmenkin Date: Wed, 28 Jan 2009 20:06:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r187866 - head/sys/dev/usb2/bluetooth X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 28 Jan 2009 20:06:05 -0000 Author: emax Date: Wed Jan 28 20:06:02 2009 New Revision: 187866 URL: http://svn.freebsd.org/changeset/base/187866 Log: Update ubtbcmfw2 (aka usb2_bluetooth_fw) driver Reviewed by: HPS Modified: head/sys/dev/usb2/bluetooth/ubtbcmfw2.c Modified: head/sys/dev/usb2/bluetooth/ubtbcmfw2.c ============================================================================== --- head/sys/dev/usb2/bluetooth/ubtbcmfw2.c Wed Jan 28 20:04:39 2009 (r187865) +++ head/sys/dev/usb2/bluetooth/ubtbcmfw2.c Wed Jan 28 20:06:02 2009 (r187866) @@ -3,7 +3,7 @@ */ /*- - * Copyright (c) 2003 Maksim Yevmenkin + * Copyright (c) 2003-2009 Maksim Yevmenkin * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,107 +54,85 @@ #define UBTBCMFW_CONFIG_NO 1 /* Config number */ #define UBTBCMFW_IFACE_IDX 0 /* Control interface */ -#define UBTBCMFW_T_MAX 4 /* units */ + +#define UBTBCMFW_BSIZE 1024 +#define UBTBCMFW_IFQ_MAXLEN 2 enum { - UBTBCMFW_BULK_DT_WR, - UBTBCMFW_BULK_DT_RD, - UBTBCMFW_BULK_CS_WR, - UBTBCMFW_BULK_CS_RD, - UBTBCMFW_N_TRANSFER = 4, + UBTBCMFW_BULK_DT_WR = 0, + UBTBCMFW_INTR_DT_RD, + UBTBCMFW_N_TRANSFER, }; struct ubtbcmfw_softc { - struct usb2_fifo_sc sc_fifo; - struct mtx sc_mtx; - - device_t sc_dev; - struct usb2_device *sc_udev; - struct usb2_xfer *sc_xfer[UBTBCMFW_N_TRANSFER]; - - uint8_t sc_flags; -#define UBTBCMFW_FLAG_WRITE_STALL 0x01 -#define UBTBCMFW_FLAG_READ_STALL 0x02 + struct usb2_device *sc_udev; + struct mtx sc_mtx; + struct usb2_xfer *sc_xfer[UBTBCMFW_N_TRANSFER]; + struct usb2_fifo_sc sc_fifo; }; -#define UBTBCMFW_BSIZE 1024 -#define UBTBCMFW_IFQ_MAXLEN 2 - -/* prototypes */ +/* + * 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_write_clear_stall_callback; -static usb2_callback_t ubtbcmfw_read_callback; -static usb2_callback_t ubtbcmfw_read_clear_stall_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", +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", }; -static const struct usb2_config ubtbcmfw_config[UBTBCMFW_T_MAX] = { +/* + * 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, - .mh.bufsize = UBTBCMFW_BSIZE, - .mh.flags = {.pipe_bof = 1,.proxy_buffer = 1,}, - .mh.callback = &ubtbcmfw_write_callback, + .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_BULK_DT_RD] = { - .type = UE_INTERRUPT, - .endpoint = 0x01, /* fixed */ - .direction = UE_DIR_IN, - .mh.bufsize = UBTBCMFW_BSIZE, - .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,}, - .mh.callback = &ubtbcmfw_read_callback, - }, - - [UBTBCMFW_BULK_CS_WR] = { - .type = UE_CONTROL, - .endpoint = 0x00, /* Control pipe */ - .direction = UE_DIR_ANY, - .mh.bufsize = sizeof(struct usb2_device_request), - .mh.flags = {}, - .mh.callback = &ubtbcmfw_write_clear_stall_callback, - .mh.timeout = 1000, /* 1 second */ - .mh.interval = 50, /* 50ms */ - }, - - [UBTBCMFW_BULK_CS_RD] = { - .type = UE_CONTROL, - .endpoint = 0x00, /* Control pipe */ - .direction = UE_DIR_ANY, - .mh.bufsize = sizeof(struct usb2_device_request), - .mh.flags = {}, - .mh.callback = &ubtbcmfw_read_clear_stall_callback, - .mh.timeout = 1000, /* 1 second */ - .mh.interval = 50, /* 50ms */ + [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, }, }; @@ -162,19 +140,21 @@ static const struct usb2_config ubtbcmfw * Module */ -static devclass_t ubtbcmfw_devclass; +static devclass_t ubtbcmfw_devclass; -static device_method_t ubtbcmfw_methods[] = { +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), +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); @@ -188,21 +168,21 @@ MODULE_DEPEND(ubtbcmfw, usb2_core, 1, 1, static int ubtbcmfw_probe(device_t dev) { - struct usb2_attach_arg *uaa = device_get_ivars(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) { + if (uaa->usb2_mode != USB_MODE_HOST) return (ENXIO); - } + if (uaa->info.bIfaceIndex != 0) return (ENXIO); - /* Match the boot device. */ - if (uaa->info.idVendor == USB_VENDOR_BROADCOM && - uaa->info.idProduct == USB_PRODUCT_BROADCOM_BCM2033) - return (0); - - return (ENXIO); -} + return (usb2_lookup_id_by_uaa(devs, sizeof(devs), uaa)); +} /* ubtbcmfw_probe */ /* * Attach the device @@ -211,15 +191,11 @@ ubtbcmfw_probe(device_t dev) static int ubtbcmfw_attach(device_t dev) { - struct usb2_attach_arg *uaa = device_get_ivars(dev); - struct ubtbcmfw_softc *sc = device_get_softc(dev); - int32_t err; - uint8_t iface_index; + struct usb2_attach_arg *uaa = device_get_ivars(dev); + struct ubtbcmfw_softc *sc = device_get_softc(dev); + uint8_t iface_index; + int error; - if (sc == NULL) { - return (ENOMEM); - } - sc->sc_dev = dev; sc->sc_udev = uaa->device; device_set_usb2_desc(dev); @@ -227,30 +203,35 @@ ubtbcmfw_attach(device_t dev) mtx_init(&sc->sc_mtx, "ubtbcmfw lock", NULL, MTX_DEF | MTX_RECURSE); iface_index = UBTBCMFW_IFACE_IDX; - err = usb2_transfer_setup(uaa->device, - &iface_index, sc->sc_xfer, ubtbcmfw_config, - UBTBCMFW_T_MAX, sc, &sc->sc_mtx); - if (err) { - device_printf(dev, "allocating USB transfers " - "failed, err=%s\n", usb2_errstr(err)); + 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 */ + + /* Set interface permissions */ usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, - UID_ROOT, GID_OPERATOR, 0644); + UID_ROOT, GID_OPERATOR, 0644); - err = 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 (err) { + 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 */ + + return (0); /* success */ detach: ubtbcmfw_detach(dev); - return (ENOMEM); /* failure */ -} + + return (ENXIO); /* failure */ +} /* ubtbcmfw_attach */ /* * Detach the device @@ -259,191 +240,192 @@ detach: static int ubtbcmfw_detach(device_t dev) { - struct ubtbcmfw_softc *sc = device_get_softc(dev); + struct ubtbcmfw_softc *sc = device_get_softc(dev); usb2_fifo_detach(&sc->sc_fifo); - usb2_transfer_unsetup(sc->sc_xfer, UBTBCMFW_T_MAX); + 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_RX]; - uint32_t actlen; + 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_TRANSFERRED: case USB_ST_SETUP: - if (sc->sc_flags & UBTBCMFW_FLAG_WRITE_STALL) { - usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_CS_WR]); - return; - } + case USB_ST_TRANSFERRED: +setup_next: if (usb2_fifo_get_data(f, xfer->frbuffers, 0, - UBTBCMFW_BSIZE, &actlen, 0)) { - + xfer->max_data_length, &actlen, 0)) { xfer->frlengths[0] = actlen; usb2_start_hardware(xfer); } - return; + break; - default: /* Error */ + default: /* Error */ if (xfer->error != USB_ERR_CANCELLED) { /* try to clear stall first */ - sc->sc_flags |= UBTBCMFW_FLAG_WRITE_STALL; - usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_CS_WR]); + xfer->flags.stall_pipe = 1; + goto setup_next; } - return; + break; } -} - -static void -ubtbcmfw_write_clear_stall_callback(struct usb2_xfer *xfer) -{ - struct ubtbcmfw_softc *sc = xfer->priv_sc; - struct usb2_xfer *xfer_other = sc->sc_xfer[UBTBCMFW_BULK_DT_WR]; +} /* ubtbcmfw_write_callback */ - if (usb2_clear_stall_callback(xfer, xfer_other)) { - DPRINTF("stall cleared\n"); - sc->sc_flags &= ~UBTBCMFW_FLAG_WRITE_STALL; - usb2_transfer_start(xfer_other); - } -} +/* + * USB read callback + */ static void ubtbcmfw_read_callback(struct usb2_xfer *xfer) { - struct ubtbcmfw_softc *sc = xfer->priv_sc; - struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_RX]; + 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(f, xfer->frbuffers, - 0, xfer->actlen, 1); + usb2_fifo_put_data(fifo, xfer->frbuffers, 0, xfer->actlen, 1); + /* FALLTHROUGH */ case USB_ST_SETUP: - if (sc->sc_flags & UBTBCMFW_FLAG_READ_STALL) { - usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_CS_RD]); - return; - } - if (usb2_fifo_put_bytes_max(f) != 0) { +setup_next: + if (usb2_fifo_put_bytes_max(fifo) > 0) { xfer->frlengths[0] = xfer->max_data_length; usb2_start_hardware(xfer); } - return; + break; - default: /* Error */ + default: /* Error */ if (xfer->error != USB_ERR_CANCELLED) { /* try to clear stall first */ - sc->sc_flags |= UBTBCMFW_FLAG_READ_STALL; - usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_CS_RD]); + xfer->flags.stall_pipe = 1; + goto setup_next; } - return; + break; } -} - -static void -ubtbcmfw_read_clear_stall_callback(struct usb2_xfer *xfer) -{ - struct ubtbcmfw_softc *sc = xfer->priv_sc; - struct usb2_xfer *xfer_other = sc->sc_xfer[UBTBCMFW_BULK_DT_RD]; +} /* ubtbcmfw_read_callback */ - if (usb2_clear_stall_callback(xfer, xfer_other)) { - DPRINTF("stall cleared\n"); - sc->sc_flags &= ~UBTBCMFW_FLAG_READ_STALL; - usb2_transfer_start(xfer_other); - } -} +/* + * 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; + struct ubtbcmfw_softc *sc = fifo->priv_sc0; - usb2_transfer_start(sc->sc_xfer[UBTBCMFW_BULK_DT_RD]); -} + 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; + struct ubtbcmfw_softc *sc = fifo->priv_sc0; + + usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_INTR_DT_RD]); +} /* ubtbcmfw_stop_read */ - usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_BULK_CS_RD]); - usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_BULK_DT_RD]); -} +/* + * 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; + 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; + struct ubtbcmfw_softc *sc = fifo->priv_sc0; - usb2_transfer_stop(sc->sc_xfer[UBTBCMFW_BULK_CS_WR]); 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 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); /* XXX can happen? */ + + if (usb2_fifo_alloc_buffer(fifo, xfer->max_data_length, + UBTBCMFW_IFQ_MAXLEN) != 0) + return (ENOMEM); - if (fflags & FREAD) { - if (usb2_fifo_alloc_buffer(fifo, - sc->sc_xfer[UBTBCMFW_BULK_DT_RD]->max_data_length, - UBTBCMFW_IFQ_MAXLEN)) { - return (ENOMEM); - } - } - if (fflags & FWRITE) { - /* clear stall first */ - mtx_lock(&sc->sc_mtx); - sc->sc_flags |= UBTBCMFW_FLAG_WRITE_STALL; - mtx_unlock(&sc->sc_mtx); - if (usb2_fifo_alloc_buffer(fifo, - sc->sc_xfer[UBTBCMFW_BULK_DT_WR]->max_data_length, - UBTBCMFW_IFQ_MAXLEN)) { - 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)) { + 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; + struct ubtbcmfw_softc *sc = fifo->priv_sc0; + int error = 0; switch (cmd) { case USB_GET_DEVICE_DESC: - *(struct usb2_device_descriptor *)data = - *usb2_get_device_descriptor(sc->sc_udev); + memcpy(data, usb2_get_device_descriptor(sc->sc_udev), + sizeof(struct usb2_device_descriptor)); break; default: error = EINVAL; break; } + return (error); -} +} /* ubtbcmfw_ioctl */