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

📄 microtek.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
					   context->instance->ep_response),			   context->scsi_status,			   1,			   mts_transfer_done );}static void mts_data_done( struct urb* transfer, struct pt_regs *regs )/* Interrupt context! */{	MTS_INT_INIT();	if ( context->data_length != transfer->actual_length ) {		context->srb->resid = context->data_length - transfer->actual_length;	} else if ( unlikely(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, struct pt_regs *regs )/* Interrupt context! */{	MTS_INT_INIT();	if ( unlikely(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 occurred */			MTS_DEBUG_GOT_HERE();		        context->srb->result = DID_ERROR<<16;                }		mts_transfer_cleanup(transfer);		return;	}	if (context->srb->cmnd[0] == REQUEST_SENSE) {		mts_int_submit_urb(transfer,				   context->data_pipe,				   context->srb->sense_buffer,				   context->data_length,				   mts_data_done);	} else { if ( context->data ) {			mts_int_submit_urb(transfer,					   context->data_pipe,					   context->data,					   context->data_length,					   context->srb->use_sg > 1 ? mts_do_sg : mts_data_done);		} else {			mts_get_status(transfer);		}	}	return;}static void mts_do_sg (struct urb* transfer, struct pt_regs *regs){	struct scatterlist * sg;	MTS_INT_INIT();	MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg);	if (unlikely(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,			   page_address(sg[context->fragment].page) +			   sg[context->fragment].offset,			   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 = NULL;			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 = page_address(sg[0].page) + sg[0].offset;		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->device->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(likely(callback != NULL))			callback(srb);		goto out;	}		usb_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;		/* here we need ATOMIC as we are called with the iolock */	res=usb_submit_urb(desc->urb, GFP_ATOMIC);	if(unlikely(res)){		MTS_ERROR("error %d submitting URB\n",(int)res);		srb->result = DID_ERROR << 16;		if(likely(callback != NULL))			callback(srb);	}out:	return err;}static struct scsi_host_template mts_scsi_host_template = {	.module			= THIS_MODULE,	.name			= "microtekX6",	.proc_name		= "microtekX6",	.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,	.use_clustering =	1,	.emulated =		1,	.slave_alloc =		mts_slave_alloc,	.slave_configure =	mts_slave_configure,	.max_sectors=		256, /* 128 K */};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 int mts_usb_probe(struct usb_interface *intf,			 const struct usb_device_id *id){	int i;	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;	int err_retval = -ENOMEM;	struct mts_desc * new_desc;	struct vendor_product const* p;	struct usb_device *dev = interface_to_usbdev (intf);	/* the current altsetting on the interface we're probing */	struct usb_host_interface *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",		   le16_to_cpu(dev->descriptor.idProduct),		   le16_to_cpu(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 current altsetting on the interface we're probing */	altsetting = intf->cur_altsetting;	/* Check if the config is sane */	if ( altsetting->desc.bNumEndpoints != MTS_EP_TOTAL ) {		MTS_WARNING( "expecting %d got %d endpoints! Bailing out.\n",			     (int)MTS_EP_TOTAL, (int)altsetting->desc.bNumEndpoints );		return -ENODEV;	}	for( i = 0; i < altsetting->desc.bNumEndpoints; i++ ) {		if ((altsetting->endpoint[i].desc.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].desc.bEndpointAddress );		} else {			if (altsetting->endpoint[i].desc.bEndpointAddress &			    USB_DIR_IN)				*ep_in_current++					= altsetting->endpoint[i].desc.bEndpointAddress &					USB_ENDPOINT_NUMBER_MASK;			else {				if ( ep_out != -1 ) {					MTS_WARNING( "can only deal with one output endpoints. Bailing out." );					return -ENODEV;				}				ep_out = altsetting->endpoint[i].desc.bEndpointAddress &					USB_ENDPOINT_NUMBER_MASK;			}		}	}	if ( ep_out == -1 ) {		MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" );		return -ENODEV;	}	new_desc = kzalloc(sizeof(struct mts_desc), GFP_KERNEL);	if (!new_desc)		goto out;	new_desc->urb = usb_alloc_urb(0, GFP_KERNEL);	if (!new_desc->urb)		goto out_kfree;	new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL);	if (!new_desc->context.scsi_status)		goto out_kfree2;	new_desc->usb_dev = dev;	new_desc->usb_intf = intf;	init_MUTEX(&new_desc->lock);	/* 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 );	new_desc->host = scsi_host_alloc(&mts_scsi_host_template,			sizeof(new_desc));	if (!new_desc->host)		goto out_free_urb;	new_desc->host->hostdata[0] = (unsigned long)new_desc;	if (scsi_add_host(new_desc->host, NULL)) {		err_retval = -EIO;		goto out_free_urb;	}	scsi_scan_host(new_desc->host);	usb_set_intfdata(intf, new_desc);	return 0; out_kfree2:	kfree(new_desc->context.scsi_status); out_free_urb:	usb_free_urb(new_desc->urb); out_kfree:	kfree(new_desc); out:	return err_retval;}static void mts_usb_disconnect (struct usb_interface *intf){	struct mts_desc *desc = usb_get_intfdata(intf);	usb_set_intfdata(intf, NULL);	usb_kill_urb(desc->urb);	scsi_remove_host(desc->host);	scsi_host_put(desc->host);	usb_free_urb(desc->urb);	kfree(desc->context.scsi_status);	kfree(desc);}static int __init microtek_drv_init(void){	return usb_register(&mts_usb_driver);}static void __exit microtek_drv_exit(void){	usb_deregister(&mts_usb_driver);}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 + -