Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ps5SendData example not working #3

Open
dmartauz opened this issue May 10, 2022 · 9 comments
Open

ps5SendData example not working #3

dmartauz opened this issue May 10, 2022 · 9 comments

Comments

@dmartauz
Copy link

Prior to testing the library I updated DualSense to firmware 0297. All examples seems to be working except ps5SendData.

Btw, are you planning to explore / reverse-engineer communication for other peripherals of DualSense such as touchpad, microphone, speaker?

Are there any other resources which could help during this process?

@dmartauz dmartauz changed the title ps5SendData example seems not to be working with DualSense firmware 0297 ps5SendData example seems not working with DualSense firmware 0297 May 10, 2022
@rodneybakiskan
Copy link
Owner

I never got ps5SendData to work. Only buttons and analog controller inputs are known to be functional. I didn't bother with others since it would be significantly more difficult to figure out without a resource/manual of some sort (as you mentioned). Until I find such a resource, I doubt I'll try to get the other sensors working.

@dmartauz
Copy link
Author

I was playing with DS and esp-idf with Bluedroid for few days and could not make the bt_spp_initiator example working. Trying service discovery functions I discovered that DS in pairing mode provides only single UUID 0x1124 which is HID. So I tried running esp_hid_host example and found out that it is able to pair the DS!
Then I launched the example again and with DS connected in normal mode (not pairing mode) it did even output some report:
BDA:d0:bc:c1:00:26:e3, Status: OK, Connected: YES, Handle: 0, Usage: GAMEPAD
Name: , Manufacturer: , Serial Number:
PID: 0x0ce6, VID: 0x054c, VERSION: 0x0100
Report Map Length: 279
VENDOR FEATURE REPORT, ID: 240, Length: 63
VENDOR FEATURE REPORT, ID: 242, Length: 15
VENDOR FEATURE REPORT, ID: 241, Length: 63
VENDOR FEATURE REPORT, ID: 131, Length: 63
VENDOR FEATURE REPORT, ID: 130, Length: 9
VENDOR FEATURE REPORT, ID: 129, Length: 63
VENDOR FEATURE REPORT, ID: 128, Length: 63
VENDOR FEATURE REPORT, ID: 34, Length: 63
VENDOR FEATURE REPORT, ID: 32, Length: 63
VENDOR FEATURE REPORT, ID: 9, Length: 19
VENDOR FEATURE REPORT, ID: 8, Length: 47
VENDOR FEATURE REPORT, ID: 5, Length: 40
VENDOR OUTPUT REPORT, ID: 57, Length: 546
VENDOR OUTPUT REPORT, ID: 56, Length: 525
VENDOR OUTPUT REPORT, ID: 55, Length: 461
VENDOR OUTPUT REPORT, ID: 54, Length: 397
VENDOR OUTPUT REPORT, ID: 53, Length: 333
VENDOR OUTPUT REPORT, ID: 52, Length: 269
VENDOR OUTPUT REPORT, ID: 51, Length: 205
VENDOR OUTPUT REPORT, ID: 50, Length: 141
VENDOR OUTPUT REPORT, ID: 49, Length: 77
VENDOR INPUT REPORT, ID: 49, Length: 77
GAMEPAD INPUT REPORT, ID: 1, Length: 9

So it seems DS in normal operational mode is running both HID and SPP.

@rodneybakiskan
Copy link
Owner

rodneybakiskan commented May 25, 2022

Have you taken a look at src/ps5_int.h? Seems like some of the report info might be related. To get sendData to work I believe you'll have figure out the index position of each set of data (also maybe the send buffer size), then update ps5_int.h appropriately. Only ways I can think of doing so are:

  • Diagnosis report like you're doing now
  • Manual/resource
  • Going through the code of something that is able to send data to a ps5ctrl
  • Trial and error

@nonobody15
Copy link

Hi,
I have been trying to get the sendData example to run for the last few weeks. Unfortunately without success. But I want to show here my state and sources, so that someone else can also try it.

Links, where I collected my information:
From the Windows world (especially output.cpp and IO.cpp)
From Reddit discussion (Code from original Post)
From the Linux world (his source)

Basic structure of the BT HID payload (according to my understanding!):

  1. Byte --> 0x31 (REPORT_ID)
  2. Byte --> 0x02 (sequence teg, should be counted up. But in several sources this byte is simply fixed to 0x02)
  3. Byte --> here the sources listed above do not agree (according to my understanding). Windows API: Flag0 --> 0xFF ; LINUX: magic tag --> 0x10 ???
  4. Byte --> Windows API: Flag1 --> 0xF7; LINUX: sets the first flag her --> 0xFF
  5. Byte --> Windows API: first byte to controll something (right rumble motor) ; LINUX: flag1 --> 0xF7
  6. Now follow several bytes to make various settings on the controller (player LEDs, RGB LED, rumble motor, etc.).
    for example Byte 47 to 49 are used to controle the RGB LED
    ...

