Initial commit
This commit is contained in:
282
vendor/github.com/distatus/battery/battery_openbsd.go
generated
vendored
Normal file
282
vendor/github.com/distatus/battery/battery_openbsd.go
generated
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
// battery
|
||||
// Copyright (C) 2016-2017,2019,2023 Karol 'Kenji Takahashi' Woźniak
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package battery
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func sysctl(mib []int32, out unsafe.Pointer, n uintptr) unix.Errno {
|
||||
_, _, e := unix.Syscall6(
|
||||
unix.SYS___SYSCTL,
|
||||
uintptr(unsafe.Pointer(&mib[0])),
|
||||
uintptr(len(mib)),
|
||||
uintptr(out),
|
||||
uintptr(unsafe.Pointer(&n)),
|
||||
uintptr(unsafe.Pointer(nil)),
|
||||
0,
|
||||
)
|
||||
return e
|
||||
}
|
||||
|
||||
var errValueNotFound = fmt.Errorf("Value not found")
|
||||
|
||||
func setErr(err *error, newErr error) {
|
||||
if *err == errValueNotFound {
|
||||
*err = newErr
|
||||
}
|
||||
}
|
||||
|
||||
var sensorW = [4]int32{
|
||||
2, // SENSOR_VOLTS_DC (uV)
|
||||
5, // SENSOR_WATTS (uW)
|
||||
7, // SENSOR_WATTHOUR (uWh)
|
||||
10, // SENSOR_INTEGER
|
||||
}
|
||||
|
||||
const (
|
||||
sensorA = 6 // SENSOR_AMPS (uA)
|
||||
sensorAH = 8 // SENSOR_AMPHOUR (uAh)
|
||||
)
|
||||
|
||||
type sensorStatus int32
|
||||
|
||||
const (
|
||||
unspecified sensorStatus = iota
|
||||
ok
|
||||
warning
|
||||
critical
|
||||
unknown
|
||||
)
|
||||
|
||||
type sensor struct {
|
||||
desc [32]byte
|
||||
tv [16]byte // struct timeval
|
||||
value int64
|
||||
typ [4]byte // enum sensor_type
|
||||
status sensorStatus
|
||||
numt int32
|
||||
flags int32
|
||||
}
|
||||
|
||||
func (s *sensor) readValue(div float64) (float64, error) {
|
||||
if s.status == unknown {
|
||||
return 0, fmt.Errorf("Unknown value received")
|
||||
}
|
||||
|
||||
return float64(s.value) / div, nil
|
||||
}
|
||||
|
||||
func (s *sensor) handleA(factor float64, field *float64, fieldErr *error) {
|
||||
*field, *fieldErr = s.readValue(1000)
|
||||
if *fieldErr == nil {
|
||||
*field *= factor
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sensor) handleAH(factor float64, factorErr error, field *float64, fieldErr *error) {
|
||||
if factorErr != nil {
|
||||
*fieldErr = factorErr
|
||||
return
|
||||
}
|
||||
s.handleA(factor, field, fieldErr)
|
||||
}
|
||||
|
||||
type sensordev struct {
|
||||
num int32
|
||||
xname [16]byte
|
||||
maxnumt [23]int32
|
||||
sensors_count int32
|
||||
}
|
||||
|
||||
func (sd *sensordev) get() (*Battery, error) {
|
||||
var battery Battery
|
||||
err := ErrPartial{
|
||||
Design: errValueNotFound,
|
||||
Full: errValueNotFound,
|
||||
Current: errValueNotFound,
|
||||
ChargeRate: errValueNotFound,
|
||||
State: errValueNotFound,
|
||||
Voltage: errValueNotFound,
|
||||
DesignVoltage: errValueNotFound,
|
||||
}
|
||||
|
||||
mib := []int32{unix.CTL_HW, 11, sd.num, 0, 0}
|
||||
var s sensor
|
||||
|
||||
iter := func(maxnumtIdx int32, cb func(string)) {
|
||||
mib[3] = maxnumtIdx
|
||||
|
||||
for i := int32(0); i < sd.maxnumt[maxnumtIdx]; i++ {
|
||||
mib[4] = i
|
||||
|
||||
if errno := sysctl(mib, unsafe.Pointer(&s), unsafe.Sizeof(s)); errno != 0 {
|
||||
setErr(&err.Design, errno)
|
||||
setErr(&err.Full, errno)
|
||||
setErr(&err.Current, errno)
|
||||
setErr(&err.ChargeRate, errno)
|
||||
setErr(&err.Voltage, errno)
|
||||
setErr(&err.DesignVoltage, errno)
|
||||
setErr(&err.State, errno)
|
||||
}
|
||||
|
||||
// Convert 0-terminated C-string to a Go string
|
||||
cb(string(s.desc[:bytes.IndexByte(s.desc[:], 0)]))
|
||||
}
|
||||
}
|
||||
|
||||
for _, w := range sensorW {
|
||||
mib[3] = w
|
||||
|
||||
iter(w, func(desc string) {
|
||||
if strings.HasPrefix(desc, "battery ") {
|
||||
battery.State.specific, err.State = desc, nil
|
||||
|
||||
switch desc[8:] {
|
||||
case "unknown":
|
||||
battery.State.Raw = Unknown
|
||||
case "full":
|
||||
battery.State.Raw = Full
|
||||
case "charging":
|
||||
battery.State.Raw = Charging
|
||||
case "discharging":
|
||||
battery.State.Raw = Discharging
|
||||
case "idle":
|
||||
battery.State.Raw = Idle
|
||||
case "critical":
|
||||
battery.State.Raw = Empty
|
||||
default:
|
||||
battery.State.Raw = Undefined
|
||||
}
|
||||
return
|
||||
}
|
||||
switch desc {
|
||||
case "rate":
|
||||
battery.ChargeRate, err.ChargeRate = s.readValue(1000)
|
||||
case "design capacity":
|
||||
battery.Design, err.Design = s.readValue(1000)
|
||||
case "last full capacity":
|
||||
battery.Full, err.Full = s.readValue(1000)
|
||||
case "remaining capacity":
|
||||
battery.Current, err.Current = s.readValue(1000)
|
||||
case "current voltage":
|
||||
battery.Voltage, err.Voltage = s.readValue(1000_000)
|
||||
case "voltage":
|
||||
battery.DesignVoltage, err.DesignVoltage = s.readValue(1000_000)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if err.DesignVoltage != nil && err.Voltage == nil {
|
||||
battery.DesignVoltage, err.DesignVoltage = battery.Voltage, nil
|
||||
}
|
||||
if err.ChargeRate == errValueNotFound {
|
||||
if err.Voltage == nil {
|
||||
iter(sensorA, func(desc string) {
|
||||
if desc == "rate" {
|
||||
s.handleA(battery.Voltage, &battery.ChargeRate, &err.ChargeRate)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
err.ChargeRate = err.Voltage
|
||||
}
|
||||
}
|
||||
if err.Design == errValueNotFound || err.Full == errValueNotFound || err.Current == errValueNotFound {
|
||||
iter(sensorAH, func(desc string) {
|
||||
switch desc {
|
||||
case "design capacity":
|
||||
s.handleAH(battery.DesignVoltage, err.DesignVoltage, &battery.Design, &err.Design)
|
||||
case "last full capacity":
|
||||
s.handleAH(battery.Voltage, err.Voltage, &battery.Full, &err.Full)
|
||||
case "remaining capacity":
|
||||
s.handleAH(battery.Voltage, err.Voltage, &battery.Current, &err.Current)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return &battery, err
|
||||
}
|
||||
|
||||
func getBatteryAtMIBIndex(i int32) (*Battery, int32, error) {
|
||||
mib := []int32{
|
||||
unix.CTL_HW,
|
||||
11, // HW_SENSORS
|
||||
0,
|
||||
}
|
||||
var sd sensordev
|
||||
for ; ; i++ {
|
||||
mib[2] = i
|
||||
|
||||
errno := sysctl(mib, unsafe.Pointer(&sd), unsafe.Sizeof(sd))
|
||||
if errno == unix.ENOENT {
|
||||
break
|
||||
}
|
||||
if errno != 0 {
|
||||
continue
|
||||
}
|
||||
if bytes.HasPrefix(sd.xname[:], []byte("acpibat")) {
|
||||
battery, err := sd.get()
|
||||
return battery, i + 1, err
|
||||
}
|
||||
}
|
||||
return nil, i, nil
|
||||
}
|
||||
|
||||
func systemGet(idx int) (*Battery, error) {
|
||||
var i int32
|
||||
for idxCurr := 0; ; idxCurr++ {
|
||||
battery, iNext, err := getBatteryAtMIBIndex(i)
|
||||
// If this is the index we look for, grab it.
|
||||
// Otherwise just move on, regardless of errors etc.
|
||||
if idxCurr == idx {
|
||||
return battery, err
|
||||
}
|
||||
|
||||
i = iNext
|
||||
}
|
||||
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
func systemGetAll() ([]*Battery, error) {
|
||||
var batteries []*Battery
|
||||
var errors Errors
|
||||
|
||||
var i int32
|
||||
for {
|
||||
battery, iNext, err := getBatteryAtMIBIndex(i)
|
||||
if battery == nil && err == nil { // no more batteries
|
||||
break
|
||||
}
|
||||
batteries = append(batteries, battery)
|
||||
errors = append(errors, err)
|
||||
|
||||
i = iNext
|
||||
}
|
||||
|
||||
return batteries, errors
|
||||
}
|
||||
Reference in New Issue
Block a user