Linux 2.4.0-test9pre4
[davej-history.git] / drivers / usb / microtek.c
blobab37860cd4aaadff632ce5db2ece8baf09247552
1 /* Driver for Microtek Scanmaker X6 USB scanner, and possibly others.
3 * (C) Copyright 2000 John Fremlin <vii@penguinpowered.com>
4 * (C) Copyright 2000 Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>
6 * Parts shamelessly stolen from usb-storage and copyright by their
7 * authors. Thanks to Matt Dharm for giving us permission!
9 * This driver implements a SCSI host controller driver and a USB
10 * device driver. To avoid confusion, all the USB related stuff is
11 * prefixed by mts_usb_ and all the SCSI stuff by mts_scsi_.
13 * Microtek (www.microtek.com) did not release the specifications for
14 * their USB protocol to us, so we had to reverse engineer them. We
15 * don't know for which models they are valid.
17 * The X6 USB has three bulk endpoints, one output (0x1) down which
18 * commands and outgoing data are sent, and two input: 0x82 from which
19 * normal data is read from the scanner (in packets of maximum 32
20 * bytes) and from which the status byte is read, and 0x83 from which
21 * the results of a scan (or preview) are read in up to 64 * 1024 byte
22 * chunks by the Windows driver. We don't know how much it is possible
23 * to read at a time from 0x83.
25 * It seems possible to read (with URB transfers) everything from 0x82
26 * in one go, without bothering to read in 32 byte chunks.
28 * There seems to be an optimisation of a further READ implicit if
29 * you simply read from 0x83.
31 * Guessed protocol:
33 * Send raw SCSI command to EP 0x1
35 * If there is data to receive:
36 * If the command was READ datatype=image:
37 * Read a lot of data from EP 0x83
38 * Else:
39 * Read data from EP 0x82
40 * Else:
41 * If there is data to transmit:
42 * Write it to EP 0x1
44 * Read status byte from EP 0x82
46 * References:
48 * The SCSI command set for the scanner is available from
49 * ftp://ftp.microtek.com/microtek/devpack/
51 * Microtek NV sent us a more up to date version of the document. If
52 * you want it, just send mail.
54 * Status:
56 * Untested with multiple scanners.
57 * Untested on SMP.
58 * Untested on a bigendian machine.
60 * History:
62 * 20000417 starting history
63 * 20000417 fixed load oops
64 * 20000417 fixed unload oops
65 * 20000419 fixed READ IMAGE detection
66 * 20000424 started conversion to use URBs
67 * 20000502 handled short transfers as errors
68 * 20000513 rename and organisation of functions (john)
69 * 20000513 added IDs for all products supported by Windows driver (john)
70 * 20000514 Rewrote mts_scsi_queuecommand to use URBs (john)
71 * 20000514 Version 0.0.8j
72 * 20000514 Fix reporting of non-existant devices to SCSI layer (john)
73 * 20000514 Added MTS_DEBUG_INT (john)
74 * 20000514 Changed "usb-microtek" to "microtek" for consistency (john)
75 * 20000514 Stupid bug fixes (john)
76 * 20000514 Version 0.0.9j
77 * 20000515 Put transfer context and URB in mts_desc (john)
78 * 20000515 Added prelim turn off debugging support (john)
79 * 20000515 Version 0.0.10j
80 * 20000515 Fixed up URB allocation (clear URB on alloc) (john)
81 * 20000515 Version 0.0.11j
82 * 20000516 Removed unnecessary spinlock in mts_transfer_context (john)
83 * 20000516 Removed unnecessary up on instance lock in mts_remove_nolock (john)
84 * 20000516 Implemented (badly) scsi_abort (john)
85 * 20000516 Version 0.0.12j
86 * 20000517 Hopefully removed mts_remove_nolock quasideadlock (john)
87 * 20000517 Added mts_debug_dump to print ll USB info (john)
88 * 20000518 Tweaks and documentation updates (john)
89 * 20000518 Version 0.0.13j
90 * 20000518 Cleaned up abort handling (john)
91 * 20000523 Removed scsi_command and various scsi_..._resets (john)
92 * 20000523 Added unlink URB on scsi_abort, now OHCI supports it (john)
93 * 20000523 Fixed last tiresome compile warning (john)
94 * 20000523 Version 0.0.14j (though version 0.1 has come out?)
95 * 20000602 Added primitive reset
96 * 20000602 Version 0.2.0
97 * 20000603 various cosmetic changes
98 * 20000603 Version 0.2.1
99 * 20000620 minor cosmetic changes
100 * 20000620 Version 0.2.2
101 * 20000822 Hopefully fixed deadlock in mts_remove_nolock()
102 * 20000822 Fixed minor race in mts_transfer_cleanup()
103 * 20000822 Fixed deadlock on submission error in queuecommand
104 * 20000822 Version 0.2.3
105 * 20000913 Reduced module size if debugging is off
106 * 20000913 Version 0.2.4
109 #include <linux/module.h>
110 #include <linux/kernel.h>
111 #include <linux/sched.h>
112 #include <linux/signal.h>
113 #include <linux/errno.h>
114 #include <linux/random.h>
115 #include <linux/poll.h>
116 #include <linux/init.h>
117 #include <linux/malloc.h>
118 #include <linux/spinlock.h>
119 #include <linux/smp_lock.h>
120 #include <linux/usb.h>
121 #include <linux/proc_fs.h>
123 #include <asm/atomic.h>
124 #include <linux/blk.h>
125 #include"../scsi/scsi.h"
126 #include"../scsi/hosts.h"
127 #include"../scsi/sd.h"
129 #include"microtek.h"
131 /* Constants */
133 #define MTS_ABORT_TIMEOUT HZ/*jiffies*/
136 /* Should we do debugging? */
138 // #define MTS_DO_DEBUG
141 /* USB layer driver interface */
143 static void*mts_usb_probe(struct usb_device *dev,unsigned int interface);
144 static voidmts_usb_disconnect(struct usb_device *dev,void*ptr);
146 static struct usb_driver mts_usb_driver = {
147 "microtek",
148 mts_usb_probe,
149 mts_usb_disconnect,
150 { NULL, NULL }/* we need no fops. let gcc fill it */
154 /* Internal driver stuff */
156 #define MTS_VERSION"0.2.4"
157 #define MTS_NAME"microtek usb (rev " MTS_VERSION"): "
159 #define MTS_WARNING(x...) \
160 printk( KERN_WARNING MTS_NAME x )
161 #define MTS_ERROR(x...) \
162 printk( KERN_ERR MTS_NAME x )
163 #define MTS_INT_ERROR(x...) \
164 MTS_ERROR(x)
165 #define MTS_MESSAGE(x...) \
166 printk( KERN_INFO MTS_NAME x )
168 #if defined MTS_DO_DEBUG
170 #define MTS_DEBUG(x...) \
171 printk( KERN_DEBUG MTS_NAME x )
173 #define MTS_DEBUG_GOT_HERE() \
174 MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __PRETTY_FUNCTION__ )
175 #define MTS_DEBUG_INT() \
176 do { MTS_DEBUG_GOT_HERE(); \
177 MTS_DEBUG("transfer = %x context = %x\n",(int)transfer,(int)context ); \
178 MTS_DEBUG("status = %x data-length = %x sent = %x\n",(int)transfer->status,(int)context->data_length, (int)transfer->actual_length ); \
179 mts_debug_dump(context->instance);\
180 } while(0)
181 #else
183 #define MTS_NUL_STATEMENT do { } while(0)
185 #define MTS_DEBUG(x...) MTS_NUL_STATEMENT
186 #define MTS_DEBUG_GOT_HERE() MTS_NUL_STATEMENT
187 #define MTS_DEBUG_INT() MTS_NUL_STATEMENT
189 #endif
193 #define MTS_INT_INIT()\
194 do {\
195 context = (struct mts_transfer_context*)transfer->context; \
196 if (atomic_read(&context->do_abort)) {\
197 mts_transfer_cleanup(transfer);\
198 return;\
200 MTS_DEBUG_INT();\
201 } while (0)
203 #ifdef MTS_DO_DEBUG
205 staticinlinevoidmts_debug_dump(struct mts_desc* desc) {
206 MTS_DEBUG("desc at 0x%x: halted = %x%x, toggle = %x%x\n",
207 (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0],
208 (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0]
210 MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n",
211 usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
212 usb_rcvbulkpipe(desc->usb_dev,desc->ep_response),
213 usb_rcvbulkpipe(desc->usb_dev,desc->ep_image)
218 staticinlinevoidmts_show_command(Scsi_Cmnd *srb)
220 char*what = NULL;
222 switch(srb->cmnd[0]) {
223 case TEST_UNIT_READY: what ="TEST_UNIT_READY";break;
224 case REZERO_UNIT: what ="REZERO_UNIT";break;
225 case REQUEST_SENSE: what ="REQUEST_SENSE";break;
226 case FORMAT_UNIT: what ="FORMAT_UNIT";break;
227 case READ_BLOCK_LIMITS: what ="READ_BLOCK_LIMITS";break;
228 case REASSIGN_BLOCKS: what ="REASSIGN_BLOCKS";break;
229 case READ_6: what ="READ_6";break;
230 case WRITE_6: what ="WRITE_6";break;
231 case SEEK_6: what ="SEEK_6";break;
232 case READ_REVERSE: what ="READ_REVERSE";break;
233 case WRITE_FILEMARKS: what ="WRITE_FILEMARKS";break;
234 case SPACE: what ="SPACE";break;
235 case INQUIRY: what ="INQUIRY";break;
236 case RECOVER_BUFFERED_DATA: what ="RECOVER_BUFFERED_DATA";break;
237 case MODE_SELECT: what ="MODE_SELECT";break;
238 case RESERVE: what ="RESERVE";break;
239 case RELEASE: what ="RELEASE";break;
240 case COPY: what ="COPY";break;
241 case ERASE: what ="ERASE";break;
242 case MODE_SENSE: what ="MODE_SENSE";break;
243 case START_STOP: what ="START_STOP";break;
244 case RECEIVE_DIAGNOSTIC: what ="RECEIVE_DIAGNOSTIC";break;
245 case SEND_DIAGNOSTIC: what ="SEND_DIAGNOSTIC";break;
246 case ALLOW_MEDIUM_REMOVAL: what ="ALLOW_MEDIUM_REMOVAL";break;
247 case SET_WINDOW: what ="SET_WINDOW";break;
248 case READ_CAPACITY: what ="READ_CAPACITY";break;
249 case READ_10: what ="READ_10";break;
250 case WRITE_10: what ="WRITE_10";break;
251 case SEEK_10: what ="SEEK_10";break;
252 case WRITE_VERIFY: what ="WRITE_VERIFY";break;
253 case VERIFY: what ="VERIFY";break;
254 case SEARCH_HIGH: what ="SEARCH_HIGH";break;
255 case SEARCH_EQUAL: what ="SEARCH_EQUAL";break;
256 case SEARCH_LOW: what ="SEARCH_LOW";break;
257 case SET_LIMITS: what ="SET_LIMITS";break;
258 case READ_POSITION: what ="READ_POSITION";break;
259 case SYNCHRONIZE_CACHE: what ="SYNCHRONIZE_CACHE";break;
260 case LOCK_UNLOCK_CACHE: what ="LOCK_UNLOCK_CACHE";break;
261 case READ_DEFECT_DATA: what ="READ_DEFECT_DATA";break;
262 case MEDIUM_SCAN: what ="MEDIUM_SCAN";break;
263 case COMPARE: what ="COMPARE";break;
264 case COPY_VERIFY: what ="COPY_VERIFY";break;
265 case WRITE_BUFFER: what ="WRITE_BUFFER";break;
266 case READ_BUFFER: what ="READ_BUFFER";break;
267 case UPDATE_BLOCK: what ="UPDATE_BLOCK";break;
268 case READ_LONG: what ="READ_LONG";break;
269 case WRITE_LONG: what ="WRITE_LONG";break;
270 case CHANGE_DEFINITION: what ="CHANGE_DEFINITION";break;
271 case WRITE_SAME: what ="WRITE_SAME";break;
272 case READ_TOC: what ="READ_TOC";break;
273 case LOG_SELECT: what ="LOG_SELECT";break;
274 case LOG_SENSE: what ="LOG_SENSE";break;
275 case MODE_SELECT_10: what ="MODE_SELECT_10";break;
276 case MODE_SENSE_10: what ="MODE_SENSE_10";break;
277 case MOVE_MEDIUM: what ="MOVE_MEDIUM";break;
278 case READ_12: what ="READ_12";break;
279 case WRITE_12: what ="WRITE_12";break;
280 case WRITE_VERIFY_12: what ="WRITE_VERIFY_12";break;
281 case SEARCH_HIGH_12: what ="SEARCH_HIGH_12";break;
282 case SEARCH_EQUAL_12: what ="SEARCH_EQUAL_12";break;
283 case SEARCH_LOW_12: what ="SEARCH_LOW_12";break;
284 case READ_ELEMENT_STATUS: what ="READ_ELEMENT_STATUS";break;
285 case SEND_VOLUME_TAG: what ="SEND_VOLUME_TAG";break;
286 case WRITE_LONG_2: what ="WRITE_LONG_2";break;
287 default:
288 MTS_DEBUG("can't decode command\n");
289 goto out;
290 break;
292 MTS_DEBUG("Command %s (%d bytes)\n", what, srb->cmd_len);
294 out:
295 MTS_DEBUG(" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
296 srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5],
297 srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]);
300 #else
302 staticinlinevoidmts_show_command(Scsi_Cmnd *srb)
304 while(0) {}
307 staticinlinevoidmts_debug_dump(struct mts_desc* desc)
309 while(0) {}
312 #endif
317 staticinlineintmts_is_aborting(struct mts_desc* desc) {
318 return(atomic_read(&desc->context.do_abort));
321 staticinlinevoidmts_request_abort(struct mts_desc* desc) {
322 MTS_DEBUG_GOT_HERE();
323 mts_debug_dump(desc);
324 atomic_set(&desc->context.do_abort,1);
327 staticinlinevoidmts_urb_abort(struct mts_desc* desc) {
328 MTS_DEBUG_GOT_HERE();
329 mts_debug_dump(desc);
330 if( desc->urb.status == USB_ST_URB_PENDING ) {
331 usb_unlink_urb( &desc->urb );
335 staticinlinevoidmts_wait_abort(struct mts_desc* desc)
337 mts_request_abort(desc);
339 while( !atomic_read(&desc->lock.count) ) {
340 /* Is there a function to check if the semaphore is locked? */
341 schedule_timeout( MTS_ABORT_TIMEOUT );
342 MTS_DEBUG_GOT_HERE();
343 mts_urb_abort(desc);
349 static struct mts_desc * mts_list;/* list of active scanners */
350 struct semaphore mts_list_semaphore;
352 /* Internal list operations */
354 static
355 voidmts_remove_nolock(struct mts_desc* to_remove )
357 MTS_DEBUG("removing 0x%x from list\n",
358 (int)to_remove );
360 lock_kernel();
361 mts_wait_abort(to_remove);
363 MTS_DEBUG_GOT_HERE();
365 if( to_remove != mts_list ) {
366 MTS_DEBUG_GOT_HERE();
367 if(to_remove->prev && to_remove->next)
368 to_remove->prev->next = to_remove->next;
369 }else{
370 MTS_DEBUG_GOT_HERE();
371 mts_list = to_remove->next;
372 if(mts_list) {
373 MTS_DEBUG_GOT_HERE();
374 mts_list->prev =0;
378 if( to_remove->next ) {
379 MTS_DEBUG_GOT_HERE();
380 to_remove->next->prev = to_remove->prev;
383 MTS_DEBUG_GOT_HERE();
384 scsi_unregister_module(MODULE_SCSI_HA, &(to_remove->ctempl));
385 unlock_kernel();
387 kfree( to_remove );
390 static
391 voidmts_add_nolock(struct mts_desc* to_add )
393 MTS_DEBUG("adding 0x%x to list\n", (int)to_add );
395 to_add->prev =0;
396 to_add->next = mts_list;
397 if( mts_list ) {
398 mts_list->prev = to_add;
401 mts_list = to_add;
407 /* SCSI driver interface */
409 /* scsi related functions - dummies for now mostly */
411 static intmts_scsi_release(struct Scsi_Host *psh)
413 MTS_DEBUG_GOT_HERE();
415 return0;
418 static intmts_scsi_abort(Scsi_Cmnd *srb)
419 /* interrupt context (!) *//* FIXME this is about to become task context */
421 struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
423 MTS_DEBUG_GOT_HERE();
425 mts_request_abort(desc);
426 mts_urb_abort(desc);
428 return SCSI_ABORT_PENDING;
431 static intmts_scsi_host_reset(Scsi_Cmnd *srb)
433 struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
435 MTS_DEBUG_GOT_HERE();
436 mts_debug_dump(desc);
438 usb_reset_device(desc->usb_dev);/*FIXME: untested on new reset code */
439 return0;/* RANT why here 0 and not SUCCESS */
442 /* the core of the scsi part */
444 /* faking a detection - which can't fail :-) */
446 static intmts_scsi_detect(struct SHT * sht)
448 /* Whole function stolen from usb-storage */
450 struct mts_desc * desc = (struct mts_desc *)sht->proc_dir;
451 /* What a hideous hack! */
453 char local_name[48];
455 MTS_DEBUG_GOT_HERE();
457 /* set up the name of our subdirectory under /proc/scsi/ */
458 sprintf(local_name,"microtek-%d", desc->host_number);
459 sht->proc_name =kmalloc(strlen(local_name) +1, GFP_KERNEL);
460 /* FIXME: where is this freed ? */
462 if(!sht->proc_name) {
463 MTS_ERROR("unable to allocate memory for proc interface!!\n");
464 return0;
467 strcpy(sht->proc_name, local_name);
469 sht->proc_dir = NULL;
471 /* In host->hostdata we store a pointer to desc */
472 desc->host =scsi_register(sht,sizeof(desc));
473 desc->host->hostdata[0] = (unsigned long)desc;
474 /* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */
476 return1;
481 /* Main entrypoint: SCSI commands are dispatched to here */
485 static
486 intmts_scsi_queuecommand(Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
488 static voidmts_transfer_cleanup(struct urb *transfer );
491 inlinestatic
492 voidmts_int_submit_urb(struct urb* transfer,
493 int pipe,
494 void* data,
495 unsigned length,
496 mts_usb_urb_callback callback )
497 /* Interrupt context! */
499 /* Holding transfer->context->lock! */
501 int res;
502 struct mts_transfer_context* context;
504 MTS_INT_INIT();
506 FILL_BULK_URB(transfer,
507 context->instance->usb_dev,
508 pipe,
509 data,
510 length,
511 callback,
512 context
515 /* transfer->transfer_flags = USB_DISABLE_SPD;*/
516 transfer->transfer_flags = USB_ASYNC_UNLINK;
517 transfer->status =0;
518 transfer->timeout =100;
520 res =usb_submit_urb( transfer );
521 if( res ) {
522 MTS_INT_ERROR("could not submit URB! Error was %d\n",(int)res );
523 context->srb->result = DID_ERROR <<16;
524 context->state = mts_con_error;
525 mts_transfer_cleanup(transfer);
527 return;
531 static voidmts_transfer_cleanup(struct urb *transfer )
532 /* Interrupt context! */
534 struct mts_transfer_context* context = (struct mts_transfer_context*)transfer->context;
536 if( context->final_callback )
537 context->final_callback(context->srb);
538 up( &context->instance->lock );
542 static voidmts_transfer_done(struct urb *transfer )
544 struct mts_transfer_context* context;
546 MTS_INT_INIT();
548 context->srb->result &= MTS_SCSI_ERR_MASK;
549 context->srb->result |= (unsigned)context->status<<1;
551 mts_transfer_cleanup(transfer);
553 return;
557 static voidmts_get_status(struct urb *transfer )
558 /* Interrupt context! */
560 struct mts_transfer_context* context;
562 MTS_INT_INIT();
564 context->state = mts_con_status;
566 mts_int_submit_urb(transfer,
567 usb_rcvbulkpipe(context->instance->usb_dev,
568 context->instance->ep_response),
569 &context->status,
571 mts_transfer_done );
574 return;
577 static voidmts_data_done(struct urb* transfer )
578 /* Interrupt context! */
580 struct mts_transfer_context* context;
582 MTS_INT_INIT();
584 if( context->data_length != transfer->actual_length ) {
585 context->srb->resid = context->data_length - transfer->actual_length;
586 }else if( transfer->status ) {
587 context->srb->result = DID_ERROR<<16;
590 mts_get_status(transfer);
592 return;
596 static voidmts_command_done(struct urb *transfer )
597 /* Interrupt context! */
599 struct mts_transfer_context* context;
601 MTS_INT_INIT();
603 if( transfer->status ) {
604 context->srb->result = DID_ERROR<<16;
605 mts_transfer_cleanup(transfer);
607 return;
610 if( context->data ) {
611 context->state = mts_con_data;
612 mts_int_submit_urb(transfer,
613 context->data_pipe,
614 context->data,
615 context->data_length,
616 mts_data_done);
617 }elsemts_get_status(transfer);
619 return;
624 static const u8 mts_read_image_sig[] = {0x28,00,00,00};
625 static const u8 mts_read_image_sig_len =4;
626 static const unsigned char mts_direction[256/8] = {
627 0x28,0x81,0x14,0x14,0x20,0x01,0x90,0x77,
628 0x0C,0x20,0x00,0x04,0x00,0x00,0x00,0x00,
629 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
630 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
634 #define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1)
636 static void
637 mts_build_transfer_context( Scsi_Cmnd *srb,struct mts_desc* desc )
640 int pipe;
643 MTS_DEBUG_GOT_HERE();
645 desc->context.instance = desc;
646 desc->context.srb = srb;
647 desc->context.state = mts_con_command;
648 atomic_set(&desc->context.do_abort,0);
650 if( !srb->bufflen ){
651 desc->context.data =0;
652 desc->context.data_length =0;
653 return;
654 }else{
655 desc->context.data = srb->buffer;
656 desc->context.data_length = srb->bufflen;
659 /* can't rely on srb->sc_data_direction */
661 /* Brutally ripped from usb-storage */
663 if( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len )
664 ) { pipe =usb_rcvbulkpipe(desc->usb_dev,desc->ep_image);
665 MTS_DEBUG("transfering from desc->ep_image == %d\n",
666 (int)desc->ep_image );
667 }else if(MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) {
668 pipe =usb_rcvbulkpipe(desc->usb_dev,desc->ep_response);
669 MTS_DEBUG("transfering from desc->ep_response == %d\n",
670 (int)desc->ep_response);
671 }else{
672 MTS_DEBUG("transfering to desc->ep_out == %d\n",
673 (int)desc->ep_out);
674 pipe =usb_sndbulkpipe(desc->usb_dev,desc->ep_out);
676 desc->context.data_pipe = pipe;
680 static
681 intmts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
683 struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
684 int err =0;
685 int res;
687 MTS_DEBUG_GOT_HERE();
688 mts_show_command(srb);
689 mts_debug_dump(desc);
691 if( srb->device->lun || srb->device->id || srb->device->channel ) {
693 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 );
695 MTS_DEBUG("this device doesn't exist\n");
697 srb->result = DID_BAD_TARGET <<16;
699 if(callback)
700 callback(srb);
702 goto out;
705 down(&desc->lock);
707 MTS_DEBUG_GOT_HERE();
708 mts_show_command(srb);
711 FILL_BULK_URB(&desc->urb,
712 desc->usb_dev,
713 usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
714 srb->cmnd,
715 srb->cmd_len,
716 mts_command_done,
717 &desc->context
721 mts_build_transfer_context( srb, desc );
722 desc->context.final_callback = callback;
723 desc->urb.timeout =100;
724 desc->urb.transfer_flags = USB_ASYNC_UNLINK;
726 /* desc->urb.transfer_flags = USB_DISABLE_SPD;*/
728 res=usb_submit_urb(&desc->urb);
730 if(res){
731 MTS_ERROR("error %d submitting URB\n",(int)res);
732 srb->result = DID_ERROR <<16;
734 if(callback)
735 callback(srb);
736 up(&desc->lock);/* no further cleanup is done */
738 goto out;
741 MTS_DEBUG_GOT_HERE();
743 out:
744 return err;
747 * this defines our 'host'
750 /* NOTE: This is taken from usb-storage, should be right. */
753 static Scsi_Host_Template mts_scsi_host_template = {
754 name:"microtek",
755 detect: mts_scsi_detect,
756 release: mts_scsi_release,
757 command:0,
758 queuecommand: mts_scsi_queuecommand,
760 eh_abort_handler: mts_scsi_abort,
761 eh_device_reset_handler:0,
762 eh_bus_reset_handler:0,
763 eh_host_reset_handler: mts_scsi_host_reset,
765 can_queue:1,
766 this_id: -1,
767 cmd_per_lun:1,
768 present:0,
769 unchecked_isa_dma: FALSE,
770 use_clustering: FALSE,
771 use_new_eh_code: TRUE,
772 emulated: TRUE
776 /* USB layer driver interface implementation */
778 static voidmts_usb_disconnect(struct usb_device *dev,void*ptr)
780 struct mts_desc* to_remove = (struct mts_desc*)ptr;
782 MTS_DEBUG_GOT_HERE();
784 /* leave the list - lock it */
785 down(&mts_list_semaphore);
787 mts_remove_nolock(to_remove);
789 up(&mts_list_semaphore);
792 struct vendor_product
794 u16 idVendor;
795 u16 idProduct;
796 char* name;
797 enum
799 mts_sup_unknown=0,
800 mts_sup_alpha,
801 mts_sup_full
803 support_status;
807 /* These are taken from the msmUSB.inf file on the Windows driver CD */
808 const static struct vendor_product mts_supported_products[] =
811 0x4ce,0x300,"Phantom 336CX",mts_sup_unknown
814 0x5da,0x94,"Phantom 336CX",mts_sup_unknown
817 0x5da,0x99,"Scanmaker X6",mts_sup_alpha
820 0x5da,0x9a,"Phantom C6",mts_sup_unknown
823 0x5da,0xa0,"Phantom 336CX",mts_sup_unknown
826 0x5da,0xa3,"ScanMaker V6USL",mts_sup_unknown
829 0x5da,0x80a3,"ScanMaker V6USL",mts_sup_unknown
832 0x5da,0x80ac,"Scanmaker V6UL",mts_sup_unknown
836 const static struct vendor_product* mts_last_product = &mts_supported_products[sizeof(mts_supported_products) /sizeof(struct vendor_product) ];
837 /* Must never be derefed, points to one after last entry */
840 static void*mts_usb_probe(struct usb_device *dev,unsigned int interface)
842 int i;
843 int result;
844 int ep_out = -1;
845 int ep_in_set[3];/* this will break if we have more than three endpoints
846 which is why we check */
847 int*ep_in_current = ep_in_set;
849 struct mts_desc * new_desc;
850 struct vendor_product const* p;
852 /* the altsettting 0 on the interface we're probing */
853 struct usb_interface_descriptor *altsetting;
855 MTS_DEBUG_GOT_HERE();
856 MTS_DEBUG("usb-device descriptor at %x\n", (int)dev );
858 MTS_DEBUG("product id = 0x%x, vendor id = 0x%x\n",
859 (int)dev->descriptor.idProduct,
860 (int)dev->descriptor.idVendor );
862 MTS_DEBUG_GOT_HERE();
864 /* checking IDs */
865 for( p = mts_supported_products; p != mts_last_product; p++ )
866 if( dev->descriptor.idVendor == p->idVendor &&
867 dev->descriptor.idProduct == p->idProduct )
868 goto is_supported;
869 else
870 MTS_DEBUG("doesn't appear to be model %s\n", p->name );
872 MTS_DEBUG("returning NULL: unsupported\n");
874 return NULL;
876 is_supported:
878 MTS_DEBUG_GOT_HERE();
880 MTS_DEBUG("found model %s\n", p->name );
881 if( p->support_status != mts_sup_full )
882 MTS_MESSAGE("model %s is not known to be fully supported, reports welcome!\n",
883 p->name );
885 /* the altsettting 0 on the interface we're probing */
886 altsetting =
887 &(dev->actconfig->interface[interface].altsetting[0]);
890 /* Check if the config is sane */
892 if( altsetting->bNumEndpoints != MTS_EP_TOTAL ) {
893 MTS_WARNING("expecting %d got %d endpoints! Bailing out.\n",
894 (int)MTS_EP_TOTAL, (int)altsetting->bNumEndpoints );
895 return NULL;
898 for( i =0; i < altsetting->bNumEndpoints; i++ ) {
899 if((altsetting->endpoint[i].bmAttributes &
900 USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {
902 MTS_WARNING("can only deal with bulk endpoints; endpoint %d is not bulk.\n",
903 (int)altsetting->endpoint[i].bEndpointAddress );
904 }else{
905 if(altsetting->endpoint[i].bEndpointAddress &
906 USB_DIR_IN)
907 *ep_in_current++
908 = altsetting->endpoint[i].bEndpointAddress &
909 USB_ENDPOINT_NUMBER_MASK;
910 else{
911 if( ep_out != -1) {
912 MTS_WARNING("can only deal with one output endpoints. Bailing out.");
913 return NULL;
916 ep_out = altsetting->endpoint[i].bEndpointAddress &
917 USB_ENDPOINT_NUMBER_MASK;
924 if( ep_out == -1) {
925 MTS_WARNING("couldn't find an output bulk endpoint. Bailing out.\n");
926 return NULL;
930 /* I don't understand the following fully (it's from usb-storage) -- John */
932 /* set the interface -- STALL is an acceptable response here */
933 result =usb_set_interface(dev, altsetting->bInterfaceNumber,0);
935 MTS_DEBUG("usb_set_interface returned %d.\n",result);
936 switch( result )
938 case0:/* no error */
939 break;
941 case-EPIPE:
942 usb_clear_halt(dev,usb_sndctrlpipe(dev,0));
943 MTS_DEBUG("clearing clearing stall on control interface\n");
944 break;
946 default:
947 MTS_DEBUG("unknown error %d from usb_set_interface\n",
948 (int)result );
949 return NULL;
953 /* allocating a new descriptor */
954 new_desc = (struct mts_desc *)kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
955 if(new_desc == NULL)
957 MTS_ERROR("couldn't allocate scanner desc, bailing out!\n");
958 return NULL;
961 /* As done by usb_alloc_urb */
962 memset( new_desc,0,sizeof(*new_desc) );
963 spin_lock_init(&new_desc->urb.lock);
966 /* initialising that descriptor */
967 new_desc->usb_dev = dev;
968 new_desc->interface = interface;
970 init_MUTEX(&new_desc->lock);
972 if(mts_list){
973 new_desc->host_number = mts_list->host_number+1;
974 }else{
975 new_desc->host_number =0;
978 /* endpoints */
980 new_desc->ep_out = ep_out;
981 new_desc->ep_response = ep_in_set[0];
982 new_desc->ep_image = ep_in_set[1];
985 if( new_desc->ep_out != MTS_EP_OUT )
986 MTS_WARNING("will this work? Command EP is not usually %d\n",
987 (int)new_desc->ep_out );
989 if( new_desc->ep_response != MTS_EP_RESPONSE )
990 MTS_WARNING("will this work? Response EP is not usually %d\n",
991 (int)new_desc->ep_response );
993 if( new_desc->ep_image != MTS_EP_IMAGE )
994 MTS_WARNING("will this work? Image data EP is not usually %d\n",
995 (int)new_desc->ep_image );
998 /* Initialize the host template based on the default one */
999 memcpy(&(new_desc->ctempl), &mts_scsi_host_template,sizeof(mts_scsi_host_template));
1000 /* HACK from usb-storage - this is needed for scsi detection */
1001 (struct mts_desc *)new_desc->ctempl.proc_dir = new_desc;/* FIXME */
1003 MTS_DEBUG("registering SCSI module\n");
1005 new_desc->ctempl.module = THIS_MODULE;
1006 result =scsi_register_module(MODULE_SCSI_HA, &(new_desc->ctempl));
1007 /* Will get hit back in microtek_detect by this func */
1008 if( result )
1010 MTS_ERROR("error %d from scsi_register_module! Help!\n",
1011 (int)result );
1013 /* FIXME: need more cleanup? */
1014 kfree( new_desc );
1015 return NULL;
1017 MTS_DEBUG_GOT_HERE();
1019 /* FIXME: the bomb is armed, must the host be registered under lock ? */
1020 /* join the list - lock it */
1021 down(&mts_list_semaphore);
1023 mts_add_nolock( new_desc );
1025 up(&mts_list_semaphore);
1028 MTS_DEBUG("completed probe and exiting happily\n");
1030 return(void*)new_desc;
1035 /* get us noticed by the rest of the kernel */
1037 int __init microtek_drv_init(void)
1039 int result;
1041 MTS_DEBUG_GOT_HERE();
1042 init_MUTEX(&mts_list_semaphore);
1044 if((result =usb_register(&mts_usb_driver)) <0) {
1045 MTS_DEBUG("usb_register returned %d\n", result );
1046 return-1;
1047 }else{
1048 MTS_DEBUG("driver registered.\n");
1051 return0;
1054 void __exit microtek_drv_exit(void)
1056 struct mts_desc* next;
1058 MTS_DEBUG_GOT_HERE();
1060 usb_deregister(&mts_usb_driver);
1062 down(&mts_list_semaphore);
1064 while(mts_list) {
1065 /* keep track of where the next one is */
1066 next = mts_list->next;
1068 mts_remove_nolock( mts_list );
1070 /* advance the list pointer */
1071 mts_list = next;
1074 up(&mts_list_semaphore);
1077 module_init(microtek_drv_init);
1078 module_exit(microtek_drv_exit);
1080 MODULE_AUTHOR("John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>");
1081 MODULE_DESCRIPTION("Microtek Scanmaker X6 USB scanner driver");
close