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.

CC2340R5: After calling GATT_DiscAllPrimaryServices() no event happens in central role

Part Number: CC2340R5

Tool/software:

Hello

I´m developing an application based in the basic BLE project set as Central (in syscfg file) and I´m using the example available in the simplelink_lowpower_f3_sdk_8_10_01_02.

When I connect to a peripheral, I´m trying to discover the Primary Services available and for that, I´m calling the GATT_DiscAllPrimaryServices function as shown in the code below present in the app_connection.c file:

void Connection_ConnEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
{
    switch(event)
    {
        case BLEAPPUTIL_LINK_ESTABLISHED_EVENT:
        {
            gapEstLinkReqEvent_t *gapEstMsg = (gapEstLinkReqEvent_t *)pMsgData;

            // Add the connection to the connected device list
            Connection_addConnInfo(gapEstMsg->connectionHandle, gapEstMsg->devAddr);

            /*! Print the peer address and connection handle number */
            MenuModule_printf(APP_MENU_CONN_EVENT, 0, "Conn status: Established - "
                              "Connected to " MENU_MODULE_COLOR_YELLOW "%s " MENU_MODULE_COLOR_RESET
                              "connectionHandle = " MENU_MODULE_COLOR_YELLOW "%d" MENU_MODULE_COLOR_RESET,
                              BLEAppUtil_convertBdAddr2Str(gapEstMsg->devAddr), gapEstMsg->connectionHandle);
            
            BLEAppUtil_registerConnNotifHandler(gapEstMsg->connectionHandle);
            uint8_t status = GATT_DiscAllPrimaryServices(gapEstMsg->connectionHandle, INVALID_TASK_ID); 

            /*! Print the number of current connections */
            MenuModule_printf(APP_MENU_NUM_CONNS, 0, "Connections number: "
                              MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET,
                              linkDB_NumActive());

            MenuModule_printf(APP_MENU_NUM_CONNS, 0, "Primary Services: "
                              MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET,
                              status);
            GPIO_write(CONFIG_GPIO_LED_GREEN, 1);
            break;
        }

        case BLEAPPUTIL_LINK_TERMINATED_EVENT:
        {
            gapTerminateLinkEvent_t *gapTermMsg = (gapTerminateLinkEvent_t *)pMsgData;

            // Remove the connection from the conneted device list
            Connection_removeConnInfo(gapTermMsg->connectionHandle);

            /*! Print the peer address and connection handle number */
            MenuModule_printf(APP_MENU_CONN_EVENT, 0, "Conn status: Terminated - "
                              "connectionHandle = " MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET
                              "reason = " MENU_MODULE_COLOR_YELLOW "%d" MENU_MODULE_COLOR_RESET,
                              gapTermMsg->connectionHandle, gapTermMsg->reason);

            /*! Print the number of current connections */
            MenuModule_printf(APP_MENU_NUM_CONNS, 0, "Connections number: "
                              MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET,
                              linkDB_NumActive());
            GPIO_write(CONFIG_GPIO_LED_GREEN, 0);
            break;
        }

        case BLEAPPUTIL_LINK_PARAM_UPDATE_REQ_EVENT:
        {
            gapUpdateLinkParamReqEvent_t *pReq = (gapUpdateLinkParamReqEvent_t *)pMsgData;

            // Only accept connection intervals with slave latency of 0
            // This is just an example of how the application can send a response
            if(pReq->req.connLatency == 0)
            {
                BLEAppUtil_paramUpdateRsp(pReq,TRUE);
            }
            else
            {
                BLEAppUtil_paramUpdateRsp(pReq,FALSE);
            }

            break;
        }

        case BLEAPPUTIL_LINK_PARAM_UPDATE_EVENT:
        {
            gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsgData;

            // Get the address from the connection handle
            linkDBInfo_t linkInfo;
            if (linkDB_GetInfo(pPkt->connectionHandle, &linkInfo) ==  SUCCESS)
            {
              // The status HCI_ERROR_CODE_PARAM_OUT_OF_MANDATORY_RANGE indicates that connection params did not change but the req and rsp still transpire
              if(pPkt->status == SUCCESS)
              {
                  MenuModule_printf(APP_MENU_CONN_EVENT, 0, "Conn status: Params update - "
                                    "connectionHandle = " MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET,
                                    pPkt->connectionHandle);
              }
              else
              {
                  MenuModule_printf(APP_MENU_CONN_EVENT, 0, "Conn status: Params update failed - "
                                    MENU_MODULE_COLOR_YELLOW "0x%x " MENU_MODULE_COLOR_RESET
                                    "connectionHandle = " MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET,
                                    pPkt->opcode, pPkt->connectionHandle);
              }
            }

            break;
        }

        default:
        {
            break;
        }
    }
}

I can confirm the event handler function above is being called when my central device connects to a peripheral and the function GATT_DiscAllPrimaryServices function is executed, returning success.

But in the GATT_EventHandler function in app_data.c file is not being invoked by the OS, which points no event is been forwarded to that event handler.

I believe I´m setting the events mask correctly like the code below shows but I don´t understand why I have no events happening after trying to discover the primary services.

static void GATT_EventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData);

