blob: 5e7b795013706591aff8dfb09099d9dd60a8fff1 [file] [log] [blame]
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -03001/*
2 * Driver for Logitech Quickcam Messenger usb video camera
3 * Copyright (C) Jaya Kumar
4 *
5 * This work was sponsored by CIS(M) Sdn Bhd.
6 * History:
7 * 05/08/2006 - Jaya Kumar
8 * I wrote this based on the konicawc by Simon Evans.
9 * -
10 * Full credit for reverse engineering and creating an initial
11 * working linux driver for the VV6422 goes to the qce-ga project by
12 * Tuukka Toivonen, Jochen Hoenicke, Peter McConnell,
13 * Cristiano De Michele, Georg Acher, Jean-Frederic Clere as well as
14 * others.
15 * ---
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
31
32#include <linux/kernel.h>
33#include <linux/module.h>
34#include <linux/init.h>
35#include <linux/input.h>
Andrew Morton20c54262006-06-26 00:24:30 -070036#include <linux/usb/input.h>
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -030037
38#include "usbvideo.h"
39#include "quickcam_messenger.h"
40
41/*
42 * Version Information
43 */
44
45#ifdef CONFIG_USB_DEBUG
46static int debug;
47#define DEBUG(n, format, arg...) \
48 if (n <= debug) { \
49 printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
50 }
51#else
52#define DEBUG(n, arg...)
53static const int debug = 0;
54#endif
55
56#define DRIVER_VERSION "v0.01"
57#define DRIVER_DESC "Logitech Quickcam Messenger USB"
58
59#define USB_LOGITECH_VENDOR_ID 0x046D
60#define USB_QCM_PRODUCT_ID 0x08F0
61
62#define MAX_CAMERAS 1
63
64#define MAX_COLOUR 32768
65#define MAX_HUE 32768
66#define MAX_BRIGHTNESS 32768
67#define MAX_CONTRAST 32768
68#define MAX_WHITENESS 32768
69
70static int size = SIZE_320X240;
71static int colour = MAX_COLOUR;
72static int hue = MAX_HUE;
73static int brightness = MAX_BRIGHTNESS;
74static int contrast = MAX_CONTRAST;
75static int whiteness = MAX_WHITENESS;
76
77static struct usbvideo *cams;
78
79static struct usb_device_id qcm_table [] = {
80 { USB_DEVICE(USB_LOGITECH_VENDOR_ID, USB_QCM_PRODUCT_ID) },
81 { }
82};
83MODULE_DEVICE_TABLE(usb, qcm_table);
84
85#ifdef CONFIG_INPUT
86static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
87{
88 struct input_dev *input_dev;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -030089 int error;
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -030090
91 usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
92 strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
93
94 cam->input = input_dev = input_allocate_device();
95 if (!input_dev) {
96 warn("insufficient mem for cam input device");
97 return;
98 }
99
100 input_dev->name = "QCM button";
101 input_dev->phys = cam->input_physname;
102 usb_to_input_id(dev, &input_dev->id);
Dmitry Torokhov2c8a3a32007-07-16 09:28:15 -0300103 input_dev->dev.parent = &dev->dev;
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -0300104
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700105 input_dev->evbit[0] = BIT_MASK(EV_KEY);
106 input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -0300107
108 input_dev->private = cam;
109
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300110 error = input_register_device(cam->input);
111 if (error) {
112 warn("Failed to register camera's input device, err: %d\n",
113 error);
114 input_free_device(cam->input);
115 cam->input = NULL;
116 }
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -0300117}
118
119static void qcm_unregister_input(struct qcm *cam)
120{
121 if (cam->input) {
122 input_unregister_device(cam->input);
123 cam->input = NULL;
124 }
125}
126
127static void qcm_report_buttonstat(struct qcm *cam)
128{
129 if (cam->input) {
130 input_report_key(cam->input, BTN_0, cam->button_sts);
131 input_sync(cam->input);
132 }
133}
134
David Howells7d12e782006-10-05 14:55:46 +0100135static void qcm_int_irq(struct urb *urb)
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -0300136{
137 int ret;
138 struct uvd *uvd = urb->context;
139 struct qcm *cam;
140
141 if (!CAMERA_IS_OPERATIONAL(uvd))
142 return;
143
144 if (!uvd->streaming)
145 return;
146
147 uvd->stats.urb_count++;
148
149 if (urb->status < 0)
150 uvd->stats.iso_err_count++;
151 else {
152 if (urb->actual_length > 0 ) {
153 cam = (struct qcm *) uvd->user_data;
154 if (cam->button_sts_buf == 0x88)
155 cam->button_sts = 0x0;
156 else if (cam->button_sts_buf == 0x80)
157 cam->button_sts = 0x1;
158 qcm_report_buttonstat(cam);
159 }
160 }
161
162 ret = usb_submit_urb(urb, GFP_ATOMIC);
163 if (ret < 0)
164 err("usb_submit_urb error (%d)", ret);
165}
166
167static int qcm_setup_input_int(struct qcm *cam, struct uvd *uvd)
168{
169 int errflag;
170 usb_fill_int_urb(cam->button_urb, uvd->dev,
171 usb_rcvintpipe(uvd->dev, uvd->video_endp + 1),
172 &cam->button_sts_buf,
173 1,
174 qcm_int_irq,
175 uvd, 16);
176
177 errflag = usb_submit_urb(cam->button_urb, GFP_KERNEL);
178 if (errflag)
179 err ("usb_submit_int ret %d", errflag);
180 return errflag;
181}
182
183static void qcm_stop_int_data(struct qcm *cam)
184{
185 usb_kill_urb(cam->button_urb);
186}
187
188static int qcm_alloc_int_urb(struct qcm *cam)
189{
190 cam->button_urb = usb_alloc_urb(0, GFP_KERNEL);
191
192 if (!cam->button_urb)
193 return -ENOMEM;
194
195 return 0;
196}
197
198static void qcm_free_int(struct qcm *cam)
199{
Mariusz Kozlowski926b1e92006-11-08 15:35:02 +0100200 usb_free_urb(cam->button_urb);
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -0300201}
202#endif /* CONFIG_INPUT */
203
204static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val)
205{
206 int ret;
207
208 /* we'll wait up to 3 slices but no more */
209 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
210 0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
211 reg, 0, &val, 1, 3*HZ);
212 return ret;
213}
214
215static int qcm_stv_setw(struct usb_device *dev, u16 reg, u16 val)
216{
217 int ret;
218
219 /* we'll wait up to 3 slices but no more */
220 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
221 0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
222 reg, 0, &val, 2, 3*HZ);
223 return ret;
224}
225
226static int qcm_stv_getw(struct usb_device *dev, unsigned short reg,
227 __le16 *val)
228{
229 int ret;
230
231 /* we'll wait up to 3 slices but no more */
232 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
233 0x04, USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
234 reg, 0, val, 2, 3*HZ);
235 return ret;
236}
237
238static int qcm_camera_on(struct uvd *uvd)
239{
240 int ret;
241 CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x01));
242 return 0;
243}
244
245static int qcm_camera_off(struct uvd *uvd)
246{
247 int ret;
248 CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00));
249 return 0;
250}
251
252static void qcm_hsv2rgb(u16 hue, u16 sat, u16 val, u16 *r, u16 *g, u16 *b)
253{
254 unsigned int segment, valsat;
255 signed int h = (signed int) hue;
256 unsigned int s = (sat - 32768) * 2; /* rescale */
257 unsigned int v = val;
258 unsigned int p;
259
260 /*
Joe Perchesc84e6032008-02-03 17:18:59 +0200261 the registers controlling gain are 8 bit of which
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -0300262 we affect only the last 4 bits with our gain.
263 we know that if saturation is 0, (unsaturated) then
264 we're grayscale (center axis of the colour cone) so
265 we set rgb=value. we use a formula obtained from
266 wikipedia to map the cone to the RGB plane. it's
267 as follows for the human value case of h=0..360,
268 s=0..1, v=0..1
269 h_i = h/60 % 6 , f = h/60 - h_i , p = v(1-s)
270 q = v(1 - f*s) , t = v(1 - (1-f)s)
271 h_i==0 => r=v , g=t, b=p
272 h_i==1 => r=q , g=v, b=p
273 h_i==2 => r=p , g=v, b=t
274 h_i==3 => r=p , g=q, b=v
275 h_i==4 => r=t , g=p, b=v
276 h_i==5 => r=v , g=p, b=q
277 the bottom side (the point) and the stuff just up
278 of that is black so we simplify those two cases.
279 */
280 if (sat < 32768) {
281 /* anything less than this is unsaturated */
282 *r = val;
283 *g = val;
284 *b = val;
285 return;
286 }
287 if (val <= (0xFFFF/8)) {
288 /* anything less than this is black */
289 *r = 0;
290 *g = 0;
291 *b = 0;
292 return;
293 }
294
295 /* the rest of this code is copying tukkat's
296 implementation of the hsv2rgb conversion as taken
297 from qc-usb-messenger code. the 10923 is 0xFFFF/6
298 to divide the cone into 6 sectors. */
299
300 segment = (h + 10923) & 0xFFFF;
301 segment = segment*3 >> 16; /* 0..2: 0=R, 1=G, 2=B */
302 hue -= segment * 21845; /* -10923..10923 */
303 h = hue;
304 h *= 3;
305 valsat = v*s >> 16; /* 0..65534 */
306 p = v - valsat;
307 if (h >= 0) {
308 unsigned int t = v - (valsat * (32769 - h) >> 15);
309 switch (segment) {
310 case 0: /* R-> */
311 *r = v;
312 *g = t;
313 *b = p;
314 break;
315 case 1: /* G-> */
316 *r = p;
317 *g = v;
318 *b = t;
319 break;
320 case 2: /* B-> */
321 *r = t;
322 *g = p;
323 *b = v;
324 break;
325 }
326 } else {
327 unsigned int q = v - (valsat * (32769 + h) >> 15);
328 switch (segment) {
329 case 0: /* ->R */
330 *r = v;
331 *g = p;
332 *b = q;
333 break;
334 case 1: /* ->G */
335 *r = q;
336 *g = v;
337 *b = p;
338 break;
339 case 2: /* ->B */
340 *r = p;
341 *g = q;
342 *b = v;
343 break;
344 }
345 }
346}
347
348static int qcm_sensor_set_gains(struct uvd *uvd, u16 hue,
349 u16 saturation, u16 value)
350{
351 int ret;
Mauro Carvalho Chehabd6144022006-05-19 13:08:09 -0300352 u16 r=0,g=0,b=0;
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -0300353
354 /* this code is based on qc-usb-messenger */
355 qcm_hsv2rgb(hue, saturation, value, &r, &g, &b);
356
357 r >>= 12;
358 g >>= 12;
359 b >>= 12;
360
361 /* min val is 8 */
362 r = max((u16) 8, r);
363 g = max((u16) 8, g);
364 b = max((u16) 8, b);
365
366 r |= 0x30;
367 g |= 0x30;
368 b |= 0x30;
369
370 /* set the r,g,b gain registers */
371 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x0509, r));
372 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050A, g));
373 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050B, b));
374
375 /* doing as qc-usb did */
376 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050C, 0x2A));
377 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050D, 0x01));
378 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
379
380 return 0;
381}
382
383static int qcm_sensor_set_exposure(struct uvd *uvd, int exposure)
384{
385 int ret;
386 int formedval;
387
388 /* calculation was from qc-usb-messenger driver */
389 formedval = ( exposure >> 12 );
390
391 /* max value for formedval is 14 */
392 formedval = min(formedval, 14);
393
394 CHECK_RET(ret, qcm_stv_setb(uvd->dev,
395 0x143A, 0xF0 | formedval));
396 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
397 return 0;
398}
399
400static int qcm_sensor_setlevels(struct uvd *uvd, int brightness, int contrast,
401 int hue, int colour)
402{
403 int ret;
404 /* brightness is exposure, contrast is gain, colour is saturation */
405 CHECK_RET(ret,
406 qcm_sensor_set_exposure(uvd, brightness));
407 CHECK_RET(ret, qcm_sensor_set_gains(uvd, hue, colour, contrast));
408
409 return 0;
410}
411
412static int qcm_sensor_setsize(struct uvd *uvd, u8 size)
413{
414 int ret;
415
416 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x1505, size));
417 return 0;
418}
419
420static int qcm_sensor_set_shutter(struct uvd *uvd, int whiteness)
421{
422 int ret;
423 /* some rescaling as done by the qc-usb-messenger code */
424 if (whiteness > 0xC000)
425 whiteness = 0xC000 + (whiteness & 0x3FFF)*8;
426
427 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143D,
428 (whiteness >> 8) & 0xFF));
429 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143E,
430 (whiteness >> 16) & 0x03));
431 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
432
433 return 0;
434}
435
436static int qcm_sensor_init(struct uvd *uvd)
437{
438 struct qcm *cam = (struct qcm *) uvd->user_data;
439 int ret;
440 int i;
441
Robert P. J. Day0c71bf12007-06-05 05:20:56 -0300442 for (i=0; i < ARRAY_SIZE(regval_table) ; i++) {
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -0300443 CHECK_RET(ret, qcm_stv_setb(uvd->dev,
444 regval_table[i].reg,
445 regval_table[i].val));
446 }
447
448 CHECK_RET(ret, qcm_stv_setw(uvd->dev, 0x15c1,
449 cpu_to_le16(ISOC_PACKET_SIZE)));
450 CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x15c3, 0x08));
451 CHECK_RET(ret, ret = qcm_stv_setb(uvd->dev, 0x143f, 0x01));
452
453 CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00));
454
455 CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
456
457 CHECK_RET(ret, qcm_sensor_setlevels(uvd, uvd->vpic.brightness,
458 uvd->vpic.contrast, uvd->vpic.hue, uvd->vpic.colour));
459
460 CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness));
461 CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
462
463 return 0;
464}
465
466static int qcm_set_camera_size(struct uvd *uvd)
467{
468 int ret;
469 struct qcm *cam = (struct qcm *) uvd->user_data;
470
471 CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
472 cam->width = camera_sizes[cam->size].width;
473 cam->height = camera_sizes[cam->size].height;
474 uvd->videosize = VIDEOSIZE(cam->width, cam->height);
475
476 return 0;
477}
478
479static int qcm_setup_on_open(struct uvd *uvd)
480{
481 int ret;
482
483 CHECK_RET(ret, qcm_sensor_set_gains(uvd, uvd->vpic.hue,
484 uvd->vpic.colour, uvd->vpic.contrast));
485 CHECK_RET(ret, qcm_sensor_set_exposure(uvd, uvd->vpic.brightness));
486 CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness));
487 CHECK_RET(ret, qcm_set_camera_size(uvd));
488 CHECK_RET(ret, qcm_camera_on(uvd));
489 return 0;
490}
491
492static void qcm_adjust_picture(struct uvd *uvd)
493{
494 int ret;
495 struct qcm *cam = (struct qcm *) uvd->user_data;
496
497 ret = qcm_camera_off(uvd);
498 if (ret) {
499 err("can't turn camera off. abandoning pic adjustment");
500 return;
501 }
502
503 /* if there's been a change in contrast, hue, or
504 colour then we need to recalculate hsv in order
505 to update gains */
506 if ((cam->contrast != uvd->vpic.contrast) ||
507 (cam->hue != uvd->vpic.hue) ||
508 (cam->colour != uvd->vpic.colour)) {
509 cam->contrast = uvd->vpic.contrast;
510 cam->hue = uvd->vpic.hue;
511 cam->colour = uvd->vpic.colour;
512 ret = qcm_sensor_set_gains(uvd, cam->hue, cam->colour,
513 cam->contrast);
514 if (ret) {
515 err("can't set gains. abandoning pic adjustment");
516 return;
517 }
518 }
519
520 if (cam->brightness != uvd->vpic.brightness) {
521 cam->brightness = uvd->vpic.brightness;
522 ret = qcm_sensor_set_exposure(uvd, cam->brightness);
523 if (ret) {
524 err("can't set exposure. abandoning pic adjustment");
525 return;
526 }
527 }
528
529 if (cam->whiteness != uvd->vpic.whiteness) {
530 cam->whiteness = uvd->vpic.whiteness;
531 qcm_sensor_set_shutter(uvd, cam->whiteness);
532 if (ret) {
533 err("can't set shutter. abandoning pic adjustment");
534 return;
535 }
536 }
537
538 ret = qcm_camera_on(uvd);
539 if (ret) {
540 err("can't reenable camera. pic adjustment failed");
541 return;
542 }
543}
544
545static int qcm_process_frame(struct uvd *uvd, u8 *cdata, int framelen)
546{
547 int datalen;
548 int totaldata;
549 struct framehdr {
550 __be16 id;
551 __be16 len;
552 };
553 struct framehdr *fhdr;
554
555 totaldata = 0;
556 while (framelen) {
557 fhdr = (struct framehdr *) cdata;
558 datalen = be16_to_cpu(fhdr->len);
559 framelen -= 4;
560 cdata += 4;
561
562 if ((fhdr->id) == cpu_to_be16(0x8001)) {
563 RingQueue_Enqueue(&uvd->dp, marker, 4);
564 totaldata += 4;
565 continue;
566 }
567 if ((fhdr->id & cpu_to_be16(0xFF00)) == cpu_to_be16(0x0200)) {
568 RingQueue_Enqueue(&uvd->dp, cdata, datalen);
569 totaldata += datalen;
570 }
571 framelen -= datalen;
572 cdata += datalen;
573 }
574 return totaldata;
575}
576
577static int qcm_compress_iso(struct uvd *uvd, struct urb *dataurb)
578{
579 int totlen;
580 int i;
581 unsigned char *cdata;
582
583 totlen=0;
584 for (i = 0; i < dataurb->number_of_packets; i++) {
585 int n = dataurb->iso_frame_desc[i].actual_length;
586 int st = dataurb->iso_frame_desc[i].status;
587
588 cdata = dataurb->transfer_buffer +
589 dataurb->iso_frame_desc[i].offset;
590
591 if (st < 0) {
592 warn("Data error: packet=%d. len=%d. status=%d.",
593 i, n, st);
594 uvd->stats.iso_err_count++;
595 continue;
596 }
597 if (!n)
598 continue;
599
600 totlen += qcm_process_frame(uvd, cdata, n);
601 }
602 return totlen;
603}
604
605static void resubmit_urb(struct uvd *uvd, struct urb *urb)
606{
607 int ret;
608
609 urb->dev = uvd->dev;
610 ret = usb_submit_urb(urb, GFP_ATOMIC);
611 if (ret)
612 err("usb_submit_urb error (%d)", ret);
613}
614
David Howells7d12e782006-10-05 14:55:46 +0100615static void qcm_isoc_irq(struct urb *urb)
jayakumar.video@gmail.come48a9c62006-05-17 15:01:07 -0300616{
617 int len;
618 struct uvd *uvd = urb->context;
619
620 if (!CAMERA_IS_OPERATIONAL(uvd))
621 return;
622
623 if (!uvd->streaming)
624 return;
625
626 uvd->stats.urb_count++;
627
628 if (!urb->actual_length) {
629 resubmit_urb(uvd, urb);
630 return;
631 }
632
633 len = qcm_compress_iso(uvd, urb);
634 resubmit_urb(uvd, urb);
635 uvd->stats.urb_length = len;
636 uvd->stats.data_count += len;
637 if (len)
638 RingQueue_WakeUpInterruptible(&uvd->dp);
639}
640
641static int qcm_start_data(struct uvd *uvd)
642{
643 struct qcm *cam = (struct qcm *) uvd->user_data;
644 int i;
645 int errflag;
646 int pktsz;
647 int err;
648
649 pktsz = uvd->iso_packet_len;
650 if (!CAMERA_IS_OPERATIONAL(uvd)) {
651 err("Camera is not operational");
652 return -EFAULT;
653 }
654
655 err = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltActive);
656 if (err < 0) {
657 err("usb_set_interface error");
658 uvd->last_error = err;
659 return -EBUSY;
660 }
661
662 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
663 int j, k;
664 struct urb *urb = uvd->sbuf[i].urb;
665 urb->dev = uvd->dev;
666 urb->context = uvd;
667 urb->pipe = usb_rcvisocpipe(uvd->dev, uvd->video_endp);
668 urb->interval = 1;
669 urb->transfer_flags = URB_ISO_ASAP;
670 urb->transfer_buffer = uvd->sbuf[i].data;
671 urb->complete = qcm_isoc_irq;
672 urb->number_of_packets = FRAMES_PER_DESC;
673 urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC;
674 for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) {
675 urb->iso_frame_desc[j].offset = k;
676 urb->iso_frame_desc[j].length = pktsz;
677 }
678 }
679
680 uvd->streaming = 1;
681 uvd->curframe = -1;
682 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
683 errflag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
684 if (errflag)
685 err ("usb_submit_isoc(%d) ret %d", i, errflag);
686 }
687
688 CHECK_RET(err, qcm_setup_input_int(cam, uvd));
689 CHECK_RET(err, qcm_camera_on(uvd));
690 return 0;
691}
692
693static void qcm_stop_data(struct uvd *uvd)
694{
695 struct qcm *cam = (struct qcm *) uvd->user_data;
696 int i, j;
697 int ret;
698
699 if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
700 return;
701
702 ret = qcm_camera_off(uvd);
703 if (ret)
704 warn("couldn't turn the cam off.");
705
706 uvd->streaming = 0;
707
708 /* Unschedule all of the iso td's */
709 for (i=0; i < USBVIDEO_NUMSBUF; i++)
710 usb_kill_urb(uvd->sbuf[i].urb);
711
712 qcm_stop_int_data(cam);
713
714 if (!uvd->remove_pending) {
715 /* Set packet size to 0 */
716 j = usb_set_interface(uvd->dev, uvd->iface,
717 uvd->ifaceAltInactive);
718 if (j < 0) {
719 err("usb_set_interface() error %d.", j);
720 uvd->last_error = j;
721 }
722 }
723}
724
725static void qcm_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame)
726{
727 struct qcm *cam = (struct qcm *) uvd->user_data;
728 int x;
729 struct rgb *rgbL0;
730 struct rgb *rgbL1;
731 struct bayL0 *bayL0;
732 struct bayL1 *bayL1;
733 int hor,ver,hordel,verdel;
734 assert(frame != NULL);
735
736 switch (cam->size) {
737 case SIZE_160X120:
738 hor = 162; ver = 124; hordel = 1; verdel = 2;
739 break;
740 case SIZE_320X240:
741 default:
742 hor = 324; ver = 248; hordel = 2; verdel = 4;
743 break;
744 }
745
746 if (frame->scanstate == ScanState_Scanning) {
747 while (RingQueue_GetLength(&uvd->dp) >=
748 4 + (hor*verdel + hordel)) {
749 if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
750 (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) &&
751 (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) &&
752 (RING_QUEUE_PEEK(&uvd->dp, 3) == 0xff)) {
753 frame->curline = 0;
754 frame->scanstate = ScanState_Lines;
755 frame->frameState = FrameState_Grabbing;
756 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4);
757 /*
758 * if we're starting, we need to discard the first
759 * 4 lines of y bayer data
760 * and the first 2 gr elements of x bayer data
761 */
762 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp,
763 (hor*verdel + hordel));
764 break;
765 }
766 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
767 }
768 }
769
770 if (frame->scanstate == ScanState_Scanning)
771 return;
772
773 /* now we can start processing bayer data so long as we have at least
774 * 2 lines worth of data. this is the simplest demosaicing method that
775 * I could think of. I use each 2x2 bayer element without interpolation
776 * to generate 4 rgb pixels.
777 */
778 while ( frame->curline < cam->height &&
779 (RingQueue_GetLength(&uvd->dp) >= hor*2)) {
780 /* get 2 lines of bayer for demosaicing
781 * into 2 lines of RGB */
782 RingQueue_Dequeue(&uvd->dp, cam->scratch, hor*2);
783 bayL0 = (struct bayL0 *) cam->scratch;
784 bayL1 = (struct bayL1 *) (cam->scratch + hor);
785 /* frame->curline is the rgb y line */
786 rgbL0 = (struct rgb *)
787 ( frame->data + (cam->width*3*frame->curline));
788 /* w/2 because we're already doing 2 pixels */
789 rgbL1 = rgbL0 + (cam->width/2);
790
791 for (x=0; x < cam->width; x+=2) {
792 rgbL0->r = bayL0->r;
793 rgbL0->g = bayL0->g;
794 rgbL0->b = bayL1->b;
795
796 rgbL0->r2 = bayL0->r;
797 rgbL0->g2 = bayL1->g;
798 rgbL0->b2 = bayL1->b;
799
800 rgbL1->r = bayL0->r;
801 rgbL1->g = bayL1->g;
802 rgbL1->b = bayL1->b;
803
804 rgbL1->r2 = bayL0->r;
805 rgbL1->g2 = bayL1->g;
806 rgbL1->b2 = bayL1->b;
807
808 rgbL0++;
809 rgbL1++;
810
811 bayL0++;
812 bayL1++;
813 }
814
815 frame->seqRead_Length += cam->width*3*2;
816 frame->curline += 2;
817 }
818 /* See if we filled the frame */
819 if (frame->curline == cam->height) {
820 frame->frameState = FrameState_Done_Hold;
821 frame->curline = 0;
822 uvd->curframe = -1;
823 uvd->stats.frame_num++;
824 }
825}
826
827/* taken from konicawc */
828static int qcm_set_video_mode(struct uvd *uvd, struct video_window *vw)
829{
830 int ret;
831 int newsize;
832 int oldsize;
833 int x = vw->width;
834 int y = vw->height;
835 struct qcm *cam = (struct qcm *) uvd->user_data;
836
837 if (x > 0 && y > 0) {
838 DEBUG(2, "trying to find size %d,%d", x, y);
839 for (newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) {
840 if ((camera_sizes[newsize].width == x) &&
841 (camera_sizes[newsize].height == y))
842 break;
843 }
844 } else
845 newsize = cam->size;
846
847 if (newsize > MAX_FRAME_SIZE) {
848 DEBUG(1, "couldn't find size %d,%d", x, y);
849 return -EINVAL;
850 }
851
852 if (newsize == cam->size) {
853 DEBUG(1, "Nothing to do");
854 return 0;
855 }
856
857 qcm_stop_data(uvd);
858
859 if (cam->size != newsize) {
860 oldsize = cam->size;
861 cam->size = newsize;
862 ret = qcm_set_camera_size(uvd);
863 if (ret) {
864 err("Couldn't set camera size, err=%d",ret);
865 /* restore the original size */
866 cam->size = oldsize;
867 return ret;
868 }
869 }
870
871 /* Flush the input queue and clear any current frame in progress */
872
873 RingQueue_Flush(&uvd->dp);
874 if (uvd->curframe != -1) {
875 uvd->frame[uvd->curframe].curline = 0;
876 uvd->frame[uvd->curframe].seqRead_Length = 0;
877 uvd->frame[uvd->curframe].seqRead_Index = 0;
878 }
879
880 CHECK_RET(ret, qcm_start_data(uvd));
881 return 0;
882}
883
884static int qcm_configure_video(struct uvd *uvd)
885{
886 int ret;
887 memset(&uvd->vpic, 0, sizeof(uvd->vpic));
888 memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
889
890 uvd->vpic.colour = colour;
891 uvd->vpic.hue = hue;
892 uvd->vpic.brightness = brightness;
893 uvd->vpic.contrast = contrast;
894 uvd->vpic.whiteness = whiteness;
895 uvd->vpic.depth = 24;
896 uvd->vpic.palette = VIDEO_PALETTE_RGB24;
897
898 memset(&uvd->vcap, 0, sizeof(uvd->vcap));
899 strcpy(uvd->vcap.name, "QCM USB Camera");
900 uvd->vcap.type = VID_TYPE_CAPTURE;
901 uvd->vcap.channels = 1;
902 uvd->vcap.audios = 0;
903
904 uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width;
905 uvd->vcap.minheight = camera_sizes[SIZE_160X120].height;
906 uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width;
907 uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height;
908
909 memset(&uvd->vchan, 0, sizeof(uvd->vchan));
910 uvd->vchan.flags = 0 ;
911 uvd->vchan.tuners = 0;
912 uvd->vchan.channel = 0;
913 uvd->vchan.type = VIDEO_TYPE_CAMERA;
914 strcpy(uvd->vchan.name, "Camera");
915
916 CHECK_RET(ret, qcm_sensor_init(uvd));
917 return 0;
918}
919
920static int qcm_probe(struct usb_interface *intf,
921 const struct usb_device_id *devid)
922{
923 int err;
924 struct uvd *uvd;
925 struct usb_device *dev = interface_to_usbdev(intf);
926 struct qcm *cam;
927 size_t buffer_size;
928 unsigned char video_ep;
929 struct usb_host_interface *interface;
930 struct usb_endpoint_descriptor *endpoint;
931 int i,j;
932 unsigned int ifacenum, ifacenum_inact=0;
933 __le16 sensor_id;
934
935 /* we don't support multiconfig cams */
936 if (dev->descriptor.bNumConfigurations != 1)
937 return -ENODEV;
938
939 /* first check for the video interface and not
940 * the audio interface */
941 interface = &intf->cur_altsetting[0];
942 if ((interface->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
943 || (interface->desc.bInterfaceSubClass !=
944 USB_CLASS_VENDOR_SPEC))
945 return -ENODEV;
946
947 /*
948 walk through each endpoint in each setting in the interface
949 stop when we find the one that's an isochronous IN endpoint.
950 */
951 for (i=0; i < intf->num_altsetting; i++) {
952 interface = &intf->cur_altsetting[i];
953 ifacenum = interface->desc.bAlternateSetting;
954 /* walk the end points */
955 for (j=0; j < interface->desc.bNumEndpoints; j++) {
956 endpoint = &interface->endpoint[j].desc;
957
958 if ((endpoint->bEndpointAddress &
959 USB_ENDPOINT_DIR_MASK) != USB_DIR_IN)
960 continue; /* not input then not good */
961
962 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
963 if (!buffer_size) {
964 ifacenum_inact = ifacenum;
965 continue; /* 0 pkt size is not what we want */
966 }
967
968 if ((endpoint->bmAttributes &
969 USB_ENDPOINT_XFERTYPE_MASK) ==
970 USB_ENDPOINT_XFER_ISOC) {
971 video_ep = endpoint->bEndpointAddress;
972 /* break out of the search */
973 goto good_videoep;
974 }
975 }
976 }
977 /* failed out since nothing useful was found */
978 err("No suitable endpoint was found\n");
979 return -ENODEV;
980
981good_videoep:
982 /* disable isochronous stream before doing anything else */
983 err = qcm_stv_setb(dev, STV_ISO_ENABLE, 0);
984 if (err < 0) {
985 err("Failed to disable sensor stream");
986 return -EIO;
987 }
988
989 /*
990 Check that this is the same unknown sensor that is known to work. This
991 sensor is suspected to be the ST VV6422C001. I'll check the same value
992 that the qc-usb driver checks. This value is probably not even the
993 sensor ID since it matches the USB dev ID. Oh well. If it doesn't
994 match, it's probably a diff sensor so exit and apologize.
995 */
996 err = qcm_stv_getw(dev, CMOS_SENSOR_IDREV, &sensor_id);
997 if (err < 0) {
998 err("Couldn't read sensor values. Err %d\n",err);
999 return err;
1000 }
1001 if (sensor_id != cpu_to_le16(0x08F0)) {
1002 err("Sensor ID %x != %x. Unsupported. Sorry\n",
1003 le16_to_cpu(sensor_id), (0x08F0));
1004 return -ENODEV;
1005 }
1006
1007 uvd = usbvideo_AllocateDevice(cams);
1008 if (!uvd)
1009 return -ENOMEM;
1010
1011 cam = (struct qcm *) uvd->user_data;
1012
1013 /* buf for doing demosaicing */
1014 cam->scratch = kmalloc(324*2, GFP_KERNEL);
1015 if (!cam->scratch) /* uvd freed in dereg */
1016 return -ENOMEM;
1017
1018 /* yes, if we fail after here, cam->scratch gets freed
1019 by qcm_free_uvd */
1020
1021 err = qcm_alloc_int_urb(cam);
1022 if (err < 0)
1023 return err;
1024
1025 /* yes, if we fail after here, int urb gets freed
1026 by qcm_free_uvd */
1027
1028 RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240);
1029 cam->width = camera_sizes[size].width;
1030 cam->height = camera_sizes[size].height;
1031 cam->size = size;
1032
1033 uvd->debug = debug;
1034 uvd->flags = 0;
1035 uvd->dev = dev;
1036 uvd->iface = intf->altsetting->desc.bInterfaceNumber;
1037 uvd->ifaceAltActive = ifacenum;
1038 uvd->ifaceAltInactive = ifacenum_inact;
1039 uvd->video_endp = video_ep;
1040 uvd->iso_packet_len = buffer_size;
1041 uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
1042 uvd->defaultPalette = VIDEO_PALETTE_RGB24;
1043 uvd->canvas = VIDEOSIZE(320, 240);
1044 uvd->videosize = VIDEOSIZE(cam->width, cam->height);
1045 err = qcm_configure_video(uvd);
1046 if (err) {
1047 err("failed to configure video settings");
1048 return err;
1049 }
1050
1051 err = usbvideo_RegisterVideoDevice(uvd);
1052 if (err) { /* the uvd gets freed in Deregister */
1053 err("usbvideo_RegisterVideoDevice() failed.");
1054 return err;
1055 }
1056
1057 uvd->max_frame_size = (320 * 240 * 3);
1058 qcm_register_input(cam, dev);
1059 usb_set_intfdata(intf, uvd);
1060 return 0;
1061}
1062
1063static void qcm_free_uvd(struct uvd *uvd)
1064{
1065 struct qcm *cam = (struct qcm *) uvd->user_data;
1066
1067 kfree(cam->scratch);
1068 qcm_unregister_input(cam);
1069 qcm_free_int(cam);
1070}
1071
1072static struct usbvideo_cb qcm_driver = {
1073 .probe = qcm_probe,
1074 .setupOnOpen = qcm_setup_on_open,
1075 .processData = qcm_process_isoc,
1076 .setVideoMode = qcm_set_video_mode,
1077 .startDataPump = qcm_start_data,
1078 .stopDataPump = qcm_stop_data,
1079 .adjustPicture = qcm_adjust_picture,
1080 .userFree = qcm_free_uvd
1081};
1082
1083static int __init qcm_init(void)
1084{
1085 info(DRIVER_DESC " " DRIVER_VERSION);
1086
1087 return usbvideo_register(
1088 &cams,
1089 MAX_CAMERAS,
1090 sizeof(struct qcm),
1091 "QCM",
1092 &qcm_driver,
1093 THIS_MODULE,
1094 qcm_table);
1095}
1096
1097static void __exit qcm_exit(void)
1098{
1099 usbvideo_Deregister(&cams);
1100}
1101
1102module_param(size, int, 0);
1103MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 320x240");
1104module_param(colour, int, 0);
1105MODULE_PARM_DESC(colour, "Initial colour");
1106module_param(hue, int, 0);
1107MODULE_PARM_DESC(hue, "Initial hue");
1108module_param(brightness, int, 0);
1109MODULE_PARM_DESC(brightness, "Initial brightness");
1110module_param(contrast, int, 0);
1111MODULE_PARM_DESC(contrast, "Initial contrast");
1112module_param(whiteness, int, 0);
1113MODULE_PARM_DESC(whiteness, "Initial whiteness");
1114
1115#ifdef CONFIG_USB_DEBUG
1116module_param(debug, int, S_IRUGO | S_IWUSR);
1117MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
1118#endif
1119
1120module_init(qcm_init);
1121module_exit(qcm_exit);
1122
1123MODULE_LICENSE("GPL");
1124MODULE_AUTHOR("Jaya Kumar");
1125MODULE_DESCRIPTION("QCM USB Camera");
1126MODULE_SUPPORTED_DEVICE("QCM USB Camera");