Skip to content

Commit

Permalink
feat: replace winapi with windows-sys (#70)
Browse files Browse the repository at this point in the history
* feat: replace winapi with windows-sys

* bump windows-sys to v0.59.0
  • Loading branch information
davidkna authored Aug 31, 2024
1 parent f0b152c commit 7f69364
Show file tree
Hide file tree
Showing 11 changed files with 221 additions and 332 deletions.
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

0 comments on commit 7f69364

Please sign in to comment.