Separated CDC, HID and its APIs.

Also added Absolute Mouse and changed the structure. Added a better
readme for changelog and todo list.
This commit is contained in:
Nico 2014-12-26 21:47:07 +01:00
parent e120b47a49
commit f7fe5f32aa
13 changed files with 1280 additions and 666 deletions

252
Arduino.h Normal file
View file

@ -0,0 +1,252 @@
/*
Arduino.h - Main include file for the Arduino SDK
Copyright (c) 2005-2013 Arduino Team. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Arduino_h
#define Arduino_h
#include <stdlib.h>
#include <stdbool.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
void yield(void);
#define HIGH 0x1
#define LOW 0x0
#define INPUT 0x0
#define OUTPUT 0x1
#define INPUT_PULLUP 0x2
#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 EULER 2.718281828459045235360287471352
#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_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
#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))
// avr-libc defines _NOP() since 1.6.2
#ifndef _NOP
#define _NOP() do { __asm__ volatile ("nop"); } while (0)
#endif
typedef unsigned int word;
#define bit(b) (1UL << (b))
typedef uint8_t boolean;
typedef uint8_t byte;
void init(void);
void initVariant(void);
int atexit(void (*func)()) __attribute__((weak));
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
#define NOT_AN_INTERRUPT -1
#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 TIMER1C 5
#define TIMER2 6
#define TIMER2A 7
#define TIMER2B 8
#define TIMER3A 9
#define TIMER3B 10
#define TIMER3C 11
#define TIMER4A 12
#define TIMER4B 13
#define TIMER4C 14
#define TIMER4D 15
#define TIMER5A 16
#define TIMER5B 17
#define TIMER5C 18
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
#include "WCharacter.h"
#include "WString.h"
#include "HardwareSerial.h"
#include "USBAPI.h"
#include "CDC.h"
#include "HID.h"
#if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL)
#error "Targets with both UART0 and CDC serial not supported"
#endif
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

View file

@ -16,7 +16,7 @@
** SOFTWARE.
*/
#include "USBAPI.h"
#include "CDC.h"
#include <avr/wdt.h>
#if defined(USBCON)

77
CDC.h Normal file
View file

@ -0,0 +1,77 @@
/*
CDC.h
Copyright (c) 2005-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __CDC__
#define __CDC__
#include "Arduino.h"
#if defined(USBCON)
#include "USBDesc.h"
#include "USBCore.h"
//================================================================================
//================================================================================
// Serial over CDC (Serial1 is the physical port)
struct ring_buffer;
#if (RAMEND < 1000)
#define SERIAL_BUFFER_SIZE 16
#else
#define SERIAL_BUFFER_SIZE 64
#endif
class Serial_ : public Stream
{
private:
int peek_buffer;
public:
Serial_() { peek_buffer = -1; };
void begin(unsigned long);
void begin(unsigned long, uint8_t);
void end(void);
virtual int available(void);
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t*, size_t);
using Print::write; // pull in write(str) and write(buf, size) from Print
uint32_t baud(void);
uint8_t stopbits(void);
uint8_t paritytype(void);
uint8_t numbits(void);
bool dtr(void);
bool rts(void);
operator bool();
volatile uint8_t _rx_buffer_head;
volatile uint8_t _rx_buffer_tail;
unsigned char _rx_buffer[SERIAL_BUFFER_SIZE];
};
extern Serial_ Serial;
#define HAVE_CDCSERIAL
#endif /* if defined(USBCON) */
#endif

483
HID.cpp
View file

