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