blob: 8b80262035b3caf20bfd86259293a29e6bf2570b [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.
extern crate libc;
use self::libc::{int32_t, uint32_t};
use fdio::{self, fdio_sys, make_ioctl};
use fuchsia_async as fasync;
use fuchsia_syslog::{fx_log_err, fx_vlog};
use fuchsia_zircon::{self as zx, Signals, sys::zx_handle_t};
use futures::TryFutureExt;
use std::fs::File;
use std::io::{self, Result};
use std::marker::Send;
use std::mem;
use std::os::raw;
use std::ptr;
const IOCTL_POWER_GET_INFO: raw::c_int = make_ioctl!(
fdio_sys::IOCTL_KIND_DEFAULT,
fdio_sys::IOCTL_FAMILY_POWER,
1
);
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct ioctl_power_get_info_t {
pub power_type: uint32_t,
pub state: uint32_t,
}
const IOCTL_POWER_GET_BATTERY_INFO: raw::c_int = make_ioctl!(
fdio_sys::IOCTL_KIND_DEFAULT,
fdio_sys::IOCTL_FAMILY_POWER,
2
);
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct ioctl_power_get_battery_info_t {
pub unit: uint32_t,
pub design_capacity: uint32_t,
pub last_full_capacity: uint32_t,
pub design_voltage: uint32_t,
pub capacity_warning: uint32_t,
pub capacity_low: uint32_t,
pub capacity_granularity_low_warning: uint32_t,
pub capacity_granularity_warning_full: uint32_t,
pub present_rate: int32_t,
pub remaining_capacity: uint32_t,
pub present_voltage: uint32_t,
}
impl ioctl_power_get_battery_info_t {
pub fn new() -> ioctl_power_get_battery_info_t {
ioctl_power_get_battery_info_t::default()
}
}
const IOCTL_POWER_GET_STATE_CHANGE_EVENT: raw::c_int = make_ioctl!(
fdio_sys::IOCTL_KIND_GET_HANDLE,
fdio_sys::IOCTL_FAMILY_POWER,
3
);
pub const POWER_TYPE_AC: uint32_t = 0;
pub const POWER_TYPE_BATTERY: uint32_t = 1;
pub const POWER_STATE_ONLINE: uint32_t = 1 << 0;
pub const POWER_STATE_DISCHARGING: uint32_t = 1 << 1;
pub const POWER_STATE_CHARGING: uint32_t = 1 << 2;
pub const POWER_STATE_CRITICAL: uint32_t = 1 << 3;
pub fn get_power_info(file: &File) -> Result<ioctl_power_get_info_t> {
let mut powerbuffer = ioctl_power_get_info_t {
power_type: 0,
state: 0,
};
let powerbuffer_ptr = &mut powerbuffer as *mut _ as *mut ::std::os::raw::c_void;
let _ = unsafe {
fdio::ioctl(
&file,
IOCTL_POWER_GET_INFO,
ptr::null(),
0,
powerbuffer_ptr,
mem::size_of::<ioctl_power_get_info_t>(),
).map_err(|e| e.into_io_error())?;
};
Ok(powerbuffer)
}
pub fn get_battery_info(file: &File) -> Result<ioctl_power_get_battery_info_t> {
let mut batterybuffer: ioctl_power_get_battery_info_t = ioctl_power_get_battery_info_t::new();
let batterybuffer_ptr = &mut batterybuffer as *mut _ as *mut ::std::os::raw::c_void;
let _ = unsafe {
fdio::ioctl(
&file,
IOCTL_POWER_GET_BATTERY_INFO,
ptr::null(),
0,
batterybuffer_ptr,
mem::size_of::<ioctl_power_get_battery_info_t>(),
).map_err(|e| e.into_io_error())?;
};
Ok(batterybuffer)
}
pub fn add_listener<F>(file: &File, callback: F) -> Result<()>
where
F: 'static + Send + Fn(&File) + Sync,
{
let mut handle: zx_handle_t = 0;
let handle_ptr = &mut handle as *mut _ as *mut ::std::os::raw::c_void;
unsafe {
fdio::ioctl(
&file,
IOCTL_POWER_GET_STATE_CHANGE_EVENT,
ptr::null(),
0,
handle_ptr,
mem::size_of::<zx_handle_t>(),
).map_err(|e| e.into_io_error())?;
};
let h = unsafe { zx::Handle::from_raw(handle) };
let file_copy = file
.try_clone()
.map_err(|e| io::Error::new(e.kind(), format!("error copying power device file: {}", e)))?;
fasync::spawn(async move {
loop {
let _signals = await!(fasync::OnSignals::new(&h, Signals::USER_0))?;
fx_vlog!(1, "callback called {:?}", file_copy);
callback(&file_copy);
}
}.unwrap_or_else(|e: failure::Error| {
fx_log_err!(
"not able to apply listener to power device, wait failed: {:?}",
e
)
}));
Ok(())
}