/* * Copyright 2012 Jun Wako * This file is based on: * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse * LUFA-120219/Demos/Device/Lowlevel/GenericHID */ /* LUFA Library Copyright (C) Dean Camera, 2012. dean [at] fourwalledcubicle [dot] com www.lufa-lib.org */ /* Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com) Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com) Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. The author disclaim all warranties with regard to this software, including all implied warranties of merchantability and fitness. In no event shall the author be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ #include "report.h" #include "host.h" #include "host_driver.h" #include "keyboard.h" #include "action.h" #include "led.h" #include "sendchar.h" #include "ringbuf.h" #include "debug.h" #ifdef SLEEP_LED_ENABLE #include "sleep_led.h" #endif #include "suspend.h" #include "hook.h" #include "timer.h" #ifdef LUFA_DEBUG_SUART #include "avr/suart.h" #endif #include "matrix.h" #include "descriptor.h" #include "lufa.h" //#define LUFA_DEBUG uint8_t keyboard_idle = 0; /* 0: Boot Protocol, 1: Report Protocol(default) */ uint8_t keyboard_protocol = 1; static uint8_t keyboard_led_stats = 0; static report_keyboard_t keyboard_report_sent; /* Host driver */ static uint8_t keyboard_leds(void); static void send_keyboard(report_keyboard_t *report); static void send_mouse(report_mouse_t *report); static void send_system(uint16_t data); static void send_consumer(uint16_t data); host_driver_t lufa_driver = { keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer }; /******************************************************************************* * Console ******************************************************************************/ #ifdef CONSOLE_ENABLE #define SENDBUF_SIZE 256 static uint8_t sbuf[SENDBUF_SIZE]; static ringbuf_t sendbuf = { .buffer = sbuf, .head = 0, .tail = 0, .size_mask = SENDBUF_SIZE - 1 }; // TODO: Around 2500ms delay often works anyhoo but proper startup would be better // 1000ms delay of hid_listen affects this probably /* wait for Console startup */ static bool console_is_ready(void) { static bool hid_listen_ready = false; if (!hid_listen_ready) { if (timer_read32() < 2500) return false; hid_listen_ready = true; } return true; } static bool console_putc(uint8_t c) { if (!console_is_ready()) goto EXIT; // return immediately if called while interrupt if (!(SREG & (1<> 8); #ifdef LUFA_DEBUG xprintf("[I%d]%d", USB_ControlRequest.wIndex, (USB_ControlRequest.wValue & 0xFF00) >> 8); #endif } break; case HID_REQ_GetIdle: if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { Endpoint_ClearSETUP(); while (!(Endpoint_IsINReady())); Endpoint_Write_8(keyboard_idle); Endpoint_ClearIN(); Endpoint_ClearStatusStage(); #ifdef LUFA_DEBUG print("[i]"); #endif } break; } } /******************************************************************************* * Host driver ******************************************************************************/ static uint8_t keyboard_leds(void) { return keyboard_led_stats; } static void send_keyboard(report_keyboard_t *report) { uint8_t timeout = 128; if (USB_DeviceState != DEVICE_STATE_Configured) return; /* Select the Keyboard Report Endpoint */ #ifdef NKRO_ENABLE if (keyboard_protocol && keyboard_nkro) { /* Report protocol - NKRO */ Endpoint_SelectEndpoint(NKRO_IN_EPNUM); /* Check if write ready for a polling interval around 1ms */ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(8); if (!Endpoint_IsReadWriteAllowed()) return; /* Write Keyboard Report Data */ Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL); } else #endif { /* Boot protocol */ Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM); /* Check if write ready for a polling interval around 10ms */ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(80); if (!Endpoint_IsReadWriteAllowed()) return; /* Write Keyboard Report Data */ Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL); } /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); keyboard_report_sent = *report; } static void send_mouse(report_mouse_t *report) { #ifdef MOUSE_ENABLE uint8_t timeout = 255; if (USB_DeviceState != DEVICE_STATE_Configured) return; /* Select the Mouse Report Endpoint */ Endpoint_SelectEndpoint(MOUSE_IN_EPNUM); /* Check if write ready for a polling interval around 10ms */ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); if (!Endpoint_IsReadWriteAllowed()) return; /* Write Mouse Report Data */ Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); #endif } static void send_system(uint16_t data) { #ifdef EXTRAKEY_ENABLE uint8_t timeout = 255; if (USB_DeviceState != DEVICE_STATE_Configured) return; report_extra_t r = { .report_id = REPORT_ID_SYSTEM, .usage = data }; Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM); /* Check if write ready for a polling interval around 10ms */ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); if (!Endpoint_IsReadWriteAllowed()) return; Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); Endpoint_ClearIN(); #endif } static void send_consumer(uint16_t data) { #ifdef EXTRAKEY_ENABLE uint8_t timeout = 255; if (USB_DeviceState != DEVICE_STATE_Configured) return; report_extra_t r = { .report_id = REPORT_ID_CONSUMER, .usage = data }; Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM); /* Check if write ready for a polling interval around 10ms */ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); if (!Endpoint_IsReadWriteAllowed()) return; Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); Endpoint_ClearIN(); #endif } /******************************************************************************* * sendchar ******************************************************************************/ #ifdef CONSOLE_ENABLE int8_t sendchar(uint8_t c) { #ifdef LUFA_DEBUG_SUART xmit(c); #endif bool r = console_putc(c); return (r ? 0 : -1); } #else int8_t sendchar(uint8_t c) { #ifdef LUFA_DEBUG_SUART xmit(c); #endif return 0; } #endif /******************************************************************************* * main ******************************************************************************/ static void setup_mcu(void) { /* Disable watchdog if enabled by bootloader/fuses */ MCUSR &= ~(1 << WDRF); wdt_disable(); /* Disable clock division */ clock_prescale_set(clock_div_1); } static void setup_usb(void) { // Leonardo needs. Without this USB device is not recognized. USB_Disable(); USB_Init(); USB_Device_EnableSOFEvents(); } int main(void) __attribute__ ((weak)); int main(void) { setup_mcu(); #ifdef LUFA_DEBUG_SUART SUART_OUT_DDR |= (1<