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

📄 usb-storage.c

📁 Usb1.1驱动c语言源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	for(;;) {		siginfo_t info;		int unsigned long signr;		interruptible_sleep_on(&us->waitq);		action = us->action;		us->action = 0;		/* FIXME: we need to examine placment of break; and 		 * scsi_done() calls */		switch (action) {		case US_ACT_COMMAND:			/* bad device */			if (us->srb->target || us->srb->lun) {				US_DEBUGP( "Bad device number (%d/%d) or dev 0x%x\n",					   us->srb->target, us->srb->lun, (unsigned int)us->pusb_dev);				us->srb->result = DID_BAD_TARGET << 16;				us->srb->scsi_done(us->srb);				us->srb = NULL;				break;			}			/* our device has gone - pretend not ready */			/* FIXME: we also need to handle INQUIRY here, 			 * probably */			if (!us->pusb_dev) {				if (us->srb->cmnd[0] == REQUEST_SENSE) {					memcpy(us->srb->request_buffer, sense_notready, 					       sizeof(sense_notready));					us->srb->result = DID_OK << 16;				} else {					us->srb->result = (DID_OK << 16) | 2;				}				us->srb->scsi_done(us->srb);				us->srb = NULL;				break;			}			/* we've got a command, let's do it! */			US_DEBUG(us_show_command(us->srb));			/* FIXME: this is to support Shuttle E-USB bridges, it 			 * appears */			if (us->srb->cmnd[0] == START_STOP &&			    us->pusb_dev->descriptor.idProduct == 0x0001 &&			    us->pusb_dev->descriptor.idVendor == 0x04e6)				us->srb->result = DID_OK << 16;			else {				us->proto_handler(us->srb, us);			}      			US_DEBUGP("scsi cmd done, result=0x%x\n", us->srb->result);			us->srb->scsi_done(us->srb);			us->srb = NULL;			break;      		case US_ACT_ABORT:			break;		case US_ACT_DEVICE_RESET:			break;		case US_ACT_BUS_RESET:			break;		case US_ACT_HOST_RESET:			break;		} /* end switch on action */    		if (signal_pending(current)) {			/* sending SIGUSR1 makes us print out some info */			spin_lock_irq(&current->sigmask_lock);			signr = dequeue_signal(&current->blocked, &info);			spin_unlock_irq(&current->sigmask_lock);			if (signr == SIGUSR2) {				usb_stor_debug = !usb_stor_debug;				printk(USB_STORAGE "debug toggle = %d\n", usb_stor_debug);			} else {				break;	    /* exit the loop on any other signal */			}		}	}  	//  MOD_DEC_USE_COUNT;	printk("usb_stor_control_thread exiting\n");	/* FIXME: this is a hack to allow for debugging */	// scsi_unregister_module(MODULE_SCSI_HA, us->htmplt);	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){	struct usb_interface_descriptor *interface;	int i;	char mf[32];		     /* manufacturer */	char prod[32];		     /* product */	char serial[32];       	     /* serial number */	struct us_data *ss = NULL;	unsigned int flags = 0;	GUID(guid);		     /* Global Unique Identifier */	struct us_data *prev;	Scsi_Host_Template *htmplt;	int protocol = 0;	int subclass = 0;	struct usb_interface_descriptor *altsetting = 		&(dev->actconfig->interface[ifnum].altsetting[0]); 	/* clear the GUID and fetch the strings */	GUID_CLEAR(guid);	memset(mf, 0, sizeof(mf));	memset(prod, 0, sizeof(prod));	memset(serial, 0, sizeof(serial));	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)		usb_string(dev, dev->descriptor.iSerialNumber, serial, sizeof(serial));		/* let's examine the device now */	/* We make an exception for the shuttle E-USB */	if (dev->descriptor.idVendor == 0x04e6 &&	    dev->descriptor.idProduct == 0x0001) {		protocol = US_PR_CB;		subclass = US_SC_8070;	    /* an assumption */	} else if (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");	/* 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, and restore	 * the flags if we find it	 */	for (ss = us_list; ss != NULL; ss = ss->next) {		if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid))    {			US_DEBUGP("Found existing GUID " GUID_FORMAT "\n",				  GUID_ARGS(guid));			flags = ss->flags;			break;		}	}	/* If ss == NULL, then this is a new device.  Allocate memory for it */	if (!ss) {		if ((ss = (struct us_data *)kmalloc(sizeof(*ss), 						    GFP_KERNEL)) == NULL) {			printk(KERN_WARNING USB_STORAGE "Out of memory\n");			return NULL;		}		memset(ss, 0, sizeof(struct us_data));	}	/* Initialize the us_data structure with some useful info */	interface = altsetting;	ss->flags = flags;	ss->ifnum = ifnum;	ss->pusb_dev = dev;	ss->attention_done = 0;	/* If the device has subclass and protocol, then use that.  Otherwise, 	 * take data from the specific interface.	 */	if (subclass) {		ss->subclass = subclass;		ss->protocol = protocol;	} else {		ss->subclass = interface->bInterfaceSubClass;		ss->protocol = interface->bInterfaceProtocol;	}	/* set the handler pointers based on the protocol */	US_DEBUGP("Transport: ");	switch (ss->protocol) {	case US_PR_CB:		US_DEBUGPX("Control/Bulk\n");		ss->transport = CB_transport;		ss->transport_reset = CB_reset;		break;	case US_PR_CBI:		US_DEBUGPX("Control/Bulk/Interrupt\n");		ss->transport = CB_transport;		ss->transport_reset = CB_reset;		break;	case US_PR_BULK:		US_DEBUGPX("Bulk\n");		ss->transport = Bulk_transport;		ss->transport_reset = Bulk_reset;		break;	default:		US_DEBUGPX("Unknown\n");    		kfree(ss);		return NULL;		break;	}	/*	 * 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 < interface->bNumEndpoints; i++) {		/* is it an BULK endpoint? */		if ((interface->endpoint[i].bmAttributes &  USB_ENDPOINT_XFERTYPE_MASK)		    == USB_ENDPOINT_XFER_BULK) {			if (interface->endpoint[i].bEndpointAddress & USB_DIR_IN)				ss->ep_in = interface->endpoint[i].bEndpointAddress &					USB_ENDPOINT_NUMBER_MASK;			else				ss->ep_out = interface->endpoint[i].bEndpointAddress &					USB_ENDPOINT_NUMBER_MASK;		}		/* is it an interrupt endpoint? */		if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 		    == USB_ENDPOINT_XFER_INT) {			ss->ep_int = interface->endpoint[i].bEndpointAddress &				USB_ENDPOINT_NUMBER_MASK;		}	}	US_DEBUGP("Endpoints In %d Out %d Int %d\n",		  ss->ep_in, ss->ep_out, ss->ep_int);	/* Do some basic sanity checks, and bail if we find a problem */	if (usb_set_interface(dev, interface->bInterfaceNumber, 0) ||	    !ss->ep_in || !ss->ep_out || 	    (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {		US_DEBUGP("Problems with device\n");		if (ss->host) {			scsi_unregister_module(MODULE_SCSI_HA, ss->htmplt);			kfree(ss->htmplt->name);			kfree(ss->htmplt);		}		kfree(ss);		return NULL;	}	/* If this is a new device (i.e. we haven't seen it before), we need to	 * generate a scsi host definition, and register with scsi above us 	 */	if (!ss->host) {		/* copy the GUID we created before */		US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid));		memcpy(ss->guid, guid, sizeof(guid));		/* set class specific stuff */		US_DEBUGP("Protocol: ");		switch (ss->subclass) {		case US_SC_RBC:			US_DEBUGPX("Reduced Block Commands\n");			break;		case US_SC_8020:			US_DEBUGPX("8020\n");			break;		case US_SC_QIC:			US_DEBUGPX("QIC157\n");			break;		case US_SC_8070:			US_DEBUGPX("8070\n");			break;		case US_SC_SCSI:			US_DEBUGPX("Transparent SCSI\n");			ss->proto_handler = transparent_scsi_command;			break;		case US_SC_UFI:			US_DEBUGPX("UFI\n");			ss->proto_handler = ufi_command;			break;		default:			US_DEBUGPX("Unknown\n");			break;		}		/* We only handle certain protocols.  Currently, these are		 *the only ones that devices use.		 */		if ((ss->subclass != US_SC_SCSI) && (ss->subclass != US_SC_UFI)) {			US_DEBUGP("Sorry, we do not support that protocol yet.\n");			US_DEBUGP("If you have a device which uses one of the unsupported\n");			US_DEBUGP("protocols, please contact mdharm-usb@one-eyed-alien.net\n");     			kfree(ss);			return NULL;		}		/* Allocate memory for the SCSI Host Template */		if ((htmplt = (Scsi_Host_Template *)		     kmalloc(sizeof(*ss->htmplt), GFP_KERNEL)) == NULL ) {			printk(KERN_WARNING USB_STORAGE "Out of memory\n");			kfree(ss);			return NULL;		}		/* Initialize the host template based on the default one */		memcpy(htmplt, &my_host_template, sizeof(my_host_template));		/* Grab the next host number */		ss->host_number = my_host_number++;		/* MDD: FIXME: this is bad.  We abuse this pointer so we		 * can pass the ss pointer to the host controler thread		 * in us_detect		 */		(struct us_data *)htmplt->proc_dir = ss; 		/* shuttle E-USB */			if (dev->descriptor.idVendor == 0x04e6 &&		    dev->descriptor.idProduct == 0x0001) {			__u8 qstat[2];			int result;	    			result = usb_control_msg(ss->pusb_dev, usb_rcvctrlpipe(dev,0),						 1, 0xC0,						 0, ss->ifnum,						 qstat, 2, HZ*5);			US_DEBUGP("C0 status 0x%x 0x%x\n", qstat[0], qstat[1]);			init_waitqueue_head(&ss->ip_waitq);			ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);			result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq,						 255, (void *)ss, &ss->irq_handle);			if (result)				return NULL;			interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*6);		} else if (ss->protocol == US_PR_CBI)		{			int result; 			init_waitqueue_head(&ss->ip_waitq);			/* set up the IRQ pipe and handler */			/* FIXME: This needs to get the period from the device */			ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);			result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq,						 255, (void *)ss, &ss->irq_handle);			if (result) {				US_DEBUGP("usb_request_irq failed (0x%x), No interrupt for CBI\n",					  result);			}		}    		/* start up our thread */		{			DECLARE_MUTEX_LOCKED(sem);			init_waitqueue_head(&ss->waitq);			ss->notify = &sem;			ss->pid = kernel_thread(usb_stor_control_thread, ss,						CLONE_FS | CLONE_FILES | CLONE_SIGHAND);			if (ss->pid < 0) {				printk(KERN_WARNING USB_STORAGE "Unable to start control thread\n");				kfree(htmplt);				kfree(ss);				return NULL;			}			/* wait for it to start */			down(&sem);		}		/* now register - our detect function will be called */		scsi_register_module(MODULE_SCSI_HA, htmplt);		/* put us in the list */		prev = (struct us_data *)&us_list;		while (prev->next)			prev = prev->next;		prev->next = ss;	}	printk(KERN_INFO "WARNING: USB Mass Storage data integrity not assured\n");	printk(KERN_INFO "USB Mass Storage device found at %d\n", dev->devnum);	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;	if (!ss)		return;	ss->pusb_dev = NULL;	//  MOD_DEC_USE_COUNT;}/*********************************************************************** * Initialization and registration ***********************************************************************/int __init usb_stor_init(void){	//  MOD_INC_USE_COUNT;	if (sizeof(my_host_template) != SCSI_HOST_TEMPLATE_SIZE) {		printk(KERN_ERR "usb-storage: SCSI_HOST_TEMPLATE_SIZE does not match\n") ;		printk(KERN_ERR "usb-storage: expected %d bytes, got %d bytes\n", 		       SCSI_HOST_TEMPLATE_SIZE, sizeof(my_host_template)) ;		return -1 ;	}	/* register the driver, return -1 if error */	if (usb_register(&storage_driver) < 0)		return -1;	printk(KERN_INFO "USB Mass Storage support registered.\n");	return 0;}void __exit usb_stor_exit(void){	usb_deregister(&storage_driver) ;}module_init(usb_stor_init) ;module_exit(usb_stor_exit) ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -