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

消息类型

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:主机顺序的8字节从设备唯一ID,或主设备的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将等于sizeof(struct w1_netlink_msg) 和 sizeof(struct w1_netlink_cmd)之和。如果为没有附加w1_netlink_cmd的主设备或根命令生成回复,则回复将仅包含cn_msg和w1_netlink_msg结构。

w1_netlink_msg.status 字段将携带正错误值(例如EINVAL),如果成功则为零。

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

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

每个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,该应用程序对总线上找到的所有主/从设备使用读取/写入/搜索命令。