blob: 5583c53e48631e9fbdbf3c87b9023f753ec0c35c [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>
31#include <asm/io.h>
32#include <asm/page.h>
33#include <asm/uaccess.h>
34#include <linux/jiffies.h>
35
36#include "gspca.h"
37
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030038#undef CONFIG_VIDEO_V4L1_COMPAT
Jean-Francois Moined43fa322008-06-12 10:58:58 -030039
40/* global values */
41#define DEF_NURBS 2 /* default number of URBs (mmap) */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030042#define USR_NURBS 5 /* default number of URBs (userptr) */
Jean-Francois Moined43fa322008-06-12 10:58:58 -030043
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030044MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
45MODULE_DESCRIPTION("GSPCA USB Camera Driver");
46MODULE_LICENSE("GPL");
47
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030048#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
49static const char version[] = "2.1.0";
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030050
51static int video_nr = -1;
52
53static int comp_fac = 30; /* Buffer size ratio when compressed in % */
54
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030055#ifdef VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030056int gspca_debug = D_ERR | D_PROBE;
57EXPORT_SYMBOL(gspca_debug);
58
59static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
60{
61 if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') {
62 PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d",
63 txt,
64 pixfmt & 0xff,
65 (pixfmt >> 8) & 0xff,
66 (pixfmt >> 16) & 0xff,
67 pixfmt >> 24,
68 w, h);
69 } else {
70 PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d",
71 txt,
72 pixfmt,
73 w, h);
74 }
75}
76#else
77#define PDEBUG_MODE(txt, pixfmt, w, h)
78#endif
79
Jean-Francois Moined43fa322008-06-12 10:58:58 -030080/* specific memory types - !! should different from V4L2_MEMORY_xxx */
81#define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */
82#define GSPCA_MEMORY_READ 7
83
Jean-Francois Moined43fa322008-06-12 10:58:58 -030084#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)
Jean-Francois Moined43fa322008-06-12 10:58:58 -030085
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030086/*
87 * VMA operations.
88 */
89static void gspca_vm_open(struct vm_area_struct *vma)
90{
91 struct gspca_frame *frame = vma->vm_private_data;
92
93 frame->vma_use_count++;
94 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_MAPPED;
95}
96
97static void gspca_vm_close(struct vm_area_struct *vma)
98{
99 struct gspca_frame *frame = vma->vm_private_data;
100
101 if (--frame->vma_use_count <= 0)
102 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_MAPPED;
103}
104
105static struct vm_operations_struct gspca_vm_ops = {
106 .open = gspca_vm_open,
107 .close = gspca_vm_close,
108};
109
110/*
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300111 * fill a video frame from an URB and resubmit
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300112 */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300113static void fill_frame(struct gspca_dev *gspca_dev,
114 struct urb *urb)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300115{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300116 struct gspca_frame *frame;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300117 __u8 *data; /* address of data in the iso message */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300118 int i, j, len, st;
119 cam_pkt_op pkt_scan;
120
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300121 if (urb->status != 0) {
122 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
123 return; /* disconnection ? */
124 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300125 pkt_scan = gspca_dev->sd_desc->pkt_scan;
126 for (i = 0; i < urb->number_of_packets; i++) {
127
128 /* check the availability of the frame buffer */
129 j = gspca_dev->fr_i;
130 j = gspca_dev->fr_queue[j];
131 frame = &gspca_dev->frame[j];
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300132 if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300133 != V4L2_BUF_FLAG_QUEUED) {
134 gspca_dev->last_packet_type = DISCARD_PACKET;
135 break;
136 }
137
138 /* check the packet status and length */
139 len = urb->iso_frame_desc[i].actual_length;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300140 if (len == 0)
141 continue;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300142 st = urb->iso_frame_desc[i].status;
143 if (st) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300144 PDEBUG(D_ERR,
145 "ISOC data error: [%d] len=%d, status=%d",
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300146 i, len, st);
147 gspca_dev->last_packet_type = DISCARD_PACKET;
148 continue;
149 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300150
151 /* let the packet be analyzed by the subdriver */
152 PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
153 i, urb->iso_frame_desc[i].offset, len);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300154 data = (__u8 *) urb->transfer_buffer
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300155 + urb->iso_frame_desc[i].offset;
156 pkt_scan(gspca_dev, frame, data, len);
157 }
158
159 /* resubmit the URB */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300160/*fixme: don't do that when userptr and too many URBs sent*/
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300161 urb->status = 0;
162 st = usb_submit_urb(urb, GFP_ATOMIC);
163 if (st < 0)
164 PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", st);
165}
166
167/*
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300168 * ISOC message interrupt from the USB device
169 *
170 * Analyse each packet and call the subdriver for copy
171 * to the frame buffer.
172 *
173 * There are 2 functions:
174 * - the first one (isoc_irq_mmap) is used when the application
175 * buffers are mapped. The frame detection and copy is done
176 * at interrupt level.
177 * - the second one (isoc_irq_user) is used when the application
178 * buffers are in user space (userptr). The frame detection
179 * and copy is done by the application.
180 */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300181static void isoc_irq_mmap(struct urb *urb
182)
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300183{
184 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
185
186 PDEBUG(D_PACK, "isoc irq mmap");
187 if (!gspca_dev->streaming)
188 return;
189 fill_frame(gspca_dev, urb);
190}
191
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300192static void isoc_irq_user(struct urb *urb
193)
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300194{
195 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
196 int i;
197
198 PDEBUG(D_PACK, "isoc irq user");
199 if (!gspca_dev->streaming)
200 return;
201
202 i = gspca_dev->urb_in % gspca_dev->nurbs;
203 if (urb != gspca_dev->urb[i]) {
204 PDEBUG(D_ERR|D_PACK, "urb out of sequence");
205 return; /* should never occur */
206 }
207
208 gspca_dev->urb_in++;
209 atomic_inc(&gspca_dev->nevent); /* new event */
210 wake_up_interruptible(&gspca_dev->wq);
211/*fixme: submit a new URBs until urb_in == urb_out (% nurbs)*/
212}
213
214/*
215 * treat the isoc messages
216 *
217 * This routine is called by the application (case userptr).
218 */
219static void isoc_transfer(struct gspca_dev *gspca_dev)
220{
221 struct urb *urb;
222 int i;
223
224 for (;;) {
225 i = gspca_dev->urb_out;
226 PDEBUG(D_PACK, "isoc transf i:%d o:%d", gspca_dev->urb_in, i);
227 if (i == gspca_dev->urb_in) /* isoc message to read */
228 break; /* no (more) message */
229 atomic_dec(&gspca_dev->nevent);
230/*PDEBUG(D_PACK, "isoc_trf nevent: %d", atomic_read(&gspca_dev->nevent));*/
231 gspca_dev->urb_out = i + 1; /* message treated */
232 urb = gspca_dev->urb[i % gspca_dev->nurbs];
233 fill_frame(gspca_dev, urb);
234 }
235}
236
237/*
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300238 * add data to the current frame
239 *
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300240 * This function is called by the subdrivers at interrupt level
241 * or user level.
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300242 * To build a frame, these ones must add
243 * - one FIRST_PACKET
244 * - 0 or many INTER_PACKETs
245 * - one LAST_PACKET
246 * DISCARD_PACKET invalidates the whole frame.
247 * On LAST_PACKET, a new frame is returned.
248 */
249struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
250 int packet_type,
251 struct gspca_frame *frame,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300252 __u8 *data,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300253 int len)
254{
255 int i, j;
256
Hans de Goedee2997a72008-04-23 08:09:12 -0300257 PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300258
259 /* when start of a new frame, if the current frame buffer
260 * is not queued, discard the whole frame */
261 if (packet_type == FIRST_PACKET) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300262 if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
263 != V4L2_BUF_FLAG_QUEUED) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300264 gspca_dev->last_packet_type = DISCARD_PACKET;
265 return frame;
266 }
267 frame->data_end = frame->data;
268 jiffies_to_timeval(get_jiffies_64(),
269 &frame->v4l2_buf.timestamp);
270 frame->v4l2_buf.sequence = ++gspca_dev->sequence;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300271 } else if (gspca_dev->last_packet_type == DISCARD_PACKET) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300272 return frame;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300273 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300274
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300275 /* append the packet to the frame buffer */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300276 if (len > 0) {
277 if (frame->data_end - frame->data + len
278 > frame->v4l2_buf.length) {
279 PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d",
280 frame->data_end - frame->data + len,
281 frame->v4l2_buf.length);
282 packet_type = DISCARD_PACKET;
283 } else {
284 if (frame->v4l2_buf.memory != V4L2_MEMORY_USERPTR)
285 memcpy(frame->data_end, data, len);
286 else
287 copy_to_user(frame->data_end, data, len);
288 frame->data_end += len;
289 }
290 }
291 gspca_dev->last_packet_type = packet_type;
292
293 /* if last packet, wake the application and advance in the queue */
294 if (packet_type == LAST_PACKET) {
295 frame->v4l2_buf.bytesused = frame->data_end - frame->data;
296 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
297 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
298 atomic_inc(&gspca_dev->nevent);
299 wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300300 i = (gspca_dev->fr_i + 1) % gspca_dev->nframes;
301 gspca_dev->fr_i = i;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300302 PDEBUG(D_FRAM, "frame complete len:%d q:%d i:%d o:%d",
303 frame->v4l2_buf.bytesused,
304 gspca_dev->fr_q,
305 i,
306 gspca_dev->fr_o);
307 j = gspca_dev->fr_queue[i];
308 frame = &gspca_dev->frame[j];
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300309 }
310 return frame;
311}
312EXPORT_SYMBOL(gspca_frame_add);
313
314static int gspca_is_compressed(__u32 format)
315{
316 switch (format) {
317 case V4L2_PIX_FMT_MJPEG:
318 case V4L2_PIX_FMT_JPEG:
319 return 1;
320 }
321 return 0;
322}
323
324static void *rvmalloc(unsigned long size)
325{
326 void *mem;
327 unsigned long adr;
328
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300329/* size = PAGE_ALIGN(size); (already done) */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300330 mem = vmalloc_32(size);
331 if (mem != 0) {
332 memset(mem, 0, size);
333 adr = (unsigned long) mem;
334 while ((long) size > 0) {
335 SetPageReserved(vmalloc_to_page((void *) adr));
336 adr += PAGE_SIZE;
337 size -= PAGE_SIZE;
338 }
339 }
340 return mem;
341}
342
343static void rvfree(void *mem, unsigned long size)
344{
345 unsigned long adr;
346
347 if (!mem)
348 return;
349 adr = (unsigned long) mem;
350 while ((long) size > 0) {
351 ClearPageReserved(vmalloc_to_page((void *) adr));
352 adr += PAGE_SIZE;
353 size -= PAGE_SIZE;
354 }
355 vfree(mem);
356}
357
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300358static __u32 get_v4l2_depth(__u32 pixfmt)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300359{
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300360 switch (pixfmt) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300361/* case V4L2_PIX_FMT_BGR32:
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300362 case V4L2_PIX_FMT_RGB32:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300363 return 32; */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300364 case V4L2_PIX_FMT_RGB24: /* 'RGB3' */
365 case V4L2_PIX_FMT_BGR24:
366 return 24;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300367/* case V4L2_PIX_FMT_RGB565: * 'RGBP' */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300368 case V4L2_PIX_FMT_YUYV: /* 'YUYV' packed 4.2.2 */
369 case V4L2_PIX_FMT_YYUV: /* 'YYUV' */
370 return 16;
371 case V4L2_PIX_FMT_YUV420: /* 'YU12' planar 4.2.0 */
372 return 12;
373 case V4L2_PIX_FMT_MJPEG:
374 case V4L2_PIX_FMT_JPEG:
375 case V4L2_PIX_FMT_SBGGR8: /* 'BA81' Bayer */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300376 case V4L2_PIX_FMT_SN9C10X: /* 'S910' SN9C10x compression */
377 case V4L2_PIX_FMT_SPCA501: /* 'S501' YUYV per line */
378 case V4L2_PIX_FMT_SPCA561: /* 'S561' compressed BGGR bayer */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300379 return 8;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300380 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300381 PDEBUG(D_ERR|D_CONF, "Unknown pixel format %c%c%c%c",
382 pixfmt & 0xff,
383 (pixfmt >> 8) & 0xff,
384 (pixfmt >> 16) & 0xff,
385 pixfmt >> 24);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300386 return 24;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300387}
388
389static int gspca_get_buff_size(struct gspca_dev *gspca_dev)
390{
391 unsigned int size;
392
393 size = gspca_dev->width * gspca_dev->height
394 * get_v4l2_depth(gspca_dev->pixfmt) / 8;
395 if (!size)
396 return -ENOMEM;
397 return size;
398}
399
400static int frame_alloc(struct gspca_dev *gspca_dev,
401 unsigned int count)
402{
403 struct gspca_frame *frame;
404 unsigned int frsz;
405 int i;
406
407 frsz = gspca_get_buff_size(gspca_dev);
408 if (frsz < 0)
409 return frsz;
410 PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300411 if (count > GSPCA_MAX_FRAMES)
412 count = GSPCA_MAX_FRAMES;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300413 /* if compressed (JPEG), reduce the buffer size */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300414 if (gspca_is_compressed(gspca_dev->pixfmt))
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300415 frsz = (frsz * comp_fac) / 100 + 600; /* (+ JPEG header sz) */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300416 frsz = PAGE_ALIGN(frsz);
417 PDEBUG(D_STREAM, "new fr_sz: %d", frsz);
418 gspca_dev->frsz = frsz;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300419 if (gspca_dev->memory == V4L2_MEMORY_MMAP) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300420 gspca_dev->frbuf = rvmalloc(frsz * count);
421 if (!gspca_dev->frbuf) {
422 err("frame alloc failed");
423 return -ENOMEM;
424 }
425 }
426 gspca_dev->nframes = count;
427 for (i = 0; i < count; i++) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300428 frame = &gspca_dev->frame[i];
429 frame->v4l2_buf.index = i;
430 frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
431 frame->v4l2_buf.flags = 0;
432 frame->v4l2_buf.field = V4L2_FIELD_NONE;
433 frame->v4l2_buf.length = frsz;
434 frame->v4l2_buf.memory = gspca_dev->memory;
435 frame->v4l2_buf.sequence = 0;
436 if (gspca_dev->memory == V4L2_MEMORY_MMAP) {
437 frame->data = frame->data_end =
438 gspca_dev->frbuf + i * frsz;
439 frame->v4l2_buf.m.offset = i * frsz;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300440 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300441 }
442 gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
443 gspca_dev->last_packet_type = DISCARD_PACKET;
444 gspca_dev->sequence = 0;
445 atomic_set(&gspca_dev->nevent, 0);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300446 return 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300447}
448
449static void frame_free(struct gspca_dev *gspca_dev)
450{
451 int i;
452
453 PDEBUG(D_STREAM, "frame free");
454 if (gspca_dev->frbuf != 0) {
455 rvfree(gspca_dev->frbuf,
456 gspca_dev->nframes * gspca_dev->frsz);
457 gspca_dev->frbuf = NULL;
458 for (i = 0; i < gspca_dev->nframes; i++)
459 gspca_dev->frame[i].data = NULL;
460 }
461 gspca_dev->nframes = 0;
462}
463
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300464static void destroy_urbs(struct gspca_dev *gspca_dev)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300465{
466 struct urb *urb;
467 unsigned int i;
468
469 PDEBUG(D_STREAM, "kill transfer");
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300470 for (i = 0; i < MAX_NURBS; ++i) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300471 urb = gspca_dev->urb[i];
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300472 if (urb == NULL)
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300473 break;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300474
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300475 gspca_dev->urb[i] = NULL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300476 usb_kill_urb(urb);
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300477 if (urb->transfer_buffer != 0)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300478 usb_buffer_free(gspca_dev->dev,
479 urb->transfer_buffer_length,
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300480 urb->transfer_buffer,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300481 urb->transfer_dma);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300482 usb_free_urb(urb);
483 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300484}
485
486/*
487 * search an input isochronous endpoint in an alternate setting
488 */
489static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
490 __u8 epaddr)
491{
492 struct usb_host_endpoint *ep;
493 int i, attr;
494
495 epaddr |= USB_DIR_IN;
496 for (i = 0; i < alt->desc.bNumEndpoints; i++) {
497 ep = &alt->endpoint[i];
498 if (ep->desc.bEndpointAddress == epaddr) {
499 attr = ep->desc.bmAttributes
500 & USB_ENDPOINT_XFERTYPE_MASK;
501 if (attr == USB_ENDPOINT_XFER_ISOC)
502 return ep;
503 break;
504 }
505 }
506 return NULL;
507}
508
509/*
510 * search an input isochronous endpoint
511 *
512 * The endpoint is defined by the subdriver.
513 * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
514 * This routine may be called many times when the bandwidth is too small
515 * (the bandwidth is checked on urb submit).
516 */
517struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
518{
519 struct usb_interface *intf;
520 struct usb_host_endpoint *ep;
521 int i, ret;
522
523 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524 ep = NULL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300525 i = gspca_dev->alt; /* previous alt setting */
526 while (--i > 0) { /* alt 0 is unusable */
527 ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr);
528 if (ep)
529 break;
530 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300531 if (ep == NULL) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300532 err("no ISOC endpoint found");
533 return NULL;
534 }
535 PDEBUG(D_STREAM, "use ISOC alt %d ep 0x%02x",
536 i, ep->desc.bEndpointAddress);
537 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
538 if (ret < 0) {
539 err("set interface err %d", ret);
540 return NULL;
541 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300542 gspca_dev->alt = i; /* memorize the current alt setting */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300543 return ep;
544}
545
546/*
547 * create the isochronous URBs
548 */
549static int create_urbs(struct gspca_dev *gspca_dev,
550 struct usb_host_endpoint *ep)
551{
552 struct urb *urb;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300553 int n, nurbs, i, psize, npkt, bsize;
554 usb_complete_t usb_complete;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300555
556 /* calculate the packet size and the number of packets */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300557 psize = le16_to_cpu(ep->desc.wMaxPacketSize);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300558
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300559 /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
560 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
561 npkt = ISO_MAX_SIZE / psize;
562 if (npkt > ISO_MAX_PKT)
563 npkt = ISO_MAX_PKT;
564 bsize = psize * npkt;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300565 PDEBUG(D_STREAM,
566 "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300567/*fixme:change for userptr*/
568/*fixme:don't submit all URBs when userptr*/
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300569 if (gspca_dev->memory == V4L2_MEMORY_MMAP) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300570 usb_complete = isoc_irq_mmap;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300571 nurbs = DEF_NURBS;
572 } else {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300573 usb_complete = isoc_irq_user;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300574 nurbs = USR_NURBS;
575 }
576 gspca_dev->nurbs = nurbs;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300577 for (n = 0; n < nurbs; n++) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300578 urb = usb_alloc_urb(npkt, GFP_KERNEL);
579 if (!urb) {
580 err("usb_alloc_urb failed");
581 return -ENOMEM;
582 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300583 urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300584 bsize,
585 GFP_KERNEL,
586 &urb->transfer_dma);
587
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300588 if (urb->transfer_buffer == NULL) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300589 usb_free_urb(urb);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300590 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300591 err("usb_buffer_urb failed");
592 return -ENOMEM;
593 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300594 gspca_dev->urb[n] = urb;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300595 urb->dev = gspca_dev->dev;
596 urb->context = gspca_dev;
597 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
598 ep->desc.bEndpointAddress);
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300599 urb->transfer_flags = URB_ISO_ASAP
600 | URB_NO_TRANSFER_DMA_MAP;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300601 urb->interval = ep->desc.bInterval;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300602 urb->complete = usb_complete;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300603 urb->number_of_packets = npkt;
604 urb->transfer_buffer_length = bsize;
605 for (i = 0; i < npkt; i++) {
606 urb->iso_frame_desc[i].length = psize;
607 urb->iso_frame_desc[i].offset = psize * i;
608 }
609 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300610 gspca_dev->urb_in = gspca_dev->urb_out = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300611 return 0;
612}
613
614/*
615 * start the USB transfer
616 */
617static int gspca_init_transfer(struct gspca_dev *gspca_dev)
618{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300619 struct usb_host_endpoint *ep;
620 int n, ret;
621
Hans de Goedee2997a72008-04-23 08:09:12 -0300622 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
623 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300624
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300625 /* set the higher alternate setting and
626 * loop until urb submit succeeds */
627 gspca_dev->alt = gspca_dev->nbalt;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300628 for (;;) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300629 PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300630 ep = get_isoc_ep(gspca_dev);
631 if (ep == NULL) {
632 ret = -EIO;
633 goto out;
634 }
635 ret = create_urbs(gspca_dev, ep);
636 if (ret < 0)
637 goto out;
638
639 /* start the cam */
640 gspca_dev->sd_desc->start(gspca_dev);
641 gspca_dev->streaming = 1;
642 atomic_set(&gspca_dev->nevent, 0);
643
644 /* submit the URBs */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300645 for (n = 0; n < gspca_dev->nurbs; n++) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300646 ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300647 if (ret < 0) {
648 PDEBUG(D_ERR|D_STREAM,
649 "usb_submit_urb [%d] err %d", n, ret);
Hans de Goedee2997a72008-04-23 08:09:12 -0300650 gspca_dev->streaming = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300651 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300652 if (ret == -ENOSPC)
653 break; /* try the previous alt */
654 goto out;
655 }
656 }
657 if (ret >= 0)
658 break;
659 }
660out:
661 mutex_unlock(&gspca_dev->usb_lock);
662 return ret;
663}
664
665static int gspca_set_alt0(struct gspca_dev *gspca_dev)
666{
667 int ret;
668
669 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
670 if (ret < 0)
671 PDEBUG(D_ERR|D_STREAM, "set interface 0 err %d", ret);
672 return ret;
673}
674
Hans de Goedee2997a72008-04-23 08:09:12 -0300675/* Note both the queue and the usb lock should be hold when calling this */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300676static void gspca_stream_off(struct gspca_dev *gspca_dev)
677{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300678 gspca_dev->streaming = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300679 atomic_set(&gspca_dev->nevent, 0);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300680 if (gspca_dev->present) {
681 gspca_dev->sd_desc->stopN(gspca_dev);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300682 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300683 gspca_set_alt0(gspca_dev);
684 gspca_dev->sd_desc->stop0(gspca_dev);
685 PDEBUG(D_STREAM, "stream off OK");
686 } else {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300687 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300688 atomic_inc(&gspca_dev->nevent);
689 wake_up_interruptible(&gspca_dev->wq);
690 PDEBUG(D_ERR|D_STREAM, "stream off no device ??");
691 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300692}
693
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300694static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300695{
696 int i;
697
698 i = gspca_dev->cam.nmodes - 1; /* take the highest mode */
699 gspca_dev->curr_mode = i;
700 gspca_dev->width = gspca_dev->cam.cam_mode[i].width;
701 gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
702 gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixfmt;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300703}
704
705static int wxh_to_mode(struct gspca_dev *gspca_dev,
706 int width, int height)
707{
708 int i;
709
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300710 for (i = gspca_dev->cam.nmodes; --i > 0; ) {
711 if (width >= gspca_dev->cam.cam_mode[i].width
712 && height >= gspca_dev->cam.cam_mode[i].height)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300713 break;
714 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300715 return i;
716}
717
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300718/*
719 * search a mode with the right pixel format
720 */
721static int gspca_get_mode(struct gspca_dev *gspca_dev,
722 int mode,
723 int pixfmt)
724{
725 int modeU, modeD;
726
727 modeU = modeD = mode;
728 while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) {
729 if (--modeD >= 0) {
730 if (gspca_dev->cam.cam_mode[modeD].pixfmt == pixfmt)
731 return modeD;
732 }
733 if (++modeU < gspca_dev->cam.nmodes) {
734 if (gspca_dev->cam.cam_mode[modeU].pixfmt == pixfmt)
735 return modeU;
736 }
737 }
738 return -EINVAL;
739}
740
741static int vidioc_enum_fmt_cap(struct file *file, void *priv,
742 struct v4l2_fmtdesc *fmtdesc)
743{
744 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300745 int i, j, index;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300746 __u32 fmt_tb[8];
747
748 PDEBUG(D_CONF, "enum fmt cap");
749
750 /* give an index to each format */
751 index = 0;
752 j = 0;
753 for (i = gspca_dev->cam.nmodes; --i >= 0; ) {
754 fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixfmt;
755 j = 0;
756 for (;;) {
757 if (fmt_tb[j] == fmt_tb[index])
758 break;
759 j++;
760 }
761 if (j == index) {
762 if (fmtdesc->index == index)
763 break; /* new format */
764 index++;
765 if (index >= sizeof fmt_tb / sizeof fmt_tb[0])
766 return -EINVAL;
767 }
768 }
769 if (i < 0)
770 return -EINVAL; /* no more format */
771
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300772 fmtdesc->pixelformat = fmt_tb[index];
773 if (gspca_is_compressed(fmt_tb[index]))
774 fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300775 fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300776 fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
777 fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
778 fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff;
779 fmtdesc->description[3] = fmtdesc->pixelformat >> 24;
780 fmtdesc->description[4] = '\0';
781 return 0;
782}
783
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300784static int vidioc_g_fmt_cap(struct file *file, void *priv,
785 struct v4l2_format *fmt)
786{
787 struct gspca_dev *gspca_dev = priv;
788
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300789 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
790 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300791 fmt->fmt.pix.width = gspca_dev->width;
792 fmt->fmt.pix.height = gspca_dev->height;
793 fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300794#ifdef VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300795 if (gspca_debug & D_CONF) {
796 PDEBUG_MODE("get fmt cap",
797 fmt->fmt.pix.pixelformat,
798 fmt->fmt.pix.width,
799 fmt->fmt.pix.height);
800 }
801#endif
802 fmt->fmt.pix.field = V4L2_FIELD_NONE;
803 fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat)
804 * fmt->fmt.pix.width / 8;
805 fmt->fmt.pix.sizeimage = fmt->fmt.pix.bytesperline
806 * fmt->fmt.pix.height;
807/* (should be in the subdriver) */
808 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
809 fmt->fmt.pix.priv = 0;
810 return 0;
811}
812
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300813static int try_fmt_cap(struct gspca_dev *gspca_dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300814 struct v4l2_format *fmt)
815{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300816 int w, h, mode, mode2, frsz;
817
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300818 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
819 return -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300820 w = fmt->fmt.pix.width;
821 h = fmt->fmt.pix.height;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300822
823 /* (luvcview problem) */
824 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
825 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300826#ifdef VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300827 if (gspca_debug & D_CONF)
828 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
829#endif
830 /* search the closest mode for width and height */
831 mode = wxh_to_mode(gspca_dev, w, h);
832
833 /* OK if right palette */
834 if (gspca_dev->cam.cam_mode[mode].pixfmt != fmt->fmt.pix.pixelformat) {
835
836 /* else, search the closest mode with the same pixel format */
837 mode2 = gspca_get_mode(gspca_dev, mode,
838 fmt->fmt.pix.pixelformat);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300839 if (mode2 >= 0) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300840 mode = mode2;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300841 } else {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300842
843 /* no chance, return this mode */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300844 fmt->fmt.pix.pixelformat =
845 gspca_dev->cam.cam_mode[mode].pixfmt;
846#ifdef VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300847 if (gspca_debug & D_CONF) {
848 PDEBUG_MODE("new format",
849 fmt->fmt.pix.pixelformat,
850 gspca_dev->cam.cam_mode[mode].width,
851 gspca_dev->cam.cam_mode[mode].height);
852 }
853#endif
854 }
855 }
856 fmt->fmt.pix.width = gspca_dev->cam.cam_mode[mode].width;
857 fmt->fmt.pix.height = gspca_dev->cam.cam_mode[mode].height;
858 fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat)
859 * fmt->fmt.pix.width / 8;
860 frsz = fmt->fmt.pix.bytesperline * fmt->fmt.pix.height;
861 if (gspca_is_compressed(fmt->fmt.pix.pixelformat))
862 frsz = (frsz * comp_fac) / 100;
863 fmt->fmt.pix.sizeimage = frsz;
864 return mode; /* used when s_fmt */
865}
866
867static int vidioc_try_fmt_cap(struct file *file,
868 void *priv,
869 struct v4l2_format *fmt)
870{
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300871 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300872 int ret;
873
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300874 ret = try_fmt_cap(gspca_dev, fmt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300875 if (ret < 0)
876 return ret;
877 return 0;
878}
879
880static int vidioc_s_fmt_cap(struct file *file, void *priv,
881 struct v4l2_format *fmt)
882{
883 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300884 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300885
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300886#ifdef CONFIG_VIDEO_V4L1_COMPAT
887 /* if v4l1 got JPEG */
888 if (fmt->fmt.pix.pixelformat == 0
889 && gspca_dev->streaming) {
890 fmt->fmt.pix.width = gspca_dev->width;
891 fmt->fmt.pix.height = gspca_dev->height;
892 fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
893 return 0;
894 }
895#endif
896#ifdef VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300897 if (gspca_debug & D_CONF) {
898 PDEBUG_MODE("set fmt cap",
899 fmt->fmt.pix.pixelformat,
900 fmt->fmt.pix.width, fmt->fmt.pix.height);
901 }
902#endif
Hans de Goedee2997a72008-04-23 08:09:12 -0300903 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
904 return -ERESTARTSYS;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300905
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300906 ret = try_fmt_cap(gspca_dev, fmt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300907 if (ret < 0)
908 goto out;
909
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300910 if (gspca_dev->nframes != 0
911 && fmt->fmt.pix.sizeimage > gspca_dev->frsz) {
912 ret = -EINVAL;
913 goto out;
914 }
915
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300916 if (ret == gspca_dev->curr_mode)
917 goto out; /* same mode */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300918
919 if (gspca_dev->streaming) {
920 ret = -EBUSY;
921 goto out;
Hans de Goedee2997a72008-04-23 08:09:12 -0300922 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300923 gspca_dev->width = fmt->fmt.pix.width;
924 gspca_dev->height = fmt->fmt.pix.height;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300925 gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
926 gspca_dev->curr_mode = ret;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300927
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300928 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300929out:
930 mutex_unlock(&gspca_dev->queue_lock);
931 return ret;
932}
933
934static int dev_open(struct inode *inode, struct file *file)
935{
936 struct gspca_dev *gspca_dev;
937 int ret;
938
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300939 PDEBUG(D_STREAM, "%s open", current->comm);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300940 gspca_dev = (struct gspca_dev *) video_devdata(file);
Hans de Goedee2997a72008-04-23 08:09:12 -0300941 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
942 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300943 if (!gspca_dev->present) {
944 ret = -ENODEV;
945 goto out;
946 }
947
948 /* if not done yet, initialize the sensor */
949 if (gspca_dev->users == 0) {
Hans de Goedee2997a72008-04-23 08:09:12 -0300950 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
951 ret = -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300952 goto out;
Hans de Goedee2997a72008-04-23 08:09:12 -0300953 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300954 ret = gspca_dev->sd_desc->open(gspca_dev);
955 mutex_unlock(&gspca_dev->usb_lock);
956 if (ret != 0) {
957 PDEBUG(D_ERR|D_CONF, "init device failed %d", ret);
958 goto out;
959 }
Hans de Goedee2997a72008-04-23 08:09:12 -0300960 } else if (gspca_dev->users > 4) { /* (arbitrary value) */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300961 ret = -EBUSY;
962 goto out;
963 }
964 gspca_dev->users++;
965 file->private_data = gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300966#ifdef VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300967 /* activate the v4l2 debug */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300968 if (gspca_debug & D_V4L2)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300969 gspca_dev->vdev.debug |= 3;
970 else
971 gspca_dev->vdev.debug &= ~3;
972#endif
973out:
974 mutex_unlock(&gspca_dev->queue_lock);
975 if (ret != 0)
976 PDEBUG(D_ERR|D_STREAM, "open failed err %d", ret);
977 else
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300978 PDEBUG(D_STREAM, "open done");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300979 return ret;
980}
981
982static int dev_close(struct inode *inode, struct file *file)
983{
984 struct gspca_dev *gspca_dev = file->private_data;
985
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300986 PDEBUG(D_STREAM, "%s close", current->comm);
Hans de Goedee2997a72008-04-23 08:09:12 -0300987 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
988 return -ERESTARTSYS;
989 gspca_dev->users--;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300990
991 /* if the file did capture, free the streaming resources */
992 if (gspca_dev->capt_file == file) {
993 mutex_lock(&gspca_dev->usb_lock);
994 if (gspca_dev->streaming)
995 gspca_stream_off(gspca_dev);
996 gspca_dev->sd_desc->close(gspca_dev);
997 mutex_unlock(&gspca_dev->usb_lock);
998 frame_free(gspca_dev);
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300999 gspca_dev->capt_file = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001000 gspca_dev->memory = GSPCA_MEMORY_NO;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001001 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001002 file->private_data = NULL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001003 mutex_unlock(&gspca_dev->queue_lock);
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001004 PDEBUG(D_STREAM, "close done");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001005 return 0;
1006}
1007
1008static int vidioc_querycap(struct file *file, void *priv,
1009 struct v4l2_capability *cap)
1010{
1011 struct gspca_dev *gspca_dev = priv;
1012
1013 PDEBUG(D_CONF, "querycap");
1014 memset(cap, 0, sizeof *cap);
1015 strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
1016 strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card);
1017 strncpy(cap->bus_info, gspca_dev->dev->bus->bus_name,
1018 sizeof cap->bus_info);
1019 cap->version = DRIVER_VERSION_NUMBER;
1020 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
1021 | V4L2_CAP_STREAMING
1022 | V4L2_CAP_READWRITE;
1023 return 0;
1024}
1025
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001026/* the use of V4L2_CTRL_FLAG_NEXT_CTRL asks for the controls to be sorted */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001027static int vidioc_queryctrl(struct file *file, void *priv,
1028 struct v4l2_queryctrl *q_ctrl)
1029{
1030 struct gspca_dev *gspca_dev = priv;
1031 int i;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001032 u32 id;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001033
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001034 id = q_ctrl->id;
1035 if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
1036 id &= V4L2_CTRL_ID_MASK;
1037 id++;
1038 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
1039 if (id >= gspca_dev->sd_desc->ctrls[i].qctrl.id) {
1040 memcpy(q_ctrl,
1041 &gspca_dev->sd_desc->ctrls[i].qctrl,
1042 sizeof *q_ctrl);
1043 return 0;
1044 }
1045 }
1046 return -EINVAL;
1047 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001048 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001049 if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001050 memcpy(q_ctrl,
1051 &gspca_dev->sd_desc->ctrls[i].qctrl,
1052 sizeof *q_ctrl);
1053 return 0;
1054 }
1055 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001056 if (id >= V4L2_CID_BASE
1057 && id <= V4L2_CID_LASTP1) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001058 q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
1059 return 0;
1060 }
1061 return -EINVAL;
1062}
1063
1064static int vidioc_s_ctrl(struct file *file, void *priv,
1065 struct v4l2_control *ctrl)
1066{
1067 struct gspca_dev *gspca_dev = priv;
1068 struct ctrl *ctrls;
1069 int i, ret;
1070
1071 PDEBUG(D_CONF, "set ctrl");
1072 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
1073 i < gspca_dev->sd_desc->nctrls;
1074 i++, ctrls++) {
1075 if (ctrl->id != ctrls->qctrl.id)
1076 continue;
1077 if (ctrl->value < ctrls->qctrl.minimum
1078 && ctrl->value > ctrls->qctrl.maximum)
1079 return -ERANGE;
1080 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
Hans de Goedee2997a72008-04-23 08:09:12 -03001081 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1082 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001083 ret = ctrls->set(gspca_dev, ctrl->value);
1084 mutex_unlock(&gspca_dev->usb_lock);
1085 return ret;
1086 }
1087 return -EINVAL;
1088}
1089
1090static int vidioc_g_ctrl(struct file *file, void *priv,
1091 struct v4l2_control *ctrl)
1092{
1093 struct gspca_dev *gspca_dev = priv;
1094
1095 struct ctrl *ctrls;
1096 int i, ret;
1097
1098 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
1099 i < gspca_dev->sd_desc->nctrls;
1100 i++, ctrls++) {
1101 if (ctrl->id != ctrls->qctrl.id)
1102 continue;
Hans de Goedee2997a72008-04-23 08:09:12 -03001103 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1104 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001105 ret = ctrls->get(gspca_dev, &ctrl->value);
1106 mutex_unlock(&gspca_dev->usb_lock);
1107 return ret;
1108 }
1109 return -EINVAL;
1110}
1111
1112static int vidioc_querymenu(struct file *file, void *priv,
1113 struct v4l2_querymenu *qmenu)
1114{
1115 struct gspca_dev *gspca_dev = priv;
1116
1117 if (!gspca_dev->sd_desc->querymenu)
1118 return -EINVAL;
1119 return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu);
1120}
1121
1122static int vidioc_enum_input(struct file *file, void *priv,
1123 struct v4l2_input *input)
1124{
1125 struct gspca_dev *gspca_dev = priv;
1126
1127 if (input->index != 0)
1128 return -EINVAL;
1129 memset(input, 0, sizeof *input);
1130 input->type = V4L2_INPUT_TYPE_CAMERA;
1131 strncpy(input->name, gspca_dev->sd_desc->name,
1132 sizeof input->name);
1133 return 0;
1134}
1135
1136static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1137{
1138 *i = 0;
1139 return 0;
1140}
1141
1142static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1143{
1144 if (i > 0)
1145 return -EINVAL;
1146 return (0);
1147}
1148
1149static int vidioc_reqbufs(struct file *file, void *priv,
1150 struct v4l2_requestbuffers *rb)
1151{
1152 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001153 int i, ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001154
1155 PDEBUG(D_STREAM, "reqbufs %d", rb->count);
1156 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1157 return -EINVAL;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001158 switch (rb->memory) {
1159 case V4L2_MEMORY_MMAP:
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001160 case V4L2_MEMORY_USERPTR:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001161 break;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001162 default:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001163 return -EINVAL;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001164 }
Hans de Goedee2997a72008-04-23 08:09:12 -03001165 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1166 return -ERESTARTSYS;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001167
1168 for (i = 0; i < gspca_dev->nframes; i++) {
1169 if (gspca_dev->frame[i].vma_use_count) {
1170 ret = -EBUSY;
1171 goto out;
1172 }
1173 }
1174
1175 /* only one file may do capture */
1176 if ((gspca_dev->capt_file != 0 && gspca_dev->capt_file != file)
1177 || gspca_dev->streaming) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001178 ret = -EBUSY;
1179 goto out;
1180 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001181
1182 if (rb->count == 0) { /* unrequest? */
1183 frame_free(gspca_dev);
1184 gspca_dev->capt_file = 0;
1185 } else {
1186 gspca_dev->memory = rb->memory;
1187 ret = frame_alloc(gspca_dev, rb->count);
1188 if (ret == 0) {
1189 rb->count = gspca_dev->nframes;
1190 gspca_dev->capt_file = file;
1191 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001192 }
1193out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001194 mutex_unlock(&gspca_dev->queue_lock);
1195 PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count);
1196 return ret;
1197}
1198
1199static int vidioc_querybuf(struct file *file, void *priv,
1200 struct v4l2_buffer *v4l2_buf)
1201{
1202 struct gspca_dev *gspca_dev = priv;
1203 struct gspca_frame *frame;
1204
1205 PDEBUG(D_STREAM, "querybuf");
1206 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1207 || v4l2_buf->index < 0
1208 || v4l2_buf->index >= gspca_dev->nframes)
1209 return -EINVAL;
1210
1211 frame = &gspca_dev->frame[v4l2_buf->index];
1212 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1213 return 0;
1214}
1215
1216static int vidioc_streamon(struct file *file, void *priv,
1217 enum v4l2_buf_type buf_type)
1218{
1219 struct gspca_dev *gspca_dev = priv;
1220 int ret;
1221
1222 PDEBUG(D_STREAM, "stream on");
1223 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1224 return -EINVAL;
Hans de Goedee2997a72008-04-23 08:09:12 -03001225 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1226 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001227 if (!gspca_dev->present) {
1228 ret = -ENODEV;
1229 goto out;
1230 }
1231 if (gspca_dev->nframes == 0) {
1232 ret = -EINVAL;
1233 goto out;
1234 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001235 if (gspca_dev->capt_file != file) {
1236 ret = -EINVAL;
1237 goto out;
1238 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001239 if (!gspca_dev->streaming) {
1240 ret = gspca_init_transfer(gspca_dev);
1241 if (ret < 0)
1242 goto out;
1243 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001244#ifdef VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001245 if (gspca_debug & D_STREAM) {
1246 PDEBUG_MODE("stream on OK",
1247 gspca_dev->pixfmt,
1248 gspca_dev->width,
1249 gspca_dev->height);
1250 }
1251#endif
Hans de Goedee2997a72008-04-23 08:09:12 -03001252 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001253out:
1254 mutex_unlock(&gspca_dev->queue_lock);
1255 return ret;
1256}
1257
1258static int vidioc_streamoff(struct file *file, void *priv,
1259 enum v4l2_buf_type buf_type)
1260{
1261 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001262 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001263
1264 PDEBUG(D_STREAM, "stream off");
1265 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1266 return -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001267 if (!gspca_dev->streaming)
1268 return 0;
1269 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1270 return -ERESTARTSYS;
1271 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
1272 ret = -ERESTARTSYS;
1273 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001274 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001275 if (gspca_dev->capt_file != file) {
1276 ret = -EINVAL;
1277 goto out2;
1278 }
1279 gspca_stream_off(gspca_dev);
1280 ret = 0;
1281out2:
1282 mutex_unlock(&gspca_dev->usb_lock);
1283out:
1284 mutex_unlock(&gspca_dev->queue_lock);
1285 return ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001286}
1287
1288static int vidioc_g_jpegcomp(struct file *file, void *priv,
1289 struct v4l2_jpegcompression *jpegcomp)
1290{
1291 struct gspca_dev *gspca_dev = priv;
1292 int ret;
1293
1294 if (!gspca_dev->sd_desc->get_jcomp)
1295 return -EINVAL;
Hans de Goedee2997a72008-04-23 08:09:12 -03001296 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1297 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001298 ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
1299 mutex_unlock(&gspca_dev->usb_lock);
1300 return ret;
1301}
1302
1303static int vidioc_s_jpegcomp(struct file *file, void *priv,
1304 struct v4l2_jpegcompression *jpegcomp)
1305{
1306 struct gspca_dev *gspca_dev = priv;
1307 int ret;
1308
Hans de Goedee2997a72008-04-23 08:09:12 -03001309 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1310 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001311 if (!gspca_dev->sd_desc->set_jcomp)
1312 return -EINVAL;
1313 ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
1314 mutex_unlock(&gspca_dev->usb_lock);
1315 return ret;
1316}
1317
1318static int vidioc_g_parm(struct file *filp, void *priv,
1319 struct v4l2_streamparm *parm)
1320{
1321 struct gspca_dev *gspca_dev = priv;
1322
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001323 memset(parm, 0, sizeof *parm);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001324 parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1325 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1326 return 0;
1327}
1328
1329static int vidioc_s_parm(struct file *filp, void *priv,
1330 struct v4l2_streamparm *parm)
1331{
1332 struct gspca_dev *gspca_dev = priv;
1333 int n;
1334
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001335 n = parm->parm.capture.readbuffers;
1336 if (n == 0 || n > GSPCA_MAX_FRAMES)
1337 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1338 else
1339 gspca_dev->nbufread = n;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001340 return 0;
1341}
1342
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001343static int vidioc_s_std(struct file *filp, void *priv,
1344 v4l2_std_id *parm)
1345{
1346 return 0;
1347}
1348
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001349#ifdef CONFIG_VIDEO_V4L1_COMPAT
1350static int vidiocgmbuf(struct file *file, void *priv,
1351 struct video_mbuf *mbuf)
1352{
1353 struct gspca_dev *gspca_dev = file->private_data;
1354 int i;
1355
1356 PDEBUG(D_STREAM, "cgmbuf");
1357 if (gspca_dev->nframes == 0) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001358 int ret;
1359
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001360 {
1361 struct v4l2_format fmt;
1362
1363 memset(&fmt, 0, sizeof fmt);
1364 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1365 i = gspca_dev->cam.nmodes - 1; /* highest mode */
1366 fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width;
1367 fmt.fmt.pix.height = gspca_dev->cam.cam_mode[i].height;
1368 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
1369 ret = vidioc_s_fmt_cap(file, priv, &fmt);
1370 if (ret != 0)
1371 return ret;
1372 }
1373 {
1374 struct v4l2_requestbuffers rb;
1375
1376 memset(&rb, 0, sizeof rb);
1377 rb.count = 4;
1378 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1379 rb.memory = V4L2_MEMORY_MMAP;
1380 ret = vidioc_reqbufs(file, priv, &rb);
1381 if (ret != 0)
1382 return ret;
1383 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001384 }
1385 mbuf->frames = gspca_dev->nframes;
1386 mbuf->size = gspca_dev->frsz * gspca_dev->nframes;
1387 for (i = 0; i < mbuf->frames; i++)
1388 mbuf->offsets[i] = gspca_dev->frame[i].v4l2_buf.m.offset;
1389 return 0;
1390}
1391#endif
1392
1393static int dev_mmap(struct file *file, struct vm_area_struct *vma)
1394{
1395 struct gspca_dev *gspca_dev = file->private_data;
1396 struct gspca_frame *frame = 0;
1397 struct page *page;
1398 unsigned long addr, start, size;
1399 int i, ret;
1400#ifdef CONFIG_VIDEO_V4L1_COMPAT
1401 int compat = 0;
1402#endif
1403
1404 start = vma->vm_start;
1405 size = vma->vm_end - vma->vm_start;
1406 PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size);
1407
Hans de Goedee2997a72008-04-23 08:09:12 -03001408 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1409 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001410 if (!gspca_dev->present) {
1411 ret = -ENODEV;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001412 goto out;
1413 }
1414 if (gspca_dev->capt_file != file) {
1415 ret = -EINVAL;
1416 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001417 }
1418
1419 for (i = 0; i < gspca_dev->nframes; ++i) {
1420 if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) {
1421 PDEBUG(D_STREAM, "mmap bad memory type");
1422 break;
1423 }
1424 if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT)
1425 == vma->vm_pgoff) {
1426 frame = &gspca_dev->frame[i];
1427 break;
1428 }
1429 }
1430 if (frame == 0) {
1431 PDEBUG(D_STREAM, "mmap no frame buffer found");
1432 ret = -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001433 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001434 }
1435#ifdef CONFIG_VIDEO_V4L1_COMPAT
1436 if (i == 0 && size == frame->v4l2_buf.length * gspca_dev->nframes)
1437 compat = 1;
1438 else
1439#endif
1440 if (size != frame->v4l2_buf.length) {
1441 PDEBUG(D_STREAM, "mmap bad size");
1442 ret = -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001443 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001444 }
1445
1446 /*
1447 * - VM_IO marks the area as being a mmaped region for I/O to a
1448 * device. It also prevents the region from being core dumped.
1449 */
1450 vma->vm_flags |= VM_IO;
1451
1452 addr = (unsigned long) frame->data;
1453 while (size > 0) {
1454 page = vmalloc_to_page((void *) addr);
1455 ret = vm_insert_page(vma, start, page);
1456 if (ret < 0)
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001457 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001458 start += PAGE_SIZE;
1459 addr += PAGE_SIZE;
1460 size -= PAGE_SIZE;
1461 }
1462
1463 vma->vm_ops = &gspca_vm_ops;
1464 vma->vm_private_data = frame;
1465 gspca_vm_open(vma);
1466#ifdef CONFIG_VIDEO_V4L1_COMPAT
1467 if (compat) {
1468/*fixme: ugly*/
1469 for (i = 1; i < gspca_dev->nframes; ++i)
1470 gspca_dev->frame[i].v4l2_buf.flags |=
1471 V4L2_BUF_FLAG_MAPPED;
1472 }
1473#endif
Hans de Goedee2997a72008-04-23 08:09:12 -03001474 ret = 0;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001475out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001476 mutex_unlock(&gspca_dev->queue_lock);
1477 return ret;
1478}
1479
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001480/*
1481 * wait for a video frame
1482 *
1483 * If a frame is ready, its index is returned.
1484 */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001485static int frame_wait(struct gspca_dev *gspca_dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001486 int nonblock_ing)
1487{
1488 struct gspca_frame *frame;
1489 int i, j, ret;
1490
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001491 /* if userptr, treat the awaiting URBs */
1492 if (gspca_dev->memory == V4L2_MEMORY_USERPTR)
1493 isoc_transfer(gspca_dev);
1494
1495 /* check if a frame is ready */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001496 i = gspca_dev->fr_o;
1497 j = gspca_dev->fr_queue[i];
1498 frame = &gspca_dev->frame[j];
1499 if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1500 goto ok;
1501 if (nonblock_ing) /* no frame yet */
1502 return -EAGAIN;
1503
1504 /* wait till a frame is ready */
1505 for (;;) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001506 ret = wait_event_interruptible_timeout(gspca_dev->wq,
1507 atomic_read(&gspca_dev->nevent) > 0,
1508 msecs_to_jiffies(3000));
1509 if (ret <= 0) {
1510 if (ret < 0)
1511 return ret;
1512 return -EIO;
1513 }
Hans de Goedee2997a72008-04-23 08:09:12 -03001514 if (!gspca_dev->streaming || !gspca_dev->present)
1515 return -EIO;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001516 if (gspca_dev->memory == V4L2_MEMORY_USERPTR)
1517 isoc_transfer(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001518 i = gspca_dev->fr_o;
1519 j = gspca_dev->fr_queue[i];
1520 frame = &gspca_dev->frame[j];
1521 if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1522 break;
1523 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001524ok:
1525 atomic_dec(&gspca_dev->nevent);
1526 gspca_dev->fr_o = (i + 1) % gspca_dev->nframes;
1527 PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d",
1528 gspca_dev->fr_q,
1529 gspca_dev->fr_i,
1530 gspca_dev->fr_o);
Hans de Goedee2997a72008-04-23 08:09:12 -03001531
1532 if (gspca_dev->sd_desc->dq_callback)
1533 gspca_dev->sd_desc->dq_callback(gspca_dev);
1534
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001535 return j;
1536}
1537
1538/*
1539 * dequeue a video buffer
1540 *
1541 * If nonblock_ing is false, block until a buffer is available.
1542 */
1543static int vidioc_dqbuf(struct file *file, void *priv,
1544 struct v4l2_buffer *v4l2_buf)
1545{
1546 struct gspca_dev *gspca_dev = priv;
1547 struct gspca_frame *frame;
1548 int i, ret;
1549
1550 PDEBUG(D_FRAM, "dqbuf");
1551 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1552 || (v4l2_buf->memory != V4L2_MEMORY_MMAP
1553 && v4l2_buf->memory != V4L2_MEMORY_USERPTR))
1554 return -EINVAL;
1555 if (!gspca_dev->streaming)
1556 return -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001557 if (gspca_dev->capt_file != file) {
1558 ret = -EINVAL;
1559 goto out;
1560 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001561
1562 /* only one read */
1563 if (mutex_lock_interruptible(&gspca_dev->read_lock))
1564 return -ERESTARTSYS;
1565
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001566 ret = frame_wait(gspca_dev, file->f_flags & O_NONBLOCK);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001567 if (ret < 0)
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001568 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001569 i = ret; /* frame index */
1570 frame = &gspca_dev->frame[i];
1571 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
1572 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1573 PDEBUG(D_FRAM, "dqbuf %d", i);
1574 ret = 0;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001575out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001576 mutex_unlock(&gspca_dev->read_lock);
1577 return ret;
1578}
1579
1580/*
1581 * queue a video buffer
1582 *
1583 * Attempting to queue a buffer that has already been
1584 * queued will return -EINVAL.
1585 */
1586static int vidioc_qbuf(struct file *file, void *priv,
1587 struct v4l2_buffer *v4l2_buf)
1588{
1589 struct gspca_dev *gspca_dev = priv;
1590 struct gspca_frame *frame;
1591 int i, index, ret;
1592
1593 PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index);
1594 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1595 return -EINVAL;
1596
1597 index = v4l2_buf->index;
1598 if ((unsigned) index >= gspca_dev->nframes) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001599 PDEBUG(D_FRAM,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001600 "qbuf idx %d >= %d", index, gspca_dev->nframes);
1601 return -EINVAL;
1602 }
1603 frame = &gspca_dev->frame[index];
1604
1605 if (v4l2_buf->memory != frame->v4l2_buf.memory) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001606 PDEBUG(D_FRAM, "qbuf bad memory type");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001607 return -EINVAL;
1608 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001609 if (gspca_dev->capt_file != file)
1610 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001611
Hans de Goedee2997a72008-04-23 08:09:12 -03001612 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1613 return -ERESTARTSYS;
1614
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001615 if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) {
1616 PDEBUG(D_FRAM, "qbuf bad state");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001617 ret = -EINVAL;
1618 goto out;
1619 }
1620
1621 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001622/* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001623
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001624 if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001625 frame->data = frame->data_end =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001626 (__u8 *) v4l2_buf->m.userptr;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001627 frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
1628 frame->v4l2_buf.length = v4l2_buf->length;
1629 }
1630
1631 /* put the buffer in the 'queued' queue */
1632 i = gspca_dev->fr_q;
1633 gspca_dev->fr_queue[i] = index;
1634 gspca_dev->fr_q = (i + 1) % gspca_dev->nframes;
1635 PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d",
1636 gspca_dev->fr_q,
1637 gspca_dev->fr_i,
1638 gspca_dev->fr_o);
1639
1640 v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
1641 v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE;
1642 ret = 0;
1643out:
1644 mutex_unlock(&gspca_dev->queue_lock);
1645 return ret;
1646}
1647
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001648/*
1649 * allocate the resources for read()
1650 */
1651static int read_alloc(struct gspca_dev *gspca_dev,
1652 struct file *file)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001653{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001654 struct v4l2_buffer v4l2_buf;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001655 int i, ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001656
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001657 PDEBUG(D_STREAM, "read alloc");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001658 if (gspca_dev->nframes == 0) {
1659 struct v4l2_requestbuffers rb;
1660
1661 memset(&rb, 0, sizeof rb);
1662 rb.count = gspca_dev->nbufread;
1663 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1664 rb.memory = V4L2_MEMORY_MMAP;
1665 ret = vidioc_reqbufs(file, gspca_dev, &rb);
1666 if (ret != 0) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001667 PDEBUG(D_STREAM, "read reqbuf err %d", ret);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001668 return ret;
1669 }
1670 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1671 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1672 v4l2_buf.memory = V4L2_MEMORY_MMAP;
1673 for (i = 0; i < gspca_dev->nbufread; i++) {
1674 v4l2_buf.index = i;
1675/*fixme: ugly!*/
1676 gspca_dev->frame[i].v4l2_buf.flags |=
1677 V4L2_BUF_FLAG_MAPPED;
1678 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1679 if (ret != 0) {
1680 PDEBUG(D_STREAM, "read qbuf err: %d", ret);
1681 return ret;
1682 }
1683 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001684 gspca_dev->memory = GSPCA_MEMORY_READ;
1685 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001686
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001687 /* start streaming */
1688 ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE);
1689 if (ret != 0)
1690 PDEBUG(D_STREAM, "read streamon err %d", ret);
1691 return ret;
1692}
1693
1694static unsigned int dev_poll(struct file *file, poll_table *wait)
1695{
1696 struct gspca_dev *gspca_dev = file->private_data;
1697 int i, ret;
1698
1699 PDEBUG(D_FRAM, "poll");
1700
1701 poll_wait(file, &gspca_dev->wq, wait);
1702 if (!gspca_dev->present)
1703 return POLLERR;
1704
1705 /* if not streaming, the user would use read() */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001706 if (!gspca_dev->streaming) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001707 if (gspca_dev->memory != GSPCA_MEMORY_NO) {
1708 ret = POLLERR; /* not the 1st time */
1709 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001710 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001711 ret = read_alloc(gspca_dev, file);
1712 if (ret != 0) {
1713 ret = POLLERR;
1714 goto out;
1715 }
1716 }
1717
1718 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0)
1719 return POLLERR;
1720 if (!gspca_dev->present) {
1721 ret = POLLERR;
1722 goto out;
1723 }
1724
1725 /* if not mmap, treat the awaiting URBs */
1726 if (gspca_dev->memory == V4L2_MEMORY_USERPTR
1727 && gspca_dev->capt_file == file)
1728 isoc_transfer(gspca_dev);
1729
1730 i = gspca_dev->fr_o;
1731 i = gspca_dev->fr_queue[i];
1732 if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1733 ret = POLLIN | POLLRDNORM; /* something to read */
1734 else
1735 ret = 0;
1736out:
1737 mutex_unlock(&gspca_dev->queue_lock);
1738 return ret;
1739}
1740
1741static ssize_t dev_read(struct file *file, char __user *data,
1742 size_t count, loff_t *ppos)
1743{
1744 struct gspca_dev *gspca_dev = file->private_data;
1745 struct gspca_frame *frame;
1746 struct v4l2_buffer v4l2_buf;
1747 struct timeval timestamp;
1748 int i, ret, ret2;
1749
1750 PDEBUG(D_FRAM, "read (%d)", count);
1751 if (!gspca_dev->present)
1752 return -ENODEV;
1753 switch (gspca_dev->memory) {
1754 case GSPCA_MEMORY_NO: /* first time */
1755 ret = read_alloc(gspca_dev, file);
1756 if (ret != 0)
1757 return ret;
1758 break;
1759 case GSPCA_MEMORY_READ:
1760 if (gspca_dev->capt_file != file)
1761 return -EINVAL;
1762 break;
1763 default:
1764 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001765 }
1766
1767 /* get a frame */
1768 jiffies_to_timeval(get_jiffies_64(), &timestamp);
1769 timestamp.tv_sec--;
1770 for (i = 0; i < 2; i++) {
1771 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1772 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1773 v4l2_buf.memory = V4L2_MEMORY_MMAP;
1774 ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf);
1775 if (ret != 0) {
1776 PDEBUG(D_STREAM, "read dqbuf err %d", ret);
1777 return ret;
1778 }
1779
1780 /* if the process slept for more than 1 second,
1781 * get a brand new frame */
1782 frame = &gspca_dev->frame[v4l2_buf.index];
1783 if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
1784 break;
1785 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1786 if (ret != 0) {
1787 PDEBUG(D_STREAM, "read qbuf err %d", ret);
1788 return ret;
1789 }
1790 }
1791
1792 /* copy the frame */
1793 if (count < frame->v4l2_buf.bytesused) {
1794 PDEBUG(D_STREAM, "read bad count: %d < %d",
1795 count, frame->v4l2_buf.bytesused);
1796/*fixme: special errno?*/
1797 ret = -EINVAL;
1798 goto out;
1799 }
1800 count = frame->v4l2_buf.bytesused;
1801 ret = copy_to_user(data, frame->data, count);
1802 if (ret != 0) {
1803 PDEBUG(D_ERR|D_STREAM,
1804 "read cp to user lack %d / %d", ret, count);
1805 ret = -EFAULT;
1806 goto out;
1807 }
1808 ret = count;
1809out:
1810 /* in each case, requeue the buffer */
1811 ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1812 if (ret2 != 0)
1813 return ret2;
1814 return ret;
1815}
1816
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001817static void dev_release(struct video_device *vfd)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001818{
1819 /* nothing */
1820}
1821
1822static struct file_operations dev_fops = {
1823 .owner = THIS_MODULE,
1824 .open = dev_open,
1825 .release = dev_close,
1826 .read = dev_read,
1827 .mmap = dev_mmap,
1828 .ioctl = video_ioctl2,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001829#ifdef CONFIG_COMPAT
1830 .compat_ioctl = v4l_compat_ioctl32,
1831#endif
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001832 .llseek = no_llseek,
1833 .poll = dev_poll,
1834};
1835
1836static struct video_device gspca_template = {
1837 .name = "gspca main driver",
1838 .type = VID_TYPE_CAPTURE,
1839 .fops = &dev_fops,
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001840 .release = dev_release, /* mandatory */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001841 .minor = -1,
1842 .vidioc_querycap = vidioc_querycap,
1843 .vidioc_dqbuf = vidioc_dqbuf,
1844 .vidioc_qbuf = vidioc_qbuf,
1845 .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap,
1846 .vidioc_try_fmt_cap = vidioc_try_fmt_cap,
1847 .vidioc_g_fmt_cap = vidioc_g_fmt_cap,
1848 .vidioc_s_fmt_cap = vidioc_s_fmt_cap,
1849 .vidioc_streamon = vidioc_streamon,
1850 .vidioc_queryctrl = vidioc_queryctrl,
1851 .vidioc_g_ctrl = vidioc_g_ctrl,
1852 .vidioc_s_ctrl = vidioc_s_ctrl,
1853 .vidioc_querymenu = vidioc_querymenu,
1854 .vidioc_enum_input = vidioc_enum_input,
1855 .vidioc_g_input = vidioc_g_input,
1856 .vidioc_s_input = vidioc_s_input,
1857 .vidioc_reqbufs = vidioc_reqbufs,
1858 .vidioc_querybuf = vidioc_querybuf,
1859 .vidioc_streamoff = vidioc_streamoff,
1860 .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
1861 .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
1862 .vidioc_g_parm = vidioc_g_parm,
1863 .vidioc_s_parm = vidioc_s_parm,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001864 .vidioc_s_std = vidioc_s_std,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001865#ifdef CONFIG_VIDEO_V4L1_COMPAT
1866 .vidiocgmbuf = vidiocgmbuf,
1867#endif
1868};
1869
1870/*
1871 * probe and create a new gspca device
1872 *
1873 * This function must be called by the sub-driver when it is
1874 * called for probing a new device.
1875 */
1876int gspca_dev_probe(struct usb_interface *intf,
1877 const struct usb_device_id *id,
1878 const struct sd_desc *sd_desc,
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001879 int dev_size,
1880 struct module *module)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001881{
1882 struct usb_interface_descriptor *interface;
1883 struct gspca_dev *gspca_dev;
1884 struct usb_device *dev = interface_to_usbdev(intf);
1885 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001886
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001887 PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001888
1889 /* we don't handle multi-config cameras */
1890 if (dev->descriptor.bNumConfigurations != 1)
1891 return -ENODEV;
1892 interface = &intf->cur_altsetting->desc;
1893 if (interface->bInterfaceNumber > 0)
1894 return -ENODEV;
1895
1896 /* create the device */
1897 if (dev_size < sizeof *gspca_dev)
1898 dev_size = sizeof *gspca_dev;
1899 gspca_dev = kzalloc(dev_size, GFP_KERNEL);
1900 if (gspca_dev == NULL) {
1901 err("couldn't kzalloc gspca struct");
1902 return -EIO;
1903 }
1904 gspca_dev->dev = dev;
1905 gspca_dev->iface = interface->bInterfaceNumber;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001906 gspca_dev->nbalt = intf->num_altsetting;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001907 gspca_dev->sd_desc = sd_desc;
1908/* gspca_dev->users = 0; (done by kzalloc) */
1909 gspca_dev->nbufread = 2;
1910
1911 /* configure the subdriver */
1912 ret = gspca_dev->sd_desc->config(gspca_dev, id);
1913 if (ret < 0)
1914 goto out;
1915 ret = gspca_set_alt0(gspca_dev);
1916 if (ret < 0)
1917 goto out;
1918 gspca_set_default_mode(gspca_dev);
1919
1920 mutex_init(&gspca_dev->usb_lock);
1921 mutex_init(&gspca_dev->read_lock);
1922 mutex_init(&gspca_dev->queue_lock);
1923 init_waitqueue_head(&gspca_dev->wq);
1924
1925 /* init video stuff */
1926 memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
1927 gspca_dev->vdev.dev = &dev->dev;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001928 memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops);
1929 gspca_dev->vdev.fops = &gspca_dev->fops;
1930 gspca_dev->fops.owner = module; /* module protection */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001931 ret = video_register_device(&gspca_dev->vdev,
1932 VFL_TYPE_GRABBER,
1933 video_nr);
1934 if (ret < 0) {
1935 err("video_register_device err %d", ret);
1936 goto out;
1937 }
1938
1939 gspca_dev->present = 1;
1940 usb_set_intfdata(intf, gspca_dev);
1941 PDEBUG(D_PROBE, "probe ok");
1942 return 0;
1943out:
1944 kfree(gspca_dev);
1945 return ret;
1946}
1947EXPORT_SYMBOL(gspca_dev_probe);
1948
1949/*
1950 * USB disconnection
1951 *
1952 * This function must be called by the sub-driver
1953 * when the device disconnects, after the specific resources are freed.
1954 */
1955void gspca_disconnect(struct usb_interface *intf)
1956{
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001957 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001958
1959 if (!gspca_dev)
1960 return;
1961 gspca_dev->present = 0;
Hans de Goedee2997a72008-04-23 08:09:12 -03001962 mutex_lock(&gspca_dev->queue_lock);
1963 mutex_lock(&gspca_dev->usb_lock);
1964 gspca_dev->streaming = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001965 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001966 mutex_unlock(&gspca_dev->usb_lock);
Hans de Goedee2997a72008-04-23 08:09:12 -03001967 mutex_unlock(&gspca_dev->queue_lock);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001968 while (gspca_dev->users != 0) { /* wait until fully closed */
1969 atomic_inc(&gspca_dev->nevent);
1970 wake_up_interruptible(&gspca_dev->wq); /* wake processes */
1971 schedule();
1972 }
1973/* We don't want people trying to open up the device */
1974 video_unregister_device(&gspca_dev->vdev);
1975/* Free the memory */
1976 kfree(gspca_dev);
1977 PDEBUG(D_PROBE, "disconnect complete");
1978}
1979EXPORT_SYMBOL(gspca_disconnect);
1980
1981/* -- module insert / remove -- */
1982static int __init gspca_init(void)
1983{
1984 info("main v%s registered", version);
1985 return 0;
1986}
1987static void __exit gspca_exit(void)
1988{
1989 info("main deregistered");
1990}
1991
1992module_init(gspca_init);
1993module_exit(gspca_exit);
1994
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001995#ifdef VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001996module_param_named(debug, gspca_debug, int, 0644);
1997MODULE_PARM_DESC(debug,
1998 "Debug (bit) 0x01:error 0x02:probe 0x04:config"
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001999 " 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout"
2000 " 0x0100: v4l2");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002001#endif
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002002module_param(comp_fac, int, 0644);
2003MODULE_PARM_DESC(comp_fac,
2004 "Buffer size ratio when compressed in percent");