Chinaunix首页 | 论坛 | 博客
  • 博客访问: 55817
  • 博文数量: 8
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 105
  • 用 户 组: 普通用户
  • 注册时间: 2015-06-19 10:45
个人简介

分享笔者从事嵌入式工作几年来在Linux, SylixOS等操作系统中关于内核、驱动框架以及各种中间件开发和设计的技术。

文章分类
文章存档

2015年(8)

我的朋友

分类: 嵌入式

2015-08-21 16:19:00

SylixOS 热插拔系统

1.1      热插拔系统简介

  热插拔系统用于管理、监控系统中所有热插拔设备的插入/拔出状态,从而能够让系统内部自动完成此类设备的创建/删除工作,无需用户手动处理。同时,热插拔系统还会收集热插拔相关信息,供应用程序使用。




  1.1  热插拔系统总体结构


  如 1.1所示,SylixOS系统中有一个名称为“t_hotplug”的内核线程,设备的热插拔状态通过事件的方式报告给该线程,对设备的创建/删除工作均由该线程处理。某些设备不能产生热插拔事件(如没有插拔中断检测引脚的设备),可以向系统注册热插拔检测函数,t_hotplug线程会定期调用注册的函数以完成热插拔检测,即轮询检测(对应上图中的poll模块)。系统中还有一个名为“/dev/hotplug”的虚拟设备,它负责收集相关热插拔消息,通常情况下热插拔消息来自于t_hotplug线程,也有可能来自于设备驱动程序。应用程序可通过读取/dev/hotplug设备,获得自己关心的热插拔消息。

SylixOS定义了当前常见的热插拔设备消息,如USBSDPCI等。此外,还有网络的连接与断开、电源的连接状态改变等与热插拔行为相似的消息。

1.2      热插拔消息

1.2.1   热插拔消息的格式


 1.2  热插拔消息格式

 如上图所示,消息的前4个字节标识了消息的类型,为大端格式。当前定义的消息类型位于SylixOS/system/hotplugLib/hotplugLib.h文件,如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字节。

1.2.2   处理热插拔消息

 下面将通过一个具体的例子介绍如何通过/dev/hotplug设备获取并处理热插拔消息。

程序清单 1.1  处理热插拔消息示例


  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. #define MSG_LEN_MAX    534
  5.  
  6. int main(int argc, char *argv[])
  7. {
  8.     UINT8    pucMsgBuff[MSG_LEN_MAX];
  9.     INT      iFd;
  10.     INT      iMsgType;
  11.     BOOL     bInsert;
  12.     CHAR    *pcDevName;
  13.     UINT8   *pucArg;
  14.     UINT8   *pucTemp;
  15.     ssize_t  sstReadLen;
  16.  
  17.     iFd = open("/dev/hotplug", O_RDONLY);
  18.     if (iFd < 0) {
  19.         fprintf(stderr, "open /dev/hotplug failed.\n");
  20.         return (-1);
  21.     }
  22.  
  23.     while (1) {
  24.         sstReadLen = read(iFd, pucMsgBuff, MSG_LEN_MAX);
  25.         if (sstReadLen < 0) {
  26.             fprintf(stderr, "read hotplug message error.\n");
  27.             close(iFd);
  28.             return (-1);
  29.         }
  30.         if (sstReadLen < 5) {
  31.             continue;
  32.         }

  33.         /*
  34.          * 解析热插拔消息
  35.          */
  36.         pucTemp = pucMsgBuff;
  37.         iMsgType = (pucTemp[0] << 24)
  38.                  | (pucTemp[1] << 16)
  39.                  | (pucTemp[2] << 8)
  40.                  | (pucTemp[3]);
  41.  
  42.         pucTemp += 4;
  43.         bInsert  = *pucTemp ? TRUE : FALSE;
  44.  
  45.         pucTemp  += 1;
  46.         pcDevName = (CHAR *)pucTemp;
  47.  
  48.         pucArg = pucTemp + strlen(pcDevName) + 1;
  49.  
  50.         printf("get new hotplug message >>\n"
  51.                " message type: %d\n"
  52.                 "device status: %s\n"
  53.                 " device name: %s\n"
  54.                 " arg0: 0x%01x%01x%01x%01x\n"
  55.                 " arg1: 0x%01x%01x%01x%01x\n"
  56.                 " arg2: 0x%01x%01x%01x%01x\n"
  57.                 " arg3: 0x%01x%01x%01x%01x\n",
  58.                 iMsgType,
  59.                 bInsert ? "insert" : "remove",
  60.                 pcDevName,
  61.                 pucArg[0],  pucArg[1],  pucArg[2],  pucArg[3],
  62.                 pucArg[4],  pucArg[5],  pucArg[6],  pucArg[7],
  63.                 pucArg[8],  pucArg[9],  pucArg[10], pucArg[11],
  64.                 pucArg[12], pucArg[13], pucArg[14], pucArg[15]);
  65.     }
  66.  
  67.     close(iFd);
  68.     return (0);
  69. }


 在上面的程序中,对获得的热插拔消息进行了简单的错误处理,即消息长度至少应该为5个字节长,因为一个热插拔消息必然包含消息类型和设备的插入/拔出状态两个信息。注意程序中处理消息类型时,需要按照大端数据存储格式进行解析,即低地址的字节代表的是高字节数据。消息的额外参数的起始地址即为设备名称起始地址加上其长度和结束字符的地址。程序运行后,假如我们插入或拔出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文件中定义的消息类型,等于LW_HOTPLUG_MSG_SD_STORAGE0x0100+90),这正代表SD存储卡设备的热插拔消息。消息中的设备名称为/media/sdcard0,这是SylixOSSD存储卡的标准命名方式,此外其他的存储设备也会默认挂载在/media目录下,如U盘的名称即为/media/udisk04个额外参数的值均为0,说明SD存储卡对应的热插拔消息并未使用这个额外参数(实际上,大部分热插拔消息都未使用额外参数)

 上面的程序为一个通用的检测系统中所有热插拔消息的示例,没有针对具体的消息类型处理对应的额外参数信息,仅仅将其值以十六进制的方式打印出来。由于/dev/hotplug设备能够被任何程序多次打开,因此在实际使用中,一个程序通常只需要读取自己关心的热插拔消息类型即可,比如SylixOS中的xinput模块,它只监测输入设备的状态,如USB鼠标、USB键盘等。

       

阅读(1960) | 评论(0) | 转发(0) |
0

上一篇:CAN协议基础应用

下一篇:没有了

给主人留下些什么吧!~~