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