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: Example for reading characteristic value

Part Number: CC2340R5
Other Parts Discussed in Thread: SYSCONFIG, , CC2541

Tool/software:

I need to read a CTS value(s) from a device.

So far I used the following:

1.  After a link was established  calling the following 

 

uint8_t uuid[2] = {0x05, 0x18}; // CTS Service

GATT_DiscPrimaryServiceByUUID(gapEstMsg->connectionHandle,uuid,2,BLEAppUtil_getSelfEntity());

2. Then Getting a  ATT_FIND_BY_TYPE_VALUE_RSP event in GATT_EventHandler() function in app_data.c

At this event, I parsed the start and end handles of the service and called the 

bStatus_t bstatus = GATT_DiscAllChars(gattMsg->connHandle,
                                              lastStart,
                                              lastEnd,
                                              BLEAppUtil_getSelfEntity());

To get the CTS characteristics.

3. This resulted a new ATT_READ_BY_TYPE_RSP event in  GATT_EventHandler() function.

Since the CTS service has more then one char. I looped throughout the data returned to this function until I identify the 

characteristics UUID  I am interested in   which is 0x2a2b 

4. At that point I could not find(figure) out how to extract the CTS data, which should be an array of 10 bytes (as far as I understand)

In the code below I just print out the bytes found in in the  pDataList , which I index like an array. The values I get makes no sense to me as CTS Data

so I probably should look another place.

Optimally the example I am looking for wile use the GATT_DiscCharsByUUID instaed of  GATT_DiscAllChars()

Thanks 

/*********************************************************************
 * @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_FIND_BY_TYPE_VALUE_RSP:
    {
        uint16_t lastStart;
        uint16_t lastEnd;
        
        attFindByTypeValueRsp_t att = (attFindByTypeValueRsp_t)gattMsg->msg.findByTypeValueRsp;
        
        /* We need to build the 16-bit handles that we received when we discovered the service. */
        for (uint8_t i = 0; i < att.numInfo; i++)
        {
            /* NOTE: We are in little endian, but the BUILD_UINT16 macro accounts for this */

            /* The first two bytes will be start handle */
            uint16_t attHandle = BUILD_UINT16(att.pHandlesInfo[i * 4], att.pHandlesInfo[i * 4 + 1]);
            /* The second two bytes will be the end handle */
            uint16_t endHandle = BUILD_UINT16(att.pHandlesInfo[i * 4 + 2], att.pHandlesInfo[i * 4 + 3]);
            
            lastStart = attHandle;
            lastEnd = endHandle;

            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "start: %x", attHandle);
            display_index++;
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "end: %x", endHandle);
            display_index++;
        }

        /* This delay can be replaced with a timer, or applicaton event that then calls GATT_DiscAllChars.
         * Without a delay, timer, or separate application event, this call will fail since the stack is busy
         * processing messages during this time. For the sake of the example, a delay was used, but
         * it does not have to be an explicit delay.
         */
        ClockP_sleep(2);


        ////////////////////////////////////////
        bStatus_t bstatus = GATT_DiscAllChars(gattMsg->connHandle,
                                              lastStart,
                                              lastEnd,
                                              BLEAppUtil_getSelfEntity());
        if (bstatus != SUCCESS)
        {
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"CharsDiscAll FAILED!!!");
            display_index++;
        }else{
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"CharsDiscAll SUCCEDDED");
            display_index++;

        }
    }
    break;

