device_create_file的使用

DEVICE_ATTR是一个宏,其定义在include/linux/device.h:

#define DEVICE_ATTR(_name, _mode, _show, _store) \
    struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)

__ATTR宏定义在include/linux/sysfs.h:

#define __ATTR(_name,_mode,_show,_store) { \
    .attr = {.name = __stringify(_name), .mode = _mode },   \
    .show   = _show,                                        \
    .store  = _store,                                       \
}
struct device_attribute结构定义在include/linux/device.h:
/* interface for exporting device attributes */
struct device_attribute {
    struct attribute    attr;
    ssize_t (*show)(struct device *dev, struct device_attribute *attr,
            char *buf);
    ssize_t (*store)(struct device *dev, struct device_attribute *attr,
             const char *buf, size_t count);
};
DEVICE_ATTR宏展开:
#define DEVICE_ATTR(_name, _mode, _show, _store) \
    struct device_attribute dev_attr_##_name = { \
        .attr = {.name = __stringify(_name), .mode = _mode },   \
        .show   = _show,                                        \
        .store  = _store,                                       \
    }
举例说明DEVICE_ATTR使用方法:
static DEVICE_ATTR(msm_gpio, 0664, msmgpio_show, msmgpio_store);

static ssize_t msmgpio_show(struct device *dev,
                   struct device_attribute *attr, char *buf)
{
    int temp[5];
    struct gpio_data *gpio_data_ptr = dev_get_drvdata(dev);

    temp[0] = gpio_get_value(gpio_data_ptr->gpio0);
    temp[1] = gpio_get_value(gpio_data_ptr->gpio2);
    temp[2] = gpio_get_value(gpio_data_ptr->gpio3);
    temp[3] = gpio_get_value(gpio_data_ptr->gpio10);
    temp[4] = gpio_get_value(gpio_data_ptr->gpio11);

    return snprintf(buf, 6, "%d%d%d%d%d", temp[0], temp[1],
                    temp[2], temp[3], temp[4]);
}

static ssize_t msmgpio_store(struct device *dev,
           struct device_attribute *attr, const char *buf, size_t size)
{
    struct gpio_data *gpio_data_ptr = dev_get_drvdata(dev);

    gpio_set_value(gpio_data_ptr->gpio0,  (buf[0] == '1') ? 1 : 0);
    gpio_set_value(gpio_data_ptr->gpio2,  (buf[1] == '1') ? 1 : 0);
    gpio_set_value(gpio_data_ptr->gpio3,  (buf[2] == '1') ? 1 : 0);
    gpio_set_value(gpio_data_ptr->gpio10, (buf[3] == '1') ? 1 : 0);
    gpio_set_value(gpio_data_ptr->gpio11, (buf[4] == '1') ? 1 : 0);

    return size;
}

static DEVICE_ATTR(msm_gpio, 0664, msmgpio_show, msmgpio_store);

之后在驱动的probe函数中即可调用device_create_file:

err = device_create_file(&dev->dev, &dev_attr_msm_gpio);
if (err) {
        dev_err(&dev->dev, "sys file creation failed\n");
        return -ENODEV;
}
device_create_file和device_remove_file定义在drivers/base/core.c中,声明在include/linux/device.h中,device_create_file返回0代表创建成功。

int device_create_file(struct device *dev, const struct device_attribute *attr)
{
    int error = 0;

    if (dev) {
        WARN(((attr->attr.mode & S_IWUGO) && !attr->store),
            "Attribute %s: write permission without 'store'\n",
            attr->attr.name);
        WARN(((attr->attr.mode & S_IRUGO) && !attr->show),
            "Attribute %s: read permission without 'show'\n",
            attr->attr.name);
        error = sysfs_create_file(&dev->kobj, &attr->attr);
    }

    return error;
}

void device_remove_file(struct device *dev,
            const struct device_attribute *attr)
{
    if (dev)
        sysfs_remove_file(&dev->kobj, &attr->attr);
}
在文件系统/sys/devices/soc.0/gpio_ctrl.72下面生成msm_gpio节点,用cat,echo操作硬件:
root@msm8909:/sys/devices/soc.0/gpio_ctrl.72 # ls -l msm_gpio                  
-rw-rw-r-- root     root         4096 1970-01-01 00:02 msm_gpio
root@msm8909:/sys/devices/soc.0/gpio_ctrl.72 # cat msm_gpio
00000
root@msm8909:/sys/devices/soc.0/gpio_ctrl.72 # echo 11111 > msm_gpio

`device_create_file()`函数用于向设备添加一个属性文件,让用户空间能够读取或写入设备的相关信息。以下是该函数的使用方法: 1. 定义读取和写入属性值的回调函数: ```c static ssize_t my_show_function(struct device *dev, struct device_attribute *attr, char *buf) { // 在这里实现读取属性的逻辑 return sprintf(buf, "value\n"); // 将属性值写入缓冲区 } static ssize_t my_store_function(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { // 在这里实现写入属性的逻辑 // 可以使用buf和count参数获取用户传递的数据 return count; // 返回写入的字节数 } ``` 在这个示例中,`my_show_function()`函数用于读取属性值,`my_store_function()`函数用于写入属性值。这些函数的签名必须与`ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf)`和`ssize_t (*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)`匹配。 2. 创建一个`struct device_attribute`结构体,并初始化它: ```c static DEVICE_ATTR(my_attribute_name, S_IRUGO | S_IWUSR, my_show_function, my_store_function); ``` 在这个示例中,`my_attribute_name`是属性的名称,`S_IRUGO | S_IWUSR`是属性的权限,`my_show_function`和`my_store_function`是之前定义的读取和写入回调函数。 3. 在设备创建后调用`device_create_file()`函数来添加属性文件: ```c int ret = device_create_file(my_device, &dev_attr_my_attribute_name); if (ret) { // 处理创建失败的情况 } ``` 在这个示例中,`my_device`是指向设备的指针,`&dev_attr_my_attribute_name`是之前创建的属性结构体的指针。 通过以上步骤,你就可以成功地在设备中创建属性文件了。这样,在/sys/class/my_class_name/my_device_name目录下就会创建一个名为my_attribute_name的属性文件。用户可以通过读取和写入该文件来获取和设置设备的相关信息。 请注意,以上示例代码仅为了演示`device_create_file()`函数的使用方法,实际应用中需要根据具体需求进行适当的修改。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值