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
This commit is contained in:
+27
-8
@@ -20,19 +20,38 @@ 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 (probe + firmware load).
|
||||
// Create with xone_open(); call the getters from the thread that opened
|
||||
// it, and before xone_close(). Only one session may be open at a time.
|
||||
// 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;
|
||||
|
||||
// Open a dongle session: probe, USB reset, and (if firmware_path is not
|
||||
// NULL) load the firmware image from that file. Returns NULL if no dongle
|
||||
// is present or opening fails.
|
||||
xone_dongle *xone_open(const char *firmware_path);
|
||||
// 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)
|
||||
};
|
||||
|
||||
// Close the session and release the dongle.
|
||||
// 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);
|
||||
|
||||
|
||||
@@ -78,6 +78,11 @@ public:
|
||||
// rescan). Host-side operation that works even when EP0 is wedged. Any
|
||||
// existing transport handles are invalidated; probe() again for a fresh
|
||||
// session. Returns 0 on success, -errno on failure.
|
||||
//
|
||||
// Do not use yet: when the chip's SIE is crashed it cannot finish the
|
||||
// host-side port reset handshake and the device drops off the bus
|
||||
// entirely. A crashed chip recovers on its own via the MCU watchdog after
|
||||
// ~90s of a quiet bus, so prefer waiting over re-enumeration.
|
||||
auto re_enumerate() -> int;
|
||||
|
||||
~transport();
|
||||
|
||||
Reference in New Issue
Block a user