Bug Summary

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