在应用程序获取视频数据的流程中,都是通过 ioctl 命令与驱动程序进行交互,常见的 ioctl 命令有:
[cpp]
VIDIOC_QUERYCAP     /* 获取设备支持的操作 */ 
VIDIOC_G_FMT        /* 获取设置支持的视频格式 */ 
VIDIOC_S_FMT        /* 设置捕获视频的格式 */ 
VIDIOC_REQBUFS      /* 向驱动提出申请内存的请求 */ 
VIDIOC_QUERYBUF     /* 向驱动查询申请到的内存 */ 
VIDIOC_QBUF         /* 将空闲的内存加入可捕获视频的队列 */ 
VIDIOC_DQBUF        /* 将已经捕获好视频的内存拉出已捕获视频的队列 */ 
VIDIOC_STREAMON     /* 打开视频流 */ 
VIDIOC_STREAMOFF    /* 关闭视频流 */ 
VIDIOC_QUERYCTRL    /* 查询驱动是否支持该命令 */ 
VIDIOC_G_CTRL       /* 获取当前命令值 */ 
VIDIOC_S_CTRL       /* 设置新的命令值 */ 
VIDIOC_G_TUNER      /* 获取调谐器信息 */ 
VIDIOC_S_TUNER      /* 设置调谐器信息 */ 
VIDIOC_G_FREQUENCY  /* 获取调谐器频率 */ 
VIDIOC_S_FREQUENCY  /* 设置调谐器频率 */ 
1、struct v4l2_capability 与 VIDIOC_QUERYCAP
VIDIOC_QUERYCAP 命令通过结构 v4l2_capability 获取设备支持的操作模式:
[cpp]
struct v4l2_capability { 
    __u8    driver[16];     /* i.e. "bttv" */ 
    __u8    card[32];       /* i.e. "Hauppauge WinTV" */ 
    __u8    bus_info[32];   /* "PCI:" + pci_name(pci_dev) */ 
    __u32   version;        /* should use KERNEL_VERSION() */ 
    __u32   capabilities;   /* Device capabilities */ 
    __u32   reserved[4]; 
}; 
其中域 capabilities 代表设备支持的操作模式,常见的值有 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING 表示是一个视频捕捉设备并且具有数据流控制模式;另外 driver 域需要和 struct video_device 中的 name 匹配。
2、struct v4l2_format 与 VIDIOC_G_FMT、VIDIOC_S_FMT、VIDIOC_TRY_FMT
通常用 VIDIOC_S_FMT 命令通过结构 v4l2_format 初始化捕获视频的格式,如果要改变格式则用 VIDIOC_TRY_FMT 命令:
[cpp] 
struct v4l2_format { 
    enum v4l2_buf_type type; 
    union { 
        struct v4l2_pix_format         pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ 
        struct v4l2_window             win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ 
        struct v4l2_vbi_format         vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */ 
        struct v4l2_sliced_vbi_format  sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */ 
        __u8   raw_data[200];                   /* user-defined */ 
    } fmt; 
}; 
其中 
enum v4l2_buf_type { 
    V4L2_BUF_TYPE_VIDEO_CAPTURE        = 1, 
    V4L2_BUF_TYPE_VIDEO_OUTPUT         = 2, 
    V4L2_BUF_TYPE_VIDEO_OVERLAY        = 3, 
    ... 
    V4L2_BUF_TYPE_PRIVATE              = 0x80, 
}; 
 
