-
Notifications
You must be signed in to change notification settings - Fork 94
/
Copy pathViveTrackerController.h
189 lines (161 loc) · 5.57 KB
/
ViveTrackerController.h
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*
* ViveTrackerController.h
*
* Created on: 05.04.2017
* Author: matzman
*/
#ifndef VIVETRACKERCONTROLLER_H_
#define VIVETRACKERCONTROLLER_H_
#include <hidboot.h>
/* Vive Tracker Button Bitmasks */
#define VIVETRACKER_BUTTON_TRIGGER (1 << 0)
#define VIVETRACKER_BUTTON_GRIP (1 << 1)
#define VIVETRACKER_BUTTON_MENU (1 << 2)
#define VIVETRACKER_BUTTON_SYSTEM (1 << 3)
#define VIVETRACKER_BUTTON_PADTRIGGERED (1 << 4)
#define VIVETRACKER_BUTTON_PADTOUCHED (1 << 5)
#define VIVETRACKER_LPF_DEFAULT 0
#define VIVETRACKER_LPF_184HZ 0
#define VIVETRACKER_LPF_5HZ 1
#define VIVETRACKER_LPF_10HZ 2
#define VIVETRACKER_LPF_20HZ 3
/*
* The format of the USB HID feature reports is unfortunately not correct in HTC's documentation.
* Fortunately Peter S. Hollander was able to find out the correct format of the feature reports,
* and he was kind enough to share the details on his blog:
* http://www.talariavr.com/blog/vive-tracker-initial-documentation/
*/
/**
* \struct Vive Tracker Feature Report 0xB3
*/
struct __attribute__((__packed__)) ViveTrackerFeatureReportB3 {
uint8_t address = 0xB3;
uint8_t payloadSize = 4;
uint8_t hostType;
uint8_t chargeEnable;
uint8_t osType;
uint8_t lpfConfig;
ViveTrackerFeatureReportB3(uint8_t hostType = 3, uint8_t chargeEnable = 0, uint8_t osType = 0, uint8_t lpfConfig = VIVETRACKER_LPF_DEFAULT)
: hostType(hostType), chargeEnable(chargeEnable), osType(osType), lpfConfig(lpfConfig) {}
};
/**
* \struct Vive Tracker Feature Report 0xB4
*/
struct __attribute__((__packed__)) ViveTrackerFeatureReportB4 {
uint8_t address = 0xB4;
uint8_t payloadSize = 10;
uint8_t tagIndex = 0;
uint8_t buttons;
int16_t padX;
int16_t padY;
uint16_t trigger;
uint16_t batteryLevel;
ViveTrackerFeatureReportB4(uint8_t buttons = 0, int16_t padX = 0, int16_t padY = 0, uint16_t trigger = 0, uint16_t batteryLevel = 0)
: buttons(buttons), padX(padX), padY(padY), trigger(trigger), batteryLevel(batteryLevel) {}
} ;
/**
* \class Customized HID Boot definition for Vive Tracker
*/
class ViveTrackerBoot : public HIDBoot<HID_PROTOCOL_NONE, HID_NONE_SUBCLASS> {
public:
using HIDBoot<HID_PROTOCOL_NONE, HID_NONE_SUBCLASS>::HIDBoot;
virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed) override {
auto retval = HIDBoot<HID_PROTOCOL_NONE, HID_NONE_SUBCLASS>::Init(parent, port, lowspeed);
if (!retval) {
_isConnected = true;
}
return retval;
}
virtual uint32_t Release() override {
auto retval = HIDBoot<HID_PROTOCOL_NONE, HID_NONE_SUBCLASS>::Release();
if (!retval) {
_isConnected = false;
}
return retval;
}
virtual uint32_t Poll() override {
return 0; // The Vive Controller does not send any data
}
bool isConnected() {
return _isConnected;
}
private:
bool _isConnected = false;
};
/**
* \class Vive Tracker Controller
*
* Represents the public API for the Vive Tracker
*/
class ViveTrackerController {
public:
ViveTrackerController(USBHost &usb, uint8_t hostType = 3, uint8_t chargeEnabled = 0, uint8_t osType = 0)
: usb(usb), hostTracker(&usb), _hostType(hostType), _chargeEnabled(chargeEnabled), _osType(osType) {}
/**
* Returns whether a vive tracker is connected and initialized.
*/
bool isConnected() {
return hostTracker.isConnected() && _isInitialized;
}
/**
* Sends the accessory state to the vive tracker.
*
* Regarding the trigger parameter: HTC's documentations states that a 16-bit value is used to represent the trigger.
* But the current firmware only uses an 8-bit value.
*
* \param buttons Bitmask representing the pressed buttons.
* \param padX X-axis of the trackpad (from -32768 to 32767)
* \param padY Y-axis of the trackpad (from -32768 to 32767)
* \param trigger Trigger state (from 0 to 255)
* \param batteryLevel Currently not used, should be set to 0.
* \param lowspeed USB device speed.
*
* \return 0 on success, error code otherwise.
*/
uint32_t setTrackerStatus(uint8_t buttons = 0, int16_t padX = 0, int16_t padY = 0, uint8_t trigger = 0, uint16_t batteryLevel = 0) {
if (isConnected()) {
ViveTrackerFeatureReportB4 report(buttons, padX, padY, trigger << 8, batteryLevel);
return hostTracker.SetReport(0, 2, 3, 0, sizeof(ViveTrackerFeatureReportB4), (uint8_t*)&report);
}
return -1;
}
uint32_t setChargeEnabled(uint8_t enabled, bool sendUsbReport = true) {
_chargeEnabled = enabled;
if (sendUsbReport) {
return sendUsbReportB3(_hostType, _chargeEnabled, _osType, VIVETRACKER_LPF_DEFAULT);
} else {
return 0;
}
}
uint32_t setLpfConfig(uint8_t lpfConfig) {
return sendUsbReportB3(_hostType, _chargeEnabled, _osType, lpfConfig);
}
/**
* Process usb and vive tracker controller tasks.
*
* Should be repeatedly called in the main-loop.
*/
void Task() {
usb.Task();
if (hostTracker.isConnected() && !_isInitialized && _initConnection() == 0) {
_isInitialized = true;
} else if (!hostTracker.isConnected()) {
_isInitialized = false;
}
}
private:
USBHost &usb;
ViveTrackerBoot hostTracker;
bool _isInitialized = false;
uint8_t _hostType;
uint8_t _chargeEnabled;
uint8_t _osType;
uint32_t _initConnection() {
return sendUsbReportB3(_hostType, _chargeEnabled, _osType, VIVETRACKER_LPF_DEFAULT);
}
uint32_t sendUsbReportB3(uint8_t hostType, uint8_t chargeEnabled, uint8_t osType, uint8_t lpfConfig) {
ViveTrackerFeatureReportB3 report(hostType, chargeEnabled, osType, lpfConfig);
return hostTracker.SetReport(0, 2, 3, 0, sizeof(ViveTrackerFeatureReportB3), (uint8_t*)&report);
}
};
#endif /* VIVETRACKERCONTROLLER_H_ */