chore: scaffold CMake build system

Add the CMake build for the Swift + C++ macOS port, mirroring the
refix layout: deps/ modules (Platform, Flags, Sanitizers, FindUnity),
per-module static libraries (usb, auth, mt76, gip, hid, api), a Swift
app entry point with a pure C bridge header, and a Unity test suite
behind BUILD_TESTING.

Swift requires the Ninja or Xcode generator; a guard in
CMakeLists.txt rejects anything else.

Co-Authored-By: qwen (qwen/qwen3.8-27b@q2_k_xl): scaffolded CMake build + tests
This commit is contained in:
portersky
2026-08-17 14:18:03 +02:00
parent 78f042ab84
commit a7d7d0f253
25 changed files with 742 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
#pragma once
// ==============================================================================
// C ABI bridge between the C++ protocol stack and the Swift app layer
// ==============================================================================
// This header is imported into Swift via -import-objc-header, so it must stay
// pure C (no C++ types). The C++ modules implement these entry points.
// ==============================================================================
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
// Human-readable version string of the protocol stack.
const char *xone_version(void);
// TRUE if an Xbox Wireless Dongle is connected, FALSE otherwise.
bool xone_dongle_present(void);
#ifdef __cplusplus
}
#endif
+16
View File
@@ -0,0 +1,16 @@
#pragma once
// ==============================================================================
// Auth + crypto
// ==============================================================================
// Port target: medusalix/xone auth/auth.c + auth/crypto.c.
// ECDH (P-256) key agreement, RSA encryption, SHA transcript/PRF for the GIP
// authentication handshake. AES-CCMP frame encryption itself runs on-chip;
// this layer only derives and installs keys into the MT76 WCID registers.
// ==============================================================================
namespace xone::auth {
// TODO(phase 1): ECDH/RSA/SHA primitives (CommonCrypto / Security.framework).
} // namespace xone::auth
+49
View File
@@ -0,0 +1,49 @@
#pragma once
// ==============================================================================
// Platform types and endianness helpers (user-space)
// ==============================================================================
// Replaces the kernel's __le16/__le32/guid_t machinery for user-space use.
// All wire formats of the MT76 chip and the GIP protocol are little-endian;
// these byte-wise helpers stay correct on any host endianness.
// ==============================================================================
#include <cstdint>
namespace xone {
// 128-bit GUID used by the GIP protocol (port of the kernel guid_t).
struct guid_t {
std::uint8_t data[16];
};
inline auto load_le16(void const *p) -> std::uint16_t
{
auto const b = static_cast<std::uint8_t const *>(p);
return static_cast<std::uint16_t>(b[0] | (b[1] << 8));
}
inline auto store_le16(void *p, std::uint16_t v) -> void
{
auto *b = static_cast<std::uint8_t *>(p);
b[0] = static_cast<std::uint8_t>(v & 0xFF);
b[1] = static_cast<std::uint8_t>((v >> 8) & 0xFF);
}
inline auto load_le32(void const *p) -> std::uint32_t
{
auto const b = static_cast<std::uint8_t const *>(p);
return static_cast<std::uint32_t>(
b[0] | (b[1] << 8) | (b[2] << 16) | (static_cast<std::uint32_t>(b[3]) << 24));
}
inline auto store_le32(void *p, std::uint32_t v) -> void
{
auto *b = static_cast<std::uint8_t *>(p);
b[0] = static_cast<std::uint8_t>(v & 0xFF);
b[1] = static_cast<std::uint8_t>((v >> 8) & 0xFF);
b[2] = static_cast<std::uint8_t>((v >> 16) & 0xFF);
b[3] = static_cast<std::uint8_t>((v >> 24) & 0xFF);
}
} // namespace xone
+15
View File
@@ -0,0 +1,15 @@
#pragma once
// ==============================================================================
// GIP protocol (Game Input Protocol)
// ==============================================================================
// Port target: medusalix/xone bus/protocol.c + bus/bus.c.
// Client lifecycle, ANNOUNCE/IDENTIFY handshake, auth handshake, status
// reports (battery, connected), HID report pass-through.
// ==============================================================================
namespace xone::gip {
// TODO(phase 1): GIP frame types, client lifecycle, handshake state machine.
} // namespace xone::gip
+16
View File
@@ -0,0 +1,16 @@
#pragma once
// ==============================================================================
// Virtual HID gamepad presentation
// ==============================================================================
// Exposes connected controllers to macOS so games recognize them natively.
// Preferred path: DriverKit extension implementing IOHIDDriver with an
// Xbox 360/One-compatible report descriptor (input reports from GIP, output
// reports for rumble relayed back via GIP).
// ==============================================================================
namespace xone::hid {
// TODO(phase 4): report descriptor + virtual device presentation.
} // namespace xone::hid
+20
View File
@@ -0,0 +1,20 @@
#pragma once
// ==============================================================================
// MT76 chip protocol (MediaTek MT76xx radio in the dongle)
// ==============================================================================
// Port target: medusalix/xone transport/mt76.c + mt76.h + mt76_defs.h.
// Firmware load (0x3800-byte chunks), EFUSE read, radio init (~80 register
// writes), channel evaluation, beacon transmission, pairing mode, client
// association and WCID/AES-CCMP key setup (encryption runs on-chip).
// ==============================================================================
#include <cstdint>
namespace xone::mt76 {
// Load the firmware image for the given dongle PID into the chip.
// TODO(phase 3): port from xone_mt76_load_firmware().
auto load_firmware(std::uint16_t pid, char const *firmware_path) -> bool;
} // namespace xone::mt76
+25
View File
@@ -0,0 +1,25 @@
#pragma once
// ==============================================================================
// USB transport (IOKit / IOUSBFamily)
// ==============================================================================
// Owns the physical Xbox Wireless Dongle:
// VID 0x045E, PIDs 0x02E6 (old), 0x02FE (new), 0x02F9 (ASUS/Lenovo built-in),
// 0x091E (Surface Book 2).
//
// Port target: medusalix/xone transport/dongle.c + transport/mt76.c USB calls.
// Linux usb_control_msg()/usb_bulk_msg() map to IOUSBDeviceInterface
// DeviceRequest / IOUSBInterfaceInterface WritePipe+ReadPipe.
// ==============================================================================
#include <cstdint>
namespace xone::usb {
// Probe for a connected dongle and claim its WLAN interface
// (bInterfaceNumber 1).
// TODO(phase 2): IOKit implementation (IOServiceMatching, interface open,
// EP 0x04 bulk in/out + EP 0x05 interrupt in).
auto probe() -> bool;
} // namespace xone::usb