USB Host Shield 2.0
Wii.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16 
17  IR camera support added by Allan Glover (adglover9.81@gmail.com) and Kristian Lauszus
18  */
19 
20 #include "Wii.h"
21 // To enable serial debugging see "settings.h"
22 //#define EXTRADEBUG // Uncomment to get even more debugging data
23 //#define PRINTREPORT // Uncomment to print the report send by the Wii controllers
24 
25 const uint8_t WII_LEDS[] PROGMEM = {
26  0x00, // OFF
27  0x10, // LED1
28  0x20, // LED2
29  0x40, // LED3
30  0x80, // LED4
31 
32  0x90, // LED5
33  0xA0, // LED6
34  0xC0, // LED7
35  0xD0, // LED8
36  0xE0, // LED9
37  0xF0, // LED10
38 };
39 
40 const uint32_t WII_BUTTONS[] PROGMEM = {
41  0x00008, // UP
42  0x00002, // RIGHT
43  0x00004, // DOWN
44  0x00001, // LEFT
45 
46  0, // Skip
47  0x00010, // PLUS
48  0x00100, // TWO
49  0x00200, // ONE
50 
51  0x01000, // MINUS
52  0x08000, // HOME
53  0x10000, // Z
54  0x20000, // C
55 
56  0x00400, // B
57  0x00800, // A
58 };
59 const uint32_t WII_PROCONTROLLER_BUTTONS[] PROGMEM = {
60  0x00100, // UP
61  0x00080, // RIGHT
62  0x00040, // DOWN
63  0x00200, // LEFT
64 
65  0, // Skip
66  0x00004, // PLUS
67  0x20000, // L3
68  0x10000, // R3
69 
70  0x00010, // MINUS
71  0x00008, // HOME
72  0, 0, // Skip
73 
74  0x04000, // B
75  0x01000, // A
76  0x00800, // X
77  0x02000, // Y
78 
79  0x00020, // L
80  0x00002, // R
81  0x08000, // ZL
82  0x00400, // ZR
83 };
84 
85 WII::WII(BTD *p, bool pair) :
86 BluetoothService(p) // Pointer to USB class instance - mandatory
87 {
89 
90  HIDBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
91 
92  /* Set device cid for the control and intterrupt channelse - LSB */
93  control_dcid[0] = 0x60; // 0x0060
94  control_dcid[1] = 0x00;
95  interrupt_dcid[0] = 0x61; // 0x0061
96  interrupt_dcid[1] = 0x00;
97 
98  Reset();
99 }
100 
101 void WII::Reset() {
102  wiimoteConnected = false;
103  nunchuckConnected = false;
104  motionPlusConnected = false;
105  activateNunchuck = false;
106  motionValuesReset = false;
107  activeConnection = false;
108  motionPlusInside = false;
109  pBtd->wiiUProController = false;
111  wiiBalanceBoardConnected = false;
112  l2cap_event_flag = 0; // Reset flags
113  l2cap_state = L2CAP_WAIT;
114 }
115 
116 void WII::disconnect() { // Use this void to disconnect any of the controllers
117  if(!motionPlusInside) { // The old Wiimote needs a delay after the first command or it will automatically reconnect
118  if(motionPlusConnected) {
119 #ifdef DEBUG_USB_HOST
120  Notify(PSTR("\r\nDeactivating Motion Plus"), 0x80);
121 #endif
122  initExtension1(); // This will disable the Motion Plus extension
123  }
124  timer = (uint32_t)millis() + 1000; // We have to wait for the message before the rest of the channels can be deactivated
125  } else
126  timer = (uint32_t)millis(); // Don't wait
127  // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection
128  pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid);
129  Reset();
130  l2cap_state = L2CAP_INTERRUPT_DISCONNECT;
131 }
132 
133 void WII::ACLData(uint8_t* l2capinbuf) {
134  if(!pBtd->l2capConnectionClaimed && pBtd->incomingWii && !wiimoteConnected && !activeConnection) {
135  if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
136  if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
137  motionPlusInside = pBtd->motionPlusInside;
138  pBtd->incomingWii = false;
139  pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
140  activeConnection = true;
141  hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
142  l2cap_state = L2CAP_WAIT;
143  }
144  }
145  }
146 
147  if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok
148  if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U
149  if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
150 #ifdef DEBUG_USB_HOST
151  Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
152  D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
153  Notify(PSTR(" "), 0x80);
154  D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
155  Notify(PSTR(" "), 0x80);
156  D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
157  Notify(PSTR(" "), 0x80);
158  D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
159  Notify(PSTR(" "), 0x80);
160  D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
161  Notify(PSTR(" "), 0x80);
162  D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
163 #endif
164  } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) {
165  if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success
166  if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) {
167  //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80);
168  identifier = l2capinbuf[9];
169  control_scid[0] = l2capinbuf[12];
170  control_scid[1] = l2capinbuf[13];
172  } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) {
173  //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80);
174  identifier = l2capinbuf[9];
175  interrupt_scid[0] = l2capinbuf[12];
176  interrupt_scid[1] = l2capinbuf[13];
178  }
179  }
180  } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
181 #ifdef EXTRADEBUG
182  Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
183  D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
184  Notify(PSTR(" "), 0x80);
185  D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
186  Notify(PSTR(" SCID: "), 0x80);
187  D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
188  Notify(PSTR(" "), 0x80);
189  D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
190  Notify(PSTR(" Identifier: "), 0x80);
191  D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
192 #endif
193  if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
194  identifier = l2capinbuf[9];
195  control_scid[0] = l2capinbuf[14];
196  control_scid[1] = l2capinbuf[15];
198  } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
199  identifier = l2capinbuf[9];
200  interrupt_scid[0] = l2capinbuf[14];
201  interrupt_scid[1] = l2capinbuf[15];
203  }
204  } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
205  if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
206  if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
207  //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
208  identifier = l2capinbuf[9];
210  } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
211  //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
212  identifier = l2capinbuf[9];
214  }
215  }
216  } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
217  if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
218  //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
219  pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);
220  } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
221  //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
222  pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);
223  }
224  } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
225  if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
226 #ifdef DEBUG_USB_HOST
227  Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
228 #endif
229  identifier = l2capinbuf[9];
230  pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);
231  Reset();
232  } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
233 #ifdef DEBUG_USB_HOST
234  Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
235 #endif
236  identifier = l2capinbuf[9];
237  pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);
238  Reset();
239  }
240  } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
241  if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
242  //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
243  identifier = l2capinbuf[9];
245  } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
246  //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
247  identifier = l2capinbuf[9];
249  }
250  }
251 #ifdef EXTRADEBUG
252  else {
253  identifier = l2capinbuf[9];
254  Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
255  D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
256  }
257 #endif
258  } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
259  //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
260  if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
261  if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons
262  if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33) // These reports have no extensions bytes
263  ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8));
265  ButtonState = (uint32_t)(((~l2capinbuf[23]) & 0xFE) | ((uint16_t)(~l2capinbuf[24]) << 8) | ((uint32_t)((~l2capinbuf[25]) & 0x03) << 16));
266  else if(motionPlusConnected) {
267  if(l2capinbuf[20] & 0x02) // Only update the Wiimote buttons, since the extension bytes are from the Motion Plus
268  ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)(ButtonState & 0xFFFF0000)));
269  else if(nunchuckConnected) // Update if it's a report from the Nunchuck
270  ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x0C) << 14));
271  //else if(classicControllerConnected) // Update if it's a report from the Classic Controller
272  } else if(nunchuckConnected) // The Nunchuck is directly connected
273  ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x03) << 16));
274  //else if(classicControllerConnected) // The Classic Controller is directly connected
275  else if(!unknownExtensionConnected)
276  ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8));
277 #ifdef PRINTREPORT
278  Notify(PSTR("ButtonState: "), 0x80);
279  D_PrintHex<uint32_t > (ButtonState, 0x80);
280  Notify(PSTR("\r\n"), 0x80);
281 #endif
282  if(ButtonState != OldButtonState) {
283  ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
284  OldButtonState = ButtonState;
285  }
286  }
287  if(l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33 || l2capinbuf[9] == 0x35 || l2capinbuf[9] == 0x37) { // Read the accelerometer
288  accXwiimote = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5)) - 500;
289  accYwiimote = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4)) - 500;
290  accZwiimote = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5)) - 500;
291  }
292  switch(l2capinbuf[9]) {
293  case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV
294 #ifdef EXTRADEBUG
295  Notify(PSTR("\r\nStatus report was received"), 0x80);
296 #endif
297  wiiState = l2capinbuf[12]; // (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4)
298  batteryLevel = l2capinbuf[15]; // Update battery level
299 
300  if(!checkBatteryLevel) { // If this is true it means that the user must have called getBatteryLevel()
301  if(l2capinbuf[12] & 0x02) { // Check if a extension is connected
302 #ifdef DEBUG_USB_HOST
303  if(!unknownExtensionConnected)
304  Notify(PSTR("\r\nExtension connected"), 0x80);
305 #endif
306  unknownExtensionConnected = true;
307 #ifdef WIICAMERA
308  if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
309 #endif
310  setReportMode(false, 0x35); // Also read the extension
311  } else {
312 #ifdef DEBUG_USB_HOST
313  Notify(PSTR("\r\nExtension disconnected"), 0x80);
314 #endif
315  if(motionPlusConnected) {
316 #ifdef DEBUG_USB_HOST
317  Notify(PSTR(" - from Motion Plus"), 0x80);
318 #endif
320  if(!activateNunchuck) // If it's already trying to initialize the Nunchuck don't set it to false
321  nunchuckConnected = false;
322  //else if(classicControllerConnected)
323  } else if(nunchuckConnected) {
324 #ifdef DEBUG_USB_HOST
325  Notify(PSTR(" - Nunchuck"), 0x80);
326 #endif
327  nunchuckConnected = false; // It must be the Nunchuck controller then
329  onInit();
330 #ifdef WIICAMERA
331  if(!isIRCameraEnabled()) // We still want to read from the IR camera, so do not change the report mode
332 #endif
333  setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer
334  } else {
335 #ifdef WIICAMERA
336  if(!isIRCameraEnabled()) // We still want to read from the IR camera, so do not change the report mode
337 #endif
338  setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer
339  }
340  }
341  }
342  else {
343 #ifdef EXTRADEBUG
344  Notify(PSTR("\r\nChecking battery level"), 0x80);
345 #endif
346  checkBatteryLevel = false; // Check for extensions by default
347  }
348 #ifdef DEBUG_USB_HOST
349  if(l2capinbuf[12] & 0x01)
350  Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80);
351 #endif
352 
353  break;
354  case 0x21: // Read Memory Data
355  if((l2capinbuf[12] & 0x0F) == 0) { // No error
356  uint8_t reportLength = (l2capinbuf[12] >> 4) + 1; // // Bit 4-7 is the length - 1
357  // See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers
358  if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) {
359 #ifdef DEBUG_USB_HOST
360  Notify(PSTR("\r\nNunchuck connected"), 0x80);
361 #endif
363  } else if(l2capinbuf[16] == 0x00 && (l2capinbuf[17] == 0xA6 || l2capinbuf[17] == 0xA4) && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x05) {
364 #ifdef DEBUG_USB_HOST
365  Notify(PSTR("\r\nMotion Plus connected"), 0x80);
366 #endif
368  } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x05) {
369 #ifdef DEBUG_USB_HOST
370  Notify(PSTR("\r\nMotion Plus activated in normal mode"), 0x80);
371 #endif
372  motionPlusConnected = true;
373 #ifdef WIICAMERA
374  if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
375 #endif
376  setReportMode(false, 0x35); // Also read the extension
377  } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x05 && l2capinbuf[20] == 0x05) {
378 #ifdef DEBUG_USB_HOST
379  Notify(PSTR("\r\nMotion Plus activated in Nunchuck pass-through mode"), 0x80);
380 #endif
381  activateNunchuck = false;
382  motionPlusConnected = true;
383  nunchuckConnected = true;
384 #ifdef WIICAMERA
385  if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
386 #endif
387  setReportMode(false, 0x35); // Also read the extension
388  } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA6 && l2capinbuf[18] == 0x20 && (l2capinbuf[19] == 0x00 || l2capinbuf[19] == 0x04 || l2capinbuf[19] == 0x05 || l2capinbuf[19] == 0x07) && l2capinbuf[20] == 0x05) {
389 #ifdef DEBUG_USB_HOST
390  Notify(PSTR("\r\nInactive Wii Motion Plus"), 0x80);
391  Notify(PSTR("\r\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension"), 0x80);
392 #endif
393  stateCounter = 300; // Skip the rest in "WII_CHECK_MOTION_PLUS_STATE"
394  } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x01 && l2capinbuf[20] == 0x20) {
395 #ifdef DEBUG_USB_HOST
396  Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80);
397 #endif
399  } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x02) {
400 #ifdef DEBUG_USB_HOST
401  Notify(PSTR("\r\nWii Balance Board connected"), 0x80);
402 #endif
403  setReportMode(false, 0x32); // Read the Wii Balance Board extension
405  }
406  // Wii Balance Board calibration reports (24 bits in total)
407  else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x24 && reportLength == 16) { // First 16-bit
408  for(uint8_t i = 0; i < 2; i++) {
409  for(uint8_t j = 0; j < 4; j++)
410  wiiBalanceBoardCal[i][j] = l2capinbuf[16 + 8 * i + 2 * j] | l2capinbuf[15 + 8 * i + 2 * j] << 8;
411  }
412  } else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x34 && reportLength == 8) { // Last 8-bit
413  for(uint8_t j = 0; j < 4; j++)
414  wiiBalanceBoardCal[2][j] = l2capinbuf[16 + 2 * j] | l2capinbuf[15 + 2 * j] << 8;
415 #ifdef DEBUG_USB_HOST
416  Notify(PSTR("\r\nWii Balance Board calibration values read successfully"), 0x80);
417 #endif
420  }
421 #ifdef DEBUG_USB_HOST
422  else {
423  Notify(PSTR("\r\nUnknown Device: "), 0x80);
424  D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
425  D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
426  Notify(PSTR("\r\nData: "), 0x80);
427  for(uint8_t i = 0; i < reportLength; i++) {
428  D_PrintHex<uint8_t > (l2capinbuf[15 + i], 0x80);
429  Notify(PSTR(" "), 0x80);
430  }
431  }
432 #endif
433  }
434 #ifdef EXTRADEBUG
435  else {
436  Notify(PSTR("\r\nReport Error: "), 0x80);
437  D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
438  D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
439  }
440 #endif
441  break;
442  case 0x22: // Acknowledge output report, return function result
443 #ifdef DEBUG_USB_HOST
444  if(l2capinbuf[13] != 0x00) { // Check if there is an error
445  Notify(PSTR("\r\nCommand failed: "), 0x80);
446  D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
447  }
448 #endif
449  break;
450  case 0x30: // Core buttons - (a1) 30 BB BB
451  break;
452  case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA
453  break;
454  case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE
455  // See: http://wiibrew.org/wiki/Wii_Balance_Board#Data_Format
456  wiiBalanceBoardRaw[TopRight] = l2capinbuf[13] | l2capinbuf[12] << 8; // Top right
457  wiiBalanceBoardRaw[BotRight] = l2capinbuf[15] | l2capinbuf[14] << 8; // Bottom right
458  wiiBalanceBoardRaw[TopLeft] = l2capinbuf[17] | l2capinbuf[16] << 8; // Top left
459  wiiBalanceBoardRaw[BotLeft] = l2capinbuf[19] | l2capinbuf[18] << 8; // Bottom left
460  break;
461  case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II
462 #ifdef WIICAMERA
463  // Read the IR data
464  IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position
465  IR_object_y1 = (l2capinbuf[16] | ((uint16_t)(l2capinbuf[17] & 0xC0) << 2)); // y position
466  IR_object_s1 = (l2capinbuf[17] & 0x0F); // Size value, 0-15
467 
468  IR_object_x2 = (l2capinbuf[18] | ((uint16_t)(l2capinbuf[20] & 0x30) << 4));
469  IR_object_y2 = (l2capinbuf[19] | ((uint16_t)(l2capinbuf[20] & 0xC0) << 2));
470  IR_object_s2 = (l2capinbuf[20] & 0x0F);
471 
472  IR_object_x3 = (l2capinbuf[21] | ((uint16_t)(l2capinbuf[23] & 0x30) << 4));
473  IR_object_y3 = (l2capinbuf[22] | ((uint16_t)(l2capinbuf[23] & 0xC0) << 2));
474  IR_object_s3 = (l2capinbuf[23] & 0x0F);
475 
476  IR_object_x4 = (l2capinbuf[24] | ((uint16_t)(l2capinbuf[26] & 0x30) << 4));
477  IR_object_y4 = (l2capinbuf[25] | ((uint16_t)(l2capinbuf[26] & 0xC0) << 2));
478  IR_object_s4 = (l2capinbuf[26] & 0x0F);
479 #endif
480  break;
481  case 0x34: // Core Buttons with 19 Extension bytes - (a1) 34 BB BB EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
482  break;
483  /* 0x3e and 0x3f both give unknown report types when report mode is 0x3e or 0x3f with mode number 0x05 */
484  case 0x3E: // Core Buttons with Accelerometer and 32 IR bytes
485  // (a1) 31 BB BB AA AA AA II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II
486  // corresponds to output report mode 0x3e
487 
488  /**** for reading in full mode: DOES NOT WORK YET ****/
489  /* When it works it will also have intensity and bounding box data */
490  /*
491  IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4));
492  IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2));
493  IR_object_s1 = (l2capinbuf[15] & 0x0F);
494  */
495  break;
496  case 0x3F:
497  /*
498  IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4));
499  IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2));
500  IR_object_s1 = (l2capinbuf[15] & 0x0F);
501  */
502  break;
503  case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes
504  // (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
505 #if 1 // Set this to 0 if you don't want to use an extension, this reduceds the size of the library a lot!
506  if(motionPlusConnected) {
507  if(l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension
508  if(motionValuesReset) { // We will only use the values when the gyro value has been set
509  gyroYawRaw = ((l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)) - gyroYawZero);
510  gyroRollRaw = ((l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)) - gyroRollZero);
511  gyroPitchRaw = ((l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)) - gyroPitchZero);
512 
513  yawGyroSpeed = (float)gyroYawRaw / ((float)gyroYawZero / yawGyroScale);
514  rollGyroSpeed = -(float)gyroRollRaw / ((float)gyroRollZero / rollGyroScale); // We invert these values so they will fit the acc values
516 
517  /* The onboard gyro has two ranges for slow and fast mode */
518  if(!(l2capinbuf[18] & 0x02)) // Check if fast mode is used
519  yawGyroSpeed *= 4.545;
520  if(!(l2capinbuf[18] & 0x01)) // Check if fast mode is used
521  pitchGyroSpeed *= 4.545;
522  if(!(l2capinbuf[19] & 0x02)) // Check if fast mode is used
523  rollGyroSpeed *= 4.545;
524 
525  compPitch = (0.93f * (compPitch + (pitchGyroSpeed * (float)((uint32_t)micros() - timer) / 1000000.0f)))+(0.07f * getWiimotePitch()); // Use a complimentary filter to calculate the angle
526  compRoll = (0.93f * (compRoll + (rollGyroSpeed * (float)((uint32_t)micros() - timer) / 1000000.0f)))+(0.07f * getWiimoteRoll());
527 
528  gyroYaw += (yawGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));
529  gyroRoll += (rollGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));
530  gyroPitch += (pitchGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));
531  timer = (uint32_t)micros();
532  /*
533  // Uncomment these lines to tune the gyro scale variabels
534  Notify(PSTR("\r\ngyroYaw: "), 0x80);
535  Notify(gyroYaw, 0x80);
536  Notify(PSTR("\tgyroRoll: "), 0x80);
537  Notify(gyroRoll, 0x80);
538  Notify(PSTR("\tgyroPitch: "), 0x80);
539  Notify(gyroPitch, 0x80);
540  */
541  /*
542  Notify(PSTR("\twiimoteRoll: "), 0x80);
543  Notify(wiimoteRoll, 0x80);
544  Notify(PSTR("\twiimotePitch: "), 0x80);
545  Notify(wiimotePitch, 0x80);
546  */
547  } else {
548  if((int32_t)((uint32_t)micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values
549 #ifdef DEBUG_USB_HOST
550  Notify(PSTR("\r\nThe gyro values has been reset"), 0x80);
551 #endif
552  gyroYawZero = (l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6));
553  gyroRollZero = (l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6));
554  gyroPitchZero = (l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6));
555 
556  rollGyroScale = 500; // You might need to adjust these
557  pitchGyroScale = 400;
558  yawGyroScale = 415;
559 
560  gyroYaw = 0;
561  gyroRoll = 0;
562  gyroPitch = 0;
563 
564  motionValuesReset = true;
565  timer = (uint32_t)micros();
566  }
567  }
568  } else {
569  if(nunchuckConnected) {
570  hatValues[HatX] = l2capinbuf[15];
571  hatValues[HatY] = l2capinbuf[16];
572  accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x10 >> 3)) - 416;
573  accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x20 >> 4)) - 416;
574  accZnunchuck = (((l2capinbuf[19] & 0xFE) << 2) | (l2capinbuf[20] & 0xC0 >> 5)) - 416;
575  }
576  //else if(classicControllerConnected) { }
577  }
578  if(l2capinbuf[19] & 0x01) {
579  if(!extensionConnected) {
580  extensionConnected = true;
581  unknownExtensionConnected = true;
582 #ifdef DEBUG_USB_HOST
583  Notify(PSTR("\r\nExtension connected to Motion Plus"), 0x80);
584 #endif
585  }
586  } else {
587  if(extensionConnected && !unknownExtensionConnected) {
588  extensionConnected = false;
589  unknownExtensionConnected = true;
590 #ifdef DEBUG_USB_HOST
591  Notify(PSTR("\r\nExtension disconnected from Motion Plus"), 0x80);
592 #endif
593  nunchuckConnected = false; // There is no extension connected to the Motion Plus if this report is sent
594  }
595  }
596 
597  } else if(nunchuckConnected) {
598  hatValues[HatX] = l2capinbuf[15];
599  hatValues[HatY] = l2capinbuf[16];
600  accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x0C >> 2)) - 416;
601  accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x30 >> 4)) - 416;
602  accZnunchuck = ((l2capinbuf[19] << 2) | (l2capinbuf[20] & 0xC0 >> 6)) - 416;
603  } else if(wiiUProControllerConnected) {
604  hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8);
605  hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8);
606  hatValues[LeftHatY] = (l2capinbuf[19] | l2capinbuf[20] << 8);
607  hatValues[RightHatY] = (l2capinbuf[21] | l2capinbuf[22] << 8);
608  }
609 #endif
610  break;
611 #ifdef DEBUG_USB_HOST
612  default:
613  Notify(PSTR("\r\nUnknown Report type: "), 0x80);
614  D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
615  break;
616 #endif
617  }
618  }
619  }
620  L2CAP_task();
621  }
622 }
623 
624 void WII::L2CAP_task() {
625  switch(l2cap_state) {
626  /* These states are used if the Wiimote is the host */
629 #ifdef DEBUG_USB_HOST
630  Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
631 #endif
632  l2cap_state = L2CAP_INTERRUPT_SETUP;
633  }
634  break;
635 
638 #ifdef DEBUG_USB_HOST
639  Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
640 #endif
641  pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING);
642  delay(1);
643  pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);
644  identifier++;
645  delay(1);
646  pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
647 
648  l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
649  }
650  break;
651 
652  /* These states are used if the Arduino is the host */
655 #ifdef DEBUG_USB_HOST
656  Notify(PSTR("\r\nSend HID Control Config Request"), 0x80);
657 #endif
658  identifier++;
660  l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST;
661  }
662  break;
663 
666 #ifdef DEBUG_USB_HOST
667  Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80);
668 #endif
669  identifier++;
671  l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST;
672  }
673  break;
674 
677 #ifdef DEBUG_USB_HOST
678  Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80);
679 #endif
680  identifier++;
681  pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
682  l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
683  }
684  break;
685 
687  if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
688 #ifdef DEBUG_USB_HOST
689  Notify(PSTR("\r\nHID Channels Established"), 0x80);
690 #endif
691  pBtd->connectToWii = false;
692  pBtd->pairWithWii = false;
693  stateCounter = 0;
694  l2cap_state = WII_CHECK_MOTION_PLUS_STATE;
695  }
696  break;
697 
698  /* The next states are in run() */
699 
701  if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && ((int32_t)((uint32_t)millis() - timer) >= 0L)) {
702 #ifdef DEBUG_USB_HOST
703  Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
704 #endif
705  identifier++;
706  pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid);
707  l2cap_state = L2CAP_CONTROL_DISCONNECT;
708  }
709  break;
710 
713 #ifdef DEBUG_USB_HOST
714  Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
715 #endif
717  hci_handle = -1; // Reset handle
718  l2cap_event_flag = 0; // Reset flags
719  l2cap_state = L2CAP_WAIT;
720  }
721  break;
722  }
723 }
724 
725 void WII::Run() {
726  if(l2cap_state == L2CAP_INTERRUPT_DISCONNECT && ((int32_t)((uint32_t)millis() - timer) >= 0L))
727  L2CAP_task(); // Call the rest of the disconnection routine after we have waited long enough
728 
729  switch(l2cap_state) {
730  case L2CAP_WAIT:
731  if(pBtd->connectToWii && !pBtd->l2capConnectionClaimed && !wiimoteConnected && !activeConnection) {
733  activeConnection = true;
734  motionPlusInside = pBtd->motionPlusInside;
735 #ifdef DEBUG_USB_HOST
736  Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80);
737 #endif
738  hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
739  l2cap_event_flag = 0; // Reset flags
740  identifier = 0;
742  l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST;
744 #ifdef DEBUG_USB_HOST
745  Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
746 #endif
747  pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING);
748  delay(1);
749  pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL);
750  identifier++;
751  delay(1);
753  l2cap_state = L2CAP_CONTROL_SUCCESS;
754  }
755  break;
756 
758 #ifdef DEBUG_USB_HOST
759  if(stateCounter == 0) // Only print onnce
760  Notify(PSTR("\r\nChecking if a Motion Plus is connected"), 0x80);
761 #endif
762  stateCounter++;
763  if(stateCounter % 200 == 0)
764  checkMotionPresent(); // Check if there is a motion plus connected
766  stateCounter = 0;
767  l2cap_state = WII_INIT_MOTION_PLUS_STATE;
768  timer = (uint32_t)micros();
769 
770  if(unknownExtensionConnected) {
771 #ifdef DEBUG_USB_HOST
772  Notify(PSTR("\r\nA extension is also connected"), 0x80);
773 #endif
774  activateNunchuck = true; // For we will just set this to true as this the only extension supported so far
775  }
776 
777  } else if(stateCounter == 601) { // We will try three times to check for the motion plus
778 #ifdef DEBUG_USB_HOST
779  Notify(PSTR("\r\nNo Motion Plus was detected"), 0x80);
780 #endif
781  stateCounter = 0;
782  l2cap_state = WII_CHECK_EXTENSION_STATE;
783  }
784  break;
785 
786  case WII_CHECK_EXTENSION_STATE: // This is used to check if there is anything plugged in to the extension port
787 #ifdef DEBUG_USB_HOST
788  if(stateCounter == 0) // Only print onnce
789  Notify(PSTR("\r\nChecking if there is any extension connected"), 0x80);
790 #endif
791  stateCounter++; // We use this counter as there has to be a short delay between the commands
792  if(stateCounter == 1)
793  statusRequest(); // See if a new device has connected
794  if(stateCounter == 100) {
795  if(unknownExtensionConnected) // Check if there is a extension is connected to the port
796  initExtension1();
797  else
798  stateCounter = 499;
799  } else if(stateCounter == 200)
800  initExtension2();
801  else if(stateCounter == 300) {
802  readExtensionType();
803  unknownExtensionConnected = false;
804  } else if(stateCounter == 400) {
806 #ifdef DEBUG_USB_HOST
807  Notify(PSTR("\r\nReading Wii Balance Board calibration values"), 0x80);
808 #endif
809  readWiiBalanceBoardCalibration();
810  } else
811  stateCounter = 499;
812  } else if(stateCounter == 500) {
813  stateCounter = 0;
814  l2cap_state = TURN_ON_LED;
815  }
816  break;
817 
819  stateCounter++;
820  if(stateCounter == 1)
821  initMotionPlus();
822  else if(stateCounter == 100)
823  activateMotionPlus();
824  else if(stateCounter == 200)
825  readExtensionType(); // Check if it has been activated
826  else if(stateCounter == 300) {
827  stateCounter = 0;
828  unknownExtensionConnected = false; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus
829  l2cap_state = TURN_ON_LED;
830  }
831  break;
832 
833  case TURN_ON_LED:
835  nunchuckConnected = true;
836  wiimoteConnected = true;
837  onInit();
838  l2cap_state = L2CAP_DONE;
839  break;
840 
841  case L2CAP_DONE:
842  if(unknownExtensionConnected) {
843 #ifdef DEBUG_USB_HOST
844  if(stateCounter == 0) // Only print once
845  Notify(PSTR("\r\nChecking extension port"), 0x80);
846 #endif
847  stateCounter++; // We will use this counter as there has to be a short delay between the commands
848  if(stateCounter == 50)
849  statusRequest();
850  else if(stateCounter == 100)
851  initExtension1();
852  else if(stateCounter == 150)
853  if((extensionConnected && motionPlusConnected) || (unknownExtensionConnected && !motionPlusConnected))
854  initExtension2();
855  else
856  stateCounter = 299; // There is no extension connected
857  else if(stateCounter == 200)
858  readExtensionType();
859  else if(stateCounter == 250) {
861 #ifdef DEBUG_USB_HOST
862  Notify(PSTR("\r\nNunchuck was reconnected"), 0x80);
863 #endif
864  activateNunchuck = true;
865  nunchuckConnected = true;
866  }
868  stateCounter = 449;
869  } else if(stateCounter == 300) {
870  if(motionPlusConnected) {
871 #ifdef DEBUG_USB_HOST
872  Notify(PSTR("\r\nReactivating the Motion Plus"), 0x80);
873 #endif
874  initMotionPlus();
875  } else
876  stateCounter = 449;
877  } else if(stateCounter == 350)
878  activateMotionPlus();
879  else if(stateCounter == 400)
880  readExtensionType(); // Check if it has been activated
881  else if(stateCounter == 450) {
882  onInit();
883  stateCounter = 0;
884  unknownExtensionConnected = false;
885  }
886  } else
887  stateCounter = 0;
888  break;
889  }
890 }
891 
892 /************************************************************/
893 /* HID Commands */
894 /************************************************************/
895 
896 void WII::HID_Command(uint8_t* data, uint8_t nbytes) {
897  if(motionPlusInside)
898  pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // It's the new Wiimote with the Motion Plus Inside or Wii U Pro controller
899  else
900  pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]);
901 }
902 
904  HIDBuffer[1] = 0x11;
905  HIDBuffer[2] = 0x00;
906  HID_Command(HIDBuffer, 3);
907 }
908 
910  HIDBuffer[1] = 0x11;
911  HIDBuffer[2] &= ~0x01; // Bit 0 control the rumble
912  HID_Command(HIDBuffer, 3);
913 }
914 
916  HIDBuffer[1] = 0x11;
917  HIDBuffer[2] |= 0x01; // Bit 0 control the rumble
918  HID_Command(HIDBuffer, 3);
919 }
920 
922  HIDBuffer[1] = 0x11;
923  HIDBuffer[2] ^= 0x01; // Bit 0 control the rumble
924  HID_Command(HIDBuffer, 3);
925 }
926 
927 void WII::setLedRaw(uint8_t value) {
928  HIDBuffer[1] = 0x11;
929  HIDBuffer[2] = value | (HIDBuffer[2] & 0x01); // Keep the rumble bit
930  HID_Command(HIDBuffer, 3);
931 }
932 
934  HIDBuffer[1] = 0x11;
935  HIDBuffer[2] &= ~(pgm_read_byte(&WII_LEDS[(uint8_t)a]));
936  HID_Command(HIDBuffer, 3);
937 }
938 
940  if(a == OFF)
941  setLedRaw(0);
942  else {
943  HIDBuffer[1] = 0x11;
944  HIDBuffer[2] |= pgm_read_byte(&WII_LEDS[(uint8_t)a]);
945  HID_Command(HIDBuffer, 3);
946  }
947 }
948 
950  HIDBuffer[1] = 0x11;
951  HIDBuffer[2] ^= pgm_read_byte(&WII_LEDS[(uint8_t)a]);
952  HID_Command(HIDBuffer, 3);
953 }
954 
956  HIDBuffer[1] = 0x11;
957  HIDBuffer[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit
958  if(wiimoteConnected)
959  HIDBuffer[2] |= 0x10; // If it's connected LED1 will light up
961  HIDBuffer[2] |= 0x20; // If it's connected LED2 will light up
963  HIDBuffer[2] |= 0x40; // If it's connected LED3 will light up
964 
965  HID_Command(HIDBuffer, 3);
966 }
967 
969  checkBatteryLevel = true; // This is needed so the library knows that the status response is a response to this function
970  statusRequest(); // This will update the battery level
971  return batteryLevel;
972 };
973 
974 void WII::setReportMode(bool continuous, uint8_t mode) {
975 #ifdef EXTRADEBUG
976  Notify(PSTR("\r\nReport mode was changed to: "), 0x80);
977  D_PrintHex<uint8_t > (mode, 0x80);
978 #endif
979  uint8_t cmd_buf[4];
980  cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
981  cmd_buf[1] = 0x12;
982  if(continuous)
983  cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit
984  else
985  cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Keep the rumble bit
986  cmd_buf[3] = mode;
987  HID_Command(cmd_buf, 4);
988 }
989 
990 void WII::statusRequest() {
991  uint8_t cmd_buf[3];
992  cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
993  cmd_buf[1] = 0x15;
994  cmd_buf[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit
995  HID_Command(cmd_buf, 3);
996 }
997 
998 /************************************************************/
999 /* Memmory Commands */
1000 /************************************************************/
1001 
1002 void WII::writeData(uint32_t offset, uint8_t size, uint8_t* data) {
1003  uint8_t cmd_buf[23];
1004  cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
1005  cmd_buf[1] = 0x16; // Write data
1006  cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Write to memory, clear bit 2 to write to EEPROM
1007  cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16);
1008  cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8);
1009  cmd_buf[5] = (uint8_t)(offset & 0xFF);
1010  cmd_buf[6] = size;
1011  uint8_t i = 0;
1012  for(; i < size; i++)
1013  cmd_buf[7 + i] = data[i];
1014  for(; i < 16; i++) // Set the rest to zero
1015  cmd_buf[7 + i] = 0x00;
1016  HID_Command(cmd_buf, 23);
1017 }
1018 
1019 void WII::initExtension1() {
1020  uint8_t buf[1];
1021  buf[0] = 0x55;
1022  writeData(0xA400F0, 1, buf);
1023 }
1024 
1025 void WII::initExtension2() {
1026  uint8_t buf[1];
1027  buf[0] = 0x00;
1028  writeData(0xA400FB, 1, buf);
1029 }
1030 
1031 void WII::initMotionPlus() {
1032  uint8_t buf[1];
1033  buf[0] = 0x55;
1034  writeData(0xA600F0, 1, buf);
1035 }
1036 
1037 void WII::activateMotionPlus() {
1038  uint8_t buf[1];
1039  if(pBtd->wiiUProController) {
1040 #ifdef DEBUG_USB_HOST
1041  Notify(PSTR("\r\nActivating Wii U Pro Controller"), 0x80);
1042 #endif
1043  buf[0] = 0x00; // It seems like you can send anything but 0x04, 0x05, and 0x07
1044  } else if(activateNunchuck) {
1045 #ifdef DEBUG_USB_HOST
1046  Notify(PSTR("\r\nActivating Motion Plus in pass-through mode"), 0x80);
1047 #endif
1048  buf[0] = 0x05; // Activate nunchuck pass-through mode
1049  }//else if(classicControllerConnected && extensionConnected)
1050  //buf[0] = 0x07;
1051  else {
1052 #ifdef DEBUG_USB_HOST
1053  Notify(PSTR("\r\nActivating Motion Plus in normal mode"), 0x80);
1054 #endif
1055  buf[0] = 0x04; // Don't use any extension
1056  }
1057  writeData(0xA600FE, 1, buf);
1058 }
1059 
1060 void WII::readData(uint32_t offset, uint16_t size, bool EEPROM) {
1061  uint8_t cmd_buf[8];
1062  cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
1063  cmd_buf[1] = 0x17; // Read data
1064  if(EEPROM)
1065  cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Read from EEPROM
1066  else
1067  cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory
1068  cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16);
1069  cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8);
1070  cmd_buf[5] = (uint8_t)(offset & 0xFF);
1071  cmd_buf[6] = (uint8_t)((size & 0xFF00) >> 8);
1072  cmd_buf[7] = (uint8_t)(size & 0xFF);
1073 
1074  HID_Command(cmd_buf, 8);
1075 }
1076 
1077 void WII::readExtensionType() {
1078  readData(0xA400FA, 6, false);
1079 }
1080 
1081 void WII::readCalData() {
1082  readData(0x0016, 8, true);
1083 }
1084 
1085 void WII::checkMotionPresent() {
1086  readData(0xA600FA, 6, false);
1087 }
1088 
1089 void WII::readWiiBalanceBoardCalibration() {
1090  readData(0xA40024, 24, false);
1091 }
1092 
1093 /************************************************************/
1094 /* WII Commands */
1095 /************************************************************/
1096 
1097 bool WII::getButtonPress(ButtonEnum b) { // Return true when a button is pressed
1099  return (ButtonState & pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b]));
1100  else
1101  return (ButtonState & pgm_read_dword(&WII_BUTTONS[(uint8_t)b]));
1102 }
1103 
1104 bool WII::getButtonClick(ButtonEnum b) { // Only return true when a button is clicked
1105  uint32_t button;
1107  button = pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b]);
1108  else
1109  button = pgm_read_dword(&WII_BUTTONS[(uint8_t)b]);
1110  bool click = (ButtonClickState & button);
1111  ButtonClickState &= ~button; // clear "click" event
1112  return click;
1113 }
1114 
1116  if(!nunchuckConnected)
1117  return 127; // Return center position
1118  else {
1119  uint8_t output = hatValues[(uint8_t)a];
1120  if(output == 0xFF || output == 0x00) // The joystick will only read 255 or 0 when the cable is unplugged or initializing, so we will just return the center position
1121  return 127;
1122  else
1123  return output;
1124  }
1125 }
1126 
1129  return 2000;
1130  else {
1131  uint16_t output = hatValues[(uint8_t)a];
1132  if(output == 0x00) // The joystick will only read 0 when it is first initializing, so we will just return the center position
1133  return 2000;
1134  else
1135  return output;
1136  }
1137 }
1138 
1139 void WII::onInit() {
1140  if(pFuncOnInit)
1141  pFuncOnInit(); // Call the user function
1142  else
1143  setLedStatus();
1144 }
1145 
1146 /************************************************************/
1147 /* Wii Balance Board Commands */
1148 /************************************************************/
1149 
1151  // Use interpolating between two points - based on: https://github.com/skorokithakis/gr8w8upd8m8/blob/master/gr8w8upd8m8.py
1152  // wiiBalanceBoardCal[pos][0] is calibration values for 0 kg
1153  // wiiBalanceBoardCal[pos][1] is calibration values for 17 kg
1154  // wiiBalanceBoardCal[pos][2] is calibration values for 34 kg
1155  if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[0][pos])
1156  return 0.0f; // Below 0 kg
1157  else if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[1][pos]) // Between 0 and 17 kg
1158  return 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[0][pos]) / (float)(wiiBalanceBoardCal[1][pos] - wiiBalanceBoardCal[0][pos]);
1159  else // More than 17 kg
1160  return 17.0f + 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[1][pos]) / (float)(wiiBalanceBoardCal[2][pos] - wiiBalanceBoardCal[1][pos]);
1161 };
1162 
1165 };
1166 
1167 /************************************************************/
1168 /* The following functions are for the IR camera */
1169 /************************************************************/
1170 
1171 #ifdef WIICAMERA
1172 
1173 void WII::IRinitialize() { // Turns on and initialises the IR camera
1174 
1175  enableIRCamera1();
1176 #ifdef DEBUG_USB_HOST
1177  Notify(PSTR("\r\nEnable IR Camera1 Complete"), 0x80);
1178 #endif
1179  delay(80);
1180 
1181  enableIRCamera2();
1182 #ifdef DEBUG_USB_HOST
1183  Notify(PSTR("\r\nEnable IR Camera2 Complete"), 0x80);
1184 #endif
1185  delay(80);
1186 
1187  write0x08Value();
1188 #ifdef DEBUG_USB_HOST
1189  Notify(PSTR("\r\nWrote hex number 0x08"), 0x80);
1190 #endif
1191  delay(80);
1192 
1193  writeSensitivityBlock1();
1194 #ifdef DEBUG_USB_HOST
1195  Notify(PSTR("\r\nWrote Sensitivity Block 1"), 0x80);
1196 #endif
1197  delay(80);
1198 
1199  writeSensitivityBlock2();
1200 #ifdef DEBUG_USB_HOST
1201  Notify(PSTR("\r\nWrote Sensitivity Block 2"), 0x80);
1202 #endif
1203  delay(80);
1204 
1205  uint8_t mode_num = 0x03;
1206  setWiiModeNumber(mode_num); // Change input for whatever mode you want i.e. 0x01, 0x03, or 0x05
1207 #ifdef DEBUG_USB_HOST
1208  Notify(PSTR("\r\nSet Wii Mode Number To 0x"), 0x80);
1209  D_PrintHex<uint8_t > (mode_num, 0x80);
1210 #endif
1211  delay(80);
1212 
1213  write0x08Value();
1214 #ifdef DEBUG_USB_HOST
1215  Notify(PSTR("\r\nWrote Hex Number 0x08"), 0x80);
1216 #endif
1217  delay(80);
1218 
1219  setReportMode(false, 0x33);
1220  //setReportMode(false, 0x3f); // For full reporting mode, doesn't work yet
1221 #ifdef DEBUG_USB_HOST
1222  Notify(PSTR("\r\nSet Report Mode to 0x33"), 0x80);
1223 #endif
1224  delay(80);
1225 
1226  statusRequest(); // Used to update wiiState - call isIRCameraEnabled() afterwards to check if it actually worked
1227 #ifdef DEBUG_USB_HOST
1228  Notify(PSTR("\r\nIR Initialized"), 0x80);
1229 #endif
1230 }
1231 
1232 void WII::enableIRCamera1() {
1233  uint8_t cmd_buf[3];
1234  cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
1235  cmd_buf[1] = 0x13; // Output report 13
1236  cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2
1237  HID_Command(cmd_buf, 3);
1238 }
1239 
1240 void WII::enableIRCamera2() {
1241  uint8_t cmd_buf[3];
1242  cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
1243  cmd_buf[1] = 0x1A; // Output report 1A
1244  cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2
1245  HID_Command(cmd_buf, 3);
1246 }
1247 
1248 void WII::writeSensitivityBlock1() {
1249  uint8_t buf[9];
1250  buf[0] = 0x00;
1251  buf[1] = 0x00;
1252  buf[2] = 0x00;
1253  buf[3] = 0x00;
1254  buf[4] = 0x00;
1255  buf[5] = 0x00;
1256  buf[6] = 0x90;
1257  buf[7] = 0x00;
1258  buf[8] = 0x41;
1259 
1260  writeData(0xB00000, 9, buf);
1261 }
1262 
1263 void WII::writeSensitivityBlock2() {
1264  uint8_t buf[2];
1265  buf[0] = 0x40;
1266  buf[1] = 0x00;
1267 
1268  writeData(0xB0001A, 2, buf);
1269 }
1270 
1271 void WII::write0x08Value() {
1272  uint8_t cmd = 0x08;
1273  writeData(0xb00030, 1, &cmd);
1274 }
1275 
1276 void WII::setWiiModeNumber(uint8_t mode_number) { // mode_number in hex i.e. 0x03 for extended mode
1277  writeData(0xb00033, 1, &mode_number);
1278 }
1279 #endif
L2CAP_INTERRUPT_DISCONNECT
#define L2CAP_INTERRUPT_DISCONNECT
Definition: BTD.h:126
BTD::hci_disconnect
void hci_disconnect(uint16_t handle)
Definition: BTD.cpp:1399
L2CAP_INTERRUPT_SETUP
#define L2CAP_INTERRUPT_SETUP
Definition: BTD.h:123
WII::setLedRaw
void setLedRaw(uint8_t value)
Definition: Wii.cpp:927
WII_CHECK_MOTION_PLUS_STATE
#define WII_CHECK_MOTION_PLUS_STATE
Definition: BTD.h:141
WII_LEDS
const uint8_t WII_LEDS[]
Definition: Wii.cpp:25
L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS
#define L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS
Definition: BTD.h:153
WII::setLedOff
void setLedOff()
Definition: Wii.h:152
SUCCESSFUL
#define SUCCESSFUL
Definition: BTD.h:187
BTD::L2CAP_Command
void L2CAP_Command(uint16_t handle, uint8_t *data, uint8_t nbytes, uint8_t channelLow=0x01, uint8_t channelHigh=0x00)
Definition: BTD.cpp:1447
WII_BUTTONS
const uint32_t WII_BUTTONS[]
Definition: Wii.cpp:40
WII::getButtonClick
bool getButtonClick(ButtonEnum b)
Definition: Wii.cpp:1104
L2CAP_CMD_CONNECTION_RESPONSE
#define L2CAP_CMD_CONNECTION_RESPONSE
Definition: BTD.h:177
WII::setRumbleOff
void setRumbleOff()
Definition: Wii.cpp:909
BTD::l2cap_config_request
void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t *dcid)
Definition: BTD.cpp:1505
TURN_ON_LED
#define TURN_ON_LED
Definition: BTD.h:139
wii_set_flag
#define wii_set_flag(flag)
Definition: Wii.h:32
WII::gyroRoll
float gyroRoll
Definition: Wii.h:243
WII::setAllOff
void setAllOff()
Definition: Wii.cpp:903
WII::disconnect
void disconnect()
Definition: Wii.cpp:116
WII::gyroYawRaw
int16_t gyroYawRaw
Definition: Wii.h:263
WII::pitchGyroSpeed
float pitchGyroSpeed
Definition: Wii.h:249
WII::onInit
void onInit()
Definition: Wii.cpp:1139
WII::getWiimoteRoll
float getWiimoteRoll()
Definition: Wii.h:216
BTD::incomingWii
bool incomingWii
Definition: BTD.h:504
WII_PROCONTROLLER_BUTTONS
const uint32_t WII_PROCONTROLLER_BUTTONS[]
Definition: Wii.cpp:59
WII::ACLData
void ACLData(uint8_t *ACLData)
Definition: Wii.cpp:133
WII::wiiBalanceBoardConnected
bool wiiBalanceBoardConnected
Definition: Wii.h:204
PENDING
#define PENDING
Definition: BTD.h:186
L2CAP_FLAG_INTERRUPT_CONNECTED
#define L2CAP_FLAG_INTERRUPT_CONNECTED
Definition: BTD.h:154
l2cap_check_flag
#define l2cap_check_flag(flag)
Definition: BTD.h:170
WII::IRinitialize
void IRinitialize()
Definition: Wii.cpp:1173
HatY
@ HatY
Definition: Wii.h:40
L2CAP_CONTROL_SUCCESS
#define L2CAP_CONTROL_SUCCESS
Definition: BTD.h:119
L2CAP_WAIT
#define L2CAP_WAIT
Definition: BTD.h:113
WII_FLAG_MOTION_PLUS_CONNECTED
#define WII_FLAG_MOTION_PLUS_CONNECTED
Definition: Wii.h:27
L2CAP_FLAG_CONFIG_CONTROL_SUCCESS
#define L2CAP_FLAG_CONFIG_CONTROL_SUCCESS
Definition: BTD.h:147
WII::yawGyroSpeed
float yawGyroSpeed
Definition: Wii.h:251
Notify
#define Notify(...)
Definition: message.h:51
BTD::connectToWii
bool connectToWii
Definition: BTD.h:500
L2CAP_INTERRUPT_CONFIG_REQUEST
#define L2CAP_INTERRUPT_CONFIG_REQUEST
Definition: BTD.h:125
L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST
#define L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST
Definition: BTD.h:152
WII::Reset
void Reset()
Definition: Wii.cpp:101
L2CAP_CONTROL_CONFIG_REQUEST
#define L2CAP_CONTROL_CONFIG_REQUEST
Definition: BTD.h:118
BTD
Definition: BTD.h:221
L2CAP_CMD_DISCONNECT_RESPONSE
#define L2CAP_CMD_DISCONNECT_RESPONSE
Definition: BTD.h:181
L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE
#define L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE
Definition: BTD.h:155
L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE
#define L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE
Definition: BTD.h:149
L2CAP_CMD_DISCONNECT_REQUEST
#define L2CAP_CMD_DISCONNECT_REQUEST
Definition: BTD.h:180
BotLeft
@ BotLeft
Definition: Wii.h:48
L2CAP_FLAG_CONNECTION_CONTROL_REQUEST
#define L2CAP_FLAG_CONNECTION_CONTROL_REQUEST
Definition: BTD.h:146
WII::getWiimotePitch
float getWiimotePitch()
Definition: Wii.h:212
WII::accXnunchuck
int16_t accXnunchuck
Definition: Wii.h:236
LEDEnum
LEDEnum
Definition: controllerEnums.h:31
TopLeft
@ TopLeft
Definition: Wii.h:47
WII::accZwiimote
int16_t accZwiimote
Definition: Wii.h:235
BTD::motionPlusInside
bool motionPlusInside
Definition: BTD.h:508
BTD::l2cap_config_response
void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t *scid)
Definition: BTD.cpp:1522
WII::getButtonPress
bool getButtonPress(ButtonEnum b)
Definition: Wii.cpp:1097
WII::Run
void Run()
Definition: Wii.cpp:725
WII_CHECK_EXTENSION_STATE
#define WII_CHECK_EXTENSION_STATE
Definition: BTD.h:142
WII::accXwiimote
int16_t accXwiimote
Definition: Wii.h:230
WII::pitchGyroScale
uint16_t pitchGyroScale
Definition: Wii.h:256
BluetoothService::l2cap_event_flag
uint32_t l2cap_event_flag
Definition: BTD.h:652
WII::WII
WII(BTD *p, bool pair=false)
Definition: Wii.cpp:85
WII::wiimoteConnected
bool wiimoteConnected
Definition: Wii.h:191
BluetoothService::pBtd
BTD * pBtd
Definition: BTD.h:646
WII_FLAG_NUNCHUCK_CONNECTED
#define WII_FLAG_NUNCHUCK_CONNECTED
Definition: Wii.h:28
RightHatY
@ RightHatY
Definition: controllerEnums.h:178
L2CAP_DONE
#define L2CAP_DONE
Definition: BTD.h:114
WII::setLedToggle
void setLedToggle(LEDEnum a)
Definition: Wii.cpp:949
WII::getTotalWeight
float getTotalWeight()
Definition: Wii.cpp:1163
HatX
@ HatX
Definition: Wii.h:38
WII::rollGyroScale
uint16_t rollGyroScale
Definition: Wii.h:257
L2CAP_CONTROL_CONNECT_REQUEST
#define L2CAP_CONTROL_CONNECT_REQUEST
Definition: BTD.h:117
HID_CTRL_PSM
#define HID_CTRL_PSM
Definition: BTD.h:192
WII::gyroPitchRaw
int16_t gyroPitchRaw
Definition: Wii.h:265
wii_clear_flag
#define wii_clear_flag(flag)
Definition: Wii.h:33
BTD::l2cap_disconnection_response
void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid)
Definition: BTD.cpp:1554
HatEnum
HatEnum
Definition: Wii.h:36
WII::getWeight
float getWeight(BalanceBoardEnum pos)
Definition: Wii.cpp:1150
WII::nunchuckConnected
bool nunchuckConnected
Definition: Wii.h:198
WII::rollGyroSpeed
float rollGyroSpeed
Definition: Wii.h:250
BTD::l2cap_connection_request
void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t *scid, uint16_t psm)
Definition: BTD.cpp:1475
BluetoothService::identifier
uint8_t identifier
Definition: BTD.h:655
L2CAP_FLAG_CONTROL_CONNECTED
#define L2CAP_FLAG_CONTROL_CONNECTED
Definition: BTD.h:148
WII::setLedStatus
void setLedStatus()
Definition: Wii.cpp:955
pgm_read_dword
#define pgm_read_dword(addr)
Definition: version_helper.h:167
L2CAP_CMD_COMMAND_REJECT
#define L2CAP_CMD_COMMAND_REJECT
Definition: BTD.h:175
L
@ L
Definition: controllerEnums.h:102
HID_INTR_PSM
#define HID_INTR_PSM
Definition: BTD.h:193
WII::getAnalogHat
uint8_t getAnalogHat(HatEnum a)
Definition: Wii.cpp:1115
WII::accYwiimote
int16_t accYwiimote
Definition: Wii.h:235
WII::yawGyroScale
uint16_t yawGyroScale
Definition: Wii.h:258
BTD::l2cap_disconnection_request
void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid)
Definition: BTD.cpp:1541
WII::setLedOn
void setLedOn(LEDEnum a)
Definition: Wii.cpp:939
BTD::pairWithWii
bool pairWithWii
Definition: BTD.h:506
WII::setRumbleOn
void setRumbleOn()
Definition: Wii.cpp:915
pgm_read_byte
#define pgm_read_byte(addr)
Definition: version_helper.h:161
BotRight
@ BotRight
Definition: Wii.h:46
BluetoothService::pFuncOnInit
void(* pFuncOnInit)(void)
Definition: BTD.h:643
L2CAP_CMD_CONFIG_RESPONSE
#define L2CAP_CMD_CONFIG_RESPONSE
Definition: BTD.h:179
BluetoothService::hci_handle
uint16_t hci_handle
Definition: BTD.h:649
BluetoothService::checkHciHandle
bool checkHciHandle(uint8_t *buf, uint16_t handle)
Definition: BTD.h:638
OFF
@ OFF
Definition: controllerEnums.h:32
BalanceBoardEnum
BalanceBoardEnum
Definition: Wii.h:44
WII::gyroPitch
float gyroPitch
Definition: Wii.h:241
BluetoothService
Definition: BTD.h:603
WII::accZnunchuck
int16_t accZnunchuck
Definition: Wii.h:236
WII::getBatteryLevel
uint8_t getBatteryLevel()
Definition: Wii.cpp:968
WII::motionPlusConnected
bool motionPlusConnected
Definition: Wii.h:200
PSTR
#define PSTR(str)
Definition: version_helper.h:54
WII::gyroRollRaw
int16_t gyroRollRaw
Definition: Wii.h:264
WII::gyroYaw
float gyroYaw
Definition: Wii.h:245
WII::pair
void pair(void)
Definition: Wii.h:89
WII::isIRCameraEnabled
bool isIRCameraEnabled()
Definition: Wii.h:408
TopRight
@ TopRight
Definition: Wii.h:45
LeftHatX
@ LeftHatX
Definition: controllerEnums.h:172
BTD::l2capConnectionClaimed
bool l2capConnectionClaimed
Definition: BTD.h:470
BTD::l2cap_connection_response
void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid, uint8_t result)
Definition: BTD.cpp:1488
WII::gyroRollZero
int16_t gyroRollZero
Definition: Wii.h:271
L2CAP_CMD_CONNECTION_REQUEST
#define L2CAP_CMD_CONNECTION_REQUEST
Definition: BTD.h:176
WII::setRumbleToggle
void setRumbleToggle()
Definition: Wii.cpp:921
WII::gyroPitchZero
int16_t gyroPitchZero
Definition: Wii.h:272
L2CAP_CMD_CONFIG_REQUEST
#define L2CAP_CMD_CONFIG_REQUEST
Definition: BTD.h:178
WII::accYnunchuck
int16_t accYnunchuck
Definition: Wii.h:236
WII::gyroYawZero
int16_t gyroYawZero
Definition: Wii.h:270
WII_INIT_MOTION_PLUS_STATE
#define WII_INIT_MOTION_PLUS_STATE
Definition: BTD.h:143
L2CAP_CONTROL_DISCONNECT
#define L2CAP_CONTROL_DISCONNECT
Definition: BTD.h:120
Wii.h
wii_check_flag
#define wii_check_flag(flag)
Definition: Wii.h:31
l2cap_set_flag
#define l2cap_set_flag(flag)
Definition: BTD.h:171
BTD::hci_handle
uint16_t hci_handle
Definition: BTD.h:484
ButtonEnum
ButtonEnum
Definition: controllerEnums.h:78
L2CAP_INTERRUPT_CONNECT_REQUEST
#define L2CAP_INTERRUPT_CONNECT_REQUEST
Definition: BTD.h:124
AnalogHatEnum
AnalogHatEnum
Definition: controllerEnums.h:170
LeftHatY
@ LeftHatY
Definition: controllerEnums.h:174
RightHatX
@ RightHatX
Definition: controllerEnums.h:176
WII::wiiUProControllerConnected
bool wiiUProControllerConnected
Definition: Wii.h:202
WII_FLAG_CALIBRATE_BALANCE_BOARD
#define WII_FLAG_CALIBRATE_BALANCE_BOARD
Definition: Wii.h:29
BTD::wiiUProController
bool wiiUProController
Definition: BTD.h:510