接前一篇文章《Linux内核中ideapad-laptop.c文件全解析6》,地址为:
Linux内核中ideapad-laptop.c文件全解析6_蓝天居士的博客-优快云博客
上一篇分析了ideapad_input_init,本篇详细分析ideapad_kbd_bl_init。
-
ideapad_kbd_bl_init
ideapad_kbd_bl_init在同文件(drivers/platform/x86/ideapad-laptop.c)中实现,代码如下:
static int ideapad_kbd_bl_init(struct ideapad_private *priv)
{
int brightness, err;
if (!priv->features.kbd_bl)
return -ENODEV;
if (WARN_ON(priv->kbd_bl.initialized))
return -EEXIST;
brightness = ideapad_kbd_bl_brightness_get(priv);
if (brightness < 0)
return brightness;
priv->kbd_bl.last_brightness = brightness;
priv->kbd_bl.led.name = "platform::" LED_FUNCTION_KBD_BACKLIGHT;
priv->kbd_bl.led.max_brightness = 1;
priv->kbd_bl.led.brightness_get = ideapad_kbd_bl_led_cdev_brightness_get;
priv->kbd_bl.led.brightness_set_blocking = ideapad_kbd_bl_led_cdev_brightness_set;
priv->kbd_bl.led.flags = LED_BRIGHT_HW_CHANGED;
err = led_classdev_register(&priv->platform_device->dev, &priv->kbd_bl.led);
if (err)
return err;
priv->kbd_bl.initialized = true;
return 0;
}
static void ideapad_kbd_bl_exit(struct ideapad_private *priv)
{
if (!priv->kbd_bl.initialized)
return;
priv->kbd_bl.initialized = false;
led_classdev_unregister(&priv->kbd_bl.led);
}
如果kbd_bl.initialized为true,则说明已经做过初始化了,返回-EEXIST。这个逻辑要求系统只能有一个键盘背光设备。
ideapad_kbd_bl_brightness_get函数在同文件中实现,代码如下:
static int ideapad_kbd_bl_brightness_get(struct ideapad_private *priv)
{
unsigned long hals;
int err;
err = eval_hals(priv->adev->handle, &hals);
if (err)
return err;
return !!test_bit(HALS_KBD_BL_STATE_BIT, &hals);
}
eval_hals函数单独在一篇文章中介绍。
test_bit检测读取的hals中是否包含了HALS_KBD_BL_STATE_BIT。
设置kbd_bl.led的name为"platform::kbd_backlight"。LED_FUNCTION_KBD_BACKLIGHT宏定义在include/dt-bindings/leds/common.h中。
设置kbd_bl.led的max_brightness为1。
设置kbd_bl.led的brightness_get函数指针为ideapad_kbd_bl_led_cdev_brightness_get。ideapad_kbd_bl_led_cdev_brightness_get函数在同文件(drivers/platform/x86/ideapad-laptop.c)中定义,代码如下:
static enum led_brightness ideapad_kbd_bl_led_cdev_brightness_get(struct led_classdev *led_cdev)
{
struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led);
return ideapad_kbd_bl_brightness_get(priv);
}
设置kbd_bl.led的brightness_set_blocking函数指针为ideapad_kbd_bl_led_cdev_brightness_set。ideapad_kbd_bl_led_cdev_brightness_set函数在同文件(drivers/platform/x86/ideapad-laptop.c)中定义,代码如下:
static int ideapad_kbd_bl_led_cdev_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led);
return ideapad_kbd_bl_brightness_set(priv, brightness);
}
设置kbd_bl.led的flags为LED_BRIGHT_HW_CHANGED(include/linux/leds.h中定义:BIT(21))。
led_classdev_register函数也在include/linux/leds.h中定义和实现,代码如下:
/**
* led_classdev_register - register a new object of LED class
* @parent: LED controller device this LED is driven by
* @led_cdev: the led_classdev structure for this device
*
* Register a new object of LED class, with name derived from the name property
* of passed led_cdev argument.
*
* Returns: 0 on success or negative error value on failure
*/
static inline int led_classdev_register(struct device *parent,
struct led_classdev *led_cdev)
{
return led_classdev_register_ext(parent, led_cdev, NULL);
}
led_classdev_register_ext函数在drivers/leds/led-class.c中,代码较长,内容和知识点较多,放到下一篇文章中详述。