Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c17ff3f4 authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Jakub Pawłowski
Browse files

GATT: Read Multiple Variable Length

Add option to specify either "Read Multiple" or "Read Multiple Variable
Length" GATT read type. Also, fix up the callbacks, to ensure it's
actually passed to apps that send them.

Test: manual. Apply aosp/2780990 and connect to LE Audio capable device
Bug: 296836982
Change-Id: Ieff4996357928fdaf5326c3e449feb760e757199
parent 39d695e1
Loading
Loading
Loading
Loading
+44 −20
Original line number Diff line number Diff line
@@ -1014,7 +1014,7 @@ void bta_gattc_read_multi(tBTA_GATTC_CLCB* p_clcb,
                          const tBTA_GATTC_DATA* p_data) {
  if (bta_gattc_enqueue(p_clcb, p_data) == ENQUEUED_FOR_LATER) return;

  if (p_data->api_read_multi.num_attr > GATT_MAX_READ_MULTI_HANDLES) {
  if (p_data->api_read_multi.handles.num_attr > GATT_MAX_READ_MULTI_HANDLES) {
    LOG(ERROR) << "api_read_multi.num_attr > GATT_MAX_READ_MULTI_HANDLES";
    return;
  }
@@ -1022,13 +1022,18 @@ void bta_gattc_read_multi(tBTA_GATTC_CLCB* p_clcb,
  tGATT_READ_PARAM read_param;
  memset(&read_param, 0, sizeof(tGATT_READ_PARAM));

  read_param.read_multiple.num_handles = p_data->api_read_multi.num_attr;
  read_param.read_multiple.num_handles =
      p_data->api_read_multi.handles.num_attr;
  read_param.read_multiple.auth_req = p_data->api_read_multi.auth_req;
  memcpy(&read_param.read_multiple.handles, p_data->api_read_multi.handles,
         sizeof(uint16_t) * p_data->api_read_multi.num_attr);

  tGATT_STATUS status =
      GATTC_Read(p_clcb->bta_conn_id, GATT_READ_MULTIPLE, &read_param);
  read_param.read_multiple.variable_len = p_data->api_read_multi.variable_len;
  memcpy(&read_param.read_multiple.handles,
         p_data->api_read_multi.handles.handles,
         sizeof(uint16_t) * p_data->api_read_multi.handles.num_attr);

  tGATT_READ_TYPE read_type = (read_param.read_multiple.variable_len)
                                  ? GATT_READ_MULTIPLE_VAR_LEN
                                  : GATT_READ_MULTIPLE;
  tGATT_STATUS status = GATTC_Read(p_clcb->bta_conn_id, read_type, &read_param);
  /* read fail */
  if (status != GATT_SUCCESS) {
    /* Dequeue the data, if it was enqueued */
@@ -1110,11 +1115,14 @@ void bta_gattc_confirm(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) {
/** read complete */
static void bta_gattc_read_cmpl(tBTA_GATTC_CLCB* p_clcb,
                                const tBTA_GATTC_OP_CMPL* p_data) {
  void* my_cb_data;

  if (!p_clcb->p_q_cmd->api_read.is_multi_read) {
    GATT_READ_OP_CB cb = p_clcb->p_q_cmd->api_read.read_cb;
  void* my_cb_data = p_clcb->p_q_cmd->api_read.read_cb_data;
    my_cb_data = p_clcb->p_q_cmd->api_read.read_cb_data;

  /* if it was read by handle, return the handle requested, if read by UUID, use
   * handle returned from remote
    /* if it was read by handle, return the handle requested, if read by UUID,
     * use handle returned from remote
     */
    uint16_t handle = p_clcb->p_q_cmd->api_read.handle;
    if (handle == 0) handle = p_data->p_cmpl->att_value.handle;
@@ -1126,6 +1134,19 @@ static void bta_gattc_read_cmpl(tBTA_GATTC_CLCB* p_clcb,
         p_data->p_cmpl->att_value.len, p_data->p_cmpl->att_value.value,
         my_cb_data);
    }
  } else {
    GATT_READ_MULTI_OP_CB cb = p_clcb->p_q_cmd->api_read_multi.read_cb;
    my_cb_data = p_clcb->p_q_cmd->api_read_multi.read_cb_data;
    tBTA_GATTC_MULTI handles = p_clcb->p_q_cmd->api_read_multi.handles;

    osi_free_and_reset((void**)&p_clcb->p_q_cmd);

    if (cb) {
      cb(p_clcb->bta_conn_id, p_data->status, handles,
         p_data->p_cmpl->att_value.len, p_data->p_cmpl->att_value.value,
         my_cb_data);
    }
  }
}

/** write complete */
@@ -1223,9 +1244,12 @@ void bta_gattc_op_cmpl(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) {
  }

  if (p_clcb->p_q_cmd->hdr.event !=
      bta_gattc_opcode_to_int_evt[op - GATTC_OPTYPE_READ]) {
          bta_gattc_opcode_to_int_evt[op - GATTC_OPTYPE_READ] &&
      (p_clcb->p_q_cmd->hdr.event != BTA_GATTC_API_READ_MULTI_EVT ||
       op != GATTC_OPTYPE_READ)) {
    uint8_t mapped_op =
        p_clcb->p_q_cmd->hdr.event - BTA_GATTC_API_READ_EVT + GATTC_OPTYPE_READ;

    if (mapped_op > GATTC_OPTYPE_INDICATION) mapped_op = 0;

    LOG(ERROR) << StringPrintf(
+17 −11
Original line number Diff line number Diff line
@@ -129,8 +129,8 @@ void BTA_GATTC_AppDeregister(tGATT_IF client_if) {
 *                  transport: Transport to be used for GATT connection
 *                             (BREDR/LE)
 *                  initiating_phys: LE PHY to use, optional
 *                  opportunistic: wether the connection shall be opportunistic,
 *                                 and don't impact the disconnection timer
 *                  opportunistic: whether the connection shall be
 *                  opportunistic, and don't impact the disconnection timer
 *
 ******************************************************************************/
void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda,
@@ -398,6 +398,7 @@ void BTA_GATTC_ReadCharacteristic(uint16_t conn_id, uint16_t handle,

  p_buf->hdr.event = BTA_GATTC_API_READ_EVT;
  p_buf->hdr.layer_specific = conn_id;
  p_buf->is_multi_read = false;
  p_buf->auth_req = auth_req;
  p_buf->handle = handle;
  p_buf->read_cb = callback;
@@ -419,6 +420,7 @@ void BTA_GATTC_ReadUsingCharUuid(uint16_t conn_id, const Uuid& uuid,

  p_buf->hdr.event = BTA_GATTC_API_READ_EVT;
  p_buf->hdr.layer_specific = conn_id;
  p_buf->is_multi_read = false;
  p_buf->auth_req = auth_req;
  p_buf->handle = 0;
  p_buf->uuid = uuid;
@@ -450,6 +452,7 @@ void BTA_GATTC_ReadCharDescr(uint16_t conn_id, uint16_t handle,

  p_buf->hdr.event = BTA_GATTC_API_READ_EVT;
  p_buf->hdr.layer_specific = conn_id;
  p_buf->is_multi_read = false;
  p_buf->auth_req = auth_req;
  p_buf->handle = handle;
  p_buf->read_cb = callback;
@@ -467,24 +470,27 @@ void BTA_GATTC_ReadCharDescr(uint16_t conn_id, uint16_t handle,
 *
 * Parameters       conn_id - connectino ID.
 *                  p_read_multi - pointer to the read multiple parameter.
 *                  variable_len - whether "read multi variable length" variant
 *                                 shall be used.
 *
 *
 * Returns          None
 *
 ******************************************************************************/
void BTA_GATTC_ReadMultiple(uint16_t conn_id, tBTA_GATTC_MULTI* p_read_multi,
                            tGATT_AUTH_REQ auth_req) {
void BTA_GATTC_ReadMultiple(uint16_t conn_id, tBTA_GATTC_MULTI& handles,
                            bool variable_len, tGATT_AUTH_REQ auth_req,
                            GATT_READ_MULTI_OP_CB callback, void* cb_data) {
  tBTA_GATTC_API_READ_MULTI* p_buf =
      (tBTA_GATTC_API_READ_MULTI*)osi_calloc(sizeof(tBTA_GATTC_API_READ_MULTI));

  p_buf->hdr.event = BTA_GATTC_API_READ_MULTI_EVT;
  p_buf->hdr.layer_specific = conn_id;
  p_buf->is_multi_read = true;
  p_buf->auth_req = auth_req;
  p_buf->num_attr = p_read_multi->num_attr;

  if (p_buf->num_attr > 0)
    memcpy(p_buf->handles, p_read_multi->handles,
           sizeof(uint16_t) * p_read_multi->num_attr);

  p_buf->handles = handles;
  p_buf->variable_len = variable_len;
  p_buf->read_cb = callback;
  p_buf->read_cb_data = cb_data;
  bta_sys_sendmsg(p_buf);
}

+16 −2
Original line number Diff line number Diff line
@@ -108,6 +108,12 @@ typedef struct {

typedef struct {
  BT_HDR_RIGID hdr;

  /* it is important that is_multi_read field stays at same position between
   * tBTA_GATTC_API_READ and tBTA_GATTC_API_READ_MULTI, as it is read from
   * parent union */
  uint8_t is_multi_read;

  tGATT_AUTH_REQ auth_req;

  // read by handle data
@@ -159,9 +165,17 @@ typedef struct {

typedef struct {
  BT_HDR_RIGID hdr;

  /* it is important that is_multi_read field stays at same position between
   * tBTA_GATTC_API_READ and tBTA_GATTC_API_READ_MULTI, as it is read from
   * parent union */
  uint8_t is_multi_read;

  tGATT_AUTH_REQ auth_req;
  uint8_t num_attr;
  uint16_t handles[GATT_MAX_READ_MULTI_HANDLES];
  tBTA_GATTC_MULTI handles;
  uint8_t variable_len;
  GATT_READ_MULTI_OP_CB read_cb;
  void* read_cb_data;
} tBTA_GATTC_API_READ_MULTI;

typedef struct {
+47 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ constexpr uint8_t GATT_READ_DESC = 2;
constexpr uint8_t GATT_WRITE_CHAR = 3;
constexpr uint8_t GATT_WRITE_DESC = 4;
constexpr uint8_t GATT_CONFIG_MTU = 5;
constexpr uint8_t GATT_READ_MULTI = 6;

struct gatt_read_op_data {
  GATT_READ_OP_CB cb;
@@ -112,6 +113,31 @@ void BtaGattQueue::gatt_configure_mtu_op_finished(uint16_t conn_id,
  }
}

struct gatt_read_multi_op_data {
  GATT_READ_MULTI_OP_CB cb;
  void* cb_data;
};

void BtaGattQueue::gatt_read_multi_op_finished(uint16_t conn_id,
                                               tGATT_STATUS status,
                                               tBTA_GATTC_MULTI& handles,
                                               uint16_t len, uint8_t* value,
                                               void* data) {
  gatt_read_multi_op_data* tmp = (gatt_read_multi_op_data*)data;
  GATT_READ_MULTI_OP_CB tmp_cb = tmp->cb;
  void* tmp_cb_data = tmp->cb_data;

  osi_free(data);

  mark_as_not_executing(conn_id);
  gatt_execute_next_op(conn_id);

  if (tmp_cb) {
    tmp_cb(conn_id, status, handles, len, value, tmp_cb_data);
    return;
  }
}

void BtaGattQueue::gatt_execute_next_op(uint16_t conn_id) {
  LOG_VERBOSE("%s: conn_id=0x%x", __func__, conn_id);
  if (gatt_op_queue.empty()) {
@@ -177,6 +203,14 @@ void BtaGattQueue::gatt_execute_next_op(uint16_t conn_id) {
    BTA_GATTC_ConfigureMTU(conn_id, static_cast<uint16_t>(op.value[0] |
                                                          (op.value[1] << 8)),
                           gatt_configure_mtu_op_finished, data);
  } else if (op.type == GATT_READ_MULTI) {
    gatt_read_multi_op_data* data =
        (gatt_read_multi_op_data*)osi_malloc(sizeof(gatt_read_multi_op_data));
    data->cb = op.read_multi_cb;
    data->cb_data = op.read_cb_data;
    BTA_GATTC_ReadMultiple(conn_id, op.handles, op.variable_len,
                           GATT_AUTH_REQ_NONE, gatt_read_multi_op_finished,
                           data);
  }

  gatt_ops.pop_front();
@@ -239,3 +273,16 @@ void BtaGattQueue::ConfigureMtu(uint16_t conn_id, uint16_t mtu) {
                                    .value = std::move(value)});
  gatt_execute_next_op(conn_id);
}

void BtaGattQueue::ReadMultiCharacteristic(uint16_t conn_id,
                                           tBTA_GATTC_MULTI& handles,
                                           bool variable_len,
                                           GATT_READ_MULTI_OP_CB cb,
                                           void* cb_data) {
  gatt_op_queue[conn_id].push_back({.type = GATT_READ_MULTI,
                                    .handles = handles,
                                    .variable_len = variable_len,
                                    .read_multi_cb = cb,
                                    .read_cb_data = cb_data});
  gatt_execute_next_op(conn_id);
}
 No newline at end of file
+9 −4
Original line number Diff line number Diff line
@@ -621,7 +621,9 @@ typedef void (*GATT_WRITE_OP_CB)(uint16_t conn_id, tGATT_STATUS status,
                                 const uint8_t* value, void* data);
typedef void (*GATT_CONFIGURE_MTU_OP_CB)(uint16_t conn_id, tGATT_STATUS status,
                                         void* data);

typedef void (*GATT_READ_MULTI_OP_CB)(uint16_t conn_id, tGATT_STATUS status,
                                      tBTA_GATTC_MULTI& handles, uint16_t len,
                                      uint8_t* value, void* data);
/*******************************************************************************
 *
 * Function         BTA_GATTC_ReadCharacteristic
@@ -794,12 +796,15 @@ void BTA_GATTC_ExecuteWrite(uint16_t conn_id, bool is_execute);
 *
 * Parameters       conn_id - connectino ID.
 *                  p_read_multi - read multiple parameters.
 *                  variable_len - whether "read multi variable length" variant
 *                                 shall be used.
 *
 * Returns          None
 *
 ******************************************************************************/
void BTA_GATTC_ReadMultiple(uint16_t conn_id, tBTA_GATTC_MULTI* p_read_multi,
                            tGATT_AUTH_REQ auth_req);
void BTA_GATTC_ReadMultiple(uint16_t conn_id, tBTA_GATTC_MULTI& p_read_multi,
                            bool variable_len, tGATT_AUTH_REQ auth_req,
                            GATT_READ_MULTI_OP_CB callback, void* cb_data);

/*******************************************************************************
 *
Loading