vrpn 07.35
Virtual Reality Peripheral Network
Loading...
Searching...
No Matches
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.
25class 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)
51struct 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
64inline 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
71inline void vrpn_WiiMote::releaseMessageLock() {
72#if defined (vrpn_THREADS_AVAILABLE)
73 sharedData->msgLock.v();
74#endif
75}
76
77unsigned 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
119void 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
264void 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 else {
317 acquireMessageLock();
318 vrpn_gettimeofday(&now, NULL);
319 sprintf(msg, "No connection to remote %d", wiimote->which);
321 releaseMessageLock();
322 }
323}
324
325void vrpn_WiiMote::initialize_wiimote_state(void) {
326 if (!wiimote->device || !wiimote->found || !wiimote->connected) {
327 return;
328 }
329
330 // Turn on a light so we know which device we are.
331 switch (wiimote->which) {
332 case 1:
333 wiiuse_set_leds(wiimote->device, WIIMOTE_LED_1);
334 break;
335 case 2:
336 wiiuse_set_leds(wiimote->device, WIIMOTE_LED_2);
337 break;
338 case 3:
339 wiiuse_set_leds(wiimote->device, WIIMOTE_LED_3);
340 break;
341 case 4:
342 wiiuse_set_leds(wiimote->device, WIIMOTE_LED_4);
343 break;
344 default:
345 struct timeval now;
346 vrpn_gettimeofday(&now, NULL);
347 char msg[1024];
348 sprintf(msg, "Too-large remote %d (1-4 available)", wiimote->which);
350 break;
351 }
352
353 // Set motion sensing on or off
354 wiiuse_motion_sensing(wiimote->device, wiimote->useMS);
355
356 // Turn off rumbling
357 wiiuse_rumble(wiimote->device, 0);
358
359 // Set IR sensing on or off
360 wiiuse_set_ir(wiimote->device, wiimote->useIR);
361}
362
363// Device constructor.
364// Parameters:
365// - name: VRPN name to assign to this server
366// - c: VRPN connection this device should be attached to
367vrpn_WiiMote::vrpn_WiiMote(const char *name, vrpn_Connection *c, unsigned which, unsigned useMS, unsigned useIR, unsigned reorderButtons, const char *bdaddr):
368 vrpn_Analog(name, c),
369 vrpn_Button_Filter(name, c),
370 vrpn_Analog_Output(name, c),
371#if defined (vrpn_THREADS_AVAILABLE)
372 waitingForConnection(true),
373 sharedData(0),
374 connectThread(0),
375#endif
376 wiimote(NULL)
377{
378#ifndef vrpn_THREADS_AVAILABLE
379 last_reconnect_attempt.tv_sec = 0;
380 last_reconnect_attempt.tv_usec = 0;
381#endif
382
383 try { wiimote = new vrpn_Wiimote_Device; }
384 catch (...) {
385 FAIL("vrpn_WiiMote: out of memory");
386 return;
387 }
388
389 int i;
390
392 for (i = 0; i < vrpn_Analog::num_channel; i++) {
393 channel[i] = 0;
394 }
395
396 // There are bits for up to 16 buttons on the main remote, and for
397 // up to 16 more on an expansion pack.
399 for (i = 0; i < vrpn_Button::num_buttons; i++) {
400 buttons[i] = 0;
401 }
402
403 // Two channels: channel 0 is rumble, channel 1 is IR sensitivity.
405
406 // Register a handler for the request channel change message
409 FAIL("vrpn_WiiMote: can't register change channel request handler");
410 return;
411 }
412
413 // Register a handler for the request channels change message
416 FAIL("vrpn_WiiMote: can't register change channels request handler");
417 return;
418 }
419
420 // Register a handler for the no-one's-connected-now message
424 FAIL("Can't register self-destruct handler");
425 return;
426 }
427
428 // Get a list of available devices and select the one we want.
429 // Look for up to VRPN_WIIUSE_MAX_WIIMOTES motes. Timeout in 5 seconds if one not found.
430 wiimote->which = which > 0 ? which : 1;
431 wiimote->useMS = useMS;
432 wiimote->useIR = useIR;
433 wiimote->reorderButtons = (reorderButtons != 0);
434 if (bdaddr) {
435 wiimote->bdaddr = std::string(bdaddr);
436 }
437#ifndef __linux
438 if (!wiimote->bdaddr.empty()) {
439 fprintf(stderr, "vrpn_WiiMote: Specifying the bluetooth address of the desired wiimote is only supported on Linux right now\n");
440 wiimote->bdaddr.clear();
441 }
442#endif
443
444 available_wiimotes = wiiuse_init(VRPN_WIIUSE_MAX_WIIMOTES);
445#if !defined(DEBUG) && defined(WIIUSE_HAS_OUTPUT_REDIRECTION)
446 /* disable debug and info messages from wiiuse itself */
447 wiiuse_set_output(LOGLEVEL_DEBUG, 0);
448 wiiuse_set_output(LOGLEVEL_INFO, 0);
449#endif
450#if defined (vrpn_THREADS_AVAILABLE)
451 // Pack the sharedData into another ThreadData
452 // (this is an API flaw in vrpn_Thread)
453 vrpn_ThreadData connectThreadData;
454 try { sharedData = new vrpn_WiiMote_SharedData(this); }
455 catch (...) {
456 FAIL("vrpn_WiiMote: out of memory");
457 return;
458 }
459 connectThreadData.pvUD = sharedData;
460 // take ownership of msgLock:
461 acquireMessageLock();
462 // initialize connectThread:
463 try { connectThread = new vrpn_Thread(&vrpn_WiiMote::connectThreadFunc, connectThreadData); }
464 catch (...) {
465 FAIL("vrpn_WiiMote: out of memory");
466 return;
467 }
468 connectThread->go();
469#else
470 connect_wiimote(3);
471#endif
472}
473
474// Device destructor
476#if defined (vrpn_THREADS_AVAILABLE)
477 // stop connectThread
478 sharedData->stopFlag = true;
479 // Release the lock blocking the connection thread.
480 if (!waitingForConnection) {
481 sharedData->connectLock.v();
482 }
483 while (connectThread->running()) {
484 // Let the connect thread send messages
485
486 releaseMessageLock();
487 vrpn_SleepMsecs(10);
488 acquireMessageLock();
489 }
490
491 try {
492 delete connectThread;
493 delete sharedData;
494 } catch (...) {
495 fprintf(stderr, "vrpn_WiiMote::~vrpn_WiiMote(): delete failed\n");
496 return;
497 }
498#endif
499 // Close the device and delete
500
501 if (wiimote->connected) {
502 wiiuse_disconnect(wiimote->device);
503 }
504 try {
505 delete wiimote;
506 } catch (...) {
507 fprintf(stderr, "vrpn_WiiMote::~vrpn_WiiMote(): delete failed\n");
508 return;
509 }
510}
511
512// VRPN main loop
513// Poll the device and let the VRPN change notifications fire
515
516 vrpn_gettimeofday(&_timestamp, NULL);
517
518#if defined (vrpn_THREADS_AVAILABLE)
519 if (waitingForConnection) {
520 // did connectThread establish a connection?
521 if (sharedData->connectLock.condP()) {
522 // yay, we can use wiimote again!
523 waitingForConnection = false;
524 } else {
525 // allow connectThread to send its messages:
526 releaseMessageLock();
527 vrpn_SleepMsecs(10);
528 acquireMessageLock();
529 // still waiting
530 // do housekeeping and return:
532 // no need to update timestamp?
533 // no need to call report_changes?
534 return;
535 }
536 }
537#endif
538 if (! isValid()) {
539#if defined (vrpn_THREADS_AVAILABLE)
540 waitingForConnection = true;
541 // release semaphore, so connectThread gets active again:
542 sharedData->connectLock.v();
543#else // no thread support: we have to block the server:
544 // try reconnect every second:
545 timeval diff = vrpn_TimevalDiff(_timestamp, last_reconnect_attempt);
546 if (diff.tv_sec >= 1) {
547 last_reconnect_attempt = _timestamp;
548 //reconnect
549 // timeout=1 means that we block the vrpn server for a whole second!
550 connect_wiimote(1);
551 }
552#endif
553 }
554
556
557 // Poll to get the status of the device. When an event happens, call
558 // the appropriate handler to fill in our data structures.
559 if (wiimote->connected && wiiuse_poll(&(wiimote->device), 1)) {
560 switch (wiimote->device->event) {
561 case WIIUSE_EVENT: // A generic event
562 handle_event();
563 break;
564
565 case WIIUSE_STATUS: // A status event
566 // Nothing to do here, we're polling what we need to know in mainloop.
567 break;
568
569 case WIIUSE_DISCONNECT:
570 case WIIUSE_UNEXPECTED_DISCONNECT:
571 wiimote->connected = false;
572 wiiuse_disconnect(wiimote->device);
573 send_text_message("Disconnected", _timestamp, vrpn_TEXT_ERROR);
574#ifndef vrpn_THREADS_AVAILABLE
575 last_reconnect_attempt = _timestamp;
576#endif
577 break;
578
579 case WIIUSE_READ_DATA:
580 // Data we requested was returned. Take a look at wiimote->device->read_req
581 // for the info.
582 break;
583
584 case WIIUSE_NUNCHUK_INSERTED:
585 send_text_message("Nunchuck inserted", _timestamp);
586 break;
587
588 case WIIUSE_CLASSIC_CTRL_INSERTED:
589 send_text_message("Classic controller inserted", _timestamp);
590 break;
591
592 case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
593 send_text_message("Guitar Hero 3 controller inserted", _timestamp);
594 break;
595
596#ifdef EXP_WII_BOARD
597 case WIIUSE_WII_BOARD_CTRL_INSERTED:
598 send_text_message("Wii Balance Board controller inserted/detected", _timestamp);
599 break;
600#endif
601
602 case WIIUSE_NUNCHUK_REMOVED:
603 case WIIUSE_CLASSIC_CTRL_REMOVED:
604 case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
605 send_text_message("An expansion controller was removed", _timestamp,
607 break;
608#ifdef EXP_WII_BOARD
609 case WIIUSE_WII_BOARD_CTRL_REMOVED:
610 send_text_message("Wii Balance Board controller removed/disconnected", _timestamp,
612 break;
613#endif
614
615 default:
616 send_text_message("unknown event", _timestamp);
617 break;
618 }
619 }
620
621 // Send any changes out over the connection.
622 vrpn_gettimeofday(&_timestamp, NULL);
624}
625
627 return (wiimote->found) && (wiimote->connected);
628}
629
630void vrpn_WiiMote::report(vrpn_uint32 class_of_service) {
631 vrpn_Analog::timestamp = _timestamp;
632 vrpn_Button::timestamp = _timestamp;
633
634 vrpn_Analog::report(class_of_service);
636}
637
638void vrpn_WiiMote::report_changes(vrpn_uint32 class_of_service) {
639 vrpn_Analog::timestamp = _timestamp;
640 vrpn_Button::timestamp = _timestamp;
641
642 vrpn_Analog::report_changes(class_of_service);
644}
645
646/* static */
649 const char* bufptr = p.buffer;
650 vrpn_int32 chan_num;
651 vrpn_int32 pad;
652 vrpn_float64 value;
654
655 // Read the parameters from the buffer
656 vrpn_unbuffer(&bufptr, &chan_num);
657 vrpn_unbuffer(&bufptr, &pad);
658 vrpn_unbuffer(&bufptr, &value);
659
660 // Set the appropriate value, if the channel number is in the
661 // range of the ones we have.
662 if ((chan_num < 0) || (chan_num >= me->o_num_channel)) {
663 fprintf(stderr, "vrpn_WiiMote::handle_request_message(): Index out of bounds\n");
664 char msg[1024];
665 sprintf(msg, "Error: (handle_request_message): channel %d is not active. Squelching.", chan_num);
667 return 0;
668 }
669 me->o_channel[chan_num] = value;
670 switch (chan_num) {
671 case 0:
672 {
673 if (value >= 0.5) {
674 wiiuse_rumble(me->wiimote->device, 1);
675 } else {
676 wiiuse_rumble(me->wiimote->device, 0);
677 }
678 break;
679 }
680 case 1:
681 {
682 int level = static_cast<int>(value);
683 wiiuse_set_ir_sensitivity(me->wiimote->device, level);
684 break;
685 }
686 }
687 return 0;
688}
689
690/* static */
693 const char* bufptr = p.buffer;
694 vrpn_int32 num;
695 vrpn_int32 pad;
697
698 // Read the values from the buffer
699 vrpn_unbuffer(&bufptr, &num);
700 vrpn_unbuffer(&bufptr, &pad);
701 if (num > me->o_num_channel) {
702 char msg[1024];
703 sprintf(msg, "Error: (handle_request_channels_message): channels above %d not active; "
704 "bad request up to channel %d. Squelching.", me->o_num_channel, num);
706 num = me->o_num_channel;
707 }
708 if (num < 0) {
709 char msg[1024];
710 sprintf(msg, "Error: (handle_request_channels_message): invalid channel %d. Squelching.", num);
712 return 0;
713 }
714
715 // Pull only channel 0 from the buffer, no matter how many values we received.
716 vrpn_float64 value;
717 vrpn_unbuffer(&bufptr, &value);
718 if (value >= 0.5) {
719 wiiuse_rumble(me->wiimote->device, 1);
720 } else {
721 wiiuse_rumble(me->wiimote->device, 0);
722 }
723
724 return 0;
725}
726
728 //XXX Turn off any rumble.
729 return 0;
730}
731
732#if defined (vrpn_THREADS_AVAILABLE)
733/* static */
734void vrpn_WiiMote::connectThreadFunc(vrpn_ThreadData &threadData) {
735 vrpn_WiiMote_SharedData *sharedData = static_cast<vrpn_WiiMote_SharedData *>(threadData.pvUD);
736 if (! sharedData || ! sharedData->wmHandle) {
737 return;
738 }
739 while (true) {
740 // wait for semaphore
741 sharedData->connectLock.p();
742 if (sharedData->stopFlag) {
743 break;
744 }
745 sharedData->wmHandle->connect_wiimote(3);
746 // release semaphore
747 sharedData->connectLock.v();
748 // make sure that main thread gets semaphore:
749 vrpn_SleepMsecs(100);
750 }
751}
752#endif
753
754#endif // VRPN_USE_WIIUSE
vrpn_float64 o_channel[vrpn_CHANNEL_MAX]
vrpn_int32 request_channels_m_id
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.
vrpn_int32 d_sender_id
Sender ID registered with the connection.
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
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.
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)
Definition: vrpn_Button.C:383
vrpn_int32 num_buttons
Definition: vrpn_Button.h:48
struct timeval timestamp
Definition: vrpn_Button.h:49
virtual void report_changes(void)
Definition: vrpn_Button.C:423
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)
static int VRPN_CALLBACK handle_request_message(void *userdata, vrpn_HANDLERPARAM p)
Definition: vrpn_WiiMote.C:647
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:367
bool isValid() const
Definition: vrpn_WiiMote.C:626
static int VRPN_CALLBACK handle_request_channels_message(void *userdata, vrpn_HANDLERPARAM p)
Definition: vrpn_WiiMote.C:691
static int VRPN_CALLBACK handle_last_connection_dropped(void *selfPtr, vrpn_HANDLERPARAM data)
Definition: vrpn_WiiMote.C:727
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_WiiMote.C:514
This structure is what is passed to a vrpn_Connection message callback.
const char * buffer
struct timeval msg_time
#define vrpn_CHANNEL_MAX
Definition: vrpn_Analog.h:16
@ vrpn_TEXT_WARNING
@ vrpn_TEXT_ERROR
const int vrpn_BUTTON_MAX_BUTTONS
Definition: vrpn_Button.h:13
#define VRPN_CALLBACK
const char * vrpn_dropped_last_connection
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:321
timeval vrpn_TimevalDiff(const timeval &tv1, const timeval &tv2)
Definition: vrpn_Shared.C:101
void vrpn_SleepMsecs(double dMilliSecs)
Definition: vrpn_Shared.C:166
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:99
#define min(x, y)
Definition: vrpn_WiiMote.C:47
#define VRPN_WIIUSE_MAX_WIIMOTES
Definition: vrpn_WiiMote.h:20