我正在尝试使用 regmap api 来访问 I2C 设备,但完全不清楚 val 指针的预期类型是什么。
Cfr : int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
我看到的两个选项是(恕我直言,两者都很糟糕):
[1] 它实际上应该是一个指向 unsigned int 类型的指针,并且在读取它时必须使用中间变量。由于您不知道位大小和 unsigned int 类型是什么,因此您永远无法确定它是否能容纳 32 位。
[2] 它应该是一个指向与您在 regmap_config 中传入 val_bits 的内容相对应的类型的指针(并且您必须错误地将该指针重新转换为 API 期望的类型以使其可编译)。
该文档根本没有帮助(惊讶):
/**
...
* @val: Pointer to store read value
...
*/
类似https://patchwork.kernel.org/patch/9378201/之类的东西似乎表明它是[1], 但我看到其他驱动程序,我认为这些驱动程序可以做[2],例如:
static inline int
ar1335_read_reg(struct ar1335_info *info, u16 addr, u16 *val)
{
return regmap_read(info->regmap, addr, (unsigned int *) val);
}
(https://github.com/Bogdacutu/STLinux-Kernel/blob/master/drivers/media/platform/tegra/ar1335.c)
如果我尝试遵循实际上分配给读取的功能(我认为,这是完整的抽象和更多抽象),我想我最终会得到
static int regmap_i2c_read(void *context,
const void *reg, size_t reg_size,
void *val, size_t val_size)
{
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);
struct i2c_msg xfer[2];
int ret;
xfer[0].addr = i2c->addr;
xfer[0].flags = 0;
xfer[0].len = reg_size;
xfer[0].buf = (void *)reg;
xfer[1].addr = i2c->addr;
xfer[1].flags = I2C_M_RD;
xfer[1].len = val_size;
xfer[1].buf = val;
ret = i2c_transfer(i2c->adapter, xfer, 2);
if (ret == 2)
return 0;
else if (ret < 0)
return ret;
else
return -EIO;
}
这表明它必须是指向真实数据类型的指针,例如 u16 * 如果 val_bits = 16。
有人有任何见解吗? 如果是 [2] 为什么不使用 void * 指针来避免像 i2c 读取中那样的丑陋的强制转换?历史混乱?
谢谢,
布拉姆