blob: 95fd9906b1ce5ad3a5d487ed059ab278e9237dae [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>
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030041#include <media/videobuf-vmalloc.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030042
43
44/* Version Information */
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030045#define DRIVER_VERSION "0.7.4"
Antoine Jacquetb7eee612007-04-27 12:30:59 -030046#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
47#define DRIVER_DESC "Zoran 364xx"
48
49
50/* Camera */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030051#define FRAMES 1
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -030052#define MAX_FRAME_SIZE 200000
Antoine Jacquetb7eee612007-04-27 12:30:59 -030053#define BUFFER_SIZE 0x1000
54#define CTRL_TIMEOUT 500
55
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030056#define ZR364XX_DEF_BUFS 4
57#define ZR364XX_READ_IDLE 0
58#define ZR364XX_READ_FRAME 1
Antoine Jacquetb7eee612007-04-27 12:30:59 -030059
60/* Debug macro */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030061#define DBG(fmt, args...) \
62 do { \
63 if (debug) { \
64 printk(KERN_INFO KBUILD_MODNAME " " fmt, ##args); \
65 } \
66 } while (0)
Antoine Jacquetb7eee612007-04-27 12:30:59 -030067
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -030068/*#define FULL_DEBUG 1*/
69#ifdef FULL_DEBUG
70#define _DBG DBG
71#else
72#define _DBG(fmt, args...)
73#endif
74
Antoine Jacquetb7eee612007-04-27 12:30:59 -030075/* Init methods, need to find nicer names for these
76 * the exact names of the chipsets would be the best if someone finds it */
77#define METHOD0 0
78#define METHOD1 1
79#define METHOD2 2
Antoine Jacquet08135ba2009-12-27 18:22:05 -030080#define METHOD3 3
Antoine Jacquetb7eee612007-04-27 12:30:59 -030081
82
83/* Module parameters */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030084static int debug;
85static int mode;
Antoine Jacquetb7eee612007-04-27 12:30:59 -030086
87
88/* Module parameters interface */
89module_param(debug, int, 0644);
90MODULE_PARM_DESC(debug, "Debug level");
91module_param(mode, int, 0644);
92MODULE_PARM_DESC(mode, "0 = 320x240, 1 = 160x120, 2 = 640x480");
93
94
95/* Devices supported by this driver
96 * .driver_info contains the init method used by the camera */
97static struct usb_device_id device_table[] = {
98 {USB_DEVICE(0x08ca, 0x0109), .driver_info = METHOD0 },
99 {USB_DEVICE(0x041e, 0x4024), .driver_info = METHOD0 },
100 {USB_DEVICE(0x0d64, 0x0108), .driver_info = METHOD0 },
101 {USB_DEVICE(0x0546, 0x3187), .driver_info = METHOD0 },
102 {USB_DEVICE(0x0d64, 0x3108), .driver_info = METHOD0 },
103 {USB_DEVICE(0x0595, 0x4343), .driver_info = METHOD0 },
104 {USB_DEVICE(0x0bb0, 0x500d), .driver_info = METHOD0 },
105 {USB_DEVICE(0x0feb, 0x2004), .driver_info = METHOD0 },
106 {USB_DEVICE(0x055f, 0xb500), .driver_info = METHOD0 },
107 {USB_DEVICE(0x08ca, 0x2062), .driver_info = METHOD2 },
108 {USB_DEVICE(0x052b, 0x1a18), .driver_info = METHOD1 },
109 {USB_DEVICE(0x04c8, 0x0729), .driver_info = METHOD0 },
110 {USB_DEVICE(0x04f2, 0xa208), .driver_info = METHOD0 },
111 {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 },
112 {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
113 {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
Antoine Jacquetbebeaea2007-06-25 16:00:34 -0300114 {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
Antoine Jacquet71c04472008-01-25 22:01:53 -0300115 {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
Antoine Jacquetc0e0aff2008-01-25 22:03:10 -0300116 {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300117 {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD3 },
Antoine Jacquet9018f6c2009-11-19 22:35:38 -0300118 {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 },
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300119 {} /* Terminating entry */
120};
121
122MODULE_DEVICE_TABLE(usb, device_table);
123
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300124struct zr364xx_mode {
125 u32 color; /* output video color format */
126 u32 brightness; /* brightness */
127};
128
129/* frame structure */
130struct zr364xx_framei {
131 unsigned long ulState; /* ulState:ZR364XX_READ_IDLE,
132 ZR364XX_READ_FRAME */
133 void *lpvbits; /* image data */
134 unsigned long cur_size; /* current data copied to it */
135};
136
137/* image buffer structure */
138struct zr364xx_bufferi {
139 unsigned long dwFrames; /* number of frames in buffer */
140 struct zr364xx_framei frame[FRAMES]; /* array of FRAME structures */
141};
142
143struct zr364xx_dmaqueue {
144 struct list_head active;
145 struct zr364xx_camera *cam;
146};
147
148struct zr364xx_pipeinfo {
149 u32 transfer_size;
150 u8 *transfer_buffer;
151 u32 state;
152 void *stream_urb;
153 void *cam; /* back pointer to zr364xx_camera struct */
154 u32 err_count;
155 u32 idx;
156};
157
158struct zr364xx_fmt {
159 char *name;
160 u32 fourcc;
161 int depth;
162};
163
164/* image formats. */
165static const struct zr364xx_fmt formats[] = {
166 {
167 .name = "JPG",
168 .fourcc = V4L2_PIX_FMT_JPEG,
169 .depth = 24
170 }
171};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300172
173/* Camera stuff */
174struct zr364xx_camera {
175 struct usb_device *udev; /* save off the usb device pointer */
176 struct usb_interface *interface;/* the interface for this device */
Hans Verkuila906f622012-06-02 07:16:49 -0300177 struct v4l2_device v4l2_dev;
Hans Verkuil2b992512012-06-02 06:32:48 -0300178 struct video_device vdev; /* v4l video device */
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;
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300186 int users;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300187
188 spinlock_t slock;
189 struct zr364xx_dmaqueue vidq;
190 int resources;
191 int last_frame;
192 int cur_frame;
193 unsigned long frame_count;
194 int b_acquire;
195 struct zr364xx_pipeinfo pipe[1];
196
197 u8 read_endpoint;
198
199 const struct zr364xx_fmt *fmt;
200 struct videobuf_queue vb_vidq;
201 enum v4l2_buf_type type;
202 struct zr364xx_mode mode;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300203};
204
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300205/* buffer for one video frame */
206struct zr364xx_buffer {
207 /* common v4l buffer stuff -- must be first */
208 struct videobuf_buffer vb;
209 const struct zr364xx_fmt *fmt;
210};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300211
212/* function used to send initialisation commands to the camera */
213static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
214 u16 index, unsigned char *cp, u16 size)
215{
216 int status;
217
218 unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
219 if (!transfer_buffer) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300220 dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300221 return -ENOMEM;
222 }
223
224 memcpy(transfer_buffer, cp, size);
225
226 status = usb_control_msg(udev,
227 usb_sndctrlpipe(udev, 0),
228 request,
229 USB_DIR_OUT | USB_TYPE_VENDOR |
230 USB_RECIP_DEVICE, value, index,
231 transfer_buffer, size, CTRL_TIMEOUT);
232
233 kfree(transfer_buffer);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300234 return status;
235}
236
237
238/* Control messages sent to the camera to initialize it
239 * and launch the capture */
240typedef struct {
241 unsigned int value;
242 unsigned int size;
243 unsigned char *bytes;
244} message;
245
246/* method 0 */
247static unsigned char m0d1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
248static unsigned char m0d2[] = { 0, 0, 0, 0, 0, 0 };
249static unsigned char m0d3[] = { 0, 0 };
250static message m0[] = {
251 {0x1f30, 0, NULL},
252 {0xd000, 0, NULL},
253 {0x3370, sizeof(m0d1), m0d1},
254 {0x2000, 0, NULL},
255 {0x2f0f, 0, NULL},
256 {0x2610, sizeof(m0d2), m0d2},
257 {0xe107, 0, NULL},
258 {0x2502, 0, NULL},
259 {0x1f70, 0, NULL},
260 {0xd000, 0, NULL},
261 {0x9a01, sizeof(m0d3), m0d3},
262 {-1, -1, NULL}
263};
264
265/* method 1 */
266static unsigned char m1d1[] = { 0xff, 0xff };
267static unsigned char m1d2[] = { 0x00, 0x00 };
268static message m1[] = {
269 {0x1f30, 0, NULL},
270 {0xd000, 0, NULL},
271 {0xf000, 0, NULL},
272 {0x2000, 0, NULL},
273 {0x2f0f, 0, NULL},
274 {0x2650, 0, NULL},
275 {0xe107, 0, NULL},
276 {0x2502, sizeof(m1d1), m1d1},
277 {0x1f70, 0, NULL},
278 {0xd000, 0, NULL},
279 {0xd000, 0, NULL},
280 {0xd000, 0, NULL},
281 {0x9a01, sizeof(m1d2), m1d2},
282 {-1, -1, NULL}
283};
284
285/* method 2 */
286static unsigned char m2d1[] = { 0xff, 0xff };
287static message m2[] = {
288 {0x1f30, 0, NULL},
289 {0xf000, 0, NULL},
290 {0x2000, 0, NULL},
291 {0x2f0f, 0, NULL},
292 {0x2650, 0, NULL},
293 {0xe107, 0, NULL},
294 {0x2502, sizeof(m2d1), m2d1},
295 {0x1f70, 0, NULL},
296 {-1, -1, NULL}
297};
298
299/* init table */
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300300static message *init[4] = { m0, m1, m2, m2 };
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300301
302
303/* JPEG static data in header (Huffman table, etc) */
304static unsigned char header1[] = {
305 0xFF, 0xD8,
306 /*
307 0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F',
308 0x00, 0x01, 0x01, 0x00, 0x33, 0x8A, 0x00, 0x00, 0x33, 0x88,
309 */
310 0xFF, 0xDB, 0x00, 0x84
311};
312static unsigned char header2[] = {
313 0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
314 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
316 0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
317 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
318 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
319 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
320 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33,
321 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25,
322 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
323 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,
324 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
325 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
326 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
327 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
328 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
329 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
330 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
331 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
332 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC4, 0x00, 0x1F,
333 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
334 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
335 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0xC4, 0x00, 0xB5,
336 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
337 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,
338 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
339 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
340 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
341 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27,
342 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
343 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57,
344 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
345 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84,
346 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
347 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
348 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
349 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
350 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,
351 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
352 0xF8, 0xF9, 0xFA, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01,
353 0x40, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
354 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
355 0x00, 0x3F, 0x00
356};
357static unsigned char header3;
358
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300359/* ------------------------------------------------------------------
360 Videobuf operations
361 ------------------------------------------------------------------*/
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300362
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300363static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
364 unsigned int *size)
365{
366 struct zr364xx_camera *cam = vq->priv_data;
367
368 *size = cam->width * cam->height * (cam->fmt->depth >> 3);
369
370 if (*count == 0)
371 *count = ZR364XX_DEF_BUFS;
372
Andreas Bombedab7e312010-03-21 16:02:45 -0300373 if (*size * *count > ZR364XX_DEF_BUFS * 1024 * 1024)
374 *count = (ZR364XX_DEF_BUFS * 1024 * 1024) / *size;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300375
376 return 0;
377}
378
379static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf)
380{
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300381 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300382
383 if (in_interrupt())
384 BUG();
385
386 videobuf_vmalloc_free(&buf->vb);
387 buf->vb.state = VIDEOBUF_NEEDS_INIT;
388}
389
390static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
391 enum v4l2_field field)
392{
393 struct zr364xx_camera *cam = vq->priv_data;
394 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
395 vb);
396 int rc;
397
398 DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ?
399 cam->fmt->name : "");
400 if (cam->fmt == NULL)
401 return -EINVAL;
402
403 buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3);
404
405 if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) {
406 DBG("invalid buffer prepare\n");
407 return -EINVAL;
408 }
409
410 buf->fmt = cam->fmt;
411 buf->vb.width = cam->width;
412 buf->vb.height = cam->height;
413 buf->vb.field = field;
414
415 if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
416 rc = videobuf_iolock(vq, &buf->vb, NULL);
417 if (rc < 0)
418 goto fail;
419 }
420
421 buf->vb.state = VIDEOBUF_PREPARED;
422 return 0;
423fail:
424 free_buffer(vq, buf);
425 return rc;
426}
427
428static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
429{
430 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
431 vb);
432 struct zr364xx_camera *cam = vq->priv_data;
433
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300434 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300435
436 buf->vb.state = VIDEOBUF_QUEUED;
437 list_add_tail(&buf->vb.queue, &cam->vidq.active);
438}
439
440static void buffer_release(struct videobuf_queue *vq,
441 struct videobuf_buffer *vb)
442{
443 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
444 vb);
445
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300446 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300447 free_buffer(vq, buf);
448}
449
450static struct videobuf_queue_ops zr364xx_video_qops = {
451 .buf_setup = buffer_setup,
452 .buf_prepare = buffer_prepare,
453 .buf_queue = buffer_queue,
454 .buf_release = buffer_release,
455};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300456
457/********************/
458/* V4L2 integration */
459/********************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300460static int zr364xx_vidioc_streamon(struct file *file, void *priv,
461 enum v4l2_buf_type type);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300462
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300463static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300464 loff_t * ppos)
465{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300466 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila906f622012-06-02 07:16:49 -0300467 int err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300468
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300469 _DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300470
471 if (!buf)
472 return -EINVAL;
473
474 if (!count)
475 return -EINVAL;
476
Hans Verkuila906f622012-06-02 07:16:49 -0300477 if (mutex_lock_interruptible(&cam->lock))
478 return -ERESTARTSYS;
479
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300480 if (cam->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
481 zr364xx_vidioc_streamon(file, cam, cam->type) == 0) {
482 DBG("%s: reading %d bytes at pos %d.\n", __func__, (int) count,
483 (int) *ppos);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300484
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300485 /* NoMan Sux ! */
Hans Verkuila906f622012-06-02 07:16:49 -0300486 err = videobuf_read_one(&cam->vb_vidq, buf, count, ppos,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300487 file->f_flags & O_NONBLOCK);
488 }
Hans Verkuila906f622012-06-02 07:16:49 -0300489 mutex_unlock(&cam->lock);
490 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300491}
492
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300493/* video buffer vmalloc implementation based partly on VIVI driver which is
494 * Copyright (c) 2006 by
495 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
496 * Ted Walther <ted--a.t--enumera.com>
497 * John Sokol <sokol--a.t--videotechnology.com>
498 * http://v4l.videotechnology.com/
499 *
500 */
501static void zr364xx_fillbuff(struct zr364xx_camera *cam,
502 struct zr364xx_buffer *buf,
503 int jpgsize)
504{
505 int pos = 0;
506 struct timeval ts;
507 const char *tmpbuf;
508 char *vbuf = videobuf_to_vmalloc(&buf->vb);
509 unsigned long last_frame;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300510
511 if (!vbuf)
512 return;
513
514 last_frame = cam->last_frame;
515 if (last_frame != -1) {
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300516 tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits;
517 switch (buf->fmt->fourcc) {
518 case V4L2_PIX_FMT_JPEG:
519 buf->vb.size = jpgsize;
520 memcpy(vbuf, tmpbuf, buf->vb.size);
521 break;
522 default:
523 printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n");
524 }
525 cam->last_frame = -1;
526 } else {
527 printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n");
528 return;
529 }
530 DBG("%s: Buffer 0x%08lx size= %d\n", __func__,
531 (unsigned long)vbuf, pos);
532 /* tell v4l buffer was filled */
533
534 buf->vb.field_count = cam->frame_count * 2;
535 do_gettimeofday(&ts);
536 buf->vb.ts = ts;
537 buf->vb.state = VIDEOBUF_DONE;
538}
539
540static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize)
541{
542 struct zr364xx_dmaqueue *dma_q = &cam->vidq;
543 struct zr364xx_buffer *buf;
544 unsigned long flags = 0;
545 int rc = 0;
546
547 DBG("wakeup: %p\n", &dma_q);
548 spin_lock_irqsave(&cam->slock, flags);
549
550 if (list_empty(&dma_q->active)) {
551 DBG("No active queue to serve\n");
552 rc = -1;
553 goto unlock;
554 }
555 buf = list_entry(dma_q->active.next,
556 struct zr364xx_buffer, vb.queue);
557
558 if (!waitqueue_active(&buf->vb.done)) {
559 /* no one active */
560 rc = -1;
561 goto unlock;
562 }
563 list_del(&buf->vb.queue);
564 do_gettimeofday(&buf->vb.ts);
565 DBG("[%p/%d] wakeup\n", buf, buf->vb.i);
566 zr364xx_fillbuff(cam, buf, jpgsize);
567 wake_up(&buf->vb.done);
568 DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
569unlock:
570 spin_unlock_irqrestore(&cam->slock, flags);
Julia Lawall30538142010-08-16 13:27:47 -0300571 return rc;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300572}
573
574/* this function moves the usb stream read pipe data
575 * into the system buffers.
576 * returns 0 on success, EAGAIN if more data to process (call this
577 * function again).
578 */
579static int zr364xx_read_video_callback(struct zr364xx_camera *cam,
580 struct zr364xx_pipeinfo *pipe_info,
581 struct urb *purb)
582{
583 unsigned char *pdest;
584 unsigned char *psrc;
585 s32 idx = -1;
586 struct zr364xx_framei *frm;
587 int i = 0;
588 unsigned char *ptr = NULL;
589
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300590 _DBG("buffer to user\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300591 idx = cam->cur_frame;
592 frm = &cam->buffer.frame[idx];
593
594 /* swap bytes if camera needs it */
595 if (cam->method == METHOD0) {
596 u16 *buf = (u16 *)pipe_info->transfer_buffer;
597 for (i = 0; i < purb->actual_length/2; i++)
598 swab16s(buf + i);
599 }
600
601 /* search done. now find out if should be acquiring */
602 if (!cam->b_acquire) {
603 /* we found a frame, but this channel is turned off */
604 frm->ulState = ZR364XX_READ_IDLE;
605 return -EINVAL;
606 }
607
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300608 psrc = (u8 *)pipe_info->transfer_buffer;
609 ptr = pdest = frm->lpvbits;
610
611 if (frm->ulState == ZR364XX_READ_IDLE) {
612 frm->ulState = ZR364XX_READ_FRAME;
613 frm->cur_size = 0;
614
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300615 _DBG("jpeg header, ");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300616 memcpy(ptr, header1, sizeof(header1));
617 ptr += sizeof(header1);
618 header3 = 0;
619 memcpy(ptr, &header3, 1);
620 ptr++;
621 memcpy(ptr, psrc, 64);
622 ptr += 64;
623 header3 = 1;
624 memcpy(ptr, &header3, 1);
625 ptr++;
626 memcpy(ptr, psrc + 64, 64);
627 ptr += 64;
628 memcpy(ptr, header2, sizeof(header2));
629 ptr += sizeof(header2);
630 memcpy(ptr, psrc + 128,
631 purb->actual_length - 128);
632 ptr += purb->actual_length - 128;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300633 _DBG("header : %d %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300634 psrc[0], psrc[1], psrc[2],
635 psrc[3], psrc[4], psrc[5],
636 psrc[6], psrc[7], psrc[8]);
637 frm->cur_size = ptr - pdest;
638 } else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300639 if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) {
640 dev_info(&cam->udev->dev,
641 "%s: buffer (%d bytes) too small to hold "
642 "frame data. Discarding frame data.\n",
643 __func__, MAX_FRAME_SIZE);
644 } else {
645 pdest += frm->cur_size;
646 memcpy(pdest, psrc, purb->actual_length);
647 frm->cur_size += purb->actual_length;
648 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300649 }
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300650 /*_DBG("cur_size %lu urb size %d\n", frm->cur_size,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300651 purb->actual_length);*/
652
653 if (purb->actual_length < pipe_info->transfer_size) {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300654 _DBG("****************Buffer[%d]full*************\n", idx);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300655 cam->last_frame = cam->cur_frame;
656 cam->cur_frame++;
657 /* end of system frame ring buffer, start at zero */
658 if (cam->cur_frame == cam->buffer.dwFrames)
659 cam->cur_frame = 0;
660
661 /* frame ready */
662 /* go back to find the JPEG EOI marker */
663 ptr = pdest = frm->lpvbits;
664 ptr += frm->cur_size - 2;
665 while (ptr > pdest) {
666 if (*ptr == 0xFF && *(ptr + 1) == 0xD9
667 && *(ptr + 2) == 0xFF)
668 break;
669 ptr--;
670 }
671 if (ptr == pdest)
672 DBG("No EOI marker\n");
673
674 /* Sometimes there is junk data in the middle of the picture,
675 * we want to skip this bogus frames */
676 while (ptr > pdest) {
677 if (*ptr == 0xFF && *(ptr + 1) == 0xFF
678 && *(ptr + 2) == 0xFF)
679 break;
680 ptr--;
681 }
682 if (ptr != pdest) {
683 DBG("Bogus frame ? %d\n", ++(cam->nb));
684 } else if (cam->b_acquire) {
685 /* we skip the 2 first frames which are usually buggy */
686 if (cam->skip)
687 cam->skip--;
688 else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300689 _DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300690 frm->cur_size,
691 pdest[0], pdest[1], pdest[2], pdest[3],
692 pdest[4], pdest[5], pdest[6], pdest[7]);
693
694 zr364xx_got_frame(cam, frm->cur_size);
695 }
696 }
697 cam->frame_count++;
698 frm->ulState = ZR364XX_READ_IDLE;
699 frm->cur_size = 0;
700 }
701 /* done successfully */
702 return 0;
703}
704
705static int res_get(struct zr364xx_camera *cam)
706{
707 /* is it free? */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300708 if (cam->resources) {
709 /* no, someone else uses it */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300710 return 0;
711 }
712 /* it's free, grab it */
713 cam->resources = 1;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300714 _DBG("res: get\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300715 return 1;
716}
717
718static inline int res_check(struct zr364xx_camera *cam)
719{
720 return cam->resources;
721}
722
723static void res_free(struct zr364xx_camera *cam)
724{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300725 cam->resources = 0;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300726 _DBG("res: put\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300727}
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300728
729static int zr364xx_vidioc_querycap(struct file *file, void *priv,
730 struct v4l2_capability *cap)
731{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300732 struct zr364xx_camera *cam = video_drvdata(file);
733
734 strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
735 strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
736 strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
737 sizeof(cap->bus_info));
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300738 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
739 V4L2_CAP_READWRITE |
740 V4L2_CAP_STREAMING;
741
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300742 return 0;
743}
744
745static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
746 struct v4l2_input *i)
747{
748 if (i->index != 0)
749 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300750 strcpy(i->name, DRIVER_DESC " Camera");
751 i->type = V4L2_INPUT_TYPE_CAMERA;
752 return 0;
753}
754
755static int zr364xx_vidioc_g_input(struct file *file, void *priv,
756 unsigned int *i)
757{
758 *i = 0;
759 return 0;
760}
761
762static int zr364xx_vidioc_s_input(struct file *file, void *priv,
763 unsigned int i)
764{
765 if (i != 0)
766 return -EINVAL;
767 return 0;
768}
769
770static int zr364xx_vidioc_queryctrl(struct file *file, void *priv,
771 struct v4l2_queryctrl *c)
772{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300773 struct zr364xx_camera *cam;
774
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300775 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300776 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300777 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300778
779 switch (c->id) {
780 case V4L2_CID_BRIGHTNESS:
781 c->type = V4L2_CTRL_TYPE_INTEGER;
782 strcpy(c->name, "Brightness");
783 c->minimum = 0;
784 c->maximum = 127;
785 c->step = 1;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300786 c->default_value = cam->mode.brightness;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300787 c->flags = 0;
788 break;
789 default:
790 return -EINVAL;
791 }
792 return 0;
793}
794
795static int zr364xx_vidioc_s_ctrl(struct file *file, void *priv,
796 struct v4l2_control *c)
797{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300798 struct zr364xx_camera *cam;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300799 int temp;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300800
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300801 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300802 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300803 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300804
805 switch (c->id) {
806 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300807 cam->mode.brightness = c->value;
808 /* hardware brightness */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300809 send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
810 temp = (0x60 << 8) + 127 - cam->mode.brightness;
811 send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300812 break;
813 default:
814 return -EINVAL;
815 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300816
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300817 return 0;
818}
819
820static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv,
821 struct v4l2_control *c)
822{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300823 struct zr364xx_camera *cam;
824
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300825 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300826 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300827 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300828
829 switch (c->id) {
830 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300831 c->value = cam->mode.brightness;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300832 break;
833 default:
834 return -EINVAL;
835 }
836 return 0;
837}
838
Hans Verkuil78b526a2008-05-28 12:16:41 -0300839static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300840 void *priv, struct v4l2_fmtdesc *f)
841{
842 if (f->index > 0)
843 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300844 f->flags = V4L2_FMT_FLAG_COMPRESSED;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300845 strcpy(f->description, formats[0].name);
846 f->pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300847 return 0;
848}
849
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300850static char *decode_fourcc(__u32 pixelformat, char *buf)
851{
852 buf[0] = pixelformat & 0xff;
853 buf[1] = (pixelformat >> 8) & 0xff;
854 buf[2] = (pixelformat >> 16) & 0xff;
855 buf[3] = (pixelformat >> 24) & 0xff;
856 buf[4] = '\0';
857 return buf;
858}
859
Hans Verkuil78b526a2008-05-28 12:16:41 -0300860static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300861 struct v4l2_format *f)
862{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300863 struct zr364xx_camera *cam = video_drvdata(file);
864 char pixelformat_name[5];
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300865
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300866 if (cam == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300867 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300868
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300869 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
870 DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__,
871 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name));
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300872 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300873 }
874
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300875 if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) &&
876 !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) {
877 f->fmt.pix.width = 320;
878 f->fmt.pix.height = 240;
879 }
880
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300881 f->fmt.pix.field = V4L2_FIELD_NONE;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300882 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
883 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
884 f->fmt.pix.colorspace = 0;
885 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300886 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
887 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
888 f->fmt.pix.field);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300889 return 0;
890}
891
Hans Verkuil78b526a2008-05-28 12:16:41 -0300892static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300893 struct v4l2_format *f)
894{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300895 struct zr364xx_camera *cam;
896
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300897 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300898 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300899 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300900
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300901 f->fmt.pix.pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300902 f->fmt.pix.field = V4L2_FIELD_NONE;
903 f->fmt.pix.width = cam->width;
904 f->fmt.pix.height = cam->height;
905 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
906 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
907 f->fmt.pix.colorspace = 0;
908 f->fmt.pix.priv = 0;
909 return 0;
910}
911
Hans Verkuil78b526a2008-05-28 12:16:41 -0300912static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300913 struct v4l2_format *f)
914{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300915 struct zr364xx_camera *cam = video_drvdata(file);
916 struct videobuf_queue *q = &cam->vb_vidq;
917 char pixelformat_name[5];
918 int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f);
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300919 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300920
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300921 if (ret < 0)
922 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300923
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300924 mutex_lock(&q->vb_lock);
925
926 if (videobuf_queue_is_busy(&cam->vb_vidq)) {
927 DBG("%s queue busy\n", __func__);
928 ret = -EBUSY;
929 goto out;
930 }
931
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300932 if (res_check(cam)) {
933 DBG("%s can't change format after started\n", __func__);
934 ret = -EBUSY;
935 goto out;
936 }
937
938 cam->width = f->fmt.pix.width;
939 cam->height = f->fmt.pix.height;
940 dev_info(&cam->udev->dev, "%s: %dx%d mode selected\n", __func__,
941 cam->width, cam->height);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300942 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
943 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
944 f->fmt.pix.colorspace = 0;
945 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300946 cam->vb_vidq.field = f->fmt.pix.field;
947 cam->mode.color = V4L2_PIX_FMT_JPEG;
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300948
949 if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
950 mode = 1;
951 else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480)
952 mode = 2;
953 else
954 mode = 0;
955
956 m0d1[0] = mode;
957 m1[2].value = 0xf000 + mode;
958 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300959
960 /* special case for METHOD3, the modes are different */
961 if (cam->method == METHOD3) {
962 switch (mode) {
963 case 1:
964 m2[1].value = 0xf000 + 4;
965 break;
966 case 2:
967 m2[1].value = 0xf000 + 0;
968 break;
969 default:
970 m2[1].value = 0xf000 + 1;
971 break;
972 }
973 }
974
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300975 header2[437] = cam->height / 256;
976 header2[438] = cam->height % 256;
977 header2[439] = cam->width / 256;
978 header2[440] = cam->width % 256;
979
980 for (i = 0; init[cam->method][i].size != -1; i++) {
981 ret =
982 send_control_msg(cam->udev, 1, init[cam->method][i].value,
983 0, init[cam->method][i].bytes,
984 init[cam->method][i].size);
985 if (ret < 0) {
986 dev_err(&cam->udev->dev,
987 "error during resolution change sequence: %d\n", i);
988 goto out;
989 }
990 }
991
992 /* Added some delay here, since opening/closing the camera quickly,
993 * like Ekiga does during its startup, can crash the webcam
994 */
995 mdelay(100);
996 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300997 ret = 0;
998
999out:
1000 mutex_unlock(&q->vb_lock);
1001
1002 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
1003 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
1004 f->fmt.pix.field);
1005 return ret;
1006}
1007
1008static int zr364xx_vidioc_reqbufs(struct file *file, void *priv,
1009 struct v4l2_requestbuffers *p)
1010{
1011 int rc;
1012 struct zr364xx_camera *cam = video_drvdata(file);
1013 rc = videobuf_reqbufs(&cam->vb_vidq, p);
1014 return rc;
1015}
1016
1017static int zr364xx_vidioc_querybuf(struct file *file,
1018 void *priv,
1019 struct v4l2_buffer *p)
1020{
1021 int rc;
1022 struct zr364xx_camera *cam = video_drvdata(file);
1023 rc = videobuf_querybuf(&cam->vb_vidq, p);
1024 return rc;
1025}
1026
1027static int zr364xx_vidioc_qbuf(struct file *file,
1028 void *priv,
1029 struct v4l2_buffer *p)
1030{
1031 int rc;
1032 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001033 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001034 rc = videobuf_qbuf(&cam->vb_vidq, p);
1035 return rc;
1036}
1037
1038static int zr364xx_vidioc_dqbuf(struct file *file,
1039 void *priv,
1040 struct v4l2_buffer *p)
1041{
1042 int rc;
1043 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001044 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001045 rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK);
1046 return rc;
1047}
1048
1049static void read_pipe_completion(struct urb *purb)
1050{
1051 struct zr364xx_pipeinfo *pipe_info;
1052 struct zr364xx_camera *cam;
1053 int pipe;
1054
1055 pipe_info = purb->context;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001056 _DBG("%s %p, status %d\n", __func__, purb, purb->status);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001057 if (pipe_info == NULL) {
1058 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
1059 return;
1060 }
1061
1062 cam = pipe_info->cam;
1063 if (cam == NULL) {
1064 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
1065 return;
1066 }
1067
1068 /* if shutting down, do not resubmit, exit immediately */
1069 if (purb->status == -ESHUTDOWN) {
1070 DBG("%s, err shutdown\n", __func__);
1071 pipe_info->err_count++;
1072 return;
1073 }
1074
1075 if (pipe_info->state == 0) {
1076 DBG("exiting USB pipe\n");
1077 return;
1078 }
1079
1080 if (purb->actual_length < 0 ||
1081 purb->actual_length > pipe_info->transfer_size) {
1082 dev_err(&cam->udev->dev, "wrong number of bytes\n");
1083 return;
1084 }
1085
1086 if (purb->status == 0)
1087 zr364xx_read_video_callback(cam, pipe_info, purb);
1088 else {
1089 pipe_info->err_count++;
1090 DBG("%s: failed URB %d\n", __func__, purb->status);
1091 }
1092
1093 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1094
1095 /* reuse urb */
1096 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1097 pipe,
1098 pipe_info->transfer_buffer,
1099 pipe_info->transfer_size,
1100 read_pipe_completion, pipe_info);
1101
1102 if (pipe_info->state != 0) {
1103 purb->status = usb_submit_urb(pipe_info->stream_urb,
1104 GFP_ATOMIC);
1105
1106 if (purb->status)
1107 dev_err(&cam->udev->dev,
1108 "error submitting urb (error=%i)\n",
1109 purb->status);
1110 } else
1111 DBG("read pipe complete state 0\n");
1112}
1113
1114static int zr364xx_start_readpipe(struct zr364xx_camera *cam)
1115{
1116 int pipe;
1117 int retval;
1118 struct zr364xx_pipeinfo *pipe_info = cam->pipe;
1119 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1120 DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint);
1121
1122 pipe_info->state = 1;
1123 pipe_info->err_count = 0;
1124 pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
1125 if (!pipe_info->stream_urb) {
1126 dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n");
1127 return -ENOMEM;
1128 }
1129 /* transfer buffer allocated in board_init */
1130 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1131 pipe,
1132 pipe_info->transfer_buffer,
1133 pipe_info->transfer_size,
1134 read_pipe_completion, pipe_info);
1135
1136 DBG("submitting URB %p\n", pipe_info->stream_urb);
1137 retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
1138 if (retval) {
1139 printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n");
1140 return retval;
1141 }
1142
1143 return 0;
1144}
1145
1146static void zr364xx_stop_readpipe(struct zr364xx_camera *cam)
1147{
1148 struct zr364xx_pipeinfo *pipe_info;
1149
1150 if (cam == NULL) {
1151 printk(KERN_ERR KBUILD_MODNAME ": invalid device\n");
1152 return;
1153 }
1154 DBG("stop read pipe\n");
1155 pipe_info = cam->pipe;
1156 if (pipe_info) {
1157 if (pipe_info->state != 0)
1158 pipe_info->state = 0;
1159
1160 if (pipe_info->stream_urb) {
1161 /* cancel urb */
1162 usb_kill_urb(pipe_info->stream_urb);
1163 usb_free_urb(pipe_info->stream_urb);
1164 pipe_info->stream_urb = NULL;
1165 }
1166 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001167 return;
1168}
1169
1170/* starts acquisition process */
1171static int zr364xx_start_acquire(struct zr364xx_camera *cam)
1172{
1173 int j;
1174
1175 DBG("start acquire\n");
1176
1177 cam->last_frame = -1;
1178 cam->cur_frame = 0;
1179 for (j = 0; j < FRAMES; j++) {
1180 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1181 cam->buffer.frame[j].cur_size = 0;
1182 }
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -03001183 cam->b_acquire = 1;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001184 return 0;
1185}
1186
1187static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam)
1188{
1189 cam->b_acquire = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001190 return 0;
1191}
1192
1193static int zr364xx_vidioc_streamon(struct file *file, void *priv,
1194 enum v4l2_buf_type type)
1195{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001196 struct zr364xx_camera *cam = video_drvdata(file);
1197 int j;
1198 int res;
1199
1200 DBG("%s\n", __func__);
1201
1202 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1203 dev_err(&cam->udev->dev, "invalid fh type0\n");
1204 return -EINVAL;
1205 }
1206 if (cam->type != type) {
1207 dev_err(&cam->udev->dev, "invalid fh type1\n");
1208 return -EINVAL;
1209 }
1210
1211 if (!res_get(cam)) {
1212 dev_err(&cam->udev->dev, "stream busy\n");
1213 return -EBUSY;
1214 }
1215
1216 cam->last_frame = -1;
1217 cam->cur_frame = 0;
1218 cam->frame_count = 0;
1219 for (j = 0; j < FRAMES; j++) {
1220 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1221 cam->buffer.frame[j].cur_size = 0;
1222 }
1223 res = videobuf_streamon(&cam->vb_vidq);
1224 if (res == 0) {
1225 zr364xx_start_acquire(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001226 } else {
1227 res_free(cam);
1228 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001229 return res;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001230}
1231
1232static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
1233 enum v4l2_buf_type type)
1234{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001235 int res;
1236 struct zr364xx_camera *cam = video_drvdata(file);
1237
1238 DBG("%s\n", __func__);
1239 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1240 dev_err(&cam->udev->dev, "invalid fh type0\n");
1241 return -EINVAL;
1242 }
1243 if (cam->type != type) {
1244 dev_err(&cam->udev->dev, "invalid fh type1\n");
1245 return -EINVAL;
1246 }
1247 zr364xx_stop_acquire(cam);
1248 res = videobuf_streamoff(&cam->vb_vidq);
1249 if (res < 0)
1250 return res;
1251 res_free(cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001252 return 0;
1253}
1254
1255
1256/* open the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -03001257static int zr364xx_open(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001258{
1259 struct video_device *vdev = video_devdata(file);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001260 struct zr364xx_camera *cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001261 struct usb_device *udev = cam->udev;
1262 int i, err;
1263
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001264 DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001265
Hans Verkuila906f622012-06-02 07:16:49 -03001266 if (mutex_lock_interruptible(&cam->lock))
1267 return -ERESTARTSYS;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001268
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001269 if (cam->users) {
1270 err = -EBUSY;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001271 goto out;
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001272 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001273
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001274 for (i = 0; init[cam->method][i].size != -1; i++) {
1275 err =
1276 send_control_msg(udev, 1, init[cam->method][i].value,
1277 0, init[cam->method][i].bytes,
1278 init[cam->method][i].size);
1279 if (err < 0) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001280 dev_err(&cam->udev->dev,
1281 "error during open sequence: %d\n", i);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001282 goto out;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001283 }
1284 }
1285
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001286 cam->skip = 2;
1287 cam->users++;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001288 file->private_data = vdev;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001289 cam->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1290 cam->fmt = formats;
1291
1292 videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops,
1293 NULL, &cam->slock,
1294 cam->type,
1295 V4L2_FIELD_NONE,
Hans Verkuila906f622012-06-02 07:16:49 -03001296 sizeof(struct zr364xx_buffer), cam, &cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001297
1298 /* Added some delay here, since opening/closing the camera quickly,
1299 * like Ekiga does during its startup, can crash the webcam
1300 */
1301 mdelay(100);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001302 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001303
Antoine Jacquet69025c92008-08-18 17:09:53 -03001304out:
Hans Verkuila906f622012-06-02 07:16:49 -03001305 mutex_unlock(&cam->lock);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001306 DBG("%s: %d\n", __func__, err);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001307 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001308}
1309
Hans Verkuila906f622012-06-02 07:16:49 -03001310static void zr364xx_release(struct v4l2_device *v4l2_dev)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001311{
Hans Verkuila906f622012-06-02 07:16:49 -03001312 struct zr364xx_camera *cam =
1313 container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001314 unsigned long i;
1315
Hans Verkuila906f622012-06-02 07:16:49 -03001316 v4l2_device_unregister(&cam->v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001317
Hans Verkuila906f622012-06-02 07:16:49 -03001318 videobuf_mmap_free(&cam->vb_vidq);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001319
1320 /* release sys buffers */
1321 for (i = 0; i < FRAMES; i++) {
1322 if (cam->buffer.frame[i].lpvbits) {
1323 DBG("vfree %p\n", cam->buffer.frame[i].lpvbits);
1324 vfree(cam->buffer.frame[i].lpvbits);
1325 }
1326 cam->buffer.frame[i].lpvbits = NULL;
1327 }
1328
1329 /* release transfer buffer */
1330 kfree(cam->pipe->transfer_buffer);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001331 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001332}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001333
1334/* release the camera */
Hans Verkuila906f622012-06-02 07:16:49 -03001335static int zr364xx_close(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001336{
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001337 struct zr364xx_camera *cam;
1338 struct usb_device *udev;
Hans Verkuila906f622012-06-02 07:16:49 -03001339 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001340
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001341 DBG("%s\n", __func__);
1342 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001343
Hans Verkuila906f622012-06-02 07:16:49 -03001344 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001345 udev = cam->udev;
1346
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001347 /* turn off stream */
1348 if (res_check(cam)) {
1349 if (cam->b_acquire)
1350 zr364xx_stop_acquire(cam);
1351 videobuf_streamoff(&cam->vb_vidq);
1352 res_free(cam);
1353 }
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001354
1355 cam->users--;
1356 file->private_data = NULL;
1357
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001358 for (i = 0; i < 2; i++) {
Hans Verkuila906f622012-06-02 07:16:49 -03001359 send_control_msg(udev, 1, init[cam->method][i].value,
Roel Kluin7b808922009-08-11 08:10:25 -03001360 0, init[cam->method][i].bytes,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001361 init[cam->method][i].size);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001362 }
1363
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001364 /* Added some delay here, since opening/closing the camera quickly,
1365 * like Ekiga does during its startup, can crash the webcam
1366 */
1367 mdelay(100);
Hans Verkuila906f622012-06-02 07:16:49 -03001368 mutex_unlock(&cam->lock);
1369 return 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001370}
1371
1372
1373static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
1374{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001375 struct zr364xx_camera *cam = video_drvdata(file);
1376 int ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001377
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001378 if (cam == NULL) {
1379 DBG("%s: cam == NULL\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001380 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001381 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001382 DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001383
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001384 ret = videobuf_mmap_mapper(&cam->vb_vidq, vma);
1385
1386 DBG("vma start=0x%08lx, size=%ld, ret=%d\n",
1387 (unsigned long)vma->vm_start,
1388 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
1389 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001390}
1391
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001392static unsigned int zr364xx_poll(struct file *file,
1393 struct poll_table_struct *wait)
1394{
1395 struct zr364xx_camera *cam = video_drvdata(file);
1396 struct videobuf_queue *q = &cam->vb_vidq;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001397 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001398
1399 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1400 return POLLERR;
1401
1402 return videobuf_poll_stream(file, q, wait);
1403}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001404
Hans Verkuilbec43662008-12-30 06:58:20 -03001405static const struct v4l2_file_operations zr364xx_fops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001406 .owner = THIS_MODULE,
1407 .open = zr364xx_open,
Hans Verkuila906f622012-06-02 07:16:49 -03001408 .release = zr364xx_close,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001409 .read = zr364xx_read,
1410 .mmap = zr364xx_mmap,
Hans Verkuila906f622012-06-02 07:16:49 -03001411 .unlocked_ioctl = video_ioctl2,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001412 .poll = zr364xx_poll,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001413};
1414
Hans Verkuila3998102008-07-21 02:57:38 -03001415static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001416 .vidioc_querycap = zr364xx_vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001417 .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
1418 .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
1419 .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
1420 .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001421 .vidioc_enum_input = zr364xx_vidioc_enum_input,
1422 .vidioc_g_input = zr364xx_vidioc_g_input,
1423 .vidioc_s_input = zr364xx_vidioc_s_input,
1424 .vidioc_streamon = zr364xx_vidioc_streamon,
1425 .vidioc_streamoff = zr364xx_vidioc_streamoff,
1426 .vidioc_queryctrl = zr364xx_vidioc_queryctrl,
1427 .vidioc_g_ctrl = zr364xx_vidioc_g_ctrl,
1428 .vidioc_s_ctrl = zr364xx_vidioc_s_ctrl,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001429 .vidioc_reqbufs = zr364xx_vidioc_reqbufs,
1430 .vidioc_querybuf = zr364xx_vidioc_querybuf,
1431 .vidioc_qbuf = zr364xx_vidioc_qbuf,
1432 .vidioc_dqbuf = zr364xx_vidioc_dqbuf,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001433};
1434
Hans Verkuila3998102008-07-21 02:57:38 -03001435static struct video_device zr364xx_template = {
Hans Verkuila3998102008-07-21 02:57:38 -03001436 .name = DRIVER_DESC,
Hans Verkuila3998102008-07-21 02:57:38 -03001437 .fops = &zr364xx_fops,
1438 .ioctl_ops = &zr364xx_ioctl_ops,
Hans Verkuil2b992512012-06-02 06:32:48 -03001439 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03001440};
1441
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001442
1443
1444/*******************/
1445/* USB integration */
1446/*******************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001447static int zr364xx_board_init(struct zr364xx_camera *cam)
1448{
1449 struct zr364xx_pipeinfo *pipe = cam->pipe;
1450 unsigned long i;
1451
1452 DBG("board init: %p\n", cam);
1453 memset(pipe, 0, sizeof(*pipe));
1454 pipe->cam = cam;
1455 pipe->transfer_size = BUFFER_SIZE;
1456
1457 pipe->transfer_buffer = kzalloc(pipe->transfer_size,
1458 GFP_KERNEL);
1459 if (pipe->transfer_buffer == NULL) {
1460 DBG("out of memory!\n");
1461 return -ENOMEM;
1462 }
1463
1464 cam->b_acquire = 0;
1465 cam->frame_count = 0;
1466
1467 /*** start create system buffers ***/
1468 for (i = 0; i < FRAMES; i++) {
1469 /* always allocate maximum size for system buffers */
1470 cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE);
1471
1472 DBG("valloc %p, idx %lu, pdata %p\n",
1473 &cam->buffer.frame[i], i,
1474 cam->buffer.frame[i].lpvbits);
1475 if (cam->buffer.frame[i].lpvbits == NULL) {
1476 printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
1477 "Using less frames\n");
1478 break;
1479 }
1480 }
1481
1482 if (i == 0) {
1483 printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
1484 kfree(cam->pipe->transfer_buffer);
1485 cam->pipe->transfer_buffer = NULL;
1486 return -ENOMEM;
1487 } else
1488 cam->buffer.dwFrames = i;
1489
1490 /* make sure internal states are set */
1491 for (i = 0; i < FRAMES; i++) {
1492 cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE;
1493 cam->buffer.frame[i].cur_size = 0;
1494 }
1495
1496 cam->cur_frame = 0;
1497 cam->last_frame = -1;
1498 /*** end create system buffers ***/
1499
1500 /* start read pipe */
1501 zr364xx_start_readpipe(cam);
1502 DBG(": board initialized\n");
1503 return 0;
1504}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001505
1506static int zr364xx_probe(struct usb_interface *intf,
1507 const struct usb_device_id *id)
1508{
1509 struct usb_device *udev = interface_to_usbdev(intf);
1510 struct zr364xx_camera *cam = NULL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001511 struct usb_host_interface *iface_desc;
1512 struct usb_endpoint_descriptor *endpoint;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001513 int err;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001514 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001515
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001516 DBG("probing...\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001517
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001518 dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
1519 dev_info(&intf->dev, "model %04x:%04x detected\n",
1520 le16_to_cpu(udev->descriptor.idVendor),
1521 le16_to_cpu(udev->descriptor.idProduct));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001522
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001523 cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
1524 if (cam == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001525 dev_err(&udev->dev, "cam: out of memory !\n");
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001526 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001527 }
Hans Verkuila906f622012-06-02 07:16:49 -03001528
1529 cam->v4l2_dev.release = zr364xx_release;
1530 err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
1531 if (err < 0) {
1532 dev_err(&udev->dev, "couldn't register v4l2_device\n");
1533 kfree(cam);
1534 return err;
1535 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001536 /* save the init method used by this camera */
1537 cam->method = id->driver_info;
Hans Verkuila906f622012-06-02 07:16:49 -03001538 mutex_init(&cam->lock);
Hans Verkuil2b992512012-06-02 06:32:48 -03001539 cam->vdev = zr364xx_template;
Hans Verkuila906f622012-06-02 07:16:49 -03001540 cam->vdev.lock = &cam->lock;
1541 cam->vdev.v4l2_dev = &cam->v4l2_dev;
Hans Verkuil2b992512012-06-02 06:32:48 -03001542 video_set_drvdata(&cam->vdev, cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001543 if (debug)
Hans Verkuil2b992512012-06-02 06:32:48 -03001544 cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001545
1546 cam->udev = udev;
1547
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001548 switch (mode) {
1549 case 1:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001550 dev_info(&udev->dev, "160x120 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001551 cam->width = 160;
1552 cam->height = 120;
1553 break;
1554 case 2:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001555 dev_info(&udev->dev, "640x480 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001556 cam->width = 640;
1557 cam->height = 480;
1558 break;
1559 default:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001560 dev_info(&udev->dev, "320x240 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001561 cam->width = 320;
1562 cam->height = 240;
1563 break;
1564 }
1565
1566 m0d1[0] = mode;
1567 m1[2].value = 0xf000 + mode;
1568 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -03001569
1570 /* special case for METHOD3, the modes are different */
1571 if (cam->method == METHOD3) {
1572 switch (mode) {
1573 case 1:
1574 m2[1].value = 0xf000 + 4;
1575 break;
1576 case 2:
1577 m2[1].value = 0xf000 + 0;
1578 break;
1579 default:
1580 m2[1].value = 0xf000 + 1;
1581 break;
1582 }
1583 }
1584
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001585 header2[437] = cam->height / 256;
1586 header2[438] = cam->height % 256;
1587 header2[439] = cam->width / 256;
1588 header2[440] = cam->width % 256;
1589
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001590 cam->users = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001591 cam->nb = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001592 cam->mode.brightness = 64;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001593
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001594 DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf);
1595
1596 /* set up the endpoint information */
1597 iface_desc = intf->cur_altsetting;
1598 DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
1599 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1600 endpoint = &iface_desc->endpoint[i].desc;
1601 if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
1602 /* we found the bulk in endpoint */
1603 cam->read_endpoint = endpoint->bEndpointAddress;
1604 }
1605 }
1606
1607 if (!cam->read_endpoint) {
1608 dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
Hans Verkuila906f622012-06-02 07:16:49 -03001609 v4l2_device_unregister(&cam->v4l2_dev);
Julia Lawall0163b922011-08-12 08:40:08 -03001610 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001611 return -ENOMEM;
1612 }
1613
1614 /* v4l */
1615 INIT_LIST_HEAD(&cam->vidq.active);
1616 cam->vidq.cam = cam;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001617
1618 usb_set_intfdata(intf, cam);
1619
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001620 /* load zr364xx board specific */
1621 err = zr364xx_board_init(cam);
1622 if (err) {
Hans Verkuil2b992512012-06-02 06:32:48 -03001623 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001624 return err;
1625 }
1626
1627 spin_lock_init(&cam->slock);
1628
Hans Verkuil2b992512012-06-02 06:32:48 -03001629 err = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
1630 if (err) {
1631 dev_err(&udev->dev, "video_register_device failed\n");
Hans Verkuila906f622012-06-02 07:16:49 -03001632 v4l2_device_unregister(&cam->v4l2_dev);
Hans Verkuil2b992512012-06-02 06:32:48 -03001633 kfree(cam);
1634 return err;
1635 }
1636
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001637 dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
Hans Verkuil2b992512012-06-02 06:32:48 -03001638 video_device_node_name(&cam->vdev));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001639 return 0;
1640}
1641
1642
1643static void zr364xx_disconnect(struct usb_interface *intf)
1644{
1645 struct zr364xx_camera *cam = usb_get_intfdata(intf);
Hans Verkuila906f622012-06-02 07:16:49 -03001646
1647 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001648 usb_set_intfdata(intf, NULL);
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001649 dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
Hans Verkuila906f622012-06-02 07:16:49 -03001650 video_unregister_device(&cam->vdev);
1651 v4l2_device_disconnect(&cam->v4l2_dev);
1652
1653 /* stops the read pipe if it is running */
1654 if (cam->b_acquire)
1655 zr364xx_stop_acquire(cam);
1656
1657 zr364xx_stop_readpipe(cam);
1658 mutex_unlock(&cam->lock);
1659 v4l2_device_put(&cam->v4l2_dev);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001660}
1661
1662
1663
1664/**********************/
1665/* Module integration */
1666/**********************/
1667
1668static struct usb_driver zr364xx_driver = {
1669 .name = "zr364xx",
1670 .probe = zr364xx_probe,
1671 .disconnect = zr364xx_disconnect,
1672 .id_table = device_table
1673};
1674
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001675module_usb_driver(zr364xx_driver);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001676
1677MODULE_AUTHOR(DRIVER_AUTHOR);
1678MODULE_DESCRIPTION(DRIVER_DESC);
1679MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001680MODULE_VERSION(DRIVER_VERSION);