⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bthid.cxx

📁 CE下串口复用程序
💻 CXX
📖 第 1 页 / 共 5 页
字号:
//
// 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 + -