Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

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