vrpn  07.33
Virtual Reality Peripheral Network
vrpn_WiiMote.C
Go to the documentation of this file.
1 // vrpn_WiiMote.C: Drive for the WiiMote, based on the WiiUse library.
2 //
3 // Russ Taylor, revised December 2008
4 
5 #include "vrpn_WiiMote.h"
6 
7 #if defined(VRPN_USE_WIIUSE)
8 #include <stdio.h>
9 #include <stdlib.h>
10 #ifndef _WIN32
11 #include <unistd.h>
12 #endif
13 
14 #include VRPN_WIIUSE_H
15 
16 #include <string>
17 
19 #ifndef WIIUSE_HAS_VERSION
20 #define WIIUSE_HAS_VERSION(major, minor, patch) false
21 #endif
22 
23 // Opaque class to hold WiiMote device information so we don't have
24 // to include wiimote.h in the vrpn_WiiMote.h file.
25 class vrpn_Wiimote_Device {
26  public:
27  vrpn_Wiimote_Device() :
28  device(NULL),
29  which(0),
30  useMS(0),
31  useIR(0),
32  reorderButtons(false),
33  found(false),
34  connected(false) {}
35  struct wiimote_t *device;
36  unsigned which;
37  unsigned useMS;
38  unsigned useIR;
39  bool reorderButtons;
40  bool found;
41  bool connected;
42  std::string bdaddr;
43 };
44 
45 // Helper routines.
46 #ifndef min
47 #define min(x,y) ((x)<(y)?(x):(y))
48 #endif
49 
50 #if defined (vrpn_THREADS_AVAILABLE)
51 struct vrpn_WiiMote_SharedData {
52  vrpn_WiiMote_SharedData(vrpn_WiiMote* wm)
53  : connectLock(), wmHandle(wm), msgLock(), stopFlag(false), running(false)
54  {}
55  vrpn_Semaphore connectLock;
56  vrpn_WiiMote *wmHandle;
57  vrpn_Semaphore msgLock;
58  bool stopFlag;
59  bool running;
60 };
61 #endif
62 
63 
64 inline void vrpn_WiiMote::acquireMessageLock() {
65 #if defined (vrpn_THREADS_AVAILABLE)
66  // altering server state needs to be synced with server main loop!
67  sharedData->msgLock.p();
68 #endif
69 }
70 
71 inline void vrpn_WiiMote::releaseMessageLock() {
72 #if defined (vrpn_THREADS_AVAILABLE)
73  sharedData->msgLock.v();
74 #endif
75 }
76 
77 unsigned vrpn_WiiMote::map_button(unsigned btn) {
78  switch (btn) {
79  case 0: //WIIMOTE_BUTTON_TWO:
80  return 2;
81  case 1: //WIIMOTE_BUTTON_ONE:
82  return 1;
83  case 2: //WIIMOTE_BUTTON_B:
84  return 4;
85  case 3: //WIIMOTE_BUTTON_A:
86  return 3;
87  case 4: //WIIMOTE_BUTTON_MINUS:
88  return 5;
89  case 5: //WIIMOTE_BUTTON_ZACCEL_BIT6
90  return 13;
91  case 6: //WIIMOTE_BUTTON_ZACCEL_BIT7
92  return 14;
93  case 7: //WIIMOTE_BUTTON_HOME:
94  return 0;
95  case 8: //WIIMOTE_BUTTON_LEFT:
96  return 7;
97  case 9: //WIIMOTE_BUTTON_RIGHT:
98  return 8;
99  case 10: //WIIMOTE_BUTTON_DOWN:
100  return 9;
101  case 11: //WIIMOTE_BUTTON_UP:
102  return 10;
103  case 12: //WIIMOTE_BUTTON_PLUS:
104  return 6;
105  case 13: //WIIMOTE_BUTTON_ZACCEL_BIT4
106  return 11;
107  case 14: //WIIMOTE_BUTTON_ZACCEL_BIT5
108  return 12;
109  case 15: //WIIMOTE_BUTTON_UNKNOWN
110  return 15;
111  default:
112 #ifdef DEBUG
113  fprintf(stderr, "WiiMote: unhandled button %d\n", btn);
114 #endif
115  return btn;
116  }
117 }
118 
119 void vrpn_WiiMote::handle_event() {
120  //-------------------------------------------------------------------------
121  // Set the status of the buttons. The first 16 buttons come from
122  // the main contoller. If there is an expansion controller plugged in,
123  // then there is a second set of up to 16 buttons that can be read from it.
124  unsigned i;
125  for (i = 0; i < 16; i++) {
126  if (wiimote->reorderButtons) {
127  buttons[map_button(i)] = (wiimote->device->btns & (1 << i)) != 0;
128  } else {
129  buttons[i] = (wiimote->device->btns & (1 << i)) != 0;
130  }
131  }
132 
133  switch (wiimote->device->exp.type) {
134  case EXP_NONE:
135  // No expansion buttons to grab
136  break;
137  case EXP_NUNCHUK:
138  for (i = 0; i < 16; i++) {
139  buttons[16 + i] = (wiimote->device->exp.nunchuk.btns & (1 << i)) != 0;
140  }
141  break;
142 
143  case EXP_CLASSIC:
144  for (i = 0; i < 16; i++) {
145  buttons[32 + i] = (wiimote->device->exp.classic.btns & (1 << i)) != 0;
146  }
147  break;
148 
149  case EXP_GUITAR_HERO_3:
150  for (i = 0; i < 16; i++) {
151  buttons[48 + i] = (wiimote->device->exp.gh3.btns & (1 << i)) != 0;
152  }
153  break;
154 #ifdef EXP_WII_BOARD
155  case EXP_WII_BOARD:
156  // The balance board pretends to be its own wiimote, with only an "a" button
157  // Use to calibrate, in a perfect world..
158  if (IS_PRESSED(wiimote->device, WIIMOTE_BUTTON_A)) {
159  wiiuse_set_wii_board_calib(wiimote->device);
160  }
161  break;
162 #endif
163  }
164 
165  //-------------------------------------------------------------------------
166  // Read the status of the analog values. There are six of them for the
167  // base unit and extras for expansion units.
168  channel[0] = wiimote->device->battery_level;
169  if (WIIUSE_USING_ACC(wiimote->device)) {
170  channel[1] = wiimote->device->gforce.x;
171  channel[2] = wiimote->device->gforce.y;
172  channel[3] = wiimote->device->gforce.z;
173  }
174  if (WIIUSE_USING_IR(wiimote->device)) {
175  unsigned dot;
176  for (dot = 0; dot < 4; dot++) {
177  if (wiimote->device->ir.dot[dot].visible) {
178  channel[4 + 3 * dot + 0] = wiimote->device->ir.dot[dot].rx;
179  channel[4 + 3 * dot + 1] = wiimote->device->ir.dot[dot].ry;
180  channel[4 + 3 * dot + 2] = wiimote->device->ir.dot[dot].size;
181  } else {
182  channel[4 + 3 * dot + 0] = -1;
183  channel[4 + 3 * dot + 1] = -1;
184  channel[4 + 3 * dot + 2] = -1;
185  }
186  }
187  }
188 
189  // See which secondary controller is installed and report
190  switch (wiimote->device->exp.type) {
191  case EXP_NONE:
192  // No expansion analogs to grab
193  break;
194 
195  case EXP_NUNCHUK:
196  channel[16 + 0] = wiimote->device->exp.nunchuk.gforce.x;
197  channel[16 + 1] = wiimote->device->exp.nunchuk.gforce.y;
198  channel[16 + 2] = wiimote->device->exp.nunchuk.gforce.z;
199  channel[16 + 3] = wiimote->device->exp.nunchuk.js.ang;
200  channel[16 + 4] = wiimote->device->exp.nunchuk.js.mag;
201 #if WIIUSE_HAS_VERSION(0,14,2)
202  channel[16 + 5] = wiimote->device->exp.nunchuk.js.x;
203  channel[16 + 6] = wiimote->device->exp.nunchuk.js.y;
204 #endif
205  break;
206 
207  case EXP_CLASSIC:
208  channel[32 + 0] = wiimote->device->exp.classic.l_shoulder;
209  channel[32 + 1] = wiimote->device->exp.classic.r_shoulder;
210  channel[32 + 2] = wiimote->device->exp.classic.ljs.ang;
211  channel[32 + 3] = wiimote->device->exp.classic.ljs.mag;
212  channel[32 + 4] = wiimote->device->exp.classic.rjs.ang;
213  channel[32 + 5] = wiimote->device->exp.classic.rjs.mag;
214 #if WIIUSE_HAS_VERSION(0,14,2)
215  channel[32 + 6] = wiimote->device->exp.classic.ljs.x;
216  channel[32 + 7] = wiimote->device->exp.classic.ljs.y;
217  channel[32 + 8] = wiimote->device->exp.classic.rjs.x;
218  channel[32 + 9] = wiimote->device->exp.classic.rjs.y;
219 #endif
220  break;
221 
222 
223  case EXP_GUITAR_HERO_3:
224  channel[48 + 0] = wiimote->device->exp.gh3.whammy_bar;
225  channel[48 + 1] = wiimote->device->exp.gh3.js.ang;
226  channel[48 + 2] = wiimote->device->exp.gh3.js.mag;
227 #if WIIUSE_HAS_VERSION(0,14,2)
228  channel[48 + 3] = wiimote->device->exp.gh3.js.x;
229  channel[48 + 4] = wiimote->device->exp.gh3.js.y;
230 #endif
231  break;
232 
233 #ifdef EXP_WII_BOARD
234  case EXP_WII_BOARD:
235  {
236  struct wii_board_t* wb = (wii_board_t*)&wiimote->device->exp.wb;
237  float total = wb->tl + wb->tr + wb->bl + wb->br;
238  float x = ((wb->tr + wb->br) / total) * 2 - 1;
239  float y = ((wb->tl + wb->tr) / total) * 2 - 1;
240  //printf("Got a wii board report: %f kg, @ (%f, %f)\n", total, x, y);
241  //printf("Got a wii board report: %f, %f, %f, %f\n", wb->tl, wb->tr, wb->bl, wb->br);
242  channel[64 + 0] = wb->tl;
243  channel[64 + 1] = wb->tr;
244  channel[64 + 2] = wb->bl;
245  channel[64 + 3] = wb->br;
246  channel[64 + 4] = total;
247  channel[64 + 5] = x;
248  channel[64 + 6] = y;
249  break;
250  }
251 #endif
252  default:
253  struct timeval now;
254  vrpn_gettimeofday(&now, NULL);
255  char msg[1024];
256  sprintf(msg, "Unknown Wii Remote expansion type: device->exp.type = %d", wiimote->device->exp.type);
258  }
259 
260  //-------------------------------------------------------------------------
261  // Read the state of the Infrared sensors.
262 }
263 
264 void vrpn_WiiMote::connect_wiimote(int timeout) {
265  struct timeval now;
266  char msg[1024];
267 
268  wiimote->device = NULL;
269  unsigned num_available;
270  num_available = wiiuse_find(available_wiimotes, VRPN_WIIUSE_MAX_WIIMOTES, timeout);
271 #ifdef __linux
272  if (!wiimote->bdaddr.empty()) {
273  for (int i = 0; i < VRPN_WIIUSE_MAX_WIIMOTES; ++i) {
274  std::string current(available_wiimotes[i]->bdaddr_str);
275  if (current == wiimote->bdaddr) {
276  wiimote->device = available_wiimotes[i];
277  break;
278  } else if (!current.empty()) {
279  acquireMessageLock();
280  vrpn_gettimeofday(&now, NULL);
281  sprintf(msg, "Wiimote found, but it's not the one we want: '%s' isn't '%s'\n", available_wiimotes[i]->bdaddr_str, wiimote->bdaddr.c_str());
282  send_text_message(msg, now);
283  releaseMessageLock();
284  }
285  }
286  }
287 #endif
288  if (wiimote->bdaddr.empty()) {
289  wiimote->device = wiiuse_get_by_id(available_wiimotes, VRPN_WIIUSE_MAX_WIIMOTES, wiimote->which);
290  }
291  if (! wiimote->device) {
292  acquireMessageLock();
293  vrpn_gettimeofday(&now, NULL);
294  sprintf(msg, "Could not open remote %d (%d found)", wiimote->which, num_available);
296  releaseMessageLock();
297  wiimote->found = false;
298  return;
299  } else {
300  wiimote->found = true;
301  }
302 
303  wiimote->connected = (wiiuse_connect(&(wiimote->device), 1) != 0);
304  if (wiimote->connected) {
305  acquireMessageLock();
306  vrpn_gettimeofday(&now, NULL);
307  sprintf(msg, "Connected to remote %d", wiimote->which);
308  send_text_message(msg, now);
309  releaseMessageLock();
310 
311  // rumble shortly to acknowledge connection:
312  wiiuse_rumble(wiimote->device, 1);
313  vrpn_SleepMsecs(200);
314  initialize_wiimote_state();
315  }
316 #ifdef DEBUG
317  else {
318  acquireMessageLock();
319  vrpn_gettimeofday(&now, NULL);
320  sprintf(msg, "No connection to remote %d", wiimote->which);
322  releaseMessageLock();
323  }
324 #endif
325 }
326 
327 void vrpn_WiiMote::initialize_wiimote_state(void) {
328  if (!wiimote->device || !wiimote->found || !wiimote->connected) {
329  return;
330  }
331 
332  // Turn on a light so we know which device we are.
333  switch (wiimote->which) {
334  case 1:
335  wiiuse_set_leds(wiimote->device, WIIMOTE_LED_1);
336  break;
337  case 2:
338  wiiuse_set_leds(wiimote->device, WIIMOTE_LED_2);
339  break;
340  case 3:
341  wiiuse_set_leds(wiimote->device, WIIMOTE_LED_3);
342  break;
343  case 4:
344  wiiuse_set_leds(wiimote->device, WIIMOTE_LED_4);
345  break;
346  default:
347  struct timeval now;
348  vrpn_gettimeofday(&now, NULL);
349  char msg[1024];
350  sprintf(msg, "Too-large remote %d (1-4 available)", wiimote->which);
352  break;
353  }
354 
355  // Set motion sensing on or off
356  wiiuse_motion_sensing(wiimote->device, wiimote->useMS);
357 
358  // Turn off rumbling
359  wiiuse_rumble(wiimote->device, 0);
360 
361  // Set IR sensing on or off
362  wiiuse_set_ir(wiimote->device, wiimote->useIR);
363 }
364 
365 // Device constructor.
366 // Parameters:
367 // - name: VRPN name to assign to this server
368 // - c: VRPN connection this device should be attached to
369 vrpn_WiiMote::vrpn_WiiMote(const char *name, vrpn_Connection *c, unsigned which, unsigned useMS, unsigned useIR, unsigned reorderButtons, const char *bdaddr):
370  vrpn_Analog(name, c),
371  vrpn_Button_Filter(name, c),
372  vrpn_Analog_Output(name, c),
373 #if defined (vrpn_THREADS_AVAILABLE)
374  waitingForConnection(true),
375  sharedData(0),
376  connectThread(0),
377 #endif
378  wiimote(new vrpn_Wiimote_Device)
379 {
380 #ifndef vrpn_THREADS_AVAILABLE
381  last_reconnect_attempt.tv_sec = 0;
382  last_reconnect_attempt.tv_usec = 0;
383 #endif
384 
385  int i;
386 
388  for (i = 0; i < vrpn_Analog::num_channel; i++) {
389  channel[i] = 0;
390  }
391 
392  // There are bits for up to 16 buttons on the main remote, and for
393  // up to 16 more on an expansion pack.
395  for (i = 0; i < vrpn_Button::num_buttons; i++) {
396  buttons[i] = 0;
397  }
398 
399  // Two channels: channel 0 is rumble, channel 1 is IR sensitivity.
401 
402  // Register a handler for the request channel change message
405  FAIL("vrpn_WiiMote: can't register change channel request handler");
406  return;
407  }
408 
409  // Register a handler for the request channels change message
412  FAIL("vrpn_WiiMote: can't register change channels request handler");
413  return;
414  }
415 
416  // Register a handler for the no-one's-connected-now message
420  FAIL("Can't register self-destruct handler");
421  return;
422  }
423 
424  // Get a list of available devices and select the one we want.
425  // Look for up to VRPN_WIIUSE_MAX_WIIMOTES motes. Timeout in 5 seconds if one not found.
426  wiimote->which = which > 0 ? which : 1;
427  wiimote->useMS = useMS;
428  wiimote->useIR = useIR;
429  wiimote->reorderButtons = (reorderButtons != 0);
430  if (bdaddr) {
431  wiimote->bdaddr = std::string(bdaddr);
432  }
433 #ifndef __linux
434  if (!wiimote->bdaddr.empty()) {
435  fprintf(stderr, "vrpn_WiiMote: Specifying the bluetooth address of the desired wiimote is only supported on Linux right now\n");
436  wiimote->bdaddr.clear();
437  }
438 #endif
439 
440  available_wiimotes = wiiuse_init(VRPN_WIIUSE_MAX_WIIMOTES);
441 #if !defined(DEBUG) && defined(WIIUSE_HAS_OUTPUT_REDIRECTION)
442  /* disable debug and info messages from wiiuse itself */
443  wiiuse_set_output(LOGLEVEL_DEBUG, 0);
444  wiiuse_set_output(LOGLEVEL_INFO, 0);
445 #endif
446 #if defined (vrpn_THREADS_AVAILABLE)
447  // Pack the sharedData into another ThreadData
448  // (this is an API flaw in vrpn_Thread)
449  vrpn_ThreadData connectThreadData;
450  sharedData = new vrpn_WiiMote_SharedData(this);
451  connectThreadData.pvUD = sharedData;
452  // take ownership of msgLock:
453  acquireMessageLock();
454  // initialize connectThread:
455  connectThread = new vrpn_Thread(&vrpn_WiiMote::connectThreadFunc, connectThreadData);
456  connectThread->go();
457 #else
458  connect_wiimote(3);
459 #endif
460 }
461 
462 // Device destructor
464 #if defined (vrpn_THREADS_AVAILABLE)
465  // stop connectThread
466  sharedData->stopFlag = true;
467  // Release the lock blocking the connection thread.
468  if (!waitingForConnection) {
469  sharedData->connectLock.v();
470  }
471  while (connectThread->running()) {
472  // Let the connect thread send messages
473 
474  releaseMessageLock();
475  vrpn_SleepMsecs(10);
476  acquireMessageLock();
477  }
478 
479  delete connectThread;
480  delete sharedData;
481 #endif
482  // Close the device and delete
483 
484  if (wiimote->connected) {
485  wiiuse_disconnect(wiimote->device);
486  }
487  delete wiimote;
488 }
489 
490 // VRPN main loop
491 // Poll the device and let the VRPN change notifications fire
493 
494  vrpn_gettimeofday(&_timestamp, NULL);
495 
496 #if defined (vrpn_THREADS_AVAILABLE)
497  if (waitingForConnection) {
498  // did connectThread establish a connection?
499  if (sharedData->connectLock.condP()) {
500  // yay, we can use wiimote again!
501  waitingForConnection = false;
502  } else {
503  // allow connectThread to send its messages:
504  releaseMessageLock();
505  vrpn_SleepMsecs(10);
506  acquireMessageLock();
507  // still waiting
508  // do housekeeping and return:
509  server_mainloop();
510  // no need to update timestamp?
511  // no need to call report_changes?
512  return;
513  }
514  }
515 #endif
516  if (! isValid()) {
517 #if defined (vrpn_THREADS_AVAILABLE)
518  waitingForConnection = true;
519  // release semaphore, so connectThread gets active again:
520  sharedData->connectLock.v();
521 #else // no thread support: we have to block the server:
522  // try reconnect every second:
523  timeval diff = vrpn_TimevalDiff(_timestamp, last_reconnect_attempt);
524  if (diff.tv_sec >= 1) {
525  last_reconnect_attempt = _timestamp;
526  //reconnect
527  // timeout=1 means that we block the vrpn server for a whole second!
528  connect_wiimote(1);
529  }
530 #endif
531  }
532 
533  server_mainloop();
534 
535  // Poll to get the status of the device. When an event happens, call
536  // the appropriate handler to fill in our data structures.
537  if (wiimote->connected && wiiuse_poll(&(wiimote->device), 1)) {
538  switch (wiimote->device->event) {
539  case WIIUSE_EVENT: // A generic event
540  handle_event();
541  break;
542 
543  case WIIUSE_STATUS: // A status event
544  // Nothing to do here, we're polling what we need to know in mainloop.
545  break;
546 
547  case WIIUSE_DISCONNECT:
548  case WIIUSE_UNEXPECTED_DISCONNECT:
549  wiimote->connected = false;
550  wiiuse_disconnect(wiimote->device);
551  send_text_message("Disconnected", _timestamp, vrpn_TEXT_ERROR);
552 #ifndef vrpn_THREADS_AVAILABLE
553  last_reconnect_attempt = _timestamp;
554 #endif
555  break;
556 
557  case WIIUSE_READ_DATA:
558  // Data we requested was returned. Take a look at wiimote->device->read_req
559  // for the info.
560  break;
561 
562  case WIIUSE_NUNCHUK_INSERTED:
563  send_text_message("Nunchuck inserted", _timestamp);
564  break;
565 
566  case WIIUSE_CLASSIC_CTRL_INSERTED:
567  send_text_message("Classic controller inserted", _timestamp);
568  break;
569 
570  case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
571  send_text_message("Guitar Hero 3 controller inserted", _timestamp);
572  break;
573 
574 #ifdef EXP_WII_BOARD
575  case WIIUSE_WII_BOARD_CTRL_INSERTED:
576  send_text_message("Wii Balance Board controller inserted/detected", _timestamp);
577  break;
578 #endif
579 
580  case WIIUSE_NUNCHUK_REMOVED:
581  case WIIUSE_CLASSIC_CTRL_REMOVED:
582  case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
583  send_text_message("An expansion controller was removed", _timestamp,
585  break;
586 #ifdef EXP_WII_BOARD
587  case WIIUSE_WII_BOARD_CTRL_REMOVED:
588  send_text_message("Wii Balance Board controller removed/disconnected", _timestamp,
590  break;
591 #endif
592 
593  default:
594  send_text_message("unknown event", _timestamp);
595  break;
596  }
597  }
598 
599  // Send any changes out over the connection.
600  vrpn_gettimeofday(&_timestamp, NULL);
601  report_changes();
602 }
603 
604 bool vrpn_WiiMote::isValid() const {
605  return (wiimote->found) && (wiimote->connected);
606 }
607 
608 void vrpn_WiiMote::report(vrpn_uint32 class_of_service) {
609  vrpn_Analog::timestamp = _timestamp;
610  vrpn_Button::timestamp = _timestamp;
611 
612  vrpn_Analog::report(class_of_service);
614 }
615 
616 void vrpn_WiiMote::report_changes(vrpn_uint32 class_of_service) {
617  vrpn_Analog::timestamp = _timestamp;
618  vrpn_Button::timestamp = _timestamp;
619 
620  vrpn_Analog::report_changes(class_of_service);
622 }
623 
624 /* static */
626  vrpn_HANDLERPARAM p) {
627  const char* bufptr = p.buffer;
628  vrpn_int32 chan_num;
629  vrpn_int32 pad;
630  vrpn_float64 value;
632 
633  // Read the parameters from the buffer
634  vrpn_unbuffer(&bufptr, &chan_num);
635  vrpn_unbuffer(&bufptr, &pad);
636  vrpn_unbuffer(&bufptr, &value);
637 
638  // Set the appropriate value, if the channel number is in the
639  // range of the ones we have.
640  if ((chan_num < 0) || (chan_num >= me->o_num_channel)) {
641  fprintf(stderr, "vrpn_WiiMote::handle_request_message(): Index out of bounds\n");
642  char msg[1024];
643  sprintf(msg, "Error: (handle_request_message): channel %d is not active. Squelching.", chan_num);
645  return 0;
646  }
647  me->o_channel[chan_num] = value;
648  switch (chan_num) {
649  case 0:
650  {
651  if (value >= 0.5) {
652  wiiuse_rumble(me->wiimote->device, 1);
653  } else {
654  wiiuse_rumble(me->wiimote->device, 0);
655  }
656  break;
657  }
658  case 1:
659  {
660  int level = static_cast<int>(value);
661  wiiuse_set_ir_sensitivity(me->wiimote->device, level);
662  break;
663  }
664  }
665  return 0;
666 }
667 
668 /* static */
670  vrpn_HANDLERPARAM p) {
671  const char* bufptr = p.buffer;
672  vrpn_int32 num;
673  vrpn_int32 pad;
675 
676  // Read the values from the buffer
677  vrpn_unbuffer(&bufptr, &num);
678  vrpn_unbuffer(&bufptr, &pad);
679  if (num > me->o_num_channel) {
680  char msg[1024];
681  sprintf(msg, "Error: (handle_request_channels_message): channels above %d not active; "
682  "bad request up to channel %d. Squelching.", me->o_num_channel, num);
684  num = me->o_num_channel;
685  }
686  if (num < 0) {
687  char msg[1024];
688  sprintf(msg, "Error: (handle_request_channels_message): invalid channel %d. Squelching.", num);
690  return 0;
691  }
692 
693  // Pull only channel 0 from the buffer, no matter how many values we received.
694  vrpn_float64 value;
695  vrpn_unbuffer(&bufptr, &value);
696  if (value >= 0.5) {
697  wiiuse_rumble(me->wiimote->device, 1);
698  } else {
699  wiiuse_rumble(me->wiimote->device, 0);
700  }
701 
702  return 0;
703 }
704 
706  //XXX Turn off any rumble.
707  return 0;
708 }
709 
710 #if defined (vrpn_THREADS_AVAILABLE)
711 /* static */
712 void vrpn_WiiMote::connectThreadFunc(vrpn_ThreadData &threadData) {
713  vrpn_WiiMote_SharedData *sharedData = static_cast<vrpn_WiiMote_SharedData *>(threadData.pvUD);
714  if (! sharedData || ! sharedData->wmHandle) {
715  return;
716  }
717  while (true) {
718  // wait for semaphore
719  sharedData->connectLock.p();
720  if (sharedData->stopFlag) {
721  break;
722  }
723  sharedData->wmHandle->connect_wiimote(3);
724  // release semaphore
725  sharedData->connectLock.v();
726  // make sure that main thread gets semaphore:
727  vrpn_SleepMsecs(100);
728  }
729 }
730 #endif
731 
732 #endif // VRPN_USE_WIIUSE
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_Button::report_changes
virtual void report_changes(void)
Definition: vrpn_Button.C:422
min
#define min(x, y)
Definition: vrpn_WiiMote.C:47
vrpn_Button_Filter::report_changes
virtual void report_changes(void)
Definition: vrpn_Button.C:382
vrpn_BUTTON_MAX_BUTTONS
const int vrpn_BUTTON_MAX_BUTTONS
Definition: vrpn_Button.h:12
vrpn_WiiMote::~vrpn_WiiMote
~vrpn_WiiMote()
Definition: vrpn_WiiMote.C:463
vrpn_Analog::channel
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:38
vrpn_Semaphore
Definition: vrpn_Shared.h:487
vrpn_Thread
Definition: vrpn_Shared.h:558
vrpn_dropped_last_connection
const char * vrpn_dropped_last_connection
Definition: vrpn_Connection.C:187
vrpn_WiiMote::isValid
bool isValid() const
Definition: vrpn_WiiMote.C:604
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_WiiMote.h
vrpn_BaseClassUnique::userdata
void * userdata
Definition: vrpn_BaseClass.h:287
vrpn_Analog
Definition: vrpn_Analog.h:28
vrpn_Analog_Output::o_num_channel
vrpn_int32 o_num_channel
Definition: vrpn_Analog_Output.h:37
vrpn_Analog::timestamp
struct timeval timestamp
Definition: vrpn_Analog.h:41
vrpn_Analog_Output
Definition: vrpn_Analog_Output.h:26
vrpn_CHANNEL_MAX
#define vrpn_CHANNEL_MAX
Definition: vrpn_Analog.h:16
vrpn_Button::num_buttons
vrpn_int32 num_buttons
Definition: vrpn_Button.h:47
vrpn_Button::buttons
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:44
vrpn_unbuffer
VRPN_API int vrpn_unbuffer(const char **buffer, timeval *t)
Utility routine for taking a struct timeval from a buffer that was sent as a message.
Definition: vrpn_Shared.C:312
vrpn_WiiMote
Definition: vrpn_WiiMote.h:127
vrpn_BaseClassUnique::d_connection
vrpn_Connection * d_connection
Connection that this object talks to.
Definition: vrpn_BaseClass.h:224
vrpn_HANDLERPARAM::buffer
const char * buffer
Definition: vrpn_Connection.h:49
vrpn_Connection::register_message_type
virtual vrpn_int32 register_message_type(const char *name)
Definition: vrpn_Connection.C:5074
vrpn_TEXT_ERROR
Definition: vrpn_BaseClass.h:103
vrpn_TimevalDiff
timeval vrpn_TimevalDiff(const timeval &tv1, const timeval &tv2)
Definition: vrpn_Shared.C:92
vrpn_SleepMsecs
void vrpn_SleepMsecs(double dMsecs)
Definition: vrpn_Shared.C:157
vrpn_ThreadData
Definition: vrpn_Shared.h:548
vrpn_HANDLERPARAM
This structure is what is passed to a vrpn_Connection message callback.
Definition: vrpn_Connection.h:44
vrpn_TEXT_WARNING
Definition: vrpn_BaseClass.h:102
vrpn_BaseClassUnique::d_sender_id
vrpn_int32 d_sender_id
Sender ID registered with the connection.
Definition: vrpn_BaseClass.h:228
vrpn_Button::timestamp
struct timeval timestamp
Definition: vrpn_Button.h:48
vrpn_WiiMote::handle_request_channels_message
static int VRPN_CALLBACK handle_request_channels_message(void *userdata, vrpn_HANDLERPARAM p)
Definition: vrpn_WiiMote.C:669
vrpn_ThreadData::pvUD
void * pvUD
Definition: vrpn_Shared.h:549
VRPN_WIIUSE_MAX_WIIMOTES
#define VRPN_WIIUSE_MAX_WIIMOTES
Definition: vrpn_WiiMote.h:20
vrpn_HANDLERPARAM::msg_time
struct timeval msg_time
Definition: vrpn_Connection.h:47
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_WiiMote::mainloop
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_WiiMote.C:492
vrpn_gettimeofday
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
vrpn_WiiMote::vrpn_WiiMote
vrpn_WiiMote(const char *name, vrpn_Connection *c=NULL, unsigned which=0, unsigned useMS=1, unsigned useIR=1, unsigned reorderButtons=0, const char *bdaddr=NULL)
Definition: vrpn_WiiMote.C:369
vrpn_WiiMote::handle_last_connection_dropped
static int VRPN_CALLBACK handle_last_connection_dropped(void *selfPtr, vrpn_HANDLERPARAM data)
Definition: vrpn_WiiMote.C:705
VRPN_CALLBACK
#define VRPN_CALLBACK
Definition: vrpn_Configure.h:647
vrpn_Analog_Output::o_channel
vrpn_float64 o_channel[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog_Output.h:36
vrpn_BaseClassUnique::send_text_message
int send_text_message(const char *msg, struct timeval timestamp, vrpn_TEXT_SEVERITY type=vrpn_TEXT_NORMAL, vrpn_uint32 level=0)
Sends a NULL-terminated text message from the device d_sender_id.
Definition: vrpn_BaseClass.C:568
vrpn_WiiMote::handle_request_message
static int VRPN_CALLBACK handle_request_message(void *userdata, vrpn_HANDLERPARAM p)
Definition: vrpn_WiiMote.C:625
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_Analog_Output::request_channels_m_id
vrpn_int32 request_channels_m_id
Definition: vrpn_Analog_Output.h:40
vrpn_Analog_Output::request_m_id
vrpn_int32 request_m_id
Definition: vrpn_Analog_Output.h:39
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_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