|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: * audio_kern_server.m
26: *
27: * Copyright (c) 1993, NeXT Computer, Inc. All rights reserved.
28: *
29: */
30:
31: #import <mach/mach_types.h>
32: #import <kern/lock.h>
33: #import <kernserv/kern_server_types.h>
34: #import <kernserv/prototypes.h>
35: #import <kernserv/kern_server_reply.h>
36: #import <driverkit/kernelDriver.h>
37: #import <driverkit/generalFuncs.h>
38: #import "audio_server.h"
39: #import "snd_server.h"
40: #import "audio_kern_server.h"
41:
42: /*
43: * definitions for audioMessages
44: */
45: #define SERVER_SEND_OPTIONS SEND_TIMEOUT
46: #define SERVER_SEND_TIMEOUT 1000
47:
48: /*
49: * for IOAudio instance
50: */
51: #import <driverkit/IOAudioPrivate.h>
52:
53: /*
54: * imported for handleControl
55: */
56: #import <audio/audio_msgs.h>
57: #import "portFuncs.h"
58:
59: /*
60: * imported for snd_server
61: */
62: #import <bsd/dev/snd_msgs.h>
63: #import "snd_reply.h"
64:
65: #import <mach/mig_errors.h> // death_pill_t
66:
67: /*
68: * declaration for createAudioPorts()
69: */
70: void audioMessages(msg_header_t *in_msg, msg_header_t *out_msg);
71:
72: /*
73: * these are initialized at load time but not used until after
74: * the device is probed.
75: */
76: port_t outPort = PORT_NULL, inPort = PORT_NULL, sndPort = PORT_NULL;
77:
78: static kern_server_t *instance; /* kernserv instance */
79:
80: /*
81: * Allocate user message listen ports.
82: */
83: static void createAudioPorts()
84: {
85: kern_return_t krtn;
86:
87: /*
88: * Kern_server passes the last argument of kern_serv_port_serv()
89: * as the first argument to the MIG-generated interface
90: * functions (in audio_server.m). In this case, it is the
91: * port the message was received on.
92: */
93:
94: outPort = allocatePort();
95: krtn = kern_serv_port_serv(instance, outPort,
96: (port_map_proc_t) audioMessages, outPort);
97: if (krtn != KERN_SUCCESS)
98: IOLog("Audio: createAudioPorts error %d\n", krtn);
99:
100: inPort = allocatePort();
101: krtn = kern_serv_port_serv(instance, inPort,
102: (port_map_proc_t) audioMessages, inPort);
103: if (krtn != KERN_SUCCESS)
104: IOLog("Audio: createAudioPorts error %d\n", krtn);
105:
106: sndPort = allocatePort();
107: krtn = kern_serv_port_serv(instance, sndPort,
108: (port_map_proc_t) audioMessages, sndPort);
109: if (krtn != KERN_SUCCESS)
110: IOLog("Audio: createAudioPorts error %d\n", krtn);
111: }
112:
113: /*
114: * Called when an audio driver instance is initialized.
115: */
116: void audioKernServInit(kern_server_t *instance_var)
117: {
118: #ifdef DEBUG
119: IOLog("Audio server loaded, inst=0x%x\n", (unsigned int)instance_var);
120: #endif DEBUG
121:
122: instance = instance_var;
123: }
124:
125:
126: /*
127: * Register stream port - exported for Audio.
128: */
129: boolean_t audio_enroll_stream_port(port_t stream_port, boolean_t enroll)
130: {
131: kern_return_t krtn;
132:
133: if (enroll) {
134: krtn = kern_serv_port_serv(instance, stream_port,
135: (port_map_proc_t) audioMessages, stream_port);
136: if (krtn != KERN_SUCCESS)
137: IOLog("Audio: kern_serv_port_serv returns %d\n", krtn);
138: } else {
139: kern_serv_port_gone(instance, stream_port);
140: krtn = KERN_SUCCESS;
141: }
142:
143: return (krtn == KERN_SUCCESS ? TRUE : FALSE);
144: }
145:
146: /*
147: * Realloc just the snd device port - exported for snd_server.m.
148: */
149: port_t audio_reset_snd_dev_port(IOAudio *dev, port_t priv_port)
150: {
151: port_t kern_port, sndPort;
152:
153: if ((kern_port = IOHostPrivSelf()) == PORT_NULL) {
154: IOLog("Audio: cannot get kernel port (must run as root)\n");
155: IOLog("reset_snd_dev_port");
156: }
157: if (priv_port != kern_port)
158: return PORT_NULL;
159:
160: /* snd input and output share the same user port */
161: deallocatePort([[dev _outputChannel] userSndPort]);
162: sndPort = allocatePort();
163: [[dev _inputChannel] setUserSndPort:sndPort];
164: [[dev _outputChannel] setUserSndPort:sndPort];
165:
166: return sndPort;
167: }
168:
169: /*
170: * Handle privileged control message.
171: */
172: static boolean_t handleControl(msg_header_t *in_msg,
173: msg_header_t *out_msg)
174: {
175: audio_get_ports_t *get_ports = (audio_get_ports_t *)in_msg;
176: audio_ret_ports_t *ret_ports = (audio_ret_ports_t *)out_msg;
177: port_t kern_port;
178:
179: IOAudio *dev = [IOAudio _instance];
180: static boolean_t initialized = FALSE;
181:
182: /*
183: * Standard reply header.
184: */
185: out_msg->msg_simple = TRUE;
186: out_msg->msg_size = sizeof(msg_header_t);
187: out_msg->msg_type = MSG_TYPE_NORMAL;
188: out_msg->msg_local_port = PORT_NULL;
189: out_msg->msg_remote_port = in_msg->msg_remote_port;
190: out_msg->msg_id = 0;
191:
192: if (in_msg->msg_id != AUDIO_MSG_GET_PORTS)
193: return FALSE;
194:
195: /*
196: * If the IOAudio instance fails to load, the control ports are
197: * never returned. The kernel server instance variable is guaranteed to
198: * be set when an audio device is successfully instantiated.
199: */
200: if (dev == nil)
201: return TRUE;
202:
203: if (! initialized) {
204: kern_serv_port_death_proc(instance,
205: (port_death_proc_t)audio_port_gone);
206: createAudioPorts();
207: initialized = TRUE;
208: }
209:
210: out_msg->msg_simple = FALSE;
211: out_msg->msg_size = sizeof(audio_ret_ports_t);
212: out_msg->msg_id = AUDIO_MSG_RET_PORTS;
213: ret_ports->portsType.msg_type_name = MSG_TYPE_PORT;
214: ret_ports->portsType.msg_type_size = 32;
215: ret_ports->portsType.msg_type_number = 3;
216: ret_ports->portsType.msg_type_inline = TRUE;
217: ret_ports->portsType.msg_type_longform = FALSE;
218: ret_ports->portsType.msg_type_deallocate = FALSE;
219: ret_ports->portsType.msg_type_unused = 0;
220:
221: if ((kern_port = IOHostPrivSelf()) == PORT_NULL) {
222: IOLog("Audio: cannot get kernel port (must run as root)\n");
223: return TRUE;
224: }
225:
226: if (get_ports->priv != kern_port) {
227:
228: #ifdef DEBUG
229: IOLog("handleControl: returning NULL ports\n");
230: #endif DEBUG
231:
232: ret_ports->inputPort = PORT_NULL;
233: ret_ports->outputPort = PORT_NULL;
234: ret_ports->sndPort = PORT_NULL;
235: } else {
236: if (get_ports->reset) {
237:
238: #ifdef DEBUG
239: IOLog("handleControl: resetting ports\n");
240: #endif DEBUG
241:
242: if (inPort != PORT_NULL) {
243: kern_serv_port_gone(instance, inPort);
244: deallocatePort(inPort);
245: }
246: if (outPort != PORT_NULL) {
247: kern_serv_port_gone(instance, outPort);
248: deallocatePort(outPort);
249: }
250: /* snd input and output share the same user port */
251: if (sndPort != PORT_NULL) {
252: kern_serv_port_gone(instance, sndPort);
253: deallocatePort(sndPort);
254: }
255: createAudioPorts();
256: }
257:
258: ret_ports->inputPort = inPort;
259: ret_ports->outputPort = outPort;
260: ret_ports->sndPort = sndPort;
261:
262: #ifdef DEBUG
263: IOLog("handleControl: returning ports %d %d %d\n",
264: ret_ports->inputPort, ret_ports->outputPort,
265: ret_ports->sndPort);
266: #endif DEBUG
267: }
268:
269: [[dev _outputChannel] setUserChannelPort:outPort];
270: [[dev _outputChannel] setUserSndPort:sndPort];
271: [[dev _inputChannel] setUserChannelPort:inPort];
272: [[dev _inputChannel] setUserSndPort:sndPort];
273:
274: return TRUE;
275: }
276:
277: /*
278: * Called when messages arrive on registered ports
279: */
280: void audioMessages(msg_header_t *in_msg, msg_header_t *out_msg)
281: {
282: kern_return_t krtn;
283:
284: #ifdef DEBUG
285: // IOLog("Audio: message received id: %d\n", in_msg->msg_id);
286: #endif DEBUG
287:
288: if (in_msg->msg_local_port == 0) {
289: if (! (handleControl(in_msg, out_msg)))
290: IOLog("Audio: unrecognized control message %d\n",
291: in_msg->msg_id);
292: } else if (in_msg->msg_id < AUDIO_USER_MSG_BASE) {
293: /*
294: * Handle old style SoundDSP driver message.
295: */
296: if (!snd_server(in_msg, out_msg))
297: IOLog("Audio: unrecognized snd user message %d\n",
298: in_msg->msg_id);
299: } else {
300: /*
301: * Handle new style NXSoundDevice message.
302: */
303: if (!audio_server(in_msg, out_msg))
304: IOLog("Audio: unrecognized audio user message %d\n",
305: in_msg->msg_id);
306: }
307: /*
308: * Send a reply message, even if error.
309: */
310: krtn = msg_send(out_msg, SERVER_SEND_OPTIONS, SERVER_SEND_TIMEOUT);
311: if (krtn != KERN_SUCCESS) {
312: IOLog("msg_send failed %d\n", krtn);
313: }
314:
315: /*
316: * Under normal circumstances, kernserv sends the reply message. In this
317: * case, both the control and snd interfaces are not generated by MiG. We
318: * must send the response and then set MIG_NO_REPLY to prevent kernserv
319: * from sending a response on our behalf.
320: */
321: ((death_pill_t *)out_msg)->RetCode = MIG_NO_REPLY;
322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.