📄 usb.c
字号:
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; /* establish the connection to the new device */ ss->ifnum = ifnum; ss->pusb_dev = dev; /* copy over the identifiying strings */ strncpy(ss->vendor, mf, USB_STOR_STRING_LEN); strncpy(ss->product, prod, USB_STOR_STRING_LEN); strncpy(ss->serial, serial, USB_STOR_STRING_LEN); if (strlen(ss->vendor) == 0) { if (unusual_dev->vendorName) strncpy(ss->vendor, unusual_dev->vendorName, USB_STOR_STRING_LEN); else strncpy(ss->vendor, "Unknown", USB_STOR_STRING_LEN); } if (strlen(ss->product) == 0) { if (unusual_dev->productName) strncpy(ss->product, unusual_dev->productName, USB_STOR_STRING_LEN); else strncpy(ss->product, "Unknown", USB_STOR_STRING_LEN); } if (strlen(ss->serial) == 0) strncpy(ss->serial, "None", USB_STOR_STRING_LEN); /* copy the GUID we created before */ memcpy(ss->guid, guid, sizeof(guid)); /* * Set the handler pointers based on the protocol * Again, this data is persistant across reattachments */ switch (ss->protocol) { case US_PR_CB: ss->transport_name = "Control/Bulk"; ss->transport = usb_stor_CB_transport; ss->transport_reset = usb_stor_CB_reset; ss->max_lun = 7; break; case US_PR_CBI: ss->transport_name = "Control/Bulk/Interrupt"; ss->transport = usb_stor_CBI_transport; ss->transport_reset = usb_stor_CB_reset; ss->max_lun = 7; break; case US_PR_BULK: ss->transport_name = "Bulk"; ss->transport = usb_stor_Bulk_transport; ss->transport_reset = usb_stor_Bulk_reset; ss->max_lun = usb_stor_Bulk_max_lun(ss); break;#ifdef CONFIG_USB_STORAGE_HP8200e case US_PR_SCM_ATAPI: ss->transport_name = "SCM/ATAPI"; ss->transport = hp8200e_transport; ss->transport_reset = usb_stor_CB_reset; ss->max_lun = 1; break;#endif#ifdef CONFIG_USB_STORAGE_SDDR09 case US_PR_EUSB_SDDR09: ss->transport_name = "EUSB/SDDR09"; ss->transport = sddr09_transport; ss->transport_reset = usb_stor_CB_reset; ss->max_lun = 0; break;#endif#ifdef CONFIG_USB_STORAGE_SDDR55 case US_PR_SDDR55: ss->transport_name = "SDDR55"; ss->transport = sddr55_transport; ss->transport_reset = sddr55_reset; ss->max_lun = 0; break;#endif#ifdef CONFIG_USB_STORAGE_DPCM case US_PR_DPCM_USB: ss->transport_name = "Control/Bulk-EUSB/SDDR09"; ss->transport = dpcm_transport; ss->transport_reset = usb_stor_CB_reset; ss->max_lun = 1; break;#endif#ifdef CONFIG_USB_STORAGE_FREECOM case US_PR_FREECOM: ss->transport_name = "Freecom"; ss->transport = freecom_transport; ss->transport_reset = usb_stor_freecom_reset; ss->max_lun = 0; break;#endif#ifdef CONFIG_USB_STORAGE_DATAFAB case US_PR_DATAFAB: ss->transport_name = "Datafab Bulk-Only"; ss->transport = datafab_transport; ss->transport_reset = usb_stor_Bulk_reset; ss->max_lun = 1; break;#endif#ifdef CONFIG_USB_STORAGE_JUMPSHOT case US_PR_JUMPSHOT: ss->transport_name = "Lexar Jumpshot Control/Bulk"; ss->transport = jumpshot_transport; ss->transport_reset = usb_stor_Bulk_reset; ss->max_lun = 1; break;#endif default: ss->transport_name = "Unknown"; kfree(ss->current_urb); kfree(ss); usb_dec_dev_use(dev); return NULL; break; } US_DEBUGP("Transport: %s\n", ss->transport_name); /* fix for single-lun devices */ if (ss->flags & US_FL_SINGLE_LUN) ss->max_lun = 0; switch (ss->subclass) { case US_SC_RBC: ss->protocol_name = "Reduced Block Commands (RBC)"; ss->proto_handler = usb_stor_transparent_scsi_command; break; case US_SC_8020: ss->protocol_name = "8020i"; ss->proto_handler = usb_stor_ATAPI_command; ss->max_lun = 0; break; case US_SC_QIC: ss->protocol_name = "QIC-157"; ss->proto_handler = usb_stor_qic157_command; ss->max_lun = 0; break; case US_SC_8070: ss->protocol_name = "8070i"; ss->proto_handler = usb_stor_ATAPI_command; ss->max_lun = 0; break; case US_SC_SCSI: ss->protocol_name = "Transparent SCSI"; ss->proto_handler = usb_stor_transparent_scsi_command; break; case US_SC_UFI: ss->protocol_name = "Uniform Floppy Interface (UFI)"; ss->proto_handler = usb_stor_ufi_command; break;#ifdef CONFIG_USB_STORAGE_ISD200 case US_SC_ISD200: ss->protocol_name = "ISD200 ATA/ATAPI"; ss->proto_handler = isd200_ata_command; break;#endif default: ss->protocol_name = "Unknown"; kfree(ss->current_urb); kfree(ss); usb_dec_dev_use(dev); return NULL; break; } US_DEBUGP("Protocol: %s\n", ss->protocol_name); /* allocate an IRQ callback if one is needed */ if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) { kfree(ss->current_urb); kfree(ss); usb_dec_dev_use(dev); return NULL; } /* * Since this is a new device, we need to generate a scsi * host definition, and register with the higher SCSI layers */ /* Initialize the host template based on the default one */ memcpy(&(ss->htmplt), &usb_stor_host_template, sizeof(usb_stor_host_template)); /* Grab the next host number */ ss->host_number = my_host_number++; /* We abuse this pointer so we can pass the ss pointer to * the host controller thread in us_detect. But how else are * we to do it? */ ss->htmplt.proc_dir = (void *)ss; /* According to the technical support people at Genesys Logic, * devices using their chips have problems transferring more * than 32 KB at a time. In practice people have found that * 64 KB works okay and that's what Windows does. But we'll * be conservative. */ if (ss->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS) ss->htmplt.max_sectors = 64; /* Just before we start our control thread, initialize * the device if it needs initialization */ if (unusual_dev && unusual_dev->initFunction) unusual_dev->initFunction(ss); /* start up our control thread */ ss->pid = kernel_thread(usb_stor_control_thread, ss, CLONE_VM); if (ss->pid < 0) { printk(KERN_WARNING USB_STORAGE "Unable to start control thread\n"); kfree(ss->current_urb); kfree(ss); usb_dec_dev_use(dev); return NULL; } /* wait for the thread to start */ wait_for_completion(&(ss->notify)); /* now register - our detect function will be called */ ss->htmplt.module = THIS_MODULE; scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt)); /* lock access to the data structures */ down(&us_list_semaphore); /* put us in the list */ ss->next = us_list; us_list = ss; /* release the data structure lock */ up(&us_list_semaphore); } printk(KERN_DEBUG "WARNING: USB Mass Storage data integrity not assured\n"); printk(KERN_DEBUG "USB Mass Storage device found at %d\n", dev->devnum); /* return a pointer for the disconnect function */ return ss;}/* Handle a disconnect event from the USB core */static void storage_disconnect(struct usb_device *dev, void *ptr){ struct us_data *ss = ptr; int result; US_DEBUGP("storage_disconnect() called\n"); /* this is the odd case -- we disconnected but weren't using it */ if (!ss) { US_DEBUGP("-- device was not in use\n"); return; } /* lock access to the device data structure */ down(&(ss->dev_semaphore)); /* release the IRQ, if we have one */ if (ss->irq_urb) { US_DEBUGP("-- releasing irq URB\n"); result = usb_unlink_urb(ss->irq_urb); US_DEBUGP("-- usb_unlink_urb() returned %d\n", result); usb_free_urb(ss->irq_urb); ss->irq_urb = NULL; } /* free up the main URB for this device */ US_DEBUGP("-- releasing main URB\n"); result = usb_unlink_urb(ss->current_urb); US_DEBUGP("-- usb_unlink_urb() returned %d\n", result); usb_free_urb(ss->current_urb); ss->current_urb = NULL; /* mark the device as gone */ usb_dec_dev_use(ss->pusb_dev); ss->pusb_dev = NULL; /* unlock access to the device data structure */ up(&(ss->dev_semaphore));}/*********************************************************************** * Initialization and registration ***********************************************************************/int __init usb_stor_init(void){ printk(KERN_INFO "Initializing USB Mass Storage driver...\n"); /* initialize internal global data elements */ us_list = NULL; init_MUTEX(&us_list_semaphore); my_host_number = 0; /* register the driver, return -1 if error */ if (usb_register(&usb_storage_driver) < 0) return -1; /* we're all set */ printk(KERN_INFO "USB Mass Storage support registered.\n"); return 0;}void __exit usb_stor_exit(void){ struct us_data *next; US_DEBUGP("usb_stor_exit() called\n"); /* Deregister the driver * This eliminates races with probes and disconnects */ US_DEBUGP("-- calling usb_deregister()\n"); usb_deregister(&usb_storage_driver) ; /* While there are still virtual hosts, unregister them * Note that it's important to do this completely before removing * the structures because of possible races with the /proc * interface */ for (next = us_list; next; next = next->next) { US_DEBUGP("-- calling scsi_unregister_module()\n"); scsi_unregister_module(MODULE_SCSI_HA, &(next->htmplt)); } /* While there are still structures, free them. Note that we are * now race-free, since these structures can no longer be accessed * from either the SCSI command layer or the /proc interface */ while (us_list) { /* keep track of where the next one is */ next = us_list->next; /* If there's extra data in the us_data structure then * free that first */ if (us_list->extra) { /* call the destructor routine, if it exists */ if (us_list->extra_destructor) { US_DEBUGP("-- calling extra_destructor()\n"); us_list->extra_destructor(us_list->extra); } /* destroy the extra data */ US_DEBUGP("-- freeing the data structure\n"); kfree(us_list->extra); } /* free the structure itself */ kfree (us_list); /* advance the list pointer */ us_list = next; }}module_init(usb_stor_init);module_exit(usb_stor_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -