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

📄 btecho.cxx

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CXX
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/**
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 application sample

**/
#define _STRSAFE_H_INCLUDED_	1

#include <windows.h>
#include <stdio.h>
#if ! defined (UNDER_CE)
#include <stddef.h>
#endif

#include <bt_api.h>
#include "../l2capapi/l2capapi.hxx"

#include <svsutil.hxx>

#define MAX_THREADS		100
#define MAX_RUNS		100000
#define MAX_REQS		1000000
#define RANDOM(x)		(((x * 214013 + 2531011) >> 16 ) & 0x7fff)
#define BIG_RANDOM(x)	(x | (RANDOM(x) << 15))

class Packet {
public:
	int iRequest;
	int iRandom;
	unsigned int cPos;
	unsigned int cSize;
	unsigned char uc[1];
};

class ThreadData {
public:
	unsigned short cid;
	unsigned short outMTU;
};

class Paragraph {
public:
	unsigned int	cText;
	unsigned char	*pText;
};

SVSExpArray<class Paragraph>	*g_pFile;
unsigned int					g_cParagraphs = 0;

unsigned short	g_usMaxPacket = 0;
int				g_iRequests = 0;
unsigned short  g_usPSM = 0;
BT_ADDR			g_ba;

#if defined (USE_RPC)
extern "C" handle_t bluetooth_IfHandle;

extern "C" void __RPC_FAR * __RPC_API midl_user_allocate (size_t len) {
	return malloc(len);
}

extern "C" void __RPC_API midl_user_free (void * __RPC_FAR ptr) {
	free (ptr);
}
#endif

#if ! defined (UNDER_CE)
BOOL WINAPI cmd_InterruptHandler (DWORD dwCtrl) {
	if (dwCtrl == CTRL_C_EVENT) {
		L2CAPClosePSM (g_usPSM);
		return TRUE;
	}

	return FALSE;
}
#endif

int GetBA (WCHAR **pp, BT_ADDR *pba) {
	while (**pp == ' ')
		++*pp;

	for (int i = 0 ; i < 4 ; ++i, ++*pp) {
		if (! iswxdigit (**pp))
			return FALSE;

		int c = **pp;
		if (c >= 'a')
			c = c - 'a' + 0xa;
		else if (c >= 'A')
			c = c - 'A' + 0xa;
		else c = c - '0';

		if ((c < 0) || (c > 16))
			return FALSE;

		*pba = *pba * 16 + c;
	}

	for (i = 0 ; i < 8 ; ++i, ++*pp) {
		if (! iswxdigit (**pp))
			return FALSE;

		int c = **pp;
		if (c >= 'a')
			c = c - 'a' + 0xa;
		else if (c >= 'A')
			c = c - 'A' + 0xa;
		else c = c - '0';

		if ((c < 0) || (c > 16))
			return FALSE;

		*pba = *pba * 16 + c;
	}

	if ((**pp != ' ') && (**pp != '\0'))
		return FALSE;

	return TRUE;
}

int GetUS (WCHAR **pp, unsigned short *pus) {
	while (**pp == ' ')
		++*pp;
	if (**pp != '0')
		return FALSE;
	++*pp;
	if (**pp != 'x')
		return FALSE;

	++*pp;

	int iDig = 0;
	*pus = 0;
	while (iswxdigit (**pp)) {
		int c = **pp;
		if (c >= 'a')
			c = c - 'a' + 0xa;
		else if (c >= 'A')
			c = c - 'A' + 0xa;
		else c = c - '0';

		if ((c < 0) || (c > 16))
			return FALSE;

		*pus = *pus * 16 + c;

		++*pp;

		++iDig;
	}

	if (iDig > 4)
		return FALSE;

	return TRUE;
}

