c++ - 创建 ChargeInhibit 断言 (OS X 10.6.8)

标签 c++ macos battery iokit power-management

平台 (OS X 10.6.8) - [Macbook Pro - 这很重要,因为我想处理电池处理 - 不适用于台式机]

如果我犯了一个我没有看到的基本错误,请原谅我,因为我已经五年或更长时间没有写过任何 C/C++,而且我没有完全遵循 Apple API 希望您编写的方式与他们打交道,所以这就是我的问题。基本上,我希望能够根据我的命令禁止从 AC 适配器充电,这样我就可以选择是否在使用和插入笔记本电脑时为笔记本电脑充电。我一直找不到任何实用程序这个,所以我一开始把它写成硬件级别的东西,不能从软件上改变,但后来我遇到了一些令人鼓舞的事情:

如果你打开终端窗口并运行

pmset -g assertionslog

您会得到一个断言列表,每个断言都有一个 0 或 1,表示某个进程是否已断言该断言。其中第一个名为 ChargeInhibit,经过一番挖掘后我发现这在软件级别完全符合我的要求。我只需要弄清楚如何断言它。

我从 Apple 源代码存档中名为 SetActive.c (link) 的文件中复制了一些代码我将函数 sendSmartBatteryCommand 复制到我的 XCode 项目中,并花时间链接其他 header 并复制定义,直到我可以正确编译它。这是复制的函数:

// 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;
}

在我的头文件(也从 SetActive.c 复制)的枚举中定义了“which”参数的选项:

enum {
    kSBUCInflowDisable = 0,
    kSBUCChargeInhibit = 1
};

最佳答案

我首先尝试了同样的事情但没有成功,然后我找到了“pmset noidle”。 ( pmset.c ) 这提出了一个断言,但不是正确的断言。查看函数 prevent_idle_sleep。

改变这个:

IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep,
                    kIOPMAssertionLevelOn,
                    CFSTR("pmset prevent sleep"),
                    &neverSleep))

到:

IOPMAssertionCreateWithName(kIOPMAssertionTypeInhibitCharging,
                    kIOPMAssertionLevelOn,
                    CFSTR("prevent charging..."),
                    &neverSleep))

并添加这些定义:

// Disables battery charging (requires root to initiate)
#define kIOPMAssertionTypeInhibitCharging       CFSTR("ChargeInhibit")
#define kIOPMChargeInhibitAssertion             kIOPMAssertionTypeInhibitCharging

关于c++ - 创建 ChargeInhibit 断言 (OS X 10.6.8),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7670158/

相关文章:

c++ - Web Assemblies WASM 新手

c++ - 使用alignas 进行参数包扩展的语法是什么?

python - 为什么pip安装tbb失败

Android - 故意快速耗尽电池

c++ - 将名称转换为数字,然后生成输出

c++ - 使用列表语法中的删除更正迭代

python - osx下打开的子进程

c# - 我应该使用什么 gulp 插件在 Mac 上构建 ASP.NET 5?

macos - cocoa : Displaying battery percentage in the menu bar

android - 电池圈像 Battery Widget Reborn