@@ -37,8 +37,7 @@
unsigned short brightness;
unsigned short contrast;
- char packet;
- char synchro;
+ unsigned int packet;
};
/* V4L2 controls supported by the driver */
@@ -451,35 +450,45 @@
reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
}
+#define MAX_PKT_LENGTH 1023
+#define WIDTH ((TESTLINE & 0x80) ? 352 : (TESTLINE & 0x40) ? 176 : 320)
+#define LINES_PER_PKT ((TESTLINE & 0x0f) + 1)
+#define PKT_LENGTH ((TESTCOMP & 0x80) ? \
+ (3 + (2 + WIDTH + 3 + WIDTH + 2)) : \
+ (3 + (((16 + WIDTH - 2) * LINES_PER_PKT + 7) >> 3)))
+
+static const int num_pkts[][17] = { /* ceil(height / lines_per_pkt) */
+ { 0, 240, 120, 80, 60, 48, 40, 34, 30, 26, 24, 21, 20, 18, 17, 16, 15 },
+ { 0, 144, 72, 48, 36, 29, 24, 21, 18, 16, 15, 14, 12, 12, 11, 10, 9 },
+ { 0, 288, 144, 96, 72, 58, 48, 42, 36, 32, 29, 27, 24, 23, 21, 20, 18 },
+ { 0, 288, 144, 96, 72, 58, 48, 42, 36, 32, 29, 27, 24, 23, 21, 20, 18 },
+};
+
static void tv8532_preprocess(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
-/* we should received a whole frame with header and EOL marker
- * in gspca_dev->tmpbuf and return a GBRG pattern in gspca_dev->tmpbuf2
- * sequence 2bytes header the Alternate pixels bayer GB 4 bytes
- * Alternate pixels bayer RG 4 bytes EOL */
- int width = gspca_dev->width;
- int height = gspca_dev->height;
- unsigned char *dst = sd->tmpbuf2;
- unsigned char *data = sd->tmpbuf;
- int i;
-
- /* precompute where is the good bayer line */
- if (((data[3] + data[width + 7]) >> 1)
- + (data[4] >> 2)
- + (data[width + 6] >> 1) >= ((data[2] + data[width + 6]) >> 1)
- + (data[3] >> 2)
- + (data[width + 5] >> 1))
- data += 3;
- else
- data += 2;
- for (i = 0; i < height / 2; i++) {
- memcpy(dst, data, width);
- data += width + 3;
- dst += width;
- memcpy(dst, data, width);
- data += width + 7;
- dst += width;
+ int pkts_needed = num_pkts[TESTLINE >> 6][LINES_PER_PKT];
+ int i, j;
+ __u8 *dst = sd->tmpbuf2;
+ __u8 *src = sd->tmpbuf;
+ __u8 *max;
+
+ if (TESTCOMP & 0x80) {
+ for (i = 0; i < pkts_needed; i++) {
+ max = src + MAX_PKT_LENGTH;
+ src++;
+ for (j = 0; j < LINES_PER_PKT; j++) {
+ src++;
+ memcpy(dst, src, WIDTH);
+ src += WIDTH + 2;
+ dst += WIDTH;
+ }
+ src += 3;
+ src = (src > max) ? max : src;
+ }
+ } else {
+ //icm532_decode(dst, src, width, height,
+ // QUANT, LINES_PER_PKT, MAX_PKT_LENGTH, 0);
}
}
@@ -489,73 +498,106 @@
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
+ int pkts_needed = num_pkts[TESTLINE >> 6][LINES_PER_PKT];
- if (data[0] != 0x80) {
- sd->packet++;
- if (sd->buflen + len > sizeof sd->tmpbuf) {
- if (gspca_dev->last_packet_type != DISCARD_PACKET) {
- PDEBUG(D_PACK, "buffer overflow");
- gspca_dev->last_packet_type = DISCARD_PACKET;
- }
+ //printk("packet: %d id: 0x%02x size: %d "
+ // "start: %02x %02x %02x %02x end: %02x %02x %02x %02x\n",
+ // sd->packet, data[0], len,
+ // data[1], data[2], data[3], data[4],
+ // data[len - 4], data[len - 3], data[len - 2], data[len - 1]);
+
+ /* 6-bit counter wraps after 64 packets or on a new frame */
+
+ while ((sd->packet & 0x3f) > (data[0] & 0x3f)) {
+ if ((sd->packet & 0x3f) < (data[0] & 0x3f) + 2) {
+ //printk("dropped duplicate packet %d(0x%02x)\n",
+ // sd->packet, data[0]);
return;
}
- memcpy(&sd->tmpbuf[sd->buflen], data, len);
- sd->buflen += len;
- return;
- }
-
- /* here we detect 0x80 */
- /* counter is limited so we need few header for a frame :) */
- /* header 0x80 0x80 0x80 0x80 0x80 */
- /* packet 00 63 127 145 00 */
- /* sof 0 1 1 0 0 */
-
- /* update sequence */
- if (sd->packet == 63 || sd->packet == 127)
- sd->synchro = 1;
-
- /* is there a frame start ? */
- if (sd->packet >= (gspca_dev->height >> 1) - 1) {
- PDEBUG(D_PACK, "SOF > %d packet %d", sd->synchro,
- sd->packet);
- if (!sd->synchro) { /* start of frame */
+ if ((sd->packet >= pkts_needed)) {
if (gspca_dev->last_packet_type == FIRST_PACKET) {
tv8532_preprocess(gspca_dev);
frame = gspca_frame_add(gspca_dev,
LAST_PACKET,
frame, sd->tmpbuf2,
gspca_dev->width *
- gspca_dev->width);
+ gspca_dev->height);
}
gspca_frame_add(gspca_dev, FIRST_PACKET,
frame, data, 0);
- memcpy(sd->tmpbuf, data, len);
- sd->buflen = len;
+ sd->buflen = 0;
+ sd->packet = 0;
+ break;
+ }
+
+ //printk("over %d\n", sd->packet);
+ if (sd->buflen + PKT_LENGTH > sizeof sd->tmpbuf) {
+ if (gspca_dev->last_packet_type != DISCARD_PACKET) {
+ PDEBUG(D_PACK, "buffer overflow");
+ gspca_dev->last_packet_type = DISCARD_PACKET;
+ }
+ sd->buflen = 0;
sd->packet = 0;
return;
}
- if (gspca_dev->last_packet_type != DISCARD_PACKET) {
- PDEBUG(D_PACK,
- "Warning wrong TV8532 frame detection %d",
- sd->packet);
- gspca_dev->last_packet_type = DISCARD_PACKET;
+ sd->tmpbuf[sd->buflen + 0] = 0x80 | (sd->packet & 0x3f);
+ sd->tmpbuf[sd->buflen + 1] = 0xff;
+ sd->tmpbuf[sd->buflen + 2] = 0x00;
+ memset(&sd->tmpbuf[sd->buflen + 3], 0x00, PKT_LENGTH - 5);
+ sd->tmpbuf[sd->buflen + PKT_LENGTH - 2] = 0xff;
+ sd->tmpbuf[sd->buflen + PKT_LENGTH - 1] = 0xff;
+ sd->buflen += PKT_LENGTH;
+ sd->packet++;
+
+ sd->packet = sd->packet & 0x3f;
+ }
+
+ while ((sd->packet & 0x3f) < (data[0] & 0x3f)) {
+ if (sd->packet >= pkts_needed) {
+ break;
}
- return;
+
+ //printk("under %d\n", sd->packet);
+ if (sd->buflen + PKT_LENGTH > sizeof sd->tmpbuf) {
+ if (gspca_dev->last_packet_type != DISCARD_PACKET) {
+ PDEBUG(D_PACK, "buffer overflow");
+ gspca_dev->last_packet_type = DISCARD_PACKET;
+ }
+ sd->buflen = 0;
+ sd->packet = 0;
+ return;
+ }
+ sd->tmpbuf[sd->buflen + 0] = 0x80 | (sd->packet & 0x3f);
+ sd->tmpbuf[sd->buflen + 1] = 0x00;
+ sd->tmpbuf[sd->buflen + 2] = 0xff;
+ memset(&sd->tmpbuf[sd->buflen + 3], 0x00, PKT_LENGTH - 5);
+ sd->tmpbuf[sd->buflen + PKT_LENGTH - 2] = 0xff;
+ sd->tmpbuf[sd->buflen + PKT_LENGTH - 1] = 0xff;
+ sd->buflen += PKT_LENGTH;
+ sd->packet++;
}
- if (!sd->synchro) {
- /* Drop packet frame corrupt */
- PDEBUG(D_PACK, "DROP SOF %d packet %d",
- sd->synchro, sd->packet);
+ if (sd->packet >= pkts_needed) {
+ //printk("dropped packet %d(0x%02x)\n", sd->packet, data[0]);
+ sd->packet = pkts_needed;
+ return;
+ }
+
+ if (sd->buflen + len > sizeof sd->tmpbuf) {
+ if (gspca_dev->last_packet_type != DISCARD_PACKET) {
+ PDEBUG(D_PACK, "buffer overflow");
+ gspca_dev->last_packet_type = DISCARD_PACKET;
+ }
+ sd->buflen = 0;
sd->packet = 0;
- gspca_dev->last_packet_type = DISCARD_PACKET;
return;
}
- sd->synchro = 1;
- sd->packet++;
+
+ //printk("saved packet %d(0x%02x)\n", sd->packet, data[0]);
memcpy(&sd->tmpbuf[sd->buflen], data, len);
sd->buflen += len;
+ sd->packet++;
}
static void setcontrast(struct gspca_dev *gspca_dev)