AppleUSBKeyboard.cpp [plain text]
#include <libkern/OSByteOrder.h>
extern "C" {
#include <pexpert/pexpert.h>
}
#include <IOKit/hidsystem/IOHIPointing.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include <IOKit/IOMessage.h>
#include <IOKit/usb/IOUSBInterface.h>
#include <IOKit/usb/IOUSBPipe.h>
#include <IOKit/usb/IOUSBController.h>
#include <IOKit/usb/IOUSBLog.h>
#include "AppleUSBKeyboard.h"
#define super IOHIKeyboard
#define self this
OSDefineMetaClassAndStructors(AppleUSBKeyboard, IOHIKeyboard)
extern unsigned char def_usb_2_adb_keymap[];
bool
AppleUSBKeyboard::init(OSDictionary *properties)
{
if (!super::init(properties)) return false;
_prevent_LED_set = false;
_ledState = 0;
_deviceIsDead = false;
_deviceHasBeenDisconnected = false;
_retryCount = kKeyboardRetryCount;
prev_bytes_read=8;
oldmodifier = 0;
_outstandingIO = 0;
_needToClose = false;
bzero( old_array, kUSB_LOWSPEED_MAXPACKET);
bcopy(def_usb_2_adb_keymap, usb_2_adb_keymap, ADB_CONVERTER_LEN);
return true;
}
bool
AppleUSBKeyboard::start(IOService * provider)
{
IOReturn err = 0;
UInt16 productID;
OSNumber *xml_swap_CTRL_CAPSLOCK;
IOWorkLoop *wl;
USBLog(3, "%s[%p]::start - beginning - retain count = %d", getName(), this, getRetainCount());
IncrementOutstandingIO();
_interface = OSDynamicCast(IOUSBInterface, provider);
if (!_interface)
{
USBError(1, "%s[%p]::start - Provider is not an IOUSBInterface! - something must be wrong", getName(), this);
goto ErrorExit;
}
_device = _interface->GetDevice();
if (!_device)
{
USBError(1, "%s[%p]::start - unable to get handle to my device - something must be wrong", getName(), this);
goto ErrorExit;
}
if( !_interface->open(this))
{
USBError(1, "%s[%p]::start - unable to open provider. returning false", getName(), this);
goto ErrorExit;
}
if (_device->GetVendorID() == kIOUSBVendorIDAppleComputer)
{
productID = _device->GetProductID();
if ((productID == kprodUSBAndyISOKbd) || (productID == kprodUSBCosmoISOKbd))
{
usb_2_adb_keymap[0x35] = 0x0a; usb_2_adb_keymap[0x64] = 0x32;
}
Set_Idle_Millisecs(0);
}
else
{
Set_Idle_Millisecs(24);
}
xml_swap_CTRL_CAPSLOCK = OSDynamicCast( OSNumber, getProperty("Swap control and capslock"));
if (xml_swap_CTRL_CAPSLOCK)
{
if ( xml_swap_CTRL_CAPSLOCK->unsigned32BitValue())
{
char temp;
temp = usb_2_adb_keymap[0x39]; usb_2_adb_keymap[0x39] = usb_2_adb_keymap[0xe0]; usb_2_adb_keymap[0xe0] = temp;
}
}
do {
_gate = IOCommandGate::commandGate(this);
if(!_gate)
{
USBError(1, "%s[%p]::start - unable to create command gate", getName(), this);
break;
}
wl = getWorkLoop();
if (!wl)
{
USBError(1, "%s[%p]::start - unable to find my workloop", getName(), this);
break;
}
if (wl->addEventSource(_gate) != kIOReturnSuccess)
{
USBError(1, "%s[%p]::start - unable to add gate to work loop", getName(), this);
break;
}
IOUSBFindEndpointRequest request;
request.type = kUSBInterrupt;
request.direction = kUSBIn;
_interruptPipe = _interface->FindNextPipe(NULL, &request);
if(!_interruptPipe)
{
USBError(1, "%s[%p]::start - unable to get interrupt pipe", getName(), this);
break;
}
_maxPacketSize = request.maxPacketSize;
_buffer = IOBufferMemoryDescriptor::withCapacity(_maxPacketSize, kIODirectionIn);
if ( !_buffer )
{
USBError(1, "%s[%p]::start - unable to create buffer", getName(), this);
break;
}
_completion.target = (void *)self;
_completion.action = (IOUSBCompletionAction) &AppleUSBKeyboard::InterruptReadHandlerEntry;
_completion.parameter = (void *)0; IncrementOutstandingIO();
USBLog(3, "%s[%p]::start - issuing initial read", getName(), this);
_buffer->setLength(_maxPacketSize);
if ((err = _interruptPipe->Read(_buffer, &_completion)))
{
DecrementOutstandingIO();
USBError(1, "%s[%p]::start - err (%x) in interrupt read, retain count %d after release", getName(), this, err, getRetainCount());
break;
}
_deviceDeadCheckThread = thread_call_allocate((thread_call_func_t)CheckForDeadDeviceEntry, (thread_call_param_t)this);
_clearFeatureEndpointHaltThread = thread_call_allocate((thread_call_func_t)ClearFeatureEndpointHaltEntry, (thread_call_param_t)this);
_asyncLEDThread = thread_call_allocate((thread_call_func_t)AsyncLED, (thread_call_param_t)this);
if ( !_deviceDeadCheckThread || !_clearFeatureEndpointHaltThread || !_asyncLEDThread)
{
USBLog(3, "[%s]%p: could not allocate all thread functions", getName(), this);
break;
}
USBError(1, "%s[%p]::start USB Generic Keyboard @ %d (0x%x)", getName(), this, _interface->GetDevice()->GetAddress(), strtol(_interface->GetDevice()->getLocation(), (char **)NULL, 16));
if( !super::start(_interface))
{
USBError(1, "%s[%p]::start - unable to start superclass. returning false", getName(), this);
break; }
DecrementOutstandingIO(); return true;
} while (false);
USBLog(3, "%s[%p]::start aborting. err = 0x%x", getName(), this, err);
if ( _interruptPipe )
{
_interruptPipe->Abort();
_interruptPipe = NULL;
}
provider->close(this);
stop(provider);
ErrorExit:
DecrementOutstandingIO();
return false;
}
void
AppleUSBKeyboard::stop(IOService * provider)
{
if (_deviceDeadCheckThread)
{
thread_call_cancel(_deviceDeadCheckThread);
thread_call_free(_deviceDeadCheckThread);
_deviceDeadCheckThread = 0;
}
if (_clearFeatureEndpointHaltThread)
{
thread_call_cancel(_clearFeatureEndpointHaltThread);
thread_call_free(_clearFeatureEndpointHaltThread);
_clearFeatureEndpointHaltThread = 0;
}
if (_asyncLEDThread)
{
thread_call_cancel(_asyncLEDThread);
thread_call_free(_asyncLEDThread);
_asyncLEDThread = 0;
}
if (_gate)
{
IOWorkLoop *wl = getWorkLoop();
if (wl)
wl->removeEventSource(_gate);
_gate->release();
_gate = NULL;
}
super::stop(provider);
}
void
AppleUSBKeyboard::Set_Idle_Millisecs(UInt16 msecs)
{
IOReturn err = kIOReturnSuccess;
_request.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface);
_request.bRequest = kHIDRqSetIdle; _request.wValue = (msecs/4) << 8;
_request.wIndex = _interface->GetInterfaceNumber();
_request.wLength = 0;
_request.pData = NULL;
err = _device->DeviceRequest(&_request, 5000, 0);
if ( err )
{
USBLog(3, "%s[%p]: Set_Idle_Millisecs returned error 0x%x",getName(), this, err);
}
return;
}
void
AppleUSBKeyboard::Set_LED_States(UInt8 bits)
{
IOReturn err = kIOReturnSuccess;
if (_prevent_LED_set)
return;
_request.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface);
_request.bRequest = kHIDRqSetReport; _request.wValue = kHIDRtOutputReport << 8;
_request.wIndex = _interface->GetInterfaceNumber();
_request.wLength = 1;
_hid_report[0] = bits; _hid_report[1] = 0;
_request.pData = (void *)_hid_report;
err = _device->DeviceRequest(&_request, 5000, 0);
if ( err )
{
USBLog(3, "%s[%p]: Set_LED_States returned error 0x%x",getName(), this, err);
_prevent_LED_set = TRUE;
}
return;
}
void
AppleUSBKeyboard::Get_LED_States()
{
IOReturn err = kIOReturnSuccess;
if (_prevent_LED_set)
return;
_request.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBClass, kUSBInterface);
_request.bRequest = kHIDRqGetReport; _request.wValue = kHIDRtInputReport << 8;
_request.wIndex = _interface->GetInterfaceNumber();
_request.wLength = 1;
_request.pData = (void *)_hid_report;
err = _device->DeviceRequest(&_request, 5000, 0);
if ( err )
{
USBLog(3, "%s[%p]: Get_LED_States returned error 0x%x",getName(), this, err);
}
return;
}
extern "C" {
void Debugger( const char * );
void boot(int paniced, int howto, char * command);
#define RB_BOOT 1
}
void
AppleUSBKeyboard::Simulate_ADB_Event(UInt8 *key_ptr, UInt32 bytes_read)
{
UInt8 alpha, modifier=0;
bool found;
AbsoluteTime now;
UInt8 seq_key, i;
found = true;
for (seq_key = 2; seq_key < prev_bytes_read; seq_key++) {
if (*(key_ptr + seq_key) != 1) found = false;
}
if (found) return;
if (bytes_read > kUSB_LOWSPEED_MAXPACKET) {
bytes_read = kUSB_LOWSPEED_MAXPACKET; }
modifier = *key_ptr;
if (modifier == oldmodifier)
{
}
else {
clock_get_uptime(&now);
if ((modifier & kUSB_LEFT_CONTROL_BIT) && !(oldmodifier & kUSB_LEFT_CONTROL_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe0], true, now); _control_key = true; }
else if ((oldmodifier & kUSB_LEFT_CONTROL_BIT) && !(modifier & kUSB_LEFT_CONTROL_BIT)
&& !(modifier & kUSB_RIGHT_CONTROL_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe0], false, now);
_control_key = false;
}
if ((modifier & kUSB_RIGHT_CONTROL_BIT) && !(oldmodifier & kUSB_RIGHT_CONTROL_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe4], true, now); _control_key = true; }
else if ((oldmodifier & kUSB_RIGHT_CONTROL_BIT) && !(modifier & kUSB_RIGHT_CONTROL_BIT)
&& !(modifier & kUSB_LEFT_CONTROL_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe4], false, now);
_control_key = false;
}
if ((modifier & kUSB_LEFT_SHIFT_BIT) && !(oldmodifier & kUSB_LEFT_SHIFT_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe1], true, now);
}
else if ((oldmodifier & kUSB_LEFT_SHIFT_BIT) && !(modifier & kUSB_LEFT_SHIFT_BIT)
&& !(modifier & kUSB_RIGHT_SHIFT_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe1], false, now);
}
if ((modifier & kUSB_RIGHT_SHIFT_BIT) && !(oldmodifier & kUSB_RIGHT_SHIFT_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe5], true, now);
}
else if ((oldmodifier & kUSB_RIGHT_SHIFT_BIT) && !(modifier & kUSB_RIGHT_SHIFT_BIT)
&& !(modifier & kUSB_LEFT_SHIFT_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe5], false, now);
}
if ((modifier & kUSB_LEFT_ALT_BIT) && !(oldmodifier & kUSB_LEFT_ALT_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe2], true, now);
}
else if ((oldmodifier & kUSB_LEFT_ALT_BIT) && !(modifier & kUSB_LEFT_ALT_BIT)
&& !(modifier & kUSB_RIGHT_ALT_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe2], false, now);
}
if ((modifier & kUSB_RIGHT_ALT_BIT) && !(oldmodifier & kUSB_RIGHT_ALT_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe6], true, now);
}
else if ((oldmodifier & kUSB_RIGHT_ALT_BIT) && !(modifier & kUSB_RIGHT_ALT_BIT)
&& !(modifier & kUSB_LEFT_ALT_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe6], false, now);
}
if ((modifier & kUSB_LEFT_FLOWER_BIT) && !(oldmodifier & kUSB_LEFT_FLOWER_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe3], true, now);
_flower_key = true; }
else if ((oldmodifier & kUSB_LEFT_FLOWER_BIT) && !(modifier & kUSB_LEFT_FLOWER_BIT)
&& !(modifier & kUSB_RIGHT_FLOWER_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe3], false, now);
_flower_key = false;
}
if ((modifier & kUSB_RIGHT_FLOWER_BIT) && !(oldmodifier & kUSB_RIGHT_FLOWER_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe7], true, now);
_flower_key = true;
}
else if ((oldmodifier & kUSB_RIGHT_FLOWER_BIT) && !(modifier & kUSB_RIGHT_FLOWER_BIT)
&& !(modifier & kUSB_LEFT_FLOWER_BIT))
{
dispatchKeyboardEvent(usb_2_adb_keymap[0xe7], false, now);
_flower_key = false;
}
}
for (seq_key = 2; seq_key < prev_bytes_read; seq_key++)
{
alpha = old_array[seq_key];
if (alpha == 0) {
continue;
}
found = false;
for (i = 2; i < bytes_read; i++) {
if (alpha == *(key_ptr + i))
{
found = true; break; }
}
if (!found)
{
clock_get_uptime(&now);
dispatchKeyboardEvent(usb_2_adb_keymap[alpha], false, now); }
}
for (seq_key = 2; seq_key < bytes_read; seq_key++)
{
alpha = *(key_ptr + seq_key);
if (alpha == 0) {
continue;
}
else if (alpha == 0x66) {
if ((_control_key) && (_flower_key)) {
boot( RB_BOOT, 0, 0 ); }
if (_flower_key) {
PE_enter_debugger("USB Programmer Key");
}
}
found = false;
for (i = 2; i < prev_bytes_read; i++)
{
if (alpha == old_array[i])
{
found = true;
break;
}
}
if (!found)
{
clock_get_uptime(&now);
dispatchKeyboardEvent(usb_2_adb_keymap[alpha], true, now);
}
}
oldmodifier = modifier;
prev_bytes_read = bytes_read;
for (i=0; i< bytes_read; i++) {
old_array[i] = *(key_ptr + i);
}
}
void
AppleUSBKeyboard::AsyncLED(OSObject *target)
{
AppleUSBKeyboard *me = OSDynamicCast(AppleUSBKeyboard, target);
USBLog(5, "+%s[%p]::usb_asyncLED, isInactive() = (%d)", me->getName(), me, me->isInactive());
if ( !me->isInactive() )
{
me->Set_LED_States( me->_ledState );
}
USBLog(5, "-%s[%p]::usb_asyncLED, isInactive() = (%d)", me->getName(), me, me->isInactive());
me->DecrementOutstandingIO();
}
void
AppleUSBKeyboard::setAlphaLockFeedback ( bool LED_state)
{
UInt8 newState = _ledState;
if (LED_state) newState |= kUSB_CAPSLOCKLED_SET; else
newState &= ~kUSB_CAPSLOCKLED_SET;
if (newState != _ledState)
{
_ledState = newState;
IncrementOutstandingIO(); thread_call_enter(_asyncLEDThread);
}
}
void
AppleUSBKeyboard::setNumLockFeedback ( bool LED_state)
{
UInt8 newState = _ledState;
if (LED_state)
newState |= kUSB_NUMLOCKLED_SET; else
newState &= ~kUSB_NUMLOCKLED_SET;
if (newState != _ledState)
{
_ledState = newState;
IncrementOutstandingIO(); thread_call_enter(_asyncLEDThread);
}
}
unsigned
AppleUSBKeyboard::getLEDStatus (void )
{
Get_LED_States();
return _hid_report[0];
}
UInt32 AppleUSBKeyboard::maxKeyCodes (void )
{
return 0x80;
}
UInt32 AppleUSBKeyboard::deviceType ( void )
{
UInt32 id;
OSNumber *xml_handlerID;
xml_handlerID = OSDynamicCast( OSNumber, getProperty("alt_handler_id"));
if (xml_handlerID)
{
id = xml_handlerID->unsigned32BitValue();
}
else
{
id = handlerID();
}
return id;
}
UInt32 AppleUSBKeyboard::interfaceID ( void )
{
return NX_EVS_DEVICE_INTERFACE_ADB; }
UInt32
AppleUSBKeyboard::handlerID ( void )
{
UInt32 ret_id = 2;
if (_device->GetVendorID() == kIOUSBVendorIDAppleComputer)
{
ret_id = _device->GetProductID();
if ((ret_id == kprodUSBAndyISOKbd) || (ret_id == kprodUSBCosmoISOKbd))
{
usb_2_adb_keymap[0x35] = 0x0a; usb_2_adb_keymap[0x64] = 0x32;
USBLog(5,"USB ISO keys swapped");
}
}
if (_device->GetVendorID() == 0x045e) {
if (_device->GetProductID() == 0x000b) ret_id = 2; }
if (_device->GetVendorID() == kIOUSBVendorIDAppleComputer)
switch (ret_id)
{
case kprodUSBCosmoANSIKbd: ret_id = kgestUSBCosmoANSIKbd; break;
case kprodUSBCosmoISOKbd: ret_id = kgestUSBCosmoISOKbd; break;
case kprodUSBCosmoJISKbd: ret_id = kgestUSBCosmoJISKbd; break;
case kprodUSBAndyANSIKbd: ret_id = kgestUSBAndyANSIKbd; break;
case kprodUSBAndyISOKbd: ret_id = kgestUSBAndyISOKbd; break;
case kprodUSBAndyJISKbd: ret_id = kgestUSBAndyJISKbd; break;
default: ret_id = kgestUSBCosmoANSIKbd;
break;
}
return ret_id; }
bool AppleUSBKeyboard:: doesKeyLock ( unsigned key)
{
switch (key) {
case NX_KEYTYPE_CAPS_LOCK:
return false;
case NX_KEYTYPE_NUM_LOCK:
return false;
default:
return false;
}
}
const unsigned char * AppleUSBKeyboard::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,
0x05, 0x04,0x39, 0x05,0x72, 0x06,0x7f, 0x07,0x4a, 0x0a,0x47 };
*length = sizeof(appleUSAKeyMap);
return appleUSAKeyMap;
}
IOReturn
AppleUSBKeyboard::message( UInt32 type, IOService * provider, void * argument )
{
IOReturn err = kIOReturnSuccess;
switch ( type )
{
case kIOUSBMessagePortHasBeenReset:
USBLog(3, "%s[%p]: received kIOUSBMessagePortHasBeenReset", getName(), this);
_retryCount = kKeyboardRetryCount;
_deviceIsDead = FALSE;
_deviceHasBeenDisconnected = FALSE;
IncrementOutstandingIO();
if ((err = _interruptPipe->Read(_buffer, &_completion)))
{
DecrementOutstandingIO();
USBLog(3, "%s[%p]::message - err (%x) in interrupt read", getName(), this, err);
}
break;
default:
err = super::message (type, provider, argument);
break;
}
return err;
}
bool
AppleUSBKeyboard::finalize(IOOptionBits options)
{
return(super::finalize(options));
}
void
AppleUSBKeyboard::InterruptReadHandlerEntry(OSObject *target, void *param, IOReturn status, UInt32 bufferSizeRemaining)
{
AppleUSBKeyboard * me = OSDynamicCast(AppleUSBKeyboard, target);
if (!me)
return;
me->InterruptReadHandler(status, bufferSizeRemaining);
me->DecrementOutstandingIO();
}
void
AppleUSBKeyboard::InterruptReadHandler(IOReturn status, UInt32 bufferSizeRemaining)
{
bool queueAnother = true;
bool timeToGoAway = false;
IOReturn err = kIOReturnSuccess;
switch (status)
{
case kIOReturnOverrun:
USBLog(3, "%s[%p]::InterruptReadHandler kIOReturnOverrun error", getName(), this);
if (!isInactive())
{
_interruptPipe->ClearStall();
IncrementOutstandingIO();
thread_call_enter(_clearFeatureEndpointHaltThread);
}
queueAnother = false;
timeToGoAway = false;
case kIOReturnSuccess:
_retryCount = kKeyboardRetryCount;
Simulate_ADB_Event((UInt8 *)_buffer->getBytesNoCopy(), (UInt32)_maxPacketSize - bufferSizeRemaining);
if (isInactive())
queueAnother = false;
break;
case kIOReturnNotResponding:
USBLog(3, "%s[%p]::InterruptReadHandler kIOReturnNotResponding error", getName(), this);
if ( _deviceHasBeenDisconnected || isInactive() )
{
queueAnother = false;
timeToGoAway = true;
}
else
{
USBLog(3, "%s[%p]::InterruptReadHandler Checking to see if keyboard is still connected", getName(), this);
IncrementOutstandingIO();
thread_call_enter(_deviceDeadCheckThread);
_interruptPipe->ClearStall();
}
break;
case kIOReturnAborted:
if (isInactive() || _deviceIsDead )
{
USBLog(3,"%s[%p]::InterruptReadHandler Read aborted. We are terminating", getName(), this);
queueAnother = false;
timeToGoAway = true;
}
else
{
USBLog(3,"%s[%p]::InterruptReadHandler Read aborted. Don't know why. Trying again", getName(), this);
}
break;
case kIOReturnUnderrun:
case kIOUSBPipeStalled:
case kIOUSBLinkErr:
case kIOUSBNotSent2Err:
case kIOUSBNotSent1Err:
case kIOUSBBufferUnderrunErr:
case kIOUSBBufferOverrunErr:
case kIOUSBWrongPIDErr:
case kIOUSBPIDCheckErr:
case kIOUSBDataToggleErr:
case kIOUSBBitstufErr:
case kIOUSBCRCErr:
USBLog(3, "%s[%p]::InterruptReadHandler OHCI error (0x%x) reading interrupt pipe", getName(), this, status);
if (!isInactive())
{
_interruptPipe->ClearStall();
IncrementOutstandingIO();
thread_call_enter(_clearFeatureEndpointHaltThread);
}
queueAnother = false;
break;
default:
USBLog(3, "%s[%p]::InterruptReadHandler error (0x%x) reading interrupt pipe", getName(), this, status);
if (isInactive())
queueAnother = false;
break;
}
if ( queueAnother )
{
IncrementOutstandingIO();
err = _interruptPipe->Read(_buffer, &_completion);
if ( err != kIOReturnSuccess)
{
USBError(1, "%s[%p]::InterruptReadHandler - immediate error 0x%x queueing read\n", getName(), this, err);
DecrementOutstandingIO();
timeToGoAway = true;
}
}
if ( timeToGoAway )
{
if (_codeToRepeat != (unsigned) -1)
{
AbsoluteTime now;
clock_get_uptime(&now);
dispatchKeyboardEvent(_codeToRepeat, false, now);
}
}
}
void
AppleUSBKeyboard::CheckForDeadDeviceEntry(OSObject *target)
{
AppleUSBKeyboard *me = OSDynamicCast(AppleUSBKeyboard, target);
if (!me)
return;
me->CheckForDeadDevice();
me->DecrementOutstandingIO();
}
void
AppleUSBKeyboard::CheckForDeadDevice()
{
IOReturn err = kIOReturnSuccess;
IOUSBDevice * device;
_deviceDeadThreadActive = true;
if ( _interface )
{
device = _interface->GetDevice();
if ( device )
{
err = device->message(kIOUSBMessageHubIsDeviceConnected, NULL, 0);
if ( kIOReturnSuccess == err )
{
if ( --_retryCount == 0 )
{
_deviceIsDead = true;
USBLog(3, "%s[%p]: Detected an kIONotResponding error but still connected. Resetting port", getName(), this);
if (_interruptPipe)
_interruptPipe->Abort();
device->ResetDevice();
}
}
else
{
_deviceHasBeenDisconnected = true;
USBLog(5, "%s[%p]: CheckForDeadDevice: keyboard has been unplugged", getName(), this);
}
}
}
_deviceDeadThreadActive = false;
}
void
AppleUSBKeyboard::ClearFeatureEndpointHaltEntry(OSObject *target)
{
AppleUSBKeyboard * me = OSDynamicCast(AppleUSBKeyboard, target);
if (!me)
return;
me->ClearFeatureEndpointHalt();
me->DecrementOutstandingIO();
}
void
AppleUSBKeyboard::ClearFeatureEndpointHalt( )
{
IOReturn status;
bzero( &_request, sizeof(IOUSBDevRequest));
_request.bmRequestType = USBmakebmRequestType(kUSBNone, kUSBStandard, kUSBEndpoint);
_request.bRequest = kUSBRqClearFeature;
_request.wValue = kUSBFeatureEndpointStall;
_request.wIndex = _interruptPipe->GetEndpointNumber() | 0x80 ; _request.wLength = 0;
_request.pData = NULL;
status = _device->DeviceRequest(&_request, 5000, 0);
if ( status )
{
USBLog(3, "%s[%p]::ClearFeatureEndpointHalt - DeviceRequest returned: 0x%x", getName(), this, status);
}
IncrementOutstandingIO();
status = _interruptPipe->Read(_buffer, &_completion);
if ( status != kIOReturnSuccess)
{
USBLog(3, "%s[%p]::ClearFeatureEndpointHalt - immediate error %d queueing read", getName(), this, status);
DecrementOutstandingIO();
}
}
bool
AppleUSBKeyboard::willTerminate( IOService * provider, IOOptionBits options )
{
USBLog(5, "%s[%p]::willTerminate isInactive = %d", getName(), this, isInactive());
if (_buffer)
{
_buffer->release();
_buffer = NULL;
}
if (_interruptPipe)
{
_interruptPipe->Abort();
}
return super::willTerminate(provider, options);
}
bool
AppleUSBKeyboard::didTerminate( IOService * provider, IOOptionBits options, bool * defer )
{
USBLog(5, "%s[%p]::didTerminate isInactive = %d, outstandingIO = %d", getName(), this, isInactive(), _outstandingIO);
if (!_outstandingIO)
_interface->close(this);
else
_needToClose = true;
return super::didTerminate(provider, options, defer);
}
#if 0
bool
AppleUSBKeyboard::requestTerminate( IOService * provider, IOOptionBits options )
{
USBLog(3, "%s[%p]::requestTerminate isInactive = %d", getName(), this, isInactive());
return super::requestTerminate(provider, options);
}
bool
AppleUSBKeyboard::terminate( IOOptionBits options = 0 )
{
USBLog(3, "%s[%p]::terminate isInactive = %d", getName(), this, isInactive());
return super::terminate(options);
}
void
AppleUSBKeyboard::free( void )
{
USBLog(3, "%s[%p]::free isInactive = %d", getName(), this, isInactive());
super::free();
}
bool
AppleUSBKeyboard::terminateClient( IOService * client, IOOptionBits options )
{
USBLog(3, "%s[%p]::terminateClient isInactive = %d", getName(), this, isInactive());
return super::terminateClient(client, options);
}
#endif
void
AppleUSBKeyboard::DecrementOutstandingIO(void)
{
if (!_gate)
{
if (!--_outstandingIO && _needToClose)
{
USBLog(3, "%s[%p]::DecrementOutstandingIO isInactive = %d, outstandingIO = %d - closing device", getName(), this, isInactive(), _outstandingIO);
_interface->close(this);
}
return;
}
_gate->runAction(ChangeOutstandingIO, (void*)-1);
}
void
AppleUSBKeyboard::IncrementOutstandingIO(void)
{
if (!_gate)
{
_outstandingIO++;
return;
}
_gate->runAction(ChangeOutstandingIO, (void*)1);
}
IOReturn
AppleUSBKeyboard::ChangeOutstandingIO(OSObject *target, void *param1, void *param2, void *param3, void *param4)
{
AppleUSBKeyboard *me = OSDynamicCast(AppleUSBKeyboard, target);
UInt32 direction = (UInt32)param1;
if (!me)
{
USBLog(1, "AppleUSBKeyboard::ChangeOutstandingIO - invalid target");
return kIOReturnSuccess;
}
switch (direction)
{
case 1:
me->_outstandingIO++;
break;
case -1:
if (!--me->_outstandingIO && me->_needToClose)
{
USBLog(3, "%s[%p]::ChangeOutstandingIO isInactive = %d, outstandingIO = %d - closing device", me->getName(), me, me->isInactive(), me->_outstandingIO);
me->_interface->close(me);
}
break;
default:
USBLog(1, "%s[%p]::ChangeOutstandingIO - invalid direction", me->getName(), me);
}
return kIOReturnSuccess;
}