Commit b04d7191 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab Committed by Mauro Carvalho Chehab

V4L/DVB (12799): tm6000: avoid troubles if a header is broken on separate URBs

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 0c6612ef
...@@ -38,4 +38,7 @@ struct usb_isoc_ctl { ...@@ -38,4 +38,7 @@ struct usb_isoc_ctl {
/* Last field: ODD or EVEN? */ /* Last field: ODD or EVEN? */
int field; int field;
u32 tmp_buf;
int tmp_buf_len;
}; };
...@@ -212,7 +212,7 @@ static u8 *copy_packet (struct urb *urb, u32 header, u8 *data, u8 *endp, ...@@ -212,7 +212,7 @@ static u8 *copy_packet (struct urb *urb, u32 header, u8 *data, u8 *endp,
/* Validates header fields */ /* Validates header fields */
if(size>TM6000_URB_MSG_LEN) if(size>TM6000_URB_MSG_LEN)
size=TM6000_URB_MSG_LEN; size = TM6000_URB_MSG_LEN;
if(block>=8) if(block>=8)
cmd = TM6000_URB_MSG_ERR; cmd = TM6000_URB_MSG_ERR;
...@@ -220,8 +220,7 @@ static u8 *copy_packet (struct urb *urb, u32 header, u8 *data, u8 *endp, ...@@ -220,8 +220,7 @@ static u8 *copy_packet (struct urb *urb, u32 header, u8 *data, u8 *endp,
* It should, instead, check if the user selected * It should, instead, check if the user selected
* entrelaced or non-entrelaced mode * entrelaced or non-entrelaced mode
*/ */
pos=((line<<1)+field)*linesize+ pos=((line<<1)+field)*linesize+block*TM6000_URB_MSG_LEN;
block*TM6000_URB_MSG_LEN;
/* Don't allow to write out of the buffer */ /* Don't allow to write out of the buffer */
if (pos+TM6000_URB_MSG_LEN > (*buf)->vb.size) if (pos+TM6000_URB_MSG_LEN > (*buf)->vb.size)
...@@ -232,6 +231,7 @@ static u8 *copy_packet (struct urb *urb, u32 header, u8 *data, u8 *endp, ...@@ -232,6 +231,7 @@ static u8 *copy_packet (struct urb *urb, u32 header, u8 *data, u8 *endp,
" line=%d, field=%d\n", " line=%d, field=%d\n",
size, block, line, field); size, block, line, field);
pktsize = TM6000_URB_MSG_LEN; pktsize = TM6000_URB_MSG_LEN;
///////////////////////////// /////////////////////////////
/// nao seria size??? /// nao seria size???
...@@ -251,7 +251,8 @@ static u8 *copy_packet (struct urb *urb, u32 header, u8 *data, u8 *endp, ...@@ -251,7 +251,8 @@ static u8 *copy_packet (struct urb *urb, u32 header, u8 *data, u8 *endp,
switch(cmd) { switch(cmd) {
case TM6000_URB_MSG_VIDEO: case TM6000_URB_MSG_VIDEO:
/* Fills video buffer */ /* Fills video buffer */
bufcpy(*buf,&out_p[pos],ptr,cpysize); if (__copy_to_user(&out_p[pos],ptr,cpysize)!=0)
tm6000_err("copy_to_user failed.\n");
break; break;
} }
} }
...@@ -278,26 +279,54 @@ static int copy_streams(u8 *data, u8 *out_p, unsigned long len, ...@@ -278,26 +279,54 @@ static int copy_streams(u8 *data, u8 *out_p, unsigned long len,
struct tm6000_dmaqueue *dma_q = urb->context; struct tm6000_dmaqueue *dma_q = urb->context;
struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
u8 *ptr=data, *endp=data+len; u8 *ptr=data, *endp=data+len;
u32 header=0; unsigned long header=0;
int rc=0; int rc=0;
for (ptr=data; ptr<endp;) { for (ptr=data; ptr<endp;) {
if (!dev->isoc_ctl.cmd) { if (!dev->isoc_ctl.cmd) {
/* Seek for sync */ u8 *p=(u8 *)&dev->isoc_ctl.tmp_buf;
for (ptr+=3;ptr<endp;ptr++) { /* FIXME: This seems very complex
if (*ptr==0x47) { * It just recovers up to 3 bytes of the header that
ptr-=3; * might be at the previous packet
*/
if (dev->isoc_ctl.tmp_buf_len) {
while (dev->isoc_ctl.tmp_buf_len) {
if ( *(ptr+3-dev->isoc_ctl.tmp_buf_len) == 0x47) {
break; break;
} }
p++;
dev->isoc_ctl.tmp_buf_len--;
}
if (dev->isoc_ctl.tmp_buf_len) {
memcpy (&header,p,
dev->isoc_ctl.tmp_buf_len);
memcpy (((u8 *)header)+
dev->isoc_ctl.tmp_buf,
ptr,
4-dev->isoc_ctl.tmp_buf_len);
ptr+=4-dev->isoc_ctl.tmp_buf_len;
goto HEADER;
}
} }
if (ptr>=endp) /* Seek for sync */
for (;ptr<endp-3;ptr++) {
if (*(ptr+3)==0x47)
break;
}
if (ptr+3>=endp) {
dev->isoc_ctl.tmp_buf_len=endp-ptr;
memcpy (&dev->isoc_ctl.tmp_buf,ptr,
dev->isoc_ctl.tmp_buf_len);
dev->isoc_ctl.cmd=0;
return rc; return rc;
}
/* Get message header */ /* Get message header */
header=*(unsigned long *)ptr; header=*(unsigned long *)ptr;
ptr+=4; ptr+=4;
} }
HEADER:
/* Copy or continue last copy */ /* Copy or continue last copy */
ptr=copy_packet(urb,header,ptr,endp,out_p,buf); ptr=copy_packet(urb,header,ptr,endp,out_p,buf);
} }
...@@ -581,7 +610,8 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev, ...@@ -581,7 +610,8 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev,
sb_size, GFP_KERNEL, &urb->transfer_dma); sb_size, GFP_KERNEL, &urb->transfer_dma);
if (!dev->isoc_ctl.transfer_buffer[i]) { if (!dev->isoc_ctl.transfer_buffer[i]) {
tm6000_err ("unable to allocate %i bytes for transfer" tm6000_err ("unable to allocate %i bytes for transfer"
" buffer %i\n", sb_size, i); " buffer %i, in int=%i\n",
sb_size, i, in_interrupt());
tm6000_uninit_isoc(dev); tm6000_uninit_isoc(dev);
return -ENOMEM; return -ENOMEM;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment