Files
portersky 0f6c985f7f feat: implement rumble TX over the GIP data path
Port the rumble packet from upstream driver/gamepad.c: a 9-byte
GIP_CMD_RUMBLE payload (motors R|L|RT|LT, intensities scaled to the
0..100 GIP range, duration/repeat constants). xone_controller_rumble
now sends it via client::send_rumble; the app button pulses both
motors for 0.6s then stops them. Completes the host to controller
TX remainder of Phase 3 (the dongle LED is already driven at chip
level for pairing and client lifecycle).

Co-Authored-By: qwen3.8-27b@q3_k_xl: implemented rumble TX
2026-08-29 15:19:14 +02:00

113 lines
4.3 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.
char const *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 common upstream image
// (firmware/xow_dongle.bin) is used.
int xone_start(xone_dongle *d, char const *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(xone_dongle const *d);
// Human-readable error from the last failed operation. Empty string if none.
char const *xone_error(xone_dongle const *d);
// Product ID of the connected dongle (e.g. 0x02E6).
uint16_t xone_pid(xone_dongle const *d);
// Chip ID from EFUSE (e.g. 0x7612 for MT7612). 0 if unknown.
uint16_t xone_chip_id(xone_dongle const *d);
// MAC address from EFUSE as "xx:xx:xx:xx:xx:xx". Valid until xone_close().
char const *xone_mac_address(xone_dongle const *d);
// Build string of the loaded firmware image (e.g. "201703281033____").
// Empty string if the firmware was not loaded. Valid until xone_close().
char const *xone_firmware_build(xone_dongle const *d);
// Number of connected controllers.
int xone_controller_count(xone_dongle const *d);
// Copy the controller at index into buf as "xx:xx:xx:xx:xx:xx". Returns 0 on
// success, -1 if index is out of range.
int xone_controller_mac(xone_dongle const *d, int index, char *buf, int len);
// Snapshot of the latest standard Xbox controller input report. Stick values
// are signed 16-bit values; trigger values are unsigned 10-bit values. The
// buttons field uses the standard GIP gamepad bit assignments. Battery fields
// come from periodic GIP status packets (battery_type is 0 when unknown).
struct xone_controller_state {
uint16_t buttons;
bool guide_down;
bool gip_ready;
bool input_active;
uint16_t trigger_left;
uint16_t trigger_right;
int16_t stick_left_x;
int16_t stick_left_y;
int16_t stick_right_x;
int16_t stick_right_y;
uint32_t sequence;
uint8_t battery_type;
uint8_t battery_level;
};
// Copy the latest input state for the controller at index. Returns 0 on
// success, -1 if index is out of range or state is NULL.
int xone_controller_get_state(xone_dongle const *d, int index,
struct xone_controller_state *state);
// Enter or leave pairing mode (beacon pairing flag + LED blink).
void xone_set_pairing(xone_dongle *d, bool enable);
// Send a rumble packet to the controller at index (host to controller TX
// over the GIP data path). Intensities use a 0..255 scale; passing zero for
// both stops the motors. Returns 0 on success, -1 for an invalid session or
// index, or if the client is not ready.
int xone_controller_rumble(xone_dongle *d, int index, uint8_t left,
uint8_t right);
#ifdef __cplusplus
}
#endif