📄 bthid.cxx
字号:
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
gpState->hthReconnect = CreateThread (NULL, 0, HidReconnectThread, NULL, 0, NULL);
if (! gpState->hthReconnect) {
IFDBG(DebugOut (DEBUG_ERROR, L"-hiddev_CreateDriverInstance : Failed to create reconnect thread.\n"));
}
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;
SetEvent(gpState->hReconnectEvent);
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"));
if (gpState->hthReconnect)
CloseHandle (gpState->hthReconnect);
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);
if (! pCall) {
gpState->Unlock ();
return ERROR_OUTOFMEMORY;
}
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;
}
//
// Hid parser interface
//
//
// Parser interface
//
int HidDevice::SetIdle(unsigned char bIdle) {
// Initialize the packets
BTHHIDPacket requestPacket;
requestPacket.SetHeader(BTHID_SET_IDLE << 4);
requestPacket.SetPayload(&bIdle, sizeof(bIdle));
return WritePacket (this, &requestPacket, BTH_WIRE_TIMEOUT, NULL, BTH_PSM_CONTROL);
}
int HidDevice::GetIdle(unsigned char* pbIdle) {
BTHHIDPacket requestPacket;
requestPacket.SetHeader(BTHID_GET_IDLE << 4);
BTHHIDPacket *pPacket = NULL;
int iErr = WritePacket (this, &requestPacket, BTH_WIRE_TIMEOUT, &pPacket, BTH_PSM_CONTROL);
if (iErr == ERROR_SUCCESS) {
// Check if the request succeeded
BYTE bHeader = pPacket->GetHeader();
if ((bHeader >> 4) == BTHID_DATA) {
// Request succeeded, get the payload to the caller
BYTE *pPacketPayload;
int cbPacketPayload;
pPacket->GetPayload(&pPacketPayload, &cbPacketPayload);
if (cbPacketPayload == 1) {
*pbIdle = *pPacketPayload;
} else
iErr = ERROR_INVALID_DATA;
} else
iErr = ERROR_INVALID_DATA;
pPacket->ReleasePayload ();
delete pPacket;
}
return iErr;
}
int HidDevice::SetProtocol(E_BTHID_PROTOCOLS protocol) {
// Initialize the packets
BTHHIDPacket requestPacket;
BTHID_Header_Parameter param;
// Initialize the packets
param.bRawHeader = 0;
param.setprotocol_p.bProtocol = protocol;
requestPacket.SetHeader((BTHID_SET_PROTOCOL << 4) | param.bRawHeader);
return WritePacket (this, &requestPacket, BTH_WIRE_TIMEOUT, NULL, BTH_PSM_CONTROL);
}
int HidDevice::SetReport(E_BTHID_REPORT_TYPES type, PCHAR pBuffer, int cbBuffer, int iTimeout) {
// Initialize the packets
BTHHIDPacket requestPacket;
BTHID_Header_Parameter SetReport_param;
// Initialize the packets
SetReport_param.bRawHeader = 0;
SetReport_param.setreport_p.bReportType = type;
// Start by sending BTHIDSetReport_Request down the pipe.
requestPacket.SetHeader((BTHID_SET_REPORT << 4) | SetReport_param.bR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -