/// \brief Sends a generic block of data to the Wii Remote using the specified Output Report. /// \param type The output report type you would like to send /// \param data The raw data you would like to send using the specified \c type. /// \return On success, the total size of the data written, -1 if HIDApi reports an error, or < -1 if there is an invalid input. /// /// This should only be used to send custom data to the Wii Remote that is currently unimplemented by WiimoteApi. /// In any average use case you can use any of the higher-level output functions provided by WiimoteApi. /// /// The Wii Remote rumble settings are also updated based on RumbleOn. public int SendWithType(OutputDataType type, byte[] data) { byte[] final = new byte[data.Length + 1]; final[0] = (byte)type; for (int x = 0; x < data.Length; x++) { final[x + 1] = data[x]; } if (RumbleOn) { final[1] |= 0x01; } int res = WiimoteManager.SendRaw(hidapi_handle, final); if (res < -1) { Debug.LogError("Incorrect Input to HIDAPI. No data has been sent."); } return(res); }
public bool GetSwing(int num) { if (!WiimoteManager.HasWiimote(num)) { return(false); } bool swing = false; float ac = 0.0f; ac = PitchSpeed + RollSpeed + YawSpeed; if (ac > 300.0f && accelOld < ac && swinged == false) { swing = true; swinged = true; } else if (ac < 50.0f) { swinged = false; } return(swing); }
/// \brief Reads and interprets data reported by the Wii Remote. /// \return On success, > 0, < 0 on failure, 0 if nothing has been recieved. /// /// Wii Remote reads function similarly to a Queue, in FIFO (first in, first out) order. /// For example, if two reports were sent since the last \c ReadWiimoteData() call, /// this call will only read and interpret the first of those two (and "pop" it off /// of the queue). So, in order to make sure you don't fall behind the Wiimote's update /// frequency, you can do something like this (in a game loop for example): /// /// \code /// Wii Remote wiimote; /// int ret; /// do /// { /// ret = wiimote.ReadWiimoteData(); /// } while (ret > 0); /// \endcode public int ReadWiimoteData() { byte[] buf = new byte[22]; int status = WiimoteManager.RecieveRaw(hidapi_handle, buf); if (status <= 0) { return(status); // Either there is some sort of error or we haven't recieved anything } int typesize = GetInputDataTypeSize((InputDataType)buf[0]); byte[] data = new byte[typesize]; for (int x = 0; x < data.Length; x++) { data[x] = buf[x + 1]; } if (WiimoteManager.Debug_Messages) { Debug.Log("Recieved: [" + buf[0].ToString("X").PadLeft(2, '0') + "] " + BitConverter.ToString(data)); } // Variable names used throughout the switch/case block byte[] buttons; byte[] accel; byte[] ext = null; byte[] ir; switch ((InputDataType)buf[0]) // buf[0] is the output ID byte { case InputDataType.STATUS_INFO: // done. buttons = new byte[] { data[0], data[1] }; byte flags = data[2]; byte battery_level = data[5]; Button.InterpretData(buttons); bool old_ext_connected = Status.ext_connected; byte[] total = new byte[] { flags, battery_level }; Status.InterpretData(total); if (expecting_status_report) { expecting_status_report = false; } else // We haven't requested any data report type, meaning a controller has connected. { SendDataReportMode(last_report_type); // If we don't update the data report mode, no updates will be sent } if (Status.ext_connected != old_ext_connected && Type != WiimoteType.PROCONTROLLER) { if (Status.ext_connected) // The Wii Remote doesn't allow reading from the extension identifier { // when nothing is connected. Debug.Log("An extension has been connected."); if (current_ext != ExtensionController.MOTIONPLUS) { ActivateExtension(); RequestIdentifyExtension(); // Identify what extension was connected. } else { ExpectingWiiMotionPlusSwitch = false; } } else { if (!ExpectingWiiMotionPlusSwitch) { _current_ext = ExtensionController.NONE; } Debug.Log("An extension has been disconnected."); } } break; case InputDataType.READ_MEMORY_REGISTERS: // done. buttons = new byte[] { data[0], data[1] }; Button.InterpretData(buttons); if (CurrentReadData == null) { Debug.LogWarning("Recived Register Read Report when none was expected. Ignoring."); return(status); } byte size = (byte)((data[2] >> 4) + 0x01); byte error = (byte)(data[2] & 0x0f); // Error 0x07 means reading from a write-only register // Offset 0xa600fa is for the Wii Motion Plus. This error code can be expected behavior in this case. if (error == 0x07) { if (CurrentReadData.Offset != 0xa600fa) { Debug.LogError("Wiimote reports Read Register error 7: Attempting to read from a write-only register (" + CurrentReadData.Offset.ToString("x") + "). Aborting read."); } CurrentReadData = null; return(status); } // lowOffset is reversed because the Wii Remote reports are in Big Endian order ushort lowOffset = BitConverter.ToUInt16(new byte[] { data[4], data[3] }, 0); ushort expected = (ushort)CurrentReadData.ExpectedOffset; if (expected != lowOffset) { Debug.LogWarning("Expected Register Read Offset (" + expected + ") does not match reported offset from Wii Remote (" + lowOffset + ")"); } byte[] read = new byte[size]; for (int x = 0; x < size; x++) { read[x] = data[x + 5]; } CurrentReadData.AppendData(read); if (CurrentReadData.ExpectedOffset >= CurrentReadData.Offset + CurrentReadData.Size) { CurrentReadData = null; } break; case InputDataType.ACKNOWLEDGE_OUTPUT_REPORT: buttons = new byte[] { data[0], data[1] }; Button.InterpretData(buttons); // TODO: doesn't do any actual error handling, or do any special code about acknowledging the output report. break; case InputDataType.REPORT_BUTTONS: // done. buttons = new byte[] { data[0], data[1] }; Button.InterpretData(buttons); break; case InputDataType.REPORT_BUTTONS_ACCEL: // done. buttons = new byte[] { data[0], data[1] }; Button.InterpretData(buttons); accel = new byte[] { data[0], data[1], data[2], data[3], data[4] }; Accel.InterpretData(accel); break; case InputDataType.REPORT_BUTTONS_EXT8: // done. buttons = new byte[] { data[0], data[1] }; Button.InterpretData(buttons); ext = new byte[8]; for (int x = 0; x < ext.Length; x++) { ext[x] = data[x + 2]; } if (_Extension != null) { _Extension.InterpretData(ext); } break; case InputDataType.REPORT_BUTTONS_ACCEL_IR12: // done. buttons = new byte[] { data[0], data[1] }; Button.InterpretData(buttons); accel = new byte[] { data[0], data[1], data[2], data[3], data[4] }; Accel.InterpretData(accel); ir = new byte[12]; for (int x = 0; x < 12; x++) { ir[x] = data[x + 5]; } Ir.InterpretData(ir); break; case InputDataType.REPORT_BUTTONS_EXT19: // done. buttons = new byte[] { data[0], data[1] }; Button.InterpretData(buttons); ext = new byte[19]; for (int x = 0; x < ext.Length; x++) { ext[x] = data[x + 2]; } if (_Extension != null) { _Extension.InterpretData(ext); } break; case InputDataType.REPORT_BUTTONS_ACCEL_EXT16: // done. buttons = new byte[] { data[0], data[1] }; Button.InterpretData(buttons); accel = new byte[] { data[0], data[1], data[2], data[3], data[4] }; Accel.InterpretData(accel); ext = new byte[16]; for (int x = 0; x < ext.Length; x++) { ext[x] = data[x + 5]; } if (_Extension != null) { _Extension.InterpretData(ext); } break; case InputDataType.REPORT_BUTTONS_IR10_EXT9: // done. buttons = new byte[] { data[0], data[1] }; Button.InterpretData(buttons); ir = new byte[10]; for (int x = 0; x < 10; x++) { ir[x] = data[x + 2]; } Ir.InterpretData(ir); ext = new byte[9]; for (int x = 0; x < 9; x++) { ext[x] = data[x + 12]; } if (_Extension != null) { _Extension.InterpretData(ext); } break; case InputDataType.REPORT_BUTTONS_ACCEL_IR10_EXT6: // done. buttons = new byte[] { data[0], data[1] }; Button.InterpretData(buttons); accel = new byte[] { data[0], data[1], data[2], data[3], data[4] }; Accel.InterpretData(accel); ir = new byte[10]; for (int x = 0; x < 10; x++) { ir[x] = data[x + 5]; } Ir.InterpretData(ir); ext = new byte[6]; for (int x = 0; x < 6; x++) { ext[x] = data[x + 15]; } if (_Extension != null) { _Extension.InterpretData(ext); } break; case InputDataType.REPORT_EXT21: // done. ext = new byte[21]; for (int x = 0; x < ext.Length; x++) { ext[x] = data[x]; } if (_Extension != null) { _Extension.InterpretData(ext); } break; case InputDataType.REPORT_INTERLEAVED: if (!ExpectingSecondInterleavedPacket) { ExpectingSecondInterleavedPacket = true; InterleavedDataBuffer = data; } else if (WiimoteManager.Debug_Messages) { Debug.LogWarning( "Recieved two REPORT_INTERLEAVED (" + InputDataType.REPORT_INTERLEAVED.ToString("x") + ") reports in a row! " + "Expected REPORT_INTERLEAVED_ALT (" + InputDataType.REPORT_INTERLEAVED_ALT.ToString("x") + "). Ignoring!" ); } break; case InputDataType.REPORT_INTERLEAVED_ALT: if (ExpectingSecondInterleavedPacket) { ExpectingSecondInterleavedPacket = false; buttons = new byte[] { data[0], data[1] }; Button.InterpretData(buttons); byte[] ir1 = new byte[18]; byte[] ir2 = new byte[18]; for (int x = 0; x < 18; x++) { ir1[x] = InterleavedDataBuffer[x + 3]; ir2[x] = data[x + 3]; } Ir.InterpretDataInterleaved(ir1, ir2); Accel.InterpretDataInterleaved(InterleavedDataBuffer, data); } else if (WiimoteManager.Debug_Messages) { Debug.LogWarning( "Recieved two REPORT_INTERLEAVED_ALT (" + InputDataType.REPORT_INTERLEAVED_ALT.ToString("x") + ") reports in a row! " + "Expected REPORT_INTERLEAVED (" + InputDataType.REPORT_INTERLEAVED.ToString("x") + "). Ignoring!" ); } break; } if (ext == null) { _RawExtension = null; } else { _RawExtension = new ReadOnlyArray <byte>(ext); } return(status); }