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

📄 bthsdio.cpp

📁 WINCE5.0下
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    // Check for packet to read
    status = SDGetRegister(REG_INTRD, m_ucFunction, &ucRegValue, 1);
    if (!SD_API_SUCCESS(status)) {
        ASSERT(0);
        goto exit;
    }
    if (ucRegValue) {
        SetEvent(m_hReadPacketEvent);

        // Clear INTRD register
        ucRegValue = 0x01;
        status = SDSetRegister(REG_INTRD, m_ucFunction, &ucRegValue, 1);
        if (!SD_API_SUCCESS(status)) {
            ASSERT(0);
            goto exit;
        }
    }
       
exit:
    m_refIO.DelRef();
    return status;
}


/*

This method writes a specified amount of data to the card.

*/
SD_API_STATUS CSdioDevice::SDSend(unsigned char* pBuffer, unsigned int cbBuffer)
{
    SD_API_STATUS status = SD_API_STATUS_SUCCESS;
    DWORD dwArgument;
    SD_COMMAND_RESPONSE response;

#ifdef DEBUG
    DWORD dwCardStatus;
#endif

#if defined (BT_USE_CELOG)
    if (g_Data.fCeLog) {
        CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, pBuffer, (unsigned short)cbBuffer, 0, CELZONE_ALWAYSON, CELOG_FLAG_RAW_OUT);
    }
#endif

    //
    // We have to send data down to card in blocks no larger than m_usBlockLen.
    //

    while (cbBuffer > 0) {
        USHORT cbNextBlock;

        if (cbBuffer > m_usBlockLen) {
            cbNextBlock = m_usBlockLen;
        }
        else {
            cbNextBlock = cbBuffer;
        }

        dwArgument = BUILD_IO_RW_EXTENDED_ARG(SD_IO_OP_WRITE, 
                            SD_IO_BYTE_MODE, 
                            m_ucFunction, 
                            REG_DATAPORT, 
                            SD_IO_FIXED_ADDRESS, 
                            cbNextBlock);

        status = SDSynchronousBusRequest(m_hDevice,
                            SD_CMD_IO_RW_EXTENDED,
                            dwArgument,
                            SD_WRITE,
                            ResponseR5,
                            &response,
                            1,
                            cbNextBlock,
                            pBuffer,
                            0);
            
        if (!SD_API_SUCCESS(status)) {
            goto exit;
        }

        pBuffer += cbNextBlock;
        cbBuffer -= cbNextBlock;
    
#ifdef DEBUG
        SDGetCardStatusFromResponse(&response, &dwCardStatus);
        IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] CSdioDevice::SDSend - CardStatus from response = 0x%X\n", dwCardStatus));
#endif    
    }
    
exit:
    return status;        
}


/*

This function is called when a synchronous bus request completes.

*/
void SDRecvCallback(SD_DEVICE_HANDLE hDevice, PSD_BUS_REQUEST pRequest, PVOID pDeviceContext, DWORD dwParam)
{
	SDFreeBusRequest(pRequest);
	if (dwParam) {
		// Set event when last block is returned
		SetEvent((HANDLE)dwParam);
	}
}


/*

This method reads a specified amount of data from the card.

*/
SD_API_STATUS CSdioDevice::SDRecv(unsigned char* pBuffer, unsigned int* pcbBuffer)
{
    SD_API_STATUS status = SD_API_STATUS_SUCCESS;
    DWORD dwArgument;
    ULONG cbBytesRead = 0;
    BOOL fLastBlock = FALSE;

    //
    // We have to recv data from the card in blocks no larger than m_usBlockLen.
    //

    while (cbBytesRead < *pcbBuffer) {
        USHORT cbNextBlock;
        PSD_BUS_REQUEST pBusRequest;
        
        if ((*pcbBuffer - cbBytesRead) > m_usBlockLen) {
            cbNextBlock = m_usBlockLen;
        }
        else {
            cbNextBlock = (USHORT) (*pcbBuffer - cbBytesRead);
        }

        if ((cbBytesRead + cbNextBlock) == *pcbBuffer) {
            fLastBlock = TRUE;
        }

        dwArgument = BUILD_IO_RW_EXTENDED_ARG(SD_IO_OP_READ, 
                            SD_IO_BYTE_MODE, 
                            m_ucFunction, 
                            REG_DATAPORT, 
                            SD_IO_FIXED_ADDRESS, 
                            cbNextBlock);

        status = SDBusRequest(m_hDevice,
                            SD_CMD_IO_RW_EXTENDED,
                            dwArgument,
                            SD_READ,
                            ResponseR5,
                            1,
                            cbNextBlock,
                            pBuffer,
                            SDRecvCallback,
                            (DWORD)(fLastBlock ? m_hRecvCompleteEvent : 0),
                            &pBusRequest,
                            0);

        if (!SD_API_SUCCESS(status)) {
            goto exit;
        }

        pBuffer += cbNextBlock;
        cbBytesRead += cbNextBlock;
    }

    WaitForSingleObject(m_hRecvCompleteEvent, INFINITE);

exit:
    return status;
}


