|
|
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.