private void OnReport(IReport rawReportData)
        {
            //if (!(reportData is GenericBytesReport)) return;
            if (rawReportData.ReportTypeCode != REPORT_TYPE.GENB)
            {
                return;
            }
            GenericBytesReport reportData = (GenericBytesReport)rawReportData;

            if (reportData.CodeString != "SXTYBEAT")
            {
                return;
            }

            if (0 == Interlocked.Exchange(ref reportUsageLock, 1))
            {
                try
                {
                    State.StartStateChange();
                    try
                    {
                        byte SBJoystick_rawRightY = reverseByte(reportData.ReportBytes[2]);
                        byte SBJoystick_rawRightX = reverseByte(reportData.ReportBytes[3]);
                        byte SBJoystick_rawLeftY  = reverseByte(reportData.ReportBytes[4]);
                        byte SBJoystick_rawLeftX  = reverseByte(reportData.ReportBytes[5]);

                        (State.Controls["stick_left"] as IControlStickWithClick).X  = (float)(((double)SBJoystick_rawLeftX + (double)SBJoystick_rawLeftX) / 240.0 + -1.0);
                        (State.Controls["stick_left"] as IControlStickWithClick).Y  = (float)(((double)SBJoystick_rawLeftY + (double)SBJoystick_rawLeftY) / 240.0 + -1.0);
                        (State.Controls["stick_right"] as IControlStickWithClick).X = (float)(((double)SBJoystick_rawRightX + (double)SBJoystick_rawRightX) / 240.0 + -1.0);
                        (State.Controls["stick_right"] as IControlStickWithClick).Y = (float)(((double)SBJoystick_rawRightY + (double)SBJoystick_rawRightY) / 240.0 + -1.0);

                        (State.Controls["cluster_left"] as IControlButtonQuad).ButtonN = (reportData.ReportBytes[0] & 0x08) == 0x08;
                        (State.Controls["cluster_left"] as IControlButtonQuad).ButtonE = (reportData.ReportBytes[6] & 0x20) == 0x20;
                        (State.Controls["cluster_left"] as IControlButtonQuad).ButtonS = (reportData.ReportBytes[6] & 0x40) == 0x40;
                        (State.Controls["cluster_left"] as IControlButtonQuad).ButtonW = (reportData.ReportBytes[6] & 0x80) == 0x80;

                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonN = (reportData.ReportBytes[1] & 0x10) == 0x10;
                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonE = (reportData.ReportBytes[1] & 0x20) == 0x20;
                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonS = (reportData.ReportBytes[1] & 0x02) == 0x02;
                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonW = (reportData.ReportBytes[1] & 0x01) == 0x01;

                        (State.Controls["stick_right"] as IControlStickWithClick).Click   = (reportData.ReportBytes[6] & 0x10) == 0x10;
                        (State.Controls["stick_left"] as IControlStickWithClick).Click    = (reportData.ReportBytes[6] & 0x08) == 0x08;
                        (State.Controls["menu_right"] as IControlButton).DigitalStage1    = (reportData.ReportBytes[1] & 0x80) == 0x80;
                        (State.Controls["menu_left"] as IControlButton).DigitalStage1     = (reportData.ReportBytes[1] & 0x40) == 0x40;
                        (State.Controls["bumper_right"] as IControlButton).DigitalStage1  = (reportData.ReportBytes[0] & 0x01) == 0x01;
                        (State.Controls["bumper_left"] as IControlButton).DigitalStage1   = (reportData.ReportBytes[0] & 0x04) == 0x04;
                        (State.Controls["trigger_right"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[1] & 0x08) == 0x08;
                        (State.Controls["trigger_left"] as IControlButton).DigitalStage1  = (reportData.ReportBytes[0] & 0x02) == 0x02;

                        (State.Controls["home"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[1] & 0x04) == 0x04;
                    }
                    finally
                    {
                        State.EndStateChange();
                    }
                }
                finally
                {
                    Interlocked.Exchange(ref reportUsageLock, 0);
                }
            }
        }
        private void OnReport(IReport rawReportData)
        {
            //if (!(reportData is GenericBytesReport)) return;
            if (rawReportData.ReportTypeCode != REPORT_TYPE.HID)
            {
                return;
            }
            HidReport reportData = (HidReport)rawReportData;

            // this logic appears to be for a 0x20BC/0x5044

            //Console.WriteLine($"{reportData.ReportId:X2} {BitConverter.ToString(reportData.ReportBytes)}");

            if (reportData.ReportId == 0x05)
            {
                /*int reportLength = reportData.ReportBytes.Reverse().SkipWhile(dr => dr == 0x00).Count();
                 * if (reportLength > 0
                 *   && reportData.ReportBytes[2] != 0xBC)
                 *  Console.WriteLine($"{reportData.ReportId:X2} {BitConverter.ToString(reportData.ReportBytes)}");*/

                //lock (ReportLock)
                {
                    /*int _v21 = 2;
                     * int reportLength = reportData.ReportBytes.Reverse().SkipWhile(dr => dr == 0x00).Count();
                     *
                     * if (reportLength > 0
                     * && reportData.ReportBytes[2] != 0xBC)
                     *  Console.WriteLine($"{reportData.ReportId:X2} {BitConverter.ToString(reportData.ReportBytes)}");
                     *
                     * if (reportLength == 0 || reportData.ReportBytes[2] == 0xBC)
                     * {
                     *  counter++;
                     *  if (state == 2)
                     *  {
                     *      if (counter > 4)
                     *      {
                     *          state = 3;
                     *          _v21 = 1;
                     *          //_10040290(_v21);
                     *          Console.WriteLine($"_10040290({_v21})");
                     *      }
                     *  }
                     *  else
                     *  {
                     *      if (state == 4 && counter > 4)
                     *      {
                     *          state = 5;
                     *          //_10040290(_v21);
                     *          Console.WriteLine($"_10040290({_v21})");
                     *      }
                     *  }
                     * }
                     * else
                     * {
                     *  counter = 0;
                     * }
                     *
                     * if(reportData.ReportBytes[2] == 0x8C)
                     * {
                     *
                     * }*/


                    /*{
                     *  byte[] data = new byte[64];
                     *  data[0] = 0x05;
                     *  data[1] = 0x00;
                     *  data[2] = 0x00;
                     *  data[3] = 0xB0;
                     *  data[4] = 0x02;
                     *  _device.WriteReport(data);
                     * }*/

                    /*if (reportLength >= 0)
                     * {
                     *  if (reportData.ReportBytes[2] == 0x8C)
                     *  {
                     *      local_ac = 2;
                     *  }
                     *  else if (reportData.ReportBytes[2] == 0xF1)
                     *  {
                     *      switch (new string(reportData.ReportBytes.Skip(5).Take(3).Select(dr => (char)dr).ToArray()))
                     *      {
                     *          case "GGF":
                     *              local_b4 = reportData.ReportBytes.Skip(8).Take(8).ToArray();
                     *              Console.WriteLine("GGF fin");
                     *              break;
                     *          case "GDP":
                     *              if (state == 1)
                     *                  state = 2;
                     *
                     *              if (BitConverter.ToUInt16(reportData.ReportBytes, 0) == requestId)
                     *                  //_10006FD0(BitConverter.ToUInt32(reportData.ReportBytes, 10), reportData.ReportBytes[5] - 8);
                     *                  Console.WriteLine($"_10006FD0({BitConverter.ToUInt32(reportData.ReportBytes, 10)}, {reportData.ReportBytes[5] - 8})");
                     *              break;
                     *          case "GDT":
                     *              if (state == 3)
                     *                  state = 4;
                     *              if (BitConverter.ToUInt16(reportData.ReportBytes, 0) == requestId)
                     *                  //_10006FD0(BitConverter.ToUInt32(reportData.ReportBytes, 10), reportData.ReportBytes[5] - 8);
                     *                  Console.WriteLine($"_10006FD0({BitConverter.ToUInt32(reportData.ReportBytes, 10)}, {reportData.ReportBytes[5] - 8});");
                     *              break;
                     *      }
                     *  }
                     * }*/
                    /*if (local_ac == 0)
                     * {
                     *  EnableConfigMode(0x03, 0x02);
                     * }*/
                    /*else if (local_b4[0] == 0)
                     * {
                     *  //write(_020000F005474746, 8);
                     *  {
                     *      byte[] data = new byte[64];
                     *      data[0] = 0x05;
                     *      data[1] = 0x00;
                     *      data[2] = 0x00;
                     *      data[3] = 0xF0;
                     *      data[4] = 0x05;
                     *      data[5] = 0x47;
                     *      data[6] = 0x47;
                     *      data[7] = 0x46;
                     *      _device.WriteReport(data);
                     *      Console.ForegroundColor = ConsoleColor.DarkGray;
                     *      Console.WriteLine($"{BitConverter.ToString(data)}");
                     *      Console.ResetColor();
                     *  }
                     *  state = 1;
                     * }
                     * else
                     * {
                     *  if (state == 1)
                     *  {
                     *      if (local_74 == 0)
                     *      {
                     *          seq++;
                     *          //_020000F005474450[1...2] = seq;
                     *          //write(_020000F005474450, 8);
                     *          {
                     *              byte[] data = new byte[64];
                     *              data[0] = 0x05;
                     *              data[1] = (byte)(seq & 0xFF);
                     *              data[2] = (byte)((seq >> 8) & 0xFF);
                     *              data[3] = 0xF0;
                     *              data[4] = 0x05;
                     *              data[5] = 0x47;
                     *              data[6] = 0x44;
                     *              data[7] = 0x50;
                     *              _device.WriteReport(data);
                     *              Console.ForegroundColor = ConsoleColor.DarkGray;
                     *              Console.WriteLine($"{BitConverter.ToString(data)}");
                     *              Console.ResetColor();
                     *          }
                     *      }
                     *  }
                     *  else if (state == 3)
                     *  {
                     *      if (local_5c == 0)
                     *      {
                     *          seq++;
                     *          //_020000F005474454[1...2] = seq;
                     *          //write(_020000F005474746, 8);
                     *          {
                     *              byte[] data = new byte[64];
                     *              data[0] = 0x05;
                     *              data[1] = (byte)(seq & 0xFF);
                     *              data[2] = (byte)((seq >> 8) & 0xFF);
                     *              data[3] = 0xF0;
                     *              data[4] = 0x05;
                     *              data[5] = 0x47;
                     *              data[6] = 0x47;
                     *              data[7] = 0x46;
                     *              _device.WriteReport(data);
                     *              Console.ForegroundColor = ConsoleColor.DarkGray;
                     *              Console.WriteLine($"{BitConverter.ToString(data)}");
                     *              Console.ResetColor();
                     *          }
                     *      }
                     *  }
                     *  else if (state == 5)
                     *  {
                     *      //write(_020000800301, 6);
                     *      {
                     *          byte[] data = new byte[64];
                     *          data[0] = 0x05;
                     *          data[1] = 0x00;
                     *          data[2] = 0x00;
                     *          data[3] = 0x80;
                     *          data[4] = 0x03;
                     *          data[5] = 0x01;
                     *          _device.WriteReport(data);
                     *          Console.ForegroundColor = ConsoleColor.DarkGray;
                     *          Console.WriteLine($"{BitConverter.ToString(data)}");
                     *          Console.ResetColor();
                     *
                     *      }
                     *      //Sleep(1000);
                     *      //state = _1000da70();
                     *      //break;
                     *  }
                     * }*/
                }
            }
            else
            {
                //Console.WriteLine($"{reportData.ReportId:X2} {BitConverter.ToString(reportData.ReportBytes)}");
            }

            switch (reportData.ReportId)
            {
            case 0x05:
                switch (reportData.ReportBytes[2])
                {
                case 0x3D:         // config data came in, so obviously we have it enabled
                    ConfigMode = true;
                    break;

                case 0x8C:         // ACK for config mode enable
                    ConfigMode = true;
                    EnableKeyEvent();
                    break;

                case 0xAC:         // ACK for KeyData for ConfigMode
                    ConfigModeKeyData = true;
                    break;

                case 0xAD:         // KeyData for ConfigMode
                    ConfigModeKeyData = true;
                    break;
                }
                break;
            }

            if (0 == Interlocked.Exchange(ref reportUsageLock, 1))
            {
                try
                {
                    // Clone the current state before altering it since the OldState is likely a shared reference
                    //ControllerState StateInFlight = (ControllerState)State.Clone();

                    //if(_device.VendorId == VENDOR_BETOP && _device.ProductId == PRODUCT_BETOP_ASURA3)
                    {
                        //if(_device2 != null) // device2 is the vendor specific device that handles config events
                        {
                            switch (reportData.ReportId)
                            {
                            case 0x03:
                                if (!ConfigModeKeyData)
                                {
                                    State.StartStateChange();
                                    try
                                    {
                                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonN = (reportData.ReportBytes[2] & 0x10) == 0x10;
                                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonE = (reportData.ReportBytes[2] & 0x02) == 0x02;
                                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonS = (reportData.ReportBytes[2] & 0x01) == 0x01;
                                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonW = (reportData.ReportBytes[2] & 0x08) == 0x08;

                                        switch (reportData.ReportBytes[1])
                                        {
                                        case 0x0f: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.None; break;

                                        case 0x00: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.North; break;

                                        case 0x01: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.NorthEast; break;

                                        case 0x02: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.East; break;

                                        case 0x03: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.SouthEast; break;

                                        case 0x04: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.South; break;

                                        case 0x05: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.SouthWest; break;

                                        case 0x06: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.West; break;

                                        case 0x07: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.NorthWest; break;
                                        }
                                        (State.Controls["bumper_left"] as IControlButton).DigitalStage1  = (reportData.ReportBytes[2] & 0x40) == 0x40;
                                        (State.Controls["bumper_right"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[2] & 0x80) == 0x80;

                                        (State.Controls["trigger_left"] as IControlTrigger).AnalogStage1  = (float)(reportData.ReportBytes[8] > 0 ? reportData.ReportBytes[8] : (reportData.ReportBytes[3] & 0x01) == 0x01 ? byte.MaxValue : 0) / byte.MaxValue;
                                        (State.Controls["trigger_right"] as IControlTrigger).AnalogStage1 = (float)(reportData.ReportBytes[9] > 0 ? reportData.ReportBytes[9] : (reportData.ReportBytes[3] & 0x02) == 0x02 ? byte.MaxValue : 0) / byte.MaxValue;

                                        (State.Controls["stick_left"] as IControlStickWithClick).X      = ControllerMathTools.QuickStickToFloat(reportData.ReportBytes[4]);
                                        (State.Controls["stick_left"] as IControlStickWithClick).Y      = ControllerMathTools.QuickStickToFloat(reportData.ReportBytes[5]);
                                        (State.Controls["stick_left"] as IControlStickWithClick).Click  = (reportData.ReportBytes[3] & 0x20) == 0x20;
                                        (State.Controls["stick_right"] as IControlStickWithClick).X     = ControllerMathTools.QuickStickToFloat(reportData.ReportBytes[6]);
                                        (State.Controls["stick_right"] as IControlStickWithClick).Y     = ControllerMathTools.QuickStickToFloat(reportData.ReportBytes[7]);
                                        (State.Controls["stick_right"] as IControlStickWithClick).Click = (reportData.ReportBytes[3] & 0x40) == 0x40;

                                        (State.Controls["menu_left"] as IControlButton).DigitalStage1  = (reportData.ReportBytes[3] & 0x04) == 0x04;
                                        (State.Controls["menu_right"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[3] & 0x08) == 0x08;

                                        (State.Controls["home"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[3] & 0x10) == 0x10;
                                    }
                                    finally
                                    {
                                        State.EndStateChange();
                                    }
                                }
                                break;

                            case 0x05:
                                switch (reportData.ReportBytes[2])
                                {
                                case 0x3D:
                                {
                                    byte          DataLen = reportData.ReportBytes[3];
                                    StringBuilder bld     = new StringBuilder();
                                    for (int i = 0; i < DataLen - 2; i += 2)
                                    {
                                        switch (reportData.ReportBytes[4 + i])
                                        {
                                        case 0x10:                 // light
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} light");
                                            break;

                                        case 0x20:                 // lightdir
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} lightdir");
                                            break;

                                        case 0x30:                 // lightcolor
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} lightcolor");
                                            break;

                                        case 0x40:                 // lightlevel
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} lightlevel");
                                            break;

                                        case 0x50:                 // freqlevel
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} freqlevel");
                                            break;

                                        case 0x60:                 // viblevel
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} viblevel");
                                            break;

                                        case 0x70:                 // viblight
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} viblight");
                                            break;

                                        case 0x80:                 // battery
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} battery");
                                            break;

                                        case 0x90:                 // leftsense
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} leftsense  |{new string('=', reportData.ReportBytes[4 + i + 1] - 1)}{new string('-', 7 - reportData.ReportBytes[4 + i + 1])}|");
                                            break;

                                        case 0xA0:                 // rightsense
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} rightsense |{new string('=', reportData.ReportBytes[4 + i + 1] - 1)}{new string('-', 7 - reportData.ReportBytes[4 + i + 1])}|");
                                            break;

                                        case 0xB0:                 // ltlevel
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} ltlevel");
                                            break;

                                        case 0xC0:                 // rtlevel
                                            bld.AppendLine($"{reportData.ReportBytes[4 + i + 1]:X2} rtlevel");
                                            break;
                                        }
                                    }
                                    Console.WriteLine(bld.ToString());
                                }
                                break;

                                case 0xAD:
                                {
                                    State.StartStateChange();
                                    try
                                    {
                                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonN = (reportData.ReportBytes[4] == 0x01);
                                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonE = (reportData.ReportBytes[6] == 0x01);
                                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonS = (reportData.ReportBytes[5] == 0x01);
                                        (State.Controls["cluster_right"] as IControlButtonQuad).ButtonW = (reportData.ReportBytes[3] == 0x01);
                                        {
                                            bool buttonUp    = (reportData.ReportBytes[15] == 0x01);
                                            bool buttonRight = (reportData.ReportBytes[18] == 0x01);
                                            bool buttonDown  = (reportData.ReportBytes[16] == 0x01);
                                            bool buttonLeft  = (reportData.ReportBytes[17] == 0x01);
                                            int  padH        = 0;
                                            int  padV        = 0;
                                            if (buttonUp)
                                            {
                                                padV++;
                                            }
                                            if (buttonDown)
                                            {
                                                padV--;
                                            }
                                            if (buttonRight)
                                            {
                                                padH++;
                                            }
                                            if (buttonLeft)
                                            {
                                                padH--;
                                            }
                                            if (padH > 0)
                                            {
                                                if (padV > 0)
                                                {
                                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.NorthEast;
                                                }
                                                else if (padV < 0)
                                                {
                                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.SouthEast;
                                                }
                                                else
                                                {
                                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.East;
                                                }
                                            }
                                            else if (padH < 0)
                                            {
                                                if (padV > 0)
                                                {
                                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.NorthWest;
                                                }
                                                else if (padV < 0)
                                                {
                                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.SouthWest;
                                                }
                                                else
                                                {
                                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.West;
                                                }
                                            }
                                            else
                                            if (padV > 0)
                                            {
                                                (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.North;
                                            }
                                            else if (padV < 0)
                                            {
                                                (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.South;
                                            }
                                            else
                                            {
                                                (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.None;
                                            }
                                        }

                                        (State.Controls["bumper_left"] as IControlButton).DigitalStage1  = (reportData.ReportBytes[7] == 0x01);
                                        (State.Controls["bumper_right"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[8] == 0x01);

                                        (State.Controls["trigger_left"] as IControlTrigger).AnalogStage1  = (float)reportData.ReportBytes[9] / byte.MaxValue;
                                        (State.Controls["trigger_right"] as IControlTrigger).AnalogStage1 = (float)reportData.ReportBytes[10] / byte.MaxValue;

                                        (State.Controls["stick_left"] as IControlStickWithClick).X      = ControllerMathTools.QuickStickToFloat(reportData.ReportBytes[21]);
                                        (State.Controls["stick_left"] as IControlStickWithClick).Y      = ControllerMathTools.QuickStickToFloat(reportData.ReportBytes[22]);
                                        (State.Controls["stick_left"] as IControlStickWithClick).Click  = reportData.ReportBytes[11] == 0x01;
                                        (State.Controls["stick_right"] as IControlStickWithClick).X     = ControllerMathTools.QuickStickToFloat(reportData.ReportBytes[23]);
                                        (State.Controls["stick_right"] as IControlStickWithClick).Y     = ControllerMathTools.QuickStickToFloat(reportData.ReportBytes[24]);
                                        (State.Controls["stick_right"] as IControlStickWithClick).Click = reportData.ReportBytes[12] == 0x01;

                                        (State.Controls["menu_left"] as IControlButton).DigitalStage1  = reportData.ReportBytes[14] == 0x01;
                                        (State.Controls["menu_right"] as IControlButton).DigitalStage1 = reportData.ReportBytes[13] == 0x01;

                                        (State.Controls["menu2_left"] as IControlButton).DigitalStage1  = reportData.ReportBytes[28] == 0x01;
                                        (State.Controls["menu2_right"] as IControlButton).DigitalStage1 = reportData.ReportBytes[27] == 0x01;

                                        (State.Controls["grip_left"] as IControlButton).DigitalStage1  = reportData.ReportBytes[25] == 0x01;
                                        (State.Controls["grip_right"] as IControlButton).DigitalStage1 = reportData.ReportBytes[26] == 0x01;

                                        (State.Controls["home"] as IControlButton).DigitalStage1 = reportData.ReportBytes[29] == 0x01;
                                    }
                                    finally
                                    {
                                        State.EndStateChange();
                                    }
                                }
                                break;
                                }
                                break;
                            }
                        }
                        //else
                        //{
                        //
                        //}
                    }

                    /*
                     * byte SBJoystick_rawRightY = reverseByte(reportData.ReportBytes[2]);
                     * byte SBJoystick_rawRightX = reverseByte(reportData.ReportBytes[3]);
                     * byte SBJoystick_rawLeftY = reverseByte(reportData.ReportBytes[4]);
                     * byte SBJoystick_rawLeftX = reverseByte(reportData.ReportBytes[5]);
                     *
                     * (StateInFlight.Controls["stick_left"] as IControlStick).X = (float)(((double)SBJoystick_rawLeftX + (double)SBJoystick_rawLeftX) / 240.0 + -1.0);
                     * (StateInFlight.Controls["stick_left"] as IControlStick).Y = (float)(((double)SBJoystick_rawLeftY + (double)SBJoystick_rawLeftY) / 240.0 + -1.0);
                     * (StateInFlight.Controls["stick_right"] as IControlStick).X = (float)(((double)SBJoystick_rawRightX + (double)SBJoystick_rawRightX) / 240.0 + -1.0);
                     * (StateInFlight.Controls["stick_right"] as IControlStick).Y = (float)(((double)SBJoystick_rawRightY + (double)SBJoystick_rawRightY) / 240.0 + -1.0);
                     *
                     * (StateInFlight.Controls["cluster_left"] as IControlButtonQuad).ButtonN = (reportData.ReportBytes[0] & 0x08) == 0x08;
                     * (StateInFlight.Controls["cluster_left"] as IControlButtonQuad).ButtonE = (reportData.ReportBytes[6] & 0x20) == 0x20;
                     * (StateInFlight.Controls["cluster_left"] as IControlButtonQuad).ButtonS = (reportData.ReportBytes[6] & 0x40) == 0x40;
                     * (StateInFlight.Controls["cluster_left"] as IControlButtonQuad).ButtonW = (reportData.ReportBytes[6] & 0x80) == 0x80;
                     *
                     * (StateInFlight.Controls["cluster_right"] as IControlButtonQuad).ButtonN = (reportData.ReportBytes[1] & 0x10) == 0x10;
                     * (StateInFlight.Controls["cluster_right"] as IControlButtonQuad).ButtonE = (reportData.ReportBytes[1] & 0x20) == 0x20;
                     * (StateInFlight.Controls["cluster_right"] as IControlButtonQuad).ButtonS = (reportData.ReportBytes[1] & 0x02) == 0x02;
                     * (StateInFlight.Controls["cluster_right"] as IControlButtonQuad).ButtonW = (reportData.ReportBytes[1] & 0x01) == 0x01;
                     *
                     * (StateInFlight.Controls["stick_right"] as IControlStick).Click = (reportData.ReportBytes[6] & 0x10) == 0x10;
                     * (StateInFlight.Controls["stick_left"] as IControlStick).Click = (reportData.ReportBytes[6] & 0x08) == 0x08;
                     * (StateInFlight.Controls["menu"] as ControlButtonPair).Right.Digital = (reportData.ReportBytes[1] & 0x80) == 0x80;
                     * (StateInFlight.Controls["menu"] as ControlButtonPair).Left.Digital = (reportData.ReportBytes[1] & 0x40) == 0x40;
                     * (StateInFlight.Controls["bumpers"] as ControlButtonPair).Right.Digital = (reportData.ReportBytes[0] & 0x01) == 0x01;
                     * (StateInFlight.Controls["bumpers"] as ControlButtonPair).Left.Digital = (reportData.ReportBytes[0] & 0x04) == 0x04;
                     * (StateInFlight.Controls["triggers"] as ControlButtonPair).Right.Digital = (reportData.ReportBytes[1] & 0x08) == 0x08;
                     * (StateInFlight.Controls["triggers"] as ControlButtonPair).Left.Digital = (reportData.ReportBytes[0] & 0x02) == 0x02;
                     *
                     * (StateInFlight.Controls["home"] as ControlButton).Digital = (reportData.ReportBytes[1] & 0x04) == 0x04;
                     */


                    //Console.WriteLine($"{reportData.ReportId:X2} {BitConverter.ToString(reportData.ReportBytes)}");


                    // bring OldState in line with new State
                    //State = StateInFlight;

                    //ControllerStateUpdate?.Invoke(this, State);
                }
                finally
                {
                    Interlocked.Exchange(ref reportUsageLock, 0);
                }
            }
        }
        private void OnReport(IReport rawReportData)
        {
            //if (!(reportData is XInputReport)) return;
            if (rawReportData.ReportTypeCode != REPORT_TYPE.XINP)
            {
                return;
            }
            XInputReport reportData = (XInputReport)rawReportData;

            /*if (reportData.Connected != Connected)
             * {
             *  ConnectedState.Wait();
             *  try
             *  {
             *      if (reportData.Connected)
             *      {
             *          ControllerTypeCode = _DEVICE_XBOX360;
             *          IsPresent = true;
             *          Connected = true;
             *      }
             *      else
             *      {
             *          ControllerTypeCode = _DEVICE_NONE;
             *          IsPresent = false;
             *          Connected = false;
             *      }
             *
             *      ControllerMetadataUpdate?.Invoke(this);
             *  }
             *  finally
             *  {
             *      ConnectedState.Release();
             *  }
             * }*/

            if (Initalized < 1)
            {
                return;
            }

            if (0 == Interlocked.Exchange(ref reportUsageLock, 1))
            {
                ConnectedState.Wait();
                try
                {
                    State.StartStateChange();
                    try
                    {
                        if (reportData.sThumbLX.HasValue)
                        {
                            (State.Controls["stick_left"] as IControlStickWithClick).X = reportData.sThumbLX.Value * 1.0f / Int16.MaxValue;
                        }
                        if (reportData.sThumbLY.HasValue)
                        {
                            (State.Controls["stick_left"] as IControlStickWithClick).Y = reportData.sThumbLY.Value * -1.0f / Int16.MaxValue;
                        }
                        if (reportData.sThumbRX.HasValue)
                        {
                            (State.Controls["stick_right"] as IControlStickWithClick).X = reportData.sThumbRX.Value * 1.0f / Int16.MaxValue;
                        }
                        if (reportData.sThumbRY.HasValue)
                        {
                            (State.Controls["stick_right"] as IControlStickWithClick).Y = reportData.sThumbRY.Value * -1.0f / Int16.MaxValue;
                        }

                        if (reportData.wButtons.HasValue)
                        {
                            (State.Controls["cluster_right"] as IControlButtonQuad).ButtonN = (reportData.wButtons.Value & 0x8000) == 0x8000;
                            (State.Controls["cluster_right"] as IControlButtonQuad).ButtonE = (reportData.wButtons.Value & 0x2000) == 0x2000;
                            (State.Controls["cluster_right"] as IControlButtonQuad).ButtonS = (reportData.wButtons.Value & 0x1000) == 0x1000;
                            (State.Controls["cluster_right"] as IControlButtonQuad).ButtonW = (reportData.wButtons.Value & 0x4000) == 0x4000;

                            bool DPadUp    = (reportData.wButtons.Value & 0x0001) == 0x0001;
                            bool DPadDown  = (reportData.wButtons.Value & 0x0002) == 0x0002;
                            bool DPadLeft  = (reportData.wButtons.Value & 0x0004) == 0x0004;
                            bool DPadRight = (reportData.wButtons.Value & 0x0008) == 0x0008;

                            if (DPadUp && DPadDown)
                            {
                                DPadUp = DPadDown = false;
                            }

                            if (DPadLeft && DPadRight)
                            {
                                DPadLeft = DPadRight = false;
                            }

                            if (DPadUp)
                            {
                                if (DPadRight)
                                {
                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.NorthEast;
                                }
                                else if (DPadLeft)
                                {
                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.NorthWest;
                                }
                                else
                                {
                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.North;
                                }
                            }
                            else if (DPadDown)
                            {
                                if (DPadRight)
                                {
                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.SouthEast;
                                }
                                else if (DPadLeft)
                                {
                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.SouthWest;
                                }
                                else
                                {
                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.South;
                                }
                            }
                            else
                            {
                                if (DPadRight)
                                {
                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.East;
                                }
                                else if (DPadLeft)
                                {
                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.West;
                                }
                                else
                                {
                                    (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.None;
                                }
                            }

                            (State.Controls["stick_right"] as IControlStickWithClick).Click = (reportData.wButtons.Value & 0x0080) == 0x0080;
                            (State.Controls["stick_left"] as IControlStickWithClick).Click  = (reportData.wButtons.Value & 0x0040) == 0x0040;
                            (State.Controls["menu_right"] as ControlButton).DigitalStage1   = (reportData.wButtons.Value & 0x0010) == 0x0010;
                            (State.Controls["menu_left"] as ControlButton).DigitalStage1    = (reportData.wButtons.Value & 0x0020) == 0x0020;
                            (State.Controls["bumper_right"] as ControlButton).DigitalStage1 = (reportData.wButtons.Value & 0x0200) == 0x0200;
                            (State.Controls["bumper_left"] as ControlButton).DigitalStage1  = (reportData.wButtons.Value & 0x0100) == 0x0100;
                            (State.Controls["home"] as IControlButton).DigitalStage1        = (reportData.wButtons.Value & 0x0400) == 0x0400;
                        }

                        //(State.Controls["home"] as ControlButton).Button0 = (buttons & 0x1) == 0x1;
                        if (reportData.bLeftTrigger.HasValue)
                        {
                            (State.Controls["trigger_left"] as ControlTrigger).AnalogStage1 = (float)reportData.bLeftTrigger.Value / byte.MaxValue;
                        }
                        if (reportData.bRightTrigger.HasValue)
                        {
                            (State.Controls["trigger_right"] as ControlTrigger).AnalogStage1 = (float)reportData.bRightTrigger.Value / byte.MaxValue;
                        }
                    }
                    finally
                    {
                        State.EndStateChange();
                    }
                }
                finally
                {
                    ConnectedState.Release();
                    Interlocked.Exchange(ref reportUsageLock, 0);
                }
            }
        }
Exemple #4
0
        private void OnReport(IReport rawReportData)
        {
            if (PollingState == EPollingState.Inactive) return;
            //if (!(reportData is HidReport)) return;
            if (rawReportData.ReportTypeCode != REPORT_TYPE.HID) return;
            HidReport reportData = (HidReport)rawReportData;

            if (0 == Interlocked.Exchange(ref reportUsageLock, 1))
            {
                try
                {
                    int baseOffset = 0;
                    bool HasStateData = true;
                    if (ConnectionType == EConnectionType.Bluetooth && reportData.ReportId == 0x01)
                    {
                        State.StartStateChange();
                        try
                        {
                            (State.Controls["stick_left"] as IControlStickWithClick).X = (reportData.ReportBytes[baseOffset + 0] - 128) / 128f;
                            (State.Controls["stick_left"] as IControlStickWithClick).Y = (reportData.ReportBytes[baseOffset + 1] - 128) / 128f;
                            (State.Controls["stick_right"] as IControlStickWithClick).X = (reportData.ReportBytes[baseOffset + 2] - 128) / 128f;
                            (State.Controls["stick_right"] as IControlStickWithClick).Y = (reportData.ReportBytes[baseOffset + 3] - 128) / 128f;

                            (State.Controls["cluster_right"] as IControlButtonQuad).ButtonN = (reportData.ReportBytes[baseOffset + 4] & 128) == 128;
                            (State.Controls["cluster_right"] as IControlButtonQuad).ButtonE = (reportData.ReportBytes[baseOffset + 4] & 64) == 64;
                            (State.Controls["cluster_right"] as IControlButtonQuad).ButtonS = (reportData.ReportBytes[baseOffset + 4] & 32) == 32;
                            (State.Controls["cluster_right"] as IControlButtonQuad).ButtonW = (reportData.ReportBytes[baseOffset + 4] & 16) == 16;

                            switch ((reportData.ReportBytes[baseOffset + 4] & 0x0f))
                            {
                                case 0: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.North; break;
                                case 1: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.NorthEast; break;
                                case 2: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.East; break;
                                case 3: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.SouthEast; break;
                                case 4: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.South; break;
                                case 5: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.SouthWest; break;
                                case 6: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.West; break;
                                case 7: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.NorthWest; break;
                                default: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.None; break;
                            }

                            (State.Controls["stick_right"] as IControlStickWithClick).Click = (reportData.ReportBytes[baseOffset + 5] & 128) == 128;
                            (State.Controls["stick_left"] as IControlStickWithClick).Click = (reportData.ReportBytes[baseOffset + 5] & 64) == 64;
                            (State.Controls["menu_right"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[baseOffset + 5] & 32) == 32;
                            (State.Controls["menu_left"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[baseOffset + 5] & 16) == 16;
                            //(StateInFlight.Controls["bumpers2"] as IControlButton).Right.Button0 = (reportData.ReportBytes[baseOffset + 5] & 8) == 8;
                            //(StateInFlight.Controls["bumpers2"] as IControlButton).Left.Button0 = (reportData.ReportBytes[baseOffset + 5] & 4) == 4;
                            (State.Controls["bumper_right"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[baseOffset + 5] & 2) == 2;
                            (State.Controls["bumper_left"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[baseOffset + 5] & 1) == 1;

                            // counter
                            // bld.Append((reportData.ReportBytes[baseOffset + 6] & 0xfc).ToString().PadLeft(3, '0'));

                            (State.Controls["home"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[baseOffset + 6] & 0x1) == 0x1;
                            (State.Controls["touch_center"] as ControlTouch).Click = (reportData.ReportBytes[baseOffset + 6] & 0x2) == 0x2;
                            (State.Controls["trigger_left"] as IControlTrigger).AnalogStage1 = (float)reportData.ReportBytes[baseOffset + 7] / byte.MaxValue;
                            (State.Controls["trigger_right"] as IControlTrigger).AnalogStage1 = (float)reportData.ReportBytes[baseOffset + 8] / byte.MaxValue;
                        }
                        finally
                        {
                            State.EndStateChange();
                        }
                    }
                    else
                    {
                        if (ConnectionType == EConnectionType.Bluetooth)
                        {
                            baseOffset = 1;
                            HasStateData = (reportData.ReportBytes[0] & 0x01) == 0x01;
                        }

                        if (HasStateData)
                        {
                            State.StartStateChange();
                            try
                            {
                                (State.Controls["stick_left"] as IControlStickWithClick).X = (reportData.ReportBytes[baseOffset + 0] - 128) / 128f;
                                (State.Controls["stick_left"] as IControlStickWithClick).Y = (reportData.ReportBytes[baseOffset + 1] - 128) / 128f;
                                (State.Controls["stick_right"] as IControlStickWithClick).X = (reportData.ReportBytes[baseOffset + 2] - 128) / 128f;
                                (State.Controls["stick_right"] as IControlStickWithClick).Y = (reportData.ReportBytes[baseOffset + 3] - 128) / 128f;

                                (State.Controls["cluster_right"] as IControlButtonQuad).ButtonN = (reportData.ReportBytes[baseOffset + 7] & 128) == 128;
                                (State.Controls["cluster_right"] as IControlButtonQuad).ButtonE = (reportData.ReportBytes[baseOffset + 7] & 64) == 64;
                                (State.Controls["cluster_right"] as IControlButtonQuad).ButtonS = (reportData.ReportBytes[baseOffset + 7] & 32) == 32;
                                (State.Controls["cluster_right"] as IControlButtonQuad).ButtonW = (reportData.ReportBytes[baseOffset + 7] & 16) == 16;

                                switch ((reportData.ReportBytes[baseOffset + 7] & 0x0f))
                                {
                                    case 0: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.North; break;
                                    case 1: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.NorthEast; break;
                                    case 2: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.East; break;
                                    case 3: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.SouthEast; break;
                                    case 4: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.South; break;
                                    case 5: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.SouthWest; break;
                                    case 6: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.West; break;
                                    case 7: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.NorthWest; break;
                                    default: (State.Controls["cluster_left"] as IControlDPad).Direction = EDPadDirection.None; break;
                                }

                                (State.Controls["stick_right"] as IControlStickWithClick).Click = (reportData.ReportBytes[baseOffset + 8] & 128) == 128;
                                (State.Controls["stick_left"] as IControlStickWithClick).Click = (reportData.ReportBytes[baseOffset + 8] & 64) == 64;
                                (State.Controls["menu_right"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[baseOffset + 8] & 32) == 32;
                                (State.Controls["menu_left"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[baseOffset + 8] & 16) == 16;
                                //(StateInFlight.Controls["bumpers2"] as ControlButtonPair).Right.Button0 = (reportData.ReportBytes[baseOffset + 8] & 8) == 8;
                                //(StateInFlight.Controls["bumpers2"] as ControlButtonPair).Left.Button0 = (reportData.ReportBytes[baseOffset + 8] & 4) == 4;
                                (State.Controls["bumper_right"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[baseOffset + 8] & 2) == 2;
                                (State.Controls["bumper_left"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[baseOffset + 8] & 1) == 1;

                                (State.Controls["home"] as IControlButton).DigitalStage1 = (reportData.ReportBytes[baseOffset + 9] & 0x1) == 0x1;
                                (State.Controls["touch_center"] as ControlTouch).Click = (reportData.ReportBytes[baseOffset + 9] & 0x2) == 0x2;
                                (State.Controls["mute"] as IControlButtonWithStateLight).DigitalStage1 = (reportData.ReportBytes[baseOffset + 9] & 0x4) == 0x4;
                                (State.Controls["trigger_left"] as IControlTrigger).AnalogStage1 = (float)reportData.ReportBytes[baseOffset + 4] / byte.MaxValue;
                                (State.Controls["trigger_right"] as IControlTrigger).AnalogStage1 = (float)reportData.ReportBytes[baseOffset + 5] / byte.MaxValue;

                                (State.Controls["motion"] as ControlMotion).AngularVelocityX = BitConverter.ToInt16(reportData.ReportBytes, baseOffset + 15);
                                (State.Controls["motion"] as ControlMotion).AngularVelocityZ = BitConverter.ToInt16(reportData.ReportBytes, baseOffset + 17);
                                (State.Controls["motion"] as ControlMotion).AngularVelocityY = BitConverter.ToInt16(reportData.ReportBytes, baseOffset + 19);
                                (State.Controls["motion"] as ControlMotion).AccelerometerX = BitConverter.ToInt16(reportData.ReportBytes, baseOffset + 21);
                                (State.Controls["motion"] as ControlMotion).AccelerometerY = BitConverter.ToInt16(reportData.ReportBytes, baseOffset + 23);
                                (State.Controls["motion"] as ControlMotion).AccelerometerZ = BitConverter.ToInt16(reportData.ReportBytes, baseOffset + 25);

                                //bool DisconnectedFlag = (reportData.ReportBytes[baseOffset + 30] & 0x04) == 0x04;
                                //if (DisconnectedFlag != DisconnectedBit)
                                //{
                                //    DisconnectedBit = DisconnectedFlag;
                                //    ControllerNameUpdated?.Invoke();
                                //}

                                //int TouchDataCount = reportData.ReportBytes[baseOffset + 32];
                                int TouchDataCount = 1;

                                for (int FingerCounter = 0; FingerCounter < TouchDataCount; FingerCounter++)
                                {
                                    bool Finger1 = (reportData.ReportBytes[baseOffset + 32 + (FingerCounter * 9)] & 0x80) != 0x80;
                                    byte Finger1Index = (byte)(reportData.ReportBytes[baseOffset + 32 + (FingerCounter * 9)] & 0x7f);
                                    int F1X = reportData.ReportBytes[baseOffset + 33 + (FingerCounter * 9)]
                                          | ((reportData.ReportBytes[baseOffset + 34 + (FingerCounter * 9)] & 0xF) << 8);
                                    int F1Y = ((reportData.ReportBytes[baseOffset + 34 + (FingerCounter * 9)] & 0xF0) >> 4)
                                             | (reportData.ReportBytes[baseOffset + 35 + (FingerCounter * 9)] << 4);

                                    bool Finger2 = (reportData.ReportBytes[baseOffset + 36 + (FingerCounter * 9)] & 0x80) != 0x80;
                                    byte Finger2Index = (byte)(reportData.ReportBytes[baseOffset + 36 + (FingerCounter * 9)] & 0x7f);
                                    int F2X = reportData.ReportBytes[baseOffset + 37 + (FingerCounter * 9)]
                                          | ((reportData.ReportBytes[baseOffset + 38 + (FingerCounter * 9)] & 0xF) << 8);
                                    int F2Y = ((reportData.ReportBytes[baseOffset + 38 + (FingerCounter * 9)] & 0xF0) >> 4)
                                             | (reportData.ReportBytes[baseOffset + 39 + (FingerCounter * 9)] << 4);

                                    byte touch_timestamp = reportData.ReportBytes[baseOffset + 41 + (FingerCounter * 9)]; // Touch Pad Counter
                                                                                                                          //DateTime tmp_now = DateTime.Now;

                                    byte TimeDelta = touch_last_frame ? GetOverflowedDelta(last_touch_timestamp, touch_timestamp) : (byte)0;

                                    (State.Controls["touch_center"] as ControlTouch).AddTouch(0, Finger1, (F1X / 1919f) * 2f - 1f, (F1Y / 1079f) * 2f - 1f, TimeDelta); // everything beyond 1073 is not reliably producible
                                    (State.Controls["touch_center"] as ControlTouch).AddTouch(1, Finger2, (F2X / 1919f) * 2f - 1f, (F2Y / 1079f) * 2f - 1f, TimeDelta); // everything beyond 1073 is not reliably producible

                                    last_touch_timestamp = touch_timestamp;
                                }

                                touch_last_frame = TouchDataCount > 0;
                            }
                            finally
                            {
                                State.EndStateChange();
                            }
                        }
                    }
                }
                finally
                {
                    Interlocked.Exchange(ref reportUsageLock, 0);
                }
            }
        }