2011-10-06 114 views
1

平台(OS X 10.6.8) - [MacBook Pro的 - 并不适用于台式机 - 因为我要处理的电池处理,这是很重要]创建ChargeInhibit断言(OS X 10.6.8)

如果我犯了一个我看不到的基本错误,请原谅我,因为我在五年或更长时间内没有编写任何C/C++,并且我没有完全遵循苹果API希望您处理的方式他们,所以这是我的问题。基本上,我希望能够通过我的命令禁止从AC适配器进行充电,以便在使用和插入时可以选择是否对笔记本电脑充电。我无法找到任何可以使用的公用设施这一点,所以我在第一次写它作为东西是在硬件层面,不能从软件改变了,但后来我碰到一些令人鼓舞的跑:

如果你打开一个终端窗口,执行

pmset -g assertionslog 

您会得到一个断言列表,并为每个断言指定一个0或1,指示某个进程是否声明了该断言。其中第一个名为ChargeInhibit,我经过一番挖掘后发现,这正是我想要的,在软件层面。我只需要弄清楚如何声明它。

我从苹果源文件夹中的一个文件复制了一些代码,名为SetActive.c (link)我将函数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; 
} 

哪里的“这”参数选项枚举的定义在我的头文件(也SETACTIVE复制.c):

enum { 
    kSBUCInflowDisable = 0, 
    kSBUCChargeInhibit = 1 
}; 
+0

你是否能找到一个解决,并使其发挥作用?我一直试图做同样的目标,但甚至没有达到你的目标。 –

回答

0

我第一次尝试同样的事情没有运气,然后我发现“pmset noidle”。 (​​)这引发了一个断言,但不是正确的。看看函数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