我有一台便宜的一次性笔记本电脑,我想把它摆弄一番,它是一台 Thinkpad SL 500。
令我烦恼的是两个 LED,一个用于无线连接,一个用于休眠,它们根本不亮,虽然它们可以正常工作,但我已经在 Windows 上尝试过了。
所以我想为他们编写一个内核驱动程序,没什么大不了的,只是玩一下内核看起来是个好主意。
我的问题是我应该系统地遵循什么方法来找出哪些设备负责这些 led(一般来说,不一定特定于我的硬件),哪些驱动程序负责另外两个工作的 led,蓝牙和电池指示器?
当我说方法论时,我实际上指的是方法论,一步一步,并给出每一步的理由,就像我在这里给其他人的答案一样:void *p = &&abc; 中的 && 是什么意思
我擅长使用静态代码分析器等通过大型代码存储库进行 fgrepping,但我认为我缺乏硬件知识阻碍了我解决这个问题。
PS:我使用的是 ArchLinux,所以几乎是最新的内核版本。
答案1
我认为我缺乏硬件知识阻碍了我解决这个问题。
那么让我们从基础开始。指示灯 LED 可以通过多种方式控制:
LED 直接由外围芯片/设备控制。在这种情况下,CPU 和内核驱动程序无法控制 LED。以太网 RJ-45 插孔上的“活动”和“链接速度”LED 通常就是这种情况;这些 LED 将由以太网 PHY 设备直接/独家控制。
LED 由 CPU 或 SoC 的 GPIO(通用输入/输出)引脚控制。
LED是外部逻辑(例如FPGA芯片)的输出。
LED 是外围芯片上的输出。
最后三种情况在源代码中可能无法区分。端口或设备中的一个位登记将打开或关闭 LED。检查头文件以了解寄存器中的其他位将控制什么。将使用 I/O 指令或内存提取/存储指令读取/写入寄存器,具体取决于处理器架构。
请注意,LED 通常是电流接收器,与逻辑高电压相连,因此通过写入一个0
位值将引脚接地,LED 就会亮起。相反,LED 通常通过写入一个1
位值来关闭。由于只更改了寄存器的一位,因此在修改位之前通常需要读取整个寄存器。寄存器本身可能是一个关键区域,这将需要获取(和释放)互斥锁或自旋锁来保护整个操作。
源代码检查
如果设备驱动程序是专有的,那么您就完蛋了。否则,您应该能够获得源代码。您的发行版应该提供其源代码。有在线查看器,例如这个 Linux 内核树带有内置交叉引用超链接。如果驱动程序不在主线内核源代码树中,则应要求硬件制造商根据 GPL 条款提供源代码。
您提到了四个指标:
- 无线连接
- 冬眠
- 蓝牙连接
- 电池
获取命令的输出lsmod
,其中将列出附加到内核的运行时模块。从模块列表中,您需要确定哪些驱动程序与这些 LED 的功能相对应,例如无线网络、电源等。假设此 ThinkPad 具有 Intel 无线控制器芯片,则需要查看目录drivers/net/wireless/iwlwifi
。检查该驱动程序目录中的Kconfig
和文件,以了解实际硬件设备名称、配置符号、构建的模块和相应源代码Makefile
之间的关联。.ko
检查驱动程序源代码以了解指示灯 LED 的操作。如果操作未注释,则必须查找位操作、宏或过程调用。根据代码的模块化程度,组织此代码的方法有很多种,或者是否采用了 OOP 技术并且这些 LED 操作封装在其他驱动程序的过程内。请注意宏(即)#define
和头文件中的文本(可执行代码)。也就是说,仅检查.c
文件将是一个错误。还要注意某些设备代码可能位于arch/xxx/platform
或之下arch/xxx/machine
,尤其是对于嵌入式单板计算机。