mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
ps2_drv: drive mode indicator LEDs
The new feature is demonstrated by the input.run script. It uses a dynamic ROM service to toggle the keyboard LEDs at different intervals. Fixes #2546
This commit is contained in:
parent
d6a05245f2
commit
a0a7d5d165
@ -7,6 +7,7 @@ assert_spec x86
|
||||
set build_components {
|
||||
core init
|
||||
drivers/timer
|
||||
server/dynamic_rom
|
||||
test/input
|
||||
}
|
||||
|
||||
@ -59,8 +60,12 @@ append_if [have_spec ps2] config {
|
||||
<start name="ps2_drv">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides><service name="Input"/></provides>
|
||||
<config verbose_keyboard="no" verbose_mouse="no" verbose_scancodes="no"/>
|
||||
<config verbose_keyboard="no" verbose_mouse="no" verbose_scancodes="no"
|
||||
capslock_led="rom" numlock_led="rom" scrlock_led="rom"/>
|
||||
<route>
|
||||
<service name="ROM" label="capslock"> <child name="dynamic_rom"/> </service>
|
||||
<service name="ROM" label="numlock"> <child name="dynamic_rom"/> </service>
|
||||
<service name="ROM" label="scrlock"> <child name="dynamic_rom"/> </service>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
<service name="PD"> <parent/> </service>
|
||||
@ -86,6 +91,39 @@ append_if [have_spec sdl] config {
|
||||
<alias name="input_drv" child="fb_sdl"/>}
|
||||
|
||||
append config {
|
||||
|
||||
<start name="dynamic_rom">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides> <service name="ROM"/> </provides>
|
||||
<config verbose="no">
|
||||
<rom name="capslock">
|
||||
<inline> <capslock enabled="no"/> </inline>
|
||||
<sleep milliseconds="250" />
|
||||
<inline> <capslock enabled="yes"/> </inline>
|
||||
<sleep milliseconds="250" />
|
||||
</rom>
|
||||
<rom name="numlock">
|
||||
<inline> <numlock enabled="no"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
<inline> <numlock enabled="yes"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
</rom>
|
||||
<rom name="scrlock">
|
||||
<inline> <scrlock enabled="no"/> </inline>
|
||||
<sleep milliseconds="1000" />
|
||||
<inline> <scrlock enabled="yes"/> </inline>
|
||||
<sleep milliseconds="1000" />
|
||||
</rom>
|
||||
</config>
|
||||
<route>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
<service name="PD"> <parent/> </service>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
<service name="Timer"> <child name="timer"/> </service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="test-input">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<route>
|
||||
@ -110,7 +148,7 @@ install_config $config
|
||||
# generic modules
|
||||
set boot_modules {
|
||||
core ld.lib.so init
|
||||
timer
|
||||
timer dynamic_rom
|
||||
test-input
|
||||
}
|
||||
|
||||
|
20
repos/os/src/drivers/input/spec/ps2/README
Normal file
20
repos/os/src/drivers/input/spec/ps2/README
Normal file
@ -0,0 +1,20 @@
|
||||
The PS/2 driver makes PS/2 mouse and keyboard input available as an input
|
||||
session. It accepts the following configuration attributes. The default
|
||||
values are shown as attribute values.
|
||||
|
||||
! <config verbose_keyboard="no"
|
||||
! verbose_mouse="no"
|
||||
! verbose_scancodes="no"
|
||||
! capslock_led="no"
|
||||
! numlock_led="no"
|
||||
! scrlock_led="no"/>
|
||||
|
||||
The 'capslock_led', 'numlock_led', and 'scrlock_led' attributes can have the
|
||||
values "no" (LED is turned off), "yes" (LED is turned on), or "rom". In the
|
||||
latter case, the PS/2 driver reads the LED state from a dedicated ROM module
|
||||
called "capslock", "numlock", or "scrlock" respectively. The ROM module is
|
||||
expected to have a top-level XML node with the attribute 'enabled' set to
|
||||
"yes" or "no". The PS/2 driver supports dynamic updates of its configuration
|
||||
as well as the ROM modules for LED states. This mechanism enables other
|
||||
components to control the indicator states by the means of providing and
|
||||
updating those ROM modules.
|
66
repos/os/src/drivers/input/spec/ps2/led_state.h
Normal file
66
repos/os/src/drivers/input/spec/ps2/led_state.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* \brief Configuration of keyboard mode indicators
|
||||
* \author Norman Feske
|
||||
* \date 2017-10-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _DRIVERS__INPUT__SPEC__LED_STATE_H_
|
||||
#define _DRIVERS__INPUT__SPEC__LED_STATE_H_
|
||||
|
||||
#include <util/xml_node.h>
|
||||
#include <util/reconstructible.h>
|
||||
#include <base/component.h>
|
||||
|
||||
namespace Ps2 { struct Led_state; }
|
||||
|
||||
|
||||
struct Ps2::Led_state
|
||||
{
|
||||
Genode::Env &_env;
|
||||
|
||||
typedef Genode::String<32> Name;
|
||||
|
||||
Name const _name;
|
||||
|
||||
Genode::Constructible<Genode::Attached_rom_dataspace> _rom;
|
||||
|
||||
bool _enabled = false;
|
||||
|
||||
Led_state(Genode::Env &env, Name const &name) : _env(env), _name(name) { }
|
||||
|
||||
void update(Genode::Xml_node config, Genode::Signal_context_capability sigh)
|
||||
{
|
||||
typedef Genode::String<32> Attr;
|
||||
typedef Genode::String<16> Value;
|
||||
|
||||
Attr const attr(_name, "_led");
|
||||
Value const value = config.attribute_value(attr.string(), Value());
|
||||
|
||||
bool const rom_configured = (value == "rom");
|
||||
|
||||
if (rom_configured && !_rom.constructed()) {
|
||||
_rom.construct(_env, _name.string());
|
||||
_rom->sigh(sigh);
|
||||
}
|
||||
|
||||
if (!rom_configured && _rom.constructed())
|
||||
_rom.destruct();
|
||||
|
||||
if (_rom.constructed())
|
||||
_rom->update();
|
||||
|
||||
_enabled = _rom.constructed() ? _rom->xml().attribute_value("enabled", false)
|
||||
: config.attribute_value(attr.string(), false);
|
||||
}
|
||||
|
||||
bool enabled() const { return _enabled; }
|
||||
};
|
||||
|
||||
#endif /* _DRIVERS__INPUT__SPEC__LED_STATE_H_ */
|
@ -23,6 +23,7 @@
|
||||
#include "ps2_mouse.h"
|
||||
#include "irq_handler.h"
|
||||
#include "pl050.h"
|
||||
#include "led_state.h"
|
||||
|
||||
namespace Ps2 { struct Main; }
|
||||
|
||||
@ -47,16 +48,42 @@ struct Ps2::Main
|
||||
|
||||
Genode::Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
Verbose _verbose { _config.xml() };
|
||||
Genode::Reconstructible<Verbose> _verbose { _config.xml() };
|
||||
|
||||
Mouse _mouse { _pl050.aux_interface(), _session.event_queue(), _verbose };
|
||||
Keyboard _keyboard { _pl050.kbd_interface(), _session.event_queue(), false, _verbose };
|
||||
Mouse _mouse { _pl050.aux_interface(), _session.event_queue(), *_verbose };
|
||||
Keyboard _keyboard { _pl050.kbd_interface(), _session.event_queue(), false, *_verbose };
|
||||
|
||||
Irq_handler _mouse_irq { _env, PL050_MOUSE_IRQ, _pl050.aux_interface(), _mouse };
|
||||
Irq_handler _keyboard_irq { _env, PL050_KEYBD_IRQ, _pl050.kbd_interface(), _keyboard };
|
||||
|
||||
Led_state _capslock { _env, "capslock" },
|
||||
_numlock { _env, "numlock" },
|
||||
_scrlock { _env, "scrlock" };
|
||||
|
||||
void _handle_config()
|
||||
{
|
||||
_config.update();
|
||||
|
||||
Genode::Xml_node config = _config.xml();
|
||||
|
||||
_verbose.construct(config);
|
||||
|
||||
_capslock.update(config, _config_handler);
|
||||
_numlock .update(config, _config_handler);
|
||||
_scrlock .update(config, _config_handler);
|
||||
|
||||
_keyboard.led_enabled(Keyboard::CAPSLOCK_LED, _capslock.enabled());
|
||||
_keyboard.led_enabled(Keyboard::NUMLOCK_LED, _numlock .enabled());
|
||||
_keyboard.led_enabled(Keyboard::SCRLOCK_LED, _scrlock .enabled());
|
||||
}
|
||||
|
||||
Genode::Signal_handler<Main> _config_handler {
|
||||
_env.ep(), *this, &Main::_handle_config };
|
||||
|
||||
Main(Genode::Env &env) : _env(env)
|
||||
{
|
||||
_handle_config();
|
||||
|
||||
env.parent().announce(env.ep().manage(_root));
|
||||
}
|
||||
};
|
||||
|
@ -351,11 +351,33 @@ class Ps2::Keyboard : public Input_driver
|
||||
|
||||
} _scan_code_set_2_state_machine;
|
||||
|
||||
/* acknowledge code from keyboard */
|
||||
enum { ACK = 0xfa };
|
||||
|
||||
/**
|
||||
* Used keyboard-packet state machine
|
||||
*/
|
||||
Scan_code_state_machine *_state_machine;
|
||||
|
||||
bool _capslock = false;
|
||||
bool _numlock = false;
|
||||
bool _scrlock = false;
|
||||
|
||||
void _update_leds()
|
||||
{
|
||||
_kbd.write(0xed);
|
||||
if (_kbd.read() != ACK) {
|
||||
Genode::warning("setting of mode indicators failed (0xed)");
|
||||
return;
|
||||
}
|
||||
|
||||
_kbd.write((_capslock ? 4:0) | (_numlock ? 2:0) | (_scrlock ? 1:0));
|
||||
if (_kbd.read() != ACK) {
|
||||
Genode::warning("setting of mode indicators failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -387,11 +409,20 @@ class Ps2::Keyboard : public Input_driver
|
||||
: "2");
|
||||
}
|
||||
|
||||
enum Led { CAPSLOCK_LED, NUMLOCK_LED, SCRLOCK_LED };
|
||||
|
||||
void led_enabled(Led led, bool enabled)
|
||||
{
|
||||
switch (led) {
|
||||
case CAPSLOCK_LED: _capslock = enabled; break;
|
||||
case NUMLOCK_LED: _numlock = enabled; break;
|
||||
case SCRLOCK_LED: _scrlock = enabled; break;
|
||||
}
|
||||
_update_leds();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
/* acknowledge code from keyboard */
|
||||
enum { ACK = 0xfa };
|
||||
|
||||
/* scan-code request/config commands */
|
||||
enum { SCAN_CODE_REQUEST = 0, SCAN_CODE_SET_1 = 1, SCAN_CODE_SET_2 = 2 };
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "ps2_mouse.h"
|
||||
#include "irq_handler.h"
|
||||
#include "verbose.h"
|
||||
#include "led_state.h"
|
||||
|
||||
namespace Ps2 { struct Main; }
|
||||
|
||||
@ -55,18 +56,44 @@ struct Ps2::Main
|
||||
|
||||
Genode::Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
Verbose _verbose { _config.xml() };
|
||||
Genode::Reconstructible<Verbose> _verbose { _config.xml() };
|
||||
|
||||
Keyboard _keyboard { _i8042.kbd_interface(), _session.event_queue(),
|
||||
_i8042.kbd_xlate(), _verbose };
|
||||
_i8042.kbd_xlate(), *_verbose };
|
||||
|
||||
Mouse _mouse { _i8042.aux_interface(), _session.event_queue(), _verbose };
|
||||
Mouse _mouse { _i8042.aux_interface(), _session.event_queue(), *_verbose };
|
||||
|
||||
Irq_handler _keyboard_irq { _env.ep(), _keyboard, _device_ps2.irq(0) };
|
||||
Irq_handler _mouse_irq { _env.ep(), _mouse, _device_ps2.irq(1) };
|
||||
|
||||
Led_state _capslock { _env, "capslock" },
|
||||
_numlock { _env, "numlock" },
|
||||
_scrlock { _env, "scrlock" };
|
||||
|
||||
void _handle_config()
|
||||
{
|
||||
_config.update();
|
||||
|
||||
Genode::Xml_node config = _config.xml();
|
||||
|
||||
_verbose.construct(config);
|
||||
|
||||
_capslock.update(config, _config_handler);
|
||||
_numlock .update(config, _config_handler);
|
||||
_scrlock .update(config, _config_handler);
|
||||
|
||||
_keyboard.led_enabled(Keyboard::CAPSLOCK_LED, _capslock.enabled());
|
||||
_keyboard.led_enabled(Keyboard::NUMLOCK_LED, _numlock .enabled());
|
||||
_keyboard.led_enabled(Keyboard::SCRLOCK_LED, _scrlock .enabled());
|
||||
}
|
||||
|
||||
Genode::Signal_handler<Main> _config_handler {
|
||||
_env.ep(), *this, &Main::_handle_config };
|
||||
|
||||
Main(Genode::Env &env) : _env(env)
|
||||
{
|
||||
_handle_config();
|
||||
|
||||
env.parent().announce(env.ep().manage(_root));
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user