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

Commit 9834d230 authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Gerrit Code Review
Browse files

Merge "stack/eatt: Add multi read var and multi notification handling"

parents a77647ed d7098bb8
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -189,8 +189,8 @@ BT_HDR* attp_build_read_by_type_value_cmd(uint16_t payload_size,
 * Returns          None.
 *
 ******************************************************************************/
BT_HDR* attp_build_read_multi_cmd(uint16_t payload_size, uint16_t num_handle,
                                  uint16_t* p_handle) {
BT_HDR* attp_build_read_multi_cmd(uint8_t op_code, uint16_t payload_size,
                                  uint16_t num_handle, uint16_t* p_handle) {
  uint8_t *p, i = 0;
  BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR) + num_handle * 2 + 1 +
                                      L2CAP_MIN_OFFSET);
@@ -199,7 +199,7 @@ BT_HDR* attp_build_read_multi_cmd(uint16_t payload_size, uint16_t num_handle,
  p_buf->offset = L2CAP_MIN_OFFSET;
  p_buf->len = 1;

  UINT8_TO_STREAM(p, GATT_REQ_READ_MULTI);
  UINT8_TO_STREAM(p, op_code);

  for (i = 0; i < num_handle && p_buf->len + 2 <= payload_size; i++) {
    UINT16_TO_STREAM(p, *(p_handle + i));
@@ -570,8 +570,9 @@ tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
      break;

    case GATT_REQ_READ_MULTI:
      p_cmd =
          attp_build_read_multi_cmd(payload_size, p_msg->read_multi.num_handles,
    case GATT_REQ_READ_MULTI_VAR:
      p_cmd = attp_build_read_multi_cmd(op_code, payload_size,
                                        p_msg->read_multi.num_handles,
                                        p_msg->read_multi.handles);
      break;

+5 −1
Original line number Diff line number Diff line
@@ -42,6 +42,10 @@ using bluetooth::Uuid;

#define BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK 0x01
#define BLE_GATT_CL_SUP_FEAT_EATT_BITMASK 0x02
#define BLE_GATT_CL_SUP_FEAT_MULTI_NOTIF_BITMASK 0x04

#define BLE_GATT_CL_ANDROID_SUP_FEAT \
  (BLE_GATT_CL_SUP_FEAT_EATT_BITMASK | BLE_GATT_CL_SUP_FEAT_MULTI_NOTIF_BITMASK)

using gatt_eatt_support_cb = base::OnceCallback<void(const RawAddress&, bool)>;

@@ -408,7 +412,7 @@ void gatt_profile_db_init(void) {
  gatt_cb.handle_cl_supported_feat = service[3].attribute_handle;

  gatt_cb.gatt_svr_supported_feat_mask |= BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK;
  gatt_cb.gatt_cl_supported_feat_mask |= BLE_GATT_CL_SUP_FEAT_EATT_BITMASK;
  gatt_cb.gatt_cl_supported_feat_mask |= BLE_GATT_CL_ANDROID_SUP_FEAT;

  VLOG(1) << __func__ << ": gatt_if=" << gatt_cb.gatt_if << " EATT supported";
}
+37 −14
Original line number Diff line number Diff line
@@ -625,9 +625,9 @@ void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
  tGATT_STATUS encrypt_status;
  uint8_t* p = p_data;
  uint8_t i;
  uint8_t event = (op_code == GATT_HANDLE_VALUE_NOTIF)
                      ? GATTC_OPTYPE_NOTIFICATION
                      : GATTC_OPTYPE_INDICATION;
  uint8_t event = (op_code == GATT_HANDLE_VALUE_IND)
                      ? GATTC_OPTYPE_INDICATION
                      : GATTC_OPTYPE_NOTIFICATION;

  VLOG(1) << __func__;

@@ -638,12 +638,19 @@ void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,

  memset(&value, 0, sizeof(value));
  STREAM_TO_UINT16(value.handle, p);

  if (op_code == GATT_HANDLE_MULTI_VALUE_NOTIF) {
    STREAM_TO_UINT16(value.len, p);
  } else {
    value.len = len - 2;
  }

  if (value.len > GATT_MAX_ATTR_LEN) {
    LOG(ERROR) << "value.len larger than GATT_MAX_ATTR_LEN, discard";
    return;
  }
  memcpy(value.value, p, value.len);

  STREAM_TO_ARRAY(value.value, p, value.len);

  if (!GATT_HANDLE_IS_VALID(value.handle)) {
    /* illegal handle, send ack now */
@@ -686,6 +693,9 @@ void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
  }

  encrypt_status = gatt_get_link_encrypt_status(tcb);

  uint16_t rem_len = len;
  while (rem_len) {
    tGATT_CL_COMPLETE gatt_cl_complete;
    gatt_cl_complete.att_value = value;
    gatt_cl_complete.cid = cid;
@@ -697,6 +707,17 @@ void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
                                   &gatt_cl_complete);
      }
    }

    if (op_code != GATT_HANDLE_MULTI_VALUE_NOTIF) return;

    /* 4 stands for 2 octects for handle and 2 octecs for len */
    rem_len -= (4 + value.len);
    if (rem_len) {
      STREAM_TO_UINT16(value.handle, p);
      STREAM_TO_UINT16(value.len, p);
      STREAM_TO_ARRAY(value.value, p, value.len);
    }
  }
}

