📄 usb.c
字号:
us->srb = NULL; break; } if (us->srb->lun > us->max_lun) { US_DEBUGP("Bad LUN (%d/%d)\n", us->srb->target, us->srb->lun); us->srb->result = DID_BAD_TARGET << 16; set_current_state(TASK_INTERRUPTIBLE); us->srb->scsi_done(us->srb); us->srb = NULL; break; } /* lock the device pointers */ down(&(us->dev_semaphore)); /* our device has gone - pretend not ready */ if (!us->pusb_dev) { US_DEBUGP("Request is for removed device\n"); /* For REQUEST_SENSE, it's the data. But * for anything else, it should look like * we auto-sensed for it. */ if (us->srb->cmnd[0] == REQUEST_SENSE) { memcpy(us->srb->request_buffer, usb_stor_sense_notready, sizeof(usb_stor_sense_notready)); us->srb->result = GOOD << 1; } else if(us->srb->cmnd[0] == INQUIRY) { unsigned char data_ptr[36] = { 0x20, 0x80, 0x02, 0x02, 0x1F, 0x00, 0x00, 0x00}; US_DEBUGP("Faking INQUIRY command for disconnected device\n"); fill_inquiry_response(us, data_ptr, 36); us->srb->result = GOOD << 1; } else { memcpy(us->srb->sense_buffer, usb_stor_sense_notready, sizeof(usb_stor_sense_notready)); us->srb->result = CHECK_CONDITION << 1; } } else { /* !us->pusb_dev */ /* Handle those devices which need us to fake * their inquiry data */ 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 = GOOD << 1; } else { /* we've got a command, let's do it! */ US_DEBUG(usb_stor_show_command(us->srb)); us->proto_handler(us->srb, us); } } /* unlock the device pointers */ up(&(us->dev_semaphore)); /* 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); set_current_state(TASK_INTERRUPTIBLE); us->srb->scsi_done(us->srb); }; if (atomic_read(&us->abortcnt) != 0) { US_DEBUGP("scsi command aborted\n"); set_current_state(TASK_INTERRUPTIBLE); complete(&(us->notify)); } us->srb = NULL; break; case US_ACT_DEVICE_RESET: break; case US_ACT_BUS_RESET: break; case US_ACT_HOST_RESET: break; } /* end switch on action */ /* exit if we get a signal to exit */ if (action == US_ACT_EXIT) { US_DEBUGP("-- US_ACT_EXIT command received\n"); break; } } /* for (;;) */ /* clean up after ourselves */ set_current_state(TASK_INTERRUPTIBLE); /* notify the exit routine that we're actually exiting now */ complete(&(us->notify)); return 0;} /* 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 * * ss->dev_semaphore is expected taken, except for a newly minted, * unregistered device. */ 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"); /* allocate the URB */ ss->irq_urb = usb_alloc_urb(0); if (!ss->irq_urb) { 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); return 2; } 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; const int id_index = id - storage_usb_ids; 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 on the interface we're probing that matched our * usb_match_id table */ struct usb_interface *intf = dev->actconfig->interface; struct usb_interface_descriptor *altsetting = intf[ifnum].altsetting + intf[ifnum].act_altsetting; US_DEBUGP("act_altsettting is %d\n", intf[ifnum].act_altsetting); /* clear the temporary strings */ memset(mf, 0, sizeof(mf)); memset(prod, 0, sizeof(prod)); memset(serial, 0, sizeof(serial)); /* * 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? * * id_index is calculated in the declaration to be the index number * of the match from the usb_device_id table, so we can find the * corresponding entry in the private table. */ US_DEBUGP("id_index calculated to be: %d\n", id_index); US_DEBUGP("Array length appears to be: %d\n", sizeof(us_unusual_dev_list) / sizeof(us_unusual_dev_list[0])); if (id_index < sizeof(us_unusual_dev_list) / sizeof(us_unusual_dev_list[0])) { unusual_dev = &us_unusual_dev_list[id_index]; if (unusual_dev->vendorName) US_DEBUGP("Vendor: %s\n", unusual_dev->vendorName); if (unusual_dev->productName) US_DEBUGP("Product: %s\n", unusual_dev->productName); } else /* no, we can't support it */ 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 */ subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ? altsetting->bInterfaceSubClass : unusual_dev->useProtocol; protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? altsetting->bInterfaceProtocol : unusual_dev->useTransport; flags = unusual_dev->flags; /* * 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("Endpoint sanity check failed! Rejecting dev.\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)) { up(&(ss->dev_semaphore)); usb_dec_dev_use(dev); return NULL; } /* allocate the URB we're going to use */ ss->current_urb = usb_alloc_urb(0); if (!ss->current_urb) { up(&(ss->dev_semaphore)); usb_dec_dev_use(dev); return NULL; } /* Re-Initialize the device if it needs it */ if (unusual_dev && unusual_dev->initFunction) (unusual_dev->initFunction)(ss); /* unlock the device pointers */ up(&(ss->dev_semaphore)); } else { /* New device -- allocate memory and initialize */ US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data), GFP_KERNEL)) == NULL) { printk(KERN_WARNING USB_STORAGE "Out of memory\n"); usb_dec_dev_use(dev); return NULL; } memset(ss, 0, sizeof(struct us_data)); /* allocate the URB we're going to use */ ss->current_urb = usb_alloc_urb(0); if (!ss->current_urb) { kfree(ss); usb_dec_dev_use(dev); return NULL; } /* Initialize the mutexes only when the struct is new */ init_completion(&(ss->notify)); init_MUTEX_LOCKED(&(ss->ip_waitq)); spin_lock_init(&(ss->queue_exclusion)); init_MUTEX(&(ss->current_urb_sem)); init_MUTEX(&(ss->dev_semaphore)); /* copy over the subclass and protocol data */ ss->subclass = subclass; ss->protocol = protocol; ss->flags = flags; ss->unusual_dev = unusual_dev; /* copy over the endpoint data */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -