Hid.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. using Ryujinx.Core.OsHle;
  2. using System;
  3. using System.Runtime.InteropServices;
  4. namespace Ryujinx.Core
  5. {
  6. public class Hid
  7. {
  8. /*
  9. Thanks to:
  10. https://github.com/reswitched/libtransistor/blob/development/lib/hid.c
  11. https://github.com/reswitched/libtransistor/blob/development/include/libtransistor/hid.h
  12. https://github.com/switchbrew/libnx/blob/master/nx/source/services/hid.c
  13. https://github.com/switchbrew/libnx/blob/master/nx/include/switch/services/hid.h
  14. struct HidSharedMemory
  15. {
  16. header[0x400];
  17. touchscreen[0x3000];
  18. mouse[0x400];
  19. keyboard[0x400];
  20. unkSection1[0x400];
  21. unkSection2[0x400];
  22. unkSection3[0x400];
  23. unkSection4[0x400];
  24. unkSection5[0x200];
  25. unkSection6[0x200];
  26. unkSection7[0x200];
  27. unkSection8[0x800];
  28. controllerSerials[0x4000];
  29. controllers[0x5000 * 10];
  30. unkSection9[0x4600];
  31. }
  32. */
  33. private const int Hid_Num_Entries = 17;
  34. private Switch Ns;
  35. private long SharedMemOffset;
  36. public Hid(Switch Ns)
  37. {
  38. this.Ns = Ns;
  39. }
  40. public void Init(long HidOffset)
  41. {
  42. unsafe
  43. {
  44. if (HidOffset == 0 || HidOffset + Horizon.HidSize > uint.MaxValue)
  45. {
  46. return;
  47. }
  48. SharedMemOffset = HidOffset;
  49. uint InnerOffset = (uint)Marshal.SizeOf(typeof(HidSharedMemHeader));
  50. IntPtr HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset);
  51. HidTouchScreen TouchScreen = new HidTouchScreen();
  52. TouchScreen.Header.TimestampTicks = (ulong)Environment.TickCount;
  53. TouchScreen.Header.NumEntries = (ulong)Hid_Num_Entries;
  54. TouchScreen.Header.LatestEntry = 0;
  55. TouchScreen.Header.MaxEntryIndex = (ulong)Hid_Num_Entries - 1;
  56. TouchScreen.Header.Timestamp = (ulong)Environment.TickCount;
  57. Marshal.StructureToPtr(TouchScreen, HidPtr, false);
  58. InnerOffset += (uint)Marshal.SizeOf(typeof(HidTouchScreen));
  59. HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset);
  60. HidMouse Mouse = new HidMouse();
  61. Mouse.Header.TimestampTicks = (ulong)Environment.TickCount;
  62. Mouse.Header.NumEntries = (ulong)Hid_Num_Entries;
  63. Mouse.Header.LatestEntry = 0;
  64. Mouse.Header.MaxEntryIndex = (ulong)Hid_Num_Entries - 1;
  65. //TODO: Write this structure when the input is implemented
  66. //Marshal.StructureToPtr(Mouse, HidPtr, false);
  67. InnerOffset += (uint)Marshal.SizeOf(typeof(HidMouse));
  68. HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset);
  69. HidKeyboard Keyboard = new HidKeyboard();
  70. Keyboard.Header.TimestampTicks = (ulong)Environment.TickCount;
  71. Keyboard.Header.NumEntries = (ulong)Hid_Num_Entries;
  72. Keyboard.Header.LatestEntry = 0;
  73. Keyboard.Header.MaxEntryIndex = (ulong)Hid_Num_Entries - 1;
  74. //TODO: Write this structure when the input is implemented
  75. //Marshal.StructureToPtr(Keyboard, HidPtr, false);
  76. InnerOffset += (uint)Marshal.SizeOf(typeof(HidKeyboard)) +
  77. (uint)Marshal.SizeOf(typeof(HidUnknownSection1)) +
  78. (uint)Marshal.SizeOf(typeof(HidUnknownSection2)) +
  79. (uint)Marshal.SizeOf(typeof(HidUnknownSection3)) +
  80. (uint)Marshal.SizeOf(typeof(HidUnknownSection4)) +
  81. (uint)Marshal.SizeOf(typeof(HidUnknownSection5)) +
  82. (uint)Marshal.SizeOf(typeof(HidUnknownSection6)) +
  83. (uint)Marshal.SizeOf(typeof(HidUnknownSection7)) +
  84. (uint)Marshal.SizeOf(typeof(HidUnknownSection8)) +
  85. (uint)Marshal.SizeOf(typeof(HidControllerSerials));
  86. //Increase the loop to initialize more controller.
  87. for (int i = 8; i < Enum.GetNames(typeof(HidControllerID)).Length - 1; i++)
  88. {
  89. HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset + (uint)(Marshal.SizeOf(typeof(HidController)) * i));
  90. HidController Controller = new HidController();
  91. Controller.Header.Type = (uint)(HidControllerType.ControllerType_Handheld | HidControllerType.ControllerType_JoyconPair);
  92. Controller.Header.IsHalf = 0;
  93. Controller.Header.SingleColorsDescriptor = (uint)(HidControllerColorDescription.ColorDesc_ColorsNonexistent);
  94. Controller.Header.SingleColorBody = 0;
  95. Controller.Header.SingleColorButtons = 0;
  96. Controller.Header.SplitColorsDescriptor = 0;
  97. Controller.Header.LeftColorBody = (uint)JoyConColor.Body_Neon_Red;
  98. Controller.Header.LeftColorButtons = (uint)JoyConColor.Buttons_Neon_Red;
  99. Controller.Header.RightColorBody = (uint)JoyConColor.Body_Neon_Blue;
  100. Controller.Header.RightColorButtons = (uint)JoyConColor.Buttons_Neon_Blue;
  101. Controller.Layouts = new HidControllerLayout[Enum.GetNames(typeof(HidControllerLayouts)).Length];
  102. Controller.Layouts[(int)HidControllerLayouts.Main] = new HidControllerLayout();
  103. Controller.Layouts[(int)HidControllerLayouts.Main].Header.LatestEntry = (ulong)Hid_Num_Entries;
  104. Marshal.StructureToPtr(Controller, HidPtr, false);
  105. }
  106. Logging.Info("HID Initialized!");
  107. }
  108. }
  109. public void SendControllerButtons(HidControllerID ControllerId,
  110. HidControllerLayouts Layout,
  111. HidControllerKeys Buttons,
  112. JoystickPosition LeftJoystick,
  113. JoystickPosition RightJoystick)
  114. {
  115. uint InnerOffset = (uint)Marshal.SizeOf(typeof(HidSharedMemHeader)) +
  116. (uint)Marshal.SizeOf(typeof(HidTouchScreen)) +
  117. (uint)Marshal.SizeOf(typeof(HidMouse)) +
  118. (uint)Marshal.SizeOf(typeof(HidKeyboard)) +
  119. (uint)Marshal.SizeOf(typeof(HidUnknownSection1)) +
  120. (uint)Marshal.SizeOf(typeof(HidUnknownSection2)) +
  121. (uint)Marshal.SizeOf(typeof(HidUnknownSection3)) +
  122. (uint)Marshal.SizeOf(typeof(HidUnknownSection4)) +
  123. (uint)Marshal.SizeOf(typeof(HidUnknownSection5)) +
  124. (uint)Marshal.SizeOf(typeof(HidUnknownSection6)) +
  125. (uint)Marshal.SizeOf(typeof(HidUnknownSection7)) +
  126. (uint)Marshal.SizeOf(typeof(HidUnknownSection8)) +
  127. (uint)Marshal.SizeOf(typeof(HidControllerSerials)) +
  128. ((uint)(Marshal.SizeOf(typeof(HidController)) * (int)ControllerId)) +
  129. (uint)Marshal.SizeOf(typeof(HidControllerHeader)) +
  130. (uint)Layout * (uint)Marshal.SizeOf(typeof(HidControllerLayout));
  131. IntPtr HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset);
  132. HidControllerLayoutHeader OldControllerHeaderLayout = (HidControllerLayoutHeader)Marshal.PtrToStructure(HidPtr, typeof(HidControllerLayoutHeader));
  133. HidControllerLayoutHeader ControllerLayoutHeader = new HidControllerLayoutHeader
  134. {
  135. TimestampTicks = (ulong)Environment.TickCount,
  136. NumEntries = (ulong)Hid_Num_Entries,
  137. MaxEntryIndex = (ulong)Hid_Num_Entries - 1,
  138. LatestEntry = (OldControllerHeaderLayout.LatestEntry < (ulong)Hid_Num_Entries ? OldControllerHeaderLayout.LatestEntry + 1 : 0)
  139. };
  140. Marshal.StructureToPtr(ControllerLayoutHeader, HidPtr, false);
  141. InnerOffset += (uint)Marshal.SizeOf(typeof(HidControllerLayoutHeader)) + (uint)((uint)(ControllerLayoutHeader.LatestEntry) * Marshal.SizeOf(typeof(HidControllerInputEntry)));
  142. HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset);
  143. HidControllerInputEntry ControllerInputEntry = new HidControllerInputEntry
  144. {
  145. Timestamp = (ulong)Environment.TickCount,
  146. Timestamp_2 = (ulong)Environment.TickCount,
  147. Buttons = (ulong)Buttons,
  148. Joysticks = new JoystickPosition[(int)HidControllerJoystick.Joystick_Num_Sticks]
  149. };
  150. ControllerInputEntry.Joysticks[(int)HidControllerJoystick.Joystick_Left] = LeftJoystick;
  151. ControllerInputEntry.Joysticks[(int)HidControllerJoystick.Joystick_Right] = RightJoystick;
  152. ControllerInputEntry.ConnectionState = (ulong)(HidControllerConnectionState.Controller_State_Connected | HidControllerConnectionState.Controller_State_Wired);
  153. Marshal.StructureToPtr(ControllerInputEntry, HidPtr, false);
  154. }
  155. public void SendTouchPoint(HidTouchScreenEntryTouch TouchPoint)
  156. {
  157. uint InnerOffset = (uint)Marshal.SizeOf(typeof(HidSharedMemHeader));
  158. IntPtr HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset);
  159. HidTouchScreenHeader OldTouchScreenHeader = (HidTouchScreenHeader)Marshal.PtrToStructure(HidPtr,typeof(HidTouchScreenHeader));
  160. HidTouchScreenHeader TouchScreenHeader = new HidTouchScreenHeader()
  161. {
  162. TimestampTicks = (ulong)Environment.TickCount,
  163. NumEntries = (ulong)Hid_Num_Entries,
  164. MaxEntryIndex = (ulong)Hid_Num_Entries - 1,
  165. Timestamp = (ulong)Environment.TickCount,
  166. LatestEntry = OldTouchScreenHeader.LatestEntry < Hid_Num_Entries-1 ? OldTouchScreenHeader.LatestEntry + 1 : 0
  167. };
  168. Marshal.StructureToPtr(TouchScreenHeader, HidPtr, false);
  169. InnerOffset += (uint)Marshal.SizeOf(typeof(HidTouchScreenHeader))
  170. + (uint)((uint)(OldTouchScreenHeader.LatestEntry) * Marshal.SizeOf(typeof(HidTouchScreenEntry)));
  171. HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset);
  172. HidTouchScreenEntry hidTouchScreenEntry = new HidTouchScreenEntry()
  173. {
  174. Header = new HidTouchScreenEntryHeader()
  175. {
  176. Timestamp = (ulong)Environment.TickCount,
  177. NumTouches = 1
  178. },
  179. Touches = new HidTouchScreenEntryTouch[16]
  180. };
  181. //Only supports single touch
  182. hidTouchScreenEntry.Touches[0] = TouchPoint;
  183. Marshal.StructureToPtr(hidTouchScreenEntry, HidPtr, false);
  184. }
  185. }
  186. }