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