linux驱动中ioctl使用
在驱动头文件中定义幻数
#define OLED_IOC_MAGIC 'k'
#define OLED_IOC_OPEN _IO(OLED_IOC_MAGIC, 1)
#define OLED_IOC_CLOSE _IO(OLED_IOC_MAGIC, 2)
#define OLED_IOC_SET_POINT _IOR(OLED_IOC_MAGIC, 3, int)
#define OLED_IOC_SET_STRING _IOW(OLED_IOC_MAGIC, 4, int)
#define OLED_IOC_REFRESH _IO(OLED_IOC_MAGIC, 5)
#define OLED_IOC_CLEAR _IO(OLED_IOC_MAGIC, 6)
#define OLED_IOC_MAXNR 6
在驱动源文件中实现ioctl函数
static int oled12864_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int err = 0;
int ret = 0;
if (_IOC_TYPE(cmd) != OLED_IOC_MAGIC)
return -EINVAL;
if (_IOC_NR(cmd) > OLED_IOC_MAXNR)
return -EINVAL;
if (_IOC_DIR(cmd) & _IOC_READ)
err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
if (err)
return -EFAULT;
switch(cmd) {
case OLED_IOC_OPEN:
OLED_DisPlay_On();
printk("<--- CMD OLED_IOC_OPEN Done--->\n\n");
break;
case OLED_IOC_CLOSE:
OLED_DisPlay_Off();
printk("<--- CMD OLED_IOC_CLOSE Done--->\n\n");
break;
case OLED_IOC_REFRESH:
OLED_Refresh();
break;
case OLED_IOC_CLEAR:
OLED_Clear();
break;
case OLED_IOC_SET_POINT:
{
pointData tmp;
copy_from_user((unsigned char *)&tmp,(unsigned char *)arg,sizeof(stringData));
if(tmp.on = 0){
OLED_ClearPoint(tmp.p.x, tmp.p.y);
}else{
OLED_DrawPoint(tmp.p.x, tmp.p.y);
}
printk("<--- In Kernel = %d %d %d %d--->\n\n", tmp.p.x, tmp.p.y, tmp.on, 16);
}
break;
case OLED_IOC_SET_STRING:
{
stringData tmp;
copy_from_user((unsigned char *)&tmp,(unsigned char *)arg,sizeof(stringData));
OLED_ShowString(tmp.p.x, tmp.p.y, tmp.data, tmp.len);
OLED_Refresh();
printk("<--- In Kernel = %d %d %s %d--->\n\n", tmp.p.x, tmp.p.y, tmp.data, 16);
}
break;
default:
return -EINVAL;
}
return ret;
}
ops操作集合
static const struct file_operations oled12864_ops = {
.owner = THIS_MODULE,
.open = oled12864_open,
.read = oled12864_read,
.write = oled12864_write,
.unlocked_ioctl = oled12864_ioctl,
.release = oled12864_release,
};