Index: head/sys/dev/usb/umass.c =================================================================== --- head/sys/dev/usb/umass.c (revision 130105) +++ head/sys/dev/usb/umass.c (revision 130106) @@ -1,3068 +1,3072 @@ /*- * Copyright (c) 1999 MAEKAWA Masahide , * Nick Hibma * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ * $NetBSD: umass.c,v 1.28 2000/04/02 23:46:53 augustss Exp $ */ /* Also already merged from NetBSD: * $NetBSD: umass.c,v 1.67 2001/11/25 19:05:22 augustss Exp $ * $NetBSD: umass.c,v 1.90 2002/11/04 19:17:33 pooka Exp $ * $NetBSD: umass.c,v 1.108 2003/11/07 17:03:25 wiz Exp $ * $NetBSD: umass.c,v 1.109 2003/12/04 13:57:31 keihan Exp $ */ /* * Universal Serial Bus Mass Storage Class specs: * http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf * http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf * http://www.usb.org/developers/devclass_docs/usb_msc_cbi_1.1.pdf * http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf */ /* * Ported to NetBSD by Lennart Augustsson . * Parts of the code written by Jason R. Thorpe . */ /* * The driver handles 3 Wire Protocols * - Command/Bulk/Interrupt (CBI) * - Command/Bulk/Interrupt with Command Completion Interrupt (CBI with CCI) * - Mass Storage Bulk-Only (BBB) * (BBB refers Bulk/Bulk/Bulk for Command/Data/Status phases) * * Over these wire protocols it handles the following command protocols * - SCSI * - UFI (floppy command set) * - 8070i (ATAPI) * * UFI and 8070i (ATAPI) are transformed versions of the SCSI command set. The * sc->transform method is used to convert the commands into the appropriate * format (if at all necessary). For example, UFI requires all commands to be * 12 bytes in length amongst other things. * * The source code below is marked and can be split into a number of pieces * (in this order): * * - probe/attach/detach * - generic transfer routines * - BBB * - CBI * - CBI_I (in addition to functions from CBI) * - CAM (Common Access Method) * - SCSI * - UFI * - 8070i (ATAPI) * * The protocols are implemented using a state machine, for the transfers as * well as for the resets. The state machine is contained in umass_*_state. * The state machine is started through either umass_*_transfer or * umass_*_reset. * * The reason for doing this is a) CAM performs a lot better this way and b) it * avoids using tsleep from interrupt context (for example after a failed * transfer). */ /* * The SCSI related part of this driver has been derived from the * dev/ppbus/vpo.c driver, by Nicolas Souchu (nsouch@freebsd.org). * * The CAM layer uses so called actions which are messages sent to the host * adapter for completion. The actions come in through umass_cam_action. The * appropriate block of routines is called depending on the transport protocol * in use. When the transfer has finished, these routines call * umass_cam_cb again to complete the CAM command. */ /* * XXX Currently CBI with CCI is not supported because it bombs the system * when the device is detached (low frequency interrupts are detached * too late. */ #undef CBI_I #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef USB_DEBUG #define DIF(m, x) if (umassdebug & (m)) do { x ; } while (0) #define DPRINTF(m, x) if (umassdebug & (m)) logprintf x #define UDMASS_GEN 0x00010000 /* general */ #define UDMASS_SCSI 0x00020000 /* scsi */ #define UDMASS_UFI 0x00040000 /* ufi command set */ #define UDMASS_ATAPI 0x00080000 /* 8070i command set */ #define UDMASS_CMD (UDMASS_SCSI|UDMASS_UFI|UDMASS_ATAPI) #define UDMASS_USB 0x00100000 /* USB general */ #define UDMASS_BBB 0x00200000 /* Bulk-Only transfers */ #define UDMASS_CBI 0x00400000 /* CBI transfers */ #define UDMASS_WIRE (UDMASS_BBB|UDMASS_CBI) #define UDMASS_ALL 0xffff0000 /* all of the above */ int umassdebug = 0; SYSCTL_NODE(_hw_usb, OID_AUTO, umass, CTLFLAG_RW, 0, "USB umass"); SYSCTL_INT(_hw_usb_umass, OID_AUTO, debug, CTLFLAG_RW, &umassdebug, 0, "umass debug level"); #else #define DIF(m, x) /* nop */ #define DPRINTF(m, x) /* nop */ #endif /* Generic definitions */ /* Direction for umass_*_transfer */ #define DIR_NONE 0 #define DIR_IN 1 #define DIR_OUT 2 /* device name */ #define DEVNAME "umass" #define DEVNAME_SIM "umass-sim" #define UMASS_MAX_TRANSFER_SIZE 65536 #define UMASS_DEFAULT_TRANSFER_SPEED 1000 #define UMASS_FLOPPY_TRANSFER_SPEED 20 #define UMASS_TIMEOUT 5000 /* msecs */ /* CAM specific definitions */ #define UMASS_SCSIID_MAX 1 /* maximum number of drives expected */ #define UMASS_SCSIID_HOST UMASS_SCSIID_MAX #define MS_TO_TICKS(ms) ((ms) * hz / 1000) /* Bulk-Only features */ #define UR_BBB_RESET 0xff /* Bulk-Only reset */ #define UR_BBB_GET_MAX_LUN 0xfe /* Get maximum lun */ /* Command Block Wrapper */ typedef struct { uDWord dCBWSignature; # define CBWSIGNATURE 0x43425355 uDWord dCBWTag; uDWord dCBWDataTransferLength; uByte bCBWFlags; # define CBWFLAGS_OUT 0x00 # define CBWFLAGS_IN 0x80 uByte bCBWLUN; uByte bCDBLength; # define CBWCDBLENGTH 16 uByte CBWCDB[CBWCDBLENGTH]; } umass_bbb_cbw_t; #define UMASS_BBB_CBW_SIZE 31 /* Command Status Wrapper */ typedef struct { uDWord dCSWSignature; # define CSWSIGNATURE 0x53425355 # define CSWSIGNATURE_OLYMPUS_C1 0x55425355 uDWord dCSWTag; uDWord dCSWDataResidue; uByte bCSWStatus; # define CSWSTATUS_GOOD 0x0 # define CSWSTATUS_FAILED 0x1 # define CSWSTATUS_PHASE 0x2 } umass_bbb_csw_t; #define UMASS_BBB_CSW_SIZE 13 /* CBI features */ #define UR_CBI_ADSC 0x00 typedef unsigned char umass_cbi_cbl_t[16]; /* Command block */ typedef union { struct { unsigned char type; #define IDB_TYPE_CCI 0x00 unsigned char value; #define IDB_VALUE_PASS 0x00 #define IDB_VALUE_FAIL 0x01 #define IDB_VALUE_PHASE 0x02 #define IDB_VALUE_PERSISTENT 0x03 #define IDB_VALUE_STATUS_MASK 0x03 } common; struct { unsigned char asc; unsigned char ascq; } ufi; } umass_cbi_sbl_t; struct umass_softc; /* see below */ typedef void (*transfer_cb_f) (struct umass_softc *sc, void *priv, int residue, int status); #define STATUS_CMD_OK 0 /* everything ok */ #define STATUS_CMD_UNKNOWN 1 /* will have to fetch sense */ #define STATUS_CMD_FAILED 2 /* transfer was ok, command failed */ #define STATUS_WIRE_FAILED 3 /* couldn't even get command across */ typedef void (*wire_reset_f) (struct umass_softc *sc, int status); typedef void (*wire_transfer_f) (struct umass_softc *sc, int lun, void *cmd, int cmdlen, void *data, int datalen, int dir, u_int timeout, transfer_cb_f cb, void *priv); typedef void (*wire_state_f) (usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status err); typedef int (*command_transform_f) (struct umass_softc *sc, unsigned char *cmd, int cmdlen, unsigned char **rcmd, int *rcmdlen); struct umass_devdescr_t { u_int32_t vid; # define VID_WILDCARD 0xffffffff # define VID_EOT 0xfffffffe u_int32_t pid; # define PID_WILDCARD 0xffffffff # define PID_EOT 0xfffffffe u_int32_t rid; # define RID_WILDCARD 0xffffffff # define RID_EOT 0xfffffffe /* wire and command protocol */ u_int16_t proto; # define UMASS_PROTO_BBB 0x0001 /* USB wire protocol */ # define UMASS_PROTO_CBI 0x0002 # define UMASS_PROTO_CBI_I 0x0004 # define UMASS_PROTO_WIRE 0x00ff /* USB wire protocol mask */ # define UMASS_PROTO_SCSI 0x0100 /* command protocol */ # define UMASS_PROTO_ATAPI 0x0200 # define UMASS_PROTO_UFI 0x0400 # define UMASS_PROTO_RBC 0x0800 # define UMASS_PROTO_COMMAND 0xff00 /* command protocol mask */ /* Device specific quirks */ u_int16_t quirks; # define NO_QUIRKS 0x0000 /* The drive does not support Test Unit Ready. Convert to Start Unit */ # define NO_TEST_UNIT_READY 0x0001 /* The drive does not reset the Unit Attention state after REQUEST * SENSE has been sent. The INQUIRY command does not reset the UA * either, and so CAM runs in circles trying to retrieve the initial * INQUIRY data. */ # define RS_NO_CLEAR_UA 0x0002 /* The drive does not support START STOP. */ # define NO_START_STOP 0x0004 /* Don't ask for full inquiry data (255b). */ # define FORCE_SHORT_INQUIRY 0x0008 /* Needs to be initialised the Shuttle way */ # define SHUTTLE_INIT 0x0010 /* Drive needs to be switched to alternate iface 1 */ # define ALT_IFACE_1 0x0020 /* Drive does not do 1Mb/s, but just floppy speeds (20kb/s) */ # define FLOPPY_SPEED 0x0040 /* The device can't count and gets the residue of transfers wrong */ # define IGNORE_RESIDUE 0x0080 /* No GetMaxLun call */ # define NO_GETMAXLUN 0x0100 /* The device uses a weird CSWSIGNATURE. */ # define WRONG_CSWSIG 0x0200 /* Device cannot handle INQUIRY so fake a generic response */ # define NO_INQUIRY 0x0400 /* Device cannot handle INQUIRY EVPD, return CHECK CONDITION */ # define NO_INQUIRY_EVPD 0x0800 }; Static struct umass_devdescr_t umass_devdescrs[] = { { USB_VENDOR_ASAHIOPTICAL, PID_WILDCARD, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, RS_NO_CLEAR_UA }, { USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, RS_NO_CLEAR_UA }, { USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE }, { USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE_2, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE }, { USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE }, { USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_USB, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, NO_INQUIRY }, { USB_VENDOR_HP, USB_PRODUCT_HP_CDW8200, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, NO_TEST_UNIT_READY | NO_START_STOP }, { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, NO_TEST_UNIT_READY | NO_START_STOP | ALT_IFACE_1 }, { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_IU_CD2, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, NO_QUIRKS }, { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_DVR_UEH8, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, NO_QUIRKS }, { USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP100, RID_WILDCARD, /* XXX This is not correct as there are Zip drives that use ATAPI. */ UMASS_PROTO_SCSI | UMASS_PROTO_BBB, NO_TEST_UNIT_READY }, { USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443SU2, RID_WILDCARD, UMASS_PROTO_SCSI, NO_QUIRKS }, { USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443U2, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, NO_QUIRKS }, { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_DUBPXXG, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE }, { USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_DPCM, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_CBI, NO_TEST_UNIT_READY | NO_START_STOP }, { USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, IGNORE_RESIDUE | NO_GETMAXLUN | RS_NO_CLEAR_UA }, { USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY2, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, NO_QUIRKS }, + { USB_VENDOR_NEODIO, USB_PRODUCT_NEODIO_ND3260, RID_WILDCARD, + UMASS_PROTO_SCSI | UMASS_PROTO_BBB, + FORCE_SHORT_INQUIRY + }, { USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, WRONG_CSWSIG }, { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_UCF100, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, NO_INQUIRY | NO_GETMAXLUN }, { USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB20AN, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, NO_QUIRKS }, { USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB35AN, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, NO_QUIRKS }, { USB_VENDOR_PLEXTOR, USB_PRODUCT_PLEXTOR_40_12_40U, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, NO_TEST_UNIT_READY }, { USB_VENDOR_PNY, USB_PRODUCT_PNY_ATTACHE, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, IGNORE_RESIDUE }, { USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, NO_INQUIRY }, { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, NO_TEST_UNIT_READY | NO_START_STOP | SHUTTLE_INIT }, { USB_VENDOR_SIGMATEL, USB_PRODUCT_SIGMATEL_I_BEAD100, RID_WILDCARD, UMASS_PROTO_SCSI | UMASS_PROTO_BBB, SHUTTLE_INIT }, { USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC, RID_WILDCARD, UMASS_PROTO_RBC | UMASS_PROTO_CBI, NO_QUIRKS }, { USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC, RID_WILDCARD, UMASS_PROTO_RBC | UMASS_PROTO_CBI, NO_QUIRKS }, { USB_VENDOR_TREK, USB_PRODUCT_TREK_THUMBDRIVE_8MB, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, IGNORE_RESIDUE }, { USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO, RID_WILDCARD, UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, FORCE_SHORT_INQUIRY }, { VID_EOT, PID_EOT, RID_EOT, 0, 0 } }; /* the per device structure */ struct umass_softc { USBBASEDEVICE sc_dev; /* base device */ usbd_device_handle sc_udev; /* USB device */ struct cam_sim *umass_sim; /* SCSI Interface Module */ unsigned char flags; /* various device flags */ # define UMASS_FLAGS_GONE 0x01 /* devices is no more */ u_int16_t proto; /* wire and cmd protocol */ u_int16_t quirks; /* they got it almost right */ usbd_interface_handle iface; /* Mass Storage interface */ int ifaceno; /* MS iface number */ u_int8_t bulkin; /* bulk-in Endpoint Address */ u_int8_t bulkout; /* bulk-out Endpoint Address */ u_int8_t intrin; /* intr-in Endp. (CBI) */ usbd_pipe_handle bulkin_pipe; usbd_pipe_handle bulkout_pipe; usbd_pipe_handle intrin_pipe; /* Reset the device in a wire protocol specific way */ wire_reset_f reset; /* The start of a wire transfer. It prepares the whole transfer (cmd, * data, and status stage) and initiates it. It is up to the state * machine (below) to handle the various stages and errors in these */ wire_transfer_f transfer; /* The state machine, handling the various states during a transfer */ wire_state_f state; /* The command transform function is used to conver the SCSI commands * into their derivatives, like UFI, ATAPI, and friends. */ command_transform_f transform; /* command transform */ /* Bulk specific variables for transfers in progress */ umass_bbb_cbw_t cbw; /* command block wrapper */ umass_bbb_csw_t csw; /* command status wrapper*/ /* CBI specific variables for transfers in progress */ umass_cbi_cbl_t cbl; /* command block */ umass_cbi_sbl_t sbl; /* status block */ /* generic variables for transfers in progress */ /* ctrl transfer requests */ usb_device_request_t request; /* xfer handles * Most of our operations are initiated from interrupt context, so * we need to avoid using the one that is in use. We want to avoid * allocating them in the interrupt context as well. */ /* indices into array below */ # define XFER_BBB_CBW 0 /* Bulk-Only */ # define XFER_BBB_DATA 1 # define XFER_BBB_DCLEAR 2 # define XFER_BBB_CSW1 3 # define XFER_BBB_CSW2 4 # define XFER_BBB_SCLEAR 5 # define XFER_BBB_RESET1 6 # define XFER_BBB_RESET2 7 # define XFER_BBB_RESET3 8 # define XFER_CBI_CB 0 /* CBI */ # define XFER_CBI_DATA 1 # define XFER_CBI_STATUS 2 # define XFER_CBI_DCLEAR 3 # define XFER_CBI_SCLEAR 4 # define XFER_CBI_RESET1 5 # define XFER_CBI_RESET2 6 # define XFER_CBI_RESET3 7 # define XFER_NR 9 /* maximum number */ usbd_xfer_handle transfer_xfer[XFER_NR]; /* for ctrl xfers */ int transfer_dir; /* data direction */ void *transfer_data; /* data buffer */ int transfer_datalen; /* (maximum) length */ int transfer_actlen; /* actual length */ transfer_cb_f transfer_cb; /* callback */ void *transfer_priv; /* for callback */ int transfer_status; int transfer_state; # define TSTATE_ATTACH 0 /* in attach */ # define TSTATE_IDLE 1 # define TSTATE_BBB_COMMAND 2 /* CBW transfer */ # define TSTATE_BBB_DATA 3 /* Data transfer */ # define TSTATE_BBB_DCLEAR 4 /* clear endpt stall */ # define TSTATE_BBB_STATUS1 5 /* clear endpt stall */ # define TSTATE_BBB_SCLEAR 6 /* clear endpt stall */ # define TSTATE_BBB_STATUS2 7 /* CSW transfer */ # define TSTATE_BBB_RESET1 8 /* reset command */ # define TSTATE_BBB_RESET2 9 /* in clear stall */ # define TSTATE_BBB_RESET3 10 /* out clear stall */ # define TSTATE_CBI_COMMAND 11 /* command transfer */ # define TSTATE_CBI_DATA 12 /* data transfer */ # define TSTATE_CBI_STATUS 13 /* status transfer */ # define TSTATE_CBI_DCLEAR 14 /* clear ep stall */ # define TSTATE_CBI_SCLEAR 15 /* clear ep stall */ # define TSTATE_CBI_RESET1 16 /* reset command */ # define TSTATE_CBI_RESET2 17 /* in clear stall */ # define TSTATE_CBI_RESET3 18 /* out clear stall */ # define TSTATE_STATES 19 /* # of states above */ /* SCSI/CAM specific variables */ unsigned char cam_scsi_command[CAM_MAX_CDBLEN]; unsigned char cam_scsi_command2[CAM_MAX_CDBLEN]; struct scsi_sense cam_scsi_sense; struct scsi_sense cam_scsi_test_unit_ready; int timeout; /* in msecs */ int maxlun; /* maximum LUN number */ }; #ifdef USB_DEBUG char *states[TSTATE_STATES+1] = { /* should be kept in sync with the list at transfer_state */ "Attach", "Idle", "BBB CBW", "BBB Data", "BBB Data bulk-in/-out clear stall", "BBB CSW, 1st attempt", "BBB CSW bulk-in clear stall", "BBB CSW, 2nd attempt", "BBB Reset", "BBB bulk-in clear stall", "BBB bulk-out clear stall", "CBI Command", "CBI Data", "CBI Status", "CBI Data bulk-in/-out clear stall", "CBI Status intr-in clear stall", "CBI Reset", "CBI bulk-in clear stall", "CBI bulk-out clear stall", NULL }; #endif /* If device cannot return valid inquiry data, fake it */ Static uint8_t fake_inq_data[SHORT_INQUIRY_LENGTH] = { 0, /*removable*/ 0x80, SCSI_REV_2, SCSI_REV_2, /*additional_length*/ 31, 0, 0, 0 }; /* USB device probe/attach/detach functions */ USB_DECLARE_DRIVER(umass); Static int umass_match_proto (struct umass_softc *sc, usbd_interface_handle iface, usbd_device_handle udev); /* quirk functions */ Static void umass_init_shuttle (struct umass_softc *sc); /* generic transfer functions */ Static usbd_status umass_setup_transfer (struct umass_softc *sc, usbd_pipe_handle pipe, void *buffer, int buflen, int flags, usbd_xfer_handle xfer); Static usbd_status umass_setup_ctrl_transfer (struct umass_softc *sc, usbd_device_handle udev, usb_device_request_t *req, void *buffer, int buflen, int flags, usbd_xfer_handle xfer); Static void umass_clear_endpoint_stall (struct umass_softc *sc, u_int8_t endpt, usbd_pipe_handle pipe, int state, usbd_xfer_handle xfer); Static void umass_reset (struct umass_softc *sc, transfer_cb_f cb, void *priv); /* Bulk-Only related functions */ Static void umass_bbb_reset (struct umass_softc *sc, int status); Static void umass_bbb_transfer (struct umass_softc *sc, int lun, void *cmd, int cmdlen, void *data, int datalen, int dir, u_int timeout, transfer_cb_f cb, void *priv); Static void umass_bbb_state (usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status err); Static int umass_bbb_get_max_lun (struct umass_softc *sc); /* CBI related functions */ Static int umass_cbi_adsc (struct umass_softc *sc, char *buffer, int buflen, usbd_xfer_handle xfer); Static void umass_cbi_reset (struct umass_softc *sc, int status); Static void umass_cbi_transfer (struct umass_softc *sc, int lun, void *cmd, int cmdlen, void *data, int datalen, int dir, u_int timeout, transfer_cb_f cb, void *priv); Static void umass_cbi_state (usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status err); /* CAM related functions */ Static void umass_cam_action (struct cam_sim *sim, union ccb *ccb); Static void umass_cam_poll (struct cam_sim *sim); Static void umass_cam_cb (struct umass_softc *sc, void *priv, int residue, int status); Static void umass_cam_sense_cb (struct umass_softc *sc, void *priv, int residue, int status); Static void umass_cam_quirk_cb (struct umass_softc *sc, void *priv, int residue, int status); Static void umass_cam_rescan_callback (struct cam_periph *periph,union ccb *ccb); Static void umass_cam_rescan (void *addr); Static int umass_cam_attach_sim (struct umass_softc *sc); Static int umass_cam_attach (struct umass_softc *sc); Static int umass_cam_detach_sim (struct umass_softc *sc); /* SCSI specific functions */ Static int umass_scsi_transform (struct umass_softc *sc, unsigned char *cmd, int cmdlen, unsigned char **rcmd, int *rcmdlen); /* UFI specific functions */ #define UFI_COMMAND_LENGTH 12 /* UFI commands are always 12 bytes */ Static int umass_ufi_transform (struct umass_softc *sc, unsigned char *cmd, int cmdlen, unsigned char **rcmd, int *rcmdlen); /* ATAPI (8070i) specific functions */ #define ATAPI_COMMAND_LENGTH 12 /* ATAPI commands are always 12 bytes */ Static int umass_atapi_transform (struct umass_softc *sc, unsigned char *cmd, int cmdlen, unsigned char **rcmd, int *rcmdlen); /* RBC specific functions */ Static int umass_rbc_transform (struct umass_softc *sc, unsigned char *cmd, int cmdlen, unsigned char **rcmd, int *rcmdlen); #ifdef USB_DEBUG /* General debugging functions */ Static void umass_bbb_dump_cbw (struct umass_softc *sc, umass_bbb_cbw_t *cbw); Static void umass_bbb_dump_csw (struct umass_softc *sc, umass_bbb_csw_t *csw); Static void umass_cbi_dump_cmd (struct umass_softc *sc, void *cmd, int cmdlen); Static void umass_dump_buffer (struct umass_softc *sc, u_int8_t *buffer, int buflen, int printlen); #endif #if defined(__FreeBSD__) MODULE_DEPEND(umass, cam, 1,1,1); #endif /* * USB device probe/attach/detach */ /* * Match the device we are seeing with the devices supported. Fill in the * description in the softc accordingly. This function is called from both * probe and attach. */ Static int umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface, usbd_device_handle udev) { usb_device_descriptor_t *dd; usb_interface_descriptor_t *id; int i; int found = 0; sc->sc_udev = udev; sc->proto = 0; sc->quirks = 0; dd = usbd_get_device_descriptor(udev); /* An entry specifically for Y-E Data devices as they don't fit in the * device description table. */ if (UGETW(dd->idVendor) == USB_VENDOR_YEDATA && UGETW(dd->idProduct) == USB_PRODUCT_YEDATA_FLASHBUSTERU) { /* Revisions < 1.28 do not handle the interrupt endpoint * very well. */ if (UGETW(dd->bcdDevice) < 0x128) { sc->proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI; } else { sc->proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI_I; } /* * Revisions < 1.28 do not have the TEST UNIT READY command * Revisions == 1.28 have a broken TEST UNIT READY */ if (UGETW(dd->bcdDevice) <= 0x128) sc->quirks |= NO_TEST_UNIT_READY; sc->quirks |= RS_NO_CLEAR_UA | FLOPPY_SPEED; return(UMATCH_VENDOR_PRODUCT); } /* Check the list of supported devices for a match. While looking, * check for wildcarded and fully matched. First match wins. */ for (i = 0; umass_devdescrs[i].vid != VID_EOT && !found; i++) { if (umass_devdescrs[i].vid == VID_WILDCARD && umass_devdescrs[i].pid == PID_WILDCARD && umass_devdescrs[i].rid == RID_WILDCARD) { printf("umass: ignoring invalid wildcard quirk\n"); continue; } if ((umass_devdescrs[i].vid == UGETW(dd->idVendor) || umass_devdescrs[i].vid == VID_WILDCARD) && (umass_devdescrs[i].pid == UGETW(dd->idProduct) || umass_devdescrs[i].pid == PID_WILDCARD)) { if (umass_devdescrs[i].rid == RID_WILDCARD) { sc->proto = umass_devdescrs[i].proto; sc->quirks = umass_devdescrs[i].quirks; return (UMATCH_VENDOR_PRODUCT); } else if (umass_devdescrs[i].rid == UGETW(dd->bcdDevice)) { sc->proto = umass_devdescrs[i].proto; sc->quirks = umass_devdescrs[i].quirks; return (UMATCH_VENDOR_PRODUCT_REV); } /* else RID does not match */ } } /* Check for a standards compliant device */ id = usbd_get_interface_descriptor(iface); if (id == NULL || id->bInterfaceClass != UICLASS_MASS) return(UMATCH_NONE); switch (id->bInterfaceSubClass) { case UISUBCLASS_SCSI: sc->proto |= UMASS_PROTO_SCSI; break; case UISUBCLASS_UFI: sc->proto |= UMASS_PROTO_UFI; break; case UISUBCLASS_RBC: sc->proto |= UMASS_PROTO_RBC; break; case UISUBCLASS_SFF8020I: case UISUBCLASS_SFF8070I: sc->proto |= UMASS_PROTO_ATAPI; break; default: DPRINTF(UDMASS_GEN, ("%s: Unsupported command protocol %d\n", USBDEVNAME(sc->sc_dev), id->bInterfaceSubClass)); return(UMATCH_NONE); } switch (id->bInterfaceProtocol) { case UIPROTO_MASS_CBI: sc->proto |= UMASS_PROTO_CBI; break; case UIPROTO_MASS_CBI_I: sc->proto |= UMASS_PROTO_CBI_I; break; case UIPROTO_MASS_BBB_OLD: case UIPROTO_MASS_BBB: sc->proto |= UMASS_PROTO_BBB; break; default: DPRINTF(UDMASS_GEN, ("%s: Unsupported wire protocol %d\n", USBDEVNAME(sc->sc_dev), id->bInterfaceProtocol)); return(UMATCH_NONE); } return(UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO); } USB_MATCH(umass) { USB_MATCH_START(umass, uaa); struct umass_softc *sc = device_get_softc(self); USB_MATCH_SETUP; if (uaa->iface == NULL) return(UMATCH_NONE); return(umass_match_proto(sc, uaa->iface, uaa->device)); } USB_ATTACH(umass) { USB_ATTACH_START(umass, sc, uaa); usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; char devinfo[1024]; int i; int err; /* * the softc struct is bzero-ed in device_set_driver. We can safely * call umass_detach without specifically initialising the struct. */ usbd_devinfo(uaa->device, 0, devinfo); USB_ATTACH_SETUP; sc->iface = uaa->iface; sc->ifaceno = uaa->ifaceno; /* initialise the proto and drive values in the umass_softc (again) */ (void) umass_match_proto(sc, sc->iface, uaa->device); id = usbd_get_interface_descriptor(sc->iface); printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); #ifdef USB_DEBUG printf("%s: ", USBDEVNAME(sc->sc_dev)); switch (sc->proto&UMASS_PROTO_COMMAND) { case UMASS_PROTO_SCSI: printf("SCSI"); break; case UMASS_PROTO_ATAPI: printf("8070i (ATAPI)"); break; case UMASS_PROTO_UFI: printf("UFI"); break; case UMASS_PROTO_RBC: printf("RBC"); break; default: printf("(unknown 0x%02x)", sc->proto&UMASS_PROTO_COMMAND); break; } printf(" over "); switch (sc->proto&UMASS_PROTO_WIRE) { case UMASS_PROTO_BBB: printf("Bulk-Only"); break; case UMASS_PROTO_CBI: /* uses Comand/Bulk pipes */ printf("CBI"); break; case UMASS_PROTO_CBI_I: /* uses Comand/Bulk/Interrupt pipes */ printf("CBI with CCI"); #ifndef CBI_I printf(" (using CBI)"); #endif break; default: printf("(unknown 0x%02x)", sc->proto&UMASS_PROTO_WIRE); } printf("; quirks = 0x%04x\n", sc->quirks); #endif #ifndef CBI_I if (sc->proto & UMASS_PROTO_CBI_I) { /* See beginning of file for comment on the use of CBI with CCI */ sc->proto = (sc->proto & ~UMASS_PROTO_CBI_I) | UMASS_PROTO_CBI; } #endif if (sc->quirks & ALT_IFACE_1) { err = usbd_set_interface(0, 1); if (err) { DPRINTF(UDMASS_USB, ("%s: could not switch to " "Alt Interface %d\n", USBDEVNAME(sc->sc_dev), 1)); umass_detach(self); USB_ATTACH_ERROR_RETURN; } } /* * In addition to the Control endpoint the following endpoints * are required: * a) bulk-in endpoint. * b) bulk-out endpoint. * and for Control/Bulk/Interrupt with CCI (CBI_I) * c) intr-in * * The endpoint addresses are not fixed, so we have to read them * from the device descriptors of the current interface. */ for (i = 0 ; i < id->bNumEndpoints ; i++) { ed = usbd_interface2endpoint_descriptor(sc->iface, i); if (!ed) { printf("%s: could not read endpoint descriptor\n", USBDEVNAME(sc->sc_dev)); USB_ATTACH_ERROR_RETURN; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { sc->bulkin = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { sc->bulkout = ed->bEndpointAddress; } else if (sc->proto & UMASS_PROTO_CBI_I && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { sc->intrin = ed->bEndpointAddress; #ifdef USB_DEBUG if (UGETW(ed->wMaxPacketSize) > 2) { DPRINTF(UDMASS_CBI, ("%s: intr size is %d\n", USBDEVNAME(sc->sc_dev), UGETW(ed->wMaxPacketSize))); } #endif } } /* check whether we found all the endpoints we need */ if (!sc->bulkin || !sc->bulkout || (sc->proto & UMASS_PROTO_CBI_I && !sc->intrin) ) { DPRINTF(UDMASS_USB, ("%s: endpoint not found %d/%d/%d\n", USBDEVNAME(sc->sc_dev), sc->bulkin, sc->bulkout, sc->intrin)); umass_detach(self); USB_ATTACH_ERROR_RETURN; } /* Open the bulk-in and -out pipe */ err = usbd_open_pipe(sc->iface, sc->bulkout, USBD_EXCLUSIVE_USE, &sc->bulkout_pipe); if (err) { DPRINTF(UDMASS_USB, ("%s: cannot open %d-out pipe (bulk)\n", USBDEVNAME(sc->sc_dev), sc->bulkout)); umass_detach(self); USB_ATTACH_ERROR_RETURN; } err = usbd_open_pipe(sc->iface, sc->bulkin, USBD_EXCLUSIVE_USE, &sc->bulkin_pipe); if (err) { DPRINTF(UDMASS_USB, ("%s: could not open %d-in pipe (bulk)\n", USBDEVNAME(sc->sc_dev), sc->bulkin)); umass_detach(self); USB_ATTACH_ERROR_RETURN; } /* Open the intr-in pipe if the protocol is CBI with CCI. * Note: early versions of the Zip drive do have an interrupt pipe, but * this pipe is unused. * * We do not open the interrupt pipe as an interrupt pipe, but as a * normal bulk endpoint. We send an IN transfer down the wire at the * appropriate time, because we know exactly when to expect data on * that endpoint. This saves bandwidth, but more important, makes the * code for handling the data on that endpoint simpler. No data * arriving concurrently. */ if (sc->proto & UMASS_PROTO_CBI_I) { err = usbd_open_pipe(sc->iface, sc->intrin, USBD_EXCLUSIVE_USE, &sc->intrin_pipe); if (err) { DPRINTF(UDMASS_USB, ("%s: couldn't open %d-in (intr)\n", USBDEVNAME(sc->sc_dev), sc->intrin)); umass_detach(self); USB_ATTACH_ERROR_RETURN; } } /* initialisation of generic part */ sc->transfer_state = TSTATE_ATTACH; /* request a sufficient number of xfer handles */ for (i = 0; i < XFER_NR; i++) { sc->transfer_xfer[i] = usbd_alloc_xfer(uaa->device); if (!sc->transfer_xfer[i]) { DPRINTF(UDMASS_USB, ("%s: Out of memory\n", USBDEVNAME(sc->sc_dev))); umass_detach(self); USB_ATTACH_ERROR_RETURN; } } /* Initialise the wire protocol specific methods */ if (sc->proto & UMASS_PROTO_BBB) { sc->reset = umass_bbb_reset; sc->transfer = umass_bbb_transfer; sc->state = umass_bbb_state; } else if (sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I)) { sc->reset = umass_cbi_reset; sc->transfer = umass_cbi_transfer; sc->state = umass_cbi_state; #ifdef USB_DEBUG } else { panic("%s:%d: Unknown proto 0x%02x", __FILE__, __LINE__, sc->proto); #endif } if (sc->proto & UMASS_PROTO_SCSI) sc->transform = umass_scsi_transform; else if (sc->proto & UMASS_PROTO_UFI) sc->transform = umass_ufi_transform; else if (sc->proto & UMASS_PROTO_ATAPI) sc->transform = umass_atapi_transform; else if (sc->proto & UMASS_PROTO_RBC) sc->transform = umass_rbc_transform; #ifdef USB_DEBUG else panic("No transformation defined for command proto 0x%02x", sc->proto & UMASS_PROTO_COMMAND); #endif /* From here onwards the device can be used. */ if (sc->quirks & SHUTTLE_INIT) umass_init_shuttle(sc); /* Get the maximum LUN supported by the device. */ if ((sc->proto & UMASS_PROTO_WIRE) == UMASS_PROTO_BBB) sc->maxlun = umass_bbb_get_max_lun(sc); else sc->maxlun = 0; if ((sc->proto & UMASS_PROTO_SCSI) || (sc->proto & UMASS_PROTO_ATAPI) || (sc->proto & UMASS_PROTO_UFI) || (sc->proto & UMASS_PROTO_RBC)) { /* Prepare the SCSI command block */ sc->cam_scsi_sense.opcode = REQUEST_SENSE; sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY; /* register the SIM */ err = umass_cam_attach_sim(sc); if (err) { umass_detach(self); USB_ATTACH_ERROR_RETURN; } /* scan the new sim */ err = umass_cam_attach(sc); if (err) { umass_cam_detach_sim(sc); umass_detach(self); USB_ATTACH_ERROR_RETURN; } } else { panic("%s:%d: Unknown proto 0x%02x", __FILE__, __LINE__, sc->proto); } sc->transfer_state = TSTATE_IDLE; DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", USBDEVNAME(sc->sc_dev))); USB_ATTACH_SUCCESS_RETURN; } USB_DETACH(umass) { USB_DETACH_START(umass, sc); int err = 0; int i; DPRINTF(UDMASS_USB, ("%s: detached\n", USBDEVNAME(sc->sc_dev))); sc->flags |= UMASS_FLAGS_GONE; if ((sc->proto & UMASS_PROTO_SCSI) || (sc->proto & UMASS_PROTO_ATAPI) || (sc->proto & UMASS_PROTO_UFI) || (sc->proto & UMASS_PROTO_RBC)) /* detach the SCSI host controller (SIM) */ err = umass_cam_detach_sim(sc); for (i = 0; i < XFER_NR; i++) if (sc->transfer_xfer[i]) usbd_free_xfer(sc->transfer_xfer[i]); /* remove all the pipes */ if (sc->bulkout_pipe) usbd_close_pipe(sc->bulkout_pipe); if (sc->bulkin_pipe) usbd_close_pipe(sc->bulkin_pipe); if (sc->intrin_pipe) usbd_close_pipe(sc->intrin_pipe); return(err); } Static void umass_init_shuttle(struct umass_softc *sc) { usb_device_request_t req; u_char status[2]; /* The Linux driver does this, but no one can tell us what the * command does. */ req.bmRequestType = UT_READ_VENDOR_DEVICE; req.bRequest = 1; /* XXX unknown command */ USETW(req.wValue, 0); USETW(req.wIndex, sc->ifaceno); USETW(req.wLength, sizeof status); (void) usbd_do_request(sc->sc_udev, &req, &status); DPRINTF(UDMASS_GEN, ("%s: Shuttle init returned 0x%02x%02x\n", USBDEVNAME(sc->sc_dev), status[0], status[1])); } /* * Generic functions to handle transfers */ Static usbd_status umass_setup_transfer(struct umass_softc *sc, usbd_pipe_handle pipe, void *buffer, int buflen, int flags, usbd_xfer_handle xfer) { usbd_status err; /* Initialise a USB transfer and then schedule it */ (void) usbd_setup_xfer(xfer, pipe, (void *) sc, buffer, buflen, flags, sc->timeout, sc->state); err = usbd_transfer(xfer); if (err && err != USBD_IN_PROGRESS) { DPRINTF(UDMASS_BBB, ("%s: failed to setup transfer, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err))); return(err); } return (USBD_NORMAL_COMPLETION); } Static usbd_status umass_setup_ctrl_transfer(struct umass_softc *sc, usbd_device_handle udev, usb_device_request_t *req, void *buffer, int buflen, int flags, usbd_xfer_handle xfer) { usbd_status err; /* Initialise a USB control transfer and then schedule it */ (void) usbd_setup_default_xfer(xfer, udev, (void *) sc, sc->timeout, req, buffer, buflen, flags, sc->state); err = usbd_transfer(xfer); if (err && err != USBD_IN_PROGRESS) { DPRINTF(UDMASS_BBB, ("%s: failed to setup ctrl transfer, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err))); /* do not reset, as this would make us loop */ return(err); } return (USBD_NORMAL_COMPLETION); } Static void umass_clear_endpoint_stall(struct umass_softc *sc, u_int8_t endpt, usbd_pipe_handle pipe, int state, usbd_xfer_handle xfer) { usbd_device_handle udev; DPRINTF(UDMASS_BBB, ("%s: Clear endpoint 0x%02x stall\n", USBDEVNAME(sc->sc_dev), endpt)); usbd_interface2device_handle(sc->iface, &udev); sc->transfer_state = state; usbd_clear_endpoint_toggle(pipe); sc->request.bmRequestType = UT_WRITE_ENDPOINT; sc->request.bRequest = UR_CLEAR_FEATURE; USETW(sc->request.wValue, UF_ENDPOINT_HALT); USETW(sc->request.wIndex, endpt); USETW(sc->request.wLength, 0); umass_setup_ctrl_transfer(sc, udev, &sc->request, NULL, 0, 0, xfer); } Static void umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv) { sc->transfer_cb = cb; sc->transfer_priv = priv; /* The reset is a forced reset, so no error (yet) */ sc->reset(sc, STATUS_CMD_OK); } /* * Bulk protocol specific functions */ Static void umass_bbb_reset(struct umass_softc *sc, int status) { usbd_device_handle udev; KASSERT(sc->proto & UMASS_PROTO_BBB, ("%s: umass_bbb_reset: wrong sc->proto 0x%02x\n", USBDEVNAME(sc->sc_dev), sc->proto)); /* * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class) * * For Reset Recovery the host shall issue in the following order: * a) a Bulk-Only Mass Storage Reset * b) a Clear Feature HALT to the Bulk-In endpoint * c) a Clear Feature HALT to the Bulk-Out endpoint * * This is done in 3 steps, states: * TSTATE_BBB_RESET1 * TSTATE_BBB_RESET2 * TSTATE_BBB_RESET3 * * If the reset doesn't succeed, the device should be port reset. */ DPRINTF(UDMASS_BBB, ("%s: Bulk Reset\n", USBDEVNAME(sc->sc_dev))); sc->transfer_state = TSTATE_BBB_RESET1; sc->transfer_status = status; usbd_interface2device_handle(sc->iface, &udev); /* reset is a class specific interface write */ sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE; sc->request.bRequest = UR_BBB_RESET; USETW(sc->request.wValue, 0); USETW(sc->request.wIndex, sc->ifaceno); USETW(sc->request.wLength, 0); umass_setup_ctrl_transfer(sc, udev, &sc->request, NULL, 0, 0, sc->transfer_xfer[XFER_BBB_RESET1]); } Static void umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen, void *data, int datalen, int dir, u_int timeout, transfer_cb_f cb, void *priv) { KASSERT(sc->proto & UMASS_PROTO_BBB, ("%s: umass_bbb_transfer: wrong sc->proto 0x%02x\n", USBDEVNAME(sc->sc_dev), sc->proto)); /* Be a little generous. */ sc->timeout = timeout + UMASS_TIMEOUT; /* * Do a Bulk-Only transfer with cmdlen bytes from cmd, possibly * a data phase of datalen bytes from/to the device and finally a * csw read phase. * If the data direction was inbound a maximum of datalen bytes * is stored in the buffer pointed to by data. * * umass_bbb_transfer initialises the transfer and lets the state * machine in umass_bbb_state handle the completion. It uses the * following states: * TSTATE_BBB_COMMAND * -> TSTATE_BBB_DATA * -> TSTATE_BBB_STATUS * -> TSTATE_BBB_STATUS2 * -> TSTATE_BBB_IDLE * * An error in any of those states will invoke * umass_bbb_reset. */ /* check the given arguments */ KASSERT(datalen == 0 || data != NULL, ("%s: datalen > 0, but no buffer",USBDEVNAME(sc->sc_dev))); KASSERT(cmdlen <= CBWCDBLENGTH, ("%s: cmdlen exceeds CDB length in CBW (%d > %d)", USBDEVNAME(sc->sc_dev), cmdlen, CBWCDBLENGTH)); KASSERT(dir == DIR_NONE || datalen > 0, ("%s: datalen == 0 while direction is not NONE\n", USBDEVNAME(sc->sc_dev))); KASSERT(datalen == 0 || dir != DIR_NONE, ("%s: direction is NONE while datalen is not zero\n", USBDEVNAME(sc->sc_dev))); KASSERT(sizeof(umass_bbb_cbw_t) == UMASS_BBB_CBW_SIZE, ("%s: CBW struct does not have the right size (%ld vs. %d)\n", USBDEVNAME(sc->sc_dev), (long)sizeof(umass_bbb_cbw_t), UMASS_BBB_CBW_SIZE)); KASSERT(sizeof(umass_bbb_csw_t) == UMASS_BBB_CSW_SIZE, ("%s: CSW struct does not have the right size (%ld vs. %d)\n", USBDEVNAME(sc->sc_dev), (long)sizeof(umass_bbb_csw_t), UMASS_BBB_CSW_SIZE)); /* * Determine the direction of the data transfer and the length. * * dCBWDataTransferLength (datalen) : * This field indicates the number of bytes of data that the host * intends to transfer on the IN or OUT Bulk endpoint(as indicated by * the Direction bit) during the execution of this command. If this * field is set to 0, the device will expect that no data will be * transferred IN or OUT during this command, regardless of the value * of the Direction bit defined in dCBWFlags. * * dCBWFlags (dir) : * The bits of the Flags field are defined as follows: * Bits 0-6 reserved * Bit 7 Direction - this bit shall be ignored if the * dCBWDataTransferLength field is zero. * 0 = data Out from host to device * 1 = data In from device to host */ /* Fill in the Command Block Wrapper * We fill in all the fields, so there is no need to bzero it first. */ USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE); /* We don't care about the initial value, as long as the values are unique */ USETDW(sc->cbw.dCBWTag, UGETDW(sc->cbw.dCBWTag) + 1); USETDW(sc->cbw.dCBWDataTransferLength, datalen); /* DIR_NONE is treated as DIR_OUT (0x00) */ sc->cbw.bCBWFlags = (dir == DIR_IN? CBWFLAGS_IN:CBWFLAGS_OUT); sc->cbw.bCBWLUN = lun; sc->cbw.bCDBLength = cmdlen; bcopy(cmd, sc->cbw.CBWCDB, cmdlen); DIF(UDMASS_BBB, umass_bbb_dump_cbw(sc, &sc->cbw)); /* store the details for the data transfer phase */ sc->transfer_dir = dir; sc->transfer_data = data; sc->transfer_datalen = datalen; sc->transfer_actlen = 0; sc->transfer_cb = cb; sc->transfer_priv = priv; sc->transfer_status = STATUS_CMD_OK; /* move from idle to the command state */ sc->transfer_state = TSTATE_BBB_COMMAND; /* Send the CBW from host to device via bulk-out endpoint. */ if (umass_setup_transfer(sc, sc->bulkout_pipe, &sc->cbw, UMASS_BBB_CBW_SIZE, 0, sc->transfer_xfer[XFER_BBB_CBW])) { umass_bbb_reset(sc, STATUS_WIRE_FAILED); } } Static void umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status err) { struct umass_softc *sc = (struct umass_softc *) priv; usbd_xfer_handle next_xfer; KASSERT(sc->proto & UMASS_PROTO_BBB, ("%s: umass_bbb_state: wrong sc->proto 0x%02x\n", USBDEVNAME(sc->sc_dev), sc->proto)); /* * State handling for BBB transfers. * * The subroutine is rather long. It steps through the states given in * Annex A of the Bulk-Only specification. * Each state first does the error handling of the previous transfer * and then prepares the next transfer. * Each transfer is done asynchronously so after the request/transfer * has been submitted you will find a 'return;'. */ DPRINTF(UDMASS_BBB, ("%s: Handling BBB state %d (%s), xfer=%p, %s\n", USBDEVNAME(sc->sc_dev), sc->transfer_state, states[sc->transfer_state], xfer, usbd_errstr(err))); switch (sc->transfer_state) { /***** Bulk Transfer *****/ case TSTATE_BBB_COMMAND: /* Command transport phase, error handling */ if (err) { DPRINTF(UDMASS_BBB, ("%s: failed to send CBW\n", USBDEVNAME(sc->sc_dev))); /* If the device detects that the CBW is invalid, then * the device may STALL both bulk endpoints and require * a Bulk-Reset */ umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; } /* Data transport phase, setup transfer */ sc->transfer_state = TSTATE_BBB_DATA; if (sc->transfer_dir == DIR_IN) { if (umass_setup_transfer(sc, sc->bulkin_pipe, sc->transfer_data, sc->transfer_datalen, USBD_SHORT_XFER_OK, sc->transfer_xfer[XFER_BBB_DATA])) umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; } else if (sc->transfer_dir == DIR_OUT) { if (umass_setup_transfer(sc, sc->bulkout_pipe, sc->transfer_data, sc->transfer_datalen, 0, /* fixed length transfer */ sc->transfer_xfer[XFER_BBB_DATA])) umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; } else { DPRINTF(UDMASS_BBB, ("%s: no data phase\n", USBDEVNAME(sc->sc_dev))); } /* FALLTHROUGH if no data phase, err == 0 */ case TSTATE_BBB_DATA: /* Command transport phase, error handling (ignored if no data * phase (fallthrough from previous state)) */ if (sc->transfer_dir != DIR_NONE) { /* retrieve the length of the transfer that was done */ usbd_get_xfer_status(xfer, NULL, NULL, &sc->transfer_actlen, NULL); if (err) { DPRINTF(UDMASS_BBB, ("%s: Data-%s %db failed, " "%s\n", USBDEVNAME(sc->sc_dev), (sc->transfer_dir == DIR_IN?"in":"out"), sc->transfer_datalen,usbd_errstr(err))); if (err == USBD_STALLED) { umass_clear_endpoint_stall(sc, (sc->transfer_dir == DIR_IN? sc->bulkin:sc->bulkout), (sc->transfer_dir == DIR_IN? sc->bulkin_pipe:sc->bulkout_pipe), TSTATE_BBB_DCLEAR, sc->transfer_xfer[XFER_BBB_DCLEAR]); return; } else { /* Unless the error is a pipe stall the * error is fatal. */ umass_bbb_reset(sc,STATUS_WIRE_FAILED); return; } } } DIF(UDMASS_BBB, if (sc->transfer_dir == DIR_IN) umass_dump_buffer(sc, sc->transfer_data, sc->transfer_datalen, 48)); /* FALLTHROUGH, err == 0 (no data phase or successfull) */ case TSTATE_BBB_DCLEAR: /* stall clear after data phase */ case TSTATE_BBB_SCLEAR: /* stall clear after status phase */ /* Reading of CSW after bulk stall condition in data phase * (TSTATE_BBB_DATA2) or bulk-in stall condition after * reading CSW (TSTATE_BBB_SCLEAR). * In the case of no data phase or successfull data phase, * err == 0 and the following if block is passed. */ if (err) { /* should not occur */ /* try the transfer below, even if clear stall failed */ DPRINTF(UDMASS_BBB, ("%s: bulk-%s stall clear failed" ", %s\n", USBDEVNAME(sc->sc_dev), (sc->transfer_dir == DIR_IN? "in":"out"), usbd_errstr(err))); umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; } /* Status transport phase, setup transfer */ if (sc->transfer_state == TSTATE_BBB_COMMAND || sc->transfer_state == TSTATE_BBB_DATA || sc->transfer_state == TSTATE_BBB_DCLEAR) { /* After no data phase, successfull data phase and * after clearing bulk-in/-out stall condition */ sc->transfer_state = TSTATE_BBB_STATUS1; next_xfer = sc->transfer_xfer[XFER_BBB_CSW1]; } else { /* After first attempt of fetching CSW */ sc->transfer_state = TSTATE_BBB_STATUS2; next_xfer = sc->transfer_xfer[XFER_BBB_CSW2]; } /* Read the Command Status Wrapper via bulk-in endpoint. */ if (umass_setup_transfer(sc, sc->bulkin_pipe, &sc->csw, UMASS_BBB_CSW_SIZE, 0, next_xfer)) { umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; } return; case TSTATE_BBB_STATUS1: /* first attempt */ case TSTATE_BBB_STATUS2: /* second attempt */ /* Status transfer, error handling */ if (err) { DPRINTF(UDMASS_BBB, ("%s: Failed to read CSW, %s%s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err), (sc->transfer_state == TSTATE_BBB_STATUS1? ", retrying":""))); /* If this was the first attempt at fetching the CSW * retry it, otherwise fail. */ if (sc->transfer_state == TSTATE_BBB_STATUS1) { umass_clear_endpoint_stall(sc, sc->bulkin, sc->bulkin_pipe, TSTATE_BBB_SCLEAR, sc->transfer_xfer[XFER_BBB_SCLEAR]); return; } else { umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; } } DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw)); /* Translate weird command-status signatures. */ if ((sc->quirks & WRONG_CSWSIG) && UGETDW(sc->csw.dCSWSignature) == CSWSIGNATURE_OLYMPUS_C1) USETDW(sc->csw.dCSWSignature, CSWSIGNATURE); int Residue; Residue = UGETDW(sc->csw.dCSWDataResidue); if (Residue == 0 && sc->transfer_datalen - sc->transfer_actlen != 0) Residue = sc->transfer_datalen - sc->transfer_actlen; /* Check CSW and handle any error */ if (UGETDW(sc->csw.dCSWSignature) != CSWSIGNATURE) { /* Invalid CSW: Wrong signature or wrong tag might * indicate that the device is confused -> reset it. */ printf("%s: Invalid CSW: sig 0x%08x should be 0x%08x\n", USBDEVNAME(sc->sc_dev), UGETDW(sc->csw.dCSWSignature), CSWSIGNATURE); umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; } else if (UGETDW(sc->csw.dCSWTag) != UGETDW(sc->cbw.dCBWTag)) { printf("%s: Invalid CSW: tag %d should be %d\n", USBDEVNAME(sc->sc_dev), UGETDW(sc->csw.dCSWTag), UGETDW(sc->cbw.dCBWTag)); umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; /* CSW is valid here */ } else if (sc->csw.bCSWStatus > CSWSTATUS_PHASE) { printf("%s: Invalid CSW: status %d > %d\n", USBDEVNAME(sc->sc_dev), sc->csw.bCSWStatus, CSWSTATUS_PHASE); umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; } else if (sc->csw.bCSWStatus == CSWSTATUS_PHASE) { printf("%s: Phase Error, residue = %d\n", USBDEVNAME(sc->sc_dev), Residue); umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; } else if (sc->transfer_actlen > sc->transfer_datalen) { /* Buffer overrun! Don't let this go by unnoticed */ panic("%s: transferred %db instead of %db", USBDEVNAME(sc->sc_dev), sc->transfer_actlen, sc->transfer_datalen); } else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) { DPRINTF(UDMASS_BBB, ("%s: Command Failed, res = %d\n", USBDEVNAME(sc->sc_dev), Residue)); /* SCSI command failed but transfer was succesful */ sc->transfer_state = TSTATE_IDLE; sc->transfer_cb(sc, sc->transfer_priv, Residue, STATUS_CMD_FAILED); return; } else { /* success */ sc->transfer_state = TSTATE_IDLE; sc->transfer_cb(sc, sc->transfer_priv, Residue, STATUS_CMD_OK); return; } /***** Bulk Reset *****/ case TSTATE_BBB_RESET1: if (err) printf("%s: BBB reset failed, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err)); umass_clear_endpoint_stall(sc, sc->bulkin, sc->bulkin_pipe, TSTATE_BBB_RESET2, sc->transfer_xfer[XFER_BBB_RESET2]); return; case TSTATE_BBB_RESET2: if (err) /* should not occur */ printf("%s: BBB bulk-in clear stall failed, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err)); /* no error recovery, otherwise we end up in a loop */ umass_clear_endpoint_stall(sc, sc->bulkout, sc->bulkout_pipe, TSTATE_BBB_RESET3, sc->transfer_xfer[XFER_BBB_RESET3]); return; case TSTATE_BBB_RESET3: if (err) /* should not occur */ printf("%s: BBB bulk-out clear stall failed, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err)); /* no error recovery, otherwise we end up in a loop */ sc->transfer_state = TSTATE_IDLE; if (sc->transfer_priv) { sc->transfer_cb(sc, sc->transfer_priv, sc->transfer_datalen, sc->transfer_status); } return; /***** Default *****/ default: panic("%s: Unknown state %d", USBDEVNAME(sc->sc_dev), sc->transfer_state); } } Static int umass_bbb_get_max_lun(struct umass_softc *sc) { usbd_device_handle udev; usb_device_request_t req; usbd_status err; usb_interface_descriptor_t *id; int maxlun = 0; u_int8_t buf = 0; usbd_interface2device_handle(sc->iface, &udev); id = usbd_get_interface_descriptor(sc->iface); /* The Get Max Lun command is a class-specific request. */ req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_BBB_GET_MAX_LUN; USETW(req.wValue, 0); USETW(req.wIndex, id->bInterfaceNumber); USETW(req.wLength, 1); err = usbd_do_request(udev, &req, &buf); switch (err) { case USBD_NORMAL_COMPLETION: maxlun = buf; DPRINTF(UDMASS_BBB, ("%s: Max Lun is %d\n", USBDEVNAME(sc->sc_dev), maxlun)); break; case USBD_STALLED: case USBD_SHORT_XFER: default: /* Device doesn't support Get Max Lun request. */ printf("%s: Get Max Lun not supported (%s)\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err)); /* XXX Should we port_reset the device? */ break; } return(maxlun); } /* * Command/Bulk/Interrupt (CBI) specific functions */ Static int umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen, usbd_xfer_handle xfer) { usbd_device_handle udev; KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), ("%s: umass_cbi_adsc: wrong sc->proto 0x%02x\n", USBDEVNAME(sc->sc_dev), sc->proto)); usbd_interface2device_handle(sc->iface, &udev); sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE; sc->request.bRequest = UR_CBI_ADSC; USETW(sc->request.wValue, 0); USETW(sc->request.wIndex, sc->ifaceno); USETW(sc->request.wLength, buflen); return umass_setup_ctrl_transfer(sc, udev, &sc->request, buffer, buflen, 0, xfer); } Static void umass_cbi_reset(struct umass_softc *sc, int status) { int i; # define SEND_DIAGNOSTIC_CMDLEN 12 KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), ("%s: umass_cbi_reset: wrong sc->proto 0x%02x\n", USBDEVNAME(sc->sc_dev), sc->proto)); /* * Command Block Reset Protocol * * First send a reset request to the device. Then clear * any possibly stalled bulk endpoints. * * This is done in 3 steps, states: * TSTATE_CBI_RESET1 * TSTATE_CBI_RESET2 * TSTATE_CBI_RESET3 * * If the reset doesn't succeed, the device should be port reset. */ DPRINTF(UDMASS_CBI, ("%s: CBI Reset\n", USBDEVNAME(sc->sc_dev))); KASSERT(sizeof(sc->cbl) >= SEND_DIAGNOSTIC_CMDLEN, ("%s: CBL struct is too small (%ld < %d)\n", USBDEVNAME(sc->sc_dev), (long)sizeof(sc->cbl), SEND_DIAGNOSTIC_CMDLEN)); sc->transfer_state = TSTATE_CBI_RESET1; sc->transfer_status = status; /* The 0x1d code is the SEND DIAGNOSTIC command. To distinguish between * the two the last 10 bytes of the cbl is filled with 0xff (section * 2.2 of the CBI spec). */ sc->cbl[0] = 0x1d; /* Command Block Reset */ sc->cbl[1] = 0x04; for (i = 2; i < SEND_DIAGNOSTIC_CMDLEN; i++) sc->cbl[i] = 0xff; umass_cbi_adsc(sc, sc->cbl, SEND_DIAGNOSTIC_CMDLEN, sc->transfer_xfer[XFER_CBI_RESET1]); /* XXX if the command fails we should reset the port on the hub */ } Static void umass_cbi_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen, void *data, int datalen, int dir, u_int timeout, transfer_cb_f cb, void *priv) { KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), ("%s: umass_cbi_transfer: wrong sc->proto 0x%02x\n", USBDEVNAME(sc->sc_dev), sc->proto)); /* Be a little generous. */ sc->timeout = timeout + UMASS_TIMEOUT; /* * Do a CBI transfer with cmdlen bytes from cmd, possibly * a data phase of datalen bytes from/to the device and finally a * csw read phase. * If the data direction was inbound a maximum of datalen bytes * is stored in the buffer pointed to by data. * * umass_cbi_transfer initialises the transfer and lets the state * machine in umass_cbi_state handle the completion. It uses the * following states: * TSTATE_CBI_COMMAND * -> XXX fill in * * An error in any of those states will invoke * umass_cbi_reset. */ /* check the given arguments */ KASSERT(datalen == 0 || data != NULL, ("%s: datalen > 0, but no buffer",USBDEVNAME(sc->sc_dev))); KASSERT(datalen == 0 || dir != DIR_NONE, ("%s: direction is NONE while datalen is not zero\n", USBDEVNAME(sc->sc_dev))); /* store the details for the data transfer phase */ sc->transfer_dir = dir; sc->transfer_data = data; sc->transfer_datalen = datalen; sc->transfer_actlen = 0; sc->transfer_cb = cb; sc->transfer_priv = priv; sc->transfer_status = STATUS_CMD_OK; /* move from idle to the command state */ sc->transfer_state = TSTATE_CBI_COMMAND; DIF(UDMASS_CBI, umass_cbi_dump_cmd(sc, cmd, cmdlen)); /* Send the Command Block from host to device via control endpoint. */ if (umass_cbi_adsc(sc, cmd, cmdlen, sc->transfer_xfer[XFER_CBI_CB])) umass_cbi_reset(sc, STATUS_WIRE_FAILED); } Static void umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status err) { struct umass_softc *sc = (struct umass_softc *) priv; KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), ("%s: umass_cbi_state: wrong sc->proto 0x%02x\n", USBDEVNAME(sc->sc_dev), sc->proto)); /* * State handling for CBI transfers. */ DPRINTF(UDMASS_CBI, ("%s: Handling CBI state %d (%s), xfer=%p, %s\n", USBDEVNAME(sc->sc_dev), sc->transfer_state, states[sc->transfer_state], xfer, usbd_errstr(err))); switch (sc->transfer_state) { /***** CBI Transfer *****/ case TSTATE_CBI_COMMAND: if (err == USBD_STALLED) { DPRINTF(UDMASS_CBI, ("%s: Command Transport failed\n", USBDEVNAME(sc->sc_dev))); /* Status transport by control pipe (section 2.3.2.1). * The command contained in the command block failed. * * The control pipe has already been unstalled by the * USB stack. * Section 2.4.3.1.1 states that the bulk in endpoints * should not be stalled at this point. */ sc->transfer_state = TSTATE_IDLE; sc->transfer_cb(sc, sc->transfer_priv, sc->transfer_datalen, STATUS_CMD_FAILED); return; } else if (err) { DPRINTF(UDMASS_CBI, ("%s: failed to send ADSC\n", USBDEVNAME(sc->sc_dev))); umass_cbi_reset(sc, STATUS_WIRE_FAILED); return; } sc->transfer_state = TSTATE_CBI_DATA; if (sc->transfer_dir == DIR_IN) { if (umass_setup_transfer(sc, sc->bulkin_pipe, sc->transfer_data, sc->transfer_datalen, USBD_SHORT_XFER_OK, sc->transfer_xfer[XFER_CBI_DATA])) umass_cbi_reset(sc, STATUS_WIRE_FAILED); } else if (sc->transfer_dir == DIR_OUT) { if (umass_setup_transfer(sc, sc->bulkout_pipe, sc->transfer_data, sc->transfer_datalen, 0, /* fixed length transfer */ sc->transfer_xfer[XFER_CBI_DATA])) umass_cbi_reset(sc, STATUS_WIRE_FAILED); } else if (sc->proto & UMASS_PROTO_CBI_I) { DPRINTF(UDMASS_CBI, ("%s: no data phase\n", USBDEVNAME(sc->sc_dev))); sc->transfer_state = TSTATE_CBI_STATUS; if (umass_setup_transfer(sc, sc->intrin_pipe, &sc->sbl, sizeof(sc->sbl), 0, /* fixed length transfer */ sc->transfer_xfer[XFER_CBI_STATUS])){ umass_cbi_reset(sc, STATUS_WIRE_FAILED); } } else { DPRINTF(UDMASS_CBI, ("%s: no data phase\n", USBDEVNAME(sc->sc_dev))); /* No command completion interrupt. Request * sense data. */ sc->transfer_state = TSTATE_IDLE; sc->transfer_cb(sc, sc->transfer_priv, 0, STATUS_CMD_UNKNOWN); } return; case TSTATE_CBI_DATA: /* retrieve the length of the transfer that was done */ usbd_get_xfer_status(xfer,NULL,NULL,&sc->transfer_actlen,NULL); if (err) { DPRINTF(UDMASS_CBI, ("%s: Data-%s %db failed, " "%s\n", USBDEVNAME(sc->sc_dev), (sc->transfer_dir == DIR_IN?"in":"out"), sc->transfer_datalen,usbd_errstr(err))); if (err == USBD_STALLED) { umass_clear_endpoint_stall(sc, sc->bulkin, sc->bulkin_pipe, TSTATE_CBI_DCLEAR, sc->transfer_xfer[XFER_CBI_DCLEAR]); } else { umass_cbi_reset(sc, STATUS_WIRE_FAILED); } return; } DIF(UDMASS_CBI, if (sc->transfer_dir == DIR_IN) umass_dump_buffer(sc, sc->transfer_data, sc->transfer_actlen, 48)); if (sc->proto & UMASS_PROTO_CBI_I) { sc->transfer_state = TSTATE_CBI_STATUS; if (umass_setup_transfer(sc, sc->intrin_pipe, &sc->sbl, sizeof(sc->sbl), 0, /* fixed length transfer */ sc->transfer_xfer[XFER_CBI_STATUS])){ umass_cbi_reset(sc, STATUS_WIRE_FAILED); } } else { /* No command completion interrupt. Request * sense to get status of command. */ sc->transfer_state = TSTATE_IDLE; sc->transfer_cb(sc, sc->transfer_priv, sc->transfer_datalen - sc->transfer_actlen, STATUS_CMD_UNKNOWN); } return; case TSTATE_CBI_STATUS: if (err) { DPRINTF(UDMASS_CBI, ("%s: Status Transport failed\n", USBDEVNAME(sc->sc_dev))); /* Status transport by interrupt pipe (section 2.3.2.2). */ if (err == USBD_STALLED) { umass_clear_endpoint_stall(sc, sc->intrin, sc->intrin_pipe, TSTATE_CBI_SCLEAR, sc->transfer_xfer[XFER_CBI_SCLEAR]); } else { umass_cbi_reset(sc, STATUS_WIRE_FAILED); } return; } /* Dissect the information in the buffer */ if (sc->proto & UMASS_PROTO_UFI) { int status; /* Section 3.4.3.1.3 specifies that the UFI command * protocol returns an ASC and ASCQ in the interrupt * data block. */ DPRINTF(UDMASS_CBI, ("%s: UFI CCI, ASC = 0x%02x, " "ASCQ = 0x%02x\n", USBDEVNAME(sc->sc_dev), sc->sbl.ufi.asc, sc->sbl.ufi.ascq)); if (sc->sbl.ufi.asc == 0 && sc->sbl.ufi.ascq == 0) status = STATUS_CMD_OK; else status = STATUS_CMD_FAILED; sc->transfer_state = TSTATE_IDLE; sc->transfer_cb(sc, sc->transfer_priv, sc->transfer_datalen - sc->transfer_actlen, status); } else { /* Command Interrupt Data Block */ DPRINTF(UDMASS_CBI, ("%s: type=0x%02x, value=0x%02x\n", USBDEVNAME(sc->sc_dev), sc->sbl.common.type, sc->sbl.common.value)); if (sc->sbl.common.type == IDB_TYPE_CCI) { int err; if ((sc->sbl.common.value&IDB_VALUE_STATUS_MASK) == IDB_VALUE_PASS) { err = STATUS_CMD_OK; } else if ((sc->sbl.common.value & IDB_VALUE_STATUS_MASK) == IDB_VALUE_FAIL || (sc->sbl.common.value & IDB_VALUE_STATUS_MASK) == IDB_VALUE_PERSISTENT) { err = STATUS_CMD_FAILED; } else { err = STATUS_WIRE_FAILED; } sc->transfer_state = TSTATE_IDLE; sc->transfer_cb(sc, sc->transfer_priv, sc->transfer_datalen-sc->transfer_actlen, err); } } return; case TSTATE_CBI_DCLEAR: if (err) { /* should not occur */ printf("%s: CBI bulk-in/out stall clear failed, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err)); umass_cbi_reset(sc, STATUS_WIRE_FAILED); } sc->transfer_state = TSTATE_IDLE; sc->transfer_cb(sc, sc->transfer_priv, sc->transfer_datalen, STATUS_CMD_FAILED); return; case TSTATE_CBI_SCLEAR: if (err) /* should not occur */ printf("%s: CBI intr-in stall clear failed, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err)); /* Something really bad is going on. Reset the device */ umass_cbi_reset(sc, STATUS_CMD_FAILED); return; /***** CBI Reset *****/ case TSTATE_CBI_RESET1: if (err) printf("%s: CBI reset failed, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err)); umass_clear_endpoint_stall(sc, sc->bulkin, sc->bulkin_pipe, TSTATE_CBI_RESET2, sc->transfer_xfer[XFER_CBI_RESET2]); return; case TSTATE_CBI_RESET2: if (err) /* should not occur */ printf("%s: CBI bulk-in stall clear failed, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err)); /* no error recovery, otherwise we end up in a loop */ umass_clear_endpoint_stall(sc, sc->bulkout, sc->bulkout_pipe, TSTATE_CBI_RESET3, sc->transfer_xfer[XFER_CBI_RESET3]); return; case TSTATE_CBI_RESET3: if (err) /* should not occur */ printf("%s: CBI bulk-out stall clear failed, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err)); /* no error recovery, otherwise we end up in a loop */ sc->transfer_state = TSTATE_IDLE; if (sc->transfer_priv) { sc->transfer_cb(sc, sc->transfer_priv, sc->transfer_datalen, sc->transfer_status); } return; /***** Default *****/ default: panic("%s: Unknown state %d", USBDEVNAME(sc->sc_dev), sc->transfer_state); } } /* * CAM specific functions (used by SCSI, UFI, 8070i (ATAPI)) */ Static int umass_cam_attach_sim(struct umass_softc *sc) { struct cam_devq *devq; /* Per device Queue */ /* A HBA is attached to the CAM layer. * * The CAM layer will then after a while start probing for * devices on the bus. The number of SIMs is limited to one. */ devq = cam_simq_alloc(1 /*maximum openings*/); if (devq == NULL) return(ENOMEM); sc->umass_sim = cam_sim_alloc(umass_cam_action, umass_cam_poll, DEVNAME_SIM, sc /*priv*/, USBDEVUNIT(sc->sc_dev) /*unit number*/, 1 /*maximum device openings*/, 0 /*maximum tagged device openings*/, devq); if (sc->umass_sim == NULL) { cam_simq_free(devq); return(ENOMEM); } if(xpt_bus_register(sc->umass_sim, USBDEVUNIT(sc->sc_dev)) != CAM_SUCCESS) return(ENOMEM); return(0); } Static void umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb) { #ifdef USB_DEBUG if (ccb->ccb_h.status != CAM_REQ_CMP) { DPRINTF(UDMASS_SCSI, ("%s:%d Rescan failed, 0x%04x\n", periph->periph_name, periph->unit_number, ccb->ccb_h.status)); } else { DPRINTF(UDMASS_SCSI, ("%s%d: Rescan succeeded\n", periph->periph_name, periph->unit_number)); } #endif xpt_free_path(ccb->ccb_h.path); free(ccb, M_USBDEV); } Static void umass_cam_rescan(void *addr) { struct umass_softc *sc = (struct umass_softc *) addr; struct cam_path *path; union ccb *ccb = malloc(sizeof(union ccb), M_USBDEV, M_WAITOK); memset(ccb, 0, sizeof(union ccb)); DPRINTF(UDMASS_SCSI, ("scbus%d: scanning for %s:%d:%d:%d\n", cam_sim_path(sc->umass_sim), USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim), USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD)); if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->umass_sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) return; xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/); ccb->ccb_h.func_code = XPT_SCAN_BUS; ccb->ccb_h.cbfcnp = umass_cam_rescan_callback; ccb->crcn.flags = CAM_FLAG_NONE; xpt_action(ccb); /* The scan is in progress now. */ } Static int umass_cam_attach(struct umass_softc *sc) { #ifndef USB_DEBUG if (bootverbose) #endif printf("%s:%d:%d:%d: Attached to scbus%d\n", USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim), USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD, cam_sim_path(sc->umass_sim)); if (!cold) { /* Notify CAM of the new device after 1 second delay. Any * failure is benign, as the user can still do it by hand * (camcontrol rescan ). Only do this if we are not * booting, because CAM does a scan after booting has * completed, when interrupts have been enabled. */ /* XXX This will bomb if the driver is unloaded between attach * and execution of umass_cam_rescan. */ timeout(umass_cam_rescan, sc, MS_TO_TICKS(200)); } return(0); /* always succesfull */ } /* umass_cam_detach * detach from the CAM layer */ Static int umass_cam_detach_sim(struct umass_softc *sc) { if (sc->umass_sim) { if (xpt_bus_deregister(cam_sim_path(sc->umass_sim))) cam_sim_free(sc->umass_sim, /*free_devq*/TRUE); else return(EBUSY); sc->umass_sim = NULL; } return(0); } /* umass_cam_action * CAM requests for action come through here */ Static void umass_cam_action(struct cam_sim *sim, union ccb *ccb) { struct umass_softc *sc = (struct umass_softc *)sim->softc; /* The softc is still there, but marked as going away. umass_cam_detach * has not yet notified CAM of the lost device however. */ if (sc && (sc->flags & UMASS_FLAGS_GONE)) { DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: " "Invalid target (gone)\n", USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun, ccb->ccb_h.func_code)); ccb->ccb_h.status = CAM_TID_INVALID; xpt_done(ccb); return; } /* Verify, depending on the operation to perform, that we either got a * valid sc, because an existing target was referenced, or otherwise * the SIM is addressed. * * This avoids bombing out at a printf and does give the CAM layer some * sensible feedback on errors. */ switch (ccb->ccb_h.func_code) { case XPT_SCSI_IO: case XPT_RESET_DEV: case XPT_GET_TRAN_SETTINGS: case XPT_SET_TRAN_SETTINGS: case XPT_CALC_GEOMETRY: /* the opcodes requiring a target. These should never occur. */ if (sc == NULL) { printf("%s:%d:%d:%d:func_code 0x%04x: " "Invalid target (target needed)\n", DEVNAME_SIM, cam_sim_path(sc->umass_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun, ccb->ccb_h.func_code); ccb->ccb_h.status = CAM_TID_INVALID; xpt_done(ccb); return; } break; case XPT_PATH_INQ: case XPT_NOOP: /* The opcodes sometimes aimed at a target (sc is valid), * sometimes aimed at the SIM (sc is invalid and target is * CAM_TARGET_WILDCARD) */ if (sc == NULL && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: " "Invalid target (no wildcard)\n", DEVNAME_SIM, cam_sim_path(sc->umass_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun, ccb->ccb_h.func_code)); ccb->ccb_h.status = CAM_TID_INVALID; xpt_done(ccb); return; } break; default: /* XXX Hm, we should check the input parameters */ break; } /* Perform the requested action */ switch (ccb->ccb_h.func_code) { case XPT_SCSI_IO: { struct ccb_scsiio *csio = &ccb->csio; /* deref union */ int dir; unsigned char *cmd; int cmdlen; unsigned char *rcmd; int rcmdlen; DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: " "cmd: 0x%02x, flags: 0x%02x, " "%db cmd/%db data/%db sense\n", USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun, csio->cdb_io.cdb_bytes[0], ccb->ccb_h.flags & CAM_DIR_MASK, csio->cdb_len, csio->dxfer_len, csio->sense_len)); /* clear the end of the buffer to make sure we don't send out * garbage. */ DIF(UDMASS_SCSI, if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) umass_dump_buffer(sc, csio->data_ptr, csio->dxfer_len, 48)); if (sc->transfer_state != TSTATE_IDLE) { DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: " "I/O in progress, deferring (state %d, %s)\n", USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun, sc->transfer_state,states[sc->transfer_state])); ccb->ccb_h.status = CAM_SCSI_BUSY; xpt_done(ccb); return; } switch(ccb->ccb_h.flags&CAM_DIR_MASK) { case CAM_DIR_IN: dir = DIR_IN; break; case CAM_DIR_OUT: dir = DIR_OUT; break; default: dir = DIR_NONE; } ccb->ccb_h.status = CAM_REQ_INPROG | CAM_SIM_QUEUED; if (csio->ccb_h.flags & CAM_CDB_POINTER) { cmd = (unsigned char *) csio->cdb_io.cdb_ptr; } else { cmd = (unsigned char *) &csio->cdb_io.cdb_bytes; } cmdlen = csio->cdb_len; rcmd = (unsigned char *) &sc->cam_scsi_command; rcmdlen = sizeof(sc->cam_scsi_command); /* sc->transform will convert the command to the command * (format) needed by the specific command set and return * the converted command in a buffer pointed to be rcmd. * We pass in a buffer, but if the command does not * have to be transformed it returns a ptr to the original * buffer (see umass_scsi_transform). */ if (sc->transform(sc, cmd, cmdlen, &rcmd, &rcmdlen)) { /* * Handle EVPD inquiry for broken devices first * NO_INQUIRY also implies NO_INQUIRY_EVPD */ if ((sc->quirks & (NO_INQUIRY_EVPD | NO_INQUIRY)) && rcmd[0] == INQUIRY && (rcmd[1] & SI_EVPD)) { struct scsi_sense_data *sense; sense = &ccb->csio.sense_data; bzero(sense, sizeof(*sense)); sense->error_code = SSD_CURRENT_ERROR; sense->flags = SSD_KEY_ILLEGAL_REQUEST; sense->add_sense_code = 0x24; sense->extra_len = 10; ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; xpt_done(ccb); return; } /* Return fake inquiry data for broken devices */ if ((sc->quirks & NO_INQUIRY) && rcmd[0] == INQUIRY) { struct ccb_scsiio *csio = &ccb->csio; memcpy(csio->data_ptr, &fake_inq_data, sizeof(fake_inq_data)); csio->scsi_status = SCSI_STATUS_OK; ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); return; } if ((sc->quirks & FORCE_SHORT_INQUIRY) && rcmd[0] == INQUIRY) { csio->dxfer_len = SHORT_INQUIRY_LENGTH; } sc->transfer(sc, ccb->ccb_h.target_lun, rcmd, rcmdlen, csio->data_ptr, csio->dxfer_len, dir, ccb->ccb_h.timeout, umass_cam_cb, (void *) ccb); } else { ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); } break; } case XPT_PATH_INQ: { struct ccb_pathinq *cpi = &ccb->cpi; DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_PATH_INQ:.\n", (sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)), cam_sim_path(sc->umass_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); /* host specific information */ cpi->version_num = 1; cpi->hba_inquiry = 0; cpi->target_sprt = 0; cpi->hba_misc = PIM_NO_6_BYTE; cpi->hba_eng_cnt = 0; cpi->max_target = UMASS_SCSIID_MAX; /* one target */ cpi->initiator_id = UMASS_SCSIID_HOST; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); strncpy(cpi->hba_vid, "USB SCSI", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); cpi->bus_id = USBDEVUNIT(sc->sc_dev); if (sc == NULL) { cpi->base_transfer_speed = 0; cpi->max_lun = 0; } else { if (sc->quirks & FLOPPY_SPEED) { cpi->base_transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED; } else { cpi->base_transfer_speed = UMASS_DEFAULT_TRANSFER_SPEED; } cpi->max_lun = sc->maxlun; } cpi->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; } case XPT_RESET_DEV: { DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_RESET_DEV:.\n", USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); ccb->ccb_h.status = CAM_REQ_INPROG; umass_reset(sc, umass_cam_cb, (void *) ccb); break; } case XPT_GET_TRAN_SETTINGS: { struct ccb_trans_settings *cts = &ccb->cts; DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_GET_TRAN_SETTINGS:.\n", USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); cts->valid = 0; cts->flags = 0; /* no disconnection, tagging */ ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; } case XPT_SET_TRAN_SETTINGS: { DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SET_TRAN_SETTINGS:.\n", USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; xpt_done(ccb); break; } case XPT_CALC_GEOMETRY: { cam_calc_geometry(&ccb->ccg, /*extended*/1); xpt_done(ccb); break; } case XPT_NOOP: { DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_NOOP:.\n", (sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)), cam_sim_path(sc->umass_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; } default: DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: " "Not implemented\n", (sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)), cam_sim_path(sc->umass_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun, ccb->ccb_h.func_code)); ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; xpt_done(ccb); break; } } /* umass_cam_poll * all requests are handled through umass_cam_action, requests * are never pending. So, nothing to do here. */ Static void umass_cam_poll(struct cam_sim *sim) { #ifdef USB_DEBUG struct umass_softc *sc = (struct umass_softc *) sim->softc; DPRINTF(UDMASS_SCSI, ("%s: CAM poll\n", USBDEVNAME(sc->sc_dev))); #endif /* nop */ } /* umass_cam_cb * finalise a completed CAM command */ Static void umass_cam_cb(struct umass_softc *sc, void *priv, int residue, int status) { union ccb *ccb = (union ccb *) priv; struct ccb_scsiio *csio = &ccb->csio; /* deref union */ csio->resid = residue; switch (status) { case STATUS_CMD_OK: ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; case STATUS_CMD_UNKNOWN: case STATUS_CMD_FAILED: switch (ccb->ccb_h.func_code) { case XPT_SCSI_IO: { unsigned char *rcmd; int rcmdlen; /* fetch sense data */ /* the rest of the command was filled in at attach */ sc->cam_scsi_sense.length = csio->sense_len; DPRINTF(UDMASS_SCSI,("%s: Fetching %db sense data\n", USBDEVNAME(sc->sc_dev), csio->sense_len)); rcmd = (unsigned char *) &sc->cam_scsi_command; rcmdlen = sizeof(sc->cam_scsi_command); if (sc->transform(sc, (unsigned char *) &sc->cam_scsi_sense, sizeof(sc->cam_scsi_sense), &rcmd, &rcmdlen)) { if ((sc->quirks & FORCE_SHORT_INQUIRY) && (rcmd[0] == INQUIRY)) { csio->sense_len = SHORT_INQUIRY_LENGTH; } sc->transfer(sc, ccb->ccb_h.target_lun, rcmd, rcmdlen, &csio->sense_data, csio->sense_len, DIR_IN, ccb->ccb_h.timeout, umass_cam_sense_cb, (void *) ccb); } else { panic("transform(REQUEST_SENSE) failed"); } break; } case XPT_RESET_DEV: /* Reset failed */ ccb->ccb_h.status = CAM_REQ_CMP_ERR; xpt_done(ccb); break; default: panic("umass_cam_cb called for func_code %d", ccb->ccb_h.func_code); } break; case STATUS_WIRE_FAILED: /* the wire protocol failed and will have recovered * (hopefully). We return an error to CAM and let CAM retry * the command if necessary. */ ccb->ccb_h.status = CAM_REQ_CMP_ERR; xpt_done(ccb); break; default: panic("%s: Unknown status %d in umass_cam_cb", USBDEVNAME(sc->sc_dev), status); } } /* Finalise a completed autosense operation */ Static void umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status) { union ccb *ccb = (union ccb *) priv; struct ccb_scsiio *csio = &ccb->csio; /* deref union */ unsigned char *rcmd; int rcmdlen; switch (status) { case STATUS_CMD_OK: case STATUS_CMD_UNKNOWN: case STATUS_CMD_FAILED: /* Getting sense data always succeeds (apart from wire * failures). */ if ((sc->quirks & RS_NO_CLEAR_UA) && csio->cdb_io.cdb_bytes[0] == INQUIRY && (csio->sense_data.flags & SSD_KEY) == SSD_KEY_UNIT_ATTENTION) { /* Ignore unit attention errors in the case where * the Unit Attention state is not cleared on * REQUEST SENSE. They will appear again at the next * command. */ ccb->ccb_h.status = CAM_REQ_CMP; } else if ((csio->sense_data.flags & SSD_KEY) == SSD_KEY_NO_SENSE) { /* No problem after all (in the case of CBI without * CCI) */ ccb->ccb_h.status = CAM_REQ_CMP; } else if ((sc->quirks & RS_NO_CLEAR_UA) && (csio->cdb_io.cdb_bytes[0] == READ_CAPACITY) && ((csio->sense_data.flags & SSD_KEY) == SSD_KEY_UNIT_ATTENTION)) { /* * Some devices do not clear the unit attention error * on request sense. We insert a test unit ready * command to make sure we clear the unit attention * condition, then allow the retry to proceed as * usual. */ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; csio->scsi_status = SCSI_STATUS_CHECK_COND; #if 0 DELAY(300000); #endif DPRINTF(UDMASS_SCSI,("%s: Doing a sneaky" "TEST_UNIT_READY\n", USBDEVNAME(sc->sc_dev))); /* the rest of the command was filled in at attach */ rcmd = (unsigned char *) &sc->cam_scsi_command2; rcmdlen = sizeof(sc->cam_scsi_command2); if (sc->transform(sc, (unsigned char *) &sc->cam_scsi_test_unit_ready, sizeof(sc->cam_scsi_test_unit_ready), &rcmd, &rcmdlen)) { sc->transfer(sc, ccb->ccb_h.target_lun, rcmd, rcmdlen, NULL, 0, DIR_NONE, ccb->ccb_h.timeout, umass_cam_quirk_cb, (void *) ccb); } else { panic("transform(TEST_UNIT_READY) failed"); } break; } else { ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; csio->scsi_status = SCSI_STATUS_CHECK_COND; } xpt_done(ccb); break; default: DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n", USBDEVNAME(sc->sc_dev), status)); ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; xpt_done(ccb); } } /* * This completion code just handles the fact that we sent a test-unit-ready * after having previously failed a READ CAPACITY with CHECK_COND. Even * though this command succeeded, we have to tell CAM to retry. */ Static void umass_cam_quirk_cb(struct umass_softc *sc, void *priv, int residue, int status) { union ccb *ccb = (union ccb *) priv; DPRINTF(UDMASS_SCSI, ("%s: Test unit ready returned status %d\n", USBDEVNAME(sc->sc_dev), status)); #if 0 ccb->ccb_h.status = CAM_REQ_CMP; #endif ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; xpt_done(ccb); } Static int umass_driver_load(module_t mod, int what, void *arg) { switch (what) { case MOD_UNLOAD: case MOD_LOAD: default: return(usbd_driver_load(mod, what, arg)); } } /* * SCSI specific functions */ Static int umass_scsi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, unsigned char **rcmd, int *rcmdlen) { switch (cmd[0]) { case TEST_UNIT_READY: if (sc->quirks & NO_TEST_UNIT_READY) { KASSERT(*rcmdlen >= sizeof(struct scsi_start_stop_unit), ("rcmdlen = %d < %ld, buffer too small", *rcmdlen, (long)sizeof(struct scsi_start_stop_unit))); DPRINTF(UDMASS_SCSI, ("%s: Converted TEST_UNIT_READY " "to START_UNIT\n", USBDEVNAME(sc->sc_dev))); memset(*rcmd, 0, *rcmdlen); (*rcmd)[0] = START_STOP_UNIT; (*rcmd)[4] = SSS_START; return 1; } /* fallthrough */ case INQUIRY: /* some drives wedge when asked for full inquiry information. */ if (sc->quirks & FORCE_SHORT_INQUIRY) { memcpy(*rcmd, cmd, cmdlen); *rcmdlen = cmdlen; (*rcmd)[4] = SHORT_INQUIRY_LENGTH; return 1; } /* fallthrough */ default: *rcmd = cmd; /* We don't need to copy it */ *rcmdlen = cmdlen; } return 1; } /* RBC specific functions */ Static int umass_rbc_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, unsigned char **rcmd, int *rcmdlen) { switch (cmd[0]) { /* these commands are defined in RBC: */ case READ_10: case READ_CAPACITY: case START_STOP_UNIT: case SYNCHRONIZE_CACHE: case WRITE_10: case 0x2f: /* VERIFY_10 is absent from scsi_all.h??? */ case INQUIRY: case MODE_SELECT_10: case MODE_SENSE_10: case TEST_UNIT_READY: case WRITE_BUFFER: /* The following commands are not listed in my copy of the RBC specs. * CAM however seems to want those, and at least the Sony DSC device * appears to support those as well */ case REQUEST_SENSE: case PREVENT_ALLOW: *rcmd = cmd; /* We don't need to copy it */ *rcmdlen = cmdlen; return 1; /* All other commands are not legal in RBC */ default: printf("%s: Unsupported RBC command 0x%02x", USBDEVNAME(sc->sc_dev), cmd[0]); printf("\n"); return 0; /* failure */ } } /* * UFI specific functions */ Static int umass_ufi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, unsigned char **rcmd, int *rcmdlen) { /* A UFI command is always 12 bytes in length */ KASSERT(*rcmdlen >= UFI_COMMAND_LENGTH, ("rcmdlen = %d < %d, buffer too small", *rcmdlen, UFI_COMMAND_LENGTH)); *rcmdlen = UFI_COMMAND_LENGTH; memset(*rcmd, 0, UFI_COMMAND_LENGTH); switch (cmd[0]) { /* Commands of which the format has been verified. They should work. * Copy the command into the (zeroed out) destination buffer. */ case TEST_UNIT_READY: if (sc->quirks & NO_TEST_UNIT_READY) { /* Some devices do not support this command. * Start Stop Unit should give the same results */ DPRINTF(UDMASS_UFI, ("%s: Converted TEST_UNIT_READY " "to START_UNIT\n", USBDEVNAME(sc->sc_dev))); (*rcmd)[0] = START_STOP_UNIT; (*rcmd)[4] = SSS_START; } else { memcpy(*rcmd, cmd, cmdlen); } return 1; case REZERO_UNIT: case REQUEST_SENSE: case INQUIRY: case START_STOP_UNIT: case SEND_DIAGNOSTIC: case PREVENT_ALLOW: case READ_CAPACITY: case READ_10: case WRITE_10: case POSITION_TO_ELEMENT: /* SEEK_10 */ case MODE_SELECT_10: case MODE_SENSE_10: case READ_12: case WRITE_12: memcpy(*rcmd, cmd, cmdlen); return 1; /* Other UFI commands: FORMAT_UNIT, READ_FORMAT_CAPACITY, * VERIFY, WRITE_AND_VERIFY. * These should be checked whether they somehow can be made to fit. */ default: printf("%s: Unsupported UFI command 0x%02x\n", USBDEVNAME(sc->sc_dev), cmd[0]); return 0; /* failure */ } } /* * 8070i (ATAPI) specific functions */ Static int umass_atapi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, unsigned char **rcmd, int *rcmdlen) { /* An ATAPI command is always 12 bytes in length. */ KASSERT(*rcmdlen >= ATAPI_COMMAND_LENGTH, ("rcmdlen = %d < %d, buffer too small", *rcmdlen, ATAPI_COMMAND_LENGTH)); *rcmdlen = ATAPI_COMMAND_LENGTH; memset(*rcmd, 0, ATAPI_COMMAND_LENGTH); switch (cmd[0]) { /* Commands of which the format has been verified. They should work. * Copy the command into the (zeroed out) destination buffer. */ case INQUIRY: memcpy(*rcmd, cmd, cmdlen); /* some drives wedge when asked for full inquiry information. */ if (sc->quirks & FORCE_SHORT_INQUIRY) (*rcmd)[4] = SHORT_INQUIRY_LENGTH; return 1; case TEST_UNIT_READY: if (sc->quirks & NO_TEST_UNIT_READY) { KASSERT(*rcmdlen >= sizeof(struct scsi_start_stop_unit), ("rcmdlen = %d < %ld, buffer too small", *rcmdlen, (long)sizeof(struct scsi_start_stop_unit))); DPRINTF(UDMASS_SCSI, ("%s: Converted TEST_UNIT_READY " "to START_UNIT\n", USBDEVNAME(sc->sc_dev))); memset(*rcmd, 0, *rcmdlen); (*rcmd)[0] = START_STOP_UNIT; (*rcmd)[4] = SSS_START; return 1; } /* fallthrough */ case REZERO_UNIT: case REQUEST_SENSE: case START_STOP_UNIT: case SEND_DIAGNOSTIC: case PREVENT_ALLOW: case READ_CAPACITY: case READ_10: case WRITE_10: case POSITION_TO_ELEMENT: /* SEEK_10 */ case SYNCHRONIZE_CACHE: case MODE_SELECT_10: case MODE_SENSE_10: case READ_BUFFER: case 0x42: /* READ_SUBCHANNEL */ case 0x43: /* READ_TOC */ case 0x44: /* READ_HEADER */ case 0x51: /* READ_DISK_INFO */ case 0x52: /* READ_TRACK_INFO */ case 0x54: /* SEND_OPC */ case 0x59: /* READ_MASTER_CUE */ case 0x5b: /* CLOSE_TR_SESSION */ case 0x5c: /* READ_BUFFER_CAP */ case 0x5d: /* SEND_CUE_SHEET */ case 0xa1: /* BLANK */ case 0xa6: /* EXCHANGE_MEDIUM */ case 0xad: /* READ_DVD_STRUCTURE */ case 0xbb: /* SET_CD_SPEED */ case 0xe5: /* READ_TRACK_INFO_PHILIPS */ memcpy(*rcmd, cmd, cmdlen); return 1; case READ_12: case WRITE_12: default: printf("%s: Unsupported ATAPI command 0x%02x\n", USBDEVNAME(sc->sc_dev), cmd[0]); return 0; /* failure */ } } /* (even the comment is missing) */ DRIVER_MODULE(umass, uhub, umass_driver, umass_devclass, umass_driver_load, 0); #ifdef USB_DEBUG Static void umass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw) { int clen = cbw->bCDBLength; int dlen = UGETDW(cbw->dCBWDataTransferLength); u_int8_t *c = cbw->CBWCDB; int tag = UGETDW(cbw->dCBWTag); int flags = cbw->bCBWFlags; DPRINTF(UDMASS_BBB, ("%s: CBW %d: cmd = %db " "(0x%02x%02x%02x%02x%02x%02x%s), " "data = %db, dir = %s\n", USBDEVNAME(sc->sc_dev), tag, clen, c[0], c[1], c[2], c[3], c[4], c[5], (clen > 6? "...":""), dlen, (flags == CBWFLAGS_IN? "in": (flags == CBWFLAGS_OUT? "out":"")))); } Static void umass_bbb_dump_csw(struct umass_softc *sc, umass_bbb_csw_t *csw) { int sig = UGETDW(csw->dCSWSignature); int tag = UGETW(csw->dCSWTag); int res = UGETDW(csw->dCSWDataResidue); int status = csw->bCSWStatus; DPRINTF(UDMASS_BBB, ("%s: CSW %d: sig = 0x%08x (%s), tag = %d, " "res = %d, status = 0x%02x (%s)\n", USBDEVNAME(sc->sc_dev), tag, sig, (sig == CSWSIGNATURE? "valid":"invalid"), tag, res, status, (status == CSWSTATUS_GOOD? "good": (status == CSWSTATUS_FAILED? "failed": (status == CSWSTATUS_PHASE? "phase":""))))); } Static void umass_cbi_dump_cmd(struct umass_softc *sc, void *cmd, int cmdlen) { u_int8_t *c = cmd; int dir = sc->transfer_dir; DPRINTF(UDMASS_BBB, ("%s: cmd = %db " "(0x%02x%02x%02x%02x%02x%02x%s), " "data = %db, dir = %s\n", USBDEVNAME(sc->sc_dev), cmdlen, c[0], c[1], c[2], c[3], c[4], c[5], (cmdlen > 6? "...":""), sc->transfer_datalen, (dir == DIR_IN? "in": (dir == DIR_OUT? "out": (dir == DIR_NONE? "no data phase": ""))))); } Static void umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, int buflen, int printlen) { int i, j; char s1[40]; char s2[40]; char s3[5]; s1[0] = '\0'; s3[0] = '\0'; sprintf(s2, " buffer=%p, buflen=%d", buffer, buflen); for (i = 0; i < buflen && i < printlen; i++) { j = i % 16; if (j == 0 && i != 0) { DPRINTF(UDMASS_GEN, ("%s: 0x %s%s\n", USBDEVNAME(sc->sc_dev), s1, s2)); s2[0] = '\0'; } sprintf(&s1[j*2], "%02x", buffer[i] & 0xff); } if (buflen > printlen) sprintf(s3, " ..."); DPRINTF(UDMASS_GEN, ("%s: 0x %s%s%s\n", USBDEVNAME(sc->sc_dev), s1, s2, s3)); } #endif Index: head/sys/dev/usb/usbdevs =================================================================== --- head/sys/dev/usb/usbdevs (revision 130105) +++ head/sys/dev/usb/usbdevs (revision 130106) @@ -1,1335 +1,1336 @@ $FreeBSD$ /* * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Lennart Augustsson (lennart@augustsson.net) at * Carlstedt Research & Technology. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * List of known USB vendors * * Adding an ID and its string description for a device to the usbdevs file, * enables the USB stack to print a useful description of the device that was * connected. * * The ID should be added in usbdevs and then the files usbdevs.h and * usbdevs_data.h need to be regenerated. * * # edit usbdevs * make -f Makefile.usbdevs * # test your change * cd ../../modules/usb * make * # commit, if appropriate * cvs -m "ID for device XYZ" commit usbdevs * # commit the derived files after the $ FreeBSD $ has been updated. * cvs commit usbdevs.h usbdevs_data.h * * Please note that these IDs do not do anything. Adding an ID here and * regenerating the usbdevs.h and usbdevs_data.h only makes a symbolic name * available to the source code and does not change any functionality, nor * does it make your device available to a specific driver. * It will however make the descriptive string available if a device does not * provide the string itself. * * After adding a vendor ID VNDR and a product ID PRDCT you will have the * following extra defines: * #define USB_VENDOR_VNDR 0x???? * #define USB_PRODUCT_VNDR_PRDCT 0x???? * * You may have to add these defines to the respective probe routines to * make the device recognised by the appropriate device driver. */ vendor AOX 0x03e8 AOX vendor ATMEL 0x03eb Atmel vendor MITSUMI 0x03ee Mitsumi vendor HP 0x03f0 Hewlett Packard vendor ADAPTEC 0x03f3 Adaptec vendor NATIONAL 0x0400 National Semiconductor vendor ACERLABS 0x0402 Acer Labs vendor FTDI 0x0403 Future Technology Devices vendor NEC 0x0409 NEC vendor KODAK 0x040a Eastman Kodak vendor MELCO 0x0411 Melco vendor CREATIVE 0x041e Creative vendor ADI 0x0422 ADI Systems vendor CATC 0x0423 Computer Access Technology vendor SMC2 0x0424 Standard Microsystems vendor GRAVIS 0x0428 Advanced Gravis Computer Tech. vendor SUN 0x0430 Sun Microsystems vendor TAUGA 0x0436 Taugagreining HF vendor AMD 0x0438 Advanced Micro Devices vendor LEXMARK 0x043d Lexmark International vendor NANAO 0x0440 NANAO vendor ALPS 0x044e Alps Electric vendor THRUST 0x044f Thrustmaster vendor TI 0x0451 Texas Instruments vendor ANALOGDEVICES 0x0456 Analog Devices vendor KYE 0x0458 KYE Systems vendor DIAMOND2 0x045a Diamond (Supra) vendor MICROSOFT 0x045e Microsoft vendor PRIMAX 0x0461 Primax Electronics vendor AMP 0x0464 AMP vendor CHERRY 0x046a Cherry Mikroschalter vendor MEGATRENDS 0x046b American Megatrends vendor LOGITECH 0x046d Logitech vendor BTC 0x046e Behavior Tech. Computer vendor PHILIPS 0x0471 Philips vendor SANYO 0x0474 Sanyo Electric vendor CONNECTIX 0x0478 Connectix vendor KENSINGTON 0x047d Kensington vendor LUCENT 0x047e Lucent vendor KYOCERA 0x0482 Kyocera Corp. vendor STMICRO 0x0483 STMicroelectronics vendor YAMAHA 0x0499 YAMAHA vendor COMPAQ 0x049f Compaq Computers vendor HITACHI 0x04a4 Hitachi, Ltd. vendor ACERP 0x04a5 Acer Peripherals vendor VISIONEER 0x04a7 Visioneer vendor CANON 0x04a9 Canon vendor NIKON 0x04b0 Nikon vendor IBM 0x04b3 IBM Corporation vendor CYPRESS 0x04b4 Cypress Semiconductor vendor EPSON 0x04b8 Seiko Epson vendor RAINBOW 0x04b9 Rainbow Technologies vendor IODATA 0x04bb I/O Data vendor TDK 0x04bf TDK vendor 3COMUSR 0x04c1 U.S. Robotics vendor METHODE 0x04c2 Methode Electronics Far East vendor MAXISWITCH 0x04c3 Maxi Switch vendor LOCKHEEDMER 0x04c4 Lockheed Martin Energy Research vendor FUJITSU 0x04c5 Fujitsu vendor TOSHIBAAM 0x04c6 Toshiba America Electronic Components vendor MICROMACRO 0x04c7 Micro Macro Technologies vendor KONICA 0x04c8 Konica vendor LITEON 0x04ca Lite-On Technology vendor FUJIPHOTO 0x04cb Fuji Photo Film vendor PHILIPSSEMI 0x04cc Philips Semiconductors vendor TATUNG 0x04cd Tatung Co. Of America vendor SCANLOGIC 0x04ce ScanLogic vendor MYSON 0x04cf Myson Technology vendor DIGI2 0x04d0 Digi International vendor ITTCANON 0x04d1 ITT Canon vendor ALTEC 0x04d2 Altec Lansing Technologies vendor PANASONIC 0x04da Panasonic (Matsushita) vendor IIYAMA 0x04e1 Iiyama vendor SHUTTLE 0x04e6 Shuttle Technology vendor SAMSUNG 0x04e8 Samsung Electronics vendor ANNABOOKS 0x04ed Annabooks vendor JVC 0x04f1 JVC vendor CHICONY 0x04f2 Chicony Electronics vendor BROTHER 0x04f9 Brother Industries vendor DALLAS 0x04fa Dallas Semiconductor vendor ACER 0x0502 Acer vendor 3COM 0x0506 3Com vendor AZTECH 0x0509 Aztech Systems vendor BELKIN 0x050d Belkin Components vendor KAWATSU 0x050f Kawatsu Semiconductor vendor APC 0x051d American Power Conversion vendor CONNECTEK 0x0522 Advanced Connectek USA vendor NETCHIP 0x0525 NetChip Technology vendor ALTRA 0x0527 ALTRA vendor ATI 0x0528 ATI Technologies vendor AKS 0x0529 Aladdin Knowledge Systems vendor UNIACCESS 0x0540 Universal Access vendor XIRLINK 0x0545 Xirlink vendor ANCHOR 0x0547 Anchor Chips vendor SONY 0x054c Sony vendor VISION 0x0553 VLSI Vision vendor ASAHIKASEI 0x0556 Asahi Kasei Microsystems vendor ATEN 0x0557 ATEN International vendor MUSTEK 0x055f Mustek Systems vendor TELEX 0x0562 Telex Communications vendor PERACOM 0x0565 Peracom Networks vendor ALCOR2 0x0566 Alcor Micro vendor WACOM 0x056a WACOM vendor ETEK 0x056c e-TEK Labs vendor EIZO 0x056d EIZO vendor ELECOM 0x056e Elecom vendor HAUPPAUGE 0x0573 Hauppauge Computer Works vendor BAFO 0x0576 BAFO/Quality Computer Accessories vendor YEDATA 0x057b Y-E Data vendor AVM 0x057c AVM GmbH vendor QUICKSHOT 0x057f Quickshot vendor ROLAND 0x0582 Roland vendor ROCKFIRE 0x0583 Rockfire vendor RATOC 0x0584 RATOC Systems, Inc. vendor ZYXEL 0x0586 ZyXEL Communication vendor ALCOR 0x058f Alcor Micro vendor IOMEGA 0x059b Iomega vendor ATREND 0x059c A-Trend Technology vendor AID 0x059d Advanced Input Devices vendor LACIE 0x059f LaCie vendor OMNIVISION 0x05a9 OmniVision vendor INSYSTEM 0x05ab In-System Design vendor APPLE 0x05ac Apple Computer vendor DIGI 0x05c5 Digi International vendor QTRONIX 0x05c7 Qtronix vendor ELSA 0x05cc ELSA vendor BRAINBOXES 0x05d1 Brainboxes Limited vendor ULTIMA 0x05d8 Ultima vendor AXIOHM 0x05d9 Axiohm Transaction Solutions vendor MICROTEK 0x05da Microtek vendor SUNTAC 0x05db SUN Corporation vendor LEXAR 0x05dc Lexar Media vendor SYMBOL 0x05e0 Symbol Technologies vendor GENESYS 0x05e3 Genesys Logic vendor FUJI 0x05e5 Fuji Electric vendor KEITHLEY 0x05e6 Keithley Instruments vendor EIZONANAO 0x05e7 EIZO Nanao vendor KLSI 0x05e9 Kawasaki LSI vendor FFC 0x05eb FFC vendor ANKO 0x05ef Anko Electronic vendor PIENGINEERING 0x05f3 P.I. Engineering vendor AOC 0x05f6 AOC International vendor CHIC 0x05fe Chic Technology vendor BARCO 0x0600 Barco Display Systems vendor BRIDGE 0x0607 Bridge Information vendor SOLIDYEAR 0x060b Solid Year vendor BIORAD 0x0614 Bio-Rad Laboratories vendor MACALLY 0x0618 Macally vendor ACTLABS 0x061c Act Labs vendor ALARIS 0x0620 Alaris vendor APEX 0x0624 Apex vendor AVISION 0x0638 Avision vendor TEAC 0x0644 TEAC vendor LINKSYS 0x066b Linksys vendor ACERSA 0x066e Acer Semiconductor America vendor SIGMATEL 0x066f Sigmatel vendor AIWA 0x0677 Aiwa vendor ACARD 0x0678 ACARD Technology vendor PROLIFIC 0x067b Prolific Technology vendor SIEMENS 0x067c Siemens vendor ADVANCELOGIC 0x0680 Avance Logic vendor HAGIWARA 0x0693 Hagiwara Sys-Com vendor MINOLTA 0x0686 Minolta vendor CTX 0x0698 Chuntex vendor ASKEY 0x069a Askey Computer vendor SAITEK 0x06a3 Saitek vendor ALCATELT 0x06b9 Alcatel Telecom vendor AGFA 0x06bd AGFA-Gevaert vendor ASIAMD 0x06be Asia Microelectronic Development vendor BIZLINK 0x06c4 Bizlink International vendor KEYSPAN 0x06cd Keyspan vendor AASHIMA 0x06d6 Aashima Technology vendor MULTITECH 0x06e0 MultiTech vendor ADS 0x06e1 ADS Technologies vendor ALCATELM 0x06e4 Alcatel Microelectronics vendor SIRIUS 0x06ea Sirius Technologies vendor BOSTON 0x06fd Boston Acoustics vendor SMC 0x0707 Standard Microsystems vendor PUTERCOM 0x0708 Putercom vendor MCT 0x0711 MCT vendor DIGITALSTREAM 0x074e Digital Stream vendor AUREAL 0x0755 Aureal Semiconductor vendor MIDIMAN 0x0763 Midiman vendor LINKSYS2 0x077b Linksys vendor GRIFFIN 0x077d Griffin Technology vendor SANDISK 0x0781 SanDisk Corp vendor LOGITEC 0x0789 Logitec Corp vendor BRIMAX 0x078e Brimax vendor AXIS 0x0792 Axis Communications vendor ABL 0x0794 ABL Electronics vendor ALFADATA 0x079d Alfadata Computer vendor NATIONALTECH 0x07a2 National Technical Systems vendor ONNTO 0x07a3 Onnto vendor BE 0x07a4 Be vendor ADMTEK 0x07a6 ADMtek vendor COREGA 0x07aa Corega vendor FREECOM 0x07ab Freecom vendor MICROTECH 0x07af Microtech vendor GENERALINSTMNTS 0x07b2 General Instruments (Motorola) vendor OLYMPUS 0x07b4 Olympus vendor ONSPEC 0x07c4 OnSpec Electronic vendor ABOCOM 0x07b8 AboCom Systems vendor KEISOKUGIKEN 0x07c1 Keisokugiken vendor APG 0x07c5 APG Cash Drawer vendor BUG 0x07c8 B.U.G. vendor ALLIEDTELESYN 0x07c9 Allied Telesyn International vendor AVERMEDIA 0x07ca AVerMedia Technologies vendor SIIG 0x07cc SIIG vendor CASIO 0x07cf CASIO vendor APTIO 0x07d2 Aptio Products vendor ARASAN 0x07da Arasan Chip Systems vendor ALLIEDCABLE 0x07e6 Allied Cable vendor STSN 0x07ef STSN vendor ZOOM 0x0803 Zoom Telephonics vendor BROADLOGIC 0x0827 BroadLogic vendor HANDSPRING 0x082d Handspring vendor ACTIONSTAR 0x0835 Action Star Enterprise vendor PALM 0x0830 Palm Computing vendor SOURCENEXT 0x0833 SOURCENEXT vendor ACCTON 0x083a Accton Technology vendor DIAMOND 0x0841 Diamond vendor NETGEAR 0x0846 BayNETGEAR vendor ACTIVEWIRE 0x0854 ActiveWire vendor PORTGEAR 0x085a PortGear vendor METRICOM 0x0870 Metricom vendor ADESSOKBTEK 0x087c ADESSO/Kbtek America vendor JATON 0x087d Jaton vendor APT 0x0880 APT Technologies vendor BOCARESEARCH 0x0885 Boca Research vendor ANDREA 0x08a8 Andrea Electronics vendor BURRBROWN 0x08bb Burr-Brown Japan vendor 2WIRE 0x08c8 2Wire vendor AIPTEK 0x08ca AIPTEK International vendor SMARTBRIDGES 0x08d1 SmartBridges vendor BILLIONTON 0x08dd Billionton Systems vendor EXTENDED 0x08e9 Extended Systems vendor MSYSTEMS 0x08ec M-Systems vendor AUTHENTEC 0x08ff AuthenTec vendor ALATION 0x0910 Alation Systems vendor GOHUBS 0x0921 GoHubs vendor BIOMETRIC 0x0929 American Biometric Company vendor TOSHIBA 0x0930 Toshiba Corporation vendor PLEXTOR 0x093b Plextor Corp. vendor YANO 0x094f Yano vendor KINGSTON 0x0951 Kingston Technology vendor BLUEWATER 0x0956 BlueWater Systems vendor AGILENT 0x0957 Agilent Technologies vendor PORTSMITH 0x095a Portsmith vendor ADIRONDACK 0x0976 Adirondack Wire & Cable vendor BECKHOFF 0x0978 Beckhoff vendor INTERSIL 0x09aa Intersil vendor ALTIUS 0x09b3 Altius Solutions vendor ARRIS 0x09c1 Arris Interactive vendor ACTIVCARD 0x09c3 ACTIVCARD vendor ACTISYS 0x09c4 ACTiSYS vendor AFOURTECH 0x09da A-FOUR TECH vendor AIMEX 0x09dc AIMEX vendor ADDONICS 0x09df Addonics Technologies vendor AKAI 0x09e8 AKAI professional M.I. vendor ARESCOM 0x09f5 ARESCOM vendor BAY 0x09f9 Bay Associates vendor ALTERA 0x09fb Altera vendor CSR 0x0a12 Cambridge Silicon Radio Ltd. vendor TREK 0x0a16 Trek Technology vendor ASAHIOPTICAL 0x0a17 Asahi Optical vendor BOCASYSTEMS 0x0a43 Boca Systems vendor BROADCOM 0x0a5c Broadcom vendor GREENHOUSE 0x0a6b GREENHOUSE vendor GEOCAST 0x0a79 Geocast Network Systems vendor NEODIO 0x0aec Neodio vendor TODOS 0x0b0c Todos Data System vendor HAL 0x0b41 HAL Corporation vendor EMS 0x0b43 EMS Production Ltd. vendor NEC2 0x0b62 NEC vendor ATI2 0x0b6f ATI vendor ASIX 0x0b95 ASIX Electronics vendor REALTEK 0x0bda RealTek vendor AGATE 0x0c08 Agate Technologies vendor DMI 0x0c0b DMI vendor LUWEN 0x0c76 Luwen vendor SMC3 0x0d5c Standard Microsystems vendor PNY 0x0d7d PNY vendor MSI 0x0db0 Micro Star International vendor HAWKING 0x0e66 Hawking Technologies vendor QUALCOMM 0x1004 Qualcomm vendor MOTOROLA 0x1063 Motorola vendor PLX 0x10b5 PLX vendor ASANTE 0x10bd Asante vendor JRC 0x1145 Japan Radio Company vendor ACERCM 0x1189 Acer Communications & Multimedia Inc. vendor BELKIN2 0x1293 Belkin Components vendor MOBILITY 0x1342 Mobility vendor SHARK 0x13d2 Shark vendor SILICONPORTALS 0x1527 Silicon Portals vendor SOHOWARE 0x15e8 SOHOware vendor UMAX 0x1606 UMAX Data Systems vendor INSIDEOUT 0x1608 Inside Out Networks vendor ENTREGA 0x1645 Entrega vendor ACTIONTEC 0x1668 Actiontec Electronics vendor DLINK 0x2001 D-Link vendor VIDZMEDIA 0x3275 VidzMedia Pte Ltd vendor DAISY 0x3579 Daisy Technology vendor DELL 0x413c Dell vendor INTEL 0x8086 Intel vendor HP2 0xf003 Hewlett Packard /* * List of known products. Grouped by vendor. */ /* 3Com products */ product 3COM HOMECONN 0x009d HomeConnect USB Camera product 3COM 3CREB96 0x00a0 Bluetooth USB dongle product 3COM 3C19250 0x03E8 3C19250 Ethernet adapter product 3COM USR56K 0x3021 U.S.Robotics 56000 Voice Faxmodem Pro product 3COM 3C460 0x11f8 HomeConnect 3C460 product 3COM 3C460B 0x4601 HomeConnect 3C460B product 3COMUSR OFFICECONN 0x0082 3Com OfficeConnect Analog Modem product 3COMUSR USRISDN 0x008f 3Com U.S. Robotics Pro ISDN TA product 3COMUSR HOMECONN 0x009d 3Com HomeConnect camera product 3COMUSR USR56K 0x3021 U.S.Robotics 56000 Voice Faxmodem Pro /* AboCom products */ product ABOCOM XX1 0x110c XX1 product ABOCOM XX2 0x200c XX2 product ABOCOM URE450 0x4000 URE450 Ethernet Adapter product ABOCOM UFE1000 0x4002 UFE1000 Fast Ethernet Adapter product ABOCOM DSB650TX_PNA 0x4003 1/10/100 ethernet adapter product ABOCOM XX4 0x4004 XX4 product ABOCOM XX5 0x4007 XX5 product ABOCOM XX6 0x400b XX6 product ABOCOM XX7 0x400c XX7 product ABOCOM XX8 0x4102 XX8 product ABOCOM XX9 0x4104 XX9 product ABOCOM XX10 0xabc1 XX10 /* Accton products */ product ACCTON USB320_EC 0x1046 USB320-EC Ethernet Adapter product ACCTON SS1001 0x5046 SpeedStream Ethernet Adapter /* Acer Peripherals, Inc. products */ product ACERP ACERSCAN_C310U 0x12a6 Acerscan C310U product ACERP ACERSCAN_320U 0x2022 Acerscan 320U product ACERP ACERSCAN_640U 0x2040 Acerscan 640U product ACERP ACERSCAN_620U 0x2060 Acerscan 620U product ACERP AWL300 0x9000 AWL300 Wireless adapter /* ActiveWire, Inc. products */ product ACTIVEWIRE IOBOARD 0x0100 I/O Board product ACTIVEWIRE IOBOARD_FW1 0x0101 I/O Board, rev. 1 firmware /* Actiontec, Inc. products */ product ACTIONTEC UAT1 0x7605 UAT1 Wireless Ethernet adapter /* ADMtek products */ product ADMTEK PEGASUS 0x0986 AN986 USB Ethernet adapter product ADMTEK PEGASUSII 0x8511 AN8511 USB Ethernet adapter product ADMTEK PEGASUSII_2 0x8513 AN8513 USB Ethernet adapter /* ADS products */ product ADS UBS10BT 0x0008 UBS-10BT Ethernet adapter /* Agate Technologies products */ product AGATE QDRIVE 0x0378 Q-Drive /* AGFA products */ product AGFA SNAPSCAN1212U 0x0001 SnapScan 1212U product AGFA SNAPSCAN1236U 0x0002 SnapScan 1236U product AGFA SNAPSCANTOUCH 0x0100 SnapScan Touch product AGFA SNAPSCAN1212U2 0x2061 SnapScan 1212U product AGFA SNAPSCANE40 0x208d SnapScan e40 product AGFA SNAPSCANE50 0x208f SnapScan e50 product AGFA SNAPSCANE20 0x2091 SnapScan e20 product AGFA SNAPSCANE25 0x2095 SnapScan e25 product AGFA SNAPSCANE26 0x2097 SnapScan e26 product AGFA SNAPSCANE52 0x20fd SnapScan e52 /* AKS products */ product AKS USBHASP 0x0001 USB-HASP 0.06 /* Alcor Micro, Inc. products */ product ALCOR2 KBD_HUB 0x2802 Kbd Hub product ALCOR MA_KBD_HUB 0x9213 MacAlly Kbd Hub product ALCOR AU9814 0x9215 AU9814 Hub product ALCOR SM_KBD 0x9410 MicroConnectors/StrongMan Keyboard product ALCOR NEC_KBD_HUB 0x9472 NEC Kbd Hub /* Altec Lansing products */ product ALTEC ADA70 0x0070 ADA70 Speakers product ALTEC ASC495 0xff05 ASC495 Speakers /* American Power Conversion products */ product APC UPSPRO500 0x0002 Back-UPS Pro 500 /* Anchor products */ product ANCHOR EZUSB 0x2131 EZUSB product ANCHOR EZLINK 0x2720 EZLINK /* AOX, Inc. products */ product AOX USB101 0x0008 USB ethernet controller engine /* Apple Computer products */ product APPLE OPTMOUSE 0x0302 Optical mouse product APPLE SPEAKERS 0x1101 Speakers /* Asahi Optical products */ product ASAHIOPTICAL OPTIO230 0x0004 Digital camera product ASAHIOPTICAL OPTIO330 0x0006 Digital camera /* ASIX Electronics products */ product ASIX AX88172 0x1720 USB 2.0 10/100 ethernet controller /* ATen products */ product ATEN UC1284 0x2001 Parallel printer adapter product ATEN UC10T 0x2002 10Mbps ethernet adapter product ATEN UC232A 0x2008 Serial adapter /* Atmel Comp. products */ product ATMEL UHB124 0x3301 UHB124 hub product ATMEL DWL120 0x7603 DWL-120 Wireless adapter product ATMEL BW002 0x7605 BW002 Wireless adapter product ATMEL AT76C505A 0x7614 AT76c505a Wireless adapter /* Avision products */ product AVISION 1200U 0x0268 1200U scanner /* Belkin products */ /*product BELKIN F5U111 0x???? F5U111 Ethernet adapter*/ product BELKIN2 F5U002 0x0002 F5U002 Parallel printer adapter product BELKIN USB2LAN 0x0121 USB to LAN Converter product BELKIN F5U103 0x0103 F5U103 Serial adapter product BELKIN F5U109 0x0109 F5U109 Serial adapter product BELKIN F5U120 0x1203 F5U120-PC Hub product BELKIN F5U208 0x0208 F5U208 VideoBus II /* Billionton products */ product BILLIONTON USB100 0x0986 USB100N 10/100 FastEthernet Adapter product BILLIONTON USBLP100 0x0987 USB100LP product BILLIONTON USBEL100 0x0988 USB100EL product BILLIONTON USBE100 0x8511 USBE100 /* Brother Industries products */ product BROTHER HL1050 0x0002 HL-1050 laser printer /* Behavior Technology Computer products */ product BTC BTC7932 0x6782 Keyboard with mouse port /* Broadcom products */ product BROADCOM BCM2033 0x2033 BCM2033 Bluetooth USB dongle /* Canon, Inc. products */ product CANON N656U 0x2206 CanoScan N656U product CANON N1220U 0x2207 CanoScan N1220U product CANON N676U 0x220d CanoScan N676U product CANON N1240U 0x220e CanoScan N1240U product CANON S10 0x3041 PowerShot S10 product CANON S100 0x3045 PowerShot S100 product CANON S200 0x3065 PowerShot S200 /* CATC products */ product CATC NETMATE 0x000a Netmate ethernet adapter product CATC NETMATE2 0x000c Netmate2 ethernet adapter product CATC CHIEF 0x000d USB Chief Bus & Protocol Analyzer product CATC ANDROMEDA 0x1237 Andromeda hub /* CASIO products */ product CASIO NAMELAND 0x4001 CASIO Nameland EZ-USB /* Cherry products */ product CHERRY MY3000KBD 0x0001 My3000 keyboard product CHERRY MY3000HUB 0x0003 My3000 hub product CHERRY CYBOARD 0x0004 CyBoard Keyboard /* Chic Technology products */ product CHIC MOUSE1 0x0001 mouse product CHIC CYPRESS 0x0003 Cypress USB Mouse /* Chicony products */ product CHICONY KB8933 0x0001 KB-8933 keyboard /* Compaq products */ product COMPAQ PJB100 0x504a Personal Jukebox PJB100 /* Connectix products */ product CONNECTIX QUICKCAM 0x0001 QuickCam /* Corega products */ product COREGA ETHER_USB_T 0x0001 Ether USB-T product COREGA FETHER_USB_TX 0x0004 FEther USB-TX product COREGA FETHER_USB_TXS 0x000d FEther USB-TXS product COREGA FETHER_USB_TXC 0x9601 FEther USB-TXC /* Creative products */ product CREATIVE NOMAD_II 0x1002 Nomad II MP3 player /* Crystalfontz products */ product FTDI CFA_631 0xfc0c Crystalfontz CFA-631 USB LCD product FTDI CFA_632 0xfc08 Crystalfontz CFA-632 USB LCD product FTDI CFA_633 0xfc0b Crystalfontz CFA-633 USB LCD product FTDI CFA_634 0xfc09 Crystalfontz CFA-634 USB LCD /* Cambridge Silicon Radio Ltd. products */ product CSR BT_DONGLE 0x0001 Bluetooth USB dongle product CSR CSRDFU 0xffff USB Bluetooth Device in DFU State /* CTX products */ product CTX EX1300 0x9999 Ex1300 hub /* Cypress Semiconductor products */ product CYPRESS MOUSE 0x0001 mouse product CYPRESS THERMO 0x0002 thermometer product CYPRESS FMRADIO 0x1002 FM Radio product CYPRESS SLIM_HUB 0x6560 Slim Hub /* Daisy Technology products */ product DAISY DMC 0x6901 USB MultiMedia Reader /* Dallas Semiconductor products */ product DALLAS J6502 0x4201 J-6502 speakers /* Dell products */ product DELL BC02 0x8000 Dell BC02 Bluetooth USB Adapter /* Diamond products */ product DIAMOND RIO500USB 0x0001 Rio 500 USB /* Digi International products */ product DIGI ACCELEPORT2 0x0002 AccelePort USB 2 product DIGI ACCELEPORT4 0x0004 AccelePort USB 4 product DIGI ACCELEPORT8 0x0008 AccelePort USB 8 /* D-Link products */ /*product DLINK DSBS25 0x0100 DSB-S25 serial adapter*/ product DLINK DUBE100 0x1a00 10/100 ethernet adapter product DLINK DSB650TX4 0x200c 10/100 ethernet adapter product DLINK DSB650C 0x4000 10Mbps ethernet adapter product DLINK DSB650TX1 0x4001 10/100 ethernet adapter product DLINK DSB650TX 0x4002 10/100 ethernet adapter product DLINK DSB650TX_PNA 0x4003 1/10/100 ethernet adapter product DLINK DSB650TX3 0x400b 10/100 ethernet adapter product DLINK DSB650TX2 0x4102 10/100 ethernet adapter product DLINK DSB650 0xabc1 10/100 ethernet adapter /* EIZO products */ product EIZO HUB 0x0000 hub product EIZO MONITOR 0x0001 monitor /* Elecom products */ product ELECOM MOUSE29UO 0x0002 mouse 29UO product ELECOM LDUSBTX0 0x200c LD-USB/TX product ELECOM LDUSBTX1 0x4002 LD-USB/TX product ELECOM LDUSBLTX 0x4005 LD-USBL/TX product ELECOM LDUSBTX2 0x400b LD-USB/TX product ELECOM UCSGT 0x5003 UC-SGT product ELECOM LDUSBTX3 0xabc1 LD-USB/TX /* Elsa products */ product ELSA MODEM1 0x2265 ELSA Modem Board product ELSA USB2ETHERNET 0x3000 Microlink USB2Ethernet /* EMS products */ product EMS DUAL_SHOOTER 0x0003 PSX gun controller converter /* Entrega products */ product ENTREGA 1S 0x0001 1S serial connector product ENTREGA 2S 0x0002 2S serial connector product ENTREGA 1S25 0x0003 1S25 serial connector product ENTREGA 4S 0x0004 4S serial connector product ENTREGA E45 0x0005 E45 Ethernet adapter product ENTREGA CENTRONICS 0x0006 Centronics connector product ENTREGA 1S9 0x0093 1S9 serial connector product ENTREGA EZUSB 0x8000 EZ-USB /*product ENTREGA SERIAL 0x8001 DB25 Serial connector*/ product ENTREGA 2U4S 0x8004 2U4S serial connector/usb hub /*product ENTREGA SERIAL_DB9 0x8093 DB9 Serial connector*/ /* Epson products */ product EPSON PRINTER1 0x0001 USB Printer product EPSON PRINTER2 0x0002 ISD USB Smart Cable for Mac product EPSON PRINTER3 0x0003 ISD USB Smart Cable product EPSON PRINTER5 0x0005 USB Printer product EPSON 636 0x0101 Perfection 636U / 636Photo scanner product EPSON 610 0x0103 Perfection 610 scanner product EPSON 1200 0x0104 Perfection 1200U / 1200Photo scanner product EPSON 1600 0x0107 Expression 1600 scanner product EPSON 1640 0x010a Perfection 1640SU scanner product EPSON 1240 0x010b Perfection 1240U / 1240Photo scanner product EPSON 640U 0x010c Perfection 640U scanner product EPSON 1250 0x010f Perfection 1250U / 1250Photo scanner product EPSON 1650 0x0110 Perfection 1650 scanner product EPSON GT9700F 0x0112 GT-9700F scanner product EPSON GT9300UF 0x011b GT-9300UF scanner product EPSON 3200 0x011c Perfection 3200 scanner product EPSON 1260 0x011d Perfection 1260 scanner product EPSON 1660 0x011e Perfection 1660 scanner product EPSON 1670 0x011f Perfection 1670 scanner /* e-TEK Labs products */ product ETEK 1COM 0x8007 Serial port /* Extended Systems products */ product EXTENDED XTNDACCESS 0x0100 XTNDAccess IrDA /* GoHubs products */ product GOHUBS GOCOM232 0x1001 GoCOM232 Serial converter /* Gravis products */ product GRAVIS GAMEPADPRO 0x4001 GamePad Pro /* GREENHOUSE products */ product GREENHOUSE KANA21 0x0001 CF-writer with Portable MP3 Player /* Griffin Technology */ product GRIFFIN IMATE 0x0405 iMate, ADB adapter /* Freecom products */ product FREECOM DVD 0xfc01 Connector for DVD drive /* Future Technology Devices products */ product FTDI SERIAL_8U100AX 0x8372 8U100AX Serial converter product FTDI SERIAL_8U232AM 0x6001 8U232AM Serial converter /* Fuji photo products */ product FUJIPHOTO MASS0100 0x0100 Mass Storage /* Fujitsu protducts */ product FUJITSU AH_F401U 0x105b AH-F401U Air H device /* Qualcomm products */ product QUALCOMM CDMA_MSM 0x6000 CDMA Technologies MSM phone /* General Instruments (Motorola) products */ product GENERALINSTMNTS SB5100 0x5100 SURFboard SB5100 Cable modem /* Genesys Logic products */ product GENESYS GL650 0x0604 GL650 Hub product GENESYS GL641USB 0x0700 GL641USB CompactFlash Card Reader product GENESYS GL641USB2IDE_2 0x0701 GL641USB USB-IDE Bridge No 2 product GENESYS GL641USB2IDE 0x0702 GL641USB USB-IDE Bridge /* HAL Corporation products */ product HAL IMR001 0x0011 Crossam2+USB IR commander /* Hagiwara products */ product HAGIWARA FGSM 0x0002 FlashGate SmartMedia Card Reader product HAGIWARA FGCF 0x0003 FlashGate CompactFlash Card Reader product HAGIWARA FG 0x0005 FlashGate /* Handspring, Inc. */ product HANDSPRING VISOR 0x0100 Handspring Visor product HANDSPRING TREO 0x0200 Handspring Treo product HANDSPRING TREO600 0x0300 Handspring Treo 600 /* Hauppauge Computer Works */ product HAUPPAUGE WINTV_USB_FM 0x4d12 WinTV USB FM /* Hawking Technologies products */ product HAWKING UF100 0x400c 10/100 USB Ethernet /* Hitachi, Ltd. products */ product HITACHI DVDCAM_USB 0x001e DVDCAM USB HS Interface /* HP products */ product HP 895C 0x0004 DeskJet 895C product HP 4100C 0x0101 Scanjet 4100C product HP S20 0x0102 Photosmart S20 product HP 880C 0x0104 DeskJet 880C product HP 4200C 0x0105 ScanJet 4200C product HP CDWRITERPLUS 0x0107 CD-Writer Plus product HP KBDHUB 0x010c Multimedia Keyboard Hub product HP 6200C 0x0201 ScanJet 6200C product HP S20b 0x0202 PhotoSmart S20 product HP 815C 0x0204 DeskJet 815C product HP 3300C 0x0205 ScanJet 3300C product HP CDW8200 0x0207 CD-Writer Plus 8200e product HP 1220C 0x0212 DeskJet 1220C product HP 810C 0x0304 DeskJet 810C/812C product HP 4300C 0x0305 Scanjet 4300C product HP G85XI 0x0311 OfficeJet G85xi product HP 1200 0x0317 LaserJet 1200 product HP 5200C 0x0401 Scanjet 5200C product HP 830C 0x0404 DeskJet 830C product HP 3400CSE 0x0405 ScanJet 3400cse product HP 6300C 0x0601 Scanjet 6300C product HP 840C 0x0604 DeskJet 840c product HP 2200C 0x0605 ScanJet 2200C product HP 5300C 0x0701 Scanjet 5300C product HP 4400C 0x0705 Scanjet 4400C product HP 970CSE 0x1004 Deskjet 970Cse product HP 5400C 0x1005 Scanjet 5400C product HP 930C 0x1204 DeskJet 930c product HP P2000U 0x1801 Inkjet P-2000U product HP 640C 0x2004 DeskJet 640c product HP P1100 0x3102 Photosmart P1100 product HP HN210E 0x811c Ethernet HN210E /* HP products */ product HP2 C500 0x6002 PhotoSmart C500 /* IBM Corporation */ product IBM USBCDROMDRIVE 0x4427 USB CD-ROM Drive /* Inside Out Networks products */ product INSIDEOUT EDGEPORT4 0x0001 EdgePort/4 serial ports /* In-System products */ product INSYSTEM F5U002 0x0002 Parallel printer adapter product INSYSTEM ATAPI 0x0031 ATAPI adapter product INSYSTEM ISD110 0x0200 IDE adapter ISD110 product INSYSTEM ISD105 0x0202 IDE adapter ISD105 product INSYSTEM USBCABLE 0x081a USB cable /* Intel products */ product INTEL EASYPC_CAMERA 0x0110 Easy PC Camera product INTEL TESTBOARD 0x9890 82930 test board /* Intersil products */ product INTERSIL PRISM_2X 0x3642 Prism2.x or Atmel WLAN /* I/O DATA products */ product IODATA USBETT 0x0901 USB ETT product IODATA USBETTX 0x0904 USB ETTX product IODATA USBETTXS 0x0913 USB ETTX product IODATA USBRSAQ 0x0a03 USB serial adapter USB-RSAQ1 product IODATA IU_CD2 0x0204 DVD Multi-plus unit iU-CD2 product IODATA DVR_UEH8 0x0206 DVD Multi-plus unit DVR-UEH8 /* Iomega products */ product IOMEGA ZIP100 0x0001 Zip 100 product IOMEGA ZIP250 0x0030 Zip 250 /* JVC products */ product JVC GR_DX95 0x000a GR-DX95 /* JRC products */ product JRC AH_J3001V_J3002V 0x0001 AirH\" PHONE AH-J3001V/J3002V /* Kawasaki products */ product KLSI DUH3E10BT 0x0008 USB ethernet controller engine product KLSI DUH3E10BTN 0x0009 USB ethernet controller engine /* Kawatsu products */ product KAWATSU MH4000P 0x0003 MiniHub 4000P /* Keisokugiken Corp. products */ product KEISOKUGIKEN USBDAQ 0x0068 HKS-0200 USBDAQ /* Kawasaki products */ product KLSI DUH3E10BT 0x0008 10BT Ethernet adapter, in the DU-H3E /* Kensington products */ product KENSINGTON ORBIT 0x1003 Orbit USB/PS2 trackball product KENSINGTON TURBOBALL 0x1005 TurboBall /* Keyspan products */ product KEYSPAN USA28 0x0101 USA-28 serial adapter product KEYSPAN USA28X 0x0102 USA-28X serial adapter product KEYSPAN USA19 0x0103 USA-19 serial adapter product KEYSPAN USA18X 0x0105 USA-18X serial adapter product KEYSPAN USA19W 0x0106 USA-19W serial adapter product KEYSPAN USA49W 0x0109 USA-49W serial adapter product KEYSPAN USA19QW 0x0118 USA-19QW serial adapter /* Kingston products */ product KINGSTON KNU101TX 0x000a KNU101TX USB Ethernet /* Kodak products */ product KODAK DC220 0x0100 Digital Science DC220 product KODAK DC260 0x0110 Digital Science DC260 product KODAK DC265 0x0111 Digital Science DC265 product KODAK DC290 0x0112 Digital Science DC290 product KODAK DC240 0x0120 Digital Science DC240 product KODAK DC280 0x0130 Digital Science DC280 /* Konica Corp. Products */ product KONICA CAMERA 0x0720 Digital Color Camera /* KYE products */ product KYE NICHE 0x0001 Niche mouse product KYE NETSCROLL 0x0003 Genius NetScroll mouse product KYE FLIGHT2000 0x1004 Flight 2000 joystick product KYE VIVIDPRO 0x2001 ColorPage Vivid-Pro scanner /* Kyocera products */ product KYOCERA AHK3001V 0x0203 AH-K3001V /* LaCie products */ product LACIE HD 0xa601 Hard Disk product LACIE CDRW 0xa602 CD R/W /* Lexar products */ product LEXAR JUMPSHOT 0x0001 jumpSHOT CompactFlash Reader /* Lexmark products */ product LEXMARK S2450 0x0009 Optra S 2450 /* Linksys products */ product LINKSYS MAUSB2 0x0105 Camedia MAUSB-2 product LINKSYS USB10TX1 0x200c USB10TX product LINKSYS USB10T 0x2202 USB10T Ethernet product LINKSYS USB100TX 0x2203 USB100TX Ethernet product LINKSYS USB100H1 0x2204 USB100H1 Ethernet/HPNA product LINKSYS USB10TA 0x2206 USB10TA Ethernet product LINKSYS USB10TX2 0x400b USB10TX product LINKSYS2 WUSB11 0x2219 WUSB11 Wireless adapter product LINKSYS2 USB200M 0x2226 USB 2.0 10/100 ethernet controller /* Logitech products */ product LOGITECH M2452 0x0203 M2452 keyboard product LOGITECH M4848 0x0301 M4848 mouse product LOGITECH PAGESCAN 0x040f PageScan product LOGITECH QUICKCAMWEB 0x0801 QuickCam Web product LOGITECH QUICKCAMPRO 0x0810 QuickCam Pro product LOGITECH QUICKCAMEXP 0x0840 QuickCam Express product LOGITECH QUICKCAM 0x0850 QuickCam product LOGITECH N43 0xc000 N43 product LOGITECH N48 0xc001 N48 mouse product LOGITECH MBA47 0xc002 M-BA47 mouse product LOGITECH WMMOUSE 0xc004 WingMan Gaming Mouse product LOGITECH BD58 0xc00c BD58 mouse product LOGITECH UN58A 0xc030 iFeel Mouse product LOGITECH BB13 0xc401 USB-PS/2 Trackball product LOGITECH WMPAD 0xc208 WingMan GamePad Extreme product LOGITECH WMRPAD 0xc20a WingMan RumblePad product LOGITECH WMJOY 0xc281 WingMan Force joystick product LOGITECH RK53 0xc501 Cordless mouse product LOGITECH RB6 0xc503 Cordless keyboard product LOGITECH MX700 0xc506 Cordless optical mouse product LOGITECH QUICKCAMPRO2 0xd001 QuickCam Pro /* Logitec Corp. products */ product LOGITEC LDR_H443SU2 0x0033 DVD Multi-plus unit LDR-H443SU2 product LOGITEC LDR_H443U2 0x00b3 DVD Multi-plus unit LDR-H443U2 /* Lucent products */ product LUCENT EVALKIT 0x1001 USS-720 evaluation kit /* Luwen products */ product LUWEN EASYDISK 0x0005 EasyDisc /* Macally products */ product MACALLY MOUSE1 0x0101 mouse /* Matrix Orbital products */ product FTDI USBSERIAL 0xfa00 Matrix Orbital USB Serial product FTDI MX2_3 0xfa01 Matrix Orbital MX2 or MX3 product FTDI MX4_5 0xfa02 Matrix Orbital MX4 or MX5 product FTDI LK202 0xfa03 Matrix Orbital VK/LK202 Family product FTDI LK204 0xfa04 Matrix Orbital VK/LK204 Family /* MCT Corp. */ product MCT HUB0100 0x0100 Hub product MCT DU_H3SP_USB232 0x0200 D-Link DU-H3SP USB BAY Hub product MCT USB232 0x0210 USB-232 Interface product MCT SITECOM_USB232 0x0230 Sitecom USB-232 Products /* Melco, Inc products */ product MELCO LUATX1 0x0001 LUA-TX Ethernet product MELCO LUATX5 0x0005 LUA-TX Ethernet product MELCO LUA2TX5 0x0009 LUA2-TX Ethernet product MELCO LUAKTX 0x0012 LUA-KTX Ethernet product MELCO DUBPXXG 0x001c USB-IDE Bridge: DUB-PxxG product MELCO LUAU2KTX 0x003d LUA-U2-KTX Ethernet /* Metricom products */ product METRICOM RICOCHET_GS 0x0001 Ricochet GS /* Microsoft products */ product MICROSOFT SIDEPREC 0x0008 SideWinder Precision Pro product MICROSOFT INTELLIMOUSE 0x0009 IntelliMouse product MICROSOFT NATURALKBD 0x000b Natural Keyboard Elite product MICROSOFT DDS80 0x0014 Digital Sound System 80 product MICROSOFT SIDEWINDER 0x001a Sidewinder Precision Racing Wheel product MICROSOFT INETPRO 0x001c Internet Keyboard Pro product MICROSOFT INTELLIEYE 0x0025 IntelliEye mouse product MICROSOFT INETPRO2 0x002b Internet Keyboard Pro product MICROSOFT MN110 0x007a 10/100 USB NIC /* Microtech products */ product MICROTECH SCSIDB25 0x0004 USB-SCSI-DB25 product MICROTECH SCSIHD50 0x0005 USB-SCSI-HD50 product MICROTECH DPCM 0x0006 USB CameraMate product MICROTECH FREECOM 0xfc01 Freecom USB-IDE /* Microtek products */ product MICROTEK 336CX 0x0094 Phantom 336CX - C3 scanner product MICROTEK X6U 0x0099 ScanMaker X6 - X6U product MICROTEK C6 0x009a Phantom C6 scanner product MICROTEK 336CX2 0x00a0 Phantom 336CX - C3 scanner product MICROTEK V6USL 0x00a3 ScanMaker V6USL product MICROTEK V6USL2 0x80a3 ScanMaker V6USL product MICROTEK V6UL 0x80ac ScanMaker V6UL /* Midiman products */ product MIDIMAN MIDISPORT2X2 0x1001 Midisport 2x2 /* Minolta Co., Ltd. */ product MINOLTA 2300 0x4001 Dimage 2300 product MINOLTA S304 0x4007 Dimage S304 product MINOLTA X 0x4009 Dimage X product MINOLTA 5400 0x400e Dimage 5400 /* Micro Star International products */ product MSI BT_DONGLE 0x1967 Bluetooth USB dongle /* Mitsumi products */ product MITSUMI CDRRW 0x0000 CD-R/RW Drive product MITSUMI BT_DONGLE 0x641f Bluetooth USB dongle /* Motorola products */ product MOTOROLA MC141555 0x1555 MC141555 hub controller product MOTOROLA SB4100 0x4100 SB4100 USB Cable Modem /* MultiTech products */ product MULTITECH ATLAS 0xf101 MT5634ZBA-USB modem /* Mustek products */ product MUSTEK 1200CU 0x0001 1200 CU scanner product MUSTEK 600CU 0x0002 600 CU scanner product MUSTEK 1200USB 0x0003 1200 USB scanner product MUSTEK 1200UB 0x0006 1200 UB scanner product MUSTEK 1200USBPLUS 0x0007 1200 USB Plus scanner product MUSTEK 1200CUPLUS 0x0008 1200 CU Plus scanner product MUSTEK BEARPAW1200F 0x0010 BearPaw 1200F scanner product MUSTEK BEARPAW1200TA 0x021e BearPaw 1200TA scanner product MUSTEK 600USB 0x0873 600 USB scanner product MUSTEK MDC800 0xa800 MDC-800 digital camera /* M-Systems products */ product MSYSTEMS DISKONKEY 0x0010 DiskOnKey product MSYSTEMS DISKONKEY2 0x0011 DiskOnKey /* National Semiconductor */ product NATIONAL BEARPAW1200 0x1000 BearPaw 1200 product NATIONAL BEARPAW2400 0x1001 BearPaw 2400 /* NEC products */ product NEC HUB 0x55aa hub product NEC HUB_B 0x55ab hub /* NEODIO products */ +product NEODIO ND3260 0x3260 8-in-1 Multi-format Flash Controller product NEODIO ND5010 0x5010 Multi-format Flash Controller /* NetChip Technology Products */ product NETCHIP TURBOCONNECT 0x1080 Turbo-Connect /* Netgear products */ product NETGEAR EA101 0x1001 Ethernet adapter product NETGEAR FA120 0x1040 USB 2.0 Ethernet adapter /* Nikon products */ product NIKON E990 0x0102 Digital Camera E990 /* Olympus products */ product OLYMPUS C1 0x0102 C-1 Digital Camera product OLYMPUS C700 0x0105 C-700 Ultra Zoom /* OmniVision Technologies, Inc. products */ product OMNIVISION OV511 0x0511 OV511 Camera product OMNIVISION OV511PLUS 0xa511 OV511+ Camera /* OnSpec Electronic, Inc. */ product ONSPEC UCF100 0xa400 FlashLink UCF-100 CompactFlash Reader /* Palm Computing, Inc. product */ product PALM SERIAL 0x0080 USB Serial Adaptor product PALM M500 0x0001 Palm m500 product PALM M505 0x0002 Palm m505 product PALM M515 0x0003 Palm m515 product PALM I705 0x0020 Palm i705 product PALM TUNGSTEN_Z 0x0031 Palm Tungsten Z product PALM M125 0x0040 Palm m125 product PALM M130 0x0050 Palm m130 product PALM TUNGSTEN_T 0x0060 Palm Tungsten T product PALM ZIRE31 0x0061 Palm Zire 31 product PALM ZIRE 0x0070 Palm Zire /* Panasonic products */ product PANASONIC KXLRW32AN 0x0d09 CD-R Drive KXL-RW32AN product PANASONIC KXLCB20AN 0x0d0a CD-R Drive KXL-CB20AN product PANASONIC KXLCB35AN 0x0d0e DVD-ROM & CD-R/RW product PANASONIC SDCAAE 0x1b00 MultiMediaCard Adapter /* Peracom products */ product PERACOM SERIAL1 0x0001 Serial Converter product PERACOM ENET 0x0002 Ethernet adapter product PERACOM ENET3 0x0003 At Home Ethernet Adapter product PERACOM ENET2 0x0005 Ethernet adapter /* Philips products */ product PHILIPS DSS350 0x0101 DSS 350 Digital Speaker System product PHILIPS DSS 0x0104 DSS XXX Digital Speaker System product PHILIPS HUB 0x0201 hub product PHILIPS PCA646VC 0x0303 PCA646VC PC Camera product PHILIPS PCVC680K 0x0308 PCVC680K Vesta Pro PC Camera product PHILIPS DSS150 0x0471 DSS 150 Digital Speaker System product PHILIPS DIVAUSB 0x1801 DIVA USB mp3 player /* Philips Semiconductor products */ product PHILIPSSEMI HUB1122 0x1122 hub /* P.I. Engineering products */ product PIENGINEERING PS2USB 0x020b PS2 to Mac USB Adapter /* Plextor Corp. */ product PLEXTOR 40_12_40U 0x0011 PlexWriter 40/12/40U /* PLX products */ product PLX TESTBOARD 0x9060 test board /* PNY products */ product PNY ATTACHE 0x1300 USB 2.0 Flash Drive /* Primax products */ product PRIMAX G2X300 0x0300 G2-200 scanner product PRIMAX G2E300 0x0301 G2E-300 scanner product PRIMAX G2300 0x0302 G2-300 scanner product PRIMAX G2E3002 0x0303 G2E-300 scanner product PRIMAX 9600 0x0340 Colorado USB 9600 scanner product PRIMAX 600U 0x0341 Colorado 600u scanner product PRIMAX 6200 0x0345 Visioneer 6200 scanner product PRIMAX 19200 0x0360 Colorado USB 19200 scanner product PRIMAX 1200U 0x0361 Colorado 1200u scanner product PRIMAX G600 0x0380 G2-600 scanner product PRIMAX 636I 0x0381 ReadyScan 636i product PRIMAX G2600 0x0382 G2-600 scanner product PRIMAX G2E600 0x0383 G2E-600 scanner product PRIMAX COMFORT 0x4d01 Comfort product PRIMAX MOUSEINABOX 0x4d02 Mouse-in-a-Box product PRIMAX PCGAUMS1 0x4d04 Sony PCGA-UMS1 /* Prolific products */ product PROLIFIC PL2301 0x0000 PL2301 Host-Host interface product PROLIFIC PL2302 0x0001 PL2302 Host-Host interface product PROLIFIC RSAQ2 0x04bb PL2303 Serial adapter (IODATA USB-RSAQ2) product PROLIFIC PL2303 0x2303 PL2303 Serial adapter (ATEN/IOGEAR UC232A) product PROLIFIC PL2305 0x2305 Parallel printer adapter product PROLIFIC ATAPI4 0x2307 ATAPI-4 Bridge Controller /* Putercom products */ product PUTERCOM UPA100 0x047e USB-1284 BRIDGE /* Qtronix products */ product QTRONIX 980N 0x2011 Scorpion-980N keyboard /* Quickshot products */ product QUICKSHOT STRIKEPAD 0x6238 USB StrikePad /* Rainbow Technologies products */ product RAINBOW IKEY2000 0x1200 i-Key 2000 /* ReakTek products */ product REALTEK USBKR100 0x8150 USBKR100 USB Ethernet (GREEN HOUSE) /* Roland products */ product ROLAND UM1 0x0009 UM-1 MIDI I/F product ROLAND UM880N 0x0014 EDIROL UM-880 MIDI I/F (native) product ROLAND UM880G 0x0015 EDIROL UM-880 MIDI I/F (generic) /* Rockfire products */ product ROCKFIRE GAMEPAD 0x2033 gamepad 203USB /* RATOC Systems products */ product RATOC REXUSB60 0xb000 USB serial adapter REX-USB60 /* Samsung products */ product SAMSUNG ML6060 0x3008 ML-6060 laser printer /* SanDisk products */ product SANDISK SDDR05A 0x0001 ImageMate SDDR-05a product SANDISK SDDR05 0x0005 ImageMate SDDR-05 product SANDISK SDDR31 0x0002 ImageMate SDDR-31 product SANDISK SDDR12 0x0100 ImageMate SDDR-12 product SANDISK SDDR09 0x0200 ImageMate SDDR-09 product SANDISK SDDR75 0x0810 ImageMate SDDR-75 /* Sanyo Electric products */ product SANYO SCP4900 0x0701 Sanyo SCP-4900 USB Phone /* ScanLogic products */ product SCANLOGIC SL11R 0x0002 SL11R IDE Adapter product SCANLOGIC 336CX 0x0300 Phantom 336CX - C3 scanner /* Shuttle Technology products */ product SHUTTLE EUSB 0x0001 E-USB Bridge product SHUTTLE EUSCSI 0x0002 eUSCSI Bridge product SHUTTLE SDDR09 0x0003 ImageMate SDDR09 product SHUTTLE ZIOMMC 0x0006 eUSB MultiMediaCard Adapter product SHUTTLE HIFD 0x0007 Sony Hifd product SHUTTLE EUSBATAPI 0x0009 eUSB ATA/ATAPI Adapter product SHUTTLE CF 0x000a eUSB CompactFlash Adapter product SHUTTLE EUSCSI_B 0x000b eUSCSI Bridge product SHUTTLE EUSCSI_C 0x000c eUSCSI Bridge product SHUTTLE CDRW 0x0101 CD-RW Device product SHUTTLE EUSBORCA 0x0325 eUSB ORCA Quad Reader /* Siemens products */ product SIEMENS SPEEDSTREAM 0x1001 SpeedStream USB /* Sigmatel products */ product SIGMATEL I_BEAD100 0x8008 i-Bead 100 MP3 Player /* SIIG products */ product SIIG DIGIFILMREADER 0x0004 DigiFilm-Combo Reader /* Silicon Portals Inc. */ product SILICONPORTALS YAPPH_NF 0x0200 YAP Phone (no firmware) product SILICONPORTALS YAPPHONE 0x0201 YAP Phone /* Sirius Technologies products */ product SIRIUS ROADSTER 0x0001 NetComm Roadster II 56 USB /* SmartBridges products */ product SMARTBRIDGES SMARTLINK 0x0001 SmartLink USB ethernet adapter product SMARTBRIDGES SMARTNIC 0x0003 smartNIC 2 PnP Adapter /* SMC products */ product SMC 2102USB 0x0100 10Mbps ethernet adapter product SMC 2202USB 0x0200 10/100 ethernet adapter product SMC 2206USB 0x0201 EZ Connect USB Ethernet Adapter product SMC2 2020HUB 0x2020 USB Hub product SMC3 2662WUSB 0xa002 2662W-AR Wireless Adapter /* SOHOware products */ product SOHOWARE NUB100 0x9100 10/100 USB Ethernet /* SOLID YEAR products */ product SOLIDYEAR KEYBOARD 0x2101 Solid Year USB keyboard /* SONY products */ product SONY DSC 0x0010 DSC cameras product SONY MSACUS1 0x002d Memorystick MSAC-US1 product SONY MSC 0x0032 MSC memory stick slot product SONY CLIE_35 0x0038 Sony Clie v3.5 product SONY CLIE_40 0x0066 Sony Clie v4.0 product SONY CLIE_40_MS 0x006d Sony Clie v4.0 Memory Stick slot product SONY CLIE_S360 0x0095 Sony Clie s360 product SONY CLIE_41_MS 0x0099 Sony Clie v4.1 Memory Stick slot product SONY CLIE_41 0x009a Sony Clie v4.1 product SONY CLIE_NX60 0x00da Sony Clie nx60 /* SOURCENEXT products */ product SOURCENEXT KEIKAI8 0x039f KeikaiDenwa 8 product SOURCENEXT KEIKAI8_CHG 0x012e KeikaiDenwa 8 with charger /* STMicroelectronics products */ product STMICRO COMMUNICATOR 0x7554 USB Communicator /* STSN products */ product STSN STSN0001 0x0001 Internet Access Device /* SUN Corporation products */ product SUNTAC DS96L 0x0003 SUNTAC U-Cable type D2 product SUNTAC PS64P1 0x0005 SUNTAC U-Cable type P1 product SUNTAC VS10U 0x0009 SUNTAC Slipper U product SUNTAC IS96U 0x000a SUNTAC Ir-Trinity product SUNTAC AS64LX 0x000b SUNTAC U-Cable type A3 product SUNTAC AS144L4 0x0011 SUNTAC U-Cable type A4 /* Sun Microsystems products */ product SUN KEYBOARD 0x0005 Type 6 USB keyboard /* XXX The above is a North American PC style keyboard possibly */ product SUN MOUSE 0x0100 Type 6 USB mouse /* Supra products */ product DIAMOND2 SUPRAEXPRESS56K 0x07da Supra Express 56K modem product DIAMOND2 SUPRA2890 0x0b4a SupraMax 2890 56K Modem product DIAMOND2 RIO600USB 0x5001 Rio 600 USB product DIAMOND2 RIO800USB 0x5002 Rio 800 USB /* Taugagreining products */ product TAUGA CAMERAMATE 0x0005 CameraMate (DPCM_USB) /* TDK products */ product TDK UPA9664 0x0115 USB-PDC Adapter UPA9664 product TDK UCA1464 0x0116 USB-cdmaOne Adapter UCA1464 product TDK UHA6400 0x0117 USB-PHS Adapter UHA6400 product TDK UPA6400 0x0118 USB-PHS Adapter UPA6400 product TDK BT_DONGLE 0x0309 Bluetooth USB dongle /* TEAC products */ product TEAC FD05PUB 0x0000 FD-05PUB floppy /* Telex Communications products */ product TELEX MIC1 0x0001 Enhanced USB Microphone /* Texas Intel products */ product TI UTUSB41 0x1446 UT-USB41 hub product TI TUSB2046 0x2046 TUSB2046 hub /* Thrustmaster products */ product THRUST FUSION_PAD 0xa0a3 Fusion Digital Gamepad /* Toshiba Corporation products */ product TOSHIBA POCKETPC_E740 0x0706 PocketPC e740 /* Trek Technology products */ product TREK THUMBDRIVE 0x1111 ThumbDrive product TREK THUMBDRIVE_8MB 0x9988 ThumbDrive_8MB /* Ultima products */ product ULTIMA 1200UBPLUS 0x4002 1200 UB Plus scanner /* UMAX products */ product UMAX ASTRA1236U 0x0002 Astra 1236U Scanner product UMAX ASTRA1220U 0x0010 Astra 1220U Scanner product UMAX ASTRA2000U 0x0030 Astra 2000U Scanner product UMAX ASTRA2100U 0x0130 Astra 2100U Scanner product UMAX ASTRA2200U 0x0230 Astra 2200U Scanner product UMAX ASTRA3400 0x0060 Astra 3400 Scanner /* Universal Access products */ product UNIACCESS PANACHE 0x0101 Panache Surf USB ISDN Adapter /* VidzMedia products */ product VIDZMEDIA MONSTERTV 0x4fb1 MonsterTV P2H /* Vision products */ product VISION VC6452V002 0x0002 CPiA Camera /* Visioneer products */ product VISIONEER 7600 0x0211 OneTouch 7600 product VISIONEER 5300 0x0221 OneTouch 5300 product VISIONEER 3000 0x0224 Scanport 3000 product VISIONEER 6100 0x0231 OneTouch 6100 product VISIONEER 6200 0x0311 OneTouch 6200 product VISIONEER 8100 0x0321 OneTouch 8100 product VISIONEER 8600 0x0331 OneTouch 8600 /* Wacom products */ product WACOM CT0405U 0x0000 CT-0405-U Tablet product WACOM GRAPHIRE 0x0010 Graphire product WACOM INTUOSA5 0x0021 Intuos A5 product WACOM GD0912U 0x0022 Intuos 9x12 Graphics Tablet /* Xirlink products */ product XIRLINK PCCAM 0x8080 IBM PC Camera /* Y-E Data products */ product YEDATA FLASHBUSTERU 0x0000 Flashbuster-U /* Yamaha products */ product YAMAHA UX256 0x1000 UX256 MIDI I/F product YAMAHA UX96 0x1008 UX96 MIDI I/F product YAMAHA RTA54I 0x4000 NetVolante RTA54i Broadband&ISDN Router product YAMAHA RTA55I 0x4004 NetVolante RTA55i Broadband VoIP Router product YAMAHA RTW65B 0x4001 NetVolante RTW65b Broadband Wireless Router product YAMAHA RTW65I 0x4002 NetVolante RTW65i Broadband&ISDN Wireless Router /* Yano products */ product YANO U640MO 0x0101 U640MO-03 /* Zoom Telephonics, Inc. products */ product ZOOM 2986L 0x9700 2986L Fax modem /* ZyXEL Communication Co. products */ product ZYXEL OMNI56K 0x1500 Omni 56K Plus product ZYXEL 980N 0x2011 Scorpion-980N keyboard