📄 bthid.cxx
字号:
if (pBuffer->pFree)
pBuffer->pFree (pBuffer);
gpState->Unlock ();
return ERROR_SUCCESS;
}
static int hiddev_DisconnectInd (void *pUserContext, unsigned short cid, int iError) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Disconnect indicator on channel 0x%04x\n", cid));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Link *pLink = FindLink (cid);
if (! pLink) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
SCall *pC = gpState->pCalls;
while (pC) {
if (pC->pLink == pLink) {
if (pC->fAutoClean) {
DeleteCall (pC);
pC = gpState->pCalls;
continue;
} else if (! pC->fComplete) {
pC->fComplete = TRUE;
pC->iResult = ERROR_CONNECTION_UNAVAIL;
SetEvent (pC->hEvent);
}
}
pC = pC->pNext;
}
DeleteLink (pLink);
gpState->Unlock ();
return ERROR_SUCCESS;
}
static int hiddev_lStackEvent (void *pUserContext, int iEvent, void *pEventContext) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Stack event (L2CAP) %d\n", iEvent));
if (! gpState)
return ERROR_SUCCESS;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SUCCESS;
}
LPTHREAD_START_ROUTINE p = NULL;
if (iEvent == BTH_STACK_DISCONNECT)
hiddev_CloseDriverInstance ();
else if (iEvent == BTH_STACK_DOWN)
p = StackDown;
else if (iEvent == BTH_STACK_UP)
p = StackUp;
HANDLE h = p ? CreateThread (NULL, 0, p, NULL, 0, NULL) : NULL;
if (h) {
CloseHandle (h);
gpState->AddRef ();
}
gpState->Unlock ();
return ERROR_SUCCESS;
}
static int hiddev_lCallAborted (void *pCallContext, int iError) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Aborted call 0x%08x error %d\n", pCallContext, iError));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = VerifyCall ((SCall *)pCallContext);
if (! pCall) {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: Aborted call not found!\n"));
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
SVSUTIL_ASSERT (! pCall->fComplete);
SVSUTIL_ASSERT (! pCall->pBuffer);
Link *pLink = pCall->pLink;
if (pCall->fAutoClean)
DeleteCall (pCall);
else {
pCall->iResult = iError;
pCall->fComplete = TRUE;
pCall->pLink = NULL;
SetEvent (pCall->hEvent);
}
unsigned short disconnect_cid = 0;
if (pLink) {
if ((pLink->fStage & UP) != UP) {
if (pLink->fStage & CONNECTED)
disconnect_cid = pLink->cid;
else
DeleteLink (pLink);
} else {
disconnect_cid = pLink->cid;
pLink->fStage |= LINK_ERROR;
}
}
gpState->Unlock ();
if (disconnect_cid)
HIDCloseCID_Int (disconnect_cid);
return ERROR_SUCCESS;
}
static int hiddev_ConfigInd (void *pUserContext, unsigned char id, unsigned short cid, unsigned short usOutMTU, unsigned short usInFlushTO, struct btFLOWSPEC *pInFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Config request indicator on ch 0x%04x id %d MTU %d flush 0x%04x, flow: %s\n", cid, id, usOutMTU, usInFlushTO, pInFlow ? L"yes" : L"no"));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Link *pLink = FindLink (cid);
SCall *pCall = pLink ? FindCall (pLink, CALL_L2CAP_LINK_SETUP) : NULL;
if ((! pCall) || pCall->fComplete) {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: config setup call not found!\n"));
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
pCall->l2cap_id = id;
SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_LINK_SETUP);
SVSUTIL_ASSERT (! pCall->fComplete);
SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
SVSUTIL_ASSERT (! pCall->pBuffer);
int fAccept = FALSE;
// if ((usInFlushTO == 0xffff) && (! pInFlow)) {
pCall->iResult = ERROR_SUCCESS;
pCall->pLink->fStage |= CONFIG_IND_DONE;
pCall->pLink->mtu = usOutMTU ? usOutMTU : L2CAP_MTU;
fAccept = TRUE;
if (pLink->fStage == UP) {
pCall->fComplete = TRUE;
pCall->iResult = ERROR_SUCCESS;
SetEvent (pCall->hEvent);
if (pCall->fAutoClean)
DeleteCall (pCall);
HidDevice *pDev = FindDevice (&pLink->b);
if (pDev) {
if (pLink->psm == BTH_PSM_CONTROL)
pDev->fHaveControl = TRUE;
else
pDev->fHaveInterrupt = TRUE;
if (pDev->fHaveControl && pDev->fHaveInterrupt) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: device %04x%08x connected!\n", pDev->b.NAP, pDev->b.SAP));
if (pDev->ckConnectionTimeout) {
gpState->pSchedule->UnScheduleEvent (pDev->ckConnectionTimeout);
pDev->ckConnectionTimeout = 0;
}
} else if (! pDev->ckConnectionTimeout)
pDev->ckConnectionTimeout = gpState->pSchedule->ScheduleEvent (ConnectionTimeout, pDev, BTH_CONNECTION_TIMEOUT);
} else {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: could not find HID device - connection not accepted!\n"));
fAccept = FALSE;
}
}
// } else {
// IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: not accepting config because of flow control parameters.\n"));
// }
HANDLE hL2CAP = gpState->hL2CAP;
L2CA_ConfigResponse_In pCallback = gpState->l2cap_if.l2ca_ConfigResponse_In;
gpState->Unlock ();
__try {
pCallback (hL2CAP, NULL, id, cid, fAccept ? 0 : 2, usOutMTU, 0xffff, NULL, 0, NULL);
} __except (1) {
}
if (! fAccept)
hiddev_lCallAborted (pCall, ERROR_CONNECTION_ABORTED);
return ERROR_SUCCESS;
}
static int hiddev_ConfigReq_Out (void *pCallContext, unsigned short usResult, unsigned short usOutMTU, unsigned short usOutFlushTO, struct btFLOWSPEC *pOutFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Config req out for call 0x%08x result 0x%04x mtu %d flush 0x%04x, flow %s\n", pCallContext, usResult, usOutMTU, usOutFlushTO, pOutFlow ? L"yes" : L"no" ));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = VerifyCall ((SCall *)pCallContext);
if ((! pCall) || pCall->fComplete) {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: config setup call not found!\n"));
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_LINK_SETUP);
SVSUTIL_ASSERT (! pCall->fComplete);
SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
SVSUTIL_ASSERT (! pCall->pBuffer);
if (usResult == 0) {
Link *pLink = pCall->pLink;
SVSUTIL_ASSERT (! (pLink->fStage & CONFIG_REQ_DONE));
SVSUTIL_ASSERT (pLink->fStage & CONNECTED);
SVSUTIL_ASSERT (pLink->cid);
SVSUTIL_ASSERT (pLink->psm);
pLink->fStage |= CONFIG_REQ_DONE;
if (usOutMTU)
pLink->mtu = usOutMTU;
if (pLink->fStage == UP) {
pCall->fComplete = TRUE;
pCall->iResult = ERROR_SUCCESS;
SetEvent (pCall->hEvent);
if (pCall->fAutoClean)
DeleteCall (pCall);
HidDevice *pDev = FindDevice (&pLink->b);
if (pDev) {
if (pLink->psm == BTH_PSM_CONTROL)
pDev->fHaveControl = TRUE;
else
pDev->fHaveInterrupt = TRUE;
if (pDev->fHaveControl && pDev->fHaveInterrupt) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: device %04x%08x connected!\n", pDev->b.NAP, pDev->b.SAP));
if (pDev->ckConnectionTimeout) {
gpState->pSchedule->UnScheduleEvent (pDev->ckConnectionTimeout);
pDev->ckConnectionTimeout = 0;
}
} else if (! pDev->ckConnectionTimeout)
pDev->ckConnectionTimeout = gpState->pSchedule->ScheduleEvent (ConnectionTimeout, pDev, BTH_CONNECTION_TIMEOUT);
} else {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: could not find HID device - connection not accepted!\n"));
gpState->Unlock ();
hiddev_lCallAborted (pCallContext, ERROR_CONNECTION_ABORTED);
return ERROR_SUCCESS;
}
}
gpState->Unlock ();
return ERROR_SUCCESS;
}
gpState->Unlock ();
hiddev_lCallAborted (pCallContext, ERROR_CONNECTION_ABORTED);
return ERROR_SUCCESS;
}
static int hiddev_ConnectInd (void *pUserContext, BD_ADDR *pba, unsigned short cid, unsigned char id, unsigned short psm) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Connect indicator from %04x%08x ch 0x%04x id %d psm 0x%04x\n", pba->NAP, pba->SAP, cid, id, psm));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
unsigned short result = 0;
unsigned short status = 0;
HidDevice *pDev = FindDevice (pba);
if (! pDev) {
pDev = MakeNewDevice (pba, TRUE);
if (pDev) {
DWORD cbMaxInputReport;
// Pass the report descriptor off to the MDD
if ((NULL == pDev->pvNotifyParameter) &&
(HidMdd_Attach(
(HID_PDD_HANDLE) pDev,
pDev->blobReportDescriptor.pBlobData,
pDev->blobReportDescriptor.cbSize,
0,
0,
0,
0,
&pDev->pvNotifyParameter,
&cbMaxInputReport) == FALSE)) {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: Failed to initialize HID Mdd\n"));
return ERROR_NOT_CONNECTED;
}
}
}
if (! pDev) {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: connect indication: could not make device\n"));
result = 4;
} else if (pDev->ckDeviceTimeout) {
gpState->pSchedule->UnScheduleEvent (pDev->ckDeviceTimeout);
pDev->ckDeviceTimeout = 0;
}
SCall *pCall = NULL;
if (pDev) {
Link *pLink = (Link *)svsutil_GetFixed (gpState->pfmdLinks);
pCall = pLink ? AllocCall (CALL_L2CAP_LINK_SETUP, pLink) : NULL;
if (pCall) {
pCall->fAutoClean = TRUE;
pCall->l2cap_id = id;
pLink->b = *pba;
pLink->cid = cid;
pLink->fStage = CONNECTED;
pLink->mtu = 0;
pLink->psm = psm;
pLink->fIncoming = TRUE;
pLink->pNext = gpState->pLinks;
gpState->pLinks = pLink;
result = 0;
} else {
if (pLink)
svsutil_FreeFixed (pLink, gpState->pfmdLinks);
result = 4;
}
} else {
if (result == 0)
result = 2;
}
if ((result == 0) && (pDev->fEncrypt || pDev->fAuthenticate) && (! pDev->fAuthSpinned)) {
pDev->fAuthSpinned = TRUE;
gpState->pSchedule->ScheduleEvent (AuthenticateDevice, pCall, 0);
gpState->Unlock ();
return ERROR_SUCCESS;
}
HANDLE hL2CAP = gpState->hL2CAP;
L2CA_ConnectResponse_In pCallbackConnect = gpState->l2cap_if.l2ca_ConnectResponse_In;
L2CA_ConfigReq_In pCallbackConfig = gpState->l2cap_if.l2ca_ConfigReq_In;
gpState->Unlock ();
__try {
pCallbackConnect (hL2CAP, NULL, pba, id, cid, result, status);
} __except (1) {
}
if (result == 0) {
int iRes = ERROR_INTERNAL_ERROR;
__try {
iRes = pCallbackConfig (hL2CAP, pCall, cid, BTH_MTU_MAX, 0xffff, NULL, 0, NULL);
} __except (1) {
}
if (iRes != ERROR_SUCCESS)
hiddev_lCallAborted (pCall, iRes);
}
return ERROR_SUCCESS;
}
static int hiddev_ConnectReq_Out (void *pCallContext, unsigned short cid, unsigned short result, unsigned short status) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Connect out for call 0x%08x ch 0x%04x result = 0x%04x status 0x%04x\n", pCallContext, cid, result, status));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCall *pCall = VerifyCall ((SCall *)pCallContext);
if ((! pCall) || pCall->fComplete) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_LINK_SETUP);
SVSUTIL_ASSERT (! pCall->fComplete);
SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
SVSUTIL_ASSERT (! pCall->pBuffer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -