1/* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 25 * 26 */ 27 28#include <sys/systm.h> 29#include <sys/proc.h> 30#include <kern/task.h> 31#include "AppleSmartBatteryManagerUserClient.h" 32 33#define super IOUserClient 34 35enum { 36 kCallOnOwner = 0, 37 kCallOnSelf = 1 38}; 39 40 41/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 42 43OSDefineMetaClassAndStructors(AppleSmartBatteryManagerUserClient, IOUserClient) 44 45/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 46 47bool AppleSmartBatteryManagerUserClient::initWithTask(task_t owningTask, 48 void *security_id, UInt32 type, OSDictionary * properties) 49{ 50 uint32_t _pid; 51 52 /* 1. Only root processes may open a SmartBatteryManagerUserClient. 53 * 2. Attempts to create exclusive UserClients will fail if an 54 * exclusive user client is attached. 55 * 3. Non-exclusive clients will not be able to perform transactions 56 * while an exclusive client is attached. 57 * 3a. Only battery firmware updaters should bother being exclusive. 58 */ 59 if ( kIOReturnSuccess != 60 clientHasPrivilege(owningTask, kIOClientPrivilegeAdministrator)) 61 { 62 return false; 63 } 64 65 if (!super::initWithTask(owningTask, security_id, type, properties)) { 66 return false; 67 } 68 69 fUserClientType = type; 70 71 _pid = proc_selfpid(); 72 setProperty("pid", _pid, 32); 73 74 fOwningTask = owningTask; 75 task_reference (fOwningTask); 76 return true; 77} 78 79 80bool AppleSmartBatteryManagerUserClient::start( IOService * provider ) 81{ 82 fOwner = (AppleSmartBatteryManager *)provider; 83 84 /* 85 * exclusive access user client? 86 * shut up the AppleSmartBattery from doing ongoing polls 87 * 88 */ 89 if (kSBExclusiveSMBusAccessType == fUserClientType) 90 { 91 if(!fOwner->requestExclusiveSMBusAccess(true)) { 92 // requestExclusiveSMBusAccess will return false if there's already 93 // an exclusive user client. 94 return false; 95 } 96 } 97 98 if(!super::start(provider)) 99 return false; 100 101 return true; 102} 103 104IOReturn AppleSmartBatteryManagerUserClient::secureInflowDisable( 105 int level, 106 int *return_code) 107{ 108 int admin_priv = 0; 109 IOReturn ret = kIOReturnNotPrivileged; 110 111 if( !(level == 0 || level == 1)) 112 { 113 *return_code = kIOReturnBadArgument; 114 return kIOReturnSuccess; 115 } 116 117 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 118 admin_priv = (kIOReturnSuccess == ret); 119 120 if(admin_priv && fOwner) { 121 *return_code = fOwner->disableInflow( level ); 122 return kIOReturnSuccess; 123 } else { 124 *return_code = kIOReturnNotPrivileged; 125 return kIOReturnSuccess; 126 } 127 128} 129 130IOReturn AppleSmartBatteryManagerUserClient::secureChargeInhibit( 131 int level, 132 int *return_code) 133{ 134 int admin_priv = 0; 135 IOReturn ret = kIOReturnNotPrivileged; 136 137 if( !(level == 0 || level == 1)) 138 { 139 *return_code = kIOReturnBadArgument; 140 return kIOReturnSuccess; 141 } 142 143 ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); 144 admin_priv = (kIOReturnSuccess == ret); 145 146 if(admin_priv && fOwner) { 147 *return_code = fOwner->inhibitCharging(level); 148 return kIOReturnSuccess; 149 } else { 150 *return_code = kIOReturnNotPrivileged; 151 return kIOReturnSuccess; 152 } 153 154} 155 156 157IOReturn AppleSmartBatteryManagerUserClient::clientClose( void ) 158{ 159 /* remove our request for exclusive SMBus access */ 160 if (kSBExclusiveSMBusAccessType == fUserClientType) { 161 fOwner->requestExclusiveSMBusAccess(false); 162 } 163 164 detach(fOwner); 165 166 if(fOwningTask) { 167 task_deallocate(fOwningTask); 168 fOwningTask = 0; 169 } 170 171 // We only have one application client. If the app is closed, 172 // we can terminate the user client. 173 terminate(); 174 175 return kIOReturnSuccess; 176} 177 178IOReturn 179AppleSmartBatteryManagerUserClient::externalMethod( 180 uint32_t selector, 181 IOExternalMethodArguments * arguments, 182 IOExternalMethodDispatch * dispatch __unused, 183 OSObject * target __unused, 184 void * reference __unused ) 185{ 186 if (selector >= kNumBattMethods) { 187 // Invalid selector 188 return kIOReturnBadArgument; 189 } 190 191 switch (selector) 192 { 193 case kSBInflowDisable: 194 // 1 scalar in, 1 scalar out 195 return this->secureInflowDisable((int)arguments->scalarInput[0], 196 (int *)&arguments->scalarOutput[0]); 197 break; 198 199 case kSBChargeInhibit: 200 // 1 scalar in, 1 scalar out 201 return this->secureChargeInhibit((int)arguments->scalarInput[0], 202 (int *)&arguments->scalarOutput[0]); 203 break; 204 205 case kSBSetPollingInterval: 206 // Deprecated. AppleSmartBattery doesn't have a polling interval. 207 return kIOReturnBadArgument; 208 209 case kSBSMBusReadWriteWord: 210 if ((kSBExclusiveSMBusAccessType != fUserClientType) && fOwner->hasExclusiveClient()) 211 { 212 /* SmartBatteryManager should not perform this request if there's an exclusive client 213 * attached, and this client isn't the exclusive client. */ 214 return kIOReturnSuccess; 215 } 216 // Struct in, struct out 217 return fOwner->performExternalTransaction( 218 (void *)arguments->structureInput, 219 (void *)arguments->structureOutput, 220 (IOByteCount)arguments->structureInputSize, 221 (IOByteCount *)&arguments->structureOutputSize); 222 break; 223 224 case kSBRequestPoll: 225 // 1 scalar in; 0 scalar out 226 return fOwner->requestPoll(arguments->scalarInput[0]); 227 228 default: 229 return kIOReturnBadArgument; 230 } 231} 232 233