日期:2014-05-16  浏览次数:20782 次

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,希望高手指点下
网上搜索了下,有人说
引用第二个参数不要用2。可以用linux/ioctl.h里面提供的IOC宏

2好像被2.6的内核干掉了。以前我喜欢直接用0x01, 0x02,后来全改成IOW/IOR了



------解决方案--------------------
在别人地盘混 怎么能不守规矩
老实从了__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;
}