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

NetBSD support #20

Open
svartalf opened this issue Mar 11, 2019 · 14 comments
Open

NetBSD support #20

svartalf opened this issue Mar 11, 2019 · 14 comments
Labels
A-battery Area: battery crate C-enhancement New feature or request O-netbsd Operating system: NetBSD

Comments

@svartalf
Copy link
Owner

This is a tracking issue for NetBSD support.

@svartalf svartalf added C-enhancement New feature or request O-netbsd Operating system: NetBSD A-battery Area: battery crate labels Mar 11, 2019
@svartalf svartalf added this to the v0.8 milestone Jun 3, 2019
@svartalf svartalf pinned this issue Jun 4, 2019
@svartalf
Copy link
Owner Author

svartalf commented Jun 6, 2019

Blocked by the ebarnard/rust-plist#34

@svartalf svartalf self-assigned this Jun 6, 2019
@svartalf svartalf removed their assignment Apr 24, 2020
@svartalf svartalf removed this from the v0.8 milestone Apr 24, 2020
@rtyler
Copy link

rtyler commented Jan 10, 2021

FWIW the 0.4.2 release of rust-plist has the change referenced above

@svartalf
Copy link
Owner Author

Thanks for heads up, @rtyler! I tried to tackle this issue with NetBSD installed on a VirtualBox, but it was not able to emulate battery for some reasons, so I postponed it for a while.

@rtyler
Copy link

rtyler commented Jan 17, 2021

I have a NetBSD-based Pinebook Pro, if you have some pointers, I could take a look at wiring this up in my spurious free time 😸

@svartalf
Copy link
Owner Author

@rtyler that would be really great, thanks!

I know nothing about NetBSD, so it would be great to start with figuring out what it can provide to us, looks like envstat tool should help us to do that?

Seems like Golang implementation uses ioctl to read the same information from /dev/sysmon fd with ENVSYS_GETDICTIONARY ioctl type (?) and it returns back proplist with whatever data there is.

When we will know what data we can operate with, we will need to check if it will be enough to fill Battery struct with it; if it is the case - everything is great, otherwise we might need to change public API first to suit NetBSD changes (I can work on that).

@0-wiz-0
Copy link

0-wiz-0 commented Jun 4, 2021

