Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: device/gamepad/gamepad_platform_data_fetcher_mac.mm

Issue 2808093006: [Device Service] Move Gamepad Blink headers to be part of the Gamepad client library (Closed)
Patch Set: clean up code Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "device/gamepad/gamepad_platform_data_fetcher_mac.h" 5 #include "device/gamepad/gamepad_platform_data_fetcher_mac.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <string.h> 8 #include <string.h>
9 9
10 #include "base/mac/foundation_util.h" 10 #include "base/mac/foundation_util.h"
11 #include "base/mac/scoped_nsobject.h" 11 #include "base/mac/scoped_nsobject.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/strings/string16.h" 13 #include "base/strings/string16.h"
14 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "base/time/time.h" 16 #include "base/time/time.h"
17 17
18 #import <Foundation/Foundation.h> 18 #import <Foundation/Foundation.h>
19 #include <IOKit/hid/IOHIDKeys.h> 19 #include <IOKit/hid/IOHIDKeys.h>
20 20
21 using blink::WebGamepad;
22 using blink::WebGamepads;
23
24 namespace device { 21 namespace device {
25 22
26 namespace { 23 namespace {
27 24
28 void CopyNSStringAsUTF16LittleEndian(NSString* src, 25 void CopyNSStringAsUTF16LittleEndian(NSString* src,
29 blink::WebUChar* dest, 26 UChar* dest,
dcheng 2017/04/12 23:33:27 Nit: do we need to include a header for this type?
juncai 2017/04/13 23:55:52 It is from: //device/gamepad/public/cpp/gamepad.h
30 size_t dest_len) { 27 size_t dest_len) {
31 NSData* as16 = [src dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; 28 NSData* as16 = [src dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
32 memset(dest, 0, dest_len); 29 memset(dest, 0, dest_len);
33 [as16 getBytes:dest length:dest_len - sizeof(blink::WebUChar)]; 30 [as16 getBytes:dest length:dest_len - sizeof(UChar)];
34 } 31 }
35 32
36 NSDictionary* DeviceMatching(uint32_t usage_page, uint32_t usage) { 33 NSDictionary* DeviceMatching(uint32_t usage_page, uint32_t usage) {
37 return [NSDictionary 34 return [NSDictionary
38 dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:usage_page], 35 dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:usage_page],
39 base::mac::CFToNSCast( 36 base::mac::CFToNSCast(
40 CFSTR(kIOHIDDeviceUsagePageKey)), 37 CFSTR(kIOHIDDeviceUsagePageKey)),
41 [NSNumber numberWithUnsignedInt:usage], 38 [NSNumber numberWithUnsignedInt:usage],
42 base::mac::CFToNSCast( 39 base::mac::CFToNSCast(
43 CFSTR(kIOHIDDeviceUsageKey)), 40 CFSTR(kIOHIDDeviceUsageKey)),
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 return true; 169 return true;
173 } 170 }
174 } 171 }
175 } 172 }
176 return false; 173 return false;
177 } 174 }
178 175
179 bool GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements, 176 bool GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements,
180 PadState* state, 177 PadState* state,
181 size_t slot) { 178 size_t slot) {
182 WebGamepad& pad = state->data; 179 Gamepad& pad = state->data;
183 AssociatedData& associated = associated_[slot]; 180 AssociatedData& associated = associated_[slot];
184 181
185 pad.axes_length = 0; 182 pad.axes_length = 0;
186 pad.buttons_length = 0; 183 pad.buttons_length = 0;
187 pad.timestamp = 0; 184 pad.timestamp = 0;
188 memset(pad.axes, 0, sizeof(pad.axes)); 185 memset(pad.axes, 0, sizeof(pad.axes));
189 memset(pad.buttons, 0, sizeof(pad.buttons)); 186 memset(pad.buttons, 0, sizeof(pad.buttons));
190 187
191 bool mapped_all_axes = true; 188 bool mapped_all_axes = true;
192 189
193 for (id elem in elements) { 190 for (id elem in elements) {
194 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem); 191 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
195 if (!CheckCollection(element)) 192 if (!CheckCollection(element))
196 continue; 193 continue;
197 194
198 uint32_t usage_page = IOHIDElementGetUsagePage(element); 195 uint32_t usage_page = IOHIDElementGetUsagePage(element);
199 uint32_t usage = IOHIDElementGetUsage(element); 196 uint32_t usage = IOHIDElementGetUsage(element);
200 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button && 197 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button &&
201 usage_page == kButtonUsagePage) { 198 usage_page == kButtonUsagePage) {
202 uint32_t button_index = usage - 1; 199 uint32_t button_index = usage - 1;
203 if (button_index < WebGamepad::kButtonsLengthCap) { 200 if (button_index < Gamepad::kButtonsLengthCap) {
204 associated.button_elements[button_index] = element; 201 associated.button_elements[button_index] = element;
205 pad.buttons_length = std::max(pad.buttons_length, button_index + 1); 202 pad.buttons_length = std::max(pad.buttons_length, button_index + 1);
206 } 203 }
207 } else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) { 204 } else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) {
208 uint32_t axis_index = usage - kAxisMinimumUsageNumber; 205 uint32_t axis_index = usage - kAxisMinimumUsageNumber;
209 if (axis_index < WebGamepad::kAxesLengthCap) { 206 if (axis_index < Gamepad::kAxesLengthCap) {
210 associated.axis_elements[axis_index] = element; 207 associated.axis_elements[axis_index] = element;
211 pad.axes_length = std::max(pad.axes_length, axis_index + 1); 208 pad.axes_length = std::max(pad.axes_length, axis_index + 1);
212 } else { 209 } else {
213 mapped_all_axes = false; 210 mapped_all_axes = false;
214 } 211 }
215 } 212 }
216 } 213 }
217 214
218 if (!mapped_all_axes) { 215 if (!mapped_all_axes) {
219 // For axes who's usage puts them outside the standard axesLengthCap range. 216 // For axes who's usage puts them outside the standard axesLengthCap range.
220 uint32_t next_index = 0; 217 uint32_t next_index = 0;
221 for (id elem in elements) { 218 for (id elem in elements) {
222 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem); 219 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
223 if (!CheckCollection(element)) 220 if (!CheckCollection(element))
224 continue; 221 continue;
225 222
226 uint32_t usage_page = IOHIDElementGetUsagePage(element); 223 uint32_t usage_page = IOHIDElementGetUsagePage(element);
227 uint32_t usage = IOHIDElementGetUsage(element); 224 uint32_t usage = IOHIDElementGetUsage(element);
228 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc && 225 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc &&
229 usage - kAxisMinimumUsageNumber >= WebGamepad::kAxesLengthCap && 226 usage - kAxisMinimumUsageNumber >= Gamepad::kAxesLengthCap &&
230 usage_page <= kGameControlsUsagePage) { 227 usage_page <= kGameControlsUsagePage) {
231 for (; next_index < WebGamepad::kAxesLengthCap; ++next_index) { 228 for (; next_index < Gamepad::kAxesLengthCap; ++next_index) {
232 if (associated.axis_elements[next_index] == NULL) 229 if (associated.axis_elements[next_index] == NULL)
233 break; 230 break;
234 } 231 }
235 if (next_index < WebGamepad::kAxesLengthCap) { 232 if (next_index < Gamepad::kAxesLengthCap) {
236 associated.axis_elements[next_index] = element; 233 associated.axis_elements[next_index] = element;
237 pad.axes_length = std::max(pad.axes_length, next_index + 1); 234 pad.axes_length = std::max(pad.axes_length, next_index + 1);
238 } 235 }
239 } 236 }
240 237
241 if (next_index >= WebGamepad::kAxesLengthCap) 238 if (next_index >= Gamepad::kAxesLengthCap)
242 break; 239 break;
243 } 240 }
244 } 241 }
245 242
246 for (uint32_t axis_index = 0; axis_index < pad.axes_length; ++axis_index) { 243 for (uint32_t axis_index = 0; axis_index < pad.axes_length; ++axis_index) {
247 IOHIDElementRef element = associated.axis_elements[axis_index]; 244 IOHIDElementRef element = associated.axis_elements[axis_index];
248 if (element != NULL) { 245 if (element != NULL) {
249 CFIndex axis_min = IOHIDElementGetLogicalMin(element); 246 CFIndex axis_min = IOHIDElementGetLogicalMin(element);
250 CFIndex axis_max = IOHIDElementGetLogicalMax(element); 247 CFIndex axis_max = IOHIDElementGetLogicalMax(element);
251 248
252 // Some HID axes report a logical range of -1 to 0 signed, which must be 249 // Some HID axes report a logical range of -1 to 0 signed, which must be
253 // interpreted as 0 to -1 unsigned for correct normalization behavior. 250 // interpreted as 0 to -1 unsigned for correct normalization behavior.
254 if (axis_min == -1 && axis_max == 0) { 251 if (axis_min == -1 && axis_max == 0) {
255 axis_max = -1; 252 axis_max = -1;
256 axis_min = 0; 253 axis_min = 0;
257 } 254 }
258 255
259 associated.axis_minimums[axis_index] = axis_min; 256 associated.axis_minimums[axis_index] = axis_min;
260 associated.axis_maximums[axis_index] = axis_max; 257 associated.axis_maximums[axis_index] = axis_max;
261 associated.axis_report_sizes[axis_index] = 258 associated.axis_report_sizes[axis_index] =
262 IOHIDElementGetReportSize(element); 259 IOHIDElementGetReportSize(element);
263 } 260 }
264 } 261 }
265 262
266 return (pad.axes_length > 0 || pad.buttons_length > 0); 263 return (pad.axes_length > 0 || pad.buttons_length > 0);
267 } 264 }
268 265
269 size_t GamepadPlatformDataFetcherMac::GetEmptySlot() { 266 size_t GamepadPlatformDataFetcherMac::GetEmptySlot() {
270 // Find a free slot for this device. 267 // Find a free slot for this device.
271 for (size_t slot = 0; slot < WebGamepads::kItemsLengthCap; ++slot) { 268 for (size_t slot = 0; slot < Gamepads::kItemsLengthCap; ++slot) {
272 if (associated_[slot].device_ref == nullptr) 269 if (associated_[slot].device_ref == nullptr)
273 return slot; 270 return slot;
274 } 271 }
275 return WebGamepads::kItemsLengthCap; 272 return Gamepads::kItemsLengthCap;
276 } 273 }
277 274
278 size_t GamepadPlatformDataFetcherMac::GetSlotForDevice(IOHIDDeviceRef device) { 275 size_t GamepadPlatformDataFetcherMac::GetSlotForDevice(IOHIDDeviceRef device) {
279 for (size_t slot = 0; slot < WebGamepads::kItemsLengthCap; ++slot) { 276 for (size_t slot = 0; slot < Gamepads::kItemsLengthCap; ++slot) {
280 // If we already have this device, and it's already connected, don't do 277 // If we already have this device, and it's already connected, don't do
281 // anything now. 278 // anything now.
282 if (associated_[slot].device_ref == device) 279 if (associated_[slot].device_ref == device)
283 return WebGamepads::kItemsLengthCap; 280 return Gamepads::kItemsLengthCap;
284 } 281 }
285 return GetEmptySlot(); 282 return GetEmptySlot();
286 } 283 }
287 284
288 void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) { 285 void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) {
289 using base::mac::CFToNSCast; 286 using base::mac::CFToNSCast;
290 using base::mac::CFCastStrict; 287 using base::mac::CFCastStrict;
291 288
292 if (!enabled_) 289 if (!enabled_)
293 return; 290 return;
294 291
295 NSNumber* location_id = CFToNSCast(CFCastStrict<CFNumberRef>( 292 NSNumber* location_id = CFToNSCast(CFCastStrict<CFNumberRef>(
296 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDLocationIDKey)))); 293 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDLocationIDKey))));
297 int location_int = [location_id intValue]; 294 int location_int = [location_id intValue];
298 295
299 // Find an index for this device. 296 // Find an index for this device.
300 size_t slot = GetSlotForDevice(device); 297 size_t slot = GetSlotForDevice(device);
301 298
302 // We can't handle this many connected devices. 299 // We can't handle this many connected devices.
303 if (slot == WebGamepads::kItemsLengthCap) 300 if (slot == Gamepads::kItemsLengthCap)
304 return; 301 return;
305 302
306 // Clear some state that may have been left behind by previous gamepads 303 // Clear some state that may have been left behind by previous gamepads
307 memset(&associated_[slot], 0, sizeof(AssociatedData)); 304 memset(&associated_[slot], 0, sizeof(AssociatedData));
308 305
309 PadState* state = GetPadState(location_int); 306 PadState* state = GetPadState(location_int);
310 if (!state) 307 if (!state)
311 return; // No available slot for this device 308 return; // No available slot for this device
312 309
313 NSNumber* vendor_id = CFToNSCast(CFCastStrict<CFNumberRef>( 310 NSNumber* vendor_id = CFToNSCast(CFCastStrict<CFNumberRef>(
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 associated_[slot].device_ref = device; 346 associated_[slot].device_ref = device;
350 state->data.connected = true; 347 state->data.connected = true;
351 } 348 }
352 349
353 void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) { 350 void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) {
354 if (!enabled_) 351 if (!enabled_)
355 return; 352 return;
356 353
357 // Find the index for this device. 354 // Find the index for this device.
358 size_t slot; 355 size_t slot;
359 for (slot = 0; slot < WebGamepads::kItemsLengthCap; ++slot) { 356 for (slot = 0; slot < Gamepads::kItemsLengthCap; ++slot) {
360 if (associated_[slot].device_ref == device) 357 if (associated_[slot].device_ref == device)
361 break; 358 break;
362 } 359 }
363 DCHECK(slot < WebGamepads::kItemsLengthCap); 360 DCHECK(slot < Gamepads::kItemsLengthCap);
364 // Leave associated device_ref so that it will be reconnected in the same 361 // Leave associated device_ref so that it will be reconnected in the same
365 // location. Simply mark it as disconnected. 362 // location. Simply mark it as disconnected.
366 associated_[slot].location_id = 0; 363 associated_[slot].location_id = 0;
367 associated_[slot].device_ref = nullptr; 364 associated_[slot].device_ref = nullptr;
368 } 365 }
369 366
370 void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) { 367 void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) {
371 if (!enabled_ || paused_) 368 if (!enabled_ || paused_)
372 return; 369 return;
373 370
374 IOHIDElementRef element = IOHIDValueGetElement(value); 371 IOHIDElementRef element = IOHIDValueGetElement(value);
375 IOHIDDeviceRef device = IOHIDElementGetDevice(element); 372 IOHIDDeviceRef device = IOHIDElementGetDevice(element);
376 373
377 // Find device slot. 374 // Find device slot.
378 size_t slot; 375 size_t slot;
379 for (slot = 0; slot < WebGamepads::kItemsLengthCap; ++slot) { 376 for (slot = 0; slot < Gamepads::kItemsLengthCap; ++slot) {
380 if (associated_[slot].device_ref == device) 377 if (associated_[slot].device_ref == device)
381 break; 378 break;
382 } 379 }
383 if (slot == WebGamepads::kItemsLengthCap) 380 if (slot == Gamepads::kItemsLengthCap)
384 return; 381 return;
385 382
386 PadState* state = GetPadState(associated_[slot].location_id); 383 PadState* state = GetPadState(associated_[slot].location_id);
387 if (!state) 384 if (!state)
388 return; 385 return;
389 386
390 WebGamepad& pad = state->data; 387 Gamepad& pad = state->data;
391 AssociatedData& associated = associated_[slot]; 388 AssociatedData& associated = associated_[slot];
392 389
393 uint32_t value_length = IOHIDValueGetLength(value); 390 uint32_t value_length = IOHIDValueGetLength(value);
394 if (value_length > 4) { 391 if (value_length > 4) {
395 // Workaround for bizarre issue with PS3 controllers that try to return 392 // Workaround for bizarre issue with PS3 controllers that try to return
396 // massive (30+ byte) values and crash IOHIDValueGetIntegerValue 393 // massive (30+ byte) values and crash IOHIDValueGetIntegerValue
397 return; 394 return;
398 } 395 }
399 396
400 // Find and fill in the associated button event, if any. 397 // Find and fill in the associated button event, if any.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 return; 432 return;
436 } 433 }
437 } 434 }
438 } 435 }
439 436
440 void GamepadPlatformDataFetcherMac::GetGamepadData(bool) { 437 void GamepadPlatformDataFetcherMac::GetGamepadData(bool) {
441 if (!enabled_) 438 if (!enabled_)
442 return; 439 return;
443 440
444 // Loop through and GetPadState to indicate the devices are still connected. 441 // Loop through and GetPadState to indicate the devices are still connected.
445 for (size_t slot = 0; slot < WebGamepads::kItemsLengthCap; ++slot) { 442 for (size_t slot = 0; slot < Gamepads::kItemsLengthCap; ++slot) {
446 if (associated_[slot].device_ref != nullptr) { 443 if (associated_[slot].device_ref != nullptr) {
447 GetPadState(associated_[slot].location_id); 444 GetPadState(associated_[slot].location_id);
448 } 445 }
449 } 446 }
450 } 447 }
451 448
452 } // namespace device 449 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698