| 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/memory/scoped_nsobject.h" | 8 #include "base/memory/scoped_nsobject.h" |
| 9 #include "base/string16.h" | 9 #include "base/string16.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 11 #include "base/time.h" |
| 11 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
| 12 | 13 |
| 13 #include <IOKit/hid/IOHIDKeys.h> | 14 #include <IOKit/hid/IOHIDKeys.h> |
| 14 #import <Foundation/Foundation.h> | 15 #import <Foundation/Foundation.h> |
| 15 | 16 |
| 17 using WebKit::WebGamepad; |
| 18 using WebKit::WebGamepads; |
| 19 |
| 16 namespace content { | 20 namespace content { |
| 17 | 21 |
| 18 namespace { | 22 namespace { |
| 19 | 23 |
| 20 NSDictionary* DeviceMatching(uint32_t usage_page, uint32_t usage) { | 24 NSDictionary* DeviceMatching(uint32_t usage_page, uint32_t usage) { |
| 21 return [NSDictionary dictionaryWithObjectsAndKeys: | 25 return [NSDictionary dictionaryWithObjectsAndKeys: |
| 22 [NSNumber numberWithUnsignedInt:usage_page], | 26 [NSNumber numberWithUnsignedInt:usage_page], |
| 23 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsagePageKey)), | 27 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsagePageKey)), |
| 24 [NSNumber numberWithUnsignedInt:usage], | 28 [NSNumber numberWithUnsignedInt:usage], |
| 25 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsageKey)), | 29 base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsageKey)), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 37 const uint32_t kGameUsageNumber = 0x05; | 41 const uint32_t kGameUsageNumber = 0x05; |
| 38 const uint32_t kMultiAxisUsageNumber = 0x08; | 42 const uint32_t kMultiAxisUsageNumber = 0x08; |
| 39 const uint32_t kAxisMinimumUsageNumber = 0x30; | 43 const uint32_t kAxisMinimumUsageNumber = 0x30; |
| 40 const uint32_t kAxisMaximumUsageNumber = 0x35; | 44 const uint32_t kAxisMaximumUsageNumber = 0x35; |
| 41 | 45 |
| 42 } // namespace | 46 } // namespace |
| 43 | 47 |
| 44 GamepadPlatformDataFetcherMac::GamepadPlatformDataFetcherMac() | 48 GamepadPlatformDataFetcherMac::GamepadPlatformDataFetcherMac() |
| 45 : enabled_(true) { | 49 : enabled_(true) { |
| 46 memset(associated_, 0, sizeof(associated_)); | 50 memset(associated_, 0, sizeof(associated_)); |
| 51 |
| 52 xbox_fetcher_.reset(new XboxDataFetcher(this)); |
| 53 if (!xbox_fetcher_->RegisterForNotifications()) |
| 54 xbox_fetcher_.reset(); |
| 55 |
| 47 hid_manager_ref_.reset(IOHIDManagerCreate(kCFAllocatorDefault, | 56 hid_manager_ref_.reset(IOHIDManagerCreate(kCFAllocatorDefault, |
| 48 kIOHIDOptionsTypeNone)); | 57 kIOHIDOptionsTypeNone)); |
| 49 if (CFGetTypeID(hid_manager_ref_) != IOHIDManagerGetTypeID()) { | 58 if (CFGetTypeID(hid_manager_ref_) != IOHIDManagerGetTypeID()) { |
| 50 enabled_ = false; | 59 enabled_ = false; |
| 51 return; | 60 return; |
| 52 } | 61 } |
| 53 | 62 |
| 54 scoped_nsobject<NSArray> criteria([[NSArray alloc] initWithObjects: | 63 scoped_nsobject<NSArray> criteria([[NSArray alloc] initWithObjects: |
| 55 DeviceMatching(kGenericDesktopUsagePage, kJoystickUsageNumber), | 64 DeviceMatching(kGenericDesktopUsagePage, kJoystickUsageNumber), |
| 56 DeviceMatching(kGenericDesktopUsagePage, kGameUsageNumber), | 65 DeviceMatching(kGenericDesktopUsagePage, kGameUsageNumber), |
| (...skipping 23 matching lines...) Expand all Loading... |
| 80 ValueChangedCallback, | 89 ValueChangedCallback, |
| 81 this); | 90 this); |
| 82 | 91 |
| 83 IOHIDManagerScheduleWithRunLoop( | 92 IOHIDManagerScheduleWithRunLoop( |
| 84 hid_manager_ref_, | 93 hid_manager_ref_, |
| 85 CFRunLoopGetMain(), | 94 CFRunLoopGetMain(), |
| 86 kCFRunLoopDefaultMode); | 95 kCFRunLoopDefaultMode); |
| 87 | 96 |
| 88 enabled_ = IOHIDManagerOpen(hid_manager_ref_, | 97 enabled_ = IOHIDManagerOpen(hid_manager_ref_, |
| 89 kIOHIDOptionsTypeNone) == kIOReturnSuccess; | 98 kIOHIDOptionsTypeNone) == kIOReturnSuccess; |
| 99 |
| 100 if (xbox_fetcher_) |
| 101 xbox_fetcher_->RegisterForNotifications(); |
| 90 } | 102 } |
| 91 | 103 |
| 92 void GamepadPlatformDataFetcherMac::UnregisterFromNotifications() { | 104 void GamepadPlatformDataFetcherMac::UnregisterFromNotifications() { |
| 93 IOHIDManagerUnscheduleFromRunLoop( | 105 IOHIDManagerUnscheduleFromRunLoop( |
| 94 hid_manager_ref_, | 106 hid_manager_ref_, |
| 95 CFRunLoopGetCurrent(), | 107 CFRunLoopGetCurrent(), |
| 96 kCFRunLoopDefaultMode); | 108 kCFRunLoopDefaultMode); |
| 97 IOHIDManagerClose(hid_manager_ref_, kIOHIDOptionsTypeNone); | 109 IOHIDManagerClose(hid_manager_ref_, kIOHIDOptionsTypeNone); |
| 110 if (xbox_fetcher_) |
| 111 xbox_fetcher_->UnregisterFromNotifications(); |
| 98 } | 112 } |
| 99 | 113 |
| 100 void GamepadPlatformDataFetcherMac::PauseHint(bool pause) { | 114 void GamepadPlatformDataFetcherMac::PauseHint(bool pause) { |
| 101 if (pause) | 115 if (pause) |
| 102 UnregisterFromNotifications(); | 116 UnregisterFromNotifications(); |
| 103 else | 117 else |
| 104 RegisterForNotifications(); | 118 RegisterForNotifications(); |
| 105 } | 119 } |
| 106 | 120 |
| 107 GamepadPlatformDataFetcherMac::~GamepadPlatformDataFetcherMac() { | 121 GamepadPlatformDataFetcherMac::~GamepadPlatformDataFetcherMac() { |
| 108 UnregisterFromNotifications(); | 122 UnregisterFromNotifications(); |
| 109 } | 123 } |
| 110 | 124 |
| 111 GamepadPlatformDataFetcherMac* | 125 GamepadPlatformDataFetcherMac* |
| 112 GamepadPlatformDataFetcherMac::InstanceFromContext( | 126 GamepadPlatformDataFetcherMac::InstanceFromContext(void* context) { |
| 113 void* context) { | |
| 114 return reinterpret_cast<GamepadPlatformDataFetcherMac*>(context); | 127 return reinterpret_cast<GamepadPlatformDataFetcherMac*>(context); |
| 115 } | 128 } |
| 116 | 129 |
| 117 void GamepadPlatformDataFetcherMac::DeviceAddCallback(void* context, | 130 void GamepadPlatformDataFetcherMac::DeviceAddCallback(void* context, |
| 118 IOReturn result, | 131 IOReturn result, |
| 119 void* sender, | 132 void* sender, |
| 120 IOHIDDeviceRef ref) { | 133 IOHIDDeviceRef ref) { |
| 121 InstanceFromContext(context)->DeviceAdd(ref); | 134 InstanceFromContext(context)->DeviceAdd(ref); |
| 122 } | 135 } |
| 123 | 136 |
| 124 void GamepadPlatformDataFetcherMac::DeviceRemoveCallback(void* context, | 137 void GamepadPlatformDataFetcherMac::DeviceRemoveCallback(void* context, |
| 125 IOReturn result, | 138 IOReturn result, |
| 126 void* sender, | 139 void* sender, |
| 127 IOHIDDeviceRef ref) { | 140 IOHIDDeviceRef ref) { |
| 128 InstanceFromContext(context)->DeviceRemove(ref); | 141 InstanceFromContext(context)->DeviceRemove(ref); |
| 129 } | 142 } |
| 130 | 143 |
| 131 void GamepadPlatformDataFetcherMac::ValueChangedCallback(void* context, | 144 void GamepadPlatformDataFetcherMac::ValueChangedCallback(void* context, |
| 132 IOReturn result, | 145 IOReturn result, |
| 133 void* sender, | 146 void* sender, |
| 134 IOHIDValueRef ref) { | 147 IOHIDValueRef ref) { |
| 135 InstanceFromContext(context)->ValueChanged(ref); | 148 InstanceFromContext(context)->ValueChanged(ref); |
| 136 } | 149 } |
| 137 | 150 |
| 138 void GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements, | 151 void GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements, |
| 139 size_t slot) { | 152 size_t slot) { |
| 140 WebKit::WebGamepad& pad = data_.items[slot]; | 153 WebGamepad& pad = data_.items[slot]; |
| 141 AssociatedData& associated = associated_[slot]; | 154 AssociatedData& associated = associated_[slot]; |
| 155 CHECK(!associated.is_xbox); |
| 142 | 156 |
| 143 pad.axesLength = 0; | 157 pad.axesLength = 0; |
| 144 pad.buttonsLength = 0; | 158 pad.buttonsLength = 0; |
| 145 pad.timestamp = 0; | 159 pad.timestamp = 0; |
| 146 memset(pad.axes, 0, sizeof(pad.axes)); | 160 memset(pad.axes, 0, sizeof(pad.axes)); |
| 147 memset(pad.buttons, 0, sizeof(pad.buttons)); | 161 memset(pad.buttons, 0, sizeof(pad.buttons)); |
| 148 | 162 |
| 149 for (id elem in elements) { | 163 for (id elem in elements) { |
| 150 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem); | 164 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem); |
| 151 uint32_t usagePage = IOHIDElementGetUsagePage(element); | 165 uint32_t usagePage = IOHIDElementGetUsagePage(element); |
| 152 uint32_t usage = IOHIDElementGetUsage(element); | 166 uint32_t usage = IOHIDElementGetUsage(element); |
| 153 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button && | 167 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button && |
| 154 usagePage == kButtonUsagePage) { | 168 usagePage == kButtonUsagePage) { |
| 155 uint32_t button_index = usage - 1; | 169 uint32_t button_index = usage - 1; |
| 156 if (button_index < WebKit::WebGamepad::buttonsLengthCap) { | 170 if (button_index < WebGamepad::buttonsLengthCap) { |
| 157 associated.button_elements[button_index] = element; | 171 associated.hid.button_elements[button_index] = element; |
| 158 pad.buttonsLength = std::max(pad.buttonsLength, button_index + 1); | 172 pad.buttonsLength = std::max(pad.buttonsLength, button_index + 1); |
| 159 } | 173 } |
| 160 } | 174 } |
| 161 else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) { | 175 else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) { |
| 162 uint32_t axis_index = usage - kAxisMinimumUsageNumber; | 176 uint32_t axis_index = usage - kAxisMinimumUsageNumber; |
| 163 if (axis_index < WebKit::WebGamepad::axesLengthCap) { | 177 if (axis_index < WebGamepad::axesLengthCap) { |
| 164 associated.axis_minimums[axis_index] = | 178 associated.hid.axis_minimums[axis_index] = |
| 165 IOHIDElementGetLogicalMin(element); | 179 IOHIDElementGetLogicalMin(element); |
| 166 associated.axis_maximums[axis_index] = | 180 associated.hid.axis_maximums[axis_index] = |
| 167 IOHIDElementGetLogicalMax(element); | 181 IOHIDElementGetLogicalMax(element); |
| 168 associated.axis_elements[axis_index] = element; | 182 associated.hid.axis_elements[axis_index] = element; |
| 169 pad.axesLength = std::max(pad.axesLength, axis_index + 1); | 183 pad.axesLength = std::max(pad.axesLength, axis_index + 1); |
| 170 } | 184 } |
| 171 } | 185 } |
| 172 } | 186 } |
| 173 } | 187 } |
| 174 | 188 |
| 189 size_t GamepadPlatformDataFetcherMac::GetEmptySlot() { |
| 190 // Find a free slot for this device. |
| 191 for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { |
| 192 if (!data_.items[slot].connected) |
| 193 return slot; |
| 194 } |
| 195 return WebGamepads::itemsLengthCap; |
| 196 } |
| 197 |
| 198 size_t GamepadPlatformDataFetcherMac::GetSlotForDevice(IOHIDDeviceRef device) { |
| 199 for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { |
| 200 // If we already have this device, and it's already connected, don't do |
| 201 // anything now. |
| 202 if (data_.items[slot].connected && |
| 203 !associated_[slot].is_xbox && |
| 204 associated_[slot].hid.device_ref == device) |
| 205 return WebGamepads::itemsLengthCap; |
| 206 } |
| 207 return GetEmptySlot(); |
| 208 } |
| 209 |
| 210 size_t GamepadPlatformDataFetcherMac::GetSlotForXboxDevice( |
| 211 XboxController* device) { |
| 212 for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { |
| 213 if (associated_[slot].is_xbox && |
| 214 associated_[slot].xbox.location_id == device->location_id()) { |
| 215 if (data_.items[slot].connected) { |
| 216 // The device is already connected. No idea why we got a second "device |
| 217 // added" call, but let's not add it twice. |
| 218 DCHECK_EQ(associated_[slot].xbox.device, device); |
| 219 return WebGamepads::itemsLengthCap; |
| 220 } else { |
| 221 // A device with the same location ID was previously connected, so put |
| 222 // it in the same slot. |
| 223 return slot; |
| 224 } |
| 225 } |
| 226 } |
| 227 return GetEmptySlot(); |
| 228 } |
| 229 |
| 175 void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) { | 230 void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) { |
| 176 using WebKit::WebGamepad; | |
| 177 using WebKit::WebGamepads; | |
| 178 using base::mac::CFToNSCast; | 231 using base::mac::CFToNSCast; |
| 179 using base::mac::CFCastStrict; | 232 using base::mac::CFCastStrict; |
| 180 size_t slot; | |
| 181 | 233 |
| 182 if (!enabled_) | 234 if (!enabled_) |
| 183 return; | 235 return; |
| 184 | 236 |
| 185 // Find an index for this device. | 237 // Find an index for this device. |
| 186 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { | 238 size_t slot = GetSlotForDevice(device); |
| 187 // If we already have this device, and it's already connected, don't do | |
| 188 // anything now. | |
| 189 if (associated_[slot].device_ref == device && data_.items[slot].connected) | |
| 190 return; | |
| 191 if (!data_.items[slot].connected) | |
| 192 break; | |
| 193 } | |
| 194 | 239 |
| 195 // We can't handle this many connected devices. | 240 // We can't handle this many connected devices. |
| 196 if (slot == WebGamepads::itemsLengthCap) | 241 if (slot == WebGamepads::itemsLengthCap) |
| 197 return; | 242 return; |
| 198 | 243 |
| 199 NSNumber* vendor_id = CFToNSCast(CFCastStrict<CFNumberRef>( | 244 NSNumber* vendor_id = CFToNSCast(CFCastStrict<CFNumberRef>( |
| 200 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)))); | 245 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)))); |
| 201 NSNumber* product_id = CFToNSCast(CFCastStrict<CFNumberRef>( | 246 NSNumber* product_id = CFToNSCast(CFCastStrict<CFNumberRef>( |
| 202 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)))); | 247 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)))); |
| 203 NSString* product = CFToNSCast(CFCastStrict<CFStringRef>( | 248 NSString* product = CFToNSCast(CFCastStrict<CFStringRef>( |
| 204 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)))); | 249 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)))); |
| 205 int vendor_int = [vendor_id intValue]; | 250 int vendor_int = [vendor_id intValue]; |
| 206 int product_int = [product_id intValue]; | 251 int product_int = [product_id intValue]; |
| 207 | 252 |
| 208 char vendor_as_str[5], product_as_str[5]; | 253 char vendor_as_str[5], product_as_str[5]; |
| 209 snprintf(vendor_as_str, sizeof(vendor_as_str), "%04x", vendor_int); | 254 snprintf(vendor_as_str, sizeof(vendor_as_str), "%04x", vendor_int); |
| 210 snprintf(product_as_str, sizeof(product_as_str), "%04x", product_int); | 255 snprintf(product_as_str, sizeof(product_as_str), "%04x", product_int); |
| 211 associated_[slot].mapper = | 256 associated_[slot].hid.mapper = |
| 212 GetGamepadStandardMappingFunction(vendor_as_str, product_as_str); | 257 GetGamepadStandardMappingFunction(vendor_as_str, product_as_str); |
| 213 | 258 |
| 214 NSString* ident = [NSString stringWithFormat: | 259 NSString* ident = [NSString stringWithFormat: |
| 215 @"%@ (%sVendor: %04x Product: %04x)", | 260 @"%@ (%sVendor: %04x Product: %04x)", |
| 216 product, | 261 product, |
| 217 associated_[slot].mapper ? "STANDARD GAMEPAD " : "", | 262 associated_[slot].hid.mapper ? "STANDARD GAMEPAD " : "", |
| 218 vendor_int, | 263 vendor_int, |
| 219 product_int]; | 264 product_int]; |
| 220 NSData* as16 = [ident dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; | 265 NSData* as16 = [ident dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; |
| 221 | 266 |
| 222 const size_t kOutputLengthBytes = sizeof(data_.items[slot].id); | 267 const size_t kOutputLengthBytes = sizeof(data_.items[slot].id); |
| 223 memset(&data_.items[slot].id, 0, kOutputLengthBytes); | 268 memset(&data_.items[slot].id, 0, kOutputLengthBytes); |
| 224 [as16 getBytes:data_.items[slot].id | 269 [as16 getBytes:data_.items[slot].id |
| 225 length:kOutputLengthBytes - sizeof(WebKit::WebUChar)]; | 270 length:kOutputLengthBytes - sizeof(WebKit::WebUChar)]; |
| 226 | 271 |
| 227 base::mac::ScopedCFTypeRef<CFArrayRef> elements( | 272 base::mac::ScopedCFTypeRef<CFArrayRef> elements( |
| 228 IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone)); | 273 IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone)); |
| 229 AddButtonsAndAxes(CFToNSCast(elements), slot); | 274 AddButtonsAndAxes(CFToNSCast(elements), slot); |
| 230 | 275 |
| 231 associated_[slot].device_ref = device; | 276 associated_[slot].hid.device_ref = device; |
| 232 data_.items[slot].connected = true; | 277 data_.items[slot].connected = true; |
| 233 if (slot >= data_.length) | 278 if (slot >= data_.length) |
| 234 data_.length = slot + 1; | 279 data_.length = slot + 1; |
| 235 } | 280 } |
| 236 | 281 |
| 237 void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) { | 282 void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) { |
| 238 using WebKit::WebGamepads; | |
| 239 size_t slot; | |
| 240 if (!enabled_) | 283 if (!enabled_) |
| 241 return; | 284 return; |
| 242 | 285 |
| 243 // Find the index for this device. | 286 // Find the index for this device. |
| 287 size_t slot; |
| 244 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { | 288 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { |
| 245 if (associated_[slot].device_ref == device && data_.items[slot].connected) | 289 if (data_.items[slot].connected && |
| 290 !associated_[slot].is_xbox && |
| 291 associated_[slot].hid.device_ref == device) |
| 246 break; | 292 break; |
| 247 } | 293 } |
| 248 DCHECK(slot < WebGamepads::itemsLengthCap); | 294 DCHECK(slot < WebGamepads::itemsLengthCap); |
| 249 // Leave associated device_ref so that it will be reconnected in the same | 295 // Leave associated device_ref so that it will be reconnected in the same |
| 250 // location. Simply mark it as disconnected. | 296 // location. Simply mark it as disconnected. |
| 251 data_.items[slot].connected = false; | 297 data_.items[slot].connected = false; |
| 252 } | 298 } |
| 253 | 299 |
| 254 void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) { | 300 void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) { |
| 255 if (!enabled_) | 301 if (!enabled_) |
| 256 return; | 302 return; |
| 257 | 303 |
| 258 IOHIDElementRef element = IOHIDValueGetElement(value); | 304 IOHIDElementRef element = IOHIDValueGetElement(value); |
| 259 IOHIDDeviceRef device = IOHIDElementGetDevice(element); | 305 IOHIDDeviceRef device = IOHIDElementGetDevice(element); |
| 260 | 306 |
| 261 // Find device slot. | 307 // Find device slot. |
| 262 size_t slot; | 308 size_t slot; |
| 263 for (slot = 0; slot < data_.length; ++slot) { | 309 for (slot = 0; slot < data_.length; ++slot) { |
| 264 if (data_.items[slot].connected && associated_[slot].device_ref == device) | 310 if (data_.items[slot].connected && |
| 311 !associated_[slot].is_xbox && |
| 312 associated_[slot].hid.device_ref == device) |
| 265 break; | 313 break; |
| 266 } | 314 } |
| 267 if (slot == data_.length) | 315 if (slot == data_.length) |
| 268 return; | 316 return; |
| 269 | 317 |
| 270 WebKit::WebGamepad& pad = data_.items[slot]; | 318 WebGamepad& pad = data_.items[slot]; |
| 271 AssociatedData& associated = associated_[slot]; | 319 AssociatedData& associated = associated_[slot]; |
| 272 | 320 |
| 273 // Find and fill in the associated button event, if any. | 321 // Find and fill in the associated button event, if any. |
| 274 for (size_t i = 0; i < pad.buttonsLength; ++i) { | 322 for (size_t i = 0; i < pad.buttonsLength; ++i) { |
| 275 if (associated.button_elements[i] == element) { | 323 if (associated.hid.button_elements[i] == element) { |
| 276 pad.buttons[i] = IOHIDValueGetIntegerValue(value) ? 1.f : 0.f; | 324 pad.buttons[i] = IOHIDValueGetIntegerValue(value) ? 1.f : 0.f; |
| 277 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); | 325 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); |
| 278 return; | 326 return; |
| 279 } | 327 } |
| 280 } | 328 } |
| 281 | 329 |
| 282 // Find and fill in the associated axis event, if any. | 330 // Find and fill in the associated axis event, if any. |
| 283 for (size_t i = 0; i < pad.axesLength; ++i) { | 331 for (size_t i = 0; i < pad.axesLength; ++i) { |
| 284 if (associated.axis_elements[i] == element) { | 332 if (associated.hid.axis_elements[i] == element) { |
| 285 pad.axes[i] = NormalizeAxis(IOHIDValueGetIntegerValue(value), | 333 pad.axes[i] = NormalizeAxis(IOHIDValueGetIntegerValue(value), |
| 286 associated.axis_minimums[i], | 334 associated.hid.axis_minimums[i], |
| 287 associated.axis_maximums[i]); | 335 associated.hid.axis_maximums[i]); |
| 288 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); | 336 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); |
| 289 return; | 337 return; |
| 290 } | 338 } |
| 291 } | 339 } |
| 292 } | 340 } |
| 293 | 341 |
| 294 void GamepadPlatformDataFetcherMac::GetGamepadData( | 342 void GamepadPlatformDataFetcherMac::XboxDeviceAdd(XboxController* device) { |
| 295 WebKit::WebGamepads* pads, | 343 if (!enabled_) |
| 296 bool) { | 344 return; |
| 297 if (!enabled_) { | 345 |
| 346 size_t slot = GetSlotForXboxDevice(device); |
| 347 |
| 348 // We can't handle this many connected devices. |
| 349 if (slot == WebGamepads::itemsLengthCap) |
| 350 return; |
| 351 |
| 352 device->SetLEDPattern( |
| 353 (XboxController::LEDPattern)(XboxController::LED_FLASH_TOP_LEFT + slot)); |
| 354 |
| 355 NSString* ident = |
| 356 [NSString stringWithFormat: |
| 357 @"Xbox 360 Controller (STANDARD GAMEPAD Vendor: %04x Product: %04x)", |
| 358 device->GetProductId(), device->GetVendorId()]; |
| 359 NSData* as16 = [ident dataUsingEncoding:NSUTF16StringEncoding]; |
| 360 const size_t kOutputLengthBytes = sizeof(data_.items[slot].id); |
| 361 memset(&data_.items[slot].id, 0, kOutputLengthBytes); |
| 362 [as16 getBytes:data_.items[slot].id |
| 363 length:kOutputLengthBytes - sizeof(WebKit::WebUChar)]; |
| 364 |
| 365 associated_[slot].is_xbox = true; |
| 366 associated_[slot].xbox.device = device; |
| 367 associated_[slot].xbox.location_id = device->location_id(); |
| 368 data_.items[slot].connected = true; |
| 369 data_.items[slot].axesLength = 4; |
| 370 data_.items[slot].buttonsLength = 17; |
| 371 data_.items[slot].timestamp = 0; |
| 372 if (slot >= data_.length) |
| 373 data_.length = slot + 1; |
| 374 } |
| 375 |
| 376 void GamepadPlatformDataFetcherMac::XboxDeviceRemove(XboxController* device) { |
| 377 if (!enabled_) |
| 378 return; |
| 379 |
| 380 // Find the index for this device. |
| 381 size_t slot; |
| 382 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { |
| 383 if (data_.items[slot].connected && |
| 384 associated_[slot].is_xbox && |
| 385 associated_[slot].xbox.device == device) |
| 386 break; |
| 387 } |
| 388 DCHECK(slot < WebGamepads::itemsLengthCap); |
| 389 // Leave associated location id so that the controller will be reconnected in |
| 390 // the same slot if it is plugged in again. Simply mark it as disconnected. |
| 391 data_.items[slot].connected = false; |
| 392 } |
| 393 |
| 394 void GamepadPlatformDataFetcherMac::XboxValueChanged( |
| 395 XboxController* device, const XboxController::Data& data) { |
| 396 // Find device slot. |
| 397 size_t slot; |
| 398 for (slot = 0; slot < data_.length; ++slot) { |
| 399 if (data_.items[slot].connected && |
| 400 associated_[slot].is_xbox && |
| 401 associated_[slot].xbox.device == device) |
| 402 break; |
| 403 } |
| 404 if (slot == data_.length) |
| 405 return; |
| 406 |
| 407 WebGamepad& pad = data_.items[slot]; |
| 408 |
| 409 for (size_t i = 0; i < 6; i++) { |
| 410 pad.buttons[i] = data.buttons[i] ? 0.0f : 1.1f; |
| 411 } |
| 412 pad.buttons[6] = data.triggers[0]; |
| 413 pad.buttons[7] = data.triggers[1]; |
| 414 for (size_t i = 8; i < 17; i++) { |
| 415 pad.buttons[i] = data.buttons[i - 2] ? 0.0f : 1.1f; |
| 416 } |
| 417 for (size_t i = 0; i < arraysize(data.axes); i++) { |
| 418 pad.axes[i] = data.axes[i]; |
| 419 } |
| 420 |
| 421 pad.timestamp = base::TimeTicks::Now().ToInternalValue(); |
| 422 } |
| 423 |
| 424 void GamepadPlatformDataFetcherMac::GetGamepadData(WebGamepads* pads, bool) { |
| 425 if (!enabled_ && !xbox_fetcher_) { |
| 298 pads->length = 0; | 426 pads->length = 0; |
| 299 return; | 427 return; |
| 300 } | 428 } |
| 301 | 429 |
| 302 // Copy to the current state to the output buffer, using the mapping | 430 // Copy to the current state to the output buffer, using the mapping |
| 303 // function, if there is one available. | 431 // function, if there is one available. |
| 304 pads->length = WebKit::WebGamepads::itemsLengthCap; | 432 pads->length = WebGamepads::itemsLengthCap; |
| 305 for (size_t i = 0; i < WebKit::WebGamepads::itemsLengthCap; ++i) { | 433 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { |
| 306 if (associated_[i].mapper) | 434 if (!associated_[i].is_xbox && associated_[i].hid.mapper) |
| 307 associated_[i].mapper(data_.items[i], &pads->items[i]); | 435 associated_[i].hid.mapper(data_.items[i], &pads->items[i]); |
| 308 else | 436 else |
| 309 pads->items[i] = data_.items[i]; | 437 pads->items[i] = data_.items[i]; |
| 310 } | 438 } |
| 311 } | 439 } |
| 312 | 440 |
| 313 } // namespace content | 441 } // namespace content |
| OLD | NEW |