📄 usb.c
字号:
"eUSB ATA/ATAPI Adapter", US_SC_8020, US_PR_CB, NULL, 0}, { 0x04e6, 0x000a, 0x0200, 0x0200, "Shuttle", "eUSB CompactFlash Adapter", US_SC_8020, US_PR_CB, NULL, 0}, { 0x04e6, 0x000B, 0x0100, 0x0100, "Shuttle", "eUSCSI Bridge", US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG }, { 0x04e6, 0x000C, 0x0100, 0x0100, "Shuttle", "eUSCSI Bridge", US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG }, { 0x04e6, 0x0101, 0x0200, 0x0200, "Shuttle", "CD-RW Device", US_SC_8020, US_PR_CB, NULL, 0}, { 0x054c, 0x0010, 0x0106, 0x0210, "Sony", "DSC-S30/S70/505V/F505", US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE }, { 0x054c, 0x002d, 0x0100, 0x0100, "Sony", "Memorystick MSAC-US1", US_SC_UFI, US_PR_CB, NULL, US_FL_SINGLE_LUN | US_FL_START_STOP }, { 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data", "Flashbuster-U", US_SC_UFI, US_PR_CB, NULL, US_FL_SINGLE_LUN}, { 0x057b, 0x0000, 0x0300, 0x9999, "Y-E Data", "Flashbuster-U", US_SC_UFI, US_PR_CBI, NULL, US_FL_SINGLE_LUN}, { 0x059f, 0xa601, 0x0200, 0x0200, "LaCie", "USB Hard Disk", US_SC_RBC, US_PR_CB, NULL, 0 }, { 0x05ab, 0x0031, 0x0100, 0x0100, "In-System", "USB/IDE Bridge (ATAPI ONLY!)", US_SC_8070, US_PR_BULK, NULL, 0 }, { 0x0644, 0x0000, 0x0100, 0x0100, "TEAC", "Floppy Drive", US_SC_UFI, US_PR_CB, NULL, 0 }, #ifdef CONFIG_USB_STORAGE_SDDR09 { 0x066b, 0x0105, 0x0100, 0x0100, "Olympus", "Camedia MAUSB-2", US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, US_FL_SINGLE_LUN | US_FL_START_STOP },#endif { 0x0693, 0x0002, 0x0100, 0x0100, "Hagiwara", "FlashGate SmartMedia", US_SC_SCSI, US_PR_BULK, NULL, 0 }, { 0x0693, 0x0005, 0x0100, 0x0100, "Hagiwara", "Flashgate", US_SC_SCSI, US_PR_BULK, NULL, 0 }, { 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk", "ImageMate SDDR-05a", US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN | US_FL_START_STOP}, { 0x0781, 0x0100, 0x0100, 0x0100, "Sandisk", "ImageMate SDDR-12", US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN },#ifdef CONFIG_USB_STORAGE_SDDR09 { 0x0781, 0x0200, 0x0100, 0x0208, "Sandisk", "ImageMate SDDR-09", US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, US_FL_SINGLE_LUN | US_FL_START_STOP },#endif { 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk", "ImageMate SDDR-31", US_SC_SCSI, US_PR_BULK, NULL, US_FL_IGNORE_SER}, { 0x07af, 0x0004, 0x0100, 0x0100, "Microtech", "USB-SCSI-DB25", US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG }, #ifdef CONFIG_USB_STORAGE_FREECOM { 0x07ab, 0xfc01, 0x0000, 0x9999, "Freecom", "USB-IDE", US_SC_QIC, US_PR_FREECOM, freecom_init, 0},#endif { 0x07af, 0x0005, 0x0100, 0x0100, "Microtech", "USB-SCSI-HD50", US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG }, #ifdef CONFIG_USB_STORAGE_DPCM { 0x07af, 0x0006, 0x0100, 0x0100, "Microtech", "CameraMate (DPCM_USB)", US_SC_SCSI, US_PR_DPCM_USB, NULL, US_FL_START_STOP },#endif { 0 }};/* Search our ususual device list, based on vendor/product combinations * to see if we can support this device. Returns a pointer to a structure * defining how we should support this device, or NULL if it's not in the * list */static struct us_unusual_dev* us_find_dev(u16 idVendor, u16 idProduct, u16 bcdDevice){ struct us_unusual_dev* ptr; US_DEBUGP("Searching unusual device list for (0x%x, 0x%x, 0x%x)...\n", idVendor, idProduct, bcdDevice); ptr = us_unusual_dev_list; while ((ptr->idVendor != 0x0000) && !((ptr->idVendor == idVendor) && (ptr->idProduct == idProduct) && (ptr->bcdDeviceMin <= bcdDevice) && (ptr->bcdDeviceMax >= bcdDevice))) ptr++; /* if the search ended because we hit the end record, we failed */ if (ptr->idVendor == 0x0000) { US_DEBUGP("-- did not find a matching device\n"); return NULL; } /* otherwise, we found one! */ US_DEBUGP("-- found matching device: %s %s\n", ptr->vendorName, ptr->productName); return ptr;}/* Set up the IRQ pipe and handler * Note that this function assumes that all the data in the us_data * strucuture is current. This includes the ep_int field, which gives us * the endpoint for the interrupt. * Returns non-zero on failure, zero on success */ static int usb_stor_allocate_irq(struct us_data *ss){ unsigned int pipe; int maxp; int result; US_DEBUGP("Allocating IRQ for CBI transport\n"); /* lock access to the data structure */ down(&(ss->irq_urb_sem)); /* allocate the URB */ ss->irq_urb = usb_alloc_urb(0); if (!ss->irq_urb) { up(&(ss->irq_urb_sem)); US_DEBUGP("couldn't allocate interrupt URB"); return 1; } /* calculate the pipe and max packet size */ pipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe)); if (maxp > sizeof(ss->irqbuf)) maxp = sizeof(ss->irqbuf); /* fill in the URB with our data */ FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf, maxp, usb_stor_CBI_irq, ss, ss->ep_int->bInterval); /* submit the URB for processing */ result = usb_submit_urb(ss->irq_urb); US_DEBUGP("usb_submit_urb() returns %d\n", result); if (result) { usb_free_urb(ss->irq_urb); up(&(ss->irq_urb_sem)); return 2; } /* unlock the data structure and return success */ up(&(ss->irq_urb_sem)); return 0;}/* Probe to see if a new device is actually a SCSI device */static void * storage_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id){ int i; char mf[USB_STOR_STRING_LEN]; /* manufacturer */ char prod[USB_STOR_STRING_LEN]; /* product */ char serial[USB_STOR_STRING_LEN]; /* serial number */ GUID(guid); /* Global Unique Identifier */ unsigned int flags; struct us_unusual_dev *unusual_dev; struct us_data *ss = NULL;#ifdef CONFIG_USB_STORAGE_SDDR09 int result;#endif /* these are temporary copies -- we test on these, then put them * in the us-data structure */ struct usb_endpoint_descriptor *ep_in = NULL; struct usb_endpoint_descriptor *ep_out = NULL; struct usb_endpoint_descriptor *ep_int = NULL; u8 subclass = 0; u8 protocol = 0; /* the altsettting 0 on the interface we're probing */ struct usb_interface_descriptor *altsetting = &(dev->actconfig->interface[ifnum].altsetting[0]); /* clear the temporary strings */ memset(mf, 0, sizeof(mf)); memset(prod, 0, sizeof(prod)); memset(serial, 0, sizeof(serial)); /* search for this device in our unusual device list */ unusual_dev = us_find_dev(dev->descriptor.idVendor, dev->descriptor.idProduct, dev->descriptor.bcdDevice); /* * Can we support this device, either because we know about it * from our unusual device list, or because it advertises that it's * compliant to the specification? */ if (!unusual_dev && !(dev->descriptor.bDeviceClass == 0 && altsetting->bInterfaceClass == USB_CLASS_MASS_STORAGE && altsetting->bInterfaceSubClass >= US_SC_MIN && altsetting->bInterfaceSubClass <= US_SC_MAX)) { /* if it's not a mass storage, we go no further */ return NULL; } /* At this point, we know we've got a live one */ US_DEBUGP("USB Mass Storage device detected\n"); /* Determine subclass and protocol, or copy from the interface */ if (unusual_dev) { subclass = unusual_dev->useProtocol; protocol = unusual_dev->useTransport; flags = unusual_dev->flags; } else { subclass = altsetting->bInterfaceSubClass; protocol = altsetting->bInterfaceProtocol; flags = 0; } /* * Find the endpoints we need * We are expecting a minimum of 2 endpoints - in and out (bulk). * An optional interrupt is OK (necessary for CBI protocol). * We will ignore any others. */ for (i = 0; i < altsetting->bNumEndpoints; i++) { /* is it an BULK endpoint? */ if ((altsetting->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { /* BULK in or out? */ if (altsetting->endpoint[i].bEndpointAddress & USB_DIR_IN) ep_in = &altsetting->endpoint[i]; else ep_out = &altsetting->endpoint[i]; } /* is it an interrupt endpoint? */ if ((altsetting->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { ep_int = &altsetting->endpoint[i]; } } US_DEBUGP("Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)\n", ep_in, ep_out, ep_int, ep_int ? ep_int->bInterval : 0);#ifdef CONFIG_USB_STORAGE_SDDR09 if (protocol == US_PR_EUSB_SDDR09 || protocol == US_PR_DPCM_USB) { /* set the configuration -- STALL is an acceptable response here */ result = usb_set_configuration(dev, 1); US_DEBUGP("Result from usb_set_configuration is %d\n", result); if (result == -EPIPE) { US_DEBUGP("-- clearing stall on control interface\n"); usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); } else if (result != 0) { /* it's not a stall, but another error -- time to bail */ US_DEBUGP("-- Unknown error. Rejecting device\n"); return NULL; } }#endif /* Do some basic sanity checks, and bail if we find a problem */ if (!ep_in || !ep_out || (protocol == US_PR_CBI && !ep_int)) { US_DEBUGP("Sanity check failed. Rejecting device.\n"); return NULL; } /* At this point, we're committed to using the device */ usb_inc_dev_use(dev); /* clear the GUID and fetch the strings */ GUID_CLEAR(guid); if (dev->descriptor.iManufacturer) usb_string(dev, dev->descriptor.iManufacturer, mf, sizeof(mf)); if (dev->descriptor.iProduct) usb_string(dev, dev->descriptor.iProduct, prod, sizeof(prod)); if (dev->descriptor.iSerialNumber && !(flags & US_FL_IGNORE_SER)) usb_string(dev, dev->descriptor.iSerialNumber, serial, sizeof(serial)); /* Create a GUID for this device */ if (dev->descriptor.iSerialNumber && serial[0]) { /* If we have a serial number, and it's a non-NULL string */ make_guid(guid, dev->descriptor.idVendor, dev->descriptor.idProduct, serial); } else { /* We don't have a serial number, so we use 0 */ make_guid(guid, dev->descriptor.idVendor, dev->descriptor.idProduct, "0"); } /* * Now check if we have seen this GUID before * We're looking for a device with a matching GUID that isn't * already on the system */ ss = us_list; while ((ss != NULL) && ((ss->pusb_dev) || !GUID_EQUAL(guid, ss->guid))) ss = ss->next; if (ss != NULL) { /* Existing device -- re-connect */ US_DEBUGP("Found existing GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); /* lock the device pointers */ down(&(ss->dev_semaphore)); /* establish the connection to the new device upon reconnect */ ss->ifnum = ifnum; ss->pusb_dev = dev; /* copy over the endpoint data */ if (ep_in) ss->ep_in = ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; if (ep_out) ss->ep_out = ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; ss->ep_int = ep_int; /* allocate an IRQ callback if one is needed */ if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) { usb_dec_dev_use(dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -