leds子系统-上

来源:互联网 发布:淘宝怎么帮别人代付 编辑:程序博客网 时间:2024/05/17 08:53

(本文内容涉及的代码全部取自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,可是实现定时、亮度调整等功能。



原创粉丝点击