⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wendyser.c

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		{
        return (UINT32)NULL;
		}
    
    // LAM - Oops, big hole in my MDD.  We should have passed the DevIndex or pHWObj pointer
    // down into the PDD.  But since I didn't, the PDD will have to open up the registry and
    // read the DevIndex itself.  Oh well, we'll do it right next time.

    // See if we have already inited a port on this socket
    wCardIndex = MAX_CARDS;
    pCardInfo = NULL;
    for( i=0; i<MAX_CARDS; i++ )
    {
        if( CardInfoList[i] )
        {
            if (CardInfoList[i]->hCardSock.uSocket == hCardSock.uSocket)
            {
                pCardInfo = CardInfoList[i];
                DEBUGMSG (ZONE_INIT | ZONE_ERROR,
                          (TEXT("Socket 0x%x function x%X already allocated.\r\n"),
                           pCardInfo->hCardSock.uSocket, pCardInfo->hCardSock.uFunction));
                break;
            }
        }
        else
        {
            // If we found an available slot, remember it.
            if( wCardIndex == MAX_CARDS )
                wCardIndex = i;
        }
    }
    
    if( !pCardInfo )
    {
        if( wCardIndex == MAX_CARDS )
        {
            DEBUGMSG (ZONE_INIT | ZONE_ERROR,
                      (TEXT("Max WendySer card limit reached\r\n")));
            return NULL;
        }
        else
        {
            // Allocate a new card structure and set up PCMCIA
            DEBUGMSG (ZONE_INIT | ZONE_ERROR,
                      (TEXT("Allocating WendySer card struct at index %d\r\n"),
                       wCardIndex ));
            pCardInfo = (PWENDY_CARD_SER_INFO)LocalAlloc( LMEM_ZEROINIT|LMEM_FIXED ,
                                                sizeof(WENDY_CARD_SER_INFO) );
            if ( ! pCardInfo )
                return (UINT32)NULL;

            CardInfoList[wCardIndex] = pCardInfo;
			pCardInfo->dwIndex = wCardIndex;	// Remember array index
            pCardInfo->hCardSock = hCardSock;	// GetCardHandle read this from registry
        }
    }


    // By now, we have either allocated or found our cardInfo struct.  Take care of
    // all the port specific stuff.
    pCardInfo->pMddHead	  = pMddHead;
    pCardInfo->cOpenCount   = 0;

    pCardInfo->fPowerCycle = FALSE;

//    DEBUGMSG (ZONE_INIT ,(TEXT("pHWHead x%X\r\n"), pHWHead));
#pragma message ("should fix this to match capabilities of Wendy")
    // Set up our Comm Properties data    
    pCardInfo->CommProp.wPacketLength       = 0xffff;
    pCardInfo->CommProp.wPacketVersion     = 0xffff;
    pCardInfo->CommProp.dwServiceMask      = SP_SERIALCOMM;
    pCardInfo->CommProp.dwReserved1	      = 0;
    pCardInfo->CommProp.dwMaxTxQueue	      = 128;
    pCardInfo->CommProp.dwMaxRxQueue	      = 128;
    pCardInfo->CommProp.dwMaxBaud	      = BAUD_USER;
    pCardInfo->CommProp.dwProvSubType      = PST_RS232;
    pCardInfo->CommProp.dwProvCapabilities =
        PCF_DTRDSR | PCF_RLSD | PCF_RTSCTS |
        PCF_SETXCHAR |
        PCF_INTTIMEOUTS |
        PCF_PARITY_CHECK |
        PCF_SPECIALCHARS |
        PCF_TOTALTIMEOUTS |
        PCF_XONXOFF;
    pCardInfo->CommProp.dwSettableBaud      =
		BAUD_300 | BAUD_600 | BAUD_1200 | 
		BAUD_1800 |	BAUD_2400 | BAUD_4800 |
		BAUD_7200 | BAUD_9600 | BAUD_14400 |
		BAUD_19200 | BAUD_38400 | BAUD_56K | 
		BAUD_115200 | BAUD_57600 | BAUD_USER;
    pCardInfo->CommProp.dwSettableParams    =
        SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
        SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
    pCardInfo->CommProp.wSettableData       =
        DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
    pCardInfo->CommProp.wSettableStopParity =
        STOPBITS_10 | STOPBITS_20 |
        PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_SPACE |
        PARITY_MARK;

