#include #include #include #include #include #include #include #include #include #include #include #include #include "gpioregs.h" #define DEVICE_NAME "writeprotect" #define CLASS_NAME "writeprotect_class" #define BUFFER_SIZE 1024 // 可以通过模块参数指定主设备号和次设备号 static int writeprotect_major = 56; // 默认主设备号 static int writeprotect_minor = 90; // 默认次设备号 module_param(writeprotect_major, int, S_IRUGO); module_param(writeprotect_minor, int, S_IRUGO); MODULE_PARM_DESC(writeprotect_major, "Major device number"); MODULE_PARM_DESC(writeprotect_minor, "Minor device number"); static struct class *char_class = NULL; static struct device *char_device = NULL; static struct cdev my_cdev; static dev_t dev_num; // 设备结构体 struct writeprotect_dev { char *buffer; size_t size; struct mutex lock; struct cdev cdev; struct delayed_work delay_work1; }; static struct writeprotect_dev *dev = NULL; static void delay_work_func(struct work_struct *work) { printk(KERN_INFO "delay_work_func\n"); } // 文件打开操作 static int writeprotect_open(struct inode *inode, struct file *filp) { struct writeprotect_dev *dev; dev = container_of(inode->i_cdev, struct writeprotect_dev, cdev); filp->private_data = dev; printk(KERN_INFO "writeprotect: Device opened (major=%d, minor=%d)\n", imajor(inode), iminor(inode)); return 0; } // 文件释放操作 static int writeprotect_release(struct inode *inode, struct file *filp) { // release_region(PORT_80, 1); printk(KERN_INFO "writeprotect: Device closed\n"); return 0; } // 读操作 - 支持cat命令 static ssize_t writeprotect_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct writeprotect_dev *dev = filp->private_data; ssize_t retval = 0; size_t available; int read_count = 0; int ret = 0; if (mutex_lock_interruptible(&dev->lock)) return -ERESTARTSYS; // 这里read_count没有固定为4个字节,是为了便于后续扩展 if (count > dev->size) { read_count = dev->size; } else { read_count = count; } ret = copy_to_user(buf, dev->buffer, read_count); if (ret != 0) { printk(KERN_INFO "writeprotect: copy_to_user failed\n"); goto out; } printk(KERN_INFO "writeprotect: Read %zu bytes\n", count); out: mutex_unlock(&dev->lock); return ret; } // 写操作 static ssize_t writeprotect_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct writeprotect_dev *dev = filp->private_data; ssize_t retval = 0; size_t available; int ret = 0; // 加锁 if (mutex_lock_interruptible(&dev->lock)) { return -ERESTARTSYS; } // 计算可写数据量 if (count > BUFFER_SIZE) { count = BUFFER_SIZE; } // 拷贝数据 ret = copy_from_user(dev->buffer, buf, count); if (ret != 0) { printk(KERN_INFO "writeprotect: copy_from_user failed\n"); goto out; } dev->size = count; printk(KERN_INFO "writeprotect: Written %zu bytes\n", count); out: mutex_unlock(&dev->lock); // 调度延迟工作 if (ret == 0) { schedule_delayed_work(&dev->delay_work1, msecs_to_jiffies(10)); } return count; } // 文件操作结构体 static struct file_operations fops = { .owner = THIS_MODULE, .open = writeprotect_open, .release = writeprotect_release, .read = writeprotect_read, .write = writeprotect_write, }; // 模块初始化 int writeprotect_init(void) { int result; printk(KERN_INFO "writeprotect: Initializing driver with major=%d, minor=%d\n", writeprotect_major, writeprotect_minor); // 检查主设备号是否有效 if (writeprotect_major <= 0) { printk(KERN_ALERT "writeprotect: Invalid major number %d\n", writeprotect_major); return -EINVAL; } // 构建设备号 dev_num = MKDEV(writeprotect_major, writeprotect_minor); // 注册设备号 - 使用指定的主设备号 result = register_chrdev_region(dev_num, 1, DEVICE_NAME); if (result < 0) { printk(KERN_ALERT "writeprotect: Failed to register major number %d\n", writeprotect_major); printk(KERN_ALERT "writeprotect: Try using a different major number\n"); return result; } printk(KERN_INFO "writeprotect: Registered with major=%d, minor=%d\n", MAJOR(dev_num), MINOR(dev_num)); // 分配设备结构体 dev = kmalloc(sizeof(struct writeprotect_dev), GFP_KERNEL); if (!dev) { result = -ENOMEM; goto fail_malloc; } memset(dev, 0, sizeof(struct writeprotect_dev)); // 分配缓冲区 dev->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL); if (!dev->buffer) { result = -ENOMEM; goto fail_buffer; } // 初始化互斥锁 mutex_init(&dev->lock); INIT_DELAYED_WORK(&dev->delay_work1, delay_work_func); // 初始化字符设备 cdev_init(&dev->cdev, &fops); dev->cdev.owner = THIS_MODULE; // 添加字符设备到系统 result = cdev_add(&dev->cdev, dev_num, 1); if (result) { printk(KERN_ALERT "writeprotect: Failed to add cdev\n"); goto fail_cdev; } // 创建设备类 char_class = class_create(THIS_MODULE, CLASS_NAME); if (IS_ERR(char_class)) { result = PTR_ERR(char_class); printk(KERN_ALERT "writeprotect: Failed to create class\n"); goto fail_class; } // 创建设备 char_device = device_create(char_class, NULL, dev_num, NULL, DEVICE_NAME); if (IS_ERR(char_device)) { result = PTR_ERR(char_device); printk(KERN_ALERT "writeprotect: Failed to create device\n"); goto fail_device; } printk(KERN_INFO "writeprotect: Driver initialized successfully\n"); printk(KERN_INFO "writeprotect: Device node: /dev/%s (major=%d, minor=%d)\n", DEVICE_NAME, writeprotect_major, writeprotect_minor); return 0; fail_device: class_destroy(char_class); fail_class: cdev_del(&dev->cdev); fail_cdev: kfree(dev->buffer); fail_buffer: kfree(dev); fail_malloc: unregister_chrdev_region(dev_num, 1); return result; } // 模块退出 void writeprotect_exit(void) { cancel_delayed_work_sync(&dev->delay_work1); device_destroy(char_class, dev_num); class_destroy(char_class); if (dev) { cdev_del(&dev->cdev); if (dev->buffer) kfree(dev->buffer); kfree(dev); } unregister_chrdev_region(dev_num, 1); printk(KERN_INFO "writeprotect: Driver removed (major=%d, minor=%d)\n", writeprotect_major, writeprotect_minor); }