blob: bdf562dbaf02ab88a0ca883bb401ce97eacb67d4 [file] [log] [blame]
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001/*
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03002 * Zoran 364xx based USB webcam module version 0.73
Antoine Jacquetb7eee612007-04-27 12:30:59 -03003 *
4 * Allows you to use your USB webcam with V4L2 applications
5 * This is still in heavy developpement !
6 *
7 * Copyright (C) 2004 Antoine Jacquet <royale@zerezo.com>
8 * http://royale.zerezo.com/zr364xx/
9 *
10 * Heavily inspired by usb-skeleton.c, vicam.c, cpia.c and spca50x.c drivers
11 * V4L2 version inspired by meye.c driver
12 *
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030013 * Some video buffer code by Lamarque based on s2255drv.c and vivi.c drivers.
14 *
Antoine Jacquetb7eee612007-04-27 12:30:59 -030015 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30
Antoine Jacquetb7eee612007-04-27 12:30:59 -030031#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/usb.h>
34#include <linux/vmalloc.h>
35#include <linux/slab.h>
36#include <linux/proc_fs.h>
Antoine Jacquet2575f842007-03-05 06:32:29 -030037#include <linux/highmem.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030038#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030039#include <media/v4l2-ioctl.h>
Hans Verkuila906f622012-06-02 07:16:49 -030040#include <media/v4l2-device.h>
Hans Verkuil1fc21a12012-06-02 07:44:15 -030041#include <media/v4l2-ctrls.h>
Hans Verkuil5d317ab2012-06-02 07:57:29 -030042#include <media/v4l2-fh.h>
43#include <media/v4l2-event.h>
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030044#include <media/videobuf-vmalloc.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030045
46
47/* Version Information */
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030048#define DRIVER_VERSION "0.7.4"
Antoine Jacquetb7eee612007-04-27 12:30:59 -030049#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
50#define DRIVER_DESC "Zoran 364xx"
51
52
53/* Camera */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030054#define FRAMES 1
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -030055#define MAX_FRAME_SIZE 200000
Antoine Jacquetb7eee612007-04-27 12:30:59 -030056#define BUFFER_SIZE 0x1000
57#define CTRL_TIMEOUT 500
58
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030059#define ZR364XX_DEF_BUFS 4
60#define ZR364XX_READ_IDLE 0
61#define ZR364XX_READ_FRAME 1
Antoine Jacquetb7eee612007-04-27 12:30:59 -030062
63/* Debug macro */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030064#define DBG(fmt, args...) \
65 do { \
66 if (debug) { \
67 printk(KERN_INFO KBUILD_MODNAME " " fmt, ##args); \
68 } \
69 } while (0)
Antoine Jacquetb7eee612007-04-27 12:30:59 -030070
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -030071/*#define FULL_DEBUG 1*/
72#ifdef FULL_DEBUG
73#define _DBG DBG
74#else
75#define _DBG(fmt, args...)
76#endif
77
Antoine Jacquetb7eee612007-04-27 12:30:59 -030078/* Init methods, need to find nicer names for these
79 * the exact names of the chipsets would be the best if someone finds it */
80#define METHOD0 0
81#define METHOD1 1
82#define METHOD2 2
Antoine Jacquet08135ba2009-12-27 18:22:05 -030083#define METHOD3 3
Antoine Jacquetb7eee612007-04-27 12:30:59 -030084
85
86/* Module parameters */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030087static int debug;
88static int mode;
Antoine Jacquetb7eee612007-04-27 12:30:59 -030089
90
91/* Module parameters interface */
92module_param(debug, int, 0644);
93MODULE_PARM_DESC(debug, "Debug level");
94module_param(mode, int, 0644);
95MODULE_PARM_DESC(mode, "0 = 320x240, 1 = 160x120, 2 = 640x480");
96
97
98/* Devices supported by this driver
99 * .driver_info contains the init method used by the camera */
100static struct usb_device_id device_table[] = {
101 {USB_DEVICE(0x08ca, 0x0109), .driver_info = METHOD0 },
102 {USB_DEVICE(0x041e, 0x4024), .driver_info = METHOD0 },
103 {USB_DEVICE(0x0d64, 0x0108), .driver_info = METHOD0 },
104 {USB_DEVICE(0x0546, 0x3187), .driver_info = METHOD0 },
105 {USB_DEVICE(0x0d64, 0x3108), .driver_info = METHOD0 },
106 {USB_DEVICE(0x0595, 0x4343), .driver_info = METHOD0 },
107 {USB_DEVICE(0x0bb0, 0x500d), .driver_info = METHOD0 },
108 {USB_DEVICE(0x0feb, 0x2004), .driver_info = METHOD0 },
109 {USB_DEVICE(0x055f, 0xb500), .driver_info = METHOD0 },
110 {USB_DEVICE(0x08ca, 0x2062), .driver_info = METHOD2 },
111 {USB_DEVICE(0x052b, 0x1a18), .driver_info = METHOD1 },
112 {USB_DEVICE(0x04c8, 0x0729), .driver_info = METHOD0 },
113 {USB_DEVICE(0x04f2, 0xa208), .driver_info = METHOD0 },
114 {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 },
115 {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
116 {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
Antoine Jacquetbebeaea2007-06-25 16:00:34 -0300117 {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
Antoine Jacquet71c04472008-01-25 22:01:53 -0300118 {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
Antoine Jacquetc0e0aff2008-01-25 22:03:10 -0300119 {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300120 {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD3 },
Antoine Jacquet9018f6c2009-11-19 22:35:38 -0300121 {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 },
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300122 {} /* Terminating entry */
123};
124
125MODULE_DEVICE_TABLE(usb, device_table);
126
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300127/* frame structure */
128struct zr364xx_framei {
129 unsigned long ulState; /* ulState:ZR364XX_READ_IDLE,
130 ZR364XX_READ_FRAME */
131 void *lpvbits; /* image data */
132 unsigned long cur_size; /* current data copied to it */
133};
134
135/* image buffer structure */
136struct zr364xx_bufferi {
137 unsigned long dwFrames; /* number of frames in buffer */
138 struct zr364xx_framei frame[FRAMES]; /* array of FRAME structures */
139};
140
141struct zr364xx_dmaqueue {
142 struct list_head active;
143 struct zr364xx_camera *cam;
144};
145
146struct zr364xx_pipeinfo {
147 u32 transfer_size;
148 u8 *transfer_buffer;
149 u32 state;
150 void *stream_urb;
151 void *cam; /* back pointer to zr364xx_camera struct */
152 u32 err_count;
153 u32 idx;
154};
155
156struct zr364xx_fmt {
157 char *name;
158 u32 fourcc;
159 int depth;
160};
161
162/* image formats. */
163static const struct zr364xx_fmt formats[] = {
164 {
165 .name = "JPG",
166 .fourcc = V4L2_PIX_FMT_JPEG,
167 .depth = 24
168 }
169};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300170
171/* Camera stuff */
172struct zr364xx_camera {
173 struct usb_device *udev; /* save off the usb device pointer */
174 struct usb_interface *interface;/* the interface for this device */
Hans Verkuila906f622012-06-02 07:16:49 -0300175 struct v4l2_device v4l2_dev;
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300176 struct v4l2_ctrl_handler ctrl_handler;
Hans Verkuil2b992512012-06-02 06:32:48 -0300177 struct video_device vdev; /* v4l video device */
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300178 int nb;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300179 struct zr364xx_bufferi buffer;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300180 int skip;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300181 int width;
182 int height;
183 int method;
184 struct mutex lock;
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300185 int users;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300186
187 spinlock_t slock;
188 struct zr364xx_dmaqueue vidq;
189 int resources;
190 int last_frame;
191 int cur_frame;
192 unsigned long frame_count;
193 int b_acquire;
194 struct zr364xx_pipeinfo pipe[1];
195
196 u8 read_endpoint;
197
198 const struct zr364xx_fmt *fmt;
199 struct videobuf_queue vb_vidq;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300200};
201
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300202/* buffer for one video frame */
203struct zr364xx_buffer {
204 /* common v4l buffer stuff -- must be first */
205 struct videobuf_buffer vb;
206 const struct zr364xx_fmt *fmt;
207};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300208
209/* function used to send initialisation commands to the camera */
210static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
211 u16 index, unsigned char *cp, u16 size)
212{
213 int status;
214
215 unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
216 if (!transfer_buffer) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300217 dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300218 return -ENOMEM;
219 }
220
221 memcpy(transfer_buffer, cp, size);
222
223 status = usb_control_msg(udev,
224 usb_sndctrlpipe(udev, 0),
225 request,
226 USB_DIR_OUT | USB_TYPE_VENDOR |
227 USB_RECIP_DEVICE, value, index,
228 transfer_buffer, size, CTRL_TIMEOUT);
229
230 kfree(transfer_buffer);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300231 return status;
232}
233
234
235/* Control messages sent to the camera to initialize it
236 * and launch the capture */
237typedef struct {
238 unsigned int value;
239 unsigned int size;
240 unsigned char *bytes;
241} message;
242
243/* method 0 */
244static unsigned char m0d1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
245static unsigned char m0d2[] = { 0, 0, 0, 0, 0, 0 };
246static unsigned char m0d3[] = { 0, 0 };
247static message m0[] = {
248 {0x1f30, 0, NULL},
249 {0xd000, 0, NULL},
250 {0x3370, sizeof(m0d1), m0d1},
251 {0x2000, 0, NULL},
252 {0x2f0f, 0, NULL},
253 {0x2610, sizeof(m0d2), m0d2},
254 {0xe107, 0, NULL},
255 {0x2502, 0, NULL},
256 {0x1f70, 0, NULL},
257 {0xd000, 0, NULL},
258 {0x9a01, sizeof(m0d3), m0d3},
259 {-1, -1, NULL}
260};
261
262/* method 1 */
263static unsigned char m1d1[] = { 0xff, 0xff };
264static unsigned char m1d2[] = { 0x00, 0x00 };
265static message m1[] = {
266 {0x1f30, 0, NULL},
267 {0xd000, 0, NULL},
268 {0xf000, 0, NULL},
269 {0x2000, 0, NULL},
270 {0x2f0f, 0, NULL},
271 {0x2650, 0, NULL},
272 {0xe107, 0, NULL},
273 {0x2502, sizeof(m1d1), m1d1},
274 {0x1f70, 0, NULL},
275 {0xd000, 0, NULL},
276 {0xd000, 0, NULL},
277 {0xd000, 0, NULL},
278 {0x9a01, sizeof(m1d2), m1d2},
279 {-1, -1, NULL}
280};
281
282/* method 2 */
283static unsigned char m2d1[] = { 0xff, 0xff };
284static message m2[] = {
285 {0x1f30, 0, NULL},
286 {0xf000, 0, NULL},
287 {0x2000, 0, NULL},
288 {0x2f0f, 0, NULL},
289 {0x2650, 0, NULL},
290 {0xe107, 0, NULL},
291 {0x2502, sizeof(m2d1), m2d1},
292 {0x1f70, 0, NULL},
293 {-1, -1, NULL}
294};
295
296/* init table */
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300297static message *init[4] = { m0, m1, m2, m2 };
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300298
299
300/* JPEG static data in header (Huffman table, etc) */
301static unsigned char header1[] = {
302 0xFF, 0xD8,
303 /*
304 0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F',
305 0x00, 0x01, 0x01, 0x00, 0x33, 0x8A, 0x00, 0x00, 0x33, 0x88,
306 */
307 0xFF, 0xDB, 0x00, 0x84
308};
309static unsigned char header2[] = {
310 0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
311 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
313 0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
314 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
315 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
316 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
317 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33,
318 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25,
319 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
320 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,
321 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
322 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
323 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
324 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
325 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
326 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
327 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
328 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
329 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC4, 0x00, 0x1F,
330 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
331 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
332 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0xC4, 0x00, 0xB5,
333 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
334 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,
335 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
336 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
337 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
338 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27,
339 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
340 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57,
341 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
342 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84,
343 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
344 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
345 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
346 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
347 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,
348 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
349 0xF8, 0xF9, 0xFA, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01,
350 0x40, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
351 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
352 0x00, 0x3F, 0x00
353};
354static unsigned char header3;
355
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300356/* ------------------------------------------------------------------
357 Videobuf operations
358 ------------------------------------------------------------------*/
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300359
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300360static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
361 unsigned int *size)
362{
363 struct zr364xx_camera *cam = vq->priv_data;
364
365 *size = cam->width * cam->height * (cam->fmt->depth >> 3);
366
367 if (*count == 0)
368 *count = ZR364XX_DEF_BUFS;
369
Andreas Bombedab7e312010-03-21 16:02:45 -0300370 if (*size * *count > ZR364XX_DEF_BUFS * 1024 * 1024)
371 *count = (ZR364XX_DEF_BUFS * 1024 * 1024) / *size;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300372
373 return 0;
374}
375
376static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf)
377{
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300378 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300379
380 if (in_interrupt())
381 BUG();
382
383 videobuf_vmalloc_free(&buf->vb);
384 buf->vb.state = VIDEOBUF_NEEDS_INIT;
385}
386
387static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
388 enum v4l2_field field)
389{
390 struct zr364xx_camera *cam = vq->priv_data;
391 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
392 vb);
393 int rc;
394
395 DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ?
396 cam->fmt->name : "");
397 if (cam->fmt == NULL)
398 return -EINVAL;
399
400 buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3);
401
402 if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) {
403 DBG("invalid buffer prepare\n");
404 return -EINVAL;
405 }
406
407 buf->fmt = cam->fmt;
408 buf->vb.width = cam->width;
409 buf->vb.height = cam->height;
410 buf->vb.field = field;
411
412 if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
413 rc = videobuf_iolock(vq, &buf->vb, NULL);
414 if (rc < 0)
415 goto fail;
416 }
417
418 buf->vb.state = VIDEOBUF_PREPARED;
419 return 0;
420fail:
421 free_buffer(vq, buf);
422 return rc;
423}
424
425static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
426{
427 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
428 vb);
429 struct zr364xx_camera *cam = vq->priv_data;
430
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300431 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300432
433 buf->vb.state = VIDEOBUF_QUEUED;
434 list_add_tail(&buf->vb.queue, &cam->vidq.active);
435}
436
437static void buffer_release(struct videobuf_queue *vq,
438 struct videobuf_buffer *vb)
439{
440 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
441 vb);
442
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300443 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300444 free_buffer(vq, buf);
445}
446
447static struct videobuf_queue_ops zr364xx_video_qops = {
448 .buf_setup = buffer_setup,
449 .buf_prepare = buffer_prepare,
450 .buf_queue = buffer_queue,
451 .buf_release = buffer_release,
452};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300453
454/********************/
455/* V4L2 integration */
456/********************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300457static int zr364xx_vidioc_streamon(struct file *file, void *priv,
458 enum v4l2_buf_type type);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300459
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300460static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300461 loff_t * ppos)
462{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300463 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila906f622012-06-02 07:16:49 -0300464 int err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300465
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300466 _DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300467
468 if (!buf)
469 return -EINVAL;
470
471 if (!count)
472 return -EINVAL;
473
Hans Verkuila906f622012-06-02 07:16:49 -0300474 if (mutex_lock_interruptible(&cam->lock))
475 return -ERESTARTSYS;
476
Hans Verkuil5d317ab2012-06-02 07:57:29 -0300477 if (zr364xx_vidioc_streamon(file, cam, V4L2_BUF_TYPE_VIDEO_CAPTURE) == 0) {
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300478 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));
Hans Verkuildf462902012-06-02 07:50:30 -0300734 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300735 V4L2_CAP_READWRITE |
736 V4L2_CAP_STREAMING;
Hans Verkuildf462902012-06-02 07:50:30 -0300737 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300738
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300739 return 0;
740}
741
742static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
743 struct v4l2_input *i)
744{
745 if (i->index != 0)
746 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300747 strcpy(i->name, DRIVER_DESC " Camera");
748 i->type = V4L2_INPUT_TYPE_CAMERA;
749 return 0;
750}
751
752static int zr364xx_vidioc_g_input(struct file *file, void *priv,
753 unsigned int *i)
754{
755 *i = 0;
756 return 0;
757}
758
759static int zr364xx_vidioc_s_input(struct file *file, void *priv,
760 unsigned int i)
761{
762 if (i != 0)
763 return -EINVAL;
764 return 0;
765}
766
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300767static int zr364xx_s_ctrl(struct v4l2_ctrl *ctrl)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300768{
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300769 struct zr364xx_camera *cam =
770 container_of(ctrl->handler, struct zr364xx_camera, ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300771 int temp;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300772
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300773 switch (ctrl->id) {
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300774 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300775 /* hardware brightness */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300776 send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300777 temp = (0x60 << 8) + 127 - ctrl->val;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300778 send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300779 break;
780 default:
781 return -EINVAL;
782 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300783
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300784 return 0;
785}
786
Hans Verkuil78b526a2008-05-28 12:16:41 -0300787static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300788 void *priv, struct v4l2_fmtdesc *f)
789{
790 if (f->index > 0)
791 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300792 f->flags = V4L2_FMT_FLAG_COMPRESSED;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300793 strcpy(f->description, formats[0].name);
794 f->pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300795 return 0;
796}
797
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300798static char *decode_fourcc(__u32 pixelformat, char *buf)
799{
800 buf[0] = pixelformat & 0xff;
801 buf[1] = (pixelformat >> 8) & 0xff;
802 buf[2] = (pixelformat >> 16) & 0xff;
803 buf[3] = (pixelformat >> 24) & 0xff;
804 buf[4] = '\0';
805 return buf;
806}
807
Hans Verkuil78b526a2008-05-28 12:16:41 -0300808static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300809 struct v4l2_format *f)
810{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300811 struct zr364xx_camera *cam = video_drvdata(file);
812 char pixelformat_name[5];
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300813
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300814 if (cam == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300815 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300816
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300817 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
818 DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__,
819 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name));
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300820 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300821 }
822
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300823 if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) &&
824 !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) {
825 f->fmt.pix.width = 320;
826 f->fmt.pix.height = 240;
827 }
828
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300829 f->fmt.pix.field = V4L2_FIELD_NONE;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300830 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
831 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300832 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300833 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300834 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
835 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
836 f->fmt.pix.field);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300837 return 0;
838}
839
Hans Verkuil78b526a2008-05-28 12:16:41 -0300840static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300841 struct v4l2_format *f)
842{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300843 struct zr364xx_camera *cam;
844
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300845 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300846 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300847 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300848
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300849 f->fmt.pix.pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300850 f->fmt.pix.field = V4L2_FIELD_NONE;
851 f->fmt.pix.width = cam->width;
852 f->fmt.pix.height = cam->height;
853 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
854 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300855 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300856 f->fmt.pix.priv = 0;
857 return 0;
858}
859
Hans Verkuil78b526a2008-05-28 12:16:41 -0300860static int zr364xx_vidioc_s_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 struct videobuf_queue *q = &cam->vb_vidq;
865 char pixelformat_name[5];
866 int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f);
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300867 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300868
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300869 if (ret < 0)
870 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300871
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300872 mutex_lock(&q->vb_lock);
873
874 if (videobuf_queue_is_busy(&cam->vb_vidq)) {
875 DBG("%s queue busy\n", __func__);
876 ret = -EBUSY;
877 goto out;
878 }
879
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300880 if (res_check(cam)) {
881 DBG("%s can't change format after started\n", __func__);
882 ret = -EBUSY;
883 goto out;
884 }
885
886 cam->width = f->fmt.pix.width;
887 cam->height = f->fmt.pix.height;
888 dev_info(&cam->udev->dev, "%s: %dx%d mode selected\n", __func__,
889 cam->width, cam->height);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300890 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
891 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300892 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300893 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300894 cam->vb_vidq.field = f->fmt.pix.field;
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300895
896 if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
897 mode = 1;
898 else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480)
899 mode = 2;
900 else
901 mode = 0;
902
903 m0d1[0] = mode;
904 m1[2].value = 0xf000 + mode;
905 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300906
907 /* special case for METHOD3, the modes are different */
908 if (cam->method == METHOD3) {
909 switch (mode) {
910 case 1:
911 m2[1].value = 0xf000 + 4;
912 break;
913 case 2:
914 m2[1].value = 0xf000 + 0;
915 break;
916 default:
917 m2[1].value = 0xf000 + 1;
918 break;
919 }
920 }
921
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300922 header2[437] = cam->height / 256;
923 header2[438] = cam->height % 256;
924 header2[439] = cam->width / 256;
925 header2[440] = cam->width % 256;
926
927 for (i = 0; init[cam->method][i].size != -1; i++) {
928 ret =
929 send_control_msg(cam->udev, 1, init[cam->method][i].value,
930 0, init[cam->method][i].bytes,
931 init[cam->method][i].size);
932 if (ret < 0) {
933 dev_err(&cam->udev->dev,
934 "error during resolution change sequence: %d\n", i);
935 goto out;
936 }
937 }
938
939 /* Added some delay here, since opening/closing the camera quickly,
940 * like Ekiga does during its startup, can crash the webcam
941 */
942 mdelay(100);
943 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300944 ret = 0;
945
946out:
947 mutex_unlock(&q->vb_lock);
948
949 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
950 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
951 f->fmt.pix.field);
952 return ret;
953}
954
955static int zr364xx_vidioc_reqbufs(struct file *file, void *priv,
956 struct v4l2_requestbuffers *p)
957{
958 int rc;
959 struct zr364xx_camera *cam = video_drvdata(file);
960 rc = videobuf_reqbufs(&cam->vb_vidq, p);
961 return rc;
962}
963
964static int zr364xx_vidioc_querybuf(struct file *file,
965 void *priv,
966 struct v4l2_buffer *p)
967{
968 int rc;
969 struct zr364xx_camera *cam = video_drvdata(file);
970 rc = videobuf_querybuf(&cam->vb_vidq, p);
971 return rc;
972}
973
974static int zr364xx_vidioc_qbuf(struct file *file,
975 void *priv,
976 struct v4l2_buffer *p)
977{
978 int rc;
979 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300980 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300981 rc = videobuf_qbuf(&cam->vb_vidq, p);
982 return rc;
983}
984
985static int zr364xx_vidioc_dqbuf(struct file *file,
986 void *priv,
987 struct v4l2_buffer *p)
988{
989 int rc;
990 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300991 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300992 rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK);
993 return rc;
994}
995
996static void read_pipe_completion(struct urb *purb)
997{
998 struct zr364xx_pipeinfo *pipe_info;
999 struct zr364xx_camera *cam;
1000 int pipe;
1001
1002 pipe_info = purb->context;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001003 _DBG("%s %p, status %d\n", __func__, purb, purb->status);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001004 if (pipe_info == NULL) {
1005 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
1006 return;
1007 }
1008
1009 cam = pipe_info->cam;
1010 if (cam == NULL) {
1011 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
1012 return;
1013 }
1014
1015 /* if shutting down, do not resubmit, exit immediately */
1016 if (purb->status == -ESHUTDOWN) {
1017 DBG("%s, err shutdown\n", __func__);
1018 pipe_info->err_count++;
1019 return;
1020 }
1021
1022 if (pipe_info->state == 0) {
1023 DBG("exiting USB pipe\n");
1024 return;
1025 }
1026
1027 if (purb->actual_length < 0 ||
1028 purb->actual_length > pipe_info->transfer_size) {
1029 dev_err(&cam->udev->dev, "wrong number of bytes\n");
1030 return;
1031 }
1032
1033 if (purb->status == 0)
1034 zr364xx_read_video_callback(cam, pipe_info, purb);
1035 else {
1036 pipe_info->err_count++;
1037 DBG("%s: failed URB %d\n", __func__, purb->status);
1038 }
1039
1040 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1041
1042 /* reuse urb */
1043 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1044 pipe,
1045 pipe_info->transfer_buffer,
1046 pipe_info->transfer_size,
1047 read_pipe_completion, pipe_info);
1048
1049 if (pipe_info->state != 0) {
1050 purb->status = usb_submit_urb(pipe_info->stream_urb,
1051 GFP_ATOMIC);
1052
1053 if (purb->status)
1054 dev_err(&cam->udev->dev,
1055 "error submitting urb (error=%i)\n",
1056 purb->status);
1057 } else
1058 DBG("read pipe complete state 0\n");
1059}
1060
1061static int zr364xx_start_readpipe(struct zr364xx_camera *cam)
1062{
1063 int pipe;
1064 int retval;
1065 struct zr364xx_pipeinfo *pipe_info = cam->pipe;
1066 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1067 DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint);
1068
1069 pipe_info->state = 1;
1070 pipe_info->err_count = 0;
1071 pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
1072 if (!pipe_info->stream_urb) {
1073 dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n");
1074 return -ENOMEM;
1075 }
1076 /* transfer buffer allocated in board_init */
1077 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1078 pipe,
1079 pipe_info->transfer_buffer,
1080 pipe_info->transfer_size,
1081 read_pipe_completion, pipe_info);
1082
1083 DBG("submitting URB %p\n", pipe_info->stream_urb);
1084 retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
1085 if (retval) {
1086 printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n");
1087 return retval;
1088 }
1089
1090 return 0;
1091}
1092
1093static void zr364xx_stop_readpipe(struct zr364xx_camera *cam)
1094{
1095 struct zr364xx_pipeinfo *pipe_info;
1096
1097 if (cam == NULL) {
1098 printk(KERN_ERR KBUILD_MODNAME ": invalid device\n");
1099 return;
1100 }
1101 DBG("stop read pipe\n");
1102 pipe_info = cam->pipe;
1103 if (pipe_info) {
1104 if (pipe_info->state != 0)
1105 pipe_info->state = 0;
1106
1107 if (pipe_info->stream_urb) {
1108 /* cancel urb */
1109 usb_kill_urb(pipe_info->stream_urb);
1110 usb_free_urb(pipe_info->stream_urb);
1111 pipe_info->stream_urb = NULL;
1112 }
1113 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001114 return;
1115}
1116
1117/* starts acquisition process */
1118static int zr364xx_start_acquire(struct zr364xx_camera *cam)
1119{
1120 int j;
1121
1122 DBG("start acquire\n");
1123
1124 cam->last_frame = -1;
1125 cam->cur_frame = 0;
1126 for (j = 0; j < FRAMES; j++) {
1127 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1128 cam->buffer.frame[j].cur_size = 0;
1129 }
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -03001130 cam->b_acquire = 1;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001131 return 0;
1132}
1133
1134static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam)
1135{
1136 cam->b_acquire = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001137 return 0;
1138}
1139
1140static int zr364xx_vidioc_streamon(struct file *file, void *priv,
1141 enum v4l2_buf_type type)
1142{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001143 struct zr364xx_camera *cam = video_drvdata(file);
1144 int j;
1145 int res;
1146
1147 DBG("%s\n", __func__);
1148
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001149 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001150 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001151
1152 if (!res_get(cam)) {
1153 dev_err(&cam->udev->dev, "stream busy\n");
1154 return -EBUSY;
1155 }
1156
1157 cam->last_frame = -1;
1158 cam->cur_frame = 0;
1159 cam->frame_count = 0;
1160 for (j = 0; j < FRAMES; j++) {
1161 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1162 cam->buffer.frame[j].cur_size = 0;
1163 }
1164 res = videobuf_streamon(&cam->vb_vidq);
1165 if (res == 0) {
1166 zr364xx_start_acquire(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001167 } else {
1168 res_free(cam);
1169 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001170 return res;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001171}
1172
1173static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
1174 enum v4l2_buf_type type)
1175{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001176 int res;
1177 struct zr364xx_camera *cam = video_drvdata(file);
1178
1179 DBG("%s\n", __func__);
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001180 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001181 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001182 zr364xx_stop_acquire(cam);
1183 res = videobuf_streamoff(&cam->vb_vidq);
1184 if (res < 0)
1185 return res;
1186 res_free(cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001187 return 0;
1188}
1189
1190
1191/* open the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -03001192static int zr364xx_open(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001193{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001194 struct zr364xx_camera *cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001195 struct usb_device *udev = cam->udev;
1196 int i, err;
1197
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001198 DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001199
Hans Verkuila906f622012-06-02 07:16:49 -03001200 if (mutex_lock_interruptible(&cam->lock))
1201 return -ERESTARTSYS;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001202
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001203 if (cam->users) {
1204 err = -EBUSY;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001205 goto out;
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001206 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001207
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001208 err = v4l2_fh_open(file);
1209 if (err)
1210 goto out;
1211
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001212 for (i = 0; init[cam->method][i].size != -1; i++) {
1213 err =
1214 send_control_msg(udev, 1, init[cam->method][i].value,
1215 0, init[cam->method][i].bytes,
1216 init[cam->method][i].size);
1217 if (err < 0) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001218 dev_err(&cam->udev->dev,
1219 "error during open sequence: %d\n", i);
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001220 v4l2_fh_release(file);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001221 goto out;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001222 }
1223 }
1224
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001225 cam->skip = 2;
1226 cam->users++;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001227 cam->fmt = formats;
1228
1229 videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops,
1230 NULL, &cam->slock,
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001231 V4L2_BUF_TYPE_VIDEO_CAPTURE,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001232 V4L2_FIELD_NONE,
Hans Verkuila906f622012-06-02 07:16:49 -03001233 sizeof(struct zr364xx_buffer), cam, &cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001234
1235 /* Added some delay here, since opening/closing the camera quickly,
1236 * like Ekiga does during its startup, can crash the webcam
1237 */
1238 mdelay(100);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001239 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001240
Antoine Jacquet69025c92008-08-18 17:09:53 -03001241out:
Hans Verkuila906f622012-06-02 07:16:49 -03001242 mutex_unlock(&cam->lock);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001243 DBG("%s: %d\n", __func__, err);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001244 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001245}
1246
Hans Verkuila906f622012-06-02 07:16:49 -03001247static void zr364xx_release(struct v4l2_device *v4l2_dev)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001248{
Hans Verkuila906f622012-06-02 07:16:49 -03001249 struct zr364xx_camera *cam =
1250 container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001251 unsigned long i;
1252
Hans Verkuila906f622012-06-02 07:16:49 -03001253 v4l2_device_unregister(&cam->v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001254
Hans Verkuila906f622012-06-02 07:16:49 -03001255 videobuf_mmap_free(&cam->vb_vidq);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001256
1257 /* release sys buffers */
1258 for (i = 0; i < FRAMES; i++) {
1259 if (cam->buffer.frame[i].lpvbits) {
1260 DBG("vfree %p\n", cam->buffer.frame[i].lpvbits);
1261 vfree(cam->buffer.frame[i].lpvbits);
1262 }
1263 cam->buffer.frame[i].lpvbits = NULL;
1264 }
1265
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001266 v4l2_ctrl_handler_free(&cam->ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001267 /* release transfer buffer */
1268 kfree(cam->pipe->transfer_buffer);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001269 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001270}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001271
1272/* release the camera */
Hans Verkuila906f622012-06-02 07:16:49 -03001273static int zr364xx_close(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001274{
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001275 struct zr364xx_camera *cam;
1276 struct usb_device *udev;
Hans Verkuila906f622012-06-02 07:16:49 -03001277 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001278
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001279 DBG("%s\n", __func__);
1280 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001281
Hans Verkuila906f622012-06-02 07:16:49 -03001282 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001283 udev = cam->udev;
1284
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001285 /* turn off stream */
1286 if (res_check(cam)) {
1287 if (cam->b_acquire)
1288 zr364xx_stop_acquire(cam);
1289 videobuf_streamoff(&cam->vb_vidq);
1290 res_free(cam);
1291 }
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001292
1293 cam->users--;
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001294
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001295 for (i = 0; i < 2; i++) {
Hans Verkuila906f622012-06-02 07:16:49 -03001296 send_control_msg(udev, 1, init[cam->method][i].value,
Roel Kluin7b808922009-08-11 08:10:25 -03001297 0, init[cam->method][i].bytes,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001298 init[cam->method][i].size);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001299 }
1300
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001301 /* Added some delay here, since opening/closing the camera quickly,
1302 * like Ekiga does during its startup, can crash the webcam
1303 */
1304 mdelay(100);
Hans Verkuila906f622012-06-02 07:16:49 -03001305 mutex_unlock(&cam->lock);
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001306 return v4l2_fh_release(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001307}
1308
1309
1310static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
1311{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001312 struct zr364xx_camera *cam = video_drvdata(file);
1313 int ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001314
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001315 if (cam == NULL) {
1316 DBG("%s: cam == NULL\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001317 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001318 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001319 DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001320
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001321 ret = videobuf_mmap_mapper(&cam->vb_vidq, vma);
1322
1323 DBG("vma start=0x%08lx, size=%ld, ret=%d\n",
1324 (unsigned long)vma->vm_start,
1325 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
1326 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001327}
1328
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001329static unsigned int zr364xx_poll(struct file *file,
1330 struct poll_table_struct *wait)
1331{
1332 struct zr364xx_camera *cam = video_drvdata(file);
1333 struct videobuf_queue *q = &cam->vb_vidq;
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001334 unsigned res = v4l2_ctrl_poll(file, wait);
1335
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001336 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001337
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001338 return res | videobuf_poll_stream(file, q, wait);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001339}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001340
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001341static const struct v4l2_ctrl_ops zr364xx_ctrl_ops = {
1342 .s_ctrl = zr364xx_s_ctrl,
1343};
1344
Hans Verkuilbec43662008-12-30 06:58:20 -03001345static const struct v4l2_file_operations zr364xx_fops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001346 .owner = THIS_MODULE,
1347 .open = zr364xx_open,
Hans Verkuila906f622012-06-02 07:16:49 -03001348 .release = zr364xx_close,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001349 .read = zr364xx_read,
1350 .mmap = zr364xx_mmap,
Hans Verkuila906f622012-06-02 07:16:49 -03001351 .unlocked_ioctl = video_ioctl2,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001352 .poll = zr364xx_poll,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001353};
1354
Hans Verkuila3998102008-07-21 02:57:38 -03001355static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001356 .vidioc_querycap = zr364xx_vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001357 .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
1358 .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
1359 .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
1360 .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001361 .vidioc_enum_input = zr364xx_vidioc_enum_input,
1362 .vidioc_g_input = zr364xx_vidioc_g_input,
1363 .vidioc_s_input = zr364xx_vidioc_s_input,
1364 .vidioc_streamon = zr364xx_vidioc_streamon,
1365 .vidioc_streamoff = zr364xx_vidioc_streamoff,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001366 .vidioc_reqbufs = zr364xx_vidioc_reqbufs,
1367 .vidioc_querybuf = zr364xx_vidioc_querybuf,
1368 .vidioc_qbuf = zr364xx_vidioc_qbuf,
1369 .vidioc_dqbuf = zr364xx_vidioc_dqbuf,
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001370 .vidioc_log_status = v4l2_ctrl_log_status,
1371 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1372 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001373};
1374
Hans Verkuila3998102008-07-21 02:57:38 -03001375static struct video_device zr364xx_template = {
Hans Verkuila3998102008-07-21 02:57:38 -03001376 .name = DRIVER_DESC,
Hans Verkuila3998102008-07-21 02:57:38 -03001377 .fops = &zr364xx_fops,
1378 .ioctl_ops = &zr364xx_ioctl_ops,
Hans Verkuil2b992512012-06-02 06:32:48 -03001379 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03001380};
1381
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001382
1383
1384/*******************/
1385/* USB integration */
1386/*******************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001387static int zr364xx_board_init(struct zr364xx_camera *cam)
1388{
1389 struct zr364xx_pipeinfo *pipe = cam->pipe;
1390 unsigned long i;
1391
1392 DBG("board init: %p\n", cam);
1393 memset(pipe, 0, sizeof(*pipe));
1394 pipe->cam = cam;
1395 pipe->transfer_size = BUFFER_SIZE;
1396
1397 pipe->transfer_buffer = kzalloc(pipe->transfer_size,
1398 GFP_KERNEL);
1399 if (pipe->transfer_buffer == NULL) {
1400 DBG("out of memory!\n");
1401 return -ENOMEM;
1402 }
1403
1404 cam->b_acquire = 0;
1405 cam->frame_count = 0;
1406
1407 /*** start create system buffers ***/
1408 for (i = 0; i < FRAMES; i++) {
1409 /* always allocate maximum size for system buffers */
1410 cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE);
1411
1412 DBG("valloc %p, idx %lu, pdata %p\n",
1413 &cam->buffer.frame[i], i,
1414 cam->buffer.frame[i].lpvbits);
1415 if (cam->buffer.frame[i].lpvbits == NULL) {
1416 printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
1417 "Using less frames\n");
1418 break;
1419 }
1420 }
1421
1422 if (i == 0) {
1423 printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
1424 kfree(cam->pipe->transfer_buffer);
1425 cam->pipe->transfer_buffer = NULL;
1426 return -ENOMEM;
1427 } else
1428 cam->buffer.dwFrames = i;
1429
1430 /* make sure internal states are set */
1431 for (i = 0; i < FRAMES; i++) {
1432 cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE;
1433 cam->buffer.frame[i].cur_size = 0;
1434 }
1435
1436 cam->cur_frame = 0;
1437 cam->last_frame = -1;
1438 /*** end create system buffers ***/
1439
1440 /* start read pipe */
1441 zr364xx_start_readpipe(cam);
1442 DBG(": board initialized\n");
1443 return 0;
1444}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001445
1446static int zr364xx_probe(struct usb_interface *intf,
1447 const struct usb_device_id *id)
1448{
1449 struct usb_device *udev = interface_to_usbdev(intf);
1450 struct zr364xx_camera *cam = NULL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001451 struct usb_host_interface *iface_desc;
1452 struct usb_endpoint_descriptor *endpoint;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001453 struct v4l2_ctrl_handler *hdl;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001454 int err;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001455 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001456
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001457 DBG("probing...\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001458
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001459 dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
1460 dev_info(&intf->dev, "model %04x:%04x detected\n",
1461 le16_to_cpu(udev->descriptor.idVendor),
1462 le16_to_cpu(udev->descriptor.idProduct));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001463
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001464 cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
1465 if (cam == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001466 dev_err(&udev->dev, "cam: out of memory !\n");
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001467 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001468 }
Hans Verkuila906f622012-06-02 07:16:49 -03001469
1470 cam->v4l2_dev.release = zr364xx_release;
1471 err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
1472 if (err < 0) {
1473 dev_err(&udev->dev, "couldn't register v4l2_device\n");
1474 kfree(cam);
1475 return err;
1476 }
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001477 hdl = &cam->ctrl_handler;
1478 v4l2_ctrl_handler_init(hdl, 1);
1479 v4l2_ctrl_new_std(hdl, &zr364xx_ctrl_ops,
1480 V4L2_CID_BRIGHTNESS, 0, 127, 1, 64);
1481 if (hdl->error) {
1482 err = hdl->error;
1483 dev_err(&udev->dev, "couldn't register control\n");
1484 goto fail;
1485 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001486 /* save the init method used by this camera */
1487 cam->method = id->driver_info;
Hans Verkuila906f622012-06-02 07:16:49 -03001488 mutex_init(&cam->lock);
Hans Verkuil2b992512012-06-02 06:32:48 -03001489 cam->vdev = zr364xx_template;
Hans Verkuila906f622012-06-02 07:16:49 -03001490 cam->vdev.lock = &cam->lock;
1491 cam->vdev.v4l2_dev = &cam->v4l2_dev;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001492 cam->vdev.ctrl_handler = &cam->ctrl_handler;
Hans Verkuil2b992512012-06-02 06:32:48 -03001493 video_set_drvdata(&cam->vdev, cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001494 if (debug)
Hans Verkuil2b992512012-06-02 06:32:48 -03001495 cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001496
1497 cam->udev = udev;
1498
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001499 switch (mode) {
1500 case 1:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001501 dev_info(&udev->dev, "160x120 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001502 cam->width = 160;
1503 cam->height = 120;
1504 break;
1505 case 2:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001506 dev_info(&udev->dev, "640x480 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001507 cam->width = 640;
1508 cam->height = 480;
1509 break;
1510 default:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001511 dev_info(&udev->dev, "320x240 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001512 cam->width = 320;
1513 cam->height = 240;
1514 break;
1515 }
1516
1517 m0d1[0] = mode;
1518 m1[2].value = 0xf000 + mode;
1519 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -03001520
1521 /* special case for METHOD3, the modes are different */
1522 if (cam->method == METHOD3) {
1523 switch (mode) {
1524 case 1:
1525 m2[1].value = 0xf000 + 4;
1526 break;
1527 case 2:
1528 m2[1].value = 0xf000 + 0;
1529 break;
1530 default:
1531 m2[1].value = 0xf000 + 1;
1532 break;
1533 }
1534 }
1535
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001536 header2[437] = cam->height / 256;
1537 header2[438] = cam->height % 256;
1538 header2[439] = cam->width / 256;
1539 header2[440] = cam->width % 256;
1540
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001541 cam->users = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001542 cam->nb = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001543
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001544 DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf);
1545
1546 /* set up the endpoint information */
1547 iface_desc = intf->cur_altsetting;
1548 DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
1549 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1550 endpoint = &iface_desc->endpoint[i].desc;
1551 if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
1552 /* we found the bulk in endpoint */
1553 cam->read_endpoint = endpoint->bEndpointAddress;
1554 }
1555 }
1556
1557 if (!cam->read_endpoint) {
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001558 err = -ENOMEM;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001559 dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001560 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001561 }
1562
1563 /* v4l */
1564 INIT_LIST_HEAD(&cam->vidq.active);
1565 cam->vidq.cam = cam;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001566
1567 usb_set_intfdata(intf, cam);
1568
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001569 /* load zr364xx board specific */
1570 err = zr364xx_board_init(cam);
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001571 if (!err)
1572 err = v4l2_ctrl_handler_setup(hdl);
1573 if (err)
1574 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001575
1576 spin_lock_init(&cam->slock);
1577
Hans Verkuil2b992512012-06-02 06:32:48 -03001578 err = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
1579 if (err) {
1580 dev_err(&udev->dev, "video_register_device failed\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001581 goto fail;
Hans Verkuil2b992512012-06-02 06:32:48 -03001582 }
1583
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001584 dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
Hans Verkuil2b992512012-06-02 06:32:48 -03001585 video_device_node_name(&cam->vdev));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001586 return 0;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001587
1588fail:
1589 v4l2_ctrl_handler_free(hdl);
1590 v4l2_device_unregister(&cam->v4l2_dev);
1591 kfree(cam);
1592 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001593}
1594
1595
1596static void zr364xx_disconnect(struct usb_interface *intf)
1597{
1598 struct zr364xx_camera *cam = usb_get_intfdata(intf);
Hans Verkuila906f622012-06-02 07:16:49 -03001599
1600 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001601 usb_set_intfdata(intf, NULL);
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001602 dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
Hans Verkuila906f622012-06-02 07:16:49 -03001603 video_unregister_device(&cam->vdev);
1604 v4l2_device_disconnect(&cam->v4l2_dev);
1605
1606 /* stops the read pipe if it is running */
1607 if (cam->b_acquire)
1608 zr364xx_stop_acquire(cam);
1609
1610 zr364xx_stop_readpipe(cam);
1611 mutex_unlock(&cam->lock);
1612 v4l2_device_put(&cam->v4l2_dev);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001613}
1614
1615
1616
1617/**********************/
1618/* Module integration */
1619/**********************/
1620
1621static struct usb_driver zr364xx_driver = {
1622 .name = "zr364xx",
1623 .probe = zr364xx_probe,
1624 .disconnect = zr364xx_disconnect,
1625 .id_table = device_table
1626};
1627
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001628module_usb_driver(zr364xx_driver);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001629
1630MODULE_AUTHOR(DRIVER_AUTHOR);
1631MODULE_DESCRIPTION(DRIVER_DESC);
1632MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001633MODULE_VERSION(DRIVER_VERSION);