struct v4l2_pix_format { 
    __u32                   width; 
    __u32                   height; 
    __u32                   pixelformat; 
    enum v4l2_field         field; 
    __u32                   bytesperline;   /* for padding, zero if unused */ 
    __u32                   sizeimage; 
    enum v4l2_colorspace    colorspace; 
    __u32                   priv;           /* private data, depends on pixelformat */ 
}; 
常见的捕获模式为 V4L2_BUF_TYPE_VIDEO_CAPTURE 即视频捕捉模式,在此模式下 fmt 联合体采用域 v4l2_pix_format:其中 width 为视频的宽、height 为视频的高、pixelformat 为视频数据格式(常见的值有 V4L2_PIX_FMT_YUV422P | V4L2_PIX_FMT_RGB565)、bytesperline 为一行图像占用的字节数、sizeimage 则为图像占用的总字节数、colorspace 指定设备的颜色空间。
3、struct v4l2_requestbuffers 与 VIDIOC_REQBUFS
VIDIOC_REQBUFS 命令通过结构 v4l2_requestbuffers 请求驱动申请一片连续的内存用于缓存视频信息:
[cpp] 
struct v4l2_requestbuffers { 
    __u32                   count; 
    enum v4l2_buf_type      type; 
    enum v4l2_memory        memory; 
    __u32                   reserved[2]; 
}; 
其中 
enum v4l2_memory { 
    V4L2_MEMORY_MMAP             = 1, 
    V4L2_MEMORY_USERPTR          = 2, 
    V4L2_MEMORY_OVERLAY          = 3, 
}; 
count 指定根据图像占用空间大小申请的缓存区个数,type 为视频捕获模式,memory 为内存区的使用方式。
4、struct v4l2_buffer与 VIDIOC_QUERYBUF
VIDIOC_QUERYBUF 命令通过结构 v4l2_buffer 查询驱动申请的内存区信息:
[cpp] 
struct v4l2_buffer { 
    __u32                   index; 
    enum v4l2_buf_type      type; 
    __u32                   bytesused; 
    __u32                   flags; 
    enum v4l2_field         field; 
    struct timeval          timestamp; 
    struct v4l2_timecode    timecode; 
    __u32                   sequence; 
 
    /* memory location */ 
    enum v4l2_memory        memory; 
    union { 
            __u32           offset; 
            unsigned long   userptr; 
    } m; 
    __u32                   length; 
    __u32                   input; 
    __u32                   reserved; 
}; 
index 为缓存编号,type 为视频捕获模式,bytesused 为缓存已使用空间大小,flags 为缓存当前状态(常见值有 V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE,分别代表当前缓存已经映射、缓存可以采集数据、缓存可以提取数据),timestamp 为时间戳,sequence为缓存序号,memory 为缓存使用方式,offset 为当前缓存与内存区起始地址的偏移,length 为缓存大小,reserved 一般用于传递物理地址值。
另外 VIDIOC_QBUF 和 VIDIOC_DQBUF 命令都采用结构 v4l2_buffer 与驱动通信:VIDIOC_QBUF 命令向驱动传递应用程序已经处理完的缓存,即将缓存加入空闲可捕获视频的队列,传递的主要参数为 index;VIDIOC_DQBUF 命令向驱动获取已经存放有视频数据的缓存,v4l2_buffer 的各个域几乎都会被更新,但主要的参数也是 index,应用程序会根据 index 确定可用数据的起始地址和范围。
5、enum v4l2_buf_type 与 VIDIOC_STREAMON、VIDIOC_STREAMOFF
这两个命令使用的只是一个整形数据,即 v4l2_buf_type,一般只要指定其值为 V4L2_BUF_TYPE_VIDEO_CAPTURE 即可。
6、struct v4l2_queryctrl 与 VIDIOC_QUERYCTRL
VIDIOC_QUERYCTRL 命令通过结构 v4l2_queryctrl 查询驱动是否支持该 id 代表的命令,并返回该命令的各种参数:
[cpp]
struct v4l2_queryctrl { 
    __u32                id;            /* 命令编号 */ 
    enum v4l2_ctrl_type  type;          /* 命令值的类型 */ 
    __u8                 name[32];      /* 命令名称*/ 
    __s32                minimum;       /* 最小的命令值 */ 
    __s32                maximum;       /* 最大的命令值 */ 
    __s32                step;          /* 命令值变化的步长 */ 
    __s32                default_value; /* 默认的命令值 */ 
    __u32                flags;         /* 命令的标志 */ 
    __u32                reserved[2];   /* 命令值的位图表示 */ 
}; 
其中 
enum v4l2_ctrl_type { 
    V4L2_CTRL_TYPE_INTEGER       = 1,   /* 整形 */ 
    V4L2_CTRL_TYPE_BOOLEAN       = 2,   /* 真值 */ 
    V4L2_CTRL_TYPE_MENU          = 3,   /* 菜单 */ 
    V4L2_CTRL_TYPE_BUTTON        = 4,   /* 无值 */ 
    V4L2_CTRL_TYPE_INTEGER64     = 5,   /* 后面三种不常用 */ 
    V4L2_CTRL_TYPE_CTRL_CLASS    = 6, 
    V4L2_CTRL_TYPE_STRING        = 7, 
}; 
命令的标志取值如下: 
/*  Control flags  */ 
#define V4L2_CTRL_FLAG_DISABLED     0x0001 
#define V4L2_CTRL_FLAG_GRABBED      0x0002 
#define V4L2_CTRL_FLAG_READ_ONLY    0x0004 
#define V4L2_CTRL_FLAG_UPDATE       0x0008 
#define V4L2_CTRL_FLAG_INACTIVE     0x0010 
#define V4L2_CTRL_FLAG_SLIDER       0x0020 
#define V4L2_CTRL_FLAG_WRITE_ONLY   0x0040 
 
