-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvrpn_DreamCheeky.C
123 lines (103 loc) · 3.69 KB
/
vrpn_DreamCheeky.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// vrpn_dreamcheeky.C: VRPN driver for Dream Cheeky USB roll-up drum kit
#include "vrpn_DreamCheeky.h"
#if defined(VRPN_USE_HID)
// USB vendor and product IDs for the models we support
static const vrpn_uint16 DREAMCHEEKY_VENDOR = 6465;
static const vrpn_uint16 USB_ROLL_UP_DRUM_KIT = 32801;
vrpn_DreamCheeky::vrpn_DreamCheeky(vrpn_HidAcceptor *filter, const char *name, vrpn_Connection *c)
: _filter(filter)
, vrpn_HidInterface(_filter)
, vrpn_BaseClass(name, c)
{
}
vrpn_DreamCheeky::~vrpn_DreamCheeky()
{
delete _filter;
}
void vrpn_DreamCheeky::reconnect()
{
vrpn_HidInterface::reconnect();
}
void vrpn_DreamCheeky::on_data_received(size_t bytes, vrpn_uint8 *buffer)
{
decodePacket(bytes, buffer);
}
vrpn_DreamCheeky_Drum_Kit::vrpn_DreamCheeky_Drum_Kit(const char *name, vrpn_Connection *c,
bool debounce)
: vrpn_DreamCheeky(_filter = new vrpn_HidProductAcceptor(DREAMCHEEKY_VENDOR, USB_ROLL_UP_DRUM_KIT), name, c)
, vrpn_Button(name, c)
, d_debounce(debounce)
{
vrpn_Button::num_buttons = 6;
// Initialize the state of all the buttons
memset(buttons, 0, sizeof(buttons));
memset(lastbuttons, 0, sizeof(lastbuttons));
}
void vrpn_DreamCheeky_Drum_Kit::mainloop()
{
update();
server_mainloop();
vrpn_gettimeofday(&_timestamp, NULL);
report_changes();
vrpn_Button::server_mainloop();
}
void vrpn_DreamCheeky_Drum_Kit::report(void) {
vrpn_Button::timestamp = _timestamp;
vrpn_Button::report_changes();
}
void vrpn_DreamCheeky_Drum_Kit::report_changes(void) {
vrpn_Button::timestamp = _timestamp;
vrpn_Button::report_changes();
}
void vrpn_DreamCheeky_Drum_Kit::decodePacket(size_t bytes, vrpn_uint8 *buffer)
{
// The reports are each 8 bytes long. Since there is only one type of
// report for this device, the report type is not included (stripped by
// the HIDAPI driver). The bytes are 8 identical reports.
// There is one byte per report, and it holds a binary encoding of
// the buttons. Button 0 is in the LSB, and the others proceed up
// the bit chain. Parse each report and then send any changes on.
// need to send between each report so we don't miss a button press/release
// all in one packet.
size_t i, r;
// Truncate the count to an even number of 8 bytes. This will
// throw out any partial reports (which is not necessarily what
// we want, because this will start us off parsing at the wrong
// place if the rest of the report comes next, but it is not
// clear how to handle that cleanly).
bytes -= (bytes % 8);
// Decode all full reports, each of which is 8 bytes long.
for (i = 0; i < (bytes / 8); i++) {
// If we're debouncing the buttons, then we set the button
// to "pressed" if it has 4 or more pressed events in the
// set of 8 and to "released" if it has less than 4.
if (d_debounce) {
int btn;
for (btn = 0; btn < vrpn_Button::num_buttons; btn++) {
unsigned count = 0;
vrpn_uint8 mask = 1 << btn;
for (r = 0; r < 8; r++) { // Skip the all-zeroes byte
vrpn_uint8 *report = buffer + 9*i + r;
count += ((*report & mask) != 0);
}
buttons[btn] = (count >= 4);
vrpn_gettimeofday(&_timestamp, NULL);
report_changes();
}
// If we're not debouncing, then we report each button event
// independently.
}else {
for (r = 0; r < 8; r++) { // Skip the all-zeroes byte
vrpn_uint8 *report = buffer + 9*i + r;
int btn;
for (btn = 0; btn < vrpn_Button::num_buttons; btn++) {
vrpn_uint8 mask = 1 << btn;
buttons[btn] = ((*report & mask) != 0);
}
vrpn_gettimeofday(&_timestamp, NULL);
report_changes();
}
}
}
}
#endif