blob: 333f696e7fcf03d9fcd52852b613d5694906e69e [file] [log] [blame]
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001/*
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03002 * Zoran 364xx based USB webcam module version 0.73
Antoine Jacquetb7eee612007-04-27 12:30:59 -03003 *
4 * Allows you to use your USB webcam with V4L2 applications
5 * This is still in heavy developpement !
6 *
7 * Copyright (C) 2004 Antoine Jacquet <royale@zerezo.com>
8 * http://royale.zerezo.com/zr364xx/
9 *
10 * Heavily inspired by usb-skeleton.c, vicam.c, cpia.c and spca50x.c drivers
11 * V4L2 version inspired by meye.c driver
12 *
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030013 * Some video buffer code by Lamarque based on s2255drv.c and vivi.c drivers.
14 *
Antoine Jacquetb7eee612007-04-27 12:30:59 -030015 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30
Antoine Jacquetb7eee612007-04-27 12:30:59 -030031#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/usb.h>
34#include <linux/vmalloc.h>
35#include <linux/slab.h>
36#include <linux/proc_fs.h>
Antoine Jacquet2575f842007-03-05 06:32:29 -030037#include <linux/highmem.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030038#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030039#include <media/v4l2-ioctl.h>
Hans Verkuila906f622012-06-02 07:16:49 -030040#include <media/v4l2-device.h>
Hans Verkuil1fc21a12012-06-02 07:44:15 -030041#include <media/v4l2-ctrls.h>
Hans Verkuil5d317ab2012-06-02 07:57:29 -030042#include <media/v4l2-fh.h>
43#include <media/v4l2-event.h>
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030044#include <media/videobuf-vmalloc.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030045
46
47/* Version Information */
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030048#define DRIVER_VERSION "0.7.4"
Antoine Jacquetb7eee612007-04-27 12:30:59 -030049#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
50#define DRIVER_DESC "Zoran 364xx"
51
52
53/* Camera */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030054#define FRAMES 1
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -030055#define MAX_FRAME_SIZE 200000
Antoine Jacquetb7eee612007-04-27 12:30:59 -030056#define BUFFER_SIZE 0x1000
57#define CTRL_TIMEOUT 500
58
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030059#define ZR364XX_DEF_BUFS 4
60#define ZR364XX_READ_IDLE 0
61#define ZR364XX_READ_FRAME 1
Antoine Jacquetb7eee612007-04-27 12:30:59 -030062
63/* Debug macro */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030064#define DBG(fmt, args...) \
65 do { \
66 if (debug) { \
67 printk(KERN_INFO KBUILD_MODNAME " " fmt, ##args); \
68 } \
69 } while (0)
Antoine Jacquetb7eee612007-04-27 12:30:59 -030070
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -030071/*#define FULL_DEBUG 1*/
72#ifdef FULL_DEBUG
73#define _DBG DBG
74#else
75#define _DBG(fmt, args...)
76#endif
77
Antoine Jacquetb7eee612007-04-27 12:30:59 -030078/* Init methods, need to find nicer names for these
79 * the exact names of the chipsets would be the best if someone finds it */
80#define METHOD0 0
81#define METHOD1 1
82#define METHOD2 2
Antoine Jacquet08135ba2009-12-27 18:22:05 -030083#define METHOD3 3
Antoine Jacquetb7eee612007-04-27 12:30:59 -030084
85
86/* Module parameters */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030087static int debug;
88static int mode;
Antoine Jacquetb7eee612007-04-27 12:30:59 -030089
90
91/* Module parameters interface */
92module_param(debug, int, 0644);
93MODULE_PARM_DESC(debug, "Debug level");
94module_param(mode, int, 0644);
95MODULE_PARM_DESC(mode, "0 = 320x240, 1 = 160x120, 2 = 640x480");
96
97
98/* Devices supported by this driver
99 * .driver_info contains the init method used by the camera */
100static struct usb_device_id device_table[] = {
101 {USB_DEVICE(0x08ca, 0x0109), .driver_info = METHOD0 },
102 {USB_DEVICE(0x041e, 0x4024), .driver_info = METHOD0 },
103 {USB_DEVICE(0x0d64, 0x0108), .driver_info = METHOD0 },
104 {USB_DEVICE(0x0546, 0x3187), .driver_info = METHOD0 },
105 {USB_DEVICE(0x0d64, 0x3108), .driver_info = METHOD0 },
106 {USB_DEVICE(0x0595, 0x4343), .driver_info = METHOD0 },
107 {USB_DEVICE(0x0bb0, 0x500d), .driver_info = METHOD0 },
108 {USB_DEVICE(0x0feb, 0x2004), .driver_info = METHOD0 },
109 {USB_DEVICE(0x055f, 0xb500), .driver_info = METHOD0 },
110 {USB_DEVICE(0x08ca, 0x2062), .driver_info = METHOD2 },
111 {USB_DEVICE(0x052b, 0x1a18), .driver_info = METHOD1 },
112 {USB_DEVICE(0x04c8, 0x0729), .driver_info = METHOD0 },
113 {USB_DEVICE(0x04f2, 0xa208), .driver_info = METHOD0 },
114 {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 },
115 {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
116 {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
Antoine Jacquetbebeaea2007-06-25 16:00:34 -0300117 {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
Antoine Jacquet71c04472008-01-25 22:01:53 -0300118 {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
Antoine Jacquetc0e0aff2008-01-25 22:03:10 -0300119 {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300120 {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD3 },
Antoine Jacquet9018f6c2009-11-19 22:35:38 -0300121 {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 },
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300122 {} /* Terminating entry */
123};
124
125MODULE_DEVICE_TABLE(usb, device_table);
126
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300127/* frame structure */
128struct zr364xx_framei {
129 unsigned long ulState; /* ulState:ZR364XX_READ_IDLE,
130 ZR364XX_READ_FRAME */
131 void *lpvbits; /* image data */
132 unsigned long cur_size; /* current data copied to it */
133};
134
135/* image buffer structure */
136struct zr364xx_bufferi {
137 unsigned long dwFrames; /* number of frames in buffer */
138 struct zr364xx_framei frame[FRAMES]; /* array of FRAME structures */
139};
140
141struct zr364xx_dmaqueue {
142 struct list_head active;
143 struct zr364xx_camera *cam;
144};
145
146struct zr364xx_pipeinfo {
147 u32 transfer_size;
148 u8 *transfer_buffer;
149 u32 state;
150 void *stream_urb;
151 void *cam; /* back pointer to zr364xx_camera struct */
152 u32 err_count;
153 u32 idx;
154};
155
156struct zr364xx_fmt {
157 char *name;
158 u32 fourcc;
159 int depth;
160};
161
162/* image formats. */
163static const struct zr364xx_fmt formats[] = {
164 {
165 .name = "JPG",
166 .fourcc = V4L2_PIX_FMT_JPEG,
167 .depth = 24
168 }
169};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300170
171/* Camera stuff */
172struct zr364xx_camera {
173 struct usb_device *udev; /* save off the usb device pointer */
174 struct usb_interface *interface;/* the interface for this device */
Hans Verkuila906f622012-06-02 07:16:49 -0300175 struct v4l2_device v4l2_dev;
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300176 struct v4l2_ctrl_handler ctrl_handler;
Hans Verkuil2b992512012-06-02 06:32:48 -0300177 struct video_device vdev; /* v4l video device */
Hans Verkuila0657292012-06-02 08:50:31 -0300178 struct v4l2_fh *owner; /* owns the streaming */
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300179 int nb;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300180 struct zr364xx_bufferi buffer;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300181 int skip;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300182 int width;
183 int height;
184 int method;
185 struct mutex lock;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300186
187 spinlock_t slock;
188 struct zr364xx_dmaqueue vidq;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300189 int last_frame;
190 int cur_frame;
191 unsigned long frame_count;
192 int b_acquire;
193 struct zr364xx_pipeinfo pipe[1];
194
195 u8 read_endpoint;
196
197 const struct zr364xx_fmt *fmt;
198 struct videobuf_queue vb_vidq;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300199};
200
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300201/* buffer for one video frame */
202struct zr364xx_buffer {
203 /* common v4l buffer stuff -- must be first */
204 struct videobuf_buffer vb;
205 const struct zr364xx_fmt *fmt;
206};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300207
208/* function used to send initialisation commands to the camera */
209static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
210 u16 index, unsigned char *cp, u16 size)
211{
212 int status;
213
214 unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
215 if (!transfer_buffer) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300216 dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300217 return -ENOMEM;
218 }
219
220 memcpy(transfer_buffer, cp, size);
221
222 status = usb_control_msg(udev,
223 usb_sndctrlpipe(udev, 0),
224 request,
225 USB_DIR_OUT | USB_TYPE_VENDOR |
226 USB_RECIP_DEVICE, value, index,
227 transfer_buffer, size, CTRL_TIMEOUT);
228
229 kfree(transfer_buffer);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300230 return status;
231}
232
233
234/* Control messages sent to the camera to initialize it
235 * and launch the capture */
236typedef struct {
237 unsigned int value;
238 unsigned int size;
239 unsigned char *bytes;
240} message;
241
242/* method 0 */
243static unsigned char m0d1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
244static unsigned char m0d2[] = { 0, 0, 0, 0, 0, 0 };
245static unsigned char m0d3[] = { 0, 0 };
246static message m0[] = {
247 {0x1f30, 0, NULL},
248 {0xd000, 0, NULL},
249 {0x3370, sizeof(m0d1), m0d1},
250 {0x2000, 0, NULL},
251 {0x2f0f, 0, NULL},
252 {0x2610, sizeof(m0d2), m0d2},
253 {0xe107, 0, NULL},
254 {0x2502, 0, NULL},
255 {0x1f70, 0, NULL},
256 {0xd000, 0, NULL},
257 {0x9a01, sizeof(m0d3), m0d3},
258 {-1, -1, NULL}
259};
260
261/* method 1 */
262static unsigned char m1d1[] = { 0xff, 0xff };
263static unsigned char m1d2[] = { 0x00, 0x00 };
264static message m1[] = {
265 {0x1f30, 0, NULL},
266 {0xd000, 0, NULL},
267 {0xf000, 0, NULL},
268 {0x2000, 0, NULL},
269 {0x2f0f, 0, NULL},
270 {0x2650, 0, NULL},
271 {0xe107, 0, NULL},
272 {0x2502, sizeof(m1d1), m1d1},
273 {0x1f70, 0, NULL},
274 {0xd000, 0, NULL},
275 {0xd000, 0, NULL},
276 {0xd000, 0, NULL},
277 {0x9a01, sizeof(m1d2), m1d2},
278 {-1, -1, NULL}
279};
280
281/* method 2 */
282static unsigned char m2d1[] = { 0xff, 0xff };
283static message m2[] = {
284 {0x1f30, 0, NULL},
285 {0xf000, 0, NULL},
286 {0x2000, 0, NULL},
287 {0x2f0f, 0, NULL},
288 {0x2650, 0, NULL},
289 {0xe107, 0, NULL},
290 {0x2502, sizeof(m2d1), m2d1},
291 {0x1f70, 0, NULL},
292 {-1, -1, NULL}
293};
294
295/* init table */
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300296static message *init[4] = { m0, m1, m2, m2 };
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300297
298
299/* JPEG static data in header (Huffman table, etc) */
300static unsigned char header1[] = {
301 0xFF, 0xD8,
302 /*
303 0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F',
304 0x00, 0x01, 0x01, 0x00, 0x33, 0x8A, 0x00, 0x00, 0x33, 0x88,
305 */
306 0xFF, 0xDB, 0x00, 0x84
307};
308static unsigned char header2[] = {
309 0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
310 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
312 0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
313 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
314 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
315 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
316 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33,
317 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25,
318 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
319 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,
320 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
321 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
322 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
323 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
324 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
325 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
326 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
327 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
328 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC4, 0x00, 0x1F,
329 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
330 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
331 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0xC4, 0x00, 0xB5,
332 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
333 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,
334 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
335 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
336 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
337 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27,
338 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
339 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57,
340 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
341 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84,
342 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
343 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
344 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
345 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
346 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,
347 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
348 0xF8, 0xF9, 0xFA, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01,
349 0x40, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
350 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
351 0x00, 0x3F, 0x00
352};
353static unsigned char header3;
354
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300355/* ------------------------------------------------------------------
356 Videobuf operations
357 ------------------------------------------------------------------*/
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300358
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300359static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
360 unsigned int *size)
361{
362 struct zr364xx_camera *cam = vq->priv_data;
363
364 *size = cam->width * cam->height * (cam->fmt->depth >> 3);
365
366 if (*count == 0)
367 *count = ZR364XX_DEF_BUFS;
368
Andreas Bombedab7e312010-03-21 16:02:45 -0300369 if (*size * *count > ZR364XX_DEF_BUFS * 1024 * 1024)
370 *count = (ZR364XX_DEF_BUFS * 1024 * 1024) / *size;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300371
372 return 0;
373}
374
375static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf)
376{
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300377 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300378
379 if (in_interrupt())
380 BUG();
381
382 videobuf_vmalloc_free(&buf->vb);
383 buf->vb.state = VIDEOBUF_NEEDS_INIT;
384}
385
386static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
387 enum v4l2_field field)
388{
389 struct zr364xx_camera *cam = vq->priv_data;
390 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
391 vb);
392 int rc;
393
394 DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ?
395 cam->fmt->name : "");
396 if (cam->fmt == NULL)
397 return -EINVAL;
398
399 buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3);
400
401 if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) {
402 DBG("invalid buffer prepare\n");
403 return -EINVAL;
404 }
405
406 buf->fmt = cam->fmt;
407 buf->vb.width = cam->width;
408 buf->vb.height = cam->height;
409 buf->vb.field = field;
410
411 if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
412 rc = videobuf_iolock(vq, &buf->vb, NULL);
413 if (rc < 0)
414 goto fail;
415 }
416
417 buf->vb.state = VIDEOBUF_PREPARED;
418 return 0;
419fail:
420 free_buffer(vq, buf);
421 return rc;
422}
423
424static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
425{
426 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
427 vb);
428 struct zr364xx_camera *cam = vq->priv_data;
429
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300430 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300431
432 buf->vb.state = VIDEOBUF_QUEUED;
433 list_add_tail(&buf->vb.queue, &cam->vidq.active);
434}
435
436static void buffer_release(struct videobuf_queue *vq,
437 struct videobuf_buffer *vb)
438{
439 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
440 vb);
441
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300442 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300443 free_buffer(vq, buf);
444}
445
446static struct videobuf_queue_ops zr364xx_video_qops = {
447 .buf_setup = buffer_setup,
448 .buf_prepare = buffer_prepare,
449 .buf_queue = buffer_queue,
450 .buf_release = buffer_release,
451};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300452
453/********************/
454/* V4L2 integration */
455/********************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300456static int zr364xx_vidioc_streamon(struct file *file, void *priv,
457 enum v4l2_buf_type type);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300458
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300459static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300460 loff_t * ppos)
461{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300462 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila906f622012-06-02 07:16:49 -0300463 int err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300464
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300465 _DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300466
467 if (!buf)
468 return -EINVAL;
469
470 if (!count)
471 return -EINVAL;
472
Hans Verkuila906f622012-06-02 07:16:49 -0300473 if (mutex_lock_interruptible(&cam->lock))
474 return -ERESTARTSYS;
475
Hans Verkuila0657292012-06-02 08:50:31 -0300476 err = zr364xx_vidioc_streamon(file, file->private_data,
477 V4L2_BUF_TYPE_VIDEO_CAPTURE);
478 if (err == 0) {
479 DBG("%s: reading %d bytes at pos %d.\n", __func__,
480 (int) count, (int) *ppos);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300481
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300482 /* NoMan Sux ! */
Hans Verkuila906f622012-06-02 07:16:49 -0300483 err = videobuf_read_one(&cam->vb_vidq, buf, count, ppos,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300484 file->f_flags & O_NONBLOCK);
485 }
Hans Verkuila906f622012-06-02 07:16:49 -0300486 mutex_unlock(&cam->lock);
487 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300488}
489
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300490/* video buffer vmalloc implementation based partly on VIVI driver which is
491 * Copyright (c) 2006 by
492 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
493 * Ted Walther <ted--a.t--enumera.com>
494 * John Sokol <sokol--a.t--videotechnology.com>
495 * http://v4l.videotechnology.com/
496 *
497 */
498static void zr364xx_fillbuff(struct zr364xx_camera *cam,
499 struct zr364xx_buffer *buf,
500 int jpgsize)
501{
502 int pos = 0;
503 struct timeval ts;
504 const char *tmpbuf;
505 char *vbuf = videobuf_to_vmalloc(&buf->vb);
506 unsigned long last_frame;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300507
508 if (!vbuf)
509 return;
510
511 last_frame = cam->last_frame;
512 if (last_frame != -1) {
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300513 tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits;
514 switch (buf->fmt->fourcc) {
515 case V4L2_PIX_FMT_JPEG:
516 buf->vb.size = jpgsize;
517 memcpy(vbuf, tmpbuf, buf->vb.size);
518 break;
519 default:
520 printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n");
521 }
522 cam->last_frame = -1;
523 } else {
524 printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n");
525 return;
526 }
527 DBG("%s: Buffer 0x%08lx size= %d\n", __func__,
528 (unsigned long)vbuf, pos);
529 /* tell v4l buffer was filled */
530
531 buf->vb.field_count = cam->frame_count * 2;
532 do_gettimeofday(&ts);
533 buf->vb.ts = ts;
534 buf->vb.state = VIDEOBUF_DONE;
535}
536
537static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize)
538{
539 struct zr364xx_dmaqueue *dma_q = &cam->vidq;
540 struct zr364xx_buffer *buf;
541 unsigned long flags = 0;
542 int rc = 0;
543
544 DBG("wakeup: %p\n", &dma_q);
545 spin_lock_irqsave(&cam->slock, flags);
546
547 if (list_empty(&dma_q->active)) {
548 DBG("No active queue to serve\n");
549 rc = -1;
550 goto unlock;
551 }
552 buf = list_entry(dma_q->active.next,
553 struct zr364xx_buffer, vb.queue);
554
555 if (!waitqueue_active(&buf->vb.done)) {
556 /* no one active */
557 rc = -1;
558 goto unlock;
559 }
560 list_del(&buf->vb.queue);
561 do_gettimeofday(&buf->vb.ts);
562 DBG("[%p/%d] wakeup\n", buf, buf->vb.i);
563 zr364xx_fillbuff(cam, buf, jpgsize);
564 wake_up(&buf->vb.done);
565 DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
566unlock:
567 spin_unlock_irqrestore(&cam->slock, flags);
Julia Lawall30538142010-08-16 13:27:47 -0300568 return rc;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300569}
570
571/* this function moves the usb stream read pipe data
572 * into the system buffers.
573 * returns 0 on success, EAGAIN if more data to process (call this
574 * function again).
575 */
576static int zr364xx_read_video_callback(struct zr364xx_camera *cam,
577 struct zr364xx_pipeinfo *pipe_info,
578 struct urb *purb)
579{
580 unsigned char *pdest;
581 unsigned char *psrc;
582 s32 idx = -1;
583 struct zr364xx_framei *frm;
584 int i = 0;
585 unsigned char *ptr = NULL;
586
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300587 _DBG("buffer to user\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300588 idx = cam->cur_frame;
589 frm = &cam->buffer.frame[idx];
590
591 /* swap bytes if camera needs it */
592 if (cam->method == METHOD0) {
593 u16 *buf = (u16 *)pipe_info->transfer_buffer;
594 for (i = 0; i < purb->actual_length/2; i++)
595 swab16s(buf + i);
596 }
597
598 /* search done. now find out if should be acquiring */
599 if (!cam->b_acquire) {
600 /* we found a frame, but this channel is turned off */
601 frm->ulState = ZR364XX_READ_IDLE;
602 return -EINVAL;
603 }
604
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300605 psrc = (u8 *)pipe_info->transfer_buffer;
606 ptr = pdest = frm->lpvbits;
607
608 if (frm->ulState == ZR364XX_READ_IDLE) {
609 frm->ulState = ZR364XX_READ_FRAME;
610 frm->cur_size = 0;
611
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300612 _DBG("jpeg header, ");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300613 memcpy(ptr, header1, sizeof(header1));
614 ptr += sizeof(header1);
615 header3 = 0;
616 memcpy(ptr, &header3, 1);
617 ptr++;
618 memcpy(ptr, psrc, 64);
619 ptr += 64;
620 header3 = 1;
621 memcpy(ptr, &header3, 1);
622 ptr++;
623 memcpy(ptr, psrc + 64, 64);
624 ptr += 64;
625 memcpy(ptr, header2, sizeof(header2));
626 ptr += sizeof(header2);
627 memcpy(ptr, psrc + 128,
628 purb->actual_length - 128);
629 ptr += purb->actual_length - 128;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300630 _DBG("header : %d %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300631 psrc[0], psrc[1], psrc[2],
632 psrc[3], psrc[4], psrc[5],
633 psrc[6], psrc[7], psrc[8]);
634 frm->cur_size = ptr - pdest;
635 } else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300636 if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) {
637 dev_info(&cam->udev->dev,
638 "%s: buffer (%d bytes) too small to hold "
639 "frame data. Discarding frame data.\n",
640 __func__, MAX_FRAME_SIZE);
641 } else {
642 pdest += frm->cur_size;
643 memcpy(pdest, psrc, purb->actual_length);
644 frm->cur_size += purb->actual_length;
645 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300646 }
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300647 /*_DBG("cur_size %lu urb size %d\n", frm->cur_size,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300648 purb->actual_length);*/
649
650 if (purb->actual_length < pipe_info->transfer_size) {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300651 _DBG("****************Buffer[%d]full*************\n", idx);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300652 cam->last_frame = cam->cur_frame;
653 cam->cur_frame++;
654 /* end of system frame ring buffer, start at zero */
655 if (cam->cur_frame == cam->buffer.dwFrames)
656 cam->cur_frame = 0;
657
658 /* frame ready */
659 /* go back to find the JPEG EOI marker */
660 ptr = pdest = frm->lpvbits;
661 ptr += frm->cur_size - 2;
662 while (ptr > pdest) {
663 if (*ptr == 0xFF && *(ptr + 1) == 0xD9
664 && *(ptr + 2) == 0xFF)
665 break;
666 ptr--;
667 }
668 if (ptr == pdest)
669 DBG("No EOI marker\n");
670
671 /* Sometimes there is junk data in the middle of the picture,
672 * we want to skip this bogus frames */
673 while (ptr > pdest) {
674 if (*ptr == 0xFF && *(ptr + 1) == 0xFF
675 && *(ptr + 2) == 0xFF)
676 break;
677 ptr--;
678 }
679 if (ptr != pdest) {
680 DBG("Bogus frame ? %d\n", ++(cam->nb));
681 } else if (cam->b_acquire) {
682 /* we skip the 2 first frames which are usually buggy */
683 if (cam->skip)
684 cam->skip--;
685 else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300686 _DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300687 frm->cur_size,
688 pdest[0], pdest[1], pdest[2], pdest[3],
689 pdest[4], pdest[5], pdest[6], pdest[7]);
690
691 zr364xx_got_frame(cam, frm->cur_size);
692 }
693 }
694 cam->frame_count++;
695 frm->ulState = ZR364XX_READ_IDLE;
696 frm->cur_size = 0;
697 }
698 /* done successfully */
699 return 0;
700}
701
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300702static int zr364xx_vidioc_querycap(struct file *file, void *priv,
703 struct v4l2_capability *cap)
704{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300705 struct zr364xx_camera *cam = video_drvdata(file);
706
707 strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
708 strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
709 strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
710 sizeof(cap->bus_info));
Hans Verkuildf462902012-06-02 07:50:30 -0300711 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300712 V4L2_CAP_READWRITE |
713 V4L2_CAP_STREAMING;
Hans Verkuildf462902012-06-02 07:50:30 -0300714 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300715
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300716 return 0;
717}
718
719static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
720 struct v4l2_input *i)
721{
722 if (i->index != 0)
723 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300724 strcpy(i->name, DRIVER_DESC " Camera");
725 i->type = V4L2_INPUT_TYPE_CAMERA;
726 return 0;
727}
728
729static int zr364xx_vidioc_g_input(struct file *file, void *priv,
730 unsigned int *i)
731{
732 *i = 0;
733 return 0;
734}
735
736static int zr364xx_vidioc_s_input(struct file *file, void *priv,
737 unsigned int i)
738{
739 if (i != 0)
740 return -EINVAL;
741 return 0;
742}
743
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300744static int zr364xx_s_ctrl(struct v4l2_ctrl *ctrl)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300745{
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300746 struct zr364xx_camera *cam =
747 container_of(ctrl->handler, struct zr364xx_camera, ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300748 int temp;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300749
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300750 switch (ctrl->id) {
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300751 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300752 /* hardware brightness */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300753 send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300754 temp = (0x60 << 8) + 127 - ctrl->val;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300755 send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300756 break;
757 default:
758 return -EINVAL;
759 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300760
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300761 return 0;
762}
763
Hans Verkuil78b526a2008-05-28 12:16:41 -0300764static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300765 void *priv, struct v4l2_fmtdesc *f)
766{
767 if (f->index > 0)
768 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300769 f->flags = V4L2_FMT_FLAG_COMPRESSED;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300770 strcpy(f->description, formats[0].name);
771 f->pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300772 return 0;
773}
774
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300775static char *decode_fourcc(__u32 pixelformat, char *buf)
776{
777 buf[0] = pixelformat & 0xff;
778 buf[1] = (pixelformat >> 8) & 0xff;
779 buf[2] = (pixelformat >> 16) & 0xff;
780 buf[3] = (pixelformat >> 24) & 0xff;
781 buf[4] = '\0';
782 return buf;
783}
784
Hans Verkuil78b526a2008-05-28 12:16:41 -0300785static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300786 struct v4l2_format *f)
787{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300788 struct zr364xx_camera *cam = video_drvdata(file);
789 char pixelformat_name[5];
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300790
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300791 if (cam == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300792 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300793
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300794 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
795 DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__,
796 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name));
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300797 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300798 }
799
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300800 if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) &&
801 !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) {
802 f->fmt.pix.width = 320;
803 f->fmt.pix.height = 240;
804 }
805
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300806 f->fmt.pix.field = V4L2_FIELD_NONE;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300807 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
808 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300809 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300810 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300811 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
812 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
813 f->fmt.pix.field);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300814 return 0;
815}
816
Hans Verkuil78b526a2008-05-28 12:16:41 -0300817static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300818 struct v4l2_format *f)
819{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300820 struct zr364xx_camera *cam;
821
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300822 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300823 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300824 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300825
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300826 f->fmt.pix.pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300827 f->fmt.pix.field = V4L2_FIELD_NONE;
828 f->fmt.pix.width = cam->width;
829 f->fmt.pix.height = cam->height;
830 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
831 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300832 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300833 f->fmt.pix.priv = 0;
834 return 0;
835}
836
Hans Verkuil78b526a2008-05-28 12:16:41 -0300837static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300838 struct v4l2_format *f)
839{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300840 struct zr364xx_camera *cam = video_drvdata(file);
841 struct videobuf_queue *q = &cam->vb_vidq;
842 char pixelformat_name[5];
843 int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f);
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300844 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300845
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300846 if (ret < 0)
847 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300848
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300849 mutex_lock(&q->vb_lock);
850
851 if (videobuf_queue_is_busy(&cam->vb_vidq)) {
852 DBG("%s queue busy\n", __func__);
853 ret = -EBUSY;
854 goto out;
855 }
856
Hans Verkuila0657292012-06-02 08:50:31 -0300857 if (cam->owner) {
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300858 DBG("%s can't change format after started\n", __func__);
859 ret = -EBUSY;
860 goto out;
861 }
862
863 cam->width = f->fmt.pix.width;
864 cam->height = f->fmt.pix.height;
Hans Verkuila0657292012-06-02 08:50:31 -0300865 DBG("%s: %dx%d mode selected\n", __func__,
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300866 cam->width, cam->height);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300867 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
868 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300869 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300870 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300871 cam->vb_vidq.field = f->fmt.pix.field;
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300872
873 if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
874 mode = 1;
875 else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480)
876 mode = 2;
877 else
878 mode = 0;
879
880 m0d1[0] = mode;
881 m1[2].value = 0xf000 + mode;
882 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300883
884 /* special case for METHOD3, the modes are different */
885 if (cam->method == METHOD3) {
886 switch (mode) {
887 case 1:
888 m2[1].value = 0xf000 + 4;
889 break;
890 case 2:
891 m2[1].value = 0xf000 + 0;
892 break;
893 default:
894 m2[1].value = 0xf000 + 1;
895 break;
896 }
897 }
898
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300899 header2[437] = cam->height / 256;
900 header2[438] = cam->height % 256;
901 header2[439] = cam->width / 256;
902 header2[440] = cam->width % 256;
903
904 for (i = 0; init[cam->method][i].size != -1; i++) {
905 ret =
906 send_control_msg(cam->udev, 1, init[cam->method][i].value,
907 0, init[cam->method][i].bytes,
908 init[cam->method][i].size);
909 if (ret < 0) {
910 dev_err(&cam->udev->dev,
911 "error during resolution change sequence: %d\n", i);
912 goto out;
913 }
914 }
915
916 /* Added some delay here, since opening/closing the camera quickly,
917 * like Ekiga does during its startup, can crash the webcam
918 */
919 mdelay(100);
920 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300921 ret = 0;
922
923out:
924 mutex_unlock(&q->vb_lock);
925
926 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
927 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
928 f->fmt.pix.field);
929 return ret;
930}
931
932static int zr364xx_vidioc_reqbufs(struct file *file, void *priv,
933 struct v4l2_requestbuffers *p)
934{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300935 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila0657292012-06-02 08:50:31 -0300936
937 if (cam->owner && cam->owner != priv)
938 return -EBUSY;
939 return videobuf_reqbufs(&cam->vb_vidq, p);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300940}
941
942static int zr364xx_vidioc_querybuf(struct file *file,
943 void *priv,
944 struct v4l2_buffer *p)
945{
946 int rc;
947 struct zr364xx_camera *cam = video_drvdata(file);
948 rc = videobuf_querybuf(&cam->vb_vidq, p);
949 return rc;
950}
951
952static int zr364xx_vidioc_qbuf(struct file *file,
953 void *priv,
954 struct v4l2_buffer *p)
955{
956 int rc;
957 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300958 _DBG("%s\n", __func__);
Hans Verkuila0657292012-06-02 08:50:31 -0300959 if (cam->owner && cam->owner != priv)
960 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300961 rc = videobuf_qbuf(&cam->vb_vidq, p);
962 return rc;
963}
964
965static int zr364xx_vidioc_dqbuf(struct file *file,
966 void *priv,
967 struct v4l2_buffer *p)
968{
969 int rc;
970 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300971 _DBG("%s\n", __func__);
Hans Verkuila0657292012-06-02 08:50:31 -0300972 if (cam->owner && cam->owner != priv)
973 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300974 rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK);
975 return rc;
976}
977
978static void read_pipe_completion(struct urb *purb)
979{
980 struct zr364xx_pipeinfo *pipe_info;
981 struct zr364xx_camera *cam;
982 int pipe;
983
984 pipe_info = purb->context;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300985 _DBG("%s %p, status %d\n", __func__, purb, purb->status);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300986 if (pipe_info == NULL) {
987 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
988 return;
989 }
990
991 cam = pipe_info->cam;
992 if (cam == NULL) {
993 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
994 return;
995 }
996
997 /* if shutting down, do not resubmit, exit immediately */
998 if (purb->status == -ESHUTDOWN) {
999 DBG("%s, err shutdown\n", __func__);
1000 pipe_info->err_count++;
1001 return;
1002 }
1003
1004 if (pipe_info->state == 0) {
1005 DBG("exiting USB pipe\n");
1006 return;
1007 }
1008
1009 if (purb->actual_length < 0 ||
1010 purb->actual_length > pipe_info->transfer_size) {
1011 dev_err(&cam->udev->dev, "wrong number of bytes\n");
1012 return;
1013 }
1014
1015 if (purb->status == 0)
1016 zr364xx_read_video_callback(cam, pipe_info, purb);
1017 else {
1018 pipe_info->err_count++;
1019 DBG("%s: failed URB %d\n", __func__, purb->status);
1020 }
1021
1022 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1023
1024 /* reuse urb */
1025 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1026 pipe,
1027 pipe_info->transfer_buffer,
1028 pipe_info->transfer_size,
1029 read_pipe_completion, pipe_info);
1030
1031 if (pipe_info->state != 0) {
1032 purb->status = usb_submit_urb(pipe_info->stream_urb,
1033 GFP_ATOMIC);
1034
1035 if (purb->status)
1036 dev_err(&cam->udev->dev,
1037 "error submitting urb (error=%i)\n",
1038 purb->status);
1039 } else
1040 DBG("read pipe complete state 0\n");
1041}
1042
1043static int zr364xx_start_readpipe(struct zr364xx_camera *cam)
1044{
1045 int pipe;
1046 int retval;
1047 struct zr364xx_pipeinfo *pipe_info = cam->pipe;
1048 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1049 DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint);
1050
1051 pipe_info->state = 1;
1052 pipe_info->err_count = 0;
1053 pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
1054 if (!pipe_info->stream_urb) {
1055 dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n");
1056 return -ENOMEM;
1057 }
1058 /* transfer buffer allocated in board_init */
1059 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1060 pipe,
1061 pipe_info->transfer_buffer,
1062 pipe_info->transfer_size,
1063 read_pipe_completion, pipe_info);
1064
1065 DBG("submitting URB %p\n", pipe_info->stream_urb);
1066 retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
1067 if (retval) {
1068 printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n");
1069 return retval;
1070 }
1071
1072 return 0;
1073}
1074
1075static void zr364xx_stop_readpipe(struct zr364xx_camera *cam)
1076{
1077 struct zr364xx_pipeinfo *pipe_info;
1078
1079 if (cam == NULL) {
1080 printk(KERN_ERR KBUILD_MODNAME ": invalid device\n");
1081 return;
1082 }
1083 DBG("stop read pipe\n");
1084 pipe_info = cam->pipe;
1085 if (pipe_info) {
1086 if (pipe_info->state != 0)
1087 pipe_info->state = 0;
1088
1089 if (pipe_info->stream_urb) {
1090 /* cancel urb */
1091 usb_kill_urb(pipe_info->stream_urb);
1092 usb_free_urb(pipe_info->stream_urb);
1093 pipe_info->stream_urb = NULL;
1094 }
1095 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001096 return;
1097}
1098
1099/* starts acquisition process */
1100static int zr364xx_start_acquire(struct zr364xx_camera *cam)
1101{
1102 int j;
1103
1104 DBG("start acquire\n");
1105
1106 cam->last_frame = -1;
1107 cam->cur_frame = 0;
1108 for (j = 0; j < FRAMES; j++) {
1109 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1110 cam->buffer.frame[j].cur_size = 0;
1111 }
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -03001112 cam->b_acquire = 1;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001113 return 0;
1114}
1115
1116static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam)
1117{
1118 cam->b_acquire = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001119 return 0;
1120}
1121
1122static int zr364xx_vidioc_streamon(struct file *file, void *priv,
1123 enum v4l2_buf_type type)
1124{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001125 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila0657292012-06-02 08:50:31 -03001126 int i, j;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001127 int res;
1128
1129 DBG("%s\n", __func__);
1130
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001131 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001132 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001133
Hans Verkuila0657292012-06-02 08:50:31 -03001134 if (cam->owner && cam->owner != priv)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001135 return -EBUSY;
Hans Verkuila0657292012-06-02 08:50:31 -03001136
1137 for (i = 0; init[cam->method][i].size != -1; i++) {
1138 res = send_control_msg(cam->udev, 1, init[cam->method][i].value,
1139 0, init[cam->method][i].bytes,
1140 init[cam->method][i].size);
1141 if (res < 0) {
1142 dev_err(&cam->udev->dev,
1143 "error during open sequence: %d\n", i);
1144 return res;
1145 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001146 }
1147
Hans Verkuila0657292012-06-02 08:50:31 -03001148 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001149 cam->last_frame = -1;
1150 cam->cur_frame = 0;
1151 cam->frame_count = 0;
1152 for (j = 0; j < FRAMES; j++) {
1153 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1154 cam->buffer.frame[j].cur_size = 0;
1155 }
1156 res = videobuf_streamon(&cam->vb_vidq);
1157 if (res == 0) {
1158 zr364xx_start_acquire(cam);
Hans Verkuila0657292012-06-02 08:50:31 -03001159 cam->owner = file->private_data;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001160 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001161 return res;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001162}
1163
1164static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
1165 enum v4l2_buf_type type)
1166{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001167 struct zr364xx_camera *cam = video_drvdata(file);
1168
1169 DBG("%s\n", __func__);
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001170 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001171 return -EINVAL;
Hans Verkuila0657292012-06-02 08:50:31 -03001172 if (cam->owner && cam->owner != priv)
1173 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001174 zr364xx_stop_acquire(cam);
Hans Verkuila0657292012-06-02 08:50:31 -03001175 return videobuf_streamoff(&cam->vb_vidq);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001176}
1177
1178
1179/* open the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -03001180static int zr364xx_open(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001181{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001182 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila0657292012-06-02 08:50:31 -03001183 int err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001184
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001185 DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001186
Hans Verkuila906f622012-06-02 07:16:49 -03001187 if (mutex_lock_interruptible(&cam->lock))
1188 return -ERESTARTSYS;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001189
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001190 err = v4l2_fh_open(file);
1191 if (err)
1192 goto out;
1193
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001194 /* Added some delay here, since opening/closing the camera quickly,
1195 * like Ekiga does during its startup, can crash the webcam
1196 */
1197 mdelay(100);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001198 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001199
Antoine Jacquet69025c92008-08-18 17:09:53 -03001200out:
Hans Verkuila906f622012-06-02 07:16:49 -03001201 mutex_unlock(&cam->lock);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001202 DBG("%s: %d\n", __func__, err);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001203 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001204}
1205
Hans Verkuila906f622012-06-02 07:16:49 -03001206static void zr364xx_release(struct v4l2_device *v4l2_dev)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001207{
Hans Verkuila906f622012-06-02 07:16:49 -03001208 struct zr364xx_camera *cam =
1209 container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001210 unsigned long i;
1211
Hans Verkuila906f622012-06-02 07:16:49 -03001212 v4l2_device_unregister(&cam->v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001213
Hans Verkuila906f622012-06-02 07:16:49 -03001214 videobuf_mmap_free(&cam->vb_vidq);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001215
1216 /* release sys buffers */
1217 for (i = 0; i < FRAMES; i++) {
1218 if (cam->buffer.frame[i].lpvbits) {
1219 DBG("vfree %p\n", cam->buffer.frame[i].lpvbits);
1220 vfree(cam->buffer.frame[i].lpvbits);
1221 }
1222 cam->buffer.frame[i].lpvbits = NULL;
1223 }
1224
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001225 v4l2_ctrl_handler_free(&cam->ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001226 /* release transfer buffer */
1227 kfree(cam->pipe->transfer_buffer);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001228 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001229}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001230
1231/* release the camera */
Hans Verkuila906f622012-06-02 07:16:49 -03001232static int zr364xx_close(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001233{
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001234 struct zr364xx_camera *cam;
1235 struct usb_device *udev;
Hans Verkuila906f622012-06-02 07:16:49 -03001236 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001237
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001238 DBG("%s\n", __func__);
1239 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001240
Hans Verkuila906f622012-06-02 07:16:49 -03001241 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001242 udev = cam->udev;
1243
Hans Verkuila0657292012-06-02 08:50:31 -03001244 if (file->private_data == cam->owner) {
1245 /* turn off stream */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001246 if (cam->b_acquire)
1247 zr364xx_stop_acquire(cam);
1248 videobuf_streamoff(&cam->vb_vidq);
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001249
Hans Verkuila0657292012-06-02 08:50:31 -03001250 for (i = 0; i < 2; i++) {
1251 send_control_msg(udev, 1, init[cam->method][i].value,
1252 0, init[cam->method][i].bytes,
1253 init[cam->method][i].size);
1254 }
1255 cam->owner = NULL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001256 }
1257
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001258 /* Added some delay here, since opening/closing the camera quickly,
1259 * like Ekiga does during its startup, can crash the webcam
1260 */
1261 mdelay(100);
Hans Verkuila906f622012-06-02 07:16:49 -03001262 mutex_unlock(&cam->lock);
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001263 return v4l2_fh_release(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001264}
1265
1266
1267static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
1268{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001269 struct zr364xx_camera *cam = video_drvdata(file);
1270 int ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001271
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001272 if (cam == NULL) {
1273 DBG("%s: cam == NULL\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001274 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001275 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001276 DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001277
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001278 ret = videobuf_mmap_mapper(&cam->vb_vidq, vma);
1279
1280 DBG("vma start=0x%08lx, size=%ld, ret=%d\n",
1281 (unsigned long)vma->vm_start,
1282 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
1283 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001284}
1285
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001286static unsigned int zr364xx_poll(struct file *file,
1287 struct poll_table_struct *wait)
1288{
1289 struct zr364xx_camera *cam = video_drvdata(file);
1290 struct videobuf_queue *q = &cam->vb_vidq;
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001291 unsigned res = v4l2_ctrl_poll(file, wait);
1292
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001293 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001294
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001295 return res | videobuf_poll_stream(file, q, wait);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001296}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001297
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001298static const struct v4l2_ctrl_ops zr364xx_ctrl_ops = {
1299 .s_ctrl = zr364xx_s_ctrl,
1300};
1301
Hans Verkuilbec43662008-12-30 06:58:20 -03001302static const struct v4l2_file_operations zr364xx_fops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001303 .owner = THIS_MODULE,
1304 .open = zr364xx_open,
Hans Verkuila906f622012-06-02 07:16:49 -03001305 .release = zr364xx_close,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001306 .read = zr364xx_read,
1307 .mmap = zr364xx_mmap,
Hans Verkuila906f622012-06-02 07:16:49 -03001308 .unlocked_ioctl = video_ioctl2,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001309 .poll = zr364xx_poll,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001310};
1311
Hans Verkuila3998102008-07-21 02:57:38 -03001312static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001313 .vidioc_querycap = zr364xx_vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001314 .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
1315 .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
1316 .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
1317 .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001318 .vidioc_enum_input = zr364xx_vidioc_enum_input,
1319 .vidioc_g_input = zr364xx_vidioc_g_input,
1320 .vidioc_s_input = zr364xx_vidioc_s_input,
1321 .vidioc_streamon = zr364xx_vidioc_streamon,
1322 .vidioc_streamoff = zr364xx_vidioc_streamoff,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001323 .vidioc_reqbufs = zr364xx_vidioc_reqbufs,
1324 .vidioc_querybuf = zr364xx_vidioc_querybuf,
1325 .vidioc_qbuf = zr364xx_vidioc_qbuf,
1326 .vidioc_dqbuf = zr364xx_vidioc_dqbuf,
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001327 .vidioc_log_status = v4l2_ctrl_log_status,
1328 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1329 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001330};
1331
Hans Verkuila3998102008-07-21 02:57:38 -03001332static struct video_device zr364xx_template = {
Hans Verkuila3998102008-07-21 02:57:38 -03001333 .name = DRIVER_DESC,
Hans Verkuila3998102008-07-21 02:57:38 -03001334 .fops = &zr364xx_fops,
1335 .ioctl_ops = &zr364xx_ioctl_ops,
Hans Verkuil2b992512012-06-02 06:32:48 -03001336 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03001337};
1338
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001339
1340
1341/*******************/
1342/* USB integration */
1343/*******************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001344static int zr364xx_board_init(struct zr364xx_camera *cam)
1345{
1346 struct zr364xx_pipeinfo *pipe = cam->pipe;
1347 unsigned long i;
1348
1349 DBG("board init: %p\n", cam);
1350 memset(pipe, 0, sizeof(*pipe));
1351 pipe->cam = cam;
1352 pipe->transfer_size = BUFFER_SIZE;
1353
1354 pipe->transfer_buffer = kzalloc(pipe->transfer_size,
1355 GFP_KERNEL);
1356 if (pipe->transfer_buffer == NULL) {
1357 DBG("out of memory!\n");
1358 return -ENOMEM;
1359 }
1360
1361 cam->b_acquire = 0;
1362 cam->frame_count = 0;
1363
1364 /*** start create system buffers ***/
1365 for (i = 0; i < FRAMES; i++) {
1366 /* always allocate maximum size for system buffers */
1367 cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE);
1368
1369 DBG("valloc %p, idx %lu, pdata %p\n",
1370 &cam->buffer.frame[i], i,
1371 cam->buffer.frame[i].lpvbits);
1372 if (cam->buffer.frame[i].lpvbits == NULL) {
1373 printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
1374 "Using less frames\n");
1375 break;
1376 }
1377 }
1378
1379 if (i == 0) {
1380 printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
1381 kfree(cam->pipe->transfer_buffer);
1382 cam->pipe->transfer_buffer = NULL;
1383 return -ENOMEM;
1384 } else
1385 cam->buffer.dwFrames = i;
1386
1387 /* make sure internal states are set */
1388 for (i = 0; i < FRAMES; i++) {
1389 cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE;
1390 cam->buffer.frame[i].cur_size = 0;
1391 }
1392
1393 cam->cur_frame = 0;
1394 cam->last_frame = -1;
1395 /*** end create system buffers ***/
1396
1397 /* start read pipe */
1398 zr364xx_start_readpipe(cam);
1399 DBG(": board initialized\n");
1400 return 0;
1401}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001402
1403static int zr364xx_probe(struct usb_interface *intf,
1404 const struct usb_device_id *id)
1405{
1406 struct usb_device *udev = interface_to_usbdev(intf);
1407 struct zr364xx_camera *cam = NULL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001408 struct usb_host_interface *iface_desc;
1409 struct usb_endpoint_descriptor *endpoint;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001410 struct v4l2_ctrl_handler *hdl;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001411 int err;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001412 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001413
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001414 DBG("probing...\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001415
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001416 dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
1417 dev_info(&intf->dev, "model %04x:%04x detected\n",
1418 le16_to_cpu(udev->descriptor.idVendor),
1419 le16_to_cpu(udev->descriptor.idProduct));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001420
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001421 cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
1422 if (cam == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001423 dev_err(&udev->dev, "cam: out of memory !\n");
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001424 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001425 }
Hans Verkuila906f622012-06-02 07:16:49 -03001426
1427 cam->v4l2_dev.release = zr364xx_release;
1428 err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
1429 if (err < 0) {
1430 dev_err(&udev->dev, "couldn't register v4l2_device\n");
1431 kfree(cam);
1432 return err;
1433 }
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001434 hdl = &cam->ctrl_handler;
1435 v4l2_ctrl_handler_init(hdl, 1);
1436 v4l2_ctrl_new_std(hdl, &zr364xx_ctrl_ops,
1437 V4L2_CID_BRIGHTNESS, 0, 127, 1, 64);
1438 if (hdl->error) {
1439 err = hdl->error;
1440 dev_err(&udev->dev, "couldn't register control\n");
1441 goto fail;
1442 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001443 /* save the init method used by this camera */
1444 cam->method = id->driver_info;
Hans Verkuila906f622012-06-02 07:16:49 -03001445 mutex_init(&cam->lock);
Hans Verkuil2b992512012-06-02 06:32:48 -03001446 cam->vdev = zr364xx_template;
Hans Verkuila906f622012-06-02 07:16:49 -03001447 cam->vdev.lock = &cam->lock;
1448 cam->vdev.v4l2_dev = &cam->v4l2_dev;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001449 cam->vdev.ctrl_handler = &cam->ctrl_handler;
Hans Verkuila0657292012-06-02 08:50:31 -03001450 set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
Hans Verkuil2b992512012-06-02 06:32:48 -03001451 video_set_drvdata(&cam->vdev, cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001452 if (debug)
Hans Verkuil2b992512012-06-02 06:32:48 -03001453 cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001454
1455 cam->udev = udev;
1456
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001457 switch (mode) {
1458 case 1:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001459 dev_info(&udev->dev, "160x120 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001460 cam->width = 160;
1461 cam->height = 120;
1462 break;
1463 case 2:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001464 dev_info(&udev->dev, "640x480 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001465 cam->width = 640;
1466 cam->height = 480;
1467 break;
1468 default:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001469 dev_info(&udev->dev, "320x240 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001470 cam->width = 320;
1471 cam->height = 240;
1472 break;
1473 }
1474
1475 m0d1[0] = mode;
1476 m1[2].value = 0xf000 + mode;
1477 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -03001478
1479 /* special case for METHOD3, the modes are different */
1480 if (cam->method == METHOD3) {
1481 switch (mode) {
1482 case 1:
1483 m2[1].value = 0xf000 + 4;
1484 break;
1485 case 2:
1486 m2[1].value = 0xf000 + 0;
1487 break;
1488 default:
1489 m2[1].value = 0xf000 + 1;
1490 break;
1491 }
1492 }
1493
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001494 header2[437] = cam->height / 256;
1495 header2[438] = cam->height % 256;
1496 header2[439] = cam->width / 256;
1497 header2[440] = cam->width % 256;
1498
1499 cam->nb = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001500
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001501 DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf);
1502
1503 /* set up the endpoint information */
1504 iface_desc = intf->cur_altsetting;
1505 DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
1506 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1507 endpoint = &iface_desc->endpoint[i].desc;
1508 if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
1509 /* we found the bulk in endpoint */
1510 cam->read_endpoint = endpoint->bEndpointAddress;
1511 }
1512 }
1513
1514 if (!cam->read_endpoint) {
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001515 err = -ENOMEM;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001516 dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001517 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001518 }
1519
1520 /* v4l */
1521 INIT_LIST_HEAD(&cam->vidq.active);
1522 cam->vidq.cam = cam;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001523
1524 usb_set_intfdata(intf, cam);
1525
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001526 /* load zr364xx board specific */
1527 err = zr364xx_board_init(cam);
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001528 if (!err)
1529 err = v4l2_ctrl_handler_setup(hdl);
1530 if (err)
1531 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001532
1533 spin_lock_init(&cam->slock);
1534
Hans Verkuila0657292012-06-02 08:50:31 -03001535 cam->fmt = formats;
1536
1537 videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops,
1538 NULL, &cam->slock,
1539 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1540 V4L2_FIELD_NONE,
1541 sizeof(struct zr364xx_buffer), cam, &cam->lock);
1542
Hans Verkuil2b992512012-06-02 06:32:48 -03001543 err = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
1544 if (err) {
1545 dev_err(&udev->dev, "video_register_device failed\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001546 goto fail;
Hans Verkuil2b992512012-06-02 06:32:48 -03001547 }
1548
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001549 dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
Hans Verkuil2b992512012-06-02 06:32:48 -03001550 video_device_node_name(&cam->vdev));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001551 return 0;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001552
1553fail:
1554 v4l2_ctrl_handler_free(hdl);
1555 v4l2_device_unregister(&cam->v4l2_dev);
1556 kfree(cam);
1557 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001558}
1559
1560
1561static void zr364xx_disconnect(struct usb_interface *intf)
1562{
1563 struct zr364xx_camera *cam = usb_get_intfdata(intf);
Hans Verkuila906f622012-06-02 07:16:49 -03001564
1565 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001566 usb_set_intfdata(intf, NULL);
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001567 dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
Hans Verkuila906f622012-06-02 07:16:49 -03001568 video_unregister_device(&cam->vdev);
1569 v4l2_device_disconnect(&cam->v4l2_dev);
1570
1571 /* stops the read pipe if it is running */
1572 if (cam->b_acquire)
1573 zr364xx_stop_acquire(cam);
1574
1575 zr364xx_stop_readpipe(cam);
1576 mutex_unlock(&cam->lock);
1577 v4l2_device_put(&cam->v4l2_dev);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001578}
1579
1580
1581
1582/**********************/
1583/* Module integration */
1584/**********************/
1585
1586static struct usb_driver zr364xx_driver = {
1587 .name = "zr364xx",
1588 .probe = zr364xx_probe,
1589 .disconnect = zr364xx_disconnect,
1590 .id_table = device_table
1591};
1592
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001593module_usb_driver(zr364xx_driver);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001594
1595MODULE_AUTHOR(DRIVER_AUTHOR);
1596MODULE_DESCRIPTION(DRIVER_DESC);
1597MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001598MODULE_VERSION(DRIVER_VERSION);