Linux Device Model-led Subsystem

Source: Internet
Author: User

The times are different, and even LEDs have become sub-systems. I have analyzed the general model provided by the kernel and haven't written an article for a long time!

The code is located in drivers/leds. Let's take a look at the Makefile model file:


# LED Core


Obj-$ (CONFIG_NEW_LEDS) + = led-core.o

Obj-$ (CONFIG_LEDS_CLASS) + = led-class.o

Obj-$ (CONFIG_LEDS_TRIGGERS) + = led-triggers.o

Let's look at the led-core file. This file is extremely personalized and contains four lines of subject content.

DECLARE_RWSEM (leds_list_lock );
EXPORT_SYMBOL_GPL (leds_list_lock );
LIST_HEAD (leds_list); // link the global linked list of all LEDs
EXPORT_SYMBOL_GPL (leds_list );


Let's take a look at the led-class.c function. Here we will first introduce the core structure of the led.

Struct led_classdev {
Const char * name; // name
Int brightness; // The brightness value, which can also be used to indicate the switching feature.
Int max_brightness; // maximum allowed Brightness Value
Int flags; // flag

/* Lower 16 bits reflect status */
# Define led_suincluded (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, // core callback function. When you set the brightness attribute file in the led interface under/sys/class/leds, calls back this function.
Enum led_brightness brightness );
/* Get LED brightness level */
Enum led_brightness (* brightness_get) (struct led_classdev * led_cdev); // core callback function, called when the current value of the led is obtained

/* Activate hardware accelerated blink, delays are in
* Miliseconds and if none is provided then a sensible default
* Shocould be chosen. The call can adjust the timings if it cant
* Match the values specified exactly .*/
Int (* blink_set) (struct led_classdev * led_cdev,
Unsigned long * delay_on,
Unsigned long * delay_off );

Struct device * dev; // embedded Standard device Model
Struct list_head node;/* LED Device list * // The mount point of the global led Device mentioned above
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
};

 


Now let's talk about the initialization function:

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-> suspend = led_suspend;
Leds_class-> resume = led_resume;
Leds_class-> dev_attrs = led_class_attrs; // attribute file, interface under sys. Take a closer look.
Return 0;
}

The function generates the leds sub-directory under the/sys/class directory. All devices registered according to the led model will appear in this directory.

Static struct device_attribute led_class_attrs [] = {
_ ATTR (brightness, 0644, led_brightness_show, led_brightness_store ),
_ ATTR (max_brightness, 0644, led_max_brightness_show,
Led_max_brightness_store ),
# Ifdef CONFIG_LEDS_TRIGGERS
_ ATTR (trigger, 0644, led_trigger_show, led_trigger_store ),
# Endif
_ ATTR_NULL,

};

It can be seen that the general setting function of the attribute function is led_brightness_store, and the function bit led_brightness_show is obtained, which is similar to the following:

Static ssize_t led_brightness_store (struct device * dev,
Struct device_attribute * attr, const char * buf, size_t size)
{
Struct led_classdev * led_cdev = dev_get_drvdata (dev); // obtain the led device information
Ssize_t ret =-EINVAL;
Char * after;
Unsigned long state = simple_strtoul (buf, & after, 10 );
Size_t count = after-buf;

If (isspace (* after ))
Count ++;

If (count = size ){
Ret = count;

If (state = LED_OFF)
Led_trigger_remove (led_cdev );
Led_set_brightness (led_cdev, state );
}

Return ret;

}

Follow up on the led_set_brightness function:

Static inline void led_set_brightness (struct led_classdev * led_cdev,
Enum led_brightness value)
{
If (value> led_cdev-> max_brightness)
Value = led_cdev-> max_brightness;
Led_cdev-> brightness = value;
If (! (Led_cdev-> flags & led_susponded )){
# Ifdef CONFIG_HAS_EARLYSUSPEND
If (queue_brightness_change (led_cdev, value )! = 0)
# Endif
Led_cdev-> brightness_set (led_cdev, value );
}
}

It can be seen that it is indeed the callback led_cdev-> brightness_set to complete the setting of this attribute.

Let's take a look at the interface left for us and register the function:

Int led_classdev_register (struct device * parent, struct led_classdev * led_cdev)
{
Led_cdev-> dev = device_create (leds_class, parent, 0, led_cdev,
"% S", led_cdev-> name); // generate directory items for this device under the leds directory
If (IS_ERR (led_cdev-> dev ))
Return PTR_ERR (led_cdev-> dev );

# 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); // Add the device to the global linked list.
Up_write (& leds_list_lock );

If (! Led_cdev-> max_brightness)
Led_cdev-> max_brightness = LED_FULL; // if the maximum value is not set, set it to 255.

Led_update_brightness (led_cdev );

# Ifdef CONFIG_LEDS_TRIGGERS
Led_trigger_set_default (led_cdev );
# Endif

Printk (KERN_DEBUG "Registered led device: % s ",
Led_cdev-> name );

Return 0;
}
Summary: The led sub-system is briefly analyzed. The code is not much and it is easy to see. The probe function of the main end should be configured with the I/O port function, and the led_cdev function should be filled in, then you can register ^. ^ ~


 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.