Example #1
0
/* 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;
}
Example #2
0
/* 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;
}