|
@@ -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;
|
|
|
}
|
|
|
|
|
|
|