Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
PS3BT.cpp
00001 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. 00002 00003 This software may be distributed and modified under the terms of the GNU 00004 General Public License version 2 (GPL2) as published by the Free Software 00005 Foundation and appearing in the file GPL2.TXT included in the packaging of 00006 this file. Please note that GPL2 Section 2[b] requires that all works based 00007 on this software must also be made publicly available under the terms of 00008 the GPL2 ("Copyleft"). 00009 00010 Contact information 00011 ------------------- 00012 00013 Kristian Lauszus, TKJ Electronics 00014 Web : http://www.tkjelectronics.com 00015 e-mail : kristianl@tkjelectronics.com 00016 */ 00017 00018 #include "PS3BT.h" 00019 // To enable serial debugging see "settings.h" 00020 //#define EXTRADEBUG // Uncomment to get even more debugging data 00021 //#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers 00022 00023 PS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) : 00024 BluetoothService(p) // Pointer to USB class instance - mandatory 00025 { 00026 pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead 00027 pBtd->my_bdaddr[4] = btadr4; 00028 pBtd->my_bdaddr[3] = btadr3; 00029 pBtd->my_bdaddr[2] = btadr2; 00030 pBtd->my_bdaddr[1] = btadr1; 00031 pBtd->my_bdaddr[0] = btadr0; 00032 00033 HIDBuffer[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02) 00034 HIDBuffer[1] = 0x01; // Report ID 00035 00036 // Needed for PS3 Move Controller commands to work via bluetooth 00037 HIDMoveBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) 00038 HIDMoveBuffer[1] = 0x02; // Report ID 00039 00040 /* Set device cid for the control and intterrupt channelse - LSB */ 00041 control_dcid[0] = 0x40; // 0x0040 00042 control_dcid[1] = 0x00; 00043 interrupt_dcid[0] = 0x41; // 0x0041 00044 interrupt_dcid[1] = 0x00; 00045 00046 Reset(); 00047 } 00048 00049 bool PS3BT::getButtonPress(ButtonEnum b) { 00050 return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b])); 00051 } 00052 00053 bool PS3BT::getButtonClick(ButtonEnum b) { 00054 uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]); 00055 bool click = (ButtonClickState & button); 00056 ButtonClickState &= ~button; // Clear "click" event 00057 return click; 00058 } 00059 00060 uint8_t PS3BT::getAnalogButton(ButtonEnum a) { 00061 return (uint8_t)(l2capinbuf[pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])]); 00062 } 00063 00064 uint8_t PS3BT::getAnalogHat(AnalogHatEnum a) { 00065 return (uint8_t)(l2capinbuf[(uint8_t)a + 15]); 00066 } 00067 00068 int16_t PS3BT::getSensor(SensorEnum a) { 00069 if(PS3Connected) { 00070 if(a == aX || a == aY || a == aZ || a == gZ) 00071 return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]); 00072 else 00073 return 0; 00074 } else if(PS3MoveConnected) { 00075 if(a == mXmove || a == mYmove) // These are all 12-bits long 00076 return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1])); 00077 else if(a == mZmove || a == tempMove) // The tempearature is also 12 bits long 00078 return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4)); 00079 else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove 00080 return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8)); 00081 } else 00082 return 0; 00083 } 00084 00085 float PS3BT::getAngle(AngleEnum a) { 00086 float accXval, accYval, accZval; 00087 00088 if(PS3Connected) { 00089 // Data for the Kionix KXPC4 used in the DualShock 3 00090 const float zeroG = 511.5f; // 1.65/3.3*1023 (1.65V) 00091 accXval = -((float)getSensor(aX) - zeroG); 00092 accYval = -((float)getSensor(aY) - zeroG); 00093 accZval = -((float)getSensor(aZ) - zeroG); 00094 } else if(PS3MoveConnected) { 00095 // It's a Kionix KXSC4 inside the Motion controller 00096 const uint16_t zeroG = 0x8000; 00097 accXval = -(int16_t)(getSensor(aXmove) - zeroG); 00098 accYval = (int16_t)(getSensor(aYmove) - zeroG); 00099 accZval = (int16_t)(getSensor(aZmove) - zeroG); 00100 } else 00101 return 0; 00102 00103 // Convert to 360 degrees resolution 00104 // atan2 outputs the value of -π to π (radians) 00105 // We are then converting it to 0 to 2π and then to degrees 00106 if(a == Pitch) 00107 return (atan2f(accYval, accZval) + PI) * RAD_TO_DEG; 00108 else 00109 return (atan2f(accXval, accZval) + PI) * RAD_TO_DEG; 00110 } 00111 00112 float PS3BT::get9DOFValues(SensorEnum a) { // Thanks to Manfred Piendl 00113 if(!PS3MoveConnected) 00114 return 0; 00115 int16_t value = getSensor(a); 00116 if(a == mXmove || a == mYmove || a == mZmove) { 00117 if(value > 2047) 00118 value -= 0x1000; 00119 return (float)value / 3.2f; // unit: muT = 10^(-6) Tesla 00120 } else if(a == aXmove || a == aYmove || a == aZmove) { 00121 if(value < 0) 00122 value += 0x8000; 00123 else 00124 value -= 0x8000; 00125 return (float)value / 442.0f; // unit: m/(s^2) 00126 } else if(a == gXmove || a == gYmove || a == gZmove) { 00127 if(value < 0) 00128 value += 0x8000; 00129 else 00130 value -= 0x8000; 00131 if(a == gXmove) 00132 return (float)value / 11.6f; // unit: deg/s 00133 else if(a == gYmove) 00134 return (float)value / 11.2f; // unit: deg/s 00135 else // gZmove 00136 return (float)value / 9.6f; // unit: deg/s 00137 } else 00138 return 0; 00139 } 00140 00141 String PS3BT::getTemperature() { 00142 if(PS3MoveConnected) { 00143 int16_t input = getSensor(tempMove); 00144 00145 String output = String(input / 100); 00146 output += "."; 00147 if(input % 100 < 10) 00148 output += "0"; 00149 output += String(input % 100); 00150 00151 return output; 00152 } else 00153 return "Error"; 00154 } 00155 00156 bool PS3BT::getStatus(StatusEnum c) { 00157 return (l2capinbuf[(uint16_t)c >> 8] == ((uint8_t)c & 0xff)); 00158 } 00159 00160 void PS3BT::printStatusString() { 00161 char statusOutput[102]; // Max string length plus null character 00162 if(PS3Connected || PS3NavigationConnected) { 00163 strcpy_P(statusOutput, PSTR("\r\nConnectionStatus: ")); 00164 00165 if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged")); 00166 else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged")); 00167 else strcat_P(statusOutput, PSTR("Error")); 00168 00169 strcat_P(statusOutput, PSTR(" - PowerRating: ")); 00170 00171 if(getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging")); 00172 else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); 00173 else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown")); 00174 else if(getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying")); 00175 else if(getStatus(Low)) strcat_P(statusOutput, PSTR("Low")); 00176 else if(getStatus(High)) strcat_P(statusOutput, PSTR("High")); 00177 else if(getStatus(Full)) strcat_P(statusOutput, PSTR("Full")); 00178 else strcat_P(statusOutput, PSTR("Error")); 00179 00180 strcat_P(statusOutput, PSTR(" - WirelessStatus: ")); 00181 00182 if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on")); 00183 else if(getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off")); 00184 else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on")); 00185 else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off")); 00186 else strcat_P(statusOutput, PSTR("Error")); 00187 } else if(PS3MoveConnected) { 00188 strcpy_P(statusOutput, PSTR("\r\nPowerRating: ")); 00189 00190 if(getStatus(MoveCharging)) strcat_P(statusOutput, PSTR("Charging")); 00191 else if(getStatus(MoveNotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); 00192 else if(getStatus(MoveShutdown)) strcat_P(statusOutput, PSTR("Shutdown")); 00193 else if(getStatus(MoveDying)) strcat_P(statusOutput, PSTR("Dying")); 00194 else if(getStatus(MoveLow)) strcat_P(statusOutput, PSTR("Low")); 00195 else if(getStatus(MoveHigh)) strcat_P(statusOutput, PSTR("High")); 00196 else if(getStatus(MoveFull)) strcat_P(statusOutput, PSTR("Full")); 00197 else strcat_P(statusOutput, PSTR("Error")); 00198 } else 00199 strcpy_P(statusOutput, PSTR("\r\nError")); 00200 00201 //USB_HOST_SERIAL.write(statusOutput); 00202 } 00203 00204 void PS3BT::Reset() { 00205 PS3Connected = false; 00206 PS3MoveConnected = false; 00207 PS3NavigationConnected = false; 00208 activeConnection = false; 00209 l2cap_event_flag = 0; // Reset flags 00210 l2cap_state = L2CAP_WAIT; 00211 00212 // Needed for PS3 Dualshock Controller commands to work via Bluetooth 00213 for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) 00214 HIDBuffer[i + 2] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID 00215 } 00216 00217 void PS3BT::disconnect() { // Use this void to disconnect any of the controllers 00218 // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection 00219 pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid); 00220 Reset(); 00221 l2cap_state = L2CAP_INTERRUPT_DISCONNECT; 00222 } 00223 00224 void PS3BT::ACLData(uint8_t* ACLData) { 00225 if(!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) { 00226 if(ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) { 00227 if((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) { 00228 pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service 00229 activeConnection = true; 00230 hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection 00231 l2cap_state = L2CAP_WAIT; 00232 remote_name_first = pBtd->remote_name[0]; // Store the first letter in remote name for the connection 00233 #ifdef DEBUG_USB_HOST 00234 if(pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle 00235 Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80); 00236 Notify(pBtd->hci_version, 0x80); 00237 Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80); 00238 } 00239 #endif 00240 } 00241 } 00242 } 00243 00244 if(checkHciHandle(ACLData, hci_handle)) { // acl_handle_ok 00245 memcpy(l2capinbuf, ACLData, BULK_MAXPKTSIZE); 00246 if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U 00247 if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { 00248 #ifdef DEBUG_USB_HOST 00249 Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); 00250 D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); 00251 Notify(PSTR(" "), 0x80); 00252 D_PrintHex<uint8_t > (l2capinbuf[12], 0x80); 00253 Notify(PSTR(" Data: "), 0x80); 00254 D_PrintHex<uint8_t > (l2capinbuf[17], 0x80); 00255 Notify(PSTR(" "), 0x80); 00256 D_PrintHex<uint8_t > (l2capinbuf[16], 0x80); 00257 Notify(PSTR(" "), 0x80); 00258 D_PrintHex<uint8_t > (l2capinbuf[15], 0x80); 00259 Notify(PSTR(" "), 0x80); 00260 D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); 00261 #endif 00262 } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { 00263 #ifdef EXTRADEBUG 00264 Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); 00265 D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); 00266 Notify(PSTR(" "), 0x80); 00267 D_PrintHex<uint8_t > (l2capinbuf[12], 0x80); 00268 Notify(PSTR(" SCID: "), 0x80); 00269 D_PrintHex<uint8_t > (l2capinbuf[15], 0x80); 00270 Notify(PSTR(" "), 0x80); 00271 D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); 00272 Notify(PSTR(" Identifier: "), 0x80); 00273 D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); 00274 #endif 00275 if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { 00276 identifier = l2capinbuf[9]; 00277 control_scid[0] = l2capinbuf[14]; 00278 control_scid[1] = l2capinbuf[15]; 00279 l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); 00280 } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { 00281 identifier = l2capinbuf[9]; 00282 interrupt_scid[0] = l2capinbuf[14]; 00283 interrupt_scid[1] = l2capinbuf[15]; 00284 l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); 00285 } 00286 } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { 00287 if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success 00288 if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { 00289 //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); 00290 l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); 00291 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { 00292 //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); 00293 l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); 00294 } 00295 } 00296 } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { 00297 if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { 00298 //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); 00299 pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); 00300 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { 00301 //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); 00302 pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); 00303 } 00304 } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { 00305 if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { 00306 #ifdef DEBUG_USB_HOST 00307 Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); 00308 #endif 00309 identifier = l2capinbuf[9]; 00310 pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); 00311 Reset(); 00312 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { 00313 #ifdef DEBUG_USB_HOST 00314 Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); 00315 #endif 00316 identifier = l2capinbuf[9]; 00317 pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); 00318 Reset(); 00319 } 00320 } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { 00321 if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { 00322 //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); 00323 identifier = l2capinbuf[9]; 00324 l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); 00325 } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { 00326 //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); 00327 identifier = l2capinbuf[9]; 00328 l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); 00329 } 00330 } 00331 #ifdef EXTRADEBUG 00332 else { 00333 Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); 00334 D_PrintHex<uint8_t > (l2capinbuf[8], 0x80); 00335 } 00336 #endif 00337 } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt 00338 //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80); 00339 if(PS3Connected || PS3MoveConnected || PS3NavigationConnected) { 00340 /* Read Report */ 00341 if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT 00342 lastMessageTime = (uint32_t)millis(); // Store the last message time 00343 00344 if(PS3Connected || PS3NavigationConnected) 00345 ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16)); 00346 else if(PS3MoveConnected) 00347 ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16)); 00348 00349 //Notify(PSTR("\r\nButtonState", 0x80); 00350 //PrintHex<uint32_t>(ButtonState, 0x80); 00351 00352 if(ButtonState != OldButtonState) { 00353 ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable 00354 OldButtonState = ButtonState; 00355 } 00356 00357 #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers 00358 for(uint8_t i = 10; i < 58; i++) { 00359 D_PrintHex<uint8_t > (l2capinbuf[i], 0x80); 00360 Notify(PSTR(" "), 0x80); 00361 } 00362 Notify(PSTR("\r\n"), 0x80); 00363 #endif 00364 } 00365 } 00366 } 00367 L2CAP_task(); 00368 } 00369 } 00370 00371 void PS3BT::L2CAP_task() { 00372 switch(l2cap_state) { 00373 case L2CAP_WAIT: 00374 if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { 00375 #ifdef DEBUG_USB_HOST 00376 Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); 00377 #endif 00378 pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING); 00379 delay(1); 00380 pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL); 00381 identifier++; 00382 delay(1); 00383 pBtd->l2cap_config_request(hci_handle, identifier, control_scid); 00384 l2cap_state = L2CAP_CONTROL_SUCCESS; 00385 } 00386 break; 00387 00388 case L2CAP_CONTROL_SUCCESS: 00389 if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { 00390 #ifdef DEBUG_USB_HOST 00391 Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); 00392 #endif 00393 l2cap_state = L2CAP_INTERRUPT_SETUP; 00394 } 00395 break; 00396 00397 case L2CAP_INTERRUPT_SETUP: 00398 if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { 00399 #ifdef DEBUG_USB_HOST 00400 Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); 00401 #endif 00402 pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING); 00403 delay(1); 00404 pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); 00405 identifier++; 00406 delay(1); 00407 pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); 00408 00409 l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; 00410 } 00411 break; 00412 00413 case L2CAP_INTERRUPT_CONFIG_REQUEST: 00414 if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established 00415 #ifdef DEBUG_USB_HOST 00416 Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80); 00417 #endif 00418 if(remote_name_first == 'M') { // First letter in Motion Controller ('M') 00419 memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed 00420 l2cap_state = TURN_ON_LED; 00421 } else 00422 l2cap_state = PS3_ENABLE_SIXAXIS; 00423 timer = (uint32_t)millis(); 00424 } 00425 break; 00426 00427 /* These states are handled in Run() */ 00428 00429 case L2CAP_INTERRUPT_DISCONNECT: 00430 if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) { 00431 #ifdef DEBUG_USB_HOST 00432 Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); 00433 #endif 00434 identifier++; 00435 pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); 00436 l2cap_state = L2CAP_CONTROL_DISCONNECT; 00437 } 00438 break; 00439 00440 case L2CAP_CONTROL_DISCONNECT: 00441 if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { 00442 #ifdef DEBUG_USB_HOST 00443 Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); 00444 #endif 00445 pBtd->hci_disconnect(hci_handle); 00446 hci_handle = -1; // Reset handle 00447 l2cap_event_flag = 0; // Reset flags 00448 l2cap_state = L2CAP_WAIT; 00449 } 00450 break; 00451 } 00452 } 00453 00454 void PS3BT::Run() { 00455 switch(l2cap_state) { 00456 case PS3_ENABLE_SIXAXIS: 00457 if((int32_t)((uint32_t)millis() - timer) > 1000) { // loop 1 second before sending the command 00458 memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed 00459 for(uint8_t i = 15; i < 19; i++) 00460 l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position 00461 enable_sixaxis(); 00462 l2cap_state = TURN_ON_LED; 00463 timer = (uint32_t)millis(); 00464 } 00465 break; 00466 00467 case TURN_ON_LED: 00468 if((int32_t)((uint32_t)millis() - timer) > 1000) { // loop 1 second before sending the command 00469 if(remote_name_first == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P') 00470 #ifdef DEBUG_USB_HOST 00471 Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80); 00472 #endif 00473 PS3Connected = true; 00474 } else if(remote_name_first == 'N') { // First letter in Navigation Controller ('N') 00475 #ifdef DEBUG_USB_HOST 00476 Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80); 00477 #endif 00478 PS3NavigationConnected = true; 00479 } else if(remote_name_first == 'M') { // First letter in Motion Controller ('M') 00480 timer = (uint32_t)millis(); 00481 #ifdef DEBUG_USB_HOST 00482 Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80); 00483 #endif 00484 PS3MoveConnected = true; 00485 } 00486 ButtonState = 0; // Clear all values 00487 OldButtonState = 0; 00488 ButtonClickState = 0; 00489 00490 onInit(); // Turn on the LED on the controller 00491 l2cap_state = L2CAP_DONE; 00492 } 00493 break; 00494 00495 case L2CAP_DONE: 00496 if(PS3MoveConnected) { // The Bulb and rumble values, has to be send at approximately every 5th second for it to stay on 00497 if((int32_t)((uint32_t)millis() - timer) > 4000) { // Send at least every 4th second 00498 HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on 00499 timer = (uint32_t)millis(); 00500 } 00501 } 00502 break; 00503 } 00504 } 00505 00506 /************************************************************/ 00507 /* HID Commands */ 00508 /************************************************************/ 00509 00510 // Playstation Sixaxis Dualshock and Navigation Controller commands 00511 00512 void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) { 00513 if((int32_t)((uint32_t)millis() - timerHID) <= 150) // Check if is has been more than 150ms since last command 00514 delay((uint32_t)(150 - ((uint32_t)millis() - timerHID))); // There have to be a delay between commands 00515 pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); // Both the Navigation and Dualshock controller sends data via the control channel 00516 timerHID = (uint32_t)millis(); 00517 } 00518 00519 void PS3BT::setAllOff() { 00520 HIDBuffer[3] = 0x00; // Rumble bytes 00521 HIDBuffer[4] = 0x00; 00522 HIDBuffer[5] = 0x00; 00523 HIDBuffer[6] = 0x00; 00524 00525 HIDBuffer[11] = 0x00; // LED byte 00526 00527 HID_Command(HIDBuffer, HID_BUFFERSIZE); 00528 } 00529 00530 void PS3BT::setRumbleOff() { 00531 uint8_t rumbleBuf[HID_BUFFERSIZE]; 00532 memcpy(rumbleBuf, HIDBuffer, HID_BUFFERSIZE); 00533 rumbleBuf[3] = 0x00; 00534 rumbleBuf[4] = 0x00; 00535 rumbleBuf[5] = 0x00; 00536 rumbleBuf[6] = 0x00; 00537 HID_Command(rumbleBuf, HID_BUFFERSIZE); 00538 } 00539 00540 void PS3BT::setRumbleOn(RumbleEnum mode) { 00541 uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow 00542 if(mode == RumbleHigh) { 00543 power[0] = 0x00; 00544 power[1] = 0xff; 00545 } 00546 setRumbleOn(0xfe, power[0], 0xfe, power[1]); 00547 } 00548 00549 void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { 00550 uint8_t rumbleBuf[HID_BUFFERSIZE]; 00551 memcpy(rumbleBuf, HIDBuffer, HID_BUFFERSIZE); 00552 rumbleBuf[3] = rightDuration; 00553 rumbleBuf[4] = rightPower; 00554 rumbleBuf[5] = leftDuration; 00555 rumbleBuf[6] = leftPower; 00556 HID_Command(rumbleBuf, HID_BUFFERSIZE); 00557 } 00558 00559 void PS3BT::setLedRaw(uint8_t value) { 00560 HIDBuffer[11] = value << 1; 00561 HID_Command(HIDBuffer, HID_BUFFERSIZE); 00562 } 00563 00564 void PS3BT::setLedOff(LEDEnum a) { 00565 HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1)); 00566 HID_Command(HIDBuffer, HID_BUFFERSIZE); 00567 } 00568 00569 void PS3BT::setLedOn(LEDEnum a) { 00570 if(a == OFF) 00571 setLedRaw(0); 00572 else { 00573 HIDBuffer[11] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); 00574 HID_Command(HIDBuffer, HID_BUFFERSIZE); 00575 } 00576 } 00577 00578 void PS3BT::setLedToggle(LEDEnum a) { 00579 HIDBuffer[11] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); 00580 HID_Command(HIDBuffer, HID_BUFFERSIZE); 00581 } 00582 00583 void PS3BT::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth 00584 uint8_t cmd_buf[6]; 00585 cmd_buf[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03) 00586 cmd_buf[1] = 0xF4; // Report ID 00587 cmd_buf[2] = 0x42; // Special PS3 Controller enable commands 00588 cmd_buf[3] = 0x03; 00589 cmd_buf[4] = 0x00; 00590 cmd_buf[5] = 0x00; 00591 00592 HID_Command(cmd_buf, 6); 00593 } 00594 00595 // Playstation Move Controller commands 00596 00597 void PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) { 00598 if((int32_t)((uint32_t)millis() - timerHID) <= 150)// Check if is has been less than 150ms since last command 00599 delay((uint32_t)(150 - ((uint32_t)millis() - timerHID))); // There have to be a delay between commands 00600 pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel 00601 timerHID = (uint32_t)millis(); 00602 } 00603 00604 void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values 00605 // Set the Bulb's values into the write buffer 00606 HIDMoveBuffer[3] = r; 00607 HIDMoveBuffer[4] = g; 00608 HIDMoveBuffer[5] = b; 00609 00610 HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); 00611 } 00612 00613 void PS3BT::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in enum 00614 moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); 00615 } 00616 00617 void PS3BT::moveSetRumble(uint8_t rumble) { 00618 #ifdef DEBUG_USB_HOST 00619 if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) 00620 Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); 00621 #endif 00622 // Set the rumble value into the write buffer 00623 HIDMoveBuffer[7] = rumble; 00624 00625 HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); 00626 } 00627 00628 void PS3BT::onInit() { 00629 if(pFuncOnInit) 00630 pFuncOnInit(); // Call the user function 00631 else { 00632 if(PS3MoveConnected) 00633 moveSetBulb(Red); 00634 else // Dualshock 3 or Navigation controller 00635 setLedOn(static_cast<LEDEnum>(CONTROLLER_LED1)); 00636 } 00637 } 00638
Generated on Thu Jul 14 2022 08:33:41 by
1.7.2