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

Commit fba94b7a authored by Michael Sun's avatar Michael Sun
Browse files

interop: allow hid host to connect to not-first HOG service

Due to the limitations of the current HID host implementation, it
assumes that the HID peripheral has only one HOG service, or if there
are multiple HOG services, the first one is always active. To address
this issue temporarily, an interop quirk has been introduced to allow
the HID host to connect to a non-first HID service for certain devices.
However, for a long-term solution, the HID stack needs to be refactored
to handle multiple HID services simultaneously.

Bug: 286413526
Bug: 328129633
Tag: #floss
Test: mmm packages/modules/Bluetooth
Test: Manual test on Brya, Logitech CASA working
Flag: EXEMPT, apply only to one and not-functioning device

Change-Id: I0733f1597d9058c992e46b99c6a31748714d8dfa
parent 13c9f3e5
Loading
Loading
Loading
Loading
+17 −0
Original line number Original line Diff line number Diff line
@@ -66,6 +66,8 @@ constexpr bool kBTA_HH_LE_RECONN = false;


#define BTA_LE_HID_RTP_UUID_MAX 5
#define BTA_LE_HID_RTP_UUID_MAX 5


#define HID_PREFERRED_SERVICE_INDEX_3 3

namespace {
namespace {


constexpr char kBtmLogTag[] = "LE HIDH";
constexpr char kBtmLogTag[] = "LE HIDH";
@@ -1511,12 +1513,27 @@ static void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL* p_data) {
  const gatt::Service* gap_service = nullptr;
  const gatt::Service* gap_service = nullptr;
  const gatt::Service* scp_service = nullptr;
  const gatt::Service* scp_service = nullptr;


  int num_hid_service = 0;
  bool have_hid = false;
  bool have_hid = false;
  for (const gatt::Service& service : *services) {
  for (const gatt::Service& service : *services) {
    if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_LE_HID) &&
    if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_LE_HID) &&
        service.is_primary && !have_hid) {
        service.is_primary && !have_hid) {
      have_hid = true;
      have_hid = true;


      // TODO(b/286413526): The current implementation connects to the first HID
      // service, in the case of multiple HID services being present. As a
      // temporary mitigation, connect to the third HID service for some
      // particular devices. The long-term fix should refactor HID stack to
      // connect to multiple HID services simultaneously.
      if (interop_match_vendor_product_ids(
              INTEROP_MULTIPLE_HOGP_SERVICE_CHOOSE_THIRD,
              p_dev_cb->dscp_info.vendor_id, p_dev_cb->dscp_info.product_id)) {
        if (num_hid_service != HID_PREFERRED_SERVICE_INDEX_3) {
          num_hid_service++;
          continue;
        }
      }

      /* found HID primamry service */
      /* found HID primamry service */
      p_dev_cb->hid_srvc.state = BTA_HH_SERVICE_DISCOVERED;
      p_dev_cb->hid_srvc.state = BTA_HH_SERVICE_DISCOVERED;
      p_dev_cb->hid_srvc.srvc_inst_id = service.handle;
      p_dev_cb->hid_srvc.srvc_inst_id = service.handle;
+6 −0
Original line number Original line Diff line number Diff line
@@ -857,3 +857,9 @@ fc:3f:a6 = Address_Based
[INTEROP_SUSPEND_ATT_TRAFFIC_DURING_PAIRING]
[INTEROP_SUSPEND_ATT_TRAFFIC_DURING_PAIRING]
ORN = Name_Based
ORN = Name_Based
EPG = Name_Based
EPG = Name_Based

# Some HID devices have more than one HID services, this rule ask the stack to connect to the
# specify one.
# 0X046D-0XBB01 - Logitech CASA Pop-Up Touch
[INTEROP_MULTIPLE_HOGP_SERVICE_CHOOSE_THIRD]
0X046D-0XBB01 = Vndr_Prdt_Based
+3 −0
Original line number Original line Diff line number Diff line
@@ -347,6 +347,9 @@ typedef enum {
  // collision.
  // collision.
  INTEROP_DELAY_AUTH,
  INTEROP_DELAY_AUTH,


  // Some LE HID devices contain more than one HOGP service.
  INTEROP_MULTIPLE_HOGP_SERVICE_CHOOSE_THIRD,

  END_OF_INTEROP_LIST
  END_OF_INTEROP_LIST
} interop_feature_t;
} interop_feature_t;


+1 −0
Original line number Original line Diff line number Diff line
@@ -395,6 +395,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) {
    CASE_RETURN_STR(INTEROP_SUSPEND_ATT_TRAFFIC_DURING_PAIRING);
    CASE_RETURN_STR(INTEROP_SUSPEND_ATT_TRAFFIC_DURING_PAIRING);
    CASE_RETURN_STR(INTEROP_INSERT_CALL_WHEN_SCO_START);
    CASE_RETURN_STR(INTEROP_INSERT_CALL_WHEN_SCO_START);
    CASE_RETURN_STR(INTEROP_DELAY_AUTH);
    CASE_RETURN_STR(INTEROP_DELAY_AUTH);
    CASE_RETURN_STR(INTEROP_MULTIPLE_HOGP_SERVICE_CHOOSE_THIRD);
  }
  }
  return UNKNOWN_INTEROP_FEATURE;
  return UNKNOWN_INTEROP_FEATURE;
}
}