mirror of
https://github.com/torvalds/linux.git
synced 2024-12-18 17:12:55 +00:00
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>
This commit is contained in:
parent
d526afe06b
commit
e52a5574de
@ -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;
|
||||
int i;
|
||||
|
||||
/* if (len < 5) { */
|
||||
if (len < 6) {
|
||||
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
|
||||
return;
|
||||
#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--;
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user