////////////////////
case ATT_READ_BY_TYPE_RSP:
    {
        attReadByTypeRsp_t att = (attReadByTypeRsp_t)gattMsg->msg.readByTypeRsp;

        MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "ATT_READ_BY_TYPE_RSP len: %d numPairs: %d", att.len, att.numPairs);
        display_index++;

        for (uint8_t i = 0; i < att.numPairs; i++)
        {
            /* This is the Attribute Handle */
            uint16_t attHandle = BUILD_UINT16(att.pDataList[i * att.len + 0], att.pDataList[i * att.len + 1]);
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"ATT Handle: %x", attHandle);
            display_index++;

            /* This is the index to the beginning of the value data AFTER the attribute handle */
            uint8_t index = i * att.len + 2;

            /* The characteristic value data */
            uint8_t data1 = att.pDataList[index];     // Bit field of characteristic properties

            uint8_t data2 = att.pDataList[index + 1]; // Second Byte of Characteristic Value Handle
            uint8_t data3 = att.pDataList[index + 2]; // First Byte of Characteristic Value Handle

            /* If we were using 128-bit Bluetooth UUIDs, then we would have 16 of these instead of 2. */
            uint8_t data4 = att.pDataList[index + 3]; // Second byte of UUID
            uint8_t data5 = att.pDataList[index + 4]; // First byte of UUID
            uint16_t UUID=(uint16_t)(data5<<8)+data4;

            /* Since we are in little endian, we have to reverse the order to make the values make sense. */
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"UUID: [%x]  %x%x Val Handle: %x%x Properties: %x",UUID, data5, data4, data3, data2, data1);
            display_index++;
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"Data items: %d ",att.len*att.numPairs );
          if(UUID==0x2a2b){
                for(uint16_t i=0;i< att.len*att.numPairs;i++){
                    MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"[%d] ",att.pDataList[i] );
                
                }


          }

        }
    }
    break;

////////////////////

case ATT_WRITE_REQ: //ATT_READ_BY_TYPE_RSP:
    {
        attReadByTypeRsp_t att = (attReadByTypeRsp_t)gattMsg->msg.readByTypeRsp;

        if (att.numPairs == 0)
            break;

        MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "ATT_READ_BY_TYPE_RSP");
        display_index++;
        MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "Length: %d : Number of Pairs: %d", att.len, att.numPairs);
        display_index++;

        for (uint8_t i = 0; i < att.numPairs; i++)
        {
            /* This is the Attribute Handle */
            uint16_t attHandle = BUILD_UINT16(att.pDataList[i * att.len + 0], att.pDataList[i * att.len + 1]);

            /* This is the index to the beginning of the value data AFTER the attribute handle */
            uint8_t index = i * att.len + 2;

            /* The characteristic value data */
            uint8_t char_properties = att.pDataList[index];     // Bit field of characteristic properties

            uint16_t value_handle = BUILD_UINT16(att.pDataList[index + 1], att.pDataList[index + 2]);

            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,
                              "    ATT Handle: %x : Value Handle %x : Properties : %x",
                              attHandle, value_handle, char_properties);
            display_index++;

            if (att.len - 5 == 2)
            {
               uint16_t char_16bit_uuid = BUILD_UINT16(att.pDataList[index + 3], att.pDataList[index + 4]);
               MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"    UUID: %x", char_16bit_uuid);
               display_index++;
            }
            else
            {
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"    UUID: ");
                for (uint8_t j = 0; j < 16; j++)
                {
                    MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, j + 10, "%x", att.pDataList[index + 3 + j]);
                }
                display_index++;
            }


        }
    }
    break;
    
