diff options
author | Hans de Goede <hdegoede@redhat.com> | 2009-06-17 17:37:57 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-23 02:13:11 -0400 |
commit | 8668d504d72c384fbfb6ab6f5d02a9fe4d813554 (patch) | |
tree | 4ba923b0a7ccda8121960231e758135ba9bd584a /drivers/media/video/gspca/stv06xx/stv06xx.c | |
parent | ae49c40461d8981b232e3fec28234d492067f0e1 (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.c | 53 |
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: |
358 | frame_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 -- */ |
459 | static const __devinitdata struct usb_device_id device_table[] = { | 487 | static 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 | }; |
465 | MODULE_DEVICE_TABLE(usb, device_table); | 504 | MODULE_DEVICE_TABLE(usb, device_table); |