Skip to content

Commit 77fbf71

Browse files
committed
Initial commit
0 parents  commit 77fbf71

File tree

7 files changed

+710
-0
lines changed

7 files changed

+710
-0
lines changed

README.adoc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
= HID Power Device Library for Arduino =
2+
3+
This library allows an Arduino board with USB capabilities to act as a HID-compliant Power Device according to USB HID specifications. This library is useful if you want to build a smart UPS or other power device, which can report its state or perform power on/power off operations as necessary for your project.
4+
5+
For more information about USB HID specs please read https://www.usb.org/sites/default/files/pdcv11.pdf
6+
7+
== License ==
8+
9+
Copyright (c) Arduino LLC. All right reserved.
10+
11+
This library is free software; you can redistribute it and/or
12+
modify it under the terms of the GNU Lesser General Public
13+
License as published by the Free Software Foundation; either
14+
version 2.1 of the License, or (at your option) any later version.
15+
16+
This library is distributed in the hope that it will be useful,
17+
but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19+
Lesser General Public License for more details.
20+
21+
You should have received a copy of the GNU Lesser General Public
22+
License along with this library; if not, write to the Free Software
23+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

keywords.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#######################################
2+
# Coloring Map For HIDPowerDevice
3+
#######################################
4+
5+
#######################################
6+
# Datatypes (KEYWORD1)
7+
#######################################
8+
9+
HIDPowerDevice KEYWORD1
10+
11+
#######################################
12+
# Methods and Functions (KEYWORD2)
13+
#######################################
14+
15+
begin KEYWORD2
16+
#write KEYWORD2
17+
#press KEYWORD2
18+
#release KEYWORD2
19+
#releaseAll KEYWORD2
20+
21+
#######################################
22+
# Constants (LITERAL1)
23+
#######################################
24+

library.properties

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=HIDPowerDevice
2+
version=1.0.0
3+
author=abratchik
4+
maintainer=Alex Bratchik <[email protected]>
5+
sentence=Allows an Arduino/Genuino board with USB capabilites to act as a HID-compliant Power Device.
6+
paragraph=This library plugs on the HID library. It can be used with or without other HID-based libraries (Mouse, Keyboard, Gamepad etc)
7+
category=Device Control
8+
url=https://www.arduino.cc/en/Reference/HID
9+
architectures=*

