📄 bthid.cxx
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/**
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
Abstract:
Windows CE Bluetooth stack layer sample
**/
#include <windows.h>
#include <svsutil.hxx>
#include <bt_debug.h>
#include <bt_os.h>
#include <bt_buffer.h>
#include <bt_ddi.h>
#include <bt_api.h>
#if defined (UNDER_CE)
#include <pkfuncs.h>
#endif
#include <bt_tdbg.h>
#include "bthidpar.h"
#include "hidpkt.h"
#include "hidsdp.h"
#include "hidioctl.h"
#include "hidconf.h"
#define DEBUG_LAYER_TRACE 0x00000040
DECLARE_DEBUG_VARS();
#define BTH_PSM_CONTROL 0x11
#define BTH_PSM_INTERRUPT 0x13
#define BTH_MTU_MIN 0x30
#define BTH_MTU_MAX 0x02A6
#define BTH_MAX_FRAGMENTS 256
#define BTH_PARSER_TIMEOUT 3600000
#define BTH_CONNECTION_TIMEOUT 120000
#define BTH_WIRE_TIMEOUT 5000
#define CALL_L2CAP_LINK_SETUP 0x11
#define NONE 0x00
#define CONNECTED 0x01
#define CONFIG_REQ_DONE 0x02
#define CONFIG_IND_DONE 0x04
#define UP 0x07
#define LINK_ERROR 0x80
struct Link {
Link *pNext;
BD_ADDR b;
unsigned short psm;
unsigned short cid;
unsigned int fStage;
unsigned int fIncoming : 1;
unsigned short mtu;
};
struct SCall {
SCall *pNext;
Link *pLink;
HANDLE hEvent;
int iResult;
unsigned short psm;
unsigned int fWhat : 8;
unsigned int fComplete : 1;
unsigned int fAutoClean : 1;
unsigned char l2cap_id;
BD_BUFFER *pBuffer;
};
struct HidDevice : public IBTHHIDReportHandler {
HidDevice *pNext;
BD_ADDR b;
union {
struct {
// BTH
unsigned int fEncrypt : 1;
unsigned int fAuthenticate : 1;
unsigned int fHaveControl : 1;
unsigned int fHaveInterrupt : 1;
// HID
unsigned int fReconnectInitiate : 1;
unsigned int fNormallyConnectable : 1;
unsigned int fVirtualCable : 1;
// Service
unsigned int fIncoming : 1;
unsigned int fAuthSpinned : 1;
unsigned int fTrans : 1;
};
unsigned int flags;
};
HANDLE hevtTransFree;
HANDLE hevtTrans;
int cTransWait;
BTHHIDPacket *pktTransResp;
BTHHIDPacket *pktControl;
BTHHIDPacket *pktInterrupt;
IBTHHIDParser *pHidParser;
SVSCookie ckDeviceTimeout;
SVSCookie ckConnectionTimeout;
HidDevice (BD_ADDR *pba) {
pNext = 0;
b = *pba;
flags = 0;
hevtTrans = CreateEvent (NULL, FALSE, FALSE, NULL);
hevtTransFree = CreateEvent (NULL, TRUE, FALSE, NULL);
cTransWait = 0;
pktTransResp = pktControl = pktInterrupt = NULL;
pHidParser = HIDParserAlloc (this);
ckDeviceTimeout = 0;
ckConnectionTimeout = 0;
}
~HidDevice (void) {
SetEvent (hevtTransFree);
CloseHandle (hevtTransFree);
SetEvent (hevtTrans);
CloseHandle (hevtTrans);
if (pktTransResp) {
pktTransResp->ReleasePayload ();
delete pktTransResp;
}
if (pktControl) {
pktControl->ReleasePayload ();
delete pktControl;
}
if (pktInterrupt) {
pktInterrupt->ReleasePayload ();
delete pktInterrupt;
}
if (pHidParser)
pHidParser->Release ();
}
void *operator new (size_t iSize);
void operator delete(void *ptr);
int FillPersistentParameters (int fIncoming);
// IBTHHIDReportHandler overrides
int SetIdle(unsigned char bIdle);
int SetProtocol(E_BTHID_PROTOCOLS protocol);
int GetReport(int iReportID, E_BTHID_REPORT_TYPES type, PCHAR pBuffer, int cbBuffer, PDWORD pcbTransfered, int iTimeout);
int SetReport(E_BTHID_REPORT_TYPES type, PCHAR pBuffer, int cbBuffer, int iTimeout);
};
int hiddev_CloseDriverInstance (void);
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);
static int hiddev_ConnectInd (void *pUserContext, BD_ADDR *pba, unsigned short cid, unsigned char id, unsigned short psm);
static int hiddev_DataUpInd (void *pUserContext, unsigned short cid, BD_BUFFER *pBuffer);
static int hiddev_DisconnectInd (void *pUserContext, unsigned short cid, int iError);
static int hiddev_lStackEvent (void *pUserContext, int iEvent, void *pEventContext);
static int hiddev_lCallAborted (void *pCallContext, int iError);
static int hiddev_ConfigReq_Out (void *pCallContext, unsigned short usResult, unsigned short usInMTU, unsigned short usOutFlushTO, struct btFLOWSPEC *pOutFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions);
static int hiddev_ConfigResponse_Out (void *pCallContext, unsigned short result);
static int hiddev_ConnectReq_Out (void *pCallContext, unsigned short cid, unsigned short result, unsigned short status);
static int hiddev_ConnectResponse_Out (void *pCallContext, unsigned short result);
static int hiddev_DataDown_Out (void *pCallContext, unsigned short result);
static int hiddev_Ping_Out (void *pCallContext, BD_ADDR *pba, unsigned char *pOutBuffer, unsigned short size);
static int hiddev_Disconnect_Out (void *pCallContext, unsigned short result);
#if defined (BTHHID_QUEUE)
static DWORD WINAPI HidReportHandler (LPVOID lpNull);
#endif
static int HIDCloseCID_Int (unsigned short usCID);
class HIDDEV : public SVSSynch, public SVSRefObj {
public:
Link *pLinks;
SCall *pCalls;
HidDevice *pHIDs;
unsigned int fIsRunning : 1;
unsigned int fConnected : 1;
HANDLE hL2CAP;
L2CAP_INTERFACE l2cap_if;
int cHeaders;
int cTrailers;
FixedMemDescr *pfmdLinks;
FixedMemDescr *pfmdCalls;
FixedMemDescr *pfmdHIDs;
#if defined (BTHHID_QUEUE)
HANDLE hthReports;
SVSQueue qHidReports;
HANDLE hevtReports;
#endif
SVSThreadPool *pSchedule;
HIDDEV (void) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: new HIDDEV\n"));
pLinks = NULL;
pCalls = NULL;
pHIDs = NULL;
cHeaders = 0;
cTrailers = 0;
fIsRunning = FALSE;
fConnected = FALSE;
hL2CAP = NULL;
memset (&l2cap_if, 0, sizeof(l2cap_if));
pfmdLinks = pfmdCalls = pfmdHIDs = NULL;
pSchedule = NULL;
#if defined (BTHHID_QUEUE)
hthReports = NULL;
if (! (hevtReports = CreateEvent (NULL, FALSE, FALSE, NULL)))
return;
#endif
if (! (pSchedule = new SVSThreadPool))
return;
if (! (pfmdLinks = svsutil_AllocFixedMemDescr (sizeof(Link), 10)))
return;
if (! (pfmdHIDs = svsutil_AllocFixedMemDescr (sizeof(HidDevice), 10)))
return;
if (! (pfmdCalls = svsutil_AllocFixedMemDescr (sizeof(SCall), 10)))
return;
L2CAP_EVENT_INDICATION lei;
memset (&lei, 0, sizeof(lei));
lei.l2ca_ConfigInd = hiddev_ConfigInd;
lei.l2ca_ConnectInd = hiddev_ConnectInd;
lei.l2ca_DataUpInd = hiddev_DataUpInd;
lei.l2ca_DisconnectInd = hiddev_DisconnectInd;
lei.l2ca_StackEvent = hiddev_lStackEvent;
L2CAP_CALLBACKS lc;
memset (&lc, 0, sizeof(lc));
lc.l2ca_CallAborted = hiddev_lCallAborted;
lc.l2ca_ConfigReq_Out = hiddev_ConfigReq_Out;
lc.l2ca_ConfigResponse_Out = hiddev_ConfigResponse_Out;
lc.l2ca_ConnectReq_Out = hiddev_ConnectReq_Out;
lc.l2ca_ConnectResponse_Out = hiddev_ConnectResponse_Out;
lc.l2ca_DataDown_Out = hiddev_DataDown_Out;
lc.l2ca_Ping_Out = hiddev_Ping_Out;
lc.l2ca_Disconnect_Out = hiddev_Disconnect_Out;
if (ERROR_SUCCESS != L2CAP_EstablishDeviceContext (this, L2CAP_PSM_MULTIPLE, &lei, &lc, &l2cap_if, &cHeaders, &cTrailers, &hL2CAP))
return;
int iRes = ERROR_SUCCESS;
__try {
int iRet = 0;
unsigned short usPSMin = BTH_PSM_CONTROL;
iRes = l2cap_if.l2ca_ioctl (hL2CAP, BTH_STACK_IOCTL_RESERVE_PORT, sizeof(usPSMin), (char *)&usPSMin, 0, NULL, &iRet);
if (iRes == ERROR_SUCCESS) {
usPSMin = BTH_PSM_INTERRUPT;
iRes = l2cap_if.l2ca_ioctl (hL2CAP, BTH_STACK_IOCTL_RESERVE_PORT, sizeof(usPSMin), (char *)&usPSMin, 0, NULL, &iRet);
}
} __except (1) {
iRes = ERROR_EXCEPTION_IN_SERVICE;
}
if (iRes == ERROR_SUCCESS)
fIsRunning = TRUE;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: new HIDDEV successful\n"));
}
~HIDDEV (void) {
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: delete HIDDEV\n"));
fIsRunning = FALSE;
fConnected = FALSE;
#if defined (BTHHID_QUEUE)
if (hevtReports) {
HANDLE h = hevtReports;
hevtReports = NULL;
SetEvent (h);
CloseHandle (h);
}
if (hthReports) {
if (WAIT_OBJECT_0 != WaitForSingleObject (hthReports, 15000))
TerminateThread (hthReports, 0);
CloseHandle (hthReports);
}
#endif
if (pSchedule)
delete pSchedule;
if (hL2CAP)
L2CAP_CloseDeviceContext (hL2CAP);
if (pfmdHIDs)
svsutil_ReleaseFixedNonEmpty (pfmdHIDs);
if (pfmdLinks)
svsutil_ReleaseFixedNonEmpty (pfmdLinks);
if (pfmdCalls)
svsutil_ReleaseFixedNonEmpty (pfmdCalls);
}
};
static HIDDEV *gpState = NULL;
static BYTE gbUnplugHeader = 0;
//
// Auxiliary code
//
void *HidDevice::operator new (size_t iSize) {
SVSUTIL_ASSERT (iSize == sizeof(HidDevice));
void *pRes = svsutil_GetFixed (gpState->pfmdHIDs);
return pRes;
}
void HidDevice::operator delete(void *ptr) {
svsutil_FreeFixed (ptr, gpState->pfmdHIDs);
}
static HIDDEV *CreateNewState (void) {
return new HIDDEV;
}
static SCall *AllocCall (int fWhat, Link *pLink) {
SCall *pCall = (SCall *)svsutil_GetFixed (gpState->pfmdCalls);
memset (pCall, 0, sizeof(*pCall));
if (! gpState->pCalls)
gpState->pCalls = pCall;
else {
SCall *pLast = gpState->pCalls;
while (pLast->pNext)
pLast = pLast->pNext;
pLast->pNext = pCall;
}
pCall->pLink = pLink;
pCall->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
pCall->fWhat = fWhat;
IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Allocated call 0x%08x what = 0x%02x\n", pCall, fWhat));
return pCall;
}
static void DeleteCall (SCall *pCall) {
if (pCall == gpState->pCalls)
gpState->pCalls = pCall->pNext;
else {
SCall *pParent = gpState->pCalls;
while (pParent && (pParent->pNext != pCall))
pParent = pParent->pNext;
if (! pParent) {
IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: call not in list in DeleteCall!\n"));
return;
}
pParent->pNext = pCall->pNext;
}
CloseHandle (pCall->hEvent);
svsutil_FreeFixed (pCall, gpState->pfmdCalls);
}
static SCall *VerifyCall (SCall *pCall) {
SCall *p = gpState->pCalls;
while (p && (p != pCall))
p = p->pNext;
return p;
}
static SCall *FindCall (unsigned int fOp) {
SCall *p = gpState->pCalls;
while (p && (p->fWhat != fOp))
p = p->pNext;
return p;
}
static SCall *FindCall (Link *pLink, unsigned int fOp) {
SCall *p = gpState->pCalls;
while (p && ((p->pLink != pLink) || (p->fWhat != fOp)))
p = p->pNext;
return p;
}
static HidDevice *VerifyDevice (HidDevice *pDev) {
HidDevice *pD = gpState->pHIDs;
while (pD && (pD != pDev))
pD = pD->pNext;
return pD;
}
static HidDevice *FindDevice (BD_ADDR *pba) {
HidDevice *pD = gpState->pHIDs;
while (pD && (pD->b != *pba))
pD = pD->pNext;
return pD;
}
static Link *VerifyLink (Link *pLink) {
Link *p = gpState->pLinks;
while (p && (p != pLink))
p = p->pNext;
return p;
}
static Link *FindLink (BD_ADDR *pba) {
Link *pL = gpState->pLinks;
while (pL && (pL->b != *pba))
pL = pL->pNext;
return pL;
}
static Link *FindLink (BD_ADDR *pba, unsigned short psm) {
Link *pL = gpState->pLinks;
while (pL && ((pL->b != *pba) || (pL->psm != psm)))
pL = pL->pNext;
return pL;
}
static Link *FindLink (unsigned short cid) {
Link *p = gpState->pLinks;
while (p && (p->cid != cid))
p = p->pNext;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -