vrpn  07.33
Virtual Reality Peripheral Network
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 #if defined(VRPN_USE_HID)
12 
13 static const double POLL_INTERVAL = 1e+6 / 30.0; // If we have not heard, ask.
14 
15 #define MS_GAMEPAD_LEFT_THUMB_DEADZONE 7849
16 #define MS_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
17 #define MS_GAMEPAD_TRIGGER_THRESHOLD 30
18 
20 // helpers
22 static vrpn_float64 normalize_dpad(unsigned char up, unsigned char right, unsigned char down, unsigned char left)
23 {
24  int x = 0;
25  int y = 0;
26  if (right)
27  {
28  x += 1;
29  }
30  if (left)
31  {
32  x -= 1;
33  }
34  if (up)
35  {
36  y += 1;
37  }
38  if (down)
39  {
40  y -= 1;
41  }
42  size_t index = ((x + 1) * 3) + (y + 1);
43  vrpn_float64 angles[] = {225, 270, 315, 180, -1, 0, 135, 90, 45};
44  return (angles[index]);
45 }
46 
47 static void normalize_axis(const unsigned int value, const short deadzone, const vrpn_float64 scale, vrpn_float64& channel, int wordSize = 16)
48 {
49  channel = (static_cast<float>(value) - (float) (1 << (wordSize - 1)));
50  if (fabs(channel) < (deadzone * 3 / 4))
51  {
52  channel = 0.0f;
53  }
54  else
55  {
56  channel /= (float) (1 << (wordSize - 1));
57  }
58  channel *= scale;
59  if (channel < -1.0) { channel = -1.0; }
60  if (channel > 1.0) { channel = 1.0; }
61 }
62 
63 static 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)
64 {
65 #ifdef FUTURE
66  // adapted from: http://msdn.microsoft.com/en-us/library/windows/desktop/ee417001%28v=vs.85%29.aspx
67  // determine how far the controller is pushed
68  float magnitude = (float) sqrt((double) ((x * x) + (y * y)));
69 
70  // determine the direction the controller is pushed
71  float normalizedX = ((magnitude > 0.0f) ? (x / magnitude) : 0.0f);
72  float normalizedY = ((magnitude > 0.0f) ? (y / magnitude) : 0.0f);
73 
74  float normalizedMagnitude = 0.0f;
75 
76  // check if the controller is outside a circular dead zone
77  if (magnitude > deadzone)
78  {
79  // clip the magnitude at its expected maximum value
80  if (magnitude > 32767)
81  {
82  magnitude = 32767;
83  }
84 
85  // adjust magnitude relative to the end of the dead zone
86  magnitude -= deadzone;
87 
88  // optionally normalize the magnitude with respect to its
89  // expected range giving a magnitude value of 0.0 to 1.0
90  normalizedMagnitude = magnitude / (32767.0f - deadzone);
91  }
92  else
93  { // if the controller is in the deadzone zero out the magnitude
94  magnitude = 0.0f;
95  normalizedMagnitude = 0.0f;
96  }
97 #else
98  normalize_axis(x, deadzone, scale, channelX, wordSize);
99  normalize_axis(y, deadzone, scale, channelY, wordSize);
100 #endif // FUTURE
101 }
102 
103 static vrpn_float64 normalize_trigger(unsigned int trigger)
104 {
105  // Filter out low-intensity signals
106  int value = trigger - 0x80;
107  return ((fabs(static_cast<double>(value)) < MS_GAMEPAD_TRIGGER_THRESHOLD) ? 0.0f : (value * 2.0f / 255.0f));
108 }
109 
111 // Common base class
114  : _filter(filter)
115  , vrpn_HidInterface(filter)
116  , vrpn_BaseClass(name, c)
117 {
118  init_hid();
119 }
120 
122 {
123  delete _filter;
124 }
125 
127  // Get notifications when clients connect and disconnect
130 }
131 
132 void vrpn_Microsoft_Controller_Raw::on_data_received(size_t bytes, vrpn_uint8 *buffer)
133 {
134  decodePacket(bytes, buffer);
135 }
136 
138 {
139  vrpn_Microsoft_Controller_Raw *me = static_cast<vrpn_Microsoft_Controller_Raw *>(thisPtr);
140  return 0;
141 }
142 
144 {
145  vrpn_Microsoft_Controller_Raw *me = static_cast<vrpn_Microsoft_Controller_Raw *>(thisPtr);
146  return 0;
147 }
148 
150 // SideWinder Precision 2 Joystick
153  vrpn_Microsoft_Controller_Raw(_filter = new vrpn_HidProductAcceptor(MICROSOFT_VENDOR, SIDEWINDER_PRECISION_2), name, c),
154  vrpn_Button_Filter(name, c), vrpn_Analog(name, c), vrpn_Dial(name, c)
155 {
159 
160  // Initialize the state of all the analogs, buttons, and dials
161  memset(buttons, 0, sizeof(buttons));
162  memset(lastbuttons, 0, sizeof(lastbuttons));
163  memset(channel, 0, sizeof(channel));
164  memset(last, 0, sizeof(last));
165 }
166 
168 {
169  update();
170  server_mainloop();
171  struct timeval current_time;
172  vrpn_gettimeofday(&current_time, NULL);
173  if (vrpn_TimevalDuration(current_time, _timestamp) > POLL_INTERVAL)
174  {
175  _timestamp = current_time;
176  report_changes();
177 
180  if (vrpn_Dial::num_dials > 0)
181  {
183  }
184  }
185 }
186 
187 void vrpn_Microsoft_SideWinder_Precision_2::report(vrpn_uint32 class_of_service)
188 {
191  if (vrpn_Dial::num_dials > 0)
192  {
194  }
195 
196  vrpn_Analog::report_changes(class_of_service);
198  if (vrpn_Dial::num_dials > 0)
199  {
201  }
202 }
203 
205 {
208  if (vrpn_Dial::num_dials > 0)
209  {
211  }
212 
213  vrpn_Analog::report(class_of_service);
215  if (vrpn_Dial::num_dials > 0)
216  {
218  }
219 }
220 
221 void vrpn_Microsoft_SideWinder_Precision_2::decodePacket(size_t bytes, vrpn_uint8 *buffer)
222 {
223  // SideWinder Precision 2 joystick
224 
225  // Decode all full reports, each of which is 40 bytes long.
226  // Because there is only one type of report, the initial "0" report-type
227  // byte is removed by the HIDAPI driver.
228  /*
229  Byte : Bit 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0
230  [0]: X-axis (left=00, right=ff)
231  [1]: Y-axis (up=00, down=ff)
232  [2]: Z-rotate (left=00, right=ff)
233  [3]: Slider (up=00, down=ff)
234  [4]: buttons (bit flags: none=0x00, "1" (trigger)=0x01, "2"=0x02, "3"=0x04, ..., "8"=0x80
235  [5]: POV Hat high nibble (none=0x80, N=0x00, NE=0x10, ... NW=0x80)
236  */
237  // XXX Check to see that this works with HIDAPI, there may be two smaller reports.
238  if (bytes == 6)
239  {
240  normalize_axes(buffer[0], buffer[1], 0x08, 1.0f, channel[0], channel[1], 8);
241  normalize_axis(buffer[2], 0x08, 1.0f, channel[2], 8);
242  normalize_axis(buffer[3], 0x08, 1.0f, channel[3], 8);
243 
244  vrpn_uint8 value, mask;
245  value = buffer[4];
246  for (int btn = 0; btn < 8; btn++)
247  {
248  mask = static_cast<vrpn_uint8>(1 << (btn % 8));
249  buttons[btn] = ((value & mask) != 0);
250  }
251 
252  // Point of View Hat
253  buttons[8] = buttons[9] = buttons[10] = buttons[11] = 0;
254  switch (buffer[5] >> 4)
255  {
256  case 0: // up
257  buttons[8] = true;
258  break;
259  case 1:
260  buttons[8] = buttons[9] = true;
261  break;
262  case 2: // right
263  buttons[9] = true;
264  break;
265  case 3:
266  buttons[9] = buttons[10] = true;
267  break;
268  case 4: // down
269  buttons[10] = true;
270  break;
271  case 5:
272  buttons[10] = buttons[11] = true;
273  break;
274  case 6: // left
275  buttons[11] = true;
276  break;
277  case 7:
278  buttons[11] = buttons[8] = true;
279  break;
280  case 8:
281  default:
282  // nothing to do
283  break;
284  }
285  channel[4] = normalize_dpad(buttons[8], buttons[9], buttons[10], buttons[11]);
286  }
287  else
288  {
289  fprintf(stderr, "vrpn_Microsoft_SideWinder_Precision_2: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
290  }
291 }
292 
294 // SideWinder Joystick
297  vrpn_Microsoft_Controller_Raw(_filter = new vrpn_HidProductAcceptor(MICROSOFT_VENDOR, SIDEWINDER), name, c),
298  vrpn_Button_Filter(name, c), vrpn_Analog(name, c), vrpn_Dial(name, c)
299 {
303 
304  // Initialize the state of all the analogs, buttons, and dials
305  memset(buttons, 0, sizeof(buttons));
306  memset(lastbuttons, 0, sizeof(lastbuttons));
307  memset(channel, 0, sizeof(channel));
308  memset(last, 0, sizeof(last));
309 }
310 
312 {
313  update();
314  server_mainloop();
315  struct timeval current_time;
316  vrpn_gettimeofday(&current_time, NULL);
317  if (vrpn_TimevalDuration(current_time, _timestamp) > POLL_INTERVAL)
318  {
319  _timestamp = current_time;
320  report_changes();
321 
324  if (vrpn_Dial::num_dials > 0)
325  {
327  }
328  }
329 }
330 
331 void vrpn_Microsoft_SideWinder::report(vrpn_uint32 class_of_service)
332 {
335  if (vrpn_Dial::num_dials > 0)
336  {
338  }
339 
340  vrpn_Analog::report_changes(class_of_service);
342  if (vrpn_Dial::num_dials > 0)
343  {
345  }
346 }
347 
348 void vrpn_Microsoft_SideWinder::report_changes(vrpn_uint32 class_of_service)
349 {
352  if (vrpn_Dial::num_dials > 0)
353  {
355  }
356 
357  vrpn_Analog::report(class_of_service);
359  if (vrpn_Dial::num_dials > 0)
360  {
362  }
363 }
364 
365 void vrpn_Microsoft_SideWinder::decodePacket(size_t bytes, vrpn_uint8 *buffer)
366 {
367  // SideWinder Precision 2 joystick
368 
369  // Decode all full reports, each of which is 40 bytes long.
370  // Because there is only one type of report, the initial "0" report-type
371  // byte is removed by the HIDAPI driver.
372  /*
373  Byte : Bit 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0
374  [0]: X-axis (left=00, right=ff)
375  [1]: Y-axis (up=00, down=ff)
376  [2]: slider (up/fwd=00, down/back=ff)
377  [3]: buttons (bit flags: none=0x00, "1" (trigger)=0x01, "2"=0x02, "3"=0x04, ..., "8"=0x80)
378  */
379  // XXX Check to see that this works with HIDAPI, there may be two smaller reports.
380  if (bytes == 4)
381  {
382  normalize_axes(buffer[0], buffer[1], 0x08, 1.0f, channel[0], channel[1], 8);
383  normalize_axis(buffer[2], 0x08, 1.0f, channel[2], 8);
384 
385  vrpn_uint8 value, mask;
386  value = buffer[3];
387  for (int btn = 0; btn < 8; btn++)
388  {
389  mask = static_cast<vrpn_uint8>(1 << (btn % 8));
390  buttons[btn] = ((value & mask) != 0);
391  }
392  }
393  else
394  {
395  fprintf(stderr, "vrpn_Microsoft_SideWinder: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
396  }
397 }
398 
400 // Xbox S
403  : vrpn_Microsoft_Controller_Raw(_filter = new vrpn_HidProductAcceptor(MICROSOFT_VENDOR, XBOX_S), name, c)
404  , vrpn_Button_Filter(name, c)
405  , vrpn_Analog(name, c)
406  , vrpn_Dial(name, c)
407 {
411 
412  // Initialize the state of all the analogs, buttons, and dials
413  _lastDial = 0;
414  memset(buttons, 0, sizeof(buttons));
415  memset(lastbuttons, 0, sizeof(lastbuttons));
416  memset(channel, 0, sizeof(channel));
417  memset(last, 0, sizeof(last));
418 }
419 
421 {
422  update();
423  server_mainloop();
424  struct timeval current_time;
425  vrpn_gettimeofday(&current_time, NULL);
426  if (vrpn_TimevalDuration(current_time, _timestamp) > POLL_INTERVAL ) {
427  _timestamp = current_time;
428  report_changes();
429 
432  if (vrpn_Dial::num_dials > 0)
433  {
435  }
436  }
437 }
438 
439 void vrpn_Microsoft_Controller_Raw_Xbox_S::report(vrpn_uint32 class_of_service) {
442  if (vrpn_Dial::num_dials > 0)
443  {
445  }
446 
447  vrpn_Analog::report_changes(class_of_service);
449  if (vrpn_Dial::num_dials > 0)
450  {
452  }
453 }
454 
455 void vrpn_Microsoft_Controller_Raw_Xbox_S::report_changes(vrpn_uint32 class_of_service) {
458  if (vrpn_Dial::num_dials > 0)
459  {
461  }
462 
463  vrpn_Analog::report_changes(class_of_service);
465  if (vrpn_Dial::num_dials > 0)
466  {
468  }
469 }
470 
471 void vrpn_Microsoft_Controller_Raw_Xbox_S::decodePacket(size_t bytes, vrpn_uint8 *buffer) {
472  // Xbox Controller S requires adapter to be made/purchased to connect USB to computer.
473  // Also, it may require a driver to be installed such as XBCD_Installer_0.2.7.exe (Windows).
474 
475  // Decode all full reports, each of which is 40 bytes long.
476  // Because there is only one type of report, the initial "0" report-type
477  // byte is removed by the HIDAPI driver.
478  /*
479  Byte : Bit 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0
480  [0] : | Report ID |
481  [1] : |B8 |B7 |B6 |B5 |B4 |B3 |B2 |B1 |
482  [2] : |B16|B15|B14|B13|B12|B11|B10|B9 |
483  [3] : |B24|B23|B22|B21|B20|B19|B18|B17| <------- no such buttons exist and data does not change
484  [4-5] : | X Axis |
485  [6-7] : | Y Axis |
486  [8-9] : | Z Axis |
487  [10-11] : | RX Axis |
488  [12-13]: | RY Axis |
489  [14-15]: | RZ Axis |
490  [16-17]: | Slider Axis |
491  [18] : | EMPTY | POV |
492  [19] : | Current MapMatrix |
493  --- Original data from Xbox controller ---
494  [20] : | 0x00 |
495  [21] : | 0x14(Size of report) |
496  [22] : |RSp|LSp|Bk |St |Rgt|Lft|Dn |Up | <------- other buttons
497  [23] : | 0x00 |
498  [24] : | Button A |
499  [25] : | Button B |
500  [26] : | Button X |
501  [27] : | Button Y |
502  [28] : | Button Black |
503  [29] : | Button White |
504  [30] : | Left Trigger |
505  [31] : | Right Trigger |
506  [32-33]: | Left-Stick X |
507  [34-35]: | Left-Stick Y |
508  [36-37]: | Right-Stick X |
509  [38-39]: | Right-Stick Y |
510  */
511  // XXX Check to see that this works with HIDAPI, there may be two smaller reports.
512  if (bytes == 40) {
513  if (buffer[0] == 1) {
514 
515  // Report joystick axes as analogs
516  vrpn_uint16 x, y;
517  vrpn_uint8 *bufptr;
518 #ifdef OLD_DATA
519  // left joy left/right: Left 27, center (normal) 81 (calc 7e), right D5
520  bufptr = &buffer[32];
521  x = vrpn_unbuffer<vrpn_int16>(bufptr);
522  // left joy up/down: Up 34, center (normal) 81 (calc 81), down CF
523  bufptr = &buffer[34];
524  y = vrpn_unbuffer<vrpn_int16>(bufptr);
525  normalize_axes(x, y, MS_GAMEPAD_LEFT_THUMB_DEADZONE, 1.0f, channel[0], channel[1]);
526  // right joy up/down: Up 32, (center calc 7f), down CC
527  bufptr = &buffer[36];
528  x = vrpn_unbuffer<vrpn_int16>(bufptr);
529  // right joy left/right: Left 2B, center (normal) 82 (calc 84), right DC
530  bufptr = &buffer[38];
531  y = vrpn_unbuffer<vrpn_int16>(bufptr);
532  normalize_axes(x, y, MS_GAMEPAD_RIGHT_THUMB_DEADZONE, 1.0f, channel[2], channel[3]);
533 #else
534  vrpn_int16 temp;
535  bufptr = &buffer[4];
536  temp = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr) / 2;
537  x = temp + (1 << 15);
538  x *= 2;
539  bufptr = &buffer[6];
540  temp = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr) / 2;
541  y = temp + (1 << 15);
542  y *= 2;
543  normalize_axes(x, y, MS_GAMEPAD_LEFT_THUMB_DEADZONE, 1.0f, channel[0], channel[1]);
544  bufptr = &buffer[10];
545  temp = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr) / 2;
546  x = temp + (1 << 15);
547  bufptr = &buffer[12];
548  temp = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr) / 2;
549  y = temp + (1 << 15);
550  normalize_axes(x, y, MS_GAMEPAD_LEFT_THUMB_DEADZONE, 2.0f, channel[2], channel[3]);
551 #endif // OLD_DATA
552 
553 #ifdef OLD_DATA
554  // button #0: 24 A
555  buttons[0] = (buffer[24] != 0);
556  // button #1: 25 B
557  buttons[1] = (buffer[25] != 0);
558  // button #2: 26 X
559  buttons[2] = (buffer[26] != 0);
560  // button #3: 27 Y
561  buttons[3] = (buffer[27] != 0);
562  // button #4: 28 Black
563  buttons[4] = (buffer[28] != 0);
564  // button #5: 29 White
565  buttons[5] = (buffer[29] != 0);
566  // button #6: 40 Start
567  buttons[6] = ((buffer[22] & 0x10) != 0);
568  // button #7: 80 Back
569  buttons[7] = ((buffer[22] & 0x20) != 0);
570  // button #8: left joy
571  buttons[8] = ((buffer[22] & 0x40) != 0);
572  // button #9: right joy
573  buttons[9] = ((buffer[22] & 0x80) != 0);
574  // button #10:30 left trigger
575  buttons[10] = (buffer[30] != 0);
576  // button #11:31 right trigger
577  buttons[11] = (buffer[31] != 0);
578 #else
579  vrpn_uint8 value, mask;
580  value = buffer[1];
581  for (int btn = 0; btn < 8; btn++)
582  {
583  mask = static_cast<vrpn_uint8>(1 << (btn % 8));
584  buttons[btn] = ((value & mask) != 0);
585  }
586  value = buffer[2];
587  for (int btn = 0; btn < 4; btn++)
588  {
589  mask = static_cast<vrpn_uint8>(1 << (btn % 8));
590  buttons[8 + btn] = ((value & mask) != 0);
591  }
592 #endif // OLD_DATA
593 
594  // Point of View Hat
595 #ifdef OLD_DATA
596  buttons[12] = ((buffer[22] & 0x01) != 0); // Up
597  buttons[14] = ((buffer[22] & 0x02) != 0); // Down
598  buttons[15] = ((buffer[22] & 0x04) != 0); // Left
599  buttons[13] = ((buffer[22] & 0x08) != 0); // Right
600 #else
601  // Point of View Hat
602  buttons[12] = buttons[13] = buttons[14] = buttons[15] = 0;
603  switch (buffer[18] & 0x0f)
604  {
605  case 0: // up
606  buttons[12] = true;
607  break;
608  case 1:
609  buttons[12] = buttons[13] = true;
610  break;
611  case 2: // right
612  buttons[13] = true;
613  break;
614  case 3:
615  buttons[13] = buttons[14] = true;
616  break;
617  case 4: // down
618  buttons[14] = true;
619  break;
620  case 5:
621  buttons[14] = buttons[15] = true;
622  break;
623  case 6: // left
624  buttons[15] = true;
625  break;
626  case 7:
627  buttons[15] = buttons[12] = true;
628  break;
629  case 8:
630  default:
631  // nothing to do
632  break;
633  }
634 #endif // OLD_DATA
635  channel[4] = normalize_dpad(buttons[12], buttons[13], buttons[14], buttons[15]);
636  } else {
637  fprintf(stderr, "vrpn_Microsoft_Controller_Raw_Xbox_S: Unknown report = %u\n", static_cast<unsigned>(buffer[0]));
638  }
639  } else {
640  fprintf(stderr, "vrpn_Microsoft_Controller_Raw_Xbox_S: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
641  }
642 }
643 
645 // Xbox 360
647 vrpn_Microsoft_Controller_Raw_Xbox_360::vrpn_Microsoft_Controller_Raw_Xbox_360(const char *name, vrpn_Connection *c, vrpn_uint16 vendorId /*=MICROSOFT_VENDOR*/, vrpn_uint16 productId /*=XBOX_360*/)
648 : vrpn_Microsoft_Controller_Raw(_filter = new vrpn_HidProductAcceptor(vendorId, productId), name, c)
649 , vrpn_Button_Filter(name, c)
650 , vrpn_Analog(name, c)
651 , vrpn_Dial(name, c)
652 {
656 
657  // Initialize the state of all the analogs, buttons, and dials
658  _lastDial = 0;
659  memset(buttons, 0, sizeof(buttons));
660  memset(lastbuttons, 0, sizeof(lastbuttons));
661  memset(channel, 0, sizeof(channel));
662  memset(last, 0, sizeof(last));
663 }
664 
666 {
667  update();
668  server_mainloop();
669  struct timeval current_time;
670  vrpn_gettimeofday(&current_time, NULL);
671  if (vrpn_TimevalDuration(current_time, _timestamp) > POLL_INTERVAL ) {
672  _timestamp = current_time;
673  report_changes();
674 
677  if (vrpn_Dial::num_dials > 0)
678  {
680  }
681  }
682 }
683 
684 void vrpn_Microsoft_Controller_Raw_Xbox_360::report(vrpn_uint32 class_of_service) {
687  if (vrpn_Dial::num_dials > 0)
688  {
690  }
691 
692  vrpn_Analog::report_changes(class_of_service);
694  if (vrpn_Dial::num_dials > 0)
695  {
697  }
698 }
699 
700 void vrpn_Microsoft_Controller_Raw_Xbox_360::report_changes(vrpn_uint32 class_of_service) {
703  if (vrpn_Dial::num_dials > 0)
704  {
706  }
707 
708  vrpn_Analog::report(class_of_service);
710  if (vrpn_Dial::num_dials > 0)
711  {
713  }
714 }
715 
716 void vrpn_Microsoft_Controller_Raw_Xbox_360::decodePacket(size_t bytes, vrpn_uint8 *buffer) {
717  // Decode all full reports, each of which is 14 bytes long.
718  // Because there is only one type of report, the initial "0" report-type
719  // byte is removed by the HIDAPI driver.
720  /*
721  0: left-X
722  1: "
723  2: left-Y
724  3: "
725  4: right-X
726  5: "
727  6: right-Y
728  7: "
729  8: 00/80: not sure with left & right triggers
730  9: 80 normal, ...ff=left trigger, ...00=right trigger
731  10: Button bit flags: 01=A, ..., 80=start
732  11: Button bit flags: 01=left joy, 02=right joy, 04=hat up add 04 every 45 degrees right
733  12: varies with everything
734  13: "
735  ??: not sure where Xbox button is
736  */
737  // XXX Check to see that this works with HIDAPI, there may be two smaller reports.
738  if (bytes == 14) {
739  if (true) {
740  vrpn_uint8 *bufptr;
741 
742  // Report joystick axes as analogs
743  // left joy left/right
744  vrpn_uint16 x, y;
745  bufptr = &buffer[0];
746  x = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr);
747  // left joy up/down
748  bufptr = &buffer[2];
749  y = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr);
750  normalize_axes(x, y, MS_GAMEPAD_LEFT_THUMB_DEADZONE, 1.0f, channel[0], channel[1]);
751  // right joy left/right
752  bufptr = &buffer[4];
753  x = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr);
754  // right joy up/down
755  bufptr = &buffer[6];
756  y = vrpn_unbuffer_from_little_endian<vrpn_int16>(bufptr);
757  normalize_axes(x, y, MS_GAMEPAD_RIGHT_THUMB_DEADZONE, 1.0f, channel[2], channel[3]);
758 
759  // triggers: left goes positive, right goes negative
760  channel[4] = normalize_trigger(buffer[9]);
761 
762  vrpn_uint8 value;
763  value = buffer[10];
764  for (int btn = 0; btn < 8; btn++) {
765  /*
766  1: A
767  2: B
768  3: X
769  4: Y
770  5: left bump
771  6: right bump
772  7: back
773  8: start
774  */
775  vrpn_uint8 mask = static_cast<vrpn_uint8>(1 << (btn % 8));
776  buttons[btn] = ((value & mask) != 0);
777  }
778  value = buffer[11];
779  for (int btn = 0; btn < 2; btn++) {
780  /*
781  9: left joy
782  10: right joy
783  */
784  vrpn_uint8 mask = static_cast<vrpn_uint8>(1 << (btn % 8));
785  buttons[8 + btn] = ((value & mask) != 0);
786  }
787  value &= 0x3c; // remove joystick buttons and isolate just the "Point of View Hat"
788  value >>= 2;
789  /*
790  11: 04 (>>2=1, >>3=0) hat up (0)
791  08 (>>2=2, >>3=1) up-right (45)
792  12: 0c (>>2=3, >>3=1) hat right (90)
793  10 (>>2=4, >>3=2) right-down (135)
794  13: 14 (>>2=5, >>3=2) hat down (180)
795  18 (>>2=6, >>3=3) down-left (225)
796  14: 1c (>>2=7, >>3=3) hat left (270)
797  20 (>>2=8, >>3=4) left-up (315)
798  */
799  buttons[10] = buttons[11] = buttons[12] = buttons[13] = false;
800  if (value != 0)
801  {
802  int lowerBtn = (10 + (value >> 3)) & 0x03;
803  switch (value)
804  {
805  case 1:
806  buttons[10] = true;
807  break;
808  case 2:
809  buttons[10] = buttons[11] = true;
810  break;
811  case 3:
812  buttons[11] = true;
813  break;
814  case 4:
815  buttons[11] = buttons[12] = true;
816  break;
817  case 5:
818  buttons[12] = true;
819  break;
820  case 6:
821  buttons[12] = buttons[13] = true;
822  break;
823  case 7:
824  buttons[13] = true;
825  break;
826  case 8:
827  buttons[13] = buttons[10] = true;
828  break;
829  }
830  }
831  channel[5] = normalize_dpad(buttons[10], buttons[11], buttons[12], buttons[13]);
832  } else {
833  fprintf(stderr, "vrpn_Microsoft_Controller_Raw_Xbox_360: Unknown report = %u\n", static_cast<unsigned>(buffer[0]));
834  }
835  } else {
836  fprintf(stderr, "vrpn_Microsoft_Controller_Raw_Xbox_360: Found a corrupted report; # total bytes = %u\n", static_cast<unsigned>(bytes));
837  }
838 }
839 
840 // End of VRPN_USE_HID
841 #endif
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
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
vrpn_Microsoft_Controller_Raw(vrpn_HidAcceptor *filter, const char *name, vrpn_Connection *c=0)
#define MS_GAMEPAD_TRIGGER_THRESHOLD
vrpn_Microsoft_Controller_Raw_Xbox_360(const char *name, vrpn_Connection *c=0, vrpn_uint16 vendorId=MICROSOFT_VENDOR, vrpn_uint16 productId=XBOX_360)
vrpn_int32 num_buttons
Definition: vrpn_Button.h:47
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
vrpn_Microsoft_SideWinder(const char *name, vrpn_Connection *c=0)
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:38
Accepts any device with the given vendor and product IDs.
struct timeval timestamp
Definition: vrpn_Dial.h:28
Generic connection class not specific to the transport mechanism.
vrpn_int32 num_dials
Definition: vrpn_Dial.h:27
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
#define VRPN_SUPPRESS_EMPTY_OBJECT_WARNING()
const char * vrpn_dropped_last_connection
virtual void report_changes(void)
Definition: vrpn_Button.C:382
virtual void report_changes(void)
Definition: vrpn_Button.C:422
vrpn_int32 num_channel
Definition: vrpn_Analog.h:40
#define MS_GAMEPAD_LEFT_THUMB_DEADZONE
virtual void report(void)
Definition: vrpn_Dial.C:82
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.
This structure is what is passed to a vrpn_Connection message callback.
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
vrpn_Microsoft_Controller_Raw_Xbox_S(const char *name, vrpn_Connection *c=0)
#define POLL_INTERVAL
Definition: vrpn_IDEA.C:26
const char * vrpn_got_connection
static int VRPN_CALLBACK on_last_disconnect(void *thisPtr, vrpn_HANDLERPARAM p)
struct timeval timestamp
Definition: vrpn_Button.h:48
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
virtual void update()
Polls the device buffers and causes on_data_received callbacks if appropriate You NEED to call this f...
Class from which all user-level (and other) classes that communicate with vrpn_Connections should der...
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
All button servers should derive from this class, which provides the ability to turn any of the butto...
Definition: vrpn_Button.h:65
#define MS_GAMEPAD_RIGHT_THUMB_DEADZONE
unsigned char lastbuttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:45
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 ...
static int VRPN_CALLBACK on_connect(void *thisPtr, vrpn_HANDLERPARAM p)
void on_data_received(size_t bytes, vrpn_uint8 *buffer)
Derived class reimplements this callback.
vrpn_Microsoft_SideWinder_Precision_2(const char *name, vrpn_Connection *c=0)
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:44
unsigned long vrpn_TimevalDuration(struct timeval endT, struct timeval startT)
Return number of microseconds between startT and endT.
Definition: vrpn_Shared.C:129
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
virtual vrpn_int32 register_message_type(const char *name)
virtual void decodePacket(size_t bytes, vrpn_uint8 *buffer)=0
struct timeval timestamp
Definition: vrpn_Analog.h:41
vrpn_float64 last[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:39