PERFORCE change 116977 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Fri Mar 30 21:57:52 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=116977
Change 116977 by hselasky at hselasky_mini_itx on 2007/03/30 21:57:38
Finished converting uark to the new USB stack.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/uark.c#2 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/uark.c#2 (text+ko) ====
@@ -17,43 +17,34 @@
*
* $FreeBSD: src/sys/dev/usb/uark.c,v 1.1 2006/11/15 09:13:24 maxim Exp $
*/
+
+/*
+ * NOTE: all function names beginning like "uark_cfg_" can only
+ * be called from within the config thread function !
+ */
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/termios.h>
+#include <sys/serial.h>
#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/ioccom.h>
-#include <sys/fcntl.h>
-#include <sys/conf.h>
-#include <sys/tty.h>
-#include <sys/file.h>
-#include <sys/selinfo.h>
-#include <sys/sysctl.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 <dev/usb/ucomvar.h>
+
#include "usbdevs.h"
-#include <dev/usb/ucomvar.h>
+#define DPRINTF(...) { }
-#ifdef UARK_DEBUG
-#define DPRINTFN(n, x) do { \
- if (uarkdebug > (n)) \
- logprintf x; \
-} while (0)
-int uarkebug = 0;
-#else
-#define DPRINTFN(n, x)
-#endif
-#define DPRINTF(x) DPRINTFN(0, x)
+#define UARK_BUF_SIZE 512
-#define UARKBUFSZ 256
-#define UARK_CONFIG_NO 0
-#define UARK_IFACE_NO 0
+#define UARK_N_TRANSFER 4 /* units */
-#define UARK_SET_DATA_BITS(x) (x - 5)
+#define UARK_SET_DATA_BITS(x) ((x) - 5)
#define UARK_PARITY_NONE 0x00
#define UARK_PARITY_ODD 0x08
@@ -73,177 +64,367 @@
#define UARK_IFACE_INDEX 0
struct uark_softc {
+ struct ucom_super_softc sc_super_ucom;
struct ucom_softc sc_ucom;
- usbd_interface_handle sc_iface;
+
+ struct usbd_xfer *sc_xfer[UARK_N_TRANSFER];
+ struct usbd_device *sc_udev;
+
+ uint8_t sc_flags;
+#define UARK_FLAG_BULK_READ_STALL 0x01
+#define UARK_FLAG_BULK_WRITE_STALL 0x02
+ uint8_t sc_msr;
+ uint8_t sc_lsr;
+};
+
+/* prototypes */
+
+static device_probe_t uark_probe;
+static device_attach_t uark_attach;
+static device_detach_t uark_detach;
+
+static usbd_callback_t uark_bulk_write_callback;
+static usbd_callback_t uark_bulk_write_clear_stall_callback;
+static usbd_callback_t uark_bulk_read_callback;
+static usbd_callback_t uark_bulk_read_clear_stall_callback;
+
+static void uark_start_read(struct ucom_softc *ucom);
+static void uark_stop_read(struct ucom_softc *ucom);
+static void uark_start_write(struct ucom_softc *ucom);
+static void uark_stop_write(struct ucom_softc *ucom);
+
+static int uark_pre_param(struct ucom_softc *ucom, struct termios *t);
+static void uark_cfg_param(struct ucom_softc *ucom, struct termios *t);
+static void uark_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr);
+static void uark_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff);
+static void uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value);
+
+static const struct usbd_config
+uark_xfer_config[UARK_N_TRANSFER] = {
+
+ [0] = {
+ .type = UE_BULK,
+ .endpoint = -1, /* any */
+ .direction = UE_DIR_OUT,
+ .bufsize = UARK_BUF_SIZE,
+ .flags = 0,
+ .callback = &uark_bulk_write_callback,
+ },
+
+ [1] = {
+ .type = UE_BULK,
+ .endpoint = -1, /* any */
+ .direction = UE_DIR_IN,
+ .bufsize = UARK_BUF_SIZE,
+ .flags = USBD_SHORT_XFER_OK,
+ .callback = &uark_bulk_read_callback,
+ },
+
+ [2] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .flags = (USBD_USE_DMA),
+ .callback = &uark_bulk_write_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ },
+
+ [3] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .flags = (USBD_USE_DMA),
+ .callback = &uark_bulk_read_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ },
+};
+
+static const struct ucom_callback uark_callback = {
+ .ucom_cfg_get_status = &uark_cfg_get_status,
+ .ucom_cfg_set_break = &uark_cfg_set_break,
+ .ucom_cfg_param = &uark_cfg_param,
+ .ucom_pre_param = &uark_pre_param,
+ .ucom_start_read = &uark_start_read,
+ .ucom_stop_read = &uark_stop_read,
+ .ucom_start_write = &uark_start_write,
+ .ucom_stop_write = &uark_stop_write,
+};
- u_char sc_msr;
- u_char sc_lsr;
+static device_method_t uark_methods[] = {
+ /* Device methods */
+ DEVMETHOD(device_probe, uark_probe),
+ DEVMETHOD(device_attach, uark_attach),
+ DEVMETHOD(device_detach, uark_detach),
+ { 0, 0 }
};
-static void uark_get_status(void *, int portno, u_char *lsr, u_char *msr);
-static void uark_set(void *, int, int, int);
-static int uark_param(void *, int, struct termios *);
-static void uark_break(void *, int, int);
-static int uark_cmd(struct uark_softc *, uint16_t, uint16_t);
+static devclass_t uark_devclass;
-struct ucom_callback uark_callback = {
- uark_get_status,
- uark_set,
- uark_param,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
+static driver_t uark_driver = {
+ .name = "uark",
+ .methods = uark_methods,
+ .size = sizeof(struct uark_softc),
};
-static const struct uark_product {
- uint16_t vendor;
- uint16_t product;
-} uark_products[] = {
+DRIVER_MODULE(uark, uhub, uark_driver, uark_devclass, usbd_driver_load, 0);
+MODULE_DEPEND(uark, usb, 1, 1, 1);
+MODULE_DEPEND(uark, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
+
+static const struct usb_devno uark_devs[] = {
{ USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116 },
- { 0, 0 }
};
-USB_MATCH(uark)
+#define uark_lookup(v, p) usb_lookup(uark_devs, v, p)
+
+static int
+uark_probe(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+
+ if (uaa->iface) {
+ return UMATCH_NONE;
+ }
+
+ return (uark_lookup(uaa->vendor, uaa->product) ?
+ UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
+}
+
+static int
+uark_attach(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ struct uark_softc *sc = device_get_softc(dev);
+ int32_t error;
+
+ if (sc == NULL) {
+ return ENOMEM;
+ }
+
+ usbd_set_desc(dev, uaa->device);
+
+ sc->sc_udev = uaa->device;
+
+ /* Move the device into the configured state */
+ error = usbd_set_config_index(uaa->device, UARK_CONFIG_INDEX, 1);
+ if (error) {
+ device_printf(dev, "failed to set configuration, err=%s\n",
+ usbd_errstr(error));
+ goto detach;
+ }
+
+ error = usbd_transfer_setup
+ (uaa->device, UARK_IFACE_INDEX,
+ sc->sc_xfer, uark_xfer_config, UARK_N_TRANSFER,
+ sc, &Giant);
+
+ if (error) {
+ device_printf(dev, "allocating control USB "
+ "transfers failed!\n");
+ goto detach;
+ }
+
+ /* clear stall at first run */
+ sc->sc_flags |= (UARK_FLAG_BULK_WRITE_STALL|
+ UARK_FLAG_BULK_READ_STALL);
+
+ error = ucom_attach(&(sc->sc_super_ucom), &(sc->sc_ucom), 1, sc,
+ &uark_callback, &Giant);
+ if (error) {
+ DPRINTF(0, "ucom_attach failed\n");
+ goto detach;
+ }
+
+ return 0; /* success */
+
+ detach:
+ uark_detach(dev);
+ return ENXIO; /* failure */
+}
+
+static int
+uark_detach(device_t dev)
+{
+ struct uark_softc *sc = device_get_softc(dev);
+
+ ucom_detach(&(sc->sc_super_ucom), &(sc->sc_ucom), 1);
+
+ usbd_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER);
+
+ return 0;
+}
+
+static void
+uark_bulk_write_callback(struct usbd_xfer *xfer)
{
- USB_MATCH_START(uark, uaa);
- int i;
+ struct uark_softc *sc = xfer->priv_sc;
+ uint32_t actlen;
+
+ USBD_CHECK_STATUS(xfer);
- if (uaa->iface != NULL)
- return (UMATCH_NONE);
+tr_error:
+ if (xfer->error != USBD_CANCELLED) {
+ sc->sc_flags |= UARK_FLAG_BULK_WRITE_STALL;
+ usbd_transfer_start(sc->sc_xfer[2]);
+ }
+ return;
- for (i = 0; uark_products[i].vendor != 0; i++) {
- if (uark_products[i].vendor == uaa->vendor &&
- uark_products[i].product == uaa->product) {
- return (UMATCH_VENDOR_PRODUCT);
- }
+tr_setup:
+tr_transferred:
+ if (sc->sc_flags & UARK_FLAG_BULK_WRITE_STALL) {
+ usbd_transfer_start(sc->sc_xfer[2]);
+ return;
}
- return (UMATCH_NONE);
+ if (ucom_get_data(&(sc->sc_ucom), xfer->buffer,
+ UARK_BUF_SIZE, &actlen)) {
+ xfer->length = actlen;
+ usbd_start_hardware(xfer);
+ }
+ return;
}
-USB_ATTACH(uark)
+static void
+uark_bulk_write_clear_stall_callback(struct usbd_xfer *xfer)
{
- USB_ATTACH_START(uark, sc, uaa);
- usbd_device_handle dev = uaa->device;
- usbd_interface_handle iface;
- usb_interface_descriptor_t *id;
- usb_endpoint_descriptor_t *ed;
- usbd_status error;
- char *devinfo;
- const char *devname;
- int i;
- struct ucom_softc *ucom = &sc->sc_ucom;
+ struct uark_softc *sc = xfer->priv_sc;
+ struct usbd_xfer *xfer_other = sc->sc_xfer[0];
- devinfo = malloc(1024, M_USBDEV, M_WAITOK);
+ USBD_CHECK_STATUS(xfer);
- bzero(ucom, sizeof(struct ucom_softc));
- ucom->sc_dev = self;
- ucom->sc_udev = dev;
+ tr_setup:
+ /* start clear stall */
+ usbd_clear_stall_tr_setup(xfer, xfer_other);
+ return;
- devname = device_get_nameunit(ucom->sc_dev);
+ tr_transferred:
+ usbd_clear_stall_tr_transferred(xfer, xfer_other);
+ sc->sc_flags &= ~UARK_FLAG_BULK_WRITE_STALL;
+ usbd_transfer_start(xfer_other);
+ return;
- if (uaa->iface == NULL) {
- /* Move the device into the configured state. */
- error = usbd_set_config_index(dev, UARK_CONFIG_INDEX, 1);
- if (error) {
- printf("\n%s: failed to set configuration, err=%s\n",
- devname, usbd_errstr(error));
- goto bad;
- }
- error =
- usbd_device2interface_handle(dev, UARK_IFACE_INDEX, &iface);
- if (error) {
- printf("\n%s: failed to get interface, err=%s\n",
- devname, usbd_errstr(error));
- goto bad;
- }
- } else
- iface = uaa->iface;
+ tr_error:
+ sc->sc_flags &= ~UARK_FLAG_BULK_WRITE_STALL;
+ DPRINTF(sc, 0, "clear stall failed, error=%s\n",
+ usbd_errstr(xfer->error));
+ return;
+}
- usbd_devinfo(dev, 0, devinfo);
- printf("%s: %s\n", devname, devinfo);
+static void
+uark_bulk_read_callback(struct usbd_xfer *xfer)
+{
+ struct uark_softc *sc = xfer->priv_sc;
- id = usbd_get_interface_descriptor(iface);
- ucom->sc_iface = iface;
+ USBD_CHECK_STATUS(xfer);
- ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;
- for (i = 0; i < id->bNumEndpoints; i++) {
- ed = usbd_interface2endpoint_descriptor(iface, i);
- if (ed == NULL) {
- printf("%s: could not read endpoint descriptor\n",
- devname);
- goto bad;
- }
- 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;
+ tr_error:
+ if (xfer->error != USBD_CANCELLED) {
+ sc->sc_flags |= UARK_FLAG_BULK_READ_STALL;
+ usbd_transfer_start(sc->sc_xfer[3]);
}
- if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) {
- printf("%s: missing endpoint\n", devname);
- goto bad;
+ return;
+
+ tr_transferred:
+ ucom_put_data(&(sc->sc_ucom), xfer->buffer,
+ xfer->actlen);
+
+ tr_setup:
+ if (sc->sc_flags & UARK_FLAG_BULK_READ_STALL) {
+ usbd_transfer_start(sc->sc_xfer[3]);
+ } else {
+ usbd_start_hardware(xfer);
}
- ucom->sc_parent = sc;
- ucom->sc_ibufsize = UARKBUFSZ;
- ucom->sc_obufsize = UARKBUFSZ;
- ucom->sc_ibufsizepad = UARKBUFSZ;
- ucom->sc_opkthdrlen = 0;
+ return;
+}
- ucom->sc_callback = &uark_callback;
+static void
+uark_bulk_read_clear_stall_callback(struct usbd_xfer *xfer)
+{
+ struct uark_softc *sc = xfer->priv_sc;
+ struct usbd_xfer *xfer_other = sc->sc_xfer[1];
- DPRINTF(("uark: in=0x%x out=0x%x\n", ucom->sc_bulkin_no, ucom->sc_bulkout_no));
- ucom_attach(&sc->sc_ucom);
- free(devinfo, M_USBDEV);
+ USBD_CHECK_STATUS(xfer);
- USB_ATTACH_SUCCESS_RETURN;
+ tr_setup:
+ /* start clear stall */
+ usbd_clear_stall_tr_setup(xfer, xfer_other);
+ return;
-bad:
- DPRINTF(("uftdi_attach: ATTACH ERROR\n"));
- ucom->sc_dying = 1;
- free(devinfo, M_USBDEV);
+ tr_transferred:
+ usbd_clear_stall_tr_transferred(xfer, xfer_other);
+ sc->sc_flags &= ~UARK_FLAG_BULK_READ_STALL;
+ usbd_transfer_start(xfer_other);
+ return;
- USB_ATTACH_ERROR_RETURN;
+ tr_error:
+ sc->sc_flags &= ~UARK_FLAG_BULK_READ_STALL;
+ DPRINTF(sc, 0, "clear stall failed, error=%s\n",
+ usbd_errstr(xfer->error));
+ return;
}
-USB_DETACH(uark)
+static void
+uark_start_read(struct ucom_softc *ucom)
{
- USB_DETACH_START(uark, sc);
- int rv = 0;
+ struct uark_softc *sc = ucom->sc_parent;
+ usbd_transfer_start(sc->sc_xfer[1]);
+ return;
+}
- DPRINTF(("uark_detach: sc=%p\n", sc));
- sc->sc_ucom.sc_dying = 1;
- rv = ucom_detach(&sc->sc_ucom);
+static void
+uark_stop_read(struct ucom_softc *ucom)
+{
+ struct uark_softc *sc = ucom->sc_parent;
+ usbd_transfer_stop(sc->sc_xfer[3]);
+ usbd_transfer_stop(sc->sc_xfer[1]);
+ return;
+}
- return (rv);
+static void
+uark_start_write(struct ucom_softc *ucom)
+{
+ struct uark_softc *sc = ucom->sc_parent;
+ usbd_transfer_start(sc->sc_xfer[0]);
+ return;
}
static void
-uark_set(void *vsc, int portno, int reg, int onoff)
+uark_stop_write(struct ucom_softc *ucom)
{
- struct uark_softc *sc = vsc;
+ struct uark_softc *sc = ucom->sc_parent;
+ usbd_transfer_stop(sc->sc_xfer[2]);
+ usbd_transfer_stop(sc->sc_xfer[0]);
+ return;
+}
- switch (reg) {
- case UCOM_SET_BREAK:
- uark_break(sc, portno, onoff);
- return;
- /* NOTREACHED */
- case UCOM_SET_DTR:
- case UCOM_SET_RTS:
+static int
+uark_pre_param(struct ucom_softc *ucom, struct termios *t)
+{
+ switch (t->c_ospeed) {
+ case 300:
+ case 600:
+ case 1200:
+ case 1800:
+ case 2400:
+ case 4800:
+ case 9600:
+ case 19200:
+ case 38400:
+ case 57600:
+ case 115200:
+ break;
default:
- return;
- /* NOTREACHED */
+ return EINVAL;
}
+ return 0;
}
-static int
-uark_param(void *vsc, int portno, struct termios *t)
+static void
+uark_cfg_param(struct ucom_softc *ucom, struct termios *t)
{
- struct uark_softc *sc = (struct uark_softc *)vsc;
- int data;
+ struct uark_softc *sc = ucom->sc_parent;
+ uint16_t data;
switch (t->c_ospeed) {
case 300:
@@ -257,29 +438,30 @@
case 38400:
case 57600:
case 115200:
- uark_cmd(sc, 3, 0x83);
- uark_cmd(sc, 0, (UARK_BAUD_REF / t->c_ospeed) & 0xFF);
- uark_cmd(sc, 1, (UARK_BAUD_REF / t->c_ospeed) >> 8);
- uark_cmd(sc, 3, 0x03);
+ data = (UARK_BAUD_REF / t->c_ospeed);
+ uark_cfg_write(sc, 3, 0x83);
+ uark_cfg_write(sc, 0, data & 0xFF);
+ uark_cfg_write(sc, 1, data >> 8);
+ uark_cfg_write(sc, 3, 0x03);
break;
default:
- return (EINVAL);
- /* NOTREACHED */
+ return;
}
- if (ISSET(t->c_cflag, CSTOPB))
+
+ if (t->c_cflag & CSTOPB)
data = UARK_STOP_BITS_2;
else
data = UARK_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 |= UARK_PARITY_ODD;
else
data |= UARK_PARITY_EVEN;
} else
data |= UARK_PARITY_NONE;
- switch (ISSET(t->c_cflag, CSIZE)) {
+ switch (t->c_cflag & CSIZE) {
case CS5:
data |= UARK_SET_DATA_BITS(5);
break;
@@ -289,79 +471,58 @@
case CS7:
data |= UARK_SET_DATA_BITS(7);
break;
+ default:
case CS8:
data |= UARK_SET_DATA_BITS(8);
break;
}
- uark_cmd(sc, 3, 0x00);
- uark_cmd(sc, 3, data);
-
- return (0);
+ uark_cfg_write(sc, 3, 0x00);
+ uark_cfg_write(sc, 3, data);
+ return;
}
-void
-uark_get_status(void *vsc, int portno, u_char *lsr, u_char *msr)
+static void
+uark_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr)
{
- struct uark_softc *sc = vsc;
+ struct uark_softc *sc = ucom->sc_parent;
- if (msr != NULL)
- *msr = sc->sc_msr;
- if (lsr != NULL)
- *lsr = sc->sc_lsr;
+ *lsr = sc->sc_lsr;
+ *msr = sc->sc_msr;
+ return;
}
-void
-uark_break(void *vsc, int portno, int onoff)
+static void
+uark_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff)
{
-#ifdef UARK_DEBUG
- struct uark_softc *sc = vsc;
+ struct uark_softc *sc = ucom->sc_parent;
- printf("%s: break %s!\n", device_get_nameunit(sc->sc_dev),
- onoff ? "on" : "off");
+ DPRINTF(sc, 0, "onoff=%d\n", onoff);
- if (onoff)
- /* break on */
- uark_cmd(sc, 4, 0x01);
- else
- uark_cmd(sc, 4, 0x00);
-#endif
+ uark_cfg_write(sc, 4, onoff ? 0x01 : 0x00);
+ return;
}
-int
-uark_cmd(struct uark_softc *sc, uint16_t index, uint16_t value)
+static void
+uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value)
{
usb_device_request_t req;
usbd_status err;
- struct ucom_softc *ucom = &sc->sc_ucom;
+
+ if (ucom_cfg_is_gone(&(sc->sc_ucom))) {
+ return;
+ }
req.bmRequestType = UARK_WRITE;
req.bRequest = UARK_REQUEST;
USETW(req.wValue, value);
USETW(req.wIndex, index);
USETW(req.wLength, 0);
- err = usbd_do_request(ucom->sc_udev, &req, NULL);
- if (err)
- return (EIO);
-
- return (0);
+ err = usbd_do_request_flags_mtx(sc->sc_udev, &Giant, &req,
+ NULL, 0, NULL, 1000);
+ if (err) {
+ DPRINTF(sc, -1, "device request failed, err=%s "
+ "(ignored)\n", usbd_errstr(err));
+ }
+ return;
}
-
-static device_method_t uark_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, uark_match),
- DEVMETHOD(device_attach, uark_attach),
- DEVMETHOD(device_detach, uark_detach),
-
- { 0, 0 }
-};
-
-static driver_t uark_driver = {
- "ucom",
- uark_methods,
- sizeof (struct uark_softc)
-};
-
-DRIVER_MODULE(uark, uhub, uark_driver, ucom_devclass, usbd_driver_load, 0);
-MODULE_DEPEND(uark, usb, 1, 1, 1);
-MODULE_DEPEND(uark, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
More information about the p4-projects
mailing list