diff options
-rw-r--r-- | drivers/media/video/gspca/ov534.c | 115 |
1 files changed, 57 insertions, 58 deletions
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index ea2245626d53..647c448f492f 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c | |||
@@ -46,9 +46,9 @@ MODULE_LICENSE("GPL"); | |||
46 | /* specific webcam descriptor */ | 46 | /* specific webcam descriptor */ |
47 | struct sd { | 47 | struct sd { |
48 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 48 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
49 | __u32 last_fid; | ||
50 | __u32 last_pts; | 49 | __u32 last_pts; |
51 | int frame_rate; | 50 | u16 last_fid; |
51 | u8 frame_rate; | ||
52 | }; | 52 | }; |
53 | 53 | ||
54 | /* V4L2 controls supported by the driver */ | 54 | /* V4L2 controls supported by the driver */ |
@@ -428,76 +428,75 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, | |||
428 | { | 428 | { |
429 | struct sd *sd = (struct sd *) gspca_dev; | 429 | struct sd *sd = (struct sd *) gspca_dev; |
430 | __u32 this_pts; | 430 | __u32 this_pts; |
431 | int this_fid; | 431 | u16 this_fid; |
432 | int remaining_len = len; | 432 | int remaining_len = len; |
433 | __u8 *next_data = data; | ||
434 | 433 | ||
435 | scan_next: | 434 | do { |
436 | if (remaining_len <= 0) | 435 | len = min(remaining_len, 2040); /*fixme: was 2048*/ |
437 | return; | ||
438 | |||
439 | data = next_data; | ||
440 | len = min(remaining_len, 2048); | ||
441 | remaining_len -= len; | ||
442 | next_data += len; | ||
443 | |||
444 | /* Payloads are prefixed with a UVC-style header. We | ||
445 | consider a frame to start when the FID toggles, or the PTS | ||
446 | changes. A frame ends when EOF is set, and we've received | ||
447 | the correct number of bytes. */ | ||
448 | |||
449 | /* Verify UVC header. Header length is always 12 */ | ||
450 | if (data[0] != 12 || len < 12) { | ||
451 | PDEBUG(D_PACK, "bad header"); | ||
452 | goto discard; | ||
453 | } | ||
454 | 436 | ||
455 | /* Check errors */ | 437 | /* Payloads are prefixed with a UVC-style header. We |
456 | if (data[1] & UVC_STREAM_ERR) { | 438 | consider a frame to start when the FID toggles, or the PTS |
457 | PDEBUG(D_PACK, "payload error"); | 439 | changes. A frame ends when EOF is set, and we've received |
458 | goto discard; | 440 | the correct number of bytes. */ |
459 | } | ||
460 | 441 | ||
461 | /* Extract PTS and FID */ | 442 | /* Verify UVC header. Header length is always 12 */ |
462 | if (!(data[1] & UVC_STREAM_PTS)) { | 443 | if (data[0] != 12 || len < 12) { |
463 | PDEBUG(D_PACK, "PTS not present"); | 444 | PDEBUG(D_PACK, "bad header"); |
464 | goto discard; | 445 | goto discard; |
465 | } | 446 | } |
466 | this_pts = (data[5] << 24) | (data[4] << 16) | (data[3] << 8) | data[2]; | ||
467 | this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0; | ||
468 | |||
469 | /* If PTS or FID has changed, start a new frame. */ | ||
470 | if (this_pts != sd->last_pts || this_fid != sd->last_fid) { | ||
471 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); | ||
472 | sd->last_pts = this_pts; | ||
473 | sd->last_fid = this_fid; | ||
474 | } | ||
475 | |||
476 | /* Add the data from this payload */ | ||
477 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
478 | data + 12, len - 12); | ||
479 | 447 | ||
480 | /* If this packet is marked as EOF, end the frame */ | 448 | /* Check errors */ |
481 | if (data[1] & UVC_STREAM_EOF) { | 449 | if (data[1] & UVC_STREAM_ERR) { |
482 | sd->last_pts = 0; | 450 | PDEBUG(D_PACK, "payload error"); |
451 | goto discard; | ||
452 | } | ||
483 | 453 | ||
484 | if ((frame->data_end - frame->data) != | 454 | /* Extract PTS and FID */ |
485 | (gspca_dev->width * gspca_dev->height * 2)) { | 455 | if (!(data[1] & UVC_STREAM_PTS)) { |
486 | PDEBUG(D_PACK, "short frame"); | 456 | PDEBUG(D_PACK, "PTS not present"); |
487 | goto discard; | 457 | goto discard; |
488 | } | 458 | } |
459 | this_pts = (data[5] << 24) | (data[4] << 16) | ||
460 | | (data[3] << 8) | data[2]; | ||
461 | this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0; | ||
489 | 462 | ||
490 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 463 | /* If PTS or FID has changed, start a new frame. */ |
464 | if (this_pts != sd->last_pts || this_fid != sd->last_fid) { | ||
465 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | ||
491 | NULL, 0); | 466 | NULL, 0); |
467 | sd->last_pts = this_pts; | ||
468 | sd->last_fid = this_fid; | ||
469 | } | ||
470 | |||
471 | /* Add the data from this payload */ | ||
472 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
473 | data + 12, len - 12); | ||
474 | |||
475 | /* If this packet is marked as EOF, end the frame */ | ||
476 | if (data[1] & UVC_STREAM_EOF) { | ||
477 | sd->last_pts = 0; | ||
478 | |||
479 | if (frame->data_end - frame->data != | ||
480 | gspca_dev->width * gspca_dev->height * 2) { | ||
481 | PDEBUG(D_PACK, "short frame"); | ||
482 | goto discard; | ||
483 | } | ||
484 | |||
485 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | ||
486 | NULL, 0); | ||
492 | } | 487 | } |
493 | 488 | ||
494 | /* Done this payload */ | 489 | /* Done this payload */ |
495 | goto scan_next; | 490 | goto scan_next; |
496 | 491 | ||
497 | discard: | 492 | discard: |
498 | /* Discard data until a new frame starts. */ | 493 | /* Discard data until a new frame starts. */ |
499 | gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0); | 494 | gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0); |
500 | goto scan_next; | 495 | |
496 | scan_next: | ||
497 | remaining_len -= len; | ||
498 | data += len; | ||
499 | } while (remaining_len > 0); | ||
501 | } | 500 | } |
502 | 501 | ||
503 | /* get stream parameters (framerate) */ | 502 | /* get stream parameters (framerate) */ |