diff options
Diffstat (limited to 'tmk_core/protocol')
-rw-r--r-- | tmk_core/protocol/adb.c | 256 | ||||
-rw-r--r-- | tmk_core/protocol/adb.h | 58 | ||||
-rw-r--r-- | tmk_core/protocol/arm_atsam/i2c_master.c | 3 | ||||
-rw-r--r-- | tmk_core/protocol/arm_atsam/i2c_master.h | 4 | ||||
-rw-r--r-- | tmk_core/protocol/arm_atsam/main_arm_atsam.c | 3 | ||||
-rw-r--r-- | tmk_core/protocol/chibios/main.c | 3 | ||||
-rw-r--r-- | tmk_core/protocol/chibios/usb_main.c | 86 | ||||
-rw-r--r-- | tmk_core/protocol/chibios/usb_main.h | 11 | ||||
-rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 24 | ||||
-rw-r--r-- | tmk_core/protocol/usb_descriptor.c | 12 | ||||
-rw-r--r-- | tmk_core/protocol/vusb/vusb.c | 10 |
11 files changed, 352 insertions, 118 deletions
diff --git a/tmk_core/protocol/adb.c b/tmk_core/protocol/adb.c index a23c91961..367f1b09f 100644 --- a/tmk_core/protocol/adb.c +++ b/tmk_core/protocol/adb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright 2011 Jun WAKO <wakojun@gmail.com> | 2 | Copyright 2011-19 Jun WAKO <wakojun@gmail.com> |
3 | Copyright 2013 Shay Green <gblargg@gmail.com> | 3 | Copyright 2013 Shay Green <gblargg@gmail.com> |
4 | 4 | ||
5 | This software is licensed with a Modified BSD License. | 5 | This software is licensed with a Modified BSD License. |
@@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE. | |||
41 | #include <avr/io.h> | 41 | #include <avr/io.h> |
42 | #include <avr/interrupt.h> | 42 | #include <avr/interrupt.h> |
43 | #include "adb.h" | 43 | #include "adb.h" |
44 | #include "print.h" | ||
44 | 45 | ||
45 | // GCC doesn't inline functions normally | 46 | // GCC doesn't inline functions normally |
46 | #define data_lo() (ADB_DDR |= (1 << ADB_DATA_BIT)) | 47 | #define data_lo() (ADB_DDR |= (1 << ADB_DATA_BIT)) |
@@ -59,7 +60,6 @@ static inline void place_bit1(void); | |||
59 | static inline void send_byte(uint8_t data); | 60 | static inline void send_byte(uint8_t data); |
60 | static inline uint16_t wait_data_lo(uint16_t us); | 61 | static inline uint16_t wait_data_lo(uint16_t us); |
61 | static inline uint16_t wait_data_hi(uint16_t us); | 62 | static inline uint16_t wait_data_hi(uint16_t us); |
62 | static inline uint16_t adb_host_dev_recv(uint8_t device); | ||
63 | 63 | ||
64 | void adb_host_init(void) { | 64 | void adb_host_init(void) { |
65 | ADB_PORT &= ~(1 << ADB_DATA_BIT); | 65 | ADB_PORT &= ~(1 << ADB_DATA_BIT); |
@@ -81,119 +81,164 @@ bool adb_host_psw(void) { return psw_in(); } | |||
81 | * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919> | 81 | * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919> |
82 | * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139> | 82 | * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139> |
83 | */ | 83 | */ |
84 | 84 | uint16_t adb_host_kbd_recv(void) { return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0); } | |
85 | // ADB Bit Cells | ||
86 | // | ||
87 | // bit cell time: 70-130us | ||
88 | // low part of bit0: 60-70% of bit cell | ||
89 | // low part of bit1: 30-40% of bit cell | ||
90 | // | ||
91 | // bit cell time 70us 130us | ||
92 | // -------------------------------------------- | ||
93 | // low part of bit0 42-49 78-91 | ||
94 | // high part of bit0 21-28 39-52 | ||
95 | // low part of bit1 21-28 39-52 | ||
96 | // high part of bit1 42-49 78-91 | ||
97 | // | ||
98 | // | ||
99 | // bit0: | ||
100 | // 70us bit cell: | ||
101 | // ____________~~~~~~ | ||
102 | // 42-49 21-28 | ||
103 | // | ||
104 | // 130us bit cell: | ||
105 | // ____________~~~~~~ | ||
106 | // 78-91 39-52 | ||
107 | // | ||
108 | // bit1: | ||
109 | // 70us bit cell: | ||
110 | // ______~~~~~~~~~~~~ | ||
111 | // 21-28 42-49 | ||
112 | // | ||
113 | // 130us bit cell: | ||
114 | // ______~~~~~~~~~~~~ | ||
115 | // 39-52 78-91 | ||
116 | // | ||
117 | // [from Apple IIgs Hardware Reference Second Edition] | ||
118 | |||
119 | enum { ADDR_KEYB = 0x20, ADDR_MOUSE = 0x30 }; | ||
120 | |||
121 | uint16_t adb_host_kbd_recv(void) { return adb_host_dev_recv(ADDR_KEYB); } | ||
122 | 85 | ||
123 | #ifdef ADB_MOUSE_ENABLE | 86 | #ifdef ADB_MOUSE_ENABLE |
124 | void adb_mouse_init(void) { return; } | 87 | __attribute__((weak)) void adb_mouse_init(void) { return; } |
88 | |||
89 | __attribute__((weak)) void adb_mouse_task(void) { return; } | ||
125 | 90 | ||
126 | uint16_t adb_host_mouse_recv(void) { return adb_host_dev_recv(ADDR_MOUSE); } | 91 | uint16_t adb_host_mouse_recv(void) { return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0); } |
127 | #endif | 92 | #endif |
128 | 93 | ||
129 | static inline uint16_t adb_host_dev_recv(uint8_t device) { | 94 | // This sends Talk command to read data from register and returns length of the data. |
130 | uint16_t data = 0; | 95 | uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) { |
96 | for (int8_t i = 0; i < len; i++) buf[i] = 0; | ||
97 | |||
131 | cli(); | 98 | cli(); |
132 | attention(); | 99 | attention(); |
133 | send_byte(device | 0x0C); // Addr:Keyboard(0010)/Mouse(0011), Cmd:Talk(11), Register0(00) | 100 | send_byte((addr << 4) | ADB_CMD_TALK | reg); |
134 | place_bit0(); // Stopbit(0) | 101 | place_bit0(); // Stopbit(0) |
102 | // TODO: Service Request(Srq): | ||
103 | // Device holds low part of comannd stopbit for 140-260us | ||
104 | // | ||
105 | // Command: | ||
106 | // ......._ ______________________ ___ ............_ ------- | ||
107 | // | | | | | | | | ||
108 | // Command | | | | | Data bytes | | | ||
109 | // ........|___| | 140-260 |__| |_............|___| | ||
110 | // |stop0 | Tlt Stop-to-Start |start1| |stop0 | | ||
111 | // | ||
112 | // Command without data: | ||
113 | // ......._ __________________________ | ||
114 | // | | | ||
115 | // Command | | | ||
116 | // ........|___| | 140-260 | | ||
117 | // |stop0 | Tlt Stop-to-Start | | ||
118 | // | ||
119 | // Service Request: | ||
120 | // ......._ ______ ___ ............_ ------- | ||
121 | // | 140-260 | | | | | | | ||
122 | // Command | Service Request | | | | Data bytes | | | ||
123 | // ........|___________________| |__| |_............|___| | ||
124 | // |stop0 | |start1| |stop0 | | ||
125 | // ......._ __________ | ||
126 | // | 140-260 | | ||
127 | // Command | Service Request | | ||
128 | // ........|___________________| | ||
129 | // |stop0 | | ||
130 | // This can be happened? | ||
131 | // ......._ ______________________ ___ ............_ ----- | ||
132 | // | | | | | | 140-260 | | ||
133 | // Command | | | | | Data bytes | Service Request | | ||
134 | // ........|___| | 140-260 |__| |_............|_________________| | ||
135 | // |stop0 | Tlt Stop-to-Start |start1| |stop0 | | ||
136 | // | ||
137 | // "Service requests are issued by the devices during a very specific time at the | ||
138 | // end of the reception of the command packet. | ||
139 | // If a device in need of service issues a service request, it must do so within | ||
140 | // the 65 µs of the Stop Bit’s low time and maintain the line low for a total of 300 µs." | ||
141 | // | ||
142 | // "A device sends a Service Request signal by holding the bus low during the low | ||
143 | // portion of the stop bit of any command or data transaction. The device must lengthen | ||
144 | // the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15." | ||
145 | // http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf | ||
135 | if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored | 146 | if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored |
147 | xprintf("R"); | ||
136 | sei(); | 148 | sei(); |
137 | return -30; // something wrong | 149 | return 0; |
138 | } | 150 | } |
139 | if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us) | 151 | if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us) |
140 | sei(); | 152 | sei(); |
141 | return 0; // No data to send | 153 | return 0; // No data from device(not error); |
154 | } | ||
155 | |||
156 | // start bit(1) | ||
157 | if (!wait_data_hi(40)) { | ||
158 | xprintf("S"); | ||
159 | sei(); | ||
160 | return 0; | ||
161 | } | ||
162 | if (!wait_data_lo(100)) { | ||
163 | xprintf("s"); | ||
164 | sei(); | ||
165 | return 0; | ||
142 | } | 166 | } |
143 | 167 | ||
144 | uint8_t n = 17; // start bit + 16 data bits | 168 | uint8_t n = 0; // bit count |
145 | do { | 169 | do { |
170 | // | ||
171 | // |<- bit_cell_max(130) ->| | ||
172 | // | |<- lo ->| | ||
173 | // | | |<-hi->| | ||
174 | // _______ | ||
175 | // | | | | ||
176 | // | 130-lo | lo-hi | | ||
177 | // |________| | | ||
178 | // | ||
146 | uint8_t lo = (uint8_t)wait_data_hi(130); | 179 | uint8_t lo = (uint8_t)wait_data_hi(130); |
147 | if (!lo) goto error; | 180 | if (!lo) goto error; // no more bit or after stop bit |
148 | 181 | ||
149 | uint8_t hi = (uint8_t)wait_data_lo(lo); | 182 | uint8_t hi = (uint8_t)wait_data_lo(lo); |
150 | if (!hi) goto error; | 183 | if (!hi) goto error; // stop bit extedned by Srq? |
151 | 184 | ||
152 | hi = lo - hi; | 185 | if (n / 8 >= len) continue; // can't store in buf |
153 | lo = 130 - lo; | ||
154 | 186 | ||
155 | data <<= 1; | 187 | buf[n / 8] <<= 1; |
156 | if (lo < hi) { | 188 | if ((130 - lo) < (lo - hi)) { |
157 | data |= 1; | 189 | buf[n / 8] |= 1; |
158 | } else if (n == 17) { | ||
159 | sei(); | ||
160 | return -20; | ||
161 | } | 190 | } |
162 | } while (--n); | 191 | } while (++n); |
163 | |||
164 | // Stop bit can't be checked normally since it could have service request lenghtening | ||
165 | // and its high state never goes low. | ||
166 | if (!wait_data_hi(351) || wait_data_lo(91)) { | ||
167 | sei(); | ||
168 | return -21; | ||
169 | } | ||
170 | sei(); | ||
171 | return data; | ||
172 | 192 | ||
173 | error: | 193 | error: |
174 | sei(); | 194 | sei(); |
175 | return -n; | 195 | return n / 8; |
176 | } | 196 | } |
177 | 197 | ||
178 | void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l) { | 198 | uint16_t adb_host_talk(uint8_t addr, uint8_t reg) { |
199 | uint8_t len; | ||
200 | uint8_t buf[8]; | ||
201 | len = adb_host_talk_buf(addr, reg, buf, 8); | ||
202 | if (len != 2) return 0; | ||
203 | return (buf[0] << 8 | buf[1]); | ||
204 | } | ||
205 | |||
206 | void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) { | ||
179 | cli(); | 207 | cli(); |
180 | attention(); | 208 | attention(); |
181 | send_byte(cmd); | 209 | send_byte((addr << 4) | ADB_CMD_LISTEN | reg); |
182 | place_bit0(); // Stopbit(0) | 210 | place_bit0(); // Stopbit(0) |
211 | // TODO: Service Request | ||
183 | _delay_us(200); // Tlt/Stop to Start | 212 | _delay_us(200); // Tlt/Stop to Start |
184 | place_bit1(); // Startbit(1) | 213 | place_bit1(); // Startbit(1) |
185 | send_byte(data_h); | 214 | for (int8_t i = 0; i < len; i++) { |
186 | send_byte(data_l); | 215 | send_byte(buf[i]); |
216 | // xprintf("%02X ", buf[i]); | ||
217 | } | ||
187 | place_bit0(); // Stopbit(0); | 218 | place_bit0(); // Stopbit(0); |
188 | sei(); | 219 | sei(); |
189 | } | 220 | } |
190 | 221 | ||
222 | void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l) { | ||
223 | uint8_t buf[2] = {data_h, data_l}; | ||
224 | adb_host_listen_buf(addr, reg, buf, 2); | ||
225 | } | ||
226 | |||
227 | void adb_host_flush(uint8_t addr) { | ||
228 | cli(); | ||
229 | attention(); | ||
230 | send_byte((addr << 4) | ADB_CMD_FLUSH); | ||
231 | place_bit0(); // Stopbit(0) | ||
232 | _delay_us(200); // Tlt/Stop to Start | ||
233 | sei(); | ||
234 | } | ||
235 | |||
191 | // send state of LEDs | 236 | // send state of LEDs |
192 | void adb_host_kbd_led(uint8_t led) { | 237 | void adb_host_kbd_led(uint8_t led) { |
193 | // Addr:Keyboard(0010), Cmd:Listen(10), Register2(10) | 238 | // Listen Register2 |
194 | // send upper byte (not used) | 239 | // upper byte: not used |
195 | // send lower byte (bit2: ScrollLock, bit1: CapsLock, bit0: | 240 | // lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock |
196 | adb_host_listen(0x2A, 0, led & 0x07); | 241 | adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_2, 0, led & 0x07); |
197 | } | 242 | } |
198 | 243 | ||
199 | #ifdef ADB_PSW_BIT | 244 | #ifdef ADB_PSW_BIT |
@@ -327,7 +372,7 @@ Commands | |||
327 | 372 | ||
328 | bits commands | 373 | bits commands |
329 | ------------------------------------------------------ | 374 | ------------------------------------------------------ |
330 | - - - - 0 0 0 0 Send Request(reset all devices) | 375 | - - - - 0 0 0 0 Send Reset(reset all devices) |
331 | A A A A 0 0 0 1 Flush(reset a device) | 376 | A A A A 0 0 0 1 Flush(reset a device) |
332 | - - - - 0 0 1 0 Reserved | 377 | - - - - 0 0 1 0 Reserved |
333 | - - - - 0 0 1 1 Reserved | 378 | - - - - 0 0 1 1 Reserved |
@@ -435,5 +480,56 @@ Keyboard LEDs & state of keys(Register2) | |||
435 | | +----------------------------- Delete | 480 | | +----------------------------- Delete |
436 | +------------------------------- Reserved | 481 | +------------------------------- Reserved |
437 | 482 | ||
483 | Address, Handler ID and bits(Register3) | ||
484 | 1514131211 . . 8 7 . . . . . . 0 | ||
485 | | | | | | | | | | | | | | | | | | ||
486 | | | | | | | | | +-+-+-+-+-+-+-+- Handler ID | ||
487 | | | | | +-+-+-+----------------- Address | ||
488 | | | | +------------------------- 0 | ||
489 | | | +--------------------------- Service request enable(1 = enabled) | ||
490 | | +----------------------------- Exceptional event(alwyas 1 if not used) | ||
491 | +------------------------------- 0 | ||
492 | |||
493 | ADB Bit Cells | ||
494 | bit cell time: 70-130us | ||
495 | low part of bit0: 60-70% of bit cell | ||
496 | low part of bit1: 30-40% of bit cell | ||
497 | |||
498 | bit cell time 70us 130us | ||
499 | -------------------------------------------- | ||
500 | low part of bit0 42-49 78-91 | ||
501 | high part of bit0 21-28 39-52 | ||
502 | low part of bit1 21-28 39-52 | ||
503 | high part of bit1 42-49 78-91 | ||
504 | |||
505 | |||
506 | bit0: | ||
507 | 70us bit cell: | ||
508 | ____________~~~~~~ | ||
509 | 42-49 21-28 | ||
510 | |||
511 | 130us bit cell: | ||
512 | ____________~~~~~~ | ||
513 | 78-91 39-52 | ||
514 | |||
515 | bit1: | ||
516 | 70us bit cell: | ||
517 | ______~~~~~~~~~~~~ | ||
518 | 21-28 42-49 | ||
519 | |||
520 | 130us bit cell: | ||
521 | ______~~~~~~~~~~~~ | ||
522 | 39-52 78-91 | ||
523 | |||
524 | [from Apple IIgs Hardware Reference Second Edition] | ||
525 | |||
526 | Keyboard Handle ID | ||
527 | Apple Standard Keyboard M0116: 0x01 | ||
528 | Apple Extended Keyboard M0115: 0x02 | ||
529 | Apple Extended Keyboard II M3501: 0x02 | ||
530 | Apple Adjustable Keybaord: 0x10 | ||
531 | |||
532 | http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L802 | ||
533 | |||
438 | END_OF_ADB | 534 | END_OF_ADB |
439 | */ | 535 | */ |
diff --git a/tmk_core/protocol/adb.h b/tmk_core/protocol/adb.h index 34cbcf769..fe8becc2d 100644 --- a/tmk_core/protocol/adb.h +++ b/tmk_core/protocol/adb.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright 2011 Jun WAKO <wakojun@gmail.com> | 2 | Copyright 2011-19 Jun WAKO <wakojun@gmail.com> |
3 | 3 | ||
4 | This software is licensed with a Modified BSD License. | 4 | This software is licensed with a Modified BSD License. |
5 | All of this is supposed to be Free Software, Open Source, DFSG-free, | 5 | All of this is supposed to be Free Software, Open Source, DFSG-free, |
@@ -47,12 +47,60 @@ POSSIBILITY OF SUCH DAMAGE. | |||
47 | #define ADB_POWER 0x7F | 47 | #define ADB_POWER 0x7F |
48 | #define ADB_CAPS 0x39 | 48 | #define ADB_CAPS 0x39 |
49 | 49 | ||
50 | /* ADB commands */ | ||
51 | // Default Address | ||
52 | #define ADB_ADDR_0 0 | ||
53 | #define ADB_ADDR_DONGLE 1 | ||
54 | #define ADB_ADDR_KEYBOARD 2 | ||
55 | #define ADB_ADDR_MOUSE 3 | ||
56 | #define ADB_ADDR_TABLET 4 | ||
57 | #define ADB_ADDR_APPLIANCE 7 | ||
58 | #define ADB_ADDR_8 8 | ||
59 | #define ADB_ADDR_9 9 | ||
60 | #define ADB_ADDR_10 10 | ||
61 | #define ADB_ADDR_11 11 | ||
62 | #define ADB_ADDR_12 12 | ||
63 | #define ADB_ADDR_13 13 | ||
64 | #define ADB_ADDR_14 14 | ||
65 | #define ADB_ADDR_15 15 | ||
66 | // for temporary purpose, do not use for polling | ||
67 | #define ADB_ADDR_TMP 15 | ||
68 | #define ADB_ADDR_MOUSE_POLL 10 | ||
69 | // Command Type | ||
70 | #define ADB_CMD_RESET 0 | ||
71 | #define ADB_CMD_FLUSH 1 | ||
72 | #define ADB_CMD_LISTEN 8 | ||
73 | #define ADB_CMD_TALK 12 | ||
74 | // Register | ||
75 | #define ADB_REG_0 0 | ||
76 | #define ADB_REG_1 1 | ||
77 | #define ADB_REG_2 2 | ||
78 | #define ADB_REG_3 3 | ||
79 | |||
80 | /* ADB keyboard handler id */ | ||
81 | #define ADB_HANDLER_STD 0x01 /* IIGS, M0116 */ | ||
82 | #define ADB_HANDLER_AEK 0x02 /* M0115, M3501 */ | ||
83 | #define ADB_HANDLER_AEK_RMOD 0x03 /* M0115, M3501, alternate mode enableing right modifiers */ | ||
84 | #define ADB_HANDLER_STD_ISO 0x04 /* M0118, ISO swapping keys */ | ||
85 | #define ADB_HANDLER_AEK_ISO 0x05 /* M0115, M3501, ISO swapping keys */ | ||
86 | #define ADB_HANDLER_M1242_ANSI 0x10 /* Adjustable keyboard */ | ||
87 | #define ADB_HANDLER_CLASSIC1_MOUSE 0x01 | ||
88 | #define ADB_HANDLER_CLASSIC2_MOUSE 0x02 | ||
89 | #define ADB_HANDLER_EXTENDED_MOUSE 0x04 | ||
90 | #define ADB_HANDLER_TURBO_MOUSE 0x32 | ||
91 | |||
50 | // ADB host | 92 | // ADB host |
51 | void adb_host_init(void); | 93 | void adb_host_init(void); |
52 | bool adb_host_psw(void); | 94 | bool adb_host_psw(void); |
95 | uint16_t adb_host_talk(uint8_t addr, uint8_t reg); | ||
96 | uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len); | ||
97 | void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l); | ||
98 | void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len); | ||
99 | void adb_host_flush(uint8_t addr); | ||
100 | void adb_host_kbd_led(uint8_t led); | ||
53 | uint16_t adb_host_kbd_recv(void); | 101 | uint16_t adb_host_kbd_recv(void); |
54 | uint16_t adb_host_mouse_recv(void); | 102 | uint16_t adb_host_mouse_recv(void); |
55 | void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l); | 103 | |
56 | void adb_host_kbd_led(uint8_t led); | 104 | // ADB Mouse |
57 | void adb_mouse_task(void); | 105 | void adb_mouse_task(void); |
58 | void adb_mouse_init(void); | 106 | void adb_mouse_init(void); |
diff --git a/tmk_core/protocol/arm_atsam/i2c_master.c b/tmk_core/protocol/arm_atsam/i2c_master.c index d3319ab44..dda2f85b0 100644 --- a/tmk_core/protocol/arm_atsam/i2c_master.c +++ b/tmk_core/protocol/arm_atsam/i2c_master.c | |||
@@ -28,6 +28,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
28 | 28 | ||
29 | # define I2C_LED_USE_DMA 1 // Set 1 to use background DMA transfers for leds, Set 0 to use inline software transfers | 29 | # define I2C_LED_USE_DMA 1 // Set 1 to use background DMA transfers for leds, Set 0 to use inline software transfers |
30 | 30 | ||
31 | DmacDescriptor dmac_desc; | ||
32 | DmacDescriptor dmac_desc_wb; | ||
33 | |||
31 | static uint8_t i2c_led_q[I2C_Q_SIZE]; // I2C queue circular buffer | 34 | static uint8_t i2c_led_q[I2C_Q_SIZE]; // I2C queue circular buffer |
32 | static uint8_t i2c_led_q_s; // Start of circular buffer | 35 | static uint8_t i2c_led_q_s; // Start of circular buffer |
33 | static uint8_t i2c_led_q_e; // End of circular buffer | 36 | static uint8_t i2c_led_q_e; // End of circular buffer |
diff --git a/tmk_core/protocol/arm_atsam/i2c_master.h b/tmk_core/protocol/arm_atsam/i2c_master.h index 44dbdfbff..68773f213 100644 --- a/tmk_core/protocol/arm_atsam/i2c_master.h +++ b/tmk_core/protocol/arm_atsam/i2c_master.h | |||
@@ -24,8 +24,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
24 | # include "issi3733_driver.h" | 24 | # include "issi3733_driver.h" |
25 | # include "config.h" | 25 | # include "config.h" |
26 | 26 | ||
27 | __attribute__((__aligned__(16))) DmacDescriptor dmac_desc; | 27 | extern __attribute__((__aligned__(16))) DmacDescriptor dmac_desc; |
28 | __attribute__((__aligned__(16))) DmacDescriptor dmac_desc_wb; | 28 | extern __attribute__((__aligned__(16))) DmacDescriptor dmac_desc_wb; |
29 | 29 | ||
30 | uint8_t I2C3733_Init_Control(void); | 30 | uint8_t I2C3733_Init_Control(void); |
31 | uint8_t I2C3733_Init_Drivers(void); | 31 | uint8_t I2C3733_Init_Drivers(void); |
diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index e10be52fb..a3d1f3449 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c | |||
@@ -306,9 +306,6 @@ int main(void) { | |||
306 | } | 306 | } |
307 | #endif // CONSOLE_ENABLE | 307 | #endif // CONSOLE_ENABLE |
308 | 308 | ||
309 | // Run housekeeping | ||
310 | housekeeping_task_kb(); | ||
311 | housekeeping_task_user(); | ||
312 | } | 309 | } |
313 | 310 | ||
314 | return 1; | 311 | return 1; |
diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index e07c181fc..63e4c99d2 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c | |||
@@ -163,6 +163,7 @@ int main(void) { | |||
163 | keyboard_setup(); | 163 | keyboard_setup(); |
164 | 164 | ||
165 | /* Init USB */ | 165 | /* Init USB */ |
166 | usb_event_queue_init(); | ||
166 | init_usb_driver(&USB_DRIVER); | 167 | init_usb_driver(&USB_DRIVER); |
167 | 168 | ||
168 | #ifdef MIDI_ENABLE | 169 | #ifdef MIDI_ENABLE |
@@ -221,6 +222,8 @@ int main(void) { | |||
221 | 222 | ||
222 | /* Main loop */ | 223 | /* Main loop */ |
223 | while (true) { | 224 | while (true) { |
225 | usb_event_queue_task(); | ||
226 | |||
224 | #if !defined(NO_USB_STARTUP_CHECK) | 227 | #if !defined(NO_USB_STARTUP_CHECK) |
225 | if (USB_DRIVER.state == USB_SUSPENDED) { | 228 | if (USB_DRIVER.state == USB_SUSPENDED) { |
226 | print("[s]"); | 229 | print("[s]"); |
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index ad489fb91..13b1e34d2 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | #include <ch.h> | 28 | #include <ch.h> |
29 | #include <hal.h> | 29 | #include <hal.h> |
30 | #include <string.h> | ||
30 | 31 | ||
31 | #include "usb_main.h" | 32 | #include "usb_main.h" |
32 | 33 | ||
@@ -368,6 +369,69 @@ static usb_driver_configs_t drivers = { | |||
368 | * --------------------------------------------------------- | 369 | * --------------------------------------------------------- |
369 | */ | 370 | */ |
370 | 371 | ||
372 | #define USB_EVENT_QUEUE_SIZE 16 | ||
373 | usbevent_t event_queue[USB_EVENT_QUEUE_SIZE]; | ||
374 | uint8_t event_queue_head; | ||
375 | uint8_t event_queue_tail; | ||
376 | |||
377 | void usb_event_queue_init(void) { | ||
378 | // Initialise the event queue | ||
379 | memset(&event_queue, 0, sizeof(event_queue)); | ||
380 | event_queue_head = 0; | ||
381 | event_queue_tail = 0; | ||
382 | } | ||
383 | |||
384 | static inline bool usb_event_queue_enqueue(usbevent_t event) { | ||
385 | uint8_t next = (event_queue_head + 1) % USB_EVENT_QUEUE_SIZE; | ||
386 | if (next == event_queue_tail) { | ||
387 | return false; | ||
388 | } | ||
389 | event_queue[event_queue_head] = event; | ||
390 | event_queue_head = next; | ||
391 | return true; | ||
392 | } | ||
393 | |||
394 | static inline bool usb_event_queue_dequeue(usbevent_t *event) { | ||
395 | if (event_queue_head == event_queue_tail) { | ||
396 | return false; | ||
397 | } | ||
398 | *event = event_queue[event_queue_tail]; | ||
399 | event_queue_tail = (event_queue_tail + 1) % USB_EVENT_QUEUE_SIZE; | ||
400 | return true; | ||
401 | } | ||
402 | |||
403 | static inline void usb_event_suspend_handler(void) { | ||
404 | #ifdef SLEEP_LED_ENABLE | ||
405 | sleep_led_enable(); | ||
406 | #endif /* SLEEP_LED_ENABLE */ | ||
407 | } | ||
408 | |||
409 | static inline void usb_event_wakeup_handler(void) { | ||
410 | suspend_wakeup_init(); | ||
411 | #ifdef SLEEP_LED_ENABLE | ||
412 | sleep_led_disable(); | ||
413 | // NOTE: converters may not accept this | ||
414 | led_set(host_keyboard_leds()); | ||
415 | #endif /* SLEEP_LED_ENABLE */ | ||
416 | } | ||
417 | |||
418 | void usb_event_queue_task(void) { | ||
419 | usbevent_t event; | ||
420 | while (usb_event_queue_dequeue(&event)) { | ||
421 | switch (event) { | ||
422 | case USB_EVENT_SUSPEND: | ||
423 | usb_event_suspend_handler(); | ||
424 | break; | ||
425 | case USB_EVENT_WAKEUP: | ||
426 | usb_event_wakeup_handler(); | ||
427 | break; | ||
428 | default: | ||
429 | // Nothing to do, we don't handle it. | ||
430 | break; | ||
431 | } | ||
432 | } | ||
433 | } | ||
434 | |||
371 | /* Handles the USB driver global events | 435 | /* Handles the USB driver global events |
372 | * TODO: maybe disable some things when connection is lost? */ | 436 | * TODO: maybe disable some things when connection is lost? */ |
373 | static void usb_event_cb(USBDriver *usbp, usbevent_t event) { | 437 | static void usb_event_cb(USBDriver *usbp, usbevent_t event) { |
@@ -402,9 +466,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) { | |||
402 | osalSysUnlockFromISR(); | 466 | osalSysUnlockFromISR(); |
403 | return; | 467 | return; |
404 | case USB_EVENT_SUSPEND: | 468 | case USB_EVENT_SUSPEND: |
405 | #ifdef SLEEP_LED_ENABLE | 469 | usb_event_queue_enqueue(USB_EVENT_SUSPEND); |
406 | sleep_led_enable(); | ||
407 | #endif /* SLEEP_LED_ENABLE */ | ||
408 | /* Falls into.*/ | 470 | /* Falls into.*/ |
409 | case USB_EVENT_UNCONFIGURED: | 471 | case USB_EVENT_UNCONFIGURED: |
410 | /* Falls into.*/ | 472 | /* Falls into.*/ |
@@ -425,12 +487,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) { | |||
425 | qmkusbWakeupHookI(&drivers.array[i].driver); | 487 | qmkusbWakeupHookI(&drivers.array[i].driver); |
426 | chSysUnlockFromISR(); | 488 | chSysUnlockFromISR(); |
427 | } | 489 | } |
428 | suspend_wakeup_init(); | 490 | usb_event_queue_enqueue(USB_EVENT_WAKEUP); |
429 | #ifdef SLEEP_LED_ENABLE | ||
430 | sleep_led_disable(); | ||
431 | // NOTE: converters may not accept this | ||
432 | led_set(host_keyboard_leds()); | ||
433 | #endif /* SLEEP_LED_ENABLE */ | ||
434 | return; | 491 | return; |
435 | 492 | ||
436 | case USB_EVENT_STALLED: | 493 | case USB_EVENT_STALLED: |
@@ -651,6 +708,17 @@ void init_usb_driver(USBDriver *usbp) { | |||
651 | void restart_usb_driver(USBDriver *usbp) { | 708 | void restart_usb_driver(USBDriver *usbp) { |
652 | usbStop(usbp); | 709 | usbStop(usbp); |
653 | usbDisconnectBus(usbp); | 710 | usbDisconnectBus(usbp); |
711 | |||
712 | #if USB_SUSPEND_WAKEUP_DELAY > 0 | ||
713 | // Some hubs, kvm switches, and monitors do | ||
714 | // weird things, with USB device state bouncing | ||
715 | // around wildly on wakeup, yielding race | ||
716 | // conditions that can corrupt the keyboard state. | ||
717 | // | ||
718 | // Pause for a while to let things settle... | ||
719 | wait_ms(USB_SUSPEND_WAKEUP_DELAY); | ||
720 | #endif | ||
721 | |||
654 | usbStart(usbp, &usbcfg); | 722 | usbStart(usbp, &usbcfg); |
655 | usbConnectBus(usbp); | 723 | usbConnectBus(usbp); |
656 | } | 724 | } |
diff --git a/tmk_core/protocol/chibios/usb_main.h b/tmk_core/protocol/chibios/usb_main.h index eaa08d8f7..fb33c8cd0 100644 --- a/tmk_core/protocol/chibios/usb_main.h +++ b/tmk_core/protocol/chibios/usb_main.h | |||
@@ -38,6 +38,17 @@ void init_usb_driver(USBDriver *usbp); | |||
38 | void restart_usb_driver(USBDriver *usbp); | 38 | void restart_usb_driver(USBDriver *usbp); |
39 | 39 | ||
40 | /* --------------- | 40 | /* --------------- |
41 | * USB Event queue | ||
42 | * --------------- | ||
43 | */ | ||
44 | |||
45 | /* Initialisation of the FIFO */ | ||
46 | void usb_event_queue_init(void); | ||
47 | |||
48 | /* Task to dequeue and execute any handlers for the USB events on the main thread */ | ||
49 | void usb_event_queue_task(void); | ||
50 | |||
51 | /* --------------- | ||
41 | * Keyboard header | 52 | * Keyboard header |
42 | * --------------- | 53 | * --------------- |
43 | */ | 54 | */ |
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 623aa33ff..74e48222d 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c | |||
@@ -435,7 +435,9 @@ void EVENT_USB_Device_Suspend() { | |||
435 | */ | 435 | */ |
436 | void EVENT_USB_Device_WakeUp() { | 436 | void EVENT_USB_Device_WakeUp() { |
437 | print("[W]"); | 437 | print("[W]"); |
438 | #if defined(NO_USB_STARTUP_CHECK) | ||
438 | suspend_wakeup_init(); | 439 | suspend_wakeup_init(); |
440 | #endif | ||
439 | 441 | ||
440 | #ifdef SLEEP_LED_ENABLE | 442 | #ifdef SLEEP_LED_ENABLE |
441 | sleep_led_disable(); | 443 | sleep_led_disable(); |
@@ -1073,12 +1075,26 @@ int main(void) { | |||
1073 | print("Keyboard start.\n"); | 1075 | print("Keyboard start.\n"); |
1074 | while (1) { | 1076 | while (1) { |
1075 | #if !defined(NO_USB_STARTUP_CHECK) | 1077 | #if !defined(NO_USB_STARTUP_CHECK) |
1076 | while (USB_DeviceState == DEVICE_STATE_Suspended) { | 1078 | if (USB_DeviceState == DEVICE_STATE_Suspended) { |
1077 | print("[s]"); | 1079 | print("[s]"); |
1078 | suspend_power_down(); | 1080 | while (USB_DeviceState == DEVICE_STATE_Suspended) { |
1079 | if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) { | 1081 | suspend_power_down(); |
1080 | USB_Device_SendRemoteWakeup(); | 1082 | if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) { |
1083 | USB_Device_SendRemoteWakeup(); | ||
1084 | clear_keyboard(); | ||
1085 | |||
1086 | # if USB_SUSPEND_WAKEUP_DELAY > 0 | ||
1087 | // Some hubs, kvm switches, and monitors do | ||
1088 | // weird things, with USB device state bouncing | ||
1089 | // around wildly on wakeup, yielding race | ||
1090 | // conditions that can corrupt the keyboard state. | ||
1091 | // | ||
1092 | // Pause for a while to let things settle... | ||
1093 | wait_ms(USB_SUSPEND_WAKEUP_DELAY); | ||
1094 | # endif | ||
1095 | } | ||
1081 | } | 1096 | } |
1097 | suspend_wakeup_init(); | ||
1082 | } | 1098 | } |
1083 | #endif | 1099 | #endif |
1084 | 1100 | ||
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 7ea4b2e37..ba7760f28 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c | |||
@@ -116,19 +116,15 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { | |||
116 | # endif | 116 | # endif |
117 | HID_RI_USAGE(8, 0x01), // Pointer | 117 | HID_RI_USAGE(8, 0x01), // Pointer |
118 | HID_RI_COLLECTION(8, 0x00), // Physical | 118 | HID_RI_COLLECTION(8, 0x00), // Physical |
119 | // Buttons (5 bits) | 119 | // Buttons (8 bits) |
120 | HID_RI_USAGE_PAGE(8, 0x09), // Button | 120 | HID_RI_USAGE_PAGE(8, 0x09), // Button |
121 | HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1 | 121 | HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1 |
122 | HID_RI_USAGE_MAXIMUM(8, 0x05), // Button 5 | 122 | HID_RI_USAGE_MAXIMUM(8, 0x08), // Button 8 |
123 | HID_RI_LOGICAL_MINIMUM(8, 0x00), | 123 | HID_RI_LOGICAL_MINIMUM(8, 0x00), |
124 | HID_RI_LOGICAL_MAXIMUM(8, 0x01), | 124 | HID_RI_LOGICAL_MAXIMUM(8, 0x01), |
125 | HID_RI_REPORT_COUNT(8, 0x05), | 125 | HID_RI_REPORT_COUNT(8, 0x08), |
126 | HID_RI_REPORT_SIZE(8, 0x01), | 126 | HID_RI_REPORT_SIZE(8, 0x01), |
127 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), | 127 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), |
128 | // Button padding (3 bits) | ||
129 | HID_RI_REPORT_COUNT(8, 0x01), | ||
130 | HID_RI_REPORT_SIZE(8, 0x03), | ||
131 | HID_RI_INPUT(8, HID_IOF_CONSTANT), | ||
132 | 128 | ||
133 | // X/Y position (2 bytes) | 129 | // X/Y position (2 bytes) |
134 | HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop | 130 | HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop |
@@ -356,7 +352,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = { | |||
356 | .Type = DTYPE_Device | 352 | .Type = DTYPE_Device |
357 | }, | 353 | }, |
358 | .USBSpecification = VERSION_BCD(1, 1, 0), | 354 | .USBSpecification = VERSION_BCD(1, 1, 0), |
359 | 355 | ||
360 | #if VIRTSER_ENABLE | 356 | #if VIRTSER_ENABLE |
361 | .Class = USB_CSCP_IADDeviceClass, | 357 | .Class = USB_CSCP_IADDeviceClass, |
362 | .SubClass = USB_CSCP_IADDeviceSubclass, | 358 | .SubClass = USB_CSCP_IADDeviceSubclass, |
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index a422903cc..9362fbde7 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c | |||
@@ -444,19 +444,15 @@ const PROGMEM uchar shared_hid_report[] = { | |||
444 | 0x85, REPORT_ID_MOUSE, // Report ID | 444 | 0x85, REPORT_ID_MOUSE, // Report ID |
445 | 0x09, 0x01, // Usage (Pointer) | 445 | 0x09, 0x01, // Usage (Pointer) |
446 | 0xA1, 0x00, // Collection (Physical) | 446 | 0xA1, 0x00, // Collection (Physical) |
447 | // Buttons (5 bits) | 447 | // Buttons (8 bits) |
448 | 0x05, 0x09, // Usage Page (Button) | 448 | 0x05, 0x09, // Usage Page (Button) |
449 | 0x19, 0x01, // Usage Minimum (Button 1) | 449 | 0x19, 0x01, // Usage Minimum (Button 1) |
450 | 0x29, 0x05, // Usage Maximum (Button 5) | 450 | 0x29, 0x08, // Usage Maximum (Button 8) |
451 | 0x15, 0x00, // Logical Minimum (0) | 451 | 0x15, 0x00, // Logical Minimum (0) |
452 | 0x25, 0x01, // Logical Maximum (1) | 452 | 0x25, 0x01, // Logical Maximum (1) |
453 | 0x95, 0x05, // Report Count (5) | 453 | 0x95, 0x08, // Report Count (8) |
454 | 0x75, 0x01, // Report Size (1) | 454 | 0x75, 0x01, // Report Size (1) |
455 | 0x81, 0x02, // Input (Data, Variable, Absolute) | 455 | 0x81, 0x02, // Input (Data, Variable, Absolute) |
456 | // Button padding (3 bits) | ||
457 | 0x95, 0x01, // Report Count (1) | ||
458 | 0x75, 0x03, // Report Size (3) | ||
459 | 0x81, 0x03, // Input (Constant) | ||
460 | 456 | ||
461 | // X/Y position (2 bytes) | 457 | // X/Y position (2 bytes) |
462 | 0x05, 0x01, // Usage Page (Generic Desktop) | 458 | 0x05, 0x01, // Usage Page (Generic Desktop) |