ApplePS2Keyboard.cpp [plain text]
#include <IOKit/assert.h>
#include <IOKit/IOLib.h>
#include <IOKit/hidsystem/IOHIDTypes.h>
#include <IOKit/hidsystem/IOLLEvent.h>
#include "ApplePS2Keyboard.h"
#include "ApplePS2ToADBMap.h"
#define super IOHIKeyboard
OSDefineMetaClassAndStructors(ApplePS2Keyboard, IOHIKeyboard);
UInt32 ApplePS2Keyboard::deviceType() { return NX_EVS_DEVICE_TYPE_KEYBOARD; };
UInt32 ApplePS2Keyboard::interfaceID() { return NX_EVS_DEVICE_INTERFACE_ADB; };
UInt32 ApplePS2Keyboard::maxKeyCodes() { return KBV_NUM_KEYCODES; };
bool ApplePS2Keyboard::init(OSDictionary * properties)
{
if (!super::init(properties)) return false;
_device = 0;
_extendCount = 0;
_interruptHandlerInstalled = false;
_ledState = 0;
for (int index = 0; index < KBV_NUNITS; index++) _keyBitVector[index] = 0;
return true;
}
ApplePS2Keyboard * ApplePS2Keyboard::probe(IOService * provider, SInt32 * score)
{
ApplePS2KeyboardDevice * device = (ApplePS2KeyboardDevice *)provider;
PS2Request * request = device->allocateRequest();
bool success;
if (!super::probe(provider, score)) return 0;
request->commands[0].command = kPS2C_WriteDataPort;
request->commands[0].inOrOut = kDP_TestKeyboardEcho;
request->commands[1].command = kPS2C_ReadDataPortAndCompare;
request->commands[1].inOrOut = 0xEE;
request->commandsCount = 2;
device->submitRequestAndBlock(request);
success = (request->commandsCount == 2);
device->freeRequest(request);
return (success) ? this : 0;
}
bool ApplePS2Keyboard::start(IOService * provider)
{
if (!super::start(provider)) return false;
_device = (ApplePS2KeyboardDevice *)provider;
_device->retain();
_device->installInterruptAction(this,
(PS2InterruptAction)&ApplePS2Keyboard::interruptOccurred);
_interruptHandlerInstalled = true;
setLEDs(_ledState);
setCommandByte(kCB_EnableKeyboardIRQ | kCB_TranslateMode,
kCB_DisableKeyboardClock);
setKeyboardEnable(true);
return true;
}
void ApplePS2Keyboard::stop(IOService * provider)
{
assert(_device == provider);
setKeyboardEnable(false);
setCommandByte(kCB_DisableKeyboardClock, kCB_EnableKeyboardIRQ);
if ( _interruptHandlerInstalled ) _device->uninstallInterruptAction();
_interruptHandlerInstalled = false;
_device->release();
_device = 0;
super::stop(provider);
}
void ApplePS2Keyboard::interruptOccurred(UInt8 scanCode) {
if (scanCode == kSC_Acknowledge)
IOLog("%s: Unexpected acknowledge from PS/2 controller.\n", getName());
else if (scanCode == kSC_Resend)
IOLog("%s: Unexpected resend request from PS/2 controller.\n", getName());
else
dispatchKeyboardEventWithScancode(scanCode);
}
bool ApplePS2Keyboard::dispatchKeyboardEventWithScancode(UInt8 scanCode)
{
unsigned int keyCode;
bool goingDown;
AbsoluteTime now;
if (scanCode == kSC_Extend)
{
_extendCount = 1;
return false;
}
if (scanCode == kSC_Pause)
{
_extendCount = 2;
return false;
}
if (_extendCount == 0)
keyCode = scanCode & ~kSC_UpBit;
else
{
_extendCount--;
if (_extendCount) return false;
switch (scanCode & ~kSC_UpBit)
{
case 0x1D: keyCode = 0x60; break; case 0x38: keyCode = 0x61; break; case 0x1C: keyCode = 0x62; break; case 0x35: keyCode = 0x63; break; case 0x48: keyCode = 0x64; break; case 0x50: keyCode = 0x65; break; case 0x4B: keyCode = 0x66; break; case 0x4D: keyCode = 0x67; break; case 0x52: keyCode = 0x68; break; case 0x53: keyCode = 0x69; break; case 0x49: keyCode = 0x6A; break; case 0x51: keyCode = 0x6B; break; case 0x47: keyCode = 0x6C; break; case 0x4F: keyCode = 0x6D; break; case 0x37: keyCode = 0x6E; break; case 0x45: keyCode = 0x6F; break; case 0x5B: keyCode = 0x70; break; case 0x5C: keyCode = 0x71; break; case 0x5D: keyCode = 0x72; break; case 0x2A: default: return false;
}
}
if (keyCode == 0) return false;
goingDown = !(scanCode & kSC_UpBit);
if (goingDown)
{
if (KBV_IS_KEYDOWN(keyCode, _keyBitVector)) return false;
KBV_KEYDOWN(keyCode, _keyBitVector);
}
else
{
KBV_KEYUP(keyCode, _keyBitVector);
}
clock_get_uptime(&now);
dispatchKeyboardEvent( PS2ToADBMap[keyCode],
goingDown,
now );
return true;
}
void ApplePS2Keyboard::setAlphaLockFeedback(bool locked)
{
_ledState = locked ? (_ledState | kLED_CapsLock):(_ledState & ~kLED_CapsLock);
setLEDs(_ledState);
}
void ApplePS2Keyboard::setNumLockFeedback(bool locked)
{
_ledState = locked ? (_ledState | kLED_NumLock):(_ledState & ~kLED_NumLock);
setLEDs(_ledState);
}
void ApplePS2Keyboard::setLEDs(UInt8 ledState)
{
PS2Request * request = _device->allocateRequest();
request->commands[0].command = kPS2C_WriteDataPort;
request->commands[0].inOrOut = kDP_SetKeyboardLEDs;
request->commands[1].command = kPS2C_ReadDataPortAndCompare;
request->commands[1].inOrOut = kSC_Acknowledge;
request->commands[2].command = kPS2C_WriteDataPort;
request->commands[2].inOrOut = ledState;
request->commands[3].command = kPS2C_ReadDataPortAndCompare;
request->commands[3].inOrOut = kSC_Acknowledge;
request->commandsCount = 4;
_device->submitRequest(request); }
void ApplePS2Keyboard::setKeyboardEnable(bool enable)
{
PS2Request * request = _device->allocateRequest();
request->commands[0].command = kPS2C_WriteDataPort;
request->commands[0].inOrOut = (enable)?kDP_Enable:kDP_SetDefaultsAndDisable;
request->commands[1].command = kPS2C_ReadDataPortAndCompare;
request->commands[1].inOrOut = kSC_Acknowledge;
request->commandsCount = 2;
_device->submitRequest(request); }
void ApplePS2Keyboard::setCommandByte(UInt8 setBits, UInt8 clearBits)
{
UInt8 commandByte;
UInt8 commandByteNew;
PS2Request * request = _device->allocateRequest();
do
{
request->commands[0].command = kPS2C_WriteCommandPort;
request->commands[0].inOrOut = kCP_GetCommandByte;
request->commands[1].command = kPS2C_ReadDataPort;
request->commands[1].inOrOut = 0;
request->commandsCount = 2;
_device->submitRequestAndBlock(request);
commandByte = request->commands[1].inOrOut;
commandByteNew = (commandByte | setBits) & (~clearBits);
request->commands[0].command = kPS2C_WriteCommandPort;
request->commands[0].inOrOut = kCP_GetCommandByte;
request->commands[1].command = kPS2C_ReadDataPortAndCompare;
request->commands[1].inOrOut = commandByte;
request->commands[2].command = kPS2C_WriteCommandPort;
request->commands[2].inOrOut = kCP_SetCommandByte;
request->commands[3].command = kPS2C_WriteDataPort;
request->commands[3].inOrOut = commandByteNew;
request->commandsCount = 4;
_device->submitRequestAndBlock(request);
} while (request->commandsCount != 4);
_device->freeRequest(request);
}
const unsigned char * ApplePS2Keyboard::defaultKeymapOfLength(UInt32 * length)
{
static const unsigned char appleUSAKeyMap[] =
{
0x00,0x00,
0x06, 0x01,0x01,0x38,
0x02,0x01,0x3b,0x03,0x01,0x3a,0x04,
0x01,0x37,0x05,0x15,0x52,0x41,0x4c,0x53,0x54,0x55,0x45,0x58,0x57,0x56,0x5b,0x5c,
0x43,0x4b,0x51,0x7b,0x7d,0x7e,0x7c,0x4e,0x59,0x06,0x01,0x72,0x7f,0x0d,0x00,0x61,
0x00,0x41,0x00,0x01,0x00,0x01,0x00,0xca,0x00,0xc7,0x00,0x01,0x00,0x01,0x0d,0x00,
0x73,0x00,0x53,0x00,0x13,0x00,0x13,0x00,0xfb,0x00,0xa7,0x00,0x13,0x00,0x13,0x0d,
0x00,0x64,0x00,0x44,0x00,0x04,0x00,0x04,0x01,0x44,0x01,0xb6,0x00,0x04,0x00,0x04,
0x0d,0x00,0x66,0x00,0x46,0x00,0x06,0x00,0x06,0x00,0xa6,0x01,0xac,0x00,0x06,0x00,
0x06,0x0d,0x00,0x68,0x00,0x48,0x00,0x08,0x00,0x08,0x00,0xe3,0x00,0xeb,0x00,0x00,
0x18,0x00,0x0d,0x00,0x67,0x00,0x47,0x00,0x07,0x00,0x07,0x00,0xf1,0x00,0xe1,0x00,
0x07,0x00,0x07,0x0d,0x00,0x7a,0x00,0x5a,0x00,0x1a,0x00,0x1a,0x00,0xcf,0x01,0x57,
0x00,0x1a,0x00,0x1a,0x0d,0x00,0x78,0x00,0x58,0x00,0x18,0x00,0x18,0x01,0xb4,0x01,
0xce,0x00,0x18,0x00,0x18,0x0d,0x00,0x63,0x00,0x43,0x00,0x03,0x00,0x03,0x01,0xe3,
0x01,0xd3,0x00,0x03,0x00,0x03,0x0d,0x00,0x76,0x00,0x56,0x00,0x16,0x00,0x16,0x01,
0xd6,0x01,0xe0,0x00,0x16,0x00,0x16,0x02,0x00,0x3c,0x00,0x3e,0x0d,0x00,0x62,0x00,
0x42,0x00,0x02,0x00,0x02,0x01,0xe5,0x01,0xf2,0x00,0x02,0x00,0x02,0x0d,0x00,0x71,
0x00,0x51,0x00,0x11,0x00,0x11,0x00,0xfa,0x00,0xea,0x00,0x11,0x00,0x11,0x0d,0x00,
0x77,0x00,0x57,0x00,0x17,0x00,0x17,0x01,0xc8,0x01,0xc7,0x00,0x17,0x00,0x17,0x0d,
0x00,0x65,0x00,0x45,0x00,0x05,0x00,0x05,0x00,0xc2,0x00,0xc5,0x00,0x05,0x00,0x05,
0x0d,0x00,0x72,0x00,0x52,0x00,0x12,0x00,0x12,0x01,0xe2,0x01,0xd2,0x00,0x12,0x00,
0x12,0x0d,0x00,0x79,0x00,0x59,0x00,0x19,0x00,0x19,0x00,0xa5,0x01,0xdb,0x00,0x19,
0x00,0x19,0x0d,0x00,0x74,0x00,0x54,0x00,0x14,0x00,0x14,0x01,0xe4,0x01,0xd4,0x00,
0x14,0x00,0x14,0x0a,0x00,0x31,0x00,0x21,0x01,0xad,0x00,0xa1,0x0e,0x00,0x32,0x00,
0x40,0x00,0x32,0x00,0x00,0x00,0xb2,0x00,0xb3,0x00,0x00,0x00,0x00,0x0a,0x00,0x33,
0x00,0x23,0x00,0xa3,0x01,0xba,0x0a,0x00,0x34,0x00,0x24,0x00,0xa2,0x00,0xa8,0x0e,
0x00,0x36,0x00,0x5e,0x00,0x36,0x00,0x1e,0x00,0xb6,0x00,0xc3,0x00,0x1e,0x00,0x1e,
0x0a,0x00,0x35,0x00,0x25,0x01,0xa5,0x00,0xbd,0x0a,0x00,0x3d,0x00,0x2b,0x01,0xb9,
0x01,0xb1,0x0a,0x00,0x39,0x00,0x28,0x00,0xac,0x00,0xab,0x0a,0x00,0x37,0x00,0x26,
0x01,0xb0,0x01,0xab,0x0e,0x00,0x2d,0x00,0x5f,0x00,0x1f,0x00,0x1f,0x00,0xb1,0x00,
0xd0,0x00,0x1f,0x00,0x1f,0x0a,0x00,0x38,0x00,0x2a,0x00,0xb7,0x00,0xb4,0x0a,0x00,
0x30,0x00,0x29,0x00,0xad,0x00,0xbb,0x0e,0x00,0x5d,0x00,0x7d,0x00,0x1d,0x00,0x1d,
0x00,0x27,0x00,0xba,0x00,0x1d,0x00,0x1d,0x0d,0x00,0x6f,0x00,0x4f,0x00,0x0f,0x00,
0x0f,0x00,0xf9,0x00,0xe9,0x00,0x0f,0x00,0x0f,0x0d,0x00,0x75,0x00,0x55,0x00,0x15,
0x00,0x15,0x00,0xc8,0x00,0xcd,0x00,0x15,0x00,0x15,0x0e,0x00,0x5b,0x00,0x7b,0x00,
0x1b,0x00,0x1b,0x00,0x60,0x00,0xaa,0x00,0x1b,0x00,0x1b,0x0d,0x00,0x69,0x00,0x49,
0x00,0x09,0x00,0x09,0x00,0xc1,0x00,0xf5,0x00,0x09,0x00,0x09,0x0d,0x00,0x70,0x00,
0x50,0x00,0x10,0x00,0x10,0x01,0x70,0x01,0x50,0x00,0x10,0x00,0x10,0x10,0x00,0x0d,
0x00,0x03,0x0d,0x00,0x6c,0x00,0x4c,0x00,0x0c,0x00,0x0c,0x00,0xf8,0x00,0xe8,0x00,
0x0c,0x00,0x0c,0x0d,0x00,0x6a,0x00,0x4a,0x00,0x0a,0x00,0x0a,0x00,0xc6,0x00,0xae,
0x00,0x0a,0x00,0x0a,0x0a,0x00,0x27,0x00,0x22,0x00,0xa9,0x01,0xae,0x0d,0x00,0x6b,
0x00,0x4b,0x00,0x0b,0x00,0x0b,0x00,0xce,0x00,0xaf,0x00,0x0b,0x00,0x0b,0x0a,0x00,
0x3b,0x00,0x3a,0x01,0xb2,0x01,0xa2,0x0e,0x00,0x5c,0x00,0x7c,0x00,0x1c,0x00,0x1c,
0x00,0xe3,0x00,0xeb,0x00,0x1c,0x00,0x1c,0x0a,0x00,0x2c,0x00,0x3c,0x00,0xcb,0x01,
0xa3,0x0a,0x00,0x2f,0x00,0x3f,0x01,0xb8,0x00,0xbf,0x0d,0x00,0x6e,0x00,0x4e,0x00,
0x0e,0x00,0x0e,0x00,0xc4,0x01,0xaf,0x00,0x0e,0x00,0x0e,0x0d,0x00,0x6d,0x00,0x4d,
0x00,0x0d,0x00,0x0d,0x01,0x6d,0x01,0xd8,0x00,0x0d,0x00,0x0d,0x0a,0x00,0x2e,0x00,
0x3e,0x00,0xbc,0x01,0xb3,0x02,0x00,0x09,0x00,0x19,0x0c,0x00,0x20,0x00,0x00,0x00,
0x80,0x00,0x00,0x0a,0x00,0x60,0x00,0x7e,0x00,0x60,0x01,0xbb,0x02,0x00,0x7f,0x00,
0x08,0xff,0x02,0x00,0x1b,0x00,0x7e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0x00,0x00,0x2e,0xff,0x00,0x00,
0x2a,0xff,0x00,0x00,0x2b,0xff,0x00,0x00,0x1b,0xff,0xff,0xff,0x0e,0x00,0x2f,0x00,
0x5c,0x00,0x2f,0x00,0x1c,0x00,0x2f,0x00,0x5c,0x00,0x00,0x0a,0x00,0x00,0x00,0x0d, 0xff,0x00,0x00,0x2d,0xff,0xff,0x0e,0x00,0x3d,0x00,0x7c,0x00,0x3d,0x00,0x1c,0x00,
0x3d,0x00,0x7c,0x00,0x00,0x18,0x46,0x00,0x00,0x30,0x00,0x00,0x31,0x00,0x00,0x32,
0x00,0x00,0x33,0x00,0x00,0x34,0x00,0x00,0x35,0x00,0x00,0x36,0x00,0x00,0x37,0xff,
0x00,0x00,0x38,0x00,0x00,0x39,0xff,0xff,0xff,0x00,0xfe,0x24,0x00,0xfe,0x25,0x00,
0xfe,0x26,0x00,0xfe,0x22,0x00,0xfe,0x27,0x00,0xfe,0x28,0xff,0x00,0xfe,0x2a,0xff,
0x00,0xfe,0x32,0xff,0x00,0xfe,0x33,0xff,0x00,0xfe,0x29,0xff,0x00,0xfe,0x2b,0xff,
0x00,0xfe,0x34,0xff,0x00,0xfe,0x2e,0x00,0xfe,0x30,0x00,0xfe,0x2d,0x00,0xfe,0x23,
0x00,0xfe,0x2f,0x00,0xfe,0x21,0x00,0xfe,0x31,0x00,0xfe,0x20,
0x00,0x01,0xac, 0x00,0x01,0xae, 0x00,0x01,0xaf, 0x00,0x01,0xad, 0x0f,0x02,0xff,0x04,
0x00,0x31,0x02,0xff,0x04,0x00,0x32,0x02,0xff,0x04,0x00,0x33,0x02,0xff,0x04,0x00,
0x34,0x02,0xff,0x04,0x00,0x35,0x02,0xff,0x04,0x00,0x36,0x02,0xff,0x04,0x00,0x37,
0x02,0xff,0x04,0x00,0x38,0x02,0xff,0x04,0x00,0x39,0x02,0xff,0x04,0x00,0x30,0x02,
0xff,0x04,0x00,0x2d,0x02,0xff,0x04,0x00,0x3d,0x02,0xff,0x04,0x00,0x70,0x02,0xff,
0x04,0x00,0x5d,0x02,0xff,0x04,0x00,0x5b,
0x07, 0x04,0x39, 0x05,0x72, 0x06,0x7f, 0x07,0x4a, 0x08,0x7e, 0x09,0x7d, 0x0a,0x47 };
*length = sizeof(appleUSAKeyMap);
return appleUSAKeyMap;
}