sl4f_lib/bluetooth/
types.rs

1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use anyhow::{format_err, Error};
6use fidl_fuchsia_bluetooth::{Appearance, Uuid as FidlUuid};
7use fidl_fuchsia_bluetooth_avdtp_test::PeerControllerProxy;
8use fidl_fuchsia_bluetooth_avrcp::{
9    AvcPanelCommand, BatteryStatus, CustomAttributeValue, CustomPlayerApplicationSetting,
10    Equalizer, PlayStatus, PlaybackStatus, PlayerApplicationSettingAttributeId,
11    PlayerApplicationSettings, RepeatStatusMode, ScanMode, ShuffleMode,
12};
13use fidl_fuchsia_bluetooth_gatt2::{
14    AttributePermissions, Characteristic, Descriptor, ReadByTypeResult, SecurityRequirements,
15    ServiceHandle, ServiceInfo, ServiceKind,
16};
17use fidl_fuchsia_bluetooth_le::{
18    AdvertisingData, AdvertisingModeHint, AdvertisingParameters, ConnectionOptions, Filter,
19    ManufacturerData, ServiceData,
20};
21use fidl_fuchsia_bluetooth_sys::Peer;
22use fuchsia_bluetooth::types::Uuid;
23use num_derive::FromPrimitive;
24use serde::{Deserialize, Serialize};
25use serde_json::Value;
26use std::collections::HashMap;
27use std::str::FromStr;
28
29use crate::common_utils::common::macros::parse_arg;
30
31/// Handling different sessions.
32/// Key is a generic id that is generated by the tool that is associated with a remote peer.
33/// Value is the controller associated with the remote peer.
34pub type PeerFactoryMap = HashMap<String, PeerControllerProxy>;
35
36/// BleScan result type
37/// TODO(https://fxbug.dev/42168627): Add support for RemoteDevices when clone() is implemented
38#[derive(Serialize, Clone, Debug)]
39pub struct BleScanResponse {
40    pub id: String,
41    pub name: String,
42    pub connectable: bool,
43}
44
45impl BleScanResponse {
46    pub fn new(id: String, name: String, connectable: bool) -> BleScanResponse {
47        BleScanResponse { id, name, connectable }
48    }
49}
50
51/// BleAdvertise result type (only uuid)
52/// TODO(https://fxbug.dev/42168627): Add support for AdvertisingData when clone() is implemented
53#[derive(Serialize, Clone, Debug)]
54pub struct BleAdvertiseResponse {
55    pub name: Option<String>,
56}
57
58impl BleAdvertiseResponse {
59    pub fn new(name: Option<String>) -> BleAdvertiseResponse {
60        BleAdvertiseResponse { name }
61    }
62}
63
64#[derive(Serialize, Deserialize, Clone, Debug, Default)]
65pub struct SecurityRequirementsContainer {
66    pub encryption_required: bool,
67    pub authentication_required: bool,
68    pub authorization_required: bool,
69}
70
71impl SecurityRequirementsContainer {
72    pub fn new(info: Option<SecurityRequirements>) -> SecurityRequirementsContainer {
73        match info {
74            Some(sec) => SecurityRequirementsContainer {
75                encryption_required: sec.encryption_required.unwrap_or(false),
76                authentication_required: sec.authentication_required.unwrap_or(false),
77                authorization_required: sec.authorization_required.unwrap_or(false),
78            },
79            None => SecurityRequirementsContainer::default(),
80        }
81    }
82}
83
84#[derive(Serialize, Deserialize, Clone, Debug)]
85pub struct AttributePermissionsContainer {
86    pub read: SecurityRequirementsContainer,
87    pub write: SecurityRequirementsContainer,
88    pub update: SecurityRequirementsContainer,
89}
90
91impl AttributePermissionsContainer {
92    pub fn new(info: Option<AttributePermissions>) -> Result<AttributePermissionsContainer, Error> {
93        match info {
94            Some(perm) => Ok(AttributePermissionsContainer {
95                read: SecurityRequirementsContainer::new(perm.read),
96                write: SecurityRequirementsContainer::new(perm.write),
97                update: SecurityRequirementsContainer::new(perm.update),
98            }),
99            None => return Err(format_err!("Unable to get information of AttributePermissions.")),
100        }
101    }
102}
103
104// Discover Characteristic response to hold characteristic info
105// as Characteristics are not serializable.
106#[derive(Serialize, Deserialize, Clone, Debug)]
107pub struct GattcDiscoverDescriptorResponse {
108    pub id: u64,
109    pub permissions: Option<AttributePermissionsContainer>,
110    pub uuid_type: String,
111}
112
113impl GattcDiscoverDescriptorResponse {
114    pub fn new(info: Vec<Descriptor>) -> Vec<GattcDiscoverDescriptorResponse> {
115        let mut res = Vec::new();
116        for v in info {
117            let copy = GattcDiscoverDescriptorResponse {
118                id: v.handle.unwrap().value,
119                permissions: match AttributePermissionsContainer::new(v.permissions) {
120                    Ok(n) => Some(n),
121                    Err(_) => None,
122                },
123                uuid_type: Uuid::from(v.type_.unwrap()).to_string(),
124            };
125            res.push(copy)
126        }
127        res
128    }
129}
130
131// Discover Characteristic response to hold characteristic info
132// as Characteristics are not serializable.
133#[derive(Serialize, Deserialize, Clone, Debug)]
134pub struct GattcDiscoverCharacteristicResponse {
135    pub id: u64,
136    pub properties: u32,
137    pub permissions: Option<AttributePermissionsContainer>,
138    pub uuid_type: String,
139    pub descriptors: Vec<GattcDiscoverDescriptorResponse>,
140}
141
142impl GattcDiscoverCharacteristicResponse {
143    pub fn new(info: Vec<Characteristic>) -> Vec<GattcDiscoverCharacteristicResponse> {
144        let mut res = Vec::new();
145        for v in info {
146            let copy = GattcDiscoverCharacteristicResponse {
147                id: v.handle.unwrap().value,
148                properties: v.properties.unwrap().bits().into(),
149                permissions: match AttributePermissionsContainer::new(v.permissions) {
150                    Ok(n) => Some(n),
151                    Err(_) => None,
152                },
153                uuid_type: Uuid::from(v.type_.unwrap()).to_string(),
154                descriptors: {
155                    match v.descriptors {
156                        Some(d) => GattcDiscoverDescriptorResponse::new(d),
157                        None => Vec::new(),
158                    }
159                },
160            };
161            res.push(copy)
162        }
163        res
164    }
165}
166
167/// BleConnectPeripheral response (aka ServiceInfo)
168/// TODO(https://fxbug.dev/42168627): Add support for ServiceInfo when clone(), serialize(), derived
169#[derive(Serialize, Deserialize, Clone, Debug)]
170pub struct BleConnectPeripheralResponse {
171    pub id: u64,
172    pub primary: bool,
173    pub uuid_type: String,
174}
175
176impl BleConnectPeripheralResponse {
177    pub fn new(info: Vec<ServiceInfo>) -> Vec<BleConnectPeripheralResponse> {
178        let mut res = Vec::new();
179        for v in info {
180            let copy = BleConnectPeripheralResponse {
181                id: v.handle.unwrap().value,
182                primary: v.kind.unwrap() == ServiceKind::Primary,
183                uuid_type: Uuid::from(v.type_.unwrap()).to_string(),
184            };
185            res.push(copy)
186        }
187        res
188    }
189}
190
191#[derive(Clone, Debug, Serialize)]
192pub struct SerializablePeer {
193    pub address: Option<[u8; 6]>,
194    pub appearance: Option<u32>,
195    pub device_class: Option<u32>,
196    pub id: Option<String>,
197    pub name: Option<String>,
198    pub connected: Option<bool>,
199    pub bonded: Option<bool>,
200    pub rssi: Option<i8>,
201    pub services: Option<Vec<[u8; 16]>>,
202    pub technology: Option<u32>,
203    pub tx_power: Option<i8>,
204}
205
206impl From<&Peer> for SerializablePeer {
207    fn from(peer: &Peer) -> Self {
208        let services = match &peer.services {
209            Some(s) => {
210                let mut service_list = Vec::new();
211                for item in s {
212                    service_list.push(item.value);
213                }
214                Some(service_list)
215            }
216            None => None,
217        };
218        SerializablePeer {
219            address: peer.address.map(|a| a.bytes),
220            appearance: peer.appearance.map(|a| a.into_primitive() as u32),
221            device_class: peer.device_class.map(|d| d.value),
222            id: peer.id.map(|i| i.value.to_string()),
223            name: peer.name.clone(),
224            connected: peer.connected,
225            bonded: peer.bonded,
226            rssi: peer.rssi,
227            services: services,
228            technology: peer.technology.map(|t| t as u32),
229            tx_power: peer.tx_power,
230        }
231    }
232}
233
234#[derive(Clone, Debug, Serialize)]
235pub struct SerializableReadByTypeResult {
236    pub id: Option<u64>,
237    pub value: Option<Vec<u8>>,
238}
239
240impl SerializableReadByTypeResult {
241    pub fn new(result: ReadByTypeResult) -> Option<Self> {
242        if result.error.is_some() {
243            return None;
244        }
245        let id = result.handle.unwrap().value;
246        let value = result.value.unwrap().value.unwrap();
247        Some(SerializableReadByTypeResult { id: Some(id), value: Some(value) })
248    }
249}
250
251#[derive(Clone, Debug, Serialize, Eq, Copy)]
252pub struct CustomPlayStatus {
253    pub song_length: Option<u32>,
254    pub song_position: Option<u32>,
255    pub playback_status: Option<u8>,
256}
257
258impl CustomPlayStatus {
259    pub fn new(status: &PlayStatus) -> Self {
260        let playback_status = match status.playback_status {
261            Some(p) => Some(p as u8),
262            None => None,
263        };
264        CustomPlayStatus {
265            song_length: status.song_length,
266            song_position: status.song_position,
267            playback_status: playback_status,
268        }
269    }
270}
271
272impl From<CustomPlayStatus> for PlayStatus {
273    fn from(status: CustomPlayStatus) -> Self {
274        let playback_status = match status.playback_status {
275            Some(0) => Some(PlaybackStatus::Stopped),
276            Some(1) => Some(PlaybackStatus::Playing),
277            Some(2) => Some(PlaybackStatus::Paused),
278            Some(3) => Some(PlaybackStatus::FwdSeek),
279            Some(4) => Some(PlaybackStatus::RevSeek),
280            Some(255) => Some(PlaybackStatus::Error),
281            None => None,
282            _ => panic!("Unknown playback status!"),
283        };
284        PlayStatus {
285            song_length: status.song_length,
286            song_position: status.song_position,
287            playback_status: playback_status,
288            ..Default::default()
289        }
290    }
291}
292
293impl From<PlayStatus> for CustomPlayStatus {
294    fn from(status: PlayStatus) -> Self {
295        CustomPlayStatus {
296            song_length: status.song_length,
297            song_position: status.song_position,
298            playback_status: match status.playback_status {
299                Some(p) => Some(p as u8),
300                None => None,
301            },
302        }
303    }
304}
305
306impl PartialEq for CustomPlayStatus {
307    fn eq(&self, other: &CustomPlayStatus) -> bool {
308        self.song_length == other.song_length
309            && self.song_position == other.song_position
310            && self.playback_status == other.playback_status
311    }
312}
313#[derive(Copy, Clone, Debug, FromPrimitive, Serialize, Deserialize)]
314#[repr(u8)]
315pub enum CustomAvcPanelCommand {
316    Select = 0,
317    Up = 1,
318    Down = 2,
319    Left = 3,
320    Right = 4,
321    RootMenu = 9,
322    ContentsMenu = 11,
323    FavoriteMenu = 12,
324    Exit = 13,
325    OnDemandMenu = 14,
326    AppsMenu = 15,
327    Key0 = 32,
328    Key1 = 33,
329    Key2 = 34,
330    Key3 = 35,
331    Key4 = 36,
332    Key5 = 37,
333    Key6 = 38,
334    Key7 = 39,
335    Key8 = 40,
336    Key9 = 41,
337    Dot = 42,
338    Enter = 43,
339    ChannelUp = 48,
340    ChannelDown = 49,
341    ChannelPrevious = 50,
342    InputSelect = 52,
343    Info = 53,
344    Help = 54,
345    PageUp = 55,
346    PageDown = 56,
347    Lock = 58,
348    Power = 64,
349    VolumeUp = 65,
350    VolumeDown = 66,
351    Mute = 67,
352    Play = 68,
353    Stop = 69,
354    Pause = 70,
355    Record = 71,
356    Rewind = 72,
357    FastForward = 73,
358    Eject = 74,
359    Forward = 75,
360    Backward = 76,
361    List = 77,
362    F1 = 113,
363    F2 = 114,
364    F3 = 115,
365    F4 = 116,
366    F5 = 117,
367    F6 = 118,
368    F7 = 119,
369    F8 = 120,
370    F9 = 121,
371    Red = 122,
372    Green = 123,
373    Blue = 124,
374    Yellow = 125,
375}
376
377impl From<CustomAvcPanelCommand> for AvcPanelCommand {
378    fn from(command: CustomAvcPanelCommand) -> Self {
379        match command {
380            CustomAvcPanelCommand::Select => AvcPanelCommand::Select,
381            CustomAvcPanelCommand::Up => AvcPanelCommand::Up,
382            CustomAvcPanelCommand::Down => AvcPanelCommand::Down,
383            CustomAvcPanelCommand::Left => AvcPanelCommand::Left,
384            CustomAvcPanelCommand::Right => AvcPanelCommand::Right,
385            CustomAvcPanelCommand::RootMenu => AvcPanelCommand::RootMenu,
386            CustomAvcPanelCommand::ContentsMenu => AvcPanelCommand::ContentsMenu,
387            CustomAvcPanelCommand::FavoriteMenu => AvcPanelCommand::FavoriteMenu,
388            CustomAvcPanelCommand::Exit => AvcPanelCommand::Exit,
389            CustomAvcPanelCommand::OnDemandMenu => AvcPanelCommand::OnDemandMenu,
390            CustomAvcPanelCommand::AppsMenu => AvcPanelCommand::AppsMenu,
391            CustomAvcPanelCommand::Key0 => AvcPanelCommand::Key0,
392            CustomAvcPanelCommand::Key1 => AvcPanelCommand::Key1,
393            CustomAvcPanelCommand::Key2 => AvcPanelCommand::Key2,
394            CustomAvcPanelCommand::Key3 => AvcPanelCommand::Key3,
395            CustomAvcPanelCommand::Key4 => AvcPanelCommand::Key4,
396            CustomAvcPanelCommand::Key5 => AvcPanelCommand::Key5,
397            CustomAvcPanelCommand::Key6 => AvcPanelCommand::Key6,
398            CustomAvcPanelCommand::Key7 => AvcPanelCommand::Key7,
399            CustomAvcPanelCommand::Key8 => AvcPanelCommand::Key8,
400            CustomAvcPanelCommand::Key9 => AvcPanelCommand::Key9,
401            CustomAvcPanelCommand::Dot => AvcPanelCommand::Dot,
402            CustomAvcPanelCommand::Enter => AvcPanelCommand::Enter,
403            CustomAvcPanelCommand::ChannelUp => AvcPanelCommand::ChannelUp,
404            CustomAvcPanelCommand::ChannelDown => AvcPanelCommand::ChannelDown,
405            CustomAvcPanelCommand::ChannelPrevious => AvcPanelCommand::ChannelPrevious,
406            CustomAvcPanelCommand::InputSelect => AvcPanelCommand::InputSelect,
407            CustomAvcPanelCommand::Info => AvcPanelCommand::Info,
408            CustomAvcPanelCommand::Help => AvcPanelCommand::Help,
409            CustomAvcPanelCommand::PageUp => AvcPanelCommand::PageUp,
410            CustomAvcPanelCommand::PageDown => AvcPanelCommand::PageDown,
411            CustomAvcPanelCommand::Lock => AvcPanelCommand::Lock,
412            CustomAvcPanelCommand::Power => AvcPanelCommand::Power,
413            CustomAvcPanelCommand::VolumeUp => AvcPanelCommand::VolumeUp,
414            CustomAvcPanelCommand::VolumeDown => AvcPanelCommand::VolumeDown,
415            CustomAvcPanelCommand::Mute => AvcPanelCommand::Mute,
416            CustomAvcPanelCommand::Play => AvcPanelCommand::Play,
417            CustomAvcPanelCommand::Stop => AvcPanelCommand::Stop,
418            CustomAvcPanelCommand::Pause => AvcPanelCommand::Pause,
419            CustomAvcPanelCommand::Record => AvcPanelCommand::Record,
420            CustomAvcPanelCommand::Rewind => AvcPanelCommand::Rewind,
421            CustomAvcPanelCommand::FastForward => AvcPanelCommand::FastForward,
422            CustomAvcPanelCommand::Eject => AvcPanelCommand::Eject,
423            CustomAvcPanelCommand::Forward => AvcPanelCommand::Forward,
424            CustomAvcPanelCommand::Backward => AvcPanelCommand::Backward,
425            CustomAvcPanelCommand::List => AvcPanelCommand::List,
426            CustomAvcPanelCommand::F1 => AvcPanelCommand::F1,
427            CustomAvcPanelCommand::F2 => AvcPanelCommand::F2,
428            CustomAvcPanelCommand::F3 => AvcPanelCommand::F3,
429            CustomAvcPanelCommand::F4 => AvcPanelCommand::F4,
430            CustomAvcPanelCommand::F5 => AvcPanelCommand::F5,
431            CustomAvcPanelCommand::F6 => AvcPanelCommand::F6,
432            CustomAvcPanelCommand::F7 => AvcPanelCommand::F7,
433            CustomAvcPanelCommand::F8 => AvcPanelCommand::F8,
434            CustomAvcPanelCommand::F9 => AvcPanelCommand::F9,
435            CustomAvcPanelCommand::Red => AvcPanelCommand::Red,
436            CustomAvcPanelCommand::Green => AvcPanelCommand::Green,
437            CustomAvcPanelCommand::Blue => AvcPanelCommand::Blue,
438            CustomAvcPanelCommand::Yellow => AvcPanelCommand::Yellow,
439        }
440    }
441}
442
443impl From<String> for CustomAvcPanelCommand {
444    fn from(command: String) -> Self {
445        match command.as_str() {
446            "Select" => CustomAvcPanelCommand::Select,
447            "Up" => CustomAvcPanelCommand::Up,
448            "Down" => CustomAvcPanelCommand::Down,
449            "Left" => CustomAvcPanelCommand::Left,
450            "Right" => CustomAvcPanelCommand::Right,
451            "RootMenu" => CustomAvcPanelCommand::RootMenu,
452            "ContentsMenu" => CustomAvcPanelCommand::ContentsMenu,
453            "FavoriteMenu" => CustomAvcPanelCommand::FavoriteMenu,
454            "Exit" => CustomAvcPanelCommand::Exit,
455            "OnDemandMenu" => CustomAvcPanelCommand::OnDemandMenu,
456            "AppsMenu" => CustomAvcPanelCommand::AppsMenu,
457            "Key0" => CustomAvcPanelCommand::Key0,
458            "Key1" => CustomAvcPanelCommand::Key1,
459            "Key2" => CustomAvcPanelCommand::Key2,
460            "Key3" => CustomAvcPanelCommand::Key3,
461            "Key4" => CustomAvcPanelCommand::Key4,
462            "Key5" => CustomAvcPanelCommand::Key5,
463            "Key6" => CustomAvcPanelCommand::Key6,
464            "Key7" => CustomAvcPanelCommand::Key7,
465            "Key8" => CustomAvcPanelCommand::Key8,
466            "Key9" => CustomAvcPanelCommand::Key9,
467            "Dot" => CustomAvcPanelCommand::Dot,
468            "Enter" => CustomAvcPanelCommand::Enter,
469            "ChannelUp" => CustomAvcPanelCommand::ChannelUp,
470            "ChannelDown" => CustomAvcPanelCommand::ChannelDown,
471            "ChannelPrevious" => CustomAvcPanelCommand::ChannelPrevious,
472            "InputSelect" => CustomAvcPanelCommand::InputSelect,
473            "Info" => CustomAvcPanelCommand::Info,
474            "Help" => CustomAvcPanelCommand::Help,
475            "PageUp" => CustomAvcPanelCommand::PageUp,
476            "PageDown" => CustomAvcPanelCommand::PageDown,
477            "Lock" => CustomAvcPanelCommand::Lock,
478            "Power" => CustomAvcPanelCommand::Power,
479            "VolumeUp" => CustomAvcPanelCommand::VolumeUp,
480            "VolumeDown" => CustomAvcPanelCommand::VolumeDown,
481            "Mute" => CustomAvcPanelCommand::Mute,
482            "Play" => CustomAvcPanelCommand::Play,
483            "Stop" => CustomAvcPanelCommand::Stop,
484            "Pause" => CustomAvcPanelCommand::Pause,
485            "Record" => CustomAvcPanelCommand::Record,
486            "Rewind" => CustomAvcPanelCommand::Rewind,
487            "FastForward" => CustomAvcPanelCommand::FastForward,
488            "Eject" => CustomAvcPanelCommand::Eject,
489            "Forward" => CustomAvcPanelCommand::Forward,
490            "Backward" => CustomAvcPanelCommand::Backward,
491            "List" => CustomAvcPanelCommand::List,
492            "F1" => CustomAvcPanelCommand::F1,
493            "F2" => CustomAvcPanelCommand::F2,
494            "F3" => CustomAvcPanelCommand::F3,
495            "F4" => CustomAvcPanelCommand::F4,
496            "F5" => CustomAvcPanelCommand::F5,
497            "F6" => CustomAvcPanelCommand::F6,
498            "F7" => CustomAvcPanelCommand::F7,
499            "F8" => CustomAvcPanelCommand::F8,
500            "F9" => CustomAvcPanelCommand::F9,
501            "Red" => CustomAvcPanelCommand::Red,
502            "Green" => CustomAvcPanelCommand::Green,
503            "Blue" => CustomAvcPanelCommand::Blue,
504            "Yellow" => CustomAvcPanelCommand::Yellow,
505            _invalid => panic!("Invalid CustomAvcPanelCommand command:{:?}", _invalid),
506        }
507    }
508}
509#[derive(Deserialize)]
510pub struct AbsoluteVolumeCommand {
511    pub absolute_volume: u8,
512}
513
514#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
515pub struct CustomPlayerApplicationSettingsAttributeIds {
516    pub attribute_ids: Option<Vec<u8>>,
517}
518
519impl CustomPlayerApplicationSettingsAttributeIds {
520    pub fn to_vec(&self) -> Vec<PlayerApplicationSettingAttributeId> {
521        match &self.attribute_ids {
522            Some(vec) => vec
523                .into_iter()
524                .map(|u8| match u8 {
525                    1 => PlayerApplicationSettingAttributeId::Equalizer,
526                    2 => PlayerApplicationSettingAttributeId::RepeatStatusMode,
527                    3 => PlayerApplicationSettingAttributeId::ShuffleMode,
528                    4 => PlayerApplicationSettingAttributeId::ScanMode,
529                    invalid => panic!(
530                        "Invalid value for PlayerApplicationSettingAttributeId {:?}",
531                        invalid
532                    ),
533                })
534                .collect(),
535            None => Vec::new(),
536        }
537    }
538}
539#[derive(Clone, Debug, Serialize)]
540pub enum CustomPlayerApplicationSettingsAttributeId {
541    Equalizer = 1,
542    RepeatStatusMode = 2,
543    ShuffleMode = 3,
544    ScanMode = 4,
545}
546
547impl From<u8> for CustomPlayerApplicationSettingsAttributeId {
548    fn from(attribute_id: u8) -> CustomPlayerApplicationSettingsAttributeId {
549        match attribute_id {
550            1 => CustomPlayerApplicationSettingsAttributeId::Equalizer,
551            2 => CustomPlayerApplicationSettingsAttributeId::RepeatStatusMode,
552            3 => CustomPlayerApplicationSettingsAttributeId::ShuffleMode,
553            4 => CustomPlayerApplicationSettingsAttributeId::ScanMode,
554            _ => panic!("Invalid attribute id: {:?}", attribute_id),
555        }
556    }
557}
558
559#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
560pub struct CustomPlayerApplicationSettings {
561    pub equalizer: Option<CustomEqualizer>,
562    pub repeat_status_mode: Option<CustomRepeatStatusMode>,
563    pub shuffle_mode: Option<CustomShuffleMode>,
564    pub scan_mode: Option<CustomScanMode>,
565    pub custom_settings: Option<Vec<CustomCustomPlayerApplicationSetting>>,
566}
567
568#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
569pub struct CustomCustomPlayerApplicationSetting {
570    pub attribute_id: Option<u8>,
571    pub attribute_name: Option<String>,
572    pub possible_values: Option<Vec<CustomCustomAttributeValue>>,
573    pub current_value: Option<u8>,
574}
575
576#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
577pub struct CustomCustomAttributeValue {
578    pub description: String,
579    pub value: u8,
580}
581#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Copy)]
582pub enum CustomEqualizer {
583    Off = 1,
584    On = 2,
585}
586
587#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Copy)]
588pub enum CustomRepeatStatusMode {
589    Off = 1,
590    SingleTrackRepeat = 2,
591    AllTrackRepeat = 3,
592    GroupRepeat = 4,
593}
594#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Copy)]
595pub enum CustomShuffleMode {
596    Off = 1,
597    AllTrackShuffle = 2,
598    GroupShuffle = 3,
599}
600#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Copy)]
601pub enum CustomScanMode {
602    Off = 1,
603    AllTrackScan = 2,
604    GroupScan = 3,
605}
606#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Copy)]
607pub enum CustomBatteryStatus {
608    Normal = 0,
609    Warning = 1,
610    Critical = 2,
611    External = 3,
612    FullCharge = 4,
613    Reserved = 5,
614}
615
616impl From<PlayerApplicationSettings> for CustomPlayerApplicationSettings {
617    fn from(settings: PlayerApplicationSettings) -> CustomPlayerApplicationSettings {
618        CustomPlayerApplicationSettings {
619            equalizer: match settings.equalizer {
620                Some(equalizer) => match equalizer {
621                    Equalizer::Off => Some(CustomEqualizer::Off),
622                    Equalizer::On => Some(CustomEqualizer::On),
623                },
624                None => None,
625            },
626            repeat_status_mode: match settings.repeat_status_mode {
627                Some(repeat_status_mode) => match repeat_status_mode {
628                    RepeatStatusMode::Off => Some(CustomRepeatStatusMode::Off),
629                    RepeatStatusMode::SingleTrackRepeat => {
630                        Some(CustomRepeatStatusMode::SingleTrackRepeat)
631                    }
632                    RepeatStatusMode::AllTrackRepeat => {
633                        Some(CustomRepeatStatusMode::AllTrackRepeat)
634                    }
635                    RepeatStatusMode::GroupRepeat => Some(CustomRepeatStatusMode::GroupRepeat),
636                },
637                None => None,
638            },
639            shuffle_mode: match settings.shuffle_mode {
640                Some(shuffle_mode) => match shuffle_mode {
641                    ShuffleMode::Off => Some(CustomShuffleMode::Off),
642                    ShuffleMode::AllTrackShuffle => Some(CustomShuffleMode::AllTrackShuffle),
643                    ShuffleMode::GroupShuffle => Some(CustomShuffleMode::GroupShuffle),
644                },
645                None => None,
646            },
647            scan_mode: match settings.scan_mode {
648                Some(scan_mode) => match scan_mode {
649                    ScanMode::Off => Some(CustomScanMode::Off),
650                    ScanMode::AllTrackScan => Some(CustomScanMode::AllTrackScan),
651                    ScanMode::GroupScan => Some(CustomScanMode::GroupScan),
652                },
653                None => None,
654            },
655            custom_settings: match settings.custom_settings {
656                Some(custom_settings_vec) => Some(
657                    custom_settings_vec
658                        .into_iter()
659                        .map(|custom_settings| CustomCustomPlayerApplicationSetting {
660                            attribute_id: custom_settings.attribute_id,
661                            attribute_name: custom_settings.attribute_name,
662                            possible_values: match custom_settings.possible_values {
663                                Some(possible_values) => Some(
664                                    possible_values
665                                        .into_iter()
666                                        .map(|possible_value| possible_value.into())
667                                        .collect(),
668                                ),
669                                None => None,
670                            },
671                            current_value: custom_settings.current_value,
672                        })
673                        .collect(),
674                ),
675                None => None,
676            },
677        }
678    }
679}
680
681impl From<CustomPlayerApplicationSettings> for PlayerApplicationSettings {
682    fn from(settings: CustomPlayerApplicationSettings) -> PlayerApplicationSettings {
683        PlayerApplicationSettings {
684            equalizer: match settings.equalizer {
685                Some(equalizer) => match equalizer {
686                    CustomEqualizer::Off => Some(Equalizer::Off),
687                    CustomEqualizer::On => Some(Equalizer::On),
688                },
689                None => None,
690            },
691            repeat_status_mode: match settings.repeat_status_mode {
692                Some(repeat_status_mode) => match repeat_status_mode {
693                    CustomRepeatStatusMode::Off => Some(RepeatStatusMode::Off),
694                    CustomRepeatStatusMode::SingleTrackRepeat => {
695                        Some(RepeatStatusMode::SingleTrackRepeat)
696                    }
697                    CustomRepeatStatusMode::AllTrackRepeat => {
698                        Some(RepeatStatusMode::AllTrackRepeat)
699                    }
700                    CustomRepeatStatusMode::GroupRepeat => Some(RepeatStatusMode::GroupRepeat),
701                },
702                None => None,
703            },
704            shuffle_mode: match settings.shuffle_mode {
705                Some(shuffle_mode) => match shuffle_mode {
706                    CustomShuffleMode::Off => Some(ShuffleMode::Off),
707                    CustomShuffleMode::AllTrackShuffle => Some(ShuffleMode::AllTrackShuffle),
708                    CustomShuffleMode::GroupShuffle => Some(ShuffleMode::GroupShuffle),
709                },
710                None => None,
711            },
712            scan_mode: match settings.scan_mode {
713                Some(scan_mode) => match scan_mode {
714                    CustomScanMode::Off => Some(ScanMode::Off),
715                    CustomScanMode::AllTrackScan => Some(ScanMode::AllTrackScan),
716                    CustomScanMode::GroupScan => Some(ScanMode::GroupScan),
717                },
718                None => None,
719            },
720            custom_settings: match settings.custom_settings {
721                Some(custom_settings_vec) => Some(
722                    custom_settings_vec
723                        .into_iter()
724                        .map(|custom_settings| CustomPlayerApplicationSetting {
725                            attribute_id: custom_settings.attribute_id,
726                            attribute_name: custom_settings.attribute_name,
727                            possible_values: match custom_settings.possible_values {
728                                Some(possible_values) => Some(
729                                    possible_values
730                                        .into_iter()
731                                        .map(|possible_value| possible_value.into())
732                                        .collect(),
733                                ),
734                                None => None,
735                            },
736                            current_value: custom_settings.current_value,
737                            ..Default::default()
738                        })
739                        .collect(),
740                ),
741                None => None,
742            },
743            ..Default::default()
744        }
745    }
746}
747
748impl From<CustomCustomAttributeValue> for CustomAttributeValue {
749    fn from(attribute_value: CustomCustomAttributeValue) -> CustomAttributeValue {
750        CustomAttributeValue {
751            description: attribute_value.description,
752            value: attribute_value.value,
753        }
754    }
755}
756
757impl From<CustomAttributeValue> for CustomCustomAttributeValue {
758    fn from(attribute_value: CustomAttributeValue) -> CustomCustomAttributeValue {
759        CustomCustomAttributeValue {
760            description: attribute_value.description,
761            value: attribute_value.value,
762        }
763    }
764}
765
766impl From<BatteryStatus> for CustomBatteryStatus {
767    fn from(status: BatteryStatus) -> Self {
768        match status {
769            BatteryStatus::Normal => CustomBatteryStatus::Normal,
770            BatteryStatus::Warning => CustomBatteryStatus::Warning,
771            BatteryStatus::Critical => CustomBatteryStatus::Critical,
772            BatteryStatus::External => CustomBatteryStatus::External,
773            BatteryStatus::FullCharge => CustomBatteryStatus::FullCharge,
774            BatteryStatus::Reserved => CustomBatteryStatus::Reserved,
775        }
776    }
777}
778
779impl From<CustomBatteryStatus> for BatteryStatus {
780    fn from(status: CustomBatteryStatus) -> Self {
781        match status {
782            CustomBatteryStatus::Normal => BatteryStatus::Normal,
783            CustomBatteryStatus::Warning => BatteryStatus::Warning,
784            CustomBatteryStatus::Critical => BatteryStatus::Critical,
785            CustomBatteryStatus::External => BatteryStatus::External,
786            CustomBatteryStatus::FullCharge => BatteryStatus::FullCharge,
787            CustomBatteryStatus::Reserved => BatteryStatus::Reserved,
788        }
789    }
790}
791
792#[derive(Clone, Debug, Serialize, Deserialize)]
793pub struct CustomNotificationsFilter {
794    pub notifications: u32,
795    pub position_change_interval: Option<u32>,
796}
797
798pub struct FacadeArg {
799    value: Value,
800}
801
802impl FacadeArg {
803    pub fn new(value: Value) -> Self {
804        FacadeArg { value }
805    }
806}
807
808/// Deserializes a serde json object according to the following schema
809///
810/// {
811///     'advertising_data': {
812///         'name': Some(String),
813///         'appearance': Some(u64),
814///         'service_data': {
815///             'uuid': ['fb', '34', '9b', '5f', '80', '00', '00', '80', '00', '10', '00', '00', '01', '18', '00', '00'].
816///             'data': "1"
817///         },
818///         'service_uuids': [
819///             ['fb', '34', '9b', '5f', '80', '00', '00', '80', '00', '10', '00', '00', '01', '18', '00', '00'].
820///             ['fb', '34', '9b', '5f', '80', '00', '00', '80', '00', '10', '00', '00', '00', '18', '00', '00']
821///         ],
822///         'manufacturer_data': {
823///             'id': 10,
824///             'data'
825///         },
826///         'uris': Some(['telnet://192.0.2.16:80/']),
827///         'tx_power_level': Some(1),
828///
829///     }
830///
831/// }
832///
833/// Note: A human readable uuid is represented as a list of bytes:
834///     Example Human Readable UUID: '00001801-0000-1000-8000-00805f9b34fb'
835///     Actual input:
836///         ['fb', '34', '9b', '5f', '80', '00', '00', '80', '00', '10', '00', '00', '01', '18', '00', '00']
837impl TryInto<AdvertisingData> for FacadeArg {
838    type Error = Error;
839    fn try_into(self) -> Result<AdvertisingData, Self::Error> {
840        /// Parse json input UUID and return Bluetooth UUID format.
841        ///
842        /// # Arguments
843        /// * `json_uuid`: The JSON UUID in the form of a list of bytes.
844        fn parse_uuid(json_uuid: &Value) -> Result<FidlUuid, Error> {
845            let mut byte_list = vec![];
846
847            for byte_string in json_uuid.as_array().unwrap() {
848                let raw_value = match i64::from_str_radix(byte_string.as_str().unwrap(), 16) {
849                    Ok(v) => v as u8,
850                    Err(e) => bail!("Failed to convert raw value with: {:?}", e),
851                };
852                byte_list.push(raw_value);
853            }
854            Ok(FidlUuid {
855                value: byte_list.as_slice().try_into().expect("Failed to set UUID value."),
856            })
857        }
858
859        /// Parse a list of service uuids from a json input list.
860        ///
861        /// # Arguments
862        /// * `json_service_uuids`: The JSON UUIDs in the form of lists of list of bytes.
863        fn parse_service_uuids(json_service_uuids: &Vec<Value>) -> Result<Vec<FidlUuid>, Error> {
864            let mut uuid_list = Vec::new();
865
866            for raw_uuid_list in json_service_uuids {
867                uuid_list.push(parse_uuid(raw_uuid_list)?);
868            }
869            Ok(uuid_list)
870        }
871
872        /// Parse the json input service data into a list of ServiceData
873        ///
874        /// # Arguments
875        /// * `json_service_data`: The JSON representation of ServiceData to parse.
876        fn parse_service_data(json_service_data: &Vec<Value>) -> Result<Vec<ServiceData>, Error> {
877            let mut manufacturer_data_list = Vec::new();
878
879            for raw_service_data in json_service_data {
880                let uuid = match raw_service_data.get("uuid") {
881                    Some(v) => parse_uuid(v)?,
882                    None => bail!("Missing Service data info 'uuid'."),
883                };
884                let data = match raw_service_data.get("data") {
885                    Some(d) => d.to_string().into_bytes(),
886                    None => bail!("Missing Service data info 'data'."),
887                };
888                manufacturer_data_list.push(ServiceData { uuid, data });
889            }
890            Ok(manufacturer_data_list)
891        }
892
893        /// Parse the json input manufacturer data into a list of ManufacturerData
894        ///
895        /// # Arguments
896        /// * `json_manufacturer_data`: The JSON representation of ManufacturerData to parse.
897        fn parse_manufacturer_data(
898            json_manufacturer_data: &Vec<Value>,
899        ) -> Result<Vec<ManufacturerData>, Error> {
900            let mut manufacturer_data_list = Vec::new();
901
902            for raw_manufacturer_data in json_manufacturer_data {
903                let company_id = match raw_manufacturer_data.get("id") {
904                    Some(v) => match v.as_u64() {
905                        Some(c) => c as u16,
906                        None => bail!("Company id not a valid value."),
907                    },
908                    None => bail!("Missing Manufacturer info 'id'."),
909                };
910                let data = match raw_manufacturer_data.get("data") {
911                    Some(d) => d.to_string().into_bytes(),
912                    None => bail!("Missing Manufacturer info 'data'."),
913                };
914                manufacturer_data_list.push(ManufacturerData { company_id, data });
915            }
916            Ok(manufacturer_data_list)
917        }
918
919        let name: Option<String> = self.value["name"].as_str().map(String::from);
920        let service_uuids = match self.value.get("service_uuids") {
921            Some(v) => {
922                if v.is_null() {
923                    None
924                } else {
925                    match v.clone().as_array() {
926                        Some(list) => Some(parse_service_uuids(list)?),
927                        None => bail!("Attribute 'service_uuids' is not a parseable list."),
928                    }
929                }
930            }
931            None => None,
932        };
933
934        let appearance = match self.value.get("appearance") {
935            Some(v) => {
936                if v.is_null() {
937                    None
938                } else {
939                    match v.as_u64() {
940                        Some(c) => Appearance::from_primitive(c as u16),
941                        None => None,
942                    }
943                }
944            }
945            None => bail!("Value 'appearance' missing."),
946        };
947
948        let include_tx_power_level =
949            self.value.get("tx_power_level").and_then(|v| Some(!v.is_null()));
950
951        let service_data = match self.value.get("service_data") {
952            Some(raw) => {
953                if raw.is_null() {
954                    None
955                } else {
956                    match raw.as_array() {
957                        Some(list) => Some(parse_service_data(list)?),
958                        None => None,
959                    }
960                }
961            }
962            None => bail!("Value 'service_data' missing."),
963        };
964
965        let manufacturer_data = match self.value.get("manufacturer_data") {
966            Some(raw) => {
967                if raw.is_null() {
968                    None
969                } else {
970                    match raw.as_array() {
971                        Some(list) => Some(parse_manufacturer_data(list)?),
972                        None => None,
973                    }
974                }
975            }
976            None => bail!("Value 'manufacturer_data' missing."),
977        };
978
979        let uris = match self.value.get("uris") {
980            Some(raw) => {
981                if raw.is_null() {
982                    None
983                } else {
984                    match raw.as_array() {
985                        Some(list) => {
986                            let mut uri_list = Vec::new();
987                            for item in list {
988                                match item.as_str() {
989                                    Some(i) => uri_list.push(String::from(i)),
990                                    None => bail!("Expected URI string"),
991                                }
992                            }
993                            Some(uri_list)
994                        }
995                        None => None,
996                    }
997                }
998            }
999            None => bail!("Value 'uris' missing."),
1000        };
1001
1002        Ok(AdvertisingData {
1003            name,
1004            appearance,
1005            service_uuids,
1006            service_data,
1007            manufacturer_data,
1008            uris: uris,
1009            include_tx_power_level,
1010            ..Default::default()
1011        })
1012    }
1013}
1014
1015impl TryInto<AdvertisingParameters> for FacadeArg {
1016    type Error = Error;
1017    fn try_into(self) -> Result<AdvertisingParameters, Self::Error> {
1018        let advertising_data = match self.value.get("advertising_data") {
1019            Some(adr) => Some(FacadeArg::new(adr.clone()).try_into()?),
1020            None => bail!("Value 'advertising_data' missing."),
1021        };
1022
1023        let scan_response = match self.value.get("scan_response") {
1024            Some(scn) => {
1025                if scn.is_null() {
1026                    None
1027                } else {
1028                    Some(FacadeArg::new(scn.clone()).try_into()?)
1029                }
1030            }
1031            None => None,
1032        };
1033
1034        let conn_raw =
1035            self.value.get("connectable").ok_or_else(|| format_err!("Connectable missing"))?;
1036
1037        let connectable: bool = conn_raw.as_bool().unwrap_or(false);
1038
1039        let conn_opts = if connectable {
1040            Some(ConnectionOptions {
1041                bondable_mode: Some(true),
1042                service_filter: None,
1043                ..Default::default()
1044            })
1045        } else {
1046            None
1047        };
1048
1049        Ok(AdvertisingParameters {
1050            data: advertising_data,
1051            scan_response: scan_response,
1052            mode_hint: Some(AdvertisingModeHint::VeryFast),
1053            connection_options: conn_opts,
1054            ..Default::default()
1055        })
1056    }
1057}
1058
1059impl TryInto<Filter> for FacadeArg {
1060    type Error = Error;
1061    fn try_into(self) -> Result<Filter, Self::Error> {
1062        let value =
1063            self.value.get("filter").ok_or_else(|| format_err!("Scan filter missing."))?.clone();
1064        let name = value["name_substring"].as_str().map(String::from);
1065        // For now, no scan profile, so default to empty Filter
1066        Ok(Filter { name, ..Default::default() })
1067    }
1068}
1069
1070impl TryInto<ServiceInfo> for FacadeArg {
1071    type Error = Error;
1072    fn try_into(self) -> Result<ServiceInfo, Self::Error> {
1073        let value = self.value;
1074        let id = parse_arg!(value, as_u64, "id")?;
1075        let handle = ServiceHandle { value: id };
1076        let primary = parse_arg!(value, as_bool, "primary")?;
1077        let kind = if primary { ServiceKind::Primary } else { ServiceKind::Secondary };
1078        let type_ = parse_arg!(value, as_str, "type")?.to_string();
1079        let type_: FidlUuid =
1080            Uuid::from_str(&type_).map_err(|_| format_err!("Invalid type"))?.into();
1081
1082        Ok(ServiceInfo {
1083            handle: Some(handle),
1084            kind: Some(kind),
1085            type_: Some(type_),
1086            // TODO(https://fxbug.dev/42169516): Add support for GATT characteristics and includes
1087            ..Default::default()
1088        })
1089    }
1090}