Loading drivers/staging/tm6000/tm6000-usb-isoc.h +5 −9 Original line number Diff line number Diff line Loading @@ -34,24 +34,20 @@ struct usb_isoc_ctl { /* transfer buffers for isoc transfer */ char **transfer_buffer; /* Last buffer control */ int pending; int pos; /* Last buffer command and region */ u8 cmd; int pos, size, pktsize; /* Last field: ODD or EVEN? */ int field; /* Stores incomplete commands */ u8 tbuf[TM6000_URB_MSG_LEN+4]; size_t len; u32 tmp_buf; int tmp_buf_len; /* Stores already requested buffers */ struct tm6000_buffer *buf; /* Stores the number of received fields */ int nfields; /* Checks if a complete field were received */ int last_line; unsigned int fields:2; }; drivers/staging/tm6000/tm6000-video.c +191 −196 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, */ unsigned int linewidth = (*buf)->vb.width << 1; if (!dev->isoc_ctl.cmd) { c = (header >> 24) & 0xff; /* split the header fields */ Loading Loading @@ -234,22 +235,6 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, " line=%d, field=%d\n", size, block, line, field); /* Checks if a complete set of frame0 + frame 1 were received */ if (dev->isoc_ctl.last_line > line) { if (dev->isoc_ctl.fields == 3) { /* Announces that a new buffer were filled */ buffer_filled(dev, dma_q, *buf); dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n"); rc = get_next_buf(dma_q, buf); dev->isoc_ctl.fields = 0; } else { dev->isoc_ctl.fields |= 1 << field; } } dev->isoc_ctl.last_line = line; if ((last_line!=line)&&(last_line+1!=line) && (cmd != TM6000_URB_MSG_ERR) ) { if (cmd != TM6000_URB_MSG_VIDEO) { Loading @@ -268,8 +253,15 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, (last_field != field) ) { dev->isoc_ctl.nfields++; if (dev->isoc_ctl.nfields >= 2) if (dev->isoc_ctl.nfields>=2) { dev->isoc_ctl.nfields=0; /* Announces that a new buffer were filled */ buffer_filled (dev, dma_q, *buf); dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n"); rc=get_next_buf (dma_q, buf); } } start_line=line; Loading @@ -278,6 +270,13 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, last_line=line; pktsize = TM6000_URB_MSG_LEN; } else { /* Continue the last copy */ cmd = dev->isoc_ctl.cmd; size= dev->isoc_ctl.size; pos = dev->isoc_ctl.pos; pktsize = dev->isoc_ctl.pktsize; } cpysize = (endp-(*ptr) > size) ? size : endp - *ptr; Loading @@ -286,15 +285,13 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, switch(cmd) { case TM6000_URB_MSG_VIDEO: /* Fills video buffer */ if (__copy_to_user(&out_p[pos], *ptr, cpysize) != 0) tm6000_err("copy_to_user failed.\n"); memcpy(&out_p[pos], *ptr, cpysize); break; case TM6000_URB_MSG_PTS: break; case TM6000_URB_MSG_AUDIO: /* Need some code to process audio */ printk(KERN_INFO "%ld: cmd=%s, size=%d\n", jiffies, printk ("%ld: cmd=%s, size=%d\n", jiffies, tm6000_msg_type[cmd],size); break; default: Loading @@ -302,7 +299,19 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, tm6000_msg_type[cmd],size); } } if (cpysize<size) { /* End of URB packet, but cmd processing is not * complete. Preserve the state for a next packet */ dev->isoc_ctl.pos = pos+cpysize; dev->isoc_ctl.size= size-cpysize; dev->isoc_ctl.cmd = cmd; dev->isoc_ctl.pktsize = pktsize-cpysize; (*ptr)+=cpysize; } else { dev->isoc_ctl.cmd = 0; (*ptr)+=pktsize; } return rc; } Loading @@ -312,71 +321,55 @@ static int copy_streams(u8 *data, u8 *out_p, unsigned long len, { struct tm6000_dmaqueue *dma_q = urb->context; struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); u8 *ptr, *endp; u8 *ptr=data, *endp=data+len; unsigned long header=0; int rc = 0, size; /* Process pending data */ if (dev->isoc_ctl.pending) { memcpy(dev->isoc_ctl.tbuf + dev->isoc_ctl.len, ptr, sizeof(dev->isoc_ctl.tbuf) - dev->isoc_ctl.len); int rc=0; /* Seek for sync */ endp = dev->isoc_ctl.tbuf + sizeof(dev->isoc_ctl.tbuf); for (ptr = dev->isoc_ctl.tbuf; ptr < endp - 3; ptr++) { if (*(ptr + 3) == 0x47) for (ptr=data; ptr<endp;) { if (!dev->isoc_ctl.cmd) { u8 *p=(u8 *)&dev->isoc_ctl.tmp_buf; /* FIXME: This seems very complex * It just recovers up to 3 bytes of the header that * 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; } header = *(unsigned long *)ptr; size = (((header & 0x7e) << 1) - 1) * 4; if (size > TM6000_URB_MSG_LEN) size = TM6000_URB_MSG_LEN; if (ptr + 3 + size >= endp) { printk(KERN_ERR "tm6000: broken data\n"); ptr = data; goto process_new_uri; 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; } ptr += 4; /* Copy or continue last copy */ rc = copy_packet(urb, header, &ptr, endp, out_p, buf); if (rc < 0) { buf = NULL; printk(KERN_ERR "tm6000: buffer underrun at %ld\n", jiffies); return rc; } dev->isoc_ctl.pending = 0; ptr = data + (ptr - dev->isoc_ctl.tbuf); } else ptr = data; process_new_uri: endp = data + len; while (ptr < endp) { if (!dev->isoc_ctl.pending) { /* Seek for sync */ for (;ptr<endp-3;ptr++) { if (*(ptr+3)==0x47) break; } header = *(unsigned long *)ptr; size = (((header & 0x7e) << 1) - 1) * 4; if (size > TM6000_URB_MSG_LEN) size = TM6000_URB_MSG_LEN; if (ptr + 3 + size >= endp) { int len = endp - ptr; memcpy(dev->isoc_ctl.tbuf, ptr, len); dev->isoc_ctl.len = len; dev->isoc_ctl.pending = 1; 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; } /* Get message header */ header=*(unsigned long *)ptr; ptr+=4; } HEADER: /* Copy or continue last copy */ rc=copy_packet(urb,header,&ptr,endp,out_p,buf); if (rc<0) { Loading @@ -402,10 +395,8 @@ static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len, while (len>0) { cpysize=min(len,(*buf)->vb.size-pos); if (__copy_to_user(&out_p[pos], ptr, cpysize) != 0) tm6000_err("copy_to_user failed.\n"); //printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos); memcpy(&out_p[pos], ptr, cpysize); pos+=cpysize; ptr+=cpysize; len-=cpysize; Loading @@ -426,7 +417,7 @@ static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len, return rc; } static inline void print_err_status(struct tm6000_core *dev, static void inline print_err_status (struct tm6000_core *dev, int packet, int status) { char *errmsg = "Unknown"; Loading Loading @@ -461,8 +452,7 @@ static inline void print_err_status(struct tm6000_core *dev, dprintk(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n", status, errmsg); } else { dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n", dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n", packet, status, errmsg); } } Loading @@ -479,7 +469,9 @@ static inline int tm6000_isoc_copy(struct urb *urb, struct tm6000_buffer **buf) int i, len=0, rc=1; int size=(*buf)->vb.size; char *p; unsigned long copied = 0; unsigned long copied; copied=0; if (urb->status<0) { print_err_status (dev,-1,urb->status); Loading @@ -496,18 +488,21 @@ static inline int tm6000_isoc_copy(struct urb *urb, struct tm6000_buffer **buf) len=urb->iso_frame_desc[i].actual_length; // if (len>=TM6000_URB_MSG_LEN) { p=urb->transfer_buffer + urb->iso_frame_desc[i].offset; if (!urb->iso_frame_desc[i].status) { if (((*buf)->fmt->fourcc)==V4L2_PIX_FMT_TM6000) { rc=copy_multiplexed(p,outp,len,urb,buf); if (rc<=0) return rc; } else } else { copy_streams(p,outp,len,urb,buf); } } copied += len; if (copied>=size) break; // } } return rc; } Loading Loading
drivers/staging/tm6000/tm6000-usb-isoc.h +5 −9 Original line number Diff line number Diff line Loading @@ -34,24 +34,20 @@ struct usb_isoc_ctl { /* transfer buffers for isoc transfer */ char **transfer_buffer; /* Last buffer control */ int pending; int pos; /* Last buffer command and region */ u8 cmd; int pos, size, pktsize; /* Last field: ODD or EVEN? */ int field; /* Stores incomplete commands */ u8 tbuf[TM6000_URB_MSG_LEN+4]; size_t len; u32 tmp_buf; int tmp_buf_len; /* Stores already requested buffers */ struct tm6000_buffer *buf; /* Stores the number of received fields */ int nfields; /* Checks if a complete field were received */ int last_line; unsigned int fields:2; };
drivers/staging/tm6000/tm6000-video.c +191 −196 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, */ unsigned int linewidth = (*buf)->vb.width << 1; if (!dev->isoc_ctl.cmd) { c = (header >> 24) & 0xff; /* split the header fields */ Loading Loading @@ -234,22 +235,6 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, " line=%d, field=%d\n", size, block, line, field); /* Checks if a complete set of frame0 + frame 1 were received */ if (dev->isoc_ctl.last_line > line) { if (dev->isoc_ctl.fields == 3) { /* Announces that a new buffer were filled */ buffer_filled(dev, dma_q, *buf); dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n"); rc = get_next_buf(dma_q, buf); dev->isoc_ctl.fields = 0; } else { dev->isoc_ctl.fields |= 1 << field; } } dev->isoc_ctl.last_line = line; if ((last_line!=line)&&(last_line+1!=line) && (cmd != TM6000_URB_MSG_ERR) ) { if (cmd != TM6000_URB_MSG_VIDEO) { Loading @@ -268,8 +253,15 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, (last_field != field) ) { dev->isoc_ctl.nfields++; if (dev->isoc_ctl.nfields >= 2) if (dev->isoc_ctl.nfields>=2) { dev->isoc_ctl.nfields=0; /* Announces that a new buffer were filled */ buffer_filled (dev, dma_q, *buf); dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n"); rc=get_next_buf (dma_q, buf); } } start_line=line; Loading @@ -278,6 +270,13 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, last_line=line; pktsize = TM6000_URB_MSG_LEN; } else { /* Continue the last copy */ cmd = dev->isoc_ctl.cmd; size= dev->isoc_ctl.size; pos = dev->isoc_ctl.pos; pktsize = dev->isoc_ctl.pktsize; } cpysize = (endp-(*ptr) > size) ? size : endp - *ptr; Loading @@ -286,15 +285,13 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, switch(cmd) { case TM6000_URB_MSG_VIDEO: /* Fills video buffer */ if (__copy_to_user(&out_p[pos], *ptr, cpysize) != 0) tm6000_err("copy_to_user failed.\n"); memcpy(&out_p[pos], *ptr, cpysize); break; case TM6000_URB_MSG_PTS: break; case TM6000_URB_MSG_AUDIO: /* Need some code to process audio */ printk(KERN_INFO "%ld: cmd=%s, size=%d\n", jiffies, printk ("%ld: cmd=%s, size=%d\n", jiffies, tm6000_msg_type[cmd],size); break; default: Loading @@ -302,7 +299,19 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, tm6000_msg_type[cmd],size); } } if (cpysize<size) { /* End of URB packet, but cmd processing is not * complete. Preserve the state for a next packet */ dev->isoc_ctl.pos = pos+cpysize; dev->isoc_ctl.size= size-cpysize; dev->isoc_ctl.cmd = cmd; dev->isoc_ctl.pktsize = pktsize-cpysize; (*ptr)+=cpysize; } else { dev->isoc_ctl.cmd = 0; (*ptr)+=pktsize; } return rc; } Loading @@ -312,71 +321,55 @@ static int copy_streams(u8 *data, u8 *out_p, unsigned long len, { struct tm6000_dmaqueue *dma_q = urb->context; struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); u8 *ptr, *endp; u8 *ptr=data, *endp=data+len; unsigned long header=0; int rc = 0, size; /* Process pending data */ if (dev->isoc_ctl.pending) { memcpy(dev->isoc_ctl.tbuf + dev->isoc_ctl.len, ptr, sizeof(dev->isoc_ctl.tbuf) - dev->isoc_ctl.len); int rc=0; /* Seek for sync */ endp = dev->isoc_ctl.tbuf + sizeof(dev->isoc_ctl.tbuf); for (ptr = dev->isoc_ctl.tbuf; ptr < endp - 3; ptr++) { if (*(ptr + 3) == 0x47) for (ptr=data; ptr<endp;) { if (!dev->isoc_ctl.cmd) { u8 *p=(u8 *)&dev->isoc_ctl.tmp_buf; /* FIXME: This seems very complex * It just recovers up to 3 bytes of the header that * 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; } header = *(unsigned long *)ptr; size = (((header & 0x7e) << 1) - 1) * 4; if (size > TM6000_URB_MSG_LEN) size = TM6000_URB_MSG_LEN; if (ptr + 3 + size >= endp) { printk(KERN_ERR "tm6000: broken data\n"); ptr = data; goto process_new_uri; 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; } ptr += 4; /* Copy or continue last copy */ rc = copy_packet(urb, header, &ptr, endp, out_p, buf); if (rc < 0) { buf = NULL; printk(KERN_ERR "tm6000: buffer underrun at %ld\n", jiffies); return rc; } dev->isoc_ctl.pending = 0; ptr = data + (ptr - dev->isoc_ctl.tbuf); } else ptr = data; process_new_uri: endp = data + len; while (ptr < endp) { if (!dev->isoc_ctl.pending) { /* Seek for sync */ for (;ptr<endp-3;ptr++) { if (*(ptr+3)==0x47) break; } header = *(unsigned long *)ptr; size = (((header & 0x7e) << 1) - 1) * 4; if (size > TM6000_URB_MSG_LEN) size = TM6000_URB_MSG_LEN; if (ptr + 3 + size >= endp) { int len = endp - ptr; memcpy(dev->isoc_ctl.tbuf, ptr, len); dev->isoc_ctl.len = len; dev->isoc_ctl.pending = 1; 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; } /* Get message header */ header=*(unsigned long *)ptr; ptr+=4; } HEADER: /* Copy or continue last copy */ rc=copy_packet(urb,header,&ptr,endp,out_p,buf); if (rc<0) { Loading @@ -402,10 +395,8 @@ static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len, while (len>0) { cpysize=min(len,(*buf)->vb.size-pos); if (__copy_to_user(&out_p[pos], ptr, cpysize) != 0) tm6000_err("copy_to_user failed.\n"); //printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos); memcpy(&out_p[pos], ptr, cpysize); pos+=cpysize; ptr+=cpysize; len-=cpysize; Loading @@ -426,7 +417,7 @@ static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len, return rc; } static inline void print_err_status(struct tm6000_core *dev, static void inline print_err_status (struct tm6000_core *dev, int packet, int status) { char *errmsg = "Unknown"; Loading Loading @@ -461,8 +452,7 @@ static inline void print_err_status(struct tm6000_core *dev, dprintk(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n", status, errmsg); } else { dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n", dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n", packet, status, errmsg); } } Loading @@ -479,7 +469,9 @@ static inline int tm6000_isoc_copy(struct urb *urb, struct tm6000_buffer **buf) int i, len=0, rc=1; int size=(*buf)->vb.size; char *p; unsigned long copied = 0; unsigned long copied; copied=0; if (urb->status<0) { print_err_status (dev,-1,urb->status); Loading @@ -496,18 +488,21 @@ static inline int tm6000_isoc_copy(struct urb *urb, struct tm6000_buffer **buf) len=urb->iso_frame_desc[i].actual_length; // if (len>=TM6000_URB_MSG_LEN) { p=urb->transfer_buffer + urb->iso_frame_desc[i].offset; if (!urb->iso_frame_desc[i].status) { if (((*buf)->fmt->fourcc)==V4L2_PIX_FMT_TM6000) { rc=copy_multiplexed(p,outp,len,urb,buf); if (rc<=0) return rc; } else } else { copy_streams(p,outp,len,urb,buf); } } copied += len; if (copied>=size) break; // } } return rc; } Loading