This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Stellaris + Bluetooth SPP Example: How do I connect to my desktop computer?

Other Parts Discussed in Thread: CC2560

I am attempting to connect to my desktop computer with the CC2560 Bluetooth chip with RFCOMM and send bi-directional traffic.  To do so, I began with the SPP Bluetopia example.

I am having trouble establishing the connection.  At first this was because the example does not appear to support SDP requests, so I am now explicitly connecting to RFCOMM port 1.  This eventually throws a timeout exception on the desktop, and gives the following output from the device:

 

 

Bluetooth Stack ID 1
1 Link Keys Stored
Local BD_ADDR: 0xb8fffeaf31ab
HCI Version  : 4.0
Connectable  : Yes
Discoverable : Yes
Pairable     : Yes
SSP Enabled  : Yes
Execute Scheduler
GAP_LinkKeyRequest
Located Link Key at Index 0

 

 

Is there a better starting point?  Do you have advice on how to establish a simple bidirectional SPP/RFCOMM link here?

 - Eric

PS: It is odd to be on this side of the forum...

  • Hello Eric,

     

    The included SPP example is SPP client as per the requirement. It does not have a server open and so no SDP record is associated with it. It is an example showing how Stellaris can connect to a remote device using SPP (connection initiated by Stellaris)

    We will discuss with TI how to go forward with any changes that are desired for the sample applications. 

     

    Best Regards,

    Stonestreet One

  • Hello,

     

    Also we are putting together some guidelines/code for the same. We should have more useful information on the SPP server application by Monday. 

     

    Best Regards,

    Stonestreet One

  • Has any progress been made on this?

  • Hello Eric,

    Please try the following changes to support SPP server in the sample application.

    ---

    bluetooth.h

    Add

    extern int SPPOpenServer(unsigned int uiServerPort);

    extern int SPPCloseServer(void);

    ---
    bluetooth.c 
    define these errorcodes at the top
    #define UNABLE_TO_REGISTER_SERVER   -1
    #define FUNCTION_ERROR              -2
    #define INVALID_PARAMETERS_ERROR    -3
    //define this global variable
    static unsigned long g_ulSPPServerSDPHandle;
    //Add this case to SPP_EventCallback
                //
                // Open port indication
                //
                case etPort_Open_Indication:
                {
                   SPP_Open_Port_Indication_Data_t *pData;
                   pData = psSPPEventData->
                            Event_Data.SPP_Open_Port_Indication_Data;
                   //
                   // A remote port is requesting a connection.
                   //
                   Display(("SPP Open Port Indication, ID: 0x%04X\r\n",
                            pData->SerialPortID));
                   //
                   // Save the Serial Port ID for later use.
                   //
                   g_uiSerialPortID = psSPPEventData->Event_Data.SPP_Open_Port_Indication_Data->SerialPortID;
                   //
                   // If serial port corresponds to opened serial port, issue
                   // callback to user app
                   //
                   if(pData->SerialPortID == g_uiSerialPortID)
                   {
                      g_sRemoteBD_ADDR = pData->BD_ADDR;
                      IssueCallback(&g_sRemoteBD_ADDR, ceDeviceConnected);
                   }
                   break;
                }
    //Define the Following two functions
    //*****************************************************************************
    //
    // The following function is responsible for opening a Serial Port
    // Server on the Local Device.  This function opens the Serial Port
    // Server on the specified RFCOMM Channel.  This function returns
    // zero if successful, or a negative return value if an error
    // occurred.
    //
    //*****************************************************************************
    int
    SPPOpenServer(unsigned int uiServerPort)
    {
       int  iResult;
       char sServiceName[64];
       //
       // Simply attempt to open an Serial Server, on RFCOMM Server
       // provided Port.
       //
       iResult = SPP_Open_Server_Port(g_uiBluetoothStackID,
                                      uiServerPort,
                                      SPP_EventCallback,
                                      (unsigned long)0);
       //
       // If the Open was successful, then note the Serial Port
       // Server ID.
       //
       if(iResult > 0)
       {
          //
          // Note the Serial Port Server ID of the opened Serial
          // Port Server.
          //
          g_uiSerialPortID = iResult;
          //
          // The Server was opened successfully, now register a SDP
          // Record indicating that an Serial Port Server exists.
          // Do this by first creating a Service Name.
          //
          BTPS_SprintF(sServiceName, "Serial Port Server Port %u", uiServerPort);
          //
          // Now that a Service Name has been created try to Register the
          // SDP Record.
          //
          iResult = SPP_Register_SDP_Record(g_uiBluetoothStackID,
                                            g_uiSerialPortID,
                                            NULL,
                                            sServiceName,
                                            &g_ulSPPServerSDPHandle);
          //
          // If there was an error creating the Serial Port
          // Server's SDP Service Record then go ahead an close
          // down the server an flag an error.
          //
          if(iResult < 0)
          {
             SPP_Close_Server_Port(g_uiBluetoothStackID, g_uiSerialPortID);
             //
             // Flag that there is no longer an Serial Port Server
             // Open.
             //
             g_uiSerialPortID = 0;
             iResult   = UNABLE_TO_REGISTER_SERVER;
          }
          else
          {
             //
             // Simply flag to the user that everything initialized
             // correctly.
             //
             iResult = 0;
          }
       }
       else
       {
          iResult   = UNABLE_TO_REGISTER_SERVER;
       }
       return(iResult);
    }
    //*****************************************************************************
    //
    // The following function is responsible for closing a Serial Port
    // Server that was previously opened via a successful call to the
    // OpenServer() function.  This function returns zero if successful
    // or a negative return error code if there was an error.
    //
    //*****************************************************************************
    int
    SPPCloseServer(void)
    {
       int iResult;
       //
       // If a Serial Port Server is already opened, then simply close
       // it.
       //
       if(g_uiSerialPortID)
       {
          //
          // If there is an SDP Service Record associated with the Serial
          // Port Server then we need to remove it from the SDP Database.
          //
          if(g_ulSPPServerSDPHandle)
          {
             SPP_Un_Register_SDP_Record(g_uiBluetoothStackID,
                                        g_uiSerialPortID,
                                        g_ulSPPServerSDPHandle);
             //
             // Flag that there is no longer an SDP Serial Port Server
             // Record.
             //
             g_ulSPPServerSDPHandle = 0;
          }
          //
          // Finally close the Serial Port Server.
          //
          iResult = SPP_Close_Server_Port(g_uiBluetoothStackID,
                                          g_uiSerialPortID);
          if(iResult < 0)
          {
             Display(("SPP_Close_Server_Port(): Error %d\r\n", iResult));
             iResult = FUNCTION_ERROR;
          }
          else
          {
             iResult = 0;
          }
          //
          // Flag that there is no Serial Port Server currently open.
          //
          g_uiSerialPortID = 0;
       }
       else
       {
          iResult = INVALID_PARAMETERS_ERROR;
       }
       return(iResult);
    }
    ------
    in bt_spp.c
    //in MainApp
    //replace Block1 with Block2
    //Block1
                        if(!g_bConnected)
                        {
                            //
                            // Toggle the device discovery state.
                            //
                            if(!DeviceDiscovery(!g_bDeviceDiscoveryActive))
                            {
                                g_bDeviceDiscoveryActive =
                                    !g_bDeviceDiscoveryActive;
                                if(g_bDeviceDiscoveryActive)
                                {
                                    UpdateStatusBox("Searching for "
                                                    "devices...");
                                }
                                else
                                {
                                    UpdateStatusBox("Press Button to search "
                                                    "for devices.");
                                }
                            }
                        }
    //End of Block1
    //Block2
                        if(!g_bConnected)
                        {
                            UpdateStatusBox("Opening Server.");
                            SetLocalDeviceName("My Stellaris Server");
                            SPPOpenServer(1);
                        }
                        else
                        {
                            UpdateStatusBox("Closing Server.");
                            SPPCloseServer();
                        }
    //End of Block2
    ----------------------------------
    This will make the sample application act like an SPP server and it will not try to connect out to the demo device.
    Then the computer should be able to find the device (Name: "My Stellaris Server") and should be able to connect to it. 
    Please let us know if this helps and if you need any assistance.
    Best Regards,
    Stonestreet One. 
     

  • Hi Stonestreet One,

     

    I am trying the same demo, going to apply your patches.

    But I want to clarify which version should I apply to ? Is it for 7611 or newer ?

    Thank you for your support.

     

    Best Regards,

    Leo 

  • A couple of things to note:

    • The firmware example still shows up as a Bluetooth headset to your PC.  To change it so that it appears as a serial device you can change the class of device in InitializeDevice():

                //
                // Set the class of device
                //
                ASSIGN_CLASS_OF_DEVICE(g_sClassOfDevice, (Byte_t)0, //0x24,
                                                         (Byte_t)0x1F, //0x04,
                                                         (Byte_t)0); //0x04);

    • One thing that is missing is a function to write data from the device to the PC.  Here is a function that works for me:

    int
    WriteDataSPP(unsigned int uiDataLength, unsigned char *pucData)
    {
        int iReturnValue;
        tBoolean bDone;
        unsigned int uiBytesWritten;
        unsigned int uiTotalBytesWritten;

        //
        // Verify that the parameters passed in appear valid.
        //
        if(uiDataLength && pucData)
        {
            //
            // Loop while we have buffer space and we have data to write.
            //
            bDone = false;
            uiBytesWritten = 0;
            iReturnValue = 0;
            uiTotalBytesWritten = 0;
            while(!bDone && uiDataLength)
            {
                iReturnValue = SPP_Data_Write(g_uiBluetoothStackID,
                                             g_uiSerialPortID,
                                             (Word_t)uiDataLength, pucData);
                if(iReturnValue > 0)
                {
                    uiBytesWritten = (unsigned int)iReturnValue;
                    pucData += uiBytesWritten;
                    uiTotalBytesWritten += uiBytesWritten;
                    uiDataLength -= uiBytesWritten;

                    //
                    // Set the return value to the number of bytes written to handle
                    // the case where the DataLength has been decremented to 0.
                    //
                    iReturnValue  = (int)(uiTotalBytesWritten);
                }
                else
                {
                    //
                    // We have finished writing SPP Data.
                    //
                    bDone = true;

                    if(!iReturnValue)
                    {
                        //
                        // A value of 0 indicates that their was no more data to
                        // write.
                        //
                        iReturnValue = (int)(uiTotalBytesWritten);
                    }
                    else
                    {
                        //
                        // An error occured.
                        //
                        Display(("SPP_Data_Write returned %d.\r\n", iReturnValue));
                        iReturnValue = BTH_ERROR_REQUEST_FAILURE;
                    }
                }
            }
        }
        else
        {
            iReturnValue = BTH_ERROR_INVALID_PARAMETER;
        }

        return(iReturnValue);
    }

  • Thanks for your inputs Nick.

    Regards,

    ~Miguel

  • Hi StoneStreet One,

    In your sample code, the following code segment seems unreasonable.

                   if(pData->SerialPortID == g_uiSerialPortID)
                   {
                      g_sRemoteBD_ADDR = pData->BD_ADDR;
                      IssueCallback(&g_sRemoteBD_ADDR, ceDeviceConnected);
                   }

    The expression (pData->SerialPortID == g_uiSerialPortID) must be true.

    Would you please explain why you write it this way?

    Also, do we need to call SPP_Open_Port_Request_Response() when processing SPP event etPort_Open_Indication?


    Thanks,
    Money
  • Hello Money,

    Yes, the check in this context may be redundant but may want to use something like this for making it extensible for say multiple servers. 

    SPP_Open_Port_Request_Response is not needed when processing etPort_Open_Indication. It is needed when the server is in manual mode and you receive etPort_Open_Request_Indication. The application may want to do some processing (authentication maybe) and then respond to the request with SPP_Open_Port_Request_Response. When the server is in Automatic Accept mode, the connection request will be automatically accepted and etPort_Open_Indication will be dispatched. 

    Hope this helps. Please let us know if something is not clear.

     

    Best Regards,

    Stonestreet One. 

  • hi Stonestree One,

    i try to this code to get a connection with Android App (client).

    In android, I can find the device and pair with it, but once I try to open an RFCOMM socket, the program crashes

    tmp = mmDevice.createRfcommSocketToServiceRecord( UUID.fromString("00001101-0000-100­0-8000-00805F9B34FB" ) );

    is there no RFCOMM UUID in Bluetopia (Bluetooth Stack)?