This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

ble_gattc_evt_read_rsp_t::len expected value

Hey,

I'm building an application where I control both peripheral and central sides. Both sides are custom hardware with nRF52840s with softdevice s140 v6.0.0 using SDK 15.0.0.

I am currently adding a custom service for vendor-specific data. I have both sides working but have some issues with data length being transferred.

If I set up a characteristic with the maximum value of an MTU (247) and write data that is less than that value (say size of 50), on the central side, I see data length being read as 247 instead of 50.

So, I'm trying to find the expected value of ble_gattc_evt_read_rsp_t::len on the central. Is it to be the max length of the characteristic or the size of the actual data being written? If the latter, could you help with what I'm doing wrong here.

Here are some code snippets.

Peripheral side:

registering characteristic:

  uint32_t err_code;
  ble_gatts_char_md_t char_md;
  ble_gatts_attr_t attr_char_value;
  ble_uuid_t ble_uuid;
  ble_gatts_attr_md_t attr_md;

  memset(&char_md, 0, sizeof(char_md));

  char_md.char_props.read   = 1;
  char_md.char_props.write  = 0;
  char_md.char_props.notify = 0;
  char_md.p_char_user_desc  = NULL;
  char_md.p_char_pf         = NULL;
  char_md.p_user_desc_md    = NULL;
  char_md.p_cccd_md         = NULL;
  char_md.p_sccd_md         = NULL;

  memset(&attr_md, 0, sizeof(attr_md));

  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
  BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
  attr_md.vloc    = BLE_GATTS_VLOC_STACK;
  attr_md.rd_auth = 0;
  attr_md.wr_auth = 0;
  attr_md.vlen    = 0;

  ble_uuid.type = p_bmd->uuid_type;
  ble_uuid.uuid = CUSTOM_CHAR_UUID;

  memset(&attr_char_value, 0, sizeof(attr_char_value));

  attr_char_value.p_uuid    = &ble_uuid;
  attr_char_value.p_attr_md = &attr_md;
  attr_char_value.init_offs = 0;
  attr_char_value.init_len  = sizeof(uint8_t);
  attr_char_value.max_len   = 247;

  err_code = sd_ble_gatts_characteristic_add(
      p_bmd->service_handle, &char_md, &attr_char_value, &p_bmd->char_handles);
  if (err_code != NRF_SUCCESS)
  {
    return err_code;
  }

writing to characteristic:

  if (NULL == p_bmd || NULL == data)
  {
    return NRF_ERROR_NULL;
  }

  uint32_t err_code = NRF_SUCCESS;
  ble_gatts_value_t gatts_value;

  // Initialize value struct.
  memset(&gatts_value, 0, sizeof(gatts_value));
  gatts_value.len     = data_len;
  gatts_value.offset  = 0;
  gatts_value.p_value = data;

  // Update database.
  err_code = sd_ble_gatts_value_set(
      p_bmd->conn_handle, p_bmd->char_handles.value_handle, &gatts_value);
  if (err_code != NRF_SUCCESS)
  {
    return err_code;
  }
  else
  {
    NRF_LOG_INFO("write success");
  }

Central side:

On read response:

  ble_gattc_evt_read_rsp_t const* p_response =
      &p_ble_evt->evt.gattc_evt.params.read_rsp;
  ble_bmd_c_evt_t ble_bmd_c_evt;

  // Check if the event is on the link for this instance and the event handler
  // is present.
  if ((p_bmd_c->evt_handler == NULL) ||
      (p_bmd_c->conn_handle != p_ble_evt->evt.gattc_evt.conn_handle))
  {
    return;
  }

  if (p_bmd_c->peer_db.ble_bmd_handle == p_response->handle)
  {
    memset(&ble_bmd_c_evt, 0, sizeof(ble_bmd_c_evt_t));
    ble_bmd_c_evt.conn_handle = p_ble_evt->evt.gattc_evt.conn_handle;

    if (p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_SUCCESS)
    {
      NRF_LOG_INFO("Received correct read response with len %d",
                   p_response->len);

      ble_bmd_c_evt.evt_type               = BLE_BMD_C_EVT_READ_RSP;
      ble_bmd_c_evt.params.read_rsp.p_data = (uint8_t*)p_response->data;
      ble_bmd_c_evt.params.read_rsp.len    = p_response->len;
    }
    else  // Generate error event.
    {
      ble_bmd_c_evt.evt_type = BLE_BMD_C_EVT_READ_RSP_ERROR;
      ble_bmd_c_evt.params.read_rsp_err.err_handle =
          p_ble_evt->evt.gattc_evt.error_handle;
      ble_bmd_c_evt.params.read_rsp_err.gatt_status =
          p_ble_evt->evt.gattc_evt.gatt_status;

      NRF_LOG_ERROR("Read request failed: 0x%04X.",
                    p_ble_evt->evt.gattc_evt.gatt_status);
    }
    p_bmd_c->evt_handler(p_bmd_c, &ble_bmd_c_evt);
  }

Thanks,

Vandita

Related