USB Host Shield 2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 
23 PS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) :
24 pBtd(p) // pointer to USB class instance - mandatory
25 {
26  if (pBtd)
27  pBtd->registerServiceClass(this); // Register it as a Bluetooth service
28 
29  pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead
30  pBtd->my_bdaddr[4] = btadr4;
31  pBtd->my_bdaddr[3] = btadr3;
32  pBtd->my_bdaddr[2] = btadr2;
33  pBtd->my_bdaddr[1] = btadr1;
34  pBtd->my_bdaddr[0] = btadr0;
35 
36  HIDBuffer[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02)
37  HIDBuffer[1] = 0x01; // Report ID
38 
39  // Needed for PS3 Move Controller commands to work via bluetooth
40  HIDMoveBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
41  HIDMoveBuffer[1] = 0x02; // Report ID
42 
43  /* Set device cid for the control and intterrupt channelse - LSB */
44  control_dcid[0] = 0x40; // 0x0040
45  control_dcid[1] = 0x00;
46  interrupt_dcid[0] = 0x41; // 0x0041
47  interrupt_dcid[1] = 0x00;
48 
49  Reset();
50 }
51 
53  return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b]));
54 }
55 
57  uint32_t button = pgm_read_dword(&BUTTONS[(uint8_t)b]);
58  bool click = (ButtonClickState & button);
59  ButtonClickState &= ~button; // Clear "click" event
60  return click;
61 }
62 
64  return (uint8_t)(l2capinbuf[pgm_read_byte(&ANALOGBUTTONS[(uint8_t)a])]);
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  double accXval, accYval, accZval;
90 
91  if (PS3Connected) {
92  // Data for the Kionix KXPC4 used in the DualShock 3
93  const double zeroG = 511.5; // 1.65/3.3*1023 (1.65V)
94  accXval = -((double)getSensor(aX) - zeroG);
95  accYval = -((double)getSensor(aY) - zeroG);
96  accZval = -((double)getSensor(aZ) - zeroG);
97  } else if (PS3MoveConnected) {
98  // It's a Kionix KXSC4 inside the Motion controller
99  const uint16_t zeroG = 0x8000;
100  accXval = -(int16_t)(getSensor(aXmove) - zeroG);
101  accYval = (int16_t)(getSensor(aYmove) - zeroG);
102  accZval = (int16_t)(getSensor(aZmove) - zeroG);
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 (atan2(accYval, accZval) + PI) * RAD_TO_DEG;
111  else
112  return (atan2(accXval, accZval) + PI) * RAD_TO_DEG;
113 }
114 
115 double PS3BT::get9DOFValues(Sensor a) { // Thanks to Manfred Piendl
116  if (!PS3MoveConnected)
117  return 0;
118  int16_t value = getSensor(a);
119  if (a == mXmove || a == mYmove || a == mZmove) {
120  if (value > 2047)
121  value -= 0x1000;
122  return (double)value / 3.2; // 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 (double)value / 442.0; // 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 (double)value / 11.6; // unit: deg/s
136  else if (a == gYmove)
137  return (double)value / 11.2; // unit: deg/s
138  else // gZmove
139  return (double)value / 9.6; // unit: deg/s
140  } else
141  return 0;
142 }
143 
145  if (PS3MoveConnected) {
146  int16_t input = getSensor(tempMove);
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 
165  char statusOutput[100];
166 
167  strcpy(statusOutput, "ConnectionStatus: ");
168 
169  if (getStatus(Plugged)) strcat(statusOutput, "Plugged");
170  else if (getStatus(Unplugged)) strcat(statusOutput, "Unplugged");
171  else strcat(statusOutput, "Error");
172 
173 
174  strcat(statusOutput, " - PowerRating: ");
175  if (getStatus(Charging)) strcat(statusOutput, "Charging");
176  else if (getStatus(NotCharging)) strcat(statusOutput, "Not Charging");
177  else if (getStatus(Shutdown)) strcat(statusOutput, "Shutdown");
178  else if (getStatus(Dying)) strcat(statusOutput, "Dying");
179  else if (getStatus(Low)) strcat(statusOutput, "Low");
180  else if (getStatus(High)) strcat(statusOutput, "High");
181  else if (getStatus(Full)) strcat(statusOutput, "Full");
182  else strcat(statusOutput, "Error");
183 
184  strcat(statusOutput, " - WirelessStatus: ");
185 
186  if (getStatus(CableRumble)) strcat(statusOutput, "Cable - Rumble is on");
187  else if (getStatus(Cable)) strcat(statusOutput, "Cable - Rumble is off");
188  else if (getStatus(BluetoothRumble)) strcat(statusOutput, "Bluetooth - Rumble is on");
189  else if (getStatus(Bluetooth)) strcat(statusOutput, "Bluetooth - Rumble is off");
190  else strcat(statusOutput, "Error");
191 
192  return statusOutput;
193 
194  } else if (PS3MoveConnected) {
195  char statusOutput[50];
196 
197  strcpy(statusOutput, "PowerRating: ");
198 
199  if (getStatus(MoveCharging)) strcat(statusOutput, "Charging");
200  else if (getStatus(MoveNotCharging)) strcat(statusOutput, "Not Charging");
201  else if (getStatus(MoveShutdown)) strcat(statusOutput, "Shutdown");
202  else if (getStatus(MoveDying)) strcat(statusOutput, "Dying");
203  else if (getStatus(MoveLow)) strcat(statusOutput, "Low");
204  else if (getStatus(MoveHigh)) strcat(statusOutput, "High");
205  else if (getStatus(MoveFull)) strcat(statusOutput, "Full");
206  else strcat(statusOutput, "Error");
207 
208  return statusOutput;
209  } else
210  return "Error";
211 }
212 
213 void PS3BT::Reset() {
214  PS3Connected = false;
215  PS3MoveConnected = false;
216  PS3NavigationConnected = false;
217  activeConnection = false;
218  l2cap_event_flag = 0; // Reset flags
219  l2cap_state = L2CAP_WAIT;
220 
221  // Needed for PS3 Dualshock Controller commands to work via bluetooth
222  for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
223  HIDBuffer[i + 2] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID
224 }
225 
226 void PS3BT::disconnect() { // Use this void to disconnect any of the controllers
227  //First the HID interrupt channel has to be disconencted, then the HID control channel and finally the HCI connection
228  pBtd->l2cap_disconnection_request(hci_handle, 0x0A, interrupt_scid, interrupt_dcid);
229  Reset();
230  l2cap_state = L2CAP_INTERRUPT_DISCONNECT;
231 }
232 
233 void PS3BT::ACLData(uint8_t* ACLData) {
234  if (!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) {
235  if (ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) {
236  if ((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) {
237  pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
238  activeConnection = true;
239  hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
240  l2cap_state = L2CAP_WAIT;
241  for (uint8_t i = 0; i < 30; i++)
242  remote_name[i] = pBtd->remote_name[i]; // Store the remote name for the connection
243 #ifdef DEBUG_USB_HOST
244  if (pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle
245  Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80);
246  Notify(pBtd->hci_version, 0x80);
247  Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80);
248  }
249 #endif
250  }
251  }
252  }
253  if (((ACLData[0] | (ACLData[1] << 8)) == (hci_handle | 0x2000))) { //acl_handle_ok
254  memcpy(l2capinbuf, ACLData, BULK_MAXPKTSIZE);
255  if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U
256  if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
257 #ifdef DEBUG_USB_HOST
258  Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
259  D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
260  Notify(PSTR(" "), 0x80);
261  D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
262  Notify(PSTR(" Data: "), 0x80);
263  D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
264  Notify(PSTR(" "), 0x80);
265  D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
266  Notify(PSTR(" "), 0x80);
267  D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
268  Notify(PSTR(" "), 0x80);
269  D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
270 #endif
271  } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
272 #ifdef EXTRADEBUG
273  Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
274  D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
275  Notify(PSTR(" "), 0x80);
276  D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
277  Notify(PSTR(" SCID: "), 0x80);
278  D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
279  Notify(PSTR(" "), 0x80);
280  D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
281  Notify(PSTR(" Identifier: "), 0x80);
282  D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
283 #endif
284  if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
285  identifier = l2capinbuf[9];
286  control_scid[0] = l2capinbuf[14];
287  control_scid[1] = l2capinbuf[15];
288  l2cap_event_flag |= L2CAP_FLAG_CONNECTION_CONTROL_REQUEST;
289  } else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
290  identifier = l2capinbuf[9];
291  interrupt_scid[0] = l2capinbuf[14];
292  interrupt_scid[1] = l2capinbuf[15];
293  l2cap_event_flag |= L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST;
294  }
295  } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
296  if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
297  if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
298  //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
299  l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_SUCCESS;
300  } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
301  //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
302  l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS;
303  }
304  }
305  } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
306  if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
307  //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
308  identifier = l2capinbuf[9];
309  l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_REQUEST;
310  } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
311  //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
312  identifier = l2capinbuf[9];
313  l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_REQUEST;
314  }
315  } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
316  if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
317 #ifdef DEBUG_USB_HOST
318  Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
319 #endif
320  identifier = l2capinbuf[9];
321  pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);
322  Reset();
323  } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
324 #ifdef DEBUG_USB_HOST
325  Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
326 #endif
327  identifier = l2capinbuf[9];
328  pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);
329  Reset();
330  }
331  } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
332  if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
333  //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
334  identifier = l2capinbuf[9];
335  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE;
336  } else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
337  //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
338  identifier = l2capinbuf[9];
339  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE;
340  }
341  }
342 #ifdef EXTRADEBUG
343  else {
344  Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
345  D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
346  }
347 #endif
348  } else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
349  //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
351  /* Read Report */
352  if (l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
354  ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16));
355  else if (PS3MoveConnected)
356  ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16));
357 
358  //Notify(PSTR("\r\nButtonState", 0x80);
359  //PrintHex<uint32_t>(ButtonState, 0x80);
360 
361  if (ButtonState != OldButtonState) {
362  ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
363  OldButtonState = ButtonState;
364  }
365 
366 #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
367  for (uint8_t i = 10; i < 58; i++) {
368  D_PrintHex<uint8_t > (l2capinbuf[i], 0x80);
369  Notify(PSTR(" "), 0x80);
370  }
371  Notify(PSTR("\r\n"), 0x80);
372 #endif
373  }
374  }
375  }
376  L2CAP_task();
377  }
378 }
379 
380 void PS3BT::L2CAP_task() {
381  switch (l2cap_state) {
382  case L2CAP_WAIT:
384 #ifdef DEBUG_USB_HOST
385  Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
386 #endif
387  pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING);
388  delay(1);
389  pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL);
390  identifier++;
391  delay(1);
392  pBtd->l2cap_config_request(hci_handle, identifier, control_scid);
393  l2cap_state = L2CAP_CONTROL_REQUEST;
394  }
395  break;
398 #ifdef DEBUG_USB_HOST
399  Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
400 #endif
401  pBtd->l2cap_config_response(hci_handle, identifier, control_scid);
402  l2cap_state = L2CAP_CONTROL_SUCCESS;
403  }
404  break;
405 
408 #ifdef DEBUG_USB_HOST
409  Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
410 #endif
411  l2cap_state = L2CAP_INTERRUPT_SETUP;
412  }
413  break;
416 #ifdef DEBUG_USB_HOST
417  Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
418 #endif
419  pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING);
420  delay(1);
421  pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);
422  identifier++;
423  delay(1);
424  pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
425 
426  l2cap_state = L2CAP_INTERRUPT_REQUEST;
427  }
428  break;
431 #ifdef DEBUG_USB_HOST
432  Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
433 #endif
434  pBtd->l2cap_config_response(hci_handle, identifier, interrupt_scid);
435  l2cap_state = L2CAP_INTERRUPT_SUCCESS;
436  }
437  break;
440 #ifdef DEBUG_USB_HOST
441  Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80);
442 #endif
443  if (remote_name[0] == 'M') { // First letter in Motion Controller ('M')
444  memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed
445  l2cap_state = L2CAP_HID_PS3_LED;
446  } else
447  l2cap_state = L2CAP_HID_ENABLE_SIXAXIS;
448  timer = millis();
449  }
450  break;
451 
452  /* These states are handled in Run() */
453 
456 #ifdef DEBUG_USB_HOST
457  Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
458 #endif
459  identifier++;
460  pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid);
461  l2cap_state = L2CAP_CONTROL_DISCONNECT;
462  }
463  break;
464 
467 #ifdef DEBUG_USB_HOST
468  Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
469 #endif
470  pBtd->hci_disconnect(hci_handle);
471  hci_handle = -1; // Reset handle
472  l2cap_event_flag = 0; // Reset flags
473  l2cap_state = L2CAP_WAIT;
474  }
475  break;
476  }
477 }
478 
479 void PS3BT::Run() {
480  switch (l2cap_state) {
482  if (millis() - timer > 1000) { // loop 1 second before sending the command
483  memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed
484  for (uint8_t i = 15; i < 19; i++)
485  l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position
486  enable_sixaxis();
487  l2cap_state = L2CAP_HID_PS3_LED;
488  timer = millis();
489  }
490  break;
491 
492  case L2CAP_HID_PS3_LED:
493  if (millis() - timer > 1000) { // loop 1 second before sending the command
494  if (remote_name[0] == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P')
495 #ifdef DEBUG_USB_HOST
496  Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80);
497 #endif
498  PS3Connected = true;
499  } else if (remote_name[0] == 'N') { // First letter in Navigation Controller ('N')
500 #ifdef DEBUG_USB_HOST
501  Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80);
502 #endif
503  PS3NavigationConnected = true;
504  } else if (remote_name[0] == 'M') { // First letter in Motion Controller ('M')
505  timerBulbRumble = millis();
506 #ifdef DEBUG_USB_HOST
507  Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80);
508 #endif
509  PS3MoveConnected = true;
510  }
511  ButtonState = 0; // Clear all values
512  OldButtonState = 0;
513  ButtonClickState = 0;
514 
515  onInit(); // Turn on the LED on the controller
516  l2cap_state = L2CAP_DONE;
517  }
518  break;
519 
520  case L2CAP_DONE:
521  if (PS3MoveConnected) { // The Bulb and rumble values, has to be send at aproximatly every 5th second for it to stay on
522  if (millis() - timerBulbRumble > 4000) { // Send at least every 4th second
523  HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on
524  timerBulbRumble = millis();
525  }
526  }
527  break;
528  }
529 }
530 
531 /************************************************************/
532 /* HID Commands */
533 /************************************************************/
534 
535 // Playstation Sixaxis Dualshock and Navigation Controller commands
536 
537 void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) {
538  if (millis() - timerHID <= 150) // Check if is has been more than 150ms since last command
539  delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands
540  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
541  timerHID = millis();
542 }
543 
545  HIDBuffer[3] = 0x00; // Rumble bytes
546  HIDBuffer[4] = 0x00;
547  HIDBuffer[5] = 0x00;
548  HIDBuffer[6] = 0x00;
549 
550  HIDBuffer[11] = 0x00; // LED byte
551 
552  HID_Command(HIDBuffer, HID_BUFFERSIZE);
553 }
554 
556  HIDBuffer[3] = 0x00;
557  HIDBuffer[4] = 0x00;
558  HIDBuffer[5] = 0x00;
559  HIDBuffer[6] = 0x00;
560 
561  HID_Command(HIDBuffer, HID_BUFFERSIZE);
562 }
563 
565  uint8_t power[2] = { 0xff, 0x00 }; // Defaults to RumbleLow
566  if (mode == RumbleHigh) {
567  power[0] = 0x00;
568  power[1] = 0xff;
569  }
570  setRumbleOn(0xfe, power[0], 0xfe, power[1]);
571 }
572 
573 void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) {
574  HIDBuffer[3] = rightDuration;
575  HIDBuffer[4] = rightPower;
576  HIDBuffer[5] = leftDuration;
577  HIDBuffer[6] = leftPower;
578  HID_Command(HIDBuffer, HID_BUFFERSIZE);
579 }
580 
581 void PS3BT::setLedRaw(uint8_t value) {
582  HIDBuffer[11] = value << 1;
583  HID_Command(HIDBuffer, HID_BUFFERSIZE);
584 }
585 
587  HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1));
588  HID_Command(HIDBuffer, HID_BUFFERSIZE);
589 }
590 
592  HIDBuffer[11] |= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1);
593  HID_Command(HIDBuffer, HID_BUFFERSIZE);
594 }
595 
597  HIDBuffer[11] ^= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1);
598  HID_Command(HIDBuffer, HID_BUFFERSIZE);
599 }
600 
601 void PS3BT::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth
602  uint8_t cmd_buf[6];
603  cmd_buf[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03)
604  cmd_buf[1] = 0xF4; // Report ID
605  cmd_buf[2] = 0x42; // Special PS3 Controller enable commands
606  cmd_buf[3] = 0x03;
607  cmd_buf[4] = 0x00;
608  cmd_buf[5] = 0x00;
609 
610  HID_Command(cmd_buf, 6);
611 }
612 
613 // Playstation Move Controller commands
614 
615 void PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) {
616  if (millis() - timerHID <= 150)// Check if is has been less than 150ms since last command
617  delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands
618  pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel
619  timerHID = millis();
620 }
621 
622 void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { //Use this to set the Color using RGB values
623  // Set the Bulb's values into the write buffer
624  HIDMoveBuffer[3] = r;
625  HIDMoveBuffer[4] = g;
626  HIDMoveBuffer[5] = b;
627 
628  HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);
629 }
630 
631 void PS3BT::moveSetBulb(Colors color) { //Use this to set the Color using the predefined colors in enum
632  moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
633 }
634 
635 void PS3BT::moveSetRumble(uint8_t rumble) {
636 #ifdef DEBUG_USB_HOST
637  if (rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100)
638  Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80);
639 #endif
640  // Set the rumble value into the write buffer
641  HIDMoveBuffer[7] = rumble;
642 
643  HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);
644 }
645 
646 void PS3BT::onInit() {
647  if (pFuncOnInit)
648  pFuncOnInit(); // Call the user function
649  else {
650  if (PS3MoveConnected)
651  moveSetBulb(Red);
652  else // Dualshock 3 or Navigation controller
653  setLedOn(LED1);
654  }
655 }
bool incomingWii
Definition: BTD.h:432
#define L2CAP_FLAG_CONFIG_CONTROL_REQUEST
Definition: PS3BT.h:41
uint8_t getAnalogHat(AnalogHat a)
Definition: PS3BT.cpp:67
bool getButtonClick(Button b)
Definition: PS3BT.cpp:56
bool PS3NavigationConnected
Definition: PS3BT.h:229
Definition: PS3Enums.h:117
void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid, uint8_t result)
Definition: BTD.cpp:1222
String getStatusString()
Definition: PS3BT.cpp:163
virtual void Run()
Definition: PS3BT.cpp:479
#define SUCCESSFUL
Definition: BTD.h:121
Definition: BTD.h:158
void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid)
Definition: BTD.cpp:1275
#define l2cap_config_request_interrupt_flag
Definition: PS3BT.h:54
Definition: PS3Enums.h:192
#define l2cap_disconnect_response_interrupt_flag
Definition: BTHID.h:59
uint8_t hci_version
Definition: BTD.h:422
Sensor
Definition: PS3Enums.h:141
bool pairWithWii
Definition: BTD.h:434
const uint8_t PS3_REPORT_BUFFER[]
Definition: PS3Enums.h:24
String getTemperature()
Definition: PS3BT.cpp:144
Definition: PS3Enums.h:193
#define L2CAP_INTERRUPT_REQUEST
Definition: PS3BT.h:31
void moveSetRumble(uint8_t rumble)
Definition: PS3BT.cpp:635
Definition: PS3Enums.h:194
const uint8_t LEDS[]
Definition: PS3Enums.h:43
const uint8_t ANALOGBUTTONS[]
Definition: PS3Enums.h:93
void setAllOff()
Definition: PS3BT.cpp:544
int16_t getSensor(Sensor a)
Definition: PS3BT.cpp:71
double get9DOFValues(Sensor a)
Definition: PS3BT.cpp:115
uint8_t remote_name[30]
Definition: BTD.h:416
#define HID_BUFFERSIZE
Definition: PS3BT.h:24
virtual void Reset()
Definition: PS3BT.cpp:213
#define L2CAP_INTERRUPT_SUCCESS
Definition: PS3BT.h:32
#define L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS
Definition: BTHID.h:47
#define l2cap_config_request_control_flag
Definition: PS3BT.h:51
#define l2cap_connection_request_control_flag
Definition: BTHID.h:60
double getAngle(Angle a)
Definition: PS3BT.cpp:88
void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid)
Definition: BTD.cpp:1288
#define L2CAP_FLAG_CONFIG_INTERRUPT_REQUEST
Definition: PS3BT.h:44
#define Notify(...)
Definition: message.h:44
#define L2CAP_WAIT
Definition: BTHID.h:26
#define L2CAP_CONTROL_REQUEST
Definition: PS3BT.h:28
#define L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE
Definition: BTHID.h:49
#define l2cap_connection_request_interrupt_flag
Definition: BTHID.h:61
#define HID_CTRL_PSM
Definition: BTD.h:126
Definition: PS3Enums.h:147
Status
Definition: PS3Enums.h:182
Colors
Definition: PS3Enums.h:115
#define L2CAP_INTERRUPT_DISCONNECT
Definition: BTHID.h:40
Rumble
Definition: PS3Enums.h:210
bool connectToWii
Definition: BTD.h:428
uint16_t hci_handle
Definition: BTD.h:412
bool PS3Connected
Definition: PS3BT.h:221
void hci_disconnect(uint16_t handle)
Definition: BTD.cpp:1133
void setLedToggle(LED a)
Definition: PS3BT.cpp:596
void moveSetBulb(uint8_t r, uint8_t g, uint8_t b)
Definition: PS3BT.cpp:622
bool PS3MoveConnected
Definition: PS3BT.h:227
#define L2CAP_DONE
Definition: BTHID.h:38
uint8_t my_bdaddr[6]
Definition: BTD.h:410
#define L2CAP_INTERRUPT_SETUP
Definition: BTHID.h:30
#define l2cap_disconnect_response_control_flag
Definition: BTHID.h:58
#define L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST
Definition: BTHID.h:51
#define L2CAP_FLAG_CONNECTION_CONTROL_REQUEST
Definition: BTHID.h:50
Definition: PS3Enums.h:143
#define L2CAP_CMD_CONFIG_REQUEST
Definition: BTD.h:112
#define L2CAP_CMD_DISCONNECT_REQUEST
Definition: BTD.h:114
Angle
Definition: PS3Enums.h:177
void setLedOn(LED a)
Definition: PS3BT.cpp:591
#define BULK_MAXPKTSIZE
Definition: BTD.h:33
#define HID_INTR_PSM
Definition: BTD.h:127
Definition: PS3Enums.h:149
int8_t registerServiceClass(BluetoothService *pService)
Definition: BTD.h:258
bool l2capConnectionClaimed
Definition: BTD.h:398
#define L2CAP_CMD_DISCONNECT_RESPONSE
Definition: BTD.h:115
virtual void ACLData(uint8_t *ACLData)
Definition: PS3BT.cpp:233
#define L2CAP_CMD_CONFIG_RESPONSE
Definition: BTD.h:113
#define L2CAP_HID_ENABLE_SIXAXIS
Definition: PS3BT.h:33
#define l2cap_config_success_control_flag
Definition: BTHID.h:56
#define l2cap_config_success_interrupt_flag
Definition: BTHID.h:57
void setLedOff()
Definition: PS3BT.h:180
#define L2CAP_HID_PS3_LED
Definition: PS3BT.h:34
Button
bool getStatus(Status c)
Definition: PS3BT.cpp:159
#define L2CAP_CONTROL_SUCCESS
Definition: BTHID.h:29
void setRumbleOn(Rumble mode)
Definition: PS3BT.cpp:564
#define PS3_REPORT_BUFFER_SIZE
Definition: PS3Enums.h:37
virtual void disconnect()
Definition: PS3BT.cpp:226
void L2CAP_Command(uint16_t handle, uint8_t *data, uint8_t nbytes, uint8_t channelLow=0x01, uint8_t channelHigh=0x00)
Definition: BTD.cpp:1181
void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t *scid)
Definition: BTD.cpp:1256
#define PENDING
Definition: BTD.h:120
void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t *dcid)
Definition: BTD.cpp:1239
#define L2CAP_CMD_CONNECTION_REQUEST
Definition: BTD.h:110
uint8_t getAnalogButton(Button a)
Definition: PS3BT.cpp:63
#define L2CAP_CONTROL_DISCONNECT
Definition: BTHID.h:41
#define L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE
Definition: BTHID.h:48
void setLedRaw(uint8_t value)
Definition: PS3BT.cpp:581
AnalogHat
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
const uint32_t BUTTONS[]
Definition: PS3Enums.h:62
Definition: PS3Enums.h:145
bool getButtonPress(Button b)
Definition: PS3BT.cpp:52
void setRumbleOff()
Definition: PS3BT.cpp:555
#define L2CAP_FLAG_CONFIG_CONTROL_SUCCESS
Definition: BTHID.h:46
#define L2CAP_CMD_COMMAND_REJECT
Definition: BTD.h:109