vbox: support capslock state provided by ROM

Fixes #2568
This commit is contained in:
Alexander Boettcher 2017-11-07 15:13:10 +01:00 committed by Christian Helmuth
parent 86f269feba
commit e54ad5c73a
8 changed files with 187 additions and 7 deletions

View File

@ -242,6 +242,16 @@ for { set i 1} { $i <= $use_vms } { incr i} {
}
append config_of_app {
<rom name="capslock">
<inline>
<capslock enabled="yes"/>
</inline>
<sleep milliseconds="5000"/>
<inline>
<capslock enabled="no"/>
</inline>
<sleep milliseconds="5000"/>
</rom>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
@ -261,11 +271,11 @@ for { set i 1} { $i <= $use_vms } { incr i} {
<resource name="RAM" quantum="} $vm_ram {"/>}
if { $use_vms eq 1 } {
append config_of_app "
<config ld_verbose=\"yes\" vbox_file=\"${vbox_file}\" vm_name=\"${flavor}\" xhci=\"yes\">"
<config ld_verbose=\"yes\" vbox_file=\"${vbox_file}\" vm_name=\"${flavor}\" xhci=\"yes\" capslock=\"NOROM\">"
} else {
append config_of_app "
<affinity xpos=\"[expr $i]\" width=\"2\" />
<config ld_verbose=\"yes\" vbox_file=\"${vbox_file}\" vm_name=\"${flavor}\" xhci=\"no\">"
<config ld_verbose=\"yes\" vbox_file=\"${vbox_file}\" vm_name=\"${flavor}\" xhci=\"no\" capslock=\"NOROM\">"
}
append config_of_app {
<libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc"/>
@ -307,6 +317,7 @@ for { set i 1} { $i <= $use_vms } { incr i} {
append config_of_app {
<service name="Report"><child name="report_rom" /></service>
<service name="ROM" label="usb_devices"> <child name="report_rom" /> </service>
<service name="ROM" label="capslock"> <child name="nit_fb-config"/> </service>
<any-service> <parent/> <any-child /> </any-service>
</route>
</start>}

View File

@ -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).
<config vbox_file="file.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
========
<config capslock="ROM">
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.

View File

@ -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);
}
}

View File

@ -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<Genode::Attached_rom_dataspace> _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<GenodeConsole> _input_signal_dispatcher;
Genode::Signal_handler<GenodeConsole> _mode_change_signal_dispatcher;
Genode::Signal_handler<GenodeConsole> _clipboard_signal_dispatcher;
Genode::Signal_handler<GenodeConsole> _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();
};

View File

@ -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).
<config vbox_file="file.vbox">
XHCI controller
===============
The virtual XHCI controller can be enabled with the following
configuration option:
<config xhci="yes">
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
<config force_ioapic="yes">
enforces the delivery of PCI IRQs to the IOAPIC.
CAPSLOCK
========
<config capslock="ROM">
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.

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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<Genode::Attached_rom_dataspace> _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<GenodeConsole> _input_signal_dispatcher;
Genode::Signal_handler<GenodeConsole> _mode_change_signal_dispatcher;
Genode::Signal_handler<GenodeConsole> _clipboard_signal_dispatcher;
Genode::Signal_handler<GenodeConsole> _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();
};