平台 (OS X 10.6.8) - [Macbook Pro - 这很重要,因为我想处理电池处理 - 不适用于台式机]
如果我犯了一个我看不到的基本错误,请原谅我,因为我已经五年或更长时间没有编写过任何 C/C++,而且我没有完全遵循苹果 API 希望你处理它们的方式,所以这就是我的问题。基本上,我希望能够在我的命令下禁止从交流适配器充电,这样我就可以选择是否在笔记本电脑正在使用和插入时为其充电。我找不到任何实用程序这个,所以我起初把它写成硬件级别的东西,不能从软件中改变,但后来我遇到了一些令人鼓舞的事情:
如果您打开终端窗口并运行
pmset -g assertionslog
你会得到一个断言列表,每个断言都是 0 或 1,表示某个进程是否断言了该断言。其中第一个名为 ChargeInhibit,经过一番挖掘后,我发现这在软件级别上完全符合我的要求。我只需要弄清楚如何断言它。
我从名为SetActive.c 的苹果源文件中的一个文件中复制了一些代码(链接) 我将函数 sendSmartBatteryCommand 复制到我的 XCode 项目中,并花时间链接其他头文件并复制定义,直到我可以正确编译它。这是复制的功能:
// The copied function,
// modified very slightly:
// to return a success/fail value instead of void
kern_return_t sendSmartBatteryCommand(uint32_t which, uint32_t level)
{
io_service_t sbmanager = MACH_PORT_NULL;
io_connect_t sbconnection = MACH_PORT_NULL;
kern_return_t kret = 99;
uint32_t output_count = 1;
uint64_t uc_return = kIOReturnError;
uint64_t level_64 = level;
// Find SmartBattery manager
sbmanager = IOServiceGetMatchingService(MACH_PORT_NULL,
IOServiceMatching("AppleSmartBatteryManager"));
if(MACH_PORT_NULL == sbmanager) {
goto bail;
}
kret = IOServiceOpen( sbmanager, mach_task_self(), 0, &sbconnection);
if(kIOReturnSuccess != kret) {
goto bail;
}
kret = IOConnectCallMethod(
sbconnection, // connection
which, // selector
&level_64, // uint64_t *input
1, // input Count
NULL, // input struct count
0, // input struct count
&uc_return, // output
&output_count, // output count
NULL, // output struct
0); // output struct count
bail:
if (MACH_PORT_NULL != sbconnection) {
IOServiceClose(sbconnection);
}
if (MACH_PORT_NULL != sbmanager) {
IOObjectRelease(sbmanager);
}
return kret;
}
当我尝试使用它发送用于充电抑制和流入禁用的断言时,我得到了成功值,但是来自 pmset 的日志没有显示任何更改,我的电池充电/未充电的实际状态也没有。
我还尝试将要查找的服务名称从“AppleSmartBatteryManager”修改为无意义的词,只是为了查看函数是否返回失败,并且确实如此,这表明我正在连接到真正的服务。
关于如何尽可能简单地实现这一目标的任何提示?
顺便说一句,我试图从苹果源站点上的源包重新编译 PowerManagement 项目中的 AppleSmartBatteryManager,但我在 XCode 中的错误比我能处理的要多。我希望尝试以某种方式与现有服务进行交互,这不会让我在我自己的项目中重新编译 AppleSmartBatteryManager 源代码。
编辑:顺便说一句,这是我调用函数的一个例子:
int CInh()
{
kern_return_t kret = sendSmartBatteryCommand( kSBUCChargeInhibit, 255); // zero:uninhibit, non-zero:inhibit
if(kret == KERN_SUCCESS)
return 1;
else
return 0;
}
“which”参数的选项在我的头文件的枚举中定义(也从 SetActive.c 复制):
enum {
kSBUCInflowDisable = 0,
kSBUCChargeInhibit = 1
};