aboutsummaryrefslogtreecommitdiff
path: root/libraries/HID/HID.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/HID/HID.cpp')
-rw-r--r--libraries/HID/HID.cpp246
1 files changed, 121 insertions, 125 deletions
diff --git a/libraries/HID/HID.cpp b/libraries/HID/HID.cpp
index 0d2133e..21ede26 100644
--- a/libraries/HID/HID.cpp
+++ b/libraries/HID/HID.cpp
@@ -1,166 +1,162 @@
-/* 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 "PluggableUSB.h"
+/*
+ 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 "HID.h"
#if defined(USBCON)
-HID_ HID;
-
-static u8 HID_ENDPOINT_INT;
-
-//================================================================================
-//================================================================================
-
-// HID report descriptor
-
-#define LSB(_x) ((_x) & 0xFF)
-#define MSB(_x) ((_x) >> 8)
-
-#define RAWHID_USAGE_PAGE 0xFFC0
-#define RAWHID_USAGE 0x0C00
-#define RAWHID_TX_SIZE 64
-#define RAWHID_RX_SIZE 64
-
-static u8 HID_INTERFACE;
-
-HIDDescriptor _hidInterface;
-
-static HIDDescriptorListNode* rootNode = NULL;
-static uint8_t sizeof_hidReportDescriptor = 0;
-static uint8_t modules_count = 0;
-//================================================================================
-//================================================================================
-// Driver
-
-u8 _hid_protocol = 1;
-u8 _hid_idle = 1;
+HID_& HID()
+{
+ static HID_ obj;
+ return obj;
+}
-int HID_GetInterface(u8* interfaceNum)
+int HID_::getInterface(uint8_t* interfaceCount)
{
- interfaceNum[0] += 1; // uses 1
- _hidInterface =
- {
- D_INTERFACE(HID_INTERFACE,1,3,0,0),
- D_HIDREPORT(sizeof_hidReportDescriptor),
- D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01)
+ *interfaceCount += 1; // uses 1
+ HIDDescriptor hidInterface = {
+ D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, 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));
+ return USB_SendControl(0, &hidInterface, sizeof(hidInterface));
}
-int HID_GetDescriptor(int8_t t)
+int HID_::getDescriptor(USBSetup& setup)
{
- if (HID_REPORT_DESCRIPTOR_TYPE == t) {
- HIDDescriptorListNode* current = rootNode;
- int total = 0;
- while(current != NULL) {
- total += USB_SendControl(TRANSFER_PGM,current->cb->descriptor,current->cb->length);
- current = current->next;
- }
- return total;
- } else {
- return 0;
+ // Check if this is a HID Class Descriptor request
+ if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }
+ if (setup.wValueH != 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;
+ HIDSubDescriptor* node;
+ for (node = rootNode; node; node = node->next) {
+ int res = USB_SendControl(TRANSFER_PGM, 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 = HID_REPORT_PROTOCOL;
+
+ return total;
}
-void HID_::AppendDescriptor(HIDDescriptorListNode *node)
+uint8_t HID_::getShortName(char *name)
{
- if (modules_count == 0) {
+ name[0] = 'H';
+ name[1] = 'I';
+ name[2] = 'D';
+ name[3] = 'A' + (descriptorSize & 0x0F);
+ name[4] = 'A' + ((descriptorSize >> 4) & 0x0F);
+ return 5;
+}
+
+void HID_::AppendDescriptor(HIDSubDescriptor *node)
+{
+ if (!rootNode) {
rootNode = node;
} else {
- HIDDescriptorListNode *current = rootNode;
- while(current->next != NULL) {
+ HIDSubDescriptor *current = rootNode;
+ while (current->next) {
current = current->next;
}
current->next = node;
}
- modules_count++;
- sizeof_hidReportDescriptor += node->cb->length;
+ descriptorSize += node->length;
}
-void HID_::SendReport(u8 id, const void* data, int len)
+int HID_::SendReport(uint8_t id, const void* data, int len)
{
- USB_Send(HID_TX, &id, 1);
- USB_Send(HID_TX | TRANSFER_RELEASE,data,len);
+ auto ret = USB_Send(pluggedEndpoint, &id, 1);
+ if (ret < 0) return ret;
+ auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len);
+ if (ret2 < 0) return ret2;
+ return ret + ret2;
}
-bool HID_Setup(USBSetup& setup, u8 i)
+bool HID_::setup(USBSetup& setup)
{
- if (HID_INTERFACE != i) {
+ if (pluggedInterface != setup.wIndex) {
return false;
- } else {
- 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;
- }
+ }
+
+ uint8_t request = setup.bRequest;
+ uint8_t requestType = setup.bmRequestType;
+
+ if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
+ {
+ if (request == HID_GET_REPORT) {
+ // TODO: HID_GetReport();
+ return true;
}
-
- if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
+ if (request == HID_GET_PROTOCOL) {
+ // TODO: Send8(protocol);
+ return true;
+ }
+ if (request == HID_GET_IDLE) {
+ // TODO: Send8(idle);
+ }
+ }
+
+ if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
+ {
+ if (request == 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 == HID_SET_IDLE) {
+ idle = setup.wValueL;
+ return true;
+ }
+ if (request == HID_SET_REPORT)
{
- if (HID_SET_PROTOCOL == r)
- {
- _hid_protocol = setup.wValueL;
- return true;
- }
-
- if (HID_SET_IDLE == r)
- {
- _hid_idle = setup.wValueL;
- return true;
- }
+ //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;
}
+
+ return false;
}
-HID_::HID_(void)
+HID_::HID_(void) : PluggableUSBModule(1, 1, epType),
+ rootNode(NULL), descriptorSize(0),
+ protocol(HID_REPORT_PROTOCOL), idle(1)
{
- static uint8_t endpointType[1];
-
- endpointType[0] = EP_TYPE_INTERRUPT_IN;
-
- static PUSBCallbacks cb = {
- .setup = &HID_Setup,
- .getInterface = &HID_GetInterface,
- .getDescriptor = &HID_GetDescriptor,
- .numEndpoints = 1,
- .numInterfaces = 1,
- .endpointType = endpointType,
- };
-
- static PUSBListNode node(&cb);
-
- HID_ENDPOINT_INT = PUSB_AddFunction(&node, &HID_INTERFACE);
+ epType[0] = EP_TYPE_INTERRUPT_IN;
+ PluggableUSB().plug(this);
}
int HID_::begin(void)
{
+ return 0;
}
#endif /* if defined(USBCON) */