summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/ir
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2017-10-10 23:32:14 +0200
committerbunnei <bunneidev@gmail.com>2017-10-10 23:32:14 +0200
commit0906de9a14b735d1d409290ca050eb7d2c2d3d84 (patch)
tree79bb57d3a4dc4ca377e7a62744c3941de29e785b /src/core/hle/service/ir
parentMerge remote-tracking branch 'upstream/master' into nx (diff)
downloadyuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar
yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar.gz
yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar.bz2
yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar.lz
yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar.xz
yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar.zst
yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.zip
Diffstat (limited to 'src/core/hle/service/ir')
-rw-r--r--src/core/hle/service/ir/extra_hid.cpp231
-rw-r--r--src/core/hle/service/ir/extra_hid.h48
-rw-r--r--src/core/hle/service/ir/ir.cpp35
-rw-r--r--src/core/hle/service/ir/ir.h23
-rw-r--r--src/core/hle/service/ir/ir_rst.cpp221
-rw-r--r--src/core/hle/service/ir/ir_rst.h28
-rw-r--r--src/core/hle/service/ir/ir_u.cpp38
-rw-r--r--src/core/hle/service/ir/ir_u.h22
-rw-r--r--src/core/hle/service/ir/ir_user.cpp558
-rw-r--r--src/core/hle/service/ir/ir_user.h58
10 files changed, 0 insertions, 1262 deletions
diff --git a/src/core/hle/service/ir/extra_hid.cpp b/src/core/hle/service/ir/extra_hid.cpp
deleted file mode 100644
index e7acc17a5..000000000
--- a/src/core/hle/service/ir/extra_hid.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "common/alignment.h"
-#include "common/bit_field.h"
-#include "common/string_util.h"
-#include "core/core_timing.h"
-#include "core/hle/service/ir/extra_hid.h"
-#include "core/settings.h"
-
-namespace Service {
-namespace IR {
-
-enum class RequestID : u8 {
- /**
- * ConfigureHIDPolling request
- * Starts HID input polling, or changes the polling interval if it is already started.
- * Inputs:
- * byte 0: request ID
- * byte 1: polling interval in ms
- * byte 2: unknown
- */
- ConfigureHIDPolling = 1,
-
- /**
- * ReadCalibrationData request
- * Reads the calibration data stored in circle pad pro.
- * Inputs:
- * byte 0: request ID
- * byte 1: expected response time in ms?
- * byte 2-3: data offset (aligned to 0x10)
- * byte 4-5: data size (aligned to 0x10)
- */
- ReadCalibrationData = 2,
-
- // TODO(wwylele): there are three more request types (id = 3, 4 and 5)
-};
-
-enum class ResponseID : u8 {
-
- /**
- * PollHID response
- * Sends current HID status
- * Output:
- * byte 0: response ID
- * byte 1-3: Right circle pad position. This three bytes are two little-endian 12-bit
- * fields. The first one is for x-axis and the second one is for y-axis.
- * byte 4: bit[0:4] battery level; bit[5] ZL button; bit[6] ZR button; bit[7] R button
- * Note that for the three button fields, the bit is set when the button is NOT pressed.
- * byte 5: unknown
- */
- PollHID = 0x10,
-
- /**
- * ReadCalibrationData response
- * Sends the calibration data reads from circle pad pro.
- * Output:
- * byte 0: resonse ID
- * byte 1-2: data offset (aligned to 0x10)
- * byte 3-4: data size (aligned to 0x10)
- * byte 5-...: calibration data
- */
- ReadCalibrationData = 0x11,
-};
-
-ExtraHID::ExtraHID(SendFunc send_func) : IRDevice(send_func) {
- LoadInputDevices();
-
- // The data below was retrieved from a New 3DS
- // TODO(wwylele): this data is probably writable (via request 3?) and thus should be saved to
- // and loaded from somewhere.
- calibration_data = std::array<u8, 0x40>{{
- // 0x00
- 0x00, 0x00, 0x08, 0x80, 0x85, 0xEB, 0x11, 0x3F,
- // 0x08
- 0x85, 0xEB, 0x11, 0x3F, 0xFF, 0xFF, 0xFF, 0xF5,
- // 0x10
- 0xFF, 0x00, 0x08, 0x80, 0x85, 0xEB, 0x11, 0x3F,
- // 0x18
- 0x85, 0xEB, 0x11, 0x3F, 0xFF, 0xFF, 0xFF, 0x65,
- // 0x20
- 0xFF, 0x00, 0x08, 0x80, 0x85, 0xEB, 0x11, 0x3F,
- // 0x28
- 0x85, 0xEB, 0x11, 0x3F, 0xFF, 0xFF, 0xFF, 0x65,
- // 0x30
- 0xFF, 0x00, 0x08, 0x80, 0x85, 0xEB, 0x11, 0x3F,
- // 0x38
- 0x85, 0xEB, 0x11, 0x3F, 0xFF, 0xFF, 0xFF, 0x65,
- }};
-
- hid_polling_callback_id =
- CoreTiming::RegisterEvent("ExtraHID::SendHIDStatus", [this](u64, int cycles_late) {
- SendHIDStatus();
- CoreTiming::ScheduleEvent(msToCycles(hid_period) - cycles_late,
- hid_polling_callback_id);
- });
-}
-
-ExtraHID::~ExtraHID() {
- OnDisconnect();
-}
-
-void ExtraHID::OnConnect() {}
-
-void ExtraHID::OnDisconnect() {
- CoreTiming::UnscheduleEvent(hid_polling_callback_id, 0);
-}
-
-void ExtraHID::HandleConfigureHIDPollingRequest(const std::vector<u8>& request) {
- if (request.size() != 3) {
- LOG_ERROR(Service_IR, "Wrong request size (%zu): %s", request.size(),
- Common::ArrayToString(request.data(), request.size()).c_str());
- return;
- }
-
- // Change HID input polling interval
- CoreTiming::UnscheduleEvent(hid_polling_callback_id, 0);
- hid_period = request[1];
- CoreTiming::ScheduleEvent(msToCycles(hid_period), hid_polling_callback_id);
-}
-
-void ExtraHID::HandleReadCalibrationDataRequest(const std::vector<u8>& request_buf) {
- struct ReadCalibrationDataRequest {
- RequestID request_id;
- u8 expected_response_time;
- u16_le offset;
- u16_le size;
- };
- static_assert(sizeof(ReadCalibrationDataRequest) == 6,
- "ReadCalibrationDataRequest has wrong size");
-
- if (request_buf.size() != sizeof(ReadCalibrationDataRequest)) {
- LOG_ERROR(Service_IR, "Wrong request size (%zu): %s", request_buf.size(),
- Common::ArrayToString(request_buf.data(), request_buf.size()).c_str());
- return;
- }
-
- ReadCalibrationDataRequest request;
- std::memcpy(&request, request_buf.data(), sizeof(request));
-
- const u16 offset = Common::AlignDown(request.offset, 16);
- const u16 size = Common::AlignDown(request.size, 16);
-
- if (offset + size > calibration_data.size()) {
- LOG_ERROR(Service_IR, "Read beyond the end of calibration data! (offset=%u, size=%u)",
- offset, size);
- return;
- }
-
- std::vector<u8> response(5);
- response[0] = static_cast<u8>(ResponseID::ReadCalibrationData);
- std::memcpy(&response[1], &request.offset, sizeof(request.offset));
- std::memcpy(&response[3], &request.size, sizeof(request.size));
- response.insert(response.end(), calibration_data.begin() + offset,
- calibration_data.begin() + offset + size);
- Send(response);
-}
-
-void ExtraHID::OnReceive(const std::vector<u8>& data) {
- switch (static_cast<RequestID>(data[0])) {
- case RequestID::ConfigureHIDPolling:
- HandleConfigureHIDPollingRequest(data);
- break;
- case RequestID::ReadCalibrationData:
- HandleReadCalibrationDataRequest(data);
- break;
- default:
- LOG_ERROR(Service_IR, "Unknown request: %s",
- Common::ArrayToString(data.data(), data.size()).c_str());
- break;
- }
-}
-
-void ExtraHID::SendHIDStatus() {
- if (is_device_reload_pending.exchange(false))
- LoadInputDevices();
-
- struct {
- union {
- BitField<0, 8, u32_le> header;
- BitField<8, 12, u32_le> c_stick_x;
- BitField<20, 12, u32_le> c_stick_y;
- } c_stick;
- union {
- BitField<0, 5, u8> battery_level;
- BitField<5, 1, u8> zl_not_held;
- BitField<6, 1, u8> zr_not_held;
- BitField<7, 1, u8> r_not_held;
- } buttons;
- u8 unknown;
- } response;
- static_assert(sizeof(response) == 6, "HID status response has wrong size!");
-
- constexpr int C_STICK_CENTER = 0x800;
- // TODO(wwylele): this value is not accurately measured. We currently assume that the axis can
- // take values in the whole range of a 12-bit integer.
- constexpr int C_STICK_RADIUS = 0x7FF;
-
- float x, y;
- std::tie(x, y) = c_stick->GetStatus();
-
- response.c_stick.header.Assign(static_cast<u8>(ResponseID::PollHID));
- response.c_stick.c_stick_x.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * x));
- response.c_stick.c_stick_y.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * y));
- response.buttons.battery_level.Assign(0x1F);
- response.buttons.zl_not_held.Assign(!zl->GetStatus());
- response.buttons.zr_not_held.Assign(!zr->GetStatus());
- response.buttons.r_not_held.Assign(1);
- response.unknown = 0;
-
- std::vector<u8> response_buffer(sizeof(response));
- memcpy(response_buffer.data(), &response, sizeof(response));
- Send(response_buffer);
-}
-
-void ExtraHID::RequestInputDevicesReload() {
- is_device_reload_pending.store(true);
-}
-
-void ExtraHID::LoadInputDevices() {
- zl = Input::CreateDevice<Input::ButtonDevice>(
- Settings::values.buttons[Settings::NativeButton::ZL]);
- zr = Input::CreateDevice<Input::ButtonDevice>(
- Settings::values.buttons[Settings::NativeButton::ZR]);
- c_stick = Input::CreateDevice<Input::AnalogDevice>(
- Settings::values.analogs[Settings::NativeAnalog::CStick]);
-}
-
-} // namespace IR
-} // namespace Service
diff --git a/src/core/hle/service/ir/extra_hid.h b/src/core/hle/service/ir/extra_hid.h
deleted file mode 100644
index a2459a73a..000000000
--- a/src/core/hle/service/ir/extra_hid.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <array>
-#include <atomic>
-#include "core/frontend/input.h"
-#include "core/hle/service/ir/ir_user.h"
-
-namespace Service {
-namespace IR {
-
-/**
- * An IRDevice emulating Circle Pad Pro or New 3DS additional HID hardware.
- * This device sends periodic udates at a rate configured by the 3DS, and sends calibration data if
- * requested.
- */
-class ExtraHID final : public IRDevice {
-public:
- explicit ExtraHID(SendFunc send_func);
- ~ExtraHID();
-
- void OnConnect() override;
- void OnDisconnect() override;
- void OnReceive(const std::vector<u8>& data) override;
-
- /// Requests input devices reload from current settings. Called when the input settings change.
- void RequestInputDevicesReload();
-
-private:
- void SendHIDStatus();
- void HandleConfigureHIDPollingRequest(const std::vector<u8>& request);
- void HandleReadCalibrationDataRequest(const std::vector<u8>& request);
- void LoadInputDevices();
-
- u8 hid_period;
- int hid_polling_callback_id;
- std::array<u8, 0x40> calibration_data;
- std::unique_ptr<Input::ButtonDevice> zl;
- std::unique_ptr<Input::ButtonDevice> zr;
- std::unique_ptr<Input::AnalogDevice> c_stick;
- std::atomic<bool> is_device_reload_pending;
-};
-
-} // namespace IR
-} // namespace Service
diff --git a/src/core/hle/service/ir/ir.cpp b/src/core/hle/service/ir/ir.cpp
deleted file mode 100644
index f06dd552f..000000000
--- a/src/core/hle/service/ir/ir.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/service/ir/ir.h"
-#include "core/hle/service/ir/ir_rst.h"
-#include "core/hle/service/ir/ir_u.h"
-#include "core/hle/service/ir/ir_user.h"
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace IR {
-
-void Init() {
- AddService(new IR_RST_Interface);
- AddService(new IR_U_Interface);
- AddService(new IR_User_Interface);
-
- InitUser();
- InitRST();
-}
-
-void Shutdown() {
- ShutdownUser();
- ShutdownRST();
-}
-
-void ReloadInputDevices() {
- ReloadInputDevicesUser();
- ReloadInputDevicesRST();
-}
-
-} // namespace IR
-
-} // namespace Service
diff --git a/src/core/hle/service/ir/ir.h b/src/core/hle/service/ir/ir.h
deleted file mode 100644
index 6be3e950c..000000000
--- a/src/core/hle/service/ir/ir.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-namespace Service {
-
-class Interface;
-
-namespace IR {
-
-/// Initialize IR service
-void Init();
-
-/// Shutdown IR service
-void Shutdown();
-
-/// Reload input devices. Used when input configuration changed
-void ReloadInputDevices();
-
-} // namespace IR
-} // namespace Service
diff --git a/src/core/hle/service/ir/ir_rst.cpp b/src/core/hle/service/ir/ir_rst.cpp
deleted file mode 100644
index 0912d5756..000000000
--- a/src/core/hle/service/ir/ir_rst.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <atomic>
-#include "common/bit_field.h"
-#include "core/core_timing.h"
-#include "core/frontend/input.h"
-#include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-#include "core/hle/service/hid/hid.h"
-#include "core/hle/service/ir/ir.h"
-#include "core/hle/service/ir/ir_rst.h"
-#include "core/settings.h"
-
-namespace Service {
-namespace IR {
-
-union PadState {
- u32_le hex{};
-
- BitField<14, 1, u32_le> zl;
- BitField<15, 1, u32_le> zr;
-
- BitField<24, 1, u32_le> c_stick_right;
- BitField<25, 1, u32_le> c_stick_left;
- BitField<26, 1, u32_le> c_stick_up;
- BitField<27, 1, u32_le> c_stick_down;
-};
-
-struct PadDataEntry {
- PadState current_state;
- PadState delta_additions;
- PadState delta_removals;
-
- s16_le c_stick_x;
- s16_le c_stick_y;
-};
-
-struct SharedMem {
- u64_le index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0
- u64_le index_reset_ticks_previous; ///< Previous `index_reset_ticks`
- u32_le index;
- INSERT_PADDING_WORDS(1);
- std::array<PadDataEntry, 8> entries; ///< Last 8 pad entries
-};
-
-static_assert(sizeof(SharedMem) == 0x98, "SharedMem has wrong size!");
-
-static Kernel::SharedPtr<Kernel::Event> update_event;
-static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
-static u32 next_pad_index;
-static int update_callback_id;
-static std::unique_ptr<Input::ButtonDevice> zl_button;
-static std::unique_ptr<Input::ButtonDevice> zr_button;
-static std::unique_ptr<Input::AnalogDevice> c_stick;
-static std::atomic<bool> is_device_reload_pending;
-static bool raw_c_stick;
-static int update_period;
-
-static void LoadInputDevices() {
- zl_button = Input::CreateDevice<Input::ButtonDevice>(
- Settings::values.buttons[Settings::NativeButton::ZL]);
- zr_button = Input::CreateDevice<Input::ButtonDevice>(
- Settings::values.buttons[Settings::NativeButton::ZR]);
- c_stick = Input::CreateDevice<Input::AnalogDevice>(
- Settings::values.analogs[Settings::NativeAnalog::CStick]);
-}
-
-static void UnloadInputDevices() {
- zl_button = nullptr;
- zr_button = nullptr;
- c_stick = nullptr;
-}
-
-static void UpdateCallback(u64 userdata, int cycles_late) {
- SharedMem* mem = reinterpret_cast<SharedMem*>(shared_memory->GetPointer());
-
- if (is_device_reload_pending.exchange(false))
- LoadInputDevices();
-
- PadState state;
- state.zl.Assign(zl_button->GetStatus());
- state.zr.Assign(zr_button->GetStatus());
-
- // Get current c-stick position and update c-stick direction
- float c_stick_x_f, c_stick_y_f;
- std::tie(c_stick_x_f, c_stick_y_f) = c_stick->GetStatus();
- constexpr int MAX_CSTICK_RADIUS = 0x9C; // Max value for a c-stick radius
- const s16 c_stick_x = static_cast<s16>(c_stick_x_f * MAX_CSTICK_RADIUS);
- const s16 c_stick_y = static_cast<s16>(c_stick_y_f * MAX_CSTICK_RADIUS);
-
- if (!raw_c_stick) {
- const HID::DirectionState direction = HID::GetStickDirectionState(c_stick_x, c_stick_y);
- state.c_stick_up.Assign(direction.up);
- state.c_stick_down.Assign(direction.down);
- state.c_stick_left.Assign(direction.left);
- state.c_stick_right.Assign(direction.right);
- }
-
- // TODO (wwylele): implement raw C-stick data for raw_c_stick = true
-
- const u32 last_entry_index = mem->index;
- mem->index = next_pad_index;
- next_pad_index = (next_pad_index + 1) % mem->entries.size();
-
- // Get the previous Pad state
- PadState old_state{mem->entries[last_entry_index].current_state};
-
- // Compute bitmask with 1s for bits different from the old state
- PadState changed = {state.hex ^ old_state.hex};
-
- // Get the current Pad entry
- PadDataEntry& pad_entry = mem->entries[mem->index];
-
- // Update entry properties
- pad_entry.current_state.hex = state.hex;
- pad_entry.delta_additions.hex = changed.hex & state.hex;
- pad_entry.delta_removals.hex = changed.hex & old_state.hex;
- pad_entry.c_stick_x = c_stick_x;
- pad_entry.c_stick_y = c_stick_y;
-
- // If we just updated index 0, provide a new timestamp
- if (mem->index == 0) {
- mem->index_reset_ticks_previous = mem->index_reset_ticks;
- mem->index_reset_ticks = CoreTiming::GetTicks();
- }
-
- update_event->Signal();
-
- // Reschedule recurrent event
- CoreTiming::ScheduleEvent(msToCycles(update_period) - cycles_late, update_callback_id);
-}
-
-/**
- * IR::GetHandles service function
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : Translate header, used by the ARM11-kernel
- * 3 : Shared memory handle
- * 4 : Event handle
- */
-static void GetHandles(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x01, 0, 0);
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 3);
- rb.Push(RESULT_SUCCESS);
- rb.PushMoveHandles(Kernel::g_handle_table.Create(Service::IR::shared_memory).Unwrap(),
- Kernel::g_handle_table.Create(Service::IR::update_event).Unwrap());
-}
-
-/**
- * IR::Initialize service function
- * Inputs:
- * 1 : pad state update period in ms
- * 2 : bool output raw c-stick data
- */
-static void Initialize(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x02, 2, 0);
- update_period = static_cast<int>(rp.Pop<u32>());
- raw_c_stick = rp.Pop<bool>();
-
- if (raw_c_stick)
- LOG_ERROR(Service_IR, "raw C-stick data is not implemented!");
-
- next_pad_index = 0;
- is_device_reload_pending.store(true);
- CoreTiming::ScheduleEvent(msToCycles(update_period), update_callback_id);
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
- rb.Push(RESULT_SUCCESS);
-
- LOG_DEBUG(Service_IR, "called. update_period=%d, raw_c_stick=%d", update_period, raw_c_stick);
-}
-
-static void Shutdown(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x03, 1, 0);
-
- CoreTiming::UnscheduleEvent(update_callback_id, 0);
- UnloadInputDevices();
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
- rb.Push(RESULT_SUCCESS);
- LOG_DEBUG(Service_IR, "called");
-}
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x00010000, GetHandles, "GetHandles"},
- {0x00020080, Initialize, "Initialize"},
- {0x00030000, Shutdown, "Shutdown"},
- {0x00090000, nullptr, "WriteToTwoFields"},
-};
-
-IR_RST_Interface::IR_RST_Interface() {
- Register(FunctionTable);
-}
-
-void InitRST() {
- using namespace Kernel;
- // Note: these two kernel objects are even available before Initialize service function is
- // called.
- shared_memory =
- SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read,
- 0, MemoryRegion::BASE, "IRRST:SharedMemory");
- update_event = Event::Create(ResetType::OneShot, "IRRST:UpdateEvent");
-
- update_callback_id = CoreTiming::RegisterEvent("IRRST:UpdateCallBack", UpdateCallback);
-}
-
-void ShutdownRST() {
- shared_memory = nullptr;
- update_event = nullptr;
- UnloadInputDevices();
-}
-
-void ReloadInputDevicesRST() {
- is_device_reload_pending.store(true);
-}
-
-} // namespace IR
-} // namespace Service
diff --git a/src/core/hle/service/ir/ir_rst.h b/src/core/hle/service/ir/ir_rst.h
deleted file mode 100644
index d932bb7e5..000000000
--- a/src/core/hle/service/ir/ir_rst.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included..
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace IR {
-
-class IR_RST_Interface : public Service::Interface {
-public:
- IR_RST_Interface();
-
- std::string GetPortName() const override {
- return "ir:rst";
- }
-};
-
-void InitRST();
-void ShutdownRST();
-
-/// Reload input devices. Used when input configuration changed
-void ReloadInputDevicesRST();
-
-} // namespace IR
-} // namespace Service
diff --git a/src/core/hle/service/ir/ir_u.cpp b/src/core/hle/service/ir/ir_u.cpp
deleted file mode 100644
index ce00d5732..000000000
--- a/src/core/hle/service/ir/ir_u.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/service/ir/ir_u.h"
-
-namespace Service {
-namespace IR {
-
-const Interface::FunctionInfo FunctionTable[] = {
- // clang-format off
- {0x00010000, nullptr, "Initialize"},
- {0x00020000, nullptr, "Shutdown"},
- {0x00030042, nullptr, "StartSendTransfer"},
- {0x00040000, nullptr, "WaitSendTransfer"},
- {0x000500C2, nullptr, "StartRecvTransfer"},
- {0x00060000, nullptr, "WaitRecvTransfer"},
- {0x00070080, nullptr, "GetRecvTransferCount"},
- {0x00080000, nullptr, "GetSendState"},
- {0x00090040, nullptr, "SetBitRate"},
- {0x000A0000, nullptr, "GetBitRate"},
- {0x000B0040, nullptr, "SetIRLEDState"},
- {0x000C0000, nullptr, "GetIRLEDRecvState"},
- {0x000D0000, nullptr, "GetSendFinishedEvent"},
- {0x000E0000, nullptr, "GetRecvFinishedEvent"},
- {0x000F0000, nullptr, "GetTransferState"},
- {0x00100000, nullptr, "GetErrorStatus"},
- {0x00110040, nullptr, "SetSleepModeActive"},
- {0x00120040, nullptr, "SetSleepModeState"},
- // clang-format on
-};
-
-IR_U_Interface::IR_U_Interface() {
- Register(FunctionTable);
-}
-
-} // namespace IR
-} // namespace Service
diff --git a/src/core/hle/service/ir/ir_u.h b/src/core/hle/service/ir/ir_u.h
deleted file mode 100644
index 056d2ce1a..000000000
--- a/src/core/hle/service/ir/ir_u.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace IR {
-
-class IR_U_Interface : public Service::Interface {
-public:
- IR_U_Interface();
-
- std::string GetPortName() const override {
- return "ir:u";
- }
-};
-
-} // namespace IR
-} // namespace Service
diff --git a/src/core/hle/service/ir/ir_user.cpp b/src/core/hle/service/ir/ir_user.cpp
deleted file mode 100644
index fbdf7a465..000000000
--- a/src/core/hle/service/ir/ir_user.cpp
+++ /dev/null
@@ -1,558 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <memory>
-#include <boost/crc.hpp>
-#include <boost/optional.hpp>
-#include "common/string_util.h"
-#include "common/swap.h"
-#include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/shared_memory.h"
-#include "core/hle/service/ir/extra_hid.h"
-#include "core/hle/service/ir/ir.h"
-#include "core/hle/service/ir/ir_user.h"
-
-namespace Service {
-namespace IR {
-
-// This is a header that will present in the ir:USER shared memory if it is initialized with
-// InitializeIrNopShared service function. Otherwise the shared memory doesn't have this header if
-// it is initialized with InitializeIrNop service function.
-struct SharedMemoryHeader {
- u32_le latest_receive_error_result;
- u32_le latest_send_error_result;
- // TODO(wwylele): for these fields below, make them enum when the meaning of values is known.
- u8 connection_status;
- u8 trying_to_connect_status;
- u8 connection_role;
- u8 machine_id;
- u8 connected;
- u8 network_id;
- u8 initialized;
- u8 unknown;
-
- // This is not the end of the shared memory. It is followed by a receive buffer and a send
- // buffer. We handle receive buffer in the BufferManager class. For the send buffer, because
- // games usually don't access it, we don't emulate it.
-};
-static_assert(sizeof(SharedMemoryHeader) == 16, "SharedMemoryHeader has wrong size!");
-
-/**
- * A manager of the send/receive buffers in the shared memory. Currently it is only used for the
- * receive buffer.
- *
- * A buffer consists of three parts:
- * - BufferInfo: stores available count of packets, and their position in the PacketInfo
- * circular queue.
- * - PacketInfo circular queue: stores the position of each avaiable packets in the Packet data
- * buffer. Each entry is a pair of {offset, size}.
- * - Packet data circular buffer: stores the actual data of packets.
- *
- * IR packets can be put into and get from the buffer.
- *
- * When a new packet is put into the buffer, its data is put into the data circular buffer,
- * following the end of previous packet data. A new entry is also added to the PacketInfo circular
- * queue pointing to the added packet data. Then BufferInfo is updated.
- *
- * Packets can be released from the other end of the buffer. When releasing a packet, the front
- * entry in thePacketInfo circular queue is removed, and as a result the corresponding memory in the
- * data circular buffer is also released. BufferInfo is updated as well.
- *
- * The client application usually has a similar manager constructed over the same shared memory
- * region, performing the same put/get/release operation. This way the client and the service
- * communicate via a pair of manager of the same buffer.
- *
- * TODO(wwylele): implement Get function, which is used by ReceiveIrnop service function.
- */
-class BufferManager {
-public:
- BufferManager(Kernel::SharedPtr<Kernel::SharedMemory> shared_memory_, u32 info_offset_,
- u32 buffer_offset_, u32 max_packet_count_, u32 buffer_size)
- : shared_memory(shared_memory_), info_offset(info_offset_), buffer_offset(buffer_offset_),
- max_packet_count(max_packet_count_),
- max_data_size(buffer_size - sizeof(PacketInfo) * max_packet_count_) {
- UpdateBufferInfo();
- }
-
- /**
- * Puts a packet to the head of the buffer.
- * @params packet The data of the packet to put.
- * @returns whether the operation is successful.
- */
- bool Put(const std::vector<u8>& packet) {
- if (info.packet_count == max_packet_count)
- return false;
-
- u32 write_offset;
-
- // finds free space offset in data buffer
- if (info.packet_count == 0) {
- write_offset = 0;
- if (packet.size() > max_data_size)
- return false;
- } else {
- const u32 last_index = (info.end_index + max_packet_count - 1) % max_packet_count;
- const PacketInfo first = GetPacketInfo(info.begin_index);
- const PacketInfo last = GetPacketInfo(last_index);
- write_offset = (last.offset + last.size) % max_data_size;
- const u32 free_space = (first.offset + max_data_size - write_offset) % max_data_size;
- if (packet.size() > free_space)
- return false;
- }
-
- // writes packet info
- PacketInfo packet_info{write_offset, static_cast<u32>(packet.size())};
- SetPacketInfo(info.end_index, packet_info);
-
- // writes packet data
- for (size_t i = 0; i < packet.size(); ++i) {
- *GetDataBufferPointer((write_offset + i) % max_data_size) = packet[i];
- }
-
- // updates buffer info
- info.end_index++;
- info.end_index %= max_packet_count;
- info.packet_count++;
- UpdateBufferInfo();
- return true;
- }
-
- /**
- * Release packets from the tail of the buffer
- * @params count Numbers of packets to release.
- * @returns whether the operation is successful.
- */
- bool Release(u32 count) {
- if (info.packet_count < count)
- return false;
-
- info.packet_count -= count;
- info.begin_index += count;
- info.begin_index %= max_packet_count;
- UpdateBufferInfo();
- return true;
- }
-
-private:
- struct BufferInfo {
- u32_le begin_index;
- u32_le end_index;
- u32_le packet_count;
- u32_le unknown;
- };
- static_assert(sizeof(BufferInfo) == 16, "BufferInfo has wrong size!");
-
- struct PacketInfo {
- u32_le offset;
- u32_le size;
- };
- static_assert(sizeof(PacketInfo) == 8, "PacketInfo has wrong size!");
-
- u8* GetPacketInfoPointer(u32 index) {
- return shared_memory->GetPointer(buffer_offset + sizeof(PacketInfo) * index);
- }
-
- void SetPacketInfo(u32 index, const PacketInfo& packet_info) {
- memcpy(GetPacketInfoPointer(index), &packet_info, sizeof(PacketInfo));
- }
-
- PacketInfo GetPacketInfo(u32 index) {
- PacketInfo packet_info;
- memcpy(&packet_info, GetPacketInfoPointer(index), sizeof(PacketInfo));
- return packet_info;
- }
-
- u8* GetDataBufferPointer(u32 offset) {
- return shared_memory->GetPointer(buffer_offset + sizeof(PacketInfo) * max_packet_count +
- offset);
- }
-
- void UpdateBufferInfo() {
- if (info_offset) {
- memcpy(shared_memory->GetPointer(info_offset), &info, sizeof(info));
- }
- }
-
- BufferInfo info{0, 0, 0, 0};
- Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
- u32 info_offset;
- u32 buffer_offset;
- u32 max_packet_count;
- u32 max_data_size;
-};
-
-static Kernel::SharedPtr<Kernel::Event> conn_status_event, send_event, receive_event;
-static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
-static std::unique_ptr<ExtraHID> extra_hid;
-static IRDevice* connected_device;
-static boost::optional<BufferManager> receive_buffer;
-
-/// Wraps the payload into packet and puts it to the receive buffer
-static void PutToReceive(const std::vector<u8>& payload) {
- LOG_TRACE(Service_IR, "called, data=%s",
- Common::ArrayToString(payload.data(), payload.size()).c_str());
- size_t size = payload.size();
-
- std::vector<u8> packet;
-
- // Builds packet header. For the format info:
- // https://www.3dbrew.org/wiki/IRUSER_Shared_Memory#Packet_structure
-
- // fixed value
- packet.push_back(0xA5);
- // destination network ID
- u8 network_id = *(shared_memory->GetPointer(offsetof(SharedMemoryHeader, network_id)));
- packet.push_back(network_id);
-
- // puts the size info.
- // The highest bit of the first byte is unknown, which is set to zero here. The second highest
- // bit is a flag that determines whether the size info is in extended form. If the packet size
- // can be represent within 6 bits, the short form (1 byte) of size info is chosen, the size is
- // put to the lower bits of this byte, and the flag is clear. If the packet size cannot be
- // represent within 6 bits, the extended form (2 bytes) is chosen, the lower 8 bits of the size
- // is put to the second byte, the higher bits of the size is put to the lower bits of the first
- // byte, and the flag is set. Note that the packet size must be within 14 bits due to this
- // format restriction, or it will overlap with the flag bit.
- if (size < 0x40) {
- packet.push_back(static_cast<u8>(size));
- } else if (size < 0x4000) {
- packet.push_back(static_cast<u8>(size >> 8) | 0x40);
- packet.push_back(static_cast<u8>(size));
- } else {
- ASSERT(false);
- }
-
- // puts the payload
- packet.insert(packet.end(), payload.begin(), payload.end());
-
- // calculates CRC and puts to the end
- packet.push_back(boost::crc<8, 0x07, 0, 0, false, false>(packet.data(), packet.size()));
-
- if (receive_buffer->Put(packet)) {
- receive_event->Signal();
- } else {
- LOG_ERROR(Service_IR, "receive buffer is full!");
- }
-}
-
-/**
- * IR::InitializeIrNopShared service function
- * Initializes ir:USER service with a user provided shared memory. The shared memory is configured
- * to shared mode (with SharedMemoryHeader at the beginning of the shared memory).
- * Inputs:
- * 1 : Size of shared memory
- * 2 : Recv buffer size
- * 3 : Recv buffer packet count
- * 4 : Send buffer size
- * 5 : Send buffer packet count
- * 6 : BaudRate (u8)
- * 7 : 0 (Handle descriptor)
- * 8 : Handle of shared memory
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void InitializeIrNopShared(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x18, 6, 2);
- const u32 shared_buff_size = rp.Pop<u32>();
- const u32 recv_buff_size = rp.Pop<u32>();
- const u32 recv_buff_packet_count = rp.Pop<u32>();
- const u32 send_buff_size = rp.Pop<u32>();
- const u32 send_buff_packet_count = rp.Pop<u32>();
- const u8 baud_rate = rp.Pop<u8>();
- const Kernel::Handle handle = rp.PopHandle();
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
-
- shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle);
- if (!shared_memory) {
- LOG_CRITICAL(Service_IR, "invalid shared memory handle 0x%08X", handle);
- rb.Push(IPC::ERR_INVALID_HANDLE);
- return;
- }
- shared_memory->name = "IR_USER: shared memory";
-
- receive_buffer =
- BufferManager(shared_memory, 0x10, 0x20, recv_buff_packet_count, recv_buff_size);
- SharedMemoryHeader shared_memory_init{};
- shared_memory_init.initialized = 1;
- std::memcpy(shared_memory->GetPointer(), &shared_memory_init, sizeof(SharedMemoryHeader));
-
- rb.Push(RESULT_SUCCESS);
-
- LOG_INFO(Service_IR, "called, shared_buff_size=%u, recv_buff_size=%u, "
- "recv_buff_packet_count=%u, send_buff_size=%u, "
- "send_buff_packet_count=%u, baud_rate=%u, handle=0x%08X",
- shared_buff_size, recv_buff_size, recv_buff_packet_count, send_buff_size,
- send_buff_packet_count, baud_rate, handle);
-}
-
-/**
- * IR::RequireConnection service function
- * Searches for an IR device and connects to it. After connecting to the device, applications can
- * use SendIrNop function, ReceiveIrNop function (or read from the buffer directly) to communicate
- * with the device.
- * Inputs:
- * 1 : device ID? always 1 for circle pad pro
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void RequireConnection(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x06, 1, 0);
- const u8 device_id = rp.Pop<u8>();
-
- u8* shared_memory_ptr = shared_memory->GetPointer();
- if (device_id == 1) {
- // These values are observed on a New 3DS. The meaning of them is unclear.
- // TODO (wwylele): should assign network_id a (random?) number
- shared_memory_ptr[offsetof(SharedMemoryHeader, connection_status)] = 2;
- shared_memory_ptr[offsetof(SharedMemoryHeader, connection_role)] = 2;
- shared_memory_ptr[offsetof(SharedMemoryHeader, connected)] = 1;
-
- connected_device = extra_hid.get();
- connected_device->OnConnect();
- conn_status_event->Signal();
- } else {
- LOG_WARNING(Service_IR, "unknown device id %u. Won't connect.", device_id);
- shared_memory_ptr[offsetof(SharedMemoryHeader, connection_status)] = 1;
- shared_memory_ptr[offsetof(SharedMemoryHeader, trying_to_connect_status)] = 2;
- }
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
- rb.Push(RESULT_SUCCESS);
-
- LOG_INFO(Service_IR, "called, device_id = %u", device_id);
-}
-
-/**
- * IR::GetReceiveEvent service function
- * Gets an event that is signaled when a packet is received from the IR device.
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : 0 (Handle descriptor)
- * 3 : Receive event handle
- */
-void GetReceiveEvent(Interface* self) {
- IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0A, 1, 2);
-
- rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::receive_event).Unwrap());
-
- LOG_INFO(Service_IR, "called");
-}
-
-/**
- * IR::GetSendEvent service function
- * Gets an event that is signaled when the sending of a packet is complete
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : 0 (Handle descriptor)
- * 3 : Send event handle
- */
-void GetSendEvent(Interface* self) {
- IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0B, 1, 2);
-
- rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::send_event).Unwrap());
-
- LOG_INFO(Service_IR, "called");
-}
-
-/**
- * IR::Disconnect service function
- * Disconnects from the current connected IR device.
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void Disconnect(Interface* self) {
- if (connected_device) {
- connected_device->OnDisconnect();
- connected_device = nullptr;
- conn_status_event->Signal();
- }
-
- u8* shared_memory_ptr = shared_memory->GetPointer();
- shared_memory_ptr[offsetof(SharedMemoryHeader, connection_status)] = 0;
- shared_memory_ptr[offsetof(SharedMemoryHeader, connected)] = 0;
-
- IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x09, 1, 0);
- rb.Push(RESULT_SUCCESS);
-
- LOG_INFO(Service_IR, "called");
-}
-
-/**
- * IR::GetConnectionStatusEvent service function
- * Gets an event that is signaled when the connection status is changed
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : 0 (Handle descriptor)
- * 3 : Connection Status Event handle
- */
-static void GetConnectionStatusEvent(Interface* self) {
- IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x0C, 1, 2);
-
- rb.Push(RESULT_SUCCESS);
- rb.PushCopyHandles(Kernel::g_handle_table.Create(Service::IR::conn_status_event).Unwrap());
-
- LOG_INFO(Service_IR, "called");
-}
-
-/**
- * IR::FinalizeIrNop service function
- * Finalize ir:USER service.
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void FinalizeIrNop(Interface* self) {
- if (connected_device) {
- connected_device->OnDisconnect();
- connected_device = nullptr;
- }
-
- shared_memory = nullptr;
- receive_buffer = boost::none;
-
- IPC::RequestBuilder rb(Kernel::GetCommandBuffer(), 0x02, 1, 0);
- rb.Push(RESULT_SUCCESS);
-
- LOG_INFO(Service_IR, "called");
-}
-
-/**
- * IR::SendIrNop service function
- * Sends a packet to the connected IR device
- * Inpus:
- * 1 : Size of data to send
- * 2 : 2 + (size << 14) (Static buffer descriptor)
- * 3 : Data buffer address
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void SendIrNop(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0D, 1, 2);
- const u32 size = rp.Pop<u32>();
- const VAddr address = rp.PopStaticBuffer();
-
- std::vector<u8> buffer(size);
- Memory::ReadBlock(address, buffer.data(), size);
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
- if (connected_device) {
- connected_device->OnReceive(buffer);
- send_event->Signal();
- rb.Push(RESULT_SUCCESS);
- } else {
- LOG_ERROR(Service_IR, "not connected");
- rb.Push(ResultCode(static_cast<ErrorDescription>(13), ErrorModule::IR,
- ErrorSummary::InvalidState, ErrorLevel::Status));
- }
-
- LOG_TRACE(Service_IR, "called, data=%s", Common::ArrayToString(buffer.data(), size).c_str());
-}
-
-/**
- * IR::ReleaseReceivedData function
- * Release a specified amount of packet from the receive buffer. This is called after the
- * application reads received packet from the buffer directly, to release the buffer space for
- * future packets.
- * Inpus:
- * 1 : Number of packets to release
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
-static void ReleaseReceivedData(Interface* self) {
- IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x19, 1, 0);
- u32 count = rp.Pop<u32>();
-
- IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
-
- if (receive_buffer->Release(count)) {
- rb.Push(RESULT_SUCCESS);
- } else {
- LOG_ERROR(Service_IR, "failed to release %u packets", count);
- rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::IR, ErrorSummary::NotFound,
- ErrorLevel::Status));
- }
-
- LOG_TRACE(Service_IR, "called, count=%u", count);
-}
-
-const Interface::FunctionInfo FunctionTable[] = {
- {0x00010182, nullptr, "InitializeIrNop"},
- {0x00020000, FinalizeIrNop, "FinalizeIrNop"},
- {0x00030000, nullptr, "ClearReceiveBuffer"},
- {0x00040000, nullptr, "ClearSendBuffer"},
- {0x000500C0, nullptr, "WaitConnection"},
- {0x00060040, RequireConnection, "RequireConnection"},
- {0x000702C0, nullptr, "AutoConnection"},
- {0x00080000, nullptr, "AnyConnection"},
- {0x00090000, Disconnect, "Disconnect"},
- {0x000A0000, GetReceiveEvent, "GetReceiveEvent"},
- {0x000B0000, GetSendEvent, "GetSendEvent"},
- {0x000C0000, GetConnectionStatusEvent, "GetConnectionStatusEvent"},
- {0x000D0042, SendIrNop, "SendIrNop"},
- {0x000E0042, nullptr, "SendIrNopLarge"},
- {0x000F0040, nullptr, "ReceiveIrnop"},
- {0x00100042, nullptr, "ReceiveIrnopLarge"},
- {0x00110040, nullptr, "GetLatestReceiveErrorResult"},
- {0x00120040, nullptr, "GetLatestSendErrorResult"},
- {0x00130000, nullptr, "GetConnectionStatus"},
- {0x00140000, nullptr, "GetTryingToConnectStatus"},
- {0x00150000, nullptr, "GetReceiveSizeFreeAndUsed"},
- {0x00160000, nullptr, "GetSendSizeFreeAndUsed"},
- {0x00170000, nullptr, "GetConnectionRole"},
- {0x00180182, InitializeIrNopShared, "InitializeIrNopShared"},
- {0x00190040, ReleaseReceivedData, "ReleaseReceivedData"},
- {0x001A0040, nullptr, "SetOwnMachineId"},
-};
-
-IR_User_Interface::IR_User_Interface() {
- Register(FunctionTable);
-}
-
-void InitUser() {
- using namespace Kernel;
-
- shared_memory = nullptr;
-
- conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent");
- send_event = Event::Create(ResetType::OneShot, "IR:SendEvent");
- receive_event = Event::Create(ResetType::OneShot, "IR:ReceiveEvent");
-
- receive_buffer = boost::none;
-
- extra_hid = std::make_unique<ExtraHID>(PutToReceive);
-
- connected_device = nullptr;
-}
-
-void ShutdownUser() {
- if (connected_device) {
- connected_device->OnDisconnect();
- connected_device = nullptr;
- }
-
- extra_hid = nullptr;
- receive_buffer = boost::none;
- shared_memory = nullptr;
- conn_status_event = nullptr;
- send_event = nullptr;
- receive_event = nullptr;
-}
-
-void ReloadInputDevicesUser() {
- if (extra_hid)
- extra_hid->RequestInputDevicesReload();
-}
-
-IRDevice::IRDevice(SendFunc send_func_) : send_func(send_func_) {}
-IRDevice::~IRDevice() = default;
-
-void IRDevice::Send(const std::vector<u8>& data) {
- send_func(data);
-}
-
-} // namespace IR
-} // namespace Service
diff --git a/src/core/hle/service/ir/ir_user.h b/src/core/hle/service/ir/ir_user.h
deleted file mode 100644
index 930650406..000000000
--- a/src/core/hle/service/ir/ir_user.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2015 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <functional>
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace IR {
-
-/// An interface representing a device that can communicate with 3DS via ir:USER service
-class IRDevice {
-public:
- /**
- * A function object that implements the method to send data to the 3DS, which takes a vector of
- * data to send.
- */
- using SendFunc = std::function<void(const std::vector<u8>& data)>;
-
- explicit IRDevice(SendFunc send_func);
- virtual ~IRDevice();
-
- /// Called when connected with 3DS
- virtual void OnConnect() = 0;
-
- /// Called when disconnected from 3DS
- virtual void OnDisconnect() = 0;
-
- /// Called when data is received from the 3DS. This is invoked by the ir:USER send function.
- virtual void OnReceive(const std::vector<u8>& data) = 0;
-
-protected:
- /// Sends data to the 3DS. The actual sending method is specified in the constructor
- void Send(const std::vector<u8>& data);
-
-private:
- const SendFunc send_func;
-};
-
-class IR_User_Interface : public Service::Interface {
-public:
- IR_User_Interface();
-
- std::string GetPortName() const override {
- return "ir:USER";
- }
-};
-
-void InitUser();
-void ShutdownUser();
-
-/// Reload input devices. Used when input configuration changed
-void ReloadInputDevicesUser();
-
-} // namespace IR
-} // namespace Service