📄 bthid.cxx
字号:
SetEvent(gpState->hReconnectEvent);
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 WritePacket (void *lpHidDevice, BTHHIDPacket *pSource, int iTimeout, BTHHIDPacket **ppRes, int iChannel) {
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, iChannel);
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);
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);
}
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);
}
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;
if (pDev->pvNotifyParameter) {
pPacket->GetPayload(&pPayload, &cbPayload);
if (ERROR_SUCCESS != HidMdd_ProcessInterruptReport(pPayload, cbPayload, pDev->pvNotifyParameter)) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID ProcessHidPacket : Error processing interrupt report - disconnecting device.\n"));
DisconnectDevice (pDev, TRUE);
}
}
} else {
if (pPacket->GetHeader() == gbUnplugHeader) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID ReportHandler : virtual disconnect\n"));
DisconnectDevice (pDev, FALSE);
} else {
if (! pDev->fTrans) {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH Device: protocol error - control packet w/o transaction. Aborting...\n"));
DisconnectDevice (pDev, TRUE);
} else {
if (pDev->pktTransResp) { // Transaction violated
IFDBG(DebugOut (DEBUG_ERROR, L"BTH Device: protocol error - multiple control packets for transaction. Aborting...\n"));
DisconnectDevice (pDev, TRUE);
} 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);
// Store this packet away. In some cases, we will need to buffer up
// several fragments before passing data up to HID layer.
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 this function returns 0 we can indicate the packet up to HID layer. Otherwise, we have
// to recv more data before indicating up.
if (! pPacket->AddPayloadChunk(pBuffer->pBuffer + pBuffer->cStart, BufferTotal (pBuffer))) {
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
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -