aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/stv06xx/stv06xx.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2009-06-17 17:37:57 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-23 02:13:11 -0400
commit8668d504d72c384fbfb6ab6f5d02a9fe4d813554 (patch)
tree4ba923b0a7ccda8121960231e758135ba9bd584a /drivers/media/video/gspca/stv06xx/stv06xx.c
parentae49c40461d8981b232e3fec28234d492067f0e1 (diff)
V4L/DVB (12082): gspca_stv06xx: Add support for st6422 bridge and sensor
Add support for st6422 bridge and sensor to the stv06xx gspca sub driver, tested with: Logitech QuickCam Messenger 046d:08f0 ST6422 integrated Logitech QuickCam Mess. Plus 046d:08f6 ST6422 integrated Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/stv06xx/stv06xx.c')
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx.c53
1 files changed, 46 insertions, 7 deletions
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
index e573c3406324..0da8e0de0456 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -92,11 +92,10 @@ static int stv06xx_write_sensor_finish(struct sd *sd)
92{ 92{
93 int err = 0; 93 int err = 0;
94 94
95 if (IS_850(sd)) { 95 if (sd->bridge == BRIDGE_STV610) {
96 struct usb_device *udev = sd->gspca_dev.dev; 96 struct usb_device *udev = sd->gspca_dev.dev;
97 __u8 *buf = sd->gspca_dev.usb_buf; 97 __u8 *buf = sd->gspca_dev.usb_buf;
98 98
99 /* Quickam Web needs an extra packet */
100 buf[0] = 0; 99 buf[0] = 0;
101 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 100 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
102 0x04, 0x40, 0x1704, 0, buf, 1, 101 0x04, 0x40, 0x1704, 0, buf, 1,
@@ -253,7 +252,7 @@ static int stv06xx_init(struct gspca_dev *gspca_dev)
253 252
254 err = sd->sensor->init(sd); 253 err = sd->sensor->init(sd);
255 254
256 if (dump_sensor) 255 if (dump_sensor && sd->sensor->dump)
257 sd->sensor->dump(sd); 256 sd->sensor->dump(sd);
258 257
259 return (err < 0) ? err : 0; 258 return (err < 0) ? err : 0;
@@ -318,6 +317,8 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
318 __u8 *data, /* isoc packet */ 317 __u8 *data, /* isoc packet */
319 int len) /* iso packet length */ 318 int len) /* iso packet length */
320{ 319{
320 struct sd *sd = (struct sd *) gspca_dev;
321
321 PDEBUG(D_PACK, "Packet of length %d arrived", len); 322 PDEBUG(D_PACK, "Packet of length %d arrived", len);
322 323
323 /* A packet may contain several frames 324 /* A packet may contain several frames
@@ -343,14 +344,29 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
343 if (len < chunk_len) { 344 if (len < chunk_len) {
344 PDEBUG(D_ERR, "URB packet length is smaller" 345 PDEBUG(D_ERR, "URB packet length is smaller"
345 " than the specified chunk length"); 346 " than the specified chunk length");
347 gspca_dev->last_packet_type = DISCARD_PACKET;
346 return; 348 return;
347 } 349 }
348 350
351 /* First byte seem to be 02=data 2nd byte is unknown??? */
352 if (sd->bridge == BRIDGE_ST6422 && (id & 0xFF00) == 0x0200)
353 goto frame_data;
354
349 switch (id) { 355 switch (id) {
350 case 0x0200: 356 case 0x0200:
351 case 0x4200: 357 case 0x4200:
358frame_data:
352 PDEBUG(D_PACK, "Frame data packet detected"); 359 PDEBUG(D_PACK, "Frame data packet detected");
353 360
361 if (sd->to_skip) {
362 int skip = (sd->to_skip < chunk_len) ?
363 sd->to_skip : chunk_len;
364 data += skip;
365 len -= skip;
366 chunk_len -= skip;
367 sd->to_skip -= skip;
368 }
369
354 gspca_frame_add(gspca_dev, INTER_PACKET, frame, 370 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
355 data, chunk_len); 371 data, chunk_len);
356 break; 372 break;
@@ -365,6 +381,9 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
365 gspca_frame_add(gspca_dev, FIRST_PACKET, 381 gspca_frame_add(gspca_dev, FIRST_PACKET,
366 frame, data, 0); 382 frame, data, 0);
367 383
384 if (sd->bridge == BRIDGE_ST6422)
385 sd->to_skip = gspca_dev->width * 4;
386
368 if (chunk_len) 387 if (chunk_len)
369 PDEBUG(D_ERR, "Chunk length is " 388 PDEBUG(D_ERR, "Chunk length is "
370 "non-zero on a SOF"); 389 "non-zero on a SOF");
@@ -395,8 +414,12 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
395 /* Unknown chunk with 2 bytes of data, 414 /* Unknown chunk with 2 bytes of data,
396 occurs 2-3 times per USB interrupt */ 415 occurs 2-3 times per USB interrupt */
397 break; 416 break;
417 case 0x42ff:
418 PDEBUG(D_PACK, "Chunk 0x42ff detected");
419 /* Special chunk seen sometimes on the ST6422 */
420 break;
398 default: 421 default:
399 PDEBUG(D_PACK, "Unknown chunk %d detected", id); 422 PDEBUG(D_PACK, "Unknown chunk 0x%04x detected", id);
400 /* Unknown chunk */ 423 /* Unknown chunk */
401 } 424 }
402 data += chunk_len; 425 data += chunk_len;
@@ -428,11 +451,16 @@ static int stv06xx_config(struct gspca_dev *gspca_dev,
428 451
429 cam = &gspca_dev->cam; 452 cam = &gspca_dev->cam;
430 sd->desc = sd_desc; 453 sd->desc = sd_desc;
454 sd->bridge = id->driver_info;
431 gspca_dev->sd_desc = &sd->desc; 455 gspca_dev->sd_desc = &sd->desc;
432 456
433 if (dump_bridge) 457 if (dump_bridge)
434 stv06xx_dump_bridge(sd); 458 stv06xx_dump_bridge(sd);
435 459
460 sd->sensor = &stv06xx_sensor_st6422;
461 if (!sd->sensor->probe(sd))
462 return 0;
463
436 sd->sensor = &stv06xx_sensor_vv6410; 464 sd->sensor = &stv06xx_sensor_vv6410;
437 if (!sd->sensor->probe(sd)) 465 if (!sd->sensor->probe(sd))
438 return 0; 466 return 0;
@@ -457,9 +485,20 @@ static int stv06xx_config(struct gspca_dev *gspca_dev,
457 485
458/* -- module initialisation -- */ 486/* -- module initialisation -- */
459static const __devinitdata struct usb_device_id device_table[] = { 487static const __devinitdata struct usb_device_id device_table[] = {
460 {USB_DEVICE(0x046d, 0x0840)}, /* QuickCam Express */ 488 /* QuickCam Express */
461 {USB_DEVICE(0x046d, 0x0850)}, /* LEGO cam / QuickCam Web */ 489 {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 },
462 {USB_DEVICE(0x046d, 0x0870)}, /* Dexxa WebCam USB */ 490 /* LEGO cam / QuickCam Web */
491 {USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 },
492 /* Dexxa WebCam USB */
493 {USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 },
494 /* QuickCam Messenger */
495 {USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 },
496 /* QuickCam Communicate */
497 {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },
498 /* QuickCam Messenger (new) */
499 {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },
500 /* QuickCam Messenger (new) */
501 {USB_DEVICE(0x046D, 0x08DA), .driver_info = BRIDGE_ST6422 },
463 {} 502 {}
464}; 503};
465MODULE_DEVICE_TABLE(usb, device_table); 504MODULE_DEVICE_TABLE(usb, device_table);