int SendPacket (int iRequest, int iRandom, int cid, unsigned char *ub, unsigned int cb) {
	Packet *pr = (Packet *)ub;
	pr->iRequest = iRequest;
	pr->iRandom = iRandom;
	pr->cPos = BIG_RANDOM(iRandom) % g_cParagraphs;
	pr->cSize = (*g_pFile)[pr->cPos].cText;

	if (pr->cSize + offsetof(Packet, uc) > cb)
		pr->cSize = cb - offsetof(Packet, uc);

	memcpy (pr->uc, (*g_pFile)[pr->cPos].pText, pr->cSize);
	int iErr = L2CAPWrite (cid, pr->cSize + offsetof(Packet, uc), ub);
	if (iErr != ERROR_SUCCESS) {
		wprintf (L"0x%04x Error 0x%08x (%d)\n", cid, iErr);
		return FALSE;
	}

	return TRUE;
}

int ProcessRequest (int iRequest, int iRandom, int cid, unsigned char *ub, unsigned int cb) {
	if (cb < sizeof(Packet)) {
		wprintf (L"0x%04x Bad request %d: too small\n", cid, iRequest);
		return FALSE;
	}

	Packet *pr = (Packet *)ub;
	if (pr->iRequest != iRequest) {
		wprintf (L"0x%04x Bad request %d: ordinals do not match (got %d)\n", cid, iRequest, pr->iRequest);
		return FALSE;
	}

	if (pr->iRandom != iRandom) {
		wprintf (L"0x%04x Bad request %d: random numbers do not match (got %d, expected %d)\n",
			cid, iRequest, pr->iRandom, iRandom);
		return FALSE;
	}

	if (offsetof (Packet, uc) + pr->cSize != cb) {
		wprintf (L"0x%04x Bad request %d: inconsistent packet size (got %d, expected %d + %d)\n",
			cid, iRequest, cb, offsetof (Packet, uc), pr->cSize);
		return FALSE;
	}

	if (pr->cPos >= g_cParagraphs) {
		wprintf (L"0x%04x Bad request %d: position too big (pos %d, file size is %d)\n",
			cid, iRequest, pr->cPos, g_cParagraphs);
		return FALSE;
	}

	if ((pr->cSize > (*g_pFile)[pr->cPos].cText) ||
		(memcmp (pr->uc, (*g_pFile)[pr->cPos].pText, pr->cSize) != 0)) {
		wprintf (L"0x%04x Bad request %d: mismatched text\n");
		return FALSE;
	}

	if (iRequest % 10)
		wprintf (L"0x%04x Successfully received %d th packet\n", cid, iRequest);

	return TRUE;
}

DWORD WINAPI ClientReadThread (LPVOID lpVoid) {
	unsigned short  cid;
	unsigned short  usMTU;
	BT_ADDR			ba;

	ba = g_ba;

	int iErr = L2CAPConnect (&ba, g_usPSM, g_usMaxPacket, &cid, &usMTU);

	if (iErr != ERROR_SUCCESS) {
		wprintf (L"Connect to %04x%08x has failed\n", GET_NAP(ba), GET_SAP(ba));
		return 0;
	}

	wprintf (L"Client thread 0x%08x created for connection 0x%04x\n", GetCurrentThreadId(), cid);

	int iRandom = 0;

	
	unsigned char *ub = (unsigned char *)malloc (0xffff);
	for (int i = 0 ; i < g_iRequests ; ) {
		unsigned int cSize = 0;

		iRandom = ((iRandom * 214013 + 2531011) >> 16 ) & 0x7fff;

		if (! SendPacket (++i, iRandom, cid, ub, usMTU)) {
			wprintf (L"0x%04x Connection ended in error\n", cid);
			L2CAPCloseCID (cid);
			break;
		}

		int iErr = L2CAPRead (cid, 0xffff, &cSize, ub);
		if (iErr != ERROR_SUCCESS) {
			wprintf (L"0x%04x Error 0x%08x (%d)\n", cid, iErr, iErr);
			L2CAPCloseCID (cid);
			break;
		}

		if (cSize == 0) {
			wprintf (L"0x%04x Connection ended in error <closed>!\n", cid);
			L2CAPCloseCID (cid);
			break;
		}


		iRandom = ((iRandom * 214013 + 2531011) >> 16 ) & 0x7fff;

		if (! ProcessRequest (++i, iRandom, cid, ub, cSize)) {
			wprintf (L"0x%04x Connection ended in error\n");
			L2CAPCloseCID (cid);
			break;
		}
	}

	free (ub);

	if (i == g_iRequests)
		L2CAPCloseCID (cid);
	
	wprintf (L"0x%04x Client thread finished\n", cid);

	return 0;
}


