(四)ioctl函数的使用

一、IOCTL函数的原型

1.应用程序的ioctl()—>linux的系统IO函数

 #include <sys/ioctl.h>
 int ioctl(int fd, unsigned long request, ...);

经常使用的函数原型:

int ioctl(int fd, unsigned int cmd, unsigned long args);
int ioctl(int fd, unsigned int cmd);

应用程序的ioctl()会系统调用驱动程序的ioctl()

2、驱动程序的ioctl()—>file_operations

long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, unsigned long args);

3、应用的方法
1)应用程序向驱动程序发送命令cmd,但是不发送参数

int ioctl(int fd, unsigned int cmd);
long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, unsigned long args);

unsigned long args—>忽略

2)应用程序向驱动程序发送命令,并发送参数

int ioctl(int fd, unsigned int cmd, unsigned long args);
long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, unsigned long args);

unsigned int cmd —>应用程序发下来的命令
unsigned long args —>应用程序发下来的参数
例子:

#include <linux/videodev2.h>
struct v4l2_format fmt;  //保存或设置摄像头输出的视频格式

fmt.fmt.pix.width       = 640;//设置视频输出宽为640
fmt.fmt.pix.height      = 480;//输出高位480
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//设置输出格式为YUYV格式(必须要摄像头支持YUYV格式设置才有效)
#endif
fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
ret = ioctl(fd, VIDIOC_S_FMT, &fmt); //把格式数据设置到驱动中
    if (ret < 0)
    {
        printf("VIDIOC_S_FMT failed (%d)\n", ret);
           return ret;
    }

应用程序向驱动程序发送命令VIDIOC_S_FMT,并发送参数fmt。

3)应用程序向驱动程序发送命令,并获取参数

int ioctl(int fd, unsigned int cmd, unsigned long args);
long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, unsigned long args);

unsigned int cmd —>应用程序发下来的命令
unsigned long args —>发送给应用程序的参数
例子:

#include <linux/videodev2.h>
struct v4l2_format fmt;  //保存或设置摄像头输出的视频格式
memset(&fmt, 0, sizeof(struct v4l2_format));

ret = ioctl(fd, VIDIOC_G_FMT, &fmt);//从驱动中获取信息
    if (ret < 0) {
        printf("***********************************\nVIDIOC_G_FMT failed (%d)\n", ret);
        return ret;
    }
    printf("Stream Format Informations:\n");
    printf(" type: %d\n", fmt.type);
    printf(" width: %d", fmt.fmt.pix.width);
    printf(" height: %d\n", fmt.fmt.pix.height);

应用程序向驱动程序发送命令VIDIOC_G_FMT,获取驱动的数据fmt
 

二、IOCTL的命令

IOCTL的命令需要预先定义好,应用程序和驱动程序要使用相同的命令。命令是一个32位无符号的整型值,该整型值是有固定格式要求的。
我们要使用固定的格式标准,定义自己的cmd。

#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)

—>定义一个命令,但是不需要参数参数

#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))

—>定义一个命令,应用程序从驱动程序读参数

#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))

—>定义一个命令,应用程序向驱动程序写参数

#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))

—>定义一个命令,参数是双向传递的。

函数的参数说明:
type ----> 命令的类型,一般为一个ASCII码,一般一个驱动程序使用一个type
nr —> 该命令下序号。一个驱动有多个命令,一般他们的type,序号不同
size —> args的类型

例子:
应用程序定义的cmd:/usr/include/linux/videodev2.h

#define VIDIOC_S_FMT		_IOWR('V',  5, struct v4l2_format)

驱动程序定义的cmd:内核源码/include/linux/videodev2.h

#define VIDIOC_S_FMT		_IOWR('V',  5, struct v4l2_format)

思考:
定义LED灯驱动的命令:
应用程序发命令:灯亮和灯灭
应用程序发参数:灯号:8/9/10/11

#define GEC6818_LED_ON _IOW(‘L’, 1, unsigned long)
#define GEC6818_LED_OFF _IOW(‘L’, 2, unsigned long)

#define GEC6818_BEEP_ON _IO(‘B’, 1)
#define GEC6818_BEEP_OFF _IO(‘B’, 2)
 

三、附录

示例代码:led_drv.c
示例代码:beep_drv.c
示例代码:key_drv.c

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值