blob: e9431ea0945c73a54398a0550dad84d76143b9b3 [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.
#![deny(warnings)]
use failure::{Error, ResultExt, format_err};
use fidl_fuchsia_wlan_device as wlan;
use fuchsia_async as fasync;
use fuchsia_wlan_dev as wlan_dev;
use futures::prelude::*;
use std::convert::Into;
use std::fs::{File, OpenOptions};
use std::path::Path;
use fidl_fuchsia_device_test::CONTROL_DEVICE;
mod sys;
const DEV_TEST: &str = CONTROL_DEVICE;
const WLAN: &str = "wlan";
const WLAN_DRIVER_NAME: &str = "/system/driver/wlanphy-testdev.so";
fn dev_wlanphy() -> String {
let mut s = String::from(DEV_TEST);
s.push_str("/wlan/wlanphy-test");
s
}
fn usage(appname: &str) {
eprintln!("usage: {} [add|rm|query|create|destroy <n>]", appname);
}
fn open_rdwr<P: AsRef<Path>>(path: P) -> Result<File, Error> {
OpenOptions::new().read(true).write(true).open(path).map_err(Into::into)
}
fn get_proxy() -> Result<(fasync::Executor, wlan::PhyProxy), Error> {
let executor = fasync::Executor::new().context("error creating event loop")?;
let phy = wlan_dev::Device::new(&dev_wlanphy())?;
let proxy = wlan_dev::connect_wlan_phy(&phy)?;
Ok((executor, proxy))
}
fn add_wlanphy() -> Result<(), Error> {
let devpath = sys::create_test_device(DEV_TEST, WLAN)?;
println!("created test device at {:?}", devpath);
// The device created above might not show up in the /dev filesystem right away. Loop until we
// have the device opened (or we give up).
// Note: a directory watcher could work too, but may be a bit heavy for this use-case.
let mut retry = 0;
let mut dev = None;
{
while retry < 100 {
retry += 1;
if let Ok(d) = open_rdwr(&devpath) {
dev = Some(d);
break;
}
}
}
let dev = dev.ok_or(format_err!("could not open {:?}", devpath))?;
sys::bind_test_device(&dev, WLAN_DRIVER_NAME)
}
fn rm_wlanphy() -> Result<(), Error> {
let path = Path::new(DEV_TEST).join(WLAN);
let dev = open_rdwr(path.clone())?;
sys::destroy_test_device(&dev)
.map(|_| println!("{:?} destroyed", path))
}
fn query_wlanphy() -> Result<(), Error> {
let (mut executor, proxy) = get_proxy()?;
let fut = proxy.query().map_ok(|resp| {
println!("query results: {:?}", resp.info);
});
executor.run_singlethreaded(fut).map_err(Into::into)
}
fn create_wlanintf() -> Result<(), Error> {
let (mut executor, proxy) = get_proxy()?;
let mut req = wlan::CreateIfaceRequest { role: wlan::MacRole::Client };
let fut = proxy.create_iface(&mut req).map_ok(|resp| {
println!("create results: {:?}", resp);
});
executor.run_singlethreaded(fut).map_err(Into::into)
}
fn destroy_wlanintf(id: u16) -> Result<(), Error> {
let (mut executor, proxy) = get_proxy()?;
let mut req = wlan::DestroyIfaceRequest { id: id };
let fut = proxy.destroy_iface(&mut req).map_ok(|resp| {
println!("destroyed intf {} resp: {:?}", id, resp);
});
executor.run_singlethreaded(fut).map_err(Into::into)
}
fn main() -> Result<(), Error> {
let args: Vec<_> = std::env::args().collect();
let appname = &args[0];
if args.len() < 2 {
usage(appname);
return Ok(());
}
let command = &args[1];
match command.as_ref() {
"add" => add_wlanphy(),
"rm" => rm_wlanphy(),
"query" => query_wlanphy(),
"create" => create_wlanintf(),
"destroy" => {
if args.len() < 3 {
usage(appname);
Ok(())
} else {
let id = u16::from_str_radix(&args[2], 10)?;
destroy_wlanintf(id)
}
},
_ => {
usage(appname);
Ok(())
}
}
}