diff options
Diffstat (limited to 'drivers/media/video/zr364xx.c')
-rw-r--r-- | drivers/media/video/zr364xx.c | 1226 |
1 files changed, 993 insertions, 233 deletions
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 2622a6e63da1..9aae011d92ab 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Zoran 364xx based USB webcam module version 0.72 | 2 | * Zoran 364xx based USB webcam module version 0.73 |
3 | * | 3 | * |
4 | * Allows you to use your USB webcam with V4L2 applications | 4 | * Allows you to use your USB webcam with V4L2 applications |
5 | * This is still in heavy developpement ! | 5 | * This is still in heavy developpement ! |
@@ -10,6 +10,8 @@ | |||
10 | * Heavily inspired by usb-skeleton.c, vicam.c, cpia.c and spca50x.c drivers | 10 | * Heavily inspired by usb-skeleton.c, vicam.c, cpia.c and spca50x.c drivers |
11 | * V4L2 version inspired by meye.c driver | 11 | * V4L2 version inspired by meye.c driver |
12 | * | 12 | * |
13 | * Some video buffer code by Lamarque based on s2255drv.c and vivi.c drivers. | ||
14 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | 15 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License as published by | 16 | * it under the terms of the GNU General Public License as published by |
15 | * the Free Software Foundation; either version 2 of the License, or | 17 | * the Free Software Foundation; either version 2 of the License, or |
@@ -27,6 +29,7 @@ | |||
27 | 29 | ||
28 | 30 | ||
29 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/version.h> | ||
30 | #include <linux/init.h> | 33 | #include <linux/init.h> |
31 | #include <linux/usb.h> | 34 | #include <linux/usb.h> |
32 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
@@ -35,24 +38,40 @@ | |||
35 | #include <linux/highmem.h> | 38 | #include <linux/highmem.h> |
36 | #include <media/v4l2-common.h> | 39 | #include <media/v4l2-common.h> |
37 | #include <media/v4l2-ioctl.h> | 40 | #include <media/v4l2-ioctl.h> |
41 | #include <media/videobuf-vmalloc.h> | ||
38 | 42 | ||
39 | 43 | ||
40 | /* Version Information */ | 44 | /* Version Information */ |
41 | #define DRIVER_VERSION "v0.72" | 45 | #define DRIVER_VERSION "v0.73" |
46 | #define ZR364XX_VERSION_CODE KERNEL_VERSION(0, 7, 3) | ||
42 | #define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" | 47 | #define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" |
43 | #define DRIVER_DESC "Zoran 364xx" | 48 | #define DRIVER_DESC "Zoran 364xx" |
44 | 49 | ||
45 | 50 | ||
46 | /* Camera */ | 51 | /* Camera */ |
47 | #define FRAMES 2 | 52 | #define FRAMES 1 |
48 | #define MAX_FRAME_SIZE 100000 | 53 | #define MAX_FRAME_SIZE 200000 |
49 | #define BUFFER_SIZE 0x1000 | 54 | #define BUFFER_SIZE 0x1000 |
50 | #define CTRL_TIMEOUT 500 | 55 | #define CTRL_TIMEOUT 500 |
51 | 56 | ||
57 | #define ZR364XX_DEF_BUFS 4 | ||
58 | #define ZR364XX_READ_IDLE 0 | ||
59 | #define ZR364XX_READ_FRAME 1 | ||
52 | 60 | ||
53 | /* Debug macro */ | 61 | /* Debug macro */ |
54 | #define DBG(x...) if (debug) printk(KERN_INFO KBUILD_MODNAME x) | 62 | #define DBG(fmt, args...) \ |
55 | 63 | do { \ | |
64 | if (debug) { \ | ||
65 | printk(KERN_INFO KBUILD_MODNAME " " fmt, ##args); \ | ||
66 | } \ | ||
67 | } while (0) | ||
68 | |||
69 | /*#define FULL_DEBUG 1*/ | ||
70 | #ifdef FULL_DEBUG | ||
71 | #define _DBG DBG | ||
72 | #else | ||
73 | #define _DBG(fmt, args...) | ||
74 | #endif | ||
56 | 75 | ||
57 | /* Init methods, need to find nicer names for these | 76 | /* Init methods, need to find nicer names for these |
58 | * the exact names of the chipsets would be the best if someone finds it */ | 77 | * the exact names of the chipsets would be the best if someone finds it */ |
@@ -101,24 +120,93 @@ static struct usb_device_id device_table[] = { | |||
101 | 120 | ||
102 | MODULE_DEVICE_TABLE(usb, device_table); | 121 | MODULE_DEVICE_TABLE(usb, device_table); |
103 | 122 | ||
123 | struct zr364xx_mode { | ||
124 | u32 color; /* output video color format */ | ||
125 | u32 brightness; /* brightness */ | ||
126 | }; | ||
127 | |||
128 | /* frame structure */ | ||
129 | struct zr364xx_framei { | ||
130 | unsigned long ulState; /* ulState:ZR364XX_READ_IDLE, | ||
131 | ZR364XX_READ_FRAME */ | ||
132 | void *lpvbits; /* image data */ | ||
133 | unsigned long cur_size; /* current data copied to it */ | ||
134 | }; | ||
135 | |||
136 | /* image buffer structure */ | ||
137 | struct zr364xx_bufferi { | ||
138 | unsigned long dwFrames; /* number of frames in buffer */ | ||
139 | struct zr364xx_framei frame[FRAMES]; /* array of FRAME structures */ | ||
140 | }; | ||
141 | |||
142 | struct zr364xx_dmaqueue { | ||
143 | struct list_head active; | ||
144 | struct zr364xx_camera *cam; | ||
145 | }; | ||
146 | |||
147 | struct zr364xx_pipeinfo { | ||
148 | u32 transfer_size; | ||
149 | u8 *transfer_buffer; | ||
150 | u32 state; | ||
151 | void *stream_urb; | ||
152 | void *cam; /* back pointer to zr364xx_camera struct */ | ||
153 | u32 err_count; | ||
154 | u32 idx; | ||
155 | }; | ||
156 | |||
157 | struct zr364xx_fmt { | ||
158 | char *name; | ||
159 | u32 fourcc; | ||
160 | int depth; | ||
161 | }; | ||
162 | |||
163 | /* image formats. */ | ||
164 | static const struct zr364xx_fmt formats[] = { | ||
165 | { | ||
166 | .name = "JPG", | ||
167 | .fourcc = V4L2_PIX_FMT_JPEG, | ||
168 | .depth = 24 | ||
169 | } | ||
170 | }; | ||
104 | 171 | ||
105 | /* Camera stuff */ | 172 | /* Camera stuff */ |
106 | struct zr364xx_camera { | 173 | struct zr364xx_camera { |
107 | struct usb_device *udev; /* save off the usb device pointer */ | 174 | struct usb_device *udev; /* save off the usb device pointer */ |
108 | struct usb_interface *interface;/* the interface for this device */ | 175 | struct usb_interface *interface;/* the interface for this device */ |
109 | struct video_device *vdev; /* v4l video device */ | 176 | struct video_device *vdev; /* v4l video device */ |
110 | u8 *framebuf; | ||
111 | int nb; | 177 | int nb; |
112 | unsigned char *buffer; | 178 | struct zr364xx_bufferi buffer; |
113 | int skip; | 179 | int skip; |
114 | int brightness; | ||
115 | int width; | 180 | int width; |
116 | int height; | 181 | int height; |
117 | int method; | 182 | int method; |
118 | struct mutex lock; | 183 | struct mutex lock; |
184 | struct mutex open_lock; | ||
119 | int users; | 185 | int users; |
186 | |||
187 | spinlock_t slock; | ||
188 | struct zr364xx_dmaqueue vidq; | ||
189 | int resources; | ||
190 | int last_frame; | ||
191 | int cur_frame; | ||
192 | unsigned long frame_count; | ||
193 | int b_acquire; | ||
194 | struct zr364xx_pipeinfo pipe[1]; | ||
195 | |||
196 | u8 read_endpoint; | ||
197 | |||
198 | const struct zr364xx_fmt *fmt; | ||
199 | struct videobuf_queue vb_vidq; | ||
200 | enum v4l2_buf_type type; | ||
201 | struct zr364xx_mode mode; | ||
120 | }; | 202 | }; |
121 | 203 | ||
204 | /* buffer for one video frame */ | ||
205 | struct zr364xx_buffer { | ||
206 | /* common v4l buffer stuff -- must be first */ | ||
207 | struct videobuf_buffer vb; | ||
208 | const struct zr364xx_fmt *fmt; | ||
209 | }; | ||
122 | 210 | ||
123 | /* function used to send initialisation commands to the camera */ | 211 | /* function used to send initialisation commands to the camera */ |
124 | static int send_control_msg(struct usb_device *udev, u8 request, u16 value, | 212 | static int send_control_msg(struct usb_device *udev, u8 request, u16 value, |
@@ -272,139 +360,116 @@ static unsigned char header2[] = { | |||
272 | }; | 360 | }; |
273 | static unsigned char header3; | 361 | static unsigned char header3; |
274 | 362 | ||
363 | /* ------------------------------------------------------------------ | ||
364 | Videobuf operations | ||
365 | ------------------------------------------------------------------*/ | ||
275 | 366 | ||
367 | static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, | ||
368 | unsigned int *size) | ||
369 | { | ||
370 | struct zr364xx_camera *cam = vq->priv_data; | ||
276 | 371 | ||
277 | /********************/ | 372 | *size = cam->width * cam->height * (cam->fmt->depth >> 3); |
278 | /* V4L2 integration */ | ||
279 | /********************/ | ||
280 | 373 | ||
281 | /* this function reads a full JPEG picture synchronously | 374 | if (*count == 0) |
282 | * TODO: do it asynchronously... */ | 375 | *count = ZR364XX_DEF_BUFS; |
283 | static int read_frame(struct zr364xx_camera *cam, int framenum) | ||
284 | { | ||
285 | int i, n, temp, head, size, actual_length; | ||
286 | unsigned char *ptr = NULL, *jpeg; | ||
287 | |||
288 | redo: | ||
289 | /* hardware brightness */ | ||
290 | n = send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0); | ||
291 | temp = (0x60 << 8) + 127 - cam->brightness; | ||
292 | n = send_control_msg(cam->udev, 1, temp, 0, NULL, 0); | ||
293 | |||
294 | /* during the first loop we are going to insert JPEG header */ | ||
295 | head = 0; | ||
296 | /* this is the place in memory where we are going to build | ||
297 | * the JPEG image */ | ||
298 | jpeg = cam->framebuf + framenum * MAX_FRAME_SIZE; | ||
299 | /* read data... */ | ||
300 | do { | ||
301 | n = usb_bulk_msg(cam->udev, | ||
302 | usb_rcvbulkpipe(cam->udev, 0x81), | ||
303 | cam->buffer, BUFFER_SIZE, &actual_length, | ||
304 | CTRL_TIMEOUT); | ||
305 | DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]); | ||
306 | DBG("bulk : n=%d size=%d", n, actual_length); | ||
307 | if (n < 0) { | ||
308 | dev_err(&cam->udev->dev, "error reading bulk msg\n"); | ||
309 | return 0; | ||
310 | } | ||
311 | if (actual_length < 0 || actual_length > BUFFER_SIZE) { | ||
312 | dev_err(&cam->udev->dev, "wrong number of bytes\n"); | ||
313 | return 0; | ||
314 | } | ||
315 | 376 | ||
316 | /* swap bytes if camera needs it */ | 377 | while (*size * (*count) > ZR364XX_DEF_BUFS * 1024 * 1024) |
317 | if (cam->method == METHOD0) { | 378 | (*count)--; |
318 | u16 *buf = (u16*)cam->buffer; | ||
319 | for (i = 0; i < BUFFER_SIZE/2; i++) | ||
320 | swab16s(buf + i); | ||
321 | } | ||
322 | 379 | ||
323 | /* write the JPEG header */ | 380 | return 0; |
324 | if (!head) { | 381 | } |
325 | DBG("jpeg header"); | ||
326 | ptr = jpeg; | ||
327 | memcpy(ptr, header1, sizeof(header1)); | ||
328 | ptr += sizeof(header1); | ||
329 | header3 = 0; | ||
330 | memcpy(ptr, &header3, 1); | ||
331 | ptr++; | ||
332 | memcpy(ptr, cam->buffer, 64); | ||
333 | ptr += 64; | ||
334 | header3 = 1; | ||
335 | memcpy(ptr, &header3, 1); | ||
336 | ptr++; | ||
337 | memcpy(ptr, cam->buffer + 64, 64); | ||
338 | ptr += 64; | ||
339 | memcpy(ptr, header2, sizeof(header2)); | ||
340 | ptr += sizeof(header2); | ||
341 | memcpy(ptr, cam->buffer + 128, | ||
342 | actual_length - 128); | ||
343 | ptr += actual_length - 128; | ||
344 | head = 1; | ||
345 | DBG("header : %d %d %d %d %d %d %d %d %d", | ||
346 | cam->buffer[0], cam->buffer[1], cam->buffer[2], | ||
347 | cam->buffer[3], cam->buffer[4], cam->buffer[5], | ||
348 | cam->buffer[6], cam->buffer[7], cam->buffer[8]); | ||
349 | } else { | ||
350 | memcpy(ptr, cam->buffer, actual_length); | ||
351 | ptr += actual_length; | ||
352 | } | ||
353 | } | ||
354 | /* ... until there is no more */ | ||
355 | while (actual_length == BUFFER_SIZE); | ||
356 | 382 | ||
357 | /* we skip the 2 first frames which are usually buggy */ | 383 | static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf) |
358 | if (cam->skip) { | 384 | { |
359 | cam->skip--; | 385 | _DBG("%s\n", __func__); |
360 | goto redo; | ||
361 | } | ||
362 | 386 | ||
363 | /* go back to find the JPEG EOI marker */ | 387 | if (in_interrupt()) |
364 | size = ptr - jpeg; | 388 | BUG(); |
365 | ptr -= 2; | ||
366 | while (ptr > jpeg) { | ||
367 | if (*ptr == 0xFF && *(ptr + 1) == 0xD9 | ||
368 | && *(ptr + 2) == 0xFF) | ||
369 | break; | ||
370 | ptr--; | ||
371 | } | ||
372 | if (ptr == jpeg) | ||
373 | DBG("No EOI marker"); | ||
374 | 389 | ||
375 | /* Sometimes there is junk data in the middle of the picture, | 390 | videobuf_vmalloc_free(&buf->vb); |
376 | * we want to skip this bogus frames */ | 391 | buf->vb.state = VIDEOBUF_NEEDS_INIT; |
377 | while (ptr > jpeg) { | 392 | } |
378 | if (*ptr == 0xFF && *(ptr + 1) == 0xFF | 393 | |
379 | && *(ptr + 2) == 0xFF) | 394 | static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, |
380 | break; | 395 | enum v4l2_field field) |
381 | ptr--; | 396 | { |
397 | struct zr364xx_camera *cam = vq->priv_data; | ||
398 | struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer, | ||
399 | vb); | ||
400 | int rc; | ||
401 | |||
402 | DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ? | ||
403 | cam->fmt->name : ""); | ||
404 | if (cam->fmt == NULL) | ||
405 | return -EINVAL; | ||
406 | |||
407 | buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3); | ||
408 | |||
409 | if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) { | ||
410 | DBG("invalid buffer prepare\n"); | ||
411 | return -EINVAL; | ||
382 | } | 412 | } |
383 | if (ptr != jpeg) { | 413 | |
384 | DBG("Bogus frame ? %d", cam->nb); | 414 | buf->fmt = cam->fmt; |
385 | goto redo; | 415 | buf->vb.width = cam->width; |
416 | buf->vb.height = cam->height; | ||
417 | buf->vb.field = field; | ||
418 | |||
419 | if (buf->vb.state == VIDEOBUF_NEEDS_INIT) { | ||
420 | rc = videobuf_iolock(vq, &buf->vb, NULL); | ||
421 | if (rc < 0) | ||
422 | goto fail; | ||
386 | } | 423 | } |
387 | 424 | ||
388 | DBG("jpeg : %d %d %d %d %d %d %d %d", | 425 | buf->vb.state = VIDEOBUF_PREPARED; |
389 | jpeg[0], jpeg[1], jpeg[2], jpeg[3], | 426 | return 0; |
390 | jpeg[4], jpeg[5], jpeg[6], jpeg[7]); | 427 | fail: |
428 | free_buffer(vq, buf); | ||
429 | return rc; | ||
430 | } | ||
431 | |||
432 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
433 | { | ||
434 | struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer, | ||
435 | vb); | ||
436 | struct zr364xx_camera *cam = vq->priv_data; | ||
437 | |||
438 | _DBG("%s\n", __func__); | ||
439 | |||
440 | buf->vb.state = VIDEOBUF_QUEUED; | ||
441 | list_add_tail(&buf->vb.queue, &cam->vidq.active); | ||
442 | } | ||
443 | |||
444 | static void buffer_release(struct videobuf_queue *vq, | ||
445 | struct videobuf_buffer *vb) | ||
446 | { | ||
447 | struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer, | ||
448 | vb); | ||
391 | 449 | ||
392 | return size; | 450 | _DBG("%s\n", __func__); |
451 | free_buffer(vq, buf); | ||
393 | } | 452 | } |
394 | 453 | ||
454 | static struct videobuf_queue_ops zr364xx_video_qops = { | ||
455 | .buf_setup = buffer_setup, | ||
456 | .buf_prepare = buffer_prepare, | ||
457 | .buf_queue = buffer_queue, | ||
458 | .buf_release = buffer_release, | ||
459 | }; | ||
460 | |||
461 | /********************/ | ||
462 | /* V4L2 integration */ | ||
463 | /********************/ | ||
464 | static int zr364xx_vidioc_streamon(struct file *file, void *priv, | ||
465 | enum v4l2_buf_type type); | ||
395 | 466 | ||
396 | static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t cnt, | 467 | static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count, |
397 | loff_t * ppos) | 468 | loff_t * ppos) |
398 | { | 469 | { |
399 | unsigned long count = cnt; | 470 | struct zr364xx_camera *cam = video_drvdata(file); |
400 | struct video_device *vdev = video_devdata(file); | ||
401 | struct zr364xx_camera *cam; | ||
402 | 471 | ||
403 | DBG("zr364xx_read: read %d bytes.", (int) count); | 472 | _DBG("%s\n", __func__); |
404 | |||
405 | if (vdev == NULL) | ||
406 | return -ENODEV; | ||
407 | cam = video_get_drvdata(vdev); | ||
408 | 473 | ||
409 | if (!buf) | 474 | if (!buf) |
410 | return -EINVAL; | 475 | return -EINVAL; |
@@ -412,21 +477,276 @@ static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t cnt, | |||
412 | if (!count) | 477 | if (!count) |
413 | return -EINVAL; | 478 | return -EINVAL; |
414 | 479 | ||
415 | /* NoMan Sux ! */ | 480 | if (cam->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && |
416 | count = read_frame(cam, 0); | 481 | zr364xx_vidioc_streamon(file, cam, cam->type) == 0) { |
482 | DBG("%s: reading %d bytes at pos %d.\n", __func__, (int) count, | ||
483 | (int) *ppos); | ||
484 | |||
485 | /* NoMan Sux ! */ | ||
486 | return videobuf_read_one(&cam->vb_vidq, buf, count, ppos, | ||
487 | file->f_flags & O_NONBLOCK); | ||
488 | } | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | /* video buffer vmalloc implementation based partly on VIVI driver which is | ||
494 | * Copyright (c) 2006 by | ||
495 | * Mauro Carvalho Chehab <mchehab--a.t--infradead.org> | ||
496 | * Ted Walther <ted--a.t--enumera.com> | ||
497 | * John Sokol <sokol--a.t--videotechnology.com> | ||
498 | * http://v4l.videotechnology.com/ | ||
499 | * | ||
500 | */ | ||
501 | static void zr364xx_fillbuff(struct zr364xx_camera *cam, | ||
502 | struct zr364xx_buffer *buf, | ||
503 | int jpgsize) | ||
504 | { | ||
505 | int pos = 0; | ||
506 | struct timeval ts; | ||
507 | const char *tmpbuf; | ||
508 | char *vbuf = videobuf_to_vmalloc(&buf->vb); | ||
509 | unsigned long last_frame; | ||
510 | struct zr364xx_framei *frm; | ||
511 | |||
512 | if (!vbuf) | ||
513 | return; | ||
514 | |||
515 | last_frame = cam->last_frame; | ||
516 | if (last_frame != -1) { | ||
517 | frm = &cam->buffer.frame[last_frame]; | ||
518 | tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits; | ||
519 | switch (buf->fmt->fourcc) { | ||
520 | case V4L2_PIX_FMT_JPEG: | ||
521 | buf->vb.size = jpgsize; | ||
522 | memcpy(vbuf, tmpbuf, buf->vb.size); | ||
523 | break; | ||
524 | default: | ||
525 | printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n"); | ||
526 | } | ||
527 | cam->last_frame = -1; | ||
528 | } else { | ||
529 | printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n"); | ||
530 | return; | ||
531 | } | ||
532 | DBG("%s: Buffer 0x%08lx size= %d\n", __func__, | ||
533 | (unsigned long)vbuf, pos); | ||
534 | /* tell v4l buffer was filled */ | ||
535 | |||
536 | buf->vb.field_count = cam->frame_count * 2; | ||
537 | do_gettimeofday(&ts); | ||
538 | buf->vb.ts = ts; | ||
539 | buf->vb.state = VIDEOBUF_DONE; | ||
540 | } | ||
541 | |||
542 | static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize) | ||
543 | { | ||
544 | struct zr364xx_dmaqueue *dma_q = &cam->vidq; | ||
545 | struct zr364xx_buffer *buf; | ||
546 | unsigned long flags = 0; | ||
547 | int rc = 0; | ||
548 | |||
549 | DBG("wakeup: %p\n", &dma_q); | ||
550 | spin_lock_irqsave(&cam->slock, flags); | ||
551 | |||
552 | if (list_empty(&dma_q->active)) { | ||
553 | DBG("No active queue to serve\n"); | ||
554 | rc = -1; | ||
555 | goto unlock; | ||
556 | } | ||
557 | buf = list_entry(dma_q->active.next, | ||
558 | struct zr364xx_buffer, vb.queue); | ||
559 | |||
560 | if (!waitqueue_active(&buf->vb.done)) { | ||
561 | /* no one active */ | ||
562 | rc = -1; | ||
563 | goto unlock; | ||
564 | } | ||
565 | list_del(&buf->vb.queue); | ||
566 | do_gettimeofday(&buf->vb.ts); | ||
567 | DBG("[%p/%d] wakeup\n", buf, buf->vb.i); | ||
568 | zr364xx_fillbuff(cam, buf, jpgsize); | ||
569 | wake_up(&buf->vb.done); | ||
570 | DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i); | ||
571 | unlock: | ||
572 | spin_unlock_irqrestore(&cam->slock, flags); | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | /* this function moves the usb stream read pipe data | ||
577 | * into the system buffers. | ||
578 | * returns 0 on success, EAGAIN if more data to process (call this | ||
579 | * function again). | ||
580 | */ | ||
581 | static int zr364xx_read_video_callback(struct zr364xx_camera *cam, | ||
582 | struct zr364xx_pipeinfo *pipe_info, | ||
583 | struct urb *purb) | ||
584 | { | ||
585 | unsigned char *pdest; | ||
586 | unsigned char *psrc; | ||
587 | s32 idx = -1; | ||
588 | struct zr364xx_framei *frm; | ||
589 | int i = 0; | ||
590 | unsigned char *ptr = NULL; | ||
591 | |||
592 | _DBG("buffer to user\n"); | ||
593 | idx = cam->cur_frame; | ||
594 | frm = &cam->buffer.frame[idx]; | ||
595 | |||
596 | /* swap bytes if camera needs it */ | ||
597 | if (cam->method == METHOD0) { | ||
598 | u16 *buf = (u16 *)pipe_info->transfer_buffer; | ||
599 | for (i = 0; i < purb->actual_length/2; i++) | ||
600 | swab16s(buf + i); | ||
601 | } | ||
602 | |||
603 | /* search done. now find out if should be acquiring */ | ||
604 | if (!cam->b_acquire) { | ||
605 | /* we found a frame, but this channel is turned off */ | ||
606 | frm->ulState = ZR364XX_READ_IDLE; | ||
607 | return -EINVAL; | ||
608 | } | ||
609 | |||
610 | psrc = (u8 *)pipe_info->transfer_buffer; | ||
611 | ptr = pdest = frm->lpvbits; | ||
612 | |||
613 | if (frm->ulState == ZR364XX_READ_IDLE) { | ||
614 | frm->ulState = ZR364XX_READ_FRAME; | ||
615 | frm->cur_size = 0; | ||
616 | |||
617 | _DBG("jpeg header, "); | ||
618 | memcpy(ptr, header1, sizeof(header1)); | ||
619 | ptr += sizeof(header1); | ||
620 | header3 = 0; | ||
621 | memcpy(ptr, &header3, 1); | ||
622 | ptr++; | ||
623 | memcpy(ptr, psrc, 64); | ||
624 | ptr += 64; | ||
625 | header3 = 1; | ||
626 | memcpy(ptr, &header3, 1); | ||
627 | ptr++; | ||
628 | memcpy(ptr, psrc + 64, 64); | ||
629 | ptr += 64; | ||
630 | memcpy(ptr, header2, sizeof(header2)); | ||
631 | ptr += sizeof(header2); | ||
632 | memcpy(ptr, psrc + 128, | ||
633 | purb->actual_length - 128); | ||
634 | ptr += purb->actual_length - 128; | ||
635 | _DBG("header : %d %d %d %d %d %d %d %d %d\n", | ||
636 | psrc[0], psrc[1], psrc[2], | ||
637 | psrc[3], psrc[4], psrc[5], | ||
638 | psrc[6], psrc[7], psrc[8]); | ||
639 | frm->cur_size = ptr - pdest; | ||
640 | } else { | ||
641 | if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) { | ||
642 | dev_info(&cam->udev->dev, | ||
643 | "%s: buffer (%d bytes) too small to hold " | ||
644 | "frame data. Discarding frame data.\n", | ||
645 | __func__, MAX_FRAME_SIZE); | ||
646 | } else { | ||
647 | pdest += frm->cur_size; | ||
648 | memcpy(pdest, psrc, purb->actual_length); | ||
649 | frm->cur_size += purb->actual_length; | ||
650 | } | ||
651 | } | ||
652 | /*_DBG("cur_size %lu urb size %d\n", frm->cur_size, | ||
653 | purb->actual_length);*/ | ||
654 | |||
655 | if (purb->actual_length < pipe_info->transfer_size) { | ||
656 | _DBG("****************Buffer[%d]full*************\n", idx); | ||
657 | cam->last_frame = cam->cur_frame; | ||
658 | cam->cur_frame++; | ||
659 | /* end of system frame ring buffer, start at zero */ | ||
660 | if (cam->cur_frame == cam->buffer.dwFrames) | ||
661 | cam->cur_frame = 0; | ||
662 | |||
663 | /* frame ready */ | ||
664 | /* go back to find the JPEG EOI marker */ | ||
665 | ptr = pdest = frm->lpvbits; | ||
666 | ptr += frm->cur_size - 2; | ||
667 | while (ptr > pdest) { | ||
668 | if (*ptr == 0xFF && *(ptr + 1) == 0xD9 | ||
669 | && *(ptr + 2) == 0xFF) | ||
670 | break; | ||
671 | ptr--; | ||
672 | } | ||
673 | if (ptr == pdest) | ||
674 | DBG("No EOI marker\n"); | ||
675 | |||
676 | /* Sometimes there is junk data in the middle of the picture, | ||
677 | * we want to skip this bogus frames */ | ||
678 | while (ptr > pdest) { | ||
679 | if (*ptr == 0xFF && *(ptr + 1) == 0xFF | ||
680 | && *(ptr + 2) == 0xFF) | ||
681 | break; | ||
682 | ptr--; | ||
683 | } | ||
684 | if (ptr != pdest) { | ||
685 | DBG("Bogus frame ? %d\n", ++(cam->nb)); | ||
686 | } else if (cam->b_acquire) { | ||
687 | /* we skip the 2 first frames which are usually buggy */ | ||
688 | if (cam->skip) | ||
689 | cam->skip--; | ||
690 | else { | ||
691 | _DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n", | ||
692 | frm->cur_size, | ||
693 | pdest[0], pdest[1], pdest[2], pdest[3], | ||
694 | pdest[4], pdest[5], pdest[6], pdest[7]); | ||
695 | |||
696 | zr364xx_got_frame(cam, frm->cur_size); | ||
697 | } | ||
698 | } | ||
699 | cam->frame_count++; | ||
700 | frm->ulState = ZR364XX_READ_IDLE; | ||
701 | frm->cur_size = 0; | ||
702 | } | ||
703 | /* done successfully */ | ||
704 | return 0; | ||
705 | } | ||
417 | 706 | ||
418 | if (copy_to_user(buf, cam->framebuf, count)) | 707 | static int res_get(struct zr364xx_camera *cam) |
419 | return -EFAULT; | 708 | { |
709 | /* is it free? */ | ||
710 | mutex_lock(&cam->lock); | ||
711 | if (cam->resources) { | ||
712 | /* no, someone else uses it */ | ||
713 | mutex_unlock(&cam->lock); | ||
714 | return 0; | ||
715 | } | ||
716 | /* it's free, grab it */ | ||
717 | cam->resources = 1; | ||
718 | _DBG("res: get\n"); | ||
719 | mutex_unlock(&cam->lock); | ||
720 | return 1; | ||
721 | } | ||
420 | 722 | ||
421 | return count; | 723 | static inline int res_check(struct zr364xx_camera *cam) |
724 | { | ||
725 | return cam->resources; | ||
422 | } | 726 | } |
423 | 727 | ||
728 | static void res_free(struct zr364xx_camera *cam) | ||
729 | { | ||
730 | mutex_lock(&cam->lock); | ||
731 | cam->resources = 0; | ||
732 | mutex_unlock(&cam->lock); | ||
733 | _DBG("res: put\n"); | ||
734 | } | ||
424 | 735 | ||
425 | static int zr364xx_vidioc_querycap(struct file *file, void *priv, | 736 | static int zr364xx_vidioc_querycap(struct file *file, void *priv, |
426 | struct v4l2_capability *cap) | 737 | struct v4l2_capability *cap) |
427 | { | 738 | { |
428 | strcpy(cap->driver, DRIVER_DESC); | 739 | struct zr364xx_camera *cam = video_drvdata(file); |
429 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; | 740 | |
741 | strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver)); | ||
742 | strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); | ||
743 | strlcpy(cap->bus_info, dev_name(&cam->udev->dev), | ||
744 | sizeof(cap->bus_info)); | ||
745 | cap->version = ZR364XX_VERSION_CODE; | ||
746 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
747 | V4L2_CAP_READWRITE | | ||
748 | V4L2_CAP_STREAMING; | ||
749 | |||
430 | return 0; | 750 | return 0; |
431 | } | 751 | } |
432 | 752 | ||
@@ -458,12 +778,11 @@ static int zr364xx_vidioc_s_input(struct file *file, void *priv, | |||
458 | static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, | 778 | static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, |
459 | struct v4l2_queryctrl *c) | 779 | struct v4l2_queryctrl *c) |
460 | { | 780 | { |
461 | struct video_device *vdev = video_devdata(file); | ||
462 | struct zr364xx_camera *cam; | 781 | struct zr364xx_camera *cam; |
463 | 782 | ||
464 | if (vdev == NULL) | 783 | if (file == NULL) |
465 | return -ENODEV; | 784 | return -ENODEV; |
466 | cam = video_get_drvdata(vdev); | 785 | cam = video_drvdata(file); |
467 | 786 | ||
468 | switch (c->id) { | 787 | switch (c->id) { |
469 | case V4L2_CID_BRIGHTNESS: | 788 | case V4L2_CID_BRIGHTNESS: |
@@ -472,7 +791,7 @@ static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, | |||
472 | c->minimum = 0; | 791 | c->minimum = 0; |
473 | c->maximum = 127; | 792 | c->maximum = 127; |
474 | c->step = 1; | 793 | c->step = 1; |
475 | c->default_value = cam->brightness; | 794 | c->default_value = cam->mode.brightness; |
476 | c->flags = 0; | 795 | c->flags = 0; |
477 | break; | 796 | break; |
478 | default: | 797 | default: |
@@ -484,36 +803,42 @@ static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, | |||
484 | static int zr364xx_vidioc_s_ctrl(struct file *file, void *priv, | 803 | static int zr364xx_vidioc_s_ctrl(struct file *file, void *priv, |
485 | struct v4l2_control *c) | 804 | struct v4l2_control *c) |
486 | { | 805 | { |
487 | struct video_device *vdev = video_devdata(file); | ||
488 | struct zr364xx_camera *cam; | 806 | struct zr364xx_camera *cam; |
807 | int temp; | ||
489 | 808 | ||
490 | if (vdev == NULL) | 809 | if (file == NULL) |
491 | return -ENODEV; | 810 | return -ENODEV; |
492 | cam = video_get_drvdata(vdev); | 811 | cam = video_drvdata(file); |
493 | 812 | ||
494 | switch (c->id) { | 813 | switch (c->id) { |
495 | case V4L2_CID_BRIGHTNESS: | 814 | case V4L2_CID_BRIGHTNESS: |
496 | cam->brightness = c->value; | 815 | cam->mode.brightness = c->value; |
816 | /* hardware brightness */ | ||
817 | mutex_lock(&cam->lock); | ||
818 | send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0); | ||
819 | temp = (0x60 << 8) + 127 - cam->mode.brightness; | ||
820 | send_control_msg(cam->udev, 1, temp, 0, NULL, 0); | ||
821 | mutex_unlock(&cam->lock); | ||
497 | break; | 822 | break; |
498 | default: | 823 | default: |
499 | return -EINVAL; | 824 | return -EINVAL; |
500 | } | 825 | } |
826 | |||
501 | return 0; | 827 | return 0; |
502 | } | 828 | } |
503 | 829 | ||
504 | static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv, | 830 | static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv, |
505 | struct v4l2_control *c) | 831 | struct v4l2_control *c) |
506 | { | 832 | { |
507 | struct video_device *vdev = video_devdata(file); | ||
508 | struct zr364xx_camera *cam; | 833 | struct zr364xx_camera *cam; |
509 | 834 | ||
510 | if (vdev == NULL) | 835 | if (file == NULL) |
511 | return -ENODEV; | 836 | return -ENODEV; |
512 | cam = video_get_drvdata(vdev); | 837 | cam = video_drvdata(file); |
513 | 838 | ||
514 | switch (c->id) { | 839 | switch (c->id) { |
515 | case V4L2_CID_BRIGHTNESS: | 840 | case V4L2_CID_BRIGHTNESS: |
516 | c->value = cam->brightness; | 841 | c->value = cam->mode.brightness; |
517 | break; | 842 | break; |
518 | default: | 843 | default: |
519 | return -EINVAL; | 844 | return -EINVAL; |
@@ -527,47 +852,63 @@ static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file, | |||
527 | if (f->index > 0) | 852 | if (f->index > 0) |
528 | return -EINVAL; | 853 | return -EINVAL; |
529 | f->flags = V4L2_FMT_FLAG_COMPRESSED; | 854 | f->flags = V4L2_FMT_FLAG_COMPRESSED; |
530 | strcpy(f->description, "JPEG"); | 855 | strcpy(f->description, formats[0].name); |
531 | f->pixelformat = V4L2_PIX_FMT_JPEG; | 856 | f->pixelformat = formats[0].fourcc; |
532 | return 0; | 857 | return 0; |
533 | } | 858 | } |
534 | 859 | ||
860 | static char *decode_fourcc(__u32 pixelformat, char *buf) | ||
861 | { | ||
862 | buf[0] = pixelformat & 0xff; | ||
863 | buf[1] = (pixelformat >> 8) & 0xff; | ||
864 | buf[2] = (pixelformat >> 16) & 0xff; | ||
865 | buf[3] = (pixelformat >> 24) & 0xff; | ||
866 | buf[4] = '\0'; | ||
867 | return buf; | ||
868 | } | ||
869 | |||
535 | static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, | 870 | static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
536 | struct v4l2_format *f) | 871 | struct v4l2_format *f) |
537 | { | 872 | { |
538 | struct video_device *vdev = video_devdata(file); | 873 | struct zr364xx_camera *cam = video_drvdata(file); |
539 | struct zr364xx_camera *cam; | 874 | char pixelformat_name[5]; |
540 | 875 | ||
541 | if (vdev == NULL) | 876 | if (cam == NULL) |
542 | return -ENODEV; | 877 | return -ENODEV; |
543 | cam = video_get_drvdata(vdev); | ||
544 | 878 | ||
545 | if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) | 879 | if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) { |
546 | return -EINVAL; | 880 | DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__, |
547 | if (f->fmt.pix.field != V4L2_FIELD_ANY && | 881 | decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name)); |
548 | f->fmt.pix.field != V4L2_FIELD_NONE) | ||
549 | return -EINVAL; | 882 | return -EINVAL; |
883 | } | ||
884 | |||
885 | if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) && | ||
886 | !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) { | ||
887 | f->fmt.pix.width = 320; | ||
888 | f->fmt.pix.height = 240; | ||
889 | } | ||
890 | |||
550 | f->fmt.pix.field = V4L2_FIELD_NONE; | 891 | f->fmt.pix.field = V4L2_FIELD_NONE; |
551 | f->fmt.pix.width = cam->width; | ||
552 | f->fmt.pix.height = cam->height; | ||
553 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; | 892 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; |
554 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 893 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
555 | f->fmt.pix.colorspace = 0; | 894 | f->fmt.pix.colorspace = 0; |
556 | f->fmt.pix.priv = 0; | 895 | f->fmt.pix.priv = 0; |
896 | DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__, | ||
897 | decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name), | ||
898 | f->fmt.pix.field); | ||
557 | return 0; | 899 | return 0; |
558 | } | 900 | } |
559 | 901 | ||
560 | static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, | 902 | static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
561 | struct v4l2_format *f) | 903 | struct v4l2_format *f) |
562 | { | 904 | { |
563 | struct video_device *vdev = video_devdata(file); | ||
564 | struct zr364xx_camera *cam; | 905 | struct zr364xx_camera *cam; |
565 | 906 | ||
566 | if (vdev == NULL) | 907 | if (file == NULL) |
567 | return -ENODEV; | 908 | return -ENODEV; |
568 | cam = video_get_drvdata(vdev); | 909 | cam = video_drvdata(file); |
569 | 910 | ||
570 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; | 911 | f->fmt.pix.pixelformat = formats[0].fourcc; |
571 | f->fmt.pix.field = V4L2_FIELD_NONE; | 912 | f->fmt.pix.field = V4L2_FIELD_NONE; |
572 | f->fmt.pix.width = cam->width; | 913 | f->fmt.pix.width = cam->width; |
573 | f->fmt.pix.height = cam->height; | 914 | f->fmt.pix.height = cam->height; |
@@ -581,38 +922,327 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
581 | static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 922 | static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
582 | struct v4l2_format *f) | 923 | struct v4l2_format *f) |
583 | { | 924 | { |
584 | struct video_device *vdev = video_devdata(file); | 925 | struct zr364xx_camera *cam = video_drvdata(file); |
585 | struct zr364xx_camera *cam; | 926 | struct videobuf_queue *q = &cam->vb_vidq; |
927 | char pixelformat_name[5]; | ||
928 | int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f); | ||
929 | int i; | ||
586 | 930 | ||
587 | if (vdev == NULL) | 931 | if (ret < 0) |
588 | return -ENODEV; | 932 | return ret; |
589 | cam = video_get_drvdata(vdev); | ||
590 | 933 | ||
591 | if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) | 934 | mutex_lock(&q->vb_lock); |
592 | return -EINVAL; | 935 | |
593 | if (f->fmt.pix.field != V4L2_FIELD_ANY && | 936 | if (videobuf_queue_is_busy(&cam->vb_vidq)) { |
594 | f->fmt.pix.field != V4L2_FIELD_NONE) | 937 | DBG("%s queue busy\n", __func__); |
595 | return -EINVAL; | 938 | ret = -EBUSY; |
596 | f->fmt.pix.field = V4L2_FIELD_NONE; | 939 | goto out; |
597 | f->fmt.pix.width = cam->width; | 940 | } |
598 | f->fmt.pix.height = cam->height; | 941 | |
942 | if (res_check(cam)) { | ||
943 | DBG("%s can't change format after started\n", __func__); | ||
944 | ret = -EBUSY; | ||
945 | goto out; | ||
946 | } | ||
947 | |||
948 | cam->width = f->fmt.pix.width; | ||
949 | cam->height = f->fmt.pix.height; | ||
950 | dev_info(&cam->udev->dev, "%s: %dx%d mode selected\n", __func__, | ||
951 | cam->width, cam->height); | ||
599 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; | 952 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; |
600 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 953 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
601 | f->fmt.pix.colorspace = 0; | 954 | f->fmt.pix.colorspace = 0; |
602 | f->fmt.pix.priv = 0; | 955 | f->fmt.pix.priv = 0; |
603 | DBG("ok!"); | 956 | cam->vb_vidq.field = f->fmt.pix.field; |
957 | cam->mode.color = V4L2_PIX_FMT_JPEG; | ||
958 | |||
959 | if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120) | ||
960 | mode = 1; | ||
961 | else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480) | ||
962 | mode = 2; | ||
963 | else | ||
964 | mode = 0; | ||
965 | |||
966 | m0d1[0] = mode; | ||
967 | m1[2].value = 0xf000 + mode; | ||
968 | m2[1].value = 0xf000 + mode; | ||
969 | header2[437] = cam->height / 256; | ||
970 | header2[438] = cam->height % 256; | ||
971 | header2[439] = cam->width / 256; | ||
972 | header2[440] = cam->width % 256; | ||
973 | |||
974 | for (i = 0; init[cam->method][i].size != -1; i++) { | ||
975 | ret = | ||
976 | send_control_msg(cam->udev, 1, init[cam->method][i].value, | ||
977 | 0, init[cam->method][i].bytes, | ||
978 | init[cam->method][i].size); | ||
979 | if (ret < 0) { | ||
980 | dev_err(&cam->udev->dev, | ||
981 | "error during resolution change sequence: %d\n", i); | ||
982 | goto out; | ||
983 | } | ||
984 | } | ||
985 | |||
986 | /* Added some delay here, since opening/closing the camera quickly, | ||
987 | * like Ekiga does during its startup, can crash the webcam | ||
988 | */ | ||
989 | mdelay(100); | ||
990 | cam->skip = 2; | ||
991 | ret = 0; | ||
992 | |||
993 | out: | ||
994 | mutex_unlock(&q->vb_lock); | ||
995 | |||
996 | DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__, | ||
997 | decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name), | ||
998 | f->fmt.pix.field); | ||
999 | return ret; | ||
1000 | } | ||
1001 | |||
1002 | static int zr364xx_vidioc_reqbufs(struct file *file, void *priv, | ||
1003 | struct v4l2_requestbuffers *p) | ||
1004 | { | ||
1005 | int rc; | ||
1006 | struct zr364xx_camera *cam = video_drvdata(file); | ||
1007 | rc = videobuf_reqbufs(&cam->vb_vidq, p); | ||
1008 | return rc; | ||
1009 | } | ||
1010 | |||
1011 | static int zr364xx_vidioc_querybuf(struct file *file, | ||
1012 | void *priv, | ||
1013 | struct v4l2_buffer *p) | ||
1014 | { | ||
1015 | int rc; | ||
1016 | struct zr364xx_camera *cam = video_drvdata(file); | ||
1017 | rc = videobuf_querybuf(&cam->vb_vidq, p); | ||
1018 | return rc; | ||
1019 | } | ||
1020 | |||
1021 | static int zr364xx_vidioc_qbuf(struct file *file, | ||
1022 | void *priv, | ||
1023 | struct v4l2_buffer *p) | ||
1024 | { | ||
1025 | int rc; | ||
1026 | struct zr364xx_camera *cam = video_drvdata(file); | ||
1027 | _DBG("%s\n", __func__); | ||
1028 | rc = videobuf_qbuf(&cam->vb_vidq, p); | ||
1029 | return rc; | ||
1030 | } | ||
1031 | |||
1032 | static int zr364xx_vidioc_dqbuf(struct file *file, | ||
1033 | void *priv, | ||
1034 | struct v4l2_buffer *p) | ||
1035 | { | ||
1036 | int rc; | ||
1037 | struct zr364xx_camera *cam = video_drvdata(file); | ||
1038 | _DBG("%s\n", __func__); | ||
1039 | rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK); | ||
1040 | return rc; | ||
1041 | } | ||
1042 | |||
1043 | static void read_pipe_completion(struct urb *purb) | ||
1044 | { | ||
1045 | struct zr364xx_pipeinfo *pipe_info; | ||
1046 | struct zr364xx_camera *cam; | ||
1047 | int pipe; | ||
1048 | |||
1049 | pipe_info = purb->context; | ||
1050 | _DBG("%s %p, status %d\n", __func__, purb, purb->status); | ||
1051 | if (pipe_info == NULL) { | ||
1052 | printk(KERN_ERR KBUILD_MODNAME ": no context!\n"); | ||
1053 | return; | ||
1054 | } | ||
1055 | |||
1056 | cam = pipe_info->cam; | ||
1057 | if (cam == NULL) { | ||
1058 | printk(KERN_ERR KBUILD_MODNAME ": no context!\n"); | ||
1059 | return; | ||
1060 | } | ||
1061 | |||
1062 | /* if shutting down, do not resubmit, exit immediately */ | ||
1063 | if (purb->status == -ESHUTDOWN) { | ||
1064 | DBG("%s, err shutdown\n", __func__); | ||
1065 | pipe_info->err_count++; | ||
1066 | return; | ||
1067 | } | ||
1068 | |||
1069 | if (pipe_info->state == 0) { | ||
1070 | DBG("exiting USB pipe\n"); | ||
1071 | return; | ||
1072 | } | ||
1073 | |||
1074 | if (purb->actual_length < 0 || | ||
1075 | purb->actual_length > pipe_info->transfer_size) { | ||
1076 | dev_err(&cam->udev->dev, "wrong number of bytes\n"); | ||
1077 | return; | ||
1078 | } | ||
1079 | |||
1080 | if (purb->status == 0) | ||
1081 | zr364xx_read_video_callback(cam, pipe_info, purb); | ||
1082 | else { | ||
1083 | pipe_info->err_count++; | ||
1084 | DBG("%s: failed URB %d\n", __func__, purb->status); | ||
1085 | } | ||
1086 | |||
1087 | pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint); | ||
1088 | |||
1089 | /* reuse urb */ | ||
1090 | usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev, | ||
1091 | pipe, | ||
1092 | pipe_info->transfer_buffer, | ||
1093 | pipe_info->transfer_size, | ||
1094 | read_pipe_completion, pipe_info); | ||
1095 | |||
1096 | if (pipe_info->state != 0) { | ||
1097 | purb->status = usb_submit_urb(pipe_info->stream_urb, | ||
1098 | GFP_ATOMIC); | ||
1099 | |||
1100 | if (purb->status) | ||
1101 | dev_err(&cam->udev->dev, | ||
1102 | "error submitting urb (error=%i)\n", | ||
1103 | purb->status); | ||
1104 | } else | ||
1105 | DBG("read pipe complete state 0\n"); | ||
1106 | } | ||
1107 | |||
1108 | static int zr364xx_start_readpipe(struct zr364xx_camera *cam) | ||
1109 | { | ||
1110 | int pipe; | ||
1111 | int retval; | ||
1112 | struct zr364xx_pipeinfo *pipe_info = cam->pipe; | ||
1113 | pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint); | ||
1114 | DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint); | ||
1115 | |||
1116 | pipe_info->state = 1; | ||
1117 | pipe_info->err_count = 0; | ||
1118 | pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1119 | if (!pipe_info->stream_urb) { | ||
1120 | dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n"); | ||
1121 | return -ENOMEM; | ||
1122 | } | ||
1123 | /* transfer buffer allocated in board_init */ | ||
1124 | usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev, | ||
1125 | pipe, | ||
1126 | pipe_info->transfer_buffer, | ||
1127 | pipe_info->transfer_size, | ||
1128 | read_pipe_completion, pipe_info); | ||
1129 | |||
1130 | DBG("submitting URB %p\n", pipe_info->stream_urb); | ||
1131 | retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL); | ||
1132 | if (retval) { | ||
1133 | printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n"); | ||
1134 | return retval; | ||
1135 | } | ||
1136 | |||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | static void zr364xx_stop_readpipe(struct zr364xx_camera *cam) | ||
1141 | { | ||
1142 | struct zr364xx_pipeinfo *pipe_info; | ||
1143 | |||
1144 | if (cam == NULL) { | ||
1145 | printk(KERN_ERR KBUILD_MODNAME ": invalid device\n"); | ||
1146 | return; | ||
1147 | } | ||
1148 | DBG("stop read pipe\n"); | ||
1149 | pipe_info = cam->pipe; | ||
1150 | if (pipe_info) { | ||
1151 | if (pipe_info->state != 0) | ||
1152 | pipe_info->state = 0; | ||
1153 | |||
1154 | if (pipe_info->stream_urb) { | ||
1155 | /* cancel urb */ | ||
1156 | usb_kill_urb(pipe_info->stream_urb); | ||
1157 | usb_free_urb(pipe_info->stream_urb); | ||
1158 | pipe_info->stream_urb = NULL; | ||
1159 | } | ||
1160 | } | ||
1161 | return; | ||
1162 | } | ||
1163 | |||
1164 | /* starts acquisition process */ | ||
1165 | static int zr364xx_start_acquire(struct zr364xx_camera *cam) | ||
1166 | { | ||
1167 | int j; | ||
1168 | |||
1169 | DBG("start acquire\n"); | ||
1170 | |||
1171 | cam->last_frame = -1; | ||
1172 | cam->cur_frame = 0; | ||
1173 | for (j = 0; j < FRAMES; j++) { | ||
1174 | cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE; | ||
1175 | cam->buffer.frame[j].cur_size = 0; | ||
1176 | } | ||
1177 | cam->b_acquire = 1; | ||
1178 | return 0; | ||
1179 | } | ||
1180 | |||
1181 | static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam) | ||
1182 | { | ||
1183 | cam->b_acquire = 0; | ||
604 | return 0; | 1184 | return 0; |
605 | } | 1185 | } |
606 | 1186 | ||
607 | static int zr364xx_vidioc_streamon(struct file *file, void *priv, | 1187 | static int zr364xx_vidioc_streamon(struct file *file, void *priv, |
608 | enum v4l2_buf_type type) | 1188 | enum v4l2_buf_type type) |
609 | { | 1189 | { |
610 | return 0; | 1190 | struct zr364xx_camera *cam = video_drvdata(file); |
1191 | int j; | ||
1192 | int res; | ||
1193 | |||
1194 | DBG("%s\n", __func__); | ||
1195 | |||
1196 | if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1197 | dev_err(&cam->udev->dev, "invalid fh type0\n"); | ||
1198 | return -EINVAL; | ||
1199 | } | ||
1200 | if (cam->type != type) { | ||
1201 | dev_err(&cam->udev->dev, "invalid fh type1\n"); | ||
1202 | return -EINVAL; | ||
1203 | } | ||
1204 | |||
1205 | if (!res_get(cam)) { | ||
1206 | dev_err(&cam->udev->dev, "stream busy\n"); | ||
1207 | return -EBUSY; | ||
1208 | } | ||
1209 | |||
1210 | cam->last_frame = -1; | ||
1211 | cam->cur_frame = 0; | ||
1212 | cam->frame_count = 0; | ||
1213 | for (j = 0; j < FRAMES; j++) { | ||
1214 | cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE; | ||
1215 | cam->buffer.frame[j].cur_size = 0; | ||
1216 | } | ||
1217 | res = videobuf_streamon(&cam->vb_vidq); | ||
1218 | if (res == 0) { | ||
1219 | zr364xx_start_acquire(cam); | ||
1220 | } else { | ||
1221 | res_free(cam); | ||
1222 | } | ||
1223 | return res; | ||
611 | } | 1224 | } |
612 | 1225 | ||
613 | static int zr364xx_vidioc_streamoff(struct file *file, void *priv, | 1226 | static int zr364xx_vidioc_streamoff(struct file *file, void *priv, |
614 | enum v4l2_buf_type type) | 1227 | enum v4l2_buf_type type) |
615 | { | 1228 | { |
1229 | int res; | ||
1230 | struct zr364xx_camera *cam = video_drvdata(file); | ||
1231 | |||
1232 | DBG("%s\n", __func__); | ||
1233 | if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1234 | dev_err(&cam->udev->dev, "invalid fh type0\n"); | ||
1235 | return -EINVAL; | ||
1236 | } | ||
1237 | if (cam->type != type) { | ||
1238 | dev_err(&cam->udev->dev, "invalid fh type1\n"); | ||
1239 | return -EINVAL; | ||
1240 | } | ||
1241 | zr364xx_stop_acquire(cam); | ||
1242 | res = videobuf_streamoff(&cam->vb_vidq); | ||
1243 | if (res < 0) | ||
1244 | return res; | ||
1245 | res_free(cam); | ||
616 | return 0; | 1246 | return 0; |
617 | } | 1247 | } |
618 | 1248 | ||
@@ -621,28 +1251,19 @@ static int zr364xx_vidioc_streamoff(struct file *file, void *priv, | |||
621 | static int zr364xx_open(struct file *file) | 1251 | static int zr364xx_open(struct file *file) |
622 | { | 1252 | { |
623 | struct video_device *vdev = video_devdata(file); | 1253 | struct video_device *vdev = video_devdata(file); |
624 | struct zr364xx_camera *cam = video_get_drvdata(vdev); | 1254 | struct zr364xx_camera *cam = video_drvdata(file); |
625 | struct usb_device *udev = cam->udev; | 1255 | struct usb_device *udev = cam->udev; |
626 | int i, err; | 1256 | int i, err; |
627 | 1257 | ||
628 | DBG("zr364xx_open"); | 1258 | DBG("%s\n", __func__); |
629 | 1259 | ||
630 | mutex_lock(&cam->lock); | 1260 | mutex_lock(&cam->open_lock); |
631 | 1261 | ||
632 | if (cam->users) { | 1262 | if (cam->users) { |
633 | err = -EBUSY; | 1263 | err = -EBUSY; |
634 | goto out; | 1264 | goto out; |
635 | } | 1265 | } |
636 | 1266 | ||
637 | if (!cam->framebuf) { | ||
638 | cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES); | ||
639 | if (!cam->framebuf) { | ||
640 | dev_err(&cam->udev->dev, "vmalloc_32 failed!\n"); | ||
641 | err = -ENOMEM; | ||
642 | goto out; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | for (i = 0; init[cam->method][i].size != -1; i++) { | 1267 | for (i = 0; init[cam->method][i].size != -1; i++) { |
647 | err = | 1268 | err = |
648 | send_control_msg(udev, 1, init[cam->method][i].value, | 1269 | send_control_msg(udev, 1, init[cam->method][i].value, |
@@ -658,6 +1279,14 @@ static int zr364xx_open(struct file *file) | |||
658 | cam->skip = 2; | 1279 | cam->skip = 2; |
659 | cam->users++; | 1280 | cam->users++; |
660 | file->private_data = vdev; | 1281 | file->private_data = vdev; |
1282 | cam->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1283 | cam->fmt = formats; | ||
1284 | |||
1285 | videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops, | ||
1286 | NULL, &cam->slock, | ||
1287 | cam->type, | ||
1288 | V4L2_FIELD_NONE, | ||
1289 | sizeof(struct zr364xx_buffer), cam); | ||
661 | 1290 | ||
662 | /* Added some delay here, since opening/closing the camera quickly, | 1291 | /* Added some delay here, since opening/closing the camera quickly, |
663 | * like Ekiga does during its startup, can crash the webcam | 1292 | * like Ekiga does during its startup, can crash the webcam |
@@ -666,28 +1295,70 @@ static int zr364xx_open(struct file *file) | |||
666 | err = 0; | 1295 | err = 0; |
667 | 1296 | ||
668 | out: | 1297 | out: |
669 | mutex_unlock(&cam->lock); | 1298 | mutex_unlock(&cam->open_lock); |
1299 | DBG("%s: %d\n", __func__, err); | ||
670 | return err; | 1300 | return err; |
671 | } | 1301 | } |
672 | 1302 | ||
1303 | static void zr364xx_destroy(struct zr364xx_camera *cam) | ||
1304 | { | ||
1305 | unsigned long i; | ||
1306 | |||
1307 | if (!cam) { | ||
1308 | printk(KERN_ERR KBUILD_MODNAME ", %s: no device\n", __func__); | ||
1309 | return; | ||
1310 | } | ||
1311 | mutex_lock(&cam->open_lock); | ||
1312 | if (cam->vdev) | ||
1313 | video_unregister_device(cam->vdev); | ||
1314 | cam->vdev = NULL; | ||
1315 | |||
1316 | /* stops the read pipe if it is running */ | ||
1317 | if (cam->b_acquire) | ||
1318 | zr364xx_stop_acquire(cam); | ||
1319 | |||
1320 | zr364xx_stop_readpipe(cam); | ||
1321 | |||
1322 | /* release sys buffers */ | ||
1323 | for (i = 0; i < FRAMES; i++) { | ||
1324 | if (cam->buffer.frame[i].lpvbits) { | ||
1325 | DBG("vfree %p\n", cam->buffer.frame[i].lpvbits); | ||
1326 | vfree(cam->buffer.frame[i].lpvbits); | ||
1327 | } | ||
1328 | cam->buffer.frame[i].lpvbits = NULL; | ||
1329 | } | ||
1330 | |||
1331 | /* release transfer buffer */ | ||
1332 | kfree(cam->pipe->transfer_buffer); | ||
1333 | cam->pipe->transfer_buffer = NULL; | ||
1334 | mutex_unlock(&cam->open_lock); | ||
1335 | kfree(cam); | ||
1336 | cam = NULL; | ||
1337 | } | ||
673 | 1338 | ||
674 | /* release the camera */ | 1339 | /* release the camera */ |
675 | static int zr364xx_release(struct file *file) | 1340 | static int zr364xx_release(struct file *file) |
676 | { | 1341 | { |
677 | struct video_device *vdev = video_devdata(file); | ||
678 | struct zr364xx_camera *cam; | 1342 | struct zr364xx_camera *cam; |
679 | struct usb_device *udev; | 1343 | struct usb_device *udev; |
680 | int i, err; | 1344 | int i, err; |
681 | 1345 | ||
682 | DBG("zr364xx_release"); | 1346 | DBG("%s\n", __func__); |
1347 | cam = video_drvdata(file); | ||
683 | 1348 | ||
684 | if (vdev == NULL) | 1349 | if (!cam) |
685 | return -ENODEV; | 1350 | return -ENODEV; |
686 | cam = video_get_drvdata(vdev); | ||
687 | 1351 | ||
1352 | mutex_lock(&cam->open_lock); | ||
688 | udev = cam->udev; | 1353 | udev = cam->udev; |
689 | 1354 | ||
690 | mutex_lock(&cam->lock); | 1355 | /* turn off stream */ |
1356 | if (res_check(cam)) { | ||
1357 | if (cam->b_acquire) | ||
1358 | zr364xx_stop_acquire(cam); | ||
1359 | videobuf_streamoff(&cam->vb_vidq); | ||
1360 | res_free(cam); | ||
1361 | } | ||
691 | 1362 | ||
692 | cam->users--; | 1363 | cam->users--; |
693 | file->private_data = NULL; | 1364 | file->private_data = NULL; |
@@ -710,40 +1381,43 @@ static int zr364xx_release(struct file *file) | |||
710 | err = 0; | 1381 | err = 0; |
711 | 1382 | ||
712 | out: | 1383 | out: |
713 | mutex_unlock(&cam->lock); | 1384 | mutex_unlock(&cam->open_lock); |
1385 | |||
714 | return err; | 1386 | return err; |
715 | } | 1387 | } |
716 | 1388 | ||
717 | 1389 | ||
718 | static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma) | 1390 | static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma) |
719 | { | 1391 | { |
720 | void *pos; | 1392 | struct zr364xx_camera *cam = video_drvdata(file); |
721 | unsigned long start = vma->vm_start; | 1393 | int ret; |
722 | unsigned long size = vma->vm_end - vma->vm_start; | ||
723 | struct video_device *vdev = video_devdata(file); | ||
724 | struct zr364xx_camera *cam; | ||
725 | |||
726 | DBG("zr364xx_mmap: %ld\n", size); | ||
727 | 1394 | ||
728 | if (vdev == NULL) | 1395 | if (cam == NULL) { |
1396 | DBG("%s: cam == NULL\n", __func__); | ||
729 | return -ENODEV; | 1397 | return -ENODEV; |
730 | cam = video_get_drvdata(vdev); | ||
731 | |||
732 | pos = cam->framebuf; | ||
733 | while (size > 0) { | ||
734 | if (vm_insert_page(vma, start, vmalloc_to_page(pos))) | ||
735 | return -EAGAIN; | ||
736 | start += PAGE_SIZE; | ||
737 | pos += PAGE_SIZE; | ||
738 | if (size > PAGE_SIZE) | ||
739 | size -= PAGE_SIZE; | ||
740 | else | ||
741 | size = 0; | ||
742 | } | 1398 | } |
1399 | DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma); | ||
743 | 1400 | ||
744 | return 0; | 1401 | ret = videobuf_mmap_mapper(&cam->vb_vidq, vma); |
1402 | |||
1403 | DBG("vma start=0x%08lx, size=%ld, ret=%d\n", | ||
1404 | (unsigned long)vma->vm_start, | ||
1405 | (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret); | ||
1406 | return ret; | ||
745 | } | 1407 | } |
746 | 1408 | ||
1409 | static unsigned int zr364xx_poll(struct file *file, | ||
1410 | struct poll_table_struct *wait) | ||
1411 | { | ||
1412 | struct zr364xx_camera *cam = video_drvdata(file); | ||
1413 | struct videobuf_queue *q = &cam->vb_vidq; | ||
1414 | _DBG("%s\n", __func__); | ||
1415 | |||
1416 | if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1417 | return POLLERR; | ||
1418 | |||
1419 | return videobuf_poll_stream(file, q, wait); | ||
1420 | } | ||
747 | 1421 | ||
748 | static const struct v4l2_file_operations zr364xx_fops = { | 1422 | static const struct v4l2_file_operations zr364xx_fops = { |
749 | .owner = THIS_MODULE, | 1423 | .owner = THIS_MODULE, |
@@ -752,6 +1426,7 @@ static const struct v4l2_file_operations zr364xx_fops = { | |||
752 | .read = zr364xx_read, | 1426 | .read = zr364xx_read, |
753 | .mmap = zr364xx_mmap, | 1427 | .mmap = zr364xx_mmap, |
754 | .ioctl = video_ioctl2, | 1428 | .ioctl = video_ioctl2, |
1429 | .poll = zr364xx_poll, | ||
755 | }; | 1430 | }; |
756 | 1431 | ||
757 | static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = { | 1432 | static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = { |
@@ -768,6 +1443,10 @@ static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = { | |||
768 | .vidioc_queryctrl = zr364xx_vidioc_queryctrl, | 1443 | .vidioc_queryctrl = zr364xx_vidioc_queryctrl, |
769 | .vidioc_g_ctrl = zr364xx_vidioc_g_ctrl, | 1444 | .vidioc_g_ctrl = zr364xx_vidioc_g_ctrl, |
770 | .vidioc_s_ctrl = zr364xx_vidioc_s_ctrl, | 1445 | .vidioc_s_ctrl = zr364xx_vidioc_s_ctrl, |
1446 | .vidioc_reqbufs = zr364xx_vidioc_reqbufs, | ||
1447 | .vidioc_querybuf = zr364xx_vidioc_querybuf, | ||
1448 | .vidioc_qbuf = zr364xx_vidioc_qbuf, | ||
1449 | .vidioc_dqbuf = zr364xx_vidioc_dqbuf, | ||
771 | }; | 1450 | }; |
772 | 1451 | ||
773 | static struct video_device zr364xx_template = { | 1452 | static struct video_device zr364xx_template = { |
@@ -783,15 +1462,76 @@ static struct video_device zr364xx_template = { | |||
783 | /*******************/ | 1462 | /*******************/ |
784 | /* USB integration */ | 1463 | /* USB integration */ |
785 | /*******************/ | 1464 | /*******************/ |
1465 | static int zr364xx_board_init(struct zr364xx_camera *cam) | ||
1466 | { | ||
1467 | struct zr364xx_pipeinfo *pipe = cam->pipe; | ||
1468 | unsigned long i; | ||
1469 | |||
1470 | DBG("board init: %p\n", cam); | ||
1471 | memset(pipe, 0, sizeof(*pipe)); | ||
1472 | pipe->cam = cam; | ||
1473 | pipe->transfer_size = BUFFER_SIZE; | ||
1474 | |||
1475 | pipe->transfer_buffer = kzalloc(pipe->transfer_size, | ||
1476 | GFP_KERNEL); | ||
1477 | if (pipe->transfer_buffer == NULL) { | ||
1478 | DBG("out of memory!\n"); | ||
1479 | return -ENOMEM; | ||
1480 | } | ||
1481 | |||
1482 | cam->b_acquire = 0; | ||
1483 | cam->frame_count = 0; | ||
1484 | |||
1485 | /*** start create system buffers ***/ | ||
1486 | for (i = 0; i < FRAMES; i++) { | ||
1487 | /* always allocate maximum size for system buffers */ | ||
1488 | cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE); | ||
1489 | |||
1490 | DBG("valloc %p, idx %lu, pdata %p\n", | ||
1491 | &cam->buffer.frame[i], i, | ||
1492 | cam->buffer.frame[i].lpvbits); | ||
1493 | if (cam->buffer.frame[i].lpvbits == NULL) { | ||
1494 | printk(KERN_INFO KBUILD_MODNAME ": out of memory. " | ||
1495 | "Using less frames\n"); | ||
1496 | break; | ||
1497 | } | ||
1498 | } | ||
1499 | |||
1500 | if (i == 0) { | ||
1501 | printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n"); | ||
1502 | kfree(cam->pipe->transfer_buffer); | ||
1503 | cam->pipe->transfer_buffer = NULL; | ||
1504 | return -ENOMEM; | ||
1505 | } else | ||
1506 | cam->buffer.dwFrames = i; | ||
1507 | |||
1508 | /* make sure internal states are set */ | ||
1509 | for (i = 0; i < FRAMES; i++) { | ||
1510 | cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE; | ||
1511 | cam->buffer.frame[i].cur_size = 0; | ||
1512 | } | ||
1513 | |||
1514 | cam->cur_frame = 0; | ||
1515 | cam->last_frame = -1; | ||
1516 | /*** end create system buffers ***/ | ||
1517 | |||
1518 | /* start read pipe */ | ||
1519 | zr364xx_start_readpipe(cam); | ||
1520 | DBG(": board initialized\n"); | ||
1521 | return 0; | ||
1522 | } | ||
786 | 1523 | ||
787 | static int zr364xx_probe(struct usb_interface *intf, | 1524 | static int zr364xx_probe(struct usb_interface *intf, |
788 | const struct usb_device_id *id) | 1525 | const struct usb_device_id *id) |
789 | { | 1526 | { |
790 | struct usb_device *udev = interface_to_usbdev(intf); | 1527 | struct usb_device *udev = interface_to_usbdev(intf); |
791 | struct zr364xx_camera *cam = NULL; | 1528 | struct zr364xx_camera *cam = NULL; |
1529 | struct usb_host_interface *iface_desc; | ||
1530 | struct usb_endpoint_descriptor *endpoint; | ||
792 | int err; | 1531 | int err; |
1532 | int i; | ||
793 | 1533 | ||
794 | DBG("probing..."); | 1534 | DBG("probing...\n"); |
795 | 1535 | ||
796 | dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n"); | 1536 | dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n"); |
797 | dev_info(&intf->dev, "model %04x:%04x detected\n", | 1537 | dev_info(&intf->dev, "model %04x:%04x detected\n", |
@@ -810,22 +1550,17 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
810 | if (cam->vdev == NULL) { | 1550 | if (cam->vdev == NULL) { |
811 | dev_err(&udev->dev, "cam->vdev: out of memory !\n"); | 1551 | dev_err(&udev->dev, "cam->vdev: out of memory !\n"); |
812 | kfree(cam); | 1552 | kfree(cam); |
1553 | cam = NULL; | ||
813 | return -ENOMEM; | 1554 | return -ENOMEM; |
814 | } | 1555 | } |
815 | memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template)); | 1556 | memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template)); |
1557 | cam->vdev->parent = &intf->dev; | ||
816 | video_set_drvdata(cam->vdev, cam); | 1558 | video_set_drvdata(cam->vdev, cam); |
817 | if (debug) | 1559 | if (debug) |
818 | cam->vdev->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; | 1560 | cam->vdev->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; |
819 | 1561 | ||
820 | cam->udev = udev; | 1562 | cam->udev = udev; |
821 | 1563 | ||
822 | if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) { | ||
823 | dev_info(&udev->dev, "cam->buffer: out of memory !\n"); | ||
824 | video_device_release(cam->vdev); | ||
825 | kfree(cam); | ||
826 | return -ENODEV; | ||
827 | } | ||
828 | |||
829 | switch (mode) { | 1564 | switch (mode) { |
830 | case 1: | 1565 | case 1: |
831 | dev_info(&udev->dev, "160x120 mode selected\n"); | 1566 | dev_info(&udev->dev, "160x120 mode selected\n"); |
@@ -852,21 +1587,53 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
852 | header2[439] = cam->width / 256; | 1587 | header2[439] = cam->width / 256; |
853 | header2[440] = cam->width % 256; | 1588 | header2[440] = cam->width % 256; |
854 | 1589 | ||
1590 | cam->users = 0; | ||
855 | cam->nb = 0; | 1591 | cam->nb = 0; |
856 | cam->brightness = 64; | 1592 | cam->mode.brightness = 64; |
857 | mutex_init(&cam->lock); | 1593 | mutex_init(&cam->lock); |
1594 | mutex_init(&cam->open_lock); | ||
1595 | |||
1596 | DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf); | ||
1597 | |||
1598 | /* set up the endpoint information */ | ||
1599 | iface_desc = intf->cur_altsetting; | ||
1600 | DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints); | ||
1601 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
1602 | endpoint = &iface_desc->endpoint[i].desc; | ||
1603 | if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) { | ||
1604 | /* we found the bulk in endpoint */ | ||
1605 | cam->read_endpoint = endpoint->bEndpointAddress; | ||
1606 | } | ||
1607 | } | ||
1608 | |||
1609 | if (!cam->read_endpoint) { | ||
1610 | dev_err(&intf->dev, "Could not find bulk-in endpoint\n"); | ||
1611 | return -ENOMEM; | ||
1612 | } | ||
858 | 1613 | ||
1614 | /* v4l */ | ||
1615 | INIT_LIST_HEAD(&cam->vidq.active); | ||
1616 | cam->vidq.cam = cam; | ||
859 | err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); | 1617 | err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); |
860 | if (err) { | 1618 | if (err) { |
861 | dev_err(&udev->dev, "video_register_device failed\n"); | 1619 | dev_err(&udev->dev, "video_register_device failed\n"); |
862 | video_device_release(cam->vdev); | 1620 | video_device_release(cam->vdev); |
863 | kfree(cam->buffer); | ||
864 | kfree(cam); | 1621 | kfree(cam); |
1622 | cam = NULL; | ||
865 | return err; | 1623 | return err; |
866 | } | 1624 | } |
867 | 1625 | ||
868 | usb_set_intfdata(intf, cam); | 1626 | usb_set_intfdata(intf, cam); |
869 | 1627 | ||
1628 | /* load zr364xx board specific */ | ||
1629 | err = zr364xx_board_init(cam); | ||
1630 | if (err) { | ||
1631 | spin_lock_init(&cam->slock); | ||
1632 | return err; | ||
1633 | } | ||
1634 | |||
1635 | spin_lock_init(&cam->slock); | ||
1636 | |||
870 | dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n", | 1637 | dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n", |
871 | cam->vdev->num); | 1638 | cam->vdev->num); |
872 | return 0; | 1639 | return 0; |
@@ -876,17 +1643,10 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
876 | static void zr364xx_disconnect(struct usb_interface *intf) | 1643 | static void zr364xx_disconnect(struct usb_interface *intf) |
877 | { | 1644 | { |
878 | struct zr364xx_camera *cam = usb_get_intfdata(intf); | 1645 | struct zr364xx_camera *cam = usb_get_intfdata(intf); |
1646 | videobuf_mmap_free(&cam->vb_vidq); | ||
879 | usb_set_intfdata(intf, NULL); | 1647 | usb_set_intfdata(intf, NULL); |
880 | dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n"); | 1648 | dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n"); |
881 | if (cam->vdev) | 1649 | zr364xx_destroy(cam); |
882 | video_unregister_device(cam->vdev); | ||
883 | cam->vdev = NULL; | ||
884 | kfree(cam->buffer); | ||
885 | cam->buffer = NULL; | ||
886 | vfree(cam->framebuf); | ||
887 | cam->framebuf = NULL; | ||
888 | kfree(cam); | ||
889 | cam = NULL; | ||
890 | } | 1650 | } |
891 | 1651 | ||
892 | 1652 | ||