src/HID/HID.cpp

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/*
2+
Copyright (c) 2015, Arduino LLC
3+
Original code (pre-library): Copyright (c) 2011, Peter Barrett
4+
5+
Permission to use, copy, modify, and/or distribute this software for
6+
any purpose with or without fee is hereby granted, provided that the
7+
above copyright notice and this permission notice appear in all copies.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10+
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11+
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
12+
BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
13+
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
14+
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
15+
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16+
SOFTWARE.
17+
*/
18+
19+
#include "HID.h"
20+
21+
#if defined(USBCON)
22+
23+
HID_& HID()
24+
{
25+
static HID_ obj;
26+
return obj;
27+
}
28+
29+
int HID_::getInterface(uint8_t* interfaceCount)
30+
{
31+
*interfaceCount += 1; // uses 1
32+
HIDDescriptor hidInterface = {
33+
D_INTERFACE(pluggedInterface, 2, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE),
34+
D_HIDREPORT(descriptorSize),
35+
D_ENDPOINT(USB_ENDPOINT_IN(HID_TX), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x14),
36+
D_ENDPOINT(USB_ENDPOINT_OUT(HID_RX), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x0A)
37+
};
38+
return USB_SendControl(0, &hidInterface, sizeof(hidInterface));
39+
}
40+
41+
int HID_::getDescriptor(USBSetup& setup)
42+
{
43+
// Check if this is a HID Class Descriptor request
44+
if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }
45+
if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; }
46+
47+
// In a HID Class Descriptor wIndex cointains the interface number
48+
if (setup.wIndex != pluggedInterface) { return 0; }
49+
50+
int total = 0;
51+
HIDSubDescriptor* node;
52+
for (node = rootNode; node; node = node->next) {
53+
int res = USB_SendControl(TRANSFER_PGM, node->data, node->length);
54+
if (res == -1)
55+
return -1;
56+
total += res;
57+
}
58+
59+
// Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol
60+
// due to the USB specs, but Windows and Linux just assumes its in report mode.
61+
protocol = HID_REPORT_PROTOCOL;
62+
63+
return total;
64+
}
65+
66+
uint8_t HID_::getShortName(char *name)
67+
{
68+
name[0] = 'H';
69+
name[1] = 'I';
70+
name[2] = 'D';
71+
name[3] = 'A' + (descriptorSize & 0x0F);
72+
name[4] = 'A' + ((descriptorSize >> 4) & 0x0F);
73+
return 5;
74+
}
75+
76+
void HID_::AppendDescriptor(HIDSubDescriptor *node)
77+
{
78+
if (!rootNode) {
79+
rootNode = node;
80+
} else {
81+
HIDSubDescriptor *current = rootNode;
82+
while (current->next) {
83+
current = current->next;
84+
}
85+
current->next = node;
86+
}
87+
descriptorSize += node->length;
88+
}
89+
90+
int HID_::SendReport(uint8_t id, const void* data, int len)
91+
{
92+
auto ret = USB_Send(HID_TX, &id, 1);
93+
if (ret < 0) return ret;
94+
auto ret2 = USB_Send(HID_TX | TRANSFER_RELEASE, data, len);
95+
if (ret2 < 0) return ret2;
96+
return ret + ret2;
97+
}
98+
99+
bool HID_::setup(USBSetup& setup)
100+
{
101+
if (pluggedInterface != setup.wIndex) {
102+
return false;
103+
}
104+
105+
uint8_t request = setup.bRequest;
106+
uint8_t requestType = setup.bmRequestType;
107+
108+
if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
109+
{
110+
if (request == HID_GET_REPORT) {
111+
// TODO: HID_GetReport();
112+
return true;
113+
}
114+
if (request == HID_GET_PROTOCOL) {
115+
// TODO: Send8(protocol);
116+
return true;
117+
}
118+
if (request == HID_GET_IDLE) {
119+
// TODO: Send8(idle);
120+
}
121+
}
122+
123+
if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
124+
{
125+
if (request == HID_SET_PROTOCOL) {
126+
// The USB Host tells us if we are in boot or report mode.
127+
// This only works with a real boot compatible device.
128+
protocol = setup.wValueL;
129+
return true;
130+
}
131+
if (request == HID_SET_IDLE) {
132+
idle = setup.wValueL;
133+
return true;
134+
}
135+
if (request == HID_SET_REPORT)
136+
{
137+
//uint8_t reportID = setup.wValueL;
138+
//uint16_t length = setup.wLength;
139+
//uint8_t data[length];
140+
// Make sure to not read more data than USB_EP_SIZE.
141+
// You can read multiple times through a loop.
142+
// The first byte (may!) contain the reportID on a multreport.
143+
//USB_RecvControl(data, length);
144+
}
145+
}
146+
147+
return false;
148+
}
149+
150+
HID_::HID_(void) : PluggableUSBModule(2, 1, epType),
151+
rootNode(NULL), descriptorSize(0),
152+
protocol(HID_REPORT_PROTOCOL), idle(1)
153+
{
154+
epType[0] = EP_TYPE_INTERRUPT_IN;
155+
epType[1] = EP_TYPE_INTERRUPT_OUT;
156+
PluggableUSB().plug(this);
157+
}
158+
159+
int HID_::begin(void)
160+
{
161+
return 0;
162+
}
163+
164+
#endif /* if defined(USBCON) */

