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 Read data from the wiimote (event version). * * @param wm Pointer to a wiimote_t structure. * @param buffer An allocated buffer to store the data as it arrives from the wiimote. * Must be persistent in memory and large enough to hold the data. * @param addr The address of wiimote memory to read from. * @param len The length of the block to be read. * * The library can only handle one data read request at a time * because it must keep track of the buffer and other * events that are specific to that request. So if a request * has already been made, subsequent requests will be added * to a pending list and be sent out when the previous * finishes. */ int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int addr, uint16_t len) { return wiiuse_read_data_cb(wm, NULL, buffer, addr, len); }
/** * @brief Handle the handshake data from the nunchuk. * * @param nc A pointer to a nunchuk_t structure. * @param data The data read in from the device. * @param len The length of the data block, in bytes. * * @return Returns 1 if handshake was successful, 0 if not. */ int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len) { int i; int offset = 0; nc->btns = 0; nc->btns_held = 0; nc->btns_released = 0; /* set the smoothing to the same as the wiimote */ nc->flags = &wm->flags; nc->accel_calib.st_alpha = wm->accel_calib.st_alpha; /* decrypt data */ for (i = 0; i < len; ++i) data[i] = (data[i] ^ 0x17) + 0x17; if (data[offset] == 0xFF) { /* * Sometimes the data returned here is not correct. * This might happen because the wiimote is lagging * behind our initialization sequence. * To fix this just request the handshake again. * * Other times it's just the first 16 bytes are 0xFF, * but since the next 16 bytes are the same, just use * those. */ if (data[offset + 16] == 0xFF) { /* get the calibration data */ byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte)); WIIUSE_DEBUG("Nunchuk handshake appears invalid, trying again."); wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN); return 0; } else offset += 16; } nc->accel_calib.cal_zero.x = data[offset + 0]; nc->accel_calib.cal_zero.y = data[offset + 1]; nc->accel_calib.cal_zero.z = data[offset + 2]; nc->accel_calib.cal_g.x = data[offset + 4]; nc->accel_calib.cal_g.y = data[offset + 5]; nc->accel_calib.cal_g.z = data[offset + 6]; nc->js.max.x = data[offset + 8]; nc->js.min.x = data[offset + 9]; nc->js.center.x = data[offset + 10]; nc->js.max.y = data[offset + 11]; nc->js.min.y = data[offset + 12]; nc->js.center.y = data[offset + 13]; /* default the thresholds to the same as the wiimote */ nc->orient_threshold = wm->orient_threshold; nc->accel_threshold = wm->accel_threshold; /* handshake done */ wm->exp.type = EXP_NUNCHUK; #ifdef WIN32 wm->timeout = WIIMOTE_DEFAULT_TIMEOUT; #endif return 1; }
/** * @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; } } }