Skip to content

Commit be540c5

Browse files
committed
add HidDescriptorHelper.h
HidDescriptorHelper makes it easier to construct USB HID device descriptors using many enums to descrive the structure.
1 parent 775556f commit be540c5

File tree

2 files changed

+209
-1
lines changed

2 files changed

+209
-1
lines changed

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ paragraph=Replaces the main logic board in the Gravis Phoenix with an Arduino.
77
category=Other
88
url=https://github.com/BinaryMan32/phoenix-arduino
99
architectures=avr
10-
includes=hc165.h,Potentiometer.h,Fraction.h
10+
includes=hc165.h,Potentiometer.h,Fraction.h,HidDescriptorHelper.h

src/HidDescriptorHelper.h

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
#ifndef PHOENIX_ARDUINO_HIDDESCRIPTORHELPER_H
2+
#define PHOENIX_ARDUINO_HIDDESCRIPTORHELPER_H
3+
4+
namespace usb {
5+
namespace hid {
6+
/*
7+
* Main, Global, and Local are types of usb HID elements, most of which
8+
* include an associated value, this size of which is specified using the
9+
* | operator as follows:
10+
* Global::UsagePage | 1, usage::Page::GenericDesktop
11+
* This is a UsagePage with a size of 1 which has a value of GenericDesktop.
12+
*
13+
* See http://www.usb.org/developers/hidpage/HID1_11.pdf
14+
*/
15+
16+
enum class Main : u8
17+
{
18+
Input = 0x8, // See DataBits enum for values
19+
Output = 0x9, // See DataBits enum for values
20+
Collection = 0xa, // See Collection enum for values
21+
Feature = 0xb, // See DataBits enum for values
22+
EndCollection = 0xc, // No values, size always 0
23+
};
24+
25+
enum class Global : u8
26+
{
27+
UsagePage = 0x0, // See usage::Page for values
28+
LogicalMinimum = 0x1,
29+
LogicalMaximum = 0x2,
30+
PhysicalMinumum = 0x3,
31+
PhysicalMaximum = 0x4,
32+
UnitExponent = 0x5,
33+
Unit = 0x6,
34+
ReportSize = 0x7, // value is size of each element in bits
35+
ReportID = 0x8,
36+
ReportCount = 0x9, // value is the number of elements
37+
Push = 0xa,
38+
Pop = 0xb,
39+
};
40+
41+
enum class Local : u8
42+
{
43+
Usage = 0x0, // see appropriate sub-namespace of usage
44+
// based on active Global::UsagePage
45+
UsageMinimum = 0x1,
46+
UsageMaximum = 0x2,
47+
DesignatorIndex = 0x3,
48+
DesignatorMinimum = 0x4,
49+
DesignatorMaximum = 0x5,
50+
StringIndex = 0x7,
51+
StringMinimum = 0x8,
52+
StringMaximum = 0x9,
53+
Delimiter = 0xa,
54+
};
55+
56+
namespace detail {
57+
/*
58+
* Helper function to use in overloaded operators which construct an item in the
59+
* USB HID descriptor by combining tag, type and size.
60+
*/
61+
constexpr u8 encodeItemSize(int size)
62+
{
63+
return (size == 1 || size == 2) ? size : ((size == 4) ? 3 : 0);
64+
}
65+
66+
enum class ItemType : u8
67+
{
68+
Main = 0x00,
69+
Global = 0x01,
70+
Local = 0x02,
71+
};
72+
73+
/*
74+
* Constructs an 8 bit item from:
75+
* 4 bits of u8 tag
76+
* 2 bits of ItemType type
77+
* 2 bits of int size encoded by encodeItemSize()
78+
*/
79+
constexpr u8 makeItem(u8 tag, ItemType type, int size)
80+
{
81+
return (tag << 4) | (static_cast<u8>(type) << 2) | encodeItemSize(size);
82+
}
83+
} // namespace detail
84+
85+
/*
86+
* Allows user to create an item by or-ing the enum with the item value's size.
87+
* Since the item tags are strongly typed enums, users can't forget to or in the
88+
* type because the enums can't be implictly converted to a u8.
89+
*/
90+
constexpr u8 operator | (Main tag, int size)
91+
{
92+
return detail::makeItem(static_cast<u8>(tag), detail::ItemType::Main, size);
93+
}
94+
95+
/*
96+
* Allows user to create an item by or-ing the enum with the item value's size.
97+
* Since the item tags are strongly typed enums, users can't forget to or in the
98+
* type because the enums can't be implictly converted to a u8.
99+
*/
100+
constexpr u8 operator | (Global tag, int size)
101+
{
102+
return detail::makeItem(static_cast<u8>(tag), detail::ItemType::Global, size);
103+
}
104+
105+
/*
106+
* Allows user to create an item by or-ing the enum with the item value's size.
107+
* Since the item tags are strongly typed enums, users can't forget to or in the
108+
* type because the enums can't be implictly converted to a u8.
109+
*/
110+
constexpr u8 operator | (Local tag, int size)
111+
{
112+
return detail::makeItem(static_cast<u8>(tag), detail::ItemType::Local, size);
113+
}
114+
115+
// Bits used in constructing values of Main::Input, Main::Output, and Main::Feature
116+
enum DataBits
117+
{
118+
Constant = 0x01, // Data if not set
119+
Variable = 0x02, // Array if not set
120+
Relative = 0x04, // Absolute if not set
121+
};
122+
123+
// Values of Main::Collection
124+
enum Collection
125+
{
126+
Physical = 0x00,
127+
Application = 0x01,
128+
Logical = 0x02,
129+
Report = 0x03,
130+
NamedArray = 0x04,
131+
UsageSwitch = 0x05,
132+
UsageModifier = 0x06,
133+
};
134+
135+
/*
136+
* Global::UsagePage will have a value from usage::Page.
137+
* The usage page is effectively a namespace for Local::Usage values,
138+
* see the comments on each Page value for details.
139+
*
140+
* See http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
141+
*/
142+
namespace usage {
143+
enum Page
144+
{
145+
GenericDesktop = 0x01, // See generic_desktop namespace
146+
Simulation = 0x02,
147+
VR = 0x03,
148+
Sport = 0x04,
149+
Game = 0x05,
150+
GenericDevice = 0x06,
151+
Keyboard = 0x07,
152+
LED = 0x08,
153+
Button = 0x09,
154+
Ordinal = 0x0a,
155+
Telephony = 0x0b,
156+
Consumer = 0x0c,
157+
Digitizer = 0x0d,
158+
};
159+
160+
namespace generic_desktop {
161+
162+
enum Application
163+
{
164+
Pointer = 0x01,
165+
Mouse = 0x02,
166+
Joystick = 0x04,
167+
GamePad = 0x05,
168+
Keyboard = 0x06,
169+
Keypad = 0x07,
170+
MultiAxis = 0x08,
171+
Tablet = 0x09,
172+
};
173+
174+
enum Axis
175+
{
176+
X = 0x30,
177+
Y = 0x31,
178+
Z = 0x32,
179+
Rx = 0x33,
180+
Ry = 0x34,
181+
Rz = 0x35,
182+
};
183+
184+
enum Miscellaneous
185+
{
186+
Slider = 0x36,
187+
Dial = 0x37,
188+
Wheel = 0x38,
189+
HatSwitch = 0x39,
190+
MotionWakeup = 0x3c,
191+
Start = 0x3d,
192+
Select = 0x3e,
193+
};
194+
195+
enum DirectionPad
196+
{
197+
Up = 0x90,
198+
Down = 0x91,
199+
Right = 0x92,
200+
Left = 0x93,
201+
};
202+
203+
} // namespace generic_desktop
204+
} // namespace usage
205+
} // namespace hid
206+
} // namespace usb
207+
208+
#endif /* PHOENIX_ARDUINO_HIDDESCRIPTORHELPER_H */

0 commit comments

Comments
 (0)