OLD | NEW |
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 Loading... |
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 Loading... |
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) { |
126 XboxController::Data* normalized_data) { | 167 return value < kXboxOneTriggerDeadzone ? 0 : |
| 168 static_cast<float>(value - kXboxOneTriggerDeadzone) / |
| 169 (kXboxOneTriggerMax - kXboxOneTriggerDeadzone); |
| 170 } |
| 171 |
| 172 void NormalizeXbox360ButtonData(const Xbox360ButtonData& data, |
| 173 XboxController::Data* normalized_data) { |
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) { |
| 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 Loading... |
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 Loading... |
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 Loading... |
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) |
| 518 return; |
408 DCHECK(length <= read_buffer_size_); | 519 DCHECK(length <= read_buffer_size_); |
409 if (length > read_buffer_size_) { | 520 if (length > read_buffer_size_) { |
410 IOError(); | 521 IOError(); |
411 return; | 522 return; |
412 } | 523 } |
413 uint8* buffer = read_buffer_.get(); | 524 uint8* buffer = read_buffer_.get(); |
414 | 525 |
415 if (buffer[1] != length) | 526 if (buffer[1] != length) |
416 // Length in packet doesn't match length reported by USB. | 527 // Length in packet doesn't match length reported by USB. |
417 return; | 528 return; |
418 | 529 |
419 uint8 type = buffer[0]; | 530 uint8 type = buffer[0]; |
420 buffer += 2; | 531 buffer += 2; |
421 length -= 2; | 532 length -= 2; |
422 switch (type) { | 533 switch (type) { |
423 case STATUS_MESSAGE_BUTTONS: { | 534 case STATUS_MESSAGE_BUTTONS: { |
424 if (length != sizeof(ButtonData)) | 535 if (length != sizeof(Xbox360ButtonData)) |
425 return; | 536 return; |
426 ButtonData* data = reinterpret_cast<ButtonData*>(buffer); | 537 Xbox360ButtonData* data = reinterpret_cast<Xbox360ButtonData*>(buffer); |
427 Data normalized_data; | 538 Data normalized_data; |
428 NormalizeButtonData(*data, &normalized_data); | 539 NormalizeXbox360ButtonData(*data, &normalized_data); |
429 delegate_->XboxControllerGotData(this, normalized_data); | 540 delegate_->XboxControllerGotData(this, normalized_data); |
430 break; | 541 break; |
431 } | 542 } |
432 case STATUS_MESSAGE_LED: | 543 case STATUS_MESSAGE_LED: |
433 if (length != 3) | 544 if (length != 3) |
434 return; | 545 return; |
435 // The controller sends one of these messages every time the LED pattern | 546 // The controller sends one of these messages every time the LED pattern |
436 // is set, as well as once when it is plugged in. | 547 // is set, as well as once when it is plugged in. |
437 if (led_pattern_ == LED_NUM_PATTERNS && buffer[0] < LED_NUM_PATTERNS) | 548 if (led_pattern_ == LED_NUM_PATTERNS && buffer[0] < LED_NUM_PATTERNS) |
438 led_pattern_ = static_cast<LEDPattern>(buffer[0]); | 549 led_pattern_ = static_cast<LEDPattern>(buffer[0]); |
439 break; | 550 break; |
440 default: | 551 default: |
441 // Unknown packet: ignore! | 552 // Unknown packet: ignore! |
442 break; | 553 break; |
443 } | 554 } |
444 } | 555 } |
445 | 556 |
| 557 void XboxController::ProcessXboxOnePacket(size_t length) { |
| 558 if (length < 2) |
| 559 return; |
| 560 DCHECK(length <= read_buffer_size_); |
| 561 if (length > read_buffer_size_) { |
| 562 IOError(); |
| 563 return; |
| 564 } |
| 565 uint8* buffer = read_buffer_.get(); |
| 566 |
| 567 uint8 type = buffer[0]; |
| 568 buffer += 4; |
| 569 length -= 4; |
| 570 switch (type) { |
| 571 case XBOX_ONE_STATUS_MESSAGE_BUTTONS: { |
| 572 if (length != sizeof(XboxOneButtonData)) |
| 573 return; |
| 574 XboxOneButtonData* data = reinterpret_cast<XboxOneButtonData*>(buffer); |
| 575 Data normalized_data; |
| 576 NormalizeXboxOneButtonData(*data, &normalized_data); |
| 577 delegate_->XboxControllerGotData(this, normalized_data); |
| 578 break; |
| 579 } |
| 580 default: |
| 581 // Unknown packet: ignore! |
| 582 break; |
| 583 } |
| 584 } |
| 585 |
446 void XboxController::QueueRead() { | 586 void XboxController::QueueRead() { |
447 kern_return_t kr = (*interface_)->ReadPipeAsync(interface_, | 587 kern_return_t kr = (*interface_)->ReadPipeAsync(interface_, |
448 kReadEndpoint, | 588 read_endpoint_, |
449 read_buffer_.get(), | 589 read_buffer_.get(), |
450 read_buffer_size_, | 590 read_buffer_size_, |
451 GotData, | 591 GotData, |
452 this); | 592 this); |
453 if (kr != KERN_SUCCESS) | 593 if (kr != KERN_SUCCESS) |
454 IOError(); | 594 IOError(); |
455 } | 595 } |
456 | 596 |
457 void XboxController::IOError() { | 597 void XboxController::IOError() { |
458 delegate_->XboxControllerError(this); | 598 delegate_->XboxControllerError(this); |
459 } | 599 } |
460 | 600 |
| 601 void XboxController::WriteXboxOneInit() { |
| 602 const UInt8 length = 2; |
| 603 |
| 604 // This buffer will be released in WriteComplete when WritePipeAsync |
| 605 // finishes. |
| 606 UInt8* buffer = new UInt8[length]; |
| 607 buffer[0] = 0x05; |
| 608 buffer[1] = 0x20; |
| 609 kern_return_t kr = (*interface_)->WritePipeAsync(interface_, |
| 610 control_endpoint_, |
| 611 buffer, |
| 612 (UInt32)length, |
| 613 WriteComplete, |
| 614 buffer); |
| 615 if (kr != KERN_SUCCESS) { |
| 616 delete[] buffer; |
| 617 IOError(); |
| 618 return; |
| 619 } |
| 620 } |
| 621 |
461 //----------------------------------------------------------------------------- | 622 //----------------------------------------------------------------------------- |
462 | 623 |
463 XboxDataFetcher::XboxDataFetcher(Delegate* delegate) | 624 XboxDataFetcher::XboxDataFetcher(Delegate* delegate) |
464 : delegate_(delegate), | 625 : delegate_(delegate), |
465 listening_(false), | 626 listening_(false), |
466 source_(NULL), | 627 source_(NULL), |
467 port_(NULL) { | 628 port_(NULL) { |
468 } | 629 } |
469 | 630 |
470 XboxDataFetcher::~XboxDataFetcher() { | 631 XboxDataFetcher::~XboxDataFetcher() { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 kNilOptions))); | 664 kNilOptions))); |
504 UInt32 location_id = 0; | 665 UInt32 location_id = 0; |
505 CFNumberGetValue(number, kCFNumberSInt32Type, &location_id); | 666 CFNumberGetValue(number, kCFNumberSInt32Type, &location_id); |
506 fetcher->RemoveControllerByLocationID(location_id); | 667 fetcher->RemoveControllerByLocationID(location_id); |
507 } | 668 } |
508 } | 669 } |
509 | 670 |
510 bool XboxDataFetcher::RegisterForNotifications() { | 671 bool XboxDataFetcher::RegisterForNotifications() { |
511 if (listening_) | 672 if (listening_) |
512 return true; | 673 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); | 674 port_ = IONotificationPortCreate(kIOMasterPortDefault); |
524 if (!port_) | 675 if (!port_) |
525 return false; | 676 return false; |
526 source_ = IONotificationPortGetRunLoopSource(port_); | 677 source_ = IONotificationPortGetRunLoopSource(port_); |
527 if (!source_) | 678 if (!source_) |
528 return false; | 679 return false; |
529 CFRunLoopAddSource(CFRunLoopGetCurrent(), source_, kCFRunLoopDefaultMode); | 680 CFRunLoopAddSource(CFRunLoopGetCurrent(), source_, kCFRunLoopDefaultMode); |
530 | 681 |
531 listening_ = true; | 682 listening_ = true; |
532 | 683 |
| 684 if (!RegisterForDeviceNotifications( |
| 685 kVendorMicrosoft, kProductXboxOneController, |
| 686 &xbox_one_device_added_iter_, |
| 687 &xbox_one_device_removed_iter_)) |
| 688 return false; |
| 689 |
| 690 if (!RegisterForDeviceNotifications( |
| 691 kVendorMicrosoft, kProductXbox360Controller, |
| 692 &xbox_360_device_added_iter_, |
| 693 &xbox_360_device_removed_iter_)) |
| 694 return false; |
| 695 |
| 696 return true; |
| 697 } |
| 698 |
| 699 bool XboxDataFetcher::RegisterForDeviceNotifications( |
| 700 int vendor_id, |
| 701 int product_id, |
| 702 base::mac::ScopedIOObject<io_iterator_t>* added_iter, |
| 703 base::mac::ScopedIOObject<io_iterator_t>* removed_iter) { |
| 704 base::ScopedCFTypeRef<CFNumberRef> vendor_cf(CFNumberCreate( |
| 705 kCFAllocatorDefault, kCFNumberSInt32Type, &vendor_id)); |
| 706 base::ScopedCFTypeRef<CFNumberRef> product_cf(CFNumberCreate( |
| 707 kCFAllocatorDefault, kCFNumberSInt32Type, &product_id)); |
| 708 base::ScopedCFTypeRef<CFMutableDictionaryRef> matching_dict( |
| 709 IOServiceMatching(kIOUSBDeviceClassName)); |
| 710 if (!matching_dict) |
| 711 return false; |
| 712 CFDictionarySetValue(matching_dict, CFSTR(kUSBVendorID), vendor_cf); |
| 713 CFDictionarySetValue(matching_dict, CFSTR(kUSBProductID), product_cf); |
| 714 |
533 // IOServiceAddMatchingNotification() releases the dictionary when it's done. | 715 // IOServiceAddMatchingNotification() releases the dictionary when it's done. |
534 // Retain it before each call to IOServiceAddMatchingNotification to keep | 716 // Retain it before each call to IOServiceAddMatchingNotification to keep |
535 // things balanced. | 717 // things balanced. |
536 CFRetain(matching_dict); | 718 CFRetain(matching_dict); |
537 io_iterator_t device_added_iter; | 719 io_iterator_t device_added_iter; |
538 IOReturn ret; | 720 IOReturn ret; |
539 ret = IOServiceAddMatchingNotification(port_, | 721 ret = IOServiceAddMatchingNotification(port_, |
540 kIOFirstMatchNotification, | 722 kIOFirstMatchNotification, |
541 matching_dict, | 723 matching_dict, |
542 DeviceAdded, | 724 DeviceAdded, |
543 this, | 725 this, |
544 &device_added_iter); | 726 &device_added_iter); |
545 device_added_iter_.reset(device_added_iter); | 727 added_iter->reset(device_added_iter); |
546 if (ret != kIOReturnSuccess) { | 728 if (ret != kIOReturnSuccess) { |
547 LOG(ERROR) << "Error listening for Xbox controller add events: " << ret; | 729 LOG(ERROR) << "Error listening for Xbox controller add events: " << ret; |
548 return false; | 730 return false; |
549 } | 731 } |
550 DeviceAdded(this, device_added_iter_.get()); | 732 DeviceAdded(this, added_iter->get()); |
551 | 733 |
552 CFRetain(matching_dict); | 734 CFRetain(matching_dict); |
553 io_iterator_t device_removed_iter; | 735 io_iterator_t device_removed_iter; |
554 ret = IOServiceAddMatchingNotification(port_, | 736 ret = IOServiceAddMatchingNotification(port_, |
555 kIOTerminatedNotification, | 737 kIOTerminatedNotification, |
556 matching_dict, | 738 matching_dict, |
557 DeviceRemoved, | 739 DeviceRemoved, |
558 this, | 740 this, |
559 &device_removed_iter); | 741 &device_removed_iter); |
560 device_removed_iter_.reset(device_removed_iter); | 742 removed_iter->reset(device_removed_iter); |
561 if (ret != kIOReturnSuccess) { | 743 if (ret != kIOReturnSuccess) { |
562 LOG(ERROR) << "Error listening for Xbox controller remove events: " << ret; | 744 LOG(ERROR) << "Error listening for Xbox controller remove events: " << ret; |
563 return false; | 745 return false; |
564 } | 746 } |
565 DeviceRemoved(this, device_removed_iter_.get()); | 747 DeviceRemoved(this, removed_iter->get()); |
566 return true; | 748 return true; |
567 } | 749 } |
568 | 750 |
569 void XboxDataFetcher::UnregisterFromNotifications() { | 751 void XboxDataFetcher::UnregisterFromNotifications() { |
570 if (!listening_) | 752 if (!listening_) |
571 return; | 753 return; |
572 listening_ = false; | 754 listening_ = false; |
573 if (source_) | 755 if (source_) |
574 CFRunLoopSourceInvalidate(source_); | 756 CFRunLoopSourceInvalidate(source_); |
575 if (port_) | 757 if (port_) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 } | 798 } |
617 | 799 |
618 void XboxDataFetcher::XboxControllerGotData(XboxController* controller, | 800 void XboxDataFetcher::XboxControllerGotData(XboxController* controller, |
619 const XboxController::Data& data) { | 801 const XboxController::Data& data) { |
620 delegate_->XboxValueChanged(controller, data); | 802 delegate_->XboxValueChanged(controller, data); |
621 } | 803 } |
622 | 804 |
623 void XboxDataFetcher::XboxControllerError(XboxController* controller) { | 805 void XboxDataFetcher::XboxControllerError(XboxController* controller) { |
624 RemoveController(controller); | 806 RemoveController(controller); |
625 } | 807 } |
OLD | NEW |