PERFORCE change 132094 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sun Dec 30 05:51:15 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=132094
Change 132094 by hselasky at hselasky_laptop001 on 2007/12/30 13:50:55
Getting the uchcom probe and attach routines right.
Some code borrowed from uplcom.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/uchcom.c#4 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/uchcom.c#4 (text+ko) ====
@@ -147,26 +147,23 @@
#define UCHCOM_INTR_STAT2 0x03
#define UCHCOM_INTR_LEAST 4
-#define UCHCOMIBUFSIZE 256
-#define UCHCOMOBUFSIZE 256
+#define UCHCOM_BULK_BUF_SIZE 1024 /* bytes */
+#define UCHCOM_N_TRANSFER 6 /* units */
+
+struct uchcom_softc {
+ struct ucom_super_softc sc_super_ucom;
+ struct ucom_softc sc_ucom;
-struct uchcom_softc
-{
- struct ucom_softc sc_ucom;
+ struct usbd_xfer *sc_xfer[UCHCOM_N_TRANSFER];
+ struct usbd_device *sc_udev;
- /* */
- int sc_intr_endpoint;
- int sc_intr_size;
- usbd_pipe_handle sc_intr_pipe;
- u_char *sc_intr_buf;
- /* */
- uint8_t sc_version;
- int sc_dtr;
- int sc_rts;
- u_char sc_lsr;
- u_char sc_msr;
- int sc_lcr1;
- int sc_lcr2;
+ uint8_t sc_version;
+ uint8_t sc_msr;
+ uint8_t sc_lsr; /* local status register */
+ uint8_t sc_flag;
+#define UCHCOM_FLAG_INTR_STALL 0x01
+#define UCHCOM_FLAG_READ_STALL 0x02
+#define UCHCOM_FLAG_WRITE_STALL 0x04
};
struct uchcom_endpoints
@@ -213,19 +210,78 @@
static int uchcom_param(void *, int, struct termios *);
static int uchcom_open(void *, int);
static void uchcom_close(void *, int);
-static void uchcom_intr(usbd_xfer_handle, usbd_private_handle,
- usbd_status);
-
-static int uchcom_set_config(device_t );
-static int uchcom_find_ifaces(struct uchcom_softc *, usbd_interface_handle *);
-static int uchcom_find_endpoints(struct uchcom_softc *,
- struct uchcom_endpoints *);
-static void uchcom_close_intr_pipe(struct uchcom_softc *);
static device_probe_t uchcom_probe;
static device_attach_t uchcom_attach;
static device_detach_t uchcom_detach;
+static usbd_callback_t uchcom_intr_callback;
+static usbd_callback_t uchcom_intr_clear_stall_callback;
+static usbd_callback_t uchcom_write_callback;
+static usbd_callback_t uchcom_write_clear_stall_callback;
+static usbd_callback_t uchcom_read_callback;
+static usbd_callback_t uchcom_read_clear_stall_callback;
+
+static const struct usbd_config uchcom_config_data[UCHCOM_N_TRANSFER] = {
+
+ [0] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_OUT,
+ .bufsize = UCHCOM_BULK_BUF_SIZE,
+ .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .mh.callback = &uchcom_write_callback,
+ },
+
+ [1] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_IN,
+ .bufsize = UCHCOM_BULK_BUF_SIZE,
+ .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .mh.callback = &uchcom_read_callback,
+ },
+
+ [2] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = UE_DIR_ANY,
+ .bufsize = sizeof(usb_device_request_t),
+ .mh.callback = &uchcom_write_clear_stall_callback,
+ .mh.timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
+ },
+
+ [3] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = UE_DIR_ANY,
+ .bufsize = sizeof(usb_device_request_t),
+ .mh.callback = &uchcom_read_clear_stall_callback,
+ .mh.timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
+ },
+
+ [4] = {
+ .type = UE_INTERRUPT,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_IN,
+ .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .mh.callback = &uchcom_intr_callback,
+ },
+
+ [5] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = UE_DIR_ANY,
+ .bufsize = sizeof(usb_device_request_t),
+ .mh.callback = &uchcom_intr_clear_stall_callback,
+ .mh.timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
+ },
+};
+
struct ucom_callback uchcom_callback = {
.ucom_get_status = uchcom_get_status,
.ucom_set = uchcom_set,
@@ -238,190 +294,106 @@
};
-
-
/* ----------------------------------------------------------------------
* driver entry points
*/
-static int uchcom_probe(device_t self)
+static int
+uchcom_probe(device_t dev)
{
- struct usb_attach_arg *uaa = device_get_ivars(self);
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+
+ DPRINTF(10, "\n");
+
+ if (uaa->usb_mode != USB_MODE_HOST) {
+ return (UMATCH_NONE);
+ }
+
+ if (uaa->iface) {
+ return (UMATCH_NONE);
+ }
return (uchcom_lookup(uaa->vendor, uaa->product) != NULL ?
UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
}
-static int uchcom_attach(device_t self)
+static int
+uchcom_attach(device_t dev)
{
- struct uchcom_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
- usbd_device_handle dev = uaa->device;
+ struct uchcom_softc *sc = device_get_softc(dev);
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ int error;
+ uint8_t iface_index;
+
+ DPRINTF(10, "\n");
- struct uchcom_endpoints endpoints;
- struct ucom_softc *ucom = &sc->sc_ucom;
+ if (sc == NULL) {
+ return (ENOMEM);
+ }
+ usbd_set_device_desc(dev);
- ucom->sc_dev = self;
- ucom->sc_udev = dev;
+ sc->sc_udev = uaa->device;
- ucom->sc_dying = 0;
- sc->sc_dtr = sc->sc_rts = -1;
- sc->sc_lsr = sc->sc_msr = 0;
+ /* configure the chip */
- DPRINTF(("\n\nuchcom attach: sc=%p\n", sc));
+ error = usbd_set_config_index(uaa->device, UCHCOM_CONFIG_INDEX, 1);
- if (uchcom_set_config(self))
- goto failed;
+ if (error) {
+ device_printf(dev, "failed to set configuration, "
+ "error=%s\n", usbd_errstr(error));
+ goto detach;
+ }
switch (uaa->release) {
case UCHCOM_REV_CH340:
- device_printf(self, "CH340 detected\n");
+ device_printf(dev, "CH340 detected\n");
break;
default:
- device_printf(self, "CH341 detected\n");
+ device_printf(dev, "CH341 detected\n");
break;
}
- if (uchcom_find_ifaces(sc, &ucom->sc_iface))
- goto failed;
+ iface_index = UCHCOM_IFACE_INDEX;
+ error = usbd_transfer_setup(uaa->device,
+ &iface_index, sc->sc_xfer, uchcom_config_data,
+ UCHCOM_N_TRANSFER, sc, &Giant);
- if (uchcom_find_endpoints(sc, &endpoints))
- goto failed;
+ if (error) {
+ DPRINTF(0, "one or more missing USB endpoints, "
+ "error=%s\n", usbd_errstr(error));
+ goto detach;
+ }
- sc->sc_intr_endpoint = endpoints.ep_intr;
- sc->sc_intr_size = endpoints.ep_intr_size;
+ /* clear stall at first run */
+ sc->sc_flag |= (UCHCOM_FLAG_READ_STALL |
+ UCHCOM_FLAG_WRITE_STALL);
- /* setup ucom layer */
- ucom->sc_portno = UCOM_UNK_PORTNO;
- ucom->sc_bulkin_no = endpoints.ep_bulkin;
- ucom->sc_bulkout_no = endpoints.ep_bulkout;
- ucom->sc_ibufsize = UCHCOMIBUFSIZE;
- ucom->sc_obufsize = UCHCOMOBUFSIZE;
- ucom->sc_ibufsizepad = UCHCOMIBUFSIZE;
- ucom->sc_opkthdrlen = 0;
- ucom->sc_parent = sc;
-
- ucom->sc_callback = &uchcom_callback;
-
- ucom_attach(&sc->sc_ucom);
-
+ error = ucom_attach(&(sc->sc_super_ucom), &(sc->sc_ucom), 1, sc,
+ &uchcom_callback, &Giant);
+ if (error) {
+ goto detach;
+ }
return 0;
-failed:
- ucom->sc_dying = 1;
- return ENXIO;
+detach:
+ uchcom_detach(dev);
+ return (ENXIO);
}
-static int uchcom_detach(device_t self)
-{
- struct uchcom_softc *sc = device_get_softc(self);
- struct ucom_softc *ucom = &sc->sc_ucom ;
- int rv = 0;
-
- DPRINTF(("uchcom_detach: sc=%p flags=%d\n", sc, flags));
-
- uchcom_close_intr_pipe(sc);
-
- ucom->sc_dying = 1;
-
- rv = ucom_detach(ucom);
-
- return rv;
-}
static int
-uchcom_set_config(device_t dev)
+uchcom_detach(device_t dev)
{
struct uchcom_softc *sc = device_get_softc(dev);
- struct ucom_softc *ucom = &sc->sc_ucom;
- usbd_status err;
-
- err = usbd_set_config_index(ucom->sc_udev, UCHCOM_CONFIG_INDEX, 1);
- if (err) {
- device_printf(dev, "failed to set configuration: %s\n",
- usbd_errstr(err));
- return -1;
- }
- return 0;
-}
+ DPRINTF(10, "\n");
-static int
-uchcom_find_ifaces(struct uchcom_softc *sc, usbd_interface_handle *riface)
-{
- usbd_status err;
- struct ucom_softc *ucom = &sc->sc_ucom;
+ ucom_detach(&(sc->sc_super_ucom), &(sc->sc_ucom), 1);
- err = usbd_device2interface_handle(ucom->sc_udev, UCHCOM_IFACE_INDEX,
- riface);
- if (err) {
- device_printf(ucom->sc_dev, "failed to get interface: %s\n",
- usbd_errstr(err));
- return -1;
- }
+ usbd_transfer_unsetup(sc->sc_xfer, UCHCOM_N_TRANSFER);
- return 0;
-}
-
-static int
-uchcom_find_endpoints(struct uchcom_softc *sc, struct uchcom_endpoints *endpoints)
-{
- struct ucom_softc *ucom= &sc->sc_ucom;
- int i, bin=-1, bout=-1, intr=-1, isize=0;
- usb_interface_descriptor_t *id;
- usb_endpoint_descriptor_t *ed;
-
- id = usbd_get_interface_descriptor(ucom->sc_iface);
-
- for (i = 0; i < id->bNumEndpoints; i++) {
- ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i);
- if (ed == NULL) {
- device_printf(ucom->sc_dev, "no endpoint descriptor for %d\n", i);
- return -1;
- }
-
- if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
- UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
- intr = ed->bEndpointAddress;
- isize = UGETW(ed->wMaxPacketSize);
- } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
- UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
- bin = ed->bEndpointAddress;
- } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
- UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
- bout = ed->bEndpointAddress;
- }
- }
-
- if (intr == -1 || bin == -1 || bout == -1) {
- if (intr == -1) {
- device_printf(ucom->sc_dev, "no interrupt end point\n");
- }
- if (bin == -1) {
- device_printf(ucom->sc_dev, "no data bulk in end point\n");
-
- }
- if (bout == -1) {
- device_printf(ucom->sc_dev, "no data bulk out end point\n");
- }
- return -1;
- }
- if (isize < UCHCOM_INTR_LEAST) {
- device_printf(ucom->sc_dev, "intr pipe is too short");
- return -1;
- }
-
- DPRINTF(("%s: bulkin=%d, bulkout=%d, intr=%d, isize=%d\n",
- USBDEVNAME(sc->sc_dev), bin, bout, intr, isize));
-
- endpoints->ep_intr = intr;
- endpoints->ep_intr_size = isize;
- endpoints->ep_bulkin = bin;
- endpoints->ep_bulkout = bout;
-
- return 0;
+ return (0);
}
-
/* ----------------------------------------------------------------------
* low level i/o
*/
More information about the p4-projects
mailing list