| /* |
| * |
| * Copyright (C) 2017 Patrick Rudolph <siro@das-labor.org> |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| */ |
| |
| #include <libpayload-config.h> |
| #include <libpayload.h> |
| #include <usb/usb.h> |
| |
| static struct mouse_cursor_input_driver *cursor_in; |
| |
| static int |
| mouse_cursor_driver_exists(const struct mouse_cursor_input_driver *const in) |
| { |
| struct mouse_cursor_input_driver *head = cursor_in; |
| |
| while (head) { |
| if (head == in) |
| return 1; |
| head = head->next; |
| } |
| |
| return 0; |
| } |
| |
| /** Add new mouse cursor input driver */ |
| void mouse_cursor_add_input_driver(struct mouse_cursor_input_driver *const in) |
| { |
| /* Check if this driver was already added to the console list */ |
| if (mouse_cursor_driver_exists(in)) |
| return; |
| in->next = cursor_in; |
| cursor_in = in; |
| } |
| |
| /** Init enabled mouse cursor drivers */ |
| void mouse_cursor_init(void) |
| { |
| #if CONFIG(LP_PC_MOUSE) |
| i8042_mouse_init(); |
| #endif |
| } |
| |
| static u32 mouse_buttons; |
| static u8 mouse_acceleration = 0x10; |
| /* Fixed-point 1/256 units */ |
| static int mouse_rel_x; |
| static int mouse_rel_y; |
| static int mouse_rel_z; |
| static u32 mouse_speed = 0x299; |
| |
| /** Test for fast moving cursor */ |
| static u8 mouse_cusor_is_fast(int x, int y) |
| { |
| return (x * x + y * y) > (mouse_acceleration * mouse_acceleration); |
| } |
| |
| /** |
| * Poll for mouse data. |
| * |
| * Polls all drivers for new mouse data. |
| * Applies accelerations to relative movement. |
| * Logical ORs all buttons states. |
| * Call often to prevent driver's queue overrun ! |
| */ |
| void mouse_cursor_poll(void) |
| { |
| struct mouse_cursor_input_driver *in; |
| int rel_x, rel_y, rel_z; |
| u32 buttons; |
| |
| mouse_buttons = 0; |
| /* Iterate over all connected drivers */ |
| for (in = cursor_in; in != NULL; in = in->next) |
| if (in->get_state) { |
| in->get_state(&rel_x, &rel_y, &rel_z, &buttons); |
| |
| /* Accumulate relative movement */ |
| if (mouse_cusor_is_fast(rel_x, rel_y)) { |
| /* Apply simple cursor acceleration. Default: x2.6 */ |
| mouse_rel_x += rel_x * mouse_speed; |
| mouse_rel_y += rel_y * mouse_speed; |
| mouse_rel_z += rel_z * mouse_speed; |
| } else { |
| mouse_rel_x += rel_x * 256; |
| mouse_rel_y += rel_y * 256; |
| mouse_rel_z += rel_z * 256; |
| } |
| |
| /* Logic or all buttons */ |
| mouse_buttons |= buttons; |
| } |
| } |
| |
| /** |
| * Get relative mouse movement. |
| * |
| * Returns relative mouse movement with acceleration |
| * applied. The internal state will be cleared and stays |
| * clear until one of the drivers provide motion input again. |
| */ |
| void mouse_cursor_get_rel(int *x, int *y, int *z) |
| { |
| mouse_cursor_poll(); |
| |
| if (x) { |
| *x = mouse_rel_x / 256; |
| mouse_rel_x = 0; |
| } |
| if (y) { |
| *y = mouse_rel_y / 256; |
| mouse_rel_y = 0; |
| } |
| if (z) { |
| *z = mouse_rel_z / 256; |
| mouse_rel_z = 0; |
| } |
| } |
| |
| /** |
| * Get mouse button state. |
| * |
| * Returns the current button states. |
| * There are up to 32 possible buttons, |
| * but most devices only implement three buttons. |
| */ |
| u32 mouse_cursor_get_buttons(void) |
| { |
| mouse_cursor_poll(); |
| |
| return mouse_buttons; |
| } |
| |
| /** |
| * Set cursor speed. |
| * |
| * Sets the mouse cursor speed coefficient. |
| * It is used in case the cursor is moving faster |
| * than the mouse acceleration coefficient. |
| */ |
| void mouse_cursor_set_speed(u32 val) |
| { |
| mouse_speed = val; |
| } |
| |
| /** |
| * Get cursor speed. |
| * |
| * Returns the internal mouse cursor speed in |
| * 1/256th units. |
| * Default: 0x299 ~ 2.6 |
| */ |
| u32 mouse_cursor_get_speed(void) |
| { |
| return mouse_speed; |
| } |
| |
| /** |
| * Set cursor acceleration. |
| * |
| * Sets the mouse cursor acceleration coefficient. |
| * The acceleration is used to compare the raw relative |
| * cursor movement against. If greater the raw values are |
| * multiplied by mouse_speed to fasten the cursor. |
| */ |
| void mouse_cursor_set_acceleration(u8 val) |
| { |
| mouse_acceleration = val; |
| } |
| |
| /** |
| * Get cursor acceleration. |
| * |
| * Returns the current cursor acceleration coefficient. |
| * Default: 0x10 |
| */ |
| u8 mouse_cursor_get_acceleration(void) |
| { |
| return mouse_acceleration; |
| } |