blob: 974515dd19d63b31d4bb4d232494146ab15c1f62 [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>
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030042#include <media/videobuf-vmalloc.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030043
44
45/* Version Information */
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030046#define DRIVER_VERSION "0.7.4"
Antoine Jacquetb7eee612007-04-27 12:30:59 -030047#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
48#define DRIVER_DESC "Zoran 364xx"
49
50
51/* Camera */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030052#define FRAMES 1
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -030053#define MAX_FRAME_SIZE 200000
Antoine Jacquetb7eee612007-04-27 12:30:59 -030054#define BUFFER_SIZE 0x1000
55#define CTRL_TIMEOUT 500
56
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030057#define ZR364XX_DEF_BUFS 4
58#define ZR364XX_READ_IDLE 0
59#define ZR364XX_READ_FRAME 1
Antoine Jacquetb7eee612007-04-27 12:30:59 -030060
61/* Debug macro */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030062#define DBG(fmt, args...) \
63 do { \
64 if (debug) { \
65 printk(KERN_INFO KBUILD_MODNAME " " fmt, ##args); \
66 } \
67 } while (0)
Antoine Jacquetb7eee612007-04-27 12:30:59 -030068
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -030069/*#define FULL_DEBUG 1*/
70#ifdef FULL_DEBUG
71#define _DBG DBG
72#else
73#define _DBG(fmt, args...)
74#endif
75
Antoine Jacquetb7eee612007-04-27 12:30:59 -030076/* Init methods, need to find nicer names for these
77 * the exact names of the chipsets would be the best if someone finds it */
78#define METHOD0 0
79#define METHOD1 1
80#define METHOD2 2
Antoine Jacquet08135ba2009-12-27 18:22:05 -030081#define METHOD3 3
Antoine Jacquetb7eee612007-04-27 12:30:59 -030082
83
84/* Module parameters */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030085static int debug;
86static int mode;
Antoine Jacquetb7eee612007-04-27 12:30:59 -030087
88
89/* Module parameters interface */
90module_param(debug, int, 0644);
91MODULE_PARM_DESC(debug, "Debug level");
92module_param(mode, int, 0644);
93MODULE_PARM_DESC(mode, "0 = 320x240, 1 = 160x120, 2 = 640x480");
94
95
96/* Devices supported by this driver
97 * .driver_info contains the init method used by the camera */
98static struct usb_device_id device_table[] = {
99 {USB_DEVICE(0x08ca, 0x0109), .driver_info = METHOD0 },
100 {USB_DEVICE(0x041e, 0x4024), .driver_info = METHOD0 },
101 {USB_DEVICE(0x0d64, 0x0108), .driver_info = METHOD0 },
102 {USB_DEVICE(0x0546, 0x3187), .driver_info = METHOD0 },
103 {USB_DEVICE(0x0d64, 0x3108), .driver_info = METHOD0 },
104 {USB_DEVICE(0x0595, 0x4343), .driver_info = METHOD0 },
105 {USB_DEVICE(0x0bb0, 0x500d), .driver_info = METHOD0 },
106 {USB_DEVICE(0x0feb, 0x2004), .driver_info = METHOD0 },
107 {USB_DEVICE(0x055f, 0xb500), .driver_info = METHOD0 },
108 {USB_DEVICE(0x08ca, 0x2062), .driver_info = METHOD2 },
109 {USB_DEVICE(0x052b, 0x1a18), .driver_info = METHOD1 },
110 {USB_DEVICE(0x04c8, 0x0729), .driver_info = METHOD0 },
111 {USB_DEVICE(0x04f2, 0xa208), .driver_info = METHOD0 },
112 {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 },
113 {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
114 {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
Antoine Jacquetbebeaea2007-06-25 16:00:34 -0300115 {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
Antoine Jacquet71c04472008-01-25 22:01:53 -0300116 {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
Antoine Jacquetc0e0aff2008-01-25 22:03:10 -0300117 {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300118 {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD3 },
Antoine Jacquet9018f6c2009-11-19 22:35:38 -0300119 {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 },
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300120 {} /* Terminating entry */
121};
122
123MODULE_DEVICE_TABLE(usb, device_table);
124
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300125/* frame structure */
126struct zr364xx_framei {
127 unsigned long ulState; /* ulState:ZR364XX_READ_IDLE,
128 ZR364XX_READ_FRAME */
129 void *lpvbits; /* image data */
130 unsigned long cur_size; /* current data copied to it */
131};
132
133/* image buffer structure */
134struct zr364xx_bufferi {
135 unsigned long dwFrames; /* number of frames in buffer */
136 struct zr364xx_framei frame[FRAMES]; /* array of FRAME structures */
137};
138
139struct zr364xx_dmaqueue {
140 struct list_head active;
141 struct zr364xx_camera *cam;
142};
143
144struct zr364xx_pipeinfo {
145 u32 transfer_size;
146 u8 *transfer_buffer;
147 u32 state;
148 void *stream_urb;
149 void *cam; /* back pointer to zr364xx_camera struct */
150 u32 err_count;
151 u32 idx;
152};
153
154struct zr364xx_fmt {
155 char *name;
156 u32 fourcc;
157 int depth;
158};
159
160/* image formats. */
161static const struct zr364xx_fmt formats[] = {
162 {
163 .name = "JPG",
164 .fourcc = V4L2_PIX_FMT_JPEG,
165 .depth = 24
166 }
167};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300168
169/* Camera stuff */
170struct zr364xx_camera {
171 struct usb_device *udev; /* save off the usb device pointer */
172 struct usb_interface *interface;/* the interface for this device */
Hans Verkuila906f622012-06-02 07:16:49 -0300173 struct v4l2_device v4l2_dev;
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300174 struct v4l2_ctrl_handler ctrl_handler;
Hans Verkuil2b992512012-06-02 06:32:48 -0300175 struct video_device vdev; /* v4l video device */
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300176 int nb;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300177 struct zr364xx_bufferi buffer;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300178 int skip;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300179 int width;
180 int height;
181 int method;
182 struct mutex lock;
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300183 int users;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300184
185 spinlock_t slock;
186 struct zr364xx_dmaqueue vidq;
187 int resources;
188 int last_frame;
189 int cur_frame;
190 unsigned long frame_count;
191 int b_acquire;
192 struct zr364xx_pipeinfo pipe[1];
193
194 u8 read_endpoint;
195
196 const struct zr364xx_fmt *fmt;
197 struct videobuf_queue vb_vidq;
198 enum v4l2_buf_type type;
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
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300476 if (cam->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
477 zr364xx_vidioc_streamon(file, cam, cam->type) == 0) {
478 DBG("%s: reading %d bytes at pos %d.\n", __func__, (int) count,
479 (int) *ppos);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300480
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300481 /* NoMan Sux ! */
Hans Verkuila906f622012-06-02 07:16:49 -0300482 err = videobuf_read_one(&cam->vb_vidq, buf, count, ppos,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300483 file->f_flags & O_NONBLOCK);
484 }
Hans Verkuila906f622012-06-02 07:16:49 -0300485 mutex_unlock(&cam->lock);
486 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300487}
488
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300489/* video buffer vmalloc implementation based partly on VIVI driver which is
490 * Copyright (c) 2006 by
491 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
492 * Ted Walther <ted--a.t--enumera.com>
493 * John Sokol <sokol--a.t--videotechnology.com>
494 * http://v4l.videotechnology.com/
495 *
496 */
497static void zr364xx_fillbuff(struct zr364xx_camera *cam,
498 struct zr364xx_buffer *buf,
499 int jpgsize)
500{
501 int pos = 0;
502 struct timeval ts;
503 const char *tmpbuf;
504 char *vbuf = videobuf_to_vmalloc(&buf->vb);
505 unsigned long last_frame;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300506
507 if (!vbuf)
508 return;
509
510 last_frame = cam->last_frame;
511 if (last_frame != -1) {
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300512 tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits;
513 switch (buf->fmt->fourcc) {
514 case V4L2_PIX_FMT_JPEG:
515 buf->vb.size = jpgsize;
516 memcpy(vbuf, tmpbuf, buf->vb.size);
517 break;
518 default:
519 printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n");
520 }
521 cam->last_frame = -1;
522 } else {
523 printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n");
524 return;
525 }
526 DBG("%s: Buffer 0x%08lx size= %d\n", __func__,
527 (unsigned long)vbuf, pos);
528 /* tell v4l buffer was filled */
529
530 buf->vb.field_count = cam->frame_count * 2;
531 do_gettimeofday(&ts);
532 buf->vb.ts = ts;
533 buf->vb.state = VIDEOBUF_DONE;
534}
535
536static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize)
537{
538 struct zr364xx_dmaqueue *dma_q = &cam->vidq;
539 struct zr364xx_buffer *buf;
540 unsigned long flags = 0;
541 int rc = 0;
542
543 DBG("wakeup: %p\n", &dma_q);
544 spin_lock_irqsave(&cam->slock, flags);
545
546 if (list_empty(&dma_q->active)) {
547 DBG("No active queue to serve\n");
548 rc = -1;
549 goto unlock;
550 }
551 buf = list_entry(dma_q->active.next,
552 struct zr364xx_buffer, vb.queue);
553
554 if (!waitqueue_active(&buf->vb.done)) {
555 /* no one active */
556 rc = -1;
557 goto unlock;
558 }
559 list_del(&buf->vb.queue);
560 do_gettimeofday(&buf->vb.ts);
561 DBG("[%p/%d] wakeup\n", buf, buf->vb.i);
562 zr364xx_fillbuff(cam, buf, jpgsize);
563 wake_up(&buf->vb.done);
564 DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
565unlock:
566 spin_unlock_irqrestore(&cam->slock, flags);
Julia Lawall30538142010-08-16 13:27:47 -0300567 return rc;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300568}
569
570/* this function moves the usb stream read pipe data
571 * into the system buffers.
572 * returns 0 on success, EAGAIN if more data to process (call this
573 * function again).
574 */
575static int zr364xx_read_video_callback(struct zr364xx_camera *cam,
576 struct zr364xx_pipeinfo *pipe_info,
577 struct urb *purb)
578{
579 unsigned char *pdest;
580 unsigned char *psrc;
581 s32 idx = -1;
582 struct zr364xx_framei *frm;
583 int i = 0;
584 unsigned char *ptr = NULL;
585
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300586 _DBG("buffer to user\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300587 idx = cam->cur_frame;
588 frm = &cam->buffer.frame[idx];
589
590 /* swap bytes if camera needs it */
591 if (cam->method == METHOD0) {
592 u16 *buf = (u16 *)pipe_info->transfer_buffer;
593 for (i = 0; i < purb->actual_length/2; i++)
594 swab16s(buf + i);
595 }
596
597 /* search done. now find out if should be acquiring */
598 if (!cam->b_acquire) {
599 /* we found a frame, but this channel is turned off */
600 frm->ulState = ZR364XX_READ_IDLE;
601 return -EINVAL;
602 }
603
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300604 psrc = (u8 *)pipe_info->transfer_buffer;
605 ptr = pdest = frm->lpvbits;
606
607 if (frm->ulState == ZR364XX_READ_IDLE) {
608 frm->ulState = ZR364XX_READ_FRAME;
609 frm->cur_size = 0;
610
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300611 _DBG("jpeg header, ");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300612 memcpy(ptr, header1, sizeof(header1));
613 ptr += sizeof(header1);
614 header3 = 0;
615 memcpy(ptr, &header3, 1);
616 ptr++;
617 memcpy(ptr, psrc, 64);
618 ptr += 64;
619 header3 = 1;
620 memcpy(ptr, &header3, 1);
621 ptr++;
622 memcpy(ptr, psrc + 64, 64);
623 ptr += 64;
624 memcpy(ptr, header2, sizeof(header2));
625 ptr += sizeof(header2);
626 memcpy(ptr, psrc + 128,
627 purb->actual_length - 128);
628 ptr += purb->actual_length - 128;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300629 _DBG("header : %d %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300630 psrc[0], psrc[1], psrc[2],
631 psrc[3], psrc[4], psrc[5],
632 psrc[6], psrc[7], psrc[8]);
633 frm->cur_size = ptr - pdest;
634 } else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300635 if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) {
636 dev_info(&cam->udev->dev,
637 "%s: buffer (%d bytes) too small to hold "
638 "frame data. Discarding frame data.\n",
639 __func__, MAX_FRAME_SIZE);
640 } else {
641 pdest += frm->cur_size;
642 memcpy(pdest, psrc, purb->actual_length);
643 frm->cur_size += purb->actual_length;
644 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300645 }
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300646 /*_DBG("cur_size %lu urb size %d\n", frm->cur_size,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300647 purb->actual_length);*/
648
649 if (purb->actual_length < pipe_info->transfer_size) {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300650 _DBG("****************Buffer[%d]full*************\n", idx);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300651 cam->last_frame = cam->cur_frame;
652 cam->cur_frame++;
653 /* end of system frame ring buffer, start at zero */
654 if (cam->cur_frame == cam->buffer.dwFrames)
655 cam->cur_frame = 0;
656
657 /* frame ready */
658 /* go back to find the JPEG EOI marker */
659 ptr = pdest = frm->lpvbits;
660 ptr += frm->cur_size - 2;
661 while (ptr > pdest) {
662 if (*ptr == 0xFF && *(ptr + 1) == 0xD9
663 && *(ptr + 2) == 0xFF)
664 break;
665 ptr--;
666 }
667 if (ptr == pdest)
668 DBG("No EOI marker\n");
669
670 /* Sometimes there is junk data in the middle of the picture,
671 * we want to skip this bogus frames */
672 while (ptr > pdest) {
673 if (*ptr == 0xFF && *(ptr + 1) == 0xFF
674 && *(ptr + 2) == 0xFF)
675 break;
676 ptr--;
677 }
678 if (ptr != pdest) {
679 DBG("Bogus frame ? %d\n", ++(cam->nb));
680 } else if (cam->b_acquire) {
681 /* we skip the 2 first frames which are usually buggy */
682 if (cam->skip)
683 cam->skip--;
684 else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300685 _DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300686 frm->cur_size,
687 pdest[0], pdest[1], pdest[2], pdest[3],
688 pdest[4], pdest[5], pdest[6], pdest[7]);
689
690 zr364xx_got_frame(cam, frm->cur_size);
691 }
692 }
693 cam->frame_count++;
694 frm->ulState = ZR364XX_READ_IDLE;
695 frm->cur_size = 0;
696 }
697 /* done successfully */
698 return 0;
699}
700
701static int res_get(struct zr364xx_camera *cam)
702{
703 /* is it free? */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300704 if (cam->resources) {
705 /* no, someone else uses it */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300706 return 0;
707 }
708 /* it's free, grab it */
709 cam->resources = 1;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300710 _DBG("res: get\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300711 return 1;
712}
713
714static inline int res_check(struct zr364xx_camera *cam)
715{
716 return cam->resources;
717}
718
719static void res_free(struct zr364xx_camera *cam)
720{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300721 cam->resources = 0;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300722 _DBG("res: put\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300723}
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300724
725static int zr364xx_vidioc_querycap(struct file *file, void *priv,
726 struct v4l2_capability *cap)
727{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300728 struct zr364xx_camera *cam = video_drvdata(file);
729
730 strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
731 strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
732 strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
733 sizeof(cap->bus_info));
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300734 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
735 V4L2_CAP_READWRITE |
736 V4L2_CAP_STREAMING;
737
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300738 return 0;
739}
740
741static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
742 struct v4l2_input *i)
743{
744 if (i->index != 0)
745 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300746 strcpy(i->name, DRIVER_DESC " Camera");
747 i->type = V4L2_INPUT_TYPE_CAMERA;
748 return 0;
749}
750
751static int zr364xx_vidioc_g_input(struct file *file, void *priv,
752 unsigned int *i)
753{
754 *i = 0;
755 return 0;
756}
757
758static int zr364xx_vidioc_s_input(struct file *file, void *priv,
759 unsigned int i)
760{
761 if (i != 0)
762 return -EINVAL;
763 return 0;
764}
765
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300766static int zr364xx_s_ctrl(struct v4l2_ctrl *ctrl)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300767{
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300768 struct zr364xx_camera *cam =
769 container_of(ctrl->handler, struct zr364xx_camera, ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300770 int temp;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300771
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300772 switch (ctrl->id) {
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300773 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300774 /* hardware brightness */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300775 send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300776 temp = (0x60 << 8) + 127 - ctrl->val;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300777 send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300778 break;
779 default:
780 return -EINVAL;
781 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300782
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300783 return 0;
784}
785
Hans Verkuil78b526a2008-05-28 12:16:41 -0300786static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300787 void *priv, struct v4l2_fmtdesc *f)
788{
789 if (f->index > 0)
790 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300791 f->flags = V4L2_FMT_FLAG_COMPRESSED;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300792 strcpy(f->description, formats[0].name);
793 f->pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300794 return 0;
795}
796
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300797static char *decode_fourcc(__u32 pixelformat, char *buf)
798{
799 buf[0] = pixelformat & 0xff;
800 buf[1] = (pixelformat >> 8) & 0xff;
801 buf[2] = (pixelformat >> 16) & 0xff;
802 buf[3] = (pixelformat >> 24) & 0xff;
803 buf[4] = '\0';
804 return buf;
805}
806
Hans Verkuil78b526a2008-05-28 12:16:41 -0300807static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300808 struct v4l2_format *f)
809{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300810 struct zr364xx_camera *cam = video_drvdata(file);
811 char pixelformat_name[5];
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300812
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300813 if (cam == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300814 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300815
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300816 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
817 DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__,
818 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name));
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300819 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300820 }
821
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300822 if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) &&
823 !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) {
824 f->fmt.pix.width = 320;
825 f->fmt.pix.height = 240;
826 }
827
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300828 f->fmt.pix.field = V4L2_FIELD_NONE;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300829 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
830 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
831 f->fmt.pix.colorspace = 0;
832 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300833 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
834 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
835 f->fmt.pix.field);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300836 return 0;
837}
838
Hans Verkuil78b526a2008-05-28 12:16:41 -0300839static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300840 struct v4l2_format *f)
841{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300842 struct zr364xx_camera *cam;
843
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300844 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300845 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300846 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300847
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300848 f->fmt.pix.pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300849 f->fmt.pix.field = V4L2_FIELD_NONE;
850 f->fmt.pix.width = cam->width;
851 f->fmt.pix.height = cam->height;
852 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
853 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
854 f->fmt.pix.colorspace = 0;
855 f->fmt.pix.priv = 0;
856 return 0;
857}
858
Hans Verkuil78b526a2008-05-28 12:16:41 -0300859static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300860 struct v4l2_format *f)
861{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300862 struct zr364xx_camera *cam = video_drvdata(file);
863 struct videobuf_queue *q = &cam->vb_vidq;
864 char pixelformat_name[5];
865 int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f);
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300866 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300867
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300868 if (ret < 0)
869 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300870
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300871 mutex_lock(&q->vb_lock);
872
873 if (videobuf_queue_is_busy(&cam->vb_vidq)) {
874 DBG("%s queue busy\n", __func__);
875 ret = -EBUSY;
876 goto out;
877 }
878
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300879 if (res_check(cam)) {
880 DBG("%s can't change format after started\n", __func__);
881 ret = -EBUSY;
882 goto out;
883 }
884
885 cam->width = f->fmt.pix.width;
886 cam->height = f->fmt.pix.height;
887 dev_info(&cam->udev->dev, "%s: %dx%d mode selected\n", __func__,
888 cam->width, cam->height);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300889 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
890 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
891 f->fmt.pix.colorspace = 0;
892 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300893 cam->vb_vidq.field = f->fmt.pix.field;
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300894
895 if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
896 mode = 1;
897 else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480)
898 mode = 2;
899 else
900 mode = 0;
901
902 m0d1[0] = mode;
903 m1[2].value = 0xf000 + mode;
904 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300905
906 /* special case for METHOD3, the modes are different */
907 if (cam->method == METHOD3) {
908 switch (mode) {
909 case 1:
910 m2[1].value = 0xf000 + 4;
911 break;
912 case 2:
913 m2[1].value = 0xf000 + 0;
914 break;
915 default:
916 m2[1].value = 0xf000 + 1;
917 break;
918 }
919 }
920
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300921 header2[437] = cam->height / 256;
922 header2[438] = cam->height % 256;
923 header2[439] = cam->width / 256;
924 header2[440] = cam->width % 256;
925
926 for (i = 0; init[cam->method][i].size != -1; i++) {
927 ret =
928 send_control_msg(cam->udev, 1, init[cam->method][i].value,
929 0, init[cam->method][i].bytes,
930 init[cam->method][i].size);
931 if (ret < 0) {
932 dev_err(&cam->udev->dev,
933 "error during resolution change sequence: %d\n", i);
934 goto out;
935 }
936 }
937
938 /* Added some delay here, since opening/closing the camera quickly,
939 * like Ekiga does during its startup, can crash the webcam
940 */
941 mdelay(100);
942 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300943 ret = 0;
944
945out:
946 mutex_unlock(&q->vb_lock);
947
948 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
949 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
950 f->fmt.pix.field);
951 return ret;
952}
953
954static int zr364xx_vidioc_reqbufs(struct file *file, void *priv,
955 struct v4l2_requestbuffers *p)
956{
957 int rc;
958 struct zr364xx_camera *cam = video_drvdata(file);
959 rc = videobuf_reqbufs(&cam->vb_vidq, p);
960 return rc;
961}
962
963static int zr364xx_vidioc_querybuf(struct file *file,
964 void *priv,
965 struct v4l2_buffer *p)
966{
967 int rc;
968 struct zr364xx_camera *cam = video_drvdata(file);
969 rc = videobuf_querybuf(&cam->vb_vidq, p);
970 return rc;
971}
972
973static int zr364xx_vidioc_qbuf(struct file *file,
974 void *priv,
975 struct v4l2_buffer *p)
976{
977 int rc;
978 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300979 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300980 rc = videobuf_qbuf(&cam->vb_vidq, p);
981 return rc;
982}
983
984static int zr364xx_vidioc_dqbuf(struct file *file,
985 void *priv,
986 struct v4l2_buffer *p)
987{
988 int rc;
989 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300990 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300991 rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK);
992 return rc;
993}
994
995static void read_pipe_completion(struct urb *purb)
996{
997 struct zr364xx_pipeinfo *pipe_info;
998 struct zr364xx_camera *cam;
999 int pipe;
1000
1001 pipe_info = purb->context;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001002 _DBG("%s %p, status %d\n", __func__, purb, purb->status);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001003 if (pipe_info == NULL) {
1004 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
1005 return;
1006 }
1007
1008 cam = pipe_info->cam;
1009 if (cam == NULL) {
1010 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
1011 return;
1012 }
1013
1014 /* if shutting down, do not resubmit, exit immediately */
1015 if (purb->status == -ESHUTDOWN) {
1016 DBG("%s, err shutdown\n", __func__);
1017 pipe_info->err_count++;
1018 return;
1019 }
1020
1021 if (pipe_info->state == 0) {
1022 DBG("exiting USB pipe\n");
1023 return;
1024 }
1025
1026 if (purb->actual_length < 0 ||
1027 purb->actual_length > pipe_info->transfer_size) {
1028 dev_err(&cam->udev->dev, "wrong number of bytes\n");
1029 return;
1030 }
1031
1032 if (purb->status == 0)
1033 zr364xx_read_video_callback(cam, pipe_info, purb);
1034 else {
1035 pipe_info->err_count++;
1036 DBG("%s: failed URB %d\n", __func__, purb->status);
1037 }
1038
1039 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1040
1041 /* reuse urb */
1042 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1043 pipe,
1044 pipe_info->transfer_buffer,
1045 pipe_info->transfer_size,
1046 read_pipe_completion, pipe_info);
1047
1048 if (pipe_info->state != 0) {
1049 purb->status = usb_submit_urb(pipe_info->stream_urb,
1050 GFP_ATOMIC);
1051
1052 if (purb->status)
1053 dev_err(&cam->udev->dev,
1054 "error submitting urb (error=%i)\n",
1055 purb->status);
1056 } else
1057 DBG("read pipe complete state 0\n");
1058}
1059
1060static int zr364xx_start_readpipe(struct zr364xx_camera *cam)
1061{
1062 int pipe;
1063 int retval;
1064 struct zr364xx_pipeinfo *pipe_info = cam->pipe;
1065 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1066 DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint);
1067
1068 pipe_info->state = 1;
1069 pipe_info->err_count = 0;
1070 pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
1071 if (!pipe_info->stream_urb) {
1072 dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n");
1073 return -ENOMEM;
1074 }
1075 /* transfer buffer allocated in board_init */
1076 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1077 pipe,
1078 pipe_info->transfer_buffer,
1079 pipe_info->transfer_size,
1080 read_pipe_completion, pipe_info);
1081
1082 DBG("submitting URB %p\n", pipe_info->stream_urb);
1083 retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
1084 if (retval) {
1085 printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n");
1086 return retval;
1087 }
1088
1089 return 0;
1090}
1091
1092static void zr364xx_stop_readpipe(struct zr364xx_camera *cam)
1093{
1094 struct zr364xx_pipeinfo *pipe_info;
1095
1096 if (cam == NULL) {
1097 printk(KERN_ERR KBUILD_MODNAME ": invalid device\n");
1098 return;
1099 }
1100 DBG("stop read pipe\n");
1101 pipe_info = cam->pipe;
1102 if (pipe_info) {
1103 if (pipe_info->state != 0)
1104 pipe_info->state = 0;
1105
1106 if (pipe_info->stream_urb) {
1107 /* cancel urb */
1108 usb_kill_urb(pipe_info->stream_urb);
1109 usb_free_urb(pipe_info->stream_urb);
1110 pipe_info->stream_urb = NULL;
1111 }
1112 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001113 return;
1114}
1115
1116/* starts acquisition process */
1117static int zr364xx_start_acquire(struct zr364xx_camera *cam)
1118{
1119 int j;
1120
1121 DBG("start acquire\n");
1122
1123 cam->last_frame = -1;
1124 cam->cur_frame = 0;
1125 for (j = 0; j < FRAMES; j++) {
1126 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1127 cam->buffer.frame[j].cur_size = 0;
1128 }
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -03001129 cam->b_acquire = 1;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001130 return 0;
1131}
1132
1133static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam)
1134{
1135 cam->b_acquire = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001136 return 0;
1137}
1138
1139static int zr364xx_vidioc_streamon(struct file *file, void *priv,
1140 enum v4l2_buf_type type)
1141{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001142 struct zr364xx_camera *cam = video_drvdata(file);
1143 int j;
1144 int res;
1145
1146 DBG("%s\n", __func__);
1147
1148 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1149 dev_err(&cam->udev->dev, "invalid fh type0\n");
1150 return -EINVAL;
1151 }
1152 if (cam->type != type) {
1153 dev_err(&cam->udev->dev, "invalid fh type1\n");
1154 return -EINVAL;
1155 }
1156
1157 if (!res_get(cam)) {
1158 dev_err(&cam->udev->dev, "stream busy\n");
1159 return -EBUSY;
1160 }
1161
1162 cam->last_frame = -1;
1163 cam->cur_frame = 0;
1164 cam->frame_count = 0;
1165 for (j = 0; j < FRAMES; j++) {
1166 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1167 cam->buffer.frame[j].cur_size = 0;
1168 }
1169 res = videobuf_streamon(&cam->vb_vidq);
1170 if (res == 0) {
1171 zr364xx_start_acquire(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001172 } else {
1173 res_free(cam);
1174 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001175 return res;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001176}
1177
1178static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
1179 enum v4l2_buf_type type)
1180{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001181 int res;
1182 struct zr364xx_camera *cam = video_drvdata(file);
1183
1184 DBG("%s\n", __func__);
1185 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1186 dev_err(&cam->udev->dev, "invalid fh type0\n");
1187 return -EINVAL;
1188 }
1189 if (cam->type != type) {
1190 dev_err(&cam->udev->dev, "invalid fh type1\n");
1191 return -EINVAL;
1192 }
1193 zr364xx_stop_acquire(cam);
1194 res = videobuf_streamoff(&cam->vb_vidq);
1195 if (res < 0)
1196 return res;
1197 res_free(cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001198 return 0;
1199}
1200
1201
1202/* open the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -03001203static int zr364xx_open(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001204{
1205 struct video_device *vdev = video_devdata(file);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001206 struct zr364xx_camera *cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001207 struct usb_device *udev = cam->udev;
1208 int i, err;
1209
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001210 DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001211
Hans Verkuila906f622012-06-02 07:16:49 -03001212 if (mutex_lock_interruptible(&cam->lock))
1213 return -ERESTARTSYS;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001214
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001215 if (cam->users) {
1216 err = -EBUSY;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001217 goto out;
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001218 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001219
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001220 for (i = 0; init[cam->method][i].size != -1; i++) {
1221 err =
1222 send_control_msg(udev, 1, init[cam->method][i].value,
1223 0, init[cam->method][i].bytes,
1224 init[cam->method][i].size);
1225 if (err < 0) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001226 dev_err(&cam->udev->dev,
1227 "error during open sequence: %d\n", i);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001228 goto out;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001229 }
1230 }
1231
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001232 cam->skip = 2;
1233 cam->users++;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001234 file->private_data = vdev;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001235 cam->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1236 cam->fmt = formats;
1237
1238 videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops,
1239 NULL, &cam->slock,
1240 cam->type,
1241 V4L2_FIELD_NONE,
Hans Verkuila906f622012-06-02 07:16:49 -03001242 sizeof(struct zr364xx_buffer), cam, &cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001243
1244 /* Added some delay here, since opening/closing the camera quickly,
1245 * like Ekiga does during its startup, can crash the webcam
1246 */
1247 mdelay(100);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001248 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001249
Antoine Jacquet69025c92008-08-18 17:09:53 -03001250out:
Hans Verkuila906f622012-06-02 07:16:49 -03001251 mutex_unlock(&cam->lock);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001252 DBG("%s: %d\n", __func__, err);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001253 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001254}
1255
Hans Verkuila906f622012-06-02 07:16:49 -03001256static void zr364xx_release(struct v4l2_device *v4l2_dev)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001257{
Hans Verkuila906f622012-06-02 07:16:49 -03001258 struct zr364xx_camera *cam =
1259 container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001260 unsigned long i;
1261
Hans Verkuila906f622012-06-02 07:16:49 -03001262 v4l2_device_unregister(&cam->v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001263
Hans Verkuila906f622012-06-02 07:16:49 -03001264 videobuf_mmap_free(&cam->vb_vidq);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001265
1266 /* release sys buffers */
1267 for (i = 0; i < FRAMES; i++) {
1268 if (cam->buffer.frame[i].lpvbits) {
1269 DBG("vfree %p\n", cam->buffer.frame[i].lpvbits);
1270 vfree(cam->buffer.frame[i].lpvbits);
1271 }
1272 cam->buffer.frame[i].lpvbits = NULL;
1273 }
1274
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001275 v4l2_ctrl_handler_free(&cam->ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001276 /* release transfer buffer */
1277 kfree(cam->pipe->transfer_buffer);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001278 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001279}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001280
1281/* release the camera */
Hans Verkuila906f622012-06-02 07:16:49 -03001282static int zr364xx_close(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001283{
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001284 struct zr364xx_camera *cam;
1285 struct usb_device *udev;
Hans Verkuila906f622012-06-02 07:16:49 -03001286 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001287
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001288 DBG("%s\n", __func__);
1289 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001290
Hans Verkuila906f622012-06-02 07:16:49 -03001291 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001292 udev = cam->udev;
1293
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001294 /* turn off stream */
1295 if (res_check(cam)) {
1296 if (cam->b_acquire)
1297 zr364xx_stop_acquire(cam);
1298 videobuf_streamoff(&cam->vb_vidq);
1299 res_free(cam);
1300 }
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001301
1302 cam->users--;
1303 file->private_data = NULL;
1304
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001305 for (i = 0; i < 2; i++) {
Hans Verkuila906f622012-06-02 07:16:49 -03001306 send_control_msg(udev, 1, init[cam->method][i].value,
Roel Kluin7b808922009-08-11 08:10:25 -03001307 0, init[cam->method][i].bytes,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001308 init[cam->method][i].size);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001309 }
1310
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001311 /* Added some delay here, since opening/closing the camera quickly,
1312 * like Ekiga does during its startup, can crash the webcam
1313 */
1314 mdelay(100);
Hans Verkuila906f622012-06-02 07:16:49 -03001315 mutex_unlock(&cam->lock);
1316 return 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001317}
1318
1319
1320static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
1321{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001322 struct zr364xx_camera *cam = video_drvdata(file);
1323 int ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001324
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001325 if (cam == NULL) {
1326 DBG("%s: cam == NULL\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001327 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001328 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001329 DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001330
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001331 ret = videobuf_mmap_mapper(&cam->vb_vidq, vma);
1332
1333 DBG("vma start=0x%08lx, size=%ld, ret=%d\n",
1334 (unsigned long)vma->vm_start,
1335 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
1336 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001337}
1338
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001339static unsigned int zr364xx_poll(struct file *file,
1340 struct poll_table_struct *wait)
1341{
1342 struct zr364xx_camera *cam = video_drvdata(file);
1343 struct videobuf_queue *q = &cam->vb_vidq;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001344 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001345
1346 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1347 return POLLERR;
1348
1349 return videobuf_poll_stream(file, q, wait);
1350}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001351
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001352static const struct v4l2_ctrl_ops zr364xx_ctrl_ops = {
1353 .s_ctrl = zr364xx_s_ctrl,
1354};
1355
Hans Verkuilbec43662008-12-30 06:58:20 -03001356static const struct v4l2_file_operations zr364xx_fops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001357 .owner = THIS_MODULE,
1358 .open = zr364xx_open,
Hans Verkuila906f622012-06-02 07:16:49 -03001359 .release = zr364xx_close,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001360 .read = zr364xx_read,
1361 .mmap = zr364xx_mmap,
Hans Verkuila906f622012-06-02 07:16:49 -03001362 .unlocked_ioctl = video_ioctl2,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001363 .poll = zr364xx_poll,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001364};
1365
Hans Verkuila3998102008-07-21 02:57:38 -03001366static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001367 .vidioc_querycap = zr364xx_vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001368 .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
1369 .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
1370 .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
1371 .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001372 .vidioc_enum_input = zr364xx_vidioc_enum_input,
1373 .vidioc_g_input = zr364xx_vidioc_g_input,
1374 .vidioc_s_input = zr364xx_vidioc_s_input,
1375 .vidioc_streamon = zr364xx_vidioc_streamon,
1376 .vidioc_streamoff = zr364xx_vidioc_streamoff,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001377 .vidioc_reqbufs = zr364xx_vidioc_reqbufs,
1378 .vidioc_querybuf = zr364xx_vidioc_querybuf,
1379 .vidioc_qbuf = zr364xx_vidioc_qbuf,
1380 .vidioc_dqbuf = zr364xx_vidioc_dqbuf,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001381};
1382
Hans Verkuila3998102008-07-21 02:57:38 -03001383static struct video_device zr364xx_template = {
Hans Verkuila3998102008-07-21 02:57:38 -03001384 .name = DRIVER_DESC,
Hans Verkuila3998102008-07-21 02:57:38 -03001385 .fops = &zr364xx_fops,
1386 .ioctl_ops = &zr364xx_ioctl_ops,
Hans Verkuil2b992512012-06-02 06:32:48 -03001387 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03001388};
1389
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001390
1391
1392/*******************/
1393/* USB integration */
1394/*******************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001395static int zr364xx_board_init(struct zr364xx_camera *cam)
1396{
1397 struct zr364xx_pipeinfo *pipe = cam->pipe;
1398 unsigned long i;
1399
1400 DBG("board init: %p\n", cam);
1401 memset(pipe, 0, sizeof(*pipe));
1402 pipe->cam = cam;
1403 pipe->transfer_size = BUFFER_SIZE;
1404
1405 pipe->transfer_buffer = kzalloc(pipe->transfer_size,
1406 GFP_KERNEL);
1407 if (pipe->transfer_buffer == NULL) {
1408 DBG("out of memory!\n");
1409 return -ENOMEM;
1410 }
1411
1412 cam->b_acquire = 0;
1413 cam->frame_count = 0;
1414
1415 /*** start create system buffers ***/
1416 for (i = 0; i < FRAMES; i++) {
1417 /* always allocate maximum size for system buffers */
1418 cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE);
1419
1420 DBG("valloc %p, idx %lu, pdata %p\n",
1421 &cam->buffer.frame[i], i,
1422 cam->buffer.frame[i].lpvbits);
1423 if (cam->buffer.frame[i].lpvbits == NULL) {
1424 printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
1425 "Using less frames\n");
1426 break;
1427 }
1428 }
1429
1430 if (i == 0) {
1431 printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
1432 kfree(cam->pipe->transfer_buffer);
1433 cam->pipe->transfer_buffer = NULL;
1434 return -ENOMEM;
1435 } else
1436 cam->buffer.dwFrames = i;
1437
1438 /* make sure internal states are set */
1439 for (i = 0; i < FRAMES; i++) {
1440 cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE;
1441 cam->buffer.frame[i].cur_size = 0;
1442 }
1443
1444 cam->cur_frame = 0;
1445 cam->last_frame = -1;
1446 /*** end create system buffers ***/
1447
1448 /* start read pipe */
1449 zr364xx_start_readpipe(cam);
1450 DBG(": board initialized\n");
1451 return 0;
1452}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001453
1454static int zr364xx_probe(struct usb_interface *intf,
1455 const struct usb_device_id *id)
1456{
1457 struct usb_device *udev = interface_to_usbdev(intf);
1458 struct zr364xx_camera *cam = NULL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001459 struct usb_host_interface *iface_desc;
1460 struct usb_endpoint_descriptor *endpoint;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001461 struct v4l2_ctrl_handler *hdl;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001462 int err;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001463 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001464
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001465 DBG("probing...\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001466
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001467 dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
1468 dev_info(&intf->dev, "model %04x:%04x detected\n",
1469 le16_to_cpu(udev->descriptor.idVendor),
1470 le16_to_cpu(udev->descriptor.idProduct));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001471
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001472 cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
1473 if (cam == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001474 dev_err(&udev->dev, "cam: out of memory !\n");
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001475 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001476 }
Hans Verkuila906f622012-06-02 07:16:49 -03001477
1478 cam->v4l2_dev.release = zr364xx_release;
1479 err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
1480 if (err < 0) {
1481 dev_err(&udev->dev, "couldn't register v4l2_device\n");
1482 kfree(cam);
1483 return err;
1484 }
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001485 hdl = &cam->ctrl_handler;
1486 v4l2_ctrl_handler_init(hdl, 1);
1487 v4l2_ctrl_new_std(hdl, &zr364xx_ctrl_ops,
1488 V4L2_CID_BRIGHTNESS, 0, 127, 1, 64);
1489 if (hdl->error) {
1490 err = hdl->error;
1491 dev_err(&udev->dev, "couldn't register control\n");
1492 goto fail;
1493 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001494 /* save the init method used by this camera */
1495 cam->method = id->driver_info;
Hans Verkuila906f622012-06-02 07:16:49 -03001496 mutex_init(&cam->lock);
Hans Verkuil2b992512012-06-02 06:32:48 -03001497 cam->vdev = zr364xx_template;
Hans Verkuila906f622012-06-02 07:16:49 -03001498 cam->vdev.lock = &cam->lock;
1499 cam->vdev.v4l2_dev = &cam->v4l2_dev;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001500 cam->vdev.ctrl_handler = &cam->ctrl_handler;
Hans Verkuil2b992512012-06-02 06:32:48 -03001501 video_set_drvdata(&cam->vdev, cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001502 if (debug)
Hans Verkuil2b992512012-06-02 06:32:48 -03001503 cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001504
1505 cam->udev = udev;
1506
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001507 switch (mode) {
1508 case 1:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001509 dev_info(&udev->dev, "160x120 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001510 cam->width = 160;
1511 cam->height = 120;
1512 break;
1513 case 2:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001514 dev_info(&udev->dev, "640x480 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001515 cam->width = 640;
1516 cam->height = 480;
1517 break;
1518 default:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001519 dev_info(&udev->dev, "320x240 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001520 cam->width = 320;
1521 cam->height = 240;
1522 break;
1523 }
1524
1525 m0d1[0] = mode;
1526 m1[2].value = 0xf000 + mode;
1527 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -03001528
1529 /* special case for METHOD3, the modes are different */
1530 if (cam->method == METHOD3) {
1531 switch (mode) {
1532 case 1:
1533 m2[1].value = 0xf000 + 4;
1534 break;
1535 case 2:
1536 m2[1].value = 0xf000 + 0;
1537 break;
1538 default:
1539 m2[1].value = 0xf000 + 1;
1540 break;
1541 }
1542 }
1543
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001544 header2[437] = cam->height / 256;
1545 header2[438] = cam->height % 256;
1546 header2[439] = cam->width / 256;
1547 header2[440] = cam->width % 256;
1548
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001549 cam->users = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001550 cam->nb = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001551
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001552 DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf);
1553
1554 /* set up the endpoint information */
1555 iface_desc = intf->cur_altsetting;
1556 DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
1557 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1558 endpoint = &iface_desc->endpoint[i].desc;
1559 if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
1560 /* we found the bulk in endpoint */
1561 cam->read_endpoint = endpoint->bEndpointAddress;
1562 }
1563 }
1564
1565 if (!cam->read_endpoint) {
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001566 err = -ENOMEM;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001567 dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001568 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001569 }
1570
1571 /* v4l */
1572 INIT_LIST_HEAD(&cam->vidq.active);
1573 cam->vidq.cam = cam;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001574
1575 usb_set_intfdata(intf, cam);
1576
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001577 /* load zr364xx board specific */
1578 err = zr364xx_board_init(cam);
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001579 if (!err)
1580 err = v4l2_ctrl_handler_setup(hdl);
1581 if (err)
1582 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001583
1584 spin_lock_init(&cam->slock);
1585
Hans Verkuil2b992512012-06-02 06:32:48 -03001586 err = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
1587 if (err) {
1588 dev_err(&udev->dev, "video_register_device failed\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001589 goto fail;
Hans Verkuil2b992512012-06-02 06:32:48 -03001590 }
1591
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001592 dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
Hans Verkuil2b992512012-06-02 06:32:48 -03001593 video_device_node_name(&cam->vdev));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001594 return 0;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001595
1596fail:
1597 v4l2_ctrl_handler_free(hdl);
1598 v4l2_device_unregister(&cam->v4l2_dev);
1599 kfree(cam);
1600 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001601}
1602
1603
1604static void zr364xx_disconnect(struct usb_interface *intf)
1605{
1606 struct zr364xx_camera *cam = usb_get_intfdata(intf);
Hans Verkuila906f622012-06-02 07:16:49 -03001607
1608 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001609 usb_set_intfdata(intf, NULL);
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001610 dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
Hans Verkuila906f622012-06-02 07:16:49 -03001611 video_unregister_device(&cam->vdev);
1612 v4l2_device_disconnect(&cam->v4l2_dev);
1613
1614 /* stops the read pipe if it is running */
1615 if (cam->b_acquire)
1616 zr364xx_stop_acquire(cam);
1617
1618 zr364xx_stop_readpipe(cam);
1619 mutex_unlock(&cam->lock);
1620 v4l2_device_put(&cam->v4l2_dev);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001621}
1622
1623
1624
1625/**********************/
1626/* Module integration */
1627/**********************/
1628
1629static struct usb_driver zr364xx_driver = {
1630 .name = "zr364xx",
1631 .probe = zr364xx_probe,
1632 .disconnect = zr364xx_disconnect,
1633 .id_table = device_table
1634};
1635
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001636module_usb_driver(zr364xx_driver);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001637
1638MODULE_AUTHOR(DRIVER_AUTHOR);
1639MODULE_DESCRIPTION(DRIVER_DESC);
1640MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001641MODULE_VERSION(DRIVER_VERSION);