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

📄 bthcxn.cpp

📁 演示了如何从一个Gizmondo WinCE设备通过蓝牙接口连接到PC 的代码演示.
💻 CPP
📖 第 1 页 / 共 3 页
字号:

// 
// 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 + -