blob: f2f8cdd71c46df382f77bcfda9598038cfd372be [file] [log] [blame]
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001/*
2 * Zoran 364xx based USB webcam module version 0.72
3 *
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 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28
29#include <linux/version.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/usb.h>
33#include <linux/vmalloc.h>
34#include <linux/slab.h>
35#include <linux/proc_fs.h>
Antoine Jacquet2575f842007-03-05 06:32:29 -030036#include <linux/highmem.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030037#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030038#include <media/v4l2-ioctl.h>
Antoine Jacquetb7eee612007-04-27 12:30:59 -030039
40
41/* Version Information */
42#define DRIVER_VERSION "v0.72"
43#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
44#define DRIVER_DESC "Zoran 364xx"
45
46
47/* Camera */
48#define FRAMES 2
49#define MAX_FRAME_SIZE 100000
50#define BUFFER_SIZE 0x1000
51#define CTRL_TIMEOUT 500
52
53
54/* Debug macro */
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -030055#define DBG(x...) if (debug) printk(KERN_INFO KBUILD_MODNAME x)
Antoine Jacquetb7eee612007-04-27 12:30:59 -030056
57
58/* Init methods, need to find nicer names for these
59 * the exact names of the chipsets would be the best if someone finds it */
60#define METHOD0 0
61#define METHOD1 1
62#define METHOD2 2
63
64
65/* Module parameters */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030066static int debug;
67static int mode;
Antoine Jacquetb7eee612007-04-27 12:30:59 -030068
69
70/* Module parameters interface */
71module_param(debug, int, 0644);
72MODULE_PARM_DESC(debug, "Debug level");
73module_param(mode, int, 0644);
74MODULE_PARM_DESC(mode, "0 = 320x240, 1 = 160x120, 2 = 640x480");
75
76
77/* Devices supported by this driver
78 * .driver_info contains the init method used by the camera */
79static struct usb_device_id device_table[] = {
80 {USB_DEVICE(0x08ca, 0x0109), .driver_info = METHOD0 },
81 {USB_DEVICE(0x041e, 0x4024), .driver_info = METHOD0 },
82 {USB_DEVICE(0x0d64, 0x0108), .driver_info = METHOD0 },
83 {USB_DEVICE(0x0546, 0x3187), .driver_info = METHOD0 },
84 {USB_DEVICE(0x0d64, 0x3108), .driver_info = METHOD0 },
85 {USB_DEVICE(0x0595, 0x4343), .driver_info = METHOD0 },
86 {USB_DEVICE(0x0bb0, 0x500d), .driver_info = METHOD0 },
87 {USB_DEVICE(0x0feb, 0x2004), .driver_info = METHOD0 },
88 {USB_DEVICE(0x055f, 0xb500), .driver_info = METHOD0 },
89 {USB_DEVICE(0x08ca, 0x2062), .driver_info = METHOD2 },
90 {USB_DEVICE(0x052b, 0x1a18), .driver_info = METHOD1 },
91 {USB_DEVICE(0x04c8, 0x0729), .driver_info = METHOD0 },
92 {USB_DEVICE(0x04f2, 0xa208), .driver_info = METHOD0 },
93 {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 },
94 {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
95 {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
Antoine Jacquetbebeaea2007-06-25 16:00:34 -030096 {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
Antoine Jacquet71c04472008-01-25 22:01:53 -030097 {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
Antoine Jacquetc0e0aff2008-01-25 22:03:10 -030098 {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
Antoine Jacquetc76b6382009-01-17 22:49:08 -030099 {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD2 },
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300100 {} /* Terminating entry */
101};
102
103MODULE_DEVICE_TABLE(usb, device_table);
104
105
106/* Camera stuff */
107struct zr364xx_camera {
108 struct usb_device *udev; /* save off the usb device pointer */
109 struct usb_interface *interface;/* the interface for this device */
110 struct video_device *vdev; /* v4l video device */
111 u8 *framebuf;
112 int nb;
113 unsigned char *buffer;
114 int skip;
115 int brightness;
116 int width;
117 int height;
118 int method;
119 struct mutex lock;
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300120 int users;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300121};
122
123
124/* function used to send initialisation commands to the camera */
125static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
126 u16 index, unsigned char *cp, u16 size)
127{
128 int status;
129
130 unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
131 if (!transfer_buffer) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300132 dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300133 return -ENOMEM;
134 }
135
136 memcpy(transfer_buffer, cp, size);
137
138 status = usb_control_msg(udev,
139 usb_sndctrlpipe(udev, 0),
140 request,
141 USB_DIR_OUT | USB_TYPE_VENDOR |
142 USB_RECIP_DEVICE, value, index,
143 transfer_buffer, size, CTRL_TIMEOUT);
144
145 kfree(transfer_buffer);
146
147 if (status < 0)
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300148 dev_err(&udev->dev,
149 "Failed sending control message, error %d.\n", status);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300150
151 return status;
152}
153
154
155/* Control messages sent to the camera to initialize it
156 * and launch the capture */
157typedef struct {
158 unsigned int value;
159 unsigned int size;
160 unsigned char *bytes;
161} message;
162
163/* method 0 */
164static unsigned char m0d1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
165static unsigned char m0d2[] = { 0, 0, 0, 0, 0, 0 };
166static unsigned char m0d3[] = { 0, 0 };
167static message m0[] = {
168 {0x1f30, 0, NULL},
169 {0xd000, 0, NULL},
170 {0x3370, sizeof(m0d1), m0d1},
171 {0x2000, 0, NULL},
172 {0x2f0f, 0, NULL},
173 {0x2610, sizeof(m0d2), m0d2},
174 {0xe107, 0, NULL},
175 {0x2502, 0, NULL},
176 {0x1f70, 0, NULL},
177 {0xd000, 0, NULL},
178 {0x9a01, sizeof(m0d3), m0d3},
179 {-1, -1, NULL}
180};
181
182/* method 1 */
183static unsigned char m1d1[] = { 0xff, 0xff };
184static unsigned char m1d2[] = { 0x00, 0x00 };
185static message m1[] = {
186 {0x1f30, 0, NULL},
187 {0xd000, 0, NULL},
188 {0xf000, 0, NULL},
189 {0x2000, 0, NULL},
190 {0x2f0f, 0, NULL},
191 {0x2650, 0, NULL},
192 {0xe107, 0, NULL},
193 {0x2502, sizeof(m1d1), m1d1},
194 {0x1f70, 0, NULL},
195 {0xd000, 0, NULL},
196 {0xd000, 0, NULL},
197 {0xd000, 0, NULL},
198 {0x9a01, sizeof(m1d2), m1d2},
199 {-1, -1, NULL}
200};
201
202/* method 2 */
203static unsigned char m2d1[] = { 0xff, 0xff };
204static message m2[] = {
205 {0x1f30, 0, NULL},
206 {0xf000, 0, NULL},
207 {0x2000, 0, NULL},
208 {0x2f0f, 0, NULL},
209 {0x2650, 0, NULL},
210 {0xe107, 0, NULL},
211 {0x2502, sizeof(m2d1), m2d1},
212 {0x1f70, 0, NULL},
213 {-1, -1, NULL}
214};
215
216/* init table */
217static message *init[3] = { m0, m1, m2 };
218
219
220/* JPEG static data in header (Huffman table, etc) */
221static unsigned char header1[] = {
222 0xFF, 0xD8,
223 /*
224 0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F',
225 0x00, 0x01, 0x01, 0x00, 0x33, 0x8A, 0x00, 0x00, 0x33, 0x88,
226 */
227 0xFF, 0xDB, 0x00, 0x84
228};
229static unsigned char header2[] = {
230 0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
231 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
233 0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
234 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
235 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
236 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
237 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33,
238 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25,
239 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
240 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,
241 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
242 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
243 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
244 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
245 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
246 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
247 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
248 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
249 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC4, 0x00, 0x1F,
250 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
251 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
252 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0xC4, 0x00, 0xB5,
253 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
254 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,
255 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
256 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
257 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
258 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27,
259 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
260 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57,
261 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
262 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84,
263 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
264 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
265 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
266 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
267 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,
268 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
269 0xF8, 0xF9, 0xFA, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01,
270 0x40, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
271 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
272 0x00, 0x3F, 0x00
273};
274static unsigned char header3;
275
276
277
278/********************/
279/* V4L2 integration */
280/********************/
281
282/* this function reads a full JPEG picture synchronously
283 * TODO: do it asynchronously... */
284static int read_frame(struct zr364xx_camera *cam, int framenum)
285{
286 int i, n, temp, head, size, actual_length;
Trent Piepho93566ad2007-03-07 18:19:49 -0300287 unsigned char *ptr = NULL, *jpeg;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300288
289 redo:
290 /* hardware brightness */
291 n = send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
292 temp = (0x60 << 8) + 127 - cam->brightness;
293 n = send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
294
295 /* during the first loop we are going to insert JPEG header */
296 head = 0;
297 /* this is the place in memory where we are going to build
298 * the JPEG image */
299 jpeg = cam->framebuf + framenum * MAX_FRAME_SIZE;
300 /* read data... */
301 do {
302 n = usb_bulk_msg(cam->udev,
303 usb_rcvbulkpipe(cam->udev, 0x81),
304 cam->buffer, BUFFER_SIZE, &actual_length,
305 CTRL_TIMEOUT);
306 DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]);
307 DBG("bulk : n=%d size=%d", n, actual_length);
308 if (n < 0) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300309 dev_err(&cam->udev->dev, "error reading bulk msg\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300310 return 0;
311 }
312 if (actual_length < 0 || actual_length > BUFFER_SIZE) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300313 dev_err(&cam->udev->dev, "wrong number of bytes\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300314 return 0;
315 }
316
317 /* swap bytes if camera needs it */
Trent Piepho93566ad2007-03-07 18:19:49 -0300318 if (cam->method == METHOD0) {
319 u16 *buf = (u16*)cam->buffer;
320 for (i = 0; i < BUFFER_SIZE/2; i++)
321 swab16s(buf + i);
322 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300323
324 /* write the JPEG header */
325 if (!head) {
326 DBG("jpeg header");
327 ptr = jpeg;
328 memcpy(ptr, header1, sizeof(header1));
329 ptr += sizeof(header1);
330 header3 = 0;
331 memcpy(ptr, &header3, 1);
332 ptr++;
333 memcpy(ptr, cam->buffer, 64);
334 ptr += 64;
335 header3 = 1;
336 memcpy(ptr, &header3, 1);
337 ptr++;
338 memcpy(ptr, cam->buffer + 64, 64);
339 ptr += 64;
340 memcpy(ptr, header2, sizeof(header2));
341 ptr += sizeof(header2);
342 memcpy(ptr, cam->buffer + 128,
343 actual_length - 128);
344 ptr += actual_length - 128;
345 head = 1;
346 DBG("header : %d %d %d %d %d %d %d %d %d",
347 cam->buffer[0], cam->buffer[1], cam->buffer[2],
348 cam->buffer[3], cam->buffer[4], cam->buffer[5],
349 cam->buffer[6], cam->buffer[7], cam->buffer[8]);
350 } else {
351 memcpy(ptr, cam->buffer, actual_length);
352 ptr += actual_length;
353 }
354 }
355 /* ... until there is no more */
356 while (actual_length == BUFFER_SIZE);
357
358 /* we skip the 2 first frames which are usually buggy */
359 if (cam->skip) {
360 cam->skip--;
361 goto redo;
362 }
363
364 /* go back to find the JPEG EOI marker */
365 size = ptr - jpeg;
366 ptr -= 2;
367 while (ptr > jpeg) {
368 if (*ptr == 0xFF && *(ptr + 1) == 0xD9
369 && *(ptr + 2) == 0xFF)
370 break;
371 ptr--;
372 }
373 if (ptr == jpeg)
374 DBG("No EOI marker");
375
376 /* Sometimes there is junk data in the middle of the picture,
377 * we want to skip this bogus frames */
378 while (ptr > jpeg) {
379 if (*ptr == 0xFF && *(ptr + 1) == 0xFF
380 && *(ptr + 2) == 0xFF)
381 break;
382 ptr--;
383 }
384 if (ptr != jpeg) {
385 DBG("Bogus frame ? %d", cam->nb);
386 goto redo;
387 }
388
389 DBG("jpeg : %d %d %d %d %d %d %d %d",
390 jpeg[0], jpeg[1], jpeg[2], jpeg[3],
391 jpeg[4], jpeg[5], jpeg[6], jpeg[7]);
392
393 return size;
394}
395
396
Al Viro97cf0102008-03-29 03:10:48 +0000397static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t cnt,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300398 loff_t * ppos)
399{
400 unsigned long count = cnt;
401 struct video_device *vdev = video_devdata(file);
402 struct zr364xx_camera *cam;
403
404 DBG("zr364xx_read: read %d bytes.", (int) count);
405
406 if (vdev == NULL)
407 return -ENODEV;
408 cam = video_get_drvdata(vdev);
409
410 if (!buf)
411 return -EINVAL;
412
413 if (!count)
414 return -EINVAL;
415
416 /* NoMan Sux ! */
417 count = read_frame(cam, 0);
418
419 if (copy_to_user(buf, cam->framebuf, count))
420 return -EFAULT;
421
422 return count;
423}
424
425
426static int zr364xx_vidioc_querycap(struct file *file, void *priv,
427 struct v4l2_capability *cap)
428{
429 memset(cap, 0, sizeof(*cap));
430 strcpy(cap->driver, DRIVER_DESC);
431 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
432 return 0;
433}
434
435static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
436 struct v4l2_input *i)
437{
438 if (i->index != 0)
439 return -EINVAL;
440 memset(i, 0, sizeof(*i));
441 i->index = 0;
442 strcpy(i->name, DRIVER_DESC " Camera");
443 i->type = V4L2_INPUT_TYPE_CAMERA;
444 return 0;
445}
446
447static int zr364xx_vidioc_g_input(struct file *file, void *priv,
448 unsigned int *i)
449{
450 *i = 0;
451 return 0;
452}
453
454static int zr364xx_vidioc_s_input(struct file *file, void *priv,
455 unsigned int i)
456{
457 if (i != 0)
458 return -EINVAL;
459 return 0;
460}
461
462static int zr364xx_vidioc_queryctrl(struct file *file, void *priv,
463 struct v4l2_queryctrl *c)
464{
465 struct video_device *vdev = video_devdata(file);
466 struct zr364xx_camera *cam;
467
468 if (vdev == NULL)
469 return -ENODEV;
470 cam = video_get_drvdata(vdev);
471
472 switch (c->id) {
473 case V4L2_CID_BRIGHTNESS:
474 c->type = V4L2_CTRL_TYPE_INTEGER;
475 strcpy(c->name, "Brightness");
476 c->minimum = 0;
477 c->maximum = 127;
478 c->step = 1;
479 c->default_value = cam->brightness;
480 c->flags = 0;
481 break;
482 default:
483 return -EINVAL;
484 }
485 return 0;
486}
487
488static int zr364xx_vidioc_s_ctrl(struct file *file, void *priv,
489 struct v4l2_control *c)
490{
491 struct video_device *vdev = video_devdata(file);
492 struct zr364xx_camera *cam;
493
494 if (vdev == NULL)
495 return -ENODEV;
496 cam = video_get_drvdata(vdev);
497
498 switch (c->id) {
499 case V4L2_CID_BRIGHTNESS:
500 cam->brightness = c->value;
501 break;
502 default:
503 return -EINVAL;
504 }
505 return 0;
506}
507
508static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv,
509 struct v4l2_control *c)
510{
511 struct video_device *vdev = video_devdata(file);
512 struct zr364xx_camera *cam;
513
514 if (vdev == NULL)
515 return -ENODEV;
516 cam = video_get_drvdata(vdev);
517
518 switch (c->id) {
519 case V4L2_CID_BRIGHTNESS:
520 c->value = cam->brightness;
521 break;
522 default:
523 return -EINVAL;
524 }
525 return 0;
526}
527
Hans Verkuil78b526a2008-05-28 12:16:41 -0300528static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300529 void *priv, struct v4l2_fmtdesc *f)
530{
531 if (f->index > 0)
532 return -EINVAL;
533 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
534 return -EINVAL;
535 memset(f, 0, sizeof(*f));
536 f->index = 0;
537 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
538 f->flags = V4L2_FMT_FLAG_COMPRESSED;
539 strcpy(f->description, "JPEG");
540 f->pixelformat = V4L2_PIX_FMT_JPEG;
541 return 0;
542}
543
Hans Verkuil78b526a2008-05-28 12:16:41 -0300544static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300545 struct v4l2_format *f)
546{
547 struct video_device *vdev = video_devdata(file);
548 struct zr364xx_camera *cam;
549
550 if (vdev == NULL)
551 return -ENODEV;
552 cam = video_get_drvdata(vdev);
553
554 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
555 return -EINVAL;
556 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG)
557 return -EINVAL;
558 if (f->fmt.pix.field != V4L2_FIELD_ANY &&
559 f->fmt.pix.field != V4L2_FIELD_NONE)
560 return -EINVAL;
561 f->fmt.pix.field = V4L2_FIELD_NONE;
562 f->fmt.pix.width = cam->width;
563 f->fmt.pix.height = cam->height;
564 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
565 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
566 f->fmt.pix.colorspace = 0;
567 f->fmt.pix.priv = 0;
568 return 0;
569}
570
Hans Verkuil78b526a2008-05-28 12:16:41 -0300571static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300572 struct v4l2_format *f)
573{
574 struct video_device *vdev = video_devdata(file);
575 struct zr364xx_camera *cam;
576
577 if (vdev == NULL)
578 return -ENODEV;
579 cam = video_get_drvdata(vdev);
580
581 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
582 return -EINVAL;
583 memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
584 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
585 f->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
586 f->fmt.pix.field = V4L2_FIELD_NONE;
587 f->fmt.pix.width = cam->width;
588 f->fmt.pix.height = cam->height;
589 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
590 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
591 f->fmt.pix.colorspace = 0;
592 f->fmt.pix.priv = 0;
593 return 0;
594}
595
Hans Verkuil78b526a2008-05-28 12:16:41 -0300596static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300597 struct v4l2_format *f)
598{
599 struct video_device *vdev = video_devdata(file);
600 struct zr364xx_camera *cam;
601
602 if (vdev == NULL)
603 return -ENODEV;
604 cam = video_get_drvdata(vdev);
605
606 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
607 return -EINVAL;
608 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG)
609 return -EINVAL;
610 if (f->fmt.pix.field != V4L2_FIELD_ANY &&
611 f->fmt.pix.field != V4L2_FIELD_NONE)
612 return -EINVAL;
613 f->fmt.pix.field = V4L2_FIELD_NONE;
614 f->fmt.pix.width = cam->width;
615 f->fmt.pix.height = cam->height;
616 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
617 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
618 f->fmt.pix.colorspace = 0;
619 f->fmt.pix.priv = 0;
620 DBG("ok!");
621 return 0;
622}
623
624static int zr364xx_vidioc_streamon(struct file *file, void *priv,
625 enum v4l2_buf_type type)
626{
627 return 0;
628}
629
630static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
631 enum v4l2_buf_type type)
632{
633 return 0;
634}
635
636
637/* open the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -0300638static int zr364xx_open(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300639{
640 struct video_device *vdev = video_devdata(file);
641 struct zr364xx_camera *cam = video_get_drvdata(vdev);
642 struct usb_device *udev = cam->udev;
643 int i, err;
644
645 DBG("zr364xx_open");
646
Antoine Jacquet69025c92008-08-18 17:09:53 -0300647 mutex_lock(&cam->lock);
648
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300649 if (cam->users) {
650 err = -EBUSY;
Antoine Jacquet69025c92008-08-18 17:09:53 -0300651 goto out;
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300652 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300653
654 if (!cam->framebuf) {
655 cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES);
656 if (!cam->framebuf) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300657 dev_err(&cam->udev->dev, "vmalloc_32 failed!\n");
Antoine Jacquet69025c92008-08-18 17:09:53 -0300658 err = -ENOMEM;
659 goto out;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300660 }
661 }
662
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300663 for (i = 0; init[cam->method][i].size != -1; i++) {
664 err =
665 send_control_msg(udev, 1, init[cam->method][i].value,
666 0, init[cam->method][i].bytes,
667 init[cam->method][i].size);
668 if (err < 0) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300669 dev_err(&cam->udev->dev,
670 "error during open sequence: %d\n", i);
Antoine Jacquet69025c92008-08-18 17:09:53 -0300671 goto out;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300672 }
673 }
674
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300675 cam->skip = 2;
676 cam->users++;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300677 file->private_data = vdev;
678
679 /* Added some delay here, since opening/closing the camera quickly,
680 * like Ekiga does during its startup, can crash the webcam
681 */
682 mdelay(100);
Antoine Jacquet69025c92008-08-18 17:09:53 -0300683 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300684
Antoine Jacquet69025c92008-08-18 17:09:53 -0300685out:
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300686 mutex_unlock(&cam->lock);
Antoine Jacquet69025c92008-08-18 17:09:53 -0300687 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300688}
689
690
691/* release the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -0300692static int zr364xx_release(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300693{
694 struct video_device *vdev = video_devdata(file);
695 struct zr364xx_camera *cam;
696 struct usb_device *udev;
697 int i, err;
698
699 DBG("zr364xx_release");
700
701 if (vdev == NULL)
702 return -ENODEV;
703 cam = video_get_drvdata(vdev);
704
705 udev = cam->udev;
706
707 mutex_lock(&cam->lock);
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300708
709 cam->users--;
710 file->private_data = NULL;
711
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300712 for (i = 0; i < 2; i++) {
713 err =
714 send_control_msg(udev, 1, init[cam->method][i].value,
715 0, init[i][cam->method].bytes,
716 init[cam->method][i].size);
717 if (err < 0) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300718 dev_err(&udev->dev, "error during release sequence\n");
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300719 goto out;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300720 }
721 }
722
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300723 /* Added some delay here, since opening/closing the camera quickly,
724 * like Ekiga does during its startup, can crash the webcam
725 */
726 mdelay(100);
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300727 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300728
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300729out:
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300730 mutex_unlock(&cam->lock);
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300731 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300732}
733
734
735static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
736{
737 void *pos;
738 unsigned long start = vma->vm_start;
739 unsigned long size = vma->vm_end - vma->vm_start;
740 struct video_device *vdev = video_devdata(file);
741 struct zr364xx_camera *cam;
742
743 DBG("zr364xx_mmap: %ld\n", size);
744
745 if (vdev == NULL)
746 return -ENODEV;
747 cam = video_get_drvdata(vdev);
748
749 pos = cam->framebuf;
750 while (size > 0) {
751 if (vm_insert_page(vma, start, vmalloc_to_page(pos)))
752 return -EAGAIN;
753 start += PAGE_SIZE;
754 pos += PAGE_SIZE;
755 if (size > PAGE_SIZE)
756 size -= PAGE_SIZE;
757 else
758 size = 0;
759 }
760
761 return 0;
762}
763
764
Hans Verkuilbec43662008-12-30 06:58:20 -0300765static const struct v4l2_file_operations zr364xx_fops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300766 .owner = THIS_MODULE,
767 .open = zr364xx_open,
768 .release = zr364xx_release,
769 .read = zr364xx_read,
770 .mmap = zr364xx_mmap,
771 .ioctl = video_ioctl2,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300772};
773
Hans Verkuila3998102008-07-21 02:57:38 -0300774static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300775 .vidioc_querycap = zr364xx_vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -0300776 .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
777 .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
778 .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
779 .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300780 .vidioc_enum_input = zr364xx_vidioc_enum_input,
781 .vidioc_g_input = zr364xx_vidioc_g_input,
782 .vidioc_s_input = zr364xx_vidioc_s_input,
783 .vidioc_streamon = zr364xx_vidioc_streamon,
784 .vidioc_streamoff = zr364xx_vidioc_streamoff,
785 .vidioc_queryctrl = zr364xx_vidioc_queryctrl,
786 .vidioc_g_ctrl = zr364xx_vidioc_g_ctrl,
787 .vidioc_s_ctrl = zr364xx_vidioc_s_ctrl,
788};
789
Hans Verkuila3998102008-07-21 02:57:38 -0300790static struct video_device zr364xx_template = {
Hans Verkuila3998102008-07-21 02:57:38 -0300791 .name = DRIVER_DESC,
Hans Verkuila3998102008-07-21 02:57:38 -0300792 .fops = &zr364xx_fops,
793 .ioctl_ops = &zr364xx_ioctl_ops,
794 .release = video_device_release,
795 .minor = -1,
796};
797
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300798
799
800/*******************/
801/* USB integration */
802/*******************/
803
804static int zr364xx_probe(struct usb_interface *intf,
805 const struct usb_device_id *id)
806{
807 struct usb_device *udev = interface_to_usbdev(intf);
808 struct zr364xx_camera *cam = NULL;
Akinobu Mita783aa8f2007-05-20 09:12:10 -0300809 int err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300810
811 DBG("probing...");
812
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300813 dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
814 dev_info(&intf->dev, "model %04x:%04x detected\n",
815 le16_to_cpu(udev->descriptor.idVendor),
816 le16_to_cpu(udev->descriptor.idProduct));
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300817
Akinobu Mita783aa8f2007-05-20 09:12:10 -0300818 cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
819 if (cam == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300820 dev_err(&udev->dev, "cam: out of memory !\n");
Akinobu Mita783aa8f2007-05-20 09:12:10 -0300821 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300822 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300823 /* save the init method used by this camera */
824 cam->method = id->driver_info;
825
826 cam->vdev = video_device_alloc();
827 if (cam->vdev == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300828 dev_err(&udev->dev, "cam->vdev: out of memory !\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300829 kfree(cam);
Akinobu Mita783aa8f2007-05-20 09:12:10 -0300830 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300831 }
832 memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template));
833 video_set_drvdata(cam->vdev, cam);
834 if (debug)
835 cam->vdev->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
836
837 cam->udev = udev;
838
839 if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300840 dev_info(&udev->dev, "cam->buffer: out of memory !\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300841 video_device_release(cam->vdev);
842 kfree(cam);
843 return -ENODEV;
844 }
845
846 switch (mode) {
847 case 1:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300848 dev_info(&udev->dev, "160x120 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300849 cam->width = 160;
850 cam->height = 120;
851 break;
852 case 2:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300853 dev_info(&udev->dev, "640x480 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300854 cam->width = 640;
855 cam->height = 480;
856 break;
857 default:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300858 dev_info(&udev->dev, "320x240 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300859 cam->width = 320;
860 cam->height = 240;
861 break;
862 }
863
864 m0d1[0] = mode;
865 m1[2].value = 0xf000 + mode;
866 m2[1].value = 0xf000 + mode;
867 header2[437] = cam->height / 256;
868 header2[438] = cam->height % 256;
869 header2[439] = cam->width / 256;
870 header2[440] = cam->width % 256;
871
872 cam->nb = 0;
873 cam->brightness = 64;
874 mutex_init(&cam->lock);
875
Akinobu Mita783aa8f2007-05-20 09:12:10 -0300876 err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1);
877 if (err) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300878 dev_err(&udev->dev, "video_register_device failed\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300879 video_device_release(cam->vdev);
880 kfree(cam->buffer);
881 kfree(cam);
Akinobu Mita783aa8f2007-05-20 09:12:10 -0300882 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300883 }
884
885 usb_set_intfdata(intf, cam);
886
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300887 dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n",
Hans Verkuilc6330fb2008-10-19 18:54:26 -0300888 cam->vdev->num);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300889 return 0;
890}
891
892
893static void zr364xx_disconnect(struct usb_interface *intf)
894{
895 struct zr364xx_camera *cam = usb_get_intfdata(intf);
896 usb_set_intfdata(intf, NULL);
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300897 dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300898 if (cam->vdev)
899 video_unregister_device(cam->vdev);
900 cam->vdev = NULL;
901 kfree(cam->buffer);
902 if (cam->framebuf)
903 vfree(cam->framebuf);
904 kfree(cam);
905}
906
907
908
909/**********************/
910/* Module integration */
911/**********************/
912
913static struct usb_driver zr364xx_driver = {
914 .name = "zr364xx",
915 .probe = zr364xx_probe,
916 .disconnect = zr364xx_disconnect,
917 .id_table = device_table
918};
919
920
921static int __init zr364xx_init(void)
922{
923 int retval;
Akinobu Mita783aa8f2007-05-20 09:12:10 -0300924 retval = usb_register(&zr364xx_driver);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300925 if (retval)
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300926 printk(KERN_ERR KBUILD_MODNAME ": usb_register failed!\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300927 else
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300928 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300929 return retval;
930}
931
932
933static void __exit zr364xx_exit(void)
934{
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300935 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC " module unloaded\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300936 usb_deregister(&zr364xx_driver);
937}
938
939
940module_init(zr364xx_init);
941module_exit(zr364xx_exit);
942
943MODULE_AUTHOR(DRIVER_AUTHOR);
944MODULE_DESCRIPTION(DRIVER_DESC);
945MODULE_LICENSE("GPL");