1use fidl_fuchsia_bluetooth as fidl_bt;
6use fidl_fuchsia_bluetooth_bredr::{
7 self as fidl_bredr, ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, ATTR_SERVICE_CLASS_ID_LIST,
8 ProfileDescriptor,
9};
10use fidl_table_validation::ValidFidlTable;
11#[cfg(target_os = "fuchsia")]
12use fuchsia_inspect as inspect;
13#[cfg(target_os = "fuchsia")]
14use fuchsia_inspect_derive::{AttachError, Inspect, Unit};
15use std::cmp::min;
16use std::collections::HashSet;
17
18use crate::assigned_numbers::AssignedNumber;
19use crate::assigned_numbers::constants::SERVICE_CLASS_UUIDS;
20use crate::error::Error;
21use crate::types::Uuid;
22
23pub mod avrcp;
25
26#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
28pub struct Psm(u16);
29
30impl Psm {
31 pub const RFCOMM: Self = Self(fidl_bredr::PSM_RFCOMM);
33 pub const HID_CONTROL: Self = Self(fidl_bredr::PSM_HID_CONTROL);
34 pub const HID_INTERRUPT: Self = Self(fidl_bredr::PSM_HID_INTERRUPT);
35 pub const AVDTP: Self = Self(fidl_bredr::PSM_AVDTP);
36 pub const AVCTP: Self = Self(fidl_bredr::PSM_AVCTP);
37 pub const AVCTP_BROWSE: Self = Self(fidl_bredr::PSM_AVCTP_BROWSE);
38 pub const DYNAMIC: Self = Self(fidl_bredr::PSM_DYNAMIC);
39
40 pub fn new(value: u16) -> Self {
41 Self(value)
42 }
43}
44
45impl From<Psm> for u16 {
46 fn from(src: Psm) -> u16 {
47 src.0
48 }
49}
50
51pub fn elem_to_profile_descriptor(elem: &fidl_bredr::DataElement) -> Option<ProfileDescriptor> {
54 if let fidl_bredr::DataElement::Sequence(seq) = elem {
55 if seq.len() != 2 {
56 return None;
57 }
58
59 let profile_id = match **seq[0].as_ref()? {
60 fidl_bredr::DataElement::Uuid(uuid) => {
61 let uuid: Uuid = uuid.into();
62 uuid.try_into().ok()?
63 }
64 _ => return None,
65 };
66
67 let [major_version, minor_version] = match **seq[1].as_ref()? {
68 fidl_bredr::DataElement::Uint16(val) => val.to_be_bytes(),
69 _ => return None,
70 };
71
72 return Some(ProfileDescriptor {
73 profile_id: Some(profile_id),
74 major_version: Some(major_version),
75 minor_version: Some(minor_version),
76 ..Default::default()
77 });
78 }
79 None
80}
81
82pub fn find_profile_descriptors(
87 attributes: &[fidl_bredr::Attribute],
88) -> Result<Vec<ProfileDescriptor>, Error> {
89 let attr = attributes
90 .iter()
91 .find(|a| a.id == Some(ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST))
92 .ok_or_else(|| Error::profile("missing profile descriptor"))?;
93
94 let Some(fidl_bredr::DataElement::Sequence(profiles)) = &attr.element else {
95 return Err(Error::profile("attribute element is invalidly formatted"));
96 };
97 let mut result = Vec::new();
98 for elem in profiles {
99 let elem = elem.as_ref().ok_or_else(|| Error::profile("null DataElement in sequence"))?;
100 result.push(
101 elem_to_profile_descriptor(&*elem)
102 .ok_or_else(|| Error::profile("couldn't convert to a ProfileDescriptor"))?,
103 );
104 }
105 if result.is_empty() { Err(Error::profile("no profile descriptor found")) } else { Ok(result) }
106}
107
108pub fn profile_descriptor_to_assigned(profile_desc: &ProfileDescriptor) -> Option<AssignedNumber> {
109 let Some(id) = profile_desc.profile_id else {
110 return None;
111 };
112 SERVICE_CLASS_UUIDS.iter().find(|scn| id.into_primitive() == scn.number).cloned()
113}
114
115pub fn psm_from_protocol(protocol: &Vec<ProtocolDescriptor>) -> Option<Psm> {
118 for descriptor in protocol {
119 if descriptor.protocol == fidl_bredr::ProtocolIdentifier::L2Cap {
120 if descriptor.params.len() != 1 {
121 return None;
122 }
123
124 if let DataElement::Uint16(psm) = descriptor.params[0] {
125 return Some(Psm::new(psm));
126 }
127 return None;
128 }
129 }
130 None
131}
132
133pub fn channel_number_from_protocol(
136 protocol: &Vec<fidl_bredr::ProtocolDescriptor>,
137) -> Result<i32, Error> {
138 for prot in protocol {
139 let Some(params) = prot.params.as_ref() else {
140 return Err(Error::profile("Invalid service definition"));
141 };
142 if prot.protocol == Some(fidl_bredr::ProtocolIdentifier::L2Cap) {
143 let [fidl_bredr::DataElement::Uint16(l2cap_port)] = params[..] else {
146 continue;
147 };
148 return Ok(l2cap_port.into());
149 }
150
151 if prot.protocol == Some(fidl_bredr::ProtocolIdentifier::Rfcomm) {
152 let [fidl_bredr::DataElement::Uint8(rfcomm_port)] = params[..] else {
154 return Err(Error::profile("Invalid RFCOMM service definition"));
155 };
156 return Ok(rfcomm_port.into());
157 }
158 }
159 Err(Error::profile("ProtocolDescriptor missing channel number"))
160}
161
162pub fn channel_number_from_parameters(
165 parameters: &fidl_bredr::ConnectParameters,
166) -> Result<i32, Error> {
167 match parameters {
168 fidl_bredr::ConnectParameters::Rfcomm(fidl_bredr::RfcommParameters {
169 channel: Some(port),
170 ..
171 }) => Ok((*port).into()),
172 fidl_bredr::ConnectParameters::L2cap(fidl_bredr::L2capParameters {
173 psm: Some(psm),
174 ..
175 }) => Ok((*psm).into()),
176 _ => Err(Error::profile(format!("Invalid parameters: {parameters:?}"))),
177 }
178}
179
180pub fn find_service_classes(
182 attributes: &[fidl_fuchsia_bluetooth_bredr::Attribute],
183) -> Vec<AssignedNumber> {
184 let uuids = find_all_service_classes(attributes);
185 SERVICE_CLASS_UUIDS
186 .iter()
187 .filter(|scn| uuids.contains(&Uuid::new16(scn.number)))
188 .cloned()
189 .collect()
190}
191
192pub fn find_all_service_classes(
194 attributes: &[fidl_fuchsia_bluetooth_bredr::Attribute],
195) -> Vec<Uuid> {
196 let Some(attr) = attributes.iter().find(|a| a.id == Some(ATTR_SERVICE_CLASS_ID_LIST)) else {
197 return vec![];
198 };
199 let Some(fidl_fuchsia_bluetooth_bredr::DataElement::Sequence(elems)) = &attr.element else {
200 return vec![];
201 };
202 elems
203 .iter()
204 .filter_map(|e| {
205 e.as_ref().and_then(|e| match **e {
206 fidl_fuchsia_bluetooth_bredr::DataElement::Uuid(uuid) => Some(uuid.into()),
207 _ => None,
208 })
209 })
210 .collect()
211}
212
213pub fn combine_security_requirements(
218 reqs: &SecurityRequirements,
219 other: &SecurityRequirements,
220) -> SecurityRequirements {
221 let authentication_required =
222 match (reqs.authentication_required, other.authentication_required) {
223 (Some(true), _) | (_, Some(true)) => Some(true),
224 (Some(x), None) | (None, Some(x)) => Some(x),
225 _ => None,
226 };
227 let secure_connections_required =
228 match (reqs.secure_connections_required, other.secure_connections_required) {
229 (Some(true), _) | (_, Some(true)) => Some(true),
230 (Some(x), None) | (None, Some(x)) => Some(x),
231 _ => None,
232 };
233 SecurityRequirements { authentication_required, secure_connections_required }
234}
235
236pub fn combine_channel_parameters(
242 params: &ChannelParameters,
243 other: &ChannelParameters,
244) -> ChannelParameters {
245 let channel_mode = match (params.channel_mode, other.channel_mode) {
246 (Some(fidl_bt::ChannelMode::Basic), _) | (_, Some(fidl_bt::ChannelMode::Basic)) => {
247 Some(fidl_bt::ChannelMode::Basic)
248 }
249 (Some(x), None) | (None, Some(x)) => Some(x),
250 _ => None,
251 };
252 let max_rx_sdu_size = match (params.max_rx_sdu_size, other.max_rx_sdu_size) {
253 (Some(rx1), Some(rx2)) => Some(min(rx1, rx2)),
254 (Some(x), None) | (None, Some(x)) => Some(x),
255 _ => None,
256 };
257 let security_requirements = match (¶ms.security_requirements, &other.security_requirements)
258 {
259 (Some(reqs1), Some(reqs2)) => Some(combine_security_requirements(reqs1, reqs2)),
260 (Some(reqs), _) | (_, Some(reqs)) => Some(reqs.clone()),
261 _ => None,
262 };
263 ChannelParameters { channel_mode, max_rx_sdu_size, security_requirements }
264}
265
266#[derive(Clone, Debug, Eq, PartialEq)]
271pub enum DataElement {
272 Int8(i8),
273 Int16(i16),
274 Int32(i32),
275 Int64(i64),
276 Uint8(u8),
277 Uint16(u16),
278 Uint32(u32),
279 Uint64(u64),
280 Str(Vec<u8>),
281 Url(String),
282 Uuid(fidl_bt::Uuid),
283 Bool(bool),
284 Sequence(Vec<Box<DataElement>>),
285 Alternatives(Vec<Box<DataElement>>),
286}
287
288impl std::hash::Hash for DataElement {
289 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
290 core::mem::discriminant(self).hash(state);
291 match self {
292 DataElement::Int8(x) => x.hash(state),
293 DataElement::Int16(x) => x.hash(state),
294 DataElement::Int32(x) => x.hash(state),
295 DataElement::Int64(x) => x.hash(state),
296 DataElement::Uint8(x) => x.hash(state),
297 DataElement::Uint16(x) => x.hash(state),
298 DataElement::Uint32(x) => x.hash(state),
299 DataElement::Uint64(x) => x.hash(state),
300 DataElement::Str(x) => x.hash(state),
301 DataElement::Url(x) => x.hash(state),
302 DataElement::Uuid(x) => x.value.hash(state),
303 DataElement::Bool(x) => x.hash(state),
304 DataElement::Sequence(x) => x.hash(state),
305 DataElement::Alternatives(x) => x.hash(state),
306 }
307 }
308}
309
310impl TryFrom<&fidl_bredr::DataElement> for DataElement {
311 type Error = Error;
312
313 fn try_from(src: &fidl_bredr::DataElement) -> Result<DataElement, Error> {
314 use fidl_bredr::DataElement as fDataElement;
315 let element = match src {
316 fDataElement::Int8(x) => DataElement::Int8(*x),
317 fDataElement::Int16(x) => DataElement::Int16(*x),
318 fDataElement::Int32(x) => DataElement::Int32(*x),
319 fDataElement::Int64(x) => DataElement::Int64(*x),
320 fDataElement::Uint8(x) => DataElement::Uint8(*x),
321 fDataElement::Uint16(x) => DataElement::Uint16(*x),
322 fDataElement::Uint32(x) => DataElement::Uint32(*x),
323 fDataElement::Uint64(x) => DataElement::Uint64(*x),
324 fDataElement::Str(v) => DataElement::Str(v.clone()),
326 fDataElement::Url(s) => DataElement::Url(s.to_string()),
327 fDataElement::Uuid(uuid) => DataElement::Uuid(uuid.clone()),
328 fDataElement::B(b) => DataElement::Bool(*b),
329 fDataElement::Sequence(x) => {
330 let mapped = x
331 .iter()
332 .filter_map(|opt| {
333 opt.as_ref().map(|t| match DataElement::try_from(&**t) {
334 Ok(elem) => Ok(Box::new(elem)),
335 Err(err) => Err(err),
336 })
337 })
338 .collect::<Result<Vec<_>, Error>>()?;
339 DataElement::Sequence(mapped)
340 }
341 fDataElement::Alternatives(x) => {
342 let mapped = x
343 .iter()
344 .filter_map(|opt| {
345 opt.as_ref().map(|t| match DataElement::try_from(&**t) {
346 Ok(elem) => Ok(Box::new(elem)),
347 Err(err) => Err(err),
348 })
349 })
350 .collect::<Result<Vec<_>, Error>>()?;
351 DataElement::Alternatives(mapped)
352 }
353 _ => return Err(Error::conversion("Unknown DataElement type")),
354 };
355 Ok(element)
356 }
357}
358
359impl From<&DataElement> for fidl_bredr::DataElement {
360 fn from(src: &DataElement) -> fidl_bredr::DataElement {
361 use fidl_bredr::DataElement as fDataElement;
362 match src {
363 DataElement::Int8(x) => fDataElement::Int8(*x),
364 DataElement::Int16(x) => fDataElement::Int16(*x),
365 DataElement::Int32(x) => fDataElement::Int32(*x),
366 DataElement::Int64(x) => fDataElement::Int64(*x),
367 DataElement::Uint8(x) => fDataElement::Uint8(*x),
368 DataElement::Uint16(x) => fDataElement::Uint16(*x),
369 DataElement::Uint32(x) => fDataElement::Uint32(*x),
370 DataElement::Uint64(x) => fDataElement::Uint64(*x),
371 DataElement::Str(v) => fDataElement::Str(v.clone()),
372 DataElement::Url(s) => fDataElement::Url(s.to_string()),
373 DataElement::Uuid(uuid) => fDataElement::Uuid(uuid.clone()),
374 DataElement::Bool(b) => fDataElement::B(*b),
375 DataElement::Sequence(x) => {
376 let mapped =
377 x.iter().map(|t| Some(Box::new(fDataElement::from(&**t)))).collect::<Vec<_>>();
378 fDataElement::Sequence(mapped)
379 }
380 DataElement::Alternatives(x) => {
381 let mapped =
382 x.iter().map(|t| Some(Box::new(fDataElement::from(&**t)))).collect::<Vec<_>>();
383 fDataElement::Alternatives(mapped)
384 }
385 }
386 }
387}
388
389#[derive(Debug, PartialEq)]
390pub struct DataElementConversionError {
391 pub data_element: DataElement,
392}
393
394macro_rules! generate_data_element_conversion {
396 ($variant: ident, $type: ty) => {
397 impl TryFrom<DataElement> for $type {
398 type Error = DataElementConversionError;
399
400 fn try_from(data_element: DataElement) -> Result<$type, DataElementConversionError> {
401 match data_element {
402 DataElement::$variant(x) => Ok(x),
403 _ => Err(DataElementConversionError { data_element }),
404 }
405 }
406 }
407
408 impl From<$type> for DataElement {
409 fn from(x: $type) -> DataElement {
410 DataElement::$variant(x)
411 }
412 }
413 };
414}
415
416generate_data_element_conversion!(Int8, i8);
418generate_data_element_conversion!(Int16, i16);
419generate_data_element_conversion!(Int32, i32);
420generate_data_element_conversion!(Int64, i64);
421generate_data_element_conversion!(Uint8, u8);
422generate_data_element_conversion!(Uint16, u16);
423generate_data_element_conversion!(Uint32, u32);
424generate_data_element_conversion!(Uint64, u64);
425generate_data_element_conversion!(Str, Vec<u8>);
426generate_data_element_conversion!(Uuid, fidl_bt::Uuid);
427generate_data_element_conversion!(Url, String);
428generate_data_element_conversion!(Bool, bool);
429
430#[derive(Clone, Debug, Eq, Hash, PartialEq)]
435pub struct ProtocolDescriptor {
436 pub protocol: fidl_bredr::ProtocolIdentifier,
437 pub params: Vec<DataElement>,
438}
439
440impl TryFrom<&fidl_bredr::ProtocolDescriptor> for ProtocolDescriptor {
441 type Error = Error;
442
443 fn try_from(src: &fidl_bredr::ProtocolDescriptor) -> Result<ProtocolDescriptor, Self::Error> {
444 let Some(protocol) = src.protocol else {
445 return Err(Error::missing("Missing ProtocolDescriptor.protocol"));
446 };
447 let params = src.params.as_ref().map_or(Ok(vec![]), |elems| {
448 elems
449 .iter()
450 .map(|elem| DataElement::try_from(elem))
451 .collect::<Result<Vec<DataElement>, Error>>()
452 })?;
453 Ok(ProtocolDescriptor { protocol, params })
454 }
455}
456
457impl From<&ProtocolDescriptor> for fidl_bredr::ProtocolDescriptor {
458 fn from(src: &ProtocolDescriptor) -> fidl_bredr::ProtocolDescriptor {
459 let params = src.params.iter().map(|elem| fidl_bredr::DataElement::from(elem)).collect();
460 fidl_bredr::ProtocolDescriptor {
461 protocol: Some(src.protocol),
462 params: Some(params),
463 ..Default::default()
464 }
465 }
466}
467
468pub fn l2cap_connect_parameters(
469 psm: Psm,
470 mode: fidl_bt::ChannelMode,
471) -> fidl_bredr::ConnectParameters {
472 fidl_bredr::ConnectParameters::L2cap(fidl_bredr::L2capParameters {
473 psm: Some(psm.into()),
474 parameters: Some(fidl_bt::ChannelParameters {
475 channel_mode: Some(mode),
476 ..fidl_bt::ChannelParameters::default()
477 }),
478 ..fidl_bredr::L2capParameters::default()
479 })
480}
481
482#[derive(Clone, Debug, Eq, Hash, PartialEq)]
487pub struct Attribute {
488 pub id: u16,
489 pub element: DataElement,
490}
491
492impl TryFrom<&fidl_bredr::Attribute> for Attribute {
493 type Error = Error;
494
495 fn try_from(src: &fidl_bredr::Attribute) -> Result<Attribute, Self::Error> {
496 let Some(id) = src.id else {
497 return Err(Error::missing("Attribute.id"));
498 };
499 let Some(element) = src.element.as_ref() else {
500 return Err(Error::missing("Attribute.element"));
501 };
502 let element = DataElement::try_from(element)?;
503 Ok(Attribute { id, element })
504 }
505}
506
507impl From<&Attribute> for fidl_bredr::Attribute {
508 fn from(src: &Attribute) -> fidl_bredr::Attribute {
509 fidl_bredr::Attribute {
510 id: Some(src.id),
511 element: Some(fidl_bredr::DataElement::from(&src.element)),
512 ..Default::default()
513 }
514 }
515}
516
517#[derive(Clone, Debug, Eq, Hash, PartialEq)]
522pub struct Information {
523 pub language: String,
524 pub name: Option<String>,
525 pub description: Option<String>,
526 pub provider: Option<String>,
527}
528
529impl TryFrom<&fidl_bredr::Information> for Information {
530 type Error = Error;
531
532 fn try_from(src: &fidl_bredr::Information) -> Result<Information, Self::Error> {
533 let language = match src.language.as_ref().map(String::as_str) {
534 None | Some("") => return Err(Error::missing("bredr.Information.language")),
535 Some(l) => l.to_string(),
536 };
537
538 Ok(Information {
539 language,
540 name: src.name.clone(),
541 description: src.description.clone(),
542 provider: src.provider.clone(),
543 })
544 }
545}
546
547impl TryFrom<&Information> for fidl_bredr::Information {
548 type Error = Error;
549
550 fn try_from(src: &Information) -> Result<fidl_bredr::Information, Self::Error> {
551 if src.language.is_empty() {
552 return Err(Error::missing("Information.language"));
553 }
554
555 Ok(fidl_bredr::Information {
556 language: Some(src.language.clone()),
557 name: src.name.clone(),
558 description: src.description.clone(),
559 provider: src.provider.clone(),
560 ..Default::default()
561 })
562 }
563}
564
565#[derive(Clone, Debug, Default, PartialEq)]
570pub struct ServiceDefinition {
571 pub service_class_uuids: Vec<Uuid>,
572 pub protocol_descriptor_list: Vec<ProtocolDescriptor>,
573 pub additional_protocol_descriptor_lists: Vec<Vec<ProtocolDescriptor>>,
574 pub profile_descriptors: Vec<fidl_bredr::ProfileDescriptor>,
575 pub information: Vec<Information>,
576 pub additional_attributes: Vec<Attribute>,
577}
578
579impl Eq for ServiceDefinition {}
580
581impl std::hash::Hash for ServiceDefinition {
582 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
583 self.service_class_uuids.hash(state);
584 self.protocol_descriptor_list.hash(state);
585 self.additional_protocol_descriptor_lists.hash(state);
586 for desc in &self.profile_descriptors {
588 desc.profile_id.hash(state);
589 desc.major_version.hash(state);
590 desc.minor_version.hash(state);
591 }
592 self.information.hash(state);
593 self.additional_attributes.hash(state);
594 }
595}
596
597impl ServiceDefinition {
598 pub fn try_into_fidl(this: &Vec<Self>) -> Result<Vec<fidl_bredr::ServiceDefinition>, Error> {
599 this.iter().map(fidl_bredr::ServiceDefinition::try_from).collect::<Result<Vec<_>, _>>()
600 }
601
602 pub fn try_from_fidl(src: &Vec<fidl_bredr::ServiceDefinition>) -> Result<Vec<Self>, Error> {
603 src.iter().map(Self::try_from).collect::<Result<Vec<_>, _>>()
604 }
605
606 pub fn primary_psm(&self) -> Option<Psm> {
608 psm_from_protocol(&self.protocol_descriptor_list)
609 }
610
611 pub fn additional_psms(&self) -> HashSet<Psm> {
613 self.additional_protocol_descriptor_lists
614 .iter()
615 .filter_map(|protocol| psm_from_protocol(protocol))
616 .collect()
617 }
618
619 pub fn goep_l2cap_psm(&self) -> Option<Psm> {
621 const GOEP_L2CAP_PSM_ATTRIBUTE: u16 = 0x0200;
622 let Some(attribute) =
623 self.additional_attributes.iter().find(|attr| attr.id == GOEP_L2CAP_PSM_ATTRIBUTE)
624 else {
625 return None;
626 };
627
628 let DataElement::Uint16(psm) = attribute.element else {
629 return None;
630 };
631
632 Some(Psm::new(psm))
633 }
634
635 pub fn psm_set(&self) -> HashSet<Psm> {
640 let mut psms = self.additional_psms();
641 if let Some(psm) = self.primary_psm() {
642 let _ = psms.insert(psm);
643 }
644 if let Some(psm) = self.goep_l2cap_psm() {
645 let _ = psms.insert(psm);
646 }
647
648 psms
649 }
650}
651
652impl TryFrom<&fidl_bredr::ServiceDefinition> for ServiceDefinition {
653 type Error = Error;
654
655 fn try_from(src: &fidl_bredr::ServiceDefinition) -> Result<ServiceDefinition, Self::Error> {
656 let service_class_uuids = match &src.service_class_uuids {
657 Some(uuids) if !uuids.is_empty() => uuids.iter().map(Uuid::from).collect(),
658 _ => {
659 return Err(Error::conversion(
660 "bredr.ServiceDefinition.service_class_uuids is empty",
661 ));
662 }
663 };
664
665 let protocol_descriptor_list: Vec<ProtocolDescriptor> =
666 src.protocol_descriptor_list.as_ref().map_or(Ok(vec![]), |p| {
667 p.iter()
668 .map(|d| ProtocolDescriptor::try_from(d))
669 .collect::<Result<Vec<ProtocolDescriptor>, Error>>()
670 })?;
671 let additional_protocol_descriptor_lists: Vec<Vec<ProtocolDescriptor>> =
672 src.additional_protocol_descriptor_lists.as_ref().map_or(Ok(vec![]), |desc_lists| {
673 desc_lists
674 .iter()
675 .map(|desc_list| {
676 desc_list.iter().map(|d| ProtocolDescriptor::try_from(d)).collect::<Result<
677 Vec<ProtocolDescriptor>,
678 Error,
679 >>(
680 )
681 })
682 .collect::<Result<Vec<Vec<ProtocolDescriptor>>, Error>>()
683 })?;
684 let profile_descriptors: Vec<fidl_bredr::ProfileDescriptor> =
685 src.profile_descriptors.clone().unwrap_or_default();
686 let information: Result<Vec<Information>, Error> = src
687 .information
688 .as_ref()
689 .map_or(Ok(vec![]), |infos| infos.iter().map(|i| Information::try_from(i)).collect());
690 let additional_attributes: Vec<Attribute> =
691 src.additional_attributes.as_ref().map_or(Ok(vec![]), |attrs| {
692 attrs
693 .iter()
694 .map(|a| Attribute::try_from(a))
695 .collect::<Result<Vec<Attribute>, Error>>()
696 })?;
697
698 Ok(ServiceDefinition {
699 service_class_uuids,
700 protocol_descriptor_list,
701 additional_protocol_descriptor_lists,
702 profile_descriptors,
703 information: information?,
704 additional_attributes,
705 })
706 }
707}
708
709impl TryFrom<&ServiceDefinition> for fidl_bredr::ServiceDefinition {
710 type Error = Error;
711
712 fn try_from(src: &ServiceDefinition) -> Result<fidl_bredr::ServiceDefinition, Self::Error> {
713 if src.service_class_uuids.is_empty() {
714 return Err(Error::conversion("ServiceDefinitions.service_class_uuids is empty"));
715 }
716 let service_class_uuids = src.service_class_uuids.iter().map(fidl_bt::Uuid::from).collect();
717
718 let protocol_descriptor_list: Vec<fidl_bredr::ProtocolDescriptor> = src
719 .protocol_descriptor_list
720 .iter()
721 .map(|d| fidl_bredr::ProtocolDescriptor::from(d))
722 .collect();
723 let additional_protocol_descriptor_lists: Vec<Vec<fidl_bredr::ProtocolDescriptor>> = src
724 .additional_protocol_descriptor_lists
725 .iter()
726 .map(|desc_list| {
727 desc_list.iter().map(|d| fidl_bredr::ProtocolDescriptor::from(d)).collect()
728 })
729 .collect();
730 let profile_descriptors: Vec<fidl_bredr::ProfileDescriptor> =
731 src.profile_descriptors.clone();
732 let information: Result<Vec<fidl_bredr::Information>, Error> =
733 src.information.iter().map(|i| fidl_bredr::Information::try_from(i)).collect();
734 let additional_attributes: Vec<fidl_bredr::Attribute> =
735 src.additional_attributes.iter().map(|a| fidl_bredr::Attribute::from(a)).collect();
736
737 Ok(fidl_bredr::ServiceDefinition {
738 service_class_uuids: Some(service_class_uuids),
739 protocol_descriptor_list: Some(protocol_descriptor_list),
740 additional_protocol_descriptor_lists: Some(additional_protocol_descriptor_lists),
741 profile_descriptors: Some(profile_descriptors),
742 information: Some(information?),
743 additional_attributes: Some(additional_attributes),
744 ..Default::default()
745 })
746 }
747}
748
749#[derive(Clone, Debug, Default, PartialEq)]
754pub struct SecurityRequirements {
755 pub authentication_required: Option<bool>,
756 pub secure_connections_required: Option<bool>,
757}
758
759impl From<&fidl_bt::SecurityRequirements> for SecurityRequirements {
760 fn from(src: &fidl_bt::SecurityRequirements) -> SecurityRequirements {
761 SecurityRequirements {
762 authentication_required: src.authentication_required,
763 secure_connections_required: src.secure_connections_required,
764 }
765 }
766}
767
768impl From<&SecurityRequirements> for fidl_bt::SecurityRequirements {
769 fn from(src: &SecurityRequirements) -> fidl_bt::SecurityRequirements {
770 fidl_bt::SecurityRequirements {
771 authentication_required: src.authentication_required,
772 secure_connections_required: src.secure_connections_required,
773 ..Default::default()
774 }
775 }
776}
777
778const MIN_RX_SDU_SIZE: u16 = 48;
781
782#[derive(Clone, Debug, Default, PartialEq)]
788pub struct ChannelParameters {
789 pub channel_mode: Option<fidl_bt::ChannelMode>,
790 pub max_rx_sdu_size: Option<u16>,
791 pub security_requirements: Option<SecurityRequirements>,
792}
793
794impl TryFrom<&fidl_bt::ChannelParameters> for ChannelParameters {
795 type Error = Error;
796
797 fn try_from(src: &fidl_bt::ChannelParameters) -> Result<ChannelParameters, Self::Error> {
798 if let Some(size) = src.max_rx_packet_size {
799 if size < MIN_RX_SDU_SIZE {
800 return Err(Error::conversion(format!(
801 "bredr.ChannelParameters.max_rx_sdu_size is too small: {size}"
802 )));
803 }
804 }
805
806 Ok(ChannelParameters {
807 channel_mode: src.channel_mode,
808 max_rx_sdu_size: src.max_rx_packet_size,
809 security_requirements: src
810 .security_requirements
811 .as_ref()
812 .map(SecurityRequirements::from),
813 })
814 }
815}
816
817impl TryFrom<&ChannelParameters> for fidl_bt::ChannelParameters {
818 type Error = Error;
819
820 fn try_from(src: &ChannelParameters) -> Result<fidl_bt::ChannelParameters, Self::Error> {
821 if let Some(size) = src.max_rx_sdu_size {
822 if size < MIN_RX_SDU_SIZE {
823 return Err(Error::conversion(format!(
824 "ChannelParameters.max_rx_sdu_size is too small: {size}"
825 )));
826 }
827 }
828
829 Ok(fidl_bt::ChannelParameters {
830 channel_mode: src.channel_mode,
831 max_rx_packet_size: src.max_rx_sdu_size,
832 security_requirements: src
833 .security_requirements
834 .as_ref()
835 .map(fidl_bt::SecurityRequirements::from),
836 ..Default::default()
837 })
838 }
839}
840
841#[derive(Debug, Clone, ValidFidlTable, PartialEq)]
842#[fidl_table_src(fidl_bredr::ScoConnectionParameters)]
843pub struct ValidScoConnectionParameters {
844 pub parameter_set: fidl_bredr::HfpParameterSet,
845 pub air_coding_format: fidl_bt::AssignedCodingFormat,
846 pub air_frame_size: u16,
847 pub io_bandwidth: u32,
848 pub io_coding_format: fidl_bt::AssignedCodingFormat,
849 pub io_frame_size: u16,
850 #[fidl_field_type(optional)]
851 pub io_pcm_data_format: Option<fidl_fuchsia_hardware_audio::SampleFormat>,
852 #[fidl_field_type(optional)]
853 pub io_pcm_sample_payload_msb_position: Option<u8>,
854 pub path: fidl_bredr::DataPath,
855}
856
857#[cfg(target_os = "fuchsia")]
858impl Unit for ValidScoConnectionParameters {
859 type Data = inspect::Node;
860 fn inspect_create(&self, parent: &inspect::Node, name: impl AsRef<str>) -> Self::Data {
861 let mut node = parent.create_child(name.as_ref());
862 self.inspect_update(&mut node);
863 node
864 }
865
866 fn inspect_update(&self, data: &mut Self::Data) {
867 data.record_string("parameter_set", &format!("{:?}", self.parameter_set));
868 data.record_string("air_coding_format", &format!("{:?}", self.air_coding_format));
869 data.record_uint("air_frame_size", self.air_frame_size.into());
870 data.record_uint("io_bandwidth", self.io_bandwidth.into());
871 data.record_string("io_coding_format", &format!("{:?}", self.io_coding_format));
872 data.record_uint("io_frame_size", self.io_frame_size.into());
873 if let Some(io_pcm_data_format) = &self.io_pcm_data_format {
874 data.record_string("io_pcm_data_format", &format!("{:?}", io_pcm_data_format));
875 }
876 if let Some(io_pcm_sample_payload_msb_position) = &self.io_pcm_sample_payload_msb_position {
877 data.record_uint(
878 "io_pcm_sample_payload_msb_position",
879 (*io_pcm_sample_payload_msb_position).into(),
880 );
881 }
882 data.record_string("path", &format!("{:?}", self.path));
883 }
884}
885
886#[cfg(target_os = "fuchsia")]
887impl Inspect for &mut ValidScoConnectionParameters {
888 fn iattach(self, parent: &inspect::Node, name: impl AsRef<str>) -> Result<(), AttachError> {
889 parent.record(self.inspect_create(parent, name));
891 Ok(())
892 }
893}
894
895#[cfg(test)]
896mod tests {
897 use super::*;
898 use diagnostics_assertions::assert_data_tree;
899 use std::collections::hash_map::DefaultHasher;
900 use std::hash::{Hash, Hasher};
901
902 #[test]
903 fn test_find_descriptors_fails_with_no_descriptors() {
904 assert!(find_profile_descriptors(&[]).is_err());
905
906 let mut attributes = vec![fidl_bredr::Attribute {
907 id: Some(0x3001),
908 element: Some(fidl_bredr::DataElement::Uint32(0xF00FC0DE)),
909 ..Default::default()
910 }];
911
912 assert!(find_profile_descriptors(&attributes).is_err());
913
914 attributes.push(fidl_bredr::Attribute {
916 id: Some(fidl_bredr::ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST),
917 element: Some(fidl_bredr::DataElement::Uint32(0xABADC0DE)),
918 ..Default::default()
919 });
920
921 assert!(find_profile_descriptors(&attributes).is_err());
922
923 attributes[1].element = Some(fidl_bredr::DataElement::Sequence(vec![]));
925
926 assert!(find_profile_descriptors(&attributes).is_err());
927 }
928
929 #[test]
930 fn test_find_descriptors_returns_descriptors() {
931 let attributes = vec![fidl_bredr::Attribute {
932 id: Some(fidl_bredr::ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST),
933 element: Some(fidl_bredr::DataElement::Sequence(vec![
934 Some(Box::new(fidl_bredr::DataElement::Sequence(vec![
935 Some(Box::new(fidl_bredr::DataElement::Uuid(Uuid::new16(0x1101).into()))),
936 Some(Box::new(fidl_bredr::DataElement::Uint16(0x0103))),
937 ]))),
938 Some(Box::new(fidl_bredr::DataElement::Sequence(vec![
939 Some(Box::new(fidl_bredr::DataElement::Uuid(Uuid::new16(0x113A).into()))),
940 Some(Box::new(fidl_bredr::DataElement::Uint16(0x0302))),
941 ]))),
942 ])),
943 ..Default::default()
944 }];
945
946 let result = find_profile_descriptors(&attributes);
947 assert!(result.is_ok());
948 let result = result.expect("result");
949 assert_eq!(2, result.len());
950
951 assert_eq!(
952 fidl_bredr::ServiceClassProfileIdentifier::SerialPort,
953 result[0].profile_id.unwrap()
954 );
955 assert_eq!(1, result[0].major_version.unwrap());
956 assert_eq!(3, result[0].minor_version.unwrap());
957 }
958
959 #[test]
960 fn test_find_service_classes_attribute_missing() {
961 assert_eq!(find_service_classes(&[]), Vec::new());
962 let attributes = vec![fidl_bredr::Attribute {
963 id: Some(fidl_bredr::ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST),
964 element: Some(fidl_bredr::DataElement::Sequence(vec![
965 Some(Box::new(fidl_bredr::DataElement::Sequence(vec![
966 Some(Box::new(fidl_bredr::DataElement::Uuid(Uuid::new16(0x1101).into()))),
967 Some(Box::new(fidl_bredr::DataElement::Uint16(0x0103))),
968 ]))),
969 Some(Box::new(fidl_bredr::DataElement::Sequence(vec![
970 Some(Box::new(fidl_bredr::DataElement::Uuid(Uuid::new16(0x113A).into()))),
971 Some(Box::new(fidl_bredr::DataElement::Uint16(0x0302))),
972 ]))),
973 ])),
974 ..Default::default()
975 }];
976 assert_eq!(find_service_classes(&attributes), Vec::new());
977 }
978
979 #[test]
980 fn test_find_service_classes_wrong_type() {
981 let attributes = vec![fidl_bredr::Attribute {
982 id: Some(fidl_bredr::ATTR_SERVICE_CLASS_ID_LIST),
983 element: Some(fidl_bredr::DataElement::Uint32(0xc0defae5u32)),
984 ..Default::default()
985 }];
986 assert_eq!(find_service_classes(&attributes), Vec::new());
987 }
988
989 #[test]
990 fn test_find_service_classes_returns_known_classes() {
991 let attribute = fidl_bredr::Attribute {
992 id: Some(fidl_bredr::ATTR_SERVICE_CLASS_ID_LIST),
993 element: Some(fidl_bredr::DataElement::Sequence(vec![Some(Box::new(
994 fidl_bredr::DataElement::Uuid(Uuid::new16(0x1101).into()),
995 ))])),
996 ..Default::default()
997 };
998
999 let result = find_service_classes(&[attribute]);
1000 assert_eq!(1, result.len());
1001 let assigned_num = result.first().unwrap();
1002 assert_eq!(0x1101, assigned_num.number); assert_eq!("SerialPort", assigned_num.name);
1004
1005 let unknown_uuids = fidl_bredr::Attribute {
1006 id: Some(fidl_bredr::ATTR_SERVICE_CLASS_ID_LIST),
1007 element: Some(fidl_bredr::DataElement::Sequence(vec![
1008 Some(Box::new(fidl_bredr::DataElement::Uuid(Uuid::new16(0x1101).into()))),
1009 Some(Box::new(fidl_bredr::DataElement::Uuid(Uuid::new16(0xc0de).into()))),
1010 ])),
1011 ..Default::default()
1012 };
1013
1014 let result = find_service_classes(&[unknown_uuids]);
1016 assert_eq!(1, result.len());
1017 let assigned_num = result.first().unwrap();
1018 assert_eq!(0x1101, assigned_num.number); assert_eq!("SerialPort", assigned_num.name);
1020 }
1021
1022 #[test]
1023 fn test_psm_from_protocol() {
1024 let empty = vec![];
1025 assert_eq!(None, psm_from_protocol(&empty));
1026
1027 let no_psm = vec![ProtocolDescriptor {
1028 protocol: fidl_bredr::ProtocolIdentifier::L2Cap,
1029 params: vec![],
1030 }];
1031 assert_eq!(None, psm_from_protocol(&no_psm));
1032
1033 let psm = Psm::new(10);
1034 let valid_psm = vec![ProtocolDescriptor {
1035 protocol: fidl_bredr::ProtocolIdentifier::L2Cap,
1036 params: vec![DataElement::Uint16(psm.into())],
1037 }];
1038 assert_eq!(Some(psm), psm_from_protocol(&valid_psm));
1039
1040 let rfcomm = vec![
1041 ProtocolDescriptor {
1042 protocol: fidl_bredr::ProtocolIdentifier::L2Cap,
1043 params: vec![], },
1045 ProtocolDescriptor {
1046 protocol: fidl_bredr::ProtocolIdentifier::Rfcomm,
1047 params: vec![DataElement::Uint8(10)], },
1049 ];
1050 assert_eq!(None, psm_from_protocol(&rfcomm));
1051 }
1052
1053 #[test]
1054 fn test_elem_to_profile_descriptor_works() {
1055 let element = fidl_bredr::DataElement::Sequence(vec![
1056 Some(Box::new(fidl_bredr::DataElement::Uuid(Uuid::new16(0x1101).into()))),
1057 Some(Box::new(fidl_bredr::DataElement::Uint16(0x0103))),
1058 ]);
1059
1060 let descriptor =
1061 elem_to_profile_descriptor(&element).expect("descriptor should be returned");
1062
1063 assert_eq!(
1064 fidl_bredr::ServiceClassProfileIdentifier::SerialPort,
1065 descriptor.profile_id.unwrap()
1066 );
1067 assert_eq!(1, descriptor.major_version.unwrap());
1068 assert_eq!(3, descriptor.minor_version.unwrap());
1069 }
1070
1071 #[test]
1072 fn test_elem_to_profile_descriptor_wrong_element_types() {
1073 let element = fidl_bredr::DataElement::Sequence(vec![
1074 Some(Box::new(fidl_bredr::DataElement::Uint16(0x1101))),
1075 Some(Box::new(fidl_bredr::DataElement::Uint16(0x0103))),
1076 ]);
1077 assert!(elem_to_profile_descriptor(&element).is_none());
1078
1079 let element = fidl_bredr::DataElement::Sequence(vec![
1080 Some(Box::new(fidl_bredr::DataElement::Uuid(Uuid::new16(0x1101).into()))),
1081 Some(Box::new(fidl_bredr::DataElement::Uint32(0x0103))),
1082 ]);
1083 assert!(elem_to_profile_descriptor(&element).is_none());
1084
1085 let element = fidl_bredr::DataElement::Sequence(vec![Some(Box::new(
1086 fidl_bredr::DataElement::Uint32(0x0103),
1087 ))]);
1088 assert!(elem_to_profile_descriptor(&element).is_none());
1089
1090 let element = fidl_bredr::DataElement::Sequence(vec![None]);
1091 assert!(elem_to_profile_descriptor(&element).is_none());
1092
1093 let element = fidl_bredr::DataElement::Uint32(0xDEADC0DE);
1094 assert!(elem_to_profile_descriptor(&element).is_none());
1095 }
1096
1097 #[test]
1098 fn test_invalid_information_fails_gracefully() {
1099 let empty_language = "".to_string();
1100
1101 let invalid_local = Information {
1102 language: empty_language.clone(),
1103 name: None,
1104 description: None,
1105 provider: None,
1106 };
1107 let fidl = fidl_bredr::Information::try_from(&invalid_local);
1108 assert!(fidl.is_err());
1109
1110 let local = Information::try_from(&fidl_bredr::Information::default());
1112 assert!(local.is_err());
1113
1114 let empty_lang_fidl =
1115 fidl_bredr::Information { language: Some(empty_language), ..Default::default() };
1116 let local = Information::try_from(&empty_lang_fidl);
1117 assert!(local.is_err());
1118 }
1119
1120 #[test]
1121 fn get_psm_from_empty_service_definition() {
1122 let def = ServiceDefinition {
1123 service_class_uuids: vec![Uuid::new32(1234)],
1124 protocol_descriptor_list: vec![],
1125 additional_protocol_descriptor_lists: vec![],
1126 profile_descriptors: vec![],
1127 information: vec![],
1128 additional_attributes: vec![],
1129 };
1130
1131 assert_eq!(def.primary_psm(), None);
1132 assert_eq!(def.additional_psms(), HashSet::new());
1133 assert_eq!(def.psm_set(), HashSet::new());
1134 }
1135
1136 #[test]
1137 fn test_get_psm_from_service_definition() {
1138 let uuid = Uuid::new32(1234);
1139 let psm1 = Psm(10);
1140 let psm2 = Psm(12);
1141 let psm3 = Psm(4000);
1142 let mut def = ServiceDefinition {
1143 service_class_uuids: vec![uuid],
1144 protocol_descriptor_list: vec![ProtocolDescriptor {
1145 protocol: fidl_bredr::ProtocolIdentifier::L2Cap,
1146 params: vec![DataElement::Uint16(psm1.into())],
1147 }],
1148 additional_protocol_descriptor_lists: vec![],
1149 profile_descriptors: vec![],
1150 information: vec![],
1151 additional_attributes: vec![],
1152 };
1153
1154 assert_eq!(def.primary_psm(), Some(psm1));
1156 assert_eq!(def.additional_psms(), HashSet::new());
1157 assert_eq!(def.psm_set(), HashSet::from([psm1]));
1158
1159 def.additional_protocol_descriptor_lists = vec![
1160 vec![ProtocolDescriptor {
1161 protocol: fidl_bredr::ProtocolIdentifier::L2Cap,
1162 params: vec![DataElement::Uint16(psm2.into())],
1163 }],
1164 vec![ProtocolDescriptor {
1165 protocol: fidl_bredr::ProtocolIdentifier::Avdtp,
1166 params: vec![DataElement::Uint16(0x0103)],
1167 }],
1168 ];
1169
1170 assert_eq!(def.primary_psm(), Some(psm1));
1172 assert_eq!(def.additional_psms(), HashSet::from([psm2]));
1173 assert_eq!(def.psm_set(), HashSet::from([psm1, psm2]));
1174
1175 def.additional_attributes =
1177 vec![Attribute { id: 0x0200, element: DataElement::Uint16(psm3.into()) }];
1178 assert_eq!(def.primary_psm(), Some(psm1));
1179 assert_eq!(def.additional_psms(), HashSet::from([psm2]));
1180 assert_eq!(def.goep_l2cap_psm(), Some(psm3));
1181 assert_eq!(def.psm_set(), HashSet::from([psm1, psm2, psm3]));
1182 }
1183
1184 #[test]
1185 fn test_service_definition_conversions() {
1186 let uuid = fidl_bt::Uuid { value: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] };
1187 let prof_descs = vec![ProfileDescriptor {
1188 profile_id: Some(fidl_bredr::ServiceClassProfileIdentifier::AvRemoteControl),
1189 major_version: Some(1),
1190 minor_version: Some(6),
1191 ..Default::default()
1192 }];
1193 let language = "en".to_string();
1194 let name = "foobar".to_string();
1195 let description = "fake".to_string();
1196 let provider = "random".to_string();
1197 let attribute_id = 0x3001;
1198 let attribute_value = 0xF00FC0DE;
1199
1200 let local = ServiceDefinition {
1201 service_class_uuids: vec![uuid.into()],
1202 protocol_descriptor_list: vec![ProtocolDescriptor {
1203 protocol: fidl_bredr::ProtocolIdentifier::L2Cap,
1204 params: vec![DataElement::Uint16(10)],
1205 }],
1206 additional_protocol_descriptor_lists: vec![
1207 vec![ProtocolDescriptor {
1208 protocol: fidl_bredr::ProtocolIdentifier::L2Cap,
1209 params: vec![DataElement::Uint16(12)],
1210 }],
1211 vec![ProtocolDescriptor {
1212 protocol: fidl_bredr::ProtocolIdentifier::Avdtp,
1213 params: vec![DataElement::Uint16(3)],
1214 }],
1215 ],
1216 profile_descriptors: prof_descs.clone(),
1217 information: vec![Information {
1218 language: language.clone(),
1219 name: Some(name.clone()),
1220 description: Some(description.clone()),
1221 provider: Some(provider.clone()),
1222 }],
1223 additional_attributes: vec![Attribute {
1224 id: attribute_id,
1225 element: DataElement::Sequence(vec![Box::new(DataElement::Uint32(
1226 attribute_value,
1227 ))]),
1228 }],
1229 };
1230
1231 let fidl = fidl_bredr::ServiceDefinition {
1232 service_class_uuids: Some(vec![uuid]),
1233 protocol_descriptor_list: Some(vec![fidl_bredr::ProtocolDescriptor {
1234 protocol: Some(fidl_bredr::ProtocolIdentifier::L2Cap),
1235 params: Some(vec![fidl_bredr::DataElement::Uint16(10)]),
1236 ..Default::default()
1237 }]),
1238 additional_protocol_descriptor_lists: Some(vec![
1239 vec![fidl_bredr::ProtocolDescriptor {
1240 protocol: Some(fidl_bredr::ProtocolIdentifier::L2Cap),
1241 params: Some(vec![fidl_bredr::DataElement::Uint16(12)]),
1242 ..Default::default()
1243 }],
1244 vec![fidl_bredr::ProtocolDescriptor {
1245 protocol: Some(fidl_bredr::ProtocolIdentifier::Avdtp),
1246 params: Some(vec![fidl_bredr::DataElement::Uint16(3)]),
1247 ..Default::default()
1248 }],
1249 ]),
1250 profile_descriptors: Some(prof_descs.clone()),
1251 information: Some(vec![fidl_bredr::Information {
1252 language: Some(language.clone()),
1253 name: Some(name.clone()),
1254 description: Some(description.clone()),
1255 provider: Some(provider.clone()),
1256 ..Default::default()
1257 }]),
1258 additional_attributes: Some(vec![fidl_bredr::Attribute {
1259 id: Some(attribute_id),
1260 element: Some(fidl_bredr::DataElement::Sequence(vec![Some(Box::new(
1261 fidl_bredr::DataElement::Uint32(attribute_value),
1262 ))])),
1263 ..Default::default()
1264 }]),
1265 ..Default::default()
1266 };
1267
1268 let local_to_fidl: fidl_bredr::ServiceDefinition =
1270 fidl_bredr::ServiceDefinition::try_from(&local).expect("should work");
1271 assert_eq!(local_to_fidl, fidl);
1272
1273 let fidl_to_local: ServiceDefinition =
1275 ServiceDefinition::try_from(&fidl).expect("should work");
1276 assert_eq!(fidl_to_local, local);
1277 }
1278
1279 #[test]
1280 fn test_invalid_service_definition_fails_gracefully() {
1281 let no_uuids_fidl = fidl_bredr::ServiceDefinition::default();
1282 let fidl_to_local = ServiceDefinition::try_from(&no_uuids_fidl);
1283 assert!(fidl_to_local.is_err());
1284
1285 let empty_uuids_fidl = fidl_bredr::ServiceDefinition {
1286 service_class_uuids: Some(vec![]),
1287 ..Default::default()
1288 };
1289 let fidl_to_local = ServiceDefinition::try_from(&empty_uuids_fidl);
1290 assert!(fidl_to_local.is_err());
1291 }
1292
1293 #[test]
1294 fn test_channel_parameters_conversions() {
1295 let channel_mode = Some(fidl_bt::ChannelMode::EnhancedRetransmission);
1296 let max_rx_sdu_size = Some(MIN_RX_SDU_SIZE);
1297
1298 let local =
1299 ChannelParameters { channel_mode, max_rx_sdu_size, security_requirements: None };
1300 let fidl = fidl_bt::ChannelParameters {
1301 channel_mode,
1302 max_rx_packet_size: max_rx_sdu_size,
1303 ..Default::default()
1304 };
1305
1306 let local_to_fidl =
1307 fidl_bt::ChannelParameters::try_from(&local).expect("conversion should work");
1308 assert_eq!(local_to_fidl, fidl);
1309
1310 let fidl_to_local = ChannelParameters::try_from(&fidl).expect("conversion should work");
1311 assert_eq!(fidl_to_local, local);
1312
1313 let fidl = fidl_bt::ChannelParameters::default();
1315 let expected = ChannelParameters {
1316 channel_mode: None,
1317 max_rx_sdu_size: None,
1318 security_requirements: None,
1319 };
1320
1321 let fidl_to_local = ChannelParameters::try_from(&fidl).expect("conversion should work");
1322 assert_eq!(fidl_to_local, expected);
1323 }
1324
1325 #[test]
1326 fn test_invalid_channel_parameters_fails_gracefully() {
1327 let too_small_sdu = Some(MIN_RX_SDU_SIZE - 1);
1328 let local = ChannelParameters {
1329 channel_mode: None,
1330 max_rx_sdu_size: too_small_sdu,
1331 security_requirements: None,
1332 };
1333 let fidl =
1334 fidl_bt::ChannelParameters { max_rx_packet_size: too_small_sdu, ..Default::default() };
1335
1336 let local_to_fidl = fidl_bt::ChannelParameters::try_from(&local);
1337 assert!(local_to_fidl.is_err());
1338
1339 let fidl_to_local = ChannelParameters::try_from(&fidl);
1340 assert!(fidl_to_local.is_err());
1341 }
1342
1343 #[test]
1344 fn test_security_requirements_conversions() {
1345 let authentication_required = Some(false);
1346 let secure_connections_required = Some(true);
1347
1348 let local = SecurityRequirements { authentication_required, secure_connections_required };
1349 let fidl = fidl_bt::SecurityRequirements {
1350 authentication_required,
1351 secure_connections_required,
1352 ..Default::default()
1353 };
1354
1355 let local_to_fidl = fidl_bt::SecurityRequirements::from(&local);
1356 assert_eq!(local_to_fidl, fidl);
1357
1358 let fidl_to_local = SecurityRequirements::from(&fidl);
1359 assert_eq!(fidl_to_local, local);
1360 }
1361
1362 #[test]
1363 fn test_combine_security_requirements() {
1364 let req1 = SecurityRequirements {
1365 authentication_required: None,
1366 secure_connections_required: None,
1367 };
1368 let req2 = SecurityRequirements {
1369 authentication_required: None,
1370 secure_connections_required: None,
1371 };
1372 let expected = SecurityRequirements {
1373 authentication_required: None,
1374 secure_connections_required: None,
1375 };
1376 assert_eq!(combine_security_requirements(&req1, &req2), expected);
1377
1378 let req1 = SecurityRequirements {
1379 authentication_required: Some(true),
1380 secure_connections_required: None,
1381 };
1382 let req2 = SecurityRequirements {
1383 authentication_required: None,
1384 secure_connections_required: Some(true),
1385 };
1386 let expected = SecurityRequirements {
1387 authentication_required: Some(true),
1388 secure_connections_required: Some(true),
1389 };
1390 assert_eq!(combine_security_requirements(&req1, &req2), expected);
1391
1392 let req1 = SecurityRequirements {
1393 authentication_required: Some(false),
1394 secure_connections_required: Some(true),
1395 };
1396 let req2 = SecurityRequirements {
1397 authentication_required: None,
1398 secure_connections_required: Some(true),
1399 };
1400 let expected = SecurityRequirements {
1401 authentication_required: Some(false),
1402 secure_connections_required: Some(true),
1403 };
1404 assert_eq!(combine_security_requirements(&req1, &req2), expected);
1405
1406 let req1 = SecurityRequirements {
1407 authentication_required: Some(true),
1408 secure_connections_required: Some(false),
1409 };
1410 let req2 = SecurityRequirements {
1411 authentication_required: Some(false),
1412 secure_connections_required: Some(true),
1413 };
1414 let expected = SecurityRequirements {
1415 authentication_required: Some(true),
1416 secure_connections_required: Some(true),
1417 };
1418 assert_eq!(combine_security_requirements(&req1, &req2), expected);
1419 }
1420
1421 #[test]
1422 fn test_combine_channel_parameters() {
1423 let p1 = ChannelParameters::default();
1424 let p2 = ChannelParameters::default();
1425 let expected = ChannelParameters::default();
1426 assert_eq!(combine_channel_parameters(&p1, &p2), expected);
1427
1428 let p1 = ChannelParameters {
1429 channel_mode: Some(fidl_bt::ChannelMode::EnhancedRetransmission),
1430 max_rx_sdu_size: None,
1431 security_requirements: None,
1432 };
1433 let p2 = ChannelParameters {
1434 channel_mode: Some(fidl_bt::ChannelMode::Basic),
1435 max_rx_sdu_size: Some(70),
1436 security_requirements: None,
1437 };
1438 let expected = ChannelParameters {
1439 channel_mode: Some(fidl_bt::ChannelMode::Basic),
1440 max_rx_sdu_size: Some(70),
1441 security_requirements: None,
1442 };
1443 assert_eq!(combine_channel_parameters(&p1, &p2), expected);
1444
1445 let empty_seq_reqs = SecurityRequirements::default();
1446 let p1 = ChannelParameters {
1447 channel_mode: None,
1448 max_rx_sdu_size: Some(75),
1449 security_requirements: Some(empty_seq_reqs.clone()),
1450 };
1451 let p2 = ChannelParameters {
1452 channel_mode: Some(fidl_bt::ChannelMode::EnhancedRetransmission),
1453 max_rx_sdu_size: None,
1454 security_requirements: None,
1455 };
1456 let expected = ChannelParameters {
1457 channel_mode: Some(fidl_bt::ChannelMode::EnhancedRetransmission),
1458 max_rx_sdu_size: Some(75),
1459 security_requirements: Some(empty_seq_reqs),
1460 };
1461 assert_eq!(combine_channel_parameters(&p1, &p2), expected);
1462
1463 let reqs1 = SecurityRequirements {
1464 authentication_required: Some(true),
1465 secure_connections_required: None,
1466 };
1467 let reqs2 = SecurityRequirements {
1468 authentication_required: Some(false),
1469 secure_connections_required: Some(false),
1470 };
1471 let combined_reqs = combine_security_requirements(&reqs1, &reqs2);
1472 let p1 = ChannelParameters {
1473 channel_mode: None,
1474 max_rx_sdu_size: Some(90),
1475 security_requirements: Some(reqs1),
1476 };
1477 let p2 = ChannelParameters {
1478 channel_mode: Some(fidl_bt::ChannelMode::Basic),
1479 max_rx_sdu_size: Some(70),
1480 security_requirements: Some(reqs2),
1481 };
1482 let expected = ChannelParameters {
1483 channel_mode: Some(fidl_bt::ChannelMode::Basic),
1484 max_rx_sdu_size: Some(70),
1485 security_requirements: Some(combined_reqs),
1486 };
1487 assert_eq!(combine_channel_parameters(&p1, &p2), expected);
1488 }
1489
1490 #[fuchsia::test]
1491 async fn local_sco_parameters_inspect_tree() {
1492 let inspect = inspect::Inspector::default();
1493 assert_data_tree!(inspect, root: {});
1494
1495 let params = fidl_bredr::ScoConnectionParameters {
1496 parameter_set: Some(fidl_bredr::HfpParameterSet::D1),
1497 air_coding_format: Some(fidl_bt::AssignedCodingFormat::Cvsd),
1498 air_frame_size: Some(60),
1499 io_bandwidth: Some(16000),
1500 io_coding_format: Some(fidl_bt::AssignedCodingFormat::LinearPcm),
1501 io_frame_size: Some(16),
1502 io_pcm_data_format: Some(fidl_fuchsia_hardware_audio::SampleFormat::PcmSigned),
1503 io_pcm_sample_payload_msb_position: Some(1),
1504 path: Some(fidl_bredr::DataPath::Offload),
1505 ..Default::default()
1506 };
1507
1508 let mut local: ValidScoConnectionParameters = params.try_into().expect("can convert");
1509 assert_data_tree!(inspect, root: {});
1510
1511 let _ = local.iattach(&inspect.root(), "state").expect("can attach inspect");
1512 assert_data_tree!(inspect, root: {
1513 state: {
1514 parameter_set: "D1",
1515 air_coding_format: "Cvsd",
1516 air_frame_size: 60u64,
1517 io_bandwidth: 16000u64,
1518 io_coding_format: "LinearPcm",
1519 io_frame_size: 16u64,
1520 io_pcm_data_format: "PcmSigned",
1521 io_pcm_sample_payload_msb_position: 1u64,
1522 path: "Offload",
1523 }
1524 });
1525 }
1526
1527 #[test]
1528 fn data_element_primitve_conversions() {
1529 type Result<T> = std::result::Result<T, DataElementConversionError>;
1530
1531 let rust_u8 = 8u8;
1532 let data_element_uint8 = DataElement::Uint8(8u8);
1533 let data_element_uint8_into: DataElement = rust_u8.into();
1534 let rust_u8_ok: Result<u8> = data_element_uint8.clone().try_into();
1535 let rust_u8_err: Result<u16> = data_element_uint8.clone().try_into();
1536 assert_eq!(data_element_uint8_into, data_element_uint8);
1537 assert_eq!(rust_u8_ok, Ok(rust_u8));
1538 assert_eq!(
1539 rust_u8_err,
1540 Err(DataElementConversionError { data_element: data_element_uint8 })
1541 );
1542
1543 let rust_i8 = 9i8;
1544 let data_element_int8 = DataElement::Int8(9i8);
1545 let data_element_int8_into: DataElement = rust_i8.into();
1546 let rust_i8_ok: Result<i8> = data_element_int8.clone().try_into();
1547 let rust_i8_err: Result<u16> = data_element_int8.clone().try_into();
1548 assert_eq!(data_element_int8_into, data_element_int8);
1549 assert_eq!(rust_i8_ok, Ok(rust_i8));
1550 assert_eq!(
1551 rust_i8_err,
1552 Err(DataElementConversionError { data_element: data_element_int8 })
1553 );
1554
1555 let rust_u16 = 16u16;
1556 let data_element_uint16 = DataElement::Uint16(16u16);
1557 let data_element_uint16_into: DataElement = rust_u16.into();
1558 let rust_u16_ok: Result<u16> = data_element_uint16.clone().try_into();
1559 let rust_u16_err: Result<i16> = data_element_uint16.clone().try_into();
1560 assert_eq!(data_element_uint16_into, data_element_uint16);
1561 assert_eq!(rust_u16_ok, Ok(rust_u16));
1562 assert_eq!(
1563 rust_u16_err,
1564 Err(DataElementConversionError { data_element: data_element_uint16 })
1565 );
1566
1567 let rust_i16 = 17i16;
1568 let data_element_int16 = DataElement::Int16(17i16);
1569 let data_element_int16_into: DataElement = rust_i16.into();
1570 let rust_i16_ok: Result<i16> = data_element_int16.clone().try_into();
1571 let rust_i16_err: Result<u16> = data_element_int16.clone().try_into();
1572 assert_eq!(data_element_int16_into, data_element_int16);
1573 assert_eq!(rust_i16_ok, Ok(rust_i16));
1574 assert_eq!(
1575 rust_i16_err,
1576 Err(DataElementConversionError { data_element: data_element_int16 })
1577 );
1578
1579 let rust_u32 = 32u32;
1580 let data_element_uint32 = DataElement::Uint32(32u32);
1581 let data_element_uint32_into: DataElement = rust_u32.into();
1582 let rust_u32_ok: Result<u32> = data_element_uint32.clone().try_into();
1583 let rust_u32_err: Result<u16> = data_element_uint32.clone().try_into();
1584 assert_eq!(data_element_uint32_into, data_element_uint32);
1585 assert_eq!(rust_u32_ok, Ok(rust_u32));
1586 assert_eq!(
1587 rust_u32_err,
1588 Err(DataElementConversionError { data_element: data_element_uint32 })
1589 );
1590
1591 let rust_i32 = 33i32;
1592 let data_element_int32 = DataElement::Int32(33i32);
1593 let data_element_int32_into: DataElement = rust_i32.into();
1594 let rust_i32_ok: Result<i32> = data_element_int32.clone().try_into();
1595 let rust_i32_err: Result<u16> = data_element_int32.clone().try_into();
1596 assert_eq!(data_element_int32_into, data_element_int32);
1597 assert_eq!(rust_i32_ok, Ok(rust_i32));
1598 assert_eq!(
1599 rust_i32_err,
1600 Err(DataElementConversionError { data_element: data_element_int32 })
1601 );
1602
1603 let rust_u64 = 64u64;
1604 let data_element_uint64 = DataElement::Uint64(64u64);
1605 let data_element_uint64_into: DataElement = rust_u64.into();
1606 let rust_u64_ok: Result<u64> = data_element_uint64.clone().try_into();
1607 let rust_u64_err: Result<u16> = data_element_uint64.clone().try_into();
1608 assert_eq!(data_element_uint64_into, data_element_uint64);
1609 assert_eq!(rust_u64_ok, Ok(rust_u64));
1610 assert_eq!(
1611 rust_u64_err,
1612 Err(DataElementConversionError { data_element: data_element_uint64 })
1613 );
1614
1615 let rust_i64 = 65i64;
1616 let data_element_int64 = DataElement::Int64(65i64);
1617 let data_element_int64_into: DataElement = rust_i64.into();
1618 let rust_i64_ok: Result<i64> = data_element_int64.clone().try_into();
1619 let rust_i64_err: Result<u16> = data_element_int64.clone().try_into();
1620 assert_eq!(data_element_int64_into, data_element_int64);
1621 assert_eq!(rust_i64_ok, Ok(rust_i64));
1622 assert_eq!(
1623 rust_i64_err,
1624 Err(DataElementConversionError { data_element: data_element_int64 })
1625 );
1626
1627 let rust_vec = "ABC".as_bytes().to_vec();
1628 let data_element_str = DataElement::Str("ABC".as_bytes().to_vec());
1629 let data_element_str_into: DataElement = rust_vec.clone().into();
1630 let rust_vec_ok: Result<Vec<u8>> = data_element_str.clone().try_into();
1631 let rust_vec_err: Result<u16> = data_element_str.clone().try_into();
1632 assert_eq!(data_element_str_into, data_element_str);
1633 assert_eq!(rust_vec_ok, Ok(rust_vec));
1634 assert_eq!(
1635 rust_vec_err,
1636 Err(DataElementConversionError { data_element: data_element_str })
1637 );
1638
1639 let rust_uuid: fidl_bt::Uuid = Uuid::new16(0x1101).into();
1640 let data_element_uuid = DataElement::Uuid(Uuid::new16(0x1101).into());
1641 let data_element_uuid_into: DataElement = rust_uuid.clone().into();
1642 let rust_uuid_ok: Result<fidl_bt::Uuid> = data_element_uuid.clone().try_into();
1643 let rust_uuid_err: Result<u16> = data_element_uuid.clone().try_into();
1644 assert_eq!(data_element_uuid_into, data_element_uuid);
1645 assert_eq!(rust_uuid_ok, Ok(rust_uuid));
1646 assert_eq!(
1647 rust_uuid_err,
1648 Err(DataElementConversionError { data_element: data_element_uuid })
1649 );
1650
1651 let rust_string = String::from("ABC");
1652 let data_element_url = DataElement::Url(String::from("ABC"));
1653 let data_element_url_into: DataElement = rust_string.clone().into();
1654 let rust_string_ok: Result<String> = data_element_url.clone().try_into();
1655 let rust_string_err: Result<u16> = data_element_url.clone().try_into();
1656 assert_eq!(data_element_url_into, data_element_url);
1657 assert_eq!(rust_string_ok, Ok(rust_string));
1658 assert_eq!(
1659 rust_string_err,
1660 Err(DataElementConversionError { data_element: data_element_url })
1661 );
1662
1663 let rust_bool = true;
1664 let data_element_bool = DataElement::Bool(true);
1665 let data_element_bool_into: DataElement = rust_bool.into();
1666 let rust_bool_ok: Result<bool> = data_element_bool.clone().try_into();
1667 let rust_bool_err: Result<u16> = data_element_bool.clone().try_into();
1668 assert_eq!(data_element_bool_into, data_element_bool);
1669 assert_eq!(rust_bool_ok, Ok(rust_bool));
1670 assert_eq!(
1671 rust_bool_err,
1672 Err(DataElementConversionError { data_element: data_element_bool })
1673 );
1674 }
1675
1676 #[test]
1677 fn test_find_service_class_uuids() {
1678 assert_eq!(find_all_service_classes(&[]), Vec::<Uuid>::new());
1680
1681 let attributes = vec![fidl_bredr::Attribute {
1683 id: Some(fidl_bredr::ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST),
1684 element: Some(fidl_bredr::DataElement::Sequence(vec![Some(Box::new(
1685 fidl_bredr::DataElement::Uuid(Uuid::new16(0x1101).into()),
1686 ))])),
1687 ..Default::default()
1688 }];
1689 assert_eq!(find_all_service_classes(&attributes), Vec::<Uuid>::new());
1690
1691 let attributes = vec![fidl_bredr::Attribute {
1693 id: Some(fidl_bredr::ATTR_SERVICE_CLASS_ID_LIST),
1694 element: Some(fidl_bredr::DataElement::Uint32(0xc0defae5u32)),
1695 ..Default::default()
1696 }];
1697 assert_eq!(find_all_service_classes(&attributes), Vec::<Uuid>::new());
1698
1699 let uuid1 = Uuid::new16(0x1101);
1701 let uuid2 = Uuid::from_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
1702 let attribute = fidl_bredr::Attribute {
1703 id: Some(fidl_bredr::ATTR_SERVICE_CLASS_ID_LIST),
1704 element: Some(fidl_bredr::DataElement::Sequence(vec![
1705 Some(Box::new(fidl_bredr::DataElement::Uuid(uuid1.into()))),
1706 Some(Box::new(fidl_bredr::DataElement::Uint16(5))), Some(Box::new(fidl_bredr::DataElement::Uuid(uuid2.into()))),
1708 None, ])),
1710 ..Default::default()
1711 };
1712
1713 let result = find_all_service_classes(&[attribute]);
1714 assert_eq!(vec![uuid1, uuid2], result);
1715 }
1716
1717 #[test]
1718 fn test_channel_number_from_protocol() {
1719 let l2cap_only = vec![fidl_bredr::ProtocolDescriptor {
1721 protocol: Some(fidl_bredr::ProtocolIdentifier::L2Cap),
1722 params: Some(vec![fidl_bredr::DataElement::Uint16(42)]),
1723 ..Default::default()
1724 }];
1725 assert_eq!(channel_number_from_protocol(&l2cap_only).unwrap(), 42);
1726
1727 let rfcomm = vec![
1729 fidl_bredr::ProtocolDescriptor {
1730 protocol: Some(fidl_bredr::ProtocolIdentifier::L2Cap),
1731 params: Some(vec![]), ..Default::default()
1733 },
1734 fidl_bredr::ProtocolDescriptor {
1735 protocol: Some(fidl_bredr::ProtocolIdentifier::Rfcomm),
1736 params: Some(vec![fidl_bredr::DataElement::Uint8(5)]),
1737 ..Default::default()
1738 },
1739 ];
1740 assert_eq!(channel_number_from_protocol(&rfcomm).unwrap(), 5);
1741
1742 let l2cap_invalid = vec![fidl_bredr::ProtocolDescriptor {
1744 protocol: Some(fidl_bredr::ProtocolIdentifier::L2Cap),
1745 params: Some(vec![]),
1746 ..Default::default()
1747 }];
1748 assert!(channel_number_from_protocol(&l2cap_invalid).is_err());
1749
1750 let rfcomm_invalid = vec![
1752 fidl_bredr::ProtocolDescriptor {
1753 protocol: Some(fidl_bredr::ProtocolIdentifier::L2Cap),
1754 params: Some(vec![]),
1755 ..Default::default()
1756 },
1757 fidl_bredr::ProtocolDescriptor {
1758 protocol: Some(fidl_bredr::ProtocolIdentifier::Rfcomm),
1759 params: Some(vec![]),
1760 ..Default::default()
1761 },
1762 ];
1763 assert!(channel_number_from_protocol(&rfcomm_invalid).is_err());
1764
1765 let rfcomm_wrong_type = vec![
1767 fidl_bredr::ProtocolDescriptor {
1768 protocol: Some(fidl_bredr::ProtocolIdentifier::L2Cap),
1769 params: Some(vec![]),
1770 ..Default::default()
1771 },
1772 fidl_bredr::ProtocolDescriptor {
1773 protocol: Some(fidl_bredr::ProtocolIdentifier::Rfcomm),
1774 params: Some(vec![fidl_bredr::DataElement::Uint16(5)]),
1775 ..Default::default()
1776 },
1777 ];
1778 assert!(channel_number_from_protocol(&rfcomm_wrong_type).is_err());
1779
1780 assert!(channel_number_from_protocol(&vec![]).is_err());
1782 }
1783
1784 #[test]
1785 fn test_channel_number_from_parameters() {
1786 let rfcomm = fidl_bredr::ConnectParameters::Rfcomm(fidl_bredr::RfcommParameters {
1788 channel: Some(7),
1789 ..Default::default()
1790 });
1791 assert_eq!(channel_number_from_parameters(&rfcomm).unwrap(), 7);
1792
1793 let l2cap = fidl_bredr::ConnectParameters::L2cap(fidl_bredr::L2capParameters {
1795 psm: Some(42),
1796 ..Default::default()
1797 });
1798 assert_eq!(channel_number_from_parameters(&l2cap).unwrap(), 42);
1799
1800 let rfcomm_invalid = fidl_bredr::ConnectParameters::Rfcomm(fidl_bredr::RfcommParameters {
1802 channel: None,
1803 ..Default::default()
1804 });
1805 assert!(channel_number_from_parameters(&rfcomm_invalid).is_err());
1806
1807 let l2cap_invalid = fidl_bredr::ConnectParameters::L2cap(fidl_bredr::L2capParameters {
1809 psm: None,
1810 ..Default::default()
1811 });
1812 assert!(channel_number_from_parameters(&l2cap_invalid).is_err());
1813 }
1814
1815 fn calculate_hash<T: Hash>(t: &T) -> u64 {
1816 let mut s = DefaultHasher::new();
1817 t.hash(&mut s);
1818 s.finish()
1819 }
1820
1821 #[test]
1822 fn test_data_element_hash() {
1823 let elem1 = DataElement::Int8(5);
1825 let elem2 = elem1.clone();
1826 assert_eq!(calculate_hash(&elem1), calculate_hash(&elem2));
1827
1828 let elem3 = DataElement::Uint8(5);
1830 assert_ne!(calculate_hash(&elem1), calculate_hash(&elem3));
1831
1832 let elem4 = DataElement::Int8(6);
1834 assert_ne!(calculate_hash(&elem1), calculate_hash(&elem4));
1835
1836 let seq1 = DataElement::Sequence(vec![
1838 Box::new(DataElement::Int8(1)),
1839 Box::new(DataElement::Int8(2)),
1840 ]);
1841 let seq2 = DataElement::Sequence(vec![
1842 Box::new(DataElement::Int8(2)),
1843 Box::new(DataElement::Int8(1)),
1844 ]);
1845 assert_ne!(calculate_hash(&seq1), calculate_hash(&seq2));
1846
1847 let seq_seq1 = DataElement::Sequence(vec![
1850 Box::new(DataElement::Sequence(vec![
1851 Box::new(DataElement::Int8(1)),
1852 Box::new(DataElement::Int8(2)),
1853 ])),
1854 Box::new(DataElement::Sequence(vec![Box::new(DataElement::Int8(3))])),
1855 ]);
1856 let seq_seq2 = DataElement::Sequence(vec![
1857 Box::new(DataElement::Sequence(vec![Box::new(DataElement::Int8(1))])),
1858 Box::new(DataElement::Sequence(vec![
1859 Box::new(DataElement::Int8(2)),
1860 Box::new(DataElement::Int8(3)),
1861 ])),
1862 ]);
1863 assert_ne!(calculate_hash(&seq_seq1), calculate_hash(&seq_seq2));
1864 }
1865
1866 #[test]
1867 fn test_service_definition_hash() {
1868 let def1 = ServiceDefinition {
1869 service_class_uuids: vec![Uuid::new16(0x1101)],
1870 ..Default::default()
1871 };
1872 let def2 = def1.clone();
1873
1874 assert_eq!(calculate_hash(&def1), calculate_hash(&def2));
1876
1877 let def3 =
1879 ServiceDefinition { service_class_uuids: vec![Uuid::new16(0x1102)], ..def1.clone() };
1880 assert_ne!(calculate_hash(&def1), calculate_hash(&def3));
1881
1882 let def4 = ServiceDefinition {
1884 profile_descriptors: vec![fidl_bredr::ProfileDescriptor {
1885 profile_id: Some(fidl_bredr::ServiceClassProfileIdentifier::SerialPort),
1886 major_version: Some(1),
1887 minor_version: Some(0),
1888 ..Default::default()
1889 }],
1890 ..def1.clone()
1891 };
1892 assert_ne!(calculate_hash(&def1), calculate_hash(&def4));
1893
1894 let mut def5 = def4.clone();
1895 def5.profile_descriptors[0].minor_version = Some(1);
1896 assert_ne!(calculate_hash(&def4), calculate_hash(&def5));
1897 }
1898}