hidbus.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/logging/log.h"
  4. #include "common/settings.h"
  5. #include "core/core.h"
  6. #include "core/core_timing.h"
  7. #include "core/hle/kernel/k_event.h"
  8. #include "core/hle/kernel/k_readable_event.h"
  9. #include "core/hle/kernel/k_shared_memory.h"
  10. #include "core/hle/kernel/k_transfer_memory.h"
  11. #include "core/hle/service/cmif_serialization.h"
  12. #include "core/hle/service/hid/hidbus.h"
  13. #include "core/hle/service/ipc_helpers.h"
  14. #include "core/hle/service/service.h"
  15. #include "core/memory.h"
  16. #include "hid_core/hid_types.h"
  17. #include "hid_core/hidbus/ringcon.h"
  18. #include "hid_core/hidbus/starlink.h"
  19. #include "hid_core/hidbus/stubbed.h"
  20. namespace Service::HID {
  21. // (15ms, 66Hz)
  22. constexpr auto hidbus_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000};
  23. Hidbus::Hidbus(Core::System& system_)
  24. : ServiceFramework{system_, "hidbus"}, service_context{system_, service_name} {
  25. // clang-format off
  26. static const FunctionInfo functions[] = {
  27. {1, C<&Hidbus::GetBusHandle>, "GetBusHandle"},
  28. {2, C<&Hidbus::IsExternalDeviceConnected>, "IsExternalDeviceConnected"},
  29. {3, C<&Hidbus::Initialize>, "Initialize"},
  30. {4, C<&Hidbus::Finalize>, "Finalize"},
  31. {5, C<&Hidbus::EnableExternalDevice>, "EnableExternalDevice"},
  32. {6, C<&Hidbus::GetExternalDeviceId>, "GetExternalDeviceId"},
  33. {7, C<&Hidbus::SendCommandAsync>, "SendCommandAsync"},
  34. {8, C<&Hidbus::GetSendCommandAsynceResult>, "GetSendCommandAsynceResult"},
  35. {9, C<&Hidbus::SetEventForSendCommandAsycResult>, "SetEventForSendCommandAsycResult"},
  36. {10, C<&Hidbus::GetSharedMemoryHandle>, "GetSharedMemoryHandle"},
  37. {11, C<&Hidbus::EnableJoyPollingReceiveMode>, "EnableJoyPollingReceiveMode"},
  38. {12, C<&Hidbus::DisableJoyPollingReceiveMode>, "DisableJoyPollingReceiveMode"},
  39. {13, nullptr, "GetPollingData"},
  40. {14, C<&Hidbus::SetStatusManagerType>, "SetStatusManagerType"},
  41. };
  42. // clang-format on
  43. RegisterHandlers(functions);
  44. // Register update callbacks
  45. hidbus_update_event = Core::Timing::CreateEvent(
  46. "Hidbus::UpdateCallback",
  47. [this](s64 time,
  48. std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
  49. const auto guard = LockService();
  50. UpdateHidbus(ns_late);
  51. return std::nullopt;
  52. });
  53. system_.CoreTiming().ScheduleLoopingEvent(hidbus_update_ns, hidbus_update_ns,
  54. hidbus_update_event);
  55. }
  56. Hidbus::~Hidbus() {
  57. system.CoreTiming().UnscheduleEvent(hidbus_update_event);
  58. }
  59. void Hidbus::UpdateHidbus(std::chrono::nanoseconds ns_late) {
  60. if (is_hidbus_enabled) {
  61. for (std::size_t i = 0; i < devices.size(); ++i) {
  62. if (!devices[i].is_device_initialized) {
  63. continue;
  64. }
  65. auto& device = devices[i].device;
  66. device->OnUpdate();
  67. auto& cur_entry = hidbus_status.entries[devices[i].handle.internal_index];
  68. cur_entry.is_polling_mode = device->IsPollingMode();
  69. cur_entry.polling_mode = device->GetPollingMode();
  70. cur_entry.is_enabled = device->IsEnabled();
  71. u8* shared_memory = system.Kernel().GetHidBusSharedMem().GetPointer();
  72. std::memcpy(shared_memory + (i * sizeof(HidbusStatusManagerEntry)), &hidbus_status,
  73. sizeof(HidbusStatusManagerEntry));
  74. }
  75. }
  76. }
  77. std::optional<std::size_t> Hidbus::GetDeviceIndexFromHandle(BusHandle handle) const {
  78. for (std::size_t i = 0; i < devices.size(); ++i) {
  79. const auto& device_handle = devices[i].handle;
  80. if (handle.abstracted_pad_id == device_handle.abstracted_pad_id &&
  81. handle.internal_index == device_handle.internal_index &&
  82. handle.player_number == device_handle.player_number &&
  83. handle.bus_type_id == device_handle.bus_type_id &&
  84. handle.is_valid == device_handle.is_valid) {
  85. return i;
  86. }
  87. }
  88. return std::nullopt;
  89. }
  90. Result Hidbus::GetBusHandle(Out<bool> out_is_valid, Out<BusHandle> out_bus_handle,
  91. Core::HID::NpadIdType npad_id, BusType bus_type,
  92. AppletResourceUserId aruid) {
  93. LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}", npad_id,
  94. bus_type, aruid.pid);
  95. bool is_handle_found = 0;
  96. std::size_t handle_index = 0;
  97. for (std::size_t i = 0; i < devices.size(); i++) {
  98. const auto& handle = devices[i].handle;
  99. if (!handle.is_valid) {
  100. continue;
  101. }
  102. if (handle.player_number.As<Core::HID::NpadIdType>() == npad_id &&
  103. handle.bus_type_id == static_cast<u8>(bus_type)) {
  104. is_handle_found = true;
  105. handle_index = i;
  106. break;
  107. }
  108. }
  109. // Handle not found. Create a new one
  110. if (!is_handle_found) {
  111. for (std::size_t i = 0; i < devices.size(); i++) {
  112. if (devices[i].handle.is_valid) {
  113. continue;
  114. }
  115. devices[i].handle.raw = 0;
  116. devices[i].handle.abstracted_pad_id.Assign(i);
  117. devices[i].handle.internal_index.Assign(i);
  118. devices[i].handle.player_number.Assign(static_cast<u8>(npad_id));
  119. devices[i].handle.bus_type_id.Assign(static_cast<u8>(bus_type));
  120. devices[i].handle.is_valid.Assign(true);
  121. handle_index = i;
  122. break;
  123. }
  124. }
  125. *out_is_valid = true;
  126. *out_bus_handle = devices[handle_index].handle;
  127. R_SUCCEED();
  128. }
  129. Result Hidbus::IsExternalDeviceConnected(Out<bool> out_is_connected, BusHandle bus_handle) {
  130. LOG_INFO(Service_HID,
  131. "Called, abstracted_pad_id={}, bus_type={}, internal_index={}, "
  132. "player_number={}, is_valid={}",
  133. bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
  134. bus_handle.player_number, bus_handle.is_valid);
  135. const auto device_index = GetDeviceIndexFromHandle(bus_handle);
  136. R_UNLESS(device_index.has_value(), ResultUnknown);
  137. *out_is_connected = devices[device_index.value()].device->IsDeviceActivated();
  138. R_SUCCEED();
  139. }
  140. Result Hidbus::Initialize(BusHandle bus_handle, AppletResourceUserId aruid) {
  141. LOG_INFO(Service_HID,
  142. "called, abstracted_pad_id={} bus_type={} internal_index={} "
  143. "player_number={} is_valid={}, applet_resource_user_id={}",
  144. bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
  145. bus_handle.player_number, bus_handle.is_valid, aruid.pid);
  146. is_hidbus_enabled = true;
  147. const auto device_index = GetDeviceIndexFromHandle(bus_handle);
  148. R_UNLESS(device_index.has_value(), ResultUnknown);
  149. const auto entry_index = devices[device_index.value()].handle.internal_index;
  150. auto& cur_entry = hidbus_status.entries[entry_index];
  151. if (bus_handle.internal_index == 0 && Settings::values.enable_ring_controller) {
  152. MakeDevice<RingController>(bus_handle);
  153. devices[device_index.value()].is_device_initialized = true;
  154. devices[device_index.value()].device->ActivateDevice();
  155. cur_entry.is_in_focus = true;
  156. cur_entry.is_connected = true;
  157. cur_entry.is_connected_result = ResultSuccess;
  158. cur_entry.is_enabled = false;
  159. cur_entry.is_polling_mode = false;
  160. } else {
  161. MakeDevice<HidbusStubbed>(bus_handle);
  162. devices[device_index.value()].is_device_initialized = true;
  163. cur_entry.is_in_focus = true;
  164. cur_entry.is_connected = false;
  165. cur_entry.is_connected_result = ResultSuccess;
  166. cur_entry.is_enabled = false;
  167. cur_entry.is_polling_mode = false;
  168. }
  169. std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
  170. sizeof(hidbus_status));
  171. R_SUCCEED();
  172. }
  173. Result Hidbus::Finalize(BusHandle bus_handle, AppletResourceUserId aruid) {
  174. LOG_INFO(Service_HID,
  175. "called, abstracted_pad_id={}, bus_type={}, internal_index={}, "
  176. "player_number={}, is_valid={}, applet_resource_user_id={}",
  177. bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
  178. bus_handle.player_number, bus_handle.is_valid, aruid.pid);
  179. const auto device_index = GetDeviceIndexFromHandle(bus_handle);
  180. R_UNLESS(device_index.has_value(), ResultUnknown);
  181. const auto entry_index = devices[device_index.value()].handle.internal_index;
  182. auto& cur_entry = hidbus_status.entries[entry_index];
  183. auto& device = devices[device_index.value()].device;
  184. devices[device_index.value()].is_device_initialized = false;
  185. device->DeactivateDevice();
  186. cur_entry.is_in_focus = true;
  187. cur_entry.is_connected = false;
  188. cur_entry.is_connected_result = ResultSuccess;
  189. cur_entry.is_enabled = false;
  190. cur_entry.is_polling_mode = false;
  191. std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status,
  192. sizeof(hidbus_status));
  193. R_SUCCEED();
  194. }
  195. Result Hidbus::EnableExternalDevice(bool is_enabled, BusHandle bus_handle, u64 inval,
  196. AppletResourceUserId aruid) {
  197. LOG_DEBUG(Service_HID,
  198. "called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, "
  199. "player_number={}, is_valid={}, inval={}, applet_resource_user_id{}",
  200. is_enabled, bus_handle.abstracted_pad_id, bus_handle.bus_type_id,
  201. bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid, inval,
  202. aruid.pid);
  203. const auto device_index = GetDeviceIndexFromHandle(bus_handle);
  204. R_UNLESS(device_index.has_value(), ResultUnknown);
  205. devices[device_index.value()].device->Enable(is_enabled);
  206. R_SUCCEED();
  207. }
  208. Result Hidbus::GetExternalDeviceId(Out<u32> out_device_id, BusHandle bus_handle) {
  209. LOG_DEBUG(Service_HID,
  210. "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
  211. "is_valid={}",
  212. bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
  213. bus_handle.player_number, bus_handle.is_valid);
  214. const auto device_index = GetDeviceIndexFromHandle(bus_handle);
  215. R_UNLESS(device_index.has_value(), ResultUnknown);
  216. *out_device_id = devices[device_index.value()].device->GetDeviceId();
  217. R_SUCCEED();
  218. }
  219. Result Hidbus::SendCommandAsync(BusHandle bus_handle,
  220. InBuffer<BufferAttr_HipcAutoSelect> buffer_data) {
  221. LOG_DEBUG(Service_HID,
  222. "called, data_size={}, abstracted_pad_id={}, bus_type={}, internal_index={}, "
  223. "player_number={}, is_valid={}",
  224. buffer_data.size(), bus_handle.abstracted_pad_id, bus_handle.bus_type_id,
  225. bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid);
  226. const auto device_index = GetDeviceIndexFromHandle(bus_handle);
  227. R_UNLESS(device_index.has_value(), ResultUnknown);
  228. devices[device_index.value()].device->SetCommand(buffer_data);
  229. R_SUCCEED();
  230. };
  231. Result Hidbus::GetSendCommandAsynceResult(Out<u64> out_data_size, BusHandle bus_handle,
  232. OutBuffer<BufferAttr_HipcAutoSelect> out_buffer_data) {
  233. LOG_DEBUG(Service_HID,
  234. "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
  235. "is_valid={}",
  236. bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
  237. bus_handle.player_number, bus_handle.is_valid);
  238. const auto device_index = GetDeviceIndexFromHandle(bus_handle);
  239. R_UNLESS(device_index.has_value(), ResultUnknown);
  240. *out_data_size = devices[device_index.value()].device->GetReply(out_buffer_data);
  241. R_SUCCEED();
  242. };
  243. Result Hidbus::SetEventForSendCommandAsycResult(OutCopyHandle<Kernel::KReadableEvent> out_event,
  244. BusHandle bus_handle) {
  245. LOG_INFO(Service_HID,
  246. "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
  247. "is_valid={}",
  248. bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
  249. bus_handle.player_number, bus_handle.is_valid);
  250. const auto device_index = GetDeviceIndexFromHandle(bus_handle);
  251. R_UNLESS(device_index.has_value(), ResultUnknown);
  252. *out_event = &devices[device_index.value()].device->GetSendCommandAsycEvent();
  253. R_SUCCEED();
  254. };
  255. Result Hidbus::GetSharedMemoryHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
  256. LOG_DEBUG(Service_HID, "called");
  257. *out_shared_memory = &system.Kernel().GetHidBusSharedMem();
  258. R_SUCCEED();
  259. }
  260. Result Hidbus::EnableJoyPollingReceiveMode(u32 t_mem_size, JoyPollingMode polling_mode,
  261. BusHandle bus_handle,
  262. InCopyHandle<Kernel::KTransferMemory> t_mem) {
  263. ASSERT_MSG(t_mem_size == 0x1000, "t_mem_size is not 0x1000 bytes");
  264. ASSERT_MSG(t_mem->GetSize() == t_mem_size, "t_mem has incorrect size");
  265. LOG_INFO(Service_HID,
  266. "called, polling_mode={}, abstracted_pad_id={}, bus_type={}, "
  267. "internal_index={}, player_number={}, is_valid={}",
  268. polling_mode, bus_handle.abstracted_pad_id, bus_handle.bus_type_id,
  269. bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid);
  270. const auto device_index = GetDeviceIndexFromHandle(bus_handle);
  271. R_UNLESS(device_index.has_value(), ResultUnknown);
  272. auto& device = devices[device_index.value()].device;
  273. device->SetPollingMode(polling_mode);
  274. device->SetTransferMemoryAddress(t_mem->GetSourceAddress());
  275. R_SUCCEED();
  276. }
  277. Result Hidbus::DisableJoyPollingReceiveMode(BusHandle bus_handle) {
  278. LOG_INFO(Service_HID,
  279. "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
  280. "is_valid={}",
  281. bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index,
  282. bus_handle.player_number, bus_handle.is_valid);
  283. const auto device_index = GetDeviceIndexFromHandle(bus_handle);
  284. R_UNLESS(device_index.has_value(), ResultUnknown);
  285. auto& device = devices[device_index.value()].device;
  286. device->DisablePollingMode();
  287. R_SUCCEED();
  288. }
  289. Result Hidbus::SetStatusManagerType(StatusManagerType manager_type) {
  290. LOG_WARNING(Service_HID, "(STUBBED) called, manager_type={}", manager_type);
  291. R_SUCCEED();
  292. };
  293. } // namespace Service::HID