Files
Sub 70f3419796 pad2c 1.1.0: 8BitDo USB Wireless Adapter 2 (closes #1), several controllers, settings page (#4)
* pad2c 1.1.0 (in progress): the 8BitDo USB Wireless Adapter 2, several pads

- Several pads at once, each its own virtual DualSense (up to 4), each
  slot remembering its own user (/data/pad2c/owner, owner.1, ...).
- New pads looked for every 100 ms; a node found not to be a pad is not
  opened again for 2 s unless it changes.
- XInput pads get what Windows asks first (the Microsoft OS string and
  the XUSB vendor request) before the LED: the USB Wireless Adapter 2
  then stays in XInput on its own, instead of ending in a DualShock 4
  mode that stops sending after a moment.
- A boot keyboard or mouse beside the pad (the adapter's macros, the
  2C receiver in XInput) is detached from the console's driver, so the
  console lists only the controller among its accessories.
- DInput: the adapter's touchpad bit (a DualSense's touchpad click).
- The adapter is named "8BitDo USB Wireless Adapter 2" (it calls itself
  "8BitDo Receiver" or "Controller").
- pad2c-probe: product and manufacturer strings, device release, 90 s.

Tested on a PS5 Slim, 13.60, adapter firmware 1.10: DualSense, Ultimate
2C and GameSir G8 through the adapter; DualSense on the adapter and the
2C on its own receiver at the same time.

* Settings page on port 8090; README and CHANGELOG for 1.1.0

- src/web.c: a small HTTP server in the main loop, never blocking the
  pads: GET / (the page), GET /api/status (JSON), POST /api/swap.
- src/webpage.h: one self-contained page: each controller's name, mode,
  slot and user, a Nintendo layout switch, and its buttons, sticks and
  triggers live (about 10 updates a second).
- src/config.c: /data/pad2c/config, "swap <controller name>" lines;
  unknown lines kept.
- The start notification gives the page's address.
- Tests: the settings file and the swap, the status JSON.

Tested on the PS5: the page from a computer, the live view, and the
swap on and off with a DualSense through the adapter.
2026-10-22 18:01:23 -03:00

38 lines
1.2 KiB
C

/* The status JSON of the settings page. Runs on the PC. */
#include "web.h"
#include <stdio.h>
#include <string.h>
static int fails;
#define CHECK(cond, ...) do { if (!(cond)) { printf("FAIL " __VA_ARGS__); printf("\n"); fails++; } } while (0)
int main(void)
{
web_pad p[2];
char out[2048];
memset(p, 0, sizeof p);
pad_state_reset(&p[0].st);
pad_state_reset(&p[1].st);
web_status_json(p, 2, out, sizeof out);
CHECK(strstr(out, "\"pads\":[]}") != NULL, "no pads: %s", out);
p[1].present = 1;
p[1].connected = 1;
p[1].swap = 1;
strcpy(p[1].name, "Pad \"X\" \\ 2");
strcpy(p[1].mode, "XInput");
strcpy(p[1].user, "Sub");
p[1].st.buttons = 0x4000;
web_status_json(p, 2, out, sizeof out);
CHECK(strstr(out, "\"slot\":1,\"name\":\"Pad \\\"X\\\" \\\\ 2\"") != NULL, "escaping: %s", out);
CHECK(strstr(out, "\"connected\":1,\"user\":\"Sub\",\"swap\":1,\"buttons\":16384") != NULL, "fields: %s", out);
CHECK(strstr(out, "\"slot\":0") == NULL, "an empty slot listed: %s", out);
CHECK(web_status_json(p, 2, out, 40) < 40 && strlen(out) < 40, "a small buffer overflowed");
printf("%s (%d failure(s))\n", fails ? "FAILED" : "all passed", fails);
return fails != 0;
}