C++ 创建ChargeInhibit断言(OS X 10.6.8)

C++ 创建ChargeInhibit断言(OS X 10.6.8),c++,macos,battery,iokit,power-management,C++,Macos,Battery,Iokit,Power Management,平台(OS X 10.6.8)- [Macbook Pro-这很重要,因为我想处理电池处理-不适用于台式机] 如果我犯了一个我看不到的基本错误,请原谅我,因为我已经五年或更长时间没有编写过任何C/C++了,而且我没有完全按照苹果API希望您处理它们的方式,所以这就是我的问题所在。基本上,我希望能够在我的命令下禁止从交流适配器充电,这样我就可以在笔记本电脑使用和插入电源时选择是否充电。我找不到任何实用程序可以做到这一点,所以起初我把它写成硬件级别的东西,不能从软件更改,但后来我遇到了一些鼓舞人心的

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

如果我犯了一个我看不到的基本错误,请原谅我,因为我已经五年或更长时间没有编写过任何C/C++了,而且我没有完全按照苹果API希望您处理它们的方式,所以这就是我的问题所在。基本上,我希望能够在我的命令下禁止从交流适配器充电,这样我就可以在笔记本电脑使用和插入电源时选择是否充电。我找不到任何实用程序可以做到这一点,所以起初我把它写成硬件级别的东西,不能从软件更改,但后来我遇到了一些鼓舞人心的东西:

如果打开终端窗口并运行

pmset -g assertionslog
您将得到一个断言列表,每个断言都有一个0或1,指示某个进程是否断言了该断言。第一个标题是ChargeInhibit,经过一番挖掘,我发现它在软件级别上完全符合我的要求。我只需要弄清楚如何维护它

我从苹果源代码归档中的一个名为“我将函数sendsmartmatterycommand复制到我的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;
}
int CInh()
{
    kern_return_t kret = sendSmartBatteryCommand( kSBUCChargeInhibit, 255);  // zero:uninhibit, non-zero:inhibit

    if(kret == KERN_SUCCESS)
        return 1;
    else
        return 0;
}
当我尝试使用它发送充电抑制和流入禁用断言时,我会返回成功值,但是pmset的日志没有显示任何更改,电池充电/不充电的实际状态也没有显示任何更改

我还尝试将服务的名称从“AppleSmartBatteryManager”修改为一个无意义的词,以查看函数是否返回failure,它确实返回了failure,这表明我正在连接到一个真正的服务

关于如何尽可能简单地做到这一点,有什么建议吗

顺便说一句,我试图从apple源站点的源程序包中重新编译PowerManagement项目中的AppleSmartBatteryManager,但是我发现XCode中的错误太多了,我无法处理。我希望尝试以某种方式与现有服务交互,而不会让我在自己的项目旁边重新编译AppleSmartBatteryManager源代码

编辑: 顺便说一下,这是我调用函数的一个示例:

// 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;
}
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复制)的枚举中定义:


我先是尝试了同样的方法,但没有成功,然后我发现了“pmset noidle”。()这提出了一个断言,但不是正确的。查看“防止空闲睡眠”功能

更改此项:

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

并添加以下定义:

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

我先是尝试了同样的方法,但没有成功,然后我发现了“pmset noidle”。()这提出了一个断言,但不是正确的。查看“防止空闲睡眠”功能

更改此项:

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

并添加以下定义:

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

你能找到一个解决方案并让它工作吗?我一直试图用完全相同的目标来做同样的事情,但还没有达到你的程度。你能找到解决办法并使其发挥作用吗?我一直试图用完全相同的目标来实现同样的目标,但还没有达到你的程度。。