///////////////////////////////////////////








    default:
      break;
  }
}

  • I modified my example above and call now the   GATT_ReadCharValue() that should fire the  ATT_READ_RSP event

    But instead it fires the ATT_ERROR_RSP event

    The code below shows the process  and it is located in  the app_data.c file

    /******************************************************************************
    
    @file  app_data.c
    
    @brief This file contains the application data functionality
    
    Group: WCS, BTS
    Target Device: cc23xx
    
    ******************************************************************************
    
     Copyright (c) 2022-2024, Texas Instruments Incorporated
     All rights reserved.
    
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
    
     *  Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
    
     *  Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
    
     *  Neither the name of Texas Instruments Incorporated nor the names of
        its contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
    
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
    ******************************************************************************
    
    
    *****************************************************************************/
    
    //*****************************************************************************
    //! Includes
    //*****************************************************************************
    #include <string.h>
    #include <ti/bleapp/ble_app_util/inc/bleapputil_api.h>
    #include <ti/bleapp/menu_module/menu_module.h>
    #include <app_main.h>
    
    
    
    //*****************************************************************************
    //! Defines
    //*****************************************************************************
    
    //*****************************************************************************
    //! Globals
    //*****************************************************************************
    
    //*****************************************************************************
    //
    //*****************************************************************************
    
    
    
    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_FIND_BY_TYPE_VALUE_RSP | // service discovery.
                          BLEAPPUTIL_ATT_READ_BY_TYPE_RSP  | // characteristics read evebt.
                          BLEAPPUTIL_ATT_READ_RSP |         // response for reading charac value.
                          BLEAPPUTIL_ATT_ERROR_RSP  // error on the server
    };
    
    static uint16_t display_index=0;
    //*****************************************************************************
    //! 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_FIND_BY_TYPE_VALUE_RSP: // result from  call to GATT_DiscPrimaryServiceByUUID() in app_connection.c
        {
            uint16_t lastStart;
            uint16_t lastEnd;
            
            attFindByTypeValueRsp_t att = (attFindByTypeValueRsp_t)gattMsg->msg.findByTypeValueRsp;
            
           
            /* We need to build the 16-bit handles that we received when we discovered the service. */
            for (uint8_t i = 0; i < att.numInfo; i++)
            {
                /* NOTE: We are in little endian, but the BUILD_UINT16 macro accounts for this */
    
                /* The first two bytes will be start handle */
                uint16_t attHandle = BUILD_UINT16(att.pHandlesInfo[i * 4], att.pHandlesInfo[i * 4 + 1]);
                /* The second two bytes will be the end handle */
                uint16_t endHandle = BUILD_UINT16(att.pHandlesInfo[i * 4 + 2], att.pHandlesInfo[i * 4 + 3]);
                
                lastStart = attHandle;
                lastEnd = endHandle;
    
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0, " CTS Service: Start Handle= %x. End Handle= %x", attHandle, endHandle);
                
            }
    
            
            ClockP_sleep(2);
            // Discovering char by UUID
            attAttrType_t 	attType = {
                .len=2,
                .uuid= {0x2b, 0x2a} // CTS Service value
                //.uuid =BUILD_UINT16(0x2a,0x2b)
            };
            attReadByTypeReq_t byTypeReq={
            .startHandle=lastStart,
            .endHandle=lastEnd,
            .type=attType
            };
    
            // this  call will result a ATT_READ_BY_TYPE_RSP event
            bStatus_t bstatus = GATT_DiscCharsByUUID(gattMsg->connHandle,   
                                                  &byTypeReq,
                                                  BLEAppUtil_getSelfEntity());
            
             if (bstatus == SUCCESS)
            {
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"Call to DiscCharsByUUID  SUCCEDDED");
            }else{
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"Call to DiscCharsByUUID FAILED!!!");
            }
        }
        break;
    
    
    case ATT_READ_BY_TYPE_RSP:
        {
            attReadByTypeRsp_t att = (attReadByTypeRsp_t)gattMsg->msg.readByTypeRsp;
    
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0, "ATT_READ_BY_TYPE_RSP len: %d numPairs: %d", att.len, att.numPairs);
            
            if(att.len==0){
                break;
            }
    
            for (uint8_t i = 0; i < att.numPairs; i++)
            {
                /* This is the Attribute Handle */
                uint16_t attHandle = BUILD_UINT16(att.pDataList[i * att.len + 0], att.pDataList[i * att.len + 1]);
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"ATT Handle: %x", attHandle);
            
    
                /* This is the index to the beginning of the value data AFTER the attribute handle */
                uint8_t index = i * att.len + 2;
    
                /* The characteristic value data */
                uint8_t data1 = att.pDataList[index];     // Bit field of characteristic properties
    
                uint8_t data2 = att.pDataList[index + 1]; // Second Byte of Characteristic Value Handle
                uint8_t data3 = att.pDataList[index + 2]; // First Byte of Characteristic Value Handle
    
                /* If we were using 128-bit Bluetooth UUIDs, then we would have 16 of these instead of 2. */
                uint8_t data4 = att.pDataList[index + 3]; // Second byte of UUID
                uint8_t data5 = att.pDataList[index + 4]; // First byte of UUID
                uint16_t UUID=(uint16_t)(data5<<8)+data4;
    
                /* Since we are in little endian, we have to reverse the order to make the values make sense. */
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"UUID: [%x]  %x%x Val Handle: %x%x Properties: %x",UUID, data5, data4, data3, data2, data1);
                
              if(UUID==0x2a2b){
                     MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"CHAR 2a2b Discovered" );
                    
                    //bStatus_t bstatus  = GATT_ReadCharValue(	uint16 	connHandle,attReadReq_t * 	pReq,uint8 	taskId ); // this will return ATT_READ_RSP event
                    attReadReq_t readReq={
                            //.handle =(uint16_t)(data2<<8)+data3
                            .handle =BUILD_UINT16(data2,data3)
                    };
                 
                  ClockP_sleep(2);
    
                   bStatus_t bstatus = GATT_ReadCharValue(gattMsg->connHandle,&readReq,BLEAppUtil_getSelfEntity() ); // this will return ATT_READ_RSP event
    
                    if (bstatus == SUCCESS)
                    {
                        MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"Call Read Char Val SUCCEDDED");
                        
                    }else{
                        MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"Call Read Char Val FAILED!!!");
                        
    
                    }
                break;
              } // 0x2a2b CTS current time characteristic
            
            }
        }
        break;
    case ATT_READ_RSP:
        {
            attReadRsp_t readRsp=  (attReadRsp_t)gattMsg->msg.readRsp; 
                uint16_t len=readRsp.len;
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"ERROR ON the Server ");
          
        }
      break;
    case ATT_ERROR_RSP:
            {
                   MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"ERROR ON the Server ");
                   
            }
    break;
    ////////////////////
    
    case ATT_WRITE_REQ: //ATT_READ_BY_TYPE_RSP:
        {
            attReadByTypeRsp_t att = (attReadByTypeRsp_t)gattMsg->msg.readByTypeRsp;
    
    
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0, " ATT_READ_BY_TYPE_RSP Length: %d : Number of Pairs: %d", att.len, att.numPairs);
            if (att.numPairs == 0){
                break;        
            }
    
            for (uint8_t i = 0; i < att.numPairs; i++)
            {
                /* This is the Attribute Handle */
                uint16_t attHandle = BUILD_UINT16(att.pDataList[i * att.len + 0], att.pDataList[i * att.len + 1]);
    
                /* This is the index to the beginning of the value data AFTER the attribute handle */
                uint8_t index = i * att.len + 2;
    
                /* The characteristic value data */
                uint8_t char_properties = att.pDataList[index];     // Bit field of characteristic properties
    
                uint16_t value_handle = BUILD_UINT16(att.pDataList[index + 1], att.pDataList[index + 2]);
    
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,
                                  "    ATT Handle: %x : Value Handle %x : Properties : %x",
                                  attHandle, value_handle, char_properties);
               
    
                if (att.len - 5 == 2)
                {
                   uint16_t char_16bit_uuid = BUILD_UINT16(att.pDataList[index + 3], att.pDataList[index + 4]);
                   MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"    UUID: %x", char_16bit_uuid);
                  
                }
                else
                {
                    MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"    UUID: ");
                    for (uint8_t j = 0; j < 16; j++)
                    {
                        MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, j + 10, "%x", att.pDataList[index + 3 + j]);
                    }
                    
                }
    
    
            }
        }
        break;
        
    ///////////////////////////////////////////
    
    
    
    
    
    
    
    
        default:
          break;
      }
      GATT_bm_free(&gattMsg->msg, gattMsg->method) ;
    }
    
    /*********************************************************************
     * @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 );
    }
    

  • Hello,

    Thank you for reaching out! We will take a look at your issue and get back to you ASAP. In the meantime, what SDK version are you using?

    Best Regards,

    Tarek

  • F3_sdk  8.40.02.1

    Sysconfig 1.23.0

    Compiler TI Clang v4.0.2.LTS

  • Hello,

    Thanks for providing all this info! This is strange behavior indeed, and unfortunately, this error event is somewhat generic. Are you sure the UUID sent is not reversed? As in the difference between little endian notation vs big endian notation?

    Best Regards,

    Tarek

  • Hello,

    As much as I can see the address is correct. I tried both ways.

    I am using a 16 bit cahractristics UUID

    in the following way:

     // Discovering char by UUID
            attAttrType_t 	attType = {
                .len=2,
                .uuid= {0x2b, 0x2a} // CTS characteristic value of 0x2a2b
               
            };
            attReadByTypeReq_t byTypeReq={
            .startHandle=lastStart,
            .endHandle=lastEnd,
            .type=attType
            };
    
            // this  call will result a ATT_READ_BY_TYPE_RSP event
            bStatus_t bstatus = GATT_DiscCharsByUUID(gattMsg->connHandle,   
                                                  &byTypeReq,
                                                  BLEAppUtil_getSelfEntity());

    Do you have an example of reading characteristics value ?

    This could be very helpfull

  • Hello,

    I'm looking into this. Expect a response soon. Thank you for your patience!

    Best regards,

    Tarek

  • Hi Tarek 

    I am still looking forword for your help....

    Thanks

  • Hello Itmar,

    I'm so sorry for the delay! I was able to run the code you provided on my end and i was able to read the characteristic successfully.

    I followed the same process you did, and I noticed that you will indeed receive the ATT_ERROR_RSP event, however, right after, you will receive the ATT_READ_RSP event, where you'll be able to read the characteristic.

    Another note, the readRsp structure will include the length of the read response, but it will also include a pointer to the location in memory where the data read has been stored. You can double check this by checking the memory map. 

    If this doesn't work, and if you're receiving a large response, that cannot be sent in 1 read response, I would recommend using GATT_ReadLongCharValue().

    I believe this should solve your problem, if not, please let me know!

    Best Regards,

    Tarek

  • Hi Tarek

    Could you please post your project. This will be the easiest to verify that we are doing the same

    I tested mine by connecting to my CC2340R5 Development Kit from an IPhone, which like all OS devices has a built in CTS service.

    (this works fine using the older CC2541 chip with the the old BLE sdk 1.5.2 from which I am trying to migrate)

    Thanks

  • Hello Itamar,

    I'm using the same code you have provided. The only difference is the UUIDs I'm looking for, since I'm using the TI Simple Peripheral Service (UUID 0xFFF0 instead of 0x0518), and looking for char UUID 0xFFF2 instead of 0x2a2b. 

    Are you receiving the ATT_READ_RSP event? You can test this by turning on a GPIO by using GPIO_write(), or by simply breakpointing inside the event.

    Also, could you try connecting to a peripheral running the basic_ble out of box example, and looking for the UUIDs I mentioned above (UUID 0xFFF0 for service and 0xFFF2 for characteristic)? This way we can rule out the possibility that the peripheral is not sending the correct read response.

    Best Regards,

    Tarek

  • Hi Tarek

    I never get ATT_READ_RSP event. I simply set a breakpoint in this event but it never fired.

    The fact that you succeeded with reading characteristics value from another TI unit only shows that the TI BLE stack is compatible with itself. 

    This is expected.

    However,  in my case I connect to the CC2340R5 Development Kit from an IPhone. The connection is successful but when the development kit tries reading characteristics values from the phone, it fails. I would expect it to succeed, unless the CC2340R5 is not capable of such a transaction or I am doing something wrong Or there is a bug in the TI BLE stack itself.

    From your suggestion above (... try connecting to a peripheral running the basic_ble out of box example) I am not sure I explained my case well enough.

    ​I could of course test it as you suggested. But for the first you have concluded that it works for you and I have no reason to believe it will fail for me.

    Secondly, this is a different case. so approving it will not say much about my case.

    In may case the central (IPhone) initiates a connection to the peripheral(the dev.kit) and  soonafter  the connection is established, 

    the  peripheral​ (dev. kit) tries to read the CTS service  value provided by the central​ (phone).

    I would expect that such a scenario ​will work like it ​is working for me with the old CC2541. 

    Am I missing  something 

  • Hello Itamar,

    Thank you for the clarification! I had missed the fact that you're using the CTS service, which makes the peripheral a GATT client, and not the usual GATT server.

    I'm attempting replicating this exact issue on my end and will provide an answer as soon as possible.

    Thank you for your patience.

    Best Regards,

    Tarek

  • Hi Tarek

    I think I found the problem

    Apperantly in order to read CTS data from an OS device,the client and server must be paired.

    After pairing I can now read 10 bytes from the CTS service and the ATT_READ_RSP  is fired as expected.

    Thank you for trying to help me. Hope others can use this info for some good.