mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
PS5 is now also working via Bluetooth
However the output report is still not working
This commit is contained in:
parent
ee7bf6e5a0
commit
28a75dea6b
11 changed files with 480 additions and 28 deletions
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
@ -8,7 +8,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
# find examples -type f -name "*.ino" | rev | cut -d/ -f2- | rev | sort | sed -z 's/\n/, /g'
|
||||
example: [examples/acm/acm_terminal, examples/adk/adk_barcode, examples/adk/ArduinoBlinkLED, examples/adk/demokit_20, examples/adk/term_test, examples/adk/term_time, examples/Bluetooth/BTHID, examples/Bluetooth/PS3BT, examples/Bluetooth/PS3Multi, examples/Bluetooth/PS3SPP, examples/Bluetooth/PS4BT, examples/Bluetooth/SPP, examples/Bluetooth/SPPMulti, examples/Bluetooth/Wii, examples/Bluetooth/WiiBalanceBoard, examples/Bluetooth/WiiIRCamera, examples/Bluetooth/WiiMulti, examples/Bluetooth/WiiUProController, examples/board_qc, examples/cdc_XR21B1411/XR_terminal, examples/ftdi/USBFTDILoopback, examples/GPIO/Blink, examples/GPIO/Blink_LowLevel, examples/GPIO/Input, examples/HID/le3dp, examples/HID/scale, examples/HID/SRWS1, examples/HID/t16km, examples/HID/USBHIDBootKbd, examples/HID/USBHIDBootKbdAndMouse, examples/HID/USBHIDBootMouse, examples/HID/USBHID_desc, examples/HID/USBHIDJoystick, examples/HID/USBHIDMultimediaKbd, examples/hub_demo, examples/max_LCD, examples/pl2303/pl2303_gprs_terminal, examples/pl2303/pl2303_gps, examples/pl2303/pl2303_tinygps, examples/pl2303/pl2303_xbee_terminal, examples/PS3USB, examples/PS4USB, examples/PSBuzz, examples/USB_desc, examples/USBH_MIDI/bidirectional_converter, examples/USBH_MIDI/eVY1_sample, examples/USBH_MIDI/USBH_MIDI_dump, examples/USBH_MIDI/USB_MIDI_converter, examples/USBH_MIDI/USB_MIDI_converter_multi, examples/Xbox/XBOXOLD, examples/Xbox/XBOXONE, examples/Xbox/XBOXONESBT, examples/Xbox/XBOXRECV, examples/Xbox/XBOXUSB]
|
||||
example: [examples/acm/acm_terminal, examples/adk/adk_barcode, examples/adk/ArduinoBlinkLED, examples/adk/demokit_20, examples/adk/term_test, examples/adk/term_time, examples/Bluetooth/BTHID, examples/Bluetooth/PS3BT, examples/Bluetooth/PS3Multi, examples/Bluetooth/PS3SPP, examples/Bluetooth/PS4BT, examples/Bluetooth/PS5BT, examples/Bluetooth/SPP, examples/Bluetooth/SPPMulti, examples/Bluetooth/Wii, examples/Bluetooth/WiiBalanceBoard, examples/Bluetooth/WiiIRCamera, examples/Bluetooth/WiiMulti, examples/Bluetooth/WiiUProController, examples/board_qc, examples/cdc_XR21B1411/XR_terminal, examples/ftdi/USBFTDILoopback, examples/GPIO/Blink, examples/GPIO/Blink_LowLevel, examples/GPIO/Input, examples/HID/le3dp, examples/HID/scale, examples/HID/SRWS1, examples/HID/t16km, examples/HID/USBHIDBootKbd, examples/HID/USBHIDBootKbdAndMouse, examples/HID/USBHIDBootMouse, examples/HID/USBHID_desc, examples/HID/USBHIDJoystick, examples/HID/USBHIDMultimediaKbd, examples/hub_demo, examples/max_LCD, examples/pl2303/pl2303_gprs_terminal, examples/pl2303/pl2303_gps, examples/pl2303/pl2303_tinygps, examples/pl2303/pl2303_xbee_terminal, examples/PS3USB, examples/PS4USB, examples/PS5USB, examples/PSBuzz, examples/USB_desc, examples/USBH_MIDI/bidirectional_converter, examples/USBH_MIDI/eVY1_sample, examples/USBH_MIDI/USBH_MIDI_dump, examples/USBH_MIDI/USB_MIDI_converter, examples/USBH_MIDI/USB_MIDI_converter_multi, examples/Xbox/XBOXOLD, examples/Xbox/XBOXONE, examples/Xbox/XBOXONESBT, examples/Xbox/XBOXRECV, examples/Xbox/XBOXUSB]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
|
|
12
BTD.cpp
12
BTD.cpp
|
@ -317,7 +317,7 @@ void BTD::Initialize() {
|
|||
incomingWii = false;
|
||||
connectToHIDDevice = false;
|
||||
incomingHIDDevice = false;
|
||||
incomingPS4 = false;
|
||||
incomingPSController = false;
|
||||
bAddress = 0; // Clear device address
|
||||
bNumEP = 1; // Must have to be reset to 1
|
||||
qNextPollTime = 0; // Reset next poll time
|
||||
|
@ -1011,9 +1011,9 @@ void BTD::HCI_task() {
|
|||
}
|
||||
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);
|
||||
Notify(PSTR("\r\nPS4/PS5 controller is connecting"), 0x80);
|
||||
#endif
|
||||
incomingPS4 = true;
|
||||
incomingPSController = true;
|
||||
}
|
||||
if((pairWithWii || pairWithHIDDevice) && checkRemoteName)
|
||||
hci_state = HCI_CONNECT_DEVICE_STATE;
|
||||
|
@ -1034,8 +1034,8 @@ void BTD::HCI_task() {
|
|||
}
|
||||
D_PrintHex<uint8_t > (disc_bdaddr[0], 0x80);
|
||||
#endif
|
||||
if(incomingPS4)
|
||||
connectToHIDDevice = true; // We should always connect to the PS4 controller
|
||||
if(incomingPSController)
|
||||
connectToHIDDevice = true; // We should always connect to the PS4/PS5 controller
|
||||
|
||||
// Clear these flags for a new connection
|
||||
l2capConnectionClaimed = false;
|
||||
|
@ -1068,7 +1068,7 @@ void BTD::HCI_task() {
|
|||
|
||||
connectToWii = incomingWii = pairWithWii = false;
|
||||
connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false;
|
||||
incomingPS4 = false;
|
||||
incomingPSController = false;
|
||||
|
||||
hci_state = HCI_SCANNING_STATE;
|
||||
}
|
||||
|
|
2
BTD.h
2
BTD.h
|
@ -575,7 +575,7 @@ private:
|
|||
|
||||
bool pairWiiUsingSync; // True if pairing was done using the Wii SYNC button.
|
||||
bool checkRemoteName; // Used to check remote device's name before connecting.
|
||||
bool incomingPS4; // True if a PS4 controller is connecting
|
||||
bool incomingPSController; // True if a PS4/PS5 controller is connecting
|
||||
uint8_t classOfDevice[3]; // Class of device of last device
|
||||
|
||||
/* Variables used by high level HCI task */
|
||||
|
|
282
PS5BT.h
Normal file
282
PS5BT.h
Normal file
|
@ -0,0 +1,282 @@
|
|||
/* Copyright (C) 2021 Kristian Sloth Lauszus. 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 Sloth Lauszus
|
||||
Web : https://lauszus.com
|
||||
e-mail : lauszus@gmail.com
|
||||
*/
|
||||
|
||||
#ifndef _ps5bt_h_
|
||||
#define _ps5bt_h_
|
||||
|
||||
#include "BTHID.h"
|
||||
#include "PS5Parser.h"
|
||||
|
||||
/*const uint32_t crc32_table[] PROGMEM = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
uint32_t crc32(uint8_t *buffer, size_t length) { // Inspired by: http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/libkern/crc32.c and http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=28214
|
||||
uint32_t crc = ~0L; // Initial value
|
||||
for (size_t i = 0; i < length; i++)
|
||||
crc = (crc >> 8) ^ pgm_read_dword(&crc32_table[*buffer++ ^ (crc & 0xFF)]);
|
||||
return ~crc;
|
||||
};*/
|
||||
|
||||
/*
|
||||
* There are multiple 16-bit CRC polynomials in common use, but this is
|
||||
* *the* standard CRC-32 polynomial, first popularized by Ethernet.
|
||||
* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0
|
||||
*/
|
||||
#if 0
|
||||
#define CRC32_POLY_LE 0xedb88320
|
||||
#define CRC32_POLY_BE 0x04c11db7
|
||||
|
||||
#define CRC_LE_BITS 1
|
||||
|
||||
typedef uint32_t u32;
|
||||
|
||||
static inline u32 crc32_le_generic(u32 crc, unsigned char const *p, size_t len, const u32 (*tab)[256], u32 polynomial)
|
||||
{
|
||||
#if CRC_LE_BITS == 1
|
||||
int i;
|
||||
while (len--) {
|
||||
crc ^= *p++;
|
||||
for (i = 0; i < 8; i++)
|
||||
crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0);
|
||||
}
|
||||
# elif CRC_LE_BITS == 2
|
||||
while (len--) {
|
||||
crc ^= *p++;
|
||||
crc = (crc >> 2) ^ tab[0][crc & 3];
|
||||
crc = (crc >> 2) ^ tab[0][crc & 3];
|
||||
crc = (crc >> 2) ^ tab[0][crc & 3];
|
||||
crc = (crc >> 2) ^ tab[0][crc & 3];
|
||||
}
|
||||
# elif CRC_LE_BITS == 4
|
||||
while (len--) {
|
||||
crc ^= *p++;
|
||||
crc = (crc >> 4) ^ tab[0][crc & 15];
|
||||
crc = (crc >> 4) ^ tab[0][crc & 15];
|
||||
}
|
||||
# elif CRC_LE_BITS == 8
|
||||
/* aka Sarwate algorithm */
|
||||
while (len--) {
|
||||
crc ^= *p++;
|
||||
crc = (crc >> 8) ^ tab[0][crc & 255];
|
||||
}
|
||||
# else
|
||||
crc = (__force u32) __cpu_to_le32(crc);
|
||||
crc = crc32_body(crc, p, len, tab);
|
||||
crc = __le32_to_cpu((__force __le32)crc);
|
||||
#endif
|
||||
return crc;
|
||||
}
|
||||
|
||||
#if CRC_LE_BITS == 1
|
||||
static u32 crc32_le(u32 crc, unsigned char const *p, size_t len)
|
||||
{
|
||||
return crc32_le_generic(crc, p, len, NULL, CRC32_POLY_LE);
|
||||
}
|
||||
#else
|
||||
static u32 crc32_le(u32 crc, unsigned char const *p, size_t len)
|
||||
{
|
||||
return crc32_le_generic(crc, p, len, (const u32 (*)[256])crc32table_le, CRC32_POLY_LE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This class implements support for the PS5 controller via Bluetooth.
|
||||
* It uses the BTHID class for all the Bluetooth communication.
|
||||
*/
|
||||
class PS5BT : public BTHID, public PS5Parser {
|
||||
public:
|
||||
/**
|
||||
* Constructor for the PS5BT class.
|
||||
* @param p Pointer to the BTD class instance.
|
||||
* @param pair Set this to true in order to pair with the device. If the argument is omitted then it will not pair with it. One can use ::PAIR to set it to true.
|
||||
* @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used.
|
||||
*/
|
||||
PS5BT(BTD *p, bool pair = false, const char *pin = "0000") :
|
||||
BTHID(p, pair, pin) {
|
||||
PS5Parser::Reset();
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to check if a PS5 controller is connected.
|
||||
* @return Returns true if it is connected.
|
||||
*/
|
||||
bool connected() {
|
||||
return BTHID::connected;
|
||||
};
|
||||
|
||||
protected:
|
||||
/** @name BTHID implementation */
|
||||
/**
|
||||
* Used to parse Bluetooth HID data.
|
||||
* @param len The length of the incoming data.
|
||||
* @param buf Pointer to the data buffer.
|
||||
*/
|
||||
virtual void ParseBTHIDData(uint8_t len, uint8_t *buf) {
|
||||
PS5Parser::Parse(len, buf);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
virtual void OnInitBTHID() {
|
||||
PS5Parser::Reset();
|
||||
enable_sixaxis(); // Make the controller send out the entire output report
|
||||
if (pFuncOnInit)
|
||||
pFuncOnInit(); // Call the user function
|
||||
else
|
||||
setLed(Blue);
|
||||
};
|
||||
|
||||
/** Used to reset the different buffers to there default values */
|
||||
virtual void ResetBTHID() {
|
||||
PS5Parser::Reset();
|
||||
};
|
||||
/**@}*/
|
||||
|
||||
/** @name PS5Parser implementation */
|
||||
virtual void sendOutputReport(PS5Output *output) {
|
||||
#if 1
|
||||
return; // TODO: Fix this
|
||||
#else
|
||||
// See the series of patches here: https://patchwork.kernel.org/project/linux-input/patch/20201219062336.72568-14-roderick@gaikai.com/
|
||||
|
||||
uint8_t buf[1 /* BT Set Output Report */ + 1 /* report id */ + 1 /* seq_tag */ + 1 /* tag */ + 47 /* common */ + 24 /* reserved */ + 4 /* crc32 */];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
buf[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02)
|
||||
|
||||
buf[0x01] = 0x31; // Report ID
|
||||
buf[0x02] = (output_sequence << 4) | 0x0; // Highest 4-bit is a sequence number, which needs to be increased every report. Lowest 4-bit is tag and can be zero for now.
|
||||
if(++output_sequence == 15)
|
||||
output_sequence = 0;
|
||||
buf[0x03] = 0x10; // Magic number must be set to 0x10
|
||||
|
||||
buf[0x01 + 3] = 0xFF; // feature flags 1
|
||||
buf[0x02 + 3]= 0xF7; // feature flags 2
|
||||
|
||||
buf[0x03 + 3] = output->smallRumble; // Small Rumble
|
||||
buf[0x04 + 3] = output->bigRumble; // Big rumble
|
||||
|
||||
// 5-7 headphone, speaker, mic volume, audio flags
|
||||
|
||||
buf[0x09 + 3] = (uint8_t)output->microphoneLed;
|
||||
|
||||
// 0x0A mute flags
|
||||
|
||||
// Adaptive Triggers: 0x0B-0x14 right, 0x15 unknown, 0x16-0x1F left
|
||||
rightTrigger.processTrigger(&buf[0x0B + 3]); // right
|
||||
leftTrigger.processTrigger(&buf[0x16 + 3]); // left
|
||||
|
||||
// 0x20-0x24 unknown
|
||||
// 0x25 trigger motor effect strengths
|
||||
// 0x26 speaker volume
|
||||
|
||||
// player LEDs
|
||||
buf[0x27 + 3] = 0x03; // led brightness, pulse
|
||||
buf[0x2A + 3] = output->disableLeds ? 0x01 : 0x2; // led pulse option
|
||||
// buf[0x2B] LED brightness, 0 = full, 1= medium, 2 = low
|
||||
buf[0x2C + 3] = output->playerLeds; // 5 white player LEDs
|
||||
|
||||
// lightbar
|
||||
buf[0x2D + 3] = output->r; // Red
|
||||
buf[0x2E + 3] = output->g; // Green
|
||||
buf[0x2F + 3] = output->b; // Blue
|
||||
|
||||
//uint32_t crc = crc32(&buf[1], 79 - 1 /* do not include the BT Set Output Report */ - 4 /* crc */);
|
||||
|
||||
uint8_t seed = 0xA2;
|
||||
uint32_t crc = crc32_le(0xFFFFFFFF, &seed, 1);
|
||||
crc = ~crc32_le(crc, &buf[1], 79 - 1 /* do not include the BT Set Output Report */ - 4 /* crc */);
|
||||
|
||||
buf[75] = crc;
|
||||
buf[76] = crc >> 8;
|
||||
buf[77] = crc >> 16;
|
||||
buf[78] = crc >> 24;
|
||||
|
||||
output->reportChanged = false;
|
||||
|
||||
// The PS5 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed
|
||||
|
||||
HID_Command(buf, sizeof(buf));
|
||||
#endif
|
||||
};
|
||||
/**@}*/
|
||||
|
||||
private:
|
||||
uint8_t output_sequence = 0;
|
||||
|
||||
void enable_sixaxis() { // Command used to make the PS5 controller send out the entire output report
|
||||
// Request the paring info. This makes the controller send out the full report - see: https://patchwork.kernel.org/project/linux-input/patch/20201219062336.72568-14-roderick@gaikai.com/
|
||||
uint8_t buf[2];
|
||||
buf[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03)
|
||||
buf[1] = 9; // Report ID for paring info
|
||||
|
||||
HID_Command(buf, 2);
|
||||
};
|
||||
|
||||
void HID_Command(uint8_t *data, uint8_t nbytes) {
|
||||
pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]);
|
||||
};
|
||||
};
|
||||
#endif
|
|
@ -15,7 +15,8 @@
|
|||
e-mail : lauszus@gmail.com
|
||||
|
||||
Thanks to Joseph Duchesne for the initial code.
|
||||
Based on Ludwig Füchsl's https://github.com/Ohjurot/DualSense-Windows PS5 port.
|
||||
Based on Ludwig Füchsl's https://github.com/Ohjurot/DualSense-Windows PS5 port
|
||||
and the series of patches found here: https://patchwork.kernel.org/project/linux-input/patch/20201219062336.72568-14-roderick@gaikai.com/
|
||||
*/
|
||||
|
||||
#include "PS5Parser.h"
|
||||
|
@ -88,19 +89,21 @@ void PS5Parser::Parse(uint8_t len, uint8_t *buf) {
|
|||
|
||||
if (buf[0] == 0x01) // Check report ID
|
||||
memcpy(&ps5Data, buf + 1, min((uint8_t)(len - 1), MFK_CASTUINT8T sizeof(ps5Data)));
|
||||
else if (buf[0] == 0x11) { // This report is send via Bluetooth, it has an offset of 2 compared to the USB data
|
||||
if (len < 4) {
|
||||
else if (buf[0] == 0x31) { // This report is send via Bluetooth, it has an offset of 2 compared to the USB data
|
||||
if (len < 3) {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(PSTR("\r\nReport is too short: "), 0x80);
|
||||
D_PrintHex<uint8_t > (len, 0x80);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
memcpy(&ps5Data, buf + 3, min((uint8_t)(len - 3), MFK_CASTUINT8T sizeof(ps5Data)));
|
||||
memcpy(&ps5Data, buf + 2, min((uint8_t)(len - 2), MFK_CASTUINT8T sizeof(ps5Data)));
|
||||
} else {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(PSTR("\r\nUnknown report id: "), 0x80);
|
||||
D_PrintHex<uint8_t > (buf[0], 0x80);
|
||||
Notify(PSTR(", len: "), 0x80);
|
||||
D_PrintHex<uint8_t > (len, 0x80);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
23
PS5Parser.h
23
PS5Parser.h
|
@ -15,7 +15,8 @@
|
|||
e-mail : lauszus@gmail.com
|
||||
|
||||
Thanks to Joseph Duchesne for the initial code.
|
||||
Based on Ludwig Füchsl's https://github.com/Ohjurot/DualSense-Windows PS5 port.
|
||||
Based on Ludwig Füchsl's https://github.com/Ohjurot/DualSense-Windows PS5 port
|
||||
and the series of patches found here: https://patchwork.kernel.org/project/linux-input/patch/20201219062336.72568-14-roderick@gaikai.com/
|
||||
*/
|
||||
|
||||
#ifndef _ps5parser_h_
|
||||
|
@ -32,7 +33,7 @@ const uint8_t PS5_BUTTONS[] PROGMEM = {
|
|||
DOWN, // DOWN
|
||||
LEFT, // LEFT
|
||||
|
||||
0x0C, // SHARE
|
||||
0x0C, // CREATE
|
||||
0x0D, // OPTIONS
|
||||
0x0E, // L3
|
||||
0x0F, // R3
|
||||
|
@ -64,7 +65,7 @@ union PS5Buttons {
|
|||
uint8_t r1 : 1;
|
||||
uint8_t l2 : 1;
|
||||
uint8_t r2 : 1;
|
||||
uint8_t share : 1;
|
||||
uint8_t create : 1;
|
||||
uint8_t menu : 1;
|
||||
uint8_t l3 : 1;
|
||||
uint8_t r3 : 1;
|
||||
|
@ -96,7 +97,7 @@ union PS5Status {
|
|||
|
||||
// second byte
|
||||
uint8_t mic : 1;
|
||||
uint8_t dummy4 : 3;
|
||||
uint8_t dummy3 : 3;
|
||||
} __attribute__((packed));
|
||||
uint16_t val;
|
||||
} __attribute__((packed));
|
||||
|
@ -106,28 +107,28 @@ struct PS5Data {
|
|||
uint8_t hatValue[4]; // 0-3 bytes
|
||||
uint8_t trigger[2]; // 4-5
|
||||
|
||||
uint8_t dummy; // 6 unknown
|
||||
uint8_t sequence_number; // 6
|
||||
|
||||
PS5Buttons btn; // 7-9
|
||||
|
||||
uint8_t dummy2[5]; // 0xA-0xD unknown
|
||||
uint8_t reserved[5]; // 0xA-0xD
|
||||
|
||||
/* Gyro and accelerometer values */
|
||||
int16_t gyroX, gyroZ, gyroY; // 0x0F - 0x14
|
||||
int16_t accX, accZ, accY; // 0x15-0x1A
|
||||
int32_t sensor_timestamp;
|
||||
|
||||
uint8_t dummy3[5]; // 0x1B - 0x1F unknown
|
||||
uint8_t reserved2;
|
||||
|
||||
// 0x20 - 0x23 touchpad point 1
|
||||
// 0x24 - 0x27 touchpad point 2
|
||||
ps5TouchpadXY xy;
|
||||
|
||||
uint8_t dummy4; //0x28 unknown
|
||||
uint8_t reserved3; // 0x28
|
||||
|
||||
uint8_t rightTriggerFeedback; // 0x29
|
||||
uint8_t leftTriggerFeedback; // 0x2A
|
||||
|
||||
uint8_t dummy5[10]; // 0x2B - 0x34 unknown
|
||||
uint8_t reserved4[10]; // 0x2B - 0x34
|
||||
|
||||
// status bytes 0x35-0x36
|
||||
PS5Status status;
|
||||
|
@ -260,7 +261,7 @@ public:
|
|||
* @return The battery level in the range 0-15.
|
||||
*/
|
||||
/*uint8_t getBatteryLevel() {
|
||||
return ps5Data.status.battery;
|
||||
return ps5Data.status.battery; // TODO: Where to read the battery level?
|
||||
};*/
|
||||
|
||||
/**
|
||||
|
|
9
PS5USB.h
9
PS5USB.h
|
@ -93,13 +93,16 @@ protected:
|
|||
virtual void sendOutputReport(PS5Output *output) { // Source: https://github.com/chrippa/ds4drv
|
||||
// PS4 Source: https://github.com/chrippa/ds4drv
|
||||
// PS5 values from https://www.reddit.com/r/gamedev/comments/jumvi5/dualsense_haptics_leds_and_more_hid_output_report/
|
||||
// and Ludwig Füchsl's https://github.com/Ohjurot/DualSense-Windows
|
||||
uint8_t buf[48];
|
||||
// , Ludwig Füchsl's https://github.com/Ohjurot/DualSense-Windows
|
||||
// and the series of patches found here: https://patchwork.kernel.org/project/linux-input/patch/20201219062336.72568-14-roderick@gaikai.com/
|
||||
uint8_t buf[1 /* report id */ + 47 /* common */];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
buf[0x00] = 0x02; // report type
|
||||
buf[0x00] = 0x02; // Report ID
|
||||
|
||||
buf[0x01] = 0xFF; // feature flags 1
|
||||
buf[0x02]= 0xF7; // feature flags 2
|
||||
|
||||
buf[0x03] = output->smallRumble; // Small Rumble
|
||||
buf[0x04] = output->bigRumble; // Big rumble
|
||||
|
||||
|
|
|
@ -161,6 +161,7 @@ enum ButtonEnum {
|
|||
|
||||
/**@{*/
|
||||
/** PS5 buttons */
|
||||
CREATE = 4,
|
||||
MICROPHONE = 18,
|
||||
/**@}*/
|
||||
};
|
||||
|
|
159
examples/Bluetooth/PS5BT/PS5BT.ino
Normal file
159
examples/Bluetooth/PS5BT/PS5BT.ino
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
Example sketch for the PS5 Bluetooth library - developed by Kristian Sloth Lauszus
|
||||
For more information visit the Github repository: github.com/felis/USB_Host_Shield_2.0 or
|
||||
send me an e-mail: lauszus@gmail.com
|
||||
*/
|
||||
|
||||
#include <PS5BT.h>
|
||||
#include <usbhub.h>
|
||||
|
||||
// Satisfy the IDE, which needs to see the include statment in the ino too.
|
||||
#ifdef dobogusinclude
|
||||
#include <spi4teensy3.h>
|
||||
#endif
|
||||
#include <SPI.h>
|
||||
|
||||
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 PS5BT class in two ways */
|
||||
// This will start an inquiry and then pair with the PS5 controller - you only have to do this once
|
||||
// You will need to hold down the PS and Share button at the same time, the PS5 controller will then start to blink rapidly indicating that it is in pairing mode
|
||||
PS5BT PS5(&Btd, PAIR);
|
||||
|
||||
// After that you can simply create the instance like so and then press the PS button on the device
|
||||
//PS5BT PS5(&Btd);
|
||||
|
||||
bool printAngle, printTouch;
|
||||
uint16_t lastMessageCounter = -1;
|
||||
uint8_t player_led_mask = 0;
|
||||
bool microphone_led = false;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
#if !defined(__MIPSEL__)
|
||||
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
|
||||
#endif
|
||||
if (Usb.Init() == -1) {
|
||||
Serial.print(F("\r\nOSC did not start"));
|
||||
while (1); // Halt
|
||||
}
|
||||
Serial.print(F("\r\nPS5 Bluetooth Library Started"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Usb.Task();
|
||||
|
||||
if (PS5.connected() && lastMessageCounter != PS5.getMessageCounter()) {
|
||||
lastMessageCounter = PS5.getMessageCounter();
|
||||
|
||||
if (PS5.getAnalogHat(LeftHatX) > 137 || PS5.getAnalogHat(LeftHatX) < 117 || PS5.getAnalogHat(LeftHatY) > 137 || PS5.getAnalogHat(LeftHatY) < 117 || PS5.getAnalogHat(RightHatX) > 137 || PS5.getAnalogHat(RightHatX) < 117 || PS5.getAnalogHat(RightHatY) > 137 || PS5.getAnalogHat(RightHatY) < 117) {
|
||||
Serial.print(F("\r\nLeftHatX: "));
|
||||
Serial.print(PS5.getAnalogHat(LeftHatX));
|
||||
Serial.print(F("\tLeftHatY: "));
|
||||
Serial.print(PS5.getAnalogHat(LeftHatY));
|
||||
Serial.print(F("\tRightHatX: "));
|
||||
Serial.print(PS5.getAnalogHat(RightHatX));
|
||||
Serial.print(F("\tRightHatY: "));
|
||||
Serial.print(PS5.getAnalogHat(RightHatY));
|
||||
}
|
||||
|
||||
if (PS5.getAnalogButton(L2) || PS5.getAnalogButton(R2)) { // These are the only analog buttons on the PS5 controller
|
||||
Serial.print(F("\r\nL2: "));
|
||||
Serial.print(PS5.getAnalogButton(L2));
|
||||
Serial.print(F("\tR2: "));
|
||||
Serial.print(PS5.getAnalogButton(R2));
|
||||
}
|
||||
|
||||
// Set the left trigger to resist at the right trigger's level
|
||||
PS5.leftTrigger.setTriggerForce(PS5.getAnalogButton(R2), 255);
|
||||
|
||||
if (PS5.getButtonClick(PS)) {
|
||||
Serial.print(F("\r\nPS"));
|
||||
PS5.disconnect();
|
||||
} else {
|
||||
if (PS5.getButtonClick(TRIANGLE)) {
|
||||
Serial.print(F("\r\nTriangle"));
|
||||
PS5.setRumbleOn(RumbleLow);
|
||||
}
|
||||
if (PS5.getButtonClick(CIRCLE)) {
|
||||
Serial.print(F("\r\nCircle"));
|
||||
PS5.setRumbleOn(RumbleHigh);
|
||||
}
|
||||
if (PS5.getButtonClick(CROSS)) {
|
||||
Serial.print(F("\r\nCross"));
|
||||
|
||||
// Set the player LEDs
|
||||
player_led_mask = (player_led_mask << 1) | 1;
|
||||
if (player_led_mask > 0x1F)
|
||||
player_led_mask = 0;
|
||||
PS5.setPlayerLed(player_led_mask); // The bottom 5 bits set player LEDs
|
||||
}
|
||||
if (PS5.getButtonClick(SQUARE)) {
|
||||
Serial.print(F("\r\nSquare"));
|
||||
PS5.setRumbleOff();
|
||||
}
|
||||
|
||||
if (PS5.getButtonClick(UP)) {
|
||||
Serial.print(F("\r\nUp"));
|
||||
PS5.setLed(Red);
|
||||
} if (PS5.getButtonClick(RIGHT)) {
|
||||
Serial.print(F("\r\nRight"));
|
||||
PS5.setLed(Blue);
|
||||
} if (PS5.getButtonClick(DOWN)) {
|
||||
Serial.print(F("\r\nDown"));
|
||||
PS5.setLed(Yellow);
|
||||
} if (PS5.getButtonClick(LEFT)) {
|
||||
Serial.print(F("\r\nLeft"));
|
||||
PS5.setLed(Green);
|
||||
}
|
||||
|
||||
if (PS5.getButtonClick(L1))
|
||||
Serial.print(F("\r\nL1"));
|
||||
if (PS5.getButtonClick(L3))
|
||||
Serial.print(F("\r\nL3"));
|
||||
if (PS5.getButtonClick(R1))
|
||||
Serial.print(F("\r\nR1"));
|
||||
if (PS5.getButtonClick(R3))
|
||||
Serial.print(F("\r\nR3"));
|
||||
|
||||
if (PS5.getButtonClick(CREATE))
|
||||
Serial.print(F("\r\nCreate"));
|
||||
if (PS5.getButtonClick(OPTIONS)) {
|
||||
Serial.print(F("\r\nOptions"));
|
||||
printAngle = !printAngle;
|
||||
}
|
||||
if (PS5.getButtonClick(TOUCHPAD)) {
|
||||
Serial.print(F("\r\nTouchpad"));
|
||||
printTouch = !printTouch;
|
||||
}
|
||||
if (PS5.getButtonClick(MICROPHONE)) {
|
||||
Serial.print(F("\r\nMicrophone"));
|
||||
microphone_led = !microphone_led;
|
||||
PS5.setMicLed(microphone_led);
|
||||
}
|
||||
|
||||
if (printAngle) { // Print angle calculated using the accelerometer only
|
||||
Serial.print(F("\r\nPitch: "));
|
||||
Serial.print(PS5.getAngle(Pitch));
|
||||
Serial.print(F("\tRoll: "));
|
||||
Serial.print(PS5.getAngle(Roll));
|
||||
}
|
||||
|
||||
if (printTouch) { // Print the x, y coordinates of the touchpad
|
||||
if (PS5.isTouching(0) || PS5.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 (PS5.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(PS5.getX(i));
|
||||
Serial.print(F("\tY")); Serial.print(i + 1); Serial.print(F(": "));
|
||||
Serial.print(PS5.getY(i));
|
||||
Serial.print(F("\t"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -106,8 +106,8 @@ void loop() {
|
|||
if (PS5.getButtonClick(R3))
|
||||
Serial.print(F("\r\nR3"));
|
||||
|
||||
if (PS5.getButtonClick(SHARE))
|
||||
Serial.print(F("\r\nShare"));
|
||||
if (PS5.getButtonClick(CREATE))
|
||||
Serial.print(F("\r\nCreate"));
|
||||
if (PS5.getButtonClick(OPTIONS)) {
|
||||
Serial.print(F("\r\nOptions"));
|
||||
printAngle = !printAngle;
|
||||
|
|
|
@ -36,6 +36,8 @@ PS3BT KEYWORD1
|
|||
PS3USB KEYWORD1
|
||||
PS4BT KEYWORD1
|
||||
PS4USB KEYWORD1
|
||||
PS5BT KEYWORD1
|
||||
PS5USB KEYWORD1
|
||||
|
||||
####################################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
|
@ -135,6 +137,7 @@ SHARE LITERAL1
|
|||
OPTIONS LITERAL1
|
||||
TOUCHPAD LITERAL1
|
||||
|
||||
CREATE LITERAL1
|
||||
MICROPHONE LITERAL1
|
||||
|
||||
LeftHatX LITERAL1
|
||||
|
|
Loading…
Reference in a new issue