1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "device/gamepad/nintendo_controller.h"
6 
7 #include <algorithm>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/numerics/ranges.h"
12 #include "base/strings/stringprintf.h"
13 #include "device/gamepad/gamepad_data_fetcher.h"
14 #include "device/gamepad/gamepad_id_list.h"
15 
16 namespace device {
17 namespace {
18 // Device IDs for the Switch Charging Grip, also used for composite devices.
19 const uint16_t kVendorNintendo = 0x057e;
20 const uint16_t kProductSwitchChargingGrip = 0x200e;
21 
22 // Maximum output report sizes, used to distinguish USB and Bluetooth.
23 const size_t kSwitchProMaxOutputReportSizeBytesUsb = 63;
24 const size_t kSwitchProMaxOutputReportSizeBytesBluetooth = 48;
25 
26 // Input report size.
27 const size_t kMaxInputReportSizeBytes = 64;
28 
29 // Device name for a composite Joy-Con device.
30 const char kProductNameSwitchCompositeDevice[] = "Joy-Con L+R";
31 
32 // Report IDs.
33 const uint8_t kReportIdOutput01 = 0x01;
34 const uint8_t kReportIdOutput10 = 0x10;
35 const uint8_t kReportIdInput21 = 0x21;
36 const uint8_t kReportIdInput30 = 0x30;
37 const uint8_t kUsbReportIdOutput80 = 0x80;
38 const uint8_t kUsbReportIdInput81 = 0x81;
39 
40 // Sub-types of the 0x80 output report, used for initialization.
41 const uint8_t kSubTypeRequestMac = 0x01;
42 const uint8_t kSubTypeHandshake = 0x02;
43 const uint8_t kSubTypeBaudRate = 0x03;
44 const uint8_t kSubTypeDisableUsbTimeout = 0x04;
45 const uint8_t kSubTypeEnableUsbTimeout = 0x05;
46 
47 // UART subcommands.
48 const uint8_t kSubCommandSetInputReportMode = 0x03;
49 const uint8_t kSubCommandReadSpi = 0x10;
50 const uint8_t kSubCommandSetPlayerLights = 0x30;
51 const uint8_t kSubCommand33 = 0x33;
52 const uint8_t kSubCommandSetHomeLight = 0x38;
53 const uint8_t kSubCommandEnableImu = 0x40;
54 const uint8_t kSubCommandSetImuSensitivity = 0x41;
55 const uint8_t kSubCommandEnableVibration = 0x48;
56 
57 // SPI memory regions.
58 const uint16_t kSpiImuCalibrationAddress = 0x6020;
59 const size_t kSpiImuCalibrationSize = 24;
60 const uint16_t kSpiAnalogStickCalibrationAddress = 0x603d;
61 const size_t kSpiAnalogStickCalibrationSize = 18;
62 const uint16_t kSpiImuHorizontalOffsetsAddress = 0x6080;
63 const size_t kSpiImuHorizontalOffsetsSize = 6;
64 const uint16_t kSpiAnalogStickParametersAddress = 0x6086;
65 const size_t kSpiAnalogStickParametersSize = 18;
66 
67 // Byte index for the first byte of subcommand data in 0x80 output reports.
68 const size_t kSubCommandDataOffset = 11;
69 // Byte index for the first byte of SPI data in SPI read responses.
70 const size_t kSpiDataOffset = 20;
71 
72 // Values for the |device_type| field reported in the MAC reply.
73 const uint8_t kUsbDeviceTypeChargingGripNoDevice = 0x00;
74 const uint8_t kUsbDeviceTypeChargingGripJoyConL = 0x01;
75 const uint8_t kUsbDeviceTypeChargingGripJoyConR = 0x02;
76 const uint8_t kUsbDeviceTypeProController = 0x03;
77 
78 // During initialization, the current initialization step will be retried if
79 // the client does not respond within |kTimeoutDuration|. After |kMaxRetryCount|
80 // retries, initialization is restarted from the first step.
81 //
82 // The timeout duration was chosen through experimentation. A shorter duration
83 // (~1 second) works for Pro controllers, but Joy-Cons sometimes fail to
84 // initialize correctly.
85 const base::TimeDelta kTimeoutDuration =
86     base::TimeDelta::FromMilliseconds(3000);
87 const size_t kMaxRetryCount = 3;
88 
89 const size_t kMaxVibrationEffectDurationMillis = 100;
90 
91 // Initialization parameters.
92 const uint8_t kGyroSensitivity2000Dps = 0x03;
93 const uint8_t kAccelerometerSensitivity8G = 0x00;
94 const uint8_t kGyroPerformance208Hz = 0x01;
95 const uint8_t kAccelerometerFilterBandwidth100Hz = 0x01;
96 const uint8_t kPlayerLightPattern1 = 0x01;
97 
98 // Bogus calibration value that should be ignored.
99 const uint16_t kCalBogusValue = 0xfff;
100 
101 // Default calibration values to use if the controller returns bogus values.
102 const uint16_t kCalDefaultDeadzone = 160;
103 const uint16_t kCalDefaultMin = 550;
104 const uint16_t kCalDefaultCenter = 2050;
105 const uint16_t kCalDefaultMax = 3550;
106 
107 // Parameters for the "strong" and "weak" components of the dual-rumble effect.
108 const double kVibrationFrequencyStrongRumble = 141.0;
109 const double kVibrationFrequencyWeakRumble = 182.0;
110 const double kVibrationAmplitudeStrongRumbleMax = 0.9;
111 const double kVibrationAmplitudeWeakRumbleMax = 0.1;
112 
113 const int kVibrationFrequencyHzMin = 41;
114 const int kVibrationFrequencyHzMax = 1253;
115 const int kVibrationAmplitudeMax = 1000;
116 
117 // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
118 struct VibrationFrequency {
119   uint16_t hf;
120   uint8_t lf;
121   int freq_hz;  // rounded
122 } kVibrationFrequency[] = {
123     // The linear resonant actuators (LRAs) on Switch devices are capable of
124     // producing vibration effects at a wide range of frequencies, but the
125     // Gamepad API assumes "dual-rumble" style vibration which is typically
126     // implemented by a pair of eccentric rotating mass (ERM) actuators. To
127     // simulate "dual-rumble" with Switch LRAs, the strong and weak vibration
128     // magnitudes are translated into low and high frequency vibration effects.
129     // Only the frequencies used for this translation are included; unused
130     // frequencies have been removed.
131     //
132     // This list must be kept sorted.
133     {0x0068, 0x3a, 141},
134     {0x0098, 0x46, 182}};
135 const size_t kVibrationFrequencySize = base::size(kVibrationFrequency);
136 
137 // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
138 struct VibrationAmplitude {
139   uint8_t hfa;
140   uint16_t lfa;
141   int amp;  // rounded, max 1000 (kVibrationAmplitudeMax)
142 } kVibrationAmplitude[]{
143     // Only include safe amplitudes.
144     {0x00, 0x0040, 0},   {0x02, 0x8040, 10},   {0x04, 0x0041, 12},
145     {0x06, 0x8041, 14},  {0x08, 0x0042, 17},   {0x0a, 0x8042, 20},
146     {0x0c, 0x0043, 24},  {0x0e, 0x8043, 28},   {0x10, 0x0044, 33},
147     {0x12, 0x8044, 40},  {0x14, 0x0045, 47},   {0x16, 0x8045, 56},
148     {0x18, 0x0046, 67},  {0x1a, 0x8046, 80},   {0x1c, 0x0047, 95},
149     {0x1e, 0x8047, 112}, {0x20, 0x0048, 117},  {0x22, 0x8048, 123},
150     {0x24, 0x0049, 128}, {0x26, 0x8049, 134},  {0x28, 0x004a, 140},
151     {0x2a, 0x804a, 146}, {0x2c, 0x004b, 152},  {0x2e, 0x804b, 159},
152     {0x30, 0x004c, 166}, {0x32, 0x804c, 173},  {0x34, 0x004d, 181},
153     {0x36, 0x804d, 189}, {0x38, 0x004e, 198},  {0x3a, 0x804e, 206},
154     {0x3c, 0x004f, 215}, {0x3e, 0x804f, 225},  {0x40, 0x0050, 230},
155     {0x42, 0x8050, 235}, {0x44, 0x0051, 240},  {0x46, 0x8051, 245},
156     {0x48, 0x0052, 251}, {0x4a, 0x8052, 256},  {0x4c, 0x0053, 262},
157     {0x4e, 0x8053, 268}, {0x50, 0x0054, 273},  {0x52, 0x8054, 279},
158     {0x54, 0x0055, 286}, {0x56, 0x8055, 292},  {0x58, 0x0056, 298},
159     {0x5a, 0x8056, 305}, {0x5c, 0x0057, 311},  {0x5e, 0x8057, 318},
160     {0x60, 0x0058, 325}, {0x62, 0x8058, 332},  {0x64, 0x0059, 340},
161     {0x66, 0x8059, 347}, {0x68, 0x005a, 355},  {0x6a, 0x805a, 362},
162     {0x6c, 0x005b, 370}, {0x6e, 0x805b, 378},  {0x70, 0x005c, 387},
163     {0x72, 0x805c, 395}, {0x74, 0x005d, 404},  {0x76, 0x805d, 413},
164     {0x78, 0x005e, 422}, {0x7a, 0x805e, 431},  {0x7c, 0x005f, 440},
165     {0x7e, 0x805f, 450}, {0x80, 0x0060, 460},  {0x82, 0x8060, 470},
166     {0x84, 0x0061, 480}, {0x86, 0x8061, 491},  {0x88, 0x0062, 501},
167     {0x8a, 0x8062, 512}, {0x8c, 0x0063, 524},  {0x8e, 0x8063, 535},
168     {0x90, 0x0064, 547}, {0x92, 0x8064, 559},  {0x94, 0x0065, 571},
169     {0x96, 0x8065, 584}, {0x98, 0x0066, 596},  {0x9a, 0x8066, 609},
170     {0x9c, 0x0067, 623}, {0x9e, 0x8067, 636},  {0xa0, 0x0068, 650},
171     {0xa2, 0x8068, 665}, {0xa4, 0x0069, 679},  {0xa6, 0x8069, 694},
172     {0xa8, 0x006a, 709}, {0xaa, 0x806a, 725},  {0xac, 0x006b, 741},
173     {0xae, 0x806b, 757}, {0xb0, 0x006c, 773},  {0xb2, 0x806c, 790},
174     {0xb4, 0x006d, 808}, {0xb6, 0x806d, 825},  {0xb8, 0x006e, 843},
175     {0xba, 0x806e, 862}, {0xbc, 0x006f, 881},  {0xbe, 0x806f, 900},
176     {0xc0, 0x0070, 920}, {0xc2, 0x8070, 940},  {0xc4, 0x0071, 960},
177     {0xc6, 0x8071, 981}, {0xc8, 0x0072, 1000},
178 };
179 const size_t kVibrationAmplitudeSize = base::size(kVibrationAmplitude);
180 
181 // Define indices for the additional buttons on Switch controllers.
182 enum SWITCH_BUTTON_INDICES {
183   SWITCH_BUTTON_INDEX_CAPTURE = BUTTON_INDEX_META + 1,
184   SWITCH_BUTTON_INDEX_LEFT_SL,
185   SWITCH_BUTTON_INDEX_LEFT_SR,
186   SWITCH_BUTTON_INDEX_RIGHT_SL,
187   SWITCH_BUTTON_INDEX_RIGHT_SR,
188   SWITCH_BUTTON_INDEX_COUNT
189 };
190 
191 // Input reports with ID 0x81 are replies to commands sent during the
192 // initialization sequence.
193 #pragma pack(push, 1)
194 struct UsbInputReport81 {
195   uint8_t subtype;
196   uint8_t data[kMaxInputReportSizeBytes - 2];
197 };
198 #pragma pack(pop)
199 static_assert(sizeof(UsbInputReport81) == kMaxInputReportSizeBytes - 1,
200               "UsbInputReport81 has incorrect size");
201 
202 // When connected over USB, the initialization sequence includes a step to
203 // request the MAC address. The MAC is returned in an input report with ID 0x81
204 // and subtype 0x01.
205 #pragma pack(push, 1)
206 struct MacAddressReport {
207   uint8_t subtype;  // 0x01
208   uint8_t padding;
209   uint8_t device_type;
210   uint8_t mac_data[6];
211   uint8_t padding2[kMaxInputReportSizeBytes - 10];
212 };
213 #pragma pack(pop)
214 static_assert(sizeof(MacAddressReport) == kMaxInputReportSizeBytes - 1,
215               "MacAddressReport has incorrect size");
216 
217 // When configured for standard full input report mode, controller data is
218 // reported at regular intervals. The data format is the same for all Switch
219 // devices, although some buttons are not present on all devices.
220 #pragma pack(push, 1)
221 struct ControllerData {
222   uint8_t timestamp;
223   uint8_t battery_level : 4;
224   uint8_t connection_info : 4;
225   bool button_y : 1;
226   bool button_x : 1;
227   bool button_b : 1;
228   bool button_a : 1;
229   bool button_right_sr : 1;
230   bool button_right_sl : 1;
231   bool button_r : 1;
232   bool button_zr : 1;
233   bool button_minus : 1;
234   bool button_plus : 1;
235   bool button_thumb_r : 1;
236   bool button_thumb_l : 1;
237   bool button_home : 1;
238   bool button_capture : 1;
239   uint8_t dummy : 1;
240   bool charging_grip : 1;
241   bool dpad_down : 1;
242   bool dpad_up : 1;
243   bool dpad_right : 1;
244   bool dpad_left : 1;
245   bool button_left_sr : 1;
246   bool button_left_sl : 1;
247   bool button_l : 1;
248   bool button_zl : 1;
249   uint8_t analog[6];
250   uint8_t vibrator_input_report;
251 };
252 #pragma pack(pop)
253 static_assert(sizeof(ControllerData) == 12,
254               "ControllerData has incorrect size");
255 
256 // In standard full input report mode, controller data is reported with IMU data
257 // in reports with ID 0x30.
258 #pragma pack(push, 1)
259 struct ControllerDataReport {
260   ControllerData controller_data;  // 12 bytes
261   uint8_t imu_data[36];
262   uint8_t padding[kMaxInputReportSizeBytes - 49];
263 };
264 #pragma pack(pop)
265 static_assert(sizeof(ControllerDataReport) == kMaxInputReportSizeBytes - 1,
266               "ControllerDataReport has incorrect size");
267 
268 // Responses to SPI read requests are sent in reports with ID 0x21. These
269 // reports also include controller data.
270 #pragma pack(push, 1)
271 struct SpiReadReport {
272   ControllerData controller_data;  // 12 bytes
273   uint8_t subcommand_ack;          // 0x90
274   uint8_t subcommand;              // 0x10
275   uint8_t addrl;
276   uint8_t addrh;
277   uint8_t padding[2];  // 0x00 0x00
278   uint8_t length;
279   uint8_t spi_data[kMaxInputReportSizeBytes - kSpiDataOffset];
280 };
281 #pragma pack(pop)
282 static_assert(sizeof(SpiReadReport) == kMaxInputReportSizeBytes - 1,
283               "SpiReadReport has incorrect size");
284 
285 // Unpack two packed 12-bit values.
UnpackShorts(uint8_t byte0,uint8_t byte1,uint8_t byte2,uint16_t * short1,uint16_t * short2)286 void UnpackShorts(uint8_t byte0,
287                   uint8_t byte1,
288                   uint8_t byte2,
289                   uint16_t* short1,
290                   uint16_t* short2) {
291   DCHECK(short1);
292   DCHECK(short2);
293   *short1 = ((byte1 << 8) & 0x0f00) | byte0;
294   *short2 = (byte2 << 4) | (byte1 >> 4);
295 }
296 
297 // Unpack a 6-byte MAC address.
UnpackSwitchMacAddress(const uint8_t * data)298 uint64_t UnpackSwitchMacAddress(const uint8_t* data) {
299   DCHECK(data);
300   uint64_t acc = data[5];
301   acc = (acc << 8) | data[4];
302   acc = (acc << 8) | data[3];
303   acc = (acc << 8) | data[2];
304   acc = (acc << 8) | data[1];
305   acc = (acc << 8) | data[0];
306   return acc;
307 }
308 
309 // Unpack the analog stick parameters into |cal|.
UnpackSwitchAnalogStickParameters(const uint8_t * data,NintendoController::SwitchCalibrationData & cal)310 void UnpackSwitchAnalogStickParameters(
311     const uint8_t* data,
312     NintendoController::SwitchCalibrationData& cal) {
313   DCHECK(data);
314   // Only fetch the dead zone and range ratio. The other parameters are unknown.
315   UnpackShorts(data[3], data[4], data[5], &cal.dead_zone, &cal.range_ratio);
316   if (cal.dead_zone == kCalBogusValue) {
317     // If the controller reports an invalid dead zone, default to something
318     // reasonable.
319     cal.dead_zone = kCalDefaultDeadzone;
320   }
321 }
322 
323 // Unpack the IMU calibration data into |cal|
UnpackSwitchImuCalibration(const uint8_t * data,NintendoController::SwitchCalibrationData & cal)324 void UnpackSwitchImuCalibration(
325     const uint8_t* data,
326     NintendoController::SwitchCalibrationData& cal) {
327   DCHECK(data);
328   // 24 bytes, as 4 groups of 3 16-bit little-endian values.
329   cal.accelerometer_origin_x = (data[1] << 8) | data[0];
330   cal.accelerometer_origin_y = (data[3] << 8) | data[2];
331   cal.accelerometer_origin_z = (data[5] << 8) | data[4];
332   cal.accelerometer_sensitivity_x = (data[7] << 8) | data[6];
333   cal.accelerometer_sensitivity_y = (data[9] << 8) | data[8];
334   cal.accelerometer_sensitivity_z = (data[11] << 8) | data[10];
335   cal.gyro_origin_x = (data[13] << 8) | data[12];
336   cal.gyro_origin_y = (data[15] << 8) | data[14];
337   cal.gyro_origin_z = (data[17] << 8) | data[16];
338   cal.gyro_sensitivity_x = (data[19] << 8) | data[18];
339   cal.gyro_sensitivity_y = (data[21] << 8) | data[20];
340   cal.gyro_sensitivity_z = (data[23] << 8) | data[22];
341 }
342 
343 // Unpack the IMU horizontal offsets into |cal|.
UnpackSwitchImuHorizontalOffsets(const uint8_t * data,NintendoController::SwitchCalibrationData & cal)344 void UnpackSwitchImuHorizontalOffsets(
345     const uint8_t* data,
346     NintendoController::SwitchCalibrationData& cal) {
347   DCHECK(data);
348   // 6 bytes, as 3 16-bit little-endian values.
349   cal.horizontal_offset_x = (data[1] << 8) | data[0];
350   cal.horizontal_offset_y = (data[3] << 8) | data[2];
351   cal.horizontal_offset_z = (data[5] << 8) | data[4];
352 }
353 
354 // Unpack the analog stick calibration data into |cal|.
UnpackSwitchAnalogStickCalibration(const uint8_t * data,NintendoController::SwitchCalibrationData & cal)355 void UnpackSwitchAnalogStickCalibration(
356     const uint8_t* data,
357     NintendoController::SwitchCalibrationData& cal) {
358   DCHECK(data);
359   // 18 bytes, as 2 groups of 6 packed 12-bit values.
360   UnpackShorts(data[0], data[1], data[2], &cal.lx_max, &cal.ly_max);
361   UnpackShorts(data[3], data[4], data[5], &cal.lx_center, &cal.ly_center);
362   UnpackShorts(data[6], data[7], data[8], &cal.lx_min, &cal.ly_min);
363   UnpackShorts(data[9], data[10], data[11], &cal.rx_center, &cal.ry_center);
364   UnpackShorts(data[12], data[13], data[14], &cal.rx_min, &cal.ry_min);
365   UnpackShorts(data[15], data[16], data[17], &cal.rx_max, &cal.ry_max);
366   if (cal.lx_min == kCalBogusValue && cal.ly_max == kCalBogusValue) {
367     // If the controller reports bogus values, default to something reasonable.
368     cal.lx_min = kCalDefaultMin;
369     cal.lx_center = kCalDefaultCenter;
370     cal.lx_max = kCalDefaultMax;
371     cal.ly_min = kCalDefaultMin;
372     cal.ly_center = kCalDefaultCenter;
373     cal.ly_max = kCalDefaultMax;
374     cal.rx_min = kCalDefaultMin;
375     cal.rx_center = kCalDefaultCenter;
376     cal.rx_max = kCalDefaultMax;
377     cal.ry_min = kCalDefaultMin;
378     cal.ry_center = kCalDefaultCenter;
379     cal.ry_max = kCalDefaultMax;
380   } else {
381     cal.lx_min = cal.lx_center - cal.lx_min;
382     cal.lx_max = cal.lx_center + cal.lx_max;
383     cal.ly_min = cal.ly_center - cal.ly_min;
384     cal.ly_max = cal.ly_center + cal.ly_max;
385     cal.rx_min = cal.rx_center - cal.rx_min;
386     cal.rx_max = cal.rx_center + cal.rx_max;
387     cal.ry_min = cal.ry_center - cal.ry_min;
388     cal.ry_max = cal.ry_center + cal.ry_max;
389   }
390 }
391 
392 // Unpack one frame of IMU data into |imu_data|.
UnpackSwitchImuData(const uint8_t * data,NintendoController::SwitchImuData * imu_data)393 void UnpackSwitchImuData(const uint8_t* data,
394                          NintendoController::SwitchImuData* imu_data) {
395   DCHECK(data);
396   DCHECK(imu_data);
397   // 12 bytes of IMU data containing 6 16-bit little-endian values.
398   imu_data->accelerometer_x = (data[1] << 8) | data[0];
399   imu_data->accelerometer_y = (data[3] << 8) | data[2];
400   imu_data->accelerometer_z = (data[5] << 8) | data[4];
401   imu_data->gyro_x = (data[7] << 8) | data[6];
402   imu_data->gyro_y = (data[9] << 8) | data[8];
403   imu_data->gyro_z = (data[11] << 8) | data[10];
404 }
405 
406 // Given joystick input |x|,|y|, apply a radial deadzone with radius
407 // |dead_zone| centered at |x_center|,|y_center|. If the input is within the
408 // dead zone region, the value is snapped to the center of the dead zone.
ApplyDeadZone(uint16_t & x,uint16_t & y,uint16_t x_center,uint16_t y_center,uint16_t dead_zone)409 bool ApplyDeadZone(uint16_t& x,
410                    uint16_t& y,
411                    uint16_t x_center,
412                    uint16_t y_center,
413                    uint16_t dead_zone) {
414   int dx = x - x_center;
415   int dy = y - y_center;
416   if (dx * dx + dy * dy < dead_zone * dead_zone) {
417     x = x_center;
418     y = y_center;
419     return true;
420   }
421   return false;
422 }
423 
424 // Normalize |value| to the range [|min|,|max|]. If |value| is outside this
425 // range, clamp it.
NormalizeAndClampAxis(int value,int min,int max)426 double NormalizeAndClampAxis(int value, int min, int max) {
427   if (value <= min)
428     return -1.0;
429   if (value >= max)
430     return 1.0;
431   return (2.0 * (value - min) / static_cast<double>(max - min)) - 1.0;
432 }
433 
434 // Update the button and axis state in |pad| with the new controller data in
435 // |data|, using the calibration data |cal|. Returns true if the new data
436 // differs from the previous data.
UpdateGamepadFromControllerData(const ControllerData & data,const NintendoController::SwitchCalibrationData & cal,Gamepad & pad)437 bool UpdateGamepadFromControllerData(
438     const ControllerData& data,
439     const NintendoController::SwitchCalibrationData& cal,
440     Gamepad& pad) {
441   bool buttons_changed =
442       pad.buttons_length != SWITCH_BUTTON_INDEX_COUNT ||
443       pad.buttons[BUTTON_INDEX_PRIMARY].pressed != data.button_b ||
444       pad.buttons[BUTTON_INDEX_SECONDARY].pressed != data.button_a ||
445       pad.buttons[BUTTON_INDEX_TERTIARY].pressed != data.button_y ||
446       pad.buttons[BUTTON_INDEX_QUATERNARY].pressed != data.button_x ||
447       pad.buttons[BUTTON_INDEX_LEFT_SHOULDER].pressed != data.button_l ||
448       pad.buttons[BUTTON_INDEX_RIGHT_SHOULDER].pressed != data.button_r ||
449       pad.buttons[BUTTON_INDEX_LEFT_TRIGGER].pressed != data.button_zl ||
450       pad.buttons[BUTTON_INDEX_RIGHT_TRIGGER].pressed != data.button_zr ||
451       pad.buttons[BUTTON_INDEX_BACK_SELECT].pressed != data.button_minus ||
452       pad.buttons[BUTTON_INDEX_START].pressed != data.button_plus ||
453       pad.buttons[BUTTON_INDEX_LEFT_THUMBSTICK].pressed !=
454           data.button_thumb_l ||
455       pad.buttons[BUTTON_INDEX_RIGHT_THUMBSTICK].pressed !=
456           data.button_thumb_r ||
457       pad.buttons[BUTTON_INDEX_DPAD_UP].pressed != data.dpad_up ||
458       pad.buttons[BUTTON_INDEX_DPAD_DOWN].pressed != data.dpad_down ||
459       pad.buttons[BUTTON_INDEX_DPAD_LEFT].pressed != data.dpad_left ||
460       pad.buttons[BUTTON_INDEX_DPAD_RIGHT].pressed != data.dpad_right ||
461       pad.buttons[BUTTON_INDEX_META].pressed != data.button_home ||
462       pad.buttons[SWITCH_BUTTON_INDEX_CAPTURE].pressed != data.button_capture ||
463       pad.buttons[SWITCH_BUTTON_INDEX_LEFT_SL].pressed != data.button_left_sl ||
464       pad.buttons[SWITCH_BUTTON_INDEX_LEFT_SR].pressed != data.button_left_sr ||
465       pad.buttons[SWITCH_BUTTON_INDEX_RIGHT_SL].pressed !=
466           data.button_right_sl ||
467       pad.buttons[SWITCH_BUTTON_INDEX_RIGHT_SR].pressed != data.button_right_sr;
468 
469   if (buttons_changed) {
470     pad.buttons_length = SWITCH_BUTTON_INDEX_COUNT;
471     pad.buttons[BUTTON_INDEX_PRIMARY].pressed = data.button_b;
472     pad.buttons[BUTTON_INDEX_PRIMARY].value = data.button_b ? 1.0 : 0.0;
473     pad.buttons[BUTTON_INDEX_SECONDARY].pressed = data.button_a;
474     pad.buttons[BUTTON_INDEX_SECONDARY].value = data.button_a ? 1.0 : 0.0;
475     pad.buttons[BUTTON_INDEX_TERTIARY].pressed = data.button_y;
476     pad.buttons[BUTTON_INDEX_TERTIARY].value = data.button_y ? 1.0 : 0.0;
477     pad.buttons[BUTTON_INDEX_QUATERNARY].pressed = data.button_x;
478     pad.buttons[BUTTON_INDEX_QUATERNARY].value = data.button_x ? 1.0 : 0.0;
479     pad.buttons[BUTTON_INDEX_LEFT_SHOULDER].pressed = data.button_l;
480     pad.buttons[BUTTON_INDEX_LEFT_SHOULDER].value = data.button_l ? 1.0 : 0.0;
481     pad.buttons[BUTTON_INDEX_RIGHT_SHOULDER].pressed = data.button_r;
482     pad.buttons[BUTTON_INDEX_RIGHT_SHOULDER].value = data.button_r ? 1.0 : 0.0;
483     pad.buttons[BUTTON_INDEX_LEFT_TRIGGER].pressed = data.button_zl;
484     pad.buttons[BUTTON_INDEX_LEFT_TRIGGER].value = data.button_zl ? 1.0 : 0.0;
485     pad.buttons[BUTTON_INDEX_RIGHT_TRIGGER].pressed = data.button_zr;
486     pad.buttons[BUTTON_INDEX_RIGHT_TRIGGER].value = data.button_zr ? 1.0 : 0.0;
487     pad.buttons[BUTTON_INDEX_BACK_SELECT].pressed = data.button_minus;
488     pad.buttons[BUTTON_INDEX_BACK_SELECT].value = data.button_minus ? 1.0 : 0.0;
489     pad.buttons[BUTTON_INDEX_START].pressed = data.button_plus;
490     pad.buttons[BUTTON_INDEX_START].value = data.button_plus ? 1.0 : 0.0;
491     pad.buttons[BUTTON_INDEX_LEFT_THUMBSTICK].pressed = data.button_thumb_l;
492     pad.buttons[BUTTON_INDEX_LEFT_THUMBSTICK].value =
493         data.button_thumb_l ? 1.0 : 0.0;
494     pad.buttons[BUTTON_INDEX_RIGHT_THUMBSTICK].pressed = data.button_thumb_r;
495     pad.buttons[BUTTON_INDEX_RIGHT_THUMBSTICK].value =
496         data.button_thumb_r ? 1.0 : 0.0;
497     pad.buttons[BUTTON_INDEX_DPAD_UP].pressed = data.dpad_up;
498     pad.buttons[BUTTON_INDEX_DPAD_UP].value = data.dpad_up ? 1.0 : 0.0;
499     pad.buttons[BUTTON_INDEX_DPAD_DOWN].pressed = data.dpad_down;
500     pad.buttons[BUTTON_INDEX_DPAD_DOWN].value = data.dpad_down ? 1.0 : 0.0;
501     pad.buttons[BUTTON_INDEX_DPAD_LEFT].pressed = data.dpad_left;
502     pad.buttons[BUTTON_INDEX_DPAD_LEFT].value = data.dpad_left ? 1.0 : 0.0;
503     pad.buttons[BUTTON_INDEX_DPAD_RIGHT].pressed = data.dpad_right;
504     pad.buttons[BUTTON_INDEX_DPAD_RIGHT].value = data.dpad_right ? 1.0 : 0.0;
505     pad.buttons[BUTTON_INDEX_META].pressed = data.button_home;
506     pad.buttons[BUTTON_INDEX_META].value = data.button_home ? 1.0 : 0.0;
507     pad.buttons[SWITCH_BUTTON_INDEX_CAPTURE].pressed = data.button_capture;
508     pad.buttons[SWITCH_BUTTON_INDEX_CAPTURE].value =
509         data.button_capture ? 1.0 : 0.0;
510     pad.buttons[SWITCH_BUTTON_INDEX_LEFT_SL].pressed = data.button_left_sl;
511     pad.buttons[SWITCH_BUTTON_INDEX_LEFT_SL].value =
512         data.button_left_sl ? 1.0 : 0.0;
513     pad.buttons[SWITCH_BUTTON_INDEX_LEFT_SR].pressed = data.button_left_sr;
514     pad.buttons[SWITCH_BUTTON_INDEX_LEFT_SR].value =
515         data.button_left_sr ? 1.0 : 0.0;
516     pad.buttons[SWITCH_BUTTON_INDEX_RIGHT_SL].pressed = data.button_right_sl;
517     pad.buttons[SWITCH_BUTTON_INDEX_RIGHT_SL].value =
518         data.button_right_sl ? 1.0 : 0.0;
519     pad.buttons[SWITCH_BUTTON_INDEX_RIGHT_SR].pressed = data.button_right_sr;
520     pad.buttons[SWITCH_BUTTON_INDEX_RIGHT_SR].value =
521         data.button_right_sr ? 1.0 : 0.0;
522   }
523 
524   uint16_t axis_lx;
525   uint16_t axis_ly;
526   uint16_t axis_rx;
527   uint16_t axis_ry;
528   UnpackShorts(data.analog[0], data.analog[1], data.analog[2], &axis_lx,
529                &axis_ly);
530   UnpackShorts(data.analog[3], data.analog[4], data.analog[5], &axis_rx,
531                &axis_ry);
532   // Apply a radial dead zone to both sticks.
533   bool ldead = ApplyDeadZone(axis_lx, axis_ly, cal.lx_center, cal.ly_center,
534                              cal.dead_zone);
535   bool rdead = ApplyDeadZone(axis_rx, axis_ry, cal.rx_center, cal.ry_center,
536                              cal.dead_zone);
537   // Normalize using calibration data.
538   double lx =
539       ldead ? 0.0 : NormalizeAndClampAxis(axis_lx, cal.lx_min, cal.lx_max);
540   double ly =
541       ldead ? 0.0 : -NormalizeAndClampAxis(axis_ly, cal.ly_min, cal.ly_max);
542   double rx =
543       rdead ? 0.0 : NormalizeAndClampAxis(axis_rx, cal.rx_min, cal.rx_max);
544   double ry =
545       rdead ? 0.0 : -NormalizeAndClampAxis(axis_ry, cal.ry_min, cal.ry_max);
546   bool axes_changed = pad.axes_length != AXIS_INDEX_COUNT ||
547                       pad.axes[device::AXIS_INDEX_LEFT_STICK_X] != lx ||
548                       pad.axes[device::AXIS_INDEX_LEFT_STICK_Y] != ly ||
549                       pad.axes[device::AXIS_INDEX_RIGHT_STICK_X] != rx ||
550                       pad.axes[device::AXIS_INDEX_RIGHT_STICK_Y] != ry;
551   if (axes_changed) {
552     pad.axes_length = AXIS_INDEX_COUNT;
553     pad.axes[device::AXIS_INDEX_LEFT_STICK_X] = lx;
554     pad.axes[device::AXIS_INDEX_LEFT_STICK_Y] = ly;
555     pad.axes[device::AXIS_INDEX_RIGHT_STICK_X] = rx;
556     pad.axes[device::AXIS_INDEX_RIGHT_STICK_Y] = ry;
557   }
558 
559   return buttons_changed || axes_changed;
560 }
561 
562 // Update the state for a single button. The button state is taken from
563 // the button at index |button_index| in |src_pad|. If this is a composite
564 // device, |src_pad| holds the state for the left component. If |horizontal| is
565 // true, the button index is remapped for horizontal orientation before updating
566 // the state in |dst_pad|.
UpdateButtonForLeftSide(const Gamepad & src_pad,Gamepad & dst_pad,size_t button_index,bool horizontal)567 void UpdateButtonForLeftSide(const Gamepad& src_pad,
568                              Gamepad& dst_pad,
569                              size_t button_index,
570                              bool horizontal) {
571   size_t remapped_index = button_index;
572   // The internal button mapping assumes a docked orientation for Joy-Cons. If
573   // a Joy-Con is used by itself, remap the buttons so they match the Standard
574   // Gamepad spec when held horizontally.
575   if (horizontal) {
576     switch (button_index) {
577       // Map the D-pad buttons to action buttons.
578       case BUTTON_INDEX_DPAD_LEFT:
579         remapped_index = BUTTON_INDEX_PRIMARY;
580         break;
581       case BUTTON_INDEX_DPAD_DOWN:
582         remapped_index = BUTTON_INDEX_SECONDARY;
583         break;
584       case BUTTON_INDEX_DPAD_UP:
585         remapped_index = BUTTON_INDEX_TERTIARY;
586         break;
587       case BUTTON_INDEX_DPAD_RIGHT:
588         remapped_index = BUTTON_INDEX_QUATERNARY;
589         break;
590       // Map L to Select.
591       case BUTTON_INDEX_LEFT_SHOULDER:
592         remapped_index = BUTTON_INDEX_BACK_SELECT;
593         break;
594       // Map Minus to Start.
595       case BUTTON_INDEX_BACK_SELECT:
596         remapped_index = BUTTON_INDEX_START;
597         break;
598       // Map Capture to Meta.
599       case SWITCH_BUTTON_INDEX_CAPTURE:
600         remapped_index = BUTTON_INDEX_META;
601         break;
602       // Map SL and SR to the left and right shoulders.
603       case SWITCH_BUTTON_INDEX_LEFT_SL:
604         remapped_index = BUTTON_INDEX_LEFT_SHOULDER;
605         break;
606       case SWITCH_BUTTON_INDEX_LEFT_SR:
607         remapped_index = BUTTON_INDEX_RIGHT_SHOULDER;
608         break;
609       // ZL and the left thumbstick are unmodified.
610       case BUTTON_INDEX_LEFT_TRIGGER:
611       case BUTTON_INDEX_LEFT_THUMBSTICK:
612         break;
613       default:
614         NOTREACHED();
615         break;
616     }
617   }
618   dst_pad.buttons[remapped_index] = src_pad.buttons[button_index];
619 }
620 
621 // Update the state for a single button. The button state is taken from
622 // the button at index |button_index| in |src_pad|. If this is a composite
623 // device, |src_pad| holds the state for the right component. If |horizontal| is
624 // true, the button index is remapped for horizontal orientation before updating
625 // the state in |dst_pad|.
UpdateButtonForRightSide(const Gamepad & src_pad,Gamepad & dst_pad,size_t button_index,bool horizontal)626 void UpdateButtonForRightSide(const Gamepad& src_pad,
627                               Gamepad& dst_pad,
628                               size_t button_index,
629                               bool horizontal) {
630   size_t remapped_index = button_index;
631   // The internal button mapping assumes a docked orientation for Joy-Cons. If
632   // a Joy-Con is used by itself, remap the buttons so they match the Standard
633   // Gamepad spec when held horizontally.
634   if (horizontal) {
635     switch (button_index) {
636       // Re-map the action buttons to rotate them.
637       case BUTTON_INDEX_PRIMARY:
638         remapped_index = BUTTON_INDEX_TERTIARY;
639         break;
640       case BUTTON_INDEX_TERTIARY:
641         remapped_index = BUTTON_INDEX_QUATERNARY;
642         break;
643       case BUTTON_INDEX_QUATERNARY:
644         remapped_index = BUTTON_INDEX_SECONDARY;
645         break;
646       case BUTTON_INDEX_SECONDARY:
647         remapped_index = BUTTON_INDEX_PRIMARY;
648         break;
649       // Map R to Select.
650       case BUTTON_INDEX_RIGHT_SHOULDER:
651         remapped_index = BUTTON_INDEX_BACK_SELECT;
652         break;
653       // Map SL and SR to the left and right shoulders.
654       case SWITCH_BUTTON_INDEX_RIGHT_SL:
655         remapped_index = BUTTON_INDEX_LEFT_SHOULDER;
656         break;
657       case SWITCH_BUTTON_INDEX_RIGHT_SR:
658         remapped_index = BUTTON_INDEX_RIGHT_SHOULDER;
659         break;
660       // Map right thumbstick button to left thumbstick button.
661       case BUTTON_INDEX_RIGHT_THUMBSTICK:
662         remapped_index = BUTTON_INDEX_LEFT_THUMBSTICK;
663         break;
664       // The Plus, Home, and ZR buttons are unmodified.
665       case BUTTON_INDEX_START:
666       case BUTTON_INDEX_META:
667       case BUTTON_INDEX_RIGHT_TRIGGER:
668         break;
669       default:
670         NOTREACHED();
671         break;
672     }
673   }
674   dst_pad.buttons[remapped_index] = src_pad.buttons[button_index];
675 }
676 
677 // Update the state for a single axis. The axis state is taken from the axis at
678 // index |axis_index| in |src_pad|. If this is a composite device, |src_pad|
679 // holds the state for the left component. If |horizontal| is true, the axis
680 // index and value are remapped for horizontal orientation before updating the
681 // state in |dst_pad|.
UpdateAxisForLeftSide(const Gamepad & src_pad,Gamepad & dst_pad,size_t axis_index,bool horizontal)682 void UpdateAxisForLeftSide(const Gamepad& src_pad,
683                            Gamepad& dst_pad,
684                            size_t axis_index,
685                            bool horizontal) {
686   size_t remapped_index = axis_index;
687   double axis_value = src_pad.axes[axis_index];
688   // The internal axis values assume a docked orientation for Joy-Cons. If a
689   // Joy-Con is used by itself, remap the axis indices and adjust the sign on
690   // the axis value for a horizontal orientation.
691   if (horizontal) {
692     switch (axis_index) {
693       case AXIS_INDEX_LEFT_STICK_X:
694         // Map +X to -Y.
695         axis_value = -axis_value;
696         remapped_index = AXIS_INDEX_LEFT_STICK_Y;
697         break;
698       case AXIS_INDEX_LEFT_STICK_Y:
699         // Map +Y to +X.
700         remapped_index = AXIS_INDEX_LEFT_STICK_X;
701         break;
702       default:
703         NOTREACHED();
704         break;
705     }
706   }
707   dst_pad.axes[remapped_index] = axis_value;
708 }
709 
710 // Update the state for a single axis. The axis state is taken from the axis at
711 // index |axis_index| in |src_pad|. If this is a composite device, |src_pad|
712 // holds the state for the right component. If |horizontal| is true, the axis
713 // index and value are remapped for horizontal orientation before updating the
714 // state in |dst_pad|.
UpdateAxisForRightSide(const Gamepad & src_pad,Gamepad & dst_pad,size_t axis_index,bool horizontal)715 void UpdateAxisForRightSide(const Gamepad& src_pad,
716                             Gamepad& dst_pad,
717                             size_t axis_index,
718                             bool horizontal) {
719   size_t remapped_index = axis_index;
720   double axis_value = src_pad.axes[axis_index];
721   // The internal axis values assume a docked orientation for Joy-Cons. If a
722   // Joy-Con is used by itself, remap the axis indices and adjust the sign on
723   // the axis value for a horizontal orientation.
724   if (horizontal) {
725     switch (axis_index) {
726       case AXIS_INDEX_RIGHT_STICK_X:
727         // Map +X to +Y.
728         remapped_index = AXIS_INDEX_LEFT_STICK_Y;
729         break;
730       case AXIS_INDEX_RIGHT_STICK_Y:
731         // Map +Y to -X.
732         axis_value = -axis_value;
733         remapped_index = AXIS_INDEX_LEFT_STICK_X;
734         break;
735       default:
736         NOTREACHED();
737         break;
738     }
739   }
740   dst_pad.axes[remapped_index] = axis_value;
741 }
742 
743 // Convert the vibration parameters |frequency| and |amplitude| into a set of
744 // parameters that can be sent to the vibration actuator.
FrequencyToHex(float frequency,float amplitude,uint16_t * hf,uint8_t * lf,uint8_t * hf_amp,uint16_t * lf_amp)745 void FrequencyToHex(float frequency,
746                     float amplitude,
747                     uint16_t* hf,
748                     uint8_t* lf,
749                     uint8_t* hf_amp,
750                     uint16_t* lf_amp) {
751   int freq = static_cast<int>(frequency);
752   int amp = static_cast<int>(amplitude * kVibrationAmplitudeMax);
753   // Clamp the target frequency and amplitude to a safe range.
754   freq = base::ClampToRange(freq, kVibrationFrequencyHzMin,
755                             kVibrationFrequencyHzMax);
756   amp = base::ClampToRange(amp, 0, kVibrationAmplitudeMax);
757   const auto* best_vf = &kVibrationFrequency[0];
758   for (size_t i = 1; i < kVibrationFrequencySize; ++i) {
759     const auto* vf = &kVibrationFrequency[i];
760     if (vf->freq_hz < freq) {
761       best_vf = vf;
762     } else {
763       // The candidate frequency is higher than the target frequency. Check if
764       // it is closer than the current best.
765       int vf_error_above = vf->freq_hz - freq;
766       int best_vf_error_below = freq - best_vf->freq_hz;
767       if (vf_error_above < best_vf_error_below)
768         best_vf = vf;
769       break;
770     }
771   }
772   const auto* best_va = &kVibrationAmplitude[0];
773   for (size_t i = 0; i < kVibrationAmplitudeSize; ++i) {
774     const auto* va = &kVibrationAmplitude[i];
775     if (va->amp < amp) {
776       best_va = va;
777     } else {
778       // The candidate amplitude is higher than the target amplitude. Check if
779       // it is closer than the current best.
780       int va_error_above = va->amp - amp;
781       int best_va_error_below = amp - best_va->amp;
782       if (va_error_above < best_va_error_below)
783         best_va = va;
784       break;
785     }
786   }
787   DCHECK(best_vf);
788   DCHECK(best_va);
789   *hf = best_vf->hf;
790   *lf = best_vf->lf;
791   *hf_amp = best_va->hfa;
792   *lf_amp = best_va->lfa;
793 }
794 
795 // Return the bus type of the Switch device described by |device_info|. This is
796 // needed for Windows which does not report the bus type in the HID API.
BusTypeFromDeviceInfo(const mojom::HidDeviceInfo * device_info)797 GamepadBusType BusTypeFromDeviceInfo(const mojom::HidDeviceInfo* device_info) {
798   DCHECK(device_info);
799   // If the |device_info| indicates the device is connected over Bluetooth, it's
800   // probably right. On some platforms the bus type is reported as USB
801   // regardless of the actual connection.
802   if (device_info->bus_type == mojom::HidBusType::kHIDBusTypeBluetooth)
803     return GAMEPAD_BUS_BLUETOOTH;
804   auto gamepad_id = GamepadIdList::Get().GetGamepadId(device_info->product_name,
805                                                       device_info->vendor_id,
806                                                       device_info->product_id);
807   switch (gamepad_id) {
808     case GamepadId::kNintendoProduct2009:
809       // The Switch Pro Controller may be connected over USB or Bluetooth.
810       // Determine which connection is in use by comparing the max output report
811       // size against known values.
812       switch (device_info->max_output_report_size) {
813         case kSwitchProMaxOutputReportSizeBytesUsb:
814           return GAMEPAD_BUS_USB;
815         case kSwitchProMaxOutputReportSizeBytesBluetooth:
816           return GAMEPAD_BUS_BLUETOOTH;
817         default:
818           break;
819       }
820       break;
821     case GamepadId::kNintendoProduct200e:
822       // The Charging Grip can only be connected over USB.
823       return GAMEPAD_BUS_USB;
824     case GamepadId::kNintendoProduct2006:
825     case GamepadId::kNintendoProduct2007:
826       // Joy Cons can only be connected over Bluetooth. When connected through
827       // a Charging Grip, the grip's ID is reported instead.
828       return GAMEPAD_BUS_BLUETOOTH;
829     case GamepadId::kPowerALicPro:
830       // The PowerA controller can only be connected over Bluetooth.
831       return GAMEPAD_BUS_BLUETOOTH;
832     default:
833       break;
834   }
835   NOTREACHED();
836   return GAMEPAD_BUS_UNKNOWN;
837 }
838 }  // namespace
839 
840 NintendoController::SwitchCalibrationData::SwitchCalibrationData() = default;
841 NintendoController::SwitchCalibrationData::~SwitchCalibrationData() = default;
842 
843 NintendoController::SwitchImuData::SwitchImuData() = default;
844 NintendoController::SwitchImuData::~SwitchImuData() = default;
845 
NintendoController(int source_id,mojom::HidDeviceInfoPtr device_info,mojom::HidManager * hid_manager)846 NintendoController::NintendoController(int source_id,
847                                        mojom::HidDeviceInfoPtr device_info,
848                                        mojom::HidManager* hid_manager)
849     : source_id_(source_id),
850       is_composite_(false),
851       bus_type_(GAMEPAD_BUS_UNKNOWN),
852       output_report_size_bytes_(0),
853       device_info_(std::move(device_info)),
854       hid_manager_(hid_manager) {
855   if (device_info_) {
856     bus_type_ = BusTypeFromDeviceInfo(device_info_.get());
857     output_report_size_bytes_ = device_info_->max_output_report_size;
858     gamepad_id_ = GamepadIdList::Get().GetGamepadId(device_info_->product_name,
859                                                     device_info_->vendor_id,
860                                                     device_info_->product_id);
861   } else {
862     gamepad_id_ = GamepadId::kUnknownGamepad;
863   }
864 }
865 
NintendoController(int source_id,std::unique_ptr<NintendoController> composite1,std::unique_ptr<NintendoController> composite2,mojom::HidManager * hid_manager)866 NintendoController::NintendoController(
867     int source_id,
868     std::unique_ptr<NintendoController> composite1,
869     std::unique_ptr<NintendoController> composite2,
870     mojom::HidManager* hid_manager)
871     : source_id_(source_id), is_composite_(true), hid_manager_(hid_manager) {
872   // Require exactly one left component and one right component, but allow them
873   // to be provided in either order.
874   DCHECK(composite1);
875   DCHECK(composite2);
876   composite_left_ = std::move(composite1);
877   composite_right_ = std::move(composite2);
878   if (composite_left_->GetGamepadHand() != GamepadHand::kLeft)
879     composite_left_.swap(composite_right_);
880   DCHECK_EQ(composite_left_->GetGamepadHand(), GamepadHand::kLeft);
881   DCHECK_EQ(composite_right_->GetGamepadHand(), GamepadHand::kRight);
882   DCHECK_EQ(composite_left_->GetBusType(), composite_right_->GetBusType());
883   bus_type_ = composite_left_->GetBusType();
884 }
885 
886 NintendoController::~NintendoController() = default;
887 
888 // static
Create(int source_id,mojom::HidDeviceInfoPtr device_info,mojom::HidManager * hid_manager)889 std::unique_ptr<NintendoController> NintendoController::Create(
890     int source_id,
891     mojom::HidDeviceInfoPtr device_info,
892     mojom::HidManager* hid_manager) {
893   return std::make_unique<NintendoController>(source_id, std::move(device_info),
894                                               hid_manager);
895 }
896 
897 // static
CreateComposite(int source_id,std::unique_ptr<NintendoController> composite1,std::unique_ptr<NintendoController> composite2,mojom::HidManager * hid_manager)898 std::unique_ptr<NintendoController> NintendoController::CreateComposite(
899     int source_id,
900     std::unique_ptr<NintendoController> composite1,
901     std::unique_ptr<NintendoController> composite2,
902     mojom::HidManager* hid_manager) {
903   return std::make_unique<NintendoController>(
904       source_id, std::move(composite1), std::move(composite2), hid_manager);
905 }
906 
907 // static
IsNintendoController(GamepadId gamepad_id)908 bool NintendoController::IsNintendoController(GamepadId gamepad_id) {
909   switch (gamepad_id) {
910     case GamepadId::kNintendoProduct2006:
911     case GamepadId::kNintendoProduct2007:
912     case GamepadId::kNintendoProduct2009:
913     case GamepadId::kNintendoProduct200e:
914     case GamepadId::kPowerALicPro:
915       return true;
916     default:
917       break;
918   }
919   return false;
920 }
921 
922 std::vector<std::unique_ptr<NintendoController>>
Decompose()923 NintendoController::Decompose() {
924   // Stop any ongoing vibration effects before decomposing the device.
925   SetZeroVibration();
926 
927   std::vector<std::unique_ptr<NintendoController>> decomposed_devices;
928   if (composite_left_)
929     decomposed_devices.push_back(std::move(composite_left_));
930   if (composite_right_)
931     decomposed_devices.push_back(std::move(composite_right_));
932   return decomposed_devices;
933 }
934 
Open(base::OnceClosure device_ready_closure)935 void NintendoController::Open(base::OnceClosure device_ready_closure) {
936   device_ready_closure_ = std::move(device_ready_closure);
937   if (is_composite_) {
938     StartInitSequence();
939   } else {
940     GamepadId gamepad_id = GamepadIdList::Get().GetGamepadId(
941         device_info_->product_name, device_info_->vendor_id,
942         device_info_->product_id);
943     if (IsNintendoController(gamepad_id)) {
944       Connect(base::BindOnce(&NintendoController::OnConnect,
945                              weak_factory_.GetWeakPtr()));
946     }
947   }
948 }
949 
GetGamepadHand() const950 GamepadHand NintendoController::GetGamepadHand() const {
951   if (is_composite_)
952     return GamepadHand::kNone;
953   switch (gamepad_id_) {
954     case GamepadId::kNintendoProduct2009:
955     case GamepadId::kPowerALicPro:
956       // Switch Pro and PowerA are held in both hands.
957       return GamepadHand::kNone;
958     case GamepadId::kNintendoProduct2006:
959       // Joy-Con L is held in the left hand.
960       return GamepadHand::kLeft;
961     case GamepadId::kNintendoProduct2007:
962       // Joy-Con R is held in the right hand.
963       return GamepadHand::kRight;
964     case GamepadId::kNintendoProduct200e:
965       // Refer to |usb_device_type_| to determine the handedness of Joy-Cons
966       // connected to a Charging Grip.
967       if (state_ == kInitialized) {
968         switch (usb_device_type_) {
969           case kUsbDeviceTypeChargingGripJoyConL:
970             return GamepadHand::kLeft;
971           case kUsbDeviceTypeChargingGripJoyConR:
972             return GamepadHand::kRight;
973           case kUsbDeviceTypeChargingGripNoDevice:
974           case kUsbDeviceTypeProController:
975             return GamepadHand::kNone;
976           default:
977             break;
978         }
979       } else {
980         return GamepadHand::kNone;
981       }
982       break;
983     default:
984       break;
985   }
986   NOTREACHED();
987   return GamepadHand::kNone;
988 }
989 
IsUsable() const990 bool NintendoController::IsUsable() const {
991   if (state_ != kInitialized)
992     return false;
993   if (is_composite_)
994     return composite_left_ && composite_right_;
995   switch (gamepad_id_) {
996     case GamepadId::kNintendoProduct2009:
997     case GamepadId::kNintendoProduct2006:
998     case GamepadId::kNintendoProduct2007:
999     case GamepadId::kPowerALicPro:
1000       return true;
1001     case GamepadId::kNintendoProduct200e:
1002       // Only usable as a composite device.
1003       return false;
1004     default:
1005       break;
1006   }
1007   NOTREACHED();
1008   return false;
1009 }
1010 
HasGuid(const std::string & guid) const1011 bool NintendoController::HasGuid(const std::string& guid) const {
1012   if (is_composite_) {
1013     DCHECK(composite_left_);
1014     DCHECK(composite_right_);
1015     return composite_left_->HasGuid(guid) || composite_right_->HasGuid(guid);
1016   }
1017   return device_info_->guid == guid;
1018 }
1019 
GetMappingFunction() const1020 GamepadStandardMappingFunction NintendoController::GetMappingFunction() const {
1021   if (is_composite_) {
1022     // In composite mode, we use the same mapping as the Charging Grip.
1023     return GetGamepadStandardMappingFunction(
1024         kProductNameSwitchCompositeDevice, kVendorNintendo,
1025         kProductSwitchChargingGrip,
1026         /*hid_specification_version=*/0, /*version_number=*/0, bus_type_);
1027   } else {
1028     return GetGamepadStandardMappingFunction(
1029         device_info_->product_name, device_info_->vendor_id,
1030         device_info_->product_id,
1031 
1032         /*hid_specification_version=*/0, /*version_number=*/0, bus_type_);
1033   }
1034 }
1035 
InitializeGamepadState(bool has_standard_mapping,Gamepad & pad) const1036 void NintendoController::InitializeGamepadState(bool has_standard_mapping,
1037                                                 Gamepad& pad) const {
1038   pad.buttons_length = SWITCH_BUTTON_INDEX_COUNT;
1039   pad.axes_length = device::AXIS_INDEX_COUNT;
1040   if (gamepad_id_ == GamepadId::kPowerALicPro) {
1041     pad.vibration_actuator.not_null = false;
1042   } else {
1043     pad.vibration_actuator.type = GamepadHapticActuatorType::kDualRumble;
1044     pad.vibration_actuator.not_null = true;
1045   }
1046   pad.timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
1047   if (is_composite_) {
1048     // Composite devices use the same product ID as the Switch Charging Grip.
1049     GamepadDataFetcher::UpdateGamepadStrings(
1050         kProductNameSwitchCompositeDevice, kVendorNintendo,
1051         kProductSwitchChargingGrip, has_standard_mapping, pad);
1052   } else {
1053     GamepadDataFetcher::UpdateGamepadStrings(
1054         device_info_->product_name, device_info_->vendor_id,
1055         device_info_->product_id, has_standard_mapping, pad);
1056   }
1057 }
1058 
UpdatePadConnected()1059 void NintendoController::UpdatePadConnected() {
1060   if (is_composite_) {
1061     // Composite devices are always connected.
1062     pad_.connected = true;
1063     return;
1064   }
1065 
1066   if (gamepad_id_ == GamepadId::kNintendoProduct200e &&
1067       usb_device_type_ == kUsbDeviceTypeChargingGripNoDevice) {
1068     // If the Charging Grip reports that no Joy-Con is docked, mark the gamepad
1069     // disconnected.
1070     pad_.connected = false;
1071     return;
1072   }
1073 
1074   // All other devices are considered connected after completing initialization.
1075   pad_.connected = (state_ == kInitialized);
1076 }
1077 
UpdateGamepadState(Gamepad & pad) const1078 void NintendoController::UpdateGamepadState(Gamepad& pad) const {
1079   if (is_composite_) {
1080     DCHECK(composite_left_);
1081     DCHECK(composite_right_);
1082     // If this is a composite device, update the gamepad state using the state
1083     // of the subcomponents.
1084     pad.connected = true;
1085     composite_left_->UpdateLeftGamepadState(pad, false);
1086     composite_right_->UpdateRightGamepadState(pad, false);
1087   } else {
1088     switch (GetGamepadHand()) {
1089       case GamepadHand::kLeft:
1090         // Update state for a Joy-Con L, remapping buttons and axes to match the
1091         // Standard Gamepad when the device is held horizontally.
1092         UpdateLeftGamepadState(pad, true);
1093         break;
1094       case GamepadHand::kRight:
1095         // Update state for a Joy-Con R, remapping buttons and axes to match the
1096         // Standard Gamepad when the device is held horizontally.
1097         UpdateRightGamepadState(pad, true);
1098         break;
1099       case GamepadHand::kNone:
1100         // Update state for a Pro Controller.
1101         UpdateLeftGamepadState(pad, false);
1102         UpdateRightGamepadState(pad, false);
1103         break;
1104       default:
1105         NOTREACHED();
1106         break;
1107     }
1108     pad.connected = pad_.connected;
1109   }
1110 }
1111 
UpdateLeftGamepadState(Gamepad & pad,bool horizontal) const1112 void NintendoController::UpdateLeftGamepadState(Gamepad& pad,
1113                                                 bool horizontal) const {
1114   // Buttons associated with the left Joy-Con.
1115   const size_t kLeftButtonIndices[] = {
1116       BUTTON_INDEX_LEFT_SHOULDER,  // ZL button
1117       BUTTON_INDEX_LEFT_TRIGGER,   // L button
1118       BUTTON_INDEX_BACK_SELECT,    // - button
1119       BUTTON_INDEX_LEFT_THUMBSTICK,
1120       BUTTON_INDEX_DPAD_UP,    // D-pad directions for the composite gamepad
1121       BUTTON_INDEX_DPAD_DOWN,  // assume the Joy-Con is held in the vertical
1122       BUTTON_INDEX_DPAD_LEFT,  // orientation or is attached to a grip.
1123       BUTTON_INDEX_DPAD_RIGHT,      SWITCH_BUTTON_INDEX_CAPTURE,
1124       SWITCH_BUTTON_INDEX_LEFT_SL,  SWITCH_BUTTON_INDEX_LEFT_SR,
1125   };
1126   const size_t kLeftButtonIndicesSize = base::size(kLeftButtonIndices);
1127 
1128   // Axes associated with the left Joy-Con thumbstick.
1129   const size_t kLeftAxisIndices[] = {
1130       AXIS_INDEX_LEFT_STICK_X,  // Axes assume the Joy-Con is held vertically
1131       AXIS_INDEX_LEFT_STICK_Y,  // or is attached to a grip.
1132   };
1133   const size_t kLeftAxisIndicesSize = base::size(kLeftAxisIndices);
1134 
1135   if (pad_.buttons_length == SWITCH_BUTTON_INDEX_COUNT) {
1136     for (size_t i = 0; i < kLeftButtonIndicesSize; ++i)
1137       UpdateButtonForLeftSide(pad_, pad, kLeftButtonIndices[i], horizontal);
1138   }
1139   if (pad_.axes_length == AXIS_INDEX_COUNT) {
1140     for (size_t i = 0; i < kLeftAxisIndicesSize; ++i)
1141       UpdateAxisForLeftSide(pad_, pad, kLeftAxisIndices[i], horizontal);
1142   }
1143   pad.timestamp = std::max(pad.timestamp, pad_.timestamp);
1144   if (!pad_.connected)
1145     pad.connected = false;
1146 }
1147 
UpdateRightGamepadState(Gamepad & pad,bool horizontal) const1148 void NintendoController::UpdateRightGamepadState(Gamepad& pad,
1149                                                  bool horizontal) const {
1150   // Buttons associated with the right Joy-Con.
1151   const size_t kRightButtonIndices[]{
1152       BUTTON_INDEX_PRIMARY,         // B button
1153       BUTTON_INDEX_SECONDARY,       // A button
1154       BUTTON_INDEX_TERTIARY,        // Y button
1155       BUTTON_INDEX_QUATERNARY,      // X button
1156       BUTTON_INDEX_RIGHT_SHOULDER,  // R button
1157       BUTTON_INDEX_RIGHT_TRIGGER,   // ZR button
1158       BUTTON_INDEX_START,           // + button
1159       BUTTON_INDEX_RIGHT_THUMBSTICK,
1160       BUTTON_INDEX_META,  // Home button
1161       SWITCH_BUTTON_INDEX_RIGHT_SL,
1162       SWITCH_BUTTON_INDEX_RIGHT_SR,
1163   };
1164   const size_t kRightButtonIndicesSize = base::size(kRightButtonIndices);
1165 
1166   // Axes associated with the right Joy-Con thumbstick.
1167   const size_t kRightAxisIndices[] = {
1168       AXIS_INDEX_RIGHT_STICK_X,  // Axes assume the Joy-Con is held vertically
1169       AXIS_INDEX_RIGHT_STICK_Y,  // or is attached to a grip.
1170   };
1171   const size_t kRightAxisIndicesSize = base::size(kRightAxisIndices);
1172 
1173   if (pad_.buttons_length == SWITCH_BUTTON_INDEX_COUNT) {
1174     for (size_t i = 0; i < kRightButtonIndicesSize; ++i)
1175       UpdateButtonForRightSide(pad_, pad, kRightButtonIndices[i], horizontal);
1176   }
1177   if (pad_.axes_length == AXIS_INDEX_COUNT) {
1178     for (size_t i = 0; i < kRightAxisIndicesSize; ++i)
1179       UpdateAxisForRightSide(pad_, pad, kRightAxisIndices[i], horizontal);
1180   }
1181   pad.timestamp = std::max(pad.timestamp, pad_.timestamp);
1182   if (!pad_.connected)
1183     pad.connected = false;
1184 }
1185 
Connect(mojom::HidManager::ConnectCallback callback)1186 void NintendoController::Connect(mojom::HidManager::ConnectCallback callback) {
1187   DCHECK(!is_composite_);
1188   DCHECK(hid_manager_);
1189   hid_manager_->Connect(device_info_->guid,
1190                         /*connection_client=*/mojo::NullRemote(),
1191                         /*watcher=*/mojo::NullRemote(), std::move(callback));
1192 }
1193 
OnConnect(mojo::PendingRemote<mojom::HidConnection> connection)1194 void NintendoController::OnConnect(
1195     mojo::PendingRemote<mojom::HidConnection> connection) {
1196   if (connection) {
1197     connection_.Bind(std::move(connection));
1198     ReadInputReport();
1199     StartInitSequence();
1200   }
1201 }
1202 
StartInitSequence()1203 void NintendoController::StartInitSequence() {
1204   if (is_composite_) {
1205     if (composite_left_ && composite_left_->IsOpen() && composite_right_ &&
1206         composite_right_->IsOpen()) {
1207       DCHECK_EQ(composite_left_->GetGamepadHand(), GamepadHand::kLeft);
1208       DCHECK_EQ(composite_right_->GetGamepadHand(), GamepadHand::kRight);
1209       FinishInitSequence();
1210     } else {
1211       FailInitSequence();
1212     }
1213     return;
1214   }
1215 
1216   switch (bus_type_) {
1217     case GAMEPAD_BUS_USB:
1218       DCHECK(timeout_callback_.IsCancelled());
1219       MakeInitSequenceRequests(kPendingMacAddress);
1220       break;
1221     case GAMEPAD_BUS_BLUETOOTH:
1222       DCHECK(timeout_callback_.IsCancelled());
1223       MakeInitSequenceRequests(kPendingSetPlayerLights);
1224       break;
1225     default:
1226       NOTREACHED();
1227       break;
1228   }
1229 }
1230 
FinishInitSequence()1231 void NintendoController::FinishInitSequence() {
1232   state_ = kInitialized;
1233   UpdatePadConnected();
1234   if (device_ready_closure_)
1235     std::move(device_ready_closure_).Run();
1236 }
1237 
FailInitSequence()1238 void NintendoController::FailInitSequence() {
1239   state_ = kUninitialized;
1240   UpdatePadConnected();
1241 }
1242 
HandleInputReport(uint8_t report_id,const std::vector<uint8_t> & report_bytes)1243 void NintendoController::HandleInputReport(
1244     uint8_t report_id,
1245     const std::vector<uint8_t>& report_bytes) {
1246   // Register to receive the next input report.
1247   ReadInputReport();
1248 
1249   // Listen for reports related to the initialization sequence or gamepad state.
1250   // Other reports are ignored.
1251   if (bus_type_ == GAMEPAD_BUS_USB && report_id == kUsbReportIdInput81)
1252     HandleUsbInputReport81(report_bytes);
1253   else if (report_id == kReportIdInput21)
1254     HandleInputReport21(report_bytes);
1255   else if (report_id == kReportIdInput30)
1256     HandleInputReport30(report_bytes);
1257 
1258   // Check whether the input report should cause us to transition to the next
1259   // initialization step.
1260   if (state_ != kInitialized && state_ != kUninitialized)
1261     ContinueInitSequence(report_id, report_bytes);
1262 }
1263 
HandleUsbInputReport81(const std::vector<uint8_t> & report_bytes)1264 void NintendoController::HandleUsbInputReport81(
1265     const std::vector<uint8_t>& report_bytes) {
1266   const auto* ack_report =
1267       reinterpret_cast<const UsbInputReport81*>(report_bytes.data());
1268   switch (ack_report->subtype) {
1269     case kSubTypeRequestMac: {
1270       const auto* mac_report =
1271           reinterpret_cast<const MacAddressReport*>(report_bytes.data());
1272       mac_address_ = UnpackSwitchMacAddress(mac_report->mac_data);
1273       if (usb_device_type_ != mac_report->device_type) {
1274         usb_device_type_ = mac_report->device_type;
1275         switch (usb_device_type_) {
1276           case kUsbDeviceTypeChargingGripNoDevice:
1277             UpdatePadConnected();
1278             // If this was received from an initialized gamepad it means one of
1279             // the Joy-Cons was disconnected from the charging grip. The HID
1280             // device does not disconnect; de-initialize the device so the
1281             // composite device will be hidden.
1282             if (state_ == kInitialized)
1283               FailInitSequence();
1284             break;
1285           case kUsbDeviceTypeChargingGripJoyConL:
1286           case kUsbDeviceTypeChargingGripJoyConR:
1287             UpdatePadConnected();
1288             // A Joy-Con was connected to a de-initialized device. Restart the
1289             // initialization sequence.
1290             if (state_ == kUninitialized)
1291               StartInitSequence();
1292             break;
1293           default:
1294             break;
1295         }
1296       }
1297       break;
1298     }
1299     default:
1300       break;
1301   }
1302 }
1303 
HandleInputReport21(const std::vector<uint8_t> & report_bytes)1304 void NintendoController::HandleInputReport21(
1305     const std::vector<uint8_t>& report_bytes) {
1306   const auto* spi_report =
1307       reinterpret_cast<const SpiReadReport*>(report_bytes.data());
1308   if (UpdateGamepadFromControllerData(spi_report->controller_data, cal_data_,
1309                                       pad_)) {
1310     pad_.timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
1311   }
1312   // The input report includes the parameters for the SPI read request along
1313   // with the data that was read. Use the read address to determine how to
1314   // unpack the data.
1315   if (spi_report->subcommand == kSubCommandReadSpi) {
1316     uint16_t address = (spi_report->addrh << 8) | spi_report->addrl;
1317     switch (address) {
1318       case kSpiImuCalibrationAddress:
1319         UnpackSwitchImuCalibration(spi_report->spi_data, cal_data_);
1320         break;
1321       case kSpiImuHorizontalOffsetsAddress:
1322         UnpackSwitchImuHorizontalOffsets(spi_report->spi_data, cal_data_);
1323         break;
1324       case kSpiAnalogStickCalibrationAddress:
1325         UnpackSwitchAnalogStickCalibration(spi_report->spi_data, cal_data_);
1326         break;
1327       case kSpiAnalogStickParametersAddress:
1328         UnpackSwitchAnalogStickParameters(spi_report->spi_data, cal_data_);
1329         break;
1330       default:
1331         break;
1332     }
1333   }
1334 }
1335 
HandleInputReport30(const std::vector<uint8_t> & report_bytes)1336 void NintendoController::HandleInputReport30(
1337     const std::vector<uint8_t>& report_bytes) {
1338   const auto* controller_report =
1339       reinterpret_cast<const ControllerDataReport*>(report_bytes.data());
1340   // Each input report contains three frames of IMU data.
1341   UnpackSwitchImuData(&controller_report->imu_data[0], &imu_data_[0]);
1342   UnpackSwitchImuData(&controller_report->imu_data[12], &imu_data_[1]);
1343   UnpackSwitchImuData(&controller_report->imu_data[24], &imu_data_[2]);
1344   if (UpdateGamepadFromControllerData(controller_report->controller_data,
1345                                       cal_data_, pad_)) {
1346     pad_.timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
1347   }
1348 }
1349 
ContinueInitSequence(uint8_t report_id,const std::vector<uint8_t> & report_bytes)1350 void NintendoController::ContinueInitSequence(
1351     uint8_t report_id,
1352     const std::vector<uint8_t>& report_bytes) {
1353   const auto* ack_report =
1354       reinterpret_cast<const UsbInputReport81*>(report_bytes.data());
1355   const auto* spi_report =
1356       reinterpret_cast<const SpiReadReport*>(report_bytes.data());
1357   const uint8_t ack_subtype =
1358       (report_id == kUsbReportIdInput81) ? ack_report->subtype : 0;
1359   const uint8_t spi_subcommand =
1360       (report_id == kReportIdInput21) ? spi_report->subcommand : 0;
1361   const bool is_spi_read =
1362       (report_id == kReportIdInput21 && spi_subcommand == kSubCommandReadSpi);
1363   const uint16_t spi_read_address =
1364       is_spi_read ? ((spi_report->addrh << 8) | spi_report->addrl) : 0;
1365   const uint16_t spi_read_length = is_spi_read ? spi_report->length : 0;
1366 
1367   switch (state_) {
1368     case kPendingMacAddress:
1369       if (ack_subtype == kSubTypeRequestMac) {
1370         CancelTimeout();
1371         if (mac_address_)
1372           MakeInitSequenceRequests(kPendingHandshake1);
1373         else
1374           FailInitSequence();
1375       }
1376       break;
1377     case kPendingHandshake1:
1378       if (ack_subtype == kSubTypeHandshake) {
1379         CancelTimeout();
1380         MakeInitSequenceRequests(kPendingBaudRate);
1381       }
1382       break;
1383     case kPendingBaudRate:
1384       if (ack_subtype == kSubTypeBaudRate) {
1385         CancelTimeout();
1386         MakeInitSequenceRequests(kPendingHandshake2);
1387       }
1388       break;
1389     case kPendingHandshake2:
1390       if (ack_subtype == kSubTypeHandshake) {
1391         CancelTimeout();
1392         MakeInitSequenceRequests(kPendingDisableUsbTimeout);
1393       }
1394       break;
1395     case kPendingDisableUsbTimeout:
1396       if (spi_subcommand == kSubCommand33) {
1397         CancelTimeout();
1398         MakeInitSequenceRequests(kPendingSetPlayerLights);
1399       }
1400       break;
1401     case kPendingSetPlayerLights:
1402       if (spi_subcommand == kSubCommandSetPlayerLights) {
1403         CancelTimeout();
1404         MakeInitSequenceRequests(kPendingEnableImu);
1405       }
1406       break;
1407     case kPendingEnableImu:
1408       if (spi_subcommand == kSubCommandEnableImu) {
1409         CancelTimeout();
1410         MakeInitSequenceRequests(kPendingSetImuSensitivity);
1411       }
1412       break;
1413     case kPendingSetImuSensitivity:
1414       if (spi_subcommand == kSubCommandSetImuSensitivity) {
1415         CancelTimeout();
1416         MakeInitSequenceRequests(kPendingReadImuCalibration);
1417       }
1418       break;
1419     case kPendingReadImuCalibration:
1420       if (spi_read_address == kSpiImuCalibrationAddress &&
1421           spi_read_length == kSpiImuCalibrationSize) {
1422         CancelTimeout();
1423         MakeInitSequenceRequests(kPendingReadHorizontalOffsets);
1424       }
1425       break;
1426     case kPendingReadHorizontalOffsets:
1427       if (spi_read_address == kSpiImuHorizontalOffsetsAddress &&
1428           spi_read_length == kSpiImuHorizontalOffsetsSize) {
1429         CancelTimeout();
1430         MakeInitSequenceRequests(kPendingReadAnalogStickCalibration);
1431       }
1432       break;
1433     case kPendingReadAnalogStickCalibration:
1434       if (spi_read_address == kSpiAnalogStickCalibrationAddress &&
1435           spi_read_length == kSpiAnalogStickCalibrationSize) {
1436         CancelTimeout();
1437         MakeInitSequenceRequests(kPendingReadAnalogStickParameters);
1438       }
1439       break;
1440     case kPendingReadAnalogStickParameters:
1441       if (spi_read_address == kSpiAnalogStickParametersAddress &&
1442           spi_read_length == kSpiAnalogStickParametersSize) {
1443         CancelTimeout();
1444         MakeInitSequenceRequests(kPendingEnableVibration);
1445       }
1446       break;
1447     case kPendingEnableVibration:
1448       if (spi_subcommand == kSubCommandEnableVibration) {
1449         CancelTimeout();
1450         // PowerA controller doesn't have a home light and trying to set it will
1451         // fail, so skip this step.
1452         if (gamepad_id_ == GamepadId::kPowerALicPro) {
1453           MakeInitSequenceRequests(kPendingSetInputReportMode);
1454         } else {
1455           MakeInitSequenceRequests(kPendingSetHomeLight);
1456         }
1457       }
1458       break;
1459     case kPendingSetHomeLight:
1460       if (spi_subcommand == kSubCommandSetHomeLight) {
1461         CancelTimeout();
1462         MakeInitSequenceRequests(kPendingSetInputReportMode);
1463       }
1464       break;
1465     case kPendingSetInputReportMode:
1466       if (spi_subcommand == kSubCommandSetInputReportMode) {
1467         CancelTimeout();
1468         MakeInitSequenceRequests(kPendingControllerData);
1469       }
1470       break;
1471     case kPendingControllerData:
1472       if (report_id == kReportIdInput30) {
1473         CancelTimeout();
1474         FinishInitSequence();
1475       }
1476       break;
1477     case kInitialized:
1478     case kUninitialized:
1479       NOTREACHED();
1480       break;
1481     default:
1482       break;
1483   }
1484 }
1485 
MakeInitSequenceRequests(InitializationState state)1486 void NintendoController::MakeInitSequenceRequests(InitializationState state) {
1487   DCHECK(timeout_callback_.IsCancelled());
1488   state_ = state;
1489   switch (state_) {
1490     case kPendingMacAddress:
1491       RequestMacAddress();
1492       break;
1493     case kPendingHandshake1:
1494     case kPendingHandshake2:
1495       RequestHandshake();
1496       break;
1497     case kPendingBaudRate:
1498       RequestBaudRate();
1499       break;
1500     case kPendingDisableUsbTimeout:
1501       RequestEnableUsbTimeout(false);
1502       break;
1503     case kPendingSetPlayerLights:
1504       RequestSetPlayerLights(kPlayerLightPattern1);  // Player 1 indicator on.
1505       break;
1506     case kPendingEnableImu:
1507       RequestEnableImu(false);  // IMU disabled.
1508       break;
1509     case kPendingSetImuSensitivity:
1510       RequestSetImuSensitivity(
1511           kGyroSensitivity2000Dps, kAccelerometerSensitivity8G,
1512           kGyroPerformance208Hz, kAccelerometerFilterBandwidth100Hz);
1513       break;
1514     case kPendingReadImuCalibration:
1515       RequestImuCalibration();
1516       break;
1517     case kPendingReadHorizontalOffsets:
1518       RequestHorizontalOffsets();
1519       break;
1520     case kPendingReadAnalogStickCalibration:
1521       RequestAnalogCalibration();
1522       break;
1523     case kPendingReadAnalogStickParameters:
1524       RequestAnalogParameters();
1525       break;
1526     case kPendingEnableVibration:
1527       RequestEnableVibration(true);
1528       break;
1529     case kPendingSetHomeLight:
1530       RequestSetHomeLightIntensity(1.0);  // 100% intensity.
1531       break;
1532     case kPendingSetInputReportMode:
1533       RequestSetInputReportMode(0x30);  // Standard full mode reported at 60Hz.
1534       break;
1535     case kPendingControllerData:
1536       ArmTimeout();
1537       break;
1538     case kInitialized:
1539     case kUninitialized:
1540     default:
1541       NOTREACHED();
1542       break;
1543   }
1544 }
1545 
SubCommand(uint8_t sub_command,const std::vector<uint8_t> & bytes)1546 void NintendoController::SubCommand(uint8_t sub_command,
1547                                     const std::vector<uint8_t>& bytes) {
1548   std::vector<uint8_t> report_bytes(output_report_size_bytes_ - 1);
1549   // Serial subcommands also carry vibration data. Configure the vibration
1550   // portion of the report for a neutral vibration effect (zero amplitude).
1551   // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/bluetooth_hid_notes.md#output-0x12
1552   report_bytes[0] = uint8_t{output_report_counter_++ & 0xff};
1553   report_bytes[1] = 0x00;
1554   report_bytes[2] = 0x01;
1555   report_bytes[3] = 0x40;
1556   report_bytes[4] = 0x40;
1557   report_bytes[5] = 0x00;
1558   report_bytes[6] = 0x01;
1559   report_bytes[7] = 0x40;
1560   report_bytes[8] = 0x40;
1561   report_bytes[9] = sub_command;
1562   DCHECK_LT(bytes.size() + kSubCommandDataOffset, output_report_size_bytes_);
1563   std::copy(bytes.begin(), bytes.end(),
1564             &report_bytes[kSubCommandDataOffset - 1]);
1565   WriteOutputReport(kReportIdOutput01, report_bytes, true);
1566 }
1567 
RequestMacAddress()1568 void NintendoController::RequestMacAddress() {
1569   std::vector<uint8_t> report_bytes(output_report_size_bytes_ - 1);
1570   report_bytes[0] = kSubTypeRequestMac;
1571   WriteOutputReport(kUsbReportIdOutput80, report_bytes, true);
1572 }
1573 
RequestHandshake()1574 void NintendoController::RequestHandshake() {
1575   std::vector<uint8_t> report_bytes(output_report_size_bytes_ - 1);
1576   report_bytes[0] = kSubTypeHandshake;
1577   WriteOutputReport(kUsbReportIdOutput80, report_bytes, true);
1578 }
1579 
RequestBaudRate()1580 void NintendoController::RequestBaudRate() {
1581   std::vector<uint8_t> report_bytes(output_report_size_bytes_ - 1);
1582   report_bytes[0] = kSubTypeBaudRate;
1583   WriteOutputReport(kUsbReportIdOutput80, report_bytes, true);
1584 }
1585 
RequestSubCommand33()1586 void NintendoController::RequestSubCommand33() {
1587   // Unrecognized commands do nothing, but still generate a reply.
1588   SubCommand(kSubCommand33, {});
1589 }
1590 
RequestVibration(double left_frequency,double left_magnitude,double right_frequency,double right_magnitude)1591 void NintendoController::RequestVibration(double left_frequency,
1592                                           double left_magnitude,
1593                                           double right_frequency,
1594                                           double right_magnitude) {
1595   uint16_t lhf;
1596   uint8_t llf;
1597   uint8_t lhfa;
1598   uint16_t llfa;
1599   uint16_t rhf;
1600   uint8_t rlf;
1601   uint8_t rhfa;
1602   uint16_t rlfa;
1603   FrequencyToHex(left_frequency, left_magnitude, &lhf, &llf, &lhfa, &llfa);
1604   FrequencyToHex(right_frequency, right_magnitude, &rhf, &rlf, &rhfa, &rlfa);
1605   std::vector<uint8_t> report_bytes(output_report_size_bytes_ - 1);
1606   uint8_t counter = uint8_t{output_report_counter_++ & 0x0f};
1607   report_bytes[0] = counter;
1608   report_bytes[1] = lhf & 0xff;
1609   report_bytes[2] = lhfa + ((lhf >> 8) & 0xff);
1610   report_bytes[3] = llf + ((llfa >> 8) & 0xff);
1611   report_bytes[4] = llfa & 0xff;
1612   report_bytes[5] = rhf & 0xff;
1613   report_bytes[6] = rhfa + ((rhf >> 8) & 0xff);
1614   report_bytes[7] = rlf + ((rlfa >> 8) & 0xff);
1615   report_bytes[8] = rlfa & 0xff;
1616   WriteOutputReport(kReportIdOutput10, report_bytes, false);
1617 }
1618 
RequestEnableUsbTimeout(bool enable)1619 void NintendoController::RequestEnableUsbTimeout(bool enable) {
1620   // By default, Switch Pro will revert to Bluetooth mode if it does not
1621   // receive any USB HID commands within a timeout window. Disabling the
1622   // timeout keeps the device in USB mode.
1623   std::vector<uint8_t> report_bytes(output_report_size_bytes_ - 1);
1624   report_bytes[0] =
1625       enable ? kSubTypeEnableUsbTimeout : kSubTypeDisableUsbTimeout;
1626   // This report may not be acked due to a software bug on the device.
1627   WriteOutputReport(kUsbReportIdOutput80, report_bytes, false);
1628   // Send an unused subcommand (0x33) which is acked.
1629   RequestSubCommand33();
1630 }
1631 
RequestEnableImu(bool enable)1632 void NintendoController::RequestEnableImu(bool enable) {
1633   SubCommand(kSubCommandEnableImu, {enable ? 0x01 : 0x00});
1634 }
1635 
RequestEnableVibration(bool enable)1636 void NintendoController::RequestEnableVibration(bool enable) {
1637   SubCommand(kSubCommandEnableVibration, {enable ? 0x01 : 0x00});
1638 }
1639 
RequestSetPlayerLights(uint8_t light_pattern)1640 void NintendoController::RequestSetPlayerLights(uint8_t light_pattern) {
1641   SubCommand(kSubCommandSetPlayerLights, {light_pattern});
1642 }
1643 
RequestSetHomeLight(uint8_t minicycle_count,uint8_t minicycle_duration,uint8_t start_intensity,uint8_t cycle_count,const std::vector<uint8_t> & minicycle_data)1644 void NintendoController::RequestSetHomeLight(
1645     uint8_t minicycle_count,
1646     uint8_t minicycle_duration,
1647     uint8_t start_intensity,
1648     uint8_t cycle_count,
1649     const std::vector<uint8_t>& minicycle_data) {
1650   DCHECK_LE(minicycle_count, 0xf);
1651   DCHECK_LE(minicycle_duration, 0xf);
1652   DCHECK_LE(start_intensity, 0xf);
1653   DCHECK_LE(cycle_count, 0xf);
1654   if ((cycle_count > 0 && minicycle_count == 1) || minicycle_duration == 0)
1655     minicycle_count = 0;
1656   std::vector<uint8_t> bytes = {(minicycle_count << 4) | minicycle_duration,
1657                                 (start_intensity << 4) | cycle_count};
1658   bytes.insert(bytes.end(), minicycle_data.begin(), minicycle_data.end());
1659   SubCommand(kSubCommandSetHomeLight, bytes);
1660 }
1661 
RequestSetHomeLightIntensity(double intensity)1662 void NintendoController::RequestSetHomeLightIntensity(double intensity) {
1663   intensity = base::ClampToRange(intensity, 0.0, 1.0);
1664   uint8_t led_intensity = std::round(intensity * 0x0f);
1665   // Each pair of bytes in the minicycle data describes two minicyles.
1666   // The first byte holds two 4-bit values encoding minicycle intensities.
1667   // The second byte holds two 4-bit multipliers for the duration of each
1668   // transition.
1669   //
1670   // This command encodes one minicycle that transitions to 100% intensity after
1671   // 1x minicycle duration. Because |minicycle_count| and |cycle_count| are
1672   // both zero, the device will transition to the 1st minicycle and then stay at
1673   // |led_intensity|.
1674   RequestSetHomeLight(0, 1, led_intensity, 0, {led_intensity << 4, 0x00});
1675 }
1676 
RequestSetImuSensitivity(uint8_t gyro_sensitivity,uint8_t accelerometer_sensitivity,uint8_t gyro_performance_rate,uint8_t accelerometer_filter_bandwidth)1677 void NintendoController::RequestSetImuSensitivity(
1678     uint8_t gyro_sensitivity,
1679     uint8_t accelerometer_sensitivity,
1680     uint8_t gyro_performance_rate,
1681     uint8_t accelerometer_filter_bandwidth) {
1682   SubCommand(kSubCommandSetImuSensitivity,
1683              {gyro_sensitivity, accelerometer_sensitivity,
1684               gyro_performance_rate, accelerometer_filter_bandwidth});
1685 }
1686 
RequestSetInputReportMode(uint8_t mode)1687 void NintendoController::RequestSetInputReportMode(uint8_t mode) {
1688   SubCommand(kSubCommandSetInputReportMode, {mode});
1689 }
1690 
ReadSpi(uint16_t address,size_t length)1691 void NintendoController::ReadSpi(uint16_t address, size_t length) {
1692   DCHECK_LE(length + kSpiDataOffset, output_report_size_bytes_);
1693   length = std::min(length, output_report_size_bytes_ - kSpiDataOffset);
1694   uint8_t address_high = (address >> 8) & 0xff;
1695   uint8_t address_low = address & 0xff;
1696   SubCommand(kSubCommandReadSpi,
1697              {address_low, address_high, 0x00, 0x00, uint8_t{length}});
1698 }
1699 
RequestImuCalibration()1700 void NintendoController::RequestImuCalibration() {
1701   ReadSpi(kSpiImuCalibrationAddress, kSpiImuCalibrationSize);
1702 }
1703 
RequestHorizontalOffsets()1704 void NintendoController::RequestHorizontalOffsets() {
1705   ReadSpi(kSpiImuHorizontalOffsetsAddress, kSpiImuHorizontalOffsetsSize);
1706 }
1707 
RequestAnalogCalibration()1708 void NintendoController::RequestAnalogCalibration() {
1709   ReadSpi(kSpiAnalogStickCalibrationAddress, kSpiAnalogStickCalibrationSize);
1710 }
1711 
RequestAnalogParameters()1712 void NintendoController::RequestAnalogParameters() {
1713   ReadSpi(kSpiAnalogStickParametersAddress, kSpiAnalogStickParametersSize);
1714 }
1715 
ReadInputReport()1716 void NintendoController::ReadInputReport() {
1717   DCHECK(connection_);
1718   connection_->Read(base::BindOnce(&NintendoController::OnReadInputReport,
1719                                    weak_factory_.GetWeakPtr()));
1720 }
1721 
OnReadInputReport(bool success,uint8_t report_id,const base::Optional<std::vector<uint8_t>> & report_bytes)1722 void NintendoController::OnReadInputReport(
1723     bool success,
1724     uint8_t report_id,
1725     const base::Optional<std::vector<uint8_t>>& report_bytes) {
1726   if (success) {
1727     DCHECK(report_bytes);
1728     HandleInputReport(report_id, *report_bytes);
1729   } else {
1730     CancelTimeout();
1731     FailInitSequence();
1732   }
1733 }
1734 
WriteOutputReport(uint8_t report_id,const std::vector<uint8_t> & report_bytes,bool expect_reply)1735 void NintendoController::WriteOutputReport(
1736     uint8_t report_id,
1737     const std::vector<uint8_t>& report_bytes,
1738     bool expect_reply) {
1739   DCHECK(connection_);
1740   DCHECK(timeout_callback_.IsCancelled());
1741   connection_->Write(report_id, report_bytes,
1742                      base::BindOnce(&NintendoController::OnWriteOutputReport,
1743                                     weak_factory_.GetWeakPtr()));
1744   if (expect_reply)
1745     ArmTimeout();
1746 }
1747 
OnWriteOutputReport(bool success)1748 void NintendoController::OnWriteOutputReport(bool success) {
1749   if (!success) {
1750     CancelTimeout();
1751     FailInitSequence();
1752   }
1753 }
1754 
DoShutdown()1755 void NintendoController::DoShutdown() {
1756   if (composite_left_)
1757     composite_left_->Shutdown();
1758   composite_left_.reset();
1759   if (composite_right_)
1760     composite_right_->Shutdown();
1761   composite_right_.reset();
1762   connection_.reset();
1763   device_info_.reset();
1764 }
1765 
SetVibration(double strong_magnitude,double weak_magnitude)1766 void NintendoController::SetVibration(double strong_magnitude,
1767                                       double weak_magnitude) {
1768   if (is_composite_) {
1769     // Split the vibration effect between the left and right subdevices.
1770     if (composite_left_ && composite_right_) {
1771       composite_left_->SetVibration(strong_magnitude, 0);
1772       composite_right_->SetVibration(0, weak_magnitude);
1773     }
1774   } else {
1775     RequestVibration(kVibrationFrequencyStrongRumble,
1776                      kVibrationAmplitudeStrongRumbleMax * strong_magnitude,
1777                      kVibrationFrequencyWeakRumble,
1778                      kVibrationAmplitudeWeakRumbleMax * weak_magnitude);
1779   }
1780 }
1781 
GetMaxEffectDurationMillis()1782 double NintendoController::GetMaxEffectDurationMillis() {
1783   return kMaxVibrationEffectDurationMillis;
1784 }
1785 
ArmTimeout()1786 void NintendoController::ArmTimeout() {
1787   DCHECK(timeout_callback_.IsCancelled());
1788   timeout_callback_.Reset(base::BindOnce(&NintendoController::OnTimeout,
1789                                          weak_factory_.GetWeakPtr()));
1790   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1791       FROM_HERE, timeout_callback_.callback(), kTimeoutDuration);
1792 }
1793 
CancelTimeout()1794 void NintendoController::CancelTimeout() {
1795   timeout_callback_.Cancel();
1796   retry_count_ = 0;
1797 }
1798 
OnTimeout()1799 void NintendoController::OnTimeout() {
1800   ++retry_count_;
1801   if (retry_count_ <= kMaxRetryCount)
1802     MakeInitSequenceRequests(state_);
1803   else {
1804     retry_count_ = 0;
1805     StartInitSequence();
1806   }
1807 }
1808 
GetWeakPtr()1809 base::WeakPtr<AbstractHapticGamepad> NintendoController::GetWeakPtr() {
1810   return weak_factory_.GetWeakPtr();
1811 }
1812 
1813 }  // namespace device
1814