最近一直在发关于ideapad-laptop.c(位于<内核源码根目录>/drivers/platform/x86/下)的系列文章,究其原因,是因为工作中遇到了一个问题,描述如下:
在笔者的联想笔记本上,通过Fn+Space可以控制笔记本键盘按键的背光(点亮/熄灭/增加亮度),但在图形界面中并没有相应的图标显示出来。举个例子,按亮度+或亮度-键,屏幕的亮度可以增加或减少,同时桌面图形环境中出现相应的图标,如下所示:
对于音量+和音量-也是一样,调节音量大小的同时出现以下图标::
而键盘按键背光控制和上边不一样,只能控制背光,却无法在桌面图形环境下出现类似上边的图标。
于是开始针对这一问题进行分析,当然希望在解决这一问题的过程中,能够顺带多涉及一些ideapad-laptop.c文件中的内容,尽可能地多学习一些相关知识,这才有了围绕ideapad-laptop.c展开的一系列文章。
抛开其它知识点不谈,单就这个问题而言,通过内核日志(/var/log/kern.log)发现每次按Fn+Space的时候,内核日志中都会出现一次如下打印(时间及时间戳会有所不同):
Dec 5 23:10:33 ph-ThinkBook-14-G2-ITL kernel: [95710.506261] ideapad_acpi VPC2004:00: Unknown event: 12
搜索关键字"Unknown event",最终定位到其出自于ideapad-laptop.c,具体所在函数如下:
static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
{
struct ideapad_private *priv = data;
unsigned long vpc1, vpc2, bit;
if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
return;
if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
return;
vpc1 = (vpc2 << 8) | vpc1;
for_each_set_bit (bit, &vpc1, 16) {
switch (bit) {
case 13:
case 11:
case 8:
case 7:
case 6:
ideapad_input_report(priv, bit);
break;
case 10:
/*
* This event gets send on a Yoga 300-11IBR when the EC
* believes that the device has changed between laptop/
* tent/stand/tablet mode. The EC relies on getting
* angle info from 2 accelerometers through a special
* windows service calling a DSM on the DUAL250E ACPI-
* device. Linux does not do this, making the laptop/
* tent/stand/tablet mode info unreliable, so we simply
* ignore these events.
*/
break;
case 9:
ideapad_sync_rfk_state(priv);
break;
case 5:
ideapad_sync_touchpad_state(priv);
break;
case 4:
ideapad_backlight_notify_brightness(priv);
break;
case 3:
ideapad_input_novokey(priv);
break;
case 2:
ideapad_backlight_notify_power(priv);
break;
case 1:
/*
* Some IdeaPads report event 1 every ~20
* seconds while on battery power; some
* report this when changing to/from tablet
* mode; some report this when the keyboard
* backlight has changed.
*/
ideapad_kbd_bl_notify(priv);
break;
case 0:
ideapad_check_special_buttons(priv);
break;
default:
dev_info(&priv->platform_device->dev,
"Unknown event: %lu\n", bit);
}
}
}
笔者曾经一度认为到这里问题的根因就已经找到了,就是因为没有对bit为12的处理,加入处理后问题就能解决。于是在case 1的上一行加入了"case 12:",之后重新编译内核并烧录。满心以为问题能够解决,但没想到问题依旧,仍然是无法出现图标。看来问题并非想象中那样简单,有更深层次的原因。这更深层次的原因是什么,又应该如何探索才能揭开谜团?且看下回分解。