applet_resource.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-3.0-or-later
  3. #include "core/core.h"
  4. #include "core/hle/kernel/k_shared_memory.h"
  5. #include "hid_core/hid_result.h"
  6. #include "hid_core/resources/applet_resource.h"
  7. #include "hid_core/resources/shared_memory_format.h"
  8. namespace Service::HID {
  9. AppletResource::AppletResource(Core::System& system_) : system{system_} {}
  10. AppletResource::~AppletResource() = default;
  11. Result AppletResource::CreateAppletResource(u64 aruid) {
  12. const u64 index = GetIndexFromAruid(aruid);
  13. if (index >= AruidIndexMax) {
  14. return ResultAruidNotRegistered;
  15. }
  16. if (data[index].flag.is_assigned) {
  17. return ResultAruidAlreadyRegistered;
  18. }
  19. auto& shared_memory = shared_memory_holder[index];
  20. if (!shared_memory.IsMapped()) {
  21. const Result result = shared_memory.Initialize(system);
  22. if (result.IsError()) {
  23. return result;
  24. }
  25. if (shared_memory.GetAddress() == nullptr) {
  26. shared_memory.Finalize();
  27. return ResultSharedMemoryNotInitialized;
  28. }
  29. }
  30. auto* shared_memory_format = shared_memory.GetAddress();
  31. if (shared_memory_format != nullptr) {
  32. shared_memory_format->Initialize();
  33. }
  34. data[index].shared_memory_format = shared_memory_format;
  35. data[index].flag.is_assigned.Assign(true);
  36. // TODO: InitializeSixAxisControllerConfig(false);
  37. active_aruid = aruid;
  38. return ResultSuccess;
  39. }
  40. Result AppletResource::RegisterAppletResourceUserId(u64 aruid, bool enable_input) {
  41. const u64 index = GetIndexFromAruid(aruid);
  42. if (index < AruidIndexMax) {
  43. return ResultAruidAlreadyRegistered;
  44. }
  45. std::size_t data_index = AruidIndexMax;
  46. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  47. if (!data[i].flag.is_initialized) {
  48. data_index = i;
  49. break;
  50. }
  51. }
  52. if (data_index == AruidIndexMax) {
  53. return ResultAruidNoAvailableEntries;
  54. }
  55. AruidData& aruid_data = data[data_index];
  56. aruid_data.aruid = aruid;
  57. aruid_data.flag.is_initialized.Assign(true);
  58. if (enable_input) {
  59. aruid_data.flag.enable_pad_input.Assign(true);
  60. aruid_data.flag.enable_six_axis_sensor.Assign(true);
  61. aruid_data.flag.bit_18.Assign(true);
  62. aruid_data.flag.enable_touchscreen.Assign(true);
  63. }
  64. data_index = AruidIndexMax;
  65. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  66. if (registration_list.flag[i] == RegistrationStatus::Initialized) {
  67. if (registration_list.aruid[i] != aruid) {
  68. continue;
  69. }
  70. data_index = i;
  71. break;
  72. }
  73. // TODO: Don't Handle pending delete here
  74. if (registration_list.flag[i] == RegistrationStatus::None ||
  75. registration_list.flag[i] == RegistrationStatus::PendingDelete) {
  76. data_index = i;
  77. break;
  78. }
  79. }
  80. if (data_index == AruidIndexMax) {
  81. return ResultSuccess;
  82. }
  83. registration_list.flag[data_index] = RegistrationStatus::Initialized;
  84. registration_list.aruid[data_index] = aruid;
  85. return ResultSuccess;
  86. }
  87. void AppletResource::UnregisterAppletResourceUserId(u64 aruid) {
  88. const u64 index = GetIndexFromAruid(aruid);
  89. if (index >= AruidIndexMax) {
  90. return;
  91. }
  92. FreeAppletResourceId(aruid);
  93. DestroySevenSixAxisTransferMemory();
  94. data[index].flag.raw = 0;
  95. data[index].aruid = 0;
  96. registration_list.flag[index] = RegistrationStatus::PendingDelete;
  97. }
  98. void AppletResource::FreeAppletResourceId(u64 aruid) {
  99. const u64 index = GetIndexFromAruid(aruid);
  100. if (index >= AruidIndexMax) {
  101. return;
  102. }
  103. auto& aruid_data = data[index];
  104. if (aruid_data.flag.is_assigned) {
  105. aruid_data.shared_memory_format = nullptr;
  106. aruid_data.flag.is_assigned.Assign(false);
  107. shared_memory_holder[index].Finalize();
  108. }
  109. }
  110. u64 AppletResource::GetActiveAruid() {
  111. return active_aruid;
  112. }
  113. Result AppletResource::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) {
  114. const u64 index = GetIndexFromAruid(aruid);
  115. if (index >= AruidIndexMax) {
  116. return ResultAruidNotRegistered;
  117. }
  118. *out_handle = shared_memory_holder[index].GetHandle();
  119. return ResultSuccess;
  120. }
  121. Result AppletResource::GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format,
  122. u64 aruid) {
  123. const u64 index = GetIndexFromAruid(aruid);
  124. if (index >= AruidIndexMax) {
  125. return ResultAruidNotRegistered;
  126. }
  127. *out_shared_memory_format = data[index].shared_memory_format;
  128. return ResultSuccess;
  129. }
  130. AruidData* AppletResource::GetAruidData(u64 aruid) {
  131. const u64 aruid_index = GetIndexFromAruid(aruid);
  132. if (aruid_index == AruidIndexMax) {
  133. return nullptr;
  134. }
  135. return &data[aruid_index];
  136. }
  137. AruidData* AppletResource::GetAruidDataByIndex(std::size_t aruid_index) {
  138. return &data[aruid_index];
  139. }
  140. bool AppletResource::IsVibrationAruidActive(u64 aruid) const {
  141. return aruid == 0 || aruid == active_vibration_aruid;
  142. }
  143. u64 AppletResource::GetIndexFromAruid(u64 aruid) {
  144. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  145. if (registration_list.flag[i] == RegistrationStatus::Initialized &&
  146. registration_list.aruid[i] == aruid) {
  147. return i;
  148. }
  149. }
  150. return AruidIndexMax;
  151. }
  152. Result AppletResource::DestroySevenSixAxisTransferMemory() {
  153. // TODO
  154. return ResultSuccess;
  155. }
  156. void AppletResource::EnableInput(u64 aruid, bool is_enabled) {
  157. const u64 index = GetIndexFromAruid(aruid);
  158. if (index >= AruidIndexMax) {
  159. return;
  160. }
  161. data[index].flag.enable_pad_input.Assign(is_enabled);
  162. data[index].flag.enable_touchscreen.Assign(is_enabled);
  163. }
  164. void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) {
  165. const u64 index = GetIndexFromAruid(aruid);
  166. if (index >= AruidIndexMax) {
  167. return;
  168. }
  169. data[index].flag.enable_six_axis_sensor.Assign(is_enabled);
  170. }
  171. void AppletResource::EnablePadInput(u64 aruid, bool is_enabled) {
  172. const u64 index = GetIndexFromAruid(aruid);
  173. if (index >= AruidIndexMax) {
  174. return;
  175. }
  176. data[index].flag.enable_pad_input.Assign(is_enabled);
  177. }
  178. void AppletResource::EnableTouchScreen(u64 aruid, bool is_enabled) {
  179. const u64 index = GetIndexFromAruid(aruid);
  180. if (index >= AruidIndexMax) {
  181. return;
  182. }
  183. data[index].flag.enable_touchscreen.Assign(is_enabled);
  184. }
  185. void AppletResource::SetIsPalmaConnectable(u64 aruid, bool is_connectable) {
  186. const u64 index = GetIndexFromAruid(aruid);
  187. if (index >= AruidIndexMax) {
  188. return;
  189. }
  190. data[index].flag.is_palma_connectable.Assign(is_connectable);
  191. }
  192. void AppletResource::EnablePalmaBoostMode(u64 aruid, bool is_enabled) {
  193. const u64 index = GetIndexFromAruid(aruid);
  194. if (index >= AruidIndexMax) {
  195. return;
  196. }
  197. data[index].flag.enable_palma_boost_mode.Assign(is_enabled);
  198. }
  199. Result AppletResource::RegisterCoreAppletResource() {
  200. if (ref_counter == std::numeric_limits<s32>::max() - 1) {
  201. return ResultAppletResourceOverflow;
  202. }
  203. if (ref_counter == 0) {
  204. const u64 index = GetIndexFromAruid(0);
  205. if (index < AruidIndexMax) {
  206. return ResultAruidAlreadyRegistered;
  207. }
  208. std::size_t data_index = AruidIndexMax;
  209. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  210. if (!data[i].flag.is_initialized) {
  211. data_index = i;
  212. break;
  213. }
  214. }
  215. if (data_index == AruidIndexMax) {
  216. return ResultAruidNoAvailableEntries;
  217. }
  218. AruidData& aruid_data = data[data_index];
  219. aruid_data.aruid = 0;
  220. aruid_data.flag.is_initialized.Assign(true);
  221. aruid_data.flag.enable_pad_input.Assign(true);
  222. aruid_data.flag.enable_six_axis_sensor.Assign(true);
  223. aruid_data.flag.bit_18.Assign(true);
  224. aruid_data.flag.enable_touchscreen.Assign(true);
  225. data_index = AruidIndexMax;
  226. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  227. if (registration_list.flag[i] == RegistrationStatus::Initialized) {
  228. if (registration_list.aruid[i] != 0) {
  229. continue;
  230. }
  231. data_index = i;
  232. break;
  233. }
  234. if (registration_list.flag[i] == RegistrationStatus::None) {
  235. data_index = i;
  236. break;
  237. }
  238. }
  239. Result result = ResultSuccess;
  240. if (data_index == AruidIndexMax) {
  241. result = CreateAppletResource(0);
  242. } else {
  243. registration_list.flag[data_index] = RegistrationStatus::Initialized;
  244. registration_list.aruid[data_index] = 0;
  245. }
  246. if (result.IsError()) {
  247. UnregisterAppletResourceUserId(0);
  248. return result;
  249. }
  250. }
  251. ref_counter++;
  252. return ResultSuccess;
  253. }
  254. Result AppletResource::UnregisterCoreAppletResource() {
  255. if (ref_counter == 0) {
  256. return ResultAppletResourceNotInitialized;
  257. }
  258. if (--ref_counter == 0) {
  259. UnregisterAppletResourceUserId(0);
  260. }
  261. return ResultSuccess;
  262. }
  263. } // namespace Service::HID