1/* 2 * Copyright (c) 1998-2014 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 "IOAudioPort.h" 24#include "IOAudioControl.h" 25#include "IOAudioDevice.h" 26#include "IOAudioTypes.h" 27#include "IOAudioDefines.h" 28#include "IOAudioDebug.h" 29#include "AudioTracepoints.h" 30 31#include <libkern/c++/OSSet.h> 32#include <libkern/c++/OSCollectionIterator.h> 33 34#include <IOKit/IOLib.h> 35 36#define super IOService 37 38OSDefineMetaClassAndStructors(IOAudioPort, IOService) 39OSMetaClassDefineReservedUnused(IOAudioPort, 0); 40OSMetaClassDefineReservedUnused(IOAudioPort, 1); 41OSMetaClassDefineReservedUnused(IOAudioPort, 2); 42OSMetaClassDefineReservedUnused(IOAudioPort, 3); 43OSMetaClassDefineReservedUnused(IOAudioPort, 4); 44OSMetaClassDefineReservedUnused(IOAudioPort, 5); 45OSMetaClassDefineReservedUnused(IOAudioPort, 6); 46OSMetaClassDefineReservedUnused(IOAudioPort, 7); 47OSMetaClassDefineReservedUnused(IOAudioPort, 8); 48OSMetaClassDefineReservedUnused(IOAudioPort, 9); 49OSMetaClassDefineReservedUnused(IOAudioPort, 10); 50OSMetaClassDefineReservedUnused(IOAudioPort, 11); 51OSMetaClassDefineReservedUnused(IOAudioPort, 12); 52OSMetaClassDefineReservedUnused(IOAudioPort, 13); 53OSMetaClassDefineReservedUnused(IOAudioPort, 14); 54OSMetaClassDefineReservedUnused(IOAudioPort, 15); 55OSMetaClassDefineReservedUnused(IOAudioPort, 16); 56OSMetaClassDefineReservedUnused(IOAudioPort, 17); 57OSMetaClassDefineReservedUnused(IOAudioPort, 18); 58OSMetaClassDefineReservedUnused(IOAudioPort, 19); 59OSMetaClassDefineReservedUnused(IOAudioPort, 20); 60OSMetaClassDefineReservedUnused(IOAudioPort, 21); 61OSMetaClassDefineReservedUnused(IOAudioPort, 22); 62OSMetaClassDefineReservedUnused(IOAudioPort, 23); 63OSMetaClassDefineReservedUnused(IOAudioPort, 24); 64OSMetaClassDefineReservedUnused(IOAudioPort, 25); 65OSMetaClassDefineReservedUnused(IOAudioPort, 26); 66OSMetaClassDefineReservedUnused(IOAudioPort, 27); 67OSMetaClassDefineReservedUnused(IOAudioPort, 28); 68OSMetaClassDefineReservedUnused(IOAudioPort, 29); 69OSMetaClassDefineReservedUnused(IOAudioPort, 30); 70OSMetaClassDefineReservedUnused(IOAudioPort, 31); 71 72IOAudioPort *IOAudioPort::withAttributes(UInt32 portType, const char *portName, UInt32 subType, OSDictionary *properties) 73{ 74 IOAudioPort *port; 75 76 port = new IOAudioPort; 77 if (port) { 78 if (!port->initWithAttributes(portType, portName, subType, properties)) { 79 port->release(); 80 port = 0; 81 } 82 } 83 84 return port; 85} 86 87bool IOAudioPort::initWithAttributes(UInt32 portType, const char *portName, UInt32 subType, OSDictionary *properties) 88{ 89 if (!init(properties)) { 90 return false; 91 } 92 93 if (portType == 0) { 94 return false; 95 } 96 97 audioDevice = 0; 98 isRegistered = false; 99 100 setType(portType); 101 102 if (portName != 0) { 103 setName(portName); 104 } 105 106 if (subType != 0) { 107 setSubType(subType); 108 } 109 110 audioControls = OSSet::withCapacity(1); 111 if (!audioControls) { 112 return false; 113 } 114 115 return true; 116} 117 118void IOAudioPort::free() 119{ 120 if (audioControls) { 121 audioControls->release(); 122 } 123 124 super::free(); 125} 126 127void IOAudioPort::setType(UInt32 portType) 128{ 129 setProperty(kIOAudioPortTypeKey, portType, sizeof(UInt32)*8); 130} 131 132void IOAudioPort::setSubType(UInt32 subType) 133{ 134 setProperty(kIOAudioPortSubTypeKey, subType, sizeof(UInt32)*8); 135} 136 137void IOAudioPort::setName(const char *portName) 138{ 139 setProperty(kIOAudioPortNameKey, portName); 140} 141 142bool IOAudioPort::start(IOService *provider) 143{ 144 AudioTrace_Start(kAudioTIOAudioPort, kTPIOAudioPortStart, (uintptr_t)this, (uintptr_t)provider, 0, 0); 145 if (!super::start(provider)) { 146 return false; 147 } 148 149 if (!(audioDevice = OSDynamicCast(IOAudioDevice, provider))) { 150 return false; 151 } 152 153 AudioTrace_End(kAudioTIOAudioPort, kTPIOAudioPortStart, (uintptr_t)this, (uintptr_t)provider, true, 0); 154 return true; 155} 156 157void IOAudioPort::stop(IOService *provider) 158{ 159 deactivateAudioControls(); 160 super::stop(provider); 161} 162 163void IOAudioPort::registerService(IOOptionBits options) 164{ 165 super::registerService(options); 166 167 if (audioControls && !isRegistered) { 168 OSCollectionIterator *iterator; 169 170 iterator = OSCollectionIterator::withCollection(audioControls); 171 if (iterator) { 172 IOAudioControl *control; 173 174 while ( (control = (IOAudioControl *)iterator->getNextObject()) ) { 175 if (control->getProvider() == this) { 176 control->registerService(); 177 } 178 } 179 iterator->release(); 180 } 181 } 182 183 isRegistered = true; 184} 185 186IOAudioDevice *IOAudioPort::getAudioDevice() 187{ 188 return audioDevice; 189} 190 191IOReturn IOAudioPort::addAudioControl(IOAudioControl *control) 192{ 193 bool controlWasStarted; 194 195 if (!control || !audioControls) { 196 return kIOReturnBadArgument; 197 } 198 199 if (!control->attach(this)) { 200 return kIOReturnError; 201 } 202 203 controlWasStarted = control->getIsStarted(); 204 205 if (!controlWasStarted) { 206 if (!control->start(this)) { 207 control->detach(this); 208 return kIOReturnError; 209 } 210 } 211 212 audioControls->setObject(control); 213 214 if (isRegistered && !controlWasStarted) { 215 control->registerService(); 216 } 217 218 return kIOReturnSuccess; 219} 220 221void IOAudioPort::deactivateAudioControls() 222{ 223 OSCollectionIterator *iterator; 224 225 if (!audioControls) { 226 return; 227 } 228 229 iterator = OSCollectionIterator::withCollection(audioControls); 230 231 if (iterator) { 232 IOAudioControl *control; 233 234 while ( (control = (IOAudioControl *)iterator->getNextObject()) ) { 235 // Should we check to see if we're the provider? 236 if (!isInactive()) { 237 control->terminate(); 238 } 239 } 240 241 iterator->release(); 242 } 243 244 audioControls->flushCollection(); 245} 246