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

📄 bthsdio.cpp

📁 WINCE5.0下
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include "bthsdio.h"
#include <ceddk.h>


// Bluetooth SDIO registers
#define REG_DATAPORT            0x00        // Send/Recv data
#define REG_PCRRT               0x10        // Read Packet Control
#define REG_PCWRT               0x11        // Write Packet Control
#define REG_RTC                 0x12        // Retry Control
#define REG_INTRD               0x13        // Interrupt
#define REG_ENINTRD             0x14        // Interrupt Enable
#define REG_MDSTAT              0x20        // Bluetooth Mode Status

// SDIO registers
#define REG_CCCR_CARD_CAP       0x08

// BT card types
#define BT_CARD_TYPE_A          0x02
#define BT_CARD_TYPE_B          0x03

// Constants
#define DEFAULT_HOST_BLOCK_SIZE             512
#define DEFAULT_HOST_NUM_BLOCKS             8
#define DEFAULT_SDIO_FUNCTION_RETRIES       5
#define DEFAULT_SDIO_FUNCTION_RETRY_TIMEOUT 1000


CSdioDevice::CSdioDevice()
{
    m_hDevice = 0;
    m_dwState = DETACHED;
    m_ucFunction = 0;
    m_fInterruptConnected = FALSE;
    m_pRegPath = NULL;
    m_hReadPacketEvent = NULL;
    m_hIOStoppedEvent = NULL;
    m_hRecvCompleteEvent = NULL;
    m_usBlockLen = 0;
    m_usBTCardType = 0;
    m_fBlockMode = FALSE;
    m_fCancelIO = FALSE;
    m_hBusAccess = NULL;
    m_cpsCurrent = D0;
    m_fGoTo4BitModeOnResume = FALSE;

    // SVSRefObj always starts at 1.  For our purposes, we want
    // it to initially be 0
    ASSERT(m_refIO.GetRefCount() == 1);
    m_refIO.SetSignal(SignalRefCountZero, (PVOID)this);
    m_refIO.DelRef();
}

CSdioDevice::~CSdioDevice()
{
    if (m_hReadPacketEvent) {
        CloseHandle(m_hReadPacketEvent);
    }
    if (m_hIOStoppedEvent) {
        CloseHandle(m_hIOStoppedEvent);
    }
    if (m_hRecvCompleteEvent) {
    	CloseHandle(m_hRecvCompleteEvent);
    }
}


/*

This method is called to initialize the object.

*/
BOOL CSdioDevice::Init(void)
{
    BOOL fRetVal = TRUE;
    
    if (! m_hReadPacketEvent) {
        m_hReadPacketEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (NULL == m_hReadPacketEvent) {
            ASSERT(0);
            fRetVal = FALSE;
            goto exit;
        }
    }
    if (! m_hIOStoppedEvent) {
        m_hIOStoppedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (NULL == m_hIOStoppedEvent) {
            ASSERT(0);
            fRetVal = FALSE;
            goto exit;
        }
    }
    if (! m_hRecvCompleteEvent) {
        m_hRecvCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (NULL == m_hRecvCompleteEvent) {
            ASSERT(0);
            fRetVal = FALSE;
            goto exit;
        }
    }

exit:
    return fRetVal;
}


/*

This method is called when a card is inserted into the host controller.  This method will
initialize the SDIO card.

*/
BOOL CSdioDevice::Attach(DWORD dwContext)
{
    BOOL fRetVal = TRUE;
    SDCARD_CLIENT_REGISTRATION_INFO clientInfo;
    SD_IO_FUNCTION_ENABLE_INFO functionEnable;
    SDIO_CARD_INFO sdioInfo;

    Init();

    m_hDevice = SDGetDeviceHandle(dwContext, &m_pRegPath);
    if (NULL == m_hDevice) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    SDRegisterDebugZones(m_hDevice, m_pRegPath);
    
    memset(&clientInfo, 0, sizeof(clientInfo));
    wcscpy(clientInfo.ClientName, TEXT("Bluetooth Card"));

    if (! SD_API_SUCCESS(SDRegisterClient(m_hDevice, this, &clientInfo))) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    if (! SD_API_SUCCESS(SDIOConnectInterrupt(m_hDevice, SDIOIsrCallBack))) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    m_hBusAccess = CreateBusAccessHandle((LPCTSTR) dwContext);

    m_fInterruptConnected = TRUE;

    functionEnable.Interval = DEFAULT_SDIO_FUNCTION_RETRY_TIMEOUT;
    functionEnable.ReadyRetryCount = DEFAULT_SDIO_FUNCTION_RETRIES;

    if (! SD_API_SUCCESS(SDSetCardFeature(m_hDevice, SD_IO_FUNCTION_ENABLE, &functionEnable, sizeof(functionEnable)))) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    if (! SD_API_SUCCESS(SDCardInfoQuery(m_hDevice, SD_INFO_SDIO, &sdioInfo, sizeof(sdioInfo)))) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    m_ucFunction = sdioInfo.FunctionNumber;
    
    m_dwState = ATTACHED;

exit:

    if (m_dwState != ATTACHED) {
        Detach();
    }
    else if(g_Data.pfnHCICallback && !g_Data.fStopHardware) {
        g_Data.pfnHCICallback(DEVICE_UP, NULL);
    }

    return fRetVal;
}


