OSDN Git Service

Fall back to Read Request when reading Characteristic Extended Properties
authorJakub Pawlowski <jpawlowski@google.com>
Thu, 28 Jun 2018 15:27:57 +0000 (08:27 -0700)
committerJakub Pawlowski <jpawlowski@google.com>
Thu, 3 Sep 2020 14:24:35 +0000 (14:24 +0000)
If Read Multiple Request is not supported, fall back to Read Request.

Test: Manually tested against device modified to not support Read
Multiple Request (GATT_REQ_READ_MULTI in gatt_server_handle_client_req
forced to return GATT_REQ_NOT_SUPPORTED)
Bug: 110864501

Change-Id: I262678c93f2c3e56832502d1f46542dfc97c7904

bta/gatt/bta_gattc_cache.cc
bta/gatt/bta_gattc_int.h

index 455a1a5..fcd5d4f 100644 (file)
@@ -171,6 +171,15 @@ static void bta_gattc_explore_next_service(uint16_t conn_id,
   const auto& descriptors =
       p_srvc_cb->pending_discovery.DescriptorHandlesToRead();
   if (!descriptors.empty()) {
+    if (p_srvc_cb->read_multiple_not_supported) {
+      tGATT_READ_PARAM read_param{
+          .by_handle = {.handle = descriptors.front(),
+                        .auth_req = GATT_AUTH_REQ_NONE}};
+      GATTC_Read(conn_id, GATT_READ_BY_HANDLE, &read_param);
+      // asynchronous continuation in bta_gattc_op_cmpl_during_discovery
+      return;
+    }
+
     // TODO(jpawlowski): as a limit we should use MTU/2 rather than
     // GATT_MAX_READ_MULTI_HANDLES
     /* each descriptor contains just 2 bytes, so response size is same as
@@ -187,8 +196,7 @@ static void bta_gattc_explore_next_service(uint16_t conn_id,
            sizeof(uint16_t) * num_handles);
     GATTC_Read(conn_id, GATT_READ_MULTIPLE, &read_param);
 
-    // asynchronous continuation in bta_gattc_op_cmpl_during_discovery, when
-    // read is finished
+    // asynchronous continuation in bta_gattc_op_cmpl_during_discovery
     return;
   }
 
@@ -356,21 +364,35 @@ void bta_gattc_op_cmpl_during_discovery(UNUSED_ATTR tBTA_GATTC_CLCB* p_clcb,
     VLOG(1) << __func__ << ": op = " << +p_data->hdr.layer_specific;
     return;
   }
-
   // our read operation is finished.
   // TODO: check if we can get here when any other read operation i.e. initiated
   // by upper layer apps, can get us there.
+
+  tBTA_GATTC_SERV* p_srvc_cb = p_clcb->p_srcb;
   const uint8_t status = p_data->op_cmpl.status;
+
+  if (status == GATT_REQ_NOT_SUPPORTED &&
+      !p_srvc_cb->read_multiple_not_supported) {
+    // can't do "read multiple request", fall back to "read request"
+    p_srvc_cb->read_multiple_not_supported = true;
+    bta_gattc_explore_next_service(p_clcb->bta_conn_id, p_srvc_cb);
+    return;
+  }
+
   if (status != GATT_SUCCESS) {
-    if (status == GATT_REQ_NOT_SUPPORTED) {
-      // TODO: handle case when read multiple is not supported on remote device.
-    }
     LOG(WARNING) << "Discovery on server failed: " << loghex(status);
     bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR);
   }
 
   const tGATT_VALUE& att_value = p_data->op_cmpl.p_cmpl->att_value;
+  if (!p_srvc_cb->read_multiple_not_supported && att_value.len != 2) {
+    // Just one Characteristic Extended Properties value at a time in Read
+    // Response
+    LOG(WARNING) << __func__ << " Read Response should be just 2 bytes!";
+    bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR);
+  }
 
+  // Parsing is same for "Read Multiple Response", and for "Read Response"
   const uint8_t* p = att_value.value;
   std::vector<uint16_t> value_of_descriptors;
   while (p < att_value.value + att_value.len) {
@@ -379,7 +401,6 @@ void bta_gattc_op_cmpl_during_discovery(UNUSED_ATTR tBTA_GATTC_CLCB* p_clcb,
     value_of_descriptors.push_back(extended_properties);
   }
 
-  tBTA_GATTC_SERV* p_srvc_cb = p_clcb->p_srcb;
   bool ret =
       p_srvc_cb->pending_discovery.SetValueOfDescriptors(value_of_descriptors);
   if (!ret) {
index 3eec9a8..50c6776 100644 (file)
@@ -214,6 +214,10 @@ typedef struct {
 
   gatt::DatabaseBuilder pending_discovery;
 
+  /* used only during service discovery, when reading Extended Characteristic
+   * Properties */
+  bool read_multiple_not_supported;
+
   uint8_t srvc_hdl_chg; /* service handle change indication pending */
   uint16_t attr_index;  /* cahce NV saving/loading attribute index */