blob: b36913017d7bc1e9f159b293853ec438505884a6 [file] [log] [blame]
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001/*
2 * Main USB camera driver
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#define MODULE_NAME "gspca"
22
23#include <linux/init.h>
24#include <linux/fs.h>
25#include <linux/vmalloc.h>
26#include <linux/sched.h>
27#include <linux/slab.h>
28#include <linux/mm.h>
29#include <linux/string.h>
30#include <linux/pagemap.h>
Jean-Francois Moine956e42d2008-07-01 10:03:42 -030031#include <linux/io.h>
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030032#include <asm/page.h>
Jean-Francois Moine956e42d2008-07-01 10:03:42 -030033#include <linux/uaccess.h>
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030034#include <linux/jiffies.h>
35
36#include "gspca.h"
37
Jean-Francois Moined43fa322008-06-12 10:58:58 -030038/* global values */
39#define DEF_NURBS 2 /* default number of URBs (mmap) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030040#define USR_NURBS 5 /* default number of URBs (userptr) */
Jean-Francois Moined43fa322008-06-12 10:58:58 -030041
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030042MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
43MODULE_DESCRIPTION("GSPCA USB Camera Driver");
44MODULE_LICENSE("GPL");
45
Jean-Francois Moine82643d02008-07-02 09:14:56 -030046#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 2)
47static const char version[] = "2.1.2";
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030048
49static int video_nr = -1;
50
51static int comp_fac = 30; /* Buffer size ratio when compressed in % */
52
Hans de Goeded646e702008-07-03 06:48:22 -030053#ifdef CONFIG_VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030054int gspca_debug = D_ERR | D_PROBE;
55EXPORT_SYMBOL(gspca_debug);
56
57static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
58{
59 if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') {
60 PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d",
61 txt,
62 pixfmt & 0xff,
63 (pixfmt >> 8) & 0xff,
64 (pixfmt >> 16) & 0xff,
65 pixfmt >> 24,
66 w, h);
67 } else {
68 PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d",
69 txt,
70 pixfmt,
71 w, h);
72 }
73}
74#else
75#define PDEBUG_MODE(txt, pixfmt, w, h)
76#endif
77
Jean-Francois Moined43fa322008-06-12 10:58:58 -030078/* specific memory types - !! should different from V4L2_MEMORY_xxx */
79#define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */
80#define GSPCA_MEMORY_READ 7
81
Jean-Francois Moined43fa322008-06-12 10:58:58 -030082#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)
Jean-Francois Moined43fa322008-06-12 10:58:58 -030083
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030084/*
85 * VMA operations.
86 */
87static void gspca_vm_open(struct vm_area_struct *vma)
88{
89 struct gspca_frame *frame = vma->vm_private_data;
90
91 frame->vma_use_count++;
92 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_MAPPED;
93}
94
95static void gspca_vm_close(struct vm_area_struct *vma)
96{
97 struct gspca_frame *frame = vma->vm_private_data;
98
99 if (--frame->vma_use_count <= 0)
100 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_MAPPED;
101}
102
103static struct vm_operations_struct gspca_vm_ops = {
104 .open = gspca_vm_open,
105 .close = gspca_vm_close,
106};
107
108/*
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300109 * fill a video frame from an URB and resubmit
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300110 */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300111static void fill_frame(struct gspca_dev *gspca_dev,
112 struct urb *urb)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300113{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300114 struct gspca_frame *frame;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300115 __u8 *data; /* address of data in the iso message */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300116 int i, j, len, st;
117 cam_pkt_op pkt_scan;
118
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300119 if (urb->status != 0) {
120 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
121 return; /* disconnection ? */
122 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300123 pkt_scan = gspca_dev->sd_desc->pkt_scan;
124 for (i = 0; i < urb->number_of_packets; i++) {
125
126 /* check the availability of the frame buffer */
127 j = gspca_dev->fr_i;
128 j = gspca_dev->fr_queue[j];
129 frame = &gspca_dev->frame[j];
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300130 if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300131 != V4L2_BUF_FLAG_QUEUED) {
132 gspca_dev->last_packet_type = DISCARD_PACKET;
133 break;
134 }
135
136 /* check the packet status and length */
137 len = urb->iso_frame_desc[i].actual_length;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300138 if (len == 0)
139 continue;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300140 st = urb->iso_frame_desc[i].status;
141 if (st) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300142 PDEBUG(D_ERR,
143 "ISOC data error: [%d] len=%d, status=%d",
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300144 i, len, st);
145 gspca_dev->last_packet_type = DISCARD_PACKET;
146 continue;
147 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300148
149 /* let the packet be analyzed by the subdriver */
150 PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
151 i, urb->iso_frame_desc[i].offset, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300152 data = (__u8 *) urb->transfer_buffer
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300153 + urb->iso_frame_desc[i].offset;
154 pkt_scan(gspca_dev, frame, data, len);
155 }
156
157 /* resubmit the URB */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300158/*fixme: don't do that when userptr and too many URBs sent*/
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300159 urb->status = 0;
160 st = usb_submit_urb(urb, GFP_ATOMIC);
161 if (st < 0)
162 PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", st);
163}
164
165/*
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300166 * ISOC message interrupt from the USB device
167 *
168 * Analyse each packet and call the subdriver for copy
169 * to the frame buffer.
170 *
171 * There are 2 functions:
172 * - the first one (isoc_irq_mmap) is used when the application
173 * buffers are mapped. The frame detection and copy is done
174 * at interrupt level.
175 * - the second one (isoc_irq_user) is used when the application
176 * buffers are in user space (userptr). The frame detection
177 * and copy is done by the application.
178 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300179static void isoc_irq_mmap(struct urb *urb
180)
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300181{
182 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
183
184 PDEBUG(D_PACK, "isoc irq mmap");
185 if (!gspca_dev->streaming)
186 return;
187 fill_frame(gspca_dev, urb);
188}
189
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300190static void isoc_irq_user(struct urb *urb
191)
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300192{
193 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
194 int i;
195
196 PDEBUG(D_PACK, "isoc irq user");
197 if (!gspca_dev->streaming)
198 return;
199
200 i = gspca_dev->urb_in % gspca_dev->nurbs;
201 if (urb != gspca_dev->urb[i]) {
202 PDEBUG(D_ERR|D_PACK, "urb out of sequence");
203 return; /* should never occur */
204 }
205
206 gspca_dev->urb_in++;
207 atomic_inc(&gspca_dev->nevent); /* new event */
208 wake_up_interruptible(&gspca_dev->wq);
209/*fixme: submit a new URBs until urb_in == urb_out (% nurbs)*/
210}
211
212/*
213 * treat the isoc messages
214 *
215 * This routine is called by the application (case userptr).
216 */
217static void isoc_transfer(struct gspca_dev *gspca_dev)
218{
219 struct urb *urb;
220 int i;
221
222 for (;;) {
223 i = gspca_dev->urb_out;
224 PDEBUG(D_PACK, "isoc transf i:%d o:%d", gspca_dev->urb_in, i);
225 if (i == gspca_dev->urb_in) /* isoc message to read */
226 break; /* no (more) message */
227 atomic_dec(&gspca_dev->nevent);
228/*PDEBUG(D_PACK, "isoc_trf nevent: %d", atomic_read(&gspca_dev->nevent));*/
229 gspca_dev->urb_out = i + 1; /* message treated */
230 urb = gspca_dev->urb[i % gspca_dev->nurbs];
231 fill_frame(gspca_dev, urb);
232 }
233}
234
235/*
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300236 * add data to the current frame
237 *
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300238 * This function is called by the subdrivers at interrupt level
239 * or user level.
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300240 * To build a frame, these ones must add
241 * - one FIRST_PACKET
242 * - 0 or many INTER_PACKETs
243 * - one LAST_PACKET
244 * DISCARD_PACKET invalidates the whole frame.
245 * On LAST_PACKET, a new frame is returned.
246 */
247struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
248 int packet_type,
249 struct gspca_frame *frame,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300250 __u8 *data,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300251 int len)
252{
253 int i, j;
254
Hans de Goedee2997a72008-04-23 08:09:12 -0300255 PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300256
257 /* when start of a new frame, if the current frame buffer
258 * is not queued, discard the whole frame */
259 if (packet_type == FIRST_PACKET) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300260 if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
261 != V4L2_BUF_FLAG_QUEUED) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300262 gspca_dev->last_packet_type = DISCARD_PACKET;
263 return frame;
264 }
265 frame->data_end = frame->data;
266 jiffies_to_timeval(get_jiffies_64(),
267 &frame->v4l2_buf.timestamp);
268 frame->v4l2_buf.sequence = ++gspca_dev->sequence;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300269 } else if (gspca_dev->last_packet_type == DISCARD_PACKET) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300270 return frame;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300271 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300272
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300273 /* append the packet to the frame buffer */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300274 if (len > 0) {
275 if (frame->data_end - frame->data + len
276 > frame->v4l2_buf.length) {
277 PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d",
278 frame->data_end - frame->data + len,
279 frame->v4l2_buf.length);
280 packet_type = DISCARD_PACKET;
281 } else {
Jean-Francois Moine82643d02008-07-02 09:14:56 -0300282 if (frame->v4l2_buf.memory != V4L2_MEMORY_USERPTR) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300283 memcpy(frame->data_end, data, len);
Jean-Francois Moine82643d02008-07-02 09:14:56 -0300284 } else {
285 if (copy_to_user(frame->data_end,
286 data, len) != 0) {
287 PDEBUG(D_ERR|D_PACK,
288 "copy to user failed");
289 packet_type = DISCARD_PACKET;
290 }
291 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300292 frame->data_end += len;
293 }
294 }
295 gspca_dev->last_packet_type = packet_type;
296
297 /* if last packet, wake the application and advance in the queue */
298 if (packet_type == LAST_PACKET) {
299 frame->v4l2_buf.bytesused = frame->data_end - frame->data;
300 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
301 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
302 atomic_inc(&gspca_dev->nevent);
303 wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300304 i = (gspca_dev->fr_i + 1) % gspca_dev->nframes;
305 gspca_dev->fr_i = i;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300306 PDEBUG(D_FRAM, "frame complete len:%d q:%d i:%d o:%d",
307 frame->v4l2_buf.bytesused,
308 gspca_dev->fr_q,
309 i,
310 gspca_dev->fr_o);
311 j = gspca_dev->fr_queue[i];
312 frame = &gspca_dev->frame[j];
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300313 }
314 return frame;
315}
316EXPORT_SYMBOL(gspca_frame_add);
317
318static int gspca_is_compressed(__u32 format)
319{
320 switch (format) {
321 case V4L2_PIX_FMT_MJPEG:
322 case V4L2_PIX_FMT_JPEG:
Jean-Francois Moine50a871f2008-06-30 19:47:33 -0300323 case V4L2_PIX_FMT_SPCA561:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300324 return 1;
325 }
326 return 0;
327}
328
329static void *rvmalloc(unsigned long size)
330{
331 void *mem;
332 unsigned long adr;
333
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300334/* size = PAGE_ALIGN(size); (already done) */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300335 mem = vmalloc_32(size);
336 if (mem != 0) {
337 memset(mem, 0, size);
338 adr = (unsigned long) mem;
339 while ((long) size > 0) {
340 SetPageReserved(vmalloc_to_page((void *) adr));
341 adr += PAGE_SIZE;
342 size -= PAGE_SIZE;
343 }
344 }
345 return mem;
346}
347
348static void rvfree(void *mem, unsigned long size)
349{
350 unsigned long adr;
351
352 if (!mem)
353 return;
354 adr = (unsigned long) mem;
355 while ((long) size > 0) {
356 ClearPageReserved(vmalloc_to_page((void *) adr));
357 adr += PAGE_SIZE;
358 size -= PAGE_SIZE;
359 }
360 vfree(mem);
361}
362
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300363static __u32 get_v4l2_depth(__u32 pixfmt)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300364{
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300365 switch (pixfmt) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300366/* case V4L2_PIX_FMT_BGR32:
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300367 case V4L2_PIX_FMT_RGB32:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300368 return 32; */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300369 case V4L2_PIX_FMT_RGB24: /* 'RGB3' */
370 case V4L2_PIX_FMT_BGR24:
371 return 24;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300372/* case V4L2_PIX_FMT_RGB565: * 'RGBP' */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300373 case V4L2_PIX_FMT_YUYV: /* 'YUYV' packed 4.2.2 */
374 case V4L2_PIX_FMT_YYUV: /* 'YYUV' */
375 return 16;
376 case V4L2_PIX_FMT_YUV420: /* 'YU12' planar 4.2.0 */
Jean-Francois Moine50a871f2008-06-30 19:47:33 -0300377 case V4L2_PIX_FMT_SPCA501: /* 'S501' YUYV per line */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300378 return 12;
379 case V4L2_PIX_FMT_MJPEG:
380 case V4L2_PIX_FMT_JPEG:
381 case V4L2_PIX_FMT_SBGGR8: /* 'BA81' Bayer */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300382 case V4L2_PIX_FMT_SN9C10X: /* 'S910' SN9C10x compression */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300383 case V4L2_PIX_FMT_SPCA561: /* 'S561' compressed BGGR bayer */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300384 return 8;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300385 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300386 PDEBUG(D_ERR|D_CONF, "Unknown pixel format %c%c%c%c",
387 pixfmt & 0xff,
388 (pixfmt >> 8) & 0xff,
389 (pixfmt >> 16) & 0xff,
390 pixfmt >> 24);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300391 return 24;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300392}
393
394static int gspca_get_buff_size(struct gspca_dev *gspca_dev)
395{
396 unsigned int size;
397
398 size = gspca_dev->width * gspca_dev->height
399 * get_v4l2_depth(gspca_dev->pixfmt) / 8;
400 if (!size)
401 return -ENOMEM;
402 return size;
403}
404
405static int frame_alloc(struct gspca_dev *gspca_dev,
406 unsigned int count)
407{
408 struct gspca_frame *frame;
409 unsigned int frsz;
410 int i;
411
412 frsz = gspca_get_buff_size(gspca_dev);
413 if (frsz < 0)
414 return frsz;
415 PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300416 if (count > GSPCA_MAX_FRAMES)
417 count = GSPCA_MAX_FRAMES;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300418 /* if compressed (JPEG), reduce the buffer size */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300419 if (gspca_is_compressed(gspca_dev->pixfmt))
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300420 frsz = (frsz * comp_fac) / 100 + 600; /* (+ JPEG header sz) */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300421 frsz = PAGE_ALIGN(frsz);
422 PDEBUG(D_STREAM, "new fr_sz: %d", frsz);
423 gspca_dev->frsz = frsz;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300424 if (gspca_dev->memory == V4L2_MEMORY_MMAP) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300425 gspca_dev->frbuf = rvmalloc(frsz * count);
426 if (!gspca_dev->frbuf) {
427 err("frame alloc failed");
428 return -ENOMEM;
429 }
430 }
431 gspca_dev->nframes = count;
432 for (i = 0; i < count; i++) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300433 frame = &gspca_dev->frame[i];
434 frame->v4l2_buf.index = i;
435 frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
436 frame->v4l2_buf.flags = 0;
437 frame->v4l2_buf.field = V4L2_FIELD_NONE;
438 frame->v4l2_buf.length = frsz;
439 frame->v4l2_buf.memory = gspca_dev->memory;
440 frame->v4l2_buf.sequence = 0;
441 if (gspca_dev->memory == V4L2_MEMORY_MMAP) {
442 frame->data = frame->data_end =
443 gspca_dev->frbuf + i * frsz;
444 frame->v4l2_buf.m.offset = i * frsz;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300445 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300446 }
447 gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
448 gspca_dev->last_packet_type = DISCARD_PACKET;
449 gspca_dev->sequence = 0;
450 atomic_set(&gspca_dev->nevent, 0);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300451 return 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300452}
453
454static void frame_free(struct gspca_dev *gspca_dev)
455{
456 int i;
457
458 PDEBUG(D_STREAM, "frame free");
459 if (gspca_dev->frbuf != 0) {
460 rvfree(gspca_dev->frbuf,
461 gspca_dev->nframes * gspca_dev->frsz);
462 gspca_dev->frbuf = NULL;
463 for (i = 0; i < gspca_dev->nframes; i++)
464 gspca_dev->frame[i].data = NULL;
465 }
466 gspca_dev->nframes = 0;
467}
468
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300469static void destroy_urbs(struct gspca_dev *gspca_dev)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300470{
471 struct urb *urb;
472 unsigned int i;
473
474 PDEBUG(D_STREAM, "kill transfer");
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300475 for (i = 0; i < MAX_NURBS; ++i) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300476 urb = gspca_dev->urb[i];
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300477 if (urb == NULL)
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300478 break;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300479
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300480 gspca_dev->urb[i] = NULL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300481 usb_kill_urb(urb);
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300482 if (urb->transfer_buffer != 0)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300483 usb_buffer_free(gspca_dev->dev,
484 urb->transfer_buffer_length,
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300485 urb->transfer_buffer,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300486 urb->transfer_dma);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300487 usb_free_urb(urb);
488 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300489}
490
491/*
492 * search an input isochronous endpoint in an alternate setting
493 */
494static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
495 __u8 epaddr)
496{
497 struct usb_host_endpoint *ep;
498 int i, attr;
499
500 epaddr |= USB_DIR_IN;
501 for (i = 0; i < alt->desc.bNumEndpoints; i++) {
502 ep = &alt->endpoint[i];
503 if (ep->desc.bEndpointAddress == epaddr) {
504 attr = ep->desc.bmAttributes
505 & USB_ENDPOINT_XFERTYPE_MASK;
506 if (attr == USB_ENDPOINT_XFER_ISOC)
507 return ep;
508 break;
509 }
510 }
511 return NULL;
512}
513
514/*
515 * search an input isochronous endpoint
516 *
517 * The endpoint is defined by the subdriver.
518 * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
519 * This routine may be called many times when the bandwidth is too small
520 * (the bandwidth is checked on urb submit).
521 */
522struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
523{
524 struct usb_interface *intf;
525 struct usb_host_endpoint *ep;
526 int i, ret;
527
528 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300529 ep = NULL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300530 i = gspca_dev->alt; /* previous alt setting */
531 while (--i > 0) { /* alt 0 is unusable */
532 ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr);
533 if (ep)
534 break;
535 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300536 if (ep == NULL) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300537 err("no ISOC endpoint found");
538 return NULL;
539 }
540 PDEBUG(D_STREAM, "use ISOC alt %d ep 0x%02x",
541 i, ep->desc.bEndpointAddress);
542 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
543 if (ret < 0) {
544 err("set interface err %d", ret);
545 return NULL;
546 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300547 gspca_dev->alt = i; /* memorize the current alt setting */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300548 return ep;
549}
550
551/*
552 * create the isochronous URBs
553 */
554static int create_urbs(struct gspca_dev *gspca_dev,
555 struct usb_host_endpoint *ep)
556{
557 struct urb *urb;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300558 int n, nurbs, i, psize, npkt, bsize;
559 usb_complete_t usb_complete;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300560
561 /* calculate the packet size and the number of packets */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300562 psize = le16_to_cpu(ep->desc.wMaxPacketSize);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300563
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300564 /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
565 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
566 npkt = ISO_MAX_SIZE / psize;
567 if (npkt > ISO_MAX_PKT)
568 npkt = ISO_MAX_PKT;
569 bsize = psize * npkt;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300570 PDEBUG(D_STREAM,
571 "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300572/*fixme:don't submit all URBs when userptr*/
Jean-Francois Moine82643d02008-07-02 09:14:56 -0300573 if (gspca_dev->memory != V4L2_MEMORY_USERPTR) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300574 usb_complete = isoc_irq_mmap;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300575 nurbs = DEF_NURBS;
576 } else {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300577 usb_complete = isoc_irq_user;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300578 nurbs = USR_NURBS;
579 }
580 gspca_dev->nurbs = nurbs;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300581 for (n = 0; n < nurbs; n++) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300582 urb = usb_alloc_urb(npkt, GFP_KERNEL);
583 if (!urb) {
584 err("usb_alloc_urb failed");
585 return -ENOMEM;
586 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300587 urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300588 bsize,
589 GFP_KERNEL,
590 &urb->transfer_dma);
591
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300592 if (urb->transfer_buffer == NULL) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300593 usb_free_urb(urb);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300594 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300595 err("usb_buffer_urb failed");
596 return -ENOMEM;
597 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300598 gspca_dev->urb[n] = urb;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300599 urb->dev = gspca_dev->dev;
600 urb->context = gspca_dev;
601 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
602 ep->desc.bEndpointAddress);
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300603 urb->transfer_flags = URB_ISO_ASAP
604 | URB_NO_TRANSFER_DMA_MAP;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300605 urb->interval = ep->desc.bInterval;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300606 urb->complete = usb_complete;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300607 urb->number_of_packets = npkt;
608 urb->transfer_buffer_length = bsize;
609 for (i = 0; i < npkt; i++) {
610 urb->iso_frame_desc[i].length = psize;
611 urb->iso_frame_desc[i].offset = psize * i;
612 }
613 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300614 gspca_dev->urb_in = gspca_dev->urb_out = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300615 return 0;
616}
617
618/*
619 * start the USB transfer
620 */
621static int gspca_init_transfer(struct gspca_dev *gspca_dev)
622{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300623 struct usb_host_endpoint *ep;
624 int n, ret;
625
Hans de Goedee2997a72008-04-23 08:09:12 -0300626 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
627 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300628
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300629 /* set the higher alternate setting and
630 * loop until urb submit succeeds */
631 gspca_dev->alt = gspca_dev->nbalt;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300632 for (;;) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300633 PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300634 ep = get_isoc_ep(gspca_dev);
635 if (ep == NULL) {
636 ret = -EIO;
637 goto out;
638 }
639 ret = create_urbs(gspca_dev, ep);
640 if (ret < 0)
641 goto out;
642
643 /* start the cam */
644 gspca_dev->sd_desc->start(gspca_dev);
645 gspca_dev->streaming = 1;
646 atomic_set(&gspca_dev->nevent, 0);
647
648 /* submit the URBs */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300649 for (n = 0; n < gspca_dev->nurbs; n++) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300650 ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300651 if (ret < 0) {
652 PDEBUG(D_ERR|D_STREAM,
653 "usb_submit_urb [%d] err %d", n, ret);
Hans de Goedee2997a72008-04-23 08:09:12 -0300654 gspca_dev->streaming = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300655 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300656 if (ret == -ENOSPC)
657 break; /* try the previous alt */
658 goto out;
659 }
660 }
661 if (ret >= 0)
662 break;
663 }
664out:
665 mutex_unlock(&gspca_dev->usb_lock);
666 return ret;
667}
668
669static int gspca_set_alt0(struct gspca_dev *gspca_dev)
670{
671 int ret;
672
673 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
674 if (ret < 0)
675 PDEBUG(D_ERR|D_STREAM, "set interface 0 err %d", ret);
676 return ret;
677}
678
Hans de Goedee2997a72008-04-23 08:09:12 -0300679/* Note both the queue and the usb lock should be hold when calling this */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300680static void gspca_stream_off(struct gspca_dev *gspca_dev)
681{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300682 gspca_dev->streaming = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300683 atomic_set(&gspca_dev->nevent, 0);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300684 if (gspca_dev->present) {
685 gspca_dev->sd_desc->stopN(gspca_dev);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300686 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300687 gspca_set_alt0(gspca_dev);
688 gspca_dev->sd_desc->stop0(gspca_dev);
689 PDEBUG(D_STREAM, "stream off OK");
690 } else {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300691 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300692 atomic_inc(&gspca_dev->nevent);
693 wake_up_interruptible(&gspca_dev->wq);
694 PDEBUG(D_ERR|D_STREAM, "stream off no device ??");
695 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300696}
697
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300698static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300699{
700 int i;
701
702 i = gspca_dev->cam.nmodes - 1; /* take the highest mode */
703 gspca_dev->curr_mode = i;
704 gspca_dev->width = gspca_dev->cam.cam_mode[i].width;
705 gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
706 gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixfmt;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300707}
708
709static int wxh_to_mode(struct gspca_dev *gspca_dev,
710 int width, int height)
711{
712 int i;
713
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300714 for (i = gspca_dev->cam.nmodes; --i > 0; ) {
715 if (width >= gspca_dev->cam.cam_mode[i].width
716 && height >= gspca_dev->cam.cam_mode[i].height)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300717 break;
718 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300719 return i;
720}
721
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300722/*
723 * search a mode with the right pixel format
724 */
725static int gspca_get_mode(struct gspca_dev *gspca_dev,
726 int mode,
727 int pixfmt)
728{
729 int modeU, modeD;
730
731 modeU = modeD = mode;
732 while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) {
733 if (--modeD >= 0) {
734 if (gspca_dev->cam.cam_mode[modeD].pixfmt == pixfmt)
735 return modeD;
736 }
737 if (++modeU < gspca_dev->cam.nmodes) {
738 if (gspca_dev->cam.cam_mode[modeU].pixfmt == pixfmt)
739 return modeU;
740 }
741 }
742 return -EINVAL;
743}
744
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300745static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300746 struct v4l2_fmtdesc *fmtdesc)
747{
748 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300749 int i, j, index;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300750 __u32 fmt_tb[8];
751
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300752 /* give an index to each format */
753 index = 0;
754 j = 0;
755 for (i = gspca_dev->cam.nmodes; --i >= 0; ) {
756 fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixfmt;
757 j = 0;
758 for (;;) {
759 if (fmt_tb[j] == fmt_tb[index])
760 break;
761 j++;
762 }
763 if (j == index) {
764 if (fmtdesc->index == index)
765 break; /* new format */
766 index++;
767 if (index >= sizeof fmt_tb / sizeof fmt_tb[0])
768 return -EINVAL;
769 }
770 }
771 if (i < 0)
772 return -EINVAL; /* no more format */
773
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300774 fmtdesc->pixelformat = fmt_tb[index];
775 if (gspca_is_compressed(fmt_tb[index]))
776 fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300777 fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300778 fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
779 fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
780 fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff;
781 fmtdesc->description[3] = fmtdesc->pixelformat >> 24;
782 fmtdesc->description[4] = '\0';
783 return 0;
784}
785
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300786static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300787 struct v4l2_format *fmt)
788{
789 struct gspca_dev *gspca_dev = priv;
790
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300791 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
792 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300793 fmt->fmt.pix.width = gspca_dev->width;
794 fmt->fmt.pix.height = gspca_dev->height;
795 fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300796 fmt->fmt.pix.field = V4L2_FIELD_NONE;
797 fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat)
798 * fmt->fmt.pix.width / 8;
799 fmt->fmt.pix.sizeimage = fmt->fmt.pix.bytesperline
800 * fmt->fmt.pix.height;
801/* (should be in the subdriver) */
802 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
803 fmt->fmt.pix.priv = 0;
804 return 0;
805}
806
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300807static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300808 struct v4l2_format *fmt)
809{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300810 int w, h, mode, mode2, frsz;
811
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300812 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
813 return -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300814 w = fmt->fmt.pix.width;
815 h = fmt->fmt.pix.height;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300816
817 /* (luvcview problem) */
818 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
819 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
Hans de Goeded646e702008-07-03 06:48:22 -0300820#ifdef CONFIG_VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300821 if (gspca_debug & D_CONF)
822 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
823#endif
824 /* search the closest mode for width and height */
825 mode = wxh_to_mode(gspca_dev, w, h);
826
827 /* OK if right palette */
828 if (gspca_dev->cam.cam_mode[mode].pixfmt != fmt->fmt.pix.pixelformat) {
829
830 /* else, search the closest mode with the same pixel format */
831 mode2 = gspca_get_mode(gspca_dev, mode,
832 fmt->fmt.pix.pixelformat);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300833 if (mode2 >= 0) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300834 mode = mode2;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300835 } else {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300836
837 /* no chance, return this mode */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300838 fmt->fmt.pix.pixelformat =
839 gspca_dev->cam.cam_mode[mode].pixfmt;
Hans de Goeded646e702008-07-03 06:48:22 -0300840#ifdef CONFIG_VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300841 if (gspca_debug & D_CONF) {
842 PDEBUG_MODE("new format",
843 fmt->fmt.pix.pixelformat,
844 gspca_dev->cam.cam_mode[mode].width,
845 gspca_dev->cam.cam_mode[mode].height);
846 }
847#endif
848 }
849 }
850 fmt->fmt.pix.width = gspca_dev->cam.cam_mode[mode].width;
851 fmt->fmt.pix.height = gspca_dev->cam.cam_mode[mode].height;
852 fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat)
853 * fmt->fmt.pix.width / 8;
854 frsz = fmt->fmt.pix.bytesperline * fmt->fmt.pix.height;
855 if (gspca_is_compressed(fmt->fmt.pix.pixelformat))
856 frsz = (frsz * comp_fac) / 100;
857 fmt->fmt.pix.sizeimage = frsz;
858 return mode; /* used when s_fmt */
859}
860
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300861static int vidioc_try_fmt_vid_cap(struct file *file,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300862 void *priv,
863 struct v4l2_format *fmt)
864{
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300865 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300866 int ret;
867
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300868 ret = try_fmt_vid_cap(gspca_dev, fmt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300869 if (ret < 0)
870 return ret;
871 return 0;
872}
873
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300874static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300875 struct v4l2_format *fmt)
876{
877 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300878 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300879
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300880#ifdef CONFIG_VIDEO_V4L1_COMPAT
881 /* if v4l1 got JPEG */
882 if (fmt->fmt.pix.pixelformat == 0
883 && gspca_dev->streaming) {
884 fmt->fmt.pix.width = gspca_dev->width;
885 fmt->fmt.pix.height = gspca_dev->height;
886 fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
887 return 0;
888 }
889#endif
Hans de Goedee2997a72008-04-23 08:09:12 -0300890 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
891 return -ERESTARTSYS;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300892
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300893 ret = try_fmt_vid_cap(gspca_dev, fmt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300894 if (ret < 0)
895 goto out;
896
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300897 if (gspca_dev->nframes != 0
898 && fmt->fmt.pix.sizeimage > gspca_dev->frsz) {
899 ret = -EINVAL;
900 goto out;
901 }
902
Jean-Francois Moine50a871f2008-06-30 19:47:33 -0300903 if (ret == gspca_dev->curr_mode) {
904 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300905 goto out; /* same mode */
Jean-Francois Moine50a871f2008-06-30 19:47:33 -0300906 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300907
908 if (gspca_dev->streaming) {
909 ret = -EBUSY;
910 goto out;
Hans de Goedee2997a72008-04-23 08:09:12 -0300911 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300912 gspca_dev->width = fmt->fmt.pix.width;
913 gspca_dev->height = fmt->fmt.pix.height;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300914 gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
915 gspca_dev->curr_mode = ret;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300916
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300917 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300918out:
919 mutex_unlock(&gspca_dev->queue_lock);
920 return ret;
921}
922
923static int dev_open(struct inode *inode, struct file *file)
924{
925 struct gspca_dev *gspca_dev;
926 int ret;
927
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300928 PDEBUG(D_STREAM, "%s open", current->comm);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300929 gspca_dev = (struct gspca_dev *) video_devdata(file);
Hans de Goedee2997a72008-04-23 08:09:12 -0300930 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
931 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300932 if (!gspca_dev->present) {
933 ret = -ENODEV;
934 goto out;
935 }
936
937 /* if not done yet, initialize the sensor */
938 if (gspca_dev->users == 0) {
Hans de Goedee2997a72008-04-23 08:09:12 -0300939 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
940 ret = -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300941 goto out;
Hans de Goedee2997a72008-04-23 08:09:12 -0300942 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300943 ret = gspca_dev->sd_desc->open(gspca_dev);
944 mutex_unlock(&gspca_dev->usb_lock);
945 if (ret != 0) {
946 PDEBUG(D_ERR|D_CONF, "init device failed %d", ret);
947 goto out;
948 }
Hans de Goedee2997a72008-04-23 08:09:12 -0300949 } else if (gspca_dev->users > 4) { /* (arbitrary value) */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300950 ret = -EBUSY;
951 goto out;
952 }
953 gspca_dev->users++;
954 file->private_data = gspca_dev;
Hans de Goeded646e702008-07-03 06:48:22 -0300955#ifdef CONFIG_VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300956 /* activate the v4l2 debug */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300957 if (gspca_debug & D_V4L2)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300958 gspca_dev->vdev.debug |= 3;
959 else
960 gspca_dev->vdev.debug &= ~3;
961#endif
962out:
963 mutex_unlock(&gspca_dev->queue_lock);
964 if (ret != 0)
965 PDEBUG(D_ERR|D_STREAM, "open failed err %d", ret);
966 else
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300967 PDEBUG(D_STREAM, "open done");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300968 return ret;
969}
970
971static int dev_close(struct inode *inode, struct file *file)
972{
973 struct gspca_dev *gspca_dev = file->private_data;
974
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300975 PDEBUG(D_STREAM, "%s close", current->comm);
Hans de Goedee2997a72008-04-23 08:09:12 -0300976 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
977 return -ERESTARTSYS;
978 gspca_dev->users--;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300979
980 /* if the file did capture, free the streaming resources */
981 if (gspca_dev->capt_file == file) {
982 mutex_lock(&gspca_dev->usb_lock);
983 if (gspca_dev->streaming)
984 gspca_stream_off(gspca_dev);
985 gspca_dev->sd_desc->close(gspca_dev);
986 mutex_unlock(&gspca_dev->usb_lock);
987 frame_free(gspca_dev);
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300988 gspca_dev->capt_file = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300989 gspca_dev->memory = GSPCA_MEMORY_NO;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300990 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300991 file->private_data = NULL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300992 mutex_unlock(&gspca_dev->queue_lock);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300993 PDEBUG(D_STREAM, "close done");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300994 return 0;
995}
996
997static int vidioc_querycap(struct file *file, void *priv,
998 struct v4l2_capability *cap)
999{
1000 struct gspca_dev *gspca_dev = priv;
1001
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001002 memset(cap, 0, sizeof *cap);
1003 strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
1004 strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card);
1005 strncpy(cap->bus_info, gspca_dev->dev->bus->bus_name,
1006 sizeof cap->bus_info);
1007 cap->version = DRIVER_VERSION_NUMBER;
1008 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
1009 | V4L2_CAP_STREAMING
1010 | V4L2_CAP_READWRITE;
1011 return 0;
1012}
1013
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001014/* the use of V4L2_CTRL_FLAG_NEXT_CTRL asks for the controls to be sorted */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001015static int vidioc_queryctrl(struct file *file, void *priv,
1016 struct v4l2_queryctrl *q_ctrl)
1017{
1018 struct gspca_dev *gspca_dev = priv;
1019 int i;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001020 u32 id;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001021
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001022 id = q_ctrl->id;
1023 if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
1024 id &= V4L2_CTRL_ID_MASK;
1025 id++;
1026 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
1027 if (id >= gspca_dev->sd_desc->ctrls[i].qctrl.id) {
1028 memcpy(q_ctrl,
1029 &gspca_dev->sd_desc->ctrls[i].qctrl,
1030 sizeof *q_ctrl);
1031 return 0;
1032 }
1033 }
1034 return -EINVAL;
1035 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001036 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001037 if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001038 memcpy(q_ctrl,
1039 &gspca_dev->sd_desc->ctrls[i].qctrl,
1040 sizeof *q_ctrl);
1041 return 0;
1042 }
1043 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001044 if (id >= V4L2_CID_BASE
1045 && id <= V4L2_CID_LASTP1) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001046 q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
1047 return 0;
1048 }
1049 return -EINVAL;
1050}
1051
1052static int vidioc_s_ctrl(struct file *file, void *priv,
1053 struct v4l2_control *ctrl)
1054{
1055 struct gspca_dev *gspca_dev = priv;
1056 struct ctrl *ctrls;
1057 int i, ret;
1058
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001059 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
1060 i < gspca_dev->sd_desc->nctrls;
1061 i++, ctrls++) {
1062 if (ctrl->id != ctrls->qctrl.id)
1063 continue;
1064 if (ctrl->value < ctrls->qctrl.minimum
1065 && ctrl->value > ctrls->qctrl.maximum)
1066 return -ERANGE;
1067 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
Hans de Goedee2997a72008-04-23 08:09:12 -03001068 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1069 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001070 ret = ctrls->set(gspca_dev, ctrl->value);
1071 mutex_unlock(&gspca_dev->usb_lock);
1072 return ret;
1073 }
1074 return -EINVAL;
1075}
1076
1077static int vidioc_g_ctrl(struct file *file, void *priv,
1078 struct v4l2_control *ctrl)
1079{
1080 struct gspca_dev *gspca_dev = priv;
1081
1082 struct ctrl *ctrls;
1083 int i, ret;
1084
1085 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
1086 i < gspca_dev->sd_desc->nctrls;
1087 i++, ctrls++) {
1088 if (ctrl->id != ctrls->qctrl.id)
1089 continue;
Hans de Goedee2997a72008-04-23 08:09:12 -03001090 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1091 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001092 ret = ctrls->get(gspca_dev, &ctrl->value);
1093 mutex_unlock(&gspca_dev->usb_lock);
1094 return ret;
1095 }
1096 return -EINVAL;
1097}
1098
1099static int vidioc_querymenu(struct file *file, void *priv,
1100 struct v4l2_querymenu *qmenu)
1101{
1102 struct gspca_dev *gspca_dev = priv;
1103
1104 if (!gspca_dev->sd_desc->querymenu)
1105 return -EINVAL;
1106 return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu);
1107}
1108
1109static int vidioc_enum_input(struct file *file, void *priv,
1110 struct v4l2_input *input)
1111{
1112 struct gspca_dev *gspca_dev = priv;
1113
1114 if (input->index != 0)
1115 return -EINVAL;
1116 memset(input, 0, sizeof *input);
1117 input->type = V4L2_INPUT_TYPE_CAMERA;
1118 strncpy(input->name, gspca_dev->sd_desc->name,
1119 sizeof input->name);
1120 return 0;
1121}
1122
1123static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1124{
1125 *i = 0;
1126 return 0;
1127}
1128
1129static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1130{
1131 if (i > 0)
1132 return -EINVAL;
1133 return (0);
1134}
1135
1136static int vidioc_reqbufs(struct file *file, void *priv,
1137 struct v4l2_requestbuffers *rb)
1138{
1139 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001140 int i, ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001141
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001142 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1143 return -EINVAL;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001144 switch (rb->memory) {
1145 case V4L2_MEMORY_MMAP:
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001146 case V4L2_MEMORY_USERPTR:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001147 break;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001148 default:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001149 return -EINVAL;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001150 }
Hans de Goedee2997a72008-04-23 08:09:12 -03001151 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1152 return -ERESTARTSYS;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001153
1154 for (i = 0; i < gspca_dev->nframes; i++) {
1155 if (gspca_dev->frame[i].vma_use_count) {
1156 ret = -EBUSY;
1157 goto out;
1158 }
1159 }
1160
1161 /* only one file may do capture */
1162 if ((gspca_dev->capt_file != 0 && gspca_dev->capt_file != file)
1163 || gspca_dev->streaming) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001164 ret = -EBUSY;
1165 goto out;
1166 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001167
1168 if (rb->count == 0) { /* unrequest? */
1169 frame_free(gspca_dev);
1170 gspca_dev->capt_file = 0;
1171 } else {
1172 gspca_dev->memory = rb->memory;
1173 ret = frame_alloc(gspca_dev, rb->count);
1174 if (ret == 0) {
1175 rb->count = gspca_dev->nframes;
1176 gspca_dev->capt_file = file;
1177 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001178 }
1179out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001180 mutex_unlock(&gspca_dev->queue_lock);
1181 PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count);
1182 return ret;
1183}
1184
1185static int vidioc_querybuf(struct file *file, void *priv,
1186 struct v4l2_buffer *v4l2_buf)
1187{
1188 struct gspca_dev *gspca_dev = priv;
1189 struct gspca_frame *frame;
1190
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001191 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1192 || v4l2_buf->index < 0
1193 || v4l2_buf->index >= gspca_dev->nframes)
1194 return -EINVAL;
1195
1196 frame = &gspca_dev->frame[v4l2_buf->index];
1197 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1198 return 0;
1199}
1200
1201static int vidioc_streamon(struct file *file, void *priv,
1202 enum v4l2_buf_type buf_type)
1203{
1204 struct gspca_dev *gspca_dev = priv;
1205 int ret;
1206
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001207 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1208 return -EINVAL;
Hans de Goedee2997a72008-04-23 08:09:12 -03001209 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1210 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001211 if (!gspca_dev->present) {
1212 ret = -ENODEV;
1213 goto out;
1214 }
1215 if (gspca_dev->nframes == 0) {
1216 ret = -EINVAL;
1217 goto out;
1218 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001219 if (gspca_dev->capt_file != file) {
1220 ret = -EINVAL;
1221 goto out;
1222 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001223 if (!gspca_dev->streaming) {
1224 ret = gspca_init_transfer(gspca_dev);
1225 if (ret < 0)
1226 goto out;
1227 }
Hans de Goeded646e702008-07-03 06:48:22 -03001228#ifdef CONFIG_VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001229 if (gspca_debug & D_STREAM) {
1230 PDEBUG_MODE("stream on OK",
1231 gspca_dev->pixfmt,
1232 gspca_dev->width,
1233 gspca_dev->height);
1234 }
1235#endif
Hans de Goedee2997a72008-04-23 08:09:12 -03001236 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001237out:
1238 mutex_unlock(&gspca_dev->queue_lock);
1239 return ret;
1240}
1241
1242static int vidioc_streamoff(struct file *file, void *priv,
1243 enum v4l2_buf_type buf_type)
1244{
1245 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001246 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001247
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001248 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1249 return -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001250 if (!gspca_dev->streaming)
1251 return 0;
1252 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1253 return -ERESTARTSYS;
1254 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
1255 ret = -ERESTARTSYS;
1256 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001257 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001258 if (gspca_dev->capt_file != file) {
1259 ret = -EINVAL;
1260 goto out2;
1261 }
1262 gspca_stream_off(gspca_dev);
1263 ret = 0;
1264out2:
1265 mutex_unlock(&gspca_dev->usb_lock);
1266out:
1267 mutex_unlock(&gspca_dev->queue_lock);
1268 return ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001269}
1270
1271static int vidioc_g_jpegcomp(struct file *file, void *priv,
1272 struct v4l2_jpegcompression *jpegcomp)
1273{
1274 struct gspca_dev *gspca_dev = priv;
1275 int ret;
1276
1277 if (!gspca_dev->sd_desc->get_jcomp)
1278 return -EINVAL;
Hans de Goedee2997a72008-04-23 08:09:12 -03001279 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1280 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001281 ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
1282 mutex_unlock(&gspca_dev->usb_lock);
1283 return ret;
1284}
1285
1286static int vidioc_s_jpegcomp(struct file *file, void *priv,
1287 struct v4l2_jpegcompression *jpegcomp)
1288{
1289 struct gspca_dev *gspca_dev = priv;
1290 int ret;
1291
Hans de Goedee2997a72008-04-23 08:09:12 -03001292 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1293 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001294 if (!gspca_dev->sd_desc->set_jcomp)
1295 return -EINVAL;
1296 ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
1297 mutex_unlock(&gspca_dev->usb_lock);
1298 return ret;
1299}
1300
1301static int vidioc_g_parm(struct file *filp, void *priv,
1302 struct v4l2_streamparm *parm)
1303{
1304 struct gspca_dev *gspca_dev = priv;
1305
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001306 memset(parm, 0, sizeof *parm);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001307 parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1308 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1309 return 0;
1310}
1311
1312static int vidioc_s_parm(struct file *filp, void *priv,
1313 struct v4l2_streamparm *parm)
1314{
1315 struct gspca_dev *gspca_dev = priv;
1316 int n;
1317
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001318 n = parm->parm.capture.readbuffers;
1319 if (n == 0 || n > GSPCA_MAX_FRAMES)
1320 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1321 else
1322 gspca_dev->nbufread = n;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001323 return 0;
1324}
1325
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001326static int vidioc_s_std(struct file *filp, void *priv,
1327 v4l2_std_id *parm)
1328{
1329 return 0;
1330}
1331
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001332#ifdef CONFIG_VIDEO_V4L1_COMPAT
1333static int vidiocgmbuf(struct file *file, void *priv,
1334 struct video_mbuf *mbuf)
1335{
1336 struct gspca_dev *gspca_dev = file->private_data;
1337 int i;
1338
1339 PDEBUG(D_STREAM, "cgmbuf");
1340 if (gspca_dev->nframes == 0) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001341 int ret;
1342
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001343 {
1344 struct v4l2_format fmt;
1345
1346 memset(&fmt, 0, sizeof fmt);
1347 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1348 i = gspca_dev->cam.nmodes - 1; /* highest mode */
1349 fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width;
1350 fmt.fmt.pix.height = gspca_dev->cam.cam_mode[i].height;
1351 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -03001352 ret = vidioc_s_fmt_vid_cap(file, priv, &fmt);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001353 if (ret != 0)
1354 return ret;
1355 }
1356 {
1357 struct v4l2_requestbuffers rb;
1358
1359 memset(&rb, 0, sizeof rb);
1360 rb.count = 4;
1361 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1362 rb.memory = V4L2_MEMORY_MMAP;
1363 ret = vidioc_reqbufs(file, priv, &rb);
1364 if (ret != 0)
1365 return ret;
1366 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001367 }
1368 mbuf->frames = gspca_dev->nframes;
1369 mbuf->size = gspca_dev->frsz * gspca_dev->nframes;
1370 for (i = 0; i < mbuf->frames; i++)
1371 mbuf->offsets[i] = gspca_dev->frame[i].v4l2_buf.m.offset;
1372 return 0;
1373}
1374#endif
1375
1376static int dev_mmap(struct file *file, struct vm_area_struct *vma)
1377{
1378 struct gspca_dev *gspca_dev = file->private_data;
1379 struct gspca_frame *frame = 0;
1380 struct page *page;
1381 unsigned long addr, start, size;
1382 int i, ret;
1383#ifdef CONFIG_VIDEO_V4L1_COMPAT
1384 int compat = 0;
1385#endif
1386
1387 start = vma->vm_start;
1388 size = vma->vm_end - vma->vm_start;
1389 PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size);
1390
Hans de Goedee2997a72008-04-23 08:09:12 -03001391 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1392 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001393 if (!gspca_dev->present) {
1394 ret = -ENODEV;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001395 goto out;
1396 }
1397 if (gspca_dev->capt_file != file) {
1398 ret = -EINVAL;
1399 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001400 }
1401
1402 for (i = 0; i < gspca_dev->nframes; ++i) {
1403 if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) {
1404 PDEBUG(D_STREAM, "mmap bad memory type");
1405 break;
1406 }
1407 if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT)
1408 == vma->vm_pgoff) {
1409 frame = &gspca_dev->frame[i];
1410 break;
1411 }
1412 }
1413 if (frame == 0) {
1414 PDEBUG(D_STREAM, "mmap no frame buffer found");
1415 ret = -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001416 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001417 }
1418#ifdef CONFIG_VIDEO_V4L1_COMPAT
1419 if (i == 0 && size == frame->v4l2_buf.length * gspca_dev->nframes)
1420 compat = 1;
1421 else
1422#endif
1423 if (size != frame->v4l2_buf.length) {
1424 PDEBUG(D_STREAM, "mmap bad size");
1425 ret = -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001426 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001427 }
1428
1429 /*
1430 * - VM_IO marks the area as being a mmaped region for I/O to a
1431 * device. It also prevents the region from being core dumped.
1432 */
1433 vma->vm_flags |= VM_IO;
1434
1435 addr = (unsigned long) frame->data;
1436 while (size > 0) {
1437 page = vmalloc_to_page((void *) addr);
1438 ret = vm_insert_page(vma, start, page);
1439 if (ret < 0)
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001440 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001441 start += PAGE_SIZE;
1442 addr += PAGE_SIZE;
1443 size -= PAGE_SIZE;
1444 }
1445
1446 vma->vm_ops = &gspca_vm_ops;
1447 vma->vm_private_data = frame;
1448 gspca_vm_open(vma);
1449#ifdef CONFIG_VIDEO_V4L1_COMPAT
1450 if (compat) {
1451/*fixme: ugly*/
1452 for (i = 1; i < gspca_dev->nframes; ++i)
1453 gspca_dev->frame[i].v4l2_buf.flags |=
1454 V4L2_BUF_FLAG_MAPPED;
1455 }
1456#endif
Hans de Goedee2997a72008-04-23 08:09:12 -03001457 ret = 0;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001458out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001459 mutex_unlock(&gspca_dev->queue_lock);
1460 return ret;
1461}
1462
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001463/*
1464 * wait for a video frame
1465 *
1466 * If a frame is ready, its index is returned.
1467 */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001468static int frame_wait(struct gspca_dev *gspca_dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001469 int nonblock_ing)
1470{
1471 struct gspca_frame *frame;
1472 int i, j, ret;
1473
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001474 /* if userptr, treat the awaiting URBs */
1475 if (gspca_dev->memory == V4L2_MEMORY_USERPTR)
1476 isoc_transfer(gspca_dev);
1477
1478 /* check if a frame is ready */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001479 i = gspca_dev->fr_o;
1480 j = gspca_dev->fr_queue[i];
1481 frame = &gspca_dev->frame[j];
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001482 if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) {
1483 atomic_dec(&gspca_dev->nevent);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001484 goto ok;
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001485 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001486 if (nonblock_ing) /* no frame yet */
1487 return -EAGAIN;
1488
1489 /* wait till a frame is ready */
1490 for (;;) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001491 ret = wait_event_interruptible_timeout(gspca_dev->wq,
1492 atomic_read(&gspca_dev->nevent) > 0,
1493 msecs_to_jiffies(3000));
1494 if (ret <= 0) {
1495 if (ret < 0)
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001496 return ret; /* interrupt */
1497 return -EIO; /* timeout */
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001498 }
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001499 atomic_dec(&gspca_dev->nevent);
Hans de Goedee2997a72008-04-23 08:09:12 -03001500 if (!gspca_dev->streaming || !gspca_dev->present)
1501 return -EIO;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001502 if (gspca_dev->memory == V4L2_MEMORY_USERPTR)
1503 isoc_transfer(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001504 i = gspca_dev->fr_o;
1505 j = gspca_dev->fr_queue[i];
1506 frame = &gspca_dev->frame[j];
1507 if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1508 break;
1509 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001510ok:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001511 gspca_dev->fr_o = (i + 1) % gspca_dev->nframes;
1512 PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d",
1513 gspca_dev->fr_q,
1514 gspca_dev->fr_i,
1515 gspca_dev->fr_o);
Hans de Goedee2997a72008-04-23 08:09:12 -03001516
1517 if (gspca_dev->sd_desc->dq_callback)
1518 gspca_dev->sd_desc->dq_callback(gspca_dev);
1519
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001520 return j;
1521}
1522
1523/*
1524 * dequeue a video buffer
1525 *
1526 * If nonblock_ing is false, block until a buffer is available.
1527 */
1528static int vidioc_dqbuf(struct file *file, void *priv,
1529 struct v4l2_buffer *v4l2_buf)
1530{
1531 struct gspca_dev *gspca_dev = priv;
1532 struct gspca_frame *frame;
1533 int i, ret;
1534
1535 PDEBUG(D_FRAM, "dqbuf");
1536 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1537 || (v4l2_buf->memory != V4L2_MEMORY_MMAP
1538 && v4l2_buf->memory != V4L2_MEMORY_USERPTR))
1539 return -EINVAL;
1540 if (!gspca_dev->streaming)
1541 return -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001542 if (gspca_dev->capt_file != file) {
1543 ret = -EINVAL;
1544 goto out;
1545 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001546
1547 /* only one read */
1548 if (mutex_lock_interruptible(&gspca_dev->read_lock))
1549 return -ERESTARTSYS;
1550
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001551 ret = frame_wait(gspca_dev, file->f_flags & O_NONBLOCK);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001552 if (ret < 0)
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001553 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001554 i = ret; /* frame index */
1555 frame = &gspca_dev->frame[i];
1556 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
1557 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1558 PDEBUG(D_FRAM, "dqbuf %d", i);
1559 ret = 0;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001560out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001561 mutex_unlock(&gspca_dev->read_lock);
1562 return ret;
1563}
1564
1565/*
1566 * queue a video buffer
1567 *
1568 * Attempting to queue a buffer that has already been
1569 * queued will return -EINVAL.
1570 */
1571static int vidioc_qbuf(struct file *file, void *priv,
1572 struct v4l2_buffer *v4l2_buf)
1573{
1574 struct gspca_dev *gspca_dev = priv;
1575 struct gspca_frame *frame;
1576 int i, index, ret;
1577
1578 PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index);
1579 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1580 return -EINVAL;
1581
1582 index = v4l2_buf->index;
1583 if ((unsigned) index >= gspca_dev->nframes) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001584 PDEBUG(D_FRAM,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001585 "qbuf idx %d >= %d", index, gspca_dev->nframes);
1586 return -EINVAL;
1587 }
1588 frame = &gspca_dev->frame[index];
1589
1590 if (v4l2_buf->memory != frame->v4l2_buf.memory) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001591 PDEBUG(D_FRAM, "qbuf bad memory type");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001592 return -EINVAL;
1593 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001594 if (gspca_dev->capt_file != file)
1595 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001596
Hans de Goedee2997a72008-04-23 08:09:12 -03001597 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1598 return -ERESTARTSYS;
1599
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001600 if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) {
1601 PDEBUG(D_FRAM, "qbuf bad state");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001602 ret = -EINVAL;
1603 goto out;
1604 }
1605
1606 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001607/* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001608
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001609 if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001610 frame->data = frame->data_end =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001611 (__u8 *) v4l2_buf->m.userptr;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001612 frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
1613 frame->v4l2_buf.length = v4l2_buf->length;
1614 }
1615
1616 /* put the buffer in the 'queued' queue */
1617 i = gspca_dev->fr_q;
1618 gspca_dev->fr_queue[i] = index;
1619 gspca_dev->fr_q = (i + 1) % gspca_dev->nframes;
1620 PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d",
1621 gspca_dev->fr_q,
1622 gspca_dev->fr_i,
1623 gspca_dev->fr_o);
1624
1625 v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
1626 v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE;
1627 ret = 0;
1628out:
1629 mutex_unlock(&gspca_dev->queue_lock);
1630 return ret;
1631}
1632
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001633/*
1634 * allocate the resources for read()
1635 */
1636static int read_alloc(struct gspca_dev *gspca_dev,
1637 struct file *file)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001638{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001639 struct v4l2_buffer v4l2_buf;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001640 int i, ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001641
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001642 PDEBUG(D_STREAM, "read alloc");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001643 if (gspca_dev->nframes == 0) {
1644 struct v4l2_requestbuffers rb;
1645
1646 memset(&rb, 0, sizeof rb);
1647 rb.count = gspca_dev->nbufread;
1648 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1649 rb.memory = V4L2_MEMORY_MMAP;
1650 ret = vidioc_reqbufs(file, gspca_dev, &rb);
1651 if (ret != 0) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001652 PDEBUG(D_STREAM, "read reqbuf err %d", ret);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001653 return ret;
1654 }
1655 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1656 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1657 v4l2_buf.memory = V4L2_MEMORY_MMAP;
1658 for (i = 0; i < gspca_dev->nbufread; i++) {
1659 v4l2_buf.index = i;
1660/*fixme: ugly!*/
1661 gspca_dev->frame[i].v4l2_buf.flags |=
1662 V4L2_BUF_FLAG_MAPPED;
1663 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1664 if (ret != 0) {
1665 PDEBUG(D_STREAM, "read qbuf err: %d", ret);
1666 return ret;
1667 }
1668 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001669 gspca_dev->memory = GSPCA_MEMORY_READ;
1670 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001671
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001672 /* start streaming */
1673 ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE);
1674 if (ret != 0)
1675 PDEBUG(D_STREAM, "read streamon err %d", ret);
1676 return ret;
1677}
1678
1679static unsigned int dev_poll(struct file *file, poll_table *wait)
1680{
1681 struct gspca_dev *gspca_dev = file->private_data;
1682 int i, ret;
1683
1684 PDEBUG(D_FRAM, "poll");
1685
1686 poll_wait(file, &gspca_dev->wq, wait);
1687 if (!gspca_dev->present)
1688 return POLLERR;
1689
1690 /* if not streaming, the user would use read() */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001691 if (!gspca_dev->streaming) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001692 if (gspca_dev->memory != GSPCA_MEMORY_NO) {
1693 ret = POLLERR; /* not the 1st time */
1694 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001695 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001696 ret = read_alloc(gspca_dev, file);
1697 if (ret != 0) {
1698 ret = POLLERR;
1699 goto out;
1700 }
1701 }
1702
1703 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0)
1704 return POLLERR;
1705 if (!gspca_dev->present) {
1706 ret = POLLERR;
1707 goto out;
1708 }
1709
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001710 /* if userptr, treat the awaiting URBs */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001711 if (gspca_dev->memory == V4L2_MEMORY_USERPTR
1712 && gspca_dev->capt_file == file)
1713 isoc_transfer(gspca_dev);
1714
1715 i = gspca_dev->fr_o;
1716 i = gspca_dev->fr_queue[i];
1717 if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1718 ret = POLLIN | POLLRDNORM; /* something to read */
1719 else
1720 ret = 0;
1721out:
1722 mutex_unlock(&gspca_dev->queue_lock);
1723 return ret;
1724}
1725
1726static ssize_t dev_read(struct file *file, char __user *data,
1727 size_t count, loff_t *ppos)
1728{
1729 struct gspca_dev *gspca_dev = file->private_data;
1730 struct gspca_frame *frame;
1731 struct v4l2_buffer v4l2_buf;
1732 struct timeval timestamp;
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001733 int n, ret, ret2;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001734
1735 PDEBUG(D_FRAM, "read (%d)", count);
1736 if (!gspca_dev->present)
1737 return -ENODEV;
1738 switch (gspca_dev->memory) {
1739 case GSPCA_MEMORY_NO: /* first time */
1740 ret = read_alloc(gspca_dev, file);
1741 if (ret != 0)
1742 return ret;
1743 break;
1744 case GSPCA_MEMORY_READ:
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001745 if (gspca_dev->capt_file == file)
1746 break;
1747 /* fall thru */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001748 default:
1749 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001750 }
1751
1752 /* get a frame */
1753 jiffies_to_timeval(get_jiffies_64(), &timestamp);
1754 timestamp.tv_sec--;
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001755 n = 2;
1756 for (;;) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001757 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1758 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1759 v4l2_buf.memory = V4L2_MEMORY_MMAP;
1760 ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf);
1761 if (ret != 0) {
1762 PDEBUG(D_STREAM, "read dqbuf err %d", ret);
1763 return ret;
1764 }
1765
1766 /* if the process slept for more than 1 second,
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001767 * get anewer frame */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001768 frame = &gspca_dev->frame[v4l2_buf.index];
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001769 if (--n < 0)
1770 break; /* avoid infinite loop */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001771 if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
1772 break;
1773 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1774 if (ret != 0) {
1775 PDEBUG(D_STREAM, "read qbuf err %d", ret);
1776 return ret;
1777 }
1778 }
1779
1780 /* copy the frame */
1781 if (count < frame->v4l2_buf.bytesused) {
1782 PDEBUG(D_STREAM, "read bad count: %d < %d",
1783 count, frame->v4l2_buf.bytesused);
1784/*fixme: special errno?*/
1785 ret = -EINVAL;
1786 goto out;
1787 }
1788 count = frame->v4l2_buf.bytesused;
1789 ret = copy_to_user(data, frame->data, count);
1790 if (ret != 0) {
1791 PDEBUG(D_ERR|D_STREAM,
1792 "read cp to user lack %d / %d", ret, count);
1793 ret = -EFAULT;
1794 goto out;
1795 }
1796 ret = count;
1797out:
1798 /* in each case, requeue the buffer */
1799 ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1800 if (ret2 != 0)
1801 return ret2;
1802 return ret;
1803}
1804
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001805static void dev_release(struct video_device *vfd)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001806{
1807 /* nothing */
1808}
1809
1810static struct file_operations dev_fops = {
1811 .owner = THIS_MODULE,
1812 .open = dev_open,
1813 .release = dev_close,
1814 .read = dev_read,
1815 .mmap = dev_mmap,
1816 .ioctl = video_ioctl2,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001817#ifdef CONFIG_COMPAT
1818 .compat_ioctl = v4l_compat_ioctl32,
1819#endif
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001820 .llseek = no_llseek,
1821 .poll = dev_poll,
1822};
1823
1824static struct video_device gspca_template = {
1825 .name = "gspca main driver",
1826 .type = VID_TYPE_CAPTURE,
1827 .fops = &dev_fops,
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001828 .release = dev_release, /* mandatory */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001829 .minor = -1,
1830 .vidioc_querycap = vidioc_querycap,
1831 .vidioc_dqbuf = vidioc_dqbuf,
1832 .vidioc_qbuf = vidioc_qbuf,
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -03001833 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1834 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1835 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1836 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001837 .vidioc_streamon = vidioc_streamon,
1838 .vidioc_queryctrl = vidioc_queryctrl,
1839 .vidioc_g_ctrl = vidioc_g_ctrl,
1840 .vidioc_s_ctrl = vidioc_s_ctrl,
1841 .vidioc_querymenu = vidioc_querymenu,
1842 .vidioc_enum_input = vidioc_enum_input,
1843 .vidioc_g_input = vidioc_g_input,
1844 .vidioc_s_input = vidioc_s_input,
1845 .vidioc_reqbufs = vidioc_reqbufs,
1846 .vidioc_querybuf = vidioc_querybuf,
1847 .vidioc_streamoff = vidioc_streamoff,
1848 .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
1849 .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
1850 .vidioc_g_parm = vidioc_g_parm,
1851 .vidioc_s_parm = vidioc_s_parm,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001852 .vidioc_s_std = vidioc_s_std,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001853#ifdef CONFIG_VIDEO_V4L1_COMPAT
1854 .vidiocgmbuf = vidiocgmbuf,
1855#endif
1856};
1857
1858/*
1859 * probe and create a new gspca device
1860 *
1861 * This function must be called by the sub-driver when it is
1862 * called for probing a new device.
1863 */
1864int gspca_dev_probe(struct usb_interface *intf,
1865 const struct usb_device_id *id,
1866 const struct sd_desc *sd_desc,
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001867 int dev_size,
1868 struct module *module)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001869{
1870 struct usb_interface_descriptor *interface;
1871 struct gspca_dev *gspca_dev;
1872 struct usb_device *dev = interface_to_usbdev(intf);
1873 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001874
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001875 PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001876
1877 /* we don't handle multi-config cameras */
1878 if (dev->descriptor.bNumConfigurations != 1)
1879 return -ENODEV;
1880 interface = &intf->cur_altsetting->desc;
1881 if (interface->bInterfaceNumber > 0)
1882 return -ENODEV;
1883
1884 /* create the device */
1885 if (dev_size < sizeof *gspca_dev)
1886 dev_size = sizeof *gspca_dev;
1887 gspca_dev = kzalloc(dev_size, GFP_KERNEL);
1888 if (gspca_dev == NULL) {
1889 err("couldn't kzalloc gspca struct");
1890 return -EIO;
1891 }
1892 gspca_dev->dev = dev;
1893 gspca_dev->iface = interface->bInterfaceNumber;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001894 gspca_dev->nbalt = intf->num_altsetting;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001895 gspca_dev->sd_desc = sd_desc;
1896/* gspca_dev->users = 0; (done by kzalloc) */
1897 gspca_dev->nbufread = 2;
1898
1899 /* configure the subdriver */
1900 ret = gspca_dev->sd_desc->config(gspca_dev, id);
1901 if (ret < 0)
1902 goto out;
1903 ret = gspca_set_alt0(gspca_dev);
1904 if (ret < 0)
1905 goto out;
1906 gspca_set_default_mode(gspca_dev);
1907
1908 mutex_init(&gspca_dev->usb_lock);
1909 mutex_init(&gspca_dev->read_lock);
1910 mutex_init(&gspca_dev->queue_lock);
1911 init_waitqueue_head(&gspca_dev->wq);
1912
1913 /* init video stuff */
1914 memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
1915 gspca_dev->vdev.dev = &dev->dev;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001916 memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops);
1917 gspca_dev->vdev.fops = &gspca_dev->fops;
1918 gspca_dev->fops.owner = module; /* module protection */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001919 ret = video_register_device(&gspca_dev->vdev,
1920 VFL_TYPE_GRABBER,
1921 video_nr);
1922 if (ret < 0) {
1923 err("video_register_device err %d", ret);
1924 goto out;
1925 }
1926
1927 gspca_dev->present = 1;
1928 usb_set_intfdata(intf, gspca_dev);
1929 PDEBUG(D_PROBE, "probe ok");
1930 return 0;
1931out:
1932 kfree(gspca_dev);
1933 return ret;
1934}
1935EXPORT_SYMBOL(gspca_dev_probe);
1936
1937/*
1938 * USB disconnection
1939 *
1940 * This function must be called by the sub-driver
1941 * when the device disconnects, after the specific resources are freed.
1942 */
1943void gspca_disconnect(struct usb_interface *intf)
1944{
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001945 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001946
1947 if (!gspca_dev)
1948 return;
1949 gspca_dev->present = 0;
Hans de Goedee2997a72008-04-23 08:09:12 -03001950 mutex_lock(&gspca_dev->queue_lock);
1951 mutex_lock(&gspca_dev->usb_lock);
1952 gspca_dev->streaming = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001953 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001954 mutex_unlock(&gspca_dev->usb_lock);
Hans de Goedee2997a72008-04-23 08:09:12 -03001955 mutex_unlock(&gspca_dev->queue_lock);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001956 while (gspca_dev->users != 0) { /* wait until fully closed */
1957 atomic_inc(&gspca_dev->nevent);
1958 wake_up_interruptible(&gspca_dev->wq); /* wake processes */
1959 schedule();
1960 }
1961/* We don't want people trying to open up the device */
1962 video_unregister_device(&gspca_dev->vdev);
1963/* Free the memory */
1964 kfree(gspca_dev);
1965 PDEBUG(D_PROBE, "disconnect complete");
1966}
1967EXPORT_SYMBOL(gspca_disconnect);
1968
1969/* -- module insert / remove -- */
1970static int __init gspca_init(void)
1971{
1972 info("main v%s registered", version);
1973 return 0;
1974}
1975static void __exit gspca_exit(void)
1976{
1977 info("main deregistered");
1978}
1979
1980module_init(gspca_init);
1981module_exit(gspca_exit);
1982
Hans de Goeded646e702008-07-03 06:48:22 -03001983#ifdef CONFIG_VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001984module_param_named(debug, gspca_debug, int, 0644);
1985MODULE_PARM_DESC(debug,
1986 "Debug (bit) 0x01:error 0x02:probe 0x04:config"
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001987 " 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout"
1988 " 0x0100: v4l2");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001989#endif
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001990module_param(comp_fac, int, 0644);
1991MODULE_PARM_DESC(comp_fac,
1992 "Buffer size ratio when compressed in percent");