vrpn 07.35
Virtual Reality Peripheral Network
 
Loading...
Searching...
No Matches
vrpn_Xkeys.C
Go to the documentation of this file.
1// vrpn_Xkeys.C: VRPN driver for P.I. Engineering's X-Keys devices
2
3#include <stdio.h> // for fprintf, stderr, NULL
4#include <string.h> // for memset
5
6#include "vrpn_Xkeys.h"
7
9
10#if defined(VRPN_USE_HID)
11
12// USB vendor and product IDs for the models we support
13static const vrpn_uint16 XKEYS_VENDOR = 0x05F3;
14static const vrpn_uint16 XKEYS_DESKTOP = 0x0281;
15static const vrpn_uint16 XKEYS_JOG_AND_SHUTTLE = 0x0241;
16static const vrpn_uint16 XKEYS_PRO = 0x0291;
17static const vrpn_uint16 XKEYS_JOYSTICK = 0x0251;
18static const vrpn_uint16 XKEYS_XK3 = 0x042C;
19static const vrpn_uint16 XKEYS_JOG_AND_SHUTTLE12 = 0x0426;
20static const vrpn_uint16 XKEYS_JOG_AND_SHUTTLE68 = 0x045a;
21static const vrpn_uint16 XKEYS_JOYSTICK12 = 0x0429;
22
23vrpn_Xkeys::vrpn_Xkeys(vrpn_HidAcceptor *filter, const char *name,
24 vrpn_Connection *c, vrpn_uint16 vendor, vrpn_uint16 product,
25 bool toggle_light)
26 : vrpn_BaseClass(name, c)
28 , _filter(filter)
29 , _toggle_light(toggle_light)
30{
31 init_hid();
32}
33
35{
36 try {
37 delete _filter;
38 } catch (...) {
39 fprintf(stderr, "vrpn_Xkeys::~vrpn_Xkeys(): delete failed\n");
40 return;
41 }
42}
43
45 // Get notifications when clients connect and disconnect
48}
49
50void vrpn_Xkeys::on_data_received(size_t bytes, vrpn_uint8 *buffer)
51{
52 decodePacket(bytes, buffer);
53}
54
56{
57 vrpn_Xkeys *me = static_cast<vrpn_Xkeys *>(thisPtr);
58 if (me->_toggle_light) {
59 // Set light to red to indicate we have no active connections
60 me->setLEDs(On, Off);
61 }
62 return 0;
63}
64
66{
67 vrpn_Xkeys *me = static_cast<vrpn_Xkeys *>(thisPtr);
68
69 if (me->_toggle_light) {
70 // Set light to green to indicate we have an active connection
71 me->setLEDs(Off, On);
72 }
73 return 0;
74}
75
77{
78 vrpn_uint8 outputs[9] = {0};
79 switch (red) {
80 case Off: // do not set anything to 1 for off.
81 break;
82 case On:
83 case Flash:
84 outputs[8] |= 128;
85 break;
86 default: // For both on and flash, turn on (we don't know how to flash)
87 fprintf(stderr,"vrpn_Xkeys_v2::setLED(): Unrecognized state\n");
88 }
89 switch (green) {
90 case Off: // do not set anything to 1 for off.
91 break;
92 case On:
93 case Flash:
94 outputs[8] |= 64;
95 break;
96 default: // For both on and flash, turn on (we don't know how to flash)
97 fprintf(stderr,"vrpn_Xkeys_v2::setLED(): Unrecognized state\n");
98 }
99
100 // Send the combined command to turn on and off both red and green.
101 send_data(9, outputs);
102}
103
105{
106 vrpn_uint8 outputs[36] = {0};
107 outputs[1] = 0xb3;
108
109 // Send the red command.
110 outputs[2] = 7; // 6 = green LED, 7 = red LED
111 switch (red) {
112 case On: // do not set anything to 1 for off.
113 outputs[3] = 1; // 0 = off, 1 = on, 2 = flash
114 break;
115 case Flash: // do not set anything to 1 for off.
116 outputs[3] = 2; // 0 = off, 1 = on, 2 = flash
117 break;
118 case Off: // do not set anything to 1 for off.
119 outputs[3] = 0; // 0 = off, 1 = on, 2 = flash
120 break;
121 default: // Never heard of this state.
122 fprintf(stderr,"vrpn_Xkeys_v2::setLED(): Unrecognized state\n");
123 }
124 send_data(36, outputs);
125
126 // Send the green command.
127 outputs[2] = 6; // 6 = green LED, 7 = red LED
128 switch (green) {
129 case On: // do not set anything to 1 for off.
130 outputs[3] = 1; // 0 = off, 1 = on, 2 = flash
131 break;
132 case Flash: // do not set anything to 1 for off.
133 outputs[3] = 2; // 0 = off, 1 = on, 2 = flash
134 break;
135 case Off: // do not set anything to 1 for off.
136 outputs[3] = 0; // 0 = off, 1 = on, 2 = flash
137 break;
138 default: // Never heard of this state.
139 fprintf(stderr,"vrpn_Xkeys_v2::setLED(): Unrecognized state\n");
140 }
141 send_data(36, outputs);
142}
143
145 : vrpn_Xkeys_v1(_filter = new vrpn_HidProductAcceptor(XKEYS_VENDOR, XKEYS_DESKTOP), name, c, XKEYS_VENDOR, XKEYS_DESKTOP)
146 , vrpn_Button_Filter(name, c)
147{
148 // 21 buttons (don't forget about button 0)
150
151 // Initialize the state of all the buttons
152 memset(buttons, 0, sizeof(buttons));
153 memset(lastbuttons, 0, sizeof(lastbuttons));
154}
155
157{
158 update();
162
163 // Call the server_mainloop on our unique base class.
165}
166
172
178
179void vrpn_Xkeys_Desktop::decodePacket(size_t bytes, vrpn_uint8 *buffer)
180{
181 // Decode all full reports, each of which is 11 bytes long.
182 // Because there is only one type of report, the initial "0" report-type
183 // byte is removed by the HIDAPI driver.
184 for (size_t i = 0; i < bytes / 11; i++) {
185 vrpn_uint8 *report = buffer + (i * 11);
186
187 if (!(report[10] & 0x08)) {
188 // Apparently we got a corrupted report; skip this one.
189 fprintf(stderr, "vrpn_Xkeys_Desktop: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
190 continue;
191 }
192
193 // Decode the "programming switch"
194 buttons[0] = (report[10] & 0x10) != 0;
195
196 // Decode the other buttons into column-major order
197 for (int btn = 0; btn < 20; btn++) {
198 vrpn_uint8 *offset, mask;
199
200 offset = report + btn / 5;
201 mask = static_cast<vrpn_uint8>(1 << (btn % 5));
202
203 buttons[btn + 1] = (*offset & mask) != 0;
204 }
205 }
206}
207
209 : vrpn_Xkeys_v1(_filter = new vrpn_HidProductAcceptor(XKEYS_VENDOR, XKEYS_JOG_AND_SHUTTLE), name, c, XKEYS_VENDOR, XKEYS_JOG_AND_SHUTTLE)
210 , vrpn_Analog(name, c)
211 , vrpn_Button_Filter(name, c)
212 , vrpn_Dial(name, c)
213{
216 vrpn_Button::num_buttons = 59; // Don't forget button 0
217
218 // Initialize the state of all the analogs, buttons, and dials
219 _lastDial = 0;
220 memset(buttons, 0, sizeof(buttons));
221 memset(lastbuttons, 0, sizeof(lastbuttons));
222 memset(channel, 0, sizeof(channel));
223 memset(last, 0, sizeof(last));
224}
225
227{
228 update();
232
233 // Call the server_mainloop on our unique base class.
235}
236
246
256
257void vrpn_Xkeys_Jog_And_Shuttle::decodePacket(size_t bytes, vrpn_uint8 *buffer)
258{
259 // Decode all full reports.
260 // Full reports for all of the pro devices are 15 bytes long.
261 // Because there is only one type of report, the initial "0" report-type
262 // byte is removed by the HIDAPI driver, leaving 14 bytes.
263 // Also, it appears as though the
264 // remaining 14-byte command is split into two, one 8-byte that is sent
265 // first and then a 6-byte that is sent later. So we need to check the
266 // length of the packet to see which it is and then parse it appropriately.
267 if (bytes == 8) { // The first 8 bytes of a report (happens on Linux)
268
269 // Report jog dial as analog and dial
270 // Report shuttle knob as analog
271
272 // Double cast on channel 0 ensures negative values stay negative
273 channel[0] = static_cast<float>(static_cast<signed char>(buffer[0])) / 7.0;
274 channel[1] = static_cast<float>(buffer[1]);
275
276 // Do the unsigned/signed conversion at the last minute so the
277 // signed values work properly.
278 dials[0] = static_cast<vrpn_int8>(buffer[1] - _lastDial) / 256.0;
279
280 // Store the current dial position for the next delta
281 _lastDial = buffer[1];
282
283 // Decode the other buttons in column-major order. We skip the
284 // first three bytes, which record the joystick value or the
285 // shuttle/jog value (depending on device).
286 // This results in some gaps when using a shuttle or joystick model,
287 // but there really aren't any internally consistent numbering schemes.
288 // The first 35 buttons are in this report, the remaining 23 in the next.
289 for (int btn = 0; btn < 35; btn++) {
290 vrpn_uint8 *offset, mask;
291
292 offset = buffer + btn / 7 + 3;
293 mask = static_cast<vrpn_uint8>(1 << (btn % 7));
294
295 buttons[btn + 1] = (*offset & mask) != 0;
296 }
297
298 } else if (bytes == 6) { // The last 6 bytes of a report (happens on Linux)
299
300 if (!(buffer[5] & 0x08)) {
301 // Garbled report; skip it
302 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
303 return;
304 }
305
306 // Decode the "programming switch"
307 buttons[0] = (buffer[5] & 0x10) != 0;
308
309 // Decode the other buttons in column-major order.
310 // This results in some gaps when using a shuttle or joystick model,
311 // but there really aren't any internally consistent numbering schemes.
312 // The last 23 buttons are in this report, the remaining 23 in the next.
313 for (int btn = 35; btn < 58; btn++) {
314 vrpn_uint8 *offset, mask;
315 int local_btn = btn - 35;
316
317 offset = buffer + local_btn / 7;
318 mask = static_cast<vrpn_uint8>(1 << (local_btn % 7));
319
320 buttons[btn + 1] = (*offset & mask) != 0;
321 }
322
323 } else if (bytes == 14) { // A full report in one swoop (happens on Windows)
324 // Full reports for all of the pro devices are 15 bytes long.
325 // Because there is only one type of report, the initial "0" report-type
326 // byte is removed by the HIDAPI driver, leaving 14 bytes.
327 size_t i;
328 for (i = 0; i < bytes / 14; i++) {
329 vrpn_uint8 *report = buffer + (i * 14);
330
331 if (!(report[13] & 0x08)) {
332 // Garbled report; skip it
333 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
334 continue;
335 }
336
337 // Decode the "programming switch"
338 buttons[0] = (report[13] & 0x10) != 0;
339
340 // Decode the other buttons in column-major order
341 // This results in some gaps when using a shuttle or joystick model,
342 // but there really aren't any internally consistent numbering schemes.
343 for (int btn = 0; btn < 58; btn++) {
344 vrpn_uint8 *offset, mask;
345
346 offset = report + btn / 7 + 3;
347 mask = static_cast<vrpn_uint8>(1 << (btn % 7));
348
349 buttons[btn + 1] = (*offset & mask) != 0;
350 }
351
352 // Report jog dial as analog and dial
353 // Report shuttle knob as analog
354
355 // Double cast on channel 0 ensures negative values stay negative
356 channel[0] = static_cast<float>(static_cast<signed char>(report[0])) / 7.0;
357 channel[1] = static_cast<float>(report[1]);
358
359 // Do the unsigned/signed conversion at the last minute so the
360 // signed values work properly.
361 dials[0] = static_cast<vrpn_int8>(report[1] - _lastDial) / 256.0;
362
363 // Store the current dial position for the next delta
364 _lastDial = report[1];
365
366 }
367 } else {
368 fprintf(stderr,"vrpn_Xkeys_Jog_And_Shuttle::decodePacket(): Unrecognized packet length (%u)\n", static_cast<unsigned>(bytes));
369 return;
370 }
371}
372
374 : vrpn_Xkeys_v2(_filter = new vrpn_HidProductAcceptor(XKEYS_VENDOR, XKEYS_JOG_AND_SHUTTLE12), name, c, XKEYS_VENDOR, XKEYS_JOG_AND_SHUTTLE12)
375 , vrpn_Analog(name, c)
376 , vrpn_Button_Filter(name, c)
377 , vrpn_Dial(name, c)
378{
381 vrpn_Button::num_buttons = 13; // Don't forget button 0
382
383 // Initialize the state of all the analogs, buttons, and dials
384 _lastDial = 0;
385 memset(buttons, 0, sizeof(buttons));
386 memset(lastbuttons, 0, sizeof(lastbuttons));
387 memset(channel, 0, sizeof(channel));
388 memset(last, 0, sizeof(last));
389}
390
392{
393 update();
397
398 // Call the server_mainloop on our unique base class.
400}
401
411
421
422void vrpn_Xkeys_Jog_And_Shuttle12::decodePacket(size_t bytes, vrpn_uint8 *buffer)
423{
424/*
425 // Print the report so we can figure out what is going on.
426 for (size_t i = 0; i < bytes; i++) {
427 printf("%02x ", buffer[i]);
428 }
429 printf("\n");
430 return;
431*/
432
433 // The full report is 32 bytes long. Byte 0 is always 0, as are
434 // bytes 12-31. Bytes 8-11 seem to be some sort of time code.
435 // Buttons: The reset button is the low-order bit in byte 1.
436 // The first column are the 3 low-order bits in byte 2
437 // The next three columns are the low-order bits in bytes 3-5.
438 // Jog: Shows up as various high-order bits in the button bytes
439 // but also as a signed number in byte 7 that ranges from
440 // 0 through 7 for positive rotation and down to F9 for
441 // negative.
442 // Shuttle: Shows up as high-order bits in the button bytes,
443 // but also as a signed number in byte 6, which goes to
444 // 1 briefly as you jog right and to FF briefly as you
445 // jog left; then back to 0.
446
447 if (bytes % 32 == 0) {
448
449 // Loop through the reports in case we got multiple.
450 size_t i;
451 for (i = 0; i < bytes / 32; i++) {
452 vrpn_uint8 *report = buffer + (i * 32);
453
454 // Check for zero in the bytes that should be.
455 if (report[0] != 0) {
456 // Garbled report; skip it
457 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
458 continue;
459 }
460 for (size_t j = 12; j < 32; j++) {
461 if (report[j] != 0) {
462 // Garbled report; skip it
463 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
464 continue;
465 }
466 }
467
468 // Decode the "programming switch"
469 buttons[0] = (report[1] & 0x01) != 0;
470
471 // Decode the other buttons in column-major order
472 for (int btn = 0; btn < 12; btn++) {
473 vrpn_uint8 *offset, mask;
474
475 offset = report + btn / 3 + 2;
476 mask = static_cast<vrpn_uint8>(1 << (btn % 3));
477
478 buttons[btn + 1] = (*offset & mask) != 0;
479 }
480
481 // Report jog dial as analog and dial
482 // Report shuttle knob as analog
483
484 // Do the unsigned/signed conversion at the last minute so the
485 // signed values work properly. The dial turns 1/10th of the
486 // way around for each tick.
487 dials[0] = static_cast<vrpn_int8>(report[6]) / 10.0;
488
489 // Double cast on channel 0 ensures negative values stay negative.
490 // Channel 1 sums the revolutions of the dial.
491 channel[0] = static_cast<float>(static_cast<signed char>(report[7])) / 7.0;
492 channel[1] += dials[0];
493
494 // Store the current dial position for the next delta
495 _lastDial = report[1];
496 }
497 }
498 else {
499 fprintf(stderr, "vrpn_Xkeys_Jog_And_Shuttle12::decodePacket(): Unrecognized packet length (%u)\n", static_cast<unsigned>(bytes));
500 return;
501 }
502}
503
505 : vrpn_Xkeys_v2(_filter = new vrpn_HidProductAcceptor(XKEYS_VENDOR, XKEYS_JOG_AND_SHUTTLE68), name, c, XKEYS_VENDOR, XKEYS_JOG_AND_SHUTTLE68)
506 , vrpn_Analog(name, c)
507 , vrpn_Button_Filter(name, c)
508 , vrpn_Dial(name, c)
509{
512 vrpn_Button::num_buttons = 69; // Don't forget button 0
513
514 // Initialize the state of all the analogs, buttons, and dials
515 _lastDial = 0;
516 memset(buttons, 0, sizeof(buttons));
517 memset(lastbuttons, 0, sizeof(lastbuttons));
518 memset(channel, 0, sizeof(channel));
519 memset(last, 0, sizeof(last));
520}
521
523{
524 update();
528
529 // Call the server_mainloop on our unique base class.
531}
532
543
554
555void vrpn_Xkeys_Jog_And_Shuttle68::decodePacket(size_t bytes, vrpn_uint8 *buffer)
556{
557/*
558 // Print the report so we can figure out what is going on.
559 for (size_t i = 0; i < bytes; i++) {
560 printf("%02x ", buffer[i]);
561 }
562 printf("\n");
563 return;
564*/
565
566 // The full report is 32 bytes long. Byte 0 is always 0, as are
567 // bytes 22-31. Bytes 19-21 seem to be some sort of time code.
568 // Buttons: The reset button is the low-order bit in byte 1.
569 // The first column of 8 buttons are the bits in byte 2.
570 // The next 9 columns are the bits in bytes 3-11.
571 // The last 3 bits are unused in the middle four columns,
572 // where the shuttle-jog lives (columns 3-6).
573 // Jog: Shows up as various high-order bits in the button bytes
574 // but also as a signed number in byte 17 that ranges from
575 // 0 through 7 for positive rotation and down to F9 for
576 // negative.
577 // Shuttle: Shows up as high-order bits in the button bytes,
578 // but also as a signed number in byte 16, which goes to
579 // 1 briefly as you jog right and to FF briefly as you
580 // jog left; then back to 0.
581
582 if (bytes % 32 == 0) {
583
584 // Loop through the reports in case we got multiple.
585 size_t i;
586 for (i = 0; i < bytes / 32; i++) {
587 vrpn_uint8 *report = buffer + (i * 32);
588
589 // Check for zero in the bytes that should be.
590 if (report[0] != 0) {
591 // Garbled report; skip it
592 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
593 continue;
594 }
595 for (size_t j = 22; j < 32; j++) {
596 if (report[j] != 0) {
597 // Garbled report; skip it
598 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
599 continue;
600 }
601 }
602
603 // Decode the "programming switch"
604 buttons[0] = (report[1] & 0x01) != 0;
605
606 // Decode the other buttons in column-major order
607 for (int btn = 0; btn < 68; btn++) {
608
609 // Convert the button number into slot
610 // number, which means skipping the last
611 // 3 elements in the middle four columns.
612 int slot = btn;
613 if (btn > 28) { slot += 3; }
614 if (btn > 33) { slot += 3; }
615 if (btn > 38) { slot += 3; }
616 if (btn > 43) { slot += 3; }
617 vrpn_uint8 *offset, mask;
618
619 offset = report + slot / 8 + 2;
620 mask = static_cast<vrpn_uint8>(1 << (slot % 8));
621 buttons[btn + 1] = (*offset & mask) != 0;
622 }
623
624 // Report jog dial as analog and dial
625 // Report shuttle knob as analog
626
627 // Do the unsigned/signed conversion at the last minute so the
628 // signed values work properly. The dial turns 1/10th of the
629 // way around for each tick.
630 dials[0] = static_cast<vrpn_int8>(report[16]) / 10.0;
631
632 // Double cast on channel 0 ensures negative values stay negative.
633 // Channel 1 sums the revolutions of the dial.
634 channel[0] = static_cast<float>(static_cast<signed char>(report[17])) / 7.0;
635 channel[1] += dials[0];
636
637 // Store the current dial position for the next delta
638 _lastDial = report[1];
639 }
640 }
641 else {
642 fprintf(stderr, "vrpn_Xkeys_Jog_And_Shuttle68::decodePacket(): Unrecognized packet length (%u)\n", static_cast<unsigned>(bytes));
643 return;
644 }
645}
646
648 : vrpn_Xkeys_v1(_filter = new vrpn_HidProductAcceptor(XKEYS_VENDOR, XKEYS_JOYSTICK), name, c, XKEYS_VENDOR, XKEYS_JOYSTICK)
649 , vrpn_Analog(name, c)
650 , vrpn_Button_Filter(name, c)
651 , vrpn_Dial(name, c)
652{
655 vrpn_Button::num_buttons = 59; // Don't forget button 0
656
657 // Initialize the state of all the analogs, buttons, and dials
658 _gotDial = false;
659 _lastDial = 0;
660 memset(buttons, 0, sizeof(buttons));
661 memset(lastbuttons, 0, sizeof(lastbuttons));
662 memset(channel, 0, sizeof(channel));
663 memset(last, 0, sizeof(last));
664}
665
667{
668 update();
672
673 // Call the server_mainloop on our unique base class.
675}
676
686
696
697void vrpn_Xkeys_Joystick::decodePacket(size_t bytes, vrpn_uint8 *buffer)
698{
699 // Decode all full reports.
700 // Full reports for all of the pro devices are 15 bytes long.
701 // Because there is only one type of report, the initial "0" report-type
702 // byte is removed by the HIDAPI driver, leaving 14 bytes.
703 // Also, it appears as though the
704 // remaining 14-byte command is split into two, one 8-byte that is sent
705 // first and then a 6-byte that is sent later. So we need to check the
706 // length of the packet to see which it is and then parse it appropriately.
707 if (bytes == 8) { // The first 8 bytes of a report
708
709 // Report joystick axes as analogs
710 channel[0] = (static_cast<float>(buffer[0]) - 128) / 128.0;
711 channel[1] = (static_cast<float>(buffer[1]) - 128) / 128.0;
712 channel[2] = (static_cast<float>(buffer[2]) - 128) / 128.0;
713
714 // Decode the other buttons in column-major order. We skip the
715 // first three bytes, which record the joystick value or the
716 // shuttle/jog value (depending on device).
717 // This results in some gaps when using a shuttle or joystick model,
718 // but there really aren't any internally consistent numbering schemes.
719 // The first 35 buttons are in this report, the remaining 23 in the next.
720 for (int btn = 0; btn < 35; btn++) {
721 vrpn_uint8 *offset, mask;
722
723 offset = buffer + btn / 7 + 3;
724 mask = static_cast<vrpn_uint8>(1 << (btn % 7));
725
726 buttons[btn + 1] = (*offset & mask) != 0;
727 }
728
729 } else if (bytes == 6) { // The last 6 bytes of a report
730
731 if (!(buffer[5] & 0x08)) {
732 // Garbled report; skip it
733 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
734 return;
735 }
736
737 // Decode the "programming switch"
738 buttons[0] = (buffer[5] & 0x10) != 0;
739
740 // Decode the other buttons in column-major order.
741 // This results in some gaps when using a shuttle or joystick model,
742 // but there really aren't any internally consistent numbering schemes.
743 // The last 23 buttons are in this report, the remaining 23 in the next.
744 for (int btn = 35; btn < 58; btn++) {
745 vrpn_uint8 *offset, mask;
746 int local_btn = btn - 35;
747
748 offset = buffer + local_btn / 7;
749 mask = static_cast<vrpn_uint8>(1 << (local_btn % 7));
750
751 buttons[btn + 1] = (*offset & mask) != 0;
752 }
753
754 } else if (bytes == 14) { // A full report in one swoop (happens on Windows)
755 // Full reports for all of the pro devices are 15 bytes long.
756 // Because there is only one type of report, the initial "0" report-type
757 // byte is removed by the HIDAPI driver, leaving 14 bytes.
758 size_t i;
759 for (i = 0; i < bytes / 14; i++) {
760 vrpn_uint8 *report = buffer + (i * 14);
761
762 if (!(report[13] & 0x08)) {
763 // Garbled report; skip it
764 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
765 continue;
766 }
767
768 // Decode the "programming switch"
769 buttons[0] = (report[13] & 0x10) != 0;
770
771 // Decode the other buttons in column-major order
772 // This results in some gaps when using a shuttle or joystick model,
773 // but there really aren't any internally consistent numbering schemes.
774 for (int btn = 0; btn < 58; btn++) {
775 vrpn_uint8 *offset, mask;
776
777 offset = report + btn / 7 + 3;
778 mask = static_cast<vrpn_uint8>(1 << (btn % 7));
779
780 buttons[btn + 1] = (*offset & mask) != 0;
781 }
782
783 // Report joystick twist as analog and dial
784 if (!_gotDial) {
785 _gotDial = true;
786 }
787 else {
788 dials[0] = static_cast<vrpn_int8>(report[2] - _lastDial) / 256.0;
789 }
790 _lastDial = report[2];
791
792 // Double cast on channels 0 and 1 ensures negative values stay negative.
793 // Channel 2 sums the revolutions of the dial.
794 channel[0] = static_cast<float>(static_cast<signed char>(report[6])) / 127.0;
795 channel[1] = static_cast<float>(static_cast<signed char>(report[7])) / 127.0;
796 channel[2] += dials[0];
797
798 // Report joystick axes as analogs
799 channel[0] = (static_cast<float>(report[0]) - 128) / 128.0;
800 channel[1] = -(static_cast<float>(report[1]) - 128) / 128.0;
801 channel[2] += dials[0];
802 }
803 } else {
804 fprintf(stderr,"vrpn_Xkeys_Joystick::decodePacket(): Unrecognized packet length (%u)\n", static_cast<unsigned>(bytes));
805 return;
806 }
807}
808
810 : vrpn_Xkeys_v2(_filter = new vrpn_HidProductAcceptor(XKEYS_VENDOR, XKEYS_JOYSTICK12), name, c, XKEYS_VENDOR, XKEYS_JOYSTICK12)
811 , vrpn_Analog(name, c)
812 , vrpn_Button_Filter(name, c)
813 , vrpn_Dial(name, c)
814{
817 vrpn_Button::num_buttons = 13; // Don't forget button 0
818
819 // Initialize the state of all the analogs, buttons, and dials
820 _gotDial = false;
821 _lastDial = 0;
822 memset(buttons, 0, sizeof(buttons));
823 memset(lastbuttons, 0, sizeof(lastbuttons));
824 memset(channel, 0, sizeof(channel));
825 memset(last, 0, sizeof(last));
826}
827
829{
830 update();
834
835 // Call the server_mainloop on our unique base class.
837}
838
848
858
859void vrpn_Xkeys_Joystick12::decodePacket(size_t bytes, vrpn_uint8 *buffer)
860{
861 /*
862 // Print the report so we can figure out what is going on.
863 for (size_t i = 0; i < bytes; i++) {
864 printf("%02x ", buffer[i]);
865 }
866 printf("\n");
867 return;
868*/
869
870 // The full report is 32 bytes long. Byte 0 is always 0, as are
871 // bytes 16-31. Bytes 12-15 seem to be some sort of time code.
872 // Buttons: The reset button is the low-order bit in byte 1.
873 // The first column are the 3 low-order bits in byte 2
874 // The next three columns are the low-order bits in bytes 3-5.
875 // Joystick X axis: Byte 6 goes up to 7F to right, down to 81 to left.
876 // Joystick Y axis: Byte 7 goes to 7F when down, 81 when up.
877 // Joystick Z axis: Byte 8 goes up when spun right, down left, and
878 // wraps around from 255 to 0.
879
880 if (bytes % 32 == 0) {
881
882 // Loop through the reports in case we got multiple.
883 size_t i;
884 for (i = 0; i < bytes / 32; i++) {
885 vrpn_uint8 *report = buffer + (i * 32);
886
887 // Check for zero in the bytes that should be.
888 if (report[0] != 0) {
889 // Garbled report; skip it
890 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
891 continue;
892 }
893 for (size_t j = 16; j < 32; j++) {
894 if (report[j] != 0) {
895 // Garbled report; skip it
896 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
897 continue;
898 }
899 }
900
901 // Decode the "programming switch"
902 buttons[0] = (report[1] & 0x01) != 0;
903
904 // Decode the other buttons in column-major order
905 for (int btn = 0; btn < 12; btn++) {
906 vrpn_uint8 *offset, mask;
907
908 offset = report + btn / 3 + 2;
909 mask = static_cast<vrpn_uint8>(1 << (btn % 3));
910
911 buttons[btn + 1] = (*offset & mask) != 0;
912 }
913
914 // Report joystick twist as analog and dial
915 if (!_gotDial) {
916 _gotDial = true;
917 } else {
918 dials[0] = static_cast<vrpn_int8>(report[8] - _lastDial) / 256.0;
919 }
920 _lastDial = report[8];
921
922 // Double cast on channels 0 and 1 ensures negative values stay negative.
923 // Channel 2 sums the revolutions of the dial.
924 channel[0] = static_cast<float>(static_cast<signed char>(report[6])) / 127.0;
925 channel[1] = -static_cast<float>(static_cast<signed char>(report[7])) / 127.0;
926 channel[2] += dials[0];
927 }
928 }
929 else {
930 fprintf(stderr, "vrpn_Xkeys_Joystick12::decodePacket(): Unrecognized packet length (%u)\n", static_cast<unsigned>(bytes));
931 return;
932 }
933}
934
936 : vrpn_Xkeys_v1(_filter = new vrpn_HidProductAcceptor(XKEYS_VENDOR, XKEYS_PRO), name, c, XKEYS_VENDOR, XKEYS_PRO)
937 , vrpn_Button_Filter(name, c)
938{
939 vrpn_Button::num_buttons = 59; // Don't forget button 0
940
941 // Initialize the state of all the buttons
942 memset(buttons, 0, sizeof(buttons));
943 memset(lastbuttons, 0, sizeof(lastbuttons));
944}
945
947{
948 update();
952
953 // Call the server_mainloop on our unique base class.
955}
956
961
966
967void vrpn_Xkeys_Pro::decodePacket(size_t bytes, vrpn_uint8 *buffer)
968{
969 // Decode all full reports.
970 // Full reports for all of the pro devices are 15 bytes long.
971 // Because there is only one type of report, the initial "0" report-type
972 // byte is removed by the HIDAPI driver, leaving 14 bytes.
973 // Also, it appears as though the
974 // remaining 14-byte command is split into two, one 8-byte that is sent
975 // first and then a 6-byte that is sent later. So we need to check the
976 // length of the packet to see which it is and then parse it appropriately.
977 if (bytes == 8) { // The first 8 bytes of a report
978
979 // Decode the other buttons in column-major order. We skip the
980 // first three bytes, which record the joystick value or the
981 // shuttle/jog value (depending on device).
982 // This results in some gaps when using a shuttle or joystick model,
983 // but there really aren't any internally consistent numbering schemes.
984 // The first 35 buttons are in this report, the remaining 23 in the next.
985 for (int btn = 0; btn < 35; btn++) {
986 vrpn_uint8 *offset, mask;
987
988 offset = buffer + btn / 7 + 3;
989 mask = static_cast<vrpn_uint8>(1 << (btn % 7));
990
991 buttons[btn + 1] = (*offset & mask) != 0;
992 }
993
994 } else if (bytes == 6) { // The last 6 bytes of a report
995
996 if (!(buffer[5] & 0x08)) {
997 // Garbled report; skip it
998 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
999 return;
1000 }
1001
1002 // Decode the "programming switch"
1003 buttons[0] = (buffer[5] & 0x10) != 0;
1004
1005 // Decode the other buttons in column-major order.
1006 // This results in some gaps when using a shuttle or joystick model,
1007 // but there really aren't any internally consistent numbering schemes.
1008 // The last 23 buttons are in this report, the remaining 23 in the next.
1009 for (int btn = 35; btn < 58; btn++) {
1010 vrpn_uint8 *offset, mask;
1011 int local_btn = btn - 35;
1012
1013 offset = buffer + local_btn / 7;
1014 mask = static_cast<vrpn_uint8>(1 << (local_btn % 7));
1015
1016 buttons[btn + 1] = (*offset & mask) != 0;
1017 }
1018
1019 } else if (bytes == 14) { // A full report in one swoop (happens on Windows)
1020 // Full reports for all of the pro devices are 15 bytes long.
1021 // Because there is only one type of report, the initial "0" report-type
1022 // byte is removed by the HIDAPI driver, leaving 14 bytes.
1023 size_t i;
1024 // Decode all full reports.
1025 // Full reports for all of the pro devices are 15 bytes long.
1026 for (i = 0; i < bytes / 14; i++) {
1027 vrpn_uint8 *report = buffer + (i * 14);
1028
1029 if (!(report[13] & 0x08)) {
1030 // Garbled report; skip it
1031 fprintf(stderr, "vrpn_Xkeys: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
1032 continue;
1033 }
1034
1035 // Decode the "programming switch"
1036 buttons[0] = (report[13] & 0x10) != 0;
1037
1038 // Decode the other buttons in column-major order
1039 // This results in some gaps when using a shuttle or joystick model,
1040 // but there really aren't any internally consistent numbering schemes.
1041 for (int btn = 0; btn < 58; btn++) {
1042 vrpn_uint8 *offset, mask;
1043
1044 offset = buffer + btn / 7 + 3;
1045 mask = static_cast<vrpn_uint8>(1 << (btn % 7));
1046
1047 buttons[btn + 1] = (*offset & mask) != 0;
1048 }
1049 }
1050 } else {
1051 fprintf(stderr,"vrpn_Xkeys_Pro::decodePacket(): Unrecognized packet length (%u)\n", static_cast<unsigned>(bytes));
1052 return;
1053 }
1054}
1055
1057 : vrpn_Xkeys_noLEDs(_filter = new vrpn_HidProductAcceptor(XKEYS_VENDOR, XKEYS_XK3), name, c, XKEYS_VENDOR, XKEYS_XK3, false)
1058 , vrpn_Button_Filter(name, c)
1059{
1060 // 3 buttons
1062
1063 // Initialize the state of all the buttons
1064 memset(buttons, 0, sizeof(buttons));
1065 memset(lastbuttons, 0, sizeof(lastbuttons));
1066}
1067
1069{
1070 update();
1074
1075 // Call the server_mainloop on our unique base class.
1077}
1078
1083
1088
1089void vrpn_Xkeys_XK3::decodePacket(size_t bytes, vrpn_uint8 *buffer) {
1090 // Decode all full reports, each of which is 32 bytes long.
1091 // Because there is only one type of report, the initial "0" report-type
1092 // byte is removed by the HIDAPI driver.
1093 for (size_t i = 0; i < bytes / 32; i++) {
1094 vrpn_uint8 *report = buffer + (i * 32);
1095
1096 // The first two bytes of the report always seem to be
1097 // 0x00 0x01.
1098 if ((report[0] != 0x00) || (report[1] != 0x01) ) {
1099 // Apparently we got a corrupted report; skip this one.
1100 fprintf(stderr, "vrpn_Xkeys_XK3: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
1101 continue;
1102 }
1103
1104 // The left button is bit 1 (value 0x02) in the third byte
1105 // The middle button is bit 2 (value 0x04) in the third byte
1106 // The right button is bit 3 (value 0x08) in the third byte
1107 buttons[0] = (report[2] & 0x02) != 0;
1108 buttons[1] = (report[2] & 0x04) != 0;
1109 buttons[2] = (report[2] & 0x08) != 0;
1110 }
1111}
1112
1113// End of VRPN_USE_HID
1114#endif
vrpn_float64 last[vrpn_CHANNEL_MAX]
Definition vrpn_Analog.h:39
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition vrpn_Analog.h:38
vrpn_Analog(const char *name, vrpn_Connection *c=NULL)
Definition vrpn_Analog.C:14
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...
vrpn_BaseClass(const char *name, vrpn_Connection *c=NULL)
Names the device and assigns or opens connection, calls registration methods.
virtual void report_changes(void)
vrpn_Button_Filter(const char *, vrpn_Connection *c=NULL)
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 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_Dial(const char *name, vrpn_Connection *c=NULL)
Definition vrpn_Dial.C:8
vrpn_int32 num_dials
Definition vrpn_Dial.h:27
vrpn_uint16 product() const
Returns USB product ID of connected device May not contain valid if an already-open device was provid...
vrpn_HidInterface(vrpn_HidAcceptor *acceptor, vrpn_uint16 vendor=0, vrpn_uint16 product=0, hid_device *device=NULL)
Constructor If we already have a HID device from some other source, it can be passed and we'll take o...
virtual void update()
Polls the device buffers and causes on_data_received callbacks if appropriate You NEED to call this f...
vrpn_uint16 vendor() const
Returns USB vendor ID of connected device May not contain valid if an already-open device was provide...
void send_data(size_t bytes, const vrpn_uint8 *buffer)
Call this to send data to the device.
Accepts any device with the given vendor and product IDs.
vrpn_Xkeys_Desktop(const char *name, vrpn_Connection *c=0)
Definition vrpn_Xkeys.C:144
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition vrpn_Xkeys.C:156
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
Definition vrpn_Xkeys.C:179
void report(void)
Definition vrpn_Xkeys.C:167
void report_changes(void)
Definition vrpn_Xkeys.C:173
vrpn_Xkeys_Jog_And_Shuttle12(const char *name, vrpn_Connection *c=0)
Definition vrpn_Xkeys.C:373
void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
Definition vrpn_Xkeys.C:402
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition vrpn_Xkeys.C:391
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
Definition vrpn_Xkeys.C:422
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
Definition vrpn_Xkeys.C:555
void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
Definition vrpn_Xkeys.C:533
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition vrpn_Xkeys.C:522
vrpn_Xkeys_Jog_And_Shuttle68(const char *name, vrpn_Connection *c=0)
Definition vrpn_Xkeys.C:504
void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
Definition vrpn_Xkeys.C:237
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
Definition vrpn_Xkeys.C:257
vrpn_Xkeys_Jog_And_Shuttle(const char *name, vrpn_Connection *c=0)
Definition vrpn_Xkeys.C:208
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition vrpn_Xkeys.C:226
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
Definition vrpn_Xkeys.C:859
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition vrpn_Xkeys.C:828
void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
Definition vrpn_Xkeys.C:839
vrpn_Xkeys_Joystick12(const char *name, vrpn_Connection *c=0)
Definition vrpn_Xkeys.C:809
vrpn_Xkeys_Joystick(const char *name, vrpn_Connection *c=0)
Definition vrpn_Xkeys.C:647
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition vrpn_Xkeys.C:666
void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
Definition vrpn_Xkeys.C:677
vrpn_uint8 _lastDial
Definition vrpn_Xkeys.h:174
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
Definition vrpn_Xkeys.C:697
vrpn_Xkeys_Pro(const char *name, vrpn_Connection *c=0)
Definition vrpn_Xkeys.C:935
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition vrpn_Xkeys.C:946
void report(void)
Definition vrpn_Xkeys.C:957
void report_changes(void)
Definition vrpn_Xkeys.C:962
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
Definition vrpn_Xkeys.C:967
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
vrpn_Xkeys_XK3(const char *name, vrpn_Connection *c=0)
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
void report(void)
void report_changes(void)
vrpn_Xkeys_noLEDs(vrpn_HidAcceptor *filter, const char *name, vrpn_Connection *c=0, vrpn_uint16 vendor=0, vrpn_uint16 product=0, bool toggle_light=true)
Definition vrpn_Xkeys.h:79
virtual void setLEDs(LED_STATE red, LED_STATE green)
Definition vrpn_Xkeys.C:76
vrpn_Xkeys_v1(vrpn_HidAcceptor *filter, const char *name, vrpn_Connection *c=0, vrpn_uint16 vendor=0, vrpn_uint16 product=0, bool toggle_light=true)
Definition vrpn_Xkeys.h:91
virtual void setLEDs(LED_STATE red, LED_STATE green)
Definition vrpn_Xkeys.C:104
vrpn_Xkeys_v2(vrpn_HidAcceptor *filter, const char *name, vrpn_Connection *c=0, vrpn_uint16 vendor=0, vrpn_uint16 product=0, bool toggle_light=true)
Definition vrpn_Xkeys.h:108
virtual ~vrpn_Xkeys()
Definition vrpn_Xkeys.C:34
struct timeval _timestamp
Definition vrpn_Xkeys.h:67
virtual void setLEDs(LED_STATE red, LED_STATE green)=0
vrpn_HidAcceptor * _filter
Definition vrpn_Xkeys.h:68
virtual void decodePacket(size_t bytes, vrpn_uint8 *buffer)=0
bool _toggle_light
Definition vrpn_Xkeys.h:69
vrpn_Xkeys(vrpn_HidAcceptor *filter, const char *name, vrpn_Connection *c=0, vrpn_uint16 vendor=0, vrpn_uint16 product=0, bool toggle_light=true)
Definition vrpn_Xkeys.C:23
static int VRPN_CALLBACK on_connect(void *thisPtr, vrpn_HANDLERPARAM p)
Definition vrpn_Xkeys.C:65
void init_hid()
Definition vrpn_Xkeys.C:44
void on_data_received(size_t bytes, vrpn_uint8 *buffer)
Derived class reimplements this callback.
Definition vrpn_Xkeys.C:50
static int VRPN_CALLBACK on_last_disconnect(void *thisPtr, vrpn_HANDLERPARAM p)
Definition vrpn_Xkeys.C:55
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 vrpn_gettimeofday
Definition vrpn_Shared.h:99