/*  Query flag, to be ORed with the control ID */ 
#define V4L2_CTRL_FLAG_NEXT_CTRL    0x80000000 
id 是命令的编号,常见的命令有两种:一种以 V4L2_CID_BASE 为起始值,是公用命令;一种以 V4L2_CID_PRIVATE_BASE 为起始值,是私有命令。在一般的应用中命令值可见如下:
[cpp] 
V4L2_CID_CONTRAST               (V4L2_CID_BASE+1)            /* 对比度调节 */ 
V4L2_CID_SATURATION             (V4L2_CID_BASE+2)            /* 饱和度调节 */ 
V4L2_CID_AUDIO_VOLUME           (V4L2_CID_BASE+5)            /* 音量调节 */ 
V4L2_CID_AUDIO_MUTE             (V4L2_CID_BASE+9)            /* 静音设置 */ 
V4L2_CID_DO_WHITE_BALANCE       (V4L2_CID_BASE+13)           /* 白平衡调节 */ 
V4L2_CID_GAMMA                  (V4L2_CID_BASE+16)           /* 伽马值调节 */ 
V4L2_CID_EXPOSURE               (V4L2_CID_BASE+17)           /* 曝光度调节 */ 
 
V4L2_CID_PRIVATE_ATXX_FLASH     (V4L2_CID_PRIVATE_BASE + 2)  /* 闪光灯控制 */ 
V4L2_CID_PRIVATE_ATXX_FRAME     (V4L2_CID_PRIVATE_BASE + 12) /* 帧率调节 */ 
 type 为命令值的类型(总共有7中类型的值),name 是命令的名称,reserved 则是命令值的位图表示,驱动会将所有的命令值都以 bit 的形式写到 64 位的域中,上层应用查询时可以根据位图判断命令支持的值。
7、struct v4l2_control 与 VIDIOC_G_CTRL、VIDIOC_S_CTRL
VIDIOC_S_CTRL 或 VIDIOC_G_CTRL 命令通过结构 v4l2_control 设置或者获取 id 命令的值:
[cpp] 
struct v4l2_control { 
    __u32            id; 
    __s32            value; 
}; 
这个结构只有 2 个域,id 是命令编号,value 则是命令的值。
8、struct v4l2_tuner 与 VIDIOC_G_TUNER、VIDIOC_S_TUNER
VIDIOC_S_TUNER 或 VIDIOC_G_TUNER 命令通过结构 v4l2_tuner 设置调谐器的信息:
[cpp] 
struct v4l2_tuner { 
    __u32                   index;           /* 调谐器编号,由应用程序设置 */ 
    __u8                    name[32];        /* 调谐器名称 */ 
    enum v4l2_tuner_type    type;            /* 调谐器类型 */ 
    __u32                   capability;      /* 调谐器支持的操作 */ 
    __u32                   rangelow;        /* 最低频率值,单位为62.5Hz或者62.5KHz */ 
    __u32                   rangehigh;       /* 最高频率值 */ 
    __u32                   rxsubchans;      /* 接收的音频信号类型 */ 
    __u32                   audmode;         /* 当前音频播放形式 */ 
    __s32                   signal;          /* 信号强度 */ 
    __s32                   afc;             /* 自动频率控制 */ 
    __u32                   reserved[4];     /* 保留备用 */ 
}; 
其中 
enum v4l2_tuner_type { 
    V4L2_TUNER_RADIO             = 1,        /* 调频收音机 */ 
    V4L2_TUNER_ANALOG_TV         = 2,        /* 模拟电视高频头 */ 
    V4L2_TUNER_DIGITAL_TV        = 3,        /* 数字电视高频头 */ 
}; 
其中域 type 有三种类型;capability 域一般为 V4L2_TUNER_CAP_LOW,表明频率调节的步长是62.5Hz,如果没有这个标志位则步长为62.5KHz;rangelow 与 rangehigh 是调谐器可以调频率的最高值和最低值,但都以步长为单位表示;rxsubchans 表示调谐器接收的音频信号类型,常见值有 V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO  即单声道与立体声;audmode 表示以何种方式播放声音,常见值有 V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO,即以单声道还是立体声的方式播放;signal 为当前信号强度,一般取值范围为 0 - 65535。
9、struct v4l2_frequency 与 VIDIOC_G_FREQUENCY、VIDIOC_S_FREQUENCY
VIDIOC_S_FREQUENCY 或 VIDIOC_G_FREQUENCY 命令通过结构 v4l2_frequency 设置或获取当前频率值:
[cpp] view plaincopy
struct v4l2_frequency { 
    __u32                 tuner;          /* 调谐器编号 */ 
    enum v4l2_tuner_type  type;           /* 调谐器类型 */ 
    __u32                 frequency;      /* 调谐器频率 */ 
    __u32                 reserved[8]; 
}; 
注意:frequency 的值是以62.5Hz 或者 62.5KHZ 为单位的。
附1、_IO、_IOR、_IOW、_IOWR 宏的使用说明
驱动程序中 ioctl  函数传递的变量 cmd 是应用程序向驱动程序请求处理的命令。cmd 除了用于区别不同命令的数值,还可包含有助于处理的几种信息。cmd 的大小为 32 bit,共分 4 个域:
bit29 ~ bit31: 3bit  为 “读写” 区,作用是区分是读命令还是写命令。
bit16 ~ bit28:13bit 为 "数据大小" 区,表示 ioctl 中的 arg 变量传递的数据大小;有时候为 14bit 即将 bit29 覆盖。
bit8 ~ bit15:   8bit  为 “魔数"(也称为"幻数")区,这个值用以与其它设备驱动程序的 ioctl 命令进行区别。
bit0 ~ bit7:     8bit  为 "序号" 区,是区分命令的命令顺序序号。
魔数(magic number)
魔数范围为 0~255 。通常,用英文字符 'A' ~ 'Z' 或者 'a' ~ 'z' 来表示。设备驱动程序从传递进来的命令获取魔数,然后与自身处理的魔数想比较,如果相同则处理,不同则不处理。魔数是拒绝误使用的初步辅助参数。设备驱动程序可以通过宏 _IOC_TYPE (cmd) 来获取魔数。不同的设备驱动程序最好设置不同的魔数,但并不是要求绝对,也是可以使用其他设备驱动程序已用过的魔数。
基数(序号)
基数用于区别各种命令。通常,从 0开始递增,相同设备驱动程序上可以重复使用该值。例如,读和写命令中使用了相同的基数,设备驱动程序也能分辨出来,原因在于设备驱动程序区分命令时使用 switch ,且直接使用命令变量 cmd 值。创建命令的宏生成的值由多个域组合而成,所以即使是相同的基数,也会判断为不同的命令。设备驱动程序想要从命令中获取该基数,就使用宏 _IOC_NR (cmd)。
下面我们看一下上述宏在内核中的原型:
[cpp] 
/*
 * Our DIR and SIZE overlap in order to simulteneously provide
 * a non-zero _IOC_NONE (for binary compatibility) and
 * 14 bits of size as on i386. Here's the layout:
 *
 *   0xE0000000   DIR            3bit
 *   0x80000000   DIR = WRITE    bit31
 *   0x40000000   DIR = READ     bit30
 *   0x20000000   DIR = NONE     bit29
 *   0x3FFF0000   SIZE (overlaps NONE bit)  13bit
 *   0x0000FF00   TYPE           8bit
 *   0x000000FF   NR (CMD)       8bit
 */ 
