aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/protocol/chibios
diff options
context:
space:
mode:
authorfredizzimo <fsundvik@gmail.com>2018-02-08 22:07:46 +0200
committerJack Humbert <jack.humb@gmail.com>2018-02-08 15:07:46 -0500
commit53ff8a31b61952d9675558149d927f7942071df9 (patch)
treea57b9e6f7d6494c9ef903f886a660dd43f4e5044 /tmk_core/protocol/chibios
parent63c16f4b632a2a82a775f51a3ad0cc690cca1fc9 (diff)
downloadqmk_firmware-53ff8a31b61952d9675558149d927f7942071df9.tar.gz
qmk_firmware-53ff8a31b61952d9675558149d927f7942071df9.zip
Merge ChibiOS and LUFA descriptor support (#2362)
* Move lufa descriptor to protocol/usb_descriptor * Try to compile usb_descriptor on ChibiOS * Add lufa_utils for ChibiOS Lufa USB descriptors for ChibiOS * More lufa_util compatibility fixes * First compiling version of shared USB descriptor * Send the usb descriptors * Fix the CONSOLE output on ChibiOS * Add errors for unsupported interfaces * Enable support for vitual serial port USB descriptors * Implement virtual serial port for ChibiOS * Cleanup the lufa_utils Use the default lufa header files * Add raw hid support for ChibiOS This is completely untested * Enable midi compilation on ChibiOS * Move midi functionality out of lufa.c * Don't register sysex callback when not needed * ChibiOS compilation fixes * Update ChibiOS submodule * Fix the Midi USB descriptor It didn't work properly when both Midi and Virtual serial port was enabled. * Add MIDI support for ChibiOS * Fix USB descriptor strings on ChibiOS * Use serial usb driver for raw hid * Generalize the ChibiOS stream like drivers This makes the initialization much more simple and eliminates a lot of the code duplication. * Convert console output to chibios stream driver * Fixes for ChibiOS update * Update the ChibiOS contrib submodule To include the usb data toggle synchronization fixes * Fix duplicate reset enumeration on ChibiOS * Add missing include * Add number of endpoints check for ChibiOS * Enable serial USB driver on all keyboards * Add missing includes when API is enabled withot midi * Add another missing inlcude
Diffstat (limited to 'tmk_core/protocol/chibios')
-rw-r--r--tmk_core/protocol/chibios/lufa_utils/LUFA/Drivers/USB/USB.h42
-rw-r--r--tmk_core/protocol/chibios/main.c27
-rw-r--r--tmk_core/protocol/chibios/usb_main.c1027
-rw-r--r--tmk_core/protocol/chibios/usb_main.h34
4 files changed, 348 insertions, 782 deletions
diff --git a/tmk_core/protocol/chibios/lufa_utils/LUFA/Drivers/USB/USB.h b/tmk_core/protocol/chibios/lufa_utils/LUFA/Drivers/USB/USB.h
new file mode 100644
index 000000000..a5374d820
--- /dev/null
+++ b/tmk_core/protocol/chibios/lufa_utils/LUFA/Drivers/USB/USB.h
@@ -0,0 +1,42 @@
1#include "progmem.h"
2#include "stddef.h"
3#include "inttypes.h"
4
5#define ATTR_PACKED __attribute__ ((packed))
6/** Concatenates the given input into a single token, via the C Preprocessor.
7 *
8 * \param[in] x First item to concatenate.
9 * \param[in] y Second item to concatenate.
10 *
11 * \return Concatenated version of the input.
12 */
13#define CONCAT(x, y) x ## y
14
15/** CConcatenates the given input into a single token after macro expansion, via the C Preprocessor.
16 *
17 * \param[in] x First item to concatenate.
18 * \param[in] y Second item to concatenate.
19 *
20 * \return Concatenated version of the expanded input.
21 */
22#define CONCAT_EXPANDED(x, y) CONCAT(x, y)
23#define CPU_TO_LE16(x) (x)
24
25// We don't need anything from the following files, or we have defined it already
26#define __LUFA_COMMON_H__
27#define __USBMODE_H__
28#define __USBEVENTS_H__
29#define __HIDPARSER_H__
30#define __USBCONTROLLER_AVR8_H__
31
32#define __INCLUDE_FROM_USB_DRIVER
33#define __INCLUDE_FROM_HID_DRIVER
34#define __INCLUDE_FROM_CDC_DRIVER
35#define __INCLUDE_FROM_AUDIO_DRIVER
36#define __INCLUDE_FROM_MIDI_DRIVER
37#include "lib/lufa/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h"
38#include "lib/lufa/LUFA/Drivers/USB/Class/Common/HIDReportData.h"
39#include "lib/lufa/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h"
40#include "lib/lufa/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h"
41#include "lib/lufa/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h"
42#include "lib/lufa/LUFA/Drivers/USB/Core/USBController.h"
diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c
index 47a7eb09a..f2abc438d 100644
--- a/tmk_core/protocol/chibios/main.c
+++ b/tmk_core/protocol/chibios/main.c
@@ -41,6 +41,9 @@
41#ifdef VISUALIZER_ENABLE 41#ifdef VISUALIZER_ENABLE
42#include "visualizer/visualizer.h" 42#include "visualizer/visualizer.h"
43#endif 43#endif
44#ifdef MIDI_ENABLE
45#include "qmk_midi.h"
46#endif
44#include "suspend.h" 47#include "suspend.h"
45#include "wait.h" 48#include "wait.h"
46 49
@@ -65,6 +68,17 @@ host_driver_t chibios_driver = {
65 send_consumer 68 send_consumer
66}; 69};
67 70
71#ifdef VIRTSER_ENABLE
72void virtser_task(void);
73#endif
74
75#ifdef RAW_HID_ENABLE
76void raw_hid_task(void);
77#endif
78
79#ifdef CONSOLE_ENABLE
80void console_task(void);
81#endif
68 82
69/* TESTING 83/* TESTING
70 * Amber LED blinker thread, times are in milliseconds. 84 * Amber LED blinker thread, times are in milliseconds.
@@ -104,6 +118,10 @@ int main(void) {
104 /* init printf */ 118 /* init printf */
105 init_printf(NULL,sendchar_pf); 119 init_printf(NULL,sendchar_pf);
106 120
121#ifdef MIDI_ENABLE
122 setup_midi();
123#endif
124
107#ifdef SERIAL_LINK_ENABLE 125#ifdef SERIAL_LINK_ENABLE
108 init_serial_link(); 126 init_serial_link();
109#endif 127#endif
@@ -182,5 +200,14 @@ int main(void) {
182 } 200 }
183 201
184 keyboard_task(); 202 keyboard_task();
203#ifdef CONSOLE_ENABLE
204 console_task();
205#endif
206#ifdef VIRTSER_ENABLE
207 virtser_task();
208#endif
209#ifdef RAW_HID_ENABLE
210 raw_hid_task();
211#endif
185 } 212 }
186} 213}
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
index caa2770b5..f980024ab 100644
--- a/tmk_core/protocol/chibios/usb_main.c
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -28,6 +28,7 @@
28#include "led.h" 28#include "led.h"
29#endif 29#endif
30#include "wait.h" 30#include "wait.h"
31#include "usb_descriptor.h"
31 32
32#ifdef NKRO_ENABLE 33#ifdef NKRO_ENABLE
33 #include "keycode_config.h" 34 #include "keycode_config.h"
@@ -63,24 +64,12 @@ report_mouse_t mouse_report_blank = {0};
63uint8_t extra_report_blank[3] = {0}; 64uint8_t extra_report_blank[3] = {0};
64#endif /* EXTRAKEY_ENABLE */ 65#endif /* EXTRAKEY_ENABLE */
65 66
66#ifdef CONSOLE_ENABLE
67/* The emission buffers queue */
68output_buffers_queue_t console_buf_queue;
69static uint8_t console_queue_buffer[BQ_BUFFER_SIZE(CONSOLE_QUEUE_CAPACITY, CONSOLE_EPSIZE)];
70
71static virtual_timer_t console_flush_timer;
72void console_queue_onotify(io_buffers_queue_t *bqp);
73static void console_flush_cb(void *arg);
74#endif /* CONSOLE_ENABLE */
75
76/* --------------------------------------------------------- 67/* ---------------------------------------------------------
77 * Descriptors and USB driver objects 68 * Descriptors and USB driver objects
78 * --------------------------------------------------------- 69 * ---------------------------------------------------------
79 */ 70 */
80 71
81/* HID specific constants */ 72/* HID specific constants */
82#define USB_DESCRIPTOR_HID 0x21
83#define USB_DESCRIPTOR_HID_REPORT 0x22
84#define HID_GET_REPORT 0x01 73#define HID_GET_REPORT 0x01
85#define HID_GET_IDLE 0x02 74#define HID_GET_IDLE 0x02
86#define HID_GET_PROTOCOL 0x03 75#define HID_GET_PROTOCOL 0x03
@@ -88,593 +77,21 @@ static void console_flush_cb(void *arg);
88#define HID_SET_IDLE 0x0A 77#define HID_SET_IDLE 0x0A
89#define HID_SET_PROTOCOL 0x0B 78#define HID_SET_PROTOCOL 0x0B
90 79
91/* USB Device Descriptor */
92static const uint8_t usb_device_descriptor_data[] = {
93 USB_DESC_DEVICE(0x0200, // bcdUSB (1.1)
94 0, // bDeviceClass (defined in later in interface)
95 0, // bDeviceSubClass
96 0, // bDeviceProtocol
97 64, // bMaxPacketSize (64 bytes) (the driver didn't work with 32)
98 VENDOR_ID, // idVendor
99 PRODUCT_ID, // idProduct
100 DEVICE_VER, // bcdDevice
101 1, // iManufacturer
102 2, // iProduct
103 3, // iSerialNumber
104 1) // bNumConfigurations
105};
106
107/* Device Descriptor wrapper */
108static const USBDescriptor usb_device_descriptor = {
109 sizeof usb_device_descriptor_data,
110 usb_device_descriptor_data
111};
112
113/*
114 * HID Report Descriptor
115 *
116 * See "Device Class Definition for Human Interface Devices (HID)"
117 * (http://www.usb.org/developers/hidpage/HID1_11.pdf) for the
118 * detailed descrition of all the fields
119 */
120
121/* Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 */
122static const uint8_t keyboard_hid_report_desc_data[] = {
123 0x05, 0x01, // Usage Page (Generic Desktop),
124 0x09, 0x06, // Usage (Keyboard),
125 0xA1, 0x01, // Collection (Application),
126 0x75, 0x01, // Report Size (1),
127 0x95, 0x08, // Report Count (8),
128 0x05, 0x07, // Usage Page (Key Codes),
129 0x19, 0xE0, // Usage Minimum (224),
130 0x29, 0xE7, // Usage Maximum (231),
131 0x15, 0x00, // Logical Minimum (0),
132 0x25, 0x01, // Logical Maximum (1),
133 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
134 0x95, 0x01, // Report Count (1),
135 0x75, 0x08, // Report Size (8),
136 0x81, 0x03, // Input (Constant), ;Reserved byte
137 0x95, 0x05, // Report Count (5),
138 0x75, 0x01, // Report Size (1),
139 0x05, 0x08, // Usage Page (LEDs),
140 0x19, 0x01, // Usage Minimum (1),
141 0x29, 0x05, // Usage Maximum (5),
142 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
143 0x95, 0x01, // Report Count (1),
144 0x75, 0x03, // Report Size (3),
145 0x91, 0x03, // Output (Constant), ;LED report padding
146 0x95, KBD_REPORT_KEYS, // Report Count (),
147 0x75, 0x08, // Report Size (8),
148 0x15, 0x00, // Logical Minimum (0),
149 0x26, 0xFF, 0x00, // Logical Maximum(255),
150 0x05, 0x07, // Usage Page (Key Codes),
151 0x19, 0x00, // Usage Minimum (0),
152 0x29, 0xFF, // Usage Maximum (255),
153 0x81, 0x00, // Input (Data, Array),
154 0xc0 // End Collection
155};
156/* wrapper */
157static const USBDescriptor keyboard_hid_report_descriptor = {
158 sizeof keyboard_hid_report_desc_data,
159 keyboard_hid_report_desc_data
160};
161
162#ifdef NKRO_ENABLE
163static const uint8_t nkro_hid_report_desc_data[] = {
164 0x05, 0x01, // Usage Page (Generic Desktop),
165 0x09, 0x06, // Usage (Keyboard),
166 0xA1, 0x01, // Collection (Application),
167 // bitmap of modifiers
168 0x75, 0x01, // Report Size (1),
169 0x95, 0x08, // Report Count (8),
170 0x05, 0x07, // Usage Page (Key Codes),
171 0x19, 0xE0, // Usage Minimum (224),
172 0x29, 0xE7, // Usage Maximum (231),
173 0x15, 0x00, // Logical Minimum (0),
174 0x25, 0x01, // Logical Maximum (1),
175 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
176 // LED output report
177 0x95, 0x05, // Report Count (5),
178 0x75, 0x01, // Report Size (1),
179 0x05, 0x08, // Usage Page (LEDs),
180 0x19, 0x01, // Usage Minimum (1),
181 0x29, 0x05, // Usage Maximum (5),
182 0x91, 0x02, // Output (Data, Variable, Absolute),
183 0x95, 0x01, // Report Count (1),
184 0x75, 0x03, // Report Size (3),
185 0x91, 0x03, // Output (Constant),
186 // bitmap of keys
187 0x95, NKRO_REPORT_KEYS * 8, // Report Count (),
188 0x75, 0x01, // Report Size (1),
189 0x15, 0x00, // Logical Minimum (0),
190 0x25, 0x01, // Logical Maximum(1),
191 0x05, 0x07, // Usage Page (Key Codes),
192 0x19, 0x00, // Usage Minimum (0),
193 0x29, NKRO_REPORT_KEYS * 8 - 1, // Usage Maximum (),
194 0x81, 0x02, // Input (Data, Variable, Absolute),
195 0xc0 // End Collection
196};
197/* wrapper */
198static const USBDescriptor nkro_hid_report_descriptor = {
199 sizeof nkro_hid_report_desc_data,
200 nkro_hid_report_desc_data
201};
202#endif /* NKRO_ENABLE */
203
204#ifdef MOUSE_ENABLE
205/* Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
206 * http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
207 * http://www.keil.com/forum/15671/
208 * http://www.microsoft.com/whdc/device/input/wheel.mspx */
209static const uint8_t mouse_hid_report_desc_data[] = {
210 /* mouse */
211 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
212 0x09, 0x02, // USAGE (Mouse)
213 0xa1, 0x01, // COLLECTION (Application)
214 //0x85, REPORT_ID_MOUSE, // REPORT_ID (1)
215 0x09, 0x01, // USAGE (Pointer)
216 0xa1, 0x00, // COLLECTION (Physical)
217 // ---------------------------- Buttons
218 0x05, 0x09, // USAGE_PAGE (Button)
219 0x19, 0x01, // USAGE_MINIMUM (Button 1)
220 0x29, 0x05, // USAGE_MAXIMUM (Button 5)
221 0x15, 0x00, // LOGICAL_MINIMUM (0)
222 0x25, 0x01, // LOGICAL_MAXIMUM (1)
223 0x75, 0x01, // REPORT_SIZE (1)
224 0x95, 0x05, // REPORT_COUNT (5)
225 0x81, 0x02, // INPUT (Data,Var,Abs)
226 0x75, 0x03, // REPORT_SIZE (3)
227 0x95, 0x01, // REPORT_COUNT (1)
228 0x81, 0x03, // INPUT (Cnst,Var,Abs)
229 // ---------------------------- X,Y position
230 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
231 0x09, 0x30, // USAGE (X)
232 0x09, 0x31, // USAGE (Y)
233 0x15, 0x81, // LOGICAL_MINIMUM (-127)
234 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
235 0x75, 0x08, // REPORT_SIZE (8)
236 0x95, 0x02, // REPORT_COUNT (2)
237 0x81, 0x06, // INPUT (Data,Var,Rel)
238 // ---------------------------- Vertical wheel
239 0x09, 0x38, // USAGE (Wheel)
240 0x15, 0x81, // LOGICAL_MINIMUM (-127)
241 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
242 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
243 0x45, 0x00, // PHYSICAL_MAXIMUM (0)
244 0x75, 0x08, // REPORT_SIZE (8)
245 0x95, 0x01, // REPORT_COUNT (1)
246 0x81, 0x06, // INPUT (Data,Var,Rel)
247 // ---------------------------- Horizontal wheel
248 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
249 0x0a, 0x38, 0x02, // USAGE (AC Pan)
250 0x15, 0x81, // LOGICAL_MINIMUM (-127)
251 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
252 0x75, 0x08, // REPORT_SIZE (8)
253 0x95, 0x01, // REPORT_COUNT (1)
254 0x81, 0x06, // INPUT (Data,Var,Rel)
255 0xc0, // END_COLLECTION
256 0xc0, // END_COLLECTION
257};
258/* wrapper */
259static const USBDescriptor mouse_hid_report_descriptor = {
260 sizeof mouse_hid_report_desc_data,
261 mouse_hid_report_desc_data
262};
263#endif /* MOUSE_ENABLE */
264
265#ifdef CONSOLE_ENABLE
266static const uint8_t console_hid_report_desc_data[] = {
267 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined)
268 0x09, 0x74, // Usage 0x74
269 0xA1, 0x53, // Collection 0x53
270 0x75, 0x08, // report size = 8 bits
271 0x15, 0x00, // logical minimum = 0
272 0x26, 0xFF, 0x00, // logical maximum = 255
273 0x95, CONSOLE_EPSIZE, // report count
274 0x09, 0x75, // usage
275 0x81, 0x02, // Input (array)
276 0xC0 // end collection
277};
278/* wrapper */
279static const USBDescriptor console_hid_report_descriptor = {
280 sizeof console_hid_report_desc_data,
281 console_hid_report_desc_data
282};
283#endif /* CONSOLE_ENABLE */
284
285#ifdef EXTRAKEY_ENABLE
286/* audio controls & system controls
287 * http://www.microsoft.com/whdc/archive/w2kbd.mspx */
288static const uint8_t extra_hid_report_desc_data[] = {
289 /* system control */
290 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
291 0x09, 0x80, // USAGE (System Control)
292 0xa1, 0x01, // COLLECTION (Application)
293 0x85, REPORT_ID_SYSTEM, // REPORT_ID (2)
294 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
295 0x25, 0xb7, // LOGICAL_MAXIMUM (0xb7)
296 0x19, 0x01, // USAGE_MINIMUM (0x1)
297 0x29, 0xb7, // USAGE_MAXIMUM (0xb7)
298 0x75, 0x10, // REPORT_SIZE (16)
299 0x95, 0x01, // REPORT_COUNT (1)
300 0x81, 0x00, // INPUT (Data,Array,Abs)
301 0xc0, // END_COLLECTION
302 /* consumer */
303 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
304 0x09, 0x01, // USAGE (Consumer Control)
305 0xa1, 0x01, // COLLECTION (Application)
306 0x85, REPORT_ID_CONSUMER, // REPORT_ID (3)
307 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
308 0x26, 0x9c, 0x02, // LOGICAL_MAXIMUM (0x29c)
309 0x19, 0x01, // USAGE_MINIMUM (0x1)
310 0x2a, 0x9c, 0x02, // USAGE_MAXIMUM (0x29c)
311 0x75, 0x10, // REPORT_SIZE (16)
312 0x95, 0x01, // REPORT_COUNT (1)
313 0x81, 0x00, // INPUT (Data,Array,Abs)
314 0xc0, // END_COLLECTION
315};
316/* wrapper */
317static const USBDescriptor extra_hid_report_descriptor = {
318 sizeof extra_hid_report_desc_data,
319 extra_hid_report_desc_data
320};
321#endif /* EXTRAKEY_ENABLE */
322
323
324/*
325 * Configuration Descriptor tree for a HID device
326 *
327 * The HID Specifications version 1.11 require the following order:
328 * - Configuration Descriptor
329 * - Interface Descriptor
330 * - HID Descriptor
331 * - Endpoints Descriptors
332 */
333#define KBD_HID_DESC_NUM 0
334#define KBD_HID_DESC_OFFSET (9 + (9 + 9 + 7) * KBD_HID_DESC_NUM + 9)
335
336#ifdef MOUSE_ENABLE
337# define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 1)
338# define MOUSE_HID_DESC_OFFSET (9 + (9 + 9 + 7) * MOUSE_HID_DESC_NUM + 9)
339#else /* MOUSE_ENABLE */
340# define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 0)
341#endif /* MOUSE_ENABLE */
342
343#ifdef CONSOLE_ENABLE
344#define CONSOLE_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 1)
345#define CONSOLE_HID_DESC_OFFSET (9 + (9 + 9 + 7) * CONSOLE_HID_DESC_NUM + 9)
346#else /* CONSOLE_ENABLE */
347# define CONSOLE_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 0)
348#endif /* CONSOLE_ENABLE */
349
350#ifdef EXTRAKEY_ENABLE
351# define EXTRA_HID_DESC_NUM (CONSOLE_HID_DESC_NUM + 1)
352# define EXTRA_HID_DESC_OFFSET (9 + (9 + 9 + 7) * EXTRA_HID_DESC_NUM + 9)
353#else /* EXTRAKEY_ENABLE */
354# define EXTRA_HID_DESC_NUM (CONSOLE_HID_DESC_NUM + 0)
355#endif /* EXTRAKEY_ENABLE */
356
357#ifdef NKRO_ENABLE
358# define NKRO_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 1)
359# define NKRO_HID_DESC_OFFSET (9 + (9 + 9 + 7) * EXTRA_HID_DESC_NUM + 9)
360#else /* NKRO_ENABLE */
361# define NKRO_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 0)
362#endif /* NKRO_ENABLE */
363
364#define NUM_INTERFACES (NKRO_HID_DESC_NUM + 1)
365#define CONFIG1_DESC_SIZE (9 + (9 + 9 + 7) * NUM_INTERFACES)
366
367static const uint8_t hid_configuration_descriptor_data[] = {
368 /* Configuration Descriptor (9 bytes) USB spec 9.6.3, page 264-266, Table 9-10 */
369 USB_DESC_CONFIGURATION(CONFIG1_DESC_SIZE, // wTotalLength
370 NUM_INTERFACES, // bNumInterfaces
371 1, // bConfigurationValue
372 0, // iConfiguration
373 0xA0, // bmAttributes (RESERVED|REMOTEWAKEUP)
374 50), // bMaxPower (50mA)
375
376 /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
377 USB_DESC_INTERFACE(KBD_INTERFACE, // bInterfaceNumber
378 0, // bAlternateSetting
379 1, // bNumEndpoints
380 0x03, // bInterfaceClass: HID
381 0x01, // bInterfaceSubClass: Boot
382 0x01, // bInterfaceProtocol: Keyboard
383 0), // iInterface
384
385 /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
386 USB_DESC_BYTE(9), // bLength
387 USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
388 USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
389 USB_DESC_BYTE(0), // bCountryCode
390 USB_DESC_BYTE(1), // bNumDescriptors
391 USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
392 USB_DESC_WORD(sizeof(keyboard_hid_report_desc_data)), // wDescriptorLength
393
394 /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
395 USB_DESC_ENDPOINT(KBD_ENDPOINT | 0x80, // bEndpointAddress
396 0x03, // bmAttributes (Interrupt)
397 KBD_EPSIZE,// wMaxPacketSize
398 10), // bInterval
399
400 #ifdef MOUSE_ENABLE
401 /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
402 USB_DESC_INTERFACE(MOUSE_INTERFACE, // bInterfaceNumber
403 0, // bAlternateSetting
404 1, // bNumEndpoints
405 0x03, // bInterfaceClass (0x03 = HID)
406 // ThinkPad T23 BIOS doesn't work with boot mouse.
407 0x00, // bInterfaceSubClass (0x01 = Boot)
408 0x00, // bInterfaceProtocol (0x02 = Mouse)
409 /*
410 0x01, // bInterfaceSubClass (0x01 = Boot)
411 0x02, // bInterfaceProtocol (0x02 = Mouse)
412 */
413 0), // iInterface
414
415 /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
416 USB_DESC_BYTE(9), // bLength
417 USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
418 USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
419 USB_DESC_BYTE(0), // bCountryCode
420 USB_DESC_BYTE(1), // bNumDescriptors
421 USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
422 USB_DESC_WORD(sizeof(mouse_hid_report_desc_data)), // wDescriptorLength
423
424 /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
425 USB_DESC_ENDPOINT(MOUSE_ENDPOINT | 0x80, // bEndpointAddress
426 0x03, // bmAttributes (Interrupt)
427 MOUSE_EPSIZE, // wMaxPacketSize
428 1), // bInterval
429 #endif /* MOUSE_ENABLE */
430
431 #ifdef CONSOLE_ENABLE
432 /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
433 USB_DESC_INTERFACE(CONSOLE_INTERFACE, // bInterfaceNumber
434 0, // bAlternateSetting
435 1, // bNumEndpoints
436 0x03, // bInterfaceClass: HID
437 0x00, // bInterfaceSubClass: None
438 0x00, // bInterfaceProtocol: None
439 0), // iInterface
440
441 /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
442 USB_DESC_BYTE(9), // bLength
443 USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
444 USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
445 USB_DESC_BYTE(0), // bCountryCode
446 USB_DESC_BYTE(1), // bNumDescriptors
447 USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
448 USB_DESC_WORD(sizeof(console_hid_report_desc_data)), // wDescriptorLength
449
450 /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
451 USB_DESC_ENDPOINT(CONSOLE_ENDPOINT | 0x80, // bEndpointAddress
452 0x03, // bmAttributes (Interrupt)
453 CONSOLE_EPSIZE, // wMaxPacketSize
454 1), // bInterval
455 #endif /* CONSOLE_ENABLE */
456
457 #ifdef EXTRAKEY_ENABLE
458 /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
459 USB_DESC_INTERFACE(EXTRA_INTERFACE, // bInterfaceNumber
460 0, // bAlternateSetting
461 1, // bNumEndpoints
462 0x03, // bInterfaceClass: HID
463 0x00, // bInterfaceSubClass: None
464 0x00, // bInterfaceProtocol: None
465 0), // iInterface
466
467 /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
468 USB_DESC_BYTE(9), // bLength
469 USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
470 USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
471 USB_DESC_BYTE(0), // bCountryCode
472 USB_DESC_BYTE(1), // bNumDescriptors
473 USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
474 USB_DESC_WORD(sizeof(extra_hid_report_desc_data)), // wDescriptorLength
475
476 /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
477 USB_DESC_ENDPOINT(EXTRA_ENDPOINT | 0x80, // bEndpointAddress
478 0x03, // bmAttributes (Interrupt)
479 EXTRA_EPSIZE, // wMaxPacketSize
480 10), // bInterval
481 #endif /* EXTRAKEY_ENABLE */
482
483 #ifdef NKRO_ENABLE
484 /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
485 USB_DESC_INTERFACE(NKRO_INTERFACE, // bInterfaceNumber
486 0, // bAlternateSetting
487 1, // bNumEndpoints
488 0x03, // bInterfaceClass: HID
489 0x00, // bInterfaceSubClass: None
490 0x00, // bInterfaceProtocol: None
491 0), // iInterface
492
493 /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
494 USB_DESC_BYTE(9), // bLength
495 USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
496 USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
497 USB_DESC_BYTE(0), // bCountryCode
498 USB_DESC_BYTE(1), // bNumDescriptors
499 USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
500 USB_DESC_WORD(sizeof(nkro_hid_report_desc_data)), // wDescriptorLength
501
502 /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
503 USB_DESC_ENDPOINT(NKRO_ENDPOINT | 0x80, // bEndpointAddress
504 0x03, // bmAttributes (Interrupt)
505 NKRO_EPSIZE, // wMaxPacketSize
506 1), // bInterval
507 #endif /* NKRO_ENABLE */
508};
509
510/* Configuration Descriptor wrapper */
511static const USBDescriptor hid_configuration_descriptor = {
512 sizeof hid_configuration_descriptor_data,
513 hid_configuration_descriptor_data
514};
515
516/* wrappers */
517#define HID_DESCRIPTOR_SIZE 9
518static const USBDescriptor keyboard_hid_descriptor = {
519 HID_DESCRIPTOR_SIZE,
520 &hid_configuration_descriptor_data[KBD_HID_DESC_OFFSET]
521};
522#ifdef MOUSE_ENABLE
523static const USBDescriptor mouse_hid_descriptor = {
524 HID_DESCRIPTOR_SIZE,
525 &hid_configuration_descriptor_data[MOUSE_HID_DESC_OFFSET]
526};
527#endif /* MOUSE_ENABLE */
528#ifdef CONSOLE_ENABLE
529static const USBDescriptor console_hid_descriptor = {
530 HID_DESCRIPTOR_SIZE,
531 &hid_configuration_descriptor_data[CONSOLE_HID_DESC_OFFSET]
532};
533#endif /* CONSOLE_ENABLE */
534#ifdef EXTRAKEY_ENABLE
535static const USBDescriptor extra_hid_descriptor = {
536 HID_DESCRIPTOR_SIZE,
537 &hid_configuration_descriptor_data[EXTRA_HID_DESC_OFFSET]
538};
539#endif /* EXTRAKEY_ENABLE */
540#ifdef NKRO_ENABLE
541static const USBDescriptor nkro_hid_descriptor = {
542 HID_DESCRIPTOR_SIZE,
543 &hid_configuration_descriptor_data[NKRO_HID_DESC_OFFSET]
544};
545#endif /* NKRO_ENABLE */
546
547
548/* U.S. English language identifier */
549static const uint8_t usb_string_langid[] = {
550 USB_DESC_BYTE(4), // bLength
551 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
552 USB_DESC_WORD(0x0409) // wLANGID (U.S. English)
553};
554
555/* ugly ugly hack */
556#define PP_NARG(...) \
557 PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
558#define PP_NARG_(...) \
559 PP_ARG_N(__VA_ARGS__)
560#define PP_ARG_N( \
561 _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
562 _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
563 _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
564 _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
565 _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
566 _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
567 _61,_62,_63,N,...) N
568#define PP_RSEQ_N() \
569 63,62,61,60, \
570 59,58,57,56,55,54,53,52,51,50, \
571 49,48,47,46,45,44,43,42,41,40, \
572 39,38,37,36,35,34,33,32,31,30, \
573 29,28,27,26,25,24,23,22,21,20, \
574 19,18,17,16,15,14,13,12,11,10, \
575 9,8,7,6,5,4,3,2,1,0
576
577/* Vendor string = manufacturer */
578static const uint8_t usb_string_vendor[] = {
579 USB_DESC_BYTE(PP_NARG(USBSTR_MANUFACTURER)+2), // bLength
580 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
581 USBSTR_MANUFACTURER
582};
583
584/* Device Description string = product */
585static const uint8_t usb_string_description[] = {
586 USB_DESC_BYTE(PP_NARG(USBSTR_PRODUCT)+2), // bLength
587 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
588 USBSTR_PRODUCT
589};
590
591/* Serial Number string (will be filled by the function init_usb_serial_string) */
592static uint8_t usb_string_serial[] = {
593 USB_DESC_BYTE(22), // bLength
594 USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
595 '0', 0, 'x', 0, 'D', 0, 'E', 0, 'A', 0, 'D', 0, 'B', 0, 'E', 0, 'E', 0, 'F', 0
596};
597
598/* Strings wrappers array */
599static const USBDescriptor usb_strings[] = {
600 { sizeof usb_string_langid, usb_string_langid }
601 ,
602 { sizeof usb_string_vendor, usb_string_vendor }
603 ,
604 { sizeof usb_string_description, usb_string_description }
605 ,
606 { sizeof usb_string_serial, usb_string_serial }
607};
608
609/* 80/*
610 * Handles the GET_DESCRIPTOR callback 81 * Handles the GET_DESCRIPTOR callback
611 * 82 *
612 * Returns the proper descriptor 83 * Returns the proper descriptor
613 */ 84 */
614static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t lang) { 85static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t wIndex) {
615 (void)usbp; 86 (void)usbp;
616 (void)lang; 87 static USBDescriptor desc;
617 switch(dtype) { 88 uint16_t wValue = ((uint16_t)dtype << 8) | dindex;
618 /* Generic descriptors */ 89 desc.ud_string = NULL;
619 case USB_DESCRIPTOR_DEVICE: /* Device Descriptor */ 90 desc.ud_size = get_usb_descriptor(wValue, wIndex, (const void** const)&desc.ud_string);
620 return &usb_device_descriptor; 91 if (desc.ud_string == NULL)
621 92 return NULL;
622 case USB_DESCRIPTOR_CONFIGURATION: /* Configuration Descriptor */ 93 else
623 return &hid_configuration_descriptor; 94 return &desc;
624
625 case USB_DESCRIPTOR_STRING: /* Strings */
626 if(dindex < 4)
627 return &usb_strings[dindex];
628 break;
629
630 /* HID specific descriptors */
631 case USB_DESCRIPTOR_HID: /* HID Descriptors */
632 switch(lang) { /* yea, poor label, it's actually wIndex from the setup packet */
633 case KBD_INTERFACE:
634 return &keyboard_hid_descriptor;
635
636#ifdef MOUSE_ENABLE
637 case MOUSE_INTERFACE:
638 return &mouse_hid_descriptor;
639#endif /* MOUSE_ENABLE */
640#ifdef CONSOLE_ENABLE
641 case CONSOLE_INTERFACE:
642 return &console_hid_descriptor;
643#endif /* CONSOLE_ENABLE */
644#ifdef EXTRAKEY_ENABLE
645 case EXTRA_INTERFACE:
646 return &extra_hid_descriptor;
647#endif /* EXTRAKEY_ENABLE */
648#ifdef NKRO_ENABLE
649 case NKRO_INTERFACE:
650 return &nkro_hid_descriptor;
651#endif /* NKRO_ENABLE */
652 }
653
654 case USB_DESCRIPTOR_HID_REPORT: /* HID Report Descriptor */
655 switch(lang) {
656 case KBD_INTERFACE:
657 return &keyboard_hid_report_descriptor;
658
659#ifdef MOUSE_ENABLE
660 case MOUSE_INTERFACE:
661 return &mouse_hid_report_descriptor;
662#endif /* MOUSE_ENABLE */
663#ifdef CONSOLE_ENABLE
664 case CONSOLE_INTERFACE:
665 return &console_hid_report_descriptor;
666#endif /* CONSOLE_ENABLE */
667#ifdef EXTRAKEY_ENABLE
668 case EXTRA_INTERFACE:
669 return &extra_hid_report_descriptor;
670#endif /* EXTRAKEY_ENABLE */
671#ifdef NKRO_ENABLE
672 case NKRO_INTERFACE:
673 return &nkro_hid_report_descriptor;
674#endif /* NKRO_ENABLE */
675 }
676 }
677 return NULL;
678} 95}
679 96
680/* keyboard endpoint state structure */ 97/* keyboard endpoint state structure */
@@ -685,7 +102,7 @@ static const USBEndpointConfig kbd_ep_config = {
685 NULL, /* SETUP packet notification callback */ 102 NULL, /* SETUP packet notification callback */
686 kbd_in_cb, /* IN notification callback */ 103 kbd_in_cb, /* IN notification callback */
687 NULL, /* OUT notification callback */ 104 NULL, /* OUT notification callback */
688 KBD_EPSIZE, /* IN maximum packet size */ 105 KEYBOARD_EPSIZE, /* IN maximum packet size */
689 0, /* OUT maximum packet size */ 106 0, /* OUT maximum packet size */
690 &kbd_ep_state, /* IN Endpoint state */ 107 &kbd_ep_state, /* IN Endpoint state */
691 NULL, /* OUT endpoint state */ 108 NULL, /* OUT endpoint state */
@@ -712,25 +129,6 @@ static const USBEndpointConfig mouse_ep_config = {
712}; 129};
713#endif /* MOUSE_ENABLE */ 130#endif /* MOUSE_ENABLE */
714 131
715#ifdef CONSOLE_ENABLE
716/* console endpoint state structure */
717static USBInEndpointState console_ep_state;
718
719/* console endpoint initialization structure (IN) */
720static const USBEndpointConfig console_ep_config = {
721 USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
722 NULL, /* SETUP packet notification callback */
723 console_in_cb, /* IN notification callback */
724 NULL, /* OUT notification callback */
725 CONSOLE_EPSIZE, /* IN maximum packet size */
726 0, /* OUT maximum packet size */
727 &console_ep_state, /* IN Endpoint state */
728 NULL, /* OUT endpoint state */
729 2, /* IN multiplier */
730 NULL /* SETUP buffer (not a SETUP endpoint) */
731};
732#endif /* CONSOLE_ENABLE */
733
734#ifdef EXTRAKEY_ENABLE 132#ifdef EXTRAKEY_ENABLE
735/* extrakey endpoint state structure */ 133/* extrakey endpoint state structure */
736static USBInEndpointState extra_ep_state; 134static USBInEndpointState extra_ep_state;
@@ -741,7 +139,7 @@ static const USBEndpointConfig extra_ep_config = {
741 NULL, /* SETUP packet notification callback */ 139 NULL, /* SETUP packet notification callback */
742 extra_in_cb, /* IN notification callback */ 140 extra_in_cb, /* IN notification callback */
743 NULL, /* OUT notification callback */ 141 NULL, /* OUT notification callback */
744 EXTRA_EPSIZE, /* IN maximum packet size */ 142 EXTRAKEY_EPSIZE, /* IN maximum packet size */
745 0, /* OUT maximum packet size */ 143 0, /* OUT maximum packet size */
746 &extra_ep_state, /* IN Endpoint state */ 144 &extra_ep_state, /* IN Endpoint state */
747 NULL, /* OUT endpoint state */ 145 NULL, /* OUT endpoint state */
@@ -769,6 +167,129 @@ static const USBEndpointConfig nkro_ep_config = {
769}; 167};
770#endif /* NKRO_ENABLE */ 168#endif /* NKRO_ENABLE */
771 169
170typedef struct {
171 size_t queue_capacity_in;
172 size_t queue_capacity_out;
173 uint8_t* queue_buffer_in;
174 uint8_t* queue_buffer_out;
175 USBInEndpointState in_ep_state;
176 USBOutEndpointState out_ep_state;
177 USBInEndpointState int_ep_state;
178 USBEndpointConfig in_ep_config;
179 USBEndpointConfig out_ep_config;
180 USBEndpointConfig int_ep_config;
181 const SerialUSBConfig config;
182 SerialUSBDriver driver;
183} stream_driver_t;
184
185#define STREAM_DRIVER(stream, notification) { \
186 .queue_capacity_in = stream##_IN_CAPACITY, \
187 .queue_capacity_out = stream##_OUT_CAPACITY, \
188 .queue_buffer_in = (uint8_t[BQ_BUFFER_SIZE(stream##_IN_CAPACITY, stream##_EPSIZE)]) {}, \
189 .queue_buffer_out = (uint8_t[BQ_BUFFER_SIZE(stream##_OUT_CAPACITY,stream##_EPSIZE)]) {}, \
190 .in_ep_config = { \
191 .ep_mode = stream##_IN_MODE, \
192 .setup_cb = NULL, \
193 .in_cb = sduDataTransmitted, \
194 .out_cb = NULL, \
195 .in_maxsize = stream##_EPSIZE, \
196 .out_maxsize = 0, \
197 /* The pointer to the states will be filled during initialization */ \
198 .in_state = NULL, \
199 .out_state = NULL, \
200 .ep_buffers = 2, \
201 .setup_buf = NULL \
202 }, \
203 .out_ep_config = { \
204 .ep_mode = stream##_OUT_MODE, \
205 .setup_cb = NULL, \
206 .in_cb = NULL, \
207 .out_cb = sduDataReceived, \
208 .in_maxsize = 0, \
209 .out_maxsize = stream##_EPSIZE, \
210 /* The pointer to the states will be filled during initialization */ \
211 .in_state = NULL, \
212 .out_state = NULL, \
213 .ep_buffers = 2, \
214 .setup_buf = NULL, \
215 }, \
216 .int_ep_config = { \
217 .ep_mode = USB_EP_MODE_TYPE_INTR, \
218 .setup_cb = NULL, \
219 .in_cb = sduInterruptTransmitted, \
220 .out_cb = NULL, \
221 .in_maxsize = CDC_NOTIFICATION_EPSIZE, \
222 .out_maxsize = 0, \
223 /* The pointer to the states will be filled during initialization */ \
224 .in_state = NULL, \
225 .out_state = NULL, \
226 .ep_buffers = 2, \
227 .setup_buf = NULL, \
228 }, \
229 .config = { \
230 .usbp = &USB_DRIVER, \
231 .bulk_in = stream##_IN_EPNUM, \
232 .bulk_out = stream##_OUT_EPNUM, \
233 .int_in = notification \
234 } \
235}
236
237typedef struct {
238 union {
239 struct {
240#ifdef CONSOLE_ENABLE
241 stream_driver_t console_driver;
242#endif
243#ifdef RAW_ENABLE
244 stream_driver_t raw_driver;
245#endif
246#ifdef MIDI_ENABLE
247 stream_driver_t midi_driver;
248#endif
249#ifdef VIRTSER_ENABLE
250 stream_driver_t serial_driver;
251#endif
252 };
253 stream_driver_t array[0];
254 };
255} stream_drivers_t;
256
257static stream_drivers_t drivers = {
258#ifdef CONSOLE_ENABLE
259 #define CONSOLE_IN_CAPACITY 4
260 #define CONSOLE_OUT_CAPACITY 4
261 #define CONSOLE_IN_MODE USB_EP_MODE_TYPE_INTR
262 #define CONSOLE_OUT_MODE USB_EP_MODE_TYPE_INTR
263 .console_driver = STREAM_DRIVER(CONSOLE, 0),
264#endif
265#ifdef RAW_ENABLE
266 #define RAW_IN_CAPACITY 4
267 #define RAW_OUT_CAPACITY 4
268 #define RAW_IN_MODE USB_EP_MODE_TYPE_INTR
269 #define RAW_OUT_MODE USB_EP_MODE_TYPE_INTR
270 .raw_driver = STREAM_DRIVER(RAW, 0),
271#endif
272
273#ifdef MIDI_ENABLE
274 #define MIDI_STREAM_IN_CAPACITY 4
275 #define MIDI_STREAM_OUT_CAPACITY 4
276 #define MIDI_STREAM_IN_MODE USB_EP_MODE_TYPE_BULK
277 #define MIDI_STREAM_OUT_MODE USB_EP_MODE_TYPE_BULK
278 .midi_driver = STREAM_DRIVER(MIDI_STREAM, 0),
279#endif
280
281#ifdef VIRTSER_ENABLE
282 #define CDC_IN_CAPACITY 4
283 #define CDC_OUT_CAPACITY 4
284 #define CDC_IN_MODE USB_EP_MODE_TYPE_BULK
285 #define CDC_OUT_MODE USB_EP_MODE_TYPE_BULK
286 .serial_driver = STREAM_DRIVER(CDC, CDC_NOTIFICATION_EPNUM),
287#endif
288};
289
290#define NUM_STREAM_DRIVERS (sizeof(drivers) / sizeof(stream_driver_t))
291
292
772/* --------------------------------------------------------- 293/* ---------------------------------------------------------
773 * USB driver functions 294 * USB driver functions
774 * --------------------------------------------------------- 295 * ---------------------------------------------------------
@@ -784,24 +305,27 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
784 case USB_EVENT_CONFIGURED: 305 case USB_EVENT_CONFIGURED:
785 osalSysLockFromISR(); 306 osalSysLockFromISR();
786 /* Enable the endpoints specified into the configuration. */ 307 /* Enable the endpoints specified into the configuration. */
787 usbInitEndpointI(usbp, KBD_ENDPOINT, &kbd_ep_config); 308 usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config);
788#ifdef MOUSE_ENABLE 309#ifdef MOUSE_ENABLE
789 usbInitEndpointI(usbp, MOUSE_ENDPOINT, &mouse_ep_config); 310 usbInitEndpointI(usbp, MOUSE_IN_EPNUM, &mouse_ep_config);
790#endif /* MOUSE_ENABLE */ 311#endif /* MOUSE_ENABLE */
791#ifdef CONSOLE_ENABLE
792 usbInitEndpointI(usbp, CONSOLE_ENDPOINT, &console_ep_config);
793 /* don't need to start the flush timer, it starts from console_in_cb automatically */
794#endif /* CONSOLE_ENABLE */
795#ifdef EXTRAKEY_ENABLE 312#ifdef EXTRAKEY_ENABLE
796 usbInitEndpointI(usbp, EXTRA_ENDPOINT, &extra_ep_config); 313 usbInitEndpointI(usbp, EXTRAKEY_IN_EPNUM, &extra_ep_config);
797#endif /* EXTRAKEY_ENABLE */ 314#endif /* EXTRAKEY_ENABLE */
798#ifdef NKRO_ENABLE 315#ifdef NKRO_ENABLE
799 usbInitEndpointI(usbp, NKRO_ENDPOINT, &nkro_ep_config); 316 usbInitEndpointI(usbp, NKRO_IN_EPNUM, &nkro_ep_config);
800#endif /* NKRO_ENABLE */ 317#endif /* NKRO_ENABLE */
318 for (int i=0;i<NUM_STREAM_DRIVERS;i++) {
319 usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].in_ep_config);
320 usbInitEndpointI(usbp, drivers.array[i].config.bulk_out, &drivers.array[i].out_ep_config);
321 if (drivers.array[i].config.int_in) {
322 usbInitEndpointI(usbp, drivers.array[i].config.int_in, &drivers.array[i].int_ep_config);
323 }
324 sduConfigureHookI(&drivers.array[i].driver);
325 }
801 osalSysUnlockFromISR(); 326 osalSysUnlockFromISR();
802 return; 327 return;
803 case USB_EVENT_SUSPEND: 328 case USB_EVENT_SUSPEND:
804 //TODO: from ISR! print("[S]");
805#ifdef SLEEP_LED_ENABLE 329#ifdef SLEEP_LED_ENABLE
806 sleep_led_enable(); 330 sleep_led_enable();
807#endif /* SLEEP_LED_ENABLE */ 331#endif /* SLEEP_LED_ENABLE */
@@ -809,10 +333,22 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
809 case USB_EVENT_UNCONFIGURED: 333 case USB_EVENT_UNCONFIGURED:
810 /* Falls into.*/ 334 /* Falls into.*/
811 case USB_EVENT_RESET: 335 case USB_EVENT_RESET:
336 for (int i=0;i<NUM_STREAM_DRIVERS;i++) {
337 chSysLockFromISR();
338 /* Disconnection event on suspend.*/
339 sduSuspendHookI(&drivers.array[i].driver);
340 chSysUnlockFromISR();
341 }
812 return; 342 return;
813 343
814 case USB_EVENT_WAKEUP: 344 case USB_EVENT_WAKEUP:
815 //TODO: from ISR! print("[W]"); 345 //TODO: from ISR! print("[W]");
346 for (int i=0;i<NUM_STREAM_DRIVERS;i++) {
347 chSysLockFromISR();
348 /* Disconnection event on suspend.*/
349 sduWakeupHookI(&drivers.array[i].driver);
350 chSysUnlockFromISR();
351 }
816 suspend_wakeup_init(); 352 suspend_wakeup_init();
817#ifdef SLEEP_LED_ENABLE 353#ifdef SLEEP_LED_ENABLE
818 sleep_led_disable(); 354 sleep_led_disable();
@@ -868,7 +404,7 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
868 switch(usbp->setup[1]) { /* bRequest */ 404 switch(usbp->setup[1]) { /* bRequest */
869 case HID_GET_REPORT: 405 case HID_GET_REPORT:
870 switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */ 406 switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
871 case KBD_INTERFACE: 407 case KEYBOARD_INTERFACE:
872#ifdef NKRO_ENABLE 408#ifdef NKRO_ENABLE
873 case NKRO_INTERFACE: 409 case NKRO_INTERFACE:
874#endif /* NKRO_ENABLE */ 410#endif /* NKRO_ENABLE */
@@ -883,15 +419,8 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
883 break; 419 break;
884#endif /* MOUSE_ENABLE */ 420#endif /* MOUSE_ENABLE */
885 421
886#ifdef CONSOLE_ENABLE
887 case CONSOLE_INTERFACE:
888 usbSetupTransfer(usbp, console_queue_buffer, CONSOLE_EPSIZE, NULL);
889 return TRUE;
890 break;
891#endif /* CONSOLE_ENABLE */
892
893#ifdef EXTRAKEY_ENABLE 422#ifdef EXTRAKEY_ENABLE
894 case EXTRA_INTERFACE: 423 case EXTRAKEY_INTERFACE:
895 if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */ 424 if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
896 switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */ 425 switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
897 case REPORT_ID_SYSTEM: 426 case REPORT_ID_SYSTEM:
@@ -921,7 +450,7 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
921 break; 450 break;
922 451
923 case HID_GET_PROTOCOL: 452 case HID_GET_PROTOCOL:
924 if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */ 453 if((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
925 usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL); 454 usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
926 return TRUE; 455 return TRUE;
927 } 456 }
@@ -938,7 +467,7 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
938 switch(usbp->setup[1]) { /* bRequest */ 467 switch(usbp->setup[1]) { /* bRequest */
939 case HID_SET_REPORT: 468 case HID_SET_REPORT:
940 switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */ 469 switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */
941 case KBD_INTERFACE: 470 case KEYBOARD_INTERFACE:
942#ifdef NKRO_ENABLE 471#ifdef NKRO_ENABLE
943 case NKRO_INTERFACE: 472 case NKRO_INTERFACE:
944#endif /* NKRO_ENABLE */ 473#endif /* NKRO_ENABLE */
@@ -951,7 +480,7 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
951 break; 480 break;
952 481
953 case HID_SET_PROTOCOL: 482 case HID_SET_PROTOCOL:
954 if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */ 483 if((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
955 keyboard_protocol = ((usbp->setup[2]) != 0x00); /* LSB(wValue) */ 484 keyboard_protocol = ((usbp->setup[2]) != 0x00); /* LSB(wValue) */
956#ifdef NKRO_ENABLE 485#ifdef NKRO_ENABLE
957 keymap_config.nkro = !!keyboard_protocol; 486 keymap_config.nkro = !!keyboard_protocol;
@@ -998,12 +527,24 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
998 return TRUE; 527 return TRUE;
999 } 528 }
1000 529
530 for (int i=0;i<NUM_STREAM_DRIVERS;i++) {
531 if (drivers.array[i].config.int_in) {
532 // NOTE: Assumes that we only have one serial driver
533 return sduRequestsHook(usbp);
534 }
535 }
536
1001 return FALSE; 537 return FALSE;
1002} 538}
1003 539
1004/* Start-of-frame callback */ 540/* Start-of-frame callback */
1005static void usb_sof_cb(USBDriver *usbp) { 541static void usb_sof_cb(USBDriver *usbp) {
1006 kbd_sof_cb(usbp); 542 kbd_sof_cb(usbp);
543 osalSysLockFromISR();
544 for (int i=0; i<NUM_STREAM_DRIVERS;i++) {
545 sduSOFHookI(&drivers.array[i].driver);
546 }
547 osalSysUnlockFromISR();
1007} 548}
1008 549
1009 550
@@ -1019,6 +560,19 @@ static const USBConfig usbcfg = {
1019 * Initialize the USB driver 560 * Initialize the USB driver
1020 */ 561 */
1021void init_usb_driver(USBDriver *usbp) { 562void init_usb_driver(USBDriver *usbp) {
563 for (int i=0; i<NUM_STREAM_DRIVERS;i++) {
564 SerialUSBDriver* driver = &drivers.array[i].driver;
565 drivers.array[i].in_ep_config.in_state = &drivers.array[i].in_ep_state;
566 drivers.array[i].out_ep_config.out_state = &drivers.array[i].out_ep_state;
567 drivers.array[i].int_ep_config.in_state = &drivers.array[i].int_ep_state;
568 sduObjectInit(driver);
569 bqnotify_t notify = driver->ibqueue.notify;
570 ibqObjectInit(&driver->ibqueue, false, drivers.array[i].queue_buffer_in, drivers.array[i].in_ep_config.in_maxsize, drivers.array[i].queue_capacity_in, notify, driver);
571 notify = driver->obqueue.notify;
572 ibqObjectInit(&driver->ibqueue, false, drivers.array[i].queue_buffer_out, drivers.array[i].out_ep_config.out_maxsize, drivers.array[i].queue_capacity_out, notify, driver);
573 sduStart(driver, &drivers.array[i].config);
574 }
575
1022 /* 576 /*
1023 * Activates the USB driver and then the USB bus pull-up on D+. 577 * Activates the USB driver and then the USB bus pull-up on D+.
1024 * Note, a delay is inserted in order to not have to disconnect the cable 578 * Note, a delay is inserted in order to not have to disconnect the cable
@@ -1030,17 +584,12 @@ void init_usb_driver(USBDriver *usbp) {
1030 usbConnectBus(usbp); 584 usbConnectBus(usbp);
1031 585
1032 chVTObjectInit(&keyboard_idle_timer); 586 chVTObjectInit(&keyboard_idle_timer);
1033#ifdef CONSOLE_ENABLE
1034 obqObjectInit(&console_buf_queue, false, console_queue_buffer, CONSOLE_EPSIZE, CONSOLE_QUEUE_CAPACITY, console_queue_onotify, (void*)usbp);
1035 chVTObjectInit(&console_flush_timer);
1036#endif
1037} 587}
1038 588
1039/* --------------------------------------------------------- 589/* ---------------------------------------------------------
1040 * Keyboard functions 590 * Keyboard functions
1041 * --------------------------------------------------------- 591 * ---------------------------------------------------------
1042 */ 592 */
1043
1044/* keyboard IN callback hander (a kbd report has made it IN) */ 593/* keyboard IN callback hander (a kbd report has made it IN) */
1045void kbd_in_cb(USBDriver *usbp, usbep_t ep) { 594void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
1046 /* STUB */ 595 /* STUB */
@@ -1084,8 +633,8 @@ static void keyboard_idle_timer_cb(void *arg) {
1084 if(keyboard_idle) { 633 if(keyboard_idle) {
1085#endif /* NKRO_ENABLE */ 634#endif /* NKRO_ENABLE */
1086 /* TODO: are we sure we want the KBD_ENDPOINT? */ 635 /* TODO: are we sure we want the KBD_ENDPOINT? */
1087 if(!usbGetTransmitStatusI(usbp, KBD_ENDPOINT)) { 636 if(!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) {
1088 usbStartTransmitI(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, KBD_EPSIZE); 637 usbStartTransmitI(usbp, KEYBOARD_IN_EPNUM, (uint8_t *)&keyboard_report_sent, KEYBOARD_EPSIZE);
1089 } 638 }
1090 /* rearm the timer */ 639 /* rearm the timer */
1091 chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp); 640 chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
@@ -1119,14 +668,14 @@ void send_keyboard(report_keyboard_t *report) {
1119 * this is more efficient */ 668 * this is more efficient */
1120 /* busy wait, should be short and not very common */ 669 /* busy wait, should be short and not very common */
1121 osalSysLock(); 670 osalSysLock();
1122 if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_ENDPOINT)) { 671 if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_IN_EPNUM)) {
1123 /* Need to either suspend, or loop and call unlock/lock during 672 /* Need to either suspend, or loop and call unlock/lock during
1124 * every iteration - otherwise the system will remain locked, 673 * every iteration - otherwise the system will remain locked,
1125 * no interrupts served, so USB not going through as well. 674 * no interrupts served, so USB not going through as well.
1126 * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */ 675 * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
1127 osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_ENDPOINT]->in_state->thread); 676 osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_IN_EPNUM]->in_state->thread);
1128 } 677 }
1129 usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t)); 678 usbStartTransmitI(&USB_DRIVER, NKRO_IN_EPNUM, (uint8_t *)report, sizeof(report_keyboard_t));
1130 osalSysUnlock(); 679 osalSysUnlock();
1131 } else 680 } else
1132#endif /* NKRO_ENABLE */ 681#endif /* NKRO_ENABLE */
@@ -1134,14 +683,14 @@ void send_keyboard(report_keyboard_t *report) {
1134 /* need to wait until the previous packet has made it through */ 683 /* need to wait until the previous packet has made it through */
1135 /* busy wait, should be short and not very common */ 684 /* busy wait, should be short and not very common */
1136 osalSysLock(); 685 osalSysLock();
1137 if(usbGetTransmitStatusI(&USB_DRIVER, KBD_ENDPOINT)) { 686 if(usbGetTransmitStatusI(&USB_DRIVER, KEYBOARD_IN_EPNUM)) {
1138 /* Need to either suspend, or loop and call unlock/lock during 687 /* Need to either suspend, or loop and call unlock/lock during
1139 * every iteration - otherwise the system will remain locked, 688 * every iteration - otherwise the system will remain locked,
1140 * no interrupts served, so USB not going through as well. 689 * no interrupts served, so USB not going through as well.
1141 * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */ 690 * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
1142 osalThreadSuspendS(&(&USB_DRIVER)->epc[KBD_ENDPOINT]->in_state->thread); 691 osalThreadSuspendS(&(&USB_DRIVER)->epc[KEYBOARD_IN_EPNUM]->in_state->thread);
1143 } 692 }
1144 usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE); 693 usbStartTransmitI(&USB_DRIVER, KEYBOARD_IN_EPNUM, (uint8_t *)report, KEYBOARD_EPSIZE);
1145 osalSysUnlock(); 694 osalSysUnlock();
1146 } 695 }
1147 keyboard_report_sent = *report; 696 keyboard_report_sent = *report;
@@ -1174,7 +723,7 @@ void send_mouse(report_mouse_t *report) {
1174 */ 723 */
1175 724
1176 osalSysLock(); 725 osalSysLock();
1177 usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t)); 726 usbStartTransmitI(&USB_DRIVER, MOUSE_IN_EPNUM, (uint8_t *)report, sizeof(report_mouse_t));
1178 osalSysUnlock(); 727 osalSysUnlock();
1179} 728}
1180 729
@@ -1210,7 +759,7 @@ static void send_extra_report(uint8_t report_id, uint16_t data) {
1210 .usage = data 759 .usage = data
1211 }; 760 };
1212 761
1213 usbStartTransmitI(&USB_DRIVER, EXTRA_ENDPOINT, (uint8_t *)&report, sizeof(report_extra_t)); 762 usbStartTransmitI(&USB_DRIVER, EXTRAKEY_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t));
1214 osalSysUnlock(); 763 osalSysUnlock();
1215} 764}
1216 765
@@ -1238,125 +787,107 @@ void send_consumer(uint16_t data) {
1238 787
1239#ifdef CONSOLE_ENABLE 788#ifdef CONSOLE_ENABLE
1240 789
1241/* console IN callback hander */ 790int8_t sendchar(uint8_t c) {
1242void console_in_cb(USBDriver *usbp, usbep_t ep) { 791 // The previous implmentation had timeouts, but I think it's better to just slow down
1243 (void)ep; /* should have ep == CONSOLE_ENDPOINT, so use that to save time/space */ 792 // and make sure that everything is transferred, rather than dropping stuff
1244 uint8_t *buf; 793 return chnWrite(&drivers.console_driver.driver, &c, 1);
1245 size_t n; 794}
1246 795
1247 osalSysLockFromISR(); 796// Just a dummy function for now, this could be exposed as a weak function
797// Or connected to the actual QMK console
798static void console_receive( uint8_t *data, uint8_t length ) {
799 (void)data;
800 (void)length;
801}
1248 802
1249 /* rearm the timer */ 803void console_task(void) {
1250 chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp); 804 uint8_t buffer[CONSOLE_EPSIZE];
805 size_t size = 0;
806 do {
807 size_t size = chnReadTimeout(&drivers.console_driver.driver, buffer, sizeof(buffer), TIME_IMMEDIATE);
808 if (size > 0) {
809 console_receive(buffer, size);
810 }
811 } while(size > 0);
812}
1251 813
1252 /* Freeing the buffer just transmitted, if it was not a zero size packet.*/ 814#else /* CONSOLE_ENABLE */
1253 if (usbp->epc[CONSOLE_ENDPOINT]->in_state->txsize > 0U) { 815int8_t sendchar(uint8_t c) {
1254 obqReleaseEmptyBufferI(&console_buf_queue); 816 (void)c;
1255 } 817 return 0;
818}
819#endif /* CONSOLE_ENABLE */
1256 820
1257 /* Checking if there is a buffer ready for transmission.*/ 821void sendchar_pf(void *p, char c) {
1258 buf = obqGetFullBufferI(&console_buf_queue, &n); 822 (void)p;
823 sendchar((uint8_t)c);
824}
1259 825
1260 if (buf != NULL) { 826#ifdef RAW_ENABLE
1261 /* The endpoint cannot be busy, we are in the context of the callback, 827void raw_hid_send( uint8_t *data, uint8_t length ) {
1262 so it is safe to transmit without a check.*/ 828 // TODO: implement variable size packet
1263 /* Should have n == CONSOLE_EPSIZE; check it? */ 829 if ( length != RAW_EPSIZE )
1264 usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE); 830 {
1265 } else { 831 return;
1266 /* Nothing to transmit.*/
1267 }
1268 832
1269 osalSysUnlockFromISR(); 833 }
834 chnWrite(&drivers.raw_driver.driver, data, length);
1270} 835}
1271 836
1272/* Callback when data is inserted into the output queue 837__attribute__ ((weak))
1273 * Called from a locked state */ 838void raw_hid_receive( uint8_t *data, uint8_t length ) {
1274void console_queue_onotify(io_buffers_queue_t *bqp) { 839 // Users should #include "raw_hid.h" in their own code
1275 size_t n; 840 // and implement this function there. Leave this as weak linkage
1276 USBDriver *usbp = bqGetLinkX(bqp); 841 // so users can opt to not handle data coming in.
1277 842}
1278 if(usbGetDriverStateI(usbp) != USB_ACTIVE)
1279 return;
1280 843
1281 /* Checking if there is already a transaction ongoing on the endpoint.*/ 844void raw_hid_task(void) {
1282 if (!usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) { 845 uint8_t buffer[RAW_EPSIZE];
1283 /* Trying to get a full buffer.*/ 846 size_t size = 0;
1284 uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n); 847 do {
1285 if (buf != NULL) { 848 size_t size = chnReadTimeout(&drivers.raw_driver.driver, buffer, sizeof(buffer), TIME_IMMEDIATE);
1286 /* Buffer found, starting a new transaction.*/ 849 if (size > 0) {
1287 /* Should have n == CONSOLE_EPSIZE; check this? */ 850 raw_hid_receive(buffer, size);
1288 usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
1289 } 851 }
1290 } 852 } while(size > 0);
1291} 853}
1292 854
1293/* Flush timer code 855#endif
1294 * callback (called from ISR, unlocked state) */
1295static void console_flush_cb(void *arg) {
1296 USBDriver *usbp = (USBDriver *)arg;
1297 osalSysLockFromISR();
1298 856
1299 /* check that the states of things are as they're supposed to */ 857#ifdef MIDI_ENABLE
1300 if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
1301 /* rearm the timer */
1302 chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
1303 osalSysUnlockFromISR();
1304 return;
1305 }
1306 858
1307 /* If there is already a transaction ongoing then another one cannot be 859void send_midi_packet(MIDI_EventPacket_t* event) {
1308 started.*/ 860 chnWrite(&drivers.midi_driver.driver, (uint8_t*)event, sizeof(MIDI_EventPacket_t));
1309 if (usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) { 861}
1310 /* rearm the timer */
1311 chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
1312 osalSysUnlockFromISR();
1313 return;
1314 }
1315 862
1316 /* Checking if there only a buffer partially filled, if so then it is 863bool recv_midi_packet(MIDI_EventPacket_t* const event) {
1317 enforced in the queue and transmitted.*/ 864 size_t size = chnReadTimeout(&drivers.midi_driver.driver, (uint8_t*)event, sizeof(MIDI_EventPacket_t), TIME_IMMEDIATE);
1318 if(obqTryFlushI(&console_buf_queue)) { 865 return size == sizeof(MIDI_EventPacket_t);
1319 size_t n,i; 866}
1320 uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n);
1321 867
1322 osalDbgAssert(buf != NULL, "queue is empty"); 868#endif
1323 869
1324 /* zero the rest of the buffer (buf should point to allocated space) */ 870#ifdef VIRTSER_ENABLE
1325 for(i=n; i<CONSOLE_EPSIZE; i++)
1326 buf[i]=0;
1327 usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
1328 }
1329 871
1330 /* rearm the timer */ 872void virtser_send(const uint8_t byte) {
1331 chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp); 873 chnWrite(&drivers.serial_driver.driver, &byte, 1);
1332 osalSysUnlockFromISR();
1333} 874}
1334 875
1335 876__attribute__ ((weak))
1336int8_t sendchar(uint8_t c) { 877void virtser_recv(uint8_t c)
1337 osalSysLock(); 878{
1338 if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) { 879 // Ignore by default
1339 osalSysUnlock();
1340 return 0;
1341 }
1342 osalSysUnlock();
1343 /* Timeout after 100us if the queue is full.
1344 * Increase this timeout if too much stuff is getting
1345 * dropped (i.e. the buffer is getting full too fast
1346 * for USB/HIDRAW to dequeue). Another possibility
1347 * for fixing this kind of thing is to increase
1348 * CONSOLE_QUEUE_CAPACITY. */
1349 return(obqPutTimeout(&console_buf_queue, c, US2ST(100)));
1350} 880}
1351 881
1352#else /* CONSOLE_ENABLE */ 882void virtser_task(void) {
1353int8_t sendchar(uint8_t c) { 883 uint8_t numBytesReceived = 0;
1354 (void)c; 884 uint8_t buffer[16];
1355 return 0; 885 do {
886 numBytesReceived = chnReadTimeout(&drivers.serial_driver.driver, buffer, sizeof(buffer), TIME_IMMEDIATE);
887 for (int i=0;i<numBytesReceived;i++) {
888 virtser_recv(buffer[i]);
889 }
890 } while (numBytesReceived > 0);
1356} 891}
1357#endif /* CONSOLE_ENABLE */
1358 892
1359void sendchar_pf(void *p, char c) { 893#endif
1360 (void)p;
1361 sendchar((uint8_t)c);
1362}
diff --git a/tmk_core/protocol/chibios/usb_main.h b/tmk_core/protocol/chibios/usb_main.h
index b4f894f2f..1f7eb12f8 100644
--- a/tmk_core/protocol/chibios/usb_main.h
+++ b/tmk_core/protocol/chibios/usb_main.h
@@ -41,20 +41,6 @@ void init_usb_driver(USBDriver *usbp);
41 * --------------- 41 * ---------------
42 */ 42 */
43 43
44/* main keyboard (6kro) */
45#define KBD_INTERFACE 0
46#define KBD_ENDPOINT 1
47#define KBD_EPSIZE 8
48#define KBD_REPORT_KEYS (KBD_EPSIZE - 2)
49
50/* secondary keyboard */
51#ifdef NKRO_ENABLE
52#define NKRO_INTERFACE 4
53#define NKRO_ENDPOINT 5
54#define NKRO_EPSIZE 16
55#define NKRO_REPORT_KEYS (NKRO_EPSIZE - 1)
56#endif
57
58/* extern report_keyboard_t keyboard_report_sent; */ 44/* extern report_keyboard_t keyboard_report_sent; */
59 45
60/* keyboard IN request callback handler */ 46/* keyboard IN request callback handler */
@@ -75,10 +61,6 @@ void nkro_in_cb(USBDriver *usbp, usbep_t ep);
75 61
76#ifdef MOUSE_ENABLE 62#ifdef MOUSE_ENABLE
77 63
78#define MOUSE_INTERFACE 1
79#define MOUSE_ENDPOINT 2
80#define MOUSE_EPSIZE 8
81
82/* mouse IN request callback handler */ 64/* mouse IN request callback handler */
83void mouse_in_cb(USBDriver *usbp, usbep_t ep); 65void mouse_in_cb(USBDriver *usbp, usbep_t ep);
84#endif /* MOUSE_ENABLE */ 66#endif /* MOUSE_ENABLE */
@@ -90,10 +72,6 @@ void mouse_in_cb(USBDriver *usbp, usbep_t ep);
90 72
91#ifdef EXTRAKEY_ENABLE 73#ifdef EXTRAKEY_ENABLE
92 74
93#define EXTRA_INTERFACE 3
94#define EXTRA_ENDPOINT 4
95#define EXTRA_EPSIZE 8
96
97/* extrakey IN request callback handler */ 75/* extrakey IN request callback handler */
98void extra_in_cb(USBDriver *usbp, usbep_t ep); 76void extra_in_cb(USBDriver *usbp, usbep_t ep);
99 77
@@ -111,24 +89,12 @@ typedef struct {
111 89
112#ifdef CONSOLE_ENABLE 90#ifdef CONSOLE_ENABLE
113 91
114#define CONSOLE_INTERFACE 2
115#define CONSOLE_ENDPOINT 3
116#define CONSOLE_EPSIZE 16
117
118/* Number of IN reports that can be stored inside the output queue */
119#define CONSOLE_QUEUE_CAPACITY 4
120
121/* Console flush time */
122#define CONSOLE_FLUSH_MS 50
123
124/* Putchar over the USB console */ 92/* Putchar over the USB console */
125int8_t sendchar(uint8_t c); 93int8_t sendchar(uint8_t c);
126 94
127/* Flush output (send everything immediately) */ 95/* Flush output (send everything immediately) */
128void console_flush_output(void); 96void console_flush_output(void);
129 97
130/* console IN request callback handler */
131void console_in_cb(USBDriver *usbp, usbep_t ep);
132#endif /* CONSOLE_ENABLE */ 98#endif /* CONSOLE_ENABLE */
133 99
134void sendchar_pf(void *p, char c); 100void sendchar_pf(void *p, char c);