|
|
1.1 ! root 1: #include <IOKit/IOUserClient.h> ! 2: #include <IOKit/assert.h> ! 3: #include "IOCDAudioNub.h" ! 4: #include "IOCDAudioNubClient.h" ! 5: ! 6: #define super IOUserClient ! 7: ! 8: OSDefineMetaClassAndStructors(IOCDAudioNubClient, IOUserClient) ! 9: ! 10: IOCDAudioNubClient *IOCDAudioNubClient::withTask(task_t owningTask) ! 11: { ! 12: IOCDAudioNubClient *me; ! 13: ! 14: me = new IOCDAudioNubClient; ! 15: if(me) { ! 16: if(!me->init()) { ! 17: me->release(); ! 18: return NULL; ! 19: } ! 20: me->fTask = owningTask; ! 21: } ! 22: return me; ! 23: } ! 24: ! 25: bool IOCDAudioNubClient::start( IOService * provider ) ! 26: { ! 27: kprintf("IOCDAudioNubClient::start\n"); ! 28: ! 29: assert(OSDynamicCast(IOCDAudioNub, provider)); ! 30: if(!super::start(provider)) ! 31: return false; ! 32: fOwner = (IOCDAudioNub *)provider; ! 33: ! 34: fMethods[kTest].object = this; ! 35: fMethods[kTest].func = ! 36: (IOMethod)&IOCDAudioNubClient::CDAudioNubTest; ! 37: fMethods[kTest].count0 = 3; ! 38: fMethods[kTest].count1 = 1; ! 39: fMethods[kTest].flags = kIOUCScalarIScalarO; ! 40: ! 41: fMethods[kGetNumAudioTracks].object = this; ! 42: fMethods[kGetNumAudioTracks].func = ! 43: (IOMethod)&IOCDAudioNubClient::getNumAudioTracks; ! 44: fMethods[kGetNumAudioTracks].count0 = 0; ! 45: fMethods[kGetNumAudioTracks].count1 = 1; ! 46: fMethods[kGetNumAudioTracks].flags = kIOUCScalarIScalarO; ! 47: ! 48: fMethods[kGetMSF].object = this; ! 49: fMethods[kGetMSF].func = ! 50: (IOMethod)&IOCDAudioNubClient::getMSF; ! 51: fMethods[kGetMSF].count0 = 1; ! 52: fMethods[kGetMSF].count1 = 1; ! 53: fMethods[kGetMSF].flags = kIOUCScalarIScalarO; ! 54: ! 55: fMethods[kPlayTrack].object = this; ! 56: fMethods[kPlayTrack].func = ! 57: (IOMethod)&IOCDAudioNubClient::playTrack; ! 58: fMethods[kPlayTrack].count0 = 1; ! 59: fMethods[kPlayTrack].count1 = 1; ! 60: fMethods[kPlayTrack].flags = kIOUCScalarIScalarO; ! 61: ! 62: fMethods[kPause].object = this; ! 63: fMethods[kPause].func = ! 64: (IOMethod)&IOCDAudioNubClient::pause; ! 65: fMethods[kPause].count0 = 0; ! 66: fMethods[kPause].count1 = 1; ! 67: fMethods[kPause].flags = kIOUCScalarIScalarO; ! 68: ! 69: fMethods[kResume].object = this; ! 70: fMethods[kResume].func = ! 71: (IOMethod)&IOCDAudioNubClient::resume; ! 72: fMethods[kResume].count0 = 0; ! 73: fMethods[kResume].count1 = 1; ! 74: fMethods[kResume].flags = kIOUCScalarIScalarO; ! 75: ! 76: fMethods[kGetVolume].object = this; ! 77: fMethods[kGetVolume].func = ! 78: (IOMethod)&IOCDAudioNubClient::getVolume; ! 79: fMethods[kGetVolume].count0 = 0; ! 80: fMethods[kGetVolume].count1 = 1; ! 81: fMethods[kGetVolume].flags = kIOUCScalarIScalarO; ! 82: ! 83: fMethods[kSetVolume].object = this; ! 84: fMethods[kSetVolume].func = ! 85: (IOMethod)&IOCDAudioNubClient::setVolume; ! 86: fMethods[kSetVolume].count0 = 2; ! 87: fMethods[kSetVolume].count1 = 1; ! 88: fMethods[kSetVolume].flags = kIOUCScalarIScalarO; ! 89: ! 90: fMethods[kGetAudioStatus].object = this; ! 91: fMethods[kGetAudioStatus].func = ! 92: (IOMethod)&IOCDAudioNubClient::getAudioStatus; ! 93: fMethods[kGetAudioStatus].count0 = 0; ! 94: fMethods[kGetAudioStatus].count1 = 4; ! 95: fMethods[kGetAudioStatus].flags = kIOUCScalarIScalarO; ! 96: ! 97: fMethods[kPlayMSF].object = this; ! 98: fMethods[kPlayMSF].func = ! 99: (IOMethod)&IOCDAudioNubClient::playMSF; ! 100: fMethods[kPlayMSF].count0 = 2; ! 101: fMethods[kPlayMSF].count1 = 1; ! 102: fMethods[kPlayMSF].flags = kIOUCScalarIScalarO; ! 103: ! 104: return true; ! 105: } ! 106: ! 107: IOReturn IOCDAudioNubClient::clientClose( void ) ! 108: { ! 109: kprintf("IOCDAudioNubClient::clientClose\n"); ! 110: if (fOwner) { ! 111: fOwner->close(this); ! 112: detach( fOwner); ! 113: } ! 114: return kIOReturnSuccess; ! 115: } ! 116: ! 117: IOReturn IOCDAudioNubClient::clientDied( void ) ! 118: { ! 119: return( clientClose()); ! 120: } ! 121: ! 122: IOReturn IOCDAudioNubClient::connectClient( IOUserClient * client ) ! 123: { ! 124: return kIOReturnSuccess; ! 125: } ! 126: ! 127: IOExternalMethod * IOCDAudioNubClient::getExternalMethodForIndex( UInt32 index ) ! 128: { ! 129: kprintf("IOCDAudioNubClient::getExternalMethodForIndex: %d\n",index); ! 130: if(index >= kMethods) { ! 131: kprintf("IOCDAudioNubClient::getExternalMethodForIndex: bad index\n"); ! 132: return NULL; ! 133: } else { ! 134: return &fMethods[index]; ! 135: } ! 136: } ! 137: ! 138: IOReturn IOCDAudioNubClient::registerNotificationPort( ! 139: mach_port_t port, UInt32 type ) ! 140: { ! 141: return kIOReturnUnsupported; ! 142: } ! 143: ! 144: IOReturn IOCDAudioNubClient::clientMemoryForType( UInt32 type, ! 145: UInt32 * flags, IOMemoryDescriptor ** memory ) ! 146: { ! 147: return 1; ! 148: } ! 149: ! 150: IOReturn IOCDAudioNubClient::CDAudioNubTest(UInt32 opcode, UInt32 operand1, UInt32 operand2, UInt32 *status) ! 151: { ! 152: // IOLog("IOCDAudioNubClient::CDAudioNubTest %d %d %d\n", opcode,operand1,operand2); ! 153: ! 154: if (!fOwner) return -2; ! 155: ! 156: switch(opcode) { ! 157: case 0: ! 158: return getNumAudioTracks(status); ! 159: case 1: ! 160: return getMSF(operand1-1,status); ! 161: case 2: ! 162: return playTrack(operand1-1,status); ! 163: case 3: ! 164: return pause(status); ! 165: case 4: ! 166: return resume(status); ! 167: case 5: ! 168: return getVolume(status); ! 169: case 6: ! 170: return setVolume((UInt8)operand1,(UInt8)operand2,status); ! 171: case 7: ! 172: return getAudioStatus(status,status,status,status); ! 173: case 8: ! 174: return playMSF(operand1,operand2,status); ! 175: case 9: ! 176: return readHeader(operand1,status); ! 177: } ! 178: ! 179: return -1; ! 180: } ! 181: ! 182: int subMSF(int m1, int m2) ! 183: { ! 184: int f1,f2; ! 185: int min,sec,frm; ! 186: ! 187: // convert to total frames ! 188: f1 = (m1 >> 16 & 0xff) * 75 * 60 + ! 189: (m1 >> 8 & 0xff) * 75 + ! 190: (m1 & 0xff); ! 191: f2 = (m2 >> 16 & 0xff) * 75 * 60 + ! 192: (m2 >> 8 & 0xff) * 75 + ! 193: (m2 & 0xff); ! 194: ! 195: // get the total difference in frames ! 196: m1 = f1 - f2; ! 197: ! 198: // convert make to MSF ! 199: min = (int)(m1 / (75 * 60)); ! 200: m1 = m1 - min * 75 * 60; ! 201: sec = (int)(m1 / 75); ! 202: frm = m1 - sec * 75; ! 203: return (min << 16) | (sec << 8) | frm; ! 204: } ! 205: ! 206: IOReturn IOCDAudioNubClient::playTrack(UInt32 track,UInt32 *status) ! 207: { ! 208: struct macEntireToc toc; ! 209: UInt32 starting_msf, ending_msf; ! 210: UInt32 starting_track, ending_track; ! 211: ! 212: if (!fOwner) return -2; ! 213: if (track > 101) return -1; ! 214: ! 215: // read the TOC ! 216: fOwner->readEntireTOC(&toc); ! 217: ! 218: // get the starting and ending MSF ! 219: starting_msf = (toc.entries[track].pMin << 16) | ! 220: (toc.entries[track].pSec << 8) | ! 221: (toc.entries[track].pFrame); ! 222: ! 223: ending_msf = (toc.entries[track+1].pMin << 16) | ! 224: (toc.entries[track+1].pSec << 8) | ! 225: (toc.entries[track+1].pFrame); ! 226: ! 227: if (ending_msf == 0) return -3; ! 228: ! 229: // subtrace one frame from the ending MSF ! 230: ending_msf = subMSF(ending_msf,1); ! 231: ! 232: // status returns the time ! 233: *status = subMSF(ending_msf,starting_msf); ! 234: ! 235: // IOLog("IOCDAudioNubClient::playTrack %d %x %x\n", track,starting_msf,ending_msf); ! 236: ! 237: // set the audio stop address ! 238: fOwner->setAudioStopAddress(kAbsoluteTime,(cdAddress)ending_msf); ! 239: ! 240: // send the play command and return immediately ! 241: return fOwner->audioPlay(kAbsoluteTime,(cdAddress)starting_msf,kNormalMode); ! 242: } ! 243: ! 244: IOReturn IOCDAudioNubClient::playMSF( ! 245: UInt32 starting_msf, UInt32 ending_msf, UInt32 *status) ! 246: { ! 247: // status returns the time ! 248: *status = subMSF(ending_msf,starting_msf); ! 249: ! 250: // set the audio stop address ! 251: fOwner->setAudioStopAddress(kAbsoluteTime,(cdAddress)ending_msf); ! 252: ! 253: // send the play command and return immediately ! 254: return fOwner->audioPlay(kAbsoluteTime,(cdAddress)starting_msf,kNormalMode); ! 255: } ! 256: ! 257: IOReturn IOCDAudioNubClient::readHeader(UInt32 address, UInt32 *status) ! 258: { ! 259: struct headerInfo buffer; ! 260: IOReturn ret; ! 261: ! 262: ret = fOwner->readHeader(address,&buffer); ! 263: *status = buffer.address; ! 264: return ret; ! 265: } ! 266: IOReturn IOCDAudioNubClient::getMSF(UInt32 track, UInt32 *status) ! 267: { ! 268: struct macEntireToc toc; ! 269: UInt32 msf; ! 270: ! 271: if (!fOwner) return -2; ! 272: ! 273: // get the TOC ! 274: fOwner->readEntireTOC(&toc); ! 275: ! 276: // get the MSF ! 277: msf = (toc.entries[track].pMin << 16) | ! 278: (toc.entries[track].pSec << 8) | ! 279: (toc.entries[track].pFrame); ! 280: ! 281: // status is the MSF ! 282: *status = msf; ! 283: ! 284: // IOLog("IOCDAudioNubClient::getMSF %d %x\n",track,msf); ! 285: return 0; ! 286: } ! 287: ! 288: IOReturn IOCDAudioNubClient::getNumAudioTracks(UInt32 *status) ! 289: { ! 290: struct macEntireToc toc; ! 291: UInt32 track = 0; ! 292: ! 293: if (!fOwner) return -2; ! 294: ! 295: // get the TOC ! 296: fOwner->readEntireTOC(&toc); ! 297: ! 298: // count the number of tracks ! 299: for(;;) { ! 300: if (!toc.entries[track].trackPoint) break; ! 301: track++; ! 302: } ! 303: if (track) track--; ! 304: ! 305: // status returns the number of tracks ! 306: *status = track; ! 307: ! 308: // IOLog("IOCDAudioNubClient::getNumAudioTracks %d\n",track); ! 309: return 0; ! 310: } ! 311: ! 312: IOReturn IOCDAudioNubClient::pause(UInt32 *status) ! 313: { ! 314: if (!fOwner) return -2; ! 315: *status = 0; ! 316: return fOwner->audioPause(true); ! 317: } ! 318: ! 319: IOReturn IOCDAudioNubClient::resume(UInt32 *status) ! 320: { ! 321: if (!fOwner) return -2; ! 322: *status = 0; ! 323: return fOwner->audioPause(false); ! 324: } ! 325: ! 326: IOReturn IOCDAudioNubClient::getVolume(UInt32 *status) ! 327: { ! 328: UInt8 right, left; ! 329: IOReturn ret; ! 330: ! 331: if (!fOwner) return -2; ! 332: ret = fOwner->readAudioVolume(&left,&right); ! 333: *status = (left << 8 & 0xff00) | (right & 0xff); ! 334: return ret; ! 335: } ! 336: ! 337: IOReturn IOCDAudioNubClient::setVolume(UInt8 left, UInt8 right, UInt32 *status) ! 338: { ! 339: IOReturn ret; ! 340: ! 341: // IOLog("IOCDAudioNubClient::setVolume %d %d\n",left,right); ! 342: ! 343: if (!fOwner) return -2; ! 344: ret = fOwner->setVolume(left,right); ! 345: *status = (left << 8 & 0xff00) | (right & 0xff); ! 346: return ret; ! 347: } ! 348: ! 349: IOReturn IOCDAudioNubClient::getAudioStatus(UInt32 *status, ! 350: UInt32 *absAddress, UInt32 *relAddress, UInt32 *trackType) ! 351: { ! 352: IOReturn ret; ! 353: struct audioStatus stat; ! 354: struct qSubcode buffer; ! 355: bool found; ! 356: UInt8 buf[15]; ! 357: ! 358: ret = fOwner->getAudioStatus(&stat); ! 359: *status = stat.status; ! 360: *trackType = stat.type; ! 361: ! 362: ret = fOwner->readTheQSubcode(&buffer); ! 363: *relAddress = buffer.relAddress; ! 364: *absAddress = buffer.absAddress; ! 365: ! 366: // IOLog("IOCDAudioNubClient::getAudioStatus abs=0x%x rel=0x%x status=%d type=%x\n", *absAddress, *relAddress, *status, *trackType); ! 367: ! 368: return ret; ! 369: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.