Создание утверждения ChargeInhibit (OS X 10.6.8) - PullRequest
2 голосов
/ 06 октября 2011
* Платформа

(OS X 10.6.8) - [Macbook Pro - это важно, так как я хочу иметь дело с обращением с батареей - не применимо для настольного компьютера]

Простите, если я сделал базовыйошибка, которую я не вижу, потому что я не писал ни C / C ++ в течение пяти или более лет, и я не совсем понимаю, как Apple API хочет, чтобы вы справились с ними, так что это мой вопрос.По сути, я хочу иметь возможность запретить зарядку от адаптера переменного тока по моей команде, чтобы я мог выбирать, заряжать ли свой ноутбук или нет, когда он используется и подключен. Мне не удалось найти какие-либо утилиты, которые делаютэто, поэтому я сначала списал это как что-то, что было на аппаратном уровне и не могло быть заменено программным обеспечением, но затем я столкнулся с чем-то обнадеживающим:

Если вы откроете окно терминала и запустите

pmset -g assertionslog

вы получаете список утверждений и 0 или 1 для каждого, указывающий, подтвердил ли какой-либо процесс это утверждение.Первый из них называется ChargeInhibit, и после некоторого поиска я обнаружил, что это именно то, что я хочу, на уровне программного обеспечения.Мне просто нужно выяснить, как это утверждать.

Я скопировал некоторый код из файла в исходном архиве Apple с именем 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» на бессмысленное слово, просто чтобы проверить, возвращает ли функция ошибку,и это так, что указывает на то, что я подключаюсь к реальному сервису.

Какие-нибудь советы о том, как я могу добиться этого как можно проще?

Кстати, я пыталсяперекомпилируйте AppleSmartBatteryManager в проекте PowerManagement из пакета с исходным кодом на исходном сайте Apple, но я обнаружил в 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
};

1 Ответ

0 голосов
/ 23 декабря 2012

Сначала я попробовал то же самое без удачи, потом нашел «pmset noidle». ( pmset.c ) Это выдвигает утверждение, только не правильное. Посмотрите на функцию protect_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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...