/*

This method is called when the card is ejected from the host controller.  Anything that
was initialized in Attach() must be deinitialized.

*/
void CSdioDevice::Detach(void)
{
    if ((m_dwState == ATTACHED) && g_Data.pfnHCICallback && !g_Data.fStopHardware) {
        g_Data.pfnHCICallback(DEVICE_DOWN, NULL);
    }

    m_dwState = SHUTDOWN_IN_PROGRESS;

    // Signal IO to stop.  Detach() must wait until IO
    // has completed to return.
    SetEvent(m_hReadPacketEvent);
    WaitForSingleObject(m_hIOStoppedEvent, INFINITE);

    if (m_hBusAccess) {
        CloseBusAccessHandle(m_hBusAccess);
        m_hBusAccess = NULL;
    }

    if (m_fInterruptConnected) {
        SDIODisconnectInterrupt(m_hDevice);
        m_fInterruptConnected = FALSE;
    }

    if (m_pRegPath) {
        SDFreeMemory(m_pRegPath);
        m_pRegPath = NULL;
    }

    m_dwState = DETACHED;
}


/*

This is a static method which just calls a method on the object passed in pv.

*/
void CSdioDevice::SignalRefCountZero(void *pv)
{
    CSdioDevice* pInst = (CSdioDevice*)pv;
    pInst->SignalRefCountZero_Int();
}


/*

This method is called when m_refIO becomes zero.  If a detach is in progress
this should signal that all IO has completed.  At this point no new IO will begin
since m_dwState will equal SHUTDOWN_IN_PROGRESS.

*/
void CSdioDevice::SignalRefCountZero_Int(void)
{
    if ((m_dwState == SHUTDOWN_IN_PROGRESS) || m_fCancelIO) {
        IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] CSdioDevice::SignalRefCountZero - IO completed, detach can proceed.\n"));
        SetEvent(m_hIOStoppedEvent);
    }
}


/*

This method initializes Bluetooth card in preparation for read/write.

*/
BOOL CSdioDevice::OpenConnection(void)
{
    BOOL fRetVal = TRUE;
    UCHAR ucRegVal;
    
    m_refIO.AddRef();

    m_fCancelIO = FALSE; // reset

    if (m_dwState != ATTACHED) {
        IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] CSdioDevice::OpenConnection - currently not attached, aborting.\n"));    
        fRetVal = FALSE;
        goto exit;
    }

    if (! GetMaxBlockLen()) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    // Is block mode supported?
    if (! SD_API_SUCCESS(SDGetRegister(REG_CCCR_CARD_CAP, 0, &ucRegVal, 1))) {
        fRetVal = FALSE;
        goto exit;
    }

    m_fBlockMode = (ucRegVal & 0x2) >> 1; // SMB is bit 1

    IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] Block Mode: %d  Max Block Size: %d\n", m_fBlockMode, m_usBlockLen));

    if (! InitializeBTRegisters()) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }    

exit:

    m_refIO.DelRef();

    if (! fRetVal) {
        CloseConnection();
    }

    return fRetVal;
}


/*

This method cleans up anything required from OpenConnection.

*/
void CSdioDevice::CloseConnection(void)
{
    m_fCancelIO = TRUE;
    if (m_refIO.GetRefCount()) {
        // Signal IO to stop
        SetEvent(m_hReadPacketEvent);
    }
}


