|
|
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: #include <IOKit/assert.h>
23: #include <IOKit/IOMessage.h>
24: #include <IOKit/IOLib.h>
25: #include "IOBSDConsole.h"
26: #include <IOKit/hidsystem/IOHIKeyboard.h>
27: #include <IOKit/hidsystem/IOLLEvent.h>
28: #include <IOKit/audio/IOAudio.h>
29:
30: static IOBSDConsole * gBSDConsoleInst = 0;
31: bool displayWranglerPublished( OSObject *, void *, IOService * );
32:
33: #define super IOService
34: OSDefineMetaClassAndStructors(IOBSDConsole, IOService);
35:
36: //************************************************************************
37:
38: bool IOBSDConsole::start(IOService * provider)
39: {
40: OSObject * notify;
41:
42: if (!super::start(provider)) return false;
43:
44: assert( gBSDConsoleInst == 0 );
45: gBSDConsoleInst = this;
46:
47: notify = addNotification( gIOPublishNotification,
48: serviceMatching("IOHIKeyboard"),
49: (IOServiceNotificationHandler) &IOBSDConsole::publishNotificationHandler,
50: this, 0 );
51: assert( notify );
52:
53: notify = addNotification( gIOPublishNotification,
54: serviceMatching("IODisplayWrangler"),
55: (IOServiceNotificationHandler)displayWranglerPublished,
56: this, 0 );
57: assert( notify );
58:
59: notify = addNotification( gIOPublishNotification,
60: serviceMatching("IOAudioStream"),
61: (IOServiceNotificationHandler) &IOBSDConsole::publishNotificationHandler,
62: this, this );
63: assert( notify );
64:
65: return( true );
66: }
67:
68: bool IOBSDConsole::publishNotificationHandler(
69: IOBSDConsole * self,
70: void * ref,
71: IOService * newService )
72:
73: {
74: IOHIKeyboard * keyboard;
75: IOAudioStream * audio;
76:
77: if( ref) {
78: keyboard = 0;
79: audio = OSDynamicCast(IOAudioStream, newService);
80: if(audio) {
81: SInt32 isOut;
82: audio->isOutput(&isOut);
83: if(isOut)
84: self->fAudioOut = audio; // A stream we can write to
85: }
86:
87: } else {
88: audio = 0;
89: keyboard = OSDynamicCast( IOHIKeyboard, newService );
90:
91: if( keyboard && self->attach( keyboard ))
92: self->arbitrateForKeyboard( keyboard );
93: }
94:
95: if( !keyboard && !audio)
96: IOLog("%s: strange service notify \"%s\"\n",
97: self->getName(), newService->getName());
98:
99: return true;
100: }
101:
102: // **********************************************************************************
103: // displayWranglerPublished
104: //
105: // The Display Wrangler has appeared. We will be calling its
106: // ActivityTickle method when there is user activity.
107: // **********************************************************************************
108: bool displayWranglerPublished( OSObject * us, void * ref, IOService * yourDevice )
109: {
110: if ( yourDevice != NULL ) {
111: ((IOBSDConsole *)us)->displayManager = yourDevice;
112: }
113: return true;
114: }
115:
116:
117: //************************************************************************
118: // Keyboard client stuff
119: //************************************************************************
120:
121: void IOBSDConsole::arbitrateForKeyboard( IOHIKeyboard * nub )
122: {
123: nub->open(this, 0,
124: keyboardEvent, keyboardSpecialEvent, updateEventFlags);
125: // failure can be expected if the HID system already has it
126: }
127:
128: IOReturn IOBSDConsole::message(UInt32 type, IOService * provider,
129: void * argument)
130: {
131: IOReturn status = kIOReturnSuccess;
132:
133: switch (type)
134: {
135: case kIOMessageServiceIsTerminated:
136: case kIOMessageServiceIsRequestingClose:
137: provider->close( this );
138: break;
139:
140: case kIOMessageServiceWasClosed:
141: arbitrateForKeyboard( (IOHIKeyboard *) provider );
142: break;
143:
144: default:
145: status = super::message(type, provider, argument);
146: break;
147: }
148:
149: return status;
150: }
151:
152: extern "C" {
153: void cons_cinput( char c);
154: }
155: #warning REMOVE cons_cinput DECLARATION FROM HERE
156:
157: void IOBSDConsole::keyboardEvent(OSObject * target,
158: /* eventType */ unsigned eventType,
159: /* flags */ unsigned /* flags */,
160: /* keyCode */ unsigned /* key */,
161: /* charCode */ unsigned charCode,
162: /* charSet */ unsigned charSet,
163: /* originalCharCode */ unsigned /* origCharCode */,
164: /* originalCharSet */ unsigned /* origCharSet */,
165: /* repeat */ bool /* repeat */,
166: /* atTime */ AbsoluteTime /* ts */)
167: {
168: static const char cursorCodes[] = { 'D', 'A', 'C', 'B' };
169:
170: if ( ((IOBSDConsole *)target)->displayManager != NULL ) { // if there is a display manager,
171: ((IOBSDConsole *)target)->displayManager->activityTickle(kIOPMSuperclassPolicy1); // tell it there is user activity
172: }
173:
174: if( eventType == NX_KEYDOWN) {
175: if( (charSet == NX_SYMBOLSET)
176: && (charCode >= 0xac) && (charCode <= 0xaf)) {
177: cons_cinput( '\033');
178: cons_cinput( 'O');
179: charCode = cursorCodes[ charCode - 0xac ];
180: }
181: cons_cinput( charCode);
182: }
183: }
184:
185: void IOBSDConsole::keyboardSpecialEvent(OSObject * target,
186: /* eventType */ unsigned /* eventType */,
187: /* flags */ unsigned /* flags */,
188: /* keyCode */ unsigned /* key */,
189: /* specialty */ unsigned /* flavor */,
190: /* atTime */ AbsoluteTime /* ts */)
191: {
192: if ( ((IOBSDConsole *)target)->displayManager != NULL ) { // if there is a display manager,
193: ((IOBSDConsole *)target)->displayManager->activityTickle(kIOPMSuperclassPolicy1); // tell it there is user activity
194: }
195: return;
196: }
197: void IOBSDConsole::updateEventFlags(OSObject * /*target*/, unsigned /*flags*/)
198: {
199: return;
200: }
201:
202: //************************************************************************
203: // Utility sound making stuff, callable from C
204: //************************************************************************
205: extern "C" {
206: int asc_ringbell();
207: }
208:
209: /*
210: * Make some sort of noise if possible, else return false
211: */
212: int asc_ringbell()
213: {
214: IOAudioStream *output;
215:
216: if(gBSDConsoleInst && (output = gBSDConsoleInst->getAudioOut())) {
217: int dmaBlockStart, dmaBlockEnd;
218: int i;
219: IOAudioStreamStatus *status;
220: short *sampleBuffer;
221: IOByteCount bufSize;
222: IOUserClient *handler;
223: IOMemoryMap *statusMap;
224: IOMemoryMap *sampleMap;
225: IOReturn ret;
226: int j, div, mul;
227: int size;
228: int val;
229:
230: ret = output->newUserClient( kernel_task, NULL, 0, &handler );
231: if(kIOReturnSuccess != ret)
232: return false;
233:
234: sampleMap = output->mapClientMemory( kSampleBuffer, kernel_task );
235: assert(sampleMap);
236: sampleBuffer = (short *) sampleMap->getVirtualAddress();
237: bufSize = sampleMap->getLength();
238:
239: statusMap = output->mapClientMemory( kStatus, kernel_task );
240: assert(statusMap);
241: status = (IOAudioStreamStatus *) statusMap->getVirtualAddress();
242:
243: assert(status->fSampleSize == 2);
244: // Put 1/10 second of 440Hz sound in the buffer, starting just after the current block.
245: div = status->fDataRate/status->fSampleSize/status->fChannels/440;
246: mul = 0x4000/div;
247: size = status->fDataRate/status->fSampleSize/status->fChannels/10;
248: dmaBlockStart = status->fCurrentBlock * status->fBlockSize;
249: dmaBlockEnd = dmaBlockStart + status->fBlockSize;
250: for(i=dmaBlockEnd/2; i<status->fBufSize/2; i += status->fChannels){
251: if(!--size)
252: break;
253: val = (size) % div;
254: if(val > div/2)
255: val = div/2 - val;
256: val = val*mul - 0x1000;
257: for(j=0; j<status->fChannels; j++) {
258: sampleBuffer[i+j] = val;
259: }
260: }
261: if(size)
262: for(i=0; i<dmaBlockStart/2; i += status->fChannels){
263: if(!--size)
264: break;
265: val = (size) % div;
266: if(val > div/2)
267: val = div/2 - val;
268: val = val*mul - 0x1000;
269: for(j=0; j<status->fChannels; j++) {
270: sampleBuffer[i+j] = val;
271: }
272: }
273:
274: sampleMap->release();
275: statusMap->release();
276: handler->clientClose();
277: return true;
278: }
279: else
280: return false;
281: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.