blob: 2ef110b5221bd961d2d66fe995969cc133f870bb [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>
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030032#include <linux/version.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030033#include <linux/init.h>
34#include <linux/usb.h>
35#include <linux/vmalloc.h>
36#include <linux/slab.h>
37#include <linux/proc_fs.h>
Antoine Jacquet2575f842007-03-05 06:32:29 -030038#include <linux/highmem.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030039#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030040#include <media/v4l2-ioctl.h>
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030041#include <media/videobuf-vmalloc.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030042
43
44/* Version Information */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030045#define DRIVER_VERSION "v0.73"
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -030046#define ZR364XX_VERSION_CODE KERNEL_VERSION(0, 7, 3)
Antoine Jacquetb7eee612007-04-27 12:30:59 -030047#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
48#define DRIVER_DESC "Zoran 364xx"
49
50
51/* Camera */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030052#define FRAMES 1
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -030053#define MAX_FRAME_SIZE 200000
Antoine Jacquetb7eee612007-04-27 12:30:59 -030054#define BUFFER_SIZE 0x1000
55#define CTRL_TIMEOUT 500
56
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030057#define ZR364XX_DEF_BUFS 4
58#define ZR364XX_READ_IDLE 0
59#define ZR364XX_READ_FRAME 1
Antoine Jacquetb7eee612007-04-27 12:30:59 -030060
61/* Debug macro */
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -030062#define DBG(fmt, args...) \
63 do { \
64 if (debug) { \
65 printk(KERN_INFO KBUILD_MODNAME " " fmt, ##args); \
66 } \
67 } while (0)
Antoine Jacquetb7eee612007-04-27 12:30:59 -030068
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -030069/*#define FULL_DEBUG 1*/
70#ifdef FULL_DEBUG
71#define _DBG DBG
72#else
73#define _DBG(fmt, args...)
74#endif
75
Antoine Jacquetb7eee612007-04-27 12:30:59 -030076/* Init methods, need to find nicer names for these
77 * the exact names of the chipsets would be the best if someone finds it */
78#define METHOD0 0
79#define METHOD1 1
80#define METHOD2 2
81
82
83/* Module parameters */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030084static int debug;
85static int mode;
Antoine Jacquetb7eee612007-04-27 12:30:59 -030086
87
88/* Module parameters interface */
89module_param(debug, int, 0644);
90MODULE_PARM_DESC(debug, "Debug level");
91module_param(mode, int, 0644);
92MODULE_PARM_DESC(mode, "0 = 320x240, 1 = 160x120, 2 = 640x480");
93
94
95/* Devices supported by this driver
96 * .driver_info contains the init method used by the camera */
97static struct usb_device_id device_table[] = {
98 {USB_DEVICE(0x08ca, 0x0109), .driver_info = METHOD0 },
99 {USB_DEVICE(0x041e, 0x4024), .driver_info = METHOD0 },
100 {USB_DEVICE(0x0d64, 0x0108), .driver_info = METHOD0 },
101 {USB_DEVICE(0x0546, 0x3187), .driver_info = METHOD0 },
102 {USB_DEVICE(0x0d64, 0x3108), .driver_info = METHOD0 },
103 {USB_DEVICE(0x0595, 0x4343), .driver_info = METHOD0 },
104 {USB_DEVICE(0x0bb0, 0x500d), .driver_info = METHOD0 },
105 {USB_DEVICE(0x0feb, 0x2004), .driver_info = METHOD0 },
106 {USB_DEVICE(0x055f, 0xb500), .driver_info = METHOD0 },
107 {USB_DEVICE(0x08ca, 0x2062), .driver_info = METHOD2 },
108 {USB_DEVICE(0x052b, 0x1a18), .driver_info = METHOD1 },
109 {USB_DEVICE(0x04c8, 0x0729), .driver_info = METHOD0 },
110 {USB_DEVICE(0x04f2, 0xa208), .driver_info = METHOD0 },
111 {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 },
112 {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
113 {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
Antoine Jacquetbebeaea2007-06-25 16:00:34 -0300114 {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
Antoine Jacquet71c04472008-01-25 22:01:53 -0300115 {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
Antoine Jacquetc0e0aff2008-01-25 22:03:10 -0300116 {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
Antoine Jacquetc76b6382009-01-17 22:49:08 -0300117 {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD2 },
Antoine Jacquet9018f6c2009-11-19 22:35:38 -0300118 {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 },
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300119 {} /* Terminating entry */
120};
121
122MODULE_DEVICE_TABLE(usb, device_table);
123
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300124struct zr364xx_mode {
125 u32 color; /* output video color format */
126 u32 brightness; /* brightness */
127};
128
129/* frame structure */
130struct zr364xx_framei {
131 unsigned long ulState; /* ulState:ZR364XX_READ_IDLE,
132 ZR364XX_READ_FRAME */
133 void *lpvbits; /* image data */
134 unsigned long cur_size; /* current data copied to it */
135};
136
137/* image buffer structure */
138struct zr364xx_bufferi {
139 unsigned long dwFrames; /* number of frames in buffer */
140 struct zr364xx_framei frame[FRAMES]; /* array of FRAME structures */
141};
142
143struct zr364xx_dmaqueue {
144 struct list_head active;
145 struct zr364xx_camera *cam;
146};
147
148struct zr364xx_pipeinfo {
149 u32 transfer_size;
150 u8 *transfer_buffer;
151 u32 state;
152 void *stream_urb;
153 void *cam; /* back pointer to zr364xx_camera struct */
154 u32 err_count;
155 u32 idx;
156};
157
158struct zr364xx_fmt {
159 char *name;
160 u32 fourcc;
161 int depth;
162};
163
164/* image formats. */
165static const struct zr364xx_fmt formats[] = {
166 {
167 .name = "JPG",
168 .fourcc = V4L2_PIX_FMT_JPEG,
169 .depth = 24
170 }
171};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300172
173/* Camera stuff */
174struct zr364xx_camera {
175 struct usb_device *udev; /* save off the usb device pointer */
176 struct usb_interface *interface;/* the interface for this device */
177 struct video_device *vdev; /* v4l video device */
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300178 int nb;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300179 struct zr364xx_bufferi buffer;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300180 int skip;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300181 int width;
182 int height;
183 int method;
184 struct mutex lock;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300185 struct mutex open_lock;
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300186 int users;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300187
188 spinlock_t slock;
189 struct zr364xx_dmaqueue vidq;
190 int resources;
191 int last_frame;
192 int cur_frame;
193 unsigned long frame_count;
194 int b_acquire;
195 struct zr364xx_pipeinfo pipe[1];
196
197 u8 read_endpoint;
198
199 const struct zr364xx_fmt *fmt;
200 struct videobuf_queue vb_vidq;
201 enum v4l2_buf_type type;
202 struct zr364xx_mode mode;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300203};
204
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300205/* buffer for one video frame */
206struct zr364xx_buffer {
207 /* common v4l buffer stuff -- must be first */
208 struct videobuf_buffer vb;
209 const struct zr364xx_fmt *fmt;
210};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300211
212/* function used to send initialisation commands to the camera */
213static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
214 u16 index, unsigned char *cp, u16 size)
215{
216 int status;
217
218 unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
219 if (!transfer_buffer) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300220 dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300221 return -ENOMEM;
222 }
223
224 memcpy(transfer_buffer, cp, size);
225
226 status = usb_control_msg(udev,
227 usb_sndctrlpipe(udev, 0),
228 request,
229 USB_DIR_OUT | USB_TYPE_VENDOR |
230 USB_RECIP_DEVICE, value, index,
231 transfer_buffer, size, CTRL_TIMEOUT);
232
233 kfree(transfer_buffer);
234
235 if (status < 0)
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300236 dev_err(&udev->dev,
237 "Failed sending control message, error %d.\n", status);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300238
239 return status;
240}
241
242
243/* Control messages sent to the camera to initialize it
244 * and launch the capture */
245typedef struct {
246 unsigned int value;
247 unsigned int size;
248 unsigned char *bytes;
249} message;
250
251/* method 0 */
252static unsigned char m0d1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
253static unsigned char m0d2[] = { 0, 0, 0, 0, 0, 0 };
254static unsigned char m0d3[] = { 0, 0 };
255static message m0[] = {
256 {0x1f30, 0, NULL},
257 {0xd000, 0, NULL},
258 {0x3370, sizeof(m0d1), m0d1},
259 {0x2000, 0, NULL},
260 {0x2f0f, 0, NULL},
261 {0x2610, sizeof(m0d2), m0d2},
262 {0xe107, 0, NULL},
263 {0x2502, 0, NULL},
264 {0x1f70, 0, NULL},
265 {0xd000, 0, NULL},
266 {0x9a01, sizeof(m0d3), m0d3},
267 {-1, -1, NULL}
268};
269
270/* method 1 */
271static unsigned char m1d1[] = { 0xff, 0xff };
272static unsigned char m1d2[] = { 0x00, 0x00 };
273static message m1[] = {
274 {0x1f30, 0, NULL},
275 {0xd000, 0, NULL},
276 {0xf000, 0, NULL},
277 {0x2000, 0, NULL},
278 {0x2f0f, 0, NULL},
279 {0x2650, 0, NULL},
280 {0xe107, 0, NULL},
281 {0x2502, sizeof(m1d1), m1d1},
282 {0x1f70, 0, NULL},
283 {0xd000, 0, NULL},
284 {0xd000, 0, NULL},
285 {0xd000, 0, NULL},
286 {0x9a01, sizeof(m1d2), m1d2},
287 {-1, -1, NULL}
288};
289
290/* method 2 */
291static unsigned char m2d1[] = { 0xff, 0xff };
292static message m2[] = {
293 {0x1f30, 0, NULL},
294 {0xf000, 0, NULL},
295 {0x2000, 0, NULL},
296 {0x2f0f, 0, NULL},
297 {0x2650, 0, NULL},
298 {0xe107, 0, NULL},
299 {0x2502, sizeof(m2d1), m2d1},
300 {0x1f70, 0, NULL},
301 {-1, -1, NULL}
302};
303
304/* init table */
305static message *init[3] = { m0, m1, m2 };
306
307
308/* JPEG static data in header (Huffman table, etc) */
309static unsigned char header1[] = {
310 0xFF, 0xD8,
311 /*
312 0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F',
313 0x00, 0x01, 0x01, 0x00, 0x33, 0x8A, 0x00, 0x00, 0x33, 0x88,
314 */
315 0xFF, 0xDB, 0x00, 0x84
316};
317static unsigned char header2[] = {
318 0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
319 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
321 0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
322 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
323 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
324 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
325 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33,
326 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25,
327 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
328 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,
329 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
330 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
331 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
332 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
333 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
334 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
335 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
336 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
337 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC4, 0x00, 0x1F,
338 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
339 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
340 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0xC4, 0x00, 0xB5,
341 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
342 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,
343 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
344 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
345 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
346 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27,
347 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
348 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57,
349 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
350 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84,
351 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
352 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
353 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
354 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
355 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,
356 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
357 0xF8, 0xF9, 0xFA, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01,
358 0x40, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
359 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
360 0x00, 0x3F, 0x00
361};
362static unsigned char header3;
363
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300364/* ------------------------------------------------------------------
365 Videobuf operations
366 ------------------------------------------------------------------*/
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300367
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300368static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
369 unsigned int *size)
370{
371 struct zr364xx_camera *cam = vq->priv_data;
372
373 *size = cam->width * cam->height * (cam->fmt->depth >> 3);
374
375 if (*count == 0)
376 *count = ZR364XX_DEF_BUFS;
377
378 while (*size * (*count) > ZR364XX_DEF_BUFS * 1024 * 1024)
379 (*count)--;
380
381 return 0;
382}
383
384static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf)
385{
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300386 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300387
388 if (in_interrupt())
389 BUG();
390
391 videobuf_vmalloc_free(&buf->vb);
392 buf->vb.state = VIDEOBUF_NEEDS_INIT;
393}
394
395static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
396 enum v4l2_field field)
397{
398 struct zr364xx_camera *cam = vq->priv_data;
399 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
400 vb);
401 int rc;
402
403 DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ?
404 cam->fmt->name : "");
405 if (cam->fmt == NULL)
406 return -EINVAL;
407
408 buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3);
409
410 if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) {
411 DBG("invalid buffer prepare\n");
412 return -EINVAL;
413 }
414
415 buf->fmt = cam->fmt;
416 buf->vb.width = cam->width;
417 buf->vb.height = cam->height;
418 buf->vb.field = field;
419
420 if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
421 rc = videobuf_iolock(vq, &buf->vb, NULL);
422 if (rc < 0)
423 goto fail;
424 }
425
426 buf->vb.state = VIDEOBUF_PREPARED;
427 return 0;
428fail:
429 free_buffer(vq, buf);
430 return rc;
431}
432
433static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
434{
435 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
436 vb);
437 struct zr364xx_camera *cam = vq->priv_data;
438
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300439 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300440
441 buf->vb.state = VIDEOBUF_QUEUED;
442 list_add_tail(&buf->vb.queue, &cam->vidq.active);
443}
444
445static void buffer_release(struct videobuf_queue *vq,
446 struct videobuf_buffer *vb)
447{
448 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
449 vb);
450
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300451 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300452 free_buffer(vq, buf);
453}
454
455static struct videobuf_queue_ops zr364xx_video_qops = {
456 .buf_setup = buffer_setup,
457 .buf_prepare = buffer_prepare,
458 .buf_queue = buffer_queue,
459 .buf_release = buffer_release,
460};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300461
462/********************/
463/* V4L2 integration */
464/********************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300465static int zr364xx_vidioc_streamon(struct file *file, void *priv,
466 enum v4l2_buf_type type);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300467
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300468static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300469 loff_t * ppos)
470{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300471 struct zr364xx_camera *cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300472
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300473 _DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300474
475 if (!buf)
476 return -EINVAL;
477
478 if (!count)
479 return -EINVAL;
480
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300481 if (cam->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
482 zr364xx_vidioc_streamon(file, cam, cam->type) == 0) {
483 DBG("%s: reading %d bytes at pos %d.\n", __func__, (int) count,
484 (int) *ppos);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300485
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300486 /* NoMan Sux ! */
487 return videobuf_read_one(&cam->vb_vidq, buf, count, ppos,
488 file->f_flags & O_NONBLOCK);
489 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300490
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300491 return 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300492}
493
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300494/* video buffer vmalloc implementation based partly on VIVI driver which is
495 * Copyright (c) 2006 by
496 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
497 * Ted Walther <ted--a.t--enumera.com>
498 * John Sokol <sokol--a.t--videotechnology.com>
499 * http://v4l.videotechnology.com/
500 *
501 */
502static void zr364xx_fillbuff(struct zr364xx_camera *cam,
503 struct zr364xx_buffer *buf,
504 int jpgsize)
505{
506 int pos = 0;
507 struct timeval ts;
508 const char *tmpbuf;
509 char *vbuf = videobuf_to_vmalloc(&buf->vb);
510 unsigned long last_frame;
511 struct zr364xx_framei *frm;
512
513 if (!vbuf)
514 return;
515
516 last_frame = cam->last_frame;
517 if (last_frame != -1) {
518 frm = &cam->buffer.frame[last_frame];
519 tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits;
520 switch (buf->fmt->fourcc) {
521 case V4L2_PIX_FMT_JPEG:
522 buf->vb.size = jpgsize;
523 memcpy(vbuf, tmpbuf, buf->vb.size);
524 break;
525 default:
526 printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n");
527 }
528 cam->last_frame = -1;
529 } else {
530 printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n");
531 return;
532 }
533 DBG("%s: Buffer 0x%08lx size= %d\n", __func__,
534 (unsigned long)vbuf, pos);
535 /* tell v4l buffer was filled */
536
537 buf->vb.field_count = cam->frame_count * 2;
538 do_gettimeofday(&ts);
539 buf->vb.ts = ts;
540 buf->vb.state = VIDEOBUF_DONE;
541}
542
543static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize)
544{
545 struct zr364xx_dmaqueue *dma_q = &cam->vidq;
546 struct zr364xx_buffer *buf;
547 unsigned long flags = 0;
548 int rc = 0;
549
550 DBG("wakeup: %p\n", &dma_q);
551 spin_lock_irqsave(&cam->slock, flags);
552
553 if (list_empty(&dma_q->active)) {
554 DBG("No active queue to serve\n");
555 rc = -1;
556 goto unlock;
557 }
558 buf = list_entry(dma_q->active.next,
559 struct zr364xx_buffer, vb.queue);
560
561 if (!waitqueue_active(&buf->vb.done)) {
562 /* no one active */
563 rc = -1;
564 goto unlock;
565 }
566 list_del(&buf->vb.queue);
567 do_gettimeofday(&buf->vb.ts);
568 DBG("[%p/%d] wakeup\n", buf, buf->vb.i);
569 zr364xx_fillbuff(cam, buf, jpgsize);
570 wake_up(&buf->vb.done);
571 DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
572unlock:
573 spin_unlock_irqrestore(&cam->slock, flags);
574 return 0;
575}
576
577/* this function moves the usb stream read pipe data
578 * into the system buffers.
579 * returns 0 on success, EAGAIN if more data to process (call this
580 * function again).
581 */
582static int zr364xx_read_video_callback(struct zr364xx_camera *cam,
583 struct zr364xx_pipeinfo *pipe_info,
584 struct urb *purb)
585{
586 unsigned char *pdest;
587 unsigned char *psrc;
588 s32 idx = -1;
589 struct zr364xx_framei *frm;
590 int i = 0;
591 unsigned char *ptr = NULL;
592
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300593 _DBG("buffer to user\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300594 idx = cam->cur_frame;
595 frm = &cam->buffer.frame[idx];
596
597 /* swap bytes if camera needs it */
598 if (cam->method == METHOD0) {
599 u16 *buf = (u16 *)pipe_info->transfer_buffer;
600 for (i = 0; i < purb->actual_length/2; i++)
601 swab16s(buf + i);
602 }
603
604 /* search done. now find out if should be acquiring */
605 if (!cam->b_acquire) {
606 /* we found a frame, but this channel is turned off */
607 frm->ulState = ZR364XX_READ_IDLE;
608 return -EINVAL;
609 }
610
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300611 psrc = (u8 *)pipe_info->transfer_buffer;
612 ptr = pdest = frm->lpvbits;
613
614 if (frm->ulState == ZR364XX_READ_IDLE) {
615 frm->ulState = ZR364XX_READ_FRAME;
616 frm->cur_size = 0;
617
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300618 _DBG("jpeg header, ");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300619 memcpy(ptr, header1, sizeof(header1));
620 ptr += sizeof(header1);
621 header3 = 0;
622 memcpy(ptr, &header3, 1);
623 ptr++;
624 memcpy(ptr, psrc, 64);
625 ptr += 64;
626 header3 = 1;
627 memcpy(ptr, &header3, 1);
628 ptr++;
629 memcpy(ptr, psrc + 64, 64);
630 ptr += 64;
631 memcpy(ptr, header2, sizeof(header2));
632 ptr += sizeof(header2);
633 memcpy(ptr, psrc + 128,
634 purb->actual_length - 128);
635 ptr += purb->actual_length - 128;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300636 _DBG("header : %d %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300637 psrc[0], psrc[1], psrc[2],
638 psrc[3], psrc[4], psrc[5],
639 psrc[6], psrc[7], psrc[8]);
640 frm->cur_size = ptr - pdest;
641 } else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300642 if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) {
643 dev_info(&cam->udev->dev,
644 "%s: buffer (%d bytes) too small to hold "
645 "frame data. Discarding frame data.\n",
646 __func__, MAX_FRAME_SIZE);
647 } else {
648 pdest += frm->cur_size;
649 memcpy(pdest, psrc, purb->actual_length);
650 frm->cur_size += purb->actual_length;
651 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300652 }
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300653 /*_DBG("cur_size %lu urb size %d\n", frm->cur_size,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300654 purb->actual_length);*/
655
656 if (purb->actual_length < pipe_info->transfer_size) {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300657 _DBG("****************Buffer[%d]full*************\n", idx);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300658 cam->last_frame = cam->cur_frame;
659 cam->cur_frame++;
660 /* end of system frame ring buffer, start at zero */
661 if (cam->cur_frame == cam->buffer.dwFrames)
662 cam->cur_frame = 0;
663
664 /* frame ready */
665 /* go back to find the JPEG EOI marker */
666 ptr = pdest = frm->lpvbits;
667 ptr += frm->cur_size - 2;
668 while (ptr > pdest) {
669 if (*ptr == 0xFF && *(ptr + 1) == 0xD9
670 && *(ptr + 2) == 0xFF)
671 break;
672 ptr--;
673 }
674 if (ptr == pdest)
675 DBG("No EOI marker\n");
676
677 /* Sometimes there is junk data in the middle of the picture,
678 * we want to skip this bogus frames */
679 while (ptr > pdest) {
680 if (*ptr == 0xFF && *(ptr + 1) == 0xFF
681 && *(ptr + 2) == 0xFF)
682 break;
683 ptr--;
684 }
685 if (ptr != pdest) {
686 DBG("Bogus frame ? %d\n", ++(cam->nb));
687 } else if (cam->b_acquire) {
688 /* we skip the 2 first frames which are usually buggy */
689 if (cam->skip)
690 cam->skip--;
691 else {
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300692 _DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n",
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300693 frm->cur_size,
694 pdest[0], pdest[1], pdest[2], pdest[3],
695 pdest[4], pdest[5], pdest[6], pdest[7]);
696
697 zr364xx_got_frame(cam, frm->cur_size);
698 }
699 }
700 cam->frame_count++;
701 frm->ulState = ZR364XX_READ_IDLE;
702 frm->cur_size = 0;
703 }
704 /* done successfully */
705 return 0;
706}
707
708static int res_get(struct zr364xx_camera *cam)
709{
710 /* is it free? */
711 mutex_lock(&cam->lock);
712 if (cam->resources) {
713 /* no, someone else uses it */
714 mutex_unlock(&cam->lock);
715 return 0;
716 }
717 /* it's free, grab it */
718 cam->resources = 1;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300719 _DBG("res: get\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300720 mutex_unlock(&cam->lock);
721 return 1;
722}
723
724static inline int res_check(struct zr364xx_camera *cam)
725{
726 return cam->resources;
727}
728
729static void res_free(struct zr364xx_camera *cam)
730{
731 mutex_lock(&cam->lock);
732 cam->resources = 0;
733 mutex_unlock(&cam->lock);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -0300734 _DBG("res: put\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300735}
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300736
737static int zr364xx_vidioc_querycap(struct file *file, void *priv,
738 struct v4l2_capability *cap)
739{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300740 struct zr364xx_camera *cam = video_drvdata(file);
741
742 strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
743 strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
744 strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
745 sizeof(cap->bus_info));
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300746 cap->version = ZR364XX_VERSION_CODE;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300747 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
748 V4L2_CAP_READWRITE |
749 V4L2_CAP_STREAMING;
750
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300751 return 0;
752}
753
754static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
755 struct v4l2_input *i)
756{
757 if (i->index != 0)
758 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300759 strcpy(i->name, DRIVER_DESC " Camera");
760 i->type = V4L2_INPUT_TYPE_CAMERA;
761 return 0;
762}
763
764static int zr364xx_vidioc_g_input(struct file *file, void *priv,
765 unsigned int *i)
766{
767 *i = 0;
768 return 0;
769}
770
771static int zr364xx_vidioc_s_input(struct file *file, void *priv,
772 unsigned int i)
773{
774 if (i != 0)
775 return -EINVAL;
776 return 0;
777}
778
779static int zr364xx_vidioc_queryctrl(struct file *file, void *priv,
780 struct v4l2_queryctrl *c)
781{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300782 struct zr364xx_camera *cam;
783
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300784 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300785 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300786 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300787
788 switch (c->id) {
789 case V4L2_CID_BRIGHTNESS:
790 c->type = V4L2_CTRL_TYPE_INTEGER;
791 strcpy(c->name, "Brightness");
792 c->minimum = 0;
793 c->maximum = 127;
794 c->step = 1;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300795 c->default_value = cam->mode.brightness;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300796 c->flags = 0;
797 break;
798 default:
799 return -EINVAL;
800 }
801 return 0;
802}
803
804static int zr364xx_vidioc_s_ctrl(struct file *file, void *priv,
805 struct v4l2_control *c)
806{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300807 struct zr364xx_camera *cam;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300808 int temp;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300809
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300810 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300811 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300812 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300813
814 switch (c->id) {
815 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300816 cam->mode.brightness = c->value;
817 /* hardware brightness */
818 mutex_lock(&cam->lock);
819 send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
820 temp = (0x60 << 8) + 127 - cam->mode.brightness;
821 send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
822 mutex_unlock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300823 break;
824 default:
825 return -EINVAL;
826 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300827
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300828 return 0;
829}
830
831static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv,
832 struct v4l2_control *c)
833{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300834 struct zr364xx_camera *cam;
835
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300836 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300837 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300838 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300839
840 switch (c->id) {
841 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300842 c->value = cam->mode.brightness;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300843 break;
844 default:
845 return -EINVAL;
846 }
847 return 0;
848}
849
Hans Verkuil78b526a2008-05-28 12:16:41 -0300850static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300851 void *priv, struct v4l2_fmtdesc *f)
852{
853 if (f->index > 0)
854 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300855 f->flags = V4L2_FMT_FLAG_COMPRESSED;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300856 strcpy(f->description, formats[0].name);
857 f->pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300858 return 0;
859}
860
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300861static char *decode_fourcc(__u32 pixelformat, char *buf)
862{
863 buf[0] = pixelformat & 0xff;
864 buf[1] = (pixelformat >> 8) & 0xff;
865 buf[2] = (pixelformat >> 16) & 0xff;
866 buf[3] = (pixelformat >> 24) & 0xff;
867 buf[4] = '\0';
868 return buf;
869}
870
Hans Verkuil78b526a2008-05-28 12:16:41 -0300871static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300872 struct v4l2_format *f)
873{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300874 struct zr364xx_camera *cam = video_drvdata(file);
875 char pixelformat_name[5];
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300876
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300877 if (cam == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300878 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300879
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300880 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
881 DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__,
882 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name));
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300883 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300884 }
885
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300886 if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) &&
887 !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) {
888 f->fmt.pix.width = 320;
889 f->fmt.pix.height = 240;
890 }
891
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300892 f->fmt.pix.field = V4L2_FIELD_NONE;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300893 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
894 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
895 f->fmt.pix.colorspace = 0;
896 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300897 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
898 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
899 f->fmt.pix.field);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300900 return 0;
901}
902
Hans Verkuil78b526a2008-05-28 12:16:41 -0300903static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300904 struct v4l2_format *f)
905{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300906 struct zr364xx_camera *cam;
907
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300908 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300909 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300910 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300911
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300912 f->fmt.pix.pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300913 f->fmt.pix.field = V4L2_FIELD_NONE;
914 f->fmt.pix.width = cam->width;
915 f->fmt.pix.height = cam->height;
916 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
917 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
918 f->fmt.pix.colorspace = 0;
919 f->fmt.pix.priv = 0;
920 return 0;
921}
922
Hans Verkuil78b526a2008-05-28 12:16:41 -0300923static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300924 struct v4l2_format *f)
925{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300926 struct zr364xx_camera *cam = video_drvdata(file);
927 struct videobuf_queue *q = &cam->vb_vidq;
928 char pixelformat_name[5];
929 int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f);
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300930 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300931
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300932 if (ret < 0)
933 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300934
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300935 mutex_lock(&q->vb_lock);
936
937 if (videobuf_queue_is_busy(&cam->vb_vidq)) {
938 DBG("%s queue busy\n", __func__);
939 ret = -EBUSY;
940 goto out;
941 }
942
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300943 if (res_check(cam)) {
944 DBG("%s can't change format after started\n", __func__);
945 ret = -EBUSY;
946 goto out;
947 }
948
949 cam->width = f->fmt.pix.width;
950 cam->height = f->fmt.pix.height;
951 dev_info(&cam->udev->dev, "%s: %dx%d mode selected\n", __func__,
952 cam->width, cam->height);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300953 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
954 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
955 f->fmt.pix.colorspace = 0;
956 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300957 cam->vb_vidq.field = f->fmt.pix.field;
958 cam->mode.color = V4L2_PIX_FMT_JPEG;
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300959
960 if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
961 mode = 1;
962 else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480)
963 mode = 2;
964 else
965 mode = 0;
966
967 m0d1[0] = mode;
968 m1[2].value = 0xf000 + mode;
969 m2[1].value = 0xf000 + mode;
970 header2[437] = cam->height / 256;
971 header2[438] = cam->height % 256;
972 header2[439] = cam->width / 256;
973 header2[440] = cam->width % 256;
974
975 for (i = 0; init[cam->method][i].size != -1; i++) {
976 ret =
977 send_control_msg(cam->udev, 1, init[cam->method][i].value,
978 0, init[cam->method][i].bytes,
979 init[cam->method][i].size);
980 if (ret < 0) {
981 dev_err(&cam->udev->dev,
982 "error during resolution change sequence: %d\n", i);
983 goto out;
984 }
985 }
986
987 /* Added some delay here, since opening/closing the camera quickly,
988 * like Ekiga does during its startup, can crash the webcam
989 */
990 mdelay(100);
991 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300992 ret = 0;
993
994out:
995 mutex_unlock(&q->vb_lock);
996
997 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
998 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
999 f->fmt.pix.field);
1000 return ret;
1001}
1002
1003static int zr364xx_vidioc_reqbufs(struct file *file, void *priv,
1004 struct v4l2_requestbuffers *p)
1005{
1006 int rc;
1007 struct zr364xx_camera *cam = video_drvdata(file);
1008 rc = videobuf_reqbufs(&cam->vb_vidq, p);
1009 return rc;
1010}
1011
1012static int zr364xx_vidioc_querybuf(struct file *file,
1013 void *priv,
1014 struct v4l2_buffer *p)
1015{
1016 int rc;
1017 struct zr364xx_camera *cam = video_drvdata(file);
1018 rc = videobuf_querybuf(&cam->vb_vidq, p);
1019 return rc;
1020}
1021
1022static int zr364xx_vidioc_qbuf(struct file *file,
1023 void *priv,
1024 struct v4l2_buffer *p)
1025{
1026 int rc;
1027 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001028 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001029 rc = videobuf_qbuf(&cam->vb_vidq, p);
1030 return rc;
1031}
1032
1033static int zr364xx_vidioc_dqbuf(struct file *file,
1034 void *priv,
1035 struct v4l2_buffer *p)
1036{
1037 int rc;
1038 struct zr364xx_camera *cam = video_drvdata(file);
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001039 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001040 rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK);
1041 return rc;
1042}
1043
1044static void read_pipe_completion(struct urb *purb)
1045{
1046 struct zr364xx_pipeinfo *pipe_info;
1047 struct zr364xx_camera *cam;
1048 int pipe;
1049
1050 pipe_info = purb->context;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001051 _DBG("%s %p, status %d\n", __func__, purb, purb->status);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001052 if (pipe_info == NULL) {
1053 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
1054 return;
1055 }
1056
1057 cam = pipe_info->cam;
1058 if (cam == NULL) {
1059 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
1060 return;
1061 }
1062
1063 /* if shutting down, do not resubmit, exit immediately */
1064 if (purb->status == -ESHUTDOWN) {
1065 DBG("%s, err shutdown\n", __func__);
1066 pipe_info->err_count++;
1067 return;
1068 }
1069
1070 if (pipe_info->state == 0) {
1071 DBG("exiting USB pipe\n");
1072 return;
1073 }
1074
1075 if (purb->actual_length < 0 ||
1076 purb->actual_length > pipe_info->transfer_size) {
1077 dev_err(&cam->udev->dev, "wrong number of bytes\n");
1078 return;
1079 }
1080
1081 if (purb->status == 0)
1082 zr364xx_read_video_callback(cam, pipe_info, purb);
1083 else {
1084 pipe_info->err_count++;
1085 DBG("%s: failed URB %d\n", __func__, purb->status);
1086 }
1087
1088 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1089
1090 /* reuse urb */
1091 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1092 pipe,
1093 pipe_info->transfer_buffer,
1094 pipe_info->transfer_size,
1095 read_pipe_completion, pipe_info);
1096
1097 if (pipe_info->state != 0) {
1098 purb->status = usb_submit_urb(pipe_info->stream_urb,
1099 GFP_ATOMIC);
1100
1101 if (purb->status)
1102 dev_err(&cam->udev->dev,
1103 "error submitting urb (error=%i)\n",
1104 purb->status);
1105 } else
1106 DBG("read pipe complete state 0\n");
1107}
1108
1109static int zr364xx_start_readpipe(struct zr364xx_camera *cam)
1110{
1111 int pipe;
1112 int retval;
1113 struct zr364xx_pipeinfo *pipe_info = cam->pipe;
1114 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1115 DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint);
1116
1117 pipe_info->state = 1;
1118 pipe_info->err_count = 0;
1119 pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
1120 if (!pipe_info->stream_urb) {
1121 dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n");
1122 return -ENOMEM;
1123 }
1124 /* transfer buffer allocated in board_init */
1125 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1126 pipe,
1127 pipe_info->transfer_buffer,
1128 pipe_info->transfer_size,
1129 read_pipe_completion, pipe_info);
1130
1131 DBG("submitting URB %p\n", pipe_info->stream_urb);
1132 retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
1133 if (retval) {
1134 printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n");
1135 return retval;
1136 }
1137
1138 return 0;
1139}
1140
1141static void zr364xx_stop_readpipe(struct zr364xx_camera *cam)
1142{
1143 struct zr364xx_pipeinfo *pipe_info;
1144
1145 if (cam == NULL) {
1146 printk(KERN_ERR KBUILD_MODNAME ": invalid device\n");
1147 return;
1148 }
1149 DBG("stop read pipe\n");
1150 pipe_info = cam->pipe;
1151 if (pipe_info) {
1152 if (pipe_info->state != 0)
1153 pipe_info->state = 0;
1154
1155 if (pipe_info->stream_urb) {
1156 /* cancel urb */
1157 usb_kill_urb(pipe_info->stream_urb);
1158 usb_free_urb(pipe_info->stream_urb);
1159 pipe_info->stream_urb = NULL;
1160 }
1161 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001162 return;
1163}
1164
1165/* starts acquisition process */
1166static int zr364xx_start_acquire(struct zr364xx_camera *cam)
1167{
1168 int j;
1169
1170 DBG("start acquire\n");
1171
1172 cam->last_frame = -1;
1173 cam->cur_frame = 0;
1174 for (j = 0; j < FRAMES; j++) {
1175 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1176 cam->buffer.frame[j].cur_size = 0;
1177 }
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -03001178 cam->b_acquire = 1;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001179 return 0;
1180}
1181
1182static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam)
1183{
1184 cam->b_acquire = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001185 return 0;
1186}
1187
1188static int zr364xx_vidioc_streamon(struct file *file, void *priv,
1189 enum v4l2_buf_type type)
1190{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001191 struct zr364xx_camera *cam = video_drvdata(file);
1192 int j;
1193 int res;
1194
1195 DBG("%s\n", __func__);
1196
1197 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1198 dev_err(&cam->udev->dev, "invalid fh type0\n");
1199 return -EINVAL;
1200 }
1201 if (cam->type != type) {
1202 dev_err(&cam->udev->dev, "invalid fh type1\n");
1203 return -EINVAL;
1204 }
1205
1206 if (!res_get(cam)) {
1207 dev_err(&cam->udev->dev, "stream busy\n");
1208 return -EBUSY;
1209 }
1210
1211 cam->last_frame = -1;
1212 cam->cur_frame = 0;
1213 cam->frame_count = 0;
1214 for (j = 0; j < FRAMES; j++) {
1215 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1216 cam->buffer.frame[j].cur_size = 0;
1217 }
1218 res = videobuf_streamon(&cam->vb_vidq);
1219 if (res == 0) {
1220 zr364xx_start_acquire(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001221 } else {
1222 res_free(cam);
1223 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001224 return res;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001225}
1226
1227static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
1228 enum v4l2_buf_type type)
1229{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001230 int res;
1231 struct zr364xx_camera *cam = video_drvdata(file);
1232
1233 DBG("%s\n", __func__);
1234 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1235 dev_err(&cam->udev->dev, "invalid fh type0\n");
1236 return -EINVAL;
1237 }
1238 if (cam->type != type) {
1239 dev_err(&cam->udev->dev, "invalid fh type1\n");
1240 return -EINVAL;
1241 }
1242 zr364xx_stop_acquire(cam);
1243 res = videobuf_streamoff(&cam->vb_vidq);
1244 if (res < 0)
1245 return res;
1246 res_free(cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001247 return 0;
1248}
1249
1250
1251/* open the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -03001252static int zr364xx_open(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001253{
1254 struct video_device *vdev = video_devdata(file);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001255 struct zr364xx_camera *cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001256 struct usb_device *udev = cam->udev;
1257 int i, err;
1258
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001259 DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001260
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001261 mutex_lock(&cam->open_lock);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001262
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001263 if (cam->users) {
1264 err = -EBUSY;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001265 goto out;
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001266 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001267
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001268 for (i = 0; init[cam->method][i].size != -1; i++) {
1269 err =
1270 send_control_msg(udev, 1, init[cam->method][i].value,
1271 0, init[cam->method][i].bytes,
1272 init[cam->method][i].size);
1273 if (err < 0) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001274 dev_err(&cam->udev->dev,
1275 "error during open sequence: %d\n", i);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001276 goto out;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001277 }
1278 }
1279
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001280 cam->skip = 2;
1281 cam->users++;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001282 file->private_data = vdev;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001283 cam->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1284 cam->fmt = formats;
1285
1286 videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops,
1287 NULL, &cam->slock,
1288 cam->type,
1289 V4L2_FIELD_NONE,
1290 sizeof(struct zr364xx_buffer), cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001291
1292 /* Added some delay here, since opening/closing the camera quickly,
1293 * like Ekiga does during its startup, can crash the webcam
1294 */
1295 mdelay(100);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001296 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001297
Antoine Jacquet69025c92008-08-18 17:09:53 -03001298out:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001299 mutex_unlock(&cam->open_lock);
1300 DBG("%s: %d\n", __func__, err);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001301 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001302}
1303
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001304static void zr364xx_destroy(struct zr364xx_camera *cam)
1305{
1306 unsigned long i;
1307
1308 if (!cam) {
1309 printk(KERN_ERR KBUILD_MODNAME ", %s: no device\n", __func__);
1310 return;
1311 }
1312 mutex_lock(&cam->open_lock);
1313 if (cam->vdev)
1314 video_unregister_device(cam->vdev);
1315 cam->vdev = NULL;
1316
1317 /* stops the read pipe if it is running */
1318 if (cam->b_acquire)
1319 zr364xx_stop_acquire(cam);
1320
1321 zr364xx_stop_readpipe(cam);
1322
1323 /* release sys buffers */
1324 for (i = 0; i < FRAMES; i++) {
1325 if (cam->buffer.frame[i].lpvbits) {
1326 DBG("vfree %p\n", cam->buffer.frame[i].lpvbits);
1327 vfree(cam->buffer.frame[i].lpvbits);
1328 }
1329 cam->buffer.frame[i].lpvbits = NULL;
1330 }
1331
1332 /* release transfer buffer */
1333 kfree(cam->pipe->transfer_buffer);
1334 cam->pipe->transfer_buffer = NULL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001335 mutex_unlock(&cam->open_lock);
1336 kfree(cam);
1337 cam = NULL;
1338}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001339
1340/* release the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -03001341static int zr364xx_release(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001342{
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001343 struct zr364xx_camera *cam;
1344 struct usb_device *udev;
1345 int i, err;
1346
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001347 DBG("%s\n", __func__);
1348 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001349
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001350 if (!cam)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001351 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001352
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001353 mutex_lock(&cam->open_lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001354 udev = cam->udev;
1355
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001356 /* turn off stream */
1357 if (res_check(cam)) {
1358 if (cam->b_acquire)
1359 zr364xx_stop_acquire(cam);
1360 videobuf_streamoff(&cam->vb_vidq);
1361 res_free(cam);
1362 }
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001363
1364 cam->users--;
1365 file->private_data = NULL;
1366
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001367 for (i = 0; i < 2; i++) {
1368 err =
1369 send_control_msg(udev, 1, init[cam->method][i].value,
Roel Kluin7b808922009-08-11 08:10:25 -03001370 0, init[cam->method][i].bytes,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001371 init[cam->method][i].size);
1372 if (err < 0) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001373 dev_err(&udev->dev, "error during release sequence\n");
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001374 goto out;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001375 }
1376 }
1377
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001378 /* Added some delay here, since opening/closing the camera quickly,
1379 * like Ekiga does during its startup, can crash the webcam
1380 */
1381 mdelay(100);
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001382 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001383
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001384out:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001385 mutex_unlock(&cam->open_lock);
1386
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001387 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001388}
1389
1390
1391static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
1392{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001393 struct zr364xx_camera *cam = video_drvdata(file);
1394 int ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001395
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001396 if (cam == NULL) {
1397 DBG("%s: cam == NULL\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001398 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001399 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001400 DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001401
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001402 ret = videobuf_mmap_mapper(&cam->vb_vidq, vma);
1403
1404 DBG("vma start=0x%08lx, size=%ld, ret=%d\n",
1405 (unsigned long)vma->vm_start,
1406 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
1407 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001408}
1409
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001410static unsigned int zr364xx_poll(struct file *file,
1411 struct poll_table_struct *wait)
1412{
1413 struct zr364xx_camera *cam = video_drvdata(file);
1414 struct videobuf_queue *q = &cam->vb_vidq;
Lamarque Vieira Souza76594c52009-07-22 16:54:51 -03001415 _DBG("%s\n", __func__);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001416
1417 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1418 return POLLERR;
1419
1420 return videobuf_poll_stream(file, q, wait);
1421}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001422
Hans Verkuilbec43662008-12-30 06:58:20 -03001423static const struct v4l2_file_operations zr364xx_fops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001424 .owner = THIS_MODULE,
1425 .open = zr364xx_open,
1426 .release = zr364xx_release,
1427 .read = zr364xx_read,
1428 .mmap = zr364xx_mmap,
1429 .ioctl = video_ioctl2,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001430 .poll = zr364xx_poll,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001431};
1432
Hans Verkuila3998102008-07-21 02:57:38 -03001433static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001434 .vidioc_querycap = zr364xx_vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001435 .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
1436 .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
1437 .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
1438 .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001439 .vidioc_enum_input = zr364xx_vidioc_enum_input,
1440 .vidioc_g_input = zr364xx_vidioc_g_input,
1441 .vidioc_s_input = zr364xx_vidioc_s_input,
1442 .vidioc_streamon = zr364xx_vidioc_streamon,
1443 .vidioc_streamoff = zr364xx_vidioc_streamoff,
1444 .vidioc_queryctrl = zr364xx_vidioc_queryctrl,
1445 .vidioc_g_ctrl = zr364xx_vidioc_g_ctrl,
1446 .vidioc_s_ctrl = zr364xx_vidioc_s_ctrl,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001447 .vidioc_reqbufs = zr364xx_vidioc_reqbufs,
1448 .vidioc_querybuf = zr364xx_vidioc_querybuf,
1449 .vidioc_qbuf = zr364xx_vidioc_qbuf,
1450 .vidioc_dqbuf = zr364xx_vidioc_dqbuf,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001451};
1452
Hans Verkuila3998102008-07-21 02:57:38 -03001453static struct video_device zr364xx_template = {
Hans Verkuila3998102008-07-21 02:57:38 -03001454 .name = DRIVER_DESC,
Hans Verkuila3998102008-07-21 02:57:38 -03001455 .fops = &zr364xx_fops,
1456 .ioctl_ops = &zr364xx_ioctl_ops,
1457 .release = video_device_release,
1458 .minor = -1,
1459};
1460
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001461
1462
1463/*******************/
1464/* USB integration */
1465/*******************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001466static int zr364xx_board_init(struct zr364xx_camera *cam)
1467{
1468 struct zr364xx_pipeinfo *pipe = cam->pipe;
1469 unsigned long i;
1470
1471 DBG("board init: %p\n", cam);
1472 memset(pipe, 0, sizeof(*pipe));
1473 pipe->cam = cam;
1474 pipe->transfer_size = BUFFER_SIZE;
1475
1476 pipe->transfer_buffer = kzalloc(pipe->transfer_size,
1477 GFP_KERNEL);
1478 if (pipe->transfer_buffer == NULL) {
1479 DBG("out of memory!\n");
1480 return -ENOMEM;
1481 }
1482
1483 cam->b_acquire = 0;
1484 cam->frame_count = 0;
1485
1486 /*** start create system buffers ***/
1487 for (i = 0; i < FRAMES; i++) {
1488 /* always allocate maximum size for system buffers */
1489 cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE);
1490
1491 DBG("valloc %p, idx %lu, pdata %p\n",
1492 &cam->buffer.frame[i], i,
1493 cam->buffer.frame[i].lpvbits);
1494 if (cam->buffer.frame[i].lpvbits == NULL) {
1495 printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
1496 "Using less frames\n");
1497 break;
1498 }
1499 }
1500
1501 if (i == 0) {
1502 printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
1503 kfree(cam->pipe->transfer_buffer);
1504 cam->pipe->transfer_buffer = NULL;
1505 return -ENOMEM;
1506 } else
1507 cam->buffer.dwFrames = i;
1508
1509 /* make sure internal states are set */
1510 for (i = 0; i < FRAMES; i++) {
1511 cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE;
1512 cam->buffer.frame[i].cur_size = 0;
1513 }
1514
1515 cam->cur_frame = 0;
1516 cam->last_frame = -1;
1517 /*** end create system buffers ***/
1518
1519 /* start read pipe */
1520 zr364xx_start_readpipe(cam);
1521 DBG(": board initialized\n");
1522 return 0;
1523}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001524
1525static int zr364xx_probe(struct usb_interface *intf,
1526 const struct usb_device_id *id)
1527{
1528 struct usb_device *udev = interface_to_usbdev(intf);
1529 struct zr364xx_camera *cam = NULL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001530 struct usb_host_interface *iface_desc;
1531 struct usb_endpoint_descriptor *endpoint;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001532 int err;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001533 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001534
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001535 DBG("probing...\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001536
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001537 dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
1538 dev_info(&intf->dev, "model %04x:%04x detected\n",
1539 le16_to_cpu(udev->descriptor.idVendor),
1540 le16_to_cpu(udev->descriptor.idProduct));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001541
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001542 cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
1543 if (cam == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001544 dev_err(&udev->dev, "cam: out of memory !\n");
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001545 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001546 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001547 /* save the init method used by this camera */
1548 cam->method = id->driver_info;
1549
1550 cam->vdev = video_device_alloc();
1551 if (cam->vdev == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001552 dev_err(&udev->dev, "cam->vdev: out of memory !\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001553 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001554 cam = NULL;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001555 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001556 }
1557 memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template));
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001558 cam->vdev->parent = &intf->dev;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001559 video_set_drvdata(cam->vdev, cam);
1560 if (debug)
1561 cam->vdev->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
1562
1563 cam->udev = udev;
1564
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001565 switch (mode) {
1566 case 1:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001567 dev_info(&udev->dev, "160x120 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001568 cam->width = 160;
1569 cam->height = 120;
1570 break;
1571 case 2:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001572 dev_info(&udev->dev, "640x480 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001573 cam->width = 640;
1574 cam->height = 480;
1575 break;
1576 default:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001577 dev_info(&udev->dev, "320x240 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001578 cam->width = 320;
1579 cam->height = 240;
1580 break;
1581 }
1582
1583 m0d1[0] = mode;
1584 m1[2].value = 0xf000 + mode;
1585 m2[1].value = 0xf000 + mode;
1586 header2[437] = cam->height / 256;
1587 header2[438] = cam->height % 256;
1588 header2[439] = cam->width / 256;
1589 header2[440] = cam->width % 256;
1590
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001591 cam->users = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001592 cam->nb = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001593 cam->mode.brightness = 64;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001594 mutex_init(&cam->lock);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001595 mutex_init(&cam->open_lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001596
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001597 DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf);
1598
1599 /* set up the endpoint information */
1600 iface_desc = intf->cur_altsetting;
1601 DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
1602 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1603 endpoint = &iface_desc->endpoint[i].desc;
1604 if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
1605 /* we found the bulk in endpoint */
1606 cam->read_endpoint = endpoint->bEndpointAddress;
1607 }
1608 }
1609
1610 if (!cam->read_endpoint) {
1611 dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
1612 return -ENOMEM;
1613 }
1614
1615 /* v4l */
1616 INIT_LIST_HEAD(&cam->vidq.active);
1617 cam->vidq.cam = cam;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001618 err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1);
1619 if (err) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001620 dev_err(&udev->dev, "video_register_device failed\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001621 video_device_release(cam->vdev);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001622 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001623 cam = NULL;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001624 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001625 }
1626
1627 usb_set_intfdata(intf, cam);
1628
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001629 /* load zr364xx board specific */
1630 err = zr364xx_board_init(cam);
1631 if (err) {
1632 spin_lock_init(&cam->slock);
1633 return err;
1634 }
1635
1636 spin_lock_init(&cam->slock);
1637
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001638 dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n",
Hans Verkuilc6330fb2008-10-19 18:54:26 -03001639 cam->vdev->num);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001640 return 0;
1641}
1642
1643
1644static void zr364xx_disconnect(struct usb_interface *intf)
1645{
1646 struct zr364xx_camera *cam = usb_get_intfdata(intf);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001647 videobuf_mmap_free(&cam->vb_vidq);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001648 usb_set_intfdata(intf, NULL);
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001649 dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001650 zr364xx_destroy(cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001651}
1652
1653
1654
1655/**********************/
1656/* Module integration */
1657/**********************/
1658
1659static struct usb_driver zr364xx_driver = {
1660 .name = "zr364xx",
1661 .probe = zr364xx_probe,
1662 .disconnect = zr364xx_disconnect,
1663 .id_table = device_table
1664};
1665
1666
1667static int __init zr364xx_init(void)
1668{
1669 int retval;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001670 retval = usb_register(&zr364xx_driver);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001671 if (retval)
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001672 printk(KERN_ERR KBUILD_MODNAME ": usb_register failed!\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001673 else
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001674 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001675 return retval;
1676}
1677
1678
1679static void __exit zr364xx_exit(void)
1680{
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001681 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC " module unloaded\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001682 usb_deregister(&zr364xx_driver);
1683}
1684
1685
1686module_init(zr364xx_init);
1687module_exit(zr364xx_exit);
1688
1689MODULE_AUTHOR(DRIVER_AUTHOR);
1690MODULE_DESCRIPTION(DRIVER_DESC);
1691MODULE_LICENSE("GPL");