#if 0
// This is now done on CF_Open
     // Lets do the rest of the card initialization
    if( !InitPCMCIACard( pCardInfo ) )
    {
        DEBUGMSG (ZONE_OPEN|ZONE_ERROR, (TEXT("CF_Init - Failed to init card\r\n")));
		return (UINT32)NULL;
    }

    SL_Init( pCardInfo, pCardInfo->pCardIOWin, pCardInfo->IO_Granularity,
             EvaluateEventFlag, pCardInfo->pMddHead, NULL);

#endif
    DEBUGMSG (ZONE_FUNCTION, (TEXT("-CF_INIT\r\n") ));

    return pCardInfo;
}

//
// @doc OEM
// @func ULONG | CF_Close | This routine closes the device identified
// by pHead.
// 
// @rdesc The return value is 0 if successful, -1 if failed.
//
ULONG
CF_Close(
    PVOID   pHead	// @parm PVOID returned by CF_Init.
    )
{
    PWENDY_CARD_SER_INFO   pCardInfo = (PWENDY_CARD_SER_INFO)pHead;
    ULONG  uTries;
    ULONG retval = 0;
    
    DEBUGMSG (ZONE_FUNCTION, (TEXT("+CF_CLOSE\r\n") ));


    if( pCardInfo->cOpenCount )
    {
        pCardInfo->cOpenCount--;

        if( ! pCardInfo->cOpenCount )
        {
            // Note: We can not call SL_Close when PCMCIA closes the driver after power cycle.
            // because SL_Close accesses IO to mask all the interrupts. Of course at this point
            // IO space have disappeared.
            // It is OK not to call SL_Close here. Only thing is wrong is OpenCount..
            // But we always call SL_Init & SL_Open  or SL_Close & SL_Deinit together. And
            // SL_Deinit does not check cOpenCount So cOpenCount will be initialed to zero in SL_Init.
            if (! pCardInfo->fPowerCycle)
            {
                // while we are still transmitting, sleep.
                uTries = 0;
                while ( (uTries++ < 100) &&
                    !(pCardInfo->ser16950.LSR & SERIAL_LSR_TEMT) )
                {
                    Sleep(10);
                }

                SL_Close( pCardInfo );
            }
                // Let ser16550 lib free any resources it may have created.
            SL_Deinit( pCardInfo );
			
             // Free up all PCMCIA objects/handles by deregistering
            CallCardServices(CardDeregisterClient) (pCardInfo->hCardClient);
        }
        else
        {
             // If someone else still has device open, we don't do anything.
            DEBUGMSG (ZONE_CLOSE|ZONE_ERROR, (TEXT("CF_CLOSE : Open Count > 1, do nothing\r\n")) );
        }
    }
    else
    {
        DEBUGMSG (ZONE_CLOSE|ZONE_ERROR, (TEXT("CF_CLOSE : Open Count == 0, not performing close\r\n")) );
        retval = (ULONG)-1;
    }
    
    DEBUGMSG (ZONE_FUNCTION, (TEXT("+CF_CLOSE\r\n") ));

    return retval;
}

//
// @doc OEM
// @func	VOID | CF_GetCommProperties | Retrieves Comm Properties.
// 
// @rdesc	None.
//
VOID
CF_GetCommProperties(
    PVOID	pHead,	    // @parm PVOID returned by CF_Init. 
    LPCOMMPROP	pCommProp   // @parm Pointer to receive COMMPROP structure. 
    )
{
    PWENDY_CARD_SER_INFO   pCardInfo = (PWENDY_CARD_SER_INFO)pHead;

    memcpy(pCommProp, &pCardInfo->CommProp, sizeof(COMMPROP));
    return;
}

//
// @doc OEM
// @func BOOL | CF_PowerOff |
//   Called by driver to turn off power to serial port.
// 
// @rdesc TRUE if success, FALSE if fail.
//
BOOL
CF_PowerOff(
    PVOID   pHead	    // @parm	PVOID returned by CF_Init.
    )
{
    return TRUE;
}

//
// @doc OEM
// @func BOOL | CF_PowerOn |
//   Called by driver to turn on power to serial port.
// 
// @rdesc TRUE if success, FALSE if fail.
//
BOOL
CF_PowerOn(
    PVOID   pHead	    // @parm	PVOID returned by CF_Init.
    )
{
    PWENDY_CARD_SER_INFO pCardInfo = (PWENDY_CARD_SER_INFO)pHead;
    pCardInfo->fPowerCycle = TRUE;
    return TRUE;
}

