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

Side by Side Diff: content/browser/gamepad/xbox_data_fetcher_mac.cc

Issue 176003003: Added support for the Xbox One gamepad on OSX (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 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
« no previous file with comments | « content/browser/gamepad/xbox_data_fetcher_mac.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/xbox_data_fetcher_mac.h" 5 #include "content/browser/gamepad/xbox_data_fetcher_mac.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits> 9 #include <limits>
10 10
11 #include <CoreFoundation/CoreFoundation.h> 11 #include <CoreFoundation/CoreFoundation.h>
12 #include <IOKit/IOCFPlugIn.h> 12 #include <IOKit/IOCFPlugIn.h>
13 #include <IOKit/IOKitLib.h> 13 #include <IOKit/IOKitLib.h>
14 #include <IOKit/usb/IOUSBLib.h> 14 #include <IOKit/usb/IOUSBLib.h>
15 #include <IOKit/usb/USB.h> 15 #include <IOKit/usb/USB.h>
16 16
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/mac/foundation_util.h" 18 #include "base/mac/foundation_util.h"
19 19
20 namespace { 20 namespace {
21 const int kVendorMicrosoft = 0x045e; 21 const int kVendorMicrosoft = 0x045e;
22 const int kProduct360Controller = 0x028e; 22 const int kProductXbox360Controller = 0x028e;
23 const int kProductXboxOneController = 0x02d1;
23 24
24 const int kReadEndpoint = 1; 25 const int kXbox360ReadEndpoint = 1;
25 const int kControlEndpoint = 2; 26 const int kXbox360ControlEndpoint = 2;
27
28 const int kXboxOneReadEndpoint = 2;
29 const int kXboxOneControlEndpoint = 1;
26 30
27 enum { 31 enum {
28 STATUS_MESSAGE_BUTTONS = 0, 32 STATUS_MESSAGE_BUTTONS = 0,
29 STATUS_MESSAGE_LED = 1, 33 STATUS_MESSAGE_LED = 1,
30 34
31 // Apparently this message tells you if the rumble pack is disabled in the 35 // Apparently this message tells you if the rumble pack is disabled in the
32 // controller. If the rumble pack is disabled, vibration control messages 36 // controller. If the rumble pack is disabled, vibration control messages
33 // have no effect. 37 // have no effect.
34 STATUS_MESSAGE_RUMBLE = 3, 38 STATUS_MESSAGE_RUMBLE = 3,
35 }; 39 };
36 40
37 enum { 41 enum {
42 XBOX_ONE_STATUS_MESSAGE_BUTTONS = 0x20,
43 };
44
45 enum {
38 CONTROL_MESSAGE_SET_RUMBLE = 0, 46 CONTROL_MESSAGE_SET_RUMBLE = 0,
39 CONTROL_MESSAGE_SET_LED = 1, 47 CONTROL_MESSAGE_SET_LED = 1,
40 }; 48 };
41 49
42 #pragma pack(push, 1) 50 #pragma pack(push, 1)
43 struct ButtonData { 51 struct Xbox360ButtonData {
44 bool dpad_up : 1; 52 bool dpad_up : 1;
45 bool dpad_down : 1; 53 bool dpad_down : 1;
46 bool dpad_left : 1; 54 bool dpad_left : 1;
47 bool dpad_right : 1; 55 bool dpad_right : 1;
48 56
49 bool start : 1; 57 bool start : 1;
50 bool back : 1; 58 bool back : 1;
51 bool stick_left_click : 1; 59 bool stick_left_click : 1;
52 bool stick_right_click : 1; 60 bool stick_right_click : 1;
53 61
(...skipping 12 matching lines...) Expand all
66 74
67 int16 stick_left_x; 75 int16 stick_left_x;
68 int16 stick_left_y; 76 int16 stick_left_y;
69 int16 stick_right_x; 77 int16 stick_right_x;
70 int16 stick_right_y; 78 int16 stick_right_y;
71 79
72 // Always 0. 80 // Always 0.
73 uint32 dummy2; 81 uint32 dummy2;
74 uint16 dummy3; 82 uint16 dummy3;
75 }; 83 };
84
85 struct XboxOneButtonData {
86 bool sync : 1;
87 bool dummy1 : 1; // Always 0.
88 bool start : 1;
89 bool back : 1;
90
91 bool a : 1;
92 bool b : 1;
93 bool x : 1;
94 bool y : 1;
95
96 bool dpad_up : 1;
97 bool dpad_down : 1;
98 bool dpad_left : 1;
99 bool dpad_right : 1;
100
101 bool bumper_left : 1;
102 bool bumper_right : 1;
103 bool stick_left_click : 1;
104 bool stick_right_click : 1;
105
106 uint16 trigger_left;
107 uint16 trigger_right;
108
109 int16 stick_left_x;
110 int16 stick_left_y;
111 int16 stick_right_x;
112 int16 stick_right_y;
113 };
76 #pragma pack(pop) 114 #pragma pack(pop)
77 115
78 COMPILE_ASSERT(sizeof(ButtonData) == 0x12, xbox_button_data_wrong_size); 116 COMPILE_ASSERT(sizeof(Xbox360ButtonData) == 18, xbox_button_data_wrong_size);
117 COMPILE_ASSERT(sizeof(XboxOneButtonData) == 14, xbox_button_data_wrong_size);
79 118
80 // From MSDN: 119 // From MSDN:
81 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee417001(v=vs.85).asp x#dead_zone 120 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee417001(v=vs.85).asp x#dead_zone
82 const int16 kLeftThumbDeadzone = 7849; 121 const int16 kLeftThumbDeadzone = 7849;
83 const int16 kRightThumbDeadzone = 8689; 122 const int16 kRightThumbDeadzone = 8689;
84 const uint8 kTriggerDeadzone = 30; 123 const uint8 kXbox360TriggerDeadzone = 30;
124 const uint16 kXboxOneTriggerMax = 1023;
125 const uint16 kXboxOneTriggerDeadzone = 120;
85 126
86 void NormalizeAxis(int16 x, 127 void NormalizeAxis(int16 x,
87 int16 y, 128 int16 y,
88 int16 deadzone, 129 int16 deadzone,
89 float* x_out, 130 float* x_out,
90 float* y_out) { 131 float* y_out) {
91 float x_val = x; 132 float x_val = x;
92 float y_val = y; 133 float y_val = y;
93 134
94 // Determine how far the stick is pushed. 135 // Determine how far the stick is pushed.
(...skipping 15 matching lines...) Expand all
110 // the 'standard controller' recommendations. 151 // the 'standard controller' recommendations.
111 *x_out = x_val * ratio; 152 *x_out = x_val * ratio;
112 *y_out = -y_val * ratio; 153 *y_out = -y_val * ratio;
113 } else { 154 } else {
114 // If the controller is in the deadzone zero out the magnitude. 155 // If the controller is in the deadzone zero out the magnitude.
115 *x_out = *y_out = 0.0f; 156 *x_out = *y_out = 0.0f;
116 } 157 }
117 } 158 }
118 159
119 float NormalizeTrigger(uint8 value) { 160 float NormalizeTrigger(uint8 value) {
120 return value < kTriggerDeadzone ? 0 : 161 return value < kXbox360TriggerDeadzone ? 0 :
121 static_cast<float>(value - kTriggerDeadzone) / 162 static_cast<float>(value - kXbox360TriggerDeadzone) /
122 (std::numeric_limits<uint8>::max() - kTriggerDeadzone); 163 (std::numeric_limits<uint8>::max() - kXbox360TriggerDeadzone);
123 } 164 }
124 165
125 void NormalizeButtonData(const ButtonData& data, 166 float NormalizeXboxOneTrigger(uint16 value) {
167 return value < kXboxOneTriggerDeadzone ? 0 :
168 static_cast<float>(value - kXboxOneTriggerDeadzone) /
169 (kXboxOneTriggerMax - kXboxOneTriggerDeadzone);
170 }
171
172 void NormalizeXbox360ButtonData(const Xbox360ButtonData& data,
126 XboxController::Data* normalized_data) { 173 XboxController::Data* normalized_data) {
scottmg 2014/02/24 17:37:22 nit; indent
127 normalized_data->buttons[0] = data.a; 174 normalized_data->buttons[0] = data.a;
128 normalized_data->buttons[1] = data.b; 175 normalized_data->buttons[1] = data.b;
129 normalized_data->buttons[2] = data.x; 176 normalized_data->buttons[2] = data.x;
130 normalized_data->buttons[3] = data.y; 177 normalized_data->buttons[3] = data.y;
131 normalized_data->buttons[4] = data.bumper_left; 178 normalized_data->buttons[4] = data.bumper_left;
132 normalized_data->buttons[5] = data.bumper_right; 179 normalized_data->buttons[5] = data.bumper_right;
133 normalized_data->buttons[6] = data.back; 180 normalized_data->buttons[6] = data.back;
134 normalized_data->buttons[7] = data.start; 181 normalized_data->buttons[7] = data.start;
135 normalized_data->buttons[8] = data.stick_left_click; 182 normalized_data->buttons[8] = data.stick_left_click;
136 normalized_data->buttons[9] = data.stick_right_click; 183 normalized_data->buttons[9] = data.stick_right_click;
137 normalized_data->buttons[10] = data.dpad_up; 184 normalized_data->buttons[10] = data.dpad_up;
138 normalized_data->buttons[11] = data.dpad_down; 185 normalized_data->buttons[11] = data.dpad_down;
139 normalized_data->buttons[12] = data.dpad_left; 186 normalized_data->buttons[12] = data.dpad_left;
140 normalized_data->buttons[13] = data.dpad_right; 187 normalized_data->buttons[13] = data.dpad_right;
141 normalized_data->buttons[14] = data.guide; 188 normalized_data->buttons[14] = data.guide;
142 normalized_data->triggers[0] = NormalizeTrigger(data.trigger_left); 189 normalized_data->triggers[0] = NormalizeTrigger(data.trigger_left);
143 normalized_data->triggers[1] = NormalizeTrigger(data.trigger_right); 190 normalized_data->triggers[1] = NormalizeTrigger(data.trigger_right);
144 NormalizeAxis(data.stick_left_x, 191 NormalizeAxis(data.stick_left_x,
145 data.stick_left_y, 192 data.stick_left_y,
146 kLeftThumbDeadzone, 193 kLeftThumbDeadzone,
147 &normalized_data->axes[0], 194 &normalized_data->axes[0],
148 &normalized_data->axes[1]); 195 &normalized_data->axes[1]);
149 NormalizeAxis(data.stick_right_x, 196 NormalizeAxis(data.stick_right_x,
150 data.stick_right_y, 197 data.stick_right_y,
151 kRightThumbDeadzone, 198 kRightThumbDeadzone,
152 &normalized_data->axes[2], 199 &normalized_data->axes[2],
153 &normalized_data->axes[3]); 200 &normalized_data->axes[3]);
154 } 201 }
155 202
203 void NormalizeXboxOneButtonData(const XboxOneButtonData& data,
204 XboxController::Data* normalized_data) {
scottmg 2014/02/24 17:37:22 nit; indent
205 normalized_data->buttons[0] = data.a;
206 normalized_data->buttons[1] = data.b;
207 normalized_data->buttons[2] = data.x;
208 normalized_data->buttons[3] = data.y;
209 normalized_data->buttons[4] = data.bumper_left;
210 normalized_data->buttons[5] = data.bumper_right;
211 normalized_data->buttons[6] = data.back;
212 normalized_data->buttons[7] = data.start;
213 normalized_data->buttons[8] = data.stick_left_click;
214 normalized_data->buttons[9] = data.stick_right_click;
215 normalized_data->buttons[10] = data.dpad_up;
216 normalized_data->buttons[11] = data.dpad_down;
217 normalized_data->buttons[12] = data.dpad_left;
218 normalized_data->buttons[13] = data.dpad_right;
219 normalized_data->buttons[14] = data.sync;
220 normalized_data->triggers[0] = NormalizeXboxOneTrigger(data.trigger_left);
221 normalized_data->triggers[1] = NormalizeXboxOneTrigger(data.trigger_right);
222 NormalizeAxis(data.stick_left_x,
223 data.stick_left_y,
224 kLeftThumbDeadzone,
225 &normalized_data->axes[0],
226 &normalized_data->axes[1]);
227 NormalizeAxis(data.stick_right_x,
228 data.stick_right_y,
229 kRightThumbDeadzone,
230 &normalized_data->axes[2],
231 &normalized_data->axes[3]);
232 }
233
156 } // namespace 234 } // namespace
157 235
158 XboxController::XboxController(Delegate* delegate) 236 XboxController::XboxController(Delegate* delegate)
159 : device_(NULL), 237 : device_(NULL),
160 interface_(NULL), 238 interface_(NULL),
161 device_is_open_(false), 239 device_is_open_(false),
162 interface_is_open_(false), 240 interface_is_open_(false),
163 read_buffer_size_(0), 241 read_buffer_size_(0),
164 led_pattern_(LED_NUM_PATTERNS), 242 led_pattern_(LED_NUM_PATTERNS),
165 location_id_(0), 243 location_id_(0),
166 delegate_(delegate) { 244 delegate_(delegate),
245 controller_type_(UNKNOWN_CONTROLLER),
246 read_endpoint_(0),
247 control_endpoint_(0) {
167 } 248 }
168 249
169 XboxController::~XboxController() { 250 XboxController::~XboxController() {
170 if (source_) 251 if (source_)
171 CFRunLoopSourceInvalidate(source_); 252 CFRunLoopSourceInvalidate(source_);
172 if (interface_ && interface_is_open_) 253 if (interface_ && interface_is_open_)
173 (*interface_)->USBInterfaceClose(interface_); 254 (*interface_)->USBInterfaceClose(interface_);
174 if (device_ && device_is_open_) 255 if (device_ && device_is_open_)
175 (*device_)->USBDeviceClose(device_); 256 (*device_)->USBDeviceClose(device_);
176 } 257 }
(...skipping 13 matching lines...) Expand all
190 271
191 HRESULT res = 272 HRESULT res =
192 (*plugin)->QueryInterface(plugin, 273 (*plugin)->QueryInterface(plugin,
193 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID320), 274 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID320),
194 (LPVOID *)&device_); 275 (LPVOID *)&device_);
195 if (!SUCCEEDED(res) || !device_) 276 if (!SUCCEEDED(res) || !device_)
196 return false; 277 return false;
197 278
198 UInt16 vendor_id; 279 UInt16 vendor_id;
199 kr = (*device_)->GetDeviceVendor(device_, &vendor_id); 280 kr = (*device_)->GetDeviceVendor(device_, &vendor_id);
200 if (kr != KERN_SUCCESS) 281 if (kr != KERN_SUCCESS || vendor_id != kVendorMicrosoft)
201 return false; 282 return false;
283
202 UInt16 product_id; 284 UInt16 product_id;
203 kr = (*device_)->GetDeviceProduct(device_, &product_id); 285 kr = (*device_)->GetDeviceProduct(device_, &product_id);
204 if (kr != KERN_SUCCESS) 286 if (kr != KERN_SUCCESS)
205 return false; 287 return false;
206 if (vendor_id != kVendorMicrosoft || product_id != kProduct360Controller) 288
207 return false; 289 IOUSBFindInterfaceRequest request;
290 switch (product_id) {
291 case kProductXbox360Controller:
292 controller_type_ = XBOX_360_CONTROLLER;
293 read_endpoint_ = kXbox360ReadEndpoint;
294 control_endpoint_ = kXbox360ControlEndpoint;
295 request.bInterfaceClass = 255;
296 request.bInterfaceSubClass = 93;
297 request.bInterfaceProtocol = 1;
298 request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
299 break;
300 case kProductXboxOneController:
301 controller_type_ = XBOX_ONE_CONTROLLER;
302 read_endpoint_ = kXboxOneReadEndpoint;
303 control_endpoint_ = kXboxOneControlEndpoint;
304 request.bInterfaceClass = 255;
305 request.bInterfaceSubClass = 71;
306 request.bInterfaceProtocol = 208;
307 request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
308 break;
309 default:
310 return false;
311 }
208 312
209 // Open the device and configure it. 313 // Open the device and configure it.
210 kr = (*device_)->USBDeviceOpen(device_); 314 kr = (*device_)->USBDeviceOpen(device_);
211 if (kr != KERN_SUCCESS) 315 if (kr != KERN_SUCCESS)
212 return false; 316 return false;
213 device_is_open_ = true; 317 device_is_open_ = true;
214 318
215 // Xbox controllers have one configuration option which has configuration 319 // Xbox controllers have one configuration option which has configuration
216 // value 1. Try to set it and fail if it couldn't be configured. 320 // value 1. Try to set it and fail if it couldn't be configured.
217 IOUSBConfigurationDescriptorPtr config_desc; 321 IOUSBConfigurationDescriptorPtr config_desc;
(...skipping 11 matching lines...) Expand all
229 // Protocol 2 has a single endpoint to read from a connected ChatPad device. 333 // Protocol 2 has a single endpoint to read from a connected ChatPad device.
230 // Protocol 3 is used by a connected headset device. 334 // Protocol 3 is used by a connected headset device.
231 // The device also has an interface on subclass 253, protocol 10 with no 335 // The device also has an interface on subclass 253, protocol 10 with no
232 // endpoints. It is unused. 336 // endpoints. It is unused.
233 // 337 //
234 // We don't currently support the ChatPad or headset, so protocol 1 is the 338 // We don't currently support the ChatPad or headset, so protocol 1 is the
235 // only protocol we care about. 339 // only protocol we care about.
236 // 340 //
237 // For more detail, see 341 // For more detail, see
238 // https://github.com/Grumbel/xboxdrv/blob/master/PROTOCOL 342 // https://github.com/Grumbel/xboxdrv/blob/master/PROTOCOL
239 IOUSBFindInterfaceRequest request;
240 request.bInterfaceClass = 255;
241 request.bInterfaceSubClass = 93;
242 request.bInterfaceProtocol = 1;
243 request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
244 io_iterator_t iter; 343 io_iterator_t iter;
245 kr = (*device_)->CreateInterfaceIterator(device_, &request, &iter); 344 kr = (*device_)->CreateInterfaceIterator(device_, &request, &iter);
246 if (kr != KERN_SUCCESS) 345 if (kr != KERN_SUCCESS)
247 return false; 346 return false;
248 base::mac::ScopedIOObject<io_iterator_t> iter_ref(iter); 347 base::mac::ScopedIOObject<io_iterator_t> iter_ref(iter);
249 348
250 // There should be exactly one USB interface which matches the requested 349 // There should be exactly one USB interface which matches the requested
251 // settings. 350 // settings.
252 io_service_t usb_interface = IOIteratorNext(iter); 351 io_service_t usb_interface = IOIteratorNext(iter);
253 if (!usb_interface) 352 if (!usb_interface)
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 uint16 max_packet_size; 410 uint16 max_packet_size;
312 uint8 interval; 411 uint8 interval;
313 412
314 kr = (*interface_)->GetPipeProperties(interface_, 413 kr = (*interface_)->GetPipeProperties(interface_,
315 i, 414 i,
316 &direction, 415 &direction,
317 &number, 416 &number,
318 &transfer_type, 417 &transfer_type,
319 &max_packet_size, 418 &max_packet_size,
320 &interval); 419 &interval);
321 if (kr != KERN_SUCCESS || transfer_type != kUSBInterrupt) 420 if (kr != KERN_SUCCESS || transfer_type != kUSBInterrupt) {
322 return false; 421 return false;
323 if (i == kReadEndpoint) { 422 }
423 if (i == read_endpoint_) {
324 if (direction != kUSBIn) 424 if (direction != kUSBIn)
325 return false; 425 return false;
326 if (max_packet_size > 32)
327 return false;
328 read_buffer_.reset(new uint8[max_packet_size]); 426 read_buffer_.reset(new uint8[max_packet_size]);
329 read_buffer_size_ = max_packet_size; 427 read_buffer_size_ = max_packet_size;
330 QueueRead(); 428 QueueRead();
331 } else if (i == kControlEndpoint) { 429 } else if (i == control_endpoint_) {
332 if (direction != kUSBOut) 430 if (direction != kUSBOut)
333 return false; 431 return false;
432 if (controller_type_ == XBOX_ONE_CONTROLLER)
433 WriteXboxOneInit();
334 } 434 }
335 } 435 }
336 436
337 // The location ID is unique per controller, and can be used to track 437 // The location ID is unique per controller, and can be used to track
338 // controllers through reconnections (though if a controller is detached from 438 // controllers through reconnections (though if a controller is detached from
339 // one USB hub and attached to another, the location ID will change). 439 // one USB hub and attached to another, the location ID will change).
340 kr = (*device_)->GetLocationID(device_, &location_id_); 440 kr = (*device_)->GetLocationID(device_, &location_id_);
341 if (kr != KERN_SUCCESS) 441 if (kr != KERN_SUCCESS)
342 return false; 442 return false;
343 443
344 return true; 444 return true;
345 } 445 }
346 446
347 void XboxController::SetLEDPattern(LEDPattern pattern) { 447 void XboxController::SetLEDPattern(LEDPattern pattern) {
348 led_pattern_ = pattern; 448 led_pattern_ = pattern;
349 const UInt8 length = 3; 449 const UInt8 length = 3;
350 450
351 // This buffer will be released in WriteComplete when WritePipeAsync 451 // This buffer will be released in WriteComplete when WritePipeAsync
352 // finishes. 452 // finishes.
353 UInt8* buffer = new UInt8[length]; 453 UInt8* buffer = new UInt8[length];
354 buffer[0] = static_cast<UInt8>(CONTROL_MESSAGE_SET_LED); 454 buffer[0] = static_cast<UInt8>(CONTROL_MESSAGE_SET_LED);
355 buffer[1] = length; 455 buffer[1] = length;
356 buffer[2] = static_cast<UInt8>(pattern); 456 buffer[2] = static_cast<UInt8>(pattern);
357 kern_return_t kr = (*interface_)->WritePipeAsync(interface_, 457 kern_return_t kr = (*interface_)->WritePipeAsync(interface_,
358 kControlEndpoint, 458 control_endpoint_,
359 buffer, 459 buffer,
360 (UInt32)length, 460 (UInt32)length,
361 WriteComplete, 461 WriteComplete,
362 buffer); 462 buffer);
363 if (kr != KERN_SUCCESS) { 463 if (kr != KERN_SUCCESS) {
364 delete[] buffer; 464 delete[] buffer;
365 IOError(); 465 IOError();
366 return; 466 return;
367 } 467 }
368 } 468 }
369 469
370 int XboxController::GetVendorId() const { 470 int XboxController::GetVendorId() const {
371 return kVendorMicrosoft; 471 return kVendorMicrosoft;
372 } 472 }
373 473
374 int XboxController::GetProductId() const { 474 int XboxController::GetProductId() const {
375 return kProduct360Controller; 475 if (controller_type_ == XBOX_360_CONTROLLER)
476 return kProductXbox360Controller;
477 else
478 return kProductXboxOneController;
479 }
480
481 XboxController::ControllerType XboxController::GetControllerType() const {
482 return controller_type_;
376 } 483 }
377 484
378 void XboxController::WriteComplete(void* context, IOReturn result, void* arg0) { 485 void XboxController::WriteComplete(void* context, IOReturn result, void* arg0) {
379 UInt8* buffer = static_cast<UInt8*>(context); 486 UInt8* buffer = static_cast<UInt8*>(context);
380 delete[] buffer; 487 delete[] buffer;
381 488
382 // Ignoring any errors sending data, because they will usually only occur 489 // Ignoring any errors sending data, because they will usually only occur
383 // when the device is disconnected, in which case it really doesn't matter if 490 // when the device is disconnected, in which case it really doesn't matter if
384 // the data got to the controller or not. 491 // the data got to the controller or not.
385 if (result != kIOReturnSuccess) 492 if (result != kIOReturnSuccess)
386 return; 493 return;
387 } 494 }
388 495
389 void XboxController::GotData(void* context, IOReturn result, void* arg0) { 496 void XboxController::GotData(void* context, IOReturn result, void* arg0) {
390 size_t bytes_read = reinterpret_cast<size_t>(arg0); 497 size_t bytes_read = reinterpret_cast<size_t>(arg0);
391 XboxController* controller = static_cast<XboxController*>(context); 498 XboxController* controller = static_cast<XboxController*>(context);
392 499
393 if (result != kIOReturnSuccess) { 500 if (result != kIOReturnSuccess) {
394 // This will happen if the device was disconnected. The gamepad has 501 // This will happen if the device was disconnected. The gamepad has
395 // probably been destroyed by a meteorite. 502 // probably been destroyed by a meteorite.
396 controller->IOError(); 503 controller->IOError();
397 return; 504 return;
398 } 505 }
399 506
400 controller->ProcessPacket(bytes_read); 507 if (controller->GetControllerType() == XBOX_360_CONTROLLER)
508 controller->ProcessXbox360Packet(bytes_read);
509 else
510 controller->ProcessXboxOnePacket(bytes_read);
401 511
402 // Queue up another read. 512 // Queue up another read.
403 controller->QueueRead(); 513 controller->QueueRead();
404 } 514 }
405 515
406 void XboxController::ProcessPacket(size_t length) { 516 void XboxController::ProcessXbox360Packet(size_t length) {
407 if (length < 2) return; 517 if (length < 2) return;
408 DCHECK(length <= read_buffer_size_); 518 DCHECK(length <= read_buffer_size_);
409 if (length > read_buffer_size_) { 519 if (length > read_buffer_size_) {
410 IOError(); 520 IOError();
411 return; 521 return;
412 } 522 }
413 uint8* buffer = read_buffer_.get(); 523 uint8* buffer = read_buffer_.get();
414 524
415 if (buffer[1] != length) 525 if (buffer[1] != length)
416 // Length in packet doesn't match length reported by USB. 526 // Length in packet doesn't match length reported by USB.
417 return; 527 return;
418 528
419 uint8 type = buffer[0]; 529 uint8 type = buffer[0];
420 buffer += 2; 530 buffer += 2;
421 length -= 2; 531 length -= 2;
422 switch (type) { 532 switch (type) {
423 case STATUS_MESSAGE_BUTTONS: { 533 case STATUS_MESSAGE_BUTTONS: {
424 if (length != sizeof(ButtonData)) 534 if (length != sizeof(Xbox360ButtonData))
425 return; 535 return;
426 ButtonData* data = reinterpret_cast<ButtonData*>(buffer); 536 Xbox360ButtonData* data = reinterpret_cast<Xbox360ButtonData*>(buffer);
427 Data normalized_data; 537 Data normalized_data;
428 NormalizeButtonData(*data, &normalized_data); 538 NormalizeXbox360ButtonData(*data, &normalized_data);
429 delegate_->XboxControllerGotData(this, normalized_data); 539 delegate_->XboxControllerGotData(this, normalized_data);
430 break; 540 break;
431 } 541 }
432 case STATUS_MESSAGE_LED: 542 case STATUS_MESSAGE_LED:
433 if (length != 3) 543 if (length != 3)
434 return; 544 return;
435 // The controller sends one of these messages every time the LED pattern 545 // The controller sends one of these messages every time the LED pattern
436 // is set, as well as once when it is plugged in. 546 // is set, as well as once when it is plugged in.
437 if (led_pattern_ == LED_NUM_PATTERNS && buffer[0] < LED_NUM_PATTERNS) 547 if (led_pattern_ == LED_NUM_PATTERNS && buffer[0] < LED_NUM_PATTERNS)
438 led_pattern_ = static_cast<LEDPattern>(buffer[0]); 548 led_pattern_ = static_cast<LEDPattern>(buffer[0]);
439 break; 549 break;
440 default: 550 default:
441 // Unknown packet: ignore! 551 // Unknown packet: ignore!
442 break; 552 break;
443 } 553 }
444 } 554 }
445 555
556 void XboxController::ProcessXboxOnePacket(size_t length) {
557 if (length < 2) return;
scottmg 2014/02/24 17:37:22 nit; return on next line
558 DCHECK(length <= read_buffer_size_);
559 if (length > read_buffer_size_) {
560 IOError();
561 return;
562 }
563 uint8* buffer = read_buffer_.get();
564
565 uint8 type = buffer[0];
566 buffer += 4;
567 length -= 4;
568 switch (type) {
569 case XBOX_ONE_STATUS_MESSAGE_BUTTONS: {
570 if (length != sizeof(XboxOneButtonData))
571 return;
scottmg 2014/02/24 17:37:22 does this return ever get hit? does it send partia
572 XboxOneButtonData* data = reinterpret_cast<XboxOneButtonData*>(buffer);
573 Data normalized_data;
574 NormalizeXboxOneButtonData(*data, &normalized_data);
575 delegate_->XboxControllerGotData(this, normalized_data);
576 break;
577 }
578 default:
579 // Unknown packet: ignore!
580 break;
581 }
582 }
583
446 void XboxController::QueueRead() { 584 void XboxController::QueueRead() {
447 kern_return_t kr = (*interface_)->ReadPipeAsync(interface_, 585 kern_return_t kr = (*interface_)->ReadPipeAsync(interface_,
448 kReadEndpoint, 586 read_endpoint_,
449 read_buffer_.get(), 587 read_buffer_.get(),
450 read_buffer_size_, 588 read_buffer_size_,
451 GotData, 589 GotData,
452 this); 590 this);
453 if (kr != KERN_SUCCESS) 591 if (kr != KERN_SUCCESS)
454 IOError(); 592 IOError();
455 } 593 }
456 594
457 void XboxController::IOError() { 595 void XboxController::IOError() {
458 delegate_->XboxControllerError(this); 596 delegate_->XboxControllerError(this);
459 } 597 }
460 598
599 void XboxController::WriteXboxOneInit() {
600 const UInt8 length = 2;
601
602 // This buffer will be released in WriteComplete when WritePipeAsync
603 // finishes.
604 UInt8* buffer = new UInt8[length];
605 buffer[0] = 0x05;
606 buffer[1] = 0x20;
607 kern_return_t kr = (*interface_)->WritePipeAsync(interface_,
608 control_endpoint_,
609 buffer,
610 (UInt32)length,
611 WriteComplete,
612 buffer);
613 if (kr != KERN_SUCCESS) {
614 delete[] buffer;
615 IOError();
616 return;
617 }
618 }
619
461 //----------------------------------------------------------------------------- 620 //-----------------------------------------------------------------------------
462 621
463 XboxDataFetcher::XboxDataFetcher(Delegate* delegate) 622 XboxDataFetcher::XboxDataFetcher(Delegate* delegate)
464 : delegate_(delegate), 623 : delegate_(delegate),
465 listening_(false), 624 listening_(false),
466 source_(NULL), 625 source_(NULL),
467 port_(NULL) { 626 port_(NULL) {
468 } 627 }
469 628
470 XboxDataFetcher::~XboxDataFetcher() { 629 XboxDataFetcher::~XboxDataFetcher() {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 kNilOptions))); 662 kNilOptions)));
504 UInt32 location_id = 0; 663 UInt32 location_id = 0;
505 CFNumberGetValue(number, kCFNumberSInt32Type, &location_id); 664 CFNumberGetValue(number, kCFNumberSInt32Type, &location_id);
506 fetcher->RemoveControllerByLocationID(location_id); 665 fetcher->RemoveControllerByLocationID(location_id);
507 } 666 }
508 } 667 }
509 668
510 bool XboxDataFetcher::RegisterForNotifications() { 669 bool XboxDataFetcher::RegisterForNotifications() {
511 if (listening_) 670 if (listening_)
512 return true; 671 return true;
513 base::ScopedCFTypeRef<CFNumberRef> vendor_cf(CFNumberCreate(
514 kCFAllocatorDefault, kCFNumberSInt32Type, &kVendorMicrosoft));
515 base::ScopedCFTypeRef<CFNumberRef> product_cf(CFNumberCreate(
516 kCFAllocatorDefault, kCFNumberSInt32Type, &kProduct360Controller));
517 base::ScopedCFTypeRef<CFMutableDictionaryRef> matching_dict(
518 IOServiceMatching(kIOUSBDeviceClassName));
519 if (!matching_dict)
520 return false;
521 CFDictionarySetValue(matching_dict, CFSTR(kUSBVendorID), vendor_cf);
522 CFDictionarySetValue(matching_dict, CFSTR(kUSBProductID), product_cf);
523 port_ = IONotificationPortCreate(kIOMasterPortDefault); 672 port_ = IONotificationPortCreate(kIOMasterPortDefault);
524 if (!port_) 673 if (!port_)
525 return false; 674 return false;
526 source_ = IONotificationPortGetRunLoopSource(port_); 675 source_ = IONotificationPortGetRunLoopSource(port_);
527 if (!source_) 676 if (!source_)
528 return false; 677 return false;
529 CFRunLoopAddSource(CFRunLoopGetCurrent(), source_, kCFRunLoopDefaultMode); 678 CFRunLoopAddSource(CFRunLoopGetCurrent(), source_, kCFRunLoopDefaultMode);
530 679
531 listening_ = true; 680 listening_ = true;
532 681
682 if (!RegisterForDeviceNotifications(
683 kVendorMicrosoft, kProductXboxOneController,
684 &xbox_one_device_added_iter_,
685 &xbox_one_device_removed_iter_))
686 return false;
687
688 if (!RegisterForDeviceNotifications(
689 kVendorMicrosoft, kProductXbox360Controller,
690 &xbox_360_device_added_iter_,
691 &xbox_360_device_removed_iter_))
692 return false;
693
694 return true;
695 }
696
697 bool XboxDataFetcher::RegisterForDeviceNotifications(
698 int vendor_id,
699 int product_id,
700 base::mac::ScopedIOObject<io_iterator_t>* added_iter,
701 base::mac::ScopedIOObject<io_iterator_t>* removed_iter) {
702 base::ScopedCFTypeRef<CFNumberRef> vendor_cf(CFNumberCreate(
703 kCFAllocatorDefault, kCFNumberSInt32Type, &vendor_id));
704 base::ScopedCFTypeRef<CFNumberRef> product_cf(CFNumberCreate(
705 kCFAllocatorDefault, kCFNumberSInt32Type, &product_id));
706 base::ScopedCFTypeRef<CFMutableDictionaryRef> matching_dict(
707 IOServiceMatching(kIOUSBDeviceClassName));
708 if (!matching_dict)
709 return false;
710 CFDictionarySetValue(matching_dict, CFSTR(kUSBVendorID), vendor_cf);
711 CFDictionarySetValue(matching_dict, CFSTR(kUSBProductID), product_cf);
712
533 // IOServiceAddMatchingNotification() releases the dictionary when it's done. 713 // IOServiceAddMatchingNotification() releases the dictionary when it's done.
534 // Retain it before each call to IOServiceAddMatchingNotification to keep 714 // Retain it before each call to IOServiceAddMatchingNotification to keep
535 // things balanced. 715 // things balanced.
536 CFRetain(matching_dict); 716 CFRetain(matching_dict);
537 io_iterator_t device_added_iter; 717 io_iterator_t device_added_iter;
538 IOReturn ret; 718 IOReturn ret;
539 ret = IOServiceAddMatchingNotification(port_, 719 ret = IOServiceAddMatchingNotification(port_,
540 kIOFirstMatchNotification, 720 kIOFirstMatchNotification,
541 matching_dict, 721 matching_dict,
542 DeviceAdded, 722 DeviceAdded,
543 this, 723 this,
544 &device_added_iter); 724 &device_added_iter);
545 device_added_iter_.reset(device_added_iter); 725 added_iter->reset(device_added_iter);
546 if (ret != kIOReturnSuccess) { 726 if (ret != kIOReturnSuccess) {
547 LOG(ERROR) << "Error listening for Xbox controller add events: " << ret; 727 LOG(ERROR) << "Error listening for Xbox controller add events: " << ret;
548 return false; 728 return false;
549 } 729 }
550 DeviceAdded(this, device_added_iter_.get()); 730 DeviceAdded(this, added_iter->get());
551 731
552 CFRetain(matching_dict); 732 CFRetain(matching_dict);
553 io_iterator_t device_removed_iter; 733 io_iterator_t device_removed_iter;
554 ret = IOServiceAddMatchingNotification(port_, 734 ret = IOServiceAddMatchingNotification(port_,
555 kIOTerminatedNotification, 735 kIOTerminatedNotification,
556 matching_dict, 736 matching_dict,
557 DeviceRemoved, 737 DeviceRemoved,
558 this, 738 this,
559 &device_removed_iter); 739 &device_removed_iter);
560 device_removed_iter_.reset(device_removed_iter); 740 removed_iter->reset(device_removed_iter);
561 if (ret != kIOReturnSuccess) { 741 if (ret != kIOReturnSuccess) {
562 LOG(ERROR) << "Error listening for Xbox controller remove events: " << ret; 742 LOG(ERROR) << "Error listening for Xbox controller remove events: " << ret;
563 return false; 743 return false;
564 } 744 }
565 DeviceRemoved(this, device_removed_iter_.get()); 745 DeviceRemoved(this, removed_iter->get());
566 return true; 746 return true;
567 } 747 }
568 748
569 void XboxDataFetcher::UnregisterFromNotifications() { 749 void XboxDataFetcher::UnregisterFromNotifications() {
570 if (!listening_) 750 if (!listening_)
571 return; 751 return;
572 listening_ = false; 752 listening_ = false;
573 if (source_) 753 if (source_)
574 CFRunLoopSourceInvalidate(source_); 754 CFRunLoopSourceInvalidate(source_);
575 if (port_) 755 if (port_)
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 } 796 }
617 797
618 void XboxDataFetcher::XboxControllerGotData(XboxController* controller, 798 void XboxDataFetcher::XboxControllerGotData(XboxController* controller,
619 const XboxController::Data& data) { 799 const XboxController::Data& data) {
620 delegate_->XboxValueChanged(controller, data); 800 delegate_->XboxValueChanged(controller, data);
621 } 801 }
622 802
623 void XboxDataFetcher::XboxControllerError(XboxController* controller) { 803 void XboxDataFetcher::XboxControllerError(XboxController* controller) {
624 RemoveController(controller); 804 RemoveController(controller);
625 } 805 }
OLDNEW
« no previous file with comments | « content/browser/gamepad/xbox_data_fetcher_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698