Upload files to "libraries/ArduinoJoystickLibrary/src"
This commit is contained in:
169
libraries/ArduinoJoystickLibrary/src/DynamicHID.cpp
Normal file
169
libraries/ArduinoJoystickLibrary/src/DynamicHID.cpp
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
Modified by Matthew Heironimus to support HID Report Descriptors to be in
|
||||||
|
standard RAM in addition to program memory (PROGMEM).
|
||||||
|
|
||||||
|
Copyright (c) 2015, Arduino LLC
|
||||||
|
Original code (pre-library): Copyright (c) 2011, Peter Barrett
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
any purpose with or without fee is hereby granted, provided that the
|
||||||
|
above copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||||
|
BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||||
|
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DynamicHID.h"
|
||||||
|
|
||||||
|
#if defined(USBCON)
|
||||||
|
|
||||||
|
#ifdef _VARIANT_ARDUINO_DUE_X_
|
||||||
|
#define USB_SendControl USBD_SendControl
|
||||||
|
#define USB_Send USBD_Send
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DynamicHID_& DynamicHID()
|
||||||
|
{
|
||||||
|
static DynamicHID_ obj;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DynamicHID_::getInterface(uint8_t* interfaceCount)
|
||||||
|
{
|
||||||
|
*interfaceCount += 1; // uses 1
|
||||||
|
DYNAMIC_HIDDescriptor hidInterface = {
|
||||||
|
D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, DYNAMIC_HID_SUBCLASS_NONE, DYNAMIC_HID_PROTOCOL_NONE),
|
||||||
|
D_HIDREPORT(descriptorSize),
|
||||||
|
D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01)
|
||||||
|
};
|
||||||
|
return USB_SendControl(0, &hidInterface, sizeof(hidInterface));
|
||||||
|
}
|
||||||
|
|
||||||
|
int DynamicHID_::getDescriptor(USBSetup& setup)
|
||||||
|
{
|
||||||
|
// Check if this is a HID Class Descriptor request
|
||||||
|
if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }
|
||||||
|
if (setup.wValueH != DYNAMIC_HID_REPORT_DESCRIPTOR_TYPE) { return 0; }
|
||||||
|
|
||||||
|
// In a HID Class Descriptor wIndex cointains the interface number
|
||||||
|
if (setup.wIndex != pluggedInterface) { return 0; }
|
||||||
|
|
||||||
|
int total = 0;
|
||||||
|
DynamicHIDSubDescriptor* node;
|
||||||
|
for (node = rootNode; node; node = node->next) {
|
||||||
|
int res = USB_SendControl((node->inProgMem ? TRANSFER_PGM : 0), node->data, node->length);
|
||||||
|
if (res == -1)
|
||||||
|
return -1;
|
||||||
|
total += res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol
|
||||||
|
// due to the USB specs, but Windows and Linux just assumes its in report mode.
|
||||||
|
protocol = DYNAMIC_HID_REPORT_PROTOCOL;
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t DynamicHID_::getShortName(char *name)
|
||||||
|
{
|
||||||
|
name[0] = 'H';
|
||||||
|
name[1] = 'I';
|
||||||
|
name[2] = 'D';
|
||||||
|
name[3] = 'A' + (descriptorSize & 0x0F);
|
||||||
|
name[4] = 'A' + ((descriptorSize >> 4) & 0x0F);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicHID_::AppendDescriptor(DynamicHIDSubDescriptor *node)
|
||||||
|
{
|
||||||
|
if (!rootNode) {
|
||||||
|
rootNode = node;
|
||||||
|
} else {
|
||||||
|
DynamicHIDSubDescriptor *current = rootNode;
|
||||||
|
while (current->next) {
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
current->next = node;
|
||||||
|
}
|
||||||
|
descriptorSize += node->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DynamicHID_::SendReport(uint8_t id, const void* data, int len)
|
||||||
|
{
|
||||||
|
uint8_t p[len + 1];
|
||||||
|
p[0] = id;
|
||||||
|
memcpy(&p[1], data, len);
|
||||||
|
return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, p, len + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynamicHID_::setup(USBSetup& setup)
|
||||||
|
{
|
||||||
|
if (pluggedInterface != setup.wIndex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t request = setup.bRequest;
|
||||||
|
uint8_t requestType = setup.bmRequestType;
|
||||||
|
|
||||||
|
if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
|
||||||
|
{
|
||||||
|
if (request == DYNAMIC_HID_GET_REPORT) {
|
||||||
|
// TODO: DYNAMIC_HID_GetReport();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (request == DYNAMIC_HID_GET_PROTOCOL) {
|
||||||
|
// TODO: Send8(protocol);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (request == DYNAMIC_HID_GET_IDLE) {
|
||||||
|
// TODO: Send8(idle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
|
||||||
|
{
|
||||||
|
if (request == DYNAMIC_HID_SET_PROTOCOL) {
|
||||||
|
// The USB Host tells us if we are in boot or report mode.
|
||||||
|
// This only works with a real boot compatible device.
|
||||||
|
protocol = setup.wValueL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (request == DYNAMIC_HID_SET_IDLE) {
|
||||||
|
idle = setup.wValueL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (request == DYNAMIC_HID_SET_REPORT)
|
||||||
|
{
|
||||||
|
//uint8_t reportID = setup.wValueL;
|
||||||
|
//uint16_t length = setup.wLength;
|
||||||
|
//uint8_t data[length];
|
||||||
|
// Make sure to not read more data than USB_EP_SIZE.
|
||||||
|
// You can read multiple times through a loop.
|
||||||
|
// The first byte (may!) contain the reportID on a multreport.
|
||||||
|
//USB_RecvControl(data, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicHID_::DynamicHID_(void) : PluggableUSBModule(1, 1, epType),
|
||||||
|
rootNode(NULL), descriptorSize(0),
|
||||||
|
protocol(DYNAMIC_HID_REPORT_PROTOCOL), idle(1)
|
||||||
|
{
|
||||||
|
epType[0] = EP_TYPE_INTERRUPT_IN;
|
||||||
|
PluggableUSB().plug(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DynamicHID_::begin(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* if defined(USBCON) */
|
||||||
144
libraries/ArduinoJoystickLibrary/src/DynamicHID.h
Normal file
144
libraries/ArduinoJoystickLibrary/src/DynamicHID.h
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
Modified by Matthew Heironimus to support HID Report Descriptors to be in
|
||||||
|
standard RAM in addition to program memory (PROGMEM).
|
||||||
|
|
||||||
|
Copyright (c) 2015, Arduino LLC
|
||||||
|
Original code (pre-library): 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DYNAMIC_HID_h
|
||||||
|
#define DYNAMIC_HID_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#ifdef _VARIANT_ARDUINO_DUE_X_
|
||||||
|
// The following values are the same as AVR's USBAPI.h
|
||||||
|
// Reproduced here because SAM doesn't have these in
|
||||||
|
// its own USBAPI.H
|
||||||
|
#define USB_EP_SIZE 64
|
||||||
|
#define TRANSFER_PGM 0x80
|
||||||
|
|
||||||
|
#include "USB/PluggableUSB.h"
|
||||||
|
#else
|
||||||
|
#include "PluggableUSB.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(USBCON)
|
||||||
|
|
||||||
|
#define _USING_DYNAMIC_HID
|
||||||
|
|
||||||
|
// DYNAMIC_HID 'Driver'
|
||||||
|
// ------------
|
||||||
|
#define DYNAMIC_HID_GET_REPORT 0x01
|
||||||
|
#define DYNAMIC_HID_GET_IDLE 0x02
|
||||||
|
#define DYNAMIC_HID_GET_PROTOCOL 0x03
|
||||||
|
#define DYNAMIC_HID_SET_REPORT 0x09
|
||||||
|
#define DYNAMIC_HID_SET_IDLE 0x0A
|
||||||
|
#define DYNAMIC_HID_SET_PROTOCOL 0x0B
|
||||||
|
|
||||||
|
#define DYNAMIC_HID_DESCRIPTOR_TYPE 0x21
|
||||||
|
#define DYNAMIC_HID_REPORT_DESCRIPTOR_TYPE 0x22
|
||||||
|
#define DYNAMIC_HID_PHYSICAL_DESCRIPTOR_TYPE 0x23
|
||||||
|
|
||||||
|
// HID subclass HID1.11 Page 8 4.2 Subclass
|
||||||
|
#define DYNAMIC_HID_SUBCLASS_NONE 0
|
||||||
|
#define DYNAMIC_HID_SUBCLASS_BOOT_INTERFACE 1
|
||||||
|
|
||||||
|
// HID Keyboard/Mouse bios compatible protocols HID1.11 Page 9 4.3 Protocols
|
||||||
|
#define DYNAMIC_HID_PROTOCOL_NONE 0
|
||||||
|
#define DYNAMIC_HID_PROTOCOL_KEYBOARD 1
|
||||||
|
#define DYNAMIC_HID_PROTOCOL_MOUSE 2
|
||||||
|
|
||||||
|
// Normal or bios protocol (Keyboard/Mouse) HID1.11 Page 54 7.2.5 Get_Protocol Request
|
||||||
|
// "protocol" variable is used for this purpose.
|
||||||
|
#define DYNAMIC_HID_BOOT_PROTOCOL 0
|
||||||
|
#define DYNAMIC_HID_REPORT_PROTOCOL 1
|
||||||
|
|
||||||
|
// HID Request Type HID1.11 Page 51 7.2.1 Get_Report Request
|
||||||
|
#define DYNAMIC_HID_REPORT_TYPE_INPUT 1
|
||||||
|
#define DYNAMIC_HID_REPORT_TYPE_OUTPUT 2
|
||||||
|
#define DYNAMIC_HID_REPORT_TYPE_FEATURE 3
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t len; // 9
|
||||||
|
uint8_t dtype; // 0x21
|
||||||
|
uint8_t addr;
|
||||||
|
uint8_t versionL; // 0x101
|
||||||
|
uint8_t versionH; // 0x101
|
||||||
|
uint8_t country;
|
||||||
|
uint8_t desctype; // 0x22 report
|
||||||
|
uint8_t descLenL;
|
||||||
|
uint8_t descLenH;
|
||||||
|
} DYNAMIC_HIDDescDescriptor;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
InterfaceDescriptor hid;
|
||||||
|
DYNAMIC_HIDDescDescriptor desc;
|
||||||
|
EndpointDescriptor in;
|
||||||
|
} DYNAMIC_HIDDescriptor;
|
||||||
|
|
||||||
|
class DynamicHIDSubDescriptor {
|
||||||
|
public:
|
||||||
|
DynamicHIDSubDescriptor *next = NULL;
|
||||||
|
DynamicHIDSubDescriptor(const void *d, const uint16_t l, const bool ipm = true) : data(d), length(l), inProgMem(ipm) { }
|
||||||
|
|
||||||
|
const void* data;
|
||||||
|
const uint16_t length;
|
||||||
|
const bool inProgMem;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DynamicHID_ : public PluggableUSBModule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DynamicHID_(void);
|
||||||
|
int begin(void);
|
||||||
|
int SendReport(uint8_t id, const void* data, int len);
|
||||||
|
void AppendDescriptor(DynamicHIDSubDescriptor* node);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Implementation of the PluggableUSBModule
|
||||||
|
int getInterface(uint8_t* interfaceCount);
|
||||||
|
int getDescriptor(USBSetup& setup);
|
||||||
|
bool setup(USBSetup& setup);
|
||||||
|
uint8_t getShortName(char* name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef _VARIANT_ARDUINO_DUE_X_
|
||||||
|
uint32_t epType[1];
|
||||||
|
#else
|
||||||
|
uint8_t epType[1];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DynamicHIDSubDescriptor* rootNode;
|
||||||
|
uint16_t descriptorSize;
|
||||||
|
|
||||||
|
uint8_t protocol;
|
||||||
|
uint8_t idle;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Replacement for global singleton.
|
||||||
|
// This function prevents static-initialization-order-fiasco
|
||||||
|
// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use
|
||||||
|
DynamicHID_& DynamicHID();
|
||||||
|
|
||||||
|
#define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) }
|
||||||
|
|
||||||
|
#endif // USBCON
|
||||||
|
|
||||||
|
#endif // DYNAMIC_HID_h
|
||||||
682
libraries/ArduinoJoystickLibrary/src/Joystick.cpp
Normal file
682
libraries/ArduinoJoystickLibrary/src/Joystick.cpp
Normal file
@@ -0,0 +1,682 @@
|
|||||||
|
/*
|
||||||
|
Joystick.cpp
|
||||||
|
|
||||||
|
Copyright (c) 2015-2017, Matthew Heironimus
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Joystick.h"
|
||||||
|
|
||||||
|
#if defined(_USING_DYNAMIC_HID)
|
||||||
|
|
||||||
|
#define JOYSTICK_REPORT_ID_INDEX 7
|
||||||
|
#define JOYSTICK_AXIS_MINIMUM 0
|
||||||
|
#define JOYSTICK_AXIS_MAXIMUM 65535
|
||||||
|
#define JOYSTICK_SIMULATOR_MINIMUM 0
|
||||||
|
#define JOYSTICK_SIMULATOR_MAXIMUM 65535
|
||||||
|
|
||||||
|
#define JOYSTICK_INCLUDE_X_AXIS B00000001
|
||||||
|
#define JOYSTICK_INCLUDE_Y_AXIS B00000010
|
||||||
|
#define JOYSTICK_INCLUDE_Z_AXIS B00000100
|
||||||
|
#define JOYSTICK_INCLUDE_RX_AXIS B00001000
|
||||||
|
#define JOYSTICK_INCLUDE_RY_AXIS B00010000
|
||||||
|
#define JOYSTICK_INCLUDE_RZ_AXIS B00100000
|
||||||
|
|
||||||
|
#define JOYSTICK_INCLUDE_RUDDER B00000001
|
||||||
|
#define JOYSTICK_INCLUDE_THROTTLE B00000010
|
||||||
|
#define JOYSTICK_INCLUDE_ACCELERATOR B00000100
|
||||||
|
#define JOYSTICK_INCLUDE_BRAKE B00001000
|
||||||
|
#define JOYSTICK_INCLUDE_STEERING B00010000
|
||||||
|
|
||||||
|
Joystick_::Joystick_(
|
||||||
|
uint8_t hidReportId,
|
||||||
|
uint8_t joystickType,
|
||||||
|
uint8_t buttonCount,
|
||||||
|
uint8_t hatSwitchCount,
|
||||||
|
bool includeXAxis,
|
||||||
|
bool includeYAxis,
|
||||||
|
bool includeZAxis,
|
||||||
|
bool includeRxAxis,
|
||||||
|
bool includeRyAxis,
|
||||||
|
bool includeRzAxis,
|
||||||
|
bool includeRudder,
|
||||||
|
bool includeThrottle,
|
||||||
|
bool includeAccelerator,
|
||||||
|
bool includeBrake,
|
||||||
|
bool includeSteering)
|
||||||
|
{
|
||||||
|
// Set the USB HID Report ID
|
||||||
|
_hidReportId = hidReportId;
|
||||||
|
|
||||||
|
// Save Joystick Settings
|
||||||
|
_buttonCount = buttonCount;
|
||||||
|
_hatSwitchCount = hatSwitchCount;
|
||||||
|
_includeAxisFlags = 0;
|
||||||
|
_includeAxisFlags |= (includeXAxis ? JOYSTICK_INCLUDE_X_AXIS : 0);
|
||||||
|
_includeAxisFlags |= (includeYAxis ? JOYSTICK_INCLUDE_Y_AXIS : 0);
|
||||||
|
_includeAxisFlags |= (includeZAxis ? JOYSTICK_INCLUDE_Z_AXIS : 0);
|
||||||
|
_includeAxisFlags |= (includeRxAxis ? JOYSTICK_INCLUDE_RX_AXIS : 0);
|
||||||
|
_includeAxisFlags |= (includeRyAxis ? JOYSTICK_INCLUDE_RY_AXIS : 0);
|
||||||
|
_includeAxisFlags |= (includeRzAxis ? JOYSTICK_INCLUDE_RZ_AXIS : 0);
|
||||||
|
_includeSimulatorFlags = 0;
|
||||||
|
_includeSimulatorFlags |= (includeRudder ? JOYSTICK_INCLUDE_RUDDER : 0);
|
||||||
|
_includeSimulatorFlags |= (includeThrottle ? JOYSTICK_INCLUDE_THROTTLE : 0);
|
||||||
|
_includeSimulatorFlags |= (includeAccelerator ? JOYSTICK_INCLUDE_ACCELERATOR : 0);
|
||||||
|
_includeSimulatorFlags |= (includeBrake ? JOYSTICK_INCLUDE_BRAKE : 0);
|
||||||
|
_includeSimulatorFlags |= (includeSteering ? JOYSTICK_INCLUDE_STEERING : 0);
|
||||||
|
|
||||||
|
// Build Joystick HID Report Description
|
||||||
|
|
||||||
|
// Button Calculations
|
||||||
|
uint8_t buttonsInLastByte = _buttonCount % 8;
|
||||||
|
uint8_t buttonPaddingBits = 0;
|
||||||
|
if (buttonsInLastByte > 0)
|
||||||
|
{
|
||||||
|
buttonPaddingBits = 8 - buttonsInLastByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Axis Calculations
|
||||||
|
uint8_t axisCount = (includeXAxis == true)
|
||||||
|
+ (includeYAxis == true)
|
||||||
|
+ (includeZAxis == true)
|
||||||
|
+ (includeRxAxis == true)
|
||||||
|
+ (includeRyAxis == true)
|
||||||
|
+ (includeRzAxis == true);
|
||||||
|
|
||||||
|
uint8_t simulationCount = (includeRudder == true)
|
||||||
|
+ (includeThrottle == true)
|
||||||
|
+ (includeAccelerator == true)
|
||||||
|
+ (includeBrake == true)
|
||||||
|
+ (includeSteering == true);
|
||||||
|
|
||||||
|
uint8_t tempHidReportDescriptor[150];
|
||||||
|
int hidReportDescriptorSize = 0;
|
||||||
|
|
||||||
|
// USAGE_PAGE (Generic Desktop)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// USAGE (Joystick - 0x04; Gamepad - 0x05; Multi-axis Controller - 0x08)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = joystickType;
|
||||||
|
|
||||||
|
// COLLECTION (Application)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xa1;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// REPORT_ID (Default: 3)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x85;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = _hidReportId;
|
||||||
|
|
||||||
|
if (_buttonCount > 0) {
|
||||||
|
|
||||||
|
// USAGE_PAGE (Button)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
|
||||||
|
// USAGE_MINIMUM (Button 1)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x19;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// USAGE_MAXIMUM (Button 32)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x29;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = _buttonCount;
|
||||||
|
|
||||||
|
// LOGICAL_MINIMUM (0)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x15;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
// LOGICAL_MAXIMUM (1)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x25;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// REPORT_SIZE (1)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// REPORT_COUNT (# of buttons)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = _buttonCount;
|
||||||
|
|
||||||
|
// UNIT_EXPONENT (0)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x55;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
// UNIT (None)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x65;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
// INPUT (Data,Var,Abs)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
|
||||||
|
|
||||||
|
if (buttonPaddingBits > 0) {
|
||||||
|
|
||||||
|
// REPORT_SIZE (1)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// REPORT_COUNT (# of padding bits)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = buttonPaddingBits;
|
||||||
|
|
||||||
|
// INPUT (Const,Var,Abs)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x03;
|
||||||
|
|
||||||
|
} // Padding Bits Needed
|
||||||
|
|
||||||
|
} // Buttons
|
||||||
|
|
||||||
|
if ((axisCount > 0) || (_hatSwitchCount > 0)) {
|
||||||
|
|
||||||
|
// USAGE_PAGE (Generic Desktop)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_hatSwitchCount > 0) {
|
||||||
|
|
||||||
|
// USAGE (Hat Switch)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x39;
|
||||||
|
|
||||||
|
// LOGICAL_MINIMUM (0)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x15;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
// LOGICAL_MAXIMUM (7)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x25;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x07;
|
||||||
|
|
||||||
|
// PHYSICAL_MINIMUM (0)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x35;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
// PHYSICAL_MAXIMUM (315)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x46;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x3B;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// UNIT (Eng Rot:Angular Pos)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x65;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x14;
|
||||||
|
|
||||||
|
// REPORT_SIZE (4)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x04;
|
||||||
|
|
||||||
|
// REPORT_COUNT (1)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// INPUT (Data,Var,Abs)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
|
||||||
|
|
||||||
|
if (_hatSwitchCount > 1) {
|
||||||
|
|
||||||
|
// USAGE (Hat Switch)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x39;
|
||||||
|
|
||||||
|
// LOGICAL_MINIMUM (0)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x15;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
// LOGICAL_MAXIMUM (7)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x25;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x07;
|
||||||
|
|
||||||
|
// PHYSICAL_MINIMUM (0)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x35;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
// PHYSICAL_MAXIMUM (315)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x46;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x3B;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// UNIT (Eng Rot:Angular Pos)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x65;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x14;
|
||||||
|
|
||||||
|
// REPORT_SIZE (4)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x04;
|
||||||
|
|
||||||
|
// REPORT_COUNT (1)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// INPUT (Data,Var,Abs)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Use Padding Bits
|
||||||
|
|
||||||
|
// REPORT_SIZE (1)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// REPORT_COUNT (4)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x04;
|
||||||
|
|
||||||
|
// INPUT (Const,Var,Abs)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x03;
|
||||||
|
|
||||||
|
} // One or Two Hat Switches?
|
||||||
|
|
||||||
|
} // Hat Switches
|
||||||
|
|
||||||
|
if (axisCount > 0) {
|
||||||
|
|
||||||
|
// USAGE (Pointer)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
|
||||||
|
|
||||||
|
// LOGICAL_MINIMUM (0)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x15;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
// LOGICAL_MAXIMUM (65535)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x27;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0XFF;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0XFF;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
// REPORT_SIZE (16)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x10;
|
||||||
|
|
||||||
|
// REPORT_COUNT (axisCount)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = axisCount;
|
||||||
|
|
||||||
|
// COLLECTION (Physical)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xA1;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
if (includeXAxis == true) {
|
||||||
|
// USAGE (X)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x30;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeYAxis == true) {
|
||||||
|
// USAGE (Y)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x31;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeZAxis == true) {
|
||||||
|
// USAGE (Z)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeRxAxis == true) {
|
||||||
|
// USAGE (Rx)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x33;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeRyAxis == true) {
|
||||||
|
// USAGE (Ry)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x34;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeRzAxis == true) {
|
||||||
|
// USAGE (Rz)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x35;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INPUT (Data,Var,Abs)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
|
||||||
|
|
||||||
|
// END_COLLECTION (Physical)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0;
|
||||||
|
|
||||||
|
} // X, Y, Z, Rx, Ry, and Rz Axis
|
||||||
|
|
||||||
|
if (simulationCount > 0) {
|
||||||
|
|
||||||
|
// USAGE_PAGE (Simulation Controls)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
|
||||||
|
|
||||||
|
// LOGICAL_MINIMUM (0)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x15;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
// LOGICAL_MAXIMUM (65535)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x27;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0XFF;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0XFF;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
// REPORT_SIZE (16)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x10;
|
||||||
|
|
||||||
|
// REPORT_COUNT (simulationCount)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = simulationCount;
|
||||||
|
|
||||||
|
// COLLECTION (Physical)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xA1;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
|
||||||
|
|
||||||
|
if (includeRudder == true) {
|
||||||
|
// USAGE (Rudder)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xBA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeThrottle == true) {
|
||||||
|
// USAGE (Throttle)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xBB;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeAccelerator == true) {
|
||||||
|
// USAGE (Accelerator)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xC4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeBrake == true) {
|
||||||
|
// USAGE (Brake)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xC5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeSteering == true) {
|
||||||
|
// USAGE (Steering)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xC8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INPUT (Data,Var,Abs)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
|
||||||
|
|
||||||
|
// END_COLLECTION (Physical)
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0;
|
||||||
|
|
||||||
|
} // Simulation Controls
|
||||||
|
|
||||||
|
// END_COLLECTION
|
||||||
|
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0;
|
||||||
|
|
||||||
|
// Create a copy of the HID Report Descriptor template that is just the right size
|
||||||
|
uint8_t *customHidReportDescriptor = new uint8_t[hidReportDescriptorSize];
|
||||||
|
memcpy(customHidReportDescriptor, tempHidReportDescriptor, hidReportDescriptorSize);
|
||||||
|
|
||||||
|
// Register HID Report Description
|
||||||
|
DynamicHIDSubDescriptor *node = new DynamicHIDSubDescriptor(customHidReportDescriptor, hidReportDescriptorSize, false);
|
||||||
|
DynamicHID().AppendDescriptor(node);
|
||||||
|
|
||||||
|
// Setup Joystick State
|
||||||
|
if (buttonCount > 0) {
|
||||||
|
_buttonValuesArraySize = _buttonCount / 8;
|
||||||
|
if ((_buttonCount % 8) > 0) {
|
||||||
|
_buttonValuesArraySize++;
|
||||||
|
}
|
||||||
|
_buttonValues = new uint8_t[_buttonValuesArraySize];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate HID Report Size
|
||||||
|
_hidReportSize = _buttonValuesArraySize;
|
||||||
|
_hidReportSize += (_hatSwitchCount > 0);
|
||||||
|
_hidReportSize += (axisCount * 2);
|
||||||
|
_hidReportSize += (simulationCount * 2);
|
||||||
|
|
||||||
|
// Initialize Joystick State
|
||||||
|
_xAxis = 0;
|
||||||
|
_yAxis = 0;
|
||||||
|
_zAxis = 0;
|
||||||
|
_xAxisRotation = 0;
|
||||||
|
_yAxisRotation = 0;
|
||||||
|
_zAxisRotation = 0;
|
||||||
|
_throttle = 0;
|
||||||
|
_rudder = 0;
|
||||||
|
_accelerator = 0;
|
||||||
|
_brake = 0;
|
||||||
|
_steering = 0;
|
||||||
|
for (int index = 0; index < JOYSTICK_HATSWITCH_COUNT_MAXIMUM; index++)
|
||||||
|
{
|
||||||
|
_hatSwitchValues[index] = JOYSTICK_HATSWITCH_RELEASE;
|
||||||
|
}
|
||||||
|
for (int index = 0; index < _buttonValuesArraySize; index++)
|
||||||
|
{
|
||||||
|
_buttonValues[index] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Joystick_::begin(bool initAutoSendState)
|
||||||
|
{
|
||||||
|
_autoSendState = initAutoSendState;
|
||||||
|
sendState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Joystick_::end()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Joystick_::setButton(uint8_t button, uint8_t value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
releaseButton(button);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pressButton(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Joystick_::pressButton(uint8_t button)
|
||||||
|
{
|
||||||
|
if (button >= _buttonCount) return;
|
||||||
|
|
||||||
|
int index = button / 8;
|
||||||
|
int bit = button % 8;
|
||||||
|
|
||||||
|
bitSet(_buttonValues[index], bit);
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
void Joystick_::releaseButton(uint8_t button)
|
||||||
|
{
|
||||||
|
if (button >= _buttonCount) return;
|
||||||
|
|
||||||
|
int index = button / 8;
|
||||||
|
int bit = button % 8;
|
||||||
|
|
||||||
|
bitClear(_buttonValues[index], bit);
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Joystick_::setXAxis(int32_t value)
|
||||||
|
{
|
||||||
|
_xAxis = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
void Joystick_::setYAxis(int32_t value)
|
||||||
|
{
|
||||||
|
_yAxis = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
void Joystick_::setZAxis(int32_t value)
|
||||||
|
{
|
||||||
|
_zAxis = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Joystick_::setRxAxis(int32_t value)
|
||||||
|
{
|
||||||
|
_xAxisRotation = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
void Joystick_::setRyAxis(int32_t value)
|
||||||
|
{
|
||||||
|
_yAxisRotation = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
void Joystick_::setRzAxis(int32_t value)
|
||||||
|
{
|
||||||
|
_zAxisRotation = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Joystick_::setRudder(int32_t value)
|
||||||
|
{
|
||||||
|
_rudder = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
void Joystick_::setThrottle(int32_t value)
|
||||||
|
{
|
||||||
|
_throttle = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
void Joystick_::setAccelerator(int32_t value)
|
||||||
|
{
|
||||||
|
_accelerator = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
void Joystick_::setBrake(int32_t value)
|
||||||
|
{
|
||||||
|
_brake = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
void Joystick_::setSteering(int32_t value)
|
||||||
|
{
|
||||||
|
_steering = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Joystick_::setHatSwitch(int8_t hatSwitchIndex, int16_t value)
|
||||||
|
{
|
||||||
|
if (hatSwitchIndex >= _hatSwitchCount) return;
|
||||||
|
|
||||||
|
_hatSwitchValues[hatSwitchIndex] = value;
|
||||||
|
if (_autoSendState) sendState();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Joystick_::buildAndSet16BitValue(bool includeValue, int32_t value, int32_t valueMinimum, int32_t valueMaximum, int32_t actualMinimum, int32_t actualMaximum, uint8_t dataLocation[])
|
||||||
|
{
|
||||||
|
int32_t convertedValue;
|
||||||
|
uint8_t highByte;
|
||||||
|
uint8_t lowByte;
|
||||||
|
int32_t realMinimum = min(valueMinimum, valueMaximum);
|
||||||
|
int32_t realMaximum = max(valueMinimum, valueMaximum);
|
||||||
|
|
||||||
|
if (includeValue == false) return 0;
|
||||||
|
|
||||||
|
if (value < realMinimum) {
|
||||||
|
value = realMinimum;
|
||||||
|
}
|
||||||
|
if (value > realMaximum) {
|
||||||
|
value = realMaximum;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valueMinimum > valueMaximum) {
|
||||||
|
// Values go from a larger number to a smaller number (e.g. 1024 to 0)
|
||||||
|
value = realMaximum - value + realMinimum;
|
||||||
|
}
|
||||||
|
|
||||||
|
convertedValue = map(value, realMinimum, realMaximum, actualMinimum, actualMaximum);
|
||||||
|
|
||||||
|
highByte = (uint8_t)(convertedValue >> 8);
|
||||||
|
lowByte = (uint8_t)(convertedValue & 0x00FF);
|
||||||
|
|
||||||
|
dataLocation[0] = lowByte;
|
||||||
|
dataLocation[1] = highByte;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Joystick_::buildAndSetAxisValue(bool includeAxis, int32_t axisValue, int32_t axisMinimum, int32_t axisMaximum, uint8_t dataLocation[])
|
||||||
|
{
|
||||||
|
return buildAndSet16BitValue(includeAxis, axisValue, axisMinimum, axisMaximum, JOYSTICK_AXIS_MINIMUM, JOYSTICK_AXIS_MAXIMUM, dataLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Joystick_::buildAndSetSimulationValue(bool includeValue, int32_t value, int32_t valueMinimum, int32_t valueMaximum, uint8_t dataLocation[])
|
||||||
|
{
|
||||||
|
return buildAndSet16BitValue(includeValue, value, valueMinimum, valueMaximum, JOYSTICK_SIMULATOR_MINIMUM, JOYSTICK_SIMULATOR_MAXIMUM, dataLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Joystick_::sendState()
|
||||||
|
{
|
||||||
|
uint8_t data[_hidReportSize];
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
// Load Button State
|
||||||
|
for (; index < _buttonValuesArraySize; index++)
|
||||||
|
{
|
||||||
|
data[index] = _buttonValues[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Hat Switch Values
|
||||||
|
if (_hatSwitchCount > 0) {
|
||||||
|
|
||||||
|
// Calculate hat-switch values
|
||||||
|
uint8_t convertedHatSwitch[JOYSTICK_HATSWITCH_COUNT_MAXIMUM];
|
||||||
|
for (int hatSwitchIndex = 0; hatSwitchIndex < JOYSTICK_HATSWITCH_COUNT_MAXIMUM; hatSwitchIndex++)
|
||||||
|
{
|
||||||
|
if (_hatSwitchValues[hatSwitchIndex] < 0)
|
||||||
|
{
|
||||||
|
convertedHatSwitch[hatSwitchIndex] = 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
convertedHatSwitch[hatSwitchIndex] = (_hatSwitchValues[hatSwitchIndex] % 360) / 45;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pack hat-switch states into a single byte
|
||||||
|
data[index++] = (convertedHatSwitch[1] << 4) | (B00001111 & convertedHatSwitch[0]);
|
||||||
|
|
||||||
|
} // Hat Switches
|
||||||
|
|
||||||
|
// Set Axis Values
|
||||||
|
index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_X_AXIS, _xAxis, _xAxisMinimum, _xAxisMaximum, &(data[index]));
|
||||||
|
index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_Y_AXIS, _yAxis, _yAxisMinimum, _yAxisMaximum, &(data[index]));
|
||||||
|
index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_Z_AXIS, _zAxis, _zAxisMinimum, _zAxisMaximum, &(data[index]));
|
||||||
|
index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_RX_AXIS, _xAxisRotation, _rxAxisMinimum, _rxAxisMaximum, &(data[index]));
|
||||||
|
index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_RY_AXIS, _yAxisRotation, _ryAxisMinimum, _ryAxisMaximum, &(data[index]));
|
||||||
|
index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_RZ_AXIS, _zAxisRotation, _rzAxisMinimum, _rzAxisMaximum, &(data[index]));
|
||||||
|
|
||||||
|
// Set Simulation Values
|
||||||
|
index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_RUDDER, _rudder, _rudderMinimum, _rudderMaximum, &(data[index]));
|
||||||
|
index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_THROTTLE, _throttle, _throttleMinimum, _throttleMaximum, &(data[index]));
|
||||||
|
index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_ACCELERATOR, _accelerator, _acceleratorMinimum, _acceleratorMaximum, &(data[index]));
|
||||||
|
index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_BRAKE, _brake, _brakeMinimum, _brakeMaximum, &(data[index]));
|
||||||
|
index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_STEERING, _steering, _steeringMinimum, _steeringMaximum, &(data[index]));
|
||||||
|
|
||||||
|
DynamicHID().SendReport(_hidReportId, data, _hidReportSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
218
libraries/ArduinoJoystickLibrary/src/Joystick.h
Normal file
218
libraries/ArduinoJoystickLibrary/src/Joystick.h
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
Joystick.h
|
||||||
|
|
||||||
|
Copyright (c) 2015-2017, Matthew Heironimus
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JOYSTICK_h
|
||||||
|
#define JOYSTICK_h
|
||||||
|
|
||||||
|
#include "DynamicHID/DynamicHID.h"
|
||||||
|
|
||||||
|
#if ARDUINO < 10606
|
||||||
|
#error The Joystick library requires Arduino IDE 1.6.6 or greater. Please update your IDE.
|
||||||
|
#endif // ARDUINO < 10606
|
||||||
|
|
||||||
|
#if ARDUINO > 10606
|
||||||
|
#if !defined(USBCON)
|
||||||
|
#error The Joystick library can only be used with a USB MCU (e.g. Arduino Leonardo, Arduino Micro, etc.).
|
||||||
|
#endif // !defined(USBCON)
|
||||||
|
#endif // ARDUINO > 10606
|
||||||
|
|
||||||
|
#if !defined(_USING_DYNAMIC_HID)
|
||||||
|
|
||||||
|
#warning "Using legacy HID core (non pluggable)"
|
||||||
|
|
||||||
|
#else // !defined(_USING_DYNAMIC_HID)
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
// Joystick (Gamepad)
|
||||||
|
|
||||||
|
#define JOYSTICK_DEFAULT_REPORT_ID 0x03
|
||||||
|
#define JOYSTICK_DEFAULT_BUTTON_COUNT 32
|
||||||
|
#define JOYSTICK_DEFAULT_AXIS_MINIMUM 0
|
||||||
|
#define JOYSTICK_DEFAULT_AXIS_MAXIMUM 1023
|
||||||
|
#define JOYSTICK_DEFAULT_SIMULATOR_MINIMUM 0
|
||||||
|
#define JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM 1023
|
||||||
|
#define JOYSTICK_DEFAULT_HATSWITCH_COUNT 2
|
||||||
|
#define JOYSTICK_HATSWITCH_COUNT_MAXIMUM 2
|
||||||
|
#define JOYSTICK_HATSWITCH_RELEASE -1
|
||||||
|
#define JOYSTICK_TYPE_JOYSTICK 0x04
|
||||||
|
#define JOYSTICK_TYPE_GAMEPAD 0x05
|
||||||
|
#define JOYSTICK_TYPE_MULTI_AXIS 0x08
|
||||||
|
|
||||||
|
class Joystick_
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Joystick State
|
||||||
|
int32_t _xAxis;
|
||||||
|
int32_t _yAxis;
|
||||||
|
int32_t _zAxis;
|
||||||
|
int32_t _xAxisRotation;
|
||||||
|
int32_t _yAxisRotation;
|
||||||
|
int32_t _zAxisRotation;
|
||||||
|
int32_t _throttle;
|
||||||
|
int32_t _rudder;
|
||||||
|
int32_t _accelerator;
|
||||||
|
int32_t _brake;
|
||||||
|
int32_t _steering;
|
||||||
|
int16_t _hatSwitchValues[JOYSTICK_HATSWITCH_COUNT_MAXIMUM];
|
||||||
|
uint8_t *_buttonValues = NULL;
|
||||||
|
|
||||||
|
// Joystick Settings
|
||||||
|
bool _autoSendState;
|
||||||
|
uint8_t _buttonCount;
|
||||||
|
uint8_t _buttonValuesArraySize = 0;
|
||||||
|
uint8_t _hatSwitchCount;
|
||||||
|
uint8_t _includeAxisFlags;
|
||||||
|
uint8_t _includeSimulatorFlags;
|
||||||
|
int32_t _xAxisMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM;
|
||||||
|
int32_t _xAxisMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM;
|
||||||
|
int32_t _yAxisMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM;
|
||||||
|
int32_t _yAxisMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM;
|
||||||
|
int32_t _zAxisMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM;
|
||||||
|
int32_t _zAxisMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM;
|
||||||
|
int32_t _rxAxisMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM;
|
||||||
|
int32_t _rxAxisMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM;
|
||||||
|
int32_t _ryAxisMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM;
|
||||||
|
int32_t _ryAxisMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM;
|
||||||
|
int32_t _rzAxisMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM;
|
||||||
|
int32_t _rzAxisMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM;
|
||||||
|
int32_t _rudderMinimum = JOYSTICK_DEFAULT_SIMULATOR_MINIMUM;
|
||||||
|
int32_t _rudderMaximum = JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM;
|
||||||
|
int32_t _throttleMinimum = JOYSTICK_DEFAULT_SIMULATOR_MINIMUM;
|
||||||
|
int32_t _throttleMaximum = JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM;
|
||||||
|
int32_t _acceleratorMinimum = JOYSTICK_DEFAULT_SIMULATOR_MINIMUM;
|
||||||
|
int32_t _acceleratorMaximum = JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM;
|
||||||
|
int32_t _brakeMinimum = JOYSTICK_DEFAULT_SIMULATOR_MINIMUM;
|
||||||
|
int32_t _brakeMaximum = JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM;
|
||||||
|
int32_t _steeringMinimum = JOYSTICK_DEFAULT_SIMULATOR_MINIMUM;
|
||||||
|
int32_t _steeringMaximum = JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM;
|
||||||
|
|
||||||
|
uint8_t _hidReportId;
|
||||||
|
uint8_t _hidReportSize;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int buildAndSet16BitValue(bool includeValue, int32_t value, int32_t valueMinimum, int32_t valueMaximum, int32_t actualMinimum, int32_t actualMaximum, uint8_t dataLocation[]);
|
||||||
|
int buildAndSetAxisValue(bool includeAxis, int32_t axisValue, int32_t axisMinimum, int32_t axisMaximum, uint8_t dataLocation[]);
|
||||||
|
int buildAndSetSimulationValue(bool includeValue, int32_t value, int32_t valueMinimum, int32_t valueMaximum, uint8_t dataLocation[]);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Joystick_(
|
||||||
|
uint8_t hidReportId = JOYSTICK_DEFAULT_REPORT_ID,
|
||||||
|
uint8_t joystickType = JOYSTICK_TYPE_JOYSTICK,
|
||||||
|
uint8_t buttonCount = JOYSTICK_DEFAULT_BUTTON_COUNT,
|
||||||
|
uint8_t hatSwitchCount = JOYSTICK_DEFAULT_HATSWITCH_COUNT,
|
||||||
|
bool includeXAxis = true,
|
||||||
|
bool includeYAxis = true,
|
||||||
|
bool includeZAxis = true,
|
||||||
|
bool includeRxAxis = true,
|
||||||
|
bool includeRyAxis = true,
|
||||||
|
bool includeRzAxis = true,
|
||||||
|
bool includeRudder = true,
|
||||||
|
bool includeThrottle = true,
|
||||||
|
bool includeAccelerator = true,
|
||||||
|
bool includeBrake = true,
|
||||||
|
bool includeSteering = true);
|
||||||
|
|
||||||
|
void begin(bool initAutoSendState = true);
|
||||||
|
void end();
|
||||||
|
|
||||||
|
// Set Range Functions
|
||||||
|
inline void setXAxisRange(int32_t minimum, int32_t maximum)
|
||||||
|
{
|
||||||
|
_xAxisMinimum = minimum;
|
||||||
|
_xAxisMaximum = maximum;
|
||||||
|
}
|
||||||
|
inline void setYAxisRange(int32_t minimum, int32_t maximum)
|
||||||
|
{
|
||||||
|
_yAxisMinimum = minimum;
|
||||||
|
_yAxisMaximum = maximum;
|
||||||
|
}
|
||||||
|
inline void setZAxisRange(int32_t minimum, int32_t maximum)
|
||||||
|
{
|
||||||
|
_zAxisMinimum = minimum;
|
||||||
|
_zAxisMaximum = maximum;
|
||||||
|
}
|
||||||
|
inline void setRxAxisRange(int32_t minimum, int32_t maximum)
|
||||||
|
{
|
||||||
|
_rxAxisMinimum = minimum;
|
||||||
|
_rxAxisMaximum = maximum;
|
||||||
|
}
|
||||||
|
inline void setRyAxisRange(int32_t minimum, int32_t maximum)
|
||||||
|
{
|
||||||
|
_ryAxisMinimum = minimum;
|
||||||
|
_ryAxisMaximum = maximum;
|
||||||
|
}
|
||||||
|
inline void setRzAxisRange(int32_t minimum, int32_t maximum)
|
||||||
|
{
|
||||||
|
_rzAxisMinimum = minimum;
|
||||||
|
_rzAxisMaximum = maximum;
|
||||||
|
}
|
||||||
|
inline void setRudderRange(int32_t minimum, int32_t maximum)
|
||||||
|
{
|
||||||
|
_rudderMinimum = minimum;
|
||||||
|
_rudderMaximum = maximum;
|
||||||
|
}
|
||||||
|
inline void setThrottleRange(int32_t minimum, int32_t maximum)
|
||||||
|
{
|
||||||
|
_throttleMinimum = minimum;
|
||||||
|
_throttleMaximum = maximum;
|
||||||
|
}
|
||||||
|
inline void setAcceleratorRange(int32_t minimum, int32_t maximum)
|
||||||
|
{
|
||||||
|
_acceleratorMinimum = minimum;
|
||||||
|
_acceleratorMaximum = maximum;
|
||||||
|
}
|
||||||
|
inline void setBrakeRange(int32_t minimum, int32_t maximum)
|
||||||
|
{
|
||||||
|
_brakeMinimum = minimum;
|
||||||
|
_brakeMaximum = maximum;
|
||||||
|
}
|
||||||
|
inline void setSteeringRange(int32_t minimum, int32_t maximum)
|
||||||
|
{
|
||||||
|
_steeringMinimum = minimum;
|
||||||
|
_steeringMaximum = maximum;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Axis Values
|
||||||
|
void setXAxis(int32_t value);
|
||||||
|
void setYAxis(int32_t value);
|
||||||
|
void setZAxis(int32_t value);
|
||||||
|
void setRxAxis(int32_t value);
|
||||||
|
void setRyAxis(int32_t value);
|
||||||
|
void setRzAxis(int32_t value);
|
||||||
|
|
||||||
|
// Set Simulation Values
|
||||||
|
void setRudder(int32_t value);
|
||||||
|
void setThrottle(int32_t value);
|
||||||
|
void setAccelerator(int32_t value);
|
||||||
|
void setBrake(int32_t value);
|
||||||
|
void setSteering(int32_t value);
|
||||||
|
|
||||||
|
void setButton(uint8_t button, uint8_t value);
|
||||||
|
void pressButton(uint8_t button);
|
||||||
|
void releaseButton(uint8_t button);
|
||||||
|
|
||||||
|
void setHatSwitch(int8_t hatSwitch, int16_t value);
|
||||||
|
|
||||||
|
void sendState();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(_USING_DYNAMIC_HID)
|
||||||
|
#endif // JOYSTICK_h
|
||||||
Reference in New Issue
Block a user