blob: cc128db85723c90d1619d774e55af6e747604a5b [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
Mauro Carvalho Chehab09f20822015-05-19 08:00:56 -0300380 BUG_ON(in_interrupt());
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300381
382 videobuf_vmalloc_free(&buf->vb);
383 buf->vb.state = VIDEOBUF_NEEDS_INIT;
384}
385
386static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
387 enum v4l2_field field)
388{
389 struct zr364xx_camera *cam = vq->priv_data;
390 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
391 vb);
392 int rc;
393
394 DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ?
395 cam->fmt->name : "");
396 if (cam->fmt == NULL)
397 return -EINVAL;
398
399 buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3);
400
401 if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) {
402 DBG("invalid buffer prepare\n");
403 return -EINVAL;
404 }
405
406 buf->fmt = cam->fmt;
407 buf->vb.width = cam->width;
408 buf->vb.height = cam->height;
409 buf->vb.field = field;
410
411 if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
412 rc = videobuf_iolock(vq, &buf->vb, NULL);
413 if (rc < 0)
414 goto fail;
415 }
416
417 buf->vb.state = VIDEOBUF_PREPARED;
418 return 0;
419fail:
420 free_buffer(vq, buf);
421 return rc;
422}
423
424static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
425{
426 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
427 vb);
428 struct zr364xx_camera *cam = vq->priv_data;
429
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300430 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300431
432 buf->vb.state = VIDEOBUF_QUEUED;
433 list_add_tail(&buf->vb.queue, &cam->vidq.active);
434}
435
436static void buffer_release(struct videobuf_queue *vq,
437 struct videobuf_buffer *vb)
438{
439 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
440 vb);
441
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300442 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300443 free_buffer(vq, buf);
444}
445
446static struct videobuf_queue_ops zr364xx_video_qops = {
447 .buf_setup = buffer_setup,
448 .buf_prepare = buffer_prepare,
449 .buf_queue = buffer_queue,
450 .buf_release = buffer_release,
451};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300452
453/********************/
454/* V4L2 integration */
455/********************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300456static int zr364xx_vidioc_streamon(struct file *file, void *priv,
457 enum v4l2_buf_type type);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300458
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300459static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300460 loff_t * ppos)
461{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300462 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila906f622012-06-02 07:16:49 -0300463 int err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300464
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300465 _DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300466
467 if (!buf)
468 return -EINVAL;
469
470 if (!count)
471 return -EINVAL;
472
Hans Verkuila906f622012-06-02 07:16:49 -0300473 if (mutex_lock_interruptible(&cam->lock))
474 return -ERESTARTSYS;
475
Hans Verkuila0657292012-06-02 08:50:31 -0300476 err = zr364xx_vidioc_streamon(file, file->private_data,
477 V4L2_BUF_TYPE_VIDEO_CAPTURE);
478 if (err == 0) {
479 DBG("%s: reading %d bytes at pos %d.\n", __func__,
480 (int) count, (int) *ppos);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300481
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300482 /* NoMan Sux ! */
Hans Verkuila906f622012-06-02 07:16:49 -0300483 err = videobuf_read_one(&cam->vb_vidq, buf, count, ppos,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300484 file->f_flags & O_NONBLOCK);
485 }
Hans Verkuila906f622012-06-02 07:16:49 -0300486 mutex_unlock(&cam->lock);
487 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300488}
489
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300490/* video buffer vmalloc implementation based partly on VIVI driver which is
491 * Copyright (c) 2006 by
492 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
493 * Ted Walther <ted--a.t--enumera.com>
494 * John Sokol <sokol--a.t--videotechnology.com>
495 * http://v4l.videotechnology.com/
496 *
497 */
498static void zr364xx_fillbuff(struct zr364xx_camera *cam,
499 struct zr364xx_buffer *buf,
500 int jpgsize)
501{
502 int pos = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300503 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;
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300531 v4l2_get_timestamp(&buf->vb.ts);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300532 buf->vb.state = VIDEOBUF_DONE;
533}
534
535static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize)
536{
537 struct zr364xx_dmaqueue *dma_q = &cam->vidq;
538 struct zr364xx_buffer *buf;
539 unsigned long flags = 0;
540 int rc = 0;
541
542 DBG("wakeup: %p\n", &dma_q);
543 spin_lock_irqsave(&cam->slock, flags);
544
545 if (list_empty(&dma_q->active)) {
546 DBG("No active queue to serve\n");
547 rc = -1;
548 goto unlock;
549 }
550 buf = list_entry(dma_q->active.next,
551 struct zr364xx_buffer, vb.queue);
552
553 if (!waitqueue_active(&buf->vb.done)) {
554 /* no one active */
555 rc = -1;
556 goto unlock;
557 }
558 list_del(&buf->vb.queue);
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300559 v4l2_get_timestamp(&buf->vb.ts);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300560 DBG("[%p/%d] wakeup\n", buf, buf->vb.i);
561 zr364xx_fillbuff(cam, buf, jpgsize);
562 wake_up(&buf->vb.done);
563 DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
564unlock:
565 spin_unlock_irqrestore(&cam->slock, flags);
Julia Lawall30538142010-08-16 13:27:47 -0300566 return rc;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300567}
568
569/* this function moves the usb stream read pipe data
570 * into the system buffers.
571 * returns 0 on success, EAGAIN if more data to process (call this
572 * function again).
573 */
574static int zr364xx_read_video_callback(struct zr364xx_camera *cam,
575 struct zr364xx_pipeinfo *pipe_info,
576 struct urb *purb)
577{
578 unsigned char *pdest;
579 unsigned char *psrc;
580 s32 idx = -1;
581 struct zr364xx_framei *frm;
582 int i = 0;
583 unsigned char *ptr = NULL;
584
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300585 _DBG("buffer to user\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300586 idx = cam->cur_frame;
587 frm = &cam->buffer.frame[idx];
588
589 /* swap bytes if camera needs it */
590 if (cam->method == METHOD0) {
591 u16 *buf = (u16 *)pipe_info->transfer_buffer;
592 for (i = 0; i < purb->actual_length/2; i++)
593 swab16s(buf + i);
594 }
595
596 /* search done. now find out if should be acquiring */
597 if (!cam->b_acquire) {
598 /* we found a frame, but this channel is turned off */
599 frm->ulState = ZR364XX_READ_IDLE;
600 return -EINVAL;
601 }
602
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300603 psrc = (u8 *)pipe_info->transfer_buffer;
604 ptr = pdest = frm->lpvbits;
605
606 if (frm->ulState == ZR364XX_READ_IDLE) {
607 frm->ulState = ZR364XX_READ_FRAME;
608 frm->cur_size = 0;
609
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300610 _DBG("jpeg header, ");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300611 memcpy(ptr, header1, sizeof(header1));
612 ptr += sizeof(header1);
613 header3 = 0;
614 memcpy(ptr, &header3, 1);
615 ptr++;
616 memcpy(ptr, psrc, 64);
617 ptr += 64;
618 header3 = 1;
619 memcpy(ptr, &header3, 1);
620 ptr++;
621 memcpy(ptr, psrc + 64, 64);
622 ptr += 64;
623 memcpy(ptr, header2, sizeof(header2));
624 ptr += sizeof(header2);
625 memcpy(ptr, psrc + 128,
626 purb->actual_length - 128);
627 ptr += purb->actual_length - 128;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300628 _DBG("header : %d %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300629 psrc[0], psrc[1], psrc[2],
630 psrc[3], psrc[4], psrc[5],
631 psrc[6], psrc[7], psrc[8]);
632 frm->cur_size = ptr - pdest;
633 } else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300634 if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) {
635 dev_info(&cam->udev->dev,
636 "%s: buffer (%d bytes) too small to hold "
637 "frame data. Discarding frame data.\n",
638 __func__, MAX_FRAME_SIZE);
639 } else {
640 pdest += frm->cur_size;
641 memcpy(pdest, psrc, purb->actual_length);
642 frm->cur_size += purb->actual_length;
643 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300644 }
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300645 /*_DBG("cur_size %lu urb size %d\n", frm->cur_size,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300646 purb->actual_length);*/
647
648 if (purb->actual_length < pipe_info->transfer_size) {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300649 _DBG("****************Buffer[%d]full*************\n", idx);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300650 cam->last_frame = cam->cur_frame;
651 cam->cur_frame++;
652 /* end of system frame ring buffer, start at zero */
653 if (cam->cur_frame == cam->buffer.dwFrames)
654 cam->cur_frame = 0;
655
656 /* frame ready */
657 /* go back to find the JPEG EOI marker */
658 ptr = pdest = frm->lpvbits;
659 ptr += frm->cur_size - 2;
660 while (ptr > pdest) {
661 if (*ptr == 0xFF && *(ptr + 1) == 0xD9
662 && *(ptr + 2) == 0xFF)
663 break;
664 ptr--;
665 }
666 if (ptr == pdest)
667 DBG("No EOI marker\n");
668
669 /* Sometimes there is junk data in the middle of the picture,
670 * we want to skip this bogus frames */
671 while (ptr > pdest) {
672 if (*ptr == 0xFF && *(ptr + 1) == 0xFF
673 && *(ptr + 2) == 0xFF)
674 break;
675 ptr--;
676 }
677 if (ptr != pdest) {
678 DBG("Bogus frame ? %d\n", ++(cam->nb));
679 } else if (cam->b_acquire) {
680 /* we skip the 2 first frames which are usually buggy */
681 if (cam->skip)
682 cam->skip--;
683 else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300684 _DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300685 frm->cur_size,
686 pdest[0], pdest[1], pdest[2], pdest[3],
687 pdest[4], pdest[5], pdest[6], pdest[7]);
688
689 zr364xx_got_frame(cam, frm->cur_size);
690 }
691 }
692 cam->frame_count++;
693 frm->ulState = ZR364XX_READ_IDLE;
694 frm->cur_size = 0;
695 }
696 /* done successfully */
697 return 0;
698}
699
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300700static int zr364xx_vidioc_querycap(struct file *file, void *priv,
701 struct v4l2_capability *cap)
702{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300703 struct zr364xx_camera *cam = video_drvdata(file);
704
705 strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
706 strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
707 strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
708 sizeof(cap->bus_info));
Hans Verkuildf462902012-06-02 07:50:30 -0300709 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300710 V4L2_CAP_READWRITE |
711 V4L2_CAP_STREAMING;
Hans Verkuildf462902012-06-02 07:50:30 -0300712 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300713
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300714 return 0;
715}
716
717static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
718 struct v4l2_input *i)
719{
720 if (i->index != 0)
721 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300722 strcpy(i->name, DRIVER_DESC " Camera");
723 i->type = V4L2_INPUT_TYPE_CAMERA;
724 return 0;
725}
726
727static int zr364xx_vidioc_g_input(struct file *file, void *priv,
728 unsigned int *i)
729{
730 *i = 0;
731 return 0;
732}
733
734static int zr364xx_vidioc_s_input(struct file *file, void *priv,
735 unsigned int i)
736{
737 if (i != 0)
738 return -EINVAL;
739 return 0;
740}
741
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300742static int zr364xx_s_ctrl(struct v4l2_ctrl *ctrl)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300743{
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300744 struct zr364xx_camera *cam =
745 container_of(ctrl->handler, struct zr364xx_camera, ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300746 int temp;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300747
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300748 switch (ctrl->id) {
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300749 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300750 /* hardware brightness */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300751 send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
Hans Verkuil1fc21a12012-06-02 07:44:15 -0300752 temp = (0x60 << 8) + 127 - ctrl->val;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300753 send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300754 break;
755 default:
756 return -EINVAL;
757 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300758
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300759 return 0;
760}
761
Hans Verkuil78b526a2008-05-28 12:16:41 -0300762static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300763 void *priv, struct v4l2_fmtdesc *f)
764{
765 if (f->index > 0)
766 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300767 f->flags = V4L2_FMT_FLAG_COMPRESSED;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300768 strcpy(f->description, formats[0].name);
769 f->pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300770 return 0;
771}
772
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300773static char *decode_fourcc(__u32 pixelformat, char *buf)
774{
775 buf[0] = pixelformat & 0xff;
776 buf[1] = (pixelformat >> 8) & 0xff;
777 buf[2] = (pixelformat >> 16) & 0xff;
778 buf[3] = (pixelformat >> 24) & 0xff;
779 buf[4] = '\0';
780 return buf;
781}
782
Hans Verkuil78b526a2008-05-28 12:16:41 -0300783static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300784 struct v4l2_format *f)
785{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300786 struct zr364xx_camera *cam = video_drvdata(file);
787 char pixelformat_name[5];
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300788
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300789 if (cam == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300790 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300791
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300792 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
793 DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__,
794 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name));
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300795 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300796 }
797
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300798 if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) &&
799 !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) {
800 f->fmt.pix.width = 320;
801 f->fmt.pix.height = 240;
802 }
803
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300804 f->fmt.pix.field = V4L2_FIELD_NONE;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300805 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
806 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300807 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300808 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
809 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
810 f->fmt.pix.field);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300811 return 0;
812}
813
Hans Verkuil78b526a2008-05-28 12:16:41 -0300814static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300815 struct v4l2_format *f)
816{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300817 struct zr364xx_camera *cam;
818
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300819 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300820 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300821 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300822
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300823 f->fmt.pix.pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300824 f->fmt.pix.field = V4L2_FIELD_NONE;
825 f->fmt.pix.width = cam->width;
826 f->fmt.pix.height = cam->height;
827 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
828 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300829 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300830 return 0;
831}
832
Hans Verkuil78b526a2008-05-28 12:16:41 -0300833static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300834 struct v4l2_format *f)
835{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300836 struct zr364xx_camera *cam = video_drvdata(file);
837 struct videobuf_queue *q = &cam->vb_vidq;
838 char pixelformat_name[5];
839 int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f);
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300840 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300841
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300842 if (ret < 0)
843 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300844
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300845 mutex_lock(&q->vb_lock);
846
847 if (videobuf_queue_is_busy(&cam->vb_vidq)) {
848 DBG("%s queue busy\n", __func__);
849 ret = -EBUSY;
850 goto out;
851 }
852
Hans Verkuila0657292012-06-02 08:50:31 -0300853 if (cam->owner) {
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300854 DBG("%s can't change format after started\n", __func__);
855 ret = -EBUSY;
856 goto out;
857 }
858
859 cam->width = f->fmt.pix.width;
860 cam->height = f->fmt.pix.height;
Hans Verkuila0657292012-06-02 08:50:31 -0300861 DBG("%s: %dx%d mode selected\n", __func__,
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300862 cam->width, cam->height);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300863 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
864 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuildf462902012-06-02 07:50:30 -0300865 f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300866 cam->vb_vidq.field = f->fmt.pix.field;
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300867
868 if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
869 mode = 1;
870 else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480)
871 mode = 2;
872 else
873 mode = 0;
874
875 m0d1[0] = mode;
876 m1[2].value = 0xf000 + mode;
877 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -0300878
879 /* special case for METHOD3, the modes are different */
880 if (cam->method == METHOD3) {
881 switch (mode) {
882 case 1:
883 m2[1].value = 0xf000 + 4;
884 break;
885 case 2:
886 m2[1].value = 0xf000 + 0;
887 break;
888 default:
889 m2[1].value = 0xf000 + 1;
890 break;
891 }
892 }
893
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300894 header2[437] = cam->height / 256;
895 header2[438] = cam->height % 256;
896 header2[439] = cam->width / 256;
897 header2[440] = cam->width % 256;
898
899 for (i = 0; init[cam->method][i].size != -1; i++) {
900 ret =
901 send_control_msg(cam->udev, 1, init[cam->method][i].value,
902 0, init[cam->method][i].bytes,
903 init[cam->method][i].size);
904 if (ret < 0) {
905 dev_err(&cam->udev->dev,
906 "error during resolution change sequence: %d\n", i);
907 goto out;
908 }
909 }
910
911 /* Added some delay here, since opening/closing the camera quickly,
912 * like Ekiga does during its startup, can crash the webcam
913 */
914 mdelay(100);
915 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300916 ret = 0;
917
918out:
919 mutex_unlock(&q->vb_lock);
920
921 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
922 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
923 f->fmt.pix.field);
924 return ret;
925}
926
927static int zr364xx_vidioc_reqbufs(struct file *file, void *priv,
928 struct v4l2_requestbuffers *p)
929{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300930 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila0657292012-06-02 08:50:31 -0300931
932 if (cam->owner && cam->owner != priv)
933 return -EBUSY;
934 return videobuf_reqbufs(&cam->vb_vidq, p);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300935}
936
937static int zr364xx_vidioc_querybuf(struct file *file,
938 void *priv,
939 struct v4l2_buffer *p)
940{
941 int rc;
942 struct zr364xx_camera *cam = video_drvdata(file);
943 rc = videobuf_querybuf(&cam->vb_vidq, p);
944 return rc;
945}
946
947static int zr364xx_vidioc_qbuf(struct file *file,
948 void *priv,
949 struct v4l2_buffer *p)
950{
951 int rc;
952 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300953 _DBG("%s\n", __func__);
Hans Verkuila0657292012-06-02 08:50:31 -0300954 if (cam->owner && cam->owner != priv)
955 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300956 rc = videobuf_qbuf(&cam->vb_vidq, p);
957 return rc;
958}
959
960static int zr364xx_vidioc_dqbuf(struct file *file,
961 void *priv,
962 struct v4l2_buffer *p)
963{
964 int rc;
965 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300966 _DBG("%s\n", __func__);
Hans Verkuila0657292012-06-02 08:50:31 -0300967 if (cam->owner && cam->owner != priv)
968 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300969 rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK);
970 return rc;
971}
972
973static void read_pipe_completion(struct urb *purb)
974{
975 struct zr364xx_pipeinfo *pipe_info;
976 struct zr364xx_camera *cam;
977 int pipe;
978
979 pipe_info = purb->context;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300980 _DBG("%s %p, status %d\n", __func__, purb, purb->status);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300981 if (pipe_info == NULL) {
982 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
983 return;
984 }
985
986 cam = pipe_info->cam;
987 if (cam == NULL) {
988 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
989 return;
990 }
991
992 /* if shutting down, do not resubmit, exit immediately */
993 if (purb->status == -ESHUTDOWN) {
994 DBG("%s, err shutdown\n", __func__);
995 pipe_info->err_count++;
996 return;
997 }
998
999 if (pipe_info->state == 0) {
1000 DBG("exiting USB pipe\n");
1001 return;
1002 }
1003
Mauro Carvalho Chehab50c80122012-10-27 16:30:47 -03001004 if (purb->actual_length > pipe_info->transfer_size) {
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001005 dev_err(&cam->udev->dev, "wrong number of bytes\n");
1006 return;
1007 }
1008
1009 if (purb->status == 0)
1010 zr364xx_read_video_callback(cam, pipe_info, purb);
1011 else {
1012 pipe_info->err_count++;
1013 DBG("%s: failed URB %d\n", __func__, purb->status);
1014 }
1015
1016 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1017
1018 /* reuse urb */
1019 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1020 pipe,
1021 pipe_info->transfer_buffer,
1022 pipe_info->transfer_size,
1023 read_pipe_completion, pipe_info);
1024
1025 if (pipe_info->state != 0) {
1026 purb->status = usb_submit_urb(pipe_info->stream_urb,
1027 GFP_ATOMIC);
1028
1029 if (purb->status)
1030 dev_err(&cam->udev->dev,
1031 "error submitting urb (error=%i)\n",
1032 purb->status);
1033 } else
1034 DBG("read pipe complete state 0\n");
1035}
1036
1037static int zr364xx_start_readpipe(struct zr364xx_camera *cam)
1038{
1039 int pipe;
1040 int retval;
1041 struct zr364xx_pipeinfo *pipe_info = cam->pipe;
1042 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1043 DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint);
1044
1045 pipe_info->state = 1;
1046 pipe_info->err_count = 0;
1047 pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
Wolfram Sang4e9f0372016-08-11 23:04:04 +02001048 if (!pipe_info->stream_urb)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001049 return -ENOMEM;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001050 /* transfer buffer allocated in board_init */
1051 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1052 pipe,
1053 pipe_info->transfer_buffer,
1054 pipe_info->transfer_size,
1055 read_pipe_completion, pipe_info);
1056
1057 DBG("submitting URB %p\n", pipe_info->stream_urb);
1058 retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
1059 if (retval) {
1060 printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n");
1061 return retval;
1062 }
1063
1064 return 0;
1065}
1066
1067static void zr364xx_stop_readpipe(struct zr364xx_camera *cam)
1068{
1069 struct zr364xx_pipeinfo *pipe_info;
1070
1071 if (cam == NULL) {
1072 printk(KERN_ERR KBUILD_MODNAME ": invalid device\n");
1073 return;
1074 }
1075 DBG("stop read pipe\n");
1076 pipe_info = cam->pipe;
1077 if (pipe_info) {
1078 if (pipe_info->state != 0)
1079 pipe_info->state = 0;
1080
1081 if (pipe_info->stream_urb) {
1082 /* cancel urb */
1083 usb_kill_urb(pipe_info->stream_urb);
1084 usb_free_urb(pipe_info->stream_urb);
1085 pipe_info->stream_urb = NULL;
1086 }
1087 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001088 return;
1089}
1090
1091/* starts acquisition process */
1092static int zr364xx_start_acquire(struct zr364xx_camera *cam)
1093{
1094 int j;
1095
1096 DBG("start acquire\n");
1097
1098 cam->last_frame = -1;
1099 cam->cur_frame = 0;
1100 for (j = 0; j < FRAMES; j++) {
1101 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1102 cam->buffer.frame[j].cur_size = 0;
1103 }
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -03001104 cam->b_acquire = 1;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001105 return 0;
1106}
1107
1108static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam)
1109{
1110 cam->b_acquire = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001111 return 0;
1112}
1113
Hans Verkuil587a5762012-06-08 06:43:59 -03001114static int zr364xx_prepare(struct zr364xx_camera *cam)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001115{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001116 int res;
Hans Verkuil587a5762012-06-08 06:43:59 -03001117 int i, j;
Hans Verkuila0657292012-06-02 08:50:31 -03001118
1119 for (i = 0; init[cam->method][i].size != -1; i++) {
1120 res = send_control_msg(cam->udev, 1, init[cam->method][i].value,
1121 0, init[cam->method][i].bytes,
1122 init[cam->method][i].size);
1123 if (res < 0) {
1124 dev_err(&cam->udev->dev,
1125 "error during open sequence: %d\n", i);
1126 return res;
1127 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001128 }
1129
Hans Verkuila0657292012-06-02 08:50:31 -03001130 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001131 cam->last_frame = -1;
1132 cam->cur_frame = 0;
1133 cam->frame_count = 0;
1134 for (j = 0; j < FRAMES; j++) {
1135 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1136 cam->buffer.frame[j].cur_size = 0;
1137 }
Hans Verkuil587a5762012-06-08 06:43:59 -03001138 v4l2_ctrl_handler_setup(&cam->ctrl_handler);
1139 return 0;
1140}
1141
1142static int zr364xx_vidioc_streamon(struct file *file, void *priv,
1143 enum v4l2_buf_type type)
1144{
1145 struct zr364xx_camera *cam = video_drvdata(file);
1146 int res;
1147
1148 DBG("%s\n", __func__);
1149
1150 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1151 return -EINVAL;
1152
1153 if (cam->owner && cam->owner != priv)
1154 return -EBUSY;
1155
1156 res = zr364xx_prepare(cam);
1157 if (res)
1158 return res;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001159 res = videobuf_streamon(&cam->vb_vidq);
1160 if (res == 0) {
1161 zr364xx_start_acquire(cam);
Hans Verkuila0657292012-06-02 08:50:31 -03001162 cam->owner = file->private_data;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001163 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001164 return res;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001165}
1166
1167static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
1168 enum v4l2_buf_type type)
1169{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001170 struct zr364xx_camera *cam = video_drvdata(file);
1171
1172 DBG("%s\n", __func__);
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001173 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001174 return -EINVAL;
Hans Verkuila0657292012-06-02 08:50:31 -03001175 if (cam->owner && cam->owner != priv)
1176 return -EBUSY;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001177 zr364xx_stop_acquire(cam);
Hans Verkuila0657292012-06-02 08:50:31 -03001178 return videobuf_streamoff(&cam->vb_vidq);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001179}
1180
1181
1182/* open the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -03001183static int zr364xx_open(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001184{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001185 struct zr364xx_camera *cam = video_drvdata(file);
Hans Verkuila0657292012-06-02 08:50:31 -03001186 int err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001187
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001188 DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001189
Hans Verkuila906f622012-06-02 07:16:49 -03001190 if (mutex_lock_interruptible(&cam->lock))
1191 return -ERESTARTSYS;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001192
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001193 err = v4l2_fh_open(file);
1194 if (err)
1195 goto out;
1196
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001197 /* Added some delay here, since opening/closing the camera quickly,
1198 * like Ekiga does during its startup, can crash the webcam
1199 */
1200 mdelay(100);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001201 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001202
Antoine Jacquet69025c92008-08-18 17:09:53 -03001203out:
Hans Verkuila906f622012-06-02 07:16:49 -03001204 mutex_unlock(&cam->lock);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001205 DBG("%s: %d\n", __func__, err);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001206 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001207}
1208
Hans Verkuila906f622012-06-02 07:16:49 -03001209static void zr364xx_release(struct v4l2_device *v4l2_dev)
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001210{
Hans Verkuila906f622012-06-02 07:16:49 -03001211 struct zr364xx_camera *cam =
1212 container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001213 unsigned long i;
1214
Hans Verkuila906f622012-06-02 07:16:49 -03001215 v4l2_device_unregister(&cam->v4l2_dev);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001216
Hans Verkuila906f622012-06-02 07:16:49 -03001217 videobuf_mmap_free(&cam->vb_vidq);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001218
1219 /* release sys buffers */
1220 for (i = 0; i < FRAMES; i++) {
1221 if (cam->buffer.frame[i].lpvbits) {
1222 DBG("vfree %p\n", cam->buffer.frame[i].lpvbits);
1223 vfree(cam->buffer.frame[i].lpvbits);
1224 }
1225 cam->buffer.frame[i].lpvbits = NULL;
1226 }
1227
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001228 v4l2_ctrl_handler_free(&cam->ctrl_handler);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001229 /* release transfer buffer */
1230 kfree(cam->pipe->transfer_buffer);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001231 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001232}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001233
1234/* release the camera */
Hans Verkuila906f622012-06-02 07:16:49 -03001235static int zr364xx_close(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001236{
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001237 struct zr364xx_camera *cam;
1238 struct usb_device *udev;
Hans Verkuila906f622012-06-02 07:16:49 -03001239 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001240
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001241 DBG("%s\n", __func__);
1242 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001243
Hans Verkuila906f622012-06-02 07:16:49 -03001244 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001245 udev = cam->udev;
1246
Hans Verkuila0657292012-06-02 08:50:31 -03001247 if (file->private_data == cam->owner) {
1248 /* turn off stream */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001249 if (cam->b_acquire)
1250 zr364xx_stop_acquire(cam);
1251 videobuf_streamoff(&cam->vb_vidq);
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001252
Hans Verkuila0657292012-06-02 08:50:31 -03001253 for (i = 0; i < 2; i++) {
1254 send_control_msg(udev, 1, init[cam->method][i].value,
1255 0, init[cam->method][i].bytes,
1256 init[cam->method][i].size);
1257 }
1258 cam->owner = NULL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001259 }
1260
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001261 /* Added some delay here, since opening/closing the camera quickly,
1262 * like Ekiga does during its startup, can crash the webcam
1263 */
1264 mdelay(100);
Hans Verkuila906f622012-06-02 07:16:49 -03001265 mutex_unlock(&cam->lock);
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001266 return v4l2_fh_release(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001267}
1268
1269
1270static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
1271{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001272 struct zr364xx_camera *cam = video_drvdata(file);
1273 int ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001274
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001275 if (cam == NULL) {
1276 DBG("%s: cam == NULL\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001277 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001278 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001279 DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001280
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001281 ret = videobuf_mmap_mapper(&cam->vb_vidq, vma);
1282
1283 DBG("vma start=0x%08lx, size=%ld, ret=%d\n",
1284 (unsigned long)vma->vm_start,
1285 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
1286 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001287}
1288
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001289static unsigned int zr364xx_poll(struct file *file,
1290 struct poll_table_struct *wait)
1291{
1292 struct zr364xx_camera *cam = video_drvdata(file);
1293 struct videobuf_queue *q = &cam->vb_vidq;
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001294 unsigned res = v4l2_ctrl_poll(file, wait);
1295
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001296 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001297
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001298 return res | videobuf_poll_stream(file, q, wait);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001299}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001300
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001301static const struct v4l2_ctrl_ops zr364xx_ctrl_ops = {
1302 .s_ctrl = zr364xx_s_ctrl,
1303};
1304
Hans Verkuilbec43662008-12-30 06:58:20 -03001305static const struct v4l2_file_operations zr364xx_fops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001306 .owner = THIS_MODULE,
1307 .open = zr364xx_open,
Hans Verkuila906f622012-06-02 07:16:49 -03001308 .release = zr364xx_close,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001309 .read = zr364xx_read,
1310 .mmap = zr364xx_mmap,
Hans Verkuila906f622012-06-02 07:16:49 -03001311 .unlocked_ioctl = video_ioctl2,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001312 .poll = zr364xx_poll,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001313};
1314
Hans Verkuila3998102008-07-21 02:57:38 -03001315static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001316 .vidioc_querycap = zr364xx_vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001317 .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
1318 .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
1319 .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
1320 .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001321 .vidioc_enum_input = zr364xx_vidioc_enum_input,
1322 .vidioc_g_input = zr364xx_vidioc_g_input,
1323 .vidioc_s_input = zr364xx_vidioc_s_input,
1324 .vidioc_streamon = zr364xx_vidioc_streamon,
1325 .vidioc_streamoff = zr364xx_vidioc_streamoff,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001326 .vidioc_reqbufs = zr364xx_vidioc_reqbufs,
1327 .vidioc_querybuf = zr364xx_vidioc_querybuf,
1328 .vidioc_qbuf = zr364xx_vidioc_qbuf,
1329 .vidioc_dqbuf = zr364xx_vidioc_dqbuf,
Hans Verkuil5d317ab2012-06-02 07:57:29 -03001330 .vidioc_log_status = v4l2_ctrl_log_status,
1331 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1332 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001333};
1334
Hans Verkuila3998102008-07-21 02:57:38 -03001335static struct video_device zr364xx_template = {
Hans Verkuila3998102008-07-21 02:57:38 -03001336 .name = DRIVER_DESC,
Hans Verkuila3998102008-07-21 02:57:38 -03001337 .fops = &zr364xx_fops,
1338 .ioctl_ops = &zr364xx_ioctl_ops,
Hans Verkuil2b992512012-06-02 06:32:48 -03001339 .release = video_device_release_empty,
Hans Verkuila3998102008-07-21 02:57:38 -03001340};
1341
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001342
1343
1344/*******************/
1345/* USB integration */
1346/*******************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001347static int zr364xx_board_init(struct zr364xx_camera *cam)
1348{
1349 struct zr364xx_pipeinfo *pipe = cam->pipe;
1350 unsigned long i;
1351
1352 DBG("board init: %p\n", cam);
1353 memset(pipe, 0, sizeof(*pipe));
1354 pipe->cam = cam;
1355 pipe->transfer_size = BUFFER_SIZE;
1356
1357 pipe->transfer_buffer = kzalloc(pipe->transfer_size,
1358 GFP_KERNEL);
1359 if (pipe->transfer_buffer == NULL) {
1360 DBG("out of memory!\n");
1361 return -ENOMEM;
1362 }
1363
1364 cam->b_acquire = 0;
1365 cam->frame_count = 0;
1366
1367 /*** start create system buffers ***/
1368 for (i = 0; i < FRAMES; i++) {
1369 /* always allocate maximum size for system buffers */
1370 cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE);
1371
1372 DBG("valloc %p, idx %lu, pdata %p\n",
1373 &cam->buffer.frame[i], i,
1374 cam->buffer.frame[i].lpvbits);
1375 if (cam->buffer.frame[i].lpvbits == NULL) {
1376 printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
1377 "Using less frames\n");
1378 break;
1379 }
1380 }
1381
1382 if (i == 0) {
1383 printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
1384 kfree(cam->pipe->transfer_buffer);
1385 cam->pipe->transfer_buffer = NULL;
1386 return -ENOMEM;
1387 } else
1388 cam->buffer.dwFrames = i;
1389
1390 /* make sure internal states are set */
1391 for (i = 0; i < FRAMES; i++) {
1392 cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE;
1393 cam->buffer.frame[i].cur_size = 0;
1394 }
1395
1396 cam->cur_frame = 0;
1397 cam->last_frame = -1;
1398 /*** end create system buffers ***/
1399
1400 /* start read pipe */
1401 zr364xx_start_readpipe(cam);
1402 DBG(": board initialized\n");
1403 return 0;
1404}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001405
1406static int zr364xx_probe(struct usb_interface *intf,
1407 const struct usb_device_id *id)
1408{
1409 struct usb_device *udev = interface_to_usbdev(intf);
1410 struct zr364xx_camera *cam = NULL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001411 struct usb_host_interface *iface_desc;
1412 struct usb_endpoint_descriptor *endpoint;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001413 struct v4l2_ctrl_handler *hdl;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001414 int err;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001415 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001416
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001417 DBG("probing...\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001418
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001419 dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
1420 dev_info(&intf->dev, "model %04x:%04x detected\n",
1421 le16_to_cpu(udev->descriptor.idVendor),
1422 le16_to_cpu(udev->descriptor.idProduct));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001423
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001424 cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
1425 if (cam == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001426 dev_err(&udev->dev, "cam: out of memory !\n");
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001427 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001428 }
Hans Verkuila906f622012-06-02 07:16:49 -03001429
1430 cam->v4l2_dev.release = zr364xx_release;
1431 err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
1432 if (err < 0) {
1433 dev_err(&udev->dev, "couldn't register v4l2_device\n");
1434 kfree(cam);
1435 return err;
1436 }
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001437 hdl = &cam->ctrl_handler;
1438 v4l2_ctrl_handler_init(hdl, 1);
1439 v4l2_ctrl_new_std(hdl, &zr364xx_ctrl_ops,
1440 V4L2_CID_BRIGHTNESS, 0, 127, 1, 64);
1441 if (hdl->error) {
1442 err = hdl->error;
1443 dev_err(&udev->dev, "couldn't register control\n");
1444 goto fail;
1445 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001446 /* save the init method used by this camera */
1447 cam->method = id->driver_info;
Hans Verkuila906f622012-06-02 07:16:49 -03001448 mutex_init(&cam->lock);
Hans Verkuil2b992512012-06-02 06:32:48 -03001449 cam->vdev = zr364xx_template;
Hans Verkuila906f622012-06-02 07:16:49 -03001450 cam->vdev.lock = &cam->lock;
1451 cam->vdev.v4l2_dev = &cam->v4l2_dev;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001452 cam->vdev.ctrl_handler = &cam->ctrl_handler;
Hans Verkuil2b992512012-06-02 06:32:48 -03001453 video_set_drvdata(&cam->vdev, cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001454
1455 cam->udev = udev;
1456
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001457 switch (mode) {
1458 case 1:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001459 dev_info(&udev->dev, "160x120 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001460 cam->width = 160;
1461 cam->height = 120;
1462 break;
1463 case 2:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001464 dev_info(&udev->dev, "640x480 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001465 cam->width = 640;
1466 cam->height = 480;
1467 break;
1468 default:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001469 dev_info(&udev->dev, "320x240 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001470 cam->width = 320;
1471 cam->height = 240;
1472 break;
1473 }
1474
1475 m0d1[0] = mode;
1476 m1[2].value = 0xf000 + mode;
1477 m2[1].value = 0xf000 + mode;
Antoine Jacquet08135ba2009-12-27 18:22:05 -03001478
1479 /* special case for METHOD3, the modes are different */
1480 if (cam->method == METHOD3) {
1481 switch (mode) {
1482 case 1:
1483 m2[1].value = 0xf000 + 4;
1484 break;
1485 case 2:
1486 m2[1].value = 0xf000 + 0;
1487 break;
1488 default:
1489 m2[1].value = 0xf000 + 1;
1490 break;
1491 }
1492 }
1493
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001494 header2[437] = cam->height / 256;
1495 header2[438] = cam->height % 256;
1496 header2[439] = cam->width / 256;
1497 header2[440] = cam->width % 256;
1498
1499 cam->nb = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001500
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001501 DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf);
1502
1503 /* set up the endpoint information */
1504 iface_desc = intf->cur_altsetting;
1505 DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
1506 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1507 endpoint = &iface_desc->endpoint[i].desc;
1508 if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
1509 /* we found the bulk in endpoint */
1510 cam->read_endpoint = endpoint->bEndpointAddress;
1511 }
1512 }
1513
1514 if (!cam->read_endpoint) {
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001515 err = -ENOMEM;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001516 dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001517 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001518 }
1519
1520 /* v4l */
1521 INIT_LIST_HEAD(&cam->vidq.active);
1522 cam->vidq.cam = cam;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001523
1524 usb_set_intfdata(intf, cam);
1525
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001526 /* load zr364xx board specific */
1527 err = zr364xx_board_init(cam);
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001528 if (!err)
1529 err = v4l2_ctrl_handler_setup(hdl);
1530 if (err)
1531 goto fail;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001532
1533 spin_lock_init(&cam->slock);
1534
Hans Verkuila0657292012-06-02 08:50:31 -03001535 cam->fmt = formats;
1536
1537 videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops,
1538 NULL, &cam->slock,
1539 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1540 V4L2_FIELD_NONE,
1541 sizeof(struct zr364xx_buffer), cam, &cam->lock);
1542
Hans Verkuil2b992512012-06-02 06:32:48 -03001543 err = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
1544 if (err) {
1545 dev_err(&udev->dev, "video_register_device failed\n");
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001546 goto fail;
Hans Verkuil2b992512012-06-02 06:32:48 -03001547 }
1548
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001549 dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
Hans Verkuil2b992512012-06-02 06:32:48 -03001550 video_device_node_name(&cam->vdev));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001551 return 0;
Hans Verkuil1fc21a12012-06-02 07:44:15 -03001552
1553fail:
1554 v4l2_ctrl_handler_free(hdl);
1555 v4l2_device_unregister(&cam->v4l2_dev);
1556 kfree(cam);
1557 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001558}
1559
1560
1561static void zr364xx_disconnect(struct usb_interface *intf)
1562{
1563 struct zr364xx_camera *cam = usb_get_intfdata(intf);
Hans Verkuila906f622012-06-02 07:16:49 -03001564
1565 mutex_lock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001566 usb_set_intfdata(intf, NULL);
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001567 dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
Hans Verkuila906f622012-06-02 07:16:49 -03001568 video_unregister_device(&cam->vdev);
1569 v4l2_device_disconnect(&cam->v4l2_dev);
1570
1571 /* stops the read pipe if it is running */
1572 if (cam->b_acquire)
1573 zr364xx_stop_acquire(cam);
1574
1575 zr364xx_stop_readpipe(cam);
1576 mutex_unlock(&cam->lock);
1577 v4l2_device_put(&cam->v4l2_dev);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001578}
1579
1580
Hans Verkuil587a5762012-06-08 06:43:59 -03001581#ifdef CONFIG_PM
1582static int zr364xx_suspend(struct usb_interface *intf, pm_message_t message)
1583{
1584 struct zr364xx_camera *cam = usb_get_intfdata(intf);
1585
1586 cam->was_streaming = cam->b_acquire;
1587 if (!cam->was_streaming)
1588 return 0;
1589 zr364xx_stop_acquire(cam);
1590 zr364xx_stop_readpipe(cam);
1591 return 0;
1592}
1593
1594static int zr364xx_resume(struct usb_interface *intf)
1595{
1596 struct zr364xx_camera *cam = usb_get_intfdata(intf);
1597 int res;
1598
1599 if (!cam->was_streaming)
1600 return 0;
1601
1602 zr364xx_start_readpipe(cam);
1603 res = zr364xx_prepare(cam);
1604 if (!res)
1605 zr364xx_start_acquire(cam);
1606 return res;
1607}
1608#endif
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001609
1610/**********************/
1611/* Module integration */
1612/**********************/
1613
1614static struct usb_driver zr364xx_driver = {
1615 .name = "zr364xx",
1616 .probe = zr364xx_probe,
1617 .disconnect = zr364xx_disconnect,
Hans Verkuil587a5762012-06-08 06:43:59 -03001618#ifdef CONFIG_PM
1619 .suspend = zr364xx_suspend,
1620 .resume = zr364xx_resume,
1621 .reset_resume = zr364xx_resume,
1622#endif
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001623 .id_table = device_table
1624};
1625
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001626module_usb_driver(zr364xx_driver);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001627
1628MODULE_AUTHOR(DRIVER_AUTHOR);
1629MODULE_DESCRIPTION(DRIVER_DESC);
1630MODULE_LICENSE("GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001631MODULE_VERSION(DRIVER_VERSION);