Can now read the IMU and touchpad values of the PS4 controller via Bluetooth as well

Thanks to Frank Zhao - see: http://eleccelerator.com/wiki/index.php?title=DualShock_4#0x11
This commit is contained in:
Kristian Lauszus 2014-01-22 05:13:49 +01:00
parent e2bf041286
commit 2a1db31cf1
7 changed files with 71 additions and 21 deletions

View file

@ -202,7 +202,7 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
if(pRptParser[MOUSE_PARSER_ID]) if(pRptParser[MOUSE_PARSER_ID])
pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
break; break;
#ifdef DEBUG_USB_HOST #ifdef EXTRADEBUG
default: default:
Notify(PSTR("\r\nUnknown Report type: "), 0x80); Notify(PSTR("\r\nUnknown Report type: "), 0x80);
D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);

28
BTHID.h
View file

@ -126,8 +126,20 @@ protected:
} }
/**@}*/ /**@}*/
/** Pointer to BTD instance */
BTD *pBtd;
/** HCI Handle for connection */
uint16_t hci_handle;
/** L2CAP source CID for HID_Control */
uint8_t control_scid[2];
/** L2CAP source CID for HID_Interrupt */
uint8_t interrupt_scid[2];
private: private:
BTD *pBtd; // Pointer to BTD instance
HIDReportParser *pRptParser[NUM_PARSERS]; // Pointer to HIDReportParsers. HIDReportParser *pRptParser[NUM_PARSERS]; // Pointer to HIDReportParsers.
/** Set report protocol. */ /** Set report protocol. */
@ -148,19 +160,13 @@ private:
void L2CAP_task(); // L2CAP state machine void L2CAP_task(); // L2CAP state machine
/* Variables filled from HCI event management */
uint16_t hci_handle;
bool activeConnection; // Used to indicate if it already has established a connection bool activeConnection; // Used to indicate if it already has established a connection
/* Variables used by high level L2CAP task */ /* Variables used for L2CAP communication */
uint8_t control_dcid[2]; // L2CAP device CID for HID_Control - Always 0x0070
uint8_t interrupt_dcid[2]; // L2CAP device CID for HID_Interrupt - Always 0x0071
uint8_t identifier; // Identifier for connection
uint8_t l2cap_state; uint8_t l2cap_state;
uint32_t l2cap_event_flag; // l2cap flags of received Bluetooth events uint32_t l2cap_event_flag; // l2cap flags of received Bluetooth events
/* L2CAP Channels */
uint8_t control_scid[2]; // L2CAP source CID for HID_Control
uint8_t control_dcid[2]; // 0x0070
uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt
uint8_t interrupt_dcid[2]; // 0x0071
uint8_t identifier; // Identifier for connection
}; };
#endif #endif

13
PS4BT.h
View file

@ -72,6 +72,7 @@ protected:
* This is useful for instance if you want to set the LEDs in a specific way. * This is useful for instance if you want to set the LEDs in a specific way.
*/ */
virtual void OnInitBTHID() { virtual void OnInitBTHID() {
enable_sixaxis(); // Make the controller to send out the entire output report
if (pFuncOnInit) if (pFuncOnInit)
pFuncOnInit(); // Call the user function pFuncOnInit(); // Call the user function
}; };
@ -84,5 +85,17 @@ protected:
private: private:
void (*pFuncOnInit)(void); // Pointer to function called in onInit() void (*pFuncOnInit)(void); // Pointer to function called in onInit()
void HID_Command(uint8_t *data, uint8_t nbytes) {
pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]);
};
void enable_sixaxis() { // Command used to make the PS4 controller send out the entire output report
uint8_t buf[2];
buf[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03)
buf[1] = 0x02; // Report ID
HID_Command(buf, 2);
};
}; };
#endif #endif

View file