/*

This method calculates the largest block length supported by
both the card and host controller.

*/
BOOL CSdioDevice::GetMaxBlockLen(void)
{
    BOOL fRetVal = TRUE;
    SD_HOST_BLOCK_CAPABILITY blockCapability;
    UCHAR rgucTuple[SD_CISTPLE_MAX_BODY_SIZE];
    PSD_CISTPL_FUNCE_FUNCTION pFunce = (PSD_CISTPL_FUNCE_FUNCTION) rgucTuple;
    ULONG ulLength = 0;
    USHORT usHostBlockLen, usCardBlockLen;

    if (! SD_API_SUCCESS(SDGetTuple(m_hDevice, SD_CISTPL_FUNCE, NULL, &ulLength, FALSE)) ||
          (ulLength > sizeof(rgucTuple)) ) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    if (! SD_API_SUCCESS(SDGetTuple(m_hDevice, SD_CISTPL_FUNCE, rgucTuple, &ulLength, FALSE)) ||
          (pFunce->bType != SD_CISTPL_FUNCE_FUNCTION_TYPE) ) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    usCardBlockLen = pFunce->wMaxBlkSize;

    blockCapability.ReadBlocks = DEFAULT_HOST_NUM_BLOCKS;
    blockCapability.WriteBlocks = DEFAULT_HOST_NUM_BLOCKS;
    blockCapability.ReadBlockSize = DEFAULT_HOST_BLOCK_SIZE;
    blockCapability.WriteBlockSize = DEFAULT_HOST_BLOCK_SIZE;
    if (! SD_API_SUCCESS(SDCardInfoQuery(m_hDevice, SD_INFO_HOST_BLOCK_CAPABILITY, &blockCapability, sizeof(blockCapability)))) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] Block Capability on host: read_blocks=%d write_blocks=%d read_size=%d write_size=%d\n",
        blockCapability.ReadBlocks,
        blockCapability.WriteBlocks,
        blockCapability.ReadBlockSize,
        blockCapability.WriteBlockSize));

    usHostBlockLen = (blockCapability.ReadBlockSize < blockCapability.WriteBlockSize) ? blockCapability.ReadBlockSize : blockCapability.WriteBlockSize;

    m_usBlockLen = (usHostBlockLen < usCardBlockLen) ? usHostBlockLen : usCardBlockLen;

exit:    
    return fRetVal;
}

/*

This method reads tuple 0x91 to determine if this is a type A or B BT card.

*/
BOOL CSdioDevice::GetBTCardType(void)
{
    BOOL fRetVal = TRUE;
    PUCHAR pucTuple = NULL;
    ULONG ulLength = 0;
    
    if (! SD_API_SUCCESS(SDGetTuple(m_hDevice, SD_CISTPL_SDIO_STD, NULL, &ulLength, FALSE))) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    pucTuple = (UCHAR*) LocalAlloc(0, ulLength);
    if (! pucTuple) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    if (! SD_API_SUCCESS(SDGetTuple(m_hDevice, SD_CISTPL_SDIO_STD, pucTuple, &ulLength, FALSE))) {
        ASSERT(0);
        fRetVal = FALSE;
        goto exit;
    }

    m_usBTCardType = (BYTE) *pucTuple; // card type is first byte in tuple

exit:
    if (pucTuple) {
        LocalFree(pucTuple);
    }
    
    return fRetVal;
}

