📄 bthid.cxx
字号:
} 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) {
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);
if (result) {
if (result != 1) {
pCall->fComplete = TRUE;
pCall->iResult = ERROR_CONNECTION_REFUSED;
SetEvent (pCall->hEvent);
}
gpState->Unlock ();
return ERROR_SUCCESS;
}
HidDevice *pDev = FindDevice (&pCall->pLink->b);
if (! pDev) {
pCall->fComplete = TRUE;
pCall->iResult = ERROR_CONNECTION_REFUSED;
SetEvent (pCall->hEvent);
gpState->Unlock ();
HIDCloseCID_Int (cid);
return ERROR_SUCCESS;
}
Link *pLink = pCall->pLink;
SVSUTIL_ASSERT (pLink->fStage == NONE);
SVSUTIL_ASSERT (! pLink->cid);
SVSUTIL_ASSERT (pLink->psm);
pLink->fStage = CONNECTED;
pLink->cid = cid;
if ((pDev->fEncrypt || pDev->fAuthenticate) && (! pDev->fAuthSpinned)) {
pDev->fAuthSpinned = TRUE;
gpState->pSchedule->ScheduleEvent (AuthenticateDevice, pCallContext, 0);
gpState->Unlock ();
return ERROR_SUCCESS;
}
HANDLE hL2CAP = gpState->hL2CAP;
L2CA_ConfigReq_In pCallback = gpState->l2cap_if.l2ca_ConfigReq_In;
gpState->Unlock ();
int iRes = ERROR_INTERNAL_ERROR;
__try {
iRes = pCallback (hL2CAP, pCallContext, cid, BTH_MTU_MAX, 0xffff, NULL, 0, NULL);
} __except (1) {
}
if (iRes != ERROR_SUCCESS)
hiddev_lCallAborted (pCallContext, iRes);
return ERROR_SUCCESS;
}
static int hiddev_DataDown_Out (void *pCallContext, unsigned short result) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Data down call 0x%08x result %d\n", pCallContext, result));
return ERROR_SUCCESS;
}
static int hiddev_Ping_Out (void *pCallContext, BD_ADDR *pba, unsigned char *pOutBuffer, unsigned short size) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: hiddev_Ping_Out call 0x%08x result %d\n", pCallContext));
return ERROR_SUCCESS;
}
// These are just stubs - they do nothing
static int hiddev_ConfigResponse_Out (void *pCallContext, unsigned short result) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: ConfigResponse out call 0x%08x, result %d\n", pCallContext, result));
return ERROR_SUCCESS;
}
static int hiddev_ConnectResponse_Out (void *pCallContext, unsigned short result) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: ConnectResponse out call 0x%08x, result %d\n", pCallContext, result));
return ERROR_SUCCESS;
}
static int hiddev_Disconnect_Out (void *pCallContext, unsigned short result) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: disconnect out call 0x%08x, result %d\n", pCallContext, result));
return ERROR_SUCCESS;
}
//
// Init stuff
//
static int hiddev_CreateDriverInstance (void) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"+hiddev_CreateDriverInstance\n"));
if (gpState) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CreateDriverInstance : ERROR_ALREADY_INITIALIZED\n"));
return ERROR_ALREADY_INITIALIZED;
}
if (! BthPktInitAllocator ())
return ERROR_OUTOFMEMORY;
BTHID_Header_Parameter packetVirtualUnplug;
packetVirtualUnplug.bRawHeader = 0;
packetVirtualUnplug.control_p.bControlOp = BTHID_CONTROL_VIRTUAL_CABLE_UNPLUG;
gbUnplugHeader = (BTHID_HID_CONTROL << 4) | packetVirtualUnplug.bRawHeader;
gpState = CreateNewState ();
if ((! gpState) || (! gpState->fIsRunning)) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CreateDriverInstance : ERROR_OUTOFMEMORY\n"));
if (gpState)
delete gpState;
gpState = NULL;
return ERROR_OUTOFMEMORY;
}
#if defined (BTHHID_QUEUE)
gpState->hthReports = CreateThread (NULL, 0, HidReportHandler, NULL, 0, NULL);
if (gpState->hthReports)
SetThreadPriority (gpState->hthReports, THREAD_PRIORITY_HIGHEST);
#endif
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CreateDriverInstance : ERROR_SUCCESS\n"));
return ERROR_SUCCESS;
}
static int hiddev_CloseDriverInstance (void) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"+hiddev_CloseDriverInstance\n"));
if (! gpState) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CloseDriverInstance : ERROR_SERVICE_NOT_ACTIVE\n"));
return ERROR_SERVICE_NOT_ACTIVE;
}
gpState->Lock ();
if (! gpState->fIsRunning) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CloseDriverInstance : ERROR_SERVICE_NOT_ACTIVE\n"));
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
gpState->fIsRunning = FALSE;
while (gpState->GetRefCount () > 1) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Waiting for ref count in hiddev_CloseDriverInstance\n"));
gpState->Unlock ();
Sleep (200);
gpState->Lock ();
}
while (gpState->pCalls) {
SetEvent (gpState->pCalls->hEvent);
gpState->pCalls->iResult = ERROR_CANCELLED;
gpState->pCalls = gpState->pCalls->pNext;
}
while (gpState->pLinks) {
unsigned short cid = gpState->pLinks->cid;
gpState->Unlock ();
gpState->l2cap_if.l2ca_Disconnect_In (gpState->hL2CAP, NULL, cid);
gpState->Lock ();
gpState->pLinks = gpState->pLinks->pNext;
}
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CloseDriverInstance : ERROR_SUCCESS\n"));
gpState->Unlock ();
delete gpState;
gpState = NULL;
BthPktFreeAllocator ();
return ERROR_SUCCESS;
}
#if defined (BTHHID_QUEUE)
//
// HID reports processing
//
static DWORD WINAPI HidReportHandler (LPVOID lpNull) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID ReportHandler : started\n"));
for ( ; ; ) {
if (! gpState)
return 0;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
break;
}
HANDLE hEvent = gpState->hevtReports;
gpState->Unlock ();
WaitForSingleObject (hEvent, INFINITE);
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
break;
}
while (! gpState->qHidReports.IsEmpty()) {
BTHHIDPacket *pPacket = (BTHHIDPacket *)gpState->qHidReports.Get ();
HidDevice *pDev = VerifyDevice ((HidDevice *)pPacket->GetOwner());
int fRelease = TRUE;
if (pDev)
fRelease = ProcessHidPacket (pPacket, pDev);
else {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH Device: Device not found for a packet...\n"));
}
if (fRelease) {
pPacket->ReleasePayload();
delete pPacket;
}
}
gpState->Unlock ();
}
return 0;
}
#endif
//
// Internal API section
//
static int HIDConnect_Int
(
BD_ADDR *pba,
unsigned short usPSM,
unsigned short *pusCid
) {
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Link *pLink = (Link *)svsutil_GetFixed (gpState->pfmdLinks);
memset (pLink, 0, sizeof (*pLink));
pLink->cid = 0;
pLink->b = *pba;
pLink->fStage = NONE;
pLink->fIncoming = FALSE;
pLink->psm = usPSM;
pLink->pNext = gpState->pLinks;
gpState->pLinks = pLink;
SCall *pCall = AllocCall (CALL_L2CAP_LINK_SETUP, pLink);
HANDLE hEvent = pCall->hEvent;
HANDLE hL2CAP = gpState->hL2CAP;
L2CA_ConnectReq_In pCallbackConnect = gpState->l2cap_if.l2ca_ConnectReq_In;
L2CA_ConfigReq_In pCallbackConfig = gpState->l2cap_if.l2ca_ConfigReq_In;
int iRes = ERROR_INTERNAL_ERROR;
gpState->Unlock ();
__try {
iRes = pCallbackConnect (hL2CAP, pCall, usPSM, pba);
} __except (1) {
}
if (iRes == ERROR_SUCCESS)
WaitForSingleObject (hEvent, INFINITE);
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (gpState->fIsRunning) {
pCall = VerifyCall (pCall);
pLink = VerifyLink (pLink);
} else {
pCall = NULL;
pLink = NULL;
iRes = ERROR_SERVICE_NOT_ACTIVE;
}
if (iRes == ERROR_SUCCESS) {
if (pCall && pCall->fComplete)
iRes = pCall->iResult;
else
iRes = ERROR_TIMEOUT;
}
if (pCall)
DeleteCall (pCall);
else
iRes = ERROR_INTERNAL_ERROR;
if ((! pLink) || (pLink->fStage & LINK_ERROR) || (iRes != ERROR_SUCCESS) || (pLink->fStage != UP)) {
unsigned short cid_disconnect = 0;
if (pLink) {
if ((iRes == ERROR_SUCCESS) && (pLink->fStage != UP))
iRes = ERROR_INTERNAL_ERROR;
cid_disconnect = pLink->cid;
} else
iRes = ERROR_INTERNAL_ERROR;
gpState->Unlock ();
if (cid_disconnect)
HIDCloseCID_Int (cid_disconnect);
return iRes;
}
*pusCid = pLink->cid;
gpState->Unlock ();
return ERROR_SUCCESS;
}
static int HIDCloseCID_Int (unsigned short usCID) {
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Link *pLink = FindLink (usCID);
if (! pLink) {
gpState->Unlock ();
return ERROR_NOT_FOUND;
}
unsigned short cid = pLink->cid;
DeleteLink (pLink);
HANDLE hL2CAP = gpState->hL2CAP;
L2CA_Disconnect_In pCallback = gpState->l2cap_if.l2ca_Disconnect_In;
gpState->Unlock ();
__try {
pCallback (hL2CAP, NULL, cid);
} __except (1) {
}
return ERROR_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -