diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-09-03 15:47:21 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-09-03 17:36:26 -0400 |
commit | e52a5574de9d3bb297a26566871eabcbdfab13b5 (patch) | |
tree | a31652a542132c5ae772bb9932ab4d1ea17de8c1 /drivers/media/video | |
parent | d526afe06b285006c63ed8f2eba9589f04e3283a (diff) |
V4L/DVB (8660): gspca: Simplify the scan of URB packets in pac7311.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/gspca/pac7311.c | 206 |
1 files changed, 110 insertions, 96 deletions
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 815bea6edc44..caa33292a08a 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c | |||
@@ -40,7 +40,8 @@ struct sd { | |||
40 | unsigned char colors; | 40 | unsigned char colors; |
41 | unsigned char autogain; | 41 | unsigned char autogain; |
42 | 42 | ||
43 | char ffseq; | 43 | char ffnb; /* number of 'ff' in the previous frame */ |
44 | char tosof; /* number of bytes before next start of frame */ | ||
44 | signed char ag_cnt; | 45 | signed char ag_cnt; |
45 | #define AG_CNT_START 13 | 46 | #define AG_CNT_START 13 |
46 | }; | 47 | }; |
@@ -335,6 +336,10 @@ static int sd_open(struct gspca_dev *gspca_dev) | |||
335 | 336 | ||
336 | static void sd_start(struct gspca_dev *gspca_dev) | 337 | static void sd_start(struct gspca_dev *gspca_dev) |
337 | { | 338 | { |
339 | struct sd *sd = (struct sd *) gspca_dev; | ||
340 | |||
341 | sd->ffnb = 0; | ||
342 | sd->tosof = 0; | ||
338 | reg_w(gspca_dev, 0xff, 0x01); | 343 | reg_w(gspca_dev, 0xff, 0x01); |
339 | reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8); | 344 | reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8); |
340 | reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8); | 345 | reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8); |
@@ -511,114 +516,123 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
511 | } | 516 | } |
512 | } | 517 | } |
513 | 518 | ||
519 | /* output the jpeg header */ | ||
520 | static void put_jpeg_head(struct gspca_dev *gspca_dev, | ||
521 | struct gspca_frame *frame) | ||
522 | { | ||
523 | unsigned char tmpbuf[4]; | ||
524 | |||
525 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | ||
526 | (__u8 *) pac7311_jpeg_header, | ||
527 | 12); | ||
528 | tmpbuf[0] = gspca_dev->height >> 8; | ||
529 | tmpbuf[1] = gspca_dev->height & 0xff; | ||
530 | tmpbuf[2] = gspca_dev->width >> 8; | ||
531 | tmpbuf[3] = gspca_dev->width & 0xff; | ||
532 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
533 | tmpbuf, 4); | ||
534 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
535 | (__u8 *) &pac7311_jpeg_header[16], | ||
536 | PAC7311_JPEG_HEADER_SIZE - 16); | ||
537 | } | ||
538 | |||
539 | /* this function is run at interrupt level */ | ||
514 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 540 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
515 | struct gspca_frame *frame, /* target */ | 541 | struct gspca_frame *frame, /* target */ |
516 | __u8 *data, /* isoc packet */ | 542 | __u8 *data, /* isoc packet */ |
517 | int len) /* iso packet length */ | 543 | int len) /* iso packet length */ |
518 | { | 544 | { |
519 | struct sd *sd = (struct sd *) gspca_dev; | 545 | struct sd *sd = (struct sd *) gspca_dev; |
520 | unsigned char tmpbuf[4]; | 546 | int i; |
521 | int i, p, ffseq; | 547 | |
522 | 548 | #define INTER_FRAME 0x53 | |
523 | /* if (len < 5) { */ | 549 | #define LUM_OFFSET 0x1e /* reverse offset / start of frame */ |
524 | if (len < 6) { | 550 | |
525 | /* gspca_dev->last_packet_type = DISCARD_PACKET; */ | 551 | /* |
526 | return; | 552 | * inside a frame, there may be: |
527 | } | 553 | * escaped ff ('ff 00') |
528 | 554 | * sequences'ff ff ff xx' to remove | |
529 | ffseq = sd->ffseq; | 555 | * end of frame ('ff d9') |
530 | 556 | * at the end of frame, there are: | |
531 | for (p = 0; p < len - 6; p++) { | 557 | * ff d9 end of frame |
532 | if ((data[0 + p] == 0xff) | 558 | * 0x33 bytes |
533 | && (data[1 + p] == 0xff) | 559 | * one byte luminosity |
534 | && (data[2 + p] == 0x00) | 560 | * 0x16 bytes |
535 | && (data[3 + p] == 0xff) | 561 | * ff ff 00 ff 96 62 44 start of frame header |
536 | && (data[4 + p] == 0x96)) { | 562 | */ |
537 | 563 | ||
538 | /* start of frame */ | 564 | if (sd->tosof == 0) { /* if inside a frame */ |
539 | if (sd->ag_cnt >= 0 && p > 28) { | 565 | |
540 | sd->lum_sum += data[p - 23]; | 566 | /* check for 'ff ff ff xx' at start and at end of packet */ |
541 | if (--sd->ag_cnt < 0) { | 567 | /* (len is always >= 3) */ |
542 | sd->ag_cnt = AG_CNT_START; | 568 | switch (sd->ffnb) { |
543 | atomic_set(&sd->avg_lum, | 569 | case 1: |
544 | sd->lum_sum / AG_CNT_START); | 570 | if (data[0] != 0xff) |
545 | sd->lum_sum = 0; | 571 | break; /* keep 'ff 00' */ |
546 | atomic_set(&sd->do_gain, 1); | 572 | /* fall thru */ |
573 | case 2: | ||
574 | case 3: | ||
575 | data += 4 - sd->ffnb; | ||
576 | len -= 4 - sd->ffnb; | ||
577 | sd->ffnb = 0; | ||
578 | break; | ||
579 | } | ||
580 | if (data[len - 1] == 0xff) { | ||
581 | if (data[len - 2] == 0xff) { | ||
582 | if (data[len - 3] == 0xff) { | ||
583 | sd->ffnb = 3; | ||
584 | len -= 3; | ||
585 | } else { | ||
586 | sd->ffnb = 2; | ||
587 | len -= 2; | ||
547 | } | 588 | } |
589 | } else { | ||
590 | sd->ffnb = 1; | ||
591 | len--; | ||
548 | } | 592 | } |
549 | |||
550 | /* copy the end of data to the current frame */ | ||
551 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | ||
552 | data, p); | ||
553 | |||
554 | /* put the JPEG header in the new frame */ | ||
555 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | ||
556 | (unsigned char *) pac7311_jpeg_header, | ||
557 | 12); | ||
558 | tmpbuf[0] = gspca_dev->height >> 8; | ||
559 | tmpbuf[1] = gspca_dev->height & 0xff; | ||
560 | tmpbuf[2] = gspca_dev->width >> 8; | ||
561 | tmpbuf[3] = gspca_dev->width & 0xff; | ||
562 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
563 | tmpbuf, 4); | ||
564 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
565 | (unsigned char *) &pac7311_jpeg_header[16], | ||
566 | PAC7311_JPEG_HEADER_SIZE - 16); | ||
567 | |||
568 | data += p + 7; | ||
569 | len -= p + 7; | ||
570 | ffseq = 0; | ||
571 | break; | ||
572 | } | 593 | } |
594 | } else { /* outside a frame */ | ||
595 | |||
596 | /* | ||
597 | * get the luminosity | ||
598 | * and go to the start of frame | ||
599 | */ | ||
600 | data += sd->tosof; | ||
601 | len -= sd->tosof; | ||
602 | if (sd->tosof > LUM_OFFSET) | ||
603 | sd->lum_sum += data[-LUM_OFFSET]; | ||
604 | put_jpeg_head(gspca_dev, frame); | ||
605 | sd->tosof = 0; | ||
573 | } | 606 | } |
574 | 607 | ||
575 | /* remove the 'ff ff ff xx' sequences */ | 608 | for (i = 0; i < len; i++) { |
576 | switch (ffseq) { | 609 | if (data[i] != 0xff) |
577 | case 3: | 610 | continue; |
578 | data += 1; | 611 | switch (data[i + 1]) { |
579 | len -= 1; | 612 | case 0xd9: /* end of frame */ |
580 | break; | 613 | frame = gspca_frame_add(gspca_dev, |
581 | case 2: | 614 | LAST_PACKET, |
582 | if (data[0] == 0xff) { | 615 | frame, data, i + 1); |
583 | data += 2; | 616 | data += INTER_FRAME; |
584 | len -= 2; | 617 | len -= INTER_FRAME; |
585 | frame->data_end -= 2; | 618 | i = 0; |
586 | } | 619 | if (len > LUM_OFFSET) |
587 | break; | 620 | sd->lum_sum += data[-LUM_OFFSET]; |
588 | case 1: | 621 | if (len < 0) { |
589 | if (data[0] == 0xff | 622 | sd->tosof = -len; |
590 | && data[1] == 0xff) { | 623 | break; |
591 | data += 3; | 624 | } |
592 | len -= 3; | 625 | put_jpeg_head(gspca_dev, frame); |
593 | frame->data_end -= 1; | 626 | break; |
594 | } | 627 | case 0xff: /* 'ff ff ff xx' */ |
595 | break; | 628 | gspca_frame_add(gspca_dev, INTER_PACKET, |
596 | } | 629 | frame, data, i); |
597 | for (i = 0; i < len - 4; i++) { | 630 | data += i + 4; |
598 | if (data[i] == 0xff | 631 | len -= i + 4; |
599 | && data[i + 1] == 0xff | 632 | i = 0; |
600 | && data[i + 2] == 0xff) { | 633 | break; |
601 | memmove(&data[i], &data[i + 4], len - i - 4); | ||
602 | len -= 4; | ||
603 | } | 634 | } |
604 | } | 635 | } |
605 | ffseq = 0; | ||
606 | if (data[len - 4] == 0xff) { | ||
607 | if (data[len - 3] == 0xff | ||
608 | && data[len - 2] == 0xff) { | ||
609 | len -= 4; | ||
610 | } | ||
611 | } else if (data[len - 3] == 0xff) { | ||
612 | if (data[len - 2] == 0xff | ||
613 | && data[len - 1] == 0xff) | ||
614 | ffseq = 3; | ||
615 | } else if (data[len - 2] == 0xff) { | ||
616 | if (data[len - 1] == 0xff) | ||
617 | ffseq = 2; | ||
618 | } else if (data[len - 1] == 0xff) | ||
619 | ffseq = 1; | ||
620 | sd->ffseq = ffseq; | ||
621 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | ||
622 | } | 636 | } |
623 | 637 | ||
624 | static void getbrightness(struct gspca_dev *gspca_dev) | 638 | static void getbrightness(struct gspca_dev *gspca_dev) |