@ -76,17 +76,22 @@ uint8_t PS4Parser::getAnalogHat(AnalogHatEnum a) {
void PS4Parser::Parse(uint8_t len, uint8_t *buf) { void PS4Parser::Parse(uint8_t len, uint8_t *buf) {
if (len > 0 && buf) { if (len > 0 && buf) {
#ifdef PRINTREPORT #ifdef PRINTREPORT
Notify(PSTR("\r\n"), 0x80);
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
D_PrintHex<uint8_t > (buf[i], 0x80); D_PrintHex<uint8_t > (buf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
Notify(PSTR("\r\n"), 0x80);
#endif #endif
memcpy(&ps4Data, buf, min(len, sizeof(ps4Data)));
if (ps4Data.reportId != 0x01) { if (buf[0] == 0x01) // Check report ID
memcpy(&ps4Data, buf + 1, min(len - 1, sizeof(ps4Data)));
else if (buf[0] == 0x11) // This report is send via Bluetooth, it has an offset of 2 compared to the USB data
memcpy(&ps4Data, buf + 3, min(len - 3, sizeof(ps4Data)));
else {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nUnknown report id"), 0x80); Notify(PSTR("\r\nUnknown report id: "), 0x80);
D_PrintHex<uint8_t > (buf[0], 0x80);
#endif #endif
return; return;
} }

View file

@ -87,7 +87,6 @@ struct touchpadXY {
struct PS4Data { struct PS4Data {
/* Button and joystick values */ /* Button and joystick values */
uint8_t reportId; // Always 0x01
uint8_t hatValue[4]; uint8_t hatValue[4];
PS4Buttons btn; PS4Buttons btn;
uint8_t trigger[2]; uint8_t trigger[2];

View file

@ -124,8 +124,6 @@ The [PS4BT.ino](examples/Bluetooth/PS4BT/PS4BT.ino) and [PS4USB.ino](examples/PS
I still have not figured out how to turn rumble on and off and set the color of the light, but hopefully I will figure that out soon. I still have not figured out how to turn rumble on and off and set the color of the light, but hopefully I will figure that out soon.
Also the gyro, accelerometer and touchpad values are still only available via USB at the moment.
Before you can use the PS4 controller via Bluetooth you will need to pair with it. Before you can use the PS4 controller via Bluetooth you will need to pair with it.
Simply create the PS4BT instance like so: ```PS4BT PS4(&Btd, PAIR);``` and then hold down the PS and Share button at the same time, the PS4 controller will then start to blink rapidly indicating that it is in paring mode. Simply create the PS4BT instance like so: ```PS4BT PS4(&Btd, PAIR);``` and then hold down the PS and Share button at the same time, the PS4 controller will then start to blink rapidly indicating that it is in paring mode.
@ -134,6 +132,8 @@ It should then automatically pair the dongle with your controller. This only hav
For information see the following blog post: <http://blog.tkjelectronics.dk/2014/01/ps4-controller-now-supported-by-the-usb-host-library/>. For information see the following blog post: <http://blog.tkjelectronics.dk/2014/01/ps4-controller-now-supported-by-the-usb-host-library/>.
Also check out this excellent Wiki by Frank Zhao about the PS4 controller: <http://eleccelerator.com/wiki/index.php?title=DualShock_4>.
### PS3 Library ### PS3 Library
These libraries consist of the [PS3BT](PS3BT.cpp) and [PS3USB](PS3USB.cpp). These libraries allows you to use a Dualshock 3, Navigation or a Motion controller with the USB Host Shield both via Bluetooth and USB. These libraries consist of the [PS3BT](PS3BT.cpp) and [PS3USB](PS3USB.cpp). These libraries allows you to use a Dualshock 3, Navigation or a Motion controller with the USB Host Shield both via Bluetooth and USB.

View file

@ -24,6 +24,8 @@ PS4BT PS4(&Btd, PAIR);
// After that you can simply create the instance like so and then press the PS button on the device // After that you can simply create the instance like so and then press the PS button on the device
//PS4BT PS4(&Btd); //PS4BT PS4(&Btd);
boolean printAngle, printTouch;
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
@ -88,10 +90,35 @@ void loop() {
if (PS4.getButtonClick(SHARE)) if (PS4.getButtonClick(SHARE))
Serial.print(F("\r\nShare")); Serial.print(F("\r\nShare"));
if (PS4.getButtonClick(OPTIONS)) if (PS4.getButtonClick(OPTIONS)) {
Serial.print(F("\r\nOptions")); Serial.print(F("\r\nOptions"));
if (PS4.getButtonClick(TOUCHPAD)) printAngle = !printAngle;
}
if (PS4.getButtonClick(TOUCHPAD)) {
Serial.print(F("\r\nTouchpad")); Serial.print(F("\r\nTouchpad"));
printTouch = !printTouch;
}
if (printAngle) { // Print angle calculated using the accelerometer only
Serial.print(F("\r\nPitch: "));
Serial.print(PS4.getAngle(Pitch));
Serial.print(F("\tRoll: "));
Serial.print(PS4.getAngle(Roll));
}
if (printTouch) { // Print the x, y coordinates of the touchpad
if (PS4.isTouching(0) || PS4.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad
Serial.print(F("\r\n"));
for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers
if (PS4.isTouching(i)) { // Print the position of the finger if it is touching the touchpad
Serial.print(F("X")); Serial.print(i + 1); Serial.print(F(": "));
Serial.print(PS4.getX(i));
Serial.print(F("\tY")); Serial.print(i + 1); Serial.print(F(": "));
Serial.print(PS4.getY(i));
Serial.print(F("\t"));
}
}
}
} }
} }
} }