📄 bthsdio.cpp
字号:
// 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 + -