diff options
author | Frank Schaefer <fschaefer.oss@googlemail.com> | 2012-12-08 11:31:31 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-12-22 20:57:17 -0200 |
commit | 227b7c90671624e0d143e324a3015726282981df (patch) | |
tree | b0d88cf25c16adeb45441575b614398aadb3145e /drivers/media | |
parent | e04c00d985c62a6e1cc6c8048308f3216442f708 (diff) | |
download | linux-227b7c90671624e0d143e324a3015726282981df.tar.bz2 |
[media] em28xx: move the em2710/em2750/em28xx specific frame data processing code to a separate function
em28xx_urb_data_copy() actually consists of two parts:
USB urb processing (checks, data extraction) and frame data packet processing.
Move the latter to a separate function and call it from em28xx_urb_data_copy()
for each data packet.
The em25xx, em2760, em2765 (and likely em277x) chip variants are using a
different frame data format, for which support will be added later with
another function.
This reduces the size of em28xx_urb_data_copy() and makes the code much more
readable. While we're at it, clean up the code a bit (rename some variables to
something more meaningful, improve some comments etc.)
Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-video.c | 170 |
1 files changed, 90 insertions, 80 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index a1f6de0f1b3b..133e6b0a5c7d 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -379,15 +379,90 @@ finish_field_prepare_next(struct em28xx *dev, return buf; } -/* Processes and copies the URB data content (video and VBI data) */ -static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb) +/* + * Process data packet according to the em2710/em2750/em28xx frame data format + */ +static inline void process_frame_data_em28xx(struct em28xx *dev, + unsigned char *data_pkt, + unsigned int data_len) { - struct em28xx_buffer *buf, *vbi_buf; + struct em28xx_buffer *buf = dev->usb_ctl.vid_buf; + struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf; struct em28xx_dmaqueue *dma_q = &dev->vidq; struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; - int xfer_bulk, num_packets, i, rc = 1; - unsigned int actual_length, len = 0; - unsigned char *p; + + /* capture type 0 = vbi start + capture type 1 = vbi in progress + capture type 2 = video start + capture type 3 = video in progress */ + if (data_len >= 4) { + /* NOTE: Headers are always 4 bytes and + * never split across packets */ + if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 && + data_pkt[2] == 0x88 && data_pkt[3] == 0x88) { + /* Continuation */ + data_pkt += 4; + data_len -= 4; + } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) { + /* Field start (VBI mode) */ + dev->capture_type = 0; + dev->vbi_read = 0; + em28xx_isocdbg("VBI START HEADER !!!\n"); + dev->top_field = !(data_pkt[2] & 1); + data_pkt += 4; + data_len -= 4; + } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) { + /* Field start (VBI disabled) */ + dev->capture_type = 2; + em28xx_isocdbg("VIDEO START HEADER !!!\n"); + dev->top_field = !(data_pkt[2] & 1); + data_pkt += 4; + data_len -= 4; + } + } + /* NOTE: With bulk transfers, intermediate data packets + * have no continuation header */ + + if (dev->capture_type == 0) { + vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q); + dev->usb_ctl.vbi_buf = vbi_buf; + dev->capture_type = 1; + } + + if (dev->capture_type == 1) { + int vbi_size = dev->vbi_width * dev->vbi_height; + int vbi_data_len = ((dev->vbi_read + data_len) > vbi_size) ? + (vbi_size - dev->vbi_read) : data_len; + + /* Copy VBI data */ + if (vbi_buf != NULL) + em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len); + dev->vbi_read += vbi_data_len; + + if (vbi_data_len < data_len) { + /* Continue with copying video data */ + dev->capture_type = 2; + data_pkt += vbi_data_len; + data_len -= vbi_data_len; + } + } + + if (dev->capture_type == 2) { + buf = finish_field_prepare_next(dev, buf, dma_q); + dev->usb_ctl.vid_buf = buf; + dev->capture_type = 3; + } + + if (dev->capture_type == 3 && buf != NULL && data_len > 0) + em28xx_copy_video(dev, buf, data_pkt, data_len); +} + +/* Processes and copies the URB data content (video and VBI data) */ +static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb) +{ + int xfer_bulk, num_packets, i; + unsigned char *usb_data_pkt; + unsigned int usb_data_len; if (!dev) return 0; @@ -400,9 +475,6 @@ static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb) xfer_bulk = usb_pipebulk(urb->pipe); - buf = dev->usb_ctl.vid_buf; - vbi_buf = dev->usb_ctl.vbi_buf; - if (xfer_bulk) /* bulk */ num_packets = 1; else /* isoc */ @@ -410,9 +482,9 @@ static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb) for (i = 0; i < num_packets; i++) { if (xfer_bulk) { /* bulk */ - actual_length = urb->actual_length; + usb_data_len = urb->actual_length; - p = urb->transfer_buffer; + usb_data_pkt = urb->transfer_buffer; } else { /* isoc */ if (urb->iso_frame_desc[i].status < 0) { print_err_status(dev, i, @@ -421,87 +493,25 @@ static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb) continue; } - actual_length = urb->iso_frame_desc[i].actual_length; - if (actual_length > dev->max_pkt_size) { + usb_data_len = urb->iso_frame_desc[i].actual_length; + if (usb_data_len > dev->max_pkt_size) { em28xx_isocdbg("packet bigger than packet size"); continue; } - p = urb->transfer_buffer + - urb->iso_frame_desc[i].offset; + usb_data_pkt = urb->transfer_buffer + + urb->iso_frame_desc[i].offset; } - if (actual_length == 0) { + if (usb_data_len == 0) { /* NOTE: happens very often with isoc transfers */ /* em28xx_usbdbg("packet %d is empty",i); - spammy */ continue; } - /* capture type 0 = vbi start - capture type 1 = vbi in progress - capture type 2 = video start - capture type 3 = video in progress */ - len = actual_length; - if (len >= 4) { - /* NOTE: headers are always 4 bytes and - * never split across packets */ - if (p[0] == 0x33 && p[1] == 0x95) { - dev->capture_type = 0; - dev->vbi_read = 0; - em28xx_isocdbg("VBI START HEADER!!!\n"); - dev->top_field = !(p[2] & 1); - p += 4; - len -= 4; - } else if (p[0] == 0x88 && p[1] == 0x88 && - p[2] == 0x88 && p[3] == 0x88) { - /* continuation */ - p += 4; - len -= 4; - } else if (p[0] == 0x22 && p[1] == 0x5a) { - /* start video */ - dev->capture_type = 2; - dev->top_field = !(p[2] & 1); - p += 4; - len -= 4; - } - } - /* NOTE: with bulk transfers, intermediate data packets - * have no continuation header */ - - if (dev->capture_type == 0) { - vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q); - dev->usb_ctl.vbi_buf = vbi_buf; - dev->capture_type = 1; - } - - if (dev->capture_type == 1) { - int vbi_size = dev->vbi_width * dev->vbi_height; - int vbi_data_len = ((dev->vbi_read + len) > vbi_size) ? - (vbi_size - dev->vbi_read) : len; - - /* Copy VBI data */ - if (vbi_buf != NULL) - em28xx_copy_vbi(dev, vbi_buf, p, vbi_data_len); - dev->vbi_read += vbi_data_len; - - if (vbi_data_len < len) { - /* Continue with copying video data */ - dev->capture_type = 2; - p += vbi_data_len; - len -= vbi_data_len; - } - } - - if (dev->capture_type == 2) { - buf = finish_field_prepare_next(dev, buf, dma_q); - dev->usb_ctl.vid_buf = buf; - dev->capture_type = 3; - } - - if (buf != NULL && dev->capture_type == 3 && len > 0) - em28xx_copy_video(dev, buf, p, len); + process_frame_data_em28xx(dev, usb_data_pkt, usb_data_len); } - return rc; + return 1; } |