feat: allow to write a value on a key by SMC app

This commit is contained in:
Serhiy Mytrovtsiy
2021-05-29 17:00:09 +02:00
parent ed362c3b5b
commit a040bf7326
4 changed files with 127 additions and 81 deletions

View File

@@ -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")
}

View File

@@ -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
)
}
}

View File

@@ -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
}

View File

@@ -56,7 +56,7 @@
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "-t"
argument = "set -k &quot;FS! &quot; -v 0000"
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>