Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: replace winapi with windows-sys #70

Merged
merged 2 commits into from
Aug 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,20 @@ libc = "^0.2.158"
mach = { version = "^0.4.2", package = "mach2" }
core-foundation = "~0.10.0"

[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "~0.3.9", features = ["impl-default", "devguid", "winbase", "ioapiset", "ntdef", "setupapi", "handleapi", "errhandlingapi", "winerror"] }
[target.'cfg(target_os = "windows")'.dependencies.windows-sys]
version = "0.59.0"
features = [
"Win32_Devices",
"Win32_Devices_DeviceAndDriverInstallation",
"Win32_Foundation",
"Win32_Security",
"Win32_Storage",
"Win32_Storage_FileSystem",
"Win32_System",
"Win32_System_IO",
"Win32_System_Memory",
"Win32_System_Power",
]

[target.'cfg(any(target_os = "dragonfly", target_os = "freebsd"))'.dependencies]
libc = "~0.2.158"
Expand Down
4 changes: 0 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@
#[macro_use]
extern crate cfg_if;

#[cfg(target_os = "windows")]
#[macro_use]
extern crate winapi;

#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd"))]
#[macro_use]
extern crate nix;
Expand Down
48 changes: 40 additions & 8 deletions src/platform/windows/device.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use std::convert::AsRef;
use std::fmt;

use super::ffi::{BatteryQueryInformation, DeviceHandle};
use windows_sys::Win32::System::Power::BATTERY_QUERY_INFORMATION;

use super::ffi::DeviceHandle;
use crate::platform::traits::BatteryDevice;
use crate::units::{ElectricPotential, Energy, Power, ThermodynamicTemperature};
use crate::{Error, Result, State, Technology};