A friend complained that this crate does not support NetBSD, so I took a quick look at it. Adding 'target_os = "netbsd"' to all "freebsd" cases makes it compile, but the 5 tests fail. So I guess that is not sufficient :)
(NetBSD also uses acpica (same as FreeBSD) that's why I thought this might be enough.)
Then I found this issue.

NetBSD's envstat source code is here:
https://github.com/NetBSD/src/tree/trunk/usr.sbin/envstat

@0-wiz-0
Copy link

0-wiz-0 commented Jun 4, 2021

The general framework for system monitoring and power management on NetBSD is sysmon (https://man.netbsd.org/sysmon.4) and in particular for environmental sensors, sysmon_envsys (kernel side documented here: https://man.netbsd.org/sysmon_envsys.9, but that does not really apply here). I hope this is sufficient information!

@bsiegert
Copy link

@svartalf What you describe (read /dev/sysmon) is exactly what envstat does too. Caveat: by default, only root may read from the sysmon device, so there should be some fallback (e.g. pretend there is no battery?).

@he32
Copy link

he32 commented Jun 23, 2021

Another piece to take a look at could be e.g. https://github.com/NetBSD/pkgsrc/tree/trunk/sysutils/xbattbar which in the patches/ sub-directory contains a patch for adapting this to NetBSD. It is considerably smaller than the envstat program. And as far as I can see, neither envstat nor xbattbar needs to be set-uid-root to work.

@0-wiz-0
Copy link

0-wiz-0 commented Jun 27, 2021

Here's some sample code that gives a plist:

use std::error::Error;                                                                                                                                             
use std::fs::File;                                                                                                                                                 
use std::os::unix::io::AsRawFd;                                                                                                                                    
use nix::ioctl_readwrite;                                                                                                                                          
use std::ffi::c_void;                                                                                                                                              
use std::mem::MaybeUninit;                                                                                                                                         
use plist::Value;                                                                                                                                                  
use std::slice::from_raw_parts;                                                                                                                                    
use std::io::Cursor;                                                                                                                                               
                                                                                                                                                                   
#[allow(non_camel_case_types)]                                                                                                                                     
#[repr(C)]                                                                                                                                                         
#[derive(Debug)]                                                                                                                                                   
pub struct plistref {                                                                                                                                              
        pref_plist: *mut c_void,               /* plist data */                                                                                                    
        pref_len: usize,                /* total length of plist data */                                                                                           
}                                                                                                                                                                  
                                                                                                                                                                   
ioctl_readwrite!(envsys_getdictionary, b'E', 0, plistref);                                                                                                         
                                                                                                                                                                   
fn main() {                                                                                                                                                        
    match detect_sensors() {                                                                                                                                       
        Ok(_) => (),                                                                                                                                               
        Err(err) => println!("error: {}", err),                                                                                                                    
    }                                                                                                                                                              
}                                                                                                                                                                  
                                                                                                                                                                   
fn detect_sensors() -> Result <(), Box<dyn Error>> {                                                                                                               
    let envsys = File::open("/dev/sysmon")?;                                                                                                                       
    let mut dict = MaybeUninit::<plistref>::uninit();                                                                                                              
    let _res = unsafe { envsys_getdictionary(envsys.as_raw_fd(), dict.as_mut_ptr()) };                                                                             
    let dict = unsafe { dict.assume_init() };                                                                                                                      
    let u8slice: &[u8] = unsafe { from_raw_parts(dict.pref_plist as *const u8, dict.pref_len) };                                                                   
    let cursor = Cursor::new(u8slice);                                                                                                                             
    let value = Value::from_reader(cursor)?;                                                                                                                       
    println!("{:?}", value);                                                                                                                                       
    Ok(())                                                                                                                                                         
}

On one of my systems that prints:

Dictionary({"amdzentemp0": Array([Dictionary({"cur-value": Integer(314900000), "description": String("cpu0 temperature"), "index": String("sensor0"), "monitoring-state-refresh-event": Boolean(true), "monitoring-supported": Boolean(true), "state": String("valid"), "type": String("Temperature")}), Dictionary({"cur-value": Integer(313150000), "description": String("cpu0 ccd0 temperature"), "index": String("sensor1"), "monitoring-state-refresh-event": Boolean(true), "monitoring-supported": Boolean(true), "state": String("valid"), "type": String("Temperature")}), Dictionary({"device-properties": Dictionary({"device-class": String("other"), "refresh-timeout": Integer(30)})})]), "amdzentemp1": Array([Dictionary({"cur-value": Integer(311775000), "description": String("cpu1 temperature"), "index": String("sensor0"), "monitoring-state-refresh-event": Boolean(true), "monitoring-supported": Boolean(true), "state": String("valid"), "type": String("Temperature")}), Dictionary({"device-properties": Dictionary({"device-class": String("other"), "refresh-timeout": Integer(30)})})])})

Sorry, I don't currently have a laptop with NetBSD i.e. no battery to test with.

@0-wiz-0
Copy link

0-wiz-0 commented Jun 27, 2021

Cargo dependencies:

[dependencies]
nix = "*"
plist = "*"

@0-wiz-0
Copy link

0-wiz-0 commented Jun 27, 2021

I put the code here for easier testing.
Pull requests welcome!

@0-wiz-0
Copy link

0-wiz-0 commented Jul 4, 2021

I've extended the example code to include basic parsing of the structure and adding some example outputs, including one from a laptop with a battery. I think this now contains enough information that you should be able to extract the information you need rather easily. Can you take over from here?

@naguam
Copy link

naguam commented May 3, 2024

A lot of project are still depending on this library instead of using Starship's fork.

I just made the full port for NetBSD.

starship#69

Are you (and especially the maintainer) interested by a backport ?

I don't think it should be too hard.

The interest might be about the ffi that the Starship's fork removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-battery Area: battery crate C-enhancement New feature or request O-netbsd Operating system: NetBSD
Projects
None yet
Development

No branches or pull requests

6 participants