nintendo_data_fetcher.cc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "device/gamepad/nintendo_data_fetcher.h"
  5. #include "base/bind.h"
  6. #include "base/callback_helpers.h"
  7. #include "device/gamepad/gamepad_service.h"
  8. #include "device/gamepad/gamepad_uma.h"
  9. namespace device {
  10. NintendoDataFetcher::NintendoDataFetcher() = default;
  11. NintendoDataFetcher::~NintendoDataFetcher() {
  12. for (auto& entry : controllers_) {
  13. auto& device = *entry.second;
  14. device.Shutdown();
  15. }
  16. }
  17. GamepadSource NintendoDataFetcher::source() {
  18. return Factory::static_source();
  19. }
  20. void NintendoDataFetcher::OnAddedToProvider() {
  21. // Open a connection to the HID service. On a successful connection,
  22. // OnGetDevices will be called with a list of connected HID devices.
  23. BindHidManager(hid_manager_.BindNewPipeAndPassReceiver());
  24. hid_manager_->GetDevicesAndSetClient(
  25. receiver_.BindNewEndpointAndPassRemote(),
  26. base::BindOnce(&NintendoDataFetcher::OnGetDevices,
  27. weak_factory_.GetWeakPtr()));
  28. }
  29. void NintendoDataFetcher::OnGetDevices(
  30. std::vector<mojom::HidDeviceInfoPtr> device_infos) {
  31. for (auto& device_info : device_infos)
  32. DeviceAdded(std::move(device_info));
  33. }
  34. void NintendoDataFetcher::OnDeviceReady(int source_id) {
  35. auto find_it = controllers_.find(source_id);
  36. if (find_it == controllers_.end())
  37. return;
  38. const auto* ready_device_ptr = find_it->second.get();
  39. DCHECK(ready_device_ptr);
  40. if (ready_device_ptr->IsComposite())
  41. return;
  42. // Extract a connected device that can be associated with the newly-connected
  43. // device, if it exists.
  44. std::unique_ptr<NintendoController> associated_device =
  45. ExtractAssociatedDevice(ready_device_ptr);
  46. if (associated_device) {
  47. // Extract the newly-ready device from |controllers_|.
  48. auto ready_device = std::move(find_it->second);
  49. controllers_.erase(source_id);
  50. // Create a composite gamepad from the newly-ready device and the associated
  51. // device. Each device provides button and axis state for half of the
  52. // gamepad and vibration effects are split between them.
  53. int composite_source_id = next_source_id_++;
  54. auto emplace_result = controllers_.emplace(
  55. composite_source_id,
  56. NintendoController::CreateComposite(
  57. composite_source_id, std::move(associated_device),
  58. std::move(ready_device), hid_manager_.get()));
  59. if (emplace_result.second) {
  60. auto& composite_gamepad = emplace_result.first->second;
  61. DCHECK(composite_gamepad);
  62. composite_gamepad->Open(
  63. base::BindOnce(&NintendoDataFetcher::OnDeviceReady,
  64. weak_factory_.GetWeakPtr(), composite_source_id));
  65. }
  66. }
  67. }
  68. void NintendoDataFetcher::DeviceAdded(mojom::HidDeviceInfoPtr device_info) {
  69. GamepadId gamepad_id = GamepadIdList::Get().GetGamepadId(
  70. device_info->product_name, device_info->vendor_id,
  71. device_info->product_id);
  72. if (NintendoController::IsNintendoController(gamepad_id)) {
  73. AddDevice(std::move(device_info));
  74. }
  75. }
  76. void NintendoDataFetcher::DeviceRemoved(mojom::HidDeviceInfoPtr device_info) {
  77. GamepadId gamepad_id = GamepadIdList::Get().GetGamepadId(
  78. device_info->product_name, device_info->vendor_id,
  79. device_info->product_id);
  80. if (NintendoController::IsNintendoController(gamepad_id)) {
  81. RemoveDevice(device_info->guid);
  82. }
  83. }
  84. void NintendoDataFetcher::DeviceChanged(mojom::HidDeviceInfoPtr device_info) {
  85. // Ignore updated device info. NintendoController will retain the old
  86. // HidDeviceInfo. This is fine since it does not rely on any HidDeviceInfo
  87. // members that could change.
  88. }
  89. bool NintendoDataFetcher::AddDevice(mojom::HidDeviceInfoPtr device_info) {
  90. DCHECK(hid_manager_);
  91. GamepadId gamepad_id = GamepadIdList::Get().GetGamepadId(
  92. device_info->product_name, device_info->vendor_id,
  93. device_info->product_id);
  94. RecordConnectedGamepad(gamepad_id);
  95. int source_id = next_source_id_++;
  96. auto emplace_result = controllers_.emplace(
  97. source_id, NintendoController::Create(source_id, std::move(device_info),
  98. hid_manager_.get()));
  99. if (emplace_result.second) {
  100. auto& new_device = emplace_result.first->second;
  101. DCHECK(new_device);
  102. new_device->Open(base::BindOnce(&NintendoDataFetcher::OnDeviceReady,
  103. weak_factory_.GetWeakPtr(), source_id));
  104. return true;
  105. }
  106. return false;
  107. }
  108. bool NintendoDataFetcher::RemoveDevice(const std::string& guid) {
  109. for (auto& entry : controllers_) {
  110. auto& match_device = entry.second;
  111. if (match_device->HasGuid(guid)) {
  112. if (match_device->IsComposite()) {
  113. // Decompose the composite device and return the remaining subdevice to
  114. // |controllers_|.
  115. auto decomposed_devices = match_device->Decompose();
  116. match_device->Shutdown();
  117. controllers_.erase(entry.first);
  118. for (auto& device : decomposed_devices) {
  119. if (device->HasGuid(guid)) {
  120. device->Shutdown();
  121. } else {
  122. int source_id = device->GetSourceId();
  123. controllers_.emplace(source_id, std::move(device));
  124. }
  125. }
  126. } else {
  127. match_device->Shutdown();
  128. controllers_.erase(entry.first);
  129. }
  130. return true;
  131. }
  132. }
  133. return false;
  134. }
  135. std::unique_ptr<NintendoController>
  136. NintendoDataFetcher::ExtractAssociatedDevice(const NintendoController* device) {
  137. DCHECK(device);
  138. std::unique_ptr<NintendoController> associated_device;
  139. GamepadHand device_hand = device->GetGamepadHand();
  140. if (device_hand != GamepadHand::kNone) {
  141. GamepadHand target_hand = (device_hand == GamepadHand::kLeft)
  142. ? GamepadHand::kRight
  143. : GamepadHand::kLeft;
  144. for (auto& entry : controllers_) {
  145. auto& match_device = entry.second;
  146. if (match_device->IsOpen() &&
  147. match_device->GetGamepadHand() == target_hand &&
  148. match_device->GetBusType() == device->GetBusType()) {
  149. associated_device = std::move(match_device);
  150. controllers_.erase(entry.first);
  151. break;
  152. }
  153. }
  154. }
  155. // Set the PadState source back to the default to signal that the slot
  156. // occupied by the associated device is no longer in use.
  157. if (associated_device) {
  158. PadState* state = GetPadState(associated_device->GetSourceId());
  159. if (state)
  160. state->source = GAMEPAD_SOURCE_NONE;
  161. }
  162. return associated_device;
  163. }
  164. void NintendoDataFetcher::GetGamepadData(bool) {
  165. for (auto& entry : controllers_) {
  166. auto& device = entry.second;
  167. if (device->IsOpen() && device->IsUsable()) {
  168. PadState* state = GetPadState(device->GetSourceId());
  169. if (!state)
  170. continue;
  171. if (!state->is_initialized) {
  172. state->mapper = device->GetMappingFunction();
  173. device->InitializeGamepadState(state->mapper != nullptr, state->data);
  174. state->is_initialized = true;
  175. }
  176. device->UpdateGamepadState(state->data);
  177. }
  178. }
  179. }
  180. NintendoController* NintendoDataFetcher::GetControllerFromGuid(
  181. const std::string& guid) {
  182. for (auto& entry : controllers_) {
  183. auto& device = entry.second;
  184. if (device->HasGuid(guid))
  185. return device.get();
  186. }
  187. return nullptr;
  188. }
  189. NintendoController* NintendoDataFetcher::GetControllerFromSourceId(
  190. int source_id) {
  191. auto find_it = controllers_.find(source_id);
  192. return find_it == controllers_.end() ? nullptr : find_it->second.get();
  193. }
  194. void NintendoDataFetcher::PlayEffect(
  195. int source_id,
  196. mojom::GamepadHapticEffectType type,
  197. mojom::GamepadEffectParametersPtr params,
  198. mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback callback,
  199. scoped_refptr<base::SequencedTaskRunner> callback_runner) {
  200. auto* controller = GetControllerFromSourceId(source_id);
  201. if (!controller || !controller->IsOpen()) {
  202. RunVibrationCallback(
  203. std::move(callback), std::move(callback_runner),
  204. mojom::GamepadHapticsResult::GamepadHapticsResultError);
  205. return;
  206. }
  207. controller->PlayEffect(type, std::move(params), std::move(callback),
  208. std::move(callback_runner));
  209. }
  210. void NintendoDataFetcher::ResetVibration(
  211. int source_id,
  212. mojom::GamepadHapticsManager::ResetVibrationActuatorCallback callback,
  213. scoped_refptr<base::SequencedTaskRunner> callback_runner) {
  214. auto* controller = GetControllerFromSourceId(source_id);
  215. if (!controller || !controller->IsOpen()) {
  216. RunVibrationCallback(
  217. std::move(callback), std::move(callback_runner),
  218. mojom::GamepadHapticsResult::GamepadHapticsResultError);
  219. return;
  220. }
  221. controller->ResetVibration(std::move(callback), std::move(callback_runner));
  222. }
  223. } // namespace device