#define SUPPORT_AUDIO 1
static ssize_t  attr_audio_value_show(struct device *dev,
                   struct device_attribute *attr, char *buf)
{
    int val = SUPPORT_AUDIO;    //1 : support audio
    return sprintf(buf, "%d\n", val);
}

static struct device_attribute attributes[] = {    
    __ATTR(audio, 0444, attr_audio_value_show, NULL),
};


static int create_sysfs_interfaces(struct device *dev)
{    
    int i;    
    for (i = 0; i < ARRAY_SIZE(attributes); i++)    
        if (device_create_file(dev, attributes + i))            
            goto error;    
        return 0;

error:
    printk("%s error, i = %d\n", __func__, i );
    for ( ; i >= 0; i--)        
          device_remove_file(dev, attributes + i);    
          dev_err(dev, "%s:Unable to create interface\n", __func__);    
         return -1;
}

static int remove_sysfs_interfaces(struct device *dev)
{
    int i;
    for (i = 0; i < ARRAY_SIZE(attributes); i++)
        device_remove_file(dev, attributes + i);
    return 0;
}
 

註冊完裝置後 再註冊

        if ( create_sysfs_interfaces(&dev) ) {
            printk("create_sysfs_interface failed\n");
            return -1;
        }

 

移除
            remove_sysfs_interfaces(&dev);
   

 

http://www.voidcn.com/blog/a_jige/article/p-1149266.html

 

http://www.itwendao.com/article/detail/100483.html

 

http://victoryuembeddedlinux.blogspot.tw/2011/04/driversysfs.html

 

如何撰寫Driver支援sysfs檔案系統

 
前言
在現在Linux的系統中,有一個新的虛擬檔案系統,叫做sysfs,它只要是來管理Linux系統中的週邊元件,及配合使用公用程式來自動產生device node。其實它是一個虛擬的記憶體檔案系統,它是由proc所變化而來的,它是由各個driver所產生,換另一句話就是要Driver有撰寫才會有這樣的功能,它是繼承kobject的資料結構,另外其檔名及內容都是driver自行解決,目前主要都是來設定driver自己本身的一些功能,這樣可以讓驅動程式更多元化,或者可以讀取驅動程式現在的情形為何,這可以來維護系統的運作,現在有很多驅動程式已經支援這個功能,所以有許多的系統管理程式,也是透過這個介面來管理系統核心。現在我們來介紹如何在driver中撰這些程式碼。
 
如何啓動這個目錄
因為它是一個虛擬的記憶體檔案系統,所以將使用Linux系統中管理檔案系統一樣的方法,就是使用mount的指令將其掛載在作業系統的檔案系統中,以下為單獨載入的指令:
 
> mount  –t  sysfs  sysfs  /sys
 
另外在kernel的選項中必須要啓動以下選項:
 
CONFIG_SYSFS=y
 
系統驅動程式結構
我們先來了解一下linux kernel其中驅動程式的結構,在linux kernel的驅動程式中會將各種元件給予分門別類,並且在各種類別中會給予建構一個管理層的驅動程式,其主要目的是要建立和應用程式之間的標準介面,並且管理相同類別中的各家不同的硬體廠商,如此一來即可規範硬體廠商如何撰寫廠商,避免因不同的廠商而產生不同的驅動程式的撰寫格式不同,或者造成應用程式的介面,進而造成使用者因不同的廠商而要修改軟體。其架構圖如下:
 
 
圖一:驅動程式系統架構
 
以圖一中來看將會有一個RTC class產生,它將會統籌管理系統中所有的RTC元件,而系統中所有的RTC將會和它來做一個註冊,如此會產生一個RTC的class及其底下的RTC0, RTC1 ….. RTCn,其會在/sys/class之下會建立一個RTC的目錄,而每一個註冊的RTC元件將會在RTC class目錄之下產生RTC0至RTCn的子目錄,而每一個子目錄將會各別產生或者說是繼承RTC class的各個檔案。
 
Kernel API
在介紹如何撰寫前,先來了解有那些kernel API可供使用,其所用的include file是,而API如下:
 
struct class *class_create(struct module *owner, const char *name)
這是建立一個模組的類別,其input/output說明如下:
Input :
struct module *owner – 模組的擁有者,通常是設定為THIS_MODULE
const char *name –要建立之類別名稱,之後可以建立在這個類別之下的檔案。
Output :
其返回值為一個class資料結構的位址point,這個資料結構會在後面介紹,這個point位址將會給予保留,因為我們需要在其中幾個call back欄位填入我們要實現的功能,也就是提供給AP如何溝通的介面。
 
