From 04874827dbbfe036d172dd2256a7ec88ddf9d1a7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 5 Aug 2008 10:01:44 +0200 Subject: gspca: Simplify the scan of URB packets in pac7311. From: Jean-Francois Moine Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/pac7311.c | 206 ++++++++++++++++-------------- 1 file changed, 110 insertions(+), 96 deletions(-) (limited to 'linux/drivers/media/video/gspca/pac7311.c') diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index 1b3ea1e93..0fecf4ea7 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -40,7 +40,8 @@ struct sd { unsigned char colors; unsigned char autogain; - char ffseq; + char ffnb; /* number of 'ff' in the previous frame */ + char tosof; /* number of bytes before next start of frame */ signed char ag_cnt; #define AG_CNT_START 13 }; @@ -335,6 +336,10 @@ static int sd_open(struct gspca_dev *gspca_dev) static void sd_start(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + sd->ffnb = 0; + sd->tosof = 0; reg_w(gspca_dev, 0xff, 0x01); reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8); 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) } } +/* output the jpeg header */ +static void put_jpeg_head(struct gspca_dev *gspca_dev, + struct gspca_frame *frame) +{ + unsigned char tmpbuf[4]; + + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + (__u8 *) pac7311_jpeg_header, + 12); + tmpbuf[0] = gspca_dev->height >> 8; + tmpbuf[1] = gspca_dev->height & 0xff; + tmpbuf[2] = gspca_dev->width >> 8; + tmpbuf[3] = gspca_dev->width & 0xff; + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + tmpbuf, 4); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + (__u8 *) &pac7311_jpeg_header[16], + PAC7311_JPEG_HEADER_SIZE - 16); +} + +/* this function is run at interrupt level */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; - unsigned char tmpbuf[4]; - int i, p, ffseq; - -/* if (len < 5) { */ - if (len < 6) { -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ - return; - } - - ffseq = sd->ffseq; - - for (p = 0; p < len - 6; p++) { - if ((data[0 + p] == 0xff) - && (data[1 + p] == 0xff) - && (data[2 + p] == 0x00) - && (data[3 + p] == 0xff) - && (data[4 + p] == 0x96)) { - - /* start of frame */ - if (sd->ag_cnt >= 0 && p > 28) { - sd->lum_sum += data[p - 23]; - if (--sd->ag_cnt < 0) { - sd->ag_cnt = AG_CNT_START; - atomic_set(&sd->avg_lum, - sd->lum_sum / AG_CNT_START); - sd->lum_sum = 0; - atomic_set(&sd->do_gain, 1); + int i; + +#define INTER_FRAME 0x53 +#define LUM_OFFSET 0x1e /* reverse offset / start of frame */ + + /* + * inside a frame, there may be: + * escaped ff ('ff 00') + * sequences'ff ff ff xx' to remove + * end of frame ('ff d9') + * at the end of frame, there are: + * ff d9 end of frame + * 0x33 bytes + * one byte luminosity + * 0x16 bytes + * ff ff 00 ff 96 62 44 start of frame header + */ + + if (sd->tosof == 0) { /* if inside a frame */ + + /* check for 'ff ff ff xx' at start and at end of packet */ + /* (len is always >= 3) */ + switch (sd->ffnb) { + case 1: + if (data[0] != 0xff) + break; /* keep 'ff 00' */ + /* fall thru */ + case 2: + case 3: + data += 4 - sd->ffnb; + len -= 4 - sd->ffnb; + sd->ffnb = 0; + break; + } + if (data[len - 1] == 0xff) { + if (data[len - 2] == 0xff) { + if (data[len - 3] == 0xff) { + sd->ffnb = 3; + len -= 3; + } else { + sd->ffnb = 2; + len -= 2; } + } else { + sd->ffnb = 1; + len--; } - - /* copy the end of data to the current frame */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, p); - - /* put the JPEG header in the new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - (unsigned char *) pac7311_jpeg_header, - 12); - tmpbuf[0] = gspca_dev->height >> 8; - tmpbuf[1] = gspca_dev->height & 0xff; - tmpbuf[2] = gspca_dev->width >> 8; - tmpbuf[3] = gspca_dev->width & 0xff; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - tmpbuf, 4); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - (unsigned char *) &pac7311_jpeg_header[16], - PAC7311_JPEG_HEADER_SIZE - 16); - - data += p + 7; - len -= p + 7; - ffseq = 0; - break; } + } else { /* outside a frame */ + + /* + * get the luminosity + * and go to the start of frame + */ + data += sd->tosof; + len -= sd->tosof; + if (sd->tosof > LUM_OFFSET) + sd->lum_sum += data[-LUM_OFFSET]; + put_jpeg_head(gspca_dev, frame); + sd->tosof = 0; } - /* remove the 'ff ff ff xx' sequences */ - switch (ffseq) { - case 3: - data += 1; - len -= 1; - break; - case 2: - if (data[0] == 0xff) { - data += 2; - len -= 2; - frame->data_end -= 2; - } - break; - case 1: - if (data[0] == 0xff - && data[1] == 0xff) { - data += 3; - len -= 3; - frame->data_end -= 1; - } - break; - } - for (i = 0; i < len - 4; i++) { - if (data[i] == 0xff - && data[i + 1] == 0xff - && data[i + 2] == 0xff) { - memmove(&data[i], &data[i + 4], len - i - 4); - len -= 4; + for (i = 0; i < len; i++) { + if (data[i] != 0xff) + continue; + switch (data[i + 1]) { + case 0xd9: /* end of frame */ + frame = gspca_frame_add(gspca_dev, + LAST_PACKET, + frame, data, i + 1); + data += INTER_FRAME; + len -= INTER_FRAME; + i = 0; + if (len > LUM_OFFSET) + sd->lum_sum += data[-LUM_OFFSET]; + if (len < 0) { + sd->tosof = -len; + break; + } + put_jpeg_head(gspca_dev, frame); + break; + case 0xff: /* 'ff ff ff xx' */ + gspca_frame_add(gspca_dev, INTER_PACKET, + frame, data, i); + data += i + 4; + len -= i + 4; + i = 0; + break; } } - ffseq = 0; - if (data[len - 4] == 0xff) { - if (data[len - 3] == 0xff - && data[len - 2] == 0xff) { - len -= 4; - } - } else if (data[len - 3] == 0xff) { - if (data[len - 2] == 0xff - && data[len - 1] == 0xff) - ffseq = 3; - } else if (data[len - 2] == 0xff) { - if (data[len - 1] == 0xff) - ffseq = 2; - } else if (data[len - 1] == 0xff) - ffseq = 1; - sd->ffseq = ffseq; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } static void getbrightness(struct gspca_dev *gspca_dev) -- cgit v1.2.3 From 2ff4bb725cf7b17813461842cd8b4d20e3fff28a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 5 Aug 2008 11:16:19 +0200 Subject: gspca: Bug in the previous changeset about pac7311. From: Jean-Francois Moine Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/pac7311.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux/drivers/media/video/gspca/pac7311.c') diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index 0fecf4ea7..1648c948e 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -610,13 +610,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, continue; switch (data[i + 1]) { case 0xd9: /* end of frame */ + i += 2; frame = gspca_frame_add(gspca_dev, LAST_PACKET, - frame, data, i + 1); - data += INTER_FRAME; - len -= INTER_FRAME; + frame, data, i); + data += i + INTER_FRAME; + len -= i + INTER_FRAME; i = 0; - if (len > LUM_OFFSET) + if (len > -LUM_OFFSET) sd->lum_sum += data[-LUM_OFFSET]; if (len < 0) { sd->tosof = -len; -- cgit v1.2.3 From 68ba76cddf919051dfaf92ad1b0d130a6dfe0b32 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 6 Aug 2008 09:11:18 +0200 Subject: gspca: The bridge/sensor of the webcam 093a:2621 is a PAC 7302. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/pac7311.c | 431 ++++++++++++++++++++---------- 1 file changed, 294 insertions(+), 137 deletions(-) (limited to 'linux/drivers/media/video/gspca/pac7311.c') diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index 1648c948e..034c00d6c 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -44,6 +44,10 @@ struct sd { char tosof; /* number of bytes before next start of frame */ signed char ag_cnt; #define AG_CNT_START 13 + + __u8 sensor; +#define SENSOR_PAC7302 0 +#define SENSOR_PAC7311 1 }; /* V4L2 controls supported by the driver */ @@ -206,9 +210,158 @@ static const __u8 pac7311_jpeg_header[] = { 0x11, 0x00, 0x3f, 0x00 }; +/* pac 7302 */ +static const __u8 probe_7302[] = { +/* index,value */ + 0xff, 0x01, /* page 1 */ + 0x78, 0x00, /* deactivate */ + 0xff, 0x01, + 0x78, 0x40, /* led off */ +}; +static const __u8 start_7302[] = { +/* index, len, [value]* */ + 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, + 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7, + 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11, + 0x26, 2, 0xaa, 0xaa, + 0x2e, 1, 0x31, + 0x38, 1, 0x01, + 0x3a, 3, 0x14, 0xff, 0x5a, + 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, + 0x00, 0x54, 0x11, + 0x55, 1, 0x00, + 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, + 0x6b, 1, 0x00, + 0x6e, 3, 0x08, 0x06, 0x00, + 0x72, 3, 0x00, 0xff, 0x00, + 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c, + 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50, + 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00, + 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9, + 0xd2, 0xeb, + 0xaf, 1, 0x02, + 0xb5, 2, 0x08, 0x08, + 0xb8, 2, 0x08, 0x88, + 0xc4, 4, 0xae, 0x01, 0x04, 0x01, + 0xcc, 1, 0x00, + 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, + 0xc1, 0xd7, 0xec, + 0xdc, 1, 0x01, + 0xff, 1, 0x01, + 0x12, 3, 0x02, 0x00, 0x01, + 0x3e, 2, 0x00, 0x00, + 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, + 0x7c, 1, 0x00, + 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, + 0x02, 0x00, + 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, + 0xc8, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, + 0x01, + 0xdb, 2, 0x00, 0x01, + 0xde, 8, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, + 0xe6, 4, 0x00, 0x00, 0x00, 0x01, + 0xeb, 1, 0x00, + 0xff, 1, 0x02, + 0x22, 1, 0x00, + 0xff, 1, 0x03, + 0x00, 255, /* load the page 3 */ + 0x11, 1, 0x01, + 0xff, 1, 0x02, + 0x13, 1, 0x00, + 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, + 0x27, 2, 0x14, 0x0c, + 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, + 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, + 0x6e, 1, 0x08, + 0xff, 1, 0x03, + 0x78, 1, 0x00, + 0, 0 /* end of sequence */ +}; + +/* page 3 - the value 0xaa says skip the index - see reg_w_page() */ +static const __u8 page3_7302[] = { + 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16, + 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, + 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21, + 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54, + 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8, + 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00, + 0x00 +}; + +/* pac 7311 */ +static const __u8 probe_7311[] = { + 0x78, 0x40, /* Bit_0=start stream, Bit_7=LED */ + 0x78, 0x40, /* Bit_0=start stream, Bit_7=LED */ + 0x78, 0x44, /* Bit_0=start stream, Bit_7=LED */ + 0xff, 0x04, + 0x27, 0x80, + 0x28, 0xca, + 0x29, 0x53, + 0x2a, 0x0e, + 0xff, 0x01, + 0x3e, 0x20, +}; + +static const __u8 start_7311[] = { +/* index, len, [value]* */ + 0xff, 1, 0x01, + 0x02, 53, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00, + 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c, + 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x3e, 52, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e, + 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49, + 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48, + 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78, + 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b, + 0xd0, 0xff, + 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80, + 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84, + 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14, + 0x18, 0x20, + 0x96, 3, 0x01, 0x08, 0x04, + 0xa0, 4, 0x44, 0x44, 0x44, 0x04, + 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00, + 0x3f, 0x00, 0x0a, 0x01, 0x00, + 0xff, 1, 0x04, + 0x00, 254, /* load the page 4 */ + 0x11, 1, 0x01, + 0, 0 /* end of sequence */ +}; + +/* page 4 - the value 0xaa says skip the index - see reg_w_page() */ +static const __u8 page4_7311[] = { + 0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f, + 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62, + 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa, + 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x01, + 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 +}; + static void reg_w_buf(struct gspca_dev *gspca_dev, - __u16 index, - const char *buffer, __u16 len) + __u8 index, + const char *buffer, int len) { memcpy(gspca_dev->usb_buf, buffer, len); usb_control_msg(gspca_dev->dev, @@ -221,7 +374,7 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, } static __u8 reg_r(struct gspca_dev *gspca_dev, - __u16 index) + __u8 index) { usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), @@ -234,7 +387,7 @@ static __u8 reg_r(struct gspca_dev *gspca_dev, } static void reg_w(struct gspca_dev *gspca_dev, - __u16 index, + __u8 index, __u8 value) { gspca_dev->usb_buf[0] = value; @@ -246,6 +399,74 @@ static void reg_w(struct gspca_dev *gspca_dev, 500); } +static void reg_w_seq(struct gspca_dev *gspca_dev, + const __u8 *seq, int len) +{ + while (--len >= 0) { + reg_w(gspca_dev, seq[0], seq[1]); + seq += 2; + } +} + +/* load the beginning of a page */ +static void reg_w_page(struct gspca_dev *gspca_dev, + const __u8 *page, int len) +{ + int index; + + for (index = 0; index < len; index++) { + if (page[index] == 0xaa) /* skip this index */ + continue; + gspca_dev->usb_buf[0] = page[index]; + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, index, gspca_dev->usb_buf, 1, + 500); + } +} + +/* output a variable sequence */ +static void reg_w_var(struct gspca_dev *gspca_dev, + const __u8 *seq) +{ + int index, len; + + for (;;) { + index = *seq++; + len = *seq++; + switch (len) { + case 0: + return; + case 254: + reg_w_page(gspca_dev, page4_7311, sizeof page4_7311); + break; + case 255: + reg_w_page(gspca_dev, page3_7302, sizeof page3_7302); + break; + default: + if (len > 32) { + PDEBUG(D_ERR|D_STREAM, + "Incorrect variable sequence"); + return; + } + while (len > 0) { + if (len < 8) { + reg_w_buf(gspca_dev, index, seq, len); + seq += len; + break; + } + reg_w_buf(gspca_dev, index, seq, 8); + seq += 8; + index += 8; + len -= 8; + } + } + } + /* not reached */ +} + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -253,22 +474,23 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; - PDEBUG(D_CONF, "Find Sensor PAC7311"); - reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x27, 0x80); - reg_w(gspca_dev, 0x28, 0xca); - reg_w(gspca_dev, 0x29, 0x53); - reg_w(gspca_dev, 0x2a, 0x0e); - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x3e, 0x20); - cam = &gspca_dev->cam; cam->epaddr = 0x05; - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); + + sd->sensor = id->driver_info; + if (sd->sensor == SENSOR_PAC7302) { + PDEBUG(D_CONF, "Find Sensor PAC7302"); + reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302); + + cam->cam_mode = &vga_mode[2]; /* only 640x480 */ + cam->nmodes = 1; + } else { + PDEBUG(D_CONF, "Find Sensor PAC7311"); + reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302); + + cam->cam_mode = vga_mode; + cam->nmodes = ARRAY_SIZE(vga_mode); + } sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; @@ -283,10 +505,11 @@ static void setbrightness(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int brightness; + if (sd->sensor == SENSOR_PAC7302) + return; /*jfm: inverted?*/ brightness = BRIGHTNESS_MAX - sd->brightness; reg_w(gspca_dev, 0xff, 0x04); -/* reg_w(gspca_dev, 0x0e, 0x00); */ reg_w(gspca_dev, 0x0f, brightness); /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); @@ -297,6 +520,8 @@ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (sd->sensor == SENSOR_PAC7302) + return; reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x80, sd->contrast); /* load registers to sensor (Bit 0, auto clear) */ @@ -308,6 +533,8 @@ static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (sd->sensor == SENSOR_PAC7302) + return; reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x10, sd->colors); /* load registers to sensor (Bit 0, auto clear) */ @@ -340,75 +567,12 @@ static void sd_start(struct gspca_dev *gspca_dev) sd->ffnb = 0; sd->tosof = 0; - reg_w(gspca_dev, 0xff, 0x01); - reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8); - reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8); - reg_w_buf(gspca_dev, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8); - reg_w_buf(gspca_dev, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8); - reg_w_buf(gspca_dev, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8); - reg_w_buf(gspca_dev, 0x002a, "\x00\x00\x00", 3); - reg_w_buf(gspca_dev, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8); - reg_w_buf(gspca_dev, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8); - reg_w_buf(gspca_dev, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8); - reg_w_buf(gspca_dev, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8); - reg_w_buf(gspca_dev, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8); - reg_w_buf(gspca_dev, 0x0066, "\xd0\xff", 2); - reg_w_buf(gspca_dev, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6); - reg_w_buf(gspca_dev, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8); - reg_w_buf(gspca_dev, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8); - reg_w_buf(gspca_dev, 0x008f, "\x18\x20", 2); - reg_w_buf(gspca_dev, 0x0096, "\x01\x08\x04", 3); - reg_w_buf(gspca_dev, 0x00a0, "\x44\x44\x44\x04", 4); - reg_w_buf(gspca_dev, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8); - reg_w_buf(gspca_dev, 0x00f8, "\x3f\x00\x0a\x01\x00", 5); - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x02, 0x04); - reg_w(gspca_dev, 0x03, 0x54); - reg_w(gspca_dev, 0x04, 0x07); - reg_w(gspca_dev, 0x05, 0x2b); - reg_w(gspca_dev, 0x06, 0x09); - reg_w(gspca_dev, 0x07, 0x0f); - reg_w(gspca_dev, 0x08, 0x09); - reg_w(gspca_dev, 0x09, 0x00); - reg_w(gspca_dev, 0x0c, 0x07); - reg_w(gspca_dev, 0x0d, 0x00); - reg_w(gspca_dev, 0x0e, 0x00); - reg_w(gspca_dev, 0x0f, 0x62); - reg_w(gspca_dev, 0x10, 0x08); - reg_w(gspca_dev, 0x12, 0x07); - reg_w(gspca_dev, 0x13, 0x00); - reg_w(gspca_dev, 0x14, 0x00); - reg_w(gspca_dev, 0x15, 0x00); - reg_w(gspca_dev, 0x16, 0x00); - reg_w(gspca_dev, 0x17, 0x00); - reg_w(gspca_dev, 0x18, 0x00); - reg_w(gspca_dev, 0x19, 0x00); - reg_w(gspca_dev, 0x1a, 0x00); - reg_w(gspca_dev, 0x1b, 0x03); - reg_w(gspca_dev, 0x1c, 0xa0); - reg_w(gspca_dev, 0x1d, 0x01); - reg_w(gspca_dev, 0x1e, 0xf4); - reg_w(gspca_dev, 0x21, 0x00); - reg_w(gspca_dev, 0x22, 0x08); - reg_w(gspca_dev, 0x24, 0x03); - reg_w(gspca_dev, 0x26, 0x00); - reg_w(gspca_dev, 0x27, 0x01); - reg_w(gspca_dev, 0x28, 0xca); - reg_w(gspca_dev, 0x29, 0x10); - reg_w(gspca_dev, 0x2a, 0x06); - reg_w(gspca_dev, 0x2b, 0x78); - reg_w(gspca_dev, 0x2c, 0x00); - reg_w(gspca_dev, 0x2d, 0x00); - reg_w(gspca_dev, 0x2e, 0x00); - reg_w(gspca_dev, 0x2f, 0x00); - reg_w(gspca_dev, 0x30, 0x23); - reg_w(gspca_dev, 0x31, 0x28); - reg_w(gspca_dev, 0x32, 0x04); - reg_w(gspca_dev, 0x33, 0x11); - reg_w(gspca_dev, 0x34, 0x00); - reg_w(gspca_dev, 0x35, 0x00); - reg_w(gspca_dev, 0x11, 0x01); + if (sd->sensor == SENSOR_PAC7302) + reg_w_var(gspca_dev, start_7302); + else + reg_w_var(gspca_dev, start_7311); + setcontrast(gspca_dev); setbrightness(gspca_dev); setcolors(gspca_dev); @@ -416,7 +580,7 @@ static void sd_start(struct gspca_dev *gspca_dev) /* set correct resolution */ switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { - case 2: /* 160x120 */ + case 2: /* 160x120 pac7311 */ reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0x02, 0x03); reg_w(gspca_dev, 0xff, 0x01); @@ -426,7 +590,7 @@ static void sd_start(struct gspca_dev *gspca_dev) /* reg_w(gspca_dev, 0x80, 0x69); */ reg_w(gspca_dev, 0x87, 0x10); break; - case 1: /* 320x240 */ + case 1: /* 320x240 pac7311 */ reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0x02, 0x03); reg_w(gspca_dev, 0xff, 0x01); @@ -436,6 +600,8 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x87, 0x11); break; case 0: /* 640x480 */ + if (sd->sensor == SENSOR_PAC7302) + break; reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0x02, 0x03); reg_w(gspca_dev, 0xff, 0x01); @@ -448,12 +614,25 @@ static void sd_start(struct gspca_dev *gspca_dev) /* start stream */ reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x04); - reg_w(gspca_dev, 0x78, 0x05); + if (sd->sensor == SENSOR_PAC7302) { + reg_w(gspca_dev, 0x78, 0x01); + reg_w(gspca_dev, 0xff, 0x01); + reg_w(gspca_dev, 0x78, 0x01); + } else { + reg_w(gspca_dev, 0x78, 0x04); + reg_w(gspca_dev, 0x78, 0x05); + } } static void sd_stopN(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->sensor == SENSOR_PAC7302) { + reg_w(gspca_dev, 0x78, 0x00); + reg_w(gspca_dev, 0x78, 0x00); + return; + } reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0x27, 0x80); reg_w(gspca_dev, 0x28, 0xca); @@ -468,21 +647,17 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->sensor == SENSOR_PAC7302) { + reg_w(gspca_dev, 0xff, 0x01); + reg_w(gspca_dev, 0x78, 0x40); + } } /* this function is called at close time */ static void sd_close(struct gspca_dev *gspca_dev) { - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x27, 0x80); - reg_w(gspca_dev, 0x28, 0xca); - reg_w(gspca_dev, 0x29, 0x53); - reg_w(gspca_dev, 0x2a, 0x0e); - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x3e, 0x20); - reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ } static void do_autogain(struct gspca_dev *gspca_dev) @@ -509,10 +684,17 @@ static void do_autogain(struct gspca_dev *gspca_dev) else if (Gbright < 4) Gbright = 4; PDEBUG(D_FRAM, "gbright %d", Gbright); - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x0f, Gbright); - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); + if (sd->sensor == SENSOR_PAC7302) { + reg_w(gspca_dev, 0xff, 0x03); + reg_w(gspca_dev, 0x10, Gbright); + /* load registers to sensor (Bit 0, auto clear) */ + reg_w(gspca_dev, 0x11, 0x01); + } else { + reg_w(gspca_dev, 0xff, 0x04); + reg_w(gspca_dev, 0x0f, Gbright); + /* load registers to sensor (Bit 0, auto clear) */ + reg_w(gspca_dev, 0x11, 0x01); + } } } @@ -636,28 +818,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } } -static void getbrightness(struct gspca_dev *gspca_dev) -{ -/* sd->brightness = reg_r(gspca_dev, 0x08); - return sd->brightness; */ -/* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */ -} - -#if 0 -static void getcontrast(struct gspca_dev *gspca_dev) -{ -/* sd->contrast = reg_r(gspca_dev, 0x0e); - return sd->contrast; */ - PDEBUG(D_CONF, "getcontrast: Not implemented yet"); -} -#endif - -#if 0 -static void getcolors(struct gspca_dev *gspca_dev) -{ -} -#endif - static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -672,7 +832,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getbrightness(gspca_dev); *val = sd->brightness; return 0; } @@ -691,7 +850,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; -/* getcontrast(gspca_dev); */ *val = sd->contrast; return 0; } @@ -710,7 +868,6 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; -/* getcolors(gspca_dev); */ *val = sd->colors; return 0; } @@ -750,13 +907,13 @@ static struct sd_desc sd_desc = { /* -- module initialisation -- */ static __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x093a, 0x2600)}, - {USB_DEVICE(0x093a, 0x2601)}, - {USB_DEVICE(0x093a, 0x2603)}, - {USB_DEVICE(0x093a, 0x2608)}, - {USB_DEVICE(0x093a, 0x260e)}, - {USB_DEVICE(0x093a, 0x260f)}, - {USB_DEVICE(0x093a, 0x2621)}, + {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302}, {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v1.2.3 From 3152cfe67c96844ba8c651a064533925c09107b8 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 8 Aug 2008 07:59:04 +0200 Subject: gspca: Bad scanning of frames in pac7311. From: Jean-Francois Moine The previous change in packet scanning did not work, Also, autogain was no more treated at interrupt level. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/pac7311.c | 33 +++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'linux/drivers/media/video/gspca/pac7311.c') diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index 034c00d6c..730b4a1ae 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -702,8 +702,16 @@ static void do_autogain(struct gspca_dev *gspca_dev) static void put_jpeg_head(struct gspca_dev *gspca_dev, struct gspca_frame *frame) { + struct sd *sd = (struct sd *) gspca_dev; unsigned char tmpbuf[4]; + if (sd->ag_cnt >= 0) { + if (--sd->ag_cnt < 0) { + sd->ag_cnt = AG_CNT_START; + atomic_set(&sd->avg_lum, sd->lum_sum / AG_CNT_START); + atomic_set(&sd->do_gain, 1); + } + } gspca_frame_add(gspca_dev, FIRST_PACKET, frame, (__u8 *) pac7311_jpeg_header, 12); @@ -727,7 +735,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; int i; -#define INTER_FRAME 0x53 +#define INTER_FRAME 0x53 /* eof + inter frame + sof */ #define LUM_OFFSET 0x1e /* reverse offset / start of frame */ /* @@ -746,11 +754,18 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (sd->tosof == 0) { /* if inside a frame */ /* check for 'ff ff ff xx' at start and at end of packet */ - /* (len is always >= 3) */ + /* (len is always >= 3 and xx never ff) */ switch (sd->ffnb) { case 1: - if (data[0] != 0xff) + if (data[0] != 0xff) { /* can be '00' only */ + __u8 ff; + + sd->ffnb = 0; + ff = 0xff; + gspca_frame_add(gspca_dev, INTER_PACKET, + frame, &ff, 1); break; /* keep 'ff 00' */ + } /* fall thru */ case 2: case 3: @@ -775,16 +790,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } } else { /* outside a frame */ - /* - * get the luminosity - * and go to the start of frame - */ + /* get the luminosity and go to the start of frame */ data += sd->tosof; len -= sd->tosof; if (sd->tosof > LUM_OFFSET) sd->lum_sum += data[-LUM_OFFSET]; - put_jpeg_head(gspca_dev, frame); sd->tosof = 0; + put_jpeg_head(gspca_dev, frame); } for (i = 0; i < len; i++) { @@ -792,10 +804,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, continue; switch (data[i + 1]) { case 0xd9: /* end of frame */ - i += 2; frame = gspca_frame_add(gspca_dev, LAST_PACKET, - frame, data, i); + frame, data, i + 2); data += i + INTER_FRAME; len -= i + INTER_FRAME; i = 0; @@ -816,6 +827,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, break; } } + gspca_frame_add(gspca_dev, INTER_PACKET, + frame, data, i); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) -- cgit v1.2.3 From 1ed2472d509f192f2420635f87057f0d53345ed6 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 11 Aug 2008 17:06:20 +0200 Subject: gspca: Bad frame scanning again and bad init in pac7311. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/pac7311.c | 62 +++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 12 deletions(-) (limited to 'linux/drivers/media/video/gspca/pac7311.c') diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index 730b4a1ae..85d9ddbc5 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -220,6 +220,7 @@ static const __u8 probe_7302[] = { }; static const __u8 start_7302[] = { /* index, len, [value]* */ + 0xff, 1, 0x00, /* page 0 */ 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, @@ -249,7 +250,7 @@ static const __u8 start_7302[] = { 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, 0xc1, 0xd7, 0xec, 0xdc, 1, 0x01, - 0xff, 1, 0x01, + 0xff, 1, 0x01, /* page 1 */ 0x12, 3, 0x02, 0x00, 0x01, 0x3e, 2, 0x00, 0x00, 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, @@ -257,26 +258,26 @@ static const __u8 start_7302[] = { 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, 0x02, 0x00, 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, - 0xc8, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, + 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, - 0x01, + 0xd8, 1, 0x01, 0xdb, 2, 0x00, 0x01, - 0xde, 8, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, + 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, 0xe6, 4, 0x00, 0x00, 0x00, 0x01, 0xeb, 1, 0x00, - 0xff, 1, 0x02, + 0xff, 1, 0x02, /* page 2 */ 0x22, 1, 0x00, - 0xff, 1, 0x03, + 0xff, 1, 0x03, /* page 3 */ 0x00, 255, /* load the page 3 */ 0x11, 1, 0x01, - 0xff, 1, 0x02, + 0xff, 1, 0x02, /* page 2 */ 0x13, 1, 0x00, 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, 0x27, 2, 0x14, 0x0c, 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, 0x6e, 1, 0x08, - 0xff, 1, 0x03, + 0xff, 1, 0x03, /* page 1 */ 0x78, 1, 0x00, 0, 0 /* end of sequence */ }; @@ -321,14 +322,14 @@ static const __u8 probe_7311[] = { static const __u8 start_7311[] = { /* index, len, [value]* */ - 0xff, 1, 0x01, - 0x02, 53, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00, + 0xff, 1, 0x01, /* page 1 */ + 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00, 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c, 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 52, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e, + 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e, 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48, 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78, @@ -342,7 +343,7 @@ static const __u8 start_7311[] = { 0xa0, 4, 0x44, 0x44, 0x44, 0x04, 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00, 0x3f, 0x00, 0x0a, 0x01, 0x00, - 0xff, 1, 0x04, + 0xff, 1, 0x04, /* page 4 */ 0x00, 254, /* load the page 4 */ 0x11, 1, 0x01, 0, 0 /* end of sequence */ @@ -738,6 +739,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, #define INTER_FRAME 0x53 /* eof + inter frame + sof */ #define LUM_OFFSET 0x1e /* reverse offset / start of frame */ +/*fixme:test+*/ +/* dump the packet */ + if (gspca_debug & 0x200) { + static char tmp[50]; + + PDEBUG(0x200, "pkt_scan"); + tmp[0] = 0; + for (i = 0; i < len; i++) { + if (i % 16 == 0 && i != 0) { + PDEBUG(0x200, "%s", tmp); + tmp[0] = 0; + } + sprintf(&tmp[(i % 16) * 3], "%02x ", data[i]); + } + if (tmp[0] != 0) + PDEBUG(0x200, "%s", tmp); + } +/*fixme:test-*/ /* * inside a frame, there may be: * escaped ff ('ff 00') @@ -819,6 +838,25 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, put_jpeg_head(gspca_dev, frame); break; case 0xff: /* 'ff ff ff xx' */ +/*fixme:test+*/ +/* is there a start of frame ? */ + if (data[i + 2] == 0x00) { + static __u8 ffd9[2] = {0xff, 0xd9}; + + gspca_frame_add(gspca_dev, + INTER_PACKET, + frame, data, + i + 7 - INTER_FRAME); + frame = gspca_frame_add(gspca_dev, + LAST_PACKET, + frame, ffd9, 2); + data += i + 7; + len -= i + 7; + i = 0; + put_jpeg_head(gspca_dev, frame); + break; + } +/*fixme:test-*/ gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, i); data += i + 4; -- cgit v1.2.3 From bf23e05b3f443503624b55cb16f32afdcb74289c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 14 Aug 2008 10:50:14 +0200 Subject: gspca: Pixmap PJPG (Pixart 73xx JPEG) added, generated by pac7311. From: Jean-Francois Moine The JPEG frames generated by the Pixart 73xx have: - special markers 'ff ff ff xx' every 1024/512 bytes, - unused 8 bits at end of JPEG blocks, and then ask for a new pixel format. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/pac7311.c | 173 +++--------------------------- 1 file changed, 15 insertions(+), 158 deletions(-) (limited to 'linux/drivers/media/video/gspca/pac7311.c') diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index 85d9ddbc5..c148d1003 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -22,6 +22,7 @@ #define MODULE_NAME "pac7311" #include "gspca.h" +#include "jpeg.h" MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); MODULE_DESCRIPTION("Pixart PAC7311"); @@ -40,7 +41,6 @@ struct sd { unsigned char colors; unsigned char autogain; - char ffnb; /* number of 'ff' in the previous frame */ char tosof; /* number of bytes before next start of frame */ signed char ag_cnt; #define AG_CNT_START 13 @@ -121,95 +121,23 @@ static struct ctrl sd_ctrls[] = { }; static struct v4l2_pix_format vga_mode[] = { - {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 2}, - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 1}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; -#define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */ - -static const __u8 pac7311_jpeg_header[] = { - 0xff, 0xd8, - 0xff, 0xe0, 0x00, 0x03, 0x20, - 0xff, 0xc0, 0x00, 0x11, 0x08, - 0x01, 0xe0, /* 12: height */ - 0x02, 0x80, /* 14: width */ - 0x03, /* 16 */ - 0x01, 0x21, 0x00, - 0x02, 0x11, 0x01, - 0x03, 0x11, 0x01, - 0xff, 0xdb, 0x00, 0x84, - 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, - 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, - 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, - 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, - 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f, - 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64, - 0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18, - 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, - 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, - 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, - 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, - 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, - 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, - 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, - 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, - 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, - 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, - 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, - 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, - 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, - 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, - 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, - 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, - 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, - 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, - 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, - 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, - 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, - 0x11, 0x00, 0x3f, 0x00 -}; - /* pac 7302 */ static const __u8 probe_7302[] = { /* index,value */ @@ -566,7 +494,6 @@ static void sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - sd->ffnb = 0; sd->tosof = 0; if (sd->sensor == SENSOR_PAC7302) @@ -699,34 +626,6 @@ static void do_autogain(struct gspca_dev *gspca_dev) } } -/* output the jpeg header */ -static void put_jpeg_head(struct gspca_dev *gspca_dev, - struct gspca_frame *frame) -{ - struct sd *sd = (struct sd *) gspca_dev; - unsigned char tmpbuf[4]; - - if (sd->ag_cnt >= 0) { - if (--sd->ag_cnt < 0) { - sd->ag_cnt = AG_CNT_START; - atomic_set(&sd->avg_lum, sd->lum_sum / AG_CNT_START); - atomic_set(&sd->do_gain, 1); - } - } - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - (__u8 *) pac7311_jpeg_header, - 12); - tmpbuf[0] = gspca_dev->height >> 8; - tmpbuf[1] = gspca_dev->height & 0xff; - tmpbuf[2] = gspca_dev->width >> 8; - tmpbuf[3] = gspca_dev->width & 0xff; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - tmpbuf, 4); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - (__u8 *) &pac7311_jpeg_header[16], - PAC7311_JPEG_HEADER_SIZE - 16); -} - /* this function is run at interrupt level */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ @@ -739,7 +638,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, #define INTER_FRAME 0x53 /* eof + inter frame + sof */ #define LUM_OFFSET 0x1e /* reverse offset / start of frame */ -/*fixme:test+*/ +#if 0 /*fixme:test+*/ /* dump the packet */ if (gspca_debug & 0x200) { static char tmp[50]; @@ -756,7 +655,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (tmp[0] != 0) PDEBUG(0x200, "%s", tmp); } -/*fixme:test-*/ +#endif /*fixme:test-*/ /* * inside a frame, there may be: * escaped ff ('ff 00') @@ -767,47 +666,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, * 0x33 bytes * one byte luminosity * 0x16 bytes - * ff ff 00 ff 96 62 44 start of frame header + * ff ff 00 ff 96 62 44 start of frame */ - if (sd->tosof == 0) { /* if inside a frame */ - - /* check for 'ff ff ff xx' at start and at end of packet */ - /* (len is always >= 3 and xx never ff) */ - switch (sd->ffnb) { - case 1: - if (data[0] != 0xff) { /* can be '00' only */ - __u8 ff; - - sd->ffnb = 0; - ff = 0xff; - gspca_frame_add(gspca_dev, INTER_PACKET, - frame, &ff, 1); - break; /* keep 'ff 00' */ - } - /* fall thru */ - case 2: - case 3: - data += 4 - sd->ffnb; - len -= 4 - sd->ffnb; - sd->ffnb = 0; - break; - } - if (data[len - 1] == 0xff) { - if (data[len - 2] == 0xff) { - if (data[len - 3] == 0xff) { - sd->ffnb = 3; - len -= 3; - } else { - sd->ffnb = 2; - len -= 2; - } - } else { - sd->ffnb = 1; - len--; - } - } - } else { /* outside a frame */ + if (sd->tosof != 0) { /* if outside a frame */ /* get the luminosity and go to the start of frame */ data += sd->tosof; @@ -815,14 +677,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (sd->tosof > LUM_OFFSET) sd->lum_sum += data[-LUM_OFFSET]; sd->tosof = 0; - put_jpeg_head(gspca_dev, frame); + jpeg_put_header(gspca_dev, frame, 1, 0x21); } for (i = 0; i < len; i++) { if (data[i] != 0xff) continue; switch (data[i + 1]) { - case 0xd9: /* end of frame */ + case 0xd9: /* 'ff d9' end of frame */ frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, i + 2); @@ -835,11 +697,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, sd->tosof = -len; break; } - put_jpeg_head(gspca_dev, frame); + jpeg_put_header(gspca_dev, frame, 1, 0x21); break; - case 0xff: /* 'ff ff ff xx' */ -/*fixme:test+*/ +#if 0 /*fixme:test+*/ /* is there a start of frame ? */ + case 0xff: /* 'ff ff' */ if (data[i + 2] == 0x00) { static __u8 ffd9[2] = {0xff, 0xd9}; @@ -853,16 +715,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data += i + 7; len -= i + 7; i = 0; - put_jpeg_head(gspca_dev, frame); + jpeg_put_header(gspca_dev, frame, 1, 0x21); break; } -/*fixme:test-*/ - gspca_frame_add(gspca_dev, INTER_PACKET, - frame, data, i); - data += i + 4; - len -= i + 4; - i = 0; break; +#endif /*fixme:test-*/ } } gspca_frame_add(gspca_dev, INTER_PACKET, -- cgit v1.2.3