/*******************************************************************************
@@ -1112,7 +1133,8 @@ void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint16_t cid,

  uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, cid);

  if (op_code == GATT_HANDLE_VALUE_IND || op_code == GATT_HANDLE_VALUE_NOTIF) {
  if (op_code == GATT_HANDLE_VALUE_IND || op_code == GATT_HANDLE_VALUE_NOTIF ||
      op_code == GATT_HANDLE_MULTI_VALUE_NOTIF) {
    if (len >= payload_size) {
      LOG(ERROR) << StringPrintf(
          "%s: invalid indicate pkt size: %d, PDU size: %d", __func__, len + 1,
@@ -1173,6 +1195,7 @@ void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint16_t cid,
      case GATT_RSP_READ:
      case GATT_RSP_READ_BLOB:
      case GATT_RSP_READ_MULTI:
      case GATT_RSP_READ_MULTI_VAR:
        gatt_process_read_rsp(tcb, p_clcb, op_code, len, p_data);
        break;

+93 −76
Original line number Diff line number Diff line
@@ -134,48 +134,26 @@ void gatt_dequeue_sr_cmd(tGATT_TCB& tcb, uint16_t cid) {
  fixed_queue_free(p_cmd->multi_rsp_q, NULL);
  memset(p_cmd, 0, sizeof(tGATT_SR_CMD));
}
/*******************************************************************************
 *
 * Function         process_read_multi_rsp
 *
 * Description      This function check the read multiple response.
 *
 * Returns          bool    if all replies have been received
 *
 ******************************************************************************/
static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status,
                                   tGATTS_RSP* p_msg, uint16_t mtu) {

static void build_read_multi_rsp(tGATT_SR_CMD* p_cmd, uint16_t mtu) {
  uint16_t ii, total_len, len;
  uint8_t* p;
  bool is_overflow = false;

  VLOG(1) << StringPrintf("%s status=%d mtu=%d", __func__, status, mtu);

  if (p_cmd->multi_rsp_q == NULL)
    p_cmd->multi_rsp_q = fixed_queue_new(SIZE_MAX);

  /* Enqueue the response */
  BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(tGATTS_RSP));
  memcpy((void*)p_buf, (const void*)p_msg, sizeof(tGATTS_RSP));
  fixed_queue_enqueue(p_cmd->multi_rsp_q, p_buf);

  p_cmd->status = status;
  if (status == GATT_SUCCESS) {
    VLOG(1) << "Multi read count=" << fixed_queue_length(p_cmd->multi_rsp_q)
            << " num_hdls=" << p_cmd->multi_req.num_handles;
    /* Wait till we get all the responses */
    if (fixed_queue_length(p_cmd->multi_rsp_q) ==
        p_cmd->multi_req.num_handles) {
  len = sizeof(BT_HDR) + L2CAP_MIN_OFFSET + mtu;
      p_buf = (BT_HDR*)osi_calloc(len);
  BT_HDR* p_buf = (BT_HDR*)osi_calloc(len);
  p_buf->offset = L2CAP_MIN_OFFSET;
  p = (uint8_t*)(p_buf + 1) + p_buf->offset;

  /* First byte in the response is the opcode */
  if (p_cmd->multi_req.variable_len)
    *p++ = GATT_RSP_READ_MULTI_VAR;
  else
    *p++ = GATT_RSP_READ_MULTI;

  p_buf->len = 1;

      /* Now walk through the buffers puting the data into the response in order
  /* Now walk through the buffers putting the data into the response in order
   */
  list_t* list = NULL;
  const list_node_t* node = NULL;
@@ -206,6 +184,11 @@ static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status,
        len = p_rsp->attr_value.len;
      }

      if (p_cmd->multi_req.variable_len) {
        UINT16_TO_STREAM(p, len);
        p_buf->len += 2;
      }

      if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii]) {
        memcpy(p, p_rsp->attr_value.value, len);
        if (!is_overflow) p += len;
@@ -235,7 +218,38 @@ static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status,
  } else {
    p_cmd->p_rsp_msg = p_buf;
  }
}

/*******************************************************************************
 *
 * Function         process_read_multi_rsp
 *
 * Description      This function check the read multiple response.
 *
 * Returns          bool    if all replies have been received
 *
 ******************************************************************************/