DWORD WINAPI ServerReadThread (LPVOID lpVoid) {
	ThreadData *ptd = (ThreadData *)lpVoid;
	unsigned short cid = ptd->cid;
	unsigned short usMTU = ptd->outMTU;
	free (ptd);
	
	wprintf (L"Server thread 0x%08x created for connection 0x%04x\n", GetCurrentThreadId(), cid);

	int i = 0;
	int iRandom = 0;
	unsigned char *ub = (unsigned char *)malloc (0xffff);

	for ( ; ; ) {
		unsigned int cSize = 0;

		int iErr = L2CAPRead (cid, 0xffff, &cSize, ub);
		if (iErr != ERROR_SUCCESS) {
			wprintf (L"0x%04x Error 0x%08x (%d)\n", cid, iErr, iErr);
			L2CAPCloseCID (cid);
			break;
		}

		if (cSize == 0) {
			wprintf (L"0x%04x Connection ended\n", cid);
			L2CAPCloseCID (cid);
			break;
		}

		iRandom = ((iRandom * 214013 + 2531011) >> 16 ) & 0x7fff;

		if (! (ProcessRequest (++i, iRandom, cid, ub, cSize) &&
			SendPacket (++i,
				iRandom = ((iRandom * 214013 + 2531011) >> 16 ) & 0x7fff,
				cid, ub, usMTU))) {
			wprintf (L"0x%04x Connection ended in error\n");
			L2CAPCloseCID (cid);
			break;
		}
	}

	free (ub);
	wprintf (L"0x%04x Server thread finished\n", cid);

	return 0;
}

