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