FreeBSD/sys/dev/usb/serial/uftdi.c
/*
 * Set up softc fields whose value depends on the device type.
 *
 * Note that the 2232C and 2232D devices are the same for our purposes.  In the
 * silicon the difference is that the D series has CPU FIFO mode and C doesn't.
 * I haven't found any way of determining the C/D difference from info provided
 * by the chip other than trying to set CPU FIFO mode and having it work or not.
 * 
 * Due to a hardware bug, a 232B chip without an eeprom reports itself as a 
 * 232A, but if the serial number is also zero we know it's really a 232B. 
 */
Set up softc fields whose value depends on the device type.
Note that the 2232C and 2232D devices are the same for our purposes.  In the
silicon the difference is that the D series has CPU FIFO mode and C doesn't.
I haven't found any way of determining the C/D difference from info provided
by the chip other than trying to set CPU FIFO mode and having it work or not.

Due to a hardware bug, a 232B chip without an eeprom reports itself as a
232A, but if the serial number is also zero we know it's really a 232B.
Set up softc fields whose value depends on the device type . Note that the 2232C and 2232D devices are the same for our purposes . In the silicon the difference is that the D series has CPU FIFO mode and C doesn ' t . I haven ' t found any way of determining the C / D difference from info provided by the chip other than trying to set CPU FIFO mode and having it work or not . Due to a hardware bug a 232B chip without an eeprom reports itself as a 232A but if the serial number is also zero we know it ' s really a 232B .
static void
uftdi_devtype_setup(struct uftdi_softc *sc, struct usb_attach_arg *uaa)
{
	struct usb_device_descriptor *dd;
	sc->sc_bcdDevice = uaa->info.bcdDevice;
	switch (uaa->info.bcdDevice) {
	case 0x200:
		dd = usbd_get_device_descriptor(sc->sc_udev);
		if (dd->iSerialNumber == 0) {
			sc->sc_devtype = DEVT_232B;
		} else {
			sc->sc_devtype = DEVT_232A;
		}
		sc->sc_ucom.sc_portno = 0;
		break;
	case 0x400:
		sc->sc_devtype = DEVT_232B;
		sc->sc_ucom.sc_portno = 0;
		break;
	case 0x500:
		sc->sc_devtype = DEVT_2232D;
		sc->sc_devflags |= DEVF_BAUDBITS_HINDEX;
		sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
		break;
	case 0x600:
		sc->sc_devtype = DEVT_232R;
		sc->sc_ucom.sc_portno = 0;
		break;
	case 0x700:
		sc->sc_devtype = DEVT_2232H;
		sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
		sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
		break;
	case 0x800:
		sc->sc_devtype = DEVT_4232H;
		sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
		sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
		break;
	case 0x900:
		sc->sc_devtype = DEVT_232H;
		sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
		sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
		break;
	case 0x1000:
		sc->sc_devtype = DEVT_230X;
		sc->sc_devflags |= DEVF_BAUDBITS_HINDEX;
		sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
		break;
	default:
		if (uaa->info.bcdDevice < 0x200) {
			sc->sc_devtype = DEVT_SIO;
			sc->sc_hdrlen = 1;
		} else {
			sc->sc_devtype = DEVT_232R;
			device_printf(sc->sc_dev, "Warning: unknown FTDI "
			    "device type, bcdDevice=0x%04x, assuming 232R\n", 
			    uaa->info.bcdDevice);
		}
		sc->sc_ucom.sc_portno = 0;
		break;
	}
}
static void uftdi_devtype_setup ( struct uftdi_softc * sc , struct usb_attach_arg * uaa ) { struct usb_device_descriptor * dd ; sc -> sc_bcdDevice = uaa -> info . bcdDevice ; switch ( uaa -> info . bcdDevice ) { case 0x200 : dd = usbd_get_device_descriptor ( sc -> sc_udev ) ; if ( dd -> iSerialNumber == 0 ) { sc -> sc_devtype = DEVT_232B ; } else { sc -> sc_devtype = DEVT_232A ; } sc -> sc_ucom . sc_portno = 0 ; break ; case 0x400 : sc -> sc_devtype = DEVT_232B ; sc -> sc_ucom . sc_portno = 0 ; break ; case 0x500 : sc -> sc_devtype = DEVT_2232D ; sc -> sc_devflags |= DEVF_BAUDBITS_HINDEX ; sc -> sc_ucom . sc_portno = FTDI_PIT_SIOA + uaa -> info . bIfaceNum ; break ; case 0x600 : sc -> sc_devtype = DEVT_232R ; sc -> sc_ucom . sc_portno = 0 ; break ; case 0x700 : sc -> sc_devtype = DEVT_2232H ; sc -> sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M ; sc -> sc_ucom . sc_portno = FTDI_PIT_SIOA + uaa -> info . bIfaceNum ; break ; case 0x800 : sc -> sc_devtype = DEVT_4232H ; sc -> sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M ; sc -> sc_ucom . sc_portno = FTDI_PIT_SIOA + uaa -> info . bIfaceNum ; break ; case 0x900 : sc -> sc_devtype = DEVT_232H ; sc -> sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M ; sc -> sc_ucom . sc_portno = FTDI_PIT_SIOA + uaa -> info . bIfaceNum ; break ; case 0x1000 : sc -> sc_devtype = DEVT_230X ; sc -> sc_devflags |= DEVF_BAUDBITS_HINDEX ; sc -> sc_ucom . sc_portno = FTDI_PIT_SIOA + uaa -> info . bIfaceNum ; break ; default : if ( uaa -> info . bcdDevice < 0x200 ) { sc -> sc_devtype = DEVT_SIO ; sc -> sc_hdrlen = 1 ; } else { sc -> sc_devtype = DEVT_232R ; device_printf ( sc -> sc_dev , " " " \n " , uaa -> info . bcdDevice ) ; } sc -> sc_ucom . sc_portno = 0 ; break ; } }
Set up softc fields whose value depends on the device type.
Set up softc fields whose value depends on the device type .