📄 sca.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
**/
#include <windows.h>
#include <bt_api.h>
#define BUF_MAX 256
int GetDI (WCHAR **pp, unsigned int *pi) {
while (**pp == ' ')
++*pp;
int iDig = 0;
*pi = 0;
while (iswdigit (**pp)) {
int c = **pp;
c = c - '0';
if ((c < 0) || (c > 9))
return FALSE;
*pi = *pi * 10 + c;
++*pp;
++iDig;
}
if ((iDig <= 0) || (iDig > 10))
return FALSE;
return TRUE;
}
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;
}
#define BPR 8
int GetUx (WCHAR **pp, void *pRes, int nDigs) {
while (**pp == ' ')
++*pp;
if (**pp != '0')
return FALSE;
++*pp;
if (**pp != 'x')
return FALSE;
++*pp;
int iDig = 0;
int iRes = 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;
iRes = iRes * 16 + c;
++*pp;
++iDig;
}
if (iDig > nDigs)
return FALSE;
switch (nDigs) {
case 2:
*(unsigned char *)pRes = (unsigned char)iRes;
break;
case 4:
*(unsigned short *)pRes = (unsigned short)iRes;
break;
case 8:
*(unsigned int *)pRes = (unsigned int)iRes;
break;
}
return TRUE;
}
void DumpBuff (WCHAR *szLineHeader, unsigned char *lpBuffer, unsigned int cBuffer) {
WCHAR szLine[5 + 7 + 2 + 4 * BPR];
for (int i = 0 ; i < (int)cBuffer ; i += BPR) {
int bpr = cBuffer - i;
if (bpr > BPR)
bpr = BPR;
wsprintf (szLine, L"%04x ", i);
WCHAR *p = szLine + wcslen (szLine);
for (int j = 0 ; j < bpr ; ++j) {
WCHAR c = (lpBuffer[i + j] >> 4) & 0xf;
if (c > 9) c += L'a' - 10; else c += L'0';
*p++ = c;
c = lpBuffer[i + j] & 0xf;
if (c > 9) c += L'a' - 10; else c += L'0';
*p++ = c;
*p++ = L' ';
}
for ( ; j < BPR ; ++j) {
*p++ = L' ';
*p++ = L' ';
*p++ = L' ';
}
*p++ = L' ';
*p++ = L' ';
*p++ = L' ';
*p++ = L'|';
*p++ = L' ';
*p++ = L' ';
*p++ = L' ';
for (j = 0 ; j < bpr ; ++j) {
WCHAR c = lpBuffer[i + j];
if ((c < L' ') || (c >= 127))
c = L'.';
*p++ = c;
}
for ( ; j < BPR ; ++j) {
*p++ = L' ';
}
*p++ = L'\n';
*p++ = L'\0';
wprintf (L"%s %s", szLineHeader ? szLineHeader : L"", szLine);
}
}
void DisplayModem (HANDLE hFile) {
DWORD dwModem = 0;
GetCommModemStatus (hFile, &dwModem);
wprintf (L": ");
if (dwModem & MS_CTS_ON)
wprintf (L"MS_CTS_ON ");
if (dwModem & MS_DSR_ON)
wprintf (L"MS_DSR_ON ");
if (dwModem & MS_RING_ON)
wprintf (L"MS_RING_ON ");
if (dwModem & MS_RLSD_ON)
wprintf (L"MS_RLSD_ON ");
wprintf (L"\n");
}
void GetAndPrintDCB (HANDLE hFile) {
DCB dcb;
memset (&dcb, 0, sizeof(dcb));
dcb.DCBlength = sizeof(dcb);
if (GetCommState (hFile, &dcb)) {
wprintf (L"Baud rate: %d\n", dcb.BaudRate);
wprintf (L"Binary: %s\n", dcb.fBinary ? L"yes" : L"no");
wprintf (L"Parity: %s\n", dcb.fParity ? L"yes" : L"no");
wprintf (L"fOutxCtsFlow %s\n", dcb.fOutxCtsFlow ? L"yes" : L"no");
wprintf (L"fOutxDsrFlow %s\n", dcb.fOutxDsrFlow ? L"yes" : L"no");
wprintf (L"fDtrControl %s\n", dcb.fDtrControl == DTR_CONTROL_DISABLE ? L"DTR_CONTROL_DISABLE" : (dcb.fDtrControl == DTR_CONTROL_ENABLE ? L"DTR_CONTROL_ENABLE" : (dcb.fDtrControl == DTR_CONTROL_HANDSHAKE ? L"DTR_CONTROL_HANDSHAKE" : L"unknown")));
wprintf (L"fDsrSensitivity %s\n", dcb.fDsrSensitivity ? L"yes" : L"no");
wprintf (L"fTXContinueOnXoff %s\n", dcb.fTXContinueOnXoff ? L"yes" : L"no");
wprintf (L"fOutX %s\n", dcb.fOutX ? L"yes" : L"no");
wprintf (L"fInX %s\n", dcb.fInX ? L"yes" : L"no");
wprintf (L"fErrorChar %s\n", dcb.fErrorChar ? L"yes" : L"no");
wprintf (L"fNull %s\n", dcb.fNull ? L"yes" : L"no");
wprintf (L"fRtsControl %s\n", dcb.fRtsControl == RTS_CONTROL_DISABLE ? L"RTS_CONTROL_DISABLE" : (dcb.fRtsControl == RTS_CONTROL_ENABLE ? L"RTS_CONTROL_ENABLE" : (dcb.fRtsControl == RTS_CONTROL_HANDSHAKE ? L"RTS_CONTROL_HANDSHAKE" : L"unknown")));
wprintf (L"fAbortOnError %s\n", dcb.fAbortOnError ? L"yes" : L"no");
wprintf (L"XonLim %d\n", dcb.XonLim);
wprintf (L"XoffLim %d\n", dcb.XoffLim);
wprintf (L"ByteSize %d\n", dcb.ByteSize);
wprintf (L"Parity %s\n", dcb.Parity == NOPARITY ? L"NOPARITY" : (dcb.Parity == ODDPARITY ? L"ODDPARITY" : (dcb.Parity == EVENPARITY ? L"EVENPARITY" : (dcb.Parity == MARKPARITY ? L"MARKPARITY" : dcb.Parity == SPACEPARITY ? L"SPACEPARITY" : L"UNKNOWN"))));
wprintf (L"StopBits %s\n", dcb.StopBits == ONESTOPBIT ? L"ONESTOPBIT" : (dcb.StopBits == ONE5STOPBITS ? L"ONE5STOPBITS" : (dcb.StopBits == TWOSTOPBITS ? L"TWOSTOPBITS" : L"UNKNOWN")));
wprintf (L"XonChar 0x%02x\n", dcb.XonChar);
wprintf (L"XoffChar 0x%02x\n", dcb.XoffChar);
wprintf (L"ErrorChar 0x%02x\n", dcb.ErrorChar);
wprintf (L"EofChar 0x%02x\n", dcb.EofChar);
wprintf (L"EvtChar 0x%02x\n", dcb.EvtChar);
} else
wprintf (L"GetCommState fails, error %d\n", GetLastError ());
}
DWORD WINAPI ReadThread (LPVOID lpVoid) {
HANDLE hFile = (HANDLE)lpVoid;
WCHAR szHeader[25];
wsprintf (szHeader, L"0x%08x > ", hFile);
SetCommMask (hFile, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_ERR | EV_RING | EV_EVENT1);
for ( ; ; ) {
DWORD ModemState;
if (! WaitCommEvent (hFile, &ModemState, NULL))
break;
wprintf (L"Read thread woke up, ModemState = 0x%08x!\n", ModemState);
if (ModemState & EV_RXCHAR) {
char buffer[BUF_MAX];
DWORD dwRead = 0;
if (! ReadFile (hFile, buffer, sizeof(buffer), &dwRead, NULL))
break;
DumpBuff (szHeader, (unsigned char *)buffer, dwRead);
}
if (ModemState & EV_ERR)
wprintf (L"COMM: Error signalled!\n");
int fDisplayModem = FALSE;
if (ModemState & EV_CTS) {
wprintf (L"EV_CTS ");
fDisplayModem = TRUE;
}
if (ModemState & EV_DSR) {
wprintf (L"EV_DSR ");
fDisplayModem = TRUE;
}
if (ModemState & EV_RLSD) {
wprintf (L"EV_RLSD ");
fDisplayModem = TRUE;
}
if (ModemState & EV_RING) {
wprintf (L"EV_RING ");
fDisplayModem = TRUE;
}
if (fDisplayModem)
DisplayModem (hFile);
if (ModemState & EV_EVENT1) {
wprintf (L"DCB arrived\n");
GetAndPrintDCB (hFile);
}
}
CloseHandle (hFile);
return 0;
}
int UserGetDCB (HANDLE hFile, DCB *pdcb) {
wprintf (L"Setting DCB.\n");
memset (pdcb, 0, sizeof (*pdcb));
pdcb->DCBlength = sizeof(*pdcb);
if (! GetCommState (hFile, pdcb)) {
wprintf (L"Cound not get comm state\n");
return FALSE;
}
int iDatum;
wprintf (L"Baud> ");
scanf ("%d", &iDatum);
pdcb->BaudRate = iDatum;
wprintf (L"DATABITS, 5-8\nByte Size> ");
scanf ("%d", &iDatum);
pdcb->ByteSize = iDatum;
wprintf (L"ONESTOPBIT=0, ONE5STOPBITS=1\nStop Bits> ");
scanf ("%d", &iDatum);
pdcb->StopBits = iDatum;
wprintf (L"NOPARITY = 0, ODDPARITY=1, EVENPARITY=2, MARKPARITY=3, SPACEPARITY=4\nParity> ");
scanf ("%d", &iDatum);
pdcb->Parity = iDatum;
if (pdcb->Parity != 0)
pdcb->fParity = TRUE;
return TRUE;
}
static void Help (void) {
wprintf (L"Use one of:\n\tEXIT\n\tSEND file\n\tTEXT string\n\tBIN binary data (list of 2 dig hex numbers)\n\tSETDCB\n\tGETDCB\n");
}
DWORD WINAPI WriteThread (LPVOID lpVoid) {
Help ();
HANDLE hFile = (HANDLE)lpVoid;
for ( ; ; ) {
wprintf (L"> ");
WCHAR szCommand[BUF_MAX];
if (! fgetws (szCommand, BUF_MAX, stdin))
break;
WCHAR *p = wcschr (szCommand, L'\n');
if (p)
*p = '\0';
if (wcsicmp (szCommand, L"EXIT") == 0)
break;
if (wcsicmp (szCommand, L"SETDCB") == 0) {
DCB dcb;
if (UserGetDCB (hFile, &dcb)) {
if (! SetCommState (hFile, &dcb))
wprintf (L"SetCommState: error %d\n", GetLastError ());
}
continue;
}
if (wcsicmp (szCommand, L"GETDCB") == 0) {
GetAndPrintDCB (hFile);
continue;
}
if (wcsnicmp (szCommand, L"SEND ", 5) == 0) {
WCHAR *szName = szCommand + 5;
WCHAR *szEOL = wcschr (szName, L'\n');
if (szEOL)
*szEOL = '\0';
FILE *fp = _wfopen (szName, L"r");
if (fp) {
unsigned char b[BUF_MAX];
for ( ; ; ) {
int c = fread (b, 1, sizeof(b), fp);
if (c <= 0)
break;
DWORD dwWritten = 0;
if (! WriteFile (hFile, (char *)b, c, &dwWritten, NULL)) {
wprintf (L"WriteFile returns %d bytes written, Error = %d\n", dwWritten, GetLastError ());
break;
}
if ((int)dwWritten != c)
wprintf (L"Written %d out of requested %d\n", dwWritten, c);
}
fclose (fp);
} else
wprintf (L"Cannot open %s\n", szCommand);
continue;
}
if (wcsnicmp (szCommand, L"TEXT ", 5) == 0) {
WCHAR *szString = szCommand + 5;
WCHAR *szEOL = wcschr (szString, L'\n');
if (szEOL)
*szEOL = '\0';
int c = (wcslen (szString) + 1) * sizeof(WCHAR);
if (c > sizeof (WCHAR)) {
DWORD dwWritten = 0;
if (! WriteFile (hFile, (char *)szString, c, &dwWritten, NULL)) {
wprintf (L"WriteFile returns %d bytes written, Error = %d\n", dwWritten, GetLastError ());
} else {
if ((int)dwWritten != c)
wprintf (L"Written %d out of requested %d\n", dwWritten, c);
}
} else
wprintf (L"Empty string!\n");
continue;
}
if (wcsnicmp (szCommand, L"BIN ", 4) == 0) {
WCHAR *szData = szCommand + 4;
WCHAR *szEOL = wcschr (szData, L'\n');
if (szEOL)
*szEOL = '\0';
int c = 0;
unsigned char *b = (unsigned char *)szCommand;
for ( ; ; ) {
if (! GetUx (&szData, b + c, 2))
break;
++c;
}
if (c > 0) {
DWORD dwWritten = 0;
if (! WriteFile (hFile, (char *)b, c, &dwWritten, NULL)) {
wprintf (L"WriteFile returns %d bytes written, Error = %d\n", dwWritten, GetLastError ());
} else {
if ((int)dwWritten != c)
wprintf (L"Written %d out of requested %d\n", dwWritten, c);
}
} else
wprintf (L"Empty string!\n");
continue;
}
}
CloseHandle (hFile);
return 0;
}
int wmain (int argc, WCHAR **argv) {
WCHAR *arg2 = argv[2];
WCHAR *arg3 = argv[3];
WCHAR *arg4 = argv[4];
int channel = 0;
int index = 0;
PORTEMUPortParams pp;
memset (&pp, 0, sizeof(pp));
if ((argc == 5) && (wcsicmp (argv[1], L"client") == 0) && GetBA(&arg2, &pp.device) && GetDI(&arg3, (unsigned int *)&channel) && GetDI(&arg4, (unsigned int *)&index)) {
pp.channel = channel & 0xff;
pp.uiportflags = RFCOMM_PORT_FLAGS_REMOTE_DCB;
} else if ((argc == 4) && (wcsicmp (argv[1], L"server") == 0) && GetDI(&arg2, (unsigned int *)&channel) && GetDI(&arg3, (unsigned int *)&index)) {
pp.flocal = TRUE;
pp.channel = channel & 0xff;
} else {
wprintf (L"Usage: %s {server | client <target bt_addr>} channel port_index\n", argv[0]);
return 1;
}
HANDLE h = RegisterDevice (L"COM", index, L"btd.dll", (DWORD)&pp);
wprintf (L"handle = 0x%08x\n", h);
if (h == NULL) {
wprintf (L"GetLastError = %d\n", GetLastError ());
return 0;
}
WCHAR szComPort[30];
wsprintf (szComPort, L"COM%d:", index);
HANDLE hCommPort = CreateFile (szComPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hCommPort == INVALID_HANDLE_VALUE) {
wprintf (L"Failed to open %s. Error = %d\n", szComPort, GetLastError ());
DeregisterDevice (h);
return 0;
}
CloseHandle (CreateThread(NULL, 0, ReadThread, (LPVOID)hCommPort, 0, NULL));
WriteThread ((LPVOID)hCommPort);
DeregisterDevice (h);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -