1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124#include <linux/module.h>
125#include <linux/kernel.h>
126#include <linux/sched.h>
127#include <linux/signal.h>
128#include <linux/errno.h>
129#include <linux/random.h>
130#include <linux/poll.h>
131#include <linux/init.h>
132#include <linux/slab.h>
133#include <linux/spinlock.h>
134#include <linux/smp_lock.h>
135#include <linux/usb.h>
136#include <linux/proc_fs.h>
137
138#include <asm/atomic.h>
139#include <linux/blk.h>
140#include "../scsi/scsi.h"
141#include "../scsi/hosts.h"
142#include "../scsi/sd.h"
143
144#include "microtek.h"
145
146
147
148
149#define DRIVER_VERSION "v0.4.4"
150#define DRIVER_AUTHOR "John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>"
151#define DRIVER_DESC "Microtek Scanmaker X6 USB scanner driver"
152
153
154
155
156
157
158
159static void *mts_usb_probe(struct usb_device *dev, unsigned int interface,
160 const struct usb_device_id *id);
161static void mts_usb_disconnect(struct usb_device *dev, void *ptr);
162
163static struct usb_device_id mts_usb_ids [];
164
165static struct usb_driver mts_usb_driver = {
166 name: "microtekX6",
167 probe: mts_usb_probe,
168 disconnect: mts_usb_disconnect,
169 id_table: mts_usb_ids,
170};
171
172
173
174
175#define MTS_VERSION "0.4.3"
176#define MTS_NAME "microtek usb (rev " MTS_VERSION "): "
177
178#define MTS_WARNING(x...) \
179 printk( KERN_WARNING MTS_NAME x )
180#define MTS_ERROR(x...) \
181 printk( KERN_ERR MTS_NAME x )
182#define MTS_INT_ERROR(x...) \
183 MTS_ERROR(x)
184#define MTS_MESSAGE(x...) \
185 printk( KERN_INFO MTS_NAME x )
186
187#if defined MTS_DO_DEBUG
188
189#define MTS_DEBUG(x...) \
190 printk( KERN_DEBUG MTS_NAME x )
191
192#define MTS_DEBUG_GOT_HERE() \
193 MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __PRETTY_FUNCTION__ )
194#define MTS_DEBUG_INT() \
195 do { MTS_DEBUG_GOT_HERE(); \
196 MTS_DEBUG("transfer = 0x%x context = 0x%x\n",(int)transfer,(int)context ); \
197 MTS_DEBUG("status = 0x%x data-length = 0x%x sent = 0x%x\n",(int)transfer->status,(int)context->data_length, (int)transfer->actual_length ); \
198 mts_debug_dump(context->instance);\
199 } while(0)
200#else
201
202#define MTS_NUL_STATEMENT do { } while(0)
203
204#define MTS_DEBUG(x...) MTS_NUL_STATEMENT
205#define MTS_DEBUG_GOT_HERE() MTS_NUL_STATEMENT
206#define MTS_DEBUG_INT() MTS_NUL_STATEMENT
207
208#endif
209
210
211
212#define MTS_INT_INIT()\
213 struct mts_transfer_context* context = (struct mts_transfer_context*)transfer->context; \
214 MTS_DEBUG_INT();\
215
216#ifdef MTS_DO_DEBUG
217
218static inline void mts_debug_dump(struct mts_desc* desc) {
219 MTS_DEBUG("desc at 0x%x: halted = %02x%02x, toggle = %02x%02x\n",
220 (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0],
221 (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0]
222 );
223 MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n",
224 usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
225 usb_rcvbulkpipe(desc->usb_dev,desc->ep_response),
226 usb_rcvbulkpipe(desc->usb_dev,desc->ep_image)
227 );
228}
229
230
231static inline void mts_show_command(Scsi_Cmnd *srb)
232{
233 char *what = NULL;
234
235 switch (srb->cmnd[0]) {
236 case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break;
237 case REZERO_UNIT: what = "REZERO_UNIT"; break;
238 case REQUEST_SENSE: what = "REQUEST_SENSE"; break;
239 case FORMAT_UNIT: what = "FORMAT_UNIT"; break;
240 case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break;
241 case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break;
242 case READ_6: what = "READ_6"; break;
243 case WRITE_6: what = "WRITE_6"; break;
244 case SEEK_6: what = "SEEK_6"; break;
245 case READ_REVERSE: what = "READ_REVERSE"; break;
246 case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break;
247 case SPACE: what = "SPACE"; break;
248 case INQUIRY: what = "INQUIRY"; break;
249 case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break;
250 case MODE_SELECT: what = "MODE_SELECT"; break;
251 case RESERVE: what = "RESERVE"; break;
252 case RELEASE: what = "RELEASE"; break;
253 case COPY: what = "COPY"; break;
254 case ERASE: what = "ERASE"; break;
255 case MODE_SENSE: what = "MODE_SENSE"; break;
256 case START_STOP: what = "START_STOP"; break;
257 case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break;
258 case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break;
259 case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break;
260 case SET_WINDOW: what = "SET_WINDOW"; break;
261 case READ_CAPACITY: what = "READ_CAPACITY"; break;
262 case READ_10: what = "READ_10"; break;
263 case WRITE_10: what = "WRITE_10"; break;
264 case SEEK_10: what = "SEEK_10"; break;
265 case WRITE_VERIFY: what = "WRITE_VERIFY"; break;
266 case VERIFY: what = "VERIFY"; break;
267 case SEARCH_HIGH: what = "SEARCH_HIGH"; break;
268 case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break;
269 case SEARCH_LOW: what = "SEARCH_LOW"; break;
270 case SET_LIMITS: what = "SET_LIMITS"; break;
271 case READ_POSITION: what = "READ_POSITION"; break;
272 case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break;
273 case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break;
274 case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break;
275 case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break;
276 case COMPARE: what = "COMPARE"; break;
277 case COPY_VERIFY: what = "COPY_VERIFY"; break;
278 case WRITE_BUFFER: what = "WRITE_BUFFER"; break;
279 case READ_BUFFER: what = "READ_BUFFER"; break;
280 case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break;
281 case READ_LONG: what = "READ_LONG"; break;
282 case WRITE_LONG: what = "WRITE_LONG"; break;
283 case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break;
284 case WRITE_SAME: what = "WRITE_SAME"; break;
285 case READ_TOC: what = "READ_TOC"; break;
286 case LOG_SELECT: what = "LOG_SELECT"; break;
287 case LOG_SENSE: what = "LOG_SENSE"; break;
288 case MODE_SELECT_10: what = "MODE_SELECT_10"; break;
289 case MODE_SENSE_10: what = "MODE_SENSE_10"; break;
290 case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break;
291 case READ_12: what = "READ_12"; break;
292 case WRITE_12: what = "WRITE_12"; break;
293 case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break;
294 case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break;
295 case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break;
296 case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break;
297 case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break;
298 case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break;
299 case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
300 default:
301 MTS_DEBUG("can't decode command\n");
302 goto out;
303 break;
304 }
305 MTS_DEBUG( "Command %s (%d bytes)\n", what, srb->cmd_len);
306
307 out:
308 MTS_DEBUG( " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
309 srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5],
310 srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]);
311}
312
313#else
314
315static inline void mts_show_command(Scsi_Cmnd * dummy)
316{
317}
318
319static inline void mts_debug_dump(struct mts_desc* dummy)
320{
321}
322
323#endif
324
325
326
327
328
329
330static inline void mts_urb_abort(struct mts_desc* desc) {
331 spin_unlock_irq(&io_request_lock);
332 MTS_DEBUG_GOT_HERE();
333 mts_debug_dump(desc);
334
335 usb_unlink_urb( &desc->urb );
336 spin_lock_irq(&io_request_lock);
337}
338
339static struct mts_desc * mts_list;
340struct semaphore mts_list_semaphore;
341
342
343
344static
345void mts_remove_nolock( struct mts_desc* to_remove )
346{
347 MTS_DEBUG( "removing 0x%x from list\n",
348 (int)to_remove );
349
350 lock_kernel();
351 mts_urb_abort(to_remove);
352
353 MTS_DEBUG_GOT_HERE();
354
355 if ( to_remove != mts_list ) {
356 MTS_DEBUG_GOT_HERE();
357 if (to_remove->prev && to_remove->next)
358 to_remove->prev->next = to_remove->next;
359 } else {
360 MTS_DEBUG_GOT_HERE();
361 mts_list = to_remove->next;
362 if (mts_list) {
363 MTS_DEBUG_GOT_HERE();
364 mts_list->prev = 0;
365 }
366 }
367
368 if ( to_remove->next ) {
369 MTS_DEBUG_GOT_HERE();
370 to_remove->next->prev = to_remove->prev;
371 }
372
373 MTS_DEBUG_GOT_HERE();
374 scsi_unregister_module(MODULE_SCSI_HA, &(to_remove->ctempl));
375 unlock_kernel();
376
377 kfree( to_remove );
378}
379
380static
381void mts_add_nolock( struct mts_desc* to_add )
382{
383 MTS_DEBUG( "adding 0x%x to list\n", (int)to_add );
384
385 to_add->prev = 0;
386 to_add->next = mts_list;
387 if ( mts_list ) {
388 mts_list->prev = to_add;
389 }
390
391 mts_list = to_add;
392}
393
394
395
396
397
398
399
400
401static int mts_scsi_release(struct Scsi_Host *psh)
402{
403 MTS_DEBUG_GOT_HERE();
404
405 return 0;
406}
407
408static int mts_scsi_abort (Scsi_Cmnd *srb)
409{
410 struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
411
412 MTS_DEBUG_GOT_HERE();
413
414 mts_urb_abort(desc);
415
416 return SCSI_ABORT_PENDING;
417}
418
419static int mts_scsi_host_reset (Scsi_Cmnd *srb)
420{
421
422 struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
423 spin_unlock_irq(&io_request_lock);
424 MTS_DEBUG_GOT_HERE();
425 mts_debug_dump(desc);
426
427 usb_reset_device(desc->usb_dev);
428 spin_lock_irq(&io_request_lock);
429 return 0;
430}
431
432
433
434
435
436static int mts_scsi_detect (struct SHT * sht)
437{
438
439
440 struct mts_desc * desc = (struct mts_desc *)sht->proc_dir;
441
442
443 char local_name[48];
444 spin_unlock_irq(&io_request_lock);
445
446 MTS_DEBUG_GOT_HERE();
447
448
449 sprintf(local_name, "microtek-%d", desc->host_number);
450 sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL);
451
452
453 if (!sht->proc_name) {
454 MTS_ERROR( "unable to allocate memory for proc interface!!\n" );
455 spin_lock_irq(&io_request_lock);
456 return 0;
457 }
458
459 strcpy(sht->proc_name, local_name);
460
461 sht->proc_dir = NULL;
462
463
464 desc->host = scsi_register(sht, sizeof(desc));
465 if (desc->host == NULL) {
466 MTS_ERROR("Cannot register due to low memory");
467 kfree(sht->proc_name);
468 spin_lock_irq(&io_request_lock);
469 return 0;
470 }
471 desc->host->hostdata[0] = (unsigned long)desc;
472
473 spin_lock_irq(&io_request_lock);
474 return 1;
475}
476
477
478
479
480
481
482
483static
484int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
485
486static void mts_transfer_cleanup( struct urb *transfer );
487static void mts_do_sg(struct urb * transfer);
488
489
490inline static
491void mts_int_submit_urb (struct urb* transfer,
492 int pipe,
493 void* data,
494 unsigned length,
495 mts_usb_urb_callback callback )
496
497
498
499{
500 int res;
501
502 MTS_INT_INIT();
503
504 FILL_BULK_URB(transfer,
505 context->instance->usb_dev,
506 pipe,
507 data,
508 length,
509 callback,
510 context
511 );
512
513 transfer->status = 0;
514
515 res = usb_submit_urb( transfer );
516 if ( res ) {
517 MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res );
518 context->srb->result = DID_ERROR << 16;
519 mts_transfer_cleanup(transfer);
520 }
521 return;
522}
523
524
525static void mts_transfer_cleanup( struct urb *transfer )
526
527{
528 MTS_INT_INIT();
529
530 if ( context->final_callback )
531 context->final_callback(context->srb);
532
533}
534
535static void mts_transfer_done( struct urb *transfer )
536{
537 MTS_INT_INIT();
538
539 context->srb->result &= MTS_SCSI_ERR_MASK;
540 context->srb->result |= (unsigned)context->status<<1;
541
542 mts_transfer_cleanup(transfer);
543
544 return;
545}
546
547
548static void mts_get_status( struct urb *transfer )
549
550{
551 MTS_INT_INIT();
552
553 mts_int_submit_urb(transfer,
554 usb_rcvbulkpipe(context->instance->usb_dev,
555 context->instance->ep_response),
556 &context->status,
557 1,
558 mts_transfer_done );
559}
560
561static void mts_data_done( struct urb* transfer )
562
563{
564 MTS_INT_INIT();
565
566 if ( context->data_length != transfer->actual_length ) {
567 context->srb->resid = context->data_length - transfer->actual_length;
568 } else if ( transfer->status ) {
569 context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
570 }
571
572 mts_get_status(transfer);
573
574 return;
575}
576
577
578static void mts_command_done( struct urb *transfer )
579
580{
581 MTS_INT_INIT();
582
583 if ( transfer->status ) {
584 if (transfer->status == -ENOENT) {
585
586 MTS_DEBUG_GOT_HERE();
587 context->srb->result = DID_ABORT<<16;
588 } else {
589
590 MTS_DEBUG_GOT_HERE();
591
592 context->srb->result = DID_ERROR<<16;
593 }
594 mts_transfer_cleanup(transfer);
595
596 return;
597 }
598
599 if ( context->data ) {
600 mts_int_submit_urb(transfer,
601 context->data_pipe,
602 context->data,
603 context->data_length,
604 context->srb->use_sg ? mts_do_sg : mts_data_done);
605 } else mts_get_status(transfer);
606
607 return;
608}
609
610static void mts_do_sg (struct urb* transfer)
611{
612 struct scatterlist * sg;
613 MTS_INT_INIT();
614
615 MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg);
616
617 if (transfer->status) {
618 context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
619 mts_transfer_cleanup(transfer);
620 }
621
622 sg = context->srb->buffer;
623 context->fragment++;
624 mts_int_submit_urb(transfer,
625 context->data_pipe,
626 sg[context->fragment].address,
627 sg[context->fragment].length,
628 context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);
629 return;
630}
631
632static const u8 mts_read_image_sig[] = { 0x28, 00, 00, 00 };
633static const u8 mts_read_image_sig_len = 4;
634static const unsigned char mts_direction[256/8] = {
635 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
636 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
639};
640
641
642#define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1)
643
644static void
645mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc )
646{
647 int pipe;
648 struct scatterlist * sg;
649
650 MTS_DEBUG_GOT_HERE();
651
652 desc->context.instance = desc;
653 desc->context.srb = srb;
654 desc->context.fragment = 0;
655
656 if (!srb->use_sg) {
657 if ( !srb->bufflen ){
658 desc->context.data = 0;
659 desc->context.data_length = 0;
660 return;
661 } else {
662 desc->context.data = srb->buffer;
663 desc->context.data_length = srb->bufflen;
664 MTS_DEBUG("length = %d or %d\n",
665 srb->request_bufflen, srb->bufflen);
666 }
667 } else {
668 MTS_DEBUG("Using scatter/gather\n");
669 sg = srb->buffer;
670 desc->context.data = sg[0].address;
671 desc->context.data_length = sg[0].length;
672 }
673
674
675
676
677
678
679 if ( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len )
680) { pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_image);
681 MTS_DEBUG( "transfering from desc->ep_image == %d\n",
682 (int)desc->ep_image );
683 } else if ( MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) {
684 pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_response);
685 MTS_DEBUG( "transfering from desc->ep_response == %d\n",
686 (int)desc->ep_response);
687 } else {
688 MTS_DEBUG("transfering to desc->ep_out == %d\n",
689 (int)desc->ep_out);
690 pipe = usb_sndbulkpipe(desc->usb_dev,desc->ep_out);
691 }
692 desc->context.data_pipe = pipe;
693}
694
695
696static
697int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
698{
699 struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
700 int err = 0;
701 int res;
702
703 MTS_DEBUG_GOT_HERE();
704 mts_show_command(srb);
705 mts_debug_dump(desc);
706
707 if ( srb->device->lun || srb->device->id || srb->device->channel ) {
708
709 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 );
710
711 MTS_DEBUG("this device doesn't exist\n");
712
713 srb->result = DID_BAD_TARGET << 16;
714
715 if(callback)
716 callback(srb);
717
718 goto out;
719 }
720
721
722 FILL_BULK_URB(&desc->urb,
723 desc->usb_dev,
724 usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
725 srb->cmnd,
726 srb->cmd_len,
727 mts_command_done,
728 &desc->context
729 );
730
731
732 mts_build_transfer_context( srb, desc );
733 desc->context.final_callback = callback;
734
735 res=usb_submit_urb(&desc->urb);
736
737 if(res){
738 MTS_ERROR("error %d submitting URB\n",(int)res);
739 srb->result = DID_ERROR << 16;
740
741 if(callback)
742 callback(srb);
743
744 }
745
746out:
747 return err;
748}
749
750
751
752
753
754
755
756static Scsi_Host_Template mts_scsi_host_template = {
757 name: "microtekX6",
758 detect: mts_scsi_detect,
759 release: mts_scsi_release,
760 queuecommand: mts_scsi_queuecommand,
761
762 eh_abort_handler: mts_scsi_abort,
763 eh_host_reset_handler: mts_scsi_host_reset,
764
765 sg_tablesize: SG_ALL,
766 can_queue: 1,
767 this_id: -1,
768 cmd_per_lun: 1,
769 present: 0,
770 unchecked_isa_dma: FALSE,
771 use_clustering: TRUE,
772 use_new_eh_code: TRUE,
773 emulated: TRUE
774};
775
776
777
778
779static void mts_usb_disconnect (struct usb_device *dev, void *ptr)
780{
781 struct mts_desc* to_remove = (struct mts_desc*)ptr;
782
783 MTS_DEBUG_GOT_HERE();
784
785
786 down(&mts_list_semaphore);
787
788 mts_remove_nolock(to_remove);
789
790 up(&mts_list_semaphore);
791}
792
793struct vendor_product
794{
795 char* name;
796 enum
797 {
798 mts_sup_unknown=0,
799 mts_sup_alpha,
800 mts_sup_full
801 }
802 support_status;
803} ;
804
805
806
807const static struct vendor_product mts_supported_products[] =
808{
809 { "Phantom 336CX", mts_sup_unknown},
810 { "Phantom 336CX", mts_sup_unknown},
811 { "Scanmaker X6", mts_sup_alpha},
812 { "Phantom C6", mts_sup_unknown},
813 { "Phantom 336CX", mts_sup_unknown},
814 { "ScanMaker V6USL", mts_sup_unknown},
815 { "ScanMaker V6USL", mts_sup_unknown},
816 { "Scanmaker V6UL", mts_sup_unknown},
817 { "Scanmaker V6UPL", mts_sup_alpha},
818};
819
820
821
822
823static struct usb_device_id mts_usb_ids [] =
824{
825 { USB_DEVICE(0x4ce, 0x0300) },
826 { USB_DEVICE(0x5da, 0x0094) },
827 { USB_DEVICE(0x5da, 0x0099) },
828 { USB_DEVICE(0x5da, 0x009a) },
829 { USB_DEVICE(0x5da, 0x00a0) },
830 { USB_DEVICE(0x5da, 0x00a3) },
831 { USB_DEVICE(0x5da, 0x80a3) },
832 { USB_DEVICE(0x5da, 0x80ac) },
833 { USB_DEVICE(0x5da, 0x00b6) },
834 { }
835};
836
837MODULE_DEVICE_TABLE (usb, mts_usb_ids);
838
839
840static void * mts_usb_probe (struct usb_device *dev, unsigned int interface,
841 const struct usb_device_id *id)
842{
843 int i;
844 int result;
845 int ep_out = -1;
846 int ep_in_set[3];
847
848 int *ep_in_current = ep_in_set;
849
850 struct mts_desc * new_desc;
851 struct vendor_product const* p;
852
853
854 struct usb_interface_descriptor *altsetting;
855
856 MTS_DEBUG_GOT_HERE();
857 MTS_DEBUG( "usb-device descriptor at %x\n", (int)dev );
858
859 MTS_DEBUG( "product id = 0x%x, vendor id = 0x%x\n",
860 (int)dev->descriptor.idProduct,
861 (int)dev->descriptor.idVendor );
862
863 MTS_DEBUG_GOT_HERE();
864
865 p = &mts_supported_products[id - mts_usb_ids];
866
867 MTS_DEBUG_GOT_HERE();
868
869 MTS_DEBUG( "found model %s\n", p->name );
870 if ( p->support_status != mts_sup_full )
871 MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n",
872 p->name );
873
874
875 altsetting =
876 &(dev->actconfig->interface[interface].altsetting[0]);
877
878
879
880
881 if ( altsetting->bNumEndpoints != MTS_EP_TOTAL ) {
882 MTS_WARNING( "expecting %d got %d endpoints! Bailing out.\n",
883 (int)MTS_EP_TOTAL, (int)altsetting->bNumEndpoints );
884 return NULL;
885 }
886
887 for( i = 0; i < altsetting->bNumEndpoints; i++ ) {
888 if ((altsetting->endpoint[i].bmAttributes &
889 USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {
890
891 MTS_WARNING( "can only deal with bulk endpoints; endpoint %d is not bulk.\n",
892 (int)altsetting->endpoint[i].bEndpointAddress );
893 } else {
894 if (altsetting->endpoint[i].bEndpointAddress &
895 USB_DIR_IN)
896 *ep_in_current++
897 = altsetting->endpoint[i].bEndpointAddress &
898 USB_ENDPOINT_NUMBER_MASK;
899 else {
900 if ( ep_out != -1 ) {
901 MTS_WARNING( "can only deal with one output endpoints. Bailing out." );
902 return NULL;
903 }
904
905 ep_out = altsetting->endpoint[i].bEndpointAddress &
906 USB_ENDPOINT_NUMBER_MASK;
907 }
908 }
909
910 }
911
912
913 if ( ep_out == -1 ) {
914 MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" );
915 return NULL;
916 }
917
918
919
920
921
922 result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0);
923
924 MTS_DEBUG("usb_set_interface returned %d.\n",result);
925 switch( result )
926 {
927 case 0:
928 break;
929
930 case -EPIPE:
931 usb_clear_halt(dev, usb_sndctrlpipe(dev, 0));
932 MTS_DEBUG( "clearing clearing stall on control interface\n" );
933 break;
934
935 default:
936 MTS_DEBUG( "unknown error %d from usb_set_interface\n",
937 (int)result );
938 return NULL;
939 }
940
941
942
943 new_desc = (struct mts_desc *)kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
944 if (new_desc == NULL)
945 {
946 MTS_ERROR("couldn't allocate scanner desc, bailing out!\n");
947 return NULL;
948 }
949
950
951 memset( new_desc, 0, sizeof(*new_desc) );
952 spin_lock_init(&new_desc->urb.lock);
953
954
955
956 new_desc->usb_dev = dev;
957 new_desc->interface = interface;
958
959 init_MUTEX(&new_desc->lock);
960
961 if(mts_list){
962 new_desc->host_number = mts_list->host_number+1;
963 } else {
964 new_desc->host_number = 0;
965 }
966
967
968
969 new_desc->ep_out = ep_out;
970 new_desc->ep_response = ep_in_set[0];
971 new_desc->ep_image = ep_in_set[1];
972
973
974 if ( new_desc->ep_out != MTS_EP_OUT )
975 MTS_WARNING( "will this work? Command EP is not usually %d\n",
976 (int)new_desc->ep_out );
977
978 if ( new_desc->ep_response != MTS_EP_RESPONSE )
979 MTS_WARNING( "will this work? Response EP is not usually %d\n",
980 (int)new_desc->ep_response );
981
982 if ( new_desc->ep_image != MTS_EP_IMAGE )
983 MTS_WARNING( "will this work? Image data EP is not usually %d\n",
984 (int)new_desc->ep_image );
985
986
987
988 memcpy(&(new_desc->ctempl), &mts_scsi_host_template, sizeof(mts_scsi_host_template));
989
990 new_desc->ctempl.proc_dir = (void *)new_desc;
991
992 MTS_DEBUG("registering SCSI module\n");
993
994 new_desc->ctempl.module = THIS_MODULE;
995 result = scsi_register_module(MODULE_SCSI_HA, &(new_desc->ctempl));
996
997 if ( result )
998 {
999 MTS_ERROR( "error %d from scsi_register_module! Help!\n",
1000 (int)result );
1001
1002
1003 kfree( new_desc );
1004 return NULL;
1005 }
1006 MTS_DEBUG_GOT_HERE();
1007
1008
1009
1010 down(&mts_list_semaphore);
1011
1012 mts_add_nolock( new_desc );
1013
1014 up(&mts_list_semaphore);
1015
1016
1017 MTS_DEBUG("completed probe and exiting happily\n");
1018
1019 return (void *)new_desc;
1020}
1021
1022
1023
1024
1025
1026int __init microtek_drv_init(void)
1027{
1028 int result;
1029
1030 MTS_DEBUG_GOT_HERE();
1031 init_MUTEX(&mts_list_semaphore);
1032
1033 if ((result = usb_register(&mts_usb_driver)) < 0) {
1034 MTS_DEBUG("usb_register returned %d\n", result );
1035 return -1;
1036 } else {
1037 MTS_DEBUG("driver registered.\n");
1038 }
1039
1040 info(DRIVER_VERSION ":" DRIVER_DESC);
1041
1042 return 0;
1043}
1044
1045void __exit microtek_drv_exit(void)
1046{
1047 struct mts_desc* next;
1048
1049 MTS_DEBUG_GOT_HERE();
1050
1051 usb_deregister(&mts_usb_driver);
1052
1053 down(&mts_list_semaphore);
1054
1055 while (mts_list) {
1056
1057 next = mts_list->next;
1058
1059 mts_remove_nolock( mts_list );
1060
1061
1062 mts_list = next;
1063 }
1064
1065 up(&mts_list_semaphore);
1066}
1067
1068module_init(microtek_drv_init);
1069module_exit(microtek_drv_exit);
1070
1071MODULE_AUTHOR( DRIVER_AUTHOR );
1072MODULE_DESCRIPTION( DRIVER_DESC );
1073MODULE_LICENSE("GPL");
1074
1075