blob: 0e6a4ec0fec94596efe75f3065db4855011e56e9 [file] [log] [blame]
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001/*
2 * Main USB camera driver
3 *
Jean-Francois Moine11bd1992009-04-21 04:17:59 -03004 * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03005 *
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>
Jean-Francois Moinecf0fe082008-10-17 04:36:47 -030024#include <linux/version.h>
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030025#include <linux/fs.h>
26#include <linux/vmalloc.h>
27#include <linux/sched.h>
28#include <linux/slab.h>
29#include <linux/mm.h>
30#include <linux/string.h>
31#include <linux/pagemap.h>
Jean-Francois Moine956e42d2008-07-01 10:03:42 -030032#include <linux/io.h>
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030033#include <asm/page.h>
Jean-Francois Moine956e42d2008-07-01 10:03:42 -030034#include <linux/uaccess.h>
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030035#include <linux/jiffies.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030036#include <media/v4l2-ioctl.h>
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030037
38#include "gspca.h"
39
Jean-Francois Moined43fa322008-06-12 10:58:58 -030040/* global values */
Jean-Francois Moine8fee8452009-01-17 04:46:38 -030041#define DEF_NURBS 3 /* default number of URBs */
42#if DEF_NURBS > MAX_NURBS
43#error "DEF_NURBS too big"
44#endif
Jean-Francois Moined43fa322008-06-12 10:58:58 -030045
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030046MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
47MODULE_DESCRIPTION("GSPCA USB Camera Driver");
48MODULE_LICENSE("GPL");
49
Jean-Francois Moine77ee3312009-11-07 15:30:50 -030050#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 8, 0)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030051
Jean-Francois Moine335b3f82008-07-30 04:53:02 -030052#ifdef GSPCA_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030053int gspca_debug = D_ERR | D_PROBE;
54EXPORT_SYMBOL(gspca_debug);
55
56static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
57{
58 if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') {
59 PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d",
60 txt,
61 pixfmt & 0xff,
62 (pixfmt >> 8) & 0xff,
63 (pixfmt >> 16) & 0xff,
64 pixfmt >> 24,
65 w, h);
66 } else {
67 PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d",
68 txt,
69 pixfmt,
70 w, h);
71 }
72}
73#else
74#define PDEBUG_MODE(txt, pixfmt, w, h)
75#endif
76
Jean-Francois Moine77ee3312009-11-07 15:30:50 -030077/* specific memory types - !! should be different from V4L2_MEMORY_xxx */
Jean-Francois Moined43fa322008-06-12 10:58:58 -030078#define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */
79#define GSPCA_MEMORY_READ 7
80
Jean-Francois Moined43fa322008-06-12 10:58:58 -030081#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)
Jean-Francois Moined43fa322008-06-12 10:58:58 -030082
Jean-Francois Moine63eb9542008-04-12 09:58:09 -030083/*
84 * VMA operations.
85 */
86static void gspca_vm_open(struct vm_area_struct *vma)
87{
88 struct gspca_frame *frame = vma->vm_private_data;
89
90 frame->vma_use_count++;
91 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_MAPPED;
92}
93
94static void gspca_vm_close(struct vm_area_struct *vma)
95{
96 struct gspca_frame *frame = vma->vm_private_data;
97
98 if (--frame->vma_use_count <= 0)
99 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_MAPPED;
100}
101
Alexey Dobriyanf0f37e22009-09-27 22:29:37 +0400102static const struct vm_operations_struct gspca_vm_ops = {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300103 .open = gspca_vm_open,
104 .close = gspca_vm_close,
105};
106
Jean-Francois Moine1b60e1a2008-09-20 05:44:21 -0300107/* get the current input frame buffer */
108struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev)
109{
110 struct gspca_frame *frame;
Jean-Francois Moine1b60e1a2008-09-20 05:44:21 -0300111
Jean-Francois Moinedb870872009-12-15 05:16:04 -0300112 frame = gspca_dev->cur_frame;
Jean-Francois Moine1b60e1a2008-09-20 05:44:21 -0300113 if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
114 != V4L2_BUF_FLAG_QUEUED)
115 return NULL;
116 return frame;
117}
118EXPORT_SYMBOL(gspca_get_i_frame);
119
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300120/*
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300121 * fill a video frame from an URB and resubmit
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300122 */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300123static void fill_frame(struct gspca_dev *gspca_dev,
124 struct urb *urb)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300125{
Jean-Francois Moine8d584a52009-01-13 06:07:59 -0300126 u8 *data; /* address of data in the iso message */
Jean-Francois Moine1b60e1a2008-09-20 05:44:21 -0300127 int i, len, st;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300128 cam_pkt_op pkt_scan;
129
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300130 if (urb->status != 0) {
Jean-Francois Moine090264e2009-02-12 08:05:45 -0300131 if (urb->status == -ESHUTDOWN)
132 return; /* disconnection */
Jean-Francois Moine62ee8ee2008-09-03 17:12:13 -0300133#ifdef CONFIG_PM
Hans de Goede6a540bd2009-10-24 15:02:14 -0300134 if (gspca_dev->frozen)
135 return;
Jean-Francois Moine62ee8ee2008-09-03 17:12:13 -0300136#endif
Hans de Goede6a540bd2009-10-24 15:02:14 -0300137 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
Jean-Francois Moine81578522009-11-13 07:15:08 -0300138 urb->status = 0;
Hans de Goedebf926ad2009-10-23 06:56:06 -0300139 goto resubmit;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300140 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300141 pkt_scan = gspca_dev->sd_desc->pkt_scan;
142 for (i = 0; i < urb->number_of_packets; i++) {
143
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300144 /* check the packet status and length */
145 len = urb->iso_frame_desc[i].actual_length;
Jean-Francois Moineff374742008-10-23 07:29:51 -0300146 if (len == 0) {
147 if (gspca_dev->empty_packet == 0)
148 gspca_dev->empty_packet = 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300149 continue;
Jean-Francois Moineff374742008-10-23 07:29:51 -0300150 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300151 st = urb->iso_frame_desc[i].status;
152 if (st) {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300153 PDEBUG(D_ERR,
154 "ISOC data error: [%d] len=%d, status=%d",
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300155 i, len, st);
156 gspca_dev->last_packet_type = DISCARD_PACKET;
157 continue;
158 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300159
160 /* let the packet be analyzed by the subdriver */
161 PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
162 i, urb->iso_frame_desc[i].offset, len);
Jean-Francois Moine8d584a52009-01-13 06:07:59 -0300163 data = (u8 *) urb->transfer_buffer
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300164 + urb->iso_frame_desc[i].offset;
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300165 pkt_scan(gspca_dev, data, len);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300166 }
167
Hans de Goedebf926ad2009-10-23 06:56:06 -0300168resubmit:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300169 /* resubmit the URB */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300170 st = usb_submit_urb(urb, GFP_ATOMIC);
171 if (st < 0)
172 PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", st);
173}
174
175/*
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300176 * ISOC message interrupt from the USB device
177 *
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -0300178 * Analyse each packet and call the subdriver for copy to the frame buffer.
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300179 */
Jean-Francois Moine8d584a52009-01-13 06:07:59 -0300180static void isoc_irq(struct urb *urb)
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300181{
182 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
183
Hans de Goede3647fea2008-07-15 05:36:30 -0300184 PDEBUG(D_PACK, "isoc irq");
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300185 if (!gspca_dev->streaming)
186 return;
187 fill_frame(gspca_dev, urb);
188}
189
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300190/*
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300191 * bulk message interrupt from the USB device
192 */
Jean-Francois Moine8d584a52009-01-13 06:07:59 -0300193static void bulk_irq(struct urb *urb)
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300194{
195 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
Antonio Ospitedff369a2008-11-14 07:53:32 -0300196 int st;
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300197
198 PDEBUG(D_PACK, "bulk irq");
199 if (!gspca_dev->streaming)
200 return;
Jean-Francois Moine880ae242008-11-18 04:19:52 -0300201 switch (urb->status) {
202 case 0:
203 break;
Jean-Francois Moine090264e2009-02-12 08:05:45 -0300204 case -ESHUTDOWN:
205 return; /* disconnection */
Jean-Francois Moine880ae242008-11-18 04:19:52 -0300206 default:
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300207#ifdef CONFIG_PM
Hans de Goede6a540bd2009-10-24 15:02:14 -0300208 if (gspca_dev->frozen)
209 return;
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300210#endif
Hans de Goede6a540bd2009-10-24 15:02:14 -0300211 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
Jean-Francois Moine81578522009-11-13 07:15:08 -0300212 urb->status = 0;
Hans de Goedebf926ad2009-10-23 06:56:06 -0300213 goto resubmit;
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300214 }
215
Jean-Francois Moined131c3c2009-11-13 08:16:02 -0300216 PDEBUG(D_PACK, "packet l:%d", urb->actual_length);
217 gspca_dev->sd_desc->pkt_scan(gspca_dev,
Jean-Francois Moined131c3c2009-11-13 08:16:02 -0300218 urb->transfer_buffer,
219 urb->actual_length);
Antonio Ospitedff369a2008-11-14 07:53:32 -0300220
Hans de Goedebf926ad2009-10-23 06:56:06 -0300221resubmit:
Antonio Ospitedff369a2008-11-14 07:53:32 -0300222 /* resubmit the URB */
223 if (gspca_dev->cam.bulk_nurbs != 0) {
224 st = usb_submit_urb(urb, GFP_ATOMIC);
225 if (st < 0)
226 PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", st);
227 }
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300228}
229
230/*
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300231 * add data to the current frame
232 *
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -0300233 * This function is called by the subdrivers at interrupt level.
234 *
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300235 * To build a frame, these ones must add
236 * - one FIRST_PACKET
237 * - 0 or many INTER_PACKETs
238 * - one LAST_PACKET
239 * DISCARD_PACKET invalidates the whole frame.
240 * On LAST_PACKET, a new frame is returned.
241 */
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300242void gspca_frame_add(struct gspca_dev *gspca_dev,
243 enum gspca_packet_type packet_type,
244 const u8 *data,
245 int len)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300246{
Jean-Francois Moine3ec342f2009-11-13 07:38:16 -0300247 struct gspca_frame *frame;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300248 int i, j;
249
Hans de Goedee2997a72008-04-23 08:09:12 -0300250 PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len);
Jean-Francois Moined131c3c2009-11-13 08:16:02 -0300251
252 /* check the availability of the frame buffer */
Jean-Francois Moine3ec342f2009-11-13 07:38:16 -0300253 frame = gspca_dev->cur_frame;
Jean-Francois Moined131c3c2009-11-13 08:16:02 -0300254 if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
255 != V4L2_BUF_FLAG_QUEUED) {
256 gspca_dev->last_packet_type = DISCARD_PACKET;
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300257 return;
Jean-Francois Moined131c3c2009-11-13 08:16:02 -0300258 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300259
260 /* when start of a new frame, if the current frame buffer
261 * is not queued, discard the whole frame */
262 if (packet_type == FIRST_PACKET) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300263 frame->data_end = frame->data;
264 jiffies_to_timeval(get_jiffies_64(),
265 &frame->v4l2_buf.timestamp);
266 frame->v4l2_buf.sequence = ++gspca_dev->sequence;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300267 } else if (gspca_dev->last_packet_type == DISCARD_PACKET) {
Jean-Francois Moine06ca78f2008-07-22 03:45:08 -0300268 if (packet_type == LAST_PACKET)
269 gspca_dev->last_packet_type = packet_type;
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300270 return;
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) {
Mauro Carvalho Chehaba9e11132008-07-09 05:26:26 -0300277 PDEBUG(D_ERR|D_PACK, "frame overflow %zd > %d",
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300278 frame->data_end - frame->data + len,
279 frame->v4l2_buf.length);
280 packet_type = DISCARD_PACKET;
281 } else {
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -0300282 memcpy(frame->data_end, data, len);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300283 frame->data_end += len;
284 }
285 }
286 gspca_dev->last_packet_type = packet_type;
287
Frank Zago219423c2008-09-26 07:43:54 -0300288 /* if last packet, wake up the application and advance in the queue */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300289 if (packet_type == LAST_PACKET) {
290 frame->v4l2_buf.bytesused = frame->data_end - frame->data;
291 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
292 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300293 wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300294 i = (gspca_dev->fr_i + 1) % gspca_dev->nframes;
295 gspca_dev->fr_i = i;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300296 PDEBUG(D_FRAM, "frame complete len:%d q:%d i:%d o:%d",
297 frame->v4l2_buf.bytesused,
298 gspca_dev->fr_q,
299 i,
300 gspca_dev->fr_o);
301 j = gspca_dev->fr_queue[i];
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300302 gspca_dev->cur_frame = &gspca_dev->frame[j];
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300303 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300304}
305EXPORT_SYMBOL(gspca_frame_add);
306
307static int gspca_is_compressed(__u32 format)
308{
309 switch (format) {
310 case V4L2_PIX_FMT_MJPEG:
311 case V4L2_PIX_FMT_JPEG:
Jean-Francois Moine50a871f2008-06-30 19:47:33 -0300312 case V4L2_PIX_FMT_SPCA561:
Hans de Goedeab8f12c2008-07-04 18:29:32 -0300313 case V4L2_PIX_FMT_PAC207:
Kyle Guinnd661e622009-01-16 05:36:14 -0300314 case V4L2_PIX_FMT_MR97310A:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300315 return 1;
316 }
317 return 0;
318}
319
Jean-Francois Moined50e2572009-11-26 15:36:40 -0300320static void *rvmalloc(long size)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300321{
322 void *mem;
323 unsigned long adr;
324
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300325 mem = vmalloc_32(size);
Harvey Harrisonefab8212008-07-05 06:12:47 -0300326 if (mem != NULL) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300327 adr = (unsigned long) mem;
Jean-Francois Moined50e2572009-11-26 15:36:40 -0300328 while (size > 0) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300329 SetPageReserved(vmalloc_to_page((void *) adr));
330 adr += PAGE_SIZE;
331 size -= PAGE_SIZE;
332 }
333 }
334 return mem;
335}
336
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -0300337static void rvfree(void *mem, long size)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300338{
339 unsigned long adr;
340
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300341 adr = (unsigned long) mem;
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -0300342 while (size > 0) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300343 ClearPageReserved(vmalloc_to_page((void *) adr));
344 adr += PAGE_SIZE;
345 size -= PAGE_SIZE;
346 }
347 vfree(mem);
348}
349
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300350static int frame_alloc(struct gspca_dev *gspca_dev,
351 unsigned int count)
352{
353 struct gspca_frame *frame;
354 unsigned int frsz;
355 int i;
356
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300357 i = gspca_dev->curr_mode;
358 frsz = gspca_dev->cam.cam_mode[i].sizeimage;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300359 PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300360 frsz = PAGE_ALIGN(frsz);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300361 gspca_dev->frsz = frsz;
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300362 if (count > GSPCA_MAX_FRAMES)
363 count = GSPCA_MAX_FRAMES;
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -0300364 gspca_dev->frbuf = rvmalloc(frsz * count);
365 if (!gspca_dev->frbuf) {
366 err("frame alloc failed");
367 return -ENOMEM;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300368 }
369 gspca_dev->nframes = count;
370 for (i = 0; i < count; i++) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300371 frame = &gspca_dev->frame[i];
372 frame->v4l2_buf.index = i;
373 frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
374 frame->v4l2_buf.flags = 0;
375 frame->v4l2_buf.field = V4L2_FIELD_NONE;
376 frame->v4l2_buf.length = frsz;
377 frame->v4l2_buf.memory = gspca_dev->memory;
378 frame->v4l2_buf.sequence = 0;
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -0300379 frame->data = frame->data_end =
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300380 gspca_dev->frbuf + i * frsz;
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -0300381 frame->v4l2_buf.m.offset = i * frsz;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300382 }
383 gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
Jean-Francois Moine3ec342f2009-11-13 07:38:16 -0300384 gspca_dev->cur_frame = &gspca_dev->frame[0];
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300385 gspca_dev->last_packet_type = DISCARD_PACKET;
386 gspca_dev->sequence = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300387 return 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300388}
389
390static void frame_free(struct gspca_dev *gspca_dev)
391{
392 int i;
393
394 PDEBUG(D_STREAM, "frame free");
Harvey Harrisonefab8212008-07-05 06:12:47 -0300395 if (gspca_dev->frbuf != NULL) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300396 rvfree(gspca_dev->frbuf,
397 gspca_dev->nframes * gspca_dev->frsz);
398 gspca_dev->frbuf = NULL;
399 for (i = 0; i < gspca_dev->nframes; i++)
400 gspca_dev->frame[i].data = NULL;
401 }
402 gspca_dev->nframes = 0;
403}
404
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300405static void destroy_urbs(struct gspca_dev *gspca_dev)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300406{
407 struct urb *urb;
408 unsigned int i;
409
410 PDEBUG(D_STREAM, "kill transfer");
Erik Andrén44732812008-10-13 15:52:46 -0300411 for (i = 0; i < MAX_NURBS; i++) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300412 urb = gspca_dev->urb[i];
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300413 if (urb == NULL)
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300414 break;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300415
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300416 gspca_dev->urb[i] = NULL;
Jean-Francois Moine090264e2009-02-12 08:05:45 -0300417 usb_kill_urb(urb);
Harvey Harrisonefab8212008-07-05 06:12:47 -0300418 if (urb->transfer_buffer != NULL)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300419 usb_buffer_free(gspca_dev->dev,
420 urb->transfer_buffer_length,
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300421 urb->transfer_buffer,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300422 urb->transfer_dma);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300423 usb_free_urb(urb);
424 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300425}
426
427/*
Frank Zago219423c2008-09-26 07:43:54 -0300428 * look for an input transfer endpoint in an alternate setting
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300429 */
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300430static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
Jean-Francois Moine6929dc62009-04-21 13:45:56 -0300431 int xfer)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300432{
433 struct usb_host_endpoint *ep;
434 int i, attr;
435
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300436 for (i = 0; i < alt->desc.bNumEndpoints; i++) {
437 ep = &alt->endpoint[i];
Jean-Francois Moine50e06de2008-12-31 08:13:46 -0300438 attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
Jean-Francois Moine30d35e42009-04-21 13:57:31 -0300439 if (attr == xfer
440 && ep->desc.wMaxPacketSize != 0)
Jean-Francois Moine50e06de2008-12-31 08:13:46 -0300441 return ep;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300442 }
443 return NULL;
444}
445
446/*
Frank Zago219423c2008-09-26 07:43:54 -0300447 * look for an input (isoc or bulk) endpoint
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300448 *
449 * The endpoint is defined by the subdriver.
450 * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
451 * This routine may be called many times when the bandwidth is too small
452 * (the bandwidth is checked on urb submit).
453 */
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300454static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300455{
456 struct usb_interface *intf;
457 struct usb_host_endpoint *ep;
Jean-Francois Moine6929dc62009-04-21 13:45:56 -0300458 int xfer, i, ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300459
460 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300461 ep = NULL;
Jean-Francois Moine6929dc62009-04-21 13:45:56 -0300462 xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
463 : USB_ENDPOINT_XFER_ISOC;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300464 i = gspca_dev->alt; /* previous alt setting */
Hans de Goedea511ba92009-10-16 07:13:07 -0300465 if (gspca_dev->cam.reverse_alts) {
466 while (++i < gspca_dev->nbalt) {
467 ep = alt_xfer(&intf->altsetting[i], xfer);
468 if (ep)
469 break;
470 }
471 } else {
472 while (--i >= 0) {
473 ep = alt_xfer(&intf->altsetting[i], xfer);
474 if (ep)
475 break;
476 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300477 }
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300478 if (ep == NULL) {
Jean-Francois Moine6929dc62009-04-21 13:45:56 -0300479 err("no transfer endpoint found");
480 return NULL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300481 }
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300482 PDEBUG(D_STREAM, "use alt %d ep 0x%02x",
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300483 i, ep->desc.bEndpointAddress);
Jean-Francois Moine1c8336d2009-07-28 04:38:25 -0300484 gspca_dev->alt = i; /* memorize the current alt setting */
Jean-Francois Moine8dd07ef2009-04-21 14:05:44 -0300485 if (gspca_dev->nbalt > 1) {
Jean-Francois Moine95d91422008-09-29 05:57:32 -0300486 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
487 if (ret < 0) {
Jean-Francois Moine6929dc62009-04-21 13:45:56 -0300488 err("set alt %d err %d", i, ret);
Jean-Francois Moine95d91422008-09-29 05:57:32 -0300489 return NULL;
490 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300491 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300492 return ep;
493}
494
495/*
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300496 * create the URBs for image transfer
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300497 */
498static int create_urbs(struct gspca_dev *gspca_dev,
499 struct usb_host_endpoint *ep)
500{
501 struct urb *urb;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300502 int n, nurbs, i, psize, npkt, bsize;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300503
504 /* calculate the packet size and the number of packets */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300505 psize = le16_to_cpu(ep->desc.wMaxPacketSize);
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300506
Jean-Francois Moine6929dc62009-04-21 13:45:56 -0300507 if (!gspca_dev->cam.bulk) { /* isoc */
Jean-Francois Moine95d91422008-09-29 05:57:32 -0300508
509 /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
Jean-Francois Moine1f53b0b2009-06-30 07:07:01 -0300510 if (gspca_dev->pkt_size == 0)
511 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
512 else
513 psize = gspca_dev->pkt_size;
Jean-Francois Moine49cb6b02009-04-25 13:29:01 -0300514 npkt = gspca_dev->cam.npkt;
515 if (npkt == 0)
516 npkt = 32; /* default value */
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300517 bsize = psize * npkt;
518 PDEBUG(D_STREAM,
519 "isoc %d pkts size %d = bsize:%d",
520 npkt, psize, bsize);
Jean-Francois Moine51977a82008-09-08 03:22:42 -0300521 nurbs = DEF_NURBS;
Jean-Francois Moine95d91422008-09-29 05:57:32 -0300522 } else { /* bulk */
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300523 npkt = 0;
Antonio Ospitedff369a2008-11-14 07:53:32 -0300524 bsize = gspca_dev->cam.bulk_size;
Jean-Francois Moine95d91422008-09-29 05:57:32 -0300525 if (bsize == 0)
526 bsize = psize;
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300527 PDEBUG(D_STREAM, "bulk bsize:%d", bsize);
Antonio Ospitedff369a2008-11-14 07:53:32 -0300528 if (gspca_dev->cam.bulk_nurbs != 0)
529 nurbs = gspca_dev->cam.bulk_nurbs;
530 else
531 nurbs = 1;
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300532 }
533
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300534 for (n = 0; n < nurbs; n++) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300535 urb = usb_alloc_urb(npkt, GFP_KERNEL);
536 if (!urb) {
537 err("usb_alloc_urb failed");
538 return -ENOMEM;
539 }
Jean-Francois Moinedb870872009-12-15 05:16:04 -0300540 gspca_dev->urb[n] = urb;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300541 urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300542 bsize,
543 GFP_KERNEL,
544 &urb->transfer_dma);
545
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300546 if (urb->transfer_buffer == NULL) {
Jean-Francois Moinedb870872009-12-15 05:16:04 -0300547 err("usb_buffer_alloc failed");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300548 return -ENOMEM;
549 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300550 urb->dev = gspca_dev->dev;
551 urb->context = gspca_dev;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300552 urb->transfer_buffer_length = bsize;
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300553 if (npkt != 0) { /* ISOC */
554 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
555 ep->desc.bEndpointAddress);
Frank Zago6c49da72008-09-28 07:43:00 -0300556 urb->transfer_flags = URB_ISO_ASAP
557 | URB_NO_TRANSFER_DMA_MAP;
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300558 urb->interval = ep->desc.bInterval;
559 urb->complete = isoc_irq;
560 urb->number_of_packets = npkt;
561 for (i = 0; i < npkt; i++) {
562 urb->iso_frame_desc[i].length = psize;
563 urb->iso_frame_desc[i].offset = psize * i;
564 }
565 } else { /* bulk */
566 urb->pipe = usb_rcvbulkpipe(gspca_dev->dev,
567 ep->desc.bEndpointAddress),
Frank Zago6c49da72008-09-28 07:43:00 -0300568 urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
Jean-Francois Moine0be01002008-09-04 07:01:50 -0300569 urb->complete = bulk_irq;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300570 }
571 }
572 return 0;
573}
574
575/*
576 * start the USB transfer
577 */
578static int gspca_init_transfer(struct gspca_dev *gspca_dev)
579{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300580 struct usb_host_endpoint *ep;
Jean-Francois Moinedb870872009-12-15 05:16:04 -0300581 struct urb *urb;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300582 int n, ret;
583
Hans de Goedee2997a72008-04-23 08:09:12 -0300584 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
585 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300586
Jean-Francois Moine090264e2009-02-12 08:05:45 -0300587 if (!gspca_dev->present) {
588 ret = -ENODEV;
589 goto out;
590 }
591
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300592 /* set the higher alternate setting and
593 * loop until urb submit succeeds */
Hans de Goedea511ba92009-10-16 07:13:07 -0300594 if (gspca_dev->cam.reverse_alts)
595 gspca_dev->alt = 0;
596 else
597 gspca_dev->alt = gspca_dev->nbalt;
598
Jean-Francois Moine1f53b0b2009-06-30 07:07:01 -0300599 if (gspca_dev->sd_desc->isoc_init) {
600 ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
601 if (ret < 0)
602 goto out;
603 }
604 ep = get_ep(gspca_dev);
605 if (ep == NULL) {
606 ret = -EIO;
607 goto out;
608 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300609 for (;;) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300610 PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300611 ret = create_urbs(gspca_dev, ep);
Jean-Francois Moinedb870872009-12-15 05:16:04 -0300612 if (ret < 0) {
613 destroy_urbs(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300614 goto out;
Jean-Francois Moinedb870872009-12-15 05:16:04 -0300615 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300616
Jean-Francois Moine8fe2f1d2008-10-22 14:51:56 -0300617 /* clear the bulk endpoint */
Jean-Francois Moine6929dc62009-04-21 13:45:56 -0300618 if (gspca_dev->cam.bulk)
Jean-Francois Moine8fe2f1d2008-10-22 14:51:56 -0300619 usb_clear_halt(gspca_dev->dev,
Jean-Francois Moine50e06de2008-12-31 08:13:46 -0300620 gspca_dev->urb[0]->pipe);
Jean-Francois Moine8fe2f1d2008-10-22 14:51:56 -0300621
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300622 /* start the cam */
Jean-Francois Moine72ab97c2008-09-20 06:39:08 -0300623 ret = gspca_dev->sd_desc->start(gspca_dev);
624 if (ret < 0) {
625 destroy_urbs(gspca_dev);
626 goto out;
627 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300628 gspca_dev->streaming = 1;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300629
Antonio Ospitedff369a2008-11-14 07:53:32 -0300630 /* some bulk transfers are started by the subdriver */
Jean-Francois Moine6929dc62009-04-21 13:45:56 -0300631 if (gspca_dev->cam.bulk && gspca_dev->cam.bulk_nurbs == 0)
Jean-Francois Moine51977a82008-09-08 03:22:42 -0300632 break;
633
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300634 /* submit the URBs */
Jean-Francois Moinedb870872009-12-15 05:16:04 -0300635 for (n = 0; n < MAX_NURBS; n++) {
636 urb = gspca_dev->urb[n];
637 if (urb == NULL)
638 break;
639 ret = usb_submit_urb(urb, GFP_KERNEL);
Jean-Francois Moine1f53b0b2009-06-30 07:07:01 -0300640 if (ret < 0)
641 break;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300642 }
643 if (ret >= 0)
644 break;
Jean-Francois Moine1f53b0b2009-06-30 07:07:01 -0300645 gspca_dev->streaming = 0;
646 destroy_urbs(gspca_dev);
Jean-Francois Moine4bdf4a82009-11-10 14:49:43 -0300647 if (ret != -ENOSPC) {
648 PDEBUG(D_ERR|D_STREAM,
649 "usb_submit_urb alt %d err %d",
650 gspca_dev->alt, ret);
Jean-Francois Moine1f53b0b2009-06-30 07:07:01 -0300651 goto out;
Jean-Francois Moine4bdf4a82009-11-10 14:49:43 -0300652 }
Jean-Francois Moine1f53b0b2009-06-30 07:07:01 -0300653
654 /* the bandwidth is not wide enough
655 * negociate or try a lower alternate setting */
Jean-Francois Moine4bdf4a82009-11-10 14:49:43 -0300656 PDEBUG(D_ERR|D_STREAM,
657 "bandwidth not wide enough - trying again");
Jean-Francois Moine1f53b0b2009-06-30 07:07:01 -0300658 msleep(20); /* wait for kill complete */
659 if (gspca_dev->sd_desc->isoc_nego) {
660 ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
661 if (ret < 0)
662 goto out;
663 } else {
664 ep = get_ep(gspca_dev);
665 if (ep == NULL) {
666 ret = -EIO;
667 goto out;
668 }
669 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300670 }
671out:
672 mutex_unlock(&gspca_dev->usb_lock);
673 return ret;
674}
675
676static int gspca_set_alt0(struct gspca_dev *gspca_dev)
677{
678 int ret;
679
Jean-Francois Moine8dd07ef2009-04-21 14:05:44 -0300680 if (gspca_dev->alt == 0)
681 return 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300682 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
683 if (ret < 0)
Jean-Francois Moinef955c4f2008-11-28 08:51:50 -0300684 PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300685 return ret;
686}
687
Frank Zago219423c2008-09-26 07:43:54 -0300688/* Note: both the queue and the usb locks should be held when calling this */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300689static void gspca_stream_off(struct gspca_dev *gspca_dev)
690{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300691 gspca_dev->streaming = 0;
Jean-Francois Moine090264e2009-02-12 08:05:45 -0300692 if (gspca_dev->present) {
693 if (gspca_dev->sd_desc->stopN)
694 gspca_dev->sd_desc->stopN(gspca_dev);
695 destroy_urbs(gspca_dev);
Jean-Francois Moined08e2ce2009-01-20 16:21:44 -0300696 gspca_set_alt0(gspca_dev);
Jean-Francois Moine090264e2009-02-12 08:05:45 -0300697 }
698
699 /* always call stop0 to free the subdriver's resources */
Jean-Francois Moine98522a72008-11-18 06:33:08 -0300700 if (gspca_dev->sd_desc->stop0)
701 gspca_dev->sd_desc->stop0(gspca_dev);
702 PDEBUG(D_STREAM, "stream off OK");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300703}
704
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300705static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300706{
707 int i;
708
709 i = gspca_dev->cam.nmodes - 1; /* take the highest mode */
710 gspca_dev->curr_mode = i;
711 gspca_dev->width = gspca_dev->cam.cam_mode[i].width;
712 gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300713 gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixelformat;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300714}
715
716static int wxh_to_mode(struct gspca_dev *gspca_dev,
717 int width, int height)
718{
719 int i;
720
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300721 for (i = gspca_dev->cam.nmodes; --i > 0; ) {
722 if (width >= gspca_dev->cam.cam_mode[i].width
723 && height >= gspca_dev->cam.cam_mode[i].height)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300724 break;
725 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300726 return i;
727}
728
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300729/*
730 * search a mode with the right pixel format
731 */
732static int gspca_get_mode(struct gspca_dev *gspca_dev,
733 int mode,
734 int pixfmt)
735{
736 int modeU, modeD;
737
738 modeU = modeD = mode;
739 while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) {
740 if (--modeD >= 0) {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300741 if (gspca_dev->cam.cam_mode[modeD].pixelformat
742 == pixfmt)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300743 return modeD;
744 }
745 if (++modeU < gspca_dev->cam.nmodes) {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300746 if (gspca_dev->cam.cam_mode[modeU].pixelformat
747 == pixfmt)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300748 return modeU;
749 }
750 }
751 return -EINVAL;
752}
753
Brian Johnsonaf1d9af2009-07-19 05:29:20 -0300754#ifdef CONFIG_VIDEO_ADV_DEBUG
755static int vidioc_g_register(struct file *file, void *priv,
756 struct v4l2_dbg_register *reg)
757{
758 int ret;
759 struct gspca_dev *gspca_dev = priv;
760
761 if (!gspca_dev->sd_desc->get_chip_ident)
762 return -EINVAL;
763
764 if (!gspca_dev->sd_desc->get_register)
765 return -EINVAL;
766
767 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
768 return -ERESTARTSYS;
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -0300769 gspca_dev->usb_err = 0;
Brian Johnsonaf1d9af2009-07-19 05:29:20 -0300770 if (gspca_dev->present)
771 ret = gspca_dev->sd_desc->get_register(gspca_dev, reg);
772 else
773 ret = -ENODEV;
774 mutex_unlock(&gspca_dev->usb_lock);
775
776 return ret;
777}
778
779static int vidioc_s_register(struct file *file, void *priv,
780 struct v4l2_dbg_register *reg)
781{
782 int ret;
783 struct gspca_dev *gspca_dev = priv;
784
785 if (!gspca_dev->sd_desc->get_chip_ident)
786 return -EINVAL;
787
788 if (!gspca_dev->sd_desc->set_register)
789 return -EINVAL;
790
791 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
792 return -ERESTARTSYS;
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -0300793 gspca_dev->usb_err = 0;
Brian Johnsonaf1d9af2009-07-19 05:29:20 -0300794 if (gspca_dev->present)
795 ret = gspca_dev->sd_desc->set_register(gspca_dev, reg);
796 else
797 ret = -ENODEV;
798 mutex_unlock(&gspca_dev->usb_lock);
799
800 return ret;
801}
802#endif
803
804static int vidioc_g_chip_ident(struct file *file, void *priv,
805 struct v4l2_dbg_chip_ident *chip)
806{
807 int ret;
808 struct gspca_dev *gspca_dev = priv;
809
810 if (!gspca_dev->sd_desc->get_chip_ident)
811 return -EINVAL;
812
813 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
814 return -ERESTARTSYS;
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -0300815 gspca_dev->usb_err = 0;
Brian Johnsonaf1d9af2009-07-19 05:29:20 -0300816 if (gspca_dev->present)
817 ret = gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip);
818 else
819 ret = -ENODEV;
820 mutex_unlock(&gspca_dev->usb_lock);
821
822 return ret;
823}
824
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300825static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300826 struct v4l2_fmtdesc *fmtdesc)
827{
828 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300829 int i, j, index;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300830 __u32 fmt_tb[8];
831
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300832 /* give an index to each format */
833 index = 0;
834 j = 0;
835 for (i = gspca_dev->cam.nmodes; --i >= 0; ) {
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300836 fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixelformat;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300837 j = 0;
838 for (;;) {
839 if (fmt_tb[j] == fmt_tb[index])
840 break;
841 j++;
842 }
843 if (j == index) {
844 if (fmtdesc->index == index)
845 break; /* new format */
846 index++;
Julia Lawall80297122008-11-12 23:18:21 -0300847 if (index >= ARRAY_SIZE(fmt_tb))
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300848 return -EINVAL;
849 }
850 }
851 if (i < 0)
852 return -EINVAL; /* no more format */
853
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300854 fmtdesc->pixelformat = fmt_tb[index];
855 if (gspca_is_compressed(fmt_tb[index]))
856 fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
857 fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
858 fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
859 fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff;
860 fmtdesc->description[3] = fmtdesc->pixelformat >> 24;
861 fmtdesc->description[4] = '\0';
862 return 0;
863}
864
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300865static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300866 struct v4l2_format *fmt)
867{
868 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300869 int mode;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300870
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300871 mode = gspca_dev->curr_mode;
872 memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode],
873 sizeof fmt->fmt.pix);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300874 return 0;
875}
876
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300877static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300878 struct v4l2_format *fmt)
879{
Hans de Goede24c530b2008-07-04 17:55:18 -0300880 int w, h, mode, mode2;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300881
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300882 w = fmt->fmt.pix.width;
883 h = fmt->fmt.pix.height;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300884
Jean-Francois Moine335b3f82008-07-30 04:53:02 -0300885#ifdef GSPCA_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300886 if (gspca_debug & D_CONF)
887 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
888#endif
889 /* search the closest mode for width and height */
890 mode = wxh_to_mode(gspca_dev, w, h);
891
892 /* OK if right palette */
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300893 if (gspca_dev->cam.cam_mode[mode].pixelformat
894 != fmt->fmt.pix.pixelformat) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300895
896 /* else, search the closest mode with the same pixel format */
897 mode2 = gspca_get_mode(gspca_dev, mode,
898 fmt->fmt.pix.pixelformat);
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300899 if (mode2 >= 0)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300900 mode = mode2;
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300901/* else
902 ; * no chance, return this mode */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300903 }
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300904 memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode],
905 sizeof fmt->fmt.pix);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300906 return mode; /* used when s_fmt */
907}
908
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300909static int vidioc_try_fmt_vid_cap(struct file *file,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300910 void *priv,
911 struct v4l2_format *fmt)
912{
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300913 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300914 int ret;
915
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300916 ret = try_fmt_vid_cap(gspca_dev, fmt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300917 if (ret < 0)
918 return ret;
919 return 0;
920}
921
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300922static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300923 struct v4l2_format *fmt)
924{
925 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300926 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300927
Hans de Goedee2997a72008-04-23 08:09:12 -0300928 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
929 return -ERESTARTSYS;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300930
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -0300931 ret = try_fmt_vid_cap(gspca_dev, fmt);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300932 if (ret < 0)
933 goto out;
934
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300935 if (gspca_dev->nframes != 0
936 && fmt->fmt.pix.sizeimage > gspca_dev->frsz) {
937 ret = -EINVAL;
938 goto out;
939 }
940
Jean-Francois Moine50a871f2008-06-30 19:47:33 -0300941 if (ret == gspca_dev->curr_mode) {
942 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300943 goto out; /* same mode */
Jean-Francois Moine50a871f2008-06-30 19:47:33 -0300944 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300945
946 if (gspca_dev->streaming) {
947 ret = -EBUSY;
948 goto out;
Hans de Goedee2997a72008-04-23 08:09:12 -0300949 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300950 gspca_dev->width = fmt->fmt.pix.width;
951 gspca_dev->height = fmt->fmt.pix.height;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300952 gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
953 gspca_dev->curr_mode = ret;
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300954
Jean-Francois Moined43fa322008-06-12 10:58:58 -0300955 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -0300956out:
957 mutex_unlock(&gspca_dev->queue_lock);
958 return ret;
959}
960
Hans de Goede11c635a2009-05-25 15:04:22 -0300961static int vidioc_enum_framesizes(struct file *file, void *priv,
962 struct v4l2_frmsizeenum *fsize)
963{
964 struct gspca_dev *gspca_dev = priv;
965 int i;
966 __u32 index = 0;
967
968 for (i = 0; i < gspca_dev->cam.nmodes; i++) {
969 if (fsize->pixel_format !=
970 gspca_dev->cam.cam_mode[i].pixelformat)
971 continue;
972
973 if (fsize->index == index) {
974 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
975 fsize->discrete.width =
976 gspca_dev->cam.cam_mode[i].width;
977 fsize->discrete.height =
978 gspca_dev->cam.cam_mode[i].height;
979 return 0;
980 }
981 index++;
982 }
983
984 return -EINVAL;
985}
986
Antonio Ospite28ffe772009-12-02 06:18:46 -0300987static int vidioc_enum_frameintervals(struct file *filp, void *priv,
988 struct v4l2_frmivalenum *fival)
989{
990 struct gspca_dev *gspca_dev = priv;
991 int mode = wxh_to_mode(gspca_dev, fival->width, fival->height);
992 __u32 i;
993
994 if (gspca_dev->cam.mode_framerates == NULL ||
995 gspca_dev->cam.mode_framerates[mode].nrates == 0)
996 return -EINVAL;
997
998 if (fival->pixel_format !=
999 gspca_dev->cam.cam_mode[mode].pixelformat)
1000 return -EINVAL;
1001
1002 for (i = 0; i < gspca_dev->cam.mode_framerates[mode].nrates; i++) {
1003 if (fival->index == i) {
1004 fival->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1005 fival->discrete.numerator = 1;
1006 fival->discrete.denominator =
1007 gspca_dev->cam.mode_framerates[mode].rates[i];
1008 return 0;
1009 }
1010 }
1011
1012 return -EINVAL;
1013}
1014
Hans de Goeded0182302008-11-19 17:10:47 -03001015static void gspca_release(struct video_device *vfd)
Frank Zago6b060ff2008-09-28 08:12:22 -03001016{
Hans de Goeded0182302008-11-19 17:10:47 -03001017 struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev);
Frank Zago6b060ff2008-09-28 08:12:22 -03001018
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001019 PDEBUG(D_PROBE, "%s released",
1020 video_device_node_name(&gspca_dev->vdev));
Frank Zago6b060ff2008-09-28 08:12:22 -03001021
1022 kfree(gspca_dev->usb_buf);
1023 kfree(gspca_dev);
1024}
1025
Hans Verkuilbec43662008-12-30 06:58:20 -03001026static int dev_open(struct file *file)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001027{
1028 struct gspca_dev *gspca_dev;
1029 int ret;
1030
Jean-Francois Moine0d07e242009-10-01 13:44:49 -03001031 PDEBUG(D_STREAM, "[%s] open", current->comm);
Jean-Francois Moinea12ca6a2008-11-19 06:37:53 -03001032 gspca_dev = (struct gspca_dev *) video_devdata(file);
Hans de Goedee2997a72008-04-23 08:09:12 -03001033 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1034 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001035 if (!gspca_dev->present) {
1036 ret = -ENODEV;
1037 goto out;
1038 }
1039
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001040 if (gspca_dev->users > 4) { /* (arbitrary value) */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001041 ret = -EBUSY;
1042 goto out;
1043 }
Jean-Francois Moine5c4fa002008-11-18 15:52:31 -03001044
1045 /* protect the subdriver against rmmod */
1046 if (!try_module_get(gspca_dev->module)) {
1047 ret = -ENODEV;
1048 goto out;
1049 }
1050
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001051 gspca_dev->users++;
Frank Zago6b060ff2008-09-28 08:12:22 -03001052
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001053 file->private_data = gspca_dev;
Jean-Francois Moine335b3f82008-07-30 04:53:02 -03001054#ifdef GSPCA_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001055 /* activate the v4l2 debug */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001056 if (gspca_debug & D_V4L2)
Jean-Francois Moinea12ca6a2008-11-19 06:37:53 -03001057 gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
Frank Zago9de436c2008-09-15 05:20:38 -03001058 | V4L2_DEBUG_IOCTL_ARG;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001059 else
Jean-Francois Moinea12ca6a2008-11-19 06:37:53 -03001060 gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
Frank Zago9de436c2008-09-15 05:20:38 -03001061 | V4L2_DEBUG_IOCTL_ARG);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001062#endif
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03001063 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001064out:
1065 mutex_unlock(&gspca_dev->queue_lock);
1066 if (ret != 0)
1067 PDEBUG(D_ERR|D_STREAM, "open failed err %d", ret);
1068 else
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001069 PDEBUG(D_STREAM, "open done");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001070 return ret;
1071}
1072
Hans Verkuilbec43662008-12-30 06:58:20 -03001073static int dev_close(struct file *file)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001074{
1075 struct gspca_dev *gspca_dev = file->private_data;
1076
Jean-Francois Moine0d07e242009-10-01 13:44:49 -03001077 PDEBUG(D_STREAM, "[%s] close", current->comm);
Hans de Goedee2997a72008-04-23 08:09:12 -03001078 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1079 return -ERESTARTSYS;
1080 gspca_dev->users--;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001081
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001082 /* if the file did the capture, free the streaming resources */
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001083 if (gspca_dev->capt_file == file) {
Jean-Francois Moinea1e82882008-09-03 17:12:17 -03001084 if (gspca_dev->streaming) {
1085 mutex_lock(&gspca_dev->usb_lock);
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -03001086 gspca_dev->usb_err = 0;
Jean-Francois Moinea1e82882008-09-03 17:12:17 -03001087 gspca_stream_off(gspca_dev);
1088 mutex_unlock(&gspca_dev->usb_lock);
1089 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001090 frame_free(gspca_dev);
Harvey Harrisonefab8212008-07-05 06:12:47 -03001091 gspca_dev->capt_file = NULL;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001092 gspca_dev->memory = GSPCA_MEMORY_NO;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001093 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001094 file->private_data = NULL;
Jean-Francois Moine5c4fa002008-11-18 15:52:31 -03001095 module_put(gspca_dev->module);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001096 mutex_unlock(&gspca_dev->queue_lock);
Frank Zago6b060ff2008-09-28 08:12:22 -03001097
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001098 PDEBUG(D_STREAM, "close done");
Frank Zago6b060ff2008-09-28 08:12:22 -03001099
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001100 return 0;
1101}
1102
1103static int vidioc_querycap(struct file *file, void *priv,
1104 struct v4l2_capability *cap)
1105{
1106 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine090264e2009-02-12 08:05:45 -03001107 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001108
Jean-Francois Moine090264e2009-02-12 08:05:45 -03001109 /* protect the access to the usb device */
1110 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1111 return -ERESTARTSYS;
1112 if (!gspca_dev->present) {
1113 ret = -ENODEV;
1114 goto out;
1115 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001116 strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
Jean-Francois Moinec6edaf12008-07-23 03:24:06 -03001117 if (gspca_dev->dev->product != NULL) {
1118 strncpy(cap->card, gspca_dev->dev->product,
1119 sizeof cap->card);
1120 } else {
1121 snprintf(cap->card, sizeof cap->card,
1122 "USB Camera (%04x:%04x)",
1123 le16_to_cpu(gspca_dev->dev->descriptor.idVendor),
1124 le16_to_cpu(gspca_dev->dev->descriptor.idProduct));
1125 }
Thierry MERLE59320282009-01-21 15:32:26 -03001126 usb_make_path(gspca_dev->dev, cap->bus_info, sizeof(cap->bus_info));
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001127 cap->version = DRIVER_VERSION_NUMBER;
1128 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
1129 | V4L2_CAP_STREAMING
1130 | V4L2_CAP_READWRITE;
Jean-Francois Moine090264e2009-02-12 08:05:45 -03001131 ret = 0;
1132out:
1133 mutex_unlock(&gspca_dev->usb_lock);
1134 return ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001135}
1136
Hans de Goedea0001a22009-06-10 04:52:18 -03001137static const struct ctrl *get_ctrl(struct gspca_dev *gspca_dev,
1138 int id)
1139{
1140 const struct ctrl *ctrls;
1141 int i;
1142
1143 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
1144 i < gspca_dev->sd_desc->nctrls;
1145 i++, ctrls++) {
1146 if (gspca_dev->ctrl_dis & (1 << i))
1147 continue;
1148 if (id == ctrls->qctrl.id)
1149 return ctrls;
1150 }
1151 return NULL;
1152}
1153
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001154static int vidioc_queryctrl(struct file *file, void *priv,
1155 struct v4l2_queryctrl *q_ctrl)
1156{
1157 struct gspca_dev *gspca_dev = priv;
Hans de Goedea0001a22009-06-10 04:52:18 -03001158 const struct ctrl *ctrls;
1159 int i;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001160 u32 id;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001161
Hans de Goedea0001a22009-06-10 04:52:18 -03001162 ctrls = NULL;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001163 id = q_ctrl->id;
1164 if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
1165 id &= V4L2_CTRL_ID_MASK;
1166 id++;
1167 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
Hans de Goedea0001a22009-06-10 04:52:18 -03001168 if (gspca_dev->ctrl_dis & (1 << i))
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -03001169 continue;
Hans de Goedeb8bfb5f2009-06-13 18:56:22 -03001170 if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -03001171 continue;
Hans de Goedeb8bfb5f2009-06-13 18:56:22 -03001172 if (ctrls && gspca_dev->sd_desc->ctrls[i].qctrl.id
Hans de Goedea0001a22009-06-10 04:52:18 -03001173 > ctrls->qctrl.id)
Hans de Goedeb8bfb5f2009-06-13 18:56:22 -03001174 continue;
Hans de Goedea0001a22009-06-10 04:52:18 -03001175 ctrls = &gspca_dev->sd_desc->ctrls[i];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001176 }
Jean-Francois Moine83955552009-12-12 06:58:01 -03001177 if (ctrls == NULL)
1178 return -EINVAL;
Hans de Goedea0001a22009-06-10 04:52:18 -03001179 } else {
1180 ctrls = get_ctrl(gspca_dev, id);
Jean-Francois Moine83955552009-12-12 06:58:01 -03001181 if (ctrls == NULL)
1182 return -EINVAL;
Jean-Francois Moine4af85662009-11-12 15:59:27 -03001183 i = ctrls - gspca_dev->sd_desc->ctrls;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001184 }
Hans de Goedea0001a22009-06-10 04:52:18 -03001185 memcpy(q_ctrl, ctrls, sizeof *q_ctrl);
Jean-Francois Moine4af85662009-11-12 15:59:27 -03001186 if (gspca_dev->ctrl_inac & (1 << i))
1187 q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
Jean-Francois Moinef50ba1b2008-09-03 17:12:14 -03001188 return 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001189}
1190
1191static int vidioc_s_ctrl(struct file *file, void *priv,
1192 struct v4l2_control *ctrl)
1193{
1194 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001195 const struct ctrl *ctrls;
Hans de Goedea0001a22009-06-10 04:52:18 -03001196 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001197
Hans de Goedea0001a22009-06-10 04:52:18 -03001198 ctrls = get_ctrl(gspca_dev, ctrl->id);
1199 if (ctrls == NULL)
1200 return -EINVAL;
1201
1202 if (ctrl->value < ctrls->qctrl.minimum
1203 || ctrl->value > ctrls->qctrl.maximum)
1204 return -ERANGE;
1205 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
1206 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1207 return -ERESTARTSYS;
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -03001208 gspca_dev->usb_err = 0;
Hans de Goedea0001a22009-06-10 04:52:18 -03001209 if (gspca_dev->present)
1210 ret = ctrls->set(gspca_dev, ctrl->value);
1211 else
1212 ret = -ENODEV;
1213 mutex_unlock(&gspca_dev->usb_lock);
1214 return ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001215}
1216
1217static int vidioc_g_ctrl(struct file *file, void *priv,
1218 struct v4l2_control *ctrl)
1219{
1220 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001221 const struct ctrl *ctrls;
Hans de Goedea0001a22009-06-10 04:52:18 -03001222 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001223
Hans de Goedea0001a22009-06-10 04:52:18 -03001224 ctrls = get_ctrl(gspca_dev, ctrl->id);
1225 if (ctrls == NULL)
1226 return -EINVAL;
1227
1228 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1229 return -ERESTARTSYS;
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -03001230 gspca_dev->usb_err = 0;
Hans de Goedea0001a22009-06-10 04:52:18 -03001231 if (gspca_dev->present)
1232 ret = ctrls->get(gspca_dev, &ctrl->value);
1233 else
1234 ret = -ENODEV;
1235 mutex_unlock(&gspca_dev->usb_lock);
1236 return ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001237}
1238
Jean-Francois Moinef955c4f2008-11-28 08:51:50 -03001239/*fixme: have an audio flag in gspca_dev?*/
1240static int vidioc_s_audio(struct file *file, void *priv,
1241 struct v4l2_audio *audio)
1242{
1243 if (audio->index != 0)
1244 return -EINVAL;
1245 return 0;
1246}
1247
1248static int vidioc_g_audio(struct file *file, void *priv,
1249 struct v4l2_audio *audio)
1250{
Jean-Francois Moinef955c4f2008-11-28 08:51:50 -03001251 strcpy(audio->name, "Microphone");
1252 return 0;
1253}
1254
1255static int vidioc_enumaudio(struct file *file, void *priv,
1256 struct v4l2_audio *audio)
1257{
1258 if (audio->index != 0)
1259 return -EINVAL;
1260
1261 strcpy(audio->name, "Microphone");
1262 audio->capability = 0;
1263 audio->mode = 0;
1264 return 0;
1265}
1266
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001267static int vidioc_querymenu(struct file *file, void *priv,
1268 struct v4l2_querymenu *qmenu)
1269{
1270 struct gspca_dev *gspca_dev = priv;
1271
1272 if (!gspca_dev->sd_desc->querymenu)
1273 return -EINVAL;
1274 return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu);
1275}
1276
1277static int vidioc_enum_input(struct file *file, void *priv,
1278 struct v4l2_input *input)
1279{
1280 struct gspca_dev *gspca_dev = priv;
1281
1282 if (input->index != 0)
1283 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001284 input->type = V4L2_INPUT_TYPE_CAMERA;
Adam Bakerdfa76fa2009-03-29 19:17:10 -03001285 input->status = gspca_dev->cam.input_flags;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001286 strncpy(input->name, gspca_dev->sd_desc->name,
1287 sizeof input->name);
1288 return 0;
1289}
1290
1291static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1292{
1293 *i = 0;
1294 return 0;
1295}
1296
1297static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1298{
1299 if (i > 0)
1300 return -EINVAL;
1301 return (0);
1302}
1303
1304static int vidioc_reqbufs(struct file *file, void *priv,
1305 struct v4l2_requestbuffers *rb)
1306{
1307 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001308 int i, ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001309
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001310 switch (rb->memory) {
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001311 case GSPCA_MEMORY_READ: /* (internal call) */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001312 case V4L2_MEMORY_MMAP:
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001313 case V4L2_MEMORY_USERPTR:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001314 break;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001315 default:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001316 return -EINVAL;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001317 }
Hans de Goedee2997a72008-04-23 08:09:12 -03001318 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1319 return -ERESTARTSYS;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001320
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001321 if (gspca_dev->memory != GSPCA_MEMORY_NO
1322 && gspca_dev->memory != rb->memory) {
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001323 ret = -EBUSY;
1324 goto out;
1325 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001326
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001327 /* only one file may do the capture */
1328 if (gspca_dev->capt_file != NULL
1329 && gspca_dev->capt_file != file) {
1330 ret = -EBUSY;
1331 goto out;
1332 }
1333
1334 /* if allocated, the buffers must not be mapped */
1335 for (i = 0; i < gspca_dev->nframes; i++) {
1336 if (gspca_dev->frame[i].vma_use_count) {
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -03001337 ret = -EBUSY;
1338 goto out;
1339 }
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001340 }
1341
1342 /* stop streaming */
1343 if (gspca_dev->streaming) {
1344 mutex_lock(&gspca_dev->usb_lock);
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -03001345 gspca_dev->usb_err = 0;
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001346 gspca_stream_off(gspca_dev);
1347 mutex_unlock(&gspca_dev->usb_lock);
1348 }
1349
1350 /* free the previous allocated buffers, if any */
1351 if (gspca_dev->nframes != 0) {
1352 frame_free(gspca_dev);
1353 gspca_dev->capt_file = NULL;
1354 }
1355 if (rb->count == 0) /* unrequest */
1356 goto out;
1357 gspca_dev->memory = rb->memory;
1358 ret = frame_alloc(gspca_dev, rb->count);
1359 if (ret == 0) {
1360 rb->count = gspca_dev->nframes;
1361 gspca_dev->capt_file = file;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001362 }
1363out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001364 mutex_unlock(&gspca_dev->queue_lock);
1365 PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count);
1366 return ret;
1367}
1368
1369static int vidioc_querybuf(struct file *file, void *priv,
1370 struct v4l2_buffer *v4l2_buf)
1371{
1372 struct gspca_dev *gspca_dev = priv;
1373 struct gspca_frame *frame;
1374
Jean-Francois Moine13752bd2008-12-19 15:08:51 -03001375 if (v4l2_buf->index < 0
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001376 || v4l2_buf->index >= gspca_dev->nframes)
1377 return -EINVAL;
1378
1379 frame = &gspca_dev->frame[v4l2_buf->index];
1380 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1381 return 0;
1382}
1383
1384static int vidioc_streamon(struct file *file, void *priv,
1385 enum v4l2_buf_type buf_type)
1386{
1387 struct gspca_dev *gspca_dev = priv;
1388 int ret;
1389
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001390 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1391 return -EINVAL;
Hans de Goedee2997a72008-04-23 08:09:12 -03001392 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1393 return -ERESTARTSYS;
Jean-Francois Moine090264e2009-02-12 08:05:45 -03001394
Jean-Francois Moine1edabe72008-12-19 15:17:25 -03001395 if (gspca_dev->nframes == 0
1396 || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001397 ret = -EINVAL;
1398 goto out;
1399 }
1400 if (!gspca_dev->streaming) {
1401 ret = gspca_init_transfer(gspca_dev);
1402 if (ret < 0)
1403 goto out;
1404 }
Jean-Francois Moine335b3f82008-07-30 04:53:02 -03001405#ifdef GSPCA_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001406 if (gspca_debug & D_STREAM) {
1407 PDEBUG_MODE("stream on OK",
1408 gspca_dev->pixfmt,
1409 gspca_dev->width,
1410 gspca_dev->height);
1411 }
1412#endif
Hans de Goedee2997a72008-04-23 08:09:12 -03001413 ret = 0;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001414out:
1415 mutex_unlock(&gspca_dev->queue_lock);
1416 return ret;
1417}
1418
1419static int vidioc_streamoff(struct file *file, void *priv,
1420 enum v4l2_buf_type buf_type)
1421{
1422 struct gspca_dev *gspca_dev = priv;
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001423 int i, ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001424
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001425 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1426 return -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001427 if (!gspca_dev->streaming)
1428 return 0;
1429 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1430 return -ERESTARTSYS;
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001431
1432 /* stop streaming */
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001433 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
1434 ret = -ERESTARTSYS;
1435 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001436 }
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -03001437 gspca_dev->usb_err = 0;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001438 gspca_stream_off(gspca_dev);
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001439 mutex_unlock(&gspca_dev->usb_lock);
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001440
1441 /* empty the application queues */
1442 for (i = 0; i < gspca_dev->nframes; i++)
1443 gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS;
1444 gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
1445 gspca_dev->last_packet_type = DISCARD_PACKET;
1446 gspca_dev->sequence = 0;
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001447 ret = 0;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001448out:
1449 mutex_unlock(&gspca_dev->queue_lock);
1450 return ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001451}
1452
1453static int vidioc_g_jpegcomp(struct file *file, void *priv,
1454 struct v4l2_jpegcompression *jpegcomp)
1455{
1456 struct gspca_dev *gspca_dev = priv;
1457 int ret;
1458
1459 if (!gspca_dev->sd_desc->get_jcomp)
1460 return -EINVAL;
Hans de Goedee2997a72008-04-23 08:09:12 -03001461 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1462 return -ERESTARTSYS;
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -03001463 gspca_dev->usb_err = 0;
Jean-Francois Moine090264e2009-02-12 08:05:45 -03001464 if (gspca_dev->present)
1465 ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
1466 else
1467 ret = -ENODEV;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001468 mutex_unlock(&gspca_dev->usb_lock);
1469 return ret;
1470}
1471
1472static int vidioc_s_jpegcomp(struct file *file, void *priv,
1473 struct v4l2_jpegcompression *jpegcomp)
1474{
1475 struct gspca_dev *gspca_dev = priv;
1476 int ret;
1477
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001478 if (!gspca_dev->sd_desc->set_jcomp)
1479 return -EINVAL;
Jim Parisf86d4a92008-12-10 05:50:44 -03001480 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1481 return -ERESTARTSYS;
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -03001482 gspca_dev->usb_err = 0;
Jean-Francois Moine090264e2009-02-12 08:05:45 -03001483 if (gspca_dev->present)
1484 ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
1485 else
1486 ret = -ENODEV;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001487 mutex_unlock(&gspca_dev->usb_lock);
1488 return ret;
1489}
1490
1491static int vidioc_g_parm(struct file *filp, void *priv,
1492 struct v4l2_streamparm *parm)
1493{
1494 struct gspca_dev *gspca_dev = priv;
1495
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001496 parm->parm.capture.readbuffers = gspca_dev->nbufread;
Jim Paris627a5ef2008-12-10 06:02:42 -03001497
1498 if (gspca_dev->sd_desc->get_streamparm) {
1499 int ret;
1500
1501 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1502 return -ERESTARTSYS;
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -03001503 gspca_dev->usb_err = 0;
Jean-Francois Moine090264e2009-02-12 08:05:45 -03001504 if (gspca_dev->present)
1505 ret = gspca_dev->sd_desc->get_streamparm(gspca_dev,
1506 parm);
1507 else
1508 ret = -ENODEV;
Jim Paris627a5ef2008-12-10 06:02:42 -03001509 mutex_unlock(&gspca_dev->usb_lock);
1510 return ret;
1511 }
1512
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001513 return 0;
1514}
1515
1516static int vidioc_s_parm(struct file *filp, void *priv,
1517 struct v4l2_streamparm *parm)
1518{
1519 struct gspca_dev *gspca_dev = priv;
1520 int n;
1521
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001522 n = parm->parm.capture.readbuffers;
1523 if (n == 0 || n > GSPCA_MAX_FRAMES)
1524 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1525 else
1526 gspca_dev->nbufread = n;
Jim Paris627a5ef2008-12-10 06:02:42 -03001527
1528 if (gspca_dev->sd_desc->set_streamparm) {
1529 int ret;
1530
1531 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1532 return -ERESTARTSYS;
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -03001533 gspca_dev->usb_err = 0;
Jean-Francois Moine090264e2009-02-12 08:05:45 -03001534 if (gspca_dev->present)
1535 ret = gspca_dev->sd_desc->set_streamparm(gspca_dev,
1536 parm);
1537 else
1538 ret = -ENODEV;
Jim Paris627a5ef2008-12-10 06:02:42 -03001539 mutex_unlock(&gspca_dev->usb_lock);
1540 return ret;
1541 }
1542
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001543 return 0;
1544}
1545
1546#ifdef CONFIG_VIDEO_V4L1_COMPAT
1547static int vidiocgmbuf(struct file *file, void *priv,
1548 struct video_mbuf *mbuf)
1549{
1550 struct gspca_dev *gspca_dev = file->private_data;
1551 int i;
1552
1553 PDEBUG(D_STREAM, "cgmbuf");
1554 if (gspca_dev->nframes == 0) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001555 int ret;
1556
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001557 {
1558 struct v4l2_format fmt;
1559
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001560 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1561 i = gspca_dev->cam.nmodes - 1; /* highest mode */
1562 fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width;
1563 fmt.fmt.pix.height = gspca_dev->cam.cam_mode[i].height;
1564 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -03001565 ret = vidioc_s_fmt_vid_cap(file, priv, &fmt);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001566 if (ret != 0)
1567 return ret;
1568 }
1569 {
1570 struct v4l2_requestbuffers rb;
1571
1572 memset(&rb, 0, sizeof rb);
1573 rb.count = 4;
1574 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1575 rb.memory = V4L2_MEMORY_MMAP;
1576 ret = vidioc_reqbufs(file, priv, &rb);
1577 if (ret != 0)
1578 return ret;
1579 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001580 }
1581 mbuf->frames = gspca_dev->nframes;
1582 mbuf->size = gspca_dev->frsz * gspca_dev->nframes;
1583 for (i = 0; i < mbuf->frames; i++)
1584 mbuf->offsets[i] = gspca_dev->frame[i].v4l2_buf.m.offset;
1585 return 0;
1586}
1587#endif
1588
1589static int dev_mmap(struct file *file, struct vm_area_struct *vma)
1590{
1591 struct gspca_dev *gspca_dev = file->private_data;
Harvey Harrisonefab8212008-07-05 06:12:47 -03001592 struct gspca_frame *frame;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001593 struct page *page;
1594 unsigned long addr, start, size;
1595 int i, ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001596
1597 start = vma->vm_start;
1598 size = vma->vm_end - vma->vm_start;
1599 PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size);
1600
Hans de Goedee2997a72008-04-23 08:09:12 -03001601 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1602 return -ERESTARTSYS;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001603 if (!gspca_dev->present) {
1604 ret = -ENODEV;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001605 goto out;
1606 }
1607 if (gspca_dev->capt_file != file) {
1608 ret = -EINVAL;
1609 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001610 }
1611
Harvey Harrisonefab8212008-07-05 06:12:47 -03001612 frame = NULL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001613 for (i = 0; i < gspca_dev->nframes; ++i) {
1614 if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) {
1615 PDEBUG(D_STREAM, "mmap bad memory type");
1616 break;
1617 }
1618 if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT)
1619 == vma->vm_pgoff) {
1620 frame = &gspca_dev->frame[i];
1621 break;
1622 }
1623 }
Harvey Harrisonefab8212008-07-05 06:12:47 -03001624 if (frame == NULL) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001625 PDEBUG(D_STREAM, "mmap no frame buffer found");
1626 ret = -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001627 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001628 }
1629#ifdef CONFIG_VIDEO_V4L1_COMPAT
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -03001630 /* v4l1 maps all the buffers */
1631 if (i != 0
1632 || size != frame->v4l2_buf.length * gspca_dev->nframes)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001633#endif
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -03001634 if (size != frame->v4l2_buf.length) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001635 PDEBUG(D_STREAM, "mmap bad size");
1636 ret = -EINVAL;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001637 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001638 }
1639
1640 /*
1641 * - VM_IO marks the area as being a mmaped region for I/O to a
1642 * device. It also prevents the region from being core dumped.
1643 */
1644 vma->vm_flags |= VM_IO;
1645
1646 addr = (unsigned long) frame->data;
1647 while (size > 0) {
1648 page = vmalloc_to_page((void *) addr);
1649 ret = vm_insert_page(vma, start, page);
1650 if (ret < 0)
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001651 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001652 start += PAGE_SIZE;
1653 addr += PAGE_SIZE;
1654 size -= PAGE_SIZE;
1655 }
1656
Jean-Francois Moined50e2572009-11-26 15:36:40 -03001657 vma->vm_ops = &gspca_vm_ops;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001658 vma->vm_private_data = frame;
1659 gspca_vm_open(vma);
Hans de Goedee2997a72008-04-23 08:09:12 -03001660 ret = 0;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001661out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001662 mutex_unlock(&gspca_dev->queue_lock);
1663 return ret;
1664}
1665
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001666/*
1667 * wait for a video frame
1668 *
1669 * If a frame is ready, its index is returned.
1670 */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001671static int frame_wait(struct gspca_dev *gspca_dev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001672 int nonblock_ing)
1673{
1674 struct gspca_frame *frame;
1675 int i, j, ret;
1676
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001677 /* check if a frame is ready */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001678 i = gspca_dev->fr_o;
1679 j = gspca_dev->fr_queue[i];
1680 frame = &gspca_dev->frame[j];
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001681
Hans de Goede181b7042008-11-19 17:16:26 -03001682 if (!(frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE)) {
1683 if (nonblock_ing)
1684 return -EAGAIN;
1685
1686 /* wait till a frame is ready */
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001687 ret = wait_event_interruptible_timeout(gspca_dev->wq,
Hans de Goede181b7042008-11-19 17:16:26 -03001688 (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) ||
1689 !gspca_dev->streaming || !gspca_dev->present,
1690 msecs_to_jiffies(3000));
1691 if (ret < 0)
1692 return ret;
1693 if (ret == 0 || !gspca_dev->streaming || !gspca_dev->present)
Hans de Goedee2997a72008-04-23 08:09:12 -03001694 return -EIO;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001695 }
Hans de Goede181b7042008-11-19 17:16:26 -03001696
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001697 gspca_dev->fr_o = (i + 1) % gspca_dev->nframes;
1698 PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d",
1699 gspca_dev->fr_q,
1700 gspca_dev->fr_i,
1701 gspca_dev->fr_o);
Hans de Goedee2997a72008-04-23 08:09:12 -03001702
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001703 if (gspca_dev->sd_desc->dq_callback) {
1704 mutex_lock(&gspca_dev->usb_lock);
Jean-Francois Moine8c4ebae2009-12-02 07:14:33 -03001705 gspca_dev->usb_err = 0;
Jean-Francois Moine090264e2009-02-12 08:05:45 -03001706 if (gspca_dev->present)
1707 gspca_dev->sd_desc->dq_callback(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001708 mutex_unlock(&gspca_dev->usb_lock);
1709 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001710 return j;
1711}
1712
1713/*
1714 * dequeue a video buffer
1715 *
1716 * If nonblock_ing is false, block until a buffer is available.
1717 */
1718static int vidioc_dqbuf(struct file *file, void *priv,
1719 struct v4l2_buffer *v4l2_buf)
1720{
1721 struct gspca_dev *gspca_dev = priv;
1722 struct gspca_frame *frame;
1723 int i, ret;
1724
1725 PDEBUG(D_FRAM, "dqbuf");
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -03001726 if (v4l2_buf->memory != gspca_dev->memory)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001727 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001728
Jean-Francois Moine090264e2009-02-12 08:05:45 -03001729 if (!gspca_dev->present)
1730 return -ENODEV;
1731
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001732 /* if not streaming, be sure the application will not loop forever */
1733 if (!(file->f_flags & O_NONBLOCK)
1734 && !gspca_dev->streaming && gspca_dev->users == 1)
1735 return -EINVAL;
1736
1737 /* only the capturing file may dequeue */
1738 if (gspca_dev->capt_file != file)
1739 return -EINVAL;
1740
1741 /* only one dequeue / read at a time */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001742 if (mutex_lock_interruptible(&gspca_dev->read_lock))
1743 return -ERESTARTSYS;
1744
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001745 ret = frame_wait(gspca_dev, file->f_flags & O_NONBLOCK);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001746 if (ret < 0)
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001747 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001748 i = ret; /* frame index */
1749 frame = &gspca_dev->frame[i];
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -03001750 if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -03001751 if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -03001752 frame->data,
1753 frame->v4l2_buf.bytesused)) {
1754 PDEBUG(D_ERR|D_STREAM,
1755 "dqbuf cp to user failed");
1756 ret = -EFAULT;
1757 goto out;
1758 }
1759 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001760 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
1761 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1762 PDEBUG(D_FRAM, "dqbuf %d", i);
1763 ret = 0;
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001764out:
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001765 mutex_unlock(&gspca_dev->read_lock);
1766 return ret;
1767}
1768
1769/*
1770 * queue a video buffer
1771 *
1772 * Attempting to queue a buffer that has already been
1773 * queued will return -EINVAL.
1774 */
1775static int vidioc_qbuf(struct file *file, void *priv,
1776 struct v4l2_buffer *v4l2_buf)
1777{
1778 struct gspca_dev *gspca_dev = priv;
1779 struct gspca_frame *frame;
1780 int i, index, ret;
1781
1782 PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001783
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001784 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1785 return -ERESTARTSYS;
1786
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001787 index = v4l2_buf->index;
1788 if ((unsigned) index >= gspca_dev->nframes) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001789 PDEBUG(D_FRAM,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001790 "qbuf idx %d >= %d", index, gspca_dev->nframes);
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001791 ret = -EINVAL;
1792 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001793 }
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001794 if (v4l2_buf->memory != gspca_dev->memory) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001795 PDEBUG(D_FRAM, "qbuf bad memory type");
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001796 ret = -EINVAL;
1797 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001798 }
1799
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001800 frame = &gspca_dev->frame[index];
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001801 if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) {
1802 PDEBUG(D_FRAM, "qbuf bad state");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001803 ret = -EINVAL;
1804 goto out;
1805 }
1806
1807 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001808
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001809 if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001810 frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
1811 frame->v4l2_buf.length = v4l2_buf->length;
1812 }
1813
1814 /* put the buffer in the 'queued' queue */
1815 i = gspca_dev->fr_q;
1816 gspca_dev->fr_queue[i] = index;
Jean-Francois Moine8c32aa52009-12-14 14:57:49 -03001817 if (gspca_dev->fr_i == i)
1818 gspca_dev->cur_frame = frame;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001819 gspca_dev->fr_q = (i + 1) % gspca_dev->nframes;
1820 PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d",
1821 gspca_dev->fr_q,
1822 gspca_dev->fr_i,
1823 gspca_dev->fr_o);
1824
1825 v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
1826 v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE;
1827 ret = 0;
1828out:
1829 mutex_unlock(&gspca_dev->queue_lock);
1830 return ret;
1831}
1832
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001833/*
1834 * allocate the resources for read()
1835 */
1836static int read_alloc(struct gspca_dev *gspca_dev,
1837 struct file *file)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001838{
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001839 struct v4l2_buffer v4l2_buf;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001840 int i, ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001841
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001842 PDEBUG(D_STREAM, "read alloc");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001843 if (gspca_dev->nframes == 0) {
1844 struct v4l2_requestbuffers rb;
1845
1846 memset(&rb, 0, sizeof rb);
1847 rb.count = gspca_dev->nbufread;
1848 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -03001849 rb.memory = GSPCA_MEMORY_READ;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001850 ret = vidioc_reqbufs(file, gspca_dev, &rb);
1851 if (ret != 0) {
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001852 PDEBUG(D_STREAM, "read reqbuf err %d", ret);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001853 return ret;
1854 }
1855 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1856 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -03001857 v4l2_buf.memory = GSPCA_MEMORY_READ;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001858 for (i = 0; i < gspca_dev->nbufread; i++) {
1859 v4l2_buf.index = i;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001860 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1861 if (ret != 0) {
1862 PDEBUG(D_STREAM, "read qbuf err: %d", ret);
1863 return ret;
1864 }
1865 }
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001866 gspca_dev->memory = GSPCA_MEMORY_READ;
1867 }
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03001868
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001869 /* start streaming */
1870 ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE);
1871 if (ret != 0)
1872 PDEBUG(D_STREAM, "read streamon err %d", ret);
1873 return ret;
1874}
1875
1876static unsigned int dev_poll(struct file *file, poll_table *wait)
1877{
1878 struct gspca_dev *gspca_dev = file->private_data;
1879 int i, ret;
1880
1881 PDEBUG(D_FRAM, "poll");
1882
1883 poll_wait(file, &gspca_dev->wq, wait);
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001884
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001885 /* if reqbufs is not done, the user would use read() */
1886 if (gspca_dev->nframes == 0) {
1887 if (gspca_dev->memory != GSPCA_MEMORY_NO)
1888 return POLLERR; /* not the 1st time */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001889 ret = read_alloc(gspca_dev, file);
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001890 if (ret != 0)
1891 return POLLERR;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001892 }
1893
1894 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0)
1895 return POLLERR;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001896
Jean-Francois Moine5b77ae72008-07-12 09:28:04 -03001897 /* check the next incoming buffer */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001898 i = gspca_dev->fr_o;
1899 i = gspca_dev->fr_queue[i];
1900 if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1901 ret = POLLIN | POLLRDNORM; /* something to read */
1902 else
1903 ret = 0;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001904 mutex_unlock(&gspca_dev->queue_lock);
Jean-Francois Moine090264e2009-02-12 08:05:45 -03001905 if (!gspca_dev->present)
1906 return POLLHUP;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001907 return ret;
1908}
1909
1910static ssize_t dev_read(struct file *file, char __user *data,
1911 size_t count, loff_t *ppos)
1912{
1913 struct gspca_dev *gspca_dev = file->private_data;
1914 struct gspca_frame *frame;
1915 struct v4l2_buffer v4l2_buf;
1916 struct timeval timestamp;
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001917 int n, ret, ret2;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001918
Mauro Carvalho Chehaba9e11132008-07-09 05:26:26 -03001919 PDEBUG(D_FRAM, "read (%zd)", count);
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001920 if (!gspca_dev->present)
1921 return -ENODEV;
1922 switch (gspca_dev->memory) {
1923 case GSPCA_MEMORY_NO: /* first time */
1924 ret = read_alloc(gspca_dev, file);
1925 if (ret != 0)
1926 return ret;
1927 break;
1928 case GSPCA_MEMORY_READ:
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001929 if (gspca_dev->capt_file == file)
1930 break;
1931 /* fall thru */
Jean-Francois Moined43fa322008-06-12 10:58:58 -03001932 default:
1933 return -EINVAL;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001934 }
1935
1936 /* get a frame */
1937 jiffies_to_timeval(get_jiffies_64(), &timestamp);
1938 timestamp.tv_sec--;
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001939 n = 2;
1940 for (;;) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001941 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1942 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -03001943 v4l2_buf.memory = GSPCA_MEMORY_READ;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001944 ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf);
1945 if (ret != 0) {
1946 PDEBUG(D_STREAM, "read dqbuf err %d", ret);
1947 return ret;
1948 }
1949
1950 /* if the process slept for more than 1 second,
Frank Zago219423c2008-09-26 07:43:54 -03001951 * get a newer frame */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001952 frame = &gspca_dev->frame[v4l2_buf.index];
Jean-Francois Moine82643d02008-07-02 09:14:56 -03001953 if (--n < 0)
1954 break; /* avoid infinite loop */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001955 if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
1956 break;
1957 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1958 if (ret != 0) {
1959 PDEBUG(D_STREAM, "read qbuf err %d", ret);
1960 return ret;
1961 }
1962 }
1963
1964 /* copy the frame */
Jean-Francois Moineac0d6df2008-07-08 06:58:15 -03001965 if (count > frame->v4l2_buf.bytesused)
1966 count = frame->v4l2_buf.bytesused;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001967 ret = copy_to_user(data, frame->data, count);
1968 if (ret != 0) {
1969 PDEBUG(D_ERR|D_STREAM,
Mauro Carvalho Chehaba9e11132008-07-09 05:26:26 -03001970 "read cp to user lack %d / %zd", ret, count);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001971 ret = -EFAULT;
1972 goto out;
1973 }
1974 ret = count;
1975out:
1976 /* in each case, requeue the buffer */
1977 ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1978 if (ret2 != 0)
1979 return ret2;
1980 return ret;
1981}
1982
Hans Verkuilbec43662008-12-30 06:58:20 -03001983static struct v4l2_file_operations dev_fops = {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001984 .owner = THIS_MODULE,
1985 .open = dev_open,
1986 .release = dev_close,
1987 .read = dev_read,
1988 .mmap = dev_mmap,
Hans Verkuilbec43662008-12-30 06:58:20 -03001989 .unlocked_ioctl = video_ioctl2,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001990 .poll = dev_poll,
1991};
1992
Hans Verkuila3998102008-07-21 02:57:38 -03001993static const struct v4l2_ioctl_ops dev_ioctl_ops = {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03001994 .vidioc_querycap = vidioc_querycap,
1995 .vidioc_dqbuf = vidioc_dqbuf,
1996 .vidioc_qbuf = vidioc_qbuf,
Mauro Carvalho Chehabe0787702008-07-01 04:06:22 -03001997 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1998 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1999 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2000 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002001 .vidioc_streamon = vidioc_streamon,
2002 .vidioc_queryctrl = vidioc_queryctrl,
2003 .vidioc_g_ctrl = vidioc_g_ctrl,
2004 .vidioc_s_ctrl = vidioc_s_ctrl,
Jean-Francois Moinef955c4f2008-11-28 08:51:50 -03002005 .vidioc_g_audio = vidioc_g_audio,
2006 .vidioc_s_audio = vidioc_s_audio,
2007 .vidioc_enumaudio = vidioc_enumaudio,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002008 .vidioc_querymenu = vidioc_querymenu,
2009 .vidioc_enum_input = vidioc_enum_input,
2010 .vidioc_g_input = vidioc_g_input,
2011 .vidioc_s_input = vidioc_s_input,
2012 .vidioc_reqbufs = vidioc_reqbufs,
2013 .vidioc_querybuf = vidioc_querybuf,
2014 .vidioc_streamoff = vidioc_streamoff,
2015 .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
2016 .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
2017 .vidioc_g_parm = vidioc_g_parm,
2018 .vidioc_s_parm = vidioc_s_parm,
Hans de Goede11c635a2009-05-25 15:04:22 -03002019 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Antonio Ospite28ffe772009-12-02 06:18:46 -03002020 .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
Brian Johnsonaf1d9af2009-07-19 05:29:20 -03002021#ifdef CONFIG_VIDEO_ADV_DEBUG
2022 .vidioc_g_register = vidioc_g_register,
2023 .vidioc_s_register = vidioc_s_register,
2024#endif
2025 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002026#ifdef CONFIG_VIDEO_V4L1_COMPAT
2027 .vidiocgmbuf = vidiocgmbuf,
2028#endif
2029};
2030
Hans Verkuila3998102008-07-21 02:57:38 -03002031static struct video_device gspca_template = {
2032 .name = "gspca main driver",
Hans Verkuila3998102008-07-21 02:57:38 -03002033 .fops = &dev_fops,
2034 .ioctl_ops = &dev_ioctl_ops,
Hans de Goeded0182302008-11-19 17:10:47 -03002035 .release = gspca_release,
Hans Verkuila3998102008-07-21 02:57:38 -03002036};
2037
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002038/*
2039 * probe and create a new gspca device
2040 *
2041 * This function must be called by the sub-driver when it is
2042 * called for probing a new device.
2043 */
2044int gspca_dev_probe(struct usb_interface *intf,
2045 const struct usb_device_id *id,
2046 const struct sd_desc *sd_desc,
Jean-Francois Moined43fa322008-06-12 10:58:58 -03002047 int dev_size,
2048 struct module *module)
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002049{
2050 struct usb_interface_descriptor *interface;
2051 struct gspca_dev *gspca_dev;
2052 struct usb_device *dev = interface_to_usbdev(intf);
2053 int ret;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002054
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002055 PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002056
2057 /* we don't handle multi-config cameras */
Jean-Francois Moine0d07e242009-10-01 13:44:49 -03002058 if (dev->descriptor.bNumConfigurations != 1) {
2059 PDEBUG(D_ERR, "Too many config");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002060 return -ENODEV;
Jean-Francois Moine0d07e242009-10-01 13:44:49 -03002061 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002062 interface = &intf->cur_altsetting->desc;
Jean-Francois Moine0d07e242009-10-01 13:44:49 -03002063 if (interface->bInterfaceNumber > 0) {
2064 PDEBUG(D_ERR, "intf != 0");
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002065 return -ENODEV;
Jean-Francois Moine0d07e242009-10-01 13:44:49 -03002066 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002067
2068 /* create the device */
2069 if (dev_size < sizeof *gspca_dev)
2070 dev_size = sizeof *gspca_dev;
2071 gspca_dev = kzalloc(dev_size, GFP_KERNEL);
Erik Andrene293e592008-10-03 08:46:50 -03002072 if (!gspca_dev) {
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002073 err("couldn't kzalloc gspca struct");
Erik Andrene293e592008-10-03 08:46:50 -03002074 return -ENOMEM;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002075 }
Jean-Francois Moine8295d992008-09-03 17:12:19 -03002076 gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
2077 if (!gspca_dev->usb_buf) {
2078 err("out of memory");
Erik Andrene293e592008-10-03 08:46:50 -03002079 ret = -ENOMEM;
Jean-Francois Moine8295d992008-09-03 17:12:19 -03002080 goto out;
2081 }
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002082 gspca_dev->dev = dev;
2083 gspca_dev->iface = interface->bInterfaceNumber;
Jean-Francois Moined43fa322008-06-12 10:58:58 -03002084 gspca_dev->nbalt = intf->num_altsetting;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002085 gspca_dev->sd_desc = sd_desc;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002086 gspca_dev->nbufread = 2;
Jean-Francois Moineff374742008-10-23 07:29:51 -03002087 gspca_dev->empty_packet = -1; /* don't check the empty packets */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002088
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03002089 /* configure the subdriver and initialize the USB device */
Jean-Francois Moineba38ee82008-11-22 04:27:34 -03002090 ret = sd_desc->config(gspca_dev, id);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002091 if (ret < 0)
2092 goto out;
Jean-Francois Moineba38ee82008-11-22 04:27:34 -03002093 ret = sd_desc->init(gspca_dev);
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03002094 if (ret < 0)
2095 goto out;
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002096 gspca_set_default_mode(gspca_dev);
2097
2098 mutex_init(&gspca_dev->usb_lock);
2099 mutex_init(&gspca_dev->read_lock);
2100 mutex_init(&gspca_dev->queue_lock);
2101 init_waitqueue_head(&gspca_dev->wq);
2102
2103 /* init video stuff */
Jean-Francois Moineba38ee82008-11-22 04:27:34 -03002104 memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
Hans de Goede24441632009-03-27 16:08:20 -03002105 gspca_dev->vdev.parent = &intf->dev;
Jean-Francois Moine5c4fa002008-11-18 15:52:31 -03002106 gspca_dev->module = module;
Oliver Neukumee56a4d2008-07-27 14:01:59 -03002107 gspca_dev->present = 1;
Jean-Francois Moinea12ca6a2008-11-19 06:37:53 -03002108 ret = video_register_device(&gspca_dev->vdev,
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002109 VFL_TYPE_GRABBER,
Jean-Francois Moine8d584a52009-01-13 06:07:59 -03002110 -1);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002111 if (ret < 0) {
2112 err("video_register_device err %d", ret);
2113 goto out;
2114 }
2115
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002116 usb_set_intfdata(intf, gspca_dev);
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002117 PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev));
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002118 return 0;
2119out:
Jean-Francois Moinee07a1d82008-11-19 06:37:53 -03002120 kfree(gspca_dev->usb_buf);
2121 kfree(gspca_dev);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002122 return ret;
2123}
2124EXPORT_SYMBOL(gspca_dev_probe);
2125
2126/*
2127 * USB disconnection
2128 *
2129 * This function must be called by the sub-driver
2130 * when the device disconnects, after the specific resources are freed.
2131 */
2132void gspca_disconnect(struct usb_interface *intf)
2133{
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -03002134 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002135
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002136 PDEBUG(D_PROBE, "%s disconnect",
2137 video_device_node_name(&gspca_dev->vdev));
Adam Bakerad281272009-02-04 15:33:21 -03002138 mutex_lock(&gspca_dev->usb_lock);
Jean-Francois Moine6e4ae872008-11-22 05:35:49 -03002139 gspca_dev->present = 0;
Jean-Francois Moine090264e2009-02-12 08:05:45 -03002140
2141 if (gspca_dev->streaming) {
2142 destroy_urbs(gspca_dev);
2143 wake_up_interruptible(&gspca_dev->wq);
2144 }
2145
2146 /* the device is freed at exit of this function */
2147 gspca_dev->dev = NULL;
Adam Bakerad281272009-02-04 15:33:21 -03002148 mutex_unlock(&gspca_dev->usb_lock);
Jean-Francois Moine6e4ae872008-11-22 05:35:49 -03002149
Frank Zago6b060ff2008-09-28 08:12:22 -03002150 usb_set_intfdata(intf, NULL);
2151
Jean-Francois Moinea12ca6a2008-11-19 06:37:53 -03002152 /* release the device */
2153 /* (this will call gspca_release() immediatly or on last close) */
2154 video_unregister_device(&gspca_dev->vdev);
Jean-Francois Moine3145b8c2008-10-05 04:22:10 -03002155
Jean-Francois Moine0d07e242009-10-01 13:44:49 -03002156/* PDEBUG(D_PROBE, "disconnect complete"); */
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002157}
2158EXPORT_SYMBOL(gspca_disconnect);
2159
Jean-Francois Moine6a709742008-09-03 16:48:10 -03002160#ifdef CONFIG_PM
2161int gspca_suspend(struct usb_interface *intf, pm_message_t message)
2162{
2163 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
2164
2165 if (!gspca_dev->streaming)
2166 return 0;
2167 gspca_dev->frozen = 1; /* avoid urb error messages */
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03002168 if (gspca_dev->sd_desc->stopN)
2169 gspca_dev->sd_desc->stopN(gspca_dev);
Jean-Francois Moine6a709742008-09-03 16:48:10 -03002170 destroy_urbs(gspca_dev);
2171 gspca_set_alt0(gspca_dev);
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03002172 if (gspca_dev->sd_desc->stop0)
2173 gspca_dev->sd_desc->stop0(gspca_dev);
Jean-Francois Moine6a709742008-09-03 16:48:10 -03002174 return 0;
2175}
2176EXPORT_SYMBOL(gspca_suspend);
2177
2178int gspca_resume(struct usb_interface *intf)
2179{
2180 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
2181
2182 gspca_dev->frozen = 0;
Jean-Francois Moine012d6b02008-09-03 17:12:16 -03002183 gspca_dev->sd_desc->init(gspca_dev);
2184 if (gspca_dev->streaming)
2185 return gspca_init_transfer(gspca_dev);
Jean-Francois Moine1e89e2d2008-09-03 17:12:15 -03002186 return 0;
Jean-Francois Moine6a709742008-09-03 16:48:10 -03002187}
2188EXPORT_SYMBOL(gspca_resume);
2189#endif
Hans de Goededcef3232008-07-10 10:40:53 -03002190/* -- cam driver utility functions -- */
2191
2192/* auto gain and exposure algorithm based on the knee algorithm described here:
2193 http://ytse.tricolour.net/docs/LowLightOptimization.html
2194
2195 Returns 0 if no changes were made, 1 if the gain and or exposure settings
2196 where changed. */
2197int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
2198 int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee)
2199{
2200 int i, steps, gain, orig_gain, exposure, orig_exposure, autogain;
2201 const struct ctrl *gain_ctrl = NULL;
2202 const struct ctrl *exposure_ctrl = NULL;
2203 const struct ctrl *autogain_ctrl = NULL;
2204 int retval = 0;
2205
2206 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
2207 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN)
2208 gain_ctrl = &gspca_dev->sd_desc->ctrls[i];
2209 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE)
2210 exposure_ctrl = &gspca_dev->sd_desc->ctrls[i];
2211 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_AUTOGAIN)
2212 autogain_ctrl = &gspca_dev->sd_desc->ctrls[i];
2213 }
2214 if (!gain_ctrl || !exposure_ctrl || !autogain_ctrl) {
2215 PDEBUG(D_ERR, "Error: gspca_auto_gain_n_exposure called "
2216 "on cam without (auto)gain/exposure");
2217 return 0;
2218 }
2219
2220 if (gain_ctrl->get(gspca_dev, &gain) ||
2221 exposure_ctrl->get(gspca_dev, &exposure) ||
2222 autogain_ctrl->get(gspca_dev, &autogain) || !autogain)
2223 return 0;
2224
2225 orig_gain = gain;
2226 orig_exposure = exposure;
2227
2228 /* If we are of a multiple of deadzone, do multiple steps to reach the
2229 desired lumination fast (with the risc of a slight overshoot) */
2230 steps = abs(desired_avg_lum - avg_lum) / deadzone;
2231
Jean-Francois Moine1c44d812008-11-10 05:56:55 -03002232 PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
Hans de Goededcef3232008-07-10 10:40:53 -03002233 avg_lum, desired_avg_lum, steps);
2234
2235 for (i = 0; i < steps; i++) {
2236 if (avg_lum > desired_avg_lum) {
2237 if (gain > gain_knee)
2238 gain--;
2239 else if (exposure > exposure_knee)
2240 exposure--;
2241 else if (gain > gain_ctrl->qctrl.default_value)
2242 gain--;
2243 else if (exposure > exposure_ctrl->qctrl.minimum)
2244 exposure--;
2245 else if (gain > gain_ctrl->qctrl.minimum)
2246 gain--;
2247 else
2248 break;
2249 } else {
2250 if (gain < gain_ctrl->qctrl.default_value)
2251 gain++;
2252 else if (exposure < exposure_knee)
2253 exposure++;
2254 else if (gain < gain_knee)
2255 gain++;
2256 else if (exposure < exposure_ctrl->qctrl.maximum)
2257 exposure++;
2258 else if (gain < gain_ctrl->qctrl.maximum)
2259 gain++;
2260 else
2261 break;
2262 }
2263 }
2264
2265 if (gain != orig_gain) {
2266 gain_ctrl->set(gspca_dev, gain);
2267 retval = 1;
2268 }
2269 if (exposure != orig_exposure) {
2270 exposure_ctrl->set(gspca_dev, exposure);
2271 retval = 1;
2272 }
2273
2274 return retval;
2275}
2276EXPORT_SYMBOL(gspca_auto_gain_n_exposure);
2277
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002278/* -- module insert / remove -- */
2279static int __init gspca_init(void)
2280{
Jean-Francois Moinebb64e862008-07-19 06:49:28 -03002281 info("main v%d.%d.%d registered",
2282 (DRIVER_VERSION_NUMBER >> 16) & 0xff,
2283 (DRIVER_VERSION_NUMBER >> 8) & 0xff,
2284 DRIVER_VERSION_NUMBER & 0xff);
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002285 return 0;
2286}
2287static void __exit gspca_exit(void)
2288{
2289 info("main deregistered");
2290}
2291
2292module_init(gspca_init);
2293module_exit(gspca_exit);
2294
Jean-Francois Moine335b3f82008-07-30 04:53:02 -03002295#ifdef GSPCA_DEBUG
Jean-Francois Moine63eb9542008-04-12 09:58:09 -03002296module_param_named(debug, gspca_debug, int, 0644);
2297MODULE_PARM_DESC(debug,
2298 "Debug (bit) 0x01:error 0x02:probe 0x04:config"
Jean-Francois Moined43fa322008-06-12 10:58:58 -03002299 " 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout"
2300 " 0x0100: v4l2");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03002301#endif