@ -16,138 +16,32 @@
** SOFTWARE.
*/
#include "USBAPI.h"
#include "HID.h"
#define WEAK __attribute__ ((weak))
#if defined(USBCON)
#ifdef HID_ENABLED
//#define RAWHID_ENABLED
// Singletons for mouse and keyboard
Mouse_ Mouse;
Keyboard_ Keyboard;
//================================================================================
//================================================================================
// HID report descriptor
#define LSB(_x) ((_x) & 0xFF)
#define MSB(_x) ((_x) >> 8)
#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF
#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF
#define RAWHID_TX_SIZE (USB_EP_SIZE-1)
#define RAWHID_RX_SIZE (USB_EP_SIZE-1)
#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED)
// extern accessible led out report
uint8_t hid_keyboard_leds = 0;
#endif
extern const u8 _hidReportDescriptor[] PROGMEM;
const u8 _hidReportDescriptor[] = {
#ifdef HID_MOUSE_ENABLED
// Mouse
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x85, HID_REPORTID_MouseReport,// REPORT_ID
// 5 buttons
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x05, // USAGE_MAXIMUM (Button 5)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
// reserved
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
// x, y, wheel
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x38, // USAGE (Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x06, // INPUT (Data,Var,Rel)
// end
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
#endif
#ifdef HID_KEYBOARD_ENABLED
// Keyboard
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, HID_REPORTID_KeyboardReport, // REPORT_ID
0x05, 0x07, // USAGE_PAGE (Keyboard)
// modifiers
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
// reserved byte
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
// Key[6] Array
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
// by default use the standard HID APIs
#ifndef EXTERN_HID_REPORT
#ifdef HID_KEYBOARD_LEDS_ENABLED
// LEDs for num lock etc
0x05, 0x08, /* USAGE_PAGE (LEDs) */
0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */
0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
0x95, 0x05, /* REPORT_COUNT (5) */
0x75, 0x01, /* REPORT_SIZE (1) */
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
// Reserved 3 bits
0x95, 0x01, /* REPORT_COUNT (1) */
0x75, 0x03, /* REPORT_SIZE (3) */
0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */
HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD),
#else
HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD),
#endif
// end
0xc0, // END_COLLECTION
#endif
#ifdef HID_RAWHID_ENABLED
// RAW HID
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
0xA1, 0x01, // Collection 0x01
0x85, HID_REPORTID_RawKeyboardReport, // REPORT_ID
0x75, 0x08, // report size = 8 bits
0x15, 0x00, // logical minimum = 0
0x26, 0xFF, 0x00, // logical maximum = 255
0x95, RAWHID_TX_SIZE, // report count TX
0x09, 0x01, // usage
0x81, 0x02, // Input (array)
0x95, RAWHID_RX_SIZE, // report count RX
0x09, 0x02, // usage
0x91, 0x02, // Output (array)
0xC0, // end collection
HID_REPORT_MOUSE(HID_REPORTID_MOUSE),
HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE),
//HID_REPORT_RAWHID(HID_REPORTID_RAWHID),
HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL),
HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL),
#else
EXTERN_HID_REPORT
#endif
};
@ -167,8 +61,6 @@ const HIDDescriptor _hidInterface =
u8 _hid_protocol = 1;
u8 _hid_idle = 1;
#define WEAK __attribute__ ((weak))
int WEAK HID_GetInterface(u8* interfaceNum)
{
interfaceNum[0] += 1; // uses 1
@ -217,354 +109,39 @@ bool WEAK HID_Setup(Setup& setup)
_hid_idle = setup.wValueL;
return true;
}
#if defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED)
#if defined(HID_KEYBOARD_LEDS_ENABLED)
if (HID_SET_REPORT == r)
{
//TODO check correct report ID (not needed for now, no other device has an out report)
// maybe make this a general weak implementation to use it for RAW HID later?
if (setup.wLength == 2)
{
// write led out report data
uint8_t data[2];
if (2 == USB_RecvControl(data, 2))
hid_keyboard_leds = data[1];
HID_SetKeyboardLedReport(data[1]);
}
// else TODO check for other devices like RAW HID, not needed for now
}
#endif
}
return false;
}
//================================================================================
//================================================================================
// Mouse
#ifdef HID_MOUSE_ENABLED
Mouse_::Mouse_(void) : _buttons(0)
{
#if defined(HID_KEYBOARD_LEDS_ENABLED)
void WEAK HID_SetKeyboardLedReport(uint8_t leds){
// weak function implemented by the Keyboard API
// to not always create the Keyboard object, if it isn't used
}
void Mouse_::begin(void)
{
}
void Mouse_::end(void)
{
}
void Mouse_::click(uint8_t b)
{
_buttons = b;
move(0, 0, 0);
_buttons = 0;
move(0, 0, 0);
}
void Mouse_::move(signed char x, signed char y, signed char wheel)
{
u8 m[4];
m[0] = _buttons;
m[1] = x;
m[2] = y;
m[3] = wheel;
HID_SendReport(1, m, 4);
}
void Mouse_::buttons(uint8_t b)
{
if (b != _buttons)
{
_buttons = b;
move(0, 0, 0);
}
}
void Mouse_::press(uint8_t b)
{
buttons(_buttons | b);
}
void Mouse_::release(uint8_t b)
{
buttons(_buttons & ~b);
}
bool Mouse_::isPressed(uint8_t b)
{
if ((b & _buttons) > 0)
return true;
return false;
}
#endif
//================================================================================
//================================================================================
// Keyboard
#ifdef HID_KEYBOARD_ENABLED
Keyboard_::Keyboard_(void)
{
}
void Keyboard_::begin(void)
{
}
void Keyboard_::end(void)
{
}
void Keyboard_::sendReport(KeyReport* keys)
{
HID_SendReport(2, keys, sizeof(KeyReport));
}
extern
const uint8_t _asciimap[128] PROGMEM;
#define SHIFT 0x80
const uint8_t _asciimap[128] =
{
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x34 | SHIFT, // "
0x20 | SHIFT, // #
0x21 | SHIFT, // $
0x22 | SHIFT, // %
0x24 | SHIFT, // &
0x34, // '
0x26 | SHIFT, // (
0x27 | SHIFT, // )
0x25 | SHIFT, // *
0x2e | SHIFT, // +
0x36, // ,
0x2d, // -
0x37, // .
0x38, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x33 | SHIFT, // :
0x33, // ;
0x36 | SHIFT, // <
0x2e, // =
0x37 | SHIFT, // >
0x38 | SHIFT, // ?
0x1f | SHIFT, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x2f, // [
0x31, // bslash
0x30, // ]
0x23 | SHIFT, // ^
0x2d | SHIFT, // _
0x35, // `
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x2f | SHIFT, //
0x31 | SHIFT, // |
0x30 | SHIFT, // }
0x35 | SHIFT, // ~
0 // DEL
};
uint8_t USBPutChar(uint8_t c);
// press() adds the specified key (printing, non-printing, or modifier)
// to the persistent key report and sends the report. Because of the way
// USB HID works, the host acts like the key remains pressed until we
// call release(), releaseAll(), or otherwise clear the report and resend.
size_t Keyboard_::press(uint8_t k)
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
}
else if (k >= 128) { // it's a modifier key
_keyReport.modifiers |= (1 << (k - 128));
k = 0;
}
else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
setWriteError();
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
_keyReport.modifiers |= 0x02; // the left shift modifier
k &= 0x7F;
}
}
// Add k to the key report only if it's not already present
// and if there is an empty slot.
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
for (i = 0; i < 6; i++) {
if (_keyReport.keys[i] == 0x00) {
_keyReport.keys[i] = k;
break;
}
}
if (i == 6) {
setWriteError();
return 0;
}
}
sendReport(&_keyReport);
return 1;
}
// release() takes the specified key out of the persistent key report and
// sends the report. This tells the OS the key is no longer pressed and that
// it shouldn't be repeated any more.
size_t Keyboard_::release(uint8_t k)
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
}
else if (k >= 128) { // it's a modifier key
_keyReport.modifiers &= ~(1 << (k - 128));
k = 0;
}
else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
_keyReport.modifiers &= ~(0x02); // the left shift modifier
k &= 0x7F;
}
}
// Test the key report to see if k is present. Clear it if it exists.
// Check all positions in case the key is present more than once (which it shouldn't be)
for (i = 0; i < 6; i++) {
if (0 != k && _keyReport.keys[i] == k) {
_keyReport.keys[i] = 0x00;
}
}
sendReport(&_keyReport);
return 1;
}
void Keyboard_::releaseAll(void)
{
_keyReport.keys[0] = 0;
_keyReport.keys[1] = 0;
_keyReport.keys[2] = 0;
_keyReport.keys[3] = 0;
_keyReport.keys[4] = 0;
_keyReport.keys[5] = 0;
_keyReport.modifiers = 0;
sendReport(&_keyReport);
}
size_t Keyboard_::write(uint8_t c)
{
uint8_t p = press(c); // Keydown
release(c); // Keyup
return p; // just return the result of press() since release() almost always returns 1
}
#endif
#endif
#else /* if defined(USBCON) */
void WEAK HID_SendReport(u8 id, const void* data, int len)
{
// empty to let the user use the HIDAPI for different use
}
#endif /* if defined(USBCON) */

