summaryrefslogtreecommitdiffstats
path: root/drivers/staging/media/easycap/easycap_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/media/easycap/easycap_main.c')
-rw-r--r--drivers/staging/media/easycap/easycap_main.c4239
1 files changed, 0 insertions, 4239 deletions
diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c
deleted file mode 100644
index 8269c77dbf7d..000000000000
--- a/drivers/staging/media/easycap/easycap_main.c
+++ /dev/null
@@ -1,4239 +0,0 @@
-/******************************************************************************
-* *
-* easycap_main.c *
-* *
-* Video driver for EasyCAP USB2.0 Video Capture Device DC60 *
-* *
-* *
-******************************************************************************/
-/*
- *
- * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
- *
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
-*/
-/*****************************************************************************/
-
-#include "easycap.h"
-#include <linux/usb/audio.h>
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
-MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
-MODULE_VERSION(EASYCAP_DRIVER_VERSION);
-
-#ifdef CONFIG_EASYCAP_DEBUG
-int easycap_debug;
-module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9");
-#endif /* CONFIG_EASYCAP_DEBUG */
-
-bool easycap_readback;
-module_param_named(readback, easycap_readback, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(readback, "read back written registers: (default false)");
-
-static int easycap_bars = 1;
-module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(bars,
- "Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
-
-static int easycap_gain = 16;
-module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31");
-
-static bool easycap_ntsc;
-module_param_named(ntsc, easycap_ntsc, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ntsc, "NTSC default encoding (default PAL)");
-
-
-
-struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
-static struct mutex mutex_dongle;
-static void easycap_complete(struct urb *purb);
-static int reset(struct easycap *peasycap);
-static int field2frame(struct easycap *peasycap);
-static int redaub(struct easycap *peasycap,
- void *pad, void *pex, int much, int more,
- u8 mask, u8 margin, bool isuy);
-
-const char *strerror(int err)
-{
-#define ERRNOSTR(_e) case _e: return # _e
- switch (err) {
- case 0: return "OK";
- ERRNOSTR(ENOMEM);
- ERRNOSTR(ENODEV);
- ERRNOSTR(ENXIO);
- ERRNOSTR(EINVAL);
- ERRNOSTR(EAGAIN);
- ERRNOSTR(EFBIG);
- ERRNOSTR(EPIPE);
- ERRNOSTR(EMSGSIZE);
- ERRNOSTR(ENOSPC);
- ERRNOSTR(EINPROGRESS);
- ERRNOSTR(ENOSR);
- ERRNOSTR(EOVERFLOW);
- ERRNOSTR(EPROTO);
- ERRNOSTR(EILSEQ);
- ERRNOSTR(ETIMEDOUT);
- ERRNOSTR(EOPNOTSUPP);
- ERRNOSTR(EPFNOSUPPORT);
- ERRNOSTR(EAFNOSUPPORT);
- ERRNOSTR(EADDRINUSE);
- ERRNOSTR(EADDRNOTAVAIL);
- ERRNOSTR(ENOBUFS);
- ERRNOSTR(EISCONN);
- ERRNOSTR(ENOTCONN);
- ERRNOSTR(ESHUTDOWN);
- ERRNOSTR(ENOENT);
- ERRNOSTR(ECONNRESET);
- ERRNOSTR(ETIME);
- ERRNOSTR(ECOMM);
- ERRNOSTR(EREMOTEIO);
- ERRNOSTR(EXDEV);
- ERRNOSTR(EPERM);
- default: return "unknown";
- }
-
-#undef ERRNOSTR
-}
-
-/****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
-*/
-/*---------------------------------------------------------------------------*/
-int easycap_isdongle(struct easycap *peasycap)
-{
- int k;
- if (!peasycap)
- return -2;
- for (k = 0; k < DONGLE_MANY; k++) {
- if (easycapdc60_dongle[k].peasycap == peasycap) {
- peasycap->isdongle = k;
- return k;
- }
- }
- return -1;
-}
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-static int easycap_open(struct inode *inode, struct file *file)
-{
- struct video_device *pvideo_device;
- struct easycap *peasycap;
- int rc;
-
- JOT(4, "\n");
- SAY("==========OPEN=========\n");
-
- pvideo_device = video_devdata(file);
- if (!pvideo_device) {
- SAY("ERROR: pvideo_device is NULL.\n");
- return -EFAULT;
- }
- peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
- if (!peasycap) {
- SAY("ERROR: peasycap is NULL\n");
- return -EFAULT;
- }
- if (!peasycap->pusb_device) {
- SAM("ERROR: peasycap->pusb_device is NULL\n");
- return -EFAULT;
- }
-
- JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
-
- file->private_data = peasycap;
- rc = easycap_wakeup_device(peasycap->pusb_device);
- if (rc) {
- SAM("ERROR: wakeup_device() rc = %i\n", rc);
- if (-ENODEV == rc)
- SAM("ERROR: wakeup_device() returned -ENODEV\n");
- else
- SAM("ERROR: wakeup_device() rc = %i\n", rc);
- return rc;
- }
- JOM(8, "wakeup_device() OK\n");
- peasycap->input = 0;
- rc = reset(peasycap);
- if (rc) {
- SAM("ERROR: reset() rc = %i\n", rc);
- return -EFAULT;
- }
- return 0;
-}
-
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- * RESET THE HARDWARE TO ITS REFERENCE STATE.
- *
- * THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
- * A BAD VIDEO FRAME SIZE.
-*/
-/*---------------------------------------------------------------------------*/
-static int reset(struct easycap *peasycap)
-{
- struct easycap_standard const *peasycap_standard;
- int fmtidx, input, rate;
- bool ntsc, other;
- int rc;
-
- if (!peasycap) {
- SAY("ERROR: peasycap is NULL\n");
- return -EFAULT;
- }
- input = peasycap->input;
-
-/*---------------------------------------------------------------------------*/
-/*
- * IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
- * FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL. THIS IS ESSENTIAL FOR
- * gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
- * A SWITCH BETWEEN PAL AND NTSC.
- *
- * FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
- * COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
-*/
-/*---------------------------------------------------------------------------*/
- other = false;
- JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc);
-
- rate = ready_saa(peasycap->pusb_device);
- if (rate < 0) {
- JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
- ntsc = !peasycap->ntsc;
- JOM(8, "... trying %s ..\n", ntsc ? "NTSC" : "PAL");
- rc = setup_stk(peasycap->pusb_device, ntsc);
- if (rc) {
- SAM("ERROR: setup_stk() rc = %i\n", rc);
- return -EFAULT;
- }
- rc = setup_saa(peasycap->pusb_device, ntsc);
- if (rc) {
- SAM("ERROR: setup_saa() rc = %i\n", rc);
- return -EFAULT;
- }
-
- rate = ready_saa(peasycap->pusb_device);
- if (rate < 0) {
- JOM(8, "not ready to capture after %i ms\n", PATIENCE);
- JOM(8, "... saa register 0x1F has 0x%02X\n",
- read_saa(peasycap->pusb_device, 0x1F));
- ntsc = peasycap->ntsc;
- } else {
- JOM(8, "... success at second try: %i=rate\n", rate);
- ntsc = (0 < (rate/2)) ? true : false ;
- other = true;
- }
- } else {
- JOM(8, "... success at first try: %i=rate\n", rate);
- ntsc = (0 < rate/2) ? true : false ;
- }
- JOM(8, "ntsc=%d\n", ntsc);
-/*---------------------------------------------------------------------------*/
-
- rc = setup_stk(peasycap->pusb_device, ntsc);
- if (rc) {
- SAM("ERROR: setup_stk() rc = %i\n", rc);
- return -EFAULT;
- }
- rc = setup_saa(peasycap->pusb_device, ntsc);
- if (rc) {
- SAM("ERROR: setup_saa() rc = %i\n", rc);
- return -EFAULT;
- }
-
- memset(peasycap->merit, 0, sizeof(peasycap->merit));
-
- peasycap->video_eof = 0;
- peasycap->audio_eof = 0;
-/*---------------------------------------------------------------------------*/
-/*
- * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
- *
- * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
-*/
-/*---------------------------------------------------------------------------*/
- peasycap->input = -8192;
- peasycap->standard_offset = -8192;
- fmtidx = ntsc ? NTSC_M : PAL_BGHIN;
- if (other) {
- peasycap_standard = &easycap_standard[0];
- while (0xFFFF != peasycap_standard->mask) {
- if (fmtidx == peasycap_standard->v4l2_standard.index) {
- peasycap->inputset[input].standard_offset =
- peasycap_standard - easycap_standard;
- break;
- }
- peasycap_standard++;
- }
- if (0xFFFF == peasycap_standard->mask) {
- SAM("ERROR: standard not found\n");
- return -EINVAL;
- }
- JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
- peasycap->inputset[input].standard_offset, input);
- }
- peasycap->format_offset = -8192;
- peasycap->brightness = -8192;
- peasycap->contrast = -8192;
- peasycap->saturation = -8192;
- peasycap->hue = -8192;
-
- rc = easycap_newinput(peasycap, input);
-
- if (rc) {
- SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
- return -EFAULT;
- }
- JOM(4, "restored input, standard and format\n");
-
- JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc);
-
- if (0 > peasycap->input) {
- SAM("MISTAKE: %i=peasycap->input\n", peasycap->input);
- return -ENOENT;
- }
- if (0 > peasycap->standard_offset) {
- SAM("MISTAKE: %i=peasycap->standard_offset\n",
- peasycap->standard_offset);
- return -ENOENT;
- }
- if (0 > peasycap->format_offset) {
- SAM("MISTAKE: %i=peasycap->format_offset\n",
- peasycap->format_offset);
- return -ENOENT;
- }
- if (0 > peasycap->brightness) {
- SAM("MISTAKE: %i=peasycap->brightness\n",
- peasycap->brightness);
- return -ENOENT;
- }
- if (0 > peasycap->contrast) {
- SAM("MISTAKE: %i=peasycap->contrast\n", peasycap->contrast);
- return -ENOENT;
- }
- if (0 > peasycap->saturation) {
- SAM("MISTAKE: %i=peasycap->saturation\n",
- peasycap->saturation);
- return -ENOENT;
- }
- if (0 > peasycap->hue) {
- SAM("MISTAKE: %i=peasycap->hue\n", peasycap->hue);
- return -ENOENT;
- }
- return 0;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- * IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
- * OTHERWISE:
- * KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
- * _read AND _fill POINTERS.
- * SELECT THE NEW INPUT.
- * ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
- * ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
- * RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
- *
- * NOTE:
- * THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
- * SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
-*/
-/*---------------------------------------------------------------------------*/
-int easycap_newinput(struct easycap *peasycap, int input)
-{
- int rc, k, m, mood, off;
- int inputnow, video_idlenow, audio_idlenow;
- bool resubmit;
-
- if (!peasycap) {
- SAY("ERROR: peasycap is NULL\n");
- return -EFAULT;
- }
- JOM(8, "%i=input sought\n", input);
-
- if (0 > input && INPUT_MANY <= input)
- return -ENOENT;
- inputnow = peasycap->input;
- if (input == inputnow)
- return 0;
-/*---------------------------------------------------------------------------*/
-/*
- * IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
- * STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
- * IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
- * ROUTINE.
-*/
-/*---------------------------------------------------------------------------*/
- video_idlenow = peasycap->video_idle;
- audio_idlenow = peasycap->audio_idle;
-
- peasycap->video_idle = 1;
- peasycap->audio_idle = 1;
- if (peasycap->video_isoc_streaming) {
- resubmit = true;
- easycap_video_kill_urbs(peasycap);
- } else {
- resubmit = false;
- }
-/*---------------------------------------------------------------------------*/
- if (!peasycap->pusb_device) {
- SAM("ERROR: peasycap->pusb_device is NULL\n");
- return -ENODEV;
- }
- rc = usb_set_interface(peasycap->pusb_device,
- peasycap->video_interface,
- peasycap->video_altsetting_off);
- if (rc) {
- SAM("ERROR: usb_set_interface() rc = %i\n", rc);
- return -EFAULT;
- }
- rc = stop_100(peasycap->pusb_device);
- if (rc) {
- SAM("ERROR: stop_100() rc = %i\n", rc);
- return -EFAULT;
- }
- for (k = 0; k < FIELD_BUFFER_MANY; k++) {
- for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
- memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
- }
- for (k = 0; k < FRAME_BUFFER_MANY; k++) {
- for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
- memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
- }
- peasycap->field_page = 0;
- peasycap->field_read = 0;
- peasycap->field_fill = 0;
-
- peasycap->frame_read = 0;
- peasycap->frame_fill = 0;
- for (k = 0; k < peasycap->input; k++) {
- (peasycap->frame_fill)++;
- if (peasycap->frame_buffer_many <= peasycap->frame_fill)
- peasycap->frame_fill = 0;
- }
- peasycap->input = input;
- select_input(peasycap->pusb_device, peasycap->input, 9);
-/*---------------------------------------------------------------------------*/
- if (input == peasycap->inputset[input].input) {
- off = peasycap->inputset[input].standard_offset;
- if (off != peasycap->standard_offset) {
- rc = adjust_standard(peasycap,
- easycap_standard[off].v4l2_standard.id);
- if (rc) {
- SAM("ERROR: adjust_standard() rc = %i\n", rc);
- return -EFAULT;
- }
- JOM(8, "%i=peasycap->standard_offset\n",
- peasycap->standard_offset);
- } else {
- JOM(8, "%i=peasycap->standard_offset unchanged\n",
- peasycap->standard_offset);
- }
- off = peasycap->inputset[input].format_offset;
- if (off != peasycap->format_offset) {
- struct v4l2_pix_format *pix =
- &easycap_format[off].v4l2_format.fmt.pix;
- rc = adjust_format(peasycap,
- pix->width, pix->height,
- pix->pixelformat, pix->field, false);
- if (0 > rc) {
- SAM("ERROR: adjust_format() rc = %i\n", rc);
- return -EFAULT;
- }
- JOM(8, "%i=peasycap->format_offset\n",
- peasycap->format_offset);
- } else {
- JOM(8, "%i=peasycap->format_offset unchanged\n",
- peasycap->format_offset);
- }
- mood = peasycap->inputset[input].brightness;
- if (mood != peasycap->brightness) {
- rc = adjust_brightness(peasycap, mood);
- if (rc) {
- SAM("ERROR: adjust_brightness rc = %i\n", rc);
- return -EFAULT;
- }
- JOM(8, "%i=peasycap->brightness\n",
- peasycap->brightness);
- }
- mood = peasycap->inputset[input].contrast;
- if (mood != peasycap->contrast) {
- rc = adjust_contrast(peasycap, mood);
- if (rc) {
- SAM("ERROR: adjust_contrast rc = %i\n", rc);
- return -EFAULT;
- }
- JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
- }
- mood = peasycap->inputset[input].saturation;
- if (mood != peasycap->saturation) {
- rc = adjust_saturation(peasycap, mood);
- if (rc) {
- SAM("ERROR: adjust_saturation rc = %i\n", rc);
- return -EFAULT;
- }
- JOM(8, "%i=peasycap->saturation\n",
- peasycap->saturation);
- }
- mood = peasycap->inputset[input].hue;
- if (mood != peasycap->hue) {
- rc = adjust_hue(peasycap, mood);
- if (rc) {
- SAM("ERROR: adjust_hue rc = %i\n", rc);
- return -EFAULT;
- }
- JOM(8, "%i=peasycap->hue\n", peasycap->hue);
- }
- } else {
- SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
- return -ENOENT;
- }
-/*---------------------------------------------------------------------------*/
- if (!peasycap->pusb_device) {
- SAM("ERROR: peasycap->pusb_device is NULL\n");
- return -ENODEV;
- }
- rc = usb_set_interface(peasycap->pusb_device,
- peasycap->video_interface,
- peasycap->video_altsetting_on);
- if (rc) {
- SAM("ERROR: usb_set_interface() rc = %i\n", rc);
- return -EFAULT;
- }
- rc = start_100(peasycap->pusb_device);
- if (rc) {
- SAM("ERROR: start_100() rc = %i\n", rc);
- return -EFAULT;
- }
- if (resubmit)
- easycap_video_submit_urbs(peasycap);
-
- peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
- peasycap->video_idle = video_idlenow;
- peasycap->audio_idle = audio_idlenow;
- peasycap->video_junk = 0;
-
- return 0;
-}
-/*****************************************************************************/
-int easycap_video_submit_urbs(struct easycap *peasycap)
-{
- struct data_urb *pdata_urb;
- struct urb *purb;
- struct list_head *plist_head;
- int j, isbad, nospc, m, rc;
- int isbuf;
-
- if (!peasycap) {
- SAY("ERROR: peasycap is NULL\n");
- return -EFAULT;
- }
-
- if (!peasycap->purb_video_head) {
- SAY("ERROR: peasycap->urb_video_head uninitialized\n");
- return -EFAULT;
- }
- if (!peasycap->pusb_device) {
- SAY("ERROR: peasycap->pusb_device is NULL\n");
- return -ENODEV;
- }
- if (!peasycap->video_isoc_streaming) {
- JOM(4, "submission of all video urbs\n");
- isbad = 0; nospc = 0; m = 0;
- list_for_each(plist_head, (peasycap->purb_video_head)) {
- pdata_urb = list_entry(plist_head,
- struct data_urb, list_head);
- if (pdata_urb && pdata_urb->purb) {
- purb = pdata_urb->purb;
- isbuf = pdata_urb->isbuf;
- purb->interval = 1;
- purb->dev = peasycap->pusb_device;
- purb->pipe =
- usb_rcvisocpipe(peasycap->pusb_device,
- peasycap->video_endpointnumber);
- purb->transfer_flags = URB_ISO_ASAP;
- purb->transfer_buffer =
- peasycap->video_isoc_buffer[isbuf].pgo;
- purb->transfer_buffer_length =
- peasycap->video_isoc_buffer_size;
- purb->complete = easycap_complete;
- purb->context = peasycap;
- purb->start_frame = 0;
- purb->number_of_packets =
- peasycap->video_isoc_framesperdesc;
-
- for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
- purb->iso_frame_desc[j]. offset =
- j * peasycap->video_isoc_maxframesize;
- purb->iso_frame_desc[j]. length =
- peasycap->video_isoc_maxframesize;
- }
-
- rc = usb_submit_urb(purb, GFP_KERNEL);
- if (rc) {
- isbad++;
- SAM("ERROR: usb_submit_urb() failed "
- "for urb with rc:-%s\n",
- strerror(rc));
- if (rc == -ENOSPC)
- nospc++;
- } else {
- m++;
- }
- } else {
- isbad++;
- }
- }
- if (nospc) {
- SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
- SAM("..... possibly inadequate USB bandwidth\n");
- peasycap->video_eof = 1;
- }
-
- if (isbad)
- easycap_video_kill_urbs(peasycap);
- else
- peasycap->video_isoc_streaming = 1;
- } else {
- JOM(4, "already streaming video urbs\n");
- }
- return 0;
-}
-/*****************************************************************************/
-int easycap_audio_kill_urbs(struct easycap *peasycap)
-{
- int m;
- struct list_head *plist_head;
- struct data_urb *pdata_urb;
-
- if (!peasycap->audio_isoc_streaming)
- return 0;
-
- if (!peasycap->purb_audio_head) {
- SAM("ERROR: peasycap->purb_audio_head is NULL\n");
- return -EFAULT;
- }
-
- peasycap->audio_isoc_streaming = 0;
- m = 0;
- list_for_each(plist_head, peasycap->purb_audio_head) {
- pdata_urb = list_entry(plist_head, struct data_urb, list_head);
- if (pdata_urb && pdata_urb->purb) {
- usb_kill_urb(pdata_urb->purb);
- m++;
- }
- }
-
- JOM(4, "%i audio urbs killed\n", m);
-
- return 0;
-}
-int easycap_video_kill_urbs(struct easycap *peasycap)
-{
- int m;
- struct list_head *plist_head;
- struct data_urb *pdata_urb;
-
- if (!peasycap->video_isoc_streaming)
- return 0;
-
- if (!peasycap->purb_video_head) {
- SAM("ERROR: peasycap->purb_video_head is NULL\n");
- return -EFAULT;
- }
-
- peasycap->video_isoc_streaming = 0;
- JOM(4, "killing video urbs\n");
- m = 0;
- list_for_each(plist_head, (peasycap->purb_video_head)) {
- pdata_urb = list_entry(plist_head, struct data_urb, list_head);
- if (pdata_urb && pdata_urb->purb) {
- usb_kill_urb(pdata_urb->purb);
- m++;
- }
- }
- JOM(4, "%i video urbs killed\n", m);
-
- return 0;
-}
-/****************************************************************************/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-/*--------------------------------------------------------------------------*/
-static int easycap_open_noinode(struct file *file)
-{
- return easycap_open(NULL, file);
-}
-
-static int videodev_release(struct video_device *pvideo_device)
-{
- struct easycap *peasycap;
-
- peasycap = video_get_drvdata(pvideo_device);
- if (!peasycap) {
- SAY("ERROR: peasycap is NULL\n");
- SAY("ending unsuccessfully\n");
- return -EFAULT;
- }
- if (easycap_video_kill_urbs(peasycap)) {
- SAM("ERROR: easycap_video_kill_urbs() failed\n");
- return -EFAULT;
- }
- JOM(4, "ending successfully\n");
- return 0;
-}
-
-/*****************************************************************************/
-static unsigned int easycap_poll(struct file *file, poll_table *wait)
-{
- struct easycap *peasycap;
- int rc, kd;
-
- JOT(8, "\n");
-
- if (NULL == ((poll_table *)wait))
- JOT(8, "WARNING: poll table pointer is NULL ... continuing\n");
- if (!file) {
- SAY("ERROR: file pointer is NULL\n");
- return -ERESTARTSYS;
- }
- peasycap = file->private_data;
- if (!peasycap) {
- SAY("ERROR: peasycap is NULL\n");
- return -EFAULT;
- }
- if (!peasycap->pusb_device) {
- SAY("ERROR: peasycap->pusb_device is NULL\n");
- return -EFAULT;
- }
-/*---------------------------------------------------------------------------*/
- kd = easycap_isdongle(peasycap);
- if (0 <= kd && DONGLE_MANY > kd) {
- if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
- SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
- return -ERESTARTSYS;
- }
- JOM(4, "locked dongle[%i].mutex_video\n", kd);
- /*
- * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
- * peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
- * IF NECESSARY, BAIL OUT.
- */
- if (kd != easycap_isdongle(peasycap)) {
- mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
- return -ERESTARTSYS;
- }
- if (!file) {
- SAY("ERROR: file is NULL\n");
- mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
- return -ERESTARTSYS;
- }
- peasycap = file->private_data;
- if (!peasycap) {
- SAY("ERROR: peasycap is NULL\n");
- mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
- return -ERESTARTSYS;
- }
- if (!peasycap->pusb_device) {
- SAM("ERROR: peasycap->pusb_device is NULL\n");
- mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
- return -ERESTARTSYS;
- }
- } else
- /*
- * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
- * BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
- * HAVE FAILED. BAIL OUT.
- */
- return -ERESTARTSYS;
-/*---------------------------------------------------------------------------*/
- rc = easycap_video_dqbuf(peasycap, 0);
- peasycap->polled = 1;
- mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
- if (rc)
- return POLLERR;
-
- return POLLIN | POLLRDNORM;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
- */
-/*---------------------------------------------------------------------------*/
-int easycap_video_dqbuf(struct easycap *peasycap, int mode)
-{
- int input, ifield, miss, rc;
-
-
- if (!peasycap) {
- SAY("ERROR: peasycap is NULL\n");
- return -EFAULT;
- }
- if (!peasycap->pusb_device) {
- SAY("ERROR: peasycap->pusb_device is NULL\n");
- return -EFAULT;
- }
- ifield = 0;
- JOM(8, "%i=ifield\n", ifield);
-/*---------------------------------------------------------------------------*/
-/*
- * CHECK FOR LOST INPUT SIGNAL.
- *
- * FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
- * IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
- * RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
- * IS FLYWHEELING ON INPUT 0. THE UPSHOT IS:
- *
- * INPUT 0 PLUGGED, INPUT 4 PLUGGED => SCREEN 0 OK, SCREEN 4 OK
- * INPUT 0 PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK, SCREEN 4 BLACK
- * INPUT 0 UNPLUGGED, INPUT 4 PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
- * INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
-*/
-/*---------------------------------------------------------------------------*/
- input = peasycap->input;
- if (0 <= input && INPUT_MANY > input) {
- rc = read_saa(peasycap->pusb_device, 0x1F);
- if (0 <= rc) {
- if (rc & 0x40)
- peasycap->lost[input] += 1;
- else
- peasycap->lost[input] -= 2;
-
- if (0 > peasycap->lost[input])
- peasycap->lost[input] = 0;
- else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
- peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
- }
- }
-/*---------------------------------------------------------------------------*/
-/*
- * WAIT FOR FIELD ifield (0 => TOP, 1 => BOTTOM)
- */
-/*---------------------------------------------------------------------------*/
- miss = 0;
- while ((peasycap->field_read == peasycap->field_fill) ||
- (0 != (0xFF00 & peasycap->field_buffer
- [peasycap->field_read][0].kount)) ||
- (ifield != (0x00FF & peasycap->field_buffer
- [peasycap->field_read][0].kount))) {
- if (mode)
- return -EAGAIN;
-
- JOM(8, "first wait on wq_video, %i=field_read %i=field_fill\n",
- peasycap->field_read, peasycap->field_fill);
-
- if (0 != (wait_event_interruptible(peasycap->wq_video,
- (peasycap->video_idle || peasycap->video_eof ||
- ((peasycap->field_read != peasycap->field_fill) &&
- (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
- (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
- SAM("aborted by signal\n");
- return -EIO;
- }
- if (peasycap->video_idle) {
- JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
- peasycap->video_idle);
- return -EAGAIN;
- }
- if (peasycap->video_eof) {
- JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
- #if defined(PERSEVERE)
- if (1 == peasycap->status) {
- JOM(8, "persevering ...\n");
- peasycap->video_eof = 0;
- peasycap->audio_eof = 0;
- if (0 != reset(peasycap)) {
- JOM(8, " ... failed returning -EIO\n");
- peasycap->video_eof = 1;
- peasycap->audio_eof = 1;
- easycap_video_kill_urbs(peasycap);
- return -EIO;
- }
- peasycap->status = 0;
- JOM(8, " ... OK returning -EAGAIN\n");
- return -EAGAIN;
- }
- #endif /*PERSEVERE*/
- peasycap->video_eof = 1;
- peasycap->audio_eof = 1;
- easycap_video_kill_urbs(peasycap);
- JOM(8, "returning -EIO\n");
- return -EIO;
- }
- miss++;
- }
- JOM(8, "first awakening on wq_video after %i waits\n", miss);
-
- rc = field2frame(peasycap);
- if (rc)
- SAM("ERROR: field2frame() rc = %i\n", rc);
-/*---------------------------------------------------------------------------*/
-/*
- * WAIT FOR THE OTHER FIELD
- */
-/*---------------------------------------------------------------------------*/
- if (ifield)
- ifield = 0;
- else
- ifield = 1;
- miss = 0;
- while ((peasycap->field_read == peasycap->field_fill) ||
- (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) ||
- (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) {
- if (mode)
- return -EAGAIN;
-
- JOM(8, "second wait on wq_video %i=field_read %i=field_fill\n",
- peasycap->field_read, peasycap->field_fill);
- if (0 != (wait_event_interruptible(peasycap->wq_video,
- (peasycap->video_idle || peasycap->video_eof ||
- ((peasycap->field_read != peasycap->field_fill) &&
- (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
- (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
- SAM("aborted by signal\n");
- return -EIO;
- }
- if (peasycap->video_idle) {
- JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
- peasycap->video_idle);
- return -EAGAIN;
- }
- if (peasycap->video_eof) {
- JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
-#if defined(PERSEVERE)
- if (1 == peasycap->status) {
- JOM(8, "persevering ...\n");
- peasycap->video_eof = 0;
- peasycap->audio_eof = 0;
- if (0 != reset(peasycap)) {
- JOM(8, " ... failed returning -EIO\n");
- peasycap->video_eof = 1;
- peasycap->audio_eof = 1;
- easycap_video_kill_urbs(peasycap);
- return -EIO;
- }
- peasycap->status = 0;
- JOM(8, " ... OK ... returning -EAGAIN\n");
- return -EAGAIN;
- }
-#endif /*PERSEVERE*/
- peasycap->video_eof = 1;
- peasycap->audio_eof = 1;
- easycap_video_kill_urbs(peasycap);
- JOM(8, "returning -EIO\n");
- return -EIO;
- }
- miss++;
- }
- JOM(8, "second awakening on wq_video after %i waits\n", miss);
-
- rc = field2frame(peasycap);
- if (rc)
- SAM("ERROR: field2frame() rc = %i\n", rc);
-/*---------------------------------------------------------------------------*/
-/*
- * WASTE THIS FRAME
-*/
-/*---------------------------------------------------------------------------*/
- if (peasycap->skip) {
- peasycap->skipped++;
- if (peasycap->skip != peasycap->skipped)
- return peasycap->skip - peasycap->skipped;
- else
- peasycap->skipped = 0;
- }
-/*---------------------------------------------------------------------------*/
- peasycap->frame_read = peasycap->frame_fill;
- peasycap->queued[peasycap->frame_read] = 0;
- peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE;
-
- peasycap->frame_fill++;
- if (peasycap->frame_buffer_many <= peasycap->frame_fill)
- peasycap->frame_fill = 0;
-
- if (0x01 & easycap_standard[peasycap->standard_offset].mask)
- peasycap->frame_buffer[peasycap->frame_read][0].kount =
- V4L2_FIELD_TOP;
- else
- peasycap->frame_buffer[peasycap->frame_read][0].kount =
- V4L2_FIELD_BOTTOM;
-
-
- JOM(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read);
- JOM(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill);
-
- return 0;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
- * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
- *
- * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
- * odd==false IS TRANSFERRED TO THE FRAME BUFFER.
- *
- */
-/*---------------------------------------------------------------------------*/
-static int field2frame(struct easycap *peasycap)
-{
-
- void *pex, *pad;
- int kex, kad, mex, mad, rex, rad, rad2;
- int c2, c3, w2, w3, cz, wz;
- int rc, bytesperpixel, multiplier;
- int much, more, over, rump, caches, input;
- u8 mask, margin;
- bool odd, isuy, decimatepixel, badinput;
-
- if (!peasycap) {
- SAY("ERROR: peasycap is NULL\n");
- return -EFAULT;
- }
-
- badinput = false;
- input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
-
- JOM(8, "===== parity %i, input 0x%02X, field buffer %i --> "
- "frame buffer %i\n",
- peasycap->field_buffer[peasycap->field_read][0].kount,
- peasycap->field_buffer[peasycap->field_read][0].input,
- peasycap->field_read, peasycap->frame_fill);
- JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel);
-
-/*---------------------------------------------------------------------------*/
-/*
- * REJECT OR CLEAN BAD FIELDS
- */
-/*---------------------------------------------------------------------------*/
- if (peasycap->field_read == peasycap->field_fill) {
- SAM("ERROR: on entry, still filling field buffer %i\n",
- peasycap->field_read);
- return 0;
- }
-#ifdef EASYCAP_TESTCARD
- easycap_testcard(peasycap, peasycap->field_read);
-#else
- if (0 <= input && INPUT_MANY > input) {
- if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
- easycap_testcard(peasycap, peasycap->field_read);
- }
-#endif /*EASYCAP_TESTCARD*/
-/*---------------------------------------------------------------------------*/
-
- bytesperpixel = peasycap->bytesperpixel;
- decimatepixel = peasycap->decimatepixel;
-
- if ((2 != bytesperpixel) &&
- (3 != bytesperpixel) &&
- (4 != bytesperpixel)) {
- SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
- return -EFAULT;
- }
- if (decimatepixel)
- multiplier = 2;
- else
- multiplier = 1;
-
- w2 = 2 * multiplier * (peasycap->width);
- w3 = bytesperpixel * multiplier * (peasycap->width);
- wz = multiplier * (peasycap->height) *
- multiplier * (peasycap->width);
-
- kex = peasycap->field_read; mex = 0;
- kad = peasycap->frame_fill; mad = 0;
-
- pex = peasycap->field_buffer[kex][0].pgo; rex = PAGE_SIZE;
- pad = peasycap->frame_buffer[kad][0].pgo; rad = PAGE_SIZE;
- odd = !!(peasycap->field_buffer[kex][0].kount);
-
- if (odd && (!decimatepixel)) {
- JOM(8, "initial skipping %4i bytes p.%4i\n",
- w3/multiplier, mad);
- pad += (w3 / multiplier); rad -= (w3 / multiplier);
- }
- isuy = true;
- mask = 0; rump = 0; caches = 0;
-
- cz = 0;
- while (cz < wz) {
- /*
- * PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
- * READ w2 BYTES FROM FIELD BUFFER,
- * WRITE w3 BYTES TO FRAME BUFFER
- */
- if (!decimatepixel) {
- over = w2;
- do {
- much = over; more = 0;
- margin = 0; mask = 0x00;
- if (rex < much)
- much = rex;
- rump = 0;
-
- if (much % 2) {<