一、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)