//
// @doc OEM
// @func BOOL | CF_EnableIR | This routine enables the ir.
// 
// @rdesc Returns FALSE since IR not supported on PCMCIA.
//
BOOL
CF_EnableIR(
    PVOID   pHead, // @parm PVOID returned by CF_init.
    ULONG   BaudRate  // @parm BaudRate
    )
{
    return FALSE;
}

//
// @doc OEM
// @func BOOL | CF_DisableIR | This routine disables the ir.
// 
// @rdesc Returns TRUE if successful, FALSE if failed.
//
BOOL
CF_DisableIR(
    PVOID   pHead // @parm PVOID returned by CF_init.
    )
{
    return TRUE;
}

//
// @doc OEM
// @func BOOL | CF_Deinit | This routine disables the ir.
// 
// @rdesc Returns TRUE if successful, FALSE if failure.
//
BOOL
CF_Deinit(
    PVOID   pHead // @parm PVOID returned by CF_init.
    )
{
    PWENDY_CARD_SER_INFO   pCardInfo = (PWENDY_CARD_SER_INFO)pHead;

    if ( !pCardInfo )
        return FALSE;

     // Make sure device is closed before doing DeInit
    while( pCardInfo->cOpenCount )
        CF_Close( pCardInfo );

    // Let ser16550 lib free any resources it may have created.
	// These next 2 calls are now done in CF_Close, to match the SL_Init in CF_Open
	// SL_Deinit( pCardInfo );
    // Free up all PCMCIA objects/handles by deregistering
	// CallCardServices(CardDeregisterClient) (pCardInfo->hCardClient);

	CardInfoList[pCardInfo->dwIndex] = NULL;
   	LocalFree(pCardInfo);

    return TRUE;
}

//
// @doc OEM
// @func BOOL | CF_Open | This routine opens the port.
// 
// @rdesc Returns TRUE if successful, FALSE otherwise.
//
BOOL
CF_Open(
    PVOID   pHead // @parm PVOID returned by I_init.
    )
{
    PWENDY_CARD_SER_INFO   pCardInfo = (PWENDY_CARD_SER_INFO)pHead;
    STATUS status;
    DEBUGMSG (ZONE_OPEN|ZONE_FUNCTION, (TEXT("+CF_OPEN - port\r\n")));

     // Lets do the rest of the card initialization
    if( !InitPCMCIACard( pCardInfo ) )
    {
        DEBUGMSG (ZONE_OPEN|ZONE_ERROR, (TEXT("CF_OPEN - Failed to init card\r\n")));
        return FALSE;
    }


     // Init 16550 info.  Note that we do both SL_INIT and SL_OPEN
     // This is an unfortunate side effect of PCMCIA.  As soon as
     // I do a CardRequestConfig, I start sucking power.  So we postpone
     // that till here (in the open).  But, SL_INIT needs our card
     // address space in his init routine, and we don't get the address
     // till after the request config.  So till we come up with a better
     // idea for power enable/disable on PCMCIA, we will have to couple
     // SL_INIT and SL_OPEN.  

    SL_Init( pCardInfo, pCardInfo->pCardIOWin, (UINT8)(pCardInfo->IO_Granularity),
             EvaluateEventFlag, pCardInfo->pMddHead, NULL);

    DEBUGMSG (ZONE_INIT, (TEXT("CF_OPEN - Init 16550 data (addr x%X)\r\n"),
                          pCardInfo->pCardIOWin ));

	// This will be set by ser16550.c in SL_Open() to ID_16550 or ID_16950
    //pCardInfo->ser16550.ChipID = CHIP_ID_16550;

	// This is kind of interesting....SL_Open will enable the RDA, RLS and MS interrupts.
	// Since power to the UART is not cycled between CF_Open/CF_Close calls, it is possible 
	// for the UART to have some pending interrupt state, such as characters to be read.
	// If the UART INTs are enabled before we have registered for CardService interrupts, 
	// the LAN driver gets the interrupt but never clears it and the H/PC is hung.
	// This code will make an attempt to clear any pending interrupt state in the uart, then
	// register to get interrupts before calling SL_OPEN. 
	// Additionally, we should reset the uart.   LLO
	//ResetUart(pCardInfo);

#if 0
	{
    PSER16950_INFO pHWHead = (PSER16950_INFO)pCardInfo;
	BYTE	value;
	try
		{

		OUTB(pHWHead, pIIR_FCR, SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET);

		value = INB(pHWHead, pMSR);

		value = INB(pHWHead, pData);


		value = INB(pHWHead, pLSR);

#if 1

		value = INB(pHWHead, pIIR_FCR);

		while ((value = INB(pHWHead, pLSR)) & 1)
			{
			value = INB(pHWHead, pData);
			}
		value = INB(pHWHead, pData);
#endif
		}

    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        // Just get out of here.
	    }
	}
