7 #if defined(VRPN_USE_WIIUSE)
14 #include VRPN_WIIUSE_H
19 #ifndef WIIUSE_HAS_VERSION
20 #define WIIUSE_HAS_VERSION(major, minor, patch) false
25 class vrpn_Wiimote_Device {
27 vrpn_Wiimote_Device() :
32 reorderButtons(
false),
35 struct wiimote_t *device;
47 #define min(x,y) ((x)<(y)?(x):(y))
50 #if defined (vrpn_THREADS_AVAILABLE)
51 struct vrpn_WiiMote_SharedData {
53 : connectLock(), wmHandle(wm), msgLock(), stopFlag(
false), running(
false)
64 inline void vrpn_WiiMote::acquireMessageLock() {
65 #if defined (vrpn_THREADS_AVAILABLE)
67 sharedData->msgLock.p();
71 inline void vrpn_WiiMote::releaseMessageLock() {
72 #if defined (vrpn_THREADS_AVAILABLE)
73 sharedData->msgLock.v();
77 unsigned vrpn_WiiMote::map_button(
unsigned btn) {
113 fprintf(stderr,
"WiiMote: unhandled button %d\n", btn);
119 void vrpn_WiiMote::handle_event() {
125 for (i = 0; i < 16; i++) {
126 if (wiimote->reorderButtons) {
127 buttons[map_button(i)] = (wiimote->device->btns & (1 << i)) != 0;
129 buttons[i] = (wiimote->device->btns & (1 << i)) != 0;
133 switch (wiimote->device->exp.type) {
138 for (i = 0; i < 16; i++) {
139 buttons[16 + i] = (wiimote->device->exp.nunchuk.btns & (1 << i)) != 0;
144 for (i = 0; i < 16; i++) {
145 buttons[32 + i] = (wiimote->device->exp.classic.btns & (1 << i)) != 0;
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;
158 if (IS_PRESSED(wiimote->device, WIIMOTE_BUTTON_A)) {
159 wiiuse_set_wii_board_calib(wiimote->device);
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;
174 if (WIIUSE_USING_IR(wiimote->device)) {
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;
190 switch (wiimote->device->exp.type) {
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;
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;
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;
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;
256 sprintf(msg,
"Unknown Wii Remote expansion type: device->exp.type = %d", wiimote->device->exp.type);
264 void vrpn_WiiMote::connect_wiimote(
int timeout) {
268 wiimote->device = NULL;
269 unsigned num_available;
272 if (!wiimote->bdaddr.empty()) {
274 std::string current(available_wiimotes[i]->bdaddr_str);
275 if (current == wiimote->bdaddr) {
276 wiimote->device = available_wiimotes[i];
278 }
else if (!current.empty()) {
279 acquireMessageLock();
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());
283 releaseMessageLock();
288 if (wiimote->bdaddr.empty()) {
291 if (! wiimote->device) {
292 acquireMessageLock();
294 sprintf(msg,
"Could not open remote %d (%d found)", wiimote->which, num_available);
296 releaseMessageLock();
297 wiimote->found =
false;
300 wiimote->found =
true;
303 wiimote->connected = (wiiuse_connect(&(wiimote->device), 1) != 0);
304 if (wiimote->connected) {
305 acquireMessageLock();
307 sprintf(msg,
"Connected to remote %d", wiimote->which);
309 releaseMessageLock();
312 wiiuse_rumble(wiimote->device, 1);
314 initialize_wiimote_state();
318 acquireMessageLock();
320 sprintf(msg,
"No connection to remote %d", wiimote->which);
322 releaseMessageLock();
327 void vrpn_WiiMote::initialize_wiimote_state(
void) {
328 if (!wiimote->device || !wiimote->found || !wiimote->connected) {
333 switch (wiimote->which) {
335 wiiuse_set_leds(wiimote->device, WIIMOTE_LED_1);
338 wiiuse_set_leds(wiimote->device, WIIMOTE_LED_2);
341 wiiuse_set_leds(wiimote->device, WIIMOTE_LED_3);
344 wiiuse_set_leds(wiimote->device, WIIMOTE_LED_4);
350 sprintf(msg,
"Too-large remote %d (1-4 available)", wiimote->which);
356 wiiuse_motion_sensing(wiimote->device, wiimote->useMS);
359 wiiuse_rumble(wiimote->device, 0);
362 wiiuse_set_ir(wiimote->device, wiimote->useIR);
373 #if defined (vrpn_THREADS_AVAILABLE)
374 waitingForConnection(true),
378 wiimote(new vrpn_Wiimote_Device)
380 #ifndef vrpn_THREADS_AVAILABLE
381 last_reconnect_attempt.tv_sec = 0;
382 last_reconnect_attempt.tv_usec = 0;
405 FAIL(
"vrpn_WiiMote: can't register change channel request handler");
412 FAIL(
"vrpn_WiiMote: can't register change channels request handler");
420 FAIL(
"Can't register self-destruct handler");
426 wiimote->which = which > 0 ? which : 1;
427 wiimote->useMS = useMS;
428 wiimote->useIR = useIR;
429 wiimote->reorderButtons = (reorderButtons != 0);
431 wiimote->bdaddr = std::string(bdaddr);
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();
441 #if !defined(DEBUG) && defined(WIIUSE_HAS_OUTPUT_REDIRECTION)
443 wiiuse_set_output(LOGLEVEL_DEBUG, 0);
444 wiiuse_set_output(LOGLEVEL_INFO, 0);
446 #if defined (vrpn_THREADS_AVAILABLE)
450 sharedData =
new vrpn_WiiMote_SharedData(
this);
451 connectThreadData.
pvUD = sharedData;
453 acquireMessageLock();
455 connectThread =
new vrpn_Thread(&vrpn_WiiMote::connectThreadFunc, connectThreadData);
464 #if defined (vrpn_THREADS_AVAILABLE)
466 sharedData->stopFlag =
true;
468 if (!waitingForConnection) {
469 sharedData->connectLock.v();
471 while (connectThread->running()) {
474 releaseMessageLock();
476 acquireMessageLock();
479 delete connectThread;
484 if (wiimote->connected) {
485 wiiuse_disconnect(wiimote->device);
496 #if defined (vrpn_THREADS_AVAILABLE)
497 if (waitingForConnection) {
499 if (sharedData->connectLock.condP()) {
501 waitingForConnection =
false;
504 releaseMessageLock();
506 acquireMessageLock();
517 #if defined (vrpn_THREADS_AVAILABLE)
518 waitingForConnection =
true;
520 sharedData->connectLock.v();
521 #else // no thread support: we have to block the server:
524 if (diff.tv_sec >= 1) {
525 last_reconnect_attempt = _timestamp;
537 if (wiimote->connected && wiiuse_poll(&(wiimote->device), 1)) {
538 switch (wiimote->device->event) {
547 case WIIUSE_DISCONNECT:
548 case WIIUSE_UNEXPECTED_DISCONNECT:
549 wiimote->connected =
false;
550 wiiuse_disconnect(wiimote->device);
552 #ifndef vrpn_THREADS_AVAILABLE
553 last_reconnect_attempt = _timestamp;
557 case WIIUSE_READ_DATA:
562 case WIIUSE_NUNCHUK_INSERTED:
566 case WIIUSE_CLASSIC_CTRL_INSERTED:
570 case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
575 case WIIUSE_WII_BOARD_CTRL_INSERTED:
580 case WIIUSE_NUNCHUK_REMOVED:
581 case WIIUSE_CLASSIC_CTRL_REMOVED:
582 case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
587 case WIIUSE_WII_BOARD_CTRL_REMOVED:
588 send_text_message(
"Wii Balance Board controller removed/disconnected", _timestamp,
605 return (wiimote->found) && (wiimote->connected);
608 void vrpn_WiiMote::report(vrpn_uint32 class_of_service) {
627 const char* bufptr = p.
buffer;
641 fprintf(stderr,
"vrpn_WiiMote::handle_request_message(): Index out of bounds\n");
643 sprintf(msg,
"Error: (handle_request_message): channel %d is not active. Squelching.", chan_num);
652 wiiuse_rumble(me->wiimote->device, 1);
654 wiiuse_rumble(me->wiimote->device, 0);
660 int level =
static_cast<int>(value);
661 wiiuse_set_ir_sensitivity(me->wiimote->device, level);
671 const char* bufptr = p.
buffer;
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);
688 sprintf(msg,
"Error: (handle_request_channels_message): invalid channel %d. Squelching.", num);
697 wiiuse_rumble(me->wiimote->device, 1);
699 wiiuse_rumble(me->wiimote->device, 0);
710 #if defined (vrpn_THREADS_AVAILABLE)
713 vrpn_WiiMote_SharedData *sharedData =
static_cast<vrpn_WiiMote_SharedData *
>(threadData.
pvUD);
714 if (! sharedData || ! sharedData->wmHandle) {
719 sharedData->connectLock.p();
720 if (sharedData->stopFlag) {
723 sharedData->wmHandle->connect_wiimote(3);
725 sharedData->connectLock.v();
732 #endif // VRPN_USE_WIIUSE