文章

适配thinkbook的风扇控制器

本文目录 7

bg

重装系统之后摆脱了联想自带的应用商店和电脑管家,但是突然怀念起电脑管家的“降温除尘”功能了

在网上搜索了一下只有控制thinkpad的风扇的小程序,没有针对thinkbook的,借助寇德叉的帮助搓了一个

代码以及最后的程序见github

涉及到的一些东西以前也不是很了解,这里补充一下

WMI

WMI, Windows Management Instrumentation(Windows 管理规范):相当于Windows操作系统提供出来的一个系统管理界面

上层的程序可以通过它来查询/控制:

  • CPU、硬盘等硬件信息;
  • Windows 服务;
  • 系统设置;
  • 某些厂商提供的 BIOS 功能;
  • 某些 ACPI 设备

BIOS

一台机器有很多硬件,cpu、dram(memory)、ssd(disk)等等,OS统筹这些硬件,把接口开放给上面的应用

但是DRAM这种是通电之后就直接清空的硬件,那么机器刚通电的时候,操作系统要怎么初始化进去呢?因此就需要一个通电可以恢复的东西,他就是Firmware固件,在PC中通常就是BIOS/UEFI,他们会被存在**Flash Memory(闪存)**中

通电之后,CPU复位之后的第一件事就是从一个固定的PC开始执行指令,而这个地址叫作Reset Vector复位向量,它会被映射到主板Firmware的地方

ACPI

在windows启动之后,系统要进行电源管理、温度、睡眠、设备控制等等的操作;而每一块主板对于这些的操作都是不尽相同的,因此BIOS还需要提供一张表ACPI, Advanced Configuration and Power Interface(高级配置与电源接口),相当于写给OS的硬件说明书

在Windows的注册表里可以读到加载的ACPI

HKEY_LOCAL_MACHINE\HARDWARE\ACPI

ACPI里不止存了一些静态的数据,还包括AML, ACPI Machine Language(ACPI 机器语言,二进制码)以及用它写成的小程序

比如读取一个温度传感器的路径就是

Windows
   ↓
ACPI interpreter
   ↓
执行 AML method
   ↓
访问 EC
   ↓
读取温度传感器

EC

风扇特殊的地方在于,大多数机器里都有一个嵌入式控制器Embedded Controller,这个EC可以在OS完全不参与的情况下自己控制风扇,比如BIOS在开机的时候配置好风扇转动的策略,然后CPU/sensors给EC传数据,进而控制风扇


找接口

既然联想电脑管家有这个功能,那么说明这台机子肯定有对应的接口,但是直接去找无异于大海捞针

既然这样直接监视一下电脑管家的“降温除尘”用了驱动提供的什么设备,调用了什么接口就好了

经过观察,电脑管家的过程是这样的:

    ↓
打开 \\.\EnergyDrv
    ↓
调用 DeviceIoControl
    ↓
发送 {6, 1, 1}
    ↓
启动脉冲式除尘

照着这个思路复刻一遍,最后的效果还是和原来的降温除尘一样是脉冲式的,不会一直持续

这样之后寇德叉去扫了一下这台机子的 BIOS/ACPI 接口,从注册表里的HKEY_LOCAL_MACHINE\HARDWARE\ACPI的AML反编译成ASL(ACPI source language),然后顺着含着FA1S字样找了一下,发现了这样的判断逻辑

如果功能编号是 0x04030001
    返回 FA1S × 100

如果功能编号是 0x04030002
    返回 FA2S × 100

似乎是找到了两个风扇对应的编号

这个时候在root\wmi中又发现了很多包含LENOVO的类,其中的 LENOVO_OTHER_METHOD 里提供里通用的读写器

GetFeatureValue(IDs)
SetFeatureValue(IDs, value)

再把刚刚得到的设备代码送进去试一试

GetFeatureValue(0x04030001)
GetFeatureValue(0x04030002)

oi得到了风扇的转速,那再测试一下写入并改变转速的功能

SetFeatureValue(0x04030001, 4500)
SetFeatureValue(0x04030002, 4800)

随后每秒执行:

GetFeatureValue(0x04030001)
GetFeatureValue(0x04030002)

看到两个返回值迅速上升到约:

风扇 1:4500~4800 RPM
风扇 2:4900~5100 RPM

而且持续高速,不再像除尘模式那样断断续续

最后写入:

SetFeatureValue(0x04030001, 0)
SetFeatureValue(0x04030002, 0)

风扇又恢复了 BIOS 自动调速

代码

由于用到了WMI来对系统进行操作,所以寇德叉这里用微软的C#来写的(本人不会),也就简单的调用了一些windows和Lenovo给的接口

主要使用了.NET Framework这个库,来让C#程序能使用System.Management去访问Windows WMI