• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            唐吉訶德

              C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              5 Posts :: 75 Stories :: 3 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(2)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            1. PDD層代碼簡單分析

            PDD層的主要包含了以下2個類:CSerialPDDPowerUpCallback, CSerialPDD, 下面簡單的分析這2個類的作用。

            1.1 CSerialPDDPowerUpCallback

            CSerialPDDPowerUpCallback 類用于串口電源上電時的處理。

            在調(diào)用CSerialPDD::Init()后會創(chuàng)建一個CSerialPDDPowerUpCallback類型的對象

            在CSerialPDD::PowerOn()函數(shù)中會調(diào)用此對象的SignalCallBack()函數(shù), 這樣RunThread就開始運行, 進而通過調(diào)用CSerialPDD::NotifyPDDInterrupt()進行后續(xù)處理, 包括調(diào)用

            CeEventHasOccurred (NOTIFICATION_EVENT_RS232_DETECTED, NULL) 通知系統(tǒng)有串口被探測到.

            以及調(diào)用SerialEventHandler()進行MDD層上的處理.

            更詳細的細節(jié)可以參考微軟的源代碼:

            %WINCEROOT%\PUBLIC\COMMON\OAK\DRIVERS\SERIAL\SERPDDCM\cserpdd.cpp

            %WINCEROOT%\PUBLIC\COMMON\OAK\INC\cserpdd.h

            2.2 CSerialPDD

            CSerialPDD 是串口PDD層的關(guān)鍵,實現(xiàn)對硬件的操作,開發(fā)者開發(fā)的驅(qū)動就是繼承這個類,并實現(xiàn)重載相關(guān)的函數(shù)來完成特定設(shè)備的PDD功能的。

            這個類抽象了以下這些接口:

            //  Tx Function.

                virtual BOOL    InitXmit(BOOL bInit) = 0;

                virtual void    XmitInterruptHandler(PUCHAR pTxBuffer, ULONG *pBuffLen) = 0;

                virtual void    XmitComChar(UCHAR ComChar) = 0;

                virtual BOOL    EnableXmitInterrupt(BOOL bEnable)= 0;

                virtual BOOL    CancelXmit() = 0 ;

            //  Rx Function.

                virtual BOOL    InitReceive(BOOL bInit) = 0;

                virtual ULONG   ReceiveInterruptHandler(PUCHAR pRxBuffer,ULONG *pBufflen) = 0;

                virtual ULONG   CancelReceive() = 0;

            //  Modem

                virtual BOOL    InitModem(BOOL bInit) = 0;

                virtual void    ModemInterruptHandler()= 0; // This is Used to Indicate Modem Signal Changes.

                virtual ULONG   GetModemStatus() = 0;

                virtual void    SetDTR(BOOL bSet)= 0;

                virtual void    SetRTS(BOOL bSet)= 0;

                virtual BOOL    IsCTSOff() {  return ((GetModemStatus() & MS_CTS_ON)==0) ; };

                virtual BOOL    IsDSROff() {  return ((GetModemStatus() & MS_DSR_ON)==0) ; };

            //  Line Function

                virtual BOOL    InitLine(BOOL bInit) = 0;

                virtual void    LineInterruptHandler() = 0;

                virtual void    SetBreak(BOOL bSet) = 0 ;   

                virtual BOOL    SetBaudRate(ULONG BaudRate,BOOL bIrModule) = 0;

                virtual BOOL    SetByteSize(ULONG ByteSize) = 0;

                virtual BOOL    SetParity(ULONG Parity)= 0;

                virtual BOOL    SetStopBits(ULONG StopBits)= 0;

                以上這些接口都是純虛函數(shù), 在實現(xiàn)PDD層時, 必須實現(xiàn)這些接口.

            當然不需要的功能你可以簡單的用類似virtual BOOL func() {;} 的形式來實現(xiàn)。

            其他的非純虛函數(shù)的虛函數(shù)也可以被用戶重載, 以實現(xiàn)自己特定的功能。

                我們知道PDD層的函數(shù)為如下函數(shù):

            GetSerialObject

             This function returns a pointer to a HWOBJ structure. The structure contains the function pointers and parameters for the hardware interface functions of the relevant lower layer.

            HWClearBreak

             This function clears an RS-232 line break condition.

            HWClearDTR

             This function clears the Data Terminal Ready (DTR) signal.

            HWClearRTS

             This function clears the Request to Send (RTS) signal.

            HWClose

             This function closes the device initialized by the HWInit function.

            HWDeinit

             This function is called by the upper layer to de-initialize the hardware when a device driver is unloaded.

            HWDisableIR

             This function disables the infrared (IR) serial interface.

            HWEnableIR

             This function enables the infrared (IR) serial interface.

            HWGetCommProperties

             This function retrieves the current properties of the communications device.

            HWGetIntrType

             This function returns the current interrupt type.

            HWGetModemStatus

             This function retrieves the modem status.

            HWGetRxBufferSize

             This function returns the maximum number of bytes that the hardware buffer can hold, not including the padding, stop, and start bits.

            HWGetRxStart

             This function returns the start of the hardware-receive buffer.

            HWGetStatus

             This function specifies the hardware status API.

            HWInit

             This function initializes a serial device.

            HWIoctl

             This function executes device I/O control (IOCTL) routines.

            HWLineIntrHandler

             This function handles line interrupts for serial port devices.

            HWModemIntrHandler

             This function handles the modem interrupt. In the serial port upper layer implementation available in Microsoft Windows CE 3.0 and later, this function replaces the HWOtherIntrHandler function.

            HWOpen

             This function is called by the upper layer to open the serial device.

            HWOtherIntrHandler

             In Windows CE 3.0 and later, this function has been replaced with the new function HWModemIntrHandler.

            HWPostInit

             This function performs necessary operations after it initializes all data structures and prepares the serial IST to begin handling interrupts. It is called by the upper layer.

            HWPowerOff

             This function notifies the platform-dependent driver that the hardware platform is about to enter suspend mode. It is called by the model device driver (MDD).

            HWPowerOn

             This function notifies the platform-dependent driver that the hardware platform is resuming from suspend mode. It is called by the MDD.

            HWPurgeComm

             This function purges the communications device.

            HWPutBytes

             This function writes bytes to hardware. The driver calls this function.

            HWReset

             This function resets the hardware API.

            HWRxIntrHandler

             This function handles serial port interrupts.

            HWSetBreak

             This function sets the line break condition on the transmit line.

            HWSetCommTimeouts

             This function sets the communications time-out events in response to a call to the SetCommTimeouts function.

            HWSetDCB

             This function sets the device control block.

            HWSetDTR

             This function sets the Data Terminal Ready (DTR) signal.

            HWSetRTS

             This function sets the Request to Send (RTS) signal.

            HWTxIntrHandler

             This function handles the transmit interrupt for serial port devices.

            HWXmitComChar

             This function transmits a single character.

            更具體的細節(jié)可以參考:MSDN幫助 ms-help://MS.WindowsCE.500/wceddk5/html/wce50grfserialportdriverfunctions.htm

                微軟用一堆SerXXXXX()的函數(shù)封裝了CSerialPdd相關(guān)的操作,來完成PDD功能。

            2. PDD與MDD層的交互

            2.1 PDD層的函數(shù)是如何能夠被MDD層所調(diào)用

            1.2節(jié)介紹的那一堆SerXXXXX()函數(shù)會被記錄到一個函數(shù)指針表里,真是通過這個函數(shù)指針表來實現(xiàn)與MDD層的交互的。此函數(shù)指針表是HW_VTBL類型的, 在微軟的代碼里是命名為IoVTbl的函數(shù)指針表。

                MDD層通過調(diào)用 GetSerialObject(DWORD DeviceArrayIndex)函數(shù)來獲取一個HWOBJ結(jié)構(gòu)的指針, 這個結(jié)構(gòu)包含以下成員:

                ULONG  BindFlags; // Flags controlling MDD behaviour.  Se above.

                DWORD   dwIntID;   // Interrupt Identifier used if THREAD_AT_INIT or THREAD_AT_OPEN

                PHW_VTBL   pFuncTbl;

                其中pFuncTbl正是指向我們之前說到的 IoVTbl 函數(shù)指針結(jié)構(gòu)的地址.

            這樣MDD層就可以通過->pFuncTbl.DDSIFunction()來對特定的硬件做特定的操作了.

            2.2 GetSerialObject函數(shù)

            這個函數(shù)的原型是:PHWOBJ GetSerialObject(DWORD DeviceArrayIndex) ,它是連接MDD和PDD層的關(guān)鍵函數(shù), 也是實現(xiàn)多端口驅(qū)動的關(guān)鍵, 這個函數(shù)允許一個MDD層連接多個PDD層。

            在MDD層的COM_Init函數(shù)中,驅(qū)動會通過查詢DeviceArrayIndex鍵值, 得到我們需要打開的是普通串口或者是其他種類的串口設(shè)備。

            而正是這個數(shù)值決定了GetSerialObject是返回哪個串口的PHWOBJ指針, PHWOBJ包含了pFuncTbl,這個正是前一節(jié)說到的PDD層函數(shù)指針表,通過這個函數(shù)表我們就可以實現(xiàn)對相應(yīng)的串口設(shè)備進行操作。(串口有可能是標準的串口,也有可能是紅外設(shè)備)

            2.3 CreateSerialObject 函數(shù)

            如果開發(fā)者選擇直接繼承微軟CSerialPdd類來實現(xiàn)串口的PDD層,還要實現(xiàn)CreateSerialObject及DeleteSerialObject函數(shù)。

            在MDD層的COM_Init函數(shù)被調(diào)用時,驅(qū)動會通過查詢注冊表來得到相關(guān)參數(shù)并調(diào)用PDD層的HWInit函數(shù),HWInit函數(shù)又會調(diào)用CreateSerialObject來初始化串口設(shè)備,在關(guān)閉串口以后DeleteSerialObject函數(shù)會被調(diào)用。

            3. 其他

            3.1 COM_Init函數(shù)如何被調(diào)用

            此函數(shù)通常是由Device.exe進程調(diào)用的, 而此函數(shù)的參數(shù)Identifier 是一個指向注冊表HKEY_LOCAL_MACHINE\Drivers\Active.下的一個鍵值,這也是決定驅(qū)動如何操作硬件的關(guān)鍵。

            對于使用ActivateDeviceEx函數(shù)調(diào)用的情況,請參照MSND, http://msdn.microsoft.com/en-us/library/aa447677.aspx

            3.2 相關(guān)代碼段:

            view plaincopy to clipboardprint?

            HANDLE 

            COM_Init(  

                    ULONG   Identifier  

                    )  

            {  

                PVOID           pHWHead     = NULL;  

                PHW_INDEP_INFO  pSerialHead = NULL;  

                ULONG           HWBufferSize;  

                DWORD           DevIndex;  

                HKEY            hKey;  

                ULONG           kreserved = 0, kvaluetype;  

                ULONG           datasize = sizeof(ULONG);  

                /* 

                 *  INTERNAL: this routine initializes the hardware abstraction interface 

                 *  via HWInit(). It allocates a data structure representing this 

                 *  instantiation of the device. It also creates an event and initializes 

                 *  a critical section for receiving as well as registering the logical 

                 *  interrupt dwIntID with NK via InterruptInitialize. This call 

                 *  requires that the hardware dependent portion export apis that return 

                 *  the physical address of the receive buffer and the size of that buffer. 

                 *  Finally, it creates a buffer to act as an intermediate 

                 *  buffer when receiving. 

                 */ 

                DEBUGMSG (ZONE_INIT | ZONE_FUNCTION, (TEXT("+COM_Init\r\n")));  

                // Allocate our control structure.  

                pSerialHead  =  (PHW_INDEP_INFO)LocalAlloc(LPTR, sizeof(HW_INDEP_INFO));  

                // Check that LocalAlloc did stuff ok too.  

                if ( !pSerialHead ) {  

                    DEBUGMSG(ZONE_INIT | ZONE_ERROR,  

                             (TEXT("Error allocating memory for pSerialHead, COM_Init failed\n\r")));  

                    return(NULL);  

                }  

                // Initially, open list is empty.  

                InitializeListHead( &pSerialHead->OpenList );  

                InitializeCriticalSection(&(pSerialHead->OpenCS));  

                pSerialHead->pAccessOwner = NULL;  

                pSerialHead->fEventMask = 0;  

                // Init CommTimeouts.  

                pSerialHead->CommTimeouts.ReadIntervalTimeout = READ_TIMEOUT;  

                pSerialHead->CommTimeouts.ReadTotalTimeoutMultiplier =  

                READ_TIMEOUT_MULTIPLIER;  

                pSerialHead->CommTimeouts.ReadTotalTimeoutConstant =  

                READ_TIMEOUT_CONSTANT;  

                pSerialHead->CommTimeouts.WriteTotalTimeoutMultiplier=  0;  

                pSerialHead->CommTimeouts.WriteTotalTimeoutConstant =   0;  

                /* Create tx and rx events and stash in global struct field. Check return. 

                 */ 

                pSerialHead->hSerialEvent = CreateEvent(0,FALSE,FALSE,NULL);  

                pSerialHead->hKillDispatchThread = CreateEvent(0, FALSE, FALSE, NULL);  

                pSerialHead->hTransmitEvent = CreateEvent(0, FALSE, FALSE, NULL);  

                pSerialHead->hReadEvent = CreateEvent(0, FALSE, FALSE, NULL);  

                if ( !pSerialHead->hSerialEvent || !pSerialHead->hKillDispatchThread ||  

                     !pSerialHead->hTransmitEvent || !pSerialHead->hReadEvent ) {  

                    DEBUGMSG(ZONE_ERROR | ZONE_INIT,  

                             (TEXT("Error creating event, COM_Init failed\n\r")));  

                    LocalFree(pSerialHead);  

                    return(NULL);  

                }  

                /* Initialize the critical sections that will guard the parts of 

                 * the receive and transmit buffers. 

                 */ 

                InitializeCriticalSection(&(pSerialHead->ReceiveCritSec1));  

                InitializeCriticalSection(&(pSerialHead->TransmitCritSec1));  

                /* Want to use the Identifier to do RegOpenKey and RegQueryValue (?) 

                 * to get the index to be passed to GetHWObj. 

                 * The HWObj will also have a flag denoting whether to start the 

                 * listening thread or provide the callback. 

                 */ 

                DEBUGMSG (ZONE_INIT,(TEXT("Try to open %s\r\n"), (LPCTSTR)Identifier));  

                hKey = OpenDeviceKey((LPCTSTR)Identifier);  

                // 通過調(diào)用OpenDeviceKey, 驅(qū)動可以通過Identifier找到驅(qū)動的注冊表鍵的所在.  

                if ( !hKey ) {  

                    DEBUGMSG (ZONE_INIT | ZONE_ERROR,  

                              (TEXT("Failed to open devkeypath, COM_Init failed\r\n")));  

                    LocalFree(pSerialHead);  

                    return(NULL);  

                }  

                datasize = sizeof(DWORD);  

                // 通過查詢DeviceArrayIndex鍵值, 我們可以知道需要打開的是普通串口或者是其他類型的串口設(shè)備.  

                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);  

                // 通過查詢Priority256鍵值, 我們可以知道IST的優(yōu)先級,  在后面會通過這個值來改變IST的優(yōu)先級.  

                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.  

                // GetSerialObject是連接MDD和PDD層的關(guān)鍵函數(shù), 在這個函數(shù)里面決定了DevIndex是對什么設(shè)備進行操作.  

                // 可能是標準的串口, 也可能是紅外接口  

                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));  

                // 這里調(diào)用了PDD層的HWInit  

                pHWHead = pSerialHead->pHWObj->pFuncTbl->HWInit(Identifier, pSerialHead, pSerialHead->pHWObj);  

                pSerialHead->pHWHead = pHWHead;  

                /* Check that HWInit did stuff ok.  From here on out, call Deinit function 

                 * when things fail.  

                 */ 

                if ( !pHWHead ) {  

                    DEBUGMSG (ZONE_INIT | ZONE_ERROR,  

                              (TEXT("Hardware doesn't init correctly, COM_Init failed\r\n")));  

                    COM_Deinit(pSerialHead);  

                    return(NULL);  

                }  

                DEBUGMSG (ZONE_INIT,  

                          (TEXT("Back from hardware init\r\n")));  

                // Allocate at least twice the hardware buffer size so we have headroom  

                HWBufferSize        = 2 * pSerialHead->pHWObj->pFuncTbl->HWGetRxBufferSize(pHWHead);  

                // Init rx buffer and buffer length here.  

                pSerialHead->RxBufferInfo.Length =  

                HWBufferSize > RX_BUFFER_SIZE ? HWBufferSize:RX_BUFFER_SIZE;  

                pSerialHead->RxBufferInfo.RxCharBuffer =  

                LocalAlloc(LPTR, pSerialHead->RxBufferInfo.Length);  

                if ( !pSerialHead->RxBufferInfo.RxCharBuffer ) {  

                    DEBUGMSG(ZONE_INIT|ZONE_ERROR,  

                             (TEXT("Error allocating receive buffer, COM_Init failed\n\r")));  

                    COM_Deinit(pSerialHead);  

                    return(NULL);  

                }  

                DEBUGMSG (ZONE_INIT, (TEXT("RxHead init'ed\r\n")));  

                RxResetFifo(pSerialHead);  

                InitializeCriticalSection(&(pSerialHead->RxBufferInfo.CS));  

                InitializeCriticalSection(&(pSerialHead->TxBufferInfo.CS));  

                DEBUGMSG (ZONE_INIT, (TEXT("RxBuffer init'ed with start at %x\r\n"),  

                                      pSerialHead->RxBufferInfo.RxCharBuffer));  

                if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_INIT ) {  

                    // Hook the interrupt and start the associated thread.  

                    if ( ! StartDispatchThread( pSerialHead ) ) {  

                        // Failed on InterruptInitialize or CreateThread.  Bail.  

                        COM_Deinit(pSerialHead);  

                        return(NULL);          

                    }  

                }  

                // OK, now that everything is ready on our end, give the PDD  

                // one last chance to init interrupts, etc.  

                (void) pSerialHead->pHWObj->pFuncTbl->HWPostInit( pHWHead );  

                DEBUGMSG (ZONE_INIT | ZONE_FUNCTION, (TEXT("-COM_Init\r\n")));  

                return(pSerialHead);  

            HANDLE

            COM_Init(

                    ULONG   Identifier

                    )

            {

                PVOID           pHWHead     = NULL;

                PHW_INDEP_INFO  pSerialHead = NULL;

                ULONG           HWBufferSize;

                DWORD           DevIndex;

                HKEY            hKey;

                ULONG           kreserved = 0, kvaluetype;

                ULONG           datasize = sizeof(ULONG);

                /*

                 *  INTERNAL: this routine initializes the hardware abstraction interface

                 *  via HWInit(). It allocates a data structure representing this

                 *  instantiation of the device. It also creates an event and initializes

                 *  a critical section for receiving as well as registering the logical

                 *  interrupt dwIntID with NK via InterruptInitialize. This call

                 *  requires that the hardware dependent portion export apis that return

                 *  the physical address of the receive buffer and the size of that buffer.

                 *  Finally, it creates a buffer to act as an intermediate

                 *  buffer when receiving.

                 */

                DEBUGMSG (ZONE_INIT | ZONE_FUNCTION, (TEXT("+COM_Init\r\n")));

                // Allocate our control structure.

                pSerialHead = (PHW_INDEP_INFO)LocalAlloc(LPTR, sizeof(HW_INDEP_INFO));

                // Check that LocalAlloc did stuff ok too.

                if ( !pSerialHead ) {

                    DEBUGMSG(ZONE_INIT | ZONE_ERROR,

                             (TEXT("Error allocating memory for pSerialHead, COM_Init failed\n\r")));

                    return(NULL);

                }

                // Initially, open list is empty.

                InitializeListHead( &pSerialHead->OpenList );

                InitializeCriticalSection(&(pSerialHead->OpenCS));

                pSerialHead->pAccessOwner = NULL;

                pSerialHead->fEventMask = 0;

                // Init CommTimeouts.

                pSerialHead->CommTimeouts.ReadIntervalTimeout = READ_TIMEOUT;

                pSerialHead->CommTimeouts.ReadTotalTimeoutMultiplier =

                READ_TIMEOUT_MULTIPLIER;

                pSerialHead->CommTimeouts.ReadTotalTimeoutConstant =

                READ_TIMEOUT_CONSTANT;

                pSerialHead->CommTimeouts.WriteTotalTimeoutMultiplier=  0;

                pSerialHead->CommTimeouts.WriteTotalTimeoutConstant =   0;

                /* Create tx and rx events and stash in global struct field. Check return.

                 */

                pSerialHead->hSerialEvent = CreateEvent(0,FALSE,FALSE,NULL);

                pSerialHead->hKillDispatchThread = CreateEvent(0, FALSE, FALSE, NULL);

                pSerialHead->hTransmitEvent = CreateEvent(0, FALSE, FALSE, NULL);

                pSerialHead->hReadEvent = CreateEvent(0, FALSE, FALSE, NULL);

                if ( !pSerialHead->hSerialEvent || !pSerialHead->hKillDispatchThread ||

                     !pSerialHead->hTransmitEvent || !pSerialHead->hReadEvent ) {

                    DEBUGMSG(ZONE_ERROR | ZONE_INIT,

                             (TEXT("Error creating event, COM_Init failed\n\r")));

                    LocalFree(pSerialHead);

                    return(NULL);

                }

                /* Initialize the critical sections that will guard the parts of

                 * the receive and transmit buffers.

                 */

                InitializeCriticalSection(&(pSerialHead->ReceiveCritSec1));

                InitializeCriticalSection(&(pSerialHead->TransmitCritSec1));

                /* Want to use the Identifier to do RegOpenKey and RegQueryValue (?)

                 * to get the index to be passed to GetHWObj.

                 * The HWObj will also have a flag denoting whether to start the

                 * listening thread or provide the callback.

                 */

                DEBUGMSG (ZONE_INIT,(TEXT("Try to open %s\r\n"), (LPCTSTR)Identifier));

                hKey = OpenDeviceKey((LPCTSTR)Identifier);

                // 通過調(diào)用OpenDeviceKey, 驅(qū)動可以通過Identifier找到驅(qū)動的注冊表鍵的所在.

                if ( !hKey ) {

                    DEBUGMSG (ZONE_INIT | ZONE_ERROR,

                              (TEXT("Failed to open devkeypath, COM_Init failed\r\n")));

                    LocalFree(pSerialHead);

                    return(NULL);

                }

                datasize = sizeof(DWORD);

                // 通過查詢DeviceArrayIndex鍵值, 我們可以知道需要打開的是普通串口或者是其他類型的串口設(shè)備.

                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);

                // 通過查詢Priority256鍵值, 我們可以知道IST的優(yōu)先級,  在后面會通過這個值來改變IST的優(yōu)先級.

                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.

                // GetSerialObject是連接MDD和PDD層的關(guān)鍵函數(shù), 在這個函數(shù)里面決定了DevIndex是對什么設(shè)備進行操作.

                // 可能是標準的串口, 也可能是紅外接口

                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));

                // 這里調(diào)用了PDD層的HWInit

                pHWHead = pSerialHead->pHWObj->pFuncTbl->HWInit(Identifier, pSerialHead, pSerialHead->pHWObj);

                pSerialHead->pHWHead = pHWHead;

                /* Check that HWInit did stuff ok.  From here on out, call Deinit function

                 * when things fail.

                 */

                if ( !pHWHead ) {

                    DEBUGMSG (ZONE_INIT | ZONE_ERROR,

                              (TEXT("Hardware doesn't init correctly, COM_Init failed\r\n")));

                    COM_Deinit(pSerialHead);

                    return(NULL);

                }

                DEBUGMSG (ZONE_INIT,

                          (TEXT("Back from hardware init\r\n")));

                // Allocate at least twice the hardware buffer size so we have headroom

                HWBufferSize = 2 * pSerialHead->pHWObj->pFuncTbl->HWGetRxBufferSize(pHWHead);

                // Init rx buffer and buffer length here.

                pSerialHead->RxBufferInfo.Length =

                HWBufferSize > RX_BUFFER_SIZE ? HWBufferSize:RX_BUFFER_SIZE;

                pSerialHead->RxBufferInfo.RxCharBuffer =

                LocalAlloc(LPTR, pSerialHead->RxBufferInfo.Length);

                if ( !pSerialHead->RxBufferInfo.RxCharBuffer ) {

                    DEBUGMSG(ZONE_INIT|ZONE_ERROR,

                             (TEXT("Error allocating receive buffer, COM_Init failed\n\r")));

                    COM_Deinit(pSerialHead);

                    return(NULL);

                }

                DEBUGMSG (ZONE_INIT, (TEXT("RxHead init'ed\r\n")));

                RxResetFifo(pSerialHead);

                InitializeCriticalSection(&(pSerialHead->RxBufferInfo.CS));

                InitializeCriticalSection(&(pSerialHead->TxBufferInfo.CS));

                DEBUGMSG (ZONE_INIT, (TEXT("RxBuffer init'ed with start at %x\r\n"),

                                      pSerialHead->RxBufferInfo.RxCharBuffer));

                if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_INIT ) {

                    // Hook the interrupt and start the associated thread.

                    if ( ! StartDispatchThread( pSerialHead ) ) {

                        // Failed on InterruptInitialize or CreateThread.  Bail.

                        COM_Deinit(pSerialHead);

                        return(NULL);

                    }

                }

                // OK, now that everything is ready on our end, give the PDD

                // one last chance to init interrupts, etc.

                (void) pSerialHead->pHWObj->pFuncTbl->HWPostInit( pHWHead );

                DEBUGMSG (ZONE_INIT | ZONE_FUNCTION, (TEXT("-COM_Init\r\n")));

                return(pSerialHead);

            }


            posted on 2011-03-01 16:13 心羽 閱讀(571) 評論(0)  編輯 收藏 引用 所屬分類: wince
            日本欧美国产精品第一页久久| 亚洲色欲久久久综合网东京热| 97久久超碰成人精品网站| 久久99国产综合精品| 国产三级精品久久| 狠狠色婷婷久久综合频道日韩| 婷婷综合久久中文字幕蜜桃三电影| 久久国产精品99精品国产987| 婷婷久久精品国产| 国产精品久久国产精品99盘 | 久久综合狠狠色综合伊人| 久久99精品国产99久久6| 亚洲va久久久噜噜噜久久狠狠| 青青草原综合久久| 久久人人爽人人爽人人片AV不| 人妻精品久久久久中文字幕| 91久久精一区二区三区大全| 久久久久人妻一区二区三区 | 麻豆精品久久久久久久99蜜桃| 99久久国语露脸精品国产| 2021国产精品久久精品| 久久久久久一区国产精品| 国产精品久久永久免费| 亚洲综合伊人久久大杳蕉| 亚洲国产成人久久笫一页| 99久久久久| 久久青草国产精品一区| 国产综合久久久久| 日韩精品久久无码人妻中文字幕| 久久亚洲国产精品123区| 久久中文字幕一区二区| 久久综合九色综合97_久久久| 国产Av激情久久无码天堂| 奇米影视7777久久精品| 久久久国产精品亚洲一区| 亚洲国产精品无码久久久不卡| 人妻无码αv中文字幕久久琪琪布| 一本综合久久国产二区| 欧美日韩精品久久久免费观看| 18禁黄久久久AAA片| 亚洲女久久久噜噜噜熟女|