mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-02-03 09:34:42 +00:00
[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>
This commit is contained in:
parent
e04c00d985
commit
227b7c9067
@ -379,15 +379,90 @@ finish_field_prepare_next(struct em28xx *dev,
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 = 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;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct em28xx_buffer *buf, *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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user