1 /*
2  * Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
3  * www.ehima.com
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /*
19  *  This module contains API of the audio stream control protocol.
20  */
21 
22 #include "client_parser.h"
23 
24 #include <base/strings/string_number_conversions.h>
25 #include <bluetooth/log.h>
26 #include <endian.h>
27 #include <hardware/bt_common_types.h>
28 #include <hardware/bt_gatt_types.h>
29 
30 #include <map>
31 #include <numeric>
32 
33 #include "internal_include/bt_trace.h"
34 #include "le_audio_types.h"
35 #include "le_audio_utils.h"
36 #include "os/log.h"
37 #include "stack/include/bt_types.h"
38 
39 using bluetooth::le_audio::types::acs_ac_record;
40 
41 namespace bluetooth::le_audio {
42 namespace client_parser {
43 namespace ascs {
44 static std::map<uint8_t, std::string> ase_state_map_string = {
45     {kAseStateIdle, "Idle"},
46     {kAseStateCodecConfigured, "Codec Configured"},
47     {kAseStateQosConfigured, "QoS Configured"},
48     {kAseStateEnabling, "Enabling"},
49     {kAseStateStreaming, "Streaming"},
50     {kAseStateDisabling, "Disabling"},
51     {kAseStateReleasing, "Releasing"},
52 };
53 
54 static std::map<uint8_t, std::string> ctp_opcode_map_string = {
55     {kCtpOpcodeCodecConfiguration, "Config Codec"},
56     {kCtpOpcodeQosConfiguration, "Config QoS"},
57     {kCtpOpcodeEnable, "Enable"},
58     {kCtpOpcodeReceiverStartReady, "Receiver Start Ready"},
59     {kCtpOpcodeDisable, "Disable"},
60     {kCtpOpcodeReceiverStopReady, "Receiver Stop Ready"},
61     {kCtpOpcodeUpdateMetadata, "Update Metadata"},
62     {kCtpOpcodeRelease, "Release"},
63 };
64 
65 static std::map<uint8_t, std::string> ctp_configuration_reason_map_string = {
66     {kCtpResponseNoReason, ""},
67     {kCtpResponseCodecId, "Codec ID"},
68     {kCtpResponseCodecSpecificConfiguration, "Codec specific configuration"},
69     {kCtpResponseSduInterval, "SDU interval"},
70     {kCtpResponseFraming, "Framing"},
71     {kCtpResponsePhy, "PHY"},
72     {kCtpResponseMaximumSduSize, "Maximum SDU size"},
73     {kCtpResponseRetransmissionNumber, "Retransmission number"},
74     {kCtpResponseMaxTransportLatency, "Max Transport latency"},
75     {kCtpResponsePresentationDelay, "Presentation delay"},
76     {kCtpResponseInvalidAseCisMapping, "Invalid ASE CIS mapping"},
77 };
78 
79 static std::map<uint8_t, std::string> ctp_response_code_map_string = {
80     {kCtpResponseCodeSuccess, "Success"},
81     {kCtpResponseCodeUnsupportedOpcode, "Unsupported Opcode"},
82     {kCtpResponseCodeInvalidLength, "Invalid Length"},
83     {kCtpResponseCodeInvalidAseId, "Invalid ASE ID"},
84     {kCtpResponseCodeInvalidAseStateMachineTransition,
85      "Invalid ASE State Machine Transition"},
86     {kCtpResponseCodeInvalidAseDirection, "Invalid ASE Direction"},
87     {kCtpResponseCodeUnsupportedAudioCapabilities,
88      "Unsupported Audio Capabilities"},
89     {kCtpResponseCodeUnsupportedConfigurationParameterValue,
90      "Unsupported Configuration Parameter Value"},
91     {kCtpResponseCodeRejectedConfigurationParameterValue,
92      "Rejected Configuration Parameter Value"},
93     {kCtpResponseCodeInvalidConfigurationParameterValue,
94      "Invalid Configuration Parameter Value"},
95     {kCtpResponseCodeUnsupportedMetadata, "Unsupported Metadata"},
96     {kCtpResponseCodeRejectedMetadata, "Rejected Metadata"},
97     {kCtpResponseCodeInvalidMetadata, "Invalid Metadata"},
98     {kCtpResponseCodeInsufficientResources, "Insufficient Resources"},
99     {kCtpResponseCodeUnspecifiedError, "Unspecified Error"},
100 };
101 
102 static std::map<uint8_t, std::string> ctp_metadata_reason_map_string = {
103     {kCtpMetadataResponsePreferredAudioContexts, "Preferred Audio Contexts"},
104     {kCtpMetadataResponseStreamingAudioContexts, "Streaming Audio Contexts"},
105     {kCtpMetadataResponseProgramInfo, "Program Info"},
106     {kCtpMetadataResponseLanguage, "Language"},
107     {kCtpMetadataResponseCcidList, "CCID List"},
108     {kCtpMetadataResponseParentalRating, "Parental Rating"},
109     {kCtpMetadataResponseProgramInfoUri, "Program Info URI"},
110     {kCtpMetadataResponseExtendedMetadata, "Extended Metadata"},
111     {kCtpMetadataResponseVendorSpecific, "Vendor Specific"},
112 };
113 
114 static std::map<uint8_t, std::map<uint8_t, std::string>*>
115     ctp_response_code_map = {
116         {kCtpResponseCodeUnsupportedConfigurationParameterValue,
117          &ctp_configuration_reason_map_string},
118         {kCtpResponseCodeRejectedConfigurationParameterValue,
119          &ctp_configuration_reason_map_string},
120         {kCtpResponseCodeInvalidConfigurationParameterValue,
121          &ctp_configuration_reason_map_string},
122         {kCtpResponseCodeUnsupportedMetadata, &ctp_metadata_reason_map_string},
123         {kCtpResponseCodeRejectedMetadata, &ctp_metadata_reason_map_string},
124         {kCtpResponseCodeInvalidMetadata, &ctp_metadata_reason_map_string},
125 };
126 
ParseAseStatusHeader(ase_rsp_hdr & arh,uint16_t len,const uint8_t * value)127 bool ParseAseStatusHeader(ase_rsp_hdr& arh, uint16_t len,
128                           const uint8_t* value) {
129   if (len < kAseRspHdrMinLen) {
130     log::error("wrong len of ASE char (header): {}", static_cast<int>(len));
131 
132     return false;
133   }
134 
135   STREAM_TO_UINT8(arh.id, value);
136   STREAM_TO_UINT8(arh.state, value);
137 
138   log::info("ASE status: \tASE id: 0x{:x}\tASE state: {} (0x{:x})", arh.id,
139             ase_state_map_string[arh.state], arh.state);
140 
141   return true;
142 }
143 
ParseAseStatusCodecConfiguredStateParams(struct ase_codec_configured_state_params & rsp,uint16_t len,const uint8_t * value)144 bool ParseAseStatusCodecConfiguredStateParams(
145     struct ase_codec_configured_state_params& rsp, uint16_t len,
146     const uint8_t* value) {
147   uint8_t codec_spec_conf_len;
148 
149   if (len < kAseStatusCodecConfMinLen) {
150     log::error("Wrong len of codec conf status (Codec conf header)");
151     return false;
152   }
153 
154   STREAM_TO_UINT8(rsp.framing, value);
155   STREAM_TO_UINT8(rsp.preferred_phy, value);
156   STREAM_TO_UINT8(rsp.preferred_retrans_nb, value);
157   STREAM_TO_UINT16(rsp.max_transport_latency, value);
158   STREAM_TO_UINT24(rsp.pres_delay_min, value);
159   STREAM_TO_UINT24(rsp.pres_delay_max, value);
160   STREAM_TO_UINT24(rsp.preferred_pres_delay_min, value);
161   STREAM_TO_UINT24(rsp.preferred_pres_delay_max, value);
162   STREAM_TO_UINT8(rsp.codec_id.coding_format, value);
163   STREAM_TO_UINT16(rsp.codec_id.vendor_company_id, value);
164   STREAM_TO_UINT16(rsp.codec_id.vendor_codec_id, value);
165   STREAM_TO_UINT8(codec_spec_conf_len, value);
166 
167   len -= kAseStatusCodecConfMinLen;
168 
169   if (len != codec_spec_conf_len) {
170     log::error("Wrong len of codec conf status (Codec spec conf)");
171     return false;
172   }
173   if (codec_spec_conf_len)
174     rsp.codec_spec_conf =
175         std::vector<uint8_t>(value, value + codec_spec_conf_len);
176 
177   log::info(
178       "Codec configuration\n\tFraming: 0x{:x}\n\tPreferred PHY: "
179       "0x{:x}\n\tPreferred retransmission number: 0x{:x}\n\tMax transport "
180       "latency: 0x{:x}\n\tPresence delay min: 0x{:x}\n\tPresence delay max: "
181       "0x{:x}\n\tPreferredPresentationDelayMin: "
182       "0x{:x}\n\tPreferredPresentationDelayMax: 0x{:x}\n\tCoding format: "
183       "0x{:x}\n\tVendor codec company ID: 0x{:x}\n\tVendor codec ID: "
184       "0x{:x}\n\tCodec specific conf len: {}\n\tCodec specific conf: {}",
185       rsp.framing, rsp.preferred_phy, rsp.preferred_retrans_nb,
186       rsp.max_transport_latency, rsp.pres_delay_min, rsp.pres_delay_max,
187       rsp.preferred_pres_delay_min, rsp.preferred_pres_delay_max,
188       rsp.codec_id.coding_format, rsp.codec_id.vendor_company_id,
189       rsp.codec_id.vendor_codec_id, (int)codec_spec_conf_len,
190       base::HexEncode(rsp.codec_spec_conf.data(), rsp.codec_spec_conf.size()));
191 
192   return true;
193 }
194 
ParseAseStatusQosConfiguredStateParams(struct ase_qos_configured_state_params & rsp,uint16_t len,const uint8_t * value)195 bool ParseAseStatusQosConfiguredStateParams(
196     struct ase_qos_configured_state_params& rsp, uint16_t len,
197     const uint8_t* value) {
198   if (len != kAseStatusCodecQosConfMinLen) {
199     log::error("Wrong len of ASE characteristic (QOS conf header)");
200     return false;
201   }
202 
203   STREAM_TO_UINT8(rsp.cig_id, value);
204   STREAM_TO_UINT8(rsp.cis_id, value);
205   STREAM_TO_UINT24(rsp.sdu_interval, value);
206   STREAM_TO_UINT8(rsp.framing, value);
207   STREAM_TO_UINT8(rsp.phy, value);
208   STREAM_TO_UINT16(rsp.max_sdu, value);
209   STREAM_TO_UINT8(rsp.retrans_nb, value);
210   STREAM_TO_UINT16(rsp.max_transport_latency, value);
211   STREAM_TO_UINT24(rsp.pres_delay, value);
212 
213   log::info(
214       "Codec QoS Configured\n\tCIG: 0x{:x}\n\tCIS: 0x{:x}\n\tSDU interval: "
215       "0x{:x}\n\tFraming: 0x{:x}\n\tPHY: 0x{:x}\n\tMax SDU: "
216       "0x{:x}\n\tRetransmission number: 0x{:x}\n\tMax transport latency: "
217       "0x{:x}\n\tPresentation delay: 0x{:x}",
218       rsp.cig_id, rsp.cis_id, rsp.sdu_interval, rsp.framing, rsp.phy,
219       rsp.max_sdu, rsp.retrans_nb, rsp.max_transport_latency, rsp.pres_delay);
220 
221   return true;
222 }
223 
ParseAseStatusTransientStateParams(struct ase_transient_state_params & rsp,uint16_t len,const uint8_t * value)224 bool ParseAseStatusTransientStateParams(struct ase_transient_state_params& rsp,
225                                         uint16_t len, const uint8_t* value) {
226   uint8_t metadata_len;
227 
228   if (len < kAseStatusTransMinLen) {
229     log::error("Wrong len of ASE characteristic (metadata)");
230     return false;
231   }
232 
233   STREAM_TO_UINT8(rsp.cig_id, value);
234   STREAM_TO_UINT8(rsp.cis_id, value);
235   STREAM_TO_UINT8(metadata_len, value);
236   len -= kAseStatusTransMinLen;
237 
238   if (len != metadata_len) {
239     log::error("Wrong len of ASE characteristic (metadata)");
240     return false;
241   }
242 
243   if (metadata_len > 0)
244     rsp.metadata = std::vector<uint8_t>(value, value + metadata_len);
245 
246   log::info(
247       "Status enabling/streaming/disabling\n\tCIG: 0x{:x}\n\tCIS: "
248       "0x{:x}\n\tMetadata: {}",
249       rsp.cig_id, rsp.cis_id,
250       base::HexEncode(rsp.metadata.data(), rsp.metadata.size()));
251 
252   return true;
253 }
254 
ParseAseCtpNotification(struct ctp_ntf & ntf,uint16_t len,const uint8_t * value)255 bool ParseAseCtpNotification(struct ctp_ntf& ntf, uint16_t len,
256                              const uint8_t* value) {
257   uint8_t num_entries;
258 
259   if (len < kCtpNtfMinLen) {
260     log::error("Wrong len of ASE control point notification: {}", (int)len);
261     return false;
262   }
263 
264   STREAM_TO_UINT8(ntf.op, value);
265   STREAM_TO_UINT8(num_entries, value);
266 
267   if (len != kCtpNtfMinLen + (num_entries * kCtpAseEntryMinLen)) {
268     log::error("Wrong len of ASE control point notification (ASE IDs)");
269     return false;
270   }
271 
272   for (int i = 0; i < num_entries; i++) {
273     struct ctp_ase_entry entry;
274 
275     STREAM_TO_UINT8(entry.ase_id, value);
276     STREAM_TO_UINT8(entry.response_code, value);
277     STREAM_TO_UINT8(entry.reason, value);
278 
279     ntf.entries.push_back(std::move(entry));
280   }
281 
282   log::info(
283       "Control point notification\n\tOpcode: {} (0x{:x})\n\tNum ASE IDs: {}",
284       ctp_opcode_map_string[ntf.op], ntf.op, (int)num_entries);
285   for (size_t i = 0; i < num_entries; i++)
286     log::info("\n\tASE ID[0x{:x}] response: {} (0x{:x}) reason: {} (0x{:x})",
287               ntf.entries[i].ase_id,
288               ctp_response_code_map_string[ntf.entries[i].response_code],
289               ntf.entries[i].response_code,
290               ((ctp_response_code_map.count(ntf.entries[i].response_code) != 0)
291                    ? (*ctp_response_code_map[ntf.entries[i].response_code])
292                          [ntf.entries[i].reason]
293                    : ""),
294               ntf.entries[i].reason);
295 
296   return true;
297 }
298 
PrepareAseCtpCodecConfig(const std::vector<struct ctp_codec_conf> & confs,std::vector<uint8_t> & value)299 bool PrepareAseCtpCodecConfig(const std::vector<struct ctp_codec_conf>& confs,
300                               std::vector<uint8_t>& value) {
301   if (confs.size() == 0) return false;
302 
303   std::stringstream conf_ents_str;
304   size_t msg_len = std::accumulate(
305       confs.begin(), confs.end(),
306       confs.size() * kCtpCodecConfMinLen + kAseNumSize + kCtpOpSize,
307       [&conf_ents_str](size_t cur_len, auto const& conf) {
308         if (utils::IsCodecUsingLtvFormat(conf.codec_id)) {
309           types::LeAudioLtvMap ltv;
310           if (ltv.Parse(conf.codec_config.data(), conf.codec_config.size())) {
311             for (const auto& [type, value] : ltv.Values()) {
312               conf_ents_str
313                   << "\ttype: " << std::to_string(type)
314                   << "\tlen: " << std::to_string(value.size())
315                   << "\tdata: " << base::HexEncode(value.data(), value.size())
316                   << "\n";
317             }
318             return cur_len + conf.codec_config.size();
319           }
320           log::error("Error parsing codec configuration LTV data.");
321         }
322 
323         conf_ents_str << "\t"
324                       << base::HexEncode(conf.codec_config.data(),
325                                          conf.codec_config.size());
326         return cur_len + conf.codec_config.size();
327       });
328 
329   value.resize(msg_len);
330   uint8_t* msg = value.data();
331   UINT8_TO_STREAM(msg, kCtpOpcodeCodecConfiguration);
332 
333   UINT8_TO_STREAM(msg, confs.size());
334   for (const struct ctp_codec_conf& conf : confs) {
335     UINT8_TO_STREAM(msg, conf.ase_id);
336     UINT8_TO_STREAM(msg, conf.target_latency);
337     UINT8_TO_STREAM(msg, conf.target_phy);
338     UINT8_TO_STREAM(msg, conf.codec_id.coding_format);
339     UINT16_TO_STREAM(msg, conf.codec_id.vendor_company_id);
340     UINT16_TO_STREAM(msg, conf.codec_id.vendor_codec_id);
341 
342     UINT8_TO_STREAM(msg, conf.codec_config.size());
343     ARRAY_TO_STREAM(msg, conf.codec_config.data(),
344                     static_cast<int>(conf.codec_config.size()));
345 
346     log::info(
347         "Codec configuration\n\tAse id: 0x{:x}\n\tTarget latency: "
348         "0x{:x}\n\tTarget PHY: 0x{:x}\n\tCoding format: 0x{:x}\n\tVendor codec "
349         "company ID: 0x{:x}\n\tVendor codec ID: 0x{:x}\n\tCodec config len: "
350         "{}\n\tCodec spec conf: \n{}",
351         conf.ase_id, conf.target_latency, conf.target_phy,
352         conf.codec_id.coding_format, conf.codec_id.vendor_company_id,
353         conf.codec_id.vendor_codec_id,
354         static_cast<int>(conf.codec_config.size()), conf_ents_str.str());
355   }
356 
357   return true;
358 }
359 
PrepareAseCtpConfigQos(const std::vector<struct ctp_qos_conf> & confs,std::vector<uint8_t> & value)360 bool PrepareAseCtpConfigQos(const std::vector<struct ctp_qos_conf>& confs,
361                             std::vector<uint8_t>& value) {
362   if (confs.size() == 0) return false;
363   value.resize(confs.size() * kCtpQosConfMinLen + kAseNumSize + kCtpOpSize);
364 
365   uint8_t* msg = value.data();
366   UINT8_TO_STREAM(msg, kCtpOpcodeQosConfiguration);
367   UINT8_TO_STREAM(msg, confs.size());
368 
369   for (const struct ctp_qos_conf& conf : confs) {
370     UINT8_TO_STREAM(msg, conf.ase_id);
371     UINT8_TO_STREAM(msg, conf.cig);
372     UINT8_TO_STREAM(msg, conf.cis);
373     UINT24_TO_STREAM(msg, conf.sdu_interval);
374     UINT8_TO_STREAM(msg, conf.framing);
375     UINT8_TO_STREAM(msg, conf.phy);
376     UINT16_TO_STREAM(msg, conf.max_sdu);
377     UINT8_TO_STREAM(msg, conf.retrans_nb);
378     UINT16_TO_STREAM(msg, conf.max_transport_latency);
379     UINT24_TO_STREAM(msg, conf.pres_delay);
380 
381     log::info(
382         "QoS configuration\n\tAse id: 0x{:x}\n\tcig: 0x{:x}\n\tCis: "
383         "0x{:x}\n\tSDU interval: 0x{:x}\n\tFraming: 0x{:x}\n\tPhy: "
384         "0x{:x}\n\tMax sdu size: 0x{:x}\n\tRetrans nb: 0x{:x}\n\tMax Transport "
385         "latency: 0x{:x}\n\tPres delay: 0x{:x}",
386         conf.ase_id, conf.cig, conf.cis, conf.sdu_interval, conf.framing,
387         conf.phy, conf.max_sdu, conf.retrans_nb, conf.max_transport_latency,
388         conf.pres_delay);
389   }
390 
391   return true;
392 }
393 
PrepareAseCtpEnable(const std::vector<struct ctp_enable> & confs,std::vector<uint8_t> & value)394 bool PrepareAseCtpEnable(const std::vector<struct ctp_enable>& confs,
395                          std::vector<uint8_t>& value) {
396   if (confs.size() == 0) return false;
397 
398   if (confs.size() > UINT8_MAX) {
399     log::error("To many ASEs to update metadata");
400     return false;
401   }
402 
403   uint16_t msg_len = confs.size() * kCtpEnableMinLen + kAseNumSize + kCtpOpSize;
404   for (auto& conf : confs) {
405     if (msg_len > GATT_MAX_ATTR_LEN) {
406       log::error("Message length above GATT maximum");
407       return false;
408     }
409     if (conf.metadata.size() > UINT8_MAX) {
410       log::error("ase[{}] metadata length is invalid", conf.ase_id);
411       return false;
412     }
413 
414     msg_len += conf.metadata.size();
415   }
416   value.resize(msg_len);
417 
418   uint8_t* msg = value.data();
419   UINT8_TO_STREAM(msg, kCtpOpcodeEnable);
420   UINT8_TO_STREAM(msg, confs.size());
421 
422   for (const struct ctp_enable& conf : confs) {
423     UINT8_TO_STREAM(msg, conf.ase_id);
424     UINT8_TO_STREAM(msg, conf.metadata.size());
425     ARRAY_TO_STREAM(msg, conf.metadata.data(),
426                     static_cast<int>(conf.metadata.size()));
427 
428     log::info("Enable\n\tAse id: 0x{:x}\n\tMetadata: {}", conf.ase_id,
429               base::HexEncode(conf.metadata.data(), conf.metadata.size()));
430   }
431 
432   return true;
433 }
434 
PrepareAseCtpAudioReceiverStartReady(const std::vector<uint8_t> & ase_ids,std::vector<uint8_t> & value)435 bool PrepareAseCtpAudioReceiverStartReady(const std::vector<uint8_t>& ase_ids,
436                                           std::vector<uint8_t>& value) {
437   if (ase_ids.size() == 0) return false;
438   value.resize(ase_ids.size() * kAseIdSize + kAseNumSize + kCtpOpSize);
439 
440   uint8_t* msg = value.data();
441   UINT8_TO_STREAM(msg, kCtpOpcodeReceiverStartReady);
442   UINT8_TO_STREAM(msg, ase_ids.size());
443 
444   for (const uint8_t& id : ase_ids) {
445     UINT8_TO_STREAM(msg, id);
446 
447     log::info("ReceiverStartReady\n\tAse id: 0x{:x}", id);
448   }
449 
450   return true;
451 }
452 
PrepareAseCtpDisable(const std::vector<uint8_t> & ase_ids,std::vector<uint8_t> & value)453 bool PrepareAseCtpDisable(const std::vector<uint8_t>& ase_ids,
454                           std::vector<uint8_t>& value) {
455   if (ase_ids.size() == 0) return false;
456   value.resize(ase_ids.size() * kAseIdSize + kAseNumSize + kCtpOpSize);
457 
458   uint8_t* msg = value.data();
459   UINT8_TO_STREAM(msg, kCtpOpcodeDisable);
460   UINT8_TO_STREAM(msg, ase_ids.size());
461 
462   for (const uint8_t& id : ase_ids) {
463     UINT8_TO_STREAM(msg, id);
464 
465     log::info("Disable\n\tAse id: 0x{:x}", id);
466   }
467 
468   return true;
469 }
470 
PrepareAseCtpAudioReceiverStopReady(const std::vector<uint8_t> & ase_ids,std::vector<uint8_t> & value)471 bool PrepareAseCtpAudioReceiverStopReady(const std::vector<uint8_t>& ase_ids,
472                                          std::vector<uint8_t>& value) {
473   if (ase_ids.size() == 0) return false;
474   value.resize(ase_ids.size() * kAseIdSize + kAseNumSize + kCtpOpSize);
475 
476   uint8_t* msg = value.data();
477   UINT8_TO_STREAM(msg, kCtpOpcodeReceiverStopReady);
478   UINT8_TO_STREAM(msg, ase_ids.size());
479 
480   for (const uint8_t& ase_id : ase_ids) {
481     UINT8_TO_STREAM(msg, ase_id);
482 
483     log::info("ReceiverStopReady\n\tAse id: 0x{:x}", ase_id);
484   }
485 
486   return true;
487 }
488 
PrepareAseCtpUpdateMetadata(const std::vector<struct ctp_update_metadata> & confs,std::vector<uint8_t> & value)489 bool PrepareAseCtpUpdateMetadata(
490     const std::vector<struct ctp_update_metadata>& confs,
491     std::vector<uint8_t>& value) {
492   if (confs.size() == 0) return false;
493 
494   if (confs.size() > UINT8_MAX) {
495     log::error("To many ASEs to update metadata");
496     return false;
497   }
498 
499   uint16_t msg_len =
500       confs.size() * kCtpUpdateMetadataMinLen + kAseNumSize + kCtpOpSize;
501   for (auto& conf : confs) {
502     if (msg_len > GATT_MAX_ATTR_LEN) {
503       log::error("Message length above GATT maximum");
504       return false;
505     }
506     if (conf.metadata.size() > UINT8_MAX) {
507       log::error("ase[{}] metadata length is invalid", conf.ase_id);
508       return false;
509     }
510 
511     msg_len += conf.metadata.size();
512   }
513   value.resize(msg_len);
514 
515   uint8_t* msg = value.data();
516   UINT8_TO_STREAM(msg, kCtpOpcodeUpdateMetadata);
517   UINT8_TO_STREAM(msg, confs.size());
518 
519   for (const struct ctp_update_metadata& conf : confs) {
520     UINT8_TO_STREAM(msg, conf.ase_id);
521     UINT8_TO_STREAM(msg, conf.metadata.size());
522     ARRAY_TO_STREAM(msg, conf.metadata.data(),
523                     static_cast<int>(conf.metadata.size()));
524 
525     log::info("Update Metadata\n\tAse id: 0x{:x}\n\tMetadata: {}", conf.ase_id,
526               base::HexEncode(conf.metadata.data(), conf.metadata.size()));
527   }
528 
529   return true;
530 }
531 
PrepareAseCtpRelease(const std::vector<uint8_t> & ase_ids,std::vector<uint8_t> & value)532 bool PrepareAseCtpRelease(const std::vector<uint8_t>& ase_ids,
533                           std::vector<uint8_t>& value) {
534   if (ase_ids.size() == 0) return true;
535   value.resize(ase_ids.size() * kAseIdSize + kAseNumSize + kCtpOpSize);
536 
537   uint8_t* msg = value.data();
538   UINT8_TO_STREAM(msg, kCtpOpcodeRelease);
539   UINT8_TO_STREAM(msg, ase_ids.size());
540 
541   for (const uint8_t& ase_id : ase_ids) {
542     UINT8_TO_STREAM(msg, ase_id);
543 
544     log::info("Release\n\tAse id: 0x{:x}", ase_id);
545   }
546 
547   return true;
548 }
549 }  // namespace ascs
550 
551 namespace pacs {
552 
ParseSinglePac(std::vector<struct acs_ac_record> & pac_recs,uint16_t len,const uint8_t * value)553 int ParseSinglePac(std::vector<struct acs_ac_record>& pac_recs, uint16_t len,
554                    const uint8_t* value) {
555   struct acs_ac_record rec;
556   uint8_t codec_spec_cap_len, metadata_len;
557 
558   if (len < kAcsPacRecordMinLen) {
559     log::error("Wrong len of PAC record ({}!={})", len, kAcsPacRecordMinLen);
560     pac_recs.clear();
561     return -1;
562   }
563 
564   STREAM_TO_UINT8(rec.codec_id.coding_format, value);
565   STREAM_TO_UINT16(rec.codec_id.vendor_company_id, value);
566   STREAM_TO_UINT16(rec.codec_id.vendor_codec_id, value);
567   STREAM_TO_UINT8(codec_spec_cap_len, value);
568   len -= kAcsPacRecordMinLen - kAcsPacMetadataLenLen;
569 
570   if (len < codec_spec_cap_len + kAcsPacMetadataLenLen) {
571     log::error("Wrong len of PAC record (codec specific capabilities) ({}!={})",
572                len, codec_spec_cap_len + kAcsPacMetadataLenLen);
573     pac_recs.clear();
574     return -1;
575   }
576 
577   rec.codec_spec_caps_raw.assign(value, value + codec_spec_cap_len);
578 
579   if (utils::IsCodecUsingLtvFormat(rec.codec_id)) {
580     bool parsed;
581     rec.codec_spec_caps =
582         types::LeAudioLtvMap::Parse(value, codec_spec_cap_len, parsed);
583     if (!parsed) return -1;
584   }
585 
586   value += codec_spec_cap_len;
587   len -= codec_spec_cap_len;
588 
589   STREAM_TO_UINT8(metadata_len, value);
590   len -= kAcsPacMetadataLenLen;
591 
592   if (len < metadata_len) {
593     log::error("Wrong len of PAC record (metadata) ({}!={})", len,
594                metadata_len);
595     pac_recs.clear();
596     return -1;
597   }
598 
599   rec.metadata = std::vector<uint8_t>(value, value + metadata_len);
600   value += metadata_len;
601   len -= metadata_len;
602 
603   pac_recs.push_back(std::move(rec));
604 
605   return len;
606 }
607 
ParsePacs(std::vector<struct acs_ac_record> & pac_recs,uint16_t len,const uint8_t * value)608 bool ParsePacs(std::vector<struct acs_ac_record>& pac_recs, uint16_t len,
609                const uint8_t* value) {
610   if (len < kAcsPacDiscoverRspMinLen) {
611     log::error("Wrong len of PAC characteristic ({}!={})", len,
612                kAcsPacDiscoverRspMinLen);
613     return false;
614   }
615 
616   uint8_t pac_rec_nb;
617   STREAM_TO_UINT8(pac_rec_nb, value);
618   len -= kAcsPacDiscoverRspMinLen;
619 
620   pac_recs.reserve(pac_rec_nb);
621   for (int i = 0; i < pac_rec_nb; i++) {
622     int remaining_len = ParseSinglePac(pac_recs, len, value);
623     if (remaining_len < 0) return false;
624 
625     value += (len - remaining_len);
626     len = remaining_len;
627   }
628 
629   return true;
630 }
631 
ParseAudioLocations(types::AudioLocations & audio_locations,uint16_t len,const uint8_t * value)632 bool ParseAudioLocations(types::AudioLocations& audio_locations, uint16_t len,
633                          const uint8_t* value) {
634   if (len != kAudioLocationsRspMinLen) {
635     log::error("Wrong len of Audio Location characteristic");
636     return false;
637   }
638 
639   STREAM_TO_UINT32(audio_locations, value);
640 
641   log::info("Audio locations: {}", audio_locations.to_string());
642 
643   return true;
644 }
645 
ParseSupportedAudioContexts(types::BidirectionalPair<types::AudioContexts> & contexts,uint16_t len,const uint8_t * value)646 bool ParseSupportedAudioContexts(
647     types::BidirectionalPair<types::AudioContexts>& contexts, uint16_t len,
648     const uint8_t* value) {
649   if (len != kAseAudioSuppContRspMinLen) {
650     log::error("Wrong len of Audio Supported Context characteristic");
651     return false;
652   }
653 
654   STREAM_TO_UINT16(contexts.sink.value_ref(), value);
655   STREAM_TO_UINT16(contexts.source.value_ref(), value);
656 
657   log::info(
658       "Supported Audio Contexts: \n\tSupported Sink Contexts: {}\n\tSupported "
659       "Source Contexts: {}",
660       contexts.sink.to_string(), contexts.source.to_string());
661 
662   return true;
663 }
664 
ParseAvailableAudioContexts(types::BidirectionalPair<types::AudioContexts> & contexts,uint16_t len,const uint8_t * value)665 bool ParseAvailableAudioContexts(
666     types::BidirectionalPair<types::AudioContexts>& contexts, uint16_t len,
667     const uint8_t* value) {
668   if (len != kAseAudioAvailRspMinLen) {
669     log::error("Wrong len of Audio Availability characteristic");
670     return false;
671   }
672 
673   STREAM_TO_UINT16(contexts.sink.value_ref(), value);
674   STREAM_TO_UINT16(contexts.source.value_ref(), value);
675 
676   log::info(
677       "Available Audio Contexts: \n\tAvailable Sink Contexts: {}\n\tAvailable "
678       "Source Contexts: {}",
679       contexts.sink.to_string(), contexts.source.to_string());
680 
681   return true;
682 }
683 }  // namespace pacs
684 
685 namespace tmap {
686 
ParseTmapRole(std::bitset<16> & role,uint16_t len,const uint8_t * value)687 bool ParseTmapRole(std::bitset<16>& role, uint16_t len, const uint8_t* value) {
688   if (len != kTmapRoleLen) {
689     log::error(
690         ", Wrong len of Telephony Media Audio Profile Role, characteristic");
691     return false;
692   }
693 
694   STREAM_TO_UINT16(role, value);
695 
696   log::info(", Telephony Media Audio Profile Role:\n\tRole: {}",
697             role.to_string());
698 
699   return true;
700 }
701 }  // namespace tmap
702 
703 }  // namespace client_parser
704 }  // namespace bluetooth::le_audio
705