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 uncomment "#define DEBUG_USB_HOST" in message.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  if (l2capinbuf == NULL)
65  return 0;
66  return (uint8_t)(l2capinbuf[pgm_read_byte(&ANALOGBUTTONS[(uint8_t)a])]);
67 }
68 
70  if (l2capinbuf == NULL)
71  return 0;
72  return (uint8_t)(l2capinbuf[(uint8_t)a + 15]);
73 }
74 
76  if (l2capinbuf == NULL)
77  return 0;
78  if (PS3Connected) {
79  if (a == aX || a == aY || a == aZ || a == gZ)
80  return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]);
81  else
82  return 0;
83  } else if (PS3MoveConnected) {
84  if (a == mXmove || a == mYmove) // These are all 12-bits long
85  return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1]));
86  else if (a == mZmove || a == tempMove) // The tempearature is also 12 bits long
87  return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4));
88  else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove
89  return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8));
90  } else
91  return 0;
92 }
93 
95  double accXval;
96  double accYval;
97  double accZval;
98 
99  if (PS3Connected) {
100  // Data for the Kionix KXPC4 used in the DualShock 3
101  const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V)
102  accXval = -((double)getSensor(aX) - zeroG);
103  accYval = -((double)getSensor(aY) - zeroG);
104  accZval = -((double)getSensor(aZ) - zeroG);
105  } else if (PS3MoveConnected) {
106  // It's a Kionix KXSC4 inside the Motion controller
107  const uint16_t zeroG = 0x8000;
108  accXval = -(int16_t)(getSensor(aXmove) - zeroG);
109  accYval = (int16_t)(getSensor(aYmove) - zeroG);
110  accZval = (int16_t)(getSensor(aZmove) - zeroG);
111  } else
112  return 0;
113 
114  // Convert to 360 degrees resolution
115  // atan2 outputs the value of -π to π (radians)
116  // We are then converting it to 0 to 2π and then to degrees
117  if (a == Pitch) {
118  double angle = (atan2(accYval, accZval) + PI) * RAD_TO_DEG;
119  return angle;
120  } else {
121  double angle = (atan2(accXval, accZval) + PI) * RAD_TO_DEG;
122  return angle;
123  }
124 }
125 
126 double PS3BT::get9DOFValues(Sensor a) { // Thanks to Manfred Piendl
127  if (!PS3MoveConnected)
128  return 0;
129  int16_t value = getSensor(a);
130  if (a == mXmove || a == mYmove || a == mZmove) {
131  if (value > 2047)
132  value -= 0x1000;
133  return (double)value / 3.2; // unit: muT = 10^(-6) Tesla
134  } else if (a == aXmove || a == aYmove || a == aZmove) {
135  if (value < 0)
136  value += 0x8000;
137  else
138  value -= 0x8000;
139  return (double)value / 442.0; // unit: m/(s^2)
140  } else if (a == gXmove || a == gYmove || a == gZmove) {
141  if (value < 0)
142  value += 0x8000;
143  else
144  value -= 0x8000;
145  if (a == gXmove)
146  return (double)value / 11.6; // unit: deg/s
147  else if (a == gYmove)
148  return (double)value / 11.2; // unit: deg/s
149  else // gZmove
150  return (double)value / 9.6; // unit: deg/s
151  } else
152  return 0;
153 }
154 
156  if (PS3MoveConnected) {
157  int16_t input = getSensor(tempMove);
158 
159  String output = String(input / 100);
160  output += ".";
161  if (input % 100 < 10)
162  output += "0";
163  output += String(input % 100);
164 
165  return output;
166  } else
167  return "Error";
168 }
169 
171  if (l2capinbuf == NULL)
172  return false;
173  if (l2capinbuf[(uint16_t)c >> 8] == ((uint8_t)c & 0xff))
174  return true;
175  return false;
176 }
177 
180  char statusOutput[100];
181 
182  strcpy(statusOutput, "ConnectionStatus: ");
183 
184  if (getStatus(Plugged)) strcat(statusOutput, "Plugged");
185  else if (getStatus(Unplugged)) strcat(statusOutput, "Unplugged");
186  else strcat(statusOutput, "Error");
187 
188 
189  strcat(statusOutput, " - PowerRating: ");
190  if (getStatus(Charging)) strcat(statusOutput, "Charging");
191  else if (getStatus(NotCharging)) strcat(statusOutput, "Not Charging");
192  else if (getStatus(Shutdown)) strcat(statusOutput, "Shutdown");
193  else if (getStatus(Dying)) strcat(statusOutput, "Dying");
194  else if (getStatus(Low)) strcat(statusOutput, "Low");
195  else if (getStatus(High)) strcat(statusOutput, "High");
196  else if (getStatus(Full)) strcat(statusOutput, "Full");
197  else strcat(statusOutput, "Error");
198 
199  strcat(statusOutput, " - WirelessStatus: ");
200 
201  if (getStatus(CableRumble)) strcat(statusOutput, "Cable - Rumble is on");
202  else if (getStatus(Cable)) strcat(statusOutput, "Cable - Rumble is off");
203  else if (getStatus(BluetoothRumble)) strcat(statusOutput, "Bluetooth - Rumble is on");
204  else if (getStatus(Bluetooth)) strcat(statusOutput, "Bluetooth - Rumble is off");
205  else strcat(statusOutput, "Error");
206 
207  return statusOutput;
208 
209  } else if (PS3MoveConnected) {
210  char statusOutput[50];
211 
212  strcpy(statusOutput, "PowerRating: ");
213 
214  if (getStatus(MoveCharging)) strcat(statusOutput, "Charging");
215  else if (getStatus(MoveNotCharging)) strcat(statusOutput, "Not Charging");
216  else if (getStatus(MoveShutdown)) strcat(statusOutput, "Shutdown");
217  else if (getStatus(MoveDying)) strcat(statusOutput, "Dying");
218  else if (getStatus(MoveLow)) strcat(statusOutput, "Low");
219  else if (getStatus(MoveHigh)) strcat(statusOutput, "High");
220  else if (getStatus(MoveFull)) strcat(statusOutput, "Full");
221  else strcat(statusOutput, "Error");
222 
223  return statusOutput;
224  } else
225  return "Error";
226 }
227 
228 void PS3BT::Reset() {
229  PS3Connected = false;
230  PS3MoveConnected = false;
231  PS3NavigationConnected = false;
232  activeConnection = false;
233  l2cap_event_flag = 0; // Reset flags
234  l2cap_state = L2CAP_WAIT;
235 
236  // Needed for PS3 Dualshock Controller commands to work via bluetooth
237  for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
238  HIDBuffer[i + 2] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID
239 }
240 
241 void PS3BT::disconnect() { // Use this void to disconnect any of the controllers
242  //First the HID interrupt channel has to be disconencted, then the HID control channel and finally the HCI connection
243  pBtd->l2cap_disconnection_request(hci_handle, 0x0A, interrupt_scid, interrupt_dcid);
244  Reset();
245  l2cap_state = L2CAP_INTERRUPT_DISCONNECT;
246 }
247 
248 void PS3BT::ACLData(uint8_t* ACLData) {
249  if (!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) {
250  if (ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) {
251  if ((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) {
252  pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
253  activeConnection = true;
254  hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
255  l2cap_state = L2CAP_WAIT;
256  for (uint8_t i = 0; i < 30; i++)
257  remote_name[i] = pBtd->remote_name[i]; // Store the remote name for the connection
258 #ifdef DEBUG_USB_HOST
259  if (pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle
260  Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80);
261  Notify(pBtd->hci_version, 0x80);
262  Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80);
263  }
264 #endif
265  }
266  }
267  }
268  if (((ACLData[0] | (ACLData[1] << 8)) == (hci_handle | 0x2000))) { //acl_handle_ok
269  for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++)
270  l2capinbuf[i] = ACLData[i];
271  if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U
272  if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
273 #ifdef DEBUG_USB_HOST
274  Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
275  D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
276  Notify(PSTR(" "), 0x80);
277  D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
278  Notify(PSTR(" Data: "), 0x80);
279  D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
280  Notify(PSTR(" "), 0x80);
281  D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
282  Notify(PSTR(" "), 0x80);
283  D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
284  Notify(PSTR(" "), 0x80);
285  D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
286 #endif
287  } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
288 #ifdef EXTRADEBUG
289  Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
290  D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
291  Notify(PSTR(" "), 0x80);
292  D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
293  Notify(PSTR(" SCID: "), 0x80);
294  D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
295  Notify(PSTR(" "), 0x80);
296  D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
297  Notify(PSTR(" Identifier: "), 0x80);
298  D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
299 #endif
300  if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
301  identifier = l2capinbuf[9];
302  control_scid[0] = l2capinbuf[14];
303  control_scid[1] = l2capinbuf[15];
304  l2cap_event_flag |= L2CAP_FLAG_CONNECTION_CONTROL_REQUEST;
305  } else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
306  identifier = l2capinbuf[9];
307  interrupt_scid[0] = l2capinbuf[14];
308  interrupt_scid[1] = l2capinbuf[15];
309  l2cap_event_flag |= L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST;
310  }
311  } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
312  if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
313  if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
314  //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
315  l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_SUCCESS;
316  } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
317  //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
318  l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS;
319  }
320  }
321  } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
322  if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
323  //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
324  identifier = l2capinbuf[9];
325  l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_REQUEST;
326  } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
327  //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
328  identifier = l2capinbuf[9];
329  l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_REQUEST;
330  }
331  } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
332  if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
333 #ifdef DEBUG_USB_HOST
334  Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
335 #endif
336  identifier = l2capinbuf[9];
337  pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);
338  Reset();
339  } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
340 #ifdef DEBUG_USB_HOST
341  Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
342 #endif
343  identifier = l2capinbuf[9];
344  pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);
345  Reset();
346  }
347  } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
348  if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
349  //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
350  identifier = l2capinbuf[9];
351  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE;
352  } else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
353  //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
354  identifier = l2capinbuf[9];
355  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE;
356  }
357  }
358 #ifdef EXTRADEBUG
359  else {
360  Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
361  D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
362  }
363 #endif
364  } else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
365  //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
367  /* Read Report */
368  if (l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
370  ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16));
371  else if (PS3MoveConnected)
372  ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16));
373 
374  //Notify(PSTR("\r\nButtonState", 0x80);
375  //PrintHex<uint32_t>(ButtonState, 0x80);
376 
377  if (ButtonState != OldButtonState) {
378  ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
379  OldButtonState = ButtonState;
380  }
381 
382 #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
383  for (uint8_t i = 10; i < 58; i++) {
384  D_PrintHex<uint8_t > (l2capinbuf[i], 0x80);
385  Notify(PSTR(" "), 0x80);
386  }
387  Notify(PSTR("\r\n"), 0x80);
388 #endif
389  }
390  }
391  }
392  L2CAP_task();
393  }
394 }
395 
396 void PS3BT::L2CAP_task() {
397  switch (l2cap_state) {
398  case L2CAP_WAIT:
400 #ifdef DEBUG_USB_HOST
401  Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
402 #endif
403  pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING);
404  delay(1);
405  pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL);
406  identifier++;
407  delay(1);
408  pBtd->l2cap_config_request(hci_handle, identifier, control_scid);
409  l2cap_state = L2CAP_CONTROL_REQUEST;
410  }
411  break;
414 #ifdef DEBUG_USB_HOST
415  Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
416 #endif
417  pBtd->l2cap_config_response(hci_handle, identifier, control_scid);
418  l2cap_state = L2CAP_CONTROL_SUCCESS;
419  }
420  break;
421 
424 #ifdef DEBUG_USB_HOST
425  Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
426 #endif
427  l2cap_state = L2CAP_INTERRUPT_SETUP;
428  }
429  break;
432 #ifdef DEBUG_USB_HOST
433  Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
434 #endif
435  pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING);
436  delay(1);
437  pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);
438  identifier++;
439  delay(1);
440  pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
441 
442  l2cap_state = L2CAP_INTERRUPT_REQUEST;
443  }
444  break;
447 #ifdef DEBUG_USB_HOST
448  Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
449 #endif
450  pBtd->l2cap_config_response(hci_handle, identifier, interrupt_scid);
451  l2cap_state = L2CAP_INTERRUPT_SUCCESS;
452  }
453  break;
456 #ifdef DEBUG_USB_HOST
457  Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80);
458 #endif
459  if (remote_name[0] == 'M') { // First letter in Motion Controller ('M')
460  for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) // Reset l2cap in buffer as it sometimes read it as a button has been pressed
461  l2capinbuf[i] = 0;
462  l2cap_state = L2CAP_HID_PS3_LED;
463  } else
464  l2cap_state = L2CAP_HID_ENABLE_SIXAXIS;
465  timer = millis();
466  }
467  break;
468 
469  /* These states are handled in Run() */
470 
473 #ifdef DEBUG_USB_HOST
474  Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
475 #endif
476  identifier++;
477  pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid);
478  l2cap_state = L2CAP_CONTROL_DISCONNECT;
479  }
480  break;
481 
484 #ifdef DEBUG_USB_HOST
485  Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
486 #endif
487  pBtd->hci_disconnect(hci_handle);
488  hci_handle = -1; // Reset handle
489  l2cap_event_flag = 0; // Reset flags
490  l2cap_state = L2CAP_WAIT;
491  }
492  break;
493  }
494 }
495 
496 void PS3BT::Run() {
497  switch (l2cap_state) {
499  if (millis() - timer > 1000) { // loop 1 second before sending the command
500  for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) // Reset l2cap in buffer as it sometimes read it as a button has been pressed
501  l2capinbuf[i] = 0;
502  for (uint8_t i = 15; i < 19; i++)
503  l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position
504  enable_sixaxis();
505  l2cap_state = L2CAP_HID_PS3_LED;
506  timer = millis();
507  }
508  break;
509 
510  case L2CAP_HID_PS3_LED:
511  if (millis() - timer > 1000) { // loop 1 second before sending the command
512  if (remote_name[0] == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P')
513 #ifdef DEBUG_USB_HOST
514  Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80);
515 #endif
516  PS3Connected = true;
517  } else if (remote_name[0] == 'N') { // First letter in Navigation Controller ('N')
518 #ifdef DEBUG_USB_HOST
519  Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80);
520 #endif
521  PS3NavigationConnected = true;
522  } else if (remote_name[0] == 'M') { // First letter in Motion Controller ('M')
523  timerBulbRumble = millis();
524 #ifdef DEBUG_USB_HOST
525  Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80);
526 #endif
527  PS3MoveConnected = true;
528  }
529  ButtonState = 0; // Clear all values
530  OldButtonState = 0;
531  ButtonClickState = 0;
532 
533  onInit(); // Turn on the LED on the controller
534  l2cap_state = L2CAP_DONE;
535  }
536  break;
537 
538  case L2CAP_DONE:
539  if (PS3MoveConnected) { //The Bulb and rumble values, has to be send at aproximatly every 5th second for it to stay on
540  if (millis() - timerBulbRumble > 4000) { //Send at least every 4th second
541  HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); //The Bulb and rumble values, has to be written again and again, for it to stay turned on
542  timerBulbRumble = millis();
543  }
544  }
545  break;
546  }
547 }
548 
549 /************************************************************/
550 /* HID Commands */
551 /************************************************************/
552 
553 //Playstation Sixaxis Dualshock and Navigation Controller commands
554 
555 void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) {
556  if (millis() - timerHID <= 250)// Check if is has been more than 250ms since last command
557  delay((uint32_t)(250 - (millis() - timerHID))); //There have to be a delay between commands
558  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
559  timerHID = millis();
560 }
561 
563  for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
564  HIDBuffer[i + 2] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID
565 
566  HID_Command(HIDBuffer, HID_BUFFERSIZE);
567 }
568 
570  HIDBuffer[3] = 0x00;
571  HIDBuffer[4] = 0x00;
572  HIDBuffer[5] = 0x00;
573  HIDBuffer[6] = 0x00;
574 
575  HID_Command(HIDBuffer, HID_BUFFERSIZE);
576 }
577 
579  uint8_t power[2] = { 0xff, 0x00 }; // Defaults to RumbleLow
580  if (mode == RumbleHigh) {
581  power[0] = 0x00;
582  power[1] = 0xff;
583  }
584  setRumbleOn(0xfe, power[0], 0xfe, power[1]);
585 }
586 
587 void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) {
588  HIDBuffer[3] = rightDuration;
589  HIDBuffer[4] = rightPower;
590  HIDBuffer[5] = leftDuration;
591  HIDBuffer[6] = leftPower;
592  HID_Command(HIDBuffer, HID_BUFFERSIZE);
593 }
594 
595 void PS3BT::setLedRaw(uint8_t value) {
596  HIDBuffer[11] = value << 1;
597  HID_Command(HIDBuffer, HID_BUFFERSIZE);
598 }
600  HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1));
601  HID_Command(HIDBuffer, HID_BUFFERSIZE);
602 }
603 
605  HIDBuffer[11] |= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1);
606  HID_Command(HIDBuffer, HID_BUFFERSIZE);
607 }
608 
610  HIDBuffer[11] ^= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1);
611  HID_Command(HIDBuffer, HID_BUFFERSIZE);
612 }
613 
614 void PS3BT::enable_sixaxis() { //Command used to enable the Dualshock 3 and Navigation controller to send data via USB
615  uint8_t cmd_buf[6];
616  cmd_buf[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03)
617  cmd_buf[1] = 0xF4; // Report ID
618  cmd_buf[2] = 0x42; // Special PS3 Controller enable commands
619  cmd_buf[3] = 0x03;
620  cmd_buf[4] = 0x00;
621  cmd_buf[5] = 0x00;
622 
623  HID_Command(cmd_buf, 6);
624 }
625 
626 //Playstation Move Controller commands
627 
628 void PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) {
629  if (millis() - timerHID <= 250)// Check if is has been less than 200ms since last command
630  delay((uint32_t)(250 - (millis() - timerHID))); //There have to be a delay between commands
631  pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel
632  timerHID = millis();
633 }
634 
635 void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { //Use this to set the Color using RGB values
636  //set the Bulb's values into the write buffer
637  HIDMoveBuffer[3] = r;
638  HIDMoveBuffer[4] = g;
639  HIDMoveBuffer[5] = b;
640 
641  HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);
642 }
643 
644 void PS3BT::moveSetBulb(Colors color) { //Use this to set the Color using the predefined colors in enum
645  moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
646 }
647 
648 void PS3BT::moveSetRumble(uint8_t rumble) {
649 #ifdef DEBUG_USB_HOST
650  if (rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100)
651  Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80);
652 #endif
653  //set the rumble value into the write buffer
654  HIDMoveBuffer[7] = rumble;
655 
656  HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);
657 }
658 
659 void PS3BT::onInit() {
660  if (pFuncOnInit)
661  pFuncOnInit(); // Call the user function
662  else {
663  if (PS3MoveConnected)
664  moveSetBulb(Red);
665  else // Dualshock 3 or Navigation controller
666  setLedOn(LED1);
667  }
668 }