aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/protocol/ps2_mouse.c
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/protocol/ps2_mouse.c')
-rw-r--r--tmk_core/protocol/ps2_mouse.c274
1 files changed, 0 insertions, 274 deletions
diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c
deleted file mode 100644
index 39251a643..000000000
--- a/tmk_core/protocol/ps2_mouse.c
+++ /dev/null
@@ -1,274 +0,0 @@
1/*
2Copyright 2011,2013 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include <stdbool.h>
19
20#if defined(__AVR__)
21# include <avr/io.h>
22#endif
23
24#include "ps2_mouse.h"
25#include "wait.h"
26#include "host.h"
27#include "timer.h"
28#include "print.h"
29#include "report.h"
30#include "debug.h"
31#include "ps2.h"
32
33/* ============================= MACROS ============================ */
34
35static report_mouse_t mouse_report = {};
36
37static inline void ps2_mouse_print_report(report_mouse_t *mouse_report);
38static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report);
39static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report);
40static inline void ps2_mouse_enable_scrolling(void);
41static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report);
42
43/* ============================= IMPLEMENTATION ============================ */
44
45/* supports only 3 button mouse at this time */
46void ps2_mouse_init(void) {
47 ps2_host_init();
48
49 wait_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up
50
51 PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset");
52
53 PS2_MOUSE_RECEIVE("ps2_mouse_init: read BAT");
54 PS2_MOUSE_RECEIVE("ps2_mouse_init: read DevID");
55
56#ifdef PS2_MOUSE_USE_REMOTE_MODE
57 ps2_mouse_set_remote_mode();
58#else
59 ps2_mouse_enable_data_reporting();
60#endif
61
62#ifdef PS2_MOUSE_ENABLE_SCROLLING
63 ps2_mouse_enable_scrolling();
64#endif
65
66#ifdef PS2_MOUSE_USE_2_1_SCALING
67 ps2_mouse_set_scaling_2_1();
68#endif
69
70 ps2_mouse_init_user();
71}
72
73__attribute__((weak)) void ps2_mouse_init_user(void) {}
74
75__attribute__((weak)) void ps2_mouse_moved_user(report_mouse_t *mouse_report) {}
76
77void ps2_mouse_task(void) {
78 static uint8_t buttons_prev = 0;
79 extern int tp_buttons;
80
81 /* receives packet from mouse */
82 uint8_t rcv;
83 rcv = ps2_host_send(PS2_MOUSE_READ_DATA);
84 if (rcv == PS2_ACK) {
85 mouse_report.buttons = ps2_host_recv_response() | tp_buttons;
86 mouse_report.x = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER;
87 mouse_report.y = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER;
88#ifdef PS2_MOUSE_ENABLE_SCROLLING
89 mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK) * PS2_MOUSE_V_MULTIPLIER;
90#endif
91 } else {
92 if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n");
93 return;
94 }
95
96 /* if mouse moves or buttons state changes */
97 if (mouse_report.x || mouse_report.y || mouse_report.v || ((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) {
98#ifdef PS2_MOUSE_DEBUG_RAW
99 // Used to debug raw ps2 bytes from mouse
100 ps2_mouse_print_report(&mouse_report);
101#endif
102 buttons_prev = mouse_report.buttons;
103 ps2_mouse_convert_report_to_hid(&mouse_report);
104#if PS2_MOUSE_SCROLL_BTN_MASK
105 ps2_mouse_scroll_button_task(&mouse_report);
106#endif
107 if (mouse_report.x || mouse_report.y || mouse_report.v) {
108 ps2_mouse_moved_user(&mouse_report);
109 }
110#ifdef PS2_MOUSE_DEBUG_HID
111 // Used to debug the bytes sent to the host
112 ps2_mouse_print_report(&mouse_report);
113#endif
114 host_mouse_send(&mouse_report);
115 }
116
117 ps2_mouse_clear_report(&mouse_report);
118}
119
120void ps2_mouse_disable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_DISABLE_DATA_REPORTING, "ps2 mouse disable data reporting"); }
121
122void ps2_mouse_enable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_ENABLE_DATA_REPORTING, "ps2 mouse enable data reporting"); }
123
124void ps2_mouse_set_remote_mode(void) {
125 PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode");
126 ps2_mouse_mode = PS2_MOUSE_REMOTE_MODE;
127}
128
129void ps2_mouse_set_stream_mode(void) {
130 PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_STREAM_MODE, "ps2 mouse set stream mode");
131 ps2_mouse_mode = PS2_MOUSE_STREAM_MODE;
132}
133
134void ps2_mouse_set_scaling_2_1(void) { PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_2_1, "ps2 mouse set scaling 2:1"); }
135
136void ps2_mouse_set_scaling_1_1(void) { PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_1_1, "ps2 mouse set scaling 1:1"); }
137
138void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution) { PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_RESOLUTION, resolution, "ps2 mouse set resolution"); }
139
140void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate) { PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_SAMPLE_RATE, sample_rate, "ps2 mouse set sample rate"); }
141
142/* ============================= HELPERS ============================ */
143
144#define X_IS_NEG (mouse_report->buttons & (1 << PS2_MOUSE_X_SIGN))
145#define Y_IS_NEG (mouse_report->buttons & (1 << PS2_MOUSE_Y_SIGN))
146#define X_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_X_OVFLW))
147#define Y_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_Y_OVFLW))
148static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report) {
149 // PS/2 mouse data is '9-bit integer'(-256 to 255) which is comprised of sign-bit and 8-bit value.
150 // bit: 8 7 ... 0
151 // sign \8-bit/
152 //
153 // Meanwhile USB HID mouse indicates 8bit data(-127 to 127), note that -128 is not used.
154 //
155 // This converts PS/2 data into HID value. Use only -127-127 out of PS/2 9-bit.
156 mouse_report->x = X_IS_NEG ? ((!X_IS_OVF && -127 <= mouse_report->x && mouse_report->x <= -1) ? mouse_report->x : -127) : ((!X_IS_OVF && 0 <= mouse_report->x && mouse_report->x <= 127) ? mouse_report->x : 127);
157 mouse_report->y = Y_IS_NEG ? ((!Y_IS_OVF && -127 <= mouse_report->y && mouse_report->y <= -1) ? mouse_report->y : -127) : ((!Y_IS_OVF && 0 <= mouse_report->y && mouse_report->y <= 127) ? mouse_report->y : 127);
158
159#ifdef PS2_MOUSE_INVERT_BUTTONS
160 // swap left & right buttons
161 uint8_t needs_left = mouse_report->buttons & PS2_MOUSE_BTN_RIGHT;
162 uint8_t needs_right = mouse_report->buttons & PS2_MOUSE_BTN_LEFT;
163 mouse_report->buttons = (mouse_report->buttons & ~(PS2_MOUSE_BTN_MASK)) | (needs_left ? PS2_MOUSE_BTN_LEFT : 0) | (needs_right ? PS2_MOUSE_BTN_RIGHT : 0);
164#else
165 // remove sign and overflow flags
166 mouse_report->buttons &= PS2_MOUSE_BTN_MASK;
167#endif
168
169#ifdef PS2_MOUSE_INVERT_X
170 mouse_report->x = -mouse_report->x;
171#endif
172#ifndef PS2_MOUSE_INVERT_Y // NOTE if not!
173 // invert coordinate of y to conform to USB HID mouse
174 mouse_report->y = -mouse_report->y;
175#endif
176
177#ifdef PS2_MOUSE_ROTATE
178 int8_t x = mouse_report->x;
179 int8_t y = mouse_report->y;
180# if PS2_MOUSE_ROTATE == 90
181 mouse_report->x = y;
182 mouse_report->y = -x;
183# elif PS2_MOUSE_ROTATE == 180
184 mouse_report->x = -x;
185 mouse_report->y = -y;
186# elif PS2_MOUSE_ROTATE == 270
187 mouse_report->x = -y;
188 mouse_report->y = x;
189# endif
190#endif
191}
192
193static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report) {
194 mouse_report->x = 0;
195 mouse_report->y = 0;
196 mouse_report->v = 0;
197 mouse_report->h = 0;
198 mouse_report->buttons = 0;
199}
200
201static inline void ps2_mouse_print_report(report_mouse_t *mouse_report) {
202 if (!debug_mouse) return;
203 print("ps2_mouse: [");
204 print_hex8(mouse_report->buttons);
205 print("|");
206 print_hex8((uint8_t)mouse_report->x);
207 print(" ");
208 print_hex8((uint8_t)mouse_report->y);
209 print(" ");
210 print_hex8((uint8_t)mouse_report->v);
211 print(" ");
212 print_hex8((uint8_t)mouse_report->h);
213 print("]\n");
214}
215
216static inline void ps2_mouse_enable_scrolling(void) {
217 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Initiaing scroll wheel enable: Set sample rate");
218 PS2_MOUSE_SEND(200, "200");
219 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate");
220 PS2_MOUSE_SEND(100, "100");
221 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate");
222 PS2_MOUSE_SEND(80, "80");
223 PS2_MOUSE_SEND(PS2_MOUSE_GET_DEVICE_ID, "Finished enabling scroll wheel");
224 wait_ms(20);
225}
226
227#define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK)
228#define RELEASE_SCROLL_BUTTONS mouse_report->buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK)
229static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) {
230 static enum {
231 SCROLL_NONE,
232 SCROLL_BTN,
233 SCROLL_SENT,
234 } scroll_state = SCROLL_NONE;
235 static uint16_t scroll_button_time = 0;
236
237 if (PS2_MOUSE_SCROLL_BTN_MASK == (mouse_report->buttons & (PS2_MOUSE_SCROLL_BTN_MASK))) {
238 // All scroll buttons are pressed
239
240 if (scroll_state == SCROLL_NONE) {
241 scroll_button_time = timer_read();
242 scroll_state = SCROLL_BTN;
243 }
244
245 // If the mouse has moved, update the report to scroll instead of move the mouse
246 if (mouse_report->x || mouse_report->y) {
247 scroll_state = SCROLL_SENT;
248 mouse_report->v = -mouse_report->y / (PS2_MOUSE_SCROLL_DIVISOR_V);
249 mouse_report->h = mouse_report->x / (PS2_MOUSE_SCROLL_DIVISOR_H);
250 mouse_report->x = 0;
251 mouse_report->y = 0;
252#ifdef PS2_MOUSE_INVERT_H
253 mouse_report->h = -mouse_report->h;
254#endif
255#ifdef PS2_MOUSE_INVERT_V
256 mouse_report->v = -mouse_report->v;
257#endif
258 }
259 } else if (0 == (PS2_MOUSE_SCROLL_BTN_MASK & mouse_report->buttons)) {
260 // None of the scroll buttons are pressed
261
262#if PS2_MOUSE_SCROLL_BTN_SEND
263 if (scroll_state == SCROLL_BTN && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) {
264 PRESS_SCROLL_BUTTONS;
265 host_mouse_send(mouse_report);
266 wait_ms(100);
267 RELEASE_SCROLL_BUTTONS;
268 }
269#endif
270 scroll_state = SCROLL_NONE;
271 }
272
273 RELEASE_SCROLL_BUTTONS;
274}