mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
Added support for the PS4 controller via Bluetooth
This commit is contained in:
parent
1f33f2bd08
commit
e9bd896ca2
8 changed files with 438 additions and 16 deletions
43
BTD.cpp
43
BTD.cpp
|
@ -302,6 +302,7 @@ void BTD::Initialize() {
|
||||||
incomingWii = false;
|
incomingWii = false;
|
||||||
connectToHIDDevice = false;
|
connectToHIDDevice = false;
|
||||||
incomingHIDDevice = false;
|
incomingHIDDevice = false;
|
||||||
|
incomingPS4 = false;
|
||||||
bAddress = 0; // Clear device address
|
bAddress = 0; // Clear device address
|
||||||
bNumEP = 1; // Must have to be reset to 1
|
bNumEP = 1; // Must have to be reset to 1
|
||||||
qNextPollTime = 0; // Reset next poll time
|
qNextPollTime = 0; // Reset next poll time
|
||||||
|
@ -434,7 +435,6 @@ void BTD::HCI_event_task() {
|
||||||
#endif
|
#endif
|
||||||
for(uint8_t i = 0; i < hcibuf[2]; i++) {
|
for(uint8_t i = 0; i < hcibuf[2]; i++) {
|
||||||
uint8_t offset = 8 * hcibuf[2] + 3 * i;
|
uint8_t offset = 8 * hcibuf[2] + 3 * i;
|
||||||
uint8_t classOfDevice[3];
|
|
||||||
|
|
||||||
for(uint8_t j = 0; j < 3; j++)
|
for(uint8_t j = 0; j < 3; j++)
|
||||||
classOfDevice[j] = hcibuf[j + 4 + offset];
|
classOfDevice[j] = hcibuf[j + 4 + offset];
|
||||||
|
@ -450,12 +450,14 @@ void BTD::HCI_event_task() {
|
||||||
|
|
||||||
hci_set_flag(HCI_FLAG_DEVICE_FOUND);
|
hci_set_flag(HCI_FLAG_DEVICE_FOUND);
|
||||||
break;
|
break;
|
||||||
} else if(pairWithHIDDevice && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC0)) { // Check if it is a mouse or keyboard - see: http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
|
} else if(pairWithHIDDevice && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad - see: http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
|
||||||
#ifdef DEBUG_USB_HOST
|
#ifdef DEBUG_USB_HOST
|
||||||
if(classOfDevice[0] & 0x80)
|
if(classOfDevice[0] & 0x80)
|
||||||
Notify(PSTR("\r\nMouse found"), 0x80);
|
Notify(PSTR("\r\nMouse found"), 0x80);
|
||||||
if(classOfDevice[0] & 0x40)
|
if(classOfDevice[0] & 0x40)
|
||||||
Notify(PSTR("\r\nKeyboard found"), 0x80);
|
Notify(PSTR("\r\nKeyboard found"), 0x80);
|
||||||
|
if(classOfDevice[0] & 0x08)
|
||||||
|
Notify(PSTR("\r\nGamepad found"), 0x80);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(uint8_t j = 0; j < 6; j++)
|
for(uint8_t j = 0; j < 6; j++)
|
||||||
|
@ -516,23 +518,28 @@ void BTD::HCI_event_task() {
|
||||||
for(uint8_t i = 0; i < 6; i++)
|
for(uint8_t i = 0; i < 6; i++)
|
||||||
disc_bdaddr[i] = hcibuf[i + 2];
|
disc_bdaddr[i] = hcibuf[i + 2];
|
||||||
|
|
||||||
if((hcibuf[9] & 0x05) && (hcibuf[8] & 0xC0)) { // Check if it is a mouse or keyboard
|
for(uint8_t i = 0; i < 3; i++)
|
||||||
|
classOfDevice[i] = hcibuf[i + 8];
|
||||||
|
|
||||||
|
if((classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad
|
||||||
#ifdef DEBUG_USB_HOST
|
#ifdef DEBUG_USB_HOST
|
||||||
if(hcibuf[8] & 0x80)
|
if(classOfDevice[0] & 0x80)
|
||||||
Notify(PSTR("\r\nMouse is connecting"), 0x80);
|
Notify(PSTR("\r\nMouse is connecting"), 0x80);
|
||||||
if(hcibuf[8] & 0x40)
|
if(classOfDevice[0] & 0x40)
|
||||||
Notify(PSTR("\r\nKeyboard is connecting"), 0x80);
|
Notify(PSTR("\r\nKeyboard is connecting"), 0x80);
|
||||||
|
if(classOfDevice[0] & 0x08)
|
||||||
|
Notify(PSTR("\r\nGamepad is connecting"), 0x80);
|
||||||
#endif
|
#endif
|
||||||
incomingHIDDevice = true;
|
incomingHIDDevice = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EXTRADEBUG
|
#ifdef EXTRADEBUG
|
||||||
Notify(PSTR("\r\nClass of device: "), 0x80);
|
Notify(PSTR("\r\nClass of device: "), 0x80);
|
||||||
D_PrintHex<uint8_t > (hcibuf[10], 0x80);
|
D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
|
||||||
Notify(PSTR(" "), 0x80);
|
Notify(PSTR(" "), 0x80);
|
||||||
D_PrintHex<uint8_t > (hcibuf[9], 0x80);
|
D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
|
||||||
Notify(PSTR(" "), 0x80);
|
Notify(PSTR(" "), 0x80);
|
||||||
D_PrintHex<uint8_t > (hcibuf[8], 0x80);
|
D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
|
||||||
#endif
|
#endif
|
||||||
hci_set_flag(HCI_FLAG_INCOMING_REQUEST);
|
hci_set_flag(HCI_FLAG_INCOMING_REQUEST);
|
||||||
break;
|
break;
|
||||||
|
@ -816,6 +823,12 @@ void BTD::HCI_task() {
|
||||||
wiiUProController = false;
|
wiiUProController = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(classOfDevice[2] == 0 && classOfDevice[1] == 0x25 && classOfDevice[0] == 0x08 && strncmp((const char*)remote_name, "Wireless Controller", 19) == 0) {
|
||||||
|
#ifdef DEBUG_USB_HOST
|
||||||
|
Notify(PSTR("\r\nPS4 controller is connecting"), 0x80);
|
||||||
|
#endif
|
||||||
|
incomingPS4 = true;
|
||||||
|
}
|
||||||
if(pairWithWii && motionPlusInside)
|
if(pairWithWii && motionPlusInside)
|
||||||
hci_state = HCI_CONNECT_DEVICE_STATE;
|
hci_state = HCI_CONNECT_DEVICE_STATE;
|
||||||
else {
|
else {
|
||||||
|
@ -835,6 +848,9 @@ void BTD::HCI_task() {
|
||||||
}
|
}
|
||||||
D_PrintHex<uint8_t > (disc_bdaddr[0], 0x80);
|
D_PrintHex<uint8_t > (disc_bdaddr[0], 0x80);
|
||||||
#endif
|
#endif
|
||||||
|
if(incomingPS4)
|
||||||
|
connectToHIDDevice = true; // We should always connect to the PS4 controller
|
||||||
|
|
||||||
// Clear these flags for a new connection
|
// Clear these flags for a new connection
|
||||||
l2capConnectionClaimed = false;
|
l2capConnectionClaimed = false;
|
||||||
sdpConnectionClaimed = false;
|
sdpConnectionClaimed = false;
|
||||||
|
@ -866,6 +882,7 @@ void BTD::HCI_task() {
|
||||||
|
|
||||||
connectToWii = incomingWii = pairWithWii = false;
|
connectToWii = incomingWii = pairWithWii = false;
|
||||||
connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = false;
|
connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = false;
|
||||||
|
incomingPS4 = false;
|
||||||
|
|
||||||
hci_state = HCI_SCANNING_STATE;
|
hci_state = HCI_SCANNING_STATE;
|
||||||
}
|
}
|
||||||
|
@ -967,7 +984,7 @@ void BTD::hci_accept_connection() {
|
||||||
hcibuf[6] = disc_bdaddr[3];
|
hcibuf[6] = disc_bdaddr[3];
|
||||||
hcibuf[7] = disc_bdaddr[4];
|
hcibuf[7] = disc_bdaddr[4];
|
||||||
hcibuf[8] = disc_bdaddr[5];
|
hcibuf[8] = disc_bdaddr[5];
|
||||||
hcibuf[9] = 0x00; //switch role to master
|
hcibuf[9] = 0x00; // Switch role to master
|
||||||
|
|
||||||
HCI_Command(hcibuf, 10);
|
HCI_Command(hcibuf, 10);
|
||||||
}
|
}
|
||||||
|
@ -983,10 +1000,10 @@ void BTD::hci_remote_name() {
|
||||||
hcibuf[6] = disc_bdaddr[3];
|
hcibuf[6] = disc_bdaddr[3];
|
||||||
hcibuf[7] = disc_bdaddr[4];
|
hcibuf[7] = disc_bdaddr[4];
|
||||||
hcibuf[8] = disc_bdaddr[5];
|
hcibuf[8] = disc_bdaddr[5];
|
||||||
hcibuf[9] = 0x01; //Page Scan Repetition Mode
|
hcibuf[9] = 0x01; // Page Scan Repetition Mode
|
||||||
hcibuf[10] = 0x00; //Reserved
|
hcibuf[10] = 0x00; // Reserved
|
||||||
hcibuf[11] = 0x00; //Clock offset - low byte
|
hcibuf[11] = 0x00; // Clock offset - low byte
|
||||||
hcibuf[12] = 0x00; //Clock offset - high byte
|
hcibuf[12] = 0x00; // Clock offset - high byte
|
||||||
|
|
||||||
HCI_Command(hcibuf, 13);
|
HCI_Command(hcibuf, 13);
|
||||||
}
|
}
|
||||||
|
|
3
BTD.h
3
BTD.h
|
@ -571,6 +571,9 @@ private:
|
||||||
uint8_t pollInterval;
|
uint8_t pollInterval;
|
||||||
bool bPollEnable;
|
bool bPollEnable;
|
||||||
|
|
||||||
|
bool incomingPS4; // True if a PS4 controller is connecting
|
||||||
|
uint8_t classOfDevice[3]; // Class of device of last device
|
||||||
|
|
||||||
/* Variables used by high level HCI task */
|
/* Variables used by high level HCI task */
|
||||||
uint8_t hci_state; //current state of bluetooth hci connection
|
uint8_t hci_state; //current state of bluetooth hci connection
|
||||||
uint16_t hci_counter; // counter used for bluetooth hci reset loops
|
uint16_t hci_counter; // counter used for bluetooth hci reset loops
|
||||||
|
|
|
@ -192,14 +192,14 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
|
||||||
case 0x01: // Keyboard events
|
case 0x01: // Keyboard events
|
||||||
if(pRptParser[KEYBOARD_PARSER_ID]) {
|
if(pRptParser[KEYBOARD_PARSER_ID]) {
|
||||||
uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
|
uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
|
||||||
pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)length, &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
|
pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02: // Mouse events
|
case 0x02: // Mouse events
|
||||||
if(pRptParser[MOUSE_PARSER_ID]) {
|
if(pRptParser[MOUSE_PARSER_ID]) {
|
||||||
uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
|
uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
|
||||||
pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)length, &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 DEBUG_USB_HOST
|
||||||
|
|
117
PS4BT.cpp
Normal file
117
PS4BT.cpp
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
|
This software may be distributed and modified under the terms of the GNU
|
||||||
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
|
on this software must also be made publicly available under the terms of
|
||||||
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
|
Contact information
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Kristian Lauszus, TKJ Electronics
|
||||||
|
Web : http://www.tkjelectronics.com
|
||||||
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PS4BT.h"
|
||||||
|
|
||||||
|
// To enable serial debugging see "settings.h"
|
||||||
|
//#define PRINTREPORT // Uncomment to print the report send by the PS4 Controller
|
||||||
|
|
||||||
|
/** Buttons on the controller */
|
||||||
|
const uint8_t PS4_BUTTONS[] PROGMEM = {
|
||||||
|
DPAD_UP, // UP
|
||||||
|
DPAD_RIGHT, // RIGHT
|
||||||
|
DPAD_DOWN, // DOWN
|
||||||
|
DPAD_LEFT, // LEFT
|
||||||
|
|
||||||
|
0x0C, // SHARE
|
||||||
|
0x0D, // OPTIONS
|
||||||
|
0x0E, // L3
|
||||||
|
0x0F, // R3
|
||||||
|
|
||||||
|
0x0A, // L2
|
||||||
|
0x0B, // R2
|
||||||
|
0x08, // L1
|
||||||
|
0x09, // R1
|
||||||
|
|
||||||
|
0x07, // TRIANGLE
|
||||||
|
0x06, // CIRCLE
|
||||||
|
0x05, // CROSS
|
||||||
|
0x04, // SQUARE
|
||||||
|
|
||||||
|
0x10, // PS
|
||||||
|
0x11, // KEYPAD
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Analog buttons on the controller */
|
||||||
|
const uint8_t PS4_ANALOG_BUTTONS[] PROGMEM = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, // Skip UP_ANALOG, RIGHT_ANALOG, DOWN_ANALOG, LEFT_ANALOG, SELECT, L3, R3 and START
|
||||||
|
0, // L2_ANALOG
|
||||||
|
1, // R2_ANALOG
|
||||||
|
};
|
||||||
|
|
||||||
|
bool PS4BT::checkDpad(PS4Buttons ps4Buttons, DPADEnum b) {
|
||||||
|
return ps4Buttons.dpad == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PS4BT::getButtonPress(ButtonEnum b) {
|
||||||
|
uint8_t button = pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]);
|
||||||
|
if (b < 4) // Dpad
|
||||||
|
return checkDpad(ps4Data.btn, (DPADEnum)button);
|
||||||
|
else {
|
||||||
|
uint8_t index = button < 8 ? 0 : button < 16 ? 1 : 2;
|
||||||
|
uint8_t mask = (1 << (button - 8 * index));
|
||||||
|
return ps4Data.btn.val[index] & mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PS4BT::getButtonClick(ButtonEnum b) {
|
||||||
|
uint8_t button = pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]);
|
||||||
|
if (b < 4) { // Dpad
|
||||||
|
if (checkDpad(buttonClickState, (DPADEnum)button)) {
|
||||||
|
buttonClickState.dpad = DPAD_OFF;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
uint8_t index = button < 8 ? 0 : button < 16 ? 1 : 2;
|
||||||
|
uint8_t mask = (1 << (button - 8 * index));
|
||||||
|
|
||||||
|
bool click = buttonClickState.val[index] & mask;
|
||||||
|
buttonClickState.val[index] &= ~mask; // Clear "click" event
|
||||||
|
return click;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t PS4BT::getAnalogButton(ButtonEnum a) {
|
||||||
|
return (uint8_t)(ps4Data.trigger[pgm_read_byte(&PS4_ANALOG_BUTTONS[(uint8_t)a])]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t PS4BT::getAnalogHat(AnalogHatEnum a) {
|
||||||
|
return ps4Data.hatValue[(uint8_t)a];
|
||||||
|
}
|
||||||
|
|
||||||
|
void PS4BT::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
|
||||||
|
if (len == sizeof(PS4Data) && buf) {
|
||||||
|
memcpy(&ps4Data, buf, len);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < sizeof(ps4Data.btn); i++) {
|
||||||
|
if (ps4Data.btn.val[i] != oldButtonState.val[i]) {
|
||||||
|
buttonClickState.val[i] = ps4Data.btn.val[i] & ~oldButtonState.val[i]; // Update click state variable
|
||||||
|
oldButtonState.val[i] = ps4Data.btn.val[i];
|
||||||
|
if (i == 0)
|
||||||
|
buttonClickState.dpad = ps4Data.btn.dpad; // The DPAD buttons does not set the different bits, but set a value corresponding to the buttons pressed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef PRINTREPORT
|
||||||
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
|
D_PrintHex<uint8_t > (buf[i], 0x80);
|
||||||
|
Notify(PSTR(" "), 0x80);
|
||||||
|
}
|
||||||
|
Notify(PSTR("\r\n"), 0x80);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
176
PS4BT.h
Normal file
176
PS4BT.h
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
|
This software may be distributed and modified under the terms of the GNU
|
||||||
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
|
on this software must also be made publicly available under the terms of
|
||||||
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
|
Contact information
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Kristian Lauszus, TKJ Electronics
|
||||||
|
Web : http://www.tkjelectronics.com
|
||||||
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ps4bt_h_
|
||||||
|
#define _ps4bt_h_
|
||||||
|
|
||||||
|
#include "BTHID.h"
|
||||||
|
#include "PS3Enums.h"
|
||||||
|
|
||||||
|
enum DPADEnum {
|
||||||
|
DPAD_UP = 0x0,
|
||||||
|
DPAD_UP_RIGHT = 0x1,
|
||||||
|
DPAD_RIGHT = 0x2,
|
||||||
|
DPAD_RIGHT_DOWN = 0x3,
|
||||||
|
DPAD_DOWN = 0x4,
|
||||||
|
DPAD_DOWN_LEFT = 0x5,
|
||||||
|
DPAD_LEFT = 0x6,
|
||||||
|
DPAD_LEFT_UP = 0x7,
|
||||||
|
DPAD_OFF = 0x8,
|
||||||
|
};
|
||||||
|
|
||||||
|
union PS4Buttons {
|
||||||
|
struct {
|
||||||
|
uint8_t dpad : 4;
|
||||||
|
uint8_t square : 1;
|
||||||
|
uint8_t cross : 1;
|
||||||
|
uint8_t circle : 1;
|
||||||
|
uint8_t triangle : 1;
|
||||||
|
|
||||||
|
uint8_t l1 : 1;
|
||||||
|
uint8_t r1 : 1;
|
||||||
|
uint8_t l2 : 1;
|
||||||
|
uint8_t r2 : 1;
|
||||||
|
uint8_t share : 1;
|
||||||
|
uint8_t options : 1;
|
||||||
|
uint8_t l3 : 1;
|
||||||
|
uint8_t r3 : 1;
|
||||||
|
|
||||||
|
uint8_t ps : 1;
|
||||||
|
uint8_t keypad : 1;
|
||||||
|
uint8_t dummy : 6;
|
||||||
|
};
|
||||||
|
uint8_t val[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PS4Data {
|
||||||
|
uint8_t hatValue[4];
|
||||||
|
PS4Buttons btn;
|
||||||
|
uint8_t trigger[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** This BluetoothService class implements support for the PS4 controller via Bluetooth. */
|
||||||
|
class PS4BT : public HIDReportParser {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor for the PS4BT class.
|
||||||
|
* @param p Pointer to the BTD class instance.
|
||||||
|
*/
|
||||||
|
PS4BT(BTHID *p) :
|
||||||
|
pBthid(p) {
|
||||||
|
pBthid->SetReportParser(KEYBOARD_PARSER_ID, this);
|
||||||
|
Reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
|
||||||
|
|
||||||
|
/** @name PS4 Controller functions */
|
||||||
|
/**
|
||||||
|
* getButtonPress(ButtonEnum b) will return true as long as the button is held down.
|
||||||
|
*
|
||||||
|
* While getButtonClick(ButtonEnum b) will only return it once.
|
||||||
|
*
|
||||||
|
* So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),
|
||||||
|
* but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).
|
||||||
|
* @param b ::ButtonEnum to read.
|
||||||
|
* @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.
|
||||||
|
*/
|
||||||
|
bool getButtonPress(ButtonEnum b);
|
||||||
|
bool getButtonClick(ButtonEnum b);
|
||||||
|
/**@}*/
|
||||||
|
/** @name PS4 Controller functions */
|
||||||
|
/**
|
||||||
|
* Used to get the analog value from button presses.
|
||||||
|
* @param a The ::ButtonEnum to read.
|
||||||
|
* The supported buttons are:
|
||||||
|
* ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,
|
||||||
|
* ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.
|
||||||
|
* @return Analog value in the range of 0-255.
|
||||||
|
*/
|
||||||
|
uint8_t getAnalogButton(ButtonEnum a);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to read the analog joystick.
|
||||||
|
* @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.
|
||||||
|
* @return Return the analog value in the range of 0-255.
|
||||||
|
*/
|
||||||
|
uint8_t getAnalogHat(AnalogHatEnum a);
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
|
/** True if a device is connected */
|
||||||
|
bool connected() {
|
||||||
|
if (pBthid)
|
||||||
|
return pBthid->connected;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Used this to disconnect the devices. */
|
||||||
|
void disconnect() {
|
||||||
|
if (pBthid)
|
||||||
|
pBthid->disconnect();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Call this to start the paring sequence with a device */
|
||||||
|
void pair(void) {
|
||||||
|
if (pBthid)
|
||||||
|
pBthid->pair();
|
||||||
|
};
|
||||||
|
|
||||||
|
void Reset() {
|
||||||
|
uint8_t i;
|
||||||
|
for (0; i < sizeof(ps4Data.hatValue); i++)
|
||||||
|
ps4Data.hatValue[i] = 127;
|
||||||
|
for (0; i < sizeof(PS4Buttons); i++) {
|
||||||
|
ps4Data.btn.val[i] = 0;
|
||||||
|
oldButtonState.val[i] = 0;
|
||||||
|
}
|
||||||
|
for (0; i < sizeof(ps4Data.trigger); i++)
|
||||||
|
ps4Data.trigger[i] = 0;
|
||||||
|
|
||||||
|
ps4Data.btn.dpad = DPAD_OFF;
|
||||||
|
oldButtonState.dpad = DPAD_OFF;
|
||||||
|
buttonClickState.dpad = DPAD_OFF;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to call your own function when the device is successfully initialized.
|
||||||
|
* @param funcOnInit Function to call.
|
||||||
|
*/
|
||||||
|
void attachOnInit(void (*funcOnInit)(void)) {
|
||||||
|
pFuncOnInit = funcOnInit;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Called when a device is successfully initialized.
|
||||||
|
* Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
|
||||||
|
* This is useful for instance if you want to set the LEDs in a specific way.
|
||||||
|
*/
|
||||||
|
void onInit() {
|
||||||
|
Reset();
|
||||||
|
if(pFuncOnInit)
|
||||||
|
pFuncOnInit(); // Call the user function
|
||||||
|
};
|
||||||
|
void (*pFuncOnInit)(void); // Pointer to function called in onInit()
|
||||||
|
|
||||||
|
bool checkDpad(PS4Buttons ps4Buttons, DPADEnum b); // Used to check PS4 DPAD buttons
|
||||||
|
|
||||||
|
BTHID *pBthid; // Pointer to BTHID instance
|
||||||
|
PS4Data ps4Data;
|
||||||
|
PS4Buttons oldButtonState, buttonClickState;
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -94,6 +94,12 @@ enum ButtonEnum {
|
||||||
T = 18, // Covers 12 bits - we only need to read the top 8
|
T = 18, // Covers 12 bits - we only need to read the top 8
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|
||||||
|
/** PS4 controllers buttons - SHARE and OPTIONS are present instead of SELECT and START */
|
||||||
|
SHARE = 4,
|
||||||
|
OPTIONS = 5,
|
||||||
|
KEYPAD = 17,
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
/**@{*/
|
/**@{*/
|
||||||
/** Xbox buttons */
|
/** Xbox buttons */
|
||||||
BACK = 4,
|
BACK = 4,
|
||||||
|
|
98
examples/Bluetooth/PS4BT/PS4BT.ino
Normal file
98
examples/Bluetooth/PS4BT/PS4BT.ino
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
Example sketch for the PS4 Bluetooth library - developed by Kristian Lauszus
|
||||||
|
For more information visit my blog: http://blog.tkjelectronics.dk/ or
|
||||||
|
send me an e-mail: kristianl@tkjelectronics.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <PS4BT.h>
|
||||||
|
#include <usbhub.h>
|
||||||
|
|
||||||
|
// Satisfy IDE, which only needs to see the include statment in the ino.
|
||||||
|
#ifdef dobogusinclude
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
USB Usb;
|
||||||
|
//USBHub Hub1(&Usb); // Some dongles have a hub inside
|
||||||
|
BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
|
||||||
|
|
||||||
|
/* You can create the instance of the BTHID class in two ways */
|
||||||
|
// This will start an inquiry and then pair with the PS4 controller - you only have to do this once
|
||||||
|
BTHID bthid(&Btd, PAIR);
|
||||||
|
|
||||||
|
// After that you can simply create the instance like so and then press the PS button on the device
|
||||||
|
//BTHID bthid(&Btd);
|
||||||
|
|
||||||
|
PS4BT PS4(&bthid); // You should not modify this instance
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
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
|
||||||
|
if (Usb.Init() == -1) {
|
||||||
|
Serial.print(F("\r\nOSC did not start"));
|
||||||
|
while (1); // Halt
|
||||||
|
}
|
||||||
|
Serial.print(F("\r\nPS4 Bluetooth Library Started"));
|
||||||
|
}
|
||||||
|
void loop() {
|
||||||
|
Usb.Task();
|
||||||
|
|
||||||
|
if (PS4.connected()) {
|
||||||
|
if (PS4.getAnalogHat(LeftHatX) > 137 || PS4.getAnalogHat(LeftHatX) < 117 || PS4.getAnalogHat(LeftHatY) > 137 || PS4.getAnalogHat(LeftHatY) < 117 || PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) {
|
||||||
|
Serial.print(F("\r\nLeftHatX: "));
|
||||||
|
Serial.print(PS4.getAnalogHat(LeftHatX));
|
||||||
|
Serial.print(F("\tLeftHatY: "));
|
||||||
|
Serial.print(PS4.getAnalogHat(LeftHatY));
|
||||||
|
Serial.print(F("\tRightHatX: "));
|
||||||
|
Serial.print(PS4.getAnalogHat(RightHatX));
|
||||||
|
Serial.print(F("\tRightHatY: "));
|
||||||
|
Serial.print(PS4.getAnalogHat(RightHatY));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PS4.getAnalogButton(L2) || PS4.getAnalogButton(R2)) { // These are the only analog buttons on the PS4 controller
|
||||||
|
Serial.print(F("\r\nL2: "));
|
||||||
|
Serial.print(PS4.getAnalogButton(L2));
|
||||||
|
Serial.print(F("\tR2: "));
|
||||||
|
Serial.print(PS4.getAnalogButton(R2));
|
||||||
|
}
|
||||||
|
if (PS4.getButtonClick(PS)) {
|
||||||
|
Serial.print(F("\r\nPS"));
|
||||||
|
PS4.disconnect();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (PS4.getButtonClick(TRIANGLE))
|
||||||
|
Serial.print(F("\r\nTraingle"));
|
||||||
|
if (PS4.getButtonClick(CIRCLE))
|
||||||
|
Serial.print(F("\r\nCircle"));
|
||||||
|
if (PS4.getButtonClick(CROSS))
|
||||||
|
Serial.print(F("\r\nCross"));
|
||||||
|
if (PS4.getButtonClick(SQUARE))
|
||||||
|
Serial.print(F("\r\nSquare"));
|
||||||
|
|
||||||
|
if (PS4.getButtonClick(UP))
|
||||||
|
Serial.print(F("\r\nUp"));
|
||||||
|
if (PS4.getButtonClick(RIGHT))
|
||||||
|
Serial.print(F("\r\nRight"));
|
||||||
|
if (PS4.getButtonClick(DOWN))
|
||||||
|
Serial.print(F("\r\nDown"));
|
||||||
|
if (PS4.getButtonClick(LEFT))
|
||||||
|
Serial.print(F("\r\nLeft"));
|
||||||
|
|
||||||
|
if (PS4.getButtonClick(L1))
|
||||||
|
Serial.print(F("\r\nL1"));
|
||||||
|
if (PS4.getButtonClick(L3))
|
||||||
|
Serial.print(F("\r\nL3"));
|
||||||
|
if (PS4.getButtonClick(R1))
|
||||||
|
Serial.print(F("\r\nR1"));
|
||||||
|
if (PS4.getButtonClick(R3))
|
||||||
|
Serial.print(F("\r\nR3"));
|
||||||
|
|
||||||
|
if (PS4.getButtonClick(SHARE))
|
||||||
|
Serial.print(F("\r\nShare"));
|
||||||
|
if (PS4.getButtonClick(OPTIONS))
|
||||||
|
Serial.print(F("\r\nOptions"));
|
||||||
|
if (PS4.getButtonClick(KEYPAD))
|
||||||
|
Serial.print(F("\r\nKeypad"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,13 +25,14 @@ BTD KEYWORD1
|
||||||
Task KEYWORD2
|
Task KEYWORD2
|
||||||
|
|
||||||
####################################################
|
####################################################
|
||||||
# Syntax Coloring Map For PS3 Bluetooth/USB Library
|
# Syntax Coloring Map For PS3/PS4 Bluetooth/USB Library
|
||||||
####################################################
|
####################################################
|
||||||
|
|
||||||
####################################################
|
####################################################
|
||||||
# Datatypes (KEYWORD1)
|
# Datatypes (KEYWORD1)
|
||||||
####################################################
|
####################################################
|
||||||
|
|
||||||
|
PS4BT KEYWORD1
|
||||||
PS3BT KEYWORD1
|
PS3BT KEYWORD1
|
||||||
PS3USB KEYWORD1
|
PS3USB KEYWORD1
|
||||||
|
|
||||||
|
@ -118,6 +119,10 @@ PS LITERAL1
|
||||||
MOVE LITERAL1
|
MOVE LITERAL1
|
||||||
T LITERAL1
|
T LITERAL1
|
||||||
|
|
||||||
|
SHARE LITERAL1
|
||||||
|
OPTIONS LITERAL1
|
||||||
|
KEYPAD LITERAL1
|
||||||
|
|
||||||
LeftHatX LITERAL1
|
LeftHatX LITERAL1
|
||||||
LeftHatY LITERAL1
|
LeftHatY LITERAL1
|
||||||
RightHatX LITERAL1
|
RightHatX LITERAL1
|
||||||
|
|
Loading…
Reference in a new issue