Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 357154
b: refs/heads/master
c: 227b7c9
h: refs/heads/master
v: v3
  • Loading branch information
Frank Schaefer authored and Mauro Carvalho Chehab committed Dec 22, 2012
1 parent 7231b8c commit 4a96dca
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 81 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e04c00d985c62a6e1cc6c8048308f3216442f708
refs/heads/master: 227b7c90671624e0d143e324a3015726282981df
170 changes: 90 additions & 80 deletions trunk/drivers/media/usb/em28xx/em28xx-video.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -400,19 +475,16 @@ 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 */
num_packets = urb->number_of_packets;

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,
Expand All @@ -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;
}


Expand Down

0 comments on commit 4a96dca

Please sign in to comment.