1 // Copyright 2008 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #include "Core/IOS/USB/Bluetooth/BTEmu.h"
6 
7 #include <algorithm>
8 #include <cstring>
9 #include <memory>
10 #include <string>
11 
12 #include "Common/Assert.h"
13 #include "Common/Logging/Log.h"
14 #include "Common/MsgHandler.h"
15 #include "Common/NandPaths.h"
16 #include "Common/StringUtil.h"
17 #include "Core/Core.h"
18 #include "Core/CoreTiming.h"
19 #include "Core/Debugger/Debugger_SymbolMap.h"
20 #include "Core/HW/Memmap.h"
21 #include "Core/HW/SystemTimers.h"
22 #include "Core/HW/Wiimote.h"
23 #include "Core/IOS/Device.h"
24 #include "Core/IOS/IOS.h"
25 #include "Core/SysConf.h"
26 #include "InputCommon/ControllerInterface/ControllerInterface.h"
27 
28 namespace IOS::HLE
29 {
SQueuedEvent(u32 size_,u16 handle)30 SQueuedEvent::SQueuedEvent(u32 size_, u16 handle) : size(size_), connection_handle(handle)
31 {
32   if (size > 1024)
33     PanicAlert("SQueuedEvent: The size is too large.");
34 }
35 
36 namespace Device
37 {
BluetoothEmu(Kernel & ios,const std::string & device_name)38 BluetoothEmu::BluetoothEmu(Kernel& ios, const std::string& device_name)
39     : BluetoothBase(ios, device_name)
40 {
41   SysConf sysconf{ios.GetFS()};
42   if (!Core::WantsDeterminism())
43     BackUpBTInfoSection(&sysconf);
44 
45   ConfPads bt_dinf{};
46 
47   for (u8 i = 0; i != MAX_BBMOTES; ++i)
48   {
49     // Note: BluetoothEmu::GetConnectionHandle and WiimoteDevice::GetNumber rely on final byte.
50     const bdaddr_t tmp_bd = {0x11, 0x02, 0x19, 0x79, 0, i};
51 
52     // Previous records can be safely overwritten, since they are backed up
53     std::copy(tmp_bd.begin(), tmp_bd.end(), std::rbegin(bt_dinf.active[i].bdaddr));
54     std::copy(tmp_bd.begin(), tmp_bd.end(), std::rbegin(bt_dinf.registered[i].bdaddr));
55 
56     const auto& wm_name =
57         (i == WIIMOTE_BALANCE_BOARD) ? "Nintendo RVL-WBC-01" : "Nintendo RVL-CNT-01";
58     memcpy(bt_dinf.registered[i].name, wm_name, 20);
59     memcpy(bt_dinf.active[i].name, wm_name, 20);
60 
61     DEBUG_LOG(IOS_WIIMOTE, "Wii Remote %d BT ID %x,%x,%x,%x,%x,%x", i, tmp_bd[0], tmp_bd[1],
62               tmp_bd[2], tmp_bd[3], tmp_bd[4], tmp_bd[5]);
63 
64     m_wiimotes.emplace_back(std::make_unique<WiimoteDevice>(this, i, tmp_bd));
65   }
66 
67   bt_dinf.num_registered = MAX_BBMOTES;
68 
69   // save now so that when games load sysconf file it includes the new Wii Remotes
70   // and the correct order for connected Wii Remotes
71   auto& section = sysconf.GetOrAddEntry("BT.DINF", SysConf::Entry::Type::BigArray)->bytes;
72   section.resize(sizeof(ConfPads));
73   std::memcpy(section.data(), &bt_dinf, sizeof(ConfPads));
74   if (!sysconf.Save())
75     PanicAlertT("Failed to write BT.DINF to SYSCONF");
76 }
77 
78 BluetoothEmu::~BluetoothEmu() = default;
79 
80 template <typename T>
DoStateForMessage(Kernel & ios,PointerWrap & p,std::unique_ptr<T> & message)81 static void DoStateForMessage(Kernel& ios, PointerWrap& p, std::unique_ptr<T>& message)
82 {
83   u32 request_address = (message != nullptr) ? message->ios_request.address : 0;
84   p.Do(request_address);
85   if (request_address != 0)
86   {
87     IOCtlVRequest request{request_address};
88     message = std::make_unique<T>(ios, request);
89   }
90 }
91 
DoState(PointerWrap & p)92 void BluetoothEmu::DoState(PointerWrap& p)
93 {
94   bool passthrough_bluetooth = false;
95   p.Do(passthrough_bluetooth);
96   if (passthrough_bluetooth && p.GetMode() == PointerWrap::MODE_READ)
97   {
98     Core::DisplayMessage("State needs Bluetooth passthrough to be enabled. Aborting load.", 4000);
99     p.SetMode(PointerWrap::MODE_VERIFY);
100     return;
101   }
102 
103   p.Do(m_is_active);
104   p.Do(m_controller_bd);
105   DoStateForMessage(m_ios, p, m_hci_endpoint);
106   DoStateForMessage(m_ios, p, m_acl_endpoint);
107   p.Do(m_last_ticks);
108   p.DoArray(m_packet_count);
109   p.Do(m_scan_enable);
110   p.Do(m_event_queue);
111   m_acl_pool.DoState(p);
112 
113   for (unsigned int i = 0; i < MAX_BBMOTES; i++)
114     m_wiimotes[i]->DoState(p);
115 }
116 
RemoteConnect(WiimoteDevice & wiimote)117 bool BluetoothEmu::RemoteConnect(WiimoteDevice& wiimote)
118 {
119   // If page scan is disabled the controller will not see this connection request.
120   if (!(m_scan_enable & HCI_PAGE_SCAN_ENABLE))
121     return false;
122 
123   SendEventRequestConnection(wiimote);
124   return true;
125 }
126 
RemoteDisconnect(const bdaddr_t & address)127 bool BluetoothEmu::RemoteDisconnect(const bdaddr_t& address)
128 {
129   return SendEventDisconnect(GetConnectionHandle(address), 0x13);
130 }
131 
Close(u32 fd)132 IPCCommandResult BluetoothEmu::Close(u32 fd)
133 {
134   // Clean up state
135   m_scan_enable = 0;
136   m_last_ticks = 0;
137   memset(m_packet_count, 0, sizeof(m_packet_count));
138   m_hci_endpoint.reset();
139   m_acl_endpoint.reset();
140 
141   return Device::Close(fd);
142 }
143 
IOCtlV(const IOCtlVRequest & request)144 IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
145 {
146   bool send_reply = true;
147   switch (request.request)
148   {
149   case USB::IOCTLV_USBV0_CTRLMSG:  // HCI command is received from the stack
150   {
151     // Replies are generated inside
152     ExecuteHCICommandMessage(USB::V0CtrlMessage(m_ios, request));
153     send_reply = false;
154     break;
155   }
156 
157   case USB::IOCTLV_USBV0_BLKMSG:
158   {
159     const USB::V0BulkMessage ctrl{m_ios, request};
160     switch (ctrl.endpoint)
161     {
162     case ACL_DATA_OUT:  // ACL data is received from the stack
163     {
164       // This is the ACL datapath from CPU to Wii Remote
165       const auto* acl_header =
166           reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(ctrl.data_address));
167 
168       DEBUG_ASSERT(HCI_BC_FLAG(acl_header->con_handle) == HCI_POINT2POINT);
169       DEBUG_ASSERT(HCI_PB_FLAG(acl_header->con_handle) == HCI_PACKET_START);
170 
171       SendToDevice(HCI_CON_HANDLE(acl_header->con_handle),
172                    Memory::GetPointer(ctrl.data_address + sizeof(hci_acldata_hdr_t)),
173                    acl_header->length);
174       break;
175     }
176     case ACL_DATA_IN:  // We are given an ACL buffer to fill
177     {
178       m_acl_endpoint = std::make_unique<USB::V0BulkMessage>(m_ios, request);
179       DEBUG_LOG(IOS_WIIMOTE, "ACL_DATA_IN: 0x%08x ", request.address);
180       send_reply = false;
181       break;
182     }
183     default:
184       DEBUG_ASSERT_MSG(IOS_WIIMOTE, 0, "Unknown USB::IOCTLV_USBV0_BLKMSG: %x", ctrl.endpoint);
185     }
186     break;
187   }
188 
189   case USB::IOCTLV_USBV0_INTRMSG:
190   {
191     const USB::V0IntrMessage ctrl{m_ios, request};
192     if (ctrl.endpoint == HCI_EVENT)  // We are given a HCI buffer to fill
193     {
194       m_hci_endpoint = std::make_unique<USB::V0IntrMessage>(m_ios, request);
195       DEBUG_LOG(IOS_WIIMOTE, "HCI_EVENT: 0x%08x ", request.address);
196       send_reply = false;
197     }
198     else
199     {
200       DEBUG_ASSERT_MSG(IOS_WIIMOTE, 0, "Unknown USB::IOCTLV_USBV0_INTRMSG: %x", ctrl.endpoint);
201     }
202     break;
203   }
204 
205   default:
206     request.DumpUnknown(GetDeviceName(), Common::Log::IOS_WIIMOTE);
207   }
208 
209   return send_reply ? GetDefaultReply(IPC_SUCCESS) : GetNoReply();
210 }
211 
212 // Here we handle the USB::IOCTLV_USBV0_BLKMSG Ioctlv
SendToDevice(u16 connection_handle,u8 * data,u32 size)213 void BluetoothEmu::SendToDevice(u16 connection_handle, u8* data, u32 size)
214 {
215   WiimoteDevice* wiimote = AccessWiimote(connection_handle);
216   if (wiimote == nullptr)
217     return;
218 
219   DEBUG_LOG(IOS_WIIMOTE, "Send ACL Packet to ConnectionHandle 0x%04x", connection_handle);
220   IncDataPacket(connection_handle);
221   wiimote->ExecuteL2capCmd(data, size);
222 }
223 
IncDataPacket(u16 connection_handle)224 void BluetoothEmu::IncDataPacket(u16 connection_handle)
225 {
226   m_packet_count[GetWiimoteNumberFromConnectionHandle(connection_handle)]++;
227 }
228 
229 // Here we send ACL packets to CPU. They will consist of header + data.
230 // The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
SendACLPacket(const bdaddr_t & source,const u8 * data,u32 size)231 void BluetoothEmu::SendACLPacket(const bdaddr_t& source, const u8* data, u32 size)
232 {
233   const u16 connection_handle = GetConnectionHandle(source);
234 
235   DEBUG_LOG(IOS_WIIMOTE, "ACL packet from %x ready to send to stack...", connection_handle);
236 
237   if (m_acl_endpoint && !m_hci_endpoint && m_event_queue.empty())
238   {
239     DEBUG_LOG(IOS_WIIMOTE, "ACL endpoint valid, sending packet to %08x",
240               m_acl_endpoint->ios_request.address);
241 
242     hci_acldata_hdr_t* header =
243         reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(m_acl_endpoint->data_address));
244     header->con_handle = HCI_MK_CON_HANDLE(connection_handle, HCI_PACKET_START, HCI_POINT2POINT);
245     header->length = size;
246 
247     // Write the packet to the buffer
248     memcpy(reinterpret_cast<u8*>(header) + sizeof(hci_acldata_hdr_t), data, header->length);
249 
250     m_ios.EnqueueIPCReply(m_acl_endpoint->ios_request, sizeof(hci_acldata_hdr_t) + size);
251     m_acl_endpoint.reset();
252   }
253   else
254   {
255     DEBUG_LOG(IOS_WIIMOTE, "ACL endpoint not currently valid, queuing...");
256     m_acl_pool.Store(data, size, connection_handle);
257   }
258 }
259 
260 // These messages are sent from the Wii Remote to the game, for example RequestConnection()
261 // or ConnectionComplete().
262 //
263 // Our IOS is so efficient that we could fill the buffer immediately
264 // rather than enqueue it to some other memory and this will do good for StateSave
AddEventToQueue(const SQueuedEvent & event)265 void BluetoothEmu::AddEventToQueue(const SQueuedEvent& event)
266 {
267   DEBUG_LOG(IOS_WIIMOTE, "HCI event %x completed...", ((hci_event_hdr_t*)event.buffer)->event);
268 
269   if (m_hci_endpoint)
270   {
271     if (m_event_queue.empty())  // fast path :)
272     {
273       DEBUG_LOG(IOS_WIIMOTE, "HCI endpoint valid, sending packet to %08x",
274                 m_hci_endpoint->ios_request.address);
275       m_hci_endpoint->FillBuffer(event.buffer, event.size);
276 
277       // Send a reply to indicate HCI buffer is filled
278       m_ios.EnqueueIPCReply(m_hci_endpoint->ios_request, event.size);
279       m_hci_endpoint.reset();
280     }
281     else  // push new one, pop oldest
282     {
283       DEBUG_LOG(IOS_WIIMOTE, "HCI endpoint not currently valid, queueing (%zu)...",
284                 m_event_queue.size());
285       m_event_queue.push_back(event);
286       const SQueuedEvent& queued_event = m_event_queue.front();
287       DEBUG_LOG(IOS_WIIMOTE,
288                 "HCI event %x "
289                 "being written from queue (%zu) to %08x...",
290                 ((hci_event_hdr_t*)queued_event.buffer)->event, m_event_queue.size() - 1,
291                 m_hci_endpoint->ios_request.address);
292       m_hci_endpoint->FillBuffer(queued_event.buffer, queued_event.size);
293 
294       // Send a reply to indicate HCI buffer is filled
295       m_ios.EnqueueIPCReply(m_hci_endpoint->ios_request, queued_event.size);
296       m_hci_endpoint.reset();
297       m_event_queue.pop_front();
298     }
299   }
300   else
301   {
302     DEBUG_LOG(IOS_WIIMOTE, "HCI endpoint not currently valid, queuing (%zu)...",
303               m_event_queue.size());
304     m_event_queue.push_back(event);
305   }
306 }
307 
Update()308 void BluetoothEmu::Update()
309 {
310   // check HCI queue
311   if (!m_event_queue.empty() && m_hci_endpoint)
312   {
313     // an endpoint has become available, and we have a stored response.
314     const SQueuedEvent& event = m_event_queue.front();
315     DEBUG_LOG(IOS_WIIMOTE, "HCI event %x being written from queue (%zu) to %08x...",
316               ((hci_event_hdr_t*)event.buffer)->event, m_event_queue.size() - 1,
317               m_hci_endpoint->ios_request.address);
318     m_hci_endpoint->FillBuffer(event.buffer, event.size);
319 
320     // Send a reply to indicate HCI buffer is filled
321     m_ios.EnqueueIPCReply(m_hci_endpoint->ios_request, event.size);
322     m_hci_endpoint.reset();
323     m_event_queue.pop_front();
324   }
325 
326   // check ACL queue
327   if (!m_acl_pool.IsEmpty() && m_acl_endpoint && m_event_queue.empty())
328   {
329     m_acl_pool.WriteToEndpoint(*m_acl_endpoint);
330     m_acl_endpoint.reset();
331   }
332 
333   for (auto& wiimote : m_wiimotes)
334     wiimote->Update();
335 
336   const u64 interval = SystemTimers::GetTicksPerSecond() / Wiimote::UPDATE_FREQ;
337   const u64 now = CoreTiming::GetTicks();
338 
339   if (now - m_last_ticks > interval)
340   {
341     g_controller_interface.UpdateInput();
342     for (auto& wiimote : m_wiimotes)
343       wiimote->UpdateInput();
344     m_last_ticks = now;
345   }
346 
347   SendEventNumberOfCompletedPackets();
348 }
349 
Store(const u8 * data,const u16 size,const u16 conn_handle)350 void BluetoothEmu::ACLPool::Store(const u8* data, const u16 size, const u16 conn_handle)
351 {
352   if (m_queue.size() >= 100)
353   {
354     // Many simultaneous exchanges of ACL packets tend to cause the queue to fill up.
355     ERROR_LOG(IOS_WIIMOTE, "ACL queue size reached 100 - current packet will be dropped!");
356     return;
357   }
358 
359   DEBUG_ASSERT_MSG(IOS_WIIMOTE, size < ACL_PKT_SIZE, "ACL packet too large for pool");
360 
361   m_queue.push_back(Packet());
362   auto& packet = m_queue.back();
363 
364   std::copy(data, data + size, packet.data);
365   packet.size = size;
366   packet.conn_handle = conn_handle;
367 }
368 
WriteToEndpoint(const USB::V0BulkMessage & endpoint)369 void BluetoothEmu::ACLPool::WriteToEndpoint(const USB::V0BulkMessage& endpoint)
370 {
371   auto& packet = m_queue.front();
372 
373   const u8* const data = packet.data;
374   const u16 size = packet.size;
375   const u16 conn_handle = packet.conn_handle;
376 
377   DEBUG_LOG(IOS_WIIMOTE,
378             "ACL packet being written from "
379             "queue to %08x",
380             endpoint.ios_request.address);
381 
382   hci_acldata_hdr_t* header = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.data_address);
383   header->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
384   header->length = size;
385 
386   // Write the packet to the buffer
387   std::copy(data, data + size, (u8*)header + sizeof(hci_acldata_hdr_t));
388 
389   m_queue.pop_front();
390 
391   m_ios.EnqueueIPCReply(endpoint.ios_request, sizeof(hci_acldata_hdr_t) + size);
392 }
393 
SendEventInquiryComplete(u8 num_responses)394 bool BluetoothEmu::SendEventInquiryComplete(u8 num_responses)
395 {
396   SQueuedEvent event(sizeof(SHCIEventInquiryComplete), 0);
397 
398   SHCIEventInquiryComplete* inquiry_complete = (SHCIEventInquiryComplete*)event.buffer;
399   inquiry_complete->EventType = HCI_EVENT_INQUIRY_COMPL;
400   inquiry_complete->PayloadLength = sizeof(SHCIEventInquiryComplete) - 2;
401   inquiry_complete->EventStatus = 0x00;
402   inquiry_complete->num_responses = num_responses;
403 
404   AddEventToQueue(event);
405 
406   DEBUG_LOG(IOS_WIIMOTE, "Event: Inquiry complete");
407 
408   return true;
409 }
410 
SendEventInquiryResponse()411 bool BluetoothEmu::SendEventInquiryResponse()
412 {
413   // We only respond with the first discoverable remote.
414   // The Wii instructs users to press 1+2 in the desired play order.
415   // Responding with all remotes at once can place them in undesirable slots.
416   // Additional scans will connect each remote in the proper order.
417   constexpr u8 num_responses = 1;
418 
419   static_assert(
420       sizeof(SHCIEventInquiryResult) - 2 + (num_responses * sizeof(hci_inquiry_response)) < 256);
421 
422   const auto iter = std::find_if(m_wiimotes.begin(), m_wiimotes.end(),
423                                  std::mem_fn(&WiimoteDevice::IsInquiryScanEnabled));
424   if (iter == m_wiimotes.end())
425   {
426     // No remotes are discoverable.
427     SendEventInquiryComplete(0);
428     return false;
429   }
430 
431   const auto& wiimote = *iter;
432 
433   SQueuedEvent event(
434       u32(sizeof(SHCIEventInquiryResult) + num_responses * sizeof(hci_inquiry_response)), 0);
435 
436   const auto inquiry_result = reinterpret_cast<SHCIEventInquiryResult*>(event.buffer);
437   inquiry_result->EventType = HCI_EVENT_INQUIRY_RESULT;
438   inquiry_result->num_responses = num_responses;
439 
440   u8* const buffer = event.buffer + sizeof(SHCIEventInquiryResult);
441   const auto response = reinterpret_cast<hci_inquiry_response*>(buffer);
442 
443   response->bdaddr = wiimote->GetBD();
444   response->page_scan_rep_mode = 1;
445   response->page_scan_period_mode = 0;
446   response->page_scan_mode = 0;
447   std::copy_n(wiimote->GetClass().begin(), HCI_CLASS_SIZE, response->uclass);
448   response->clock_offset = 0x3818;
449 
450   DEBUG_LOG(IOS_WIIMOTE, "Event: Send Fake Inquiry of one controller");
451   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", response->bdaddr[0],
452             response->bdaddr[1], response->bdaddr[2], response->bdaddr[3], response->bdaddr[4],
453             response->bdaddr[5]);
454 
455   inquiry_result->PayloadLength =
456       u8(sizeof(SHCIEventInquiryResult) - 2 +
457          (inquiry_result->num_responses * sizeof(hci_inquiry_response)));
458 
459   AddEventToQueue(event);
460   SendEventInquiryComplete(num_responses);
461   return true;
462 }
463 
SendEventConnectionComplete(const bdaddr_t & bd,u8 status)464 bool BluetoothEmu::SendEventConnectionComplete(const bdaddr_t& bd, u8 status)
465 {
466   SQueuedEvent event(sizeof(SHCIEventConnectionComplete), 0);
467 
468   SHCIEventConnectionComplete* connection_complete = (SHCIEventConnectionComplete*)event.buffer;
469 
470   connection_complete->EventType = HCI_EVENT_CON_COMPL;
471   connection_complete->PayloadLength = sizeof(SHCIEventConnectionComplete) - 2;
472   connection_complete->EventStatus = status;
473   connection_complete->Connection_Handle = GetConnectionHandle(bd);
474   connection_complete->bdaddr = bd;
475   connection_complete->LinkType = HCI_LINK_ACL;
476   connection_complete->EncryptionEnabled = HCI_ENCRYPTION_MODE_NONE;
477 
478   AddEventToQueue(event);
479 
480   static constexpr const char* link_type[] = {
481       "HCI_LINK_SCO     0x00 - Voice",
482       "HCI_LINK_ACL     0x01 - Data",
483       "HCI_LINK_eSCO    0x02 - eSCO",
484   };
485 
486   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventConnectionComplete");
487   DEBUG_LOG(IOS_WIIMOTE, "  Connection_Handle: 0x%04x", connection_complete->Connection_Handle);
488   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", connection_complete->bdaddr[0],
489             connection_complete->bdaddr[1], connection_complete->bdaddr[2],
490             connection_complete->bdaddr[3], connection_complete->bdaddr[4],
491             connection_complete->bdaddr[5]);
492   DEBUG_LOG(IOS_WIIMOTE, "  LinkType: %s", link_type[connection_complete->LinkType]);
493   DEBUG_LOG(IOS_WIIMOTE, "  EncryptionEnabled: %i", connection_complete->EncryptionEnabled);
494 
495   return true;
496 }
497 
SendEventRequestConnection(const WiimoteDevice & wiimote)498 bool BluetoothEmu::SendEventRequestConnection(const WiimoteDevice& wiimote)
499 {
500   SQueuedEvent event(sizeof(SHCIEventRequestConnection), 0);
501 
502   SHCIEventRequestConnection* event_request_connection = (SHCIEventRequestConnection*)event.buffer;
503 
504   event_request_connection->EventType = HCI_EVENT_CON_REQ;
505   event_request_connection->PayloadLength = sizeof(SHCIEventRequestConnection) - 2;
506   event_request_connection->bdaddr = wiimote.GetBD();
507   event_request_connection->uclass[0] = wiimote.GetClass()[0];
508   event_request_connection->uclass[1] = wiimote.GetClass()[1];
509   event_request_connection->uclass[2] = wiimote.GetClass()[2];
510   event_request_connection->LinkType = HCI_LINK_ACL;
511 
512   AddEventToQueue(event);
513 
514   static constexpr const char* link_type[] = {
515       "HCI_LINK_SCO     0x00 - Voice",
516       "HCI_LINK_ACL     0x01 - Data",
517       "HCI_LINK_eSCO    0x02 - eSCO",
518   };
519 
520   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventRequestConnection");
521   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", event_request_connection->bdaddr[0],
522             event_request_connection->bdaddr[1], event_request_connection->bdaddr[2],
523             event_request_connection->bdaddr[3], event_request_connection->bdaddr[4],
524             event_request_connection->bdaddr[5]);
525   DEBUG_LOG(IOS_WIIMOTE, "  COD[0]: 0x%02x", event_request_connection->uclass[0]);
526   DEBUG_LOG(IOS_WIIMOTE, "  COD[1]: 0x%02x", event_request_connection->uclass[1]);
527   DEBUG_LOG(IOS_WIIMOTE, "  COD[2]: 0x%02x", event_request_connection->uclass[2]);
528   DEBUG_LOG(IOS_WIIMOTE, "  LinkType: %s", link_type[event_request_connection->LinkType]);
529 
530   return true;
531 }
532 
SendEventDisconnect(u16 connection_handle,u8 reason)533 bool BluetoothEmu::SendEventDisconnect(u16 connection_handle, u8 reason)
534 {
535   WiimoteDevice* wiimote = AccessWiimote(connection_handle);
536   if (wiimote == nullptr)
537     return false;
538 
539   SQueuedEvent event(sizeof(SHCIEventDisconnectCompleted), connection_handle);
540 
541   SHCIEventDisconnectCompleted* disconnect = (SHCIEventDisconnectCompleted*)event.buffer;
542   disconnect->EventType = HCI_EVENT_DISCON_COMPL;
543   disconnect->PayloadLength = sizeof(SHCIEventDisconnectCompleted) - 2;
544   disconnect->EventStatus = 0;
545   disconnect->Connection_Handle = connection_handle;
546   disconnect->Reason = reason;
547 
548   AddEventToQueue(event);
549 
550   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventDisconnect");
551   DEBUG_LOG(IOS_WIIMOTE, "  Connection_Handle: 0x%04x", disconnect->Connection_Handle);
552   DEBUG_LOG(IOS_WIIMOTE, "  Reason: 0x%02x", disconnect->Reason);
553 
554   return true;
555 }
556 
SendEventAuthenticationCompleted(u16 connection_handle)557 bool BluetoothEmu::SendEventAuthenticationCompleted(u16 connection_handle)
558 {
559   WiimoteDevice* wiimote = AccessWiimote(connection_handle);
560   if (wiimote == nullptr)
561     return false;
562 
563   SQueuedEvent event(sizeof(SHCIEventAuthenticationCompleted), connection_handle);
564 
565   SHCIEventAuthenticationCompleted* event_authentication_completed =
566       (SHCIEventAuthenticationCompleted*)event.buffer;
567   event_authentication_completed->EventType = HCI_EVENT_AUTH_COMPL;
568   event_authentication_completed->PayloadLength = sizeof(SHCIEventAuthenticationCompleted) - 2;
569   event_authentication_completed->EventStatus = 0;
570   event_authentication_completed->Connection_Handle = connection_handle;
571 
572   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventAuthenticationCompleted");
573   DEBUG_LOG(IOS_WIIMOTE, "  Connection_Handle: 0x%04x",
574             event_authentication_completed->Connection_Handle);
575 
576   AddEventToQueue(event);
577 
578   return true;
579 }
580 
SendEventRemoteNameReq(const bdaddr_t & bd)581 bool BluetoothEmu::SendEventRemoteNameReq(const bdaddr_t& bd)
582 {
583   WiimoteDevice* wiimote = AccessWiimote(bd);
584   if (wiimote == nullptr)
585     return false;
586 
587   SQueuedEvent event(sizeof(SHCIEventRemoteNameReq), 0);
588 
589   SHCIEventRemoteNameReq* remote_name_req = (SHCIEventRemoteNameReq*)event.buffer;
590 
591   remote_name_req->EventType = HCI_EVENT_REMOTE_NAME_REQ_COMPL;
592   remote_name_req->PayloadLength = sizeof(SHCIEventRemoteNameReq) - 2;
593   remote_name_req->EventStatus = 0x00;
594   remote_name_req->bdaddr = bd;
595   strcpy((char*)remote_name_req->RemoteName, wiimote->GetName());
596 
597   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventRemoteNameReq");
598   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", remote_name_req->bdaddr[0],
599             remote_name_req->bdaddr[1], remote_name_req->bdaddr[2], remote_name_req->bdaddr[3],
600             remote_name_req->bdaddr[4], remote_name_req->bdaddr[5]);
601   DEBUG_LOG(IOS_WIIMOTE, "  RemoteName: %s", remote_name_req->RemoteName);
602 
603   AddEventToQueue(event);
604 
605   return true;
606 }
607 
SendEventReadRemoteFeatures(u16 connection_handle)608 bool BluetoothEmu::SendEventReadRemoteFeatures(u16 connection_handle)
609 {
610   WiimoteDevice* wiimote = AccessWiimote(connection_handle);
611   if (wiimote == nullptr)
612     return false;
613 
614   SQueuedEvent event(sizeof(SHCIEventReadRemoteFeatures), connection_handle);
615 
616   SHCIEventReadRemoteFeatures* read_remote_features = (SHCIEventReadRemoteFeatures*)event.buffer;
617 
618   read_remote_features->EventType = HCI_EVENT_READ_REMOTE_FEATURES_COMPL;
619   read_remote_features->PayloadLength = sizeof(SHCIEventReadRemoteFeatures) - 2;
620   read_remote_features->EventStatus = 0x00;
621   read_remote_features->ConnectionHandle = connection_handle;
622   std::copy_n(wiimote->GetFeatures().begin(), HCI_FEATURES_SIZE, read_remote_features->features);
623 
624   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventReadRemoteFeatures");
625   DEBUG_LOG(IOS_WIIMOTE, "  Connection_Handle: 0x%04x", read_remote_features->ConnectionHandle);
626   DEBUG_LOG(IOS_WIIMOTE, "  features: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
627             read_remote_features->features[0], read_remote_features->features[1],
628             read_remote_features->features[2], read_remote_features->features[3],
629             read_remote_features->features[4], read_remote_features->features[5],
630             read_remote_features->features[6], read_remote_features->features[7]);
631 
632   AddEventToQueue(event);
633 
634   return true;
635 }
636 
SendEventReadRemoteVerInfo(u16 connection_handle)637 bool BluetoothEmu::SendEventReadRemoteVerInfo(u16 connection_handle)
638 {
639   WiimoteDevice* wiimote = AccessWiimote(connection_handle);
640   if (wiimote == nullptr)
641     return false;
642 
643   SQueuedEvent event(sizeof(SHCIEventReadRemoteVerInfo), connection_handle);
644 
645   SHCIEventReadRemoteVerInfo* read_remote_ver_info = (SHCIEventReadRemoteVerInfo*)event.buffer;
646   read_remote_ver_info->EventType = HCI_EVENT_READ_REMOTE_VER_INFO_COMPL;
647   read_remote_ver_info->PayloadLength = sizeof(SHCIEventReadRemoteVerInfo) - 2;
648   read_remote_ver_info->EventStatus = 0x00;
649   read_remote_ver_info->ConnectionHandle = connection_handle;
650   read_remote_ver_info->lmp_version = wiimote->GetLMPVersion();
651   read_remote_ver_info->manufacturer = wiimote->GetManufactorID();
652   read_remote_ver_info->lmp_subversion = wiimote->GetLMPSubVersion();
653 
654   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventReadRemoteVerInfo");
655   DEBUG_LOG(IOS_WIIMOTE, "  Connection_Handle: 0x%04x", read_remote_ver_info->ConnectionHandle);
656   DEBUG_LOG(IOS_WIIMOTE, "  lmp_version: 0x%02x", read_remote_ver_info->lmp_version);
657   DEBUG_LOG(IOS_WIIMOTE, "  manufacturer: 0x%04x", read_remote_ver_info->manufacturer);
658   DEBUG_LOG(IOS_WIIMOTE, "  lmp_subversion: 0x%04x", read_remote_ver_info->lmp_subversion);
659 
660   AddEventToQueue(event);
661 
662   return true;
663 }
664 
SendEventCommandComplete(u16 opcode,const void * data,u32 data_size)665 void BluetoothEmu::SendEventCommandComplete(u16 opcode, const void* data, u32 data_size)
666 {
667   DEBUG_ASSERT((sizeof(SHCIEventCommand) - 2 + data_size) < 256);
668 
669   SQueuedEvent event(sizeof(SHCIEventCommand) + data_size, 0);
670 
671   SHCIEventCommand* hci_event = reinterpret_cast<SHCIEventCommand*>(event.buffer);
672   hci_event->EventType = HCI_EVENT_COMMAND_COMPL;
673   hci_event->PayloadLength = (u8)(sizeof(SHCIEventCommand) - 2 + data_size);
674   hci_event->PacketIndicator = 0x01;
675   hci_event->Opcode = opcode;
676 
677   // add the payload
678   if (data != nullptr && data_size > 0)
679   {
680     u8* payload = event.buffer + sizeof(SHCIEventCommand);
681     memcpy(payload, data, data_size);
682   }
683 
684   DEBUG_LOG(IOS_WIIMOTE, "Event: Command Complete (Opcode: 0x%04x)", hci_event->Opcode);
685 
686   AddEventToQueue(event);
687 }
688 
SendEventCommandStatus(u16 opcode)689 bool BluetoothEmu::SendEventCommandStatus(u16 opcode)
690 {
691   SQueuedEvent event(sizeof(SHCIEventStatus), 0);
692 
693   SHCIEventStatus* hci_event = (SHCIEventStatus*)event.buffer;
694   hci_event->EventType = HCI_EVENT_COMMAND_STATUS;
695   hci_event->PayloadLength = sizeof(SHCIEventStatus) - 2;
696   hci_event->EventStatus = 0x0;
697   hci_event->PacketIndicator = 0x01;
698   hci_event->Opcode = opcode;
699 
700   INFO_LOG(IOS_WIIMOTE, "Event: Command Status (Opcode: 0x%04x)", hci_event->Opcode);
701 
702   AddEventToQueue(event);
703 
704   return true;
705 }
706 
SendEventRoleChange(bdaddr_t bd,bool master)707 bool BluetoothEmu::SendEventRoleChange(bdaddr_t bd, bool master)
708 {
709   WiimoteDevice* wiimote = AccessWiimote(bd);
710   if (wiimote == nullptr)
711     return false;
712 
713   SQueuedEvent event(sizeof(SHCIEventRoleChange), 0);
714 
715   SHCIEventRoleChange* role_change = (SHCIEventRoleChange*)event.buffer;
716 
717   role_change->EventType = HCI_EVENT_ROLE_CHANGE;
718   role_change->PayloadLength = sizeof(SHCIEventRoleChange) - 2;
719   role_change->EventStatus = 0x00;
720   role_change->bdaddr = bd;
721   role_change->NewRole = master ? 0x00 : 0x01;
722 
723   AddEventToQueue(event);
724 
725   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventRoleChange");
726   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", role_change->bdaddr[0],
727             role_change->bdaddr[1], role_change->bdaddr[2], role_change->bdaddr[3],
728             role_change->bdaddr[4], role_change->bdaddr[5]);
729   DEBUG_LOG(IOS_WIIMOTE, "  NewRole: %i", role_change->NewRole);
730 
731   return true;
732 }
733 
SendEventNumberOfCompletedPackets()734 bool BluetoothEmu::SendEventNumberOfCompletedPackets()
735 {
736   SQueuedEvent event((u32)(sizeof(hci_event_hdr_t) + sizeof(hci_num_compl_pkts_ep) +
737                            (sizeof(hci_num_compl_pkts_info) * m_wiimotes.size())),
738                      0);
739 
740   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventNumberOfCompletedPackets");
741 
742   auto* event_hdr = (hci_event_hdr_t*)event.buffer;
743   auto* hci_event = (hci_num_compl_pkts_ep*)((u8*)event_hdr + sizeof(hci_event_hdr_t));
744   auto* info = (hci_num_compl_pkts_info*)((u8*)hci_event + sizeof(hci_num_compl_pkts_ep));
745 
746   event_hdr->event = HCI_EVENT_NUM_COMPL_PKTS;
747   event_hdr->length = sizeof(hci_num_compl_pkts_ep);
748   hci_event->num_con_handles = 0;
749 
750   u32 acc = 0;
751 
752   for (unsigned int i = 0; i < m_wiimotes.size(); i++)
753   {
754     event_hdr->length += sizeof(hci_num_compl_pkts_info);
755     hci_event->num_con_handles++;
756     info->compl_pkts = m_packet_count[i];
757     info->con_handle = GetConnectionHandle(m_wiimotes[i]->GetBD());
758 
759     DEBUG_LOG(IOS_WIIMOTE, "  Connection_Handle: 0x%04x", info->con_handle);
760     DEBUG_LOG(IOS_WIIMOTE, "  Number_Of_Completed_Packets: %i", info->compl_pkts);
761 
762     acc += info->compl_pkts;
763     m_packet_count[i] = 0;
764     info++;
765   }
766 
767   if (acc)
768   {
769     AddEventToQueue(event);
770   }
771   else
772   {
773     DEBUG_LOG(IOS_WIIMOTE, "SendEventNumberOfCompletedPackets: no packets; no event");
774   }
775 
776   return true;
777 }
778 
SendEventModeChange(u16 connection_handle,u8 mode,u16 value)779 bool BluetoothEmu::SendEventModeChange(u16 connection_handle, u8 mode, u16 value)
780 {
781   WiimoteDevice* wiimote = AccessWiimote(connection_handle);
782   if (wiimote == nullptr)
783     return false;
784 
785   SQueuedEvent event(sizeof(SHCIEventModeChange), connection_handle);
786 
787   SHCIEventModeChange* mode_change = (SHCIEventModeChange*)event.buffer;
788   mode_change->EventType = HCI_EVENT_MODE_CHANGE;
789   mode_change->PayloadLength = sizeof(SHCIEventModeChange) - 2;
790   mode_change->EventStatus = 0;
791   mode_change->Connection_Handle = connection_handle;
792   mode_change->CurrentMode = mode;
793   mode_change->Value = value;
794 
795   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventModeChange");
796   DEBUG_LOG(IOS_WIIMOTE, "  Connection_Handle: 0x%04x", mode_change->Connection_Handle);
797   DEBUG_LOG(IOS_WIIMOTE, "  Current Mode: 0x%02x", mode_change->CurrentMode = mode);
798 
799   AddEventToQueue(event);
800 
801   return true;
802 }
803 
SendEventLinkKeyNotification(const u8 num_to_send)804 bool BluetoothEmu::SendEventLinkKeyNotification(const u8 num_to_send)
805 {
806   u8 payload_length = sizeof(hci_return_link_keys_ep) + sizeof(hci_link_key_rep_cp) * num_to_send;
807   SQueuedEvent event(2 + payload_length, 0);
808   SHCIEventLinkKeyNotification* event_link_key = (SHCIEventLinkKeyNotification*)event.buffer;
809 
810   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventLinkKeyNotification");
811 
812   // event header
813   event_link_key->EventType = HCI_EVENT_RETURN_LINK_KEYS;
814   event_link_key->PayloadLength = payload_length;
815   // this is really hci_return_link_keys_ep.num_keys
816   event_link_key->numKeys = num_to_send;
817 
818   // copy infos - this only works correctly if we're meant to start at first device and read all
819   // keys
820   for (int i = 0; i < num_to_send; i++)
821   {
822     hci_link_key_rep_cp* link_key_info =
823         (hci_link_key_rep_cp*)((u8*)&event_link_key->bdaddr + sizeof(hci_link_key_rep_cp) * i);
824     link_key_info->bdaddr = m_wiimotes[i]->GetBD();
825     std::copy_n(m_wiimotes[i]->GetLinkKey().begin(), HCI_KEY_SIZE, link_key_info->key);
826 
827     DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", link_key_info->bdaddr[0],
828               link_key_info->bdaddr[1], link_key_info->bdaddr[2], link_key_info->bdaddr[3],
829               link_key_info->bdaddr[4], link_key_info->bdaddr[5]);
830   }
831 
832   AddEventToQueue(event);
833 
834   return true;
835 };
836 
SendEventRequestLinkKey(const bdaddr_t & bd)837 bool BluetoothEmu::SendEventRequestLinkKey(const bdaddr_t& bd)
838 {
839   SQueuedEvent event(sizeof(SHCIEventRequestLinkKey), 0);
840 
841   SHCIEventRequestLinkKey* event_request_link_key = (SHCIEventRequestLinkKey*)event.buffer;
842 
843   event_request_link_key->EventType = HCI_EVENT_LINK_KEY_REQ;
844   event_request_link_key->PayloadLength = sizeof(SHCIEventRequestLinkKey) - 2;
845   event_request_link_key->bdaddr = bd;
846 
847   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventRequestLinkKey");
848   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", event_request_link_key->bdaddr[0],
849             event_request_link_key->bdaddr[1], event_request_link_key->bdaddr[2],
850             event_request_link_key->bdaddr[3], event_request_link_key->bdaddr[4],
851             event_request_link_key->bdaddr[5]);
852 
853   AddEventToQueue(event);
854 
855   return true;
856 };
857 
SendEventReadClockOffsetComplete(u16 connection_handle)858 bool BluetoothEmu::SendEventReadClockOffsetComplete(u16 connection_handle)
859 {
860   WiimoteDevice* wiimote = AccessWiimote(connection_handle);
861   if (wiimote == nullptr)
862     return false;
863 
864   SQueuedEvent event(sizeof(SHCIEventReadClockOffsetComplete), connection_handle);
865 
866   SHCIEventReadClockOffsetComplete* read_clock_offset_complete =
867       (SHCIEventReadClockOffsetComplete*)event.buffer;
868   read_clock_offset_complete->EventType = HCI_EVENT_READ_CLOCK_OFFSET_COMPL;
869   read_clock_offset_complete->PayloadLength = sizeof(SHCIEventReadClockOffsetComplete) - 2;
870   read_clock_offset_complete->EventStatus = 0x00;
871   read_clock_offset_complete->ConnectionHandle = connection_handle;
872   read_clock_offset_complete->ClockOffset = 0x3818;
873 
874   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventReadClockOffsetComplete");
875   DEBUG_LOG(IOS_WIIMOTE, "  Connection_Handle: 0x%04x",
876             read_clock_offset_complete->ConnectionHandle);
877   DEBUG_LOG(IOS_WIIMOTE, "  ClockOffset: 0x%04x", read_clock_offset_complete->ClockOffset);
878 
879   AddEventToQueue(event);
880 
881   return true;
882 }
883 
SendEventConPacketTypeChange(u16 connection_handle,u16 packet_type)884 bool BluetoothEmu::SendEventConPacketTypeChange(u16 connection_handle, u16 packet_type)
885 {
886   WiimoteDevice* wiimote = AccessWiimote(connection_handle);
887   if (wiimote == nullptr)
888     return false;
889 
890   SQueuedEvent event(sizeof(SHCIEventConPacketTypeChange), connection_handle);
891 
892   SHCIEventConPacketTypeChange* change_con_packet_type =
893       (SHCIEventConPacketTypeChange*)event.buffer;
894   change_con_packet_type->EventType = HCI_EVENT_CON_PKT_TYPE_CHANGED;
895   change_con_packet_type->PayloadLength = sizeof(SHCIEventConPacketTypeChange) - 2;
896   change_con_packet_type->EventStatus = 0x00;
897   change_con_packet_type->ConnectionHandle = connection_handle;
898   change_con_packet_type->PacketType = packet_type;
899 
900   DEBUG_LOG(IOS_WIIMOTE, "Event: SendEventConPacketTypeChange");
901   DEBUG_LOG(IOS_WIIMOTE, "  Connection_Handle: 0x%04x", change_con_packet_type->ConnectionHandle);
902   DEBUG_LOG(IOS_WIIMOTE, "  PacketType: 0x%04x", change_con_packet_type->PacketType);
903 
904   AddEventToQueue(event);
905 
906   return true;
907 }
908 
909 // Command dispatcher
910 // This is called from the USB::IOCTLV_USBV0_CTRLMSG Ioctlv
ExecuteHCICommandMessage(const USB::V0CtrlMessage & ctrl_message)911 void BluetoothEmu::ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl_message)
912 {
913   const u8* input = Memory::GetPointer(ctrl_message.data_address + 3);
914 
915   SCommandMessage msg;
916   std::memcpy(&msg, Memory::GetPointer(ctrl_message.data_address), sizeof(msg));
917 
918   const u16 ocf = HCI_OCF(msg.Opcode);
919   const u16 ogf = HCI_OGF(msg.Opcode);
920 
921   DEBUG_LOG(IOS_WIIMOTE, "**************************************************");
922   DEBUG_LOG(IOS_WIIMOTE, "Execute HCI Command: 0x%04x (ocf: 0x%02x, ogf: 0x%02x)", msg.Opcode, ocf,
923             ogf);
924 
925   switch (msg.Opcode)
926   {
927   //
928   // --- read commands ---
929   //
930   case HCI_CMD_RESET:
931     CommandReset(input);
932     break;
933 
934   case HCI_CMD_READ_BUFFER_SIZE:
935     CommandReadBufferSize(input);
936     break;
937 
938   case HCI_CMD_READ_LOCAL_VER:
939     CommandReadLocalVer(input);
940     break;
941 
942   case HCI_CMD_READ_BDADDR:
943     CommandReadBDAdrr(input);
944     break;
945 
946   case HCI_CMD_READ_LOCAL_FEATURES:
947     CommandReadLocalFeatures(input);
948     break;
949 
950   case HCI_CMD_READ_STORED_LINK_KEY:
951     CommandReadStoredLinkKey(input);
952     break;
953 
954   case HCI_CMD_WRITE_UNIT_CLASS:
955     CommandWriteUnitClass(input);
956     break;
957 
958   case HCI_CMD_WRITE_LOCAL_NAME:
959     CommandWriteLocalName(input);
960     break;
961 
962   case HCI_CMD_WRITE_PIN_TYPE:
963     CommandWritePinType(input);
964     break;
965 
966   case HCI_CMD_HOST_BUFFER_SIZE:
967     CommandHostBufferSize(input);
968     break;
969 
970   case HCI_CMD_WRITE_PAGE_TIMEOUT:
971     CommandWritePageTimeOut(input);
972     break;
973 
974   case HCI_CMD_WRITE_SCAN_ENABLE:
975     CommandWriteScanEnable(input);
976     break;
977 
978   case HCI_CMD_WRITE_INQUIRY_MODE:
979     CommandWriteInquiryMode(input);
980     break;
981 
982   case HCI_CMD_WRITE_PAGE_SCAN_TYPE:
983     CommandWritePageScanType(input);
984     break;
985 
986   case HCI_CMD_SET_EVENT_FILTER:
987     CommandSetEventFilter(input);
988     break;
989 
990   case HCI_CMD_INQUIRY:
991     CommandInquiry(input);
992     break;
993 
994   case HCI_CMD_WRITE_INQUIRY_SCAN_TYPE:
995     CommandWriteInquiryScanType(input);
996     break;
997 
998   // vendor specific...
999   case 0xFC4C:
1000     CommandVendorSpecific_FC4C(input, ctrl_message.length - 3);
1001     break;
1002 
1003   case 0xFC4F:
1004     CommandVendorSpecific_FC4F(input, ctrl_message.length - 3);
1005     break;
1006 
1007   case HCI_CMD_INQUIRY_CANCEL:
1008     CommandInquiryCancel(input);
1009     break;
1010 
1011   case HCI_CMD_REMOTE_NAME_REQ:
1012     CommandRemoteNameReq(input);
1013     break;
1014 
1015   case HCI_CMD_CREATE_CON:
1016     CommandCreateCon(input);
1017     break;
1018 
1019   case HCI_CMD_ACCEPT_CON:
1020     CommandAcceptCon(input);
1021     break;
1022 
1023   case HCI_CMD_CHANGE_CON_PACKET_TYPE:
1024     CommandChangeConPacketType(input);
1025     break;
1026 
1027   case HCI_CMD_READ_CLOCK_OFFSET:
1028     CommandReadClockOffset(input);
1029     break;
1030 
1031   case HCI_CMD_READ_REMOTE_VER_INFO:
1032     CommandReadRemoteVerInfo(input);
1033     break;
1034 
1035   case HCI_CMD_READ_REMOTE_FEATURES:
1036     CommandReadRemoteFeatures(input);
1037     break;
1038 
1039   case HCI_CMD_WRITE_LINK_POLICY_SETTINGS:
1040     CommandWriteLinkPolicy(input);
1041     break;
1042 
1043   case HCI_CMD_AUTH_REQ:
1044     CommandAuthenticationRequested(input);
1045     break;
1046 
1047   case HCI_CMD_SNIFF_MODE:
1048     CommandSniffMode(input);
1049     break;
1050 
1051   case HCI_CMD_DISCONNECT:
1052     CommandDisconnect(input);
1053     break;
1054 
1055   case HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT:
1056     CommandWriteLinkSupervisionTimeout(input);
1057     break;
1058 
1059   case HCI_CMD_LINK_KEY_NEG_REP:
1060     CommandLinkKeyNegRep(input);
1061     break;
1062 
1063   case HCI_CMD_LINK_KEY_REP:
1064     CommandLinkKeyRep(input);
1065     break;
1066 
1067   case HCI_CMD_DELETE_STORED_LINK_KEY:
1068     CommandDeleteStoredLinkKey(input);
1069     break;
1070 
1071   default:
1072     // send fake okay msg...
1073     SendEventCommandComplete(msg.Opcode, nullptr, 0);
1074 
1075     if (ogf == HCI_OGF_VENDOR)
1076     {
1077       ERROR_LOG(IOS_WIIMOTE, "Command: vendor specific: 0x%04X (ocf: 0x%x)", msg.Opcode, ocf);
1078       for (int i = 0; i < msg.len; i++)
1079       {
1080         ERROR_LOG(IOS_WIIMOTE, "  0x02%x", input[i]);
1081       }
1082     }
1083     else
1084     {
1085       DEBUG_ASSERT_MSG(IOS_WIIMOTE, 0, "Unknown USB_IOCTL_CTRLMSG: 0x%04X (ocf: 0x%x  ogf 0x%x)",
1086                        msg.Opcode, ocf, ogf);
1087     }
1088     break;
1089   }
1090 
1091   // HCI command is finished, send a reply to command
1092   m_ios.EnqueueIPCReply(ctrl_message.ios_request, ctrl_message.length);
1093 }
1094 
1095 //
1096 //
1097 // --- command helper
1098 //
1099 //
CommandInquiry(const u8 * input)1100 void BluetoothEmu::CommandInquiry(const u8* input)
1101 {
1102   // Inquiry should not be called normally
1103   hci_inquiry_cp inquiry;
1104   std::memcpy(&inquiry, input, sizeof(inquiry));
1105 
1106   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_INQUIRY:");
1107   DEBUG_LOG(IOS_WIIMOTE, "write:");
1108   DEBUG_LOG(IOS_WIIMOTE, "  LAP[0]: 0x%02x", inquiry.lap[0]);
1109   DEBUG_LOG(IOS_WIIMOTE, "  LAP[1]: 0x%02x", inquiry.lap[1]);
1110   DEBUG_LOG(IOS_WIIMOTE, "  LAP[2]: 0x%02x", inquiry.lap[2]);
1111   DEBUG_LOG(IOS_WIIMOTE, "  inquiry_length: %i (N x 1.28) sec", inquiry.inquiry_length);
1112   DEBUG_LOG(IOS_WIIMOTE, "  num_responses: %i (N x 1.28) sec", inquiry.num_responses);
1113 
1114   SendEventCommandStatus(HCI_CMD_INQUIRY);
1115   SendEventInquiryResponse();
1116 }
1117 
CommandInquiryCancel(const u8 * input)1118 void BluetoothEmu::CommandInquiryCancel(const u8* input)
1119 {
1120   hci_inquiry_cancel_rp reply;
1121   reply.status = 0x00;
1122 
1123   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_INQUIRY_CANCEL");
1124 
1125   SendEventCommandComplete(HCI_CMD_INQUIRY_CANCEL, &reply, sizeof(hci_inquiry_cancel_rp));
1126 }
1127 
CommandCreateCon(const u8 * input)1128 void BluetoothEmu::CommandCreateCon(const u8* input)
1129 {
1130   hci_create_con_cp create_connection;
1131   std::memcpy(&create_connection, input, sizeof(create_connection));
1132 
1133   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_CREATE_CON");
1134   DEBUG_LOG(IOS_WIIMOTE, "Input:");
1135   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", create_connection.bdaddr[0],
1136             create_connection.bdaddr[1], create_connection.bdaddr[2], create_connection.bdaddr[3],
1137             create_connection.bdaddr[4], create_connection.bdaddr[5]);
1138   DEBUG_LOG(IOS_WIIMOTE, "  pkt_type: %i", create_connection.pkt_type);
1139   DEBUG_LOG(IOS_WIIMOTE, "  page_scan_rep_mode: %i", create_connection.page_scan_rep_mode);
1140   DEBUG_LOG(IOS_WIIMOTE, "  page_scan_mode: %i", create_connection.page_scan_mode);
1141   DEBUG_LOG(IOS_WIIMOTE, "  clock_offset: %i", create_connection.clock_offset);
1142   DEBUG_LOG(IOS_WIIMOTE, "  accept_role_switch: %i", create_connection.accept_role_switch);
1143 
1144   SendEventCommandStatus(HCI_CMD_CREATE_CON);
1145 
1146   WiimoteDevice* wiimote = AccessWiimote(create_connection.bdaddr);
1147   const bool successful = wiimote && wiimote->EventConnectionRequest();
1148 
1149   // Status 0x08 (Connection Timeout) if WiimoteDevice does not accept the connection.
1150   SendEventConnectionComplete(create_connection.bdaddr, successful ? 0x00 : 0x08);
1151 }
1152 
CommandDisconnect(const u8 * input)1153 void BluetoothEmu::CommandDisconnect(const u8* input)
1154 {
1155   hci_discon_cp disconnect;
1156   std::memcpy(&disconnect, input, sizeof(disconnect));
1157 
1158   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_DISCONNECT");
1159   DEBUG_LOG(IOS_WIIMOTE, "  ConnectionHandle: 0x%04x", disconnect.con_handle);
1160   DEBUG_LOG(IOS_WIIMOTE, "  Reason: 0x%02x", disconnect.reason);
1161 
1162   SendEventCommandStatus(HCI_CMD_DISCONNECT);
1163   SendEventDisconnect(disconnect.con_handle, disconnect.reason);
1164 
1165   WiimoteDevice* wiimote = AccessWiimote(disconnect.con_handle);
1166   if (wiimote)
1167     wiimote->EventDisconnect(disconnect.reason);
1168 }
1169 
CommandAcceptCon(const u8 * input)1170 void BluetoothEmu::CommandAcceptCon(const u8* input)
1171 {
1172   hci_accept_con_cp accept_connection;
1173   std::memcpy(&accept_connection, input, sizeof(accept_connection));
1174 
1175   static constexpr const char* roles[] = {
1176       "Master (0x00)",
1177       "Slave (0x01)",
1178   };
1179 
1180   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_ACCEPT_CON");
1181   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", accept_connection.bdaddr[0],
1182             accept_connection.bdaddr[1], accept_connection.bdaddr[2], accept_connection.bdaddr[3],
1183             accept_connection.bdaddr[4], accept_connection.bdaddr[5]);
1184   DEBUG_LOG(IOS_WIIMOTE, "  role: %s", roles[accept_connection.role]);
1185 
1186   SendEventCommandStatus(HCI_CMD_ACCEPT_CON);
1187 
1188   WiimoteDevice* wiimote = AccessWiimote(accept_connection.bdaddr);
1189   const bool successful = wiimote && wiimote->EventConnectionAccept();
1190 
1191   if (successful)
1192   {
1193     // This connection wants to be the master.
1194     // The controller performs a master-slave switch and notifies the host.
1195     if (accept_connection.role == 0)
1196       SendEventRoleChange(accept_connection.bdaddr, true);
1197 
1198     SendEventConnectionComplete(accept_connection.bdaddr, 0x00);
1199   }
1200   else
1201   {
1202     // Status 0x08 (Connection Timeout) if WiimoteDevice no longer wants this connection.
1203     SendEventConnectionComplete(accept_connection.bdaddr, 0x08);
1204   }
1205 }
1206 
CommandLinkKeyRep(const u8 * input)1207 void BluetoothEmu::CommandLinkKeyRep(const u8* input)
1208 {
1209   hci_link_key_rep_cp key_rep;
1210   std::memcpy(&key_rep, input, sizeof(key_rep));
1211 
1212   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_LINK_KEY_REP");
1213   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", key_rep.bdaddr[0],
1214             key_rep.bdaddr[1], key_rep.bdaddr[2], key_rep.bdaddr[3], key_rep.bdaddr[4],
1215             key_rep.bdaddr[5]);
1216 
1217   hci_link_key_rep_rp reply;
1218   reply.status = 0x00;
1219   reply.bdaddr = key_rep.bdaddr;
1220 
1221   SendEventCommandComplete(HCI_CMD_LINK_KEY_REP, &reply, sizeof(hci_link_key_rep_rp));
1222 }
1223 
CommandLinkKeyNegRep(const u8 * input)1224 void BluetoothEmu::CommandLinkKeyNegRep(const u8* input)
1225 {
1226   hci_link_key_neg_rep_cp key_neg;
1227   std::memcpy(&key_neg, input, sizeof(key_neg));
1228 
1229   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_LINK_KEY_NEG_REP");
1230   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", key_neg.bdaddr[0],
1231             key_neg.bdaddr[1], key_neg.bdaddr[2], key_neg.bdaddr[3], key_neg.bdaddr[4],
1232             key_neg.bdaddr[5]);
1233 
1234   hci_link_key_neg_rep_rp reply;
1235   reply.status = 0x00;
1236   reply.bdaddr = key_neg.bdaddr;
1237 
1238   SendEventCommandComplete(HCI_CMD_LINK_KEY_NEG_REP, &reply, sizeof(hci_link_key_neg_rep_rp));
1239 }
1240 
CommandChangeConPacketType(const u8 * input)1241 void BluetoothEmu::CommandChangeConPacketType(const u8* input)
1242 {
1243   hci_change_con_pkt_type_cp change_packet_type;
1244   std::memcpy(&change_packet_type, input, sizeof(change_packet_type));
1245 
1246   // ntd stack sets packet type 0xcc18, which is HCI_PKT_DH5 | HCI_PKT_DM5 | HCI_PKT_DH1 |
1247   // HCI_PKT_DM1
1248   // dunno what to do...run awayyyyyy!
1249   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_CHANGE_CON_PACKET_TYPE");
1250   DEBUG_LOG(IOS_WIIMOTE, "  ConnectionHandle: 0x%04x", change_packet_type.con_handle);
1251   DEBUG_LOG(IOS_WIIMOTE, "  PacketType: 0x%04x", change_packet_type.pkt_type);
1252 
1253   SendEventCommandStatus(HCI_CMD_CHANGE_CON_PACKET_TYPE);
1254   SendEventConPacketTypeChange(change_packet_type.con_handle, change_packet_type.pkt_type);
1255 }
1256 
CommandAuthenticationRequested(const u8 * input)1257 void BluetoothEmu::CommandAuthenticationRequested(const u8* input)
1258 {
1259   hci_auth_req_cp auth_req;
1260   std::memcpy(&auth_req, input, sizeof(auth_req));
1261 
1262   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_AUTH_REQ");
1263   DEBUG_LOG(IOS_WIIMOTE, "  ConnectionHandle: 0x%04x", auth_req.con_handle);
1264 
1265   SendEventCommandStatus(HCI_CMD_AUTH_REQ);
1266   SendEventAuthenticationCompleted(auth_req.con_handle);
1267 }
1268 
CommandRemoteNameReq(const u8 * input)1269 void BluetoothEmu::CommandRemoteNameReq(const u8* input)
1270 {
1271   hci_remote_name_req_cp remote_name_req;
1272   std::memcpy(&remote_name_req, input, sizeof(remote_name_req));
1273 
1274   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_REMOTE_NAME_REQ");
1275   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", remote_name_req.bdaddr[0],
1276             remote_name_req.bdaddr[1], remote_name_req.bdaddr[2], remote_name_req.bdaddr[3],
1277             remote_name_req.bdaddr[4], remote_name_req.bdaddr[5]);
1278   DEBUG_LOG(IOS_WIIMOTE, "  page_scan_rep_mode: %i", remote_name_req.page_scan_rep_mode);
1279   DEBUG_LOG(IOS_WIIMOTE, "  page_scan_mode: %i", remote_name_req.page_scan_mode);
1280   DEBUG_LOG(IOS_WIIMOTE, "  clock_offset: %i", remote_name_req.clock_offset);
1281 
1282   SendEventCommandStatus(HCI_CMD_REMOTE_NAME_REQ);
1283   SendEventRemoteNameReq(remote_name_req.bdaddr);
1284 }
1285 
CommandReadRemoteFeatures(const u8 * input)1286 void BluetoothEmu::CommandReadRemoteFeatures(const u8* input)
1287 {
1288   hci_read_remote_features_cp read_remote_features;
1289   std::memcpy(&read_remote_features, input, sizeof(read_remote_features));
1290 
1291   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_READ_REMOTE_FEATURES");
1292   DEBUG_LOG(IOS_WIIMOTE, "  ConnectionHandle: 0x%04x", read_remote_features.con_handle);
1293 
1294   SendEventCommandStatus(HCI_CMD_READ_REMOTE_FEATURES);
1295   SendEventReadRemoteFeatures(read_remote_features.con_handle);
1296 }
1297 
CommandReadRemoteVerInfo(const u8 * input)1298 void BluetoothEmu::CommandReadRemoteVerInfo(const u8* input)
1299 {
1300   hci_read_remote_ver_info_cp read_remote_ver_info;
1301   std::memcpy(&read_remote_ver_info, input, sizeof(read_remote_ver_info));
1302 
1303   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_READ_REMOTE_VER_INFO");
1304   DEBUG_LOG(IOS_WIIMOTE, "  ConnectionHandle: 0x%02x", read_remote_ver_info.con_handle);
1305 
1306   SendEventCommandStatus(HCI_CMD_READ_REMOTE_VER_INFO);
1307   SendEventReadRemoteVerInfo(read_remote_ver_info.con_handle);
1308 }
1309 
CommandReadClockOffset(const u8 * input)1310 void BluetoothEmu::CommandReadClockOffset(const u8* input)
1311 {
1312   hci_read_clock_offset_cp read_clock_offset;
1313   std::memcpy(&read_clock_offset, input, sizeof(read_clock_offset));
1314 
1315   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_READ_CLOCK_OFFSET");
1316   DEBUG_LOG(IOS_WIIMOTE, "  ConnectionHandle: 0x%02x", read_clock_offset.con_handle);
1317 
1318   SendEventCommandStatus(HCI_CMD_READ_CLOCK_OFFSET);
1319   SendEventReadClockOffsetComplete(read_clock_offset.con_handle);
1320 }
1321 
CommandSniffMode(const u8 * input)1322 void BluetoothEmu::CommandSniffMode(const u8* input)
1323 {
1324   hci_sniff_mode_cp sniff_mode;
1325   std::memcpy(&sniff_mode, input, sizeof(sniff_mode));
1326 
1327   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_SNIFF_MODE");
1328   DEBUG_LOG(IOS_WIIMOTE, "  ConnectionHandle: 0x%04x", sniff_mode.con_handle);
1329   DEBUG_LOG(IOS_WIIMOTE, "  max_interval: %f msec", sniff_mode.max_interval * .625);
1330   DEBUG_LOG(IOS_WIIMOTE, "  min_interval: %f msec", sniff_mode.min_interval * .625);
1331   DEBUG_LOG(IOS_WIIMOTE, "  attempt: %f msec", sniff_mode.attempt * 1.25);
1332   DEBUG_LOG(IOS_WIIMOTE, "  timeout: %f msec", sniff_mode.timeout * 1.25);
1333 
1334   SendEventCommandStatus(HCI_CMD_SNIFF_MODE);
1335   SendEventModeChange(sniff_mode.con_handle, 0x02, sniff_mode.max_interval);  // 0x02 - sniff mode
1336 }
1337 
CommandWriteLinkPolicy(const u8 * input)1338 void BluetoothEmu::CommandWriteLinkPolicy(const u8* input)
1339 {
1340   hci_write_link_policy_settings_cp link_policy;
1341   std::memcpy(&link_policy, input, sizeof(link_policy));
1342 
1343   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_WRITE_LINK_POLICY_SETTINGS");
1344   DEBUG_LOG(IOS_WIIMOTE, "  ConnectionHandle: 0x%04x", link_policy.con_handle);
1345   DEBUG_LOG(IOS_WIIMOTE, "  Policy: 0x%04x", link_policy.settings);
1346 
1347   SendEventCommandStatus(HCI_CMD_WRITE_LINK_POLICY_SETTINGS);
1348 }
1349 
CommandReset(const u8 * input)1350 void BluetoothEmu::CommandReset(const u8* input)
1351 {
1352   hci_status_rp reply;
1353   reply.status = 0x00;
1354 
1355   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_RESET");
1356   SendEventCommandComplete(HCI_CMD_RESET, &reply, sizeof(hci_status_rp));
1357 
1358   // TODO: We should actually reset connections and channels and everything here.
1359 }
1360 
CommandSetEventFilter(const u8 * input)1361 void BluetoothEmu::CommandSetEventFilter(const u8* input)
1362 {
1363   hci_set_event_filter_cp set_event_filter;
1364   std::memcpy(&set_event_filter, input, sizeof(set_event_filter));
1365 
1366   // It looks like software only ever sets a "new device inquiry response" filter.
1367   // This is one we can safely ignore because of our fake inquiry implementation
1368   // and documentation says controllers can opt to not implement this filter anyways.
1369 
1370   // TODO: There should be a warn log if an actual filter is being set.
1371 
1372   hci_set_event_filter_rp reply;
1373   reply.status = 0x00;
1374 
1375   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_SET_EVENT_FILTER:");
1376   DEBUG_LOG(IOS_WIIMOTE, "  filter_type: %i", set_event_filter.filter_type);
1377   DEBUG_LOG(IOS_WIIMOTE, "  filter_condition_type: %i", set_event_filter.filter_condition_type);
1378 
1379   SendEventCommandComplete(HCI_CMD_SET_EVENT_FILTER, &reply, sizeof(hci_set_event_filter_rp));
1380 }
1381 
CommandWritePinType(const u8 * input)1382 void BluetoothEmu::CommandWritePinType(const u8* input)
1383 {
1384   hci_write_pin_type_cp write_pin_type;
1385   std::memcpy(&write_pin_type, input, sizeof(write_pin_type));
1386 
1387   hci_write_pin_type_rp reply;
1388   reply.status = 0x00;
1389 
1390   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_WRITE_PIN_TYPE:");
1391   DEBUG_LOG(IOS_WIIMOTE, "  pin_type: %x", write_pin_type.pin_type);
1392 
1393   SendEventCommandComplete(HCI_CMD_WRITE_PIN_TYPE, &reply, sizeof(hci_write_pin_type_rp));
1394 }
1395 
CommandReadStoredLinkKey(const u8 * input)1396 void BluetoothEmu::CommandReadStoredLinkKey(const u8* input)
1397 {
1398   hci_read_stored_link_key_cp read_stored_link_key;
1399   std::memcpy(&read_stored_link_key, input, sizeof(read_stored_link_key));
1400 
1401   hci_read_stored_link_key_rp reply;
1402   reply.status = 0x00;
1403   reply.num_keys_read = 0;
1404   reply.max_num_keys = 255;
1405 
1406   if (read_stored_link_key.read_all == 1)
1407     reply.num_keys_read = static_cast<u16>(m_wiimotes.size());
1408   else
1409     ERROR_LOG(IOS_WIIMOTE, "CommandReadStoredLinkKey isn't looking for all devices");
1410 
1411   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_READ_STORED_LINK_KEY:");
1412   DEBUG_LOG(IOS_WIIMOTE, "input:");
1413   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", read_stored_link_key.bdaddr[0],
1414             read_stored_link_key.bdaddr[1], read_stored_link_key.bdaddr[2],
1415             read_stored_link_key.bdaddr[3], read_stored_link_key.bdaddr[4],
1416             read_stored_link_key.bdaddr[5]);
1417   DEBUG_LOG(IOS_WIIMOTE, "  read_all: %i", read_stored_link_key.read_all);
1418   DEBUG_LOG(IOS_WIIMOTE, "return:");
1419   DEBUG_LOG(IOS_WIIMOTE, "  max_num_keys: %i", reply.max_num_keys);
1420   DEBUG_LOG(IOS_WIIMOTE, "  num_keys_read: %i", reply.num_keys_read);
1421 
1422   SendEventLinkKeyNotification(static_cast<u8>(reply.num_keys_read));
1423   SendEventCommandComplete(HCI_CMD_READ_STORED_LINK_KEY, &reply,
1424                            sizeof(hci_read_stored_link_key_rp));
1425 }
1426 
CommandDeleteStoredLinkKey(const u8 * input)1427 void BluetoothEmu::CommandDeleteStoredLinkKey(const u8* input)
1428 {
1429   hci_delete_stored_link_key_cp delete_stored_link_key;
1430   std::memcpy(&delete_stored_link_key, input, sizeof(delete_stored_link_key));
1431 
1432   INFO_LOG(IOS_WIIMOTE, "Command: HCI_OCF_DELETE_STORED_LINK_KEY");
1433   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", delete_stored_link_key.bdaddr[0],
1434             delete_stored_link_key.bdaddr[1], delete_stored_link_key.bdaddr[2],
1435             delete_stored_link_key.bdaddr[3], delete_stored_link_key.bdaddr[4],
1436             delete_stored_link_key.bdaddr[5]);
1437   DEBUG_LOG(IOS_WIIMOTE, "  delete_all: 0x%01x", delete_stored_link_key.delete_all);
1438 
1439   const WiimoteDevice* wiimote = AccessWiimote(delete_stored_link_key.bdaddr);
1440   if (wiimote == nullptr)
1441     return;
1442 
1443   hci_delete_stored_link_key_rp reply;
1444   reply.status = 0x00;
1445   reply.num_keys_deleted = 0;
1446 
1447   SendEventCommandComplete(HCI_CMD_DELETE_STORED_LINK_KEY, &reply,
1448                            sizeof(hci_delete_stored_link_key_rp));
1449 
1450   ERROR_LOG(IOS_WIIMOTE, "HCI: CommandDeleteStoredLinkKey... Probably the security for linking "
1451                          "has failed. Could be a problem with loading the SCONF");
1452 }
1453 
CommandWriteLocalName(const u8 * input)1454 void BluetoothEmu::CommandWriteLocalName(const u8* input)
1455 {
1456   hci_write_local_name_cp write_local_name;
1457   std::memcpy(&write_local_name, input, sizeof(write_local_name));
1458 
1459   hci_write_local_name_rp reply;
1460   reply.status = 0x00;
1461 
1462   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_WRITE_LOCAL_NAME:");
1463   DEBUG_LOG(IOS_WIIMOTE, "  local_name: %s", write_local_name.name);
1464 
1465   SendEventCommandComplete(HCI_CMD_WRITE_LOCAL_NAME, &reply, sizeof(hci_write_local_name_rp));
1466 }
1467 
CommandWritePageTimeOut(const u8 * input)1468 void BluetoothEmu::CommandWritePageTimeOut(const u8* input)
1469 {
1470   hci_write_page_timeout_cp write_page_timeout;
1471   std::memcpy(&write_page_timeout, input, sizeof(write_page_timeout));
1472 
1473   hci_host_buffer_size_rp reply;
1474   reply.status = 0x00;
1475 
1476   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_WRITE_PAGE_TIMEOUT:");
1477   DEBUG_LOG(IOS_WIIMOTE, "  timeout: %i", write_page_timeout.timeout);
1478 
1479   SendEventCommandComplete(HCI_CMD_WRITE_PAGE_TIMEOUT, &reply, sizeof(hci_host_buffer_size_rp));
1480 }
1481 
CommandWriteScanEnable(const u8 * input)1482 void BluetoothEmu::CommandWriteScanEnable(const u8* input)
1483 {
1484   hci_write_scan_enable_cp write_scan_enable;
1485   std::memcpy(&write_scan_enable, input, sizeof(write_scan_enable));
1486 
1487   m_scan_enable = write_scan_enable.scan_enable;
1488 
1489   hci_write_scan_enable_rp reply;
1490   reply.status = 0x00;
1491 
1492   static constexpr const char* scanning[] = {
1493       "HCI_NO_SCAN_ENABLE",
1494       "HCI_INQUIRY_SCAN_ENABLE",
1495       "HCI_PAGE_SCAN_ENABLE",
1496       "HCI_INQUIRY_AND_PAGE_SCAN_ENABLE",
1497   };
1498 
1499   DEBUG_LOG(IOS_WIIMOTE, "Command: HCI_CMD_WRITE_SCAN_ENABLE: (0x%02x)",
1500             write_scan_enable.scan_enable);
1501   DEBUG_LOG(IOS_WIIMOTE, "  scan_enable: %s", scanning[write_scan_enable.scan_enable]);
1502 
1503   SendEventCommandComplete(HCI_CMD_WRITE_SCAN_ENABLE, &reply, sizeof(hci_write_scan_enable_rp));
1504 }
1505 
CommandWriteUnitClass(const u8 * input)1506 void BluetoothEmu::CommandWriteUnitClass(const u8* input)
1507 {
1508   hci_write_unit_class_cp write_unit_class;
1509   std::memcpy(&write_unit_class, input, sizeof(write_unit_class));
1510 
1511   hci_write_unit_class_rp reply;
1512   reply.status = 0x00;
1513 
1514   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_WRITE_UNIT_CLASS:");
1515   DEBUG_LOG(IOS_WIIMOTE, "  COD[0]: 0x%02x", write_unit_class.uclass[0]);
1516   DEBUG_LOG(IOS_WIIMOTE, "  COD[1]: 0x%02x", write_unit_class.uclass[1]);
1517   DEBUG_LOG(IOS_WIIMOTE, "  COD[2]: 0x%02x", write_unit_class.uclass[2]);
1518 
1519   SendEventCommandComplete(HCI_CMD_WRITE_UNIT_CLASS, &reply, sizeof(hci_write_unit_class_rp));
1520 }
1521 
CommandHostBufferSize(const u8 * input)1522 void BluetoothEmu::CommandHostBufferSize(const u8* input)
1523 {
1524   hci_host_buffer_size_cp host_buffer_size;
1525   std::memcpy(&host_buffer_size, input, sizeof(host_buffer_size));
1526 
1527   hci_host_buffer_size_rp reply;
1528   reply.status = 0x00;
1529 
1530   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_HOST_BUFFER_SIZE:");
1531   DEBUG_LOG(IOS_WIIMOTE, "  max_acl_size: %i", host_buffer_size.max_acl_size);
1532   DEBUG_LOG(IOS_WIIMOTE, "  max_sco_size: %i", host_buffer_size.max_sco_size);
1533   DEBUG_LOG(IOS_WIIMOTE, "  num_acl_pkts: %i", host_buffer_size.num_acl_pkts);
1534   DEBUG_LOG(IOS_WIIMOTE, "  num_sco_pkts: %i", host_buffer_size.num_sco_pkts);
1535 
1536   SendEventCommandComplete(HCI_CMD_HOST_BUFFER_SIZE, &reply, sizeof(hci_host_buffer_size_rp));
1537 }
1538 
CommandWriteLinkSupervisionTimeout(const u8 * input)1539 void BluetoothEmu::CommandWriteLinkSupervisionTimeout(const u8* input)
1540 {
1541   hci_write_link_supervision_timeout_cp supervision;
1542   std::memcpy(&supervision, input, sizeof(supervision));
1543 
1544   // timeout of 0 means timing out is disabled
1545   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT");
1546   DEBUG_LOG(IOS_WIIMOTE, "  con_handle: 0x%04x", supervision.con_handle);
1547   DEBUG_LOG(IOS_WIIMOTE, "  timeout: 0x%02x", supervision.timeout);
1548 
1549   hci_write_link_supervision_timeout_rp reply;
1550   reply.status = 0x00;
1551   reply.con_handle = supervision.con_handle;
1552 
1553   SendEventCommandComplete(HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT, &reply,
1554                            sizeof(hci_write_link_supervision_timeout_rp));
1555 }
1556 
CommandWriteInquiryScanType(const u8 * input)1557 void BluetoothEmu::CommandWriteInquiryScanType(const u8* input)
1558 {
1559   hci_write_inquiry_scan_type_cp set_event_filter;
1560   std::memcpy(&set_event_filter, input, sizeof(set_event_filter));
1561 
1562   hci_write_inquiry_scan_type_rp reply;
1563   reply.status = 0x00;
1564 
1565   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_WRITE_INQUIRY_SCAN_TYPE:");
1566   DEBUG_LOG(IOS_WIIMOTE, "  type: %i", set_event_filter.type);
1567 
1568   SendEventCommandComplete(HCI_CMD_WRITE_INQUIRY_SCAN_TYPE, &reply,
1569                            sizeof(hci_write_inquiry_scan_type_rp));
1570 }
1571 
CommandWriteInquiryMode(const u8 * input)1572 void BluetoothEmu::CommandWriteInquiryMode(const u8* input)
1573 {
1574   hci_write_inquiry_mode_cp inquiry_mode;
1575   std::memcpy(&inquiry_mode, input, sizeof(inquiry_mode));
1576 
1577   hci_write_inquiry_mode_rp reply;
1578   reply.status = 0x00;
1579 
1580   // TODO: Software seems to set an RSSI mode but our fake inquiries generate standard events.
1581 
1582   static constexpr const char* inquiry_mode_tag[] = {
1583       "Standard Inquiry Result event format (default)",
1584       "Inquiry Result format with RSSI",
1585       "Inquiry Result with RSSI format or Extended Inquiry Result format",
1586   };
1587   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_WRITE_INQUIRY_MODE:");
1588   DEBUG_LOG(IOS_WIIMOTE, "  mode: %s", inquiry_mode_tag[inquiry_mode.mode]);
1589 
1590   SendEventCommandComplete(HCI_CMD_WRITE_INQUIRY_MODE, &reply, sizeof(hci_write_inquiry_mode_rp));
1591 }
1592 
CommandWritePageScanType(const u8 * input)1593 void BluetoothEmu::CommandWritePageScanType(const u8* input)
1594 {
1595   hci_write_page_scan_type_cp write_page_scan_type;
1596   std::memcpy(&write_page_scan_type, input, sizeof(write_page_scan_type));
1597 
1598   hci_write_page_scan_type_rp reply;
1599   reply.status = 0x00;
1600 
1601   static constexpr const char* page_scan_type[] = {
1602       "Mandatory: Standard Scan (default)",
1603       "Optional: Interlaced Scan",
1604   };
1605 
1606   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_WRITE_PAGE_SCAN_TYPE:");
1607   DEBUG_LOG(IOS_WIIMOTE, "  type: %s", page_scan_type[write_page_scan_type.type]);
1608 
1609   SendEventCommandComplete(HCI_CMD_WRITE_PAGE_SCAN_TYPE, &reply,
1610                            sizeof(hci_write_page_scan_type_rp));
1611 }
1612 
CommandReadLocalVer(const u8 * input)1613 void BluetoothEmu::CommandReadLocalVer(const u8* input)
1614 {
1615   hci_read_local_ver_rp reply;
1616   reply.status = 0x00;
1617   reply.hci_version = 0x03;       // HCI version: 1.1
1618   reply.hci_revision = 0x40a7;    // current revision (?)
1619   reply.lmp_version = 0x03;       // LMP version: 1.1
1620   reply.manufacturer = 0x000F;    // manufacturer: reserved for tests
1621   reply.lmp_subversion = 0x430e;  // LMP subversion
1622 
1623   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_READ_LOCAL_VER:");
1624   DEBUG_LOG(IOS_WIIMOTE, "return:");
1625   DEBUG_LOG(IOS_WIIMOTE, "  status:         %i", reply.status);
1626   DEBUG_LOG(IOS_WIIMOTE, "  hci_revision:   %i", reply.hci_revision);
1627   DEBUG_LOG(IOS_WIIMOTE, "  lmp_version:    %i", reply.lmp_version);
1628   DEBUG_LOG(IOS_WIIMOTE, "  manufacturer:   %i", reply.manufacturer);
1629   DEBUG_LOG(IOS_WIIMOTE, "  lmp_subversion: %i", reply.lmp_subversion);
1630 
1631   SendEventCommandComplete(HCI_CMD_READ_LOCAL_VER, &reply, sizeof(hci_read_local_ver_rp));
1632 }
1633 
CommandReadLocalFeatures(const u8 * input)1634 void BluetoothEmu::CommandReadLocalFeatures(const u8* input)
1635 {
1636   hci_read_local_features_rp reply;
1637   reply.status = 0x00;
1638   reply.features[0] = 0xFF;
1639   reply.features[1] = 0xFF;
1640   reply.features[2] = 0x8D;
1641   reply.features[3] = 0xFE;
1642   reply.features[4] = 0x9B;
1643   reply.features[5] = 0xF9;
1644   reply.features[6] = 0x00;
1645   reply.features[7] = 0x80;
1646 
1647   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_READ_LOCAL_FEATURES:");
1648   DEBUG_LOG(IOS_WIIMOTE, "return:");
1649   DEBUG_LOG(IOS_WIIMOTE, "  features: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", reply.features[0],
1650             reply.features[1], reply.features[2], reply.features[3], reply.features[4],
1651             reply.features[5], reply.features[6], reply.features[7]);
1652 
1653   SendEventCommandComplete(HCI_CMD_READ_LOCAL_FEATURES, &reply, sizeof(hci_read_local_features_rp));
1654 }
1655 
CommandReadBufferSize(const u8 * input)1656 void BluetoothEmu::CommandReadBufferSize(const u8* input)
1657 {
1658   hci_read_buffer_size_rp reply;
1659   reply.status = 0x00;
1660   reply.max_acl_size = ACL_PKT_SIZE;
1661   // Due to how the widcomm stack which Nintendo uses is coded, we must never
1662   // let the stack think the controller is buffering more than 10 data packets
1663   // - it will cause a u8 underflow and royally screw things up.
1664   reply.num_acl_pkts = ACL_PKT_NUM;
1665   reply.max_sco_size = SCO_PKT_SIZE;
1666   reply.num_sco_pkts = SCO_PKT_NUM;
1667 
1668   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_READ_BUFFER_SIZE:");
1669   DEBUG_LOG(IOS_WIIMOTE, "return:");
1670   DEBUG_LOG(IOS_WIIMOTE, "  max_acl_size: %i", reply.max_acl_size);
1671   DEBUG_LOG(IOS_WIIMOTE, "  num_acl_pkts: %i", reply.num_acl_pkts);
1672   DEBUG_LOG(IOS_WIIMOTE, "  max_sco_size: %i", reply.max_sco_size);
1673   DEBUG_LOG(IOS_WIIMOTE, "  num_sco_pkts: %i", reply.num_sco_pkts);
1674 
1675   SendEventCommandComplete(HCI_CMD_READ_BUFFER_SIZE, &reply, sizeof(hci_read_buffer_size_rp));
1676 }
1677 
CommandReadBDAdrr(const u8 * input)1678 void BluetoothEmu::CommandReadBDAdrr(const u8* input)
1679 {
1680   hci_read_bdaddr_rp reply;
1681   reply.status = 0x00;
1682   reply.bdaddr = m_controller_bd;
1683 
1684   INFO_LOG(IOS_WIIMOTE, "Command: HCI_CMD_READ_BDADDR:");
1685   DEBUG_LOG(IOS_WIIMOTE, "return:");
1686   DEBUG_LOG(IOS_WIIMOTE, "  bd: %02x:%02x:%02x:%02x:%02x:%02x", reply.bdaddr[0], reply.bdaddr[1],
1687             reply.bdaddr[2], reply.bdaddr[3], reply.bdaddr[4], reply.bdaddr[5]);
1688 
1689   SendEventCommandComplete(HCI_CMD_READ_BDADDR, &reply, sizeof(hci_read_bdaddr_rp));
1690 }
1691 
CommandVendorSpecific_FC4F(const u8 * input,u32 size)1692 void BluetoothEmu::CommandVendorSpecific_FC4F(const u8* input, u32 size)
1693 {
1694   // callstack...
1695   // BTM_VendorSpecificCommad()
1696   // WUDiRemovePatch()
1697   // WUDiAppendRuntimePatch()
1698   // WUDiGetFirmwareVersion()
1699   // WUDiStackSetupComplete()
1700 
1701   hci_status_rp reply;
1702   reply.status = 0x00;
1703 
1704   INFO_LOG(IOS_WIIMOTE, "Command: CommandVendorSpecific_FC4F: (callstack WUDiRemovePatch)");
1705   DEBUG_LOG(IOS_WIIMOTE, "Input (size 0x%x):", size);
1706 
1707   Dolphin_Debugger::PrintDataBuffer(Common::Log::IOS_WIIMOTE, input, size, "Data: ");
1708 
1709   SendEventCommandComplete(0xFC4F, &reply, sizeof(hci_status_rp));
1710 }
1711 
CommandVendorSpecific_FC4C(const u8 * input,u32 size)1712 void BluetoothEmu::CommandVendorSpecific_FC4C(const u8* input, u32 size)
1713 {
1714   hci_status_rp reply;
1715   reply.status = 0x00;
1716 
1717   DEBUG_LOG(IOS_WIIMOTE, "Command: CommandVendorSpecific_FC4C:");
1718   DEBUG_LOG(IOS_WIIMOTE, "Input (size 0x%x):", size);
1719   Dolphin_Debugger::PrintDataBuffer(Common::Log::IOS_WIIMOTE, input, size, "Data: ");
1720 
1721   SendEventCommandComplete(0xFC4C, &reply, sizeof(hci_status_rp));
1722 }
1723 
AccessWiimoteByIndex(std::size_t index)1724 WiimoteDevice* BluetoothEmu::AccessWiimoteByIndex(std::size_t index)
1725 {
1726   if (index < MAX_BBMOTES)
1727     return m_wiimotes[index].get();
1728 
1729   return nullptr;
1730 }
1731 
GetConnectionHandle(const bdaddr_t & address)1732 u16 BluetoothEmu::GetConnectionHandle(const bdaddr_t& address)
1733 {
1734   // Handles are normally generated per connection but HLE allows fixed values for each remote.
1735   return 0x100 + address.back();
1736 }
1737 
GetWiimoteNumberFromConnectionHandle(u16 connection_handle)1738 u32 BluetoothEmu::GetWiimoteNumberFromConnectionHandle(u16 connection_handle)
1739 {
1740   // Fixed handle values are generated in GetConnectionHandle.
1741   return connection_handle & 0xff;
1742 }
1743 
AccessWiimote(const bdaddr_t & address)1744 WiimoteDevice* BluetoothEmu::AccessWiimote(const bdaddr_t& address)
1745 {
1746   // Fixed bluetooth addresses are generated in WiimoteDevice::WiimoteDevice.
1747   const auto wiimote = AccessWiimoteByIndex(address.back());
1748 
1749   if (wiimote && wiimote->GetBD() == address)
1750     return wiimote;
1751 
1752   return nullptr;
1753 }
1754 
AccessWiimote(u16 connection_handle)1755 WiimoteDevice* BluetoothEmu::AccessWiimote(u16 connection_handle)
1756 {
1757   const auto wiimote =
1758       AccessWiimoteByIndex(GetWiimoteNumberFromConnectionHandle(connection_handle));
1759 
1760   if (wiimote)
1761     return wiimote;
1762 
1763   ERROR_LOG(IOS_WIIMOTE, "Can't find Wiimote by connection handle %02x", connection_handle);
1764   PanicAlertT("Can't find Wii Remote by connection handle %02x", connection_handle);
1765 
1766   return nullptr;
1767 }
1768 
1769 }  // namespace Device
1770 }  // namespace IOS::HLE
1771