applet_resource.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  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. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  98. if (registration_list.flag[i] == RegistrationStatus::Initialized) {
  99. active_aruid = registration_list.aruid[i];
  100. }
  101. }
  102. }
  103. void AppletResource::FreeAppletResourceId(u64 aruid) {
  104. const u64 index = GetIndexFromAruid(aruid);
  105. if (index >= AruidIndexMax) {
  106. return;
  107. }
  108. auto& aruid_data = data[index];
  109. if (aruid_data.flag.is_assigned) {
  110. aruid_data.shared_memory_format = nullptr;
  111. aruid_data.flag.is_assigned.Assign(false);
  112. shared_memory_holder[index].Finalize();
  113. }
  114. }
  115. u64 AppletResource::GetActiveAruid() {
  116. return active_aruid;
  117. }
  118. Result AppletResource::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) {
  119. const u64 index = GetIndexFromAruid(aruid);
  120. if (index >= AruidIndexMax) {
  121. return ResultAruidNotRegistered;
  122. }
  123. *out_handle = shared_memory_holder[index].GetHandle();
  124. return ResultSuccess;
  125. }
  126. Result AppletResource::GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format,
  127. u64 aruid) {
  128. const u64 index = GetIndexFromAruid(aruid);
  129. if (index >= AruidIndexMax) {
  130. return ResultAruidNotRegistered;
  131. }
  132. *out_shared_memory_format = data[index].shared_memory_format;
  133. return ResultSuccess;
  134. }
  135. AruidData* AppletResource::GetAruidData(u64 aruid) {
  136. const u64 aruid_index = GetIndexFromAruid(aruid);
  137. if (aruid_index == AruidIndexMax) {
  138. return nullptr;
  139. }
  140. return &data[aruid_index];
  141. }
  142. AruidData* AppletResource::GetAruidDataByIndex(std::size_t aruid_index) {
  143. return &data[aruid_index];
  144. }
  145. bool AppletResource::IsVibrationAruidActive(u64 aruid) const {
  146. return aruid == 0 || aruid == active_vibration_aruid;
  147. }
  148. u64 AppletResource::GetIndexFromAruid(u64 aruid) {
  149. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  150. if (registration_list.flag[i] == RegistrationStatus::Initialized &&
  151. registration_list.aruid[i] == aruid) {
  152. return i;
  153. }
  154. }
  155. return AruidIndexMax;
  156. }
  157. Result AppletResource::DestroySevenSixAxisTransferMemory() {
  158. // TODO
  159. return ResultSuccess;
  160. }
  161. void AppletResource::EnableInput(u64 aruid, bool is_enabled) {
  162. const u64 index = GetIndexFromAruid(aruid);
  163. if (index >= AruidIndexMax) {
  164. return;
  165. }
  166. data[index].flag.enable_pad_input.Assign(is_enabled);
  167. data[index].flag.enable_touchscreen.Assign(is_enabled);
  168. }
  169. bool AppletResource::SetAruidValidForVibration(u64 aruid, bool is_enabled) {
  170. const u64 index = GetIndexFromAruid(aruid);
  171. if (index >= AruidIndexMax) {
  172. return false;
  173. }
  174. if (!is_enabled && aruid == active_vibration_aruid) {
  175. active_vibration_aruid = SystemAruid;
  176. return true;
  177. }
  178. if (is_enabled && aruid != active_vibration_aruid) {
  179. active_vibration_aruid = aruid;
  180. return true;
  181. }
  182. return false;
  183. }
  184. void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) {
  185. const u64 index = GetIndexFromAruid(aruid);
  186. if (index >= AruidIndexMax) {
  187. return;
  188. }
  189. data[index].flag.enable_six_axis_sensor.Assign(is_enabled);
  190. }
  191. void AppletResource::EnablePadInput(u64 aruid, bool is_enabled) {
  192. const u64 index = GetIndexFromAruid(aruid);
  193. if (index >= AruidIndexMax) {
  194. return;
  195. }
  196. data[index].flag.enable_pad_input.Assign(is_enabled);
  197. }
  198. void AppletResource::EnableTouchScreen(u64 aruid, bool is_enabled) {
  199. const u64 index = GetIndexFromAruid(aruid);
  200. if (index >= AruidIndexMax) {
  201. return;
  202. }
  203. data[index].flag.enable_touchscreen.Assign(is_enabled);
  204. }
  205. void AppletResource::SetIsPalmaConnectable(u64 aruid, bool is_connectable) {
  206. const u64 index = GetIndexFromAruid(aruid);
  207. if (index >= AruidIndexMax) {
  208. return;
  209. }
  210. data[index].flag.is_palma_connectable.Assign(is_connectable);
  211. }
  212. void AppletResource::EnablePalmaBoostMode(u64 aruid, bool is_enabled) {
  213. const u64 index = GetIndexFromAruid(aruid);
  214. if (index >= AruidIndexMax) {
  215. return;
  216. }
  217. data[index].flag.enable_palma_boost_mode.Assign(is_enabled);
  218. }
  219. Result AppletResource::RegisterCoreAppletResource() {
  220. if (ref_counter == std::numeric_limits<s32>::max() - 1) {
  221. return ResultAppletResourceOverflow;
  222. }
  223. if (ref_counter == 0) {
  224. const u64 index = GetIndexFromAruid(0);
  225. if (index < AruidIndexMax) {
  226. return ResultAruidAlreadyRegistered;
  227. }
  228. std::size_t data_index = AruidIndexMax;
  229. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  230. if (!data[i].flag.is_initialized) {
  231. data_index = i;
  232. break;
  233. }
  234. }
  235. if (data_index == AruidIndexMax) {
  236. return ResultAruidNoAvailableEntries;
  237. }
  238. AruidData& aruid_data = data[data_index];
  239. aruid_data.aruid = 0;
  240. aruid_data.flag.is_initialized.Assign(true);
  241. aruid_data.flag.enable_pad_input.Assign(true);
  242. aruid_data.flag.enable_six_axis_sensor.Assign(true);
  243. aruid_data.flag.bit_18.Assign(true);
  244. aruid_data.flag.enable_touchscreen.Assign(true);
  245. data_index = AruidIndexMax;
  246. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  247. if (registration_list.flag[i] == RegistrationStatus::Initialized) {
  248. if (registration_list.aruid[i] != 0) {
  249. continue;
  250. }
  251. data_index = i;
  252. break;
  253. }
  254. if (registration_list.flag[i] == RegistrationStatus::None) {
  255. data_index = i;
  256. break;
  257. }
  258. }
  259. Result result = ResultSuccess;
  260. if (data_index == AruidIndexMax) {
  261. result = CreateAppletResource(0);
  262. } else {
  263. registration_list.flag[data_index] = RegistrationStatus::Initialized;
  264. registration_list.aruid[data_index] = 0;
  265. }
  266. if (result.IsError()) {
  267. UnregisterAppletResourceUserId(0);
  268. return result;
  269. }
  270. }
  271. ref_counter++;
  272. return ResultSuccess;
  273. }
  274. Result AppletResource::UnregisterCoreAppletResource() {
  275. if (ref_counter == 0) {
  276. return ResultAppletResourceNotInitialized;
  277. }
  278. if (--ref_counter == 0) {
  279. UnregisterAppletResourceUserId(0);
  280. }
  281. return ResultSuccess;
  282. }
  283. } // namespace Service::HID