📄 hcibcsp.cpp
字号:
dwSize = sizeof(dwData);
if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"Priority256", NULL, &dwType, (LPBYTE)&dwData, &dwSize)) &&
(dwType == REG_DWORD) && (dwSize == sizeof(dwData)))
dwThreadPriority = dwData;
RegCloseKey (hk);
}
IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[BCSP] Opening port %s (rate %d) for I/O with unit\n", szComPortName, dwBaud));
hFile = CreateFile(szComPortName,
GENERIC_READ | GENERIC_WRITE,
0, // comm devices must be opened w/exclusive-access
NULL, // no security attrs
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_ATTRIBUTE_NORMAL, // overlapped I/O
NULL // hTemplate must be NULL for comm devices
);
if (hFile == INVALID_HANDLE_VALUE) {
IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed CreateFile in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
return FALSE;
}
if (! SetupComm (hFile, 4096, 4096)) {
CloseCommPort ();
IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed SetupComm in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
return FALSE;
}
// purge any information in the buffer
// if ( ! PurgeComm (hFile, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR )) {
// CloseCommPort ();
//
// IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed PurgeComm in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
// return FALSE;
// }
DCB dcb;
if (! GetCommState(hFile, &dcb)) {
CloseCommPort ();
IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed GetCommState in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
return FALSE;
}
dcb.BaudRate = dwBaud;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fAbortOnError = FALSE;
dcb.ByteSize =8;
dcb.fParity = TRUE;
dcb.Parity = EVENPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.ErrorChar = -64;
if (! SetCommState(hFile, &dcb)) {
CloseCommPort ();
IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed SetCommState in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
return FALSE;
}
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 1 ;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
CommTimeOuts.ReadTotalTimeoutConstant = 1000 ;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ;
CommTimeOuts.WriteTotalTimeoutConstant = 1000 ;
if (! SetCommTimeouts (hFile, &CommTimeOuts)) {
CloseCommPort ();
IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] Failed SetCommTimeouts in BCSP HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
return FALSE;
}
#if defined (BT_USE_CELOG)
if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_BASE, L"software\\microsoft\\bluetooth\\debug", 0, KEY_READ, &hk)) {
DWORD dwType;
DWORD dw;
DWORD dwSize = sizeof(dw);
if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"celog", NULL, &dwType, (LPBYTE)&dw, &dwSize)) &&
(dwType == REG_DWORD) && (dwSize == sizeof(dw)) && dw)
g_fCeLog = IsCeLogStatus (CELOGSTATUS_ENABLED_GENERAL);
RegCloseKey (hk);
}
if (g_fCeLog) {
#if defined (SDK_BUILD)
CELOGSDK_START ();
#endif
BTH_CELOG_START_DATA sd;
sd.eTransport = BCSP;
GetLocalTime (&sd.st);
wsprintf (sd.szDriverString, L"BCSP Driver v. 0x%08x on %s", HCI_INTERFACE_VERSION_1_1, szComPortName);
CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, &sd, sizeof(sd), 0, CELZONE_ALWAYSON, CELOG_FLAG_START);
}
#endif
g_fShutDown = FALSE;
ReinitGlobals ();
g_pWriteBuff = (unsigned char*) malloc (MAX_BUFFER_SIZE);
if (! g_pWriteBuff) {
CloseCommPort ();
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection failed: Error allocating write buffer.\n"));
return FALSE;
}
g_hCanTransmitPacket = CreateEvent (NULL, FALSE, FALSE, NULL);
g_hWriteThreadEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
g_hPacketReady = CreateEvent (NULL, FALSE, FALSE, NULL);
g_pfmdPacketDescr = svsutil_AllocFixedMemDescr (sizeof(SerialPacket), 10);
InitializeCriticalSection (&g_csBCSP);
InitializeCriticalSection (&g_csPackets);
g_hReadThread = CreateThread (NULL, 0, COMReadThread, NULL, 0, NULL);
g_hWriteThread = CreateThread (NULL, 0, BCSPWriteThread, NULL, 0, NULL);
CeSetThreadPriority(g_hReadThread, dwThreadPriority);
CeSetThreadPriority(g_hWriteThread, dwThreadPriority);
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection: Attempting BCSP link establishment.\n"));
if (! BCSPLinkEstablishment()) {
HCI_CloseConnection ();
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection failed: Could not complete BCSP link establishment.\n"));
return FALSE;
}
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection: BCSP link establishment complete.\n"));
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_OpenConnection: Successful.\n"));
return TRUE;
}
void HCI_CloseConnection (void) {
if (g_fShutDown) {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_CloseConnection: already in shutdown.\n"));
return;
}
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_CloseConnection: entered.\n"));
CloseCommPort ();
EnterCriticalSection (&g_csBCSP);
g_fShutDown = TRUE;
SetEvent (g_hCanTransmitPacket);
CloseHandle(g_hCanTransmitPacket);
SetEvent (g_hWriteThreadEvent);
CloseHandle(g_hWriteThreadEvent);
SetEvent (g_hPacketReady);
CloseHandle (g_hPacketReady);
if (g_pWriteBuff) {
free (g_pWriteBuff);
g_pWriteBuff = NULL;
}
while (g_pTransmitPackets) {
BCSPPacketListNode *pNext = g_pTransmitPackets->next;
delete g_pTransmitPackets;
g_pTransmitPackets = pNext;
}
while (g_pSCOTransmitPackets) {
BCSPPacketListNode *pNext = g_pSCOTransmitPackets->next;
delete g_pSCOTransmitPackets;
g_pSCOTransmitPackets = pNext;
}
LeaveCriticalSection (&g_csBCSP);
DeleteCriticalSection(&g_csBCSP);
if (g_hWriteThread) {
WaitForSingleObject (g_hWriteThread, INFINITE);
CloseHandle (g_hWriteThread);
}
if (g_hReadThread) {
WaitForSingleObject (g_hReadThread, INFINITE);
CloseHandle (g_hReadThread);
}
EnterCriticalSection (&g_csPackets);
svsutil_ReleaseFixedNonEmpty (g_pfmdPacketDescr);
g_pfmdPacketDescr = NULL;
g_pPackets = NULL;
LeaveCriticalSection (&g_csPackets);
DeleteCriticalSection(&g_csPackets);
ReinitGlobals ();
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_CloseConnection: success\n"));
}
int HCI_ReadPacket (HCI_TYPE *peType, BD_BUFFER *pBuff) {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket\n"));
if(pBuff->cSize < PACKET_SIZE_R) {
IFDBG(DebugOut(DEBUG_ERROR, L"[BCSP] HCI_ReadPacket failed: passed in buffer is too small. ERROR\n"));
return FALSE;
}
while (TRUE) { // loop through ack packets, link establishment packets,
// and other packets the client doesn't care about
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] In HCI_ReadPacket...\n"));
BCSPHeader header;
if (! ReadFromCOMPort(&header, pBuff->pBuffer))
break;
if (header.checksum != header.GetChecksum()) {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket: packet checksum is invalid. Discarding.\n"));
continue;
}
if((header.protocolID == 1) && (header.protocolType == 0) && (header.payloadLength == 4)) {
const unsigned char syncPayload[] = { 0xDA, 0xDC, 0xED, 0xED };
const unsigned char confPayload[] = { 0xAD, 0xEF, 0xAC, 0xED };
if(0 == memcmp(syncPayload, pBuff->pBuffer, 4)) { // SYNC received so send SYNC-RESP
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : got SYNC scheduling SYNC-RESP.\n"));
InterlockedIncrement ((LONG *)&g_iRxSyncs);
SetEvent(g_hWriteThreadEvent);
} else if(0 == memcmp(confPayload, pBuff->pBuffer, 4)) { // CONF received so send CONF-RESP
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : got CONF scheduling CONF-RESP.\n"));
InterlockedIncrement ((LONG *)&g_iRxConfs);
SetEvent(g_hWriteThreadEvent);
} else
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : got something strange, discarding...\n"));
continue;
}
if (g_fShutDown)
break;
// we now get into the processing stage so enter the critical section
SVSLocalCriticalSection cs(&g_csBCSP);
if (g_fShutDown)
break;
// For unreliable data there is no need to send an ACK
if (header.protocolType) {
// now look for a new ack value to free packets from the transmit window
if (header.ack != g_iRxAck) {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : received ACK = %d, scheduling ACK processing\n", header.ack));
g_iRxAckLast = header.ack;
SetEvent(g_hWriteThreadEvent);
}
// if the packet is a pure ack packet continue
if (! header.payloadLength) {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : no payload, ignoring\n"));
continue;
}
if(header.seq == g_iTxAck) { // this is the sequence number we were expecting
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : packet in sequence, scheduling ACK send\n"));
g_iTxAck = (g_iTxAck + 1) & BCSP_SEQ_MASK;
if ((g_iTxUnack++) == 0)
g_dwTxAckDue = GetTickCount () + BCSP_ACTIVE_TIMEOUT / 2;
SetEvent(g_hWriteThreadEvent);
} else {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket : packet out of sequence, scheduling immediate ACK send\n"));
g_iTxUnack = BCSP_SEQ_MASK + 1;
g_dwTxAckDue = GetTickCount ();
SetEvent(g_hWriteThreadEvent);
continue; // keep reading
}
}
// the packet has a payload so if it is one that the client wants (ACL data or HCI event) return it
BOOL success = TRUE; // return this packet if true after switch
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got a packet.\n"));
switch(header.protocolID) {
case IO_DATA_PROTOCOL_NULL:
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got a null ID packet. Discarding.\n"));
success = FALSE;
break;
case IO_DATA_PROTOCOL_HCI_CMD_EVT:
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got an HCI event packet.\n"));
*peType = EVENT_PACKET;
break;
case IO_DATA_PROTOCOL_HCI_ACL:
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got an ACL data packet.\n"));
*peType = DATA_PACKET_ACL;
break;
case IO_DATA_PROTOCOL_HCI_SCO:
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got a SCO data packet.\n"));
*peType = DATA_PACKET_SCO;
break;
case IO_DATA_PROTOCOL_CHIP_MGT_CH:
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got a chip management packet.\n"));
success = FALSE;
break;
default:
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_ReadPacket got some unexepected packet. Discarding.\n"));
success = FALSE;
break;
}
if (! success)
continue; // keep reading for a suitable packet
pBuff->cEnd = header.payloadLength;
pBuff->cStart = 0;
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] Packet received:\n"));
IFDBG(DumpBuff (DEBUG_HCI_TRANSPORT, pBuff->pBuffer, pBuff->cEnd));
return TRUE;
}
IFDBG(DebugOut(DEBUG_ERROR, L"[BCSP] HCI_ReadPacket failed. ERROR\n"));
return FALSE;
}
int HCI_WritePacket (HCI_TYPE eType, BD_BUFFER *pBuff) {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_WritePacket\n"));
IFDBG(DumpBuff (DEBUG_HCI_DUMP, pBuff->pBuffer + pBuff->cStart, BufferTotal (pBuff)));
// create a packet and set the payload and header flags
BCSPPacketListNode *pPacketListNode = new BCSPPacketListNode;
if (! pPacketListNode) {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"HCI_WritePacket: OOM!\n"));
return FALSE;
}
pPacketListNode->packet.SetData(pBuff->pBuffer + pBuff->cStart, BufferTotal (pBuff));
if(eType == COMMAND_PACKET)
pPacketListNode->packet.header.protocolID = IO_DATA_PROTOCOL_HCI_CMD_EVT;
else if(eType == DATA_PACKET_ACL)
pPacketListNode->packet.header.protocolID = IO_DATA_PROTOCOL_HCI_ACL;
else if(eType == DATA_PACKET_SCO)
pPacketListNode->packet.header.protocolID = IO_DATA_PROTOCOL_HCI_SCO;
pPacketListNode->packet.header.crcPresent = 0;
pPacketListNode->packet.fNewPacket = TRUE;
pPacketListNode->next = 0;
// the remaining header fields are filled out by BCSPWriteThread prior to being sent across the wire
if (pPacketListNode->packet.header.protocolID == IO_DATA_PROTOCOL_HCI_SCO) {
pPacketListNode->packet.header.protocolType = 0;
pPacketListNode->packet.header.seq = 0;
pPacketListNode->packet.header.ack = 0;
}
else {
pPacketListNode->packet.header.protocolType = 1; // reliable connection type
}
// now wait for an empty slot in the transmit queue to open up
for ( ; ; ) {
if (g_fShutDown) {
IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] HCI_WritePacket : shutting down!\n"));
return FALSE;
}
EnterCriticalSection (&g_csBCSP);
if (g_fShutDown) {
IFDBG(DebugOut (DEBUG_ERROR, L"[BCSP] HCI_WritePacket : shutting down!\n"));
LeaveCriticalSection (&g_csBCSP);
return FALSE;
}
if (pPacketListNode->packet.header.protocolID == IO_DATA_PROTOCOL_HCI_SCO) {
if (GetSCOListSize () < BCSP_WIN_SIZE_SCO)
break;
}
else {
if (GetListSize () < BCSP_WIN_SIZE)
break;
}
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_WritePacket :: waiting for empty slot...\n"));
LeaveCriticalSection (&g_csBCSP);
WaitForSingleObject(g_hCanTransmitPacket, INFINITE);
}
AddToList(pPacketListNode);
#ifdef DEBUG
if (pPacketListNode->packet.header.protocolID == IO_DATA_PROTOCOL_HCI_SCO) {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_WritePacket : SCO Packet added to the list (total %d in list)\n", GetSCOListSize()));
}
else {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[BCSP] HCI_WritePacket : Packet added to the list (total %d in list)\n", GetListSize()));
}
#endif
SetEvent(g_hWriteThreadEvent);
LeaveCriticalSection (&g_csBCSP);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -