android 使用 linux LED driver 來控制GPIO 的LED行為

Linux Kernel’s LED driver
一般embedded system廠商控制LED都是透過GPIO的high/low操作
所以不會使用linux kernel內的預設LED功能, 而是自己寫獨立的driver
但是因為正統方式應該要配合Linux Kernel會比較有系統
kernel/drivers/leds


先到kernel作make menuconfig
將LED功能打開

+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_GPIO_PLATFORM=y
+CONFIG_LEDS_TRIGGERS=y


去kernel/driver/led底下
作出客製化的修改

Makefile

# LED Platform Drivers
+#++
+obj-y += leds-xxxx.o
+#–

從led-gpio.c 改寫成另一份檔案 led-xxxx.c

1: 可以改寫 led_dat->platform_gpio_blink_set = blink_set;
2: 改寫 gpio_led_work()
反正就是接到led的driver的API, 如led_on(), led_off()

Access介面node:

ledtrig-timer.c:78: static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);

順便提到, led-class: always implement blinking

在2010年時候, kernel/driver/leds
Johannes Berg 新增一個功能 led-class: always implement blinking
led-class: always implement blinking


Currently, blinking LEDs can be awkward because it is not guaranteed that
all LEDs implement blinking. The trigger that wants it to blink then
needs to implement its own timer solution.

Rather than require that, add led_blink_set() API that triggers can use.
This function will attempt to use hw blinking, but if that fails
implements a timer for it. To stop blinking again, brightness_set() also
needs to be wrapped into API that will stop the software blink.

As a result of this, the timer trigger becomes a very trivial one, and
hopefully we can finally see triggers using blinking as well because it’s
always easy to use.

Signed-off-by: Johannes Berg
Acked-by: Richard Purdie
Signed-off-by: Andrew Morton
Signed-off-by: Linus Torvalds

這是近年來 kernel/driver/leds 比較大的修改


如何注册gpio-led平台设备:
(如果是android系統, 應該是寫在 kernel/arch/arm/mach-tegra/board-xxxxx.c)

例子如下:
#define GPIO_LED3 138
#define GPIO_LED4 139

static struct gpio_led gpio_leds[] = {
{
.name = “led3”,
.default_trigger = “heartbeat”,
.gpio = GPIO_LED3,
.active_low = 1,
.default_state = LEDS_GPIO_DEFSTATE_OFF,
},
{
.name = “led4”,
.gpio = GPIO_LED4,
.active_low = 1,
.default_state = LEDS_GPIO_DEFSTATE_OFF,
},
};

static struct gpio_led_platform_data gpio_led_info = {
.leds = gpio_leds,
.num_leds = ARRAY_SIZE(gpio_leds),
};

static struct platform_device leds_gpio = {
.name = “leds-gpio”,
.id = -1,
.dev = {
.platform_data = &gpio_led_info,
},
};
最后调用platform_device_register(&leds_gpio)将LED设备注册到内核中。注册之前一定要保证编号为138和139的两个端口是可用的。
成功注册之后,系统中便会出现名为led3和led4的两个led_classdev了。由于是用gpio模拟led,所以对gpio-led设置的亮度,只要不是0就是全亮(gpio只有两个状态)。
对于可能睡眠的gpio,gpio-led会借助于工作队列去设置亮度,所以不用担心会被阻塞。


做完了以上的kernel部分
想要往上讓android系統可以控制光的話, 要使用android光系統

修改:
device/nvidia/common/liblights/lights.c 裡面的
open_lights() 和改寫 set_light_backlight()變成控制LED

修改:
frameworks/base/services/java/com/android/server/BatteryService.java 裡面的
updateLightsLocked()


參考:
led子系统
http://blog.csdn.net/yuanlulu/article/details/6438841

内核中led触发器实例
http://blog.csdn.net/yuanlulu/article/details/6438847