int wmain (int argc, WCHAR **argv) {
#if defined (USE_RPC)
	WCHAR	*pszUuid = NULL;
	WCHAR 	*pszProtocolSequence = L"ncalrpc";
	WCHAR   *pszNetworkAddress   = NULL;
	WCHAR	*pszEndpoint         = L"bt_server";
	WCHAR   *pszOptions          = NULL;
	WCHAR   *pszStringBinding    = NULL;

	RpcStringBindingCompose (pszUuid, pszProtocolSequence, pszNetworkAddress,
					pszEndpoint, pszOptions, &pszStringBinding);

	wprintf (L"String binding : %s\n", pszStringBinding);

	RpcBindingFromStringBinding (pszStringBinding, &bluetooth_IfHandle);
#endif

	svsutil_Initialize ();
	int fArgError = TRUE;
	int fServer = FALSE;
	int iRuns = 0;
	int iThreads = 0;

	WCHAR szTargetName[_MAX_PATH];

	// -server name psm <max packet>
	// -client name psm <max packet> <bt_addr/name/*> <runs> <iterations per run> <threads active>

	while (argc > 4) {
		if (wcsicmp (argv[1], L"-server") == 0)
			fServer = TRUE;
		else if (wcsicmp (argv[1], L"-client") != 0) {
			wprintf (L"Neither server nor client...\n");
			break;
		}

		WCHAR *p = argv[3];

		if (! GetUS (&p, &g_usPSM)) {
			wprintf (L"Bad PSM format\n");
			break;
		}

		p = argv[4];

		if ((! GetUS (&p, &g_usMaxPacket)) || (g_usMaxPacket < sizeof(Packet))) {
			wprintf (L"Bad max packet format or too small (min %d)\n", sizeof (Packet));
			break;
		}

		g_pFile = new SVSExpArray<Paragraph>;

		FILE *fp = _wfopen (argv[2], L"r");
		if (! fp) {
			wprintf (L"Cannot open %s for read\n", argv[2]);
			break;
		}

		char *szCurrentText = NULL;
		int cCurrentText = 1;

		int fArgError2 = FALSE;

		while (! feof (fp)) {
			char szString[512];
			if (! fgets (szString, sizeof(szString), fp))
				break;

			int c = strlen (szString);

			if ((szString[0] != '\0') && (szString[0] != '\n')) {
				szCurrentText = (char *)realloc (szCurrentText, c + cCurrentText);
				if (! szCurrentText) {
					wprintf (L"No memory for the string!\n");
					fArgError2 = TRUE;
					break;
				}
				memcpy (szCurrentText + cCurrentText - 1, szString, c + 1);
				cCurrentText += c;
			} else if (szCurrentText) {
				if (! (*g_pFile).SRealloc (g_cParagraphs + 1)) {
					wprintf (L"No memory for the string!\n");
					fArgError2 = TRUE;
					break;
				}
				(*g_pFile)[g_cParagraphs].cText = cCurrentText;
				(*g_pFile)[g_cParagraphs].pText = (unsigned char *)szCurrentText;

				++g_cParagraphs;

				cCurrentText = 1;
				szCurrentText = NULL;
			}
		}

		fclose (fp);

		if (fArgError2)
			break;

		wprintf (L"Read file %s successfully\n", argv[2]);
		if (! fServer) {
			if (argc != 9) {
				wprintf (L"Not enough or too many args for client\n");
				break;
			}

			p = argv[5];

			if (! GetBA (&p, &g_ba)) {
				wcsncpy (szTargetName, argv[5], _MAX_PATH-2);
				szTargetName[_MAX_PATH-1] = '\0';
			}

			iRuns = _wtoi (argv[6]);
			g_iRequests = _wtoi (argv[7]);
			iThreads = _wtoi (argv[8]);
			if ((iRuns <= 0) || (iRuns > MAX_RUNS)) {
				wprintf (L"runs number out of bounds\n");
				break;
			}
			if ((iThreads <= 0) || (iThreads > MAX_THREADS)) {
				wprintf (L"threads number out of bounds\n");
				break;
			}
			if ((g_iRequests <= 0) || (g_iRequests > MAX_REQS)) {
				wprintf (L"number of requests out of bounds\n");
				break;
			}
		}

		fArgError = FALSE;
		break;
	}

	if (fArgError) {
		wprintf (L"Usage:\n\t%s -server name psm <max packet>\nor\n\t%s -client name psm <max packet> <machine name or *> <runs> <iterations per run> <threads active>\n", argv[0], argv[0]);
		exit (1);
	}

	if (fServer) {
#if ! defined (UNDER_CE)
		HANDLE hConsoleOutput    = GetStdHandle (STD_OUTPUT_HANDLE);
		SetConsoleCtrlHandler (cmd_InterruptHandler, TRUE);
#endif
		int iErr = BthWriteScanEnableMask (3);
		wprintf (L"Enabled inquiry and connect scan. Return code %d\n", iErr);
		wprintf (L"Entering server.\n");
		iErr = L2CAPListen (g_usPSM, g_usMaxPacket);

		wprintf (L"L2CAPListen returns 0x%08x (%d)\n", iErr, iErr);

		while (iErr == ERROR_SUCCESS) {
			unsigned short cid, outmtu;
			BT_ADDR ba;
			int iErr = L2CAPAccept (g_usPSM, &ba, &cid, &outmtu);

			if (iErr != ERROR_SUCCESS) {
				wprintf (L"Accept exited with code 0x%08x (%d)\n", iErr, iErr);
				L2CAPClosePSM (g_usPSM);
				break;
			}

			if (outmtu < sizeof(Packet)) {
				wprintf (L"0x%04x New connection rejected: too small an MTU (%d)\n", cid, outmtu);
				L2CAPCloseCID (cid);
				continue;
			}

			wprintf (L"0x%04x New connection successful - spinning read thread\n", cid);

			ThreadData *ptd = (ThreadData *)malloc(sizeof(ThreadData));
			ptd->cid = cid;
			ptd->outMTU = outmtu;

			CloseHandle (CreateThread (NULL, 0, ServerReadThread, (void *)ptd, 0, NULL));
		}

		wprintf (L"Exiting server\n");
		return 0;
	}

	if (szTargetName[0]) {
		wprintf (L"Performing inquiry\n");
		BthInquiryResult ir[256];
		unsigned int cGot = 0;
		int iError = BthPerformInquiry (0x9e8b33, 0x10, szTargetName[0] == '*' ? 1 : 0, 256, &cGot, ir);
		if ((iError != ERROR_SUCCESS) || (! cGot)) {
			wprintf (L"Inquiry returned error code %d, %d entries\n", iError, cGot);
			return 0;
		}

		if (szTargetName[0] == '*')
			g_ba = ir[0].ba;
		else {
			for (int i = 0 ; i < (int)cGot ; ++i) {
				WCHAR sz[_MAX_PATH];
				unsigned int cLen;
				iError = BthRemoteNameQuery (&ir[i].ba, _MAX_PATH, &cLen, sz);
				if ((iError == ERROR_SUCCESS) && (wcsicmp (sz, szTargetName) == 0))
					break;
			}

			if (i != (int)cGot) {
				g_ba = ir[i].ba;
			} else {
				wprintf (L"Name %s not found!\n", szTargetName);
				return 0;
			}
		}
	}

	//	client
	HANDLE hThreads[MAX_THREADS];
	DWORD dwTicks[MAX_THREADS];

	for (int i = 0 ; i < iThreads ; ++i) {
		dwTicks[i] = GetTickCount ();
		if (hThreads[i] = CreateThread (NULL, 0, ClientReadThread, NULL, 0, NULL))
			--iRuns;
		else
			break;
	}

	for ( ; i < iThreads ; ++i)
		hThreads[i] = NULL;

	for ( ; ; ) {
		int iActive = 0;
		for (i = 0 ; i < iThreads ; ++i, ++iActive) {
			if (! hThreads[i])
				break;
		}

		if (iActive == 0)
			break;

		DWORD dwRes = WaitForMultipleObjects (iActive, hThreads, FALSE, 10000);

		if (dwRes == WAIT_TIMEOUT) {
			DWORD dwNow = GetTickCount ();
			for (i = 0 ; i < iActive ; ++i) {
				if (dwNow - dwTicks[i] > 3600000) {
					wprintf (L"Thread 0x%08x is running for over an hour\n", hThreads[i]);
					dwTicks[i] += 300000; // check in 5 minutes
				}
			}
			continue;
		}

		if ((dwRes >= WAIT_OBJECT_0) && (dwRes < WAIT_OBJECT_0 + (DWORD)iActive)) {
			i = dwRes - WAIT_OBJECT_0;
			CloseHandle (hThreads[i]);
			if (i < iActive - 1) {
				hThreads[i] = hThreads[iActive - 1];
				dwTicks[i] = dwTicks[iActive - 1];
			}
			hThreads[iActive-1] = NULL;
			dwTicks[iActive-1] = 0;
			iActive--;
			if (iRuns > 0) {
				dwTicks[iActive] = GetTickCount ();
				hThreads[iActive] = CreateThread (NULL, 0, ClientReadThread, NULL, 0, NULL);
				if (hThreads[iActive]) {
					wprintf (L"New thread created (0x%08x)\n", hThreads[iActive]);
					--iRuns;
				} else 
					wprintf (L"Failed to create new thread, error 0x%08x %d\n", GetLastError (), GetLastError ());
			}
		} else {
			wprintf (L"Error in main thread (0x%08x %d)\n", dwRes, dwRes);
			break;
		}

	}

	wprintf (L"All done!\n");
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -