Loading drivers/staging/easycap/README +64 −29 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ Two kinds of EasyCAP have this USB ID, namely: BUILD OPTIONS AND DEPENDENCIES ------------------------------ Unless EASYCAP_DEBUG is defined during compilation it will not be possible to select a debug level at the time of module installation. If the parameter EASYCAP_IS_VIDEODEV_CLIENT is undefined during compilation the built module is entirely independent of the videodev module, and when the EasyCAP is physically plugged into a USB port the special files Loading @@ -33,41 +36,54 @@ respectively. If the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined during compilation the built easycap module is configured to register with the videodev module, in which case the special files created when the EasyCAP is plugged in are /dev/video0 and /dev/easysnd0. Use of the easycap module as a client of the videodev module has received very little testing as of June 2010. /dev/video0 and /dev/easysnd0. During in-tree builds the following should should be defined whenever the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined: EASYCAP_NEEDS_V4L2_DEVICE_H EASYCAP_NEEDS_V4L2_FOPS EASYCAP_NEEDS_UNLOCKED_IOCTL If the build is performed out-of-tree against older kernels the parameters to be defined depend on the kernel version in a way which will not be discussed here. KNOWN BUILD PROBLEMS KNOWN RUNTIME ISSUES -------------------- (1) Recent gcc versions may generate the message: (1) Intentionally, this driver will not stream material which is unambiguously identified by the hardware as copy-protected. Normal video output will be present for about a minute but will then freeze when this situation arises. warning: the frame size of .... bytes is larger than 1024 bytes (2) The controls for luminance, contrast, saturation, hue and volume may not always work properly. This warning can be suppressed by specifying in the Makefile: (3) Reduced-resolution S-Video seems to suffer from moire artefacts. EXTRA_CFLAGS += -Wframe-larger-than=8192 but it would be preferable to remove the cause of the warning. INPUT NUMBERING --------------- For the EasyCAP with S-VIDEO input cable the driver regards a request for inputs numbered 0 or 1 as referring to CVBS and a request for input numbered 5 as referring to S-VIDEO. KNOWN RUNTIME ISSUES -------------------- For the EasyCAP with four CVBS inputs the driver expects to be asked for any one of inputs numbered 1,2,3,4. If input 0 is asked for, it is interpreted as input 1. (1) Randomly (maybe 5 to 10% of occasions) the driver fails to produce any output at start-up. Closing mplayer (or whatever the user program is) and restarting it restores normal performance without any other remedial action being necessary. The reason for this is not known. (2) Intentionally, this driver will not stream material which is unambiguously identified by the hardware as copy-protected. The video output will freeze within about a minute when this situation arises. MODULE PARAMETERS ----------------- (3) The controls for luminance, contrast, saturation, hue and volume may not always work properly. Three module parameters are defined: (4) Reduced-resolution S-Video seems to suffer from moire artefacts. No attempt has yet been made to rememdy this. debug the easycap module is configured at diagnostic level n (0 to 9) gain audio gain level n (0 to 31, default is 16) bars 0 => testcard bars when incoming video signal is lost 1 => testcard bars when incoming video signal is lost (default) SUPPORTED TV STANDARDS AND RESOLUTIONS Loading @@ -82,18 +98,29 @@ usable as (for example) the "norm=" parameter in the mplayer command: PAL_60, NTSC_443, PAL_M. In addition, the driver offers "custom" pseudo-standards with a framerate which is 20% of the usual framerate. These pseudo-standards are named: PAL_BGHIN_SLOW, NTSC_N_443_SLOW, PAL_Nc_SLOW, NTSC_N_SLOW, SECAM_SLOW, NTSC_M_SLOW, NTSC_M_JP_SLOW, PAL_60_SLOW, NTSC_443_SLOW, PAL_M_SLOW. The available picture sizes are: at 25 frames per second: 720x576, 704x576, 640x480, 360x288, 320x240; at 30 frames per second: 720x480, 640x480, 360x240, 320x240; at 30 frames per second: 720x480, 640x480, 360x240, 320x240. WHAT'S TESTED AND WHAT'S NOT ---------------------------- This driver is known to work with mplayer, mencoder, tvtime and sufficiently recent versions of vlc. An interface to ffmpeg is implemented, but serious audio-video synchronization problems remain. This driver is known to work with mplayer, mencoder, tvtime, zoneminder, xawtv, gstreamer and sufficiently recent versions of vlc. An interface to ffmpeg is implemented, but serious audio-video synchronization problems remain. The driver is designed to support all the TV standards accepted by the hardware, but as yet it has actually been tested on only a few of these. Loading @@ -101,10 +128,7 @@ hardware, but as yet it has actually been tested on only a few of these. I have been unable to test and calibrate the S-video input myself because I do not possess any equipment with S-video output. This driver does not understand the V4L1 IOCTL commands, so programs such as camorama are not compatible. There are reports that the driver does work with sufficiently recent (V4L2) versions of zoneminder, but I have not attempted to confirm this myself. This driver does not understand the V4L1 IOCTL commands. UDEV RULES Loading @@ -120,6 +144,17 @@ ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \ LABEL="easycap_rules_end" MODPROBE CONFIGURATION ---------------------- The easycap module is in competition with the module snd-usb-audio for the EasyCAP's audio channel, and its installation can be aided by providing a file in directory /etc/modprobe.d with content: options easycap gain=16 bars=1 install easycap /sbin/rmmod snd-usb-audio; /sbin/modprobe --ignore-install easycap ACKNOWLEGEMENTS AND REFERENCES ------------------------------ This driver makes use of information contained in the Syntek Semicon DC-1125 Loading drivers/staging/easycap/easycap.h +3 −13 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ * EASYCAP_NEEDS_USBVIDEO_H * EASYCAP_NEEDS_V4L2_DEVICE_H * EASYCAP_NEEDS_V4L2_FOPS * EASYCAP_NEEDS_UNLOCKED_IOCTL * * IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER * OPTIONS. Loading Loading @@ -81,25 +82,14 @@ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if (!defined(__OLD_VIDIOC_)) #define __OLD_VIDIOC_ #endif /* !defined(__OLD_VIDIOC_) */ #include <media/v4l2-dev.h> #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) #include <media/v4l2-device.h> #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ #if (!defined(__OLD_VIDIOC_)) #define __OLD_VIDIOC_ #endif /* !defined(__OLD_VIDIOC_) */ #include <linux/videodev2.h> #include <linux/soundcard.h> #if defined(EASYCAP_NEEDS_USBVIDEO_H) #include <config/video/usbvideo.h> #endif /*EASYCAP_NEEDS_USBVIDEO_H*/ Loading @@ -110,7 +100,6 @@ #define STRINGIZE_AGAIN(x) #x #define STRINGIZE(x) STRINGIZE_AGAIN(x) /*---------------------------------------------------------------------------*/ /* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd * Loading Loading @@ -305,6 +294,8 @@ int hue_ok; */ /*---------------------------------------------------------------------------*/ struct easycap { #define TELLTALE "expectedstring" char telltale[16]; int isdongle; /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ Loading Loading @@ -501,7 +492,6 @@ long easycap_ioctl_noinode(struct file *, unsigned int, \ unsigned long); int easycap_ioctl(struct inode *, struct file *, unsigned int, \ unsigned long); /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) int easycap_open_noinode(struct file *); Loading drivers/staging/easycap/easycap_ioctl.c +24 −2 Original line number Diff line number Diff line Loading @@ -977,9 +977,13 @@ if (NULL == file) { } peasycap = file->private_data; if (NULL == peasycap) { SAY("ERROR: peasycap is NULL.\n"); SAY("ERROR: peasycap is NULL\n"); return -1; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap\n"); return -EFAULT; } p = peasycap->pusb_device; if (NULL == p) { SAM("ERROR: peasycap->pusb_device is NULL\n"); Loading Loading @@ -1012,6 +1016,11 @@ if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_video); return -ERESTARTSYS; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap\n"); mutex_unlock(&easycap_dongle[kd].mutex_video); return -EFAULT; } p = peasycap->pusb_device; if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); Loading Loading @@ -2317,6 +2326,8 @@ case VIDIOC_DQBUF: JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused); JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags); JOM(16, " %10i=field\n", v4l2_buffer.field); JOM(16, " %10li=timestamp.tv_sec\n", \ (long)v4l2_buffer.timestamp.tv_sec); JOM(16, " %10li=timestamp.tv_usec\n", \ (long)v4l2_buffer.timestamp.tv_usec); JOM(16, " %10i=sequence\n", v4l2_buffer.sequence); Loading Loading @@ -2528,6 +2539,10 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL.\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap\n"); return -EFAULT; } p = peasycap->pusb_device; if (NULL == p) { SAM("ERROR: peasycap->pusb_device is NULL\n"); Loading Loading @@ -2560,6 +2575,11 @@ if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_audio); return -ERESTARTSYS; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap\n"); mutex_unlock(&easycap_dongle[kd].mutex_audio); return -EFAULT; } p = peasycap->pusb_device; if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); Loading Loading @@ -2795,3 +2815,5 @@ mutex_unlock(&easycap_dongle[kd].mutex_audio); return 0; } /*****************************************************************************/ drivers/staging/easycap/easycap_main.c +135 −26 Original line number Diff line number Diff line Loading @@ -102,7 +102,6 @@ struct usb_class_driver easycap_class = { .fops = &easycap_fops, .minor_base = USB_SKEL_MINOR_BASE, }; /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_NEEDS_V4L2_FOPS) Loading @@ -121,7 +120,6 @@ const struct v4l2_file_operations v4l2_fops = { #endif /*EASYCAP_NEEDS_V4L2_FOPS*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*--------------------------------------------------------------------------*/ /* * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE Loading @@ -147,7 +145,7 @@ struct usb_class_driver easysnd_class = { /****************************************************************************/ /*---------------------------------------------------------------------------*/ /* * THIS ROUTINE DOES NOT DETECT MULTIPLE OCCURRENCES OF POINTER peasycap * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap */ /*---------------------------------------------------------------------------*/ int Loading Loading @@ -215,6 +213,10 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); return -EFAULT; Loading Loading @@ -838,6 +840,10 @@ if (NULL == peasycap) { SAY("ending unsuccessfully\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (0 != kill_video_urbs(peasycap)) { SAM("ERROR: kill_video_urbs() failed\n"); return -EFAULT; Loading Loading @@ -867,6 +873,10 @@ if (NULL == peasycap) { SAY("ending unsuccessfully\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (0 != kill_video_urbs(peasycap)) { SAM("ERROR: kill_video_urbs() failed\n"); return -EFAULT; Loading Loading @@ -904,6 +914,10 @@ if (NULL == peasycap) { SAM("ERROR: peasycap is NULL: cannot perform deletions\n"); return; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return; } kd = isdongle(peasycap); /*---------------------------------------------------------------------------*/ /* Loading Loading @@ -1026,8 +1040,6 @@ if ((struct list_head *)NULL != peasycap->purb_audio_head) { JOM(4, "%i audio data_urb structures freed\n", m); JOM(4, "setting peasycap->purb_audio_head=NULL\n"); peasycap->purb_audio_head = (struct list_head *)NULL; } else { JOM(4, "peasycap->purb_audio_head is NULL\n"); } /*---------------------------------------------------------------------------*/ JOM(4, "freeing audio isoc buffers.\n"); Loading Loading @@ -1108,6 +1120,10 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (NULL == peasycap->pusb_device) { SAY("ERROR: peasycap->pusb_device is NULL\n"); return -EFAULT; Loading Loading @@ -1140,6 +1156,12 @@ if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_video); return -ERESTARTSYS; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", \ (unsigned long int) peasycap); mutex_unlock(&easycap_dongle[kd].mutex_video); return -ERESTARTSYS; } if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); mutex_unlock(&easycap_dongle[kd].mutex_video); Loading Loading @@ -2687,11 +2709,16 @@ easycap_vma_open(struct vm_area_struct *pvma) struct easycap *peasycap; peasycap = pvma->vm_private_data; if (NULL != peasycap) if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return; } peasycap->vma_many++; JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); return; } /*****************************************************************************/ Loading @@ -2701,10 +2728,16 @@ easycap_vma_close(struct vm_area_struct *pvma) struct easycap *peasycap; peasycap = pvma->vm_private_data; if (NULL != peasycap) { if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return; } peasycap->vma_many--; JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); } return; } /*****************************************************************************/ Loading Loading @@ -2820,10 +2853,12 @@ if (NULL == peasycap) { SAY("ERROR: easycap_complete(): peasycap is NULL\n"); return; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return; } if (peasycap->video_eof) return; for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo) break; Loading Loading @@ -3545,6 +3580,7 @@ if (0 == bInterfaceNumber) { * PERFORM URGENT INTIALIZATIONS ... */ /*---------------------------------------------------------------------------*/ strcpy(&peasycap->telltale[0], TELLTALE); kref_init(&peasycap->kref); JOM(8, "intf[%i]: after kref_init(..._video) " \ "%i=peasycap->kref.refcount.counter\n", \ Loading Loading @@ -4299,6 +4335,26 @@ case 0: { */ /*--------------------------------------------------------------------------*/ usb_set_intfdata(pusb_interface, peasycap); /*---------------------------------------------------------------------------*/ /* * IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER, * THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE * CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH. * BEWARE. */ /*---------------------------------------------------------------------------*/ #if defined(PREFER_NTSC) peasycap->ntsc = true; JOM(8, "defaulting initially to NTSC\n"); #else peasycap->ntsc = false; JOM(8, "defaulting initially to PAL\n"); #endif /*PREFER_NTSC*/ rc = reset(peasycap); if (0 != rc) { SAM("ERROR: reset() returned %i\n", rc); return -EFAULT; } /*--------------------------------------------------------------------------*/ /* * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY. Loading Loading @@ -4687,6 +4743,13 @@ struct easycap *peasycap; struct list_head *plist_head; struct data_urb *pdata_urb; int minor, m, kd; /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) struct v4l2_device *pv4l2_device; #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ JOT(4, "\n"); Loading Loading @@ -4717,6 +4780,38 @@ if (NULL == peasycap) { return; } /*---------------------------------------------------------------------------*/ #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) # /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #else #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) /*---------------------------------------------------------------------------*/ /* * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(), * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE. * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED. */ /*---------------------------------------------------------------------------*/ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { pv4l2_device = usb_get_intfdata(pusb_interface); if ((struct v4l2_device *)NULL == pv4l2_device) { SAY("ERROR: pv4l2_device is NULL\n"); return; } peasycap = (struct easycap *) \ container_of(pv4l2_device, struct easycap, v4l2_device); } #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ # #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*---------------------------------------------------------------------------*/ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return; } /*---------------------------------------------------------------------------*/ /* * IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE. */ Loading Loading @@ -4806,14 +4901,28 @@ case 0: { JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); SAM("easycap detached from minor #%d\n", minor); } /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #else #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) if (!peasycap->v4l2_device.name[0]) { SAM("ERROR: peasycap->v4l2_device.name is empty\n"); if (0 <= kd && DONGLE_MANY > kd) mutex_unlock(&easycap_dongle[kd].mutex_video); return; } v4l2_device_disconnect(&peasycap->v4l2_device); JOM(4, "v4l2_device_disconnect() OK\n"); v4l2_device_unregister(&peasycap->v4l2_device); JOM(4, "v4l2_device_unregister() OK\n"); #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ video_unregister_device(&peasycap->video_device); JOM(4, "unregistered with videodev: %i=minor\n", \ peasycap->video_device.minor); JOM(4, "intf[%i]: video_unregister_device() OK\n", bInterfaceNumber); (peasycap->registered_video)--; /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ JOM(4, "unregistered with videodev: %i=minor\n", minor); #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_video); JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); Loading Loading @@ -4941,7 +5050,7 @@ MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>"); MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION); MODULE_VERSION(EASYCAP_DRIVER_VERSION); #if defined(EASYCAP_DEBUG) MODULE_PARM_DESC(debug, "Debug level: 0 (default),1,2,..."); MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9"); #endif /*EASYCAP_DEBUG*/ MODULE_PARM_DESC(bars, \ "Testcard bars on input signal failure: 0=>no, 1=>yes(default)"); Loading drivers/staging/easycap/easycap_sound.c +61 −2 Original line number Diff line number Diff line Loading @@ -64,6 +64,11 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap\n"); return; } much = 0; if (peasycap->audio_idle) { Loading Loading @@ -595,6 +600,13 @@ easysnd_open(struct inode *inode, struct file *file) struct usb_interface *pusb_interface; struct easycap *peasycap; int subminor, rc; /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) struct v4l2_device *pv4l2_device; #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ JOT(4, "begins\n"); Loading @@ -612,6 +624,39 @@ if (NULL == peasycap) { SAY("ending unsuccessfully\n"); return -1; } /*---------------------------------------------------------------------------*/ #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) # /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #else #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) /*---------------------------------------------------------------------------*/ /* * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(), * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE. * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED. */ /*---------------------------------------------------------------------------*/ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { pv4l2_device = usb_get_intfdata(pusb_interface); if ((struct v4l2_device *)NULL == pv4l2_device) { SAY("ERROR: pv4l2_device is NULL\n"); return -EFAULT; } peasycap = (struct easycap *) \ container_of(pv4l2_device, struct easycap, v4l2_device); } #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ # #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*---------------------------------------------------------------------------*/ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } /*---------------------------------------------------------------------------*/ file->private_data = peasycap; Loading @@ -624,7 +669,7 @@ JOM(4, "starting initialization\n"); if ((struct usb_device *)NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); return -EFAULT; return -ENODEV; } JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device); Loading @@ -641,7 +686,7 @@ if ((struct usb_device *)NULL == peasycap->pusb_device) { /*---------------------------------------------------------------------------*/ if ((struct usb_device *)NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device has become NULL\n"); return -EFAULT; return -ENODEV; } rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \ peasycap->audio_altsetting_on); Loading Loading @@ -678,6 +723,10 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL.\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (0 != kill_audio_urbs(peasycap)) { SAM("ERROR: kill_audio_urbs() failed\n"); return -EFAULT; Loading Loading @@ -722,6 +771,10 @@ if (NULL == peasycap) { SAY("ERROR in easysnd_read(): peasycap is NULL\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (NULL == peasycap->pusb_device) { SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n"); return -EFAULT; Loading Loading @@ -753,6 +806,12 @@ if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_audio); return -ERESTARTSYS; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", \ (unsigned long int) peasycap); mutex_unlock(&easycap_dongle[kd].mutex_audio); return -ERESTARTSYS; } if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); mutex_unlock(&easycap_dongle[kd].mutex_audio); Loading Loading
drivers/staging/easycap/README +64 −29 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ Two kinds of EasyCAP have this USB ID, namely: BUILD OPTIONS AND DEPENDENCIES ------------------------------ Unless EASYCAP_DEBUG is defined during compilation it will not be possible to select a debug level at the time of module installation. If the parameter EASYCAP_IS_VIDEODEV_CLIENT is undefined during compilation the built module is entirely independent of the videodev module, and when the EasyCAP is physically plugged into a USB port the special files Loading @@ -33,41 +36,54 @@ respectively. If the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined during compilation the built easycap module is configured to register with the videodev module, in which case the special files created when the EasyCAP is plugged in are /dev/video0 and /dev/easysnd0. Use of the easycap module as a client of the videodev module has received very little testing as of June 2010. /dev/video0 and /dev/easysnd0. During in-tree builds the following should should be defined whenever the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined: EASYCAP_NEEDS_V4L2_DEVICE_H EASYCAP_NEEDS_V4L2_FOPS EASYCAP_NEEDS_UNLOCKED_IOCTL If the build is performed out-of-tree against older kernels the parameters to be defined depend on the kernel version in a way which will not be discussed here. KNOWN BUILD PROBLEMS KNOWN RUNTIME ISSUES -------------------- (1) Recent gcc versions may generate the message: (1) Intentionally, this driver will not stream material which is unambiguously identified by the hardware as copy-protected. Normal video output will be present for about a minute but will then freeze when this situation arises. warning: the frame size of .... bytes is larger than 1024 bytes (2) The controls for luminance, contrast, saturation, hue and volume may not always work properly. This warning can be suppressed by specifying in the Makefile: (3) Reduced-resolution S-Video seems to suffer from moire artefacts. EXTRA_CFLAGS += -Wframe-larger-than=8192 but it would be preferable to remove the cause of the warning. INPUT NUMBERING --------------- For the EasyCAP with S-VIDEO input cable the driver regards a request for inputs numbered 0 or 1 as referring to CVBS and a request for input numbered 5 as referring to S-VIDEO. KNOWN RUNTIME ISSUES -------------------- For the EasyCAP with four CVBS inputs the driver expects to be asked for any one of inputs numbered 1,2,3,4. If input 0 is asked for, it is interpreted as input 1. (1) Randomly (maybe 5 to 10% of occasions) the driver fails to produce any output at start-up. Closing mplayer (or whatever the user program is) and restarting it restores normal performance without any other remedial action being necessary. The reason for this is not known. (2) Intentionally, this driver will not stream material which is unambiguously identified by the hardware as copy-protected. The video output will freeze within about a minute when this situation arises. MODULE PARAMETERS ----------------- (3) The controls for luminance, contrast, saturation, hue and volume may not always work properly. Three module parameters are defined: (4) Reduced-resolution S-Video seems to suffer from moire artefacts. No attempt has yet been made to rememdy this. debug the easycap module is configured at diagnostic level n (0 to 9) gain audio gain level n (0 to 31, default is 16) bars 0 => testcard bars when incoming video signal is lost 1 => testcard bars when incoming video signal is lost (default) SUPPORTED TV STANDARDS AND RESOLUTIONS Loading @@ -82,18 +98,29 @@ usable as (for example) the "norm=" parameter in the mplayer command: PAL_60, NTSC_443, PAL_M. In addition, the driver offers "custom" pseudo-standards with a framerate which is 20% of the usual framerate. These pseudo-standards are named: PAL_BGHIN_SLOW, NTSC_N_443_SLOW, PAL_Nc_SLOW, NTSC_N_SLOW, SECAM_SLOW, NTSC_M_SLOW, NTSC_M_JP_SLOW, PAL_60_SLOW, NTSC_443_SLOW, PAL_M_SLOW. The available picture sizes are: at 25 frames per second: 720x576, 704x576, 640x480, 360x288, 320x240; at 30 frames per second: 720x480, 640x480, 360x240, 320x240; at 30 frames per second: 720x480, 640x480, 360x240, 320x240. WHAT'S TESTED AND WHAT'S NOT ---------------------------- This driver is known to work with mplayer, mencoder, tvtime and sufficiently recent versions of vlc. An interface to ffmpeg is implemented, but serious audio-video synchronization problems remain. This driver is known to work with mplayer, mencoder, tvtime, zoneminder, xawtv, gstreamer and sufficiently recent versions of vlc. An interface to ffmpeg is implemented, but serious audio-video synchronization problems remain. The driver is designed to support all the TV standards accepted by the hardware, but as yet it has actually been tested on only a few of these. Loading @@ -101,10 +128,7 @@ hardware, but as yet it has actually been tested on only a few of these. I have been unable to test and calibrate the S-video input myself because I do not possess any equipment with S-video output. This driver does not understand the V4L1 IOCTL commands, so programs such as camorama are not compatible. There are reports that the driver does work with sufficiently recent (V4L2) versions of zoneminder, but I have not attempted to confirm this myself. This driver does not understand the V4L1 IOCTL commands. UDEV RULES Loading @@ -120,6 +144,17 @@ ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \ LABEL="easycap_rules_end" MODPROBE CONFIGURATION ---------------------- The easycap module is in competition with the module snd-usb-audio for the EasyCAP's audio channel, and its installation can be aided by providing a file in directory /etc/modprobe.d with content: options easycap gain=16 bars=1 install easycap /sbin/rmmod snd-usb-audio; /sbin/modprobe --ignore-install easycap ACKNOWLEGEMENTS AND REFERENCES ------------------------------ This driver makes use of information contained in the Syntek Semicon DC-1125 Loading
drivers/staging/easycap/easycap.h +3 −13 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ * EASYCAP_NEEDS_USBVIDEO_H * EASYCAP_NEEDS_V4L2_DEVICE_H * EASYCAP_NEEDS_V4L2_FOPS * EASYCAP_NEEDS_UNLOCKED_IOCTL * * IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER * OPTIONS. Loading Loading @@ -81,25 +82,14 @@ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if (!defined(__OLD_VIDIOC_)) #define __OLD_VIDIOC_ #endif /* !defined(__OLD_VIDIOC_) */ #include <media/v4l2-dev.h> #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) #include <media/v4l2-device.h> #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ #if (!defined(__OLD_VIDIOC_)) #define __OLD_VIDIOC_ #endif /* !defined(__OLD_VIDIOC_) */ #include <linux/videodev2.h> #include <linux/soundcard.h> #if defined(EASYCAP_NEEDS_USBVIDEO_H) #include <config/video/usbvideo.h> #endif /*EASYCAP_NEEDS_USBVIDEO_H*/ Loading @@ -110,7 +100,6 @@ #define STRINGIZE_AGAIN(x) #x #define STRINGIZE(x) STRINGIZE_AGAIN(x) /*---------------------------------------------------------------------------*/ /* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd * Loading Loading @@ -305,6 +294,8 @@ int hue_ok; */ /*---------------------------------------------------------------------------*/ struct easycap { #define TELLTALE "expectedstring" char telltale[16]; int isdongle; /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ Loading Loading @@ -501,7 +492,6 @@ long easycap_ioctl_noinode(struct file *, unsigned int, \ unsigned long); int easycap_ioctl(struct inode *, struct file *, unsigned int, \ unsigned long); /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) int easycap_open_noinode(struct file *); Loading
drivers/staging/easycap/easycap_ioctl.c +24 −2 Original line number Diff line number Diff line Loading @@ -977,9 +977,13 @@ if (NULL == file) { } peasycap = file->private_data; if (NULL == peasycap) { SAY("ERROR: peasycap is NULL.\n"); SAY("ERROR: peasycap is NULL\n"); return -1; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap\n"); return -EFAULT; } p = peasycap->pusb_device; if (NULL == p) { SAM("ERROR: peasycap->pusb_device is NULL\n"); Loading Loading @@ -1012,6 +1016,11 @@ if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_video); return -ERESTARTSYS; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap\n"); mutex_unlock(&easycap_dongle[kd].mutex_video); return -EFAULT; } p = peasycap->pusb_device; if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); Loading Loading @@ -2317,6 +2326,8 @@ case VIDIOC_DQBUF: JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused); JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags); JOM(16, " %10i=field\n", v4l2_buffer.field); JOM(16, " %10li=timestamp.tv_sec\n", \ (long)v4l2_buffer.timestamp.tv_sec); JOM(16, " %10li=timestamp.tv_usec\n", \ (long)v4l2_buffer.timestamp.tv_usec); JOM(16, " %10i=sequence\n", v4l2_buffer.sequence); Loading Loading @@ -2528,6 +2539,10 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL.\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap\n"); return -EFAULT; } p = peasycap->pusb_device; if (NULL == p) { SAM("ERROR: peasycap->pusb_device is NULL\n"); Loading Loading @@ -2560,6 +2575,11 @@ if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_audio); return -ERESTARTSYS; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap\n"); mutex_unlock(&easycap_dongle[kd].mutex_audio); return -EFAULT; } p = peasycap->pusb_device; if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); Loading Loading @@ -2795,3 +2815,5 @@ mutex_unlock(&easycap_dongle[kd].mutex_audio); return 0; } /*****************************************************************************/
drivers/staging/easycap/easycap_main.c +135 −26 Original line number Diff line number Diff line Loading @@ -102,7 +102,6 @@ struct usb_class_driver easycap_class = { .fops = &easycap_fops, .minor_base = USB_SKEL_MINOR_BASE, }; /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_NEEDS_V4L2_FOPS) Loading @@ -121,7 +120,6 @@ const struct v4l2_file_operations v4l2_fops = { #endif /*EASYCAP_NEEDS_V4L2_FOPS*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*--------------------------------------------------------------------------*/ /* * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE Loading @@ -147,7 +145,7 @@ struct usb_class_driver easysnd_class = { /****************************************************************************/ /*---------------------------------------------------------------------------*/ /* * THIS ROUTINE DOES NOT DETECT MULTIPLE OCCURRENCES OF POINTER peasycap * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap */ /*---------------------------------------------------------------------------*/ int Loading Loading @@ -215,6 +213,10 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); return -EFAULT; Loading Loading @@ -838,6 +840,10 @@ if (NULL == peasycap) { SAY("ending unsuccessfully\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (0 != kill_video_urbs(peasycap)) { SAM("ERROR: kill_video_urbs() failed\n"); return -EFAULT; Loading Loading @@ -867,6 +873,10 @@ if (NULL == peasycap) { SAY("ending unsuccessfully\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (0 != kill_video_urbs(peasycap)) { SAM("ERROR: kill_video_urbs() failed\n"); return -EFAULT; Loading Loading @@ -904,6 +914,10 @@ if (NULL == peasycap) { SAM("ERROR: peasycap is NULL: cannot perform deletions\n"); return; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return; } kd = isdongle(peasycap); /*---------------------------------------------------------------------------*/ /* Loading Loading @@ -1026,8 +1040,6 @@ if ((struct list_head *)NULL != peasycap->purb_audio_head) { JOM(4, "%i audio data_urb structures freed\n", m); JOM(4, "setting peasycap->purb_audio_head=NULL\n"); peasycap->purb_audio_head = (struct list_head *)NULL; } else { JOM(4, "peasycap->purb_audio_head is NULL\n"); } /*---------------------------------------------------------------------------*/ JOM(4, "freeing audio isoc buffers.\n"); Loading Loading @@ -1108,6 +1120,10 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (NULL == peasycap->pusb_device) { SAY("ERROR: peasycap->pusb_device is NULL\n"); return -EFAULT; Loading Loading @@ -1140,6 +1156,12 @@ if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_video); return -ERESTARTSYS; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", \ (unsigned long int) peasycap); mutex_unlock(&easycap_dongle[kd].mutex_video); return -ERESTARTSYS; } if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); mutex_unlock(&easycap_dongle[kd].mutex_video); Loading Loading @@ -2687,11 +2709,16 @@ easycap_vma_open(struct vm_area_struct *pvma) struct easycap *peasycap; peasycap = pvma->vm_private_data; if (NULL != peasycap) if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return; } peasycap->vma_many++; JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); return; } /*****************************************************************************/ Loading @@ -2701,10 +2728,16 @@ easycap_vma_close(struct vm_area_struct *pvma) struct easycap *peasycap; peasycap = pvma->vm_private_data; if (NULL != peasycap) { if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return; } peasycap->vma_many--; JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); } return; } /*****************************************************************************/ Loading Loading @@ -2820,10 +2853,12 @@ if (NULL == peasycap) { SAY("ERROR: easycap_complete(): peasycap is NULL\n"); return; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return; } if (peasycap->video_eof) return; for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo) break; Loading Loading @@ -3545,6 +3580,7 @@ if (0 == bInterfaceNumber) { * PERFORM URGENT INTIALIZATIONS ... */ /*---------------------------------------------------------------------------*/ strcpy(&peasycap->telltale[0], TELLTALE); kref_init(&peasycap->kref); JOM(8, "intf[%i]: after kref_init(..._video) " \ "%i=peasycap->kref.refcount.counter\n", \ Loading Loading @@ -4299,6 +4335,26 @@ case 0: { */ /*--------------------------------------------------------------------------*/ usb_set_intfdata(pusb_interface, peasycap); /*---------------------------------------------------------------------------*/ /* * IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER, * THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE * CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH. * BEWARE. */ /*---------------------------------------------------------------------------*/ #if defined(PREFER_NTSC) peasycap->ntsc = true; JOM(8, "defaulting initially to NTSC\n"); #else peasycap->ntsc = false; JOM(8, "defaulting initially to PAL\n"); #endif /*PREFER_NTSC*/ rc = reset(peasycap); if (0 != rc) { SAM("ERROR: reset() returned %i\n", rc); return -EFAULT; } /*--------------------------------------------------------------------------*/ /* * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY. Loading Loading @@ -4687,6 +4743,13 @@ struct easycap *peasycap; struct list_head *plist_head; struct data_urb *pdata_urb; int minor, m, kd; /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) struct v4l2_device *pv4l2_device; #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ JOT(4, "\n"); Loading Loading @@ -4717,6 +4780,38 @@ if (NULL == peasycap) { return; } /*---------------------------------------------------------------------------*/ #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) # /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #else #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) /*---------------------------------------------------------------------------*/ /* * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(), * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE. * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED. */ /*---------------------------------------------------------------------------*/ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { pv4l2_device = usb_get_intfdata(pusb_interface); if ((struct v4l2_device *)NULL == pv4l2_device) { SAY("ERROR: pv4l2_device is NULL\n"); return; } peasycap = (struct easycap *) \ container_of(pv4l2_device, struct easycap, v4l2_device); } #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ # #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*---------------------------------------------------------------------------*/ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return; } /*---------------------------------------------------------------------------*/ /* * IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE. */ Loading Loading @@ -4806,14 +4901,28 @@ case 0: { JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); SAM("easycap detached from minor #%d\n", minor); } /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #else #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) if (!peasycap->v4l2_device.name[0]) { SAM("ERROR: peasycap->v4l2_device.name is empty\n"); if (0 <= kd && DONGLE_MANY > kd) mutex_unlock(&easycap_dongle[kd].mutex_video); return; } v4l2_device_disconnect(&peasycap->v4l2_device); JOM(4, "v4l2_device_disconnect() OK\n"); v4l2_device_unregister(&peasycap->v4l2_device); JOM(4, "v4l2_device_unregister() OK\n"); #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ video_unregister_device(&peasycap->video_device); JOM(4, "unregistered with videodev: %i=minor\n", \ peasycap->video_device.minor); JOM(4, "intf[%i]: video_unregister_device() OK\n", bInterfaceNumber); (peasycap->registered_video)--; /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ JOM(4, "unregistered with videodev: %i=minor\n", minor); #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_video); JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); Loading Loading @@ -4941,7 +5050,7 @@ MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>"); MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION); MODULE_VERSION(EASYCAP_DRIVER_VERSION); #if defined(EASYCAP_DEBUG) MODULE_PARM_DESC(debug, "Debug level: 0 (default),1,2,..."); MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9"); #endif /*EASYCAP_DEBUG*/ MODULE_PARM_DESC(bars, \ "Testcard bars on input signal failure: 0=>no, 1=>yes(default)"); Loading
drivers/staging/easycap/easycap_sound.c +61 −2 Original line number Diff line number Diff line Loading @@ -64,6 +64,11 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap\n"); return; } much = 0; if (peasycap->audio_idle) { Loading Loading @@ -595,6 +600,13 @@ easysnd_open(struct inode *inode, struct file *file) struct usb_interface *pusb_interface; struct easycap *peasycap; int subminor, rc; /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) struct v4l2_device *pv4l2_device; #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ JOT(4, "begins\n"); Loading @@ -612,6 +624,39 @@ if (NULL == peasycap) { SAY("ending unsuccessfully\n"); return -1; } /*---------------------------------------------------------------------------*/ #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) # /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #else #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) /*---------------------------------------------------------------------------*/ /* * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(), * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE. * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED. */ /*---------------------------------------------------------------------------*/ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { pv4l2_device = usb_get_intfdata(pusb_interface); if ((struct v4l2_device *)NULL == pv4l2_device) { SAY("ERROR: pv4l2_device is NULL\n"); return -EFAULT; } peasycap = (struct easycap *) \ container_of(pv4l2_device, struct easycap, v4l2_device); } #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ # #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*---------------------------------------------------------------------------*/ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } /*---------------------------------------------------------------------------*/ file->private_data = peasycap; Loading @@ -624,7 +669,7 @@ JOM(4, "starting initialization\n"); if ((struct usb_device *)NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); return -EFAULT; return -ENODEV; } JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device); Loading @@ -641,7 +686,7 @@ if ((struct usb_device *)NULL == peasycap->pusb_device) { /*---------------------------------------------------------------------------*/ if ((struct usb_device *)NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device has become NULL\n"); return -EFAULT; return -ENODEV; } rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \ peasycap->audio_altsetting_on); Loading Loading @@ -678,6 +723,10 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL.\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (0 != kill_audio_urbs(peasycap)) { SAM("ERROR: kill_audio_urbs() failed\n"); return -EFAULT; Loading Loading @@ -722,6 +771,10 @@ if (NULL == peasycap) { SAY("ERROR in easysnd_read(): peasycap is NULL\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); return -EFAULT; } if (NULL == peasycap->pusb_device) { SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n"); return -EFAULT; Loading Loading @@ -753,6 +806,12 @@ if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_audio); return -ERESTARTSYS; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { SAY("ERROR: bad peasycap: 0x%08lX\n", \ (unsigned long int) peasycap); mutex_unlock(&easycap_dongle[kd].mutex_audio); return -ERESTARTSYS; } if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); mutex_unlock(&easycap_dongle[kd].mutex_audio); Loading