vrpn 07.35
Virtual Reality Peripheral Network
Loading...
Searching...
No Matches
vrpn_Microsoft_Controller_Raw.C
Go to the documentation of this file.
1// vrpn_Microsoft_Controller_Raw.C: VRPN driver for Microsoft Controller Raw devices
2
3#include <stdio.h> // for fprintf, stderr, NULL
4#include <string.h> // for memset
5#include <math.h> // for sqrt and fabs
6
8
10
11// USB vendor and product IDs for the models we support
12static const vrpn_uint16 MICROSOFT_VENDOR = 0x045e;
13static const vrpn_uint16 SIDEWINDER_PRECISION_2 = 0x0038;
14static const vrpn_uint16 SIDEWINDER = 0x003c;
15static const vrpn_uint16 XBOX_S = 0x0289;
16static const vrpn_uint16 XBOX_360 = 0x028e;
17static const vrpn_uint16 XBOX_360_WIRELESS = 0x02a1;
18
19// and generic controllers that act the same as the above
20static const vrpn_uint16 AFTERGLOW_VENDOR = 0x0e6f;
21static const vrpn_uint16 AX1_FOR_XBOX_360 = 0x0213;
22
23#if defined(VRPN_USE_HID)
24
25static const double POLL_INTERVAL = 1e+6 / 30.0; // If we have not heard, ask.
26
27#define MS_GAMEPAD_LEFT_THUMB_DEADZONE 7849
28#define MS_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
29#define MS_GAMEPAD_TRIGGER_THRESHOLD 30
30
32// helpers
34static vrpn_float64 normalize_dpad(unsigned char up, unsigned char right, unsigned char down, unsigned char left)
35{
36 int x = 0;
37 int y = 0;
38 if (right)
39 {
40 x += 1;
41 }
42 if (left)
43 {
44 x -= 1;
45 }
46 if (up)
47 {
48 y += 1;
49 }
50 if (down)
51 {
52 y -= 1;
53 }
54 size_t index = ((x + 1) * 3) + (y + 1);
55 vrpn_float64 angles[] = {225, 270, 315, 180, -1, 0, 135, 90, 45};
56 return (angles[index]);
57}
58
59static void normalize_axis(const unsigned int value, const short deadzone, const vrpn_float64 scale, vrpn_float64& channel, int wordSize = 16)
60{
61 channel = (static_cast<float>(value) - (float) (1 << (wordSize - 1)));
62 if (fabs(channel) < (deadzone * 3 / 4))
63 {
64 channel = 0.0f;
65 }
66 else
67 {
68 channel /= (float) (1 << (wordSize - 1));
69 }
70 channel *= scale;
71 if (channel < -1.0) { channel = -1.0; }
72 if (channel > 1.0) { channel = 1.0; }
73}
74
75static void normalize_axes(const unsigned int x, const unsigned int y, const short deadzone, const vrpn_float64 scale, vrpn_float64& channelX, vrpn_float64& channelY, int wordSize = 16)
76{
77#ifdef FUTURE
78 // adapted from: http://msdn.microsoft.com/en-us/library/windows/desktop/ee417001%28v=vs.85%29.aspx
79 // determine how far the controller is pushed
80 float magnitude = (float) sqrt((double) ((x * x) + (y * y)));
81
82 // determine the direction the controller is pushed
83 float normalizedX = ((magnitude > 0.0f) ? (x / magnitude) : 0.0f);
84 float normalizedY = ((magnitude > 0.0f) ? (y / magnitude) : 0.0f);
85
86 float normalizedMagnitude = 0.0f;
87
88 // check if the controller is outside a circular dead zone
89 if (magnitude > deadzone)
90 {
91 // clip the magnitude at its expected maximum value
92 if (magnitude > 32767)
93 {
94 magnitude = 32767;
95 }
96
97 // adjust magnitude relative to the end of the dead zone
98 magnitude -= deadzone;
99
100 // optionally normalize the magnitude with respect to its
101 // expected range giving a magnitude value of 0.0 to 1.0
102 normalizedMagnitude = magnitude / (32767.0f - deadzone);
103 }
104 else
105 { // if the controller is in the deadzone zero out the magnitude
106 magnitude = 0.0f;
107 normalizedMagnitude = 0.0f;
108 }
109#else
110 normalize_axis(x, deadzone, scale, channelX, wordSize);
111 normalize_axis(y, deadzone, scale, channelY, wordSize);
112#endif // FUTURE
113}
114
115static vrpn_float64 normalize_trigger(unsigned int trigger)
116{
117 // Filter out low-intensity signals
118 int value = trigger - 0x80;
119 return ((fabs(static_cast<double>(value)) < MS_GAMEPAD_TRIGGER_THRESHOLD) ? 0.0f : (value * 2.0f / 255.0f));
120}
121
123// Common base class
126 vrpn_uint16 vendor, vrpn_uint16 product)
127 : vrpn_BaseClass(name, c)
128 , vrpn_HidInterface(filter, vendor, product)
129 , _filter(filter)
130{
131 init_hid();
132}
133
135{
136 try {
137 delete _filter;
138 } catch (...) {
139 fprintf(stderr, "vrpn_Microsoft_Controller_Raw::~vrpn_Microsoft_Controller_Raw(): delete failed\n");
140 return;
141 }
142}
143
149
150void vrpn_Microsoft_Controller_Raw::on_data_received(size_t bytes, vrpn_uint8 *buffer)
151{
152 decodePacket(bytes, buffer);
153}
154
156{
157 return 0;
158}
159
161{
162 return 0;
163}
164
166// SideWinder Precision 2 Joystick
169vrpn_Microsoft_Controller_Raw(new vrpn_HidProductAcceptor(MICROSOFT_VENDOR, SIDEWINDER_PRECISION_2), name, c, MICROSOFT_VENDOR, SIDEWINDER_PRECISION_2),
170 vrpn_Analog(name, c), vrpn_Button_Filter(name, c), vrpn_Dial(name, c)
171{
175
176 // Initialize the state of all the analogs, buttons, and dials
177 memset(buttons, 0, sizeof(buttons));
178 memset(lastbuttons, 0, sizeof(lastbuttons));
179 memset(channel, 0, sizeof(channel));
180 memset(last, 0, sizeof(last));
181}
182
184{
185 update();
187 struct timeval current_time;
188 vrpn_gettimeofday(&current_time, NULL);
189 if (vrpn_TimevalDuration(current_time, _timestamp) > POLL_INTERVAL)
190 {
191 _timestamp = current_time;
193
194 // Call the server_mainloop on our unique base class.
196 }
197}
198
215
232
233void vrpn_Microsoft_SideWinder_Precision_2::decodePacket(size_t bytes, vrpn_uint8 *buffer)
234{
235 // SideWinder Precision 2 joystick
236
237 // Decode all full reports, each of which is 40 bytes long.
238 // Because there is only one type of report, the initial "0" report-type
239 // byte is removed by the HIDAPI driver.
240 /*
241 Byte : Bit 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0
242 [0]: X-axis (left=00, right=ff)
243 [1]: Y-axis (up=00, down=ff)
244 [2]: Z-rotate (left=00, right=ff)
245 [3]: Slider (up=00, down=ff)
246 [4]: buttons (bit flags: none=0x00, "1" (trigger)=0x01, "2"=0x02, "3"=0x04, ..., "8"=0x80
247 [5]: POV Hat high nibble (none=0x80, N=0x00, NE=0x10, ... NW=0x80)
248 */
249 // XXX Check to see that this works with HIDAPI, there may be two smaller reports.
250 if (bytes == 6)
251 {
252 normalize_axes(buffer[0], buffer[1], 0x08, 1.0f, channel[0], channel[1], 8);
253 normalize_axis(buffer[2], 0x08, 1.0f, channel[2], 8);
254 normalize_axis(buffer[3], 0x08, 1.0f, channel[3], 8);
255
256 vrpn_uint8 value, mask;
257 value = buffer[4];
258 for (int btn = 0; btn < 8; btn++)
259 {
260 mask = static_cast<vrpn_uint8>(1 << (btn % 8));
261 buttons[btn] = ((value & mask) != 0);
262 }
263
264 // Point of View Hat
265 buttons[8] = buttons[9] = buttons[10] = buttons[11] = 0;
266 switch (buffer[5] >> 4)
267 {
268 case 0: // up
269 buttons[8] = true;
270 break;
271 case 1:
272 buttons[8] = buttons[9] = true;
273 break;
274 case 2: // right
275 buttons[9] = true;
276 break;
277 case 3:
278 buttons[9] = buttons[10] = true;
279 break;
280 case 4: // down
281 buttons[10] = true;
282 break;
283 case 5:
284 buttons[10] = buttons[11] = true;
285 break;
286 case 6: // left
287 buttons[11] = true;
288 break;
289 case 7:
290 buttons[11] = buttons[8] = true;
291 break;
292 case 8:
293 default:
294 // nothing to do
295 break;
296 }
297 channel[4] = normalize_dpad(buttons[8], buttons[9], buttons[10], buttons[11]);
298 }
299 else
300 {
301 fprintf(stderr, "vrpn_Microsoft_SideWinder_Precision_2: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
302 }
303}
304
306// SideWinder Joystick
309vrpn_Microsoft_Controller_Raw(new vrpn_HidProductAcceptor(MICROSOFT_VENDOR, SIDEWINDER), name, c, MICROSOFT_VENDOR, SIDEWINDER),
310 vrpn_Analog(name, c), vrpn_Button_Filter(name, c), vrpn_Dial(name, c)
311{
315
316 // Initialize the state of all the analogs, buttons, and dials
317 memset(buttons, 0, sizeof(buttons));
318 memset(lastbuttons, 0, sizeof(lastbuttons));
319 memset(channel, 0, sizeof(channel));
320 memset(last, 0, sizeof(last));
321}
322
324{
325 update();
327 struct timeval current_time;
328 vrpn_gettimeofday(&current_time, NULL);
329 if (vrpn_TimevalDuration(current_time, _timestamp) > POLL_INTERVAL)
330 {
331 _timestamp = current_time;
333
334 // Call the server_mainloop on our unique base class.
336 }
337}
338
339void vrpn_Microsoft_SideWinder::report(vrpn_uint32 class_of_service)
340{
343 if (vrpn_Dial::num_dials > 0)
344 {
346 }
347
348 vrpn_Analog::report_changes(class_of_service);
350 if (vrpn_Dial::num_dials > 0)
351 {
353 }
354}
355
356void vrpn_Microsoft_SideWinder::report_changes(vrpn_uint32 class_of_service)
357{
360 if (vrpn_Dial::num_dials > 0)
361 {
363 }
364
365 vrpn_Analog::report(class_of_service);
367 if (vrpn_Dial::num_dials > 0)
368 {
370 }
371}
372
373void vrpn_Microsoft_SideWinder::decodePacket(size_t bytes, vrpn_uint8 *buffer)
374{
375 // SideWinder Precision 2 joystick
376
377 // Decode all full reports, each of which is 40 bytes long.
378 // Because there is only one type of report, the initial "0" report-type
379 // byte is removed by the HIDAPI driver.
380 /*
381 Byte : Bit 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0
382 [0]: X-axis (left=00, right=ff)
383 [1]: Y-axis (up=00, down=ff)
384 [2]: slider (up/fwd=00, down/back=ff)
385 [3]: buttons (bit flags: none=0x00, "1" (trigger)=0x01, "2"=0x02, "3"=0x04, ..., "8"=0x80)
386 */
387 // XXX Check to see that this works with HIDAPI, there may be two smaller reports.
388 if (bytes == 4)
389 {
390 normalize_axes(buffer[0], buffer[1], 0x08, 1.0f, channel[0], channel[1], 8);
391 normalize_axis(buffer[2], 0x08, 1.0f, channel[2], 8);
392
393 vrpn_uint8 value, mask;
394 value = buffer[3];
395 for (int btn = 0; btn < 8; btn++)
396 {
397 mask = static_cast<vrpn_uint8>(1 << (btn % 8));
398 buttons[btn] = ((value & mask) != 0);
399 }
400 }
401 else
402 {
403 fprintf(stderr, "vrpn_Microsoft_SideWinder: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
404 }
405}
406
408// Xbox S
411 : vrpn_Microsoft_Controller_Raw(new vrpn_HidProductAcceptor(MICROSOFT_VENDOR, XBOX_S), name, c, MICROSOFT_VENDOR, XBOX_S)
412 , vrpn_Analog(name, c)
413 , vrpn_Button_Filter(name, c)
414 , vrpn_Dial(name, c)
415{
419
420 // Initialize the state of all the analogs, buttons, and dials
421 _lastDial = 0;
422 memset(buttons, 0, sizeof(buttons));
423 memset(lastbuttons, 0, sizeof(lastbuttons));
424 memset(channel, 0, sizeof(channel));
425 memset(last, 0, sizeof(last));
426}
427
429{
430 update();
432 struct timeval current_time;
433 vrpn_gettimeofday(&current_time, NULL);
434 if (vrpn_TimevalDuration(current_time, _timestamp) > POLL_INTERVAL ) {
435 _timestamp = current_time;
437
438 // Call the server_mainloop on our unique base class.
440 }
441}
442
458
474
475void vrpn_Microsoft_Controller_Raw_Xbox_S::decodePacket(size_t bytes, vrpn_uint8 *buffer) {
476 // Xbox Controller S requires adapter to be made/purchased to connect USB to computer.
477 // Also, it may require a driver to be installed such as XBCD_Installer_0.2.7.exe (Windows).
478
479 // Decode all full reports, each of which is 40 bytes long.
480 // Because there is only one type of report, the initial "0" report-type
481 // byte is removed by the HIDAPI driver.
482 /*
483 Byte : Bit 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0
484 [0] : | Report ID |
485 [1] : |B8 |B7 |B6 |B5 |B4 |B3 |B2 |B1 |
486 [2] : |B16|B15|B14|B13|B12|B11|B10|B9 |
487 [3] : |B24|B23|B22|B21|B20|B19|B18|B17| <------- no such buttons exist and data does not change
488 [4-5] : | X Axis |
489 [6-7] : | Y Axis |
490 [8-9] : | Z Axis |
491 [10-11] : | RX Axis |
492 [12-13]: | RY Axis |
493 [14-15]: | RZ Axis |
494 [16-17]: | Slider Axis |
495 [18] : | EMPTY | POV |
496 [19] : | Current MapMatrix |
497 --- Original data from Xbox controller ---
498 [20] : | 0x00 |
499 [21] : | 0x14(Size of report) |
500 [22] : |RSp|LSp|Bk |St |Rgt|Lft|Dn |Up | <------- other buttons
501 [23] : | 0x00 |
502 [24] : | Button A |
503 [25] : | Button B |
504 [26] : | Button X |
505 [27] : | Button Y |
506 [28] : | Button Black |
507 [29] : | Button White |
508 [30] : | Left Trigger |
509 [31] : | Right Trigger |
510 [32-33]: | Left-Stick X |
511 [34-35]: | Left-Stick Y |
512 [36-37]: | Right-Stick X |
513 [38-39]: | Right-Stick Y |
514 */
515 // XXX Check to see that this works with HIDAPI, there may be two smaller reports.
516 if (bytes == 40) {
517 if (buffer[0] == 1) {
518
519 // Report joystick axes as analogs
520 vrpn_uint16 x, y;
521 vrpn_uint8 *bufptr;
522#ifdef OLD_DATA
523 // left joy left/right: Left 27, center (normal) 81 (calc 7e), right D5
524 bufptr = &buffer[32];
525 x = vrpn_unbuffer<vrpn_int16>(bufptr);
526 // left joy up/down: Up 34, center (normal) 81 (calc 81), down CF
527 bufptr = &buffer[34];
528 y = vrpn_unbuffer<vrpn_int16>(bufptr);
529 normalize_axes(x, y, MS_GAMEPAD_LEFT_THUMB_DEADZONE, 1.0f, channel[0], channel[1]);
530 // right joy up/down: Up 32, (center calc 7f), down CC
531 bufptr = &buffer[36];
532 x = vrpn_unbuffer<vrpn_int16>(bufptr);
533 // right joy left/right: Left 2B, center (normal) 82 (calc 84), right DC
534 bufptr = &buffer[38];
535 y = vrpn_unbuffer<vrpn_int16>(bufptr);
536 normalize_axes(x, y, MS_GAMEPAD_RIGHT_THUMB_DEADZONE, 1.0f, channel[2], channel[3]);
537#else
538 vrpn_int16 temp;
539 bufptr = &buffer[4];
540 temp = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr) / 2;
541 x = temp + (1 << 15);
542 x *= 2;
543 bufptr = &buffer[6];
544 temp = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr) / 2;
545 y = temp + (1 << 15);
546 y *= 2;
547 normalize_axes(x, y, MS_GAMEPAD_LEFT_THUMB_DEADZONE, 1.0f, channel[0], channel[1]);
548 bufptr = &buffer[10];
549 temp = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr) / 2;
550 x = temp + (1 << 15);
551 bufptr = &buffer[12];
552 temp = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr) / 2;
553 y = temp + (1 << 15);
554 normalize_axes(x, y, MS_GAMEPAD_LEFT_THUMB_DEADZONE, 2.0f, channel[2], channel[3]);
555#endif // OLD_DATA
556
557#ifdef OLD_DATA
558 // button #0: 24 A
559 buttons[0] = (buffer[24] != 0);
560 // button #1: 25 B
561 buttons[1] = (buffer[25] != 0);
562 // button #2: 26 X
563 buttons[2] = (buffer[26] != 0);
564 // button #3: 27 Y
565 buttons[3] = (buffer[27] != 0);
566 // button #4: 28 Black
567 buttons[4] = (buffer[28] != 0);
568 // button #5: 29 White
569 buttons[5] = (buffer[29] != 0);
570 // button #6: 40 Start
571 buttons[6] = ((buffer[22] & 0x10) != 0);
572 // button #7: 80 Back
573 buttons[7] = ((buffer[22] & 0x20) != 0);
574 // button #8: left joy
575 buttons[8] = ((buffer[22] & 0x40) != 0);
576 // button #9: right joy
577 buttons[9] = ((buffer[22] & 0x80) != 0);
578 // button #10:30 left trigger
579 buttons[10] = (buffer[30] != 0);
580 // button #11:31 right trigger
581 buttons[11] = (buffer[31] != 0);
582#else
583 vrpn_uint8 value, mask;
584 value = buffer[1];
585 for (int btn = 0; btn < 8; btn++)
586 {
587 mask = static_cast<vrpn_uint8>(1 << (btn % 8));
588 buttons[btn] = ((value & mask) != 0);
589 }
590 value = buffer[2];
591 for (int btn = 0; btn < 4; btn++)
592 {
593 mask = static_cast<vrpn_uint8>(1 << (btn % 8));
594 buttons[8 + btn] = ((value & mask) != 0);
595 }
596#endif // OLD_DATA
597
598 // Point of View Hat
599#ifdef OLD_DATA
600 buttons[12] = ((buffer[22] & 0x01) != 0); // Up
601 buttons[14] = ((buffer[22] & 0x02) != 0); // Down
602 buttons[15] = ((buffer[22] & 0x04) != 0); // Left
603 buttons[13] = ((buffer[22] & 0x08) != 0); // Right
604#else
605 // Point of View Hat
606 buttons[12] = buttons[13] = buttons[14] = buttons[15] = 0;
607 switch (buffer[18] & 0x0f)
608 {
609 case 0: // up
610 buttons[12] = true;
611 break;
612 case 1:
613 buttons[12] = buttons[13] = true;
614 break;
615 case 2: // right
616 buttons[13] = true;
617 break;
618 case 3:
619 buttons[13] = buttons[14] = true;
620 break;
621 case 4: // down
622 buttons[14] = true;
623 break;
624 case 5:
625 buttons[14] = buttons[15] = true;
626 break;
627 case 6: // left
628 buttons[15] = true;
629 break;
630 case 7:
631 buttons[15] = buttons[12] = true;
632 break;
633 case 8:
634 default:
635 // nothing to do
636 break;
637 }
638#endif // OLD_DATA
639 channel[4] = normalize_dpad(buttons[12], buttons[13], buttons[14], buttons[15]);
640 } else {
641 fprintf(stderr, "vrpn_Microsoft_Controller_Raw_Xbox_S: Unknown report = %u\n", static_cast<unsigned>(buffer[0]));
642 }
643 } else {
644 fprintf(stderr, "vrpn_Microsoft_Controller_Raw_Xbox_S: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
645 }
646}
647
649// Xbox 360
652 : vrpn_Microsoft_Controller_Raw(new vrpn_HidProductAcceptor(vendor, product), name, c, vendor, product)
653, vrpn_Analog(name, c)
654, vrpn_Button_Filter(name, c)
655, vrpn_Dial(name, c)
656{
660
661 // Initialize the state of all the analogs, buttons, and dials
662 _lastDial = 0;
663 memset(buttons, 0, sizeof(buttons));
664 memset(lastbuttons, 0, sizeof(lastbuttons));
665 memset(channel, 0, sizeof(channel));
666 memset(last, 0, sizeof(last));
667}
668
670{
671 update();
673 struct timeval current_time;
674 vrpn_gettimeofday(&current_time, NULL);
675 if (vrpn_TimevalDuration(current_time, _timestamp) > POLL_INTERVAL ) {
676 _timestamp = current_time;
678
679 // Call the server_mainloop on our unique base class.
681 }
682}
683
699
715
717{
718 // Decode all full reports, each of which is 14 bytes long.
719 // Because there is only one type of report, the initial "0" report-type
720 // byte is removed by the HIDAPI driver.
721 /*
722 0: left-X
723 1: "
724 2: left-Y
725 3: "
726 4: right-X
727 5: "
728 6: right-Y
729 7: "
730 8: 00/80: not sure with left & right triggers
731 9: 80 normal, ...ff=left trigger, ...00=right trigger
732 10: Button bit flags: 01=A, ..., 80=start
733 11: Button bit flags: 01=left joy, 02=right joy, 04=hat up add 04 every 45 degrees right
734 12: varies with everything
735 13: "
736 ??: not sure where Xbox button is
737 */
738 // XXX Check to see that this works with HIDAPI, there may be two smaller reports.
739 if (bytes == 14) {
740 if (true) {
741 vrpn_uint8 *bufptr;
742
743 // Report joystick axes as analogs
744 // left joy left/right
745 vrpn_uint16 x, y;
746 bufptr = &buffer[0];
747 x = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr);
748 // left joy up/down
749 bufptr = &buffer[2];
750 y = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr);
751 normalize_axes(x, y, MS_GAMEPAD_LEFT_THUMB_DEADZONE, 1.0f, channel[0], channel[1]);
752 // right joy left/right
753 bufptr = &buffer[4];
754 x = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr);
755 // right joy up/down
756 bufptr = &buffer[6];
757 y = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr);
758 normalize_axes(x, y, MS_GAMEPAD_RIGHT_THUMB_DEADZONE, 1.0f, channel[2], channel[3]);
759
760 // triggers: left goes positive, right goes negative
761 channel[4] = normalize_trigger(buffer[9]);
762
763 vrpn_uint8 value;
764 value = buffer[10];
765 for (int btn = 0; btn < 8; btn++) {
766 /*
767 1: A
768 2: B
769 3: X
770 4: Y
771 5: left bump
772 6: right bump
773 7: back
774 8: start
775 */
776 vrpn_uint8 mask = static_cast<vrpn_uint8>(1 << (btn % 8));
777 buttons[btn] = ((value & mask) != 0);
778 }
779 value = buffer[11];
780 for (int btn = 0; btn < 2; btn++) {
781 /*
782 9: left joy
783 10: right joy
784 */
785 vrpn_uint8 mask = static_cast<vrpn_uint8>(1 << (btn % 8));
786 buttons[8 + btn] = ((value & mask) != 0);
787 }
788 value &= 0x3c; // remove joystick buttons and isolate just the "Point of View Hat"
789 value >>= 2;
790 /*
791 11: 04 (>>2=1, >>3=0) hat up (0)
792 08 (>>2=2, >>3=1) up-right (45)
793 12: 0c (>>2=3, >>3=1) hat right (90)
794 10 (>>2=4, >>3=2) right-down (135)
795 13: 14 (>>2=5, >>3=2) hat down (180)
796 18 (>>2=6, >>3=3) down-left (225)
797 14: 1c (>>2=7, >>3=3) hat left (270)
798 20 (>>2=8, >>3=4) left-up (315)
799 */
800 buttons[10] = buttons[11] = buttons[12] = buttons[13] = false;
801 if (value != 0)
802 {
803 //int lowerBtn = (10 + (value >> 3)) & 0x03;
804 switch (value)
805 {
806 case 1:
807 buttons[10] = true;
808 break;
809 case 2:
810 buttons[10] = buttons[11] = true;
811 break;
812 case 3:
813 buttons[11] = true;
814 break;
815 case 4:
816 buttons[11] = buttons[12] = true;
817 break;
818 case 5:
819 buttons[12] = true;
820 break;
821 case 6:
822 buttons[12] = buttons[13] = true;
823 break;
824 case 7:
825 buttons[13] = true;
826 break;
827 case 8:
828 buttons[13] = buttons[10] = true;
829 break;
830 }
831 }
832 channel[5] = normalize_dpad(buttons[10], buttons[11], buttons[12], buttons[13]);
833 } else {
834 fprintf(stderr, "vrpn_Microsoft_Controvrpn_Microsoft_Controller_Raw_Xbox_360_baseller_Raw_Xbox_360: Unknown report = %u\n", static_cast<unsigned>(buffer[0]));
835 }
836 } else {
837 fprintf(stderr, "vrpn_Microsoft_Controller_Raw_Xbox_360_base: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
838 }
839}
840
841// The original Xbox_360. We just declare the vendor and product ID.
846
847// The wireless Xbox_360. We just declare the vendor and product ID.
852
853// The device otherwise behaves exactly like an Xbox_360, so we re-use all of
854// the functions from that class. We just declare the vendor and product ID.
856 : vrpn_Microsoft_Controller_Raw_Xbox_360_base(name, c, AFTERGLOW_VENDOR, AX1_FOR_XBOX_360)
857{
858}
859
860// End of VRPN_USE_HID
861#endif
vrpn_Afterglow_Ax1_For_Xbox_360(const char *name, vrpn_Connection *c)
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)
struct timeval timestamp
Definition vrpn_Dial.h:28
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.
vrpn_Microsoft_Controller_Raw_Xbox_360_Wireless(const char *name, vrpn_Connection *c)
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
vrpn_Microsoft_Controller_Raw_Xbox_360_base(const char *name, vrpn_Connection *c=0, vrpn_uint16 vendor=0, vrpn_uint16 product=0)
vrpn_Microsoft_Controller_Raw_Xbox_360(const char *name, vrpn_Connection *c)
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 ...
vrpn_Microsoft_Controller_Raw_Xbox_S(const char *name, vrpn_Connection *c=0)
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)
virtual void decodePacket(size_t bytes, vrpn_uint8 *buffer)=0
vrpn_Microsoft_Controller_Raw(vrpn_HidAcceptor *filter, const char *name, vrpn_Connection *c=0, vrpn_uint16 vendor=0, vrpn_uint16 product=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 ...
vrpn_Microsoft_SideWinder_Precision_2(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 ...
vrpn_Microsoft_SideWinder(const char *name, vrpn_Connection *c=0)
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
#define MS_GAMEPAD_TRIGGER_THRESHOLD
#define MS_GAMEPAD_LEFT_THUMB_DEADZONE
#define MS_GAMEPAD_RIGHT_THUMB_DEADZONE
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