diff --git a/repos/ports/run/vbox_win.inc b/repos/ports/run/vbox_win.inc index c56434050..7e672adec 100644 --- a/repos/ports/run/vbox_win.inc +++ b/repos/ports/run/vbox_win.inc @@ -242,6 +242,16 @@ for { set i 1} { $i <= $use_vms } { incr i} { } append config_of_app { + + + + + + + + + + @@ -261,11 +271,11 @@ for { set i 1} { $i <= $use_vms } { incr i} { } if { $use_vms eq 1 } { append config_of_app " - " + " } else { append config_of_app " - " + " } append config_of_app { @@ -307,6 +317,7 @@ for { set i 1} { $i <= $use_vms } { incr i} { append config_of_app { + } diff --git a/repos/ports/src/virtualbox/README b/repos/ports/src/virtualbox/README index 7ec2f238a..eec7691b6 100644 --- a/repos/ports/src/virtualbox/README +++ b/repos/ports/src/virtualbox/README @@ -1,6 +1,11 @@ VirtualBox configuration options ################################ +The configuration requires an attribute named vbox_file with the name of the +vbox configuration to be used (.vbox). + + + XHCI controller =============== @@ -22,3 +27,12 @@ methods (for example Genode/NOVA), the configuration option enforces the delivery of PCI IRQs to the IOAPIC. +CAPSLOCK +======== + + + +If the capslock attribute is set to "ROM", virtualbox will open a connection +to the ROM named "capslock" and expect in the top-level node a attribute +'enabled' (yes|no). If the ROM capslock differ from the internal VM capslock, +the VMM will trigger aritifical capslock key events to the VM. diff --git a/repos/ports/src/virtualbox/frontend/console.cc b/repos/ports/src/virtualbox/frontend/console.cc index 818b6f210..907ec0297 100644 --- a/repos/ports/src/virtualbox/frontend/console.cc +++ b/repos/ports/src/virtualbox/frontend/console.cc @@ -106,7 +106,6 @@ HRESULT Console::setDiskEncryptionKeys(const Utf8Str &strCfg) void Console::onAdditionsOutdated() DUMMY() -void Console::onKeyboardLedsChange(bool, bool, bool) TRACE() HRESULT Console::onVideoCaptureChange() DUMMY(E_FAIL) HRESULT Console::onSharedFolderChange(BOOL aGlobal) DUMMY(E_FAIL) HRESULT Console::onUSBControllerChange() DUMMY(E_FAIL) @@ -567,3 +566,46 @@ int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient) return VINF_SUCCESS; } + +/** + * Sticky key handling + */ +static bool host_caps_lock = false; +static bool guest_caps_lock = false; + +void Console::onKeyboardLedsChange(bool num_lock, bool caps_lock, bool scroll_lock) +{ + guest_caps_lock = caps_lock; +} + +void GenodeConsole::handle_sticky_keys() +{ + /* no keyboard - no sticky key handling */ + if (!_vbox_keyboard || !_caps_lock.constructed()) + return; + + _caps_lock->update(); + + if (!_caps_lock->valid()) + return; + + bool const caps_lock = _caps_lock->xml().attribute_value("enabled", + guest_caps_lock); + bool trigger_caps_lock = false; + + /* + * If guest didn't respond with led change last time, we have to + * trigger caps_lock change - mainly assuming that guest don't use the + * led to externalize its internal caps_lock state. + */ + if (caps_lock != host_caps_lock && host_caps_lock != guest_caps_lock) + trigger_caps_lock = true; + + if (caps_lock != guest_caps_lock) + trigger_caps_lock = true; + + if (trigger_caps_lock) { + _vbox_keyboard->PutScancode(Input::KEY_CAPSLOCK); + _vbox_keyboard->PutScancode(Input::KEY_CAPSLOCK | 0x80); + } +} diff --git a/repos/ports/src/virtualbox/frontend/console.h b/repos/ports/src/virtualbox/frontend/console.h index f05f28de4..6e53e8d56 100644 --- a/repos/ports/src/virtualbox/frontend/console.h +++ b/repos/ports/src/virtualbox/frontend/console.h @@ -116,6 +116,7 @@ class GenodeConsole : public Console { bool _last_received_motion_event_was_absolute; Report::Connection _shape_report_connection; Genode::Attached_dataspace _shape_report_ds; + Genode::Constructible _caps_lock; Vbox_pointer::Shape_report *_shape_report; Genode::Reporter *_clipboard_reporter; Genode::Attached_rom_dataspace *_clipboard_rom; @@ -124,6 +125,7 @@ class GenodeConsole : public Console { Genode::Signal_handler _input_signal_dispatcher; Genode::Signal_handler _mode_change_signal_dispatcher; Genode::Signal_handler _clipboard_signal_dispatcher; + Genode::Signal_handler _input_sticky_keys_dispatcher; bool _key_status[Input::KEY_MAX + 1]; @@ -152,12 +154,22 @@ class GenodeConsole : public Console { _vbox_mouse(0), _input_signal_dispatcher(genode_env().ep(), *this, &GenodeConsole::handle_input), _mode_change_signal_dispatcher(genode_env().ep(), *this, &GenodeConsole::handle_mode_change), - _clipboard_signal_dispatcher(genode_env().ep(), *this, &GenodeConsole::handle_cb_rom_change) + _clipboard_signal_dispatcher(genode_env().ep(), *this, &GenodeConsole::handle_cb_rom_change), + _input_sticky_keys_dispatcher(genode_env().ep(), *this, &GenodeConsole::handle_sticky_keys) { for (unsigned i = 0; i <= Input::KEY_MAX; i++) _key_status[i] = 0; _input.sigh(_input_signal_dispatcher); + + Genode::Attached_rom_dataspace config(genode_env(), "config"); + + /* by default we take the capslock key from the input stream */ + Genode::String<10> capslock("input"); + if (config.xml().attribute_value("capslock", capslock) == "ROM") { + _caps_lock.construct(genode_env(), "capslock"); + _caps_lock->sigh(_input_sticky_keys_dispatcher); + } } void init_clipboard(); @@ -231,4 +243,5 @@ class GenodeConsole : public Console { void handle_input(); void handle_mode_change(); void handle_cb_rom_change(); + void handle_sticky_keys(); }; diff --git a/repos/ports/src/virtualbox5/README b/repos/ports/src/virtualbox5/README new file mode 100644 index 000000000..eec7691b6 --- /dev/null +++ b/repos/ports/src/virtualbox5/README @@ -0,0 +1,38 @@ +VirtualBox configuration options +################################ + +The configuration requires an attribute named vbox_file with the name of the +vbox configuration to be used (.vbox). + + + +XHCI controller +=============== + +The virtual XHCI controller can be enabled with the following +configuration option: + + + +IOAPIC +====== + +The virtual PCI model delivers IRQs to the PIC by default and to the IOAPIC +only if the guest operating system selected the IOAPIC with the '_PIC' ACPI +method and if it called the '_PRT' ACPI method afterwards. When running a +guest operating system which uses the IOAPIC, but does not call these ACPI +methods (for example Genode/NOVA), the configuration option + + + +enforces the delivery of PCI IRQs to the IOAPIC. + +CAPSLOCK +======== + + + +If the capslock attribute is set to "ROM", virtualbox will open a connection +to the ROM named "capslock" and expect in the top-level node a attribute +'enabled' (yes|no). If the ROM capslock differ from the internal VM capslock, +the VMM will trigger aritifical capslock key events to the VM. diff --git a/repos/ports/src/virtualbox5/frontend/VBoxEvents.h b/repos/ports/src/virtualbox5/frontend/VBoxEvents.h index 86b9c22ee..10780b630 100644 --- a/repos/ports/src/virtualbox5/frontend/VBoxEvents.h +++ b/repos/ports/src/virtualbox5/frontend/VBoxEvents.h @@ -5,6 +5,9 @@ void fireStateChangedEvent(IEventSource* aSource, MachineState_T a_state); void fireRuntimeErrorEvent(IEventSource* aSource, BOOL a_fatal, CBSTR a_id, CBSTR a_message); +void fireKeyboardLedsChangedEvent(IEventSource *aSource, bool fNumLock, + bool fCapsLock, bool fScrollLock); + #define fireAdditionsStateChangedEvent(a) #define fireBandwidthGroupChangedEvent(a, b) @@ -23,8 +26,6 @@ void fireRuntimeErrorEvent(IEventSource* aSource, BOOL a_fatal, CBSTR a_id, #define fireHostNameResolutionConfigurationChangeEvent(a) #define fireHostPCIDevicePlugEvent(a, b, c, d, e, f) -#define fireKeyboardLedsChangedEvent(a, b, c, d) - #define fireMediumChangedEvent(a, b) #define fireMousePointerShapeChangedEvent(a, b, c, d, e, f, g, h) #define fireMouseCapabilityChangedEvent(a, b, c, d, e) diff --git a/repos/ports/src/virtualbox5/frontend/console.cc b/repos/ports/src/virtualbox5/frontend/console.cc index d903b0fa7..a033f12a1 100644 --- a/repos/ports/src/virtualbox5/frontend/console.cc +++ b/repos/ports/src/virtualbox5/frontend/console.cc @@ -519,3 +519,51 @@ int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient) return VINF_SUCCESS; } + +/** + * Sticky key handling + */ +static bool host_caps_lock = false; +static bool guest_caps_lock = false; + +void fireKeyboardLedsChangedEvent(IEventSource *, bool num_lock, + bool caps_lock, bool scroll_lock) +{ + guest_caps_lock = caps_lock; +} + +void GenodeConsole::handle_sticky_keys() +{ + /* no keyboard - no sticky key handling */ + if (!_vbox_keyboard || !_caps_lock.constructed()) + return; + + _caps_lock->update(); + + if (!_caps_lock->valid()) + return; + + bool const caps_lock = _caps_lock->xml().attribute_value("enabled", + guest_caps_lock); + + bool trigger_caps_lock = false; + + /* + * If guest didn't respond with led change last time, we have to + * trigger caps_lock change - mainly assuming that guest don't use the + * led to externalize its internal caps_lock state. + */ + if (caps_lock != host_caps_lock && host_caps_lock != guest_caps_lock) + trigger_caps_lock = true; + + if (caps_lock != guest_caps_lock) + trigger_caps_lock = true; + + /* remember last seen host caps lock state */ + host_caps_lock = caps_lock; + + if (trigger_caps_lock) { + _vbox_keyboard->PutScancode(Input::KEY_CAPSLOCK); + _vbox_keyboard->PutScancode(Input::KEY_CAPSLOCK | 0x80); + } +} diff --git a/repos/ports/src/virtualbox5/frontend/console.h b/repos/ports/src/virtualbox5/frontend/console.h index 1f6162178..a2234b0e8 100644 --- a/repos/ports/src/virtualbox5/frontend/console.h +++ b/repos/ports/src/virtualbox5/frontend/console.h @@ -116,6 +116,7 @@ class GenodeConsole : public Console { bool _last_received_motion_event_was_absolute; Report::Connection _shape_report_connection; Genode::Attached_dataspace _shape_report_ds; + Genode::Constructible _caps_lock; Vbox_pointer::Shape_report *_shape_report; Genode::Reporter *_clipboard_reporter; Genode::Attached_rom_dataspace *_clipboard_rom; @@ -124,6 +125,7 @@ class GenodeConsole : public Console { Genode::Signal_handler _input_signal_dispatcher; Genode::Signal_handler _mode_change_signal_dispatcher; Genode::Signal_handler _clipboard_signal_dispatcher; + Genode::Signal_handler _input_sticky_keys_dispatcher; bool _key_status[Input::KEY_MAX + 1]; @@ -152,12 +154,22 @@ class GenodeConsole : public Console { _vbox_mouse(0), _input_signal_dispatcher(genode_env().ep(), *this, &GenodeConsole::handle_input), _mode_change_signal_dispatcher(genode_env().ep(), *this, &GenodeConsole::handle_mode_change), - _clipboard_signal_dispatcher(genode_env().ep(), *this, &GenodeConsole::handle_cb_rom_change) + _clipboard_signal_dispatcher(genode_env().ep(), *this, &GenodeConsole::handle_cb_rom_change), + _input_sticky_keys_dispatcher(genode_env().ep(), *this, &GenodeConsole::handle_sticky_keys) { for (unsigned i = 0; i <= Input::KEY_MAX; i++) _key_status[i] = 0; _input.sigh(_input_signal_dispatcher); + + Genode::Attached_rom_dataspace config(genode_env(), "config"); + + /* by default we take the capslock key from the input stream */ + Genode::String<10> capslock("input"); + if (config.xml().attribute_value("capslock", capslock) == "ROM") { + _caps_lock.construct(genode_env(), "capslock"); + _caps_lock->sigh(_input_sticky_keys_dispatcher); + } } void init_clipboard(); @@ -231,4 +243,5 @@ class GenodeConsole : public Console { void handle_input(); void handle_mode_change(); void handle_cb_rom_change(); + void handle_sticky_keys(); };