#include #include #include #include #include #include #include #include const char *TAG = "MYNEWNODE"; static int major_number = 0; // 默认自动分配主设备号 static struct cdev my_cdev; static struct class *my_class; static int gpio_pin = -1; // GPIO 引脚号 // 打开字符设备 static int gpio_led_open(struct inode *inode, struct file *file) { int ret; printk("%s:open!\n", TAG); // 如果 GPIO 引脚没有初始化,先进行初始化 if (gpio_pin < 0) { printk("%s:GPIO not initialized correctly.\n", TAG); return -EINVAL; } // 设置 GPIO 为输出模式,初始化时设置为低电平(关闭 LED) ret = gpio_direction_output(gpio_pin, 0); // 默认设置为低电平(LED 关闭) if (ret) { printk("%s:Failed to set GPIO direction\n", TAG); return ret; } // 可以根据需要设置 GPIO 的初始电平,比如点亮 LED gpio_set_value(gpio_pin, 1); // 设置为高电平,点亮 LED(假设低电平为关闭) return 0; } // 释放字符设备 static int gpio_led_release(struct inode *inode, struct file *file) { printk("%s:release!\n", TAG); // 在设备释放时设置 GPIO 为低电平(关闭 LED) gpio_set_value(gpio_pin, 0); // 设置为低电平,关闭 LED return 0; } // 读取数据(此示例没有实际硬件操作) // 读取数据(控制 LED) static ssize_t gpio_led_read(struct file *file, char __user *buf, size_t len, loff_t *offset) { int gpio_value = 0; char read_buf[2]; // 用来存储读取的数据 printk("%s:read!\n", TAG); // 模拟 LED 状态控制,循环写入 '0' 和 '1' if (*offset % 2 == 0) { gpio_value = 0; // 关闭 LED read_buf[0] = '0'; } else { gpio_value = 1; // 点亮 LED read_buf[0] = '1'; } // 设置 GPIO 引脚电平,控制 LED 开关 gpio_set_value(gpio_pin, gpio_value); // 将 LED 状态写入到用户空间 if (copy_to_user(buf, read_buf, 1)) { return -EFAULT; } // 更新偏移量,每次切换一次 *offset += 1; return 1; // 返回读取的字节数 } // 写入数据(控制 GPIO) static ssize_t gpio_led_write(struct file *file, const char __user *buf, size_t len, loff_t *offset) { char user_buf[10]; int gpio_value = 0; printk("%s:write!\n", TAG); if (len > sizeof(user_buf) - 1) { len = sizeof(user_buf) - 1; } if (copy_from_user(user_buf, buf, len)) { return -EFAULT; } user_buf[len] = '\0'; if (user_buf[0] == '1') { gpio_value = 1; } else if (user_buf[0] == '0') { gpio_value = 0; } else { return -EINVAL; } gpio_set_value(gpio_pin, gpio_value); 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); // 获取设备树中的 GPIO 引脚 gpio_pin = of_get_named_gpio(pdev->dev.of_node, "gpios", 0); if (gpio_pin < 0) { printk("%s:Failed to get GPIO from device tree!\n", TAG); return gpio_pin; } // 申请 GPIO 引脚 ret = gpio_request(gpio_pin, "gpio_led"); if (ret) { printk("%s:Failed to request GPIO %d\n", TAG, gpio_pin); return ret; } // 初始化设备文件 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); // 释放 GPIO 引脚 gpio_free(gpio_pin); // 注销字符设备 device_destroy(my_class, major_number); class_destroy(my_class); cdev_del(&my_cdev); unregister_chrdev_region(major_number, 1); return 0; } // 关机处理函数 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 = "gpio_led_driver", .of_match_table = of_gpio_leds_match, }, }; module_platform_driver(gpio_led_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("GPIO control driver with character device");