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

Side by Side Diff: content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm

Issue 1627643002: Revert of Refactoring gamepad polling to support dynamically added sources (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 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 "content/browser/gamepad/gamepad_platform_data_fetcher_mac.h" 5 #include "content/browser/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"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 const uint32_t kGameControlsUsagePage = 0x05; 50 const uint32_t kGameControlsUsagePage = 0x05;
51 const uint32_t kButtonUsagePage = 0x09; 51 const uint32_t kButtonUsagePage = 0x09;
52 const uint32_t kJoystickUsageNumber = 0x04; 52 const uint32_t kJoystickUsageNumber = 0x04;
53 const uint32_t kGameUsageNumber = 0x05; 53 const uint32_t kGameUsageNumber = 0x05;
54 const uint32_t kMultiAxisUsageNumber = 0x08; 54 const uint32_t kMultiAxisUsageNumber = 0x08;
55 const uint32_t kAxisMinimumUsageNumber = 0x30; 55 const uint32_t kAxisMinimumUsageNumber = 0x30;
56 56
57 } // namespace 57 } // namespace
58 58
59 GamepadPlatformDataFetcherMac::GamepadPlatformDataFetcherMac() 59 GamepadPlatformDataFetcherMac::GamepadPlatformDataFetcherMac()
60 : enabled_(true), 60 : enabled_(true), paused_(false) {
61 paused_(false) {
62 memset(associated_, 0, sizeof(associated_)); 61 memset(associated_, 0, sizeof(associated_));
63 }
64 62
65 void GamepadPlatformDataFetcherMac::OnAddedToProvider() { 63 xbox_fetcher_.reset(new XboxDataFetcher(this));
64 if (!xbox_fetcher_->RegisterForNotifications())
65 xbox_fetcher_.reset();
66
66 hid_manager_ref_.reset(IOHIDManagerCreate(kCFAllocatorDefault, 67 hid_manager_ref_.reset(IOHIDManagerCreate(kCFAllocatorDefault,
67 kIOHIDOptionsTypeNone)); 68 kIOHIDOptionsTypeNone));
68 if (CFGetTypeID(hid_manager_ref_) != IOHIDManagerGetTypeID()) { 69 if (CFGetTypeID(hid_manager_ref_) != IOHIDManagerGetTypeID()) {
69 enabled_ = false; 70 enabled_ = false;
70 return; 71 return;
71 } 72 }
72 73
73 base::scoped_nsobject<NSArray> criteria([[NSArray alloc] initWithObjects: 74 base::scoped_nsobject<NSArray> criteria([[NSArray alloc] initWithObjects:
74 DeviceMatching(kGenericDesktopUsagePage, kJoystickUsageNumber), 75 DeviceMatching(kGenericDesktopUsagePage, kJoystickUsageNumber),
75 DeviceMatching(kGenericDesktopUsagePage, kGameUsageNumber), 76 DeviceMatching(kGenericDesktopUsagePage, kGameUsageNumber),
(...skipping 23 matching lines...) Expand all
99 ValueChangedCallback, 100 ValueChangedCallback,
100 this); 101 this);
101 102
102 IOHIDManagerScheduleWithRunLoop( 103 IOHIDManagerScheduleWithRunLoop(
103 hid_manager_ref_, 104 hid_manager_ref_,
104 CFRunLoopGetMain(), 105 CFRunLoopGetMain(),
105 kCFRunLoopDefaultMode); 106 kCFRunLoopDefaultMode);
106 107
107 enabled_ = IOHIDManagerOpen(hid_manager_ref_, 108 enabled_ = IOHIDManagerOpen(hid_manager_ref_,
108 kIOHIDOptionsTypeNone) == kIOReturnSuccess; 109 kIOHIDOptionsTypeNone) == kIOReturnSuccess;
110
111 if (xbox_fetcher_)
112 xbox_fetcher_->RegisterForNotifications();
109 } 113 }
110 114
111 void GamepadPlatformDataFetcherMac::UnregisterFromNotifications() { 115 void GamepadPlatformDataFetcherMac::UnregisterFromNotifications() {
112 IOHIDManagerUnscheduleFromRunLoop( 116 IOHIDManagerUnscheduleFromRunLoop(
113 hid_manager_ref_, 117 hid_manager_ref_,
114 CFRunLoopGetCurrent(), 118 CFRunLoopGetCurrent(),
115 kCFRunLoopDefaultMode); 119 kCFRunLoopDefaultMode);
116 IOHIDManagerClose(hid_manager_ref_, kIOHIDOptionsTypeNone); 120 IOHIDManagerClose(hid_manager_ref_, kIOHIDOptionsTypeNone);
121 if (xbox_fetcher_)
122 xbox_fetcher_->UnregisterFromNotifications();
117 } 123 }
118 124
119 void GamepadPlatformDataFetcherMac::PauseHint(bool pause) { 125 void GamepadPlatformDataFetcherMac::PauseHint(bool pause) {
120 paused_ = pause; 126 paused_ = pause;
121 } 127 }
122 128
123 GamepadPlatformDataFetcherMac::~GamepadPlatformDataFetcherMac() { 129 GamepadPlatformDataFetcherMac::~GamepadPlatformDataFetcherMac() {
124 UnregisterFromNotifications(); 130 UnregisterFromNotifications();
125 } 131 }
126 132
(...skipping 17 matching lines...) Expand all
144 } 150 }
145 151
146 void GamepadPlatformDataFetcherMac::ValueChangedCallback(void* context, 152 void GamepadPlatformDataFetcherMac::ValueChangedCallback(void* context,
147 IOReturn result, 153 IOReturn result,
148 void* sender, 154 void* sender,
149 IOHIDValueRef ref) { 155 IOHIDValueRef ref) {
150 InstanceFromContext(context)->ValueChanged(ref); 156 InstanceFromContext(context)->ValueChanged(ref);
151 } 157 }
152 158
153 bool GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements, 159 bool GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements,
154 PadState* state,
155 size_t slot) { 160 size_t slot) {
156 WebGamepad& pad = state->data; 161 WebGamepad& pad = pad_state_[slot].data;
157 AssociatedData& associated = associated_[slot]; 162 AssociatedData& associated = associated_[slot];
163 CHECK(!associated.is_xbox);
158 164
159 pad.axesLength = 0; 165 pad.axesLength = 0;
160 pad.buttonsLength = 0; 166 pad.buttonsLength = 0;
161 pad.timestamp = 0; 167 pad.timestamp = 0;
162 memset(pad.axes, 0, sizeof(pad.axes)); 168 memset(pad.axes, 0, sizeof(pad.axes));
163 memset(pad.buttons, 0, sizeof(pad.buttons)); 169 memset(pad.buttons, 0, sizeof(pad.buttons));
164 170
165 bool mapped_all_axes = true; 171 bool mapped_all_axes = true;
166 172
167 for (id elem in elements) { 173 for (id elem in elements) {
168 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem); 174 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
169 uint32_t usage_page = IOHIDElementGetUsagePage(element); 175 uint32_t usage_page = IOHIDElementGetUsagePage(element);
170 uint32_t usage = IOHIDElementGetUsage(element); 176 uint32_t usage = IOHIDElementGetUsage(element);
171 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button && 177 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button &&
172 usage_page == kButtonUsagePage) { 178 usage_page == kButtonUsagePage) {
173 uint32_t button_index = usage - 1; 179 uint32_t button_index = usage - 1;
174 if (button_index < WebGamepad::buttonsLengthCap) { 180 if (button_index < WebGamepad::buttonsLengthCap) {
175 associated.button_elements[button_index] = element; 181 associated.hid.button_elements[button_index] = element;
176 pad.buttonsLength = std::max(pad.buttonsLength, button_index + 1); 182 pad.buttonsLength = std::max(pad.buttonsLength, button_index + 1);
177 } 183 }
178 } 184 }
179 else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) { 185 else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) {
180 uint32_t axis_index = usage - kAxisMinimumUsageNumber; 186 uint32_t axis_index = usage - kAxisMinimumUsageNumber;
181 if (axis_index < WebGamepad::axesLengthCap) { 187 if (axis_index < WebGamepad::axesLengthCap) {
182 associated.axis_minimums[axis_index] = 188 associated.hid.axis_minimums[axis_index] =
183 IOHIDElementGetLogicalMin(element); 189 IOHIDElementGetLogicalMin(element);
184 associated.axis_maximums[axis_index] = 190 associated.hid.axis_maximums[axis_index] =
185 IOHIDElementGetLogicalMax(element); 191 IOHIDElementGetLogicalMax(element);
186 associated.axis_elements[axis_index] = element; 192 associated.hid.axis_elements[axis_index] = element;
187 pad.axesLength = std::max(pad.axesLength, axis_index + 1); 193 pad.axesLength = std::max(pad.axesLength, axis_index + 1);
188 } else { 194 } else {
189 mapped_all_axes = false; 195 mapped_all_axes = false;
190 } 196 }
191 } 197 }
192 } 198 }
193 199
194 if (!mapped_all_axes) { 200 if (!mapped_all_axes) {
195 // For axes who's usage puts them outside the standard axesLengthCap range. 201 // For axes who's usage puts them outside the standard axesLengthCap range.
196 uint32_t next_index = 0; 202 uint32_t next_index = 0;
197 for (id elem in elements) { 203 for (id elem in elements) {
198 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem); 204 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
199 uint32_t usage_page = IOHIDElementGetUsagePage(element); 205 uint32_t usage_page = IOHIDElementGetUsagePage(element);
200 uint32_t usage = IOHIDElementGetUsage(element); 206 uint32_t usage = IOHIDElementGetUsage(element);
201 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc && 207 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc &&
202 usage - kAxisMinimumUsageNumber >= WebGamepad::axesLengthCap && 208 usage - kAxisMinimumUsageNumber >= WebGamepad::axesLengthCap &&
203 usage_page <= kGameControlsUsagePage) { 209 usage_page <= kGameControlsUsagePage) {
204 for (; next_index < WebGamepad::axesLengthCap; ++next_index) { 210 for (; next_index < WebGamepad::axesLengthCap; ++next_index) {
205 if (associated.axis_elements[next_index] == NULL) 211 if (associated.hid.axis_elements[next_index] == NULL)
206 break; 212 break;
207 } 213 }
208 if (next_index < WebGamepad::axesLengthCap) { 214 if (next_index < WebGamepad::axesLengthCap) {
209 associated.axis_minimums[next_index] = 215 associated.hid.axis_minimums[next_index] =
210 IOHIDElementGetLogicalMin(element); 216 IOHIDElementGetLogicalMin(element);
211 associated.axis_maximums[next_index] = 217 associated.hid.axis_maximums[next_index] =
212 IOHIDElementGetLogicalMax(element); 218 IOHIDElementGetLogicalMax(element);
213 associated.axis_elements[next_index] = element; 219 associated.hid.axis_elements[next_index] = element;
214 pad.axesLength = std::max(pad.axesLength, next_index + 1); 220 pad.axesLength = std::max(pad.axesLength, next_index + 1);
215 } 221 }
216 } 222 }
217 223
218 if (next_index >= WebGamepad::axesLengthCap) 224 if (next_index >= WebGamepad::axesLengthCap)
219 break; 225 break;
220 } 226 }
221 } 227 }
222 228
223 return (pad.axesLength > 0 || pad.buttonsLength > 0); 229 return (pad.axesLength > 0 || pad.buttonsLength > 0);
224 } 230 }
225 231
226 size_t GamepadPlatformDataFetcherMac::GetEmptySlot() { 232 size_t GamepadPlatformDataFetcherMac::GetEmptySlot() {
227 // Find a free slot for this device. 233 // Find a free slot for this device.
228 for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { 234 for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
229 if (associated_[slot].device_ref == nullptr) 235 if (!pad_state_[slot].data.connected)
230 return slot; 236 return slot;
231 } 237 }
232 return WebGamepads::itemsLengthCap; 238 return WebGamepads::itemsLengthCap;
233 } 239 }
234 240
235 size_t GamepadPlatformDataFetcherMac::GetSlotForDevice(IOHIDDeviceRef device) { 241 size_t GamepadPlatformDataFetcherMac::GetSlotForDevice(IOHIDDeviceRef device) {
236 for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { 242 for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
237 // If we already have this device, and it's already connected, don't do 243 // If we already have this device, and it's already connected, don't do
238 // anything now. 244 // anything now.
239 if (associated_[slot].device_ref == device) 245 if (pad_state_[slot].data.connected &&
246 !associated_[slot].is_xbox &&
247 associated_[slot].hid.device_ref == device)
240 return WebGamepads::itemsLengthCap; 248 return WebGamepads::itemsLengthCap;
241 } 249 }
242 return GetEmptySlot(); 250 return GetEmptySlot();
243 } 251 }
252
253 size_t GamepadPlatformDataFetcherMac::GetSlotForXboxDevice(
254 XboxController* device) {
255 for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
256 if (associated_[slot].is_xbox &&
257 associated_[slot].xbox.location_id == device->location_id()) {
258 if (pad_state_[slot].data.connected) {
259 // The device is already connected. No idea why we got a second "device
260 // added" call, but let's not add it twice.
261 DCHECK_EQ(associated_[slot].xbox.device, device);
262 return WebGamepads::itemsLengthCap;
263 } else {
264 // A device with the same location ID was previously connected, so put
265 // it in the same slot.
266 return slot;
267 }
268 }
269 }
270 return GetEmptySlot();
271 }
244 272
245 void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) { 273 void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) {
246 using base::mac::CFToNSCast; 274 using base::mac::CFToNSCast;
247 using base::mac::CFCastStrict; 275 using base::mac::CFCastStrict;
248 276
249 if (!enabled_) 277 if (!enabled_)
250 return; 278 return;
251 279
252 NSNumber* location_id = CFToNSCast(CFCastStrict<CFNumberRef>(
253 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDLocationIDKey))));
254 int location_int = [location_id intValue];
255
256 // Find an index for this device. 280 // Find an index for this device.
257 size_t slot = GetSlotForDevice(device); 281 size_t slot = GetSlotForDevice(device);
282
258 // We can't handle this many connected devices. 283 // We can't handle this many connected devices.
259 if (slot == WebGamepads::itemsLengthCap) 284 if (slot == WebGamepads::itemsLengthCap)
260 return; 285 return;
261 286
262 // Clear some state that may have been left behind by previous gamepads 287 // Clear some state that may have been left behind by previous gamepads
263 memset(&associated_[slot], 0, sizeof(AssociatedData)); 288 memset(&associated_[slot], 0, sizeof(AssociatedData));
264 289
265 PadState* state = provider()->GetPadState(GAMEPAD_SOURCE_MAC_HID,
266 location_int);
267 if (!state)
268 return; // No available slot for this device
269
270 NSNumber* vendor_id = CFToNSCast(CFCastStrict<CFNumberRef>( 290 NSNumber* vendor_id = CFToNSCast(CFCastStrict<CFNumberRef>(
271 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)))); 291 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey))));
272 NSNumber* product_id = CFToNSCast(CFCastStrict<CFNumberRef>( 292 NSNumber* product_id = CFToNSCast(CFCastStrict<CFNumberRef>(
273 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)))); 293 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey))));
274
275 NSString* product = CFToNSCast(CFCastStrict<CFStringRef>( 294 NSString* product = CFToNSCast(CFCastStrict<CFStringRef>(
276 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)))); 295 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey))));
277 int vendor_int = [vendor_id intValue]; 296 int vendor_int = [vendor_id intValue];
278 int product_int = [product_id intValue]; 297 int product_int = [product_id intValue];
279 298
280 char vendor_as_str[5], product_as_str[5]; 299 char vendor_as_str[5], product_as_str[5];
281 snprintf(vendor_as_str, sizeof(vendor_as_str), "%04x", vendor_int); 300 snprintf(vendor_as_str, sizeof(vendor_as_str), "%04x", vendor_int);
282 snprintf(product_as_str, sizeof(product_as_str), "%04x", product_int); 301 snprintf(product_as_str, sizeof(product_as_str), "%04x", product_int);
283 state->mapper = 302 pad_state_[slot].mapper =
284 GetGamepadStandardMappingFunction(vendor_as_str, product_as_str); 303 GetGamepadStandardMappingFunction(vendor_as_str, product_as_str);
285 304
286 NSString* ident = [NSString stringWithFormat: 305 NSString* ident = [NSString stringWithFormat:
287 @"%@ (%sVendor: %04x Product: %04x)", 306 @"%@ (%sVendor: %04x Product: %04x)",
288 product, 307 product,
289 state->mapper ? "STANDARD GAMEPAD " : "", 308 pad_state_[slot].mapper ? "STANDARD GAMEPAD " : "",
290 vendor_int, 309 vendor_int,
291 product_int]; 310 product_int];
292 CopyNSStringAsUTF16LittleEndian( 311 CopyNSStringAsUTF16LittleEndian(
293 ident, 312 ident,
294 state->data.id, 313 pad_state_[slot].data.id,
295 sizeof(state->data.id)); 314 sizeof(pad_state_[slot].data.id));
296 315
297 if (state->mapper) { 316 if (pad_state_[slot].mapper) {
298 CopyNSStringAsUTF16LittleEndian( 317 CopyNSStringAsUTF16LittleEndian(
299 @"standard", 318 @"standard",
300 state->data.mapping, 319 pad_state_[slot].data.mapping,
301 sizeof(state->data.mapping)); 320 sizeof(pad_state_[slot].data.mapping));
302 } else { 321 } else {
303 state->data.mapping[0] = 0; 322 pad_state_[slot].data.mapping[0] = 0;
304 } 323 }
305 324
306 base::ScopedCFTypeRef<CFArrayRef> elements( 325 base::ScopedCFTypeRef<CFArrayRef> elements(
307 IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone)); 326 IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone));
308 327
309 if (!AddButtonsAndAxes(CFToNSCast(elements), state, slot)) 328 if (!AddButtonsAndAxes(CFToNSCast(elements), slot))
310 return; 329 return;
311 330
312 associated_[slot].location_id = location_int; 331 associated_[slot].hid.device_ref = device;
313 associated_[slot].device_ref = device; 332 pad_state_[slot].data.connected = true;
314 state->data.connected = true; 333 pad_state_[slot].axis_mask = 0;
334 pad_state_[slot].button_mask = 0;
315 } 335 }
316 336
317 void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) { 337 void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) {
318 if (!enabled_) 338 if (!enabled_)
319 return; 339 return;
320 340
321 // Find the index for this device. 341 // Find the index for this device.
322 size_t slot; 342 size_t slot;
323 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { 343 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
324 if (associated_[slot].device_ref == device) 344 if (pad_state_[slot].data.connected &&
345 !associated_[slot].is_xbox &&
346 associated_[slot].hid.device_ref == device)
325 break; 347 break;
326 } 348 }
327 DCHECK(slot < WebGamepads::itemsLengthCap); 349 DCHECK(slot < WebGamepads::itemsLengthCap);
328 // Leave associated device_ref so that it will be reconnected in the same 350 // Leave associated device_ref so that it will be reconnected in the same
329 // location. Simply mark it as disconnected. 351 // location. Simply mark it as disconnected.
330 associated_[slot].location_id = 0; 352 pad_state_[slot].data.connected = false;
331 associated_[slot].device_ref = nullptr;
332 } 353 }
333 354
334 void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) { 355 void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) {
335 if (!enabled_ || paused_) 356 if (!enabled_ || paused_)
336 return; 357 return;
337 358
338 IOHIDElementRef element = IOHIDValueGetElement(value); 359 IOHIDElementRef element = IOHIDValueGetElement(value);
339 IOHIDDeviceRef device = IOHIDElementGetDevice(element); 360 IOHIDDeviceRef device = IOHIDElementGetDevice(element);
340 361
341 // Find device slot. 362 // Find device slot.
342 size_t slot; 363 size_t slot;
343 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { 364 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
344 if (associated_[slot].device_ref == device) 365 if (pad_state_[slot].data.connected &&
366 !associated_[slot].is_xbox &&
367 associated_[slot].hid.device_ref == device)
345 break; 368 break;
346 } 369 }
347 if (slot == WebGamepads::itemsLengthCap) 370 if (slot == WebGamepads::itemsLengthCap)
348 return; 371 return;
349 372
350 PadState* state = provider()->GetPadState(GAMEPAD_SOURCE_MAC_HID, 373 WebGamepad& pad = pad_state_[slot].data;
351 associated_[slot].location_id);
352 if (!state)
353 return;
354
355 WebGamepad& pad = state->data;
356 AssociatedData& associated = associated_[slot]; 374 AssociatedData& associated = associated_[slot];
357 375
358 uint32_t value_length = IOHIDValueGetLength(value); 376 uint32_t value_length = IOHIDValueGetLength(value);
359 if (value_length > 4) { 377 if (value_length > 4) {
360 // Workaround for bizarre issue with PS3 controllers that try to return 378 // Workaround for bizarre issue with PS3 controllers that try to return
361 // massive (30+ byte) values and crash IOHIDValueGetIntegerValue 379 // massive (30+ byte) values and crash IOHIDValueGetIntegerValue
362 return; 380 return;
363 } 381 }
364 382
365 // Find and fill in the associated button event, if any. 383 // Find and fill in the associated button event, if any.
366 for (size_t i = 0; i < pad.buttonsLength; ++i) { 384 for (size_t i = 0; i < pad.buttonsLength; ++i) {
367 if (associated.button_elements[i] == element) { 385 if (associated.hid.button_elements[i] == element) {
368 pad.buttons[i].pressed = IOHIDValueGetIntegerValue(value); 386 pad.buttons[i].pressed = IOHIDValueGetIntegerValue(value);
369 pad.buttons[i].value = pad.buttons[i].pressed ? 1.f : 0.f; 387 pad.buttons[i].value = pad.buttons[i].pressed ? 1.f : 0.f;
370 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); 388 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value));
371 return; 389 return;
372 } 390 }
373 } 391 }
374 392
375 // Find and fill in the associated axis event, if any. 393 // Find and fill in the associated axis event, if any.
376 for (size_t i = 0; i < pad.axesLength; ++i) { 394 for (size_t i = 0; i < pad.axesLength; ++i) {
377 if (associated.axis_elements[i] == element) { 395 if (associated.hid.axis_elements[i] == element) {
378 pad.axes[i] = NormalizeAxis(IOHIDValueGetIntegerValue(value), 396 pad.axes[i] = NormalizeAxis(IOHIDValueGetIntegerValue(value),
379 associated.axis_minimums[i], 397 associated.hid.axis_minimums[i],
380 associated.axis_maximums[i]); 398 associated.hid.axis_maximums[i]);
381 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); 399 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value));
382 return; 400 return;
383 } 401 }
384 } 402 }
385 } 403 }
386 404
387 void GamepadPlatformDataFetcherMac::GetGamepadData(bool) { 405 void GamepadPlatformDataFetcherMac::XboxDeviceAdd(XboxController* device) {
388 if (!enabled_) 406 if (!enabled_)
389 return; 407 return;
390 408
391 // Loop through and GetPadState to indicate the devices are still connected. 409 size_t slot = GetSlotForXboxDevice(device);
392 for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { 410
393 if (associated_[slot].device_ref != nullptr) { 411 // We can't handle this many connected devices.
394 provider()->GetPadState(GAMEPAD_SOURCE_MAC_HID, 412 if (slot == WebGamepads::itemsLengthCap)
395 associated_[slot].location_id); 413 return;
396 } 414
415 device->SetLEDPattern(
416 (XboxController::LEDPattern)(XboxController::LED_FLASH_TOP_LEFT + slot));
417
418 NSString* ident =
419 [NSString stringWithFormat:
420 @"%@ (STANDARD GAMEPAD Vendor: %04x Product: %04x)",
421 device->GetControllerType() == XboxController::XBOX_360_CONTROLLER
422 ? @"Xbox 360 Controller"
423 : @"Xbox One Controller",
424 device->GetProductId(), device->GetVendorId()];
425 CopyNSStringAsUTF16LittleEndian(
426 ident,
427 pad_state_[slot].data.id,
428 sizeof(pad_state_[slot].data.id));
429
430 CopyNSStringAsUTF16LittleEndian(
431 @"standard",
432 pad_state_[slot].data.mapping,
433 sizeof(pad_state_[slot].data.mapping));
434
435 associated_[slot].is_xbox = true;
436 associated_[slot].xbox.device = device;
437 associated_[slot].xbox.location_id = device->location_id();
438 pad_state_[slot].data.connected = true;
439 pad_state_[slot].data.axesLength = 4;
440 pad_state_[slot].data.buttonsLength = 17;
441 pad_state_[slot].data.timestamp = 0;
442 pad_state_[slot].mapper = 0;
443 pad_state_[slot].axis_mask = 0;
444 pad_state_[slot].button_mask = 0;
445 }
446
447 void GamepadPlatformDataFetcherMac::XboxDeviceRemove(XboxController* device) {
448 if (!enabled_)
449 return;
450
451 // Find the index for this device.
452 size_t slot;
453 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
454 if (pad_state_[slot].data.connected &&
455 associated_[slot].is_xbox &&
456 associated_[slot].xbox.device == device)
457 break;
397 } 458 }
459 DCHECK(slot < WebGamepads::itemsLengthCap);
460 // Leave associated location id so that the controller will be reconnected in
461 // the same slot if it is plugged in again. Simply mark it as disconnected.
462 pad_state_[slot].data.connected = false;
463 }
464
465 void GamepadPlatformDataFetcherMac::XboxValueChanged(
466 XboxController* device, const XboxController::Data& data) {
467 // Find device slot.
468 size_t slot;
469 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
470 if (pad_state_[slot].data.connected &&
471 associated_[slot].is_xbox &&
472 associated_[slot].xbox.device == device)
473 break;
474 }
475 if (slot == WebGamepads::itemsLengthCap)
476 return;
477
478 WebGamepad& pad = pad_state_[slot].data;
479
480 for (size_t i = 0; i < 6; i++) {
481 pad.buttons[i].pressed = data.buttons[i];
482 pad.buttons[i].value = data.buttons[i] ? 1.0f : 0.0f;
483 }
484 pad.buttons[6].pressed = data.triggers[0] > kDefaultButtonPressedThreshold;
485 pad.buttons[6].value = data.triggers[0];
486 pad.buttons[7].pressed = data.triggers[1] > kDefaultButtonPressedThreshold;
487 pad.buttons[7].value = data.triggers[1];
488 for (size_t i = 8; i < 17; i++) {
489 pad.buttons[i].pressed = data.buttons[i - 2];
490 pad.buttons[i].value = data.buttons[i - 2] ? 1.0f : 0.0f;
491 }
492 for (size_t i = 0; i < arraysize(data.axes); i++) {
493 pad.axes[i] = data.axes[i];
494 }
495
496 pad.timestamp = base::TimeTicks::Now().ToInternalValue();
497 }
498
499 void GamepadPlatformDataFetcherMac::GetGamepadData(WebGamepads* pads, bool) {
500 if (!enabled_ && !xbox_fetcher_) {
501 pads->length = 0;
502 return;
503 }
504
505 pads->length = WebGamepads::itemsLengthCap;
506 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i)
507 MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]);
398 } 508 }
399 509
400 } // namespace content 510 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698