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