PERFORCE change 140247 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sat Apr 19 08:18:21 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=140247
Change 140247 by hselasky at 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>
More information about the p4-projects
mailing list