⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 LINUX下USB驱动程序的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
				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 + -