Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * cpia_usb CPiA USB driver | |
3 | * | |
4 | * Supports CPiA based parallel port Video Camera's. | |
5 | * | |
6 | * Copyright (C) 1999 Jochen Scharrlach <Jochen.Scharrlach@schwaben.de> | |
7 | * Copyright (C) 1999, 2000 Johannes Erdfelt <johannes@erdfelt.com> | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 2 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
22 | */ | |
23 | ||
24 | /* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ | |
25 | /* #define _CPIA_DEBUG_ 1 */ | |
26 | ||
27 | #include <linux/module.h> | |
28 | #include <linux/kernel.h> | |
29 | #include <linux/init.h> | |
30 | #include <linux/wait.h> | |
31 | #include <linux/list.h> | |
32 | #include <linux/slab.h> | |
33 | #include <linux/vmalloc.h> | |
34 | #include <linux/usb.h> | |
35 | ||
36 | #include "cpia.h" | |
37 | ||
38 | #define USB_REQ_CPIA_GRAB_FRAME 0xC1 | |
39 | #define USB_REQ_CPIA_UPLOAD_FRAME 0xC2 | |
40 | #define WAIT_FOR_NEXT_FRAME 0 | |
41 | #define FORCE_FRAME_UPLOAD 1 | |
42 | ||
43 | #define FRAMES_PER_DESC 10 | |
44 | #define FRAME_SIZE_PER_DESC 960 /* Shouldn't be hardcoded */ | |
45 | #define CPIA_NUMSBUF 2 | |
46 | #define STREAM_BUF_SIZE (PAGE_SIZE * 4) | |
47 | #define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2) | |
48 | ||
49 | struct cpia_sbuf { | |
50 | char *data; | |
51 | struct urb *urb; | |
52 | }; | |
53 | ||
54 | #define FRAMEBUF_LEN (CPIA_MAX_FRAME_SIZE+100) | |
55 | enum framebuf_status { | |
56 | FRAME_EMPTY, | |
57 | FRAME_READING, | |
58 | FRAME_READY, | |
59 | FRAME_ERROR, | |
60 | }; | |
61 | ||
62 | struct framebuf { | |
63 | int length; | |
64 | enum framebuf_status status; | |
65 | u8 data[FRAMEBUF_LEN]; | |
66 | struct framebuf *next; | |
67 | }; | |
68 | ||
69 | struct usb_cpia { | |
70 | /* Device structure */ | |
71 | struct usb_device *dev; | |
72 | ||
73 | unsigned char iface; | |
74 | wait_queue_head_t wq_stream; | |
75 | ||
76 | int cursbuf; /* Current receiving sbuf */ | |
77 | struct cpia_sbuf sbuf[CPIA_NUMSBUF]; /* Double buffering */ | |
78 | ||
79 | int streaming; | |
80 | int open; | |
81 | int present; | |
82 | struct framebuf *buffers[3]; | |
83 | struct framebuf *curbuff, *workbuff; | |
84 | }; | |
85 | ||
86 | static int cpia_usb_open(void *privdata); | |
87 | static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata), | |
88 | void *cbdata); | |
89 | static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data); | |
90 | static int cpia_usb_streamStart(void *privdata); | |
91 | static int cpia_usb_streamStop(void *privdata); | |
92 | static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock); | |
93 | static int cpia_usb_close(void *privdata); | |
94 | ||
95 | #define ABOUT "USB driver for Vision CPiA based cameras" | |
96 | ||
97 | static struct cpia_camera_ops cpia_usb_ops = { | |
98 | cpia_usb_open, | |
99 | cpia_usb_registerCallback, | |
100 | cpia_usb_transferCmd, | |
101 | cpia_usb_streamStart, | |
102 | cpia_usb_streamStop, | |
103 | cpia_usb_streamRead, | |
104 | cpia_usb_close, | |
105 | 0, | |
106 | THIS_MODULE | |
107 | }; | |
108 | ||
109 | static LIST_HEAD(cam_list); | |
110 | static spinlock_t cam_list_lock_usb; | |
111 | ||
112 | static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs) | |
113 | { | |
114 | int i; | |
115 | char *cdata; | |
116 | struct usb_cpia *ucpia; | |
117 | ||
118 | if (!urb || !urb->context) | |
119 | return; | |
120 | ||
121 | ucpia = (struct usb_cpia *) urb->context; | |
122 | ||
123 | if (!ucpia->dev || !ucpia->streaming || !ucpia->present || !ucpia->open) | |
124 | return; | |
125 | ||
126 | if (ucpia->workbuff->status == FRAME_EMPTY) { | |
127 | ucpia->workbuff->status = FRAME_READING; | |
128 | ucpia->workbuff->length = 0; | |
129 | } | |
130 | ||
131 | for (i = 0; i < urb->number_of_packets; i++) { | |
132 | int n = urb->iso_frame_desc[i].actual_length; | |
133 | int st = urb->iso_frame_desc[i].status; | |
134 | ||
135 | cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; | |
136 | ||
137 | if (st) | |
138 | printk(KERN_DEBUG "cpia data error: [%d] len=%d, status=%X\n", i, n, st); | |
139 | ||
140 | if (FRAMEBUF_LEN < ucpia->workbuff->length + n) { | |
141 | printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n", ucpia->workbuff->length, n); | |
142 | return; | |
143 | } | |
144 | ||
145 | if (n) { | |
146 | if ((ucpia->workbuff->length > 0) || | |
147 | (0x19 == cdata[0] && 0x68 == cdata[1])) { | |
148 | memcpy(ucpia->workbuff->data + ucpia->workbuff->length, cdata, n); | |
149 | ucpia->workbuff->length += n; | |
150 | } else | |
151 | DBG("Ignoring packet!\n"); | |
152 | } else { | |
153 | if (ucpia->workbuff->length > 4 && | |
154 | 0xff == ucpia->workbuff->data[ucpia->workbuff->length-1] && | |
155 | 0xff == ucpia->workbuff->data[ucpia->workbuff->length-2] && | |
156 | 0xff == ucpia->workbuff->data[ucpia->workbuff->length-3] && | |
157 | 0xff == ucpia->workbuff->data[ucpia->workbuff->length-4]) { | |
158 | ucpia->workbuff->status = FRAME_READY; | |
159 | ucpia->curbuff = ucpia->workbuff; | |
160 | ucpia->workbuff = ucpia->workbuff->next; | |
161 | ucpia->workbuff->status = FRAME_EMPTY; | |
162 | ucpia->workbuff->length = 0; | |
163 | ||
164 | if (waitqueue_active(&ucpia->wq_stream)) | |
165 | wake_up_interruptible(&ucpia->wq_stream); | |
166 | } | |
167 | } | |
168 | } | |
169 | ||
170 | /* resubmit */ | |
171 | urb->dev = ucpia->dev; | |
172 | if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0) | |
173 | printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __FUNCTION__, i); | |
174 | } | |
175 | ||
176 | static int cpia_usb_open(void *privdata) | |
177 | { | |
178 | struct usb_cpia *ucpia = (struct usb_cpia *) privdata; | |
179 | struct urb *urb; | |
180 | int ret, retval = 0, fx, err; | |
181 | ||
182 | if (!ucpia) | |
183 | return -EINVAL; | |
184 | ||
185 | ucpia->sbuf[0].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); | |
186 | if (!ucpia->sbuf[0].data) | |
187 | return -EINVAL; | |
188 | ||
189 | ucpia->sbuf[1].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); | |
190 | if (!ucpia->sbuf[1].data) { | |
191 | retval = -EINVAL; | |
192 | goto error_0; | |
193 | } | |
194 | ||
195 | ret = usb_set_interface(ucpia->dev, ucpia->iface, 3); | |
196 | if (ret < 0) { | |
197 | printk(KERN_ERR "cpia_usb_open: usb_set_interface error (ret = %d)\n", ret); | |
198 | retval = -EBUSY; | |
199 | goto error_1; | |
200 | } | |
201 | ||
202 | ucpia->buffers[0]->status = FRAME_EMPTY; | |
203 | ucpia->buffers[0]->length = 0; | |
204 | ucpia->buffers[1]->status = FRAME_EMPTY; | |
205 | ucpia->buffers[1]->length = 0; | |
206 | ucpia->buffers[2]->status = FRAME_EMPTY; | |
207 | ucpia->buffers[2]->length = 0; | |
208 | ucpia->curbuff = ucpia->buffers[0]; | |
209 | ucpia->workbuff = ucpia->buffers[1]; | |
210 | ||
211 | /* We double buffer the Iso lists, and also know the polling | |
212 | * interval is every frame (1 == (1 << (bInterval -1))). | |
213 | */ | |
214 | urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); | |
215 | if (!urb) { | |
216 | printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 0\n"); | |
217 | retval = -ENOMEM; | |
218 | goto error_1; | |
219 | } | |
220 | ||
221 | ucpia->sbuf[0].urb = urb; | |
222 | urb->dev = ucpia->dev; | |
223 | urb->context = ucpia; | |
224 | urb->pipe = usb_rcvisocpipe(ucpia->dev, 1); | |
225 | urb->transfer_flags = URB_ISO_ASAP; | |
226 | urb->transfer_buffer = ucpia->sbuf[0].data; | |
227 | urb->complete = cpia_usb_complete; | |
228 | urb->number_of_packets = FRAMES_PER_DESC; | |
229 | urb->interval = 1; | |
230 | urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; | |
231 | for (fx = 0; fx < FRAMES_PER_DESC; fx++) { | |
232 | urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; | |
233 | urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; | |
234 | } | |
235 | ||
236 | urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); | |
237 | if (!urb) { | |
238 | printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 1\n"); | |
239 | retval = -ENOMEM; | |
240 | goto error_urb0; | |
241 | } | |
242 | ||
243 | ucpia->sbuf[1].urb = urb; | |
244 | urb->dev = ucpia->dev; | |
245 | urb->context = ucpia; | |
246 | urb->pipe = usb_rcvisocpipe(ucpia->dev, 1); | |
247 | urb->transfer_flags = URB_ISO_ASAP; | |
248 | urb->transfer_buffer = ucpia->sbuf[1].data; | |
249 | urb->complete = cpia_usb_complete; | |
250 | urb->number_of_packets = FRAMES_PER_DESC; | |
251 | urb->interval = 1; | |
252 | urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; | |
253 | for (fx = 0; fx < FRAMES_PER_DESC; fx++) { | |
254 | urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; | |
255 | urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; | |
256 | } | |
257 | ||
258 | /* queue the ISO urbs, and resubmit in the completion handler */ | |
259 | err = usb_submit_urb(ucpia->sbuf[0].urb, GFP_KERNEL); | |
260 | if (err) { | |
261 | printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 0 ret %d\n", | |
262 | err); | |
263 | goto error_urb1; | |
264 | } | |
265 | err = usb_submit_urb(ucpia->sbuf[1].urb, GFP_KERNEL); | |
266 | if (err) { | |
267 | printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 1 ret %d\n", | |
268 | err); | |
269 | goto error_urb1; | |
270 | } | |
271 | ||
272 | ucpia->streaming = 1; | |
273 | ucpia->open = 1; | |
274 | ||
275 | return 0; | |
276 | ||
277 | error_urb1: /* free urb 1 */ | |
278 | usb_free_urb(ucpia->sbuf[1].urb); | |
279 | ucpia->sbuf[1].urb = NULL; | |
280 | error_urb0: /* free urb 0 */ | |
281 | usb_free_urb(ucpia->sbuf[0].urb); | |
282 | ucpia->sbuf[0].urb = NULL; | |
283 | error_1: | |
284 | kfree (ucpia->sbuf[1].data); | |
285 | ucpia->sbuf[1].data = NULL; | |
286 | error_0: | |
287 | kfree (ucpia->sbuf[0].data); | |
288 | ucpia->sbuf[0].data = NULL; | |
289 | ||
290 | return retval; | |
291 | } | |
292 | ||
293 | // | |
294 | // convenience functions | |
295 | // | |
296 | ||
297 | /**************************************************************************** | |
298 | * | |
299 | * WritePacket | |
300 | * | |
301 | ***************************************************************************/ | |
302 | static int WritePacket(struct usb_device *udev, const u8 *packet, u8 *buf, size_t size) | |
303 | { | |
304 | if (!packet) | |
305 | return -EINVAL; | |
306 | ||
307 | return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | |
308 | packet[1] + (packet[0] << 8), | |
309 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
310 | packet[2] + (packet[3] << 8), | |
311 | packet[4] + (packet[5] << 8), buf, size, 1000); | |
312 | } | |
313 | ||
314 | /**************************************************************************** | |
315 | * | |
316 | * ReadPacket | |
317 | * | |
318 | ***************************************************************************/ | |
319 | static int ReadPacket(struct usb_device *udev, u8 *packet, u8 *buf, size_t size) | |
320 | { | |
321 | if (!packet || size <= 0) | |
322 | return -EINVAL; | |
323 | ||
324 | return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | |
325 | packet[1] + (packet[0] << 8), | |
326 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
327 | packet[2] + (packet[3] << 8), | |
328 | packet[4] + (packet[5] << 8), buf, size, 1000); | |
329 | } | |
330 | ||
331 | static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data) | |
332 | { | |
333 | int err = 0; | |
334 | int databytes; | |
335 | struct usb_cpia *ucpia = (struct usb_cpia *)privdata; | |
336 | struct usb_device *udev = ucpia->dev; | |
337 | ||
338 | if (!udev) { | |
339 | DBG("Internal driver error: udev is NULL\n"); | |
340 | return -EINVAL; | |
341 | } | |
342 | ||
343 | if (!command) { | |
344 | DBG("Internal driver error: command is NULL\n"); | |
345 | return -EINVAL; | |
346 | } | |
347 | ||
348 | databytes = (((int)command[7])<<8) | command[6]; | |
349 | ||
350 | if (command[0] == DATA_IN) { | |
351 | u8 buffer[8]; | |
352 | ||
353 | if (!data) { | |
354 | DBG("Internal driver error: data is NULL\n"); | |
355 | return -EINVAL; | |
356 | } | |
357 | ||
358 | err = ReadPacket(udev, command, buffer, 8); | |
359 | if (err < 0) | |
360 | return err; | |
361 | ||
362 | memcpy(data, buffer, databytes); | |
363 | } else if(command[0] == DATA_OUT) | |
364 | WritePacket(udev, command, data, databytes); | |
365 | else { | |
366 | DBG("Unexpected first byte of command: %x\n", command[0]); | |
367 | err = -EINVAL; | |
368 | } | |
369 | ||
370 | return 0; | |
371 | } | |
372 | ||
373 | static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata), | |
374 | void *cbdata) | |
375 | { | |
376 | return -ENODEV; | |
377 | } | |
378 | ||
379 | static int cpia_usb_streamStart(void *privdata) | |
380 | { | |
381 | return -ENODEV; | |
382 | } | |
383 | ||
384 | static int cpia_usb_streamStop(void *privdata) | |
385 | { | |
386 | return -ENODEV; | |
387 | } | |
388 | ||
389 | static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock) | |
390 | { | |
391 | struct usb_cpia *ucpia = (struct usb_cpia *) privdata; | |
392 | struct framebuf *mybuff; | |
393 | ||
394 | if (!ucpia || !ucpia->present) | |
395 | return -1; | |
396 | ||
397 | if (ucpia->curbuff->status != FRAME_READY) | |
398 | interruptible_sleep_on(&ucpia->wq_stream); | |
399 | else | |
400 | DBG("Frame already waiting!\n"); | |
401 | ||
402 | mybuff = ucpia->curbuff; | |
403 | ||
404 | if (!mybuff) | |
405 | return -1; | |
406 | ||
407 | if (mybuff->status != FRAME_READY || mybuff->length < 4) { | |
408 | DBG("Something went wrong!\n"); | |
409 | return -1; | |
410 | } | |
411 | ||
412 | memcpy(frame, mybuff->data, mybuff->length); | |
413 | mybuff->status = FRAME_EMPTY; | |
414 | ||
415 | /* DBG("read done, %d bytes, Header: %x/%x, Footer: %x%x%x%x\n", */ | |
416 | /* mybuff->length, frame[0], frame[1], */ | |
417 | /* frame[mybuff->length-4], frame[mybuff->length-3], */ | |
418 | /* frame[mybuff->length-2], frame[mybuff->length-1]); */ | |
419 | ||
420 | return mybuff->length; | |
421 | } | |
422 | ||
423 | static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try) | |
424 | { | |
425 | if (!ucpia->streaming) | |
426 | return; | |
427 | ||
428 | ucpia->streaming = 0; | |
429 | ||
430 | /* Set packet size to 0 */ | |
431 | if (try) { | |
432 | int ret; | |
433 | ||
434 | ret = usb_set_interface(ucpia->dev, ucpia->iface, 0); | |
435 | if (ret < 0) { | |
436 | printk(KERN_ERR "usb_set_interface error (ret = %d)\n", ret); | |
437 | return; | |
438 | } | |
439 | } | |
440 | ||
441 | /* Unschedule all of the iso td's */ | |
442 | if (ucpia->sbuf[1].urb) { | |
443 | usb_kill_urb(ucpia->sbuf[1].urb); | |
444 | usb_free_urb(ucpia->sbuf[1].urb); | |
445 | ucpia->sbuf[1].urb = NULL; | |
446 | } | |
447 | ||
f9101210 JJ |
448 | kfree(ucpia->sbuf[1].data); |
449 | ucpia->sbuf[1].data = NULL; | |
1da177e4 LT |
450 | |
451 | if (ucpia->sbuf[0].urb) { | |
452 | usb_kill_urb(ucpia->sbuf[0].urb); | |
453 | usb_free_urb(ucpia->sbuf[0].urb); | |
454 | ucpia->sbuf[0].urb = NULL; | |
455 | } | |
456 | ||
f9101210 JJ |
457 | kfree(ucpia->sbuf[0].data); |
458 | ucpia->sbuf[0].data = NULL; | |
1da177e4 LT |
459 | } |
460 | ||
461 | static int cpia_usb_close(void *privdata) | |
462 | { | |
463 | struct usb_cpia *ucpia = (struct usb_cpia *) privdata; | |
464 | ||
465 | if(!ucpia) | |
466 | return -ENODEV; | |
467 | ||
468 | ucpia->open = 0; | |
469 | ||
470 | /* ucpia->present = 0 protects against trying to reset the | |
471 | * alt setting if camera is physically disconnected while open */ | |
472 | cpia_usb_free_resources(ucpia, ucpia->present); | |
473 | ||
474 | return 0; | |
475 | } | |
476 | ||
477 | int cpia_usb_init(void) | |
478 | { | |
479 | /* return -ENODEV; */ | |
480 | return 0; | |
481 | } | |
482 | ||
483 | /* Probing and initializing */ | |
484 | ||
485 | static int cpia_probe(struct usb_interface *intf, | |
486 | const struct usb_device_id *id) | |
487 | { | |
488 | struct usb_device *udev = interface_to_usbdev(intf); | |
489 | struct usb_host_interface *interface; | |
490 | struct usb_cpia *ucpia; | |
491 | struct cam_data *cam; | |
492 | int ret; | |
493 | ||
494 | /* A multi-config CPiA camera? */ | |
495 | if (udev->descriptor.bNumConfigurations != 1) | |
496 | return -ENODEV; | |
497 | ||
498 | interface = intf->cur_altsetting; | |
499 | ||
500 | printk(KERN_INFO "USB CPiA camera found\n"); | |
501 | ||
7408187d | 502 | ucpia = kzalloc(sizeof(*ucpia), GFP_KERNEL); |
1da177e4 LT |
503 | if (!ucpia) { |
504 | printk(KERN_ERR "couldn't kmalloc cpia struct\n"); | |
505 | return -ENOMEM; | |
506 | } | |
507 | ||
1da177e4 LT |
508 | ucpia->dev = udev; |
509 | ucpia->iface = interface->desc.bInterfaceNumber; | |
510 | init_waitqueue_head(&ucpia->wq_stream); | |
511 | ||
512 | ucpia->buffers[0] = vmalloc(sizeof(*ucpia->buffers[0])); | |
513 | if (!ucpia->buffers[0]) { | |
514 | printk(KERN_ERR "couldn't vmalloc frame buffer 0\n"); | |
515 | goto fail_alloc_0; | |
516 | } | |
517 | ||
518 | ucpia->buffers[1] = vmalloc(sizeof(*ucpia->buffers[1])); | |
519 | if (!ucpia->buffers[1]) { | |
520 | printk(KERN_ERR "couldn't vmalloc frame buffer 1\n"); | |
521 | goto fail_alloc_1; | |
522 | } | |
523 | ||
524 | ucpia->buffers[2] = vmalloc(sizeof(*ucpia->buffers[2])); | |
525 | if (!ucpia->buffers[2]) { | |
526 | printk(KERN_ERR "couldn't vmalloc frame buffer 2\n"); | |
527 | goto fail_alloc_2; | |
528 | } | |
529 | ||
530 | ucpia->buffers[0]->next = ucpia->buffers[1]; | |
531 | ucpia->buffers[1]->next = ucpia->buffers[2]; | |
532 | ucpia->buffers[2]->next = ucpia->buffers[0]; | |
533 | ||
534 | ret = usb_set_interface(udev, ucpia->iface, 0); | |
535 | if (ret < 0) { | |
536 | printk(KERN_ERR "cpia_probe: usb_set_interface error (ret = %d)\n", ret); | |
537 | /* goto fail_all; */ | |
538 | } | |
539 | ||
540 | /* Before register_camera, important */ | |
541 | ucpia->present = 1; | |
542 | ||
543 | cam = cpia_register_camera(&cpia_usb_ops, ucpia); | |
544 | if (!cam) { | |
545 | LOG("failed to cpia_register_camera\n"); | |
546 | goto fail_all; | |
547 | } | |
548 | ||
549 | spin_lock( &cam_list_lock_usb ); | |
550 | list_add( &cam->cam_data_list, &cam_list ); | |
551 | spin_unlock( &cam_list_lock_usb ); | |
552 | ||
553 | usb_set_intfdata(intf, cam); | |
554 | return 0; | |
555 | ||
556 | fail_all: | |
557 | vfree(ucpia->buffers[2]); | |
558 | ucpia->buffers[2] = NULL; | |
559 | fail_alloc_2: | |
560 | vfree(ucpia->buffers[1]); | |
561 | ucpia->buffers[1] = NULL; | |
562 | fail_alloc_1: | |
563 | vfree(ucpia->buffers[0]); | |
564 | ucpia->buffers[0] = NULL; | |
565 | fail_alloc_0: | |
566 | kfree(ucpia); | |
567 | return -EIO; | |
568 | } | |
569 | ||
570 | static void cpia_disconnect(struct usb_interface *intf); | |
571 | ||
572 | static struct usb_device_id cpia_id_table [] = { | |
573 | { USB_DEVICE(0x0553, 0x0002) }, | |
574 | { USB_DEVICE(0x0813, 0x0001) }, | |
575 | { } /* Terminating entry */ | |
576 | }; | |
577 | ||
578 | MODULE_DEVICE_TABLE (usb, cpia_id_table); | |
579 | MODULE_LICENSE("GPL"); | |
580 | ||
581 | ||
582 | static struct usb_driver cpia_driver = { | |
1da177e4 LT |
583 | .name = "cpia", |
584 | .probe = cpia_probe, | |
585 | .disconnect = cpia_disconnect, | |
586 | .id_table = cpia_id_table, | |
587 | }; | |
588 | ||
589 | static void cpia_disconnect(struct usb_interface *intf) | |
590 | { | |
591 | struct cam_data *cam = usb_get_intfdata(intf); | |
592 | struct usb_cpia *ucpia; | |
593 | struct usb_device *udev; | |
594 | ||
595 | usb_set_intfdata(intf, NULL); | |
596 | if (!cam) | |
597 | return; | |
598 | ||
599 | ucpia = (struct usb_cpia *) cam->lowlevel_data; | |
600 | spin_lock( &cam_list_lock_usb ); | |
601 | list_del(&cam->cam_data_list); | |
602 | spin_unlock( &cam_list_lock_usb ); | |
603 | ||
604 | ucpia->present = 0; | |
605 | ||
606 | cpia_unregister_camera(cam); | |
607 | if(ucpia->open) | |
608 | cpia_usb_close(cam->lowlevel_data); | |
609 | ||
610 | ucpia->curbuff->status = FRAME_ERROR; | |
611 | ||
612 | if (waitqueue_active(&ucpia->wq_stream)) | |
613 | wake_up_interruptible(&ucpia->wq_stream); | |
614 | ||
615 | udev = interface_to_usbdev(intf); | |
616 | ||
617 | ucpia->curbuff = ucpia->workbuff = NULL; | |
618 | ||
f9101210 JJ |
619 | vfree(ucpia->buffers[2]); |
620 | ucpia->buffers[2] = NULL; | |
1da177e4 | 621 | |
f9101210 JJ |
622 | vfree(ucpia->buffers[1]); |
623 | ucpia->buffers[1] = NULL; | |
1da177e4 | 624 | |
f9101210 JJ |
625 | vfree(ucpia->buffers[0]); |
626 | ucpia->buffers[0] = NULL; | |
1da177e4 LT |
627 | |
628 | cam->lowlevel_data = NULL; | |
629 | kfree(ucpia); | |
630 | } | |
631 | ||
632 | static int __init usb_cpia_init(void) | |
633 | { | |
634 | printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, | |
635 | CPIA_USB_MAJ_VER,CPIA_USB_MIN_VER,CPIA_USB_PATCH_VER); | |
636 | ||
637 | spin_lock_init(&cam_list_lock_usb); | |
638 | return usb_register(&cpia_driver); | |
639 | } | |
640 | ||
641 | static void __exit usb_cpia_cleanup(void) | |
642 | { | |
643 | usb_deregister(&cpia_driver); | |
644 | } | |
645 | ||
646 | ||
647 | module_init (usb_cpia_init); | |
648 | module_exit (usb_cpia_cleanup); | |
649 |