ioctl的疑问
驱动部分:
- C/C++ code
MODULE_LICENSE("GPL");#define TEST_ENA 0x00#define TEST_SET_TIME 0x01#define TEST_SET_DATE 0x02 #define TEST_SET_CH0_PIXEL 0x03 int test_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg){ unsigned int __user *argp=(unsigned int __user *)arg; unsigned char tmp_uchar; printk("CMD=%d",cmd); switch (cmd) { case TEST_ENA : break; case TEST_SET_TIME : break; case TEST_SET_DATE: break; case TEST_SET_CH0_PIXEL : break; default: break; }//end switch return 0; }测试程序:
- C/C++ code
int main(void){ int wdt_fd = -1; int ret,nTimeout=20; int i; Osd_Date osd_date; wdt_fd = open("/dev/ti_test",O_WRONLY); if(wdt_fd == -1) { printf("CEM Open error!!\n"); } i=2; ret=ioctl(wdt_fd, i ,&nTimeout); printf("ret=%d \n",ret); return 0;}结果发现ioctl在i=2的时候,不会调用test_ioctl,其他时候均没有问题,返回值是0,希望高手指点下
网上搜索了下,有人说
[解决办法]
在别人地盘混 怎么能不守规矩
老实从了__IOW _IOR 吧
[解决办法]
ioctl的cmd不是想怎么定义就怎么定义的 得按规矩来
内核有一个自定义头文件 用户层也得有一个相同的自定义头文件
每一个头文件都必须使用__IOW _IOR来定义这些cmd
如果你随便定义一个cmd 很可能就跟linux内核中这类驱动已经定义好的cmd重复
于是就优先被这类驱动默认的ioctl处理函数截获了,只有这类驱动默认的ioctl处理函数不认识的cmd,才轮得到你自定义的ioctl
[解决办法]
听说比较新的版本ioctl接口发生了变化了,不过好久没搞驱动了,忘了。
[解决办法]
不知道你的版本
以3.0.4为例
fs/ioctl.c
(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) -> do_vfs_ioctl
- C/C++ code
int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg){ int error = 0; int __user *argp = (int __user *)arg; struct inode *inode = filp->f_path.dentry->d_inode; switch (cmd) { case FIOCLEX: set_close_on_exec(fd, 1); break; case FIONCLEX: set_close_on_exec(fd, 0); break; case FIONBIO: error = ioctl_fionbio(filp, argp); break; case FIOASYNC: error = ioctl_fioasync(fd, filp, argp); break; case FIOQSIZE: if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) { loff_t res = inode_get_bytes(inode); error = copy_to_user(argp, &res, sizeof(res)) ? -EFAULT : 0; } else error = -ENOTTY; break; case FIFREEZE: error = ioctl_fsfreeze(filp); break; case FITHAW: error = ioctl_fsthaw(filp); break; case FS_IOC_FIEMAP: return ioctl_fiemap(filp, arg); [b]case FIGETBSZ:[/b] return put_user(inode->i_sb->s_blocksize, argp); [b]default:[/b] if (S_ISREG(inode->i_mode)) error = file_ioctl(filp, cmd, arg); else error =[b] vfs_ioctl[/b](filp, cmd, arg); break; } return error;}