blob: 39edd444293226406a4faed135930dcf09ff059c [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;
Hans Verkuil587a5762012-06-08 06:43:59 -0300199 bool was_streaming;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300200};
201
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300202/* buffer for one video frame */
203struct zr364xx_buffer {
204 /* common v4l buffer stuff -- must be first */
205 struct videobuf_buffer vb;
206 const struct zr364xx_fmt *fmt;
207};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300208
209/* function used to send initialisation commands to the camera */
210static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
211 u16 index, unsigned char *cp, u16 size)
212{
213 int status;
214
215 unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
216 if (!transfer_buffer) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300217 dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300218 return -ENOMEM;
219 }
220
221 memcpy(transfer_buffer, cp, size);
222
223 status = usb_control_msg(udev,
224 usb_sndctrlpipe(udev, 0),
225 request,
226 USB_DIR_OUT | USB_TYPE_VENDOR |
227 USB_RECIP_DEVICE, value, index,
228 transfer_buffer, size, CTRL_TIMEOUT);
229
230 kfree(transfer_buffer);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300231 return status;
232}
233
234
235/* Control messages sent to the camera to initialize it
236 * and launch the capture */
237typedef struct {
238 unsigned int value;
239 unsigned int size;
240 unsigned char *bytes;
241} message;
242
243/* method 0 */
244static unsigned char m0d1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
245static unsigned char m0d2[] = { 0, 0, 0, 0, 0, 0 };
246static unsigned char m0d3[] = { 0, 0 };
247static message m0[] = {
248 {0x1f30, 0, NULL},
249 {0xd000, 0, NULL},
250 {0x3370, sizeof(m0d1), m0d1},
251 {0x2000, 0, NULL},
252 {0x2f0f, 0, NULL},
253 {0x2610, sizeof(m0d2), m0d2},
254 {0xe107, 0, NULL},
255 {0x2502, 0, NULL},
256 {0x1f70, 0, NULL},
257 {0xd000, 0, NULL},
258 {0x9a01, sizeof(m0d3), m0d3},
259 {-1, -1, NULL}
260};
261
262/* method 1 */
263static unsigned char m1d1[] = { 0xff, 0xff };
264static unsigned char m1d2[] = { 0x00, 0x00 };
265static message m1[] = {
266 {0x1f30, 0, NULL},
267 {0xd000, 0, NULL},
268 {0xf000, 0, NULL},
269 {0x2000, 0, NULL},
270 {0x2f0f, 0, NULL},
271 {0x2650, 0, NULL},
272 {0xe107, 0, NULL},
273 {0x2502, sizeof(m1d1), m1d1},
274 {0x1f70, 0, NULL},
275 {0xd000, 0, NULL},
276 {0xd000, 0, NULL},
277 {0xd000, 0, NULL},
278 {0x9a01, sizeof(m1d2), m1d2},
279 {-1, -1, NULL}
280};
281
282/* method 2 */
283static unsigned char m2d1[] = { 0xff, 0xff };
284static message m2[] = {
285 {0x1f30, 0, NULL},
286 {0xf000, 0, NULL},
287 {0x2000, 0, NULL},
288 {0x2f0f, 0, NULL},
289 {0x2650, 0, NULL},
290 {0xe107, 0, NULL},
291 {0x2502, sizeof(m2d1), m2d1},
292 {0x1f70, 0, NULL},
293 {-1, -1, NULL}
294};
295
296/* init table */
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300297static message *init[4] = { m0, m1, m2, m2 };
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300298
299
300/* JPEG static data in header (Huffman table, etc) */
301static unsigned char header1[] = {
302 0xFF, 0xD8,
303 /*
304 0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F',
305 0x00, 0x01, 0x01, 0x00, 0x33, 0x8A, 0x00, 0x00, 0x33, 0x88,
306 */
307 0xFF, 0xDB, 0x00, 0x84
308};
309static unsigned char header2[] = {
310 0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
311 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
313 0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
314 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
315 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
316 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
317 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33,
318 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25,
319 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
320 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,
321 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
322 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
323 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
324 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
325 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
326 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
327 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
328 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
329 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC4, 0x00, 0x1F,
330 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
331 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
332 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0xC4, 0x00, 0xB5,
333 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
334 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,
335 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
336 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
337 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
338 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27,
339 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
340 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57,
341 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
342 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84,
343 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
344 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
345 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
346 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
347 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,
348 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
349 0xF8, 0xF9, 0xFA, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01,
350 0x40, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
351 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
352 0x00, 0x3F, 0x00
353};
354static unsigned char header3;
355
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300356/* ------------------------------------------------------------------
357 Videobuf operations
358 ------------------------------------------------------------------*/
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300359
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300360static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
361 unsigned int *size)
362{
363 struct zr364xx_camera *cam = vq->priv_data;
364
365 *size = cam->width * cam->height * (cam->fmt->depth >> 3);
366
367 if (*count == 0)
368 *count = ZR364XX_DEF_BUFS;
369
Andreas Bombedab7e312010-03-21 16:02:45 -0300370 if (*size * *count > ZR364XX_DEF_BUFS * 1024 * 1024)
371 *count = (ZR364XX_DEF_BUFS * 1024 * 1024) / *size;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300372
373 return 0;
374}
375
376static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf)
377{
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300378 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300379
380 if (in_interrupt())
381 BUG();
382
383 videobuf_vmalloc_free(&buf->vb);
384 buf->vb.state = VIDEOBUF_NEEDS_INIT;
385}
386
387static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
388 enum v4l2_field field)
389{
390 struct zr364xx_camera *cam = vq->priv_data;
391 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
392 vb);
393 int rc;
394
395 DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ?
396 cam->fmt->name : "");
397 if (cam->fmt == NULL)
398 return -EINVAL;
399
400 buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3);
401
402 if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) {
403 DBG("invalid buffer prepare\n");
404 return -EINVAL;
405 }
406
407 buf->fmt = cam->fmt;
408 buf->vb.width = cam->width;
409 buf->vb.height = cam->height;
410 buf->vb.field = field;
411
412 if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
413 rc = videobuf_iolock(vq, &buf->vb, NULL);
414 if (rc < 0)
415 goto fail;
416 }
417
418 buf->vb.state = VIDEOBUF_PREPARED;
419 return 0;
420fail:
421 free_buffer(vq, buf);
422 return rc;
423}
424
425static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
426{
427 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
428 vb);
429 struct zr364xx_camera *cam = vq->priv_data;
430
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300431 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300432
433 buf->vb.state = VIDEOBUF_QUEUED;
434 list_add_tail(&buf->vb.queue, &cam->vidq.active);
435}
436
437static void buffer_release(struct videobuf_queue *vq,
438 struct videobuf_buffer *vb)
439{
440 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
441 vb);
442
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300443 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300444 free_buffer(vq, buf);
445}
446
447static struct videobuf_queue_ops zr364xx_video_qops = {
448 .buf_setup = buffer_setup,
449 .buf_prepare = buffer_prepare,
450 .buf_queue = buffer_queue,
451 .buf_release = buffer_release,
452};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300453
454/********************/
455/* V4L2 integration */
456/********************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300457static int zr364xx_vidioc_streamon(struct file *file, void *priv,
458 enum v4l2_buf_type type);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300459
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300460static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300461 loff_t * ppos)
462{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300463 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila906f622012-06-02 07:16:49 -0300464 int err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300465
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300466 _DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300467
468 if (!buf)
469 return -EINVAL;
470
471 if (!count)
472 return -EINVAL;
473
Hans Verkuila906f622012-06-02 07:16:49 -0300474 if (mutex_lock_interruptible(&cam->lock))
475 return -ERESTARTSYS;
476
Hans Verkuila0657292012-06-02 08:50:31 -0300477 err = zr364xx_vidioc_streamon(file, file->private_data,
478 V4L2_BUF_TYPE_VIDEO_CAPTURE);
479 if (err == 0) {
480 DBG("%s: reading %d bytes at pos %d.\n", __func__,
481 (int) count, (int) *ppos);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300482
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300483 /* NoMan Sux ! */
Hans Verkuila906f622012-06-02 07:16:49 -0300484 err = videobuf_read_one(&cam->vb_vidq, buf, count, ppos,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300485 file->f_flags & O_NONBLOCK);
486 }
Hans Verkuila906f622012-06-02 07:16:49 -0300487 mutex_unlock(&cam->lock);
488 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300489}
490
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300491/* video buffer vmalloc implementation based partly on VIVI driver which is
492 * Copyright (c) 2006 by
493 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
494 * Ted Walther <ted--a.t--enumera.com>
495 * John Sokol <sokol--a.t--videotechnology.com>
496 * http://v4l.videotechnology.com/
497 *
498 */
499static void zr364xx_fillbuff(struct zr364xx_camera *cam,
500 struct zr364xx_buffer *buf,
501 int jpgsize)
502{
503 int pos = 0;
504 struct timeval ts;
505 const char *tmpbuf;
506 char *vbuf = videobuf_to_vmalloc(&buf->vb);
507 unsigned long last_frame;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300508
509 if (!vbuf)
510 return;
511
512 last_frame = cam->last_frame;
513 if (last_frame != -1) {
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300514 tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits;
515 switch (buf->fmt->fourcc) {
516 case V4L2_PIX_FMT_JPEG:
517 buf->vb.size = jpgsize;
518 memcpy(vbuf, tmpbuf, buf->vb.size);
519 break;
520 default:
521 printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n");
522 }
523 cam->last_frame = -1;
524 } else {
525 printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n");
526 return;
527 }
528 DBG("%s: Buffer 0x%08lx size= %d\n", __func__,
529 (unsigned long)vbuf, pos);
530 /* tell v4l buffer was filled */
531
532 buf->vb.field_count = cam->frame_count * 2;
533 do_gettimeofday(&ts);
534 buf->vb.ts = ts;
535 buf->vb.state = VIDEOBUF_DONE;
536}
537
538static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize)
539{
540 struct zr364xx_dmaqueue *dma_q = &cam->vidq;
541 struct zr364xx_buffer *buf;
542 unsigned long flags = 0;
543 int rc = 0;
544
545 DBG("wakeup: %p\n", &dma_q);
546 spin_lock_irqsave(&cam->slock, flags);
547
548 if (list_empty(&dma_q->active)) {
549 DBG("No active queue to serve\n");
550 rc = -1;
551 goto unlock;
552 }
553 buf = list_entry(dma_q->active.next,
554 struct zr364xx_buffer, vb.queue);
555
556 if (!waitqueue_active(&buf->vb.done)) {
557 /* no one active */
558 rc = -1;
559 goto unlock;
560 }
561 list_del(&buf->vb.queue);
562 do_gettimeofday(&buf->vb.ts);
563 DBG("[%p/%d] wakeup\n", buf, buf->vb.i);
564 zr364xx_fillbuff(cam, buf, jpgsize);
565 wake_up(&buf->vb.done);
566 DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
567unlock:
568 spin_unlock_irqrestore(&cam->slock, flags);
Julia Lawall30538142010-08-16 13:27:47 -0300569 return rc;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300570}
571
572/* this function moves the usb stream read pipe data
573 * into the system buffers.
574 * returns 0 on success, EAGAIN if more data to process (call this
575 * function again).
576 */
577static int zr364xx_read_video_callback(struct zr364xx_camera *cam,
578 struct zr364xx_pipeinfo *pipe_info,
579 struct urb *purb)
580{
581 unsigned char *pdest;
582 unsigned char *psrc;
583 s32 idx = -1;
584 struct zr364xx_framei *frm;
585 int i = 0;
586 unsigned char *ptr = NULL;
587
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300588 _DBG("buffer to user\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300589 idx = cam->cur_frame;
590 frm = &cam->buffer.frame[idx];
591
592 /* swap bytes if camera needs it */
593 if (cam->method == METHOD0) {
594 u16 *buf = (u16 *)pipe_info->transfer_buffer;
595 for (i = 0; i < purb->actual_length/2; i++)
596 swab16s(buf + i);
597 }
598
599 /* search done. now find out if should be acquiring */
600 if (!cam->b_acquire) {
601 /* we found a frame, but this channel is turned off */
602 frm->ulState = ZR364XX_READ_IDLE;
603 return -EINVAL;
604 }
605
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300606 psrc = (u8 *)pipe_info->transfer_buffer;
607 ptr = pdest = frm->lpvbits;
608
609 if (frm->ulState == ZR364XX_READ_IDLE) {
610 frm->ulState = ZR364XX_READ_FRAME;
611 frm->cur_size = 0;
612
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300613 _DBG("jpeg header, ");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300614 memcpy(ptr, header1, sizeof(header1));
615 ptr += sizeof(header1);
616 header3 = 0;
617 memcpy(ptr, &header3, 1);
618 ptr++;
619 memcpy(ptr, psrc, 64);
620 ptr += 64;
621 header3 = 1;
622 memcpy(ptr, &header3, 1);
623 ptr++;
624 memcpy(ptr, psrc + 64, 64);
625 ptr += 64;
626 memcpy(ptr, header2, sizeof(header2));
627 ptr += sizeof(header2);
628 memcpy(ptr, psrc + 128,
629 purb->actual_length - 128);
630 ptr += purb->actual_length - 128;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300631 _DBG("header : %d %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300632 psrc[0], psrc[1], psrc[2],
633 psrc[3], psrc[4], psrc[5],
634 psrc[6], psrc[7], psrc[8]);
635 frm->cur_size = ptr - pdest;
636 } else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300637 if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) {
638 dev_info(&cam->udev->dev,
639 "%s: buffer (%d bytes) too small to hold "
640 "frame data. Discarding frame data.\n",
641 __func__, MAX_FRAME_SIZE);
642 } else {
643 pdest += frm->cur_size;
644 memcpy(pdest, psrc, purb->actual_length);
645 frm->cur_size += purb->actual_length;
646 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300647 }
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300648 /*_DBG("cur_size %lu urb size %d\n", frm->cur_size,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300649 purb->actual_length);*/
650
651 if (purb->actual_length < pipe_info->transfer_size) {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300652 _DBG("****************Buffer[%d]full*************\n", idx);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300653 cam->last_frame = cam->cur_frame;
654 cam->cur_frame++;
655 /* end of system frame ring buffer, start at zero */
656 if (cam->cur_frame == cam->buffer.dwFrames)
657 cam->cur_frame = 0;
658
659 /* frame ready */
660 /* go back to find the JPEG EOI marker */
661 ptr = pdest = frm->lpvbits;
662 ptr += frm->cur_size - 2;
663 while (ptr > pdest) {
664 if (*ptr == 0xFF && *(ptr + 1) == 0xD9
665 && *(ptr + 2) == 0xFF)
666 break;
667 ptr--;
668 }
669 if (ptr == pdest)
670 DBG("No EOI marker\n");
671
672 /* Sometimes there is junk data in the middle of the picture,
673 * we want to skip this bogus frames */
674 while (ptr > pdest) {
675 if (*ptr == 0xFF && *(ptr + 1) == 0xFF
676 && *(ptr + 2) == 0xFF)
677 break;
678 ptr--;
679 }
680 if (ptr != pdest) {
681 DBG("Bogus frame ? %d\n", ++(cam->nb));
682 } else if (cam->b_acquire) {
683 /* we skip the 2 first frames which are usually buggy */
684 if (cam->skip)
685 cam->skip--;
686 else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300687 _DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300688 frm->cur_size,
689 pdest[0], pdest[1], pdest[2], pdest[3],
690 pdest[4], pdest[5], pdest[6], pdest[7]);
691
692 zr364xx_got_frame(cam, frm->cur_size);
693 }
694 }
695 cam->frame_count++;
696 frm->ulState = ZR364XX_READ_IDLE;
697 frm->cur_size = 0;
698 }
699 /* done successfully */
700 return 0;
701}
702
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300703static int zr364xx_vidioc_querycap(struct file *file, void *priv,
704 struct v4l2_capability *cap)
705{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300706 struct zr364xx_camera *cam = video_drvdata(file);
707
708 strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
709 strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
710 strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
711 sizeof(cap->bus_info));
Hans Verkuildf462902012-06-02 07:50:30 -0300712 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300713 V4L2_CAP_READWRITE |
714 V4L2_CAP_STREAMING;
Hans Verkuildf462902012-06-02 07:50:30 -0300715 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300716
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300717 return 0;
718}
719
720static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
721 struct v4l2_input *i)
722{
723 if (i->index != 0)
724 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300725 strcpy(i->name, DRIVER_DESC " Camera");
726 i->type = V4L2_INPUT_TYPE_CAMERA;
727 return 0;
728}
729
730static int zr364xx_vidioc_g_input(struct file *file, void *priv,
731 unsigned int *i)
732{
733 *i = 0;
734 return 0;
735}
736
737static int zr364xx_vidioc_s_input(struct file *file, void *priv,
738 unsigned int i)
739{
740 if (i != 0)
741 return -EINVAL;
742 return 0;
743}
744
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300745static int zr364xx_s_ctrl(struct v4l2_ctrl *ctrl)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300746{
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300747 struct zr364xx_camera *cam =
748 container_of(ctrl->handler, struct zr364xx_camera, ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300749 int temp;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300750
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300751 switch (ctrl->id) {
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300752 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300753 /* hardware brightness */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300754 send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300755 temp = (0x60 << 8) + 127 - ctrl->val;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300756 send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300757 break;
758 default:
759 return -EINVAL;
760 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300761
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300762 return 0;
763}
764
Hans Verkuil78b526a2008-05-28 12:16:41 -0300765static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300766 void *priv, struct v4l2_fmtdesc *f)
767{
768 if (f->index > 0)
769 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300770 f->flags = V4L2_FMT_FLAG_COMPRESSED;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300771 strcpy(f->description, formats[0].name);
772 f->pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300773 return 0;
774}
775
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300776static char *decode_fourcc(__u32 pixelformat, char *buf)
777{
778 buf[0] = pixelformat & 0xff;
779 buf[1] = (pixelformat >> 8) & 0xff;
780 buf[2] = (pixelformat >> 16) & 0xff;
781 buf[3] = (pixelformat >> 24) & 0xff;
782 buf[4] = '\0';
783 return buf;
784}
785
Hans Verkuil78b526a2008-05-28 12:16:41 -0300786static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300787 struct v4l2_format *f)
788{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300789 struct zr364xx_camera *cam = video_drvdata(file);
790 char pixelformat_name[5];
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300791
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300792 if (cam == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300793 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300794
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300795 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
796 DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__,
797 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name));
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300798 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300799 }
800
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300801 if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) &&
802 !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) {
803 f->fmt.pix.width = 320;
804 f->fmt.pix.height = 240;
805 }
806
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300807 f->fmt.pix.field = V4L2_FIELD_NONE;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300808 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
809 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300810 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300811 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300812 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
813 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
814 f->fmt.pix.field);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300815 return 0;
816}
817
Hans Verkuil78b526a2008-05-28 12:16:41 -0300818static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300819 struct v4l2_format *f)
820{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300821 struct zr364xx_camera *cam;
822
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300823 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300824 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300825 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300826
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300827 f->fmt.pix.pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300828 f->fmt.pix.field = V4L2_FIELD_NONE;
829 f->fmt.pix.width = cam->width;
830 f->fmt.pix.height = cam->height;
831 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
832 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300833 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300834 f->fmt.pix.priv = 0;
835 return 0;
836}
837
Hans Verkuil78b526a2008-05-28 12:16:41 -0300838static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300839 struct v4l2_format *f)
840{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300841 struct zr364xx_camera *cam = video_drvdata(file);
842 struct videobuf_queue *q = &cam->vb_vidq;
843 char pixelformat_name[5];
844 int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f);
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300845 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300846
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300847 if (ret < 0)
848 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300849
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300850 mutex_lock(&q->vb_lock);
851
852 if (videobuf_queue_is_busy(&cam->vb_vidq)) {
853 DBG("%s queue busy\n", __func__);
854 ret = -EBUSY;
855 goto out;
856 }
857
Hans Verkuila0657292012-06-02 08:50:31 -0300858 if (cam->owner) {
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300859 DBG("%s can't change format after started\n", __func__);
860 ret = -EBUSY;
861 goto out;
862 }
863
864 cam->width = f->fmt.pix.width;
865 cam->height = f->fmt.pix.height;
Hans Verkuila0657292012-06-02 08:50:31 -0300866 DBG("%s: %dx%d mode selected\n", __func__,
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300867 cam->width, cam->height);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300868 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
869 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300870 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300871 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300872 cam->vb_vidq.field = f->fmt.pix.field;
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300873
874 if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
875 mode = 1;
876 else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480)
877 mode = 2;
878 else
879 mode = 0;
880
881 m0d1[0] = mode;
882 m1[2].value = 0xf000 + mode;
883 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300884
885 /* special case for METHOD3, the modes are different */
886 if (cam->method == METHOD3) {
887 switch (mode) {
888 case 1:
889 m2[1].value = 0xf000 + 4;
890 break;
891 case 2:
892 m2[1].value = 0xf000 + 0;
893 break;
894 default:
895 m2[1].value = 0xf000 + 1;
896 break;
897 }
898 }
899
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300900 header2[437] = cam->height / 256;
901 header2[438] = cam->height % 256;
902 header2[439] = cam->width / 256;
903 header2[440] = cam->width % 256;
904
905 for (i = 0; init[cam->method][i].size != -1; i++) {
906 ret =
907 send_control_msg(cam->udev, 1, init[cam->method][i].value,
908 0, init[cam->method][i].bytes,
909 init[cam->method][i].size);
910 if (ret < 0) {
911 dev_err(&cam->udev->dev,
912 "error during resolution change sequence: %d\n", i);
913 goto out;
914 }
915 }
916
917 /* Added some delay here, since opening/closing the camera quickly,
918 * like Ekiga does during its startup, can crash the webcam
919 */
920 mdelay(100);
921 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300922 ret = 0;
923
924out:
925 mutex_unlock(&q->vb_lock);
926
927 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
928 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
929 f->fmt.pix.field);
930 return ret;
931}
932
933static int zr364xx_vidioc_reqbufs(struct file *file, void *priv,
934 struct v4l2_requestbuffers *p)
935{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300936 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila0657292012-06-02 08:50:31 -0300937
938 if (cam->owner && cam->owner != priv)
939 return -EBUSY;
940 return videobuf_reqbufs(&cam->vb_vidq, p);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300941}
942
943static int zr364xx_vidioc_querybuf(struct file *file,
944 void *priv,
945 struct v4l2_buffer *p)
946{
947 int rc;
948 struct zr364xx_camera *cam = video_drvdata(file);
949 rc = videobuf_querybuf(&cam->vb_vidq, p);
950 return rc;
951}
952
953static int zr364xx_vidioc_qbuf(struct file *file,
954 void *priv,
955 struct v4l2_buffer *p)
956{
957 int rc;
958 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300959 _DBG("%s\n", __func__);
Hans Verkuila0657292012-06-02 08:50:31 -0300960 if (cam->owner && cam->owner != priv)
961 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300962 rc = videobuf_qbuf(&cam->vb_vidq, p);
963 return rc;
964}
965
966static int zr364xx_vidioc_dqbuf(struct file *file,
967 void *priv,
968 struct v4l2_buffer *p)
969{
970 int rc;
971 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300972 _DBG("%s\n", __func__);
Hans Verkuila0657292012-06-02 08:50:31 -0300973 if (cam->owner && cam->owner != priv)
974 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300975 rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK);
976 return rc;
977}
978
979static void read_pipe_completion(struct urb *purb)
980{
981 struct zr364xx_pipeinfo *pipe_info;
982 struct zr364xx_camera *cam;
983 int pipe;
984
985 pipe_info = purb->context;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300986 _DBG("%s %p, status %d\n", __func__, purb, purb->status);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300987 if (pipe_info == NULL) {
988 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
989 return;
990 }
991
992 cam = pipe_info->cam;
993 if (cam == NULL) {
994 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
995 return;
996 }
997
998 /* if shutting down, do not resubmit, exit immediately */
999 if (purb->status == -ESHUTDOWN) {
1000 DBG("%s, err shutdown\n", __func__);
1001 pipe_info->err_count++;
1002 return;
1003 }
1004
1005 if (pipe_info->state == 0) {
1006 DBG("exiting USB pipe\n");
1007 return;
1008 }
1009
Mauro Carvalho Chehab50c80122012-10-27 16:30:47 -03001010 if (purb->actual_length > pipe_info->transfer_size) {
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001011 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
Hans Verkuil587a5762012-06-08 06:43:59 -03001122static int zr364xx_prepare(struct zr364xx_camera *cam)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001123{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001124 int res;
Hans Verkuil587a5762012-06-08 06:43:59 -03001125 int i, j;
Hans Verkuila0657292012-06-02 08:50:31 -03001126
1127 for (i = 0; init[cam->method][i].size != -1; i++) {
1128 res = send_control_msg(cam->udev, 1, init[cam->method][i].value,
1129 0, init[cam->method][i].bytes,
1130 init[cam->method][i].size);
1131 if (res < 0) {
1132 dev_err(&cam->udev->dev,
1133 "error during open sequence: %d\n", i);
1134 return res;
1135 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001136 }
1137
Hans Verkuila0657292012-06-02 08:50:31 -03001138 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001139 cam->last_frame = -1;
1140 cam->cur_frame = 0;
1141 cam->frame_count = 0;
1142 for (j = 0; j < FRAMES; j++) {
1143 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1144 cam->buffer.frame[j].cur_size = 0;
1145 }
Hans Verkuil587a5762012-06-08 06:43:59 -03001146 v4l2_ctrl_handler_setup(&cam->ctrl_handler);
1147 return 0;
1148}
1149
1150static int zr364xx_vidioc_streamon(struct file *file, void *priv,
1151 enum v4l2_buf_type type)
1152{
1153 struct zr364xx_camera *cam = video_drvdata(file);
1154 int res;
1155
1156 DBG("%s\n", __func__);
1157
1158 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1159 return -EINVAL;
1160
1161 if (cam->owner && cam->owner != priv)
1162 return -EBUSY;
1163
1164 res = zr364xx_prepare(cam);
1165 if (res)
1166 return res;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001167 res = videobuf_streamon(&cam->vb_vidq);
1168 if (res == 0) {
1169 zr364xx_start_acquire(cam);
Hans Verkuila0657292012-06-02 08:50:31 -03001170 cam->owner = file->private_data;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001171 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001172 return res;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001173}
1174
1175static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
1176 enum v4l2_buf_type type)
1177{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001178 struct zr364xx_camera *cam = video_drvdata(file);
1179
1180 DBG("%s\n", __func__);
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001181 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001182 return -EINVAL;
Hans Verkuila0657292012-06-02 08:50:31 -03001183 if (cam->owner && cam->owner != priv)
1184 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001185 zr364xx_stop_acquire(cam);
Hans Verkuila0657292012-06-02 08:50:31 -03001186 return videobuf_streamoff(&cam->vb_vidq);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001187}
1188
1189
1190/* open the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -03001191static int zr364xx_open(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001192{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001193 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila0657292012-06-02 08:50:31 -03001194 int err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001195
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001196 DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001197
Hans Verkuila906f622012-06-02 07:16:49 -03001198 if (mutex_lock_interruptible(&cam->lock))
1199 return -ERESTARTSYS;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001200
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001201 err = v4l2_fh_open(file);
1202 if (err)
1203 goto out;
1204
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001205 /* Added some delay here, since opening/closing the camera quickly,
1206 * like Ekiga does during its startup, can crash the webcam
1207 */
1208 mdelay(100);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001209 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001210
Antoine Jacquet69025c92008-08-18 17:09:53 -03001211out:
Hans Verkuila906f622012-06-02 07:16:49 -03001212 mutex_unlock(&cam->lock);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001213 DBG("%s: %d\n", __func__, err);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001214 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001215}
1216
Hans Verkuila906f622012-06-02 07:16:49 -03001217static void zr364xx_release(struct v4l2_device *v4l2_dev)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001218{
Hans Verkuila906f622012-06-02 07:16:49 -03001219 struct zr364xx_camera *cam =
1220 container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001221 unsigned long i;
1222
Hans Verkuila906f622012-06-02 07:16:49 -03001223 v4l2_device_unregister(&cam->v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001224
Hans Verkuila906f622012-06-02 07:16:49 -03001225 videobuf_mmap_free(&cam->vb_vidq);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001226
1227 /* release sys buffers */
1228 for (i = 0; i < FRAMES; i++) {
1229 if (cam->buffer.frame[i].lpvbits) {
1230 DBG("vfree %p\n", cam->buffer.frame[i].lpvbits);
1231 vfree(cam->buffer.frame[i].lpvbits);
1232 }
1233 cam->buffer.frame[i].lpvbits = NULL;
1234 }
1235
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001236 v4l2_ctrl_handler_free(&cam->ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001237 /* release transfer buffer */
1238 kfree(cam->pipe->transfer_buffer);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001239 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001240}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001241
1242/* release the camera */
Hans Verkuila906f622012-06-02 07:16:49 -03001243static int zr364xx_close(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001244{
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001245 struct zr364xx_camera *cam;
1246 struct usb_device *udev;
Hans Verkuila906f622012-06-02 07:16:49 -03001247 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001248
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001249 DBG("%s\n", __func__);
1250 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001251
Hans Verkuila906f622012-06-02 07:16:49 -03001252 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001253 udev = cam->udev;
1254
Hans Verkuila0657292012-06-02 08:50:31 -03001255 if (file->private_data == cam->owner) {
1256 /* turn off stream */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001257 if (cam->b_acquire)
1258 zr364xx_stop_acquire(cam);
1259 videobuf_streamoff(&cam->vb_vidq);
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001260
Hans Verkuila0657292012-06-02 08:50:31 -03001261 for (i = 0; i < 2; i++) {
1262 send_control_msg(udev, 1, init[cam->method][i].value,
1263 0, init[cam->method][i].bytes,
1264 init[cam->method][i].size);
1265 }
1266 cam->owner = NULL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001267 }
1268
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001269 /* Added some delay here, since opening/closing the camera quickly,
1270 * like Ekiga does during its startup, can crash the webcam
1271 */
1272 mdelay(100);
Hans Verkuila906f622012-06-02 07:16:49 -03001273 mutex_unlock(&cam->lock);
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001274 return v4l2_fh_release(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001275}
1276
1277
1278static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
1279{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001280 struct zr364xx_camera *cam = video_drvdata(file);
1281 int ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001282
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001283 if (cam == NULL) {
1284 DBG("%s: cam == NULL\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001285 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001286 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001287 DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001288
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001289 ret = videobuf_mmap_mapper(&cam->vb_vidq, vma);
1290
1291 DBG("vma start=0x%08lx, size=%ld, ret=%d\n",
1292 (unsigned long)vma->vm_start,
1293 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
1294 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001295}
1296
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001297static unsigned int zr364xx_poll(struct file *file,
1298 struct poll_table_struct *wait)
1299{
1300 struct zr364xx_camera *cam = video_drvdata(file);
1301 struct videobuf_queue *q = &cam->vb_vidq;
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001302 unsigned res = v4l2_ctrl_poll(file, wait);
1303
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001304 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001305
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001306 return res | videobuf_poll_stream(file, q, wait);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001307}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001308
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001309static const struct v4l2_ctrl_ops zr364xx_ctrl_ops = {
1310 .s_ctrl = zr364xx_s_ctrl,
1311};
1312
Hans Verkuilbec43662008-12-30 06:58:20 -03001313static const struct v4l2_file_operations zr364xx_fops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001314 .owner = THIS_MODULE,
1315 .open = zr364xx_open,
Hans Verkuila906f622012-06-02 07:16:49 -03001316 .release = zr364xx_close,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001317 .read = zr364xx_read,
1318 .mmap = zr364xx_mmap,
Hans Verkuila906f622012-06-02 07:16:49 -03001319 .unlocked_ioctl = video_ioctl2,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001320 .poll = zr364xx_poll,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001321};
1322
Hans Verkuila3998102008-07-21 02:57:38 -03001323static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001324 .vidioc_querycap = zr364xx_vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001325 .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
1326 .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
1327 .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
1328 .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001329 .vidioc_enum_input = zr364xx_vidioc_enum_input,
1330 .vidioc_g_input = zr364xx_vidioc_g_input,
1331 .vidioc_s_input = zr364xx_vidioc_s_input,
1332 .vidioc_streamon = zr364xx_vidioc_streamon,
1333 .vidioc_streamoff = zr364xx_vidioc_streamoff,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001334 .vidioc_reqbufs = zr364xx_vidioc_reqbufs,
1335 .vidioc_querybuf = zr364xx_vidioc_querybuf,
1336 .vidioc_qbuf = zr364xx_vidioc_qbuf,
1337 .vidioc_dqbuf = zr364xx_vidioc_dqbuf,
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001338 .vidioc_log_status = v4l2_ctrl_log_status,
1339 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1340 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001341};
1342
Hans Verkuila3998102008-07-21 02:57:38 -03001343static struct video_device zr364xx_template = {
Hans Verkuila3998102008-07-21 02:57:38 -03001344 .name = DRIVER_DESC,
Hans Verkuila3998102008-07-21 02:57:38 -03001345 .fops = &zr364xx_fops,
1346 .ioctl_ops = &zr364xx_ioctl_ops,
Hans Verkuil2b992512012-06-02 06:32:48 -03001347 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03001348};
1349
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001350
1351
1352/*******************/
1353/* USB integration */
1354/*******************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001355static int zr364xx_board_init(struct zr364xx_camera *cam)
1356{
1357 struct zr364xx_pipeinfo *pipe = cam->pipe;
1358 unsigned long i;
1359
1360 DBG("board init: %p\n", cam);
1361 memset(pipe, 0, sizeof(*pipe));
1362 pipe->cam = cam;
1363 pipe->transfer_size = BUFFER_SIZE;
1364
1365 pipe->transfer_buffer = kzalloc(pipe->transfer_size,
1366 GFP_KERNEL);
1367 if (pipe->transfer_buffer == NULL) {
1368 DBG("out of memory!\n");
1369 return -ENOMEM;
1370 }
1371
1372 cam->b_acquire = 0;
1373 cam->frame_count = 0;
1374
1375 /*** start create system buffers ***/
1376 for (i = 0; i < FRAMES; i++) {
1377 /* always allocate maximum size for system buffers */
1378 cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE);
1379
1380 DBG("valloc %p, idx %lu, pdata %p\n",
1381 &cam->buffer.frame[i], i,
1382 cam->buffer.frame[i].lpvbits);
1383 if (cam->buffer.frame[i].lpvbits == NULL) {
1384 printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
1385 "Using less frames\n");
1386 break;
1387 }
1388 }
1389
1390 if (i == 0) {
1391 printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
1392 kfree(cam->pipe->transfer_buffer);
1393 cam->pipe->transfer_buffer = NULL;
1394 return -ENOMEM;
1395 } else
1396 cam->buffer.dwFrames = i;
1397
1398 /* make sure internal states are set */
1399 for (i = 0; i < FRAMES; i++) {
1400 cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE;
1401 cam->buffer.frame[i].cur_size = 0;
1402 }
1403
1404 cam->cur_frame = 0;
1405 cam->last_frame = -1;
1406 /*** end create system buffers ***/
1407
1408 /* start read pipe */
1409 zr364xx_start_readpipe(cam);
1410 DBG(": board initialized\n");
1411 return 0;
1412}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001413
1414static int zr364xx_probe(struct usb_interface *intf,
1415 const struct usb_device_id *id)
1416{
1417 struct usb_device *udev = interface_to_usbdev(intf);
1418 struct zr364xx_camera *cam = NULL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001419 struct usb_host_interface *iface_desc;
1420 struct usb_endpoint_descriptor *endpoint;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001421 struct v4l2_ctrl_handler *hdl;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001422 int err;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001423 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001424
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001425 DBG("probing...\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001426
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001427 dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
1428 dev_info(&intf->dev, "model %04x:%04x detected\n",
1429 le16_to_cpu(udev->descriptor.idVendor),
1430 le16_to_cpu(udev->descriptor.idProduct));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001431
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001432 cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
1433 if (cam == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001434 dev_err(&udev->dev, "cam: out of memory !\n");
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001435 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001436 }
Hans Verkuila906f622012-06-02 07:16:49 -03001437
1438 cam->v4l2_dev.release = zr364xx_release;
1439 err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
1440 if (err < 0) {
1441 dev_err(&udev->dev, "couldn't register v4l2_device\n");
1442 kfree(cam);
1443 return err;
1444 }
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001445 hdl = &cam->ctrl_handler;
1446 v4l2_ctrl_handler_init(hdl, 1);
1447 v4l2_ctrl_new_std(hdl, &zr364xx_ctrl_ops,
1448 V4L2_CID_BRIGHTNESS, 0, 127, 1, 64);
1449 if (hdl->error) {
1450 err = hdl->error;
1451 dev_err(&udev->dev, "couldn't register control\n");
1452 goto fail;
1453 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001454 /* save the init method used by this camera */
1455 cam->method = id->driver_info;
Hans Verkuila906f622012-06-02 07:16:49 -03001456 mutex_init(&cam->lock);
Hans Verkuil2b992512012-06-02 06:32:48 -03001457 cam->vdev = zr364xx_template;
Hans Verkuila906f622012-06-02 07:16:49 -03001458 cam->vdev.lock = &cam->lock;
1459 cam->vdev.v4l2_dev = &cam->v4l2_dev;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001460 cam->vdev.ctrl_handler = &cam->ctrl_handler;
Hans Verkuila0657292012-06-02 08:50:31 -03001461 set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
Hans Verkuil2b992512012-06-02 06:32:48 -03001462 video_set_drvdata(&cam->vdev, cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001463 if (debug)
Hans Verkuil2b992512012-06-02 06:32:48 -03001464 cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001465
1466 cam->udev = udev;
1467
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001468 switch (mode) {
1469 case 1:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001470 dev_info(&udev->dev, "160x120 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001471 cam->width = 160;
1472 cam->height = 120;
1473 break;
1474 case 2:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001475 dev_info(&udev->dev, "640x480 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001476 cam->width = 640;
1477 cam->height = 480;
1478 break;
1479 default:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001480 dev_info(&udev->dev, "320x240 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001481 cam->width = 320;
1482 cam->height = 240;
1483 break;
1484 }
1485
1486 m0d1[0] = mode;
1487 m1[2].value = 0xf000 + mode;
1488 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -03001489
1490 /* special case for METHOD3, the modes are different */
1491 if (cam->method == METHOD3) {
1492 switch (mode) {
1493 case 1:
1494 m2[1].value = 0xf000 + 4;
1495 break;
1496 case 2:
1497 m2[1].value = 0xf000 + 0;
1498 break;
1499 default:
1500 m2[1].value = 0xf000 + 1;
1501 break;
1502 }
1503 }
1504
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001505 header2[437] = cam->height / 256;
1506 header2[438] = cam->height % 256;
1507 header2[439] = cam->width / 256;
1508 header2[440] = cam->width % 256;
1509
1510 cam->nb = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001511
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001512 DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf);
1513
1514 /* set up the endpoint information */
1515 iface_desc = intf->cur_altsetting;
1516 DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
1517 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1518 endpoint = &iface_desc->endpoint[i].desc;
1519 if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
1520 /* we found the bulk in endpoint */
1521 cam->read_endpoint = endpoint->bEndpointAddress;
1522 }
1523 }
1524
1525 if (!cam->read_endpoint) {
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001526 err = -ENOMEM;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001527 dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001528 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001529 }
1530
1531 /* v4l */
1532 INIT_LIST_HEAD(&cam->vidq.active);
1533 cam->vidq.cam = cam;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001534
1535 usb_set_intfdata(intf, cam);
1536
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001537 /* load zr364xx board specific */
1538 err = zr364xx_board_init(cam);
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001539 if (!err)
1540 err = v4l2_ctrl_handler_setup(hdl);
1541 if (err)
1542 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001543
1544 spin_lock_init(&cam->slock);
1545
Hans Verkuila0657292012-06-02 08:50:31 -03001546 cam->fmt = formats;
1547
1548 videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops,
1549 NULL, &cam->slock,
1550 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1551 V4L2_FIELD_NONE,
1552 sizeof(struct zr364xx_buffer), cam, &cam->lock);
1553
Hans Verkuil2b992512012-06-02 06:32:48 -03001554 err = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
1555 if (err) {
1556 dev_err(&udev->dev, "video_register_device failed\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001557 goto fail;
Hans Verkuil2b992512012-06-02 06:32:48 -03001558 }
1559
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001560 dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
Hans Verkuil2b992512012-06-02 06:32:48 -03001561 video_device_node_name(&cam->vdev));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001562 return 0;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001563
1564fail:
1565 v4l2_ctrl_handler_free(hdl);
1566 v4l2_device_unregister(&cam->v4l2_dev);
1567 kfree(cam);
1568 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001569}
1570
1571
1572static void zr364xx_disconnect(struct usb_interface *intf)
1573{
1574 struct zr364xx_camera *cam = usb_get_intfdata(intf);
Hans Verkuila906f622012-06-02 07:16:49 -03001575
1576 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001577 usb_set_intfdata(intf, NULL);
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001578 dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
Hans Verkuila906f622012-06-02 07:16:49 -03001579 video_unregister_device(&cam->vdev);
1580 v4l2_device_disconnect(&cam->v4l2_dev);
1581
1582 /* stops the read pipe if it is running */
1583 if (cam->b_acquire)
1584 zr364xx_stop_acquire(cam);
1585
1586 zr364xx_stop_readpipe(cam);
1587 mutex_unlock(&cam->lock);
1588 v4l2_device_put(&cam->v4l2_dev);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001589}
1590
1591
Hans Verkuil587a5762012-06-08 06:43:59 -03001592#ifdef CONFIG_PM
1593static int zr364xx_suspend(struct usb_interface *intf, pm_message_t message)
1594{
1595 struct zr364xx_camera *cam = usb_get_intfdata(intf);
1596
1597 cam->was_streaming = cam->b_acquire;
1598 if (!cam->was_streaming)
1599 return 0;
1600 zr364xx_stop_acquire(cam);
1601 zr364xx_stop_readpipe(cam);
1602 return 0;
1603}
1604
1605static int zr364xx_resume(struct usb_interface *intf)
1606{
1607 struct zr364xx_camera *cam = usb_get_intfdata(intf);
1608 int res;
1609
1610 if (!cam->was_streaming)
1611 return 0;
1612
1613 zr364xx_start_readpipe(cam);
1614 res = zr364xx_prepare(cam);
1615 if (!res)
1616 zr364xx_start_acquire(cam);
1617 return res;
1618}
1619#endif
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001620
1621/**********************/
1622/* Module integration */
1623/**********************/
1624
1625static struct usb_driver zr364xx_driver = {
1626 .name = "zr364xx",
1627 .probe = zr364xx_probe,
1628 .disconnect = zr364xx_disconnect,
Hans Verkuil587a5762012-06-08 06:43:59 -03001629#ifdef CONFIG_PM
1630 .suspend = zr364xx_suspend,
1631 .resume = zr364xx_resume,
1632 .reset_resume = zr364xx_resume,
1633#endif
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001634 .id_table = device_table
1635};
1636
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001637module_usb_driver(zr364xx_driver);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001638
1639MODULE_AUTHOR(DRIVER_AUTHOR);
1640MODULE_DESCRIPTION(DRIVER_DESC);
1641MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001642MODULE_VERSION(DRIVER_VERSION);