📄 bthid.cxx
字号:
SetEvent (hevtComplete);
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
if (! VerifyDevice (pDev)) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
BTHHIDPacket *pPacket = pDev->pktTransResp;
pDev->pktTransResp = NULL;
pDev->fTrans = FALSE; // Clear the transaction
if (! pPacket) {
gpState->Unlock ();
return iRes == ERROR_SUCCESS ? ERROR_TIMEOUT : iRes;
}
if (ppRes)
*ppRes = pPacket;
else {
pPacket->ReleasePayload ();
delete pPacket;
}
gpState->Unlock ();
break;
}
return iRes;
}
int HidDevice::FillPersistentParameters (int fIncoming) {
DWORD dwDeviceFlags = 0;
unsigned char *psdp = NULL;
unsigned int csdp = 0;
if (! GetDeviceConfig (&b, &dwDeviceFlags, &psdp, &csdp)) {
IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: FillPersistentParameters %04x%08x - bonding does not exist\n", b.NAP, b.SAP));
return FALSE;
}
if (fIncoming && ((dwDeviceFlags & HIDCONF_FLAGS_ACTIVE) == 0)) {
IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: FillPersistentParameters %04x%08x - device is not activated\n", b.NAP, b.SAP));
g_funcFree (psdp, g_pvFreeData);
return FALSE;
}
if (dwDeviceFlags & HIDCONF_FLAGS_AUTH)
fAuthenticate = TRUE;
if (dwDeviceFlags & HIDCONF_FLAGS_ENCRYPT)
fEncrypt = TRUE;
BTHHIDSdpParser sdpParser;
int iErr = sdpParser.Start (psdp, csdp);
BOOL bb = FALSE;
if (iErr == ERROR_SUCCESS)
iErr = sdpParser.GetHIDReconnectInitiate(&bb);
if (iErr == ERROR_SUCCESS) {
fReconnectInitiate = bb;
iErr = sdpParser.GetHIDNormallyConnectable(&bb);
if (iErr == ERROR_SUCCESS)
fNormallyConnectable = bb;
iErr = ERROR_SUCCESS;
}
if (iErr == ERROR_SUCCESS) {
iErr = sdpParser.GetHIDVirtualCable(&bb);
}
// Pass in an empty structure to retrieve the size of the blob
BLOB blobReportDescriptor = {0, NULL};
if (iErr == ERROR_SUCCESS) {
fVirtualCable = bb;
iErr = sdpParser.GetHIDReportDescriptor(&blobReportDescriptor);
}
if (iErr == ERROR_SUCCESS) {
// Now we have the size. Allocate and requery.
SVSUTIL_ASSERT(blobReportDescriptor.cbSize > 0);
blobReportDescriptor.pBlobData = (unsigned char *)g_funcAlloc (blobReportDescriptor.cbSize, g_pvAllocData);
iErr = sdpParser.GetHIDReportDescriptor(&blobReportDescriptor);
if (iErr == ERROR_SUCCESS) {
iErr = pHidParser->SetReportDescriptor(blobReportDescriptor.pBlobData, blobReportDescriptor.cbSize);
g_funcFree (blobReportDescriptor.pBlobData, g_pvFreeData);
}
}
sdpParser.End ();
if (iErr != ERROR_SUCCESS) {
IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: FillPersistentParameters %04x%08x - parsing SDP record failed\n", b.NAP, b.SAP));
}
g_funcFree (psdp, g_pvFreeData);
return iErr == ERROR_SUCCESS;
}
static int ProcessHidPacket (BTHHIDPacket *pPacket, HidDevice *pDev) {
if (pPacket->GetReportType () == BTHID_REPORT_INPUT) {
BYTE* pPayload;
int cbPayload;
pPacket->GetPayload(&pPayload, &cbPayload);
pDev->pHidParser->ProcessInterruptReport(pPayload, cbPayload);
} else {
if (pPacket->GetHeader() == gbUnplugHeader) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID ReportHandler : virtual disconnect\n"));
// We'll be unloaded really soon. Clean up.
// ???DisconnectDevice (pDev);
} else {
if (! pDev->fTrans) {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH Device: protocol error - control packet w/o transaction. Aborting...\n"));
DisconnectDevice (pDev);
} else {
if (pDev->pktTransResp) { // Transaction violated
IFDBG(DebugOut (DEBUG_ERROR, L"BTH Device: protocol error - multiple control packets for transaction. Aborting...\n"));
DisconnectDevice (pDev);
} else {
pDev->pktTransResp = pPacket;
SetEvent (pDev->hevtTrans);
return FALSE; // Don't destroy the packet
}
}
}
}
return TRUE;
}
//
// L2CAP stuff
//
static int hiddev_DataUpInd (void *pUserContext, unsigned short cid, BD_BUFFER *pBuffer) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Data up on channel 0x%04x %d bytes\n", cid, BufferTotal (pBuffer)));
if (! gpState)
return ERROR_SERVICE_NOT_ACTIVE;
gpState->Lock ();
if (! gpState->fIsRunning) {
gpState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Link *pLink = FindLink (cid);
HidDevice *pDev = pLink ? FindDevice (&pLink->b) : NULL;
BTHHIDPacket *pPacket = pDev ? (pLink->psm == BTH_PSM_CONTROL ? pDev->pktControl : pDev->pktInterrupt) : NULL;
if (pDev && (! pPacket)) {
pPacket = new BTHHIDPacket;
if (pPacket) {
pPacket->SetMTU (pLink->mtu);
pPacket->SetOwner (pDev);
if (pLink->psm == BTH_PSM_CONTROL) {
pPacket->SetReportType(BTHID_REPORT_FEATURE);
pDev->pktControl = pPacket;
} else {
pPacket->SetReportType(BTHID_REPORT_INPUT);
pDev->pktInterrupt = pPacket;
}
}
}
#if defined (DEBUG) || defined (_DEBUG)
if (pPacket) {
SVSUTIL_ASSERT (pPacket->GetOwner() == pDev);
} else {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: Data up - no packet\n"));
}
#endif
if (pPacket) {
if (! pPacket->AddPayloadChunk(pBuffer->pBuffer + pBuffer->cStart, BufferTotal (pBuffer))) { // finished
if (pLink->psm == BTH_PSM_CONTROL)
pDev->pktControl = NULL;
else
pDev->pktInterrupt = NULL;
#if defined (BTHHID_QUEUE)
if (! gpState->qHidReports.Put (pPacket)) {
pPacket->ReleasePayload();
delete pPacket;
}
SetEvent (gpState->hevtReports);
#else
int fRelease = ProcessHidPacket (pPacket, pDev);
if (fRelease) {
pPacket->ReleasePayload();
delete pPacket;
}
#endif
}
}
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;
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, 0, 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 usInMTU, 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, usInMTU, 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 (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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -