#include #include #include #include #include #include #include #include #include #include #include #include #include #include "gpioregs.h" #define DEVICE_NAME "power" #define CLASS_NAME "power_class" #define BUFFER_SIZE 1024 // 可以通过模块参数指定主设备号和次设备号 static int power_major = 56; // 默认主设备号 static int power_minor = 70; // 默认次设备号 module_param(power_major, int, S_IRUGO); module_param(power_minor, int, S_IRUGO); MODULE_PARM_DESC(power_major, "Major device number"); MODULE_PARM_DESC(power_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 power_dev { char *buffer; size_t size; struct mutex lock; struct cdev cdev; wait_queue_head_t read_wait; struct delayed_work delay_work1; }; static struct power_dev *dev = NULL; static void delay_work_func(struct work_struct *work) { printk(KERN_INFO "delay_work_func\n"); } // 文件打开操作 static int power_open(struct inode *inode, struct file *filp) { struct power_dev *dev; dev = container_of(inode->i_cdev, struct power_dev, cdev); filp->private_data = dev; printk(KERN_INFO "power: Device opened (major=%d, minor=%d)\n", imajor(inode), iminor(inode)); return 0; } // 文件释放操作 static int power_release(struct inode *inode, struct file *filp) { // release_region(PORT_80, 1); printk(KERN_INFO "power: Device closed\n"); return 0; } // 读操作 - 支持cat命令 static ssize_t power_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct power_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 "power: copy_to_user failed\n"); goto out; } printk(KERN_INFO "power: Read %zu bytes\n", count); out: mutex_unlock(&dev->lock); return ret; } // 写操作 static ssize_t power_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct power_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 "power: copy_from_user failed\n"); goto out; } dev->size = count; printk(KERN_INFO "power: 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 unsigned int power_poll(struct file *filp, poll_table *wait) { // poll_wait(filp, &dev->read_wait, wait); return 0; } // 文件操作结构体 static struct file_operations fops = { .owner = THIS_MODULE, .open = power_open, .release = power_release, .read = power_read, .write = power_write, .poll = power_poll, }; // 模块初始化 int power_init(void) { int result; printk(KERN_INFO "power: Initializing driver with major=%d, minor=%d\n", power_major, power_minor); // 检查主设备号是否有效 if (power_major <= 0) { printk(KERN_ALERT "power: Invalid major number %d\n", power_major); return -EINVAL; } // 构建设备号 dev_num = MKDEV(power_major, power_minor); // 注册设备号 - 使用指定的主设备号 result = register_chrdev_region(dev_num, 1, DEVICE_NAME); if (result < 0) { printk(KERN_ALERT "power: Failed to register major number %d\n", power_major); printk(KERN_ALERT "power: Try using a different major number\n"); return result; } printk(KERN_INFO "power: Registered with major=%d, minor=%d\n", MAJOR(dev_num), MINOR(dev_num)); // 分配设备结构体 dev = kmalloc(sizeof(struct power_dev), GFP_KERNEL); if (!dev) { result = -ENOMEM; goto fail_malloc; } memset(dev, 0, sizeof(struct power_dev)); init_waitqueue_head(&dev->read_wait); // 分配缓冲区 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 "power: 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 "power: 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 "power: Failed to create device\n"); goto fail_device; } printk(KERN_INFO "power: Driver initialized successfully\n"); printk(KERN_INFO "power: Device node: /dev/%s (major=%d, minor=%d)\n", DEVICE_NAME, power_major, power_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 power_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 "power: Driver removed (major=%d, minor=%d)\n", power_major, power_minor); }