分类: 嵌入式
2014-03-14 13:45:08
要按Linux内核的约定方法为驱动程序选择ioctl编号,应该首先看看include/asm/ioctl.h和Doucumention/ioctl-number.txt这两个文件。头文件定义了要使用的位字段:类型(幻数)、序数、传送方向以及参数大小等。ioctl-number.txt文件中罗列了内核所使用的幻数,选择自己的幻数要避免和内核冲突。以下是对include/asm/ioctl.h中定义的宏的注释:
_IOC 宏将dir,type,nr,size四个参数组合成一个cmd参数,如下图:点击(此处)折叠或打开
- #define _IOC_DIRBITS 2 //方向(direction)字段的字位宽度,2bits
- #define _IOC_TYPEBITS 8 //幻数(type)字段的字位宽度,8bits
- #define _IOC_NRBITS 8 //序数(number)字段的字位宽度,8bits
- #define _IOC_SIZEBITS 14 //大小(size)字段的字位宽度,14bits
- #define _IOC_NONE 0U //没有数据传输
- #define _IOC_WRITE 1U //向设备写入数据,驱动程序必须从用户空间读入数据
- #define _IOC_READ 2U //从设备中读取数据,驱动程序必须向用户空间写入数据
- #define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) //序数字段的掩码,0x000000FF
- #define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) //幻数字段的掩码,0x000000FF
- #define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) //大小字段的掩码,0x00003FFF
- #define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) //方向字段的掩码,0x00000003
- #define _IOC_NRSHIFT 0 //序数字段在整个字段中的位移,0
- #define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) //幻数字段的位移,8
- #define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) //大小字段的位移,16
- #define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) //方向字段的位移,30
- #define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
- /* 生成cmd */
- #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(cmd) (((cmd) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) //从命令参数中解析出数据方向,即写进还是读出
- #define _IOC_TYPE(cmd) (((cmd) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) //从命令参数中解析出幻数type
- #define _IOC_NR(cmd) (((cmd) >> _IOC_NRSHIFT) & _IOC_cmdMASK) //从命令参数中解析出序数number
- #define _IOC_SIZE(cmd) (((cmd) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) //从命令参数中解析出用户数据大小