PERFORCE change 106227 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sun Sep 17 02:39:26 PDT 2006
http://perforce.freebsd.org/chv.cgi?CH=106227
Change 106227 by hselasky at hselasky_mini_itx on 2006/09/17 09:38:36
Finished reworking "ubtbcmfw". Please test!
Affected files ...
.. //depot/projects/usb/src/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c#2 edit
Differences ...
==== //depot/projects/usb/src/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c#2 (text+ko) ====
@@ -33,20 +33,14 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/filio.h>
+#include <sys/kernel.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 <sys/ioccom.h>
+#include <sys/syslog.h>
+#include <dev/usb/usb_port.h>
#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usb_subr.h>
#include "usbdevs.h"
@@ -56,81 +50,141 @@
#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_T_MAX 4 /* units */
struct ubtbcmfw_softc {
- USBBASEDEVICE 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 usb_cdev sc_cdev;
+ struct mtx sc_mtx;
+ struct usbd_memory_wait sc_mem_wait;
+
+ device_t sc_dev;
+ struct usbd_device *sc_udev;
+ struct usbd_xfer *sc_xfer[UBTBCMFW_T_MAX];
+
+ u_int8_t sc_flags;
+#define UBTBCMFW_FLAG_WRITE_STALL 0x01
+#define UBTBCMFW_FLAG_READ_STALL 0x02
};
-typedef struct ubtbcmfw_softc *ubtbcmfw_softc_p;
+#define UBTBCMFW_BSIZE 1024
+#define UBTBCMFW_IFQ_MAXLEN 2
+
+/* prototypes */
+
+static device_probe_t ubtbcmfw_probe;
+static device_attach_t ubtbcmfw_attach;
+static device_detach_t ubtbcmfw_detach;
+
+static void
+ubtbcmfw_write_callback(struct usbd_xfer *xfer);
+
+static void
+ubtbcmfw_write_clear_stall_callback(struct usbd_xfer *xfer);
+
+static void
+ubtbcmfw_read_callback(struct usbd_xfer *xfer);
+
+static void
+ubtbcmfw_read_clear_stall_callback(struct usbd_xfer *xfer);
+
+static void
+ubtbcmfw_start_read(struct usb_cdev *cdev);
+
+static void
+ubtbcmfw_stop_read(struct usb_cdev *cdev);
+
+static void
+ubtbcmfw_start_write(struct usb_cdev *cdev);
+
+static void
+ubtbcmfw_stop_write(struct usb_cdev *cdev);
+
+static int32_t
+ubtbcmfw_open(struct usb_cdev *cdev, int32_t fflags,
+ int32_t devtype, struct thread *td);
+static int32_t
+ubtbcmfw_ioctl(struct usb_cdev *cdev, u_long cmd, caddr_t data,
+ int32_t fflags, struct thread *td);
+
+static const struct usbd_config ubtbcmfw_config[UBTBCMFW_T_MAX] = {
-/*
- * Device methods
- */
+ [0] = {
+ .type = UE_BULK,
+ .endpoint = 0x02, /* fixed */
+ .direction = UE_DIR_OUT,
+ .bufsize = UBTBCMFW_BSIZE,
+ .flags = 0,
+ .callback = &ubtbcmfw_write_callback,
+ },
-#define UBTBCMFW_UNIT(n) ((minor(n) >> 4) & 0xf)
-#define UBTBCMFW_ENDPOINT(n) (minor(n) & 0xf)
-#define UBTBCMFW_MINOR(u, e) (((u) << 4) | (e))
-#define UBTBCMFW_BSIZE 1024
+ [1] = {
+ .type = UE_INTERRUPT,
+ .endpoint = 0x01, /* fixed */
+ .direction = UE_DIR_IN,
+ .bufsize = UBTBCMFW_BSIZE,
+ .flags = USBD_SHORT_XFER_OK,
+ .callback = &ubtbcmfw_read_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;
+ [2] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .flags = USBD_USE_DMA,
+ .callback = &ubtbcmfw_write_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ },
-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",
+ [3] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .flags = USBD_USE_DMA,
+ .callback = &ubtbcmfw_read_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ },
};
/*
* Module
*/
-USB_DECLARE_DRIVER(ubtbcmfw);
-DRIVER_MODULE(ubtbcmfw, uhub, ubtbcmfw_driver, ubtbcmfw_devclass,
+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, uhub, ubtbcmfw_driver, ubtbcmfw_devclass,
usbd_driver_load, 0);
+MODULE_DEPEND(ubtbcmfw, usb, 1, 1, 1);
/*
* Probe for a USB Bluetooth device
*/
-USB_MATCH(ubtbcmfw)
+static int
+ubtbcmfw_probe(device_t dev)
{
-#define USB_PRODUCT_BROADCOM_BCM2033NF 0x2033
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
- USB_MATCH_START(ubtbcmfw, uaa);
-
if (uaa->iface != NULL)
return (UMATCH_NONE);
/* Match the boot device. */
if (uaa->vendor == USB_VENDOR_BROADCOM &&
- uaa->product == USB_PRODUCT_BROADCOM_BCM2033NF)
+ uaa->product == USB_PRODUCT_BROADCOM_BCM2033)
return (UMATCH_VENDOR_PRODUCT);
return (UMATCH_NONE);
@@ -140,364 +194,273 @@
* Attach the device
*/
-USB_ATTACH(ubtbcmfw)
+static int
+ubtbcmfw_attach(device_t dev)
{
- USB_ATTACH_START(ubtbcmfw, sc, uaa);
- usbd_interface_handle iface;
- usbd_status err;
- char devinfo[1024];
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ struct ubtbcmfw_softc *sc = device_get_softc(dev);
+ int32_t err;
+ const char *p_buf[4];
+ char buf_1[32];
+ char buf_2[32];
+ char buf_3[32];
+
+ if (sc == NULL) {
+ return ENOMEM;
+ }
+ sc->sc_dev = dev;
sc->sc_udev = uaa->device;
- usbd_devinfo(sc->sc_udev, 0, devinfo);
- USB_ATTACH_SETUP;
- printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
+
+ usbd_set_desc(dev, 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;
+ mtx_init(&(sc->sc_mtx), "ubtbcmfw lock", NULL, MTX_DEF|MTX_RECURSE);
err = usbd_set_config_no(sc->sc_udev, UBTBCMFW_CONFIG_NO, 1);
if (err) {
- printf("%s: setting config no failed. %s\n",
- USBDEVNAME(sc->sc_dev), usbd_errstr(err));
- goto bad;
+ device_printf(dev, "setting config no failed, err=%s\n",
+ usbd_errstr(err));
+ goto detach;;
}
- err = usbd_device2interface_handle(sc->sc_udev, UBTBCMFW_IFACE_IDX,
- &iface);
+ err = usbd_transfer_setup(uaa->device, UBTBCMFW_IFACE_IDX,
+ sc->sc_xfer, ubtbcmfw_config, UBTBCMFW_T_MAX,
+ sc, &(sc->sc_mtx), &(sc->sc_mem_wait));
if (err) {
- printf("%s: getting interface handle failed. %s\n",
- USBDEVNAME(sc->sc_dev), usbd_errstr(err));
- goto bad;
+ device_printf(dev, "allocating USB transfers "
+ "failed, err=%s\n", usbd_errstr(err));
+ 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",
- USBDEVNAME(sc->sc_dev), usbd_errstr(err));
- goto bad;
- }
+ snprintf(buf_1, sizeof(buf_1), "%s",
+ device_get_nameunit(dev));
+
+ snprintf(buf_2, sizeof(buf_2), "%s.1",
+ device_get_nameunit(dev));
+
+ snprintf(buf_3, sizeof(buf_3), "%s.2",
+ device_get_nameunit(dev));
+
+ p_buf[0] = buf_1;
+ p_buf[1] = buf_2;
+ p_buf[2] = buf_3;
+ p_buf[3] = NULL;
+
+ sc->sc_cdev.sc_start_read = &ubtbcmfw_start_read;
+ sc->sc_cdev.sc_start_write = &ubtbcmfw_start_write;
+ sc->sc_cdev.sc_stop_read = &ubtbcmfw_stop_read;
+ sc->sc_cdev.sc_stop_write = &ubtbcmfw_stop_write;
+ sc->sc_cdev.sc_open = &ubtbcmfw_open;
+ sc->sc_cdev.sc_ioctl = &ubtbcmfw_ioctl;
+ sc->sc_cdev.sc_flags |= (USB_CDEV_FLAG_FWD_SHORT|
+ USB_CDEV_FLAG_WAKEUP_RD_IMMED|
+ USB_CDEV_FLAG_WAKEUP_WR_IMMED);
- err = usbd_open_pipe(iface, UBTBCMFW_BULK_OUT_EP, 0,
- &sc->sc_bulk_out_pipe);
+ err = usb_cdev_attach(&(sc->sc_cdev), sc, &(sc->sc_mtx), p_buf,
+ UID_ROOT, GID_OPERATOR, 0644,
+ UBTBCMFW_BSIZE, UBTBCMFW_IFQ_MAXLEN,
+ UBTBCMFW_BSIZE, UBTBCMFW_IFQ_MAXLEN);
if (err) {
- printf("%s: open bulk out failed. %s\n",
- USBDEVNAME(sc->sc_dev), usbd_errstr(err));
- goto bad;
+ goto detach;
}
- /* Create device nodes */
- sc->sc_ctrl_dev = make_dev(&ubtbcmfw_cdevsw,
- UBTBCMFW_MINOR(USBDEVUNIT(sc->sc_dev), 0),
- UID_ROOT, GID_OPERATOR, 0644,
- "%s", USBDEVNAME(sc->sc_dev));
+ return 0; /* success */
- sc->sc_intr_in_dev = make_dev(&ubtbcmfw_cdevsw,
- UBTBCMFW_MINOR(USBDEVUNIT(sc->sc_dev), UBTBCMFW_INTR_IN),
- UID_ROOT, GID_OPERATOR, 0644,
- "%s.%d", USBDEVNAME(sc->sc_dev), UBTBCMFW_INTR_IN);
-
- sc->sc_bulk_out_dev = make_dev(&ubtbcmfw_cdevsw,
- UBTBCMFW_MINOR(USBDEVUNIT(sc->sc_dev), UBTBCMFW_BULK_OUT),
- UID_ROOT, GID_OPERATOR, 0644,
- "%s.%d", USBDEVNAME(sc->sc_dev), UBTBCMFW_BULK_OUT);
-
- USB_ATTACH_SUCCESS_RETURN;
-bad:
- ubtbcmfw_detach(self);
-
- USB_ATTACH_ERROR_RETURN;
+ detach:
+ ubtbcmfw_detach(dev);
+ return ENOMEM; /* failure */
}
/*
* Detach the device
*/
-USB_DETACH(ubtbcmfw)
+static int
+ubtbcmfw_detach(device_t dev)
{
- USB_DETACH_START(ubtbcmfw, sc);
+ struct ubtbcmfw_softc *sc = device_get_softc(dev);
+
+ usb_cdev_detach(&(sc->sc_cdev));
- sc->sc_dying = 1;
+ usbd_transfer_unsetup(sc->sc_xfer, UBTBCMFW_T_MAX);
- if (-- sc->sc_refcnt >= 0) {
- if (sc->sc_intr_in_pipe != NULL)
- usbd_abort_pipe(sc->sc_intr_in_pipe);
+ usbd_transfer_drain(&(sc->sc_mem_wait), &(sc->sc_mtx));
- if (sc->sc_bulk_out_pipe != NULL)
- usbd_abort_pipe(sc->sc_bulk_out_pipe);
+ mtx_destroy(&(sc->sc_mtx));
- usb_detach_wait(USBDEV(sc->sc_dev));
- }
+ return (0);
+}
- /* Destroy device nodes */
- if (sc->sc_bulk_out_dev != NULL) {
- destroy_dev(sc->sc_bulk_out_dev);
- sc->sc_bulk_out_dev = NULL;
- }
+static void
+ubtbcmfw_write_callback(struct usbd_xfer *xfer)
+{
+ struct ubtbcmfw_softc *sc = xfer->priv_sc;
+ u_int32_t actlen;
- if (sc->sc_intr_in_dev != NULL) {
- destroy_dev(sc->sc_intr_in_dev);
- sc->sc_intr_in_dev = NULL;
- }
+ USBD_CHECK_STATUS(xfer);
- if (sc->sc_ctrl_dev != NULL) {
- destroy_dev(sc->sc_ctrl_dev);
- sc->sc_ctrl_dev = NULL;
+ tr_transferred:
+ tr_setup:
+ if (sc->sc_flags & UBTBCMFW_FLAG_WRITE_STALL) {
+ usbd_transfer_start(sc->sc_xfer[2]);
+ return;
}
+ if (usb_cdev_get_data(&(sc->sc_cdev), xfer->buffer,
+ UBTBCMFW_BSIZE, &actlen, 0)) {
- /* Close pipes */
- if (sc->sc_intr_in_pipe != NULL) {
- usbd_close_pipe(sc->sc_intr_in_pipe);
- sc->sc_intr_in_pipe = NULL;
+ xfer->length = actlen;
+ usbd_start_hardware(xfer);
}
+ return;
- if (sc->sc_bulk_out_pipe != NULL) {
- usbd_close_pipe(sc->sc_bulk_out_pipe);
- sc->sc_intr_in_pipe = NULL;
+ tr_error:
+ if (xfer->error != USBD_CANCELLED) {
+ /* try to clear stall first */
+ sc->sc_flags |= UBTBCMFW_FLAG_WRITE_STALL;
+ usbd_transfer_start(sc->sc_xfer[2]);
}
-
- return (0);
+ return;
}
-/*
- * Open endpoint device
- * XXX FIXME softc locking
- */
-
-Static int
-ubtbcmfw_open(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
+static void
+ubtbcmfw_write_clear_stall_callback(struct usbd_xfer *xfer)
{
- ubtbcmfw_softc_p sc = NULL;
- int error = 0;
+ struct ubtbcmfw_softc *sc = xfer->priv_sc;
+ struct usbd_xfer *xfer_other = sc->sc_xfer[0];
- /* checks for sc != NULL */
- USB_GET_SC_OPEN(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
- if (sc->sc_dying)
- return (ENXIO);
+ USBD_CHECK_STATUS(xfer);
- switch (UBTBCMFW_ENDPOINT(dev)) {
- case USB_CONTROL_ENDPOINT:
- if (!(sc->sc_flags & UBTBCMFW_CTRL_DEV))
- sc->sc_flags |= UBTBCMFW_CTRL_DEV;
- else
- error = EBUSY;
- break;
+ tr_setup:
+ /* start clear stall */
+ usbd_clear_stall_tr_setup(xfer, xfer_other);
+ return;
- 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;
- break;
+ tr_transferred:
+ usbd_clear_stall_tr_transferred(xfer, xfer_other);
- 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;
+ sc->sc_flags &= ~UBTBCMFW_FLAG_WRITE_STALL;
+ usbd_transfer_start(xfer_other);
+ return;
- default:
- error = ENXIO;
- break;
- }
-
- return (error);
+ tr_error:
+ /* bomb out */
+ sc->sc_flags &= ~UBTBCMFW_FLAG_WRITE_STALL;
+ usb_cdev_get_data_error(&(sc->sc_cdev));
+ return;
}
-/*
- * Close endpoint device
- * XXX FIXME softc locking
- */
-
-Static int
-ubtbcmfw_close(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
+static void
+ubtbcmfw_read_callback(struct usbd_xfer *xfer)
{
- ubtbcmfw_softc_p sc = NULL;
+ struct ubtbcmfw_softc *sc = xfer->priv_sc;
+ struct usbd_mbuf *m;
- USB_GET_SC(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
- if (sc == NULL)
- return (ENXIO);
+ USBD_CHECK_STATUS(xfer);
- switch (UBTBCMFW_ENDPOINT(dev)) {
- case USB_CONTROL_ENDPOINT:
- sc->sc_flags &= ~UBTBCMFW_CTRL_DEV;
- break;
+ tr_transferred:
+ usb_cdev_put_data(&(sc->sc_cdev), xfer->buffer, xfer->actlen, 1);
- case UBTBCMFW_INTR_IN:
- if (sc->sc_intr_in_pipe != NULL)
- usbd_abort_pipe(sc->sc_intr_in_pipe);
+ tr_setup:
+ if (sc->sc_flags & UBTBCMFW_FLAG_READ_STALL) {
+ usbd_transfer_start(sc->sc_xfer[3]);
+ return;
+ }
- sc->sc_flags &= ~UBTBCMFW_INTR_IN_DEV;
- break;
+ USBD_IF_POLL(&sc->sc_cdev.sc_rdq_free, m);
- case UBTBCMFW_BULK_OUT:
- if (sc->sc_bulk_out_pipe != NULL)
- usbd_abort_pipe(sc->sc_bulk_out_pipe);
+ if (m) {
+ usbd_start_hardware(xfer);
+ }
+ return;
- sc->sc_flags &= ~UBTBCMFW_BULK_OUT_DEV;
- break;
+ tr_error:
+ if (xfer->error != USBD_CANCELLED) {
+ /* try to clear stall first */
+ sc->sc_flags |= UBTBCMFW_FLAG_READ_STALL;
+ usbd_transfer_start(sc->sc_xfer[3]);
}
-
- return (0);
+ return;
}
-/*
- * Read from the endpoint device
- * XXX FIXME softc locking
- */
-
-Static int
-ubtbcmfw_read(struct cdev *dev, struct uio *uio, int flag)
+static void
+ubtbcmfw_read_clear_stall_callback(struct usbd_xfer *xfer)
{
- ubtbcmfw_softc_p sc = NULL;
- u_int8_t buf[UBTBCMFW_BSIZE];
- usbd_xfer_handle xfer;
- usbd_status err;
- int n, tn, error = 0;
+ struct ubtbcmfw_softc *sc = xfer->priv_sc;
+ struct usbd_xfer *xfer_other = sc->sc_xfer[1];
- USB_GET_SC(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
- if (sc == NULL || sc->sc_dying)
- return (ENXIO);
+ USBD_CHECK_STATUS(xfer);
- if (UBTBCMFW_ENDPOINT(dev) != UBTBCMFW_INTR_IN)
- return (EOPNOTSUPP);
- if (sc->sc_intr_in_pipe == NULL)
- return (ENXIO);
+ tr_setup:
+ /* start clear stall */
+ usbd_clear_stall_tr_setup(xfer, xfer_other);
+ return;
- xfer = usbd_alloc_xfer(sc->sc_udev);
- if (xfer == NULL)
- return (ENOMEM);
+ tr_transferred:
+ usbd_clear_stall_tr_transferred(xfer, xfer_other);
- sc->sc_refcnt ++;
+ sc->sc_flags &= ~UBTBCMFW_FLAG_READ_STALL;
+ usbd_transfer_start(xfer_other);
+ return;
- 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;
+ tr_error:
+ /* bomb out */
+ sc->sc_flags &= ~UBTBCMFW_FLAG_READ_STALL;
+ usb_cdev_put_data_error(&(sc->sc_cdev));
+ return;
+}
- case USBD_INTERRUPTED:
- error = EINTR;
- break;
+static void
+ubtbcmfw_start_read(struct usb_cdev *cdev)
+{
+ struct ubtbcmfw_softc *sc = cdev->sc_priv_ptr;
+ usbd_transfer_start(sc->sc_xfer[1]);
+ return;
+}
- case USBD_TIMEOUT:
- error = ETIMEDOUT;
- break;
+static void
+ubtbcmfw_stop_read(struct usb_cdev *cdev)
+{
+ struct ubtbcmfw_softc *sc = cdev->sc_priv_ptr;
+ usbd_transfer_stop(sc->sc_xfer[3]);
+ usbd_transfer_stop(sc->sc_xfer[1]);
+ return;
+}
- default:
- error = EIO;
- break;
- }
+static void
+ubtbcmfw_start_write(struct usb_cdev *cdev)
+{
+ struct ubtbcmfw_softc *sc = cdev->sc_priv_ptr;
+ usbd_transfer_start(sc->sc_xfer[0]);
+ return;
+}
- if (error != 0 || tn < n)
- break;
- }
-
- usbd_free_xfer(xfer);
-
- if (-- sc->sc_refcnt < 0)
- usb_detach_wakeup(USBDEV(sc->sc_dev));
-
- return (error);
+static void
+ubtbcmfw_stop_write(struct usb_cdev *cdev)
+{
+ struct ubtbcmfw_softc *sc = cdev->sc_priv_ptr;
+ usbd_transfer_stop(sc->sc_xfer[2]);
+ usbd_transfer_stop(sc->sc_xfer[0]);
+ return;
}
-/*
- * Write into the endpoint device
- * XXX FIXME softc locking
- */
-
-Static int
-ubtbcmfw_write(struct cdev *dev, struct uio *uio, int flag)
+static int32_t
+ubtbcmfw_open(struct usb_cdev *cdev, int32_t fflags,
+ int32_t devtype, struct thread *td)
{
- ubtbcmfw_softc_p sc = NULL;
- u_int8_t buf[UBTBCMFW_BSIZE];
- usbd_xfer_handle xfer;
- usbd_status err;
- int n, error = 0;
+ struct ubtbcmfw_softc *sc = cdev->sc_priv_ptr;
- USB_GET_SC(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
- if (sc == NULL || sc->sc_dying)
- return (ENXIO);
-
- if (UBTBCMFW_ENDPOINT(dev) != UBTBCMFW_BULK_OUT)
- return (EOPNOTSUPP);
- if (sc->sc_bulk_out_pipe == NULL)
- return (ENXIO);
-
- xfer = usbd_alloc_xfer(sc->sc_udev);
- if (xfer == NULL)
- return (ENOMEM);
-
- sc->sc_refcnt ++;
-
- while ((n = min(sizeof(buf), uio->uio_resid)) != 0) {
- error = uiomove(buf, n, uio);
- if (error != 0)
- break;
-
- 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;
-
- case USBD_TIMEOUT:
- error = ETIMEDOUT;
- break;
-
- default:
- error = EIO;
- break;
- }
-
- if (error != 0)
- break;
+ if (fflags & FWRITE) {
+ sc->sc_flags |= UBTBCMFW_FLAG_WRITE_STALL;
}
-
- usbd_free_xfer(xfer);
-
- if (-- sc->sc_refcnt < 0)
- usb_detach_wakeup(USBDEV(sc->sc_dev));
-
- return (error);
+ return 0;
}
-/*
- * Process ioctl on the endpoint device
- * XXX FIXME softc locking
- */
-
-Static int
-ubtbcmfw_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, usb_proc_ptr p)
+static int32_t
+ubtbcmfw_ioctl(struct usb_cdev *cdev, u_long cmd, caddr_t data,
+ int32_t fflags, struct thread *td)
{
- ubtbcmfw_softc_p sc = NULL;
- int error = 0;
-
- USB_GET_SC(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
- if (sc == NULL || sc->sc_dying)
- return (ENXIO);
-
- if (UBTBCMFW_ENDPOINT(dev) != USB_CONTROL_ENDPOINT)
- return (EOPNOTSUPP);
-
- sc->sc_refcnt ++;
+ struct ubtbcmfw_softc *sc = cdev->sc_priv_ptr;
+ int32_t error = 0;
switch (cmd) {
case USB_GET_DEVICE_DESC:
@@ -510,47 +473,5 @@
break;
}
- if (-- sc->sc_refcnt < 0)
- usb_detach_wakeup(USBDEV(sc->sc_dev));
-
return (error);
}
-
-/*
- * Poll the endpoint device
- * XXX FIXME softc locking
- */
-
-Static int
-ubtbcmfw_poll(struct cdev *dev, int events, usb_proc_ptr p)
-{
- ubtbcmfw_softc_p sc = NULL;
- int revents = 0;
-
- USB_GET_SC(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
- if (sc == NULL)
- return (ENXIO);
-
- switch (UBTBCMFW_ENDPOINT(dev)) {
- case UBTBCMFW_INTR_IN:
- if (sc->sc_intr_in_pipe != NULL)
- revents |= events & (POLLIN | POLLRDNORM);
- else
- revents = ENXIO;
- break;
-
- case UBTBCMFW_BULK_OUT:
- if (sc->sc_bulk_out_pipe != NULL)
- revents |= events & (POLLOUT | POLLWRNORM);
- else
- revents = ENXIO;
- break;
-
- default:
- revents = EOPNOTSUPP;
- break;
- }
-
- return (revents);
-}
-
More information about the p4-projects
mailing list