qmk_firmware

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

protocol.c (3642B)


      1 /* Name: main.c
      2  * Project: hid-mouse, a very simple HID example
      3  * Author: Christian Starkjohann
      4  * Creation Date: 2008-04-07
      5  * Tabsize: 4
      6  * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
      7  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
      8  * This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $
      9  */
     10 
     11 #include <stdint.h>
     12 
     13 #include <avr/interrupt.h>
     14 #include <avr/power.h>
     15 #include <avr/wdt.h>
     16 #include <avr/sleep.h>
     17 
     18 #include <usbdrv/usbdrv.h>
     19 
     20 #include "vusb.h"
     21 
     22 #include "keyboard.h"
     23 #include "host.h"
     24 #include "timer.h"
     25 #include "debug.h"
     26 #include "suspend.h"
     27 #include "wait.h"
     28 #include "sendchar.h"
     29 
     30 /* This is from main.c of USBaspLoader */
     31 static void initForUsbConnectivity(void) {
     32     uint8_t i = 0;
     33 
     34     usbInit();
     35     /* enforce USB re-enumerate: */
     36     usbDeviceDisconnect(); /* do this while interrupts are disabled */
     37     while (--i) {          /* fake USB disconnect for > 250 ms */
     38         wdt_reset();
     39         wait_ms(1);
     40     }
     41     usbDeviceConnect();
     42 }
     43 
     44 static inline void vusb_send_remote_wakeup(void) {
     45     cli();
     46 
     47     uint8_t ddr_orig = USBDDR;
     48     USBOUT |= (1 << USBMINUS);
     49     USBDDR = ddr_orig | USBMASK;
     50     USBOUT ^= USBMASK;
     51 
     52     wait_ms(25);
     53 
     54     USBOUT ^= USBMASK;
     55     USBDDR = ddr_orig;
     56     USBOUT &= ~(1 << USBMINUS);
     57 
     58     sei();
     59 }
     60 
     61 bool vusb_suspended = false;
     62 
     63 /** \brief Setup USB
     64  *
     65  * FIXME: Needs doc
     66  */
     67 static void setup_usb(void) {
     68     initForUsbConnectivity();
     69 }
     70 
     71 uint16_t sof_timer = 0;
     72 
     73 void protocol_setup(void) {
     74 #if USB_COUNT_SOF
     75     sof_timer = timer_read();
     76 #endif
     77 
     78 #ifdef CLKPR
     79     // avoid unintentional changes of clock frequency in devices that have a
     80     // clock prescaler
     81     clock_prescale_set(clock_div_1);
     82 #endif
     83 }
     84 
     85 void protocol_pre_init(void) {
     86     setup_usb();
     87     sei();
     88 }
     89 
     90 void protocol_post_init(void) {
     91     host_set_driver(vusb_driver());
     92     wait_ms(50);
     93 }
     94 
     95 static inline bool should_do_suspend(void) {
     96 #if USB_COUNT_SOF
     97     if (usbSofCount != 0) {
     98         usbSofCount    = 0;
     99         sof_timer      = timer_read();
    100         vusb_suspended = false;
    101     } else {
    102         // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1)
    103         if (!vusb_suspended && timer_elapsed(sof_timer) > 5) {
    104             vusb_suspended = true;
    105         }
    106     }
    107 #endif
    108     return vusb_suspended;
    109 }
    110 
    111 void protocol_pre_task(void) {
    112 #if !defined(NO_USB_STARTUP_CHECK)
    113     if (should_do_suspend()) {
    114         dprintln("suspending keyboard");
    115         while (should_do_suspend()) {
    116             suspend_power_down();
    117             if (suspend_wakeup_condition()) {
    118                 vusb_send_remote_wakeup();
    119 
    120 #    if USB_SUSPEND_WAKEUP_DELAY > 0
    121                 // Some hubs, kvm switches, and monitors do
    122                 // weird things, with USB device state bouncing
    123                 // around wildly on wakeup, yielding race
    124                 // conditions that can corrupt the keyboard state.
    125                 //
    126                 // Pause for a while to let things settle...
    127                 wait_ms(USB_SUSPEND_WAKEUP_DELAY);
    128                 // ...and then update the wakeup matrix again as the waking key
    129                 // might have been released during the delay
    130                 update_matrix_state_after_wakeup();
    131 #    endif
    132             }
    133         }
    134         suspend_wakeup_init();
    135     }
    136 #endif
    137 }
    138 
    139 void protocol_keyboard_task(void) {
    140     usbPoll();
    141 
    142     // TODO: configuration process is inconsistent. it sometime fails.
    143     // To prevent failing to configure NOT scan keyboard during configuration
    144     if (usbConfiguration && usbInterruptIsReady()) {
    145         keyboard_task();
    146     }
    147 }
    148 
    149 void protocol_post_task(void) {
    150     // do nothing
    151 }