2008-07-20 15:12:02 +04:00
/*
* Video capture interface for Linux version 2
*
* A generic framework to process V4L2 ioctl commands .
*
* 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 .
*
2008-10-27 21:13:47 +03:00
* Authors : Alan Cox , < alan @ lxorguk . ukuu . org . uk > ( version 1 )
2008-07-20 15:12:02 +04:00
* Mauro Carvalho Chehab < mchehab @ infradead . org > ( version 2 )
*/
# include <linux/module.h>
# include <linux/types.h>
# include <linux/kernel.h>
# define __OLD_VIDIOC_ /* To allow fixing old calls */
# include <linux/videodev2.h>
# ifdef CONFIG_VIDEO_V4L1
# include <linux/videodev.h>
# endif
# include <media/v4l2-common.h>
# include <media/v4l2-ioctl.h>
2009-02-07 17:00:02 +03:00
# include <media/v4l2-chip-ident.h>
2008-07-20 15:12:02 +04:00
# include <linux/video_decoder.h>
# define dbgarg(cmd, fmt, arg...) \
do { \
if ( vfd - > debug & V4L2_DEBUG_IOCTL_ARG ) { \
printk ( KERN_DEBUG " %s: " , vfd - > name ) ; \
v4l_printk_ioctl ( cmd ) ; \
printk ( " " fmt , # # arg ) ; \
} \
} while ( 0 )
# define dbgarg2(fmt, arg...) \
do { \
if ( vfd - > debug & V4L2_DEBUG_IOCTL_ARG ) \
printk ( KERN_DEBUG " %s: " fmt , vfd - > name , # # arg ) ; \
} while ( 0 )
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 " }
} ;
/* video4linux standard ID conversion to standard name
*/
const char * v4l2_norm_to_name ( v4l2_std_id id )
{
u32 myid = id ;
int i ;
/* 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 ) ;
for ( i = 0 ; standards [ i ] . std ; i + + )
if ( myid = = standards [ i ] . std )
break ;
return standards [ i ] . descr ;
}
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 ,
int id , const char * name )
{
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 */
const 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 ) ;
const char * v4l2_type_names [ ] = {
[ V4L2_BUF_TYPE_VIDEO_CAPTURE ] = " vid-cap " ,
[ V4L2_BUF_TYPE_VIDEO_OVERLAY ] = " vid-overlay " ,
[ V4L2_BUF_TYPE_VIDEO_OUTPUT ] = " vid-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 ] = " vid-out-overlay " ,
} ;
EXPORT_SYMBOL ( v4l2_type_names ) ;
static const 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 " ,
2008-12-30 13:14:19 +03:00
[ _IOC_NR ( VIDIOC_DBG_G_CHIP_IDENT ) ] = " VIDIOC_DBG_G_CHIP_IDENT " ,
2008-07-20 15:12:02 +04:00
[ _IOC_NR ( VIDIOC_S_HW_FREQ_SEEK ) ] = " VIDIOC_S_HW_FREQ_SEEK " ,
# 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 )
{
char * dir , * type ;
switch ( _IOC_TYPE ( cmd ) ) {
case ' d ' :
if ( _IOC_NR ( cmd ) > = V4L2_INT_IOCTLS ) {
type = " v4l2_int " ;
break ;
}
printk ( " %s " , v4l2_int_ioctls [ _IOC_NR ( cmd ) ] ) ;
return ;
# ifdef CONFIG_VIDEO_V4L1_COMPAT
case ' v ' :
if ( _IOC_NR ( cmd ) > = V4L1_IOCTLS ) {
type = " v4l1 " ;
break ;
}
printk ( " %s " , v4l1_ioctls [ _IOC_NR ( cmd ) ] ) ;
return ;
# endif
case ' V ' :
if ( _IOC_NR ( cmd ) > = V4L2_IOCTLS ) {
type = " v4l2 " ;
break ;
}
printk ( " %s " , v4l2_ioctls [ _IOC_NR ( cmd ) ] ) ;
return ;
default :
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 ;
}
printk ( " %s ioctl '%c', dir=%s, #%d (0x%08x) " ,
type , _IOC_TYPE ( cmd ) , dir , _IOC_NR ( cmd ) , cmd ) ;
}
EXPORT_SYMBOL ( v4l_printk_ioctl ) ;
/*
* helper function - - handles userspace copying for ioctl arguments
*/
# ifdef __OLD_VIDIOC_
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 ;
}
# endif
/*
* Obsolete usercopy function - Should be removed soon
*/
2008-12-30 13:04:34 +03:00
long
2008-11-01 14:25:11 +03:00
video_usercopy ( struct file * file , unsigned int cmd , unsigned long arg ,
v4l2_kioctl func )
2008-07-20 15:12:02 +04:00
{
char sbuf [ 128 ] ;
void * mbuf = NULL ;
void * parg = NULL ;
2008-12-30 13:04:34 +03:00
long err = - EINVAL ;
2008-07-20 15:12:02 +04:00
int is_ext_ctrl ;
size_t ctrls_size = 0 ;
void __user * user_ptr = NULL ;
# ifdef __OLD_VIDIOC_
cmd = video_fix_command ( cmd ) ;
# endif
is_ext_ctrl = ( cmd = = VIDIOC_S_EXT_CTRLS | | cmd = = VIDIOC_G_EXT_CTRLS | |
cmd = = VIDIOC_TRY_EXT_CTRLS ) ;
/* 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 ;
}
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 ;
}
}
/* call driver */
2008-11-01 14:25:11 +03:00
err = func ( file , cmd , parg ) ;
2008-07-20 15:12:02 +04:00
if ( err = = - ENOIOCTLCMD )
err = - EINVAL ;
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 ;
}
if ( err < 0 )
goto out ;
out_ext_ctrl :
/* 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 ;
}
EXPORT_SYMBOL ( video_usercopy ) ;
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, "
" field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d \n " ,
p - > timestamp . tv_sec / 3600 ,
( int ) ( p - > timestamp . tv_sec / 60 ) % 60 ,
( int ) ( p - > timestamp . tv_sec % 60 ) ,
2008-09-03 23:47:38 +04:00
( long ) p - > timestamp . tv_usec ,
2008-07-20 15:12:02 +04:00
p - > index ,
prt_names ( p - > type , v4l2_type_names ) ,
p - > bytesused , p - > flags ,
p - > field , p - > sequence ,
prt_names ( p - > memory , v4l2_memory_names ) ,
p - > m . userptr , p - > length ) ;
dbgarg2 ( " timecode=%02d:%02d:%02d type=%d, "
" flags=0x%08d, frames=%d, userbits=0x%08x \n " ,
tc - > hours , tc - > minutes , tc - > seconds ,
tc - > type , tc - > flags , tc - > frames , * ( __u32 * ) tc - > userbits ) ;
}
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 )
{
dbgarg2 ( " width=%d, height=%d, format=%c%c%c%c, field=%s, "
" bytesperline=%d sizeimage=%d, colorspace=%d \n " ,
fmt - > width , fmt - > height ,
( fmt - > pixelformat & 0xff ) ,
( fmt - > pixelformat > > 8 ) & 0xff ,
( fmt - > pixelformat > > 16 ) & 0xff ,
( fmt - > pixelformat > > 24 ) & 0xff ,
prt_names ( fmt - > field , v4l2_field_names ) ,
fmt - > bytesperline , fmt - > sizeimage , fmt - > colorspace ) ;
} ;
static inline void v4l_print_ext_ctrls ( unsigned int cmd ,
struct video_device * vfd , struct v4l2_ext_controls * c , int show_vals )
{
__u32 i ;
if ( ! ( vfd - > debug & V4L2_DEBUG_IOCTL_ARG ) )
return ;
dbgarg ( cmd , " " ) ;
printk ( KERN_CONT " class=0x%x " , c - > ctrl_class ) ;
for ( i = 0 ; i < c - > count ; i + + ) {
if ( show_vals )
printk ( KERN_CONT " id/val=0x%x/0x%x " ,
c - > controls [ i ] . id , c - > controls [ i ] . value ) ;
else
printk ( KERN_CONT " id=0x%x " , c - > controls [ i ] . id ) ;
}
printk ( KERN_CONT " \n " ) ;
} ;
static inline int check_ext_ctrls ( struct v4l2_ext_controls * c , int allow_priv )
{
__u32 i ;
/* zero the reserved fields */
c - > reserved [ 0 ] = c - > reserved [ 1 ] = 0 ;
for ( i = 0 ; i < c - > count ; i + + ) {
c - > controls [ i ] . reserved2 [ 0 ] = 0 ;
c - > controls [ i ] . reserved2 [ 1 ] = 0 ;
}
/* V4L2_CID_PRIVATE_BASE cannot be used as control class
when using extended controls .
Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
is it allowed for backwards compatibility .
*/
if ( ! allow_priv & & c - > ctrl_class = = V4L2_CID_PRIVATE_BASE )
return 0 ;
/* Check that all controls are from the same control class. */
for ( i = 0 ; i < c - > count ; i + + ) {
if ( V4L2_CTRL_ID2CLASS ( c - > controls [ i ] . id ) ! = c - > ctrl_class ) {
c - > error_idx = i ;
return 0 ;
}
}
return 1 ;
}
2008-07-21 09:57:38 +04:00
static int check_fmt ( const struct v4l2_ioctl_ops * ops , enum v4l2_buf_type type )
2008-07-20 15:12:02 +04:00
{
2008-07-21 09:57:38 +04:00
if ( ops = = NULL )
return - EINVAL ;
2008-07-20 15:12:02 +04:00
switch ( type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vid_cap )
2008-07-20 15:12:02 +04:00
return 0 ;
break ;
case V4L2_BUF_TYPE_VIDEO_OVERLAY :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vid_overlay )
2008-07-20 15:12:02 +04:00
return 0 ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vid_out )
2008-07-20 15:12:02 +04:00
return 0 ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vid_out_overlay )
2008-07-20 15:12:02 +04:00
return 0 ;
break ;
case V4L2_BUF_TYPE_VBI_CAPTURE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vbi_cap )
2008-07-20 15:12:02 +04:00
return 0 ;
break ;
case V4L2_BUF_TYPE_VBI_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vbi_out )
2008-07-20 15:12:02 +04:00
return 0 ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_sliced_vbi_cap )
2008-07-20 15:12:02 +04:00
return 0 ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_sliced_vbi_out )
2008-07-20 15:12:02 +04:00
return 0 ;
break ;
case V4L2_BUF_TYPE_PRIVATE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_type_private )
2008-07-20 15:12:02 +04:00
return 0 ;
break ;
}
return - EINVAL ;
}
2008-12-30 13:04:34 +03:00
static long __video_do_ioctl ( struct file * file ,
2008-07-20 15:12:02 +04:00
unsigned int cmd , void * arg )
{
struct video_device * vfd = video_devdata ( file ) ;
2008-07-21 09:57:38 +04:00
const struct v4l2_ioctl_ops * ops = vfd - > ioctl_ops ;
2008-10-18 20:39:53 +04:00
void * fh = file - > private_data ;
2008-12-30 13:04:34 +03:00
long ret = - EINVAL ;
2008-07-20 15:12:02 +04:00
if ( ( vfd - > debug & V4L2_DEBUG_IOCTL ) & &
! ( vfd - > debug & V4L2_DEBUG_IOCTL_ARG ) ) {
v4l_print_ioctl ( vfd - > name , cmd ) ;
printk ( KERN_CONT " \n " ) ;
}
2008-07-21 09:57:38 +04:00
if ( ops = = NULL ) {
printk ( KERN_WARNING " videodev: \" %s \" has no ioctl_ops. \n " ,
vfd - > name ) ;
return - EINVAL ;
}
2008-07-20 15:12:02 +04:00
# ifdef CONFIG_VIDEO_V4L1_COMPAT
/***********************************************************
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* --- streaming capture ------------------------------------- */
if ( cmd = = VIDIOCGMBUF ) {
struct video_mbuf * p = arg ;
memset ( p , 0 , sizeof ( * p ) ) ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidiocgmbuf )
2008-07-20 15:12:02 +04:00
return ret ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidiocgmbuf ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " size=%d, frames=%d, offsets=0x%08lx \n " ,
p - > size , p - > frames ,
( unsigned long ) p - > offsets ) ;
return ret ;
}
/********************************************************
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-09-03 23:46:50 +04:00
if ( _IOC_TYPE ( cmd ) = = ' v ' & & _IOC_NR ( cmd ) < BASE_VIDIOCPRIVATE )
2008-10-21 18:27:20 +04:00
return v4l_compat_translate_ioctl ( file , cmd , arg ,
2008-07-20 15:12:02 +04:00
__video_do_ioctl ) ;
# endif
switch ( cmd ) {
/* --- capabilities ------------------------------------------ */
case VIDIOC_QUERYCAP :
{
struct v4l2_capability * cap = ( struct v4l2_capability * ) arg ;
memset ( cap , 0 , sizeof ( * cap ) ) ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_querycap )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_querycap ( file , fh , cap ) ;
2008-07-20 15:12:02 +04:00
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 ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_priority )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_priority ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " priority is %d \n " , * p ) ;
break ;
}
case VIDIOC_S_PRIORITY :
{
enum v4l2_priority * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_priority )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " setting priority to %d \n " , * p ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_priority ( file , fh , * p ) ;
2008-07-20 15:12:02 +04:00
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 :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_enum_fmt_vid_cap )
ret = ops - > vidioc_enum_fmt_vid_cap ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
break ;
case V4L2_BUF_TYPE_VIDEO_OVERLAY :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_enum_fmt_vid_overlay )
ret = ops - > vidioc_enum_fmt_vid_overlay ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_enum_fmt_vid_out )
ret = ops - > vidioc_enum_fmt_vid_out ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
break ;
case V4L2_BUF_TYPE_PRIVATE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_enum_fmt_type_private )
ret = ops - > vidioc_enum_fmt_type_private ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
default :
break ;
}
if ( ! ret )
dbgarg ( cmd , " index=%d, type=%d, flags=%d, "
" pixelformat=%c%c%c%c, description='%s' \n " ,
f - > index , f - > type , f - > flags ,
( f - > pixelformat & 0xff ) ,
( f - > pixelformat > > 8 ) & 0xff ,
( f - > pixelformat > > 16 ) & 0xff ,
( f - > pixelformat > > 24 ) & 0xff ,
f - > description ) ;
break ;
}
case VIDIOC_G_FMT :
{
struct v4l2_format * f = ( struct v4l2_format * ) arg ;
memset ( f - > fmt . raw_data , 0 , sizeof ( f - > fmt . raw_data ) ) ;
/* FIXME: Should be one dump per type */
dbgarg ( cmd , " type=%s \n " , prt_names ( f - > type , v4l2_type_names ) ) ;
switch ( f - > type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_fmt_vid_cap )
ret = ops - > vidioc_g_fmt_vid_cap ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
v4l_print_pix_fmt ( vfd , & f - > fmt . pix ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OVERLAY :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_fmt_vid_overlay )
ret = ops - > vidioc_g_fmt_vid_overlay ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_fmt_vid_out )
ret = ops - > vidioc_g_fmt_vid_out ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
v4l_print_pix_fmt ( vfd , & f - > fmt . pix ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_fmt_vid_out_overlay )
ret = ops - > vidioc_g_fmt_vid_out_overlay ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_VBI_CAPTURE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_fmt_vbi_cap )
ret = ops - > vidioc_g_fmt_vbi_cap ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
break ;
case V4L2_BUF_TYPE_VBI_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_fmt_vbi_out )
ret = ops - > vidioc_g_fmt_vbi_out ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
break ;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_fmt_sliced_vbi_cap )
ret = ops - > vidioc_g_fmt_sliced_vbi_cap ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_fmt_sliced_vbi_out )
ret = ops - > vidioc_g_fmt_sliced_vbi_out ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_PRIVATE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_fmt_type_private )
ret = ops - > vidioc_g_fmt_type_private ( file ,
2008-07-20 15:12:02 +04:00
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 , v4l2_type_names ) ) ;
switch ( f - > type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
v4l_print_pix_fmt ( vfd , & f - > fmt . pix ) ;
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_s_fmt_vid_cap )
ret = ops - > vidioc_s_fmt_vid_cap ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
break ;
case V4L2_BUF_TYPE_VIDEO_OVERLAY :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_s_fmt_vid_overlay )
ret = ops - > vidioc_s_fmt_vid_overlay ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT :
v4l_print_pix_fmt ( vfd , & f - > fmt . pix ) ;
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_s_fmt_vid_out )
ret = ops - > vidioc_s_fmt_vid_out ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_s_fmt_vid_out_overlay )
ret = ops - > vidioc_s_fmt_vid_out_overlay ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_VBI_CAPTURE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_s_fmt_vbi_cap )
ret = ops - > vidioc_s_fmt_vbi_cap ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
break ;
case V4L2_BUF_TYPE_VBI_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_s_fmt_vbi_out )
ret = ops - > vidioc_s_fmt_vbi_out ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
break ;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_s_fmt_sliced_vbi_cap )
ret = ops - > vidioc_s_fmt_sliced_vbi_cap ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_s_fmt_sliced_vbi_out )
ret = ops - > vidioc_s_fmt_sliced_vbi_out ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_PRIVATE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_s_fmt_type_private )
ret = ops - > vidioc_s_fmt_type_private ( file ,
2008-07-20 15:12:02 +04:00
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 ,
v4l2_type_names ) ) ;
switch ( f - > type ) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vid_cap )
ret = ops - > vidioc_try_fmt_vid_cap ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
v4l_print_pix_fmt ( vfd , & f - > fmt . pix ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OVERLAY :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vid_overlay )
ret = ops - > vidioc_try_fmt_vid_overlay ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vid_out )
ret = ops - > vidioc_try_fmt_vid_out ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
v4l_print_pix_fmt ( vfd , & f - > fmt . pix ) ;
break ;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vid_out_overlay )
ret = ops - > vidioc_try_fmt_vid_out_overlay ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_VBI_CAPTURE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vbi_cap )
ret = ops - > vidioc_try_fmt_vbi_cap ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
break ;
case V4L2_BUF_TYPE_VBI_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_vbi_out )
ret = ops - > vidioc_try_fmt_vbi_out ( file , fh , f ) ;
2008-07-20 15:12:02 +04:00
break ;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_sliced_vbi_cap )
ret = ops - > vidioc_try_fmt_sliced_vbi_cap ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_sliced_vbi_out )
ret = ops - > vidioc_try_fmt_sliced_vbi_out ( file ,
2008-07-20 15:12:02 +04:00
fh , f ) ;
break ;
case V4L2_BUF_TYPE_PRIVATE :
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_try_fmt_type_private )
ret = ops - > vidioc_try_fmt_type_private ( file ,
2008-07-20 15:12:02 +04:00
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 ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_reqbufs )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = check_fmt ( ops , p - > type ) ;
2008-07-20 15:12:02 +04:00
if ( ret )
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_reqbufs ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
dbgarg ( cmd , " count=%d, type=%s, memory=%s \n " ,
p - > count ,
prt_names ( p - > type , v4l2_type_names ) ,
prt_names ( p - > memory , v4l2_memory_names ) ) ;
break ;
}
case VIDIOC_QUERYBUF :
{
struct v4l2_buffer * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_querybuf )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = check_fmt ( ops , p - > type ) ;
2008-07-20 15:12:02 +04:00
if ( ret )
break ;
2009-03-04 02:44:45 +03:00
/* Zero out all fields starting with bytesysed, which is
* everything but index and type . */
memset ( 0 , & p - > bytesused ,
sizeof ( * p ) - offsetof ( typeof ( * p ) , bytesused ) ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_querybuf ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgbuf ( cmd , vfd , p ) ;
break ;
}
case VIDIOC_QBUF :
{
struct v4l2_buffer * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_qbuf )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = check_fmt ( ops , p - > type ) ;
2008-07-20 15:12:02 +04:00
if ( ret )
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_qbuf ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgbuf ( cmd , vfd , p ) ;
break ;
}
case VIDIOC_DQBUF :
{
struct v4l2_buffer * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_dqbuf )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = check_fmt ( ops , p - > type ) ;
2008-07-20 15:12:02 +04:00
if ( ret )
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_dqbuf ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgbuf ( cmd , vfd , p ) ;
break ;
}
case VIDIOC_OVERLAY :
{
int * i = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_overlay )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " value=%d \n " , * i ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_overlay ( file , fh , * i ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_G_FBUF :
{
struct v4l2_framebuffer * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_fbuf )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_fbuf ( file , fh , arg ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret ) {
dbgarg ( cmd , " capability=0x%x, 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 ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_fbuf )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " capability=0x%x, flags=%d, base=0x%08lx \n " ,
p - > capability , p - > flags , ( unsigned long ) p - > base ) ;
v4l_print_pix_fmt ( vfd , & p - > fmt ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_fbuf ( file , fh , arg ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_STREAMON :
{
enum v4l2_buf_type i = * ( int * ) arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_streamon )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " type=%s \n " , prt_names ( i , v4l2_type_names ) ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_streamon ( file , fh , i ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_STREAMOFF :
{
enum v4l2_buf_type i = * ( int * ) arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_streamoff )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " type=%s \n " , prt_names ( i , v4l2_type_names ) ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_streamoff ( file , fh , i ) ;
2008-07-20 15:12:02 +04:00
break ;
}
/* ---------- tv norms ---------- */
case VIDIOC_ENUMSTD :
{
struct v4l2_standard * p = arg ;
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 )
break ;
if ( curr_id ! = V4L2_STD_PAL & &
curr_id ! = V4L2_STD_SECAM & &
curr_id ! = V4L2_STD_NTSC )
id & = ~ curr_id ;
}
if ( i < = index )
return - EINVAL ;
v4l2_video_std_construct ( p , curr_id , descr ) ;
p - > index = index ;
dbgarg ( cmd , " index=%d, id=0x%Lx, name=%s, fps=%d/%d, "
" framelines=%d \n " , p - > index ,
( unsigned long long ) p - > id , p - > name ,
p - > frameperiod . numerator ,
p - > frameperiod . denominator ,
p - > framelines ) ;
ret = 0 ;
break ;
}
case VIDIOC_G_STD :
{
v4l2_std_id * id = arg ;
ret = 0 ;
/* Calls the specific handler */
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_std )
ret = ops - > vidioc_g_std ( file , fh , id ) ;
2008-07-20 15:12:02 +04:00
else
* id = vfd - > current_norm ;
if ( ! ret )
dbgarg ( cmd , " std=0x%08Lx \n " , ( long long unsigned ) * id ) ;
break ;
}
case VIDIOC_S_STD :
{
v4l2_std_id * id = arg , norm ;
dbgarg ( cmd , " std=%08Lx \n " , ( long long unsigned ) * id ) ;
norm = ( * id ) & vfd - > tvnorms ;
if ( vfd - > tvnorms & & ! norm ) /* Check if std is supported */
break ;
/* Calls the specific handler */
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_s_std )
ret = ops - > vidioc_s_std ( file , fh , & norm ) ;
2008-07-20 15:12:02 +04:00
else
ret = - EINVAL ;
/* Updates standard information */
if ( ret > = 0 )
vfd - > current_norm = norm ;
break ;
}
case VIDIOC_QUERYSTD :
{
v4l2_std_id * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_querystd )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_querystd ( file , fh , arg ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " detected std=%08Lx \n " ,
( 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 ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_enum_input )
2008-07-20 15:12:02 +04:00
break ;
memset ( p , 0 , sizeof ( * p ) ) ;
p - > index = i ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_enum_input ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " index=%d, name=%s, type=%d, "
" audioset=%d, "
" tuner=%d, std=%08Lx, status=%d \n " ,
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 ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_input )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_input ( file , fh , i ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " value=%d \n " , * i ) ;
break ;
}
case VIDIOC_S_INPUT :
{
unsigned int * i = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_input )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " value=%d \n " , * i ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_input ( file , fh , * i ) ;
2008-07-20 15:12:02 +04:00
break ;
}
/* ------ output switching ---------- */
case VIDIOC_ENUMOUTPUT :
{
struct v4l2_output * p = arg ;
int i = p - > index ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_enum_output )
2008-07-20 15:12:02 +04:00
break ;
memset ( p , 0 , sizeof ( * p ) ) ;
p - > index = i ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_enum_output ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " index=%d, name=%s, type=%d, "
" audioset=0x%x, "
" modulator=%d, std=0x%08Lx \n " ,
p - > index , p - > name , p - > type , p - > audioset ,
p - > modulator , ( unsigned long long ) p - > std ) ;
break ;
}
case VIDIOC_G_OUTPUT :
{
unsigned int * i = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_output )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_output ( file , fh , i ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " value=%d \n " , * i ) ;
break ;
}
case VIDIOC_S_OUTPUT :
{
unsigned int * i = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_output )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " value=%d \n " , * i ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_output ( file , fh , * i ) ;
2008-07-20 15:12:02 +04:00
break ;
}
/* --- controls ---------------------------------------------- */
case VIDIOC_QUERYCTRL :
{
struct v4l2_queryctrl * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_queryctrl )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_queryctrl ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " id=0x%x, 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 ) ;
else
dbgarg ( cmd , " id=0x%x \n " , p - > id ) ;
break ;
}
case VIDIOC_G_CTRL :
{
struct v4l2_control * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_ctrl )
ret = ops - > vidioc_g_ctrl ( file , fh , p ) ;
else if ( ops - > vidioc_g_ext_ctrls ) {
2008-07-20 15:12:02 +04:00
struct v4l2_ext_controls ctrls ;
struct v4l2_ext_control ctrl ;
ctrls . ctrl_class = V4L2_CTRL_ID2CLASS ( p - > id ) ;
ctrls . count = 1 ;
ctrls . controls = & ctrl ;
ctrl . id = p - > id ;
ctrl . value = p - > value ;
if ( check_ext_ctrls ( & ctrls , 1 ) ) {
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_ext_ctrls ( file , fh , & ctrls ) ;
2008-07-20 15:12:02 +04:00
if ( ret = = 0 )
p - > value = ctrl . value ;
}
} else
break ;
if ( ! ret )
dbgarg ( cmd , " id=0x%x, value=%d \n " , p - > id , p - > value ) ;
else
dbgarg ( cmd , " id=0x%x \n " , p - > id ) ;
break ;
}
case VIDIOC_S_CTRL :
{
struct v4l2_control * p = arg ;
struct v4l2_ext_controls ctrls ;
struct v4l2_ext_control ctrl ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_ctrl & & ! ops - > vidioc_s_ext_ctrls )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " id=0x%x, value=%d \n " , p - > id , p - > value ) ;
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_s_ctrl ) {
ret = ops - > vidioc_s_ctrl ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_ext_ctrls )
2008-07-20 15:12:02 +04:00
break ;
ctrls . ctrl_class = V4L2_CTRL_ID2CLASS ( p - > id ) ;
ctrls . count = 1 ;
ctrls . controls = & ctrl ;
ctrl . id = p - > id ;
ctrl . value = p - > value ;
if ( check_ext_ctrls ( & ctrls , 1 ) )
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_ext_ctrls ( file , fh , & ctrls ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_G_EXT_CTRLS :
{
struct v4l2_ext_controls * p = arg ;
p - > error_idx = p - > count ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_ext_ctrls )
2008-07-20 15:12:02 +04:00
break ;
if ( check_ext_ctrls ( p , 0 ) )
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_ext_ctrls ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
v4l_print_ext_ctrls ( cmd , vfd , p , ! ret ) ;
break ;
}
case VIDIOC_S_EXT_CTRLS :
{
struct v4l2_ext_controls * p = arg ;
p - > error_idx = p - > count ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_ext_ctrls )
2008-07-20 15:12:02 +04:00
break ;
v4l_print_ext_ctrls ( cmd , vfd , p , 1 ) ;
if ( check_ext_ctrls ( p , 0 ) )
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_ext_ctrls ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_TRY_EXT_CTRLS :
{
struct v4l2_ext_controls * p = arg ;
p - > error_idx = p - > count ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_try_ext_ctrls )
2008-07-20 15:12:02 +04:00
break ;
v4l_print_ext_ctrls ( cmd , vfd , p , 1 ) ;
if ( check_ext_ctrls ( p , 0 ) )
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_try_ext_ctrls ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_QUERYMENU :
{
struct v4l2_querymenu * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_querymenu )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_querymenu ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " id=0x%x, index=%d, name=%s \n " ,
p - > id , p - > index , p - > name ) ;
else
dbgarg ( cmd , " id=0x%x, index=%d \n " ,
p - > id , p - > index ) ;
break ;
}
/* --- audio ---------------------------------------------- */
case VIDIOC_ENUMAUDIO :
{
struct v4l2_audio * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_enumaudio )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_enumaudio ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " index=%d, name=%s, capability=0x%x, "
" mode=0x%x \n " , p - > index , p - > name ,
p - > capability , p - > mode ) ;
else
dbgarg ( cmd , " index=%d \n " , p - > index ) ;
break ;
}
case VIDIOC_G_AUDIO :
{
struct v4l2_audio * p = arg ;
__u32 index = p - > index ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_audio )
2008-07-20 15:12:02 +04:00
break ;
memset ( p , 0 , sizeof ( * p ) ) ;
p - > index = index ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_audio ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " index=%d, name=%s, capability=0x%x, "
" mode=0x%x \n " , p - > index ,
p - > name , p - > capability , p - > mode ) ;
else
dbgarg ( cmd , " index=%d \n " , p - > index ) ;
break ;
}
case VIDIOC_S_AUDIO :
{
struct v4l2_audio * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_audio )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " index=%d, name=%s, capability=0x%x, "
" mode=0x%x \n " , p - > index , p - > name ,
p - > capability , p - > mode ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_audio ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_ENUMAUDOUT :
{
struct v4l2_audioout * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_enumaudout )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " Enum for index=%d \n " , p - > index ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_enumaudout ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
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 ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_audout )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " Enum for index=%d \n " , p - > index ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_audout ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
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 ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_audout )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " index=%d, name=%s, capability=%d, "
" mode=%d \n " , p - > index , p - > name ,
p - > capability , p - > mode ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_audout ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_G_MODULATOR :
{
struct v4l2_modulator * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_modulator )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_modulator ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
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 ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_modulator )
2008-07-20 15:12:02 +04:00
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 ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_modulator ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_G_CROP :
{
struct v4l2_crop * p = arg ;
2008-11-12 03:15:03 +03:00
__u32 type ;
2008-07-20 15:12:02 +04:00
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_crop )
2008-07-20 15:12:02 +04:00
break ;
2008-11-12 03:15:03 +03:00
type = p - > type ;
memset ( p , 0 , sizeof ( * p ) ) ;
p - > type = type ;
2008-07-20 15:12:02 +04:00
dbgarg ( cmd , " type=%s \n " , prt_names ( p - > type , v4l2_type_names ) ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_crop ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgrect ( vfd , " " , & p - > c ) ;
break ;
}
case VIDIOC_S_CROP :
{
struct v4l2_crop * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_crop )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " type=%s \n " , prt_names ( p - > type , v4l2_type_names ) ) ;
dbgrect ( vfd , " " , & p - > c ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_crop ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_CROPCAP :
{
struct v4l2_cropcap * p = arg ;
2008-11-12 03:15:03 +03:00
__u32 type ;
2008-07-20 15:12:02 +04:00
/*FIXME: Should also show v4l2_fract pixelaspect */
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_cropcap )
2008-07-20 15:12:02 +04:00
break ;
2008-11-12 03:15:03 +03:00
type = p - > type ;
memset ( p , 0 , sizeof ( * p ) ) ;
p - > type = type ;
2008-07-20 15:12:02 +04:00
dbgarg ( cmd , " type=%s \n " , prt_names ( p - > type , v4l2_type_names ) ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_cropcap ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret ) {
dbgrect ( vfd , " bounds " , & p - > bounds ) ;
dbgrect ( vfd , " defrect " , & p - > defrect ) ;
}
break ;
}
case VIDIOC_G_JPEGCOMP :
{
struct v4l2_jpegcompression * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_jpegcomp )
2008-07-20 15:12:02 +04:00
break ;
2008-11-12 03:15:03 +03:00
memset ( p , 0 , sizeof ( * p ) ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_jpegcomp ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
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 ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_jpegcomp )
2008-07-20 15:12:02 +04:00
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 ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_jpegcomp ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_G_ENC_INDEX :
{
struct v4l2_enc_idx * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_enc_index )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_enc_index ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " entries=%d, entries_cap=%d \n " ,
p - > entries , p - > entries_cap ) ;
break ;
}
case VIDIOC_ENCODER_CMD :
{
struct v4l2_encoder_cmd * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_encoder_cmd )
2008-07-20 15:12:02 +04:00
break ;
memset ( & p - > raw , 0 , sizeof ( p - > raw ) ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_encoder_cmd ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " cmd=%d, flags=%x \n " , p - > cmd , p - > flags ) ;
break ;
}
case VIDIOC_TRY_ENCODER_CMD :
{
struct v4l2_encoder_cmd * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_try_encoder_cmd )
2008-07-20 15:12:02 +04:00
break ;
memset ( & p - > raw , 0 , sizeof ( p - > raw ) ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_try_encoder_cmd ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " cmd=%d, flags=%x \n " , p - > cmd , p - > flags ) ;
break ;
}
case VIDIOC_G_PARM :
{
struct v4l2_streamparm * p = arg ;
__u32 type = p - > type ;
memset ( p , 0 , sizeof ( * p ) ) ;
p - > type = type ;
2008-07-21 09:57:38 +04:00
if ( ops - > vidioc_g_parm ) {
ret = ops - > vidioc_g_parm ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
} else {
struct v4l2_standard s ;
if ( p - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE )
return - EINVAL ;
v4l2_video_std_construct ( & s , vfd - > current_norm ,
v4l2_norm_to_name ( vfd - > current_norm ) ) ;
p - > parm . capture . timeperframe = s . frameperiod ;
ret = 0 ;
}
dbgarg ( cmd , " type=%d \n " , p - > type ) ;
break ;
}
case VIDIOC_S_PARM :
{
struct v4l2_streamparm * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_parm )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " type=%d \n " , p - > type ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_parm ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_G_TUNER :
{
struct v4l2_tuner * p = arg ;
__u32 index = p - > index ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_tuner )
2008-07-20 15:12:02 +04:00
break ;
memset ( p , 0 , sizeof ( * p ) ) ;
p - > index = index ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_tuner ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " index=%d, name=%s, type=%d, "
" capability=0x%x, rangelow=%d, "
" rangehigh=%d, signal=%d, afc=%d, "
" rxsubchans=0x%x, audmode=%d \n " ,
p - > index , p - > name , p - > type ,
p - > capability , p - > rangelow ,
p - > rangehigh , p - > signal , p - > afc ,
p - > rxsubchans , p - > audmode ) ;
break ;
}
case VIDIOC_S_TUNER :
{
struct v4l2_tuner * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_tuner )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " index=%d, name=%s, type=%d, "
" capability=0x%x, rangelow=%d, "
" rangehigh=%d, signal=%d, afc=%d, "
" rxsubchans=0x%x, audmode=%d \n " ,
p - > index , p - > name , p - > type ,
p - > capability , p - > rangelow ,
p - > rangehigh , p - > signal , p - > afc ,
p - > rxsubchans , p - > audmode ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_tuner ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_G_FREQUENCY :
{
struct v4l2_frequency * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_frequency )
2008-07-20 15:12:02 +04:00
break ;
memset ( p - > reserved , 0 , sizeof ( p - > reserved ) ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_frequency ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
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 ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_frequency )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd , " tuner=%d, type=%d, frequency=%d \n " ,
p - > tuner , p - > type , p - > frequency ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_frequency ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_G_SLICED_VBI_CAP :
{
struct v4l2_sliced_vbi_cap * p = arg ;
__u32 type = p - > type ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_sliced_vbi_cap )
2008-07-20 15:12:02 +04:00
break ;
memset ( p , 0 , sizeof ( * p ) ) ;
p - > type = type ;
dbgarg ( cmd , " type=%s \n " , prt_names ( p - > type , v4l2_type_names ) ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_sliced_vbi_cap ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg2 ( " service_set=%d \n " , p - > service_set ) ;
break ;
}
case VIDIOC_LOG_STATUS :
{
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_log_status )
2008-07-20 15:12:02 +04:00
break ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_log_status ( file , fh ) ;
2008-07-20 15:12:02 +04:00
break ;
}
# ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_DBG_G_REGISTER :
{
2008-12-30 13:14:19 +03:00
struct v4l2_dbg_register * p = arg ;
2008-07-20 15:12:02 +04:00
if ( ! capable ( CAP_SYS_ADMIN ) )
ret = - EPERM ;
2008-07-21 09:57:38 +04:00
else if ( ops - > vidioc_g_register )
ret = ops - > vidioc_g_register ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
case VIDIOC_DBG_S_REGISTER :
{
2008-12-30 13:14:19 +03:00
struct v4l2_dbg_register * p = arg ;
2008-07-20 15:12:02 +04:00
if ( ! capable ( CAP_SYS_ADMIN ) )
ret = - EPERM ;
2008-07-21 09:57:38 +04:00
else if ( ops - > vidioc_s_register )
ret = ops - > vidioc_s_register ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
break ;
}
# endif
2008-12-30 13:14:19 +03:00
case VIDIOC_DBG_G_CHIP_IDENT :
2008-07-20 15:12:02 +04:00
{
2008-12-30 13:14:19 +03:00
struct v4l2_dbg_chip_ident * p = arg ;
2008-07-20 15:12:02 +04:00
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_g_chip_ident )
2008-07-20 15:12:02 +04:00
break ;
2009-02-07 17:00:02 +03:00
p - > ident = V4L2_IDENT_NONE ;
p - > revision = 0 ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_g_chip_ident ( file , fh , p ) ;
2008-07-20 15:12:02 +04:00
if ( ! ret )
dbgarg ( cmd , " chip_ident=%u, revision=0x%x \n " , p - > ident , p - > revision ) ;
break ;
}
2008-12-30 13:14:19 +03:00
case VIDIOC_G_CHIP_IDENT_OLD :
printk ( KERN_ERR " VIDIOC_G_CHIP_IDENT has been deprecated and will disappear in 2.6.30. \n " ) ;
printk ( KERN_ERR " It is a debugging ioctl and must not be used in applications! \n " ) ;
return - EINVAL ;
2008-07-20 15:12:02 +04:00
case VIDIOC_S_HW_FREQ_SEEK :
{
struct v4l2_hw_freq_seek * p = arg ;
2008-07-21 09:57:38 +04:00
if ( ! ops - > vidioc_s_hw_freq_seek )
2008-07-20 15:12:02 +04:00
break ;
dbgarg ( cmd ,
" tuner=%d, type=%d, seek_upward=%d, wrap_around=%d \n " ,
p - > tuner , p - > type , p - > seek_upward , p - > wrap_around ) ;
2008-07-21 09:57:38 +04:00
ret = ops - > vidioc_s_hw_freq_seek ( file , fh , p ) ;
break ;
}
2008-11-12 03:13:47 +03:00
case VIDIOC_ENUM_FRAMESIZES :
{
struct v4l2_frmsizeenum * p = arg ;
if ( ! ops - > vidioc_enum_framesizes )
break ;
memset ( p , 0 , sizeof ( * p ) ) ;
ret = ops - > vidioc_enum_framesizes ( file , fh , p ) ;
dbgarg ( cmd ,
" index=%d, pixelformat=%d, type=%d " ,
p - > index , p - > pixel_format , p - > type ) ;
switch ( p - > type ) {
case V4L2_FRMSIZE_TYPE_DISCRETE :
dbgarg2 ( " width = %d, height=%d \n " ,
p - > discrete . width , p - > discrete . height ) ;
break ;
case V4L2_FRMSIZE_TYPE_STEPWISE :
dbgarg2 ( " min %dx%d, max %dx%d, step %dx%d \n " ,
p - > stepwise . min_width , p - > stepwise . min_height ,
p - > stepwise . step_width , p - > stepwise . step_height ,
p - > stepwise . max_width , p - > stepwise . max_height ) ;
break ;
case V4L2_FRMSIZE_TYPE_CONTINUOUS :
dbgarg2 ( " continuous \n " ) ;
break ;
default :
dbgarg2 ( " - Unknown type! \n " ) ;
}
break ;
}
case VIDIOC_ENUM_FRAMEINTERVALS :
{
struct v4l2_frmivalenum * p = arg ;
if ( ! ops - > vidioc_enum_frameintervals )
break ;
memset ( p , 0 , sizeof ( * p ) ) ;
ret = ops - > vidioc_enum_frameintervals ( file , fh , p ) ;
dbgarg ( cmd ,
" index=%d, pixelformat=%d, width=%d, height=%d, type=%d " ,
p - > index , p - > pixel_format ,
p - > width , p - > height , p - > type ) ;
switch ( p - > type ) {
case V4L2_FRMIVAL_TYPE_DISCRETE :
dbgarg2 ( " fps=%d/%d \n " ,
p - > discrete . numerator ,
p - > discrete . denominator ) ;
break ;
case V4L2_FRMIVAL_TYPE_STEPWISE :
2008-11-12 07:03:02 +03:00
dbgarg2 ( " min=%d/%d, max=%d/%d, step=%d/%d \n " ,
p - > stepwise . min . numerator ,
p - > stepwise . min . denominator ,
p - > stepwise . max . numerator ,
p - > stepwise . max . denominator ,
p - > stepwise . step . numerator ,
p - > stepwise . step . denominator ) ;
2008-11-12 03:13:47 +03:00
break ;
case V4L2_FRMIVAL_TYPE_CONTINUOUS :
dbgarg2 ( " continuous \n " ) ;
break ;
default :
dbgarg2 ( " - Unknown type! \n " ) ;
}
break ;
}
2008-07-21 09:57:38 +04:00
default :
{
if ( ! ops - > vidioc_default )
break ;
ret = ops - > vidioc_default ( file , fh , cmd , arg ) ;
2008-07-20 15:12:02 +04:00
break ;
}
} /* switch */
if ( vfd - > debug & V4L2_DEBUG_IOCTL_ARG ) {
if ( ret < 0 ) {
v4l_print_ioctl ( vfd - > name , cmd ) ;
2008-12-30 13:04:34 +03:00
printk ( KERN_CONT " error %ld \n " , ret ) ;
2008-07-20 15:12:02 +04:00
}
}
return ret ;
}
2008-12-30 13:04:34 +03:00
long video_ioctl2 ( struct file * file ,
2008-07-20 15:12:02 +04:00
unsigned int cmd , unsigned long arg )
{
char sbuf [ 128 ] ;
void * mbuf = NULL ;
void * parg = NULL ;
2008-12-30 13:04:34 +03:00
long err = - EINVAL ;
2008-07-20 15:12:02 +04:00
int is_ext_ctrl ;
size_t ctrls_size = 0 ;
void __user * user_ptr = NULL ;
# ifdef __OLD_VIDIOC_
cmd = video_fix_command ( cmd ) ;
# endif
is_ext_ctrl = ( cmd = = VIDIOC_S_EXT_CTRLS | | cmd = = VIDIOC_G_EXT_CTRLS | |
cmd = = VIDIOC_TRY_EXT_CTRLS ) ;
/* 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 ;
}
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 ;
}
}
/* Handles IOCTL */
2008-10-21 18:27:20 +04:00
err = __video_do_ioctl ( file , cmd , parg ) ;
2008-07-20 15:12:02 +04:00
if ( err = = - ENOIOCTLCMD )
err = - EINVAL ;
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 ;
}
if ( err < 0 )
goto out ;
out_ext_ctrl :
/* 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-10-21 18:58:39 +04:00
EXPORT_SYMBOL ( video_ioctl2 ) ;