热插拔消息传递模型
热插拔概述
热插拔设备指支持带电操作的一类设备,允许用户不关闭系统、不切断电源情况下取出或更换设备。热插拔系统用于管理、监控系统中所有热插拔设备的插入、拔出状态,从而能够让系统内部自动完成此类设备的创建、删除而无需用户手动处理。同时,热插拔系统会收集热插拔相关信息,供应用程序使用。
如下图所示,SylixOS 中有一个名称为“t_hotplug”的内核线程,设备的热插拔状态通过事件的方式报告给该线程,对设备的创建或删除工作均由该线程处理。系统会创建一个名为“/dev/hotplug”的虚拟设备,它负责收集相关的热插拔消息,应用程序可通过读取“/dev/hotplug”设备,获得自己关心的热插拔消息。
热插拔消息
SylixOS 定义了常见的热插拔设备消息,如 USB 设备、SD 设备、PCI 设备等。此外,还定义了网络的连接与断开、电源的连接状态改变等与热插拔行为相似的消息。
如下图可知,消息的前 4 个字节标识了消息的类型。SylixOS 中已经定义了 USB 键盘、USB 鼠标、SD 存储卡、SDIO 无线网卡等热插拔类型。在实际的硬件平台上,设备驱动也可以定义自己的热插拔消息类型。
第 5 个字节为设备状态,0 表示拔出状态,1 表示插入状态。
第 6 个字节开始,表示设备的名称,其内容为一个以‘\0’结束的字符串,应用程序应该以此为结束符得到完整的名称。该名称为一个设备的完整路径名称,如“/dev/ttyUSB0”、“/media/sdcard0”等。由于在 SylixOS 中一个完整路径名称的最大长度为 512 字节,加上结束字符‘\0’,因此,“dev name”字段的最大长度为 513 字节。
设备名称(‘\0’字符结尾)后的是 4 个可用于灵活扩展的参数,均为 4 字节长度。这 4 个参数可适应不同设备消息的特殊处理。SylixOS 未规定每个参数的具体用法和存储格式(大端或小端),完全由设备驱动定义。
因此,一个热插拔消息的最大长度为:4 + 1 + 513 + 4 + 4 + 4 + 4 = 534 字节。
处理热插拔消息
应用程序可通过读取“/dev/hotplug”设备获取热插拔消息,如以下程序所示,代码说明应用层如何获取热插拔消息。
#include <SylixOS.h>
int main (int argc, char *argv[])
{
……
iFd = open("/dev/hotplug", O_RDONLY);
if (iFd < 0) {
fprintf(stderr, "open /dev/hotplug failed.\n");
return (-1);
}
while (1) {
sstReadLen = read(iFd, pucMsgBuff, MSG_LEN_MAX);
if (sstReadLen < 0) {
fprintf(stderr, "read hotplug message error.\n");
close(iFd);
return (-1);
}
/*
* 解析热插拔消息
*/
pucTemp = pucMsgBuff;
iMsgType = (pucTemp[0] << 24)
| (pucTemp[1] << 16)
| (pucTemp[2] << 8)
| (pucTemp[3]);
pucTemp += 4;
bInsert = *pucTemp ? TRUE : FALSE;
pucTemp += 1;
pcDevName = (CHAR *) pucTemp;
pucArg = pucTemp + strlen(pcDevName) + 1;
printf( "get new hotplug message >>\n"
" message type: %d\n"
" device status: %s\n"
" device name: %s\n"
" arg0: 0x%01x%01x%01x%01x\n"
" arg1: 0x%01x%01x%01x%01x\n"
" arg2: 0x%01x%01x%01x%01x\n"
" arg3: 0x%01x%01x%01x%01x\n", iMsgType,
bInsert ? "insert" : "remove", pcDevName, pucArg[0], pucArg[1],
pucArg[2], pucArg[3], pucArg[4], pucArg[5], pucArg[6],
pucArg[7], pucArg[8], pucArg[9], pucArg[10], pucArg[11],
pucArg[12], pucArg[13], pucArg[14], pucArg[15]);
}
……
}
以上程序的代码分析如下:
- 打开 “/dev/hotplug” 热插拔设备。
- 循环读取该设备中的热插拔消息。
- 解析热插拔消息并输出打印。
应用程序在解析消息类型时,需要按照大端数据存储格式进行解析,即低地址的字节代表的是高字节数据。消息的额外参数的起始地址即为设备名称起始地址加上其长度和结束字符的地址。程序运行后,插入或拔出 SD 存储卡,会打印如下的信息:
插入 SD 存储卡:
get new hotplug message >>
message type: 346
device status: insert
device name: /media/sdcard0
arg0: 0x0000
arg1: 0x0000
arg2: 0x0000
arg3: 0x0000
拔出 SD 存储卡:
get new hotplug message >>
message type: 346
device status: remove
device name: /media/sdcard0
arg0: 0x0000
arg1: 0x0000
arg2: 0x0000
arg3: 0x0000
上面显示消息类型的值为十进制的 346,对比“SylixOS/system/hotplugLib/hotplugLib.h”文件中定义的消息类型,346 对应的为 LW_HOTPLUG_MSG_SD_STORAGE(0x0100+90),表示是 SD 存储卡设备的热插拔消息。消息中的设备名称为/media/sdcard0,是 SylixOS 中 SD 存储卡的标准命名方式,此外其他的存储设备也会默认挂载在/media/目录下,如 U 盘的名称为/media/udisk0。其他 4 个参数的值均为 0,说明 SD 存储卡对应的热插拔消息并未使用这个额外参数(实际上,大部分热插拔消息都未使用额外参数)。
SylixOS 定义的热插拔消息
SylixOS 已经定义的热插拔消息如下表所示。
热插拔设备 | 热插拔消息 |
---|---|
USB 热插拔消息类型 | USB 键盘 |
USB 热插拔消息类型 | USB 鼠标 |
USB 热插拔消息类型 | USB 触摸屏 |
USB 热插拔消息类型 | USB 打印机 |
USB 热插拔消息类型 | USB 大容量设备 |
USB 热插拔消息类型 | USB 网络适配器 |
USB 热插拔消息类型 | USB 声卡 |
USB 热插拔消息类型 | USB 串口 |
USB 热插拔消息类型 | USB 摄像头 |
USB 热插拔消息类型 | USB HUB |
USB 热插拔消息类型 | USB 用户自定义设备 |
SD 热插拔消息类型 | SDIO 串口 |
SD 热插拔消息类型 | SDIO 蓝牙 TYPE-A |
SD 热插拔消息类型 | SDIO 蓝牙 TYPE-B |
SD 热插拔消息类型 | SDIO GPS |
SD 热插拔消息类型 | SDIO 摄像头 |
SD 热插拔消息类型 | SDIO 标准 PHS 设备 |
SD 热插拔消息类型 | SDIO 无线网卡 |
SD 热插拔消息类型 | SDIO 转 ATA 接口 |
SD 热插拔消息类型 | SD 存储卡 |
SD 热插拔消息类型 | SD/SDIO 用户自定义设备 |
PCI/PCI-E 热插拔消息类型 | PCI(E) 存储设备 |
PCI/PCI-E 热插拔消息类型 | PCI(E) 网络适配器 |
PCI/PCI-E 热插拔消息类型 | PCI(E) 声卡 |
PCI/PCI-E 热插拔消息类型 | PCI(E) 摄像头 |
PCI/PCI-E 热插拔消息类型 | PCI(E) VGA XGA 3D |
PCI/PCI-E 热插拔消息类型 | PCI(E) VIDEO AUDIO PHONE |
PCI/PCI-E 热插拔消息类型 | PCI(E) RAM FLASH |
PCI/PCI-E 热插拔消息类型 | PCI(E) 桥连器 |
PCI/PCI-E 热插拔消息类型 | PCI(E) 串/并口 调制解调器等 |
PCI/PCI-E 热插拔消息类型 | PCI(E) 系统类设备 |
PCI/PCI-E 热插拔消息类型 | PCI(E) 鼠标键盘等输入设备 |
PCI/PCI-E 热插拔消息类型 | PCI(E) Docking |
PCI/PCI-E 热插拔消息类型 | PCI(E) 处理器 |
PCI/PCI-E 热插拔消息类型 | PCI(E) PCI 串行通信 |
PCI/PCI-E 热插拔消息类型 | PCI(E) INTELLIGENT |
PCI/PCI-E 热插拔消息类型 | PCI(E) 卫星通信 |
PCI/PCI-E 热插拔消息类型 | PCI(E) 加密系统 |
PCI/PCI-E 热插拔消息类型 | PCI(E) 信号处理系统 |
PCI/PCI-E 热插拔消息类型 | PCI(E) 用户自定义设备 |
SATA 热插拔消息 | SATA 硬盘 |
SATA 热插拔消息 | SATA 用户自定义设备 |
网络连接状态 | 网络连接状态变化 |
电源连接状态 | 电源连接状态变化 |
用户自定义热插拔事件 | 接收所有热插拔信息 |
用户自定义热插拔事件 | 用户自定义类型设备 |