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

Commit bde1dad7 authored by Himanshu Rawat's avatar Himanshu Rawat
Browse files

Early reservation of HID control block

BTA HID host marks the device control block in-use after the connection
is opened. If another connection request is received when a previous
connection is pending, BTA HID host may end up using the same control
block for it.
Device control block should be reserved when
1. Device is added on stack initialization
2. Connection initiated locally
3. Connection initiated by the remote device

Control block finder utilities should be separate from the utility which
finds or allocates the control block.

Test: mmm packages/modules/Bluetooth
Test: Manual | Change preferred HID transport on pairing with earbuds
supporting both DSA 1.0 and DSA 2.0
Flag: EXEMPT bugfix
Bug: 347241319

Change-Id: Id4072f7ba86dd2f26fe22dab0d2080e8a478fea9
parent 1cc4b175
Loading
Loading
Loading
Loading
+11 −22
Original line number Diff line number Diff line
@@ -288,8 +288,7 @@ static void bta_hh_di_sdp_cback(const RawAddress& /* bd_addr */, tSDP_RESULT res
                              0);
      }

    } else /* no DI record available */
    {
    } else /* no DI record available */ {
      bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0, 0);
    }

@@ -324,14 +323,14 @@ static void bta_hh_di_sdp_cback(const RawAddress& /* bd_addr */, tSDP_RESULT res
 * Returns          void
 *
 ******************************************************************************/
static void bta_hh_start_sdp(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
static void bta_hh_start_sdp(tBTA_HH_DEV_CB* p_cb) {
  if (!bta_hh_cb.p_disc_db) {
    bta_hh_cb.p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(p_bta_hh_cfg->sdp_db_size);

    /* Do DI discovery first */
    if (get_legacy_stack_sdp_api()->device_id.SDP_DiDiscover(
                p_data->api_conn.link_spec.addrt.bda, bta_hh_cb.p_disc_db,
                p_bta_hh_cfg->sdp_db_size, bta_hh_di_sdp_cback) == SDP_SUCCESS) {
                p_cb->link_spec.addrt.bda, bta_hh_cb.p_disc_db, p_bta_hh_cfg->sdp_db_size,
                bta_hh_di_sdp_cback) == SDP_SUCCESS) {
      /* SDP search started successfully
       * Connection will be triggered at the end of successful SDP search
       */
@@ -447,12 +446,10 @@ void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
 * Returns          void
 *
 ******************************************************************************/
static void bta_hh_bredr_conn(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
  bta_hh_cb.p_cur = p_cb;

static void bta_hh_bredr_conn(tBTA_HH_DEV_CB* p_cb) {
  /* If previously virtually cabled device */
  if (p_cb->app_id) {
    tBTA_HH_DATA bta_hh_data;
    tBTA_HH_DATA bta_hh_data = {};
    bta_hh_data.status = BTA_HH_OK;

    log::verbose("skip SDP for known devices");
@@ -461,7 +458,7 @@ static void bta_hh_bredr_conn(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data)
      uint8_t hdl;
      if (HID_HostAddDev(p_cb->link_spec.addrt.bda, p_cb->attr_mask, &hdl) == HID_SUCCESS) {
        /* update device CB with newly register device handle */
        bta_hh_add_device_to_list(p_cb, hdl, p_cb->attr_mask, NULL, p_cb->sub_class,
        bta_hh_add_device_to_list(p_cb, hdl, p_cb->attr_mask, nullptr, p_cb->sub_class,
                                  p_cb->dscp_info.ssr_max_latency, p_cb->dscp_info.ssr_min_tout,
                                  p_cb->app_id);
        /* update cb_index[] map */
@@ -473,7 +470,7 @@ static void bta_hh_bredr_conn(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data)

    bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &bta_hh_data);
  } else { /* First time connection, start SDP */
    bta_hh_start_sdp(p_cb, p_data);
    bta_hh_start_sdp(p_cb);
  }
}

@@ -487,15 +484,14 @@ static void bta_hh_bredr_conn(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data)
 *
 ******************************************************************************/
void bta_hh_connect(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
  p_cb->link_spec = p_data->api_conn.link_spec;
  p_cb->mode = p_data->api_conn.mode;
  bta_hh_cb.p_cur = p_cb;

  // Initiate HID host connection
  if (p_cb->link_spec.transport == BT_TRANSPORT_LE) {
    bta_hh_le_open_conn(p_cb, p_data->api_conn.link_spec);
    bta_hh_le_open_conn(p_cb);
  } else {
    bta_hh_bredr_conn(p_cb, p_data);
    bta_hh_bredr_conn(p_cb);
  }
}

@@ -601,8 +597,6 @@ void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
 *
 ******************************************************************************/
void bta_hh_open_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
  tBTA_HH_API_CONN conn_data;

  uint8_t dev_handle = p_data ? (uint8_t)p_data->hid_cback.hdr.layer_specific : p_cb->hid_handle;

  log::verbose("Device[{}] connected", dev_handle);
@@ -619,13 +613,8 @@ void bta_hh_open_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
    /* store the handle here in case sdp fails - need to disconnect */
    p_cb->incoming_hid_handle = dev_handle;

    memset(&conn_data, 0, sizeof(tBTA_HH_API_CONN));
    conn_data.link_spec = p_cb->link_spec;
    bta_hh_cb.p_cur = p_cb;
    bta_hh_bredr_conn(p_cb, (tBTA_HH_DATA*)&conn_data);
    bta_hh_bredr_conn(p_cb);
  }

  return;
}

/*******************************************************************************
+4 −5
Original line number Diff line number Diff line
@@ -252,7 +252,7 @@ extern tBTA_HH_CFG* p_bta_hh_cfg;
 *  Function prototypes
 ****************************************************************************/
bool bta_hh_hdl_event(const BT_HDR_RIGID* p_msg);
void bta_hh_sm_execute(tBTA_HH_DEV_CB* p_cb, uint16_t event, const tBTA_HH_DATA* p_data);
void bta_hh_sm_execute(tBTA_HH_DEV_CB* p_cb, tBTA_HH_INT_EVT event, const tBTA_HH_DATA* p_data);

/* action functions */
void bta_hh_api_disc_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data);
@@ -270,8 +270,9 @@ void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data);
void bta_hh_open_failure(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data);

/* utility functions */
uint8_t bta_hh_find_cb(const tAclLinkSpec& link_spec);
tBTA_HH_DEV_CB* bta_hh_find_cb(const tAclLinkSpec& link_spec);
tBTA_HH_DEV_CB* bta_hh_get_cb(const tAclLinkSpec& link_spec);
tBTA_HH_DEV_CB* bta_hh_find_cb_by_handle(uint8_t hid_handle);
bool bta_hh_tod_spt(tBTA_HH_DEV_CB* p_cb, uint8_t sub_class);
void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB* p_cb);

@@ -282,8 +283,6 @@ void bta_hh_update_di_info(tBTA_HH_DEV_CB* p_cb, uint16_t vendor_id, uint16_t pr
                           uint16_t version, uint8_t flag, uint8_t ctry_code);
void bta_hh_cleanup_disable(tBTA_HH_STATUS status);

uint8_t bta_hh_dev_handle_to_cb_idx(uint8_t dev_handle);

/* action functions used outside state machine */
void bta_hh_api_enable(tBTA_HH_CBACK* p_cback, bool enable_hid, bool enable_hogp);
void bta_hh_api_disable(void);
@@ -295,7 +294,7 @@ tBTA_HH_STATUS bta_hh_read_ssr_param(const tAclLinkSpec& link_spec, uint16_t* p_
/* functions for LE HID */
void bta_hh_le_enable(void);
void bta_hh_le_deregister(void);
void bta_hh_le_open_conn(tBTA_HH_DEV_CB* p_cb, const tAclLinkSpec& link_spec);
void bta_hh_le_open_conn(tBTA_HH_DEV_CB* p_cb);
void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB* p_cb);
void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB* p_cb);
void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data);
+18 −29
Original line number Diff line number Diff line
@@ -241,19 +241,16 @@ void bta_hh_le_deregister(void) { BTA_GATTC_AppDeregister(bta_hh_cb.gatt_if); }
 *
 ******************************************************************************/
