📄 bthcxn.cpp
字号:
//
// BTHCxnDemo.cpp - Simple Bluetooth application using Winsock 2.2 and RFCOMM protocol
//
// This is a part of the Microsoft Source Code Samples.
// Copyright 1996 - 2002 Microsoft Corporation.
// All rights reserved.
// This source code is only intended as a supplement to
// Microsoft Development Tools and/or WinHelp documentation.
// See these sources for detailed information regarding the
// Microsoft samples programs.
//
// This example demonstrates how to use Winsock-2.2 APIs to connect
// between two remote bluetooth devices and transfer data between them.
// This example only supports address family of type AF_BTH,
// socket of type SOCK_STREAM, protocol of type BTHPROTO_RFCOMM.
//
// Once this source code is built, the resulting application can be
// run either in server mode or in client mode. See command line help
// for command-line-examples and detailed explanation about all options.
//
#include <stdio.h>
#include <initguid.h>
#include <winsock2.h>
#include <ws2bth.h>
// {B62C4E8D-62CC-404b-BBBF-BF3E3BBB1374}
DEFINE_GUID(g_guidServiceClass, 0xb62c4e8d, 0x62cc, 0x404b, 0xbb, 0xbf, 0xbf, 0x3e, 0x3b, 0xbb, 0x13, 0x74);
#define CXN_BDADDR_STR_LEN 17 // 6 two-digit hex values plus 5 colons
#define CXN_TRANSFER_DATA_LENGTH 100 // length of the data to be transferred
#define CXN_MAX_INQUIRY_RETRY 3
#define CXN_DELAY_NEXT_INQUIRY 15
char g_szRemoteName[BTH_MAX_NAME_SIZE + 1] = {0}; // 1 extra for trailing NULL character
char g_szRemoteAddr[CXN_BDADDR_STR_LEN + 1] = {0}; // 1 extra for trailing NULL character
int g_ulMaxCxnCycles = 1, g_iOutputLevel = 0;
ULONG NameToBthAddr(IN const char * pszRemoteName, OUT BTH_ADDR * pRemoteBthAddr);
ULONG AddrStringToBtAddr(IN const char * pszRemoteAddr, OUT BTH_ADDR * pRemoteBtAddr);
ULONG RunClientMode(IN ULONGLONG ululRemoteBthAddr, IN int iMaxCxnCycles = 1);
ULONG RunServerMode(IN int iMaxCxnCycles = 1);
void ShowCmdLineHelp(void);
ULONG ParseCmdLine(IN int argc, IN char * argv[]);
int _cdecl main(int argc, char *argv[])
{
ULONG ulRetCode = 0;
WSADATA WSAData = {0};
ULONGLONG ululRemoteBthAddr = 0;
//
// Parse the command line
//
if ( 0 == ( ulRetCode = ParseCmdLine(argc, argv) ) )
{
//
// Ask for Winsock version 2.2.
//
if ( 0 != ( ulRetCode = WSAStartup(MAKEWORD(2, 2), &WSAData) ) )
{
printf("-FATAL- | Unable to initialize Winsock version 2.2\n");
goto CleanupAndExit;
}
if ( '\0' != g_szRemoteName[0] )
{
//
// Get address from name of the remote device and run the application in client mode
//
if ( 0 != ( ulRetCode = NameToBthAddr(g_szRemoteName, (BTH_ADDR *) &ululRemoteBthAddr) ) )
{
printf("-FATAL- | Unable to get address of the remote radio having name %s\n", g_szRemoteName);
goto CleanupAndExit;
}
ulRetCode = RunClientMode(ululRemoteBthAddr, g_ulMaxCxnCycles);
}
else if ( '\0' != g_szRemoteAddr[0] )
{
//
// Get address from formated address-string of the remote device and run the application in client mode
//
// BUGBUG should be calling WSAStringToAddress
//
if ( 0 != ( ulRetCode = AddrStringToBtAddr(g_szRemoteAddr, (BTH_ADDR *) &ululRemoteBthAddr) ) )
{
printf("-FATAL- | Unable to get address of the remote radio having formated address-string %s\n", g_szRemoteAddr);
goto CleanupAndExit;
}
ulRetCode = RunClientMode(ululRemoteBthAddr, g_ulMaxCxnCycles);
}
else
{
//
// No remote name/address specified. Run the application in server mode
//
ulRetCode = RunServerMode(g_ulMaxCxnCycles);
}
}
else if ( 1 == ulRetCode )
{
//
// Command line syntax error. Display cmd line help
//
ShowCmdLineHelp();
}
else
{
printf("-FATAL- | Error in parsing command line\n");
}
CleanupAndExit:
return (int) (ulRetCode);
}
//
// TODO: use inquiry timeout SDP_DEFAULT_INQUIRY_SECONDS
//
//
// NameToBthAddr converts a bluetooth device name to a bluetooth address,
// if required by performing inquiry with remote name requests.
// This function demonstrates device inquiry, with optional LUP flags.
//
ULONG NameToBthAddr(IN const char * pszRemoteName, OUT BTH_ADDR * pRemoteBtAddr)
{
INT iResult = 0, iRetryCount = 0;
BOOL bContinueLookup = FALSE, bRemoteDeviceFound = FALSE;
ULONG ulFlags = 0, ulPQSSize = sizeof(WSAQUERYSET);
HANDLE hLookup = 0;
PWSAQUERYSET pWSAQuerySet = NULL;
if ( ( NULL == pszRemoteName ) || ( NULL == pRemoteBtAddr ) )
{
goto CleanupAndExit;
}
if ( NULL == ( pWSAQuerySet = (PWSAQUERYSET) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulPQSSize) ) )
{
printf("!ERROR! | Unable to allocate memory for WSAQUERYSET\n");
goto CleanupAndExit;
}
//
// Search for the device with the correct name
//
for (iRetryCount = 0; !bRemoteDeviceFound && (iRetryCount < CXN_MAX_INQUIRY_RETRY); iRetryCount++)
{
//
// WSALookupService is used for both service search and device inquiry
// LUP_CONTAINERS is the flag which signals that we're doing a device inquiry.
//
ulFlags = LUP_CONTAINERS;
//
// Friendly device name (if available) will be returned in lpszServiceInstanceName
//
ulFlags |= LUP_RETURN_NAME;
//
// BTH_ADDR will be returned in lpcsaBuffer member of WSAQUERYSET
//
ulFlags |= LUP_RETURN_ADDR;
if ( 0 == iRetryCount )
{
printf("*INFO* | Inquiring device from cache...\n");
}
else
{
//
// Flush the device cache for all inquiries, except for the first inquiry
//
// By setting LUP_FLUSHCACHE flag, we're asking the lookup service to do
// a fresh lookup instead of pulling the information from device cache.
//
ulFlags |= LUP_FLUSHCACHE;
//
// Pause for some time before all the inquiries after the first inquiry
//
//
// BUGBUG why sleep. Try to get rid of this
//
// Remote Name requests will arrive after device inquiry has
// completed. Without a window to receive IN_RANGE notifications,
// we don't have a direct mechanism to determine when remote
// name requests have completed.
//
printf("*INFO* | Unable to find device. Waiting for %d seconds before re-inquiry...\n", CXN_DELAY_NEXT_INQUIRY);
Sleep(CXN_DELAY_NEXT_INQUIRY * 1000);
printf("*INFO* | Inquiring device ...\n");
}
//
// Start the lookup service
//
iResult = 0;
hLookup = 0;
bContinueLookup = FALSE;
ZeroMemory(pWSAQuerySet, ulPQSSize);
pWSAQuerySet->dwNameSpace = NS_BTH;
pWSAQuerySet->dwSize = sizeof(WSAQUERYSET);
iResult = WSALookupServiceBegin(pWSAQuerySet, ulFlags, &hLookup);
if ( (NO_ERROR == iResult) && (NULL != hLookup) )
{
bContinueLookup = TRUE;
}
else if ( 0 < iRetryCount )
{
printf("=CRITICAL= | WSALookupServiceBegin() failed with error code %d, WSALastError = %d\n", iResult, WSAGetLastError());
goto CleanupAndExit;
}
while ( bContinueLookup )
{
//
// Get information about next bluetooth device
//
// Note you may pass the same WSAQUERYSET from LookupBegin
// as long as you don't need to modify any of the pointer
// members of the structure, etc.
//
// ZeroMemory(pWSAQuerySet, ulPQSSize);
// pWSAQuerySet->dwNameSpace = NS_BTH;
// pWSAQuerySet->dwSize = sizeof(WSAQUERYSET);
if ( NO_ERROR == WSALookupServiceNext(hLookup, ulFlags, &ulPQSSize, pWSAQuerySet) )
{
//
// Since we're a non-unicode application, the remote
// name in lpszServiceInstanceName will have been converted
// from CP_UTF8 to CP_ACP, this may cause the name match
// to fail unexpectedly. If the app is to handle this,
// the app needs to be unicode.
//
if ( ( pWSAQuerySet->lpszServiceInstanceName != NULL ) && ( 0 == _stricmp(pWSAQuerySet->lpszServiceInstanceName, pszRemoteName) ) )
{
//
// Found a remote bluetooth device with matching name.
// Get the address of the device and exit the lookup.
//
CopyMemory(pRemoteBtAddr,
&((PSOCKADDR_BTH) pWSAQuerySet->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr,
sizeof(*pRemoteBtAddr));
bRemoteDeviceFound = TRUE;
bContinueLookup = FALSE;
}
}
else
{
if ( WSA_E_NO_MORE == ( iResult = WSAGetLastError() ) ) //No more data
{
//
// No more devices found. Exit the lookup.
//
bContinueLookup = FALSE;
}
else if ( WSAEFAULT == iResult )
{
//
// The buffer for QUERYSET was insufficient.
// In such case 3rd parameter "ulPQSSize" of function "WSALookupServiceNext()" receives
// the required size. So we can use this parameter to reallocate memory for QUERYSET.
//
HeapFree(GetProcessHeap(), 0, pWSAQuerySet);
pWSAQuerySet = NULL;
if ( NULL == ( pWSAQuerySet = (PWSAQUERYSET) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulPQSSize) ) )
{
printf("!ERROR! | Unable to allocate memory for WSAQERYSET\n");
bContinueLookup = FALSE;
}
}
else
{
printf("=CRITICAL= | WSALookupServiceNext() failed with error code %d\n", iResult);
bContinueLookup = FALSE;
}
}
}
//
// End the lookup service
//
WSALookupServiceEnd(hLookup);
}
CleanupAndExit:
if ( NULL != pWSAQuerySet )
{
HeapFree(GetProcessHeap(), 0, pWSAQuerySet);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -