blob: b7633226ee35298bc01b9a0e8c58de35f39e255f [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use async;
use fidl::encoding2::OutOfLine;
use fidl_fuchsia_bluetooth;
use fidl_fuchsia_bluetooth_control::{Control, ControlImpl};
use futures::{future, Future, FutureExt, Never};
use futures::future::Either::{Left, Right};
use futures::prelude::*;
use host_dispatcher::*;
use parking_lot::RwLock;
use std::sync::Arc;
use zx::Duration;
use async::TimeoutExt;
pub static TIMEOUT: u64 = 3; // Seconds
struct ControlServiceState {
host: Arc<RwLock<HostDispatcher>>,
discovery_token: Option<Arc<DiscoveryRequestToken>>,
discoverable_token: Option<Arc<DiscoverableRequestToken>>,
}
/// Build the ControlImpl to interact with fidl messages
/// State is stored in the HostDispatcher object
pub fn make_control_service(
hd: Arc<RwLock<HostDispatcher>>, chan: async::Channel
) -> impl Future<Item = (), Error = Never> {
ControlImpl {
state: Arc::new(RwLock::new(ControlServiceState {
host: hd,
discovery_token: None,
discoverable_token: None,
})),
on_open: |state, handle| {
let wstate = state.write();
let mut hd = wstate.host.write();
hd.events = Some(handle.clone());
future::ok(())
},
connect: |_, _, _, res| {
res.send(&mut bt_fidl_status!(NotSupported))
.into_future()
.recover(|e| eprintln!("error sending response: {:?}", e))
},
disconnect: |_, _, res| {
res.send(&mut bt_fidl_status!(NotSupported))
.into_future()
.recover(|e| eprintln!("error sending response: {:?}", e))
},
forget: |_, _, res| {
res.send(&mut bt_fidl_status!(NotSupported))
.into_future()
.recover(|e| eprintln!("error sending response: {:?}", e))
},
set_name: |state, name, res| {
let wstate = state.write();
let mut hd = wstate.host.write();
hd.set_name(name)
.and_then(move |mut resp| res.send(&mut resp))
.recover(|e| eprintln!("error sending response: {:?}", e))
},
get_active_adapter_info: |state, res| {
let wstate = state.write();
let mut hd = wstate.host.write();
let mut adap = hd.get_active_adapter_info();
res.send(adap.as_mut().map(OutOfLine))
.into_future()
.recover(|e| eprintln!("error sending response: {:?}", e))
},
get_known_remote_devices: |_state, _res| future::ok(()),
get_adapters: |state, res| {
let wstate = state.write();
let mut hd = wstate.host.clone();
HostDispatcher::get_adapters(&mut hd)
.on_timeout(Duration::from_seconds(TIMEOUT).after_now(), || {
eprintln!("Timed out waiting for adapters");
Ok(vec![])
}).unwrap()
.and_then(move |mut resp| res.send(Some(&mut resp.iter_mut())))
.recover(|e| eprintln!("error sending response: {:?}", e))
},
is_bluetooth_available: |state, res| {
let rstate = state.read();
let mut hd = rstate.host.write();
let is_available = hd.get_active_adapter_info().is_some();
res.send(is_available)
.into_future()
.recover(|e| eprintln!("error sending response: {:?}", e))
},
request_discovery: |state, discover, res| {
let fut = if discover {
let stateref = Arc::clone(&state);
Left(
HostDispatcher::start_discovery(&state.read().host).and_then(
move |(mut resp, token)| {
stateref.write().discovery_token = token;
res.send(&mut resp).into_future()
},
),
)
} else {
state.write().discovery_token = None;
Right(res.send(&mut bt_fidl_status!()).into_future())
};
fut.recover(|e| eprintln!("error sending response: {:?}", e))
},
set_discoverable: |state, discoverable, res| {
let fut = if discoverable {
let stateref = Arc::clone(&state);
Left(
HostDispatcher::set_discoverable(&state.read().host).and_then(
move |(mut resp, token)| {
stateref.write().discoverable_token = token;
res.send(&mut resp).into_future()
},
),
)
} else {
state.write().discoverable_token = None;
Right(res.send(&mut bt_fidl_status!()).into_future())
};
fut.recover(|e| eprintln!("error sending response: {:?}", e))
},
set_active_adapter: |state, adapter, res| {
let wstate = state.write();
let mut success = wstate.host.write().set_active_adapter(adapter.clone());
res.send(&mut success)
.into_future()
.recover(|e| eprintln!("error sending response: {:?}", e))
},
set_pairing_delegate: |state, _, _, delegate, _res| {
if let Some(delegate) = delegate {
if let Ok(proxy) = delegate.into_proxy() {
let mut wstate = state.write();
wstate.host.write().pairing_delegate = Some(proxy);
}
}
future::ok(())
},
}.serve(chan)
.recover(|e| eprintln!("error running service: {:?}", e))
}