/
1:有两个主要结构:
struct led_classdev,
struct
led_trigger,(其实就是sysfs,class文件中的一个属性?)
2:全局结构:
(系统核心结构)
LIST_HEAD(leds_list); 所有的led设备。
static
LIST_HEAD(trigger_list); 所有的trigger成员链表。
DECLARE_RWSEM(leds_list_lock);
3:
led
子系统实现(class):
生成系统全局类变
量:
static struct class
*leds_class;
提供
led_classdev注册,注销函数
设置
led的设备属性文件:(brightness与 trigger)
static DEVICE_ATTR(brightness, 0644, led_brightness_show,
led_brightness_store);
#ifdef
CONFIG_LEDS_TRIGGERS
static
DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
#endif
led子系统实现(trigger)
提供注册,注销trigger函数,即在全局变量(trigger_list)
上的操作。及属性操作函数:led_trigger_show, led_trigger_store
4:led_trigger
注册过程:
添加到全局链表中,同时遍历全局leds_list,设置以这个trigger为trigger的led.
5:led_classdev
注册过程:
生成sysfs文件,(关联trigger)设置trigger,添加到leds_list中
int
led_classdev_register(struct device *parent, struct led_classdev
*led_cdev)
{
int
rc;
led_cdev->dev
= device_create(leds_class, parent, 0, led_cdev,
"%s", led_cdev->name);
if (IS_ERR(led_cdev->dev))
return PTR_ERR(led_cdev->dev);
/* register the attributes */
rc =
device_create_file(led_cdev->dev, &dev_attr_brightness);
if (rc)
goto err_out;
#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);
led_update_brightness(led_cdev);
#ifdef
CONFIG_LEDS_TRIGGERS
rc
= device_create_file(led_cdev->dev, &dev_attr_trigger);
if (rc)
goto err_out_led_list;
led_trigger_set_default(led_cdev);
#endif
printk(KERN_INFO "Registered led
device: %s\n",
led_cdev->name);
return 0;
#ifdef
CONFIG_LEDS_TRIGGERS
err_out_led_list:
device_remove_file(led_cdev->dev,
&dev_attr_brightness);
list_del(&led_cdev->node);
#endif
err_out:
device_unregister(led_cdev->dev);
return rc;
}
6:
led_classdev与 led_trigger的关联。
在设置led platformdata时,就设置好对应的
led_trigger。(char * name)
向系统注册led_trigger:
在另外的包含这个
trigger的模块的 module_init中向系统注册。 led_trigger_register_simple("nand-disk",
&nand_led_trigger);
//********************
控制led
struct led_trigger {
/* Trigger Properties */
const char *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;
struct list_head led_cdevs;
/* Link to next registered trigger */
struct list_head next_trig;
};
//************************
表示led的class:
struct led_classdev {
const char *name;
int 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)(struct led_classdev
*led_cdev,
enum
led_brightness brightness);
/*
Get LED brightness level */
enum
led_brightness (*brightness_get)(struct led_classdev *led_cdev);
/* Activate hardware accelerated
blink */
int (*blink_set)(struct led_classdev
*led_cdev,
unsigned long *delay_on,
unsigned long *delay_off);
struct device *dev;
struct
list_head node; /* LED Device list */
const char *default_trigger; /*
Trigger to use */
#ifdef CONFIG_LEDS_TRIGGERS
/* Protects the trigger data
below */
struct
rw_semaphore trigger_lock;
struct led_trigger *trigger;
struct list_head trig_list;
void *trigger_data;
#endif
};
转自:http://lhsblog01.blog.163.com/blog/static/1020045192010221103155591/