mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +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.
 | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <atomic> | ||||
| #include <cmath> | ||||
| #include <memory> | ||||
| #include "common/logging/log.h" | ||||
| #include "core/3ds.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/frontend/input.h" | ||||
| #include "core/hle/ipc.h" | ||||
| #include "core/hle/ipc_helpers.h" | ||||
| #include "core/hle/kernel/event.h" | ||||
| #include "core/hle/kernel/handle_table.h" | ||||
| #include "core/hle/kernel/shared_memory.h" | ||||
|  | @ -23,27 +20,7 @@ | |||
| namespace Service { | ||||
| namespace HID { | ||||
| 
 | ||||
| // Handle to shared memory region designated to HID_User service
 | ||||
| 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; | ||||
| static std::weak_ptr<Module> current_module; | ||||
| 
 | ||||
| // 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; | ||||
|  | @ -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 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) { | ||||
|     // 30 degree and 60 degree are angular thresholds for directions
 | ||||
|     constexpr float TAN30 = 0.577350269f; | ||||
|  | @ -89,7 +59,7 @@ DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y) { | |||
|     return state; | ||||
| } | ||||
| 
 | ||||
| static void LoadInputDevices() { | ||||
| void Module::LoadInputDevices() { | ||||
|     std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, | ||||
|                    Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END, | ||||
|                    buttons.begin(), Input::CreateDevice<Input::ButtonDevice>); | ||||
|  | @ -99,16 +69,7 @@ static void LoadInputDevices() { | |||
|     touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touch_device); | ||||
| } | ||||
| 
 | ||||
| static void UnloadInputDevices() { | ||||
|     for (auto& button : buttons) { | ||||
|         button.reset(); | ||||
|     } | ||||
|     circle_pad.reset(); | ||||
|     motion_device.reset(); | ||||
|     touch_device.reset(); | ||||
| } | ||||
| 
 | ||||
| static void UpdatePadCallback(u64 userdata, int cycles_late) { | ||||
| void Module::UpdatePadCallback(u64 userdata, int cycles_late) { | ||||
|     SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer()); | ||||
| 
 | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
| static void UpdateAccelerometerCallback(u64 userdata, int cycles_late) { | ||||
| void Module::UpdateAccelerometerCallback(u64 userdata, int cycles_late) { | ||||
|     SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer()); | ||||
| 
 | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
| static void UpdateGyroscopeCallback(u64 userdata, int cycles_late) { | ||||
| void Module::UpdateGyroscopeCallback(u64 userdata, int cycles_late) { | ||||
|     SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer()); | ||||
| 
 | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
| void GetIPCHandles(Service::Interface* self) { | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     cmd_buff[1] = 0;          // No error
 | ||||
|     cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header
 | ||||
|     // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling)
 | ||||
|     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 Module::Interface::GetIPCHandles(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx, 0xA, 0, 0}; | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 7); | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushCopyObjects(hid->shared_mem, hid->event_pad_or_touch_1, hid->event_pad_or_touch_2, | ||||
|                        hid->event_accelerometer, hid->event_gyroscope, hid->event_debug_pad); | ||||
| } | ||||
| 
 | ||||
| void EnableAccelerometer(Service::Interface* self) { | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| void Module::Interface::EnableAccelerometer(Kernel::HLERequestContext& ctx) { | ||||
|     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
 | ||||
|     if (enable_accelerometer_count == 1) { | ||||
|         CoreTiming::ScheduleEvent(accelerometer_update_ticks, accelerometer_update_event); | ||||
|     if (hid->enable_accelerometer_count == 1) { | ||||
|         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"); | ||||
| } | ||||
| 
 | ||||
| void DisableAccelerometer(Service::Interface* self) { | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| void Module::Interface::DisableAccelerometer(Kernel::HLERequestContext& ctx) { | ||||
|     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
 | ||||
|     if (enable_accelerometer_count == 0) { | ||||
|         CoreTiming::UnscheduleEvent(accelerometer_update_event, 0); | ||||
|     if (hid->enable_accelerometer_count == 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"); | ||||
| } | ||||
| 
 | ||||
| void EnableGyroscopeLow(Service::Interface* self) { | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| void Module::Interface::EnableGyroscopeLow(Kernel::HLERequestContext& ctx) { | ||||
|     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
 | ||||
|     if (enable_gyroscope_count == 1) { | ||||
|         CoreTiming::ScheduleEvent(gyroscope_update_ticks, gyroscope_update_event); | ||||
|     if (hid->enable_gyroscope_count == 1) { | ||||
|         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"); | ||||
| } | ||||
| 
 | ||||
| void DisableGyroscopeLow(Service::Interface* self) { | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| void Module::Interface::DisableGyroscopeLow(Kernel::HLERequestContext& ctx) { | ||||
|     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
 | ||||
|     if (enable_gyroscope_count == 0) { | ||||
|         CoreTiming::UnscheduleEvent(gyroscope_update_event, 0); | ||||
|     if (hid->enable_gyroscope_count == 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"); | ||||
| } | ||||
| 
 | ||||
| void GetGyroscopeLowRawToDpsCoefficient(Service::Interface* self) { | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| void Module::Interface::GetGyroscopeLowRawToDpsCoefficient(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx, 0x15, 0, 0}; | ||||
| 
 | ||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; | ||||
| 
 | ||||
|     f32 coef = gyroscope_coef; | ||||
|     memcpy(&cmd_buff[2], &coef, 4); | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushRaw<f32>(gyroscope_coef); | ||||
| } | ||||
| 
 | ||||
| void GetGyroscopeLowCalibrateParam(Service::Interface* self) { | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| void Module::Interface::GetGyroscopeLowCalibrateParam(Kernel::HLERequestContext& ctx) { | ||||
|     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
 | ||||
|     GyroscopeCalibrateParam param = { | ||||
|         {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"); | ||||
| } | ||||
| 
 | ||||
| void GetSoundVolume(Service::Interface* self) { | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| void Module::Interface::GetSoundVolume(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx, 0x17, 0, 0}; | ||||
| 
 | ||||
|     const u8 volume = 0x3F; // TODO(purpasmart): Find out if this is the max value for the volume
 | ||||
| 
 | ||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; | ||||
|     cmd_buff[2] = volume; | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.Push(volume); | ||||
| 
 | ||||
|     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; | ||||
| 
 | ||||
|     AddService(new HID_U_Interface); | ||||
|     AddService(new HID_SPVR_Interface); | ||||
| 
 | ||||
|     is_device_reload_pending.store(true); | ||||
| 
 | ||||
|     using Kernel::MemoryPermission; | ||||
|     shared_mem = | ||||
|         SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read, | ||||
|                              0, Kernel::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; | ||||
|                              0, MemoryRegion::BASE, "HID:SharedMemory"); | ||||
| 
 | ||||
|     // Create event handles
 | ||||
|     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"); | ||||
| 
 | ||||
|     // Register update callbacks
 | ||||
|     pad_update_event = CoreTiming::RegisterEvent("HID::UpdatePadCallback", UpdatePadCallback); | ||||
|     accelerometer_update_event = | ||||
|         CoreTiming::RegisterEvent("HID::UpdateAccelerometerCallback", UpdateAccelerometerCallback); | ||||
|     gyroscope_update_event = | ||||
|         CoreTiming::RegisterEvent("HID::UpdateGyroscopeCallback", UpdateGyroscopeCallback); | ||||
|     pad_update_event = | ||||
|         CoreTiming::RegisterEvent("HID::UpdatePadCallback", [this](u64 userdata, int cycles_late) { | ||||
|             UpdatePadCallback(userdata, cycles_late); | ||||
|         }); | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
| void Shutdown() { | ||||
|     shared_mem = nullptr; | ||||
|     event_pad_or_touch_1 = nullptr; | ||||
|     event_pad_or_touch_2 = nullptr; | ||||
|     event_accelerometer = nullptr; | ||||
|     event_gyroscope = nullptr; | ||||
|     event_debug_pad = nullptr; | ||||
|     UnloadInputDevices(); | ||||
| void Module::ReloadInputDevices() { | ||||
|     is_device_reload_pending.store(true); | ||||
| } | ||||
| 
 | ||||
| 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
 | ||||
|  |  | |||
|  | @ -5,17 +5,29 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <array> | ||||
| #include <atomic> | ||||
| #ifndef _MSC_VER | ||||
| #include <cstddef> | ||||
| #endif | ||||
| #include <memory> | ||||
| #include "common/bit_field.h" | ||||
| #include "common/common_funcs.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" | ||||
| 
 | ||||
| namespace Service { | ||||
| namespace Kernel { | ||||
| class Event; | ||||
| class SharedMemory; | ||||
| } | ||||
| 
 | ||||
| class Interface; | ||||
| namespace CoreTiming { | ||||
| class EventType; | ||||
| }; | ||||
| 
 | ||||
| namespace Service { | ||||
| 
 | ||||
| namespace HID { | ||||
| 
 | ||||
|  | @ -186,93 +198,140 @@ struct DirectionState { | |||
| /// 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); | ||||
| 
 | ||||
| /**
 | ||||
|  * HID::GetIPCHandles service function | ||||
|  *  Inputs: | ||||
|  *      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 Module final { | ||||
| public: | ||||
|     Module(); | ||||
| 
 | ||||
| /**
 | ||||
|  * HID::EnableAccelerometer service function | ||||
|  *  Inputs: | ||||
|  *      None | ||||
|  *  Outputs: | ||||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| void EnableAccelerometer(Interface* self); | ||||
|     class Interface : public ServiceFramework<Interface> { | ||||
|     public: | ||||
|         Interface(std::shared_ptr<Module> hid, const char* name, u32 max_session); | ||||
| 
 | ||||
| /**
 | ||||
|  * HID::DisableAccelerometer service function | ||||
|  *  Inputs: | ||||
|  *      None | ||||
|  *  Outputs: | ||||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| void DisableAccelerometer(Interface* self); | ||||
|     protected: | ||||
|         /**
 | ||||
|          * HID::GetIPCHandles service function | ||||
|          *  Inputs: | ||||
|          *      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(Kernel::HLERequestContext& ctx); | ||||
| 
 | ||||
| /**
 | ||||
|  * HID::EnableGyroscopeLow service function | ||||
|  *  Inputs: | ||||
|  *      None | ||||
|  *  Outputs: | ||||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| void EnableGyroscopeLow(Interface* self); | ||||
|         /**
 | ||||
|          * HID::EnableAccelerometer service function | ||||
|          *  Inputs: | ||||
|          *      None | ||||
|          *  Outputs: | ||||
|          *      1 : Result of function, 0 on success, otherwise error code | ||||
|          */ | ||||
|         void EnableAccelerometer(Kernel::HLERequestContext& ctx); | ||||
| 
 | ||||
| /**
 | ||||
|  * HID::DisableGyroscopeLow service function | ||||
|  *  Inputs: | ||||
|  *      None | ||||
|  *  Outputs: | ||||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  */ | ||||
| void DisableGyroscopeLow(Interface* self); | ||||
|         /**
 | ||||
|          * HID::DisableAccelerometer service function | ||||
|          *  Inputs: | ||||
|          *      None | ||||
|          *  Outputs: | ||||
|          *      1 : Result of function, 0 on success, otherwise error code | ||||
|          */ | ||||
|         void DisableAccelerometer(Kernel::HLERequestContext& ctx); | ||||
| 
 | ||||
| /**
 | ||||
|  * HID::GetSoundVolume service function | ||||
|  *  Inputs: | ||||
|  *      None | ||||
|  *  Outputs: | ||||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  *      2 : u8 output value | ||||
|  */ | ||||
| void GetSoundVolume(Interface* self); | ||||
|         /**
 | ||||
|          * HID::EnableGyroscopeLow service function | ||||
|          *  Inputs: | ||||
|          *      None | ||||
|          *  Outputs: | ||||
|          *      1 : Result of function, 0 on success, otherwise error code | ||||
|          */ | ||||
|         void EnableGyroscopeLow(Kernel::HLERequestContext& ctx); | ||||
| 
 | ||||
| /**
 | ||||
|  * HID::GetGyroscopeLowRawToDpsCoefficient service function | ||||
|  *  Inputs: | ||||
|  *      None | ||||
|  *  Outputs: | ||||
|  *      1 : Result of function, 0 on success, otherwise error code | ||||
|  *      2 : float output value | ||||
|  */ | ||||
| void GetGyroscopeLowRawToDpsCoefficient(Service::Interface* self); | ||||
|         /**
 | ||||
|          * HID::DisableGyroscopeLow service function | ||||
|          *  Inputs: | ||||
|          *      None | ||||
|          *  Outputs: | ||||
|          *      1 : Result of function, 0 on success, otherwise error code | ||||
|          */ | ||||
|         void DisableGyroscopeLow(Kernel::HLERequestContext& ctx); | ||||
| 
 | ||||
| /**
 | ||||
|  * 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(Service::Interface* self); | ||||
|         /**
 | ||||
|          * HID::GetSoundVolume service function | ||||
|          *  Inputs: | ||||
|          *      None | ||||
|          *  Outputs: | ||||
|          *      1 : Result of function, 0 on success, otherwise error code | ||||
|          *      2 : u8 output value | ||||
|          */ | ||||
|         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
 | ||||
| void ReloadInputDevices(); | ||||
|  |  | |||
|  | @ -2,27 +2,26 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "core/hle/service/hid/hid.h" | ||||
| #include "core/hle/service/hid/hid_spvr.h" | ||||
| 
 | ||||
| namespace Service { | ||||
| namespace HID { | ||||
| 
 | ||||
| const Interface::FunctionInfo FunctionTable[] = { | ||||
|     {0x000A0000, GetIPCHandles, "GetIPCHandles"}, | ||||
|     {0x000B0000, nullptr, "StartAnalogStickCalibration"}, | ||||
|     {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, | ||||
|     {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, | ||||
|     {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, | ||||
|     {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, | ||||
|     {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, | ||||
|     {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, | ||||
|     {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, | ||||
|     {0x00170000, GetSoundVolume, "GetSoundVolume"}, | ||||
| }; | ||||
| 
 | ||||
| HID_SPVR_Interface::HID_SPVR_Interface() { | ||||
|     Register(FunctionTable); | ||||
| Spvr::Spvr(std::shared_ptr<Module> hid) : Module::Interface(std::move(hid), "hid:SPVR", 6) { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0x000A0000, &Spvr::GetIPCHandles, "GetIPCHandles"}, | ||||
|         {0x000B0000, nullptr, "StartAnalogStickCalibration"}, | ||||
|         {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, | ||||
|         {0x00110000, &Spvr::EnableAccelerometer, "EnableAccelerometer"}, | ||||
|         {0x00120000, &Spvr::DisableAccelerometer, "DisableAccelerometer"}, | ||||
|         {0x00130000, &Spvr::EnableGyroscopeLow, "EnableGyroscopeLow"}, | ||||
|         {0x00140000, &Spvr::DisableGyroscopeLow, "DisableGyroscopeLow"}, | ||||
|         {0x00150000, &Spvr::GetGyroscopeLowRawToDpsCoefficient, | ||||
|          "GetGyroscopeLowRawToDpsCoefficient"}, | ||||
|         {0x00160000, &Spvr::GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, | ||||
|         {0x00170000, &Spvr::GetSoundVolume, "GetSoundVolume"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
| 
 | ||||
| } // namespace HID
 | ||||
|  |  | |||
|  | @ -4,18 +4,14 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "core/hle/service/service.h" | ||||
| #include "core/hle/service/hid/hid.h" | ||||
| 
 | ||||
| namespace Service { | ||||
| namespace HID { | ||||
| 
 | ||||
| class HID_SPVR_Interface : public Service::Interface { | ||||
| class Spvr final : public Module::Interface { | ||||
| public: | ||||
|     HID_SPVR_Interface(); | ||||
| 
 | ||||
|     std::string GetPortName() const override { | ||||
|         return "hid:SPVR"; | ||||
|     } | ||||
|     explicit Spvr(std::shared_ptr<Module> hid); | ||||
| }; | ||||
| 
 | ||||
| } // namespace HID
 | ||||
|  |  | |||
|  | @ -2,27 +2,26 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "core/hle/service/hid/hid.h" | ||||
| #include "core/hle/service/hid/hid_user.h" | ||||
| 
 | ||||
| namespace Service { | ||||
| namespace HID { | ||||
| 
 | ||||
| const Interface::FunctionInfo FunctionTable[] = { | ||||
|     {0x000A0000, GetIPCHandles, "GetIPCHandles"}, | ||||
|     {0x000B0000, nullptr, "StartAnalogStickCalibration"}, | ||||
|     {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, | ||||
|     {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, | ||||
|     {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, | ||||
|     {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, | ||||
|     {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, | ||||
|     {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, | ||||
|     {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, | ||||
|     {0x00170000, GetSoundVolume, "GetSoundVolume"}, | ||||
| }; | ||||
| 
 | ||||
| HID_U_Interface::HID_U_Interface() { | ||||
|     Register(FunctionTable); | ||||
| User::User(std::shared_ptr<Module> hid) : Module::Interface(std::move(hid), "hid:USER", 6) { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0x000A0000, &User::GetIPCHandles, "GetIPCHandles"}, | ||||
|         {0x000B0000, nullptr, "StartAnalogStickCalibration"}, | ||||
|         {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, | ||||
|         {0x00110000, &User::EnableAccelerometer, "EnableAccelerometer"}, | ||||
|         {0x00120000, &User::DisableAccelerometer, "DisableAccelerometer"}, | ||||
|         {0x00130000, &User::EnableGyroscopeLow, "EnableGyroscopeLow"}, | ||||
|         {0x00140000, &User::DisableGyroscopeLow, "DisableGyroscopeLow"}, | ||||
|         {0x00150000, &User::GetGyroscopeLowRawToDpsCoefficient, | ||||
|          "GetGyroscopeLowRawToDpsCoefficient"}, | ||||
|         {0x00160000, &User::GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, | ||||
|         {0x00170000, &User::GetSoundVolume, "GetSoundVolume"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
| 
 | ||||
| } // namespace HID
 | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 
 | ||||
| #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.
 | ||||
| // Uses include game pad controls, touchscreen, accelerometers, gyroscopes, and debug pad.
 | ||||
|  | @ -12,16 +12,9 @@ | |||
| namespace Service { | ||||
| namespace HID { | ||||
| 
 | ||||
| /**
 | ||||
|  * HID service interface. | ||||
|  */ | ||||
| class HID_U_Interface : public Service::Interface { | ||||
| class User final : public Module::Interface { | ||||
| public: | ||||
|     HID_U_Interface(); | ||||
| 
 | ||||
|     std::string GetPortName() const override { | ||||
|         return "hid:USER"; | ||||
|     } | ||||
|     explicit User(std::shared_ptr<Module> hid); | ||||
| }; | ||||
| 
 | ||||
| } // namespace HID
 | ||||
|  |  | |||
|  | @ -277,7 +277,7 @@ void Init() { | |||
|     DLP::Init(); | ||||
|     FRD::Init(); | ||||
|     GSP::InstallInterfaces(*SM::g_service_manager); | ||||
|     HID::Init(); | ||||
|     HID::InstallInterfaces(*SM::g_service_manager); | ||||
|     IR::InstallInterfaces(*SM::g_service_manager); | ||||
|     MVD::Init(); | ||||
|     NDM::Init(); | ||||
|  | @ -307,7 +307,6 @@ void Shutdown() { | |||
|     NIM::Shutdown(); | ||||
|     NEWS::Shutdown(); | ||||
|     NDM::Shutdown(); | ||||
|     HID::Shutdown(); | ||||
|     FRD::Shutdown(); | ||||
|     DLP::Shutdown(); | ||||
|     CFG::Shutdown(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue