From ab34d3bc0f351c38649a8426bff4b50fdd36a386 Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Thu, 8 Nov 2012 14:11:46 -0300 Subject: [PATCH] --- yaml --- r: 357135 b: refs/heads/master c: 4601cc39773b33a336eda2010ea5a551aaf6d7f0 h: refs/heads/master i: 357133: cc19dd80219d1b2c8c253bf5e7d719f80cde8be4 357131: b1d7abf1eb70c61ca12b98d884f8bc2ce2255bc1 357127: b755d3866aba5602e739892424cdbf615f3eabf1 357119: 23e2d649f91f01abe529d95a4be4b59538873c05 v: v3 --- [refs] | 2 +- trunk/drivers/media/usb/em28xx/em28xx-video.c | 70 ++++++++++++------- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/[refs] b/[refs] index 26ea03069466..ce0f6ac7e11f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0fa4a4029025507feb6c0322cd4c4693fbad9aac +refs/heads/master: 4601cc39773b33a336eda2010ea5a551aaf6d7f0 diff --git a/trunk/drivers/media/usb/em28xx/em28xx-video.c b/trunk/drivers/media/usb/em28xx/em28xx-video.c index 87161eea257e..df294f3858ea 100644 --- a/trunk/drivers/media/usb/em28xx/em28xx-video.c +++ b/trunk/drivers/media/usb/em28xx/em28xx-video.c @@ -518,18 +518,16 @@ static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb) return rc; } -/* Version of isoc handler that takes into account a mixture of video and - VBI data */ -static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) +/* Version of the urb data handler that takes into account a mixture of + video and VBI data */ +static inline int em28xx_urb_data_copy_vbi(struct em28xx *dev, struct urb *urb) { struct em28xx_buffer *buf, *vbi_buf; struct em28xx_dmaqueue *dma_q = &dev->vidq; struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; - unsigned char *outp = NULL; - unsigned char *vbioutp = NULL; - int i, len = 0, rc = 1; - unsigned char *p; - int vbi_size; + int xfer_bulk, vbi_size, num_packets, i, rc = 1; + unsigned int actual_length, len = 0; + unsigned char *p, *outp = NULL, *vbioutp = NULL; if (!dev) return 0; @@ -540,6 +538,8 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) if (urb->status < 0) print_err_status(dev, -1, urb->status); + xfer_bulk = usb_pipebulk(urb->pipe); + buf = dev->usb_ctl.vid_buf; if (buf != NULL) outp = videobuf_to_vmalloc(&buf->vb); @@ -548,28 +548,40 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) if (vbi_buf != NULL) vbioutp = videobuf_to_vmalloc(&vbi_buf->vb); - for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; + if (xfer_bulk) /* bulk */ + num_packets = 1; + else /* isoc */ + num_packets = urb->number_of_packets; - if (status < 0) { - print_err_status(dev, i, status); - if (urb->iso_frame_desc[i].status != -EPROTO) + for (i = 0; i < num_packets; i++) { + if (xfer_bulk) { /* bulk */ + actual_length = urb->actual_length; + + p = urb->transfer_buffer; + } else { /* isoc */ + if (urb->iso_frame_desc[i].status < 0) { + print_err_status(dev, i, + urb->iso_frame_desc[i].status); + if (urb->iso_frame_desc[i].status != -EPROTO) + continue; + } + + actual_length = urb->iso_frame_desc[i].actual_length; + if (actual_length > dev->max_pkt_size) { + em28xx_isocdbg("packet bigger than packet size"); continue; - } + } - len = urb->iso_frame_desc[i].actual_length; - if (urb->iso_frame_desc[i].actual_length <= 0) { - /* em28xx_isocdbg("packet %d is empty",i); - spammy */ - continue; + p = urb->transfer_buffer + + urb->iso_frame_desc[i].offset; } - if (urb->iso_frame_desc[i].actual_length > - dev->max_pkt_size) { - em28xx_isocdbg("packet bigger than packet size"); + + if (actual_length <= 0) { + /* NOTE: happens very often with isoc transfers */ + /* em28xx_usbdbg("packet %d is empty",i); - spammy */ continue; } - p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - /* capture type 0 = vbi start capture type 1 = video start capture type 2 = video in progress */ @@ -579,16 +591,20 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) em28xx_isocdbg("VBI START HEADER!!!\n"); dev->cur_field = p[2]; p += 4; - len -= 4; + len = actual_length - 4; } else if (p[0] == 0x88 && p[1] == 0x88 && p[2] == 0x88 && p[3] == 0x88) { /* continuation */ p += 4; - len -= 4; + len = actual_length - 4; } else if (p[0] == 0x22 && p[1] == 0x5a) { /* start video */ p += 4; - len -= 4; + len = actual_length - 4; + } else { + /* NOTE: With bulk transfers, intermediate data packets + * have no continuation header */ + len = actual_length; } vbi_size = dev->vbi_width * dev->vbi_height; @@ -776,7 +792,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, EM28XX_NUM_BUFS, dev->max_pkt_size, EM28XX_NUM_ISOC_PACKETS, - em28xx_isoc_copy_vbi); + em28xx_urb_data_copy_vbi); else rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE, 0, EM28XX_NUM_BUFS,