#include #include #include #include #include #include // for copy_to_user() and copy_from_user() const char *TAG = "MYNEWNODE"; static int major_number = 0; // 默认自动分配主设备号 static struct cdev my_cdev; static struct class *my_class; char data_buf[100] = "Hello from kernel space! ."; char write_buf[100 = "Hello from user space!"; // 打开字符设备 static int gpio_led_open(struct inode *inode, struct file *file) { printk("%s: open!\n", TAG); return 0; } // 关闭字符设备 static int gpio_led_release(struct inode *inode, struct file *file) { printk("%s: release!\n", TAG); return 0; } // 读取数据(从内核空间的 data_buf[] 数组中读取数据) static ssize_t gpio_led_read(struct file *file, char __user *buf, size_t len, loff_t *offset) { ssize_t ret; size_t to_read; printk("%s: read!\n", TAG); if (*offset >= sizeof(data_buf)) { return 0; // 没有更多数据可以读取 } // 计算最多读取的数据长度,并确保不会越界 to_read = min(len, (size_t)(sizeof(data_buf) - *offset)); // 强制转换为 size_t 类型 // 从内核空间复制数据到用户空间 ret = copy_to_user(buf, data_buf + *offset, to_read); if (ret != 0) { printk("%s: copy_to_user failed!\n", TAG); return -EFAULT; } // 更新偏移量 *offset += to_read; return to_read; // 返回实际读取的字节数 } // 写入数据(将数据保存到内核空间的 data_buf[] 数组) static ssize_t gpio_led_write(struct file *file, const char __user *buf, size_t len, loff_t *offset) { ssize_t ret; printk("%s: write!\n", TAG); // 确保写入的数据大小不超过缓冲区 if (len > sizeof(data_buf)) { printk("%s: write data_buf too large!\n", TAG); return -EINVAL; } // 从用户空间复制数据到内核空间 ret = copy_from_user(data_buf, buf, len); if (ret != 0) { printk("%s: copy_from_user failed!\n", TAG); return -EFAULT; } return len; // 返回实际写入的字节数 } // 字符设备操作结构体 static const struct file_operations gpio_led_fops = { .owner = THIS_MODULE, .open = gpio_led_open, .release = gpio_led_release, .read = gpio_led_read, .write = gpio_led_write, }; // probe函数:设备初始化时调用 static int gpio_led_probe(struct platform_device *pdev) { int ret; printk("%s: probe!\n", TAG); // 为字符设备分配主设备号 ret = alloc_chrdev_region(&major_number, 0, 1, "gpio_led"); if (ret < 0) { printk("%s: alloc_chrdev_region failed!\n", TAG); return ret; } // 注册字符设备 cdev_init(&my_cdev, &gpio_led_fops); my_cdev.owner = THIS_MODULE; ret = cdev_add(&my_cdev, major_number, 1); if (ret) { printk("%s: cdev_add failed!\n", TAG); unregister_chrdev_region(major_number, 1); return ret; } // 创建设备类 my_class = class_create(THIS_MODULE, "gpio_led_class"); if (IS_ERR(my_class)) { ret = PTR_ERR(my_class); printk("%s: class_create failed!\n", TAG); cdev_del(&my_cdev); unregister_chrdev_region(major_number, 1); return ret; } // 创建设备节点 if (IS_ERR(device_create(my_class, NULL, major_number, NULL, "gpio_led"))) { printk("%s: device_create failed!\n", TAG); class_destroy(my_class); cdev_del(&my_cdev); unregister_chrdev_region(major_number, 1); return -ENOMEM; } return 0; } // remove函数:设备卸载时调用 static int gpio_led_remove(struct platform_device *pdev) { printk("%s: remove!\n", TAG); // 注销字符设备 device_destroy(my_class, major_number); class_destroy(my_class); cdev_del(&my_cdev); unregister_chrdev_region(major_number, 1); return 0; } // shutdown函数:设备关闭时调用 static void gpio_led_shutdown(struct platform_device *pdev) { printk("%s: shutdown!\n", TAG); } static const struct of_device_id of_gpio_leds_match[] = { { .compatible = "led-user", }, {} }; MODULE_DEVICE_TABLE(of, of_gpio_leds_match); // 定义平台驱动 static struct platform_driver gpio_led_driver = { .probe = gpio_led_probe, .remove = gpio_led_remove, .shutdown = gpio_led_shutdown, .driver = { .name = "led-user", .of_match_table = of_gpio_leds_match, }, }; module_platform_driver(gpio_led_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Simple GPIO LEDs driver");