Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / usb / microtek.c
blobdaa18c88f77727f5f5548f2ae4784084f5addab9
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 const struct usb_device_id *id);
145 static voidmts_usb_disconnect(struct usb_device *dev,void*ptr);
147 static struct usb_device_id mts_usb_ids [];
149 static struct usb_driver mts_usb_driver = {
150 name:"microtek",
151 probe: mts_usb_probe,
152 disconnect: mts_usb_disconnect,
153 id_table: mts_usb_ids,
157 /* Internal driver stuff */
159 #define MTS_VERSION"0.2.4"
160 #define MTS_NAME"microtek usb (rev " MTS_VERSION"): "
162 #define MTS_WARNING(x...) \
163 printk( KERN_WARNING MTS_NAME x )
164 #define MTS_ERROR(x...) \
165 printk( KERN_ERR MTS_NAME x )
166 #define MTS_INT_ERROR(x...) \
167 MTS_ERROR(x)
168 #define MTS_MESSAGE(x...) \
169 printk( KERN_INFO MTS_NAME x )
171 #if defined MTS_DO_DEBUG
173 #define MTS_DEBUG(x...) \
174 printk( KERN_DEBUG MTS_NAME x )
176 #define MTS_DEBUG_GOT_HERE() \
177 MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __PRETTY_FUNCTION__ )
178 #define MTS_DEBUG_INT() \
179 do { MTS_DEBUG_GOT_HERE(); \
180 MTS_DEBUG("transfer = %x context = %x\n",(int)transfer,(int)context ); \
181 MTS_DEBUG("status = %x data-length = %x sent = %x\n",(int)transfer->status,(int)context->data_length, (int)transfer->actual_length ); \
182 mts_debug_dump(context->instance);\
183 } while(0)
184 #else
186 #define MTS_NUL_STATEMENT do { } while(0)
188 #define MTS_DEBUG(x...) MTS_NUL_STATEMENT
189 #define MTS_DEBUG_GOT_HERE() MTS_NUL_STATEMENT
190 #define MTS_DEBUG_INT() MTS_NUL_STATEMENT
192 #endif
196 #define MTS_INT_INIT()\
197 do {\
198 context = (struct mts_transfer_context*)transfer->context; \
199 if (atomic_read(&context->do_abort)) {\
200 mts_transfer_cleanup(transfer);\
201 return;\
203 MTS_DEBUG_INT();\
204 } while (0)
206 #ifdef MTS_DO_DEBUG
208 staticinlinevoidmts_debug_dump(struct mts_desc* desc) {
209 MTS_DEBUG("desc at 0x%x: halted = %x%x, toggle = %x%x\n",
210 (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0],
211 (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0]
213 MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n",
214 usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
215 usb_rcvbulkpipe(desc->usb_dev,desc->ep_response),
216 usb_rcvbulkpipe(desc->usb_dev,desc->ep_image)
221 staticinlinevoidmts_show_command(Scsi_Cmnd *srb)
223 char*what = NULL;
225 switch(srb->cmnd[0]) {
226 case TEST_UNIT_READY: what ="TEST_UNIT_READY";break;
227 case REZERO_UNIT: what ="REZERO_UNIT";break;
228 case REQUEST_SENSE: what ="REQUEST_SENSE";break;
229 case FORMAT_UNIT: what ="FORMAT_UNIT";break;
230 case READ_BLOCK_LIMITS: what ="READ_BLOCK_LIMITS";break;
231 case REASSIGN_BLOCKS: what ="REASSIGN_BLOCKS";break;
232 case READ_6: what ="READ_6";break;
233 case WRITE_6: what ="WRITE_6";break;
234 case SEEK_6: what ="SEEK_6";break;
235 case READ_REVERSE: what ="READ_REVERSE";break;
236 case WRITE_FILEMARKS: what ="WRITE_FILEMARKS";break;
237 case SPACE: what ="SPACE";break;
238 case INQUIRY: what ="INQUIRY";break;
239 case RECOVER_BUFFERED_DATA: what ="RECOVER_BUFFERED_DATA";break;
240 case MODE_SELECT: what ="MODE_SELECT";break;
241 case RESERVE: what ="RESERVE";break;
242 case RELEASE: what ="RELEASE";break;
243 case COPY: what ="COPY";break;
244 case ERASE: what ="ERASE";break;
245 case MODE_SENSE: what ="MODE_SENSE";break;
246 case START_STOP: what ="START_STOP";break;
247 case RECEIVE_DIAGNOSTIC: what ="RECEIVE_DIAGNOSTIC";break;
248 case SEND_DIAGNOSTIC: what ="SEND_DIAGNOSTIC";break;
249 case ALLOW_MEDIUM_REMOVAL: what ="ALLOW_MEDIUM_REMOVAL";break;
250 case SET_WINDOW: what ="SET_WINDOW";break;
251 case READ_CAPACITY: what ="READ_CAPACITY";break;
252 case READ_10: what ="READ_10";break;
253 case WRITE_10: what ="WRITE_10";break;
254 case SEEK_10: what ="SEEK_10";break;
255 case WRITE_VERIFY: what ="WRITE_VERIFY";break;
256 case VERIFY: what ="VERIFY";break;
257 case SEARCH_HIGH: what ="SEARCH_HIGH";break;
258 case SEARCH_EQUAL: what ="SEARCH_EQUAL";break;
259 case SEARCH_LOW: what ="SEARCH_LOW";break;
260 case SET_LIMITS: what ="SET_LIMITS";break;
261 case READ_POSITION: what ="READ_POSITION";break;
262 case SYNCHRONIZE_CACHE: what ="SYNCHRONIZE_CACHE";break;
263 case LOCK_UNLOCK_CACHE: what ="LOCK_UNLOCK_CACHE";break;
264 case READ_DEFECT_DATA: what ="READ_DEFECT_DATA";break;
265 case MEDIUM_SCAN: what ="MEDIUM_SCAN";break;
266 case COMPARE: what ="COMPARE";break;
267 case COPY_VERIFY: what ="COPY_VERIFY";break;
268 case WRITE_BUFFER: what ="WRITE_BUFFER";break;
269 case READ_BUFFER: what ="READ_BUFFER";break;
270 case UPDATE_BLOCK: what ="UPDATE_BLOCK";break;
271 case READ_LONG: what ="READ_LONG";break;
272 case WRITE_LONG: what ="WRITE_LONG";break;
273 case CHANGE_DEFINITION: what ="CHANGE_DEFINITION";break;
274 case WRITE_SAME: what ="WRITE_SAME";break;
275 case READ_TOC: what ="READ_TOC";break;
276 case LOG_SELECT: what ="LOG_SELECT";break;
277 case LOG_SENSE: what ="LOG_SENSE";break;
278 case MODE_SELECT_10: what ="MODE_SELECT_10";break;
279 case MODE_SENSE_10: what ="MODE_SENSE_10";break;
280 case MOVE_MEDIUM: what ="MOVE_MEDIUM";break;
281 case READ_12: what ="READ_12";break;
282 case WRITE_12: what ="WRITE_12";break;
283 case WRITE_VERIFY_12: what ="WRITE_VERIFY_12";break;
284 case SEARCH_HIGH_12: what ="SEARCH_HIGH_12";break;
285 case SEARCH_EQUAL_12: what ="SEARCH_EQUAL_12";break;
286 case SEARCH_LOW_12: what ="SEARCH_LOW_12";break;
287 case READ_ELEMENT_STATUS: what ="READ_ELEMENT_STATUS";break;
288 case SEND_VOLUME_TAG: what ="SEND_VOLUME_TAG";break;
289 case WRITE_LONG_2: what ="WRITE_LONG_2";break;
290 default:
291 MTS_DEBUG("can't decode command\n");
292 goto out;
293 break;
295 MTS_DEBUG("Command %s (%d bytes)\n", what, srb->cmd_len);
297 out:
298 MTS_DEBUG(" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
299 srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5],
300 srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]);
303 #else
305 staticinlinevoidmts_show_command(Scsi_Cmnd *srb)
307 while(0) {}
310 staticinlinevoidmts_debug_dump(struct mts_desc* desc)
312 while(0) {}
315 #endif
320 staticinlineintmts_is_aborting(struct mts_desc* desc) {
321 return(atomic_read(&desc->context.do_abort));
324 staticinlinevoidmts_request_abort(struct mts_desc* desc) {
325 MTS_DEBUG_GOT_HERE();
326 mts_debug_dump(desc);
327 atomic_set(&desc->context.do_abort,1);
330 staticinlinevoidmts_urb_abort(struct mts_desc* desc) {
331 MTS_DEBUG_GOT_HERE();
332 mts_debug_dump(desc);
333 if( desc->urb.status == USB_ST_URB_PENDING ) {
334 usb_unlink_urb( &desc->urb );
338 staticinlinevoidmts_wait_abort(struct mts_desc* desc)
340 mts_request_abort(desc);
342 while( !atomic_read(&desc->lock.count) ) {
343 /* Is there a function to check if the semaphore is locked? */
344 set_current_state(TASK_INTERRUPTIBLE);
345 schedule_timeout( MTS_ABORT_TIMEOUT );
346 MTS_DEBUG_GOT_HERE();
347 mts_urb_abort(desc);
353 static struct mts_desc * mts_list;/* list of active scanners */
354 struct semaphore mts_list_semaphore;
356 /* Internal list operations */
358 static
359 voidmts_remove_nolock(struct mts_desc* to_remove )
361 MTS_DEBUG("removing 0x%x from list\n",
362 (int)to_remove );
364 lock_kernel();
365 mts_wait_abort(to_remove);
367 MTS_DEBUG_GOT_HERE();
369 if( to_remove != mts_list ) {
370 MTS_DEBUG_GOT_HERE();
371 if(to_remove->prev && to_remove->next)
372 to_remove->prev->next = to_remove->next;
373 }else{
374 MTS_DEBUG_GOT_HERE();
375 mts_list = to_remove->next;
376 if(mts_list) {
377 MTS_DEBUG_GOT_HERE();
378 mts_list->prev =0;
382 if( to_remove->next ) {
383 MTS_DEBUG_GOT_HERE();
384 to_remove->next->prev = to_remove->prev;
387 MTS_DEBUG_GOT_HERE();
388 scsi_unregister_module(MODULE_SCSI_HA, &(to_remove->ctempl));
389 unlock_kernel();
391 kfree( to_remove );
394 static
395 voidmts_add_nolock(struct mts_desc* to_add )
397 MTS_DEBUG("adding 0x%x to list\n", (int)to_add );
399 to_add->prev =0;
400 to_add->next = mts_list;
401 if( mts_list ) {
402 mts_list->prev = to_add;
405 mts_list = to_add;
411 /* SCSI driver interface */
413 /* scsi related functions - dummies for now mostly */
415 static intmts_scsi_release(struct Scsi_Host *psh)
417 MTS_DEBUG_GOT_HERE();
419 return0;
422 static intmts_scsi_abort(Scsi_Cmnd *srb)
423 /* interrupt context (!) *//* FIXME this is about to become task context */
425 struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
427 MTS_DEBUG_GOT_HERE();
429 mts_request_abort(desc);
430 mts_urb_abort(desc);
432 return SCSI_ABORT_PENDING;
435 static intmts_scsi_host_reset(Scsi_Cmnd *srb)
437 struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
439 MTS_DEBUG_GOT_HERE();
440 mts_debug_dump(desc);
442 usb_reset_device(desc->usb_dev);/*FIXME: untested on new reset code */
443 return0;/* RANT why here 0 and not SUCCESS */
446 /* the core of the scsi part */
448 /* faking a detection - which can't fail :-) */
450 static intmts_scsi_detect(struct SHT * sht)
452 /* Whole function stolen from usb-storage */
454 struct mts_desc * desc = (struct mts_desc *)sht->proc_dir;
455 /* What a hideous hack! */
457 char local_name[48];
459 MTS_DEBUG_GOT_HERE();
461 /* set up the name of our subdirectory under /proc/scsi/ */
462 sprintf(local_name,"microtek-%d", desc->host_number);
463 sht->proc_name =kmalloc(strlen(local_name) +1, GFP_KERNEL);
464 /* FIXME: where is this freed ? */
466 if(!sht->proc_name) {
467 MTS_ERROR("unable to allocate memory for proc interface!!\n");
468 return0;
471 strcpy(sht->proc_name, local_name);
473 sht->proc_dir = NULL;
475 /* In host->hostdata we store a pointer to desc */
476 desc->host =scsi_register(sht,sizeof(desc));
477 desc->host->hostdata[0] = (unsigned long)desc;
478 /* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */
480 return1;
485 /* Main entrypoint: SCSI commands are dispatched to here */
489 static
490 intmts_scsi_queuecommand(Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
492 static voidmts_transfer_cleanup(struct urb *transfer );
495 inlinestatic
496 voidmts_int_submit_urb(struct urb* transfer,
497 int pipe,
498 void* data,
499 unsigned length,
500 mts_usb_urb_callback callback )
501 /* Interrupt context! */
503 /* Holding transfer->context->lock! */
505 int res;
506 struct mts_transfer_context* context;
508 MTS_INT_INIT();
510 FILL_BULK_URB(transfer,
511 context->instance->usb_dev,
512 pipe,
513 data,
514 length,
515 callback,
516 context
519 /* transfer->transfer_flags = USB_DISABLE_SPD;*/
520 transfer->transfer_flags = USB_ASYNC_UNLINK;
521 transfer->status =0;
522 transfer->timeout =100;
524 res =usb_submit_urb( transfer );
525 if( res ) {
526 MTS_INT_ERROR("could not submit URB! Error was %d\n",(int)res );
527 context->srb->result = DID_ERROR <<16;
528 context->state = mts_con_error;
529 mts_transfer_cleanup(transfer);
531 return;
535 static voidmts_transfer_cleanup(struct urb *transfer )
536 /* Interrupt context! */
538 struct mts_transfer_context* context = (struct mts_transfer_context*)transfer->context;
540 if( context->final_callback )
541 context->final_callback(context->srb);
542 up( &context->instance->lock );
546 static voidmts_transfer_done(struct urb *transfer )
548 struct mts_transfer_context* context;
550 MTS_INT_INIT();
552 context->srb->result &= MTS_SCSI_ERR_MASK;
553 context->srb->result |= (unsigned)context->status<<1;
555 mts_transfer_cleanup(transfer);
557 return;
561 static voidmts_get_status(struct urb *transfer )
562 /* Interrupt context! */
564 struct mts_transfer_context* context;
566 MTS_INT_INIT();
568 context->state = mts_con_status;
570 mts_int_submit_urb(transfer,
571 usb_rcvbulkpipe(context->instance->usb_dev,
572 context->instance->ep_response),
573 &context->status,
575 mts_transfer_done );
578 return;
581 static voidmts_data_done(struct urb* transfer )
582 /* Interrupt context! */
584 struct mts_transfer_context* context;
586 MTS_INT_INIT();
588 if( context->data_length != transfer->actual_length ) {
589 context->srb->resid = context->data_length - transfer->actual_length;
590 }else if( transfer->status ) {
591 context->srb->result = DID_ERROR<<16;
594 mts_get_status(transfer);
596 return;
600 static voidmts_command_done(struct urb *transfer )
601 /* Interrupt context! */
603 struct mts_transfer_context* context;
605 MTS_INT_INIT();
607 if( transfer->status ) {
608 context->srb->result = DID_ERROR<<16;
609 mts_transfer_cleanup(transfer);
611 return;
614 if( context->data ) {
615 context->state = mts_con_data;
616 mts_int_submit_urb(transfer,
617 context->data_pipe,
618 context->data,
619 context->data_length,
620 mts_data_done);
621 }elsemts_get_status(transfer);
623 return;
628 static const u8 mts_read_image_sig[] = {0x28,00,00,00};
629 static const u8 mts_read_image_sig_len =4;
630 static const unsigned char mts_direction[256/8] = {
631 0x28,0x81,0x14,0x14,0x20,0x01,0x90,0x77,
632 0x0C,0x20,0x00,0x04,0x00,0x00,0x00,0x00,
633 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
634 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
638 #define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1)
640 static void
641 mts_build_transfer_context( Scsi_Cmnd *srb,struct mts_desc* desc )
644 int pipe;
647 MTS_DEBUG_GOT_HERE();
649 desc->context.instance = desc;
650 desc->context.srb = srb;
651 desc->context.state = mts_con_command;
652 atomic_set(&desc->context.do_abort,0);
654 if( !srb->bufflen ){
655 desc->context.data =0;
656 desc->context.data_length =0;
657 return;
658 }else{
659 desc->context.data = srb->buffer;
660 desc->context.data_length = srb->bufflen;
663 /* can't rely on srb->sc_data_direction */
665 /* Brutally ripped from usb-storage */
667 if( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len )
668 ) { pipe =usb_rcvbulkpipe(desc->usb_dev,desc->ep_image);
669 MTS_DEBUG("transfering from desc->ep_image == %d\n",
670 (int)desc->ep_image );
671 }else if(MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) {
672 pipe =usb_rcvbulkpipe(desc->usb_dev,desc->ep_response);
673 MTS_DEBUG("transfering from desc->ep_response == %d\n",
674 (int)desc->ep_response);
675 }else{
676 MTS_DEBUG("transfering to desc->ep_out == %d\n",
677 (int)desc->ep_out);
678 pipe =usb_sndbulkpipe(desc->usb_dev,desc->ep_out);
680 desc->context.data_pipe = pipe;
684 static
685 intmts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
687 struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
688 int err =0;
689 int res;
691 MTS_DEBUG_GOT_HERE();
692 mts_show_command(srb);
693 mts_debug_dump(desc);
695 if( srb->device->lun || srb->device->id || srb->device->channel ) {
697 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 );
699 MTS_DEBUG("this device doesn't exist\n");
701 srb->result = DID_BAD_TARGET <<16;
703 if(callback)
704 callback(srb);
706 goto out;
709 down(&desc->lock);
711 MTS_DEBUG_GOT_HERE();
712 mts_show_command(srb);
715 FILL_BULK_URB(&desc->urb,
716 desc->usb_dev,
717 usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
718 srb->cmnd,
719 srb->cmd_len,
720 mts_command_done,
721 &desc->context
725 mts_build_transfer_context( srb, desc );
726 desc->context.final_callback = callback;
727 desc->urb.timeout =100;
728 desc->urb.transfer_flags = USB_ASYNC_UNLINK;
730 /* desc->urb.transfer_flags = USB_DISABLE_SPD;*/
732 res=usb_submit_urb(&desc->urb);
734 if(res){
735 MTS_ERROR("error %d submitting URB\n",(int)res);
736 srb->result = DID_ERROR <<16;
738 if(callback)
739 callback(srb);
740 up(&desc->lock);/* no further cleanup is done */
742 goto out;
745 MTS_DEBUG_GOT_HERE();
747 out:
748 return err;
751 * this defines our 'host'
754 /* NOTE: This is taken from usb-storage, should be right. */
757 static Scsi_Host_Template mts_scsi_host_template = {
758 name:"microtek",
759 detect: mts_scsi_detect,
760 release: mts_scsi_release,
761 command:0,
762 queuecommand: mts_scsi_queuecommand,
764 eh_abort_handler: mts_scsi_abort,
765 eh_device_reset_handler:0,
766 eh_bus_reset_handler:0,
767 eh_host_reset_handler: mts_scsi_host_reset,
769 can_queue:1,
770 this_id: -1,
771 cmd_per_lun:1,
772 present:0,
773 unchecked_isa_dma: FALSE,
774 use_clustering: FALSE,
775 use_new_eh_code: TRUE,
776 emulated: TRUE
780 /* USB layer driver interface implementation */
782 static voidmts_usb_disconnect(struct usb_device *dev,void*ptr)
784 struct mts_desc* to_remove = (struct mts_desc*)ptr;
786 MTS_DEBUG_GOT_HERE();
788 /* leave the list - lock it */
789 down(&mts_list_semaphore);
791 mts_remove_nolock(to_remove);
793 up(&mts_list_semaphore);
796 struct vendor_product
798 char* name;
799 enum
801 mts_sup_unknown=0,
802 mts_sup_alpha,
803 mts_sup_full
805 support_status;
809 /* These are taken from the msmUSB.inf file on the Windows driver CD */
810 const static struct vendor_product mts_supported_products[] =
812 {"Phantom 336CX", mts_sup_unknown},
813 {"Phantom 336CX", mts_sup_unknown},
814 {"Scanmaker X6", mts_sup_alpha},
815 {"Phantom C6", mts_sup_unknown},
816 {"Phantom 336CX", mts_sup_unknown},
817 {"ScanMaker V6USL", mts_sup_unknown},
818 {"ScanMaker V6USL", mts_sup_unknown},
819 {"Scanmaker V6UL", mts_sup_unknown},
822 /* The entries of microtek_table must correspond, line-by-line to
823 the entries of mts_supported_products[]. */
825 static struct usb_device_id mts_usb_ids [] =
827 {idVendor:0x4ce, idProduct:0x0300},
828 {idVendor:0x5da, idProduct:0x0094},
829 {idVendor:0x5da, idProduct:0x0099},
830 {idVendor:0x5da, idProduct:0x009a},
831 {idVendor:0x5da, idProduct:0x00a0},
832 {idVendor:0x5da, idProduct:0x00a3},
833 {idVendor:0x5da, idProduct:0x80a3},
834 {idVendor:0x5da, idProduct:0x80ac},
835 { }/* Terminating entry */
838 MODULE_DEVICE_TABLE(usb, mts_usb_ids);
841 static void*mts_usb_probe(struct usb_device *dev,unsigned int interface,
842 const struct usb_device_id *id)
844 int i;
845 int result;
846 int ep_out = -1;
847 int ep_in_set[3];/* this will break if we have more than three endpoints
848 which is why we check */
849 int*ep_in_current = ep_in_set;
851 struct mts_desc * new_desc;
852 struct vendor_product const* p;
854 /* the altsettting 0 on the interface we're probing */
855 struct usb_interface_descriptor *altsetting;
857 MTS_DEBUG_GOT_HERE();
858 MTS_DEBUG("usb-device descriptor at %x\n", (int)dev );
860 MTS_DEBUG("product id = 0x%x, vendor id = 0x%x\n",
861 (int)dev->descriptor.idProduct,
862 (int)dev->descriptor.idVendor );
864 MTS_DEBUG_GOT_HERE();
866 p = &mts_supported_products[id - mts_usb_ids];
868 MTS_DEBUG_GOT_HERE();
870 MTS_DEBUG("found model %s\n", p->name );
871 if( p->support_status != mts_sup_full )
872 MTS_MESSAGE("model %s is not known to be fully supported, reports welcome!\n",
873 p->name );
875 /* the altsettting 0 on the interface we're probing */
876 altsetting =
877 &(dev->actconfig->interface[interface].altsetting[0]);
880 /* Check if the config is sane */
882 if( altsetting->bNumEndpoints != MTS_EP_TOTAL ) {
883 MTS_WARNING("expecting %d got %d endpoints! Bailing out.\n",
884 (int)MTS_EP_TOTAL, (int)altsetting->bNumEndpoints );
885 return NULL;
888 for( i =0; i < altsetting->bNumEndpoints; i++ ) {
889 if((altsetting->endpoint[i].bmAttributes &
890 USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {
892 MTS_WARNING("can only deal with bulk endpoints; endpoint %d is not bulk.\n",
893 (int)altsetting->endpoint[i].bEndpointAddress );
894 }else{
895 if(altsetting->endpoint[i].bEndpointAddress &
896 USB_DIR_IN)
897 *ep_in_current++
898 = altsetting->endpoint[i].bEndpointAddress &
899 USB_ENDPOINT_NUMBER_MASK;
900 else{
901 if( ep_out != -1) {
902 MTS_WARNING("can only deal with one output endpoints. Bailing out.");
903 return NULL;
906 ep_out = altsetting->endpoint[i].bEndpointAddress &
907 USB_ENDPOINT_NUMBER_MASK;
914 if( ep_out == -1) {
915 MTS_WARNING("couldn't find an output bulk endpoint. Bailing out.\n");
916 return NULL;
920 /* I don't understand the following fully (it's from usb-storage) -- John */
922 /* set the interface -- STALL is an acceptable response here */
923 result =usb_set_interface(dev, altsetting->bInterfaceNumber,0);
925 MTS_DEBUG("usb_set_interface returned %d.\n",result);
926 switch( result )
928 case0:/* no error */
929 break;
931 case-EPIPE:
932 usb_clear_halt(dev,usb_sndctrlpipe(dev,0));
933 MTS_DEBUG("clearing clearing stall on control interface\n");
934 break;
936 default:
937 MTS_DEBUG("unknown error %d from usb_set_interface\n",
938 (int)result );
939 return NULL;
943 /* allocating a new descriptor */
944 new_desc = (struct mts_desc *)kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
945 if(new_desc == NULL)
947 MTS_ERROR("couldn't allocate scanner desc, bailing out!\n");
948 return NULL;
951 /* As done by usb_alloc_urb */
952 memset( new_desc,0,sizeof(*new_desc) );
953 spin_lock_init(&new_desc->urb.lock);
956 /* initialising that descriptor */
957 new_desc->usb_dev = dev;
958 new_desc->interface = interface;
960 init_MUTEX(&new_desc->lock);
962 if(mts_list){
963 new_desc->host_number = mts_list->host_number+1;
964 }else{
965 new_desc->host_number =0;
968 /* endpoints */
970 new_desc->ep_out = ep_out;
971 new_desc->ep_response = ep_in_set[0];
972 new_desc->ep_image = ep_in_set[1];
975 if( new_desc->ep_out != MTS_EP_OUT )
976 MTS_WARNING("will this work? Command EP is not usually %d\n",
977 (int)new_desc->ep_out );
979 if( new_desc->ep_response != MTS_EP_RESPONSE )
980 MTS_WARNING("will this work? Response EP is not usually %d\n",
981 (int)new_desc->ep_response );
983 if( new_desc->ep_image != MTS_EP_IMAGE )
984 MTS_WARNING("will this work? Image data EP is not usually %d\n",
985 (int)new_desc->ep_image );
988 /* Initialize the host template based on the default one */
989 memcpy(&(new_desc->ctempl), &mts_scsi_host_template,sizeof(mts_scsi_host_template));
990 /* HACK from usb-storage - this is needed for scsi detection */
991 (struct mts_desc *)new_desc->ctempl.proc_dir = new_desc;/* FIXME */
993 MTS_DEBUG("registering SCSI module\n");
995 new_desc->ctempl.module = THIS_MODULE;
996 result =scsi_register_module(MODULE_SCSI_HA, &(new_desc->ctempl));
997 /* Will get hit back in microtek_detect by this func */
998 if( result )
1000 MTS_ERROR("error %d from scsi_register_module! Help!\n",
1001 (int)result );
1003 /* FIXME: need more cleanup? */
1004 kfree( new_desc );
1005 return NULL;
1007 MTS_DEBUG_GOT_HERE();
1009 /* FIXME: the bomb is armed, must the host be registered under lock ? */
1010 /* join the list - lock it */
1011 down(&mts_list_semaphore);
1013 mts_add_nolock( new_desc );
1015 up(&mts_list_semaphore);
1018 MTS_DEBUG("completed probe and exiting happily\n");
1020 return(void*)new_desc;
1025 /* get us noticed by the rest of the kernel */
1027 int __init microtek_drv_init(void)
1029 int result;
1031 MTS_DEBUG_GOT_HERE();
1032 init_MUTEX(&mts_list_semaphore);
1034 if((result =usb_register(&mts_usb_driver)) <0) {
1035 MTS_DEBUG("usb_register returned %d\n", result );
1036 return-1;
1037 }else{
1038 MTS_DEBUG("driver registered.\n");
1041 return0;
1044 void __exit microtek_drv_exit(void)
1046 struct mts_desc* next;
1048 MTS_DEBUG_GOT_HERE();
1050 usb_deregister(&mts_usb_driver);
1052 down(&mts_list_semaphore);
1054 while(mts_list) {
1055 /* keep track of where the next one is */
1056 next = mts_list->next;
1058 mts_remove_nolock( mts_list );
1060 /* advance the list pointer */
1061 mts_list = next;
1064 up(&mts_list_semaphore);
1067 module_init(microtek_drv_init);
1068 module_exit(microtek_drv_exit);
1070 MODULE_AUTHOR("John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>");
1071 MODULE_DESCRIPTION("Microtek Scanmaker X6 USB scanner driver");
close