mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-02 20:16:48 +00:00
vancouver: Improved PS/2 mouse backend
The previous version of the PS/2 mouse backend manged mouse motion events in a strange way, effectively throwing away most information about the motion vector. Furthermore, the tracking of the mouse-button states were missing. So drag-and-drop in a guest OS won't work. The new version fixes those issues. For the transformation of input events to PS/2 packets, a the Genode::Register facility is used. This greatly simplifies the code.
This commit is contained in:
parent
8708732e9c
commit
33c5469b92
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Manager of all VM requested console functionality
|
* \brief Manager of all VM requested console functionality
|
||||||
* \author Markus Partheymueller
|
* \author Markus Partheymueller
|
||||||
|
* \author Norman Feske
|
||||||
* \date 2012-07-31
|
* \date 2012-07-31
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -24,6 +25,7 @@
|
|||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/snprintf.h>
|
#include <base/snprintf.h>
|
||||||
|
#include <util/register.h>
|
||||||
|
|
||||||
/* nitpicker graphics backend */
|
/* nitpicker graphics backend */
|
||||||
#include <nitpicker_gfx/chunky_canvas.h>
|
#include <nitpicker_gfx/chunky_canvas.h>
|
||||||
@ -40,39 +42,73 @@ using Genode::Dataspace_client;
|
|||||||
bool fb_active = true;
|
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 */
|
struct Packet_size : Bitfield<0, 3> { };
|
||||||
unsigned ret = 0x8;
|
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)
|
static bool is_mouse_event(Input::Event const *ev)
|
||||||
ret |= (1 << 8);
|
{
|
||||||
if (x < 0)
|
using Input::Event;
|
||||||
ret |= (0xfe << 8) | (1 << 4);
|
if (ev->type() == Event::PRESS || ev->type() == Event::RELEASE) {
|
||||||
if (y < 0) /* nitpicker's negative is PS2 positive */
|
if (ev->code() == Input::BTN_LEFT) return true;
|
||||||
ret |= (1 << 16);
|
if (ev->code() == Input::BTN_MIDDLE) return true;
|
||||||
if (y > 0)
|
if (ev->code() == Input::BTN_RIGHT) return true;
|
||||||
ret |= (0xfe << 16) | (1 << 5);
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* ps2mouse model expects 3 in the first byte */
|
|
||||||
return (ret << 8) | 0x3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (ev->type() == Event::MOTION)
|
||||||
* Console implementation
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 */
|
/* bus callbacks */
|
||||||
|
|
||||||
@ -263,16 +299,17 @@ void Vancouver_console::entry()
|
|||||||
}
|
}
|
||||||
framebuffer.refresh(0, 0, _fb_mode.width(), _fb_mode.height());
|
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++) {
|
for (int i = 0, num_ev = input.flush(); i < num_ev; i++) {
|
||||||
Input::Event *ev = &ev_buf[i];
|
Input::Event *ev = &ev_buf[i];
|
||||||
|
|
||||||
/* update mouse model (PS2) */
|
/* update mouse model (PS2) */
|
||||||
unsigned mouse = mouse_value(ev);
|
if (is_mouse_event(ev)) {
|
||||||
MessageInput msg(0x10001, mouse);
|
MessageInput msg(0x10001, _input_to_ps2mouse(ev));
|
||||||
_motherboard()->bus_input.send(msg);
|
_motherboard()->bus_input.send(msg);
|
||||||
|
}
|
||||||
|
|
||||||
if (ev->type() == Input::Event::PRESS) {
|
if (ev->type() == Input::Event::PRESS) {
|
||||||
if (ev->code() <= 0xee) {
|
if (ev->code() <= 0xee) {
|
||||||
@ -304,7 +341,8 @@ Vancouver_console::Vancouver_console(Synced_motherboard &mb,
|
|||||||
_startup_lock(Genode::Lock::LOCKED),
|
_startup_lock(Genode::Lock::LOCKED),
|
||||||
_vm_fb_size(vm_fb_size), _motherboard(mb), _console_lock(console_lock),
|
_vm_fb_size(vm_fb_size), _motherboard(mb), _console_lock(console_lock),
|
||||||
_fb_size(0), _pixels(0), _guest_fb(0),
|
_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();
|
start();
|
||||||
|
|
||||||
|
@ -56,6 +56,9 @@ class Vancouver_console : public Thread<8192>, public StaticReceiver<Vancouver_c
|
|||||||
Genode::size_t _vm_fb_size;
|
Genode::size_t _vm_fb_size;
|
||||||
VgaRegs *_regs;
|
VgaRegs *_regs;
|
||||||
Framebuffer::Mode _fb_mode;
|
Framebuffer::Mode _fb_mode;
|
||||||
|
bool _left, _middle, _right;
|
||||||
|
|
||||||
|
unsigned _input_to_ps2mouse(Input::Event const *);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user