簡體   English   中英

使用宏時的字符驅動設備問題

[英]char driver device issue when using macros

語境

我被要求為特定的硬件 package 制作一個字符驅動程序。 此驅動程序需要有兩個設備位於同一 class 下。 現在,我並不真正介意整個 file_operations 結構,因為我主要遇到 sysfs 和屬性定義的問題。 我正在使用 VMware,驅動程序必須能夠在 linux v5.10.X 上運行。

做了什么

到目前為止,我已經初始化了我的驅動程序(在任何函數之外):

static struct class * dev_class; 
static struct device * some_dev_1;
static struct device * some_dev_2; 
static struct cdev some_cdev_1;
static struct cdev some_cdev_2;
static dev_t dev_num_1 = MKDEV(MAJOR_NUMBER_1, 0); /* Major is 235 */
static dev_t dev_num_2 = MKDEV(MAJOR_NUMBER_2, 0); /* Major is 240 */

所以我有兩個設備(用於 sysfs)和它們的 cdev(用於用戶界面)。 device_bringup function(見下文)內部,我想用我的show/store方法填充attribute_group ** groups結構, 如結構文檔中所示 我嘗試按照本教程教程進行操作,得到以下代碼:

int device_bringup(char * device_1_name, char * device_2_name){
    int return_value = SUCCESS;

    some_dev_1 = device_create(dev_class, NULL, dev_num_1, NULL, device_1_name); /* Create/Registers it on sysfs */
    some_dev_2 = device_create(dev_class, NULL, dev_num_2, NULL, device_2_name);

    if(some_dev_1 == NULL){
        printk(KERN_ALERT KBUILD_MODNAME " Cannot create the Device #1 !\n");
        return_value = init_error_manager(1);
    }

    printk(KERN_ALERT KBUILD_MODNAME " Device #1 was created !\n");

    if(some_dev_2 == NULL){
        printk(KERN_ALERT KBUILD_MODNAME " Cannot create the Device #2 !\n");
        return_value = init_error_manager(2);
    }
    printk(KERN_ALERT KBUILD_MODNAME " Device #2 was created !\n");


    DEVICE_ATTR(first, 0664, sysfs_show, sysfs_store); /* Name should be dev_attr_first */
    DEVICE_ATTR(second, 0664, sysfs_show, sysfs_store); /* Name should be dev_attr_second */

    struct attribute * some_dev_1_attrs[] = { /* see https://docs.kernel.org/driver-api/driver-model/device.html for info */
        &dev_attr_first.attr, 
        &dev_attr_second.attr, 
        NULL
    };

    struct attribute * some_dev_2_attrs[] = { 
        &dev_attr_first.attr, 
        &dev_attr_second.attr, 
        NULL
    };

    ATTRIBUTE_GROUPS(some_dev_1); /* Create the some_dev_1_groups */
    ATTRIBUTE_GROUPS(some_dev_2); /* Create the some_dev_2_groups */
    
    some_dev_1->groups = some_dev_1_groups;
    some_dev_2->groups = some_dev_2_groups;

    return return_value;
}

問題

在按照上面的兩個教程進行操作后,我的 kernel 無法構建,並且收到以下錯誤:

error: initializer element is not constant ATTRIBUTE_GROUPS(some_dev_1);

error: initializer element is not constant ATTRIBUTE_GROUPS(some_dev_2);

然后我閱讀了這個問題,這似乎源於some_dev_1some_dev_2設備指針未初始化的事實。 但是,在閱讀了一些 stackoverflow 線程之后,我嘗試過:

static struct device * some_dev_1 = kmalloc(sizeof(some_dev_1));

然后

static struct device * some_dev_1 = &(struct device){.name = "test"};

乃至

static struct device * some_dev_1 = NULL;

但是,這些都沒有解決問題。 我很確定這個問題很容易解決,但我似乎只能繞着它轉圈。

解決方案

事實證明,問題來自宏ATTRIBUTE_GROUPS(some_dev_1)並沒有真正使用在some_dev_1之外定義的 some_dev_1。 它僅將其用作組名稱的字符串。

使用device_create_with_groups而不將屬性組直接分配給設備是它對我有用的原因。 我還必須制作屬性 static 的DEVICE_ATTR和 arrays,以便它們在 scope 之外可用。 這是最終的工作代碼:

int device_bringup(char * device_1_name, char * device_2_name){
    int return_value = SUCCESS;

    static DEVICE_ATTR(first, 0664, sysfs_show, sysfs_store); /* Name should be dev_attr_tape_deck_first */
    static DEVICE_ATTR(second, 0664, sysfs_show, sysfs_store); /* Name should be dev_attr_tape_deck_second */

    static struct attribute * some_dev_1_attrs[] = {
        &dev_attr_first.attr, 
        &dev_attr_second.attr, 
        NULL
    };

    static struct attribute * some_dev_2_attrs[] = { 
        &dev_attr_first.attr, 
        &dev_attr_second.attr, 
        NULL
    };

    ATTRIBUTE_GROUPS(some_dev_1); 
    ATTRIBUTE_GROUPS(some_dev_2); 
    some_dev_1 = device_create_with_groups(dev_class, NULL, dev_num_1, NULL, some_dev_1_groups, device_1_name);
    some_dev_2 = device_create_with_groups(dev_class, NULL, dev_num_2, NULL, some_dev_2_groups, device_2_name);

    if(IS_ERR_OR_NULL(some_dev_1)){ 
        printk(KERN_ALERT KBUILD_MODNAME " Cannot create the Device #1 !\n");
        return_value = PTR_ERR(some_dev_1);
    }

    printk(KERN_ALERT KBUILD_MODNAME " Device #1 was created !\n");

    if(IS_ERR_OR_NULL(some_dev_2)){
        printk(KERN_ALERT KBUILD_MODNAME " Cannot create the Device #2 !\n");
        return_value = PTR_ERR(some_dev_2);
    }
    printk(KERN_ALERT KBUILD_MODNAME " Device #2 was created !\n");

    return return_value;
}

這不是它的最終版本,因為我必須使 function 更具原子性,並且不在同一個 function 中創建兩個設備,但每次調用只創建一個。 但是,上面的代碼解決了我的問題。 我希望它能幫助遇到此類問題的任何人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM