diff options
author | Lamarque Vieira Souza <lamarque@gmail.com> | 2009-07-15 19:54:55 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-12 11:17:44 -0400 |
commit | ccbf035ae5de4c535160fc99f73feb44cc55b534 (patch) | |
tree | 616ac85f09e31bfaad688dd6719a185e92eb6b81 /drivers/media/video/zr364xx.c | |
parent | a4afd65870188b872ec9b5cc0330f7c818c4c3a4 (diff) |
V4L/DVB (12278): zr364xx: implement V4L2_CAP_STREAMING
This patch implements V4L2_CAP_STREAMING for the zr364xx driver, by
converting the driver to use videobuf. This version is synced with v4l-dvb as
of 15/Jul/2009.
Tested with Creative PC-CAM 880.
It basically:
. implements V4L2_CAP_STREAMING using videobuf;
. re-implements V4L2_CAP_READWRITE using videobuf;
. copies cam->udev->product to the card field of the v4l2_capability struct.
That gives more information to the users about the webcam;
. moves the brightness setting code from before requesting a frame (in
read_frame) to the vidioc_s_ctrl ioctl. This way the brightness code is
executed only when the application requests a change in brightness and
not before every frame read;
. comments part of zr364xx_vidioc_try_fmt_vid_cap that says that Skype +
libv4l do not work.
This patch fixes zr364xx for applications such as mplayer,
Kopete+libv4l and Skype+libv4l can make use of the webcam that comes
with zr364xx chip.
Signed-off-by: Lamarque V. Souza <lamarque@gmail.com>
Signed-off-by: Antoine Jacquet <royale@zerezo.com>
[mchehab@redhat.com: fix the lack of linux/version.h]
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/zr364xx.c')
-rw-r--r-- | drivers/media/video/zr364xx.c | 1166 |
1 files changed, 939 insertions, 227 deletions
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 2622a6e63da1..aba908151b62 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,33 @@ | |||
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 ZR364_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 100000 |
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) | ||
56 | 68 | ||
57 | /* Init methods, need to find nicer names for these | 69 | /* Init methods, need to find nicer names for these |
58 | * the exact names of the chipsets would be the best if someone finds it */ | 70 | * the exact names of the chipsets would be the best if someone finds it */ |
@@ -101,24 +113,93 @@ static struct usb_device_id device_table[] = { | |||
101 | 113 | ||
102 | MODULE_DEVICE_TABLE(usb, device_table); | 114 | MODULE_DEVICE_TABLE(usb, device_table); |
103 | 115 | ||
116 | struct zr364xx_mode { | ||
117 | u32 color; /* output video color format */ | ||
118 | u32 brightness; /* brightness */ | ||
119 | }; | ||
120 | |||
121 | /* frame structure */ | ||
122 | struct zr364xx_framei { | ||
123 | unsigned long ulState; /* ulState:ZR364XX_READ_IDLE, | ||
124 | ZR364XX_READ_FRAME */ | ||
125 | void *lpvbits; /* image data */ | ||
126 | unsigned long cur_size; /* current data copied to it */ | ||
127 | }; | ||
128 | |||
129 | /* image buffer structure */ | ||
130 | struct zr364xx_bufferi { | ||
131 | unsigned long dwFrames; /* number of frames in buffer */ | ||
132 | struct zr364xx_framei frame[FRAMES]; /* array of FRAME structures */ | ||
133 | }; | ||
134 | |||
135 | struct zr364xx_dmaqueue { | ||
136 | struct list_head active; | ||
137 | struct zr364xx_camera *cam; | ||
138 | }; | ||
139 | |||
140 | struct zr364xx_pipeinfo { | ||
141 | u32 transfer_size; | ||
142 | u8 *transfer_buffer; | ||
143 | u32 state; | ||
144 | void *stream_urb; | ||
145 | void *cam; /* back pointer to zr364xx_camera struct */ | ||
146 | u32 err_count; | ||
147 | u32 idx; | ||
148 | }; | ||
149 | |||
150 | struct zr364xx_fmt { | ||
151 | char *name; | ||
152 | u32 fourcc; | ||
153 | int depth; | ||
154 | }; | ||
155 | |||
156 | /* image formats. */ | ||
157 | static const struct zr364xx_fmt formats[] = { | ||
158 | { | ||
159 | .name = "JPG", | ||
160 | .fourcc = V4L2_PIX_FMT_JPEG, | ||
161 | .depth = 24 | ||
162 | } | ||
163 | }; | ||
104 | 164 | ||
105 | /* Camera stuff */ | 165 | /* Camera stuff */ |
106 | struct zr364xx_camera { | 166 | struct zr364xx_camera { |
107 | struct usb_device *udev; /* save off the usb device pointer */ | 167 | struct usb_device *udev; /* save off the usb device pointer */ |
108 | struct usb_interface *interface;/* the interface for this device */ | 168 | struct usb_interface *interface;/* the interface for this device */ |
109 | struct video_device *vdev; /* v4l video device */ | 169 | struct video_device *vdev; /* v4l video device */ |
110 | u8 *framebuf; | ||
111 | int nb; | 170 | int nb; |
112 | unsigned char *buffer; | 171 | struct zr364xx_bufferi buffer; |
113 | int skip; | 172 | int skip; |
114 | int brightness; | ||
115 | int width; | 173 | int width; |
116 | int height; | 174 | int height; |
117 | int method; | 175 | int method; |
118 | struct mutex lock; | 176 | struct mutex lock; |
177 | struct mutex open_lock; | ||
119 | int users; | 178 | int users; |
179 | |||
180 | spinlock_t slock; | ||
181 | struct zr364xx_dmaqueue vidq; | ||
182 | int resources; | ||
183 | int last_frame; | ||
184 | int cur_frame; | ||
185 | unsigned long frame_count; | ||
186 | int b_acquire; | ||
187 | struct zr364xx_pipeinfo pipe[1]; | ||
188 | |||
189 | u8 read_endpoint; | ||
190 | |||
191 | const struct zr364xx_fmt *fmt; | ||
192 | struct videobuf_queue vb_vidq; | ||
193 | enum v4l2_buf_type type; | ||
194 | struct zr364xx_mode mode; | ||
120 | }; | 195 | }; |
121 | 196 | ||
197 | /* buffer for one video frame */ | ||
198 | struct zr364xx_buffer { | ||
199 | /* common v4l buffer stuff -- must be first */ | ||
200 | struct videobuf_buffer vb; | ||
201 | const struct zr364xx_fmt *fmt; | ||
202 | }; | ||
122 | 203 | ||
123 | /* function used to send initialisation commands to the camera */ | 204 | /* function used to send initialisation commands to the camera */ |
124 | static int send_control_msg(struct usb_device *udev, u8 request, u16 value, | 205 | static int send_control_msg(struct usb_device *udev, u8 request, u16 value, |
@@ -272,139 +353,116 @@ static unsigned char header2[] = { | |||
272 | }; | 353 | }; |
273 | static unsigned char header3; | 354 | static unsigned char header3; |
274 | 355 | ||
356 | /* ------------------------------------------------------------------ | ||
357 | Videobuf operations | ||
358 | ------------------------------------------------------------------*/ | ||
275 | 359 | ||
360 | static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, | ||
361 | unsigned int *size) | ||
362 | { | ||
363 | struct zr364xx_camera *cam = vq->priv_data; | ||
276 | 364 | ||
277 | /********************/ | 365 | *size = cam->width * cam->height * (cam->fmt->depth >> 3); |
278 | /* V4L2 integration */ | ||
279 | /********************/ | ||
280 | 366 | ||
281 | /* this function reads a full JPEG picture synchronously | 367 | if (*count == 0) |
282 | * TODO: do it asynchronously... */ | 368 | *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 | 369 | ||
316 | /* swap bytes if camera needs it */ | 370 | while (*size * (*count) > ZR364XX_DEF_BUFS * 1024 * 1024) |
317 | if (cam->method == METHOD0) { | 371 | (*count)--; |
318 | u16 *buf = (u16*)cam->buffer; | ||
319 | for (i = 0; i < BUFFER_SIZE/2; i++) | ||
320 | swab16s(buf + i); | ||
321 | } | ||
322 | 372 | ||
323 | /* write the JPEG header */ | 373 | return 0; |
324 | if (!head) { | 374 | } |
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 | 375 | ||
357 | /* we skip the 2 first frames which are usually buggy */ | 376 | static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf) |
358 | if (cam->skip) { | 377 | { |
359 | cam->skip--; | 378 | DBG("%s\n", __func__); |
360 | goto redo; | ||
361 | } | ||
362 | 379 | ||
363 | /* go back to find the JPEG EOI marker */ | 380 | if (in_interrupt()) |
364 | size = ptr - jpeg; | 381 | 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 | 382 | ||
375 | /* Sometimes there is junk data in the middle of the picture, | 383 | videobuf_vmalloc_free(&buf->vb); |
376 | * we want to skip this bogus frames */ | 384 | buf->vb.state = VIDEOBUF_NEEDS_INIT; |
377 | while (ptr > jpeg) { | 385 | } |
378 | if (*ptr == 0xFF && *(ptr + 1) == 0xFF | 386 | |
379 | && *(ptr + 2) == 0xFF) | 387 | static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, |
380 | break; | 388 | enum v4l2_field field) |
381 | ptr--; | 389 | { |
390 | struct zr364xx_camera *cam = vq->priv_data; | ||
391 | struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer, | ||
392 | vb); | ||
393 | int rc; | ||
394 | |||
395 | DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ? | ||
396 | cam->fmt->name : ""); | ||
397 | if (cam->fmt == NULL) | ||
398 | return -EINVAL; | ||
399 | |||
400 | buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3); | ||
401 | |||
402 | if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) { | ||
403 | DBG("invalid buffer prepare\n"); | ||
404 | return -EINVAL; | ||
382 | } | 405 | } |
383 | if (ptr != jpeg) { | 406 | |
384 | DBG("Bogus frame ? %d", cam->nb); | 407 | buf->fmt = cam->fmt; |
385 | goto redo; | 408 | buf->vb.width = cam->width; |
409 | buf->vb.height = cam->height; | ||
410 | buf->vb.field = field; | ||
411 | |||
412 | if (buf->vb.state == VIDEOBUF_NEEDS_INIT) { | ||
413 | rc = videobuf_iolock(vq, &buf->vb, NULL); | ||
414 | if (rc < 0) | ||
415 | goto fail; | ||
386 | } | 416 | } |
387 | 417 | ||
388 | DBG("jpeg : %d %d %d %d %d %d %d %d", | 418 | buf->vb.state = VIDEOBUF_PREPARED; |
389 | jpeg[0], jpeg[1], jpeg[2], jpeg[3], | 419 | return 0; |
390 | jpeg[4], jpeg[5], jpeg[6], jpeg[7]); | 420 | fail: |
421 | free_buffer(vq, buf); | ||
422 | return rc; | ||
423 | } | ||
424 | |||
425 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
426 | { | ||
427 | struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer, | ||
428 | vb); | ||
429 | struct zr364xx_camera *cam = vq->priv_data; | ||
430 | |||
431 | DBG("%s\n", __func__); | ||
391 | 432 | ||
392 | return size; | 433 | buf->vb.state = VIDEOBUF_QUEUED; |
434 | list_add_tail(&buf->vb.queue, &cam->vidq.active); | ||
393 | } | 435 | } |
394 | 436 | ||
437 | static void buffer_release(struct videobuf_queue *vq, | ||
438 | struct videobuf_buffer *vb) | ||
439 | { | ||
440 | struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer, | ||
441 | vb); | ||
442 | |||
443 | DBG("%s\n", __func__); | ||
444 | free_buffer(vq, buf); | ||
445 | } | ||
446 | |||
447 | static struct videobuf_queue_ops zr364xx_video_qops = { | ||
448 | .buf_setup = buffer_setup, | ||
449 | .buf_prepare = buffer_prepare, | ||
450 | .buf_queue = buffer_queue, | ||
451 | .buf_release = buffer_release, | ||
452 | }; | ||
453 | |||
454 | /********************/ | ||
455 | /* V4L2 integration */ | ||
456 | /********************/ | ||
457 | static int zr364xx_vidioc_streamon(struct file *file, void *priv, | ||
458 | enum v4l2_buf_type type); | ||
395 | 459 | ||
396 | static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t cnt, | 460 | static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count, |
397 | loff_t * ppos) | 461 | loff_t * ppos) |
398 | { | 462 | { |
399 | unsigned long count = cnt; | 463 | struct zr364xx_camera *cam = video_drvdata(file); |
400 | struct video_device *vdev = video_devdata(file); | ||
401 | struct zr364xx_camera *cam; | ||
402 | 464 | ||
403 | DBG("zr364xx_read: read %d bytes.", (int) count); | 465 | DBG("%s\n", __func__); |
404 | |||
405 | if (vdev == NULL) | ||
406 | return -ENODEV; | ||
407 | cam = video_get_drvdata(vdev); | ||
408 | 466 | ||
409 | if (!buf) | 467 | if (!buf) |
410 | return -EINVAL; | 468 | return -EINVAL; |
@@ -412,21 +470,275 @@ static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t cnt, | |||
412 | if (!count) | 470 | if (!count) |
413 | return -EINVAL; | 471 | return -EINVAL; |
414 | 472 | ||
415 | /* NoMan Sux ! */ | 473 | if (cam->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && |
416 | count = read_frame(cam, 0); | 474 | zr364xx_vidioc_streamon(file, cam, cam->type) == 0) { |
475 | DBG("%s: reading %d bytes at pos %d.\n", __func__, (int) count, | ||
476 | (int) *ppos); | ||
477 | |||
478 | /* NoMan Sux ! */ | ||
479 | return videobuf_read_one(&cam->vb_vidq, buf, count, ppos, | ||
480 | file->f_flags & O_NONBLOCK); | ||
481 | } | ||
482 | |||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | /* video buffer vmalloc implementation based partly on VIVI driver which is | ||
487 | * Copyright (c) 2006 by | ||
488 | * Mauro Carvalho Chehab <mchehab--a.t--infradead.org> | ||
489 | * Ted Walther <ted--a.t--enumera.com> | ||
490 | * John Sokol <sokol--a.t--videotechnology.com> | ||
491 | * http://v4l.videotechnology.com/ | ||
492 | * | ||
493 | */ | ||
494 | static void zr364xx_fillbuff(struct zr364xx_camera *cam, | ||
495 | struct zr364xx_buffer *buf, | ||
496 | int jpgsize) | ||
497 | { | ||
498 | int pos = 0; | ||
499 | struct timeval ts; | ||
500 | const char *tmpbuf; | ||
501 | char *vbuf = videobuf_to_vmalloc(&buf->vb); | ||
502 | unsigned long last_frame; | ||
503 | struct zr364xx_framei *frm; | ||
504 | |||
505 | if (!vbuf) | ||
506 | return; | ||
507 | |||
508 | last_frame = cam->last_frame; | ||
509 | if (last_frame != -1) { | ||
510 | frm = &cam->buffer.frame[last_frame]; | ||
511 | tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits; | ||
512 | switch (buf->fmt->fourcc) { | ||
513 | case V4L2_PIX_FMT_JPEG: | ||
514 | buf->vb.size = jpgsize; | ||
515 | memcpy(vbuf, tmpbuf, buf->vb.size); | ||
516 | break; | ||
517 | default: | ||
518 | printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n"); | ||
519 | } | ||
520 | cam->last_frame = -1; | ||
521 | } else { | ||
522 | printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n"); | ||
523 | return; | ||
524 | } | ||
525 | DBG("%s: Buffer 0x%08lx size= %d\n", __func__, | ||
526 | (unsigned long)vbuf, pos); | ||
527 | /* tell v4l buffer was filled */ | ||
528 | |||
529 | buf->vb.field_count = cam->frame_count * 2; | ||
530 | do_gettimeofday(&ts); | ||
531 | buf->vb.ts = ts; | ||
532 | buf->vb.state = VIDEOBUF_DONE; | ||
533 | } | ||
534 | |||
535 | static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize) | ||
536 | { | ||
537 | struct zr364xx_dmaqueue *dma_q = &cam->vidq; | ||
538 | struct zr364xx_buffer *buf; | ||
539 | unsigned long flags = 0; | ||
540 | int rc = 0; | ||
541 | |||
542 | DBG("wakeup: %p\n", &dma_q); | ||
543 | spin_lock_irqsave(&cam->slock, flags); | ||
544 | |||
545 | if (list_empty(&dma_q->active)) { | ||
546 | DBG("No active queue to serve\n"); | ||
547 | rc = -1; | ||
548 | goto unlock; | ||
549 | } | ||
550 | buf = list_entry(dma_q->active.next, | ||
551 | struct zr364xx_buffer, vb.queue); | ||
552 | |||
553 | if (!waitqueue_active(&buf->vb.done)) { | ||
554 | /* no one active */ | ||
555 | rc = -1; | ||
556 | goto unlock; | ||
557 | } | ||
558 | list_del(&buf->vb.queue); | ||
559 | do_gettimeofday(&buf->vb.ts); | ||
560 | DBG("[%p/%d] wakeup\n", buf, buf->vb.i); | ||
561 | zr364xx_fillbuff(cam, buf, jpgsize); | ||
562 | wake_up(&buf->vb.done); | ||
563 | DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i); | ||
564 | unlock: | ||
565 | spin_unlock_irqrestore(&cam->slock, flags); | ||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | /* this function moves the usb stream read pipe data | ||
570 | * into the system buffers. | ||
571 | * returns 0 on success, EAGAIN if more data to process (call this | ||
572 | * function again). | ||
573 | */ | ||
574 | static int zr364xx_read_video_callback(struct zr364xx_camera *cam, | ||
575 | struct zr364xx_pipeinfo *pipe_info, | ||
576 | struct urb *purb) | ||
577 | { | ||
578 | unsigned char *pdest; | ||
579 | unsigned char *psrc; | ||
580 | s32 idx = -1; | ||
581 | struct zr364xx_framei *frm; | ||
582 | int i = 0; | ||
583 | unsigned char *ptr = NULL; | ||
584 | |||
585 | /*DBG("buffer to user\n");*/ | ||
586 | idx = cam->cur_frame; | ||
587 | frm = &cam->buffer.frame[idx]; | ||
588 | |||
589 | /* swap bytes if camera needs it */ | ||
590 | if (cam->method == METHOD0) { | ||
591 | u16 *buf = (u16 *)pipe_info->transfer_buffer; | ||
592 | for (i = 0; i < purb->actual_length/2; i++) | ||
593 | swab16s(buf + i); | ||
594 | } | ||
595 | |||
596 | /* search done. now find out if should be acquiring */ | ||
597 | if (!cam->b_acquire) { | ||
598 | /* we found a frame, but this channel is turned off */ | ||
599 | frm->ulState = ZR364XX_READ_IDLE; | ||
600 | return -EINVAL; | ||
601 | } | ||
602 | |||
603 | if (frm->lpvbits == NULL) { | ||
604 | DBG("%s: frame buffer == NULL.%p %p %d\n", __func__, | ||
605 | frm, cam, idx); | ||
606 | return -ENOMEM; | ||
607 | } | ||
417 | 608 | ||
418 | if (copy_to_user(buf, cam->framebuf, count)) | 609 | psrc = (u8 *)pipe_info->transfer_buffer; |
419 | return -EFAULT; | 610 | ptr = pdest = frm->lpvbits; |
611 | |||
612 | if (frm->ulState == ZR364XX_READ_IDLE) { | ||
613 | frm->ulState = ZR364XX_READ_FRAME; | ||
614 | frm->cur_size = 0; | ||
615 | |||
616 | DBG("jpeg header, "); | ||
617 | memcpy(ptr, header1, sizeof(header1)); | ||
618 | ptr += sizeof(header1); | ||
619 | header3 = 0; | ||
620 | memcpy(ptr, &header3, 1); | ||
621 | ptr++; | ||
622 | memcpy(ptr, psrc, 64); | ||
623 | ptr += 64; | ||
624 | header3 = 1; | ||
625 | memcpy(ptr, &header3, 1); | ||
626 | ptr++; | ||
627 | memcpy(ptr, psrc + 64, 64); | ||
628 | ptr += 64; | ||
629 | memcpy(ptr, header2, sizeof(header2)); | ||
630 | ptr += sizeof(header2); | ||
631 | memcpy(ptr, psrc + 128, | ||
632 | purb->actual_length - 128); | ||
633 | ptr += purb->actual_length - 128; | ||
634 | DBG("header : %d %d %d %d %d %d %d %d %d\n", | ||
635 | psrc[0], psrc[1], psrc[2], | ||
636 | psrc[3], psrc[4], psrc[5], | ||
637 | psrc[6], psrc[7], psrc[8]); | ||
638 | frm->cur_size = ptr - pdest; | ||
639 | } else { | ||
640 | pdest += frm->cur_size; | ||
641 | memcpy(pdest, psrc, purb->actual_length); | ||
642 | frm->cur_size += purb->actual_length; | ||
643 | } | ||
644 | /*DBG("cur_size %lu urb size %d\n", frm->cur_size, | ||
645 | purb->actual_length);*/ | ||
646 | |||
647 | if (purb->actual_length < pipe_info->transfer_size) { | ||
648 | DBG("****************Buffer[%d]full*************\n", idx); | ||
649 | cam->last_frame = cam->cur_frame; | ||
650 | cam->cur_frame++; | ||
651 | /* end of system frame ring buffer, start at zero */ | ||
652 | if (cam->cur_frame == cam->buffer.dwFrames) | ||
653 | cam->cur_frame = 0; | ||
654 | |||
655 | /* frame ready */ | ||
656 | /* go back to find the JPEG EOI marker */ | ||
657 | ptr = pdest = frm->lpvbits; | ||
658 | ptr += frm->cur_size - 2; | ||
659 | while (ptr > pdest) { | ||
660 | if (*ptr == 0xFF && *(ptr + 1) == 0xD9 | ||
661 | && *(ptr + 2) == 0xFF) | ||
662 | break; | ||
663 | ptr--; | ||
664 | } | ||
665 | if (ptr == pdest) | ||
666 | DBG("No EOI marker\n"); | ||
667 | |||
668 | /* Sometimes there is junk data in the middle of the picture, | ||
669 | * we want to skip this bogus frames */ | ||
670 | while (ptr > pdest) { | ||
671 | if (*ptr == 0xFF && *(ptr + 1) == 0xFF | ||
672 | && *(ptr + 2) == 0xFF) | ||
673 | break; | ||
674 | ptr--; | ||
675 | } | ||
676 | if (ptr != pdest) { | ||
677 | DBG("Bogus frame ? %d\n", ++(cam->nb)); | ||
678 | } else if (cam->b_acquire) { | ||
679 | /* we skip the 2 first frames which are usually buggy */ | ||
680 | if (cam->skip) | ||
681 | cam->skip--; | ||
682 | else { | ||
683 | DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n", | ||
684 | frm->cur_size, | ||
685 | pdest[0], pdest[1], pdest[2], pdest[3], | ||
686 | pdest[4], pdest[5], pdest[6], pdest[7]); | ||
687 | |||
688 | zr364xx_got_frame(cam, frm->cur_size); | ||
689 | } | ||
690 | } | ||
691 | cam->frame_count++; | ||
692 | frm->ulState = ZR364XX_READ_IDLE; | ||
693 | frm->cur_size = 0; | ||
694 | } | ||
695 | /* done successfully */ | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | static int res_get(struct zr364xx_camera *cam) | ||
700 | { | ||
701 | /* is it free? */ | ||
702 | mutex_lock(&cam->lock); | ||
703 | if (cam->resources) { | ||
704 | /* no, someone else uses it */ | ||
705 | mutex_unlock(&cam->lock); | ||
706 | return 0; | ||
707 | } | ||
708 | /* it's free, grab it */ | ||
709 | cam->resources = 1; | ||
710 | DBG("res: get\n"); | ||
711 | mutex_unlock(&cam->lock); | ||
712 | return 1; | ||
713 | } | ||
420 | 714 | ||
421 | return count; | 715 | static inline int res_check(struct zr364xx_camera *cam) |
716 | { | ||
717 | return cam->resources; | ||
422 | } | 718 | } |
423 | 719 | ||
720 | static void res_free(struct zr364xx_camera *cam) | ||
721 | { | ||
722 | mutex_lock(&cam->lock); | ||
723 | cam->resources = 0; | ||
724 | mutex_unlock(&cam->lock); | ||
725 | DBG("res: put\n"); | ||
726 | } | ||
424 | 727 | ||
425 | static int zr364xx_vidioc_querycap(struct file *file, void *priv, | 728 | static int zr364xx_vidioc_querycap(struct file *file, void *priv, |
426 | struct v4l2_capability *cap) | 729 | struct v4l2_capability *cap) |
427 | { | 730 | { |
428 | strcpy(cap->driver, DRIVER_DESC); | 731 | struct zr364xx_camera *cam = video_drvdata(file); |
429 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; | 732 | |
733 | strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver)); | ||
734 | strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); | ||
735 | strlcpy(cap->bus_info, dev_name(&cam->udev->dev), | ||
736 | sizeof(cap->bus_info)); | ||
737 | cap->version = ZR364_VERSION_CODE; | ||
738 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
739 | V4L2_CAP_READWRITE | | ||
740 | V4L2_CAP_STREAMING; | ||
741 | |||
430 | return 0; | 742 | return 0; |
431 | } | 743 | } |
432 | 744 | ||
@@ -458,12 +770,11 @@ static int zr364xx_vidioc_s_input(struct file *file, void *priv, | |||
458 | static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, | 770 | static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, |
459 | struct v4l2_queryctrl *c) | 771 | struct v4l2_queryctrl *c) |
460 | { | 772 | { |
461 | struct video_device *vdev = video_devdata(file); | ||
462 | struct zr364xx_camera *cam; | 773 | struct zr364xx_camera *cam; |
463 | 774 | ||
464 | if (vdev == NULL) | 775 | if (file == NULL) |
465 | return -ENODEV; | 776 | return -ENODEV; |
466 | cam = video_get_drvdata(vdev); | 777 | cam = video_drvdata(file); |
467 | 778 | ||
468 | switch (c->id) { | 779 | switch (c->id) { |
469 | case V4L2_CID_BRIGHTNESS: | 780 | case V4L2_CID_BRIGHTNESS: |
@@ -472,7 +783,7 @@ static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, | |||
472 | c->minimum = 0; | 783 | c->minimum = 0; |
473 | c->maximum = 127; | 784 | c->maximum = 127; |
474 | c->step = 1; | 785 | c->step = 1; |
475 | c->default_value = cam->brightness; | 786 | c->default_value = cam->mode.brightness; |
476 | c->flags = 0; | 787 | c->flags = 0; |
477 | break; | 788 | break; |
478 | default: | 789 | default: |
@@ -484,36 +795,42 @@ static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, | |||
484 | static int zr364xx_vidioc_s_ctrl(struct file *file, void *priv, | 795 | static int zr364xx_vidioc_s_ctrl(struct file *file, void *priv, |
485 | struct v4l2_control *c) | 796 | struct v4l2_control *c) |
486 | { | 797 | { |
487 | struct video_device *vdev = video_devdata(file); | ||
488 | struct zr364xx_camera *cam; | 798 | struct zr364xx_camera *cam; |
799 | int temp; | ||
489 | 800 | ||
490 | if (vdev == NULL) | 801 | if (file == NULL) |
491 | return -ENODEV; | 802 | return -ENODEV; |
492 | cam = video_get_drvdata(vdev); | 803 | cam = video_drvdata(file); |
493 | 804 | ||
494 | switch (c->id) { | 805 | switch (c->id) { |
495 | case V4L2_CID_BRIGHTNESS: | 806 | case V4L2_CID_BRIGHTNESS: |
496 | cam->brightness = c->value; | 807 | cam->mode.brightness = c->value; |
808 | /* hardware brightness */ | ||
809 | mutex_lock(&cam->lock); | ||
810 | send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0); | ||
811 | temp = (0x60 << 8) + 127 - cam->mode.brightness; | ||
812 | send_control_msg(cam->udev, 1, temp, 0, NULL, 0); | ||
813 | mutex_unlock(&cam->lock); | ||
497 | break; | 814 | break; |
498 | default: | 815 | default: |
499 | return -EINVAL; | 816 | return -EINVAL; |
500 | } | 817 | } |
818 | |||
501 | return 0; | 819 | return 0; |
502 | } | 820 | } |
503 | 821 | ||
504 | static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv, | 822 | static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv, |
505 | struct v4l2_control *c) | 823 | struct v4l2_control *c) |
506 | { | 824 | { |
507 | struct video_device *vdev = video_devdata(file); | ||
508 | struct zr364xx_camera *cam; | 825 | struct zr364xx_camera *cam; |
509 | 826 | ||
510 | if (vdev == NULL) | 827 | if (file == NULL) |
511 | return -ENODEV; | 828 | return -ENODEV; |
512 | cam = video_get_drvdata(vdev); | 829 | cam = video_drvdata(file); |
513 | 830 | ||
514 | switch (c->id) { | 831 | switch (c->id) { |
515 | case V4L2_CID_BRIGHTNESS: | 832 | case V4L2_CID_BRIGHTNESS: |
516 | c->value = cam->brightness; | 833 | c->value = cam->mode.brightness; |
517 | break; | 834 | break; |
518 | default: | 835 | default: |
519 | return -EINVAL; | 836 | return -EINVAL; |
@@ -527,26 +844,36 @@ static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file, | |||
527 | if (f->index > 0) | 844 | if (f->index > 0) |
528 | return -EINVAL; | 845 | return -EINVAL; |
529 | f->flags = V4L2_FMT_FLAG_COMPRESSED; | 846 | f->flags = V4L2_FMT_FLAG_COMPRESSED; |
530 | strcpy(f->description, "JPEG"); | 847 | strcpy(f->description, formats[0].name); |
531 | f->pixelformat = V4L2_PIX_FMT_JPEG; | 848 | f->pixelformat = formats[0].fourcc; |
532 | return 0; | 849 | return 0; |
533 | } | 850 | } |
534 | 851 | ||
852 | static char *decode_fourcc(__u32 pixelformat, char *buf) | ||
853 | { | ||
854 | buf[0] = pixelformat & 0xff; | ||
855 | buf[1] = (pixelformat >> 8) & 0xff; | ||
856 | buf[2] = (pixelformat >> 16) & 0xff; | ||
857 | buf[3] = (pixelformat >> 24) & 0xff; | ||
858 | buf[4] = '\0'; | ||
859 | return buf; | ||
860 | } | ||
861 | |||
535 | static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, | 862 | static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
536 | struct v4l2_format *f) | 863 | struct v4l2_format *f) |
537 | { | 864 | { |
538 | struct video_device *vdev = video_devdata(file); | 865 | struct zr364xx_camera *cam = video_drvdata(file); |
539 | struct zr364xx_camera *cam; | 866 | char pixelformat_name[5]; |
540 | 867 | ||
541 | if (vdev == NULL) | 868 | if (cam == NULL) |
542 | return -ENODEV; | 869 | return -ENODEV; |
543 | cam = video_get_drvdata(vdev); | ||
544 | 870 | ||
545 | if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) | 871 | if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) { |
546 | return -EINVAL; | 872 | DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__, |
547 | if (f->fmt.pix.field != V4L2_FIELD_ANY && | 873 | decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name)); |
548 | f->fmt.pix.field != V4L2_FIELD_NONE) | ||
549 | return -EINVAL; | 874 | return -EINVAL; |
875 | } | ||
876 | |||
550 | f->fmt.pix.field = V4L2_FIELD_NONE; | 877 | f->fmt.pix.field = V4L2_FIELD_NONE; |
551 | f->fmt.pix.width = cam->width; | 878 | f->fmt.pix.width = cam->width; |
552 | f->fmt.pix.height = cam->height; | 879 | f->fmt.pix.height = cam->height; |
@@ -554,20 +881,22 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
554 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 881 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
555 | f->fmt.pix.colorspace = 0; | 882 | f->fmt.pix.colorspace = 0; |
556 | f->fmt.pix.priv = 0; | 883 | f->fmt.pix.priv = 0; |
884 | DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__, | ||
885 | decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name), | ||
886 | f->fmt.pix.field); | ||
557 | return 0; | 887 | return 0; |
558 | } | 888 | } |
559 | 889 | ||
560 | static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, | 890 | static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
561 | struct v4l2_format *f) | 891 | struct v4l2_format *f) |
562 | { | 892 | { |
563 | struct video_device *vdev = video_devdata(file); | ||
564 | struct zr364xx_camera *cam; | 893 | struct zr364xx_camera *cam; |
565 | 894 | ||
566 | if (vdev == NULL) | 895 | if (file == NULL) |
567 | return -ENODEV; | 896 | return -ENODEV; |
568 | cam = video_get_drvdata(vdev); | 897 | cam = video_drvdata(file); |
569 | 898 | ||
570 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; | 899 | f->fmt.pix.pixelformat = formats[0].fourcc; |
571 | f->fmt.pix.field = V4L2_FIELD_NONE; | 900 | f->fmt.pix.field = V4L2_FIELD_NONE; |
572 | f->fmt.pix.width = cam->width; | 901 | f->fmt.pix.width = cam->width; |
573 | f->fmt.pix.height = cam->height; | 902 | f->fmt.pix.height = cam->height; |
@@ -578,21 +907,26 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
578 | return 0; | 907 | return 0; |
579 | } | 908 | } |
580 | 909 | ||
910 | /* Lamarque TODO: implement changing resolution on the fly */ | ||
581 | static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 911 | static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
582 | struct v4l2_format *f) | 912 | struct v4l2_format *f) |
583 | { | 913 | { |
584 | struct video_device *vdev = video_devdata(file); | 914 | struct zr364xx_camera *cam = video_drvdata(file); |
585 | struct zr364xx_camera *cam; | 915 | struct videobuf_queue *q = &cam->vb_vidq; |
916 | char pixelformat_name[5]; | ||
917 | int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f); | ||
586 | 918 | ||
587 | if (vdev == NULL) | 919 | if (ret < 0) |
588 | return -ENODEV; | 920 | return ret; |
589 | cam = video_get_drvdata(vdev); | 921 | |
922 | mutex_lock(&q->vb_lock); | ||
923 | |||
924 | if (videobuf_queue_is_busy(&cam->vb_vidq)) { | ||
925 | DBG("%s queue busy\n", __func__); | ||
926 | ret = -EBUSY; | ||
927 | goto out; | ||
928 | } | ||
590 | 929 | ||
591 | if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) | ||
592 | return -EINVAL; | ||
593 | if (f->fmt.pix.field != V4L2_FIELD_ANY && | ||
594 | f->fmt.pix.field != V4L2_FIELD_NONE) | ||
595 | return -EINVAL; | ||
596 | f->fmt.pix.field = V4L2_FIELD_NONE; | 930 | f->fmt.pix.field = V4L2_FIELD_NONE; |
597 | f->fmt.pix.width = cam->width; | 931 | f->fmt.pix.width = cam->width; |
598 | f->fmt.pix.height = cam->height; | 932 | f->fmt.pix.height = cam->height; |
@@ -600,19 +934,265 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
600 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 934 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
601 | f->fmt.pix.colorspace = 0; | 935 | f->fmt.pix.colorspace = 0; |
602 | f->fmt.pix.priv = 0; | 936 | f->fmt.pix.priv = 0; |
603 | DBG("ok!"); | 937 | cam->vb_vidq.field = f->fmt.pix.field; |
938 | cam->mode.color = V4L2_PIX_FMT_JPEG; | ||
939 | ret = 0; | ||
940 | |||
941 | out: | ||
942 | mutex_unlock(&q->vb_lock); | ||
943 | |||
944 | DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__, | ||
945 | decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name), | ||
946 | f->fmt.pix.field); | ||
947 | return ret; | ||
948 | } | ||
949 | |||
950 | static int zr364xx_vidioc_reqbufs(struct file *file, void *priv, | ||
951 | struct v4l2_requestbuffers *p) | ||
952 | { | ||
953 | int rc; | ||
954 | struct zr364xx_camera *cam = video_drvdata(file); | ||
955 | rc = videobuf_reqbufs(&cam->vb_vidq, p); | ||
956 | return rc; | ||
957 | } | ||
958 | |||
959 | static int zr364xx_vidioc_querybuf(struct file *file, | ||
960 | void *priv, | ||
961 | struct v4l2_buffer *p) | ||
962 | { | ||
963 | int rc; | ||
964 | struct zr364xx_camera *cam = video_drvdata(file); | ||
965 | rc = videobuf_querybuf(&cam->vb_vidq, p); | ||
966 | return rc; | ||
967 | } | ||
968 | |||
969 | static int zr364xx_vidioc_qbuf(struct file *file, | ||
970 | void *priv, | ||
971 | struct v4l2_buffer *p) | ||
972 | { | ||
973 | int rc; | ||
974 | struct zr364xx_camera *cam = video_drvdata(file); | ||
975 | DBG("%s\n", __func__); | ||
976 | rc = videobuf_qbuf(&cam->vb_vidq, p); | ||
977 | return rc; | ||
978 | } | ||
979 | |||
980 | static int zr364xx_vidioc_dqbuf(struct file *file, | ||
981 | void *priv, | ||
982 | struct v4l2_buffer *p) | ||
983 | { | ||
984 | int rc; | ||
985 | struct zr364xx_camera *cam = video_drvdata(file); | ||
986 | DBG("%s\n", __func__); | ||
987 | rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK); | ||
988 | return rc; | ||
989 | } | ||
990 | |||
991 | static void read_pipe_completion(struct urb *purb) | ||
992 | { | ||
993 | struct zr364xx_pipeinfo *pipe_info; | ||
994 | struct zr364xx_camera *cam; | ||
995 | int pipe; | ||
996 | |||
997 | pipe_info = purb->context; | ||
998 | /*DBG("%s %p, status %d\n", __func__, purb, purb->status);*/ | ||
999 | if (pipe_info == NULL) { | ||
1000 | printk(KERN_ERR KBUILD_MODNAME ": no context!\n"); | ||
1001 | return; | ||
1002 | } | ||
1003 | |||
1004 | cam = pipe_info->cam; | ||
1005 | if (cam == NULL) { | ||
1006 | printk(KERN_ERR KBUILD_MODNAME ": no context!\n"); | ||
1007 | return; | ||
1008 | } | ||
1009 | |||
1010 | /* if shutting down, do not resubmit, exit immediately */ | ||
1011 | if (purb->status == -ESHUTDOWN) { | ||
1012 | DBG("%s, err shutdown\n", __func__); | ||
1013 | pipe_info->err_count++; | ||
1014 | return; | ||
1015 | } | ||
1016 | |||
1017 | if (pipe_info->state == 0) { | ||
1018 | DBG("exiting USB pipe\n"); | ||
1019 | return; | ||
1020 | } | ||
1021 | |||
1022 | if (purb->actual_length < 0 || | ||
1023 | purb->actual_length > pipe_info->transfer_size) { | ||
1024 | dev_err(&cam->udev->dev, "wrong number of bytes\n"); | ||
1025 | return; | ||
1026 | } | ||
1027 | |||
1028 | if (purb->status == 0) | ||
1029 | zr364xx_read_video_callback(cam, pipe_info, purb); | ||
1030 | else { | ||
1031 | pipe_info->err_count++; | ||
1032 | DBG("%s: failed URB %d\n", __func__, purb->status); | ||
1033 | } | ||
1034 | |||
1035 | pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint); | ||
1036 | |||
1037 | /* reuse urb */ | ||
1038 | usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev, | ||
1039 | pipe, | ||
1040 | pipe_info->transfer_buffer, | ||
1041 | pipe_info->transfer_size, | ||
1042 | read_pipe_completion, pipe_info); | ||
1043 | |||
1044 | if (pipe_info->state != 0) { | ||
1045 | purb->status = usb_submit_urb(pipe_info->stream_urb, | ||
1046 | GFP_ATOMIC); | ||
1047 | |||
1048 | if (purb->status) | ||
1049 | dev_err(&cam->udev->dev, | ||
1050 | "error submitting urb (error=%i)\n", | ||
1051 | purb->status); | ||
1052 | } else | ||
1053 | DBG("read pipe complete state 0\n"); | ||
1054 | } | ||
1055 | |||
1056 | static int zr364xx_start_readpipe(struct zr364xx_camera *cam) | ||
1057 | { | ||
1058 | int pipe; | ||
1059 | int retval; | ||
1060 | struct zr364xx_pipeinfo *pipe_info = cam->pipe; | ||
1061 | pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint); | ||
1062 | DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint); | ||
1063 | |||
1064 | pipe_info->state = 1; | ||
1065 | pipe_info->err_count = 0; | ||
1066 | pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1067 | if (!pipe_info->stream_urb) { | ||
1068 | dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n"); | ||
1069 | return -ENOMEM; | ||
1070 | } | ||
1071 | /* transfer buffer allocated in board_init */ | ||
1072 | usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev, | ||
1073 | pipe, | ||
1074 | pipe_info->transfer_buffer, | ||
1075 | pipe_info->transfer_size, | ||
1076 | read_pipe_completion, pipe_info); | ||
1077 | |||
1078 | DBG("submitting URB %p\n", pipe_info->stream_urb); | ||
1079 | retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL); | ||
1080 | if (retval) { | ||
1081 | printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n"); | ||
1082 | return retval; | ||
1083 | } | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | static void zr364xx_stop_readpipe(struct zr364xx_camera *cam) | ||
1089 | { | ||
1090 | struct zr364xx_pipeinfo *pipe_info; | ||
1091 | |||
1092 | if (cam == NULL) { | ||
1093 | printk(KERN_ERR KBUILD_MODNAME ": invalid device\n"); | ||
1094 | return; | ||
1095 | } | ||
1096 | DBG("stop read pipe\n"); | ||
1097 | pipe_info = cam->pipe; | ||
1098 | if (pipe_info) { | ||
1099 | if (pipe_info->state != 0) | ||
1100 | pipe_info->state = 0; | ||
1101 | |||
1102 | if (pipe_info->stream_urb) { | ||
1103 | /* cancel urb */ | ||
1104 | usb_kill_urb(pipe_info->stream_urb); | ||
1105 | usb_free_urb(pipe_info->stream_urb); | ||
1106 | pipe_info->stream_urb = NULL; | ||
1107 | } | ||
1108 | } | ||
1109 | DBG("stop read pipe\n"); | ||
1110 | return; | ||
1111 | } | ||
1112 | |||
1113 | /* starts acquisition process */ | ||
1114 | static int zr364xx_start_acquire(struct zr364xx_camera *cam) | ||
1115 | { | ||
1116 | int j; | ||
1117 | |||
1118 | DBG("start acquire\n"); | ||
1119 | |||
1120 | cam->last_frame = -1; | ||
1121 | cam->cur_frame = 0; | ||
1122 | for (j = 0; j < FRAMES; j++) { | ||
1123 | cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE; | ||
1124 | cam->buffer.frame[j].cur_size = 0; | ||
1125 | } | ||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1129 | static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam) | ||
1130 | { | ||
1131 | cam->b_acquire = 0; | ||
604 | return 0; | 1132 | return 0; |
605 | } | 1133 | } |
606 | 1134 | ||
607 | static int zr364xx_vidioc_streamon(struct file *file, void *priv, | 1135 | static int zr364xx_vidioc_streamon(struct file *file, void *priv, |
608 | enum v4l2_buf_type type) | 1136 | enum v4l2_buf_type type) |
609 | { | 1137 | { |
610 | return 0; | 1138 | struct zr364xx_camera *cam = video_drvdata(file); |
1139 | int j; | ||
1140 | int res; | ||
1141 | |||
1142 | DBG("%s\n", __func__); | ||
1143 | |||
1144 | if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1145 | dev_err(&cam->udev->dev, "invalid fh type0\n"); | ||
1146 | return -EINVAL; | ||
1147 | } | ||
1148 | if (cam->type != type) { | ||
1149 | dev_err(&cam->udev->dev, "invalid fh type1\n"); | ||
1150 | return -EINVAL; | ||
1151 | } | ||
1152 | |||
1153 | if (!res_get(cam)) { | ||
1154 | dev_err(&cam->udev->dev, "stream busy\n"); | ||
1155 | return -EBUSY; | ||
1156 | } | ||
1157 | |||
1158 | cam->last_frame = -1; | ||
1159 | cam->cur_frame = 0; | ||
1160 | cam->frame_count = 0; | ||
1161 | for (j = 0; j < FRAMES; j++) { | ||
1162 | cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE; | ||
1163 | cam->buffer.frame[j].cur_size = 0; | ||
1164 | } | ||
1165 | res = videobuf_streamon(&cam->vb_vidq); | ||
1166 | if (res == 0) { | ||
1167 | zr364xx_start_acquire(cam); | ||
1168 | cam->b_acquire = 1; | ||
1169 | } else { | ||
1170 | res_free(cam); | ||
1171 | } | ||
1172 | DBG("%s: %d\n", __func__, res); | ||
1173 | return res; | ||
611 | } | 1174 | } |
612 | 1175 | ||
613 | static int zr364xx_vidioc_streamoff(struct file *file, void *priv, | 1176 | static int zr364xx_vidioc_streamoff(struct file *file, void *priv, |
614 | enum v4l2_buf_type type) | 1177 | enum v4l2_buf_type type) |
615 | { | 1178 | { |
1179 | int res; | ||
1180 | struct zr364xx_camera *cam = video_drvdata(file); | ||
1181 | |||
1182 | DBG("%s\n", __func__); | ||
1183 | if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1184 | dev_err(&cam->udev->dev, "invalid fh type0\n"); | ||
1185 | return -EINVAL; | ||
1186 | } | ||
1187 | if (cam->type != type) { | ||
1188 | dev_err(&cam->udev->dev, "invalid fh type1\n"); | ||
1189 | return -EINVAL; | ||
1190 | } | ||
1191 | zr364xx_stop_acquire(cam); | ||
1192 | res = videobuf_streamoff(&cam->vb_vidq); | ||
1193 | if (res < 0) | ||
1194 | return res; | ||
1195 | res_free(cam); | ||
616 | return 0; | 1196 | return 0; |
617 | } | 1197 | } |
618 | 1198 | ||
@@ -621,28 +1201,19 @@ static int zr364xx_vidioc_streamoff(struct file *file, void *priv, | |||
621 | static int zr364xx_open(struct file *file) | 1201 | static int zr364xx_open(struct file *file) |
622 | { | 1202 | { |
623 | struct video_device *vdev = video_devdata(file); | 1203 | struct video_device *vdev = video_devdata(file); |
624 | struct zr364xx_camera *cam = video_get_drvdata(vdev); | 1204 | struct zr364xx_camera *cam = video_drvdata(file); |
625 | struct usb_device *udev = cam->udev; | 1205 | struct usb_device *udev = cam->udev; |
626 | int i, err; | 1206 | int i, err; |
627 | 1207 | ||
628 | DBG("zr364xx_open"); | 1208 | DBG("%s\n", __func__); |
629 | 1209 | ||
630 | mutex_lock(&cam->lock); | 1210 | mutex_lock(&cam->open_lock); |
631 | 1211 | ||
632 | if (cam->users) { | 1212 | if (cam->users) { |
633 | err = -EBUSY; | 1213 | err = -EBUSY; |
634 | goto out; | 1214 | goto out; |
635 | } | 1215 | } |
636 | 1216 | ||
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++) { | 1217 | for (i = 0; init[cam->method][i].size != -1; i++) { |
647 | err = | 1218 | err = |
648 | send_control_msg(udev, 1, init[cam->method][i].value, | 1219 | send_control_msg(udev, 1, init[cam->method][i].value, |
@@ -658,6 +1229,14 @@ static int zr364xx_open(struct file *file) | |||
658 | cam->skip = 2; | 1229 | cam->skip = 2; |
659 | cam->users++; | 1230 | cam->users++; |
660 | file->private_data = vdev; | 1231 | file->private_data = vdev; |
1232 | cam->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1233 | cam->fmt = formats; | ||
1234 | |||
1235 | videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops, | ||
1236 | NULL, &cam->slock, | ||
1237 | cam->type, | ||
1238 | V4L2_FIELD_NONE, | ||
1239 | sizeof(struct zr364xx_buffer), cam); | ||
661 | 1240 | ||
662 | /* Added some delay here, since opening/closing the camera quickly, | 1241 | /* Added some delay here, since opening/closing the camera quickly, |
663 | * like Ekiga does during its startup, can crash the webcam | 1242 | * like Ekiga does during its startup, can crash the webcam |
@@ -666,28 +1245,72 @@ static int zr364xx_open(struct file *file) | |||
666 | err = 0; | 1245 | err = 0; |
667 | 1246 | ||
668 | out: | 1247 | out: |
669 | mutex_unlock(&cam->lock); | 1248 | mutex_unlock(&cam->open_lock); |
1249 | DBG("%s: %d\n", __func__, err); | ||
670 | return err; | 1250 | return err; |
671 | } | 1251 | } |
672 | 1252 | ||
1253 | static void zr364xx_destroy(struct zr364xx_camera *cam) | ||
1254 | { | ||
1255 | unsigned long i; | ||
1256 | |||
1257 | if (!cam) { | ||
1258 | printk(KERN_ERR KBUILD_MODNAME ", %s: no device\n", __func__); | ||
1259 | return; | ||
1260 | } | ||
1261 | mutex_lock(&cam->open_lock); | ||
1262 | if (cam->vdev) | ||
1263 | video_unregister_device(cam->vdev); | ||
1264 | cam->vdev = NULL; | ||
1265 | |||
1266 | /* stops the read pipe if it is running */ | ||
1267 | if (cam->b_acquire) | ||
1268 | zr364xx_stop_acquire(cam); | ||
1269 | |||
1270 | zr364xx_stop_readpipe(cam); | ||
1271 | |||
1272 | /* release sys buffers */ | ||
1273 | for (i = 0; i < FRAMES; i++) { | ||
1274 | if (cam->buffer.frame[i].lpvbits) { | ||
1275 | DBG("vfree %p\n", cam->buffer.frame[i].lpvbits); | ||
1276 | vfree(cam->buffer.frame[i].lpvbits); | ||
1277 | } | ||
1278 | cam->buffer.frame[i].lpvbits = NULL; | ||
1279 | } | ||
1280 | |||
1281 | /* release transfer buffer */ | ||
1282 | kfree(cam->pipe->transfer_buffer); | ||
1283 | cam->pipe->transfer_buffer = NULL; | ||
1284 | |||
1285 | DBG("%s\n", __func__); | ||
1286 | mutex_unlock(&cam->open_lock); | ||
1287 | kfree(cam); | ||
1288 | cam = NULL; | ||
1289 | } | ||
673 | 1290 | ||
674 | /* release the camera */ | 1291 | /* release the camera */ |
675 | static int zr364xx_release(struct file *file) | 1292 | static int zr364xx_release(struct file *file) |
676 | { | 1293 | { |
677 | struct video_device *vdev = video_devdata(file); | ||
678 | struct zr364xx_camera *cam; | 1294 | struct zr364xx_camera *cam; |
679 | struct usb_device *udev; | 1295 | struct usb_device *udev; |
680 | int i, err; | 1296 | int i, err; |
681 | 1297 | ||
682 | DBG("zr364xx_release"); | 1298 | DBG("%s\n", __func__); |
1299 | cam = video_drvdata(file); | ||
683 | 1300 | ||
684 | if (vdev == NULL) | 1301 | if (!cam) |
685 | return -ENODEV; | 1302 | return -ENODEV; |
686 | cam = video_get_drvdata(vdev); | ||
687 | 1303 | ||
1304 | mutex_lock(&cam->open_lock); | ||
688 | udev = cam->udev; | 1305 | udev = cam->udev; |
689 | 1306 | ||
690 | mutex_lock(&cam->lock); | 1307 | /* turn off stream */ |
1308 | if (res_check(cam)) { | ||
1309 | if (cam->b_acquire) | ||
1310 | zr364xx_stop_acquire(cam); | ||
1311 | videobuf_streamoff(&cam->vb_vidq); | ||
1312 | res_free(cam); | ||
1313 | } | ||
691 | 1314 | ||
692 | cam->users--; | 1315 | cam->users--; |
693 | file->private_data = NULL; | 1316 | file->private_data = NULL; |
@@ -710,40 +1333,43 @@ static int zr364xx_release(struct file *file) | |||
710 | err = 0; | 1333 | err = 0; |
711 | 1334 | ||
712 | out: | 1335 | out: |
713 | mutex_unlock(&cam->lock); | 1336 | mutex_unlock(&cam->open_lock); |
1337 | |||
714 | return err; | 1338 | return err; |
715 | } | 1339 | } |
716 | 1340 | ||
717 | 1341 | ||
718 | static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma) | 1342 | static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma) |
719 | { | 1343 | { |
720 | void *pos; | 1344 | struct zr364xx_camera *cam = video_drvdata(file); |
721 | unsigned long start = vma->vm_start; | 1345 | 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 | 1346 | ||
728 | if (vdev == NULL) | 1347 | if (cam == NULL) { |
1348 | DBG("%s: cam == NULL\n", __func__); | ||
729 | return -ENODEV; | 1349 | 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 | } | 1350 | } |
1351 | DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma); | ||
743 | 1352 | ||
744 | return 0; | 1353 | ret = videobuf_mmap_mapper(&cam->vb_vidq, vma); |
1354 | |||
1355 | DBG("vma start=0x%08lx, size=%ld, ret=%d\n", | ||
1356 | (unsigned long)vma->vm_start, | ||
1357 | (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret); | ||
1358 | return ret; | ||
745 | } | 1359 | } |
746 | 1360 | ||
1361 | static unsigned int zr364xx_poll(struct file *file, | ||
1362 | struct poll_table_struct *wait) | ||
1363 | { | ||
1364 | struct zr364xx_camera *cam = video_drvdata(file); | ||
1365 | struct videobuf_queue *q = &cam->vb_vidq; | ||
1366 | DBG("%s\n", __func__); | ||
1367 | |||
1368 | if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1369 | return POLLERR; | ||
1370 | |||
1371 | return videobuf_poll_stream(file, q, wait); | ||
1372 | } | ||
747 | 1373 | ||
748 | static const struct v4l2_file_operations zr364xx_fops = { | 1374 | static const struct v4l2_file_operations zr364xx_fops = { |
749 | .owner = THIS_MODULE, | 1375 | .owner = THIS_MODULE, |
@@ -752,6 +1378,7 @@ static const struct v4l2_file_operations zr364xx_fops = { | |||
752 | .read = zr364xx_read, | 1378 | .read = zr364xx_read, |
753 | .mmap = zr364xx_mmap, | 1379 | .mmap = zr364xx_mmap, |
754 | .ioctl = video_ioctl2, | 1380 | .ioctl = video_ioctl2, |
1381 | .poll = zr364xx_poll, | ||
755 | }; | 1382 | }; |
756 | 1383 | ||
757 | static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = { | 1384 | static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = { |
@@ -768,6 +1395,10 @@ static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = { | |||
768 | .vidioc_queryctrl = zr364xx_vidioc_queryctrl, | 1395 | .vidioc_queryctrl = zr364xx_vidioc_queryctrl, |
769 | .vidioc_g_ctrl = zr364xx_vidioc_g_ctrl, | 1396 | .vidioc_g_ctrl = zr364xx_vidioc_g_ctrl, |
770 | .vidioc_s_ctrl = zr364xx_vidioc_s_ctrl, | 1397 | .vidioc_s_ctrl = zr364xx_vidioc_s_ctrl, |
1398 | .vidioc_reqbufs = zr364xx_vidioc_reqbufs, | ||
1399 | .vidioc_querybuf = zr364xx_vidioc_querybuf, | ||
1400 | .vidioc_qbuf = zr364xx_vidioc_qbuf, | ||
1401 | .vidioc_dqbuf = zr364xx_vidioc_dqbuf, | ||
771 | }; | 1402 | }; |
772 | 1403 | ||
773 | static struct video_device zr364xx_template = { | 1404 | static struct video_device zr364xx_template = { |
@@ -783,15 +1414,76 @@ static struct video_device zr364xx_template = { | |||
783 | /*******************/ | 1414 | /*******************/ |
784 | /* USB integration */ | 1415 | /* USB integration */ |
785 | /*******************/ | 1416 | /*******************/ |
1417 | static int zr364xx_board_init(struct zr364xx_camera *cam) | ||
1418 | { | ||
1419 | struct zr364xx_pipeinfo *pipe = cam->pipe; | ||
1420 | unsigned long i; | ||
1421 | |||
1422 | DBG("board init: %p\n", cam); | ||
1423 | memset(pipe, 0, sizeof(*pipe)); | ||
1424 | pipe->cam = cam; | ||
1425 | pipe->transfer_size = BUFFER_SIZE; | ||
1426 | |||
1427 | pipe->transfer_buffer = kzalloc(pipe->transfer_size, | ||
1428 | GFP_KERNEL); | ||
1429 | if (pipe->transfer_buffer == NULL) { | ||
1430 | DBG("out of memory!\n"); | ||
1431 | return -ENOMEM; | ||
1432 | } | ||
1433 | |||
1434 | cam->b_acquire = 0; | ||
1435 | cam->frame_count = 0; | ||
1436 | |||
1437 | /*** start create system buffers ***/ | ||
1438 | for (i = 0; i < FRAMES; i++) { | ||
1439 | /* always allocate maximum size for system buffers */ | ||
1440 | cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE); | ||
1441 | |||
1442 | DBG("valloc %p, idx %lu, pdata %p\n", | ||
1443 | &cam->buffer.frame[i], i, | ||
1444 | cam->buffer.frame[i].lpvbits); | ||
1445 | if (cam->buffer.frame[i].lpvbits == NULL) { | ||
1446 | printk(KERN_INFO KBUILD_MODNAME ": out of memory. " | ||
1447 | "Using less frames\n"); | ||
1448 | break; | ||
1449 | } | ||
1450 | } | ||
1451 | |||
1452 | if (i == 0) { | ||
1453 | printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n"); | ||
1454 | kfree(cam->pipe->transfer_buffer); | ||
1455 | cam->pipe->transfer_buffer = NULL; | ||
1456 | return -ENOMEM; | ||
1457 | } else | ||
1458 | cam->buffer.dwFrames = i; | ||
1459 | |||
1460 | /* make sure internal states are set */ | ||
1461 | for (i = 0; i < FRAMES; i++) { | ||
1462 | cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE; | ||
1463 | cam->buffer.frame[i].cur_size = 0; | ||
1464 | } | ||
1465 | |||
1466 | cam->cur_frame = 0; | ||
1467 | cam->last_frame = -1; | ||
1468 | /*** end create system buffers ***/ | ||
1469 | |||
1470 | /* start read pipe */ | ||
1471 | zr364xx_start_readpipe(cam); | ||
1472 | DBG(": board initialized\n"); | ||
1473 | return 0; | ||
1474 | } | ||
786 | 1475 | ||
787 | static int zr364xx_probe(struct usb_interface *intf, | 1476 | static int zr364xx_probe(struct usb_interface *intf, |
788 | const struct usb_device_id *id) | 1477 | const struct usb_device_id *id) |
789 | { | 1478 | { |
790 | struct usb_device *udev = interface_to_usbdev(intf); | 1479 | struct usb_device *udev = interface_to_usbdev(intf); |
791 | struct zr364xx_camera *cam = NULL; | 1480 | struct zr364xx_camera *cam = NULL; |
1481 | struct usb_host_interface *iface_desc; | ||
1482 | struct usb_endpoint_descriptor *endpoint; | ||
792 | int err; | 1483 | int err; |
1484 | int i; | ||
793 | 1485 | ||
794 | DBG("probing..."); | 1486 | DBG("probing...\n"); |
795 | 1487 | ||
796 | dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n"); | 1488 | dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n"); |
797 | dev_info(&intf->dev, "model %04x:%04x detected\n", | 1489 | dev_info(&intf->dev, "model %04x:%04x detected\n", |
@@ -810,22 +1502,17 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
810 | if (cam->vdev == NULL) { | 1502 | if (cam->vdev == NULL) { |
811 | dev_err(&udev->dev, "cam->vdev: out of memory !\n"); | 1503 | dev_err(&udev->dev, "cam->vdev: out of memory !\n"); |
812 | kfree(cam); | 1504 | kfree(cam); |
1505 | cam = NULL; | ||
813 | return -ENOMEM; | 1506 | return -ENOMEM; |
814 | } | 1507 | } |
815 | memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template)); | 1508 | memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template)); |
1509 | cam->vdev->parent = &intf->dev; | ||
816 | video_set_drvdata(cam->vdev, cam); | 1510 | video_set_drvdata(cam->vdev, cam); |
817 | if (debug) | 1511 | if (debug) |
818 | cam->vdev->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; | 1512 | cam->vdev->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; |
819 | 1513 | ||
820 | cam->udev = udev; | 1514 | cam->udev = udev; |
821 | 1515 | ||
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) { | 1516 | switch (mode) { |
830 | case 1: | 1517 | case 1: |
831 | dev_info(&udev->dev, "160x120 mode selected\n"); | 1518 | dev_info(&udev->dev, "160x120 mode selected\n"); |
@@ -852,21 +1539,53 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
852 | header2[439] = cam->width / 256; | 1539 | header2[439] = cam->width / 256; |
853 | header2[440] = cam->width % 256; | 1540 | header2[440] = cam->width % 256; |
854 | 1541 | ||
1542 | cam->users = 0; | ||
855 | cam->nb = 0; | 1543 | cam->nb = 0; |
856 | cam->brightness = 64; | 1544 | cam->mode.brightness = 64; |
857 | mutex_init(&cam->lock); | 1545 | mutex_init(&cam->lock); |
1546 | mutex_init(&cam->open_lock); | ||
1547 | |||
1548 | DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf); | ||
1549 | |||
1550 | /* set up the endpoint information */ | ||
1551 | iface_desc = intf->cur_altsetting; | ||
1552 | DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints); | ||
1553 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
1554 | endpoint = &iface_desc->endpoint[i].desc; | ||
1555 | if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) { | ||
1556 | /* we found the bulk in endpoint */ | ||
1557 | cam->read_endpoint = endpoint->bEndpointAddress; | ||
1558 | } | ||
1559 | } | ||
858 | 1560 | ||
1561 | if (!cam->read_endpoint) { | ||
1562 | dev_err(&intf->dev, "Could not find bulk-in endpoint\n"); | ||
1563 | return -ENOMEM; | ||
1564 | } | ||
1565 | |||
1566 | /* v4l */ | ||
1567 | INIT_LIST_HEAD(&cam->vidq.active); | ||
1568 | cam->vidq.cam = cam; | ||
859 | err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); | 1569 | err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); |
860 | if (err) { | 1570 | if (err) { |
861 | dev_err(&udev->dev, "video_register_device failed\n"); | 1571 | dev_err(&udev->dev, "video_register_device failed\n"); |
862 | video_device_release(cam->vdev); | 1572 | video_device_release(cam->vdev); |
863 | kfree(cam->buffer); | ||
864 | kfree(cam); | 1573 | kfree(cam); |
1574 | cam = NULL; | ||
865 | return err; | 1575 | return err; |
866 | } | 1576 | } |
867 | 1577 | ||
868 | usb_set_intfdata(intf, cam); | 1578 | usb_set_intfdata(intf, cam); |
869 | 1579 | ||
1580 | /* load zr364xx board specific */ | ||
1581 | err = zr364xx_board_init(cam); | ||
1582 | if (err) { | ||
1583 | spin_lock_init(&cam->slock); | ||
1584 | return err; | ||
1585 | } | ||
1586 | |||
1587 | spin_lock_init(&cam->slock); | ||
1588 | |||
870 | dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n", | 1589 | dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n", |
871 | cam->vdev->num); | 1590 | cam->vdev->num); |
872 | return 0; | 1591 | return 0; |
@@ -876,17 +1595,10 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
876 | static void zr364xx_disconnect(struct usb_interface *intf) | 1595 | static void zr364xx_disconnect(struct usb_interface *intf) |
877 | { | 1596 | { |
878 | struct zr364xx_camera *cam = usb_get_intfdata(intf); | 1597 | struct zr364xx_camera *cam = usb_get_intfdata(intf); |
1598 | videobuf_mmap_free(&cam->vb_vidq); | ||
879 | usb_set_intfdata(intf, NULL); | 1599 | usb_set_intfdata(intf, NULL); |
880 | dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n"); | 1600 | dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n"); |
881 | if (cam->vdev) | 1601 | 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 | } | 1602 | } |
891 | 1603 | ||
892 | 1604 | ||