mirror of
https://github.com/sub0x00001/pad2c.git
synced 2026-10-25 11:02:48 +01:00
* 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.
67 lines
3.1 KiB
C
67 lines
3.1 KiB
C
/* The 8BitDo mapping against reports captured on the console (calibration of
|
|
* 5 October 2026: each button pressed alone, in order). Runs on the PC. */
|
|
#include "usbpad.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
static int fails;
|
|
|
|
static void expect(const char *what, const unsigned char r[10], uint32_t buttons)
|
|
{
|
|
pad_state st;
|
|
|
|
if (!usbpad_parse_8bitdo(r, 10, &st)) {
|
|
printf("FAIL %s: not parsed\n", what);
|
|
fails++;
|
|
return;
|
|
}
|
|
if (st.buttons != buttons) {
|
|
printf("FAIL %s: buttons %#x, want %#x\n", what, (unsigned)st.buttons, (unsigned)buttons);
|
|
fails++;
|
|
}
|
|
}
|
|
|
|
#define R(b1, b2, hat, lx, ly, rx, ry, rt, lt) (const unsigned char[10]){ 1, b1, b2, hat, lx, ly, rx, ry, rt, lt }
|
|
|
|
int main(void)
|
|
{
|
|
pad_state st;
|
|
|
|
expect("idle", R(0x00, 0x00, 0x0f, 127, 127, 127, 127, 0, 0), 0);
|
|
expect("A", R(0x01, 0x00, 0x0f, 127, 127, 127, 127, 0, 0), PAD_CROSS);
|
|
expect("B", R(0x02, 0x00, 0x0f, 127, 127, 127, 127, 0, 0), PAD_CIRCLE);
|
|
expect("X", R(0x08, 0x00, 0x0f, 127, 127, 127, 127, 0, 0), PAD_SQUARE);
|
|
expect("Y", R(0x10, 0x00, 0x0f, 127, 127, 127, 127, 0, 0), PAD_TRIANGLE);
|
|
expect("LB", R(0x40, 0x00, 0x0f, 127, 127, 127, 127, 0, 0), PAD_L1);
|
|
expect("RB", R(0x80, 0x00, 0x0f, 127, 127, 127, 127, 0, 0), PAD_R1);
|
|
expect("LT", R(0x00, 0x01, 0x0f, 127, 127, 127, 127, 0, 255), PAD_L2);
|
|
expect("RT", R(0x00, 0x02, 0x0f, 127, 127, 127, 127, 255, 0), PAD_R2);
|
|
expect("View", R(0x00, 0x04, 0x0f, 127, 127, 127, 127, 0, 0), PAD_CREATE);
|
|
expect("Menu", R(0x00, 0x08, 0x0f, 127, 127, 127, 127, 0, 0), PAD_OPTIONS);
|
|
expect("Home", R(0x00, 0x10, 0x0f, 127, 127, 127, 127, 0, 0), PAD_PS);
|
|
expect("L3", R(0x00, 0x20, 0x0f, 127, 127, 127, 127, 0, 0), PAD_L3);
|
|
expect("R3", R(0x00, 0x40, 0x0f, 127, 127, 127, 127, 0, 0), PAD_R3);
|
|
expect("up", R(0x00, 0x00, 0x00, 127, 127, 127, 127, 0, 0), PAD_UP);
|
|
expect("right", R(0x00, 0x00, 0x02, 127, 127, 127, 127, 0, 0), PAD_RIGHT);
|
|
expect("down", R(0x00, 0x00, 0x04, 127, 127, 127, 127, 0, 0), PAD_DOWN);
|
|
expect("left", R(0x00, 0x00, 0x06, 127, 127, 127, 127, 0, 0), PAD_LEFT);
|
|
expect("L4", R(0x04, 0x00, 0x0f, 127, 127, 127, 127, 0, 0), PAD_TOUCHPAD);
|
|
expect("R4", R(0x20, 0x00, 0x0f, 127, 127, 127, 127, 0, 0), PAD_TOUCHPAD);
|
|
expect("LT half",R(0x00, 0x00, 0x0f, 127, 127, 127, 127, 0, 43), PAD_L2);
|
|
/* The 8BitDo USB Wireless Adapter 2 in DInput mode: a DualSense's touchpad click */
|
|
expect("touchpad", R(0x00, 0x00, 0x1f, 127, 127, 127, 127, 0, 0), PAD_TOUCHPAD);
|
|
expect("touchpad+up", R(0x00, 0x00, 0x10, 127, 127, 127, 127, 0, 0), PAD_TOUCHPAD | PAD_UP);
|
|
|
|
usbpad_parse_8bitdo(R(0, 0, 0x0f, 126, 31, 224, 136, 7, 9), 10, &st);
|
|
if (st.lx != 126 || st.ly != 31 || st.rx != 224 || st.ry != 136 || st.r2 != 7 || st.l2 != 9) {
|
|
printf("FAIL sticks/triggers\n");
|
|
fails++;
|
|
}
|
|
if (usbpad_parse_8bitdo((const unsigned char[10]){ 2 }, 10, &st)) {
|
|
printf("FAIL: IDLE report 2 taken as a pad report\n");
|
|
fails++;
|
|
}
|
|
printf("%s (%d failure(s))\n", fails ? "FAILED" : "all passed", fails);
|
|
return fails != 0;
|
|
}
|