Android led_class driver
2017-06-11 21:13
555 查看
Linux的led class驱动
echo 255 > /sys/class/leds/led1/brightness
cat /sys/class/leds/led1/brightness
cat /sys/class/leds/led1/max_brightness
闪烁
echo timer > /sys/class/leds/led1/trigger
echo 100 > /sys/class/leds/led1/delay_on
echo 200 > /sys/class/leds/led1/delay_off
关闭
echo 0 > /sys/class/leds/led1/delay_on
或
echo 0 > /sys/class/leds/led1/brightness
怎么写驱动:
a1. 分配led_classdev
a2. 设置 :
led_cdev->max_brightness
led_cdev->brightness_set
led_cdev->flags
led_cdev->brightness
led_cdev->name
led_class 子系统简要分析
static int __init leds_init(void)
{
leds_class = class_create(THIS_MODULE, "leds");
if (IS_ERR(leds_class))
return PTR_ERR(leds_class);
leds_class->suspend = led_suspend;
leds_class->resume = led_resume;
leds_class->dev_attrs
= led_class_attrs;
return 0;
}
用户空间 sys 中的接口,可以设置 brightness 、获取最大背光亮度 max_brightness 、使能闪烁 trigger
static struct device_attribute led_class_attrs[] = {
__ATTR(brightness,
0644, led_brightness_show, led_brightness_store),
__ATTR(max_brightness,
0444, led_max_brightness_show, NULL),
#ifdef CONFIG_LEDS_TRIGGERS
__ATTR(trigger,
0644, led_trigger_show, led_trigger_store),
#endif
__ATTR_NULL,
};
设置背光亮度比较简单,会调用到具体的 led_class 设备的 set_brightness 函数
简要分析一下闪烁:
int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
{
led_cdev->dev = device_create(leds_class, parent, 0, led_cdev,
"%s", led_cdev->name);
#ifdef CONFIG_LEDS_TRIGGERS
init_rwsem(&led_cdev->trigger_lock);
#endif
/* add to the list of leds */
down_write(&leds_list_lock);
list_add_tail(&led_cdev->node, &leds_list);
up_write(&leds_list_lock);
if (!led_cdev->max_brightness)
led_cdev->max_brightness = LED_FULL;
led_update_brightness(led_cdev);
init_timer(&led_cdev->blink_timer);
// 注册 led_class 设备时会初始化一个定时器
led_cdev->blink_timer.function
= led_timer_function;
led_cdev->blink_timer.data
= (unsigned long)led_cdev;
#ifdef CONFIG_LEDS_TRIGGERS
led_trigger_set_default(led_cdev);
#endif
return 0;
}
//定时器的功能自然就是为了实现led的闪烁了
static void led_timer_function(unsigned long data)
{
struct led_classdev *led_cdev = (void *)data;
unsigned long brightness;
unsigned long delay;
brightness = led_get_brightness(led_cdev);
if (!brightness) {
/* Time to switch the LED on. */
brightness = led_cdev->blink_brightness;
delay = led_cdev->blink_delay_on;
} else {
/* Store the current brightness value to be able
* to restore it when the delay_off period is over.
*/
led_cdev->blink_brightness = brightness;
brightness = LED_OFF;
delay = led_cdev->blink_delay_off;
}
led_set_brightness(led_cdev, brightness);
mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
}
echo timer > /sys/class/leds/led1/trigger // timer对应 ledtrig-timer.c
led_trigger_store // 1. 从trigger_list找出名为"timer"的trigger
list_for_each_entry(trig,
&trigger_list, next_trig) {
if (!strcmp(trigger_name,
trig->name)) {
// 2. 调用
led_trigger_set(led_cdev,
trig);
// 3. 把trigger放入led_classdev的trig_list链表里
list_add_tail(&led_cdev->trig_list,
&trigger->led_cdevs);
led_cdev->trigger
= trigger;
...
trigger->activate(led_cdev);
// 4.
对于"timer"
timer_trig_activate
//
6. 创建2个文件: delay_on, delay_off
device_create_file
device_create_file
}
}
echo 100 > /sys/class/leds/led1/delay_on
led_delay_on_store
state = simple_strtoul(buf, &after, 10);
led_blink_set // // 让LED闪烁
led_set_software_blink
mod_timer(&led_cdev->blink_timer, jiffies + 1);
led_cdev->blink_delay_on
= state;
echo 200 > /sys/class/leds/led1/delay_off
led_delay_off_store
state = simple_strtoul(buf,
&after, 10);
led_blink_set // 让LED闪烁
led_set_software_blink
mod_timer(&led_cdev->blink_timer, jiffies + 1);
led_cdev->blink_delay_off
= state;
通过 led_class 来实现标准的灯光系统驱动,用户空间可以获取、更新led亮度值,使能led闪烁。
驱动中只需要设置“set_brightness”函数,至于闪烁led子系统使用定时器已经实现。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/leds.h>
struct led_desc {
int gpio;
char *name;
};
static struct led_desc led_gpios[] = {
{EXYNOS4212_GPM4(0), "led1"},
{EXYNOS4212_GPM4(1), "led2"},
{EXYNOS4212_GPM4(2), "led3"},
{EXYNOS4212_GPM4(3), "led4"},
};
struct led_classdev_4412 {
struct led_classdev cdev;
int gpio;
};
static struct led_classdev_4412 *led_devs;
static void brightness_set_4412(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct
led_classdev_4412 *dev = (struct led_classdev_4412 *)led_cdev;
led_cdev->brightness = brightness;
if (brightness != LED_OFF)
gpio_set_value(dev->gpio, 0);
else
gpio_set_value(dev->gpio, 1);
}
static int leds_init(void)
{
int i;
int ret;
/* 1. alloc led_classdev */
led_devs = kzalloc(sizeof(struct led_classdev_4412) * sizeof(led_gpios)/sizeof(led_gpios[0]),
GFP_KERNEL);
if (led_devs == NULL) {
printk("No memory for device\n");
return -ENOMEM;
}
for (i = 0; i < sizeof(led_gpios)/sizeof(led_gpios[0]); i++)
{
s3c_gpio_cfgpin(led_gpios[i].gpio, S3C_GPIO_OUTPUT);
gpio_set_value(led_gpios[i].gpio, 1);
/* 2. set */
led_devs[i].cdev.max_brightness = LED_FULL;
led_devs[i].cdev.brightness_set = brightness_set_4412;
led_devs[i].cdev.flags = LED_CORE_SUSPENDRESUME;
led_devs[i].cdev.brightness = LED_OFF;
led_devs[i].cdev.name = led_gpios[i].name;
//led_devs[i].cdev.default_trigger = "timer";
led_devs[i].gpio = led_gpios[i].gpio;
/* 3. led_classdev_register */
ret = led_classdev_register(NULL, &led_devs[i].cdev);
if (ret) {
i--;
while (i >= 0) {
led_classdev_unregister(&led_devs[i].cdev);
i--;
}
kfree(led_devs);
return -EIO;
}
}
return 0;
}
static void leds_exit(void)
{
int i;
for (i = 0; i < sizeof(led_gpios)/sizeof(led_gpios[0]); i++)
{
led_classdev_unregister(&led_devs[i].cdev);
}
kfree(led_devs);
}
module_init(leds_init);
module_exit(leds_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("www.100ask.net");
echo 255 > /sys/class/leds/led1/brightness
cat /sys/class/leds/led1/brightness
cat /sys/class/leds/led1/max_brightness
闪烁
echo timer > /sys/class/leds/led1/trigger
echo 100 > /sys/class/leds/led1/delay_on
echo 200 > /sys/class/leds/led1/delay_off
关闭
echo 0 > /sys/class/leds/led1/delay_on
或
echo 0 > /sys/class/leds/led1/brightness
怎么写驱动:
a1. 分配led_classdev
a2. 设置 :
led_cdev->max_brightness
led_cdev->brightness_set
led_cdev->flags
led_cdev->brightness
led_cdev->name
led_class 子系统简要分析
static int __init leds_init(void)
{
leds_class = class_create(THIS_MODULE, "leds");
if (IS_ERR(leds_class))
return PTR_ERR(leds_class);
leds_class->suspend = led_suspend;
leds_class->resume = led_resume;
leds_class->dev_attrs
= led_class_attrs;
return 0;
}
用户空间 sys 中的接口,可以设置 brightness 、获取最大背光亮度 max_brightness 、使能闪烁 trigger
static struct device_attribute led_class_attrs[] = {
__ATTR(brightness,
0644, led_brightness_show, led_brightness_store),
__ATTR(max_brightness,
0444, led_max_brightness_show, NULL),
#ifdef CONFIG_LEDS_TRIGGERS
__ATTR(trigger,
0644, led_trigger_show, led_trigger_store),
#endif
__ATTR_NULL,
};
设置背光亮度比较简单,会调用到具体的 led_class 设备的 set_brightness 函数
简要分析一下闪烁:
int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
{
led_cdev->dev = device_create(leds_class, parent, 0, led_cdev,
"%s", led_cdev->name);
#ifdef CONFIG_LEDS_TRIGGERS
init_rwsem(&led_cdev->trigger_lock);
#endif
/* add to the list of leds */
down_write(&leds_list_lock);
list_add_tail(&led_cdev->node, &leds_list);
up_write(&leds_list_lock);
if (!led_cdev->max_brightness)
led_cdev->max_brightness = LED_FULL;
led_update_brightness(led_cdev);
init_timer(&led_cdev->blink_timer);
// 注册 led_class 设备时会初始化一个定时器
led_cdev->blink_timer.function
= led_timer_function;
led_cdev->blink_timer.data
= (unsigned long)led_cdev;
#ifdef CONFIG_LEDS_TRIGGERS
led_trigger_set_default(led_cdev);
#endif
return 0;
}
//定时器的功能自然就是为了实现led的闪烁了
static void led_timer_function(unsigned long data)
{
struct led_classdev *led_cdev = (void *)data;
unsigned long brightness;
unsigned long delay;
brightness = led_get_brightness(led_cdev);
if (!brightness) {
/* Time to switch the LED on. */
brightness = led_cdev->blink_brightness;
delay = led_cdev->blink_delay_on;
} else {
/* Store the current brightness value to be able
* to restore it when the delay_off period is over.
*/
led_cdev->blink_brightness = brightness;
brightness = LED_OFF;
delay = led_cdev->blink_delay_off;
}
led_set_brightness(led_cdev, brightness);
mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
}
echo timer > /sys/class/leds/led1/trigger // timer对应 ledtrig-timer.c
led_trigger_store // 1. 从trigger_list找出名为"timer"的trigger
list_for_each_entry(trig,
&trigger_list, next_trig) {
if (!strcmp(trigger_name,
trig->name)) {
// 2. 调用
led_trigger_set(led_cdev,
trig);
// 3. 把trigger放入led_classdev的trig_list链表里
list_add_tail(&led_cdev->trig_list,
&trigger->led_cdevs);
led_cdev->trigger
= trigger;
...
trigger->activate(led_cdev);
// 4.
对于"timer"
timer_trig_activate
//
6. 创建2个文件: delay_on, delay_off
device_create_file
device_create_file
}
}
echo 100 > /sys/class/leds/led1/delay_on
led_delay_on_store
state = simple_strtoul(buf, &after, 10);
led_blink_set // // 让LED闪烁
led_set_software_blink
mod_timer(&led_cdev->blink_timer, jiffies + 1);
led_cdev->blink_delay_on
= state;
echo 200 > /sys/class/leds/led1/delay_off
led_delay_off_store
state = simple_strtoul(buf,
&after, 10);
led_blink_set // 让LED闪烁
led_set_software_blink
mod_timer(&led_cdev->blink_timer, jiffies + 1);
led_cdev->blink_delay_off
= state;
通过 led_class 来实现标准的灯光系统驱动,用户空间可以获取、更新led亮度值,使能led闪烁。
驱动中只需要设置“set_brightness”函数,至于闪烁led子系统使用定时器已经实现。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/leds.h>
struct led_desc {
int gpio;
char *name;
};
static struct led_desc led_gpios[] = {
{EXYNOS4212_GPM4(0), "led1"},
{EXYNOS4212_GPM4(1), "led2"},
{EXYNOS4212_GPM4(2), "led3"},
{EXYNOS4212_GPM4(3), "led4"},
};
struct led_classdev_4412 {
struct led_classdev cdev;
int gpio;
};
static struct led_classdev_4412 *led_devs;
static void brightness_set_4412(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct
led_classdev_4412 *dev = (struct led_classdev_4412 *)led_cdev;
led_cdev->brightness = brightness;
if (brightness != LED_OFF)
gpio_set_value(dev->gpio, 0);
else
gpio_set_value(dev->gpio, 1);
}
static int leds_init(void)
{
int i;
int ret;
/* 1. alloc led_classdev */
led_devs = kzalloc(sizeof(struct led_classdev_4412) * sizeof(led_gpios)/sizeof(led_gpios[0]),
GFP_KERNEL);
if (led_devs == NULL) {
printk("No memory for device\n");
return -ENOMEM;
}
for (i = 0; i < sizeof(led_gpios)/sizeof(led_gpios[0]); i++)
{
s3c_gpio_cfgpin(led_gpios[i].gpio, S3C_GPIO_OUTPUT);
gpio_set_value(led_gpios[i].gpio, 1);
/* 2. set */
led_devs[i].cdev.max_brightness = LED_FULL;
led_devs[i].cdev.brightness_set = brightness_set_4412;
led_devs[i].cdev.flags = LED_CORE_SUSPENDRESUME;
led_devs[i].cdev.brightness = LED_OFF;
led_devs[i].cdev.name = led_gpios[i].name;
//led_devs[i].cdev.default_trigger = "timer";
led_devs[i].gpio = led_gpios[i].gpio;
/* 3. led_classdev_register */
ret = led_classdev_register(NULL, &led_devs[i].cdev);
if (ret) {
i--;
while (i >= 0) {
led_classdev_unregister(&led_devs[i].cdev);
i--;
}
kfree(led_devs);
return -EIO;
}
}
return 0;
}
static void leds_exit(void)
{
int i;
for (i = 0; i < sizeof(led_gpios)/sizeof(led_gpios[0]); i++)
{
led_classdev_unregister(&led_devs[i].cdev);
}
kfree(led_devs);
}
module_init(leds_init);
module_exit(leds_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("www.100ask.net");
相关文章推荐
- MTK Android Driver:led
- Android led_class Led驱动
- Android屏幕、键盘背光Framework和Linux led_classdev
- MTK Android Driver:led
- java.lang.ClassNotFoundException: org.gjt.mm.mysql.Driver
- 浅析COleDispatchDriver Class(Ole发布驱动类)
- 关于Class.forName(driverName).newInstance();
- Weblogic 8 & 9中设置JDBC Driver ClassPath
- Class Driver & MiniDriver Definition
- java解惑:Class.forName(String driverClassName)载入JDBC驱动程序的幕后。
- 解决Cannot create JDBC driver of class '' for connect URL 'null'
- Cannot create JDBC driver of class
- eclipse 连接 sqlserver2005错误信息:"java.lang.ClassNotFoundException: com.microsoft.jdbc.sqlserver.SQLServerDriver"
- Tomcat + SQL Server 2005 + jsp : ClassNotFoundException:com.microsoft.sqlserver.jdbc.SQLServerDriver 问题的解决
- Cannot load JDBC driver class 'oracle.jdbc.drive
- Cannot create JDBC driver of class '' for connect URL 'null'解决方法2——对我有效
- Cannot create JDBC driver of class '' for connect URL 'null'
- USB Mass Storage Class Driver (SCSI, SFF-8070i, ATAPI, RBC Command Sets)
- 关于 Cannot create JDBC driver of class '' for connect URL 'null' 的异常
- 使用TOMCAT5.5连接池连接mysql(解决Cannot create JDBC driver of class '' for connect URL 'null' 及can not load org.gjt.mm.mysql.Driver)