1 // Copyright 2017 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include "Common/CommonTypes.h"
8 #include "Core/HW/WiimoteCommon/WiimoteConstants.h"
9 #include "Core/HW/WiimoteCommon/WiimoteReport.h"
10 
11 namespace WiimoteCommon
12 {
13 // Source: HID_010_SPC_PFL/1.0 (official HID specification)
14 
15 constexpr u8 HID_TYPE_HANDSHAKE = 0;
16 constexpr u8 HID_TYPE_SET_REPORT = 5;
17 constexpr u8 HID_TYPE_DATA = 0xA;
18 
19 constexpr u8 HID_HANDSHAKE_SUCCESS = 0;
20 
21 constexpr u8 HID_PARAM_INPUT = 1;
22 constexpr u8 HID_PARAM_OUTPUT = 2;
23 
24 class HIDWiimote
25 {
26 public:
27   using InterruptCallbackType = std::function<void(u8 hid_type, const u8* data, u32 size)>;
28 
29   virtual ~HIDWiimote() = default;
30 
31   virtual void EventLinked() = 0;
32   virtual void EventUnlinked() = 0;
33 
34   // Called every ~200hz after HID channels are established.
35   virtual void Update() = 0;
36 
SetInterruptCallback(InterruptCallbackType callback)37   void SetInterruptCallback(InterruptCallbackType callback) { m_callback = std::move(callback); }
38 
39   // HID report type:0xa2 (data output) payloads sent to the wiimote interrupt channel.
40   // Does not include HID-type header.
41   virtual void InterruptDataOutput(const u8* data, u32 size) = 0;
42 
43   // Used to connect a disconnected wii remote on button press.
44   virtual bool IsButtonPressed() = 0;
45 
46 protected:
InterruptDataInputCallback(const u8 * data,u32 size)47   void InterruptDataInputCallback(const u8* data, u32 size)
48   {
49     InterruptCallback((WiimoteCommon::HID_TYPE_DATA << 4) | WiimoteCommon::HID_PARAM_INPUT, data,
50                       size);
51   }
52 
InterruptCallback(u8 hid_type,const u8 * data,u32 size)53   void InterruptCallback(u8 hid_type, const u8* data, u32 size)
54   {
55     m_callback(hid_type, data, size);
56   }
57 
58 private:
59   InterruptCallbackType m_callback;
60 };
61 
62 #ifdef _MSC_VER
63 #pragma warning(push)
64 // Disable warning for zero-sized array:
65 #pragma warning(disable : 4200)
66 #endif
67 
68 #pragma pack(push, 1)
69 
70 template <typename T>
71 struct TypedInputData
72 {
TypedInputDataTypedInputData73   TypedInputData(InputReportID _rpt_id) : report_id(_rpt_id) {}
74 
75   InputReportID report_id;
76   T payload = {};
77 
78   static_assert(std::is_standard_layout_v<T> && std::is_trivially_copyable_v<T>);
79 
GetDataTypedInputData80   u8* GetData() { return reinterpret_cast<u8*>(this); }
GetDataTypedInputData81   const u8* GetData() const { return reinterpret_cast<const u8*>(this); }
GetSizeTypedInputData82   constexpr u32 GetSize() const { return sizeof(*this); }
83 };
84 
85 #pragma pack(pop)
86 
87 #ifdef _MSC_VER
88 #pragma warning(pop)
89 #endif
90 
91 }  // namespace WiimoteCommon
92