Bug Summary

File:Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp
Location:line 149, column 6
Description:Value stored to 'BufferOut' during its initialization is never read

Annotated Source Code

1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "../Core.h"
6#include "../Debugger/Debugger_SymbolMap.h"
7#include "../HW/WII_IPC.h"
8#include "WII_IPC_HLE.h"
9#include "WII_IPC_HLE_Device_hid.h"
10#include "errno.h"
11
12#if defined(_MSC_VER) || defined(__MINGW32__)
13# include <time.h>
14#ifndef _TIMEVAL_DEFINED /* also in winsock[2].h */
15#define _TIMEVAL_DEFINED
16struct timeval {
17 long tv_sec;
18 long tv_usec;
19};
20#endif /* _TIMEVAL_DEFINED */
21#else
22# include <sys/time.h>
23#endif
24
25#define MAX_DEVICE_DEVNUM256 256
26static u64 hidDeviceAliases[MAX_DEVICE_DEVNUM256];
27
28// Regular thread
29void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid)
30{
31 timeval tv;
32 tv.tv_sec = 0;
33 tv.tv_usec = 500;
34 while (hid->usb_thread_running)
35 {
36
37 static u16 timeToFill = 0;
38 if (timeToFill == 0)
39 {
40 std::lock_guard<std::mutex> lk(hid->s_device_list_reply);
41 if (hid->deviceCommandAddress != 0){
42 hid->FillOutDevices(Memory::Read_U32(hid->deviceCommandAddress + 0x18), Memory::Read_U32(hid->deviceCommandAddress + 0x1C));
43
44 Memory::Write_U32(8, hid->deviceCommandAddress);
45 // IOS seems to write back the command that was responded to
46 Memory::Write_U32(/*COMMAND_IOCTL*/ 6, hid->deviceCommandAddress + 8);
47
48 // Return value
49 Memory::Write_U32(0, hid->deviceCommandAddress + 4);
50
51 WII_IPC_HLE_Interface::EnqueReplyCallback(hid->deviceCommandAddress);
52 hid->deviceCommandAddress = 0;
53 }
54 }
55 timeToFill+=8;
56 libusb_handle_events_timeout(NULL__null, &tv);
57 }
58
59 return;
60}
61
62void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer *transfer)
63{
64 int ret = HIDERR_NO_DEVICE_FOUND-4;
65 u32 replyAddress = (u32)(size_t)transfer->user_data;
66 if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
67 {
68 ret = transfer->length;
69 }
70
71 Memory::Write_U32(8, replyAddress);
72 // IOS seems to write back the command that was responded to
73 Memory::Write_U32(/*COMMAND_IOCTL*/ 6, replyAddress + 8);
74
75 // Return value
76 Memory::Write_U32(ret, replyAddress + 4);
77
78 WII_IPC_HLE_Interface::EnqueReplyCallback(replyAddress);
79 //DEBUG_LOG(WII_IPC_HID, "OMG OMG OMG I GOT A CALLBACK, IMMA BE FAMOUS %d %d %d", transfer->actual_length, transfer->length, transfer->status);
80}
81
82
83CWII_IPC_HLE_Device_hid::CWII_IPC_HLE_Device_hid(u32 _DeviceID, const std::string& _rDeviceName)
84 : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
85{
86 deviceCommandAddress = 0;
87 memset(hidDeviceAliases, 0, sizeof(hidDeviceAliases));
88 int ret = libusb_init(NULL__null);
89 if (ret)
90 {
91 ERROR_LOG(WII_IPC_HID, "libusb_init failed with error: %d", ret)do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 91, "libusb_init failed with error: %d", ret); } } while (0
)
;
92 }
93 else
94 {
95 usb_thread_running = true;
96 usb_thread = std::thread(checkUsbUpdates, this);
97 }
98}
99
100CWII_IPC_HLE_Device_hid::~CWII_IPC_HLE_Device_hid()
101{
102 bool deinit_libusb = false;
103 if (usb_thread_running)
104 {
105 usb_thread_running = false;
106 usb_thread.join();
107 deinit_libusb = true;
108 }
109
110 for ( std::map<u32,libusb_device_handle*>::const_iterator iter = open_devices.begin(); iter != open_devices.end(); ++iter )
111 {
112 libusb_close(iter->second);
113 }
114 open_devices.clear();
115
116 if (deinit_libusb)
117 libusb_exit(NULL__null);
118}
119
120bool CWII_IPC_HLE_Device_hid::Open(u32 _CommandAddress, u32 _Mode)
121{
122 DEBUG_LOG(WII_IPC_HID, "HID::Open")do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 122, "HID::Open"); } } while (0)
;
123 m_Active = true;
124 Memory::Write_U32(GetDeviceID(), _CommandAddress + 4);
125 return true;
126}
127
128bool CWII_IPC_HLE_Device_hid::Close(u32 _CommandAddress, bool _bForce)
129{
130 DEBUG_LOG(WII_IPC_HID, "HID::Close")do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 130, "HID::Close"); } } while (0)
;
131 m_Active = false;
132 if (!_bForce)
133 Memory::Write_U32(0, _CommandAddress + 4);
134 return true;
135}
136
137u32 CWII_IPC_HLE_Device_hid::Update()
138{
139
140 u32 work_done = 0;
141 return work_done;
142}
143
144bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
145{
146 u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
147 u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
148 u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
149 u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
Value stored to 'BufferOut' during its initialization is never read
150 u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
151
152 u32 ReturnValue = 0;
153 switch (Parameter)
154 {
155 case IOCTL_HID_GET_ATTACHED:
156 {
157 DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Get Attached) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 158, "HID::IOCtl(Get Attached) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, BufferIn, BufferInSize, BufferOut, BufferOutSize); } } while
(0)
158 BufferIn, BufferInSize, BufferOut, BufferOutSize)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 158, "HID::IOCtl(Get Attached) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, BufferIn, BufferInSize, BufferOut, BufferOutSize); } } while
(0)
;
159 deviceCommandAddress = _CommandAddress;
160 return false;
161 break;
162 }
163 case IOCTL_HID_OPEN:
164 {
165 DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Open) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 166, "HID::IOCtl(Open) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, BufferIn, BufferInSize, BufferOut, BufferOutSize); } } while
(0)
166 BufferIn, BufferInSize, BufferOut, BufferOutSize)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 166, "HID::IOCtl(Open) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, BufferIn, BufferInSize, BufferOut, BufferOutSize); } } while
(0)
;
167
168 //hid version, apparently
169 ReturnValue = 0x40001;
170 break;
171 }
172 case IOCTL_HID_SET_SUSPEND:
173 {
174 DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Set Suspend) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 175, "HID::IOCtl(Set Suspend) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, BufferIn, BufferInSize, BufferOut, BufferOutSize); } } while
(0)
175 BufferIn, BufferInSize, BufferOut, BufferOutSize)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 175, "HID::IOCtl(Set Suspend) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, BufferIn, BufferInSize, BufferOut, BufferOutSize); } } while
(0)
;
176 // not actually implemented in IOS
177 ReturnValue = 0;
178 break;
179 }
180 case IOCTL_HID_CANCEL_INTERRUPT:
181 {
182 DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Cancel Interrupt) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 183, "HID::IOCtl(Cancel Interrupt) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, BufferIn, BufferInSize, BufferOut, BufferOutSize); } } while
(0)
183 BufferIn, BufferInSize, BufferOut, BufferOutSize)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 183, "HID::IOCtl(Cancel Interrupt) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, BufferIn, BufferInSize, BufferOut, BufferOutSize); } } while
(0)
;
184 ReturnValue = 0;
185 break;
186 }
187 case IOCTL_HID_CONTROL:
188 {
189 /*
190 ERROR CODES:
191 -4 Cant find device specified
192 */
193
194 u32 dev_num = Memory::Read_U32(BufferIn+0x10);
195 u8 bmRequestType = Memory::Read_U8(BufferIn+0x14);
196 u8 bRequest = Memory::Read_U8(BufferIn+0x15);
197 u16 wValue = Memory::Read_U16(BufferIn+0x16);
198 u16 wIndex = Memory::Read_U16(BufferIn+0x18);
199 u16 wLength = Memory::Read_U16(BufferIn+0x1A);
200 u32 data = Memory::Read_U32(BufferIn+0x1C);
201
202 ReturnValue = HIDERR_NO_DEVICE_FOUND-4;
203
204 libusb_device_handle * dev_handle = GetDeviceByDevNum(dev_num);
205
206 if (dev_handle == NULL__null)
207 {
208 DEBUG_LOG(WII_IPC_HID, "Could not find handle: %X", dev_num)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 208, "Could not find handle: %X", dev_num); } } while (0)
;
209 break;
210 }
211 struct libusb_transfer *transfer = libusb_alloc_transfer(0);
212 transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
213
214 u8 * buffer = (u8*)malloc(wLength + LIBUSB_CONTROL_SETUP_SIZE(sizeof(struct libusb_control_setup)));
215 libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength);
216 memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE(sizeof(struct libusb_control_setup)), Memory::GetPointer(data), wLength);
217 libusb_fill_control_transfer(transfer, dev_handle, buffer, handleUsbUpdates, (void*)(size_t)_CommandAddress, /* no timeout */ 0);
218 libusb_submit_transfer(transfer);
219
220 //DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
221 // bmRequestType, bRequest, BufferIn, BufferInSize, BufferOut, BufferOutSize);
222
223 // It's the async way!
224 return false;
225 break;
226 }
227 case IOCTL_HID_INTERRUPT_OUT:
228 case IOCTL_HID_INTERRUPT_IN:
229 {
230 u32 dev_num = Memory::Read_U32(BufferIn+0x10);
231 u32 endpoint = Memory::Read_U32(BufferIn+0x14);
232 u32 length = Memory::Read_U32(BufferIn+0x18);
233
234 u32 data = Memory::Read_U32(BufferIn+0x1C);
235
236 ReturnValue = HIDERR_NO_DEVICE_FOUND-4;
237
238 libusb_device_handle * dev_handle = GetDeviceByDevNum(dev_num);
239
240 if (dev_handle == NULL__null)
241 {
242 DEBUG_LOG(WII_IPC_HID, "Could not find handle: %X", dev_num)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 242, "Could not find handle: %X", dev_num); } } while (0)
;
243 break;
244 }
245
246 struct libusb_transfer *transfer = libusb_alloc_transfer(0);
247 transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
248 libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, Memory::GetPointer(data), length,
249 handleUsbUpdates, (void*)(size_t)_CommandAddress, 0);
250 libusb_submit_transfer(transfer);
251
252 //DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Interrupt %s)(%d,%d,%X) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
253 // Parameter == IOCTL_HID_INTERRUPT_IN ? "In" : "Out", endpoint, length, data, BufferIn, BufferInSize, BufferOut, BufferOutSize);
254
255 // It's the async way!
256 return false;
257 break;
258 }
259 case IOCTL_HID_SHUTDOWN:
260 {
261 std::lock_guard<std::mutex> lk(s_device_list_reply);
262 if (deviceCommandAddress != 0){
263 Memory::Write_U32(0xFFFFFFFF, Memory::Read_U32(deviceCommandAddress + 0x18));
264
265 Memory::Write_U32(8, deviceCommandAddress);
266 // IOS seems to write back the command that was responded to
267 Memory::Write_U32(/*COMMAND_IOCTL*/ 6, deviceCommandAddress + 8);
268
269 // Return value
270 Memory::Write_U32(-1, deviceCommandAddress + 4);
271 WII_IPC_HLE_Interface::EnqueReplyCallback(deviceCommandAddress);
272 deviceCommandAddress = 0;
273 }
274 DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 275, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, BufferIn, BufferInSize, BufferOut, BufferOutSize); } } while
(0)
275 BufferIn, BufferInSize, BufferOut, BufferOutSize)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 275, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, BufferIn, BufferInSize, BufferOut, BufferOutSize); } } while
(0)
;
276 break;
277 }
278 default:
279 {
280 DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(0x%x) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 281, "HID::IOCtl(0x%x) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize
); } } while (0)
281 Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 281, "HID::IOCtl(0x%x) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
, Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize
); } } while (0)
;
282 break;
283 }
284 }
285
286 Memory::Write_U32(ReturnValue, _CommandAddress + 4);
287
288 return true;
289}
290
291
292bool CWII_IPC_HLE_Device_hid::ClaimDevice(libusb_device_handle * dev)
293{
294 int ret = 0;
295 if ((ret = libusb_kernel_driver_active(dev, 0)) == 1)
296 {
297 if ((ret = libusb_detach_kernel_driver(dev, 0)) && ret != LIBUSB_ERROR_NOT_SUPPORTED)
298 {
299 DEBUG_LOG(WII_IPC_HID, "libusb_detach_kernel_driver failed with error: %d", ret)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 299, "libusb_detach_kernel_driver failed with error: %d", ret
); } } while (0)
;
300 return false;
301 }
302 }
303 else if (ret != 0 && ret != LIBUSB_ERROR_NOT_SUPPORTED)
304 {
305 DEBUG_LOG(WII_IPC_HID, "libusb_kernel_driver_active error ret = %d", ret)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 305, "libusb_kernel_driver_active error ret = %d", ret); } }
while (0)
;
306 return false;
307 }
308
309 if ((ret = libusb_claim_interface(dev, 0)))
310 {
311 DEBUG_LOG(WII_IPC_HID, "libusb_claim_interface failed with error: %d", ret)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 311, "libusb_claim_interface failed with error: %d", ret); }
} while (0)
;
312 return false;
313 }
314
315 return true;
316}
317
318bool CWII_IPC_HLE_Device_hid::IOCtlV(u32 _CommandAddress)
319{
320
321 Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HID, LogTypes::LWARNING);
322 u32 ReturnValue = 0;
323 SIOCtlVBuffer CommandBuffer(_CommandAddress);
324
325 DEBUG_LOG(WII_IPC_HID, "%s - IOCtlV:", GetDeviceName().c_str())do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 325, "%s - IOCtlV:", GetDeviceName().c_str()); } } while (0
)
;
326 DEBUG_LOG(WII_IPC_HID, " Parameter: 0x%x", CommandBuffer.Parameter)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 326, " Parameter: 0x%x", CommandBuffer.Parameter); } } while
(0)
;
327 DEBUG_LOG(WII_IPC_HID, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 327, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer);
} } while (0)
;
328 DEBUG_LOG(WII_IPC_HID, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 328, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer
); } } while (0)
;
329 DEBUG_LOG(WII_IPC_HID, " BufferVector: 0x%08x", CommandBuffer.BufferVector)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 329, " BufferVector: 0x%08x", CommandBuffer.BufferVector
); } } while (0)
;
330 DEBUG_LOG(WII_IPC_HID, " PayloadAddr: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Address)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 330, " PayloadAddr: 0x%08x", CommandBuffer.PayloadBuffer
[0].m_Address); } } while (0)
;
331 DEBUG_LOG(WII_IPC_HID, " PayloadSize: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Size)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 331, " PayloadSize: 0x%08x", CommandBuffer.PayloadBuffer
[0].m_Size); } } while (0)
;
332 #if defined(_DEBUG) || defined(DEBUGFAST)
333 DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer);
334 #endif
335
336 Memory::Write_U32(ReturnValue, _CommandAddress + 4);
337 return true;
338}
339
340
341
342void CWII_IPC_HLE_Device_hid::ConvertDeviceToWii(WiiHIDDeviceDescriptor *dest, const struct libusb_device_descriptor *src)
343{
344 memcpy(dest,src,sizeof(WiiHIDDeviceDescriptor));
345 dest->bcdUSB = Common::swap16(dest->bcdUSB);
346 dest->idVendor = Common::swap16(dest->idVendor);
347 dest->idProduct = Common::swap16(dest->idProduct);
348 dest->bcdDevice = Common::swap16(dest->bcdDevice);
349}
350
351void CWII_IPC_HLE_Device_hid::ConvertConfigToWii(WiiHIDConfigDescriptor *dest, const struct libusb_config_descriptor *src)
352{
353 memcpy(dest,src,sizeof(WiiHIDConfigDescriptor));
354 dest->wTotalLength = Common::swap16(dest->wTotalLength);
355}
356
357void CWII_IPC_HLE_Device_hid::ConvertInterfaceToWii(WiiHIDInterfaceDescriptor *dest, const struct libusb_interface_descriptor *src)
358{
359 memcpy(dest,src,sizeof(WiiHIDInterfaceDescriptor));
360}
361
362void CWII_IPC_HLE_Device_hid::ConvertEndpointToWii(WiiHIDEndpointDescriptor *dest, const struct libusb_endpoint_descriptor *src)
363{
364 memcpy(dest,src,sizeof(WiiHIDEndpointDescriptor));
365 dest->wMaxPacketSize = Common::swap16(dest->wMaxPacketSize);
366}
367
368void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize)
369{
370 static u16 check = 1;
371 int OffsetBuffer = BufferOut;
372 int OffsetStart = 0;
373 //int OffsetDevice = 0;
374 int d,c,ic,i,e; /* config, interface container, interface, endpoint */
375
376 libusb_device **list;
377 //libusb_device *found = NULL;
378 ssize_t cnt = libusb_get_device_list(NULL__null, &list);
379 DEBUG_LOG(WII_IPC_HID, "Found %ld viable USB devices.", cnt)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 379, "Found %ld viable USB devices.", cnt); } } while (0)
;
380 for (d = 0; d < cnt; d++)
381 {
382 libusb_device *device = list[d];
383 struct libusb_device_descriptor desc;
384 int dRet = libusb_get_device_descriptor (device, &desc);
385 if (dRet)
386 {
387 // could not aquire the descriptor, no point in trying to use it.
388 DEBUG_LOG(WII_IPC_HID, "libusb_get_device_descriptor failed with error: %d", dRet)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 388, "libusb_get_device_descriptor failed with error: %d", dRet
); } } while (0)
;
389 continue;
390 }
391 OffsetStart = OffsetBuffer;
392 OffsetBuffer += 4; // skip length for now, fill at end
393
394 OffsetBuffer += 4; // skip devNum for now
395
396 WiiHIDDeviceDescriptor wii_device;
397 ConvertDeviceToWii(&wii_device, &desc);
398 Memory::WriteBigEData((const u8*)&wii_device, OffsetBuffer, Align(wii_device.bLength, 4));
399 OffsetBuffer += Align(wii_device.bLength, 4);
400 bool deviceValid = true;
401
402 for (c = 0; deviceValid && c < desc.bNumConfigurations; c++)
403 {
404 struct libusb_config_descriptor *config = NULL__null;
405 int cRet = libusb_get_config_descriptor(device, c, &config);
406
407 // do not try to use usb devices with more than one interface, games can crash
408 if(cRet == 0 && config->bNumInterfaces <= MAX_HID_INTERFACES1)
409 {
410 WiiHIDConfigDescriptor wii_config;
411 ConvertConfigToWii(&wii_config, config);
412 Memory::WriteBigEData((const u8*)&wii_config, OffsetBuffer, Align(wii_config.bLength, 4));
413 OffsetBuffer += Align(wii_config.bLength, 4);
414
415 for (ic = 0; ic < config->bNumInterfaces; ic++)
416 {
417 const struct libusb_interface *interfaceContainer = &config->interface[ic];
418 for (i = 0; i < interfaceContainer->num_altsetting; i++)
419 {
420 const struct libusb_interface_descriptor *interface = &interfaceContainer->altsetting[i];
421
422 WiiHIDInterfaceDescriptor wii_interface;
423 ConvertInterfaceToWii(&wii_interface, interface);
424 Memory::WriteBigEData((const u8*)&wii_interface, OffsetBuffer, Align(wii_interface.bLength, 4));
425 OffsetBuffer += Align(wii_interface.bLength, 4);
426
427 for (e = 0; e < interface->bNumEndpoints; e++)
428 {
429 const struct libusb_endpoint_descriptor *endpoint = &interface->endpoint[e];
430
431 WiiHIDEndpointDescriptor wii_endpoint;
432 ConvertEndpointToWii(&wii_endpoint, endpoint);
433 Memory::WriteBigEData((const u8*)&wii_endpoint, OffsetBuffer, Align(wii_endpoint.bLength, 4));
434 OffsetBuffer += Align(wii_endpoint.bLength, 4);
435
436 } //endpoints
437 } // interfaces
438 } // interface containters
439 libusb_free_config_descriptor(config);
440 config = NULL__null;
441 }
442 else
443 {
444 if(cRet)
445 DEBUG_LOG(WII_IPC_HID, "libusb_get_config_descriptor failed with: %d", cRet)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 445, "libusb_get_config_descriptor failed with: %d", cRet);
} } while (0)
;
446 deviceValid = false;
447 OffsetBuffer = OffsetStart;
448 }
449 } // configs
450
451 if (deviceValid)
452 {
453 Memory::Write_U32(OffsetBuffer-OffsetStart, OffsetStart); // fill in length
454
455 int devNum = GetAvaiableDevNum(desc.idVendor,
456 desc.idProduct,
457 libusb_get_bus_number (device),
458 libusb_get_device_address (device),
459 check);
460 if (devNum < 0 )
461 {
462 // too many devices to handle.
463 ERROR_LOG(WII_IPC_HID, "Exhausted device list, you have way too many usb devices plugged in."do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 464, "Exhausted device list, you have way too many usb devices plugged in."
"Or it might be our fault. Let us know at https://code.google.com/p/dolphin-emu/issues/entry?template=Defect%%20report"
); } } while (0)
464 "Or it might be our fault. Let us know at https://code.google.com/p/dolphin-emu/issues/entry?template=Defect%%20report")do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 464, "Exhausted device list, you have way too many usb devices plugged in."
"Or it might be our fault. Let us know at https://code.google.com/p/dolphin-emu/issues/entry?template=Defect%%20report"
); } } while (0)
;
465 OffsetBuffer = OffsetStart;
466 continue;
467 }
468
469 DEBUG_LOG(WII_IPC_HID, "Found device with Vendor: %X Product: %X Devnum: %d", desc.idVendor, desc.idProduct, devNum)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 469, "Found device with Vendor: %X Product: %X Devnum: %d",
desc.idVendor, desc.idProduct, devNum); } } while (0)
;
470
471 Memory::Write_U32(devNum , OffsetStart+4); //write device num
472 }
473 }
474
475 // Find devices that no longer exists and free them
476 for (i=0; i<MAX_DEVICE_DEVNUM256; i++)
477 {
478 u16 check_cur = (u16)(hidDeviceAliases[i] >> 48);
479 if(hidDeviceAliases[i] != 0 && check_cur != check)
480 {
481 DEBUG_LOG(WII_IPC_HID, "Removing: device %d %hX %hX", i, check, check_cur)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 481, "Removing: device %d %hX %hX", i, check, check_cur); }
} while (0)
;
482 std::lock_guard<std::mutex> lk(s_open_devices);
483 if (open_devices.find(i) != open_devices.end())
484 {
485 libusb_device_handle *handle = open_devices[i];
486 libusb_close(handle);
487 open_devices.erase(i);
488 }
489 hidDeviceAliases[i] = 0;
490 }
491 }
492 check++;
493
494
495 libusb_free_device_list(list, 1);
496
497 Memory::Write_U32(0xFFFFFFFF, OffsetBuffer); // no more devices
498
499}
500
501int CWII_IPC_HLE_Device_hid::Align(int num, int alignment)
502{
503 return (num + (alignment-1)) & ~(alignment-1);
504}
505
506
507libusb_device_handle * CWII_IPC_HLE_Device_hid::GetDeviceByDevNum(u32 devNum)
508{
509 u32 i;
510 libusb_device **list;
511 libusb_device_handle *handle = NULL__null;
512 ssize_t cnt;
513
514 if(devNum >= MAX_DEVICE_DEVNUM256)
515 return NULL__null;
516
517
518 std::lock_guard<std::mutex> lk(s_open_devices);
519
520 if (open_devices.find(devNum) != open_devices.end())
521 {
522 handle = open_devices[devNum];
523 if(libusb_kernel_driver_active(handle, 0) != LIBUSB_ERROR_NO_DEVICE)
524 {
525 return handle;
526 }
527 else
528 {
529 libusb_close(handle);
530 open_devices.erase(devNum);
531 }
532 }
533
534 cnt = libusb_get_device_list(NULL__null, &list);
535
536 if (cnt < 0)
537 return NULL__null;
538
539 for (i = 0; i < cnt; i++) {
540 libusb_device *device = list[i];
541 struct libusb_device_descriptor desc;
542 int dRet = libusb_get_device_descriptor (device, &desc);
543 u8 bus = libusb_get_bus_number (device);
544 u8 port = libusb_get_device_address (device);
545 u64 unique_id = ((u64)desc.idVendor << 32) | ((u64)desc.idProduct << 16) | ((u64)bus << 8) | (u64)port;
546 if ((hidDeviceAliases[devNum] & HID_ID_MASK0x0000FFFFFFFFFFFF) == unique_id)
547 {
548 int ret = libusb_open(device, &handle);
549 if (ret)
550 {
551 if (ret == LIBUSB_ERROR_ACCESS)
552 {
553 if( dRet )
554 {
555 ERROR_LOG(WII_IPC_HID, "Dolphin does not have access to this device: Bus %03d Device %03d: ID ????:???? (couldn't get id).",do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 558, "Dolphin does not have access to this device: Bus %03d Device %03d: ID ????:???? (couldn't get id)."
, bus, port); } } while (0)
556 bus,do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 558, "Dolphin does not have access to this device: Bus %03d Device %03d: ID ????:???? (couldn't get id)."
, bus, port); } } while (0)
557 portdo { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 558, "Dolphin does not have access to this device: Bus %03d Device %03d: ID ????:???? (couldn't get id)."
, bus, port); } } while (0)
558 )do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 558, "Dolphin does not have access to this device: Bus %03d Device %03d: ID ????:???? (couldn't get id)."
, bus, port); } } while (0)
;
559 }
560 else{
561 ERROR_LOG(WII_IPC_HID, "Dolphin does not have access to this device: Bus %03d Device %03d: ID %04X:%04X.",do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 566, "Dolphin does not have access to this device: Bus %03d Device %03d: ID %04X:%04X."
, bus, port, desc.idVendor, desc.idProduct); } } while (0)
562 bus,do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 566, "Dolphin does not have access to this device: Bus %03d Device %03d: ID %04X:%04X."
, bus, port, desc.idVendor, desc.idProduct); } } while (0)
563 port,do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 566, "Dolphin does not have access to this device: Bus %03d Device %03d: ID %04X:%04X."
, bus, port, desc.idVendor, desc.idProduct); } } while (0)
564 desc.idVendor,do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 566, "Dolphin does not have access to this device: Bus %03d Device %03d: ID %04X:%04X."
, bus, port, desc.idVendor, desc.idProduct); } } while (0)
565 desc.idProductdo { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 566, "Dolphin does not have access to this device: Bus %03d Device %03d: ID %04X:%04X."
, bus, port, desc.idVendor, desc.idProduct); } } while (0)
566 )do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 566, "Dolphin does not have access to this device: Bus %03d Device %03d: ID %04X:%04X."
, bus, port, desc.idVendor, desc.idProduct); } } while (0)
;
567 }
568 }
569#ifdef _WIN32
570 else if (ret == LIBUSB_ERROR_NOT_SUPPORTED)
571 {
572 WARN_LOG(WII_IPC_HID, "Please install the libusb drivers for the device %04X:%04X", desc.idVendor, desc.idProduct)do { { if (LogTypes::LWARNING <= 3) GenericLog(LogTypes::LWARNING
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 572, "Please install the libusb drivers for the device %04X:%04X"
, desc.idVendor, desc.idProduct); } } while (0)
;
573 }
574#endif
575 else
576 {
577 ERROR_LOG(WII_IPC_HID, "libusb_open failed to open device with error = %d", ret)do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 577, "libusb_open failed to open device with error = %d", ret
); } } while (0)
;
578 }
579 continue;
580 }
581
582
583 if (!ClaimDevice(handle))
584 {
585 ERROR_LOG(WII_IPC_HID, "Could not claim the device for handle: %X", devNum)do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::WII_IPC_HID, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp"
, 585, "Could not claim the device for handle: %X", devNum); }
} while (0)
;
586 libusb_close(handle);
587 continue;
588 }
589
590 open_devices[devNum] = handle;
591 break;
592 }
593 else
594 {
595 handle = NULL__null;
596 }
597 }
598
599 libusb_free_device_list(list, 1);
600
601
602 return handle;
603}
604
605
606int CWII_IPC_HLE_Device_hid::GetAvaiableDevNum(u16 idVendor, u16 idProduct, u8 bus, u8 port, u16 check)
607{
608 int i;
609 int pos = -1;
610 u64 unique_id = ((u64)idVendor << 32) | ((u64)idProduct << 16) | ((u64)bus << 8) | (u64)port;
611 for (i=0; i<MAX_DEVICE_DEVNUM256; i++)
612 {
613 u64 id = hidDeviceAliases[i] & HID_ID_MASK0x0000FFFFFFFFFFFF;
614 if(id == 0 && pos == -1)
615 {
616 pos = i;
617 }
618 else if (id == unique_id)
619 {
620 hidDeviceAliases[i] = id | ((u64)check << 48);
621 return i;
622 }
623 }
624 if(pos != -1)
625 {
626 hidDeviceAliases[pos] = unique_id | ((u64)check << 48);
627 return pos;
628 }
629 return -1;
630}