Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 19 Apr 2008 08:18:20 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 140247 for review
Message-ID:  <200804190818.m3J8IKeL059030@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=140247

Change 140247 by hselasky@hselasky_laptop001 on 2008/04/19 08:18:02

	
	Import "uslcom" driver into the new USB API.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/uslcom.c#3 edit
.. //depot/projects/usb/src/sys/modules/uslcom/Makefile#2 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/uslcom.c#3 (text+ko) ====

@@ -1,4 +1,3 @@
-#if 0
 /*	$FreeBSD: src/sys/dev/usb/uslcom.c,v 1.2 2008/03/05 14:18:29 rink Exp $ */
 /*	$OpenBSD: uslcom.c,v 1.17 2007/11/24 10:52:12 jsg Exp $	*/
 
@@ -21,35 +20,37 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/conf.h>
-#include <sys/bus.h>
-#include <sys/tty.h>
+#include <sys/termios.h>
+#include <sys/serial.h>
 
+#include <dev/usb/usb_port.h>
 #include <dev/usb/usb.h>
-#include <dev/usb/usbcdc.h>
+#include <dev/usb/usb_subr.h>
 
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
+#include <dev/usb/ucomvar.h>
 
 #include "usbdevs.h"
-#include <dev/usb/ucomvar.h>
+
+#ifdef USB_DEBUG
+#define	DPRINTF(n,fmt,...)						\
+  do { if (uslcom_debug > (n)) {						\
+      printf("%s: " fmt, __FUNCTION__,## __VA_ARGS__); } } while (0)
 
-#ifdef USLCOM_DEBUG
-#define	DPRINTFN(n, x)  do { if (uslcomdebug > (n)) printf x; } while (0)
-int	uslcomdebug = 1;
+static int uslcom_debug = 0;
 
+SYSCTL_NODE(_hw_usb, OID_AUTO, uslcom, CTLFLAG_RW, 0, "USB uslcom");
+SYSCTL_INT(_hw_usb_uslcom, OID_AUTO, debug, CTLFLAG_RW,
+    &uslcom_debug, 0, "uslcom debug level");
 #else
-#define	DPRINTFN(n, x)
+#define	DPRINTF(...) do { } while (0)
 #endif
-#define	DPRINTF(x) DPRINTFN(0, x)
 
-#define	USLCOMBUFSZ		256
-#define	USLCOM_CONFIG_NO	0
-#define	USLCOM_IFACE_NO		0
+#define	USLCOM_BUF_SIZE 1024
+#define	USLCOM_N_DATA_TRANSFER 4
+#define	USLCOM_CONFIG_INDEX	0
+#define	USLCOM_IFACE_INDEX	0
 
-#define	USLCOM_SET_DATA_BITS(x)	(x << 8)
+#define	USLCOM_SET_DATA_BITS(x)	((x) << 8)
 
 #define	USLCOM_WRITE		0x41
 #define	USLCOM_READ		0xc1
@@ -71,7 +72,6 @@
 #define	USLCOM_CTRL_DSR		0x0020
 #define	USLCOM_CTRL_DCD		0x0080
 
-
 #define	USLCOM_BAUD_REF		0x384000
 
 #define	USLCOM_STOP_BITS_1	0x00
@@ -84,34 +84,100 @@
 #define	USLCOM_BREAK_OFF	0x00
 #define	USLCOM_BREAK_ON		0x01
 
-
 struct uslcom_softc {
+	struct ucom_super_softc sc_super_ucom;
 	struct ucom_softc sc_ucom;
-	device_t sc_dev;
-	usbd_device_handle sc_udev;
+
+	struct usbd_xfer *sc_xfer_data[USLCOM_N_DATA_TRANSFER];
+	struct usbd_device *sc_udev;
 
-	u_char	sc_msr;
-	u_char	sc_lsr;
+	uint8_t	sc_msr;
+	uint8_t	sc_lsr;
 
-	u_char	sc_dying;
+	uint8_t	sc_flag;
+#define	USLCOM_FLAG_READ_STALL  0x01
+#define	USLCOM_FLAG_WRITE_STALL 0x02
+#define	USLCOM_FLAG_INTR_STALL  0x04
 };
 
-void	uslcom_get_status(void *, int portno, u_char *lsr, u_char *msr);
-void	uslcom_set(void *, int, int, int);
-int	uslcom_param(void *, int, struct termios *);
-int	uslcom_open(void *sc, int portno);
-void	uslcom_close(void *, int);
-void	uslcom_break(void *sc, int portno, int onoff);
+static device_probe_t uslcom_probe;
+static device_attach_t uslcom_attach;
+static device_detach_t uslcom_detach;
+
+static usbd_callback_t uslcom_write_callback;
+static usbd_callback_t uslcom_read_callback;
+static usbd_callback_t uslcom_write_clear_stall_callback;
+static usbd_callback_t uslcom_read_clear_stall_callback;
+
+static void uslcom_start_read(struct ucom_softc *ucom);
+static void uslcom_stop_read(struct ucom_softc *ucom);
+static void uslcom_start_write(struct ucom_softc *ucom);
+static void uslcom_stop_write(struct ucom_softc *ucom);
+
+static void uslcom_cfg_open(struct ucom_softc *ucom);
+static void uslcom_cfg_close(struct ucom_softc *ucom);
+static int uslcom_pre_param(struct ucom_softc *ucom, struct termios *t);
+static void uslcom_cfg_param(struct ucom_softc *ucom, struct termios *t);
+static void uslcom_cfg_set_dtr(struct ucom_softc *ucom, uint8_t onoff);
+static void uslcom_cfg_set_rts(struct ucom_softc *ucom, uint8_t onoff);
+static void uslcom_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff);
+static void uslcom_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr);
+static void uslcom_cfg_do_request(struct uslcom_softc *sc, usb_device_request_t *req, void *data);
+
+static const struct usbd_config uslcom_config_data[USLCOM_N_DATA_TRANSFER] = {
+
+	[0] = {
+		.type = UE_BULK,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_OUT,
+		.mh.bufsize = USLCOM_BUF_SIZE,
+		.mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+		.mh.callback = &uslcom_write_callback,
+	},
+
+	[1] = {
+		.type = UE_BULK,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_IN,
+		.mh.bufsize = USLCOM_BUF_SIZE,
+		.mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+		.mh.callback = &uslcom_read_callback,
+	},
+
+	[2] = {
+		.type = UE_CONTROL,
+		.endpoint = 0x00,	/* Control pipe */
+		.direction = UE_DIR_ANY,
+		.mh.bufsize = sizeof(usb_device_request_t),
+		.mh.callback = &uslcom_write_clear_stall_callback,
+		.mh.timeout = 1000,	/* 1 second */
+		.mh.interval = 50,	/* 50ms */
+	},
+
+	[3] = {
+		.type = UE_CONTROL,
+		.endpoint = 0x00,	/* Control pipe */
+		.direction = UE_DIR_ANY,
+		.mh.bufsize = sizeof(usb_device_request_t),
+		.mh.callback = &uslcom_read_clear_stall_callback,
+		.mh.timeout = 1000,	/* 1 second */
+		.mh.interval = 50,	/* 50ms */
+	},
+};
 
-struct ucom_callback uslcom_callback = {
-	uslcom_get_status,
-	uslcom_set,
-	uslcom_param,
-	NULL,
-	uslcom_open,
-	uslcom_close,
-	NULL,
-	NULL,
+static const struct ucom_callback uslcom_callback = {
+	.ucom_cfg_open = &uslcom_cfg_open,
+	.ucom_cfg_close = &uslcom_cfg_close,
+	.ucom_cfg_get_status = &uslcom_cfg_get_status,
+	.ucom_cfg_set_dtr = &uslcom_cfg_set_dtr,
+	.ucom_cfg_set_rts = &uslcom_cfg_set_rts,
+	.ucom_cfg_set_break = &uslcom_cfg_set_break,
+	.ucom_cfg_param = &uslcom_cfg_param,
+	.ucom_pre_param = &uslcom_pre_param,
+	.ucom_start_read = &uslcom_start_read,
+	.ucom_stop_read = &uslcom_stop_read,
+	.ucom_start_write = &uslcom_start_write,
+	.ucom_stop_write = &uslcom_stop_write,
 };
 
 static const struct usb_devno uslcom_devs[] = {
@@ -135,224 +201,283 @@
 	{USB_VENDOR_USI, USB_PRODUCT_USI_MC60}
 };
 
-static device_probe_t uslcom_match;
-static device_attach_t uslcom_attach;
-static device_detach_t uslcom_detach;
-
 static device_method_t uslcom_methods[] = {
 	/* Device interface */
-	DEVMETHOD(device_probe, uslcom_match),
+	DEVMETHOD(device_probe, uslcom_probe),
 	DEVMETHOD(device_attach, uslcom_attach),
 	DEVMETHOD(device_detach, uslcom_detach),
 	{0, 0}
 };
 
+static devclass_t uslcom_devclass;
+
 static driver_t uslcom_driver = {
-	"ucom",
-	uslcom_methods,
-	sizeof(struct uslcom_softc)
+	.name = "uslcom",
+	.methods = uslcom_methods,
+	.size = sizeof(struct uslcom_softc),
 };
 
-DRIVER_MODULE(uslcom, uhub, uslcom_driver, ucom_devclass, usbd_driver_load, 0);
+DRIVER_MODULE(uslcom, uhub, uslcom_driver, uslcom_devclass, usbd_driver_load, 0);
 MODULE_DEPEND(uslcom, usb, 1, 1, 1);
 MODULE_DEPEND(uslcom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
 MODULE_VERSION(uslcom, 1);
 
 static int
-uslcom_match(device_t self)
+uslcom_probe(device_t dev)
 {
-	struct usb_attach_arg *uaa = device_get_ivars(self);
+	struct usb_attach_arg *uaa = device_get_ivars(dev);
+
+	if (uaa->usb_mode != USB_MODE_HOST)
+		return (UMATCH_NONE);
 
 	if (uaa->iface != NULL)
-		return UMATCH_NONE;
+		return (UMATCH_NONE);
 
 	return (usb_lookup(uslcom_devs, uaa->vendor, uaa->product) != NULL) ?
 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
 }
 
 static int
-uslcom_attach(device_t self)
+uslcom_attach(device_t dev)
 {
-	struct uslcom_softc *sc = device_get_softc(self);
-	struct usb_attach_arg *uaa = device_get_ivars(self);
-	usbd_device_handle dev = uaa->device;
-	struct ucom_softc *ucom;
-	usb_interface_descriptor_t *id;
-	usb_endpoint_descriptor_t *ed;
-	usbd_status error;
-	int i;
+	struct usb_attach_arg *uaa = device_get_ivars(dev);
+	struct uslcom_softc *sc = device_get_softc(dev);
+	uint8_t ifaces[1];
+	int error;
 
-	ucom = &sc->sc_ucom;
-	ucom->sc_dev = self;
-	ucom->sc_udev = dev;
-	ucom->sc_iface = uaa->iface;
+	if (sc == NULL) {
+		return (ENOMEM);
+	}
+	usbd_set_device_desc(dev);
 
-	sc->sc_dev = self;
 	sc->sc_udev = uaa->device;
 
-	if (usbd_set_config_index(sc->sc_udev, USLCOM_CONFIG_NO, 1) != 0) {
-		device_printf(self, "could not set configuration no\n");
-		sc->sc_dying = 1;
-		return ENXIO;
+	if (usbd_set_config_index(uaa->device, USLCOM_CONFIG_INDEX, 1) != 0) {
+		device_printf(dev, "Could not set configuration 0.\n");
+		return (ENXIO);
 	}
-	/* get the first interface handle */
-	error = usbd_device2interface_handle(sc->sc_udev, USLCOM_IFACE_NO,
-	    &ucom->sc_iface);
-	if (error != 0) {
-		device_printf(self, "could not get interface handle\n");
-		sc->sc_dying = 1;
-		return ENXIO;
+	ifaces[0] = USLCOM_IFACE_INDEX;
+
+	error = usbd_transfer_setup(uaa->device,
+	    ifaces, sc->sc_xfer_data,
+	    uslcom_config_data, USLCOM_N_DATA_TRANSFER,
+	    sc, &Giant);
+	if (error) {
+		goto detach;
 	}
-	id = usbd_get_interface_descriptor(ucom->sc_iface);
+	/* clear stall at first run */
+	sc->sc_flag |= (USLCOM_FLAG_READ_STALL |
+	    USLCOM_FLAG_WRITE_STALL);
 
-	ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;
-	for (i = 0; i < id->bNumEndpoints; i++) {
-		ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i);
-		if (ed == NULL) {
-			device_printf(self, "no endpoint descriptor found for %d\n",
-			    i);
-			sc->sc_dying = 1;
-			return ENXIO;
-		}
-		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
-		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
-			ucom->sc_bulkin_no = ed->bEndpointAddress;
-		else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
-		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
-			ucom->sc_bulkout_no = ed->bEndpointAddress;
+	error = ucom_attach(&(sc->sc_super_ucom), &(sc->sc_ucom), 1, sc,
+	    &uslcom_callback, &Giant);
+	if (error) {
+		goto detach;
 	}
+	return (0);
+
+detach:
+	uslcom_detach(dev);
+	return (ENXIO);
+}
+
+static int
+uslcom_detach(device_t dev)
+{
+	struct uslcom_softc *sc = device_get_softc(dev);
+
+	DPRINTF(0, "sc=%p\n", sc);
+
+	ucom_detach(&(sc->sc_super_ucom), &(sc->sc_ucom), 1);
+
+	usbd_transfer_unsetup(sc->sc_xfer_data, USLCOM_N_DATA_TRANSFER);
+
+	return (0);
+}
+
+static void
+uslcom_start_read(struct ucom_softc *ucom)
+{
+	struct uslcom_softc *sc = ucom->sc_parent;
+
+	/* start read endpoint */
+	usbd_transfer_start(sc->sc_xfer_data[1]);
+	return;
+}
+
+static void
+uslcom_stop_read(struct ucom_softc *ucom)
+{
+	struct uslcom_softc *sc = ucom->sc_parent;
 
-	if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) {
-		device_printf(self, "missing endpoint\n");
-		sc->sc_dying = 1;
-		return ENXIO;
-	}
-	ucom->sc_parent = sc;
-	ucom->sc_portno = UCOM_UNK_PORTNO;
-	/* bulkin, bulkout set above */
-	ucom->sc_ibufsize = USLCOMBUFSZ;
-	ucom->sc_obufsize = USLCOMBUFSZ;
-	ucom->sc_ibufsizepad = USLCOMBUFSZ;
-	ucom->sc_opkthdrlen = 0;
-	ucom->sc_callback = &uslcom_callback;
+	/* stop read endpoint */
+	usbd_transfer_stop(sc->sc_xfer_data[3]);
+	usbd_transfer_stop(sc->sc_xfer_data[1]);
+	return;
+}
 
-	DPRINTF(("uslcom: in = 0x%x, out = 0x%x\n",
-	    ucom->sc_bulkin_no, ucom->sc_bulkout_no));
+static void
+uslcom_start_write(struct ucom_softc *ucom)
+{
+	struct uslcom_softc *sc = ucom->sc_parent;
 
-	ucom_attach(&sc->sc_ucom);
-	return 0;
+	usbd_transfer_start(sc->sc_xfer_data[0]);
+	return;
 }
 
-static int
-uslcom_detach(device_t self)
+static void
+uslcom_stop_write(struct ucom_softc *ucom)
 {
-	struct uslcom_softc *sc = device_get_softc(self);
+	struct uslcom_softc *sc = ucom->sc_parent;
 
-	sc->sc_dying = 1;
-	return ucom_detach(&sc->sc_ucom);
+	usbd_transfer_stop(sc->sc_xfer_data[2]);
+	usbd_transfer_stop(sc->sc_xfer_data[0]);
+	return;
 }
 
-int
-uslcom_open(void *vsc, int portno)
+static void
+uslcom_cfg_open(struct ucom_softc *ucom)
 {
-	struct uslcom_softc *sc = vsc;
+	struct uslcom_softc *sc = ucom->sc_parent;
 	usb_device_request_t req;
-	usbd_status err;
 
-	if (sc->sc_dying)
-		return (EIO);
-
 	req.bmRequestType = USLCOM_WRITE;
 	req.bRequest = USLCOM_UART;
 	USETW(req.wValue, USLCOM_UART_ENABLE);
-	USETW(req.wIndex, portno);
+	USETW(req.wIndex, 0);
 	USETW(req.wLength, 0);
-	err = usbd_do_request(sc->sc_udev, &req, NULL);
-	if (err)
-		return (EIO);
-
-	return (0);
+	uslcom_cfg_do_request(sc, &req, NULL);
+	return;
 }
 
 void
-uslcom_close(void *vsc, int portno)
+uslcom_cfg_close(struct ucom_softc *ucom)
 {
-	struct uslcom_softc *sc = vsc;
+	struct uslcom_softc *sc = ucom->sc_parent;
 	usb_device_request_t req;
 
-	if (sc->sc_dying)
-		return;
-
 	req.bmRequestType = USLCOM_WRITE;
 	req.bRequest = USLCOM_UART;
 	USETW(req.wValue, USLCOM_UART_DISABLE);
-	USETW(req.wIndex, portno);
+	USETW(req.wIndex, 0);
+	USETW(req.wLength, 0);
+	uslcom_cfg_do_request(sc, &req, NULL);
+	return;
+}
+
+static void
+uslcom_cfg_set_dtr(struct ucom_softc *ucom, uint8_t onoff)
+{
+	struct uslcom_softc *sc = ucom->sc_parent;
+	usb_device_request_t req;
+	uint16_t ctl;
+
+	DPRINTF(0, "onoff=%d\n", onoff);
+
+	if (onoff)
+		ctl = USLCOM_CTRL_DTR_ON;
+	else
+		ctl = 0;
+
+	ctl |= USLCOM_CTRL_DTR_SET;
+
+	req.bmRequestType = USLCOM_WRITE;
+	req.bRequest = USLCOM_CTRL;
+	USETW(req.wValue, ctl);
+	USETW(req.wIndex, 0);
 	USETW(req.wLength, 0);
-	usbd_do_request(sc->sc_udev, &req, NULL);
+	uslcom_cfg_do_request(sc, &req, NULL);
+	return;
 }
 
-void
-uslcom_set(void *vsc, int portno, int reg, int onoff)
+static void
+uslcom_cfg_set_rts(struct ucom_softc *ucom, uint8_t onoff)
 {
-	struct uslcom_softc *sc = vsc;
+	struct uslcom_softc *sc = ucom->sc_parent;
 	usb_device_request_t req;
-	int ctl;
+	uint16_t ctl;
+
+	DPRINTF(0, "onoff=%d\n", onoff);
+
+	if (onoff)
+		ctl = USLCOM_CTRL_RTS_ON;
+	else
+		ctl = 0;
+
+	ctl |= USLCOM_CTRL_RTS_SET;
 
-	switch (reg) {
-	case UCOM_SET_DTR:
-		ctl = onoff ? USLCOM_CTRL_DTR_ON : 0;
-		ctl |= USLCOM_CTRL_DTR_SET;
-		break;
-	case UCOM_SET_RTS:
-		ctl = onoff ? USLCOM_CTRL_RTS_ON : 0;
-		ctl |= USLCOM_CTRL_RTS_SET;
-		break;
-	case UCOM_SET_BREAK:
-		uslcom_break(sc, portno, onoff);
-		return;
-	default:
-		return;
-	}
 	req.bmRequestType = USLCOM_WRITE;
 	req.bRequest = USLCOM_CTRL;
 	USETW(req.wValue, ctl);
-	USETW(req.wIndex, portno);
+	USETW(req.wIndex, 0);
 	USETW(req.wLength, 0);
-	usbd_do_request(sc->sc_udev, &req, NULL);
+	uslcom_cfg_do_request(sc, &req, NULL);
+	return;
 }
 
-int
-uslcom_param(void *vsc, int portno, struct termios *t)
+static void
+uslcom_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff)
 {
-	struct uslcom_softc *sc = (struct uslcom_softc *)vsc;
-	usbd_status err;
+	struct uslcom_softc *sc = ucom->sc_parent;
 	usb_device_request_t req;
-	int data;
+	uint16_t brk;
+
+	DPRINTF(0, "onoff=%d\n", onoff);
+
+	if (onoff)
+		brk = USLCOM_BREAK_ON;
+	else
+		brk = USLCOM_BREAK_OFF;
+
+	req.bmRequestType = USLCOM_WRITE;
+	req.bRequest = USLCOM_BREAK;
+	USETW(req.wValue, brk);
+	USETW(req.wIndex, 0);
+	USETW(req.wLength, 0);
+	uslcom_cfg_do_request(sc, &req, NULL);
+	return;
+}
 
-	if (t->c_ospeed <= 0 || t->c_ospeed > 921600)
+static int
+uslcom_pre_param(struct ucom_softc *ucom, struct termios *t)
+{
+	if ((t->c_ospeed < 1) || (t->c_ospeed > 921600))
 		return (EINVAL);
+	else
+		return (0);
+}
+
+static void
+uslcom_cfg_param(struct ucom_softc *ucom, struct termios *t)
+{
+	struct uslcom_softc *sc = ucom->sc_parent;
+	usb_device_request_t req;
+	uint16_t data;
 
+	DPRINTF(0, "sc=%p\n", sc);
+
+	data = USLCOM_BAUD_REF / t->c_ospeed;
+
 	req.bmRequestType = USLCOM_WRITE;
 	req.bRequest = USLCOM_BAUD_RATE;
-	USETW(req.wValue, USLCOM_BAUD_REF / t->c_ospeed);
-	USETW(req.wIndex, portno);
+	USETW(req.wValue, data);
+	USETW(req.wIndex, 0);
 	USETW(req.wLength, 0);
-	err = usbd_do_request(sc->sc_udev, &req, NULL);
-	if (err)
-		return (EIO);
+	uslcom_cfg_do_request(sc, &req, NULL);
 
-	if (ISSET(t->c_cflag, CSTOPB))
+	if (t->c_cflag & CSTOPB)
 		data = USLCOM_STOP_BITS_2;
 	else
 		data = USLCOM_STOP_BITS_1;
-	if (ISSET(t->c_cflag, PARENB)) {
-		if (ISSET(t->c_cflag, PARODD))
+	if (t->c_cflag & PARENB) {
+		if (t->c_cflag & PARODD)
 			data |= USLCOM_PARITY_ODD;
 		else
 			data |= USLCOM_PARITY_EVEN;
 	} else
 		data |= USLCOM_PARITY_NONE;
-	switch (ISSET(t->c_cflag, CSIZE)) {
+
+	switch (t->c_cflag & CSIZE) {
 	case CS5:
 		data |= USLCOM_SET_DATA_BITS(5);
 		break;
@@ -370,50 +495,139 @@
 	req.bmRequestType = USLCOM_WRITE;
 	req.bRequest = USLCOM_DATA;
 	USETW(req.wValue, data);
-	USETW(req.wIndex, portno);
+	USETW(req.wIndex, 0);
 	USETW(req.wLength, 0);
-	err = usbd_do_request(sc->sc_udev, &req, NULL);
-	if (err)
-		return (EIO);
+	uslcom_cfg_do_request(sc, &req, NULL);
+	return;
+}
+
+static void
+uslcom_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr)
+{
+	struct uslcom_softc *sc = ucom->sc_parent;
+
+	DPRINTF(0, "\n");
+
+	*lsr = sc->sc_lsr;
+	*msr = sc->sc_msr;
+	return;
+}
+
+static void
+uslcom_cfg_do_request(struct uslcom_softc *sc, usb_device_request_t *req,
+    void *data)
+{
+	uint16_t length;
+	usbd_status_t err;
+
+	if (ucom_cfg_is_gone(&(sc->sc_ucom))) {
+		goto error;
+	}
+	err = usbd_do_request_flags(sc->sc_udev, &Giant, req,
+	    data, 0, NULL, 1000);
+
+	if (err) {
+
+		DPRINTF(-1, "device request failed, err=%s "
+		    "(ignored)\n", usbd_errstr(err));
+
+error:
+		length = UGETW(req->wLength);
 
-#if 0
-	/* XXX flow control */
-	if (ISSET(t->c_cflag, CRTSCTS)) {
-		/* rts/cts flow ctl */
-	} else if (ISSET(t->c_iflag, IXON | IXOFF)) {
-		/* xon/xoff flow ctl */
-	} else {
-		/* disable flow ctl */
+		if ((req->bmRequestType & UT_READ) && length) {
+			bzero(data, length);
+		}
 	}
-#endif
+	return;
+}
+
+static void
+uslcom_write_callback(struct usbd_xfer *xfer)
+{
+	struct uslcom_softc *sc = xfer->priv_sc;
+	uint32_t actlen;
+
+	switch (USBD_GET_STATE(xfer)) {
+	case USBD_ST_SETUP:
+	case USBD_ST_TRANSFERRED:
+		if (sc->sc_flag & USLCOM_FLAG_WRITE_STALL) {
+			usbd_transfer_start(sc->sc_xfer_data[2]);
+			return;
+		}
+		if (ucom_get_data(&(sc->sc_ucom), xfer->frbuffers, 0,
+		    USLCOM_BUF_SIZE, &actlen)) {
+
+			xfer->frlengths[0] = actlen;
+			usbd_start_hardware(xfer);
+		}
+		return;
+
+	default:			/* Error */
+		if (xfer->error != USBD_ERR_CANCELLED) {
+			sc->sc_flag |= USLCOM_FLAG_WRITE_STALL;
+			usbd_transfer_start(sc->sc_xfer_data[2]);
+		}
+		return;
 
-	return (0);
+	}
 }
 
-void
-uslcom_get_status(void *vsc, int portno, u_char *lsr, u_char *msr)
+static void
+uslcom_write_clear_stall_callback(struct usbd_xfer *xfer)
 {
-	struct uslcom_softc *sc = vsc;
+	struct uslcom_softc *sc = xfer->priv_sc;
+	struct usbd_xfer *xfer_other = sc->sc_xfer_data[0];
 
-	if (msr != NULL)
-		*msr = sc->sc_msr;
-	if (lsr != NULL)
-		*lsr = sc->sc_lsr;
+	if (usbd_clear_stall_callback(xfer, xfer_other)) {
+		DPRINTF(0, "stall cleared\n");
+		sc->sc_flag &= ~USLCOM_FLAG_WRITE_STALL;
+		usbd_transfer_start(xfer_other);
+	}
+	return;
 }
 
-void
-uslcom_break(void *vsc, int portno, int onoff)
+static void
+uslcom_read_callback(struct usbd_xfer *xfer)
 {
-	struct uslcom_softc *sc = vsc;
-	usb_device_request_t req;
-	int brk = onoff ? USLCOM_BREAK_ON : USLCOM_BREAK_OFF;
+	struct uslcom_softc *sc = xfer->priv_sc;
+
+	switch (USBD_GET_STATE(xfer)) {
+	case USBD_ST_TRANSFERRED:
+
+		DPRINTF(0, "actlen=%d\n", xfer->actlen);
+
+		ucom_put_data(&(sc->sc_ucom), xfer->frbuffers, 0,
+		    xfer->actlen);
+
+	case USBD_ST_SETUP:
+		if (sc->sc_flag & USLCOM_FLAG_READ_STALL) {
+			usbd_transfer_start(sc->sc_xfer_data[3]);
+		} else {
+			xfer->frlengths[0] = xfer->max_data_length;
+			usbd_start_hardware(xfer);
+		}
+		return;
+
+	default:			/* Error */
+		if (xfer->error != USBD_ERR_CANCELLED) {
+			sc->sc_flag |= USLCOM_FLAG_READ_STALL;
+			usbd_transfer_start(sc->sc_xfer_data[3]);
+		}
+		return;
 
-	req.bmRequestType = USLCOM_WRITE;
-	req.bRequest = USLCOM_BREAK;
-	USETW(req.wValue, brk);
-	USETW(req.wIndex, portno);
-	USETW(req.wLength, 0);
-	usbd_do_request(sc->sc_udev, &req, NULL);
+	}
 }
 
-#endif
+static void
+uslcom_read_clear_stall_callback(struct usbd_xfer *xfer)
+{
+	struct uslcom_softc *sc = xfer->priv_sc;
+	struct usbd_xfer *xfer_other = sc->sc_xfer_data[1];
+
+	if (usbd_clear_stall_callback(xfer, xfer_other)) {
+		DPRINTF(0, "stall cleared\n");
+		sc->sc_flag &= ~USLCOM_FLAG_READ_STALL;
+		usbd_transfer_start(xfer_other);
+	}
+	return;
+}

==== //depot/projects/usb/src/sys/modules/uslcom/Makefile#2 (text+ko) ====

@@ -4,7 +4,7 @@
 .PATH: $S/dev/usb
 
 KMOD=	uslcom
-SRCS=	uslcom.c opt_usb.h \
+SRCS=	uslcom.c opt_usb.h usb_if.h \
 	device_if.h bus_if.h usbdevs.h
 
 .include <bsd.kmod.mk>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200804190818.m3J8IKeL059030>