這里說一說LED子系統(tǒng)的一些核心源代碼文件,是如何實(shí)現(xiàn)LED子系統(tǒng)。
這里重點(diǎn)關(guān)注內(nèi)核部分的實(shí)現(xiàn):
對(duì)于內(nèi)核中需要重點(diǎn)關(guān)注的幾個(gè)文件如下:
driver/leds/led-class.c
driver/leds/led-core.c
driver/leds/led-triggers.c
include/linux/leds.h
1. LED設(shè)備管理
driver/leds/led-class.c
LED設(shè)備的注冊(cè)和注銷實(shí)現(xiàn)都在該函數(shù),這里看看里面的重要結(jié)構(gòu)體
struct led_classdev {
const char *name;
enum led_brightness brightness;
enum led_brightness max_brightness;
int flags;
/* Lower 16 bits reflect status */
#define LED_SUSPENDED BIT(0)
#define LED_UNREGISTERING BIT(1)
/* Upper 16 bits reflect control information */
#define LED_CORE_SUSPENDRESUME BIT(16)
#define LED_SYSFS_DISABLE BIT(17)
#define LED_DEV_CAP_FLASH BIT(18)
#define LED_HW_PLUGGABLE BIT(19)
#define LED_PANIC_INDICATOR BIT(20)
#define LED_BRIGHT_HW_CHANGED BIT(21)
#define LED_RETAIN_AT_SHUTDOWN BIT(22)
#define LED_INIT_DEFAULT_TRIGGER BIT(23)
/* set_brightness_work / blink_timer flags, atomic, private. */
unsigned long work_flags;
#define LED_BLINK_SW 0
#define LED_BLINK_ONESHOT 1
#define LED_BLINK_ONESHOT_STOP 2
#define LED_BLINK_INVERT 3
#define LED_BLINK_BRIGHTNESS_CHANGE 4
#define LED_BLINK_DISABLE 5
/* Set LED brightness level
* Must not sleep. Use brightness_set_blocking for drivers
* that can sleep while setting brightness.
*/
void (*brightness_set)(struct led_classdev *led_cdev,
enum led_brightness brightness);
/*
* Set LED brightness level immediately - it can block the caller for
* the time required for accessing a LED device register.
*/
int (*brightness_set_blocking)(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, delays are in milliseconds
* and if both are zero then a sensible default should be chosen.
* and if both are zero then a sensible default should be chosen.
* The call should adjust the timings in that case and if it can't
* match the values specified exactly.
* Deactivate blinking again when the brightness is set to LED_OFF
* via the brightness_set() callback.
*/
int (*blink_set)(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off);
int (*pattern_set)(struct led_classdev *led_cdev,
struct led_pattern *pattern, u32 len, int repeat);
int (*pattern_clear)(struct led_classdev *led_cdev);
struct device *dev;
const struct attribute_group **groups;
struct list_head node; /* LED Device list */
const char *default_trigger; /* Trigger to use */
unsigned long blink_delay_on, blink_delay_off;
struct timer_list blink_timer;
int blink_brightness;
int new_blink_brightness;
void (*flash_resume)(struct led_classdev *led_cdev);
struct work_struct set_brightness_work;
int delayed_set_value;
#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;
/* true if activated - deactivate routine uses it to do cleanup */
bool activated;
/* LEDs that have private triggers have this set */
struct led_hw_trigger_type *trigger_type;
#endif
#ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED
int brightness_hw_changed;
struct kernfs_node *brightness_hw_changed_kn;
#endif
/* Ensures consistent access to the LED Flash Class device */
struct mutex led_access;
};
從結(jié)構(gòu)里面可以看到已經(jīng)定義了LED設(shè)備的屬性和操作函數(shù),包括設(shè)備的名稱,LED的亮度,max 等,設(shè)置與獲取亮度函數(shù);
重要字段:
- name:設(shè)備名稱,用于在/sys/class/leds/目錄下創(chuàng)建設(shè)備子目錄。
- brightness:表示LED設(shè)備的亮度,可以通過讀寫
/sys/class/leds//brightness文件進(jìn)行控制。 - max_brightness:LED設(shè)備的最大亮度值。
- trigger:表示LED設(shè)備當(dāng)前的觸發(fā)器名稱,可以通過讀寫
/sys/class/leds//trigger文件進(jìn)行控制。 - triggers:指向LED設(shè)備可用觸發(fā)器的鏈表。
LED框架初始化
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- >pm = &leds_class_dev_pm_ops;
leds_class- >dev_groups = led_groups;
return 0;
}
它創(chuàng)建了一個(gè)名為"leds"的設(shè)備類,并設(shè)置了與電源管理相關(guān)的操作函數(shù)和設(shè)備屬性組。通過這個(gè)初始化過程,LED設(shè)備驅(qū)動(dòng)程序可以注冊(cè)到該設(shè)備類,并與LED子系統(tǒng)進(jìn)行交互。
LED 設(shè)備注冊(cè)和注銷
int led_classdev_register_ext(struct device *parent,
struct led_classdev *led_cdev,
struct led_init_data *init_data)
這個(gè)函數(shù)在將可以提供外部其他文件使用
led_classdev_unregister()函數(shù)用于注銷一個(gè)已注冊(cè)的LED設(shè)備
2. LED核心功能
driver/leds/led-core.c
LED 設(shè)備注冊(cè)和管理:led-core.c 提供了函數(shù)和數(shù)據(jù)結(jié)構(gòu),用于注冊(cè)和管理 LED 設(shè)備。它定義了 struct led_classdev 結(jié)構(gòu)體,用于表示一個(gè) LED 設(shè)備的屬性和操作函數(shù)。通過使用 led_classdev_register() 函數(shù),可以將一個(gè) LED 設(shè)備注冊(cè)到 LED 子系統(tǒng),并將其添加到 sysfs 文件系統(tǒng)中的 /sys/class/leds/ 目錄下。
觸發(fā)器管理:led-core.c 還實(shí)現(xiàn)了 LED 觸發(fā)器的注冊(cè)和管理。觸發(fā)器是一種機(jī)制,根據(jù)不同的條件或事件改變 LED 的狀態(tài)。通過使用 led_trigger_register() 函數(shù),可以將一個(gè) LED 觸發(fā)器注冊(cè)到 LED 子系統(tǒng),并將其添加到 sysfs 文件系統(tǒng)中的 /sys/class/leds/ 目錄下的觸發(fā)器文件中。
電源管理:LED 子系統(tǒng)還提供了電源管理的支持。led-core.c 定義了與電源管理相關(guān)的操作函數(shù),并將這些操作函數(shù)與設(shè)備類結(jié)構(gòu)體中的 pm 字段關(guān)聯(lián)起來。通過使用 led_classdev_register() 函數(shù)時(shí),可以將 pm 字段設(shè)置為相應(yīng)的電源管理操作函數(shù),以實(shí)現(xiàn)對(duì) LED 設(shè)備的電源管理。
屬性和操作的支持:led-core.c 提供了用于處理 LED 設(shè)備屬性和操作的函數(shù)。例如,它實(shí)現(xiàn)了與 LED 亮度相關(guān)的操作函數(shù),以便從用戶空間調(diào)整 LED 的亮度。
3. LED觸發(fā)器管理
driver/leds/led-trigger.c
觸發(fā)器注冊(cè)和管理:led-trigger.c 提供了函數(shù)和數(shù)據(jù)結(jié)構(gòu),用于注冊(cè)和管理 LED 觸發(fā)器。它定義了 struct led_trigger 結(jié)構(gòu)體,用于表示一個(gè) LED 觸發(fā)器的屬性和操作函數(shù)。通過使用 led_trigger_register() 函數(shù),可以將一個(gè) LED 觸發(fā)器注冊(cè)到 LED 子系統(tǒng),并將其添加到 sysfs 文件系統(tǒng)中的 /sys/class/leds/ 目錄下的觸發(fā)器文件中。
觸發(fā)器操作:led-trigger.c 實(shí)現(xiàn)了與 LED 觸發(fā)器相關(guān)的操作函數(shù)。這些操作函數(shù)包括觸發(fā)器的啟用、禁用、觸發(fā)等操作。通過這些操作函數(shù),用戶可以與 LED 觸發(fā)器進(jìn)行交互,并控制觸發(fā)器的行為。
內(nèi)置觸發(fā)器:led-trigger.c 還實(shí)現(xiàn)了一些內(nèi)置的 LED 觸發(fā)器。這些觸發(fā)器根據(jù)不同的條件或事件改變 LED 的狀態(tài)。例如,timer 觸發(fā)器以指定的時(shí)間間隔來閃爍。
struct led_trigger {
/* Trigger Properties */
const char *name;
int (*activate)(struct led_classdev *led_cdev);
void (*deactivate)(struct led_classdev *led_cdev);
/* LED-private triggers have this set */
struct led_hw_trigger_type *trigger_type;
/* 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;
const struct attribute_group **groups;
};
trigger 等于是led處于某種模式,可以閃爍,可以實(shí)現(xiàn)具體的一個(gè)什么實(shí)物的LED,比如呼吸道,音頻LED等等;
4. 總結(jié)
評(píng)論