75 Byte --> first Byte of CRC32 checksum
76. ....
77. ...
78. Byte --> last Byte of CRC32 checksum and last Byte of HID package

Implementation
To send this package structure to the PS5 controller, I wrote the values hard into the ps5Cmd() function in ps5.c for simplicity. In this version I try to set the RGB LED white (not pretty, but simple :-)

void ps5Cmd(ps5_cmd_t cmd) {
  hid_cmd_t hidCommand = {0};

  hidCommand.code = 0x31; // report ID (
  hidCommand.identifier = 0x02;
  hidCommand.data[0] = 0xFF;  //tag 0x10??? or just 0xFF?
  hidCommand.data[1] = 0xF7; 
  // hidCommand.data[2] = 0xFD;  //???FLAG1???

  hidCommand.data[2] = 0xff;  // Small Rumble
  hidCommand.data[3] = 0xff;  // Big rumble

  hidCommand.data[0x2C] = 100;   // Red
  hidCommand.data[0x2D] = 100;  // Green
  hidCommand.data[0x2E] = 100;   // Blue

  uint32_t libCRC = crc_string(&hidCommand.code, 74); //crc32 calculate

  hidCommand.data[0x48] = (unsigned char)((libCRC & 0x000000FF) >> 0UL); //writing CRC32 into the last 4 bytes
  hidCommand.data[0x49] = (unsigned char)((libCRC & 0x0000FF00) >> 8UL);
  hidCommand.data[0x4A] = (unsigned char)((libCRC & 0x00FF0000) >> 16UL);
  hidCommand.data[0x4B] = (unsigned char)((libCRC & 0xFF000000) >> 24UL);

  ps5_l2cap_send_hid(&hidCommand, 78);  //sending HID package
}

Regarding the flags: actually only single bits are set in them to send only certain data. But as you can read in this post both flags can be given the values listed above to simply send any parameter (one less possible cause of errors).

Summary:
I have tried all possible package structures and nothing has worked. The only uncertainty I have is the CRC32. I used this online calculator as a reference. There are different CRC32 variants listed, but I am not sure which one is used for the PS5 controller (I mean the normal CRC32?). Maybe someone knows more about this and can answer that?
I used this implementation for calculating the CRC32 on the ESP32, it spits out the same result as the online calculator. But in the Windows API, this algorithm is used. I have also run this on the ESP32, but the result is completely different from the online calculator. Therefore, I am very unsure about the CRC32 and hope that someone can help me.

If someone else was successful in sending commands to the PS5 controller with the ESP32: please report!

@rodneybakiskan rodneybakiskan changed the title ps5SendData example seems not working with DualSense firmware 0297 ps5SendData example not working Mar 18, 2023
@nonobody15
Copy link

I have found a kind of solution for this issue. Namely, ricardoquesada here has published a biblithek with which you can control a variety of gamepads using the Arduino framework (including the PS5 controller).
In this README he describes exactly how to control the controller with a single ESP32!

@pdumais
Copy link

pdumais commented Feb 1, 2024

One thing I noticed is that the code uses the control channel to send the HID packet. Shouldn't it use the interrupt channel instead?

@pdumais
Copy link

pdumais commented Feb 1, 2024

I'm making progress. Changing the channel worked. But I also did a whole bunch of changes too according to what was posted in this thread. The problem I have now is that ps5_l2cap_data_ind_cback gets flooded with packets with report ID 0x31 after I set the LED. I'm not sure if I need to ack those.

One thing to consider: I used a tool called DualSenseCtl that runs on linux. This tool helped me discover that before changing the LED colors, you first need to disable the lightbar. Makes no sense to me but it works. I'll try to report more progress sometime and will post a link to my code.

@pdumais
Copy link

pdumais commented Feb 2, 2024

I just found this: https://patchwork.kernel.org/project/linux-input/patch/20201219062336.72568-8-roderick@gaikai.com/

So basically, the library was parsing a minimal set of data. After sending an output report, the controller starts sending an extended input report that contains more data. So the fix I'm doing would enable sending commands to the controller but would also give us the sensors information that was missing as mentionned in other issues in this repo.

@pdumais
Copy link

pdumais commented Feb 2, 2024

It's working now.
I can't create a PR to this repo since I changed too many things in the lib to make it work without Arduino core. But if someone wants to look at the fix and port it here, then here is the code: pdumais/small_rover#1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants