Just like learning to program the first example HelloWorld, learning embedded, microcontroller, FPGA and the like the first example is to light a lamp. For a large Linux system, of course, you can write a character device driver to achieve the LED lights we need, or you can directly use the Gpio port, the application to pull the high pull low pin control. However, since the Linux system itself has led subsystems, then you can make good use of it. Benefits Needless to say, mainly for the application layer, the different platforms are using the Linux LED subsystem, then the application does not make any changes, you can run on the new platform, portability is good.
Linux LED subsystem source code path:
- Include/linux/leds.h//Header file
- Drivers/leds//led subsystem related source code and API
First look at the main files in the LED subsystem:
- # LED Core
- obj-$ (config_new_leds) +=LED-CORE.O
- obj-$ (config_leds_class) + = LED-CLASS.O
- obj-$ (config_leds_triggers) +=LED-TRIGGERS.O
- # LED Platformdrivers
- obj-$ (config_leds_gpio) + = LEDS-GPIO.O
- # LED Triggers
- obj-$ (Config_leds_trigger_timer) +=ledtrig-timer.o
- obj-$ (Config_leds_trigger_ide_disk) +=LEDTRIG-IDE-DISK.O
- obj-$ (config_leds_trigger_heartbeat) +=LEDTRIG-HEARTBEAT.O
- obj-$ (config_leds_trigger_backlight) +=LEDTRIG-BACKLIGHT.O
- obj-$ (Config_leds_trigger_gpio) +=ledtrig-gpio.o
- obj-$ (config_leds_trigger_default_on) + = LEDTRIG-DEFAULT-ON.O
Mainly by Leds.h, led-core.c, LED-CLASS.C, LED-TRIGGERS.C, of which led-triggers is divided into a timer, Ide-disk, heartbeat, backlight, GPIO, Default-on and other algorithms.
The example program is Leds-gpio, and then the main analysis of this driver implementation.
First, take a quick look at the main file
Leds.h
Led brightness, divided into three levels, off, in the middle, the brightest.
Enum Led_brightness {
Led_off = 0,//Full Dark
Led_half = 127,//half brightness
Led_full = 255,//maximum brightness
};
struct Led_classdev {
const char *name; LED name
int brightness; Current brightness
int max_brightness;//reference value, maximum brightness
int flags; Logo, currently only supports led_suspended and Led_core_suspendresume
/* Lower bits reflect status */
#define LED_SUSPENDED (1 << 0)
/* Upper bits reflect control information */
#define LED_CORE_SUSPENDRESUME (1 << 16)
/* Set LED brightness level */
/* Must not sleep, use a workqueue if needed */
The core callback function, when setting the brightness (Brightness) property file in the LED interface under/sys/class/leds/, will call back the function
void (*brightness_set) (struct Led_classdev *led_cdev,
enum led_brightness brightness); Brightness setting function pointer
/* Get LED brightness level */
The core callback function is called when the current luminance value of the LED is obtained.
Enum Led_brightness (*brightness_get) (struct Led_classdev *led_cdev);//Get Brightness function pointer
/*
* Activate hardware accelerated blink, delays is in milliseconds
* And if both is zero then a sensible default should is chosen.
* The call should adjust the timings in this case and if it can ' t
* Match the values specified exactly.
* Deactivate blinking again when the brightness are set to a fixed
* Value via the Brightness_set () callback.
*/
/* Activate hardware-accelerated flicker */
Int (*blink_set) (struct Led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off);//flashing time setting for light and off
Embedded Standard device model
struct device *dev;
/* All registered Led_class Dev uses this node to concatenate */
struct List_head node; /* LED Device list *///leds-list node
/* Default Trigger */
const char *default_trigger; /* Trigger to use *///default Trigger name
unsigned long blink_delay_on, Blink_delay_ off; //Flashing switch time
struct timer_list blink _timer; //Flashing timer chain list
int blink_brightness; //flashing brightness
//If the trigger function is enabled when the kernel is configured, the following paragraph will be compiled
#ifdef config_leds_triggers
/* Protects the trigger data below */
struct rw_semaphore & nbsp Trigger_lock; /* This read-write lock protects the following trigger data */
struct Led_trigger *trigger; Trigger pointer
struct List_head trig_list; The list node used by the trigger to connect all Led_classdev on the same trigger
void *trigger_data; Private data used by triggers
#endif
};
struct Led_trigger {
const char *name; Trigger Name
void (*activate) (struct Led_classdev *led_cdev);//This method is called when the Led,led_classdev is activated and the trigger establishes a connection.
void (*deactivate) (struct Led_classdev *led_cdev);//Deactivate. This method is called when the Led_classdev and triggers cancel the connection.
/* LEDs under control by this trigger (for simple triggers) */
/* LED chain list under control of this trigger */
rwlock_t Leddev_list_lock; Protect the chain list lock
struct List_head Led_cdevs; Linked list Header
/* Link to next registered trigger */
struct List_head Next_trig; /* Connect the next registered trigger's linked list node, and all registered triggers will be added to a global list */
};
Platform device-related LED data structures
struct Led_info {
const char *name;
const char *default_trigger;
int flags;
};
struct Led_platform_data {
int num_leds;
struct Led_info *leds;
};
/* For the Leds-gpio driver */
GPIO LED data structures related to platform devices
struct Gpio_led {
const char *name; The name of the LED
const char *default_trigger; The default trigger
unsigned gpio; Gpio Port
unsigned active_low:1;
unsigned retain_state_suspended:1;
unsigned default_state:2;
/* Default_state should be one of the 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; number of//led
const struct gpio_led *leds; //platform device related GPIO LED data structure
#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/* Please, BLINK */
Int (*gpio_blink_set) (unsigned gpio, int state,
unsigned long *delay_on,
unsigned long *delay_off);
};
Led-core.c
The main statement of the LED chain list and lock
Declare_rwsem (Leds_list_lock);
EXPORT_SYMBOL_GPL (Leds_list_lock);
List_head (leds_list);
EXPORT_SYMBOL_GPL (leds_list);
Led-class.c
1, Leds_init
The main is to create Leds_class, assign suspend and resume, and dev_attrs.
Led_class_attrs
A 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,
91};
2, Led_classdev_register
Creating a Classdev device, or instantiating an object in the Leds_class class, similar to the C + + object, has many LEDs, and here is the registration of a particular led, which is extremely rich in object-oriented thinking in the kernel.
Add to the Leds_list list, initialize the Blinktimer, specify Blink_timer function and data, set the trigger, and a new LED device is registered and ready to use.
Led-triggers.c
1, Led_trigger_register
Scan the trigger list for the name of the trigger, and then add the current trigger to the list, if there is a default trigger in Led_classdev, then set this default.
Well, simply look at the more important structure and function in the LED subsystem, then you can further understand the LED subsystem by Leds-gpio this driver.
Linux LED Subsystem (i)