Beispiel #1
0
        /// \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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        /// \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);
        }