2005-04-16 15:20:36 -07:00
/*
2006-06-04 10:06:18 -03:00
* Video capture interface for Linux version 2
2005-04-16 15:20:36 -07:00
*
2006-06-04 10:06:18 -03:00
* A generic video device interface for the LINUX operating system
* using a set of device structures / vectors for low level operations .
2005-04-16 15:20:36 -07:00
*
2006-06-04 10:06:18 -03:00
* This program 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 .
2005-04-16 15:20:36 -07:00
*
2006-06-04 10:06:18 -03:00
* Authors : Alan Cox , < alan @ redhat . com > ( version 1 )
* Mauro Carvalho Chehab < mchehab @ infradead . org > ( version 2 )
2005-04-16 15:20:36 -07:00
*
* Fixes : 20000516 Claudio Matsuoka < claudio @ conectiva . com >
* - Added procfs support
*/
2006-06-04 10:06:18 -03:00
# define dbgarg(cmd, fmt, arg...) \
2006-10-09 16:27:05 -03:00
if ( vfd - > debug & V4L2_DEBUG_IOCTL_ARG ) { \
2008-04-13 15:06:24 -03:00
printk ( KERN_DEBUG " %s: " , vfd - > name ) ; \
2006-06-04 10:06:18 -03:00
v4l_printk_ioctl ( cmd ) ; \
2008-04-13 15:06:24 -03:00
printk ( " " fmt , # # arg ) ; \
2006-10-09 16:27:05 -03:00
}
2006-06-04 10:06:18 -03:00
# define dbgarg2(fmt, arg...) \
if ( vfd - > debug & V4L2_DEBUG_IOCTL_ARG ) \
2008-04-13 15:07:16 -03:00
printk ( KERN_DEBUG " %s: " fmt , vfd - > name , # # arg ) ;
2006-06-04 10:06:18 -03:00
2005-04-16 15:20:36 -07:00
# include <linux/module.h>
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/mm.h>
# include <linux/string.h>
# include <linux/errno.h>
# include <linux/init.h>
# include <linux/kmod.h>
# include <linux/slab.h>
2008-05-16 14:28:31 -06:00
# include <linux/smp_lock.h>
2005-04-16 15:20:36 -07:00
# include <asm/uaccess.h>
# include <asm/system.h>
2006-06-04 10:06:18 -03:00
# define __OLD_VIDIOC_ /* To allow fixing old calls*/
# include <linux/videodev2.h>
# ifdef CONFIG_VIDEO_V4L1
2005-04-16 15:20:36 -07:00
# include <linux/videodev.h>
2006-06-04 10:06:18 -03:00
# endif
# include <media/v4l2-common.h>
2008-02-02 11:25:31 -03:00
# include <linux/video_decoder.h>
2005-04-16 15:20:36 -07:00
# define VIDEO_NUM_DEVICES 256
# define VIDEO_NAME "video4linux"
2008-06-21 13:23:27 -03:00
struct std_descr {
v4l2_std_id std ;
const char * descr ;
} ;
static const struct std_descr standards [ ] = {
{ V4L2_STD_NTSC , " NTSC " } ,
{ V4L2_STD_NTSC_M , " NTSC-M " } ,
{ V4L2_STD_NTSC_M_JP , " NTSC-M-JP " } ,
{ V4L2_STD_NTSC_M_KR , " NTSC-M-KR " } ,
{ V4L2_STD_NTSC_443 , " NTSC-443 " } ,
{ V4L2_STD_PAL , " PAL " } ,
{ V4L2_STD_PAL_BG , " PAL-BG " } ,
{ V4L2_STD_PAL_B , " PAL-B " } ,
{ V4L2_STD_PAL_B1 , " PAL-B1 " } ,
{ V4L2_STD_PAL_G , " PAL-G " } ,
{ V4L2_STD_PAL_H , " PAL-H " } ,
{ V4L2_STD_PAL_I , " PAL-I " } ,
{ V4L2_STD_PAL_DK , " PAL-DK " } ,
{ V4L2_STD_PAL_D , " PAL-D " } ,
{ V4L2_STD_PAL_D1 , " PAL-D1 " } ,
{ V4L2_STD_PAL_K , " PAL-K " } ,
{ V4L2_STD_PAL_M , " PAL-M " } ,
{ V4L2_STD_PAL_N , " PAL-N " } ,
{ V4L2_STD_PAL_Nc , " PAL-Nc " } ,
{ V4L2_STD_PAL_60 , " PAL-60 " } ,
{ V4L2_STD_SECAM , " SECAM " } ,
{ V4L2_STD_SECAM_B , " SECAM-B " } ,
{ V4L2_STD_SECAM_G , " SECAM-G " } ,
{ V4L2_STD_SECAM_H , " SECAM-H " } ,
{ V4L2_STD_SECAM_DK , " SECAM-DK " } ,
{ V4L2_STD_SECAM_D , " SECAM-D " } ,
{ V4L2_STD_SECAM_K , " SECAM-K " } ,
{ V4L2_STD_SECAM_K1 , " SECAM-K1 " } ,
{ V4L2_STD_SECAM_L , " SECAM-L " } ,
{ V4L2_STD_SECAM_LC , " SECAM-Lc " } ,
{ 0 , " Unknown " }
} ;
2008-02-02 11:25:31 -03:00
/* video4linux standard ID conversion to standard name
*/
2008-06-21 13:23:27 -03:00
const char * v4l2_norm_to_name ( v4l2_std_id id )
2008-02-02 11:25:31 -03:00
{
u32 myid = id ;
2008-06-21 13:23:27 -03:00
int i ;
2008-02-02 11:25:31 -03:00
/* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
64 bit comparations . So , on that architecture , with some gcc
variants , compilation fails . Currently , the max value is 30 bit wide .
*/
BUG_ON ( myid ! = id ) ;
2008-06-21 13:23:27 -03:00
for ( i = 0 ; standards [ i ] . std ; i + + )
if ( myid = = standards [ i ] . std )
break ;
return standards [ i ] . descr ;
2008-02-02 11:25:31 -03:00
}
EXPORT_SYMBOL ( v4l2_norm_to_name ) ;
/* Fill in the fields of a v4l2_standard structure according to the
' id ' and ' transmission ' parameters . Returns negative on error . */
int v4l2_video_std_construct ( struct v4l2_standard * vs ,
2008-06-21 13:23:27 -03:00
int id , const char * name )
2008-02-02 11:25:31 -03:00
{
u32 index = vs - > index ;
memset ( vs , 0 , sizeof ( struct v4l2_standard ) ) ;
vs - > index = index ;
vs - > id = id ;
if ( id & V4L2_STD_525_60 ) {
vs - > frameperiod . numerator = 1001 ;
vs - > frameperiod . denominator = 30000 ;
vs - > framelines = 525 ;
} else {
vs - > frameperiod . numerator = 1 ;
vs - > frameperiod . denominator = 25 ;
vs - > framelines = 625 ;
}
strlcpy ( vs - > name , name , sizeof ( vs - > name ) ) ;
return 0 ;
}
EXPORT_SYMBOL ( v4l2_video_std_construct ) ;
/* ----------------------------------------------------------------- */
/* some arrays for pretty-printing debug messages of enum types */
char * v4l2_field_names [ ] = {
[ V4L2_FIELD_ANY ] = " any " ,
[ V4L2_FIELD_NONE ] = " none " ,
[ V4L2_FIELD_TOP ] = " top " ,
[ V4L2_FIELD_BOTTOM ] = " bottom " ,
[ V4L2_FIELD_INTERLACED ] = " interlaced " ,
[ V4L2_FIELD_SEQ_TB ] = " seq-tb " ,
[ V4L2_FIELD_SEQ_BT ] = " seq-bt " ,
[ V4L2_FIELD_ALTERNATE ] = " alternate " ,
[ V4L2_FIELD_INTERLACED_TB ] = " interlaced-tb " ,
[ V4L2_FIELD_INTERLACED_BT ] = " interlaced-bt " ,
} ;
EXPORT_SYMBOL ( v4l2_field_names ) ;
char * v4l2_type_names [ ] = {
[ V4L2_BUF_TYPE_VIDEO_CAPTURE ] = " video-cap " ,
[ V4L2_BUF_TYPE_VIDEO_OVERLAY ] = " video-over " ,
[ V4L2_BUF_TYPE_VIDEO_OUTPUT ] = " video-out " ,
[ V4L2_BUF_TYPE_VBI_CAPTURE ] = " vbi-cap " ,
[ V4L2_BUF_TYPE_VBI_OUTPUT ] = " vbi-out " ,
[ V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ] = " sliced-vbi-cap " ,
[ V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ] = " sliced-vbi-out " ,
[ V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY ] = " video-out-over " ,
} ;
EXPORT_SYMBOL ( v4l2_type_names ) ;
static char * v4l2_memory_names [ ] = {
[ V4L2_MEMORY_MMAP ] = " mmap " ,
[ V4L2_MEMORY_USERPTR ] = " userptr " ,
[ V4L2_MEMORY_OVERLAY ] = " overlay " ,
} ;
# define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
arr [ a ] : " unknown " )
/* ------------------------------------------------------------------ */
/* debug help functions */
# ifdef CONFIG_VIDEO_V4L1_COMPAT
static const char * v4l1_ioctls [ ] = {
[ _IOC_NR ( VIDIOCGCAP ) ] = " VIDIOCGCAP " ,
[ _IOC_NR ( VIDIOCGCHAN ) ] = " VIDIOCGCHAN " ,
[ _IOC_NR ( VIDIOCSCHAN ) ] = " VIDIOCSCHAN " ,
[ _IOC_NR ( VIDIOCGTUNER ) ] = " VIDIOCGTUNER " ,
[ _IOC_NR ( VIDIOCSTUNER ) ] = " VIDIOCSTUNER " ,
[ _IOC_NR ( VIDIOCGPICT ) ] = " VIDIOCGPICT " ,
[ _IOC_NR ( VIDIOCSPICT ) ] = " VIDIOCSPICT " ,
[ _IOC_NR ( VIDIOCCAPTURE ) ] = " VIDIOCCAPTURE " ,
[ _IOC_NR ( VIDIOCGWIN ) ] = " VIDIOCGWIN " ,
[ _IOC_NR ( VIDIOCSWIN ) ] = " VIDIOCSWIN " ,
[ _IOC_NR ( VIDIOCGFBUF ) ] = " VIDIOCGFBUF " ,
[ _IOC_NR ( VIDIOCSFBUF ) ] = " VIDIOCSFBUF " ,
[ _IOC_NR ( VIDIOCKEY ) ] = " VIDIOCKEY " ,
[ _IOC_NR ( VIDIOCGFREQ ) ] = " VIDIOCGFREQ " ,
[ _IOC_NR ( VIDIOCSFREQ ) ] = " VIDIOCSFREQ " ,
[ _IOC_NR ( VIDIOCGAUDIO ) ] = " VIDIOCGAUDIO " ,
[ _IOC_NR ( VIDIOCSAUDIO ) ] = " VIDIOCSAUDIO " ,
[ _IOC_NR ( VIDIOCSYNC ) ] = " VIDIOCSYNC " ,
[ _IOC_NR ( VIDIOCMCAPTURE ) ] = " VIDIOCMCAPTURE " ,
[ _IOC_NR ( VIDIOCGMBUF ) ] = " VIDIOCGMBUF " ,
[ _IOC_NR ( VIDIOCGUNIT ) ] = " VIDIOCGUNIT " ,
[ _IOC_NR ( VIDIOCGCAPTURE ) ] = " VIDIOCGCAPTURE " ,
[ _IOC_NR ( VIDIOCSCAPTURE ) ] = " VIDIOCSCAPTURE " ,
[ _IOC_NR ( VIDIOCSPLAYMODE ) ] = " VIDIOCSPLAYMODE " ,
[ _IOC_NR ( VIDIOCSWRITEMODE ) ] = " VIDIOCSWRITEMODE " ,
[ _IOC_NR ( VIDIOCGPLAYINFO ) ] = " VIDIOCGPLAYINFO " ,
[ _IOC_NR ( VIDIOCSMICROCODE ) ] = " VIDIOCSMICROCODE " ,
[ _IOC_NR ( VIDIOCGVBIFMT ) ] = " VIDIOCGVBIFMT " ,
[ _IOC_NR ( VIDIOCSVBIFMT ) ] = " VIDIOCSVBIFMT "
} ;
# define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
# endif
static const char * v4l2_ioctls [ ] = {
[ _IOC_NR ( VIDIOC_QUERYCAP ) ] = " VIDIOC_QUERYCAP " ,
[ _IOC_NR ( VIDIOC_RESERVED ) ] = " VIDIOC_RESERVED " ,
[ _IOC_NR ( VIDIOC_ENUM_FMT ) ] = " VIDIOC_ENUM_FMT " ,
[ _IOC_NR ( VIDIOC_G_FMT ) ] = " VIDIOC_G_FMT " ,
[ _IOC_NR ( VIDIOC_S_FMT ) ] = " VIDIOC_S_FMT " ,
[ _IOC_NR ( VIDIOC_REQBUFS ) ] = " VIDIOC_REQBUFS " ,
[ _IOC_NR ( VIDIOC_QUERYBUF ) ] = " VIDIOC_QUERYBUF " ,
[ _IOC_NR ( VIDIOC_G_FBUF ) ] = " VIDIOC_G_FBUF " ,
[ _IOC_NR ( VIDIOC_S_FBUF ) ] = " VIDIOC_S_FBUF " ,
[ _IOC_NR ( VIDIOC_OVERLAY ) ] = " VIDIOC_OVERLAY " ,
[ _IOC_NR ( VIDIOC_QBUF ) ] = " VIDIOC_QBUF " ,
[ _IOC_NR ( VIDIOC_DQBUF ) ] = " VIDIOC_DQBUF " ,
[ _IOC_NR ( VIDIOC_STREAMON ) ] = " VIDIOC_STREAMON " ,
[ _IOC_NR ( VIDIOC_STREAMOFF ) ] = " VIDIOC_STREAMOFF " ,
[ _IOC_NR ( VIDIOC_G_PARM ) ] = " VIDIOC_G_PARM " ,
[ _IOC_NR ( VIDIOC_S_PARM ) ] = " VIDIOC_S_PARM " ,
[ _IOC_NR ( VIDIOC_G_STD ) ] = " VIDIOC_G_STD " ,
[ _IOC_NR ( VIDIOC_S_STD ) ] = " VIDIOC_S_STD " ,
[ _IOC_NR ( VIDIOC_ENUMSTD ) ] = " VIDIOC_ENUMSTD " ,
[ _IOC_NR ( VIDIOC_ENUMINPUT ) ] = " VIDIOC_ENUMINPUT " ,
[ _IOC_NR ( VIDIOC_G_CTRL ) ] = " VIDIOC_G_CTRL " ,
[ _IOC_NR ( VIDIOC_S_CTRL ) ] = " VIDIOC_S_CTRL " ,
[ _IOC_NR ( VIDIOC_G_TUNER ) ] = " VIDIOC_G_TUNER " ,
[ _IOC_NR ( VIDIOC_S_TUNER ) ] = " VIDIOC_S_TUNER " ,
[ _IOC_NR ( VIDIOC_G_AUDIO ) ] = " VIDIOC_G_AUDIO " ,
[ _IOC_NR ( VIDIOC_S_AUDIO ) ] = " VIDIOC_S_AUDIO " ,
[ _IOC_NR ( VIDIOC_QUERYCTRL ) ] = " VIDIOC_QUERYCTRL " ,
[ _IOC_NR ( VIDIOC_QUERYMENU ) ] = " VIDIOC_QUERYMENU " ,
[ _IOC_NR ( VIDIOC_G_INPUT ) ] = " VIDIOC_G_INPUT " ,
[ _IOC_NR ( VIDIOC_S_INPUT ) ] = " VIDIOC_S_INPUT " ,
[ _IOC_NR ( VIDIOC_G_OUTPUT ) ] = " VIDIOC_G_OUTPUT " ,
[ _IOC_NR ( VIDIOC_S_OUTPUT ) ] = " VIDIOC_S_OUTPUT " ,
[ _IOC_NR ( VIDIOC_ENUMOUTPUT ) ] = " VIDIOC_ENUMOUTPUT " ,
[ _IOC_NR ( VIDIOC_G_AUDOUT ) ] = " VIDIOC_G_AUDOUT " ,
[ _IOC_NR ( VIDIOC_S_AUDOUT ) ] = " VIDIOC_S_AUDOUT " ,
[ _IOC_NR ( VIDIOC_G_MODULATOR ) ] = " VIDIOC_G_MODULATOR " ,
[ _IOC_NR ( VIDIOC_S_MODULATOR ) ] = " VIDIOC_S_MODULATOR " ,
[ _IOC_NR ( VIDIOC_G_FREQUENCY ) ] = " VIDIOC_G_FREQUENCY " ,
[ _IOC_NR ( VIDIOC_S_FREQUENCY ) ] = " VIDIOC_S_FREQUENCY " ,
[ _IOC_NR ( VIDIOC_CROPCAP ) ] = " VIDIOC_CROPCAP " ,
[ _IOC_NR ( VIDIOC_G_CROP ) ] = " VIDIOC_G_CROP " ,
[ _IOC_NR ( VIDIOC_S_CROP ) ] = " VIDIOC_S_CROP " ,
[ _IOC_NR ( VIDIOC_G_JPEGCOMP ) ] = " VIDIOC_G_JPEGCOMP " ,
[ _IOC_NR ( VIDIOC_S_JPEGCOMP ) ] = " VIDIOC_S_JPEGCOMP " ,
[ _IOC_NR ( VIDIOC_QUERYSTD ) ] = " VIDIOC_QUERYSTD " ,
[ _IOC_NR ( VIDIOC_TRY_FMT ) ] = " VIDIOC_TRY_FMT " ,
[ _IOC_NR ( VIDIOC_ENUMAUDIO ) ] = " VIDIOC_ENUMAUDIO " ,
[ _IOC_NR ( VIDIOC_ENUMAUDOUT ) ] = " VIDIOC_ENUMAUDOUT " ,
[ _IOC_NR ( VIDIOC_G_PRIORITY ) ] = " VIDIOC_G_PRIORITY " ,
[ _IOC_NR ( VIDIOC_S_PRIORITY ) ] = " VIDIOC_S_PRIORITY " ,
[ _IOC_NR ( VIDIOC_G_SLICED_VBI_CAP ) ] = " VIDIOC_G_SLICED_VBI_CAP " ,
[ _IOC_NR ( VIDIOC_LOG_STATUS ) ] = " VIDIOC_LOG_STATUS " ,
[ _IOC_NR ( VIDIOC_G_EXT_CTRLS ) ] = " VIDIOC_G_EXT_CTRLS " ,
[ _IOC_NR ( VIDIOC_S_EXT_CTRLS ) ] = " VIDIOC_S_EXT_CTRLS " ,
[ _IOC_NR ( VIDIOC_TRY_EXT_CTRLS ) ] = " VIDIOC_TRY_EXT_CTRLS " ,
# if 1
[ _IOC_NR ( VIDIOC_ENUM_FRAMESIZES ) ] = " VIDIOC_ENUM_FRAMESIZES " ,
[ _IOC_NR ( VIDIOC_ENUM_FRAMEINTERVALS ) ] = " VIDIOC_ENUM_FRAMEINTERVALS " ,
[ _IOC_NR ( VIDIOC_G_ENC_INDEX ) ] = " VIDIOC_G_ENC_INDEX " ,
[ _IOC_NR ( VIDIOC_ENCODER_CMD ) ] = " VIDIOC_ENCODER_CMD " ,
[ _IOC_NR ( VIDIOC_TRY_ENCODER_CMD ) ] = " VIDIOC_TRY_ENCODER_CMD " ,
[ _IOC_NR ( VIDIOC_DBG_S_REGISTER ) ] = " VIDIOC_DBG_S_REGISTER " ,
[ _IOC_NR ( VIDIOC_DBG_G_REGISTER ) ] = " VIDIOC_DBG_G_REGISTER " ,
[ _IOC_NR ( VIDIOC_G_CHIP_IDENT ) ] = " VIDIOC_G_CHIP_IDENT " ,
# endif
} ;
# define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
static const char * v4l2_int_ioctls [ ] = {
# ifdef CONFIG_VIDEO_V4L1_COMPAT
[ _IOC_NR ( DECODER_GET_CAPABILITIES ) ] = " DECODER_GET_CAPABILITIES " ,
[ _IOC_NR ( DECODER_GET_STATUS ) ] = " DECODER_GET_STATUS " ,
[ _IOC_NR ( DECODER_SET_NORM ) ] = " DECODER_SET_NORM " ,
[ _IOC_NR ( DECODER_SET_INPUT ) ] = " DECODER_SET_INPUT " ,
[ _IOC_NR ( DECODER_SET_OUTPUT ) ] = " DECODER_SET_OUTPUT " ,
[ _IOC_NR ( DECODER_ENABLE_OUTPUT ) ] = " DECODER_ENABLE_OUTPUT " ,
[ _IOC_NR ( DECODER_SET_PICTURE ) ] = " DECODER_SET_PICTURE " ,
[ _IOC_NR ( DECODER_SET_GPIO ) ] = " DECODER_SET_GPIO " ,
[ _IOC_NR ( DECODER_INIT ) ] = " DECODER_INIT " ,
[ _IOC_NR ( DECODER_SET_VBI_BYPASS ) ] = " DECODER_SET_VBI_BYPASS " ,
[ _IOC_NR ( DECODER_DUMP ) ] = " DECODER_DUMP " ,
# endif
[ _IOC_NR ( AUDC_SET_RADIO ) ] = " AUDC_SET_RADIO " ,
[ _IOC_NR ( TUNER_SET_TYPE_ADDR ) ] = " TUNER_SET_TYPE_ADDR " ,
[ _IOC_NR ( TUNER_SET_STANDBY ) ] = " TUNER_SET_STANDBY " ,
[ _IOC_NR ( TUNER_SET_CONFIG ) ] = " TUNER_SET_CONFIG " ,
[ _IOC_NR ( VIDIOC_INT_S_TUNER_MODE ) ] = " VIDIOC_INT_S_TUNER_MODE " ,
[ _IOC_NR ( VIDIOC_INT_RESET ) ] = " VIDIOC_INT_RESET " ,
[ _IOC_NR ( VIDIOC_INT_AUDIO_CLOCK_FREQ ) ] = " VIDIOC_INT_AUDIO_CLOCK_FREQ " ,
[ _IOC_NR ( VIDIOC_INT_DECODE_VBI_LINE ) ] = " VIDIOC_INT_DECODE_VBI_LINE " ,
[ _IOC_NR ( VIDIOC_INT_S_VBI_DATA ) ] = " VIDIOC_INT_S_VBI_DATA " ,
[ _IOC_NR ( VIDIOC_INT_G_VBI_DATA ) ] = " VIDIOC_INT_G_VBI_DATA " ,
[ _IOC_NR ( VIDIOC_INT_I2S_CLOCK_FREQ ) ] = " VIDIOC_INT_I2S_CLOCK_FREQ " ,
[ _IOC_NR ( VIDIOC_INT_S_STANDBY ) ] = " VIDIOC_INT_S_STANDBY " ,
[ _IOC_NR ( VIDIOC_INT_S_AUDIO_ROUTING ) ] = " VIDIOC_INT_S_AUDIO_ROUTING " ,
[ _IOC_NR ( VIDIOC_INT_G_AUDIO_ROUTING ) ] = " VIDIOC_INT_G_AUDIO_ROUTING " ,
[ _IOC_NR ( VIDIOC_INT_S_VIDEO_ROUTING ) ] = " VIDIOC_INT_S_VIDEO_ROUTING " ,
[ _IOC_NR ( VIDIOC_INT_G_VIDEO_ROUTING ) ] = " VIDIOC_INT_G_VIDEO_ROUTING " ,
[ _IOC_NR ( VIDIOC_INT_S_CRYSTAL_FREQ ) ] = " VIDIOC_INT_S_CRYSTAL_FREQ " ,
[ _IOC_NR ( VIDIOC_INT_INIT ) ] = " VIDIOC_INT_INIT " ,
[ _IOC_NR ( VIDIOC_INT_G_STD_OUTPUT ) ] = " VIDIOC_INT_G_STD_OUTPUT " ,
[ _IOC_NR ( VIDIOC_INT_S_STD_OUTPUT ) ] = " VIDIOC_INT_S_STD_OUTPUT " ,
} ;
# define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
/* Common ioctl debug function. This function can be used by
external ioctl messages as well as internal V4L ioctl */
void v4l_printk_ioctl ( unsigned int cmd )
{
2008-04-13 15:06:24 -03:00
char * dir , * type ;
2008-02-02 11:25:31 -03:00
switch ( _IOC_TYPE ( cmd ) ) {
case ' d ' :
2008-04-13 15:06:24 -03:00
if ( _IOC_NR ( cmd ) > = V4L2_INT_IOCTLS ) {
type = " v4l2_int " ;
break ;
}
printk ( " %s " , v4l2_int_ioctls [ _IOC_NR ( cmd ) ] ) ;
return ;
2008-02-02 11:25:31 -03:00
# ifdef CONFIG_VIDEO_V4L1_COMPAT
case ' v ' :
2008-04-13 15:06:24 -03:00
if ( _IOC_NR ( cmd ) > = V4L1_IOCTLS ) {
type = " v4l1 " ;
break ;
}
printk ( " %s " , v4l1_ioctls [ _IOC_NR ( cmd ) ] ) ;
return ;
2008-02-02 11:25:31 -03:00
# endif
case ' V ' :
2008-04-13 15:06:24 -03:00
if ( _IOC_NR ( cmd ) > = V4L2_IOCTLS ) {
type = " v4l2 " ;
break ;
}
printk ( " %s " , v4l2_ioctls [ _IOC_NR ( cmd ) ] ) ;
return ;
2008-02-02 11:25:31 -03:00
default :
2008-04-13 15:06:24 -03:00
type = " unknown " ;
}
switch ( _IOC_DIR ( cmd ) ) {
case _IOC_NONE : dir = " -- " ; break ;
case _IOC_READ : dir = " r- " ; break ;
case _IOC_WRITE : dir = " -w " ; break ;
case _IOC_READ | _IOC_WRITE : dir = " rw " ; break ;
default : dir = " *ERR* " ; break ;
2008-02-02 11:25:31 -03:00
}
2008-04-13 15:06:24 -03:00
printk ( " %s ioctl '%c', dir=%s, #%d (0x%08x) " ,
type , _IOC_TYPE ( cmd ) , dir , _IOC_NR ( cmd ) , cmd ) ;
2008-02-02 11:25:31 -03:00
}
EXPORT_SYMBOL ( v4l_printk_ioctl ) ;
2005-04-16 15:20:36 -07:00
/*
* sysfs stuff
*/
2007-10-08 16:26:13 -03:00
static ssize_t show_name ( struct device * cd ,
struct device_attribute * attr , char * buf )
2005-04-16 15:20:36 -07:00
{
2006-06-04 10:06:18 -03:00
struct video_device * vfd = container_of ( cd , struct video_device ,
2007-10-08 16:26:13 -03:00
class_dev ) ;
return sprintf ( buf , " %.*s \n " , ( int ) sizeof ( vfd - > name ) , vfd - > name ) ;
2005-04-16 15:20:36 -07:00
}
struct video_device * video_device_alloc ( void )
{
struct video_device * vfd ;
2006-01-11 19:40:56 -02:00
vfd = kzalloc ( sizeof ( * vfd ) , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
return vfd ;
}
2008-02-02 11:25:31 -03:00
EXPORT_SYMBOL ( video_device_alloc ) ;
2005-04-16 15:20:36 -07:00
void video_device_release ( struct video_device * vfd )
{
kfree ( vfd ) ;
}
2008-02-02 11:25:31 -03:00
EXPORT_SYMBOL ( video_device_release ) ;
2005-04-16 15:20:36 -07:00
2007-10-08 16:26:13 -03:00
static void video_release ( struct device * cd )
2005-04-16 15:20:36 -07:00
{
2007-10-08 18:36:21 -03:00
struct video_device * vfd = container_of ( cd , struct video_device ,
class_dev ) ;
2005-04-16 15:20:36 -07:00
2006-01-09 15:25:21 -02:00
# if 1
2006-01-09 15:25:34 -02:00
/* needed until all drivers are fixed */
2005-04-16 15:20:36 -07:00
if ( ! vfd - > release )
return ;
# endif
vfd - > release ( vfd ) ;
}
2007-10-08 16:26:13 -03:00
static struct device_attribute video_device_attrs [ ] = {
__ATTR ( name , S_IRUGO , show_name , NULL ) ,
__ATTR_NULL
} ;
2005-04-16 15:20:36 -07:00
static struct class video_class = {
2005-12-01 00:51:19 -08:00
. name = VIDEO_NAME ,
2007-10-08 16:26:13 -03:00
. dev_attrs = video_device_attrs ,
. dev_release = video_release ,
2005-04-16 15:20:36 -07:00
} ;
/*
2005-12-01 00:51:19 -08:00
* Active devices
2005-04-16 15:20:36 -07:00
*/
2005-12-01 00:51:19 -08:00
2005-04-16 15:20:36 -07:00
static struct video_device * video_device [ VIDEO_NUM_DEVICES ] ;
2006-01-15 07:52:23 -02:00
static DEFINE_MUTEX ( videodev_lock ) ;
2005-04-16 15:20:36 -07:00
struct video_device * video_devdata ( struct file * file )
{
2006-12-08 02:37:47 -08:00
return video_device [ iminor ( file - > f_path . dentry - > d_inode ) ] ;
2005-04-16 15:20:36 -07:00
}
2008-02-02 11:25:31 -03:00
EXPORT_SYMBOL ( video_devdata ) ;
2005-04-16 15:20:36 -07:00
/*
2006-06-04 10:06:18 -03:00
* Open a video device - FIXME : Obsoleted
2005-04-16 15:20:36 -07:00
*/
static int video_open ( struct inode * inode , struct file * file )
{
unsigned int minor = iminor ( inode ) ;
int err = 0 ;
struct video_device * vfl ;
2006-03-28 01:56:41 -08:00
const struct file_operations * old_fops ;
2005-12-01 00:51:19 -08:00
2005-04-16 15:20:36 -07:00
if ( minor > = VIDEO_NUM_DEVICES )
return - ENODEV ;
2008-05-16 14:28:31 -06:00
lock_kernel ( ) ;
2006-01-15 07:52:23 -02:00
mutex_lock ( & videodev_lock ) ;
2005-04-16 15:20:36 -07:00
vfl = video_device [ minor ] ;
if ( vfl = = NULL ) {
2006-01-15 07:52:23 -02:00
mutex_unlock ( & videodev_lock ) ;
2005-04-16 15:20:36 -07:00
request_module ( " char-major-%d-%d " , VIDEO_MAJOR , minor ) ;
2006-01-15 07:52:23 -02:00
mutex_lock ( & videodev_lock ) ;
2005-04-16 15:20:36 -07:00
vfl = video_device [ minor ] ;
if ( vfl = = NULL ) {
2006-01-15 07:52:23 -02:00
mutex_unlock ( & videodev_lock ) ;
2008-05-16 14:28:31 -06:00
unlock_kernel ( ) ;
2005-04-16 15:20:36 -07:00
return - ENODEV ;
}
}
old_fops = file - > f_op ;
file - > f_op = fops_get ( vfl - > fops ) ;
if ( file - > f_op - > open )
err = file - > f_op - > open ( inode , file ) ;
if ( err ) {
fops_put ( file - > f_op ) ;
file - > f_op = fops_get ( old_fops ) ;
}
fops_put ( old_fops ) ;
2006-01-15 07:52:23 -02:00
mutex_unlock ( & videodev_lock ) ;
2008-05-16 14:28:31 -06:00
unlock_kernel ( ) ;
2005-04-16 15:20:36 -07:00
return err ;
}
/*
* helper function - - handles userspace copying for ioctl arguments
*/
2006-06-04 10:06:18 -03:00
# ifdef __OLD_VIDIOC_
2005-04-16 15:20:36 -07:00
static unsigned int
video_fix_command ( unsigned int cmd )
{
switch ( cmd ) {
case VIDIOC_OVERLAY_OLD :
cmd = VIDIOC_OVERLAY ;
break ;
case VIDIOC_S_PARM_OLD :
cmd = VIDIOC_S_PARM ;
break ;
case VIDIOC_S_CTRL_OLD :
cmd = VIDIOC_S_CTRL ;
break ;
case VIDIOC_G_AUDIO_OLD :
cmd = VIDIOC_G_AUDIO ;
break ;
case VIDIOC_G_AUDOUT_OLD :
cmd = VIDIOC_G_AUDOUT ;
break ;
case VIDIOC_CROPCAP_OLD :
cmd = VIDIOC_CROPCAP ;
break ;
}
return cmd ;
}
2006-06-04 10:06:18 -03:00
# endif
2005-04-16 15:20:36 -07:00
2006-06-04 10:06:18 -03:00
/*
* Obsolete usercopy function - Should be removed soon
*/
2005-04-16 15:20:36 -07:00
int
video_usercopy ( struct inode * inode , struct file * file ,
unsigned int cmd , unsigned long arg ,
int ( * func ) ( struct inode * inode , struct file * file ,
unsigned int cmd , void * arg ) )
{
char sbuf [ 128 ] ;
void * mbuf = NULL ;
void * parg = NULL ;
int err = - EINVAL ;
2006-06-18 13:43:28 -03:00
int is_ext_ctrl ;
size_t ctrls_size = 0 ;
void __user * user_ptr = NULL ;
2005-04-16 15:20:36 -07:00
2006-06-04 10:06:18 -03:00
# ifdef __OLD_VIDIOC_
2005-04-16 15:20:36 -07:00
cmd = video_fix_command ( cmd ) ;
2006-06-04 10:06:18 -03:00
# endif
2006-06-18 13:43:28 -03:00
is_ext_ctrl = ( cmd = = VIDIOC_S_EXT_CTRLS | | cmd = = VIDIOC_G_EXT_CTRLS | |
cmd = = VIDIOC_TRY_EXT_CTRLS ) ;
2005-04-16 15:20:36 -07:00
/* Copy arguments into temp kernel buffer */
switch ( _IOC_DIR ( cmd ) ) {
case _IOC_NONE :
parg = NULL ;
break ;
case _IOC_READ :
case _IOC_WRITE :
case ( _IOC_WRITE | _IOC_READ ) :
if ( _IOC_SIZE ( cmd ) < = sizeof ( sbuf ) ) {
parg = sbuf ;
} else {
/* too big to allocate from stack */
mbuf = kmalloc ( _IOC_SIZE ( cmd ) , GFP_KERNEL ) ;
if ( NULL = = mbuf )
return - ENOMEM ;
parg = mbuf ;
}
2005-12-01 00:51:19 -08:00
2005-04-16 15:20:36 -07:00
err = - EFAULT ;
if ( _IOC_DIR ( cmd ) & _IOC_WRITE )
2006-06-18 13:43:28 -03:00
if ( copy_from_user ( parg , ( void __user * ) arg , _IOC_SIZE ( cmd ) ) )
2005-04-16 15:20:36 -07:00
goto out ;
break ;
}
2006-06-18 13:43:28 -03:00
if ( is_ext_ctrl ) {
struct v4l2_ext_controls * p = parg ;
/* In case of an error, tell the caller that it wasn't
a specific control that caused it . */
p - > error_idx = p - > count ;
user_ptr = ( void __user * ) p - > controls ;
if ( p - > count ) {
ctrls_size = sizeof ( struct v4l2_ext_control ) * p - > count ;
/* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
mbuf = kmalloc ( ctrls_size , GFP_KERNEL ) ;
err = - ENOMEM ;
if ( NULL = = mbuf )
goto out_ext_ctrl ;
err = - EFAULT ;
if ( copy_from_user ( mbuf , user_ptr , ctrls_size ) )
goto out_ext_ctrl ;
p - > controls = mbuf ;
}
}
2005-04-16 15:20:36 -07:00
/* call driver */
err = func ( inode , file , cmd , parg ) ;
if ( err = = - ENOIOCTLCMD )
err = - EINVAL ;
2006-06-18 13:43:28 -03:00
if ( is_ext_ctrl ) {
struct v4l2_ext_controls * p = parg ;
p - > controls = ( void * ) user_ptr ;
if ( p - > count & & err = = 0 & & copy_to_user ( user_ptr , mbuf , ctrls_size ) )
err = - EFAULT ;
goto out_ext_ctrl ;
}
2005-04-16 15:20:36 -07:00
if ( err < 0 )
goto out ;
2006-06-18 13:43:28 -03:00
out_ext_ctrl :
2005-04-16 15:20:36 -07:00
/* Copy results into user buffer */
switch ( _IOC_DIR ( cmd ) )
{
case _IOC_READ :
case ( _IOC_WRITE | _IOC_READ ) :
if ( copy_to_user ( ( void __user * ) arg , parg , _IOC_SIZE ( cmd ) ) )
err = - EFAULT ;
break ;
}
out :
2005-11-07 01:01:31 -08:00
kfree ( mbuf ) ;
2005-04-16 15:20:36 -07:00
return err ;
}
2008-02-02 11:25:31 -03:00
EXPORT_SYMBOL ( video_usercopy ) ;
2005-04-16 15:20:36 -07:00
/*
* open / release helper functions - - handle exclusive opens
2006-06-04 10:06:18 -03:00
* Should be removed soon
2005-04-16 15:20:36 -07:00
*/
int video_exclusive_open ( struct inode * inode , struct file * file )
{
struct video_device * vfl = video_devdata ( file ) ;
int retval = 0 ;
2006-02-07 06:49:14 -02:00
mutex_lock ( & vfl - > lock ) ;
2005-04-16 15:20:36 -07:00
if ( vfl - > users ) {
retval = - EBUSY ;
} else {
vfl - > users + + ;
}
2006-02-07 06:49:14 -02:00
mutex_unlock ( & vfl - > lock ) ;
2005-04-16 15:20:36 -07:00
return retval ;
}
2008-02-02 11:25:31 -03:00
EXPORT_SYMBOL ( video_exclusive_open ) ;
2005-04-16 15:20:36 -07:00
int video_exclusive_release ( struct inode * inode , struct file * file )
{
struct video_device * vfl = video_devdata ( file ) ;
2005-12-01 00:51:19 -08:00
2005-04-16 15:20:36 -07:00
vfl - > users - - ;
return 0 ;
}
2008-02-02 11:25:31 -03:00
EXPORT_SYMBOL ( video_exclusive_release ) ;
2006-06-04 10:06:18 -03:00
static void dbgbuf ( unsigned int cmd , struct video_device * vfd ,
struct v4l2_buffer * p )
{
struct v4l2_timecode * tc = & p - > timecode ;
dbgarg ( cmd , " %02ld:%02d:%02d.%08ld index=%d, type=%s, "
" bytesused=%d, flags=0x%08d, "
2006-12-01 12:39:46 -03:00
" field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d \n " ,
2006-06-04 10:06:18 -03:00
( p - > timestamp . tv_sec / 3600 ) ,
( int ) ( p - > timestamp . tv_sec / 60 ) % 60 ,
( int ) ( p - > timestamp . tv_sec % 60 ) ,
p - > timestamp . tv_usec ,
p - > index ,
2008-02-02 11:25:31 -03:00
prt_names ( p - > type , v4l2_type_names ) ,
p - > bytesused , p - > flags ,
p - > field , p - > sequence ,
prt_names ( p - > memory , v4l2_memory_names ) ,
2006-12-01 12:39:46 -03:00
p - > m . userptr , p - > length ) ;
2006-06-04 10:06:18 -03:00
dbgarg2 ( " timecode= %02d:%02d:%02d type=%d, "
" flags=0x%08d, frames=%d, userbits=0x%08x \n " ,
tc - > hours , tc - > minutes , tc - > seconds ,
2006-06-23 07:05:22 -03:00
tc - > type , tc - > flags , tc - > frames , * ( __u32 * ) tc - > userbits ) ;
2006-06-04 10:06:18 -03:00
}
static inline void dbgrect ( struct video_device * vfd , char * s ,
struct v4l2_rect * r )
{
dbgarg2 ( " %sRect start at %dx%d, size= %dx%d \n " , s , r - > left , r - > top ,
r - > width , r - > height ) ;
} ;
static inline void v4l_print_pix_fmt ( struct video_device * vfd ,
struct v4l2_pix_format * fmt )
{
2006-12-01 12:39:46 -03:00
dbgarg2 ( " width=%d, height=%d, format=%c%c%c%c, field=%s, "
2006-06-04 10:06:18 -03:00
" bytesperline=%d sizeimage=%d, colorspace=%d \n " ,
2006-12-01 12:39:46 -03:00
fmt - > width , fmt - > height ,
( fmt - > pixelformat & 0xff ) ,
( fmt - > pixelformat > > 8 ) & 0xff ,
( fmt - > pixelformat > > 16 ) & 0xff ,
( fmt - > pixelformat > > 24 ) & 0xff ,
2008-02-02 11:25:31 -03:00
prt_names ( fmt - > field , v4l2_field_names ) ,
fmt - > bytesperline , fmt - > sizeimage , fmt - > colorspace ) ;
2006-06-04 10:06:18 -03:00
} ;
static int check_fmt ( struct video_device * vfd , enum v4l2_buf_type type )
{
switch ( type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
if ( vfd - > vidioc_try_fmt_cap )
return ( 0 ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OVERLAY :
if ( vfd - > vidioc_try_fmt_overlay )
return ( 0 ) ;
break ;
case V4L2_BUF_TYPE_VBI_CAPTURE :
if ( vfd - > vidioc_try_fmt_vbi )
return ( 0 ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT :
if ( vfd - > vidioc_try_fmt_vbi_output )
return ( 0 ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE :
if ( vfd - > vidioc_try_fmt_vbi_capture )
return ( 0 ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT :
if ( vfd - > vidioc_try_fmt_video_output )
return ( 0 ) ;
break ;
case V4L2_BUF_TYPE_VBI_OUTPUT :
if ( vfd - > vidioc_try_fmt_vbi_output )
return ( 0 ) ;
break ;
2007-04-27 12:31:02 -03:00
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY :
if ( vfd - > vidioc_try_fmt_output_overlay )
return ( 0 ) ;
break ;
2006-06-04 10:06:18 -03:00
case V4L2_BUF_TYPE_PRIVATE :
if ( vfd - > vidioc_try_fmt_type_private )
return ( 0 ) ;
break ;
}
return ( - EINVAL ) ;
}
static int __video_do_ioctl ( struct inode * inode , struct file * file ,
unsigned int cmd , void * arg )
{
struct video_device * vfd = video_devdata ( file ) ;
void * fh = file - > private_data ;
int ret = - EINVAL ;
if ( ( vfd - > debug & V4L2_DEBUG_IOCTL ) & &
2007-05-07 10:55:49 -03:00
! ( vfd - > debug & V4L2_DEBUG_IOCTL_ARG ) ) {
2006-06-04 10:06:18 -03:00
v4l_print_ioctl ( vfd - > name , cmd ) ;
2008-04-13 15:07:16 -03:00
printk ( " \n " ) ;
2006-06-04 10:06:18 -03:00
}
2007-05-01 08:46:30 -03:00
# ifdef CONFIG_VIDEO_V4L1_COMPAT
2007-05-01 08:55:00 -03:00
/***********************************************************
Handles calls to the obsoleted V4L1 API
Due to the nature of VIDIOCGMBUF , each driver that supports
V4L1 should implement its own handler for this ioctl .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-05-01 08:46:30 -03:00
/* --- streaming capture ------------------------------------- */
if ( cmd = = VIDIOCGMBUF ) {
struct video_mbuf * p = arg ;
2007-08-06 18:05:35 -03:00
memset ( p , 0 , sizeof ( * p ) ) ;
2007-05-01 08:46:30 -03:00
if ( ! vfd - > vidiocgmbuf )
return ret ;
ret = vfd - > vidiocgmbuf ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " size=%d, frames=%d, offsets=0x%08lx \n " ,
p - > size , p - > frames ,
( unsigned long ) p - > offsets ) ;
return ret ;
}
2007-05-01 08:55:00 -03:00
/********************************************************
All other V4L1 calls are handled by v4l1_compat module .
Those calls will be translated into V4L2 calls , and
__video_do_ioctl will be called again , with one or more
V4L2 ioctls .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-11-20 12:13:25 -03:00
if ( _IOC_TYPE ( cmd ) = = ' v ' )
return v4l_compat_translate_ioctl ( inode , file , cmd , arg ,
__video_do_ioctl ) ;
2007-05-01 08:55:00 -03:00
# endif
2006-11-20 12:13:25 -03:00
2006-06-04 10:06:18 -03:00
switch ( cmd ) {
/* --- capabilities ------------------------------------------ */
case VIDIOC_QUERYCAP :
{
struct v4l2_capability * cap = ( struct v4l2_capability * ) arg ;
memset ( cap , 0 , sizeof ( * cap ) ) ;
if ( ! vfd - > vidioc_querycap )
break ;
ret = vfd - > vidioc_querycap ( file , fh , cap ) ;
if ( ! ret )
dbgarg ( cmd , " driver=%s, card=%s, bus=%s, "
" version=0x%08x, "
" capabilities=0x%08x \n " ,
cap - > driver , cap - > card , cap - > bus_info ,
cap - > version ,
cap - > capabilities ) ;
break ;
}
/* --- priority ------------------------------------------ */
case VIDIOC_G_PRIORITY :
{
enum v4l2_priority * p = arg ;
if ( ! vfd - > vidioc_g_priority )
break ;
ret = vfd - > vidioc_g_priority ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " priority is %d \n " , * p ) ;
break ;
}
case VIDIOC_S_PRIORITY :
{
enum v4l2_priority * p = arg ;
if ( ! vfd - > vidioc_s_priority )
break ;
dbgarg ( cmd , " setting priority to %d \n " , * p ) ;
ret = vfd - > vidioc_s_priority ( file , fh , * p ) ;
break ;
}
/* --- capture ioctls ---------------------------------------- */
case VIDIOC_ENUM_FMT :
{
struct v4l2_fmtdesc * f = arg ;
enum v4l2_buf_type type ;
unsigned int index ;
index = f - > index ;
type = f - > type ;
memset ( f , 0 , sizeof ( * f ) ) ;
f - > index = index ;
f - > type = type ;
switch ( type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
if ( vfd - > vidioc_enum_fmt_cap )
ret = vfd - > vidioc_enum_fmt_cap ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OVERLAY :
if ( vfd - > vidioc_enum_fmt_overlay )
ret = vfd - > vidioc_enum_fmt_overlay ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_VBI_CAPTURE :
if ( vfd - > vidioc_enum_fmt_vbi )
ret = vfd - > vidioc_enum_fmt_vbi ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT :
if ( vfd - > vidioc_enum_fmt_vbi_output )
ret = vfd - > vidioc_enum_fmt_vbi_output ( file ,
fh , f ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE :
if ( vfd - > vidioc_enum_fmt_vbi_capture )
ret = vfd - > vidioc_enum_fmt_vbi_capture ( file ,
fh , f ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT :
if ( vfd - > vidioc_enum_fmt_video_output )
ret = vfd - > vidioc_enum_fmt_video_output ( file ,
fh , f ) ;
break ;
case V4L2_BUF_TYPE_VBI_OUTPUT :
if ( vfd - > vidioc_enum_fmt_vbi_output )
ret = vfd - > vidioc_enum_fmt_vbi_output ( file ,
fh , f ) ;
break ;
2007-04-27 12:31:02 -03:00
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY :
if ( vfd - > vidioc_enum_fmt_output_overlay )
ret = vfd - > vidioc_enum_fmt_output_overlay ( file , fh , f ) ;
break ;
2006-06-04 10:06:18 -03:00
case V4L2_BUF_TYPE_PRIVATE :
if ( vfd - > vidioc_enum_fmt_type_private )
ret = vfd - > vidioc_enum_fmt_type_private ( file ,
fh , f ) ;
break ;
}
if ( ! ret )
dbgarg ( cmd , " index=%d, type=%d, flags=%d, "
2006-12-01 12:39:46 -03:00
" pixelformat=%c%c%c%c, description='%s' \n " ,
2006-06-04 10:06:18 -03:00
f - > index , f - > type , f - > flags ,
2006-12-01 12:39:46 -03:00
( f - > pixelformat & 0xff ) ,
( f - > pixelformat > > 8 ) & 0xff ,
( f - > pixelformat > > 16 ) & 0xff ,
( f - > pixelformat > > 24 ) & 0xff ,
f - > description ) ;
2006-06-04 10:06:18 -03:00
break ;
}
case VIDIOC_G_FMT :
{
struct v4l2_format * f = ( struct v4l2_format * ) arg ;
enum v4l2_buf_type type = f - > type ;
memset ( & f - > fmt . pix , 0 , sizeof ( f - > fmt . pix ) ) ;
f - > type = type ;
/* FIXME: Should be one dump per type */
dbgarg ( cmd , " type=%s \n " , prt_names ( type ,
2008-02-02 11:25:31 -03:00
v4l2_type_names ) ) ;
2006-06-04 10:06:18 -03:00
switch ( type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
if ( vfd - > vidioc_g_fmt_cap )
ret = vfd - > vidioc_g_fmt_cap ( file , fh , f ) ;
if ( ! ret )
v4l_print_pix_fmt ( vfd , & f - > fmt . pix ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OVERLAY :
if ( vfd - > vidioc_g_fmt_overlay )
ret = vfd - > vidioc_g_fmt_overlay ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_VBI_CAPTURE :
if ( vfd - > vidioc_g_fmt_vbi )
ret = vfd - > vidioc_g_fmt_vbi ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT :
if ( vfd - > vidioc_g_fmt_vbi_output )
ret = vfd - > vidioc_g_fmt_vbi_output ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE :
if ( vfd - > vidioc_g_fmt_vbi_capture )
ret = vfd - > vidioc_g_fmt_vbi_capture ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT :
if ( vfd - > vidioc_g_fmt_video_output )
ret = vfd - > vidioc_g_fmt_video_output ( file ,
fh , f ) ;
break ;
2007-04-27 12:31:02 -03:00
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY :
if ( vfd - > vidioc_g_fmt_output_overlay )
ret = vfd - > vidioc_g_fmt_output_overlay ( file , fh , f ) ;
break ;
2006-06-04 10:06:18 -03:00
case V4L2_BUF_TYPE_VBI_OUTPUT :
if ( vfd - > vidioc_g_fmt_vbi_output )
ret = vfd - > vidioc_g_fmt_vbi_output ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_PRIVATE :
if ( vfd - > vidioc_g_fmt_type_private )
ret = vfd - > vidioc_g_fmt_type_private ( file ,
fh , f ) ;
break ;
}
break ;
}
case VIDIOC_S_FMT :
{
struct v4l2_format * f = ( struct v4l2_format * ) arg ;
/* FIXME: Should be one dump per type */
dbgarg ( cmd , " type=%s \n " , prt_names ( f - > type ,
2008-02-02 11:25:31 -03:00
v4l2_type_names ) ) ;
2006-06-04 10:06:18 -03:00
switch ( f - > type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
v4l_print_pix_fmt ( vfd , & f - > fmt . pix ) ;
if ( vfd - > vidioc_s_fmt_cap )
ret = vfd - > vidioc_s_fmt_cap ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OVERLAY :
if ( vfd - > vidioc_s_fmt_overlay )
ret = vfd - > vidioc_s_fmt_overlay ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_VBI_CAPTURE :
if ( vfd - > vidioc_s_fmt_vbi )
ret = vfd - > vidioc_s_fmt_vbi ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT :
if ( vfd - > vidioc_s_fmt_vbi_output )
ret = vfd - > vidioc_s_fmt_vbi_output ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE :
if ( vfd - > vidioc_s_fmt_vbi_capture )
ret = vfd - > vidioc_s_fmt_vbi_capture ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT :
if ( vfd - > vidioc_s_fmt_video_output )
ret = vfd - > vidioc_s_fmt_video_output ( file ,
fh , f ) ;
break ;
2007-04-27 12:31:02 -03:00
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY :
if ( vfd - > vidioc_s_fmt_output_overlay )
ret = vfd - > vidioc_s_fmt_output_overlay ( file , fh , f ) ;
break ;
2006-06-04 10:06:18 -03:00
case V4L2_BUF_TYPE_VBI_OUTPUT :
if ( vfd - > vidioc_s_fmt_vbi_output )
ret = vfd - > vidioc_s_fmt_vbi_output ( file ,
fh , f ) ;
break ;
case V4L2_BUF_TYPE_PRIVATE :
if ( vfd - > vidioc_s_fmt_type_private )
ret = vfd - > vidioc_s_fmt_type_private ( file ,
fh , f ) ;
break ;
}
break ;
}
case VIDIOC_TRY_FMT :
{
struct v4l2_format * f = ( struct v4l2_format * ) arg ;
/* FIXME: Should be one dump per type */
dbgarg ( cmd , " type=%s \n " , prt_names ( f - > type ,
2008-02-02 11:25:31 -03:00
v4l2_type_names ) ) ;
2006-06-04 10:06:18 -03:00
switch ( f - > type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
if ( vfd - > vidioc_try_fmt_cap )
ret = vfd - > vidioc_try_fmt_cap ( file , fh , f ) ;
if ( ! ret )
v4l_print_pix_fmt ( vfd , & f - > fmt . pix ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OVERLAY :
if ( vfd - > vidioc_try_fmt_overlay )
ret = vfd - > vidioc_try_fmt_overlay ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_VBI_CAPTURE :
if ( vfd - > vidioc_try_fmt_vbi )
ret = vfd - > vidioc_try_fmt_vbi ( file , fh , f ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT :
if ( vfd - > vidioc_try_fmt_vbi_output )
ret = vfd - > vidioc_try_fmt_vbi_output ( file ,
fh , f ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE :
if ( vfd - > vidioc_try_fmt_vbi_capture )
ret = vfd - > vidioc_try_fmt_vbi_capture ( file ,
fh , f ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT :
if ( vfd - > vidioc_try_fmt_video_output )
ret = vfd - > vidioc_try_fmt_video_output ( file ,
fh , f ) ;
break ;
2007-04-27 12:31:02 -03:00
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY :
if ( vfd - > vidioc_try_fmt_output_overlay )
ret = vfd - > vidioc_try_fmt_output_overlay ( file , fh , f ) ;
break ;
2006-06-04 10:06:18 -03:00
case V4L2_BUF_TYPE_VBI_OUTPUT :
if ( vfd - > vidioc_try_fmt_vbi_output )
ret = vfd - > vidioc_try_fmt_vbi_output ( file ,
fh , f ) ;
break ;
case V4L2_BUF_TYPE_PRIVATE :
if ( vfd - > vidioc_try_fmt_type_private )
ret = vfd - > vidioc_try_fmt_type_private ( file ,
fh , f ) ;
break ;
}
break ;
}
/* FIXME: Those buf reqs could be handled here,
with some changes on videobuf to allow its header to be included at
videodev2 . h or being merged at videodev2 .
*/
case VIDIOC_REQBUFS :
{
struct v4l2_requestbuffers * p = arg ;
if ( ! vfd - > vidioc_reqbufs )
break ;
ret = check_fmt ( vfd , p - > type ) ;
if ( ret )
break ;
ret = vfd - > vidioc_reqbufs ( file , fh , p ) ;
dbgarg ( cmd , " count=%d, type=%s, memory=%s \n " ,
p - > count ,
2008-02-02 11:25:31 -03:00
prt_names ( p - > type , v4l2_type_names ) ,
prt_names ( p - > memory , v4l2_memory_names ) ) ;
2006-06-04 10:06:18 -03:00
break ;
}
case VIDIOC_QUERYBUF :
{
struct v4l2_buffer * p = arg ;
if ( ! vfd - > vidioc_querybuf )
break ;
ret = check_fmt ( vfd , p - > type ) ;
if ( ret )
break ;
ret = vfd - > vidioc_querybuf ( file , fh , p ) ;
if ( ! ret )
dbgbuf ( cmd , vfd , p ) ;
break ;
}
case VIDIOC_QBUF :
{
struct v4l2_buffer * p = arg ;
if ( ! vfd - > vidioc_qbuf )
break ;
ret = check_fmt ( vfd , p - > type ) ;
if ( ret )
break ;
ret = vfd - > vidioc_qbuf ( file , fh , p ) ;
if ( ! ret )
dbgbuf ( cmd , vfd , p ) ;
break ;
}
case VIDIOC_DQBUF :
{
struct v4l2_buffer * p = arg ;
2006-09-11 09:49:19 -03:00
if ( ! vfd - > vidioc_dqbuf )
2006-06-04 10:06:18 -03:00
break ;
ret = check_fmt ( vfd , p - > type ) ;
if ( ret )
break ;
2006-09-11 09:49:19 -03:00
ret = vfd - > vidioc_dqbuf ( file , fh , p ) ;
2006-06-04 10:06:18 -03:00
if ( ! ret )
dbgbuf ( cmd , vfd , p ) ;
break ;
}
case VIDIOC_OVERLAY :
{
int * i = arg ;
if ( ! vfd - > vidioc_overlay )
break ;
dbgarg ( cmd , " value=%d \n " , * i ) ;
ret = vfd - > vidioc_overlay ( file , fh , * i ) ;
break ;
}
case VIDIOC_G_FBUF :
{
struct v4l2_framebuffer * p = arg ;
if ( ! vfd - > vidioc_g_fbuf )
break ;
ret = vfd - > vidioc_g_fbuf ( file , fh , arg ) ;
if ( ! ret ) {
dbgarg ( cmd , " capability=%d, flags=%d, base=0x%08lx \n " ,
p - > capability , p - > flags ,
( unsigned long ) p - > base ) ;
v4l_print_pix_fmt ( vfd , & p - > fmt ) ;
}
break ;
}
case VIDIOC_S_FBUF :
{
struct v4l2_framebuffer * p = arg ;
if ( ! vfd - > vidioc_s_fbuf )
break ;
dbgarg ( cmd , " capability=%d, flags=%d, base=0x%08lx \n " ,
p - > capability , p - > flags , ( unsigned long ) p - > base ) ;
v4l_print_pix_fmt ( vfd , & p - > fmt ) ;
ret = vfd - > vidioc_s_fbuf ( file , fh , arg ) ;
break ;
}
case VIDIOC_STREAMON :
{
enum v4l2_buf_type i = * ( int * ) arg ;
if ( ! vfd - > vidioc_streamon )
break ;
2008-02-02 11:25:31 -03:00
dbgarg ( cmd , " type=%s \n " , prt_names ( i , v4l2_type_names ) ) ;
2006-06-04 10:06:18 -03:00
ret = vfd - > vidioc_streamon ( file , fh , i ) ;
break ;
}
case VIDIOC_STREAMOFF :
{
enum v4l2_buf_type i = * ( int * ) arg ;
if ( ! vfd - > vidioc_streamoff )
break ;
2008-02-02 11:25:31 -03:00
dbgarg ( cmd , " type=%s \n " , prt_names ( i , v4l2_type_names ) ) ;
2006-06-04 10:06:18 -03:00
ret = vfd - > vidioc_streamoff ( file , fh , i ) ;
break ;
}
/* ---------- tv norms ---------- */
case VIDIOC_ENUMSTD :
{
struct v4l2_standard * p = arg ;
2008-06-21 13:23:27 -03:00
v4l2_std_id id = vfd - > tvnorms , curr_id = 0 ;
unsigned int index = p - > index , i , j = 0 ;
const char * descr = " " ;
/* Return norm array in a canonical way */
for ( i = 0 ; i < = index & & id ; i + + ) {
/* last std value in the standards array is 0, so this
while always ends there since ( id & 0 ) = = 0. */
while ( ( id & standards [ j ] . std ) ! = standards [ j ] . std )
j + + ;
curr_id = standards [ j ] . std ;
descr = standards [ j ] . descr ;
j + + ;
if ( curr_id = = 0 )
2006-11-20 13:19:20 -03:00
break ;
2008-06-21 13:23:27 -03:00
if ( curr_id ! = V4L2_STD_PAL & &
curr_id ! = V4L2_STD_SECAM & &
curr_id ! = V4L2_STD_NTSC )
id & = ~ curr_id ;
2006-06-04 10:06:18 -03:00
}
2008-06-21 13:23:27 -03:00
if ( i < = index )
2006-11-20 13:19:20 -03:00
return - EINVAL ;
2008-06-21 13:23:27 -03:00
v4l2_video_std_construct ( p , curr_id , descr ) ;
2006-06-04 10:06:18 -03:00
p - > index = index ;
2008-06-21 13:23:27 -03:00
dbgarg ( cmd , " index=%d, id=%Ld, name=%s, fps=%d/%d, "
2006-06-04 10:06:18 -03:00
" framelines=%d \n " , p - > index ,
( unsigned long long ) p - > id , p - > name ,
p - > frameperiod . numerator ,
p - > frameperiod . denominator ,
p - > framelines ) ;
2008-06-21 13:23:27 -03:00
ret = 0 ;
2006-06-04 10:06:18 -03:00
break ;
}
case VIDIOC_G_STD :
{
v4l2_std_id * id = arg ;
* id = vfd - > current_norm ;
2007-12-13 06:34:12 -03:00
dbgarg ( cmd , " value=%08Lx \n " , ( long long unsigned ) * id ) ;
2006-06-04 10:06:18 -03:00
ret = 0 ;
break ;
}
case VIDIOC_S_STD :
{
2006-11-20 13:19:20 -03:00
v4l2_std_id * id = arg , norm ;
2006-06-04 10:06:18 -03:00
2007-12-13 06:34:12 -03:00
dbgarg ( cmd , " value=%08Lx \n " , ( long long unsigned ) * id ) ;
2006-06-04 10:06:18 -03:00
2006-11-20 13:19:20 -03:00
norm = ( * id ) & vfd - > tvnorms ;
if ( vfd - > tvnorms & & ! norm ) /* Check if std is supported */
2006-06-04 10:06:18 -03:00
break ;
/* Calls the specific handler */
if ( vfd - > vidioc_s_std )
2006-11-20 13:19:20 -03:00
ret = vfd - > vidioc_s_std ( file , fh , & norm ) ;
2006-06-04 10:06:18 -03:00
else
ret = - EINVAL ;
/* Updates standard information */
2006-11-20 13:19:20 -03:00
if ( ret > = 0 )
vfd - > current_norm = norm ;
2006-06-04 10:06:18 -03:00
break ;
}
case VIDIOC_QUERYSTD :
{
v4l2_std_id * p = arg ;
if ( ! vfd - > vidioc_querystd )
break ;
ret = vfd - > vidioc_querystd ( file , fh , arg ) ;
if ( ! ret )
2007-12-13 06:34:12 -03:00
dbgarg ( cmd , " detected std=%08Lx \n " ,
2006-06-04 10:06:18 -03:00
( unsigned long long ) * p ) ;
break ;
}
/* ------ input switching ---------- */
/* FIXME: Inputs can be handled inside videodev2 */
case VIDIOC_ENUMINPUT :
{
struct v4l2_input * p = arg ;
int i = p - > index ;
if ( ! vfd - > vidioc_enum_input )
break ;
memset ( p , 0 , sizeof ( * p ) ) ;
p - > index = i ;
ret = vfd - > vidioc_enum_input ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " index=%d, name=%s, type=%d, "
" audioset=%d, "
2007-12-13 06:34:12 -03:00
" tuner=%d, std=%08Lx, status=%d \n " ,
2006-06-04 10:06:18 -03:00
p - > index , p - > name , p - > type , p - > audioset ,
p - > tuner ,
( unsigned long long ) p - > std ,
p - > status ) ;
break ;
}
case VIDIOC_G_INPUT :
{
unsigned int * i = arg ;
if ( ! vfd - > vidioc_g_input )
break ;
ret = vfd - > vidioc_g_input ( file , fh , i ) ;
if ( ! ret )
dbgarg ( cmd , " value=%d \n " , * i ) ;
break ;
}
case VIDIOC_S_INPUT :
{
unsigned int * i = arg ;
if ( ! vfd - > vidioc_s_input )
break ;
dbgarg ( cmd , " value=%d \n " , * i ) ;
ret = vfd - > vidioc_s_input ( file , fh , * i ) ;
break ;
}
/* ------ output switching ---------- */
case VIDIOC_G_OUTPUT :
{
unsigned int * i = arg ;
if ( ! vfd - > vidioc_g_output )
break ;
ret = vfd - > vidioc_g_output ( file , fh , i ) ;
if ( ! ret )
dbgarg ( cmd , " value=%d \n " , * i ) ;
break ;
}
case VIDIOC_S_OUTPUT :
{
unsigned int * i = arg ;
if ( ! vfd - > vidioc_s_output )
break ;
dbgarg ( cmd , " value=%d \n " , * i ) ;
ret = vfd - > vidioc_s_output ( file , fh , * i ) ;
break ;
}
/* --- controls ---------------------------------------------- */
case VIDIOC_QUERYCTRL :
{
struct v4l2_queryctrl * p = arg ;
if ( ! vfd - > vidioc_queryctrl )
break ;
ret = vfd - > vidioc_queryctrl ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " id=%d, type=%d, name=%s, "
" min/max=%d/%d, "
" step=%d, default=%d, flags=0x%08x \n " ,
p - > id , p - > type , p - > name , p - > minimum ,
p - > maximum , p - > step , p - > default_value ,
p - > flags ) ;
break ;
}
case VIDIOC_G_CTRL :
{
struct v4l2_control * p = arg ;
if ( ! vfd - > vidioc_g_ctrl )
break ;
dbgarg ( cmd , " Enum for index=%d \n " , p - > id ) ;
ret = vfd - > vidioc_g_ctrl ( file , fh , p ) ;
if ( ! ret )
dbgarg2 ( " id=%d, value=%d \n " , p - > id , p - > value ) ;
break ;
}
case VIDIOC_S_CTRL :
{
struct v4l2_control * p = arg ;
if ( ! vfd - > vidioc_s_ctrl )
break ;
dbgarg ( cmd , " id=%d, value=%d \n " , p - > id , p - > value ) ;
ret = vfd - > vidioc_s_ctrl ( file , fh , p ) ;
break ;
}
2006-06-18 13:43:28 -03:00
case VIDIOC_G_EXT_CTRLS :
{
struct v4l2_ext_controls * p = arg ;
if ( vfd - > vidioc_g_ext_ctrls ) {
dbgarg ( cmd , " count=%d \n " , p - > count ) ;
ret = vfd - > vidioc_g_ext_ctrls ( file , fh , p ) ;
}
break ;
}
case VIDIOC_S_EXT_CTRLS :
{
struct v4l2_ext_controls * p = arg ;
if ( vfd - > vidioc_s_ext_ctrls ) {
dbgarg ( cmd , " count=%d \n " , p - > count ) ;
ret = vfd - > vidioc_s_ext_ctrls ( file , fh , p ) ;
}
break ;
}
case VIDIOC_TRY_EXT_CTRLS :
{
struct v4l2_ext_controls * p = arg ;
if ( vfd - > vidioc_try_ext_ctrls ) {
dbgarg ( cmd , " count=%d \n " , p - > count ) ;
ret = vfd - > vidioc_try_ext_ctrls ( file , fh , p ) ;
}
break ;
}
2006-06-04 10:06:18 -03:00
case VIDIOC_QUERYMENU :
{
struct v4l2_querymenu * p = arg ;
if ( ! vfd - > vidioc_querymenu )
break ;
ret = vfd - > vidioc_querymenu ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " id=%d, index=%d, name=%s \n " ,
p - > id , p - > index , p - > name ) ;
break ;
}
/* --- audio ---------------------------------------------- */
case VIDIOC_ENUMAUDIO :
{
struct v4l2_audio * p = arg ;
if ( ! vfd - > vidioc_enumaudio )
break ;
dbgarg ( cmd , " Enum for index=%d \n " , p - > index ) ;
ret = vfd - > vidioc_enumaudio ( file , fh , p ) ;
if ( ! ret )
dbgarg2 ( " index=%d, name=%s, capability=%d, "
" mode=%d \n " , p - > index , p - > name ,
p - > capability , p - > mode ) ;
break ;
}
case VIDIOC_G_AUDIO :
{
struct v4l2_audio * p = arg ;
2006-11-20 12:10:43 -03:00
__u32 index = p - > index ;
2006-06-04 10:06:18 -03:00
if ( ! vfd - > vidioc_g_audio )
break ;
2006-11-20 12:10:43 -03:00
memset ( p , 0 , sizeof ( * p ) ) ;
p - > index = index ;
2006-06-04 10:06:18 -03:00
dbgarg ( cmd , " Get for index=%d \n " , p - > index ) ;
ret = vfd - > vidioc_g_audio ( file , fh , p ) ;
if ( ! ret )
dbgarg2 ( " index=%d, name=%s, capability=%d, "
" mode=%d \n " , p - > index ,
p - > name , p - > capability , p - > mode ) ;
break ;
}
case VIDIOC_S_AUDIO :
{
struct v4l2_audio * p = arg ;
if ( ! vfd - > vidioc_s_audio )
break ;
dbgarg ( cmd , " index=%d, name=%s, capability=%d, "
" mode=%d \n " , p - > index , p - > name ,
p - > capability , p - > mode ) ;
ret = vfd - > vidioc_s_audio ( file , fh , p ) ;
break ;
}
case VIDIOC_ENUMAUDOUT :
{
struct v4l2_audioout * p = arg ;
if ( ! vfd - > vidioc_enumaudout )
break ;
dbgarg ( cmd , " Enum for index=%d \n " , p - > index ) ;
ret = vfd - > vidioc_enumaudout ( file , fh , p ) ;
if ( ! ret )
dbgarg2 ( " index=%d, name=%s, capability=%d, "
" mode=%d \n " , p - > index , p - > name ,
p - > capability , p - > mode ) ;
break ;
}
case VIDIOC_G_AUDOUT :
{
struct v4l2_audioout * p = arg ;
if ( ! vfd - > vidioc_g_audout )
break ;
dbgarg ( cmd , " Enum for index=%d \n " , p - > index ) ;
ret = vfd - > vidioc_g_audout ( file , fh , p ) ;
if ( ! ret )
dbgarg2 ( " index=%d, name=%s, capability=%d, "
" mode=%d \n " , p - > index , p - > name ,
p - > capability , p - > mode ) ;
break ;
}
case VIDIOC_S_AUDOUT :
{
struct v4l2_audioout * p = arg ;
if ( ! vfd - > vidioc_s_audout )
break ;
dbgarg ( cmd , " index=%d, name=%s, capability=%d, "
" mode=%d \n " , p - > index , p - > name ,
p - > capability , p - > mode ) ;
ret = vfd - > vidioc_s_audout ( file , fh , p ) ;
break ;
}
case VIDIOC_G_MODULATOR :
{
struct v4l2_modulator * p = arg ;
if ( ! vfd - > vidioc_g_modulator )
break ;
ret = vfd - > vidioc_g_modulator ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " index=%d, name=%s, "
" capability=%d, rangelow=%d, "
" rangehigh=%d, txsubchans=%d \n " ,
p - > index , p - > name , p - > capability ,
p - > rangelow , p - > rangehigh ,
p - > txsubchans ) ;
break ;
}
case VIDIOC_S_MODULATOR :
{
struct v4l2_modulator * p = arg ;
if ( ! vfd - > vidioc_s_modulator )
break ;
dbgarg ( cmd , " index=%d, name=%s, capability=%d, "
" rangelow=%d, rangehigh=%d, txsubchans=%d \n " ,
p - > index , p - > name , p - > capability , p - > rangelow ,
p - > rangehigh , p - > txsubchans ) ;
ret = vfd - > vidioc_s_modulator ( file , fh , p ) ;
break ;
}
case VIDIOC_G_CROP :
{
struct v4l2_crop * p = arg ;
if ( ! vfd - > vidioc_g_crop )
break ;
ret = vfd - > vidioc_g_crop ( file , fh , p ) ;
if ( ! ret ) {
dbgarg ( cmd , " type=%d \n " , p - > type ) ;
dbgrect ( vfd , " " , & p - > c ) ;
}
break ;
}
case VIDIOC_S_CROP :
{
struct v4l2_crop * p = arg ;
if ( ! vfd - > vidioc_s_crop )
break ;
dbgarg ( cmd , " type=%d \n " , p - > type ) ;
dbgrect ( vfd , " " , & p - > c ) ;
ret = vfd - > vidioc_s_crop ( file , fh , p ) ;
break ;
}
case VIDIOC_CROPCAP :
{
struct v4l2_cropcap * p = arg ;
/*FIXME: Should also show v4l2_fract pixelaspect */
if ( ! vfd - > vidioc_cropcap )
break ;
dbgarg ( cmd , " type=%d \n " , p - > type ) ;
dbgrect ( vfd , " bounds " , & p - > bounds ) ;
dbgrect ( vfd , " defrect " , & p - > defrect ) ;
ret = vfd - > vidioc_cropcap ( file , fh , p ) ;
break ;
}
case VIDIOC_G_JPEGCOMP :
{
struct v4l2_jpegcompression * p = arg ;
if ( ! vfd - > vidioc_g_jpegcomp )
break ;
ret = vfd - > vidioc_g_jpegcomp ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " quality=%d, APPn=%d, "
" APP_len=%d, COM_len=%d, "
" jpeg_markers=%d \n " ,
p - > quality , p - > APPn , p - > APP_len ,
p - > COM_len , p - > jpeg_markers ) ;
break ;
}
case VIDIOC_S_JPEGCOMP :
{
struct v4l2_jpegcompression * p = arg ;
if ( ! vfd - > vidioc_g_jpegcomp )
break ;
dbgarg ( cmd , " quality=%d, APPn=%d, APP_len=%d, "
" COM_len=%d, jpeg_markers=%d \n " ,
p - > quality , p - > APPn , p - > APP_len ,
p - > COM_len , p - > jpeg_markers ) ;
ret = vfd - > vidioc_s_jpegcomp ( file , fh , p ) ;
break ;
}
2007-02-18 14:05:02 -03:00
case VIDIOC_G_ENC_INDEX :
{
struct v4l2_enc_idx * p = arg ;
if ( ! vfd - > vidioc_g_enc_index )
break ;
ret = vfd - > vidioc_g_enc_index ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " entries=%d, entries_cap=%d \n " ,
p - > entries , p - > entries_cap ) ;
break ;
}
2007-02-18 14:56:22 -03:00
case VIDIOC_ENCODER_CMD :
{
struct v4l2_encoder_cmd * p = arg ;
if ( ! vfd - > vidioc_encoder_cmd )
break ;
ret = vfd - > vidioc_encoder_cmd ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " cmd=%d, flags=%d \n " ,
p - > cmd , p - > flags ) ;
break ;
}
case VIDIOC_TRY_ENCODER_CMD :
{
struct v4l2_encoder_cmd * p = arg ;
if ( ! vfd - > vidioc_try_encoder_cmd )
break ;
ret = vfd - > vidioc_try_encoder_cmd ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " cmd=%d, flags=%d \n " ,
p - > cmd , p - > flags ) ;
break ;
}
2006-06-04 10:06:18 -03:00
case VIDIOC_G_PARM :
{
struct v4l2_streamparm * p = arg ;
2007-04-24 13:40:07 -03:00
__u32 type = p - > type ;
memset ( p , 0 , sizeof ( * p ) ) ;
p - > type = type ;
2006-09-14 13:36:34 -03:00
if ( vfd - > vidioc_g_parm ) {
ret = vfd - > vidioc_g_parm ( file , fh , p ) ;
} else {
struct v4l2_standard s ;
if ( p - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE )
return - EINVAL ;
2006-10-13 07:51:16 -03:00
v4l2_video_std_construct ( & s , vfd - > current_norm ,
2006-11-20 13:19:20 -03:00
v4l2_norm_to_name ( vfd - > current_norm ) ) ;
2006-09-14 13:36:34 -03:00
p - > parm . capture . timeperframe = s . frameperiod ;
ret = 0 ;
}
2006-06-04 10:06:18 -03:00
dbgarg ( cmd , " type=%d \n " , p - > type ) ;
break ;
}
case VIDIOC_S_PARM :
{
struct v4l2_streamparm * p = arg ;
if ( ! vfd - > vidioc_s_parm )
break ;
dbgarg ( cmd , " type=%d \n " , p - > type ) ;
ret = vfd - > vidioc_s_parm ( file , fh , p ) ;
break ;
}
case VIDIOC_G_TUNER :
{
struct v4l2_tuner * p = arg ;
2006-11-20 12:10:43 -03:00
__u32 index = p - > index ;
2006-06-04 10:06:18 -03:00
if ( ! vfd - > vidioc_g_tuner )
break ;
2006-11-20 12:10:43 -03:00
memset ( p , 0 , sizeof ( * p ) ) ;
p - > index = index ;
2006-06-04 10:06:18 -03:00
ret = vfd - > vidioc_g_tuner ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " index=%d, name=%s, type=%d, "
" capability=%d, rangelow=%d, "
" rangehigh=%d, signal=%d, afc=%d, "
" rxsubchans=%d, audmode=%d \n " ,
p - > index , p - > name , p - > type ,
p - > capability , p - > rangelow ,
p - > rangehigh , p - > rxsubchans ,
p - > audmode , p - > signal , p - > afc ) ;
break ;
}
case VIDIOC_S_TUNER :
{
struct v4l2_tuner * p = arg ;
if ( ! vfd - > vidioc_s_tuner )
break ;
dbgarg ( cmd , " index=%d, name=%s, type=%d, "
" capability=%d, rangelow=%d, rangehigh=%d, "
" signal=%d, afc=%d, rxsubchans=%d, "
" audmode=%d \n " , p - > index , p - > name , p - > type ,
p - > capability , p - > rangelow , p - > rangehigh ,
p - > rxsubchans , p - > audmode , p - > signal ,
p - > afc ) ;
ret = vfd - > vidioc_s_tuner ( file , fh , p ) ;
break ;
}
case VIDIOC_G_FREQUENCY :
{
struct v4l2_frequency * p = arg ;
if ( ! vfd - > vidioc_g_frequency )
break ;
2006-11-20 12:10:43 -03:00
memset ( p , 0 , sizeof ( * p ) ) ;
2006-06-04 10:06:18 -03:00
ret = vfd - > vidioc_g_frequency ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " tuner=%d, type=%d, frequency=%d \n " ,
p - > tuner , p - > type , p - > frequency ) ;
break ;
}
case VIDIOC_S_FREQUENCY :
{
struct v4l2_frequency * p = arg ;
if ( ! vfd - > vidioc_s_frequency )
break ;
dbgarg ( cmd , " tuner=%d, type=%d, frequency=%d \n " ,
p - > tuner , p - > type , p - > frequency ) ;
ret = vfd - > vidioc_s_frequency ( file , fh , p ) ;
break ;
}
case VIDIOC_G_SLICED_VBI_CAP :
{
struct v4l2_sliced_vbi_cap * p = arg ;
if ( ! vfd - > vidioc_g_sliced_vbi_cap )
break ;
ret = vfd - > vidioc_g_sliced_vbi_cap ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " service_set=%d \n " , p - > service_set ) ;
break ;
}
case VIDIOC_LOG_STATUS :
{
if ( ! vfd - > vidioc_log_status )
break ;
ret = vfd - > vidioc_log_status ( file , fh ) ;
break ;
}
2007-01-22 23:31:53 -03:00
# ifdef CONFIG_VIDEO_ADV_DEBUG
2007-01-23 22:38:13 -03:00
case VIDIOC_DBG_G_REGISTER :
2007-01-22 23:31:53 -03:00
{
struct v4l2_register * p = arg ;
2007-01-30 23:25:41 -03:00
if ( ! capable ( CAP_SYS_ADMIN ) )
ret = - EPERM ;
else if ( vfd - > vidioc_g_register )
2007-01-22 23:31:53 -03:00
ret = vfd - > vidioc_g_register ( file , fh , p ) ;
break ;
}
2007-01-23 22:38:13 -03:00
case VIDIOC_DBG_S_REGISTER :
2007-01-22 23:31:53 -03:00
{
struct v4l2_register * p = arg ;
2007-01-23 22:38:13 -03:00
if ( ! capable ( CAP_SYS_ADMIN ) )
ret = - EPERM ;
else if ( vfd - > vidioc_s_register )
2007-01-22 23:31:53 -03:00
ret = vfd - > vidioc_s_register ( file , fh , p ) ;
break ;
}
# endif
2007-04-27 12:31:08 -03:00
case VIDIOC_G_CHIP_IDENT :
{
struct v4l2_chip_ident * p = arg ;
if ( ! vfd - > vidioc_g_chip_ident )
break ;
ret = vfd - > vidioc_g_chip_ident ( file , fh , p ) ;
if ( ! ret )
dbgarg ( cmd , " chip_ident=%u, revision=0x%x \n " , p - > ident , p - > revision ) ;
break ;
}
2008-04-10 01:18:56 -03:00
default :
{
if ( ! vfd - > vidioc_default )
break ;
ret = vfd - > vidioc_default ( file , fh , cmd , arg ) ;
break ;
}
2006-11-20 12:13:25 -03:00
} /* switch */
2006-06-04 10:06:18 -03:00
if ( vfd - > debug & V4L2_DEBUG_IOCTL_ARG ) {
if ( ret < 0 ) {
2008-04-13 15:07:16 -03:00
printk ( " %s: err: on " , vfd - > name ) ;
2006-06-04 10:06:18 -03:00
v4l_print_ioctl ( vfd - > name , cmd ) ;
2008-04-13 15:07:16 -03:00
printk ( " \n " ) ;
2006-06-04 10:06:18 -03:00
}
}
return ret ;
}
int video_ioctl2 ( struct inode * inode , struct file * file ,
unsigned int cmd , unsigned long arg )
{
char sbuf [ 128 ] ;
void * mbuf = NULL ;
void * parg = NULL ;
int err = - EINVAL ;
2006-06-18 13:43:28 -03:00
int is_ext_ctrl ;
size_t ctrls_size = 0 ;
void __user * user_ptr = NULL ;
2006-06-04 10:06:18 -03:00
# ifdef __OLD_VIDIOC_
cmd = video_fix_command ( cmd ) ;
# endif
2006-06-18 13:43:28 -03:00
is_ext_ctrl = ( cmd = = VIDIOC_S_EXT_CTRLS | | cmd = = VIDIOC_G_EXT_CTRLS | |
cmd = = VIDIOC_TRY_EXT_CTRLS ) ;
2006-06-04 10:06:18 -03:00
/* Copy arguments into temp kernel buffer */
switch ( _IOC_DIR ( cmd ) ) {
case _IOC_NONE :
parg = NULL ;
break ;
case _IOC_READ :
case _IOC_WRITE :
case ( _IOC_WRITE | _IOC_READ ) :
if ( _IOC_SIZE ( cmd ) < = sizeof ( sbuf ) ) {
parg = sbuf ;
} else {
/* too big to allocate from stack */
mbuf = kmalloc ( _IOC_SIZE ( cmd ) , GFP_KERNEL ) ;
if ( NULL = = mbuf )
return - ENOMEM ;
parg = mbuf ;
}
err = - EFAULT ;
if ( _IOC_DIR ( cmd ) & _IOC_WRITE )
if ( copy_from_user ( parg , ( void __user * ) arg , _IOC_SIZE ( cmd ) ) )
goto out ;
break ;
}
2006-06-18 13:43:28 -03:00
if ( is_ext_ctrl ) {
struct v4l2_ext_controls * p = parg ;
/* In case of an error, tell the caller that it wasn't
a specific control that caused it . */
p - > error_idx = p - > count ;
user_ptr = ( void __user * ) p - > controls ;
if ( p - > count ) {
ctrls_size = sizeof ( struct v4l2_ext_control ) * p - > count ;
/* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
mbuf = kmalloc ( ctrls_size , GFP_KERNEL ) ;
err = - ENOMEM ;
if ( NULL = = mbuf )
goto out_ext_ctrl ;
err = - EFAULT ;
if ( copy_from_user ( mbuf , user_ptr , ctrls_size ) )
goto out_ext_ctrl ;
p - > controls = mbuf ;
}
}
2006-06-04 10:06:18 -03:00
/* Handles IOCTL */
err = __video_do_ioctl ( inode , file , cmd , parg ) ;
if ( err = = - ENOIOCTLCMD )
err = - EINVAL ;
2006-06-18 13:43:28 -03:00
if ( is_ext_ctrl ) {
struct v4l2_ext_controls * p = parg ;
p - > controls = ( void * ) user_ptr ;
if ( p - > count & & err = = 0 & & copy_to_user ( user_ptr , mbuf , ctrls_size ) )
err = - EFAULT ;
goto out_ext_ctrl ;
}
2006-06-04 10:06:18 -03:00
if ( err < 0 )
goto out ;
2006-06-18 13:43:28 -03:00
out_ext_ctrl :
2006-06-04 10:06:18 -03:00
/* Copy results into user buffer */
switch ( _IOC_DIR ( cmd ) )
{
case _IOC_READ :
case ( _IOC_WRITE | _IOC_READ ) :
if ( copy_to_user ( ( void __user * ) arg , parg , _IOC_SIZE ( cmd ) ) )
err = - EFAULT ;
break ;
}
out :
kfree ( mbuf ) ;
return err ;
}
2008-02-02 11:25:31 -03:00
EXPORT_SYMBOL ( video_ioctl2 ) ;
2006-06-04 10:06:18 -03:00
2007-02-12 00:55:33 -08:00
static const struct file_operations video_fops ;
2005-04-16 15:20:36 -07:00
/**
* video_register_device - register video4linux devices
* @ vfd : video device structure we want to register
* @ type : type of device to register
* @ nr : which device number ( 0 = = / dev / video0 , 1 = = / dev / video1 , . . .
* - 1 = = first free )
2005-12-01 00:51:19 -08:00
*
2005-04-16 15:20:36 -07:00
* The registration code assigns minor numbers based on the type
* requested . - ENFILE is returned in all the device slots for this
* category are full . If not then the minor field is set and the
* driver initialize function is called ( if non % NULL ) .
*
* Zero is returned on success .
*
* Valid types are
*
* % VFL_TYPE_GRABBER - A frame grabber
*
* % VFL_TYPE_VTX - A teletext device
*
* % VFL_TYPE_VBI - Vertical blank data ( undecoded )
*
2005-12-01 00:51:19 -08:00
* % VFL_TYPE_RADIO - A radio card
2005-04-16 15:20:36 -07:00
*/
int video_register_device ( struct video_device * vfd , int type , int nr )
{
int i = 0 ;
int base ;
int end ;
2006-07-19 13:23:38 -03:00
int ret ;
2005-04-16 15:20:36 -07:00
char * name_base ;
2005-12-01 00:51:19 -08:00
2005-04-16 15:20:36 -07:00
switch ( type )
{
case VFL_TYPE_GRABBER :
2006-01-23 17:11:07 -02:00
base = MINOR_VFL_TYPE_GRABBER_MIN ;
end = MINOR_VFL_TYPE_GRABBER_MAX + 1 ;
2005-04-16 15:20:36 -07:00
name_base = " video " ;
break ;
case VFL_TYPE_VTX :
2006-01-23 17:11:07 -02:00
base = MINOR_VFL_TYPE_VTX_MIN ;
end = MINOR_VFL_TYPE_VTX_MAX + 1 ;
2005-04-16 15:20:36 -07:00
name_base = " vtx " ;
break ;
case VFL_TYPE_VBI :
2006-01-23 17:11:07 -02:00
base = MINOR_VFL_TYPE_VBI_MIN ;
end = MINOR_VFL_TYPE_VBI_MAX + 1 ;
2005-04-16 15:20:36 -07:00
name_base = " vbi " ;
break ;
case VFL_TYPE_RADIO :
2006-01-23 17:11:07 -02:00
base = MINOR_VFL_TYPE_RADIO_MIN ;
end = MINOR_VFL_TYPE_RADIO_MAX + 1 ;
2005-04-16 15:20:36 -07:00
name_base = " radio " ;
break ;
default :
2006-07-25 09:31:42 -03:00
printk ( KERN_ERR " %s called with unknown type: %d \n " ,
2008-04-08 23:20:00 -03:00
__func__ , type ) ;
2005-04-16 15:20:36 -07:00
return - 1 ;
}
/* pick a minor number */
2006-01-15 07:52:23 -02:00
mutex_lock ( & videodev_lock ) ;
2005-04-16 15:20:36 -07:00
if ( nr > = 0 & & nr < end - base ) {
/* use the one the driver asked for */
i = base + nr ;
if ( NULL ! = video_device [ i ] ) {
2006-01-15 07:52:23 -02:00
mutex_unlock ( & videodev_lock ) ;
2005-04-16 15:20:36 -07:00
return - ENFILE ;
}
} else {
/* use first free */
for ( i = base ; i < end ; i + + )
if ( NULL = = video_device [ i ] )
break ;
if ( i = = end ) {
2006-01-15 07:52:23 -02:00
mutex_unlock ( & videodev_lock ) ;
2005-04-16 15:20:36 -07:00
return - ENFILE ;
}
}
video_device [ i ] = vfd ;
vfd - > minor = i ;
2006-01-15 07:52:23 -02:00
mutex_unlock ( & videodev_lock ) ;
2006-02-07 06:49:14 -02:00
mutex_init ( & vfd - > lock ) ;
2005-04-16 15:20:36 -07:00
/* sysfs class */
2005-12-01 00:51:19 -08:00
memset ( & vfd - > class_dev , 0x00 , sizeof ( vfd - > class_dev ) ) ;
2005-04-16 15:20:36 -07:00
if ( vfd - > dev )
2007-10-08 16:26:13 -03:00
vfd - > class_dev . parent = vfd - > dev ;
2005-04-16 15:20:36 -07:00
vfd - > class_dev . class = & video_class ;
2006-01-09 15:25:34 -02:00
vfd - > class_dev . devt = MKDEV ( VIDEO_MAJOR , vfd - > minor ) ;
2007-10-08 16:26:13 -03:00
sprintf ( vfd - > class_dev . bus_id , " %s%d " , name_base , i - base ) ;
ret = device_register ( & vfd - > class_dev ) ;
2006-07-25 20:37:03 -03:00
if ( ret < 0 ) {
2007-10-08 16:26:13 -03:00
printk ( KERN_ERR " %s: device_register failed \n " ,
2008-04-08 23:20:00 -03:00
__func__ ) ;
2006-07-29 17:18:06 -03:00
goto fail_minor ;
2006-07-19 13:23:38 -03:00
}
2005-04-16 15:20:36 -07:00
2006-01-09 15:25:21 -02:00
# if 1
/* needed until all drivers are fixed */
2005-04-16 15:20:36 -07:00
if ( ! vfd - > release )
printk ( KERN_WARNING " videodev: \" %s \" has no release callback. "
" Please fix your driver for proper sysfs support, see "
" http://lwn.net/Articles/36850/ \n " , vfd - > name ) ;
# endif
return 0 ;
2006-07-25 09:31:42 -03:00
fail_minor :
mutex_lock ( & videodev_lock ) ;
video_device [ vfd - > minor ] = NULL ;
vfd - > minor = - 1 ;
mutex_unlock ( & videodev_lock ) ;
return ret ;
2005-04-16 15:20:36 -07:00
}
2008-02-02 11:25:31 -03:00
EXPORT_SYMBOL ( video_register_device ) ;
2005-04-16 15:20:36 -07:00
/**
* video_unregister_device - unregister a video4linux device
* @ vfd : the device to unregister
*
* This unregisters the passed device and deassigns the minor
* number . Future open calls will be met with errors .
*/
2005-12-01 00:51:19 -08:00
2005-04-16 15:20:36 -07:00
void video_unregister_device ( struct video_device * vfd )
{
2006-01-15 07:52:23 -02:00
mutex_lock ( & videodev_lock ) ;
2005-04-16 15:20:36 -07:00
if ( video_device [ vfd - > minor ] ! = vfd )
panic ( " videodev: bad unregister " ) ;
video_device [ vfd - > minor ] = NULL ;
2007-10-08 16:26:13 -03:00
device_unregister ( & vfd - > class_dev ) ;
2006-01-15 07:52:23 -02:00
mutex_unlock ( & videodev_lock ) ;
2005-04-16 15:20:36 -07:00
}
2008-02-02 11:25:31 -03:00
EXPORT_SYMBOL ( video_unregister_device ) ;
2005-04-16 15:20:36 -07:00
2006-06-04 10:06:18 -03:00
/*
* Video fs operations
*/
2007-02-12 00:55:33 -08:00
static const struct file_operations video_fops =
2005-04-16 15:20:36 -07:00
{
. owner = THIS_MODULE ,
. llseek = no_llseek ,
. open = video_open ,
} ;
/*
* Initialise video for linux
*/
2005-12-01 00:51:19 -08:00
2005-04-16 15:20:36 -07:00
static int __init videodev_init ( void )
{
int ret ;
2006-06-04 10:06:18 -03:00
printk ( KERN_INFO " Linux video capture interface: v2.00 \n " ) ;
2005-04-16 15:20:36 -07:00
if ( register_chrdev ( VIDEO_MAJOR , VIDEO_NAME , & video_fops ) ) {
printk ( KERN_WARNING " video_dev: unable to get major %d \n " , VIDEO_MAJOR ) ;
return - EIO ;
}
ret = class_register ( & video_class ) ;
if ( ret < 0 ) {
unregister_chrdev ( VIDEO_MAJOR , VIDEO_NAME ) ;
printk ( KERN_WARNING " video_dev: class_register failed \n " ) ;
return - EIO ;
}
return 0 ;
}
static void __exit videodev_exit ( void )
{
class_unregister ( & video_class ) ;
unregister_chrdev ( VIDEO_MAJOR , VIDEO_NAME ) ;
}
module_init ( videodev_init )
module_exit ( videodev_exit )
2006-06-04 10:06:18 -03:00
MODULE_AUTHOR ( " Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org> " ) ;
MODULE_DESCRIPTION ( " Device registrar for Video4Linux drivers v2 " ) ;
2005-04-16 15:20:36 -07:00
MODULE_LICENSE ( " GPL " ) ;
/*
* Local variables :
* c - basic - offset : 8
* End :
*/