1 // Copyright 2008 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <cstddef>
8 #include <deque>
9 #include <memory>
10 #include <string>
11 #include <vector>
12 
13 #include "Common/CommonTypes.h"
14 #include "Core/HW/Wiimote.h"
15 #include "Core/IOS/Device.h"
16 #include "Core/IOS/IOS.h"
17 #include "Core/IOS/USB/Bluetooth/BTBase.h"
18 #include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
19 #include "Core/IOS/USB/Bluetooth/hci.h"
20 #include "Core/IOS/USB/USBV0.h"
21 
22 class PointerWrap;
23 
24 namespace IOS::HLE
25 {
26 struct SQueuedEvent
27 {
28   u8 buffer[1024] = {};
29   u32 size = 0;
30   u16 connection_handle = 0;
31 
32   SQueuedEvent(u32 size_, u16 handle);
33   SQueuedEvent() = default;
34 };
35 
36 namespace Device
37 {
38 // Important to remember that this class is for /dev/usb/oh1/57e/305 ONLY
39 // /dev/usb/oh1 -> internal usb bus
40 // 57e/305 -> VendorID/ProductID of device on usb bus
41 // This device is ONLY the internal Bluetooth module (based on BCM2045 chip)
42 class BluetoothEmu final : public BluetoothBase
43 {
44 public:
45   BluetoothEmu(Kernel& ios, const std::string& device_name);
46 
47   virtual ~BluetoothEmu();
48 
49   IPCCommandResult Close(u32 fd) override;
50   IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
51 
52   void Update() override;
53 
54   // Send ACL data back to Bluetooth stack
55   void SendACLPacket(const bdaddr_t& source, const u8* data, u32 size);
56 
57   // Returns true if controller is configured to see the connection request.
58   bool RemoteConnect(WiimoteDevice&);
59   bool RemoteDisconnect(const bdaddr_t& address);
60 
61   WiimoteDevice* AccessWiimoteByIndex(std::size_t index);
62 
63   void DoState(PointerWrap& p) override;
64 
65 private:
66   std::vector<std::unique_ptr<WiimoteDevice>> m_wiimotes;
67 
68   bdaddr_t m_controller_bd{{0x11, 0x02, 0x19, 0x79, 0x00, 0xff}};
69 
70   // this is used to trigger connecting via ACL
71   u8 m_scan_enable = 0;
72 
73   std::unique_ptr<USB::V0IntrMessage> m_hci_endpoint;
74   std::unique_ptr<USB::V0BulkMessage> m_acl_endpoint;
75   std::deque<SQueuedEvent> m_event_queue;
76 
77   class ACLPool
78   {
79   public:
ACLPool(Kernel & ios)80     explicit ACLPool(Kernel& ios) : m_ios(ios), m_queue() {}
81     void Store(const u8* data, const u16 size, const u16 conn_handle);
82 
83     void WriteToEndpoint(const USB::V0BulkMessage& endpoint);
84 
IsEmpty()85     bool IsEmpty() const { return m_queue.empty(); }
86     // For SaveStates
DoState(PointerWrap & p)87     void DoState(PointerWrap& p) { p.Do(m_queue); }
88 
89   private:
90     struct Packet
91     {
92       u8 data[ACL_PKT_SIZE];
93       u16 size;
94       u16 conn_handle;
95     };
96 
97     Kernel& m_ios;
98     std::deque<Packet> m_queue;
99   } m_acl_pool{m_ios};
100 
101   u32 m_packet_count[MAX_BBMOTES] = {};
102   u64 m_last_ticks = 0;
103 
104   static u16 GetConnectionHandle(const bdaddr_t&);
105 
106   WiimoteDevice* AccessWiimote(const bdaddr_t& address);
107   WiimoteDevice* AccessWiimote(u16 connection_handle);
108 
109   static u32 GetWiimoteNumberFromConnectionHandle(u16 connection_handle);
110 
111   // Send ACL data to a device (wiimote)
112   void IncDataPacket(u16 connection_handle);
113   void SendToDevice(u16 connection_handle, u8* data, u32 size);
114 
115   // Events
116   void AddEventToQueue(const SQueuedEvent& event);
117   bool SendEventCommandStatus(u16 opcode);
118   void SendEventCommandComplete(u16 opcode, const void* data, u32 data_size);
119   bool SendEventInquiryResponse();
120   bool SendEventInquiryComplete(u8 num_responses);
121   bool SendEventRemoteNameReq(const bdaddr_t& bd);
122   bool SendEventRequestConnection(const WiimoteDevice& wiimote);
123   bool SendEventConnectionComplete(const bdaddr_t& bd, u8 status);
124   bool SendEventReadClockOffsetComplete(u16 connection_handle);
125   bool SendEventConPacketTypeChange(u16 connection_handle, u16 packet_type);
126   bool SendEventReadRemoteVerInfo(u16 connection_handle);
127   bool SendEventReadRemoteFeatures(u16 connection_handle);
128   bool SendEventRoleChange(bdaddr_t bd, bool master);
129   bool SendEventNumberOfCompletedPackets();
130   bool SendEventAuthenticationCompleted(u16 connection_handle);
131   bool SendEventModeChange(u16 connection_handle, u8 mode, u16 value);
132   bool SendEventDisconnect(u16 connection_handle, u8 reason);
133   bool SendEventRequestLinkKey(const bdaddr_t& bd);
134   bool SendEventLinkKeyNotification(const u8 num_to_send);
135 
136   // Execute HCI Message
137   void ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl_message);
138 
139   // OGF 0x01 - Link control commands and return parameters
140   void CommandWriteInquiryMode(const u8* input);
141   void CommandWritePageScanType(const u8* input);
142   void CommandHostBufferSize(const u8* input);
143   void CommandInquiryCancel(const u8* input);
144   void CommandRemoteNameReq(const u8* input);
145   void CommandCreateCon(const u8* input);
146   void CommandAcceptCon(const u8* input);
147   void CommandReadClockOffset(const u8* input);
148   void CommandReadRemoteVerInfo(const u8* input);
149   void CommandReadRemoteFeatures(const u8* input);
150   void CommandAuthenticationRequested(const u8* input);
151   void CommandInquiry(const u8* input);
152   void CommandDisconnect(const u8* input);
153   void CommandLinkKeyNegRep(const u8* input);
154   void CommandLinkKeyRep(const u8* input);
155   void CommandDeleteStoredLinkKey(const u8* input);
156   void CommandChangeConPacketType(const u8* input);
157 
158   // OGF 0x02 - Link policy commands and return parameters
159   void CommandWriteLinkPolicy(const u8* input);
160   void CommandSniffMode(const u8* input);
161 
162   // OGF 0x03 - Host Controller and Baseband commands and return parameters
163   void CommandReset(const u8* input);
164   void CommandWriteLocalName(const u8* input);
165   void CommandWritePageTimeOut(const u8* input);
166   void CommandWriteScanEnable(const u8* input);
167   void CommandWriteUnitClass(const u8* input);
168   void CommandReadStoredLinkKey(const u8* input);
169   void CommandWritePinType(const u8* input);
170   void CommandSetEventFilter(const u8* input);
171   void CommandWriteInquiryScanType(const u8* input);
172   void CommandWriteLinkSupervisionTimeout(const u8* input);
173 
174   // OGF 0x04 - Informational commands and return parameters
175   void CommandReadBufferSize(const u8* input);
176   void CommandReadLocalVer(const u8* input);
177   void CommandReadLocalFeatures(const u8* input);
178   void CommandReadBDAdrr(const u8* input);
179 
180   // OGF 0x3F - Vendor specific
181   void CommandVendorSpecific_FC4C(const u8* input, u32 size);
182   void CommandVendorSpecific_FC4F(const u8* input, u32 size);
183 
184 #pragma pack(push, 1)
185 #define CONF_PAD_MAX_REGISTERED 10
186 
187   struct ConfPadDevice
188   {
189     u8 bdaddr[6];
190     char name[0x40];
191   };
192 
193   struct ConfPads
194   {
195     u8 num_registered;
196     ConfPadDevice registered[CONF_PAD_MAX_REGISTERED];
197     ConfPadDevice active[MAX_BBMOTES];
198     ConfPadDevice unknown;
199   };
200 #pragma pack(pop)
201 };
202 }  // namespace Device
203 }  // namespace IOS::HLE
204