aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/em28xx/em28xx-video.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-video.c')
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c170
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,
379 return buf; 379 return buf;
380} 380}
381 381
382/* Processes and copies the URB data content (video and VBI data) */ 382/*
383static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb) 383 * Process data packet according to the em2710/em2750/em28xx frame data format
384 */
385static inline void process_frame_data_em28xx(struct em28xx *dev,
386 unsigned char *data_pkt,
387 unsigned int data_len)
384{ 388{
385 struct em28xx_buffer *buf, *vbi_buf; 389 struct em28xx_buffer *buf = dev->usb_ctl.vid_buf;
390 struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf;
386 struct em28xx_dmaqueue *dma_q = &dev->vidq; 391 struct em28xx_dmaqueue *dma_q = &dev->vidq;
387 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; 392 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
388 int xfer_bulk, num_packets, i, rc = 1; 393
389 unsigned int actual_length, len = 0; 394 /* capture type 0 = vbi start
390 unsigned char *p; 395 capture type 1 = vbi in progress
396 capture type 2 = video start
397 capture type 3 = video in progress */
398 if (data_len >= 4) {
399 /* NOTE: Headers are always 4 bytes and
400 * never split across packets */
401 if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
402 data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
403 /* Continuation */
404 data_pkt += 4;
405 data_len -= 4;
406 } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) {
407 /* Field start (VBI mode) */
408 dev->capture_type = 0;
409 dev->vbi_read = 0;
410 em28xx_isocdbg("VBI START HEADER !!!\n");
411 dev->top_field = !(data_pkt[2] & 1);
412 data_pkt += 4;
413 data_len -= 4;
414 } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) {
415 /* Field start (VBI disabled) */
416 dev->capture_type = 2;
417 em28xx_isocdbg("VIDEO START HEADER !!!\n");
418 dev->top_field = !(data_pkt[2] & 1);
419 data_pkt += 4;
420 data_len -= 4;
421 }
422 }
423 /* NOTE: With bulk transfers, intermediate data packets
424 * have no continuation header */
425
426 if (dev->capture_type == 0) {
427 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
428 dev->usb_ctl.vbi_buf = vbi_buf;
429 dev->capture_type = 1;
430 }
431
432 if (dev->capture_type == 1) {
433 int vbi_size = dev->vbi_width * dev->vbi_height;
434 int vbi_data_len = ((dev->vbi_read + data_len) > vbi_size) ?
435 (vbi_size - dev->vbi_read) : data_len;
436
437 /* Copy VBI data */
438 if (vbi_buf != NULL)
439 em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
440 dev->vbi_read += vbi_data_len;
441
442 if (vbi_data_len < data_len) {
443 /* Continue with copying video data */
444 dev->capture_type = 2;
445 data_pkt += vbi_data_len;
446 data_len -= vbi_data_len;
447 }
448 }
449
450 if (dev->capture_type == 2) {
451 buf = finish_field_prepare_next(dev, buf, dma_q);
452 dev->usb_ctl.vid_buf = buf;
453 dev->capture_type = 3;
454 }
455
456 if (dev->capture_type == 3 && buf != NULL && data_len > 0)
457 em28xx_copy_video(dev, buf, data_pkt, data_len);
458}
459
460/* Processes and copies the URB data content (video and VBI data) */
461static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
462{
463 int xfer_bulk, num_packets, i;
464 unsigned char *usb_data_pkt;
465 unsigned int usb_data_len;
391 466
392 if (!dev) 467 if (!dev)
393 return 0; 468 return 0;
@@ -400,9 +475,6 @@ static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
400 475
401 xfer_bulk = usb_pipebulk(urb->pipe); 476 xfer_bulk = usb_pipebulk(urb->pipe);
402 477
403 buf = dev->usb_ctl.vid_buf;
404 vbi_buf = dev->usb_ctl.vbi_buf;
405
406 if (xfer_bulk) /* bulk */ 478 if (xfer_bulk) /* bulk */
407 num_packets = 1; 479 num_packets = 1;
408 else /* isoc */ 480 else /* isoc */
@@ -410,9 +482,9 @@ static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
410 482
411 for (i = 0; i < num_packets; i++) { 483 for (i = 0; i < num_packets; i++) {
412 if (xfer_bulk) { /* bulk */ 484 if (xfer_bulk) { /* bulk */
413 actual_length = urb->actual_length; 485 usb_data_len = urb->actual_length;
414 486
415 p = urb->transfer_buffer; 487 usb_data_pkt = urb->transfer_buffer;
416 } else { /* isoc */ 488 } else { /* isoc */
417 if (urb->iso_frame_desc[i].status < 0) { 489 if (urb->iso_frame_desc[i].status < 0) {
418 print_err_status(dev, i, 490 print_err_status(dev, i,
@@ -421,87 +493,25 @@ static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
421 continue; 493 continue;
422 } 494 }
423 495
424 actual_length = urb->iso_frame_desc[i].actual_length; 496 usb_data_len = urb->iso_frame_desc[i].actual_length;
425 if (actual_length > dev->max_pkt_size) { 497 if (usb_data_len > dev->max_pkt_size) {
426 em28xx_isocdbg("packet bigger than packet size"); 498 em28xx_isocdbg("packet bigger than packet size");
427 continue; 499 continue;
428 } 500 }
429 501
430 p = urb->transfer_buffer + 502 usb_data_pkt = urb->transfer_buffer +
431 urb->iso_frame_desc[i].offset; 503 urb->iso_frame_desc[i].offset;
432 } 504 }
433 505
434 if (actual_length == 0) { 506 if (usb_data_len == 0) {
435 /* NOTE: happens very often with isoc transfers */ 507 /* NOTE: happens very often with isoc transfers */
436 /* em28xx_usbdbg("packet %d is empty",i); - spammy */ 508 /* em28xx_usbdbg("packet %d is empty",i); - spammy */
437 continue; 509 continue;
438 } 510 }
439 511
440 /* capture type 0 = vbi start 512 process_frame_data_em28xx(dev, usb_data_pkt, usb_data_len);
441 capture type 1 = vbi in progress
442 capture type 2 = video start
443 capture type 3 = video in progress */
444 len = actual_length;
445 if (len >= 4) {
446 /* NOTE: headers are always 4 bytes and
447 * never split across packets */
448 if (p[0] == 0x33 && p[1] == 0x95) {
449 dev->capture_type = 0;
450 dev->vbi_read = 0;
451 em28xx_isocdbg("VBI START HEADER!!!\n");
452 dev->top_field = !(p[2] & 1);
453 p += 4;
454 len -= 4;
455 } else if (p[0] == 0x88 && p[1] == 0x88 &&
456 p[2] == 0x88 && p[3] == 0x88) {
457 /* continuation */
458 p += 4;
459 len -= 4;
460 } else if (p[0] == 0x22 && p[1] == 0x5a) {
461 /* start video */
462 dev->capture_type = 2;
463 dev->top_field = !(p[2] & 1);
464 p += 4;
465 len -= 4;
466 }
467 }
468 /* NOTE: with bulk transfers, intermediate data packets
469 * have no continuation header */
470
471 if (dev->capture_type == 0) {
472 vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
473 dev->usb_ctl.vbi_buf = vbi_buf;
474 dev->capture_type = 1;
475 }
476
477 if (dev->capture_type == 1) {
478 int vbi_size = dev->vbi_width * dev->vbi_height;
479 int vbi_data_len = ((dev->vbi_read + len) > vbi_size) ?
480 (vbi_size - dev->vbi_read) : len;
481
482 /* Copy VBI data */
483 if (vbi_buf != NULL)
484 em28xx_copy_vbi(dev, vbi_buf, p, vbi_data_len);
485 dev->vbi_read += vbi_data_len;
486
487 if (vbi_data_len < len) {
488 /* Continue with copying video data */
489 dev->capture_type = 2;
490 p += vbi_data_len;
491 len -= vbi_data_len;
492 }
493 }
494
495 if (dev->capture_type == 2) {
496 buf = finish_field_prepare_next(dev, buf, dma_q);
497 dev->usb_ctl.vid_buf = buf;
498 dev->capture_type = 3;
499 }
500
501 if (buf != NULL && dev->capture_type == 3 && len > 0)
502 em28xx_copy_video(dev, buf, p, len);
503 } 513 }
504 return rc; 514 return 1;
505} 515}
506 516
507 517