Starting from Zero

This commit is contained in:
Nico 2014-12-08 17:02:18 +01:00
parent 402efb58c1
commit c4c2f47f61
26 changed files with 0 additions and 4582 deletions

2
.gitignore vendored
View file

@ -1,2 +0,0 @@
dev/*
*.pdn

275
CDC.cpp
View file

@ -1,275 +0,0 @@
/* 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.
*/
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "USBAPI.h"
#include <avr/wdt.h>
#if defined(USBCON)
#ifdef CDC_ENABLED
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),
// edit by NicoHood
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, USB_EP_SIZE, 0),
D_ENDPOINT(USB_ENDPOINT_IN(CDC_ENDPOINT_IN), USB_ENDPOINT_TYPE_BULK, USB_EP_SIZE, 0)
};
int WEAK CDC_GetInterface(u8* interfaceNum)
{
interfaceNum[0] += 2; // uses 2
return USB_SendControl(TRANSFER_PGM, &_cdcInterface, sizeof(_cdcInterface));
}
// edit by NicoHood
// ensure the address isnt used anywhere else by adding a compiler flag in the makefile lf flag
// -Wl,--section-start=.blkey=0x280
//TODO where to put that flag? use different position: 0x100 maybe?
// someone has to add the compiler flag to fix this bug: https://github.com/arduino/Arduino/issues/2474
//volatile uint8_t MagicBootKey __attribute__((section(".blkey")));
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);
}
if (CDC_SET_CONTROL_LINE_STATE == r)
{
_usbLineInfo.lineState = setup.wValueL;
}
if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r)
{
// 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
// We check DTR state to determine if host port is open (bit 0 of lineState).
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
{
// edit by NicoHood
// change ram pointer to fit the 16u2's ram size and only use a 8bit value
#if defined(__AVR_ATmega32U4__)
*(uint16_t *)0x0800 = 0x7777;
wdt_enable(WDTO_120MS);
#else
// workaround for this issue:
// https://github.com/arduino/Arduino/issues/2474
// I didnt change this for the 32u4 to simply not touch their code
cli();
//MagicBootKey = 0x77;
*(uint8_t *)0x0280 = 0x77;
wdt_enable(WDTO_120MS);
// wait for reset
for (;;);
#endif
}
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.
// edit by NicoHood
#if defined(__AVR_ATmega32U4__)
wdt_disable();
wdt_reset();
*(uint16_t *)0x0800 = 0x0;
#else
// not used because of the workaround above
//wdt_disable();
//wdt_reset();
//MagicBootKey = 0x0;
//*(uint8_t *)0x0280 = 0x00;
#endif
}
}
return true;
}
return false;
}
void Serial_::begin(unsigned long /* baud_count */)
{
peek_buffer = -1;
}
void Serial_::begin(unsigned long /* baud_count */, byte /* config */)
{
peek_buffer = -1;
}
void Serial_::end(void)
{
}
// edit by NicoHood
uint8_t Serial_::lineState(void)
{
return _usbLineInfo.lineState;
}
int Serial_::available(void)
{
if (peek_buffer >= 0) {
return 1 + USB_Available(CDC_RX);
}
return USB_Available(CDC_RX);
}
int Serial_::peek(void)
{
if (peek_buffer < 0)
peek_buffer = USB_Recv(CDC_RX);
return peek_buffer;
}
int Serial_::read(void)
{
if (peek_buffer >= 0) {
int c = peek_buffer;
peek_buffer = -1;
return c;
}
return USB_Recv(CDC_RX);
}
void Serial_::flush(void)
{
USB_Flush(CDC_TX);
}
size_t Serial_::write(uint8_t c)
{
return write(&c, 1);
}
size_t Serial_::write(const uint8_t *buffer, size_t size)
{
/* only try to send bytes if the high-level CDC connection itself
is open (not just the pipe) - the OS should set lineState when the port
is opened and clear lineState when the port is closed.
bytes sent before the user opens the connection or after
the connection is closed are lost - just like with a UART. */
// TODO - ZE - check behavior on different OSes and test what happens if an
// open connection isn't broken cleanly (cable is yanked out, host dies
// or locks up, or host virtual serial port hangs)
if (_usbLineInfo.lineState > 0) {
int r = USB_Send(CDC_TX, buffer, size);
if (r > 0) {
return r;
}
else {
setWriteError();
return 0;
}
}
setWriteError();
return 0;
}
// This operator is a convenient way for a sketch to check whether the
// port has actually been configured and opened by the host (as opposed
// to just being connected to the host). It can be used, for example, in
// setup() before printing to ensure that an application on the host is
// actually ready to receive and display the data.
// We add a short delay before returning to fix a bug observed by Federico
// where the port is configured (lineState != 0) but not quite opened.
Serial_::operator bool() {
bool result = false;
if (_usbLineInfo.lineState > 0)
result = true;
delay(10);
return result;
}
Serial_ Serial;
#endif
#endif /* if defined(USBCON) */

405
HID.cpp
View file

@ -1,405 +0,0 @@
/* 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.
*/
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "USBAPI.h"
#if defined(USBCON)
#ifdef HID_ENABLED
//================================================================================
//================================================================================
// HID report descriptor
#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)
#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) */
#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
#endif
#ifdef HID_MEDIA_ENABLED
// Media
0x05, 0x0C, // usage page (consumer device)
0x09, 0x01, // usage -- consumer control
0xA1, 0x01, // collection (application)
0x85, HID_REPORTID_MediaReport, // report id
//0x05, 0x0C, // usage page (consumer)
// 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
#ifdef HID_SYSTEM_ENABLED
// System
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x80, // USAGE (System Control)
0xa1, 0x01, // COLLECTION (Application)
0x85, HID_REPORTID_SystemReport, // 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
#ifdef HID_GAMEPAD_ENABLED
// Gamepad
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0x85, HID_REPORTID_GamepadReport, // REPORT_ID
// 32 Buttons
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x20, // USAGE_MAXIMUM (Button 32)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x20, // REPORT_COUNT (32)
0x81, 0x02, // INPUT (Data,Var,Abs)
// 4 16bit Axis
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x33, // USAGE (Rx)
0x09, 0x34, // USAGE (Ry)
0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768)
0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
// 2 8bit Axis
0x09, 0x32, // USAGE (Z)
0x09, 0x35, // USAGE (Rz)
0x15, 0x80, // LOGICAL_MINIMUM (-128)
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
// 2 Hat Switches
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x39, // USAGE (Hat switch)
0x09, 0x39, // USAGE (Hat switch)
0x15, 0x01, // LOGICAL_MINIMUM (1)
0x25, 0x08, // LOGICAL_MAXIMUM (8)
0x95, 0x02, // REPORT_COUNT (2)
0x75, 0x04, // REPORT_SIZE (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
#endif
};
extern const HIDDescriptor _hidInterface PROGMEM;
const HIDDescriptor _hidInterface =
{
D_INTERFACE(HID_INTERFACE, 1, 3, 0, 0),
D_HIDREPORT(sizeof(_hidReportDescriptor)),
// edit by NicoHood
D_ENDPOINT(USB_ENDPOINT_IN(HID_ENDPOINT_INT), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01)
};
//================================================================================
//================================================================================
// Driver
u8 _hid_protocol = 1;
u8 _hid_idle = 1;
#define WEAK __attribute__ ((weak))
int WEAK HID_GetInterface(u8* interfaceNum)
{
interfaceNum[0] += 1; // uses 1
return USB_SendControl(TRANSFER_PGM, &_hidInterface, sizeof(_hidInterface));
}
int WEAK HID_GetDescriptor(int /* i */)
{
return USB_SendControl(TRANSFER_PGM, _hidReportDescriptor, sizeof(_hidReportDescriptor));
}
void WEAK HID_SendReport(u8 id, const void* data, int len)
{
USB_Send(HID_TX, &id, 1);
USB_Send(HID_TX | TRANSFER_RELEASE, data, len);
}
bool WEAK HID_Setup(Setup& setup)
{
u8 r = setup.bRequest;
u8 requestType = setup.bmRequestType;
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
{
if (HID_GET_REPORT == r)
{
//HID_GetReport();
return true;
}
if (HID_GET_PROTOCOL == r)
{
//Send8(_hid_protocol); // TODO
return true;
}
}
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
{
if (HID_SET_PROTOCOL == r)
{
_hid_protocol = setup.wValueL;
return true;
}
if (HID_SET_IDLE == r)
{
_hid_idle = setup.wValueL;
return true;
}
// edit by NicoHood
#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED)
if (HID_SET_REPORT == r)
{
if (setup.wLength == 2)
{
uint8_t data[2];
if (2 == USB_RecvControl(data, 2))
{
// write led out report data
hid_keyboard_leds=data[1];
}
}
}
#endif
}
return false;
}
#endif
#else if defined(USE_USB_API)
// still provide the weak HID_SendReport function to be able to overwrite it externaly
void __attribute__((weak)) HID_SendReport(uint8_t id, const void* data, int len)
{
// the user has to overwrite this if no USB Core is used
}
#endif /* if defined(USBCON) */
// HID API libs are only included if the device has USB functionality or if the USE_USB_API is needed
#if defined(USBCON) || defined(USE_USB_API)
//================================================================================
// Mouse
//================================================================================
#ifdef HID_MOUSE_ENABLED
// object instance
Mouse_ Mouse;
#endif
//================================================================================
// Keyboard
//================================================================================
#ifdef HID_KEYBOARD_ENABLED
// object instance
Keyboard_ Keyboard;
#endif
//================================================================================
// Media
//================================================================================
#ifdef HID_MEDIA_ENABLED
// object instance
Media_ Media;
#endif
//================================================================================
// System
//================================================================================
#ifdef HID_SYSTEAM_ENABLED
// object instance
System_ System;
#endif
//================================================================================
// Gamepad
//================================================================================
#ifdef HID_GAMEPAD_ENABLED
// object instance
Gamepad_ Gamepad;
#endif
#endif // if defined(USBCON) || defined(USE_USB_API)

330
Readme.md
View file

