aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2016-12-03 10:13:11 -0500
committerGitHub <noreply@github.com>2016-12-03 10:13:11 -0500
commitd0c667c790479ac50804db0d212d0adf157c3e0b (patch)
treefeb7d648bd621907e4926611bc5c9dc7097148e2
parent464f7d96874ecd0ee73246ef1a9af1cc5f1069b8 (diff)
parentf0768f8be96fb7a9af354d5f1584b0f67cc5b960 (diff)
downloadqmk_firmware-d0c667c790479ac50804db0d212d0adf157c3e0b.tar.gz
qmk_firmware-d0c667c790479ac50804db0d212d0adf157c3e0b.zip
Merge pull request #931 from OferPlesser/feature/improve-ps2-mouse
Improving ps/2 mouse
-rw-r--r--readme.md112
-rw-r--r--tmk_core/protocol/ps2_mouse.c369
-rw-r--r--tmk_core/protocol/ps2_mouse.h84
3 files changed, 400 insertions, 165 deletions
diff --git a/readme.md b/readme.md
index be1510832..1f06fe79f 100644
--- a/readme.md
+++ b/readme.md
@@ -1191,7 +1191,7 @@ Please note the USB port can only supply a limited amount of power to the keyboa
1191 1191
1192Its possible to hook up a PS/2 mouse (for example touchpads or trackpoints) to your keyboard as a composite device. 1192Its possible to hook up a PS/2 mouse (for example touchpads or trackpoints) to your keyboard as a composite device.
1193 1193
1194Then, decide whether to use USART (best), interrupts (better) or busywait (not recommended), and enable the relevant option. 1194There are three available modes for hooking up PS/2 devices: USART (best), interrupts (better) or busywait (not recommended).
1195 1195
1196### Busywait version 1196### Busywait version
1197 1197
@@ -1316,6 +1316,116 @@ In your keyboard config.h:
1316#endif 1316#endif
1317``` 1317```
1318 1318
1319### Additional Settings
1320
1321#### PS/2 mouse features
1322
1323These enable settings supported by the PS/2 mouse protocol: http://www.computer-engineering.org/ps2mouse/
1324
1325```
1326/* Use remote mode instead of the default stream mode (see link) */
1327#define PS2_MOUSE_USE_REMOTE_MODE
1328
1329/* Enable the scrollwheel or scroll gesture on your mouse or touchpad */
1330#define PS2_MOUSE_ENABLE_SCROLLING
1331
1332/* Some mice will need a scroll mask to be configured. The default is 0xFF. */
1333#define PS2_MOUSE_SCROLL_MASK 0x0F
1334
1335/* Applies a transformation to the movement before sending to the host (see link) */
1336#define PS2_MOUSE_USE_2_1_SCALING
1337
1338/* The time to wait after initializing the ps2 host */
1339#define PS2_MOUSE_INIT_DELAY 1000 /* Default */
1340```
1341
1342You can also call the following functions from ps2_mouse.h
1343
1344```
1345void ps2_mouse_disable_data_reporting(void);
1346
1347void ps2_mouse_enable_data_reporting(void);
1348
1349void ps2_mouse_set_remote_mode(void);
1350
1351void ps2_mouse_set_stream_mode(void);
1352
1353void ps2_mouse_set_scaling_2_1(void);
1354
1355void ps2_mouse_set_scaling_1_1(void);
1356
1357void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution);
1358
1359void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate);
1360```
1361
1362#### Fine control
1363
1364Use the following defines to change the sensitivity and speed of the mouse.
1365Note: you can also use `ps2_mouse_set_resolution` for the same effect (not supported on most touchpads).
1366
1367```
1368#define PS2_MOUSE_X_MULTIPLIER 3
1369#define PS2_MOUSE_Y_MULTIPLIER 3
1370#define PS2_MOUSE_V_MULTIPLIER 1
1371```
1372
1373#### Scroll button
1374
1375If you're using a trackpoint, you will likely want to be able to use it for scrolling.
1376Its possible to enable a "scroll button/s" that when pressed will cause the mouse to scroll instead of moving.
1377To enable the feature, you must set a scroll button mask as follows:
1378
1379```
1380#define PS2_MOUSE_SCROLL_BTN_MASK (1<<PS2_MOUSE_BUTTON_MIDDLE) /* Default */
1381```
1382
1383To disable the scroll button feature:
1384
1385```
1386#define PS2_MOUSE_SCROLL_BTN_MASK 0
1387```
1388
1389The available buttons are:
1390
1391```
1392#define PS2_MOUSE_BTN_LEFT 0
1393#define PS2_MOUSE_BTN_RIGHT 1
1394#define PS2_MOUSE_BTN_MIDDLE 2
1395```
1396
1397You can also combine buttons in the mask by `|`ing them together.
1398
1399Once you've configured your scroll button mask, you must configure the scroll button send interval.
1400This is the interval before which if the scroll buttons were released they would be sent to the host.
1401After this interval, they will cause the mouse to scroll and will not be sent.
1402
1403```
1404#define PS2_MOUSE_SCROLL_BTN_SEND 300 /* Default */
1405```
1406
1407To disable sending the scroll buttons:
1408```
1409#define PS2_MOUSE_SCROLL_BTN_SEND 0
1410```
1411
1412Fine control over the scrolling is supported with the following defines:
1413
1414```
1415#define PS2_MOUSE_SCROLL_DIVISOR_H 2
1416#define PS2_MOUSE_SCROLL_DIVISOR_V 2
1417```
1418
1419#### Debug settings
1420
1421To debug the mouse, add `debug_mouse = true` or enable via bootmagic.
1422
1423```
1424/* To debug the mouse reports */
1425#define PS2_MOUSE_DEBUG_HID
1426#define PS2_MOUSE_DEBUG_RAW
1427```
1428
1319## Safety Considerations 1429## Safety Considerations
1320 1430
1321You probably don't want to "brick" your keyboard, making it impossible 1431You probably don't want to "brick" your keyboard, making it impossible
diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c
index 82f6966e8..af971dd49 100644
--- a/tmk_core/protocol/ps2_mouse.c
+++ b/tmk_core/protocol/ps2_mouse.c
@@ -18,63 +18,99 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
18#include <stdbool.h> 18#include <stdbool.h>
19#include<avr/io.h> 19#include<avr/io.h>
20#include<util/delay.h> 20#include<util/delay.h>
21#include "ps2.h"
22#include "ps2_mouse.h" 21#include "ps2_mouse.h"
23#include "report.h"
24#include "host.h" 22#include "host.h"
25#include "timer.h" 23#include "timer.h"
26#include "print.h" 24#include "print.h"
25#include "report.h"
27#include "debug.h" 26#include "debug.h"
27#include "ps2.h"
28 28
29#ifndef PS2_INIT_DELAY 29/* ============================= MACROS ============================ */
30#define PS2_INIT_DELAY 1000 30
31#endif 31#define PS2_MOUSE_SEND(command, message) \
32do { \
33 uint8_t rcv = ps2_host_send(command); \
34 if (debug_mouse) { \
35 print((message)); \
36 xprintf(" command: %X, result: %X, error: %X \n", command, rcv, ps2_error); \
37 } \
38} while(0)
39
40#define PS2_MOUSE_SEND_SAFE(command, message) \
41do { \
42 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
43 ps2_mouse_disable_data_reporting(); \
44 } \
45 PS2_MOUSE_SEND(command, message); \
46 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
47 ps2_mouse_enable_data_reporting(); \
48 } \
49} while(0)
50
51#define PS2_MOUSE_SET_SAFE(command, value, message) \
52do { \
53 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
54 ps2_mouse_disable_data_reporting(); \
55 } \
56 PS2_MOUSE_SEND(command, message); \
57 PS2_MOUSE_SEND(value, "Sending value"); \
58 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
59 ps2_mouse_enable_data_reporting(); \
60 } \
61} while(0)
62
63#define PS2_MOUSE_RECEIVE(message) \
64do { \
65 uint8_t rcv = ps2_host_recv_response(); \
66 if (debug_mouse) { \
67 print((message)); \
68 xprintf(" result: %X, error: %X \n", rcv, ps2_error); \
69 } \
70} while(0)
71
72static enum ps2_mouse_mode_e {
73 PS2_MOUSE_STREAM_MODE,
74 PS2_MOUSE_REMOTE_MODE,
75} ps2_mouse_mode = PS2_MOUSE_STREAM_MODE;
32 76
33static report_mouse_t mouse_report = {}; 77static report_mouse_t mouse_report = {};
34 78
79static inline void ps2_mouse_print_report(report_mouse_t *mouse_report);
80static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report);
81static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report);
82static inline void ps2_mouse_enable_scrolling(void);
83static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report);
35 84
36static void print_usb_data(void); 85/* ============================= IMPLEMENTATION ============================ */
37
38 86
39/* supports only 3 button mouse at this time */ 87/* supports only 3 button mouse at this time */
40uint8_t ps2_mouse_init(void) { 88void ps2_mouse_init(void) {
41 uint8_t rcv;
42
43 ps2_host_init(); 89 ps2_host_init();
44 90
45 _delay_ms(PS2_INIT_DELAY); // wait for powering up 91 _delay_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up
46 92
47 // send Reset 93 PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset");
48 rcv = ps2_host_send(0xFF);
49 print("ps2_mouse_init: send Reset: ");
50 phex(rcv); phex(ps2_error); print("\n");
51 94
52 // read completion code of BAT 95 PS2_MOUSE_RECEIVE("ps2_mouse_init: read BAT");
53 rcv = ps2_host_recv_response(); 96 PS2_MOUSE_RECEIVE("ps2_mouse_init: read DevID");
54 print("ps2_mouse_init: read BAT: ");
55 phex(rcv); phex(ps2_error); print("\n");
56 97
57 // read Device ID 98#ifdef PS2_MOUSE_USE_REMOTE_MODE
58 rcv = ps2_host_recv_response(); 99 ps2_mouse_set_remote_mode();
59 print("ps2_mouse_init: read DevID: "); 100#else
60 phex(rcv); phex(ps2_error); print("\n"); 101 ps2_mouse_enable_data_reporting();
102#endif
61 103
62 // send Set Remote mode 104#ifdef PS2_MOUSE_ENABLE_SCROLLING
63 rcv = ps2_host_send(0xF0); 105 ps2_mouse_enable_scrolling();
64 print("ps2_mouse_init: send 0xF0: "); 106#endif
65 phex(rcv); phex(ps2_error); print("\n");
66 107
67 return 0; 108#ifdef PS2_MOUSE_USE_2_1_SCALING
109 ps2_mouse_set_scaling_2_1();
110#endif
68} 111}
69 112
70#define X_IS_NEG (mouse_report.buttons & (1<<PS2_MOUSE_X_SIGN)) 113void ps2_mouse_task(void) {
71#define Y_IS_NEG (mouse_report.buttons & (1<<PS2_MOUSE_Y_SIGN))
72#define X_IS_OVF (mouse_report.buttons & (1<<PS2_MOUSE_X_OVFLW))
73#define Y_IS_OVF (mouse_report.buttons & (1<<PS2_MOUSE_Y_OVFLW))
74void ps2_mouse_task(void)
75{
76 enum { SCROLL_NONE, SCROLL_BTN, SCROLL_SENT };
77 static uint8_t scroll_state = SCROLL_NONE;
78 static uint8_t buttons_prev = 0; 114 static uint8_t buttons_prev = 0;
79 115
80 /* receives packet from mouse */ 116 /* receives packet from mouse */
@@ -82,142 +118,169 @@ void ps2_mouse_task(void)
82 rcv = ps2_host_send(PS2_MOUSE_READ_DATA); 118 rcv = ps2_host_send(PS2_MOUSE_READ_DATA);
83 if (rcv == PS2_ACK) { 119 if (rcv == PS2_ACK) {
84 mouse_report.buttons = ps2_host_recv_response(); 120 mouse_report.buttons = ps2_host_recv_response();
85 mouse_report.x = ps2_host_recv_response(); 121 mouse_report.x = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER;
86 mouse_report.y = ps2_host_recv_response(); 122 mouse_report.y = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER;
123#ifdef PS2_MOUSE_ENABLE_SCROLLING
124 mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK) * PS2_MOUSE_V_MULTIPLIER;
125#endif
87 } else { 126 } else {
88 if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n"); 127 if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n");
89 return; 128 return;
90 } 129 }
91 xprintf("%ud ", timer_read());
92 print("ps2_mouse raw: [");
93 phex(mouse_report.buttons); print("|");
94 print_hex8((uint8_t)mouse_report.x); print(" ");
95 print_hex8((uint8_t)mouse_report.y); print("]\n");
96 130
97 /* if mouse moves or buttons state changes */ 131 /* if mouse moves or buttons state changes */
98 if (mouse_report.x || mouse_report.y || 132 if (mouse_report.x || mouse_report.y || mouse_report.v ||
99 ((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) { 133 ((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) {
100 134#ifdef PS2_MOUSE_DEBUG_RAW
101#ifdef PS2_MOUSE_DEBUG 135 // Used to debug raw ps2 bytes from mouse
102 print("ps2_mouse raw: ["); 136 ps2_mouse_print_report(&mouse_report);
103 phex(mouse_report.buttons); print("|");
104 print_hex8((uint8_t)mouse_report.x); print(" ");
105 print_hex8((uint8_t)mouse_report.y); print("]\n");
106#endif 137#endif
107
108 buttons_prev = mouse_report.buttons; 138 buttons_prev = mouse_report.buttons;
139 ps2_mouse_convert_report_to_hid(&mouse_report);
140#if PS2_MOUSE_SCROLL_BTN_MASK
141 ps2_mouse_scroll_button_task(&mouse_report);
142#endif
143#ifdef PS2_MOUSE_DEBUG_HID
144 // Used to debug the bytes sent to the host
145 ps2_mouse_print_report(&mouse_report);
146#endif
147 host_mouse_send(&mouse_report);
148 }
149
150 ps2_mouse_clear_report(&mouse_report);
151}
109 152
110 // PS/2 mouse data is '9-bit integer'(-256 to 255) which is comprised of sign-bit and 8-bit value. 153void ps2_mouse_disable_data_reporting(void) {
111 // bit: 8 7 ... 0 154 PS2_MOUSE_SEND(PS2_MOUSE_DISABLE_DATA_REPORTING, "ps2 mouse disable data reporting");
112 // sign \8-bit/ 155}
113 //
114 // Meanwhile USB HID mouse indicates 8bit data(-127 to 127), note that -128 is not used.
115 //
116 // This converts PS/2 data into HID value. Use only -127-127 out of PS/2 9-bit.
117 mouse_report.x = X_IS_NEG ?
118 ((!X_IS_OVF && -127 <= mouse_report.x && mouse_report.x <= -1) ? mouse_report.x : -127) :
119 ((!X_IS_OVF && 0 <= mouse_report.x && mouse_report.x <= 127) ? mouse_report.x : 127);
120 mouse_report.y = Y_IS_NEG ?
121 ((!Y_IS_OVF && -127 <= mouse_report.y && mouse_report.y <= -1) ? mouse_report.y : -127) :
122 ((!Y_IS_OVF && 0 <= mouse_report.y && mouse_report.y <= 127) ? mouse_report.y : 127);
123 156
124 // remove sign and overflow flags 157void ps2_mouse_enable_data_reporting(void) {
125 mouse_report.buttons &= PS2_MOUSE_BTN_MASK; 158 PS2_MOUSE_SEND(PS2_MOUSE_ENABLE_DATA_REPORTING, "ps2 mouse enable data reporting");
159}
126 160
127 // invert coordinate of y to conform to USB HID mouse 161void ps2_mouse_set_remote_mode(void) {
128 mouse_report.y = -mouse_report.y; 162 PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode");
163 ps2_mouse_mode = PS2_MOUSE_REMOTE_MODE;
164}
129 165
166void ps2_mouse_set_stream_mode(void) {
167 PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_STREAM_MODE, "ps2 mouse set stream mode");
168 ps2_mouse_mode = PS2_MOUSE_STREAM_MODE;
169}
130 170
131#if PS2_MOUSE_SCROLL_BTN_MASK 171void ps2_mouse_set_scaling_2_1(void) {
132 static uint16_t scroll_button_time = 0; 172 PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_2_1, "ps2 mouse set scaling 2:1");
133 if ((mouse_report.buttons & (PS2_MOUSE_SCROLL_BTN_MASK)) == (PS2_MOUSE_SCROLL_BTN_MASK)) { 173}
134 if (scroll_state == SCROLL_NONE) {
135 scroll_button_time = timer_read();
136 scroll_state = SCROLL_BTN;
137 }
138
139 // doesn't send Scroll Button
140 //mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK);
141
142 if (mouse_report.x || mouse_report.y) {
143 scroll_state = SCROLL_SENT;
144
145 mouse_report.v = -mouse_report.y/(PS2_MOUSE_SCROLL_DIVISOR_V);
146 mouse_report.h = mouse_report.x/(PS2_MOUSE_SCROLL_DIVISOR_H);
147 mouse_report.x = 0;
148 mouse_report.y = 0;
149 //host_mouse_send(&mouse_report);
150 }
151 }
152 else if ((mouse_report.buttons & (PS2_MOUSE_SCROLL_BTN_MASK)) == 0) {
153#if PS2_MOUSE_SCROLL_BTN_SEND
154 if (scroll_state == SCROLL_BTN &&
155 TIMER_DIFF_16(timer_read(), scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) {
156 // send Scroll Button(down and up at once) when not scrolled
157 mouse_report.buttons |= (PS2_MOUSE_SCROLL_BTN_MASK);
158 host_mouse_send(&mouse_report);
159 _delay_ms(100);
160 mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK);
161 }
162#endif
163 scroll_state = SCROLL_NONE;
164 }
165 // doesn't send Scroll Button
166 mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK);
167#endif
168 174
175void ps2_mouse_set_scaling_1_1(void) {
176 PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_1_1, "ps2 mouse set scaling 1:1");
177}
169 178
170 host_mouse_send(&mouse_report); 179void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution) {
171 print_usb_data(); 180 PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_RESOLUTION, resolution, "ps2 mouse set resolution");
172 } 181}
173 // clear report 182
174 mouse_report.x = 0; 183void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate) {
175 mouse_report.y = 0; 184 PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_SAMPLE_RATE, sample_rate, "ps2 mouse set sample rate");
176 mouse_report.v = 0;
177 mouse_report.h = 0;
178 mouse_report.buttons = 0;
179} 185}
180 186
181static void print_usb_data(void) 187/* ============================= HELPERS ============================ */
182{ 188
189#define X_IS_NEG (mouse_report->buttons & (1<<PS2_MOUSE_X_SIGN))
190#define Y_IS_NEG (mouse_report->buttons & (1<<PS2_MOUSE_Y_SIGN))
191#define X_IS_OVF (mouse_report->buttons & (1<<PS2_MOUSE_X_OVFLW))
192#define Y_IS_OVF (mouse_report->buttons & (1<<PS2_MOUSE_Y_OVFLW))
193static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report) {
194 // PS/2 mouse data is '9-bit integer'(-256 to 255) which is comprised of sign-bit and 8-bit value.
195 // bit: 8 7 ... 0
196 // sign \8-bit/
197 //
198 // Meanwhile USB HID mouse indicates 8bit data(-127 to 127), note that -128 is not used.
199 //
200 // This converts PS/2 data into HID value. Use only -127-127 out of PS/2 9-bit.
201 mouse_report->x = X_IS_NEG ?
202 ((!X_IS_OVF && -127 <= mouse_report->x && mouse_report->x <= -1) ? mouse_report->x : -127) :
203 ((!X_IS_OVF && 0 <= mouse_report->x && mouse_report->x <= 127) ? mouse_report->x : 127);
204 mouse_report->y = Y_IS_NEG ?
205 ((!Y_IS_OVF && -127 <= mouse_report->y && mouse_report->y <= -1) ? mouse_report->y : -127) :
206 ((!Y_IS_OVF && 0 <= mouse_report->y && mouse_report->y <= 127) ? mouse_report->y : 127);
207
208 // remove sign and overflow flags
209 mouse_report->buttons &= PS2_MOUSE_BTN_MASK;
210
211 // invert coordinate of y to conform to USB HID mouse
212 mouse_report->y = -mouse_report->y;
213}
214
215static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report) {
216 mouse_report->x = 0;
217 mouse_report->y = 0;
218 mouse_report->v = 0;
219 mouse_report->h = 0;
220 mouse_report->buttons = 0;
221}
222
223static inline void ps2_mouse_print_report(report_mouse_t *mouse_report) {
183 if (!debug_mouse) return; 224 if (!debug_mouse) return;
184 print("ps2_mouse usb: ["); 225 print("ps2_mouse: [");
185 phex(mouse_report.buttons); print("|"); 226 phex(mouse_report->buttons); print("|");
186 print_hex8((uint8_t)mouse_report.x); print(" "); 227 print_hex8((uint8_t)mouse_report->x); print(" ");
187 print_hex8((uint8_t)mouse_report.y); print(" "); 228 print_hex8((uint8_t)mouse_report->y); print(" ");
188 print_hex8((uint8_t)mouse_report.v); print(" "); 229 print_hex8((uint8_t)mouse_report->v); print(" ");
189 print_hex8((uint8_t)mouse_report.h); print("]\n"); 230 print_hex8((uint8_t)mouse_report->h); print("]\n");
231}
232
233static inline void ps2_mouse_enable_scrolling(void) {
234 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Initiaing scroll wheel enable: Set sample rate");
235 PS2_MOUSE_SEND(200, "200");
236 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate");
237 PS2_MOUSE_SEND(100, "100");
238 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate");
239 PS2_MOUSE_SEND(80, "80");
240 PS2_MOUSE_SEND(PS2_MOUSE_GET_DEVICE_ID, "Finished enabling scroll wheel");
241 _delay_ms(20);
190} 242}
191 243
244#define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK)
245#define RELEASE_SCROLL_BUTTONS mouse_report->buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK)
246static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) {
247 static enum {
248 SCROLL_NONE,
249 SCROLL_BTN,
250 SCROLL_SENT,
251 } scroll_state = SCROLL_NONE;
252 static uint16_t scroll_button_time = 0;
253
254 if (PS2_MOUSE_SCROLL_BTN_MASK == (mouse_report->buttons & (PS2_MOUSE_SCROLL_BTN_MASK))) {
255 // All scroll buttons are pressed
256
257 if (scroll_state == SCROLL_NONE) {
258 scroll_button_time = timer_read();
259 scroll_state = SCROLL_BTN;
260 }
261
262 // If the mouse has moved, update the report to scroll instead of move the mouse
263 if (mouse_report->x || mouse_report->y) {
264 scroll_state = SCROLL_SENT;
265 mouse_report->v = -mouse_report->y/(PS2_MOUSE_SCROLL_DIVISOR_V);
266 mouse_report->h = mouse_report->x/(PS2_MOUSE_SCROLL_DIVISOR_H);
267 mouse_report->x = 0;
268 mouse_report->y = 0;
269 }
270 } else if (0 == (PS2_MOUSE_SCROLL_BTN_MASK & mouse_report->buttons)) {
271 // None of the scroll buttons are pressed
272
273#if PS2_MOUSE_SCROLL_BTN_SEND
274 if (scroll_state == SCROLL_BTN
275 && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) {
276 PRESS_SCROLL_BUTTONS;
277 host_mouse_send(mouse_report);
278 _delay_ms(100);
279 RELEASE_SCROLL_BUTTONS;
280 }
281#endif
282 scroll_state = SCROLL_NONE;
283 }
192 284
193/* PS/2 Mouse Synopsis 285 RELEASE_SCROLL_BUTTONS;
194 * http://www.computer-engineering.org/ps2mouse/ 286}
195 *
196 * Command:
197 * 0xFF: Reset
198 * 0xF6: Set Defaults Sampling; rate=100, resolution=4cnt/mm, scaling=1:1, reporting=disabled
199 * 0xF5: Disable Data Reporting
200 * 0xF4: Enable Data Reporting
201 * 0xF3: Set Sample Rate
202 * 0xF2: Get Device ID
203 * 0xF0: Set Remote Mode
204 * 0xEB: Read Data
205 * 0xEA: Set Stream Mode
206 * 0xE9: Status Request
207 * 0xE8: Set Resolution
208 * 0xE7: Set Scaling 2:1
209 * 0xE6: Set Scaling 1:1
210 *
211 * Mode:
212 * Stream Mode: devices sends the data when it changs its state
213 * Remote Mode: host polls the data periodically
214 *
215 * This code uses Remote Mode and polls the data with Read Data(0xEB).
216 *
217 * Data format:
218 * byte|7 6 5 4 3 2 1 0
219 * ----+--------------------------------------------------------------
220 * 0|Yovflw Xovflw Ysign Xsign 1 Middle Right Left
221 * 1| X movement
222 * 2| Y movement
223 */
diff --git a/tmk_core/protocol/ps2_mouse.h b/tmk_core/protocol/ps2_mouse.h
index 27d9790d4..e11c705fc 100644
--- a/tmk_core/protocol/ps2_mouse.h
+++ b/tmk_core/protocol/ps2_mouse.h
@@ -20,15 +20,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
20 20
21#include <stdbool.h> 21#include <stdbool.h>
22 22
23#define PS2_MOUSE_READ_DATA 0xEB
24
25/* 23/*
26 * Data format: 24 * Data format:
27 * byte|7 6 5 4 3 2 1 0 25 * byte|7 6 5 4 3 2 1 0
28 * ----+-------------------------------------------------------------- 26 * ----+----------------------------------------------------------------
29 * 0|Yovflw Xovflw Ysign Xsign 1 Middle Right Left 27 * 0|[Yovflw][Xovflw][Ysign ][Xsign ][ 1 ][Middle][Right ][Left ]
30 * 1| X movement(0-255) 28 * 1|[ X movement(0-255) ]
31 * 2| Y movement(0-255) 29 * 2|[ Y movement(0-255) ]
32 */ 30 */
33#define PS2_MOUSE_BTN_MASK 0x07 31#define PS2_MOUSE_BTN_MASK 0x07
34#define PS2_MOUSE_BTN_LEFT 0 32#define PS2_MOUSE_BTN_LEFT 0
@@ -39,10 +37,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
39#define PS2_MOUSE_X_OVFLW 6 37#define PS2_MOUSE_X_OVFLW 6
40#define PS2_MOUSE_Y_OVFLW 7 38#define PS2_MOUSE_Y_OVFLW 7
41 39
42
43/*
44 * Scroll by mouse move with pressing button
45 */
46/* mouse button to start scrolling; set 0 to disable scroll */ 40/* mouse button to start scrolling; set 0 to disable scroll */
47#ifndef PS2_MOUSE_SCROLL_BTN_MASK 41#ifndef PS2_MOUSE_SCROLL_BTN_MASK
48#define PS2_MOUSE_SCROLL_BTN_MASK (1<<PS2_MOUSE_BTN_MIDDLE) 42#define PS2_MOUSE_SCROLL_BTN_MASK (1<<PS2_MOUSE_BTN_MIDDLE)
@@ -58,9 +52,77 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
58#ifndef PS2_MOUSE_SCROLL_DIVISOR_H 52#ifndef PS2_MOUSE_SCROLL_DIVISOR_H
59#define PS2_MOUSE_SCROLL_DIVISOR_H 2 53#define PS2_MOUSE_SCROLL_DIVISOR_H 2
60#endif 54#endif
55/* multiply reported mouse values by these */
56#ifndef PS2_MOUSE_X_MULTIPLIER
57#define PS2_MOUSE_X_MULTIPLIER 1
58#endif
59#ifndef PS2_MOUSE_Y_MULTIPLIER
60#define PS2_MOUSE_Y_MULTIPLIER 1
61#endif
62#ifndef PS2_MOUSE_V_MULTIPLIER
63#define PS2_MOUSE_V_MULTIPLIER 1
64#endif
65/* For some mice this will need to be 0x0F */
66#ifndef PS2_MOUSE_SCROLL_MASK
67#define PS2_MOUSE_SCROLL_MASK 0xFF
68#endif
69#ifndef PS2_MOUSE_INIT_DELAY
70#define PS2_MOUSE_INIT_DELAY 1000
71#endif
72
73enum ps2_mouse_command_e {
74 PS2_MOUSE_RESET = 0xFF,
75 PS2_MOUSE_RESEND = 0xFE,
76 PS2_MOSUE_SET_DEFAULTS = 0xF6,
77 PS2_MOUSE_DISABLE_DATA_REPORTING = 0xF5,
78 PS2_MOUSE_ENABLE_DATA_REPORTING = 0xF4,
79 PS2_MOUSE_SET_SAMPLE_RATE = 0xF3,
80 PS2_MOUSE_GET_DEVICE_ID = 0xF2,
81 PS2_MOUSE_SET_REMOTE_MODE = 0xF0,
82 PS2_MOUSE_SET_WRAP_MODE = 0xEC,
83 PS2_MOUSE_READ_DATA = 0xEB,
84 PS2_MOUSE_SET_STREAM_MODE = 0xEA,
85 PS2_MOUSE_STATUS_REQUEST = 0xE9,
86 PS2_MOUSE_SET_RESOLUTION = 0xE8,
87 PS2_MOUSE_SET_SCALING_2_1 = 0xE7,
88 PS2_MOUSE_SET_SCALING_1_1 = 0xE6,
89};
61 90
91typedef enum ps2_mouse_resolution_e {
92 PS2_MOUSE_1_COUNT_MM,
93 PS2_MOUSE_2_COUNT_MM,
94 PS2_MOUSE_4_COUNT_MM,
95 PS2_MOUSE_8_COUNT_MM,
96} ps2_mouse_resolution_t;
97
98typedef enum ps2_mouse_sample_rate_e {
99 PS2_MOUSE_10_SAMPLES_SEC = 10,
100 PS2_MOUSE_20_SAMPLES_SEC = 20,
101 PS2_MOUSE_40_SAMPLES_SEC = 40,
102 PS2_MOUSE_60_SAMPLES_SEC = 60,
103 PS2_MOUSE_80_SAMPLES_SEC = 80,
104 PS2_MOUSE_100_SAMPLES_SEC = 100,
105 PS2_MOUSE_200_SAMPLES_SEC = 200,
106} ps2_mouse_sample_rate_t;
107
108void ps2_mouse_init(void);
62 109
63uint8_t ps2_mouse_init(void);
64void ps2_mouse_task(void); 110void ps2_mouse_task(void);
65 111
112void ps2_mouse_disable_data_reporting(void);
113
114void ps2_mouse_enable_data_reporting(void);
115
116void ps2_mouse_set_remote_mode(void);
117
118void ps2_mouse_set_stream_mode(void);
119
120void ps2_mouse_set_scaling_2_1(void);
121
122void ps2_mouse_set_scaling_1_1(void);
123
124void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution);
125
126void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate);
127
66#endif 128#endif