📄 hci_bcsp.cpp
字号:
tempCrc = ((tempCrc & 0x00ff) << 8) | (tempCrc >> 8);
tempCrc = ((tempCrc & 0x0f0f) << 4) | ((tempCrc & 0xf0f0) >> 4);
tempCrc = ((tempCrc & 0x3333) << 2) | ((tempCrc & 0xcccc) >> 2);
tempCrc = ((tempCrc & 0x5555) << 1) | ((tempCrc & 0xaaaa) >> 1);
*crc = tempCrc;
}
DWORD BcspCommunication::CloseConnection()
{
uint8_t index;
EnterCriticalSection(&lock);
if (serialPortHandle != INVALID_HANDLE_VALUE)
{
IFDBG(DebugOut(DEBUG_BCSP_CTRL, TEXT("<BcspCommunication::CloseConnection>")));
IFSTAT(TCHAR buffer[512]);
IFSTAT(_stprintf(buffer, TEXT("state_%u.txt"), GetTickCount()));
IFSTAT(FILE* f = _tfopen(buffer, TEXT("w+")));
IFSTAT(_ftprintf(f, TEXT("STATS1 (In bytes: %u, In packets: %u, Out bytes: %u, Out packets: %u)\n"), inBytes, inPackets, outBytes, outPackets));
IFSTAT(_ftprintf(f, TEXT("STATS2 (Retransmissions: %u, Retransmissions Timeout: %u, ReceiveReady: %u, ReceiveTotal: %u)\n"), retransmissions, retransmissionsTimeout, receiveReady, receiveTotal));
IFSTAT(_ftprintf(f, TEXT("ERRORS (Sync: %u, Marker: %u, Overflow: %u, Header CRC: %u, Packet CRC: %u, Incorrect Size: %u)\n"), syncErrors, markerErrors, overflowErrors, headerCrcErrors, packetCrcErrors, packetSizeErrors));
IFSTAT(fclose(f));
IFSTAT(IFDBG(DebugOut(DEBUG_BCSP_CTRL, TEXT("<BcspCommunication::CloseConnection@%s> STATS (In bytes: %u, In packets: %u, Out bytes: %u, Out packets: %u)"), name, inBytes, inPackets, outBytes, outPackets)));
IFSTAT(IFDBG(DebugOut(DEBUG_BCSP_CTRL, TEXT("<BcspCommunication::CloseConnection@%s> ERRORS (Sync: %u, Marker: %u, Overflow: %u, Header CRC: %u, Packet CRC: %u, Incorrect Size: %u)"), name, syncErrors, markerErrors, overflowErrors, headerCrcErrors, packetCrcErrors, packetSizeErrors)));
shuttingDown = TRUE;
SetEvent(terminateEvent);
SetEvent(packetAvailable);
CloseHandle(serialPortHandle);
serialPortHandle = INVALID_HANDLE_VALUE;
CloseHandle(transmitHandle);
SetEvent(writePacketEvent);
LeaveCriticalSection(&lock);
IFDBG(DebugOut(DEBUG_BCSP_CTRL, TEXT("<BcspCommunication::CloseConnection> Waiting for threads to terminate (readThread: 0x%08x, writeThread: 0x%08x)"), readThread, writeThread));
WaitForSingleObject(readThread, 2000);
WaitForSingleObject(writeThread, 2000);
IFDBG(DebugOut(DEBUG_BCSP_CTRL, TEXT("<BcspCommunication::CloseConnection> Threads terminated")));
EnterCriticalSection(&lock);
CloseHandle(readThread);
CloseHandle(writeThread);
CloseHandle(writePacketEvent);
CloseHandle(packetAvailable);
CloseHandle(inSyncEvent);
CloseHandle(bccmdEvent);
CloseHandle(terminateEvent);
IFDBG(DebugOut(DEBUG_BCSP_CTRL, TEXT("<BcspCommunication::CloseConnection> Handles closed")));
for (index = 0; index < 8; index++)
{
free(transmitQueue[index].buffer);
free(receiveQueue[index].buffer);
}
ZeroMemory(&transmitQueue, sizeof(transmitQueue));
ZeroMemory(&receiveQueue, sizeof(receiveQueue));
free(incomingSCOData.buffer);
free(outgoingSCOData.buffer);
ZeroMemory(&incomingSCOData, sizeof(incomingSCOData));
ZeroMemory(&outgoingSCOData, sizeof(outgoingSCOData));
IFDBG(DebugOut(DEBUG_BCSP_CTRL, TEXT("<BcspCommunication::CloseConnection> Memory freed")));
free(bccmdBuffer);
transmitHandle = NULL;
readThread = NULL;
writeThread = NULL;
writePacketEvent = NULL;
packetAvailable = NULL;
inSyncEvent = NULL;
terminateEvent = NULL;
numberOfSyncs = 40;
bccmdBuffer = NULL;
bccmdSize = 0;
bccmdEvent = NULL;
IFDBG(DebugOut(DEBUG_BCSP_CTRL, TEXT("<BcspCommunication::CloseConnection@%s> Complete"), name));
}
LeaveCriticalSection(&lock);
return ERROR_SUCCESS;
}
DWORD BcspCommunication::DecodeBCSPPacket(unsigned char* buffer, DWORD size)
{
BCSPHeader* bcspHeader = (BCSPHeader*) buffer;
unsigned char* bchsPayload = (unsigned char*) (bcspHeader + 1);
IFDBG(DebugOut(DEBUG_BCSP_SYNC, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> New packet (Size: %u)"), name, size));
if (size < 4)
{
IFSTAT(packetSizeErrors++);
return ERROR_INVALID_DATA;
}
if (bcspHeader->checksum != bcspHeader->GetChecksum())
{
IFDBG(DebugOut(DEBUG_BCSP_SYNC, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> Header checksum error"), name));
IFSTAT(headerCrcErrors++);
return ERROR_INVALID_DATA;
}
if (bcspHeader->crcPresent)
{
if (size < 6 || (DWORD) bcspHeader->payloadLength + 6 > size)
{
IFSTAT(packetSizeErrors++);
return ERROR_INVALID_DATA;
}
}
else
{
if ((DWORD) bcspHeader->payloadLength + 4 > size)
{
IFSTAT(packetSizeErrors++);
return ERROR_INVALID_DATA;
}
}
if (bcspHeader->crcPresent && bcspHeader->payloadLength)
{
unsigned short crc;
unsigned char* bchsChecksum = bchsPayload + bcspHeader->payloadLength;
CalculateCRC(buffer, bcspHeader->payloadLength + sizeof(BCSPHeader), &crc);
if (((*bchsChecksum) << 8 | (*(bchsChecksum + 1))) != crc)
{
IFDBG(DebugOut(DEBUG_BCSP_SYNC, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> Payload checksum error"), name));
IFSTAT(packetCrcErrors++);
return ERROR_INVALID_DATA;
}
}
if (!bcspHeader->protocolType && (bcspHeader->protocolID == 1))
{
if (bcspHeader->payloadLength != 4)
{
return ERROR_INVALID_DATA;
}
EnterCriticalSection(&lock);
if (!memcmp(bchsPayload, syncPayload, sizeof(syncPayload)))
{
IFDBG(DebugOut(DEBUG_BCSP_SYNC, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> RECV: SYNC"), name));
if (state == BCSP_STATE_RUNNING)
{
LinkLost();
}
sendSyncResp = TRUE;
}
else if (!memcmp(bchsPayload, syncRespPayload, sizeof(syncRespPayload)))
{
IFDBG(DebugOut(DEBUG_BCSP_SYNC, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> RECV: SYNC RESP"), name));
state = BCSP_STATE_CONF;
}
else if (!memcmp(bchsPayload, confPayload, sizeof(confPayload)))
{
IFDBG(DebugOut(DEBUG_BCSP_SYNC, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> RECV: CONF"), name));
sendConfResp = TRUE;
}
else if (!memcmp(bchsPayload, confRespPayload, sizeof(confRespPayload)))
{
IFDBG(DebugOut(DEBUG_BCSP_SYNC, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> RECV: CONF RESP"), name));
state = BCSP_STATE_RUNNING;
SetEvent(inSyncEvent);
}
SetEvent(writePacketEvent);
LeaveCriticalSection(&lock);
}
else
{
EnterCriticalSection(&lock);
if (state == BCSP_STATE_RUNNING)
{
BOOL changed = FALSE;
if ((!bcspHeader->protocolType && !bcspHeader->payloadLength && !bcspHeader->seq) || (bcspHeader->protocolType &&
bcspHeader->ack != transmitPositionUnacknowledged))
{
unsigned char index;
if (transmitPositionUnacknowledged == bcspHeader->ack)
{
IFDBG(DebugOut(DEBUG_BCSP_RUN, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> CHIP DIDN'T UNDERSTAND DATA, RESENDING"), name));
for (index = 0; index < 8; index++)
{
if (transmitQueue[index].sent)
{
IFDBG(DebugOut(DEBUG_BCSP_RUN, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> %u MARKED SENT"), name, index));
IFSTAT(retransmissions++);
}
transmitQueue[index].sent = FALSE;
}
transmitWindow = 4;
transmitPosition = transmitPositionUnacknowledged;
if (++transmitQueue[transmitPosition].retries == 20)
{
LinkLost();
}
else
{
changed = TRUE;
}
}
else
{
for (index = transmitPositionUnacknowledged; index != bcspHeader->ack; index = (++index) & 0x07)
{
if (transmitQueue[index].sent)
{
free(transmitQueue[index].buffer);
transmitQueue[index].present = FALSE;
transmitQueue[index].sent = FALSE;
transmitQueue[index].buffer = NULL;
transmitPositionUnacknowledged = (++transmitPositionUnacknowledged) & 0x07;
transmitWindow++;
ReleaseSemaphore(transmitHandle, 1, NULL);
changed = TRUE;
}
else
{
IFDBG(DebugOut(DEBUG_BCSP_RUN, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> NOT ACK (%u)"), name, index));
break;
}
}
}
}
if (!bcspHeader->protocolType)
{
if (bcspHeader->protocolID == BCSP_CHANNEL_SCO)
{
free(incomingSCOData.buffer);
incomingSCOData.buffer = malloc(bcspHeader->payloadLength);
if (incomingSCOData.buffer)
{
memcpy(incomingSCOData.buffer, bchsPayload, bcspHeader->payloadLength);
incomingSCOData.size = bcspHeader->payloadLength;
SetEvent(packetAvailable);
}
}
if (changed)
{
SetEvent(writePacketEvent);
}
}
else
{
if (bcspHeader->payloadLength && bcspHeader->seq == receiveSequence)
{
if (bcspHeader->protocolID == BCSP_CHANNEL_BCCMD)
{
bccmdBuffer = malloc(bcspHeader->payloadLength);
if (bccmdBuffer)
{
bccmdSize = bcspHeader->payloadLength;
memcpy(bccmdBuffer, bchsPayload, bcspHeader->payloadLength);
}
receiveSequence = (++receiveSequence) & 0x07;
SetEvent(bccmdEvent);
}
else
{
if (!receiveQueue[receiveInsertPosition].present)
{
receiveQueue[receiveInsertPosition].buffer = malloc(bcspHeader->payloadLength);
if (receiveQueue[receiveInsertPosition].buffer)
{
IFDBG(DebugOut(DEBUG_BCSP_RUN, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> PACKET RECV"), name));
memcpy(receiveQueue[receiveInsertPosition].buffer, bchsPayload, bcspHeader->payloadLength);
receiveQueue[receiveInsertPosition].channel = (BcspChannelT) bcspHeader->protocolID;
receiveQueue[receiveInsertPosition].size = bcspHeader->payloadLength;
receiveQueue[receiveInsertPosition].present = TRUE;
receiveInsertPosition = (++receiveInsertPosition) & 0x07;
SetEvent(packetAvailable);
IFSTAT(receiveReady++);
}
receiveSequence = (++receiveSequence) & 0x07;
}
}
}
else
{
sendTransmitAck = TRUE;
}
IFSTAT(receiveTotal++);
sendTransmitAck = TRUE;
SetEvent(writePacketEvent);
}
}
IFDBG(DebugOut(DEBUG_BCSP_RUN, TEXT("<BcspCommunication::DecodeBCSPPacket@%s> PACKET IN (TIME: %u, TYPE: %u, CHL: %u, ACK: %u, SEQ: %u, SIZE: %u)"), name, GetTickCount(), bcspHeader->protocolType, bcspHeader->protocolID, bcspHeader->ack, bcspHeader->seq, bcspHeader->payloadLength));
if (bcspHeader->payloadLength && bchsPayload)
{
IFDBG(DumpBuff(DEBUG_BCSP_MSG, bchsPayload, bcspHeader->payloadLength));
}
LeaveCriticalSection(&lock);
}
return ERROR_SUCCESS;
}
#ifdef BCSP_TEST_MODE
DWORD BcspCommunication::DisableTestMode()
{
enableTestMode = FALSE;
return ERROR_SUCCESS;
}
DWORD BcspCommunication::EnableTestMode(BcspProperbilityT* properbility)
{
this->properbility = *properbility;
enableTestMode = TRUE;
return ERROR_SUCCESS;
}
#endif
BcspStatusT BcspCommunication::GetCommunicationStatus()
{
BcspStatusT result;
if (serialPortHandle != INVALID_HANDLE_VALUE)
{
if (state == BCSP_STATE_RUNNING)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -