Files
MoHadiShibli 20b6ea2e2a Create controllers without stopping the service, and match only our own device
Connecting a controller took a second or two in the middle of the request
handler: drain the kernel log, prove it delivers, call AddDevice, then read the
log until the device turns up. Everyone else waited. A second player adding a
controller froze the first player's input for as long as it took.

The service now owns one kernel-log reader and reads it a line at a time from
its main loop, and creating a controller is a state machine that loop advances:
drain, verify with a marker, AddDevice, adopt the DeviceId. Nothing blocks, so
the other players keep playing and keep being answered while it runs. Their
slots show "Connecting" until the claim is complete. One controller is created
at a time, because two AddDevice calls at once produce two log lines with no way
to tell which device is which; a second request is refused rather than queued.

Nothing in vda.c waits any more, so the callback that kept pads reporting
through those waits is gone, and the line parsing moved to src/klog_line.c,
which the host tests build as it is.

Only the login manager's own line is accepted as our new device now:
SCE_MBUS_EVENT_DEVICE_ADDED with subType 2. The old code fell back to any
"device added" line it saw, so a real pad being plugged in while a controller
was being created could hand us a DeviceId we do not own, and every input would
go to someone else's pad.

On the page: a refused claim re-reads the console's view and gives up only the
controllers that are in use elsewhere, instead of disconnecting everything this
device was playing with; and when getGamepads() starts throwing, every gamepad
source is blanked, so a held button cannot be flushed for ever with nothing left
to release it.

The test stub is now a fake kernel log: it writes the lines firmware 10.01
writes, our own mirrored output included, so the real reading, marker check and
DeviceId matching are what the tests exercise. SECURITY.md writes down what the
open-LAN design does and does not defend.
2026-10-05 02:12:34 +03:00

37 lines
1.7 KiB
C

/* Which kernel-log lines count as "our virtual pad was added". */
#include <assert.h>
#include <stdio.h>
#include "c4f_vda.h"
/* 0 when the line is not ours, otherwise the DeviceId it names. */
static uint64_t ours(const char *line)
{
return c4fKlogIsVirtualAdd(line) ? c4fKlogDeviceId(line) : 0;
}
int main(void)
{
/* What a virtual pad produces on firmware 10.01: type 1 when it is created
* for user 1, type 4 when it is created for a local-user id. */
assert(ours("<118>#LOGIN MGR# Receive Event : SCE_MBUS_EVENT_DEVICE_ADDED"
" [DeviceId:0x7030d][type:1][subType:2]") == 0x7030d);
assert(ours("<118>#LOGIN MGR# Receive Event : SCE_MBUS_EVENT_DEVICE_ADDED"
" [DeviceId:0x50301][type:4][subType:2]") == 0x50301);
/* Another MBus device turning up in the same window is not ours. A real pad
* being plugged in is subType 0, and the generic event line has no subType at
* all; taking either would send every input to a device we do not own. */
assert(ours("DEVICE_ADDED [DeviceId:0x123401] [type:1] [subType:0]") == 0);
assert(ours("ScePsP: sceMbusEvent has been received. (eventId=1 ADD, deviceId=0x123401)") == 0);
assert(ours("<118>#LOGIN MGR# Receive Event : SCE_MBUS_EVENT_DEVICE_REMOVED"
" [DeviceId:0x7030d][type:1][subType:2]") == 0);
assert(ours("<118>#LOGIN MGR# Receive Event : SCE_MBUS_EVENT_DEVICE_OWNER_CHANGED"
" [DeviceId:0x7030d][UserId:0x1a2b3c4d]") == 0);
/* The id is read in hex, whichever spelling the line uses. */
assert(c4fKlogDeviceId("[DeviceID=0xABCD][subType:2]") == 0xabcd);
assert(c4fKlogDeviceId("nothing here") == 0);
puts("PASS only the virtual pad's device-added line is accepted");
}