File:
src/joystick/hidapi/SDL_hidapi_wii.c
Checker name:
clang-diagnostic-unused-parameter
Review status:
Unreviewed
/*
74
{
75
k_eWiiOutputReportIDs_Rumble = 0x10,
76
k_eWiiOutputReportIDs_LEDs = 0x11,
77
k_eWiiOutputReportIDs_DataReportingMode = 0x12,
78
k_eWiiOutputReportIDs_IRCameraEnable = 0x13,
79
k_eWiiOutputReportIDs_SpeakerEnable = 0x14,
80
k_eWiiOutputReportIDs_StatusRequest = 0x15,
81
k_eWiiOutputReportIDs_WriteMemory = 0x16,
82
k_eWiiOutputReportIDs_ReadMemory = 0x17,
83
k_eWiiOutputReportIDs_SpeakerData = 0x18,
84
k_eWiiOutputReportIDs_SpeakerMute = 0x19,
85
k_eWiiOutputReportIDs_IRCameraEnable2 = 0x1a,
86
} EWiiOutputReportIDs;
87
88
typedef enum
89
{
90
k_eWiiPlayerLEDs_P1 = 0x10,
91
k_eWiiPlayerLEDs_P2 = 0x20,
92
k_eWiiPlayerLEDs_P3 = 0x40,
93
k_eWiiPlayerLEDs_P4 = 0x80,
94
} EWiiPlayerLEDs;
95
96
typedef enum
97
{
98
k_eWiiCommunicationState_None, /* No special communications happening */
99
k_eWiiCommunicationState_CheckMotionPlusStage1, /* Sent standard extension identify request */
100
k_eWiiCommunicationState_CheckMotionPlusStage2, /* Sent Motion Plus extension identify request */
101
} EWiiCommunicationState;
102
103
typedef enum
104
{
105
k_eWiiButtons_A = SDL_GAMEPAD_BUTTON_MISC1,
106
k_eWiiButtons_B,
107
k_eWiiButtons_One,
108
k_eWiiButtons_Two,
109
k_eWiiButtons_Plus,
110
k_eWiiButtons_Minus,
111
k_eWiiButtons_Home,
112
k_eWiiButtons_DPad_Up,
113
k_eWiiButtons_DPad_Down,
114
k_eWiiButtons_DPad_Left,
115
k_eWiiButtons_DPad_Right,
116
k_eWiiButtons_Max
117
} EWiiButtons;
118
119
120
121
typedef struct
122
{
123
Uint8 rgucBaseButtons[2];
124
Uint8 rgucAccelerometer[3];
125
Uint8 rgucExtension[21];
126
SDL_bool hasBaseButtons;
127
SDL_bool hasAccelerometer;
128
Uint8 ucNExtensionBytes;
129
} WiiButtonData;
130
131
typedef struct
132
{
133
Uint16 min;
134
Uint16 max;
135
Uint16 center;
136
Uint16 deadzone;
137
} StickCalibrationData;
138
139
typedef struct
140
{
141
SDL_HIDAPI_Device *device;
142
SDL_Joystick *joystick;
143
Uint64 timestamp;
144
EWiiCommunicationState m_eCommState;
145
EWiiExtensionControllerType m_eExtensionControllerType;
146
SDL_bool m_bPlayerLights;
147
int m_nPlayerIndex;
148
SDL_bool m_bRumbleActive;
149
SDL_bool m_bMotionPlusPresent;
150
Uint8 m_ucMotionPlusMode;
151
SDL_bool m_bReportSensors;
152
Uint8 m_rgucReadBuffer[k_unWiiPacketDataLength];
153
Uint64 m_ulLastInput;
154
Uint64 m_ulLastStatus;
155
Uint64 m_ulNextMotionPlusCheck;
156
SDL_bool m_bDisconnected;
157
158
StickCalibrationData m_StickCalibrationData[6];
159
} SDL_DriverWii_Context;
160
161
static void HIDAPI_DriverWii_RegisterHints(SDL_HintCallback callback, void *userdata)
162
{
163
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_WII, callback, userdata);
164
}
165
166
static void HIDAPI_DriverWii_UnregisterHints(SDL_HintCallback callback, void *userdata)
167
{
168
SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_WII, callback, userdata);
169
}
170
171
static SDL_bool HIDAPI_DriverWii_IsEnabled(void)
172
{
173
/* This doesn't work with the dolphinbar, so don't enable by default right now */
174
return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_WII, SDL_FALSE);
175
176
return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_WII,
177
SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
178
SDL_HIDAPI_DEFAULT));
179
180
}
181
182
static SDL_bool HIDAPI_DriverWii_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
183
{
184
if (vendor_id == USB_VENDOR_NINTENDO &&
185
(product_id == USB_PRODUCT_NINTENDO_WII_REMOTE ||
186
product_id == USB_PRODUCT_NINTENDO_WII_REMOTE2)) {
187
return SDL_TRUE;
188
}
189
return SDL_FALSE;
190
}
191
192
static int ReadInput(SDL_DriverWii_Context *ctx)
193
{
194
int size;
195
196
/* Make sure we don't try to read at the same time a write is happening */
197
if (SDL_AtomicGet(&ctx->device->rumble_pending) > 0) {
198
return 0;
199
}
200
201
size = SDL_hid_read_timeout(ctx->device->dev, ctx->m_rgucReadBuffer, sizeof(ctx->m_rgucReadBuffer), 0);
202
203
if (size > 0) {
204
HIDAPI_DumpPacket("Wii packet: size = %d", ctx->m_rgucReadBuffer, size);
205
}
206
207
return size;
208
}
209
210
static SDL_bool WriteOutput(SDL_DriverWii_Context *ctx, const Uint8 *data, int size, SDL_bool sync)
211
{
212
213
if (size > 0) {
214
HIDAPI_DumpPacket("Wii write packet: size = %d", data, size);
215
}
216
217
if (sync) {
218
return SDL_hid_write(ctx->device->dev, data, size) >= 0;
219
} else {
220
/* Use the rumble thread for general asynchronous writes */
221
if (SDL_HIDAPI_LockRumble() != 0) {
222
return SDL_FALSE;
223
}
224
return SDL_HIDAPI_SendRumbleAndUnlock(ctx->device, data, size) >= 0;
225
}
226
}
227
228
static SDL_bool ReadInputSync(SDL_DriverWii_Context *ctx, EWiiInputReportIDs expectedID, SDL_bool (*isMine)(const Uint8 *))
229
{
230
Uint64 endTicks = SDL_GetTicks() + 250; /* Seeing successful reads after about 200 ms */
231
232
int nRead = 0;
233
while ((nRead = ReadInput(ctx)) != -1) {
234
if (nRead > 0) {
235
if (ctx->m_rgucReadBuffer[0] == expectedID && (!isMine || isMine(ctx->m_rgucReadBuffer))) {
236
return SDL_TRUE;
237
}
238
} else {
239
if (SDL_GetTicks() >= endTicks) {
240
break;
241
}
242
SDL_Delay(1);
243
}
244
}
245
SDL_SetError("Read timed out");
246
return SDL_FALSE;
247
}
248
249
static SDL_bool IsWriteMemoryResponse(const Uint8 *data)
250
{
251
return data[3] == k_eWiiOutputReportIDs_WriteMemory;
252
}
253
254
static SDL_bool WriteRegister(SDL_DriverWii_Context *ctx, Uint32 address, const Uint8 *data, int size, SDL_bool sync)
255
{
256
Uint8 writeRequest[k_unWiiPacketDataLength];
257
258
SDL_zeroa(writeRequest);
259
writeRequest[0] = k_eWiiOutputReportIDs_WriteMemory;
260
writeRequest[1] = (Uint8)(0x04 | ctx->m_bRumbleActive);
261
writeRequest[2] = (address >> 16) & 0xff;
262
writeRequest[3] = (address >> 8) & 0xff;
263
writeRequest[4] = address & 0xff;
264
writeRequest[5] = (Uint8)size;
265
SDL_assert(size > 0 && size <= 16);
266
SDL_memcpy(writeRequest + 6, data, size);
267
268
if (!WriteOutput(ctx, writeRequest, sizeof(writeRequest), sync)) {
269
return SDL_FALSE;
270
}
271
if (sync) {
272
/* Wait for response */
273
if (!ReadInputSync(ctx, k_eWiiInputReportIDs_Acknowledge, IsWriteMemoryResponse)) {
274
return SDL_FALSE;
275
}
276
if (ctx->m_rgucReadBuffer[4]) {
277
SDL_SetError("Write memory failed: %u", ctx->m_rgucReadBuffer[4]);
278
return SDL_FALSE;
279
}
280
}
281
return SDL_TRUE;
282
}
283
284
static SDL_bool ReadRegister(SDL_DriverWii_Context *ctx, Uint32 address, int size, SDL_bool sync)
285
{
286
Uint8 readRequest[7];
287
288
readRequest[0] = k_eWiiOutputReportIDs_ReadMemory;
289
readRequest[1] = (Uint8)(0x04 | ctx->m_bRumbleActive);
290
readRequest[2] = (address >> 16) & 0xff;
291
readRequest[3] = (address >> 8) & 0xff;
292
readRequest[4] = address & 0xff;