📄 bthid.cxx
字号:
gpState->pCalls = pCall;
else {
SCall *pLast = gpState->pCalls;
while (pLast->pNext)
pLast = pLast->pNext;
pLast->pNext = pCall;
}
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Allocated call 0x%08x what = 0x%02x\n", pCall, fWhat));
return pCall;
}
static void DeleteCall (SCall *pCall) {
if (pCall == gpState->pCalls)
gpState->pCalls = pCall->pNext;
else {
SCall *pParent = gpState->pCalls;
while (pParent && (pParent->pNext != pCall))
pParent = pParent->pNext;
if (! pParent) {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: call not in list in DeleteCall!\n"));
return;
}
pParent->pNext = pCall->pNext;
}
CloseHandle (pCall->hEvent);
svsutil_FreeFixed (pCall, gpState->pfmdCalls);
}
static SCall *VerifyCall (SCall *pCall) {
SCall *p = gpState->pCalls;
while (p && (p != pCall))
p = p->pNext;
return p;
}
static SCall *FindCall (unsigned int fOp) {
SCall *p = gpState->pCalls;
while (p && (p->fWhat != fOp))
p = p->pNext;
return p;
}
static SCall *FindCall (Link *pLink, unsigned int fOp) {
SCall *p = gpState->pCalls;
while (p && ((p->pLink != pLink) || (p->fWhat != fOp)))
p = p->pNext;
return p;
}
static HidDevice *VerifyDevice (HidDevice *pDev) {
HidDevice *pD = gpState->pHIDs;
while (pD && (pD != pDev))
pD = pD->pNext;
return pD;
}
static HidDevice *FindDevice (BD_ADDR *pba) {
HidDevice *pD = gpState->pHIDs;
while (pD && (pD->b != *pba))
pD = pD->pNext;
return pD;
}
static void DeleteDevice (HidDevice *pDev) {
if (pDev == gpState->pHIDs)
gpState->pHIDs = pDev->pNext;
else {
HidDevice *p = gpState->pHIDs;
while (p->pNext != pDev)
p = p->pNext;
p->pNext = pDev->pNext;
}
delete pDev;
// Signal Reconnect thread that a device has been deleted
SetEvent(gpState->hReconnectEvent);
}
static Link *VerifyLink (Link *pLink) {
Link *p = gpState->pLinks;
while (p && (p != pLink))
p = p->pNext;
return p;
}
static Link *FindLink (BD_ADDR *pba) {
Link *pL = gpState->pLinks;
while (pL && (pL->b != *pba))
pL = pL->pNext;
return pL;
}
static Link *FindLink (BD_ADDR *pba, unsigned short psm) {
Link *pL = gpState->pLinks;
while (pL && ((pL->b != *pba) || (pL->psm != psm)))
pL = pL->pNext;
return pL;
}
static Link *FindLink (unsigned short cid) {
Link *p = gpState->pLinks;
while (p && (p->cid != cid))
p = p->pNext;
return p;
}
static void DisconnectDevice (HidDevice *pDev, BOOL fSendVCD) {
for ( ; ; ) {
Link *pLink = FindLink (&pDev->b);
if (! pLink)
return;
if (fSendVCD && pDev->fVirtualCable) {
// Send VIRTUAL_CABLE_DISCONNECT
BTHHIDPacket packet;
packet.SetHeader(gbUnplugHeader);
(void) WritePacket (pDev, &packet, 0, NULL, BTH_PSM_CONTROL);
}
HIDCloseCID_Int (pLink->cid);
}
}
static DWORD WINAPI HidReconnectThread (LPVOID lpArg) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Started reconnect thread\n"));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
while (1) {
DWORD dwTimeout;
if (! gpState->fIsRunning) {
break;
}
HANDLE h = gpState->hReconnectEvent;
if (gpState->pHIDs)
dwTimeout = HID_RECONNECT_INTERVAL;
else
dwTimeout = INFINITE;
gpState->AddRef ();
gpState->Unlock ();
DWORD dwWait = WaitForSingleObject(h, dwTimeout);
gpState->Lock ();
gpState->DelRef ();
if (WAIT_TIMEOUT == dwWait) {
HidDevice *pD = gpState->pHIDs;
while (pD) {
if ((!pD->fHaveControl || !pD->fHaveInterrupt) && !pD->fReconnectInitiate && pD->fNormallyConnectable) {
int iRes = ERROR_SUCCESS;
unsigned short cidControl = 0;
if (!pD->fHaveControl) {
gpState->AddRef ();
gpState->Unlock ();
iRes = HIDConnect_Int (&pD->b, BTH_PSM_CONTROL, &cidControl);
gpState->Lock ();
gpState->DelRef ();
}
if (iRes == ERROR_SUCCESS) {
unsigned short cidInterrupt = 0;
if (!pD->fHaveInterrupt) {
gpState->AddRef ();
gpState->Unlock ();
iRes = HIDConnect_Int (&pD->b, BTH_PSM_INTERRUPT, &cidInterrupt);
if (iRes != ERROR_SUCCESS) {
if (cidControl)
HIDCloseCID_Int (cidControl);
}
gpState->Lock ();
gpState->DelRef ();
}
}
}
pD = pD->pNext;
}
}
}
gpState->Unlock ();
return ERROR_SUCCESS;
}
static DWORD WINAPI DeviceTimeout (LPVOID lpArg) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Timeout on hid device\n"));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
HidDevice *pDev = VerifyDevice ((HidDevice *)lpArg);
if (pDev && pDev->ckDeviceTimeout && (! FindLink (&pDev->b))) {
DeleteDevice(pDev);
}
gpState->Unlock ();
return ERROR_SUCCESS;
}
static DWORD WINAPI ConnectionTimeout (LPVOID lpArg) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Connection Timeout on hid device\n"));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
HidDevice *pDev = VerifyDevice ((HidDevice *)lpArg);
if (pDev && pDev->ckConnectionTimeout && (! (pDev->fHaveControl && pDev->fHaveInterrupt))) {
pDev->ckConnectionTimeout = 0;
DisconnectDevice (pDev, TRUE);
}
gpState->Unlock ();
return ERROR_SUCCESS;
}
static void DeleteLink (Link *pLink) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: delete link for bd_addr %04x%08x cid 0x%04x\n", pLink->b.NAP, pLink->b.SAP, pLink->cid));
if (pLink == gpState->pLinks)
gpState->pLinks = pLink->pNext;
else {
Link *pParent = gpState->pLinks;
while (pParent && (pParent->pNext != pLink))
pParent = pParent->pNext;
if (! pParent) {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: link to be deleted not in list\n"));
return;
}
pParent->pNext = pLink->pNext;
}
SCall *pC = gpState->pCalls;
while (pC) {
if (pC->pLink == pLink) {
if (pC->fAutoClean) {
DeleteCall (pC);
pC = gpState->pCalls;
continue;
} else if (! pC->fComplete) {
pC->pLink = NULL;
pC->fComplete = TRUE;
pC->iResult = ERROR_CONNECTION_UNAVAIL;
SetEvent (pC->hEvent);
} else {
pC->pLink = NULL;
if (pC->iResult == ERROR_SUCCESS)
pC->iResult = ERROR_CONNECTION_UNAVAIL;
}
}
pC = pC->pNext;
}
HidDevice *pDev = FindDevice (&pLink->b);
if (pDev) {
if (pLink->psm == BTH_PSM_CONTROL)
pDev->fHaveControl = FALSE;
else
pDev->fHaveInterrupt = FALSE;
if (! pDev->ckDeviceTimeout)
pDev->ckDeviceTimeout = gpState->pSchedule->ScheduleEvent (DeviceTimeout, pDev, BTH_PARSER_TIMEOUT);
}
svsutil_FreeFixed (pLink, gpState->pfmdLinks);
}
static void HID_BufferFree (BD_BUFFER *pBuf) {
if (! pBuf->fMustCopy)
g_funcFree (pBuf, g_pvFreeData);
}
static void HID_BufferFreeArray (BD_BUFFER **ppArray, int carray) {
for (int i = 0 ; i < carray ; ++i)
HID_BufferFree (ppArray[i]);
}
static BD_BUFFER *HID_BufferAlloc (int cSize) {
SVSUTIL_ASSERT (cSize > 0);
BD_BUFFER *pRes = (BD_BUFFER *)g_funcAlloc (cSize + sizeof (BD_BUFFER), g_pvAllocData);
pRes->cSize = cSize;
pRes->cEnd = pRes->cSize;
pRes->cStart = 0;
pRes->fMustCopy = FALSE;
pRes->pFree = HID_BufferFree;
pRes->pBuffer = (unsigned char *)(pRes + 1);
return pRes;
}
static BD_BUFFER *HID_BufferCopy (BD_BUFFER *pBuffer) {
BD_BUFFER *pRes = HID_BufferAlloc (pBuffer->cSize);
pRes->cSize = pBuffer->cSize;
pRes->cStart = pBuffer->cStart;
pRes->cEnd = pBuffer->cEnd;
pRes->fMustCopy = FALSE;
pRes->pFree = HID_BufferFree;
pRes->pBuffer = (unsigned char *)(pRes + 1);
memcpy (pRes->pBuffer, pBuffer->pBuffer, pRes->cSize);
return pRes;
}
static DWORD WINAPI StackDown (LPVOID lpVoid) { // Attention - must increment ref count before calling this!
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Stack Down\n"));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
gpState->DelRef ();
if ((! gpState->fIsRunning) || (! gpState->fConnected)) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
gpState->fConnected = FALSE;
Link *pLink = gpState->pLinks;
while (gpState->pLinks)
DeleteLink (gpState->pLinks);
SCall *pC = gpState->pCalls;
while (pC) {
if (pC->fAutoClean) {
DeleteCall (pC);
pC = gpState->pCalls;
continue;
} else if (! pC->fComplete) {
pC->pLink = NULL;
pC->fComplete = TRUE;
pC->iResult = ERROR_CONNECTION_UNAVAIL;
SetEvent (pC->hEvent);
} else {
pC->pLink = NULL;
if (pC->iResult == ERROR_SUCCESS)
pC->iResult = ERROR_CONNECTION_UNAVAIL;
}
pC = pC->pNext;
}
gpState->Unlock ();
return ERROR_SUCCESS;
}
static DWORD WINAPI StackUp (LPVOID lpVoid) { // Attention - must increment ref count before calling this!
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Stack Up\n"));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
gpState->DelRef ();
if ((! gpState->fIsRunning) || gpState->fConnected) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
gpState->fConnected = TRUE;
gpState->Unlock ();
return ERROR_SUCCESS;
}
static HidDevice *MakeNewDevice (BD_ADDR *pba, int fIncoming) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: MakeNewDevice %04x%08x\n", pba->NAP, pba->SAP));
HidDevice *pDev = new HidDevice (pba);
if (! pDev)
return NULL;
if (! pDev->FillPersistentParameters (fIncoming)) {
IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: MakeNewDevice %04x%08x fails to retrieve pairing information\n", pba->NAP, pba->SAP));
delete pDev;
return NULL;
}
pDev->pNext = gpState->pHIDs;
gpState->pHIDs = pDev;
pDev->fIncoming = fIncoming;
// Signal Reconnect thread that we added a device.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -