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
vrpn_BaseClassUnique::register_autodeleted_handler
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.
Definition: vrpn_BaseClass.C:503
vrpn_Microsoft_Controller_Raw::_filter
vrpn_HidAcceptor * _filter
Definition: vrpn_Microsoft_Controller_Raw.h:54
vrpn_Microsoft_Controller_Raw::on_last_disconnect
static int VRPN_CALLBACK on_last_disconnect(void *thisPtr, vrpn_HANDLERPARAM p)
Definition: vrpn_Microsoft_Controller_Raw.C:137
vrpn_Dial::report
virtual void report(void)
Definition: vrpn_Dial.C:82
vrpn_Microsoft_SideWinder::mainloop
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_Microsoft_Controller_Raw.C:311
vrpn_Button::report_changes
virtual void report_changes(void)
Definition: vrpn_Button.C:422
vrpn_got_connection
const char * vrpn_got_connection
Definition: vrpn_Connection.C:185
vrpn_TimevalDuration
unsigned long vrpn_TimevalDuration(struct timeval endT, struct timeval startT)
Return number of microseconds between startT and endT.
Definition: vrpn_Shared.C:129
vrpn_Button_Filter::report_changes
virtual void report_changes(void)
Definition: vrpn_Button.C:382
vrpn_Analog::channel
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:38
vrpn_HidInterface
Definition: vrpn_HumanInterface.h:68
vrpn_Microsoft_SideWinder_Precision_2::mainloop
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_Microsoft_Controller_Raw.C:167
vrpn_dropped_last_connection
const char * vrpn_dropped_last_connection
Definition: vrpn_Connection.C:187
vrpn_Analog::report
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
vrpn_Analog
Definition: vrpn_Analog.h:28
vrpn_Microsoft_Controller_Raw::vrpn_Microsoft_Controller_Raw
vrpn_Microsoft_Controller_Raw(vrpn_HidAcceptor *filter, const char *name, vrpn_Connection *c=0)
Definition: vrpn_Microsoft_Controller_Raw.C:113
vrpn_Analog::timestamp
struct timeval timestamp
Definition: vrpn_Analog.h:41
vrpn_Microsoft_Controller_Raw_Xbox_S::_lastDial
vrpn_uint8 _lastDial
Definition: vrpn_Microsoft_Controller_Raw.h:108
vrpn_HidInterface::update
virtual void update()
Polls the device buffers and causes on_data_received callbacks if appropriate You NEED to call this f...
Definition: vrpn_HumanInterface.C:140
vrpn_HidAcceptor
Definition: vrpn_HumanInterface.h:54
vrpn_Microsoft_Controller_Raw_Xbox_360::decodePacket
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
Definition: vrpn_Microsoft_Controller_Raw.C:716
vrpn_Microsoft_SideWinder_Precision_2::decodePacket
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
Definition: vrpn_Microsoft_Controller_Raw.C:221
MS_GAMEPAD_RIGHT_THUMB_DEADZONE
#define MS_GAMEPAD_RIGHT_THUMB_DEADZONE
Definition: vrpn_Microsoft_Controller_Raw.C:16
vrpn_Button::num_buttons
vrpn_int32 num_buttons
Definition: vrpn_Button.h:47
vrpn_Microsoft_Controller_Raw::~vrpn_Microsoft_Controller_Raw
virtual ~vrpn_Microsoft_Controller_Raw(void)
Definition: vrpn_Microsoft_Controller_Raw.C:121
vrpn_Microsoft_Controller_Raw::init_hid
void init_hid(void)
Definition: vrpn_Microsoft_Controller_Raw.C:126
POLL_INTERVAL
#define POLL_INTERVAL
Definition: vrpn_IDEA.C:26
vrpn_Button::buttons
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:44
vrpn_BaseClassUnique::d_connection
vrpn_Connection * d_connection
Connection that this object talks to.
Definition: vrpn_BaseClass.h:224
MS_GAMEPAD_LEFT_THUMB_DEADZONE
#define MS_GAMEPAD_LEFT_THUMB_DEADZONE
Definition: vrpn_Microsoft_Controller_Raw.C:15
vrpn_Connection::register_message_type
virtual vrpn_int32 register_message_type(const char *name)
Definition: vrpn_Connection.C:5074
vrpn_Dial
Definition: vrpn_Dial.h:21
vrpn_HANDLERPARAM
This structure is what is passed to a vrpn_Connection message callback.
Definition: vrpn_Connection.h:44
vrpn_HidProductAcceptor
Accepts any device with the given vendor and product IDs.
Definition: vrpn_HumanInterface.h:150
vrpn_Button::timestamp
struct timeval timestamp
Definition: vrpn_Button.h:48
vrpn_Microsoft_Controller_Raw::on_data_received
void on_data_received(size_t bytes, vrpn_uint8 *buffer)
Derived class reimplements this callback.
Definition: vrpn_Microsoft_Controller_Raw.C:132
vrpn_Microsoft_Controller_Raw::decodePacket
virtual void decodePacket(size_t bytes, vrpn_uint8 *buffer)=0
vrpn_Microsoft_Controller_Raw_Xbox_S::mainloop
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_Microsoft_Controller_Raw.C:420
vrpn_Microsoft_SideWinder::decodePacket
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
Definition: vrpn_Microsoft_Controller_Raw.C:365
vrpn_Connection
Generic connection class not specific to the transport mechanism.
Definition: vrpn_Connection.h:510
vrpn_Analog::num_channel
vrpn_int32 num_channel
Definition: vrpn_Analog.h:40
vrpn_Microsoft_Controller_Raw_Xbox_S::vrpn_Microsoft_Controller_Raw_Xbox_S
vrpn_Microsoft_Controller_Raw_Xbox_S(const char *name, vrpn_Connection *c=0)
Definition: vrpn_Microsoft_Controller_Raw.C:402
vrpn_gettimeofday
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
vrpn_Button::lastbuttons
unsigned char lastbuttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:45
vrpn_Microsoft_Controller_Raw::on_connect
static int VRPN_CALLBACK on_connect(void *thisPtr, vrpn_HANDLERPARAM p)
Definition: vrpn_Microsoft_Controller_Raw.C:143
vrpn_Microsoft_Controller_Raw::_timestamp
struct timeval _timestamp
Definition: vrpn_Microsoft_Controller_Raw.h:53
MS_GAMEPAD_TRIGGER_THRESHOLD
#define MS_GAMEPAD_TRIGGER_THRESHOLD
Definition: vrpn_Microsoft_Controller_Raw.C:17
vrpn_Microsoft_SideWinder::vrpn_Microsoft_SideWinder
vrpn_Microsoft_SideWinder(const char *name, vrpn_Connection *c=0)
Definition: vrpn_Microsoft_Controller_Raw.C:296
vrpn_Analog::last
vrpn_float64 last[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:39
vrpn_Microsoft_Controller_Raw_Xbox_360::_lastDial
vrpn_uint8 _lastDial
Definition: vrpn_Microsoft_Controller_Raw.h:127
vrpn_Microsoft_Controller_Raw
Definition: vrpn_Microsoft_Controller_Raw.h:37
vrpn_Microsoft_Controller_Raw_Xbox_360::mainloop
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_Microsoft_Controller_Raw.C:665
vrpn_Microsoft_Controller_Raw_Xbox_360::vrpn_Microsoft_Controller_Raw_Xbox_360
vrpn_Microsoft_Controller_Raw_Xbox_360(const char *name, vrpn_Connection *c=0, vrpn_uint16 vendorId=MICROSOFT_VENDOR, vrpn_uint16 productId=XBOX_360)
Definition: vrpn_Microsoft_Controller_Raw.C:647
vrpn_Microsoft_Controller_Raw.h
vrpn_Microsoft_SideWinder_Precision_2::vrpn_Microsoft_SideWinder_Precision_2
vrpn_Microsoft_SideWinder_Precision_2(const char *name, vrpn_Connection *c=0)
Definition: vrpn_Microsoft_Controller_Raw.C:152
vrpn_Analog::report_changes
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_SUPPRESS_EMPTY_OBJECT_WARNING
#define VRPN_SUPPRESS_EMPTY_OBJECT_WARNING()
Definition: vrpn_Configure.h:495
vrpn_Microsoft_Controller_Raw_Xbox_S::decodePacket
void decodePacket(size_t bytes, vrpn_uint8 *buffer)
Definition: vrpn_Microsoft_Controller_Raw.C:471
vrpn_Dial::num_dials
vrpn_int32 num_dials
Definition: vrpn_Dial.h:27
vrpn_Dial::timestamp
struct timeval timestamp
Definition: vrpn_Dial.h:28
vrpn_BaseClassUnique::server_mainloop
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
Definition: vrpn_BaseClass.C:603
vrpn_BaseClass
Class from which all user-level (and other) classes that communicate with vrpn_Connections should der...
Definition: vrpn_BaseClass.h:313
vrpn_Button_Filter
All button servers should derive from this class, which provides the ability to turn any of the butto...
Definition: vrpn_Button.h:65