287
HID.h Normal file
View file

@ -0,0 +1,287 @@
/*
HID.h
Copyright (c) 2005-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __HID__
#define __HID__
#include "Arduino.h"
// enable Led out report by default
#ifndef EXTERN_HID_REPORT
#define HID_KEYBOARD_LEDS_ENABLED
#endif
// HID report IDs
// note by NicoHood: I would not change the current IDs, since it can confuse the OS
// I had several problems if i change the report id and its use.
// It doesnt matter if a device is not presented and there is a lack of IDs (at least number 1 must be represented)
// Report IDs and the report itself can be overwritten by the pins_arduino.h
#ifndef HID_REPORTID_MOUSE
#define HID_REPORTID_MOUSE 1
#endif
#ifndef HID_REPORTID_KEYBOARD
#define HID_REPORTID_KEYBOARD 2
#endif
#ifndef HID_REPORTID_RAWHID
#define HID_REPORTID_RAWHID 3
#endif
#ifndef HID_REPORTID_CONSUMERCONTROL
#define HID_REPORTID_CONSUMERCONTROL 4
#endif
#ifndef HID_REPORTID_SYSTEMCONTROL
#define HID_REPORTID_SYSTEMCONTROL 5
#endif
#ifndef HID_REPORTID_GAMEPAD
#define HID_REPORTID_GAMEPAD 5
#endif
#ifndef HID_REPORTID_MOUSE_ABSOLUTE
#define HID_REPORTID_MOUSE_ABSOLUTE 6
#endif
// HID reports
// Report IDs and the report itself can be overwritten by the pins_arduino.h
#ifndef HID_REPORT_MOUSE
#define HID_REPORT_MOUSE(report_id) /* Mouse relative */ \
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ \
0x09, 0x02, /* USAGE (Mouse) */ \
0xa1, 0x01, /* COLLECTION (Application) */ \
0x85, report_id, /* REPORT_ID */ \
\
/* 8 Buttons */ \
0x05, 0x09, /* USAGE_PAGE (Button) */ \
0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \
0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ \
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \
0x95, 0x08, /* REPORT_COUNT (8) */ \
0x75, 0x01, /* REPORT_SIZE (1) */ \
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \
\
/* X, Y, Wheel */ \
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \
0x09, 0x30, /* USAGE (X) */ \
0x09, 0x31, /* USAGE (Y) */ \
0x09, 0x38, /* USAGE (Wheel) */ \
0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ \
0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ \
0x75, 0x08, /* REPORT_SIZE (8) */ \
0x95, 0x03, /* REPORT_COUNT (3) */ \
0x81, 0x06, /* INPUT (Data,Var,Rel) */ \
\
/* End */ \
0xc0 /* END_COLLECTION */
#endif
#ifndef HID_REPORT_MOUSE_ABSOLUTE
#define HID_REPORT_MOUSE_ABSOLUTE(report_id) /* Mouse absolute */ \
0x05, 0x01, /* Usage Page (Generic Desktop) */ \
0x09, 0x02, /* Usage (Mouse) */ \
0xA1, 0x01, /* Collection (Application) */ \
0x85, report_id, /* REPORT_ID */ \
0x05, 0x01, /* Usage Page (Generic Desktop) */ \
0x09, 0x30, /* Usage (X) */ \
0x09, 0x31, /* Usage (Y) */ \
0x15, 0x00, /* Logical Minimum (0) */ \
0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ \
0x75, 0x10, /* Report Size (16), */ \
0x95, 0x02, /* Report Count (2), */ \
0x81, 0x02, /* Input (Data, Variable, Absolute) */ \
0xC0 /* End Collection */
#endif
#ifndef HID_REPORT_KEYBOARD_LEDS
#define HID_REPORT_KEYBOARD_LEDS(report_id) /* Keyboard */ \
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ \
0x09, 0x06, /* USAGE (Keyboard) */ \
0xa1, 0x01, /* COLLECTION (Application) */ \
0x85, report_id, /* REPORT_ID */ \
0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \
\
/* Keyboard Modifiers (shift, alt, ...) */ \
0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ \
0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \
0x75, 0x01, /* REPORT_SIZE (1) */ \
0x95, 0x08, /* REPORT_COUNT (8) */ \
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \
\
/* Reserved byte */ \
0x95, 0x01, /* REPORT_COUNT (1) */ \
0x75, 0x08, /* REPORT_SIZE (8) */ \
0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \
\
/* 5 LEDs for num lock etc */ \
0x05, 0x08, /* USAGE_PAGE (LEDs) */ \
0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ \
0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ \
0x95, 0x05, /* REPORT_COUNT (5) */ \
0x75, 0x01, /* REPORT_SIZE (1) */ \
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ \
/* Reserved 3 bits */ \
0x95, 0x01, /* REPORT_COUNT (1) */ \
0x75, 0x03, /* REPORT_SIZE (3) */ \
0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ \
\
/* 6 Keyboard keys */ \
0x95, 0x06, /* REPORT_COUNT (6) */ \
0x75, 0x08, /* REPORT_SIZE (8) */ \
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \
0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ \
0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \
0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \
0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \
0x81, 0x00, /* INPUT (Data,Ary,Abs) */ \
\
/* End */ \
0xc0 /* END_COLLECTION */
#endif
#ifndef HID_REPORT_KEYBOARD_KEYS
#define HID_REPORT_KEYBOARD_KEYS(report_id) /* Keyboard */ \
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ \
0x09, 0x06, /* USAGE (Keyboard) */ \
0xa1, 0x01, /* COLLECTION (Application) */ \
0x85, report_id, /* REPORT_ID */ \
0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \
\
/* Keyboard Modifiers (shift, alt, ...) */ \
0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ \
0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \
0x75, 0x01, /* REPORT_SIZE (1) */ \
0x95, 0x08, /* REPORT_COUNT (8) */ \
0x81, 0x02, /* INPUT (Data,Var,Abs) */ \
\
/* Reserved byte */ \
0x95, 0x01, /* REPORT_COUNT (1) */ \
0x75, 0x08, /* REPORT_SIZE (8) */ \
0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \
\
HID_REPORT_KEYBOARD_LEDS \
/* 6 Keyboard keys */ \
0x95, 0x06, /* REPORT_COUNT (6) */ \
0x75, 0x08, /* REPORT_SIZE (8) */ \
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \
0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ \
0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \
0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \
0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \
0x81, 0x00, /* INPUT (Data,Ary,Abs) */ \
\
/* End */ \
0xc0 /* END_COLLECTION */
#endif
//TODO limit to system keys only?
#ifndef HID_REPORT_SYSTEMCONTROL
#define HID_REPORT_SYSTEMCONTROL(report_id) /* System Control (Power Down, Sleep, Wakeup, ...) */ \
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \
0x09, 0x80, /* USAGE (System Control) */ \
0xa1, 0x01, /* COLLECTION (Application) */ \
0x85, report_id, /* REPORT_ID */ \
/* 1 system key */ \
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \
0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ \
0x19, 0x00, /* USAGE_MINIMUM (Undefined) */ \
0x29, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ \
0x95, 0x01, /* REPORT_COUNT (1) */ \
0x75, 0x08, /* REPORT_SIZE (8) */ \
0x81, 0x00, /* INPUT (Data,Ary,Abs) */ \
0xc0 /* END_COLLECTION */
#endif
#ifndef HID_REPORT_CONSUMERCONTROL
#define HID_REPORT_CONSUMERCONTROL(report_id) /* Consumer Control (Sound/Media keys) */ \
0x05, 0x0C, /* usage page (consumer device) */ \
0x09, 0x01, /* usage -- consumer control */ \
0xA1, 0x01, /* collection (application) */ \
0x85, report_id, /* report id */ \
/* 4 Media Keys */ \
0x15, 0x00, /* logical minimum */ \
0x26, 0xFF, 0x03, /* logical maximum (3ff) */ \
0x19, 0x00, /* usage minimum (0) */ \
0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ \
0x95, 0x04, /* report count (4) */ \
0x75, 0x10, /* report size (16) */ \
0x81, 0x00, /* input */ \
0xC0 /* end collection */
#endif
// note by NicoHood: RawHID might never work with multireports, because of OS problems
// therefore we have to make it a single report with no idea. No other HID device will be supported then.
#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF
#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF
#define RAWHID_TX_SIZE (USB_EP_SIZE-1)
#define RAWHID_RX_SIZE (USB_EP_SIZE-1)
#define LSB(_x) ((_x) & 0xFF)
#define MSB(_x) ((_x) >> 8)
#ifndef HID_REPORT_RAWHID
#define HID_REPORT_RAWHID(report_id) /* RAW HID */ \
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), /* 30 */ \
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), \
\
0xA1, 0x01, /* Collection 0x01 */ \
0x85, report_id, /* REPORT_ID */ \
0x75, 0x08, /* report size = 8 bits */ \
0x15, 0x00, /* logical minimum = 0 */ \
0x26, 0xFF, 0x00, /* logical maximum = 255 */ \
\
0x95, RAWHID_TX_SIZE, /* report count TX */ \
0x09, 0x01, /* usage */ \
0x81, 0x02, /* Input (array) */ \
\
0x95, RAWHID_RX_SIZE, /* report count RX */ \
0x09, 0x02, /* usage */ \
0x91, 0x02, /* Output (array) */ \
0xC0 /* end collection */
#endif
#if defined(USBCON)
#include "USBDesc.h"
#include "USBCore.h"
#include "HIDAPI.h"
//================================================================================
//================================================================================
// HID 'Driver'
int HID_GetInterface(uint8_t* interfaceNum);
int HID_GetDescriptor(int i);
bool HID_Setup(Setup& setup);
void HID_SendReport(uint8_t id, const void* data, int len);
#if defined(HID_KEYBOARD_LEDS_ENABLED)
void HID_SetKeyboardLedReport(uint8_t leds);
#endif
#else /* if defined(USBCON) */
// (weak) function prototype to let the user use the HIDAPI for different use
// if he include the api himself
void HID_SendReport(uint8_t id, const void* data, int len);
#endif /* if defined(USBCON) */
#endif

