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 }