aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2016-08-23 11:05:26 -0400
committerGitHub <noreply@github.com>2016-08-23 11:05:26 -0400
commita9205484718ab2a74bc97884a2ea7b95882ed66d (patch)
treefcc4e5429bf545dca85f32d7a174388e61966438
parentfb4452c2f5a80720fd56306ea4fa7c61a5e8040d (diff)
parent7009112752ed0729b9c20382c936a8d373062ada (diff)
downloadqmk_firmware-a9205484718ab2a74bc97884a2ea7b95882ed66d.tar.gz
qmk_firmware-a9205484718ab2a74bc97884a2ea7b95882ed66d.zip
Merge pull request #677 from SmackleFunky/master
Virtual Serial Port - and a Layout that uses that virtual serial port for Plover
-rw-r--r--Makefile4
-rw-r--r--keyboards/ergodox/ez/keymaps/steno/Makefile3
-rw-r--r--keyboards/ergodox/ez/keymaps/steno/keymap.c324
-rw-r--r--keyboards/ergodox/ez/keymaps/steno/readme.md92
-rw-r--r--tmk_core/common/virtser.h10
-rw-r--r--tmk_core/protocol/lufa.mk4
-rw-r--r--tmk_core/protocol/lufa/descriptor.c112
-rw-r--r--tmk_core/protocol/lufa/descriptor.h43
-rw-r--r--tmk_core/protocol/lufa/lufa.c107
9 files changed, 695 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index 693edc9f0..331badcf8 100644
--- a/Makefile
+++ b/Makefile
@@ -190,6 +190,10 @@ ifeq ($(strip $(MIDI_ENABLE)), yes)
190 SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c 190 SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c
191endif 191endif
192 192
193ifeq ($(strip $(VIRTSER_ENABLE)), yes)
194 OPT_DEFS += -DVIRTSER_ENABLE
195endif
196
193ifeq ($(strip $(AUDIO_ENABLE)), yes) 197ifeq ($(strip $(AUDIO_ENABLE)), yes)
194 OPT_DEFS += -DAUDIO_ENABLE 198 OPT_DEFS += -DAUDIO_ENABLE
195 SRC += $(QUANTUM_DIR)/process_keycode/process_music.c 199 SRC += $(QUANTUM_DIR)/process_keycode/process_music.c
diff --git a/keyboards/ergodox/ez/keymaps/steno/Makefile b/keyboards/ergodox/ez/keymaps/steno/Makefile
new file mode 100644
index 000000000..b6fb9b1a8
--- /dev/null
+++ b/keyboards/ergodox/ez/keymaps/steno/Makefile
@@ -0,0 +1,3 @@
1VIRTSER_ENABLE = yes
2# Not enough interupts, so something has to go
3MOUSEKEY_ENABLE = no
diff --git a/keyboards/ergodox/ez/keymaps/steno/keymap.c b/keyboards/ergodox/ez/keymaps/steno/keymap.c
new file mode 100644
index 000000000..3e9830905
--- /dev/null
+++ b/keyboards/ergodox/ez/keymaps/steno/keymap.c
@@ -0,0 +1,324 @@
1#include "ergodox.h"
2#include "debug.h"
3#include "action_layer.h"
4#include "sendchar.h"
5#include "virtser.h"
6
7#define BASE 0 // default layer
8#define SYMB 1 // symbols
9#define MDIA 2 // media keys
10#define TXBOLT 3 // TxBolt Steno Virtual Serial
11#define TXBOLT2 4 // TxBolt Steno Virtual Serial Alternative Layout
12
13const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
14/* Keymap 0: Basic layer
15 *
16 * ,--------------------------------------------------. ,--------------------------------------------------.
17 * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
18 * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
19 * | Del | Q | W | E | R | T | L1 | | TX | Y | U | I | O | P | \ |
20 * |--------+------+------+------+------+------| | | BOLT |------+------+------+------+------+--------|
21 * | BkSp | A | S | D | F | G |------| |------| H | J | K | L |; / L2|' / Cmd |
22 * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
23 * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
24 * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
25 * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
26 * `----------------------------------' `----------------------------------'
27 * ,-------------. ,-------------.
28 * | App | LGui | | Alt |Ctrl/Esc|
29 * ,------|------|------| |------+--------+------.
30 * | | | Home | | PgUp | | |
31 * | Space|Backsp|------| |------| Tab |Enter |
32 * | |ace | End | | PgDn | | |
33 * `--------------------' `----------------------'
34 */
35// If it accepts an argument (i.e, is a function), it doesn't need KC_.
36// Otherwise, it needs KC_*
37[BASE] = KEYMAP( // layer 0 : default
38 // left hand
39 KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
40 KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(SYMB),
41 KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G,
42 KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
43 LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
44 ALT_T(KC_APP), KC_LGUI,
45 KC_HOME,
46 KC_SPC,KC_BSPC,KC_END,
47 // right hand
48 KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
49 TG(TXBOLT), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
50 KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),GUI_T(KC_QUOT),
51 MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
52 KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
53 KC_LALT, CTL_T(KC_ESC),
54 KC_PGUP,
55 KC_PGDN,KC_TAB, KC_ENT
56 ),
57/* Keymap 1: Symbol Layer
58 *
59 * ,--------------------------------------------------. ,--------------------------------------------------.
60 * |Version | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
61 * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
62 * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
63 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
64 * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
65 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
66 * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
67 * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
68 * | | | | | | | | . | 0 | = | |
69 * `----------------------------------' `----------------------------------'
70 * ,-------------. ,-------------.
71 * | | | | | |
72 * ,------|------|------| |------+------+------.
73 * | | | | | | | |
74 * | | |------| |------| | |
75 * | | | | | | | |
76 * `--------------------' `--------------------'
77 */
78// SYMBOLS
79[SYMB] = KEYMAP(
80 // left hand
81 M(0), KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
82 KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
83 KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
84 KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
85 KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
86 KC_TRNS,KC_TRNS,
87 KC_TRNS,
88 KC_TRNS,KC_TRNS,KC_TRNS,
89 // right hand
90 KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
91 KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
92 KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
93 KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
94 KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
95 KC_TRNS, KC_TRNS,
96 KC_TRNS,
97 KC_TRNS, KC_TRNS, KC_TRNS
98),
99/* Keymap 2: Media and mouse keys
100 *
101 * ,--------------------------------------------------. ,--------------------------------------------------.
102 * | RESET | | | | | | | | | | | | | | |
103 * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
104 * | | | | MsUp | | | | | | | | | | | |
105 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
106 * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
107 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
108 * | | | | | | | | | | | | Prev | Next | | |
109 * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
110 * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
111 * `----------------------------------' `----------------------------------'
112 * ,-------------. ,-------------.
113 * | | | | | |
114 * ,------|------|------| |------+------+------.
115 * | | | | | | |Brwser|
116 * | | |------| |------| |Back |
117 * | | | | | | | |
118 * `--------------------' `--------------------'
119 */
120// MEDIA AND MOUSE
121[MDIA] = KEYMAP(
122 RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
123 KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
124 KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
125 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
126 KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
127 KC_TRNS, KC_TRNS,
128 KC_TRNS,
129 KC_TRNS, KC_TRNS, KC_TRNS,
130 // right hand
131 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
132 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
133 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
134 KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
135 KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
136 KC_TRNS, KC_TRNS,
137 KC_TRNS,
138 KC_TRNS, KC_TRNS, KC_WBAK
139),
140// TxBolt Codes
141#define Sl 0b00000001
142#define Tl 0b00000010
143#define Kl 0b00000100
144#define Pl 0b00001000
145#define Wl 0b00010000
146#define Hl 0b00100000
147#define Rl 0b01000001
148#define Al 0b01000010
149#define Ol 0b01000100
150#define X 0b01001000
151#define Er 0b01010000
152#define Ur 0b01100000
153#define Fr 0b10000001
154#define Rr 0b10000010
155#define Pr 0b10000100
156#define Br 0b10001000
157#define Lr 0b10010000
158#define Gr 0b10100000
159#define Tr 0b11000001
160#define Sr 0b11000010
161#define Dr 0b11000100
162#define Zr 0b11001000
163#define NM 0b11010000
164#define GRPMASK 0b11000000
165#define GRP0 0b00000000
166#define GRP1 0b01000000
167#define GRP2 0b10000000
168#define GRP3 0b11000000
169/* Keymap 3: TxBolt (Serial)
170 *
171 * ,--------------------------------------------------. ,--------------------------------------------------.
172 * | BKSPC | | | | | | | | | | | | | | |
173 * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
174 * | | # | # | # | # | # | | | | # | # | # | # | # | # |
175 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
176 * | | S | T | P | H | * |------| |------| * | F | P | L | T | D |
177 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
178 * | | S | K | W | R | * | | | | * | R | B | G | S | Z |
179 * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
180 * | | | | | | | | | | | |
181 * `----------------------------------' `----------------------------------'
182 * ,-------------. ,-------------.
183 * | | | | | |
184 * ,------|------|------| |------+------+------.
185 * | | | | | | | |
186 * | A | O |------| |------| E | U |
187 * | | | | | | | |
188 * `--------------------' `--------------------'
189 */
190// TxBolt over Serial
191[TXBOLT] = KEYMAP(
192 KC_BSPC, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
193 KC_NO, M(NM), M(NM), M(NM), M(NM), M(NM), KC_NO,
194 KC_NO, M(Sl), M(Tl), M(Pl), M(Hl), M(X),
195 KC_NO, M(Sl), M(Kl), M(Wl), M(Rl), M(X), KC_NO,
196 KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
197 KC_NO, KC_NO,
198 KC_NO,
199 M(Al), M(Ol), KC_NO,
200 // right hand
201 KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
202 KC_TRNS, M(NM), M(NM), M(NM), M(NM), M(NM), M(NM),
203 M(X), M(Fr), M(Pr), M(Lr), M(Tr), M(Dr),
204 KC_NO, M(X), M(Rr), M(Br), M(Gr), M(Sr), M(Zr),
205 KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
206 KC_NO, KC_NO,
207 KC_NO,
208 KC_NO, M(Er), M(Ur)
209),
210/* Keymap 4: TxBolt (Serial) Alternative
211 *
212 * ,--------------------------------------------------. ,--------------------------------------------------.
213 * | | # | # | # | # | # | | | | # | # | # | # | # | # |
214 * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
215 * | | S | T | P | H | * | | | | * | F | P | L | T | D |
216 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
217 * | | S | K | W | R | * |------| |------| * | R | B | G | S | Z |
218 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
219 * | | | | | | | | | | | | | | | |
220 * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
221 * | | | | A | O | | E | U | | | |
222 * `----------------------------------' `----------------------------------'
223 * ,-------------. ,-------------.
224 * | | | | | |
225 * ,------|------|------| |------+------+------.
226 * | | | | | | | |
227 * | | |------| |------| | |
228 * | | | | | | | |
229 * `--------------------' `--------------------'
230 */
231// TxBolt over Serial
232[TXBOLT2] = KEYMAP(
233 KC_NO, M(NM), M(NM), M(NM), M(NM), M(NM), KC_NO,
234 KC_NO, M(Sl), M(Tl), M(Pl), M(Hl), M(X), KC_NO,
235 KC_NO, M(Sl), M(Kl), M(Wl), M(Rl), M(X),
236 KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
237 KC_NO, KC_NO, KC_NO, M(Al), M(Ol),
238 KC_NO, KC_NO,
239 KC_NO,
240 KC_NO, KC_NO, KC_NO,
241 // right hand
242 KC_NO, M(NM), M(NM), M(NM), M(NM), M(NM), M(NM),
243 KC_TRNS, M(X), M(Fr), M(Pr), M(Lr), M(Tr), M(Dr),
244 M(X), M(Rr), M(Br), M(Gr), M(Sr), M(Zr),
245 KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
246 M(Er), M(Ur), KC_NO, KC_NO, KC_NO,
247 KC_NO, KC_NO,
248 KC_NO,
249 KC_NO, KC_NO, KC_NO
250),
251};
252
253const uint16_t PROGMEM fn_actions[] = {
254 [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
255};
256
257uint8_t chord[4] = {0,0,0,0};
258uint8_t pressed_count = 0;
259
260void send_chord(void)
261{
262 for(uint8_t i = 0; i < 4; i++)
263 {
264 if(chord[i])
265 virtser_send(chord[i]);
266 }
267 virtser_send(0);
268}
269
270bool process_record_user(uint16_t keycode, keyrecord_t *record)
271{
272 // We need to track keypresses in all modes, in case the user
273 // changes mode whilst pressing other keys.
274 if (record->event.pressed)
275 pressed_count++;
276 else
277 pressed_count--;
278 return true;
279}
280
281const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
282{
283 // MACRODOWN only works in this function
284
285 if (record->event.pressed) {
286 uint8_t grp = (id & GRPMASK) >> 6;
287 chord[grp] |= id;
288 }
289 else {
290 if (pressed_count == 0) {
291 send_chord();
292 chord[0] = chord[1] = chord[2] = chord[3] = 0;
293 }
294 }
295 return MACRO_NONE;
296};
297
298// Runs just one time when the keyboard initializes.
299void matrix_init_user(void) {
300};
301
302// Runs constantly in the background, in a loop.
303void matrix_scan_user(void) {
304
305 uint8_t layer = biton32(layer_state);
306
307 ergodox_board_led_off();
308 ergodox_right_led_1_off();
309 ergodox_right_led_2_off();
310 ergodox_right_led_3_off();
311 switch (layer) {
312 // TODO: Make this relevant to the ErgoDox EZ.
313 case 1:
314 ergodox_right_led_1_on();
315 break;
316 case 2:
317 ergodox_right_led_2_on();
318 break;
319 default:
320 // none
321 break;
322 }
323
324};
diff --git a/keyboards/ergodox/ez/keymaps/steno/readme.md b/keyboards/ergodox/ez/keymaps/steno/readme.md
new file mode 100644
index 000000000..d67cde2a3
--- /dev/null
+++ b/keyboards/ergodox/ez/keymaps/steno/readme.md
@@ -0,0 +1,92 @@
1# ErgoDox EZ Steno Configuration
2
3This layout has a layer that uses the TxBolt Stenograph protocol over a Virtual Serial port. It requires something like Plover in order to function.
4
5In Plover, you can select TX Bolt as the Stenotype Machine, and find the COM port that was assigned. In this way, your regular keyboard will still function normally, and you can switch back and forth between the Steno and Keyboard layers.
6
7<pre><code>
8/* Keymap 0: Basic layer
9 *
10 * ,--------------------------------------------------. ,--------------------------------------------------.
11 * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
12 * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
13 * | Del | Q | W | E | R | T | L1 | | TX | Y | U | I | O | P | \ |
14 * |--------+------+------+------+------+------| | | BOLT |------+------+------+------+------+--------|
15 * | BkSp | A | S | D | F | G |------| |------| H | J | K | L |; / L2|' / Cmd |
16 * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
17 * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
18 * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
19 * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
20 * `----------------------------------' `----------------------------------'
21 * ,-------------. ,-------------.
22 * | App | LGui | | Alt |Ctrl/Esc|
23 * ,------|------|------| |------+--------+------.
24 * | | | Home | | PgUp | | |
25 * | Space|Backsp|------| |------| Tab |Enter |
26 * | |ace | End | | PgDn | | |
27 * `--------------------' `----------------------'
28 */
29/* Keymap 1: Symbol Layer
30 *
31 * ,--------------------------------------------------. ,--------------------------------------------------.
32 * |Version | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
33 * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
34 * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
35 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
36 * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
37 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
38 * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
39 * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
40 * | | | | | | | | . | 0 | = | |
41 * `----------------------------------' `----------------------------------'
42 * ,-------------. ,-------------.
43 * | | | | | |
44 * ,------|------|------| |------+------+------.
45 * | | | | | | | |
46 * | | |------| |------| | |
47 * | | | | | | | |
48 * `--------------------' `--------------------'
49 */
50/* Keymap 2: Media keys
51 *
52 * ,--------------------------------------------------. ,--------------------------------------------------.
53 * | RESET | | | | | | | | | | | | | | |
54 * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
55 * | | | | | | | | | | | | | | | |
56 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
57 * | | | | | | |------| |------| | | | | | Play |
58 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
59 * | | | | | | | | | | | | Prev | Next | | |
60 * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
61 * | | | | | | |VolUp |VolDn | Mute | | |
62 * `----------------------------------' `----------------------------------'
63 * ,-------------. ,-------------.
64 * | | | | | |
65 * ,------|------|------| |------+------+------.
66 * | | | | | | |Brwser|
67 * | | |------| |------| |Back |
68 * | | | | | | | |
69 * `--------------------' `--------------------'
70 */
71/* Keymap 3: TxBolt (Serial)
72 *
73 * ,--------------------------------------------------. ,--------------------------------------------------.
74 * | BKSPC | | | | | | | | | | | | | | |
75 * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
76 * | | # | # | # | # | # | | | | # | # | # | # | # | # |
77 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
78 * | | S | T | P | H | * |------| |------| * | F | P | L | T | D |
79 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
80 * | | S | K | W | R | * | | | | * | R | B | G | S | Z |
81 * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
82 * | | | | | | | | | | | |
83 * `----------------------------------' `----------------------------------'
84 * ,-------------. ,-------------.
85 * | | | | | |
86 * ,------|------|------| |------+------+------.
87 * | | | | | | | |
88 * | A | O |------| |------| E | U |
89 * | | | | | | | |
90 * `--------------------' `--------------------'
91 */
92</code></pre>
diff --git a/tmk_core/common/virtser.h b/tmk_core/common/virtser.h
new file mode 100644
index 000000000..74891b6ae
--- /dev/null
+++ b/tmk_core/common/virtser.h
@@ -0,0 +1,10 @@
1#ifndef _VIRTSER_H_
2#define _VIRTSER_H_
3
4/* Define this function in your code to process incoming bytes */
5void virtser_recv(const uint8_t ch);
6
7/* Call this to send a character over the Virtual Serial Device */
8void virtser_send(const uint8_t byte);
9
10#endif
diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk
index 0eeace44e..5b1e3d19d 100644
--- a/tmk_core/protocol/lufa.mk
+++ b/tmk_core/protocol/lufa.mk
@@ -26,6 +26,10 @@ ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
26 $(TMK_DIR)/protocol/serial_uart.c 26 $(TMK_DIR)/protocol/serial_uart.c
27endif 27endif
28 28
29ifeq ($(strip $(VIRTSER_ENABLE)), yes)
30 LUFA_SRC += $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/CDCClassDevice.c
31endif
32
29SRC += $(LUFA_SRC) 33SRC += $(LUFA_SRC)
30 34
31# Search Path 35# Search Path
diff --git a/tmk_core/protocol/lufa/descriptor.c b/tmk_core/protocol/lufa/descriptor.c
index 539a58d66..6f2407f58 100644
--- a/tmk_core/protocol/lufa/descriptor.c
+++ b/tmk_core/protocol/lufa/descriptor.c
@@ -231,9 +231,15 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
231 .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, 231 .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
232 232
233 .USBSpecification = VERSION_BCD(1,1,0), 233 .USBSpecification = VERSION_BCD(1,1,0),
234#if VIRTSER_ENABLE
235 .Class = USB_CSCP_IADDeviceClass,
236 .SubClass = USB_CSCP_IADDeviceSubclass,
237 .Protocol = USB_CSCP_IADDeviceProtocol,
238#else
234 .Class = USB_CSCP_NoDeviceClass, 239 .Class = USB_CSCP_NoDeviceClass,
235 .SubClass = USB_CSCP_NoDeviceSubclass, 240 .SubClass = USB_CSCP_NoDeviceSubclass,
236 .Protocol = USB_CSCP_NoDeviceProtocol, 241 .Protocol = USB_CSCP_NoDeviceProtocol,
242#endif
237 243
238 .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, 244 .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
239 245
@@ -643,8 +649,112 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
643 649
644 .TotalEmbeddedJacks = 0x01, 650 .TotalEmbeddedJacks = 0x01,
645 .AssociatedJackID = {0x03} 651 .AssociatedJackID = {0x03}
646 } 652 },
647#endif 653#endif
654
655#ifdef VIRTSER_ENABLE
656 .CDC_Interface_Association =
657 {
658 .Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
659
660 .FirstInterfaceIndex = CCI_INTERFACE,
661 .TotalInterfaces = 2,
662
663 .Class = CDC_CSCP_CDCClass,
664 .SubClass = CDC_CSCP_ACMSubclass,
665 .Protocol = CDC_CSCP_ATCommandProtocol,
666
667 .IADStrIndex = NO_DESCRIPTOR,
668 },
669
670 .CDC_CCI_Interface =
671 {
672 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
673
674 .InterfaceNumber = CCI_INTERFACE,
675 .AlternateSetting = 0,
676
677 .TotalEndpoints = 1,
678
679 .Class = CDC_CSCP_CDCClass,
680 .SubClass = CDC_CSCP_ACMSubclass,
681 .Protocol = CDC_CSCP_ATCommandProtocol,
682
683 .InterfaceStrIndex = NO_DESCRIPTOR
684 },
685
686 .CDC_Functional_Header =
687 {
688 .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface},
689 .Subtype = 0x00,
690
691 .CDCSpecification = VERSION_BCD(1,1,0),
692 },
693
694 .CDC_Functional_ACM =
695 {
696 .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface},
697 .Subtype = 0x02,
698
699 .Capabilities = 0x02,
700 },
701
702 .CDC_Functional_Union =
703 {
704 .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface},
705 .Subtype = 0x06,
706
707 .MasterInterfaceNumber = CCI_INTERFACE,
708 .SlaveInterfaceNumber = CDI_INTERFACE,
709 },
710
711 .CDC_NotificationEndpoint =
712 {
713 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
714
715 .EndpointAddress = CDC_NOTIFICATION_EPADDR,
716 .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
717 .EndpointSize = CDC_NOTIFICATION_EPSIZE,
718 .PollingIntervalMS = 0xFF
719 },
720
721 .CDC_DCI_Interface =
722 {
723 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
724
725 .InterfaceNumber = CDI_INTERFACE,
726 .AlternateSetting = 0,
727
728 .TotalEndpoints = 2,
729
730 .Class = CDC_CSCP_CDCDataClass,
731 .SubClass = CDC_CSCP_NoDataSubclass,
732 .Protocol = CDC_CSCP_NoDataProtocol,
733
734 .InterfaceStrIndex = NO_DESCRIPTOR
735 },
736
737 .CDC_DataOutEndpoint =
738 {
739 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
740
741 .EndpointAddress = CDC_OUT_EPADDR,
742 .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
743 .EndpointSize = CDC_EPSIZE,
744 .PollingIntervalMS = 0x05
745 },
746
747 .CDC_DataInEndpoint =
748 {
749 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
750
751 .EndpointAddress = CDC_IN_EPADDR,
752 .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
753 .EndpointSize = CDC_EPSIZE,
754 .PollingIntervalMS = 0x05
755 },
756#endif
757
648}; 758};
649 759
650 760
diff --git a/tmk_core/protocol/lufa/descriptor.h b/tmk_core/protocol/lufa/descriptor.h
index 4fd81a0e8..316650a7b 100644
--- a/tmk_core/protocol/lufa/descriptor.h
+++ b/tmk_core/protocol/lufa/descriptor.h
@@ -104,6 +104,21 @@ typedef struct
104 USB_MIDI_Descriptor_Jack_Endpoint_t MIDI_Out_Jack_Endpoint_SPC; 104 USB_MIDI_Descriptor_Jack_Endpoint_t MIDI_Out_Jack_Endpoint_SPC;
105#endif 105#endif
106 106
107#ifdef VIRTSER_ENABLE
108 USB_Descriptor_Interface_Association_t CDC_Interface_Association;
109
110 // CDC Control Interface
111 USB_Descriptor_Interface_t CDC_CCI_Interface;
112 USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
113 USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
114 USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
115 USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
116
117 // CDC Data Interface
118 USB_Descriptor_Interface_t CDC_DCI_Interface;
119 USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
120 USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
121#endif
107} USB_Descriptor_Configuration_t; 122} USB_Descriptor_Configuration_t;
108 123
109 124
@@ -141,8 +156,15 @@ typedef struct
141# define AS_INTERFACE NKRO_INTERFACE 156# define AS_INTERFACE NKRO_INTERFACE
142#endif 157#endif
143 158
159#ifdef VIRTSER_ENABLE
160# define CCI_INTERFACE (AS_INTERFACE + 1)
161# define CDI_INTERFACE (AS_INTERFACE + 2)
162#else
163# define CDI_INTERFACE AS_INTERFACE
164#endif
165
144/* nubmer of interfaces */ 166/* nubmer of interfaces */
145#define TOTAL_INTERFACES AS_INTERFACE + 1 167#define TOTAL_INTERFACES (CDI_INTERFACE + 1)
146 168
147 169
148// Endopoint number and size 170// Endopoint number and size
@@ -180,11 +202,24 @@ typedef struct
180# define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 2) 202# define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 2)
181# define MIDI_STREAM_IN_EPADDR (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM) 203# define MIDI_STREAM_IN_EPADDR (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM)
182# define MIDI_STREAM_OUT_EPADDR (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM) 204# define MIDI_STREAM_OUT_EPADDR (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM)
205#else
206# define MIDI_STREAM_OUT_EPNUM NKRO_IN_EPNUM
207#endif
208
209#ifdef VIRTSER_ENABLE
210# define CDC_NOTIFICATION_EPNUM (MIDI_STREAM_OUT_EPNUM + 1)
211# define CDC_IN_EPNUM (MIDI_STREAM_OUT_EPNUM + 2)
212# define CDC_OUT_EPNUM (MIDI_STREAM_OUT_EPNUM + 3)
213# define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM)
214# define CDC_IN_EPADDR (ENDPOINT_DIR_IN | CDC_IN_EPNUM)
215# define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM)
216#else
217# define CDC_OUT_EPNUM MIDI_STREAM_OUT_EPNUM
183#endif 218#endif
184 219
185 220
186#if defined(__AVR_ATmega32U2__) && MIDI_STREAM_OUT_EPADDR > 4 221#if defined(__AVR_ATmega32U2__) && CDC_OUT_EPNUM > 4
187# error "Endpoints are not available enough to support all functions. Remove some in Makefile.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI)" 222# error "Endpoints are not available enough to support all functions. Remove some in Makefile.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI, SERIAL)"
188#endif 223#endif
189 224
190#define KEYBOARD_EPSIZE 8 225#define KEYBOARD_EPSIZE 8
@@ -193,6 +228,8 @@ typedef struct
193#define CONSOLE_EPSIZE 32 228#define CONSOLE_EPSIZE 32
194#define NKRO_EPSIZE 16 229#define NKRO_EPSIZE 16
195#define MIDI_STREAM_EPSIZE 64 230#define MIDI_STREAM_EPSIZE 64
231#define CDC_NOTIFICATION_EPSIZE 8
232#define CDC_EPSIZE 16
196 233
197 234
198uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, 235uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index 9ca55dbc9..9b201374a 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -60,6 +60,10 @@
60 #include "bluetooth.h" 60 #include "bluetooth.h"
61#endif 61#endif
62 62
63#ifdef VIRTSER_ENABLE
64 #include "virtser.h"
65#endif
66
63uint8_t keyboard_idle = 0; 67uint8_t keyboard_idle = 0;
64/* 0: Boot Protocol, 1: Report Protocol(default) */ 68/* 0: Boot Protocol, 1: Report Protocol(default) */
65uint8_t keyboard_protocol = 1; 69uint8_t keyboard_protocol = 1;
@@ -127,6 +131,34 @@ USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface =
127#define SYS_COMMON_3 0x30 131#define SYS_COMMON_3 0x30
128#endif 132#endif
129 133
134#ifdef VIRTSER_ENABLE
135USB_ClassInfo_CDC_Device_t cdc_device =
136{
137 .Config =
138 {
139 .ControlInterfaceNumber = CCI_INTERFACE,
140 .DataINEndpoint =
141 {
142 .Address = CDC_IN_EPADDR,
143 .Size = CDC_EPSIZE,
144 .Banks = 1,
145 },
146 .DataOUTEndpoint =
147 {
148 .Address = CDC_OUT_EPADDR,
149 .Size = CDC_EPSIZE,
150 .Banks = 1,
151 },
152 .NotificationEndpoint =
153 {
154 .Address = CDC_NOTIFICATION_EPADDR,
155 .Size = CDC_NOTIFICATION_EPSIZE,
156 .Banks = 1,
157 },
158 },
159};
160#endif
161
130 162
131/******************************************************************************* 163/*******************************************************************************
132 * Console 164 * Console
@@ -311,6 +343,12 @@ void EVENT_USB_Device_ConfigurationChanged(void)
311 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); 343 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
312 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); 344 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
313#endif 345#endif
346
347#ifdef VIRTSER_ENABLE
348 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPADDR, EP_TYPE_INTERRUPT, CDC_NOTIFICATION_EPSIZE, ENDPOINT_BANK_SINGLE);
349 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_OUT_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
350 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_IN_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
351#endif
314} 352}
315 353
316/* 354/*
@@ -432,10 +470,15 @@ void EVENT_USB_Device_ControlRequest(void)
432 470
433 break; 471 break;
434 } 472 }
473
474#ifdef VIRTSER_ENABLE
475 CDC_Device_ProcessControlRequest(&cdc_device);
476#endif
435} 477}
436 478
437/******************************************************************************* 479/*******************************************************************************
438 * Host driver 480 * Host driver
481p
439 ******************************************************************************/ 482 ******************************************************************************/
440static uint8_t keyboard_leds(void) 483static uint8_t keyboard_leds(void)
441{ 484{
@@ -827,6 +870,61 @@ void MIDI_Task(void)
827 870
828#endif 871#endif
829 872
873/*******************************************************************************
874 * VIRTUAL SERIAL
875 ******************************************************************************/
876
877#ifdef VIRTSER_ENABLE
878void virtser_init(void)
879{
880 cdc_device.State.ControlLineStates.DeviceToHost = CDC_CONTROL_LINE_IN_DSR ;
881 CDC_Device_SendControlLineStateChange(&cdc_device);
882}
883
884void virtser_recv(uint8_t c) __attribute__ ((weak));
885void virtser_recv(uint8_t c)
886{
887 // Ignore by default
888}
889
890void virtser_task(void)
891{
892 uint16_t count = CDC_Device_BytesReceived(&cdc_device);
893 uint8_t ch;
894 if (count)
895 {
896 ch = CDC_Device_ReceiveByte(&cdc_device);
897 virtser_recv(ch);
898 }
899}
900void virtser_send(const uint8_t byte)
901{
902 uint8_t timeout = 255;
903 uint8_t ep = Endpoint_GetCurrentEndpoint();
904
905 if (cdc_device.State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR)
906 {
907 /* IN packet */
908 Endpoint_SelectEndpoint(cdc_device.Config.DataINEndpoint.Address);
909
910 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
911 Endpoint_SelectEndpoint(ep);
912 return;
913 }
914
915 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
916
917 Endpoint_Write_8(byte);
918 CDC_Device_Flush(&cdc_device);
919
920 if (Endpoint_IsINReady()) {
921 Endpoint_ClearIN();
922 }
923
924 Endpoint_SelectEndpoint(ep);
925 }
926}
927#endif
830 928
831/******************************************************************************* 929/*******************************************************************************
832 * main 930 * main
@@ -918,6 +1016,10 @@ int main(void)
918 sleep_led_init(); 1016 sleep_led_init();
919#endif 1017#endif
920 1018
1019#ifdef VIRTSER_ENABLE
1020 virtser_init();
1021#endif
1022
921 print("Keyboard start.\n"); 1023 print("Keyboard start.\n");
922 while (1) { 1024 while (1) {
923 #ifndef BLUETOOTH_ENABLE 1025 #ifndef BLUETOOTH_ENABLE
@@ -936,6 +1038,11 @@ int main(void)
936#endif 1038#endif
937 keyboard_task(); 1039 keyboard_task();
938 1040
1041#ifdef VIRTSER_ENABLE
1042 virtser_task();
1043 CDC_Device_USBTask(&cdc_device);
1044#endif
1045
939#if !defined(INTERRUPT_CONTROL_ENDPOINT) 1046#if !defined(INTERRUPT_CONTROL_ENDPOINT)
940 USB_USBTask(); 1047 USB_USBTask();
941#endif 1048#endif