/*

This method waits for an event to be signalled which indicates a packet is ready.  It reads the packet
header followed by the rest of the packet.

*/
BOOL CSdioDevice::ReadPacket(unsigned char* pBuffer, unsigned int* pcbBuffer, BYTE* pbType)
{
    BOOL fRetVal = TRUE;
    unsigned int cHeader = SDIO_HEADER_SIZE;
    SD_TRANSPORT_HEADER header;
    UCHAR ucRegVal;

    m_refIO.AddRef();

    if (m_dwState != ATTACHED) {
        IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] CSdioDevice::ReadPacket - currently not attached, aborting.\n"));    
        fRetVal = FALSE;
        goto exit;
    }

    WaitForSingleObject(m_hReadPacketEvent, INFINITE);

    if ((m_dwState != ATTACHED) || m_fCancelIO) {
        fRetVal = FALSE;
        goto exit;
    }

    // Get SDIO header
    if (! SD_API_SUCCESS(SDRecv(pBuffer, &cHeader))) {
        fRetVal = FALSE;
        goto exit;
    }

    ASSERT(cHeader == SDIO_HEADER_SIZE);
    ASSERT(sizeof(header) == SDIO_HEADER_SIZE);

#if defined (BT_USE_CELOG)
    if (g_Data.fCeLog) {
        CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, pBuffer, cHeader, 0, CELZONE_ALWAYSON, CELOG_FLAG_RAW_IN);
    }
#endif
    
    memcpy(&header, pBuffer, sizeof(header));

    if ((header.u.AsULONG & 0xFFFFFF) <= 4) {
        IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] CSdioDevice::ReadPacket - Received a zero-length packet.\n"));
        fRetVal = FALSE;
        goto exit;         
    }

    // SDIO service ID maps directly to HCI_TYPE
    *pcbBuffer = (header.u.AsULONG & 0xFFFFFF) - SDIO_HEADER_SIZE;
    *pbType = (BYTE)header.u.AsUCHAR.ServiceID;
    
    IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] CSdioDevice::ReadPacket - type=%d size=%d\n", *pbType, *pcbBuffer));

    if (*pcbBuffer > PACKET_SIZE_R) {
        IFDBG(DebugOut (DEBUG_ERROR, L"[SDIO] CSdioDevice::ReadPacket - Header is specifying invalid size of data.  Bailing...\n", *pbType, *pcbBuffer));    
        fRetVal = FALSE;
        goto exit;
    }

    // Get the payload
    if (! SD_API_SUCCESS(SDRecv(pBuffer, pcbBuffer))) {
        fRetVal = FALSE;
        goto exit;
    }

#if defined (BT_USE_CELOG)
    if (g_Data.fCeLog) {
        CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, pBuffer, *pcbBuffer, 0, CELZONE_ALWAYSON, CELOG_FLAG_RAW_IN);
    }
#endif    

    // Acknowledge the packet
    ucRegVal = 0x00;
    if (! SD_API_SUCCESS(SDSetRegister(REG_PCRRT, m_ucFunction, &ucRegVal, 1))) {
        fRetVal = FALSE;
        goto exit;
    }
    
exit:
    m_refIO.DelRef();
    return fRetVal;
}
 

/*

This method just calls down to SDSend to write packet to SDIO card.

*/
BOOL CSdioDevice::WritePacket(unsigned char* pBuffer, int cbBuffer)
{
    BOOL fRetVal = TRUE;
    
    m_refIO.AddRef();

     if (m_dwState != ATTACHED) {
        IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] CSdioDevice::WritePacket - currently not attached, aborting.\n"));    
        fRetVal = FALSE;
        goto exit;
    }
    
    fRetVal = SD_API_SUCCESS(SDSend(pBuffer, cbBuffer));

exit:
    m_refIO.DelRef();
    return fRetVal;
}


/*

This is a static method which just calls a method on the object passed in pContext.

*/
SD_API_STATUS CSdioDevice::SDIOIsrCallBack(SD_DEVICE_HANDLE hDevice, PVOID pContext)
{
    CSdioDevice* pInst = (CSdioDevice*) pContext;
    return pInst->SDIOIsrCallback_Int();
}


/*

This method is called when an interrupt occurs.  It checks if data is ready to
be transferred from the card and if so, sets an event to indicate this.

*/
SD_API_STATUS CSdioDevice::SDIOIsrCallback_Int(void)
{
    SD_API_STATUS status = SD_API_STATUS_SUCCESS;
    UCHAR ucRegValue;

    m_refIO.AddRef();

    if (m_dwState != ATTACHED) {
        ASSERT(0); // not attached
        goto exit;
    }

⌨️ 快捷键说明

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