一関 Aチーム / ArduinoUsbHostShield
Committer:
kotakku
Date:
Sat Jan 18 15:06:35 2020 +0000
Revision:
0:b1ce54272580
1.0.0 first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kotakku 0:b1ce54272580 1 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
kotakku 0:b1ce54272580 2
kotakku 0:b1ce54272580 3 This software may be distributed and modified under the terms of the GNU
kotakku 0:b1ce54272580 4 General Public License version 2 (GPL2) as published by the Free Software
kotakku 0:b1ce54272580 5 Foundation and appearing in the file GPL2.TXT included in the packaging of
kotakku 0:b1ce54272580 6 this file. Please note that GPL2 Section 2[b] requires that all works based
kotakku 0:b1ce54272580 7 on this software must also be made publicly available under the terms of
kotakku 0:b1ce54272580 8 the GPL2 ("Copyleft").
kotakku 0:b1ce54272580 9
kotakku 0:b1ce54272580 10 Contact information
kotakku 0:b1ce54272580 11 -------------------
kotakku 0:b1ce54272580 12
kotakku 0:b1ce54272580 13 Kristian Lauszus, TKJ Electronics
kotakku 0:b1ce54272580 14 Web : http://www.tkjelectronics.com
kotakku 0:b1ce54272580 15 e-mail : kristianl@tkjelectronics.com
kotakku 0:b1ce54272580 16 */
kotakku 0:b1ce54272580 17
kotakku 0:b1ce54272580 18 #include "PS3BT.h"
kotakku 0:b1ce54272580 19 // To enable serial debugging see "settings.h"
kotakku 0:b1ce54272580 20 //#define EXTRADEBUG // Uncomment to get even more debugging data
kotakku 0:b1ce54272580 21 //#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers
kotakku 0:b1ce54272580 22
kotakku 0:b1ce54272580 23 PS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) :
kotakku 0:b1ce54272580 24 BluetoothService(p) // Pointer to USB class instance - mandatory
kotakku 0:b1ce54272580 25 {
kotakku 0:b1ce54272580 26 pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead
kotakku 0:b1ce54272580 27 pBtd->my_bdaddr[4] = btadr4;
kotakku 0:b1ce54272580 28 pBtd->my_bdaddr[3] = btadr3;
kotakku 0:b1ce54272580 29 pBtd->my_bdaddr[2] = btadr2;
kotakku 0:b1ce54272580 30 pBtd->my_bdaddr[1] = btadr1;
kotakku 0:b1ce54272580 31 pBtd->my_bdaddr[0] = btadr0;
kotakku 0:b1ce54272580 32
kotakku 0:b1ce54272580 33 HIDBuffer[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02)
kotakku 0:b1ce54272580 34 HIDBuffer[1] = 0x01; // Report ID
kotakku 0:b1ce54272580 35
kotakku 0:b1ce54272580 36 // Needed for PS3 Move Controller commands to work via bluetooth
kotakku 0:b1ce54272580 37 HIDMoveBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
kotakku 0:b1ce54272580 38 HIDMoveBuffer[1] = 0x02; // Report ID
kotakku 0:b1ce54272580 39
kotakku 0:b1ce54272580 40 /* Set device cid for the control and intterrupt channelse - LSB */
kotakku 0:b1ce54272580 41 control_dcid[0] = 0x40; // 0x0040
kotakku 0:b1ce54272580 42 control_dcid[1] = 0x00;
kotakku 0:b1ce54272580 43 interrupt_dcid[0] = 0x41; // 0x0041
kotakku 0:b1ce54272580 44 interrupt_dcid[1] = 0x00;
kotakku 0:b1ce54272580 45
kotakku 0:b1ce54272580 46 Reset();
kotakku 0:b1ce54272580 47 }
kotakku 0:b1ce54272580 48
kotakku 0:b1ce54272580 49 bool PS3BT::getButtonPress(ButtonEnum b) {
kotakku 0:b1ce54272580 50 return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]));
kotakku 0:b1ce54272580 51 }
kotakku 0:b1ce54272580 52
kotakku 0:b1ce54272580 53 bool PS3BT::getButtonClick(ButtonEnum b) {
kotakku 0:b1ce54272580 54 uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]);
kotakku 0:b1ce54272580 55 bool click = (ButtonClickState & button);
kotakku 0:b1ce54272580 56 ButtonClickState &= ~button; // Clear "click" event
kotakku 0:b1ce54272580 57 return click;
kotakku 0:b1ce54272580 58 }
kotakku 0:b1ce54272580 59
kotakku 0:b1ce54272580 60 uint8_t PS3BT::getAnalogButton(ButtonEnum a) {
kotakku 0:b1ce54272580 61 return (uint8_t)(l2capinbuf[pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])]);
kotakku 0:b1ce54272580 62 }
kotakku 0:b1ce54272580 63
kotakku 0:b1ce54272580 64 uint8_t PS3BT::getAnalogHat(AnalogHatEnum a) {
kotakku 0:b1ce54272580 65 return (uint8_t)(l2capinbuf[(uint8_t)a + 15]);
kotakku 0:b1ce54272580 66 }
kotakku 0:b1ce54272580 67
kotakku 0:b1ce54272580 68 int16_t PS3BT::getSensor(SensorEnum a) {
kotakku 0:b1ce54272580 69 if(PS3Connected) {
kotakku 0:b1ce54272580 70 if(a == aX || a == aY || a == aZ || a == gZ)
kotakku 0:b1ce54272580 71 return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]);
kotakku 0:b1ce54272580 72 else
kotakku 0:b1ce54272580 73 return 0;
kotakku 0:b1ce54272580 74 } else if(PS3MoveConnected) {
kotakku 0:b1ce54272580 75 if(a == mXmove || a == mYmove) // These are all 12-bits long
kotakku 0:b1ce54272580 76 return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1]));
kotakku 0:b1ce54272580 77 else if(a == mZmove || a == tempMove) // The tempearature is also 12 bits long
kotakku 0:b1ce54272580 78 return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4));
kotakku 0:b1ce54272580 79 else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove
kotakku 0:b1ce54272580 80 return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8));
kotakku 0:b1ce54272580 81 } else
kotakku 0:b1ce54272580 82 return 0;
kotakku 0:b1ce54272580 83 }
kotakku 0:b1ce54272580 84
kotakku 0:b1ce54272580 85 float PS3BT::getAngle(AngleEnum a) {
kotakku 0:b1ce54272580 86 float accXval, accYval, accZval;
kotakku 0:b1ce54272580 87
kotakku 0:b1ce54272580 88 if(PS3Connected) {
kotakku 0:b1ce54272580 89 // Data for the Kionix KXPC4 used in the DualShock 3
kotakku 0:b1ce54272580 90 const float zeroG = 511.5f; // 1.65/3.3*1023 (1.65V)
kotakku 0:b1ce54272580 91 accXval = -((float)getSensor(aX) - zeroG);
kotakku 0:b1ce54272580 92 accYval = -((float)getSensor(aY) - zeroG);
kotakku 0:b1ce54272580 93 accZval = -((float)getSensor(aZ) - zeroG);
kotakku 0:b1ce54272580 94 } else if(PS3MoveConnected) {
kotakku 0:b1ce54272580 95 // It's a Kionix KXSC4 inside the Motion controller
kotakku 0:b1ce54272580 96 const uint16_t zeroG = 0x8000;
kotakku 0:b1ce54272580 97 accXval = -(int16_t)(getSensor(aXmove) - zeroG);
kotakku 0:b1ce54272580 98 accYval = (int16_t)(getSensor(aYmove) - zeroG);
kotakku 0:b1ce54272580 99 accZval = (int16_t)(getSensor(aZmove) - zeroG);
kotakku 0:b1ce54272580 100 } else
kotakku 0:b1ce54272580 101 return 0;
kotakku 0:b1ce54272580 102
kotakku 0:b1ce54272580 103 // Convert to 360 degrees resolution
kotakku 0:b1ce54272580 104 // atan2 outputs the value of -π to π (radians)
kotakku 0:b1ce54272580 105 // We are then converting it to 0 to 2π and then to degrees
kotakku 0:b1ce54272580 106 if(a == Pitch)
kotakku 0:b1ce54272580 107 return (atan2f(accYval, accZval) + PI) * RAD_TO_DEG;
kotakku 0:b1ce54272580 108 else
kotakku 0:b1ce54272580 109 return (atan2f(accXval, accZval) + PI) * RAD_TO_DEG;
kotakku 0:b1ce54272580 110 }
kotakku 0:b1ce54272580 111
kotakku 0:b1ce54272580 112 float PS3BT::get9DOFValues(SensorEnum a) { // Thanks to Manfred Piendl
kotakku 0:b1ce54272580 113 if(!PS3MoveConnected)
kotakku 0:b1ce54272580 114 return 0;
kotakku 0:b1ce54272580 115 int16_t value = getSensor(a);
kotakku 0:b1ce54272580 116 if(a == mXmove || a == mYmove || a == mZmove) {
kotakku 0:b1ce54272580 117 if(value > 2047)
kotakku 0:b1ce54272580 118 value -= 0x1000;
kotakku 0:b1ce54272580 119 return (float)value / 3.2f; // unit: muT = 10^(-6) Tesla
kotakku 0:b1ce54272580 120 } else if(a == aXmove || a == aYmove || a == aZmove) {
kotakku 0:b1ce54272580 121 if(value < 0)
kotakku 0:b1ce54272580 122 value += 0x8000;
kotakku 0:b1ce54272580 123 else
kotakku 0:b1ce54272580 124 value -= 0x8000;
kotakku 0:b1ce54272580 125 return (float)value / 442.0f; // unit: m/(s^2)
kotakku 0:b1ce54272580 126 } else if(a == gXmove || a == gYmove || a == gZmove) {
kotakku 0:b1ce54272580 127 if(value < 0)
kotakku 0:b1ce54272580 128 value += 0x8000;
kotakku 0:b1ce54272580 129 else
kotakku 0:b1ce54272580 130 value -= 0x8000;
kotakku 0:b1ce54272580 131 if(a == gXmove)
kotakku 0:b1ce54272580 132 return (float)value / 11.6f; // unit: deg/s
kotakku 0:b1ce54272580 133 else if(a == gYmove)
kotakku 0:b1ce54272580 134 return (float)value / 11.2f; // unit: deg/s
kotakku 0:b1ce54272580 135 else // gZmove
kotakku 0:b1ce54272580 136 return (float)value / 9.6f; // unit: deg/s
kotakku 0:b1ce54272580 137 } else
kotakku 0:b1ce54272580 138 return 0;
kotakku 0:b1ce54272580 139 }
kotakku 0:b1ce54272580 140
kotakku 0:b1ce54272580 141 String PS3BT::getTemperature() {
kotakku 0:b1ce54272580 142 if(PS3MoveConnected) {
kotakku 0:b1ce54272580 143 int16_t input = getSensor(tempMove);
kotakku 0:b1ce54272580 144
kotakku 0:b1ce54272580 145 String output = String(input / 100);
kotakku 0:b1ce54272580 146 output += ".";
kotakku 0:b1ce54272580 147 if(input % 100 < 10)
kotakku 0:b1ce54272580 148 output += "0";
kotakku 0:b1ce54272580 149 output += String(input % 100);
kotakku 0:b1ce54272580 150
kotakku 0:b1ce54272580 151 return output;
kotakku 0:b1ce54272580 152 } else
kotakku 0:b1ce54272580 153 return "Error";
kotakku 0:b1ce54272580 154 }
kotakku 0:b1ce54272580 155
kotakku 0:b1ce54272580 156 bool PS3BT::getStatus(StatusEnum c) {
kotakku 0:b1ce54272580 157 return (l2capinbuf[(uint16_t)c >> 8] == ((uint8_t)c & 0xff));
kotakku 0:b1ce54272580 158 }
kotakku 0:b1ce54272580 159
kotakku 0:b1ce54272580 160 void PS3BT::printStatusString() {
kotakku 0:b1ce54272580 161 char statusOutput[102]; // Max string length plus null character
kotakku 0:b1ce54272580 162 if(PS3Connected || PS3NavigationConnected) {
kotakku 0:b1ce54272580 163 strcpy_P(statusOutput, PSTR("\r\nConnectionStatus: "));
kotakku 0:b1ce54272580 164
kotakku 0:b1ce54272580 165 if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged"));
kotakku 0:b1ce54272580 166 else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged"));
kotakku 0:b1ce54272580 167 else strcat_P(statusOutput, PSTR("Error"));
kotakku 0:b1ce54272580 168
kotakku 0:b1ce54272580 169 strcat_P(statusOutput, PSTR(" - PowerRating: "));
kotakku 0:b1ce54272580 170
kotakku 0:b1ce54272580 171 if(getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging"));
kotakku 0:b1ce54272580 172 else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging"));
kotakku 0:b1ce54272580 173 else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown"));
kotakku 0:b1ce54272580 174 else if(getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying"));
kotakku 0:b1ce54272580 175 else if(getStatus(Low)) strcat_P(statusOutput, PSTR("Low"));
kotakku 0:b1ce54272580 176 else if(getStatus(High)) strcat_P(statusOutput, PSTR("High"));
kotakku 0:b1ce54272580 177 else if(getStatus(Full)) strcat_P(statusOutput, PSTR("Full"));
kotakku 0:b1ce54272580 178 else strcat_P(statusOutput, PSTR("Error"));
kotakku 0:b1ce54272580 179
kotakku 0:b1ce54272580 180 strcat_P(statusOutput, PSTR(" - WirelessStatus: "));
kotakku 0:b1ce54272580 181
kotakku 0:b1ce54272580 182 if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on"));
kotakku 0:b1ce54272580 183 else if(getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off"));
kotakku 0:b1ce54272580 184 else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on"));
kotakku 0:b1ce54272580 185 else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off"));
kotakku 0:b1ce54272580 186 else strcat_P(statusOutput, PSTR("Error"));
kotakku 0:b1ce54272580 187 } else if(PS3MoveConnected) {
kotakku 0:b1ce54272580 188 strcpy_P(statusOutput, PSTR("\r\nPowerRating: "));
kotakku 0:b1ce54272580 189
kotakku 0:b1ce54272580 190 if(getStatus(MoveCharging)) strcat_P(statusOutput, PSTR("Charging"));
kotakku 0:b1ce54272580 191 else if(getStatus(MoveNotCharging)) strcat_P(statusOutput, PSTR("Not Charging"));
kotakku 0:b1ce54272580 192 else if(getStatus(MoveShutdown)) strcat_P(statusOutput, PSTR("Shutdown"));
kotakku 0:b1ce54272580 193 else if(getStatus(MoveDying)) strcat_P(statusOutput, PSTR("Dying"));
kotakku 0:b1ce54272580 194 else if(getStatus(MoveLow)) strcat_P(statusOutput, PSTR("Low"));
kotakku 0:b1ce54272580 195 else if(getStatus(MoveHigh)) strcat_P(statusOutput, PSTR("High"));
kotakku 0:b1ce54272580 196 else if(getStatus(MoveFull)) strcat_P(statusOutput, PSTR("Full"));
kotakku 0:b1ce54272580 197 else strcat_P(statusOutput, PSTR("Error"));
kotakku 0:b1ce54272580 198 } else
kotakku 0:b1ce54272580 199 strcpy_P(statusOutput, PSTR("\r\nError"));
kotakku 0:b1ce54272580 200
kotakku 0:b1ce54272580 201 //USB_HOST_SERIAL.write(statusOutput);
kotakku 0:b1ce54272580 202 }
kotakku 0:b1ce54272580 203
kotakku 0:b1ce54272580 204 void PS3BT::Reset() {
kotakku 0:b1ce54272580 205 PS3Connected = false;
kotakku 0:b1ce54272580 206 PS3MoveConnected = false;
kotakku 0:b1ce54272580 207 PS3NavigationConnected = false;
kotakku 0:b1ce54272580 208 activeConnection = false;
kotakku 0:b1ce54272580 209 l2cap_event_flag = 0; // Reset flags
kotakku 0:b1ce54272580 210 l2cap_state = L2CAP_WAIT;
kotakku 0:b1ce54272580 211
kotakku 0:b1ce54272580 212 // Needed for PS3 Dualshock Controller commands to work via Bluetooth
kotakku 0:b1ce54272580 213 for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
kotakku 0:b1ce54272580 214 HIDBuffer[i + 2] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID
kotakku 0:b1ce54272580 215 }
kotakku 0:b1ce54272580 216
kotakku 0:b1ce54272580 217 void PS3BT::disconnect() { // Use this void to disconnect any of the controllers
kotakku 0:b1ce54272580 218 // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection
kotakku 0:b1ce54272580 219 pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid);
kotakku 0:b1ce54272580 220 Reset();
kotakku 0:b1ce54272580 221 l2cap_state = L2CAP_INTERRUPT_DISCONNECT;
kotakku 0:b1ce54272580 222 }
kotakku 0:b1ce54272580 223
kotakku 0:b1ce54272580 224 void PS3BT::ACLData(uint8_t* ACLData) {
kotakku 0:b1ce54272580 225 if(!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) {
kotakku 0:b1ce54272580 226 if(ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) {
kotakku 0:b1ce54272580 227 if((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) {
kotakku 0:b1ce54272580 228 pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
kotakku 0:b1ce54272580 229 activeConnection = true;
kotakku 0:b1ce54272580 230 hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
kotakku 0:b1ce54272580 231 l2cap_state = L2CAP_WAIT;
kotakku 0:b1ce54272580 232 remote_name_first = pBtd->remote_name[0]; // Store the first letter in remote name for the connection
kotakku 0:b1ce54272580 233 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 234 if(pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle
kotakku 0:b1ce54272580 235 Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80);
kotakku 0:b1ce54272580 236 Notify(pBtd->hci_version, 0x80);
kotakku 0:b1ce54272580 237 Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80);
kotakku 0:b1ce54272580 238 }
kotakku 0:b1ce54272580 239 #endif
kotakku 0:b1ce54272580 240 }
kotakku 0:b1ce54272580 241 }
kotakku 0:b1ce54272580 242 }
kotakku 0:b1ce54272580 243
kotakku 0:b1ce54272580 244 if(checkHciHandle(ACLData, hci_handle)) { // acl_handle_ok
kotakku 0:b1ce54272580 245 memcpy(l2capinbuf, ACLData, BULK_MAXPKTSIZE);
kotakku 0:b1ce54272580 246 if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U
kotakku 0:b1ce54272580 247 if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
kotakku 0:b1ce54272580 248 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 249 Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
kotakku 0:b1ce54272580 250 D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
kotakku 0:b1ce54272580 251 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 252 D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
kotakku 0:b1ce54272580 253 Notify(PSTR(" Data: "), 0x80);
kotakku 0:b1ce54272580 254 D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
kotakku 0:b1ce54272580 255 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 256 D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
kotakku 0:b1ce54272580 257 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 258 D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
kotakku 0:b1ce54272580 259 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 260 D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
kotakku 0:b1ce54272580 261 #endif
kotakku 0:b1ce54272580 262 } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
kotakku 0:b1ce54272580 263 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 264 Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
kotakku 0:b1ce54272580 265 D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
kotakku 0:b1ce54272580 266 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 267 D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
kotakku 0:b1ce54272580 268 Notify(PSTR(" SCID: "), 0x80);
kotakku 0:b1ce54272580 269 D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
kotakku 0:b1ce54272580 270 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 271 D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
kotakku 0:b1ce54272580 272 Notify(PSTR(" Identifier: "), 0x80);
kotakku 0:b1ce54272580 273 D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
kotakku 0:b1ce54272580 274 #endif
kotakku 0:b1ce54272580 275 if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
kotakku 0:b1ce54272580 276 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 277 control_scid[0] = l2capinbuf[14];
kotakku 0:b1ce54272580 278 control_scid[1] = l2capinbuf[15];
kotakku 0:b1ce54272580 279 l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST);
kotakku 0:b1ce54272580 280 } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
kotakku 0:b1ce54272580 281 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 282 interrupt_scid[0] = l2capinbuf[14];
kotakku 0:b1ce54272580 283 interrupt_scid[1] = l2capinbuf[15];
kotakku 0:b1ce54272580 284 l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST);
kotakku 0:b1ce54272580 285 }
kotakku 0:b1ce54272580 286 } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
kotakku 0:b1ce54272580 287 if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
kotakku 0:b1ce54272580 288 if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
kotakku 0:b1ce54272580 289 //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
kotakku 0:b1ce54272580 290 l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS);
kotakku 0:b1ce54272580 291 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
kotakku 0:b1ce54272580 292 //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
kotakku 0:b1ce54272580 293 l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS);
kotakku 0:b1ce54272580 294 }
kotakku 0:b1ce54272580 295 }
kotakku 0:b1ce54272580 296 } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
kotakku 0:b1ce54272580 297 if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
kotakku 0:b1ce54272580 298 //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
kotakku 0:b1ce54272580 299 pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);
kotakku 0:b1ce54272580 300 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
kotakku 0:b1ce54272580 301 //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
kotakku 0:b1ce54272580 302 pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);
kotakku 0:b1ce54272580 303 }
kotakku 0:b1ce54272580 304 } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
kotakku 0:b1ce54272580 305 if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
kotakku 0:b1ce54272580 306 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 307 Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
kotakku 0:b1ce54272580 308 #endif
kotakku 0:b1ce54272580 309 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 310 pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);
kotakku 0:b1ce54272580 311 Reset();
kotakku 0:b1ce54272580 312 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
kotakku 0:b1ce54272580 313 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 314 Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
kotakku 0:b1ce54272580 315 #endif
kotakku 0:b1ce54272580 316 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 317 pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);
kotakku 0:b1ce54272580 318 Reset();
kotakku 0:b1ce54272580 319 }
kotakku 0:b1ce54272580 320 } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
kotakku 0:b1ce54272580 321 if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
kotakku 0:b1ce54272580 322 //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
kotakku 0:b1ce54272580 323 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 324 l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE);
kotakku 0:b1ce54272580 325 } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
kotakku 0:b1ce54272580 326 //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
kotakku 0:b1ce54272580 327 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 328 l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE);
kotakku 0:b1ce54272580 329 }
kotakku 0:b1ce54272580 330 }
kotakku 0:b1ce54272580 331 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 332 else {
kotakku 0:b1ce54272580 333 Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
kotakku 0:b1ce54272580 334 D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
kotakku 0:b1ce54272580 335 }
kotakku 0:b1ce54272580 336 #endif
kotakku 0:b1ce54272580 337 } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
kotakku 0:b1ce54272580 338 //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
kotakku 0:b1ce54272580 339 if(PS3Connected || PS3MoveConnected || PS3NavigationConnected) {
kotakku 0:b1ce54272580 340 /* Read Report */
kotakku 0:b1ce54272580 341 if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
kotakku 0:b1ce54272580 342 lastMessageTime = (uint32_t)millis(); // Store the last message time
kotakku 0:b1ce54272580 343
kotakku 0:b1ce54272580 344 if(PS3Connected || PS3NavigationConnected)
kotakku 0:b1ce54272580 345 ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16));
kotakku 0:b1ce54272580 346 else if(PS3MoveConnected)
kotakku 0:b1ce54272580 347 ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16));
kotakku 0:b1ce54272580 348
kotakku 0:b1ce54272580 349 //Notify(PSTR("\r\nButtonState", 0x80);
kotakku 0:b1ce54272580 350 //PrintHex<uint32_t>(ButtonState, 0x80);
kotakku 0:b1ce54272580 351
kotakku 0:b1ce54272580 352 if(ButtonState != OldButtonState) {
kotakku 0:b1ce54272580 353 ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
kotakku 0:b1ce54272580 354 OldButtonState = ButtonState;
kotakku 0:b1ce54272580 355 }
kotakku 0:b1ce54272580 356
kotakku 0:b1ce54272580 357 #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
kotakku 0:b1ce54272580 358 for(uint8_t i = 10; i < 58; i++) {
kotakku 0:b1ce54272580 359 D_PrintHex<uint8_t > (l2capinbuf[i], 0x80);
kotakku 0:b1ce54272580 360 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 361 }
kotakku 0:b1ce54272580 362 Notify(PSTR("\r\n"), 0x80);
kotakku 0:b1ce54272580 363 #endif
kotakku 0:b1ce54272580 364 }
kotakku 0:b1ce54272580 365 }
kotakku 0:b1ce54272580 366 }
kotakku 0:b1ce54272580 367 L2CAP_task();
kotakku 0:b1ce54272580 368 }
kotakku 0:b1ce54272580 369 }
kotakku 0:b1ce54272580 370
kotakku 0:b1ce54272580 371 void PS3BT::L2CAP_task() {
kotakku 0:b1ce54272580 372 switch(l2cap_state) {
kotakku 0:b1ce54272580 373 case L2CAP_WAIT:
kotakku 0:b1ce54272580 374 if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) {
kotakku 0:b1ce54272580 375 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 376 Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
kotakku 0:b1ce54272580 377 #endif
kotakku 0:b1ce54272580 378 pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING);
kotakku 0:b1ce54272580 379 delay(1);
kotakku 0:b1ce54272580 380 pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL);
kotakku 0:b1ce54272580 381 identifier++;
kotakku 0:b1ce54272580 382 delay(1);
kotakku 0:b1ce54272580 383 pBtd->l2cap_config_request(hci_handle, identifier, control_scid);
kotakku 0:b1ce54272580 384 l2cap_state = L2CAP_CONTROL_SUCCESS;
kotakku 0:b1ce54272580 385 }
kotakku 0:b1ce54272580 386 break;
kotakku 0:b1ce54272580 387
kotakku 0:b1ce54272580 388 case L2CAP_CONTROL_SUCCESS:
kotakku 0:b1ce54272580 389 if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
kotakku 0:b1ce54272580 390 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 391 Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
kotakku 0:b1ce54272580 392 #endif
kotakku 0:b1ce54272580 393 l2cap_state = L2CAP_INTERRUPT_SETUP;
kotakku 0:b1ce54272580 394 }
kotakku 0:b1ce54272580 395 break;
kotakku 0:b1ce54272580 396
kotakku 0:b1ce54272580 397 case L2CAP_INTERRUPT_SETUP:
kotakku 0:b1ce54272580 398 if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) {
kotakku 0:b1ce54272580 399 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 400 Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
kotakku 0:b1ce54272580 401 #endif
kotakku 0:b1ce54272580 402 pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING);
kotakku 0:b1ce54272580 403 delay(1);
kotakku 0:b1ce54272580 404 pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);
kotakku 0:b1ce54272580 405 identifier++;
kotakku 0:b1ce54272580 406 delay(1);
kotakku 0:b1ce54272580 407 pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
kotakku 0:b1ce54272580 408
kotakku 0:b1ce54272580 409 l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
kotakku 0:b1ce54272580 410 }
kotakku 0:b1ce54272580 411 break;
kotakku 0:b1ce54272580 412
kotakku 0:b1ce54272580 413 case L2CAP_INTERRUPT_CONFIG_REQUEST:
kotakku 0:b1ce54272580 414 if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
kotakku 0:b1ce54272580 415 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 416 Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80);
kotakku 0:b1ce54272580 417 #endif
kotakku 0:b1ce54272580 418 if(remote_name_first == 'M') { // First letter in Motion Controller ('M')
kotakku 0:b1ce54272580 419 memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed
kotakku 0:b1ce54272580 420 l2cap_state = TURN_ON_LED;
kotakku 0:b1ce54272580 421 } else
kotakku 0:b1ce54272580 422 l2cap_state = PS3_ENABLE_SIXAXIS;
kotakku 0:b1ce54272580 423 timer = (uint32_t)millis();
kotakku 0:b1ce54272580 424 }
kotakku 0:b1ce54272580 425 break;
kotakku 0:b1ce54272580 426
kotakku 0:b1ce54272580 427 /* These states are handled in Run() */
kotakku 0:b1ce54272580 428
kotakku 0:b1ce54272580 429 case L2CAP_INTERRUPT_DISCONNECT:
kotakku 0:b1ce54272580 430 if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) {
kotakku 0:b1ce54272580 431 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 432 Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
kotakku 0:b1ce54272580 433 #endif
kotakku 0:b1ce54272580 434 identifier++;
kotakku 0:b1ce54272580 435 pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid);
kotakku 0:b1ce54272580 436 l2cap_state = L2CAP_CONTROL_DISCONNECT;
kotakku 0:b1ce54272580 437 }
kotakku 0:b1ce54272580 438 break;
kotakku 0:b1ce54272580 439
kotakku 0:b1ce54272580 440 case L2CAP_CONTROL_DISCONNECT:
kotakku 0:b1ce54272580 441 if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) {
kotakku 0:b1ce54272580 442 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 443 Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
kotakku 0:b1ce54272580 444 #endif
kotakku 0:b1ce54272580 445 pBtd->hci_disconnect(hci_handle);
kotakku 0:b1ce54272580 446 hci_handle = -1; // Reset handle
kotakku 0:b1ce54272580 447 l2cap_event_flag = 0; // Reset flags
kotakku 0:b1ce54272580 448 l2cap_state = L2CAP_WAIT;
kotakku 0:b1ce54272580 449 }
kotakku 0:b1ce54272580 450 break;
kotakku 0:b1ce54272580 451 }
kotakku 0:b1ce54272580 452 }
kotakku 0:b1ce54272580 453
kotakku 0:b1ce54272580 454 void PS3BT::Run() {
kotakku 0:b1ce54272580 455 switch(l2cap_state) {
kotakku 0:b1ce54272580 456 case PS3_ENABLE_SIXAXIS:
kotakku 0:b1ce54272580 457 if((int32_t)((uint32_t)millis() - timer) > 1000) { // loop 1 second before sending the command
kotakku 0:b1ce54272580 458 memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed
kotakku 0:b1ce54272580 459 for(uint8_t i = 15; i < 19; i++)
kotakku 0:b1ce54272580 460 l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position
kotakku 0:b1ce54272580 461 enable_sixaxis();
kotakku 0:b1ce54272580 462 l2cap_state = TURN_ON_LED;
kotakku 0:b1ce54272580 463 timer = (uint32_t)millis();
kotakku 0:b1ce54272580 464 }
kotakku 0:b1ce54272580 465 break;
kotakku 0:b1ce54272580 466
kotakku 0:b1ce54272580 467 case TURN_ON_LED:
kotakku 0:b1ce54272580 468 if((int32_t)((uint32_t)millis() - timer) > 1000) { // loop 1 second before sending the command
kotakku 0:b1ce54272580 469 if(remote_name_first == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P')
kotakku 0:b1ce54272580 470 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 471 Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80);
kotakku 0:b1ce54272580 472 #endif
kotakku 0:b1ce54272580 473 PS3Connected = true;
kotakku 0:b1ce54272580 474 } else if(remote_name_first == 'N') { // First letter in Navigation Controller ('N')
kotakku 0:b1ce54272580 475 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 476 Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80);
kotakku 0:b1ce54272580 477 #endif
kotakku 0:b1ce54272580 478 PS3NavigationConnected = true;
kotakku 0:b1ce54272580 479 } else if(remote_name_first == 'M') { // First letter in Motion Controller ('M')
kotakku 0:b1ce54272580 480 timer = (uint32_t)millis();
kotakku 0:b1ce54272580 481 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 482 Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80);
kotakku 0:b1ce54272580 483 #endif
kotakku 0:b1ce54272580 484 PS3MoveConnected = true;
kotakku 0:b1ce54272580 485 }
kotakku 0:b1ce54272580 486 ButtonState = 0; // Clear all values
kotakku 0:b1ce54272580 487 OldButtonState = 0;
kotakku 0:b1ce54272580 488 ButtonClickState = 0;
kotakku 0:b1ce54272580 489
kotakku 0:b1ce54272580 490 onInit(); // Turn on the LED on the controller
kotakku 0:b1ce54272580 491 l2cap_state = L2CAP_DONE;
kotakku 0:b1ce54272580 492 }
kotakku 0:b1ce54272580 493 break;
kotakku 0:b1ce54272580 494
kotakku 0:b1ce54272580 495 case L2CAP_DONE:
kotakku 0:b1ce54272580 496 if(PS3MoveConnected) { // The Bulb and rumble values, has to be send at approximately every 5th second for it to stay on
kotakku 0:b1ce54272580 497 if((int32_t)((uint32_t)millis() - timer) > 4000) { // Send at least every 4th second
kotakku 0:b1ce54272580 498 HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on
kotakku 0:b1ce54272580 499 timer = (uint32_t)millis();
kotakku 0:b1ce54272580 500 }
kotakku 0:b1ce54272580 501 }
kotakku 0:b1ce54272580 502 break;
kotakku 0:b1ce54272580 503 }
kotakku 0:b1ce54272580 504 }
kotakku 0:b1ce54272580 505
kotakku 0:b1ce54272580 506 /************************************************************/
kotakku 0:b1ce54272580 507 /* HID Commands */
kotakku 0:b1ce54272580 508 /************************************************************/
kotakku 0:b1ce54272580 509
kotakku 0:b1ce54272580 510 // Playstation Sixaxis Dualshock and Navigation Controller commands
kotakku 0:b1ce54272580 511
kotakku 0:b1ce54272580 512 void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) {
kotakku 0:b1ce54272580 513 if((int32_t)((uint32_t)millis() - timerHID) <= 150) // Check if is has been more than 150ms since last command
kotakku 0:b1ce54272580 514 delay((uint32_t)(150 - ((uint32_t)millis() - timerHID))); // There have to be a delay between commands
kotakku 0:b1ce54272580 515 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
kotakku 0:b1ce54272580 516 timerHID = (uint32_t)millis();
kotakku 0:b1ce54272580 517 }
kotakku 0:b1ce54272580 518
kotakku 0:b1ce54272580 519 void PS3BT::setAllOff() {
kotakku 0:b1ce54272580 520 HIDBuffer[3] = 0x00; // Rumble bytes
kotakku 0:b1ce54272580 521 HIDBuffer[4] = 0x00;
kotakku 0:b1ce54272580 522 HIDBuffer[5] = 0x00;
kotakku 0:b1ce54272580 523 HIDBuffer[6] = 0x00;
kotakku 0:b1ce54272580 524
kotakku 0:b1ce54272580 525 HIDBuffer[11] = 0x00; // LED byte
kotakku 0:b1ce54272580 526
kotakku 0:b1ce54272580 527 HID_Command(HIDBuffer, HID_BUFFERSIZE);
kotakku 0:b1ce54272580 528 }
kotakku 0:b1ce54272580 529
kotakku 0:b1ce54272580 530 void PS3BT::setRumbleOff() {
kotakku 0:b1ce54272580 531 uint8_t rumbleBuf[HID_BUFFERSIZE];
kotakku 0:b1ce54272580 532 memcpy(rumbleBuf, HIDBuffer, HID_BUFFERSIZE);
kotakku 0:b1ce54272580 533 rumbleBuf[3] = 0x00;
kotakku 0:b1ce54272580 534 rumbleBuf[4] = 0x00;
kotakku 0:b1ce54272580 535 rumbleBuf[5] = 0x00;
kotakku 0:b1ce54272580 536 rumbleBuf[6] = 0x00;
kotakku 0:b1ce54272580 537 HID_Command(rumbleBuf, HID_BUFFERSIZE);
kotakku 0:b1ce54272580 538 }
kotakku 0:b1ce54272580 539
kotakku 0:b1ce54272580 540 void PS3BT::setRumbleOn(RumbleEnum mode) {
kotakku 0:b1ce54272580 541 uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow
kotakku 0:b1ce54272580 542 if(mode == RumbleHigh) {
kotakku 0:b1ce54272580 543 power[0] = 0x00;
kotakku 0:b1ce54272580 544 power[1] = 0xff;
kotakku 0:b1ce54272580 545 }
kotakku 0:b1ce54272580 546 setRumbleOn(0xfe, power[0], 0xfe, power[1]);
kotakku 0:b1ce54272580 547 }
kotakku 0:b1ce54272580 548
kotakku 0:b1ce54272580 549 void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) {
kotakku 0:b1ce54272580 550 uint8_t rumbleBuf[HID_BUFFERSIZE];
kotakku 0:b1ce54272580 551 memcpy(rumbleBuf, HIDBuffer, HID_BUFFERSIZE);
kotakku 0:b1ce54272580 552 rumbleBuf[3] = rightDuration;
kotakku 0:b1ce54272580 553 rumbleBuf[4] = rightPower;
kotakku 0:b1ce54272580 554 rumbleBuf[5] = leftDuration;
kotakku 0:b1ce54272580 555 rumbleBuf[6] = leftPower;
kotakku 0:b1ce54272580 556 HID_Command(rumbleBuf, HID_BUFFERSIZE);
kotakku 0:b1ce54272580 557 }
kotakku 0:b1ce54272580 558
kotakku 0:b1ce54272580 559 void PS3BT::setLedRaw(uint8_t value) {
kotakku 0:b1ce54272580 560 HIDBuffer[11] = value << 1;
kotakku 0:b1ce54272580 561 HID_Command(HIDBuffer, HID_BUFFERSIZE);
kotakku 0:b1ce54272580 562 }
kotakku 0:b1ce54272580 563
kotakku 0:b1ce54272580 564 void PS3BT::setLedOff(LEDEnum a) {
kotakku 0:b1ce54272580 565 HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1));
kotakku 0:b1ce54272580 566 HID_Command(HIDBuffer, HID_BUFFERSIZE);
kotakku 0:b1ce54272580 567 }
kotakku 0:b1ce54272580 568
kotakku 0:b1ce54272580 569 void PS3BT::setLedOn(LEDEnum a) {
kotakku 0:b1ce54272580 570 if(a == OFF)
kotakku 0:b1ce54272580 571 setLedRaw(0);
kotakku 0:b1ce54272580 572 else {
kotakku 0:b1ce54272580 573 HIDBuffer[11] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1);
kotakku 0:b1ce54272580 574 HID_Command(HIDBuffer, HID_BUFFERSIZE);
kotakku 0:b1ce54272580 575 }
kotakku 0:b1ce54272580 576 }
kotakku 0:b1ce54272580 577
kotakku 0:b1ce54272580 578 void PS3BT::setLedToggle(LEDEnum a) {
kotakku 0:b1ce54272580 579 HIDBuffer[11] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1);
kotakku 0:b1ce54272580 580 HID_Command(HIDBuffer, HID_BUFFERSIZE);
kotakku 0:b1ce54272580 581 }
kotakku 0:b1ce54272580 582
kotakku 0:b1ce54272580 583 void PS3BT::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth
kotakku 0:b1ce54272580 584 uint8_t cmd_buf[6];
kotakku 0:b1ce54272580 585 cmd_buf[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03)
kotakku 0:b1ce54272580 586 cmd_buf[1] = 0xF4; // Report ID
kotakku 0:b1ce54272580 587 cmd_buf[2] = 0x42; // Special PS3 Controller enable commands
kotakku 0:b1ce54272580 588 cmd_buf[3] = 0x03;
kotakku 0:b1ce54272580 589 cmd_buf[4] = 0x00;
kotakku 0:b1ce54272580 590 cmd_buf[5] = 0x00;
kotakku 0:b1ce54272580 591
kotakku 0:b1ce54272580 592 HID_Command(cmd_buf, 6);
kotakku 0:b1ce54272580 593 }
kotakku 0:b1ce54272580 594
kotakku 0:b1ce54272580 595 // Playstation Move Controller commands
kotakku 0:b1ce54272580 596
kotakku 0:b1ce54272580 597 void PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) {
kotakku 0:b1ce54272580 598 if((int32_t)((uint32_t)millis() - timerHID) <= 150)// Check if is has been less than 150ms since last command
kotakku 0:b1ce54272580 599 delay((uint32_t)(150 - ((uint32_t)millis() - timerHID))); // There have to be a delay between commands
kotakku 0:b1ce54272580 600 pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel
kotakku 0:b1ce54272580 601 timerHID = (uint32_t)millis();
kotakku 0:b1ce54272580 602 }
kotakku 0:b1ce54272580 603
kotakku 0:b1ce54272580 604 void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values
kotakku 0:b1ce54272580 605 // Set the Bulb's values into the write buffer
kotakku 0:b1ce54272580 606 HIDMoveBuffer[3] = r;
kotakku 0:b1ce54272580 607 HIDMoveBuffer[4] = g;
kotakku 0:b1ce54272580 608 HIDMoveBuffer[5] = b;
kotakku 0:b1ce54272580 609
kotakku 0:b1ce54272580 610 HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);
kotakku 0:b1ce54272580 611 }
kotakku 0:b1ce54272580 612
kotakku 0:b1ce54272580 613 void PS3BT::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in enum
kotakku 0:b1ce54272580 614 moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
kotakku 0:b1ce54272580 615 }
kotakku 0:b1ce54272580 616
kotakku 0:b1ce54272580 617 void PS3BT::moveSetRumble(uint8_t rumble) {
kotakku 0:b1ce54272580 618 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 619 if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100)
kotakku 0:b1ce54272580 620 Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80);
kotakku 0:b1ce54272580 621 #endif
kotakku 0:b1ce54272580 622 // Set the rumble value into the write buffer
kotakku 0:b1ce54272580 623 HIDMoveBuffer[7] = rumble;
kotakku 0:b1ce54272580 624
kotakku 0:b1ce54272580 625 HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);
kotakku 0:b1ce54272580 626 }
kotakku 0:b1ce54272580 627
kotakku 0:b1ce54272580 628 void PS3BT::onInit() {
kotakku 0:b1ce54272580 629 if(pFuncOnInit)
kotakku 0:b1ce54272580 630 pFuncOnInit(); // Call the user function
kotakku 0:b1ce54272580 631 else {
kotakku 0:b1ce54272580 632 if(PS3MoveConnected)
kotakku 0:b1ce54272580 633 moveSetBulb(Red);
kotakku 0:b1ce54272580 634 else // Dualshock 3 or Navigation controller
kotakku 0:b1ce54272580 635 setLedOn(static_cast<LEDEnum>(CONTROLLER_LED1));
kotakku 0:b1ce54272580 636 }
kotakku 0:b1ce54272580 637 }
kotakku 0:b1ce54272580 638