mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Merge pull request #3304 from wwylele/hid-new-framework
HID: convert to ServiceFramework
This commit is contained in:
		
						commit
						a66e4585a0
					
				
					 7 changed files with 260 additions and 258 deletions
				
			
		|  | @ -3,15 +3,12 @@ | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <atomic> |  | ||||||
| #include <cmath> | #include <cmath> | ||||||
| #include <memory> |  | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/3ds.h" | #include "core/3ds.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/frontend/input.h" | #include "core/hle/ipc_helpers.h" | ||||||
| #include "core/hle/ipc.h" |  | ||||||
| #include "core/hle/kernel/event.h" | #include "core/hle/kernel/event.h" | ||||||
| #include "core/hle/kernel/handle_table.h" | #include "core/hle/kernel/handle_table.h" | ||||||
| #include "core/hle/kernel/shared_memory.h" | #include "core/hle/kernel/shared_memory.h" | ||||||
|  | @ -23,27 +20,7 @@ | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace HID { | namespace HID { | ||||||
| 
 | 
 | ||||||
| // Handle to shared memory region designated to HID_User service
 | static std::weak_ptr<Module> current_module; | ||||||
| static Kernel::SharedPtr<Kernel::SharedMemory> shared_mem; |  | ||||||
| 
 |  | ||||||
| // Event handles
 |  | ||||||
| static Kernel::SharedPtr<Kernel::Event> event_pad_or_touch_1; |  | ||||||
| static Kernel::SharedPtr<Kernel::Event> event_pad_or_touch_2; |  | ||||||
| static Kernel::SharedPtr<Kernel::Event> event_accelerometer; |  | ||||||
| static Kernel::SharedPtr<Kernel::Event> event_gyroscope; |  | ||||||
| static Kernel::SharedPtr<Kernel::Event> event_debug_pad; |  | ||||||
| 
 |  | ||||||
| static u32 next_pad_index; |  | ||||||
| static u32 next_touch_index; |  | ||||||
| static u32 next_accelerometer_index; |  | ||||||
| static u32 next_gyroscope_index; |  | ||||||
| 
 |  | ||||||
| static int enable_accelerometer_count; // positive means enabled
 |  | ||||||
| static int enable_gyroscope_count;     // positive means enabled
 |  | ||||||
| 
 |  | ||||||
| static CoreTiming::EventType* pad_update_event; |  | ||||||
| static CoreTiming::EventType* accelerometer_update_event; |  | ||||||
| static CoreTiming::EventType* gyroscope_update_event; |  | ||||||
| 
 | 
 | ||||||
| // Updating period for each HID device. These empirical values are measured from a 11.2 3DS.
 | // Updating period for each HID device. These empirical values are measured from a 11.2 3DS.
 | ||||||
| constexpr u64 pad_update_ticks = BASE_CLOCK_RATE_ARM11 / 234; | constexpr u64 pad_update_ticks = BASE_CLOCK_RATE_ARM11 / 234; | ||||||
|  | @ -53,13 +30,6 @@ constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE_ARM11 / 101; | ||||||
| constexpr float accelerometer_coef = 512.0f; // measured from hw test result
 | constexpr float accelerometer_coef = 512.0f; // measured from hw test result
 | ||||||
| constexpr float gyroscope_coef = 14.375f; // got from hwtest GetGyroscopeLowRawToDpsCoefficient call
 | constexpr float gyroscope_coef = 14.375f; // got from hwtest GetGyroscopeLowRawToDpsCoefficient call
 | ||||||
| 
 | 
 | ||||||
| static std::atomic<bool> is_device_reload_pending; |  | ||||||
| static std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID> |  | ||||||
|     buttons; |  | ||||||
| static std::unique_ptr<Input::AnalogDevice> circle_pad; |  | ||||||
| static std::unique_ptr<Input::MotionDevice> motion_device; |  | ||||||
| static std::unique_ptr<Input::TouchDevice> touch_device; |  | ||||||
| 
 |  | ||||||
| DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y) { | DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y) { | ||||||
|     // 30 degree and 60 degree are angular thresholds for directions
 |     // 30 degree and 60 degree are angular thresholds for directions
 | ||||||
|     constexpr float TAN30 = 0.577350269f; |     constexpr float TAN30 = 0.577350269f; | ||||||
|  | @ -89,7 +59,7 @@ DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y) { | ||||||
|     return state; |     return state; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void LoadInputDevices() { | void Module::LoadInputDevices() { | ||||||
|     std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, |     std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, | ||||||
|                    Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END, |                    Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END, | ||||||
|                    buttons.begin(), Input::CreateDevice<Input::ButtonDevice>); |                    buttons.begin(), Input::CreateDevice<Input::ButtonDevice>); | ||||||
|  | @ -99,16 +69,7 @@ static void LoadInputDevices() { | ||||||
|     touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touch_device); |     touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touch_device); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void UnloadInputDevices() { | void Module::UpdatePadCallback(u64 userdata, int cycles_late) { | ||||||
|     for (auto& button : buttons) { |  | ||||||
|         button.reset(); |  | ||||||
|     } |  | ||||||
|     circle_pad.reset(); |  | ||||||
|     motion_device.reset(); |  | ||||||
|     touch_device.reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void UpdatePadCallback(u64 userdata, int cycles_late) { |  | ||||||
|     SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer()); |     SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer()); | ||||||
| 
 | 
 | ||||||
|     if (is_device_reload_pending.exchange(false)) |     if (is_device_reload_pending.exchange(false)) | ||||||
|  | @ -198,7 +159,7 @@ static void UpdatePadCallback(u64 userdata, int cycles_late) { | ||||||
|     CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event); |     CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void UpdateAccelerometerCallback(u64 userdata, int cycles_late) { | void Module::UpdateAccelerometerCallback(u64 userdata, int cycles_late) { | ||||||
|     SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer()); |     SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer()); | ||||||
| 
 | 
 | ||||||
|     mem->accelerometer.index = next_accelerometer_index; |     mem->accelerometer.index = next_accelerometer_index; | ||||||
|  | @ -240,7 +201,7 @@ static void UpdateAccelerometerCallback(u64 userdata, int cycles_late) { | ||||||
|     CoreTiming::ScheduleEvent(accelerometer_update_ticks - cycles_late, accelerometer_update_event); |     CoreTiming::ScheduleEvent(accelerometer_update_ticks - cycles_late, accelerometer_update_event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void UpdateGyroscopeCallback(u64 userdata, int cycles_late) { | void Module::UpdateGyroscopeCallback(u64 userdata, int cycles_late) { | ||||||
|     SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer()); |     SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer()); | ||||||
| 
 | 
 | ||||||
|     mem->gyroscope.index = next_gyroscope_index; |     mem->gyroscope.index = next_gyroscope_index; | ||||||
|  | @ -273,134 +234,122 @@ static void UpdateGyroscopeCallback(u64 userdata, int cycles_late) { | ||||||
|     CoreTiming::ScheduleEvent(gyroscope_update_ticks - cycles_late, gyroscope_update_event); |     CoreTiming::ScheduleEvent(gyroscope_update_ticks - cycles_late, gyroscope_update_event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetIPCHandles(Service::Interface* self) { | void Module::Interface::GetIPCHandles(Kernel::HLERequestContext& ctx) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp{ctx, 0xA, 0, 0}; | ||||||
| 
 |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 7); | ||||||
|     cmd_buff[1] = 0;          // No error
 |     rb.Push(RESULT_SUCCESS); | ||||||
|     cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header
 |     rb.PushCopyObjects(hid->shared_mem, hid->event_pad_or_touch_1, hid->event_pad_or_touch_2, | ||||||
|     // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling)
 |                        hid->event_accelerometer, hid->event_gyroscope, hid->event_debug_pad); | ||||||
|     cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).Unwrap(); |  | ||||||
|     cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_1).Unwrap(); |  | ||||||
|     cmd_buff[5] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_2).Unwrap(); |  | ||||||
|     cmd_buff[6] = Kernel::g_handle_table.Create(Service::HID::event_accelerometer).Unwrap(); |  | ||||||
|     cmd_buff[7] = Kernel::g_handle_table.Create(Service::HID::event_gyroscope).Unwrap(); |  | ||||||
|     cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::event_debug_pad).Unwrap(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EnableAccelerometer(Service::Interface* self) { | void Module::Interface::EnableAccelerometer(Kernel::HLERequestContext& ctx) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp{ctx, 0x11, 0, 0}; | ||||||
| 
 | 
 | ||||||
|     ++enable_accelerometer_count; |     ++hid->enable_accelerometer_count; | ||||||
| 
 | 
 | ||||||
|     // Schedules the accelerometer update event if the accelerometer was just enabled
 |     // Schedules the accelerometer update event if the accelerometer was just enabled
 | ||||||
|     if (enable_accelerometer_count == 1) { |     if (hid->enable_accelerometer_count == 1) { | ||||||
|         CoreTiming::ScheduleEvent(accelerometer_update_ticks, accelerometer_update_event); |         CoreTiming::ScheduleEvent(accelerometer_update_ticks, hid->accelerometer_update_event); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_HID, "called"); |     LOG_DEBUG(Service_HID, "called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DisableAccelerometer(Service::Interface* self) { | void Module::Interface::DisableAccelerometer(Kernel::HLERequestContext& ctx) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp{ctx, 0x12, 0, 0}; | ||||||
| 
 | 
 | ||||||
|     --enable_accelerometer_count; |     --hid->enable_accelerometer_count; | ||||||
| 
 | 
 | ||||||
|     // Unschedules the accelerometer update event if the accelerometer was just disabled
 |     // Unschedules the accelerometer update event if the accelerometer was just disabled
 | ||||||
|     if (enable_accelerometer_count == 0) { |     if (hid->enable_accelerometer_count == 0) { | ||||||
|         CoreTiming::UnscheduleEvent(accelerometer_update_event, 0); |         CoreTiming::UnscheduleEvent(hid->accelerometer_update_event, 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_HID, "called"); |     LOG_DEBUG(Service_HID, "called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EnableGyroscopeLow(Service::Interface* self) { | void Module::Interface::EnableGyroscopeLow(Kernel::HLERequestContext& ctx) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp{ctx, 0x13, 0, 0}; | ||||||
| 
 | 
 | ||||||
|     ++enable_gyroscope_count; |     ++hid->enable_gyroscope_count; | ||||||
| 
 | 
 | ||||||
|     // Schedules the gyroscope update event if the gyroscope was just enabled
 |     // Schedules the gyroscope update event if the gyroscope was just enabled
 | ||||||
|     if (enable_gyroscope_count == 1) { |     if (hid->enable_gyroscope_count == 1) { | ||||||
|         CoreTiming::ScheduleEvent(gyroscope_update_ticks, gyroscope_update_event); |         CoreTiming::ScheduleEvent(gyroscope_update_ticks, hid->gyroscope_update_event); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_HID, "called"); |     LOG_DEBUG(Service_HID, "called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DisableGyroscopeLow(Service::Interface* self) { | void Module::Interface::DisableGyroscopeLow(Kernel::HLERequestContext& ctx) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp{ctx, 0x14, 0, 0}; | ||||||
| 
 | 
 | ||||||
|     --enable_gyroscope_count; |     --hid->enable_gyroscope_count; | ||||||
| 
 | 
 | ||||||
|     // Unschedules the gyroscope update event if the gyroscope was just disabled
 |     // Unschedules the gyroscope update event if the gyroscope was just disabled
 | ||||||
|     if (enable_gyroscope_count == 0) { |     if (hid->enable_gyroscope_count == 0) { | ||||||
|         CoreTiming::UnscheduleEvent(gyroscope_update_event, 0); |         CoreTiming::UnscheduleEvent(hid->gyroscope_update_event, 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_HID, "called"); |     LOG_DEBUG(Service_HID, "called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetGyroscopeLowRawToDpsCoefficient(Service::Interface* self) { | void Module::Interface::GetGyroscopeLowRawToDpsCoefficient(Kernel::HLERequestContext& ctx) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp{ctx, 0x15, 0, 0}; | ||||||
| 
 | 
 | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
| 
 |     rb.Push(RESULT_SUCCESS); | ||||||
|     f32 coef = gyroscope_coef; |     rb.PushRaw<f32>(gyroscope_coef); | ||||||
|     memcpy(&cmd_buff[2], &coef, 4); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetGyroscopeLowCalibrateParam(Service::Interface* self) { | void Module::Interface::GetGyroscopeLowCalibrateParam(Kernel::HLERequestContext& ctx) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp{ctx, 0x16, 0, 0}; | ||||||
| 
 | 
 | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |     IPC::RequestBuilder rb = rp.MakeBuilder(6, 0); | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
| 
 | 
 | ||||||
|     const s16 param_unit = 6700; // an approximate value taken from hw
 |     const s16 param_unit = 6700; // an approximate value taken from hw
 | ||||||
|     GyroscopeCalibrateParam param = { |     GyroscopeCalibrateParam param = { | ||||||
|         {0, param_unit, -param_unit}, {0, param_unit, -param_unit}, {0, param_unit, -param_unit}, |         {0, param_unit, -param_unit}, {0, param_unit, -param_unit}, {0, param_unit, -param_unit}, | ||||||
|     }; |     }; | ||||||
|     memcpy(&cmd_buff[2], ¶m, sizeof(param)); |     rb.PushRaw(param); | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_HID, "(STUBBED) called"); |     LOG_WARNING(Service_HID, "(STUBBED) called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetSoundVolume(Service::Interface* self) { | void Module::Interface::GetSoundVolume(Kernel::HLERequestContext& ctx) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp{ctx, 0x17, 0, 0}; | ||||||
| 
 | 
 | ||||||
|     const u8 volume = 0x3F; // TODO(purpasmart): Find out if this is the max value for the volume
 |     const u8 volume = 0x3F; // TODO(purpasmart): Find out if this is the max value for the volume
 | ||||||
| 
 | 
 | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|     cmd_buff[2] = volume; |     rb.Push(RESULT_SUCCESS); | ||||||
|  |     rb.Push(volume); | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_HID, "(STUBBED) called"); |     LOG_WARNING(Service_HID, "(STUBBED) called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Init() { | Module::Interface::Interface(std::shared_ptr<Module> hid, const char* name, u32 max_session) | ||||||
|  |     : ServiceFramework(name, max_session), hid(std::move(hid)) {} | ||||||
|  | 
 | ||||||
|  | Module::Module() { | ||||||
|     using namespace Kernel; |     using namespace Kernel; | ||||||
| 
 | 
 | ||||||
|     AddService(new HID_U_Interface); |  | ||||||
|     AddService(new HID_SPVR_Interface); |  | ||||||
| 
 |  | ||||||
|     is_device_reload_pending.store(true); |  | ||||||
| 
 |  | ||||||
|     using Kernel::MemoryPermission; |  | ||||||
|     shared_mem = |     shared_mem = | ||||||
|         SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read, |         SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read, | ||||||
|                              0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); |                              0, MemoryRegion::BASE, "HID:SharedMemory"); | ||||||
| 
 |  | ||||||
|     next_pad_index = 0; |  | ||||||
|     next_touch_index = 0; |  | ||||||
|     next_accelerometer_index = 0; |  | ||||||
|     next_gyroscope_index = 0; |  | ||||||
| 
 |  | ||||||
|     enable_accelerometer_count = 0; |  | ||||||
|     enable_gyroscope_count = 0; |  | ||||||
| 
 | 
 | ||||||
|     // Create event handles
 |     // Create event handles
 | ||||||
|     event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1"); |     event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1"); | ||||||
|  | @ -410,27 +359,35 @@ void Init() { | ||||||
|     event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad"); |     event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad"); | ||||||
| 
 | 
 | ||||||
|     // Register update callbacks
 |     // Register update callbacks
 | ||||||
|     pad_update_event = CoreTiming::RegisterEvent("HID::UpdatePadCallback", UpdatePadCallback); |     pad_update_event = | ||||||
|     accelerometer_update_event = |         CoreTiming::RegisterEvent("HID::UpdatePadCallback", [this](u64 userdata, int cycles_late) { | ||||||
|         CoreTiming::RegisterEvent("HID::UpdateAccelerometerCallback", UpdateAccelerometerCallback); |             UpdatePadCallback(userdata, cycles_late); | ||||||
|     gyroscope_update_event = |         }); | ||||||
|         CoreTiming::RegisterEvent("HID::UpdateGyroscopeCallback", UpdateGyroscopeCallback); |     accelerometer_update_event = CoreTiming::RegisterEvent( | ||||||
|  |         "HID::UpdateAccelerometerCallback", [this](u64 userdata, int cycles_late) { | ||||||
|  |             UpdateAccelerometerCallback(userdata, cycles_late); | ||||||
|  |         }); | ||||||
|  |     gyroscope_update_event = CoreTiming::RegisterEvent( | ||||||
|  |         "HID::UpdateGyroscopeCallback", | ||||||
|  |         [this](u64 userdata, int cycles_late) { UpdateGyroscopeCallback(userdata, cycles_late); }); | ||||||
| 
 | 
 | ||||||
|     CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event); |     CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Shutdown() { | void Module::ReloadInputDevices() { | ||||||
|     shared_mem = nullptr; |     is_device_reload_pending.store(true); | ||||||
|     event_pad_or_touch_1 = nullptr; |  | ||||||
|     event_pad_or_touch_2 = nullptr; |  | ||||||
|     event_accelerometer = nullptr; |  | ||||||
|     event_gyroscope = nullptr; |  | ||||||
|     event_debug_pad = nullptr; |  | ||||||
|     UnloadInputDevices(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ReloadInputDevices() { | void ReloadInputDevices() { | ||||||
|     is_device_reload_pending.store(true); |     if (auto hid = current_module.lock()) | ||||||
|  |         hid->ReloadInputDevices(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void InstallInterfaces(SM::ServiceManager& service_manager) { | ||||||
|  |     auto hid = std::make_shared<Module>(); | ||||||
|  |     std::make_shared<User>(hid)->InstallAsService(service_manager); | ||||||
|  |     std::make_shared<Spvr>(hid)->InstallAsService(service_manager); | ||||||
|  |     current_module = hid; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace HID
 | } // namespace HID
 | ||||||
|  |  | ||||||
|  | @ -5,17 +5,29 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <array> | #include <array> | ||||||
|  | #include <atomic> | ||||||
| #ifndef _MSC_VER | #ifndef _MSC_VER | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| #endif | #endif | ||||||
|  | #include <memory> | ||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/common_funcs.h" | #include "common/common_funcs.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  | #include "core/frontend/input.h" | ||||||
|  | #include "core/hle/kernel/kernel.h" | ||||||
|  | #include "core/hle/service/service.h" | ||||||
| #include "core/settings.h" | #include "core/settings.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Kernel { | ||||||
|  | class Event; | ||||||
|  | class SharedMemory; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| class Interface; | namespace CoreTiming { | ||||||
|  | class EventType; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | namespace Service { | ||||||
| 
 | 
 | ||||||
| namespace HID { | namespace HID { | ||||||
| 
 | 
 | ||||||
|  | @ -186,93 +198,140 @@ struct DirectionState { | ||||||
| /// Translates analog stick axes to directions. This is exposed for ir_rst module to use.
 | /// Translates analog stick axes to directions. This is exposed for ir_rst module to use.
 | ||||||
| DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y); | DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y); | ||||||
| 
 | 
 | ||||||
| /**
 | class Module final { | ||||||
|  * HID::GetIPCHandles service function | public: | ||||||
|  *  Inputs: |     Module(); | ||||||
|  *      None |  | ||||||
|  *  Outputs: |  | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |  | ||||||
|  *      2 : IPC Command Structure translate-header |  | ||||||
|  *      3 : Handle to HID shared memory |  | ||||||
|  *      4 : Event signaled by HID |  | ||||||
|  *      5 : Event signaled by HID |  | ||||||
|  *      6 : Event signaled by HID |  | ||||||
|  *      7 : Gyroscope event |  | ||||||
|  *      8 : Event signaled by HID |  | ||||||
|  */ |  | ||||||
| void GetIPCHandles(Interface* self); |  | ||||||
| 
 | 
 | ||||||
| /**
 |     class Interface : public ServiceFramework<Interface> { | ||||||
|  * HID::EnableAccelerometer service function |     public: | ||||||
|  *  Inputs: |         Interface(std::shared_ptr<Module> hid, const char* name, u32 max_session); | ||||||
|  *      None |  | ||||||
|  *  Outputs: |  | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |  | ||||||
|  */ |  | ||||||
| void EnableAccelerometer(Interface* self); |  | ||||||
| 
 | 
 | ||||||
| /**
 |     protected: | ||||||
|  * HID::DisableAccelerometer service function |         /**
 | ||||||
|  *  Inputs: |          * HID::GetIPCHandles service function | ||||||
|  *      None |          *  Inputs: | ||||||
|  *  Outputs: |          *      None | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |          *  Outputs: | ||||||
|  */ |          *      1 : Result of function, 0 on success, otherwise error code | ||||||
| void DisableAccelerometer(Interface* self); |          *      2 : IPC Command Structure translate-header | ||||||
|  |          *      3 : Handle to HID shared memory | ||||||
|  |          *      4 : Event signaled by HID | ||||||
|  |          *      5 : Event signaled by HID | ||||||
|  |          *      6 : Event signaled by HID | ||||||
|  |          *      7 : Gyroscope event | ||||||
|  |          *      8 : Event signaled by HID | ||||||
|  |          */ | ||||||
|  |         void GetIPCHandles(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * HID::EnableGyroscopeLow service function |          * HID::EnableAccelerometer service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      None |          *      None | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |          *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void EnableGyroscopeLow(Interface* self); |         void EnableAccelerometer(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * HID::DisableGyroscopeLow service function |          * HID::DisableAccelerometer service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      None |          *      None | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |          *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void DisableGyroscopeLow(Interface* self); |         void DisableAccelerometer(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * HID::GetSoundVolume service function |          * HID::EnableGyroscopeLow service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      None |          *      None | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |          *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  *      2 : u8 output value |          */ | ||||||
|  */ |         void EnableGyroscopeLow(Kernel::HLERequestContext& ctx); | ||||||
| void GetSoundVolume(Interface* self); |  | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * HID::GetGyroscopeLowRawToDpsCoefficient service function |          * HID::DisableGyroscopeLow service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      None |          *      None | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |          *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  *      2 : float output value |          */ | ||||||
|  */ |         void DisableGyroscopeLow(Kernel::HLERequestContext& ctx); | ||||||
| void GetGyroscopeLowRawToDpsCoefficient(Service::Interface* self); |  | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * HID::GetGyroscopeLowCalibrateParam service function |          * HID::GetSoundVolume service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      None |          *      None | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result of function, 0 on success, otherwise error code |          *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  *      2~6 (18 bytes) : struct GyroscopeCalibrateParam |          *      2 : u8 output value | ||||||
|  */ |          */ | ||||||
| void GetGyroscopeLowCalibrateParam(Service::Interface* self); |         void GetSoundVolume(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /// Initialize HID service
 |         /**
 | ||||||
| void Init(); |          * HID::GetGyroscopeLowRawToDpsCoefficient service function | ||||||
|  |          *  Inputs: | ||||||
|  |          *      None | ||||||
|  |          *  Outputs: | ||||||
|  |          *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  |          *      2 : float output value | ||||||
|  |          */ | ||||||
|  |         void GetGyroscopeLowRawToDpsCoefficient(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /// Shutdown HID service
 |         /**
 | ||||||
| void Shutdown(); |          * HID::GetGyroscopeLowCalibrateParam service function | ||||||
|  |          *  Inputs: | ||||||
|  |          *      None | ||||||
|  |          *  Outputs: | ||||||
|  |          *      1 : Result of function, 0 on success, otherwise error code | ||||||
|  |          *      2~6 (18 bytes) : struct GyroscopeCalibrateParam | ||||||
|  |          */ | ||||||
|  |         void GetGyroscopeLowCalibrateParam(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     private: | ||||||
|  |         std::shared_ptr<Module> hid; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     void ReloadInputDevices(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     void LoadInputDevices(); | ||||||
|  |     void UpdatePadCallback(u64 userdata, int cycles_late); | ||||||
|  |     void UpdateAccelerometerCallback(u64 userdata, int cycles_late); | ||||||
|  |     void UpdateGyroscopeCallback(u64 userdata, int cycles_late); | ||||||
|  | 
 | ||||||
|  |     // Handle to shared memory region designated to HID_User service
 | ||||||
|  |     Kernel::SharedPtr<Kernel::SharedMemory> shared_mem; | ||||||
|  | 
 | ||||||
|  |     // Event handles
 | ||||||
|  |     Kernel::SharedPtr<Kernel::Event> event_pad_or_touch_1; | ||||||
|  |     Kernel::SharedPtr<Kernel::Event> event_pad_or_touch_2; | ||||||
|  |     Kernel::SharedPtr<Kernel::Event> event_accelerometer; | ||||||
|  |     Kernel::SharedPtr<Kernel::Event> event_gyroscope; | ||||||
|  |     Kernel::SharedPtr<Kernel::Event> event_debug_pad; | ||||||
|  | 
 | ||||||
|  |     u32 next_pad_index = 0; | ||||||
|  |     u32 next_touch_index = 0; | ||||||
|  |     u32 next_accelerometer_index = 0; | ||||||
|  |     u32 next_gyroscope_index = 0; | ||||||
|  | 
 | ||||||
|  |     int enable_accelerometer_count = 0; // positive means enabled
 | ||||||
|  |     int enable_gyroscope_count = 0;     // positive means enabled
 | ||||||
|  | 
 | ||||||
|  |     CoreTiming::EventType* pad_update_event; | ||||||
|  |     CoreTiming::EventType* accelerometer_update_event; | ||||||
|  |     CoreTiming::EventType* gyroscope_update_event; | ||||||
|  | 
 | ||||||
|  |     std::atomic<bool> is_device_reload_pending{true}; | ||||||
|  |     std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID> | ||||||
|  |         buttons; | ||||||
|  |     std::unique_ptr<Input::AnalogDevice> circle_pad; | ||||||
|  |     std::unique_ptr<Input::MotionDevice> motion_device; | ||||||
|  |     std::unique_ptr<Input::TouchDevice> touch_device; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void InstallInterfaces(SM::ServiceManager& service_manager); | ||||||
| 
 | 
 | ||||||
| /// Reload input devices. Used when input configuration changed
 | /// Reload input devices. Used when input configuration changed
 | ||||||
| void ReloadInputDevices(); | void ReloadInputDevices(); | ||||||
|  |  | ||||||
|  | @ -2,27 +2,26 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/hid/hid.h" |  | ||||||
| #include "core/hle/service/hid/hid_spvr.h" | #include "core/hle/service/hid/hid_spvr.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace HID { | namespace HID { | ||||||
| 
 | 
 | ||||||
| const Interface::FunctionInfo FunctionTable[] = { | Spvr::Spvr(std::shared_ptr<Module> hid) : Module::Interface(std::move(hid), "hid:SPVR", 6) { | ||||||
|     {0x000A0000, GetIPCHandles, "GetIPCHandles"}, |     static const FunctionInfo functions[] = { | ||||||
|     {0x000B0000, nullptr, "StartAnalogStickCalibration"}, |         {0x000A0000, &Spvr::GetIPCHandles, "GetIPCHandles"}, | ||||||
|     {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, |         {0x000B0000, nullptr, "StartAnalogStickCalibration"}, | ||||||
|     {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, |         {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, | ||||||
|     {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, |         {0x00110000, &Spvr::EnableAccelerometer, "EnableAccelerometer"}, | ||||||
|     {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, |         {0x00120000, &Spvr::DisableAccelerometer, "DisableAccelerometer"}, | ||||||
|     {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, |         {0x00130000, &Spvr::EnableGyroscopeLow, "EnableGyroscopeLow"}, | ||||||
|     {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, |         {0x00140000, &Spvr::DisableGyroscopeLow, "DisableGyroscopeLow"}, | ||||||
|     {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, |         {0x00150000, &Spvr::GetGyroscopeLowRawToDpsCoefficient, | ||||||
|     {0x00170000, GetSoundVolume, "GetSoundVolume"}, |          "GetGyroscopeLowRawToDpsCoefficient"}, | ||||||
| }; |         {0x00160000, &Spvr::GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, | ||||||
| 
 |         {0x00170000, &Spvr::GetSoundVolume, "GetSoundVolume"}, | ||||||
| HID_SPVR_Interface::HID_SPVR_Interface() { |     }; | ||||||
|     Register(FunctionTable); |     RegisterHandlers(functions); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace HID
 | } // namespace HID
 | ||||||
|  |  | ||||||
|  | @ -4,19 +4,15 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/hid/hid.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace HID { | namespace HID { | ||||||
| 
 | 
 | ||||||
| class HID_SPVR_Interface : public Service::Interface { | class Spvr final : public Module::Interface { | ||||||
| public: | public: | ||||||
|     HID_SPVR_Interface(); |     explicit Spvr(std::shared_ptr<Module> hid); | ||||||
| 
 |  | ||||||
|     std::string GetPortName() const override { |  | ||||||
|         return "hid:SPVR"; |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace HID
 | } // namespace HID
 | ||||||
| } // namespace Service
 | } // namespace Service
 | ||||||
|  |  | ||||||
|  | @ -2,27 +2,26 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/hid/hid.h" |  | ||||||
| #include "core/hle/service/hid/hid_user.h" | #include "core/hle/service/hid/hid_user.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace HID { | namespace HID { | ||||||
| 
 | 
 | ||||||
| const Interface::FunctionInfo FunctionTable[] = { | User::User(std::shared_ptr<Module> hid) : Module::Interface(std::move(hid), "hid:USER", 6) { | ||||||
|     {0x000A0000, GetIPCHandles, "GetIPCHandles"}, |     static const FunctionInfo functions[] = { | ||||||
|     {0x000B0000, nullptr, "StartAnalogStickCalibration"}, |         {0x000A0000, &User::GetIPCHandles, "GetIPCHandles"}, | ||||||
|     {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, |         {0x000B0000, nullptr, "StartAnalogStickCalibration"}, | ||||||
|     {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, |         {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, | ||||||
|     {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, |         {0x00110000, &User::EnableAccelerometer, "EnableAccelerometer"}, | ||||||
|     {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, |         {0x00120000, &User::DisableAccelerometer, "DisableAccelerometer"}, | ||||||
|     {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, |         {0x00130000, &User::EnableGyroscopeLow, "EnableGyroscopeLow"}, | ||||||
|     {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, |         {0x00140000, &User::DisableGyroscopeLow, "DisableGyroscopeLow"}, | ||||||
|     {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, |         {0x00150000, &User::GetGyroscopeLowRawToDpsCoefficient, | ||||||
|     {0x00170000, GetSoundVolume, "GetSoundVolume"}, |          "GetGyroscopeLowRawToDpsCoefficient"}, | ||||||
| }; |         {0x00160000, &User::GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, | ||||||
| 
 |         {0x00170000, &User::GetSoundVolume, "GetSoundVolume"}, | ||||||
| HID_U_Interface::HID_U_Interface() { |     }; | ||||||
|     Register(FunctionTable); |     RegisterHandlers(functions); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace HID
 | } // namespace HID
 | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/hid/hid.h" | ||||||
| 
 | 
 | ||||||
| // This service is used for interfacing to physical user controls.
 | // This service is used for interfacing to physical user controls.
 | ||||||
| // Uses include game pad controls, touchscreen, accelerometers, gyroscopes, and debug pad.
 | // Uses include game pad controls, touchscreen, accelerometers, gyroscopes, and debug pad.
 | ||||||
|  | @ -12,17 +12,10 @@ | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace HID { | namespace HID { | ||||||
| 
 | 
 | ||||||
| /**
 | class User final : public Module::Interface { | ||||||
|  * HID service interface. |  | ||||||
|  */ |  | ||||||
| class HID_U_Interface : public Service::Interface { |  | ||||||
| public: | public: | ||||||
|     HID_U_Interface(); |     explicit User(std::shared_ptr<Module> hid); | ||||||
| 
 |  | ||||||
|     std::string GetPortName() const override { |  | ||||||
|         return "hid:USER"; |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace HID
 | } // namespace HID
 | ||||||
| } // namespace Service
 | } // namespace Service
 | ||||||
|  |  | ||||||
|  | @ -277,7 +277,7 @@ void Init() { | ||||||
|     DLP::Init(); |     DLP::Init(); | ||||||
|     FRD::Init(); |     FRD::Init(); | ||||||
|     GSP::InstallInterfaces(*SM::g_service_manager); |     GSP::InstallInterfaces(*SM::g_service_manager); | ||||||
|     HID::Init(); |     HID::InstallInterfaces(*SM::g_service_manager); | ||||||
|     IR::InstallInterfaces(*SM::g_service_manager); |     IR::InstallInterfaces(*SM::g_service_manager); | ||||||
|     MVD::Init(); |     MVD::Init(); | ||||||
|     NDM::Init(); |     NDM::Init(); | ||||||
|  | @ -307,7 +307,6 @@ void Shutdown() { | ||||||
|     NIM::Shutdown(); |     NIM::Shutdown(); | ||||||
|     NEWS::Shutdown(); |     NEWS::Shutdown(); | ||||||
|     NDM::Shutdown(); |     NDM::Shutdown(); | ||||||
|     HID::Shutdown(); |  | ||||||
|     FRD::Shutdown(); |     FRD::Shutdown(); | ||||||
|     DLP::Shutdown(); |     DLP::Shutdown(); | ||||||
|     CFG::Shutdown(); |     CFG::Shutdown(); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue