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