/*

This method handles power management IOCTLs.

*/
DWORD CSdioDevice::IOControl(DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut)
{
    DWORD dwRet = ERROR_SUCCESS;
    
    switch(dwCode) {
        case IOCTL_POWER_CAPABILITIES: {
            if ( !pBufOut || dwLenOut != sizeof(POWER_CAPABILITIES) || 
                 !pdwActualOut ) {
                dwRet = ERROR_INVALID_PARAMETER;
            }
            else {
                PPOWER_CAPABILITIES pPowerCaps = (PPOWER_CAPABILITIES)pBufOut;
                memset(pPowerCaps, 0, sizeof(POWER_CAPABILITIES));

                pPowerCaps->DeviceDx = DX_MASK(D0) | DX_MASK(D3) | DX_MASK(D4);
                pPowerCaps->WakeFromDx = DX_MASK(D0) | DX_MASK(D3);
                *pdwActualOut = sizeof(POWER_CAPABILITIES);
            }
            break;
        }

        case IOCTL_POWER_SET: {
            if ( !pBufOut || dwLenOut != sizeof(CEDEVICE_POWER_STATE) || 
                 !pdwActualOut ) {
                dwRet = ERROR_INVALID_PARAMETER;
            }
            else {
                PCEDEVICE_POWER_STATE pcps = (PCEDEVICE_POWER_STATE) pBufOut;

                if (m_hBusAccess) {
                    SD_CARD_INTERFACE ci;
                    SD_API_STATUS status = SDCardInfoQuery(m_hDevice,
                        SD_INFO_CARD_INTERFACE,
                        &ci,
                        sizeof(ci));

                    if (SD_API_SUCCESS(status)) {
                        if (*pcps == D3) {
                            m_fGoTo4BitModeOnResume = FALSE;
                            
                            if (ci.InterfaceMode == SD_INTERFACE_SD_4BIT) {
                                // Place card into 1-bit mode so card 
                                // interrupts can wake the system.
                                ci.InterfaceMode = SD_INTERFACE_SD_MMC_1BIT;
                                status = SDSetCardFeature(m_hDevice,
                                    SD_SET_CARD_INTERFACE,
                                    &ci,
                                    sizeof(ci));
                                m_fGoTo4BitModeOnResume = SD_API_SUCCESS(status);
                            }
                            // else already in 1-bit mode
                            SetDevicePowerState(m_hBusAccess, *pcps, NULL);
                        }
                        else if (*pcps == D0 && m_cpsCurrent != D0) {
                            // Turn on power first since SDSetCardFeature
                            // performs a bus request.
                            SetDevicePowerState(m_hBusAccess, *pcps, NULL);
                            
                            if (m_fGoTo4BitModeOnResume) {
                                DEBUGCHK(ci.InterfaceMode == SD_INTERFACE_SD_MMC_1BIT);
                                ci.InterfaceMode = SD_INTERFACE_SD_4BIT;
                                status = SDSetCardFeature(m_hDevice,
                                    SD_SET_CARD_INTERFACE,
                                    &ci,
                                    sizeof(ci));
                                m_fGoTo4BitModeOnResume = FALSE;
                            }
                        }
                        else {
                            SetDevicePowerState(m_hBusAccess, *pcps, NULL);
                        }
                    }
                    
                    m_cpsCurrent = *pcps;
                    *pdwActualOut = sizeof(*pcps);
                }
                else {
                    dwRet = ERROR_INVALID_PARAMETER;
                }
            }
            break;
        }

        case IOCTL_POWER_GET: {
            if ( !pBufOut || dwLenOut != sizeof(CEDEVICE_POWER_STATE) || 
                 !pdwActualOut ) {
                dwRet = ERROR_INVALID_PARAMETER;
            }
            else {
                PCEDEVICE_POWER_STATE pcps = (PCEDEVICE_POWER_STATE) pBufOut;
                
                if (m_hBusAccess) {
                    BOOL fSuccess = GetDevicePowerState(m_hBusAccess, pcps, NULL);
                    if (fSuccess) {
                        *pdwActualOut = sizeof(*pcps);
                    }
                    else {
                        dwRet = GetLastError();
                    }
                }
                else {
                    dwRet = ERROR_INVALID_PARAMETER;
                }
            }
        }

        default:
            dwRet = ERROR_INVALID_PARAMETER;
    }

    return dwRet;
}

/*

This method initializes the BT registers in preparation for reading/writing data.

*/
BOOL CSdioDevice::InitializeBTRegisters(void)
{
    BOOL fRetVal = TRUE;
    UCHAR ucRegVal;

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

    ASSERT((m_usBTCardType == BT_CARD_TYPE_A) || (m_usBTCardType == BT_CARD_TYPE_B));

    if (m_usBTCardType == BT_CARD_TYPE_B) {
        ucRegVal = 0x00;
        if (! SD_API_SUCCESS(SDSetRegister(REG_MDSTAT, m_ucFunction, &ucRegVal, 1))) {
            ASSERT(0);
            fRetVal = FALSE;
            goto exit;
        }
    }

#ifdef DEBUG
    if (! SD_API_SUCCESS(SDGetRegister(REG_MDSTAT, m_ucFunction, &ucRegVal, 1))) {
        fRetVal = FALSE;
        goto exit;
    }

    IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] MDSTAT register: %d\n", ucRegVal));
#endif

    ucRegVal = 0x00;
    if (! SD_API_SUCCESS(SDSetRegister(REG_RTC, m_ucFunction, &ucRegVal, 1))) {
        fRetVal = FALSE;
        goto exit;
    }

#ifdef DEBUG
    if (! SD_API_SUCCESS(SDGetRegister(REG_RTC, m_ucFunction, &ucRegVal, 1))) {
        fRetVal = FALSE;
        goto exit;
    }

    IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] RTC STAT register: %d\n", ucRegVal));
#endif

    ucRegVal = 0x01;
    if (! SD_API_SUCCESS(SDSetRegister(REG_ENINTRD, m_ucFunction, &ucRegVal, 1))) {
        fRetVal = FALSE;
        goto exit;
    }

#ifdef DEBUG
    if (! SD_API_SUCCESS(SDGetRegister(REG_ENINTRD, m_ucFunction, &ucRegVal, 1))) {
        fRetVal = FALSE;
        goto exit;
    }

    IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] ENINTRD register: %d\n", ucRegVal));

    if (! SD_API_SUCCESS(SDGetRegister(REG_INTRD, m_ucFunction, &ucRegVal, 1))) {
        fRetVal = FALSE;
        goto exit;
    }

    IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[SDIO] INTRD register: %d\n", ucRegVal));
#endif

exit:
    return fRetVal;
}

⌨️ 快捷键说明

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