📄 usb.c
字号:
* their inquiry data */ else if ((us->srb->cmnd[0] == INQUIRY) && (us->flags & US_FL_FIX_INQUIRY)) { unsigned char data_ptr[36] = { 0x00, 0x80, 0x02, 0x02, 0x1F, 0x00, 0x00, 0x00}; US_DEBUGP("Faking INQUIRY command\n"); fill_inquiry_response(us, data_ptr, 36); us->srb->result = SAM_STAT_GOOD; } /* we've got a command, let's do it! */ else { US_DEBUG(usb_stor_show_command(us->srb)); us->proto_handler(us->srb, us); } /* lock access to the state */ scsi_lock(host); /* indicate that the command is done */ if (us->srb->result != DID_ABORT << 16) { US_DEBUGP("scsi cmd done, result=0x%x\n", us->srb->result); us->srb->scsi_done(us->srb); } else {SkipForAbort: US_DEBUGP("scsi command aborted\n"); } /* If an abort request was received we need to signal that * the abort has finished. The proper test for this is * the TIMED_OUT flag, not srb->result == DID_ABORT, because * the timeout might have occurred after the command had * already completed with a different result code. */ if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { complete(&(us->notify)); /* Allow USB transfers to resume */ clear_bit(US_FLIDX_ABORTING, &us->flags); clear_bit(US_FLIDX_TIMED_OUT, &us->flags); } /* finished working on this command */ us->srb = NULL; scsi_unlock(host); /* unlock the device pointers */ up(&(us->dev_semaphore)); } /* for (;;) */ scsi_host_put(host); /* notify the exit routine that we're actually exiting now * * complete()/wait_for_completion() is similar to up()/down(), * except that complete() is safe in the case where the structure * is getting deleted in a parallel mode of execution (i.e. just * after the down() -- that's necessary for the thread-shutdown * case. * * complete_and_exit() goes even further than this -- it is safe in * the case that the thread of the caller is going away (not just * the structure) -- this is necessary for the module-remove case. * This is important in preemption kernels, which transfer the flow * of execution immediately upon a complete(). */ complete_and_exit(&threads_gone, 0);} /*********************************************************************** * Device probing and disconnecting ***********************************************************************//* Associate our private data with the USB device */static int associate_dev(struct us_data *us, struct usb_interface *intf){ US_DEBUGP("-- %s\n", __FUNCTION__); /* Fill in the device-related fields */ us->pusb_dev = interface_to_usbdev(intf); us->pusb_intf = intf; us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; US_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n", le16_to_cpu(us->pusb_dev->descriptor.idVendor), le16_to_cpu(us->pusb_dev->descriptor.idProduct), le16_to_cpu(us->pusb_dev->descriptor.bcdDevice)); US_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n", intf->cur_altsetting->desc.bInterfaceSubClass, intf->cur_altsetting->desc.bInterfaceProtocol); /* Store our private data in the interface */ usb_set_intfdata(intf, us); /* Allocate the device-related DMA-mapped buffers */ us->cr = usb_buffer_alloc(us->pusb_dev, sizeof(*us->cr), GFP_KERNEL, &us->cr_dma); if (!us->cr) { US_DEBUGP("usb_ctrlrequest allocation failed\n"); return -ENOMEM; } us->iobuf = usb_buffer_alloc(us->pusb_dev, US_IOBUF_SIZE, GFP_KERNEL, &us->iobuf_dma); if (!us->iobuf) { US_DEBUGP("I/O buffer allocation failed\n"); return -ENOMEM; } return 0;}/* Get the unusual_devs entries and the string descriptors */static void get_device_info(struct us_data *us, int id_index){ struct usb_device *dev = us->pusb_dev; struct usb_interface_descriptor *idesc = &us->pusb_intf->cur_altsetting->desc; struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index]; struct usb_device_id *id = &storage_usb_ids[id_index]; /* Store the entries */ us->unusual_dev = unusual_dev; us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ? idesc->bInterfaceSubClass : unusual_dev->useProtocol; us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? idesc->bInterfaceProtocol : unusual_dev->useTransport; us->flags = unusual_dev->flags; /* * This flag is only needed when we're in high-speed, so let's * disable it if we're in full-speed */ if (dev->speed != USB_SPEED_HIGH) us->flags &= ~US_FL_GO_SLOW; /* Log a message if a non-generic unusual_dev entry contains an * unnecessary subclass or protocol override. This may stimulate * reports from users that will help us remove unneeded entries * from the unusual_devs.h table. */ if (id->idVendor || id->idProduct) { static char *msgs[3] = { "an unneeded SubClass entry", "an unneeded Protocol entry", "unneeded SubClass and Protocol entries"}; struct usb_device_descriptor *ddesc = &dev->descriptor; int msg = -1; if (unusual_dev->useProtocol != US_SC_DEVICE && us->subclass == idesc->bInterfaceSubClass) msg += 1; if (unusual_dev->useTransport != US_PR_DEVICE && us->protocol == idesc->bInterfaceProtocol) msg += 2; if (msg >= 0 && !(unusual_dev->flags & US_FL_NEED_OVERRIDE)) printk(KERN_NOTICE USB_STORAGE "This device " "(%04x,%04x,%04x S %02x P %02x)" " has %s in unusual_devs.h\n" " Please send a copy of this message to " "<linux-usb-devel@lists.sourceforge.net>\n", le16_to_cpu(ddesc->idVendor), le16_to_cpu(ddesc->idProduct), le16_to_cpu(ddesc->bcdDevice), idesc->bInterfaceSubClass, idesc->bInterfaceProtocol, msgs[msg]); }}/* Get the transport settings */static int get_transport(struct us_data *us){ switch (us->protocol) { case US_PR_CB: us->transport_name = "Control/Bulk"; us->transport = usb_stor_CB_transport; us->transport_reset = usb_stor_CB_reset; us->max_lun = 7; break; case US_PR_CBI: us->transport_name = "Control/Bulk/Interrupt"; us->transport = usb_stor_CBI_transport; us->transport_reset = usb_stor_CB_reset; us->max_lun = 7; break; case US_PR_BULK: us->transport_name = "Bulk"; us->transport = usb_stor_Bulk_transport; us->transport_reset = usb_stor_Bulk_reset; break;#ifdef CONFIG_USB_STORAGE_USBAT case US_PR_SCM_ATAPI: us->transport_name = "SCM/ATAPI"; us->transport = usbat_transport; us->transport_reset = usb_stor_CB_reset; us->max_lun = 1; break;#endif#ifdef CONFIG_USB_STORAGE_SDDR09 case US_PR_EUSB_SDDR09: us->transport_name = "EUSB/SDDR09"; us->transport = sddr09_transport; us->transport_reset = usb_stor_CB_reset; us->max_lun = 0; break;#endif#ifdef CONFIG_USB_STORAGE_SDDR55 case US_PR_SDDR55: us->transport_name = "SDDR55"; us->transport = sddr55_transport; us->transport_reset = sddr55_reset; us->max_lun = 0; break;#endif#ifdef CONFIG_USB_STORAGE_DPCM case US_PR_DPCM_USB: us->transport_name = "Control/Bulk-EUSB/SDDR09"; us->transport = dpcm_transport; us->transport_reset = usb_stor_CB_reset; us->max_lun = 1; break;#endif#ifdef CONFIG_USB_STORAGE_FREECOM case US_PR_FREECOM: us->transport_name = "Freecom"; us->transport = freecom_transport; us->transport_reset = usb_stor_freecom_reset; us->max_lun = 0; break;#endif#ifdef CONFIG_USB_STORAGE_DATAFAB case US_PR_DATAFAB: us->transport_name = "Datafab Bulk-Only"; us->transport = datafab_transport; us->transport_reset = usb_stor_Bulk_reset; us->max_lun = 1; break;#endif#ifdef CONFIG_USB_STORAGE_JUMPSHOT case US_PR_JUMPSHOT: us->transport_name = "Lexar Jumpshot Control/Bulk"; us->transport = jumpshot_transport; us->transport_reset = usb_stor_Bulk_reset; us->max_lun = 1; break;#endif default: return -EIO; } US_DEBUGP("Transport: %s\n", us->transport_name); /* fix for single-lun devices */ if (us->flags & US_FL_SINGLE_LUN) us->max_lun = 0; return 0;}/* Get the protocol settings */static int get_protocol(struct us_data *us){ switch (us->subclass) { case US_SC_RBC: us->protocol_name = "Reduced Block Commands (RBC)"; us->proto_handler = usb_stor_transparent_scsi_command; break; case US_SC_8020: us->protocol_name = "8020i"; us->proto_handler = usb_stor_ATAPI_command; us->max_lun = 0; break; case US_SC_QIC: us->protocol_name = "QIC-157"; us->proto_handler = usb_stor_qic157_command; us->max_lun = 0; break; case US_SC_8070: us->protocol_name = "8070i"; us->proto_handler = usb_stor_ATAPI_command; us->max_lun = 0; break; case US_SC_SCSI: us->protocol_name = "Transparent SCSI"; us->proto_handler = usb_stor_transparent_scsi_command; break; case US_SC_UFI: us->protocol_name = "Uniform Floppy Interface (UFI)"; us->proto_handler = usb_stor_ufi_command; break;#ifdef CONFIG_USB_STORAGE_ISD200 case US_SC_ISD200: us->protocol_name = "ISD200 ATA/ATAPI"; us->proto_handler = isd200_ata_command; break;#endif default: return -EIO; } US_DEBUGP("Protocol: %s\n", us->protocol_name); return 0;}/* Get the pipe settings */static int get_pipes(struct us_data *us){ struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting; int i; struct usb_endpoint_descriptor *ep; struct usb_endpoint_descriptor *ep_in = NULL; struct usb_endpoint_descriptor *ep_out = NULL; struct usb_endpoint_descriptor *ep_int = NULL; /* * 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->desc.bNumEndpoints; i++) { ep = &altsetting->endpoint[i].desc; /* Is it a BULK endpoint? */ if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { /* BULK in or out? */ if (ep->bEndpointAddress & USB_DIR_IN) ep_in = ep; else ep_out = ep; } /* Is it an interrupt endpoint? */ else if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { ep_int = ep; } } if (!ep_in || !ep_out || (us->protocol == US_PR_CBI && !ep_int)) { US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -