mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 00:04:15 +09:00
feat: allow to write a value on a key by SMC app
This commit is contained in:
@@ -12,33 +12,63 @@
|
||||
import Foundation
|
||||
|
||||
func main() {
|
||||
let args = CommandLine.arguments.dropFirst()
|
||||
var args = CommandLine.arguments.dropFirst()
|
||||
let cmd = CMDType(value: args.first ?? "")
|
||||
args = args.dropFirst()
|
||||
|
||||
switch cmd {
|
||||
case .list:
|
||||
var keys = SMC.shared.getAllKeys()
|
||||
args.dropFirst().forEach { (arg: String) in
|
||||
args.forEach { (arg: String) in
|
||||
let flag = FlagsType(value: arg)
|
||||
if flag != .all {
|
||||
keys = keys.filter{ $0.hasPrefix(flag.rawValue)}
|
||||
}
|
||||
}
|
||||
|
||||
print("[INFO]: found \(keys.count) keys\n")
|
||||
|
||||
keys.forEach { (key: String) in
|
||||
let value = SMC.shared.getValue(key)
|
||||
print("[\(key)] ", value ?? 0)
|
||||
}
|
||||
case .set:
|
||||
guard let keyIndex = args.firstIndex(where: { $0 == "-k" }),
|
||||
let valueIndex = args.firstIndex(where: { $0 == "-v" }),
|
||||
args.indices.contains(keyIndex+1),
|
||||
args.indices.contains(valueIndex+1) else{
|
||||
return
|
||||
}
|
||||
|
||||
let key = args[keyIndex+1]
|
||||
if key.count != 4 {
|
||||
print("[ERROR]: key must contain 4 characters!")
|
||||
return
|
||||
}
|
||||
|
||||
guard let value = Int(args[valueIndex+1]) else {
|
||||
print("[ERROR]: wrong value passed!")
|
||||
return
|
||||
}
|
||||
|
||||
let result = SMC.shared.write(key, value)
|
||||
if result != kIOReturnSuccess {
|
||||
print("[ERROR]: " + (String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
return
|
||||
}
|
||||
|
||||
print("[INFO]: set \(value) on \(key)")
|
||||
case .help, .unknown:
|
||||
print("SMC tool\n")
|
||||
print("Usage:")
|
||||
print(" ./smc [command]\n")
|
||||
print("Available Commands:")
|
||||
print(" list list keys and values")
|
||||
print(" set set value to a key")
|
||||
print(" help help menu\n")
|
||||
print("Available Flags:")
|
||||
print(" -t list temperature sensors")
|
||||
print(" -v list voltage sensors")
|
||||
print(" -v list voltage sensors (list cmd) / value (set cmd)")
|
||||
print(" -p list power sensors")
|
||||
print(" -f list fans\n")
|
||||
}
|
||||
|
||||
166
SMC/smc.swift
166
SMC/smc.swift
@@ -163,71 +163,6 @@ public class SMC {
|
||||
return nil
|
||||
}
|
||||
|
||||
private func read(_ value: UnsafeMutablePointer<SMCVal_t>) -> kern_return_t {
|
||||
var result: kern_return_t = 0
|
||||
var input = SMCKeyData_t()
|
||||
var output = SMCKeyData_t()
|
||||
|
||||
input.key = FourCharCode(fromString: value.pointee.key)
|
||||
input.data8 = SMCKeys.READ_KEYINFO.rawValue
|
||||
|
||||
result = call(SMCKeys.KERNEL_INDEX.rawValue, input: &input, output: &output)
|
||||
if result != kIOReturnSuccess {
|
||||
return result
|
||||
}
|
||||
|
||||
value.pointee.dataSize = UInt32(output.keyInfo.dataSize)
|
||||
value.pointee.dataType = output.keyInfo.dataType.toString()
|
||||
input.keyInfo.dataSize = output.keyInfo.dataSize
|
||||
input.data8 = SMCKeys.READ_BYTES.rawValue
|
||||
|
||||
result = call(SMCKeys.KERNEL_INDEX.rawValue, input: &input, output: &output)
|
||||
if result != kIOReturnSuccess {
|
||||
return result
|
||||
}
|
||||
|
||||
memcpy(&value.pointee.bytes, &output.bytes, Int(value.pointee.dataSize))
|
||||
|
||||
return kIOReturnSuccess
|
||||
}
|
||||
|
||||
private func write(_ value: SMCVal_t) -> kern_return_t {
|
||||
var input = SMCKeyData_t()
|
||||
var output = SMCKeyData_t()
|
||||
|
||||
input.key = FourCharCode(fromString: value.key)
|
||||
input.data8 = SMCKeys.WRITE_BYTES.rawValue
|
||||
input.keyInfo.dataSize = IOByteCount(value.dataSize)
|
||||
input.bytes = (value.bytes[0], value.bytes[1], value.bytes[2], value.bytes[3], value.bytes[4], value.bytes[5],
|
||||
value.bytes[6], value.bytes[7], value.bytes[8], value.bytes[9], value.bytes[10], value.bytes[11],
|
||||
value.bytes[12], value.bytes[13], value.bytes[14], value.bytes[15], value.bytes[16], value.bytes[17],
|
||||
value.bytes[18], value.bytes[19], value.bytes[20], value.bytes[21], value.bytes[22], value.bytes[23],
|
||||
value.bytes[24], value.bytes[25], value.bytes[26], value.bytes[27], value.bytes[28], value.bytes[29],
|
||||
value.bytes[30], value.bytes[31])
|
||||
|
||||
let result = self.call(SMCKeys.KERNEL_INDEX.rawValue, input: &input, output: &output)
|
||||
if result != kIOReturnSuccess {
|
||||
print("Error call(WRITE_BYTES): " + (String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
return result
|
||||
}
|
||||
|
||||
return kIOReturnSuccess
|
||||
}
|
||||
|
||||
private func call(_ index: UInt8, input: inout SMCKeyData_t, output: inout SMCKeyData_t) -> kern_return_t {
|
||||
let inputSize = MemoryLayout<SMCKeyData_t>.stride
|
||||
var outputSize = MemoryLayout<SMCKeyData_t>.stride
|
||||
|
||||
return IOConnectCallStructMethod(
|
||||
conn,
|
||||
UInt32(index),
|
||||
&input,
|
||||
inputSize,
|
||||
&output,
|
||||
&outputSize
|
||||
)
|
||||
}
|
||||
|
||||
public func getAllKeys() -> [String] {
|
||||
var list: [String] = []
|
||||
|
||||
@@ -259,6 +194,21 @@ public class SMC {
|
||||
return list
|
||||
}
|
||||
|
||||
public func write(_ key: String, _ newValue: Int) -> kern_return_t {
|
||||
var value = SMCVal_t(key)
|
||||
value.dataSize = 2
|
||||
value.bytes = [UInt8(newValue >> 6), UInt8((newValue << 2) ^ ((newValue >> 6) << 8)), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
|
||||
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
|
||||
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
|
||||
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
|
||||
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
|
||||
UInt8(0), UInt8(0)]
|
||||
|
||||
return write(value)
|
||||
}
|
||||
|
||||
// MARK: - fans
|
||||
|
||||
public func setFanMode(_ id: Int, mode: FanMode) {
|
||||
let fansMode = Int(self.getValue("FS! ") ?? 0)
|
||||
var newMode: UInt8 = 0
|
||||
@@ -308,16 +258,6 @@ public class SMC {
|
||||
}
|
||||
}
|
||||
|
||||
public func resetFans() {
|
||||
var value = SMCVal_t("FS! ")
|
||||
value.dataSize = 2
|
||||
|
||||
let result = write(value)
|
||||
if result != kIOReturnSuccess {
|
||||
print("Error write: " + (String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
}
|
||||
}
|
||||
|
||||
public func setFanSpeed(_ id: Int, speed: Int) {
|
||||
let minSpeed = Int(self.getValue("F\(id)Mn") ?? 2500)
|
||||
let maxSpeed = Int(self.getValue("F\(id)Mx") ?? 4000)
|
||||
@@ -345,4 +285,80 @@ public class SMC {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
public func resetFans() {
|
||||
var value = SMCVal_t("FS! ")
|
||||
value.dataSize = 2
|
||||
|
||||
let result = write(value)
|
||||
if result != kIOReturnSuccess {
|
||||
print("Error write: " + (String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - internal functions
|
||||
|
||||
private func read(_ value: UnsafeMutablePointer<SMCVal_t>) -> kern_return_t {
|
||||
var result: kern_return_t = 0
|
||||
var input = SMCKeyData_t()
|
||||
var output = SMCKeyData_t()
|
||||
|
||||
input.key = FourCharCode(fromString: value.pointee.key)
|
||||
input.data8 = SMCKeys.READ_KEYINFO.rawValue
|
||||
|
||||
result = call(SMCKeys.KERNEL_INDEX.rawValue, input: &input, output: &output)
|
||||
if result != kIOReturnSuccess {
|
||||
return result
|
||||
}
|
||||
|
||||
value.pointee.dataSize = UInt32(output.keyInfo.dataSize)
|
||||
value.pointee.dataType = output.keyInfo.dataType.toString()
|
||||
input.keyInfo.dataSize = output.keyInfo.dataSize
|
||||
input.data8 = SMCKeys.READ_BYTES.rawValue
|
||||
|
||||
result = call(SMCKeys.KERNEL_INDEX.rawValue, input: &input, output: &output)
|
||||
if result != kIOReturnSuccess {
|
||||
return result
|
||||
}
|
||||
|
||||
memcpy(&value.pointee.bytes, &output.bytes, Int(value.pointee.dataSize))
|
||||
|
||||
return kIOReturnSuccess
|
||||
}
|
||||
|
||||
private func write(_ value: SMCVal_t) -> kern_return_t {
|
||||
var input = SMCKeyData_t()
|
||||
var output = SMCKeyData_t()
|
||||
|
||||
input.key = FourCharCode(fromString: value.key)
|
||||
input.data8 = SMCKeys.WRITE_BYTES.rawValue
|
||||
input.keyInfo.dataSize = IOByteCount(value.dataSize)
|
||||
input.bytes = (value.bytes[0], value.bytes[1], value.bytes[2], value.bytes[3], value.bytes[4], value.bytes[5],
|
||||
value.bytes[6], value.bytes[7], value.bytes[8], value.bytes[9], value.bytes[10], value.bytes[11],
|
||||
value.bytes[12], value.bytes[13], value.bytes[14], value.bytes[15], value.bytes[16], value.bytes[17],
|
||||
value.bytes[18], value.bytes[19], value.bytes[20], value.bytes[21], value.bytes[22], value.bytes[23],
|
||||
value.bytes[24], value.bytes[25], value.bytes[26], value.bytes[27], value.bytes[28], value.bytes[29],
|
||||
value.bytes[30], value.bytes[31])
|
||||
|
||||
let result = self.call(SMCKeys.KERNEL_INDEX.rawValue, input: &input, output: &output)
|
||||
if result != kIOReturnSuccess {
|
||||
return result
|
||||
}
|
||||
|
||||
return kIOReturnSuccess
|
||||
}
|
||||
|
||||
private func call(_ index: UInt8, input: inout SMCKeyData_t, output: inout SMCKeyData_t) -> kern_return_t {
|
||||
let inputSize = MemoryLayout<SMCKeyData_t>.stride
|
||||
var outputSize = MemoryLayout<SMCKeyData_t>.stride
|
||||
|
||||
return IOConnectCallStructMethod(
|
||||
conn,
|
||||
UInt32(index),
|
||||
&input,
|
||||
inputSize,
|
||||
&output,
|
||||
&outputSize
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,16 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
// MARK: - main
|
||||
|
||||
enum CMDType: String {
|
||||
case list
|
||||
case set
|
||||
case help
|
||||
case unknown
|
||||
|
||||
init(value: String) {
|
||||
switch value {
|
||||
case "list": self = .list
|
||||
case "set": self = .set
|
||||
case "help": self = .help
|
||||
default: self = .unknown
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user