aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/usbvideo/quickcam_messenger.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/usbvideo/quickcam_messenger.c')
-rw-r--r--drivers/media/video/usbvideo/quickcam_messenger.c1126
1 files changed, 0 insertions, 1126 deletions
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
deleted file mode 100644
index fbd665fa1979..000000000000
--- a/drivers/media/video/usbvideo/quickcam_messenger.c
+++ /dev/null
@@ -1,1126 +0,0 @@
1/*
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>
36#include <linux/usb/input.h>
37#include <linux/slab.h>
38
39#include "usbvideo.h"
40#include "quickcam_messenger.h"
41
42/*
43 * Version Information
44 */
45
46#ifdef CONFIG_USB_DEBUG
47static int debug;
48#define DEBUG(n, format, arg...) \
49 if (n <= debug) { \
50 printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
51 }
52#else
53#define DEBUG(n, arg...)
54static const int debug;
55#endif
56
57#define DRIVER_VERSION "v0.01"
58#define DRIVER_DESC "Logitech Quickcam Messenger USB"
59
60#define USB_LOGITECH_VENDOR_ID 0x046D
61#define USB_QCM_PRODUCT_ID 0x08F0
62
63#define MAX_CAMERAS 1
64
65#define MAX_COLOUR 32768
66#define MAX_HUE 32768
67#define MAX_BRIGHTNESS 32768
68#define MAX_CONTRAST 32768
69#define MAX_WHITENESS 32768
70
71static int size = SIZE_320X240;
72static int colour = MAX_COLOUR;
73static int hue = MAX_HUE;
74static int brightness = MAX_BRIGHTNESS;
75static int contrast = MAX_CONTRAST;
76static int whiteness = MAX_WHITENESS;
77
78static struct usbvideo *cams;
79
80static struct usb_device_id qcm_table [] = {
81 { USB_DEVICE(USB_LOGITECH_VENDOR_ID, USB_QCM_PRODUCT_ID) },
82 { }
83};
84MODULE_DEVICE_TABLE(usb, qcm_table);
85
86#ifdef CONFIG_INPUT
87static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
88{
89 struct input_dev *input_dev;
90 int error;
91
92 usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
93 strlcat(cam->input_physname, "/input0", sizeof(cam->input_physname));
94
95 cam->input = input_dev = input_allocate_device();
96 if (!input_dev) {
97 dev_warn(&dev->dev, "insufficient mem for cam input device\n");
98 return;
99 }
100
101 input_dev->name = "QCM button";
102 input_dev->phys = cam->input_physname;
103 usb_to_input_id(dev, &input_dev->id);
104 input_dev->dev.parent = &dev->dev;
105
106 input_dev->evbit[0] = BIT_MASK(EV_KEY);
107 input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
108
109 error = input_register_device(cam->input);
110 if (error) {
111 dev_warn(&dev->dev,
112 "Failed to register camera's input device, err: %d\n",
113 error);
114 input_free_device(cam->input);
115 cam->input = NULL;
116 }
117}
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, KEY_CAMERA, cam->button_sts);
131 input_sync(cam->input);
132 }
133}
134
135static void qcm_int_irq(struct urb *urb)
136{
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{
200 usb_free_urb(cam->button_urb);
201}
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, __le16 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 /*
261 the registers controlling gain are 8 bit of which
262 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;
352 u16 r=0,g=0,b=0;
353
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
442 for (i=0; i < ARRAY_SIZE(regval_table) ; i++) {
443 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, 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 dev_warn(&uvd->dev->dev,
593 "Data error: packet=%d. len=%d. status=%d.\n",
594 i, n, st);
595 uvd->stats.iso_err_count++;
596 continue;
597 }
598 if (!n)
599 continue;
600
601 totlen += qcm_process_frame(uvd, cdata, n);
602 }
603 return totlen;
604}
605
606static void resubmit_urb(struct uvd *uvd, struct urb *urb)
607{
608 int ret;
609
610 urb->dev = uvd->dev;
611 ret = usb_submit_urb(urb, GFP_ATOMIC);
612 if (ret)
613 err("usb_submit_urb error (%d)", ret);
614}
615
616static void qcm_isoc_irq(struct urb *urb)
617{
618 int len;
619 struct uvd *uvd = urb->context;
620
621 if (!CAMERA_IS_OPERATIONAL(uvd))
622 return;
623
624 if (!uvd->streaming)
625 return;
626
627 uvd->stats.urb_count++;
628
629 if (!urb->actual_length) {
630 resubmit_urb(uvd, urb);
631 return;
632 }
633
634 len = qcm_compress_iso(uvd, urb);
635 resubmit_urb(uvd, urb);
636 uvd->stats.urb_length = len;
637 uvd->stats.data_count += len;
638 if (len)
639 RingQueue_WakeUpInterruptible(&uvd->dp);
640}
641
642static int qcm_start_data(struct uvd *uvd)
643{
644 struct qcm *cam = (struct qcm *) uvd->user_data;
645 int i;
646 int errflag;
647 int pktsz;
648 int err;
649
650 pktsz = uvd->iso_packet_len;
651 if (!CAMERA_IS_OPERATIONAL(uvd)) {
652 err("Camera is not operational");
653 return -EFAULT;
654 }
655
656 err = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltActive);
657 if (err < 0) {
658 err("usb_set_interface error");
659 uvd->last_error = err;
660 return -EBUSY;
661 }
662
663 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
664 int j, k;
665 struct urb *urb = uvd->sbuf[i].urb;
666 urb->dev = uvd->dev;
667 urb->context = uvd;
668 urb->pipe = usb_rcvisocpipe(uvd->dev, uvd->video_endp);
669 urb->interval = 1;
670 urb->transfer_flags = URB_ISO_ASAP;
671 urb->transfer_buffer = uvd->sbuf[i].data;
672 urb->complete = qcm_isoc_irq;
673 urb->number_of_packets = FRAMES_PER_DESC;
674 urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC;
675 for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) {
676 urb->iso_frame_desc[j].offset = k;
677 urb->iso_frame_desc[j].length = pktsz;
678 }
679 }
680
681 uvd->streaming = 1;
682 uvd->curframe = -1;
683 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
684 errflag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
685 if (errflag)
686 err ("usb_submit_isoc(%d) ret %d", i, errflag);
687 }
688
689 CHECK_RET(err, qcm_setup_input_int(cam, uvd));
690 CHECK_RET(err, qcm_camera_on(uvd));
691 return 0;
692}
693
694static void qcm_stop_data(struct uvd *uvd)
695{
696 struct qcm *cam;
697 int i, j;
698 int ret;
699
700 if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
701 return;
702 cam = (struct qcm *) uvd->user_data;
703
704 ret = qcm_camera_off(uvd);
705 if (ret)
706 dev_warn(&uvd->dev->dev, "couldn't turn the cam off.\n");
707
708 uvd->streaming = 0;
709
710 /* Unschedule all of the iso td's */
711 for (i=0; i < USBVIDEO_NUMSBUF; i++)
712 usb_kill_urb(uvd->sbuf[i].urb);
713
714 qcm_stop_int_data(cam);
715
716 if (!uvd->remove_pending) {
717 /* Set packet size to 0 */
718 j = usb_set_interface(uvd->dev, uvd->iface,
719 uvd->ifaceAltInactive);
720 if (j < 0) {
721 err("usb_set_interface() error %d.", j);
722 uvd->last_error = j;
723 }
724 }
725}
726
727static void qcm_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame)
728{
729 struct qcm *cam = (struct qcm *) uvd->user_data;
730 int x;
731 struct rgb *rgbL0;
732 struct rgb *rgbL1;
733 struct bayL0 *bayL0;
734 struct bayL1 *bayL1;
735 int hor,ver,hordel,verdel;
736 assert(frame != NULL);
737
738 switch (cam->size) {
739 case SIZE_160X120:
740 hor = 162; ver = 124; hordel = 1; verdel = 2;
741 break;
742 case SIZE_320X240:
743 default:
744 hor = 324; ver = 248; hordel = 2; verdel = 4;
745 break;
746 }
747
748 if (frame->scanstate == ScanState_Scanning) {
749 while (RingQueue_GetLength(&uvd->dp) >=
750 4 + (hor*verdel + hordel)) {
751 if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
752 (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) &&
753 (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) &&
754 (RING_QUEUE_PEEK(&uvd->dp, 3) == 0xff)) {
755 frame->curline = 0;
756 frame->scanstate = ScanState_Lines;
757 frame->frameState = FrameState_Grabbing;
758 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4);
759 /*
760 * if we're starting, we need to discard the first
761 * 4 lines of y bayer data
762 * and the first 2 gr elements of x bayer data
763 */
764 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp,
765 (hor*verdel + hordel));
766 break;
767 }
768 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
769 }
770 }
771
772 if (frame->scanstate == ScanState_Scanning)
773 return;
774
775 /* now we can start processing bayer data so long as we have at least
776 * 2 lines worth of data. this is the simplest demosaicing method that
777 * I could think of. I use each 2x2 bayer element without interpolation
778 * to generate 4 rgb pixels.
779 */
780 while ( frame->curline < cam->height &&
781 (RingQueue_GetLength(&uvd->dp) >= hor*2)) {
782 /* get 2 lines of bayer for demosaicing
783 * into 2 lines of RGB */
784 RingQueue_Dequeue(&uvd->dp, cam->scratch, hor*2);
785 bayL0 = (struct bayL0 *) cam->scratch;
786 bayL1 = (struct bayL1 *) (cam->scratch + hor);
787 /* frame->curline is the rgb y line */
788 rgbL0 = (struct rgb *)
789 ( frame->data + (cam->width*3*frame->curline));
790 /* w/2 because we're already doing 2 pixels */
791 rgbL1 = rgbL0 + (cam->width/2);
792
793 for (x=0; x < cam->width; x+=2) {
794 rgbL0->r = bayL0->r;
795 rgbL0->g = bayL0->g;
796 rgbL0->b = bayL1->b;
797
798 rgbL0->r2 = bayL0->r;
799 rgbL0->g2 = bayL1->g;
800 rgbL0->b2 = bayL1->b;
801
802 rgbL1->r = bayL0->r;
803 rgbL1->g = bayL1->g;
804 rgbL1->b = bayL1->b;
805
806 rgbL1->r2 = bayL0->r;
807 rgbL1->g2 = bayL1->g;
808 rgbL1->b2 = bayL1->b;
809
810 rgbL0++;
811 rgbL1++;
812
813 bayL0++;
814 bayL1++;
815 }
816
817 frame->seqRead_Length += cam->width*3*2;
818 frame->curline += 2;
819 }
820 /* See if we filled the frame */
821 if (frame->curline == cam->height) {
822 frame->frameState = FrameState_Done_Hold;
823 frame->curline = 0;
824 uvd->curframe = -1;
825 uvd->stats.frame_num++;
826 }
827}
828
829/* taken from konicawc */
830static int qcm_set_video_mode(struct uvd *uvd, struct video_window *vw)
831{
832 int ret;
833 int newsize;
834 int oldsize;
835 int x = vw->width;
836 int y = vw->height;
837 struct qcm *cam = (struct qcm *) uvd->user_data;
838
839 if (x > 0 && y > 0) {
840 DEBUG(2, "trying to find size %d,%d", x, y);
841 for (newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) {
842 if ((camera_sizes[newsize].width == x) &&
843 (camera_sizes[newsize].height == y))
844 break;
845 }
846 } else
847 newsize = cam->size;
848
849 if (newsize > MAX_FRAME_SIZE) {
850 DEBUG(1, "couldn't find size %d,%d", x, y);
851 return -EINVAL;
852 }
853
854 if (newsize == cam->size) {
855 DEBUG(1, "Nothing to do");
856 return 0;
857 }
858
859 qcm_stop_data(uvd);
860
861 if (cam->size != newsize) {
862 oldsize = cam->size;
863 cam->size = newsize;
864 ret = qcm_set_camera_size(uvd);
865 if (ret) {
866 err("Couldn't set camera size, err=%d",ret);
867 /* restore the original size */
868 cam->size = oldsize;
869 return ret;
870 }
871 }
872
873 /* Flush the input queue and clear any current frame in progress */
874
875 RingQueue_Flush(&uvd->dp);
876 if (uvd->curframe != -1) {
877 uvd->frame[uvd->curframe].curline = 0;
878 uvd->frame[uvd->curframe].seqRead_Length = 0;
879 uvd->frame[uvd->curframe].seqRead_Index = 0;
880 }
881
882 CHECK_RET(ret, qcm_start_data(uvd));
883 return 0;
884}
885
886static int qcm_configure_video(struct uvd *uvd)
887{
888 int ret;
889 memset(&uvd->vpic, 0, sizeof(uvd->vpic));
890 memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
891
892 uvd->vpic.colour = colour;
893 uvd->vpic.hue = hue;
894 uvd->vpic.brightness = brightness;
895 uvd->vpic.contrast = contrast;
896 uvd->vpic.whiteness = whiteness;
897 uvd->vpic.depth = 24;
898 uvd->vpic.palette = VIDEO_PALETTE_RGB24;
899
900 memset(&uvd->vcap, 0, sizeof(uvd->vcap));
901 strcpy(uvd->vcap.name, "QCM USB Camera");
902 uvd->vcap.type = VID_TYPE_CAPTURE;
903 uvd->vcap.channels = 1;
904 uvd->vcap.audios = 0;
905
906 uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width;
907 uvd->vcap.minheight = camera_sizes[SIZE_160X120].height;
908 uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width;
909 uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height;
910
911 memset(&uvd->vchan, 0, sizeof(uvd->vchan));
912 uvd->vchan.flags = 0 ;
913 uvd->vchan.tuners = 0;
914 uvd->vchan.channel = 0;
915 uvd->vchan.type = VIDEO_TYPE_CAMERA;
916 strcpy(uvd->vchan.name, "Camera");
917
918 CHECK_RET(ret, qcm_sensor_init(uvd));
919 return 0;
920}
921
922static int qcm_probe(struct usb_interface *intf,
923 const struct usb_device_id *devid)
924{
925 int err;
926 struct uvd *uvd;
927 struct usb_device *dev = interface_to_usbdev(intf);
928 struct qcm *cam;
929 size_t buffer_size;
930 unsigned char video_ep;
931 struct usb_host_interface *interface;
932 struct usb_endpoint_descriptor *endpoint;
933 int i,j;
934 unsigned int ifacenum, ifacenum_inact=0;
935 __le16 sensor_id;
936
937 /* we don't support multiconfig cams */
938 if (dev->descriptor.bNumConfigurations != 1)
939 return -ENODEV;
940
941 /* first check for the video interface and not
942 * the audio interface */
943 interface = &intf->cur_altsetting[0];
944 if ((interface->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
945 || (interface->desc.bInterfaceSubClass !=
946 USB_CLASS_VENDOR_SPEC))
947 return -ENODEV;
948
949 /*
950 walk through each endpoint in each setting in the interface
951 stop when we find the one that's an isochronous IN endpoint.
952 */
953 for (i=0; i < intf->num_altsetting; i++) {
954 interface = &intf->cur_altsetting[i];
955 ifacenum = interface->desc.bAlternateSetting;
956 /* walk the end points */
957 for (j=0; j < interface->desc.bNumEndpoints; j++) {
958 endpoint = &interface->endpoint[j].desc;
959
960 if (usb_endpoint_dir_out(endpoint))
961 continue; /* not input then not good */
962
963 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
964 if (!buffer_size) {
965 ifacenum_inact = ifacenum;
966 continue; /* 0 pkt size is not what we want */
967 }
968
969 if (usb_endpoint_xfer_isoc(endpoint)) {
970 video_ep = endpoint->bEndpointAddress;
971 /* break out of the search */
972 goto good_videoep;
973 }
974 }
975 }
976 /* failed out since nothing useful was found */
977 err("No suitable endpoint was found\n");
978 return -ENODEV;
979
980good_videoep:
981 /* disable isochronous stream before doing anything else */
982 err = qcm_stv_setb(dev, STV_ISO_ENABLE, 0);
983 if (err < 0) {
984 err("Failed to disable sensor stream");
985 return -EIO;
986 }
987
988 /*
989 Check that this is the same unknown sensor that is known to work. This
990 sensor is suspected to be the ST VV6422C001. I'll check the same value
991 that the qc-usb driver checks. This value is probably not even the
992 sensor ID since it matches the USB dev ID. Oh well. If it doesn't
993 match, it's probably a diff sensor so exit and apologize.
994 */
995 err = qcm_stv_getw(dev, CMOS_SENSOR_IDREV, &sensor_id);
996 if (err < 0) {
997 err("Couldn't read sensor values. Err %d\n",err);
998 return err;
999 }
1000 if (sensor_id != cpu_to_le16(0x08F0)) {
1001 err("Sensor ID %x != %x. Unsupported. Sorry\n",
1002 le16_to_cpu(sensor_id), (0x08F0));
1003 return -ENODEV;
1004 }
1005
1006 uvd = usbvideo_AllocateDevice(cams);
1007 if (!uvd)
1008 return -ENOMEM;
1009
1010 cam = (struct qcm *) uvd->user_data;
1011
1012 /* buf for doing demosaicing */
1013 cam->scratch = kmalloc(324*2, GFP_KERNEL);
1014 if (!cam->scratch) /* uvd freed in dereg */
1015 return -ENOMEM;
1016
1017 /* yes, if we fail after here, cam->scratch gets freed
1018 by qcm_free_uvd */
1019
1020 err = qcm_alloc_int_urb(cam);
1021 if (err < 0)
1022 return err;
1023
1024 /* yes, if we fail after here, int urb gets freed
1025 by qcm_free_uvd */
1026
1027 RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240);
1028 cam->width = camera_sizes[size].width;
1029 cam->height = camera_sizes[size].height;
1030 cam->size = size;
1031
1032 uvd->debug = debug;
1033 uvd->flags = 0;
1034 uvd->dev = dev;
1035 uvd->iface = intf->altsetting->desc.bInterfaceNumber;
1036 uvd->ifaceAltActive = ifacenum;
1037 uvd->ifaceAltInactive = ifacenum_inact;
1038 uvd->video_endp = video_ep;
1039 uvd->iso_packet_len = buffer_size;
1040 uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
1041 uvd->defaultPalette = VIDEO_PALETTE_RGB24;
1042 uvd->canvas = VIDEOSIZE(320, 240);
1043 uvd->videosize = VIDEOSIZE(cam->width, cam->height);
1044 err = qcm_configure_video(uvd);
1045 if (err) {
1046 err("failed to configure video settings");
1047 return err;
1048 }
1049
1050 err = usbvideo_RegisterVideoDevice(uvd);
1051 if (err) { /* the uvd gets freed in Deregister */
1052 err("usbvideo_RegisterVideoDevice() failed.");
1053 return err;
1054 }
1055
1056 uvd->max_frame_size = (320 * 240 * 3);
1057 qcm_register_input(cam, dev);
1058 usb_set_intfdata(intf, uvd);
1059 return 0;
1060}
1061
1062static void qcm_free_uvd(struct uvd *uvd)
1063{
1064 struct qcm *cam = (struct qcm *) uvd->user_data;
1065
1066 kfree(cam->scratch);
1067 qcm_unregister_input(cam);
1068 qcm_free_int(cam);
1069}
1070
1071static struct usbvideo_cb qcm_driver = {
1072 .probe = qcm_probe,
1073 .setupOnOpen = qcm_setup_on_open,
1074 .processData = qcm_process_isoc,
1075 .setVideoMode = qcm_set_video_mode,
1076 .startDataPump = qcm_start_data,
1077 .stopDataPump = qcm_stop_data,
1078 .adjustPicture = qcm_adjust_picture,
1079 .userFree = qcm_free_uvd
1080};
1081
1082static int __init qcm_init(void)
1083{
1084 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
1085 DRIVER_DESC "\n");
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");