mirror of
https://github.com/MoHadiShibli/Control4Free.git
synced 2026-10-14 07:02:24 +02:00
95 lines
4.0 KiB
C
95 lines
4.0 KiB
C
/* Control4Free -- the virtual device (VDA) lifecycle.
|
|
*
|
|
* One C4fVirtualPad is one virtual DualShock 4 as the system sees it. The call
|
|
* order and its reasons came from a staged diagnostic build, in the git history
|
|
* before 1.0.0.
|
|
*
|
|
* No function here blocks or waits, so the service can keep answering everyone
|
|
* else while a controller is being created.
|
|
*/
|
|
|
|
#ifndef C4F_VDA_H
|
|
#define C4F_VDA_H
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include "c4f_sce.h"
|
|
|
|
typedef struct {
|
|
int32_t handle; /* what InsertData takes: low 32 bits of deviceId */
|
|
uint64_t deviceId; /* the MBus DeviceId, read out of klog */
|
|
int32_t userId; /* the user it is bound to, or C4F_USER_ID_INVALID */
|
|
int32_t vdaUserId; /* the userId AddDevice was given */
|
|
int owned; /* we created it, so we delete it */
|
|
} C4fVirtualPad;
|
|
|
|
/* Loads libSceMbus. Must run before any scePad* call: libScePad imports from
|
|
* libSceMbus and those imports are unresolved in a payload, so calling into
|
|
* libScePad first can kill the process with PRX_NOT_RESOLVED_FUNCTION.
|
|
* Returns 0 on success. */
|
|
int c4fMbusInit(void);
|
|
|
|
/* scePadInit(), then scePadSetProcessPrivilege(1) (it fails with
|
|
* NOT_INITIALIZED the other way round). Returns 0 if scePadInit succeeded. */
|
|
int c4fPadInit(void);
|
|
|
|
/* ---- the kernel log ----
|
|
* /dev/klog has a single reader. GoldHEN's klog server opens it only while it
|
|
* has a client and serves one client at a time; after a client leaves it can
|
|
* go minutes without serving the next one (console, 2026-10-04). So the
|
|
* service reads the device itself, only while a controller signs in, and it
|
|
* owns the reader: these are the pieces it needs to make sense of a line. */
|
|
|
|
/* /dev/klog, non-blocking; -1 if another reader has it or it cannot be opened. */
|
|
int c4fKlogOpenDevice(void);
|
|
/* Writes one line into the kernel log, with no [c4f] prefix, so the reader can
|
|
* prove to itself that it really receives what the kernel logs. */
|
|
void c4fKlogMark(const char *marker);
|
|
/* 1 if this is the login manager's "a virtual pad was added" event. */
|
|
int c4fKlogIsVirtualAdd(const char *line);
|
|
/* The DeviceId named in this line, or 0. */
|
|
uint64_t c4fKlogDeviceId(const char *line);
|
|
|
|
/* ---- devices ---- */
|
|
|
|
/* AddDevice for `vdaUser`. The handle is not known yet: it is the DeviceId the
|
|
* kernel logs a moment later. Returns AddDevice's own value, which is non-zero
|
|
* even when the device is created, so the caller waits for the log either way. */
|
|
int32_t c4fVirtualPadAdd(int32_t vdaUser);
|
|
|
|
/* Completes a pad from the DeviceId that came out of the log. */
|
|
void c4fVirtualPadAdopt(C4fVirtualPad *out, int32_t userId, int32_t vdaUser, uint64_t deviceId);
|
|
|
|
/* ---- what the game asks of a controller ---- */
|
|
|
|
typedef struct {
|
|
uint8_t large, small; /* rumble motors, 0..255 */
|
|
uint8_t r, g, b; /* light bar; the PS4 uses 0x40 for full */
|
|
} C4fPadFeedback;
|
|
|
|
/* Reads the buffer scePadVirtualDeviceGetRemoteSetting fills (feedback.c). */
|
|
void c4fPadFeedbackParse(const uint8_t *buf, size_t size, C4fPadFeedback *out);
|
|
|
|
/* The rumble and light bar the system wants on this controller right now.
|
|
* Returns 0, the call's error code, or -1 if the call isn't exported. */
|
|
int32_t c4fVirtualPadFeedback(const C4fVirtualPad *pad, C4fPadFeedback *out);
|
|
|
|
/* The PS4's name for a user, as it shows it. Returns 0, or the call's error.
|
|
* Not written to the log: people post logs in bug reports. */
|
|
int32_t c4fUserName(uint32_t userId, char *out, size_t size);
|
|
/* Current local login sessions, independently of cached names or pad assignment.
|
|
* Failed reads never mean a user logged out. Events are nonblocking. */
|
|
int32_t c4fLoginUsers(int32_t userIds[4]);
|
|
int32_t c4fUserEvent(int32_t *type, uint32_t *userId);
|
|
|
|
/* A neutral sample: sticks centred, identity quaternion, connected. */
|
|
void c4fPadDataNeutral(ScePadData *data);
|
|
|
|
/* One InsertData call. Returns the raw return value. */
|
|
int32_t c4fVirtualPadInsert(const C4fVirtualPad *pad, const ScePadData *data);
|
|
|
|
/* DeleteDevice, if we own the handle. */
|
|
void c4fVirtualPadRemove(C4fVirtualPad *pad);
|
|
|
|
#endif /* C4F_VDA_H */
|