#include #include #include #include #include #include #include #include #include #include #include #include #include "gpioregs.h" #define DEVICE_NAME "myname" #define CLASS_NAME "myname_class" #define BUFFER_SIZE 1024 #define SWITCH_ID0 0xFD6D0A40 #define SWITCH_ID1 0xFD6D0A50 #define SWITCH_ID2 0xFD6D0B20 #define SWITCH_ID3 0xFD6D0B30 #define SWITCH_ID4 0xFD6D0B40 // 可以通过模块参数指定主设备号和次设备号 static int myname_major = 56; // 默认主设备号 static int myname_minor = 130; // 默认次设备号 module_param(myname_major, int, S_IRUGO); module_param(myname_minor, int, S_IRUGO); MODULE_PARM_DESC(myname_major, "Major device number"); MODULE_PARM_DESC(myname_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 myname_dev { char *buffer; size_t size; struct mutex lock; struct cdev cdev; struct delayed_work delay_work1; int board_id; }; static struct myname_dev *dev = NULL; unsigned int myname_readl(unsigned int addr) { void __iomem *reg_base = NULL; reg_base = ioremap(addr, 0x1000); return readl(reg_base); } static void delay_work_func(struct work_struct *work) { printk(KERN_ERR "delay_work_func\n"); } // 文件打开操作 static int myname_open(struct inode *inode, struct file *filp) { struct myname_dev *dev; dev = container_of(inode->i_cdev, struct myname_dev, cdev); filp->private_data = dev; printk(KERN_ERR "myname: Device opened (major=%d, minor=%d)\n", imajor(inode), iminor(inode)); return 0; } // 文件释放操作 static int myname_release(struct inode *inode, struct file *filp) { // release_region(PORT_80, 1); printk(KERN_ERR "myname: Device closed\n"); return 0; } // 读操作 - 支持cat命令 static ssize_t myname_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct myname_dev *dev = filp->private_data; ssize_t retval = 0; int ret = 0; if (mutex_lock_interruptible(&dev->lock)) return -ERESTARTSYS; // 关键检查:是否已经读到文件末尾? if (*f_pos >= dev->size) { printk(KERN_DEBUG "myname: EOF reached (pos=%lld, size=%zu)\n", *f_pos, dev->size); mutex_unlock(&dev->lock); return 0; // 返回 0 告诉 cat 文件结束 } // 计算剩余可读字节数 size_t available = dev->size - *f_pos; // 确定本次读取的字节数 if (count > available) { retval = available; } else { retval = count; } printk(KERN_DEBUG "myname: Attempting to read %zu bytes from pos %lld\n", retval, *f_pos); ret = copy_to_user(buf, dev->buffer + *f_pos, retval); if (ret != 0) { printk(KERN_ERR "myname: copy_to_user failed\n"); mutex_unlock(&dev->lock); return -EFAULT; } // 更新文件位置指针 - 这一步非常关键! *f_pos += retval; printk(KERN_DEBUG "myname: Read %zu bytes, new pos=%lld\n", retval, *f_pos); mutex_unlock(&dev->lock); return retval; // 返回实际读取的字节数 } // 写操作 static ssize_t myname_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct myname_dev *dev = filp->private_data; ssize_t retval = 0; size_t available; int ret = 0; return -1; // 加锁 if (mutex_lock_interruptible(&dev->lock)) { return -ERESTARTSYS; } // 计算可写数据量 if (count > dev->size) { count = dev->size; } // 拷贝数据 ret = copy_from_user(dev->buffer, buf, count); if (ret != 0) { printk(KERN_ERR "myname: copy_from_user failed\n"); goto out; } dev->size = count; printk(KERN_ERR "myname: 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 = myname_open, .release = myname_release, .read = myname_read, .write = myname_write, }; // 获取board_id int get_board_id(void) { unsigned int board_id = 0; board_id |= (myname_readl(SWITCH_ID0)&0x02) >> 1; board_id |= myname_readl(SWITCH_ID1)&0x02; board_id |= (myname_readl(SWITCH_ID2)&0x02) << 1; board_id |= (myname_readl(SWITCH_ID3)%0x02) << 2; board_id |= (myname_readl(SWITCH_ID4)%0x02) << 3; printk("board_id=%08x\n", board_id); if(board_id > 15) { printk(KERN_ERR "myname: Invalid board_id\n"); return -EINVAL; } if(board_id == 0) { memcpy(dev->buffer, "ci (Ruby Ci)", strlen("ci (Ruby Ci)")); dev->size = strlen("ci (Ruby Ci)"); } else if(board_id >= 1 && board_id <= 7) { memcpy(dev->buffer, "python (c18)", strlen("python (c18)")); dev->size = strlen("python (c18)"); } else if(board_id >= 8 && board_id <= 11) { memcpy(dev->buffer, "selene", strlen("selene")); dev->size = strlen("selene"); } else if(board_id >= 12 && board_id <= 15) { memcpy(dev->buffer, "cobra (Commander Ci)", strlen("cobra (Commander Ci)")); dev->size = strlen("cobra (Commander Ci)"); } printk(KERN_ERR "myname: board_id = %d\n", board_id); return board_id; } // 模块初始化 int myname_init(void) { int result; printk(KERN_ERR "myname: Initializing driver with major=%d, minor=%d\n", myname_major, myname_minor); // 检查主设备号是否有效 if (myname_major <= 0) { printk(KERN_ALERT "myname: Invalid major number %d\n", myname_major); return -EINVAL; } // 构建设备号 dev_num = MKDEV(myname_major, myname_minor); // 注册设备号 - 使用指定的主设备号 result = register_chrdev_region(dev_num, 1, DEVICE_NAME); if (result < 0) { printk(KERN_ALERT "myname: Failed to register major number %d\n", myname_major); printk(KERN_ALERT "myname: Try using a different major number\n"); return result; } printk(KERN_ERR "myname: Registered with major=%d, minor=%d\n", MAJOR(dev_num), MINOR(dev_num)); // 分配设备结构体 dev = kmalloc(sizeof(struct myname_dev), GFP_KERNEL); if (!dev) { result = -ENOMEM; goto fail_malloc; } memset(dev, 0, sizeof(struct myname_dev)); // 分配缓冲区 dev->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL); if (!dev->buffer) { result = -ENOMEM; goto fail_buffer; } memset(dev->buffer, 0, BUFFER_SIZE); // 初始化互斥锁 mutex_init(&dev->lock); INIT_DELAYED_WORK(&dev->delay_work1, delay_work_func); dev->board_id = get_board_id(); printk(KERN_ERR "myname: %s\n", dev->buffer); // 初始化字符设备 cdev_init(&dev->cdev, &fops); dev->cdev.owner = THIS_MODULE; // 添加字符设备到系统 result = cdev_add(&dev->cdev, dev_num, 1); if (result) { printk(KERN_ALERT "myname: 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 "myname: 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 "myname: Failed to create device\n"); goto fail_device; } printk(KERN_ERR "myname: Driver initialized successfully\n"); printk(KERN_ERR "myname: Device node: /dev/%s (major=%d, minor=%d)\n", DEVICE_NAME, myname_major, myname_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 myname_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_ERR "myname: Driver removed (major=%d, minor=%d)\n", myname_major, myname_minor); }