From 9d67f74bd2c9e66667e0e0aafa55eb2b99606d43 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Thu, 16 Jun 2016 15:43:04 +0200 Subject: [PATCH] Automated 'usb_hid' test When run with the '--autopilot' run option, the 'usb_hid.run' script tests the input events generated by a 'Pro Micro' microcontroller board. Setup instructions for the Pro Micro can be found in the run script. Fixes #2087 --- repos/dde_linux/run/usb_hid.run | 95 ++++++++++++++++++++++++++++++++- repos/os/src/test/input/test.cc | 86 +++++++++++++++++++---------- tool/autopilot.list | 1 + 3 files changed, 152 insertions(+), 30 deletions(-) diff --git a/repos/dde_linux/run/usb_hid.run b/repos/dde_linux/run/usb_hid.run index 9f8d392e40..3cf0e6a5df 100644 --- a/repos/dde_linux/run/usb_hid.run +++ b/repos/dde_linux/run/usb_hid.run @@ -1,3 +1,58 @@ +# +# USB HID test +# +# By default, the run script runs interactively and reports any received USB +# input events to the console. +# +# When run with the '--autopilot' run option, the run script tests the USB +# input events generated by a 'Pro Micro' microcontroller. +# +# Pro Micro setup instructions +# ---------------------------- +# +# Install prerequisites (example for Xubuntu 16.04): +# +# $ sudo apt-get install gcc-avr avr-libc avrdude +# +# Checkout and build the microcontroller software: +# +# $ git clone https://github.com/cproc/lufa.git +# $ cd lufa +# $ git checkout genode_usb_tests +# $ cd Demos/Device/ClassDriver/KeyboardMouseGenode +# $ make +# +# Connect the 'RST' pin with the 'GND' pin to hold the Pro Micro in the reset +# state. +# +# Connect the Pro Micro to the host PC +# +# Check the device file name with 'dmesg'. If it is not 'ttyACM0', change +# 'AVRDUDE_PORT' in 'makefile' accordingly. +# +# Release the RST/GND pin connection and within the next 8 seconds run: +# +# $ make avrdude +# +# Disconnect the Pro Micro or put it into reset state again to avoid unexpected +# input events on the host PC. +# + +if { [have_spec linux] } { + puts "Run script does not support Linux." + exit 0 +} + +if { [get_cmd_switch --autopilot] && [have_include "power_on/qemu"] } { + puts "Run script does not support autopilot mode on Qemu" + exit 0 +} + +if { [get_cmd_switch --autopilot] && ![have_spec x86] } { + puts "Run script is only supported in autopilot mode on x86 platforms" + exit 0 +} + # # Build # @@ -85,5 +140,43 @@ build_boot_image $boot_modules append qemu_args " -m 256 -usb -usbdevice mouse -usbdevice keyboard" append qemu_args " -device usb-ehci,id=ehci" +if { [have_include "power_on/qemu"] || ![get_cmd_switch --autopilot] } { run_genode_until forever } -run_genode_until forever +# autopilot test + +run_genode_until {\[init -\> test-input\] Input event #1\t} 60 + +# remove everything before the first interesting line +regexp {(\[init -\> test-input\] Input event #1\t.*)} $output all output + +run_genode_until {\[init -\> test-input\] Input event #12.*\n} 40 [output_spawn_id] + +unify_output { number [0-9]+} "" +unify_output {(?n)on usb-dummy.*$} "" +unify_output {(?n)using .*$} "" +unify_output {(?n)^.*__wait_event.*$} "" +unify_output {(?n)^.*Failed to submit URB.*$} "" +unify_output {(?n)^.*dev_warn.*$} "" +filter_out_color_escape_sequences +trim_lines + +compare_output_to { +[init -> test-input] Input event #1 type=PRESS code=45 rx=0 ry=0 ax=0 ay=0 key_cnt=1 KEY_X +[init -> test-input] Input event #2 type=RELEASE code=45 rx=0 ry=0 ax=0 ay=0 key_cnt=-1 KEY_X +[init -> test-input] Input event #3 type=PRESS code=272 rx=0 ry=0 ax=0 ay=0 key_cnt=1 BTN_LEFT +[init -> test-input] Input event #4 type=MOTION code=0 rx=-1 ry=0 ax=0 ay=0 key_cnt=1 +[init -> test-input] Input event #5 type=MOTION code=0 rx=0 ry=1 ax=0 ay=0 key_cnt=1 +[init -> test-input] Input event #6 type=RELEASE code=272 rx=0 ry=0 ax=0 ay=0 key_cnt=-1 BTN_LEFT +[init -> usb_drv] dev_info: USB disconnect, device +[init -> usb_drv] dev_info: new full-speed USB device +[init -> usb_drv] dev_info: D L +[init -> usb_drv] dev_info: input: USB HID v1.11 Keyboard [D L] +[init -> usb_drv] dev_info: D L +[init -> usb_drv] dev_info: input: USB HID v1.11 Mouse [D L] +[init -> test-input] Input event #7 type=PRESS code=45 rx=0 ry=0 ax=0 ay=0 key_cnt=1 KEY_X +[init -> test-input] Input event #8 type=RELEASE code=45 rx=0 ry=0 ax=0 ay=0 key_cnt=-1 KEY_X +[init -> test-input] Input event #9 type=PRESS code=272 rx=0 ry=0 ax=0 ay=0 key_cnt=1 BTN_LEFT +[init -> test-input] Input event #10 type=MOTION code=0 rx=-1 ry=0 ax=0 ay=0 key_cnt=1 +[init -> test-input] Input event #11 type=MOTION code=0 rx=0 ry=1 ax=0 ay=0 key_cnt=1 +[init -> test-input] Input event #12 type=RELEASE code=272 rx=0 ry=0 ax=0 ay=0 key_cnt=-1 BTN_LEFT +} diff --git a/repos/os/src/test/input/test.cc b/repos/os/src/test/input/test.cc index 248e069020..6a4de9065a 100644 --- a/repos/os/src/test/input/test.cc +++ b/repos/os/src/test/input/test.cc @@ -5,12 +5,13 @@ */ /* - * Copyright (C) 2010-2013 Genode Labs GmbH + * Copyright (C) 2010-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ +#include #include #include #include @@ -46,46 +47,73 @@ static char const * key_name(Input::Event *ev) } -int main(int argc, char **argv) +class Test_environment { - /* - * Init sessions to the required external services - */ - static Input::Connection input; - static Timer::Connection timer; + private: - log("--- Input test is up ---"); + Genode::Env &_env; - Input::Event *ev_buf = (env()->rm_session()->attach(input.dataspace())); + Input::Connection _input; - log("input buffer at ", ev_buf); + Input::Event *_ev_buf = { _env.rm().attach(_input.dataspace()) }; + Genode::Signal_handler _input_sigh; + + unsigned int event_count = 0; + + void _handle_input(); + + public: + + Test_environment(Genode::Env &env) + : _env(env), + _input_sigh(env.ep(), *this, &Test_environment::_handle_input) + { + log("--- Input test is up ---"); + + log("input buffer at ", _ev_buf); + + _input.sigh(_input_sigh); + } +}; + + +void Test_environment::_handle_input() +{ /* * Handle input events */ int key_cnt = 0; - while (1) { - /* poll input service every 20 ms */ - while (!input.pending()) timer.msleep(20); - for (int i = 0, num_ev = input.flush(); i < num_ev; ++i) { + for (int i = 0, num_ev = _input.flush(); i < num_ev; ++i) { - Input::Event *ev = &ev_buf[i]; + event_count++; - if (ev->type() == Input::Event::PRESS) key_cnt++; - if (ev->type() == Input::Event::RELEASE) key_cnt--; + Input::Event *ev = &_ev_buf[i]; - /* log event */ - log("Input event " - "type=", ev_type(ev->type()), "\t" - "code=", ev->code(), "\t" - "rx=", ev->rx(), "\t" - "ry=", ev->ry(), "\t" - "ax=", ev->ax(), "\t" - "ay=", ev->ay(), "\t" - "key_cnt=", key_cnt, "\t", key_name(ev)); - } + if (ev->type() == Input::Event::PRESS) key_cnt++; + if (ev->type() == Input::Event::RELEASE) key_cnt--; + + /* log event */ + log("Input event #", event_count, "\t" + "type=", ev_type(ev->type()), "\t" + "code=", ev->code(), "\t" + "rx=", ev->rx(), "\t" + "ry=", ev->ry(), "\t" + "ax=", ev->ax(), "\t" + "ay=", ev->ay(), "\t" + "key_cnt=", key_cnt, "\t", key_name(ev)); } - - return 0; } + +void Component::construct(Genode::Env &env) +{ + using namespace Genode; + + log("--- Test input ---\n"); + static Test_environment te(env); +} + + +Genode::size_t Component::stack_size() { + return 4*1024*sizeof(long); } diff --git a/tool/autopilot.list b/tool/autopilot.list index 511293e22e..1642086d61 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -70,3 +70,4 @@ ds_ownership fs_log cpu_sampler cpu_sampler_noux +usb_hid