* Платформа
(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
};