static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status,
                                   tGATTS_RSP* p_msg, uint16_t mtu) {
  VLOG(1) << StringPrintf("%s status=%d mtu=%d", __func__, status, mtu);

  if (p_cmd->multi_rsp_q == NULL)
    p_cmd->multi_rsp_q = fixed_queue_new(SIZE_MAX);

  /* Enqueue the response */
  BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(tGATTS_RSP));
  memcpy((void*)p_buf, (const void*)p_msg, sizeof(tGATTS_RSP));
  fixed_queue_enqueue(p_cmd->multi_rsp_q, p_buf);

  p_cmd->status = status;
  if (status == GATT_SUCCESS) {
    VLOG(1) << "Multi read count=" << fixed_queue_length(p_cmd->multi_rsp_q)
            << " num_hdls=" << p_cmd->multi_req.num_handles
            << " variable=" << p_cmd->multi_req.variable_len;
    /* Wait till we get all the responses */
    if (fixed_queue_length(p_cmd->multi_rsp_q) ==
        p_cmd->multi_req.num_handles) {
      build_read_multi_rsp(p_cmd, mtu);
      return (true);
    }
  } else /* any handle read exception occurs, return error */
@@ -269,7 +283,8 @@ tGATT_STATUS gatt_sr_process_app_rsp(tGATT_TCB& tcb, tGATT_IF gatt_if,

  gatt_sr_update_cback_cnt(tcb, sr_res_p->cid, gatt_if, false, false);

  if (op_code == GATT_REQ_READ_MULTI) {
  if ((op_code == GATT_REQ_READ_MULTI) ||
      (op_code == GATT_REQ_READ_MULTI_VAR)) {
    /* If no error and still waiting, just return */
    if (!process_read_multi_rsp(sr_res_p, status, p_msg, payload_size))
      return (GATT_SUCCESS);
@@ -396,6 +411,7 @@ void gatt_process_read_multi_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,

  tGATT_READ_MULTI* multi_req = gatt_sr_get_read_multi(tcb, cid);
  multi_req->num_handles = 0;
  multi_req->variable_len = (op_code == GATT_REQ_READ_MULTI_VAR);
  gatt_sr_get_sec_info(tcb.peer_bda, tcb.transport, &sec_flag, &key_size);

#if (GATT_CONFORMANCE_TESTING == TRUE)
@@ -1292,6 +1308,7 @@ void gatt_server_handle_client_req(tGATT_TCB& tcb, uint16_t cid,
        break;

      case GATT_REQ_READ_MULTI:
      case GATT_REQ_READ_MULTI_VAR:
        gatt_process_read_multi_req(tcb, cid, op_code, len, p_data);
        break;

+13 −1
Original line number Diff line number Diff line
@@ -109,10 +109,15 @@ typedef enum : uint8_t {
  GATT_HANDLE_VALUE_NOTIF = 0x1B,
  GATT_HANDLE_VALUE_IND = 0x1D,
  GATT_HANDLE_VALUE_CONF = 0x1E,

  GATT_REQ_READ_MULTI_VAR = 0x20,
  GATT_RSP_READ_MULTI_VAR = 0x21,
  GATT_HANDLE_MULTI_VALUE_NOTIF = 0x23,

  /* changed in V4.0 1101-0010 (signed write)  see write cmd above*/
  GATT_SIGN_CMD_WRITE = 0xD2,
  /* 0x1E = 30 + 1 = 31*/
  GATT_OP_CODE_MAX = (GATT_HANDLE_VALUE_CONF + 1),
  GATT_OP_CODE_MAX = (GATT_HANDLE_MULTI_VALUE_NOTIF + 1),
} tGATT_OP_CODE;

inline std::string gatt_op_code_text(const tGATT_OP_CODE& op_code) {
@@ -171,6 +176,12 @@ inline std::string gatt_op_code_text(const tGATT_OP_CODE& op_code) {
      return std::string("GATT_HANDLE_VALUE_IND");
    case GATT_HANDLE_VALUE_CONF:
      return std::string("GATT_HANDLE_VALUE_CONF");
    case GATT_REQ_READ_MULTI_VAR:
      return std::string("GATT_REQ_READ_MULTI_VAR");
    case GATT_RSP_READ_MULTI_VAR:
      return std::string("GATT_RSP_READ_MULTI_VAR");
    case GATT_HANDLE_MULTI_VALUE_NOTIF:
      return std::string("GATT_HANDLE_MULTI_VALUE_NOTIF");
    case GATT_SIGN_CMD_WRITE:
      return std::string("GATT_SIGN_CMD_WRITE");
    case GATT_OP_CODE_MAX:
@@ -499,6 +510,7 @@ typedef struct {
  tGATT_AUTH_REQ auth_req;
  uint16_t num_handles;                          /* number of handles to read */
  uint16_t handles[GATT_MAX_READ_MULTI_HANDLES]; /* handles list to be read */
  bool variable_len;
} tGATT_READ_MULTI;

/*   Read By Handle Request (GATT_READ_BY_HANDLE) data */