vrpn 07.35
Virtual Reality Peripheral Network
Loading...
Searching...
No Matches
vrpn_Contour.C
Go to the documentation of this file.
1// vrpn_Contour.C: VRPN driver for Contour Design devices
2
3#include <stdio.h> // for fprintf, stderr, NULL
4#include <string.h> // for memset
5#include <math.h> // for fabs
6
7#include "vrpn_Contour.h"
9
10#if defined(VRPN_USE_HID)
11
12static const double POLL_INTERVAL = 1e+6 / 30.0; // If we have not heard, ask.
13
14// USB vendor and product IDs for the models we support
15static const vrpn_uint16 CONTOUR_VENDOR = 0x0b33;
16static const vrpn_uint16 CONTOUR_SHUTTLEXPRESS = 0x0020;
17static const vrpn_uint16 CONTOUR_SHUTTLEPROV2 = 0x0030;
18
19static void normalize_axis(const unsigned int value, const short deadzone, const vrpn_float64 scale, vrpn_float64& channel) {
20 channel = (static_cast<float>(value) - 128.0f);
21 if (fabs(channel) < deadzone)
22 {
23 channel = 0.0f;
24 }
25 else
26 {
27 channel /= 128.0f;
28 }
29 channel *= scale;
30 if (channel < -1.0) { channel = -1.0; }
31 if (channel > 1.0) { channel = 1.0; }
32}
33
35 vrpn_uint16 vendor, vrpn_uint16 product)
36 : vrpn_BaseClass(name, c)
37 , vrpn_HidInterface(filter, vendor, product)
38 , _filter(filter)
39{
40 init_hid();
41
42 // We've not yet gotten a dial response.
43 _gotDial = false;
44}
45
47{
48 try {
49 delete _filter;
50 } catch (...) {
51 fprintf(stderr, "vrpn_Contour::~vrpn_Contour(): delete failed\n");
52 return;
53 }
54}
55
61
62void vrpn_Contour::on_data_received(size_t bytes, vrpn_uint8 *buffer)
63{
64 decodePacket(bytes, buffer);
65}
66
68{
69 return 0;
70}
71
72int vrpn_Contour::on_connect(void* /*thisPtr*/, vrpn_HANDLERPARAM /*p*/)
73{
74 return 0;
75}
76
78 : vrpn_Contour(new vrpn_HidProductAcceptor(CONTOUR_VENDOR, CONTOUR_SHUTTLEXPRESS), name, c, CONTOUR_VENDOR, CONTOUR_SHUTTLEXPRESS)
79 , vrpn_Analog(name, c)
80 , vrpn_Button_Filter(name, c)
81 , vrpn_Dial(name, c)
82{
86
87 // Initialize the state of all the analogs, buttons, and dials
88 _lastDial = 0;
89 memset(buttons, 0, sizeof(buttons));
90 memset(lastbuttons, 0, sizeof(lastbuttons));
91 memset(channel, 0, sizeof(channel));
92 memset(last, 0, sizeof(last));
93}
94
96{
97 update();
99 struct timeval current_time;
100 vrpn_gettimeofday(&current_time, NULL);
101 if (vrpn_TimevalDuration(current_time, _timestamp) > POLL_INTERVAL ) {
102 _timestamp = current_time;
104
105 // Call the server_mainloop on our unique base class.
107 }
108}
109
110void vrpn_Contour_ShuttleXpress::report(vrpn_uint32 class_of_service) {
112 {
114 }
116 {
118 }
119 if (vrpn_Dial::num_dials > 0)
120 {
122 }
123
125 {
126 vrpn_Analog::report(class_of_service);
127 }
129 {
131 }
132 if (vrpn_Dial::num_dials > 0)
133 {
135 }
136}
137
138void vrpn_Contour_ShuttleXpress::report_changes(vrpn_uint32 class_of_service) {
140 {
142 }
144 {
146 }
147 if (vrpn_Dial::num_dials > 0)
148 {
150 }
151
153 {
154 vrpn_Analog::report_changes(class_of_service);
155 }
157 {
159 }
160 if (vrpn_Dial::num_dials > 0)
161 {
163 }
164}
165
166void vrpn_Contour_ShuttleXpress::decodePacket(size_t bytes, vrpn_uint8 *buffer) {
167 // Decode all full reports, each of which is 5 bytes long.
168 // Because there is only one type of report, the initial "0" report-type
169 // byte is removed by the HIDAPI driver.
170 if (bytes == 5) {
171 if (!_gotDial) {
172 _gotDial = true;
173 }
174 else {
175 dials[0] = static_cast<vrpn_int8>(buffer[1] - _lastDial) / 10.0;
176 }
177 _lastDial = buffer[1];
178
179 // analog (1st byte): 0 center, 1..7 right, -1..-7 left
180 normalize_axis((unsigned int)((static_cast<float>(static_cast<vrpn_int8>(buffer[0])) * 128.0f / 7.0f) + 128.0f), 0, 1.0f, channel[0]);
181 // Second analog integrates the dial value.
182 channel[1] += dials[0];
183
184 vrpn_uint8 value;
185 // buttons (4th byte):
186 value = buffer[3];
187 for (int btn = 0; btn < 4; btn++) {
188 vrpn_uint8 mask = static_cast<vrpn_uint8>((1 << (btn % 8)) << 4);
189 buttons[btn] = ((value & mask) != 0);
190 }
191 // buttons (5th byte):
192 value = buffer[4];
193 for (int btn = 0; btn < 1; btn++) {
194 vrpn_uint8 mask = static_cast<vrpn_uint8>(1 << (btn % 8));
195 buttons[btn + 4] = ((value & mask) != 0);
196 }
197 } else {
198 fprintf(stderr, "vrpn_Contour_ShuttleXpress: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
199 }
200}
201
202
204 : vrpn_Contour(new vrpn_HidProductAcceptor(CONTOUR_VENDOR, CONTOUR_SHUTTLEPROV2), name, c, CONTOUR_VENDOR, CONTOUR_SHUTTLEPROV2)
205 , vrpn_Analog(name, c)
206 , vrpn_Button_Filter(name, c)
207 , vrpn_Dial(name, c)
208{
212
213 // Initialize the state of all the analogs, buttons, and dials
214 _lastDial = 0;
215 memset(buttons, 0, sizeof(buttons));
216 memset(lastbuttons, 0, sizeof(lastbuttons));
217 memset(channel, 0, sizeof(channel));
218 memset(last, 0, sizeof(last));
219}
220
222{
223 update();
225 struct timeval current_time;
226 vrpn_gettimeofday(&current_time, NULL);
227 if (vrpn_TimevalDuration(current_time, _timestamp) > POLL_INTERVAL) {
228 _timestamp = current_time;
230
231 // Call the server_mainloop on our unique base class.
233 }
234}
235
236void vrpn_Contour_ShuttlePROv2::report(vrpn_uint32 class_of_service)
237{
239 {
241 }
243 {
245 }
246 if (vrpn_Dial::num_dials > 0)
247 {
249 }
250
252 {
253 vrpn_Analog::report(class_of_service);
254 }
256 {
258 }
259 if (vrpn_Dial::num_dials > 0)
260 {
262 }
263}
264
265void vrpn_Contour_ShuttlePROv2::report_changes(vrpn_uint32 class_of_service)
266{
268 {
270 }
272 {
274 }
275 if (vrpn_Dial::num_dials > 0)
276 {
278 }
279
281 {
282 vrpn_Analog::report_changes(class_of_service);
283 }
285 {
287 }
288 if (vrpn_Dial::num_dials > 0)
289 {
291 }
292}
293
294void vrpn_Contour_ShuttlePROv2::decodePacket(size_t bytes, vrpn_uint8 *buffer)
295{
296 // Print the report so we can figure out what is going on.
297/* for (size_t i = 0; i < bytes; i++) {
298 printf("%02x ", buffer[i]);
299 }
300 printf("\n");
301 return; */
302
303 // Decode all full reports, each of which is 5 bytes long.
304 // Because there is only one type of report, the initial "0" report-type
305 // byte is removed by the HIDAPI driver.
306 if (bytes == 5) {
307 if (!_gotDial) {
308 _gotDial = true;
309 }
310 else {
311 dials[0] = static_cast<vrpn_int8>(buffer[1] - _lastDial) / 10.0;
312 }
313 _lastDial = buffer[1];
314
315 // analog (1st byte): 0 center, 1..7 right, -1..-7 left
316 normalize_axis((unsigned int)((static_cast<float>(static_cast<vrpn_int8>(buffer[0])) * 128.0f / 7.0f) + 128.0f), 0, 1.0f, channel[0]);
317 // Second analog integrates the dial value.
318 channel[1] += dials[0];
319
320 // Top row of four buttons, from left to right: index[bit]
321 // 3[0], 3[1], 3[2], 3[3]
322 // Second row of 5 buttons, from left to right:
323 // 3[4], 3[5], 3[6], 3[7], 4[0]
324 // Four lower buttons, from left to right and then down to next row:
325 // 4[1], 4[2], 4[3], 4[4]
326 // Two black buttons, from left to right:
327 // 4[5], 4[6]
328 for (int btn = 0; btn <= 15; btn++) {
329 vrpn_uint8 *offset, mask;
330
331 offset = buffer + btn / 8 + 3;
332 mask = static_cast<vrpn_uint8>(1 << (btn % 8));
333
334 buttons[btn] = (*offset & mask) != 0;
335 }
336 }
337 else {
338 fprintf(stderr, "vrpn_Contour_ShuttlePROv2: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
339 }
340}
341
342// End of VRPN_USE_HID
343#endif
vrpn_float64 last[vrpn_CHANNEL_MAX]
Definition vrpn_Analog.h:39
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition vrpn_Analog.h:38
struct timeval timestamp
Definition vrpn_Analog.h:41
vrpn_int32 num_channel
Definition vrpn_Analog.h:40
virtual void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY, const struct timeval time=vrpn_ANALOG_NOW)
Send a report whether something has changed or not (for servers) Optionally, tell what time to stamp ...
Definition vrpn_Analog.C:94
virtual void report_changes(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY, const struct timeval time=vrpn_ANALOG_NOW)
Send a report only if something has changed (for servers) Optionally, tell what time to stamp the val...
Definition vrpn_Analog.C:71
int register_autodeleted_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
Registers a handler with the connection, and remembers to delete at destruction.
vrpn_Connection * d_connection
Connection that this object talks to.
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
Class from which all user-level (and other) classes that communicate with vrpn_Connections should der...
All button servers should derive from this class, which provides the ability to turn any of the butto...
Definition vrpn_Button.h:66
virtual void report_changes(void)
vrpn_int32 num_buttons
Definition vrpn_Button.h:48
struct timeval timestamp
Definition vrpn_Button.h:49
virtual void report_changes(void)
unsigned char lastbuttons[vrpn_BUTTON_MAX_BUTTONS]
Definition vrpn_Button.h:46
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition vrpn_Button.h:45
Generic connection class not specific to the transport mechanism.
virtual vrpn_int32 register_message_type(const char *name)
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
vrpn_Contour_ShuttlePROv2(const char *name, vrpn_Connection *c=0)
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
vrpn_Contour_ShuttleXpress(const char *name, vrpn_Connection *c=0)
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
virtual void decodePacket(size_t bytes, vrpn_uint8 *buffer)=0
virtual ~vrpn_Contour(void)
void on_data_received(size_t bytes, vrpn_uint8 *buffer)
Derived class reimplements this callback.
static int VRPN_CALLBACK on_last_disconnect(void *thisPtr, vrpn_HANDLERPARAM p)
static int VRPN_CALLBACK on_connect(void *thisPtr, vrpn_HANDLERPARAM p)
vrpn_uint8 _lastDial
vrpn_Contour(vrpn_HidAcceptor *filter, const char *name, vrpn_Connection *c=0, vrpn_uint16 vendor=0, vrpn_uint16 product=0)
struct timeval _timestamp
vrpn_HidAcceptor * _filter
void init_hid(void)
virtual void report_changes(void)
Definition vrpn_Dial.C:54
struct timeval timestamp
Definition vrpn_Dial.h:28
vrpn_float64 dials[vrpn_DIAL_MAX]
Definition vrpn_Dial.h:26
virtual void report(void)
Definition vrpn_Dial.C:82
vrpn_int32 num_dials
Definition vrpn_Dial.h:27
virtual void update()
Polls the device buffers and causes on_data_received callbacks if appropriate You NEED to call this f...
Accepts any device with the given vendor and product IDs.
This structure is what is passed to a vrpn_Connection message callback.
#define VRPN_SUPPRESS_EMPTY_OBJECT_WARNING()
const char * vrpn_dropped_last_connection
const char * vrpn_got_connection
#define POLL_INTERVAL
Definition vrpn_IDEA.C:26
unsigned long vrpn_TimevalDuration(struct timeval endT, struct timeval startT)
Return number of microseconds between startT and endT.
#define vrpn_gettimeofday
Definition vrpn_Shared.h:99