|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 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: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * IOAudioDevice.cpp ! 26: * ! 27: * HISTORY ! 28: * ! 29: */ ! 30: ! 31: #include <IOKit/assert.h> ! 32: ! 33: #include <IOKit/IOLib.h> ! 34: #include <IOKit/IOSyncer.h> ! 35: #include <IOKit/IOWorkLoop.h> ! 36: #include <IOKit/IOCommandQueue.h> ! 37: #include <IOKit/IOMemoryDescriptor.h> ! 38: #include <IOKit/audio/IOAudioController.h> ! 39: ! 40: //************************************************************************ ! 41: // Implementation of protocol classes. ! 42: //************************************************************************ ! 43: OSDefineMetaClass( IOAudioStream, IOUserClient ) ! 44: OSDefineAbstractStructors( IOAudioStream, IOUserClient ) ! 45: ! 46: OSDefineMetaClass( IOAudioComponent, IOUserClient ) ! 47: OSDefineAbstractStructors( IOAudioComponent, IOUserClient ) ! 48: ! 49: //************************************************************************ ! 50: // Begin implementation of IOAudioStreamImpl class. ! 51: //************************************************************************ ! 52: ! 53: #undef super ! 54: #define super IOAudioStream ! 55: OSDefineMetaClassAndStructors( IOAudioStreamImpl, IOAudioStream ) ! 56: ! 57: bool ! 58: IOAudioStreamImpl::initWithPropsIndexQueue(OSDictionary *props, ! 59: AudioStreamIndex index, IOCommandQueue *queue) ! 60: { ! 61: if(!super::init(props)) ! 62: return false; ! 63: ! 64: if(!queue) ! 65: return false; ! 66: ! 67: fIndex = index; ! 68: fCmdQueue = queue; ! 69: ! 70: fMappedMem.fMixBuffer = NULL; ! 71: ! 72: // make sure essential stuff is there ! 73: assert(OSDynamicCast(OSNumber, getProperty("In")) != NULL); ! 74: assert(OSDynamicCast(OSNumber, getProperty("Out")) != NULL); ! 75: ! 76: fMethods[kCallSetFlow].object = this; ! 77: fMethods[kCallSetFlow].func = (IOMethod) &IOAudioStream::setFlow; ! 78: fMethods[kCallSetFlow].count0 = 1; ! 79: fMethods[kCallSetFlow].count1 = 0; ! 80: fMethods[kCallSetFlow].flags = kIOUCScalarIScalarO; ! 81: ! 82: fMethods[kCallFlush].object = this; ! 83: fMethods[kCallFlush].func = (IOMethod) &IOAudioStream::Flush; ! 84: fMethods[kCallFlush].count0 = sizeof(IOAudioStreamPosition); ! 85: fMethods[kCallFlush].count1 = 0; ! 86: fMethods[kCallFlush].flags = kIOUCStructIStructO; ! 87: ! 88: fMethods[kCallSetErase].object = this; ! 89: fMethods[kCallSetErase].func = (IOMethod) &IOAudioStream::setErase; ! 90: fMethods[kCallSetErase].count0 = 1; ! 91: fMethods[kCallSetErase].count1 = 1; ! 92: fMethods[kCallSetErase].flags = kIOUCScalarIScalarO; ! 93: ! 94: return true; ! 95: } ! 96: ! 97: void IOAudioStreamImpl::free() ! 98: { ! 99: if (fMappedMem.fMixBuffer) { ! 100: // Need to free mix buffer here - it will leak now ! 101: } ! 102: ! 103: super::free(); ! 104: } ! 105: ! 106: /* ! 107: * Connect a client, possibly starting DMA for the stream if it's ! 108: * the first client. ! 109: */ ! 110: IOReturn ! 111: IOAudioStreamImpl::newUserClient( task_t owningTask, void * security_id, ! 112: UInt32 type, IOUserClient ** handler ) ! 113: { ! 114: IOSyncer *syncWakeup; ! 115: ! 116: *handler = this; ! 117: (*handler)->retain(); ! 118: ! 119: syncWakeup = IOSyncer::create(); ! 120: ! 121: fCmdQueue->enqueueCommand(true, syncWakeup, (void *)kConnect, ! 122: (void *)fIndex, &fMappedMem); ! 123: ! 124: syncWakeup->wait(); ! 125: ! 126: return kIOReturnSuccess; ! 127: } ! 128: ! 129: IOReturn IOAudioStreamImpl::clientDied() ! 130: { ! 131: /* ! 132: * Decrememt connection count, possibly freeing DMA buffers ! 133: */ ! 134: fCmdQueue->enqueueCommand(true, 0, (void *)kDetach, (void *)fIndex); ! 135: ! 136: return kIOReturnSuccess; ! 137: } ! 138: ! 139: IOReturn IOAudioStreamImpl::clientClose() ! 140: { ! 141: /* ! 142: * Decrememt connection count, possibly freeing DMA buffers ! 143: */ ! 144: //fCmdQueue->enqueueCommand(true, 0, (void *)kDetach, (void *)fIndex); ! 145: ! 146: return kIOReturnSuccess; ! 147: } ! 148: ! 149: IOReturn IOAudioStreamImpl::Flush(IOAudioStreamPosition *end) ! 150: { ! 151: // Tell device when it'll be safe to stop the stream ! 152: fCmdQueue->enqueueCommand(true, 0, (void *)kFlush, (void *)fIndex, (void *)end); ! 153: return kIOReturnSuccess; ! 154: } ! 155: ! 156: IOReturn IOAudioStreamImpl::setFlow(bool flowing) ! 157: { ! 158: fCmdQueue->enqueueCommand(true, 0, (void *)kSetFlow, (void *)fIndex, ! 159: (void *)flowing); ! 160: return kIOReturnSuccess; ! 161: } ! 162: ! 163: IOReturn IOAudioStreamImpl::isOutput(SInt32 *res) const ! 164: { ! 165: const OSNumber *obj; ! 166: obj = getOutputDescriptor(); ! 167: if(obj) ! 168: *res = obj->unsigned8BitValue(); ! 169: else ! 170: *res = 0; ! 171: ! 172: return kIOReturnSuccess; ! 173: } ! 174: ! 175: IOReturn IOAudioStreamImpl::getMixBuffer(void **mixBuffer) ! 176: { ! 177: *mixBuffer = fMappedMem.fMixBuffer; ! 178: ! 179: return kIOReturnSuccess; ! 180: } ! 181: ! 182: IOReturn IOAudioStreamImpl::setErase(bool erase, SInt32 *oldErase) ! 183: { ! 184: assert(fMappedMem.fStatus != NULL); // Must be a user attached. ! 185: *oldErase = fMappedMem.fStatus->fErases; ! 186: fMappedMem.fStatus->fErases = erase; ! 187: return kIOReturnSuccess; ! 188: } ! 189: ! 190: IOReturn ! 191: IOAudioStreamImpl::setProperties( OSObject * properties ) ! 192: { ! 193: return kIOReturnNotPrivileged; ! 194: } ! 195: ! 196: ! 197: IOReturn IOAudioStreamImpl::clientMemoryForType( UInt32 type, ! 198: UInt32 * flags, IOMemoryDescriptor ** memory ) ! 199: { ! 200: // kprintf("IOAudioStream::clientMemoryForType(%d, %d, %d, %d)\n", ! 201: // type, flags, address, size); ! 202: ! 203: switch(type) { ! 204: case kSampleBuffer: ! 205: *memory = IOMemoryDescriptor::withAddress( ! 206: (void *)fMappedMem.fSampleBuffer, ! 207: fMappedMem.fStatus->fBufSize, ! 208: kIODirectionNone); ! 209: *flags = 0; ! 210: break; ! 211: case kStatus: ! 212: *memory = IOMemoryDescriptor::withAddress( ! 213: (void *)fMappedMem.fStatus, ! 214: sizeof(IOAudioStreamStatus), ! 215: kIODirectionNone); ! 216: *flags = kIOMapReadOnly; ! 217: break; ! 218: case kMixBuffer: ! 219: if (fMappedMem.fMixBuffer == NULL) { ! 220: IOSyncer *syncWakeup; ! 221: ! 222: syncWakeup = IOSyncer::create(); ! 223: ! 224: fCmdQueue->enqueueCommand(true, syncWakeup, (void *)kAllocMixBuffer, ! 225: (void *)fIndex, (void *)&fMappedMem.fMixBuffer); ! 226: syncWakeup->wait(); ! 227: } ! 228: fMappedMem.fStatus->fMixBufferInUse = true; ! 229: *memory = IOMemoryDescriptor::withAddress( ! 230: (void *)fMappedMem.fMixBuffer, ! 231: (fMappedMem.fStatus->fBufSize / fMappedMem.fStatus->fSampleSize * sizeof(float)), ! 232: kIODirectionNone); ! 233: *flags = 0; ! 234: break; ! 235: default: ! 236: return kIOReturnUnsupported; ! 237: break; ! 238: } ! 239: return kIOReturnSuccess; ! 240: } ! 241: ! 242: IOExternalMethod * ! 243: IOAudioStreamImpl::getExternalMethodForIndex( UInt32 index ) ! 244: { ! 245: IOExternalMethod *method = NULL; ! 246: ! 247: if(index < kNumCalls) ! 248: method = &fMethods[index]; ! 249: return method; ! 250: } ! 251: ! 252: ! 253: //************************************************************************ ! 254: // Begin implementation of IOAudioComponentImpl class. ! 255: //************************************************************************ ! 256: ! 257: #undef super ! 258: #define super IOAudioComponent ! 259: OSDefineMetaClassAndStructors( IOAudioComponentImpl, IOAudioComponent ) ! 260: ! 261: ! 262: bool ! 263: IOAudioComponentImpl::initWithStuff(IOAudioController *owner, OSDictionary *props, ! 264: IOCommandQueue *queue) ! 265: { ! 266: if(!super::init(props)) ! 267: return false; ! 268: ! 269: if(!queue || !owner) ! 270: return false; ! 271: ! 272: fCmdQueue = queue; ! 273: fOwner = owner; ! 274: return true; ! 275: } ! 276: ! 277: void ! 278: IOAudioComponentImpl::free() ! 279: { ! 280: if(fNotifyMsg) ! 281: IOFree(fNotifyMsg, sizeof (struct _notifyMsg)); ! 282: ! 283: super::free(); ! 284: } ! 285: ! 286: IOReturn ! 287: IOAudioComponentImpl::updateVal(UInt32 val, OSDictionary *control, bool direct) ! 288: { ! 289: IOReturn ret = kIOReturnSuccess; ! 290: OSNumber * oldVal; ! 291: ! 292: oldVal = (OSNumber *)control->getObject(IOAudioController::gValSym); ! 293: if(val != oldVal->unsigned32BitValue()) { ! 294: OSNumber * id; ! 295: OSNumber * newVal; ! 296: newVal = OSNumber::withNumber(val, oldVal->numberOfBits()); ! 297: control->setObject(IOAudioController::gValSym, newVal); ! 298: id = (OSNumber *)control->getObject(IOAudioController::gIdSym); ! 299: if(id) { ! 300: if(direct) ! 301: fOwner->SetControl(id->unsigned16BitValue(), val); ! 302: else ! 303: fCmdQueue->enqueueCommand(true, 0, (void *)kSetVal, ! 304: (void *)id->unsigned16BitValue(), (void *)val); ! 305: ! 306: } ! 307: } ! 308: return ret; ! 309: } ! 310: ! 311: void ! 312: IOAudioComponentImpl::Set(const OSSymbol *type, const OSSymbol *name, int val) ! 313: { ! 314: OSDictionary *controls; ! 315: ! 316: controls = OSDynamicCast(OSDictionary, getProperty(type)); ! 317: ! 318: if(controls) { ! 319: OSDictionary *valDict; ! 320: OSNumber * old; ! 321: OSNumber * newObj; ! 322: valDict = OSDynamicCast(OSDictionary, ! 323: controls->getObject(name)); ! 324: if(valDict) { ! 325: old = OSDynamicCast(OSNumber, valDict->getObject(IOAudioController::gValSym)); ! 326: if(old) { ! 327: newObj = OSNumber::withNumber(val, old->numberOfBits()); ! 328: valDict->setObject(IOAudioController::gValSym, newObj); ! 329: newObj->release(); // XXX -- svail: added. ! 330: /* FIXME: Don't block */ ! 331: if(fNotifyMsg) ! 332: mach_msg_send_from_kernel((mach_msg_header_t *)fNotifyMsg, ! 333: fNotifyMsg->h.msgh_size); ! 334: else if(type == IOAudioController::gInputsSym && ! 335: name == IOAudioController::gJackSym && ! 336: ( GetType() == IOAudioController::gHeadphonesSym || ! 337: GetType() == IOAudioController::gLineOutSym)) { ! 338: /* ! 339: * This is a headphone or line out jack, mute/unmute any speakers ! 340: * with the same IOAudio parent ! 341: */ ! 342: OSIterator * parents = ! 343: getParentIterator(IOAudioController::gIOAudioPlane); ! 344: IORegistryEntry *parent; ! 345: while((parent = OSDynamicCast(IORegistryEntry, parents->getNextObject()))) { ! 346: OSIterator * siblings = ! 347: parent->getChildIterator(IOAudioController::gIOAudioPlane); ! 348: IOAudioComponentImpl *sibling; ! 349: while((sibling = OSDynamicCast(IOAudioComponentImpl, siblings->getNextObject()))) { ! 350: if(sibling->GetType() == IOAudioController::gSpeakerSym) { ! 351: // Set all controls of type Mute to the new value ! 352: OSDictionary *spkrCtls = ! 353: OSDynamicCast(OSDictionary, sibling->getProperty(IOAudioController::gControlsSym)); ! 354: OSCollectionIterator *iter = OSCollectionIterator::withCollection(spkrCtls); ! 355: OSSymbol *iterKey; ! 356: while((iterKey = OSDynamicCast(OSSymbol, iter->getNextObject()))){ ! 357: OSObject *spkrCtlObj = spkrCtls->getObject(iterKey); ! 358: if(GetType(spkrCtlObj) == IOAudioController::gMuteSym) { ! 359: // Safe to just cast because GetType checks object type. ! 360: // Update hardware directly ! 361: updateVal(val, (OSDictionary *)spkrCtlObj, true); ! 362: } ! 363: } ! 364: } ! 365: } ! 366: } ! 367: } ! 368: } ! 369: } ! 370: } ! 371: } ! 372: ! 373: IOReturn IOAudioComponentImpl::clientClose( void ) ! 374: { ! 375: return kIOReturnSuccess; ! 376: } ! 377: ! 378: IOReturn IOAudioComponentImpl::clientDied( void ) ! 379: { ! 380: return kIOReturnSuccess; ! 381: } ! 382: /* ! 383: * Return a subclass of IOUserClient for User<->kernel comminication ! 384: * Since IOAudioStream is such a suclass, we can return the object ! 385: * itself (remembering to increment its retain count!). ! 386: */ ! 387: IOReturn IOAudioComponentImpl::newUserClient( task_t owningTask, ! 388: void * security_id, UInt32 type, IOUserClient ** handler ) ! 389: { ! 390: //kprintf("task:%d, sec_id:0x%x, type:%d\n", owningTask, security_id, type); ! 391: *handler = this; ! 392: (*handler)->retain(); ! 393: ! 394: return kIOReturnSuccess; ! 395: } ! 396: ! 397: ! 398: IOReturn ! 399: IOAudioComponentImpl::setProperties( OSObject * properties ) ! 400: { ! 401: OSDictionary *myControls; ! 402: OSDictionary *newControls; ! 403: OSDictionary *newDict; ! 404: OSCollectionIterator *iter; ! 405: OSObject *iterKey; ! 406: IOReturn ret = kIOReturnSuccess; ! 407: ! 408: newDict = OSDynamicCast(OSDictionary, properties); ! 409: if(!newDict) ! 410: return kIOReturnBadArgument; ! 411: ! 412: myControls = OSDynamicCast(OSDictionary, getProperty(IOAudioController::gControlsSym)); ! 413: newControls = OSDynamicCast(OSDictionary, newDict->getObject(IOAudioController::gControlsSym)); ! 414: if(!newControls) ! 415: return kIOReturnBadArgument; ! 416: ! 417: /* ! 418: * Look through the Controls dictionary, for each one that has a new Val ! 419: * make a kSetVal command, updating the hardware. ! 420: */ ! 421: iter = OSCollectionIterator::withCollection(newControls); ! 422: while((iterKey = iter->getNextObject())) { ! 423: OSSymbol *key = OSDynamicCast(OSSymbol, iterKey); ! 424: OSDictionary *newCtrl; ! 425: OSNumber* newVal; ! 426: if(!key) { ! 427: ret = kIOReturnBadArgument; ! 428: break; ! 429: } ! 430: OSDictionary *myCtrl; ! 431: myCtrl = (OSDictionary *)myControls->getObject(key); ! 432: if(!myCtrl) { ! 433: ret = kIOReturnBadArgument; ! 434: break; ! 435: } ! 436: newCtrl = OSDynamicCast(OSDictionary, newControls->getObject(key)); ! 437: if(!newCtrl) { ! 438: ret = kIOReturnBadArgument; ! 439: break; ! 440: } ! 441: newVal = OSDynamicCast(OSNumber, newCtrl->getObject(IOAudioController::gValSym)); ! 442: if(!newVal) { ! 443: ret = kIOReturnBadArgument; ! 444: break; ! 445: } ! 446: // Update hardware via command queue ! 447: ret = updateVal(newVal->unsigned16BitValue(), myCtrl, false); ! 448: if(kIOReturnSuccess != ret) ! 449: break; ! 450: } ! 451: ! 452: return ret; ! 453: } ! 454: ! 455: IOReturn ! 456: IOAudioComponentImpl::registerNotificationPort( ! 457: mach_port_t port, UInt32 type, UInt32 refCon) ! 458: { ! 459: static IOAudioNotifyMsg notify_msg = {{ ! 460: // mach_msg_bits_t msgh_bits; ! 461: MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,0), ! 462: // mach_msg_size_t msgh_size; ! 463: sizeof (IOAudioNotifyMsg), ! 464: // mach_port_t msgh_remote_port; ! 465: MACH_PORT_NULL, ! 466: // mach_port_t msgh_local_port; ! 467: MACH_PORT_NULL, ! 468: // mach_msg_size_t msgh_reserved; ! 469: 0, ! 470: // mach_msg_id_t msgh_id; ! 471: type }, ! 472: // UInt32 refCon ! 473: refCon ! 474: }; ! 475: ! 476: if( type != kIOAudioInputNotification) ! 477: return( kIOReturnUnsupported); ! 478: if ( fNotifyMsg == NULL ) ! 479: fNotifyMsg = (struct _notifyMsg *) ! 480: IOMalloc( sizeof (IOAudioNotifyMsg) ); ! 481: // Initialize the events available message. ! 482: *fNotifyMsg = notify_msg; ! 483: ! 484: fNotifyMsg->h.msgh_remote_port = port; ! 485: ! 486: return kIOReturnSuccess; ! 487: } ! 488: ! 489: const OSSymbol * ! 490: IOAudioComponentImpl::GetType() const ! 491: { ! 492: const OSString *type; ! 493: type = OSDynamicCast(OSString, getProperty(IOAudioController::gTypeSym)); ! 494: ! 495: return OSSymbol::withString(type); ! 496: } ! 497: ! 498: const OSSymbol * ! 499: IOAudioComponentImpl::GetType(const OSObject *obj) const ! 500: { ! 501: const OSString *type; ! 502: const OSDictionary *dict; ! 503: dict = OSDynamicCast(OSDictionary, obj); ! 504: if(NULL == dict) ! 505: return NULL; ! 506: type = OSDynamicCast(OSString, dict->getObject(IOAudioController::gTypeSym)); ! 507: ! 508: return OSSymbol::withString(type); ! 509: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.