Files
xone_macos/include/app/xone_api.h
T
portersky b3e747b900 feat: async C API and Swift radio state display
Split the dongle session into a fast probe (xone_open) and a background
start (xone_start) that loads the firmware and initializes the radio on
a worker thread, so the app UI never blocks. Add xone_state/xone_error
for progress display, and select the firmware image per product ID when
no path is given. The Swift app polls the state each second and shows
idle/starting/ready/error plus the firmware build or error string.

The session destructor joins the worker so quitting the app does not
terminate on a joinable thread. Note in the CLI and transport that the
recover/re-enumerate path should not be used yet: a crashed SIE drops
off the bus, while the MCU watchdog recovers it after ~90s of quiet.

Co-Authored-By: qwen3.8-27b@q2_k_xl: async C API, Swift state display, and exit-time worker join
2026-08-17 19:57:40 +02:00

71 lines
2.6 KiB
C

#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>
#include <stdint.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);
// Opaque handle to an open dongle session. Create with xone_open(); only one
// session may be open at a time. The getters are safe to call from any thread.
typedef struct xone_dongle xone_dongle;
// Session states reported by xone_state().
enum {
XONE_STATE_IDLE = 0, // Probed; no firmware loaded yet
XONE_STATE_STARTING, // Firmware load + radio init in progress
XONE_STATE_READY, // Radio initialized
XONE_STATE_ERROR // Last operation failed (see xone_error)
};
// Open a dongle session: probe and USB reset. Fast; returns NULL if no dongle
// is present or opening fails. The EFUSE getters (xone_pid/xone_chip_id/
// xone_mac_address) are valid immediately after this.
xone_dongle *xone_open(void);
// Kick off firmware load + radio init on a background thread. Non-blocking:
// returns 0 once started, -1 if the session is busy or already ready. If
// firmware_path is NULL, the image is selected per product ID
// (firmware/xone_dongle_<pid>.bin).
int xone_start(xone_dongle *d, const char *firmware_path);
// Close the session and release the dongle. Waits for any in-progress start.
void xone_close(xone_dongle *d);
// Current session state (XONE_STATE_*).
int xone_state(const xone_dongle *d);
// Human-readable error from the last failed operation. Empty string if none.
const char *xone_error(const xone_dongle *d);
// Product ID of the connected dongle (e.g. 0x02E6).
uint16_t xone_pid(const xone_dongle *d);
// Chip ID from EFUSE (e.g. 0x7612 for MT7612). 0 if unknown.
uint16_t xone_chip_id(const xone_dongle *d);
// MAC address from EFUSE as "xx:xx:xx:xx:xx:xx". Valid until xone_close().
const char *xone_mac_address(const xone_dongle *d);
// Build string of the loaded firmware image (e.g. "201703281033____").
// Empty string if the firmware was not loaded. Valid until xone_close().
const char *xone_firmware_build(const xone_dongle *d);
#ifdef __cplusplus
}
#endif