mirror of https://github.com/cjbassi/gotop.git
Update gopsutil
This commit is contained in:
parent
a65523dab6
commit
84570dfed1
|
@ -58,7 +58,7 @@
|
|||
"net",
|
||||
"process"
|
||||
]
|
||||
revision = "cd915bdc31582b0a56405ede7fa2f4ab043f851b"
|
||||
revision = "57f370e13068146efe1cb7129f79e5d51da8a242"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
|
|
@ -117,6 +117,10 @@ Several methods have been added which are not present in psutil, but will provid
|
|||
- VirtualizationSystem (ex: "LXC")
|
||||
- VirtualizationRole (ex: "guest"/"host")
|
||||
|
||||
- IOCounters
|
||||
|
||||
- Label (linux only) The registered [device mapper name](https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm)
|
||||
|
||||
- cpu/CPUInfo() (linux, freebsd)
|
||||
|
||||
- CPU (ex: 0, 1, ...)
|
||||
|
|
|
@ -42,6 +42,7 @@ type IOCountersStat struct {
|
|||
WeightedIO uint64 `json:"weightedIO"`
|
||||
Name string `json:"name"`
|
||||
SerialNumber string `json:"serialNumber"`
|
||||
Label string `json:"label"`
|
||||
}
|
||||
|
||||
func (d UsageStat) String() string {
|
||||
|
|
|
@ -5,6 +5,7 @@ package disk
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
@ -370,6 +371,8 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
|||
d.Name = name
|
||||
|
||||
d.SerialNumber = GetDiskSerialNumber(name)
|
||||
d.Label = GetLabel(name)
|
||||
|
||||
ret[name] = d
|
||||
}
|
||||
return ret, nil
|
||||
|
@ -406,6 +409,26 @@ func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// GetLabel returns label of given device or empty string on error.
|
||||
// Name of device is expected, eg. /dev/sda
|
||||
// Supports label based on devicemapper name
|
||||
// See https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm
|
||||
func GetLabel(name string) string {
|
||||
// Try label based on devicemapper name
|
||||
dmname_filename := common.HostSys(fmt.Sprintf("block/%s/dm/name", name))
|
||||
|
||||
if !common.PathExists(dmname_filename) {
|
||||
return ""
|
||||
}
|
||||
|
||||
dmname, err := ioutil.ReadFile(dmname_filename)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return string(dmname)
|
||||
}
|
||||
}
|
||||
|
||||
func getFsType(stat unix.Statfs_t) string {
|
||||
t := int64(stat.Type)
|
||||
ret, ok := fsTypeMap[t]
|
||||
|
|
|
@ -217,3 +217,11 @@ func KernelVersionWithContext(ctx context.Context) (string, error) {
|
|||
_, _, version, err := PlatformInformation()
|
||||
return version, err
|
||||
}
|
||||
|
||||
func SensorsTemperatures() ([]TemperatureStat, error) {
|
||||
return SensorsTemperaturesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
||||
return []TemperatureStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
// +build darwin
|
||||
// +build cgo
|
||||
|
||||
package host
|
||||
|
||||
// #cgo LDFLAGS: -framework IOKit
|
||||
// #include "include/smc.c"
|
||||
import "C"
|
||||
import "context"
|
||||
|
||||
func SensorsTemperatures() ([]TemperatureStat, error) {
|
||||
return SensorsTemperaturesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
||||
temperatureKeys := []string{
|
||||
C.AMBIENT_AIR_0,
|
||||
C.AMBIENT_AIR_1,
|
||||
C.CPU_0_DIODE,
|
||||
C.CPU_0_HEATSINK,
|
||||
C.CPU_0_PROXIMITY,
|
||||
C.ENCLOSURE_BASE_0,
|
||||
C.ENCLOSURE_BASE_1,
|
||||
C.ENCLOSURE_BASE_2,
|
||||
C.ENCLOSURE_BASE_3,
|
||||
C.GPU_0_DIODE,
|
||||
C.GPU_0_HEATSINK,
|
||||
C.GPU_0_PROXIMITY,
|
||||
C.HARD_DRIVE_BAY,
|
||||
C.MEMORY_SLOT_0,
|
||||
C.MEMORY_SLOTS_PROXIMITY,
|
||||
C.NORTHBRIDGE,
|
||||
C.NORTHBRIDGE_DIODE,
|
||||
C.NORTHBRIDGE_PROXIMITY,
|
||||
C.THUNDERBOLT_0,
|
||||
C.THUNDERBOLT_1,
|
||||
C.WIRELESS_MODULE,
|
||||
}
|
||||
var temperatures []TemperatureStat
|
||||
|
||||
C.open_smc()
|
||||
defer C.close_smc()
|
||||
|
||||
for _, key := range temperatureKeys {
|
||||
temperatures = append(temperatures, TemperatureStat{
|
||||
SensorKey: key,
|
||||
Temperature: float64(C.get_tmp(C.CString(key), C.CELSIUS)),
|
||||
})
|
||||
}
|
||||
return temperatures, nil
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
// +build darwin
|
||||
// +build !cgo
|
||||
|
||||
package host
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func SensorsTemperatures() ([]TemperatureStat, error) {
|
||||
return SensorsTemperaturesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
||||
return []TemperatureStat{}, common.ErrNotImplementedError
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_linux.go
|
||||
|
||||
package host
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x4
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x4
|
||||
sizeofLongLong = 0x8
|
||||
sizeOfUtmp = 0x180
|
||||
)
|
||||
|
||||
type (
|
||||
_C_short int16
|
||||
_C_int int32
|
||||
_C_long int32
|
||||
_C_long_long int64
|
||||
)
|
||||
|
||||
type utmp struct {
|
||||
Type int16
|
||||
Pad_cgo_0 [2]byte
|
||||
Pid int32
|
||||
Line [32]int8
|
||||
Id [4]int8
|
||||
User [32]int8
|
||||
Host [256]int8
|
||||
Exit exit_status
|
||||
Session int32
|
||||
Tv timeval
|
||||
Addr_v6 [4]int32
|
||||
X__unused [20]int8
|
||||
}
|
||||
type exit_status struct {
|
||||
Termination int16
|
||||
Exit int16
|
||||
}
|
||||
type timeval struct {
|
||||
Sec int32
|
||||
Usec int32
|
||||
}
|
|
@ -1,700 +0,0 @@
|
|||
/*
|
||||
* Apple System Management Controller (SMC) API from user space for Intel based
|
||||
* Macs. Works by talking to the AppleSMC.kext (kernel extension), the driver
|
||||
* for the SMC.
|
||||
*
|
||||
* smc.c
|
||||
* libsmc
|
||||
*
|
||||
* Copyright (C) 2014 beltex <https://github.com/beltex>
|
||||
*
|
||||
* Based off of fork from:
|
||||
* osx-cpu-temp <https://github.com/lavoiesl/osx-cpu-temp>
|
||||
*
|
||||
* With credits to:
|
||||
*
|
||||
* Copyright (C) 2006 devnull
|
||||
* Apple System Management Control (SMC) Tool
|
||||
*
|
||||
* Copyright (C) 2006 Hendrik Holtmann
|
||||
* smcFanControl <https://github.com/hholtmann/smcFanControl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "smc.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: MACROS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
Name of the SMC IOService as seen in the IORegistry. You can view it either via
|
||||
command line with ioreg or through the IORegistryExplorer app (found on Apple's
|
||||
developer site - Hardware IO Tools for Xcode)
|
||||
*/
|
||||
#define IOSERVICE_SMC "AppleSMC"
|
||||
|
||||
|
||||
/**
|
||||
IOService for getting machine model name
|
||||
*/
|
||||
#define IOSERVICE_MODEL "IOPlatformExpertDevice"
|
||||
|
||||
|
||||
/**
|
||||
SMC data types - 4 byte multi-character constants
|
||||
|
||||
Sources: See TMP SMC keys in smc.h
|
||||
|
||||
http://stackoverflow.com/questions/22160746/fpe2-and-sp78-data-types
|
||||
*/
|
||||
#define DATA_TYPE_UINT8 "ui8 "
|
||||
#define DATA_TYPE_UINT16 "ui16"
|
||||
#define DATA_TYPE_UINT32 "ui32"
|
||||
#define DATA_TYPE_FLAG "flag"
|
||||
#define DATA_TYPE_FPE2 "fpe2"
|
||||
#define DATA_TYPE_SFDS "{fds"
|
||||
#define DATA_TYPE_SP78 "sp78"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: GLOBAL VARS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
Our connection to the SMC
|
||||
*/
|
||||
static io_connect_t conn;
|
||||
|
||||
|
||||
/**
|
||||
Number of characters in an SMC key
|
||||
*/
|
||||
static const int SMC_KEY_SIZE = 4;
|
||||
|
||||
|
||||
/**
|
||||
Number of characters in a data type "key" returned from the SMC. See data type
|
||||
macros.
|
||||
*/
|
||||
static const int DATA_TYPE_SIZE = 4;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: ENUMS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
Defined by AppleSMC.kext. See SMCParamStruct.
|
||||
|
||||
These are SMC specific return codes
|
||||
*/
|
||||
typedef enum {
|
||||
kSMCSuccess = 0,
|
||||
kSMCError = 1,
|
||||
kSMCKeyNotFound = 0x84
|
||||
} kSMC_t;
|
||||
|
||||
|
||||
/**
|
||||
Defined by AppleSMC.kext. See SMCParamStruct.
|
||||
|
||||
Function selectors. Used to tell the SMC which function inside it to call.
|
||||
*/
|
||||
typedef enum {
|
||||
kSMCUserClientOpen = 0,
|
||||
kSMCUserClientClose = 1,
|
||||
kSMCHandleYPCEvent = 2,
|
||||
kSMCReadKey = 5,
|
||||
kSMCWriteKey = 6,
|
||||
kSMCGetKeyCount = 7,
|
||||
kSMCGetKeyFromIndex = 8,
|
||||
kSMCGetKeyInfo = 9
|
||||
} selector_t;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: STRUCTS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
Defined by AppleSMC.kext. See SMCParamStruct.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char major;
|
||||
unsigned char minor;
|
||||
unsigned char build;
|
||||
unsigned char reserved;
|
||||
unsigned short release;
|
||||
} SMCVersion;
|
||||
|
||||
|
||||
/**
|
||||
Defined by AppleSMC.kext. See SMCParamStruct.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t version;
|
||||
uint16_t length;
|
||||
uint32_t cpuPLimit;
|
||||
uint32_t gpuPLimit;
|
||||
uint32_t memPLimit;
|
||||
} SMCPLimitData;
|
||||
|
||||
|
||||
/**
|
||||
Defined by AppleSMC.kext. See SMCParamStruct.
|
||||
|
||||
- dataSize : How many values written to SMCParamStruct.bytes
|
||||
- dataType : Type of data written to SMCParamStruct.bytes. This lets us know how
|
||||
to interpret it (translate it to human readable)
|
||||
*/
|
||||
typedef struct {
|
||||
IOByteCount dataSize;
|
||||
uint32_t dataType;
|
||||
uint8_t dataAttributes;
|
||||
} SMCKeyInfoData;
|
||||
|
||||
|
||||
/**
|
||||
Defined by AppleSMC.kext.
|
||||
|
||||
This is the predefined struct that must be passed to communicate with the
|
||||
AppleSMC driver. While the driver is closed source, the definition of this
|
||||
struct happened to appear in the Apple PowerManagement project at around
|
||||
version 211, and soon after disappeared. It can be seen in the PrivateLib.c
|
||||
file under pmconfigd.
|
||||
|
||||
https://www.opensource.apple.com/source/PowerManagement/PowerManagement-211/
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t key;
|
||||
SMCVersion vers;
|
||||
SMCPLimitData pLimitData;
|
||||
SMCKeyInfoData keyInfo;
|
||||
uint8_t result;
|
||||
uint8_t status;
|
||||
uint8_t data8;
|
||||
uint32_t data32;
|
||||
uint8_t bytes[32];
|
||||
} SMCParamStruct;
|
||||
|
||||
|
||||
/**
|
||||
Used for returning data from the SMC.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t data[32];
|
||||
uint32_t dataType;
|
||||
uint32_t dataSize;
|
||||
kSMC_t kSMC;
|
||||
} smc_return_t;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: HELPERS - TYPE CONVERSION
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
Convert data from SMC of fpe2 type to human readable.
|
||||
|
||||
:param: data Data from the SMC to be converted. Assumed data size of 2.
|
||||
:returns: Converted data
|
||||
*/
|
||||
static unsigned int from_fpe2(uint8_t data[32])
|
||||
{
|
||||
unsigned int ans = 0;
|
||||
|
||||
// Data type for fan calls - fpe2
|
||||
// This is assumend to mean floating point, with 2 exponent bits
|
||||
// http://stackoverflow.com/questions/22160746/fpe2-and-sp78-data-types
|
||||
ans += data[0] << 6;
|
||||
ans += data[1] << 2;
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Convert to fpe2 data type to be passed to SMC.
|
||||
|
||||
:param: val Value to convert
|
||||
:param: data Pointer to data array to place result
|
||||
*/
|
||||
static void to_fpe2(unsigned int val, uint8_t *data)
|
||||
{
|
||||
data[0] = val >> 6;
|
||||
data[1] = (val << 2) ^ (data[0] << 8);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Convert SMC key to uint32_t. This must be done to pass it to the SMC.
|
||||
|
||||
:param: key The SMC key to convert
|
||||
:returns: uint32_t translation.
|
||||
Returns zero if key is not 4 characters in length.
|
||||
*/
|
||||
static uint32_t to_uint32_t(char *key)
|
||||
{
|
||||
uint32_t ans = 0;
|
||||
uint32_t shift = 24;
|
||||
|
||||
// SMC key is expected to be 4 bytes - thus 4 chars
|
||||
if (strlen(key) != SMC_KEY_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SMC_KEY_SIZE; i++) {
|
||||
ans += key[i] << shift;
|
||||
shift -= 8;
|
||||
}
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
For converting the dataType return from the SMC to human readable 4 byte
|
||||
multi-character constant.
|
||||
*/
|
||||
static void to_string(uint32_t val, char *dataType)
|
||||
{
|
||||
int shift = 24;
|
||||
|
||||
for (int i = 0; i < DATA_TYPE_SIZE; i++) {
|
||||
// To get each char, we shift it into the lower 8 bits, and then & by
|
||||
// 255 to insolate it
|
||||
dataType[i] = (val >> shift) & 0xff;
|
||||
shift -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: HELPERS - TMP CONVERSION
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
Celsius to Fahrenheit
|
||||
*/
|
||||
static double to_fahrenheit(double tmp)
|
||||
{
|
||||
// http://en.wikipedia.org/wiki/Fahrenheit#Definition_and_conversions
|
||||
return (tmp * 1.8) + 32;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Celsius to Kelvin
|
||||
*/
|
||||
static double to_kelvin(double tmp)
|
||||
{
|
||||
// http://en.wikipedia.org/wiki/Kelvin
|
||||
return tmp + 273.15;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: "PRIVATE" FUNCTIONS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
Make a call to the SMC
|
||||
|
||||
:param: inputStruct Struct that holds data telling the SMC what you want
|
||||
:param: outputStruct Struct holding the SMC's response
|
||||
:returns: I/O Kit return code
|
||||
*/
|
||||
static kern_return_t call_smc(SMCParamStruct *inputStruct,
|
||||
SMCParamStruct *outputStruct)
|
||||
{
|
||||
kern_return_t result;
|
||||
size_t inputStructCnt = sizeof(SMCParamStruct);
|
||||
size_t outputStructCnt = sizeof(SMCParamStruct);
|
||||
|
||||
result = IOConnectCallStructMethod(conn, kSMCHandleYPCEvent,
|
||||
inputStruct,
|
||||
inputStructCnt,
|
||||
outputStruct,
|
||||
&outputStructCnt);
|
||||
|
||||
if (result != kIOReturnSuccess) {
|
||||
// IOReturn error code lookup. See "Accessing Hardware From Applications
|
||||
// -> Handling Errors" Apple doc
|
||||
result = err_get_code(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Read data from the SMC
|
||||
|
||||
:param: key The SMC key
|
||||
*/
|
||||
static kern_return_t read_smc(char *key, smc_return_t *result_smc)
|
||||
{
|
||||
kern_return_t result;
|
||||
SMCParamStruct inputStruct;
|
||||
SMCParamStruct outputStruct;
|
||||
|
||||
memset(&inputStruct, 0, sizeof(SMCParamStruct));
|
||||
memset(&outputStruct, 0, sizeof(SMCParamStruct));
|
||||
memset(result_smc, 0, sizeof(smc_return_t));
|
||||
|
||||
// First call to AppleSMC - get key info
|
||||
inputStruct.key = to_uint32_t(key);
|
||||
inputStruct.data8 = kSMCGetKeyInfo;
|
||||
|
||||
result = call_smc(&inputStruct, &outputStruct);
|
||||
result_smc->kSMC = outputStruct.result;
|
||||
|
||||
if (result != kIOReturnSuccess || outputStruct.result != kSMCSuccess) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Store data for return
|
||||
result_smc->dataSize = outputStruct.keyInfo.dataSize;
|
||||
result_smc->dataType = outputStruct.keyInfo.dataType;
|
||||
|
||||
|
||||
// Second call to AppleSMC - now we can get the data
|
||||
inputStruct.keyInfo.dataSize = outputStruct.keyInfo.dataSize;
|
||||
inputStruct.data8 = kSMCReadKey;
|
||||
|
||||
result = call_smc(&inputStruct, &outputStruct);
|
||||
result_smc->kSMC = outputStruct.result;
|
||||
|
||||
if (result != kIOReturnSuccess || outputStruct.result != kSMCSuccess) {
|
||||
return result;
|
||||
}
|
||||
|
||||
memcpy(result_smc->data, outputStruct.bytes, sizeof(outputStruct.bytes));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Write data to the SMC.
|
||||
|
||||
:returns: IOReturn IOKit return code
|
||||
*/
|
||||
static kern_return_t write_smc(char *key, smc_return_t *result_smc)
|
||||
{
|
||||
kern_return_t result;
|
||||
SMCParamStruct inputStruct;
|
||||
SMCParamStruct outputStruct;
|
||||
|
||||
memset(&inputStruct, 0, sizeof(SMCParamStruct));
|
||||
memset(&outputStruct, 0, sizeof(SMCParamStruct));
|
||||
|
||||
// First call to AppleSMC - get key info
|
||||
inputStruct.key = to_uint32_t(key);
|
||||
inputStruct.data8 = kSMCGetKeyInfo;
|
||||
|
||||
result = call_smc(&inputStruct, &outputStruct);
|
||||
result_smc->kSMC = outputStruct.result;
|
||||
|
||||
if (result != kIOReturnSuccess || outputStruct.result != kSMCSuccess) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check data is correct
|
||||
if (result_smc->dataSize != outputStruct.keyInfo.dataSize ||
|
||||
result_smc->dataType != outputStruct.keyInfo.dataType) {
|
||||
return kIOReturnBadArgument;
|
||||
}
|
||||
|
||||
// Second call to AppleSMC - now we can write the data
|
||||
inputStruct.data8 = kSMCWriteKey;
|
||||
inputStruct.keyInfo.dataSize = outputStruct.keyInfo.dataSize;
|
||||
|
||||
// Set data to write
|
||||
memcpy(inputStruct.bytes, result_smc->data, sizeof(result_smc->data));
|
||||
|
||||
result = call_smc(&inputStruct, &outputStruct);
|
||||
result_smc->kSMC = outputStruct.result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the model name of the machine.
|
||||
*/
|
||||
static kern_return_t get_machine_model(io_name_t model)
|
||||
{
|
||||
io_service_t service;
|
||||
kern_return_t result;
|
||||
|
||||
service = IOServiceGetMatchingService(kIOMasterPortDefault,
|
||||
IOServiceMatching(IOSERVICE_MODEL));
|
||||
|
||||
if (service == 0) {
|
||||
printf("ERROR: %s NOT FOUND\n", IOSERVICE_MODEL);
|
||||
return kIOReturnError;
|
||||
}
|
||||
|
||||
// Get the model name
|
||||
result = IORegistryEntryGetName(service, model);
|
||||
IOObjectRelease(service);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: "PUBLIC" FUNCTIONS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
kern_return_t open_smc(void)
|
||||
{
|
||||
kern_return_t result;
|
||||
io_service_t service;
|
||||
|
||||
service = IOServiceGetMatchingService(kIOMasterPortDefault,
|
||||
IOServiceMatching(IOSERVICE_SMC));
|
||||
|
||||
if (service == 0) {
|
||||
// NOTE: IOServiceMatching documents 0 on failure
|
||||
printf("ERROR: %s NOT FOUND\n", IOSERVICE_SMC);
|
||||
return kIOReturnError;
|
||||
}
|
||||
|
||||
result = IOServiceOpen(service, mach_task_self(), 0, &conn);
|
||||
IOObjectRelease(service);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
kern_return_t close_smc(void)
|
||||
{
|
||||
return IOServiceClose(conn);
|
||||
}
|
||||
|
||||
|
||||
bool is_key_valid(char *key)
|
||||
{
|
||||
bool ans = false;
|
||||
kern_return_t result;
|
||||
smc_return_t result_smc;
|
||||
|
||||
if (strlen(key) != SMC_KEY_SIZE) {
|
||||
printf("ERROR: Invalid key size - must be 4 chars\n");
|
||||
return ans;
|
||||
}
|
||||
|
||||
// Try a read and see if it succeeds
|
||||
result = read_smc(key, &result_smc);
|
||||
|
||||
if (result == kIOReturnSuccess && result_smc.kSMC == kSMCSuccess) {
|
||||
ans = true;
|
||||
}
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
double get_tmp(char *key, tmp_unit_t unit)
|
||||
{
|
||||
kern_return_t result;
|
||||
smc_return_t result_smc;
|
||||
|
||||
result = read_smc(key, &result_smc);
|
||||
|
||||
if (!(result == kIOReturnSuccess &&
|
||||
result_smc.dataSize == 2 &&
|
||||
result_smc.dataType == to_uint32_t(DATA_TYPE_SP78))) {
|
||||
// Error
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// TODO: Create from_sp78() convert function
|
||||
double tmp = result_smc.data[0];
|
||||
|
||||
switch (unit) {
|
||||
case CELSIUS:
|
||||
break;
|
||||
case FAHRENHEIT:
|
||||
tmp = to_fahrenheit(tmp);
|
||||
break;
|
||||
case KELVIN:
|
||||
tmp = to_kelvin(tmp);
|
||||
break;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
bool is_battery_powered(void)
|
||||
{
|
||||
kern_return_t result;
|
||||
smc_return_t result_smc;
|
||||
|
||||
result = read_smc(BATT_PWR, &result_smc);
|
||||
|
||||
if (!(result == kIOReturnSuccess &&
|
||||
result_smc.dataSize == 1 &&
|
||||
result_smc.dataType == to_uint32_t(DATA_TYPE_FLAG))) {
|
||||
// Error
|
||||
return false;
|
||||
}
|
||||
|
||||
return result_smc.data[0];
|
||||
}
|
||||
|
||||
|
||||
bool is_optical_disk_drive_full(void)
|
||||
{
|
||||
kern_return_t result;
|
||||
smc_return_t result_smc;
|
||||
|
||||
result = read_smc(ODD_FULL, &result_smc);
|
||||
|
||||
if (!(result == kIOReturnSuccess &&
|
||||
result_smc.dataSize == 1 &&
|
||||
result_smc.dataType == to_uint32_t(DATA_TYPE_FLAG))) {
|
||||
// Error
|
||||
return false;
|
||||
}
|
||||
|
||||
return result_smc.data[0];
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: FAN FUNCTIONS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
bool get_fan_name(unsigned int fan_num, fan_name_t name)
|
||||
{
|
||||
char key[5];
|
||||
kern_return_t result;
|
||||
smc_return_t result_smc;
|
||||
|
||||
sprintf(key, "F%dID", fan_num);
|
||||
result = read_smc(key, &result_smc);
|
||||
|
||||
if (!(result == kIOReturnSuccess &&
|
||||
result_smc.dataSize == 16 &&
|
||||
result_smc.dataType == to_uint32_t(DATA_TYPE_SFDS))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
We know the data size is 16 bytes and the type is "{fds", a custom
|
||||
struct defined by the AppleSMC.kext. See TMP enum sources for the
|
||||
struct.
|
||||
|
||||
The last 12 bytes contain the name of the fan, an array of chars, hence
|
||||
the loop range.
|
||||
*/
|
||||
int index = 0;
|
||||
for (int i = 4; i < 16; i++) {
|
||||
// Check if at the end (name may not be full 12 bytes)
|
||||
// Could check for 0 (null), but instead we check for 32 (space). This
|
||||
// is a hack to remove whitespace. :)
|
||||
if (result_smc.data[i] == 32) {
|
||||
break;
|
||||
}
|
||||
|
||||
name[index] = result_smc.data[i];
|
||||
index++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int get_num_fans(void)
|
||||
{
|
||||
kern_return_t result;
|
||||
smc_return_t result_smc;
|
||||
|
||||
result = read_smc(NUM_FANS, &result_smc);
|
||||
|
||||
if (!(result == kIOReturnSuccess &&
|
||||
result_smc.dataSize == 1 &&
|
||||
result_smc.dataType == to_uint32_t(DATA_TYPE_UINT8))) {
|
||||
// Error
|
||||
return -1;
|
||||
}
|
||||
|
||||
return result_smc.data[0];
|
||||
}
|
||||
|
||||
|
||||
unsigned int get_fan_rpm(unsigned int fan_num)
|
||||
{
|
||||
char key[5];
|
||||
kern_return_t result;
|
||||
smc_return_t result_smc;
|
||||
|
||||
sprintf(key, "F%dAc", fan_num);
|
||||
result = read_smc(key, &result_smc);
|
||||
|
||||
if (!(result == kIOReturnSuccess &&
|
||||
result_smc.dataSize == 2 &&
|
||||
result_smc.dataType == to_uint32_t(DATA_TYPE_FPE2))) {
|
||||
// Error
|
||||
return 0;
|
||||
}
|
||||
|
||||
return from_fpe2(result_smc.data);
|
||||
}
|
||||
|
||||
|
||||
bool set_fan_min_rpm(unsigned int fan_num, unsigned int rpm, bool auth)
|
||||
{
|
||||
// TODO: Add rpm val safety check
|
||||
char key[5];
|
||||
bool ans = false;
|
||||
kern_return_t result;
|
||||
smc_return_t result_smc;
|
||||
|
||||
memset(&result_smc, 0, sizeof(smc_return_t));
|
||||
|
||||
// TODO: Don't use magic number
|
||||
result_smc.dataSize = 2;
|
||||
result_smc.dataType = to_uint32_t(DATA_TYPE_FPE2);
|
||||
to_fpe2(rpm, result_smc.data);
|
||||
|
||||
sprintf(key, "F%dMn", fan_num);
|
||||
result = write_smc(key, &result_smc);
|
||||
|
||||
if (result == kIOReturnSuccess && result_smc.kSMC == kSMCSuccess) {
|
||||
ans = true;
|
||||
}
|
||||
|
||||
return ans;
|
||||
}
|
|
@ -1,254 +0,0 @@
|
|||
/*
|
||||
* Apple System Management Controller (SMC) API from user space for Intel based
|
||||
* Macs. Works by talking to the AppleSMC.kext (kernel extension), the driver
|
||||
* for the SMC.
|
||||
*
|
||||
* smc.h
|
||||
* libsmc
|
||||
*
|
||||
* Copyright (C) 2014 beltex <https://github.com/beltex>
|
||||
*
|
||||
* Based off of fork from:
|
||||
* osx-cpu-temp <https://github.com/lavoiesl/osx-cpu-temp>
|
||||
*
|
||||
* With credits to:
|
||||
*
|
||||
* Copyright (C) 2006 devnull
|
||||
* Apple System Management Control (SMC) Tool
|
||||
*
|
||||
* Copyright (C) 2006 Hendrik Holtmann
|
||||
* smcFanControl <https://github.com/hholtmann/smcFanControl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: MACROS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
SMC keys for temperature sensors - 4 byte multi-character constants
|
||||
|
||||
Not applicable to all Mac's of course. In adition, the definition of the codes
|
||||
may not be 100% accurate necessarily. Finally, list is incomplete.
|
||||
|
||||
Presumed letter translations:
|
||||
|
||||
- T = Temperature (if first char)
|
||||
- C = CPU
|
||||
- G = GPU
|
||||
- P = Proximity
|
||||
- D = Diode
|
||||
- H = Heatsink
|
||||
|
||||
Sources:
|
||||
|
||||
- https://www.apple.com/downloads/dashboard/status/istatpro.html
|
||||
- https://github.com/hholtmann/smcFanControl
|
||||
- https://github.com/jedda/OSX-Monitoring-Tools
|
||||
- http://www.parhelia.ch/blog/statics/k3_keys.html
|
||||
*/
|
||||
#define AMBIENT_AIR_0 "TA0P"
|
||||
#define AMBIENT_AIR_1 "TA1P"
|
||||
#define CPU_0_DIODE "TC0D"
|
||||
#define CPU_0_HEATSINK "TC0H"
|
||||
#define CPU_0_PROXIMITY "TC0P"
|
||||
#define ENCLOSURE_BASE_0 "TB0T"
|
||||
#define ENCLOSURE_BASE_1 "TB1T"
|
||||
#define ENCLOSURE_BASE_2 "TB2T"
|
||||
#define ENCLOSURE_BASE_3 "TB3T"
|
||||
#define GPU_0_DIODE "TG0D"
|
||||
#define GPU_0_HEATSINK "TG0H"
|
||||
#define GPU_0_PROXIMITY "TG0P"
|
||||
#define HARD_DRIVE_BAY "TH0P"
|
||||
#define MEMORY_SLOT_0 "TM0S"
|
||||
#define MEMORY_SLOTS_PROXIMITY "TM0P"
|
||||
#define NORTHBRIDGE "TN0H"
|
||||
#define NORTHBRIDGE_DIODE "TN0D"
|
||||
#define NORTHBRIDGE_PROXIMITY "TN0P"
|
||||
#define THUNDERBOLT_0 "TI0P"
|
||||
#define THUNDERBOLT_1 "TI1P"
|
||||
#define WIRELESS_MODULE "TW0P"
|
||||
|
||||
|
||||
/**
|
||||
SMC keys for fans - 4 byte multi-character constants
|
||||
|
||||
Number of fans on Macs vary of course, thus not all keys will be applicable.
|
||||
|
||||
Presumed letter translations:
|
||||
|
||||
- F = Fan
|
||||
- Ac = Acutal
|
||||
- Mn = Min
|
||||
- Mx = Max
|
||||
- Sf = Safe
|
||||
- Tg = Target
|
||||
|
||||
Sources: See TMP SMC keys
|
||||
*/
|
||||
#define FAN_0 "F0Ac"
|
||||
#define FAN_0_MIN_RPM "F0Mn"
|
||||
#define FAN_0_MAX_RPM "F0Mx"
|
||||
#define FAN_0_SAFE_RPM "F0Sf"
|
||||
#define FAN_0_TARGET_RPM "F0Tg"
|
||||
#define FAN_1 "F1Ac"
|
||||
#define FAN_1_MIN_RPM "F1Mn"
|
||||
#define FAN_1_MAX_RPM "F1Mx"
|
||||
#define FAN_1_SAFE_RPM "F1Sf"
|
||||
#define FAN_1_TARGET_RPM "F1Tg"
|
||||
#define FAN_2 "F2Ac"
|
||||
#define FAN_2_MIN_RPM "F2Mn"
|
||||
#define FAN_2_MAX_RPM "F2Mx"
|
||||
#define FAN_2_SAFE_RPM "F2Sf"
|
||||
#define FAN_2_TARGET_RPM "F2Tg"
|
||||
#define NUM_FANS "FNum"
|
||||
#define FORCE_BITS "FS! "
|
||||
|
||||
|
||||
/**
|
||||
Misc SMC keys - 4 byte multi-character constants
|
||||
|
||||
Sources: See TMP SMC keys
|
||||
*/
|
||||
#define BATT_PWR "BATP"
|
||||
#define NUM_KEYS "#KEY"
|
||||
#define ODD_FULL "MSDI"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: TYPES
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
typedef char fan_name_t[13];
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: ENUMS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
typedef enum {
|
||||
CELSIUS,
|
||||
FAHRENHEIT,
|
||||
KELVIN
|
||||
} tmp_unit_t;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: PROTOTYPES
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
Open a connection to the SMC
|
||||
|
||||
:returns: kIOReturnSuccess on successful connection to the SMC.
|
||||
*/
|
||||
kern_return_t open_smc(void);
|
||||
|
||||
|
||||
/**
|
||||
Close connection to the SMC
|
||||
|
||||
:returns: kIOReturnSuccess on successful close of connection to the SMC.
|
||||
*/
|
||||
kern_return_t close_smc(void);
|
||||
|
||||
|
||||
/**
|
||||
Check if an SMC key is valid. Useful for determining if a certain machine has
|
||||
particular sensor or fan for example.
|
||||
|
||||
:param: key The SMC key to check. 4 byte multi-character constant. Must be 4
|
||||
characters in length.
|
||||
:returns: True if the key is found, false otherwise
|
||||
*/
|
||||
bool is_key_valid(char *key);
|
||||
|
||||
|
||||
/**
|
||||
Get the current temperature from a sensor
|
||||
|
||||
:param: key The temperature sensor to read from
|
||||
:param: unit The unit for the temperature value.
|
||||
:returns: Temperature of sensor. If the sensor is not found, or an error
|
||||
occurs, return will be zero
|
||||
*/
|
||||
double get_tmp(char *key, tmp_unit_t unit);
|
||||
|
||||
|
||||
/**
|
||||
Is the machine being powered by the battery?
|
||||
|
||||
:returns: True if it is, false otherwise
|
||||
*/
|
||||
bool is_battery_powered(void);
|
||||
|
||||
|
||||
/**
|
||||
Is there a CD in the optical disk drive (ODD)?
|
||||
|
||||
:returns: True if there is, false otherwise
|
||||
*/
|
||||
bool is_optical_disk_drive_full(void);
|
||||
|
||||
|
||||
/**
|
||||
Get the name of a fan.
|
||||
|
||||
:param: fanNum The number of the fan to check
|
||||
:param: name The name of the fan. Return will be empty on error.
|
||||
:returns: True if successful, false otherwise.
|
||||
*/
|
||||
bool get_fan_name(unsigned int fan_num, fan_name_t name);
|
||||
|
||||
|
||||
/**
|
||||
Get the number of fans on this machine.
|
||||
|
||||
:returns: The number of fans. If an error occurs, return will be -1.
|
||||
*/
|
||||
int get_num_fans(void);
|
||||
|
||||
|
||||
/**
|
||||
Get the current speed (RPM - revolutions per minute) of a fan.
|
||||
|
||||
:param: fan_num The number of the fan to check
|
||||
:returns: The fan RPM. If the fan is not found, or an error occurs, return
|
||||
will be zero
|
||||
*/
|
||||
UInt get_fan_rpm(UInt fan_num);
|
||||
|
||||
|
||||
/**
|
||||
Set the minimum speed (RPM - revolutions per minute) of a fan. This method
|
||||
requires root privileges. By minimum we mean that OS X can interject and
|
||||
raise the fan speed if needed, however it will not go below this.
|
||||
|
||||
WARNING: You are playing with hardware here, BE CAREFUL.
|
||||
|
||||
:param: fan_num The number of the fan to set
|
||||
:param: rpm The speed you would like to set the fan to.
|
||||
:param: auth Should the function do authentication?
|
||||
:return: True if successful, false otherwise
|
||||
*/
|
||||
bool set_fan_min_rpm(unsigned int fan_num, unsigned int rpm, bool auth);
|
|
@ -39,7 +39,7 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffers, err := unix.SysctlUint32("vfs.bufspace")
|
||||
buffers, err := unix.SysctlUint64("vfs.bufspace")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue