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

Descriptor data model / API design issues #125

Closed
martinling opened this issue Nov 10, 2024 · 2 comments · Fixed by #126
Closed

Descriptor data model / API design issues #125

martinling opened this issue Nov 10, 2024 · 2 comments · Fixed by #126

Comments

@martinling
Copy link
Member

martinling commented Nov 10, 2024

I’ve been working on making it possible to emulate a PS5 controller with Facedancer. In the process, I’ve run into some data model / API issues that aren't straightforward to fix.

The current model, as I understand it, can be summarised as follows:

  • A Configuration contains one or more Interface instances.
  • An Interface may have a single class_descriptor, which is an instance of USBClassDescriptor.
  • On a GET_CONFIGURATION request, this class_descriptor is included in the response, after the interface descriptor and before any endpoint descriptors.
  • Further USBClassDescriptor instances that appear within the Interface are not included in the GET_CONFIGURATION response. They can be fetched with the GET_DESCRIPTOR request instead.
  • Other USBDescriptor instances within an Interface, that are not a USBClassDescriptor, are excluded from the GET_CONFIGURATION response. They may be fetched with the GET_DESCRIPTOR request.

The problem is that this model does not really correspond to the USB standard, as follows:

  • There is no requirement that there be a single class descriptor for each interface.
  • There is not really any such thing as a class descriptor in the standard, except in the sense that descriptors with types in the range 0x20..0x3F have class-specific meanings.
  • Any number of descriptors may appear after an interface descriptor, including multiple descriptors of the same type. In particular, it is normal for a USB Audio Class device to include several consecutive class-specific descriptors, all of type 0x24.
  • Which descriptors are included in the GET_CONFIGURATION response, and which must be fetched separately with the GET_DESCRIPTOR request, is up to the device, or to the class definition.

I’m not quite sure how best to go about fixing this without breaking compatibility. The best I have come up with so far is:

  • Add a new property to USBDescriptor as follows:
# Whether this descriptor should be included in a GET_CONFIGURATION response.
include_in_configuration : bool = False
  • Set this property to True in USBClassDescriptor.
  • Deprecate the USBClassDescriptor class and the class_descriptor property of Interface, since these items do not have a clear meaning within the USB protocol.

This approach would not perfectly reproduce the existing behaviour of USBClassDescriptor, which is that only the first instance of it is included in a GET_CONFIGURATION response.

However, it would maintain compatibility with all the existing usage that I have been able to find.

A GitHub code search for USBClassDescriptor turns up only the following uses of this class:

All of these are simple HID devices, with a single USBClassDescriptor for the HID descriptor, followed by a HIDReportDescriptor that should not appear in the GET_CONFIGURATION response.

@nekrondev
Copy link

@martinling You might be interested to look into this epic thread (matlo/GIMX#672). It's about trying to proxy other Windows-connected controllers to PS5 as a faked DS5 controller. The bad thing Sony did was to add some 8 Byte (possibly 16 byte cropped) HMAC to the HID packets. If the HMAC doesn't match, your proxied controller will be disconnected after a few packets send. PS5 and DS5 controller do some DH key-exchange and both sides are verifying that the same shared secret is being used. If you try to proxy a DS4 controller there's a trick to use an original DS4 for the initial client certificate authentication that will be forwarded to the original controller and then after auth the unlicensed DS4-compatible controller can be used (projects like GP2020-CE do exactly this).

@martinling
Copy link
Member Author

@nekrondev Thanks, I'm aware of the authentication mechanism but hadn't seen that particular thread. We'll get onto this topic further into the video series.

This particular issue is just about fixing the Facedancer API to enable it to emulate devices that don't fit its current descriptor data model.

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

Successfully merging a pull request may close this issue.

2 participants