Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 79675)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 79676)
@@ -17582,5 +17582,5 @@
   <interface
     name="IKeyboard" extends="$unknown"
-    uuid="a7c88b82-2330-44e3-b247-1421a018f9c1"
+    uuid="755e6bdf-1640-41f9-bd74-3ef5fd653250"
     wsmap="managed"
     reservedMethods="4" reservedAttributes="4"
@@ -17645,4 +17645,18 @@
 
       </desc>
+    </method>
+
+    <method name="putUsageCode">
+      <desc>Sends a USB HID usage code and page to the keyboard. The
+        keyRelease flag is set when the key is being released.
+
+        <result name="VBOX_E_IPRT_ERROR">
+          Could not send usage code to virtual keyboard.
+        </result>
+
+      </desc>
+      <param name="usageCode" type="long" dir="in"/>
+      <param name="usagePage" type="long" dir="in"/>
+      <param name="keyRelease" type="boolean" dir="in"/>
     </method>
 
Index: /trunk/src/VBox/Main/include/KeyboardImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/KeyboardImpl.h	(revision 79675)
+++ /trunk/src/VBox/Main/include/KeyboardImpl.h	(revision 79676)
@@ -77,4 +77,5 @@
     HRESULT putCAD();
     HRESULT releaseKeys();
+    HRESULT putUsageCode(LONG aUsageCode, LONG aUsagePage, BOOL fKeyRelease);
 
     static DECLCALLBACK(void)   i_keyboardLedStatusChange(PPDMIKEYBOARDCONNECTOR pInterface, PDMKEYBLEDS enmLeds);
Index: /trunk/src/VBox/Main/src-client/KeyboardImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/KeyboardImpl.cpp	(revision 79675)
+++ /trunk/src/VBox/Main/src-client/KeyboardImpl.cpp	(revision 79676)
@@ -218,4 +218,47 @@
         return setErrorBoth(VBOX_E_IPRT_ERROR, vrc,
                             tr("Could not send all scan codes to the virtual keyboard (%Rrc)"),
+                            vrc);
+
+    return S_OK;
+}
+
+/**
+ * Sends a HID usage code and page to the keyboard.
+ *
+ * @returns COM status code
+ * @param aUsageCode    The HID usage code to send
+ * @param aUsagePage    The HID usage page corresponding to the code
+ * @param fKeyRelease   The key release flag
+ */
+HRESULT Keyboard::putUsageCode(LONG aUsageCode, LONG aUsagePage, BOOL fKeyRelease)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    CHECK_CONSOLE_DRV(mpDrv[0]);
+
+    /* Send input to the last enabled device. Relies on the fact that
+     * the USB keyboard is always initialized after the PS/2 keyboard.
+     */
+    PPDMIKEYBOARDPORT pUpPort = NULL;
+    for (int i = KEYBOARD_MAX_DEVICES - 1; i >= 0 ; --i)
+    {
+        if (mpDrv[i] && (mpDrv[i]->u32DevCaps & KEYBOARD_DEVCAP_ENABLED))
+        {
+            pUpPort = mpDrv[i]->pUpPort;
+            break;
+        }
+    }
+
+    /* No enabled keyboard - throw the input away. */
+    if (!pUpPort)
+        return S_OK;
+
+    int vrc = VINF_SUCCESS;
+    uint32_t u32Usage;
+    u32Usage = (uint8_t)aUsageCode | ((uint32_t)(uint8_t)aUsagePage << 16) | fKeyRelease ? 0x80000000 : 0;
+    vrc = pUpPort->pfnPutEventHid(pUpPort, u32Usage);
+    if (RT_FAILURE(vrc))
+        return setErrorBoth(VBOX_E_IPRT_ERROR, vrc,
+                            tr("Could not send usage code to the virtual keyboard (%Rrc)"),
                             vrc);
 