28
HIDAPI.h Normal file
View file

@ -0,0 +1,28 @@
/*
HIDAPI.h
Copyright (c) 2005-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __HIDAPI__
#define __HIDAPI__
// include all HID APIs
#include "Keyboard.h"
#include "Mouse.h"
//TODO
#endif

284
Keyboard.cpp Normal file
View file

@ -0,0 +1,284 @@
/*
Keyboard.cpp
Copyright (c) 2005-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "Keyboard.h"
//================================================================================
//================================================================================
// Keyboard
#if defined(HID_KEYBOARD_LEDS_ENABLED)
uint8_t hid_keyboard_leds = 0;
void HID_SetKeyboardLedReport(uint8_t leds){
hid_keyboard_leds = leds;
}
#endif
Keyboard_ Keyboard;
Keyboard_::Keyboard_(void)
{
}
void Keyboard_::begin(void)
{
}
void Keyboard_::end(void)
{
}
void Keyboard_::sendReport(KeyReport* keys)
{
HID_SendReport(HID_REPORTID_KEYBOARD, keys, sizeof(KeyReport));
}
extern
const uint8_t _asciimap[128] PROGMEM;
#define SHIFT 0x80
const uint8_t _asciimap[128] =
{
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x34 | SHIFT, // "
0x20 | SHIFT, // #
0x21 | SHIFT, // $
0x22 | SHIFT, // %
0x24 | SHIFT, // &
0x34, // '
0x26 | SHIFT, // (
0x27 | SHIFT, // )
0x25 | SHIFT, // *
0x2e | SHIFT, // +
0x36, // ,
0x2d, // -
0x37, // .
0x38, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x33 | SHIFT, // :
0x33, // ;
0x36 | SHIFT, // <
0x2e, // =
0x37 | SHIFT, // >
0x38 | SHIFT, // ?
0x1f | SHIFT, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x2f, // [
0x31, // bslash
0x30, // ]
0x23 | SHIFT, // ^
0x2d | SHIFT, // _
0x35, // `
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x2f | SHIFT, //
0x31 | SHIFT, // |
0x30 | SHIFT, // }
0x35 | SHIFT, // ~
0 // DEL
};
// press() adds the specified key (printing, non-printing, or modifier)
// to the persistent key report and sends the report. Because of the way
// USB HID works, the host acts like the key remains pressed until we
// call release(), releaseAll(), or otherwise clear the report and resend.
size_t Keyboard_::press(uint8_t k)
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
}
else if (k >= 128) { // it's a modifier key
_keyReport.modifiers |= (1 << (k - 128));
k = 0;
}
else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
setWriteError();
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
_keyReport.modifiers |= 0x02; // the left shift modifier
k &= 0x7F;
}
}
// Add k to the key report only if it's not already present
// and if there is an empty slot.
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
for (i = 0; i < 6; i++) {
if (_keyReport.keys[i] == 0x00) {
_keyReport.keys[i] = k;
break;
}
}
if (i == 6) {
setWriteError();
return 0;
}
}
sendReport(&_keyReport);
return 1;
}
// release() takes the specified key out of the persistent key report and
// sends the report. This tells the OS the key is no longer pressed and that
// it shouldn't be repeated any more.
size_t Keyboard_::release(uint8_t k)
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
}
else if (k >= 128) { // it's a modifier key
_keyReport.modifiers &= ~(1 << (k - 128));
k = 0;
}
else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
_keyReport.modifiers &= ~(0x02); // the left shift modifier
k &= 0x7F;
}
}
// Test the key report to see if k is present. Clear it if it exists.
// Check all positions in case the key is present more than once (which it shouldn't be)
for (i = 0; i < 6; i++) {
if (0 != k && _keyReport.keys[i] == k) {
_keyReport.keys[i] = 0x00;
}
}
sendReport(&_keyReport);
return 1;
}
void Keyboard_::releaseAll(void)
{
// release all keys
memset(&_keyReport, 0x00, sizeof(_keyReport));
sendReport(&_keyReport);
}
size_t Keyboard_::write(uint8_t c)
{
uint8_t p = press(c); // Keydown
release(c); // Keyup
return p; // just return the result of press() since release() almost always returns 1
}

110
Keyboard.h Normal file
View file

@ -0,0 +1,110 @@
/*
Keyboard.h
Copyright (c) 2005-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __KEYBOARDAPI__
#define __KEYBOARDAPI__
// to access the HID_SendReport via USBAPI.h, report number and the Print class
#include "Arduino.h"
//================================================================================
//================================================================================
// Keyboard
#define KEY_PRINT 0xCE
#define KEY_NUM_LOCK 0xDB
#define KEY_SCROLL_LOCK 0xCF
#define KEY_PAUSE 0xD0
#define KEY_LEFT_CTRL 0x80
#define KEY_LEFT_SHIFT 0x81
#define KEY_LEFT_ALT 0x82
#define KEY_LEFT_GUI 0x83
#define KEY_LEFT_WINDOWS KEY_LEFT_GUI
#define KEY_RIGHT_CTRL 0x84
#define KEY_RIGHT_SHIFT 0x85
#define KEY_RIGHT_ALT 0x86
#define KEY_RIGHT_GUI 0x87
#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI
#define KEY_UP_ARROW 0xDA
#define KEY_DOWN_ARROW 0xD9
#define KEY_LEFT_ARROW 0xD8
#define KEY_RIGHT_ARROW 0xD7
#define KEY_BACKSPACE 0xB2
#define KEY_TAB 0xB3
#define KEY_RETURN 0xB0
#define KEY_ESC 0xB1
#define KEY_INSERT 0xD1
#define KEY_DELETE 0xD4
#define KEY_PAGE_UP 0xD3
#define KEY_PAGE_DOWN 0xD6
#define KEY_HOME 0xD2
#define KEY_END 0xD5
#define KEY_CAPS_LOCK 0xC1
#define KEY_F1 0xC2
#define KEY_F2 0xC3
#define KEY_F3 0xC4
#define KEY_F4 0xC5
#define KEY_F5 0xC6
#define KEY_F6 0xC7
#define KEY_F7 0xC8
#define KEY_F8 0xC9
#define KEY_F9 0xCA
#define KEY_F10 0xCB
#define KEY_F11 0xCC
#define KEY_F12 0xCD
#define LED_NUM_LOCK 0x01
#define LED_CAPS_LOCK 0x02
#define LED_SCROLL_LOCK 0x04
// Low level key report: up to 6 keys and shift, ctrl etc at once
typedef struct
{
uint8_t modifiers;
uint8_t reserved;
uint8_t keys[6];
} KeyReport;
// extern accessible led out report
extern uint8_t hid_keyboard_leds;
class Keyboard_ : public Print
{
protected:
KeyReport _keyReport;
void sendReport(KeyReport* keys);
public:
Keyboard_(void);
void begin(void);
void end(void);
size_t write(uint8_t k);
size_t press(uint8_t k);
size_t release(uint8_t k);
void releaseAll(void);
//TODO
#if defined(HID_KEYBOARD_LEDS_ENABLED)
inline uint8_t getLEDs(void){ return hid_keyboard_leds; }
#endif
};
extern Keyboard_ Keyboard;
#endif

88
Mouse.cpp Normal file
View file

@ -0,0 +1,88 @@
/*
Mouse.cpp
Copyright (c) 2005-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "Mouse.h"
//================================================================================
//================================================================================
// Mouse
Mouse_ Mouse;
Mouse_::Mouse_(void) : _buttons(0)
{
}
void Mouse_::begin(void)
{
}
void Mouse_::end(void)
{
}
void Mouse_::click(uint8_t b)
{
_buttons = b;
move(0, 0, 0);
_buttons = 0;
move(0, 0, 0);
}
void Mouse_::move(signed char x, signed char y, signed char wheel)
{
u8 m[4];
m[0] = _buttons;
m[1] = x;
m[2] = y;
m[3] = wheel;
HID_SendReport(1, m, 4);
}
void Mouse_::buttons(uint8_t b)
{
if (b != _buttons)
{
_buttons = b;
move(0, 0, 0);
}
}
void Mouse_::press(uint8_t b)
{
buttons(_buttons | b);
}
void Mouse_::release(uint8_t b)
{
buttons(_buttons & ~b);
}
bool Mouse_::isPressed(uint8_t b)
{
if ((b & _buttons) > 0)
return true;
return false;
}
void Mouse_::moveTo(uint16_t x, uint16_t y)
{
uint32_t pos = ((uint32_t)y << 16) | x;
HID_SendReport(HID_REPORTID_MOUSE_ABSOLUTE, &pos, sizeof(pos));
}

56
Mouse.h Normal file
View file

@ -0,0 +1,56 @@
/*
Mouse.h
Copyright (c) 2005-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __MOUSEAPI__
#define __MOUSEAPI__
// to access the HID_SendReport via USBAPI.h and report number
#include "Arduino.h"
//================================================================================
//================================================================================
// Mouse
#define MOUSE_LEFT 0x01
#define MOUSE_RIGHT 0x02
#define MOUSE_MIDDLE 0x04
#define MOUSE_PREV 0x08
#define MOUSE_NEXT 0x10
#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT)
class Mouse_
{
private:
uint8_t _buttons;
void buttons(uint8_t b);
public:
Mouse_(void);
void begin(void);
void end(void);
void click(uint8_t b = MOUSE_LEFT);
void move(signed char x, signed char y, signed char wheel = 0);
void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default
void moveTo(uint16_t x, uint16_t y);
};
extern Mouse_ Mouse;
#endif

54
Readme.md Normal file
View file

@ -0,0 +1,54 @@
TODO
====
Under Construction. This is a todo list for myself and a feature list so far.
```
Keyboard Layout english only?
more usb definitions instead of fixed values, noone understands
someone has to add the keywords.txt definitions as well
keyboard music vol (change descriptor)
keyboard led move to usb function not to keyboard and from keyboard call this function?
weak hidsendreport implement somewhere the prototype?
move HID-Core to a seperate folder?
usb wakeup
keycode/raw for keyboard
magic key fix?
add examples
void Recv(volatile u8* data, u8 count) static inline??
Bugs
Mouse Abs only works with system report under special circumstances.
```
```
(flash numbers might be irrelevant due to a lot of improvements)
* Uses less flash if HID or Serial is not used
* Extended and compacter(flash) HID Report Descriptors
* Fixed USB Device Descriptor
* Added u2 compatibility with smaller USB_EP_SIZE (16u2 etc)
* Added Serial Event for LineEncoding and LineState (+12b flash)
* Added Serial Function to get dtr state, line encoding etc
* Added Keyboard Led Out report to get Led states (for numlock etc, +52b flash, 1b ram)
* Made CDC-Core independent from USB-Core
* Made HID-Core independent from USB-Core
* Made HID-API independent from HID-Core
* Removed not needed virtual functions in Keyboard
* Made HID Reports and its IDs replaceable via pins_Arduino.h
* Added Absolute Mouse
```
```
Include schematic
- Arduino.h
- USBAPI.h -> Arduino.h, USBDESC.h, USBCore.h
- CDC.h -> Arduino.h, USBDESC.h, USBCore.h
- HID.h -> Arduino.h, USBDESC.h, USBCore.h, HID-API
- HID-API -> Keyboard.h, Mouse.h
- Keyboard.h -> Arduino.h
- Mouse.h -> Arduino.h
HID.h contains all HID configuration.
Each HID-API (like Mouse) includes Arduino.h and gets these settings as well.
```

212
USBAPI.h
View file

@ -34,29 +34,6 @@ typedef unsigned long u32;
#if defined(USBCON)
// include needed HID devices
// the more you activate, the more flash it will take
// by default only Mouse + Keyboard (without LEDs) are activated
#define HID_MOUSE_ENABLED
#define HID_KEYBOARD_ENABLED
//#define HID_KEYBOARD_LEDS_ENABLED
//#define HID_RAWHID_ENABLED (currently broken for USB-Core)
//#define HID_MEDIA_ENABLED
//#define HID_SYSTEM_ENABLED
//#define HID_GAMEPAD_ENABLED
/** Enum for the HID report IDs used in the device. */
typedef enum{
HID_REPORTID_NotAReport = 0x00, /**< first entry is always zero for multireports */
HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */
HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */
HID_REPORTID_RawHidReport = 0x03, /**< Report ID for the Raw Hid report within the device. */
HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */
HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */
HID_REPORTID_GamepadReport = 0x06, /**< Report ID for the Gamepad report within the device. */
} HID_Report_IDs;
#include "USBDesc.h"
#include "USBCore.h"
@ -76,195 +53,6 @@ public:
};
extern USBDevice_ USBDevice;
//================================================================================
//================================================================================
// Serial over CDC (Serial1 is the physical port)
struct ring_buffer;
#if (RAMEND < 1000)
#define SERIAL_BUFFER_SIZE 16
#else
#define SERIAL_BUFFER_SIZE 64
#endif
class Serial_ : public Stream
{
private:
int peek_buffer;
public:
Serial_() { peek_buffer = -1; };
void begin(unsigned long);
void begin(unsigned long, uint8_t);
void end(void);
virtual int available(void);
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t*, size_t);
using Print::write; // pull in write(str) and write(buf, size) from Print
uint32_t baud(void);
uint8_t stopbits(void);
uint8_t paritytype(void);
uint8_t numbits(void);
bool dtr(void);
bool rts(void);
operator bool();
volatile uint8_t _rx_buffer_head;
volatile uint8_t _rx_buffer_tail;
unsigned char _rx_buffer[SERIAL_BUFFER_SIZE];
};
extern Serial_ Serial;
#define HAVE_CDCSERIAL
//================================================================================
//================================================================================
// Mouse
#ifdef HID_MOUSE_ENABLED
#define MOUSE_LEFT 0x01
#define MOUSE_RIGHT 0x02
#define MOUSE_MIDDLE 0x04
#define MOUSE_PREV 0x08
#define MOUSE_NEXT 0x10
#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT)
class Mouse_
{
private:
uint8_t _buttons;
void buttons(uint8_t b);
public:
Mouse_(void);
void begin(void);
void end(void);
void click(uint8_t b = MOUSE_LEFT);
void move(signed char x, signed char y, signed char wheel = 0);
void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default
};
extern Mouse_ Mouse;
#endif
//================================================================================
//================================================================================
// Keyboard
#ifdef HID_KEYBOARD_ENABLED
#define KEY_PRINT 0xCE
#define KEY_NUM_LOCK 0xDB
#define KEY_SCROLL_LOCK 0xCF
#define KEY_PAUSE 0xD0
#define KEY_LEFT_CTRL 0x80
#define KEY_LEFT_SHIFT 0x81
#define KEY_LEFT_ALT 0x82
#define KEY_LEFT_GUI 0x83
#define KEY_LEFT_WINDOWS KEY_LEFT_GUI
#define KEY_RIGHT_CTRL 0x84
#define KEY_RIGHT_SHIFT 0x85
#define KEY_RIGHT_ALT 0x86
#define KEY_RIGHT_GUI 0x87
#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI
#define KEY_UP_ARROW 0xDA
#define KEY_DOWN_ARROW 0xD9
#define KEY_LEFT_ARROW 0xD8
#define KEY_RIGHT_ARROW 0xD7
#define KEY_BACKSPACE 0xB2
#define KEY_TAB 0xB3
#define KEY_RETURN 0xB0
#define KEY_ESC 0xB1
#define KEY_INSERT 0xD1
#define KEY_DELETE 0xD4
#define KEY_PAGE_UP 0xD3
#define KEY_PAGE_DOWN 0xD6
#define KEY_HOME 0xD2
#define KEY_END 0xD5
#define KEY_CAPS_LOCK 0xC1
#define KEY_F1 0xC2
#define KEY_F2 0xC3
#define KEY_F3 0xC4
#define KEY_F4 0xC5
#define KEY_F5 0xC6
#define KEY_F6 0xC7
#define KEY_F7 0xC8
#define KEY_F8 0xC9
#define KEY_F9 0xCA
#define KEY_F10 0xCB
#define KEY_F11 0xCC
#define KEY_F12 0xCD
#define LED_NUM_LOCK 0x01
#define LED_CAPS_LOCK 0x02
#define LED_SCROLL_LOCK 0x04
#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED)
// extern accessible led out report
extern uint8_t hid_keyboard_leds;
#endif
// Low level key report: up to 6 keys and shift, ctrl etc at once
typedef struct
{
uint8_t modifiers;
uint8_t reserved;
uint8_t keys[6];
} KeyReport;
class Keyboard_ : public Print
{
private:
KeyReport _keyReport;
void sendReport(KeyReport* keys);
public:
Keyboard_(void);
void begin(void);
void end(void);
virtual size_t write(uint8_t k);
virtual size_t press(uint8_t k);
virtual size_t release(uint8_t k);
virtual void releaseAll(void);
#if defined(HID_KEYBOARD_LEDS_ENABLED)
inline uint8_t getLEDs(void){ return hid_keyboard_leds; }
#endif
};
extern Keyboard_ Keyboard;
#endif
//================================================================================
//================================================================================
// Low level API
typedef struct
{
uint8_t bmRequestType;
uint8_t bRequest;
uint8_t wValueL;
uint8_t wValueH;
uint16_t wIndex;
uint16_t wLength;
} Setup;
//================================================================================
//================================================================================
// HID 'Driver'
int HID_GetInterface(uint8_t* interfaceNum);
int HID_GetDescriptor(int i);
bool HID_Setup(Setup& setup);
void HID_SendReport(uint8_t id, const void* data, int len);
//================================================================================
//================================================================================
// MSC 'Driver'

View file

@ -317,5 +317,18 @@ typedef struct
#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 }
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
//================================================================================
//================================================================================
// Low level API
typedef struct
{
uint8_t bmRequestType;
uint8_t bRequest;
uint8_t wValueL;
uint8_t wValueH;
uint16_t wIndex;
uint16_t wLength;
} Setup;
#endif