Properly support both ports of the FTDI 2232C. This allows me to
use all 16 ports of my USB-16COM-RM adapter. I also verified that single-port units still work as expected.
This commit is contained in:
parent
0c45a149be
commit
f6f3fbbfc3
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: uftdi.c,v 1.31 2007/03/13 13:51:55 drochner Exp $ */
|
||||
/* $NetBSD: uftdi.c,v 1.32 2007/09/02 22:35:25 riz Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
|
@ -46,7 +46,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uftdi.c,v 1.31 2007/03/13 13:51:55 drochner Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uftdi.c,v 1.32 2007/09/02 22:35:25 riz Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -77,7 +77,7 @@ int uftdidebug = 0;
|
|||
|
||||
#define UFTDI_CONFIG_INDEX 0
|
||||
#define UFTDI_IFACE_INDEX 0
|
||||
|
||||
#define UFTDI_MAX_PORTS 2
|
||||
|
||||
/*
|
||||
* These are the maximum number of bytes transferred per frame.
|
||||
|
@ -89,15 +89,16 @@ int uftdidebug = 0;
|
|||
struct uftdi_softc {
|
||||
USBBASEDEVICE sc_dev; /* base device */
|
||||
usbd_device_handle sc_udev; /* device */
|
||||
usbd_interface_handle sc_iface; /* interface */
|
||||
usbd_interface_handle sc_iface[UFTDI_MAX_PORTS]; /* interface */
|
||||
|
||||
enum uftdi_type sc_type;
|
||||
u_int sc_hdrlen;
|
||||
u_int sc_numports;
|
||||
|
||||
u_char sc_msr;
|
||||
u_char sc_lsr;
|
||||
|
||||
device_ptr_t sc_subdev;
|
||||
device_ptr_t sc_subdev[UFTDI_MAX_PORTS];
|
||||
|
||||
u_char sc_dying;
|
||||
|
||||
|
@ -183,7 +184,7 @@ USB_ATTACH(uftdi)
|
|||
usb_endpoint_descriptor_t *ed;
|
||||
char *devinfop;
|
||||
char *devname = USBDEVNAME(sc->sc_dev);
|
||||
int i;
|
||||
int i,idx;
|
||||
usbd_status err;
|
||||
struct ucom_attach_args uca;
|
||||
|
||||
|
@ -197,23 +198,13 @@ USB_ATTACH(uftdi)
|
|||
goto bad;
|
||||
}
|
||||
|
||||
err = usbd_device2interface_handle(dev, UFTDI_IFACE_INDEX, &iface);
|
||||
if (err) {
|
||||
printf("\n%s: failed to get interface, err=%s\n",
|
||||
devname, usbd_errstr(err));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
devinfop = usbd_devinfo_alloc(dev, 0);
|
||||
USB_ATTACH_SETUP;
|
||||
printf("%s: %s\n", devname, devinfop);
|
||||
usbd_devinfo_free(devinfop);
|
||||
|
||||
id = usbd_get_interface_descriptor(iface);
|
||||
|
||||
sc->sc_udev = dev;
|
||||
sc->sc_iface = iface;
|
||||
|
||||
sc->sc_numports = 1;
|
||||
switch( uaa->vendor ) {
|
||||
case USB_VENDOR_FTDI:
|
||||
switch (uaa->product) {
|
||||
|
@ -221,6 +212,9 @@ USB_ATTACH(uftdi)
|
|||
sc->sc_type = UFTDI_TYPE_SIO;
|
||||
sc->sc_hdrlen = 1;
|
||||
break;
|
||||
case USB_PRODUCT_FTDI_SERIAL_2232C:
|
||||
sc->sc_numports = 2;
|
||||
/* FALLTHROUGH */
|
||||
default: /* Most uftdi devices are 8U232AM */
|
||||
sc->sc_type = UFTDI_TYPE_8U232AM;
|
||||
sc->sc_hdrlen = 0;
|
||||
|
@ -231,58 +225,71 @@ USB_ATTACH(uftdi)
|
|||
sc->sc_hdrlen = 0;
|
||||
}
|
||||
|
||||
uca.bulkin = uca.bulkout = -1;
|
||||
for (i = 0; i < id->bNumEndpoints; i++) {
|
||||
int addr, dir, attr;
|
||||
ed = usbd_interface2endpoint_descriptor(iface, i);
|
||||
if (ed == NULL) {
|
||||
printf("%s: could not read endpoint descriptor"
|
||||
": %s\n", devname, usbd_errstr(err));
|
||||
for (idx = UFTDI_IFACE_INDEX; idx < sc->sc_numports; idx++) {
|
||||
err = usbd_device2interface_handle(dev, idx, &iface);
|
||||
if (err) {
|
||||
printf("\n%s: failed to get interface idx=%d, err=%s\n",
|
||||
devname, idx, usbd_errstr(err));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
addr = ed->bEndpointAddress;
|
||||
dir = UE_GET_DIR(ed->bEndpointAddress);
|
||||
attr = ed->bmAttributes & UE_XFERTYPE;
|
||||
if (dir == UE_DIR_IN && attr == UE_BULK)
|
||||
uca.bulkin = addr;
|
||||
else if (dir == UE_DIR_OUT && attr == UE_BULK)
|
||||
uca.bulkout = addr;
|
||||
else {
|
||||
printf("%s: unexpected endpoint\n", devname);
|
||||
id = usbd_get_interface_descriptor(iface);
|
||||
|
||||
sc->sc_iface[idx] = iface;
|
||||
|
||||
uca.bulkin = uca.bulkout = -1;
|
||||
for (i = 0; i < id->bNumEndpoints; i++) {
|
||||
int addr, dir, attr;
|
||||
ed = usbd_interface2endpoint_descriptor(iface, i);
|
||||
if (ed == NULL) {
|
||||
printf("%s: could not read endpoint descriptor"
|
||||
": %s\n", devname, usbd_errstr(err));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
addr = ed->bEndpointAddress;
|
||||
dir = UE_GET_DIR(ed->bEndpointAddress);
|
||||
attr = ed->bmAttributes & UE_XFERTYPE;
|
||||
if (dir == UE_DIR_IN && attr == UE_BULK)
|
||||
uca.bulkin = addr;
|
||||
else if (dir == UE_DIR_OUT && attr == UE_BULK)
|
||||
uca.bulkout = addr;
|
||||
else {
|
||||
printf("%s: unexpected endpoint\n", devname);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
if (uca.bulkin == -1) {
|
||||
printf("%s: Could not find data bulk in\n",
|
||||
USBDEVNAME(sc->sc_dev));
|
||||
goto bad;
|
||||
}
|
||||
if (uca.bulkout == -1) {
|
||||
printf("%s: Could not find data bulk out\n",
|
||||
USBDEVNAME(sc->sc_dev));
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
if (uca.bulkin == -1) {
|
||||
printf("%s: Could not find data bulk in\n",
|
||||
USBDEVNAME(sc->sc_dev));
|
||||
goto bad;
|
||||
}
|
||||
if (uca.bulkout == -1) {
|
||||
printf("%s: Could not find data bulk out\n",
|
||||
USBDEVNAME(sc->sc_dev));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
uca.portno = FTDI_PIT_SIOA;
|
||||
/* bulkin, bulkout set above */
|
||||
uca.ibufsize = UFTDIIBUFSIZE;
|
||||
uca.obufsize = UFTDIOBUFSIZE - sc->sc_hdrlen;
|
||||
uca.ibufsizepad = UFTDIIBUFSIZE;
|
||||
uca.opkthdrlen = sc->sc_hdrlen;
|
||||
uca.device = dev;
|
||||
uca.iface = iface;
|
||||
uca.methods = &uftdi_methods;
|
||||
uca.arg = sc;
|
||||
uca.info = NULL;
|
||||
uca.portno = FTDI_PIT_SIOA + idx;
|
||||
/* bulkin, bulkout set above */
|
||||
uca.ibufsize = UFTDIIBUFSIZE;
|
||||
uca.obufsize = UFTDIOBUFSIZE - sc->sc_hdrlen;
|
||||
uca.ibufsizepad = UFTDIIBUFSIZE;
|
||||
uca.opkthdrlen = sc->sc_hdrlen;
|
||||
uca.device = dev;
|
||||
uca.iface = iface;
|
||||
uca.methods = &uftdi_methods;
|
||||
uca.arg = sc;
|
||||
uca.info = NULL;
|
||||
|
||||
DPRINTF(("uftdi: in=0x%x out=0x%x\n", uca.bulkin, uca.bulkout));
|
||||
sc->sc_subdev[idx] = config_found_sm_loc(self, "ucombus", NULL, &uca,
|
||||
ucomprint, ucomsubmatch);
|
||||
}
|
||||
|
||||
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
|
||||
USBDEV(sc->sc_dev));
|
||||
|
||||
DPRINTF(("uftdi: in=0x%x out=0x%x\n", uca.bulkin, uca.bulkout));
|
||||
sc->sc_subdev = config_found_sm_loc(self, "ucombus", NULL, &uca,
|
||||
ucomprint, ucomsubmatch);
|
||||
|
||||
USB_ATTACH_SUCCESS_RETURN;
|
||||
|
||||
bad:
|
||||
|
@ -295,15 +302,16 @@ int
|
|||
uftdi_activate(device_ptr_t self, enum devact act)
|
||||
{
|
||||
struct uftdi_softc *sc = (struct uftdi_softc *)self;
|
||||
int rv = 0;
|
||||
int rv = 0,i;
|
||||
|
||||
switch (act) {
|
||||
case DVACT_ACTIVATE:
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
case DVACT_DEACTIVATE:
|
||||
if (sc->sc_subdev != NULL)
|
||||
rv = config_deactivate(sc->sc_subdev);
|
||||
for (i=0; i < sc->sc_numports; i++)
|
||||
if (sc->sc_subdev[i] != NULL)
|
||||
rv = config_deactivate(sc->sc_subdev[i]);
|
||||
sc->sc_dying = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -314,13 +322,15 @@ int
|
|||
uftdi_detach(device_ptr_t self, int flags)
|
||||
{
|
||||
struct uftdi_softc *sc = (struct uftdi_softc *)self;
|
||||
int i;
|
||||
|
||||
DPRINTF(("uftdi_detach: sc=%p flags=%d\n", sc, flags));
|
||||
sc->sc_dying = 1;
|
||||
if (sc->sc_subdev != NULL) {
|
||||
config_detach(sc->sc_subdev, flags);
|
||||
sc->sc_subdev = NULL;
|
||||
}
|
||||
for (i=0; i < sc->sc_numports; i++)
|
||||
if (sc->sc_subdev[i] != NULL) {
|
||||
config_detach(sc->sc_subdev[i], flags);
|
||||
sc->sc_subdev[i] = NULL;
|
||||
}
|
||||
|
||||
usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
|
||||
USBDEV(sc->sc_dev));
|
||||
|
@ -394,7 +404,7 @@ uftdi_read(void *vsc, int portno, u_char **ptr, u_int32_t *count)
|
|||
lsr, sc->sc_lsr));
|
||||
sc->sc_msr = msr;
|
||||
sc->sc_lsr = lsr;
|
||||
ucom_status_change((struct ucom_softc *)sc->sc_subdev);
|
||||
ucom_status_change((struct ucom_softc *)sc->sc_subdev[portno-1]);
|
||||
}
|
||||
|
||||
/* Pick up status and adjust data part. */
|
||||
|
|
Loading…
Reference in New Issue