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

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

Issue 14328036: Implement support for USB Xbox360 controllers without a driver on Mac. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CFCastStrict Created 7 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 | Annotate | Revision Log
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 "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 27 matching lines...) Expand all
53 57
54 scoped_nsobject<NSArray> criteria([[NSArray alloc] initWithObjects: 58 scoped_nsobject<NSArray> criteria([[NSArray alloc] initWithObjects:
55 DeviceMatching(kGenericDesktopUsagePage, kJoystickUsageNumber), 59 DeviceMatching(kGenericDesktopUsagePage, kJoystickUsageNumber),
56 DeviceMatching(kGenericDesktopUsagePage, kGameUsageNumber), 60 DeviceMatching(kGenericDesktopUsagePage, kGameUsageNumber),
57 DeviceMatching(kGenericDesktopUsagePage, kMultiAxisUsageNumber), 61 DeviceMatching(kGenericDesktopUsagePage, kMultiAxisUsageNumber),
58 nil]); 62 nil]);
59 IOHIDManagerSetDeviceMatchingMultiple( 63 IOHIDManagerSetDeviceMatchingMultiple(
60 hid_manager_ref_, 64 hid_manager_ref_,
61 base::mac::NSToCFCast(criteria)); 65 base::mac::NSToCFCast(criteria));
62 66
67 xbox_fetcher_.reset(new XboxDataFetcher(this));
68
63 RegisterForNotifications(); 69 RegisterForNotifications();
64 } 70 }
65 71
66 void GamepadPlatformDataFetcherMac::RegisterForNotifications() { 72 void GamepadPlatformDataFetcherMac::RegisterForNotifications() {
67 // Register for plug/unplug notifications. 73 // Register for plug/unplug notifications.
68 IOHIDManagerRegisterDeviceMatchingCallback( 74 IOHIDManagerRegisterDeviceMatchingCallback(
69 hid_manager_ref_, 75 hid_manager_ref_,
70 &DeviceAddCallback, 76 &DeviceAddCallback,
71 this); 77 this);
72 IOHIDManagerRegisterDeviceRemovalCallback( 78 IOHIDManagerRegisterDeviceRemovalCallback(
73 hid_manager_ref_, 79 hid_manager_ref_,
74 DeviceRemoveCallback, 80 DeviceRemoveCallback,
75 this); 81 this);
76 82
77 // Register for value change notifications. 83 // Register for value change notifications.
78 IOHIDManagerRegisterInputValueCallback( 84 IOHIDManagerRegisterInputValueCallback(
79 hid_manager_ref_, 85 hid_manager_ref_,
80 ValueChangedCallback, 86 ValueChangedCallback,
81 this); 87 this);
82 88
83 IOHIDManagerScheduleWithRunLoop( 89 IOHIDManagerScheduleWithRunLoop(
84 hid_manager_ref_, 90 hid_manager_ref_,
85 CFRunLoopGetMain(), 91 CFRunLoopGetMain(),
86 kCFRunLoopDefaultMode); 92 kCFRunLoopDefaultMode);
87 93
88 enabled_ = IOHIDManagerOpen(hid_manager_ref_, 94 enabled_ = IOHIDManagerOpen(hid_manager_ref_,
89 kIOHIDOptionsTypeNone) == kIOReturnSuccess; 95 kIOHIDOptionsTypeNone) == kIOReturnSuccess;
96
97 xbox_fetcher_->RegisterForNotifications();
90 } 98 }
91 99
92 void GamepadPlatformDataFetcherMac::UnregisterFromNotifications() { 100 void GamepadPlatformDataFetcherMac::UnregisterFromNotifications() {
93 IOHIDManagerUnscheduleFromRunLoop( 101 IOHIDManagerUnscheduleFromRunLoop(
94 hid_manager_ref_, 102 hid_manager_ref_,
95 CFRunLoopGetCurrent(), 103 CFRunLoopGetCurrent(),
96 kCFRunLoopDefaultMode); 104 kCFRunLoopDefaultMode);
97 IOHIDManagerClose(hid_manager_ref_, kIOHIDOptionsTypeNone); 105 IOHIDManagerClose(hid_manager_ref_, kIOHIDOptionsTypeNone);
106 xbox_fetcher_->UnregisterFromNotifications();
98 } 107 }
99 108
100 void GamepadPlatformDataFetcherMac::PauseHint(bool pause) { 109 void GamepadPlatformDataFetcherMac::PauseHint(bool pause) {
101 if (pause) 110 if (pause)
102 UnregisterFromNotifications(); 111 UnregisterFromNotifications();
103 else 112 else
104 RegisterForNotifications(); 113 RegisterForNotifications();
105 } 114 }
106 115
107 GamepadPlatformDataFetcherMac::~GamepadPlatformDataFetcherMac() { 116 GamepadPlatformDataFetcherMac::~GamepadPlatformDataFetcherMac() {
108 UnregisterFromNotifications(); 117 UnregisterFromNotifications();
109 } 118 }
110 119
111 GamepadPlatformDataFetcherMac* 120 GamepadPlatformDataFetcherMac*
112 GamepadPlatformDataFetcherMac::InstanceFromContext( 121 GamepadPlatformDataFetcherMac::InstanceFromContext(void* context) {
113 void* context) {
114 return reinterpret_cast<GamepadPlatformDataFetcherMac*>(context); 122 return reinterpret_cast<GamepadPlatformDataFetcherMac*>(context);
115 } 123 }
116 124
117 void GamepadPlatformDataFetcherMac::DeviceAddCallback(void* context, 125 void GamepadPlatformDataFetcherMac::DeviceAddCallback(void* context,
118 IOReturn result, 126 IOReturn result,
119 void* sender, 127 void* sender,
120 IOHIDDeviceRef ref) { 128 IOHIDDeviceRef ref) {
121 InstanceFromContext(context)->DeviceAdd(ref); 129 InstanceFromContext(context)->DeviceAdd(ref);
122 } 130 }
123 131
124 void GamepadPlatformDataFetcherMac::DeviceRemoveCallback(void* context, 132 void GamepadPlatformDataFetcherMac::DeviceRemoveCallback(void* context,
125 IOReturn result, 133 IOReturn result,
126 void* sender, 134 void* sender,
127 IOHIDDeviceRef ref) { 135 IOHIDDeviceRef ref) {
128 InstanceFromContext(context)->DeviceRemove(ref); 136 InstanceFromContext(context)->DeviceRemove(ref);
129 } 137 }
130 138
131 void GamepadPlatformDataFetcherMac::ValueChangedCallback(void* context, 139 void GamepadPlatformDataFetcherMac::ValueChangedCallback(void* context,
132 IOReturn result, 140 IOReturn result,
133 void* sender, 141 void* sender,
134 IOHIDValueRef ref) { 142 IOHIDValueRef ref) {
135 InstanceFromContext(context)->ValueChanged(ref); 143 InstanceFromContext(context)->ValueChanged(ref);
136 } 144 }
137 145
138 void GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements, 146 void GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements,
139 size_t slot) { 147 size_t slot) {
140 WebKit::WebGamepad& pad = data_.items[slot]; 148 WebGamepad& pad = data_.items[slot];
141 AssociatedData& associated = associated_[slot]; 149 AssociatedData& associated = associated_[slot];
150 CHECK(!associated.is_xbox);
142 151
143 pad.axesLength = 0; 152 pad.axesLength = 0;
144 pad.buttonsLength = 0; 153 pad.buttonsLength = 0;
145 pad.timestamp = 0; 154 pad.timestamp = 0;
146 memset(pad.axes, 0, sizeof(pad.axes)); 155 memset(pad.axes, 0, sizeof(pad.axes));
147 memset(pad.buttons, 0, sizeof(pad.buttons)); 156 memset(pad.buttons, 0, sizeof(pad.buttons));
148 157
149 for (id elem in elements) { 158 for (id elem in elements) {
150 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem); 159 IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
151 uint32_t usagePage = IOHIDElementGetUsagePage(element); 160 uint32_t usagePage = IOHIDElementGetUsagePage(element);
152 uint32_t usage = IOHIDElementGetUsage(element); 161 uint32_t usage = IOHIDElementGetUsage(element);
153 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button && 162 if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button &&
154 usagePage == kButtonUsagePage) { 163 usagePage == kButtonUsagePage) {
155 uint32_t button_index = usage - 1; 164 uint32_t button_index = usage - 1;
156 if (button_index < WebKit::WebGamepad::buttonsLengthCap) { 165 if (button_index < WebGamepad::buttonsLengthCap) {
157 associated.button_elements[button_index] = element; 166 associated.hid.button_elements[button_index] = element;
158 pad.buttonsLength = std::max(pad.buttonsLength, button_index + 1); 167 pad.buttonsLength = std::max(pad.buttonsLength, button_index + 1);
159 } 168 }
160 } 169 }
161 else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) { 170 else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) {
162 uint32_t axis_index = usage - kAxisMinimumUsageNumber; 171 uint32_t axis_index = usage - kAxisMinimumUsageNumber;
163 if (axis_index < WebKit::WebGamepad::axesLengthCap) { 172 if (axis_index < WebGamepad::axesLengthCap) {
164 associated.axis_minimums[axis_index] = 173 associated.hid.axis_minimums[axis_index] =
165 IOHIDElementGetLogicalMin(element); 174 IOHIDElementGetLogicalMin(element);
166 associated.axis_maximums[axis_index] = 175 associated.hid.axis_maximums[axis_index] =
167 IOHIDElementGetLogicalMax(element); 176 IOHIDElementGetLogicalMax(element);
168 associated.axis_elements[axis_index] = element; 177 associated.hid.axis_elements[axis_index] = element;
169 pad.axesLength = std::max(pad.axesLength, axis_index + 1); 178 pad.axesLength = std::max(pad.axesLength, axis_index + 1);
170 } 179 }
171 } 180 }
172 } 181 }
173 } 182 }
174 183
175 void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) { 184 void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) {
176 using WebKit::WebGamepad;
177 using WebKit::WebGamepads;
178 using base::mac::CFToNSCast; 185 using base::mac::CFToNSCast;
179 using base::mac::CFCastStrict; 186 using base::mac::CFCastStrict;
180 size_t slot;
181 187
182 if (!enabled_) 188 if (!enabled_)
183 return; 189 return;
184 190
185 // Find an index for this device. 191 // Find an index for this device.
192 size_t slot;
186 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { 193 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
187 // If we already have this device, and it's already connected, don't do 194 // If we already have this device, and it's already connected, don't do
188 // anything now. 195 // anything now.
189 if (associated_[slot].device_ref == device && data_.items[slot].connected) 196 if (data_.items[slot].connected &&
197 !associated_[slot].is_xbox &&
198 associated_[slot].hid.device_ref == device)
190 return; 199 return;
191 if (!data_.items[slot].connected) 200 if (!data_.items[slot].connected)
192 break; 201 break;
193 } 202 }
194 203
195 // We can't handle this many connected devices. 204 // We can't handle this many connected devices.
196 if (slot == WebGamepads::itemsLengthCap) 205 if (slot == WebGamepads::itemsLengthCap)
197 return; 206 return;
198 207
199 NSNumber* vendor_id = CFToNSCast(CFCastStrict<CFNumberRef>( 208 NSNumber* vendor_id = CFToNSCast(CFCastStrict<CFNumberRef>(
200 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)))); 209 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey))));
201 NSNumber* product_id = CFToNSCast(CFCastStrict<CFNumberRef>( 210 NSNumber* product_id = CFToNSCast(CFCastStrict<CFNumberRef>(
202 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)))); 211 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey))));
203 NSString* product = CFToNSCast(CFCastStrict<CFStringRef>( 212 NSString* product = CFToNSCast(CFCastStrict<CFStringRef>(
204 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)))); 213 IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey))));
205 int vendor_int = [vendor_id intValue]; 214 int vendor_int = [vendor_id intValue];
206 int product_int = [product_id intValue]; 215 int product_int = [product_id intValue];
207 216
208 char vendor_as_str[5], product_as_str[5]; 217 char vendor_as_str[5], product_as_str[5];
209 snprintf(vendor_as_str, sizeof(vendor_as_str), "%04x", vendor_int); 218 snprintf(vendor_as_str, sizeof(vendor_as_str), "%04x", vendor_int);
210 snprintf(product_as_str, sizeof(product_as_str), "%04x", product_int); 219 snprintf(product_as_str, sizeof(product_as_str), "%04x", product_int);
211 associated_[slot].mapper = 220 associated_[slot].hid.mapper =
212 GetGamepadStandardMappingFunction(vendor_as_str, product_as_str); 221 GetGamepadStandardMappingFunction(vendor_as_str, product_as_str);
213 222
214 NSString* ident = [NSString stringWithFormat: 223 NSString* ident = [NSString stringWithFormat:
215 @"%@ (%sVendor: %04x Product: %04x)", 224 @"%@ (%sVendor: %04x Product: %04x)",
216 product, 225 product,
217 associated_[slot].mapper ? "STANDARD GAMEPAD " : "", 226 associated_[slot].hid.mapper ? "STANDARD GAMEPAD " : "",
218 vendor_int, 227 vendor_int,
219 product_int]; 228 product_int];
220 NSData* as16 = [ident dataUsingEncoding:NSUTF16StringEncoding]; 229 NSData* as16 = [ident dataUsingEncoding:NSUTF16StringEncoding];
221 230
222 const size_t kOutputLengthBytes = sizeof(data_.items[slot].id); 231 const size_t kOutputLengthBytes = sizeof(data_.items[slot].id);
223 memset(&data_.items[slot].id, 0, kOutputLengthBytes); 232 memset(&data_.items[slot].id, 0, kOutputLengthBytes);
224 [as16 getBytes:data_.items[slot].id 233 [as16 getBytes:data_.items[slot].id
225 length:kOutputLengthBytes - sizeof(WebKit::WebUChar)]; 234 length:kOutputLengthBytes - sizeof(WebKit::WebUChar)];
226 235
227 base::mac::ScopedCFTypeRef<CFArrayRef> elements( 236 base::mac::ScopedCFTypeRef<CFArrayRef> elements(
228 IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone)); 237 IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone));
229 AddButtonsAndAxes(CFToNSCast(elements), slot); 238 AddButtonsAndAxes(CFToNSCast(elements), slot);
230 239
231 associated_[slot].device_ref = device; 240 associated_[slot].hid.device_ref = device;
232 data_.items[slot].connected = true; 241 data_.items[slot].connected = true;
233 if (slot >= data_.length) 242 if (slot >= data_.length)
234 data_.length = slot + 1; 243 data_.length = slot + 1;
235 } 244 }
236 245
237 void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) { 246 void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) {
238 using WebKit::WebGamepads;
239 size_t slot;
240 if (!enabled_) 247 if (!enabled_)
241 return; 248 return;
242 249
243 // Find the index for this device. 250 // Find the index for this device.
251 size_t slot;
244 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { 252 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
245 if (associated_[slot].device_ref == device && data_.items[slot].connected) 253 if (data_.items[slot].connected &&
254 !associated_[slot].is_xbox &&
255 associated_[slot].hid.device_ref == device)
246 break; 256 break;
247 } 257 }
248 DCHECK(slot < WebGamepads::itemsLengthCap); 258 DCHECK(slot < WebGamepads::itemsLengthCap);
249 // Leave associated device_ref so that it will be reconnected in the same 259 // Leave associated device_ref so that it will be reconnected in the same
250 // location. Simply mark it as disconnected. 260 // location. Simply mark it as disconnected.
251 data_.items[slot].connected = false; 261 data_.items[slot].connected = false;
252 } 262 }
253 263
254 void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) { 264 void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) {
255 if (!enabled_) 265 if (!enabled_)
256 return; 266 return;
257 267
258 IOHIDElementRef element = IOHIDValueGetElement(value); 268 IOHIDElementRef element = IOHIDValueGetElement(value);
259 IOHIDDeviceRef device = IOHIDElementGetDevice(element); 269 IOHIDDeviceRef device = IOHIDElementGetDevice(element);
260 270
261 // Find device slot. 271 // Find device slot.
262 size_t slot; 272 size_t slot;
263 for (slot = 0; slot < data_.length; ++slot) { 273 for (slot = 0; slot < data_.length; ++slot) {
264 if (data_.items[slot].connected && associated_[slot].device_ref == device) 274 if (data_.items[slot].connected &&
275 !associated_[slot].is_xbox &&
276 associated_[slot].hid.device_ref == device)
265 break; 277 break;
266 } 278 }
267 if (slot == data_.length) 279 if (slot == data_.length)
268 return; 280 return;
269 281
270 WebKit::WebGamepad& pad = data_.items[slot]; 282 WebGamepad& pad = data_.items[slot];
271 AssociatedData& associated = associated_[slot]; 283 AssociatedData& associated = associated_[slot];
272 284
273 // Find and fill in the associated button event, if any. 285 // Find and fill in the associated button event, if any.
274 for (size_t i = 0; i < pad.buttonsLength; ++i) { 286 for (size_t i = 0; i < pad.buttonsLength; ++i) {
275 if (associated.button_elements[i] == element) { 287 if (associated.hid.button_elements[i] == element) {
276 pad.buttons[i] = IOHIDValueGetIntegerValue(value) ? 1.f : 0.f; 288 pad.buttons[i] = IOHIDValueGetIntegerValue(value) ? 1.f : 0.f;
277 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); 289 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value));
278 return; 290 return;
279 } 291 }
280 } 292 }
281 293
282 // Find and fill in the associated axis event, if any. 294 // Find and fill in the associated axis event, if any.
283 for (size_t i = 0; i < pad.axesLength; ++i) { 295 for (size_t i = 0; i < pad.axesLength; ++i) {
284 if (associated.axis_elements[i] == element) { 296 if (associated.hid.axis_elements[i] == element) {
285 pad.axes[i] = NormalizeAxis(IOHIDValueGetIntegerValue(value), 297 pad.axes[i] = NormalizeAxis(IOHIDValueGetIntegerValue(value),
286 associated.axis_minimums[i], 298 associated.hid.axis_minimums[i],
287 associated.axis_maximums[i]); 299 associated.hid.axis_maximums[i]);
288 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); 300 pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value));
289 return; 301 return;
290 } 302 }
291 } 303 }
292 } 304 }
293 305
294 void GamepadPlatformDataFetcherMac::GetGamepadData( 306 void GamepadPlatformDataFetcherMac::XboxDeviceAdd(XboxController* device) {
295 WebKit::WebGamepads* pads, 307 if (!enabled_)
296 bool) { 308 return;
309
310 size_t slot;
311 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
312 if (associated_[slot].is_xbox &&
313 !data_.items[slot].connected &&
314 associated_[slot].xbox.location_id == device->location_id()) {
315 break;
316 }
317 }
318
319 if (slot == WebGamepads::itemsLengthCap) {
320 // Find an index for this device.
321 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
322 // If we already have this device, and it's already connected, don't do
323 // anything now.
324 if (associated_[slot].is_xbox &&
325 data_.items[slot].connected &&
326 associated_[slot].xbox.device == device)
327 return;
328 // XXX looks like there's a bug here? what if the first slot is empty,
Mark Mentovai 2013/04/24 16:57:20 What’s the story here?
jeremya 2013/04/26 03:47:40 I've refactored this code to hopefully remove the
329 // but the device is connected in slot 3? hm. also in DeviceAdd.
330 if (!data_.items[slot].connected)
331 break;
332 }
333 }
334
335 // We can't handle this many connected devices.
336 if (slot == WebGamepads::itemsLengthCap)
337 return;
338
339 device->SetLEDPattern(
340 (XboxController::LEDPattern)(XboxController::LED_FLASH_1 + slot));
341
342 NSString* ident =
343 [NSString stringWithFormat:
344 @"Xbox 360 Controller (STANDARD GAMEPAD Vendor: %04x Product: %04x)",
345 device->GetProductId(), device->GetVendorId()];
346 NSData* as16 = [ident dataUsingEncoding:NSUTF16StringEncoding];
347 const size_t kOutputLengthBytes = sizeof(data_.items[slot].id);
348 memset(&data_.items[slot].id, 0, kOutputLengthBytes);
349 [as16 getBytes:data_.items[slot].id
350 length:kOutputLengthBytes - sizeof(WebKit::WebUChar)];
351
352 associated_[slot].is_xbox = true;
353 associated_[slot].xbox.device = device;
354 associated_[slot].xbox.location_id = device->location_id();
355 data_.items[slot].connected = true;
356 data_.items[slot].axesLength = 4;
357 data_.items[slot].buttonsLength = 17;
358 data_.items[slot].timestamp = 0;
359 if (slot >= data_.length)
360 data_.length = slot + 1;
361 }
362
363 void GamepadPlatformDataFetcherMac::XboxDeviceRemove(XboxController* device) {
364 if (!enabled_)
365 return;
366
367 // Find the index for this device.
368 size_t slot;
369 for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
370 if (data_.items[slot].connected &&
371 associated_[slot].is_xbox &&
372 associated_[slot].xbox.device == device)
373 break;
374 }
375 DCHECK(slot < WebGamepads::itemsLengthCap);
376 // Leave associated device_ref so that it will be reconnected in the same
377 // location. Simply mark it as disconnected.
378 // TODO(jeremya): use location id to match replugged controllers.
379 data_.items[slot].connected = false;
380 }
381
382 void GamepadPlatformDataFetcherMac::XboxValueChanged(
383 XboxController* device, const XboxController::Data& data) {
384 // XXX should have xbox_enabled_ too.
Mark Mentovai 2013/04/24 16:57:20 And this?
jeremya 2013/04/26 03:47:40 enabled_ only gates the HID stuff -- that can fail
385 if (!enabled_)
386 return;
387
388 // Find device slot.
389 size_t slot;
390 for (slot = 0; slot < data_.length; ++slot) {
391 if (data_.items[slot].connected &&
392 associated_[slot].is_xbox &&
393 associated_[slot].xbox.device == device)
394 break;
395 }
396 if (slot == data_.length)
397 return;
398
399 WebGamepad& pad = data_.items[slot];
400
401 // Find and fill in the associated button event, if any.
402 for (size_t i = 0; i < arraysize(data.buttons); i++) {
403 pad.buttons[i] = data.buttons[i];
404 }
405 for (size_t i = 0; i < arraysize(data.axes); i++) {
406 pad.axes[i] = data.axes[i];
407 }
408 pad.timestamp = base::TimeTicks::Now().ToInternalValue();
409 }
410
411 void GamepadPlatformDataFetcherMac::GetGamepadData(WebGamepads* pads, bool) {
297 if (!enabled_) { 412 if (!enabled_) {
298 pads->length = 0; 413 pads->length = 0;
299 return; 414 return;
300 } 415 }
301 416
302 // Copy to the current state to the output buffer, using the mapping 417 // Copy to the current state to the output buffer, using the mapping
303 // function, if there is one available. 418 // function, if there is one available.
304 pads->length = WebKit::WebGamepads::itemsLengthCap; 419 pads->length = WebGamepads::itemsLengthCap;
305 for (size_t i = 0; i < WebKit::WebGamepads::itemsLengthCap; ++i) { 420 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
306 if (associated_[i].mapper) 421 if (!associated_[i].is_xbox && associated_[i].hid.mapper)
307 associated_[i].mapper(data_.items[i], &pads->items[i]); 422 associated_[i].hid.mapper(data_.items[i], &pads->items[i]);
308 else 423 else
309 pads->items[i] = data_.items[i]; 424 pads->items[i] = data_.items[i];
310 } 425 }
311 } 426 }
312 427
313 } // namespace content 428 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698