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

Commit d11e8173 authored by Grzegorz Kołodziejczyk's avatar Grzegorz Kołodziejczyk
Browse files

le_audio: Initial implementation of TMAP

Patch implements part of TMAP for discovering and parsing data from
server.

Tag: #feature
Test: atest le_audio_client_test
Sponsor: jpawlowski@
Bug: 150670922
Bug: 208972148
Change-Id: I3655237be2c19ae397fc20e4c0c48c906121deac
Merged-In: I3655237be2c19ae397fc20e4c0c48c906121deac
(cherry picked from commit e94ee290)
parent 94379a03
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -1278,6 +1278,9 @@ class LeAudioClientImpl : public LeAudioClient {

      if (ParseAseCtpNotification(*ntf, len, value))
        ControlPointNotificationHandler(*ntf);
    } else if (hdl == leAudioDevice->tmap_role_hdl_) {
      le_audio::client_parser::tmap::ParseTmapRole(leAudioDevice->tmap_role_,
                                                   len, value);
    } else {
      LOG(ERROR) << __func__ << ", Unknown attribute read: " << loghex(hdl);
    }
@@ -1573,6 +1576,7 @@ class LeAudioClientImpl : public LeAudioClient {

    const gatt::Service* pac_svc = nullptr;
    const gatt::Service* ase_svc = nullptr;
    const gatt::Service* tmas_svc = nullptr;

    std::vector<uint16_t> csis_primary_handles;
    uint16_t cas_csis_included_handle = 0;
@@ -1603,6 +1607,10 @@ class LeAudioClientImpl : public LeAudioClient {
            break;
          }
        }
      } else if (tmp.uuid == le_audio::uuid::kTelephonyMediaAudioServiceUuid) {
        LOG_INFO(", Found Telephony and Media Audio service, handle: %04x",
                 tmp.handle);
        tmas_svc = &tmp;
      }
    }

@@ -1859,6 +1867,25 @@ class LeAudioClientImpl : public LeAudioClient {
      }
    }

    if (tmas_svc) {
      for (const gatt::Characteristic& charac : tmas_svc->characteristics) {
        if (charac.uuid ==
            le_audio::uuid::kTelephonyMediaAudioProfileRoleCharacteristicUuid) {
          leAudioDevice->tmap_role_hdl_ = charac.value_handle;

          /* Obtain initial state of TMAP role */
          BtaGattQueue::ReadCharacteristic(conn_id,
                                           leAudioDevice->tmap_role_hdl_,
                                           OnGattReadRspStatic, NULL);

          LOG_INFO(
              ", Found Telephony and Media Profile characteristic, "
              "handle: %04x",
              leAudioDevice->tmap_role_hdl_);
        }
      }
    }

    leAudioDevice->known_service_handles_ = true;
    leAudioDevice->notify_connected_after_read_ = true;

+21 −0
Original line number Diff line number Diff line
@@ -657,5 +657,26 @@ bool ParseAvailableAudioContexts(struct acs_available_audio_contexts& contexts,
}
}  // namespace pacs

namespace tmap {

bool ParseTmapRole(std::bitset<16>& role, uint16_t len, const uint8_t* value) {
  if (len != kTmapRoleLen) {
    LOG_ERROR(
        ", Wrong len of Telephony Media Audio Profile Role, "
        "characteristic");
    return false;
  }

  STREAM_TO_UINT16(role, value);

  LOG_INFO(
      ", Telephony Media Audio Profile Role:"
      "\n\tRole: %s",
      role.to_string().c_str());

  return true;
}
}  // namespace tmap

}  // namespace client_parser
}  // namespace le_audio
+8 −0
Original line number Diff line number Diff line
@@ -240,5 +240,13 @@ bool ParseAvailableAudioContexts(struct acs_available_audio_contexts& rsp,
bool ParseSupportedAudioContexts(struct acs_supported_audio_contexts& rsp,
                                 uint16_t len, const uint8_t* value);
}  // namespace pacs

namespace tmap {

constexpr uint16_t kTmapRoleLen = 2;

bool ParseTmapRole(std::bitset<16>& role, uint16_t len, const uint8_t* value);

}  // namespace tmap
}  // namespace client_parser
}  // namespace le_audio
+20 −0
Original line number Diff line number Diff line
@@ -1645,5 +1645,25 @@ TEST(LeAudioClientParserTest, testPrepareAseCtpReleaseMultiple) {

}  // namespace ascs

namespace tmap {

TEST(LeAudioClientParserTest, testParseTmapRoleValid) {
  std::bitset<16> role;
  const uint8_t value[] = {0x3F, 0x00};

  ASSERT_TRUE(ParseTmapRole(role, 2, value));

  ASSERT_EQ(role, 0x003F);  // All possible TMAP roles
}

TEST(LeAudioClientParserTest, testParseTmapRoleInvalidLen) {
  std::bitset<16> role;
  const uint8_t value[] = {0x00, 0x3F};

  ASSERT_FALSE(ParseTmapRole(role, 3, value));
}

}  // namespace tmap

}  // namespace client_parser
}  // namespace le_audio
+2 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ class LeAudioDevice {
  bool encrypted_;
  int group_id_;
  bool csis_member_;
  std::bitset<16> tmap_role_;

  uint8_t audio_directions_;
  types::AudioLocations snk_audio_locations_;
@@ -76,6 +77,7 @@ class LeAudioDevice {
  struct types::hdl_pair audio_supp_cont_hdls_;
  std::vector<struct types::ase> ases_;
  struct types::hdl_pair ctp_hdls_;
  uint16_t tmap_role_hdl_;

  alarm_t* link_quality_timer;
  uint16_t link_quality_timer_data;
Loading