/* 各个域的长度 */ 
#define _IOC_NRBITS      8 
#define _IOC_TYPEBITS    8 
#define _IOC_SIZEBITS   13  /* Actually 14, see below. */ 
#define _IOC_DIRBITS     3 
/* 各个域的掩码 */ 
#define _IOC_NRMASK      ((1 << _IOC_NRBITS)-1) 
#define _IOC_TYPEMASK    ((1 << _IOC_TYPEBITS)-1) 
#define _IOC_SIZEMASK    ((1 << _IOC_SIZEBITS)-1) 
#define _IOC_XSIZEMASK   ((1 << (_IOC_SIZEBITS+1))-1) 
#define _IOC_DIRMASK     ((1 << _IOC_DIRBITS)-1) 
/* 各个域的偏移 */ 
#define _IOC_NRSHIFT     0 
#define _IOC_TYPESHIFT   (_IOC_NRSHIFT + _IOC_NRBITS)       /* 8 */ 
#define _IOC_SIZESHIFT   (_IOC_TYPESHIFT + _IOC_TYPEBITS)   /* 16 */ 
#define _IOC_DIRSHIFT    (_IOC_SIZESHIFT + _IOC_SIZEBITS)   /* 29 */ 
/* 读写域的值 */ 
#define _IOC_NONE        1U 
#define _IOC_READ        2U 
#define _IOC_WRITE       4U 
 
#define _IOC(dir,type,nr,size) \ 
        (((dir)  << _IOC_DIRSHIFT) | \      /* 读写方向左移 29bit */ 
         ((type) << _IOC_TYPESHIFT) | \     /* 幻数左移 8bit */ 
         ((nr)   << _IOC_NRSHIFT) | \       /* 命令序号 */ 
         ((size) << _IOC_SIZESHIFT))        /* 参数大小左移 16bit */ 
/* 宏原型,这里将会根据传递的数据类型取其长度 */ 
#define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0) 
#define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),sizeof(size)) 
#define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) 
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) 
/* 获取各个域的值 */ 
#define _IOC_DIR(nr)        (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) 
#define _IOC_TYPE(nr)       (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) 
#define _IOC_NR(nr)         (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) 
#define _IOC_SIZE(nr)       (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) 
这里特别说明一下 _IO 宏,该宏没有可传递的变量,只用于发送命令。这是因为变量需要可变数据,只作为命令(比如 reset)使用时,没有必要判断设备上的数据,因此设备驱动程序没有必要执行文件相关的处理。在 v4l2 中使用示例如下:
[cpp] 
#define VIDIOC_QUERYCAP      _IOR('V',  0, struct v4l2_capability) 
#define VIDIOC_RESERVED       _IO('V',  1) 
#define VIDIOC_S_FMT        _IOWR('V',  5, struct v4l2_format) 
#define VIDIOC_STREAMON      _IOW('V', 18, int) 
v4l2 中对上述宏命令的处理在 video_ioctl2 函数中:
[cpp] view plaincopy
static unsigned long cmd_input_size(unsigned int cmd) 

