blob: 009f8733cb16172bca3d7fbbb048e679af65ceeb [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
69/* Init methods, need to find nicer names for these
70 * the exact names of the chipsets would be the best if someone finds it */
71#define METHOD0 0
72#define METHOD1 1
73#define METHOD2 2
74
75
76/* Module parameters */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030077static int debug;
78static int mode;
Antoine Jacquetb7eee612007-04-27 12:30:59 -030079
80
81/* Module parameters interface */
82module_param(debug, int, 0644);
83MODULE_PARM_DESC(debug, "Debug level");
84module_param(mode, int, 0644);
85MODULE_PARM_DESC(mode, "0 = 320x240, 1 = 160x120, 2 = 640x480");
86
87
88/* Devices supported by this driver
89 * .driver_info contains the init method used by the camera */
90static struct usb_device_id device_table[] = {
91 {USB_DEVICE(0x08ca, 0x0109), .driver_info = METHOD0 },
92 {USB_DEVICE(0x041e, 0x4024), .driver_info = METHOD0 },
93 {USB_DEVICE(0x0d64, 0x0108), .driver_info = METHOD0 },
94 {USB_DEVICE(0x0546, 0x3187), .driver_info = METHOD0 },
95 {USB_DEVICE(0x0d64, 0x3108), .driver_info = METHOD0 },
96 {USB_DEVICE(0x0595, 0x4343), .driver_info = METHOD0 },
97 {USB_DEVICE(0x0bb0, 0x500d), .driver_info = METHOD0 },
98 {USB_DEVICE(0x0feb, 0x2004), .driver_info = METHOD0 },
99 {USB_DEVICE(0x055f, 0xb500), .driver_info = METHOD0 },
100 {USB_DEVICE(0x08ca, 0x2062), .driver_info = METHOD2 },
101 {USB_DEVICE(0x052b, 0x1a18), .driver_info = METHOD1 },
102 {USB_DEVICE(0x04c8, 0x0729), .driver_info = METHOD0 },
103 {USB_DEVICE(0x04f2, 0xa208), .driver_info = METHOD0 },
104 {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 },
105 {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
106 {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
Antoine Jacquetbebeaea2007-06-25 16:00:34 -0300107 {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
Antoine Jacquet71c04472008-01-25 22:01:53 -0300108 {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
Antoine Jacquetc0e0aff2008-01-25 22:03:10 -0300109 {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
Antoine Jacquetc76b6382009-01-17 22:49:08 -0300110 {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD2 },
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300111 {} /* Terminating entry */
112};
113
114MODULE_DEVICE_TABLE(usb, device_table);
115
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300116struct zr364xx_mode {
117 u32 color; /* output video color format */
118 u32 brightness; /* brightness */
119};
120
121/* frame structure */
122struct zr364xx_framei {
123 unsigned long ulState; /* ulState:ZR364XX_READ_IDLE,
124 ZR364XX_READ_FRAME */
125 void *lpvbits; /* image data */
126 unsigned long cur_size; /* current data copied to it */
127};
128
129/* image buffer structure */
130struct zr364xx_bufferi {
131 unsigned long dwFrames; /* number of frames in buffer */
132 struct zr364xx_framei frame[FRAMES]; /* array of FRAME structures */
133};
134
135struct zr364xx_dmaqueue {
136 struct list_head active;
137 struct zr364xx_camera *cam;
138};
139
140struct zr364xx_pipeinfo {
141 u32 transfer_size;
142 u8 *transfer_buffer;
143 u32 state;
144 void *stream_urb;
145 void *cam; /* back pointer to zr364xx_camera struct */
146 u32 err_count;
147 u32 idx;
148};
149
150struct zr364xx_fmt {
151 char *name;
152 u32 fourcc;
153 int depth;
154};
155
156/* image formats. */
157static const struct zr364xx_fmt formats[] = {
158 {
159 .name = "JPG",
160 .fourcc = V4L2_PIX_FMT_JPEG,
161 .depth = 24
162 }
163};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300164
165/* Camera stuff */
166struct zr364xx_camera {
167 struct usb_device *udev; /* save off the usb device pointer */
168 struct usb_interface *interface;/* the interface for this device */
169 struct video_device *vdev; /* v4l video device */
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300170 int nb;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300171 struct zr364xx_bufferi buffer;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300172 int skip;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300173 int width;
174 int height;
175 int method;
176 struct mutex lock;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300177 struct mutex open_lock;
Antoine Jacquet33d27a42008-08-18 17:14:30 -0300178 int users;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300179
180 spinlock_t slock;
181 struct zr364xx_dmaqueue vidq;
182 int resources;
183 int last_frame;
184 int cur_frame;
185 unsigned long frame_count;
186 int b_acquire;
187 struct zr364xx_pipeinfo pipe[1];
188
189 u8 read_endpoint;
190
191 const struct zr364xx_fmt *fmt;
192 struct videobuf_queue vb_vidq;
193 enum v4l2_buf_type type;
194 struct zr364xx_mode mode;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300195};
196
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300197/* buffer for one video frame */
198struct zr364xx_buffer {
199 /* common v4l buffer stuff -- must be first */
200 struct videobuf_buffer vb;
201 const struct zr364xx_fmt *fmt;
202};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300203
204/* function used to send initialisation commands to the camera */
205static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
206 u16 index, unsigned char *cp, u16 size)
207{
208 int status;
209
210 unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
211 if (!transfer_buffer) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300212 dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300213 return -ENOMEM;
214 }
215
216 memcpy(transfer_buffer, cp, size);
217
218 status = usb_control_msg(udev,
219 usb_sndctrlpipe(udev, 0),
220 request,
221 USB_DIR_OUT | USB_TYPE_VENDOR |
222 USB_RECIP_DEVICE, value, index,
223 transfer_buffer, size, CTRL_TIMEOUT);
224
225 kfree(transfer_buffer);
226
227 if (status < 0)
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -0300228 dev_err(&udev->dev,
229 "Failed sending control message, error %d.\n", status);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300230
231 return status;
232}
233
234
235/* Control messages sent to the camera to initialize it
236 * and launch the capture */
237typedef struct {
238 unsigned int value;
239 unsigned int size;
240 unsigned char *bytes;
241} message;
242
243/* method 0 */
244static unsigned char m0d1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
245static unsigned char m0d2[] = { 0, 0, 0, 0, 0, 0 };
246static unsigned char m0d3[] = { 0, 0 };
247static message m0[] = {
248 {0x1f30, 0, NULL},
249 {0xd000, 0, NULL},
250 {0x3370, sizeof(m0d1), m0d1},
251 {0x2000, 0, NULL},
252 {0x2f0f, 0, NULL},
253 {0x2610, sizeof(m0d2), m0d2},
254 {0xe107, 0, NULL},
255 {0x2502, 0, NULL},
256 {0x1f70, 0, NULL},
257 {0xd000, 0, NULL},
258 {0x9a01, sizeof(m0d3), m0d3},
259 {-1, -1, NULL}
260};
261
262/* method 1 */
263static unsigned char m1d1[] = { 0xff, 0xff };
264static unsigned char m1d2[] = { 0x00, 0x00 };
265static message m1[] = {
266 {0x1f30, 0, NULL},
267 {0xd000, 0, NULL},
268 {0xf000, 0, NULL},
269 {0x2000, 0, NULL},
270 {0x2f0f, 0, NULL},
271 {0x2650, 0, NULL},
272 {0xe107, 0, NULL},
273 {0x2502, sizeof(m1d1), m1d1},
274 {0x1f70, 0, NULL},
275 {0xd000, 0, NULL},
276 {0xd000, 0, NULL},
277 {0xd000, 0, NULL},
278 {0x9a01, sizeof(m1d2), m1d2},
279 {-1, -1, NULL}
280};
281
282/* method 2 */
283static unsigned char m2d1[] = { 0xff, 0xff };
284static message m2[] = {
285 {0x1f30, 0, NULL},
286 {0xf000, 0, NULL},
287 {0x2000, 0, NULL},
288 {0x2f0f, 0, NULL},
289 {0x2650, 0, NULL},
290 {0xe107, 0, NULL},
291 {0x2502, sizeof(m2d1), m2d1},
292 {0x1f70, 0, NULL},
293 {-1, -1, NULL}
294};
295
296/* init table */
297static message *init[3] = { m0, m1, m2 };
298
299
300/* JPEG static data in header (Huffman table, etc) */
301static unsigned char header1[] = {
302 0xFF, 0xD8,
303 /*
304 0xFF, 0xE0, 0x00, 0x10, 'J', 'F', 'I', 'F',
305 0x00, 0x01, 0x01, 0x00, 0x33, 0x8A, 0x00, 0x00, 0x33, 0x88,
306 */
307 0xFF, 0xDB, 0x00, 0x84
308};
309static unsigned char header2[] = {
310 0xFF, 0xC4, 0x00, 0x1F, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
311 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
313 0xFF, 0xC4, 0x00, 0xB5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
314 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
315 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
316 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
317 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33,
318 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25,
319 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
320 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,
321 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
322 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
323 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94,
324 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
325 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
326 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
327 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
328 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
329 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xC4, 0x00, 0x1F,
330 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
331 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
332 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0xC4, 0x00, 0xB5,
333 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
334 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,
335 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
336 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1,
337 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
338 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27,
339 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
340 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57,
341 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
342 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84,
343 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
344 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
345 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
346 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
347 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,
348 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
349 0xF8, 0xF9, 0xFA, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01,
350 0x40, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
351 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
352 0x00, 0x3F, 0x00
353};
354static unsigned char header3;
355
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300356/* ------------------------------------------------------------------
357 Videobuf operations
358 ------------------------------------------------------------------*/
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300359
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300360static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
361 unsigned int *size)
362{
363 struct zr364xx_camera *cam = vq->priv_data;
364
365 *size = cam->width * cam->height * (cam->fmt->depth >> 3);
366
367 if (*count == 0)
368 *count = ZR364XX_DEF_BUFS;
369
370 while (*size * (*count) > ZR364XX_DEF_BUFS * 1024 * 1024)
371 (*count)--;
372
373 return 0;
374}
375
376static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf)
377{
378 DBG("%s\n", __func__);
379
380 if (in_interrupt())
381 BUG();
382
383 videobuf_vmalloc_free(&buf->vb);
384 buf->vb.state = VIDEOBUF_NEEDS_INIT;
385}
386
387static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
388 enum v4l2_field field)
389{
390 struct zr364xx_camera *cam = vq->priv_data;
391 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
392 vb);
393 int rc;
394
395 DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ?
396 cam->fmt->name : "");
397 if (cam->fmt == NULL)
398 return -EINVAL;
399
400 buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3);
401
402 if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) {
403 DBG("invalid buffer prepare\n");
404 return -EINVAL;
405 }
406
407 buf->fmt = cam->fmt;
408 buf->vb.width = cam->width;
409 buf->vb.height = cam->height;
410 buf->vb.field = field;
411
412 if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
413 rc = videobuf_iolock(vq, &buf->vb, NULL);
414 if (rc < 0)
415 goto fail;
416 }
417
418 buf->vb.state = VIDEOBUF_PREPARED;
419 return 0;
420fail:
421 free_buffer(vq, buf);
422 return rc;
423}
424
425static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
426{
427 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
428 vb);
429 struct zr364xx_camera *cam = vq->priv_data;
430
431 DBG("%s\n", __func__);
432
433 buf->vb.state = VIDEOBUF_QUEUED;
434 list_add_tail(&buf->vb.queue, &cam->vidq.active);
435}
436
437static void buffer_release(struct videobuf_queue *vq,
438 struct videobuf_buffer *vb)
439{
440 struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer,
441 vb);
442
443 DBG("%s\n", __func__);
444 free_buffer(vq, buf);
445}
446
447static struct videobuf_queue_ops zr364xx_video_qops = {
448 .buf_setup = buffer_setup,
449 .buf_prepare = buffer_prepare,
450 .buf_queue = buffer_queue,
451 .buf_release = buffer_release,
452};
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300453
454/********************/
455/* V4L2 integration */
456/********************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300457static int zr364xx_vidioc_streamon(struct file *file, void *priv,
458 enum v4l2_buf_type type);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300459
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300460static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300461 loff_t * ppos)
462{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300463 struct zr364xx_camera *cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300464
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300465 DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300466
467 if (!buf)
468 return -EINVAL;
469
470 if (!count)
471 return -EINVAL;
472
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300473 if (cam->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
474 zr364xx_vidioc_streamon(file, cam, cam->type) == 0) {
475 DBG("%s: reading %d bytes at pos %d.\n", __func__, (int) count,
476 (int) *ppos);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300477
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300478 /* NoMan Sux ! */
479 return videobuf_read_one(&cam->vb_vidq, buf, count, ppos,
480 file->f_flags & O_NONBLOCK);
481 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300482
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300483 return 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300484}
485
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300486/* video buffer vmalloc implementation based partly on VIVI driver which is
487 * Copyright (c) 2006 by
488 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
489 * Ted Walther <ted--a.t--enumera.com>
490 * John Sokol <sokol--a.t--videotechnology.com>
491 * http://v4l.videotechnology.com/
492 *
493 */
494static void zr364xx_fillbuff(struct zr364xx_camera *cam,
495 struct zr364xx_buffer *buf,
496 int jpgsize)
497{
498 int pos = 0;
499 struct timeval ts;
500 const char *tmpbuf;
501 char *vbuf = videobuf_to_vmalloc(&buf->vb);
502 unsigned long last_frame;
503 struct zr364xx_framei *frm;
504
505 if (!vbuf)
506 return;
507
508 last_frame = cam->last_frame;
509 if (last_frame != -1) {
510 frm = &cam->buffer.frame[last_frame];
511 tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits;
512 switch (buf->fmt->fourcc) {
513 case V4L2_PIX_FMT_JPEG:
514 buf->vb.size = jpgsize;
515 memcpy(vbuf, tmpbuf, buf->vb.size);
516 break;
517 default:
518 printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n");
519 }
520 cam->last_frame = -1;
521 } else {
522 printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n");
523 return;
524 }
525 DBG("%s: Buffer 0x%08lx size= %d\n", __func__,
526 (unsigned long)vbuf, pos);
527 /* tell v4l buffer was filled */
528
529 buf->vb.field_count = cam->frame_count * 2;
530 do_gettimeofday(&ts);
531 buf->vb.ts = ts;
532 buf->vb.state = VIDEOBUF_DONE;
533}
534
535static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize)
536{
537 struct zr364xx_dmaqueue *dma_q = &cam->vidq;
538 struct zr364xx_buffer *buf;
539 unsigned long flags = 0;
540 int rc = 0;
541
542 DBG("wakeup: %p\n", &dma_q);
543 spin_lock_irqsave(&cam->slock, flags);
544
545 if (list_empty(&dma_q->active)) {
546 DBG("No active queue to serve\n");
547 rc = -1;
548 goto unlock;
549 }
550 buf = list_entry(dma_q->active.next,
551 struct zr364xx_buffer, vb.queue);
552
553 if (!waitqueue_active(&buf->vb.done)) {
554 /* no one active */
555 rc = -1;
556 goto unlock;
557 }
558 list_del(&buf->vb.queue);
559 do_gettimeofday(&buf->vb.ts);
560 DBG("[%p/%d] wakeup\n", buf, buf->vb.i);
561 zr364xx_fillbuff(cam, buf, jpgsize);
562 wake_up(&buf->vb.done);
563 DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
564unlock:
565 spin_unlock_irqrestore(&cam->slock, flags);
566 return 0;
567}
568
569/* this function moves the usb stream read pipe data
570 * into the system buffers.
571 * returns 0 on success, EAGAIN if more data to process (call this
572 * function again).
573 */
574static int zr364xx_read_video_callback(struct zr364xx_camera *cam,
575 struct zr364xx_pipeinfo *pipe_info,
576 struct urb *purb)
577{
578 unsigned char *pdest;
579 unsigned char *psrc;
580 s32 idx = -1;
581 struct zr364xx_framei *frm;
582 int i = 0;
583 unsigned char *ptr = NULL;
584
585 /*DBG("buffer to user\n");*/
586 idx = cam->cur_frame;
587 frm = &cam->buffer.frame[idx];
588
589 /* swap bytes if camera needs it */
590 if (cam->method == METHOD0) {
591 u16 *buf = (u16 *)pipe_info->transfer_buffer;
592 for (i = 0; i < purb->actual_length/2; i++)
593 swab16s(buf + i);
594 }
595
596 /* search done. now find out if should be acquiring */
597 if (!cam->b_acquire) {
598 /* we found a frame, but this channel is turned off */
599 frm->ulState = ZR364XX_READ_IDLE;
600 return -EINVAL;
601 }
602
603 if (frm->lpvbits == NULL) {
604 DBG("%s: frame buffer == NULL.%p %p %d\n", __func__,
605 frm, cam, idx);
606 return -ENOMEM;
607 }
608
609 psrc = (u8 *)pipe_info->transfer_buffer;
610 ptr = pdest = frm->lpvbits;
611
612 if (frm->ulState == ZR364XX_READ_IDLE) {
613 frm->ulState = ZR364XX_READ_FRAME;
614 frm->cur_size = 0;
615
616 DBG("jpeg header, ");
617 memcpy(ptr, header1, sizeof(header1));
618 ptr += sizeof(header1);
619 header3 = 0;
620 memcpy(ptr, &header3, 1);
621 ptr++;
622 memcpy(ptr, psrc, 64);
623 ptr += 64;
624 header3 = 1;
625 memcpy(ptr, &header3, 1);
626 ptr++;
627 memcpy(ptr, psrc + 64, 64);
628 ptr += 64;
629 memcpy(ptr, header2, sizeof(header2));
630 ptr += sizeof(header2);
631 memcpy(ptr, psrc + 128,
632 purb->actual_length - 128);
633 ptr += purb->actual_length - 128;
634 DBG("header : %d %d %d %d %d %d %d %d %d\n",
635 psrc[0], psrc[1], psrc[2],
636 psrc[3], psrc[4], psrc[5],
637 psrc[6], psrc[7], psrc[8]);
638 frm->cur_size = ptr - pdest;
639 } else {
640 pdest += frm->cur_size;
641 memcpy(pdest, psrc, purb->actual_length);
642 frm->cur_size += purb->actual_length;
643 }
644 /*DBG("cur_size %lu urb size %d\n", frm->cur_size,
645 purb->actual_length);*/
646
647 if (purb->actual_length < pipe_info->transfer_size) {
648 DBG("****************Buffer[%d]full*************\n", idx);
649 cam->last_frame = cam->cur_frame;
650 cam->cur_frame++;
651 /* end of system frame ring buffer, start at zero */
652 if (cam->cur_frame == cam->buffer.dwFrames)
653 cam->cur_frame = 0;
654
655 /* frame ready */
656 /* go back to find the JPEG EOI marker */
657 ptr = pdest = frm->lpvbits;
658 ptr += frm->cur_size - 2;
659 while (ptr > pdest) {
660 if (*ptr == 0xFF && *(ptr + 1) == 0xD9
661 && *(ptr + 2) == 0xFF)
662 break;
663 ptr--;
664 }
665 if (ptr == pdest)
666 DBG("No EOI marker\n");
667
668 /* Sometimes there is junk data in the middle of the picture,
669 * we want to skip this bogus frames */
670 while (ptr > pdest) {
671 if (*ptr == 0xFF && *(ptr + 1) == 0xFF
672 && *(ptr + 2) == 0xFF)
673 break;
674 ptr--;
675 }
676 if (ptr != pdest) {
677 DBG("Bogus frame ? %d\n", ++(cam->nb));
678 } else if (cam->b_acquire) {
679 /* we skip the 2 first frames which are usually buggy */
680 if (cam->skip)
681 cam->skip--;
682 else {
683 DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n",
684 frm->cur_size,
685 pdest[0], pdest[1], pdest[2], pdest[3],
686 pdest[4], pdest[5], pdest[6], pdest[7]);
687
688 zr364xx_got_frame(cam, frm->cur_size);
689 }
690 }
691 cam->frame_count++;
692 frm->ulState = ZR364XX_READ_IDLE;
693 frm->cur_size = 0;
694 }
695 /* done successfully */
696 return 0;
697}
698
699static int res_get(struct zr364xx_camera *cam)
700{
701 /* is it free? */
702 mutex_lock(&cam->lock);
703 if (cam->resources) {
704 /* no, someone else uses it */
705 mutex_unlock(&cam->lock);
706 return 0;
707 }
708 /* it's free, grab it */
709 cam->resources = 1;
710 DBG("res: get\n");
711 mutex_unlock(&cam->lock);
712 return 1;
713}
714
715static inline int res_check(struct zr364xx_camera *cam)
716{
717 return cam->resources;
718}
719
720static void res_free(struct zr364xx_camera *cam)
721{
722 mutex_lock(&cam->lock);
723 cam->resources = 0;
724 mutex_unlock(&cam->lock);
725 DBG("res: put\n");
726}
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300727
728static int zr364xx_vidioc_querycap(struct file *file, void *priv,
729 struct v4l2_capability *cap)
730{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300731 struct zr364xx_camera *cam = video_drvdata(file);
732
733 strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver));
734 strlcpy(cap->card, cam->udev->product, sizeof(cap->card));
735 strlcpy(cap->bus_info, dev_name(&cam->udev->dev),
736 sizeof(cap->bus_info));
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300737 cap->version = ZR364XX_VERSION_CODE;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300738 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
739 V4L2_CAP_READWRITE |
740 V4L2_CAP_STREAMING;
741
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300742 return 0;
743}
744
745static int zr364xx_vidioc_enum_input(struct file *file, void *priv,
746 struct v4l2_input *i)
747{
748 if (i->index != 0)
749 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300750 strcpy(i->name, DRIVER_DESC " Camera");
751 i->type = V4L2_INPUT_TYPE_CAMERA;
752 return 0;
753}
754
755static int zr364xx_vidioc_g_input(struct file *file, void *priv,
756 unsigned int *i)
757{
758 *i = 0;
759 return 0;
760}
761
762static int zr364xx_vidioc_s_input(struct file *file, void *priv,
763 unsigned int i)
764{
765 if (i != 0)
766 return -EINVAL;
767 return 0;
768}
769
770static int zr364xx_vidioc_queryctrl(struct file *file, void *priv,
771 struct v4l2_queryctrl *c)
772{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300773 struct zr364xx_camera *cam;
774
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300775 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300776 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300777 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300778
779 switch (c->id) {
780 case V4L2_CID_BRIGHTNESS:
781 c->type = V4L2_CTRL_TYPE_INTEGER;
782 strcpy(c->name, "Brightness");
783 c->minimum = 0;
784 c->maximum = 127;
785 c->step = 1;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300786 c->default_value = cam->mode.brightness;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300787 c->flags = 0;
788 break;
789 default:
790 return -EINVAL;
791 }
792 return 0;
793}
794
795static int zr364xx_vidioc_s_ctrl(struct file *file, void *priv,
796 struct v4l2_control *c)
797{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300798 struct zr364xx_camera *cam;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300799 int temp;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300800
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300801 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300802 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300803 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300804
805 switch (c->id) {
806 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300807 cam->mode.brightness = c->value;
808 /* hardware brightness */
809 mutex_lock(&cam->lock);
810 send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0);
811 temp = (0x60 << 8) + 127 - cam->mode.brightness;
812 send_control_msg(cam->udev, 1, temp, 0, NULL, 0);
813 mutex_unlock(&cam->lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300814 break;
815 default:
816 return -EINVAL;
817 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300818
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300819 return 0;
820}
821
822static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv,
823 struct v4l2_control *c)
824{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300825 struct zr364xx_camera *cam;
826
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300827 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300828 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300829 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300830
831 switch (c->id) {
832 case V4L2_CID_BRIGHTNESS:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300833 c->value = cam->mode.brightness;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300834 break;
835 default:
836 return -EINVAL;
837 }
838 return 0;
839}
840
Hans Verkuil78b526a2008-05-28 12:16:41 -0300841static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300842 void *priv, struct v4l2_fmtdesc *f)
843{
844 if (f->index > 0)
845 return -EINVAL;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300846 f->flags = V4L2_FMT_FLAG_COMPRESSED;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300847 strcpy(f->description, formats[0].name);
848 f->pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300849 return 0;
850}
851
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300852static char *decode_fourcc(__u32 pixelformat, char *buf)
853{
854 buf[0] = pixelformat & 0xff;
855 buf[1] = (pixelformat >> 8) & 0xff;
856 buf[2] = (pixelformat >> 16) & 0xff;
857 buf[3] = (pixelformat >> 24) & 0xff;
858 buf[4] = '\0';
859 return buf;
860}
861
Hans Verkuil78b526a2008-05-28 12:16:41 -0300862static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300863 struct v4l2_format *f)
864{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300865 struct zr364xx_camera *cam = video_drvdata(file);
866 char pixelformat_name[5];
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300867
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300868 if (cam == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300869 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300870
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300871 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
872 DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__,
873 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name));
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300874 return -EINVAL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300875 }
876
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300877 if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) &&
878 !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) {
879 f->fmt.pix.width = 320;
880 f->fmt.pix.height = 240;
881 }
882
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300883 f->fmt.pix.field = V4L2_FIELD_NONE;
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300884 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300885 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
886 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
887 f->fmt.pix.colorspace = 0;
888 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300889 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
890 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
891 f->fmt.pix.field);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300892 return 0;
893}
894
Hans Verkuil78b526a2008-05-28 12:16:41 -0300895static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300896 struct v4l2_format *f)
897{
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300898 struct zr364xx_camera *cam;
899
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300900 if (file == NULL)
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300901 return -ENODEV;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300902 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300903
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300904 f->fmt.pix.pixelformat = formats[0].fourcc;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300905 f->fmt.pix.field = V4L2_FIELD_NONE;
906 f->fmt.pix.width = cam->width;
907 f->fmt.pix.height = cam->height;
908 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
909 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
910 f->fmt.pix.colorspace = 0;
911 f->fmt.pix.priv = 0;
912 return 0;
913}
914
Hans Verkuil78b526a2008-05-28 12:16:41 -0300915static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300916 struct v4l2_format *f)
917{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300918 struct zr364xx_camera *cam = video_drvdata(file);
919 struct videobuf_queue *q = &cam->vb_vidq;
920 char pixelformat_name[5];
921 int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f);
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300922 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300923
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300924 if (ret < 0)
925 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300926
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300927 mutex_lock(&q->vb_lock);
928
929 if (videobuf_queue_is_busy(&cam->vb_vidq)) {
930 DBG("%s queue busy\n", __func__);
931 ret = -EBUSY;
932 goto out;
933 }
934
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300935 if (res_check(cam)) {
936 DBG("%s can't change format after started\n", __func__);
937 ret = -EBUSY;
938 goto out;
939 }
940
941 cam->width = f->fmt.pix.width;
942 cam->height = f->fmt.pix.height;
943 dev_info(&cam->udev->dev, "%s: %dx%d mode selected\n", __func__,
944 cam->width, cam->height);
Antoine Jacquetb7eee612007-04-27 12:30:59 -0300945 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
946 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
947 f->fmt.pix.colorspace = 0;
948 f->fmt.pix.priv = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300949 cam->vb_vidq.field = f->fmt.pix.field;
950 cam->mode.color = V4L2_PIX_FMT_JPEG;
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -0300951
952 if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
953 mode = 1;
954 else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480)
955 mode = 2;
956 else
957 mode = 0;
958
959 m0d1[0] = mode;
960 m1[2].value = 0xf000 + mode;
961 m2[1].value = 0xf000 + mode;
962 header2[437] = cam->height / 256;
963 header2[438] = cam->height % 256;
964 header2[439] = cam->width / 256;
965 header2[440] = cam->width % 256;
966
967 for (i = 0; init[cam->method][i].size != -1; i++) {
968 ret =
969 send_control_msg(cam->udev, 1, init[cam->method][i].value,
970 0, init[cam->method][i].bytes,
971 init[cam->method][i].size);
972 if (ret < 0) {
973 dev_err(&cam->udev->dev,
974 "error during resolution change sequence: %d\n", i);
975 goto out;
976 }
977 }
978
979 /* Added some delay here, since opening/closing the camera quickly,
980 * like Ekiga does during its startup, can crash the webcam
981 */
982 mdelay(100);
983 cam->skip = 2;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -0300984 ret = 0;
985
986out:
987 mutex_unlock(&q->vb_lock);
988
989 DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
990 decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
991 f->fmt.pix.field);
992 return ret;
993}
994
995static int zr364xx_vidioc_reqbufs(struct file *file, void *priv,
996 struct v4l2_requestbuffers *p)
997{
998 int rc;
999 struct zr364xx_camera *cam = video_drvdata(file);
1000 rc = videobuf_reqbufs(&cam->vb_vidq, p);
1001 return rc;
1002}
1003
1004static int zr364xx_vidioc_querybuf(struct file *file,
1005 void *priv,
1006 struct v4l2_buffer *p)
1007{
1008 int rc;
1009 struct zr364xx_camera *cam = video_drvdata(file);
1010 rc = videobuf_querybuf(&cam->vb_vidq, p);
1011 return rc;
1012}
1013
1014static int zr364xx_vidioc_qbuf(struct file *file,
1015 void *priv,
1016 struct v4l2_buffer *p)
1017{
1018 int rc;
1019 struct zr364xx_camera *cam = video_drvdata(file);
1020 DBG("%s\n", __func__);
1021 rc = videobuf_qbuf(&cam->vb_vidq, p);
1022 return rc;
1023}
1024
1025static int zr364xx_vidioc_dqbuf(struct file *file,
1026 void *priv,
1027 struct v4l2_buffer *p)
1028{
1029 int rc;
1030 struct zr364xx_camera *cam = video_drvdata(file);
1031 DBG("%s\n", __func__);
1032 rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK);
1033 return rc;
1034}
1035
1036static void read_pipe_completion(struct urb *purb)
1037{
1038 struct zr364xx_pipeinfo *pipe_info;
1039 struct zr364xx_camera *cam;
1040 int pipe;
1041
1042 pipe_info = purb->context;
1043 /*DBG("%s %p, status %d\n", __func__, purb, purb->status);*/
1044 if (pipe_info == NULL) {
1045 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
1046 return;
1047 }
1048
1049 cam = pipe_info->cam;
1050 if (cam == NULL) {
1051 printk(KERN_ERR KBUILD_MODNAME ": no context!\n");
1052 return;
1053 }
1054
1055 /* if shutting down, do not resubmit, exit immediately */
1056 if (purb->status == -ESHUTDOWN) {
1057 DBG("%s, err shutdown\n", __func__);
1058 pipe_info->err_count++;
1059 return;
1060 }
1061
1062 if (pipe_info->state == 0) {
1063 DBG("exiting USB pipe\n");
1064 return;
1065 }
1066
1067 if (purb->actual_length < 0 ||
1068 purb->actual_length > pipe_info->transfer_size) {
1069 dev_err(&cam->udev->dev, "wrong number of bytes\n");
1070 return;
1071 }
1072
1073 if (purb->status == 0)
1074 zr364xx_read_video_callback(cam, pipe_info, purb);
1075 else {
1076 pipe_info->err_count++;
1077 DBG("%s: failed URB %d\n", __func__, purb->status);
1078 }
1079
1080 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1081
1082 /* reuse urb */
1083 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1084 pipe,
1085 pipe_info->transfer_buffer,
1086 pipe_info->transfer_size,
1087 read_pipe_completion, pipe_info);
1088
1089 if (pipe_info->state != 0) {
1090 purb->status = usb_submit_urb(pipe_info->stream_urb,
1091 GFP_ATOMIC);
1092
1093 if (purb->status)
1094 dev_err(&cam->udev->dev,
1095 "error submitting urb (error=%i)\n",
1096 purb->status);
1097 } else
1098 DBG("read pipe complete state 0\n");
1099}
1100
1101static int zr364xx_start_readpipe(struct zr364xx_camera *cam)
1102{
1103 int pipe;
1104 int retval;
1105 struct zr364xx_pipeinfo *pipe_info = cam->pipe;
1106 pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint);
1107 DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint);
1108
1109 pipe_info->state = 1;
1110 pipe_info->err_count = 0;
1111 pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
1112 if (!pipe_info->stream_urb) {
1113 dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n");
1114 return -ENOMEM;
1115 }
1116 /* transfer buffer allocated in board_init */
1117 usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev,
1118 pipe,
1119 pipe_info->transfer_buffer,
1120 pipe_info->transfer_size,
1121 read_pipe_completion, pipe_info);
1122
1123 DBG("submitting URB %p\n", pipe_info->stream_urb);
1124 retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
1125 if (retval) {
1126 printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n");
1127 return retval;
1128 }
1129
1130 return 0;
1131}
1132
1133static void zr364xx_stop_readpipe(struct zr364xx_camera *cam)
1134{
1135 struct zr364xx_pipeinfo *pipe_info;
1136
1137 if (cam == NULL) {
1138 printk(KERN_ERR KBUILD_MODNAME ": invalid device\n");
1139 return;
1140 }
1141 DBG("stop read pipe\n");
1142 pipe_info = cam->pipe;
1143 if (pipe_info) {
1144 if (pipe_info->state != 0)
1145 pipe_info->state = 0;
1146
1147 if (pipe_info->stream_urb) {
1148 /* cancel urb */
1149 usb_kill_urb(pipe_info->stream_urb);
1150 usb_free_urb(pipe_info->stream_urb);
1151 pipe_info->stream_urb = NULL;
1152 }
1153 }
1154 DBG("stop read pipe\n");
1155 return;
1156}
1157
1158/* starts acquisition process */
1159static int zr364xx_start_acquire(struct zr364xx_camera *cam)
1160{
1161 int j;
1162
1163 DBG("start acquire\n");
1164
1165 cam->last_frame = -1;
1166 cam->cur_frame = 0;
1167 for (j = 0; j < FRAMES; j++) {
1168 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1169 cam->buffer.frame[j].cur_size = 0;
1170 }
Lamarque Vieira Souza8c5f32a2009-07-20 20:46:42 -03001171 cam->b_acquire = 1;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001172 return 0;
1173}
1174
1175static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam)
1176{
1177 cam->b_acquire = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001178 return 0;
1179}
1180
1181static int zr364xx_vidioc_streamon(struct file *file, void *priv,
1182 enum v4l2_buf_type type)
1183{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001184 struct zr364xx_camera *cam = video_drvdata(file);
1185 int j;
1186 int res;
1187
1188 DBG("%s\n", __func__);
1189
1190 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1191 dev_err(&cam->udev->dev, "invalid fh type0\n");
1192 return -EINVAL;
1193 }
1194 if (cam->type != type) {
1195 dev_err(&cam->udev->dev, "invalid fh type1\n");
1196 return -EINVAL;
1197 }
1198
1199 if (!res_get(cam)) {
1200 dev_err(&cam->udev->dev, "stream busy\n");
1201 return -EBUSY;
1202 }
1203
1204 cam->last_frame = -1;
1205 cam->cur_frame = 0;
1206 cam->frame_count = 0;
1207 for (j = 0; j < FRAMES; j++) {
1208 cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE;
1209 cam->buffer.frame[j].cur_size = 0;
1210 }
1211 res = videobuf_streamon(&cam->vb_vidq);
1212 if (res == 0) {
1213 zr364xx_start_acquire(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001214 } else {
1215 res_free(cam);
1216 }
1217 DBG("%s: %d\n", __func__, res);
1218 return res;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001219}
1220
1221static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
1222 enum v4l2_buf_type type)
1223{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001224 int res;
1225 struct zr364xx_camera *cam = video_drvdata(file);
1226
1227 DBG("%s\n", __func__);
1228 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1229 dev_err(&cam->udev->dev, "invalid fh type0\n");
1230 return -EINVAL;
1231 }
1232 if (cam->type != type) {
1233 dev_err(&cam->udev->dev, "invalid fh type1\n");
1234 return -EINVAL;
1235 }
1236 zr364xx_stop_acquire(cam);
1237 res = videobuf_streamoff(&cam->vb_vidq);
1238 if (res < 0)
1239 return res;
1240 res_free(cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001241 return 0;
1242}
1243
1244
1245/* open the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -03001246static int zr364xx_open(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001247{
1248 struct video_device *vdev = video_devdata(file);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001249 struct zr364xx_camera *cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001250 struct usb_device *udev = cam->udev;
1251 int i, err;
1252
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001253 DBG("%s\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001254
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001255 mutex_lock(&cam->open_lock);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001256
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001257 if (cam->users) {
1258 err = -EBUSY;
Antoine Jacquet69025c92008-08-18 17:09:53 -03001259 goto out;
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001260 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001261
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001262 for (i = 0; init[cam->method][i].size != -1; i++) {
1263 err =
1264 send_control_msg(udev, 1, init[cam->method][i].value,
1265 0, init[cam->method][i].bytes,
1266 init[cam->method][i].size);
1267 if (err < 0) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001268 dev_err(&cam->udev->dev,
1269 "error during open sequence: %d\n", i);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001270 goto out;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001271 }
1272 }
1273
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001274 cam->skip = 2;
1275 cam->users++;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001276 file->private_data = vdev;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001277 cam->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1278 cam->fmt = formats;
1279
1280 videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops,
1281 NULL, &cam->slock,
1282 cam->type,
1283 V4L2_FIELD_NONE,
1284 sizeof(struct zr364xx_buffer), cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001285
1286 /* Added some delay here, since opening/closing the camera quickly,
1287 * like Ekiga does during its startup, can crash the webcam
1288 */
1289 mdelay(100);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001290 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001291
Antoine Jacquet69025c92008-08-18 17:09:53 -03001292out:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001293 mutex_unlock(&cam->open_lock);
1294 DBG("%s: %d\n", __func__, err);
Antoine Jacquet69025c92008-08-18 17:09:53 -03001295 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001296}
1297
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001298static void zr364xx_destroy(struct zr364xx_camera *cam)
1299{
1300 unsigned long i;
1301
1302 if (!cam) {
1303 printk(KERN_ERR KBUILD_MODNAME ", %s: no device\n", __func__);
1304 return;
1305 }
1306 mutex_lock(&cam->open_lock);
1307 if (cam->vdev)
1308 video_unregister_device(cam->vdev);
1309 cam->vdev = NULL;
1310
1311 /* stops the read pipe if it is running */
1312 if (cam->b_acquire)
1313 zr364xx_stop_acquire(cam);
1314
1315 zr364xx_stop_readpipe(cam);
1316
1317 /* release sys buffers */
1318 for (i = 0; i < FRAMES; i++) {
1319 if (cam->buffer.frame[i].lpvbits) {
1320 DBG("vfree %p\n", cam->buffer.frame[i].lpvbits);
1321 vfree(cam->buffer.frame[i].lpvbits);
1322 }
1323 cam->buffer.frame[i].lpvbits = NULL;
1324 }
1325
1326 /* release transfer buffer */
1327 kfree(cam->pipe->transfer_buffer);
1328 cam->pipe->transfer_buffer = NULL;
1329
1330 DBG("%s\n", __func__);
1331 mutex_unlock(&cam->open_lock);
1332 kfree(cam);
1333 cam = NULL;
1334}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001335
1336/* release the camera */
Hans Verkuilbec43662008-12-30 06:58:20 -03001337static int zr364xx_release(struct file *file)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001338{
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001339 struct zr364xx_camera *cam;
1340 struct usb_device *udev;
1341 int i, err;
1342
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001343 DBG("%s\n", __func__);
1344 cam = video_drvdata(file);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001345
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001346 if (!cam)
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001347 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001348
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001349 mutex_lock(&cam->open_lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001350 udev = cam->udev;
1351
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001352 /* turn off stream */
1353 if (res_check(cam)) {
1354 if (cam->b_acquire)
1355 zr364xx_stop_acquire(cam);
1356 videobuf_streamoff(&cam->vb_vidq);
1357 res_free(cam);
1358 }
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001359
1360 cam->users--;
1361 file->private_data = NULL;
1362
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001363 for (i = 0; i < 2; i++) {
1364 err =
1365 send_control_msg(udev, 1, init[cam->method][i].value,
Roel Kluin7b808922009-08-11 08:10:25 -03001366 0, init[cam->method][i].bytes,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001367 init[cam->method][i].size);
1368 if (err < 0) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001369 dev_err(&udev->dev, "error during release sequence\n");
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001370 goto out;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001371 }
1372 }
1373
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001374 /* Added some delay here, since opening/closing the camera quickly,
1375 * like Ekiga does during its startup, can crash the webcam
1376 */
1377 mdelay(100);
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001378 err = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001379
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001380out:
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001381 mutex_unlock(&cam->open_lock);
1382
Antoine Jacquet33d27a42008-08-18 17:14:30 -03001383 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001384}
1385
1386
1387static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
1388{
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001389 struct zr364xx_camera *cam = video_drvdata(file);
1390 int ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001391
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001392 if (cam == NULL) {
1393 DBG("%s: cam == NULL\n", __func__);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001394 return -ENODEV;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001395 }
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001396 DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001397
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001398 ret = videobuf_mmap_mapper(&cam->vb_vidq, vma);
1399
1400 DBG("vma start=0x%08lx, size=%ld, ret=%d\n",
1401 (unsigned long)vma->vm_start,
1402 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
1403 return ret;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001404}
1405
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001406static unsigned int zr364xx_poll(struct file *file,
1407 struct poll_table_struct *wait)
1408{
1409 struct zr364xx_camera *cam = video_drvdata(file);
1410 struct videobuf_queue *q = &cam->vb_vidq;
1411 DBG("%s\n", __func__);
1412
1413 if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1414 return POLLERR;
1415
1416 return videobuf_poll_stream(file, q, wait);
1417}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001418
Hans Verkuilbec43662008-12-30 06:58:20 -03001419static const struct v4l2_file_operations zr364xx_fops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001420 .owner = THIS_MODULE,
1421 .open = zr364xx_open,
1422 .release = zr364xx_release,
1423 .read = zr364xx_read,
1424 .mmap = zr364xx_mmap,
1425 .ioctl = video_ioctl2,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001426 .poll = zr364xx_poll,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001427};
1428
Hans Verkuila3998102008-07-21 02:57:38 -03001429static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001430 .vidioc_querycap = zr364xx_vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001431 .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
1432 .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
1433 .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
1434 .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001435 .vidioc_enum_input = zr364xx_vidioc_enum_input,
1436 .vidioc_g_input = zr364xx_vidioc_g_input,
1437 .vidioc_s_input = zr364xx_vidioc_s_input,
1438 .vidioc_streamon = zr364xx_vidioc_streamon,
1439 .vidioc_streamoff = zr364xx_vidioc_streamoff,
1440 .vidioc_queryctrl = zr364xx_vidioc_queryctrl,
1441 .vidioc_g_ctrl = zr364xx_vidioc_g_ctrl,
1442 .vidioc_s_ctrl = zr364xx_vidioc_s_ctrl,
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001443 .vidioc_reqbufs = zr364xx_vidioc_reqbufs,
1444 .vidioc_querybuf = zr364xx_vidioc_querybuf,
1445 .vidioc_qbuf = zr364xx_vidioc_qbuf,
1446 .vidioc_dqbuf = zr364xx_vidioc_dqbuf,
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001447};
1448
Hans Verkuila3998102008-07-21 02:57:38 -03001449static struct video_device zr364xx_template = {
Hans Verkuila3998102008-07-21 02:57:38 -03001450 .name = DRIVER_DESC,
Hans Verkuila3998102008-07-21 02:57:38 -03001451 .fops = &zr364xx_fops,
1452 .ioctl_ops = &zr364xx_ioctl_ops,
1453 .release = video_device_release,
1454 .minor = -1,
1455};
1456
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001457
1458
1459/*******************/
1460/* USB integration */
1461/*******************/
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001462static int zr364xx_board_init(struct zr364xx_camera *cam)
1463{
1464 struct zr364xx_pipeinfo *pipe = cam->pipe;
1465 unsigned long i;
1466
1467 DBG("board init: %p\n", cam);
1468 memset(pipe, 0, sizeof(*pipe));
1469 pipe->cam = cam;
1470 pipe->transfer_size = BUFFER_SIZE;
1471
1472 pipe->transfer_buffer = kzalloc(pipe->transfer_size,
1473 GFP_KERNEL);
1474 if (pipe->transfer_buffer == NULL) {
1475 DBG("out of memory!\n");
1476 return -ENOMEM;
1477 }
1478
1479 cam->b_acquire = 0;
1480 cam->frame_count = 0;
1481
1482 /*** start create system buffers ***/
1483 for (i = 0; i < FRAMES; i++) {
1484 /* always allocate maximum size for system buffers */
1485 cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE);
1486
1487 DBG("valloc %p, idx %lu, pdata %p\n",
1488 &cam->buffer.frame[i], i,
1489 cam->buffer.frame[i].lpvbits);
1490 if (cam->buffer.frame[i].lpvbits == NULL) {
1491 printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
1492 "Using less frames\n");
1493 break;
1494 }
1495 }
1496
1497 if (i == 0) {
1498 printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
1499 kfree(cam->pipe->transfer_buffer);
1500 cam->pipe->transfer_buffer = NULL;
1501 return -ENOMEM;
1502 } else
1503 cam->buffer.dwFrames = i;
1504
1505 /* make sure internal states are set */
1506 for (i = 0; i < FRAMES; i++) {
1507 cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE;
1508 cam->buffer.frame[i].cur_size = 0;
1509 }
1510
1511 cam->cur_frame = 0;
1512 cam->last_frame = -1;
1513 /*** end create system buffers ***/
1514
1515 /* start read pipe */
1516 zr364xx_start_readpipe(cam);
1517 DBG(": board initialized\n");
1518 return 0;
1519}
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001520
1521static int zr364xx_probe(struct usb_interface *intf,
1522 const struct usb_device_id *id)
1523{
1524 struct usb_device *udev = interface_to_usbdev(intf);
1525 struct zr364xx_camera *cam = NULL;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001526 struct usb_host_interface *iface_desc;
1527 struct usb_endpoint_descriptor *endpoint;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001528 int err;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001529 int i;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001530
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001531 DBG("probing...\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001532
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001533 dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
1534 dev_info(&intf->dev, "model %04x:%04x detected\n",
1535 le16_to_cpu(udev->descriptor.idVendor),
1536 le16_to_cpu(udev->descriptor.idProduct));
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001537
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001538 cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
1539 if (cam == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001540 dev_err(&udev->dev, "cam: out of memory !\n");
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001541 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001542 }
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001543 /* save the init method used by this camera */
1544 cam->method = id->driver_info;
1545
1546 cam->vdev = video_device_alloc();
1547 if (cam->vdev == NULL) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001548 dev_err(&udev->dev, "cam->vdev: out of memory !\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001549 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001550 cam = NULL;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001551 return -ENOMEM;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001552 }
1553 memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template));
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001554 cam->vdev->parent = &intf->dev;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001555 video_set_drvdata(cam->vdev, cam);
1556 if (debug)
1557 cam->vdev->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
1558
1559 cam->udev = udev;
1560
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001561 switch (mode) {
1562 case 1:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001563 dev_info(&udev->dev, "160x120 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001564 cam->width = 160;
1565 cam->height = 120;
1566 break;
1567 case 2:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001568 dev_info(&udev->dev, "640x480 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001569 cam->width = 640;
1570 cam->height = 480;
1571 break;
1572 default:
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001573 dev_info(&udev->dev, "320x240 mode selected\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001574 cam->width = 320;
1575 cam->height = 240;
1576 break;
1577 }
1578
1579 m0d1[0] = mode;
1580 m1[2].value = 0xf000 + mode;
1581 m2[1].value = 0xf000 + mode;
1582 header2[437] = cam->height / 256;
1583 header2[438] = cam->height % 256;
1584 header2[439] = cam->width / 256;
1585 header2[440] = cam->width % 256;
1586
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001587 cam->users = 0;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001588 cam->nb = 0;
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001589 cam->mode.brightness = 64;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001590 mutex_init(&cam->lock);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001591 mutex_init(&cam->open_lock);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001592
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001593 DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf);
1594
1595 /* set up the endpoint information */
1596 iface_desc = intf->cur_altsetting;
1597 DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints);
1598 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1599 endpoint = &iface_desc->endpoint[i].desc;
1600 if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
1601 /* we found the bulk in endpoint */
1602 cam->read_endpoint = endpoint->bEndpointAddress;
1603 }
1604 }
1605
1606 if (!cam->read_endpoint) {
1607 dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
1608 return -ENOMEM;
1609 }
1610
1611 /* v4l */
1612 INIT_LIST_HEAD(&cam->vidq.active);
1613 cam->vidq.cam = cam;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001614 err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1);
1615 if (err) {
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001616 dev_err(&udev->dev, "video_register_device failed\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001617 video_device_release(cam->vdev);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001618 kfree(cam);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001619 cam = NULL;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001620 return err;
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001621 }
1622
1623 usb_set_intfdata(intf, cam);
1624
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001625 /* load zr364xx board specific */
1626 err = zr364xx_board_init(cam);
1627 if (err) {
1628 spin_lock_init(&cam->slock);
1629 return err;
1630 }
1631
1632 spin_lock_init(&cam->slock);
1633
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001634 dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n",
Hans Verkuilc6330fb2008-10-19 18:54:26 -03001635 cam->vdev->num);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001636 return 0;
1637}
1638
1639
1640static void zr364xx_disconnect(struct usb_interface *intf)
1641{
1642 struct zr364xx_camera *cam = usb_get_intfdata(intf);
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001643 videobuf_mmap_free(&cam->vb_vidq);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001644 usb_set_intfdata(intf, NULL);
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001645 dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
Lamarque Vieira Souzaccbf0352009-07-15 20:54:55 -03001646 zr364xx_destroy(cam);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001647}
1648
1649
1650
1651/**********************/
1652/* Module integration */
1653/**********************/
1654
1655static struct usb_driver zr364xx_driver = {
1656 .name = "zr364xx",
1657 .probe = zr364xx_probe,
1658 .disconnect = zr364xx_disconnect,
1659 .id_table = device_table
1660};
1661
1662
1663static int __init zr364xx_init(void)
1664{
1665 int retval;
Akinobu Mita783aa8f2007-05-20 09:12:10 -03001666 retval = usb_register(&zr364xx_driver);
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001667 if (retval)
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001668 printk(KERN_ERR KBUILD_MODNAME ": usb_register failed!\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001669 else
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001670 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001671 return retval;
1672}
1673
1674
1675static void __exit zr364xx_exit(void)
1676{
Greg Kroah-Hartmana482f322008-10-10 05:08:23 -03001677 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC " module unloaded\n");
Antoine Jacquetb7eee612007-04-27 12:30:59 -03001678 usb_deregister(&zr364xx_driver);
1679}
1680
1681
1682module_init(zr364xx_init);
1683module_exit(zr364xx_exit);
1684
1685MODULE_AUTHOR(DRIVER_AUTHOR);
1686MODULE_DESCRIPTION(DRIVER_DESC);
1687MODULE_LICENSE("GPL");