如何打印i2c SMBUS原始数据包?

时间:2019-03-27 14:00:30

标签: c kernel linux-device-driver

我已使用代码参考https://elixir.bootlin.com/linux/latest/source/drivers/i2c/i2c-stub.c编写了样本i2c / SMBUS仿真芯片和适配器。

有没有一种方法可以打印原始的SMBUS命令请求和响应?请提供一些代码示例。

static unsigned short chip_addr=0x1c;

struct stub_chip {
    u8 pointer;
    u16 words[256]; /* Byte operations use the LSB as per SMBus  specification */
};

static struct stub_chip *my_i2c_chip;
/* Return negative errno on error. */
static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
    char read_write, u8 command, int size, union i2c_smbus_data * data)
{
    s32 ret;
    //struct stub_chip *chip = i2cstub_chip;

    if (!my_i2c_chip)
        return -ENODEV;

    switch (size) {

    case I2C_SMBUS_QUICK:
        dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr);
        ret = 0;
        break;

    case I2C_SMBUS_BYTE:
        if (read_write == I2C_SMBUS_WRITE) {
            my_i2c_chip->pointer = command;
            dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
                    "wrote 0x%02x.\n",
                    addr, command);
        } else {
            data->byte = my_i2c_chip->words[my_i2c_chip->pointer++] & 0xff;
            dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
                    "read  0x%02x.\n",
                    addr, data->byte);
        }

        ret = 0;
        break;

    case I2C_SMBUS_BYTE_DATA:
        if (read_write == I2C_SMBUS_WRITE) {
            my_i2c_chip->words[command] &= 0xff00;
            my_i2c_chip->words[command] |= data->byte;
            dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
                    "wrote 0x%02x at 0x%02x.\n",
                    addr, data->byte, command);
        } else {
            data->byte = my_i2c_chip->words[command] & 0xff;
            dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
                    "read  0x%02x at 0x%02x.\n",
                    addr, data->byte, command);
        }
        my_i2c_chip->pointer = command + 1;

        ret = 0;
        break;

    case I2C_SMBUS_WORD_DATA:
        if (read_write == I2C_SMBUS_WRITE) {
            my_i2c_chip->words[command] = data->word;
            dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
                    "wrote 0x%04x at 0x%02x.\n",
                    addr, data->word, command);
        } else {
            data->word = my_i2c_chip->words[command];
            dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
                    "read  0x%04x at 0x%02x.\n",
                    addr, data->word, command);
        }

        ret = 0;
        break;

    default:
        dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
        ret = -EOPNOTSUPP;
        break;
    } /* switch (size) */

    return ret;
}

static u32 stub_func(struct i2c_adapter *adapter)
{
    return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
        I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
}

static const struct i2c_algorithm smbus_algorithm = {
    .functionality  = stub_func,
    .smbus_xfer = stub_xfer,
};

static struct i2c_adapter stub_adapter = {
    .owner      = THIS_MODULE,
    .class      = I2C_CLASS_HWMON | I2C_CLASS_SPD,
    .algo       = &smbus_algorithm,
    .name       = "SMBus stub driver",
};


static int __init i2c_stub_init(void)
{
    int ret;

    printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", chip_addr);

    /* Allocate memory for i2c stub chip */
    my_i2c_chip = kzalloc(sizeof(struct stub_chip), GFP_KERNEL);
    if (!my_i2c_chip) {
        printk(KERN_ERR "i2c-stub: Out of memory\n");
        return -ENOMEM;
    }

    ret = i2c_add_adapter(&stub_adapter);
    if (ret)
        kfree(my_i2c_chip);
    return ret;
}

static void __exit i2c_stub_exit(void)
{
    i2c_del_adapter(&stub_adapter);
    kfree(my_i2c_chip);
}

module_init(i2c_stub_init);
module_exit(i2c_stub_exit);

---------------- code ends----------------

我想打印原始的SMBUS数据包请求和响应。我如何实现这个问题?

0 个答案:

没有答案