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

📄 microtek.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	return;}static void mts_get_status( struct urb *transfer )/* Interrupt context! */{	MTS_INT_INIT();	mts_int_submit_urb(transfer,			   usb_rcvbulkpipe(context->instance->usb_dev,					   context->instance->ep_response),			   &context->status,			   1,			   mts_transfer_done );}static void mts_data_done( struct urb* transfer )/* Interrupt context! */{	MTS_INT_INIT();	if ( context->data_length != transfer->actual_length ) {		context->srb->resid = context->data_length - transfer->actual_length;	} else if ( transfer->status ) {		context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;	}	mts_get_status(transfer);	return;}static void mts_command_done( struct urb *transfer )/* Interrupt context! */{	MTS_INT_INIT();	if ( transfer->status ) {	        if (transfer->status == -ENOENT) {		        /* We are being killed */			MTS_DEBUG_GOT_HERE();			context->srb->result = DID_ABORT<<16;                } else {		        /* A genuine error has occured */			MTS_DEBUG_GOT_HERE();		        context->srb->result = DID_ERROR<<16;                }		mts_transfer_cleanup(transfer);		return;	}	if ( context->data ) {		mts_int_submit_urb(transfer,				   context->data_pipe,				   context->data,				   context->data_length,				   context->srb->use_sg ? mts_do_sg : mts_data_done);	} else mts_get_status(transfer);	return;}static void mts_do_sg (struct urb* transfer){	struct scatterlist * sg;	MTS_INT_INIT();		MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg);	if (transfer->status) {                context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;		mts_transfer_cleanup(transfer);        }	sg = context->srb->buffer;	context->fragment++;	mts_int_submit_urb(transfer,			context->data_pipe,			sg[context->fragment].address,			sg[context->fragment].length,			context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);	return;}static const u8 mts_read_image_sig[] = { 0x28, 00, 00, 00 };static const u8 mts_read_image_sig_len = 4;static const unsigned char mts_direction[256/8] = {	0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,	0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};#define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1)static voidmts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc ){	int pipe;	struct scatterlist * sg;		MTS_DEBUG_GOT_HERE();	desc->context.instance = desc;	desc->context.srb = srb;	desc->context.fragment = 0;	if (!srb->use_sg) {		if ( !srb->bufflen ){			desc->context.data = 0;			desc->context.data_length = 0;			return;		} else {			desc->context.data = srb->buffer;			desc->context.data_length = srb->bufflen;			MTS_DEBUG("length = %d or %d\n",				  srb->request_bufflen, srb->bufflen);		}	} else {		MTS_DEBUG("Using scatter/gather\n");		sg = srb->buffer;		desc->context.data = sg[0].address;		desc->context.data_length = sg[0].length;	}	/* can't rely on srb->sc_data_direction */	/* Brutally ripped from usb-storage */	if ( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len )) { 		pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_image);		MTS_DEBUG( "transfering from desc->ep_image == %d\n",			   (int)desc->ep_image );	} else if ( MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) {			pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_response);			MTS_DEBUG( "transfering from desc->ep_response == %d\n",				   (int)desc->ep_response);	} else {		MTS_DEBUG("transfering to desc->ep_out == %d\n",			  (int)desc->ep_out);		pipe = usb_sndbulkpipe(desc->usb_dev,desc->ep_out);	}	desc->context.data_pipe = pipe;}staticint mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ){	struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);	int err = 0;	int res;	MTS_DEBUG_GOT_HERE();	mts_show_command(srb);	mts_debug_dump(desc);	if ( srb->device->lun || srb->device->id || srb->device->channel ) {		MTS_DEBUG("Command to LUN=%d ID=%d CHANNEL=%d from SCSI layer\n",(int)srb->device->lun,(int)srb->device->id, (int)srb->device->channel );		MTS_DEBUG("this device doesn't exist\n");		srb->result = DID_BAD_TARGET << 16;		if(callback)			callback(srb);		goto out;	}		FILL_BULK_URB(&desc->urb,		      desc->usb_dev,		      usb_sndbulkpipe(desc->usb_dev,desc->ep_out),		      srb->cmnd,		      srb->cmd_len,		      mts_command_done,		      &desc->context		      );	mts_build_transfer_context( srb, desc );	desc->context.final_callback = callback;		res=usb_submit_urb(&desc->urb);	if(res){		MTS_ERROR("error %d submitting URB\n",(int)res);		srb->result = DID_ERROR << 16;		if(callback)			callback(srb);	}out:	return err;}/* * this defines our 'host' *//* NOTE: This is taken from usb-storage, should be right. */static Scsi_Host_Template mts_scsi_host_template = {	name:           "microtekX6",	detect:		mts_scsi_detect,	release:	mts_scsi_release,	queuecommand:	mts_scsi_queuecommand,	eh_abort_handler:	mts_scsi_abort,	eh_host_reset_handler:	mts_scsi_host_reset,	sg_tablesize:		SG_ALL,	can_queue:		1,	this_id:		-1,	cmd_per_lun:		1,	present:		0,	unchecked_isa_dma:	FALSE,	use_clustering:		TRUE,	use_new_eh_code:	TRUE,	emulated:		TRUE};/* USB layer driver interface implementation */static void mts_usb_disconnect (struct usb_device *dev, void *ptr){	struct mts_desc* to_remove = (struct mts_desc*)ptr;	MTS_DEBUG_GOT_HERE();	/* leave the list - lock it */	down(&mts_list_semaphore);	mts_remove_nolock(to_remove);	up(&mts_list_semaphore);}struct vendor_product{	char* name;	enum	{		mts_sup_unknown=0,		mts_sup_alpha,		mts_sup_full	}	support_status;} ;/* These are taken from the msmUSB.inf file on the Windows driver CD */const static struct vendor_product mts_supported_products[] ={	{ "Phantom 336CX",	mts_sup_unknown},	{ "Phantom 336CX",	mts_sup_unknown},	{ "Scanmaker X6",	mts_sup_alpha},	{ "Phantom C6",		mts_sup_unknown},	{ "Phantom 336CX",	mts_sup_unknown},	{ "ScanMaker V6USL",	mts_sup_unknown},	{ "ScanMaker V6USL",	mts_sup_unknown},	{ "Scanmaker V6UL",	mts_sup_unknown},	{ "Scanmaker V6UPL",	mts_sup_alpha},};/* The entries of microtek_table must correspond, line-by-line to   the entries of mts_supported_products[]. */static struct usb_device_id mts_usb_ids [] ={	{ USB_DEVICE(0x4ce, 0x0300) },	{ USB_DEVICE(0x5da, 0x0094) },	{ USB_DEVICE(0x5da, 0x0099) },	{ USB_DEVICE(0x5da, 0x009a) },	{ USB_DEVICE(0x5da, 0x00a0) },	{ USB_DEVICE(0x5da, 0x00a3) },	{ USB_DEVICE(0x5da, 0x80a3) },	{ USB_DEVICE(0x5da, 0x80ac) },	{ USB_DEVICE(0x5da, 0x00b6) },	{ }						/* Terminating entry */};MODULE_DEVICE_TABLE (usb, mts_usb_ids);static void * mts_usb_probe (struct usb_device *dev, unsigned int interface,			     const struct usb_device_id *id){	int i;	int result;	int ep_out = -1;	int ep_in_set[3]; /* this will break if we have more than three endpoints			   which is why we check */	int *ep_in_current = ep_in_set;	struct mts_desc * new_desc;	struct vendor_product const* p;	/* the altsettting 0 on the interface we're probing */	struct usb_interface_descriptor *altsetting;	MTS_DEBUG_GOT_HERE();	MTS_DEBUG( "usb-device descriptor at %x\n", (int)dev );	MTS_DEBUG( "product id = 0x%x, vendor id = 0x%x\n",		   (int)dev->descriptor.idProduct,		   (int)dev->descriptor.idVendor );	MTS_DEBUG_GOT_HERE();	p = &mts_supported_products[id - mts_usb_ids];	MTS_DEBUG_GOT_HERE();	MTS_DEBUG( "found model %s\n", p->name );	if ( p->support_status != mts_sup_full )		MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n",			     p->name );	/* the altsettting 0 on the interface we're probing */	altsetting =		&(dev->actconfig->interface[interface].altsetting[0]);	/* Check if the config is sane */	if ( altsetting->bNumEndpoints != MTS_EP_TOTAL ) {		MTS_WARNING( "expecting %d got %d endpoints! Bailing out.\n",			     (int)MTS_EP_TOTAL, (int)altsetting->bNumEndpoints );		return NULL;	}	for( i = 0; i < altsetting->bNumEndpoints; i++ ) {		if ((altsetting->endpoint[i].bmAttributes &		     USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {			MTS_WARNING( "can only deal with bulk endpoints; endpoint %d is not bulk.\n",			     (int)altsetting->endpoint[i].bEndpointAddress );		} else {			if (altsetting->endpoint[i].bEndpointAddress &			    USB_DIR_IN)				*ep_in_current++					= altsetting->endpoint[i].bEndpointAddress &					USB_ENDPOINT_NUMBER_MASK;			else {				if ( ep_out != -1 ) {					MTS_WARNING( "can only deal with one output endpoints. Bailing out." );					return NULL;				}				ep_out = altsetting->endpoint[i].bEndpointAddress &					USB_ENDPOINT_NUMBER_MASK;			}		}	}	if ( ep_out == -1 ) {		MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" );		return NULL;	}	/* I don't understand the following fully (it's from usb-storage) -- John */	/* set the interface -- STALL is an acceptable response here */	result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0);	MTS_DEBUG("usb_set_interface returned %d.\n",result);	switch( result )	{	case 0: /* no error */		break;			case -EPIPE:		usb_clear_halt(dev, usb_sndctrlpipe(dev, 0));		MTS_DEBUG( "clearing clearing stall on control interface\n" );		break;			default:		MTS_DEBUG( "unknown error %d from usb_set_interface\n",			(int)result ); 		return NULL;	}			/* allocating a new descriptor */	new_desc = (struct mts_desc *)kmalloc(sizeof(struct mts_desc), GFP_KERNEL);	if (new_desc == NULL)	{		MTS_ERROR("couldn't allocate scanner desc, bailing out!\n");		return NULL;	}	/* As done by usb_alloc_urb */	memset( new_desc, 0, sizeof(*new_desc) );	spin_lock_init(&new_desc->urb.lock);				/* initialising that descriptor */	new_desc->usb_dev = dev;	new_desc->interface = interface;	init_MUTEX(&new_desc->lock);	if(mts_list){		new_desc->host_number = mts_list->host_number+1;	} else {		new_desc->host_number = 0;	}		/* endpoints */		new_desc->ep_out = ep_out;	new_desc->ep_response = ep_in_set[0];	new_desc->ep_image = ep_in_set[1];	if ( new_desc->ep_out != MTS_EP_OUT )		MTS_WARNING( "will this work? Command EP is not usually %d\n",			     (int)new_desc->ep_out );	if ( new_desc->ep_response != MTS_EP_RESPONSE )		MTS_WARNING( "will this work? Response EP is not usually %d\n",			     (int)new_desc->ep_response );	if ( new_desc->ep_image != MTS_EP_IMAGE )		MTS_WARNING( "will this work? Image data EP is not usually %d\n",			     (int)new_desc->ep_image );	/* Initialize the host template based on the default one */	memcpy(&(new_desc->ctempl), &mts_scsi_host_template, sizeof(mts_scsi_host_template));	/* HACK from usb-storage - this is needed for scsi detection */	(struct mts_desc *)new_desc->ctempl.proc_dir = new_desc; /* FIXME */	MTS_DEBUG("registering SCSI module\n");	new_desc->ctempl.module = THIS_MODULE;	result = scsi_register_module(MODULE_SCSI_HA, &(new_desc->ctempl));	/* Will get hit back in microtek_detect by this func */	if ( result )	{		MTS_ERROR( "error %d from scsi_register_module! Help!\n",			   (int)result );		/* FIXME: need more cleanup? */		kfree( new_desc );		return NULL;	}	MTS_DEBUG_GOT_HERE();	/* FIXME: the bomb is armed, must the host be registered under lock ? */	/* join the list - lock it */	down(&mts_list_semaphore);	mts_add_nolock( new_desc );	up(&mts_list_semaphore);	MTS_DEBUG("completed probe and exiting happily\n");	return (void *)new_desc;}/* get us noticed by the rest of the kernel */int __init microtek_drv_init(void){	int result;	MTS_DEBUG_GOT_HERE();	init_MUTEX(&mts_list_semaphore);	if ((result = usb_register(&mts_usb_driver)) < 0) {		MTS_DEBUG("usb_register returned %d\n", result );		return -1;	} else {		MTS_DEBUG("driver registered.\n");	}	info(DRIVER_VERSION ":" DRIVER_DESC);	return 0;}void __exit microtek_drv_exit(void){	struct mts_desc* next;	MTS_DEBUG_GOT_HERE();	usb_deregister(&mts_usb_driver);	down(&mts_list_semaphore);	while (mts_list) {		/* keep track of where the next one is */		next = mts_list->next;		mts_remove_nolock( mts_list );		/* advance the list pointer */		mts_list = next;	}	up(&mts_list_semaphore);}module_init(microtek_drv_init);module_exit(microtek_drv_exit);MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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