用户空间通过连接器通信协议

消息类型

w1 核心和用户空间之间有三种类型的消息

  1. 事件。它们在每次由于自动或请求搜索而发现新的主设备或从设备时生成。

  2. 用户空间命令。

  3. 对用户空间命令的回复。

协议

[struct cn_msg] - connector header.
      Its length field is equal to size of the attached data
[struct w1_netlink_msg] - w1 netlink header.
      __u8 type       - message type.
                      W1_LIST_MASTERS
                              list current bus masters
                      W1_SLAVE_ADD/W1_SLAVE_REMOVE
                              slave add/remove events
                      W1_MASTER_ADD/W1_MASTER_REMOVE
                              master add/remove events
                      W1_MASTER_CMD
                              userspace command for bus master
                              device (search/alarm search)
                      W1_SLAVE_CMD
                              userspace command for slave device
                              (read/write/touch)
      __u8 status     - error indication from kernel
      __u16 len       - size of data attached to this header data
      union {
              __u8 id[8];                      - slave unique device id
              struct w1_mst {
                      __u32           id;      - master's id
                      __u32           res;     - reserved
              } mst;
      } id;

[struct w1_netlink_cmd] - command for given master or slave device.
      __u8 cmd        - command opcode.
                      W1_CMD_READ     - read command
                      W1_CMD_WRITE    - write command
                      W1_CMD_SEARCH   - search command
                      W1_CMD_ALARM_SEARCH - alarm search command
                      W1_CMD_TOUCH    - touch command
                              (write and sample data back to userspace)
                      W1_CMD_RESET    - send bus reset
                      W1_CMD_SLAVE_ADD        - add slave to kernel list
                      W1_CMD_SLAVE_REMOVE     - remove slave from kernel list
                      W1_CMD_LIST_SLAVES      - get slaves list from kernel
      __u8 res        - reserved
      __u16 len       - length of data for this command
              For read command data must be allocated like for write command
      __u8 data[0]    - data for this command

每个连接器消息可以包含一个或多个 w1_netlink_msg,并带有零个或多个附加的 w1_netlink_cmd 消息。

对于事件消息,没有嵌入的 w1_netlink_cmd 结构,只有连接器头和 w1_netlink_msg 结构,其中“len”字段为零,并填充了类型(事件类型之一)和 ID:可以是主机序的从设备唯一 ID 的 8 字节,或者是主设备的 ID(在添加到 w1 核心时分配给总线主设备)。

目前,对用户空间命令的回复只针对读取命令请求生成。一个回复精确地为一次 w1_netlink_cmd 读取请求生成。发送时不会组合回复 — 即典型的回复消息如下所示

[cn_msg][w1_netlink_msg][w1_netlink_cmd]
cn_msg.len = sizeof(struct w1_netlink_msg) +
           sizeof(struct w1_netlink_cmd) +
           cmd->len;
w1_netlink_msg.len = sizeof(struct w1_netlink_cmd) + cmd->len;
w1_netlink_cmd.len = cmd->len;

对 W1_LIST_MASTERS 的回复应向用户空间发送一条消息,其中包含所有已注册主设备 ID 的列表,格式如下

cn_msg (CN_W1_IDX.CN_W1_VAL as id, len is equal to sizeof(struct
w1_netlink_msg) plus number of masters multiplied by 4)
w1_netlink_msg (type: W1_LIST_MASTERS, len is equal to
        number of masters multiplied by 4 (u32 size))
id0 ... idN

每条消息最大为 4k 字节,因此如果主设备数量超过此限制,它将被拆分为多条消息。

W1 搜索和警报搜索命令。

请求

[cn_msg]
  [w1_netlink_msg type = W1_MASTER_CMD
      id is equal to the bus master id to use for searching]
  [w1_netlink_cmd cmd = W1_CMD_SEARCH or W1_CMD_ALARM_SEARCH]

回复

[cn_msg, ack = 1 and increasing, 0 means the last message,
      seq is equal to the request seq]
[w1_netlink_msg type = W1_MASTER_CMD]
[w1_netlink_cmd cmd = W1_CMD_SEARCH or W1_CMD_ALARM_SEARCH
      len is equal to number of IDs multiplied by 8]
[64bit-id0 ... 64bit-idN]

每个头中的长度对应于其后数据的大小,因此 w1_netlink_cmd->len = N * 8;其中 N 是此消息中 ID 的数量。可以为零。

w1_netlink_msg->len = sizeof(struct w1_netlink_cmd) + N * 8;
cn_msg->len = sizeof(struct w1_netlink_msg) +
            sizeof(struct w1_netlink_cmd) +
            N*8;

W1 重置命令

[cn_msg]
  [w1_netlink_msg type = W1_MASTER_CMD
      id is equal to the bus master id to use for searching]
  [w1_netlink_cmd cmd = W1_CMD_RESET]

命令状态回复

每个命令(无论是根命令、主命令还是带或不带 w1_netlink_cmd 结构的从命令)都将由 w1 核心进行“确认”。回复的格式与请求消息相同,只是长度参数不计入用户请求的数据,即读/写/触摸 IO 请求不包含数据,因此 w1_netlink_cmd.len 将为 0,w1_netlink_msg.len 将是 w1_netlink_cmd 结构的大小,cn_msg.len 将等于 struct w1_netlink_msgstruct w1_netlink_cmd 大小之和。如果回复是为不带 w1_netlink_cmd 的主命令或根命令生成的,则回复将只包含 cn_msg 和 w1_netlink_msg 结构。

w1_netlink_msg.status 字段将携带正错误值(例如 EINVAL)或成功时的零值。

每个结构中的所有其他字段将镜像请求消息中的相同参数(除了如上所述的长度)。

对于嵌入在 w1_netlink_msg 中的每个 w1_netlink_cmd,都会生成状态回复;如果没有 w1_netlink_cmd 结构,则为 w1_netlink_msg 生成回复。

每个 w1_netlink_msg 中的所有 w1_netlink_cmd 命令结构都将被处理,即使存在错误,也只有长度不匹配才会中断消息处理。

w1 核心收到新命令时的操作步骤

当收到新消息 (w1_netlink_msg) 时,w1 核心会根据 w1_netlink_msg.type 字段检测它是主请求还是从请求。然后搜索主设备或从设备。找到后,主设备(请求的或发现从设备的那个)会被锁定。如果请求从命令,则启动复位/选择过程以选择给定设备。

然后 w1_netlink_msg 中请求的所有操作都会逐一执行。如果命令需要回复(如读取命令),则在命令完成后发送。

当所有命令 (w1_netlink_cmd) 处理完毕后,主设备将被解锁,并开始处理下一个 w1_netlink_msg 头。

连接器 [1] 特定文档

每个连接器消息包含两个 u32 字段作为“地址”。w1 使用在 include/linux/connector.h 头文件中定义的 CN_W1_IDX 和 CN_W1_VAL。每条消息还包含序列号和确认号。事件消息的序列号是适当的总线主设备序列号,随着通过该主设备发送的每个事件消息而增加。用户空间请求的序列号由用户空间应用程序设置。回复的序列号与请求中的相同,确认号设置为 seq+1。

附加文档、源代码示例

  1. 内核连接器

  2. http://www.ioremap.net/archive/w1

    该归档文件包含用户空间应用程序 w1d.c,它使用读/写/搜索命令来操作总线上找到的所有主/从设备。