qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

chibios.c (5708B)


      1 /*
      2  * (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
      3  *
      4  * Based on the following work:
      5  *  - Guillaume Duc's raw hid example (MIT License)
      6  *    https://github.com/guiduc/usb-hid-chibios-example
      7  *  - PJRC Teensy examples (MIT License)
      8  *    https://www.pjrc.com/teensy/usb_keyboard.html
      9  *  - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
     10  *    https://github.com/tmk/tmk_keyboard/
     11  *  - ChibiOS demo code (Apache 2.0 License)
     12  *    http://www.chibios.org
     13  *
     14  * Since some GPL'd code is used, this work is licensed under
     15  * GPL v2 or later.
     16  */
     17 
     18 #include <ch.h>
     19 #include <hal.h>
     20 
     21 #include "usb_main.h"
     22 
     23 /* TMK includes */
     24 #include "report.h"
     25 #include "host.h"
     26 #include "host_driver.h"
     27 #include "keyboard.h"
     28 #include "action.h"
     29 #include "action_util.h"
     30 #include "usb_device_state.h"
     31 #include "mousekey.h"
     32 #include "led.h"
     33 #include "sendchar.h"
     34 #include "debug.h"
     35 #include "print.h"
     36 
     37 #ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
     38 // Change this to be TRUE once we've migrated keyboards to the new init system
     39 // Remember to change docs/platformdev_chibios_earlyinit.md as well.
     40 #    define EARLY_INIT_PERFORM_BOOTLOADER_JUMP FALSE
     41 #endif
     42 
     43 #ifdef MIDI_ENABLE
     44 #    include "qmk_midi.h"
     45 #endif
     46 #include "suspend.h"
     47 #include "wait.h"
     48 
     49 #define USB_GETSTATUS_REMOTE_WAKEUP_ENABLED (2U)
     50 
     51 #ifdef WAIT_FOR_USB
     52 // TODO: Remove backwards compatibility with old define
     53 #    define USB_WAIT_FOR_ENUMERATION
     54 #endif
     55 
     56 /* -------------------------
     57  *   TMK host driver defs
     58  * -------------------------
     59  */
     60 
     61 /* declarations */
     62 void send_keyboard(report_keyboard_t *report);
     63 void send_nkro(report_nkro_t *report);
     64 void send_mouse(report_mouse_t *report);
     65 void send_extra(report_extra_t *report);
     66 void send_raw_hid(uint8_t *data, uint8_t length);
     67 
     68 /* host struct */
     69 host_driver_t chibios_driver = {
     70     .keyboard_leds = usb_device_state_get_leds,
     71     .send_keyboard = send_keyboard,
     72     .send_nkro     = send_nkro,
     73     .send_mouse    = send_mouse,
     74     .send_extra    = send_extra,
     75 #ifdef RAW_ENABLE
     76     .send_raw_hid = send_raw_hid,
     77 #endif
     78 };
     79 
     80 #ifdef VIRTSER_ENABLE
     81 void virtser_task(void);
     82 #endif
     83 
     84 /* TESTING
     85  * Amber LED blinker thread, times are in milliseconds.
     86  */
     87 /* set this variable to non-zero anywhere to blink once */
     88 // static THD_WORKING_AREA(waThread1, 128);
     89 // static THD_FUNCTION(Thread1, arg) {
     90 
     91 //   (void)arg;
     92 //   chRegSetThreadName("blinker");
     93 //   while (true) {
     94 //     systime_t time;
     95 
     96 //     time = USB_DRIVER.state == USB_ACTIVE ? 250 : 500;
     97 //     palClearLine(LINE_CAPS_LOCK);
     98 //     chSysPolledDelayX(MS2RTC(STM32_HCLK, time));
     99 //     palSetLine(LINE_CAPS_LOCK);
    100 //     chSysPolledDelayX(MS2RTC(STM32_HCLK, time));
    101 //   }
    102 // }
    103 
    104 /* Early initialisation
    105  */
    106 __attribute__((weak)) void early_hardware_init_pre(void) {
    107 #if EARLY_INIT_PERFORM_BOOTLOADER_JUMP
    108     void enter_bootloader_mode_if_requested(void);
    109     enter_bootloader_mode_if_requested();
    110 #endif // EARLY_INIT_PERFORM_BOOTLOADER_JUMP
    111 }
    112 
    113 __attribute__((weak)) void early_hardware_init_post(void) {}
    114 
    115 __attribute__((weak)) void board_init(void) {}
    116 
    117 // This overrides what's normally in ChibiOS board definitions
    118 void __early_init(void) {
    119     early_hardware_init_pre();
    120 
    121     // This is the renamed equivalent of __early_init in the board.c file
    122     void __chibios_override___early_init(void);
    123     __chibios_override___early_init();
    124 
    125     early_hardware_init_post();
    126 }
    127 
    128 // This overrides what's normally in ChibiOS board definitions
    129 void boardInit(void) {
    130     // This is the renamed equivalent of boardInit in the board.c file
    131     void __chibios_override_boardInit(void);
    132     __chibios_override_boardInit();
    133 
    134     board_init();
    135 }
    136 
    137 void protocol_setup(void) {
    138     usb_device_state_init();
    139 
    140     // TESTING
    141     // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
    142 }
    143 
    144 void protocol_pre_init(void) {
    145     /* Init USB */
    146     usb_event_queue_init();
    147     init_usb_driver(&USB_DRIVER);
    148 
    149 #ifdef MIDI_ENABLE
    150     setup_midi();
    151 #endif
    152 
    153     /* Wait until USB is active */
    154 #ifdef USB_WAIT_FOR_ENUMERATION
    155     while (USB_DRIVER.state != USB_ACTIVE) {
    156         wait_ms(50);
    157     }
    158 #endif
    159 
    160     /* Do need to wait here!
    161      * Otherwise the next print might start a transfer on console EP
    162      * before the USB is completely ready, which sometimes causes
    163      * HardFaults.
    164      */
    165     wait_ms(50);
    166 
    167     print("USB configured.\n");
    168 }
    169 
    170 void protocol_post_init(void) {
    171     host_set_driver(&chibios_driver);
    172 }
    173 
    174 void protocol_pre_task(void) {
    175     usb_event_queue_task();
    176 
    177 #if !defined(NO_USB_STARTUP_CHECK)
    178     if (USB_DRIVER.state == USB_SUSPENDED) {
    179         dprintln("suspending keyboard");
    180         while (USB_DRIVER.state == USB_SUSPENDED) {
    181             /* Do this in the suspended state */
    182             suspend_power_down(); // on AVR this deep sleeps for 15ms
    183             /* Remote wakeup */
    184             if (suspend_wakeup_condition() && (USB_DRIVER.status & USB_GETSTATUS_REMOTE_WAKEUP_ENABLED)) {
    185                 usbWakeupHost(&USB_DRIVER);
    186 #    if USB_SUSPEND_WAKEUP_DELAY > 0
    187                 // Some hubs, kvm switches, and monitors do
    188                 // weird things, with USB device state bouncing
    189                 // around wildly on wakeup, yielding race
    190                 // conditions that can corrupt the keyboard state.
    191                 //
    192                 // Pause for a while to let things settle...
    193                 wait_ms(USB_SUSPEND_WAKEUP_DELAY);
    194                 // ...and then update the wakeup matrix again as the waking key
    195                 // might have been released during the delay
    196                 update_matrix_state_after_wakeup();
    197 #    endif
    198             }
    199         }
    200         /* Woken up */
    201     }
    202 #endif
    203 }
    204 
    205 void protocol_post_task(void) {
    206 #ifdef VIRTSER_ENABLE
    207     virtser_task();
    208 #endif
    209     usb_idle_task();
    210 }