📄 bthid.cxx
字号:
return p;
}
static void DisconnectDevice (HidDevice *pDev) {
for ( ; ; ) {
Link *pLink = FindLink (&pDev->b);
if (! pLink)
return;
HIDCloseCID_Int (pLink->cid);
}
}
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))) {
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;
}
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);
}
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 void ProcessExited (HANDLE hProc) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: ProcessExited 0x%08x\n", hProc));
if (! gpState)
return;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return;
}
gpState->Unlock ();
}
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;
return pDev;
}
static DWORD WINAPI AuthenticateDevice (LPVOID lpArg) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: authentication request on hid device\n"));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = VerifyCall ((SCall *)lpArg);
HidDevice *pDev = pCall ? FindDevice (&pCall->pLink->b) : NULL;
if (! pDev) {
IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: authentication request on nonexistent hid device\n"));
gpState->Unlock ();
return ERROR_SUCCESS;
}
int fAuth = pDev->fAuthenticate;
int fEncr = pDev->fEncrypt;
int fIncoming = pDev->fIncoming;
unsigned char id = pCall->l2cap_id;
unsigned short cid = pCall->pLink->cid;
BD_ADDR b = pDev->b;
BT_ADDR bt = SET_NAP_SAP (b.NAP, b.SAP);
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: authentication request on hid device %04x%08x cid 0x%04x auth: %d, encr: %d, incoming: %d\n", b.NAP, b.SAP, fAuth, fEncr, fIncoming));
HANDLE hL2CAP = gpState->hL2CAP;
L2CA_ConfigReq_In pCallbackConfig = gpState->l2cap_if.l2ca_ConfigReq_In;
L2CA_ConnectResponse_In pCallbackConnect = gpState->l2cap_if.l2ca_ConnectResponse_In;
gpState->Unlock ();
if (fIncoming) {
__try {
pCallbackConnect (hL2CAP, NULL, &b, id, cid, 1, 1);
} __except (1) {
}
}
int iErr = ERROR_SUCCESS;
if (fAuth)
iErr = BthAuthenticate (&bt);
if (fEncr && (iErr == ERROR_SUCCESS))
iErr = BthSetEncryption (&bt, TRUE);
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
pDev = VerifyDevice (pDev);
if (! pDev) {
IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: authentication request : device disappeared enroute\n"));
gpState->Unlock ();
return ERROR_SUCCESS;
}
gpState->Unlock ();
if (fIncoming) {
unsigned short result = 0;
if (iErr != ERROR_SUCCESS)
result = 3;
__try {
pCallbackConnect (hL2CAP, NULL, &b, id, cid, result, 0);
} __except (1) {
}
if (result == 0) {
iErr = ERROR_INTERNAL_ERROR;
__try {
iErr = pCallbackConfig (hL2CAP, pCall, cid, BTH_MTU_MAX, 0xffff, NULL, 0, NULL);
} __except (1) {
}
}
if (iErr != ERROR_SUCCESS)
hiddev_lCallAborted (pCall, iErr);
} else {
if (iErr == ERROR_SUCCESS) {
iErr = ERROR_INTERNAL_ERROR;
__try {
iErr = pCallbackConfig (hL2CAP, pCall, cid, BTH_MTU_MAX, 0xffff, NULL, 0, NULL);
} __except (1) {
}
} else
HIDCloseCID_Int (cid);
if (iErr != ERROR_SUCCESS)
hiddev_lCallAborted (pCall, iErr);
}
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: authentication request completes with status %d\n", iErr));
return ERROR_SUCCESS;
}
static int WriteControlPacket (void *lpHidDevice, BTHHIDPacket *pSource, int iTimeout, BTHHIDPacket **ppRes) {
int iRes = ERROR_SUCCESS;
for ( ; ; ) {
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
HidDevice *pDev = VerifyDevice ((HidDevice *)lpHidDevice);
if (! pDev) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
HANDLE hevtComplete = pDev->hevtTransFree;
if (pDev->fTrans) { // We don't have the transaction
gpState->Unlock ();
if (iTimeout == 0)
return ERROR_TIMEOUT;
DWORD dwTicks = GetTickCount ();
WaitForSingleObject (hevtComplete, iTimeout);
if (iTimeout != INFINITE) {
iTimeout -= GetTickCount () - dwTicks;
if (iTimeout < 0)
iTimeout = 0;
}
continue;
}
Link *pLink = FindLink (&pDev->b, BTH_PSM_CONTROL);
if (! pLink) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
BD_BUFFER *frags[BTH_MAX_FRAGMENTS];
int cfrags = 0;
pSource->SetMTU(pLink->mtu);
for (cfrags = 0 ; cfrags < BTH_MAX_FRAGMENTS ; ++cfrags) {
int cChunk = 0;
pSource->GetPayloadChunk (NULL, 0, &cChunk);
frags[cfrags] = HID_BufferAlloc (cChunk + gpState->cHeaders + gpState->cTrailers);
if (! frags[cfrags]) {
HID_BufferFreeArray (frags, cfrags);
gpState->Unlock ();
return ERROR_OUTOFMEMORY;
}
frags[cfrags]->cStart = gpState->cHeaders;
frags[cfrags]->cEnd = frags[cfrags]->cSize - gpState->cTrailers;
if (! pSource->GetPayloadChunk(frags[cfrags]->pBuffer + frags[cfrags]->cStart, cChunk, &cChunk))
break;
}
if (cfrags == BTH_MAX_FRAGMENTS) {
HID_BufferFreeArray (frags, cfrags);
gpState->Unlock ();
return ERROR_OUTOFMEMORY;
}
++cfrags;
HANDLE hL2CAP = gpState->hL2CAP;
L2CA_DataDown_In pCallback = gpState->l2cap_if.l2ca_DataDown_In;
unsigned short usCID = pLink->cid;
HANDLE hevt = pDev->hevtTrans;
pDev->fTrans = TRUE; // We own the transaction
ResetEvent (hevtComplete);
gpState->Unlock ();
iRes = ERROR_SUCCESS;
int iSent = 0;
__try {
for (iSent = 0 ; iSent < cfrags ; ++iSent) {
if (ERROR_SUCCESS != (iRes = pCallback (hL2CAP, NULL, usCID, frags[iSent])))
break;
}
} __except (1) {
iRes = ERROR_EXCEPTION_IN_SERVICE;
}
if (iRes == ERROR_SUCCESS)
WaitForSingleObject (hevt, iTimeout);
if (! gpState) {
SetEvent (hevtComplete);
return ERROR_SERVICE_NOT_ACTIVE;
}
gpState->Lock ();
if (iRes != ERROR_SUCCESS)
HID_BufferFreeArray (frags + iSent, cfrags - iSent);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -