1/* 2 * Copyright (c) 1998-2010 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include "IOAudioDebug.h" 24#include "IOAudioControlUserClient.h" 25#include "IOAudioControl.h" 26#include "IOAudioTypes.h" 27#include "IOAudioDefines.h" 28 29#include <IOKit/IOLib.h> 30#include <IOKit/IOCommandGate.h> 31#include <IOKit/IOKitKeys.h> 32 33#define super IOUserClient 34 35OSDefineMetaClassAndStructors(IOAudioControlUserClient, IOUserClient) 36OSMetaClassDefineReservedUsed(IOAudioControlUserClient, 0); 37OSMetaClassDefineReservedUsed(IOAudioControlUserClient, 1); 38 39OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 2); 40OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 3); 41OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 4); 42OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 5); 43OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 6); 44OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 7); 45OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 8); 46OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 9); 47OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 10); 48OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 11); 49OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 12); 50OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 13); 51OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 14); 52OSMetaClassDefineReservedUnused(IOAudioControlUserClient, 15); 53 54// New code here 55 56// OSMetaClassDefineReservedUsed(IOAudioControlUserClient, 1); 57bool IOAudioControlUserClient::initWithAudioControl(IOAudioControl *control, task_t task, void *securityID, UInt32 type, OSDictionary *properties) 58{ 59 // Declare Rosetta compatibility 60 if (properties) { 61 properties->setObject(kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue); 62 } 63 64 if (!initWithTask(task, securityID, type, properties)) { 65 return false; 66 } 67/* 68 // For 3019260 69 if (clientHasPrivilege(securityID, kIOClientPrivilegeLocalUser)) { 70 // You don't have enough privileges to control the audio 71 return false; 72 } 73*/ 74 if (!control) { 75 return false; 76 } 77 78 audioControl = control; 79 audioControl->retain(); 80 clientTask = task; 81 notificationMessage = 0; 82 83 return true; 84} 85 86// OSMetaClassDefineReservedUsed(IOAudioControlUserClient, 0); 87void IOAudioControlUserClient::sendChangeNotification(UInt32 notificationType) 88{ 89 if (notificationMessage) { 90 kern_return_t kr; 91 92 notificationMessage->type = notificationType; 93 kr = mach_msg_send_from_kernel(¬ificationMessage->messageHeader, notificationMessage->messageHeader.msgh_size); 94 if ((kr != MACH_MSG_SUCCESS) && (kr != MACH_SEND_TIMED_OUT)) { 95 IOLog("IOAudioControlUserClient: sendRangeChangeNotification() failed - msg_send returned: %d\n", kr); 96 } 97 } 98} 99 100IOAudioControlUserClient *IOAudioControlUserClient::withAudioControl(IOAudioControl *control, task_t clientTask, void *securityID, UInt32 type, OSDictionary *properties) 101{ 102 IOAudioControlUserClient *client; 103 104 client = new IOAudioControlUserClient; 105 106 if (client) { 107 if (!client->initWithAudioControl(control, clientTask, securityID, type, properties)) { 108 client->release(); 109 client = 0; 110 } 111 } 112 113 return client; 114} 115 116// Original code here... 117IOAudioControlUserClient *IOAudioControlUserClient::withAudioControl(IOAudioControl *control, task_t clientTask, void *securityID, UInt32 type) 118{ 119 IOAudioControlUserClient *client; 120 121 client = new IOAudioControlUserClient; 122 123 if (client) { 124 if (!client->initWithAudioControl(control, clientTask, securityID, type)) { 125 client->release(); 126 client = 0; 127 } 128 } 129 130 return client; 131} 132 133bool IOAudioControlUserClient::initWithAudioControl(IOAudioControl *control, task_t task, void *securityID, UInt32 type) 134{ 135 if (!initWithTask(task, securityID, type)) { 136 return false; 137 } 138/* 139 // For 3019260 140 if (clientHasPrivilege(securityID, kIOClientPrivilegeLocalUser)) { 141 // You don't have enough privileges to control the audio 142 return false; 143 } 144*/ 145 if (!control) { 146 return false; 147 } 148 149 audioControl = control; 150 audioControl->retain(); 151 clientTask = task; 152 notificationMessage = 0; 153 154 return true; 155} 156 157void IOAudioControlUserClient::free() 158{ 159 audioDebugIOLog(3, "+ IOAudioControlUserClient[%p]::free()\n", this); 160 161 if (notificationMessage) { 162 IOFreeAligned(notificationMessage, sizeof(IOAudioNotificationMessage)); 163 notificationMessage = 0; 164 } 165 166 if (audioControl) { 167 audioControl->release (); 168 audioControl = 0; 169 } 170 171 if (reserved) { 172 IOFree (reserved, sizeof(struct ExpansionData)); 173 } 174 175 super::free(); 176 audioDebugIOLog(3, "- IOAudioControlUserClient[%p]::free()\n", this); 177} 178 179IOReturn IOAudioControlUserClient::clientClose() 180{ 181 audioDebugIOLog(3, "+ IOAudioControlUserClient[%p]::clientClose()\n", this); 182 183 if (audioControl) { 184 if (!audioControl->isInactive () && !isInactive()) { 185 audioControl->clientClosed(this); 186 } 187 audioControl->release(); 188 audioControl = 0; 189 } 190 191 audioDebugIOLog(3, "- IOAudioControlUserClient[%p]::clientClose() returns 0x%lX\n", this, (long unsigned int)kIOReturnSuccess ); 192 return kIOReturnSuccess; 193} 194 195IOReturn IOAudioControlUserClient::clientDied() 196{ 197 IOReturn result = kIOReturnError; 198 199 audioDebugIOLog(3, "+ IOAudioControlUserClient[%p]::clientDied()\n", this); 200 201 result = clientClose(); 202 203 audioDebugIOLog(3, "- IOAudioControlUserClient[%p]::clientDied() returns 0x%lX\n", this, (long unsigned int)result ); 204 return result; 205} 206 207IOReturn IOAudioControlUserClient::registerNotificationPort(mach_port_t port, 208 UInt32 type, // No longer used now that we have the generic sendChangeNotification routine 209 UInt32 refCon) 210{ 211 IOReturn result = kIOReturnSuccess; 212 213 if (!isInactive()) { 214 if (notificationMessage == 0) { 215 notificationMessage = (IOAudioNotificationMessage *)IOMallocAligned(sizeof(IOAudioNotificationMessage), sizeof (IOAudioNotificationMessage *)); 216 if (!notificationMessage) { 217 return kIOReturnNoMemory; 218 } 219 } 220 221 notificationMessage->messageHeader.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); 222 notificationMessage->messageHeader.msgh_size = sizeof(IOAudioNotificationMessage); 223 notificationMessage->messageHeader.msgh_remote_port = port; 224 notificationMessage->messageHeader.msgh_local_port = MACH_PORT_NULL; 225 notificationMessage->messageHeader.msgh_reserved = 0; 226 notificationMessage->messageHeader.msgh_id = 0; 227 228 // notificationMessage->type = type; // ignored now that we have the generic sendChangeNotification routine 229 notificationMessage->ref = refCon; 230 } else { 231 result = kIOReturnNoDevice; 232 } 233 234 return result; 235} 236 237void IOAudioControlUserClient::sendValueChangeNotification() 238{ 239 return sendChangeNotification(kIOAudioControlValueChangeNotification); 240} 241