extern struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...) __attribute__((format(printf, 5, 6)));
#define device_create_drvdata   device_create
 這是在該類別之下建立一個週邊元件,也就是建立一個device。
Input :
struct class *cls – 是前一個API所return回來的class pointer。
struct devuce *parent – 為該元件的上一層driver為何若没有可以設定為NULL。
dev_t devt – 這是該元件的major number & minor number的結合,可以使用巨集指令MKDEV()來產生。
const char *fmt – 為該元件的device node名稱。
Output :
其返回值為一個device的資料結構,可讓driver其它地方使用。
 
資料結構
如前面所提,其中最重要的資料結構宣告如下:
 
struct class {
        const char              *name;
        struct module           *owner;
 
        struct class_attribute          *class_attrs;
        struct device_attribute         *dev_attrs;
        struct kobject                  *dev_kobj;
 
        int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
 
        void (*class_release)(struct class *class);
        void (*dev_release)(struct device *dev);
 
        int (*suspend)(struct device *dev, pm_message_t state);
        int (*resume)(struct device *dev);
 
        struct pm_ops *pm;
        struct class_private *p;
};
 
其中的成員struct device_attribute *dev_attrs; 是比較重要,這是設定在這類別之下所建立的元件都會繼承這些基設定,而每一個設都可以設定為唯讀或可讀寫,可以參考以下範例得到較清楚的解答。
 
範例程式
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/tty.h>
#include <linux/proc_fs.h>
#include <linux/timer.h>
#include <linux/sysfs.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
 
#define VICTOR_DEBUG
#include "../include/mydebug.h"
 
#define MY_MAJOR        40
 
struct class    *sysfs_class;
 
static ssize_t
sysfs_show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
        return sprintf(buf, "show name\n");
}
 
static ssize_t
sysfs_show_date(struct device *dev, struct device_attribute *attr, char *buf)
{
        ssize_t retval;
 
        retval = sprintf(buf, "show date\n");
        return retval;
}
 
/*
這是一個讀取的call back function,必需返回共有多少的bytes放在buffer中。
*/
static ssize_t
sysfs_show_time(struct device *dev, struct device_attribute *attr, char *buf)
{
        ssize_t retval;
 
        retval = sprintf(buf, "show time\n");
        return retval;
}
 
static ssize_t
sysfs_show_max_user_freq(struct device *dev, struct device_attribute *attr, char *buf)
{
        return sprintf(buf, "show max user freq\n");
}
 
/*
這是一個寫入的call back functio,一樣必需返回共有多少bytes被處理。
*/
static ssize_t
sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t n)
{
        printk("get string = %s\n", buf);
        return n;
}
 
/*
以下設定中,S_IRUGO表示唯讀而己,S_IWUR表示可以寫入,而相對應的call back function必需要實現,其定義在linux/stat.h之。
*/
static struct device_attribute sysfs_attrs[] = {
        __ATTR(name, S_IRUGO, sysfs_show_name, NULL),
        __ATTR(date, S_IRUGO, sysfs_show_date, NULL),
        __ATTR(time, S_IRUGO, sysfs_show_time, NULL),
        __ATTR(max_user_freq, S_IRUGO | S_IWUSR, sysfs_show_max_user_freq, sysfs_set_max_user_freq),
        { },
};
 
static int sysfs_suspend(struct device *dev, pm_message_t mesg)
{
        dbg_printk("\n");
        return 0;
}
 
static int sysfs_resume(struct device *dev)
{
        dbg_printk("\n");
        return 0;
}
 
static int      __init mysysfs_init(void)
{
        dbg_printk("\n");
        sysfs_class = class_create(THIS_MODULE, "mysysfs");
        if (IS_ERR(sysfs_class)) {
                printk(KERN_ERR "%s: couldn't create class\n", __FILE__);
                return PTR_ERR(sysfs_class);
        }
        dbg_printk("class create OK.\n");
 
        sysfs_class->suspend = sysfs_suspend;
        sysfs_class->resume = sysfs_resume;
        sysfs_class->dev_attrs = sysfs_attrs;
 
        device_create_drvdata(sysfs_class, NULL, MKDEV(200, 0), NULL, "mysysfs0");
 
        return 0;
}
 
static void     __exit mysysfs_exit(void)
{
        dbg_printk("\n");
        device_destroy(sysfs_class, MKDEV(200, 0));
        class_destroy(sysfs_class);
}
 
module_init(mysysfs_init);
module_exit(mysysfs_exit);

 

http://www.voidcn.com/blog/a_jige/article/p-1149266.html

 

http://www.coctec.com/docs/linux/show-post-70096.html

arrow
arrow
    全站熱搜

    立你斯 發表在 痞客邦 留言(0) 人氣()