#define CMDINSIZE(cmd, type, field)                 \ 
    case VIDIOC_##cmd:                  \ 
        return offsetof(struct v4l2_##type, field) +    \  /* 域的偏移 */ 
            sizeof(((struct v4l2_##type *)0)->field);      /* 域的长度 */ 
 
    switch (cmd) { 
        CMDINSIZE(ENUM_FMT,     fmtdesc,    type); 
        CMDINSIZE(G_FMT,        format,     type); 
        ... 
        CMDINSIZE(ENUM_FRAMESIZES,  frmsizeenum,    pixel_format); 
        CMDINSIZE(ENUM_FRAMEINTERVALS,  frmivalenum,    height); 
    default: 
        return _IOC_SIZE(cmd);  /* 剩下的是需要全部拷贝的命令 */ 
    } 

 
long video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg) 

    char    sbuf[128];          /* 在栈中分配128个字节空间用来储存命令的参数 */ 
    void    *mbuf = NULL; 
    void    *parg = NULL;       /* 参数存放的首地址 */ 
    long    err  = -EINVAL; 
    int     is_ext_ctrl; 
    size_t  ctrls_size = 0; 
    void __user *user_ptr = NULL; 
 
    ... 
    /* 判断是否包含读写命令,如果是则将用户空间的参数值拷贝到内核 */ 
    if (_IOC_DIR(cmd) != _IOC_NONE) { 
        /* 判断参数大小是否超过128字节 */ 
        if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { 
            parg = sbuf; 
        } else { 
            /* 如果超过128字节则从堆中申请 */ 
            mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); 
            if (NULL == mbuf) 
                return -ENOMEM; 
            parg = mbuf; 
        } 
 
        err = -EFAULT; 
        /* 如果包含写命令 */ 
        if (_IOC_DIR(cmd) & _IOC_WRITE) { 
            /* 计算需要拷贝的有效数据长度,有的命令不需要全部拷贝 */ 
            unsigned long n = cmd_input_size(cmd); 
            /* 从用户空间拷贝参数值 */ 
            if (copy_from_user(parg, (void __user *)arg, n)) 
                goto out; 
 
            /* 将剩下的空间清零 */ 
            if (n < _IOC_SIZE(cmd)) 
                memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n); 
        } else { 
            /* 如果是只读命令则将整个buffer清零 */ 
            memset(parg, 0, _IOC_SIZE(cmd)); 
        } 
    } 
 
    ... 
    /* 调用 v4l2_ioctl_ops 的成员函数处理命令 */ 
    err = __video_do_ioctl(file, cmd, parg); 
    if (err == -ENOIOCTLCMD) 
        err = -EINVAL; 
    ... 
    if (err < 0) 
        goto out; 
 
out_ext_ctrl: 
    /* 如果包含读命令则将参数值拷贝到用户空间 */ 
    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_ioctl2); 
然后我们在 struct v4l2_file_operations 中将 ioctl 成员设置为 video_ioctl2 即可。