// Events handlers struct, contains the handlers and event masks
// of the application data module
BLEAppUtil_EventHandler_t dataGATTHandler =
{
    .handlerType    = BLEAPPUTIL_GATT_TYPE,
    .pEventHandler  = GATT_EventHandler,
    .eventMask      = BLEAPPUTIL_ATT_FLOW_CTRL_VIOLATED_EVENT |
                      BLEAPPUTIL_ATT_MTU_UPDATED_EVENT |
                      BLEAPPUTIL_ATT_READ_RSP |
                      BLEAPPUTIL_ATT_WRITE_RSP |
                      BLEAPPUTIL_ATT_EXCHANGE_MTU_RSP|
                      BLEAPPUTIL_ATT_ERROR_RSP |
                      BLEAPPUTIL_ATT_HANDLE_VALUE_NOTI|
                      BLEAPPUTIL_ATT_READ_BY_GRP_TYPE_RSP
};

//*****************************************************************************
//! Functions
//*****************************************************************************

/*********************************************************************
 * @fn      GATT_EventHandler
 *
 * @brief   The purpose of this function is to handle GATT events
 *          that rise from the GATT and were registered in
 *          @ref BLEAppUtil_RegisterGAPEvent
 *
 * @param   event - message event.
 * @param   pMsgData - pointer to message data.
 *
 * @return  none
 */
static void GATT_EventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
{
  gattMsgEvent_t *gattMsg = ( gattMsgEvent_t * )pMsgData;
  switch ( gattMsg->method )
  {
    case ATT_FLOW_CTRL_VIOLATED_EVENT:
      {
          MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE, 0, "GATT status: ATT flow control is violated");
      }
      break;

    case ATT_MTU_UPDATED_EVENT:
      {
          MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE, 0, "GATT status: ATT MTU update to %d",
                            gattMsg->msg.mtuEvt.MTU);
      }
      break;

     case ATT_READ_RSP:
        {

            MenuModule_printf(APP_MENU_CONN_EVENT, 0, "Read rsp = 0x%02x",
                              gattMsg->msg.readRsp.pValue[0]);

             break;
        }
        
    case ATT_WRITE_RSP:
        {
            MenuModule_printf(APP_MENU_CONN_EVENT, 0, "Write sent = 0x%02x",
                             gattMsg->msg.writeReq.pValue[0]);
             break;
        }
        
    case ATT_EXCHANGE_MTU_RSP:
        {
            MenuModule_printf(APP_MENU_CONN_EVENT, 0, "MTU max size client = %d MTU max size server = %d",
                              gattMsg->msg.exchangeMTUReq.clientRxMTU, gattMsg->msg.exchangeMTURsp.serverRxMTU);
            break;
        }

    case   ATT_HANDLE_VALUE_NOTI:
        {
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE1, 0, "Notification received = 0x%02x",
                                          gattMsg->msg.handleValueNoti.pValue[0]);
            break;
        }
        
    case   ATT_READ_BY_GRP_TYPE_RSP:
        {
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE1, 0, "RECEBEU PRIMARY SERVICE");
            break;
        }
        
    case ATT_ERROR_RSP:
        {
            attErrorRsp_t  *pReq = (attErrorRsp_t  *)pMsgData;

            MenuModule_printf(APP_MENU_CONN_EVENT, 0, "Error %d",
                              pReq->errCode);
           break;

        }
        
    default:
      break;
  }
}

/*********************************************************************
 * @fn      Data_start
 *
 * @brief   This function is called after stack initialization,
 *          the purpose of this function is to initialize and
 *          register the specific events handlers of the data
 *          application module
 *
 * @return  SUCCESS, errorInfo
 */
bStatus_t Data_start( void )
{
  bStatus_t status = SUCCESS;

  // Register the handlers
  status = BLEAppUtil_registerEventHandler( &dataGATTHandler );

  // Return status value
  return( status );
}

What am I doing wrong? Perhaps I have to pass the BLEAppUtil Task ID number instead of INVALID_TASK_ID macro when I call the GATT_DiscAllPrimaryServices function?

Or perhaps I´m not registering correctly to receive those events? If so, where to register it correctly?

Any help is appreciated, thank you.

  • Hello Alexandre,

    Thanks for reaching out.

    Calling the GATT_DiscAllPrimaryServices() should generate an event of type ATT_READ_BY_GRP_TYPE_RSP, which I see you have correctly added to your eventMask. However, I would suggest to use the BLEAppUtil_getSelfEntity() function instead of INVALID_TASK_ID to get the actual task ID that the event is subscribed to. Afterwards, when you do a GATT_DiscAllChars(), please consider using a small delay before calling the function as we have seen that this is needed if the BLE stack is still processing information so that we can avoid a "bleNotReady" return status.

    BR,

    David.

  • BLEAppUtil_getSelfEntity(); did the trick. I spent some time trying to grab the correct task ID and that was exactly the function I was in need.

    Now the events are happening and that makes all sense in the end. 

    I was in doubt since the header for GATT_EventHandler function tells it is required to register the event in BLEAppUtil_RegisterGAPEvent function, which is inside the API so I was not sure if BLEAppUtil_registerEventHandler was doing this.

    /*********************************************************************
    * @fn GATT_EventHandler
    *
    * @brief The purpose of this function is to handle GATT events
    * that rise from the GATT and were registered in
    * @ref BLEAppUtil_RegisterGAPEvent
    *
    * @param event - message event.
    * @param pMsgData - pointer to message data.
    *
    * @return none
    */

    Thank you for the help