]> git.gir.st - tmk_keyboard.git/blame - tmk_core/protocol/lufa/lufa.c
remove experimental return, cleanup slash_question key
[tmk_keyboard.git] / tmk_core / protocol / lufa / lufa.c
CommitLineData
9818d54d 1/*
a074364c 2 * Copyright 2012 Jun Wako <wakojun@gmail.com>
3 * This file is based on:
4 * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
5 * LUFA-120219/Demos/Device/Lowlevel/GenericHID
6 */
7
8/*
9 LUFA Library
10 Copyright (C) Dean Camera, 2012.
11
12 dean [at] fourwalledcubicle [dot] com
13 www.lufa-lib.org
14*/
15
16/*
17 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
18 Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
19
20 Permission to use, copy, modify, distribute, and sell this
21 software and its documentation for any purpose is hereby granted
22 without fee, provided that the above copyright notice appear in
23 all copies and that both that the copyright notice and this
24 permission notice and warranty disclaimer appear in supporting
25 documentation, and that the name of the author not be used in
26 advertising or publicity pertaining to distribution of the
27 software without specific, written prior permission.
28
29 The author disclaim all warranties with regard to this
30 software, including all implied warranties of merchantability
31 and fitness. In no event shall the author be liable for any
32 special, indirect or consequential damages or any damages
33 whatsoever resulting from loss of use, data or profits, whether
34 in an action of contract, negligence or other tortious action,
35 arising out of or in connection with the use or performance of
36 this software.
37*/
38
39#include "report.h"
40#include "host.h"
41#include "host_driver.h"
42#include "keyboard.h"
43#include "action.h"
44#include "led.h"
45#include "sendchar.h"
46#include "debug.h"
47#ifdef SLEEP_LED_ENABLE
48#include "sleep_led.h"
49#endif
50#include "suspend.h"
71381457 51#include "hook.h"
a074364c 52
87580356 53#ifdef LUFA_DEBUG_SUART
54#include "avr/suart.h"
55#endif
56
9818d54d 57#include "matrix.h"
a074364c 58#include "descriptor.h"
59#include "lufa.h"
60
9818d54d 61
62//#define LUFA_DEBUG
63
64
a074364c 65uint8_t keyboard_idle = 0;
fdc38ef3 66/* 0: Boot Protocol, 1: Report Protocol(default) */
a074364c 67uint8_t keyboard_protocol = 1;
68static uint8_t keyboard_led_stats = 0;
69
70static report_keyboard_t keyboard_report_sent;
71
72
73/* Host driver */
74static uint8_t keyboard_leds(void);
75static void send_keyboard(report_keyboard_t *report);
76static void send_mouse(report_mouse_t *report);
77static void send_system(uint16_t data);
78static void send_consumer(uint16_t data);
79host_driver_t lufa_driver = {
80 keyboard_leds,
81 send_keyboard,
82 send_mouse,
83 send_system,
84 send_consumer
85};
86
87
88/*******************************************************************************
89 * Console
90 ******************************************************************************/
91#ifdef CONSOLE_ENABLE
92static void Console_Task(void)
93{
94 /* Device must be connected and configured for the task to run */
95 if (USB_DeviceState != DEVICE_STATE_Configured)
96 return;
97
98 uint8_t ep = Endpoint_GetCurrentEndpoint();
99
100#if 0
101 // TODO: impl receivechar()/recvchar()
102 Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
103
104 /* Check to see if a packet has been sent from the host */
105 if (Endpoint_IsOUTReceived())
106 {
107 /* Check to see if the packet contains data */
108 if (Endpoint_IsReadWriteAllowed())
109 {
110 /* Create a temporary buffer to hold the read in report from the host */
111 uint8_t ConsoleData[CONSOLE_EPSIZE];
9818d54d 112
a074364c 113 /* Read Console Report Data */
114 Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
9818d54d 115
a074364c 116 /* Process Console Report Data */
117 //ProcessConsoleHIDReport(ConsoleData);
118 }
119
120 /* Finalize the stream transfer to send the last packet */
121 Endpoint_ClearOUT();
122 }
123#endif
124
125 /* IN packet */
126 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
127 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
128 Endpoint_SelectEndpoint(ep);
129 return;
130 }
131
132 // fill empty bank
133 while (Endpoint_IsReadWriteAllowed())
134 Endpoint_Write_8(0);
135
136 // flash senchar packet
137 if (Endpoint_IsINReady()) {
138 Endpoint_ClearIN();
139 }
140
141 Endpoint_SelectEndpoint(ep);
142}
143#else
144static void Console_Task(void)
145{
146}
147#endif
148
149
150/*******************************************************************************
151 * USB Events
152 ******************************************************************************/
153/*
154 * Event Order of Plug in:
155 * 0) EVENT_USB_Device_Connect
156 * 1) EVENT_USB_Device_Suspend
157 * 2) EVENT_USB_Device_Reset
158 * 3) EVENT_USB_Device_Wake
159*/
160void EVENT_USB_Device_Connect(void)
161{
162 print("[C]");
163 /* For battery powered device */
164 if (!USB_IsInitialized) {
165 USB_Disable();
166 USB_Init();
167 USB_Device_EnableSOFEvents();
168 }
169}
170
171void EVENT_USB_Device_Disconnect(void)
172{
173 print("[D]");
174 /* For battery powered device */
175 USB_IsInitialized = false;
9818d54d 176/* TODO: This doesn't work. After several plug in/outs can not be enumerated.
a074364c 177 if (USB_IsInitialized) {
178 USB_Disable(); // Disable all interrupts
179 USB_Controller_Enable();
180 USB_INT_Enable(USB_INT_VBUSTI);
181 }
182*/
183}
184
185void EVENT_USB_Device_Reset(void)
186{
9818d54d 187#ifdef LUFA_DEBUG
a074364c 188 print("[R]");
9818d54d 189#endif
a074364c 190}
191
192void EVENT_USB_Device_Suspend()
193{
9818d54d 194#ifdef LUFA_DEBUG
a074364c 195 print("[S]");
9818d54d 196#endif
71381457 197 hook_usb_suspend_entry();
a074364c 198}
199
200void EVENT_USB_Device_WakeUp()
201{
9818d54d 202#ifdef LUFA_DEBUG
a074364c 203 print("[W]");
9818d54d 204#endif
71381457 205 hook_usb_wakeup();
a074364c 206}
207
fdc38ef3
JW
208#ifdef CONSOLE_ENABLE
209static bool console_flush = false;
210#define CONSOLE_FLUSH_SET(b) do { \
211 uint8_t sreg = SREG; cli(); console_flush = b; SREG = sreg; \
212} while (0)
213
214// called every 1ms
a074364c 215void EVENT_USB_Device_StartOfFrame(void)
216{
fdc38ef3
JW
217 static uint8_t count;
218 if (++count % 50) return;
219 count = 0;
220
221 if (!console_flush) return;
a074364c 222 Console_Task();
fdc38ef3 223 console_flush = false;
a074364c 224}
fdc38ef3 225#endif
a074364c 226
227/** Event handler for the USB_ConfigurationChanged event.
228 * This is fired when the host sets the current configuration of the USB device after enumeration.
fdc38ef3
JW
229 *
230 * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
231 * it is safe to use singl bank for all endpoints.
a074364c 232 */
233void EVENT_USB_Device_ConfigurationChanged(void)
234{
9818d54d 235#ifdef LUFA_DEBUG
87580356 236 print("[c]");
9818d54d 237#endif
a074364c 238 bool ConfigSuccess = true;
239
240 /* Setup Keyboard HID Report Endpoints */
241 ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
242 KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
243
244#ifdef MOUSE_ENABLE
245 /* Setup Mouse HID Report Endpoint */
246 ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
247 MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
248#endif
249
250#ifdef EXTRAKEY_ENABLE
251 /* Setup Extra HID Report Endpoint */
252 ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
253 EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
254#endif
255
256#ifdef CONSOLE_ENABLE
257 /* Setup Console HID Report Endpoints */
258 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
fdc38ef3 259 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
a074364c 260#if 0
261 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
262 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
263#endif
264#endif
265
266#ifdef NKRO_ENABLE
267 /* Setup NKRO HID Report Endpoints */
268 ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
269 NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
270#endif
271}
272
273/*
274Appendix G: HID Request Support Requirements
275
276The following table enumerates the requests that need to be supported by various types of HID class devices.
277
278Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
279------------------------------------------------------------------------------------------
280Boot Mouse Required Optional Optional Optional Required Required
281Non-Boot Mouse Required Optional Optional Optional Optional Optional
282Boot Keyboard Required Optional Required Required Required Required
283Non-Boot Keybrd Required Optional Required Required Optional Optional
284Other Device Required Optional Optional Optional Optional Optional
285*/
286/** Event handler for the USB_ControlRequest event.
287 * This is fired before passing along unhandled control requests to the library for processing internally.
288 */
289void EVENT_USB_Device_ControlRequest(void)
290{
291 uint8_t* ReportData = NULL;
292 uint8_t ReportSize = 0;
293
294 /* Handle HID Class specific requests */
295 switch (USB_ControlRequest.bRequest)
296 {
297 case HID_REQ_GetReport:
298 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
299 {
300 Endpoint_ClearSETUP();
301
302 // Interface
303 switch (USB_ControlRequest.wIndex) {
304 case KEYBOARD_INTERFACE:
305 // TODO: test/check
306 ReportData = (uint8_t*)&keyboard_report_sent;
307 ReportSize = sizeof(keyboard_report_sent);
308 break;
309 }
310
311 /* Write the report data to the control endpoint */
312 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
313 Endpoint_ClearOUT();
9818d54d 314#ifdef LUFA_DEBUG
315 xprintf("[r%d]", USB_ControlRequest.wIndex);
316#endif
a074364c 317 }
318
319 break;
320 case HID_REQ_SetReport:
321 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
322 {
323
324 // Interface
325 switch (USB_ControlRequest.wIndex) {
326 case KEYBOARD_INTERFACE:
327#ifdef NKRO_ENABLE
328 case NKRO_INTERFACE:
329#endif
330 Endpoint_ClearSETUP();
331
332 while (!(Endpoint_IsOUTReceived())) {
333 if (USB_DeviceState == DEVICE_STATE_Unattached)
334 return;
335 }
336 keyboard_led_stats = Endpoint_Read_8();
337
338 Endpoint_ClearOUT();
339 Endpoint_ClearStatusStage();
9818d54d 340#ifdef LUFA_DEBUG
341 xprintf("[L%d]", USB_ControlRequest.wIndex);
342#endif
a074364c 343 break;
344 }
345
346 }
347
348 break;
349
350 case HID_REQ_GetProtocol:
351 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
352 {
353 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
354 Endpoint_ClearSETUP();
355 while (!(Endpoint_IsINReady()));
356 Endpoint_Write_8(keyboard_protocol);
357 Endpoint_ClearIN();
358 Endpoint_ClearStatusStage();
9818d54d 359#ifdef LUFA_DEBUG
360 print("[p]");
361#endif
a074364c 362 }
363 }
364
365 break;
366 case HID_REQ_SetProtocol:
367 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
368 {
369 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
370 Endpoint_ClearSETUP();
371 Endpoint_ClearStatusStage();
372
fdc38ef3 373 keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
a074364c 374 clear_keyboard();
9818d54d 375#ifdef LUFA_DEBUG
376 print("[P]");
377#endif
a074364c 378 }
379 }
380
381 break;
382 case HID_REQ_SetIdle:
383 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
384 {
385 Endpoint_ClearSETUP();
386 Endpoint_ClearStatusStage();
387
388 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
9818d54d 389#ifdef LUFA_DEBUG
390 xprintf("[I%d]%d", USB_ControlRequest.wIndex, (USB_ControlRequest.wValue & 0xFF00) >> 8);
391#endif
a074364c 392 }
393
394 break;
395 case HID_REQ_GetIdle:
396 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
397 {
398 Endpoint_ClearSETUP();
399 while (!(Endpoint_IsINReady()));
400 Endpoint_Write_8(keyboard_idle);
401 Endpoint_ClearIN();
402 Endpoint_ClearStatusStage();
9818d54d 403#ifdef LUFA_DEBUG
404 print("[i]");
405#endif
a074364c 406 }
407
408 break;
409 }
410}
411
412/*******************************************************************************
9818d54d 413 * Host driver
a074364c 414 ******************************************************************************/
415static uint8_t keyboard_leds(void)
416{
417 return keyboard_led_stats;
418}
419
420static void send_keyboard(report_keyboard_t *report)
421{
422 uint8_t timeout = 255;
423
424 if (USB_DeviceState != DEVICE_STATE_Configured)
425 return;
426
427 /* Select the Keyboard Report Endpoint */
428#ifdef NKRO_ENABLE
fdc38ef3 429 if (keyboard_protocol && keyboard_nkro) {
a074364c 430 /* Report protocol - NKRO */
431 Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
432
433 /* Check if write ready for a polling interval around 1ms */
8cab7e60 434 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(8);
a074364c 435 if (!Endpoint_IsReadWriteAllowed()) return;
436
437 /* Write Keyboard Report Data */
438 Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
439 }
440 else
441#endif
442 {
443 /* Boot protocol */
444 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
445
446 /* Check if write ready for a polling interval around 10ms */
447 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
448 if (!Endpoint_IsReadWriteAllowed()) return;
449
450 /* Write Keyboard Report Data */
451 Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
452 }
453
454 /* Finalize the stream transfer to send the last packet */
455 Endpoint_ClearIN();
456
457 keyboard_report_sent = *report;
458}
459
460static void send_mouse(report_mouse_t *report)
461{
462#ifdef MOUSE_ENABLE
463 uint8_t timeout = 255;
464
465 if (USB_DeviceState != DEVICE_STATE_Configured)
466 return;
467
468 /* Select the Mouse Report Endpoint */
469 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
470
471 /* Check if write ready for a polling interval around 10ms */
472 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
473 if (!Endpoint_IsReadWriteAllowed()) return;
474
475 /* Write Mouse Report Data */
476 Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
477
478 /* Finalize the stream transfer to send the last packet */
479 Endpoint_ClearIN();
480#endif
481}
482
483static void send_system(uint16_t data)
484{
485 uint8_t timeout = 255;
486
487 if (USB_DeviceState != DEVICE_STATE_Configured)
488 return;
489
490 report_extra_t r = {
491 .report_id = REPORT_ID_SYSTEM,
492 .usage = data
493 };
494 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
495
496 /* Check if write ready for a polling interval around 10ms */
497 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
498 if (!Endpoint_IsReadWriteAllowed()) return;
499
500 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
501 Endpoint_ClearIN();
502}
503
504static void send_consumer(uint16_t data)
505{
506 uint8_t timeout = 255;
507
508 if (USB_DeviceState != DEVICE_STATE_Configured)
509 return;
510
511 report_extra_t r = {
512 .report_id = REPORT_ID_CONSUMER,
513 .usage = data
514 };
515 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
516
517 /* Check if write ready for a polling interval around 10ms */
518 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
519 if (!Endpoint_IsReadWriteAllowed()) return;
520
521 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
522 Endpoint_ClearIN();
523}
524
525
526/*******************************************************************************
527 * sendchar
528 ******************************************************************************/
529#ifdef CONSOLE_ENABLE
530#define SEND_TIMEOUT 5
531int8_t sendchar(uint8_t c)
532{
87580356 533#ifdef LUFA_DEBUG_SUART
534 xmit(c);
535#endif
a074364c 536 // Not wait once timeouted.
537 // Because sendchar() is called so many times, waiting each call causes big lag.
538 static bool timeouted = false;
539
fdc38ef3
JW
540 // prevents Console_Task() from running during sendchar() runs.
541 // or char will be lost. These two function is mutually exclusive.
542 CONSOLE_FLUSH_SET(false);
543
a074364c 544 if (USB_DeviceState != DEVICE_STATE_Configured)
545 return -1;
546
547 uint8_t ep = Endpoint_GetCurrentEndpoint();
548 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
549 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
550 goto ERROR_EXIT;
551 }
552
553 if (timeouted && !Endpoint_IsReadWriteAllowed()) {
554 goto ERROR_EXIT;
555 }
556
557 timeouted = false;
558
559 uint8_t timeout = SEND_TIMEOUT;
560 while (!Endpoint_IsReadWriteAllowed()) {
561 if (USB_DeviceState != DEVICE_STATE_Configured) {
562 goto ERROR_EXIT;
563 }
564 if (Endpoint_IsStalled()) {
565 goto ERROR_EXIT;
566 }
567 if (!(timeout--)) {
568 timeouted = true;
569 goto ERROR_EXIT;
570 }
571 _delay_ms(1);
572 }
573
574 Endpoint_Write_8(c);
575
576 // send when bank is full
fdc38ef3
JW
577 if (!Endpoint_IsReadWriteAllowed()) {
578 while (!(Endpoint_IsINReady()));
a074364c 579 Endpoint_ClearIN();
fdc38ef3
JW
580 } else {
581 CONSOLE_FLUSH_SET(true);
582 }
a074364c 583
584 Endpoint_SelectEndpoint(ep);
585 return 0;
586ERROR_EXIT:
587 Endpoint_SelectEndpoint(ep);
588 return -1;
589}
590#else
591int8_t sendchar(uint8_t c)
592{
87580356 593#ifdef LUFA_DEBUG_SUART
594 xmit(c);
595#endif
a074364c 596 return 0;
597}
598#endif
599
600
601/*******************************************************************************
602 * main
603 ******************************************************************************/
fdc38ef3 604static void setup_mcu(void)
a074364c 605{
606 /* Disable watchdog if enabled by bootloader/fuses */
607 MCUSR &= ~(1 << WDRF);
608 wdt_disable();
609
610 /* Disable clock division */
611 clock_prescale_set(clock_div_1);
fdc38ef3 612}
a074364c 613
fdc38ef3
JW
614static void setup_usb(void)
615{
a074364c 616 // Leonardo needs. Without this USB device is not recognized.
617 USB_Disable();
618
619 USB_Init();
620
621 // for Console_Task
622 USB_Device_EnableSOFEvents();
a074364c 623}
624
625int main(void) __attribute__ ((weak));
626int main(void)
627{
9818d54d 628 setup_mcu();
629
87580356 630#ifdef LUFA_DEBUG_SUART
9818d54d 631 SUART_OUT_DDR |= (1<<SUART_OUT_BIT);
632 SUART_OUT_PORT |= (1<<SUART_OUT_BIT);
87580356 633#endif
634 print_set_sendchar(sendchar);
9818d54d 635 print("\r\ninit\n");
636
71381457 637 hook_early_init();
fdc38ef3
JW
638 keyboard_setup();
639 setup_usb();
a074364c 640 sei();
641
642 /* wait for USB startup & debug output */
643 while (USB_DeviceState != DEVICE_STATE_Configured) {
644#if defined(INTERRUPT_CONTROL_ENDPOINT)
645 ;
646#else
647 USB_USBTask();
648#endif
649 }
650 print("USB configured.\n");
651
652 /* init modules */
653 keyboard_init();
654 host_set_driver(&lufa_driver);
655#ifdef SLEEP_LED_ENABLE
656 sleep_led_init();
657#endif
658
659 print("Keyboard start.\n");
71381457 660 hook_late_init();
a074364c 661 while (1) {
662 while (USB_DeviceState == DEVICE_STATE_Suspended) {
9818d54d 663#ifdef LUFA_DEBUG
a074364c 664 print("[s]");
9818d54d 665#endif
71381457 666 hook_usb_suspend_loop();
a074364c 667 }
668
669 keyboard_task();
670
671#if !defined(INTERRUPT_CONTROL_ENDPOINT)
672 USB_USBTask();
673#endif
674 }
675}
71381457 676
677
678/* hooks */
679__attribute__((weak))
680void hook_early_init(void) {}
681
682__attribute__((weak))
683void hook_late_init(void) {}
684
9818d54d 685static uint8_t _led_stats = 0;
71381457 686 __attribute__((weak))
687void hook_usb_suspend_entry(void)
688{
9818d54d 689 // Turn LED off to save power
690 // Set 0 with putting aside status before suspend and restore
691 // it after wakeup, then LED is updated at keyboard_task() in main loop
692 _led_stats = keyboard_led_stats;
693 keyboard_led_stats = 0;
694 led_set(keyboard_led_stats);
695
f76a786b 696 matrix_clear();
9818d54d 697 clear_keyboard();
71381457 698#ifdef SLEEP_LED_ENABLE
699 sleep_led_enable();
700#endif
701}
702
703__attribute__((weak))
704void hook_usb_suspend_loop(void)
705{
706 suspend_power_down();
707 if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
9818d54d 708 USB_Device_SendRemoteWakeup();
71381457 709 }
710}
711
712__attribute__((weak))
713void hook_usb_wakeup(void)
714{
715 suspend_wakeup_init();
716#ifdef SLEEP_LED_ENABLE
717 sleep_led_disable();
71381457 718#endif
9818d54d 719
720 // Restore LED status
721 // BIOS/grub won't recognize/enumerate if led_set() takes long(around 40ms?)
722 // Converters fall into the case and miss wakeup event(timeout to reply?) in the end.
723 //led_set(host_keyboard_leds());
724 // Instead, restore stats and update at keyboard_task() in main loop
725 keyboard_led_stats = _led_stats;
71381457 726}
Imprint / Impressum