locked
To create a bluetooth connection using winsock RRS feed

  • Question

  • I am trying to run the sample application that has been given for creating a Bluetooth connection between two devices using the winsock library.

    I am running the sample bluetooth application a client and a CSR development board as a server. I want to transfer the data using the spp profile and display that data on the server side's terminal. On the client side, I am passing the address of the server through the command line. The connection has been established and i could see the spp server connect confirm message on the server side but unable to receive the packet with the spp data. I have also used a air sniffer to check whether the spp data packet is sent or not and i could see the spp data packet on the server side page inquiry but unable to receive the message in the handler of the server side. When trying to connect two CSR development board's using the spp profile i could see the data being transferred through the spp. Please help me with this as soon as possible. I am attaching the client side code in which i have made changes to the port of the server from 0 to 1.

    #include <stdio.h>
    #include <initguid.h>
    #include <winsock2.h>
    #include <ws2bth.h>
    #include <strsafe.h>
    #include <intsafe.h>

    // {B62C4E8D-62CC-404b-BBBF-BF3E3BBB1374}
    DEFINE_GUID(g_guidServiceClass, 0xb62c4e8d, 0x62cc, 0x404b, 0xbb, 0xbf, 0xbf, 0x3e, 0x3b, 0xbb, 0x13, 0x74);

    #define CXN_TEST_DATA_STRING              (L"ABHISHEK_TALLURI")
    #define CXN_TRANSFER_DATA_LENGTH          (sizeof(CXN_TEST_DATA_STRING))


    #define CXN_BDADDR_STR_LEN                17   // 6 two-digit hex values plus 5 colons
    #define CXN_MAX_INQUIRY_RETRY             3
    #define CXN_DELAY_NEXT_INQUIRY            15
    #define CXN_SUCCESS                       0
    #define CXN_ERROR                         1
    #define CXN_DEFAULT_LISTEN_BACKLOG        4



    wchar_t g_szRemoteAddr[CXN_BDADDR_STR_LEN + 1] = {0}; // 1 extra for trailing NULL character
    int  g_ulMaxCxnCycles = 1;




    ULONG RunClientMode(__in SOCKADDR_BTH ululRemoteBthAddr, __in int iMaxCxnCycles = 1);
    void  ShowCmdLineHelp(void);
    ULONG ParseCmdLine(__in int argc, __in_ecount(argc) wchar_t * argv[]);




    int _cdecl wmain(__in int argc, __in_ecount(argc)wchar_t *argv[])
    {
        ULONG       ulRetCode = CXN_SUCCESS;
        WSADATA     WSAData = {0};
        SOCKADDR_BTH RemoteBthAddr = {0};

        //
        // Parse the command line
        //
        ulRetCode = ParseCmdLine(argc, argv);
        if ( CXN_ERROR == ulRetCode ) {
            //
            // Command line syntax error.  Display cmd line help
            //
            ShowCmdLineHelp();
        } else if ( CXN_SUCCESS != ulRetCode) {
            wprintf(L"-FATAL- | Error in parsing command line\n");
        }

        //
        // Ask for Winsock version 2.2.
        //
        if ( CXN_SUCCESS == ulRetCode) {
            ulRetCode = WSAStartup(MAKEWORD(2, 2), &WSAData);
            if (CXN_SUCCESS != ulRetCode) {
                wprintf(L"-FATAL- | Unable to initialize Winsock version 2.2\n");
            }
        }

        if ( CXN_SUCCESS == ulRetCode) {

            //
            // Note, this app "prefers" the name if provided, but it is app-specific
            // Other applications may provide more generic treatment.
            //
                // Get address from formated address-string of the remote device and
                // run the application in client mode
                //
                int iAddrLen = sizeof(RemoteBthAddr);
                ulRetCode = WSAStringToAddressW(g_szRemoteAddr,
                                                   AF_BTH,
                                                   NULL,
                                                   (LPSOCKADDR)&RemoteBthAddr,
                                                   &iAddrLen);
                if ( CXN_SUCCESS != ulRetCode ) {
                    wprintf(L"-FATAL- | Unable to get address of the remote radio having formated address-string %s\n", g_szRemoteAddr);
                }

                if ( CXN_SUCCESS == ulRetCode ) {
                    ulRetCode = RunClientMode(RemoteBthAddr, g_ulMaxCxnCycles);
                }

            } 
        return(int)ulRetCode;
    }



    //
    // RunClientMode runs the application in client mode.  It opens a socket, connects it to a
    // remote socket, transfer some data over the connection and closes the connection.
    //
    ULONG RunClientMode(__in SOCKADDR_BTH RemoteAddr, __in int iMaxCxnCycles)
    {
        ULONG           ulRetCode = CXN_SUCCESS;
        int             iCxnCount = 0;
        wchar_t         *pszData = NULL;
        SOCKET          LocalSocket = INVALID_SOCKET;
        SOCKADDR_BTH    SockAddrBthServer = RemoteAddr;
        HRESULT         res;


    pszData = (wchar_t *) HeapAlloc(GetProcessHeap(),
                                     HEAP_ZERO_MEMORY,
                                     CXN_TRANSFER_DATA_LENGTH);
        if ( NULL == pszData ) {
            ulRetCode = STATUS_NO_MEMORY;
            wprintf(L"=CRITICAL= | HeapAlloc failed | out of memory, gle = [%d] \n", GetLastError());
        }
        if ( CXN_SUCCESS == ulRetCode ) {
            //
            // Setting address family to AF_BTH indicates winsock2 to use Bluetooth sockets
            // Port should be set to 0 if ServiceClassId is spesified.
            //
            SockAddrBthServer.addressFamily = AF_BTH;
            SockAddrBthServer.serviceClassId = g_guidServiceClass;
            SockAddrBthServer.port = 1;

            //
            // Create a static data-string, which will be transferred to the remote
            // Bluetooth device
            //

            res = StringCbCopyN(pszData, CXN_TRANSFER_DATA_LENGTH, CXN_TEST_DATA_STRING, CXN_TRANSFER_DATA_LENGTH);
            if ( FAILED(res) ) {
                wprintf(L"=CRITICAL= | Creating a static data string failed\n");
                ulRetCode = CXN_ERROR;
            }

        }

        if ( CXN_SUCCESS == ulRetCode ) {
        
            pszData[(CXN_TRANSFER_DATA_LENGTH/sizeof(wchar_t)) - 1] = 0;

            //
            // Run the connection/data-transfer for user specified number of cycles
            //
            for ( iCxnCount = 0;
                (0 == ulRetCode) && (iCxnCount < iMaxCxnCycles || iMaxCxnCycles == 0);
                iCxnCount++ ) {

                wprintf(L"\n");

                //
                // Open a bluetooth socket using RFCOMM protocol
                //
                LocalSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
                if ( INVALID_SOCKET == LocalSocket ) {
                    wprintf(L"=CRITICAL= | socket() call failed. WSAGetLastError = [%d]\n", WSAGetLastError());
                    ulRetCode = CXN_ERROR;
                    break;
                }
    wprintf(L"passed socket creation\n");
                //
                // Connect the socket (pSocket) to a given remote socket represented by address (pServerAddr)
                //
                if ( SOCKET_ERROR == connect(LocalSocket,
                                             (struct sockaddr *) &SockAddrBthServer,
                                             sizeof(SOCKADDR_BTH)) ) {
                    wprintf(L"=CRITICAL= | connect() call failed. WSAGetLastError=[%d]\n", WSAGetLastError());
                    ulRetCode = CXN_ERROR;
                    break;
                }

                //
                // send() call indicates winsock2 to send the given data
                // of a specified length over a given connection.
                //

    wprintf(L"*INFO* | Sending following data string: %s \n", str );

    int ret = 0;
    ret = send(LocalSocket,
    "abhishek",
                              sizeof("abhishek"),
                             0);
                if ( SOCKET_ERROR == ret ) {
                    wprintf(L"=CRITICAL= | send() call failed w/socket = [0x%I64X], szData = [%p], dataLen = [%I64d]. WSAGetLastError=[%d]\n", LocalSocket, pszData, CXN_TRANSFER_DATA_LENGTH, WSAGetLastError());
                    
    ulRetCode = CXN_ERROR;
                    break;
                }
    wprintf(L"return value %d\n",ret);
    int i;
    for(i=0;i<500000000;i++);
                //
                // Close the socket
                //
                if ( SOCKET_ERROR == closesocket(LocalSocket) ) {
                    wprintf(L"=CRITICAL= | closesocket() call failed w/socket = [0x%I64X]. WSAGetLastError=[%d]\n", LocalSocket, WSAGetLastError());
                    ulRetCode = CXN_ERROR;
                    break;
                }

                LocalSocket = INVALID_SOCKET;

            }
        }

        if ( INVALID_SOCKET != LocalSocket ) {
            closesocket(LocalSocket);
            LocalSocket = INVALID_SOCKET;
        }

        if ( NULL != pszData ) {
            HeapFree(GetProcessHeap(), 0, pszData);
            pszData = NULL;
        }

        return(ulRetCode);
    }

    //
    // ShowCmdLineSyntaxHelp displays the command line usage
    //
    void ShowCmdLineHelp(void)
    {
        wprintf(
              L"\n  Bluetooth Connection Sample application for demonstrating connection and data transfer."
              L"\n"
              L"\n"
              L"\n  BTHCxn.exe  [-n<RemoteName> | -a<RemoteAddress>] "
              L"\n                  [-c<ConnectionCycles>]"
              L"\n"
              L"\n"
              L"\n  Switches applicable for Client mode:"
              L"\n    -n<RemoteName>        Specifies name of remote BlueTooth-Device."
              L"\n"
              L"\n    -a<RemoteAddress>     Specifies address of remote BlueTooth-Device."
              L"\n                          The address is in form XX:XX:XX:XX:XX:XX"
              L"\n                          where XX is a hexidecimal byte"
              L"\n"
              L"\n                          One of the above two switches is required for client."
              L"\n"
              L"\n"
              L"\n  Switches applicable for both Client and Server mode:"
              L"\n    -c<ConnectionCycles>  Specifies number of connection cycles."
              L"\n                          Default value for this parameter is 1.  Specify 0 to "
              L"\n                          run infinite number of connection cycles."
              L"\n"
              L"\n"
              L"\n"
              L"\n  Command Line Examples:"
              L"\n    \"BTHCxn.exe -c0\""
              L"\n    Runs the BTHCxn server for infinite connection cycles."
              L"\n    The application reports minimal information onto the cmd window."
              L"\n"
              L"\n    \"BTHCxn.exe -nServerDevice -c50\""
              L"\n    Runs the BTHCxn client connecting to remote device (having name "
              L"\n    \"ServerDevice\" for 50 connection cycles."
              L"\n    The application reports minimal information onto the cmd window."
              L"\n"
              );
    }

    //
    // ParseCmdLine parses the command line and sets the global variables accordingly.
    // It returns CXN_SUCCESS if successful and CXN_ERROR if it detected a mistake in the
    // command line parameter used.
    //
    ULONG ParseCmdLine (__in int argc, __in_ecount(argc) wchar_t * argv[])
    {
        int     cbStrLen = 0;
        ULONG   ulRetCode = CXN_SUCCESS;
        HRESULT res;

        for ( int i = 1; i < argc; i++ ) {
            wchar_t * pszToken = argv[i];
            if ( *pszToken == L'-' || *pszToken == L'/' ) {
                wchar_t token;

                //
                // skip over the "-" or "/"
                //
                pszToken++;

                //
                // Get the command line option
                //
                token = *pszToken;

                //
                // Go one past the option the option-data
                //
                pszToken++;

                //
                // Get the option-data
                //
                switch ( token ) {
                /*case L'n':
                    cbStrLen = lstrlen(pszToken);
                    if ( ( 0 < cbStrLen ) && ( BTH_MAX_NAME_SIZE >= cbStrLen ) ) {
                        res = StringCbCopy(g_szRemoteName, sizeof(g_szRemoteName), pszToken);
                        if ( FAILED(res) ) {
                            ulRetCode = CXN_ERROR;
                            wprintf(L"!ERROR! | cmd line | Unable to parse -n<RemoteName>, length error (min 1 char, max %d chars)\n", BTH_MAX_NAME_SIZE);
                        }
                    } else {
                        ulRetCode = CXN_ERROR;
                        wprintf(L"!ERROR! | cmd line | Unable to parse -n<RemoteName>, length error (min 1 char, max %d chars)\n", BTH_MAX_NAME_SIZE);
                    }
                    break;
    */
                case L'a':
                    cbStrLen = lstrlen(pszToken);
                    if ( CXN_BDADDR_STR_LEN == cbStrLen ) {
                        res = StringCbCopy(g_szRemoteAddr, sizeof(g_szRemoteAddr), pszToken);
                        if ( FAILED(res) ) {
                            ulRetCode = CXN_ERROR;
                            wprintf(L"!ERROR! | cmd line | Unable to parse -a<RemoteAddress>, Remote bluetooth radio address string length expected %d | Found: %d)\n", CXN_BDADDR_STR_LEN, cbStrLen);
                        }
                    } else {
                        ulRetCode = CXN_ERROR;
                        wprintf(L"!ERROR! | cmd line | Unable to parse -a<RemoteAddress>, Remote bluetooth radio address string length expected %d | Found: %d)\n", CXN_BDADDR_STR_LEN, cbStrLen);
                    }
                    break;

                case L'c':
                    if ( 0 < lstrlen(pszToken) ) {
                        swscanf_s(pszToken, L"%d", &g_ulMaxCxnCycles);
                        if ( 0 > g_ulMaxCxnCycles ) {
                            ulRetCode = CXN_ERROR;
                            wprintf(L"!ERROR! | cmd line | Must provide +ve or 0 value with -c option\n");
                        }
                    } else {
                        ulRetCode = CXN_ERROR;
                        wprintf(L"!ERROR! | cmd line | Must provide a value with -c option\n");
                    }
                    break;

                case L'?':
                case L'h':
                case L'H':
                default:
                    ulRetCode = CXN_ERROR;
                }
            } else {
                ulRetCode = CXN_ERROR;
                wprintf(L"!ERROR! | cmd line | Bad option prefix, use '/' or '-' \n");
            }
        }

        return(ulRetCode);
    }
     
    Monday, August 26, 2013 6:27 AM

Answers