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

📄 usb.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Driver for USB Mass Storage compliant devices * * $Id: usb.c,v 1.70 2002/01/06 07:14:12 mdharm Exp $ * * Current development and maintenance by: *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * * Developed with the assistance of: *   (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) * * Initial work by: *   (c) 1999 Michael Gee (michael@linuxspecific.com) * * usb_device_id support by Adam J. Richter (adam@yggdrasil.com): *   (c) 2000 Yggdrasil Computing, Inc. * * This driver is based on the 'USB Mass Storage Class' document. This * describes in detail the protocol used to communicate with such * devices.  Clearly, the designers had SCSI and ATAPI commands in * mind when they created this document.  The commands are all very * similar to commands in the SCSI-II and ATAPI specifications. * * It is important to note that in a number of cases this class * exhibits class-specific exemptions from the USB specification. * Notably the usage of NAK, STALL and ACK differs from the norm, in * that they are used to communicate wait, failed and OK on commands. * * Also, for certain devices, the interrupt endpoint is used to convey * status of a command. * * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more * information about this driver. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/config.h>#include "usb.h"#include "scsiglue.h"#include "transport.h"#include "protocol.h"#include "debug.h"#include "initializers.h"#ifdef CONFIG_USB_STORAGE_HP8200e#include "shuttle_usbat.h"#endif#ifdef CONFIG_USB_STORAGE_SDDR09#include "sddr09.h"#endif#ifdef CONFIG_USB_STORAGE_DPCM#include "dpcm.h"#endif#ifdef CONFIG_USB_STORAGE_FREECOM#include "freecom.h"#endif#ifdef CONFIG_USB_STORAGE_ISD200#include "isd200.h"#endif#ifdef CONFIG_USB_STORAGE_DATAFAB#include "datafab.h"#endif#ifdef CONFIG_USB_STORAGE_JUMPSHOT#include "jumpshot.h"#endif#include <linux/module.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/slab.h>/* Some informational data */MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");MODULE_DESCRIPTION("USB Mass Storage driver for Linux");MODULE_LICENSE("GPL");/* * Per device data */static int my_host_number;/* * kernel thread actions */#define US_ACT_COMMAND		1#define US_ACT_DEVICE_RESET	2#define US_ACT_BUS_RESET	3#define US_ACT_HOST_RESET	4#define US_ACT_EXIT		5/* The list of structures and the protective lock for them */struct us_data *us_list;struct semaphore us_list_semaphore;static void * storage_probe(struct usb_device *dev, unsigned int ifnum,			    const struct usb_device_id *id);static void storage_disconnect(struct usb_device *dev, void *ptr);/* The entries in this table, except for final ones here * (USB_MASS_STORAGE_CLASS and the empty entry), correspond, * line for line with the entries of us_unsuaul_dev_list[]. * For now, we duplicate idVendor and idProduct in us_unsual_dev_list, * just to avoid alignment bugs. */#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \		    vendorName, productName,useProtocol, useTransport, \		    initFunction, flags) \{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) }static struct usb_device_id storage_usb_ids [] = {#	include "unusual_devs.h"#undef UNUSUAL_DEV	/* Control/Bulk transport for all SubClass values */	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) },	/* Control/Bulk/Interrupt transport for all SubClass values */	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) },	/* Bulk-only transport for all SubClass values */	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },	/* Terminating entry */	{ }};MODULE_DEVICE_TABLE (usb, storage_usb_ids);/* This is the list of devices we recognize, along with their flag data *//* The vendor name should be kept at eight characters or less, and * the product name should be kept at 16 characters or less. If a device * has the US_FL_FIX_INQUIRY flag, then the vendor and product names * normally generated by a device thorugh the INQUIRY response will be * taken from this list, and this is the reason for the above size * restriction. However, if the flag is not present, then you * are free to use as many characters as you like. */#undef UNUSUAL_DEV#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \		    vendor_name, product_name, use_protocol, use_transport, \		    init_function, Flags) \{ \	vendorName: vendor_name,	\	productName: product_name,	\	useProtocol: use_protocol,	\	useTransport: use_transport,	\	initFunction : init_function,	\	flags: Flags, \}static struct us_unusual_dev us_unusual_dev_list[] = {#	include "unusual_devs.h" #	undef UNUSUAL_DEV	/* Control/Bulk transport for all SubClass values */	{ useProtocol: US_SC_RBC,	  useTransport: US_PR_CB},	{ useProtocol: US_SC_8020,	  useTransport: US_PR_CB},	{ useProtocol: US_SC_QIC,	  useTransport: US_PR_CB},	{ useProtocol: US_SC_UFI,	  useTransport: US_PR_CB},	{ useProtocol: US_SC_8070,	  useTransport: US_PR_CB},	{ useProtocol: US_SC_SCSI,	  useTransport: US_PR_CB},	/* Control/Bulk/Interrupt transport for all SubClass values */	{ useProtocol: US_SC_RBC,	  useTransport: US_PR_CBI},	{ useProtocol: US_SC_8020,	  useTransport: US_PR_CBI},	{ useProtocol: US_SC_QIC,	  useTransport: US_PR_CBI},	{ useProtocol: US_SC_UFI,	  useTransport: US_PR_CBI},	{ useProtocol: US_SC_8070,	  useTransport: US_PR_CBI},	{ useProtocol: US_SC_SCSI,	  useTransport: US_PR_CBI},	/* Bulk-only transport for all SubClass values */	{ useProtocol: US_SC_RBC,	  useTransport: US_PR_BULK},	{ useProtocol: US_SC_8020,	  useTransport: US_PR_BULK},	{ useProtocol: US_SC_QIC,	  useTransport: US_PR_BULK},	{ useProtocol: US_SC_UFI,	  useTransport: US_PR_BULK},	{ useProtocol: US_SC_8070,	  useTransport: US_PR_BULK},	{ useProtocol: US_SC_SCSI,	  useTransport: US_PR_BULK},	/* Terminating entry */	{ 0 }};struct usb_driver usb_storage_driver = {	name:		"usb-storage",	probe:		storage_probe,	disconnect:	storage_disconnect,	id_table:	storage_usb_ids,};/* * fill_inquiry_response takes an unsigned char array (which must * be at least 36 characters) and populates the vendor name, * product name, and revision fields. Then the array is copied * into the SCSI command's response buffer (oddly enough * called request_buffer). data_len contains the length of the * data array, which again must be at least 36. */void fill_inquiry_response(struct us_data *us, unsigned char *data,		unsigned int data_len) {	int i;	struct scatterlist *sg;	int len =		us->srb->request_bufflen > data_len ? data_len :		us->srb->request_bufflen;	int transferred;	int amt;	if (data_len<36) // You lose.		return;	if(data[0]&0x20) { /* USB device currently not connected. Return			      peripheral qualifier 001b ("...however, the			      physical device is not currently connected			      to this logical unit") and leave vendor and			      product identification empty. ("If the target			      does store some of the INQUIRY data on the			      device, it may return zeros or ASCII spaces 			      (20h) in those fields until the data is			      available from the device."). */		memset(data+8,0,28);	} else {		memcpy(data+8, us->unusual_dev->vendorName, 			strlen(us->unusual_dev->vendorName) > 8 ? 8 :			strlen(us->unusual_dev->vendorName));		memcpy(data+16, us->unusual_dev->productName, 			strlen(us->unusual_dev->productName) > 16 ? 16 :			strlen(us->unusual_dev->productName));		data[32] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>12) & 0x0F);		data[33] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>8) & 0x0F);		data[34] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>4) & 0x0F);		data[35] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice) & 0x0F);	}	if (us->srb->use_sg) {		sg = (struct scatterlist *)us->srb->request_buffer;		for (i=0; i<us->srb->use_sg; i++)			memset(sg[i].address, 0, sg[i].length);		for (i=0, transferred=0; 				i<us->srb->use_sg && transferred < len;				i++) {			amt = sg[i].length > len-transferred ? 					len-transferred : sg[i].length;			memcpy(sg[i].address, data+transferred, amt);			transferred -= amt;		}	} else {		memset(us->srb->request_buffer, 0, us->srb->request_bufflen);		memcpy(us->srb->request_buffer, data, len);	}}static int usb_stor_control_thread(void * __us){	struct us_data *us = (struct us_data *)__us;	int action;	lock_kernel();	/*	 * This thread doesn't need any user-level access,	 * so get rid of all our resources..	 */	exit_files(current);	current->files = init_task.files;	atomic_inc(&current->files->count);	daemonize();	/* avoid getting signals */	spin_lock_irq(&current->sigmask_lock);	flush_signals(current);	sigfillset(&current->blocked);	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	/* set our name for identification purposes */	sprintf(current->comm, "usb-storage-%d", us->host_number);	unlock_kernel();	/* set up for wakeups by new commands */	init_MUTEX_LOCKED(&us->sema);	/* signal that we've started the thread */	complete(&(us->notify));	set_current_state(TASK_INTERRUPTIBLE);	for(;;) {		US_DEBUGP("*** thread sleeping.\n");		if(down_interruptible(&us->sema))			break;					US_DEBUGP("*** thread awakened.\n");		/* lock access to the queue element */		down(&(us->queue_exclusion));		/* take the command off the queue */		action = us->action;		us->action = 0;		us->srb = us->queue_srb;		/* release the queue lock as fast as possible */		up(&(us->queue_exclusion));		switch (action) {		case US_ACT_COMMAND:			/* reject the command if the direction indicator 			 * is UNKNOWN			 */			if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {				US_DEBUGP("UNKNOWN data direction\n");				us->srb->result = DID_ERROR << 16;				set_current_state(TASK_INTERRUPTIBLE);				us->srb->scsi_done(us->srb);				us->srb = NULL;				break;			}			/* reject if target != 0 or if LUN is higher than			 * the maximum known LUN			 */			if (us->srb->target && 					!(us->flags & US_FL_SCM_MULT_TARG)) {				US_DEBUGP("Bad target number (%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;

⌨️ 快捷键说明

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