请教大家一个最基本的问:
这两天研究了一下串口驱动程序(MDD,PDD),发现这么一个问题:CreateFile(L"COM1:",....)中的"COM1"的信息是怎样记录到COM_Open()的句柄中的。COM_init()(有DeviceArrayIndex和Priority256)和HWinit(有memory window,interrupt,physical base) 中好像没有对COM index的记录?有的话,麻烦指点下!,COM_Read()又是如何判断要读数据的口是COM1还是其他口的呢?我看了好几遍了都没看明白 ,请高手指点下!不胜感激!
L"COM1:"参数,就是用于COM_Read判断的
应该去研究CreateFile创建的句柄中,COM1:对应于什么信息,这个信息就是以后相关API判断操作那个文件或设备的依据。
不知道我有没有理解LZ的问题
HANDLE COM_Init(
ULONG Identifier
);
这个吧
二楼说的也对,但是就是不知道COM_Read是根据那个记录信息来判断的.
COM_Read()代码开始是对参数检查,包括对存取权限,OpenCnt等。之后计算超时时间,如果设定了超时读取动作会在超时后返回,不管是否读到了足够长度的数据。随后就是简单对软件缓冲进行读取的操作了,读取的操作是在RX_CS中完成的。最后在读取的过程中需要处理流控制的成本了,包括软件流和硬件流. 那么它从软件缓冲读取数据时,怎么知道是哪个口的数据呢?
你在 COM_Init(ULONG Identifier) 中, 應可透過 OpenDeviceKey 來得到其 registry setting (若不知如何使用, 請參考 %_WINCEROOT%\PUBLIC\COMMON\OAK\DRIVERS\SERIAL\COM_MDD2\mdd2.c 的程式). 如此即可得知其載入的 Index, 或是透過 RegOpenKeyEx(HKEY_LOCAL_MACHINE, Identifier, ...) 的方式, 來直接得到 "Activate" 的值, 將值記錄在 COM_Init 的回傳值 (return value) 中, 該值即為 COM_Open 的第一個 parameter, 而 COM_Open 的回傳值, 即為 COM_Read 的 first parameter.
Paul, Chao @ Techware
Paul,chao,我的两个真实串口的注册表如下:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Serial]
"Order"=dword:0
"InterfaceType"=dword:0
"IoBase"=dword:10030000
"IoLen"=dword:20
"Irq"=dword:9
"DeviceArrayIndex"=dword:0
"Prefix"="COM"
"Index"=dword:3
"Dll"="Serial.dll"
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Serial2]
"Order"=dword:0
"InterfaceType"=dword:0
"IoBase"=dword:10031000
"IoLen"=dword:20
"Irq"=dword:8
"DeviceArrayIndex"=dword:1
"Prefix"="COM"
"Index"=dword:2
"Dll"="Serial.dll"
我研究了一下mdd.c中的COM_Init()发现没有对COM Index的记录呀
DEBUGMSG (ZONE_INIT,(TEXT("Try to open %s\r\n"), (LPCTSTR)Identifier));
hKey = OpenDeviceKey((LPCTSTR)Identifier);
if ( !hKey ) {DEBUGMSG (ZONE_INIT | ZONE_ERROR,(TEXT("Failed to open devkeypath, COM_Init failed\r\n")));
LocalFree(pSerialHead);
return(NULL);
}
datasize = sizeof(DWORD);
if ( RegQueryValueEx(hKey, L"有这个DeviceArrayIndex", NULL, &kvaluetype,(LPBYTE)&DevIndex, &datasize) ) {
DEBUGMSG (ZONE_INIT | ZONE_ERROR,(TEXT("Failed to get DeviceArrayIndex value, COM_Init failed\r\n")));
RegCloseKey (hKey);
LocalFree(pSerialHead);
return(NULL);
}
datasize = sizeof(DWORD);
if ( RegQueryValueEx(hKey, L"有这个Priority256", NULL, &kvaluetype,
(LPBYTE)&pSerialHead->Priority256, &datasize) ) {
pSerialHead->Priority256 = DEFAULT_CE_THREAD_PRIORITY;
DEBUGMSG (ZONE_INIT | ZONE_WARN,(TEXT("Failed to get Priority256 value, defaulting to %d\r\n"), pSerialHead->Priority256));
}
RegCloseKey (hKey);
DEBUGMSG (ZONE_INIT,
(TEXT("DevIndex %X\r\n"), DevIndex));
// Initialize hardware dependent data.
pSerialHead->pHWObj = GetSerialObject( DevIndex );
if ( !pSerialHead->pHWObj ) {
DEBUGMSG(ZONE_ERROR | ZONE_INIT,
(TEXT("Error in GetSerialObject, COM_Init failed\n\r")));
LocalFree(pSerialHead);
return(NULL);
}
DEBUGMSG (ZONE_INIT, (TEXT("About to call HWInit(%s,0x%X)\r\n"),Identifier, pSerialHead));
pHWHead = pSerialHead->pHWObj->pFuncTbl->HWInit(Identifier, pSerialHead, pSerialHead->pHWObj);
pSerialHead->pHWHead = pHWHead;
只有DeviceArrayIndex和Priority256
况且即使有,按照流驱动的加载顺序:
1)加载驱动。在当系统启动时,设备管理器搜寻注册表的HKEY_LOCAL_MACHINE\Driver\BuiltIn键下面的子键,并逐一加载子键下的每个驱动,此过程叫BusEnum。
2)设备管理器从注册表的dll键值中获取驱动程序所在的DLL文件名。
3)设备管理器调用LoadDriver()函数把DLL加载到自己的虚拟地址空间内。
4)设备管理器在注册表的HKEY_LOCAL_MACHINE\Driver\Active下面,记录所有已经加载的驱动程序[2]。
5)设备管理器调用驱动中的XXX_Init()函数。
6)在XXX_Init()中,通常对硬件进行一些基本的初始化操作。通过以上6步,流接口驱动被成功加载。
7)应用程序使用该设备。首先它调用CreateFile()打开设备。CreateFile()是在FileSys.exe中实现的。但是FileSys.exe只作简单判断,如果发现打开的设备驱动程序而不是一个文件,那么就重新把主动权交还给设备管理器。
由此可见COM_Init()的执行要先于CreateFile(),那么COM_Init()执行完毕之后我注册表中的两个个串口的Index会同时被记录的呀