Bug Summary

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