#[derive(Default)]
pub struct PowerDevice {
// Used later for information refreshing
tag: BatteryQueryInformation,
tag: BATTERY_QUERY_INFORMATION,

technology: Technology,
state: State,
Expand All @@ -25,6 +26,26 @@ pub struct PowerDevice {
serial_number: Option<String>,
}

impl Default for PowerDevice {
fn default() -> Self {
Self {
technology: Default::default(),
state: Default::default(),
voltage: Default::default(),
energy_rate: Default::default(),
capacity: Default::default(),
design_capacity: Default::default(),
full_charged_capacity: Default::default(),
temperature: None,
cycle_count: None,
device_name: None,
manufacturer: None,
serial_number: None,
tag: unsafe { std::mem::zeroed() },
}
}
}

impl PowerDevice {
pub fn try_from(mut handle: DeviceHandle) -> Result<Option<PowerDevice>> {
let info = handle.information()?;
Expand All @@ -47,7 +68,7 @@ impl PowerDevice {
};

let mut device = PowerDevice {
tag: handle.tag.clone(),
tag: handle.tag,
technology: info.technology(),
device_name,
manufacturer,
Expand Down Expand Up @@ -92,7 +113,7 @@ impl PowerDevice {
Ok(())
}

pub fn tag(&self) -> &BatteryQueryInformation {
pub fn tag(&self) -> &BATTERY_QUERY_INFORMATION {
&self.tag
}
}
Expand Down Expand Up @@ -148,9 +169,20 @@ impl BatteryDevice for PowerDevice {
}

impl fmt::Debug for PowerDevice {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("WindowsDevice")
.field("tag", &self.tag.battery_tag())
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PowerDevice")
.field("technology", &self.technology)
.field("state", &self.state)
.field("voltage", &self.voltage)
.field("energy_rate", &self.energy_rate)
.field("capacity", &self.capacity)
.field("design_capacity", &self.design_capacity)
.field("full_charged_capacity", &self.full_charged_capacity)
.field("temperature", &self.temperature)
.field("cycle_count", &self.cycle_count)
.field("device_name", &self.device_name)
.field("manufacturer", &self.manufacturer)
.field("serial_number", &self.serial_number)
.finish()
}
}
56 changes: 26 additions & 30 deletions src/platform/windows/ffi/ioctl/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,44 @@

#![allow(non_snake_case, clippy::unreadable_literal)]

use std::default::Default;
use std::mem;
use std::ops;
use std::str::{self, FromStr};

use crate::Technology;
use winapi::shared::ntdef;

pub const BATTERY_CAPACITY_RELATIVE: ntdef::ULONG = 0x40000000;
pub const BATTERY_SYSTEM_BATTERY: ntdef::ULONG = 0x80000000;
use std::str::FromStr;
use windows_sys::Win32::System::Power::*;

STRUCT! {#[cfg_attr(target_arch = "x86", repr(packed))] #[derive(Debug)] struct BATTERY_INFORMATION {
Capabilities: ntdef::ULONG,
Technology: ntdef::UCHAR,
Reserved: [ntdef::UCHAR; 3],
Chemistry: [ntdef::UCHAR; 4],
DesignedCapacity: ntdef::ULONG, // mWh
FullChargedCapacity: ntdef::ULONG, // mWh
DefaultAlert1: ntdef::ULONG,
DefaultAlert2: ntdef::ULONG,
CriticalBias: ntdef::ULONG,
CycleCount: ntdef::ULONG,
}}
pub struct BatteryInformation(BATTERY_INFORMATION);

impl Default for BATTERY_INFORMATION {
#[inline]
impl Default for BatteryInformation {
fn default() -> Self {
unsafe { mem::zeroed() }
Self(unsafe { std::mem::zeroed() })
}
}

#[derive(Debug, Default)]
pub struct BatteryInformation(BATTERY_INFORMATION);
impl std::fmt::Debug for BatteryInformation {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("BatteryInformation")
.field("Capabilities", &self.0.Capabilities)
.field("Technology", &self.technology())
.field("DesignedCapacity", &self.0.DesignedCapacity)
.field("FullChargedCapacity", &self.0.FullChargedCapacity)
.field("CycleCount", &self.0.CycleCount)
.finish()
}
}

impl From<BATTERY_INFORMATION> for BatteryInformation {
fn from(info: BATTERY_INFORMATION) -> Self {
Self(info)
}
}

impl ops::Deref for BatteryInformation {
impl std::ops::Deref for BatteryInformation {
type Target = BATTERY_INFORMATION;

fn deref(&self) -> &Self::Target {
&self.0
}
}
impl ops::DerefMut for BatteryInformation {
impl std::ops::DerefMut for BatteryInformation {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
Expand All @@ -61,8 +57,8 @@ impl BatteryInformation {
}

pub fn technology(&self) -> Technology {
let raw = unsafe { str::from_utf8_unchecked(&self.0.Chemistry) };
match Technology::from_str(raw) {
let raw = String::from_utf8_lossy(&self.0.Chemistry);
match Technology::from_str(&raw) {
Ok(tech) => tech,
Err(_) => Technology::Unknown,
}
Expand Down
31 changes: 0 additions & 31 deletions src/platform/windows/ffi/ioctl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,8 @@
// Each sub-module represents a C-level struct to respective IOCTL request
// and idiomatic Rust struct around it.

use winapi::shared::minwindef;

mod info;
mod query_info;
mod status;
mod wait_status;

pub use self::info::BatteryInformation;
pub use self::query_info::BatteryQueryInformation;
pub use self::status::BatteryStatus;
pub use self::wait_status::BatteryWaitStatus;

// Following values are based on the https://www.ioctls.net data
pub const IOCTL_BATTERY_QUERY_TAG: minwindef::DWORD = 0x294040;
pub const IOCTL_BATTERY_QUERY_INFORMATION: minwindef::DWORD = 0x294044;
pub const IOCTL_BATTERY_QUERY_STATUS: minwindef::DWORD = 0x29404c;

pub mod info_level {
#![allow(non_camel_case_types, non_upper_case_globals)]

/// For some reasons, "winapi==0.3.6" `ENUM!` macro fails to compile with
/// error: no rules expected the token `@`
/// so defining `BATTERY_QUERY_INFORMATION_LEVEL` "enum" manually.

pub type BATTERY_QUERY_INFORMATION_LEVEL = u32;

// pub const BatteryInformation: BATTERY_QUERY_INFORMATION_LEVEL = 0;
// pub const BatteryGranularityInformation: BATTERY_QUERY_INFORMATION_LEVEL = 1;
pub const BatteryTemperature: BATTERY_QUERY_INFORMATION_LEVEL = 2;
// pub const BatteryEstimatedTime: BATTERY_QUERY_INFORMATION_LEVEL = 3;
pub const BatteryDeviceName: BATTERY_QUERY_INFORMATION_LEVEL = 4;
// pub const BatteryManufactureDate: BATTERY_QUERY_INFORMATION_LEVEL = 5;
pub const BatteryManufactureName: BATTERY_QUERY_INFORMATION_LEVEL = 6;
// pub const BatteryUniqueID: BATTERY_QUERY_INFORMATION_LEVEL = 7;
pub const BatterySerialNumber: BATTERY_QUERY_INFORMATION_LEVEL = 8;
}
46 changes: 0 additions & 46 deletions src/platform/windows/ffi/ioctl/query_info.rs

This file was deleted.

55 changes: 22 additions & 33 deletions src/platform/windows/ffi/ioctl/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,30 @@

#![allow(non_snake_case, clippy::unreadable_literal)]

use std::default::Default;
use std::mem;
use std::ops;

use winapi::shared::ntdef;
use windows_sys::Win32::System::Power::*;

use crate::State;

/// Current battery capacity is unknown.
const BATTERY_UNKNOWN_CAPACITY: ntdef::ULONG = 0xFFFFFFFF;
/// Current battery voltage is unknown.
const BATTERY_UNKNOWN_VOLTAGE: ntdef::ULONG = 0xFFFFFFFF;
/// Current battery rage is unknown.
#[allow(overflowing_literals)]
const BATTERY_UNKNOWN_RATE: ntdef::LONG = 0x80000000;

/// Indicates that the battery is currently charging.
const BATTERY_CHARGING: ntdef::ULONG = 0x00000004;
/// Indicates that battery failure is imminent. See the Remarks section for more information.
const BATTERY_CRITICAL: ntdef::ULONG = 0x00000008;
/// Indicates that the battery is currently discharging.
const BATTERY_DISCHARGING: ntdef::ULONG = 0x00000002;
/// Indicates that the system has access to AC power, so no batteries are being discharged.
const BATTERY_POWER_ON_LINE: ntdef::ULONG = 0x00000001;

STRUCT! {#[cfg_attr(target_arch = "x86", repr(packed))] #[derive(Debug)] struct BATTERY_STATUS {
PowerState: ntdef::ULONG,
Capacity: ntdef::ULONG, // mWh or BATTERY_UNKNOWN_CAPACITY
Voltage: ntdef::ULONG, // mV or BATTERY_UNKNOWN_VOLTAGE
Rate: ntdef::LONG, // mW, might be negative
}}

impl Default for BATTERY_STATUS {
#[inline]
pub struct BatteryStatus(BATTERY_STATUS);

impl Default for BatteryStatus {
fn default() -> Self {
unsafe { mem::zeroed() }
Self(unsafe { std::mem::zeroed() })
}
}

#[derive(Debug, Default)]
pub struct BatteryStatus(BATTERY_STATUS);
impl std::fmt::Debug for BatteryStatus {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("PowerState")
.field("PowerState", &self.0.PowerState)
.field("Capacity", &self.capacity())
.field("Voltage", &self.voltage())
.field("Rate", &self.rate())
.finish()
}
}

impl ops::Deref for BatteryStatus {
type Target = BATTERY_STATUS;
Expand All @@ -57,6 +40,12 @@ impl ops::DerefMut for BatteryStatus {
}
}

impl From<BATTERY_STATUS> for BatteryStatus {
fn from(status: BATTERY_STATUS) -> Self {
Self(status)
}
}

impl BatteryStatus {
#[inline]
pub fn is_charging(&self) -> bool {
Expand Down Expand Up @@ -106,7 +95,7 @@ impl BatteryStatus {

/// The current rate of battery charge or discharge.
pub fn rate(&self) -> Option<i32> {
if self.0.Rate == BATTERY_UNKNOWN_RATE {
if self.0.Rate == BATTERY_UNKNOWN_RATE as i32 {
None
} else {
Some(self.0.Rate.abs())
Expand Down
Loading