static void wiiuse_disable_motion_plus2(struct wiimote_t *wm, byte *data, unsigned short len) { WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_FAILED); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE); wiiuse_set_ir_mode(wm); wm->handshake_state++; wiiuse_handshake(wm, NULL, 0); }
static void wiiuse_set_motion_plus_clear2(struct wiimote_t *wm,ubyte *data,uword len) { WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_FAILED); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE); wiiuse_set_ir_mode(wm); wiiuse_status(wm,NULL); }
void wiiuse_handshake_expansion(struct wiimote_t *wm,ubyte *data,uword len) { int id; ubyte val; ubyte *buf = NULL; switch(wm->expansion_state) { /* These two initialization writes disable the encryption */ case 0: wm->expansion_state = 1; val = 0x55; wiiuse_write_data(wm,WM_EXP_MEM_ENABLE1,&val,1,wiiuse_handshake_expansion); break; case 1: wm->expansion_state = 2; val = 0x00; wiiuse_write_data(wm,WM_EXP_MEM_ENABLE2,&val,1,wiiuse_handshake_expansion); break; case 2: wm->expansion_state = 3; buf = __lwp_wkspace_allocate(sizeof(ubyte)*EXP_HANDSHAKE_LEN); wiiuse_read_data(wm,buf,WM_EXP_MEM_CALIBR,EXP_HANDSHAKE_LEN,wiiuse_handshake_expansion); break; case 3: if(!data || !len) return; id = BIG_ENDIAN_LONG(*(int*)(&data[220])); switch(id) { case EXP_ID_CODE_NUNCHUK: if(!nunchuk_handshake(wm,&wm->exp.nunchuk,data,len)) return; break; case EXP_ID_CODE_CLASSIC_CONTROLLER: if(!classic_ctrl_handshake(wm,&wm->exp.classic,data,len)) return; break; case EXP_ID_CODE_GUITAR: if(!guitar_hero_3_handshake(wm,&wm->exp.gh3,data,len)) return; break; case EXP_ID_CODE_WIIBOARD: if(!wii_board_handshake(wm,&wm->exp.wb,data,len)) return; break; default: WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_EXP_HANDSHAKE); WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_EXP_FAILED); __lwp_wkspace_free(data); wiiuse_status(wm,NULL); return; } __lwp_wkspace_free(data); WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_EXP_HANDSHAKE); WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_EXP); wiiuse_set_ir_mode(wm); wiiuse_status(wm,NULL); break; } }
/** * @brief Disconnect a wiimote. * * @param wm Pointer to a wiimote_t structure. * * @see wiic_connect() * * Note that this will not free the wiimote structure. */ void wiic_disconnect( struct wiimote_t* wm ) { if ( !wm || !WIIMOTE_IS_CONNECTED(wm) ) return; close( wm->out_sock ); close( wm->in_sock ); wm->out_sock = -1; wm->in_sock = -1; wm->event = WIIC_NONE; WIIMOTE_DISABLE_STATE( wm, WIIMOTE_STATE_CONNECTED ); WIIMOTE_DISABLE_STATE( wm, WIIMOTE_STATE_HANDSHAKE ); }
void wiiuse_disconnect(struct wiimote_t* wm) { if (!wm || WIIMOTE_IS_CONNECTED(wm)) return; CloseHandle(wm->dev_handle); wm->dev_handle = 0; ResetEvent(&wm->hid_overlap); wm->event = WIIUSE_NONE; WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); }
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 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); }
/** * @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) { WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC); } else { WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC); } wiiuse_set_report_type(wm); }
void wiiuse_handshake(struct wiimote_t *wm,ubyte *data,uword len) { ubyte *buf = NULL; struct accel_t *accel = &wm->accel_calib; //printf("wiiuse_handshake(%d,%p,%d)\n",wm->handshake_state,data,len); switch(wm->handshake_state) { case 0: wm->handshake_state++; wiiuse_set_leds(wm,WIIMOTE_LED_NONE,NULL); wiiuse_status(wm,wiiuse_handshake); return; case 1: wm->handshake_state++; buf = __lwp_wkspace_allocate(sizeof(ubyte)*8); if (len > 2 && data[2]&WM_CTRL_STATUS_BYTE1_ATTACHMENT) { wiiuse_read_data(wm,buf,WM_EXP_ID,6,wiiuse_handshake); return; case 2: if (BIG_ENDIAN_LONG(*(int*)(&data[2])) == EXP_ID_CODE_CLASSIC_WIIU_PRO) { memset(data, 0, 8); WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_WIIU_PRO); break; } buf = data; } wm->handshake_state++; wiiuse_read_data(wm,buf,WM_MEM_OFFSET_CALIBRATION,7,wiiuse_handshake); return; } accel->cal_zero.x = ((data[0]<<2)|((data[3]>>4)&3)); accel->cal_zero.y = ((data[1]<<2)|((data[3]>>2)&3)); accel->cal_zero.z = ((data[2]<<2)|(data[3]&3)); accel->cal_g.x = (((data[4]<<2)|((data[7]>>4)&3)) - accel->cal_zero.x); accel->cal_g.y = (((data[5]<<2)|((data[7]>>2)&3)) - accel->cal_zero.y); accel->cal_g.z = (((data[6]<<2)|(data[7]&3)) - accel->cal_zero.z); __lwp_wkspace_free(data); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE); wm->event = WIIUSE_CONNECT; wiiuse_status(wm,NULL); }
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 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_motion_plus_check(struct wiimote_t *wm,ubyte *data,uword len) { u32 val; if(data == NULL) { wiiuse_read_data(wm, wm->motion_plus_id, WM_EXP_ID, 6, wiiuse_motion_plus_check); } else { WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_FAILED); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE); val = (data[3] << 16) | (data[2] << 24) | (data[4] << 8) | data[5]; if(val == EXP_ID_CODE_MOTION_PLUS) { /* handshake done */ wm->event = WIIUSE_MOTION_PLUS_ACTIVATED; wm->exp.type = EXP_MOTION_PLUS; WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_EXP); wiiuse_set_ir_mode(wm); } } }
/** * @brief Set the IR sensitivity. * * @param wm Pointer to a wiimote_t structure. * @param level 1-5, same as Wii system sensitivity setting. * * If the level is < 1, then level will be set to 1. * If the level is > 5, then level will be set to 5. */ void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) { char* block1 = NULL; char* block2 = NULL; if (!wm) return; if (level > 5) level = 5; if (level < 1) level = 1; WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 | WIIMOTE_STATE_IR_SENS_LVL2 | WIIMOTE_STATE_IR_SENS_LVL3 | WIIMOTE_STATE_IR_SENS_LVL4 | WIIMOTE_STATE_IR_SENS_LVL5)); switch (level) { case 1: WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1); break; case 2: WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2); break; case 3: WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3); break; case 4: WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4); break; case 5: WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5); break; default: return; } /* set the new sensitivity */ get_ir_sens(wm, &block1, &block2); wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9); wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2); WIIUSE_DEBUG("Set IR sensitivity to level %i (unid %i)", level, wm->unid); }
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 ); } }
void wiiuse_handshake(struct wiimote_t *wm,ubyte *data,uword len) { ubyte *buf = NULL; struct accel_t *accel = &wm->accel_calib; //printf("wiiuse_handshake(%d,%p,%d)\n",wm->handshake_state,data,len); switch(wm->handshake_state) { case 0: wm->handshake_state++; wiiuse_set_leds(wm,WIIMOTE_LED_NONE,NULL); buf = __lwp_wkspace_allocate(sizeof(ubyte)*8); wiiuse_read_data(wm,buf,WM_MEM_OFFSET_CALIBRATION,7,wiiuse_handshake); break; case 1: wm->handshake_state++; accel->cal_zero.x = ((data[0]<<2)|((data[3]>>4)&3)); accel->cal_zero.y = ((data[1]<<2)|((data[3]>>2)&3)); accel->cal_zero.z = ((data[2]<<2)|(data[3]&3)); accel->cal_g.x = (((data[4]<<2)|((data[7]>>4)&3)) - accel->cal_zero.x); accel->cal_g.y = (((data[5]<<2)|((data[7]>>2)&3)) - accel->cal_zero.y); accel->cal_g.z = (((data[6]<<2)|(data[7]&3)) - accel->cal_zero.z); __lwp_wkspace_free(data); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE); wm->event = WIIUSE_CONNECT; wiiuse_status(wm,NULL); break; default: break; } }
/** * @brief The wiimote disconnected. * * @param wm Pointer to a wiimote_t structure. */ void wiiuse_disconnected(struct wiimote_t* wm) { if (!wm) { return; } WIIUSE_INFO("Wiimote disconnected [id %i].", wm->unid); /* disable the connected flag */ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); /* reset a bunch of stuff */ wm->leds = 0; wm->state = WIIMOTE_INIT_STATES; wm->read_req = NULL; #ifndef WIIUSE_SYNC_HANDSHAKE wm->handshake_state = 0; #endif wm->btns = 0; wm->btns_held = 0; wm->btns_released = 0; wm->event = WIIUSE_DISCONNECT; }
int wiiuse_os_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { GUID device_id; HANDLE dev; HDEVINFO device_info; int i, index; DWORD len; SP_DEVICE_INTERFACE_DATA device_data; PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL; HIDD_ATTRIBUTES attr; int found = 0; (void) timeout; /* unused */ device_data.cbSize = sizeof(device_data); index = 0; /* get the device id */ HidD_GetHidGuid(&device_id); /* get all hid devices connected */ device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); for (;; ++index) { if (detail_data) { free(detail_data); detail_data = NULL; } /* query the next hid device info */ if (!SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data)) { break; } /* get the size of the data block required */ i = SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL); detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*)malloc(len); detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); /* query the data for this device */ if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) { continue; } /* open the device */ dev = CreateFile(detail_data->DevicePath, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (dev == INVALID_HANDLE_VALUE) { continue; } /* get device attributes */ attr.Size = sizeof(attr); i = HidD_GetAttributes(dev, &attr); if ((attr.VendorID == WM_VENDOR_ID) && (attr.ProductID == WM_PRODUCT_ID)) { /* this is a wiimote */ wm[found]->dev_handle = dev; wm[found]->hid_overlap.hEvent = CreateEvent(NULL, 1, 1, ""); wm[found]->hid_overlap.Offset = 0; wm[found]->hid_overlap.OffsetHigh = 0; WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_DEV_FOUND); WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED); /* try to set the output report to see if the device is actually connected */ if (!wiiuse_set_report_type(wm[found])) { WIIMOTE_DISABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED); continue; } /* do the handshake */ wiiuse_handshake(wm[found], NULL, 0); WIIUSE_INFO("Connected to wiimote [id %i].", wm[found]->unid); ++found; if (found >= max_wiimotes) { break; } } else { /* not a wiimote */ CloseHandle(dev); } } if (detail_data) { free(detail_data); } SetupDiDestroyDeviceInfoList(device_info); return found; }
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 ); }
/** * @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); }
/** * @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 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; } } }