aboutsummaryrefslogtreecommitdiff
path: root/protocol
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2013-11-21 13:01:47 +0900
committertmk <nobody@nowhere>2013-11-21 13:01:47 +0900
commit772ab7025ddf88126d9d6ddb654f62434985504b (patch)
treef0b4558bba2621a824736ceea0b09b51fdd41613 /protocol
parent821578293c79c5612f9b77e447295f2947fd6c3d (diff)
parenta9c3f4750b3d703b8bbbc90db2566afd2aab0ec9 (diff)
downloadqmk_firmware-772ab7025ddf88126d9d6ddb654f62434985504b.tar.gz
qmk_firmware-772ab7025ddf88126d9d6ddb654f62434985504b.zip
Merge branch 'ps2_mouse_fix'
Diffstat (limited to 'protocol')
-rw-r--r--protocol/lufa/lufa.c9
-rw-r--r--protocol/pjrc.mk6
-rw-r--r--protocol/ps2.c59
-rw-r--r--protocol/ps2_mouse.c303
-rw-r--r--protocol/ps2_mouse.h40
-rw-r--r--protocol/ps2_usart.c54
6 files changed, 257 insertions, 214 deletions
diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c
index a230d5ba2..04e8e78f3 100644
--- a/protocol/lufa/lufa.c
+++ b/protocol/lufa/lufa.c
@@ -539,11 +539,18 @@ int main(void)
539{ 539{
540 SetupHardware(); 540 SetupHardware();
541 sei(); 541 sei();
542
543 /* wait for USB startup & debug output */
544 while (USB_DeviceState != DEVICE_STATE_Configured) {
542#if defined(INTERRUPT_CONTROL_ENDPOINT) 545#if defined(INTERRUPT_CONTROL_ENDPOINT)
543 while (USB_DeviceState != DEVICE_STATE_Configured) ; 546 ;
547#else
548 USB_USBTask();
544#endif 549#endif
550 }
545 print("USB configured.\n"); 551 print("USB configured.\n");
546 552
553 /* init modules */
547 keyboard_init(); 554 keyboard_init();
548 host_set_driver(&lufa_driver); 555 host_set_driver(&lufa_driver);
549#ifdef SLEEP_LED_ENABLE 556#ifdef SLEEP_LED_ENABLE
diff --git a/protocol/pjrc.mk b/protocol/pjrc.mk
index 27f908b1c..5a4461382 100644
--- a/protocol/pjrc.mk
+++ b/protocol/pjrc.mk
@@ -7,7 +7,11 @@ SRC += $(PJRC_DIR)/main.c \
7 $(PJRC_DIR)/usb.c 7 $(PJRC_DIR)/usb.c
8 8
9# Option modules 9# Option modules
10ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) 10ifdef MOUSEKEY_ENABLE
11 SRC += $(PJRC_DIR)/usb_mouse.c
12endif
13
14ifdef PS2_MOUSE_ENABLE
11 SRC += $(PJRC_DIR)/usb_mouse.c 15 SRC += $(PJRC_DIR)/usb_mouse.c
12endif 16endif
13 17
diff --git a/protocol/ps2.c b/protocol/ps2.c
index ed4560910..e5873a9bf 100644
--- a/protocol/ps2.c
+++ b/protocol/ps2.c
@@ -1,5 +1,5 @@
1/* 1/*
2Copyright 2010,2011 Jun WAKO <wakojun@gmail.com> 2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3 3
4This software is licensed with a Modified BSD License. 4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free, 5All of this is supposed to be Free Software, Open Source, DFSG-free,
@@ -43,7 +43,9 @@ POSSIBILITY OF SUCH DAMAGE.
43#include "debug.h" 43#include "debug.h"
44 44
45 45
46#ifndef PS2_USE_INT
46static uint8_t recv_data(void); 47static uint8_t recv_data(void);
48#endif
47static inline void clock_lo(void); 49static inline void clock_lo(void);
48static inline void clock_hi(void); 50static inline void clock_hi(void);
49static inline bool clock_in(void); 51static inline bool clock_in(void);
@@ -109,12 +111,12 @@ uint8_t ps2_host_send(uint8_t data)
109#endif 111#endif
110 /* terminate a transmission if we have */ 112 /* terminate a transmission if we have */
111 inhibit(); 113 inhibit();
112 _delay_us(100); 114 _delay_us(200); // at least 100us
113 115
114 /* start bit [1] */ 116 /* start bit [1] */
115 data_lo(); 117 data_lo();
116 clock_hi(); 118 clock_hi();
117 WAIT(clock_lo, 15000, 1); 119 WAIT(clock_lo, 20000, 10); // may take 15ms at most until device starts clocking
118 /* data [2-9] */ 120 /* data [2-9] */
119 for (uint8_t i = 0; i < 8; i++) { 121 for (uint8_t i = 0; i < 8; i++) {
120 _delay_us(15); 122 _delay_us(15);
@@ -143,6 +145,9 @@ uint8_t ps2_host_send(uint8_t data)
143 WAIT(clock_hi, 50, 8); 145 WAIT(clock_hi, 50, 8);
144 WAIT(data_hi, 50, 9); 146 WAIT(data_hi, 50, 9);
145 147
148#ifdef PS2_USE_INT
149 PS2_INT_ON();
150#endif
146 res = ps2_host_recv_response(); 151 res = ps2_host_recv_response();
147ERROR: 152ERROR:
148#ifdef PS2_USE_INT 153#ifdef PS2_USE_INT
@@ -154,11 +159,15 @@ ERROR:
154 return res; 159 return res;
155} 160}
156 161
162#ifndef PS2_USE_INT
157/* receive data when host want else inhibit communication */ 163/* receive data when host want else inhibit communication */
158uint8_t ps2_host_recv_response(void) 164uint8_t ps2_host_recv_response(void)
159{ 165{
160 uint8_t data = 0; 166 uint8_t data = 0;
161 167
168#ifdef PS2_USE_INT
169 PS2_INT_OFF();
170#endif
162 /* terminate a transmission if we have */ 171 /* terminate a transmission if we have */
163 inhibit(); 172 inhibit();
164 _delay_us(100); 173 _delay_us(100);
@@ -167,12 +176,13 @@ uint8_t ps2_host_recv_response(void)
167 idle(); 176 idle();
168 177
169 /* wait start bit */ 178 /* wait start bit */
170 wait_clock_lo(2000); 179 wait_clock_lo(25000); // command response may take 20 ms at most
171 data = recv_data(); 180 data = recv_data();
172 181
173 inhibit(); 182 inhibit();
174 return data; 183 return data;
175} 184}
185#endif
176 186
177#ifndef PS2_USE_INT 187#ifndef PS2_USE_INT
178uint8_t ps2_host_recv(void) 188uint8_t ps2_host_recv(void)
@@ -187,9 +197,6 @@ static uint8_t pbuf_head = 0;
187static uint8_t pbuf_tail = 0; 197static uint8_t pbuf_tail = 0;
188static inline void pbuf_enqueue(uint8_t data) 198static inline void pbuf_enqueue(uint8_t data)
189{ 199{
190 if (!data)
191 return;
192
193 uint8_t sreg = SREG; 200 uint8_t sreg = SREG;
194 cli(); 201 cli();
195 uint8_t next = (pbuf_head + 1) % PBUF_SIZE; 202 uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
@@ -215,6 +222,21 @@ static inline uint8_t pbuf_dequeue(void)
215 222
216 return val; 223 return val;
217} 224}
225static inline bool pbuf_has_data(void)
226{
227 uint8_t sreg = SREG;
228 cli();
229 bool has_data = (pbuf_head != pbuf_tail);
230 SREG = sreg;
231 return has_data;
232}
233static inline void pbuf_clear(void)
234{
235 uint8_t sreg = SREG;
236 cli();
237 pbuf_head = pbuf_tail = 0;
238 SREG = sreg;
239}
218 240
219/* get data received by interrupt */ 241/* get data received by interrupt */
220uint8_t ps2_host_recv(void) 242uint8_t ps2_host_recv(void)
@@ -229,13 +251,12 @@ uint8_t ps2_host_recv(void)
229 return pbuf_dequeue(); 251 return pbuf_dequeue();
230} 252}
231 253
232#if 0 254uint8_t ps2_host_recv_response(void)
233#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0) 255{
234#define DEBUGP(x) do { PORTC = x; } while (0) 256 while (!pbuf_has_data()) ;
235#else 257 return pbuf_dequeue();
236#define DEBUGP_INIT() 258}
237#define DEBUGP(x) 259
238#endif
239ISR(PS2_INT_VECT) 260ISR(PS2_INT_VECT)
240{ 261{
241 static enum { 262 static enum {
@@ -256,7 +277,6 @@ ISR(PS2_INT_VECT)
256 } 277 }
257 278
258 state++; 279 state++;
259 DEBUGP(state);
260 switch (state) { 280 switch (state) {
261 case START: 281 case START:
262 if (data_in()) 282 if (data_in())
@@ -289,6 +309,7 @@ ISR(PS2_INT_VECT)
289 if (!data_in()) 309 if (!data_in())
290 goto ERROR; 310 goto ERROR;
291 pbuf_enqueue(data); 311 pbuf_enqueue(data);
312//phex(data);
292 goto DONE; 313 goto DONE;
293 break; 314 break;
294 default: 315 default:
@@ -296,7 +317,6 @@ ISR(PS2_INT_VECT)
296 } 317 }
297 goto RETURN; 318 goto RETURN;
298ERROR: 319ERROR:
299 DEBUGP(0x0F);
300 inhibit(); 320 inhibit();
301 ps2_error = state; 321 ps2_error = state;
302DONE: 322DONE:
@@ -309,11 +329,6 @@ RETURN:
309#endif 329#endif
310 330
311 331
312static void ps2_reset(void)
313{
314 ps2_host_send(0xFF);
315}
316
317/* send LED state to keyboard */ 332/* send LED state to keyboard */
318void ps2_host_set_led(uint8_t led) 333void ps2_host_set_led(uint8_t led)
319{ 334{
@@ -322,6 +337,7 @@ void ps2_host_set_led(uint8_t led)
322} 337}
323 338
324 339
340#ifndef PS2_USE_INT
325/* called after start bit comes */ 341/* called after start bit comes */
326static uint8_t recv_data(void) 342static uint8_t recv_data(void)
327{ 343{
@@ -361,6 +377,7 @@ static uint8_t recv_data(void)
361ERROR: 377ERROR:
362 return 0; 378 return 0;
363} 379}
380#endif
364 381
365static inline void clock_lo() 382static inline void clock_lo()
366{ 383{
diff --git a/protocol/ps2_mouse.c b/protocol/ps2_mouse.c
index f796b2b4d..4702f12c4 100644
--- a/protocol/ps2_mouse.c
+++ b/protocol/ps2_mouse.c
@@ -1,5 +1,5 @@
1/* 1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com> 2Copyright 2011,2013 Jun Wako <wakojun@gmail.com>
3 3
4This program is free software: you can redistribute it and/or modify 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 5it under the terms of the GNU General Public License as published by
@@ -20,199 +20,196 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
20#include<util/delay.h> 20#include<util/delay.h>
21#include "ps2.h" 21#include "ps2.h"
22#include "ps2_mouse.h" 22#include "ps2_mouse.h"
23#include "usb_mouse.h" 23#include "report.h"
24#include "host.h"
25#include "timer.h"
26#include "print.h"
27#include "debug.h"
24 28
25#define PS2_MOUSE_DEBUG
26#ifdef PS2_MOUSE_DEBUG
27# include "print.h"
28# include "debug.h"
29#else
30# define print(s)
31# define phex(h)
32# define phex16(h)
33#endif
34 29
35// disable when errors occur 255 times. 30static report_mouse_t mouse_report = {};
36#define ERROR_RETURN() do { \
37 if (ps2_error) { \
38 if (ps2_mouse_error_count < 255) { \
39 ps2_mouse_error_count++; \
40 } else { \
41 ps2_mouse_error_count = 0; \
42 ps2_mouse_enable = false; \
43 } \
44 return ps2_error; \
45 } \
46} while (0)
47 31
48 32
49/* 33static void print_usb_data(void);
50TODO
51----
52- Stream mode
53- Tracpoint command support: needed
54- Middle button + move = Wheel traslation
55*/
56bool ps2_mouse_enable = true;
57uint8_t ps2_mouse_x = 0;
58uint8_t ps2_mouse_y = 0;
59uint8_t ps2_mouse_btn = 0;
60uint8_t ps2_mouse_error_count = 0;
61
62static uint8_t ps2_mouse_btn_prev = 0;
63 34
64 35
36/* supports only 3 button mouse at this time */
65uint8_t ps2_mouse_init(void) { 37uint8_t ps2_mouse_init(void) {
66 uint8_t rcv; 38 uint8_t rcv;
67 39
68 if (!ps2_mouse_enable) return 1;
69
70 ps2_host_init(); 40 ps2_host_init();
71 41
72 // Reset 42 _delay_ms(1000); // wait for powering up
73 rcv = ps2_host_send(0xFF);
74 print("ps2_mouse_init: send 0xFF: ");
75 phex(ps2_error); print("\n");
76 ERROR_RETURN();
77 43
78 // ACK 44 // send Reset
79 rcv = ps2_host_recv(); 45 rcv = ps2_host_send(0xFF);
80 print("ps2_mouse_init: read ACK: "); 46 print("ps2_mouse_init: send Reset: ");
81 phex(rcv); phex(ps2_error); print("\n"); 47 phex(rcv); phex(ps2_error); print("\n");
82 ERROR_RETURN();
83 48
84 // BAT takes some time 49 // read completion code of BAT
85 _delay_ms(100); 50 rcv = ps2_host_recv_response();
86 rcv = ps2_host_recv();
87 print("ps2_mouse_init: read BAT: "); 51 print("ps2_mouse_init: read BAT: ");
88 phex(rcv); phex(ps2_error); print("\n"); 52 phex(rcv); phex(ps2_error); print("\n");
89 ERROR_RETURN();
90 53
91 // Device ID 54 // read Device ID
92 rcv = ps2_host_recv(); 55 rcv = ps2_host_recv_response();
93 print("ps2_mouse_init: read DevID: "); 56 print("ps2_mouse_init: read DevID: ");
94 phex(rcv); phex(ps2_error); print("\n"); 57 phex(rcv); phex(ps2_error); print("\n");
95 ERROR_RETURN();
96 58
97 // Enable data reporting 59 // send Set Remote mode
98 ps2_host_send(0xF4); 60 rcv = ps2_host_send(0xF0);
99 print("ps2_mouse_init: send 0xF4: ");
100 phex(ps2_error); print("\n");
101 ERROR_RETURN();
102
103 // ACK
104 rcv = ps2_host_recv();
105 print("ps2_mouse_init: read ACK: ");
106 phex(rcv); phex(ps2_error); print("\n");
107 ERROR_RETURN();
108
109 // Set Remote mode
110 ps2_host_send(0xF0);
111 print("ps2_mouse_init: send 0xF0: "); 61 print("ps2_mouse_init: send 0xF0: ");
112 phex(ps2_error); print("\n");
113 ERROR_RETURN();
114
115 // ACK
116 rcv = ps2_host_recv();
117 print("ps2_mouse_init: read ACK: ");
118 phex(rcv); phex(ps2_error); print("\n"); 62 phex(rcv); phex(ps2_error); print("\n");
119 ERROR_RETURN();
120 63
121 return 0; 64 return 0;
122} 65}
123 66
124/* 67#define X_IS_NEG (mouse_report.buttons & (1<<PS2_MOUSE_X_SIGN))
125Data format: 68#define Y_IS_NEG (mouse_report.buttons & (1<<PS2_MOUSE_Y_SIGN))
126 bit: 7 6 5 4 3 2 1 0 69#define X_IS_OVF (mouse_report.buttons & (1<<PS2_MOUSE_X_OVFLW))
127----------------------------------------------------------------------- 70#define Y_IS_OVF (mouse_report.buttons & (1<<PS2_MOUSE_Y_OVFLW))
1280 btn: Yovflw Xovflw Ysign Xsign 1 Middle Right Left 71void ps2_mouse_task(void)
1291 x: X movement(0-255)
1302 y: Y movement(0-255)
131*/
132uint8_t ps2_mouse_read(void)
133{ 72{
73 enum { SCROLL_NONE, SCROLL_BTN, SCROLL_SENT };
74 static uint8_t scroll_state = SCROLL_NONE;
75 static uint8_t buttons_prev = 0;
76
77 /* receives packet from mouse */
134 uint8_t rcv; 78 uint8_t rcv;
79 rcv = ps2_host_send(PS2_MOUSE_READ_DATA);
80 if (rcv == PS2_ACK) {
81 mouse_report.buttons = ps2_host_recv_response();
82 mouse_report.x = ps2_host_recv_response();
83 mouse_report.y = ps2_host_recv_response();
84 } else {
85 if (!debug_mouse) print("ps2_mouse: fail to get mouse packet\n");
86 return;
87 }
135 88
136 if (!ps2_mouse_enable) return 1; 89 /* if mouse moves or buttons state changes */
90 if (mouse_report.x || mouse_report.y ||
91 ((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) {
137 92
138 ps2_host_send(0xEB); 93#ifdef PS2_MOUSE_DEBUG
139 ERROR_RETURN(); 94 print("ps2_mouse raw: [");
95 phex(mouse_report.buttons); print("|");
96 print_hex8((uint8_t)mouse_report.x); print(" ");
97 print_hex8((uint8_t)mouse_report.y); print("]\n");
98#endif
140 99
141 rcv=ps2_host_recv(); 100 buttons_prev = mouse_report.buttons;
142 ERROR_RETURN(); 101
102 // PS/2 mouse data is '9-bit integer'(-256 to 255) which is comprised of sign-bit and 8-bit value.
103 // bit: 8 7 ... 0
104 // sign \8-bit/
105 //
106 // Meanwhile USB HID mouse indicates 8bit data(-127 to 127), note that -128 is not used.
107 //
108 // This converts PS/2 data into HID value. Use only -127-127 out of PS/2 9-bit.
109 mouse_report.x = X_IS_NEG ?
110 ((!X_IS_OVF && -127 <= mouse_report.x && mouse_report.x <= -1) ? mouse_report.x : -127) :
111 ((!X_IS_OVF && 0 <= mouse_report.x && mouse_report.x <= 127) ? mouse_report.x : 127);
112 mouse_report.y = Y_IS_NEG ?
113 ((!Y_IS_OVF && -127 <= mouse_report.y && mouse_report.y <= -1) ? mouse_report.y : -127) :
114 ((!Y_IS_OVF && 0 <= mouse_report.y && mouse_report.y <= 127) ? mouse_report.y : 127);
115
116 // remove sign and overflow flags
117 mouse_report.buttons &= PS2_MOUSE_BTN_MASK;
118
119 // invert coordinate of y to conform to USB HID mouse
120 mouse_report.y = -mouse_report.y;
121
122
123#if PS2_MOUSE_SCROLL_BTN_MASK
124 static uint16_t scroll_button_time = 0;
125 if ((mouse_report.buttons & (PS2_MOUSE_SCROLL_BTN_MASK)) == (PS2_MOUSE_SCROLL_BTN_MASK)) {
126 if (scroll_state == SCROLL_NONE) {
127 scroll_button_time = timer_read();
128 scroll_state = SCROLL_BTN;
129 }
143 130
144 if(rcv==0xFA) { 131 // doesn't send Scroll Button
145 ps2_mouse_btn = ps2_host_recv(); 132 //mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK);
146 ERROR_RETURN();
147 ps2_mouse_x = ps2_host_recv();
148 ERROR_RETURN();
149 ps2_mouse_y = ps2_host_recv();
150 ERROR_RETURN();
151 }
152 return 0;
153}
154 133
155bool ps2_mouse_changed(void) 134 if (mouse_report.x || mouse_report.y) {
156{ 135 scroll_state = SCROLL_SENT;
157 return (ps2_mouse_x || ps2_mouse_y || (ps2_mouse_btn & PS2_MOUSE_BTN_MASK) != ps2_mouse_btn_prev);
158}
159 136
160#define PS2_MOUSE_SCROLL_BUTTON 0x04 137 mouse_report.v = -mouse_report.y/(PS2_MOUSE_SCROLL_DIVISOR_V);
161void ps2_mouse_usb_send(void) 138 mouse_report.h = mouse_report.x/(PS2_MOUSE_SCROLL_DIVISOR_H);
162{ 139 mouse_report.x = 0;
163 static bool scrolled = false; 140 mouse_report.y = 0;
164 141 //host_mouse_send(&mouse_report);
165 if (!ps2_mouse_enable) return; 142 }
166 143 }
167 if (ps2_mouse_changed()) { 144 else if ((mouse_report.buttons & (PS2_MOUSE_SCROLL_BTN_MASK)) == 0) {
168 int8_t x, y, v, h; 145#if PS2_MOUSE_SCROLL_BTN_SEND
169 x = y = v = h = 0; 146 if (scroll_state == SCROLL_BTN &&
170 147 TIMER_DIFF_16(timer_read(), scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) {
171 // convert scale of X, Y: PS/2(-256/255) -> USB(-127/127) 148 // send Scroll Button(down and up at once) when not scrolled
172 if (ps2_mouse_btn & (1<<PS2_MOUSE_X_SIGN)) 149 mouse_report.buttons |= (PS2_MOUSE_SCROLL_BTN_MASK);
173 x = ps2_mouse_x > 128 ? (int8_t)ps2_mouse_x : -127; 150 host_mouse_send(&mouse_report);
174 else
175 x = ps2_mouse_x < 128 ? (int8_t)ps2_mouse_x : 127;
176
177 if (ps2_mouse_btn & (1<<PS2_MOUSE_Y_SIGN))
178 y = ps2_mouse_y > 128 ? (int8_t)ps2_mouse_y : -127;
179 else
180 y = ps2_mouse_y < 128 ? (int8_t)ps2_mouse_y : 127;
181
182 // Y is needed to reverse
183 y = -y;
184
185 if (ps2_mouse_btn & PS2_MOUSE_SCROLL_BUTTON) {
186 // scroll
187 if (x > 0 || x < 0) h = (x > 64 ? 64 : (x < -64 ? -64 :x));
188 if (y > 0 || y < 0) v = (y > 64 ? 64 : (y < -64 ? -64 :y));
189 if (h || v) {
190 scrolled = true;
191 usb_mouse_send(0,0, -v/16, h/16, 0);
192 _delay_ms(100); 151 _delay_ms(100);
152 mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK);
193 } 153 }
194 } else if (!scrolled && (ps2_mouse_btn_prev & PS2_MOUSE_SCROLL_BUTTON)) { 154#endif
195 usb_mouse_send(0,0,0,0, PS2_MOUSE_SCROLL_BUTTON); 155 scroll_state = SCROLL_NONE;
196 _delay_ms(100);
197 usb_mouse_send(0,0,0,0, 0);
198 } else {
199 scrolled = false;
200 usb_mouse_send(x, y, 0, 0, ps2_mouse_btn & PS2_MOUSE_BTN_MASK);
201 } 156 }
157 // doesn't send Scroll Button
158 mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK);
159#endif
160
202 161
203 ps2_mouse_btn_prev = (ps2_mouse_btn & PS2_MOUSE_BTN_MASK); 162 host_mouse_send(&mouse_report);
204 ps2_mouse_print(); 163 print_usb_data();
205 } 164 }
206 ps2_mouse_x = 0; 165 // clear report
207 ps2_mouse_y = 0; 166 mouse_report.x = 0;
208 ps2_mouse_btn = 0; 167 mouse_report.y = 0;
168 mouse_report.v = 0;
169 mouse_report.h = 0;
170 mouse_report.buttons = 0;
209} 171}
210 172
211void ps2_mouse_print(void) 173static void print_usb_data(void)
212{ 174{
213 if (!debug_mouse) return; 175 if (!debug_mouse) return;
214 print("ps2_mouse[btn|x y]: "); 176 print("ps2_mouse usb: [");
215 phex(ps2_mouse_btn); print("|"); 177 phex(mouse_report.buttons); print("|");
216 phex(ps2_mouse_x); print(" "); 178 print_hex8((uint8_t)mouse_report.x); print(" ");
217 phex(ps2_mouse_y); print("\n"); 179 print_hex8((uint8_t)mouse_report.y); print(" ");
180 print_hex8((uint8_t)mouse_report.v); print(" ");
181 print_hex8((uint8_t)mouse_report.h); print("]\n");
218} 182}
183
184
185/* PS/2 Mouse Synopsis
186 * http://www.computer-engineering.org/ps2mouse/
187 *
188 * Command:
189 * 0xFF: Reset
190 * 0xF6: Set Defaults Sampling; rate=100, resolution=4cnt/mm, scaling=1:1, reporting=disabled
191 * 0xF5: Disable Data Reporting
192 * 0xF4: Enable Data Reporting
193 * 0xF3: Set Sample Rate
194 * 0xF2: Get Device ID
195 * 0xF0: Set Remote Mode
196 * 0xEB: Read Data
197 * 0xEA: Set Stream Mode
198 * 0xE9: Status Request
199 * 0xE8: Set Resolution
200 * 0xE7: Set Scaling 2:1
201 * 0xE6: Set Scaling 1:1
202 *
203 * Mode:
204 * Stream Mode: devices sends the data when it changs its state
205 * Remote Mode: host polls the data periodically
206 *
207 * This code uses Remote Mode and polls the data with Read Data(0xEB).
208 *
209 * Data format:
210 * byte|7 6 5 4 3 2 1 0
211 * ----+--------------------------------------------------------------
212 * 0|Yovflw Xovflw Ysign Xsign 1 Middle Right Left
213 * 1| X movement
214 * 2| Y movement
215 */
diff --git a/protocol/ps2_mouse.h b/protocol/ps2_mouse.h
index 4529ce113..27d9790d4 100644
--- a/protocol/ps2_mouse.h
+++ b/protocol/ps2_mouse.h
@@ -20,6 +20,16 @@ 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/*
26 * Data format:
27 * byte|7 6 5 4 3 2 1 0
28 * ----+--------------------------------------------------------------
29 * 0|Yovflw Xovflw Ysign Xsign 1 Middle Right Left
30 * 1| X movement(0-255)
31 * 2| Y movement(0-255)
32 */
23#define PS2_MOUSE_BTN_MASK 0x07 33#define PS2_MOUSE_BTN_MASK 0x07
24#define PS2_MOUSE_BTN_LEFT 0 34#define PS2_MOUSE_BTN_LEFT 0
25#define PS2_MOUSE_BTN_RIGHT 1 35#define PS2_MOUSE_BTN_RIGHT 1
@@ -29,16 +39,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
29#define PS2_MOUSE_X_OVFLW 6 39#define PS2_MOUSE_X_OVFLW 6
30#define PS2_MOUSE_Y_OVFLW 7 40#define PS2_MOUSE_Y_OVFLW 7
31 41
32bool ps2_mouse_enable; 42
33extern uint8_t ps2_mouse_x; 43/*
34extern uint8_t ps2_mouse_y; 44 * Scroll by mouse move with pressing button
35extern uint8_t ps2_mouse_btn; 45 */
36extern uint8_t ps2_mouse_error_count; 46/* mouse button to start scrolling; set 0 to disable scroll */
47#ifndef PS2_MOUSE_SCROLL_BTN_MASK
48#define PS2_MOUSE_SCROLL_BTN_MASK (1<<PS2_MOUSE_BTN_MIDDLE)
49#endif
50/* send button event when button is released within this value(ms); set 0 to disable */
51#ifndef PS2_MOUSE_SCROLL_BTN_SEND
52#define PS2_MOUSE_SCROLL_BTN_SEND 300
53#endif
54/* divide virtical and horizontal mouse move by this to convert to scroll move */
55#ifndef PS2_MOUSE_SCROLL_DIVISOR_V
56#define PS2_MOUSE_SCROLL_DIVISOR_V 2
57#endif
58#ifndef PS2_MOUSE_SCROLL_DIVISOR_H
59#define PS2_MOUSE_SCROLL_DIVISOR_H 2
60#endif
61
37 62
38uint8_t ps2_mouse_init(void); 63uint8_t ps2_mouse_init(void);
39uint8_t ps2_mouse_read(void); 64void ps2_mouse_task(void);
40bool ps2_mouse_changed(void);
41void ps2_mouse_usb_send(void);
42void ps2_mouse_print(void);
43 65
44#endif 66#endif
diff --git a/protocol/ps2_usart.c b/protocol/ps2_usart.c
index 9ea6b7786..40c46c497 100644
--- a/protocol/ps2_usart.c
+++ b/protocol/ps2_usart.c
@@ -1,5 +1,5 @@
1/* 1/*
2Copyright 2010,2011 Jun WAKO <wakojun@gmail.com> 2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3 3
4This software is licensed with a Modified BSD License. 4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free, 5All of this is supposed to be Free Software, Open Source, DFSG-free,
@@ -64,14 +64,6 @@ http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
64#include "debug.h" 64#include "debug.h"
65 65
66 66
67#if 0
68#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0)
69#define DEBUGP(x) do { PORTC = x; } while (0)
70#else
71#define DEBUGP_INIT()
72#define DEBUGP(x)
73#endif
74
75#define WAIT(stat, us, err) do { \ 67#define WAIT(stat, us, err) do { \
76 if (!wait_##stat(us)) { \ 68 if (!wait_##stat(us)) { \
77 ps2_error = err; \ 69 ps2_error = err; \
@@ -97,12 +89,12 @@ static inline void idle(void);
97static inline void inhibit(void); 89static inline void inhibit(void);
98static inline uint8_t pbuf_dequeue(void); 90static inline uint8_t pbuf_dequeue(void);
99static inline void pbuf_enqueue(uint8_t data); 91static inline void pbuf_enqueue(uint8_t data);
92static inline bool pbuf_has_data(void);
93static inline void pbuf_clear(void);
100 94
101 95
102void ps2_host_init(void) 96void ps2_host_init(void)
103{ 97{
104 DEBUGP_INIT();
105 DEBUGP(0x1);
106 idle(); 98 idle();
107 PS2_USART_INIT(); 99 PS2_USART_INIT();
108 PS2_USART_RX_INT_ON(); 100 PS2_USART_RX_INT_ON();
@@ -114,7 +106,6 @@ uint8_t ps2_host_send(uint8_t data)
114 bool parity = true; 106 bool parity = true;
115 ps2_error = PS2_ERR_NONE; 107 ps2_error = PS2_ERR_NONE;
116 108
117 DEBUGP(0x6);
118 PS2_USART_OFF(); 109 PS2_USART_OFF();
119 110
120 /* terminate a transmission if we have */ 111 /* terminate a transmission if we have */
@@ -153,6 +144,8 @@ uint8_t ps2_host_send(uint8_t data)
153 WAIT(clock_hi, 50, 8); 144 WAIT(clock_hi, 50, 8);
154 WAIT(data_hi, 50, 9); 145 WAIT(data_hi, 50, 9);
155 146
147 PS2_USART_INIT();
148 PS2_USART_RX_INT_ON();
156 res = ps2_host_recv_response(); 149 res = ps2_host_recv_response();
157ERROR: 150ERROR:
158 idle(); 151 idle();
@@ -164,15 +157,10 @@ ERROR:
164// Do polling data from keyboard to get response to last command. 157// Do polling data from keyboard to get response to last command.
165uint8_t ps2_host_recv_response(void) 158uint8_t ps2_host_recv_response(void)
166{ 159{
167 uint8_t data = 0; 160 while (!pbuf_has_data()) {
168 PS2_USART_INIT(); 161 _delay_ms(1); // without this delay it seems to fall into deadlock
169 PS2_USART_RX_POLL_ON(); 162 }
170 while (!PS2_USART_RX_READY) 163 return pbuf_dequeue();
171 ;
172 data = PS2_USART_RX_DATA;
173 PS2_USART_OFF();
174 DEBUGP(0x9);
175 return data;
176} 164}
177 165
178uint8_t ps2_host_recv(void) 166uint8_t ps2_host_recv(void)
@@ -182,15 +170,11 @@ uint8_t ps2_host_recv(void)
182 170
183ISR(PS2_USART_RX_VECT) 171ISR(PS2_USART_RX_VECT)
184{ 172{
185 DEBUGP(0x7);
186 uint8_t error = PS2_USART_ERROR; 173 uint8_t error = PS2_USART_ERROR;
187 uint8_t data = PS2_USART_RX_DATA; 174 uint8_t data = PS2_USART_RX_DATA;
188 if (error) { 175 if (!error) {
189 DEBUGP(error>>2);
190 } else {
191 pbuf_enqueue(data); 176 pbuf_enqueue(data);
192 } 177 }
193 DEBUGP(0x8);
194} 178}
195 179
196/* send LED state to keyboard */ 180/* send LED state to keyboard */
@@ -293,9 +277,6 @@ static uint8_t pbuf_head = 0;
293static uint8_t pbuf_tail = 0; 277static uint8_t pbuf_tail = 0;
294static inline void pbuf_enqueue(uint8_t data) 278static inline void pbuf_enqueue(uint8_t data)
295{ 279{
296 if (!data)
297 return;
298
299 uint8_t sreg = SREG; 280 uint8_t sreg = SREG;
300 cli(); 281 cli();
301 uint8_t next = (pbuf_head + 1) % PBUF_SIZE; 282 uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
@@ -322,3 +303,18 @@ static inline uint8_t pbuf_dequeue(void)
322 303
323 return val; 304 return val;
324} 305}
306static inline bool pbuf_has_data(void)
307{
308 uint8_t sreg = SREG;
309 cli();
310 bool has_data = (pbuf_head != pbuf_tail);
311 SREG = sreg;
312 return has_data;
313}
314static inline void pbuf_clear(void)
315{
316 uint8_t sreg = SREG;
317 cli();
318 pbuf_head = pbuf_tail = 0;
319 SREG = sreg;
320}