leds子系统-上

本文详细介绍了Linux内核2.6.36版本中的LED子系统,包括led_classdev结构体,led触发器(led_trigger)结构,以及gpio_led平台数据结构。LED子系统的初始化、注册与注销过程也进行了讲解,重点关注了led_classdev_register和led_classdev_unregister函数。此外,文中还提及了LED触发器的概念,分为简单和复杂两种类型,用于控制LED事件的来源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(本文内容涉及的代码全部取自linux-2.6.36内核中)

 

Leds子系统

介绍leds子系统之前,先从几个相关的重要结构开始介绍:

led_classdev是比较重要的一个struct,它实现的是led实例,源程序中的注释比较全面,所有没有再另外添加,免得画蛇添足。

 

include/linux/leds.h(line30-line68)

 

struct led_classdev {

       constchar            *name;

       int                 brightness;

       int                 max_brightness;

       int                 flags;

 

       /*Lower 16 bits reflect status */

#define LED_SUSPENDED          (1 << 0)

       /*Upper 16 bits reflect control information */

#define LED_CORE_SUSPENDRESUME     (1 << 16)

 

       /*Set LED brightness level */

       /*Must not sleep, use a workqueue if needed */

       void              (*brightness_set)(structled_classdev *led_cdev,

                                     enum led_brightness brightness);

       /*Get LED brightness level */

       enumled_brightness (*brightness_get)(struct led_classdev *led_cdev);

 

       /*Activate hardware accelerated blink, delays are in

        * miliseconds and if none is provided then asensible default

        * should be chosen. The call can adjust thetimings if it can't

        * match the values specified exactly. */

       int          (*blink_set)(struct led_classdev*led_cdev,

                                 unsigned long *delay_on,

                                 unsigned long *delay_off);

 

       structdevice              *dev;

       structlist_head   node;                 /* LED Device list */

       constchar            *default_trigger;  /* Trigger to use */

 

#ifdef CONFIG_LEDS_TRIGGERS

       /*Protects the trigger data below */

       structrw_semaphore  trigger_lock;

 

       structled_trigger *trigger;

       structlist_head   trig_list;

       void                     *trigger_data;

#endif

};

 

include/linux/leds.h(line83-line95)

 

struct led_trigger {

       /*Trigger Properties */

       constchar     *name;

       void              (*activate)(struct led_classdev*led_cdev);

       void              (*deactivate)(struct led_classdev*led_cdev);

 

       /*LEDs under control by this trigger (for simple triggers) */

       rwlock_t  leddev_list_lock;

       structlist_head  led_cdevs;

 

       /*Link to next registered trigger */

       structlist_head  next_trig;

};

 

平台设备相关的gpio led数据结构,这些结构在设备文件中定义led设备时会用到。

 

include/linux/leds.h(line137-line168)

 

struct led_platform_data {

       int          num_leds;

       structled_info     *leds;

};

 

/* For the leds-gpio driver */

struct gpio_led {

       constchar *name;

       constchar *default_trigger;

       unsigned     gpio;

       unsigned       active_low : 1;

       unsigned       retain_state_suspended : 1;

       unsigned       default_state : 2;

       /*default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */

};

 

#define LEDS_GPIO_DEFSTATE_OFF        0

#define LEDS_GPIO_DEFSTATE_ON          1

#define LEDS_GPIO_DEFSTATE_KEEP             2

 

struct gpio_led_platform_data {

       int        num_leds;

       structgpio_led *leds;

 

#define GPIO_LED_NO_BLINK_LOW  0     /*No blink GPIO state low */

#define GPIO_LED_NO_BLINK_HIGH 1     /*No blink GPIO state high */

#define GPIO_LED_BLINK          2     /*Plase, blink */

       int          (*gpio_blink_set)(unsigned gpio, intstate,

                                   unsignedlong *delay_on,

                                   unsignedlong *delay_off);

};

 

Led子系统的实现

1.  Led子系统的初始化与注销

 

/drivers/leds/led-class.c(line186-line203)

 

static int __init leds_init(void)

{

       leds_class= class_create(THIS_MODULE, "leds");

       if(IS_ERR(leds_class))

              returnPTR_ERR(leds_class);

       leds_class->suspend= led_suspend;       //将led的flag设为LED_SUSPENDED,关闭led

       leds_class->resume= led_resume;          //从挂起中恢复

       leds_class->dev_attrs= led_class_attrs;         //led设备的属性

       return0;

}

 

static void __exit leds_exit(void)

{

       class_destroy(leds_class);

}

 

subsys_initcall(leds_init);

module_exit(leds_exit);

 

在leds_init中初始化和注销了一个结构

static struct class *leds_class;

leds_init实现了led设备的挂起、恢复以及对应属性的初始化,最后会根据设置属性在/sys/class/leds目录下创建两类设备文件:led_brightness_show和led_brightness_store分别负责显示和设置亮度。

但是leds_init并没有对实际的注册和注销操作进行定义,接下来要了解的就是led_classdev_register和led_classdev_unregister两个led注册与注销接口函数。

 

这里面要特别注意的部分是初始化使用的不是module_init而是subsys_initcall,就因为这个内容的改变,导致介绍完led子系统后,还要追加gpio_led的操作,呵呵。。。

 

注册led-properties类对象

/drivers/leds/led-class.c(line126-line159)

 

/**

 *led_classdev_register - register a new object of led_classdev class.

 *@parent: The device to register.

 *@led_cdev: the led_classdev structure for this device.

 */

int led_classdev_register(struct device*parent, struct led_classdev *led_cdev)

{

/* 创建一个struct device并且注册了sysfs,生成/sys/class/leds目录,他的父设备是parent,drvdata是led_cdev,名字是led_cdev->name,类别是 leds_class*/

 

       led_cdev->dev= device_create(leds_class, parent, 0, led_cdev,

                                  "%s", led_cdev->name);

       if(IS_ERR(led_cdev->dev))

              returnPTR_ERR(led_cdev->dev);

 

/*初始化一个trigger的锁*/

#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);

 

#ifdef CONFIG_LEDS_TRIGGERS

       led_trigger_set_default(led_cdev);

#endif

 

       printk(KERN_DEBUG"Registered led device: %s\n",

                     led_cdev->name);

 

       return0;

}

 

注销一个led_properties类对象,与注册相反

 

/drivers/leds/led-class.c(line169-line183)

 

void led_classdev_unregister(structled_classdev *led_cdev)

 

对于trigger的设备使用方法在/driver/leds/led-triggers.c内有全部的定义,没有进行详细的描述。这里只总结一下摘引Documentation/leds-class.txt中的两段文字:

Theclass also introduces the optional concept of an LED trigger. A trigger

isa kernel based source of led events. Triggers can either be simple or

complex.A simple trigger isn't configurable and is designed to slot into

existingsubsystems with minimal additional code. Examples are the ide-disk,

nand-diskand sharpsl-charge triggers. With led triggers disabled, the code

optimisesaway.

 

Complextriggers whilst available to all LEDs have LED specific

parametersand work on a per LED basis. The timer trigger is an example.

Thetimer trigger will periodically change the LED brightness between

LED_OFFand the current brightness setting. The "on" and "off" timecan

bespecified via /sys/class/leds/<device>/delay_{on,off} in milliseconds.

Youcan change the brightness value of a LED independently of the timer

trigger.However, if you set the brightness value to LED_OFF it will

alsodisable the timer trigger.

 

Trigger是led的一种操作机制,simple trigger不能配置,实现例如硬盘指示灯闪烁等功能;Complextriggers是可配置功能,既可以单独控制led也可以控制所有led,可是实现定时、亮度调整等功能。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值