AppleSmartBatteryManagerUserClient.cpp [plain text]
#include <sys/systm.h>
#include <sys/proc.h>
#include <kern/task.h>
#include "AppleSmartBatteryManagerUserClient.h"
#define super IOUserClient
enum {
kCallOnOwner = 0,
kCallOnSelf = 1
};
OSDefineMetaClassAndStructors(AppleSmartBatteryManagerUserClient, IOUserClient)
bool AppleSmartBatteryManagerUserClient::initWithTask(task_t owningTask,
void *security_id, UInt32 type, OSDictionary * properties)
{
uint32_t _pid;
if (kSBExclusiveSMBusAccessType == type)
{
if ( kIOReturnSuccess !=
clientHasPrivilege(owningTask, kIOClientPrivilegeAdministrator))
{
return false;
}
}
if (!super::initWithTask(owningTask, security_id, type, properties)) {
return false;
}
fUserClientType = type;
_pid = proc_selfpid();
setProperty("pid", _pid, 32);
fOwningTask = owningTask;
task_reference (fOwningTask);
return true;
}
bool AppleSmartBatteryManagerUserClient::start( IOService * provider )
{
fOwner = (AppleSmartBatteryManager *)provider;
if (kSBExclusiveSMBusAccessType == fUserClientType)
{
if(!fOwner->requestExclusiveSMBusAccess(true)) {
return false;
}
}
if(!super::start(provider))
return false;
return true;
}
IOReturn AppleSmartBatteryManagerUserClient::secureInflowDisable(
int level,
int *return_code)
{
int admin_priv = 0;
IOReturn ret = kIOReturnNotPrivileged;
if( !(level == 0 || level == 1))
{
*return_code = kIOReturnBadArgument;
return kIOReturnSuccess;
}
ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator);
admin_priv = (kIOReturnSuccess == ret);
if(admin_priv && fOwner) {
*return_code = fOwner->disableInflow( level );
return kIOReturnSuccess;
} else {
*return_code = kIOReturnNotPrivileged;
return kIOReturnSuccess;
}
}
IOReturn AppleSmartBatteryManagerUserClient::secureChargeInhibit(
int level,
int *return_code)
{
int admin_priv = 0;
IOReturn ret = kIOReturnNotPrivileged;
if( !(level == 0 || level == 1))
{
*return_code = kIOReturnBadArgument;
return kIOReturnSuccess;
}
ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator);
admin_priv = (kIOReturnSuccess == ret);
if(admin_priv && fOwner) {
*return_code = fOwner->inhibitCharging(level);
return kIOReturnSuccess;
} else {
*return_code = kIOReturnNotPrivileged;
return kIOReturnSuccess;
}
}
IOReturn AppleSmartBatteryManagerUserClient::clientClose( void )
{
if (kSBExclusiveSMBusAccessType == fUserClientType) {
fOwner->requestExclusiveSMBusAccess(false);
}
detach(fOwner);
if(fOwningTask) {
task_deallocate(fOwningTask);
fOwningTask = 0;
}
terminate();
return kIOReturnSuccess;
}
IOReturn
AppleSmartBatteryManagerUserClient::externalMethod(
uint32_t selector,
IOExternalMethodArguments * arguments,
IOExternalMethodDispatch * dispatch __unused,
OSObject * target __unused,
void * reference __unused )
{
if (selector >= kNumBattMethods) {
return kIOReturnBadArgument;
}
switch (selector)
{
case kSBInflowDisable:
return this->secureInflowDisable((int)arguments->scalarInput[0],
(int *)&arguments->scalarOutput[0]);
break;
case kSBChargeInhibit:
return this->secureChargeInhibit((int)arguments->scalarInput[0],
(int *)&arguments->scalarOutput[0]);
break;
case kSBSetPollingInterval:
return fOwner->setPollingInterval((int)arguments->scalarInput[0]);
break;
case kSBSMBusReadWriteWord:
return fOwner->performExternalTransaction(
(void *)arguments->structureInput,
(void *)arguments->structureOutput,
(IOByteCount)arguments->structureInputSize,
(IOByteCount *)&arguments->structureOutputSize);
break;
default:
return kIOReturnMessageTooLarge;
}
}