src/HID/HID.h

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
Copyright (c) 2015, Arduino LLC
3+
Original code (pre-library): Copyright (c) 2011, Peter Barrett
4+
5+
Permission to use, copy, modify, and/or distribute this software for
6+
any purpose with or without fee is hereby granted, provided that the
7+
above copyright notice and this permission notice appear in all copies.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10+
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11+
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
12+
BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
13+
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
14+
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
15+
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16+
SOFTWARE.
17+
*/
18+
19+
#ifndef HID_h
20+
#define HID_h
21+
22+
#include <stdint.h>
23+
#include <Arduino.h>
24+
#include "PluggableUSB.h"
25+
26+
#if defined(USBCON)
27+
28+
#define _USING_HID
29+
30+
// HID 'Driver'
31+
// ------------
32+
#define HID_GET_REPORT 0x01
33+
#define HID_GET_IDLE 0x02
34+
#define HID_GET_PROTOCOL 0x03
35+
#define HID_SET_REPORT 0x09
36+
#define HID_SET_IDLE 0x0A
37+
#define HID_SET_PROTOCOL 0x0B
38+
39+
#define HID_HID_DESCRIPTOR_TYPE 0x21
40+
#define HID_REPORT_DESCRIPTOR_TYPE 0x22
41+
#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23
42+
43+
// HID subclass HID1.11 Page 8 4.2 Subclass
44+
#define HID_SUBCLASS_NONE 0
45+
#define HID_SUBCLASS_BOOT_INTERFACE 1
46+
47+
// HID Keyboard/Mouse bios compatible protocols HID1.11 Page 9 4.3 Protocols
48+
#define HID_PROTOCOL_NONE 0
49+
#define HID_PROTOCOL_KEYBOARD 1
50+
#define HID_PROTOCOL_MOUSE 2
51+
52+
// Normal or bios protocol (Keyboard/Mouse) HID1.11 Page 54 7.2.5 Get_Protocol Request
53+
// "protocol" variable is used for this purpose.
54+
#define HID_BOOT_PROTOCOL 0
55+
#define HID_REPORT_PROTOCOL 1
56+
57+
// HID Request Type HID1.11 Page 51 7.2.1 Get_Report Request
58+
#define HID_REPORT_TYPE_INPUT 1
59+
#define HID_REPORT_TYPE_OUTPUT 2
60+
#define HID_REPORT_TYPE_FEATURE 3
61+
62+
#define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface
63+
#define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT)
64+
#define HID_ENDPOINT_INT (HID_FIRST_ENDPOINT)
65+
#define HID_ENDPOINT_OUT (HID_FIRST_ENDPOINT+1)
66+
67+
#define HID_TX HID_ENDPOINT_INT
68+
#define HID_RX HID_ENDPOINT_OUT //++ EP HID_RX for ease of use with USB_Available & USB_Rec
69+
70+
typedef struct
71+
{
72+
uint8_t len; // 9
73+
uint8_t dtype; // 0x21
74+
uint8_t addr;
75+
uint8_t versionL; // 0x101
76+
uint8_t versionH; // 0x101
77+
uint8_t country;
78+
uint8_t desctype; // 0x22 report
79+
uint8_t descLenL;
80+
uint8_t descLenH;
81+
} HIDDescDescriptor;
82+
83+
typedef struct
84+
{
85+
InterfaceDescriptor hid;
86+
HIDDescDescriptor desc;
87+
EndpointDescriptor in;
88+
EndpointDescriptor out; //added
89+
} HIDDescriptor;
90+
91+
class HIDSubDescriptor {
92+
public:
93+
HIDSubDescriptor *next = NULL;
94+
HIDSubDescriptor(const void *d, const uint16_t l) : data(d), length(l) { }
95+
96+
const void* data;
97+
const uint16_t length;
98+
};
99+
100+
class HID_ : public PluggableUSBModule
101+
{
102+
public:
103+
HID_(void);
104+
int begin(void);
105+
int SendReport(uint8_t id, const void* data, int len);
106+
void AppendDescriptor(HIDSubDescriptor* node);
107+
108+
protected:
109+
// Implementation of the PluggableUSBModule
110+
int getInterface(uint8_t* interfaceCount);
111+
int getDescriptor(USBSetup& setup);
112+
bool setup(USBSetup& setup);
113+
uint8_t getShortName(char* name);
114+
115+
private:
116+
uint8_t epType[2];
117+
118+
HIDSubDescriptor* rootNode;
119+
uint16_t descriptorSize;
120+
121+
uint8_t protocol;
122+
uint8_t idle;
123+
};
124+
125+
// Replacement for global singleton.
126+
// This function prevents static-initialization-order-fiasco
127+
// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use
128+
HID_& HID();
129+
130+
#define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0x21, 1, 0x22, lowByte(length), highByte(length) }
131+
132+
#endif // USBCON
133+
134+
#endif // HID_h

0 commit comments

Comments
 (0)