OLD | NEW |
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 "content/browser/gamepad/gamepad_platform_data_fetcher_mac.h" | 5 #include "content/browser/gamepad/gamepad_platform_data_fetcher_mac.h" |
6 | 6 |
7 #include "base/mac/foundation_util.h" | 7 #include "base/mac/foundation_util.h" |
8 #include "base/mac/scoped_nsobject.h" | 8 #include "base/mac/scoped_nsobject.h" |
9 #include "base/strings/string16.h" | 9 #include "base/strings/string16.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "base/time/time.h" | 12 #include "base/time/time.h" |
13 | 13 |
14 #import <Foundation/Foundation.h> | 14 #import <Foundation/Foundation.h> |
15 #include <IOKit/hid/IOHIDKeys.h> | 15 #include <IOKit/hid/IOHIDKeys.h> |
16 | 16 |
17 using blink::WebGamepad; | 17 using blink::WebGamepad; |
18 using blink::WebGamepads; | 18 using blink::WebGamepads; |
19 | 19 |
20 namespace content { | 20 namespace content { |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
| 24 void CopyNSStringAsUTF16LittleEndian( |
| 25 NSString* src, blink::WebUChar* dest, size_t dest_len) { |
| 26 NSData* as16 = [src dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; |
| 27 memset(dest, 0, dest_len); |
| 28 [as16 getBytes:dest length:dest_len - sizeof(blink::WebUChar)]; |
| 29 } |
| 30 |
24 NSDictionary* DeviceMatching(uint32_t usage_page, uint32_t usage) { | 31 NSDictionary* DeviceMatching(uint32_t usage_page, uint32_t usage) { |
25 return [NSDictionary dictionaryWithObjectsAndKeys: | 32 return [NSDictionary dictionaryWithObjectsAndKeys: |
26 [NSNumber numberWithUnsignedInt:usage_page], | 33 [NSNumber numberWithUnsignedInt:usage_page], |
27 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsagePageKey)), | 34 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsagePageKey)), |
28 [NSNumber numberWithUnsignedInt:usage], | 35 [NSNumber numberWithUnsignedInt:usage], |
29 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsageKey)), | 36 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsageKey)), |
30 nil]; | 37 nil]; |
31 } | 38 } |
32 | 39 |
33 float NormalizeAxis(CFIndex value, CFIndex min, CFIndex max) { | 40 float NormalizeAxis(CFIndex value, CFIndex min, CFIndex max) { |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 snprintf(product_as_str, sizeof(product_as_str), "%04x", product_int); | 261 snprintf(product_as_str, sizeof(product_as_str), "%04x", product_int); |
255 associated_[slot].hid.mapper = | 262 associated_[slot].hid.mapper = |
256 GetGamepadStandardMappingFunction(vendor_as_str, product_as_str); | 263 GetGamepadStandardMappingFunction(vendor_as_str, product_as_str); |
257 | 264 |
258 NSString* ident = [NSString stringWithFormat: | 265 NSString* ident = [NSString stringWithFormat: |
259 @"%@ (%sVendor: %04x Product: %04x)", | 266 @"%@ (%sVendor: %04x Product: %04x)", |
260 product, | 267 product, |
261 associated_[slot].hid.mapper ? "STANDARD GAMEPAD " : "", | 268 associated_[slot].hid.mapper ? "STANDARD GAMEPAD " : "", |
262 vendor_int, | 269 vendor_int, |
263 product_int]; | 270 product_int]; |
264 NSData* as16 = [ident dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; | 271 CopyNSStringAsUTF16LittleEndian( |
| 272 ident, |
| 273 data_.items[slot].id, |
| 274 sizeof(data_.items[slot].id)); |
265 | 275 |
266 const size_t kOutputLengthBytes = sizeof(data_.items[slot].id); | 276 if (associated_[slot].hid.mapper) { |
267 memset(&data_.items[slot].id, 0, kOutputLengthBytes); | 277 CopyNSStringAsUTF16LittleEndian( |
268 [as16 getBytes:data_.items[slot].id | 278 @"standard", |
269 length:kOutputLengthBytes - sizeof(blink::WebUChar)]; | 279 data_.items[slot].mapping, |
| 280 sizeof(data_.items[slot].mapping)); |
| 281 } else { |
| 282 data_.items[slot].mapping[0] = 0; |
| 283 } |
270 | 284 |
271 base::ScopedCFTypeRef<CFArrayRef> elements( | 285 base::ScopedCFTypeRef<CFArrayRef> elements( |
272 IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone)); | 286 IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone)); |
273 AddButtonsAndAxes(CFToNSCast(elements), slot); | 287 AddButtonsAndAxes(CFToNSCast(elements), slot); |
274 | 288 |
275 associated_[slot].hid.device_ref = device; | 289 associated_[slot].hid.device_ref = device; |
276 data_.items[slot].connected = true; | 290 data_.items[slot].connected = true; |
277 if (slot >= data_.length) | 291 if (slot >= data_.length) |
278 data_.length = slot + 1; | 292 data_.length = slot + 1; |
279 } | 293 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 } | 327 } |
314 if (slot == data_.length) | 328 if (slot == data_.length) |
315 return; | 329 return; |
316 | 330 |
317 WebGamepad& pad = data_.items[slot]; | 331 WebGamepad& pad = data_.items[slot]; |
318 AssociatedData& associated = associated_[slot]; | 332 AssociatedData& associated = associated_[slot]; |
319 | 333 |
320 // Find and fill in the associated button event, if any. | 334 // Find and fill in the associated button event, if any. |
321 for (size_t i = 0; i < pad.buttonsLength; ++i) { | 335 for (size_t i = 0; i < pad.buttonsLength; ++i) { |
322 if (associated.hid.button_elements[i] == element) { | 336 if (associated.hid.button_elements[i] == element) { |
323 pad.buttons[i] = IOHIDValueGetIntegerValue(value) ? 1.f : 0.f; | 337 pad.buttons[i].pressed = IOHIDValueGetIntegerValue(value); |
| 338 pad.buttons[i].value = pad.buttons[i].pressed ? 1.f : 0.f; |
324 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); | 339 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); |
325 return; | 340 return; |
326 } | 341 } |
327 } | 342 } |
328 | 343 |
329 // Find and fill in the associated axis event, if any. | 344 // Find and fill in the associated axis event, if any. |
330 for (size_t i = 0; i < pad.axesLength; ++i) { | 345 for (size_t i = 0; i < pad.axesLength; ++i) { |
331 if (associated.hid.axis_elements[i] == element) { | 346 if (associated.hid.axis_elements[i] == element) { |
332 pad.axes[i] = NormalizeAxis(IOHIDValueGetIntegerValue(value), | 347 pad.axes[i] = NormalizeAxis(IOHIDValueGetIntegerValue(value), |
333 associated.hid.axis_minimums[i], | 348 associated.hid.axis_minimums[i], |
(...skipping 17 matching lines...) Expand all Loading... |
351 device->SetLEDPattern( | 366 device->SetLEDPattern( |
352 (XboxController::LEDPattern)(XboxController::LED_FLASH_TOP_LEFT + slot)); | 367 (XboxController::LEDPattern)(XboxController::LED_FLASH_TOP_LEFT + slot)); |
353 | 368 |
354 NSString* ident = | 369 NSString* ident = |
355 [NSString stringWithFormat: | 370 [NSString stringWithFormat: |
356 @"%@ (STANDARD GAMEPAD Vendor: %04x Product: %04x)", | 371 @"%@ (STANDARD GAMEPAD Vendor: %04x Product: %04x)", |
357 device->GetControllerType() == XboxController::XBOX_360_CONTROLLER | 372 device->GetControllerType() == XboxController::XBOX_360_CONTROLLER |
358 ? @"Xbox 360 Controller" | 373 ? @"Xbox 360 Controller" |
359 : @"Xbox One Controller", | 374 : @"Xbox One Controller", |
360 device->GetProductId(), device->GetVendorId()]; | 375 device->GetProductId(), device->GetVendorId()]; |
361 NSData* as16 = [ident dataUsingEncoding:NSUTF16StringEncoding]; | 376 CopyNSStringAsUTF16LittleEndian( |
362 const size_t kOutputLengthBytes = sizeof(data_.items[slot].id); | 377 ident, |
363 memset(&data_.items[slot].id, 0, kOutputLengthBytes); | 378 data_.items[slot].id, |
364 [as16 getBytes:data_.items[slot].id | 379 sizeof(data_.items[slot].id)); |
365 length:kOutputLengthBytes - sizeof(blink::WebUChar)]; | 380 |
| 381 CopyNSStringAsUTF16LittleEndian( |
| 382 @"standard", |
| 383 data_.items[slot].mapping, |
| 384 sizeof(data_.items[slot].mapping)); |
366 | 385 |
367 associated_[slot].is_xbox = true; | 386 associated_[slot].is_xbox = true; |
368 associated_[slot].xbox.device = device; | 387 associated_[slot].xbox.device = device; |
369 associated_[slot].xbox.location_id = device->location_id(); | 388 associated_[slot].xbox.location_id = device->location_id(); |
370 data_.items[slot].connected = true; | 389 data_.items[slot].connected = true; |
371 data_.items[slot].axesLength = 4; | 390 data_.items[slot].axesLength = 4; |
372 data_.items[slot].buttonsLength = 17; | 391 data_.items[slot].buttonsLength = 17; |
373 data_.items[slot].timestamp = 0; | 392 data_.items[slot].timestamp = 0; |
374 if (slot >= data_.length) | 393 if (slot >= data_.length) |
375 data_.length = slot + 1; | 394 data_.length = slot + 1; |
(...skipping 26 matching lines...) Expand all Loading... |
402 associated_[slot].is_xbox && | 421 associated_[slot].is_xbox && |
403 associated_[slot].xbox.device == device) | 422 associated_[slot].xbox.device == device) |
404 break; | 423 break; |
405 } | 424 } |
406 if (slot == data_.length) | 425 if (slot == data_.length) |
407 return; | 426 return; |
408 | 427 |
409 WebGamepad& pad = data_.items[slot]; | 428 WebGamepad& pad = data_.items[slot]; |
410 | 429 |
411 for (size_t i = 0; i < 6; i++) { | 430 for (size_t i = 0; i < 6; i++) { |
412 pad.buttons[i] = data.buttons[i] ? 1.0f : 0.0f; | 431 pad.buttons[i].pressed = data.buttons[i]; |
| 432 pad.buttons[i].value = data.buttons[i] ? 1.0f : 0.0f; |
413 } | 433 } |
414 pad.buttons[6] = data.triggers[0]; | 434 pad.buttons[6].pressed = data.triggers[0] > kDefaultButtonPressedThreshold; |
415 pad.buttons[7] = data.triggers[1]; | 435 pad.buttons[6].value = data.triggers[0]; |
| 436 pad.buttons[7].pressed = data.triggers[1] > kDefaultButtonPressedThreshold; |
| 437 pad.buttons[7].value = data.triggers[1]; |
416 for (size_t i = 8; i < 17; i++) { | 438 for (size_t i = 8; i < 17; i++) { |
417 pad.buttons[i] = data.buttons[i - 2] ? 1.0f : 0.0f; | 439 pad.buttons[i].pressed = data.buttons[i - 2]; |
| 440 pad.buttons[i].value = data.buttons[i - 2] ? 1.0f : 0.0f; |
418 } | 441 } |
419 for (size_t i = 0; i < arraysize(data.axes); i++) { | 442 for (size_t i = 0; i < arraysize(data.axes); i++) { |
420 pad.axes[i] = data.axes[i]; | 443 pad.axes[i] = data.axes[i]; |
421 } | 444 } |
422 | 445 |
423 pad.timestamp = base::TimeTicks::Now().ToInternalValue(); | 446 pad.timestamp = base::TimeTicks::Now().ToInternalValue(); |
424 } | 447 } |
425 | 448 |
426 void GamepadPlatformDataFetcherMac::GetGamepadData(WebGamepads* pads, bool) { | 449 void GamepadPlatformDataFetcherMac::GetGamepadData(WebGamepads* pads, bool) { |
427 if (!enabled_ && !xbox_fetcher_) { | 450 if (!enabled_ && !xbox_fetcher_) { |
428 pads->length = 0; | 451 pads->length = 0; |
429 return; | 452 return; |
430 } | 453 } |
431 | 454 |
432 // Copy to the current state to the output buffer, using the mapping | 455 // Copy to the current state to the output buffer, using the mapping |
433 // function, if there is one available. | 456 // function, if there is one available. |
434 pads->length = WebGamepads::itemsLengthCap; | 457 pads->length = WebGamepads::itemsLengthCap; |
435 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { | 458 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { |
436 if (!associated_[i].is_xbox && associated_[i].hid.mapper) | 459 if (!associated_[i].is_xbox && associated_[i].hid.mapper) |
437 associated_[i].hid.mapper(data_.items[i], &pads->items[i]); | 460 associated_[i].hid.mapper(data_.items[i], &pads->items[i]); |
438 else | 461 else |
439 pads->items[i] = data_.items[i]; | 462 pads->items[i] = data_.items[i]; |
440 } | 463 } |
441 } | 464 } |
442 | 465 |
443 } // namespace content | 466 } // namespace content |
OLD | NEW |