int wiiuse_set_report_type(struct wiimote_t *wm,cmd_blk_cb cb) { ubyte buf[2]; int motion,ir,exp; if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0; buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00); /* set to 0x04 for continuous reporting */ buf[1] = 0x00; motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC) || WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR); exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP); ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR); if (motion && ir && exp) buf[1] = WM_RPT_BTN_ACC_IR_EXP; else if (motion && exp) buf[1] = WM_RPT_BTN_ACC_EXP; else if (motion && ir) buf[1] = WM_RPT_BTN_ACC_IR; else if (ir && exp) buf[1] = WM_RPT_BTN_IR_EXP; else if (ir) buf[1] = WM_RPT_BTN_ACC_IR; else if (exp) buf[1] = WM_RPT_BTN_EXP; else if (motion) buf[1] = WM_RPT_BTN_ACC; else buf[1] = WM_RPT_BTN; WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]); wiiuse_sendcmd(wm,WM_CMD_REPORT_TYPE,buf,2,cb); return buf[1]; }
/** * @brief Get the IR sensitivity settings. * * @param wm Pointer to a wiimote_t structure. * @param block1 [out] Pointer to where block1 will be set. * @param block2 [out] Pointer to where block2 will be set. * * @return Returns the sensitivity level. */ static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2) { if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL1)) { *block1 = WM_IR_BLOCK1_LEVEL1; *block2 = WM_IR_BLOCK2_LEVEL1; return 1; } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL2)) { *block1 = WM_IR_BLOCK1_LEVEL2; *block2 = WM_IR_BLOCK2_LEVEL2; return 2; } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL3)) { *block1 = WM_IR_BLOCK1_LEVEL3; *block2 = WM_IR_BLOCK2_LEVEL3; return 3; } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL4)) { *block1 = WM_IR_BLOCK1_LEVEL4; *block2 = WM_IR_BLOCK2_LEVEL4; return 4; } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL5)) { *block1 = WM_IR_BLOCK1_LEVEL5; *block2 = WM_IR_BLOCK2_LEVEL5; return 5; } *block1 = NULL; *block2 = NULL; return 0; }
void wiiuse_handshake_expansion_start(struct wiimote_t *wm) { if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP) || WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_FAILED) || WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_HANDSHAKE)) return; wm->expansion_state = 0; WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE); wiiuse_handshake_expansion(wm, NULL, 0); }
/** * @brief Set the report type based on the current wiimote state. * * @param wm Pointer to a wiimote_t structure. * * @return The report type sent. * * The wiimote reports formatted packets depending on the * report type that was last requested. This function will * update the type of report that should be sent based on * the current state of the device. */ int wiiuse_set_report_type(struct wiimote_t* wm) { byte buf[2]; int motion, exp, ir, balance_board; if (!wm || !WIIMOTE_IS_CONNECTED(wm)) { return 0; } buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00); /* set to 0x04 for continuous reporting */ buf[1] = 0x00; /* if rumble is enabled, make sure we keep it */ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)) { buf[0] |= 0x01; } motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC); exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP); ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR); balance_board = exp && (wm->exp.type == EXP_WII_BOARD); if (motion && ir && exp) { buf[1] = WM_RPT_BTN_ACC_IR_EXP; } else if (motion && exp) { buf[1] = WM_RPT_BTN_ACC_EXP; } else if (motion && ir) { buf[1] = WM_RPT_BTN_ACC_IR; } else if (ir && exp) { buf[1] = WM_RPT_BTN_IR_EXP; } else if (ir) { buf[1] = WM_RPT_BTN_ACC_IR; } else if(exp && balance_board) { if(wm->exp.wb.use_alternate_report) buf[1] = WM_RPT_BTN_EXP_8; else buf[1] = WM_RPT_BTN_EXP; } else if (exp) { buf[1] = WM_RPT_BTN_EXP; } else if (motion) { buf[1] = WM_RPT_BTN_ACC; } else { buf[1] = WM_RPT_BTN; } WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]); exp = wiiuse_send(wm, WM_CMD_REPORT_TYPE, buf, 2); if (exp <= 0) { return exp; } return buf[1]; }
/** * @brief Set if the wiimote should report motion sensing. * * @param wm Pointer to a wiimote_t structure. * @param status 1 to enable, 0 to disable. * * Since reporting motion sensing sends a lot of data, * the wiimote saves power by not transmitting it * by default. */ void wiiuse_motion_sensing(struct wiimote_t* wm, int status) { if (status) { if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_ACC)) return; WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC); } else { if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_ACC)) return; WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC); } if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) return; wiiuse_status(wm,NULL); }
void wiiuse_disable_expansion(struct wiimote_t *wm) { if(!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) return; /* tell the associated module the expansion was removed */ switch(wm->exp.type) { case EXP_NUNCHUK: nunchuk_disconnected(&wm->exp.nunchuk); wm->event = WIIUSE_NUNCHUK_REMOVED; break; case EXP_CLASSIC: classic_ctrl_disconnected(&wm->exp.classic); wm->event = WIIUSE_CLASSIC_CTRL_REMOVED; break; case EXP_GUITAR_HERO_3: guitar_hero_3_disconnected(&wm->exp.gh3); wm->event = WIIUSE_GUITAR_HERO_3_CTRL_REMOVED; break; case EXP_WII_BOARD: wii_board_disconnected(&wm->exp.wb); wm->event = WIIUSE_WII_BOARD_REMOVED; break; default: break; } WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP); wm->exp.type = EXP_NONE; wiiuse_set_ir_mode(wm); wiiuse_status(wm,NULL); }
/** * @brief Send a packet to the wiimote. * * @param wm Pointer to a wiimote_t structure. * @param report_type The report type to send (WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc). Found in wiiuse.h * @param msg The payload. Might be changed by the callee. * @param len Length of the payload in bytes. * * This function should replace any write()s directly to the wiimote device. */ int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len) { switch (report_type) { case WM_CMD_LED: case WM_CMD_RUMBLE: case WM_CMD_CTRL_STATUS: { /* Rumble flag for: 0x11, 0x13, 0x14, 0x15, 0x19 or 0x1a */ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)) { msg[0] |= 0x01; } break; } default: break; } #ifdef WITH_WIIUSE_DEBUG { int x; printf("[DEBUG] (id %i) SEND: (%.2x) %.2x ", wm->unid, report_type, msg[0]); for (x = 1; x < len; ++x) { printf("%.2x ", msg[x]); } printf("\n"); } #endif return wiiuse_os_write(wm, report_type, msg, len); }
/** * @brief Toggle the state of the rumble. * * @param wm Pointer to a wiimote_t structure. */ void wiiuse_toggle_rumble(struct wiimote_t* wm) { if (!wm) { return; } wiiuse_rumble(wm, !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)); }
/** * @brief Enable or disable the rumble. * * @param wm Pointer to a wiimote_t structure. * @param status 1 to enable, 0 to disable. */ void wiiuse_rumble(struct wiimote_t* wm, int status) { byte buf; if (!wm || !WIIMOTE_IS_CONNECTED(wm)) { return; } /* make sure to keep the current lit leds */ buf = wm->leds; if (status) { WIIUSE_DEBUG("Starting rumble..."); WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_RUMBLE); buf |= 0x01; } else { WIIUSE_DEBUG("Stopping rumble..."); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE); buf &= ~(0x01); } /* preserve IR state */ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) { buf |= 0x04; } wiiuse_send(wm, WM_CMD_RUMBLE, &buf, 1); }
void wiiuse_handshake(struct wiimote_t* wm, byte* data, uint16_t len) { /* send request to wiimote for accelerometer calibration */ byte buf[MAX_PAYLOAD]; /* step 0 - Reset wiimote */ { //wiiuse_set_leds(wm, WIIMOTE_LED_NONE); WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP); WIIMOTE_DISABLE_FLAG(wm, WIIUSE_CONTINUOUS); wiiuse_set_report_type(wm); wiiuse_millisleep(500); WIIUSE_DEBUG("Wiimote reset!\n"); } /* step 1 - calibration of accelerometers */ if(wm->type != WIIUSE_WIIMOTE_MOTION_PLUS_INSIDE) { struct accel_t* accel = &wm->accel_calib; wiiuse_read_data_sync(wm, 1, WM_MEM_OFFSET_CALIBRATION, 8, buf); /* received read data */ accel->cal_zero.x = buf[0]; accel->cal_zero.y = buf[1]; accel->cal_zero.z = buf[2]; accel->cal_g.x = buf[4] - accel->cal_zero.x; accel->cal_g.y = buf[5] - accel->cal_zero.y; accel->cal_g.z = buf[6] - accel->cal_zero.z; WIIUSE_DEBUG("Calibrated wiimote acc\n"); } /* step 2 - re-enable IR and ask for status */ { WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); /* now enable IR if it was set before the handshake completed */ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) { WIIUSE_DEBUG("Handshake finished, enabling IR."); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); wiiuse_set_ir(wm, 1); } WIIUSE_DEBUG("Asking for status ...\n"); wm->event = WIIUSE_CONNECT; wiiuse_status(wm); } }
/** * @brief Toggle the state of the rumble. * * @param wm Pointer to a wiimote_t structure. */ void wiiuse_toggle_rumble(struct wiimote_t* wm) { if (!wm) return; WIIMOTE_TOGGLE_STATE(wm, WIIMOTE_STATE_RUMBLE); if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) return; wiiuse_set_leds(wm,wm->leds,NULL); }
int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { int connected = 0; int i = 0; for (; i < wiimotes; ++i) { if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED)) ++connected; } return connected; }
void wiic_mute_speaker( struct wiimote_t* wm, int status ) { if ( status ) { // if already enabled then stop if ( WIIMOTE_IS_SET(wm, WIIMOTE_STATE_SPEAKER_MUTE) ) return; WIIMOTE_ENABLE_STATE( wm, WIIMOTE_STATE_SPEAKER_MUTE ); WIIC_DEBUG("Speaker unmuted"); byte buf = 0x00; wiic_send( wm, WM_CMD_SPEAKER_MUTE, &buf, 1 ); } else { // if already disabled then stop if ( !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_SPEAKER_MUTE) ) return; WIIMOTE_DISABLE_STATE( wm, WIIMOTE_STATE_SPEAKER_MUTE ); WIIC_DEBUG("Speaker muted"); byte buf = 0x04; wiic_send( wm, WM_CMD_SPEAKER_MUTE, &buf, 1 ); } }
/** * Fills status variables. This method fills some status variables always filled in a WiiMoteEvent object. * This function is called in every callback function. */ static void copy_common_status(struct wiimote_t* wm) { /* Variables Declarations */ jmethodID mid; jclass cls = (*globalEnv)->GetObjectClass(globalEnv, globalWim); /* set statuses */ mid = (*globalEnv)->GetMethodID(globalEnv, cls, "setPermanentStatus", "(IZZZZFZZ)V"); if (mid == 0) { return; } (*globalEnv)->CallVoidMethod(globalEnv, globalWim, mid, wm->unid, WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED), WIIUSE_USING_IR(wm), WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE), WIIUSE_USING_ACC(wm), wm->orient_threshold, WIIMOTE_IS_FLAG_SET(wm,WIIUSE_CONTINUOUS), WIIMOTE_IS_FLAG_SET(wm,WIIUSE_SMOOTHING)); }
void wiiuse_send_next_command(struct wiimote_t *wm) { struct cmd_blk_t *cmd = wm->cmd_head; if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return; if(!cmd) return; if(cmd->state!=CMD_READY) return; cmd->state = CMD_SENT; if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) cmd->data[1] |= 0x01; wiiuse_io_write(wm,cmd->data,cmd->len); }
/** * @brief Connect to a wiimote or wiimotes once an address is known. * * @param wm An array of wiimote_t structures. * @param wiimotes The number of wiimote structures in \a wm. * * @return The number of wiimotes that successfully connected. * * @see wiiuse_find() * @see wiiuse_connect_single() * @see wiiuse_disconnect() * * Connect to a number of wiimotes when the address is already set * in the wiimote_t structures. These addresses are normally set * by the wiiuse_find() function, but can also be set manually. */ int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { int connected = 0; int i = 0; for (; i < wiimotes; ++i) { if (!WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND)) /* if the device address is not set, skip it */ continue; if (wiiuse_connect_single(wm[i], NULL)) ++connected; } return connected; }
/** * @brief Set the enabled LEDs. * * @param wm Pointer to a wiimote_t structure. * @param leds What LEDs to enable. * * \a leds is a bitwise or of WIIMOTE_LED_1, WIIMOTE_LED_2, WIIMOTE_LED_3, or WIIMOTE_LED_4. */ void wiiuse_set_leds(struct wiimote_t* wm, int leds) { byte buf; if (!wm || !WIIMOTE_IS_CONNECTED(wm)) { return; } /* remove the lower 4 bits because they control rumble */ wm->leds = (leds & 0xF0); /* make sure if the rumble is on that we keep it on */ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)) { wm->leds |= 0x01; } buf = wm->leds; wiiuse_send(wm, WM_CMD_LED, &buf, 1); }
void wiiuse_set_motion_plus(struct wiimote_t *wm, int status) { ubyte val; if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_HANDSHAKE)) return; WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE); if(status) { val = 0x04; wiiuse_write_data(wm,WM_EXP_MOTION_PLUS_ENABLE,&val,1,wiiuse_motion_plus_check); } else { wiiuse_disable_expansion(wm); val = 0x55; wiiuse_write_data(wm,WM_EXP_MEM_ENABLE1,&val,1,wiiuse_set_motion_plus_clear1); } }
/** * Get status and values from the wiimotes and send it through callbacks. * @param wim the wiimote object to fill with the datas. */ JNIEXPORT void JNICALL Java_wiiusej_WiiUseApi_specialPoll (JNIEnv *env, jobject obj, jobject gath) { /* Variables Declarations */ int i; short leds = 0; jclass cls = (*env)->GetObjectClass(env, gath); jmethodID mid; if (wiiuse_poll(wiimotes, nbMaxWiimotes)) { /* * This happens if something happened on any wiimote. * So go through each one and check if anything happened. */ for (i=0; i < nbMaxWiimotes; ++i) { switch (wiimotes[i]->event) { case WIIUSE_EVENT: /* a generic event occured */ mid = (*env)->GetMethodID(env, cls, "prepareWiiMoteEvent", "(ISSS)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid, wiimotes[i]->btns, wiimotes[i]->btns_released, wiimotes[i]->btns_held); /* * If IR tracking is enabled then print the coordinates * on the virtual screen that the wiimote is pointing to. * * Also make sure that we see at least 1 dot. */ if (WIIUSE_USING_IR(wiimotes[i])) { int a; WIIUSE_GET_IR_SENSITIVITY_CORRECTED(wiimotes[i], &a); mid = (*env)->GetMethodID(env, cls, "prepareIRevent", "(IIFIIIIIISSSF)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->ir.x, wiimotes[i]->ir.y, wiimotes[i]->ir.z, wiimotes[i]->ir.ax, wiimotes[i]->ir.ay, wiimotes[i]->ir.vres[0], wiimotes[i]->ir.vres[1], wiimotes[i]->ir.offset[0], wiimotes[i]->ir.offset[1], wiimotes[i]->ir.pos, wiimotes[i]->ir.aspect, a , wiimotes[i]->ir.distance); mid = (*env)->GetMethodID(env, cls, "addIRPointToPreparedWiiMoteEvent", "(IISSS)V"); if (mid == 0) { return; } /* go through each of the 4 possible IR sources */ for (a=0; a < 4; a++) { /* check if the source is visible */ if (wiimotes[i]->ir.dot[a].visible) { (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->ir.dot[a].x, wiimotes[i]->ir.dot[a].y, wiimotes[i]->ir.dot[a].rx, wiimotes[i]->ir.dot[a].ry, wiimotes[i]->ir.dot[a].size); } } } /* Motion Sensing */ if (WIIUSE_USING_ACC(wiimotes[i])) { /* set orientation and gravity force */ mid = (*env)->GetMethodID(env, cls, "addMotionSensingValues", "(FIZFFFFFFFFFSSS)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->orient_threshold, wiimotes[i]->accel_threshold, WIIMOTE_IS_FLAG_SET(wiimotes[i],WIIUSE_SMOOTHING), wiimotes[i]->accel_calib.st_alpha, wiimotes[i]->orient.roll, wiimotes[i]->orient.pitch, wiimotes[i]->orient.yaw, wiimotes[i]->orient.a_roll, wiimotes[i]->orient.a_pitch, wiimotes[i]->gforce.x, wiimotes[i]->gforce.y, wiimotes[i]->gforce.z, wiimotes[i]->accel.x, wiimotes[i]->accel.y, wiimotes[i]->accel.z); } /* Expansions support support*/ if (WIIUSE_USING_EXP(wiimotes[i])) { /* Nunchuk support */ if (wiimotes[i]->exp.type == EXP_NUNCHUK) { /* put nunchuk values in wiimote generic event */ mid = (*env)->GetMethodID(env, cls, "addNunchunkEventToPreparedWiimoteEvent", "(SSSFIZFFFFFFFFFSSSFFSSSSSS)V"); if (mid == 0) { return; } struct nunchuk_t* nc = (nunchuk_t*)&wiimotes[i]->exp.nunchuk; (*env)->CallVoidMethod(env, gath, mid, /* buttons */ nc->btns,nc->btns_released,nc->btns_held, /* motion sensing */ nc->orient_threshold,nc->accel_threshold, WIIMOTE_IS_FLAG_SET(wiimotes[i],WIIUSE_SMOOTHING),nc->accel_calib.st_alpha, nc->orient.roll, nc->orient.pitch, nc->orient.yaw, nc->orient.a_roll, nc->orient.a_pitch, nc->gforce.x, nc->gforce.y, nc->gforce.z, nc->accel.x, nc->accel.y, nc->accel.z, /* joystick */ nc->js.ang,nc->js.mag, nc->js.max.x,nc->js.max.y, nc->js.min.x,nc->js.min.y, nc->js.center.x,nc->js.center.y); } else if (wiimotes[i]->exp.type == EXP_GUITAR_HERO_3) { /* put guitar hero values in wiimote generic event */ mid = (*env)->GetMethodID(env, cls, "addGuitarHeroEventToPreparedWiimoteEvent", "(SSSFFFSSSSSS)V"); if (mid == 0) { return; } struct guitar_hero_3_t* gh = (guitar_hero_3_t*)&wiimotes[i]->exp.gh3; (*env)->CallVoidMethod(env, gath, mid, /* buttons */ gh->btns,gh->btns_released,gh->btns_held, /* whammy bar */ gh->whammy_bar, /* joystick */ gh->js.ang,gh->js.mag, gh->js.max.x,gh->js.max.y, gh->js.min.x,gh->js.min.y, gh->js.center.x,gh->js.center.y); }if (wiimotes[i]->exp.type == EXP_CLASSIC) { /* put classic controller values in wiimote generic event */ mid = (*env)->GetMethodID(env, cls, "addClassicControllerEventToPreparedWiimoteEvent", "(SSSFFFFSSSSSSFFSSSSSS)V"); if (mid == 0) { return; } struct classic_ctrl_t* cl = (classic_ctrl_t*)&wiimotes[i]->exp.classic; (*env)->CallVoidMethod(env, gath, mid, /* buttons */ cl->btns,cl->btns_released,cl->btns_held, /* shoulder buttons */ cl->r_shoulder,cl->l_shoulder, /* joystick left*/ cl->ljs.ang,cl->ljs.mag, cl->ljs.max.x,cl->ljs.max.y, cl->ljs.min.x,cl->ljs.min.y, cl->ljs.center.x,cl->ljs.center.y, /* joystick right */ cl->rjs.ang,cl->rjs.mag, cl->rjs.max.x,cl->rjs.max.y, cl->rjs.min.x,cl->rjs.min.y, cl->rjs.center.x,cl->rjs.center.y); } } /* add generic event to java object used to gather events in c environment */ mid = (*env)->GetMethodID(env, cls, "addWiimoteEvent", "()V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid); break; case WIIUSE_DISCONNECT: /* the wiimote disconnected */ mid = (*env)->GetMethodID(env, cls, "addDisconnectionEvent", "(I)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid); break; case WIIUSE_UNEXPECTED_DISCONNECT: /* the wimote disconnected */ mid = (*env)->GetMethodID(env, cls, "addDisconnectionEvent", "(I)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid); break; case WIIUSE_NUNCHUK_INSERTED: /* the nunchuk was just connected */ mid = (*env)->GetMethodID(env, cls, "addNunchukInsertedEvent", "(I)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid); break; case WIIUSE_NUNCHUK_REMOVED: /* the nunchuk disconnected */ mid = (*env)->GetMethodID(env, cls, "addNunchukRemovedEvent", "(I)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid); break; case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED: /* the guitar hero was just connected */ mid = (*env)->GetMethodID(env, cls, "addGuitarHeroInsertedEvent", "(I)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid); break; case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED: /* the guitar hero disconnected */ mid = (*env)->GetMethodID(env, cls, "addGuitarHeroRemovedEvent", "(I)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid); break; case WIIUSE_CLASSIC_CTRL_INSERTED: /* the classic controller was just connected */ mid = (*env)->GetMethodID(env, cls, "addClassicControllerInsertedEvent", "(I)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid); break; case WIIUSE_CLASSIC_CTRL_REMOVED: /* the classic controller disconnected */ mid = (*env)->GetMethodID(env, cls, "addClassicControllerRemovedEvent", "(I)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid); break; case WIIUSE_STATUS: /* a status event occured */ mid = (*env)->GetMethodID(env, cls, "addStatusEvent", "(IZFSZIZZZZ)V"); if (mid == 0) { return; } /* LEDS */ if (WIIUSE_IS_LED_SET(wiimotes[i], 1)) leds += 1; if (WIIUSE_IS_LED_SET(wiimotes[i], 2)) leds += 2; if (WIIUSE_IS_LED_SET(wiimotes[i], 3)) leds += 4; if (WIIUSE_IS_LED_SET(wiimotes[i], 4)) leds += 8; (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid, WIIMOTE_IS_SET(wiimotes[i], WIIMOTE_STATE_CONNECTED), wiimotes[i]->battery_level, leds, WIIUSE_USING_SPEAKER(wiimotes[i]), wiimotes[i]->exp.type,WIIMOTE_IS_SET(wiimotes[i], WIIMOTE_STATE_RUMBLE), WIIMOTE_IS_FLAG_SET(wiimotes[i],WIIUSE_CONTINUOUS), WIIUSE_USING_IR(wiimotes[i]),WIIUSE_USING_ACC(wiimotes[i])); break; default: break; } } } }
void wiiuse_handshake(struct wiimote_t* wm, byte* data, uint16_t len) { if (!wm) { return; } switch (wm->handshake_state) { case 0: { byte* buf; /* continuous reporting off, report to buttons only */ WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); wiiuse_set_leds(wm, WIIMOTE_LED_NONE); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE); WIIMOTE_DISABLE_FLAG(wm, WIIUSE_CONTINUOUS); wiiuse_set_report_type(wm); /* send request to wiimote for accelerometer calibration */ buf = (byte*)malloc(sizeof(byte) * 8); wiiuse_read_data_cb(wm, wiiuse_handshake, buf, WM_MEM_OFFSET_CALIBRATION, 7); wm->handshake_state++; wiiuse_set_leds(wm, WIIMOTE_LED_NONE); break; } case 1: { struct read_req_t* req = wm->read_req; struct accel_t* accel = &wm->accel_calib; byte val; /* received read data */ accel->cal_zero.x = req->buf[0]; accel->cal_zero.y = req->buf[1]; accel->cal_zero.z = req->buf[2]; accel->cal_g.x = req->buf[4] - accel->cal_zero.x; accel->cal_g.y = req->buf[5] - accel->cal_zero.y; accel->cal_g.z = req->buf[6] - accel->cal_zero.z; /* done with the buffer */ free(req->buf); /* handshake is done */ WIIUSE_DEBUG("Handshake finished. Calibration: Idle: X=%x Y=%x Z=%x\t+1g: X=%x Y=%x Z=%x", accel->cal_zero.x, accel->cal_zero.y, accel->cal_zero.z, accel->cal_g.x, accel->cal_g.y, accel->cal_g.z); /* M+ off */ val = 0x55; wiiuse_write_data_cb(wm, WM_EXP_MEM_ENABLE1, &val, 1, wiiuse_disable_motion_plus1); break; } case 2: { /* request the status of the wiimote to check for any expansion */ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE); wm->handshake_state++; /* now enable IR if it was set before the handshake completed */ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) { WIIUSE_DEBUG("Handshake finished, enabling IR."); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); wiiuse_set_ir(wm, 1); } wm->event = WIIUSE_CONNECT; wiiuse_status(wm); break; } default: { break; } } }
/** * @brief Get initialization data from the wiimote. * * @param wm Pointer to a wiimote_t structure. * @param data unused * @param len unused * * When first called for a wiimote_t structure, a request * is sent to the wiimote for initialization information. * This includes factory set accelerometer data. * The handshake will be concluded when the wiimote responds * with this data. */ void wiiuse_handshake(struct wiimote_t* wm, byte* data, uint16_t len) { if (!wm) return; switch (wm->handshake_state) { case 0: { /* send request to wiimote for accelerometer calibration */ byte* buf; WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); wiiuse_set_leds(wm, WIIMOTE_LED_NONE); buf = (byte*)malloc(sizeof(byte) * 8); wiiuse_read_data_cb(wm, wiiuse_handshake, buf, WM_MEM_OFFSET_CALIBRATION, 7); wm->handshake_state++; wiiuse_set_leds(wm, WIIMOTE_LED_NONE); break; } case 1: { struct read_req_t* req = wm->read_req; struct accel_t* accel = &wm->accel_calib; /* received read data */ accel->cal_zero.x = req->buf[0]; accel->cal_zero.y = req->buf[1]; accel->cal_zero.z = req->buf[2]; accel->cal_g.x = req->buf[4] - accel->cal_zero.x; accel->cal_g.y = req->buf[5] - accel->cal_zero.y; accel->cal_g.z = req->buf[6] - accel->cal_zero.z; /* done with the buffer */ free(req->buf); /* handshake is done */ WIIUSE_DEBUG("Handshake finished. Calibration: Idle: X=%x Y=%x Z=%x\t+1g: X=%x Y=%x Z=%x", accel->cal_zero.x, accel->cal_zero.y, accel->cal_zero.z, accel->cal_g.x, accel->cal_g.y, accel->cal_g.z); /* request the status of the wiimote to see if there is an expansion */ wiiuse_status(wm); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE); wm->handshake_state++; /* now enable IR if it was set before the handshake completed */ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) { WIIUSE_DEBUG("Handshake finished, enabling IR."); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); wiiuse_set_ir(wm, 1); } break; } default: { break; } } }
void wiic_set_speaker( struct wiimote_t* wm, int status ) { if ( status ) { // if already enabled then stop if ( WIIMOTE_IS_SET(wm, WIIMOTE_STATE_SPEAKER) ) return; WIIMOTE_ENABLE_STATE( wm, WIIMOTE_STATE_SPEAKER ); WIIMOTE_ENABLE_STATE( wm, WIIMOTE_STATE_SPEAKER_MUTE ); byte buf; /* Initialization Protocol */ // Enable Speaker buf = 0x04; wiic_send( wm, WM_CMD_SPEAKER_ENABLE, &buf, 1 ); // Mute Speaker buf = 0x04; wiic_send( wm, WM_CMD_SPEAKER_MUTE, &buf, 1 ); // Write 0x01 to register 0xa20009 buf = 0x01; wiic_write_data( wm, 0x04a20009, &buf, 1 ); // Write 0x08 to register 0xa20001 buf = 0x08; wiic_write_data( wm, 0x04a20001, &buf, 1 ); // 1st byte for configuration buf = 0x00; wiic_write_data( wm, 0x04a20001, &buf, 1 ); // 2nd byte for configuration buf = 0x00; wiic_write_data( wm, 0x04a20002, &buf, 1 ); // 3rd byte for configuration buf = 0xD0; wiic_write_data( wm, 0x04a20003, &buf, 1 ); // 4th byte for configuration buf = 0x07; wiic_write_data( wm, 0x04a20004, &buf, 1 ); // 5th byte for configuration buf = 40; wiic_write_data( wm, 0x04a20005, &buf, 1 ); // 6th byte for configuration buf = 0x00; wiic_write_data( wm, 0x04a20006, &buf, 1 ); // 7th byte for configuration buf = 0x00; wiic_write_data( wm, 0x04a20007, &buf, 1 ); // Write 0x01 to register 0xa20008 buf = 0x01; wiic_write_data( wm, 0x04a20008, &buf, 1 ); // Unmute Speaker buf = 0x00; wiic_send( wm, WM_CMD_SPEAKER_MUTE, &buf, 1 ); WIIC_DEBUG("Speaker enabled"); } else { // if already disabled then stop if ( !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_SPEAKER) ) return; WIIMOTE_DISABLE_STATE( wm, WIIMOTE_STATE_SPEAKER ); WIIMOTE_DISABLE_STATE( wm, WIIMOTE_STATE_SPEAKER_MUTE ); WIIC_DEBUG("Speaker disabled"); byte buf = 0x00; wiic_send( wm, WM_CMD_SPEAKER_ENABLE, &buf, 1 ); } /* set the wiimote report type */ wiic_set_report_type( wm ); /* wait for the wiimote to catch up */ usleep( 50000 ); }
/** * Get status and values from the wiimotes and send it through callbacks. * @param wim the wiimote object to fill with the datas. */ JNIEXPORT void JNICALL Java_wiiusej_WiiUseApi_specialPoll (JNIEnv *env, jobject obj, jobject gath) { /* Variables Declarations */ int i; short leds = 0; jclass cls = (*env)->GetObjectClass(env, gath); jmethodID mid; if (wiiuse_poll(wiimotes, nbMaxWiiMotes)) { /* * This happens if something happened on any wiimote. * So go through each one and check if anything happened. */ for (i=0; i < nbMaxWiiMotes; ++i) { switch (wiimotes[i]->event) { case WIIUSE_EVENT: /* a generic event occured */ mid = (*env)->GetMethodID(env, cls, "prepareWiiMoteEvent", "(ISSS)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid, wiimotes[i]->btns, wiimotes[i]->btns_released, wiimotes[i]->btns_held); /* * If IR tracking is enabled then print the coordinates * on the virtual screen that the wiimote is pointing to. * * Also make sure that we see at least 1 dot. */ if (WIIUSE_USING_IR(wiimotes[i])) { int a = 0; mid = (*env)->GetMethodID(env, cls, "prepareIRevent", "(IIIIIIIIISS)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->ir.x, wiimotes[i]->ir.y, wiimotes[i]->ir.z, wiimotes[i]->ir.ax, wiimotes[i]->ir.ay, wiimotes[i]->ir.vres[0], wiimotes[i]->ir.vres[1], wiimotes[i]->ir.offset[0], wiimotes[i]->ir.offset[1], wiimotes[i]->ir.pos, wiimotes[i]->ir.aspect); mid = (*env)->GetMethodID(env, cls, "addIRPointToPreparedWiiMoteEvent", "(IISSS)V"); if (mid == 0) { return; } /* go through each of the 4 possible IR sources */ for (; a < 4; a++) { /* check if the source is visible */ if (wiimotes[i]->ir.dot[a].visible) { (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->ir.dot[a].x, wiimotes[i]->ir.dot[a].y, wiimotes[i]->ir.dot[a].rx, wiimotes[i]->ir.dot[a].ry, wiimotes[i]->ir.dot[a].size); } } } /* Motion Sensing */ if (WIIUSE_USING_ACC(wiimotes[i])) { /* set orientation and gravity force */ mid = (*env)->GetMethodID(env, cls, "addMotionSensingValues", "(FIZFFFFFFFSSS)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->orient_threshold, wiimotes[i]->accel_threshold, WIIMOTE_IS_FLAG_SET(wiimotes[i],WIIUSE_SMOOTHING), wiimotes[i]->accel_calib.st_alpha, wiimotes[i]->orient.roll, wiimotes[i]->orient.pitch, wiimotes[i]->orient.yaw, wiimotes[i]->gforce.x, wiimotes[i]->gforce.y, wiimotes[i]->gforce.z, wiimotes[i]->accel.x, wiimotes[i]->accel.y, wiimotes[i]->accel.z); } /* add generic event to java object used to gather events in c environment */ mid = (*env)->GetMethodID(env, cls, "addWiimoteEvent", "()V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid); break; case WIIUSE_STATUS: /* a status event occured */ mid = (*env)->GetMethodID(env, cls, "addStatusEvent", "(IZFSZIZZZZ)V"); if (mid == 0) { return; } /* LEDS */ if (WIIUSE_IS_LED_SET(wiimotes[i], 1)) leds += 1; if (WIIUSE_IS_LED_SET(wiimotes[i], 2)) leds += 2; if (WIIUSE_IS_LED_SET(wiimotes[i], 3)) leds += 4; if (WIIUSE_IS_LED_SET(wiimotes[i], 4)) leds += 8; (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid, WIIMOTE_IS_SET(wiimotes[i], WIIMOTE_STATE_CONNECTED), wiimotes[i]->battery_level, leds, WIIUSE_USING_SPEAKER(wiimotes[i]), wiimotes[i]->exp.type,WIIMOTE_IS_SET(wiimotes[i], WIIMOTE_STATE_RUMBLE), WIIMOTE_IS_FLAG_SET(wiimotes[i],WIIUSE_CONTINUOUS), WIIUSE_USING_IR(wiimotes[i]),WIIUSE_USING_ACC(wiimotes[i])); break; case WIIUSE_DISCONNECT: /* the wiimote disconnected */ mid = (*env)->GetMethodID(env, cls, "addDisconnectionEvent", "(I)V"); if (mid == 0) { return; } (*env)->CallVoidMethod(env, gath, mid, wiimotes[i]->unid); break; default: break; } } } }
int wiiuse_os_poll(struct wiimote_t** wm, int wiimotes) { int evnt; struct timeval tv; fd_set fds; int r; int i; byte read_buffer[MAX_PAYLOAD]; int highest_fd = -1; evnt = 0; if (!wm) { return 0; } /* block select() for 1/2000th of a second */ tv.tv_sec = 0; tv.tv_usec = 500; FD_ZERO(&fds); for (i = 0; i < wiimotes; ++i) { /* only poll it if it is connected */ if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED)) { FD_SET(wm[i]->in_sock, &fds); /* find the highest fd of the connected wiimotes */ if (wm[i]->in_sock > highest_fd) { highest_fd = wm[i]->in_sock; } } wm[i]->event = WIIUSE_NONE; } if (highest_fd == -1) /* nothing to poll */ { return 0; } if (select(highest_fd + 1, &fds, NULL, NULL, &tv) == -1) { WIIUSE_ERROR("Unable to select() the wiimote interrupt socket(s)."); perror("Error Details"); return 0; } /* check each socket for an event */ for (i = 0; i < wiimotes; ++i) { /* if this wiimote is not connected, skip it */ if (!WIIMOTE_IS_CONNECTED(wm[i])) { continue; } if (FD_ISSET(wm[i]->in_sock, &fds)) { /* clear out the event buffer */ memset(read_buffer, 0, sizeof(read_buffer)); /* clear out any old read data */ clear_dirty_reads(wm[i]); /* read the pending message into the buffer */ r = wiiuse_os_read(wm[i], read_buffer, sizeof(read_buffer)); if (r > 0) { /* propagate the event */ propagate_event(wm[i], read_buffer[0], read_buffer + 1); evnt += (wm[i]->event != WIIUSE_NONE); } } else { /* send out any waiting writes */ wiiuse_send_next_pending_write_request(wm[i]); idle_cycle(wm[i]); } } return evnt; }
/** * @brief Enable or disable the rumble. * * @param wm Pointer to a wiimote_t structure. * @param status 1 to enable, 0 to disable. */ void wiiuse_rumble(struct wiimote_t* wm, int status) { if (status && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) return; else if(!status && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) return; wiiuse_toggle_rumble(wm); }
/** * @brief Interpret IR data into more user friendly variables. * * @param wm Pointer to a wiimote_t structure. */ static void interpret_ir_data(struct wiimote_t* wm) { struct ir_dot_t* dot = wm->ir.dot; int i; float roll = 0.0f; int last_num_dots = wm->ir.num_dots; if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC)) roll = wm->orient.roll; /* count visible dots */ wm->ir.num_dots = 0; for (i = 0; i < 4; ++i) { if (dot[i].visible) wm->ir.num_dots++; } switch (wm->ir.num_dots) { case 0: { wm->ir.state = 0; /* reset the dot ordering */ for (i = 0; i < 4; ++i) dot[i].order = 0; wm->ir.x = 0; wm->ir.y = 0; wm->ir.z = 0.0f; return; } case 1: { fix_rotated_ir_dots(wm->ir.dot, roll); if (wm->ir.state < 2) { /* * Only 1 known dot, so use just that. */ for (i = 0; i < 4; ++i) { if (dot[i].visible) { wm->ir.x = dot[i].x; wm->ir.y = dot[i].y; wm->ir.ax = wm->ir.x; wm->ir.ay = wm->ir.y; /* can't calculate yaw because we don't have the distance */ //wm->orient.yaw = calc_yaw(&wm->ir); ir_convert_to_vres(&wm->ir.x, &wm->ir.y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]); break; } } } else { /* * Only see 1 dot but know theres 2. * Try to estimate where the other one * should be and use that. */ for (i = 0; i < 4; ++i) { if (dot[i].visible) { int ox = 0; int x, y; if (dot[i].order == 1) /* visible is the left dot - estimate where the right is */ ox = dot[i].x + wm->ir.distance; else if (dot[i].order == 2) /* visible is the right dot - estimate where the left is */ ox = dot[i].x - wm->ir.distance; x = ((signed int)dot[i].x + ox) / 2; y = dot[i].y; wm->ir.ax = x; wm->ir.ay = y; wm->orient.yaw = calc_yaw(&wm->ir); if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) { ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]); wm->ir.x = x; wm->ir.y = y; } break; } } } break; } case 2: case 3: case 4: { /* * Two (or more) dots known and seen. * Average them together to estimate the true location. */ int x, y; wm->ir.state = 2; fix_rotated_ir_dots(wm->ir.dot, roll); /* if there is at least 1 new dot, reorder them all */ if (wm->ir.num_dots > last_num_dots) { reorder_ir_dots(dot); wm->ir.x = 0; wm->ir.y = 0; } wm->ir.distance = ir_distance(dot); wm->ir.z = 1023 - wm->ir.distance; get_ir_dot_avg(wm->ir.dot, &x, &y); wm->ir.ax = x; wm->ir.ay = y; wm->orient.yaw = calc_yaw(&wm->ir); if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) { ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]); wm->ir.x = x; wm->ir.y = y; } break; } default: { break; } } #ifdef WITH_WIIUSE_DEBUG { int ir_level; WIIUSE_GET_IR_SENSITIVITY(wm, &ir_level); WIIUSE_DEBUG("IR sensitivity: %i", ir_level); WIIUSE_DEBUG("IR visible dots: %i", wm->ir.num_dots); for (i = 0; i < 4; ++i) if (dot[i].visible) WIIUSE_DEBUG("IR[%i][order %i] (%.3i, %.3i) -> (%.3i, %.3i)", i, dot[i].order, dot[i].rx, dot[i].ry, dot[i].x, dot[i].y); WIIUSE_DEBUG("IR[absolute]: (%i, %i)", wm->ir.x, wm->ir.y); } #endif }
/** * @brief Set if the wiimote should track IR targets. * * @param wm Pointer to a wiimote_t structure. * @param status 1 to enable, 0 to disable. */ void wiiuse_set_ir(struct wiimote_t* wm, int status) { byte buf; char* block1 = NULL; char* block2 = NULL; int ir_level; if (!wm) return; /* * Wait for the handshake to finish first. * When it handshake finishes and sees that * IR is enabled, it will call this function * again to actually enable IR. */ if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE)) { if(status) { WIIUSE_DEBUG("Tried to enable IR, will wait until handshake finishes."); WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR); } // else ignoring request to turn off, since it's turned off by default return; } /* * Check to make sure a sensitivity setting is selected. */ ir_level = get_ir_sens(wm, &block1, &block2); if (!ir_level) { WIIUSE_ERROR("No IR sensitivity setting selected."); return; } if (status) { /* if already enabled then stop */ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) return; WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR); } else { /* if already disabled then stop */ if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) return; WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); } /* set camera 1 and 2 */ buf = (status ? 0x04 : 0x00); wiiuse_send(wm, WM_CMD_IR, &buf, 1); wiiuse_send(wm, WM_CMD_IR_2, &buf, 1); if (!status) { WIIUSE_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid); wiiuse_set_report_type(wm); return; } /* enable IR, set sensitivity */ buf = 0x08; wiiuse_write_data(wm, WM_REG_IR, &buf, 1); /* wait for the wiimote to catch up */ #ifndef WIN32 usleep(50000); #else Sleep(50); #endif /* write sensitivity blocks */ wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9); wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2); /* set the IR mode */ if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) buf = WM_IR_TYPE_BASIC; else buf = WM_IR_TYPE_EXTENDED; wiiuse_write_data(wm, WM_REG_IR_MODENUM, &buf, 1); #ifndef WIN32 usleep(50000); #else Sleep(50); #endif /* set the wiimote report type */ wiiuse_set_report_type(wm); WIIUSE_DEBUG("Enabled IR camera for wiimote id %i (sensitivity level %i).", wm->unid, ir_level); }