v412的ioctl命令相关推荐

  1. 构造IOCTL命令的学习心得-----_IO, _IOR, _IOW, _IOWR 幻数的理解

    在编写ioctl代码之前,需要选择对应不同命令的编号.为了防止对错误的设备使用正确的命令,命令号应该在系统范围内唯一,这种错误匹配并不是不会发生,程序可能发现自己正在试图对FIFO和audio等这类非 ...

  2. 构造IOCTL命令的学习心得-----_IO, _IOR, _IOW, _IOWR 幻数的理解

    在编写ioctl代码之前,需要选择对应不同命令的编号.为了防止对错误的设备使用正确的命令,命令号应该在系统范围内唯一,这种错误匹配并不是不会发生,程序可能发现自己正在试图对FIFO和audio等这类非 ...

  3. linux ioctl命令,关于LINUX下的ioctl函数

    驱动程序中ioctl函数的函数原型如下: int (*ioctl)(struct inode *inode, struct file *filp,unsigned int cmd, unsigned ...

  4. IOCTL命令-_IO, _IOR, _IOW, _IOWR 幻数的理解

    有一年半时间没有一行一行的写过linux驱动程序了,有的东西会发现遗忘了,今天就当是复习一下吧. 在编写ioctl代码之前,需要选择对应不同命令的编号.为了防止对错误的设备使用正确的命令,命令号应该在 ...

  5. ioctl命令及参数传递

    一.ioctl的简介: 虽然在文件操作结构体"struct file_operations"中有很多对应的设备操作函数,但是有些命令是实在找不到对应的操作函数.如CD-ROM的驱动 ...

  6. IOCTL命令格式解析以及调用过程

    一.IOCTL的系统调用 1.应用程序中的ioctl(系统IO的内容) #include int ioctl(int d, int request, ...); 应用程序向驱动程序发送命令(cmd), ...

  7. ioctl -构造命令编号 _IO,_IOW,_IOR,_IOWR

    原文地址:http://blog.chinaunix.net/uid-20754793-id-177774.html 今天在写字符驱动验证程序的时候要用到ioctl函数,其中有一个cmd参数,搞了半天 ...

  8. 【视频】V4L2之ioctl

    常见的ioctl命令 VIDIOC_QUERYCAP /* 获取设备支持的操作 */ VIDIOC_G_FMT /* 获取设置支持的视频格式 */ VIDIOC_S_FMT /* 设置捕获视频的格式 ...

  9. linux直接控制IO叫,Linux IO控制命令生成

    在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值.cmd除了可区别数字外,还包含有助于处理的几种相应信息. cmd的大小为 32位,共分 4 个 ...

最新文章

  1. python入门基础代码图-Python Matplotlib绘图基础知识代码解析
  2. 知识梳理——HTML篇
  3. vue.js组件学习(上)
  4. 使用正确的垃圾收集器将Java内存使用量降至最低
  5. 怎么样用System.out.println在控制台打印出颜色
  6. 这是2019年适合Java程序员读的10本书
  7. 数仓备机DN重建:快速修复你的数仓DN单点故障
  8. Linux入门-vsftp
  9. vss2005使用手册
  10. windows系统迁移,C盘搬家
  11. 小程序地理位置接口申请
  12. 运动神经元病是怎么回事?
  13. 郑州大学计算机翟雨轩,郑州大学文件-20210331220732.doc-原创力文档
  14. 谷歌浏览器驱动器下载网址
  15. android 10.0 禁止安装apk
  16. 大数据培训有前途吗,大数据工资一般多少?
  17. win10 设定计划任务时提示所指定的账户名称无效,如何解决?
  18. leeetcode77 组合
  19. 面试官:说说MySQL用得好好的,为什么要转ES?
  20. sqli-labs————less 20

热门文章

  1. galaxy+note8+android+8.0,太遗憾了!三星Galaxy S8和Note8无缘安卓10更新
  2. 毕业半年(工作一年)
  3. word插入Endnote参考文献报错{***, 1995 #307}解决方案
  4. 用计算机玩游戏教案,《单击鼠标玩游戏》教案
  5. Java设计模式之里氏替换原则(Liskov Substitution principle)
  6. 关于ntfs.sys引发的蓝屏
  7. 软件工程项目实训01
  8. 日常白嫖QQ小技巧(RGB、文字、翻译的识别)
  9. 安卓 Android 下载网络图片保存到本地
  10. IDA反汇编工具使用说明