diff --git a/ports/src/vancouver/console.cc b/ports/src/vancouver/console.cc index afabdbaa0e..3d619c2736 100644 --- a/ports/src/vancouver/console.cc +++ b/ports/src/vancouver/console.cc @@ -1,6 +1,7 @@ /* * \brief Manager of all VM requested console functionality * \author Markus Partheymueller + * \author Norman Feske * \date 2012-07-31 */ @@ -24,6 +25,7 @@ /* Genode includes */ #include +#include /* nitpicker graphics backend */ #include @@ -40,39 +42,73 @@ using Genode::Dataspace_client; bool fb_active = true; -static unsigned mouse_value(Input::Event * ev) +/** + * Layout of PS/2 mouse packet + */ +struct Ps2_mouse_packet : Genode::Register<32> { - /* bit 3 is always set */ - unsigned ret = 0x8; + struct Packet_size : Bitfield<0, 3> { }; + struct Left_button : Bitfield<8, 1> { }; + struct Middle_button : Bitfield<9, 1> { }; + struct Right_button : Bitfield<10, 1> { }; + struct Rx_high : Bitfield<12, 1> { }; + struct Ry_high : Bitfield<13, 1> { }; + struct Rx_low : Bitfield<16, 8> { }; + struct Ry_low : Bitfield<24, 8> { }; +}; - /* signs and movements */ - int x=0, y=0; - if (ev->rx() > 0) x = 1; - if (ev->rx() < 0) x = -1; - if (ev->ry() > 0) y = 1; - if (ev->ry() < 0) y = -1; - if (x > 0) - ret |= (1 << 8); - if (x < 0) - ret |= (0xfe << 8) | (1 << 4); - if (y < 0) /* nitpicker's negative is PS2 positive */ - ret |= (1 << 16); - if (y > 0) - ret |= (0xfe << 16) | (1 << 5); +static bool is_mouse_event(Input::Event const *ev) +{ + using Input::Event; + if (ev->type() == Event::PRESS || ev->type() == Event::RELEASE) { + if (ev->code() == Input::BTN_LEFT) return true; + if (ev->code() == Input::BTN_MIDDLE) return true; + if (ev->code() == Input::BTN_RIGHT) return true; + } - /* buttons */ - ret |= ((ev->code() == Input::BTN_MIDDLE ? 1 : 0) << 2); - ret |= ((ev->code() == Input::BTN_RIGHT ? 1 : 0) << 1); - ret |= ((ev->code() == Input::BTN_LEFT ? 1 : 0) << 0); + if (ev->type() == Event::MOTION) + return true; - /* ps2mouse model expects 3 in the first byte */ - return (ret << 8) | 0x3; + return false; } -/* - * Console implementation + +/** + * Convert Genode::Input event to PS/2 packet + * + * This function updates _left, _middle, and _right as a side effect. */ +unsigned Vancouver_console::_input_to_ps2mouse(Input::Event const *ev) +{ + /* track state of mouse buttons */ + using Input::Event; + if (ev->type() == Event::PRESS || ev->type() == Event::RELEASE) { + bool const pressed = ev->type() == Event::PRESS; + if (ev->code() == Input::BTN_LEFT) _left = pressed; + if (ev->code() == Input::BTN_MIDDLE) _middle = pressed; + if (ev->code() == Input::BTN_RIGHT) _right = pressed; + } + + /* clamp relative motion vector to bounds */ + int const boundary = 200; + int const rx = min(boundary, max(-boundary, ev->rx())); + int const ry = -min(boundary, max(-boundary, ev->ry())); + + /* assemble PS/2 packet */ + Ps2_mouse_packet::access_t packet = 0; + Ps2_mouse_packet::Packet_size::set (packet, 3); + Ps2_mouse_packet::Left_button::set (packet, _left); + Ps2_mouse_packet::Middle_button::set(packet, _middle); + Ps2_mouse_packet::Right_button::set (packet, _right); + Ps2_mouse_packet::Rx_high::set (packet, (rx >> 8) & 1); + Ps2_mouse_packet::Ry_high::set (packet, (ry >> 8) & 1); + Ps2_mouse_packet::Rx_low::set (packet, rx & 0xff); + Ps2_mouse_packet::Ry_low::set (packet, ry & 0xff); + + return packet; +} + /* bus callbacks */ @@ -263,16 +299,17 @@ void Vancouver_console::entry() } framebuffer.refresh(0, 0, _fb_mode.width(), _fb_mode.height()); - timer.msleep(100); + timer.msleep(10); } for (int i = 0, num_ev = input.flush(); i < num_ev; i++) { Input::Event *ev = &ev_buf[i]; /* update mouse model (PS2) */ - unsigned mouse = mouse_value(ev); - MessageInput msg(0x10001, mouse); - _motherboard()->bus_input.send(msg); + if (is_mouse_event(ev)) { + MessageInput msg(0x10001, _input_to_ps2mouse(ev)); + _motherboard()->bus_input.send(msg); + } if (ev->type() == Input::Event::PRESS) { if (ev->code() <= 0xee) { @@ -304,7 +341,8 @@ Vancouver_console::Vancouver_console(Synced_motherboard &mb, _startup_lock(Genode::Lock::LOCKED), _vm_fb_size(vm_fb_size), _motherboard(mb), _console_lock(console_lock), _fb_size(0), _pixels(0), _guest_fb(0), - _regs(0), _fb_ds(fb_ds) + _regs(0), _fb_ds(fb_ds), + _left(false), _middle(false), _right(false) { start(); diff --git a/ports/src/vancouver/console.h b/ports/src/vancouver/console.h index f11970c903..d1a7ca60ee 100644 --- a/ports/src/vancouver/console.h +++ b/ports/src/vancouver/console.h @@ -56,6 +56,9 @@ class Vancouver_console : public Thread<8192>, public StaticReceiver