diff options
Diffstat (limited to 'protocol')
56 files changed, 8711 insertions, 54 deletions
diff --git a/protocol/lufa.mk b/protocol/lufa.mk index ad6cab6d3b..bf6fc97b8e 100644 --- a/protocol/lufa.mk +++ b/protocol/lufa.mk @@ -1,18 +1,20 @@ LUFA_DIR = protocol/lufa # Path to the LUFA library -LUFA_PATH = $(TOP_DIR)/protocol/lufa/LUFA-120219 +LUFA_PATH = protocol/lufa/LUFA-120219 # Create the LUFA source path variables by including the LUFA root makefile -include $(LUFA_PATH)/LUFA/makefile +include $(TOP_DIR)/$(LUFA_PATH)/LUFA/makefile LUFA_SRC = $(LUFA_DIR)/lufa.c \ $(LUFA_DIR)/descriptor.c \ $(LUFA_SRC_USB) -SRC += $(subst $(LUFA_PATH)/,,$(LUFA_SRC)) + +SRC += $(LUFA_SRC) # Search Path -VPATH += $(LUFA_PATH) +VPATH += $(TOP_DIR)/$(LUFA_DIR) +VPATH += $(TOP_DIR)/$(LUFA_PATH) # Option modules #ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c index b7ecb8488d..81409ce9ed 100644 --- a/protocol/lufa/lufa.c +++ b/protocol/lufa/lufa.c @@ -59,7 +59,7 @@ 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); -static host_driver_t lufa_driver = { +host_driver_t lufa_driver = { keyboard_leds, send_keyboard, send_mouse, @@ -68,49 +68,9 @@ static host_driver_t lufa_driver = { }; -static void SetupHardware(void); -static void Console_Task(void); - -int main(void) -{ - SetupHardware(); - sei(); - - print_enable = true; - debug_enable = true; - debug_matrix = true; - debug_keyboard = true; - debug_mouse = true; - - // TODO: can't print here - debug("LUFA init\n"); - - keyboard_init(); - host_set_driver(&lufa_driver); - while (1) { - keyboard_proc(); - -#if !defined(INTERRUPT_CONTROL_ENDPOINT) - USB_USBTask(); -#endif - } -} - -void SetupHardware(void) -{ - /* Disable watchdog if enabled by bootloader/fuses */ - MCUSR &= ~(1 << WDRF); - wdt_disable(); - - /* Disable clock division */ - clock_prescale_set(clock_div_1); - - USB_Init(); - - // for Console_Task - USB_Device_EnableSOFEvents(); -} - +/******************************************************************************* + * Console + ******************************************************************************/ #ifdef CONSOLE_ENABLE static void Console_Task(void) { @@ -446,3 +406,51 @@ int8_t sendchar(uint8_t c) return 0; } #endif + + +/******************************************************************************* + * main + ******************************************************************************/ +static void SetupHardware(void) +{ + /* Disable watchdog if enabled by bootloader/fuses */ + MCUSR &= ~(1 << WDRF); + wdt_disable(); + + /* Disable clock division */ + clock_prescale_set(clock_div_1); + + // Leonardo needs. Without this USB device is not recognized. + USB_Disable(); + + USB_Init(); + + // for Console_Task + USB_Device_EnableSOFEvents(); +} + +int main(void) __attribute__ ((weak)); +int main(void) +{ + SetupHardware(); + sei(); + + print_enable = true; + debug_enable = true; + debug_matrix = true; + debug_keyboard = true; + debug_mouse = true; + + // TODO: can't print here + debug("LUFA init\n"); + + keyboard_init(); + host_set_driver(&lufa_driver); + while (1) { + keyboard_proc(); + +#if !defined(INTERRUPT_CONTROL_ENDPOINT) + USB_USBTask(); +#endif + } +} diff --git a/protocol/lufa/lufa.h b/protocol/lufa/lufa.h index 71c279b0dc..bcee060d67 100644 --- a/protocol/lufa/lufa.h +++ b/protocol/lufa/lufa.h @@ -47,8 +47,19 @@ #include <string.h> #include <LUFA/Version.h> #include <LUFA/Drivers/USB/USB.h> +#include "host.h" +#ifdef __cplusplus +extern "C" { +#endif + +extern host_driver_t lufa_driver; + +#ifdef __cplusplus +} +#endif + /* extra report structure */ typedef struct { uint8_t report_id; diff --git a/protocol/pjrc/main.c b/protocol/pjrc/main.c index 15f14920b4..0b0a44028e 100644 --- a/protocol/pjrc/main.c +++ b/protocol/pjrc/main.c @@ -42,12 +42,6 @@ #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) -bool debug_enable = false; -bool debug_matrix = false; -bool debug_keyboard = false; -bool debug_mouse = false; - - int main(void) { DEBUG_LED_CONFIG; diff --git a/protocol/usb_hid.mk b/protocol/usb_hid.mk new file mode 100644 index 0000000000..fb4916d562 --- /dev/null +++ b/protocol/usb_hid.mk @@ -0,0 +1,73 @@ +USB_HID_DIR = protocol/usb_hid + + +# +# USB Host Shield +# +USB_HOST_SHIELD_DIR = $(USB_HID_DIR)/USB_Host_Shield_2.0 +USB_HOST_SHIELD_SRC = \ + $(USB_HOST_SHIELD_DIR)/Usb.cpp \ + $(USB_HOST_SHIELD_DIR)/hid.cpp \ + $(USB_HOST_SHIELD_DIR)/parsetools.cpp \ + $(USB_HOST_SHIELD_DIR)/message.cpp + + + +# +# Arduino +# +ARDUINO_DIR = $(USB_HID_DIR)/arduino-1.0.1 +ARDUINO_CORES_DIR = $(ARDUINO_DIR)/cores/arduino +ARDUINO_CORES_SRC = \ + $(ARDUINO_CORES_DIR)/Print.cpp \ + $(ARDUINO_CORES_DIR)/Stream.cpp + +# replaced with override_Serial.c +# $(ARDUINO_CORES_DIR)/CDC.cpp \ +# $(ARDUINO_CORES_DIR)/HID.cpp \ +# $(ARDUINO_CORES_DIR)/USBCore.cpp \ + +# replaced with override_wiring.c and common/timer.c +# $(ARDUINO_CORES_DIR)/wiring.c \ + + + +# +# HID parser +# +SRC += $(USB_HID_DIR)/parser.cpp + +# replace arduino/CDC.cpp +SRC += $(USB_HID_DIR)/override_Serial.cpp + +# replace arduino/wiring.c +SRC += $(USB_HID_DIR)/override_wiring.c +SRC += common/timer.c + +SRC += $(USB_HOST_SHIELD_SRC) +SRC += $(ARDUINO_CORES_SRC) + + +OPT_DEFS += -DARDUINO=101 +# Arduino USBCore needs USB_VID and USB_PID. +#OPT_DEFS += -DARDUINO=101 -DUSB_VID=0x2341 -DUSB_PID=0x8036 + + + +# +# Search Path +# +VPATH += $(TOP_DIR)/$(USB_HID_DIR) +VPATH += $(TOP_DIR)/$(USB_HOST_SHIELD_DIR) + +# for #include "Arduino.h" +VPATH += $(TOP_DIR)/$(ARDUINO_CORES_DIR) + +# for #include "pins_arduino.h" +VPATH += $(TOP_DIR)/$(ARDUINO_DIR)/variants/leonardo + +# ad hoc workaround for compile problem on Windows: +# Windows doesn't know difference between common/print.h and arduino/Print.h. +# On Linux no problem. +# Change file name common/print.h to console.h ? +VPATH := $(TOP_DIR)/common $(VPATH) diff --git a/protocol/usb_hid/README b/protocol/usb_hid/README new file mode 100755 index 0000000000..1357a4c726 --- /dev/null +++ b/protocol/usb_hid/README @@ -0,0 +1,46 @@ +USB HID protocol +================ +Host side of USB HID keyboard protocol implementation. +Only standard HID Boot mode is supported at this time. This means most of normal keyboards are supported while proprietary >6KRO and NKRO is not. + +Third party Libraries +--------------------- +USB_Host_Shield_2.0 + Circuits@Home repository is git-submoduled. Do git submodule init & update to get the content. + https://github.com/felis/USB_Host_Shield_2.0 + +arduino-1.0.1 + Arduino files copied from: + https://github.com/arduino/Arduino/hardware/arduino/{cores,variants} + + +Test build +---------- +In test directory; + $ make + $ DEV=/dev/ttyACM0 make program + +You can see HID keyboard reports on debug output. + + +Restriction and Bug +------------------- +Not statble yet. + +Switching power on VBUS: + To power reset device. + http://www.circuitsathome.com/camera-control/simulating-cable-disconnect-on-usb-host-shield-2-0 + This is needed for a device which are not initilized with 'USB Bus Reset'(long SE0) + +Can't bus-reset a keyboard which already attached on bus properly. + Slow start up of Leonardo's bootloader causes this? + Need to unplug/plug a keyboard after firmware starts up. + MAX3421E doesn't work SAMPLEBUS well to know whether device connected or not. + +Keyboard with other endpoints than boot keyboard may go wrong. + On my keyboard with mouse key the converter locks up when using mouse key function. + +Can't compile on Windows filesystem. + On Linux no problem. + Windows doesn't know difference between common/print.h and arduino/Print.h. + Change file name common/print.h to console.h ? diff --git a/protocol/usb_hid/USB_Host_Shield_2.0 b/protocol/usb_hid/USB_Host_Shield_2.0 new file mode 160000 +Subproject 8bb790f83af298b5f3e5516259c9d8ec27efe52 diff --git a/protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h b/protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h new file mode 100644 index 0000000000..830c9952fb --- /dev/null +++ b/protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h @@ -0,0 +1,215 @@ +#ifndef Arduino_h +#define Arduino_h + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <avr/pgmspace.h> +#include <avr/io.h> +#include <avr/interrupt.h> + +#include "binary.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#define HIGH 0x1 +#define LOW 0x0 + +#define INPUT 0x0 +#define OUTPUT 0x1 +#define INPUT_PULLUP 0x2 + +#define true 0x1 +#define false 0x0 + +#define PI 3.1415926535897932384626433832795 +#define HALF_PI 1.5707963267948966192313216916398 +#define TWO_PI 6.283185307179586476925286766559 +#define DEG_TO_RAD 0.017453292519943295769236907684886 +#define RAD_TO_DEG 57.295779513082320876798154814105 + +#define SERIAL 0x0 +#define DISPLAY 0x1 + +#define LSBFIRST 0 +#define MSBFIRST 1 + +#define CHANGE 1 +#define FALLING 2 +#define RISING 3 + +#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) +#define DEFAULT 0 +#define EXTERNAL 1 +#define INTERNAL 2 +#else +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) +#define INTERNAL1V1 2 +#define INTERNAL2V56 3 +#else +#define INTERNAL 3 +#endif +#define DEFAULT 1 +#define EXTERNAL 0 +#endif + +// undefine stdlib's abs if encountered +#ifdef abs +#undef abs +#endif + +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#define abs(x) ((x)>0?(x):-(x)) +#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) +#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) +#define radians(deg) ((deg)*DEG_TO_RAD) +#define degrees(rad) ((rad)*RAD_TO_DEG) +#define sq(x) ((x)*(x)) + +#define interrupts() sei() +#define noInterrupts() cli() + +#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) +#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) +#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) + +#define lowByte(w) ((uint8_t) ((w) & 0xff)) +#define highByte(w) ((uint8_t) ((w) >> 8)) + +#define bitRead(value, bit) (((value) >> (bit)) & 0x01) +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) +#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) + + +typedef unsigned int word; + +#define bit(b) (1UL << (b)) + +typedef uint8_t boolean; +typedef uint8_t byte; + +void init(void); + +void pinMode(uint8_t, uint8_t); +void digitalWrite(uint8_t, uint8_t); +int digitalRead(uint8_t); +int analogRead(uint8_t); +void analogReference(uint8_t mode); +void analogWrite(uint8_t, int); + +unsigned long millis(void); +unsigned long micros(void); +void delay(unsigned long); +void delayMicroseconds(unsigned int us); +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); + +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); + +void attachInterrupt(uint8_t, void (*)(void), int mode); +void detachInterrupt(uint8_t); + +void setup(void); +void loop(void); + +// Get the bit location within the hardware port of the given virtual pin. +// This comes from the pins_*.c file for the active board configuration. + +#define analogInPinToBit(P) (P) + +// On the ATmega1280, the addresses of some of the port registers are +// greater than 255, so we can't store them in uint8_t's. +extern const uint16_t PROGMEM port_to_mode_PGM[]; +extern const uint16_t PROGMEM port_to_input_PGM[]; +extern const uint16_t PROGMEM port_to_output_PGM[]; + +extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; +// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; +extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; +extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; + +// Get the bit location within the hardware port of the given virtual pin. +// This comes from the pins_*.c file for the active board configuration. +// +// These perform slightly better as macros compared to inline functions +// +#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) +#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) +#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) +#define analogInPinToBit(P) (P) +#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) ) +#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) ) +#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) ) + +#define NOT_A_PIN 0 +#define NOT_A_PORT 0 + +#ifdef ARDUINO_MAIN +#define PA 1 +#define PB 2 +#define PC 3 +#define PD 4 +#define PE 5 +#define PF 6 +#define PG 7 +#define PH 8 +#define PJ 10 +#define PK 11 +#define PL 12 +#endif + +#define NOT_ON_TIMER 0 +#define TIMER0A 1 +#define TIMER0B 2 +#define TIMER1A 3 +#define TIMER1B 4 +#define TIMER2 5 +#define TIMER2A 6 +#define TIMER2B 7 + +#define TIMER3A 8 +#define TIMER3B 9 +#define TIMER3C 10 +#define TIMER4A 11 +#define TIMER4B 12 +#define TIMER4C 13 +#define TIMER4D 14 +#define TIMER5A 15 +#define TIMER5B 16 +#define TIMER5C 17 + +#ifdef __cplusplus +} // extern "C" +#endif + +#ifdef __cplusplus +#include "WCharacter.h" +#include "WString.h" +#include "HardwareSerial.h" + +uint16_t makeWord(uint16_t w); +uint16_t makeWord(byte h, byte l); + +#define word(...) makeWord(__VA_ARGS__) + +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); + +void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); +void noTone(uint8_t _pin); + +// WMath prototypes +long random(long); +long random(long, long); +void randomSeed(unsigned int); +long map(long, long, long, long, long); + +#endif + +#include "pins_arduino.h" + +#endif diff --git a/protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp b/protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp new file mode 100644 index 0000000000..1ee3a488a5 --- /dev/null +++ b/protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp @@ -0,0 +1,233 @@ + + +/* Copyright (c) 2011, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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 "Platform.h" +#include "USBAPI.h" +#include <avr/wdt.h> + +#if defined(USBCON) +#ifdef CDC_ENABLED + +#if (RAMEND < 1000) +#define SERIAL_BUFFER_SIZE 16 +#else +#define SERIAL_BUFFER_SIZE 64 +#endif + +struct ring_buffer +{ + unsigned char buffer[SERIAL_BUFFER_SIZE]; + volatile int head; + volatile int tail; +}; + +ring_buffer cdc_rx_buffer = { { 0 }, 0, 0}; + +typedef struct +{ + u32 dwDTERate; + u8 bCharFormat; + u8 bParityType; + u8 bDataBits; + u8 lineState; +} LineInfo; + +static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; + +#define WEAK __attribute__ ((weak)) + +extern const CDCDescriptor _cdcInterface PROGMEM; +const CDCDescriptor _cdcInterface = +{ + D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1), + + // CDC communication interface + D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0), + D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd) + D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not) + D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported + D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0 + D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40), + + // CDC data interface + D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0), + D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0), + D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0) +}; + +int WEAK CDC_GetInterface(u8* interfaceNum) +{ + interfaceNum[0] += 2; // uses 2 + return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface)); +} + +bool WEAK CDC_Setup(Setup& setup) +{ + u8 r = setup.bRequest; + u8 requestType = setup.bmRequestType; + + if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) + { + if (CDC_GET_LINE_CODING == r) + { + USB_SendControl(0,(void*)&_usbLineInfo,7); + return true; + } + } + + if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) + { + if (CDC_SET_LINE_CODING == r) + { + USB_RecvControl((void*)&_usbLineInfo,7); + return true; + } + + if (CDC_SET_CONTROL_LINE_STATE == r) + { + _usbLineInfo.lineState = setup.wValueL; + + // auto-reset into the bootloader is triggered when the port, already + // open at 1200 bps, is closed. this is the signal to start the watchdog + // with a relatively long period so it can finish housekeeping tasks + // like servicing endpoints before the sketch ends + if (1200 == _usbLineInfo.dwDTERate) { + // We check DTR state to determine if host port is open (bit 0 of lineState). + if ((_usbLineInfo.lineState & 0x01) == 0) { + *(uint16_t *)0x0800 = 0x7777; + wdt_enable(WDTO_120MS); + } else { + // Most OSs do some intermediate steps when configuring ports and DTR can + // twiggle more than once before stabilizing. + // To avoid spurious resets we set the watchdog to 250ms and eventually + // cancel if DTR goes back high. + + wdt_disable(); + wdt_reset(); + *(uint16_t *)0x0800 = 0x0; + } + } + return true; + } + } + return false; |