Linux中debugfs的应用实例

来源:互联网 发布:大数据hive 编辑:程序博客网 时间:2024/05/22 07:44
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/debugfs.h>

struct at24c02_data {
    uint8_t addr;
    uint8_t data;
    struct dentry *dir;
    struct i2c_client *client;
};

// 检查寄存器索引是否有效
static bool at24c02_debug_addr_is_valid(uint8_t addr)
{
    if (addr < 0 || addr > 0xff) {
        pr_err("eeprom reg address is invalid: 0x%x\n", addr);
        return false;
    }

    return true;
}

// 读取寄存器索引
static int at24c02_debug_addr_get(void *_data, u64 *val)
{
    struct at24c02_data *pdata = _data;

    if (at24c02_debug_addr_is_valid(pdata->addr))
        *val = pdata->addr;

    return 0;
}

// 设置寄存器索引
static int at24c02_debug_addr_set(void *_data, u64 val)
{
    struct at24c02_data *pdata = _data;

    if (at24c02_debug_addr_is_valid(val))
        pdata->addr = val;

    return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, at24c02_debug_addr_get,
            at24c02_debug_addr_set, "0x%02llX\n");
 
// 读取pdata->addr寄存器的值,存放在val所指向的地址中  
static int at24c02_debug_data_get(void *_data, u64 *val)
{
    int rt = 0;
    struct at24c02_data *pdata = _data;

    if (at24c02_debug_addr_is_valid(pdata->addr)) {
        rt = i2c_smbus_read_byte_data(pdata->client, pdata->addr);
        if (rt < 0)
            pr_err("at24c02 read register 0x%x failed %d\n", pdata->addr, rt);
        else
            *val = rt;
    }

    return 0;
}

// 向pdata->addr寄存器写入val
static int at24c02_debug_data_set(void *_data, u64 val)
{
    int rt = 0;
    struct at24c02_data *pdata = _data;

    if (at24c02_debug_addr_is_valid(pdata->addr)) {
        rt = i2c_smbus_write_byte_data(pdata->client, pdata->addr, val);
        if (rt < 0)
            pr_err("at24c02 write register 0x%x failed %d\n", pdata->addr, rt);
    }

    return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, at24c02_debug_data_get,
            at24c02_debug_data_set, "0x%02llX\n");

static int at24c02_i2c_probe(struct i2c_client *client,
                      const struct i2c_device_id *id)
{
    int rt = 0;
    struct at24c02_data *pdata;
    struct dentry *temp;

    if (!i2c_check_functionality(client->adapter,
                     I2C_FUNC_SMBUS_BYTE_DATA)) {
        dev_err(&client->dev, "SMBUS Word Data not Supported\n");
        return -EIO;
    }

    pdata = devm_kzalloc(&client->dev,
                sizeof(struct at24c02_data), GFP_KERNEL);
    if (!pdata) {
        dev_err(&client->dev, "Not enough memory\n");
        return -ENOMEM;
    }

    pdata->client = client;
    i2c_set_clientdata(client, pdata);

    pdata->dir = debugfs_create_dir("eeprom_debug", NULL);
    if (pdata->dir == NULL || IS_ERR(pdata->dir)) {
        pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(pdata->dir));
        rt = PTR_ERR(pdata->dir);
        return rt;
    }

    temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, pdata->dir, pdata,
                   &debug_addr_fops);
    if (temp == NULL || IS_ERR(temp)) {
        pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
        rt = PTR_ERR(pdata->dir);
        return rt;
    }

    temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, pdata->dir, pdata,  
                   &debug_data_fops);  
    if (temp == NULL || IS_ERR(temp)) {  
        pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));  
        rt = PTR_ERR(pdata->dir);  
        return rt;  
    }  

    pr_err("%s succeeded\n", __func__);
    return 0;
}

static int at24c02_i2c_remove(struct i2c_client *client)
{
    struct at24c02_data *pdata = i2c_get_clientdata(client);

    debugfs_remove_recursive(pdata->dir);
    kfree(pdata);
    
    return 0;
}

static const struct i2c_device_id at24c02_id[] = {
    { "at24c02", 0 },
};
MODULE_DEVICE_TABLE(i2c, at24c02_id);

static struct i2c_driver at24c02_i2c_driver = {
    .driver = {
        .name    = "at24c02",
        .owner    = THIS_MODULE,
    },
    .probe        = at24c02_i2c_probe,
    .remove        = at24c02_i2c_remove,
    .id_table    = at24c02_id,
};

static int at24c02_i2c_init(void)
{
    return i2c_add_driver(&at24c02_i2c_driver);
}
module_init(at24c02_i2c_init);

static void at24c02_i2c_exit(void)
{
    i2c_del_driver(&at24c02_i2c_driver);
}
module_exit(at24c02_i2c_exit);

MODULE_AUTHOR("yuntaohe");
MODULE_DESCRIPTION("at24c02 eeprom driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("i2c:at24c02");


调试:
root@(none) /sys/kernel/debug/eeprom_debug$ echo 0xaa > addr
root@(none) /sys/kernel/debug/eeprom_debug$ echo 0x55 > data
root@(none) /sys/kernel/debug/eeprom_debug$ cat data
0x55

0 0
原创粉丝点击