blob: f6d216316b11a990035d1d50871ecd759caf35be [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
Hans de Goede24c530b2008-07-04 17:55:18 -030046#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 4)
47static const char version[] = "2.1.4";
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 Moinea5ae2062008-07-04 11:16:16 -0300250 const __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
Hans de Goede24c530b2008-07-04 17:55:18 -0300394static int gspca_get_buff_size(struct gspca_dev *gspca_dev, int mode)
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300395{
396 unsigned int size;
397
Hans de Goede24c530b2008-07-04 17:55:18 -0300398 size = gspca_dev->cam.cam_mode[mode].width *
399 gspca_dev->cam.cam_mode[mode].height *
400 get_v4l2_depth(gspca_dev->cam.cam_mode[mode].pixfmt) / 8;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300401 if (!size)
402 return -ENOMEM;
Hans de Goede24c530b2008-07-04 17:55:18 -0300403
404 /* if compressed (JPEG), reduce the buffer size */
405 if (gspca_is_compressed(gspca_dev->cam.cam_mode[mode].pixfmt))
406 size = (size * comp_fac) / 100 + 600; /* (+ JPEG header sz) */
407
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300408 return size;
409}
410
411static int frame_alloc(struct gspca_dev *gspca_dev,
412 unsigned int count)
413{
414 struct gspca_frame *frame;
415 unsigned int frsz;
416 int i;
417
Hans de Goede24c530b2008-07-04 17:55:18 -0300418 frsz = gspca_get_buff_size(gspca_dev, gspca_dev->curr_mode);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300419 if (frsz < 0)
420 return frsz;
421 PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300422 if (count > GSPCA_MAX_FRAMES)
423 count = GSPCA_MAX_FRAMES;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300424 frsz = PAGE_ALIGN(frsz);
425 PDEBUG(D_STREAM, "new fr_sz: %d", frsz);
426 gspca_dev->frsz = frsz;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300427 if (gspca_dev->memory == V4L2_MEMORY_MMAP) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300428 gspca_dev->frbuf = rvmalloc(frsz * count);
429 if (!gspca_dev->frbuf) {
430 err("frame alloc failed");
431 return -ENOMEM;
432 }
433 }
434 gspca_dev->nframes = count;
435 for (i = 0; i < count; i++) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300436 frame = &gspca_dev->frame[i];
437 frame->v4l2_buf.index = i;
438 frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
439 frame->v4l2_buf.flags = 0;
440 frame->v4l2_buf.field = V4L2_FIELD_NONE;
441 frame->v4l2_buf.length = frsz;
442 frame->v4l2_buf.memory = gspca_dev->memory;
443 frame->v4l2_buf.sequence = 0;
444 if (gspca_dev->memory == V4L2_MEMORY_MMAP) {
445 frame->data = frame->data_end =
446 gspca_dev->frbuf + i * frsz;
447 frame->v4l2_buf.m.offset = i * frsz;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300448 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300449 }
450 gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
451 gspca_dev->last_packet_type = DISCARD_PACKET;
452 gspca_dev->sequence = 0;
453 atomic_set(&gspca_dev->nevent, 0);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300454 return 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300455}
456
457static void frame_free(struct gspca_dev *gspca_dev)
458{
459 int i;
460
461 PDEBUG(D_STREAM, "frame free");
462 if (gspca_dev->frbuf != 0) {
463 rvfree(gspca_dev->frbuf,
464 gspca_dev->nframes * gspca_dev->frsz);
465 gspca_dev->frbuf = NULL;
466 for (i = 0; i < gspca_dev->nframes; i++)
467 gspca_dev->frame[i].data = NULL;
468 }
469 gspca_dev->nframes = 0;
470}
471
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300472static void destroy_urbs(struct gspca_dev *gspca_dev)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300473{
474 struct urb *urb;
475 unsigned int i;
476
477 PDEBUG(D_STREAM, "kill transfer");
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300478 for (i = 0; i < MAX_NURBS; ++i) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300479 urb = gspca_dev->urb[i];
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300480 if (urb == NULL)
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300481 break;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300482
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300483 gspca_dev->urb[i] = NULL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300484 usb_kill_urb(urb);
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300485 if (urb->transfer_buffer != 0)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300486 usb_buffer_free(gspca_dev->dev,
487 urb->transfer_buffer_length,
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300488 urb->transfer_buffer,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300489 urb->transfer_dma);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300490 usb_free_urb(urb);
491 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300492}
493
494/*
495 * search an input isochronous endpoint in an alternate setting
496 */
497static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
498 __u8 epaddr)
499{
500 struct usb_host_endpoint *ep;
501 int i, attr;
502
503 epaddr |= USB_DIR_IN;
504 for (i = 0; i < alt->desc.bNumEndpoints; i++) {
505 ep = &alt->endpoint[i];
506 if (ep->desc.bEndpointAddress == epaddr) {
507 attr = ep->desc.bmAttributes
508 & USB_ENDPOINT_XFERTYPE_MASK;
509 if (attr == USB_ENDPOINT_XFER_ISOC)
510 return ep;
511 break;
512 }
513 }
514 return NULL;
515}
516
517/*
518 * search an input isochronous endpoint
519 *
520 * The endpoint is defined by the subdriver.
521 * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
522 * This routine may be called many times when the bandwidth is too small
523 * (the bandwidth is checked on urb submit).
524 */
525struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
526{
527 struct usb_interface *intf;
528 struct usb_host_endpoint *ep;
529 int i, ret;
530
531 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300532 ep = NULL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300533 i = gspca_dev->alt; /* previous alt setting */
534 while (--i > 0) { /* alt 0 is unusable */
535 ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr);
536 if (ep)
537 break;
538 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300539 if (ep == NULL) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300540 err("no ISOC endpoint found");
541 return NULL;
542 }
543 PDEBUG(D_STREAM, "use ISOC alt %d ep 0x%02x",
544 i, ep->desc.bEndpointAddress);
545 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
546 if (ret < 0) {
547 err("set interface err %d", ret);
548 return NULL;
549 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300550 gspca_dev->alt = i; /* memorize the current alt setting */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300551 return ep;
552}
553
554/*
555 * create the isochronous URBs
556 */
557static int create_urbs(struct gspca_dev *gspca_dev,
558 struct usb_host_endpoint *ep)
559{
560 struct urb *urb;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300561 int n, nurbs, i, psize, npkt, bsize;
562 usb_complete_t usb_complete;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300563
564 /* calculate the packet size and the number of packets */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300565 psize = le16_to_cpu(ep->desc.wMaxPacketSize);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300566
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300567 /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
568 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
569 npkt = ISO_MAX_SIZE / psize;
570 if (npkt > ISO_MAX_PKT)
571 npkt = ISO_MAX_PKT;
572 bsize = psize * npkt;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300573 PDEBUG(D_STREAM,
574 "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300575/*fixme:don't submit all URBs when userptr*/
Jean-Francois Moine82643d02008-07-02 09:14:56 -0300576 if (gspca_dev->memory != V4L2_MEMORY_USERPTR) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300577 usb_complete = isoc_irq_mmap;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300578 nurbs = DEF_NURBS;
579 } else {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300580 usb_complete = isoc_irq_user;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300581 nurbs = USR_NURBS;
582 }
583 gspca_dev->nurbs = nurbs;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300584 for (n = 0; n < nurbs; n++) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300585 urb = usb_alloc_urb(npkt, GFP_KERNEL);
586 if (!urb) {
587 err("usb_alloc_urb failed");
588 return -ENOMEM;
589 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300590 urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300591 bsize,
592 GFP_KERNEL,
593 &urb->transfer_dma);
594
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300595 if (urb->transfer_buffer == NULL) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300596 usb_free_urb(urb);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300597 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300598 err("usb_buffer_urb failed");
599 return -ENOMEM;
600 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300601 gspca_dev->urb[n] = urb;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300602 urb->dev = gspca_dev->dev;
603 urb->context = gspca_dev;
604 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
605 ep->desc.bEndpointAddress);
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300606 urb->transfer_flags = URB_ISO_ASAP
607 | URB_NO_TRANSFER_DMA_MAP;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300608 urb->interval = ep->desc.bInterval;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300609 urb->complete = usb_complete;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300610 urb->number_of_packets = npkt;
611 urb->transfer_buffer_length = bsize;
612 for (i = 0; i < npkt; i++) {
613 urb->iso_frame_desc[i].length = psize;
614 urb->iso_frame_desc[i].offset = psize * i;
615 }
616 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300617 gspca_dev->urb_in = gspca_dev->urb_out = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300618 return 0;
619}
620
621/*
622 * start the USB transfer
623 */
624static int gspca_init_transfer(struct gspca_dev *gspca_dev)
625{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300626 struct usb_host_endpoint *ep;
627 int n, ret;
628
Hans de Goedee2997a72008-04-23 08:09:12 -0300629 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
630 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300631
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300632 /* set the higher alternate setting and
633 * loop until urb submit succeeds */
634 gspca_dev->alt = gspca_dev->nbalt;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300635 for (;;) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300636 PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300637 ep = get_isoc_ep(gspca_dev);
638 if (ep == NULL) {
639 ret = -EIO;
640 goto out;
641 }
642 ret = create_urbs(gspca_dev, ep);
643 if (ret < 0)
644 goto out;
645
646 /* start the cam */
647 gspca_dev->sd_desc->start(gspca_dev);
648 gspca_dev->streaming = 1;
649 atomic_set(&gspca_dev->nevent, 0);
650
651 /* submit the URBs */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300652 for (n = 0; n < gspca_dev->nurbs; n++) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300653 ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300654 if (ret < 0) {
655 PDEBUG(D_ERR|D_STREAM,
656 "usb_submit_urb [%d] err %d", n, ret);
Hans de Goedee2997a72008-04-23 08:09:12 -0300657 gspca_dev->streaming = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300658 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300659 if (ret == -ENOSPC)
660 break; /* try the previous alt */
661 goto out;
662 }
663 }
664 if (ret >= 0)
665 break;
666 }
667out:
668 mutex_unlock(&gspca_dev->usb_lock);
669 return ret;
670}
671
672static int gspca_set_alt0(struct gspca_dev *gspca_dev)
673{
674 int ret;
675
676 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
677 if (ret < 0)
678 PDEBUG(D_ERR|D_STREAM, "set interface 0 err %d", ret);
679 return ret;
680}
681
Hans de Goedee2997a72008-04-23 08:09:12 -0300682/* Note both the queue and the usb lock should be hold when calling this */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300683static void gspca_stream_off(struct gspca_dev *gspca_dev)
684{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300685 gspca_dev->streaming = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300686 atomic_set(&gspca_dev->nevent, 0);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300687 if (gspca_dev->present) {
688 gspca_dev->sd_desc->stopN(gspca_dev);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300689 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300690 gspca_set_alt0(gspca_dev);
691 gspca_dev->sd_desc->stop0(gspca_dev);
692 PDEBUG(D_STREAM, "stream off OK");
693 } else {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300694 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300695 atomic_inc(&gspca_dev->nevent);
696 wake_up_interruptible(&gspca_dev->wq);
697 PDEBUG(D_ERR|D_STREAM, "stream off no device ??");
698 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300699}
700
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300701static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300702{
703 int i;
704
705 i = gspca_dev->cam.nmodes - 1; /* take the highest mode */
706 gspca_dev->curr_mode = i;
707 gspca_dev->width = gspca_dev->cam.cam_mode[i].width;
708 gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
709 gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixfmt;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300710}
711
712static int wxh_to_mode(struct gspca_dev *gspca_dev,
713 int width, int height)
714{
715 int i;
716
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300717 for (i = gspca_dev->cam.nmodes; --i > 0; ) {
718 if (width >= gspca_dev->cam.cam_mode[i].width
719 && height >= gspca_dev->cam.cam_mode[i].height)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300720 break;
721 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300722 return i;
723}
724
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300725/*
726 * search a mode with the right pixel format
727 */
728static int gspca_get_mode(struct gspca_dev *gspca_dev,
729 int mode,
730 int pixfmt)
731{
732 int modeU, modeD;
733
734 modeU = modeD = mode;
735 while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) {
736 if (--modeD >= 0) {
737 if (gspca_dev->cam.cam_mode[modeD].pixfmt == pixfmt)
738 return modeD;
739 }
740 if (++modeU < gspca_dev->cam.nmodes) {
741 if (gspca_dev->cam.cam_mode[modeU].pixfmt == pixfmt)
742 return modeU;
743 }
744 }
745 return -EINVAL;
746}
747
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300748static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300749 struct v4l2_fmtdesc *fmtdesc)
750{
751 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300752 int i, j, index;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300753 __u32 fmt_tb[8];
754
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300755 /* give an index to each format */
756 index = 0;
757 j = 0;
758 for (i = gspca_dev->cam.nmodes; --i >= 0; ) {
759 fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixfmt;
760 j = 0;
761 for (;;) {
762 if (fmt_tb[j] == fmt_tb[index])
763 break;
764 j++;
765 }
766 if (j == index) {
767 if (fmtdesc->index == index)
768 break; /* new format */
769 index++;
770 if (index >= sizeof fmt_tb / sizeof fmt_tb[0])
771 return -EINVAL;
772 }
773 }
774 if (i < 0)
775 return -EINVAL; /* no more format */
776
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300777 fmtdesc->pixelformat = fmt_tb[index];
778 if (gspca_is_compressed(fmt_tb[index]))
779 fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300780 fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300781 fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
782 fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
783 fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff;
784 fmtdesc->description[3] = fmtdesc->pixelformat >> 24;
785 fmtdesc->description[4] = '\0';
786 return 0;
787}
788
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300789static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300790 struct v4l2_format *fmt)
791{
792 struct gspca_dev *gspca_dev = priv;
793
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300794 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
795 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300796 fmt->fmt.pix.width = gspca_dev->width;
797 fmt->fmt.pix.height = gspca_dev->height;
798 fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300799 fmt->fmt.pix.field = V4L2_FIELD_NONE;
800 fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat)
801 * fmt->fmt.pix.width / 8;
Hans de Goede24c530b2008-07-04 17:55:18 -0300802 fmt->fmt.pix.sizeimage = gspca_get_buff_size(gspca_dev,
803 gspca_dev->curr_mode);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300804/* (should be in the subdriver) */
805 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
806 fmt->fmt.pix.priv = 0;
807 return 0;
808}
809
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300810static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300811 struct v4l2_format *fmt)
812{
Hans de Goede24c530b2008-07-04 17:55:18 -0300813 int w, h, mode, mode2;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300814
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300815 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
816 return -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300817 w = fmt->fmt.pix.width;
818 h = fmt->fmt.pix.height;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300819
820 /* (luvcview problem) */
821 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
822 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
Hans de Goeded646e702008-07-03 06:48:22 -0300823#ifdef CONFIG_VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300824 if (gspca_debug & D_CONF)
825 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
826#endif
827 /* search the closest mode for width and height */
828 mode = wxh_to_mode(gspca_dev, w, h);
829
830 /* OK if right palette */
831 if (gspca_dev->cam.cam_mode[mode].pixfmt != fmt->fmt.pix.pixelformat) {
832
833 /* else, search the closest mode with the same pixel format */
834 mode2 = gspca_get_mode(gspca_dev, mode,
835 fmt->fmt.pix.pixelformat);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300836 if (mode2 >= 0) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300837 mode = mode2;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300838 } else {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300839
840 /* no chance, return this mode */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300841 fmt->fmt.pix.pixelformat =
842 gspca_dev->cam.cam_mode[mode].pixfmt;
Hans de Goeded646e702008-07-03 06:48:22 -0300843#ifdef CONFIG_VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300844 if (gspca_debug & D_CONF) {
845 PDEBUG_MODE("new format",
846 fmt->fmt.pix.pixelformat,
847 gspca_dev->cam.cam_mode[mode].width,
848 gspca_dev->cam.cam_mode[mode].height);
849 }
850#endif
851 }
852 }
853 fmt->fmt.pix.width = gspca_dev->cam.cam_mode[mode].width;
854 fmt->fmt.pix.height = gspca_dev->cam.cam_mode[mode].height;
Hans de Goede24c530b2008-07-04 17:55:18 -0300855 fmt->fmt.pix.field = V4L2_FIELD_NONE;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300856 fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat)
857 * fmt->fmt.pix.width / 8;
Hans de Goede24c530b2008-07-04 17:55:18 -0300858 fmt->fmt.pix.sizeimage = gspca_get_buff_size(gspca_dev, mode);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300859 return mode; /* used when s_fmt */
860}
861
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300862static int vidioc_try_fmt_vid_cap(struct file *file,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300863 void *priv,
864 struct v4l2_format *fmt)
865{
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300866 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300867 int ret;
868
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300869 ret = try_fmt_vid_cap(gspca_dev, fmt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300870 if (ret < 0)
871 return ret;
872 return 0;
873}
874
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300875static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300876 struct v4l2_format *fmt)
877{
878 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300879 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300880
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300881#ifdef CONFIG_VIDEO_V4L1_COMPAT
882 /* if v4l1 got JPEG */
883 if (fmt->fmt.pix.pixelformat == 0
884 && gspca_dev->streaming) {
885 fmt->fmt.pix.width = gspca_dev->width;
886 fmt->fmt.pix.height = gspca_dev->height;
887 fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
888 return 0;
889 }
890#endif
Hans de Goedee2997a72008-04-23 08:09:12 -0300891 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
892 return -ERESTARTSYS;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300893
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300894 ret = try_fmt_vid_cap(gspca_dev, fmt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300895 if (ret < 0)
896 goto out;
897
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300898 if (gspca_dev->nframes != 0
899 && fmt->fmt.pix.sizeimage > gspca_dev->frsz) {
900 ret = -EINVAL;
901 goto out;
902 }
903
Jean-Francois Moine50a871f2008-06-30 19:47:33 -0300904 if (ret == gspca_dev->curr_mode) {
905 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300906 goto out; /* same mode */
Jean-Francois Moine50a871f2008-06-30 19:47:33 -0300907 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300908
909 if (gspca_dev->streaming) {
910 ret = -EBUSY;
911 goto out;
Hans de Goedee2997a72008-04-23 08:09:12 -0300912 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300913 gspca_dev->width = fmt->fmt.pix.width;
914 gspca_dev->height = fmt->fmt.pix.height;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300915 gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
916 gspca_dev->curr_mode = ret;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300917
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300918 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300919out:
920 mutex_unlock(&gspca_dev->queue_lock);
921 return ret;
922}
923
924static int dev_open(struct inode *inode, struct file *file)
925{
926 struct gspca_dev *gspca_dev;
927 int ret;
928
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300929 PDEBUG(D_STREAM, "%s open", current->comm);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300930 gspca_dev = (struct gspca_dev *) video_devdata(file);
Hans de Goedee2997a72008-04-23 08:09:12 -0300931 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
932 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300933 if (!gspca_dev->present) {
934 ret = -ENODEV;
935 goto out;
936 }
937
938 /* if not done yet, initialize the sensor */
939 if (gspca_dev->users == 0) {
Hans de Goedee2997a72008-04-23 08:09:12 -0300940 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
941 ret = -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300942 goto out;
Hans de Goedee2997a72008-04-23 08:09:12 -0300943 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300944 ret = gspca_dev->sd_desc->open(gspca_dev);
945 mutex_unlock(&gspca_dev->usb_lock);
946 if (ret != 0) {
947 PDEBUG(D_ERR|D_CONF, "init device failed %d", ret);
948 goto out;
949 }
Hans de Goedee2997a72008-04-23 08:09:12 -0300950 } else if (gspca_dev->users > 4) { /* (arbitrary value) */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300951 ret = -EBUSY;
952 goto out;
953 }
954 gspca_dev->users++;
955 file->private_data = gspca_dev;
Hans de Goeded646e702008-07-03 06:48:22 -0300956#ifdef CONFIG_VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300957 /* activate the v4l2 debug */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300958 if (gspca_debug & D_V4L2)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300959 gspca_dev->vdev.debug |= 3;
960 else
961 gspca_dev->vdev.debug &= ~3;
962#endif
963out:
964 mutex_unlock(&gspca_dev->queue_lock);
965 if (ret != 0)
966 PDEBUG(D_ERR|D_STREAM, "open failed err %d", ret);
967 else
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300968 PDEBUG(D_STREAM, "open done");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300969 return ret;
970}
971
972static int dev_close(struct inode *inode, struct file *file)
973{
974 struct gspca_dev *gspca_dev = file->private_data;
975
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300976 PDEBUG(D_STREAM, "%s close", current->comm);
Hans de Goedee2997a72008-04-23 08:09:12 -0300977 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
978 return -ERESTARTSYS;
979 gspca_dev->users--;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300980
981 /* if the file did capture, free the streaming resources */
982 if (gspca_dev->capt_file == file) {
983 mutex_lock(&gspca_dev->usb_lock);
984 if (gspca_dev->streaming)
985 gspca_stream_off(gspca_dev);
986 gspca_dev->sd_desc->close(gspca_dev);
987 mutex_unlock(&gspca_dev->usb_lock);
988 frame_free(gspca_dev);
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300989 gspca_dev->capt_file = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300990 gspca_dev->memory = GSPCA_MEMORY_NO;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300991 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300992 file->private_data = NULL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300993 mutex_unlock(&gspca_dev->queue_lock);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300994 PDEBUG(D_STREAM, "close done");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300995 return 0;
996}
997
998static int vidioc_querycap(struct file *file, void *priv,
999 struct v4l2_capability *cap)
1000{
1001 struct gspca_dev *gspca_dev = priv;
1002
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001003 memset(cap, 0, sizeof *cap);
1004 strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
1005 strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card);
1006 strncpy(cap->bus_info, gspca_dev->dev->bus->bus_name,
1007 sizeof cap->bus_info);
1008 cap->version = DRIVER_VERSION_NUMBER;
1009 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
1010 | V4L2_CAP_STREAMING
1011 | V4L2_CAP_READWRITE;
1012 return 0;
1013}
1014
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001015/* the use of V4L2_CTRL_FLAG_NEXT_CTRL asks for the controls to be sorted */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001016static int vidioc_queryctrl(struct file *file, void *priv,
1017 struct v4l2_queryctrl *q_ctrl)
1018{
1019 struct gspca_dev *gspca_dev = priv;
1020 int i;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001021 u32 id;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001022
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001023 id = q_ctrl->id;
1024 if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
1025 id &= V4L2_CTRL_ID_MASK;
1026 id++;
1027 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
1028 if (id >= gspca_dev->sd_desc->ctrls[i].qctrl.id) {
1029 memcpy(q_ctrl,
1030 &gspca_dev->sd_desc->ctrls[i].qctrl,
1031 sizeof *q_ctrl);
1032 return 0;
1033 }
1034 }
1035 return -EINVAL;
1036 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001037 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001038 if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001039 memcpy(q_ctrl,
1040 &gspca_dev->sd_desc->ctrls[i].qctrl,
1041 sizeof *q_ctrl);
1042 return 0;
1043 }
1044 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001045 if (id >= V4L2_CID_BASE
1046 && id <= V4L2_CID_LASTP1) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001047 q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
1048 return 0;
1049 }
1050 return -EINVAL;
1051}
1052
1053static int vidioc_s_ctrl(struct file *file, void *priv,
1054 struct v4l2_control *ctrl)
1055{
1056 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001057 const struct ctrl *ctrls;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001058 int i, ret;
1059
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001060 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
1061 i < gspca_dev->sd_desc->nctrls;
1062 i++, ctrls++) {
1063 if (ctrl->id != ctrls->qctrl.id)
1064 continue;
1065 if (ctrl->value < ctrls->qctrl.minimum
1066 && ctrl->value > ctrls->qctrl.maximum)
1067 return -ERANGE;
1068 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
Hans de Goedee2997a72008-04-23 08:09:12 -03001069 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1070 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001071 ret = ctrls->set(gspca_dev, ctrl->value);
1072 mutex_unlock(&gspca_dev->usb_lock);
1073 return ret;
1074 }
1075 return -EINVAL;
1076}
1077
1078static int vidioc_g_ctrl(struct file *file, void *priv,
1079 struct v4l2_control *ctrl)
1080{
1081 struct gspca_dev *gspca_dev = priv;
1082
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001083 const struct ctrl *ctrls;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001084 int i, ret;
1085
1086 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
1087 i < gspca_dev->sd_desc->nctrls;
1088 i++, ctrls++) {
1089 if (ctrl->id != ctrls->qctrl.id)
1090 continue;
Hans de Goedee2997a72008-04-23 08:09:12 -03001091 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1092 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001093 ret = ctrls->get(gspca_dev, &ctrl->value);
1094 mutex_unlock(&gspca_dev->usb_lock);
1095 return ret;
1096 }
1097 return -EINVAL;
1098}
1099
1100static int vidioc_querymenu(struct file *file, void *priv,
1101 struct v4l2_querymenu *qmenu)
1102{
1103 struct gspca_dev *gspca_dev = priv;
1104
1105 if (!gspca_dev->sd_desc->querymenu)
1106 return -EINVAL;
1107 return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu);
1108}
1109
1110static int vidioc_enum_input(struct file *file, void *priv,
1111 struct v4l2_input *input)
1112{
1113 struct gspca_dev *gspca_dev = priv;
1114
1115 if (input->index != 0)
1116 return -EINVAL;
1117 memset(input, 0, sizeof *input);
1118 input->type = V4L2_INPUT_TYPE_CAMERA;
1119 strncpy(input->name, gspca_dev->sd_desc->name,
1120 sizeof input->name);
1121 return 0;
1122}
1123
1124static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1125{
1126 *i = 0;
1127 return 0;
1128}
1129
1130static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1131{
1132 if (i > 0)
1133 return -EINVAL;
1134 return (0);
1135}
1136
1137static int vidioc_reqbufs(struct file *file, void *priv,
1138 struct v4l2_requestbuffers *rb)
1139{
1140 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001141 int i, ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001142
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001143 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1144 return -EINVAL;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001145 switch (rb->memory) {
1146 case V4L2_MEMORY_MMAP:
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001147 case V4L2_MEMORY_USERPTR:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001148 break;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001149 default:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001150 return -EINVAL;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001151 }
Hans de Goedee2997a72008-04-23 08:09:12 -03001152 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1153 return -ERESTARTSYS;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001154
1155 for (i = 0; i < gspca_dev->nframes; i++) {
1156 if (gspca_dev->frame[i].vma_use_count) {
1157 ret = -EBUSY;
1158 goto out;
1159 }
1160 }
1161
1162 /* only one file may do capture */
1163 if ((gspca_dev->capt_file != 0 && gspca_dev->capt_file != file)
1164 || gspca_dev->streaming) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001165 ret = -EBUSY;
1166 goto out;
1167 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001168
1169 if (rb->count == 0) { /* unrequest? */
1170 frame_free(gspca_dev);
1171 gspca_dev->capt_file = 0;
1172 } else {
1173 gspca_dev->memory = rb->memory;
1174 ret = frame_alloc(gspca_dev, rb->count);
1175 if (ret == 0) {
1176 rb->count = gspca_dev->nframes;
1177 gspca_dev->capt_file = file;
1178 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001179 }
1180out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001181 mutex_unlock(&gspca_dev->queue_lock);
1182 PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count);
1183 return ret;
1184}
1185
1186static int vidioc_querybuf(struct file *file, void *priv,
1187 struct v4l2_buffer *v4l2_buf)
1188{
1189 struct gspca_dev *gspca_dev = priv;
1190 struct gspca_frame *frame;
1191
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001192 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1193 || v4l2_buf->index < 0
1194 || v4l2_buf->index >= gspca_dev->nframes)
1195 return -EINVAL;
1196
1197 frame = &gspca_dev->frame[v4l2_buf->index];
1198 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1199 return 0;
1200}
1201
1202static int vidioc_streamon(struct file *file, void *priv,
1203 enum v4l2_buf_type buf_type)
1204{
1205 struct gspca_dev *gspca_dev = priv;
1206 int ret;
1207
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001208 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1209 return -EINVAL;
Hans de Goedee2997a72008-04-23 08:09:12 -03001210 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1211 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001212 if (!gspca_dev->present) {
1213 ret = -ENODEV;
1214 goto out;
1215 }
1216 if (gspca_dev->nframes == 0) {
1217 ret = -EINVAL;
1218 goto out;
1219 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001220 if (gspca_dev->capt_file != file) {
1221 ret = -EINVAL;
1222 goto out;
1223 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001224 if (!gspca_dev->streaming) {
1225 ret = gspca_init_transfer(gspca_dev);
1226 if (ret < 0)
1227 goto out;
1228 }
Hans de Goeded646e702008-07-03 06:48:22 -03001229#ifdef CONFIG_VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001230 if (gspca_debug & D_STREAM) {
1231 PDEBUG_MODE("stream on OK",
1232 gspca_dev->pixfmt,
1233 gspca_dev->width,
1234 gspca_dev->height);
1235 }
1236#endif
Hans de Goedee2997a72008-04-23 08:09:12 -03001237 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001238out:
1239 mutex_unlock(&gspca_dev->queue_lock);
1240 return ret;
1241}
1242
1243static int vidioc_streamoff(struct file *file, void *priv,
1244 enum v4l2_buf_type buf_type)
1245{
1246 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001247 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001248
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001249 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1250 return -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001251 if (!gspca_dev->streaming)
1252 return 0;
1253 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1254 return -ERESTARTSYS;
1255 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
1256 ret = -ERESTARTSYS;
1257 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001258 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001259 if (gspca_dev->capt_file != file) {
1260 ret = -EINVAL;
1261 goto out2;
1262 }
1263 gspca_stream_off(gspca_dev);
1264 ret = 0;
1265out2:
1266 mutex_unlock(&gspca_dev->usb_lock);
1267out:
1268 mutex_unlock(&gspca_dev->queue_lock);
1269 return ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001270}
1271
1272static int vidioc_g_jpegcomp(struct file *file, void *priv,
1273 struct v4l2_jpegcompression *jpegcomp)
1274{
1275 struct gspca_dev *gspca_dev = priv;
1276 int ret;
1277
1278 if (!gspca_dev->sd_desc->get_jcomp)
1279 return -EINVAL;
Hans de Goedee2997a72008-04-23 08:09:12 -03001280 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1281 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001282 ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
1283 mutex_unlock(&gspca_dev->usb_lock);
1284 return ret;
1285}
1286
1287static int vidioc_s_jpegcomp(struct file *file, void *priv,
1288 struct v4l2_jpegcompression *jpegcomp)
1289{
1290 struct gspca_dev *gspca_dev = priv;
1291 int ret;
1292
Hans de Goedee2997a72008-04-23 08:09:12 -03001293 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1294 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001295 if (!gspca_dev->sd_desc->set_jcomp)
1296 return -EINVAL;
1297 ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
1298 mutex_unlock(&gspca_dev->usb_lock);
1299 return ret;
1300}
1301
1302static int vidioc_g_parm(struct file *filp, void *priv,
1303 struct v4l2_streamparm *parm)
1304{
1305 struct gspca_dev *gspca_dev = priv;
1306
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001307 memset(parm, 0, sizeof *parm);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001308 parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1309 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1310 return 0;
1311}
1312
1313static int vidioc_s_parm(struct file *filp, void *priv,
1314 struct v4l2_streamparm *parm)
1315{
1316 struct gspca_dev *gspca_dev = priv;
1317 int n;
1318
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001319 n = parm->parm.capture.readbuffers;
1320 if (n == 0 || n > GSPCA_MAX_FRAMES)
1321 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1322 else
1323 gspca_dev->nbufread = n;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001324 return 0;
1325}
1326
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001327static int vidioc_s_std(struct file *filp, void *priv,
1328 v4l2_std_id *parm)
1329{
1330 return 0;
1331}
1332
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001333#ifdef CONFIG_VIDEO_V4L1_COMPAT
1334static int vidiocgmbuf(struct file *file, void *priv,
1335 struct video_mbuf *mbuf)
1336{
1337 struct gspca_dev *gspca_dev = file->private_data;
1338 int i;
1339
1340 PDEBUG(D_STREAM, "cgmbuf");
1341 if (gspca_dev->nframes == 0) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001342 int ret;
1343
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001344 {
1345 struct v4l2_format fmt;
1346
1347 memset(&fmt, 0, sizeof fmt);
1348 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1349 i = gspca_dev->cam.nmodes - 1; /* highest mode */
1350 fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width;
1351 fmt.fmt.pix.height = gspca_dev->cam.cam_mode[i].height;
1352 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -03001353 ret = vidioc_s_fmt_vid_cap(file, priv, &fmt);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001354 if (ret != 0)
1355 return ret;
1356 }
1357 {
1358 struct v4l2_requestbuffers rb;
1359
1360 memset(&rb, 0, sizeof rb);
1361 rb.count = 4;
1362 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1363 rb.memory = V4L2_MEMORY_MMAP;
1364 ret = vidioc_reqbufs(file, priv, &rb);
1365 if (ret != 0)
1366 return ret;
1367 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001368 }
1369 mbuf->frames = gspca_dev->nframes;
1370 mbuf->size = gspca_dev->frsz * gspca_dev->nframes;
1371 for (i = 0; i < mbuf->frames; i++)
1372 mbuf->offsets[i] = gspca_dev->frame[i].v4l2_buf.m.offset;
1373 return 0;
1374}
1375#endif
1376
1377static int dev_mmap(struct file *file, struct vm_area_struct *vma)
1378{
1379 struct gspca_dev *gspca_dev = file->private_data;
1380 struct gspca_frame *frame = 0;
1381 struct page *page;
1382 unsigned long addr, start, size;
1383 int i, ret;
1384#ifdef CONFIG_VIDEO_V4L1_COMPAT
1385 int compat = 0;
1386#endif
1387
1388 start = vma->vm_start;
1389 size = vma->vm_end - vma->vm_start;
1390 PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size);
1391
Hans de Goedee2997a72008-04-23 08:09:12 -03001392 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1393 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001394 if (!gspca_dev->present) {
1395 ret = -ENODEV;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001396 goto out;
1397 }
1398 if (gspca_dev->capt_file != file) {
1399 ret = -EINVAL;
1400 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001401 }
1402
1403 for (i = 0; i < gspca_dev->nframes; ++i) {
1404 if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) {
1405 PDEBUG(D_STREAM, "mmap bad memory type");
1406 break;
1407 }
1408 if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT)
1409 == vma->vm_pgoff) {
1410 frame = &gspca_dev->frame[i];
1411 break;
1412 }
1413 }
1414 if (frame == 0) {
1415 PDEBUG(D_STREAM, "mmap no frame buffer found");
1416 ret = -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001417 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001418 }
1419#ifdef CONFIG_VIDEO_V4L1_COMPAT
1420 if (i == 0 && size == frame->v4l2_buf.length * gspca_dev->nframes)
1421 compat = 1;
1422 else
1423#endif
1424 if (size != frame->v4l2_buf.length) {
1425 PDEBUG(D_STREAM, "mmap bad size");
1426 ret = -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001427 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001428 }
1429
1430 /*
1431 * - VM_IO marks the area as being a mmaped region for I/O to a
1432 * device. It also prevents the region from being core dumped.
1433 */
1434 vma->vm_flags |= VM_IO;
1435
1436 addr = (unsigned long) frame->data;
1437 while (size > 0) {
1438 page = vmalloc_to_page((void *) addr);
1439 ret = vm_insert_page(vma, start, page);
1440 if (ret < 0)
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001441 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001442 start += PAGE_SIZE;
1443 addr += PAGE_SIZE;
1444 size -= PAGE_SIZE;
1445 }
1446
1447 vma->vm_ops = &gspca_vm_ops;
1448 vma->vm_private_data = frame;
1449 gspca_vm_open(vma);
1450#ifdef CONFIG_VIDEO_V4L1_COMPAT
1451 if (compat) {
1452/*fixme: ugly*/
1453 for (i = 1; i < gspca_dev->nframes; ++i)
1454 gspca_dev->frame[i].v4l2_buf.flags |=
1455 V4L2_BUF_FLAG_MAPPED;
1456 }
1457#endif
Hans de Goedee2997a72008-04-23 08:09:12 -03001458 ret = 0;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001459out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001460 mutex_unlock(&gspca_dev->queue_lock);
1461 return ret;
1462}
1463
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001464/*
1465 * wait for a video frame
1466 *
1467 * If a frame is ready, its index is returned.
1468 */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001469static int frame_wait(struct gspca_dev *gspca_dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001470 int nonblock_ing)
1471{
1472 struct gspca_frame *frame;
1473 int i, j, ret;
1474
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001475 /* if userptr, treat the awaiting URBs */
1476 if (gspca_dev->memory == V4L2_MEMORY_USERPTR)
1477 isoc_transfer(gspca_dev);
1478
1479 /* check if a frame is ready */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001480 i = gspca_dev->fr_o;
1481 j = gspca_dev->fr_queue[i];
1482 frame = &gspca_dev->frame[j];
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001483 if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) {
1484 atomic_dec(&gspca_dev->nevent);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001485 goto ok;
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001486 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001487 if (nonblock_ing) /* no frame yet */
1488 return -EAGAIN;
1489
1490 /* wait till a frame is ready */
1491 for (;;) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001492 ret = wait_event_interruptible_timeout(gspca_dev->wq,
1493 atomic_read(&gspca_dev->nevent) > 0,
1494 msecs_to_jiffies(3000));
1495 if (ret <= 0) {
1496 if (ret < 0)
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001497 return ret; /* interrupt */
1498 return -EIO; /* timeout */
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001499 }
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001500 atomic_dec(&gspca_dev->nevent);
Hans de Goedee2997a72008-04-23 08:09:12 -03001501 if (!gspca_dev->streaming || !gspca_dev->present)
1502 return -EIO;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001503 if (gspca_dev->memory == V4L2_MEMORY_USERPTR)
1504 isoc_transfer(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001505 i = gspca_dev->fr_o;
1506 j = gspca_dev->fr_queue[i];
1507 frame = &gspca_dev->frame[j];
1508 if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1509 break;
1510 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001511ok:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001512 gspca_dev->fr_o = (i + 1) % gspca_dev->nframes;
1513 PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d",
1514 gspca_dev->fr_q,
1515 gspca_dev->fr_i,
1516 gspca_dev->fr_o);
Hans de Goedee2997a72008-04-23 08:09:12 -03001517
1518 if (gspca_dev->sd_desc->dq_callback)
1519 gspca_dev->sd_desc->dq_callback(gspca_dev);
1520
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001521 return j;
1522}
1523
1524/*
1525 * dequeue a video buffer
1526 *
1527 * If nonblock_ing is false, block until a buffer is available.
1528 */
1529static int vidioc_dqbuf(struct file *file, void *priv,
1530 struct v4l2_buffer *v4l2_buf)
1531{
1532 struct gspca_dev *gspca_dev = priv;
1533 struct gspca_frame *frame;
1534 int i, ret;
1535
1536 PDEBUG(D_FRAM, "dqbuf");
1537 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1538 || (v4l2_buf->memory != V4L2_MEMORY_MMAP
1539 && v4l2_buf->memory != V4L2_MEMORY_USERPTR))
1540 return -EINVAL;
1541 if (!gspca_dev->streaming)
1542 return -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001543 if (gspca_dev->capt_file != file) {
1544 ret = -EINVAL;
1545 goto out;
1546 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001547
1548 /* only one read */
1549 if (mutex_lock_interruptible(&gspca_dev->read_lock))
1550 return -ERESTARTSYS;
1551
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001552 ret = frame_wait(gspca_dev, file->f_flags & O_NONBLOCK);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001553 if (ret < 0)
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001554 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001555 i = ret; /* frame index */
1556 frame = &gspca_dev->frame[i];
1557 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
1558 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1559 PDEBUG(D_FRAM, "dqbuf %d", i);
1560 ret = 0;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001561out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001562 mutex_unlock(&gspca_dev->read_lock);
1563 return ret;
1564}
1565
1566/*
1567 * queue a video buffer
1568 *
1569 * Attempting to queue a buffer that has already been
1570 * queued will return -EINVAL.
1571 */
1572static int vidioc_qbuf(struct file *file, void *priv,
1573 struct v4l2_buffer *v4l2_buf)
1574{
1575 struct gspca_dev *gspca_dev = priv;
1576 struct gspca_frame *frame;
1577 int i, index, ret;
1578
1579 PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index);
1580 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1581 return -EINVAL;
1582
1583 index = v4l2_buf->index;
1584 if ((unsigned) index >= gspca_dev->nframes) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001585 PDEBUG(D_FRAM,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001586 "qbuf idx %d >= %d", index, gspca_dev->nframes);
1587 return -EINVAL;
1588 }
1589 frame = &gspca_dev->frame[index];
1590
1591 if (v4l2_buf->memory != frame->v4l2_buf.memory) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001592 PDEBUG(D_FRAM, "qbuf bad memory type");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001593 return -EINVAL;
1594 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001595 if (gspca_dev->capt_file != file)
1596 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001597
Hans de Goedee2997a72008-04-23 08:09:12 -03001598 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1599 return -ERESTARTSYS;
1600
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001601 if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) {
1602 PDEBUG(D_FRAM, "qbuf bad state");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001603 ret = -EINVAL;
1604 goto out;
1605 }
1606
1607 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001608/* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001609
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001610 if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001611 frame->data = frame->data_end =
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001612 (__u8 *) v4l2_buf->m.userptr;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001613 frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
1614 frame->v4l2_buf.length = v4l2_buf->length;
1615 }
1616
1617 /* put the buffer in the 'queued' queue */
1618 i = gspca_dev->fr_q;
1619 gspca_dev->fr_queue[i] = index;
1620 gspca_dev->fr_q = (i + 1) % gspca_dev->nframes;
1621 PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d",
1622 gspca_dev->fr_q,
1623 gspca_dev->fr_i,
1624 gspca_dev->fr_o);
1625
1626 v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
1627 v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE;
1628 ret = 0;
1629out:
1630 mutex_unlock(&gspca_dev->queue_lock);
1631 return ret;
1632}
1633
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001634/*
1635 * allocate the resources for read()
1636 */
1637static int read_alloc(struct gspca_dev *gspca_dev,
1638 struct file *file)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001639{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001640 struct v4l2_buffer v4l2_buf;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001641 int i, ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001642
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001643 PDEBUG(D_STREAM, "read alloc");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001644 if (gspca_dev->nframes == 0) {
1645 struct v4l2_requestbuffers rb;
1646
1647 memset(&rb, 0, sizeof rb);
1648 rb.count = gspca_dev->nbufread;
1649 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1650 rb.memory = V4L2_MEMORY_MMAP;
1651 ret = vidioc_reqbufs(file, gspca_dev, &rb);
1652 if (ret != 0) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001653 PDEBUG(D_STREAM, "read reqbuf err %d", ret);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001654 return ret;
1655 }
1656 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1657 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1658 v4l2_buf.memory = V4L2_MEMORY_MMAP;
1659 for (i = 0; i < gspca_dev->nbufread; i++) {
1660 v4l2_buf.index = i;
1661/*fixme: ugly!*/
1662 gspca_dev->frame[i].v4l2_buf.flags |=
1663 V4L2_BUF_FLAG_MAPPED;
1664 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1665 if (ret != 0) {
1666 PDEBUG(D_STREAM, "read qbuf err: %d", ret);
1667 return ret;
1668 }
1669 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001670 gspca_dev->memory = GSPCA_MEMORY_READ;
1671 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001672
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001673 /* start streaming */
1674 ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE);
1675 if (ret != 0)
1676 PDEBUG(D_STREAM, "read streamon err %d", ret);
1677 return ret;
1678}
1679
1680static unsigned int dev_poll(struct file *file, poll_table *wait)
1681{
1682 struct gspca_dev *gspca_dev = file->private_data;
1683 int i, ret;
1684
1685 PDEBUG(D_FRAM, "poll");
1686
1687 poll_wait(file, &gspca_dev->wq, wait);
1688 if (!gspca_dev->present)
1689 return POLLERR;
1690
1691 /* if not streaming, the user would use read() */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001692 if (!gspca_dev->streaming) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001693 if (gspca_dev->memory != GSPCA_MEMORY_NO) {
1694 ret = POLLERR; /* not the 1st time */
1695 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001696 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001697 ret = read_alloc(gspca_dev, file);
1698 if (ret != 0) {
1699 ret = POLLERR;
1700 goto out;
1701 }
1702 }
1703
1704 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0)
1705 return POLLERR;
1706 if (!gspca_dev->present) {
1707 ret = POLLERR;
1708 goto out;
1709 }
1710
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001711 /* if userptr, treat the awaiting URBs */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001712 if (gspca_dev->memory == V4L2_MEMORY_USERPTR
1713 && gspca_dev->capt_file == file)
1714 isoc_transfer(gspca_dev);
1715
1716 i = gspca_dev->fr_o;
1717 i = gspca_dev->fr_queue[i];
1718 if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1719 ret = POLLIN | POLLRDNORM; /* something to read */
1720 else
1721 ret = 0;
1722out:
1723 mutex_unlock(&gspca_dev->queue_lock);
1724 return ret;
1725}
1726
1727static ssize_t dev_read(struct file *file, char __user *data,
1728 size_t count, loff_t *ppos)
1729{
1730 struct gspca_dev *gspca_dev = file->private_data;
1731 struct gspca_frame *frame;
1732 struct v4l2_buffer v4l2_buf;
1733 struct timeval timestamp;
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001734 int n, ret, ret2;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001735
1736 PDEBUG(D_FRAM, "read (%d)", count);
1737 if (!gspca_dev->present)
1738 return -ENODEV;
1739 switch (gspca_dev->memory) {
1740 case GSPCA_MEMORY_NO: /* first time */
1741 ret = read_alloc(gspca_dev, file);
1742 if (ret != 0)
1743 return ret;
1744 break;
1745 case GSPCA_MEMORY_READ:
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001746 if (gspca_dev->capt_file == file)
1747 break;
1748 /* fall thru */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001749 default:
1750 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001751 }
1752
1753 /* get a frame */
1754 jiffies_to_timeval(get_jiffies_64(), &timestamp);
1755 timestamp.tv_sec--;
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001756 n = 2;
1757 for (;;) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001758 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1759 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1760 v4l2_buf.memory = V4L2_MEMORY_MMAP;
1761 ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf);
1762 if (ret != 0) {
1763 PDEBUG(D_STREAM, "read dqbuf err %d", ret);
1764 return ret;
1765 }
1766
1767 /* if the process slept for more than 1 second,
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001768 * get anewer frame */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001769 frame = &gspca_dev->frame[v4l2_buf.index];
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001770 if (--n < 0)
1771 break; /* avoid infinite loop */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001772 if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
1773 break;
1774 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1775 if (ret != 0) {
1776 PDEBUG(D_STREAM, "read qbuf err %d", ret);
1777 return ret;
1778 }
1779 }
1780
1781 /* copy the frame */
1782 if (count < frame->v4l2_buf.bytesused) {
1783 PDEBUG(D_STREAM, "read bad count: %d < %d",
1784 count, frame->v4l2_buf.bytesused);
1785/*fixme: special errno?*/
1786 ret = -EINVAL;
1787 goto out;
1788 }
1789 count = frame->v4l2_buf.bytesused;
1790 ret = copy_to_user(data, frame->data, count);
1791 if (ret != 0) {
1792 PDEBUG(D_ERR|D_STREAM,
1793 "read cp to user lack %d / %d", ret, count);
1794 ret = -EFAULT;
1795 goto out;
1796 }
1797 ret = count;
1798out:
1799 /* in each case, requeue the buffer */
1800 ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1801 if (ret2 != 0)
1802 return ret2;
1803 return ret;
1804}
1805
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001806static void dev_release(struct video_device *vfd)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001807{
1808 /* nothing */
1809}
1810
1811static struct file_operations dev_fops = {
1812 .owner = THIS_MODULE,
1813 .open = dev_open,
1814 .release = dev_close,
1815 .read = dev_read,
1816 .mmap = dev_mmap,
1817 .ioctl = video_ioctl2,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001818#ifdef CONFIG_COMPAT
1819 .compat_ioctl = v4l_compat_ioctl32,
1820#endif
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001821 .llseek = no_llseek,
1822 .poll = dev_poll,
1823};
1824
1825static struct video_device gspca_template = {
1826 .name = "gspca main driver",
1827 .type = VID_TYPE_CAPTURE,
1828 .fops = &dev_fops,
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001829 .release = dev_release, /* mandatory */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001830 .minor = -1,
1831 .vidioc_querycap = vidioc_querycap,
1832 .vidioc_dqbuf = vidioc_dqbuf,
1833 .vidioc_qbuf = vidioc_qbuf,
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -03001834 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1835 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1836 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1837 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001838 .vidioc_streamon = vidioc_streamon,
1839 .vidioc_queryctrl = vidioc_queryctrl,
1840 .vidioc_g_ctrl = vidioc_g_ctrl,
1841 .vidioc_s_ctrl = vidioc_s_ctrl,
1842 .vidioc_querymenu = vidioc_querymenu,
1843 .vidioc_enum_input = vidioc_enum_input,
1844 .vidioc_g_input = vidioc_g_input,
1845 .vidioc_s_input = vidioc_s_input,
1846 .vidioc_reqbufs = vidioc_reqbufs,
1847 .vidioc_querybuf = vidioc_querybuf,
1848 .vidioc_streamoff = vidioc_streamoff,
1849 .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
1850 .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
1851 .vidioc_g_parm = vidioc_g_parm,
1852 .vidioc_s_parm = vidioc_s_parm,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001853 .vidioc_s_std = vidioc_s_std,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001854#ifdef CONFIG_VIDEO_V4L1_COMPAT
1855 .vidiocgmbuf = vidiocgmbuf,
1856#endif
1857};
1858
1859/*
1860 * probe and create a new gspca device
1861 *
1862 * This function must be called by the sub-driver when it is
1863 * called for probing a new device.
1864 */
1865int gspca_dev_probe(struct usb_interface *intf,
1866 const struct usb_device_id *id,
1867 const struct sd_desc *sd_desc,
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001868 int dev_size,
1869 struct module *module)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001870{
1871 struct usb_interface_descriptor *interface;
1872 struct gspca_dev *gspca_dev;
1873 struct usb_device *dev = interface_to_usbdev(intf);
1874 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001875
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001876 PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001877
1878 /* we don't handle multi-config cameras */
1879 if (dev->descriptor.bNumConfigurations != 1)
1880 return -ENODEV;
1881 interface = &intf->cur_altsetting->desc;
1882 if (interface->bInterfaceNumber > 0)
1883 return -ENODEV;
1884
1885 /* create the device */
1886 if (dev_size < sizeof *gspca_dev)
1887 dev_size = sizeof *gspca_dev;
1888 gspca_dev = kzalloc(dev_size, GFP_KERNEL);
1889 if (gspca_dev == NULL) {
1890 err("couldn't kzalloc gspca struct");
1891 return -EIO;
1892 }
1893 gspca_dev->dev = dev;
1894 gspca_dev->iface = interface->bInterfaceNumber;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001895 gspca_dev->nbalt = intf->num_altsetting;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001896 gspca_dev->sd_desc = sd_desc;
1897/* gspca_dev->users = 0; (done by kzalloc) */
1898 gspca_dev->nbufread = 2;
1899
1900 /* configure the subdriver */
1901 ret = gspca_dev->sd_desc->config(gspca_dev, id);
1902 if (ret < 0)
1903 goto out;
1904 ret = gspca_set_alt0(gspca_dev);
1905 if (ret < 0)
1906 goto out;
1907 gspca_set_default_mode(gspca_dev);
1908
1909 mutex_init(&gspca_dev->usb_lock);
1910 mutex_init(&gspca_dev->read_lock);
1911 mutex_init(&gspca_dev->queue_lock);
1912 init_waitqueue_head(&gspca_dev->wq);
1913
1914 /* init video stuff */
1915 memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
1916 gspca_dev->vdev.dev = &dev->dev;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001917 memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops);
1918 gspca_dev->vdev.fops = &gspca_dev->fops;
1919 gspca_dev->fops.owner = module; /* module protection */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001920 ret = video_register_device(&gspca_dev->vdev,
1921 VFL_TYPE_GRABBER,
1922 video_nr);
1923 if (ret < 0) {
1924 err("video_register_device err %d", ret);
1925 goto out;
1926 }
1927
1928 gspca_dev->present = 1;
1929 usb_set_intfdata(intf, gspca_dev);
1930 PDEBUG(D_PROBE, "probe ok");
1931 return 0;
1932out:
1933 kfree(gspca_dev);
1934 return ret;
1935}
1936EXPORT_SYMBOL(gspca_dev_probe);
1937
1938/*
1939 * USB disconnection
1940 *
1941 * This function must be called by the sub-driver
1942 * when the device disconnects, after the specific resources are freed.
1943 */
1944void gspca_disconnect(struct usb_interface *intf)
1945{
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001946 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001947
1948 if (!gspca_dev)
1949 return;
1950 gspca_dev->present = 0;
Hans de Goedee2997a72008-04-23 08:09:12 -03001951 mutex_lock(&gspca_dev->queue_lock);
1952 mutex_lock(&gspca_dev->usb_lock);
1953 gspca_dev->streaming = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001954 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001955 mutex_unlock(&gspca_dev->usb_lock);
Hans de Goedee2997a72008-04-23 08:09:12 -03001956 mutex_unlock(&gspca_dev->queue_lock);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001957 while (gspca_dev->users != 0) { /* wait until fully closed */
1958 atomic_inc(&gspca_dev->nevent);
1959 wake_up_interruptible(&gspca_dev->wq); /* wake processes */
1960 schedule();
1961 }
1962/* We don't want people trying to open up the device */
1963 video_unregister_device(&gspca_dev->vdev);
1964/* Free the memory */
1965 kfree(gspca_dev);
1966 PDEBUG(D_PROBE, "disconnect complete");
1967}
1968EXPORT_SYMBOL(gspca_disconnect);
1969
1970/* -- module insert / remove -- */
1971static int __init gspca_init(void)
1972{
1973 info("main v%s registered", version);
1974 return 0;
1975}
1976static void __exit gspca_exit(void)
1977{
1978 info("main deregistered");
1979}
1980
1981module_init(gspca_init);
1982module_exit(gspca_exit);
1983
Hans de Goeded646e702008-07-03 06:48:22 -03001984#ifdef CONFIG_VIDEO_ADV_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001985module_param_named(debug, gspca_debug, int, 0644);
1986MODULE_PARM_DESC(debug,
1987 "Debug (bit) 0x01:error 0x02:probe 0x04:config"
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001988 " 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout"
1989 " 0x0100: v4l2");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001990#endif
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001991module_param(comp_fac, int, 0644);
1992MODULE_PARM_DESC(comp_fac,
1993 "Buffer size ratio when compressed in percent");