static uint8_t bta_hh_le_get_le_dev_hdl(uint8_t cb_index) {
  uint8_t i;
  for (i = 0; i < ARRAY_SIZE(bta_hh_cb.le_cb_index); i++) {
  uint8_t available_handle = BTA_HH_IDX_INVALID;
  for (uint8_t i = 0; i < ARRAY_SIZE(bta_hh_cb.le_cb_index); i++) {
    if (bta_hh_cb.le_cb_index[i] == cb_index) {
      return BTA_HH_GET_LE_DEV_HDL(i);
    } else if (available_handle == BTA_HH_IDX_INVALID &&
               bta_hh_cb.le_cb_index[i] == BTA_HH_IDX_INVALID) {
      available_handle = BTA_HH_GET_LE_DEV_HDL(i);
    }
  }

  for (i = 0; i < ARRAY_SIZE(bta_hh_cb.le_cb_index); i++) {
    if (bta_hh_cb.le_cb_index[i] == BTA_HH_IDX_INVALID) {
      return BTA_HH_GET_LE_DEV_HDL(i);
    }
  }
  return BTA_HH_IDX_INVALID;
  return available_handle;
}

/*******************************************************************************
@@ -265,21 +262,17 @@ static uint8_t bta_hh_le_get_le_dev_hdl(uint8_t cb_index) {
 * Parameters:
 *
 ******************************************************************************/
void bta_hh_le_open_conn(tBTA_HH_DEV_CB* p_cb, const tAclLinkSpec& link_spec) {
  tBTA_HH_STATUS status = BTA_HH_ERR_NO_RES;

  /* update cb_index[] map */
void bta_hh_le_open_conn(tBTA_HH_DEV_CB* p_cb) {
  p_cb->hid_handle = bta_hh_le_get_le_dev_hdl(p_cb->index);
  if (p_cb->hid_handle == BTA_HH_IDX_INVALID) {
    tBTA_HH_STATUS status = BTA_HH_ERR_NO_RES;
    bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
    return;
  }

  p_cb->link_spec = link_spec;
  bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
  p_cb->in_use = true;
  bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;  // Update index map

  BTA_GATTC_Open(bta_hh_cb.gatt_if, link_spec.addrt.bda, BTM_BLE_DIRECT_CONNECTION, false);
  BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->link_spec.addrt.bda, BTM_BLE_DIRECT_CONNECTION, false);
}

/*******************************************************************************
@@ -291,15 +284,13 @@ void bta_hh_le_open_conn(tBTA_HH_DEV_CB* p_cb, const tAclLinkSpec& link_spec) {
 *
 ******************************************************************************/
static tBTA_HH_DEV_CB* bta_hh_le_find_dev_cb_by_conn_id(uint16_t conn_id) {
  uint8_t i;
  tBTA_HH_DEV_CB* p_dev_cb = &bta_hh_cb.kdev[0];

  for (i = 0; i < BTA_HH_MAX_DEVICE; i++, p_dev_cb++) {
  for (uint8_t i = 0; i < BTA_HH_MAX_DEVICE; i++) {
    tBTA_HH_DEV_CB* p_dev_cb = &bta_hh_cb.kdev[i];
    if (p_dev_cb->in_use && p_dev_cb->conn_id == conn_id) {
      return p_dev_cb;
    }
  }
  return NULL;
  return nullptr;
}

/*******************************************************************************
@@ -311,16 +302,14 @@ static tBTA_HH_DEV_CB* bta_hh_le_find_dev_cb_by_conn_id(uint16_t conn_id) {
 *
 ******************************************************************************/
static tBTA_HH_DEV_CB* bta_hh_le_find_dev_cb_by_bda(const tAclLinkSpec& link_spec) {
  uint8_t i;
  tBTA_HH_DEV_CB* p_dev_cb = &bta_hh_cb.kdev[0];

  for (i = 0; i < BTA_HH_MAX_DEVICE; i++, p_dev_cb++) {
  for (uint8_t i = 0; i < BTA_HH_MAX_DEVICE; i++) {
    tBTA_HH_DEV_CB* p_dev_cb = &bta_hh_cb.kdev[i];
    if (p_dev_cb->in_use && p_dev_cb->link_spec.addrt.bda == link_spec.addrt.bda &&
        p_dev_cb->link_spec.transport == BT_TRANSPORT_LE) {
      return p_dev_cb;
    }
  }
  return NULL;
  return nullptr;
}

/*******************************************************************************
@@ -968,9 +957,9 @@ static void bta_hh_le_encrypt_cback(RawAddress bd_addr, tBT_TRANSPORT transport,
          .transport = transport,
  };

  tBTA_HH_DEV_CB* p_dev_cb = bta_hh_get_cb(link_spec);
  tBTA_HH_DEV_CB* p_dev_cb = bta_hh_find_cb(link_spec);
  if (p_dev_cb == nullptr) {
    log::error("unexpected encryption callback, ignore");
    log::error("Unexpected encryption callback for {}", bd_addr);
    return;
  }

+217 −212
Original line number Diff line number Diff line
@@ -44,14 +44,132 @@ tBTA_HH_CB bta_hh_cb;
/*****************************************************************************
 * Static functions
 ****************************************************************************/
static const char* bta_hh_evt_code(tBTA_HH_INT_EVT evt_code);
static const char* bta_hh_state_code(tBTA_HH_STATE state_code);
/*******************************************************************************
 *
 * Function         bta_hh_evt_code
 *
 * Description
 *
 * Returns          void
 *
 ******************************************************************************/
static const char* bta_hh_evt_code(tBTA_HH_INT_EVT evt_code) {
  switch (evt_code) {
    case BTA_HH_API_OPEN_EVT:
      return "BTA_HH_API_OPEN_EVT";
    case BTA_HH_API_CLOSE_EVT:
      return "BTA_HH_API_CLOSE_EVT";
    case BTA_HH_INT_OPEN_EVT:
      return "BTA_HH_INT_OPEN_EVT";
    case BTA_HH_INT_CLOSE_EVT:
      return "BTA_HH_INT_CLOSE_EVT";
    case BTA_HH_INT_HANDSK_EVT:
      return "BTA_HH_INT_HANDSK_EVT";
    case BTA_HH_INT_DATA_EVT:
      return "BTA_HH_INT_DATA_EVT";
    case BTA_HH_INT_CTRL_DATA:
      return "BTA_HH_INT_CTRL_DATA";
    case BTA_HH_API_WRITE_DEV_EVT:
      return "BTA_HH_API_WRITE_DEV_EVT";
    case BTA_HH_SDP_CMPL_EVT:
      return "BTA_HH_SDP_CMPL_EVT";
    case BTA_HH_API_MAINT_DEV_EVT:
      return "BTA_HH_API_MAINT_DEV_EVT";
    case BTA_HH_API_GET_DSCP_EVT:
      return "BTA_HH_API_GET_DSCP_EVT";
    case BTA_HH_OPEN_CMPL_EVT:
      return "BTA_HH_OPEN_CMPL_EVT";
    case BTA_HH_GATT_CLOSE_EVT:
      return "BTA_HH_GATT_CLOSE_EVT";
    case BTA_HH_GATT_OPEN_EVT:
      return "BTA_HH_GATT_OPEN_EVT";
    case BTA_HH_START_ENC_EVT:
      return "BTA_HH_START_ENC_EVT";
    case BTA_HH_ENC_CMPL_EVT:
      return "BTA_HH_ENC_CMPL_EVT";
    default:
      return "unknown HID Host event code";
  }
}

static void bta_hh_better_state_machine(tBTA_HH_DEV_CB* p_cb, uint16_t event,
                                        const tBTA_HH_DATA* p_data) {
  log::verbose("state:{}, event:{}", bta_hh_state_code(p_cb->state),
               bta_hh_evt_code(static_cast<tBTA_HH_INT_EVT>(event)));
  switch (p_cb->state) {
/*******************************************************************************
 *
 * Function         bta_hh_state_code
 *
 * Description      get string representation of HID host state code.
 *
 * Returns          void
 *
 ******************************************************************************/
static const char* bta_hh_state_code(tBTA_HH_STATE state_code) {
  switch (state_code) {
    case BTA_HH_NULL_ST:
      return "BTA_HH_NULL_ST";
    case BTA_HH_IDLE_ST:
      return "BTA_HH_IDLE_ST";
    case BTA_HH_W4_CONN_ST:
      return "BTA_HH_W4_CONN_ST";
    case BTA_HH_CONN_ST:
      return "BTA_HH_CONN_ST";
    case BTA_HH_W4_SEC:
      return "BTA_HH_W4_SEC";
    default:
      return "unknown HID Host state";
  }
}

/* Finds the related control block, if any */
static tBTA_HH_DEV_CB* bta_hh_find_cb_by_event(const BT_HDR_RIGID* p_msg) {
  tBTA_HH_DEV_CB* p_cb = nullptr;

  if (p_msg->event == BTA_HH_API_OPEN_EVT) {
    // Connection requested, find or allocate the control block
    p_cb = bta_hh_get_cb(((tBTA_HH_API_CONN*)p_msg)->link_spec);
  } else if (p_msg->event == BTA_HH_API_MAINT_DEV_EVT) {
    if (((tBTA_HH_MAINT_DEV*)p_msg)->sub_event == BTA_HH_ADD_DEV_EVT) {
      // Device is being added, find or allocate the control block
      p_cb = bta_hh_get_cb(((tBTA_HH_MAINT_DEV*)p_msg)->link_spec);
    } else /* else remove device by handle */ {
      p_cb = bta_hh_find_cb_by_handle((uint8_t)p_msg->layer_specific);
      /* If BT disable is done while the HID device is connected and
       * Link_Key uses unauthenticated combination
       * then we can get into a situation where remove_bonding is called
       * with the index set to 0 (without getting
       * cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the
       * index and make it MAX_KNOWN.
       * So if REMOVE_DEVICE is called and in_use is false then we should
       * treat this as a NULL p_cb. Hence we
       * force the index to be IDX_INVALID
       */
      if (p_cb != nullptr && !p_cb->in_use) {
        log::warn("Control block getting removed, device: {}, index: {}, handle: {}",
                  p_cb->link_spec, p_cb->index, p_cb->hid_handle);
        p_cb = nullptr;
      }
    }
  } else if (p_msg->event == BTA_HH_INT_OPEN_EVT) {
    p_cb = bta_hh_get_cb(((tBTA_HH_CBACK_DATA*)p_msg)->link_spec);
  } else {
    p_cb = bta_hh_find_cb_by_handle((uint8_t)p_msg->layer_specific);
  }

  return p_cb;
}

/* Handles events related to connection control blocks */
void bta_hh_sm_execute(tBTA_HH_DEV_CB* p_cb, tBTA_HH_INT_EVT event, const tBTA_HH_DATA* p_data) {
  tBTA_HH_STATE in_state = p_cb->state;
  if (p_cb->state == BTA_HH_NULL_ST || p_cb->state >= BTA_HH_INVALID_ST) {
    log::error("Invalid state State:{}, Event:{} for {}", bta_hh_state_code(in_state),
               bta_hh_evt_code(event), p_cb->link_spec);
    return;
  }

  bool unexpected_event = false;
  log::verbose("State {}, Event {} for {}", bta_hh_state_code(in_state), bta_hh_evt_code(event),
               p_cb->link_spec);

  switch (in_state) {
    case BTA_HH_IDLE_ST:
      switch (event) {
        case BTA_HH_API_OPEN_EVT:
@@ -76,6 +194,9 @@ static void bta_hh_better_state_machine(tBTA_HH_DEV_CB* p_cb, uint16_t event,
          p_cb->state = BTA_HH_W4_CONN_ST;
          bta_hh_gatt_open(p_cb, p_data);
          break;
        default:
          unexpected_event = true;
          break;
      }
      break;
    case BTA_HH_W4_CONN_ST:
@@ -115,6 +236,9 @@ static void bta_hh_better_state_machine(tBTA_HH_DEV_CB* p_cb, uint16_t event,
          p_cb->state = BTA_HH_W4_SEC;
          bta_hh_start_security(p_cb, p_data);
          break;
        default:
          unexpected_event = true;
          break;
      }
      break;
    case BTA_HH_CONN_ST:
@@ -151,6 +275,9 @@ static void bta_hh_better_state_machine(tBTA_HH_DEV_CB* p_cb, uint16_t event,
          p_cb->state = BTA_HH_IDLE_ST;
          bta_hh_gatt_close(p_cb, p_data);
          break;
        default:
          unexpected_event = true;
          break;
      }
      break;
    case BTA_HH_W4_SEC:
@@ -176,35 +303,40 @@ static void bta_hh_better_state_machine(tBTA_HH_DEV_CB* p_cb, uint16_t event,
        case BTA_HH_GATT_ENC_CMPL_EVT:
          bta_hh_le_notify_enc_cmpl(p_cb, p_data);
          break;
        default:
          unexpected_event = true;
          break;
      }
      break;
  }

  if (unexpected_event) {
    log::warn("Unexpected event event {} in state {} for {}", bta_hh_evt_code(event),
              bta_hh_state_code(in_state), p_cb->link_spec);
  } else if (in_state != p_cb->state) {
    log::debug("State Change: [{}] -> [{}] after Event [{}]", bta_hh_state_code(in_state),
               bta_hh_state_code(p_cb->state), bta_hh_evt_code(event));
  }
}

/*******************************************************************************
 *
 * Function         bta_hh_sm_execute
 *
 * Description      State machine event handling function for HID Host
 * Function         bta_hh_hdl_failure
 *
 * Description      Handler for state machine failures
 *
 * Returns          void
 *
 ******************************************************************************/
void bta_hh_sm_execute(tBTA_HH_DEV_CB* p_cb, uint16_t event, const tBTA_HH_DATA* p_data) {
  tBTA_HH cback_data;
  tBTA_HH_EVT cback_event = 0;
  tBTA_HH_STATE in_state;
  tBTA_HH_INT_EVT debug_event = static_cast<tBTA_HH_INT_EVT>(event);

  memset(&cback_data, 0, sizeof(tBTA_HH));
void bta_hh_hdl_failure(tBTA_HH_INT_EVT event, const tBTA_HH_DATA* p_data) {
  if (bta_hh_cb.p_cback == nullptr) {
    log::error("No callback handler");
    return;
  }

  /* handle exception, no valid control block was found */
  if (!p_cb) {
    log::verbose("Event:{}, bta_hh_cb.p_cback:{}", bta_hh_evt_code(debug_event),
                 fmt::ptr(bta_hh_cb.p_cback));
    /* BTA HH enabled already? otherwise ignore the event although it's bad*/
    if (bta_hh_cb.p_cback != NULL) {
  log::verbose("Event:{}", bta_hh_evt_code(event));
  tBTA_HH cback_data = {};
  tBTA_HH_EVT cback_event = BTA_HH_EMPTY_EVT;
  switch (event) {
    /* no control block available for new connection */
    case BTA_HH_API_OPEN_EVT:
@@ -251,44 +383,25 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB* p_cb, uint16_t event, const tBTA_HH_DATA*

    case BTA_HH_API_CLOSE_EVT:
      cback_event = BTA_HH_CLOSE_EVT;

      cback_data.dev_status.status = BTA_HH_ERR_HDL;
      cback_data.dev_status.handle = (uint8_t)p_data->api_sndcmd.hdr.layer_specific;
      break;

    default:
          /* invalid handle, call bad API event */
          log::error("wrong device handle:{}", p_data->hdr.layer_specific);
      /* Likely an invalid handle, call bad API event */
      log::error("wrong device handle:{} in event:{}", p_data->hdr.layer_specific,
                 bta_hh_evt_code(event));
      /* Free the callback buffer now */
          if (p_data != NULL) {
      if (p_data != nullptr) {
        osi_free_and_reset((void**)&p_data->hid_cback.p_data);
      }
      break;
  }

  if (cback_event) {
    (*bta_hh_cb.p_cback)(cback_event, &cback_data);
  }
}
  }
  /* corresponding CB is found, go to state machine */
  else {
    in_state = p_cb->state;
    log::verbose("State 0x{:02x} [{}], Event [{}]", in_state, bta_hh_state_code(in_state),
                 bta_hh_evt_code(debug_event));

    if ((p_cb->state == BTA_HH_NULL_ST) || (p_cb->state >= BTA_HH_INVALID_ST)) {
      log::error("Invalid state State=0x{:x}, Event={}", p_cb->state, event);
      return;
    }

    bta_hh_better_state_machine(p_cb, event, p_data);

    if (in_state != p_cb->state) {
      log::debug("HHID State Change: [{}] -> [{}] after Event [{}]", bta_hh_state_code(in_state),
                 bta_hh_state_code(p_cb->state), bta_hh_evt_code(debug_event));
    }
  }
}

/*******************************************************************************
 *
@@ -301,122 +414,14 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB* p_cb, uint16_t event, const tBTA_HH_DATA*
 *
 ******************************************************************************/
bool bta_hh_hdl_event(const BT_HDR_RIGID* p_msg) {
  uint8_t index = BTA_HH_IDX_INVALID;
  tBTA_HH_DEV_CB* p_cb = NULL;
  tBTA_HH_DEV_CB* p_cb = bta_hh_find_cb_by_event(p_msg);
  tBTA_HH_INT_EVT event = static_cast<tBTA_HH_INT_EVT>(p_msg->event);

  /* all events processed in state machine need to find corresponding
     CB before proceed */
  if (p_msg->event == BTA_HH_API_OPEN_EVT) {
    index = bta_hh_find_cb(((tBTA_HH_API_CONN*)p_msg)->link_spec);
  } else if (p_msg->event == BTA_HH_API_MAINT_DEV_EVT) {
    /* if add device */
    if (((tBTA_HH_MAINT_DEV*)p_msg)->sub_event == BTA_HH_ADD_DEV_EVT) {
      index = bta_hh_find_cb(((tBTA_HH_MAINT_DEV*)p_msg)->link_spec);
    } else /* else remove device by handle */ {
      index = bta_hh_dev_handle_to_cb_idx((uint8_t)p_msg->layer_specific);
      /* If BT disable is done while the HID device is connected and
       * Link_Key uses unauthenticated combination
       * then we can get into a situation where remove_bonding is called
       * with the index set to 0 (without getting
       * cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the
       * index and make it MAX_KNOWN.
       * So if REMOVE_DEVICE is called and in_use is false then we should
       * treat this as a NULL p_cb. Hence we
       * force the index to be IDX_INVALID
       */
      if ((index != BTA_HH_IDX_INVALID) && (!bta_hh_cb.kdev[index].in_use)) {
        index = BTA_HH_IDX_INVALID;
      }
    }
  } else if (p_msg->event == BTA_HH_INT_OPEN_EVT) {
    index = bta_hh_find_cb(((tBTA_HH_CBACK_DATA*)p_msg)->link_spec);
  if (p_cb != nullptr) {
    bta_hh_sm_execute(p_cb, event, (tBTA_HH_DATA*)p_msg);
  } else {
    index = bta_hh_dev_handle_to_cb_idx((uint8_t)p_msg->layer_specific);
    bta_hh_hdl_failure(event, (tBTA_HH_DATA*)p_msg);
  }

  if (index != BTA_HH_IDX_INVALID) {
    p_cb = &bta_hh_cb.kdev[index];
  }

  log::verbose("handle={} dev_cb[{}]", p_msg->layer_specific, index);
  bta_hh_sm_execute(p_cb, p_msg->event, (tBTA_HH_DATA*)p_msg);

  return true;
}

/*****************************************************************************
 *  Debug Functions
 ****************************************************************************/
/*******************************************************************************
 *
 * Function         bta_hh_evt_code
 *
 * Description
 *
 * Returns          void
 *
 ******************************************************************************/
static const char* bta_hh_evt_code(tBTA_HH_INT_EVT evt_code) {
  switch (evt_code) {
    case BTA_HH_API_OPEN_EVT:
      return "BTA_HH_API_OPEN_EVT";
    case BTA_HH_API_CLOSE_EVT:
      return "BTA_HH_API_CLOSE_EVT";
    case BTA_HH_INT_OPEN_EVT:
      return "BTA_HH_INT_OPEN_EVT";
    case BTA_HH_INT_CLOSE_EVT:
      return "BTA_HH_INT_CLOSE_EVT";
    case BTA_HH_INT_HANDSK_EVT:
      return "BTA_HH_INT_HANDSK_EVT";
    case BTA_HH_INT_DATA_EVT:
      return "BTA_HH_INT_DATA_EVT";
    case BTA_HH_INT_CTRL_DATA:
      return "BTA_HH_INT_CTRL_DATA";
    case BTA_HH_API_WRITE_DEV_EVT:
      return "BTA_HH_API_WRITE_DEV_EVT";
    case BTA_HH_SDP_CMPL_EVT:
      return "BTA_HH_SDP_CMPL_EVT";
    case BTA_HH_API_MAINT_DEV_EVT:
      return "BTA_HH_API_MAINT_DEV_EVT";
    case BTA_HH_API_GET_DSCP_EVT:
      return "BTA_HH_API_GET_DSCP_EVT";
    case BTA_HH_OPEN_CMPL_EVT:
      return "BTA_HH_OPEN_CMPL_EVT";
    case BTA_HH_GATT_CLOSE_EVT:
      return "BTA_HH_GATT_CLOSE_EVT";
    case BTA_HH_GATT_OPEN_EVT:
      return "BTA_HH_GATT_OPEN_EVT";
    case BTA_HH_START_ENC_EVT:
      return "BTA_HH_START_ENC_EVT";
    case BTA_HH_ENC_CMPL_EVT:
      return "BTA_HH_ENC_CMPL_EVT";
    default:
      return "unknown HID Host event code";
  }
}

/*******************************************************************************
 *
 * Function         bta_hh_state_code
 *
 * Description      get string representation of HID host state code.
 *
 * Returns          void
 *
 ******************************************************************************/
static const char* bta_hh_state_code(tBTA_HH_STATE state_code) {
  switch (state_code) {
    case BTA_HH_NULL_ST:
      return "BTA_HH_NULL_ST";
    case BTA_HH_IDLE_ST:
      return "BTA_HH_IDLE_ST";
    case BTA_HH_W4_CONN_ST:
      return "BTA_HH_W4_CONN_ST";
    case BTA_HH_CONN_ST:
      return "BTA_HH_CONN_ST";
    case BTA_HH_W4_SEC:
      return "BTA_HH_W4_SEC";
    default:
      return "unknown HID Host state";
  }
}
+102 −66

File changed.

Preview size limit exceeded, changes collapsed.

Loading