@ -1,330 +0,0 @@
Arduino HID Project 2.0
=======================
![Header Picture](header.jpg)
This project went through a lot of phases and has now reached an HID library with 3 software solutions.
The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards.
This is done with slightly different methods for different boards.
**Arduino IDE 1.5.8 is required for the HID Project.**
**Supported HID devices:**
* Keyboard with Leds out (modifiers + 6 keys pressed at the same time)
* Mouse (5 buttons, move, wheel)
* Media Keys (4 keys for music player, webbrowser and more)
* System Key (for PC standby/shutdown)
* 1 Gamepad (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads)
**Supported Arduinos:**
* Uno
* Mega
* Leonardo
* (Pro)Micro
* Any other 8u2/16u/at90usb162/32u2/32u4 compatible board
| Leonardo/Micro | Uno/Mega HoodLoader2 | Uno/Mega HoodLoader1 |
|:---------------------------|:----------------------------|---------------------------------------|
| Extended Arduino USB-Core | Same Core as Leonardo/Micro | Coded with Lufa |
| More HID devices | Fully reprogrammable 16u2 | No reprogrammable 16u2 |
| Keyboard Led Out report | Serial0 fully usable | Main MCU sends HID reports on Serial0 |
| System Wakeup fix (soon) | | Serial Protocol filters HID reports |
| Serial Control Line access | | Built-in ISP function |
The HID project contains HID APIs to generate HID reports and functions to send them to the USB Host.
The API (syntax/usage) of the HID Project is always the same for each solution, **you can port code from one device to another very easy**.
* On a Leonardo this function is extended and improved to get more HID devices + some improvements.
* [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is a BootLoader for the 16u2 that let's you use it as standalone MCU with the same USB-Core.
* [HoodLoader1](https://github.com/NicoHood/HoodLoader) is a 16u2 firmware that filters special HW Serial signals from the main MCU and sends HID signals to the USB Host.
To make things more clear the HID Software is in a separate repository than the HoodLoader (1 & 2) sources and installing instructions.
**HoodLoader 1&2 is only used for an Uno/Mega to actually enable USB functions.** The 16u2 is normally used for USB-Serial programming of the main MCU but can do way more than that.
To use HoodLoader1&2 you also need the HID Project. For more information and installation instructions see the specific repository.
HoodLoader1 was the first solution to enable HID functions to the Uno/Mega but HoodLoader2 opens way more options because you can reprogram the whole MCU standalone.
See the repository for more infos about this great new opportunity. HoodLoader1 API is still usable in a specific example. HoodLoader1&2 are not needed/compatible with a Leonardo/Micro.
Installation
============
**Please remove any older HID Project files from your sketchbook and your Arduino core to not run into any problems.**
Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to (access the examples, keywords.txt with IDE).
Then **move and replace** all .h and .cpp files to the path below. **I strongly recommend to install the library like this. Otherwise it wont work.**
```
C:\Arduino\arduino-1.5.8\hardware\arduino\avr\cores\arduino
```
The installation path may differ to yours. **Please use Arduino IDE 1.5.8** and file an issue if a newer version isn't working.
Restart the IDE. Ensure all drivers are installed. See [this](https://learn.sparkfun.com/tutorials/disabling-driver-signature-on-windows-8/disabling-signed-driver-enforcement-on-windows-8)
on how to install the unsigned HoodLoader2 drivers.
**If you are using an Arduino Uno/Mega follow the installation instructions of the HoodLoader1 or 2** (no extra hardware needed, just a few cables).
You can grab the latest version + installing instructions of each HoodLoader in its own repository linked above.
Of course the new version [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is recommend and HoodLoader1 API is only for compatibility reasons online.
The old, full HoodLoader1 HID (software)solution (before update 2.0) can be found here: [Outdated HID Project for 1.5.7](https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000)
How to use
==========
### Micro/Leonardo + HoodLoader2
**Edit the USBAPI.h you installed to de/activate usb functions.** By default only Mouse and Keyboard is activated.
The more you activate the more flash is used. For the Uno/Mega you have a limited ram/flash size, so please try not to exceed this limit and only use the needed HID devices.
RawHID is currently not working properly.
**Try the Basic examples for each HID device. They are pretty much self explaining.**
**The HoodLoader2 examples are to show some special cases for the 16u2.** It shows how to remove the USB functions if needed,
how to optimally use ram since its limited and some ported sketches to reprogram the main MCU or for the missing ISP function. Please check them out.
### HoodLoader1
**Try the HoodLoader1 example. It provides the basic Serial protocol API to send HID reports. You have to copy this to every sketch again.**
With HoodLoader1 you can **only use baud 115200 for HID** due to speed/programming reasons.
Use Serial.begin(115200) in every HoodLoader1 sketch.
Its not bad anyway because its the fastest baud and you want fast HID recognition.
You still can **fully use any other baud** for normal sketches but HID wont work.
If you try nevertheless it will output Serial crap to the monitor.
Keep in mind that HoodLoader1 has **no flush function**. If the PC is reading HID too slow it can miss data, like on a Raspberry Pi.
Add a delay to the sending function or just use the newer HoodLoader2.
Always release buttons to not cause any erros. Replug USB cable to reset the values if anything went wrong.
Keep in mind that **with HoodLoader1 the 16u2 is always on**. The 16u2 and its HID reports are not reset if the main MCU is reset.
So you need to reset the HID reports on every startup with a begin() of each used API.
On Windows every USB report will reset when you open the lock screen.
See [deactivate HID function (Hoodloader only)](https://github.com/NicoHood/Hoodloader) how to temporary disable HID again.
For **16u2 as ISP usage** (optional, Hoodloader only, has nothing to do with HID function)
see [Hoodloader repository](https://github.com/NicoHood/Hoodloader).
The sending API is no longer integrated directly in the HID Project since it is now more an extended USB-Core and this has nothing to do with it.
Its more a legacy version to still use HoodLoader1 or to reimplement something similar with HoodLoader2 if you still want full report access for the main MCU.
**The older, full integrated HID Core can be found here.** Keep in mind to remove all newer stuff since it may conflict (a clean arduino core would do it).
It is not better than this solution, maybe easier to use since its just more integrated.
[Outdated HID Project for 1.5.7](https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000)
How it works
============
For the Leonardo/Micro + HoodLoader2 its a modified version of the HID descriptors and USB-Core.
This changes were made to improve the functions, add more devices and add u2 series compatibility.
HoodLoader1 only:
For the Uno/Mega you need a special Bootloader. Why? See [Hoodloader repository](https://github.com/NicoHood/Hoodloader).
To sum it up: Serial information is grabbed by the "man in the middle, 16u2" and you dont have to worry to get any wrong Serial stuff via USB.
Thatswhy you need a special baud (115200) that both sides can communicate with each other.
Every USB command is send via a special [NicoHood Protocol](https://github.com/NicoHood/NicoHoodProtocol)
that's filtered out by the 16u2. If you use Serial0 for extern devices it cannot filter the signal of course.
You can still use the NHP, just dont use the reserved Address 1.
This project wouldnt be possible without
========================================
* [Lufa 140302 from Dean Camera](http://www.fourwalledcubicle.com/LUFA.php)
* [Darran's HID Projects] (https://github.com/harlequin-tech/arduino-usb)
* [Connor's Joystick for the Leonardo](http://www.imaginaryindustries.com/blog/?p=80)
* [Stefan Jones Multimedia Keys Example](http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/)
* [Athanasios Douitsis Multimedia Keys Example](https://github.com/aduitsis/ardumultimedia)
* [The Original Arduino Sources](https://github.com/arduino/Arduino/tree/master/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial)
* [USBlyzer](http://www.usblyzer.com/)
* [Mattairtechs 16u2 Lufa USB Core](https://www.mattairtech.com/index.php/development-boards/mt-db-u1.html)
* [Paul Brook's Minimus 32u2 Arduino USB Core](https://github.com/pbrook/minimus-arduino)
* [Paul Stoffregen's Teensy Core](https://github.com/PaulStoffregen/cores)
* [Keyboard Led Out report by hartmut_holgraefe](http://forum.arduino.cc/index.php?topic=173583.0)
* A lot of searching through the web
* The awesome official Arduino IRC chat!
* [The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol)
* See HoodLoader1&2 repository for more credits/links
**Projects can be found here:**
* [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo)
* [Other projects](http://nicohood.wordpress.com/)
* For donations please contact me on my blog :)
Ideas for the future
====================
* Add more devices (even more?, voice device, flight control?)
* Add Midi (no more free Endpoints, possible on 32u4)
* Add HID rumble support (very hard)
Known Bugs
==========
See [Hoodloader repository](https://github.com/NicoHood/Hoodloader) for Hoodloader related Bugs/Issues.
System Wakeup is currently not working on all versions! Will be fixed soon!
System Shutdown is only working on Windows systems.
RawHID is not working properly, test it at your own risk.
Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)!
Known Issues
============
**If You have weird Problems especially with controllers, let me know.**
Sometimes the problem is just that Windows messes up the PID so you might want to compile the hoodloader with a different PID
or reinstall the drivers. With HoodLoader1 we had a lot of problems especially with linux.
XBMC 13.1 (a Media Center) uses Gamepad input. Its seems to not work and may cause weird errors.
Even with a standard Gamepad I have these errors. Just want to mention it here.
The USB implementation of the Leonardo/Micro is not that good it can cause errors or disconnects with massiv Serial input.
This has nothing to do with this library! For example Adalight dosnt work well for me,
so you better use an Arduino Uno with Hoodloader1 (yes the older one!) for Mediacenter control and Ambilight.
Do not use HID in interrupts because it uses Serial (Hoodloader1 only). Your Arduino can crash!
HoodLoader1 only: If you get a checksum error after uploading please message me and send me the whole project.
Same if your Arduino crashes and dont want to upload sketches anymore (Replug usb fixes this).
These bugs occurred while developing the bootloader and should be fixed. Just in case it happens again I noted it here.
USB can behave weird, so please check your code for errors first. If you cannot find a mistake open a Github issue.
Version History
===============
```
2.0 Release (29.11.2014)
* Added HoodLoader2
* Separated HoodLoader1&2 more
* Added u2 series for USB-Core
* Extended USB core and fixed minor things for the u2 series
* Added Led Out report.
* Added CDC Line state
* Reworked the whole library structure again
1.8 Beta Release (26.08.2014)
* Changes in the Hoodloader:
* **Huge improvements**, see [Hoodloader repository](https://github.com/NicoHood/Hoodloader)
* Reworked the whole library, easy installation now
* HID fixes for Media Keys/Ubuntu
* Removed Joystick, added 4 Gamepads
1.7.3 Beta Release (10.08.2014)
* Changes in the Hoodloader:
* Fixed HID flush bug (1.6 - 1.7.2)
1.7.2 Beta Release (10.08.2014)
* Changes in the Hoodloader:
* Added Lite version for 8u2
* Added Versions that show up as Uno/Mega (not recommended)
* Makefile and structure changes
1.7.1 Beta Release (10.08.2014)
* Changes in the Hoodloader:
* Fixed HID deactivation bug
1.7 Beta Release (10.08.2014)
* Changes in the Hoodloader:
* Works as ISP now. See the [Hoodloader Repository](https://github.com/NicoHood/Hoodloader) for more information.
* Exceeded 8kb limit. For flashing a 8u2 use v1.6 please!
* Changed Readme text
1.6 Beta Release (09.08.2014)
* Bugfixes in the Hoodloader:
* Changed HID management (not blocking that much, faster)
* added RawHID in/out (HID to Serial)
* Added RawHID Class and example
1.5 Beta Release (21.07.2014)
* Moved Hoodloader source to a [separate Github page](https://github.com/NicoHood/Hoodloader)
* Bugfixes in the Hoodloader:
* Firmware is still available here
* Overall a lot of ram improvements, now with a big global union of ram
* Removed USBtoUSART buffer (not needed, saved 128/500 bytes)
* Removed Lite version because of better ram usage not needed
* Separated different modes better to not cause any errors in default mode
* Improved the deactivate option
* Integrated NHP directly
* Replaced LightweightRingbuffer with native Lufa Ringbuffer
* Improved writing to CDC Host
* Fixed a bug in checkNHPProtocol: & needs to be a ==
* General structure changes
* Improved stability
* Fixed Arduino as ISP bug
1.4.1 Beta Release (10.07.2014)
* #define Bugfix in USBAPI.h
1.4 Beta Release (10.07.2014)
* Bugfixes in the Hoodloader:
* Added Lite Version with less ram usage
* Changed PIDs, edited driver file
* merged v1.0.x and v1.5.x together (both are compatible!)
* added IDE v1.5.7 support
* added Tutorials
1.3 Beta Release (01.07.2014)
* Bugfixes in the Hoodloader:
* Improved ram usage (you can get even better but that messes up code and increases flash)
* **Important NHP fix inside the HID Class for Uno/Mega**
1.2 Beta Release (22.06.2014)
* Added 1.0.x/1.5.x support
* Bugfixes in the Hoodloader:
* Sometimes HID Devices weren't updating when using more than 1 Device (set forcewrite to true)
* Fast updates crashed the bootloader (too much ram usage, set CDC buffer from 128b to 100b each)
* Minor file structure changes
1.1 Beta Release (05.06.2014)
* Added Leonardo/Micro support
* Included NicoHoodProtocol
* Minor fixes
1.0 Beta Release (03.06.2014)
```
Licence and Copyright
=====================
If you use this library for any cool project let me know!
```
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
```
For Developers
==============
If you deactivate some reports it can occur that windows will cause problems and recognize it as different device.
While developing I had that much trouble that I had to change the PID. No way to repair the broken windows driver settings.
So be careful if you change the source on your own with important PIDs. (Therefore I made a 2nd Lite Version with a different PID and more ram)
Therefore reinstall the divers for any device or just dont touch the HID reports in the Bootloader.
The Leonardo/Micro version worked fine till now.
See this how to uninstall the drivers:
https://support.microsoft.com/kb/315539
The Hootloader was coded with Windows7 and Visual Studio and compiled with a Raspberry Pi.
Lufa version 140302 is included!
**To recompile see instructions in [Hoodloader Repository](https://github.com/NicoHood/Hoodloader).**
The difference between the Leonardo/Micro and Uno/Mega is that the HID Class is different. All other classes are the same.
The Leonardo/Micro Version uses USBAPI.h and no Serial while the Uno/Mega Version uses Serial.
You can also modify the library to send HID reports to other devices/other serials.
Just modify the HID Class (#define HID_SERIAL Serial).

1078
USBAPI.h

File diff suppressed because it is too large Load diff

View file

@ -1,785 +0,0 @@
/* Copyright (c) 2010, 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.
*/
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "USBAPI.h"
#if defined(USBCON)
#define EP_TYPE_CONTROL 0x00
#define EP_TYPE_BULK_IN 0x81
#define EP_TYPE_BULK_OUT 0x80
#define EP_TYPE_INTERRUPT_IN 0xC1
#define EP_TYPE_INTERRUPT_OUT 0xC0
#define EP_TYPE_ISOCHRONOUS_IN 0x41
#define EP_TYPE_ISOCHRONOUS_OUT 0x40
/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
#define TX_RX_LED_PULSE_MS 100
volatile u8 TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */
volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */
//==================================================================
//==================================================================
extern const u16 STRING_LANGUAGE[] PROGMEM;
extern const u8 STRING_PRODUCT[] PROGMEM;
extern const u8 STRING_MANUFACTURER[] PROGMEM;
extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM;
extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM;
const u16 STRING_LANGUAGE[2] = {
(3 << 8) | (2 + 2),
0x0409 // English
};
#ifndef USB_PRODUCT
// If no product is provided, use USB IO Board
#define USB_PRODUCT "USB IO Board"
#endif
const u8 STRING_PRODUCT[] PROGMEM = USB_PRODUCT;
#if USB_VID == 0x2341
# if defined(USB_MANUFACTURER)
# undef USB_MANUFACTURER
# endif
# define USB_MANUFACTURER "Arduino LLC"
#elif USB_VID == 0x1b4f
# if defined(USB_MANUFACTURER)
# undef USB_MANUFACTURER
# endif
# define USB_MANUFACTURER "SparkFun"
#elif !defined(USB_MANUFACTURER)
// Fall through to unknown if no manufacturer name was provided in a macro
# define USB_MANUFACTURER "Unknown"
#endif
const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER;
#ifdef CDC_ENABLED
#define DEVICE_CLASS 0x02
#else
#define DEVICE_CLASS 0x00
#endif
// edit by NicoHood
// warning from USBlyzer: IAD is used. Should be EFh (Miscellaneous Device Class).
// Lufa also use these values, so i will use them at least for the u2 boards. Someone should fix this for the u4 series if needed.
// You have to use this descriptor if you have CDC AND HID at the same time. Otherwise they are quite different.
#if defined(HID_ENABLED) && (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__))
// DEVICE DESCRIPTOR
const DeviceDescriptor USB_DeviceDescriptor =
D_DEVICE(0xEF, 0x02, 0x01, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1);
#else
// DEVICE DESCRIPTOR
const DeviceDescriptor USB_DeviceDescriptor =
D_DEVICE(0x00, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1);
#endif
const DeviceDescriptor USB_DeviceDescriptorA =
D_DEVICE(DEVICE_CLASS, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1);
//==================================================================
//==================================================================
volatile u8 _usbConfiguration = 0;
static inline void WaitIN(void)
{
while (!(UEINTX & (1 << TXINI)))
;
}
static inline void ClearIN(void)
{
UEINTX = ~(1 << TXINI);
}
static inline void WaitOUT(void)
{
while (!(UEINTX & (1 << RXOUTI)))
;
}
static inline u8 WaitForINOrOUT()
{
while (!(UEINTX & ((1 << TXINI) | (1 << RXOUTI))))
;
return (UEINTX & (1 << RXOUTI)) == 0;
}
static inline void ClearOUT(void)
{
UEINTX = ~(1 << RXOUTI);
}
void Recv(volatile u8* data, u8 count)
{
while (count--)
*data++ = UEDATX;
RXLED1; // light the RX LED
RxLEDPulse = TX_RX_LED_PULSE_MS;
}
static inline u8 Recv8()
{
RXLED1; // light the RX LED
RxLEDPulse = TX_RX_LED_PULSE_MS;
return UEDATX;
}
static inline void Send8(u8 d)
{
UEDATX = d;
}
static inline void SetEP(u8 ep)
{
UENUM = ep;
}
static inline u8 FifoByteCount()
{
return UEBCLX;
}
static inline u8 ReceivedSetupInt()
{
return UEINTX & (1 << RXSTPI);
}
static inline void ClearSetupInt()
{
UEINTX = ~((1 << RXSTPI) | (1 << RXOUTI) | (1 << TXINI));
}
static inline void Stall()
{
UECONX = (1 << STALLRQ) | (1 << EPEN);
}
static inline u8 ReadWriteAllowed()
{
return UEINTX & (1 << RWAL);
}
static inline u8 Stalled()
{
return UEINTX & (1 << STALLEDI);
}
static inline u8 FifoFree()
{
return UEINTX & (1 << FIFOCON);
}
static inline void ReleaseRX()
{
UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
}
static inline void ReleaseTX()
{
UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0
}
static inline u8 FrameNumber()
{
return UDFNUML;
}
//==================================================================
//==================================================================
u8 USBGetConfiguration(void)
{
return _usbConfiguration;
}
#define USB_RECV_TIMEOUT
class LockEP
{
u8 _sreg;
public:
LockEP(u8 ep) : _sreg(SREG)
{
cli();
SetEP(ep & 7);
}
~LockEP()
{
SREG = _sreg;
}
};
// Number of bytes, assumes a rx endpoint
u8 USB_Available(u8 ep)
{
LockEP lock(ep);
return FifoByteCount();
}
// Non Blocking receive
// Return number of bytes read
int USB_Recv(u8 ep, void* d, int len)
{
if (!_usbConfiguration || len < 0)
return -1;
LockEP lock(ep);
u8 n = FifoByteCount();
len = min(n, len);
n = len;
u8* dst = (u8*)d;
while (n--)
*dst++ = Recv8();
if (len && !FifoByteCount()) // release empty buffer
ReleaseRX();
return len;
}
// Recv 1 byte if ready
int USB_Recv(u8 ep)
{
u8 c;
if (USB_Recv(ep, &c, 1) != 1)
return -1;
return c;
}
// Space in send EP
u8 USB_SendSpace(u8 ep)
{
LockEP lock(ep);
if (!ReadWriteAllowed())
return 0;
// edit by NicoHood
return USB_EP_SIZE - FifoByteCount();
}
// Blocking Send of data to an endpoint
int USB_Send(u8 ep, const void* d, int len)
{
if (!_usbConfiguration)
return -1;
int r = len;
const u8* data = (const u8*)d;
u8 timeout = 250; // 250ms timeout on send? TODO
while (len)
{
u8 n = USB_SendSpace(ep);
if (n == 0)
{
if (!(--timeout))
return -1;
delay(1);
continue;
}
if (n > len)
n = len;
{
LockEP lock(ep);
// Frame may have been released by the SOF interrupt handler
if (!ReadWriteAllowed())
continue;
len -= n;
if (ep & TRANSFER_ZERO)
{
while (n--)
Send8(0);
}
else if (ep & TRANSFER_PGM)
{
while (n--)
Send8(pgm_read_byte(data++));
}
else
{
while (n--)
Send8(*data++);
}
if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer
ReleaseTX();
}
}
TXLED1; // light the TX LED
TxLEDPulse = TX_RX_LED_PULSE_MS;
return r;
}
extern const u8 _initEndpoints[] PROGMEM;
const u8 _initEndpoints[] =
{
0,
#ifdef CDC_ENABLED
EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
#endif
#ifdef HID_ENABLED
EP_TYPE_INTERRUPT_IN // HID_ENDPOINT_INT
#endif
};
#define EP_SINGLE_64 0x32 // EP0
#define EP_DOUBLE_64 0x36 // Other endpoints
// edit by NicoHood
#define EP_SINGLE_16 0x12
static
void InitEP(u8 index, u8 type, u8 size)
{
UENUM = index;
UECONX = 1;
UECFG0X = type;
UECFG1X = size;
}
static
void InitEndpoints()
{
for (u8 i = 1; i < sizeof(_initEndpoints); i++)
{
UENUM = i;
UECONX = 1;
UECFG0X = pgm_read_byte(_initEndpoints + i);
// edit by NicoHood
#if USB_EP_SIZE == 16
UECFG1X = EP_SINGLE_16;
#elif USB_EP_SIZE == 64
UECFG1X = EP_DOUBLE_64;
#else
#error Unsupported value for USB_EP_SIZE
#endif
}
UERST = 0x7E; // And reset them
UERST = 0;
}
// Handle CLASS_INTERFACE requests
static
bool ClassInterfaceRequest(Setup& setup)
{
u8 i = setup.wIndex;
#ifdef CDC_ENABLED
if (CDC_ACM_INTERFACE == i)
return CDC_Setup(setup);
#endif
#ifdef HID_ENABLED
if (HID_INTERFACE == i)
return HID_Setup(setup);
#endif
return false;
}
int _cmark;
int _cend;
void InitControl(int end)
{
SetEP(0);
_cmark = 0;
_cend = end;
}
static
bool SendControl(u8 d)
{
if (_cmark < _cend)
{
if (!WaitForINOrOUT())
return false;
Send8(d);
if (!((_cmark + 1) & 0x3F))
ClearIN(); // Fifo is full, release this packet
}
_cmark++;
return true;
};
// Clipped by _cmark/_cend
int USB_SendControl(u8 flags, const void* d, int len)
{
int sent = len;
const u8* data = (const u8*)d;
bool pgm = flags & TRANSFER_PGM;
while (len--)
{
u8 c = pgm ? pgm_read_byte(data++) : *data++;
if (!SendControl(c))
return -1;
}
return sent;
}
// Send a USB descriptor string. The string is stored in PROGMEM as a
// plain ASCII string but is sent out as UTF-16 with the correct 2-byte
// prefix
static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) {
SendControl(2 + string_len * 2);
SendControl(3);
for (u8 i = 0; i < string_len; i++) {
bool r = SendControl(pgm_read_byte(&string_P[i]));
r &= SendControl(0); // high byte
if (!r) {
return false;
}
}
return true;
}
// Does not timeout or cross fifo boundaries
// Will only work for transfers <= 64 bytes
// TODO
int USB_RecvControl(void* d, int len)
{
WaitOUT();
Recv((u8*)d, len);
ClearOUT();
return len;
}
int SendInterfaces()
{
int total = 0;
u8 interfaces = 0;
#ifdef CDC_ENABLED
total = CDC_GetInterface(&interfaces);
#endif
#ifdef HID_ENABLED
total += HID_GetInterface(&interfaces);
#endif
return interfaces;
}
// Construct a dynamic configuration descriptor
// This really needs dynamic endpoint allocation etc
// TODO
static
bool SendConfiguration(int maxlen)
{
// Count and measure interfaces
InitControl(0);
int interfaces = SendInterfaces();
ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor), interfaces);
// Now send them
InitControl(maxlen);
USB_SendControl(0, &config, sizeof(ConfigDescriptor));
SendInterfaces();
return true;
}
u8 _cdcComposite = 0;
static
bool SendDescriptor(Setup& setup)
{
u8 t = setup.wValueH;
if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)
return SendConfiguration(setup.wLength);
InitControl(setup.wLength);
#ifdef HID_ENABLED
if (HID_REPORT_DESCRIPTOR_TYPE == t)
return HID_GetDescriptor(t);
#endif
const u8* desc_addr = 0;
if (USB_DEVICE_DESCRIPTOR_TYPE == t)
{
if (setup.wLength == 8)
_cdcComposite = 1;
desc_addr = _cdcComposite ? (const u8*)&USB_DeviceDescriptorA : (const u8*)&USB_DeviceDescriptor;
}
else if (USB_STRING_DESCRIPTOR_TYPE == t)
{
if (setup.wValueL == 0) {
desc_addr = (const u8*)&STRING_LANGUAGE;
}
else if (setup.wValueL == IPRODUCT) {
return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT));
}
else if (setup.wValueL == IMANUFACTURER) {
return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER));
}
else
return false;
}
if (desc_addr == 0)
return false;
u8 desc_length = pgm_read_byte(desc_addr);
USB_SendControl(TRANSFER_PGM, desc_addr, desc_length);
return true;
}
// Endpoint 0 interrupt
ISR(USB_COM_vect)
{
SetEP(0);
if (!ReceivedSetupInt())
return;
Setup setup;
Recv((u8*)&setup, 8);
ClearSetupInt();
u8 requestType = setup.bmRequestType;
if (requestType & REQUEST_DEVICETOHOST)
WaitIN();
else
ClearIN();
bool ok = true;
if (REQUEST_STANDARD == (requestType & REQUEST_TYPE))
{
// Standard Requests
u8 r = setup.bRequest;
if (GET_STATUS == r)
{
Send8(0); // TODO
Send8(0);
}
else if (CLEAR_FEATURE == r)
{
}
else if (SET_FEATURE == r)
{
}
else if (SET_ADDRESS == r)
{
WaitIN();
UDADDR = setup.wValueL | (1 << ADDEN);
}
else if (GET_DESCRIPTOR == r)
{
ok = SendDescriptor(setup);
}
else if (SET_DESCRIPTOR == r)
{
ok = false;
}
else if (GET_CONFIGURATION == r)
{
Send8(1);
}
else if (SET_CONFIGURATION == r)
{
if (REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT))
{
InitEndpoints();
_usbConfiguration = setup.wValueL;
}
else
ok = false;
}
else if (GET_INTERFACE == r)
{
}
else if (SET_INTERFACE == r)
{
}
}
else
{
InitControl(setup.wLength); // Max length of transfer
ok = ClassInterfaceRequest(setup);
}
if (ok)
ClearIN();
else
{
Stall();
}
}
void USB_Flush(u8 ep)
{
SetEP(ep);
if (FifoByteCount())
ReleaseTX();
}
// General interrupt
ISR(USB_GEN_vect)
{
u8 udint = UDINT;
UDINT = 0;
// End of Reset
if (udint & (1 << EORSTI))
{
InitEP(0, EP_TYPE_CONTROL, EP_SINGLE_64); // init ep0
_usbConfiguration = 0; // not configured yet
UEIENX = 1 << RXSTPE; // Enable interrupts for ep0
}
// Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too
if (udint & (1 << SOFI))
{
#ifdef CDC_ENABLED
USB_Flush(CDC_TX); // Send a tx frame if found
#endif
// check whether the one-shot period has elapsed. if so, turn off the LED
if (TxLEDPulse && !(--TxLEDPulse))
TXLED0;
if (RxLEDPulse && !(--RxLEDPulse))
RXLED0;
}
}
// VBUS or counting frames
// Any frame counting?
u8 USBConnected()
{
u8 f = UDFNUML;
delay(3);
return f != UDFNUML;
}
//=======================================================================
//=======================================================================
USBDevice_ USBDevice;
USBDevice_::USBDevice_()
{
}
// edit by NicoHood
// added from teensy definition by paul stoffregen
#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
#define HW_CONFIG()
#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0)))
#define USB_CONFIG() (USBCON = (1<<USBE))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#elif defined(__AVR_ATmega32U4__)
#define HW_CONFIG() (UHWCON = 0x01)
#define PLL_CONFIG() (PLLCSR = 0x12)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#elif defined(__AVR_AT90USB646__)
#define HW_CONFIG() (UHWCON = 0x81)
#define PLL_CONFIG() (PLLCSR = 0x1A)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#elif defined(__AVR_AT90USB1286__)
#define HW_CONFIG() (UHWCON = 0x81)
#define PLL_CONFIG() (PLLCSR = 0x16)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#endif
void USBDevice_::attach()
{
// edit by NicoHood
_usbConfiguration = 0;
HW_CONFIG(); // power internal reg
// from Paul, TODO needed?
//USBCON = 0; // Reset controller
USB_FREEZE(); // clock frozen, usb enabled
#if F_CPU == 16000000UL
// Need 16 MHz xtal
#ifdef PINDIV
PLLCSR = (1 << PINDIV) | (1 << PLLE);
#else
// added from paul brook, no idea for what board this is used for
PLLCSR = (1 << PLLP0) | (1 << PLLE);
#endif
#elif F_CPU == 8000000UL
// Need 8 MHz xtal
PLLCSR = (1 << PLLE);
#endif
while (!(PLLCSR & (1 << PLOCK))) // wait for lock pll
;
// Some tests on specific versions of macosx (10.7.3), reported some
// strange behaviuors when the board is reset using the serial
// port touch at 1200 bps. This delay fixes this behaviour.
delay(1);
USB_CONFIG(); // start USB clock
UDIEN = (1 << EORSTE) | (1 << SOFE); // Enable interrupts for EOR (End of Reset) and SOF (start of frame)
UDCON = 0; // enable attach resistor
TX_RX_LED_INIT;
}
void USBDevice_::detach()
{
}
// Check for interrupts
// TODO: VBUS detection
bool USBDevice_::configured()
{
return _usbConfiguration;
}
void USBDevice_::poll()
{
}
#endif /* if defined(USBCON) */

307
USBCore.h
View file

@ -1,307 +0,0 @@
// Copyright (c) 2010, 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.
*/
#ifndef __USBCORE_H__
#define __USBCORE_H__
// Standard requests
#define GET_STATUS 0
#define CLEAR_FEATURE 1
#define SET_FEATURE 3
#define SET_ADDRESS 5
#define GET_DESCRIPTOR 6
#define SET_DESCRIPTOR 7
#define GET_CONFIGURATION 8
#define SET_CONFIGURATION 9
#define GET_INTERFACE 10
#define SET_INTERFACE 11
// bmRequestType
#define REQUEST_HOSTTODEVICE 0x00
#define REQUEST_DEVICETOHOST 0x80
#define REQUEST_DIRECTION 0x80
#define REQUEST_STANDARD 0x00
#define REQUEST_CLASS 0x20
#define REQUEST_VENDOR 0x40
#define REQUEST_TYPE 0x60
#define REQUEST_DEVICE 0x00
#define REQUEST_INTERFACE 0x01
#define REQUEST_ENDPOINT 0x02
#define REQUEST_OTHER 0x03
#define REQUEST_RECIPIENT 0x03
#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST + REQUEST_CLASS + REQUEST_INTERFACE)
#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE + REQUEST_CLASS + REQUEST_INTERFACE)
// Class requests
#define CDC_SET_LINE_CODING 0x20
#define CDC_GET_LINE_CODING 0x21
#define CDC_SET_CONTROL_LINE_STATE 0x22
// edit by NicoHood
#define CDC_CONTROL_LINE_OUT_DTR (1 << 0)
#define CDC_CONTROL_LINE_OUT_RTS (1 << 1)
#define MSC_RESET 0xFF
#define MSC_GET_MAX_LUN 0xFE
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
#define HID_GET_PROTOCOL 0x03
#define HID_SET_REPORT 0x09
#define HID_SET_IDLE 0x0A
#define HID_SET_PROTOCOL 0x0B
// Descriptors
#define USB_DEVICE_DESC_SIZE 18
#define USB_CONFIGUARTION_DESC_SIZE 9
#define USB_INTERFACE_DESC_SIZE 9
#define USB_ENDPOINT_DESC_SIZE 7
#define USB_DEVICE_DESCRIPTOR_TYPE 1
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
#define USB_STRING_DESCRIPTOR_TYPE 3
#define USB_INTERFACE_DESCRIPTOR_TYPE 4
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
#define USB_DEVICE_CLASS_STORAGE 0x08
#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
#define USB_CONFIG_POWERED_MASK 0x40
#define USB_CONFIG_BUS_POWERED 0x80
#define USB_CONFIG_SELF_POWERED 0xC0
#define USB_CONFIG_REMOTE_WAKEUP 0x20
// bMaxPower in Configuration Descriptor
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
// bEndpointAddress in Endpoint Descriptor
#define USB_ENDPOINT_DIRECTION_MASK 0x80
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
#define USB_ENDPOINT_TYPE_MASK 0x03
#define USB_ENDPOINT_TYPE_CONTROL 0x00
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
#define USB_ENDPOINT_TYPE_BULK 0x02
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
#define TOBYTES(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
#define CDC_V1_10 0x0110
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02
#define CDC_CALL_MANAGEMENT 0x01
#define CDC_ABSTRACT_CONTROL_MODEL 0x02
#define CDC_HEADER 0x00
#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02
#define CDC_UNION 0x06
#define CDC_CS_INTERFACE 0x24
#define CDC_CS_ENDPOINT 0x25
#define CDC_DATA_INTERFACE_CLASS 0x0A
#define MSC_SUBCLASS_SCSI 0x06
#define MSC_PROTOCOL_BULK_ONLY 0x50
#define HID_HID_DESCRIPTOR_TYPE 0x21
#define HID_REPORT_DESCRIPTOR_TYPE 0x22
#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23
// Device
typedef struct {
u8 len; // 18
u8 dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE
u16 usbVersion; // 0x200
u8 deviceClass;
u8 deviceSubClass;
u8 deviceProtocol;
u8 packetSize0; // Packet 0
u16 idVendor;
u16 idProduct;
u16 deviceVersion; // 0x100
u8 iManufacturer;
u8 iProduct;
u8 iSerialNumber;
u8 bNumConfigurations;
} DeviceDescriptor;
// Config
typedef struct {
u8 len; // 9
u8 dtype; // 2
u16 clen; // total length
u8 numInterfaces;
u8 config;
u8 iconfig;
u8 attributes;
u8 maxPower;
} ConfigDescriptor;
// String
// Interface
typedef struct
{
u8 len; // 9
u8 dtype; // 4
u8 number;
u8 alternate;
u8 numEndpoints;
u8 interfaceClass;
u8 interfaceSubClass;
u8 protocol;
u8 iInterface;
} InterfaceDescriptor;
// Endpoint
typedef struct
{
u8 len; // 7
u8 dtype; // 5
u8 addr;
u8 attr;
u16 packetSize;
u8 interval;
} EndpointDescriptor;
// Interface Association Descriptor
// Used to bind 2 interfaces together in CDC compostite device
typedef struct
{
u8 len; // 8
u8 dtype; // 11
u8 firstInterface;
u8 interfaceCount;
u8 functionClass;
u8 funtionSubClass;
u8 functionProtocol;
u8 iInterface;
} IADDescriptor;
// CDC CS interface descriptor
typedef struct
{
u8 len; // 5
u8 dtype; // 0x24
u8 subtype;
u8 d0;
u8 d1;
} CDCCSInterfaceDescriptor;
typedef struct
{
u8 len; // 4
u8 dtype; // 0x24
u8 subtype;
u8 d0;
} CDCCSInterfaceDescriptor4;
typedef struct
{
u8 len;
u8 dtype; // 0x24
u8 subtype; // 1
u8 bmCapabilities;
u8 bDataInterface;
} CMFunctionalDescriptor;
typedef struct
{
u8 len;
u8 dtype; // 0x24
u8 subtype; // 1
u8 bmCapabilities;
} ACMFunctionalDescriptor;
typedef struct
{
// IAD
IADDescriptor iad; // Only needed on compound device
// Control
InterfaceDescriptor cif; //
CDCCSInterfaceDescriptor header;
CMFunctionalDescriptor callManagement; // Call Management
ACMFunctionalDescriptor controlManagement; // ACM
CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION
EndpointDescriptor cifin;
// Data
InterfaceDescriptor dif;
EndpointDescriptor in;
EndpointDescriptor out;
} CDCDescriptor;
typedef struct
{
InterfaceDescriptor msc;
EndpointDescriptor in;
EndpointDescriptor out;
} MSCDescriptor;
typedef struct
{
u8 len; // 9
u8 dtype; // 0x21
u8 addr;
u8 versionL; // 0x101
u8 versionH; // 0x101
u8 country;
u8 desctype; // 0x22 report
u8 descLenL;
u8 descLenH;
} HIDDescDescriptor;
typedef struct
{
InterfaceDescriptor hid;
HIDDescDescriptor desc;
EndpointDescriptor in;
} HIDDescriptor;
#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \
{ 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs }
#define D_CONFIG(_totalLength,_interfaces) \
{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(500) }
#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \
{ 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 }
#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \
{ 7, 5, _addr,_attr,_packetSize, _interval }
#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \
{ 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 }
#define D_HIDREPORT(_descriptorLength) \
{ 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 }
#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 }
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
#endif

View file

@ -1,90 +0,0 @@
/* 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.
*/
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#define CDC_ENABLED
#define HID_ENABLED
#ifdef CDC_ENABLED
#define CDC_INTERFACE_COUNT 2
#define CDC_ENPOINT_COUNT 3
#else
#define CDC_INTERFACE_COUNT 0
#define CDC_ENPOINT_COUNT 0
#endif
#ifdef HID_ENABLED
#define HID_INTERFACE_COUNT 1
#define HID_ENPOINT_COUNT 1
#else
#define HID_INTERFACE_COUNT 0
#define HID_ENPOINT_COUNT 0
#endif
#define CDC_ACM_INTERFACE 0 // CDC ACM
#define CDC_DATA_INTERFACE 1 // CDC Data
#define CDC_FIRST_ENDPOINT 1
#define CDC_ENDPOINT_ACM (CDC_FIRST_ENDPOINT) // CDC First
#define CDC_ENDPOINT_OUT (CDC_FIRST_ENDPOINT+1)
#define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT+2)
#define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface
#define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT)
#define HID_ENDPOINT_INT (HID_FIRST_ENDPOINT)
#define INTERFACE_COUNT (MSC_INTERFACE + MSC_INTERFACE_COUNT)
#ifdef CDC_ENABLED
#define CDC_RX CDC_ENDPOINT_OUT
#define CDC_TX CDC_ENDPOINT_IN
#endif
#ifdef HID_ENABLED
#define HID_TX HID_ENDPOINT_INT
#endif
// edit by NicoHood
#ifndef USB_EP_SIZE
#define USB_EP_SIZE 64
#endif
#define IMANUFACTURER 1
#define IPRODUCT 2

View file

@ -1,53 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Advanced Gamepad example
*/
// include HID library
#include <HID.h>
// see HID_Reports.h for all data structures
HID_GamepadReport_Data_t Gamepadreport;
const int pinLed = LED_BUILTIN;
const int pinButton = 2;
// see HID_Reports.h for all data structures
HID_GamepadReport_Data_t Gamepadreport;
void setup() {
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// Sends a clean report to the host. This is important on any Arduino type.
// Make sure all desired USB functions are activated in USBAPI.h!
memset(&Gamepadreport, 0, sizeof(Gamepadreport));
HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport));
}
void loop() {
if (!digitalRead(pinButton)) {
digitalWrite(pinLed, HIGH);
// This demo is actually made for advanced users to show them how they can write an own report.
// This might be useful for a Gamepad if you want to edit the values direct on your own.
// count with buttons binary
static uint32_t count = 0;
Gamepadreport.whole32[0] = count++;
// move x/y Axis to a new position (16bit)
Gamepadreport.whole16[2] = (random(0xFFFF));
// functions before only set the values
// this writes the report to the host
HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport));
// simple debounce
delay(300);
digitalWrite(pinLed, LOW);
}
}

View file

@ -1,98 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Advanced Keyboard example
This demo is actually made for advanced users to show them how they can write an own report.
This might be useful for a Keyboard if you only use one key,
because the library has a lot of code for simple use
*/
const int pinLed = LED_BUILTIN;
const int pinButton = 2;
void setup() {
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// Sends a clean report to the host. This is important on any Arduino type.
// Make sure all desired USB functions are activated in USBAPI.h!
pressRawKeyboard(0, 0);
}
void loop() {
if (!digitalRead(pinButton)) {
digitalWrite(pinLed, HIGH);
// press normal keys (a-z, A-Z, 0-9)
pressRawKeyboard(0, RAW_KEYBOARD_KEY('a')); //modifiers + a
pressRawKeyboard(0, RAW_KEYBOARD_KEY('Z')); //modifiers + Z
// press STRG + ALT + DEL on keyboard (see usb documentation for more)
//pressRawKeyboard(RAW_KEYBOARD_LEFT_CTRL | RAW_KEYBOARD_LEFT_ALT , RAW_KEYBOARD_DELETE); //modifiers + key
// release! Important
pressRawKeyboard(0, 0);
// simple debounce
delay(300);
digitalWrite(pinLed, LOW);
}
}
void pressRawKeyboard(uint8_t modifiers, uint8_t key) {
uint8_t keys[8] = {
modifiers, 0, key, 0, 0, 0, 0, 0
}; //modifiers, reserved, key[0]
HID_SendReport(HID_REPORTID_KeyboardReport, keys, sizeof(keys));
}
/*
See Hut1_12v2.pdf Chapter 10 (Page 53) for more Keys
(especially a-z, a=0x04 z=29)
Definitions:
RAW_KEYBOARD_LEFT_CTRL
RAW_KEYBOARD_LEFT_SHIFT
RAW_KEYBOARD_LEFT_ALT
RAW_KEYBOARD_LEFT_GUI
RAW_KEYBOARD_RIGHT_CTRL
RAW_KEYBOARD_RIGHT_SHIFT
RAW_KEYBOARD_RIGHT_ALT
RAW_KEYBOARD_RIGHT_GUI
RAW_KEYBOARD_KEY(key)
RAW_KEYBOARD_UP_ARROW
RAW_KEYBOARD_DOWN_ARROW
RAW_KEYBOARD_LEFT_ARROW
RAW_KEYBOARD_RIGHT_ARROW
RAW_KEYBOARD_SPACEBAR
RAW_KEYBOARD_BACKSPACE
RAW_KEYBOARD_TAB
RAW_KEYBOARD_RETURN
RAW_KEYBOARD_ESC
RAW_KEYBOARD_INSERT
RAW_KEYBOARD_DELETE
RAW_KEYBOARD_PAGE_UP
RAW_KEYBOARD_PAGE_DOWN
RAW_KEYBOARD_HOME
RAW_KEYBOARD_END
RAW_KEYBOARD_CAPS_LOCK
RAW_KEYBOARD_F1
RAW_KEYBOARD_F2
RAW_KEYBOARD_F3
RAW_KEYBOARD_F4
RAW_KEYBOARD_F5
RAW_KEYBOARD_F6
RAW_KEYBOARD_F7
RAW_KEYBOARD_F8
RAW_KEYBOARD_F9
RAW_KEYBOARD_F10
RAW_KEYBOARD_F11
RAW_KEYBOARD_F12
RAW_KEYBOARD_PRINT
RAW_KEYBOARD_SCROLL_LOCK
RAW_KEYBOARD_PAUSE
*/

View file

@ -1,109 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Advanced RawHID example
Shows how to send bytes via raw HID
Press a button to send some example values.
Keep in mind that you can only send full data packets, the rest is filled with zero!
Definitions from HID_Reports.h:
RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF
RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF
RAWHID_TX_SIZE 15 // 1 byte for report ID
RAWHID_RX_SIZE 15 // 1 byte for report ID
*/
const int pinLed = LED_BUILTIN;
const int pinButton = 2;
void setup() {
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// no begin function needed for RawHID
// Make sure all desired USB functions are activated in USBAPI.h!
}
void loop() {
if (!digitalRead(pinButton)) {
digitalWrite(pinLed, HIGH);
// direct without library. Always send RAWHID_RX_SIZE bytes!
uint8_t buff[RAWHID_RX_SIZE]; // unitialized, has random values
HID_SendReport(HID_REPORTID_RawKeyboardReport, buff, sizeof(buff));
// with library
memset(&buff, 42, sizeof(buff));
RawHID.write(buff, sizeof(buff));
// write a single byte, will fill the rest with zeros
RawHID.write(0xCD);
// huge buffer with library, will fill the rest with zeros
uint8_t megabuff[64];
for (int i = 0; i < sizeof(megabuff); i++)
megabuff[i] = i;
RawHID.write(megabuff, sizeof(megabuff));
// You can use print too, but better dont use a linefeed
RawHID.println("Hello World");
// And compare it to write:
RawHID.write("Hello World\r\n");
// simple debounce
delay(300);
digitalWrite(pinLed, LOW);
}
}
/*
Expected output:
// manual with unintialized buff
recv 15 bytes:
01 55 C1 FF 01 01 01 00 00 01 00 00 01 00 20
// filled buff
recv 15 bytes:
2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A
// single byte filled with zero
recv 15 bytes:
CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// huge buffer filled with zero at the end
recv 15 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E
recv 15 bytes:
0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D
recv 15 bytes:
1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C
recv 15 bytes:
2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B
recv 15 bytes:
3C 3D 3E 3F 00 00 00 00 00 00 00 00 00 00 00
// print
recv 15 bytes:
48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00
//\r
recv 15 bytes:
0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00
//\n
recv 15 bytes:
0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00
//write
recv 15 bytes:
48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00
*/

View file

@ -1,87 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Gamepad example
Press a button and demonstrate Gamepad actions
*/
const int pinLed = LED_BUILTIN;
const int pinButton = 2;
void setup() {
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// Sends a clean report to the host. This is important on any Arduino type.
// Make sure all desired USB functions are activated in USBAPI.h!
Gamepad.begin();
}
void loop() {
if (!digitalRead(pinButton)) {
digitalWrite(pinLed, HIGH);
// press button 1-32 and reset (34 becaue its written later)
static uint8_t count = 1;
Gamepad.press(count++);
if (count == 34) {
Gamepad.releaseAll();
count = 1;
}
// move x/y Axis to a new position (16bit)
Gamepad.xAxis(random(0xFFFF));
Gamepad.yAxis(random(0xFFFF));
// go through all dPad positions
// values: 0-8 (0==centred)
static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED;
Gamepad.dPad1(dpad1++);
if(dpad1>GAMEPAD_DPAD_UP_LEFT) dpad1 = GAMEPAD_DPAD_CENTERED;
static int8_t dpad2 = GAMEPAD_DPAD_CENTERED;
Gamepad.dPad2(dpad2--);
if(dpad2<GAMEPAD_DPAD_CENTERED) dpad2 = GAMEPAD_DPAD_UP_LEFT;
// functions before only set the values
// this writes the report to the host
Gamepad.write();
// simple debounce
delay(300);
digitalWrite(pinLed, LOW);
}
}
/*
Prototypes:
void begin(void);
void end(void);
void write(void);
void press(uint8_t b);
void release(uint8_t b);
void releaseAll(void);
void buttons(uint32_t b);
void xAxis(int16_t a);
void yAxis(int16_t a);
void rxAxis(int16_t a);
void ryAxis(int16_t a);
void zAxis(int8_t a);
void rzAxis(int8_t a);
void dPad1(int8_t d);
void dPad2(int8_t d);
Definitions:
GAMEPAD_DPAD_CENTERED 0
GAMEPAD_DPAD_UP 1
GAMEPAD_DPAD_UP_RIGHT 2
GAMEPAD_DPAD_RIGHT 3
GAMEPAD_DPAD_DOWN_RIGHT 4
GAMEPAD_DPAD_DOWN 5
GAMEPAD_DPAD_DOWN_LEFT 6
GAMEPAD_DPAD_LEFT 7
GAMEPAD_DPAD_UP_LEFT 8
*/

View file

@ -1,84 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Keyboard example
Press a button to write some text to your pc.
See official documentation for more infos
*/
const int pinLed = LED_BUILTIN;
const int pinButton = 2;
void setup() {
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// Starts Serial debug output
Serial.begin(115200);
// Sends a clean report to the host. This is important on any Arduino type.
// Make sure all desired USB functions are activated in USBAPI.h!
Keyboard.begin();
}
void loop() {
if (!digitalRead(pinButton)) {
digitalWrite(pinLed, HIGH);
// Same use as the official library, pretty much self explaining
Keyboard.println("This message was sent with my Arduino.");
Serial.println("Serial port is still working and not glitching out");
// simple debounce
delay(300);
digitalWrite(pinLed, LOW);
}
}
/*
Definitions:
KEY_LEFT_CTRL
KEY_LEFT_SHIFT
KEY_LEFT_ALT
KEY_LEFT_GUI
KEY_RIGHT_CTRL
KEY_RIGHT_SHIFT
KEY_RIGHT_ALT
KEY_RIGHT_GUI
KEY_UP_ARROW
KEY_DOWN_ARROW
KEY_LEFT_ARROW
KEY_RIGHT_ARROW
KEY_BACKSPACE
KEY_TAB
KEY_RETURN
KEY_ESC
KEY_INSERT
KEY_DELETE
KEY_PAGE_UP
KEY_PAGE_DOWN
KEY_HOME
KEY_END
KEY_CAPS_LOCK
KEY_F1
KEY_F2
KEY_F3
KEY_F4
KEY_F5
KEY_F6
KEY_F7
KEY_F8
KEY_F9
KEY_F10
KEY_F11
KEY_F12
KEY_PRINT
KEY_SCROLL_LOCK
KEY_PAUSE
*/

View file

@ -1,58 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Media example
Press a button to play/pause music player
*/
const int pinLed = LED_BUILTIN;
const int pinButton = 2;
void setup() {
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// Sends a clean report to the host. This is important on any Arduino type.
// Make sure all desired USB functions are activated in USBAPI.h!
Media.begin();
}
void loop() {
if (!digitalRead(pinButton)) {
digitalWrite(pinLed, HIGH);
// See list below for more definitions or the official usb documentation
Media.write(MEDIA_PLAY_PAUSE);
// simple debounce
delay(300);
digitalWrite(pinLed, LOW);
}
}
/*
Definitions:
MEDIA_FAST_FORWARD
MEDIA_REWIND
MEDIA_NEXT
MEDIA_PREVIOUS
MEDIA_STOP
MEDIA_PLAY_PAUSE
MEDIA_VOLUME_MUTE
MEDIA_VOLUME_UP
MEDIA_VOLUME_DOWN
MEDIA_EMAIL_READER
MEDIA_CALCULATOR
MEDIA_EXPLORER
MEDIA_BROWSER_HOME
MEDIA_BROWSER_BACK
MEDIA_BROWSER_FORWARD
MEDIA_BROWSER_REFRESH
MEDIA_BROWSER_BOOKMARKS
*/

View file

@ -1,47 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Mouse example
Press a button to click with mouse. See official documentation for more infos
*/
const int pinLed = LED_BUILTIN;
const int pinButton = 2;
void setup() {
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// Starts Serial debug output
Serial.begin(115200);
// Sends a clean report to the host. This is important on any Arduino type.
// Make sure all desired USB functions are activated in USBAPI.h!
Mouse.begin();
}
void loop() {
if (!digitalRead(pinButton)) {
digitalWrite(pinLed, HIGH);
// Same use as the official library, pretty much self explaining
Mouse.click();
Serial.println("Serial port is still working and not glitching out");
// simple debounce
delay(300);
digitalWrite(pinLed, LOW);
}
}
/*
Definitions:
MOUSE_LEFT
MOUSE_RIGHT
MOUSE_MIDDLE
MOUSE_PREV
MOUSE_NEXT
*/

View file

@ -1,41 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
System example
Press a button to put pc into standby mode
*/
const int pinLed = LED_BUILTIN;
const int pinButton = 2;
void setup() {
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// Sends a clean report to the host. This is important on any Arduino type.
// Make sure all desired USB functions are activated in USBAPI.h!
System.begin();
}
void loop() {
if (!digitalRead(pinButton)) {
digitalWrite(pinLed, HIGH);
// See list below for more definitions or the official usb documentation
System.write(SYSTEM_SLEEP);
// simple debounce
delay(300);
digitalWrite(pinLed, LOW);
}
}
/*
Definitions:
SYSTEM_POWER_DOWN
SYSTEM_SLEEP
SYSTEM_WAKE_UP
*/

View file

@ -1,163 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Keyboard HoodLoader1 API Legacy example
Legacy Example on how to access the Serial HID API of HoodLoader1.
This methode is outdated, because you can now control the whole
16u2 with HoodLoader2. It might be still usefull if you want the 328/2560
keep control of the USB functions. Keep in mind that there is no such thing
as flushing HID reports. If the USB Host is too slow HID reports might be missed.
You can also adapt the sending method below to send Mouse/Keyboard/Media/System reports.
Gamepads/RawHID have a general problem with the original HoodLoader1 firmware, so please avoid this.
It might be compatible with the new HoodLoader2 port of the protocol later on.
HID reports are converted into a special Serial Protocol with NHP.
This sketch should only be used with a 328/2560, not a 16u2.
The 16u2 has a HoodLoader1 compatible sketch/firmware loaded and will
listen to the Serial Port for these Protocol packets on baud 115200.
The HID_SendReport function is implemented weak, so we can overwrite it
in this sketch below. A simple NHP implementation encapsulated the HID reports
into NHP packets with correct addresses and checksums.
Press a button to write some text to your pc.
See official documentation for more infos
*/
// Serial to write Protocol data to. Default: Serial
#define HID_SERIAL Serial
#define SERIAL_HID_BAUD 115200
// extra delay for raspberry. Only needed for Hoodloader and slow devices
//#define HID_EXTRADELAY 20
const int pinLed = 13;
const int pinButton = 8;
void setup() {
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// Starts Serial at baud 115200 otherwise HID wont work with HoodLoader1.
// This is not needed for Leonado/(Pro)Micro/16u2(HoodLoader2)
Serial.begin(SERIAL_HID_BAUD);
// Sends a clean report to the host. This is important on any Arduino type.
// Make sure all desired USB functions are activated in USBAPI.h!
Keyboard.begin();
}
void loop() {
if (!digitalRead(pinButton)) {
digitalWrite(pinLed, HIGH);
// Same use as the official library, pretty much self explaining
Keyboard.println("This message was sent with my Arduino.");
Serial.println("Serial port is still working and not glitching out");
// simple debounce
delay(300);
digitalWrite(pinLed, LOW);
}
}
//================================================================================
// HoodLoader1 compatible NHP sending API
//================================================================================
// Start Mask
#define NHP_MASK_START 0xC0 //B11|000000 the two MSB bits
#define NHP_MASK_LEAD 0xC0 //B11|000000
#define NHP_MASK_DATA 0x00 //B0|0000000 only the first MSB is important
#define NHP_MASK_END 0x80 //B10|000000
// Content Mask
#define NHP_MASK_LENGTH 0x38 //B00|111|000
#define NHP_MASK_COMMAND 0x0F //B0000|1111
#define NHP_MASK_DATA_7BIT 0x7F //B0|1111111
#define NHP_MASK_DATA_4BIT 0x0F //B0000|1111
#define NHP_MASK_DATA_3BIT 0x07 //B00000|111
#define NHP_MASK_ADDRESS 0x3F //B00|111111
// Reserved Addresses
#define NHP_ADDRESS_CONTROL 0x01
// Reserved Usages
#define NHP_USAGE_ARDUINOHID 0x01
// overwrites the HID_SendReport function which is empty/not used on a 328/2560
void HID_SendReport(uint8_t id, const void* data, int len)
{
// write the Report via Protocol and checksum. 16bit for each sending
// send control address
NHPwriteChecksum(NHP_ADDRESS_CONTROL, (NHP_USAGE_ARDUINOHID << 8) | id);
const uint8_t* report = (const uint8_t*)data;
for (int i = 0; i < len; i++) {
uint8_t data0 = report[i++];
uint8_t data1 = 0;
if (i != len)
data1 = report[i];
// valid HID reports start at Address 2
NHPwriteChecksum(2 + i / 2, (data1 << 8) | data0);
}
#ifdef HID_EXTRADELAY
delay(HID_EXTRADELAY);
#endif
}
// simple copy/modification of the NicoHoodProtocol writechecksum function
void NHPwriteChecksum(uint8_t address, uint16_t indata) {
// writes two bytes with its inverse
uint32_t temp = ~indata;
uint32_t data = (temp << 16) | indata;
// buffer for write operation
uint8_t writebuffer[6];
// start with the maximum size of blocks
uint8_t blocks = 7;
// check for the first 7 bit block that doesnt fit into the first 3 bits
while (blocks > 2) {
uint8_t nextvalue = (data >> (7 * (blocks - 3)));
if (nextvalue > NHP_MASK_DATA_3BIT) {
// special case for the MSB
if (blocks == 7) {
writebuffer[0] = nextvalue;
blocks--;
}
// this block is too big, write this into the next data block
break;
}
else {
// write the possible first 3 bits and check again after if zero
writebuffer[0] = nextvalue;
blocks--;
// we have our first bits, stop (nonzero)
if (nextvalue)
break;
}
}
// write the rest of the data bits
uint8_t datablocks = blocks - 2;
while (datablocks > 0) {
writebuffer[datablocks] = data & NHP_MASK_DATA_7BIT;
data >>= 7;
datablocks--;
}
// write lead + length mask
writebuffer[0] |= NHP_MASK_LEAD | (blocks << 3);
// write end mask
writebuffer[blocks - 1] = NHP_MASK_END | ((address - 1) & NHP_MASK_ADDRESS);
// write the buffer
HID_SERIAL.write(writebuffer, blocks);
}

View file

@ -1,38 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
HoodLoader2 NoUSB Blink example
This sketch demonstrates how to use HoodLoader2 without USB Core.
This might be useful to keep ram/flash usage at a very low level.
Select Tools->USB Core->No USB functions to get rid of the USB Core.
Blinks Leds and shows what workaround is needed to get the timing correct.
You can still use the normal digitalWrite(LED_BUILTIN_TX, LOW); for updating Leds.
Keep in mind that the logic is inverted then! LOW=HIGH and vice versa.
*/
#ifndef USBCON
// workaround for undefined USBCON has to be placed in every sketch
// otherwise the timings wont work correctly
ISR(USB_GEN_vect)
{
UDINT = 0;
}
#endif
void setup() {
TX_RX_LED_INIT;
}
void loop() {
TXLED0;
delay(100);
TXLED1;
delay(100);
RXLED0;
delay(100);
RXLED1;
delay(100);
}

View file

@ -1,39 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
PWM Fade
This example shows how to fade an LED on pin 7
using the analogWrite() function.
Basically it is a demonstartion that PWM on pin 7 works fine.
You can also deactivate the USB Core for this example, but then you'd
need the workaround. See the other example for this.
*/
int led = 7; // the pin that the LED is attached to
int brightness = 0; // how bright the LED is
int fadeAmount = 5; // how many points to fade the LED by
// the setup routine runs once when you press reset:
void setup() {
// declare pin 9 to be an output:
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
// set the brightness of pin 9:
analogWrite(led, brightness);
// change the brightness for next time through the loop:
brightness = brightness + fadeAmount;
// reverse the direction of the fading at the ends of the fade:
if (brightness == 0 || brightness == 255) {
fadeAmount = -fadeAmount ;
}
// wait for 30 milliseconds to see the dimming effect
delay(30);
}

View file

@ -1,54 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
HoodLoader2 SerialKeyboard example
This sketch should demonstrate how to program a basic sketch with HoodLoader2.
It was used to demonstrate that Serial and HID is working properly.
The the other examples on how to use the other APIs, it works the same.
Use the F() macro to save strings in PROGMEM to keep ram usage low.
The 16u2 has very low RAM, so don't try to use that much ram.
Open the Serial port, type in anything and see that Serial and Keyboard is working.
See official documentation for more infos.
*/
void setup() {
// start + wait for serial debug in/output
while (!Serial);
Serial.begin(115200);
Serial.println(F("Startup"));
// Sends a clean report to the host. This is important because
// the 16u2 of the Uno/Mega is not turned off while programming
// so you want to start with a clean report to avoid strange bugs after reset.
Keyboard.begin();
}
void loop() {
if (Serial.available()) {
// discard all Serial bytes to avoid multiple sendings
unsigned long currentMillis = millis();
while (millis() - currentMillis < 100) {
if (Serial.available())
Serial.write(Serial.read());
}
// print an information back to the serial port
Serial.println();
Serial.println(F("Serial port working. Printing Text in 3 seconds."));
// wait 3 seconds and discard all new in bytes to not crash the Arduino
currentMillis = millis();
while (millis() - currentMillis < 3000) {
if (Serial.available())
Serial.write(Serial.read());
}
// same use as the official library, pretty much self explaining
Keyboard.print(F("This message was sent with my Arduino."));
}
}

View file

@ -1,51 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
HoodLoader2 USB-Serial
Transferes from USB to HW Serial and vice versa.
It also resets the main MCU on a DTR rise.
*/
void setup() {
// set main MCU by default active
pinMode(MAIN_MCU_RESET_PIN, OUTPUT);
digitalWrite(MAIN_MCU_RESET_PIN, HIGH);
// Start USB and HW Serial
Serial.begin(115200);
Serial1.begin(115200);
}
void loop() {
// USB -> Serial
for (int i = 0; i < USB_EP_SIZE; i++) {
// read maximum one EP_SIZE to not block
if (Serial.available())
Serial1.write(Serial.read());
else break;
}
// Serial -> USB
if (Serial1.available()) {
Serial.flush();
// send maximum one EP_SIZE to give the usb some time to flush the buffer
uint8_t buff[USB_EP_SIZE-1];
int i = 0;
for (i = 0; i < USB_EP_SIZE-1; i++) {
if (Serial1.available())
buff[i] = Serial1.read();
else break;
}
Serial.write(buff, i);
}
// reset the main mcu if DTR goes HIGH
static bool lastDTR = 0;
bool newDTR = (Serial.lineState()&CDC_CONTROL_LINE_OUT_DTR) ? 1 : 0;
if (lastDTR ^ newDTR)
digitalWrite(MAIN_MCU_RESET_PIN, lastDTR);
lastDTR = newDTR;
}

View file

@ -1,110 +0,0 @@
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Gamepad example project
Press physical buttons to press USB Gamepad buttons.
This can be used for a simple SNES Controller.
*/
// pin mappings
const int pinButton1 = 2;
const int pinButton2 = 3;
const int pinButton3 = 4;
const int pinButton4 = 5;
const int pinButton5 = 6;
const int pinButton6 = 7;
const int pinButton7 = 8;
const int pinButton8 = 9;
const int pinButton9 = 10;
const int pinButton10 = 18;
const int pinButton11 = 19;
const int pinButton12 = 20;
void setup() {
// pinsetup
pinMode(pinButton1, INPUT_PULLUP);
pinMode(pinButton2, INPUT_PULLUP);
pinMode(pinButton3, INPUT_PULLUP);
pinMode(pinButton4, INPUT_PULLUP);
pinMode(pinButton5, INPUT_PULLUP);
pinMode(pinButton6, INPUT_PULLUP);
pinMode(pinButton7, INPUT_PULLUP);
pinMode(pinButton8, INPUT_PULLUP);
pinMode(pinButton9, INPUT_PULLUP);
pinMode(pinButton10, INPUT_PULLUP);
pinMode(pinButton11, INPUT_PULLUP);
pinMode(pinButton12, INPUT_PULLUP);
// Sends a clean report to the host. This is important on any Arduino type.
// Make sure all desired USB functions are activated in USBAPI.h!
Gamepad.begin();
}
void loop() {
// check each button and press Gamepad if needed
if (!digitalRead(pinButton1))
Gamepad.press(1);
else
Gamepad.release(1);
if (!digitalRead(pinButton2))
Gamepad.press(2);
else
Gamepad.release(2);
if (!digitalRead(pinButton3))
Gamepad.press(3);
else
Gamepad.release(3);
if (!digitalRead(pinButton4))
Gamepad.press(4);
else
Gamepad.release(4);
if (!digitalRead(pinButton5))
Gamepad.press(5);
else
Gamepad.release(5);
if (!digitalRead(pinButton6))
Gamepad.press(6);
else
Gamepad.release(6);
if (!digitalRead(pinButton7))
Gamepad.press(7);
else
Gamepad.release(7);
if (!digitalRead(pinButton8))
Gamepad.press(8);
else
Gamepad.release(8);
if (!digitalRead(pinButton9))
Gamepad.press(9);
else
Gamepad.release(9);
if (!digitalRead(pinButton10))
Gamepad.press(10);
else
Gamepad.release(10);
if (!digitalRead(pinButton11))
Gamepad.press(11);
else
Gamepad.release(11);
if (!digitalRead(pinButton12))
Gamepad.press(12);
else
Gamepad.release(12);
// write the information to the host now!
Gamepad.write();
}

View file

@ -1,4 +0,0 @@
Examples
========
Just try these examples once the HID Source is installed. Its pretty much self explaining.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

View file

@ -1,201 +0,0 @@
#######################################
# Syntax Coloring Map For HID
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
end KEYWORD2
click KEYWORD2
move KEYWORD2
write KEYWORD2
press KEYWORD2
isPressed KEYWORD2
releaseAll KEYWORD2
buttons KEYWORD2
xAxis KEYWORD2
yAxis KEYWORD2
zAxis KEYWORD2
rxAxis KEYWORD2
ryAxis KEYWORD2
rzAxis KEYWORD2
dPad1 KEYWORD2
dPad2 KEYWORD2
HID_SendReport KEYWORD2
#######################################
# Classes (KEYWORD3)
#######################################
Mouse KEYWORD3
Keyboard KEYWORD3
RawHID KEYWORD3
Media KEYWORD3
System KEYWORD3
Gamepad KEYWORD3
#######################################
# Instances (KEYWORD2)
#######################################
#######################################
# Constants (LITERAL1)
#######################################
#CDC
CDC_CONTROL_LINE_OUT_DTR LITERAL1
CDC_CONTROL_LINE_OUT_TRS LITERAL1
#Mouse
MOUSE_LEFT LITERAL1
MOUSE_RIGHT LITERAL1
MOUSE_MIDDLE LITERAL1
MOUSE_PREV LITERAL1
MOUSE_NEXT LITERAL1
#Keyboard
LED_NUM_LOCK LITERAL1
LED_CAPS_LOCK LITERAL1
LED_SCROLL_LOCK LITERAL1
KEY_LEFT_CTRL LITERAL1
KEY_LEFT_SHIFT LITERAL1
KEY_LEFT_ALT LITERAL1
KEY_LEFT_GUI LITERAL1
KEY_LEFT_WINDOWS LITERAL1
KEY_RIGHT_CTRL LITERAL1
KEY_RIGHT_SHIFT LITERAL1
KEY_RIGHT_ALT LITERAL1
KEY_RIGHT_GUI LITERAL1
KEY_RIGHT_WINDOWS LITERAL1
KEY_UP_ARROW LITERAL1
KEY_DOWN_ARROW LITERAL1
KEY_LEFT_ARROW LITERAL1
KEY_RIGHT_ARROW LITERAL1
KEY_BACKSPACE LITERAL1
KEY_TAB LITERAL1
KEY_RETURN LITERAL1
KEY_ENTER LITERAL1
KEY_ESC LITERAL1
KEY_INSERT LITERAL1
KEY_DELETE LITERAL1
KEY_PAGE_UP LITERAL1
KEY_PAGE_DOWN LITERAL1
KEY_HOME LITERAL1
KEY_END LITERAL1
KEY_CAPS_LOCK LITERAL1
KEY_F1 LITERAL1
KEY_F2 LITERAL1
KEY_F3 LITERAL1
KEY_F4 LITERAL1
KEY_F5 LITERAL1
KEY_F6 LITERAL1
KEY_F7 LITERAL1
KEY_F8 LITERAL1
KEY_F9 LITERAL1
KEY_F10 LITERAL1
KEY_F11 LITERAL1
KEY_F12 LITERAL1
KEY_PRINT LITERAL1
KEY_NUM_LOCK LITERAL1
KEY_SCROLL_LOCK LITERAL1
KEY_PAUSE LITERAL1
#Raw Keyboard definitions
RAW_KEYBOARD_LEFT_CTRL LITERAL1
RAW_KEYBOARD_LEFT_SHIFT LITERAL1
RAW_KEYBOARD_LEFT_ALT LITERAL1
RAW_KEYBOARD_LEFT_GUI LITERAL1
RAW_KEYBOARD_RIGHT_CTRL LITERAL1
RAW_KEYBOARD_RIGHT_SHIFT LITERAL1
RAW_KEYBOARD_RIGHT_ALT LITERAL1
RAW_KEYBOARD_RIGHT_GUI LITERAL1
RAW_KEYBOARD_KEY LITERAL1
RAW_KEYBOARD_UP_ARROW LITERAL1
RAW_KEYBOARD_DOWN_ARROW LITERAL1
RAW_KEYBOARD_LEFT_ARROW LITERAL1
RAW_KEYBOARD_RIGHT_ARROW LITERAL1
RAW_KEYBOARD_SPACEBAR LITERAL1
RAW_KEYBOARD_BACKSPACE LITERAL1
RAW_KEYBOARD_TAB LITERAL1
RAW_KEYBOARD_RETURN LITERAL1
RAW_KEYBOARD_ESC LITERAL1
RAW_KEYBOARD_INSERT LITERAL1
RAW_KEYBOARD_DELETE LITERAL1
RAW_KEYBOARD_PAGE_UP LITERAL1
RAW_KEYBOARD_PAGE_DOWN LITERAL1
RAW_KEYBOARD_HOME LITERAL1
RAW_KEYBOARD_END LITERAL1
RAW_KEYBOARD_CAPS_LOCK LITERAL1
RAW_KEYBOARD_F1 LITERAL1
RAW_KEYBOARD_F2 LITERAL1
RAW_KEYBOARD_F3 LITERAL1
RAW_KEYBOARD_F4 LITERAL1
RAW_KEYBOARD_F5 LITERAL1
RAW_KEYBOARD_F6 LITERAL1
RAW_KEYBOARD_F7 LITERAL1
RAW_KEYBOARD_F8 LITERAL1
RAW_KEYBOARD_F9 LITERAL1
RAW_KEYBOARD_F10 LITERAL1
RAW_KEYBOARD_F11 LITERAL1
RAW_KEYBOARD_F12 LITERAL1
RAW_KEYBOARD_PRINT LITERAL1
RAW_KEYBOARD_SCROLL_LOCK LITERAL1
RAW_KEYBOARD_PAUSE LITERAL1
#RawHID
RAWHID_RX_SIZE LITERAL1
RAWHID_TX_SIZE LITERAL1
#Media
MEDIA_FAST_FORWARD LITERAL1
MEDIA_REWIND LITERAL1
MEDIA_NEXT LITERAL1
MEDIA_PREVIOUS LITERAL1
MEDIA_STOP LITERAL1
MEDIA_PLAY_PAUSE LITERAL1
MEDIA_VOLUME_MUTE LITERAL1
MEDIA_VOLUME_UP LITERAL1
MEDIA_VOLUME_DOWN LITERAL1
MEDIA_EMAIL_READER LITERAL1
MEDIA_CALCULATOR LITERAL1
MEDIA_EXPLORER LITERAL1
MEDIA_BROWSER_HOME LITERAL1
MEDIA_BROWSER_BACK LITERAL1
MEDIA_BROWSER_FORWARD LITERAL1
MEDIA_BROWSER_REFRESH LITERAL1
MEDIA_BROWSER_BOOKMARKS LITERAL1
#System
SYSTEM_POWER_DOWN LITERAL1
SYSTEM_SLEEP LITERAL1
SYSTEM_WAKE_UP LITERAL1
#Gamepad
GAMEPAD_DPAD_CENTERED LITERAL1
GAMEPAD_DPAD_UP LITERAL1
GAMEPAD_DPAD_UP_RIGHT LITERAL1
GAMEPAD_DPAD_RIGHT LITERAL1
GAMEPAD_DPAD_DOWN_RIGHT LITERAL1
GAMEPAD_DPAD_DOWN LITERAL1
GAMEPAD_DPAD_DOWN_LEFT LITERAL1
GAMEPAD_DPAD_LEFT LITERAL1
GAMEPAD_DPAD_UP_LEFT LITERAL1

View file

@ -1,73 +0,0 @@
/*
wiring_private.h - Internal header file.
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
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., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
*/
#ifndef WiringPrivate_h
#define WiringPrivate_h
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdarg.h>
#include "Arduino.h"
#ifdef __cplusplus
extern "C"{
#endif
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
#define EXTERNAL_INT_0 0
#define EXTERNAL_INT_1 1
#define EXTERNAL_INT_2 2
#define EXTERNAL_INT_3 3
#define EXTERNAL_INT_4 4
#define EXTERNAL_INT_5 5
#define EXTERNAL_INT_6 6
#define EXTERNAL_INT_7 7
// edit by NicoHood
#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) \
|| defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega256RFR2__)
#define EXTERNAL_NUM_INTERRUPTS 8
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
#define EXTERNAL_NUM_INTERRUPTS 3
#elif defined(__AVR_ATmega32U4__)
#define EXTERNAL_NUM_INTERRUPTS 5
#else
#define EXTERNAL_NUM_INTERRUPTS 2
#endif
typedef void (*voidFuncPtr)(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif