/* Send power messages to rootDomain */ bool Insomnia::send_event(UInt32 msg) { IOPMrootDomain *root = NULL; IOReturn ret=kIOReturnSuccess; DLog(""); root = getPMRootDomain(); if (!root) { DLog("Fatal error could not get RootDomain."); return false; } ret = root->receivePowerNotification(msg); Log("root returns %d", ret); if(ret!=kIOReturnSuccess) { DLog("Error sending event: %d", ret); } else Log("Message sent to root"); return true; }
/* Send power messages to rootDomain */ bool Insomnia::send_event(UInt32 msg) { IOPMrootDomain *root = NULL; IOReturn ret=kIOReturnSuccess; char err_str[100]; IOLog("Insomina: Sending event\n"); root = getPMRootDomain(); if (!root) { IOLog("Insomnia: Fatal error could not get RootDomain.\n"); return false; } ret = root->receivePowerNotification(msg); IOLog("Insomnia: root returns %d\n", ret); if(ret!=kIOReturnSuccess) { snprintf(err_str, 100, "Insomina: Error sending event: %d\n", ret); IOLog("%s", err_str); } else IOLog("Insomnia: Message sent to root\n"); return true; }
bool IOEthernetInterface::controllerDidOpen(IONetworkController * ctr) { bool ret = false; OSData * addrData; IOEthernetAddress * addr; do { // Call the controllerDidOpen() in superclass first. if ( (ctr == 0) || (super::controllerDidOpen(ctr) == false) ) break; // If the controller supports some form of multicast filtering, // then set the ifnet IFF_MULTICAST flag. if ( GET_SUPPORTED_FILTERS(gIONetworkFilterGroup) & (kIOPacketFilterMulticast | kIOPacketFilterMulticastAll) ) { setFlags(IFF_MULTICAST); } // Advertise Wake on Magic Packet feature if supported. if ( _supportedWakeFilters & kIOEthernetWakeOnMagicPacket ) { IOPMrootDomain * root = getPMRootDomain(); if ( root ) root->publishFeature( kWOMPFeatureKey, kIOPMSupportedOnAC | kIOPMSupportedOnUPS, (uint32_t *)&_publishedFeatureID); } // Get the controller's MAC/Ethernet address. addrData = OSDynamicCast(OSData, ctr->getProperty(kIOMACAddress)); if ( (addrData == 0) || (addrData->getLength() != ETHER_ADDR_LEN) ) { DLOG("%s: kIOMACAddress property access error (len %d)\n", getName(), addrData ? addrData->getLength() : 0); break; } addr = (IOEthernetAddress *) addrData->getBytesNoCopy(); DLOG("%s: Ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n", ctr->getName(), addr->bytes[0], addr->bytes[1], addr->bytes[2], addr->bytes[3], addr->bytes[4], addr->bytes[5]); ret = true; } while (0); return ret; }
void IOEthernetInterface::controllerWillClose(IONetworkController * ctr) { if ( _supportedWakeFilters & kIOEthernetWakeOnMagicPacket ) { IOPMrootDomain * root = getPMRootDomain(); if ( root ) root->removePublishedFeature( _publishedFeatureID ); _publishedFeatureID = 0; } super::controllerWillClose(ctr); }
int IOPlatformExpert::haltRestart(unsigned int type) { IOPMrootDomain *rd = getPMRootDomain(); OSBoolean *b = 0; if(rd) b = (OSBoolean *)OSDynamicCast(OSBoolean, rd->getProperty(OSString::withCString("StallSystemAtHalt"))); if (type == kPEHangCPU) while (1); if (kOSBooleanTrue == b) { // Stall shutdown for 5 minutes, and if no outside force has removed our power, continue with // a reboot. IOSleep(1000*60*5); type = kPERestartCPU; } if (PE_halt_restart) return (*PE_halt_restart)(type); else return -1; }
int PEHaltRestart(unsigned int type) { IOPMrootDomain *pmRootDomain = IOService::getPMRootDomain(); bool noWaitForResponses; AbsoluteTime deadline; thread_call_t shutdown_hang; if(type == kPEHaltCPU || type == kPERestartCPU) { /* Notify IOKit PM clients of shutdown/restart Clients subscribe to this message with a call to IOService::registerInterest() */ /* Spawn a thread that will panic in 30 seconds. If all goes well the machine will be off by the time the timer expires. */ shutdown_hang = thread_call_allocate( &IOPMPanicOnShutdownHang, (thread_call_param_t) type); clock_interval_to_deadline( 30, kSecondScale, &deadline ); thread_call_enter1_delayed( shutdown_hang, 0, deadline ); noWaitForResponses = pmRootDomain->tellChangeDown2(type); /* This notification should have few clients who all do their work synchronously. In this "shutdown notification" context we don't give drivers the option of working asynchronously and responding later. PM internals make it very hard to wait for asynchronous replies. In fact, it's a bad idea to even be calling tellChangeDown2 from here at all. */ } if (gIOPlatform) return gIOPlatform->haltRestart(type); else return -1; }
bool ApplePS2Keyboard::dispatchKeyboardEventWithScancode(UInt8 scanCode) { // // Parses the given scan code, updating all necessary internal state, and // should a new key be detected, the key event is dispatched. // // Returns true if a key event was indeed dispatched. // unsigned int keyCode; bool goingDown; AbsoluteTime now; // // See if this scan code introduces an extended key sequence. If so, note // it and then return. Next time we get a key we'll finish the sequence. // if (scanCode == kSC_Extend) { _extendCount = 1; return false; } // // See if this scan code introduces an extended key sequence for the Pause // Key. If so, note it and then return. The next time we get a key, drop // it. The next key we get after that finishes the Pause Key sequence. // // The sequence actually sent to us by the keyboard for the Pause Key is: // // 1. E1 Extended Sequence for Pause Key // 2. 1D Useless Data, with Up Bit Cleared // 3. 45 Pause Key, with Up Bit Cleared // 4. E1 Extended Sequence for Pause Key // 5. 9D Useless Data, with Up Bit Set // 6. C5 Pause Key, with Up Bit Set // // The reason items 4 through 6 are sent with the Pause Key is because the // keyboard hardware never generates a release code for the Pause Key and // the designers are being smart about it. The sequence above translates // to this parser as two separate events, as it should be -- one down key // event and one up key event (for the Pause Key). // if (scanCode == kSC_Pause) { _extendCount = 2; return false; } // // Convert the scan code into a key code. // //IOLog("key 0x%x scan 0x%x ex %d\n",(scanCode & ~kSC_UpBit),scanCode,_extendCount); if (_extendCount == 0) { keyCode = scanCode & ~kSC_UpBit; // from "The Undocumented PC" chapter 8, The Keyboard System some // keyboard scan codes are single byte, some are multi-byte // 3023805: I want to swap alt and windows, since the windows // key is located where the alt/option key is on an Apple PowerBook // or USB keyboard, and the alt key is where the Apple/Command // key is on the PB or USB keyboard. Left alt is a single scan // code byte, right alt is a double scan code byte. Left and // right windows keys are double bytes. This is all set by an // entry in Info.plist for ApplePS2Keyboard.kext switch (keyCode) { case 0x3A: if (emacsMode == true) { keyCode = 0x60; } break; // caps lock becomes ctrl case 0x38: if (macintoshMode == true) { keyCode = 0x70; } break; // left alt becomes left windows /* CFR: Nope...this is the code for =+ case 0xd: // ² if(scanCode==0xd) { _extendCount=1; dispatchKeyboardEventWithScancode(0x5b); dispatchKeyboardEventWithScancode(0x56); } else { _extendCount=1; dispatchKeyboardEventWithScancode(0xdb); dispatchKeyboardEventWithScancode(0xd6); } return true; */ // CFR case 0x56: keyCode = 0x29; break; // < // CFR case 0x1a: keyCode = 0xd; break; // + // CFR case 0x28: keyCode = 0x1a; break; // ¼ » // CFR case 0x2b: keyCode = 0x28; break; // ~ // CFR case 0x29: keyCode = 0x2b; break; case 0x8: if (keyi==true) { if(scanCode==0x8) { dispatchKeyboardEventWithScancode(0x2a); } else { dispatchKeyboardEventWithScancode(0xaa); } keyCode = 0x9; } break; case 0xb: if (keyi==true) { if(scanCode==0xb) { dispatchKeyboardEventWithScancode(0x2a); } else { dispatchKeyboardEventWithScancode(0xaa); } keyCode = 0xa; } break; case 0x12: if (keyi==true) keyCode = 0x4; break; case 0x4: if (keyi==true) keyCode = 0x5; break; case 0x5: if (keyi==true) keyCode = 0xc; break; } } else { _extendCount--; if (_extendCount) return false; // // Convert certain extended codes on the PC keyboard into single scancodes. // Refer to the conversion table in defaultKeymapOfLength. // switch (scanCode & ~kSC_UpBit) { case 0x33: // Û if(scanCode==0x33) { dispatchKeyboardEventWithScancode(0x38); dispatchKeyboardEventWithScancode(0x10); } else { dispatchKeyboardEventWithScancode(0xb8); dispatchKeyboardEventWithScancode(0x90); } return true; case 0x34: // $ = F12 - press and hold to eject cd rom if (scanCode==0x34) { dispatchKeyboardEventWithScancode(0x58); //dispatchKeyboardEventWithScancode(0x58); } else { dispatchKeyboardEventWithScancode(0xd8); //dispatchKeyboardEventWithScancode(0x58); } return true; // scancodes from running showkey -s (under Linux) for extra keys on keyboard case 0x30: keyCode = 0x7d; break; // E030 = volume up case 0x2e: keyCode = 0x7e; break; // E02E = volume down case 0x20: keyCode = 0x7f; break; // E020 = volume mute case 0x5e: keyCode = 0x7c; break; // E05E = power case 0x5f: // E05F = sleep keyCode = 0; if (!(scanCode & kSC_UpBit)) { IOPMrootDomain * rootDomain = getPMRootDomain(); if (rootDomain) rootDomain->receivePowerNotification( kIOPMSleepNow ); } break; case 0x1D: keyCode = 0x60; break; // ctrl case 0x38: // right alt may become right command if (macintoshMode == true) { keyCode = 0x71; } else { keyCode = 0x61; } break; case 0x1C: keyCode = 0x62; break; // enter case 0x35: keyCode = 0x63; break; // / case 0x48: keyCode = 0x64; break; // up arrow case 0x50: keyCode = 0x65; break; // down arrow case 0x4B: keyCode = 0x66; break; // left arrow case 0x4D: keyCode = 0x67; break; // right arrow case 0x52: keyCode = 0x68; break; // insert 0x68 case 0x53: keyCode = 0x69; break; // delete case 0x49: keyCode = 0x6A; break; // page up case 0x51: keyCode = 0x6B; break; // page down case 0x47: keyCode = 0x6C; break; // home case 0x4F: keyCode = 0x6D; break; // end case 0x37: //keyCode = 0x6E; break; // PrintScreen if(scanCode==0x37) { dispatchKeyboardEventWithScancode(0x1d); dispatchKeyboardEventWithScancode(0x38); dispatchKeyboardEventWithScancode(0x2a); dispatchKeyboardEventWithScancode(0x5); } else { dispatchKeyboardEventWithScancode(0x9d); dispatchKeyboardEventWithScancode(0xb8); dispatchKeyboardEventWithScancode(0xaa); dispatchKeyboardEventWithScancode(0x85); } return true; case 0x45: //keyCode = 0x6F; break; // Pause if(scanCode==0x45) { dispatchKeyboardEventWithScancode(0x1d); dispatchKeyboardEventWithScancode(0x2e); } else { dispatchKeyboardEventWithScancode(0x9d); dispatchKeyboardEventWithScancode(0xae); } return true; case 0x5B: // left Windows key may become alt if (macintoshMode == true) { keyCode = 0x38; if (scanCode==0x5B) keyi=true; else keyi=false; // alt } else { keyCode = 0x70; // Left command } break; case 0x5c: // right Windows key may become alt if (macintoshMode == true) { keyCode = 0x61; // alt } else { keyCode = 0x71; // Right command } break; case 0x5D: keyCode = 0x38; if (scanCode==0x5D) keyi=true; else keyi=false; break; // Application 0x72 case 0x2A: // header or trailer for PrintScreen default: return false; } } //IOLog("keycode 0x%x\n",keyCode); if (keyCode == 0) return false; // // Update our key bit vector, which maintains the up/down status of all keys. // goingDown = !(scanCode & kSC_UpBit); if (goingDown) { // // Verify that this is not an autorepeated key -- discard it if it is. // if (KBV_IS_KEYDOWN(keyCode, _keyBitVector)) return false; KBV_KEYDOWN(keyCode, _keyBitVector); } else { KBV_KEYUP(keyCode, _keyBitVector); } // // We have a valid key event -- dispatch it to our superclass. // clock_get_uptime((uint64_t *)&now); dispatchKeyboardEvent( PS2ToADBMap[keyCode], /*direction*/ goingDown, /*timeStamp*/ now ); return true; }
bool ApplePS2Keyboard::dispatchKeyboardEventWithScancode(UInt8 scanCode) { // // Parses the given scan code, updating all necessary internal state, and // should a new key be detected, the key event is dispatched. // // Returns true if a key event was indeed dispatched. // unsigned int keyCode; bool goingDown; AbsoluteTime now; // //Accidental Input Keys // switch (scanCode & ~kSC_UpBit) { case 0X01://ESC case 0X0f://Tab case 0x3a://CapsLock case 0x2a://Shift case 0x36:// case 0x1d://Cntrl case 0x5b://Window case 0x38://Alt case 0x5d://ContextMenu case 0x45://NumLock case 0x1c://Enter case 0x0e://Backspace case 0x64://Arrows case 0x65:// case 0x66:// case 0x67:// _accidentalInputKeysException = true; break; case 0x52:/* 0........9 */ case 0x4f: case 0x50: case 0x51: case 0x4b: case 0x4c: case 0x4d: case 0x47: case 0x48: case 0x49: case 0x53:/* ". / * - + ENTER" */ case 0x63: case 0x37: case 0x4a: case 0x4e: case 0x62: _keyPadKeys = true; break; default: break; } // // See if this scan code introduces an extended key sequence. If so, note // it and then return. Next time we get a key we'll finish the sequence. // if (scanCode == kSC_Extend) { _extendCount = 1; return false; } // // See if this scan code introduces an extended key sequence for the Pause // Key. If so, note it and then return. The next time we get a key, drop // it. The next key we get after that finishes the Pause Key sequence. // // The sequence actually sent to us by the keyboard for the Pause Key is: // // 1. E1 Extended Sequence for Pause Key // 2. 1D Useless Data, with Up Bit Cleared // 3. 45 Pause Key, with Up Bit Cleared // 4. E1 Extended Sequence for Pause Key // 5. 9D Useless Data, with Up Bit Set // 6. C5 Pause Key, with Up Bit Set // // The reason items 4 through 6 are sent with the Pause Key is because the // keyboard hardware never generates a release code for the Pause Key and // the designers are being smart about it. The sequence above translates // to this parser as two separate events, as it should be -- one down key // event and one up key event (for the Pause Key). // if (scanCode == kSC_Pause) { _extendCount = 2; return false; } // // Convert the scan code into a key code. // if (_extendCount == 0) { keyCode = scanCode & ~kSC_UpBit; // from "The Undocumented PC" chapter 8, The Keyboard System some // keyboard scan codes are single byte, some are multi-byte // 3023805: I want to swap alt and windows, since the windows // key is located where the alt/option key is on an Apple PowerBook // or USB keyboard, and the alt key is where the Apple/Command // key is on the PB or USB keyboard. Left alt is a single scan // code byte, right alt is a double scan code byte. Left and // right windows keys are double bytes. This is all set by an // entry in Info.plist for ApplePS2Keyboard.kext switch (keyCode) { case 0x3A: if (emacsMode == true) { keyCode = 0x60; } break; // caps lock becomes ctrl case 0x38: if (macintoshMode == true) { keyCode = 0x70; } break; // left alt becomes left windows } } else { _extendCount--; if (_extendCount) return false; // // Convert certain extended codes on the PC keyboard into single scancodes. // Refer to the conversion table in defaultKeymapOfLength. // switch (scanCode & ~kSC_UpBit) { // scancodes from running showkey -s (under Linux) for extra keys on keyboard case 0x30: keyCode = 0x7d; break; // E030 = volume up case 0x2e: keyCode = 0x7e; break; // E02E = volume down case 0x20: keyCode = 0x7f; break; // E020 = volume mute case 0x5e: keyCode = 0x7c; break; // E05E = power case 0x5f: // E05F = sleep keyCode = 0; if (!(scanCode & kSC_UpBit)) { IOPMrootDomain * rootDomain = getPMRootDomain(); if (rootDomain) rootDomain->receivePowerNotification( kIOPMSleepNow ); } break; case 0x1D: keyCode = 0x60; break; // ctrl case 0x38: // right alt may become right command if (macintoshMode == true) { keyCode = 0x71; } else { keyCode = 0x61; } break; case 0x1C: keyCode = 0x62; break; // enter case 0x35: keyCode = 0x63; break; // / case 0x48: keyCode = 0x64; break; // up arrow case 0x50: keyCode = 0x65; break; // down arrow case 0x4B: keyCode = 0x66; break; // left arrow case 0x4D: keyCode = 0x67; break; // right arrow case 0x52: keyCode = 0x68; break; // insert case 0x53: keyCode = 0x69; break; // delete case 0x49: keyCode = 0x6A; break; // page up case 0x51: keyCode = 0x6B; break; // page down case 0x47: keyCode = 0x6C; break; // home case 0x4F: keyCode = 0x6D; break; // end case 0x37: keyCode = 0x6E; break; // PrintScreen case 0x45: keyCode = 0x6F; break; // Pause case 0x5B: // left Windows key may become alt if (macintoshMode == true) { keyCode = 0x38; // alt } else { keyCode = 0x70; // Left command } break; case 0x5d: //right context click key becomes alt (right Windows key may become alt) if (macintoshMode == true) { keyCode = 0x61; // alt } else { keyCode = 0x71; // Right command } break; //case 0x5D: keyCode = 0x72; break; // Application case 0x2A: // header or trailer for PrintScreen default: return false; } } if (keyCode == 0) return false; // // Update our key bit vector, which maintains the up/down status of all keys. // goingDown = !(scanCode & kSC_UpBit); if (goingDown) { // // Verify that this is not an autorepeated key -- discard it if it is. // if (KBV_IS_KEYDOWN(keyCode, _keyBitVector)) return false; KBV_KEYDOWN(keyCode, _keyBitVector); } else { KBV_KEYUP(keyCode, _keyBitVector); } // // We have a valid key event -- dispatch it to our superclass. // //IOLog("Keyboard key Code %x %d\n",keyCode,keyCode); //Sending PS2 Notification to Mouse/Touchpad if(goingDown) if(!_accidentalInputKeysException && !_keyPadKeys) _device->dispatchPS2Notification(kPS2C_DisableTouchpad); clock_get_uptime((uint64_t *)&now); //NUM LOCK and Print Screen Fix if(keyCode == 0x45 && goingDown) { setNumLockFeedback(_numKeypadLocked); _numKeypadLocked = !_numKeypadLocked; } else if(keyCode == 0x6e && goingDown)//Print Screen Simulation { dispatchKeyboardEvent( 55, /*direction*/ true, /*timeStamp*/ now ); clock_get_uptime((uint64_t *)&now); dispatchKeyboardEvent( 56, /*direction*/ true, /*timeStamp*/ now ); clock_get_uptime((uint64_t *)&now); dispatchKeyboardEvent( 21, /*direction*/ true, /*timeStamp*/ now ); clock_get_uptime((uint64_t *)&now); dispatchKeyboardEvent( 21, /*direction*/ false, /*timeStamp*/ now ); clock_get_uptime((uint64_t *)&now); dispatchKeyboardEvent( 56, /*direction*/ false, /*timeStamp*/ now ); clock_get_uptime((uint64_t *)&now); dispatchKeyboardEvent( 55, /*direction*/ false, /*timeStamp*/ now ); } else if(!((keyCode == 0x45 || keyCode == 0x6e) ||//NumLock & PrintScreen //Keypad Buttons ((keyCode == 0x52 || keyCode == 0x53 || keyCode == 0x62 || keyCode == 0x4f || keyCode == 0x50 || keyCode == 0x51 || keyCode == 0x4b || keyCode == 0x4c || keyCode == 0x4d || keyCode == 0x47 || keyCode == 0x48 || keyCode == 0x49 || keyCode == 0x63 || keyCode == 0x37 || keyCode == 0x4a || keyCode == 0x4e) && _numKeypadLocked))) dispatchKeyboardEvent( PS2ToADBMap[keyCode], //Dispatch of Keyboard Events /*direction*/ goingDown, /*timeStamp*/ now ); //PS2 Notification if(!goingDown && !_accidentalInputKeysException && !_keyPadKeys) _device->dispatchPS2Notification(kPS2C_EnableTouchpad); if(_accidentalInputKeysException) _accidentalInputKeysException = false; if(_keyPadKeys) _keyPadKeys = false; /*if(keyCode != 0x2a && keyCode != 0x36 && keyCode != 0x1d && keyCode != 0x60 && keyCode != 0x70 && keyCode != 0x71 && keyCode != 0x38 && keyCode != 0x61 && keyCode != 0x72 && keyCode != 0x0f && keyCode != 0x45 && keyCode != 0x6e && !(keyCode>0x3f && keyCode<0x44))*/ return true; }
bool ApplePS2Keyboard::dispatchKeyboardEventWithScancode(UInt8 scanCode) { // Parses the given scan code, updating all necessary internal state, and // should a new key be detected, the key event is dispatched. // // Returns true if a key event was indeed dispatched. DEBUG_LOG("%s: PS/2 scancode 0x%x\n", getName(), scanCode); // // See if this scan code introduces an extended key sequence. If so, note // it and then return. Next time we get a key we'll finish the sequence. // if (scanCode == kSC_Extend) { _extendCount = 1; return false; } // // See if this scan code introduces an extended key sequence for the Pause // Key. If so, note it and then return. The next time we get a key, drop // it. The next key we get after that finishes the Pause Key sequence. // // The sequence actually sent to us by the keyboard for the Pause Key is: // // 1. E1 Extended Sequence for Pause Key // 2. 1D Useless Data, with Up Bit Cleared // 3. 45 Pause Key, with Up Bit Cleared // 4. E1 Extended Sequence for Pause Key // 5. 9D Useless Data, with Up Bit Set // 6. C5 Pause Key, with Up Bit Set // // The reason items 4 through 6 are sent with the Pause Key is because the // keyboard hardware never generates a release code for the Pause Key and // the designers are being smart about it. The sequence above translates // to this parser as two separate events, as it should be -- one down key // event and one up key event (for the Pause Key). // if (scanCode == kSC_Pause) { _extendCount = 2; return false; } unsigned keyCodeRaw = scanCode & ~kSC_UpBit; unsigned keyCode; uint64_t now; clock_get_uptime(&now); // // Convert the scan code into a key code index. // // From "The Undocumented PC" chapter 8, The Keyboard System some // keyboard scan codes are single byte, some are multi-byte. // Scancodes from running showkey -s (under Linux) for extra keys on keyboard // Refer to the conversion table in defaultKeymapOfLength // and the conversion table in ApplePS2ToADBMap.h. // if (_extendCount == 0) { // LANG1(Hangul) and LANG2(Hanja) make one event only when the key was pressed. // Make key-down and key-up event ADB event if (scanCode == 0xf2 || scanCode == 0xf1) { clock_get_uptime(&now); dispatchKeyboardEvent( PS2ToADBMap[scanCode], true, *((AbsoluteTime*)&now) ); clock_get_uptime(&now); dispatchKeyboardEvent( PS2ToADBMap[scanCode], false, *((AbsoluteTime*)&now) ); return true; } // Allow PS2 -> PS2 map to work, look in normal part of the table keyCode = _PS2ToPS2Map[keyCodeRaw]; #ifdef DEBUG_MSG if (keyCode != keyCodeRaw) DEBUG_LOG("%s: keycode translated from=0x%02x to=0x%04x\n", getName(), keyCodeRaw, keyCode); #endif } else { // ignore incoming scan codes until extend count is zero if (--_extendCount) return false; // allow PS2 -> PS2 map to work, look in extended part of the table keyCodeRaw += KBV_NUM_SCANCODES; keyCode = _PS2ToPS2Map[keyCodeRaw]; #ifdef DEBUG_MSG if (keyCode != keyCodeRaw) DEBUG_LOG("%s: keycode translated from=0xe0%02x to=0x%04x\n", getName(), keyCodeRaw, keyCode); #endif // handle special cases switch (keyCodeRaw) { case 0x012a: // header or trailer for PrintScreen return false; } } // handle special cases switch (keyCode) { case 0x0153: // delete // check for Ctrl+Alt+Delete? (three finger salute) if (KBV_IS_KEYDOWN(0x1d, _keyBitVector) && KBV_IS_KEYDOWN(0x38, _keyBitVector)) { keyCode = 0; if (scanCode & kSC_UpBit) { // Note: If OS X thinks the Command and Control keys are down at the time of // receiving an ADB 0x7f (power button), it will unconditionaly and unsafely // reboot the computer, much like the old PC/AT Ctrl+Alt+Delete! // That's why we make sure Control (0x3b) and Alt (0x37) are up!! dispatchKeyboardEvent(0x37, false, now); dispatchKeyboardEvent(0x3b, false, now); dispatchKeyboardEvent(0x7f, true, now); dispatchKeyboardEvent(0x7f, false, now); } } break; case 0x015f: // sleep // This code relies on the keyboard sending repeats... If not, it won't // invoke sleep until after time has expired and we get the keyup! keyCode = 0; if (!KBV_IS_KEYDOWN(keyCodeRaw, _keyBitVector)) sleeppressedtime = now; if (now-sleeppressedtime >= maxsleeppresstime) { IOPMrootDomain* rootDomain = getPMRootDomain(); if (NULL != rootDomain) rootDomain->receivePowerNotification(kIOPMSleepNow); } break; case 0x0137: // trackpad on/off keyCode = 0; if (!(scanCode & kSC_UpBit)) { // get current enabled status, and toggle it bool enabled; _device->dispatchMouseMessage(kPS2M_getDisableTouchpad, &enabled); enabled = !enabled; _device->dispatchMouseMessage(kPS2M_setDisableTouchpad, &enabled); } break; } // Update our key bit vector, which maintains the up/down status of all keys. bool goingDown = !(scanCode & kSC_UpBit); if (goingDown) { // discard if auto-repeated key if (KBV_IS_KEYDOWN(keyCodeRaw, _keyBitVector)) return false; KBV_KEYDOWN(keyCodeRaw, _keyBitVector); } else { KBV_KEYUP(keyCodeRaw, _keyBitVector); } #ifdef DEBUG // allow hold Alt+numpad keys to type in arbitrary ADB key code static int genADB = -1; if (KBV_IS_KEYDOWN(0x38, _keyBitVector) && keyCodeRaw >= 0x47 && keyCodeRaw <= 0x52) { if (!KBV_IS_KEYDOWN(keyCodeRaw, _keyBitVector)) { // map numpad scan codes to digits static int map[0x52-0x47+1] = { 7, 8, 9, -1, 4, 5, 6, -1, 1, 2, 3, 0 }; if (-1 == genADB) genADB = 0; int digit = map[keyCodeRaw-0x47]; if (-1 != digit) genADB = genADB * 10 + digit; DEBUG_LOG("%s: genADB = %d\n", getName(), genADB); } keyCode = 0; // eat it } #endif // We have a valid key event -- dispatch it to our superclass. // map scan code to Apple code UInt8 adbKeyCode = _PS2ToADBMap[keyCode]; #ifdef DEBUG_MSG if (adbKeyCode == DEADKEY && 0 != keyCode) IOLog("%s: Unknown ADB key for PS2 scancode: 0x%x\n", getName(), scanCode); else IOLog("%s: ADB key code 0x%x %s\n", getName(), adbKeyCode, goingDown?"down":"up"); #endif // allow mouse/trackpad driver to have time of last keyboard activity // used to implement "PalmNoAction When Typing" and "OutsizeZoneNoAction When Typing" PS2KeyInfo info; info.time = now; info.adbKeyCode = adbKeyCode; info.goingDown = goingDown; _device->dispatchMouseMessage(kPS2M_notifyKeyPressed, &info); // dispatch to HID system dispatchKeyboardEvent(adbKeyCode, goingDown, now); #ifdef DEBUG if (0x38 == keyCode && !goingDown && -1 != genADB) // Alt going up { // dispatch typed adb code dispatchKeyboardEvent(genADB, true, now); dispatchKeyboardEvent(genADB, false, now); DEBUG_LOG("%s: sending typed ADB code 0x%x\n", getName(), genADB); genADB = -1; } #endif return true; }