linux驱动:(21)ioctl接口(二)驱动与应用程序传递ioctl命令
目录
copy_from_user改为用ioctl接口
修改为ioctl读取无参数命令
测试.c
驱动.c
效果
修改为ioctl读取有参数命令
测试.c
驱动.c
效果
修改为ioctl发送有参数命令
测试.c
驱动.c
效果
copy_from_user改为用ioctl接口
将以前的beep杂项设备中的copy_from_user改为用ioctl接口,修改的代码是 linux驱动:(8)实战:用杂项设备完成蜂鸣器驱动 中的代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>#define GPIO5_DR 0x020AC00
unsigned int *vir_gpio5_dr;int misc_open(struct inode * inode,struct file * file)
{printk("hello misc_open\n");return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{char kbuf[64] = "heheh";if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0){printk("copy_to_user error\n");return -1;}return 0;
}
int misc_write(struct file *file,const char _user *ubuf,size_t size,loff_t *loff_t)
{char kbuf[64] = {0};if( copy_from_user(kbuf,ubuf,size)!=0){printk("copy_from_user error\n");return -1;}printk("kbuf is %s\n",kbuf);if(kbuf[0]==1){*vir_gpio5_dr |= (1<<1);}else if{*vir_gpio5_dr &= ~(1<<1);}return 0;
}
struct const file_operation misc_fops = {.owner = THIS_MODULE,.open = misc_open,.write= misc_write,.read = misc_read
};
struct miscdevice misc_dev = {.minor = MISC_DYNAMIC_MINOR,//动态分配.name ="hellomisc",//设备节点名字.fops =&misc_fops
};static int misc_init(void)
{int ret;ret = misc_register(&misc_dev);if(ret<0){printk("misc registe is error\n");return -1;}vir_gpio5_dr = ioremap(GPIO5_DR,4);if(vir_gpio5_dr ==NULL){printk("GPIO5_DR ioremap error\n");return -EBUSY;}printk("GPIO5_DR ioremap ok\n");return 0;
}static void misc_exit(void)
{misc_deregister(&misc_dev);iounmap(vir_gpio5_dr );printk("misc goodbye");
}module_init(misc_init);
module_exit(misc_exit);MODULE_LICENSE("GPL");
修改为ioctl读取无参数命令
- 先把关于GPIO5_DR 的部分删掉
- 编写测试.c,定义发送两个无参数命令
- ioctl函数中的参数对应驱动中的函数中的参数
- 在驱动.c中也要定义两个一样的无参数命令
- 在文件操作集中定义unlocked_ioctl函数
- 在函数中判断cmd命令是否等于我们自己定义的两个命令
测试.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>#define CMD_TEST0 _IO('L',0)
#define CMD_TEST1 _IO('L',1)int main(int argc,char *argv[])
{int fd;// 读取设备节点fd = open("/dev/hello_misc",O_RDWR);if (fd < 0){perror("open error\n");return fd;}while (1){ioctl(fd,CMD_TEST0);sleep(2);ioctl(fd,CMD_TEST1);sleep(2);}return 0;
}
驱动.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <sys/ioctl.h>#define CMD_TEST0 _IO('L',0)
#define CMD_TEST1 _IO('L',1)
int misc_open(struct inode * inode,struct file * file)
{printk("hello misc_open\n");return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{char kbuf[64] = "heheh";if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0){printk("copy_to_user error\n");return -1;}return 0;
}
int misc_write(struct file *file,const char _user *ubuf,size_t size,loff_t *loff_t)
{char kbuf[64] = {0};if( copy_from_user(kbuf,ubuf,size)!=0){printk("copy_from_user error\n");return -1;}printk("kbuf is %s\n",kbuf);return 0;
}long misc_ioctl(struct file *file,unsigned int cmd, unsigned long value)
{switch (cmd){case CMD_TEST0:printk("led on\n");break;case CMD_TEST1:printk("led off\n");break;default:break;}return 0;
}struct const file_operation misc_fops = {.owner = THIS_MODULE,.open = misc_open,.write= misc_write,.unlocked_ioctl= misc_ioctl,.read = misc_read
};
struct miscdevice misc_dev = {.minor = MISC_DYNAMIC_MINOR,//动态分配.name ="hellomisc",//设备节点名字.fops =&misc_fops
};static int misc_init(void)
{int ret;ret = misc_register(&misc_dev);if(ret<0){printk("misc registe is error\n");return -1;}vir_gpio5_dr = ioremap(GPIO5_DR,4);return 0;
}static void misc_exit(void)
{misc_deregister(&misc_dev);printk("misc goodbye");
}module_init(misc_init);
module_exit(misc_exit);MODULE_LICENSE("GPL");
效果
- 编译成模块,烧录到开发板中,加载驱动,运行测试.c
- 每隔两秒打印led on或者led off
修改为ioctl读取有参数命令
- 先把关于GPIO5_DR 的部分删掉
- 编写测试.c,定义发送两个有参数命令
- ioctl函数中的参数对应驱动中的函数中的参数
- 在驱动.c中也要定义两个一样的有参数命令
- 在文件操作集中定义unlocked_ioctl函数
- 在函数中判断cmd命令是否等于我们自己定义的两个命令
测试.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>#define CMD_TEST0 _IOW('L',0,int)
#define CMD_TEST1 _IOW('L',1,int)int main(int argc,char *argv[])
{int fd;// 读取设备节点fd = open("/dev/hello_misc",O_RDWR);if (fd < 0){perror("open error\n");return fd;}while (1){ioctl(fd,CMD_TEST0,1);sleep(2);ioctl(fd,CMD_TEST1,0);sleep(2);}return 0;
}
驱动.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <sys/ioctl.h>#define CMD_TEST0 _IOW('L',0,int)
#define CMD_TEST1 _IOW('L',1,int)
int misc_open(struct inode * inode,struct file * file)
{printk("hello misc_open\n");return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{char kbuf[64] = "heheh";if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0){printk("copy_to_user error\n");return -1;}return 0;
}
int misc_write(struct file *file,const char _user *ubuf,size_t size,loff_t *loff_t)
{char kbuf[64] = {0};if( copy_from_user(kbuf,ubuf,size)!=0){printk("copy_from_user error\n");return -1;}printk("kbuf is %s\n",kbuf);return 0;
}long misc_ioctl(struct file *file,unsigned int cmd, unsigned long value)
{switch (cmd){case CMD_TEST0:printk("led on\n");printk("value is %d\n",value);break;case CMD_TEST1:printk("led off\n");printk("value is %d\n",value);break;default:break;}return 0;
}struct const file_operation misc_fops = {.owner = THIS_MODULE,.open = misc_open,.write= misc_write,.unlocked_ioctl= misc_ioctl,.read = misc_read
};
struct miscdevice misc_dev = {.minor = MISC_DYNAMIC_MINOR,//动态分配.name ="hellomisc",//设备节点名字.fops =&misc_fops
};static int misc_init(void)
{int ret;ret = misc_register(&misc_dev);if(ret<0){printk("misc registe is error\n");return -1;}vir_gpio5_dr = ioremap(GPIO5_DR,4);return 0;
}static void misc_exit(void)
{misc_deregister(&misc_dev);printk("misc goodbye");
}module_init(misc_init);
module_exit(misc_exit);MODULE_LICENSE("GPL");
效果
- 编译成模块,烧录到开发板中,加载驱动,运行测试.c
- 每隔两秒打印led on或者led off,并会打印出value的值(0和1)
修改为ioctl发送有参数命令
- 先把关于GPIO5_DR 的部分删掉
- 编写测试.c,定义接收一个有参数命令
- ioctl函数中的参数对应驱动中的函数中的参数
- 在驱动.c中也要定义一个一样的有参数命令
- 在文件操作集中定义unlocked_ioctl函数
- 在函数中判断cmd命令是否等于我们自己定义的一个命令,是就通过copy_to_user进行发送
测试.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>#define CMD_TEST0 _IOR('L',0,int)int main(int argc,char *argv[])
{int fd;int value;// 读取设备节点fd = open("/dev/hello_misc",O_RDWR);if (fd < 0){perror("open error\n");return fd;}while (1){ioctl(fd,CMD_TEST0,&value);printf("value is %d\n",value);sleep(2);}return 0;
}
驱动.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <sys/ioctl.h>#define CMD_TEST0 _IOR('L',0,int)
int misc_open(struct inode * inode,struct file * file)
{printk("hello misc_open\n");return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{char kbuf[64] = "heheh";if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0){printk("copy_to_user error\n");return -1;}return 0;
}
int misc_write(struct file *file,const char _user *ubuf,size_t size,loff_t *loff_t)
{char kbuf[64] = {0};if( copy_from_user(kbuf,ubuf,size)!=0){printk("copy_from_user error\n");return -1;}printk("kbuf is %s\n",kbuf);return 0;
}long misc_ioctl(struct file *file,unsigned int cmd, unsigned long value)
{int val;switch (cmd){case CMD_TEST0:val = 12 ;if( copy_to_user((int *)value,&val,sizeof(val))!=0){printk("copy_to_user error\n");return -1;}break;default:break;}return 0;
}struct const file_operation misc_fops = {.owner = THIS_MODULE,.open = misc_open,.write= misc_write,.unlocked_ioctl= misc_ioctl,.read = misc_read
};
struct miscdevice misc_dev = {.minor = MISC_DYNAMIC_MINOR,//动态分配.name ="hellomisc",//设备节点名字.fops =&misc_fops
};static int misc_init(void)
{int ret;ret = misc_register(&misc_dev);if(ret<0){printk("misc registe is error\n");return -1;}vir_gpio5_dr = ioremap(GPIO5_DR,4);return 0;
}static void misc_exit(void)
{misc_deregister(&misc_dev);printk("misc goodbye");
}module_init(misc_init);
module_exit(misc_exit);MODULE_LICENSE("GPL");
效果
- 编译成模块,烧录到开发板中,加载驱动,运行测试.c
- 每隔两秒打印驱动传出来的value值12