mouse_cursor.c
1 /* 2 * 3 * Copyright (C) 2017 Patrick Rudolph <siro@das-labor.org> 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <libpayload-config.h> 30 #include <libpayload.h> 31 #include <usb/usb.h> 32 33 static struct mouse_cursor_input_driver *cursor_in; 34 35 static int 36 mouse_cursor_driver_exists(const struct mouse_cursor_input_driver *const in) 37 { 38 struct mouse_cursor_input_driver *head = cursor_in; 39 40 while (head) { 41 if (head == in) 42 return 1; 43 head = head->next; 44 } 45 46 return 0; 47 } 48 49 /** Add new mouse cursor input driver */ 50 void mouse_cursor_add_input_driver(struct mouse_cursor_input_driver *const in) 51 { 52 /* Check if this driver was already added to the console list */ 53 if (mouse_cursor_driver_exists(in)) 54 return; 55 in->next = cursor_in; 56 cursor_in = in; 57 } 58 59 /** Init enabled mouse cursor drivers */ 60 void mouse_cursor_init(void) 61 { 62 #if CONFIG(LP_PC_MOUSE) 63 i8042_mouse_init(); 64 #endif 65 } 66 67 static u32 mouse_buttons; 68 static u8 mouse_acceleration = 0x10; 69 /* Fixed-point 1/256 units */ 70 static int mouse_rel_x; 71 static int mouse_rel_y; 72 static int mouse_rel_z; 73 static u32 mouse_speed = 0x299; 74 75 /** Test for fast moving cursor */ 76 static u8 mouse_cusor_is_fast(int x, int y) 77 { 78 return (x * x + y * y) > (mouse_acceleration * mouse_acceleration); 79 } 80 81 /** 82 * Poll for mouse data. 83 * 84 * Polls all drivers for new mouse data. 85 * Applies accelerations to relative movement. 86 * Logical ORs all buttons states. 87 * Call often to prevent driver's queue overrun ! 88 */ 89 void mouse_cursor_poll(void) 90 { 91 struct mouse_cursor_input_driver *in; 92 int rel_x, rel_y, rel_z; 93 u32 buttons; 94 95 mouse_buttons = 0; 96 /* Iterate over all connected drivers */ 97 for (in = cursor_in; in != NULL; in = in->next) 98 if (in->get_state) { 99 in->get_state(&rel_x, &rel_y, &rel_z, &buttons); 100 101 /* Accumulate relative movement */ 102 if (mouse_cusor_is_fast(rel_x, rel_y)) { 103 /* Apply simple cursor acceleration. Default: x2.6 */ 104 mouse_rel_x += rel_x * mouse_speed; 105 mouse_rel_y += rel_y * mouse_speed; 106 mouse_rel_z += rel_z * mouse_speed; 107 } else { 108 mouse_rel_x += rel_x * 256; 109 mouse_rel_y += rel_y * 256; 110 mouse_rel_z += rel_z * 256; 111 } 112 113 /* Logic or all buttons */ 114 mouse_buttons |= buttons; 115 } 116 } 117 118 /** 119 * Get relative mouse movement. 120 * 121 * Returns relative mouse movement with acceleration 122 * applied. The internal state will be cleared and stays 123 * clear until one of the drivers provide motion input again. 124 */ 125 void mouse_cursor_get_rel(int *x, int *y, int *z) 126 { 127 mouse_cursor_poll(); 128 129 if (x) { 130 *x = mouse_rel_x / 256; 131 mouse_rel_x = 0; 132 } 133 if (y) { 134 *y = mouse_rel_y / 256; 135 mouse_rel_y = 0; 136 } 137 if (z) { 138 *z = mouse_rel_z / 256; 139 mouse_rel_z = 0; 140 } 141 } 142 143 /** 144 * Get mouse button state. 145 * 146 * Returns the current button states. 147 * There are up to 32 possible buttons, 148 * but most devices only implement three buttons. 149 */ 150 u32 mouse_cursor_get_buttons(void) 151 { 152 mouse_cursor_poll(); 153 154 return mouse_buttons; 155 } 156 157 /** 158 * Set cursor speed. 159 * 160 * Sets the mouse cursor speed coefficient. 161 * It is used in case the cursor is moving faster 162 * than the mouse acceleration coefficient. 163 */ 164 void mouse_cursor_set_speed(u32 val) 165 { 166 mouse_speed = val; 167 } 168 169 /** 170 * Get cursor speed. 171 * 172 * Returns the internal mouse cursor speed in 173 * 1/256th units. 174 * Default: 0x299 ~ 2.6 175 */ 176 u32 mouse_cursor_get_speed(void) 177 { 178 return mouse_speed; 179 } 180 181 /** 182 * Set cursor acceleration. 183 * 184 * Sets the mouse cursor acceleration coefficient. 185 * The acceleration is used to compare the raw relative 186 * cursor movement against. If greater the raw values are 187 * multiplied by mouse_speed to fasten the cursor. 188 */ 189 void mouse_cursor_set_acceleration(u8 val) 190 { 191 mouse_acceleration = val; 192 } 193 194 /** 195 * Get cursor acceleration. 196 * 197 * Returns the current cursor acceleration coefficient. 198 * Default: 0x10 199 */ 200 u8 mouse_cursor_get_acceleration(void) 201 { 202 return mouse_acceleration; 203 }