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

Commit e3ac1c88 authored by Grzegorz Kołodziejczyk's avatar Grzegorz Kołodziejczyk Committed by Grzegorz Kolodziejczyk
Browse files

le_audio: Add reason parsing for metadata control point response

This introduces parsing of metadata reason for control point response.

Tag: #feature
Test: atest --host bluetooth_le_audio_test
Bug: 266780311
Change-Id: Ifccc2d9b14e70a893f22aef45ca92f60313fd409
parent 702caaf6
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ static std::map<uint8_t, std::string> ctp_opcode_map_string = {
    {kCtpOpcodeRelease, "Release"},
};

static std::map<uint8_t, std::string> ctp_reason_map_string = {
static std::map<uint8_t, std::string> ctp_configuration_reason_map_string = {
    {kCtpResponseNoReason, ""},
    {kCtpResponseCodecId, "Codec ID"},
    {kCtpResponseCodecSpecificConfiguration, "Codec specific configuration"},
@@ -100,6 +100,31 @@ static std::map<uint8_t, std::string> ctp_response_code_map_string = {
    {kCtpResponseCodeUnspecifiedError, "Unspecified Error"},
};

static std::map<uint8_t, std::string> ctp_metadata_reason_map_string = {
    {kCtpMetadataResponsePreferredAudioContexts, "Preferred Audio Contexts"},
    {kCtpMetadataResponseStreamingAudioContexts, "Streaming Audio Contexts"},
    {kCtpMetadataResponseProgramInfo, "Program Info"},
    {kCtpMetadataResponseLanguage, "Language"},
    {kCtpMetadataResponseCcidList, "CCID List"},
    {kCtpMetadataResponseParentalRating, "Parental Rating"},
    {kCtpMetadataResponseProgramInfoUri, "Program Info URI"},
    {kCtpMetadataResponseExtendedMetadata, "Extended Metadata"},
    {kCtpMetadataResponseVendorSpecific, "Vendor Specific"},
};

static std::map<uint8_t, std::map<uint8_t, std::string>*>
    ctp_response_code_map = {
        {kCtpResponseCodeUnsupportedConfigurationParameterValue,
         &ctp_configuration_reason_map_string},
        {kCtpResponseCodeRejectedConfigurationParameterValue,
         &ctp_configuration_reason_map_string},
        {kCtpResponseCodeInvalidConfigurationParameterValue,
         &ctp_configuration_reason_map_string},
        {kCtpResponseCodeUnsupportedMetadata, &ctp_metadata_reason_map_string},
        {kCtpResponseCodeRejectedMetadata, &ctp_metadata_reason_map_string},
        {kCtpResponseCodeInvalidMetadata, &ctp_metadata_reason_map_string},
};

bool ParseAseStatusHeader(ase_rsp_hdr& arh, uint16_t len,
                          const uint8_t* value) {
  if (len < kAseRspHdrMinLen) {
@@ -276,7 +301,12 @@ bool ParseAseCtpNotification(struct ctp_ntf& ntf, uint16_t len,
              << "] response: "
              << ctp_response_code_map_string[ntf.entries[i].response_code]
              << " (" << loghex(ntf.entries[i].response_code) << ")"
              << " reason: " << ctp_reason_map_string[ntf.entries[i].reason]
              << " reason: "
              << ((ctp_response_code_map.count(ntf.entries[i].response_code) !=
                   0)
                      ? (*ctp_response_code_map[ntf.entries[i].response_code])
                            [ntf.entries[i].reason]
                      : "")
              << " (" << loghex(ntf.entries[i].reason) << ")";

  return true;
+10 −0
Original line number Diff line number Diff line
@@ -60,6 +60,16 @@ constexpr uint8_t kCtpResponseMaxTransportLatency = 0x08;
constexpr uint8_t kCtpResponsePresentationDelay = 0x09;
constexpr uint8_t kCtpResponseInvalidAseCisMapping = 0x0A;

constexpr uint8_t kCtpMetadataResponsePreferredAudioContexts = 0x01;
constexpr uint8_t kCtpMetadataResponseStreamingAudioContexts = 0x02;
constexpr uint8_t kCtpMetadataResponseProgramInfo = 0x03;
constexpr uint8_t kCtpMetadataResponseLanguage = 0x04;
constexpr uint8_t kCtpMetadataResponseCcidList = 0x05;
constexpr uint8_t kCtpMetadataResponseParentalRating = 0x06;
constexpr uint8_t kCtpMetadataResponseProgramInfoUri = 0x07;
constexpr uint8_t kCtpMetadataResponseExtendedMetadata = 0xFE;
constexpr uint8_t kCtpMetadataResponseVendorSpecific = 0xFF;

constexpr uint8_t kLeAudioErrorCtpUnsupporterdOpcode = 0xFF;
constexpr uint8_t kLeAudioErrorCtpTruncatedOperation = 0xFE;
constexpr uint8_t kLeAudioErrorCtpCtpErr = 0xFD;
+64 −0
Original line number Diff line number Diff line
@@ -1032,6 +1032,70 @@ TEST(LeAudioClientParserTest, testParseAseCtpNotification) {
  ASSERT_EQ(ntf.entries[1].reason, 0x03);
}

TEST(LeAudioClientParserTest, testParseAseCtpNotificationConfigurationIssue) {
  ctp_ntf ntf;
  const uint8_t value1[] = {
      // Opcode
      0x01,
      // Number of ASEs
      0x02,
      // ASE ID
      0x01,
      // Response Code
      0x07,
      // Reason
      0x01,
      // ASE ID
      0x03,
      // Response Code
      0x05,
      // Reason
      0x05,
  };
  ParseAseCtpNotification(ntf, sizeof(value1), value1);

  ASSERT_EQ(ntf.op, 0x01u);
  ASSERT_EQ(ntf.entries.size(), 2u);
  ASSERT_EQ(ntf.entries[0].ase_id, 0x01u);
  ASSERT_EQ(ntf.entries[0].response_code, 0x07u);
  ASSERT_EQ(ntf.entries[0].reason, 0x01);
  ASSERT_EQ(ntf.entries[1].ase_id, 0x03u);
  ASSERT_EQ(ntf.entries[1].response_code, 0x05u);
  ASSERT_EQ(ntf.entries[1].reason, 0x05);
}

TEST(LeAudioClientParserTest, testParseAseCtpNotificationMetadataIssue) {
  ctp_ntf ntf;
  const uint8_t value1[] = {
      // Opcode
      0x01,
      // Number of ASEs
      0x02,
      // ASE ID
      0x01,
      // Response Code
      0x0A,
      // Reason
      0x01,
      // ASE ID
      0x03,
      // Response Code
      0x0D,
      // Reason
      0xFF,
  };
  ParseAseCtpNotification(ntf, sizeof(value1), value1);

  ASSERT_EQ(ntf.op, 0x01u);
  ASSERT_EQ(ntf.entries.size(), 2u);
  ASSERT_EQ(ntf.entries[0].ase_id, 0x01u);
  ASSERT_EQ(ntf.entries[0].response_code, 0x0Au);
  ASSERT_EQ(ntf.entries[0].reason, 0x01);
  ASSERT_EQ(ntf.entries[1].ase_id, 0x03u);
  ASSERT_EQ(ntf.entries[1].response_code, 0x0Du);
  ASSERT_EQ(ntf.entries[1].reason, 0xFF);
}

TEST(LeAudioClientParserTest, testPrepareAseCtpCodecConfigEmpty) {
  std::vector<struct ctp_codec_conf> confs;
  std::vector<uint8_t> value;