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