rodneybakiskan / ps5-esp32

Use a ps5 controller with an esp32
104 stars 10 forks source link

ps5SendData example not working #3

Open dmartauz opened 2 years ago

dmartauz commented 2 years ago

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?

rodneybakiskan commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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:

nonobody15 commented 1 year ago

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

  1. ....
  2. ...
  3. 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!

nonobody15 commented 9 months ago

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 commented 7 months ago

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 commented 7 months ago

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 commented 7 months ago

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 commented 7 months ago

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: https://github.com/pdumais/small_rover/pull/1