diff options
Diffstat (limited to 'drivers/usb/image')
-rw-r--r-- | drivers/usb/image/Kconfig | 30 | ||||
-rw-r--r-- | drivers/usb/image/Makefile | 6 | ||||
-rw-r--r-- | drivers/usb/image/mdc800.c | 1063 | ||||
-rw-r--r-- | drivers/usb/image/microtek.c | 862 | ||||
-rw-r--r-- | drivers/usb/image/microtek.h | 55 |
5 files changed, 2016 insertions, 0 deletions
diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig new file mode 100644 index 000000000000..95ce703110d2 --- /dev/null +++ b/drivers/usb/image/Kconfig | |||
@@ -0,0 +1,30 @@ | |||
1 | # | ||
2 | # USB Imageing devices configuration | ||
3 | # | ||
4 | comment "USB Imaging devices" | ||
5 | depends on USB | ||
6 | |||
7 | config USB_MDC800 | ||
8 | tristate "USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)" | ||
9 | depends on USB && EXPERIMENTAL | ||
10 | ---help--- | ||
11 | Say Y here if you want to connect this type of still camera to | ||
12 | your computer's USB port. This driver can be used with gphoto 0.4.3 | ||
13 | and higher (look at <http://www.gphoto.org/>). | ||
14 | To use it create a device node with "mknod /dev/mustek c 180 32" and | ||
15 | configure it in your software. | ||
16 | |||
17 | To compile this driver as a module, choose M here: the | ||
18 | module will be called mdc800. | ||
19 | |||
20 | config USB_MICROTEK | ||
21 | tristate "Microtek X6USB scanner support" | ||
22 | depends on USB && SCSI | ||
23 | help | ||
24 | Say Y here if you want support for the Microtek X6USB and | ||
25 | possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L. | ||
26 | Support for anything but the X6 is experimental. | ||
27 | Please report failures and successes. | ||
28 | The scanner will appear as a scsi generic device to the rest | ||
29 | of the system. Scsi support is required. | ||
30 | This driver can be compiled as a module, called microtek. | ||
diff --git a/drivers/usb/image/Makefile b/drivers/usb/image/Makefile new file mode 100644 index 000000000000..4148ae306352 --- /dev/null +++ b/drivers/usb/image/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for USB Image drivers | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_USB_MDC800) += mdc800.o | ||
6 | obj-$(CONFIG_USB_MICROTEK) += microtek.o | ||
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c new file mode 100644 index 000000000000..5791723e6083 --- /dev/null +++ b/drivers/usb/image/mdc800.c | |||
@@ -0,0 +1,1063 @@ | |||
1 | /* | ||
2 | * copyright (C) 1999/2000 by Henning Zabel <henning@uni-paderborn.de> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
11 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software Foundation, | ||
16 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | |||
20 | /* | ||
21 | * USB-Kernel Driver for the Mustek MDC800 Digital Camera | ||
22 | * (c) 1999/2000 Henning Zabel <henning@uni-paderborn.de> | ||
23 | * | ||
24 | * | ||
25 | * The driver brings the USB functions of the MDC800 to Linux. | ||
26 | * To use the Camera you must support the USB Protocoll of the camera | ||
27 | * to the Kernel Node. | ||
28 | * The Driver uses a misc device Node. Create it with : | ||
29 | * mknod /dev/mustek c 180 32 | ||
30 | * | ||
31 | * The driver supports only one camera. | ||
32 | * | ||
33 | * Fix: mdc800 used sleep_on and slept with io_lock held. | ||
34 | * Converted sleep_on to waitqueues with schedule_timeout and made io_lock | ||
35 | * a semaphore from a spinlock. | ||
36 | * by Oliver Neukum <oliver@neukum.name> | ||
37 | * (02/12/2001) | ||
38 | * | ||
39 | * Identify version on module load. | ||
40 | * (08/04/2001) gb | ||
41 | * | ||
42 | * version 0.7.5 | ||
43 | * Fixed potential SMP races with Spinlocks. | ||
44 | * Thanks to Oliver Neukum <oliver@neukum.name> who | ||
45 | * noticed the race conditions. | ||
46 | * (30/10/2000) | ||
47 | * | ||
48 | * Fixed: Setting urb->dev before submitting urb. | ||
49 | * by Greg KH <greg@kroah.com> | ||
50 | * (13/10/2000) | ||
51 | * | ||
52 | * version 0.7.3 | ||
53 | * bugfix : The mdc800->state field gets set to READY after the | ||
54 | * the diconnect function sets it to NOT_CONNECTED. This makes the | ||
55 | * driver running like the camera is connected and causes some | ||
56 | * hang ups. | ||
57 | * | ||
58 | * version 0.7.1 | ||
59 | * MOD_INC and MOD_DEC are changed in usb_probe to prevent load/unload | ||
60 | * problems when compiled as Module. | ||
61 | * (04/04/2000) | ||
62 | * | ||
63 | * The mdc800 driver gets assigned the USB Minor 32-47. The Registration | ||
64 | * was updated to use these values. | ||
65 | * (26/03/2000) | ||
66 | * | ||
67 | * The Init und Exit Module Function are updated. | ||
68 | * (01/03/2000) | ||
69 | * | ||
70 | * version 0.7.0 | ||
71 | * Rewrite of the driver : The driver now uses URB's. The old stuff | ||
72 | * has been removed. | ||
73 | * | ||
74 | * version 0.6.0 | ||
75 | * Rewrite of this driver: The Emulation of the rs232 protocoll | ||
76 | * has been removed from the driver. A special executeCommand function | ||
77 | * for this driver is included to gphoto. | ||
78 | * The driver supports two kind of communication to bulk endpoints. | ||
79 | * Either with the dev->bus->ops->bulk... or with callback function. | ||
80 | * (09/11/1999) | ||
81 | * | ||
82 | * version 0.5.0: | ||
83 | * first Version that gets a version number. Most of the needed | ||
84 | * functions work. | ||
85 | * (20/10/1999) | ||
86 | */ | ||
87 | |||
88 | #include <linux/sched.h> | ||
89 | #include <linux/signal.h> | ||
90 | #include <linux/spinlock.h> | ||
91 | #include <linux/errno.h> | ||
92 | #include <linux/random.h> | ||
93 | #include <linux/poll.h> | ||
94 | #include <linux/init.h> | ||
95 | #include <linux/slab.h> | ||
96 | #include <linux/module.h> | ||
97 | #include <linux/smp_lock.h> | ||
98 | #include <linux/wait.h> | ||
99 | |||
100 | #include <linux/usb.h> | ||
101 | #include <linux/fs.h> | ||
102 | |||
103 | /* | ||
104 | * Version Information | ||
105 | */ | ||
106 | #define DRIVER_VERSION "v0.7.5 (30/10/2000)" | ||
107 | #define DRIVER_AUTHOR "Henning Zabel <henning@uni-paderborn.de>" | ||
108 | #define DRIVER_DESC "USB Driver for Mustek MDC800 Digital Camera" | ||
109 | |||
110 | /* Vendor and Product Information */ | ||
111 | #define MDC800_VENDOR_ID 0x055f | ||
112 | #define MDC800_PRODUCT_ID 0xa800 | ||
113 | |||
114 | /* Timeouts (msec) */ | ||
115 | #define TO_DOWNLOAD_GET_READY 1500 | ||
116 | #define TO_DOWNLOAD_GET_BUSY 1500 | ||
117 | #define TO_WRITE_GET_READY 1000 | ||
118 | #define TO_DEFAULT_COMMAND 5000 | ||
119 | #define TO_READ_FROM_IRQ TO_DEFAULT_COMMAND | ||
120 | #define TO_GET_READY TO_DEFAULT_COMMAND | ||
121 | |||
122 | /* Minor Number of the device (create with mknod /dev/mustek c 180 32) */ | ||
123 | #define MDC800_DEVICE_MINOR_BASE 32 | ||
124 | |||
125 | |||
126 | /************************************************************************** | ||
127 | Data and structs | ||
128 | ***************************************************************************/ | ||
129 | |||
130 | |||
131 | typedef enum { | ||
132 | NOT_CONNECTED, READY, WORKING, DOWNLOAD | ||
133 | } mdc800_state; | ||
134 | |||
135 | |||
136 | /* Data for the driver */ | ||
137 | struct mdc800_data | ||
138 | { | ||
139 | struct usb_device * dev; // Device Data | ||
140 | mdc800_state state; | ||
141 | |||
142 | unsigned int endpoint [4]; | ||
143 | |||
144 | struct urb * irq_urb; | ||
145 | wait_queue_head_t irq_wait; | ||
146 | int irq_woken; | ||
147 | char* irq_urb_buffer; | ||
148 | |||
149 | int camera_busy; // is camera busy ? | ||
150 | int camera_request_ready; // Status to synchronize with irq | ||
151 | char camera_response [8]; // last Bytes send after busy | ||
152 | |||
153 | struct urb * write_urb; | ||
154 | char* write_urb_buffer; | ||
155 | wait_queue_head_t write_wait; | ||
156 | int written; | ||
157 | |||
158 | |||
159 | struct urb * download_urb; | ||
160 | char* download_urb_buffer; | ||
161 | wait_queue_head_t download_wait; | ||
162 | int downloaded; | ||
163 | int download_left; // Bytes left to download ? | ||
164 | |||
165 | |||
166 | /* Device Data */ | ||
167 | char out [64]; // Answer Buffer | ||
168 | int out_ptr; // Index to the first not readen byte | ||
169 | int out_count; // Bytes in the buffer | ||
170 | |||
171 | int open; // Camera device open ? | ||
172 | struct semaphore io_lock; // IO -lock | ||
173 | |||
174 | char in [8]; // Command Input Buffer | ||
175 | int in_count; | ||
176 | |||
177 | int pic_index; // Cache for the Imagesize (-1 for nothing cached ) | ||
178 | int pic_len; | ||
179 | int minor; | ||
180 | }; | ||
181 | |||
182 | |||
183 | /* Specification of the Endpoints */ | ||
184 | static struct usb_endpoint_descriptor mdc800_ed [4] = | ||
185 | { | ||
186 | { | ||
187 | .bLength = 0, | ||
188 | .bDescriptorType = 0, | ||
189 | .bEndpointAddress = 0x01, | ||
190 | .bmAttributes = 0x02, | ||
191 | .wMaxPacketSize = __constant_cpu_to_le16(8), | ||
192 | .bInterval = 0, | ||
193 | .bRefresh = 0, | ||
194 | .bSynchAddress = 0, | ||
195 | }, | ||
196 | { | ||
197 | .bLength = 0, | ||
198 | .bDescriptorType = 0, | ||
199 | .bEndpointAddress = 0x82, | ||
200 | .bmAttributes = 0x03, | ||
201 | .wMaxPacketSize = __constant_cpu_to_le16(8), | ||
202 | .bInterval = 0, | ||
203 | .bRefresh = 0, | ||
204 | .bSynchAddress = 0, | ||
205 | }, | ||
206 | { | ||
207 | .bLength = 0, | ||
208 | .bDescriptorType = 0, | ||
209 | .bEndpointAddress = 0x03, | ||
210 | .bmAttributes = 0x02, | ||
211 | .wMaxPacketSize = __constant_cpu_to_le16(64), | ||
212 | .bInterval = 0, | ||
213 | .bRefresh = 0, | ||
214 | .bSynchAddress = 0, | ||
215 | }, | ||
216 | { | ||
217 | .bLength = 0, | ||
218 | .bDescriptorType = 0, | ||
219 | .bEndpointAddress = 0x84, | ||
220 | .bmAttributes = 0x02, | ||
221 | .wMaxPacketSize = __constant_cpu_to_le16(64), | ||
222 | .bInterval = 0, | ||
223 | .bRefresh = 0, | ||
224 | .bSynchAddress = 0, | ||
225 | }, | ||
226 | }; | ||
227 | |||
228 | /* The Variable used by the driver */ | ||
229 | static struct mdc800_data* mdc800; | ||
230 | |||
231 | |||
232 | /*************************************************************************** | ||
233 | The USB Part of the driver | ||
234 | ****************************************************************************/ | ||
235 | |||
236 | static int mdc800_endpoint_equals (struct usb_endpoint_descriptor *a,struct usb_endpoint_descriptor *b) | ||
237 | { | ||
238 | return ( | ||
239 | ( a->bEndpointAddress == b->bEndpointAddress ) | ||
240 | && ( a->bmAttributes == b->bmAttributes ) | ||
241 | && ( a->wMaxPacketSize == b->wMaxPacketSize ) | ||
242 | ); | ||
243 | } | ||
244 | |||
245 | |||
246 | /* | ||
247 | * Checks whether the camera responds busy | ||
248 | */ | ||
249 | static int mdc800_isBusy (char* ch) | ||
250 | { | ||
251 | int i=0; | ||
252 | while (i<8) | ||
253 | { | ||
254 | if (ch [i] != (char)0x99) | ||
255 | return 0; | ||
256 | i++; | ||
257 | } | ||
258 | return 1; | ||
259 | } | ||
260 | |||
261 | |||
262 | /* | ||
263 | * Checks whether the Camera is ready | ||
264 | */ | ||
265 | static int mdc800_isReady (char *ch) | ||
266 | { | ||
267 | int i=0; | ||
268 | while (i<8) | ||
269 | { | ||
270 | if (ch [i] != (char)0xbb) | ||
271 | return 0; | ||
272 | i++; | ||
273 | } | ||
274 | return 1; | ||
275 | } | ||
276 | |||
277 | |||
278 | |||
279 | /* | ||
280 | * USB IRQ Handler for InputLine | ||
281 | */ | ||
282 | static void mdc800_usb_irq (struct urb *urb, struct pt_regs *res) | ||
283 | { | ||
284 | int data_received=0, wake_up; | ||
285 | unsigned char* b=urb->transfer_buffer; | ||
286 | struct mdc800_data* mdc800=urb->context; | ||
287 | |||
288 | if (urb->status >= 0) | ||
289 | { | ||
290 | |||
291 | //dbg ("%i %i %i %i %i %i %i %i \n",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]); | ||
292 | |||
293 | if (mdc800_isBusy (b)) | ||
294 | { | ||
295 | if (!mdc800->camera_busy) | ||
296 | { | ||
297 | mdc800->camera_busy=1; | ||
298 | dbg ("gets busy"); | ||
299 | } | ||
300 | } | ||
301 | else | ||
302 | { | ||
303 | if (mdc800->camera_busy && mdc800_isReady (b)) | ||
304 | { | ||
305 | mdc800->camera_busy=0; | ||
306 | dbg ("gets ready"); | ||
307 | } | ||
308 | } | ||
309 | if (!(mdc800_isBusy (b) || mdc800_isReady (b))) | ||
310 | { | ||
311 | /* Store Data in camera_answer field */ | ||
312 | dbg ("%i %i %i %i %i %i %i %i ",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]); | ||
313 | |||
314 | memcpy (mdc800->camera_response,b,8); | ||
315 | data_received=1; | ||
316 | } | ||
317 | } | ||
318 | wake_up= ( mdc800->camera_request_ready > 0 ) | ||
319 | && | ||
320 | ( | ||
321 | ((mdc800->camera_request_ready == 1) && (!mdc800->camera_busy)) | ||
322 | || | ||
323 | ((mdc800->camera_request_ready == 2) && data_received) | ||
324 | || | ||
325 | ((mdc800->camera_request_ready == 3) && (mdc800->camera_busy)) | ||
326 | || | ||
327 | (urb->status < 0) | ||
328 | ); | ||
329 | |||
330 | if (wake_up) | ||
331 | { | ||
332 | mdc800->camera_request_ready=0; | ||
333 | mdc800->irq_woken=1; | ||
334 | wake_up (&mdc800->irq_wait); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | |||
339 | /* | ||
340 | * Waits a while until the irq responds that camera is ready | ||
341 | * | ||
342 | * mode : 0: Wait for camera gets ready | ||
343 | * 1: Wait for receiving data | ||
344 | * 2: Wait for camera gets busy | ||
345 | * | ||
346 | * msec: Time to wait | ||
347 | */ | ||
348 | static int mdc800_usb_waitForIRQ (int mode, int msec) | ||
349 | { | ||
350 | mdc800->camera_request_ready=1+mode; | ||
351 | |||
352 | wait_event_timeout(mdc800->irq_wait, mdc800->irq_woken, msec*HZ/1000); | ||
353 | mdc800->irq_woken = 0; | ||
354 | |||
355 | if (mdc800->camera_request_ready>0) | ||
356 | { | ||
357 | mdc800->camera_request_ready=0; | ||
358 | err ("timeout waiting for camera."); | ||
359 | return -1; | ||
360 | } | ||
361 | |||
362 | if (mdc800->state == NOT_CONNECTED) | ||
363 | { | ||
364 | warn ("Camera gets disconnected during waiting for irq."); | ||
365 | mdc800->camera_request_ready=0; | ||
366 | return -2; | ||
367 | } | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | |||
373 | /* | ||
374 | * The write_urb callback function | ||
375 | */ | ||
376 | static void mdc800_usb_write_notify (struct urb *urb, struct pt_regs *res) | ||
377 | { | ||
378 | struct mdc800_data* mdc800=urb->context; | ||
379 | |||
380 | if (urb->status != 0) | ||
381 | { | ||
382 | err ("writing command fails (status=%i)", urb->status); | ||
383 | } | ||
384 | else | ||
385 | { | ||
386 | mdc800->state=READY; | ||
387 | } | ||
388 | mdc800->written = 1; | ||
389 | wake_up (&mdc800->write_wait); | ||
390 | } | ||
391 | |||
392 | |||
393 | /* | ||
394 | * The download_urb callback function | ||
395 | */ | ||
396 | static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res) | ||
397 | { | ||
398 | struct mdc800_data* mdc800=urb->context; | ||
399 | |||
400 | if (urb->status == 0) | ||
401 | { | ||
402 | /* Fill output buffer with these data */ | ||
403 | memcpy (mdc800->out, urb->transfer_buffer, 64); | ||
404 | mdc800->out_count=64; | ||
405 | mdc800->out_ptr=0; | ||
406 | mdc800->download_left-=64; | ||
407 | if (mdc800->download_left == 0) | ||
408 | { | ||
409 | mdc800->state=READY; | ||
410 | } | ||
411 | } | ||
412 | else | ||
413 | { | ||
414 | err ("request bytes fails (status:%i)", urb->status); | ||
415 | } | ||
416 | mdc800->downloaded = 1; | ||
417 | wake_up (&mdc800->download_wait); | ||
418 | } | ||
419 | |||
420 | |||
421 | /*************************************************************************** | ||
422 | Probing for the Camera | ||
423 | ***************************************************************************/ | ||
424 | |||
425 | static struct usb_driver mdc800_usb_driver; | ||
426 | static struct file_operations mdc800_device_ops; | ||
427 | static struct usb_class_driver mdc800_class = { | ||
428 | .name = "usb/mdc800%d", | ||
429 | .fops = &mdc800_device_ops, | ||
430 | .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, | ||
431 | .minor_base = MDC800_DEVICE_MINOR_BASE, | ||
432 | }; | ||
433 | |||
434 | |||
435 | /* | ||
436 | * Callback to search the Mustek MDC800 on the USB Bus | ||
437 | */ | ||
438 | static int mdc800_usb_probe (struct usb_interface *intf, | ||
439 | const struct usb_device_id *id) | ||
440 | { | ||
441 | int i,j; | ||
442 | struct usb_host_interface *intf_desc; | ||
443 | struct usb_device *dev = interface_to_usbdev (intf); | ||
444 | int irq_interval=0; | ||
445 | int retval; | ||
446 | |||
447 | dbg ("(mdc800_usb_probe) called."); | ||
448 | |||
449 | |||
450 | if (mdc800->dev != NULL) | ||
451 | { | ||
452 | warn ("only one Mustek MDC800 is supported."); | ||
453 | return -ENODEV; | ||
454 | } | ||
455 | |||
456 | if (dev->descriptor.bNumConfigurations != 1) | ||
457 | { | ||
458 | err ("probe fails -> wrong Number of Configuration"); | ||
459 | return -ENODEV; | ||
460 | } | ||
461 | intf_desc = intf->cur_altsetting; | ||
462 | |||
463 | if ( | ||
464 | ( intf_desc->desc.bInterfaceClass != 0xff ) | ||
465 | || ( intf_desc->desc.bInterfaceSubClass != 0 ) | ||
466 | || ( intf_desc->desc.bInterfaceProtocol != 0 ) | ||
467 | || ( intf_desc->desc.bNumEndpoints != 4) | ||
468 | ) | ||
469 | { | ||
470 | err ("probe fails -> wrong Interface"); | ||
471 | return -ENODEV; | ||
472 | } | ||
473 | |||
474 | /* Check the Endpoints */ | ||
475 | for (i=0; i<4; i++) | ||
476 | { | ||
477 | mdc800->endpoint[i]=-1; | ||
478 | for (j=0; j<4; j++) | ||
479 | { | ||
480 | if (mdc800_endpoint_equals (&intf_desc->endpoint [j].desc,&mdc800_ed [i])) | ||
481 | { | ||
482 | mdc800->endpoint[i]=intf_desc->endpoint [j].desc.bEndpointAddress ; | ||
483 | if (i==1) | ||
484 | { | ||
485 | irq_interval=intf_desc->endpoint [j].desc.bInterval; | ||
486 | } | ||
487 | |||
488 | continue; | ||
489 | } | ||
490 | } | ||
491 | if (mdc800->endpoint[i] == -1) | ||
492 | { | ||
493 | err ("probe fails -> Wrong Endpoints."); | ||
494 | return -ENODEV; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | |||
499 | info ("Found Mustek MDC800 on USB."); | ||
500 | |||
501 | down (&mdc800->io_lock); | ||
502 | |||
503 | retval = usb_register_dev(intf, &mdc800_class); | ||
504 | if (retval) { | ||
505 | err ("Not able to get a minor for this device."); | ||
506 | return -ENODEV; | ||
507 | } | ||
508 | |||
509 | mdc800->dev=dev; | ||
510 | mdc800->open=0; | ||
511 | |||
512 | /* Setup URB Structs */ | ||
513 | usb_fill_int_urb ( | ||
514 | mdc800->irq_urb, | ||
515 | mdc800->dev, | ||
516 | usb_rcvintpipe (mdc800->dev,mdc800->endpoint [1]), | ||
517 | mdc800->irq_urb_buffer, | ||
518 | 8, | ||
519 | mdc800_usb_irq, | ||
520 | mdc800, | ||
521 | irq_interval | ||
522 | ); | ||
523 | |||
524 | usb_fill_bulk_urb ( | ||
525 | mdc800->write_urb, | ||
526 | mdc800->dev, | ||
527 | usb_sndbulkpipe (mdc800->dev, mdc800->endpoint[0]), | ||
528 | mdc800->write_urb_buffer, | ||
529 | 8, | ||
530 | mdc800_usb_write_notify, | ||
531 | mdc800 | ||
532 | ); | ||
533 | |||
534 | usb_fill_bulk_urb ( | ||
535 | mdc800->download_urb, | ||
536 | mdc800->dev, | ||
537 | usb_rcvbulkpipe (mdc800->dev, mdc800->endpoint [3]), | ||
538 | mdc800->download_urb_buffer, | ||
539 | 64, | ||
540 | mdc800_usb_download_notify, | ||
541 | mdc800 | ||
542 | ); | ||
543 | |||
544 | mdc800->state=READY; | ||
545 | |||
546 | up (&mdc800->io_lock); | ||
547 | |||
548 | usb_set_intfdata(intf, mdc800); | ||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | |||
553 | /* | ||
554 | * Disconnect USB device (maybe the MDC800) | ||
555 | */ | ||
556 | static void mdc800_usb_disconnect (struct usb_interface *intf) | ||
557 | { | ||
558 | struct mdc800_data* mdc800 = usb_get_intfdata(intf); | ||
559 | |||
560 | dbg ("(mdc800_usb_disconnect) called"); | ||
561 | |||
562 | if (mdc800) { | ||
563 | if (mdc800->state == NOT_CONNECTED) | ||
564 | return; | ||
565 | |||
566 | usb_deregister_dev(intf, &mdc800_class); | ||
567 | |||
568 | mdc800->state=NOT_CONNECTED; | ||
569 | |||
570 | usb_kill_urb(mdc800->irq_urb); | ||
571 | usb_kill_urb(mdc800->write_urb); | ||
572 | usb_kill_urb(mdc800->download_urb); | ||
573 | |||
574 | mdc800->dev = NULL; | ||
575 | usb_set_intfdata(intf, NULL); | ||
576 | } | ||
577 | info ("Mustek MDC800 disconnected from USB."); | ||
578 | } | ||
579 | |||
580 | |||
581 | /*************************************************************************** | ||
582 | The Misc device Part (file_operations) | ||
583 | ****************************************************************************/ | ||
584 | |||
585 | /* | ||
586 | * This Function calc the Answersize for a command. | ||
587 | */ | ||
588 | static int mdc800_getAnswerSize (char command) | ||
589 | { | ||
590 | switch ((unsigned char) command) | ||
591 | { | ||
592 | case 0x2a: | ||
593 | case 0x49: | ||
594 | case 0x51: | ||
595 | case 0x0d: | ||
596 | case 0x20: | ||
597 | case 0x07: | ||
598 | case 0x01: | ||
599 | case 0x25: | ||
600 | case 0x00: | ||
601 | return 8; | ||
602 | |||
603 | case 0x05: | ||
604 | case 0x3e: | ||
605 | return mdc800->pic_len; | ||
606 | |||
607 | case 0x09: | ||
608 | return 4096; | ||
609 | |||
610 | default: | ||
611 | return 0; | ||
612 | } | ||
613 | } | ||
614 | |||
615 | |||
616 | /* | ||
617 | * Init the device: (1) alloc mem (2) Increase MOD Count .. | ||
618 | */ | ||
619 | static int mdc800_device_open (struct inode* inode, struct file *file) | ||
620 | { | ||
621 | int retval=0; | ||
622 | int errn=0; | ||
623 | |||
624 | down (&mdc800->io_lock); | ||
625 | |||
626 | if (mdc800->state == NOT_CONNECTED) | ||
627 | { | ||
628 | errn=-EBUSY; | ||
629 | goto error_out; | ||
630 | } | ||
631 | if (mdc800->open) | ||
632 | { | ||
633 | errn=-EBUSY; | ||
634 | goto error_out; | ||
635 | } | ||
636 | |||
637 | mdc800->in_count=0; | ||
638 | mdc800->out_count=0; | ||
639 | mdc800->out_ptr=0; | ||
640 | mdc800->pic_index=0; | ||
641 | mdc800->pic_len=-1; | ||
642 | mdc800->download_left=0; | ||
643 | |||
644 | mdc800->camera_busy=0; | ||
645 | mdc800->camera_request_ready=0; | ||
646 | |||
647 | retval=0; | ||
648 | mdc800->irq_urb->dev = mdc800->dev; | ||
649 | if (usb_submit_urb (mdc800->irq_urb, GFP_KERNEL)) | ||
650 | { | ||
651 | err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status); | ||
652 | errn = -EIO; | ||
653 | goto error_out; | ||
654 | } | ||
655 | |||
656 | mdc800->open=1; | ||
657 | dbg ("Mustek MDC800 device opened."); | ||
658 | |||
659 | error_out: | ||
660 | up (&mdc800->io_lock); | ||
661 | return errn; | ||
662 | } | ||
663 | |||
664 | |||
665 | /* | ||
666 | * Close the Camera and release Memory | ||
667 | */ | ||
668 | static int mdc800_device_release (struct inode* inode, struct file *file) | ||
669 | { | ||
670 | int retval=0; | ||
671 | dbg ("Mustek MDC800 device closed."); | ||
672 | |||
673 | down (&mdc800->io_lock); | ||
674 | if (mdc800->open && (mdc800->state != NOT_CONNECTED)) | ||
675 | { | ||
676 | usb_kill_urb(mdc800->irq_urb); | ||
677 | usb_kill_urb(mdc800->write_urb); | ||
678 | usb_kill_urb(mdc800->download_urb); | ||
679 | mdc800->open=0; | ||
680 | } | ||
681 | else | ||
682 | { | ||
683 | retval=-EIO; | ||
684 | } | ||
685 | |||
686 | up(&mdc800->io_lock); | ||
687 | return retval; | ||
688 | } | ||
689 | |||
690 | |||
691 | /* | ||
692 | * The Device read callback Function | ||
693 | */ | ||
694 | static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t len, loff_t *pos) | ||
695 | { | ||
696 | size_t left=len, sts=len; /* single transfer size */ | ||
697 | char __user *ptr = buf; | ||
698 | |||
699 | down (&mdc800->io_lock); | ||
700 | if (mdc800->state == NOT_CONNECTED) | ||
701 | { | ||
702 | up (&mdc800->io_lock); | ||
703 | return -EBUSY; | ||
704 | } | ||
705 | if (mdc800->state == WORKING) | ||
706 | { | ||
707 | warn ("Illegal State \"working\" reached during read ?!"); | ||
708 | up (&mdc800->io_lock); | ||
709 | return -EBUSY; | ||
710 | } | ||
711 | if (!mdc800->open) | ||
712 | { | ||
713 | up (&mdc800->io_lock); | ||
714 | return -EBUSY; | ||
715 | } | ||
716 | |||
717 | while (left) | ||
718 | { | ||
719 | if (signal_pending (current)) | ||
720 | { | ||
721 | up (&mdc800->io_lock); | ||
722 | return -EINTR; | ||
723 | } | ||
724 | |||
725 | sts=left > (mdc800->out_count-mdc800->out_ptr)?mdc800->out_count-mdc800->out_ptr:left; | ||
726 | |||
727 | if (sts <= 0) | ||
728 | { | ||
729 | /* Too less Data in buffer */ | ||
730 | if (mdc800->state == DOWNLOAD) | ||
731 | { | ||
732 | mdc800->out_count=0; | ||
733 | mdc800->out_ptr=0; | ||
734 | |||
735 | /* Download -> Request new bytes */ | ||
736 | mdc800->download_urb->dev = mdc800->dev; | ||
737 | if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL)) | ||
738 | { | ||
739 | err ("Can't submit download urb (status=%i)",mdc800->download_urb->status); | ||
740 | up (&mdc800->io_lock); | ||
741 | return len-left; | ||
742 | } | ||
743 | wait_event_timeout(mdc800->download_wait, mdc800->downloaded, | ||
744 | TO_DOWNLOAD_GET_READY*HZ/1000); | ||
745 | mdc800->downloaded = 0; | ||
746 | if (mdc800->download_urb->status != 0) | ||
747 | { | ||
748 | err ("request download-bytes fails (status=%i)",mdc800->download_urb->status); | ||
749 | up (&mdc800->io_lock); | ||
750 | return len-left; | ||
751 | } | ||
752 | } | ||
753 | else | ||
754 | { | ||
755 | /* No more bytes -> that's an error*/ | ||
756 | up (&mdc800->io_lock); | ||
757 | return -EIO; | ||
758 | } | ||
759 | } | ||
760 | else | ||
761 | { | ||
762 | /* Copy Bytes */ | ||
763 | if (copy_to_user(ptr, &mdc800->out [mdc800->out_ptr], | ||
764 | sts)) { | ||
765 | up(&mdc800->io_lock); | ||
766 | return -EFAULT; | ||
767 | } | ||
768 | ptr+=sts; | ||
769 | left-=sts; | ||
770 | mdc800->out_ptr+=sts; | ||
771 | } | ||
772 | } | ||
773 | |||
774 | up (&mdc800->io_lock); | ||
775 | return len-left; | ||
776 | } | ||
777 | |||
778 | |||
779 | /* | ||
780 | * The Device write callback Function | ||
781 | * If a 8Byte Command is received, it will be send to the camera. | ||
782 | * After this the driver initiates the request for the answer or | ||
783 | * just waits until the camera becomes ready. | ||
784 | */ | ||
785 | static ssize_t mdc800_device_write (struct file *file, const char __user *buf, size_t len, loff_t *pos) | ||
786 | { | ||
787 | size_t i=0; | ||
788 | |||
789 | down (&mdc800->io_lock); | ||
790 | if (mdc800->state != READY) | ||
791 | { | ||
792 | up (&mdc800->io_lock); | ||
793 | return -EBUSY; | ||
794 | } | ||
795 | if (!mdc800->open ) | ||
796 | { | ||
797 | up (&mdc800->io_lock); | ||
798 | return -EBUSY; | ||
799 | } | ||
800 | |||
801 | while (i<len) | ||
802 | { | ||
803 | unsigned char c; | ||
804 | if (signal_pending (current)) | ||
805 | { | ||
806 | up (&mdc800->io_lock); | ||
807 | return -EINTR; | ||
808 | } | ||
809 | |||
810 | if(get_user(c, buf+i)) | ||
811 | { | ||
812 | up(&mdc800->io_lock); | ||
813 | return -EFAULT; | ||
814 | } | ||
815 | |||
816 | /* check for command start */ | ||
817 | if (c == 0x55) | ||
818 | { | ||
819 | mdc800->in_count=0; | ||
820 | mdc800->out_count=0; | ||
821 | mdc800->out_ptr=0; | ||
822 | mdc800->download_left=0; | ||
823 | } | ||
824 | |||
825 | /* save command byte */ | ||
826 | if (mdc800->in_count < 8) | ||
827 | { | ||
828 | mdc800->in[mdc800->in_count] = c; | ||
829 | mdc800->in_count++; | ||
830 | } | ||
831 | else | ||
832 | { | ||
833 | up (&mdc800->io_lock); | ||
834 | return -EIO; | ||
835 | } | ||
836 | |||
837 | /* Command Buffer full ? -> send it to camera */ | ||
838 | if (mdc800->in_count == 8) | ||
839 | { | ||
840 | int answersize; | ||
841 | |||
842 | if (mdc800_usb_waitForIRQ (0,TO_GET_READY)) | ||
843 | { | ||
844 | err ("Camera didn't get ready.\n"); | ||
845 | up (&mdc800->io_lock); | ||
846 | return -EIO; | ||
847 | } | ||
848 | |||
849 | answersize=mdc800_getAnswerSize (mdc800->in[1]); | ||
850 | |||
851 | mdc800->state=WORKING; | ||
852 | memcpy (mdc800->write_urb->transfer_buffer, mdc800->in,8); | ||
853 | mdc800->write_urb->dev = mdc800->dev; | ||
854 | if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL)) | ||
855 | { | ||
856 | err ("submitting write urb fails (status=%i)", mdc800->write_urb->status); | ||
857 | up (&mdc800->io_lock); | ||
858 | return -EIO; | ||
859 | } | ||
860 | wait_event_timeout(mdc800->write_wait, mdc800->written, TO_WRITE_GET_READY*HZ/1000); | ||
861 | mdc800->written = 0; | ||
862 | if (mdc800->state == WORKING) | ||
863 | { | ||
864 | usb_kill_urb(mdc800->write_urb); | ||
865 | up (&mdc800->io_lock); | ||
866 | return -EIO; | ||
867 | } | ||
868 | |||
869 | switch ((unsigned char) mdc800->in[1]) | ||
870 | { | ||
871 | case 0x05: /* Download Image */ | ||
872 | case 0x3e: /* Take shot in Fine Mode (WCam Mode) */ | ||
873 | if (mdc800->pic_len < 0) | ||
874 | { | ||
875 | err ("call 0x07 before 0x05,0x3e"); | ||
876 | mdc800->state=READY; | ||
877 | up (&mdc800->io_lock); | ||
878 | return -EIO; | ||
879 | } | ||
880 | mdc800->pic_len=-1; | ||
881 | |||
882 | case 0x09: /* Download Thumbnail */ | ||
883 | mdc800->download_left=answersize+64; | ||
884 | mdc800->state=DOWNLOAD; | ||
885 | mdc800_usb_waitForIRQ (0,TO_DOWNLOAD_GET_BUSY); | ||
886 | break; | ||
887 | |||
888 | |||
889 | default: | ||
890 | if (answersize) | ||
891 | { | ||
892 | |||
893 | if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ)) | ||
894 | { | ||
895 | err ("requesting answer from irq fails"); | ||
896 | up (&mdc800->io_lock); | ||
897 | return -EIO; | ||
898 | } | ||
899 | |||
900 | /* Write dummy data, (this is ugly but part of the USB Protocol */ | ||
901 | /* if you use endpoint 1 as bulk and not as irq) */ | ||
902 | memcpy (mdc800->out, mdc800->camera_response,8); | ||
903 | |||
904 | /* This is the interpreted answer */ | ||
905 | memcpy (&mdc800->out[8], mdc800->camera_response,8); | ||
906 | |||
907 | mdc800->out_ptr=0; | ||
908 | mdc800->out_count=16; | ||
909 | |||
910 | /* Cache the Imagesize, if command was getImageSize */ | ||
911 | if (mdc800->in [1] == (char) 0x07) | ||
912 | { | ||
913 | mdc800->pic_len=(int) 65536*(unsigned char) mdc800->camera_response[0]+256*(unsigned char) mdc800->camera_response[1]+(unsigned char) mdc800->camera_response[2]; | ||
914 | |||
915 | dbg ("cached imagesize = %i",mdc800->pic_len); | ||
916 | } | ||
917 | |||
918 | } | ||
919 | else | ||
920 | { | ||
921 | if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND)) | ||
922 | { | ||
923 | err ("Command Timeout."); | ||
924 | up (&mdc800->io_lock); | ||
925 | return -EIO; | ||
926 | } | ||
927 | } | ||
928 | mdc800->state=READY; | ||
929 | break; | ||
930 | } | ||
931 | } | ||
932 | i++; | ||
933 | } | ||
934 | up (&mdc800->io_lock); | ||
935 | return i; | ||
936 | } | ||
937 | |||
938 | |||
939 | /*************************************************************************** | ||
940 | Init and Cleanup this driver (Structs and types) | ||
941 | ****************************************************************************/ | ||
942 | |||
943 | /* File Operations of this drivers */ | ||
944 | static struct file_operations mdc800_device_ops = | ||
945 | { | ||
946 | .owner = THIS_MODULE, | ||
947 | .read = mdc800_device_read, | ||
948 | .write = mdc800_device_write, | ||
949 | .open = mdc800_device_open, | ||
950 | .release = mdc800_device_release, | ||
951 | }; | ||
952 | |||
953 | |||
954 | |||
955 | static struct usb_device_id mdc800_table [] = { | ||
956 | { USB_DEVICE(MDC800_VENDOR_ID, MDC800_PRODUCT_ID) }, | ||
957 | { } /* Terminating entry */ | ||
958 | }; | ||
959 | |||
960 | MODULE_DEVICE_TABLE (usb, mdc800_table); | ||
961 | /* | ||
962 | * USB Driver Struct for this device | ||
963 | */ | ||
964 | static struct usb_driver mdc800_usb_driver = | ||
965 | { | ||
966 | .owner = THIS_MODULE, | ||
967 | .name = "mdc800", | ||
968 | .probe = mdc800_usb_probe, | ||
969 | .disconnect = mdc800_usb_disconnect, | ||
970 | .id_table = mdc800_table | ||
971 | }; | ||
972 | |||
973 | |||
974 | |||
975 | /************************************************************************ | ||
976 | Init and Cleanup this driver (Main Functions) | ||
977 | *************************************************************************/ | ||
978 | |||
979 | #define try(A) if (!(A)) goto cleanup_on_fail; | ||
980 | |||
981 | static int __init usb_mdc800_init (void) | ||
982 | { | ||
983 | int retval = -ENODEV; | ||
984 | /* Allocate Memory */ | ||
985 | try (mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL)); | ||
986 | |||
987 | memset(mdc800, 0, sizeof(struct mdc800_data)); | ||
988 | mdc800->dev = NULL; | ||
989 | mdc800->open=0; | ||
990 | mdc800->state=NOT_CONNECTED; | ||
991 | init_MUTEX (&mdc800->io_lock); | ||
992 | |||
993 | init_waitqueue_head (&mdc800->irq_wait); | ||
994 | init_waitqueue_head (&mdc800->write_wait); | ||
995 | init_waitqueue_head (&mdc800->download_wait); | ||
996 | |||
997 | mdc800->irq_woken = 0; | ||
998 | mdc800->downloaded = 0; | ||
999 | mdc800->written = 0; | ||
1000 | |||
1001 | try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL)); | ||
1002 | try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL)); | ||
1003 | try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL)); | ||
1004 | |||
1005 | try (mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL)); | ||
1006 | try (mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL)); | ||
1007 | try (mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL)); | ||
1008 | |||
1009 | /* Register the driver */ | ||
1010 | retval = usb_register(&mdc800_usb_driver); | ||
1011 | if (retval) | ||
1012 | goto cleanup_on_fail; | ||
1013 | |||
1014 | info (DRIVER_VERSION ":" DRIVER_DESC); | ||
1015 | |||
1016 | return 0; | ||
1017 | |||
1018 | /* Clean driver up, when something fails */ | ||
1019 | |||
1020 | cleanup_on_fail: | ||
1021 | |||
1022 | if (mdc800 != NULL) | ||
1023 | { | ||
1024 | err ("can't alloc memory!"); | ||
1025 | |||
1026 | kfree(mdc800->download_urb_buffer); | ||
1027 | kfree(mdc800->write_urb_buffer); | ||
1028 | kfree(mdc800->irq_urb_buffer); | ||
1029 | |||
1030 | usb_free_urb(mdc800->write_urb); | ||
1031 | usb_free_urb(mdc800->download_urb); | ||
1032 | usb_free_urb(mdc800->irq_urb); | ||
1033 | |||
1034 | kfree (mdc800); | ||
1035 | } | ||
1036 | mdc800 = NULL; | ||
1037 | return retval; | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | static void __exit usb_mdc800_cleanup (void) | ||
1042 | { | ||
1043 | usb_deregister (&mdc800_usb_driver); | ||
1044 | |||
1045 | usb_free_urb (mdc800->irq_urb); | ||
1046 | usb_free_urb (mdc800->download_urb); | ||
1047 | usb_free_urb (mdc800->write_urb); | ||
1048 | |||
1049 | kfree (mdc800->irq_urb_buffer); | ||
1050 | kfree (mdc800->write_urb_buffer); | ||
1051 | kfree (mdc800->download_urb_buffer); | ||
1052 | |||
1053 | kfree (mdc800); | ||
1054 | mdc800 = NULL; | ||
1055 | } | ||
1056 | |||
1057 | module_init (usb_mdc800_init); | ||
1058 | module_exit (usb_mdc800_cleanup); | ||
1059 | |||
1060 | MODULE_AUTHOR( DRIVER_AUTHOR ); | ||
1061 | MODULE_DESCRIPTION( DRIVER_DESC ); | ||
1062 | MODULE_LICENSE("GPL"); | ||
1063 | |||
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c new file mode 100644 index 000000000000..de0d32f6618d --- /dev/null +++ b/drivers/usb/image/microtek.c | |||
@@ -0,0 +1,862 @@ | |||
1 | /* Driver for Microtek Scanmaker X6 USB scanner, and possibly others. | ||
2 | * | ||
3 | * (C) Copyright 2000 John Fremlin <vii@penguinpowered.com> | ||
4 | * (C) Copyright 2000 Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de> | ||
5 | * | ||
6 | * Parts shamelessly stolen from usb-storage and copyright by their | ||
7 | * authors. Thanks to Matt Dharm for giving us permission! | ||
8 | * | ||
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_. | ||
12 | * | ||
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. | ||
16 | * | ||
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. | ||
24 | * | ||
25 | * It seems possible to read (with URB transfers) everything from 0x82 | ||
26 | * in one go, without bothering to read in 32 byte chunks. | ||
27 | * | ||
28 | * There seems to be an optimisation of a further READ implicit if | ||
29 | * you simply read from 0x83. | ||
30 | * | ||
31 | * Guessed protocol: | ||
32 | * | ||
33 | * Send raw SCSI command to EP 0x1 | ||
34 | * | ||
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 | ||
43 | * | ||
44 | * Read status byte from EP 0x82 | ||
45 | * | ||
46 | * References: | ||
47 | * | ||
48 | * The SCSI command set for the scanner is available from | ||
49 | * ftp://ftp.microtek.com/microtek/devpack/ | ||
50 | * | ||
51 | * Microtek NV sent us a more up to date version of the document. If | ||
52 | * you want it, just send mail. | ||
53 | * | ||
54 | * Status: | ||
55 | * | ||
56 | * Untested with multiple scanners. | ||
57 | * Untested on SMP. | ||
58 | * Untested on a bigendian machine. | ||
59 | * | ||
60 | * History: | ||
61 | * | ||
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 | ||
107 | * 20010210 New abort logic | ||
108 | * 20010210 Version 0.3.0 | ||
109 | * 20010217 Merged scatter/gather | ||
110 | * 20010218 Version 0.4.0 | ||
111 | * 20010218 Cosmetic fixes | ||
112 | * 20010218 Version 0.4.1 | ||
113 | * 20010306 Abort while using scatter/gather | ||
114 | * 20010306 Version 0.4.2 | ||
115 | * 20010311 Remove all timeouts and tidy up generally (john) | ||
116 | * 20010320 check return value of scsi_register() | ||
117 | * 20010320 Version 0.4.3 | ||
118 | * 20010408 Identify version on module load. | ||
119 | * 20011003 Fix multiple requests | ||
120 | */ | ||
121 | |||
122 | #include <linux/module.h> | ||
123 | #include <linux/kernel.h> | ||
124 | #include <linux/sched.h> | ||
125 | #include <linux/signal.h> | ||
126 | #include <linux/errno.h> | ||
127 | #include <linux/random.h> | ||
128 | #include <linux/poll.h> | ||
129 | #include <linux/init.h> | ||
130 | #include <linux/slab.h> | ||
131 | #include <linux/spinlock.h> | ||
132 | #include <linux/smp_lock.h> | ||
133 | #include <linux/usb.h> | ||
134 | #include <linux/proc_fs.h> | ||
135 | |||
136 | #include <asm/atomic.h> | ||
137 | #include <linux/blkdev.h> | ||
138 | #include "../../scsi/scsi.h" | ||
139 | #include <scsi/scsi_host.h> | ||
140 | |||
141 | #include "microtek.h" | ||
142 | |||
143 | /* | ||
144 | * Version Information | ||
145 | */ | ||
146 | #define DRIVER_VERSION "v0.4.3" | ||
147 | #define DRIVER_AUTHOR "John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>" | ||
148 | #define DRIVER_DESC "Microtek Scanmaker X6 USB scanner driver" | ||
149 | |||
150 | /* Should we do debugging? */ | ||
151 | |||
152 | //#define MTS_DO_DEBUG | ||
153 | |||
154 | /* USB layer driver interface */ | ||
155 | |||
156 | static int mts_usb_probe(struct usb_interface *intf, | ||
157 | const struct usb_device_id *id); | ||
158 | static void mts_usb_disconnect(struct usb_interface *intf); | ||
159 | |||
160 | static struct usb_device_id mts_usb_ids []; | ||
161 | |||
162 | static struct usb_driver mts_usb_driver = { | ||
163 | .owner = THIS_MODULE, | ||
164 | .name = "microtekX6", | ||
165 | .probe = mts_usb_probe, | ||
166 | .disconnect = mts_usb_disconnect, | ||
167 | .id_table = mts_usb_ids, | ||
168 | }; | ||
169 | |||
170 | |||
171 | /* Internal driver stuff */ | ||
172 | |||
173 | #define MTS_VERSION "0.4.3" | ||
174 | #define MTS_NAME "microtek usb (rev " MTS_VERSION "): " | ||
175 | |||
176 | #define MTS_WARNING(x...) \ | ||
177 | printk( KERN_WARNING MTS_NAME x ) | ||
178 | #define MTS_ERROR(x...) \ | ||
179 | printk( KERN_ERR MTS_NAME x ) | ||
180 | #define MTS_INT_ERROR(x...) \ | ||
181 | MTS_ERROR(x) | ||
182 | #define MTS_MESSAGE(x...) \ | ||
183 | printk( KERN_INFO MTS_NAME x ) | ||
184 | |||
185 | #if defined MTS_DO_DEBUG | ||
186 | |||
187 | #define MTS_DEBUG(x...) \ | ||
188 | printk( KERN_DEBUG MTS_NAME x ) | ||
189 | |||
190 | #define MTS_DEBUG_GOT_HERE() \ | ||
191 | MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __PRETTY_FUNCTION__ ) | ||
192 | #define MTS_DEBUG_INT() \ | ||
193 | do { MTS_DEBUG_GOT_HERE(); \ | ||
194 | MTS_DEBUG("transfer = 0x%x context = 0x%x\n",(int)transfer,(int)context ); \ | ||
195 | MTS_DEBUG("status = 0x%x data-length = 0x%x sent = 0x%x\n",(int)transfer->status,(int)context->data_length, (int)transfer->actual_length ); \ | ||
196 | mts_debug_dump(context->instance);\ | ||
197 | } while(0) | ||
198 | #else | ||
199 | |||
200 | #define MTS_NUL_STATEMENT do { } while(0) | ||
201 | |||
202 | #define MTS_DEBUG(x...) MTS_NUL_STATEMENT | ||
203 | #define MTS_DEBUG_GOT_HERE() MTS_NUL_STATEMENT | ||
204 | #define MTS_DEBUG_INT() MTS_NUL_STATEMENT | ||
205 | |||
206 | #endif | ||
207 | |||
208 | |||
209 | |||
210 | #define MTS_INT_INIT()\ | ||
211 | struct mts_transfer_context* context = (struct mts_transfer_context*)transfer->context; \ | ||
212 | MTS_DEBUG_INT();\ | ||
213 | |||
214 | #ifdef MTS_DO_DEBUG | ||
215 | |||
216 | static inline void mts_debug_dump(struct mts_desc* desc) { | ||
217 | MTS_DEBUG("desc at 0x%x: toggle = %02x%02x\n", | ||
218 | (int)desc, | ||
219 | (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0] | ||
220 | ); | ||
221 | MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n", | ||
222 | usb_sndbulkpipe(desc->usb_dev,desc->ep_out), | ||
223 | usb_rcvbulkpipe(desc->usb_dev,desc->ep_response), | ||
224 | usb_rcvbulkpipe(desc->usb_dev,desc->ep_image) | ||
225 | ); | ||
226 | } | ||
227 | |||
228 | |||
229 | static inline void mts_show_command(Scsi_Cmnd *srb) | ||
230 | { | ||
231 | char *what = NULL; | ||
232 | |||
233 | switch (srb->cmnd[0]) { | ||
234 | case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break; | ||
235 | case REZERO_UNIT: what = "REZERO_UNIT"; break; | ||
236 | case REQUEST_SENSE: what = "REQUEST_SENSE"; break; | ||
237 | case FORMAT_UNIT: what = "FORMAT_UNIT"; break; | ||
238 | case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break; | ||
239 | case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break; | ||
240 | case READ_6: what = "READ_6"; break; | ||
241 | case WRITE_6: what = "WRITE_6"; break; | ||
242 | case SEEK_6: what = "SEEK_6"; break; | ||
243 | case READ_REVERSE: what = "READ_REVERSE"; break; | ||
244 | case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break; | ||
245 | case SPACE: what = "SPACE"; break; | ||
246 | case INQUIRY: what = "INQUIRY"; break; | ||
247 | case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break; | ||
248 | case MODE_SELECT: what = "MODE_SELECT"; break; | ||
249 | case RESERVE: what = "RESERVE"; break; | ||
250 | case RELEASE: what = "RELEASE"; break; | ||
251 | case COPY: what = "COPY"; break; | ||
252 | case ERASE: what = "ERASE"; break; | ||
253 | case MODE_SENSE: what = "MODE_SENSE"; break; | ||
254 | case START_STOP: what = "START_STOP"; break; | ||
255 | case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break; | ||
256 | case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break; | ||
257 | case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break; | ||
258 | case SET_WINDOW: what = "SET_WINDOW"; break; | ||
259 | case READ_CAPACITY: what = "READ_CAPACITY"; break; | ||
260 | case READ_10: what = "READ_10"; break; | ||
261 | case WRITE_10: what = "WRITE_10"; break; | ||
262 | case SEEK_10: what = "SEEK_10"; break; | ||
263 | case WRITE_VERIFY: what = "WRITE_VERIFY"; break; | ||
264 | case VERIFY: what = "VERIFY"; break; | ||
265 | case SEARCH_HIGH: what = "SEARCH_HIGH"; break; | ||
266 | case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break; | ||
267 | case SEARCH_LOW: what = "SEARCH_LOW"; break; | ||
268 | case SET_LIMITS: what = "SET_LIMITS"; break; | ||
269 | case READ_POSITION: what = "READ_POSITION"; break; | ||
270 | case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break; | ||
271 | case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break; | ||
272 | case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break; | ||
273 | case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break; | ||
274 | case COMPARE: what = "COMPARE"; break; | ||
275 | case COPY_VERIFY: what = "COPY_VERIFY"; break; | ||
276 | case WRITE_BUFFER: what = "WRITE_BUFFER"; break; | ||
277 | case READ_BUFFER: what = "READ_BUFFER"; break; | ||
278 | case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break; | ||
279 | case READ_LONG: what = "READ_LONG"; break; | ||
280 | case WRITE_LONG: what = "WRITE_LONG"; break; | ||
281 | case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break; | ||
282 | case WRITE_SAME: what = "WRITE_SAME"; break; | ||
283 | case READ_TOC: what = "READ_TOC"; break; | ||
284 | case LOG_SELECT: what = "LOG_SELECT"; break; | ||
285 | case LOG_SENSE: what = "LOG_SENSE"; break; | ||
286 | case MODE_SELECT_10: what = "MODE_SELECT_10"; break; | ||
287 | case MODE_SENSE_10: what = "MODE_SENSE_10"; break; | ||
288 | case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break; | ||
289 | case READ_12: what = "READ_12"; break; | ||
290 | case WRITE_12: what = "WRITE_12"; break; | ||
291 | case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break; | ||
292 | case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break; | ||
293 | case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break; | ||
294 | case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break; | ||
295 | case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break; | ||
296 | case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break; | ||
297 | case WRITE_LONG_2: what = "WRITE_LONG_2"; break; | ||
298 | default: | ||
299 | MTS_DEBUG("can't decode command\n"); | ||
300 | goto out; | ||
301 | break; | ||
302 | } | ||
303 | MTS_DEBUG( "Command %s (%d bytes)\n", what, srb->cmd_len); | ||
304 | |||
305 | out: | ||
306 | MTS_DEBUG( " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
307 | srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5], | ||
308 | srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]); | ||
309 | } | ||
310 | |||
311 | #else | ||
312 | |||
313 | static inline void mts_show_command(Scsi_Cmnd * dummy) | ||
314 | { | ||
315 | } | ||
316 | |||
317 | static inline void mts_debug_dump(struct mts_desc* dummy) | ||
318 | { | ||
319 | } | ||
320 | |||
321 | #endif | ||
322 | |||
323 | static inline void mts_urb_abort(struct mts_desc* desc) { | ||
324 | MTS_DEBUG_GOT_HERE(); | ||
325 | mts_debug_dump(desc); | ||
326 | |||
327 | usb_kill_urb( desc->urb ); | ||
328 | } | ||
329 | |||
330 | static int mts_scsi_abort (Scsi_Cmnd *srb) | ||
331 | { | ||
332 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); | ||
333 | |||
334 | MTS_DEBUG_GOT_HERE(); | ||
335 | |||
336 | mts_urb_abort(desc); | ||
337 | |||
338 | return SCSI_ABORT_PENDING; | ||
339 | } | ||
340 | |||
341 | static int mts_scsi_host_reset (Scsi_Cmnd *srb) | ||
342 | { | ||
343 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); | ||
344 | int result, rc; | ||
345 | |||
346 | MTS_DEBUG_GOT_HERE(); | ||
347 | mts_debug_dump(desc); | ||
348 | |||
349 | rc = usb_lock_device_for_reset(desc->usb_dev, desc->usb_intf); | ||
350 | if (rc < 0) | ||
351 | return FAILED; | ||
352 | result = usb_reset_device(desc->usb_dev);; | ||
353 | if (rc) | ||
354 | usb_unlock_device(desc->usb_dev); | ||
355 | return result ? FAILED : SUCCESS; | ||
356 | } | ||
357 | |||
358 | static | ||
359 | int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ); | ||
360 | |||
361 | static void mts_transfer_cleanup( struct urb *transfer ); | ||
362 | static void mts_do_sg(struct urb * transfer, struct pt_regs *regs); | ||
363 | |||
364 | |||
365 | inline static | ||
366 | void mts_int_submit_urb (struct urb* transfer, | ||
367 | int pipe, | ||
368 | void* data, | ||
369 | unsigned length, | ||
370 | usb_complete_t callback ) | ||
371 | /* Interrupt context! */ | ||
372 | |||
373 | /* Holding transfer->context->lock! */ | ||
374 | { | ||
375 | int res; | ||
376 | |||
377 | MTS_INT_INIT(); | ||
378 | |||
379 | usb_fill_bulk_urb(transfer, | ||
380 | context->instance->usb_dev, | ||
381 | pipe, | ||
382 | data, | ||
383 | length, | ||
384 | callback, | ||
385 | context | ||
386 | ); | ||
387 | |||
388 | transfer->status = 0; | ||
389 | |||
390 | res = usb_submit_urb( transfer, GFP_ATOMIC ); | ||
391 | if ( unlikely(res) ) { | ||
392 | MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res ); | ||
393 | context->srb->result = DID_ERROR << 16; | ||
394 | mts_transfer_cleanup(transfer); | ||
395 | } | ||
396 | return; | ||
397 | } | ||
398 | |||
399 | |||
400 | static void mts_transfer_cleanup( struct urb *transfer ) | ||
401 | /* Interrupt context! */ | ||
402 | { | ||
403 | MTS_INT_INIT(); | ||
404 | |||
405 | if ( likely(context->final_callback != NULL) ) | ||
406 | context->final_callback(context->srb); | ||
407 | |||
408 | } | ||
409 | |||
410 | static void mts_transfer_done( struct urb *transfer, struct pt_regs *regs ) | ||
411 | { | ||
412 | MTS_INT_INIT(); | ||
413 | |||
414 | context->srb->result &= MTS_SCSI_ERR_MASK; | ||
415 | context->srb->result |= (unsigned)context->status<<1; | ||
416 | |||
417 | mts_transfer_cleanup(transfer); | ||
418 | |||
419 | return; | ||
420 | } | ||
421 | |||
422 | |||
423 | static void mts_get_status( struct urb *transfer ) | ||
424 | /* Interrupt context! */ | ||
425 | { | ||
426 | MTS_INT_INIT(); | ||
427 | |||
428 | mts_int_submit_urb(transfer, | ||
429 | usb_rcvbulkpipe(context->instance->usb_dev, | ||
430 | context->instance->ep_response), | ||
431 | &context->status, | ||
432 | 1, | ||
433 | mts_transfer_done ); | ||
434 | } | ||
435 | |||
436 | static void mts_data_done( struct urb* transfer, struct pt_regs *regs ) | ||
437 | /* Interrupt context! */ | ||
438 | { | ||
439 | MTS_INT_INIT(); | ||
440 | |||
441 | if ( context->data_length != transfer->actual_length ) { | ||
442 | context->srb->resid = context->data_length - transfer->actual_length; | ||
443 | } else if ( unlikely(transfer->status) ) { | ||
444 | context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; | ||
445 | } | ||
446 | |||
447 | mts_get_status(transfer); | ||
448 | |||
449 | return; | ||
450 | } | ||
451 | |||
452 | |||
453 | static void mts_command_done( struct urb *transfer, struct pt_regs *regs ) | ||
454 | /* Interrupt context! */ | ||
455 | { | ||
456 | MTS_INT_INIT(); | ||
457 | |||
458 | if ( unlikely(transfer->status) ) { | ||
459 | if (transfer->status == -ENOENT) { | ||
460 | /* We are being killed */ | ||
461 | MTS_DEBUG_GOT_HERE(); | ||
462 | context->srb->result = DID_ABORT<<16; | ||
463 | } else { | ||
464 | /* A genuine error has occurred */ | ||
465 | MTS_DEBUG_GOT_HERE(); | ||
466 | |||
467 | context->srb->result = DID_ERROR<<16; | ||
468 | } | ||
469 | mts_transfer_cleanup(transfer); | ||
470 | |||
471 | return; | ||
472 | } | ||
473 | |||
474 | if (context->srb->cmnd[0] == REQUEST_SENSE) { | ||
475 | mts_int_submit_urb(transfer, | ||
476 | context->data_pipe, | ||
477 | context->srb->sense_buffer, | ||
478 | context->data_length, | ||
479 | mts_data_done); | ||
480 | } else { if ( context->data ) { | ||
481 | mts_int_submit_urb(transfer, | ||
482 | context->data_pipe, | ||
483 | context->data, | ||
484 | context->data_length, | ||
485 | context->srb->use_sg ? mts_do_sg : mts_data_done); | ||
486 | } else { | ||
487 | mts_get_status(transfer); | ||
488 | } | ||
489 | } | ||
490 | |||
491 | return; | ||
492 | } | ||
493 | |||
494 | static void mts_do_sg (struct urb* transfer, struct pt_regs *regs) | ||
495 | { | ||
496 | struct scatterlist * sg; | ||
497 | MTS_INT_INIT(); | ||
498 | |||
499 | MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg); | ||
500 | |||
501 | if (unlikely(transfer->status)) { | ||
502 | context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; | ||
503 | mts_transfer_cleanup(transfer); | ||
504 | } | ||
505 | |||
506 | sg = context->srb->buffer; | ||
507 | context->fragment++; | ||
508 | mts_int_submit_urb(transfer, | ||
509 | context->data_pipe, | ||
510 | page_address(sg[context->fragment].page) + | ||
511 | sg[context->fragment].offset, | ||
512 | sg[context->fragment].length, | ||
513 | context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg); | ||
514 | return; | ||
515 | } | ||
516 | |||
517 | static const u8 mts_read_image_sig[] = { 0x28, 00, 00, 00 }; | ||
518 | static const u8 mts_read_image_sig_len = 4; | ||
519 | static const unsigned char mts_direction[256/8] = { | ||
520 | 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, | ||
521 | 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, | ||
522 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, | ||
523 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
524 | }; | ||
525 | |||
526 | |||
527 | #define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1) | ||
528 | |||
529 | static void | ||
530 | mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc ) | ||
531 | { | ||
532 | int pipe; | ||
533 | struct scatterlist * sg; | ||
534 | |||
535 | MTS_DEBUG_GOT_HERE(); | ||
536 | |||
537 | desc->context.instance = desc; | ||
538 | desc->context.srb = srb; | ||
539 | desc->context.fragment = 0; | ||
540 | |||
541 | if (!srb->use_sg) { | ||
542 | if ( !srb->bufflen ){ | ||
543 | desc->context.data = NULL; | ||
544 | desc->context.data_length = 0; | ||
545 | return; | ||
546 | } else { | ||
547 | desc->context.data = srb->buffer; | ||
548 | desc->context.data_length = srb->bufflen; | ||
549 | MTS_DEBUG("length = %d or %d\n", | ||
550 | srb->request_bufflen, srb->bufflen); | ||
551 | } | ||
552 | } else { | ||
553 | MTS_DEBUG("Using scatter/gather\n"); | ||
554 | sg = srb->buffer; | ||
555 | desc->context.data = page_address(sg[0].page) + sg[0].offset; | ||
556 | desc->context.data_length = sg[0].length; | ||
557 | } | ||
558 | |||
559 | |||
560 | /* can't rely on srb->sc_data_direction */ | ||
561 | |||
562 | /* Brutally ripped from usb-storage */ | ||
563 | |||
564 | if ( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len ) | ||
565 | ) { pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_image); | ||
566 | MTS_DEBUG( "transfering from desc->ep_image == %d\n", | ||
567 | (int)desc->ep_image ); | ||
568 | } else if ( MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) { | ||
569 | pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_response); | ||
570 | MTS_DEBUG( "transfering from desc->ep_response == %d\n", | ||
571 | (int)desc->ep_response); | ||
572 | } else { | ||
573 | MTS_DEBUG("transfering to desc->ep_out == %d\n", | ||
574 | (int)desc->ep_out); | ||
575 | pipe = usb_sndbulkpipe(desc->usb_dev,desc->ep_out); | ||
576 | } | ||
577 | desc->context.data_pipe = pipe; | ||
578 | } | ||
579 | |||
580 | |||
581 | static | ||
582 | int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ) | ||
583 | { | ||
584 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); | ||
585 | int err = 0; | ||
586 | int res; | ||
587 | |||
588 | MTS_DEBUG_GOT_HERE(); | ||
589 | mts_show_command(srb); | ||
590 | mts_debug_dump(desc); | ||
591 | |||
592 | if ( srb->device->lun || srb->device->id || srb->device->channel ) { | ||
593 | |||
594 | 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 ); | ||
595 | |||
596 | MTS_DEBUG("this device doesn't exist\n"); | ||
597 | |||
598 | srb->result = DID_BAD_TARGET << 16; | ||
599 | |||
600 | if(likely(callback != NULL)) | ||
601 | callback(srb); | ||
602 | |||
603 | goto out; | ||
604 | } | ||
605 | |||
606 | |||
607 | usb_fill_bulk_urb(desc->urb, | ||
608 | desc->usb_dev, | ||
609 | usb_sndbulkpipe(desc->usb_dev,desc->ep_out), | ||
610 | srb->cmnd, | ||
611 | srb->cmd_len, | ||
612 | mts_command_done, | ||
613 | &desc->context | ||
614 | ); | ||
615 | |||
616 | |||
617 | mts_build_transfer_context( srb, desc ); | ||
618 | desc->context.final_callback = callback; | ||
619 | |||
620 | /* here we need ATOMIC as we are called with the iolock */ | ||
621 | res=usb_submit_urb(desc->urb, GFP_ATOMIC); | ||
622 | |||
623 | if(unlikely(res)){ | ||
624 | MTS_ERROR("error %d submitting URB\n",(int)res); | ||
625 | srb->result = DID_ERROR << 16; | ||
626 | |||
627 | if(likely(callback != NULL)) | ||
628 | callback(srb); | ||
629 | |||
630 | } | ||
631 | |||
632 | out: | ||
633 | return err; | ||
634 | } | ||
635 | |||
636 | static Scsi_Host_Template mts_scsi_host_template = { | ||
637 | .module = THIS_MODULE, | ||
638 | .name = "microtekX6", | ||
639 | .proc_name = "microtekX6", | ||
640 | .queuecommand = mts_scsi_queuecommand, | ||
641 | .eh_abort_handler = mts_scsi_abort, | ||
642 | .eh_host_reset_handler = mts_scsi_host_reset, | ||
643 | .sg_tablesize = SG_ALL, | ||
644 | .can_queue = 1, | ||
645 | .this_id = -1, | ||
646 | .cmd_per_lun = 1, | ||
647 | .use_clustering = 1, | ||
648 | .emulated = 1, | ||
649 | }; | ||
650 | |||
651 | struct vendor_product | ||
652 | { | ||
653 | char* name; | ||
654 | enum | ||
655 | { | ||
656 | mts_sup_unknown=0, | ||
657 | mts_sup_alpha, | ||
658 | mts_sup_full | ||
659 | } | ||
660 | support_status; | ||
661 | } ; | ||
662 | |||
663 | |||
664 | /* These are taken from the msmUSB.inf file on the Windows driver CD */ | ||
665 | const static struct vendor_product mts_supported_products[] = | ||
666 | { | ||
667 | { "Phantom 336CX", mts_sup_unknown}, | ||
668 | { "Phantom 336CX", mts_sup_unknown}, | ||
669 | { "Scanmaker X6", mts_sup_alpha}, | ||
670 | { "Phantom C6", mts_sup_unknown}, | ||
671 | { "Phantom 336CX", mts_sup_unknown}, | ||
672 | { "ScanMaker V6USL", mts_sup_unknown}, | ||
673 | { "ScanMaker V6USL", mts_sup_unknown}, | ||
674 | { "Scanmaker V6UL", mts_sup_unknown}, | ||
675 | { "Scanmaker V6UPL", mts_sup_alpha}, | ||
676 | }; | ||
677 | |||
678 | /* The entries of microtek_table must correspond, line-by-line to | ||
679 | the entries of mts_supported_products[]. */ | ||
680 | |||
681 | static struct usb_device_id mts_usb_ids [] = | ||
682 | { | ||
683 | { USB_DEVICE(0x4ce, 0x0300) }, | ||
684 | { USB_DEVICE(0x5da, 0x0094) }, | ||
685 | { USB_DEVICE(0x5da, 0x0099) }, | ||
686 | { USB_DEVICE(0x5da, 0x009a) }, | ||
687 | { USB_DEVICE(0x5da, 0x00a0) }, | ||
688 | { USB_DEVICE(0x5da, 0x00a3) }, | ||
689 | { USB_DEVICE(0x5da, 0x80a3) }, | ||
690 | { USB_DEVICE(0x5da, 0x80ac) }, | ||
691 | { USB_DEVICE(0x5da, 0x00b6) }, | ||
692 | { } /* Terminating entry */ | ||
693 | }; | ||
694 | |||
695 | MODULE_DEVICE_TABLE (usb, mts_usb_ids); | ||
696 | |||
697 | |||
698 | static int mts_usb_probe(struct usb_interface *intf, | ||
699 | const struct usb_device_id *id) | ||
700 | { | ||
701 | int i; | ||
702 | int ep_out = -1; | ||
703 | int ep_in_set[3]; /* this will break if we have more than three endpoints | ||
704 | which is why we check */ | ||
705 | int *ep_in_current = ep_in_set; | ||
706 | int err_retval = -ENOMEM; | ||
707 | |||
708 | struct mts_desc * new_desc; | ||
709 | struct vendor_product const* p; | ||
710 | struct usb_device *dev = interface_to_usbdev (intf); | ||
711 | |||
712 | /* the current altsetting on the interface we're probing */ | ||
713 | struct usb_host_interface *altsetting; | ||
714 | |||
715 | MTS_DEBUG_GOT_HERE(); | ||
716 | MTS_DEBUG( "usb-device descriptor at %x\n", (int)dev ); | ||
717 | |||
718 | MTS_DEBUG( "product id = 0x%x, vendor id = 0x%x\n", | ||
719 | le16_to_cpu(dev->descriptor.idProduct), | ||
720 | le16_to_cpu(dev->descriptor.idVendor) ); | ||
721 | |||
722 | MTS_DEBUG_GOT_HERE(); | ||
723 | |||
724 | p = &mts_supported_products[id - mts_usb_ids]; | ||
725 | |||
726 | MTS_DEBUG_GOT_HERE(); | ||
727 | |||
728 | MTS_DEBUG( "found model %s\n", p->name ); | ||
729 | if ( p->support_status != mts_sup_full ) | ||
730 | MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n", | ||
731 | p->name ); | ||
732 | |||
733 | /* the current altsetting on the interface we're probing */ | ||
734 | altsetting = intf->cur_altsetting; | ||
735 | |||
736 | |||
737 | /* Check if the config is sane */ | ||
738 | |||
739 | if ( altsetting->desc.bNumEndpoints != MTS_EP_TOTAL ) { | ||
740 | MTS_WARNING( "expecting %d got %d endpoints! Bailing out.\n", | ||
741 | (int)MTS_EP_TOTAL, (int)altsetting->desc.bNumEndpoints ); | ||
742 | return -ENODEV; | ||
743 | } | ||
744 | |||
745 | for( i = 0; i < altsetting->desc.bNumEndpoints; i++ ) { | ||
746 | if ((altsetting->endpoint[i].desc.bmAttributes & | ||
747 | USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) { | ||
748 | |||
749 | MTS_WARNING( "can only deal with bulk endpoints; endpoint %d is not bulk.\n", | ||
750 | (int)altsetting->endpoint[i].desc.bEndpointAddress ); | ||
751 | } else { | ||
752 | if (altsetting->endpoint[i].desc.bEndpointAddress & | ||
753 | USB_DIR_IN) | ||
754 | *ep_in_current++ | ||
755 | = altsetting->endpoint[i].desc.bEndpointAddress & | ||
756 | USB_ENDPOINT_NUMBER_MASK; | ||
757 | else { | ||
758 | if ( ep_out != -1 ) { | ||
759 | MTS_WARNING( "can only deal with one output endpoints. Bailing out." ); | ||
760 | return -ENODEV; | ||
761 | } | ||
762 | |||
763 | ep_out = altsetting->endpoint[i].desc.bEndpointAddress & | ||
764 | USB_ENDPOINT_NUMBER_MASK; | ||
765 | } | ||
766 | } | ||
767 | |||
768 | } | ||
769 | |||
770 | |||
771 | if ( ep_out == -1 ) { | ||
772 | MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" ); | ||
773 | return -ENODEV; | ||
774 | } | ||
775 | |||
776 | |||
777 | new_desc = kmalloc(sizeof(struct mts_desc), GFP_KERNEL); | ||
778 | if (!new_desc) | ||
779 | goto out; | ||
780 | |||
781 | memset(new_desc, 0, sizeof(*new_desc)); | ||
782 | new_desc->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
783 | if (!new_desc->urb) | ||
784 | goto out_kfree; | ||
785 | |||
786 | new_desc->usb_dev = dev; | ||
787 | new_desc->usb_intf = intf; | ||
788 | init_MUTEX(&new_desc->lock); | ||
789 | |||
790 | /* endpoints */ | ||
791 | new_desc->ep_out = ep_out; | ||
792 | new_desc->ep_response = ep_in_set[0]; | ||
793 | new_desc->ep_image = ep_in_set[1]; | ||
794 | |||
795 | if ( new_desc->ep_out != MTS_EP_OUT ) | ||
796 | MTS_WARNING( "will this work? Command EP is not usually %d\n", | ||
797 | (int)new_desc->ep_out ); | ||
798 | |||
799 | if ( new_desc->ep_response != MTS_EP_RESPONSE ) | ||
800 | MTS_WARNING( "will this work? Response EP is not usually %d\n", | ||
801 | (int)new_desc->ep_response ); | ||
802 | |||
803 | if ( new_desc->ep_image != MTS_EP_IMAGE ) | ||
804 | MTS_WARNING( "will this work? Image data EP is not usually %d\n", | ||
805 | (int)new_desc->ep_image ); | ||
806 | |||
807 | new_desc->host = scsi_host_alloc(&mts_scsi_host_template, | ||
808 | sizeof(new_desc)); | ||
809 | if (!new_desc->host) | ||
810 | goto out_free_urb; | ||
811 | |||
812 | new_desc->host->hostdata[0] = (unsigned long)new_desc; | ||
813 | if (scsi_add_host(new_desc->host, NULL)) { | ||
814 | err_retval = -EIO; | ||
815 | goto out_free_urb; | ||
816 | } | ||
817 | scsi_scan_host(new_desc->host); | ||
818 | |||
819 | usb_set_intfdata(intf, new_desc); | ||
820 | return 0; | ||
821 | |||
822 | out_free_urb: | ||
823 | usb_free_urb(new_desc->urb); | ||
824 | out_kfree: | ||
825 | kfree(new_desc); | ||
826 | out: | ||
827 | return err_retval; | ||
828 | } | ||
829 | |||
830 | static void mts_usb_disconnect (struct usb_interface *intf) | ||
831 | { | ||
832 | struct mts_desc *desc = usb_get_intfdata(intf); | ||
833 | |||
834 | usb_set_intfdata(intf, NULL); | ||
835 | |||
836 | usb_kill_urb(desc->urb); | ||
837 | scsi_remove_host(desc->host); | ||
838 | |||
839 | scsi_host_put(desc->host); | ||
840 | usb_free_urb(desc->urb); | ||
841 | kfree(desc); | ||
842 | } | ||
843 | |||
844 | |||
845 | static int __init microtek_drv_init(void) | ||
846 | { | ||
847 | return usb_register(&mts_usb_driver); | ||
848 | } | ||
849 | |||
850 | static void __exit microtek_drv_exit(void) | ||
851 | { | ||
852 | usb_deregister(&mts_usb_driver); | ||
853 | } | ||
854 | |||
855 | module_init(microtek_drv_init); | ||
856 | module_exit(microtek_drv_exit); | ||
857 | |||
858 | MODULE_AUTHOR( DRIVER_AUTHOR ); | ||
859 | MODULE_DESCRIPTION( DRIVER_DESC ); | ||
860 | MODULE_LICENSE("GPL"); | ||
861 | |||
862 | |||
diff --git a/drivers/usb/image/microtek.h b/drivers/usb/image/microtek.h new file mode 100644 index 000000000000..3271deb8c001 --- /dev/null +++ b/drivers/usb/image/microtek.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Driver for Microtek Scanmaker X6 USB scanner and possibly others. | ||
3 | * | ||
4 | * (C) Copyright 2000 John Fremlin <vii@penguinpowered.com> | ||
5 | * (C) Copyright 2000 Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de> | ||
6 | * | ||
7 | * See microtek.c for history | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | typedef void (*mts_scsi_cmnd_callback)(Scsi_Cmnd *); | ||
12 | |||
13 | |||
14 | struct mts_transfer_context | ||
15 | { | ||
16 | struct mts_desc* instance; | ||
17 | mts_scsi_cmnd_callback final_callback; | ||
18 | Scsi_Cmnd *srb; | ||
19 | |||
20 | void* data; | ||
21 | unsigned data_length; | ||
22 | int data_pipe; | ||
23 | int fragment; | ||
24 | |||
25 | u8 status; /* status returned from ep_response after command completion */ | ||
26 | }; | ||
27 | |||
28 | |||
29 | struct mts_desc { | ||
30 | struct mts_desc *next; | ||
31 | struct mts_desc *prev; | ||
32 | |||
33 | struct usb_device *usb_dev; | ||
34 | struct usb_interface *usb_intf; | ||
35 | |||
36 | /* Endpoint addresses */ | ||
37 | u8 ep_out; | ||
38 | u8 ep_response; | ||
39 | u8 ep_image; | ||
40 | |||
41 | struct Scsi_Host * host; | ||
42 | struct semaphore lock; | ||
43 | |||
44 | struct urb *urb; | ||
45 | struct mts_transfer_context context; | ||
46 | }; | ||
47 | |||
48 | |||
49 | #define MTS_EP_OUT 0x1 | ||
50 | #define MTS_EP_RESPONSE 0x2 | ||
51 | #define MTS_EP_IMAGE 0x3 | ||
52 | #define MTS_EP_TOTAL 0x3 | ||
53 | |||
54 | #define MTS_SCSI_ERR_MASK ~0x3fu | ||
55 | |||