diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/usb/image/mdc800.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/usb/image/mdc800.c')
-rw-r--r-- | drivers/usb/image/mdc800.c | 1063 |
1 files changed, 1063 insertions, 0 deletions
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 | |||