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 |