WIP - add ActorContext, FidlHost loading
Change-Id: I61b3d4b1c9ab5c2f95d8b8fca00d89cce8093b25
diff --git a/bin/bluetooth/gap/src/actor.rs b/bin/bluetooth/gap/src/actor.rs
index 076bd83..5af26a56 100644
--- a/bin/bluetooth/gap/src/actor.rs
+++ b/bin/bluetooth/gap/src/actor.rs
@@ -7,7 +7,6 @@
use futures::task::LocalWaker;
use core::pin::Pin;
use std::sync::Arc;
-//use std::sync::RwLock;
use parking_lot::RwLock;
use fuchsia_async as fasync;
@@ -20,17 +19,28 @@
Could do it via message traits ala Actix What about types responders?
What do I send as the message target? Perhaps just route via oneshot channels?
*/
- fn update(&mut self, msg: Self::Message, system: System);
+ fn update(&mut self, msg: Self::Message, context: ActorContext<Self>);
// TODO - handle errors by returning a result?
// Then can terminate actors if they return an error?
// Or terminate the whole system?
// fn update(&mut self, msg: Message, system: System) -> Result<(),Error>;
}
+pub struct ActorContext<A: Actor + ?Sized> {
+ system: System,
+ handle: ActorHandle<A::Message>,
+}
+
+impl<A: Actor + ?Sized> Clone for ActorContext<A> {
+ fn clone(&self) -> Self {
+ ActorContext{ system: self.system.clone(), handle: self.handle.clone() }
+ }
+}
+
struct ActorCell<A: Actor> {
actor: A,
inbox: mpsc::UnboundedReceiver<A::Message>,
- system: System
+ cx: ActorContext<A>
}
trait ActorProc {
@@ -52,7 +62,7 @@
fn run_next(&mut self, lw: &LocalWaker) -> Poll<Option<()>> {
let inbox = Pin::new(&mut self.inbox);
match inbox.poll_next(lw) {
- Poll::Ready(Some(msg)) => Poll::Ready(Some(self.actor.update(msg, self.system.clone()))),
+ Poll::Ready(Some(msg)) => Poll::Ready(Some(self.actor.update(msg, self.cx.clone()))),
Poll::Ready(None) => Poll::Ready(None),
Poll::Pending => Poll::Pending
}
@@ -82,10 +92,11 @@
}
impl System {
- pub fn spawn<A: Actor + 'static>(&mut self, a: A) -> ActorHandle<A::Message> {
- let (sender, receiver) = mpsc::unbounded::<A::Message>();
- let b: Box<dyn ActorProc> = Box::new(ActorCell{ actor: a, inbox: receiver, system: self.clone() });
- self.inner.write().spawn(b);
+ pub fn spawn<A: Actor + 'static>(&mut self, actor: A) -> ActorHandle<A::Message> {
+ let (sender, inbox) = mpsc::unbounded::<A::Message>();
+ let cx = ActorContext{ system: self.clone(), handle: ActorHandle{ channel: sender.clone() }};
+ let dyn_actor: Box<dyn ActorProc> = Box::new(ActorCell{ actor, inbox, cx });
+ self.inner.write().spawn(dyn_actor);
ActorHandle{ channel: sender }
}
@@ -151,7 +162,7 @@
impl Actor for Hello {
type Message = String;
- fn update(&mut self, msg: Self::Message, _system: System) {
+ fn update(&mut self, msg: Self::Message, _cx: ActorContext<Hello>) {
println!("Hello, {}", msg);
}
}
diff --git a/bin/bluetooth/gap/src/adapters.rs b/bin/bluetooth/gap/src/adapters.rs
index bd2aae2..ba3ab20 100644
--- a/bin/bluetooth/gap/src/adapters.rs
+++ b/bin/bluetooth/gap/src/adapters.rs
@@ -1,12 +1,14 @@
-use fuchsia_syslog::fx_log_warn;
+use fuchsia_syslog::{fx_log_warn, fx_log_info};
use fuchsia_vfs_watcher as vfs_watcher;
use fuchsia_vfs_watcher::{WatchEvent, WatchMessage};
use std::fs::File;
-use failure::Error;
+use failure::{Error, err_msg};
use std::io;
use std::path::{Path, PathBuf};
use futures::{Stream, TryStreamExt};
+use crate::host::{FidlHost, open_host_fidl};
+
// This module defines a watcher that subscribes to the device filesystem and
// produces a stream of messages when bt-host devices are added or removed from
// the system
@@ -43,4 +45,3 @@
},
})
}
-
diff --git a/bin/bluetooth/gap/src/host.rs b/bin/bluetooth/gap/src/host.rs
index 017e26b..36fd332 100644
--- a/bin/bluetooth/gap/src/host.rs
+++ b/bin/bluetooth/gap/src/host.rs
@@ -2,13 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+use failure::{Error, err_msg};
use fuchsia_async as fasync;
+use fuchsia_bluetooth::host::open_host_channel;
+use fuchsia_bluetooth::util::clone_host_info;
use fidl_fuchsia_bluetooth_control::AdapterInfo;
use fidl_fuchsia_bluetooth_host::HostProxy;
//use fidl_fuchsia_bluetooth_control::PairingDelegateMarker;
//use fidl_fuchsia_bluetooth_control::{InputCapabilityType, OutputCapabilityType};
//use fuchsia_syslog::{fx_log, fx_log_err, fx_log_info};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
//use fidl_fuchsia_bluetooth_host::HostEvent::*;
//use fidl_fuchsia_bluetooth_host::HostEvent;
@@ -16,6 +19,7 @@
use futures::future::FutureExt;
use futures::channel::oneshot;
use futures::channel::oneshot::Receiver;
+use std::fs::File;
//use crate::host_dispatcher::*;
use crate::types::bt;
@@ -33,9 +37,29 @@
/// Type representing a BT Adapter with a loaded Host Device Driver
pub struct FidlHost {
- _device_path: PathBuf,
+ device_path: PathBuf,
proxy: HostProxy,
- _info: AdapterInfo
+ info: AdapterInfo
+}
+
+impl FidlHost {
+ pub fn get_info(&self) -> AdapterInfo { clone_host_info(&self.info) }
+ pub fn path(&self) -> &Path { &self.device_path }
+}
+
+/// Initialize a HostDevice
+pub async fn open_host_fidl(device_path: PathBuf) -> Result<FidlHost, Error> {
+ // Connect to the host device.
+ let host = File::open(device_path.clone())
+ .map_err(|_| err_msg("failed to open bt-host device"))?;
+ let handle = open_host_channel(&host)?;
+ let handle = fasync::Channel::from_channel(handle.into())?;
+ let proxy = HostProxy::new(handle);
+
+ // Obtain basic information and create and entry in the disptacher's map.
+ let info = await!(proxy.get_info())
+ .map_err(|_| err_msg("failed to obtain bt-host information"))?;
+ Ok(FidlHost{ device_path, proxy, info })
}
//struct HostListener {}
diff --git a/bin/bluetooth/gap/src/host_dispatcher.rs b/bin/bluetooth/gap/src/host_dispatcher.rs
index 5f886a5..c452570 100644
--- a/bin/bluetooth/gap/src/host_dispatcher.rs
+++ b/bin/bluetooth/gap/src/host_dispatcher.rs
@@ -3,11 +3,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+use failure::Error;
use fidl_fuchsia_bluetooth_control::ControlRequest;
use fidl_fuchsia_bluetooth_host::HostEvent;
//use failure::Error;
//use fuchsia_async::{self as fasync, TimeoutExt};
//use fuchsia_syslog::{fx_log, fx_log_err, fx_log_info, fx_log_warn};
+use fuchsia_syslog::fx_log_info;
//use fuchsia_vfs_watcher as vfs_watcher;
//use fuchsia_vfs_watcher::{WatchEvent, WatchMessage};
//use fuchsia_zircon as zx;
@@ -18,13 +20,13 @@
use std::collections::HashMap;
//use std::marker::Unpin;
//use std::sync::{Arc, Weak};
-use futures::channel::mpsc;
+//use futures::channel::mpsc;
-use crate::actor::{Actor, ActorHandle, System};
+use crate::actor::{Actor, ActorHandle, ActorContext};
use crate::adapters::AdapterEvent;
use crate::adapters::AdapterEvent::*;
//use crate::host::*;
-use crate::host::Host;
+use crate::host::{Host, FidlHost};
use crate::types::bt;
use crate::types::*;
use crate::types::DiscoveryState::*;
@@ -56,16 +58,16 @@
//}
pub struct DiscoveryClient {}
-pub struct HostDispatcherHandle {}
+//pub struct HostDispatcherHandle {}
/// A token returned to someone who has requested discovery
pub struct DiscoverySession<H: Host> {
- dispatcher: mpsc::UnboundedSender<HostDispatcherMsg<H>>
+ dispatcher: ActorHandle<HostDispatcherMsg<H>>
}
impl<H: Host> Drop for DiscoverySession<H> {
fn drop(&mut self) {
- self.dispatcher.unbounded_send(HostDispatcherMsg::StopDiscovery);
+ self.dispatcher.send(HostDispatcherMsg::StopDiscovery);
}
}
@@ -79,10 +81,18 @@
}
}
- fn handle(&self) -> mpsc::UnboundedSender<HostDispatcherMsg<H>> {
+ fn handle(&self) -> ActorHandle<HostDispatcherMsg<H>> {
unreachable!()
}
+ //fn add_host(&mut self, id: HostId, host: AdapterInfo) {
+ //panic!("NYI");
+ //}
+
+ //fn rm_host(&mut self, id: HostId, host: H) {
+ //panic!("NYI");
+ //}
+
// TODO - what should this type signature be
// pub fn start_discovery(&mut self) -> bt::Result<DiscoverySession> {
//
@@ -124,6 +134,33 @@
}
}
+impl HostDispatcher<FidlHost> {
+ /// Adds an adapter to the host dispatcher. Called by the watch_hosts device watcher
+ pub async fn add_adapter(hd: HostDispatcher<FidlHost>, host: FidlHost) -> Result<(), Error> {
+ fx_log_info!("Adding Host Device: {:?}", host.path());
+ //let info = host.get_info();
+ // TODO
+ //await!(try_restore_bonds(host.clone(), self.clone(), &info.address.clone()))?;
+
+ //hd.adapters.push(info.identifier, host);
+
+ // Start listening to Host interface events.
+ //fasync::spawn(host::run(self.clone(), host.clone()).map(|_| ()));
+
+ Ok(())
+ }
+
+ //fn activate_host(host) {
+ // // Initialize bt-gap as this host's pairing delegate.
+ // start_pairing_delegate(self.clone(), host.clone())?;
+ // // TODO(NET-1445): Only the active host should be made connectable and scanning in the background.
+ // await!(host.read().set_connectable(true)).map_err(|_| err_msg("failed to set connectable"))?;
+ // host.read().enable_background_scan(true).map_err(|_| err_msg("failed to enable background scan"))?;
+ //}
+}
+
+
+
pub enum HostDispatcherMsg<H: Host> {
StartDiscovery(ActorHandle<bt::Result<DiscoverySession<H>>>),
StopDiscovery,
@@ -135,7 +172,7 @@
impl<H: Host + Send + Sync> Actor for HostDispatcher<H> {
type Message = HostDispatcherMsg<H>;
- fn update(&mut self, msg: Self::Message, _system: System) {
+ fn update(&mut self, msg: Self::Message, _cx: ActorContext<HostDispatcher<H>>) {
match msg {
HostDispatcherMsg::StartDiscovery(mut sender) => {
let session = self.start_discovery();
diff --git a/bin/bluetooth/gap/src/main.rs b/bin/bluetooth/gap/src/main.rs
index 75892ac..9476005 100644
--- a/bin/bluetooth/gap/src/main.rs
+++ b/bin/bluetooth/gap/src/main.rs
@@ -55,7 +55,7 @@
fasync::spawn({
let hd_ = hd.clone();
async {
- let r = await!(control_service(hd_, chan));
- r.unwrap_or_else(|e| eprintln!("Failed to spawn {:?}", e))
+ let r = await!(control_service(hd_, chan));
+ r.unwrap_or_else(|e| eprintln!("Failed to spawn {:?}", e))
}})
}