blob: a9309c241c3aabf9073c6c33e4e56bb61d176945 [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};
use fdio::{self, fdio_sys};
use fidl::{self, DecodablePtr, EncodablePtr};
use std::fs::File;
use std::os::raw;
use std::os::unix::io::AsRawFd;
use wlan;
use zircon;
unsafe fn ioctl(dev: &File, op: raw::c_int, in_buf: &[u8], out_buf: &mut [u8])
-> Result<i32, zircon::Status> {
let in_ptr = if in_buf.len() > 0 {
in_buf.as_ptr() as *const raw::c_void
} else {
::std::ptr::null()
};
let out_ptr = if out_buf.len() > 0 {
out_buf.as_mut_ptr() as *mut raw::c_void
} else {
::std::ptr::null_mut()
};
match fdio::ioctl(dev.as_raw_fd(), op, in_ptr, in_buf.len(), out_ptr, out_buf.len()) as i32 {
e if e < 0 => Err(zircon::Status::from_raw(e)),
e => Ok(e),
}
}
pub fn query_wlanphy_device(device: &File) -> Result<wlan::WlanInfo, Error> {
let mut info = vec![0; 2048];
// This call is safe because the length of the output buffer is passed based on the length of
// the |info| vector. The callee will not retain any pointers from this call.
unsafe {
ioctl(device, IOCTL_WLANPHY_QUERY, &[], &mut info).context("failure in ioctl wlan query")?;
}
let mut buf = fidl::DecodeBuf::new_with(zircon::MessageBuf::new_with(info, vec![]));
wlan::WlanInfo::decode_obj(&mut buf, 0).map_err(|e| e.into())
}
pub fn create_wlaniface(device: &File, role: wlan::MacRole) -> Result<wlan::WlanIface, Error> {
let mut buf = fidl::EncodeBuf::new();
let req = wlan::CreateIfaceRequest{ role: role };
req.encode_obj(&mut buf);
let mut info = vec![0; 1024];
// This call is safe because the length of the buffers are passed based on the length of
// the |buf| and |info| vectors. The callee will not retain any pointers from this call.
unsafe {
ioctl(device, IOCTL_WLANPHY_CREATE_IFACE,
buf.get_bytes(), &mut info).context("failure in ioctl wlan create iface")?;
}
let mut recvbuf = fidl::DecodeBuf::new_with(zircon::MessageBuf::new_with(info, vec![]));
wlan::WlanIface::decode_obj(&mut recvbuf, 0).map_err(|e| e.into())
}
pub fn destroy_wlaniface(device: &File, id: u16) -> Result<(), zircon::Status> {
let mut buf = fidl::EncodeBuf::new();
let req = wlan::DestroyIfaceRequest{ id: id };
req.encode_obj(&mut buf);
// This call is safe because the length of the buffer is passed based on the length of
// the |buf| vector. The callee will not retain any pointers from this call.
unsafe {
ioctl(device, IOCTL_WLANPHY_DESTROY_IFACE, buf.get_bytes(), &mut []).map(|_| ())
}
}
const IOCTL_WLANPHY_QUERY: raw::c_int = make_ioctl!(
fdio_sys::IOCTL_KIND_DEFAULT,
fdio_sys::IOCTL_FAMILY_WLANPHY,
0
);
const IOCTL_WLANPHY_CREATE_IFACE: raw::c_int = make_ioctl!(
fdio_sys::IOCTL_KIND_DEFAULT,
fdio_sys::IOCTL_FAMILY_WLANPHY,
1
);
const IOCTL_WLANPHY_DESTROY_IFACE: raw::c_int = make_ioctl!(
fdio_sys::IOCTL_KIND_DEFAULT,
fdio_sys::IOCTL_FAMILY_WLANPHY,
2
);