2011-10-06 85 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