#include <IOKit/assert.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOLib.h>
#include "IOBSDConsole.h"
#include <IOKit/hidsystem/IOHIKeyboard.h>
#include <IOKit/hidsystem/IOLLEvent.h>
#define super IOService
OSDefineMetaClassAndStructors(IOBSDConsole, IOService);
bool (*playBeep)(IOService *outputStream) = 0;
bool IOBSDConsole::start(IOService * provider)
{
OSObject * notify;
if (!super::start(provider)) return false;
notify = addNotification( gIOPublishNotification,
serviceMatching("IOHIKeyboard"),
(IOServiceNotificationHandler) &IOBSDConsole::publishNotificationHandler,
this, 0 );
assert( notify );
notify = addNotification( gIOPublishNotification,
serviceMatching("IODisplayWrangler"),
(IOServiceNotificationHandler) &IOBSDConsole::publishNotificationHandler,
this, 0 );
assert( notify );
notify = addNotification( gIOPublishNotification,
serviceMatching("IOAudioStream"),
(IOServiceNotificationHandler) &IOBSDConsole::publishNotificationHandler,
this, this );
assert( notify );
return( true );
}
bool IOBSDConsole::publishNotificationHandler(
IOBSDConsole * self,
void * ref,
IOService * newService )
{
IOHIKeyboard * keyboard = 0;
IOService * audio = 0;
if( ref) {
audio = OSDynamicCast(IOService, newService->metaCast("IOAudioStream"));
if (audio != 0) {
OSNumber *out = newService->copyProperty("Out");
if (OSDynamicCast(OSNumber, out)) {
if (out->unsigned8BitValue() == 1) {
self->fAudioOut = newService;
}
}
OSSafeReleaseNULL(out);
}
} else {
audio = 0;
keyboard = OSDynamicCast( IOHIKeyboard, newService );
if( keyboard && self->attach( keyboard )) {
self->arbitrateForKeyboard( keyboard );
}
if( newService->metaCast("IODisplayWrangler"))
self->displayManager = newService;
}
return true;
}
void IOBSDConsole::arbitrateForKeyboard( IOHIKeyboard * nub )
{
nub->open(this, 0, 0,
(KeyboardEventCallback)keyboardEvent,
(KeyboardSpecialEventCallback) 0,
(UpdateEventFlagsCallback)updateEventFlags);
}
IOReturn IOBSDConsole::message(UInt32 type, IOService * provider,
void * argument)
{
IOReturn status = kIOReturnSuccess;
switch (type)
{
case kIOMessageServiceIsTerminated:
case kIOMessageServiceIsRequestingClose:
provider->close( this );
break;
case kIOMessageServiceWasClosed:
arbitrateForKeyboard( (IOHIKeyboard *) provider );
break;
default:
status = super::message(type, provider, argument);
break;
}
return status;
}
extern "C" {
void cons_cinput( char c);
}
void IOBSDConsole::keyboardEvent(OSObject * target,
unsigned eventType,
unsigned flags,
unsigned ,
unsigned charCode,
unsigned charSet,
unsigned ,
unsigned ,
unsigned ,
bool ,
AbsoluteTime ,
OSObject * sender,
void * refcon)
{
static const char cursorCodes[] = { 'D', 'A', 'C', 'B' };
if ( ((IOBSDConsole *)target)->displayManager != NULL ) {
((IOBSDConsole *)target)->displayManager->activityTickle(kIOPMSuperclassPolicy1);
}
if( (eventType == NX_KEYDOWN) && ((flags & NX_ALTERNATEMASK) != NX_ALTERNATEMASK)) {
if( (charSet == NX_SYMBOLSET)
&& (charCode >= 0xac) && (charCode <= 0xaf)) {
cons_cinput( '\033');
cons_cinput( 'O');
charCode = cursorCodes[ charCode - 0xac ];
}
cons_cinput( charCode);
}
}
void IOBSDConsole::updateEventFlags(OSObject * ,
unsigned ,
OSObject * ,
void * )
{
return;
}