#endif

	// Register to receive PCMCIA interrupts for this card
    status = CallCardServices(CardRequestIRQ) (pCardInfo->hCardClient,
                                               pCardInfo->hCardSock,
                                               (CARD_ISR)WendySerialEventHandler,
                                               (UINT32)pCardInfo);
    DEBUGMSG (ZONE_INIT, (TEXT("RequestIRQ returned 0x%X\r\n"),
                          status ));

	// OK, the device is open, so increment the counter.
    pCardInfo->cOpenCount++;

    SL_Open( pCardInfo );

    if (!(pCardInfo->cOpenCount)) { // If it it first open. Clean the flag
        pCardInfo->fPowerCycle  = FALSE;
    }


    return TRUE;
}

const
HW_VTBL CFIoVTbl = {
    CF_Init,              /* (*HWInit)              */
    CF_Deinit,            /* (*HWDeinit)            */
    CF_Open,              /* (*HWOpen)              */
    CF_Close,             /* (*HWClose)             */
    SL_RxIntr,            /* (*HWGetBytes)          */
    SL_GetRxStart,        /* (*HWGetRxStart)        */
    SL_GetInterruptType,  /* (*HWGetIntrType)       */
    SL_OtherIntr,         /* (*HWOtherIntrHandler)  */ /* this one gets calles when DSR,CTS,DCD,RING change */
    SL_LineIntr,          /* (*HWLineIntrHandler)   */
    SL_GetRxBufferSize,   /* (*HWGetRxBufferSize)   */
    SL_TxIntr,            /* (*HWTxIntrHandler)     */
    SL_PutBytes,          /* (*HWPutBytes)          */
    CF_PowerOff,          /* (*HWPowerOff)          */
    CF_PowerOn,           /* (*HWPowerOn)           */
    SL_ClearDTR,          /* (*HWClearDTR)          */
    SL_SetDTR,            /* (*HWSetDTR)            */
    SL_ClearRTS,          /* (*HWClearRTS)          */
    SL_SetRTS,            /* (*HWSetRTS)            */
    CF_EnableIR,          /* (*HWEnableIR)          */
    CF_DisableIR,         /* (*HWDisableIR)         */
    SL_ClearBreak,        /* (*HWClearBreak)        */
    SL_SetBreak,          /* (*HWSetBreak)          */
    SL_XmitComChar,       /* (*HWXmitComChar)       */
    SL_GetStatus,         /* (*HWGetStatus)         */
    SL_Reset,             /* (*HWReset)             */
    SL_GetModemStatus,    /* (*HWGetModemStatus)    */
    CF_GetCommProperties, /* (*HWGetCommProperties) */
    SL_PurgeComm,         /* (*HWPurgeComm)         */
    SL_SetDCB,            /* (*HWSetDCB)            */
    SL_SetCommTimeouts,   /* (*HWSetCommTimeouts)   */
    SL_Ioctl};            /* (*HWIoctl)             */


































extern const
DEVICE_LIST CFIoDL;  // forward reference, declared below

HWOBJ   CFIoObj  = { (PDEVICE_LIST) &CFIoDL,
                        THREAD_IN_PDD,  // Actually a callback for PCMCIA, no thread
                        0,  // No SYSINTR for MDD to worry about.
                        NULL,
                        (PHW_VTBL) &CFIoVTbl};

const
PHWOBJ  rgpHWObjects[1] = { &CFIoObj };

const
DEVICE_LIST CFIoDL = {"WendySer.dll", 1, (PHWOBJ *) rgpHWObjects};

PDEVICE_LIST
GetSerialObject(
    VOID
    )
{
#ifdef XDEBUG    
    extern DBGPARAM dpCurSettings;
    dpCurSettings.ulZoneMask = 0xc0c3;
#endif
    
    return  ( (PDEVICE_LIST) &CFIoDL);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -