增加和调整内容,包括:

增加注释;
修改宏名;
检测 IOCTL cmd 的合法性.

Signed-off-by: ithink.chan <chenyang@autoai.com>
This commit is contained in:
ithink.chan 2020-04-27 11:12:46 +08:00
parent 49f7904b6f
commit 80093e080e
1 changed files with 54 additions and 19 deletions

View File

@ -2,10 +2,25 @@
* @file demo_misc.c * @file demo_misc.c
* @author Rick Chan (cy187lion@sina.com) * @author Rick Chan (cy187lion@sina.com)
* @brief Linux misc driver demo. * @brief Linux misc driver demo.
* @version 0.1 Linux
* @date 2019-10-15 10
1.alloc_chrdev_region()/
2.使cdev_init()cdev_add()
misc驱动misc_register()
miscdevice 访
miscdevice file_operations
* @version 0.1.1
* @date 2020-04-27
* *
* @copyright Copyright (c) 2019 * @copyright Copyright (c) 2020
* *
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
@ -17,12 +32,14 @@
MODULE_AUTHOR("Rick Chan"); MODULE_AUTHOR("Rick Chan");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define IOCTL_IOC_SIZE 8 #define DEMO_MAGIC 'R'
#define IOCTL_IOC _IOC(_IOC_READ|_IOC_WRITE, 0, 0, IOCTL_IOC_SIZE) #define DEMO_IOC_SIZE 8
#define IOCTL_IO _IO(0, 1) #define DEMO_CTL_IOC _IOC(_IOC_READ|_IOC_WRITE, DEMO_MAGIC, 0, DEMO_IOC_SIZE)
#define IOCTL_IOR _IOR(0, 2, uint16_t) #define DEMO_CTL_IO _IO(DEMO_MAGIC, 1)
#define IOCTL_IOW _IOW(0, 3, int32_t) #define DEMO_CTL_IOR _IOR(DEMO_MAGIC, 2, uint16_t)
#define IOCTL_IOWR _IOWR(0, 4, uint32_t) #define DEMO_CTL_IOW _IOW(DEMO_MAGIC, 3, int32_t)
#define DEMO_CTL_IOWR _IOWR(DEMO_MAGIC, 4, uint32_t)
#define DEMO_CTL_MAX 5
static int demo_open(struct inode *inode, struct file* filp) static int demo_open(struct inode *inode, struct file* filp)
{ {
@ -53,30 +70,48 @@ static ssize_t demo_write(struct file *filp, const char __user *buffer, size_t c
static long demo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) static long demo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{ {
static int err = 0;
// 检测 cmd 合法性.
if(DEMO_MAGIC!=_IOC_TYPE(cmd))
return -EINVAL;
if(DEMO_CTL_MAX<_IOC_NR(cmd))
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) switch(cmd)
{ {
case IOCTL_IOC: case DEMO_CTL_IOC:
{ {
uint8_t tmp[IOCTL_IOC_SIZE]; uint8_t tmp[DEMO_IOC_SIZE];
copy_from_user(&tmp, (void*)arg, _IOC_SIZE(cmd)); copy_from_user(&tmp, (void*)arg, _IOC_SIZE(cmd));
copy_to_user((void*)arg, &tmp, _IOC_SIZE(cmd)); copy_to_user((void*)arg, &tmp, _IOC_SIZE(cmd));
} }
break; break;
case IOCTL_IO: case DEMO_CTL_IO:
break; break;
case IOCTL_IOR: case DEMO_CTL_IOR:
{ {
uint16_t tmp = 0x55AA; uint16_t tmp = 0x55AA;
copy_to_user((void*)arg, &tmp, _IOC_SIZE(cmd)); copy_to_user((void*)arg, &tmp, _IOC_SIZE(cmd));
} }
break; break;
case IOCTL_IOW: case DEMO_CTL_IOW:
{ {
int32_t tmp = 0; int32_t tmp = 0;
copy_from_user(&tmp, (void*)arg, _IOC_SIZE(cmd)); copy_from_user(&tmp, (void*)arg, _IOC_SIZE(cmd));
} }
break; break;
case IOCTL_IOWR: case DEMO_CTL_IOWR:
{ {
uint32_t tmp = 0; uint32_t tmp = 0;
copy_from_user(&tmp, (void*)arg, _IOC_SIZE(cmd)); copy_from_user(&tmp, (void*)arg, _IOC_SIZE(cmd));
@ -113,14 +148,14 @@ static struct miscdevice demo_dev = {
static int __init demo_init(void) static int __init demo_init(void)
{ {
misc_register(&demo_dev); misc_register(&demo_dev); // 注册混杂设备驱动.
return 0; return 0;
} }
static void __exit demo_exit(void) static void __exit demo_exit(void)
{ {
misc_deregister(&demo_dev); misc_deregister(&demo_dev); // 撤销混杂设备驱动.
} }
module_init(demo_init); module_init(demo_init);
module_exit(demo_exit); module_exit(demo_exit);