aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-09-03 15:47:21 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-09-03 17:36:26 -0400
commite52a5574de9d3bb297a26566871eabcbdfab13b5 (patch)
treea31652a542132c5ae772bb9932ab4d1ea17de8c1 /drivers/media/video
parentd526afe06b285006c63ed8f2eba9589f04e3283a (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.c206
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
336static void sd_start(struct gspca_dev *gspca_dev) 337static 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 */
520static 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 */
514static void sd_pkt_scan(struct gspca_dev *gspca_dev, 540static 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
624static void getbrightness(struct gspca_dev *gspca_dev) 638static void getbrightness(struct gspca_dev *gspca_dev)