哪些网站专门做细胞的收录批量查询工具
哪些网站专门做细胞的,收录批量查询工具,做网站一般都是织梦,虹口手机网站制作Input子系统框架input子系统输入事件层Linux内核中注册了多个事件处理handler驱动模块#xff0c;分别是#xff1a;evdev#xff1a;通用输入事件接口#xff0c;将不同设备的输入(如键盘、鼠标、触摸屏)转换为统一的事件格式。用户可以通过设备文件/dev/eventX或/dev/inp…Input子系统框架input子系统输入事件层Linux内核中注册了多个事件处理handler驱动模块分别是evdev通用输入事件接口将不同设备的输入(如键盘、鼠标、触摸屏)转换为统一的事件格式。用户可以通过设备文件/dev/eventX或/dev/input/eventX读取事件。evdev次设设备号范围64-95和256-1024如果设备数量不超过32使用静态保留区范围64-95如果超过32个则在256-1024之间动态分配。mousedev一个早期的鼠标事件接口支持PS/2接口的鼠标现在鼠标基本上都是USB或蓝牙接口的他们使用了HID接口HID后文会单独介绍。joydev专为游戏手柄、摇杆设计处理多轴、按键事件生成/dev/input/jsX设备节点。提供标准游戏设备接口支持校准和力反馈功能方便游戏或输入工具直接访问。input_leds管理输入设备的LED状态如键盘的CapsLock、NumLock。通过sysfs如/sys/class/leds或ioctl控制LED开关是硬件驱动与用户空间控制的中继。子系统框架关系input_dev是硬件驱动层代表一个input设备。input_handler是事件处理层代表一个事件处理器。input_handle属于核心层代表一个配对的input设备与input事件处理器。Linux内核中维护了一个名为input_handler_list的链表每个input_handler都会被注册到这个链表上而链表是通过类型为list_head的成员node串联起来的。input子系统设备驱动层Linux设备驱动层结构体#include linux/input.h #include linux/device.h #include linux/mutex.h #include linux/list.h /** * struct input_dev - Linux输入子系统核心设备结构体 * 整合了基础信息、事件能力位图、内部管理三大核心部分 */ struct input_dev { /************************ 第一部分设备基础信息 ************************/ const char *name; // 设备名称如 gpio-keys、touchscreen const char *phys; // 物理路径如 gpio/keys、i2c/tsc const char *uniq; // 设备唯一标识符区分同类型设备 struct device dev; // 集成Linux设备模型的基础结构电源/总线管理 /************************ 第二部分核心事件能力位图 ************************/ // 设备属性位图描述设备物理特性 unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)]; // 事件类型位图声明支持的事件大类 unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; // 各类事件码位图声明具体支持的事件 unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; // 按键事件码EV_KEY unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; // 相对坐标码EV_REL unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; // 绝对坐标码EV_ABS unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)]; // 混杂事件码EV_MSC unsigned long ledbit[BITS_TO_LONGS(LED_CNT)]; // LED控制码EV_LED unsigned long sndbit[BITS_TO_LONGS(SND_CNT)]; // 声音控制码EV_SND unsigned long ffbit[BITS_TO_LONGS(FF_CNT)]; // 力反馈码EV_FF unsigned long swbit[BITS_TO_LONGS(SW_CNT)]; // 开关状态码EV_SW /************************ 第三部分内部管理成员 ************************/ bool open; // 标记设备是否被用户空间打开 struct mutex mutex; // 保护结构体的互斥锁防止并发修改 struct list_head node; // 挂入内核全局input_dev_list的链表节点 };事件类型与事件码设置用户空间事件上报structinput_event表示input设备给用户空间上报的事件#include linux/types.h // 提供__uXX类型定义 #include linux/time.h // 提供struct timeval /** * struct input_event - 输入事件的标准化结构体 * 内核驱动上报事件、用户空间读取事件均使用此格式 */ struct input_event { struct timeval time; // 事件发生的时间戳秒微秒 __u16 type; // 事件类型对应EV_*宏 __u16 code; // 事件码对应KEY_*/REL_*/ABS_*等宏 __s32 value; // 事件值按键状态、坐标值等 };Input子系统常用接口input_dev结构体分配与释放手动分配input_dev结构体struct input_dev *input_allocate_device(void);释放input_dev结构体void input_free_device(struct input_dev*dev);自动管理input_dev结构体当dev被释放时input_dev结构体自动释放struct input_dev*devm_input_allocate_device(struct device *dev);Input子系统注册与注销注册input_dev到系统中的input核心层int input_register_device(struct input_dev*dev);在input核心层注销input_devvoid input_unregister_device(struct input_dev*dev);input事件上报上报一个按键事件void input_report_key(struct input_dev *dev, unsigned int code, int value);上报一个相对坐标事件void input_report_rel(struct input_dev *dev, unsigned int code, int value);上报一个绝对坐标事件void input_report_abs(struct input_dev *dev, unsigned int code, int value);标记一组输入事件的结束void input_sync(struct input_dev *dev);触摸屏事件上报上报触摸点信息void input_mt_slot(struct input_dev *dev, int slot);添加新触摸点bool input_mt_report_slot_state(struct input_dev *dev, unsigned int tool_type, bool active);同步触摸事件void input_mt_sync(struct input_dev *dev);驱动编写/* * 内核按键驱动 - 基于GPIO中断和input子系统实现 * 功能通过GPIO中断检测按键事件并上报到input子系统 * 适配设备树中compatible为fs,inputkey的设备节点 */ // 内核错误处理相关头文件 #include linux/err.h // GPIO消费者接口头文件 - 用于GPIO操作 #include linux/gpio/consumer.h // 输入事件编码头文件 - 定义了KEY_1/KEY_2等按键编码 #include linux/input-event-codes.h // 输入子系统核心头文件 #include linux/input.h // 内核打印函数头文件 #include linux/printk.h // 内核核心头文件 #include linux/kernel.h // 模块编程核心头文件 #include linux/module.h // 平台设备驱动头文件 #include linux/platform_device.h // 设备树操作头文件 #include linux/of.h // 中断处理头文件 #include linux/interrupt.h // 内核内存分配头文件 #include linux/slab.h // 按键状态定义 - 0表示按键释放1表示按键按下 #define GPIO_KEY_UP (0) // 按键释放状态 #define GPIO_KEY_DOWN (1) // 按键按下状态 // 最大支持的按键数量 #define KEY_NUM 10 /* * 按键编码映射表 * 索引对应设备树中定义的按键GPIO顺序 * user:KEY_1, key1:KEY_2, key2:KEY_3, key3:KEY_4 */ static int key_code[] {KEY_1, KEY_2, KEY_3, KEY_4}; /* * 设备私有数据结构体 * 用于保存驱动运行时的所有关键数据 */ struct fs_key_device { int key_num; // 实际检测到的按键数量 int irq[KEY_NUM]; // 每个按键对应的中断号数组 struct work_struct wq; // 工作队列 - 用于中断下半部处理 struct gpio_descs *gpiod_descs; // GPIO描述符数组 - 保存所有按键GPIO struct input_dev *input; // input子系统设备结构体 int trigger_irq; // 记录当前触发中断的irq号 }; /* * 中断处理函数(上半部) * 功能快速响应中断记录中断源调度工作队列处理具体逻辑 * irq: 触发的中断号 * dev_id: 设备私有数据指针 * 返回值IRQ_HANDLED表示中断已处理 */ irqreturn_t fs_key_isr(int irq, void *dev_id) { // 将通用指针转换为设备私有数据结构体指针 struct fs_key_device *key_dev dev_id; // 打印中断触发信息(调试用) printk(fs_key: irq %d trigger\n, irq); /* 记录触发中断的irq号 - 传递给下半部使用 */ key_dev-trigger_irq irq; /* 调度工作队列 - 将耗时操作推迟到进程上下文执行 */ schedule_work(key_dev-wq); // 告知内核中断已处理 return IRQ_HANDLED; } /* * 工作队列处理函数(下半部) * 功能在进程上下文处理按键事件读取按键状态并上报到input子系统 * wq: 工作队列结构体指针 */ void fs_key_workqueue(struct work_struct *wq) { // 通过container_of宏从work_struct指针反向获取设备私有数据 struct fs_key_device *key_dev container_of(wq, struct fs_key_device, wq); struct gpio_descs *gpiod_descs key_dev-gpiod_descs; int i 0, irq 0; int key_status 0; // 保存按键状态(0/1) int code 0; // 保存要上报的按键编码 printk(fs_key: work function\n); /* 遍历所有按键找到触发中断的那个按键 */ for (i 0; i key_dev-key_num; i) { // 将GPIO描述符转换为对应的中断号 irq gpiod_to_irq(gpiod_descs-desc[i]); // 匹配触发中断的irq号 if (key_dev-trigger_irq irq) { /* 读取触发中断的按键当前状态 */ key_status gpiod_get_value(gpiod_descs-desc[i]); /* 获取该按键对应的上报编码 */ code key_code[i]; break; // 找到后退出循环 } } /* 上报按键事件到input子系统 */ // key_status为1表示GPIO高电平(按键释放)0表示低电平(按键按下) input_report_key(key_dev-input, code, key_status ? GPIO_KEY_UP : GPIO_KEY_DOWN); /* 同步事件 - 告知input子系统事件上报完成 */ input_sync(key_dev-input); // 清除触发中断的irq号标记 key_dev-trigger_irq 0; } /* * 平台驱动probe函数 * 功能设备匹配成功后初始化驱动申请资源注册中断和input设备 * pdev: 平台设备结构体指针 * 返回值0表示成功负数表示失败 */ static int fs_key_probe(struct platform_device *pdev) { struct fs_key_device *key_dev; // 设备私有数据指针 struct device *dev pdev-dev; // 设备结构体指针 struct gpio_descs *gpiod_descs; // GPIO描述符数组 struct input_dev *input; // input设备结构体 int ret 0; // 返回值 int i 0; // 循环变量 /* 1. 申请设备私有数据结构体内存 */ key_dev kmalloc(sizeof(*key_dev), GFP_KERNEL); if (key_dev NULL) { printk(failed: no memory\n); return -ENOMEM; // 内存不足错误码 } /* 2. 从设备树获取按键GPIO数组 */ // keys - 设备树中gpio属性名GPIOD_IN - 设置为输入模式 gpiod_descs devm_gpiod_get_array(dev, keys, GPIOD_IN); if (IS_ERR(gpiod_descs)) { // 检查获取是否失败 ret PTR_ERR(gpiod_descs); // 获取具体错误码 goto err0; // 跳转到错误处理 } /* 3. 保存GPIO描述符和按键数量到私有数据 */ key_dev-gpiod_descs gpiod_descs; key_dev-key_num gpiod_descs-ndescs; /* 4. 为每个按键申请并注册中断 */ for (i 0; i key_dev-key_num; i) { /* 获取GPIO对应的中断号 */ key_dev-irq[i] gpiod_to_irq(gpiod_descs-desc[i]); // 检查中断号有效性 if (key_dev-irq[i] 0) { printk(failed: cannot get irq no\n); ret -ENODEV; // 设备不存在错误码 goto err1; // 跳转到中断释放逻辑 } /* 注册中断处理函数 */ // IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING - 双边沿触发 // fs_key - 中断名称key_dev - 传递给中断处理函数的参数 ret request_irq(key_dev-irq[i], fs_key_isr, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, fs_key, key_dev); if (ret 0) { // 检查中断注册是否失败 printk(failed: cannot request irq\n); goto err1; // 跳转到中断释放逻辑 } } /* 5. 初始化工作队列 */ INIT_WORK(key_dev-wq, fs_key_workqueue); /* 6. 将私有数据保存到平台设备中 - 方便后续remove函数获取 */ platform_set_drvdata(pdev, key_dev); /* 7. 申请input设备结构体 */ input input_allocate_device(); if (!input) { printk(failed to allocate input device.\n); ret -ENOMEM; goto err1; } key_dev-input input; // 保存到私有数据 /* 8. 配置input设备基本信息 */ input-name fsinputkey; // 设备名称 input-dev.parent dev; // 父设备 // 设置input设备ID信息 input-id.bustype BUS_HOST; // 总线类型主机总线 input-id.vendor 0x0001; // 厂商编号 input-id.product 0x0001; // 产品编号 input-id.version 0x0101; // 版本编号 /* 9. 设置input设备支持的事件类型 */ set_bit(EV_KEY, input-evbit); // 支持按键事件 /* 10. 设置支持的具体按键编码 */ for (i 0; i key_dev-key_num; i) { set_bit(key_code[i], input-keybit); // 注册支持的按键 } /* 11. 注册input设备到内核 */ ret input_register_device(input); if (ret) { printk(register input device error:%d.\n, ret); goto err2; // 跳转到input设备释放逻辑 } // 初始化成功 return 0; /* 错误处理流程 - 反向释放已申请的资源 */ err2: // 释放input设备结构体 input_free_device(input); err1: // 释放已注册的中断 for(; i0; i--) free_irq(key_dev-irq[i], key_dev); err0: // 释放设备私有数据内存 kfree(key_dev); return ret; } /* * 平台驱动remove函数 * 功能驱动卸载或设备移除时释放所有申请的资源 * pdev: 平台设备结构体指针 * 返回值0表示成功 */ static int fs_key_remove(struct platform_device *pdev) { // 从平台设备中获取私有数据 struct fs_key_device *key_dev platform_get_drvdata(pdev); int i 0, key_num key_dev-key_num; /* 1. 注销input设备 */ input_unregister_device(key_dev-input); /* 2. 释放input_dev结构体 - 注input_unregister_device会自动释放此处注释避免重复释放 // input_free_device(key_dev-input); */ /* 3. 释放中断资源 */ for (i 0; i key_num; i) free_irq(key_dev-irq[i], key_dev); /* 4. 释放设备私有数据内存 */ kfree(key_dev); return 0; } /* * 设备树匹配表 * 用于匹配设备树中compatible属性为fs,inputkey的节点 */ static const struct of_device_id __maybe_unused fs_key_of_match[] { { .compatible fs,inputkey, // 匹配字符串 }, {/* LIST END */}, // 表结束标记 }; // 将匹配表注册到内核让内核知道该驱动支持的设备树节点 MODULE_DEVICE_TABLE(of, fs_key_of_match); /* * 平台驱动结构体 * 定义驱动的核心操作函数和匹配信息 */ static struct platform_driver fs_key_driver { .driver { .name fsinputkey, // 驱动名称 .of_match_table of_match_ptr(fs_key_of_match), // 设备树匹配表 }, .probe fs_key_probe, // 匹配成功后的初始化函数 .remove fs_key_remove // 驱动卸载时的清理函数 }; /* * 模块初始化函数 * 功能加载模块时注册平台驱动 */ static int __init fs_key_init(void) { return platform_driver_register(fs_key_driver); } /* * 模块退出函数 * 功能卸载模块时注销平台驱动 */ static void __exit fs_key_exit(void) { platform_driver_unregister(fs_key_driver); } // 指定模块初始化和退出函数 module_init(fs_key_init); module_exit(fs_key_exit); // 模块许可证 - GPL许可证确保模块可以加载到内核 MODULE_LICENSE(GPL);