【问题标题】:What does ENXIO mean for an i2c ioctl?ENXIO 对 i2c ioctl 意味着什么?
【发布时间】:2016-07-15 16:25:06
【问题描述】:

我有一个 i2c 适配器以 /dev/i2c-0 暴露给用户空间。当我在该适配器上使用 i2c-tools 包中的 i2cdetect 时,我看到我的设备列在此适配器上,并且我能够从命令行对其执行获取、设置和转储操作。

我有一些 C 代码尝试使用 ioctl I2C_RDWR 操作对其执行写入操作。

这是我正在使用的精简代码(仅为上下文提供,运行它对于回答问题并不重要)。

fd = open ("/dev/i2c-0", O_RDWR | O_NONBLOCK);

/* other stuff happens here */

if (ioctl (fd, I2C_FUNCS, &funcs) != 0)
    return -1;
if (!(funcs & I2C_FUNC_I2C))
    return -1;

/* i added this bit of debug just to be sure fd didn't
 * get inadvertently closed along the way.
 */
if (fcntl (fd, F_GETFD) != 0) {
    return -1;
}

/* build the ioctl message payload */

ret = ioctl (fd, I2C_RDWR, &payload)
if (ret) {
    fprintf (stderr, "ioctl returned %d. Reason: %s (errno=%d).",
             ret, strerror(errno), errno);
    return -1;
}

return 0;

我也尝试过使用 smbus ioctl 函数,看起来像这样。

fd = open ("/dev/i2c-0", O_RDWR | O_NONBLOCK);

/* other stuff happens here */

if (ioctl (fd, I2C_FUNCS, &funcs) != 0)
    return -1;
if (!(funcs & I2C_FUNC_SMBUS_WORD_DATA))
    return -1;

/* i added this bit of debug just to be sure fd didn't
 * get inadvertently closed along the way.
 */
if (fcntl (fd, F_GETFD) != 0) {
    return -1;
}

/* build the ioctl smbus message payload */

if (ioctl (fd, I2C_SLAVE_FORCE, dev) != 0)
    return -1;

ret = ioctl (fd, I2C_SMBUS, &payload);
if (ret) {
    fprintf (stderr, "ioctl returned %d. Reason: %s (errno=%d).",
             ret, strerror(errno), errno);
    return -1;
}

return 0;

在所有情况下,程序总是点击fprintf,这是输出:

ioctl 返回 -1。原因:没有这样的设备或地址(errno=6)。

根据man 3 ioctl,ENXIO 错误的“一般”原因是:

ENXIO requestarg 参数对此设备驱动程序有效,但请求的服务无法在此特定子设备上执行.

然而,正如 Ian 在 cmets 中指出的那样,上述手册页中有关 STREAMS 的信息与 Linux 无关,我应该使用 man 2 ioctl - 不幸的是,这主要是说 ioctls 不真正符合任何标准,什么都行。

这提出了三个问题。

  1. 这对 i2c 适配器意味着什么?这个设备的驱动不支持用这种方法读写吗?
  2. 手册页包含 I_ 前缀操作的返回码的具体描述,但不包含其他操作的返回码。是否有其他地方可以查找特定于 I2C ioctl 操作的信息?
  3. 在哪里可以找到 i2c ioctl 函数的源代码?

【问题讨论】:

  • 对 STREAMS 设备的引用与 Linux 无关,因为它不支持 STREAMS。你真的应该看看man 2 ioctl
  • @IanAbbott 嗯,那个甚至没有提到 ENXIO。 :(
  • 参见“符合”部分。 :)
  • 对于 i2c,我认为 ENXIO 意味着它得到了意外的 NAK。
  • 您是否阅读过有关此开发接口的内核文档? @ 987654326@ 恕我直言,I2C_RDRW ioctl 接口非常复杂,如果您的有效负载是如何构建的,将会很有趣。也许有错误。该文档还说 I2C_SMBUS ioctl 是“不打算直接调用;相反,请使用下面的访问函数。”所以我会尝试使用它们。无论如何,这个界面看起来要容易得多。

标签: c linux i2c


【解决方案1】:

通常,这意味着设备没有响应。具体取决于您的硬件。

通用 I2C ioctl 代码是 i2c-dev 包的一部分,它是 lm-sensors 项目的一部分。这些 ioctl 没有自己的手册页,但有 documentation in the kernel source tree

在内核中,实现全部保存在drivers/i2c/i2c-dev.cdrivers/i2c/i2c-core.c中。入口点是i2cdev_ioctl()。此通用代码均不返回 ENXIO。

最终,这个通用代码需要调用 i2c 总线上的硬件级驱动程序函数。 i2c 总线的硬件驱动程序存储在drivers/i2c/busses/ 中。这些驱动程序中的每一个都可以实现master_xfer(用于I2C_RDWR ioctls)或smbus_xfer(用于I2C_SMBUS)函数中的一个或两个。

在我的例子中,该设备实际上没有专用的 i2c 硬件,并且正在使用似乎是在函数 bit_xfer of drivers/i2c/algos/i2c-algo-bit.c 中实现的位碰撞软件仿真。 ENXIO 来自函数bit_doAddress

【讨论】:

  • 提示:使用dmesg 读取内核日志。通常它会有一些失败的原因(例如,如果设备没有响应,则会出现 I2C 超时错误)。
猜你喜欢
  • 1970-01-01
  • 2011-12-28
  • 2020-10-12
  • 2011-06-11
  • 2010-10-02
  • 2013-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多