blob: 74d56df3347f59329ec6c4538023592c863bc1ac [file] [log] [blame]
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001/*
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03002 * Zoran 364xx based USB webcam module version 0.73
Antoine Jacquetb7eee612007-04-27 12:30:59 -03003 *
4 * Allows you to use your USB webcam with V4L2 applications
5 * This is still in heavy developpement !
6 *
7 * Copyright (C) 2004 Antoine Jacquet <royale@zerezo.com>
8 * http://royale.zerezo.com/zr364xx/
9 *
10 * Heavily inspired by usb-skeleton.c, vicam.c, cpia.c and spca50x.c drivers
11 * V4L2 version inspired by meye.c driver
12 *
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030013 * Some video buffer code by Lamarque based on s2255drv.c and vivi.c drivers.
14 *
Antoine Jacquetb7eee612007-04-27 12:30:59 -030015 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30
Antoine Jacquetb7eee612007-04-27 12:30:59 -030031#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/usb.h>
34#include <linux/vmalloc.h>
35#include <linux/slab.h>
36#include <linux/proc_fs.h>
Antoine Jacquet2575f842007-03-05 06:32:29 -030037#include <linux/highmem.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030038#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030039#include <media/v4l2-ioctl.h>
Hans Verkuila906f622012-06-02 07:16:49 -030040#include <media/v4l2-device.h>
Hans Verkuil1fc21a12012-06-02 07:44:15 -030041#include <media/v4l2-ctrls.h>
Hans Verkuil5d317ab2012-06-02 07:57:29 -030042#include <media/v4l2-fh.h>
43#include <media/v4l2-event.h>
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030044#include <media/videobuf-vmalloc.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030045
46
47/* Version Information */
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030048#define DRIVER_VERSION "0.7.4"
Antoine Jacquetb7eee612007-04-27 12:30:59 -030049#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
50#define DRIVER_DESC "Zoran 364xx"
51
52
53/* Camera */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030054#define FRAMES 1
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -030055#define MAX_FRAME_SIZE 200000
Antoine Jacquetb7eee612007-04-27 12:30:59 -030056#define BUFFER_SIZE 0x1000
57#define CTRL_TIMEOUT 500
58
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030059#define ZR364XX_DEF_BUFS 4
60#define ZR364XX_READ_IDLE 0
61#define ZR364XX_READ_FRAME 1
Antoine Jacquetb7eee612007-04-27 12:30:59 -030062
63/* Debug macro */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030064#define DBG(fmt, args...) \
65 do { \
66 if (debug) { \
67 printk(KERN_INFO KBUILD_MODNAME " " fmt, ##args); \
68 } \
69 } while (0)
Antoine Jacquetb7eee612007-04-27 12:30:59 -030070
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -030071/*#define FULL_DEBUG 1*/
72#ifdef FULL_DEBUG
73#define _DBG DBG
74#else
75#define _DBG(fmt, args...)
76#endif
77
Antoine Jacquetb7eee612007-04-27 12:30:59 -030078/* Init methods, need to find nicer names for these
79 * the exact names of the chipsets would be the best if someone finds it */
80#define METHOD0 0
81#define METHOD1 1
82#define METHOD2 2
Antoine Jacquet08135ba2009-12-27 18:22:05 -030083#define METHOD3 3
Antoine Jacquetb7eee612007-04-27 12:30:59 -030084
85
86/* Module parameters */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030087static int debug;
88static int mode;
Antoine Jacquetb7eee612007-04-27 12:30:59 -030089
90
91/* Module parameters interface */
92module_param(debug, int, 0644);
93MODULE_PARM_DESC(debug, "Debug level");
94module_param(mode, int, 0644);
95MODULE_PARM_DESC(mode, "0 = 320x240, 1 = 160x120, 2 = 640x480");
96
97
98/* Devices supported by this driver
99 * .driver_info contains the init method used by the camera */
100static struct usb_device_id device_table[] = {
101 {USB_DEVICE(0x08ca, 0x0109), .driver_info = METHOD0 },
102 {USB_DEVICE(0x041e, 0x4024), .driver_info = METHOD0 },
103 {USB_DEVICE(0x0d64, 0x0108), .driver_info = METHOD0 },
104 {USB_DEVICE(0x0546, 0x3187), .driver_info = METHOD0 },
105 {USB_DEVICE(0x0d64, 0x3108), .driver_info = METHOD0 },
106 {USB_DEVICE(0x0595, 0x4343), .driver_info = METHOD0 },
107 {USB_DEVICE(0x0bb0, 0x500d), .driver_info = METHOD0 },
108 {USB_DEVICE(0x0feb, 0x2004), .driver_info = METHOD0 },
109 {USB_DEVICE(0x055f, 0xb500), .driver_info = METHOD0 },
110 {USB_DEVICE(0x08ca, 0x2062), .driver_info = METHOD2 },
111 {USB_DEVICE(0x052b, 0x1a18), .driver_info = METHOD1 },
112 {USB_DEVICE(0x04c8, 0x0729), .driver_info = METHOD0 },
113 {USB_DEVICE(0x04f2, 0xa208), .driver_info = METHOD0 },
114 {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 },
115 {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
116 {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
Antoine Jacquetbebeaea2007-06-25 16:00:34 -0300117 {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
Antoine Jacquet71c04472008-01-25 22:01:53 -0300118 {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
Antoine Jacquetc0e0aff2008-01-25 22:03:10 -0300119 {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300120 {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD3 },
Antoine Jacquet9018f6c2009-11-19 22:35:38 -0300121 {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 },
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300122 {} /* Terminating entry */
123};
124
125MODULE_DEVICE_TABLE(usb, device_table);
126
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300127/* frame structure */
128struct zr364xx_framei {
129 unsigned long ulState; /* ulState:ZR364XX_READ_IDLE,
130 ZR364XX_READ_FRAME */
131 void *lpvbits; /* image data */
132 unsigned long cur_size; /* current data copied to it */
133};
134
135/* image buffer structure */
136struct zr364xx_bufferi {
137 unsigned long dwFrames; /* number of frames in buffer */
138 struct zr364xx_framei frame[FRAMES]; /* array of FRAME structures */
139};
140
141struct zr364xx_dmaqueue {
142 struct list_head active;
143 struct zr364xx_camera *cam;
144};
145
146struct zr364xx_pipeinfo {
147 u32 transfer_size;
148 u8 *transfer_buffer;
149 u32 state;
150 void *stream_urb;
151 void *cam; /* back pointer to zr364xx_camera struct */
152 u32 err_count;
153 u32 idx;
154};
155
156struct zr364xx_fmt {
157 char *name;
158 u32 fourcc;
159 int depth;
160};
161
162/* image formats. */
163static const struct zr364xx_fmt formats[] = {
164 {
165 .name = "JPG",
166 .fourcc = V4L2_PIX_FMT_JPEG,
167 .depth = 24
168 }
169};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300170
171/* Camera stuff */
172struct zr364xx_camera {
173 struct usb_device *udev; /* save off the usb device pointer */
174 struct usb_interface *interface;/* the interface for this device */
Hans Verkuila906f622012-06-02 07:16:49 -0300175 struct v4l2_device v4l2_dev;
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300176 struct v4l2_ctrl_handler ctrl_handler;
Hans Verkuil2b992512012-06-02 06:32:48 -0300177 struct video_device vdev; /* v4l video device */
Hans Verkuila0657292012-06-02 08:50:31 -0300178 struct v4l2_fh *owner; /* owns the streaming */
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300179 int nb;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300180 struct zr364xx_bufferi buffer;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300181 int skip;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300182 int width;
183 int height;
184 int method;
185 struct mutex lock;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300186
187 spinlock_t slock;
188 struct zr364xx_dmaqueue vidq;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300189 int last_frame;
190 int cur_frame;
191 unsigned long frame_count;
192 int b_acquire;
193 struct zr364xx_pipeinfo pipe[1];
194
195 u8 read_endpoint;
196
197 const struct zr364xx_fmt *fmt;
198 struct videobuf_queue vb_vidq;
Hans Verkuil587a5762012-06-08 06:43:59 -0300199 bool was_streaming;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300200};
201
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300202/* buffer for one video frame */
203struct zr364xx_buffer {
204 /* common v4l buffer stuff -- must be first */
205 struct videobuf_buffer vb;
206 const struct zr364xx_fmt *fmt;
207};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300208
209/* function used to send initialisation commands to the camera */
210static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
211 u16 index, unsigned char *cp, u16 size)
212{
213 int status;
214
215 unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
216 if (!transfer_buffer) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300217 dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300218 return -ENOMEM;
219 }
220
221 memcpy(transfer_buffer, cp, size);
222
223 status = usb_control_msg(udev,
224 usb_sndctrlpipe(udev, 0),
225 request,
226 USB_DIR_OUT | USB_TYPE_VENDOR |
227 USB_RECIP_DEVICE, value, index,
228 transfer_buffer, size, CTRL_TIMEOUT);
229
230 kfree(transfer_buffer);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300231 return status;
232}
233
234
235/* Control messages sent to the camera to initialize it
236 * and launch the capture */
237typedef struct {
238 unsigned int value;
239 unsigned int size;
240 unsigned char *bytes;
241} message;
242
243/* method 0 */
244static unsigned char m0d1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
245static unsigned char m0d2[] = { 0, 0, 0, 0, 0, 0 };
246static unsigned char m0d3[] = { 0, 0 };
247static message m0[] = {
248 {0x1f30, 0, NULL},
249 {0xd000, 0, NULL},
250 {0x3370, sizeof(m0d1), m0d1},
251 {0x2000, 0, NULL},
252 {0x2f0f, 0, NULL},
253 {0x2610, sizeof(m0d2), m0d2},
254 {0xe107, 0, NULL},
255 {0x2502, 0, NULL},
256 {0x1f70, 0, NULL},
257 {0xd000, 0, NULL},
258 {0x9a01, sizeof(m0d3), m0d3},
259 {-1, -1, NULL}
260};
261
262/* method 1 */
263static unsigned char m1d1[] = { 0xff, 0xff };
264static unsigned char m1d2[] = { 0x00, 0x00 };
265static message m1[] = {
266 {0x1f30, 0, NULL},
267 {0xd000, 0, NULL},
268 {0xf000, 0, NULL},
269 {0x2000, 0, NULL},
270 {0x2f0f, 0, NULL},
271 {0x2650, 0, NULL},
272 {0xe107, 0, NULL},
273 {0x2502, sizeof(m1d1), m1d1},
274 {0x1f70, 0, NULL},
275 {0xd000, 0, NULL},
276 {0xd000, 0, NULL},
277 {0xd000, 0, NULL},
278 {0x9a01, sizeof(m1d2), m1d2},
279 {-1, -1, NULL}
280};
281
282/* method 2 */
283static unsigned char m2d1[] = { 0xff, 0xff };
284static message m2[] = {
285 {0x1f30, 0, NULL},
286 {0xf000, 0, NULL},
287 {0x2000, 0, NULL},
288 {0x2f0f, 0, NULL},
289 {0x2650, 0, NULL},
290 {0xe107, 0, NULL},
291 {0x2502, sizeof(m2d1), m2d1},
292 {0x1f70, 0, NULL},
293 {-1, -1, NULL}
294};
295
296/* init table */
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300297static message *init[4] = { m0, m1, m2, m2 };
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300298
299
300/* JPEG static data in header (Huffman table, etc) */
301static unsigned char header1[] = {
302 0xFF, 0xD8,
303 /*
304 0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F',
305 0x00, 0x01, 0x01, 0x00, 0x33, 0x8A, 0x00, 0x00, 0x33, 0x88,
306 */
307 0xFF, 0xDB, 0x00, 0x84
308};
309static unsigned char header2[] = {
310 0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
311 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
313 0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
314 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
315 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
316 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
317 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33,
318 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25,
319 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
320 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,
321 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
322 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
323 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
324 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
325 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
326 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
327 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
328 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
329 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC4, 0x00, 0x1F,
330 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
331 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
332 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0xC4, 0x00, 0xB5,
333 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
334 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,
335 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
336 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
337 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
338 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27,
339 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
340 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57,
341 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
342 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84,
343 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
344 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
345 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
346 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
347 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,
348 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
349 0xF8, 0xF9, 0xFA, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01,
350 0x40, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
351 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
352 0x00, 0x3F, 0x00
353};
354static unsigned char header3;
355
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300356/* ------------------------------------------------------------------
357 Videobuf operations
358 ------------------------------------------------------------------*/
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300359
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300360static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
361 unsigned int *size)
362{
363 struct zr364xx_camera *cam = vq->priv_data;
364
365 *size = cam->width * cam->height * (cam->fmt->depth >> 3);
366
367 if (*count == 0)
368 *count = ZR364XX_DEF_BUFS;
369
Andreas Bombedab7e312010-03-21 16:02:45 -0300370 if (*size * *count > ZR364XX_DEF_BUFS * 1024 * 1024)
371 *count = (ZR364XX_DEF_BUFS * 1024 * 1024) / *size;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300372
373 return 0;
374}
375
376static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf)
377{
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300378 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300379
380 if (in_interrupt())
381 BUG();
382
383 videobuf_vmalloc_free(&buf->vb);
384 buf->vb.state = VIDEOBUF_NEEDS_INIT;
385}
386
387static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
388 enum v4l2_field field)
389{
390 struct zr364xx_camera *cam = vq->priv_data;
391 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
392 vb);
393 int rc;
394
395 DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ?
396 cam->fmt->name : "");
397 if (cam->fmt == NULL)
398 return -EINVAL;
399
400 buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3);
401
402 if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) {
403 DBG("invalid buffer prepare\n");
404 return -EINVAL;
405 }
406
407 buf->fmt = cam->fmt;
408 buf->vb.width = cam->width;
409 buf->vb.height = cam->height;
410 buf->vb.field = field;
411
412 if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
413 rc = videobuf_iolock(vq, &buf->vb, NULL);
414 if (rc < 0)
415 goto fail;
416 }
417
418 buf->vb.state = VIDEOBUF_PREPARED;
419 return 0;
420fail:
421 free_buffer(vq, buf);
422 return rc;
423}
424
425static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
426{
427 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
428 vb);
429 struct zr364xx_camera *cam = vq->priv_data;
430
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300431 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300432
433 buf->vb.state = VIDEOBUF_QUEUED;
434 list_add_tail(&buf->vb.queue, &cam->vidq.active);
435}
436
437static void buffer_release(struct videobuf_queue *vq,
438 struct videobuf_buffer *vb)
439{
440 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
441 vb);
442
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300443 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300444 free_buffer(vq, buf);
445}
446
447static struct videobuf_queue_ops zr364xx_video_qops = {
448 .buf_setup = buffer_setup,
449 .buf_prepare = buffer_prepare,
450 .buf_queue = buffer_queue,
451 .buf_release = buffer_release,
452};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300453
454/********************/
455/* V4L2 integration */
456/********************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300457static int zr364xx_vidioc_streamon(struct file *file, void *priv,
458 enum v4l2_buf_type type);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300459
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300460static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300461 loff_t * ppos)
462{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300463 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila906f622012-06-02 07:16:49 -0300464 int err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300465
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300466 _DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300467
468 if (!buf)
469 return -EINVAL;
470
471 if (!count)
472 return -EINVAL;
473
Hans Verkuila906f622012-06-02 07:16:49 -0300474 if (mutex_lock_interruptible(&cam->lock))
475 return -ERESTARTSYS;
476
Hans Verkuila0657292012-06-02 08:50:31 -0300477 err = zr364xx_vidioc_streamon(file, file->private_data,
478 V4L2_BUF_TYPE_VIDEO_CAPTURE);
479 if (err == 0) {
480 DBG("%s: reading %d bytes at pos %d.\n", __func__,
481 (int) count, (int) *ppos);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300482
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300483 /* NoMan Sux ! */
Hans Verkuila906f622012-06-02 07:16:49 -0300484 err = videobuf_read_one(&cam->vb_vidq, buf, count, ppos,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300485 file->f_flags & O_NONBLOCK);
486 }
Hans Verkuila906f622012-06-02 07:16:49 -0300487 mutex_unlock(&cam->lock);
488 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300489}
490
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300491/* video buffer vmalloc implementation based partly on VIVI driver which is
492 * Copyright (c) 2006 by
493 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
494 * Ted Walther <ted--a.t--enumera.com>
495 * John Sokol <sokol--a.t--videotechnology.com>
496 * http://v4l.videotechnology.com/
497 *
498 */
499static void zr364xx_fillbuff(struct zr364xx_camera *cam,
500 struct zr364xx_buffer *buf,
501 int jpgsize)
502{
503 int pos = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300504 const char *tmpbuf;
505 char *vbuf = videobuf_to_vmalloc(&buf->vb);
506 unsigned long last_frame;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300507
508 if (!vbuf)
509 return;
510
511 last_frame = cam->last_frame;
512 if (last_frame != -1) {
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300513 tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits;
514 switch (buf->fmt->fourcc) {
515 case V4L2_PIX_FMT_JPEG:
516 buf->vb.size = jpgsize;
517 memcpy(vbuf, tmpbuf, buf->vb.size);
518 break;
519 default:
520 printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n");
521 }
522 cam->last_frame = -1;
523 } else {
524 printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n");
525 return;
526 }
527 DBG("%s: Buffer 0x%08lx size= %d\n", __func__,
528 (unsigned long)vbuf, pos);
529 /* tell v4l buffer was filled */
530
531 buf->vb.field_count = cam->frame_count * 2;
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300532 v4l2_get_timestamp(&buf->vb.ts);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300533 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);
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300560 v4l2_get_timestamp(&buf->vb.ts);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300561 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
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300701static int zr364xx_vidioc_querycap(struct file *file, void *priv,
702 struct v4l2_capability *cap)
703{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300704 struct zr364xx_camera *cam = video_drvdata(file);
705
706 strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
707 strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
708 strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
709 sizeof(cap->bus_info));
Hans Verkuildf462902012-06-02 07:50:30 -0300710 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300711 V4L2_CAP_READWRITE |
712 V4L2_CAP_STREAMING;
Hans Verkuildf462902012-06-02 07:50:30 -0300713 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300714
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300715 return 0;
716}
717
718static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
719 struct v4l2_input *i)
720{
721 if (i->index != 0)
722 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300723 strcpy(i->name, DRIVER_DESC " Camera");
724 i->type = V4L2_INPUT_TYPE_CAMERA;
725 return 0;
726}
727
728static int zr364xx_vidioc_g_input(struct file *file, void *priv,
729 unsigned int *i)
730{
731 *i = 0;
732 return 0;
733}
734
735static int zr364xx_vidioc_s_input(struct file *file, void *priv,
736 unsigned int i)
737{
738 if (i != 0)
739 return -EINVAL;
740 return 0;
741}
742
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300743static int zr364xx_s_ctrl(struct v4l2_ctrl *ctrl)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300744{
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300745 struct zr364xx_camera *cam =
746 container_of(ctrl->handler, struct zr364xx_camera, ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300747 int temp;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300748
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300749 switch (ctrl->id) {
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300750 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300751 /* hardware brightness */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300752 send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300753 temp = (0x60 << 8) + 127 - ctrl->val;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300754 send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300755 break;
756 default:
757 return -EINVAL;
758 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300759
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300760 return 0;
761}
762
Hans Verkuil78b526a2008-05-28 12:16:41 -0300763static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300764 void *priv, struct v4l2_fmtdesc *f)
765{
766 if (f->index > 0)
767 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300768 f->flags = V4L2_FMT_FLAG_COMPRESSED;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300769 strcpy(f->description, formats[0].name);
770 f->pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300771 return 0;
772}
773
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300774static char *decode_fourcc(__u32 pixelformat, char *buf)
775{
776 buf[0] = pixelformat & 0xff;
777 buf[1] = (pixelformat >> 8) & 0xff;
778 buf[2] = (pixelformat >> 16) & 0xff;
779 buf[3] = (pixelformat >> 24) & 0xff;
780 buf[4] = '\0';
781 return buf;
782}
783
Hans Verkuil78b526a2008-05-28 12:16:41 -0300784static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300785 struct v4l2_format *f)
786{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300787 struct zr364xx_camera *cam = video_drvdata(file);
788 char pixelformat_name[5];
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300789
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300790 if (cam == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300791 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300792
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300793 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
794 DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__,
795 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name));
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300796 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300797 }
798
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300799 if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) &&
800 !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) {
801 f->fmt.pix.width = 320;
802 f->fmt.pix.height = 240;
803 }
804
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300805 f->fmt.pix.field = V4L2_FIELD_NONE;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300806 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
807 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300808 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300809 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300810 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
811 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
812 f->fmt.pix.field);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300813 return 0;
814}
815
Hans Verkuil78b526a2008-05-28 12:16:41 -0300816static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300817 struct v4l2_format *f)
818{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300819 struct zr364xx_camera *cam;
820
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300821 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300822 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300823 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300824
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300825 f->fmt.pix.pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300826 f->fmt.pix.field = V4L2_FIELD_NONE;
827 f->fmt.pix.width = cam->width;
828 f->fmt.pix.height = cam->height;
829 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
830 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300831 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300832 f->fmt.pix.priv = 0;
833 return 0;
834}
835
Hans Verkuil78b526a2008-05-28 12:16:41 -0300836static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300837 struct v4l2_format *f)
838{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300839 struct zr364xx_camera *cam = video_drvdata(file);
840 struct videobuf_queue *q = &cam->vb_vidq;
841 char pixelformat_name[5];
842 int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f);
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300843 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300844
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300845 if (ret < 0)
846 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300847
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300848 mutex_lock(&q->vb_lock);
849
850 if (videobuf_queue_is_busy(&cam->vb_vidq)) {
851 DBG("%s queue busy\n", __func__);
852 ret = -EBUSY;
853 goto out;
854 }
855
Hans Verkuila0657292012-06-02 08:50:31 -0300856 if (cam->owner) {
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300857 DBG("%s can't change format after started\n", __func__);
858 ret = -EBUSY;
859 goto out;
860 }
861
862 cam->width = f->fmt.pix.width;
863 cam->height = f->fmt.pix.height;
Hans Verkuila0657292012-06-02 08:50:31 -0300864 DBG("%s: %dx%d mode selected\n", __func__,
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300865 cam->width, cam->height);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300866 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
867 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300868 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300869 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300870 cam->vb_vidq.field = f->fmt.pix.field;
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300871
872 if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
873 mode = 1;
874 else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480)
875 mode = 2;
876 else
877 mode = 0;
878
879 m0d1[0] = mode;
880 m1[2].value = 0xf000 + mode;
881 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300882
883 /* special case for METHOD3, the modes are different */
884 if (cam->method == METHOD3) {
885 switch (mode) {
886 case 1:
887 m2[1].value = 0xf000 + 4;
888 break;
889 case 2:
890 m2[1].value = 0xf000 + 0;
891 break;
892 default:
893 m2[1].value = 0xf000 + 1;
894 break;
895 }
896 }
897
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300898 header2[437] = cam->height / 256;
899 header2[438] = cam->height % 256;
900 header2[439] = cam->width / 256;
901 header2[440] = cam->width % 256;
902
903 for (i = 0; init[cam->method][i].size != -1; i++) {
904 ret =
905 send_control_msg(cam->udev, 1, init[cam->method][i].value,
906 0, init[cam->method][i].bytes,
907 init[cam->method][i].size);
908 if (ret < 0) {
909 dev_err(&cam->udev->dev,
910 "error during resolution change sequence: %d\n", i);
911 goto out;
912 }
913 }
914
915 /* Added some delay here, since opening/closing the camera quickly,
916 * like Ekiga does during its startup, can crash the webcam
917 */
918 mdelay(100);
919 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300920 ret = 0;
921
922out:
923 mutex_unlock(&q->vb_lock);
924
925 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
926 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
927 f->fmt.pix.field);
928 return ret;
929}
930
931static int zr364xx_vidioc_reqbufs(struct file *file, void *priv,
932 struct v4l2_requestbuffers *p)
933{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300934 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila0657292012-06-02 08:50:31 -0300935
936 if (cam->owner && cam->owner != priv)
937 return -EBUSY;
938 return videobuf_reqbufs(&cam->vb_vidq, p);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300939}
940
941static int zr364xx_vidioc_querybuf(struct file *file,
942 void *priv,
943 struct v4l2_buffer *p)
944{
945 int rc;
946 struct zr364xx_camera *cam = video_drvdata(file);
947 rc = videobuf_querybuf(&cam->vb_vidq, p);
948 return rc;
949}
950
951static int zr364xx_vidioc_qbuf(struct file *file,
952 void *priv,
953 struct v4l2_buffer *p)
954{
955 int rc;
956 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300957 _DBG("%s\n", __func__);
Hans Verkuila0657292012-06-02 08:50:31 -0300958 if (cam->owner && cam->owner != priv)
959 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300960 rc = videobuf_qbuf(&cam->vb_vidq, p);
961 return rc;
962}
963
964static int zr364xx_vidioc_dqbuf(struct file *file,
965 void *priv,
966 struct v4l2_buffer *p)
967{
968 int rc;
969 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300970 _DBG("%s\n", __func__);
Hans Verkuila0657292012-06-02 08:50:31 -0300971 if (cam->owner && cam->owner != priv)
972 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300973 rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK);
974 return rc;
975}
976
977static void read_pipe_completion(struct urb *purb)
978{
979 struct zr364xx_pipeinfo *pipe_info;
980 struct zr364xx_camera *cam;
981 int pipe;
982
983 pipe_info = purb->context;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300984 _DBG("%s %p, status %d\n", __func__, purb, purb->status);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300985 if (pipe_info == NULL) {
986 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
987 return;
988 }
989
990 cam = pipe_info->cam;
991 if (cam == NULL) {
992 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
993 return;
994 }
995
996 /* if shutting down, do not resubmit, exit immediately */
997 if (purb->status == -ESHUTDOWN) {
998 DBG("%s, err shutdown\n", __func__);
999 pipe_info->err_count++;
1000 return;
1001 }
1002
1003 if (pipe_info->state == 0) {
1004 DBG("exiting USB pipe\n");
1005 return;
1006 }
1007
Mauro Carvalho Chehab50c80122012-10-27 16:30:47 -03001008 if (purb->actual_length > pipe_info->transfer_size) {
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001009 dev_err(&cam->udev->dev, "wrong number of bytes\n");
1010 return;
1011 }
1012
1013 if (purb->status == 0)
1014 zr364xx_read_video_callback(cam, pipe_info, purb);
1015 else {
1016 pipe_info->err_count++;
1017 DBG("%s: failed URB %d\n", __func__, purb->status);
1018 }
1019
1020 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1021
1022 /* reuse urb */
1023 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1024 pipe,
1025 pipe_info->transfer_buffer,
1026 pipe_info->transfer_size,
1027 read_pipe_completion, pipe_info);
1028
1029 if (pipe_info->state != 0) {
1030 purb->status = usb_submit_urb(pipe_info->stream_urb,
1031 GFP_ATOMIC);
1032
1033 if (purb->status)
1034 dev_err(&cam->udev->dev,
1035 "error submitting urb (error=%i)\n",
1036 purb->status);
1037 } else
1038 DBG("read pipe complete state 0\n");
1039}
1040
1041static int zr364xx_start_readpipe(struct zr364xx_camera *cam)
1042{
1043 int pipe;
1044 int retval;
1045 struct zr364xx_pipeinfo *pipe_info = cam->pipe;
1046 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1047 DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint);
1048
1049 pipe_info->state = 1;
1050 pipe_info->err_count = 0;
1051 pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
1052 if (!pipe_info->stream_urb) {
1053 dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n");
1054 return -ENOMEM;
1055 }
1056 /* transfer buffer allocated in board_init */
1057 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1058 pipe,
1059 pipe_info->transfer_buffer,
1060 pipe_info->transfer_size,
1061 read_pipe_completion, pipe_info);
1062
1063 DBG("submitting URB %p\n", pipe_info->stream_urb);
1064 retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
1065 if (retval) {
1066 printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n");
1067 return retval;
1068 }
1069
1070 return 0;
1071}
1072
1073static void zr364xx_stop_readpipe(struct zr364xx_camera *cam)
1074{
1075 struct zr364xx_pipeinfo *pipe_info;
1076
1077 if (cam == NULL) {
1078 printk(KERN_ERR KBUILD_MODNAME ": invalid device\n");
1079 return;
1080 }
1081 DBG("stop read pipe\n");
1082 pipe_info = cam->pipe;
1083 if (pipe_info) {
1084 if (pipe_info->state != 0)
1085 pipe_info->state = 0;
1086
1087 if (pipe_info->stream_urb) {
1088 /* cancel urb */
1089 usb_kill_urb(pipe_info->stream_urb);
1090 usb_free_urb(pipe_info->stream_urb);
1091 pipe_info->stream_urb = NULL;
1092 }
1093 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001094 return;
1095}
1096
1097/* starts acquisition process */
1098static int zr364xx_start_acquire(struct zr364xx_camera *cam)
1099{
1100 int j;
1101
1102 DBG("start acquire\n");
1103
1104 cam->last_frame = -1;
1105 cam->cur_frame = 0;
1106 for (j = 0; j < FRAMES; j++) {
1107 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1108 cam->buffer.frame[j].cur_size = 0;
1109 }
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -03001110 cam->b_acquire = 1;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001111 return 0;
1112}
1113
1114static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam)
1115{
1116 cam->b_acquire = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001117 return 0;
1118}
1119
Hans Verkuil587a5762012-06-08 06:43:59 -03001120static int zr364xx_prepare(struct zr364xx_camera *cam)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001121{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001122 int res;
Hans Verkuil587a5762012-06-08 06:43:59 -03001123 int i, j;
Hans Verkuila0657292012-06-02 08:50:31 -03001124
1125 for (i = 0; init[cam->method][i].size != -1; i++) {
1126 res = send_control_msg(cam->udev, 1, init[cam->method][i].value,
1127 0, init[cam->method][i].bytes,
1128 init[cam->method][i].size);
1129 if (res < 0) {
1130 dev_err(&cam->udev->dev,
1131 "error during open sequence: %d\n", i);
1132 return res;
1133 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001134 }
1135
Hans Verkuila0657292012-06-02 08:50:31 -03001136 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001137 cam->last_frame = -1;
1138 cam->cur_frame = 0;
1139 cam->frame_count = 0;
1140 for (j = 0; j < FRAMES; j++) {
1141 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1142 cam->buffer.frame[j].cur_size = 0;
1143 }
Hans Verkuil587a5762012-06-08 06:43:59 -03001144 v4l2_ctrl_handler_setup(&cam->ctrl_handler);
1145 return 0;
1146}
1147
1148static int zr364xx_vidioc_streamon(struct file *file, void *priv,
1149 enum v4l2_buf_type type)
1150{
1151 struct zr364xx_camera *cam = video_drvdata(file);
1152 int res;
1153
1154 DBG("%s\n", __func__);
1155
1156 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1157 return -EINVAL;
1158
1159 if (cam->owner && cam->owner != priv)
1160 return -EBUSY;
1161
1162 res = zr364xx_prepare(cam);
1163 if (res)
1164 return res;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001165 res = videobuf_streamon(&cam->vb_vidq);
1166 if (res == 0) {
1167 zr364xx_start_acquire(cam);
Hans Verkuila0657292012-06-02 08:50:31 -03001168 cam->owner = file->private_data;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001169 }
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 struct zr364xx_camera *cam = video_drvdata(file);
1177
1178 DBG("%s\n", __func__);
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001179 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001180 return -EINVAL;
Hans Verkuila0657292012-06-02 08:50:31 -03001181 if (cam->owner && cam->owner != priv)
1182 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001183 zr364xx_stop_acquire(cam);
Hans Verkuila0657292012-06-02 08:50:31 -03001184 return videobuf_streamoff(&cam->vb_vidq);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001185}
1186
1187
1188/* open the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -03001189static int zr364xx_open(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001190{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001191 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila0657292012-06-02 08:50:31 -03001192 int err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001193
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001194 DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001195
Hans Verkuila906f622012-06-02 07:16:49 -03001196 if (mutex_lock_interruptible(&cam->lock))
1197 return -ERESTARTSYS;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001198
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001199 err = v4l2_fh_open(file);
1200 if (err)
1201 goto out;
1202
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001203 /* Added some delay here, since opening/closing the camera quickly,
1204 * like Ekiga does during its startup, can crash the webcam
1205 */
1206 mdelay(100);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001207 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001208
Antoine Jacquet69025c92008-08-18 17:09:53 -03001209out:
Hans Verkuila906f622012-06-02 07:16:49 -03001210 mutex_unlock(&cam->lock);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001211 DBG("%s: %d\n", __func__, err);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001212 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001213}
1214
Hans Verkuila906f622012-06-02 07:16:49 -03001215static void zr364xx_release(struct v4l2_device *v4l2_dev)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001216{
Hans Verkuila906f622012-06-02 07:16:49 -03001217 struct zr364xx_camera *cam =
1218 container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001219 unsigned long i;
1220
Hans Verkuila906f622012-06-02 07:16:49 -03001221 v4l2_device_unregister(&cam->v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001222
Hans Verkuila906f622012-06-02 07:16:49 -03001223 videobuf_mmap_free(&cam->vb_vidq);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001224
1225 /* release sys buffers */
1226 for (i = 0; i < FRAMES; i++) {
1227 if (cam->buffer.frame[i].lpvbits) {
1228 DBG("vfree %p\n", cam->buffer.frame[i].lpvbits);
1229 vfree(cam->buffer.frame[i].lpvbits);
1230 }
1231 cam->buffer.frame[i].lpvbits = NULL;
1232 }
1233
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001234 v4l2_ctrl_handler_free(&cam->ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001235 /* release transfer buffer */
1236 kfree(cam->pipe->transfer_buffer);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001237 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001238}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001239
1240/* release the camera */
Hans Verkuila906f622012-06-02 07:16:49 -03001241static int zr364xx_close(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001242{
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001243 struct zr364xx_camera *cam;
1244 struct usb_device *udev;
Hans Verkuila906f622012-06-02 07:16:49 -03001245 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001246
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001247 DBG("%s\n", __func__);
1248 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001249
Hans Verkuila906f622012-06-02 07:16:49 -03001250 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001251 udev = cam->udev;
1252
Hans Verkuila0657292012-06-02 08:50:31 -03001253 if (file->private_data == cam->owner) {
1254 /* turn off stream */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001255 if (cam->b_acquire)
1256 zr364xx_stop_acquire(cam);
1257 videobuf_streamoff(&cam->vb_vidq);
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001258
Hans Verkuila0657292012-06-02 08:50:31 -03001259 for (i = 0; i < 2; i++) {
1260 send_control_msg(udev, 1, init[cam->method][i].value,
1261 0, init[cam->method][i].bytes,
1262 init[cam->method][i].size);
1263 }
1264 cam->owner = NULL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001265 }
1266
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001267 /* Added some delay here, since opening/closing the camera quickly,
1268 * like Ekiga does during its startup, can crash the webcam
1269 */
1270 mdelay(100);
Hans Verkuila906f622012-06-02 07:16:49 -03001271 mutex_unlock(&cam->lock);
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001272 return v4l2_fh_release(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001273}
1274
1275
1276static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
1277{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001278 struct zr364xx_camera *cam = video_drvdata(file);
1279 int ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001280
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001281 if (cam == NULL) {
1282 DBG("%s: cam == NULL\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001283 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001284 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001285 DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001286
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001287 ret = videobuf_mmap_mapper(&cam->vb_vidq, vma);
1288
1289 DBG("vma start=0x%08lx, size=%ld, ret=%d\n",
1290 (unsigned long)vma->vm_start,
1291 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
1292 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001293}
1294
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001295static unsigned int zr364xx_poll(struct file *file,
1296 struct poll_table_struct *wait)
1297{
1298 struct zr364xx_camera *cam = video_drvdata(file);
1299 struct videobuf_queue *q = &cam->vb_vidq;
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001300 unsigned res = v4l2_ctrl_poll(file, wait);
1301
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001302 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001303
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001304 return res | videobuf_poll_stream(file, q, wait);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001305}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001306
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001307static const struct v4l2_ctrl_ops zr364xx_ctrl_ops = {
1308 .s_ctrl = zr364xx_s_ctrl,
1309};
1310
Hans Verkuilbec43662008-12-30 06:58:20 -03001311static const struct v4l2_file_operations zr364xx_fops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001312 .owner = THIS_MODULE,
1313 .open = zr364xx_open,
Hans Verkuila906f622012-06-02 07:16:49 -03001314 .release = zr364xx_close,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001315 .read = zr364xx_read,
1316 .mmap = zr364xx_mmap,
Hans Verkuila906f622012-06-02 07:16:49 -03001317 .unlocked_ioctl = video_ioctl2,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001318 .poll = zr364xx_poll,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001319};
1320
Hans Verkuila3998102008-07-21 02:57:38 -03001321static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001322 .vidioc_querycap = zr364xx_vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001323 .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
1324 .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
1325 .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
1326 .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001327 .vidioc_enum_input = zr364xx_vidioc_enum_input,
1328 .vidioc_g_input = zr364xx_vidioc_g_input,
1329 .vidioc_s_input = zr364xx_vidioc_s_input,
1330 .vidioc_streamon = zr364xx_vidioc_streamon,
1331 .vidioc_streamoff = zr364xx_vidioc_streamoff,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001332 .vidioc_reqbufs = zr364xx_vidioc_reqbufs,
1333 .vidioc_querybuf = zr364xx_vidioc_querybuf,
1334 .vidioc_qbuf = zr364xx_vidioc_qbuf,
1335 .vidioc_dqbuf = zr364xx_vidioc_dqbuf,
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001336 .vidioc_log_status = v4l2_ctrl_log_status,
1337 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1338 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001339};
1340
Hans Verkuila3998102008-07-21 02:57:38 -03001341static struct video_device zr364xx_template = {
Hans Verkuila3998102008-07-21 02:57:38 -03001342 .name = DRIVER_DESC,
Hans Verkuila3998102008-07-21 02:57:38 -03001343 .fops = &zr364xx_fops,
1344 .ioctl_ops = &zr364xx_ioctl_ops,
Hans Verkuil2b992512012-06-02 06:32:48 -03001345 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03001346};
1347
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001348
1349
1350/*******************/
1351/* USB integration */
1352/*******************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001353static int zr364xx_board_init(struct zr364xx_camera *cam)
1354{
1355 struct zr364xx_pipeinfo *pipe = cam->pipe;
1356 unsigned long i;
1357
1358 DBG("board init: %p\n", cam);
1359 memset(pipe, 0, sizeof(*pipe));
1360 pipe->cam = cam;
1361 pipe->transfer_size = BUFFER_SIZE;
1362
1363 pipe->transfer_buffer = kzalloc(pipe->transfer_size,
1364 GFP_KERNEL);
1365 if (pipe->transfer_buffer == NULL) {
1366 DBG("out of memory!\n");
1367 return -ENOMEM;
1368 }
1369
1370 cam->b_acquire = 0;
1371 cam->frame_count = 0;
1372
1373 /*** start create system buffers ***/
1374 for (i = 0; i < FRAMES; i++) {
1375 /* always allocate maximum size for system buffers */
1376 cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE);
1377
1378 DBG("valloc %p, idx %lu, pdata %p\n",
1379 &cam->buffer.frame[i], i,
1380 cam->buffer.frame[i].lpvbits);
1381 if (cam->buffer.frame[i].lpvbits == NULL) {
1382 printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
1383 "Using less frames\n");
1384 break;
1385 }
1386 }
1387
1388 if (i == 0) {
1389 printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
1390 kfree(cam->pipe->transfer_buffer);
1391 cam->pipe->transfer_buffer = NULL;
1392 return -ENOMEM;
1393 } else
1394 cam->buffer.dwFrames = i;
1395
1396 /* make sure internal states are set */
1397 for (i = 0; i < FRAMES; i++) {
1398 cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE;
1399 cam->buffer.frame[i].cur_size = 0;
1400 }
1401
1402 cam->cur_frame = 0;
1403 cam->last_frame = -1;
1404 /*** end create system buffers ***/
1405
1406 /* start read pipe */
1407 zr364xx_start_readpipe(cam);
1408 DBG(": board initialized\n");
1409 return 0;
1410}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001411
1412static int zr364xx_probe(struct usb_interface *intf,
1413 const struct usb_device_id *id)
1414{
1415 struct usb_device *udev = interface_to_usbdev(intf);
1416 struct zr364xx_camera *cam = NULL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001417 struct usb_host_interface *iface_desc;
1418 struct usb_endpoint_descriptor *endpoint;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001419 struct v4l2_ctrl_handler *hdl;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001420 int err;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001421 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001422
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001423 DBG("probing...\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001424
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001425 dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
1426 dev_info(&intf->dev, "model %04x:%04x detected\n",
1427 le16_to_cpu(udev->descriptor.idVendor),
1428 le16_to_cpu(udev->descriptor.idProduct));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001429
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001430 cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
1431 if (cam == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001432 dev_err(&udev->dev, "cam: out of memory !\n");
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001433 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001434 }
Hans Verkuila906f622012-06-02 07:16:49 -03001435
1436 cam->v4l2_dev.release = zr364xx_release;
1437 err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
1438 if (err < 0) {
1439 dev_err(&udev->dev, "couldn't register v4l2_device\n");
1440 kfree(cam);
1441 return err;
1442 }
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001443 hdl = &cam->ctrl_handler;
1444 v4l2_ctrl_handler_init(hdl, 1);
1445 v4l2_ctrl_new_std(hdl, &zr364xx_ctrl_ops,
1446 V4L2_CID_BRIGHTNESS, 0, 127, 1, 64);
1447 if (hdl->error) {
1448 err = hdl->error;
1449 dev_err(&udev->dev, "couldn't register control\n");
1450 goto fail;
1451 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001452 /* save the init method used by this camera */
1453 cam->method = id->driver_info;
Hans Verkuila906f622012-06-02 07:16:49 -03001454 mutex_init(&cam->lock);
Hans Verkuil2b992512012-06-02 06:32:48 -03001455 cam->vdev = zr364xx_template;
Hans Verkuila906f622012-06-02 07:16:49 -03001456 cam->vdev.lock = &cam->lock;
1457 cam->vdev.v4l2_dev = &cam->v4l2_dev;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001458 cam->vdev.ctrl_handler = &cam->ctrl_handler;
Hans Verkuila0657292012-06-02 08:50:31 -03001459 set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
Hans Verkuil2b992512012-06-02 06:32:48 -03001460 video_set_drvdata(&cam->vdev, cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001461 if (debug)
Hans Verkuil2b992512012-06-02 06:32:48 -03001462 cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001463
1464 cam->udev = udev;
1465
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001466 switch (mode) {
1467 case 1:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001468 dev_info(&udev->dev, "160x120 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001469 cam->width = 160;
1470 cam->height = 120;
1471 break;
1472 case 2:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001473 dev_info(&udev->dev, "640x480 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001474 cam->width = 640;
1475 cam->height = 480;
1476 break;
1477 default:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001478 dev_info(&udev->dev, "320x240 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001479 cam->width = 320;
1480 cam->height = 240;
1481 break;
1482 }
1483
1484 m0d1[0] = mode;
1485 m1[2].value = 0xf000 + mode;
1486 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -03001487
1488 /* special case for METHOD3, the modes are different */
1489 if (cam->method == METHOD3) {
1490 switch (mode) {
1491 case 1:
1492 m2[1].value = 0xf000 + 4;
1493 break;
1494 case 2:
1495 m2[1].value = 0xf000 + 0;
1496 break;
1497 default:
1498 m2[1].value = 0xf000 + 1;
1499 break;
1500 }
1501 }
1502
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001503 header2[437] = cam->height / 256;
1504 header2[438] = cam->height % 256;
1505 header2[439] = cam->width / 256;
1506 header2[440] = cam->width % 256;
1507
1508 cam->nb = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001509
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001510 DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf);
1511
1512 /* set up the endpoint information */
1513 iface_desc = intf->cur_altsetting;
1514 DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
1515 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1516 endpoint = &iface_desc->endpoint[i].desc;
1517 if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
1518 /* we found the bulk in endpoint */
1519 cam->read_endpoint = endpoint->bEndpointAddress;
1520 }
1521 }
1522
1523 if (!cam->read_endpoint) {
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001524 err = -ENOMEM;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001525 dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001526 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001527 }
1528
1529 /* v4l */
1530 INIT_LIST_HEAD(&cam->vidq.active);
1531 cam->vidq.cam = cam;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001532
1533 usb_set_intfdata(intf, cam);
1534
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001535 /* load zr364xx board specific */
1536 err = zr364xx_board_init(cam);
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001537 if (!err)
1538 err = v4l2_ctrl_handler_setup(hdl);
1539 if (err)
1540 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001541
1542 spin_lock_init(&cam->slock);
1543
Hans Verkuila0657292012-06-02 08:50:31 -03001544 cam->fmt = formats;
1545
1546 videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops,
1547 NULL, &cam->slock,
1548 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1549 V4L2_FIELD_NONE,
1550 sizeof(struct zr364xx_buffer), cam, &cam->lock);
1551
Hans Verkuil2b992512012-06-02 06:32:48 -03001552 err = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
1553 if (err) {
1554 dev_err(&udev->dev, "video_register_device failed\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001555 goto fail;
Hans Verkuil2b992512012-06-02 06:32:48 -03001556 }
1557
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001558 dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
Hans Verkuil2b992512012-06-02 06:32:48 -03001559 video_device_node_name(&cam->vdev));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001560 return 0;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001561
1562fail:
1563 v4l2_ctrl_handler_free(hdl);
1564 v4l2_device_unregister(&cam->v4l2_dev);
1565 kfree(cam);
1566 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001567}
1568
1569
1570static void zr364xx_disconnect(struct usb_interface *intf)
1571{
1572 struct zr364xx_camera *cam = usb_get_intfdata(intf);
Hans Verkuila906f622012-06-02 07:16:49 -03001573
1574 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001575 usb_set_intfdata(intf, NULL);
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001576 dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
Hans Verkuila906f622012-06-02 07:16:49 -03001577 video_unregister_device(&cam->vdev);
1578 v4l2_device_disconnect(&cam->v4l2_dev);
1579
1580 /* stops the read pipe if it is running */
1581 if (cam->b_acquire)
1582 zr364xx_stop_acquire(cam);
1583
1584 zr364xx_stop_readpipe(cam);
1585 mutex_unlock(&cam->lock);
1586 v4l2_device_put(&cam->v4l2_dev);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001587}
1588
1589
Hans Verkuil587a5762012-06-08 06:43:59 -03001590#ifdef CONFIG_PM
1591static int zr364xx_suspend(struct usb_interface *intf, pm_message_t message)
1592{
1593 struct zr364xx_camera *cam = usb_get_intfdata(intf);
1594
1595 cam->was_streaming = cam->b_acquire;
1596 if (!cam->was_streaming)
1597 return 0;
1598 zr364xx_stop_acquire(cam);
1599 zr364xx_stop_readpipe(cam);
1600 return 0;
1601}
1602
1603static int zr364xx_resume(struct usb_interface *intf)
1604{
1605 struct zr364xx_camera *cam = usb_get_intfdata(intf);
1606 int res;
1607
1608 if (!cam->was_streaming)
1609 return 0;
1610
1611 zr364xx_start_readpipe(cam);
1612 res = zr364xx_prepare(cam);
1613 if (!res)
1614 zr364xx_start_acquire(cam);
1615 return res;
1616}
1617#endif
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001618
1619/**********************/
1620/* Module integration */
1621/**********************/
1622
1623static struct usb_driver zr364xx_driver = {
1624 .name = "zr364xx",
1625 .probe = zr364xx_probe,
1626 .disconnect = zr364xx_disconnect,
Hans Verkuil587a5762012-06-08 06:43:59 -03001627#ifdef CONFIG_PM
1628 .suspend = zr364xx_suspend,
1629 .resume = zr364xx_resume,
1630 .reset_resume = zr364xx_resume,
1631#endif
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001632 .id_table = device_table
1633};
1634
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001635module_usb_driver(zr364xx_driver);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001636
1637MODULE_AUTHOR(DRIVER_AUTHOR);
1638MODULE_DESCRIPTION(DRIVER_DESC);
1639MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001640MODULE_VERSION(DRIVER_VERSION);