LED子系統剖析

寫以前,先看一張圖:數據結構

上次說了LED驅動程序,Linux自身也攜帶了LED驅動,且是脫離平臺的,即LED子系統.操做起來十分簡單.可是它的實質卻不是那麼容易,研究了一個晚上,終於明白了其中一個文件的功能啦,機led-class.c文件.如今分享一下.函數

其實LED的驅動位於內核driver/leds目錄下.核心文件有:led-class.c leds-s3c24xx.c、leds-gpio.c .先看其中一個文件 led-core.c文件.spa

一看就知道和類class脫不了關係.class有何做用呢?首先何所謂類呢?就是一組設備具備共同性而抽象出來的.其實leds-gpio.c和leds-s3c24xx.c功能都是差很少,二者是並列的,他們都共有的功能是在class裏面實現的.在led-class.c文件實現的功能總的來講就是先創建一個類leds,而後在該類下創建一個設備節點,最後就在該設備節點下載創建幾個屬性文件.而創建類的交給函數leds_init(void)來完成,而在該類下創建設備節點,以及在該節點下創建屬性文件,並對屬性文件實現讀寫操做..net

如今咱們先看看第一個,就是init加載文件,第一句也是核心句,就是創建一個類leds,而且函數返回值賦值給了led_cdev->dev,即led_cdev->dev=class_create(THIS_MODULE, "leds"),這個將在sys目錄下產生文件即產生leds類的文件名,第一個參數指定所屬的模塊,第二個指定了設備的名字.指針

而接下來的,第二句IS_ERR(leds-class)就是判斷leds-class是否正確產生.接下來的都是函數指針.leds_class->suspend = led_suspend等就是函數指針啦,上面都有具體函數實現.其中suspend()是在設備休眠時調用,resume()是恢復設備時調用.第一個函數suspend()函數的實現,其實它就是調了brightness_set(led_cdev, 0)函數,因此就說說這個函數.這個函數是數據結構體led_classdev裏的成員,是指向一個函數,在哪裏指向呢?在leds-gpio.c裏的那時候,指向gpio_led_set函數,其實實現就是對level變量賦值.而在leds-s3c24xx.c也差很少.總而來講,實現的供能就是設備掛起時候,就level賦一個值,0仍是1就根據你的active_low的選擇啦.如今說一下resume(),其實也等同上面同樣,最終用led_cdev->brightness賦值給level.到這裏leds_init函數就OK啦,最後經過subsys_initcall(leds_init)使得eds_init在系統啓動時候就會被初始化啦.code

總結一下,leds_init函數在系統啓動的時候就會被調用.實現的功能就是在sys/class目錄下生成leds類目錄,還有就是實現掛起和恢復時候,執行brightness_set(led_cdev, *)函數.orm

接下來就主要剩下led_classdev_register函數.blog

前面說了就是產生幾個文件.其中第一個就是設備節點.該函數第一句資源

led_cdev->dev = device_create(leds_class, parent, 0, led_cdev, "%s", led_cdev->name);

函數原型get

device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...),

看看代碼實現,一個主要函數就是dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs),就是實如今對應目錄下產生設備節點,那個目錄,先看看各個參數意思,第一個參數指定所要建立的設備所從屬的類,第二個參數是這個設備的父設備,若是沒有就指定爲NULL,第三個參數是設備號,第四個參數是設備名稱,第五個參數是從設備號.咱們看一下實參,第一個實參leds_class,這個在哪裏出現的呢?在前面leds_init函數的創建類的返回值,因此其實就是在前面的leds類下創建設備文件節點.

接下來的一句也相當重要,device_create_file函數,添加屬性文件,添加了幾個文件,咱們就那其中一

個dev_attr_brightness來說,這個屬性在哪裏實現?上面有 DEVICE_ATTR(brightness, 0644, led_brightness_show, led_brightness_store),其中後面兩個參數就是實現對該屬性文件的讀寫操做,兩個操做都有具體函數實現.說具體點就是,對該屬性文件讀操做時候,即便用cat命令對該屬性文件操做,內核會自動調用led_brightness_show.同理,使用echo命令就調用led_brightness_store函數如今咱們就看看這些文件是會放在哪裏.

如今先把代碼剖出來

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);

rc = device_create_file(led_cdev->dev, &dev_attr_brightness);

}

其實這個函數使用EXPORT_SYMBOL_GPL(led_classdev_register)導出來,在leds-gpio.c和leds-s3c24xx.c中調用.

咱們跟蹤一下led_classdev_register函數.在leds-gpio.c就有調用到,以下偵測函數

gpio_led_probe(struct platform_device *pdev)

其中調用

ret = create_gpio_led(&pdata->leds[i], &leds_data[i],  &pdev->dev, pdata->gpio_blink_set);

查看

create_gpio_led(const struct gpio_led *template,struct gpio_led_data *led_dat, struct device *parent,int (*blink_set)(unsigned, unsigned long *, unsigned long *))

可知,其就調用ret = led_classdev_register(parent, &led_dat->cdev);

前面咱們說了創建設備節點,如今再細講一下.咱們主要看看parent指向的是pdev->dev.因爲pdev是平臺設備,因此得關係到平臺設備問題.其中pdev->dev對應平臺設備下的設備.因此呢,對於設備節點的設備名,跟蹤一下leds-gpio.c代碼,就知道leds-gpio.c裏的cdev就對應上面的led_cdev

led_dat->cdev.name = template->name;  //在函數creat_gpio_led

而 template有對應於pdata->leds[i]

struct gpio_led_platform_data *pdata = pdev->dev.platform_data;

簡而言之,就是在在gpio_led_probe函數中,獲取平臺信息platform_data,做爲參數傳給函數creat_gpio_led的template參數,最後經過該參數付給了led_dat->cdev.name.

因此建立的dev節點的名字由你的平臺設備的信息決定的.

如今再來看看在哪裏生成屬性文件,看函數

device_create_file(led_cdev->dev, &dev_attr_brightness);

主要是看參數led_cdev->dev,這個又是指向哪裏,其實就是創建設備節點時候的返回值,能夠看看上面.因此就在設備節點目錄下創建屬性文件,固然後面幾個創建屬性文件都同樣.

說道這裏,led-class.c就完啦,剩下沒講的函數要不就是屬性讀寫函數,要不就是卸載函數,對於屬性文件就到咱們後面的移植篇再作講解.總結一下,通常類來講,用class_creat加你類,在device_creat在類目錄下創建設備文件,還能夠在設備節點下創建屬性文件,實現對設備的操做,可是該操做通常就是讀寫,是經過命令實現的.

好啦,上米哦按那張圖就展現了在class下創建4個設備節點:led0-led4,每一個設備節點下創建屬性文件,其中有一個brigtness,往這個文件執行命令,cat是讀出,echo是寫入,如:個人板子執行echo 1 >brightness時候,第一顆燈亮.執行echo 0 >brightness時候,第一顆燈不亮.對於爲何會亮,會什麼又會滅,在LED移植篇在講解.

可是這裏仍是有點問題:我在platform設備明明就只有led0-led4四個設備節點,可是怎麼會有led0-led7八個呢,待解..........................................

接下來就差leds-gpio.c(leds-s3c24xx.c和leds_gpio.c)是同樣,代碼頁差很少,,裏面主要就是platform模型,即涉及到存放什麼硬件資源內核,怎麼存放,而後咱們又怎麼去取出來.......

本文轉自:http://blog.csdn.net/shiyi_2012/article/details/7456165

相關文章
相關標籤/搜索