From 4489d91957a01ff81e5196ae2fdff2cde556f829 Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Sun, 25 Aug 2024 06:55:42 -0300 Subject: [PATCH] Adding C bindings --- lib/c_bindings/C_LinkCable.cpp | 83 ++++++++ lib/c_bindings/C_LinkCable.h | 74 +++++++ lib/c_bindings/C_LinkCableMultiboot.cpp | 25 +++ lib/c_bindings/C_LinkCableMultiboot.h | 40 ++++ lib/c_bindings/C_LinkCube.cpp | 61 ++++++ lib/c_bindings/C_LinkCube.h | 43 ++++ lib/c_bindings/C_LinkGPIO.cpp | 47 +++++ lib/c_bindings/C_LinkGPIO.h | 47 +++++ lib/c_bindings/C_LinkMobile.cpp | 105 ++++++++++ lib/c_bindings/C_LinkMobile.h | 138 +++++++++++++ lib/c_bindings/C_LinkPS2Keyboard.cpp | 34 +++ lib/c_bindings/C_LinkPS2Keyboard.h | 39 ++++ lib/c_bindings/C_LinkPS2Mouse.cpp | 33 +++ lib/c_bindings/C_LinkPS2Mouse.h | 31 +++ lib/c_bindings/C_LinkRawCable.cpp | 85 ++++++++ lib/c_bindings/C_LinkRawCable.h | 69 +++++++ lib/c_bindings/C_LinkRawWireless.cpp | 227 +++++++++++++++++++++ lib/c_bindings/C_LinkRawWireless.h | 158 ++++++++++++++ lib/c_bindings/C_LinkSPI.cpp | 79 +++++++ lib/c_bindings/C_LinkSPI.h | 70 +++++++ lib/c_bindings/C_LinkUART.cpp | 92 +++++++++ lib/c_bindings/C_LinkUART.h | 71 +++++++ lib/c_bindings/C_LinkUniversal.cpp | 125 ++++++++++++ lib/c_bindings/C_LinkUniversal.h | 112 ++++++++++ lib/c_bindings/C_LinkWireless.cpp | 144 +++++++++++++ lib/c_bindings/C_LinkWireless.h | 145 +++++++++++++ lib/c_bindings/C_LinkWirelessMultiboot.cpp | 36 ++++ lib/c_bindings/C_LinkWirelessMultiboot.h | 65 ++++++ 28 files changed, 2278 insertions(+) create mode 100644 lib/c_bindings/C_LinkCable.cpp create mode 100644 lib/c_bindings/C_LinkCable.h create mode 100644 lib/c_bindings/C_LinkCableMultiboot.cpp create mode 100644 lib/c_bindings/C_LinkCableMultiboot.h create mode 100644 lib/c_bindings/C_LinkCube.cpp create mode 100644 lib/c_bindings/C_LinkCube.h create mode 100644 lib/c_bindings/C_LinkGPIO.cpp create mode 100644 lib/c_bindings/C_LinkGPIO.h create mode 100644 lib/c_bindings/C_LinkMobile.cpp create mode 100644 lib/c_bindings/C_LinkMobile.h create mode 100644 lib/c_bindings/C_LinkPS2Keyboard.cpp create mode 100644 lib/c_bindings/C_LinkPS2Keyboard.h create mode 100644 lib/c_bindings/C_LinkPS2Mouse.cpp create mode 100644 lib/c_bindings/C_LinkPS2Mouse.h create mode 100644 lib/c_bindings/C_LinkRawCable.cpp create mode 100644 lib/c_bindings/C_LinkRawCable.h create mode 100644 lib/c_bindings/C_LinkRawWireless.cpp create mode 100644 lib/c_bindings/C_LinkRawWireless.h create mode 100644 lib/c_bindings/C_LinkSPI.cpp create mode 100644 lib/c_bindings/C_LinkSPI.h create mode 100644 lib/c_bindings/C_LinkUART.cpp create mode 100644 lib/c_bindings/C_LinkUART.h create mode 100644 lib/c_bindings/C_LinkUniversal.cpp create mode 100644 lib/c_bindings/C_LinkUniversal.h create mode 100644 lib/c_bindings/C_LinkWireless.cpp create mode 100644 lib/c_bindings/C_LinkWireless.h create mode 100644 lib/c_bindings/C_LinkWirelessMultiboot.cpp create mode 100644 lib/c_bindings/C_LinkWirelessMultiboot.h diff --git a/lib/c_bindings/C_LinkCable.cpp b/lib/c_bindings/C_LinkCable.cpp new file mode 100644 index 0000000..73fde57 --- /dev/null +++ b/lib/c_bindings/C_LinkCable.cpp @@ -0,0 +1,83 @@ +#include "C_LinkCable.h" +#include "../LinkCable.hpp" + +extern "C" { + +C_LinkCableHandle C_LinkCable_create(C_LinkCable_BaudRate baudRate, + u32 timeout, + u16 interval, + u8 sendTimerId) { + return new LinkCable(static_cast(baudRate), timeout, + interval, sendTimerId); +} + +void C_LinkCable_destroy(C_LinkCableHandle handle) { + delete static_cast(handle); +} + +bool C_LinkCable_isActive(C_LinkCableHandle handle) { + return static_cast(handle)->isActive(); +} + +void C_LinkCable_activate(C_LinkCableHandle handle) { + static_cast(handle)->activate(); +} + +void C_LinkCable_deactivate(C_LinkCableHandle handle) { + static_cast(handle)->deactivate(); +} + +bool C_LinkCable_isConnected(C_LinkCableHandle handle) { + return static_cast(handle)->isConnected(); +} + +u8 C_LinkCable_playerCount(C_LinkCableHandle handle) { + return static_cast(handle)->playerCount(); +} + +u8 C_LinkCable_currentPlayerId(C_LinkCableHandle handle) { + return static_cast(handle)->currentPlayerId(); +} + +void C_LinkCable_sync(C_LinkCableHandle handle) { + static_cast(handle)->sync(); +} + +bool C_LinkCable_waitFor(C_LinkCableHandle handle, u8 playerId) { + return static_cast(handle)->waitFor(playerId); +} + +bool C_LinkCable_waitForWithCancel(C_LinkCableHandle handle, + u8 playerId, + bool (*cancel)()) { + return static_cast(handle)->waitFor(playerId, cancel); +} + +bool C_LinkCable_canRead(C_LinkCableHandle handle, u8 playerId) { + return static_cast(handle)->canRead(playerId); +} + +u16 C_LinkCable_read(C_LinkCableHandle handle, u8 playerId) { + return static_cast(handle)->read(playerId); +} + +u16 C_LinkCable_peek(C_LinkCableHandle handle, u8 playerId) { + return static_cast(handle)->peek(playerId); +} + +void C_LinkCable_send(C_LinkCableHandle handle, u16 data) { + static_cast(handle)->send(data); +} + +void C_LinkCable_onVBlank(C_LinkCableHandle handle) { + static_cast(handle)->_onVBlank(); +} + +void C_LinkCable_onSerial(C_LinkCableHandle handle) { + static_cast(handle)->_onSerial(); +} + +void C_LinkCable_onTimer(C_LinkCableHandle handle) { + static_cast(handle)->_onTimer(); +} +} diff --git a/lib/c_bindings/C_LinkCable.h b/lib/c_bindings/C_LinkCable.h new file mode 100644 index 0000000..1f250bd --- /dev/null +++ b/lib/c_bindings/C_LinkCable.h @@ -0,0 +1,74 @@ +#ifndef C_BINDINGS_LINK_CABLE_H +#define C_BINDINGS_LINK_CABLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef void* C_LinkCableHandle; + +#define C_LINK_CABLE_MAX_PLAYERS 4 +#define C_LINK_CABLE_DEFAULT_TIMEOUT 3 +#define C_LINK_CABLE_DEFAULT_INTERVAL 50 +#define C_LINK_CABLE_DEFAULT_SEND_TIMER_ID 3 +#define C_LINK_CABLE_DISCONNECTED 0xffff +#define C_LINK_CABLE_NO_DATA 0x0 + +typedef enum { + C_BAUD_RATE_0, // 9600 bps + C_BAUD_RATE_1, // 38400 bps + C_BAUD_RATE_2, // 57600 bps + C_BAUD_RATE_3 // 115200 bps +} C_LinkCable_BaudRate; + +C_LinkCableHandle C_LinkCable_create(C_LinkCable_BaudRate baudRate, + u32 timeout, + u16 interval, + u8 sendTimerId); +void C_LinkCable_destroy(C_LinkCableHandle handle); + +bool C_LinkCable_isActive(C_LinkCableHandle handle); +void C_LinkCable_activate(C_LinkCableHandle handle); +void C_LinkCable_deactivate(C_LinkCableHandle handle); + +bool C_LinkCable_isConnected(C_LinkCableHandle handle); +u8 C_LinkCable_playerCount(C_LinkCableHandle handle); +u8 C_LinkCable_currentPlayerId(C_LinkCableHandle handle); + +void C_LinkCable_sync(C_LinkCableHandle handle); +bool C_LinkCable_waitFor(C_LinkCableHandle handle, u8 playerId); +bool C_LinkCable_waitForWithCancel(C_LinkCableHandle handle, + u8 playerId, + bool (*cancel)()); + +bool C_LinkCable_canRead(C_LinkCableHandle handle, u8 playerId); +u16 C_LinkCable_read(C_LinkCableHandle handle, u8 playerId); +u16 C_LinkCable_peek(C_LinkCableHandle handle, u8 playerId); + +void C_LinkCable_send(C_LinkCableHandle handle, u16 data); + +void C_LinkCable_onVBlank(C_LinkCableHandle handle); +void C_LinkCable_onSerial(C_LinkCableHandle handle); +void C_LinkCable_onTimer(C_LinkCableHandle handle); + +extern C_LinkCableHandle cLinkCable; + +inline void C_LINK_CABLE_ISR_VBLANK() { + C_LinkCable_onVBlank(cLinkCable); +} + +inline void C_LINK_CABLE_ISR_SERIAL() { + C_LinkCable_onSerial(cLinkCable); +} + +inline void C_LINK_CABLE_ISR_TIMER() { + C_LinkCable_onTimer(cLinkCable); +} + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_CABLE_H diff --git a/lib/c_bindings/C_LinkCableMultiboot.cpp b/lib/c_bindings/C_LinkCableMultiboot.cpp new file mode 100644 index 0000000..13d7847 --- /dev/null +++ b/lib/c_bindings/C_LinkCableMultiboot.cpp @@ -0,0 +1,25 @@ +#include "C_LinkCableMultiboot.h" +#include "../LinkCableMultiboot.hpp" + +extern "C" { + +C_LinkCableMultibootHandle C_LinkCableMultiboot_create(void) { + return new LinkCableMultiboot(); +} + +void C_LinkCableMultiboot_destroy(C_LinkCableMultibootHandle handle) { + delete static_cast(handle); +} + +C_LinkCableMultiboot_Result C_LinkCableMultiboot_sendRom( + C_LinkCableMultibootHandle handle, + const u8* rom, + u32 romSize, + bool (*cancel)(void), + C_LinkCableMultiboot_TransferMode mode) { + return static_cast( + static_cast(handle)->sendRom( + rom, romSize, cancel, + static_cast(mode))); +} +} diff --git a/lib/c_bindings/C_LinkCableMultiboot.h b/lib/c_bindings/C_LinkCableMultiboot.h new file mode 100644 index 0000000..2235427 --- /dev/null +++ b/lib/c_bindings/C_LinkCableMultiboot.h @@ -0,0 +1,40 @@ +#ifndef C_BINDINGS_LINK_CABLE_MULTIBOOT_H +#define C_BINDINGS_LINK_CABLE_MULTIBOOT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef enum { + C_LINK_CABLE_MULTIBOOT_SUCCESS, + C_LINK_CABLE_MULTIBOOT_INVALID_SIZE, + C_LINK_CABLE_MULTIBOOT_CANCELED, + C_LINK_CABLE_MULTIBOOT_FAILURE_DURING_TRANSFER +} C_LinkCableMultiboot_Result; + +typedef enum { + C_LINK_CABLE_MULTIBOOT_TRANSFER_MODE_SPI = 0, + C_LINK_CABLE_MULTIBOOT_TRANSFER_MODE_MULTI_PLAY = 1 +} C_LinkCableMultiboot_TransferMode; + +typedef void* C_LinkCableMultibootHandle; + +C_LinkCableMultibootHandle C_LinkCableMultiboot_create(void); +void C_LinkCableMultiboot_destroy(C_LinkCableMultibootHandle handle); + +C_LinkCableMultiboot_Result C_LinkCableMultiboot_sendRom( + C_LinkCableMultibootHandle handle, + const u8* rom, + u32 romSize, + bool (*cancel)(void), + C_LinkCableMultiboot_TransferMode mode); + +extern C_LinkCableMultibootHandle cLinkCableMultiboot; + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_CABLE_MULTIBOOT_H diff --git a/lib/c_bindings/C_LinkCube.cpp b/lib/c_bindings/C_LinkCube.cpp new file mode 100644 index 0000000..ee1a7cc --- /dev/null +++ b/lib/c_bindings/C_LinkCube.cpp @@ -0,0 +1,61 @@ +#include "C_LinkCube.h" +#include "../LinkCube.hpp" + +extern "C" { + +C_LinkCubeHandle C_LinkCube_create() { + return new LinkCube(); +} + +void C_LinkCube_destroy(C_LinkCubeHandle handle) { + delete static_cast(handle); +} + +bool C_LinkCube_isActive(C_LinkCubeHandle handle) { + return static_cast(handle)->isActive(); +} + +void C_LinkCube_activate(C_LinkCubeHandle handle) { + static_cast(handle)->activate(); +} + +void C_LinkCube_deactivate(C_LinkCubeHandle handle) { + static_cast(handle)->deactivate(); +} + +bool C_LinkCube_wait(C_LinkCubeHandle handle) { + return static_cast(handle)->wait(); +} + +bool C_LinkCube_waitWithCancel(C_LinkCubeHandle handle, bool (*cancel)()) { + return static_cast(handle)->wait(cancel); +} + +bool C_LinkCube_canRead(C_LinkCubeHandle handle) { + return static_cast(handle)->canRead(); +} + +u32 C_LinkCube_read(C_LinkCubeHandle handle) { + return static_cast(handle)->read(); +} + +u32 C_LinkCube_peek(C_LinkCubeHandle handle) { + return static_cast(handle)->peek(); +} + +void C_LinkCube_send(C_LinkCubeHandle handle, u32 data) { + static_cast(handle)->send(data); +} + +u32 C_LinkCube_pendingCount(C_LinkCubeHandle handle) { + return static_cast(handle)->pendingCount(); +} + +bool C_LinkCube_didReset(C_LinkCubeHandle handle, bool clear) { + return static_cast(handle)->didReset(clear); +} + +void C_LinkCube_onSerial(C_LinkCubeHandle handle) { + static_cast(handle)->_onSerial(); +} +} diff --git a/lib/c_bindings/C_LinkCube.h b/lib/c_bindings/C_LinkCube.h new file mode 100644 index 0000000..aeaa1d4 --- /dev/null +++ b/lib/c_bindings/C_LinkCube.h @@ -0,0 +1,43 @@ +#ifndef C_BINDINGS_LINK_CUBE_H +#define C_BINDINGS_LINK_CUBE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef void* C_LinkCubeHandle; + +C_LinkCubeHandle C_LinkCube_create(); +void C_LinkCube_destroy(C_LinkCubeHandle handle); + +bool C_LinkCube_isActive(C_LinkCubeHandle handle); +void C_LinkCube_activate(C_LinkCubeHandle handle); +void C_LinkCube_deactivate(C_LinkCubeHandle handle); + +bool C_LinkCube_wait(C_LinkCubeHandle handle); +bool C_LinkCube_waitWithCancel(C_LinkCubeHandle handle, bool (*cancel)()); + +bool C_LinkCube_canRead(C_LinkCubeHandle handle); +u32 C_LinkCube_read(C_LinkCubeHandle handle); +u32 C_LinkCube_peek(C_LinkCubeHandle handle); + +void C_LinkCube_send(C_LinkCubeHandle handle, u32 data); +u32 C_LinkCube_pendingCount(C_LinkCubeHandle handle); + +bool C_LinkCube_didReset(C_LinkCubeHandle handle, bool clear); + +void C_LinkCube_onSerial(C_LinkCubeHandle handle); + +extern C_LinkCubeHandle cLinkCube; + +inline void C_LINK_CUBE_ISR_SERIAL() { + C_LinkCube_onSerial(cLinkCube); +} + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_CUBE_H diff --git a/lib/c_bindings/C_LinkGPIO.cpp b/lib/c_bindings/C_LinkGPIO.cpp new file mode 100644 index 0000000..747863c --- /dev/null +++ b/lib/c_bindings/C_LinkGPIO.cpp @@ -0,0 +1,47 @@ +#include "C_LinkGPIO.h" +#include "../LinkGPIO.hpp" + +extern "C" { + +C_LinkGPIOHandle C_LinkGPIO_create(void) { + return new LinkGPIO(); +} + +void C_LinkGPIO_destroy(C_LinkGPIOHandle handle) { + delete static_cast(handle); +} + +void C_LinkGPIO_reset(C_LinkGPIOHandle handle) { + static_cast(handle)->reset(); +} + +void C_LinkGPIO_setMode(C_LinkGPIOHandle handle, + C_LinkGPIO_Pin pin, + C_LinkGPIO_Direction direction) { + static_cast(handle)->setMode( + static_cast(pin), + static_cast(direction)); +} + +C_LinkGPIO_Direction C_LinkGPIO_getMode(C_LinkGPIOHandle handle, + C_LinkGPIO_Pin pin) { + return static_cast( + static_cast(handle)->getMode(static_cast(pin))); +} + +bool C_LinkGPIO_readPin(C_LinkGPIOHandle handle, C_LinkGPIO_Pin pin) { + return static_cast(handle)->readPin( + static_cast(pin)); +} + +void C_LinkGPIO_writePin(C_LinkGPIOHandle handle, + C_LinkGPIO_Pin pin, + bool isHigh) { + static_cast(handle)->writePin(static_cast(pin), + isHigh); +} + +void C_LinkGPIO_setSIInterrupts(C_LinkGPIOHandle handle, bool isEnabled) { + static_cast(handle)->setSIInterrupts(isEnabled); +} +} diff --git a/lib/c_bindings/C_LinkGPIO.h b/lib/c_bindings/C_LinkGPIO.h new file mode 100644 index 0000000..d3b4614 --- /dev/null +++ b/lib/c_bindings/C_LinkGPIO.h @@ -0,0 +1,47 @@ +#ifndef C_BINDINGS_LINK_GPIO_H +#define C_BINDINGS_LINK_GPIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef void* C_LinkGPIOHandle; + +typedef enum { + C_LINK_GPIO_PIN_SI, + C_LINK_GPIO_PIN_SO, + C_LINK_GPIO_PIN_SD, + C_LINK_GPIO_PIN_SC +} C_LinkGPIO_Pin; + +typedef enum { + C_LINK_GPIO_DIRECTION_INPUT, + C_LINK_GPIO_DIRECTION_OUTPUT +} C_LinkGPIO_Direction; + +C_LinkGPIOHandle C_LinkGPIO_create(void); +void C_LinkGPIO_destroy(C_LinkGPIOHandle handle); + +void C_LinkGPIO_reset(C_LinkGPIOHandle handle); +void C_LinkGPIO_setMode(C_LinkGPIOHandle handle, + C_LinkGPIO_Pin pin, + C_LinkGPIO_Direction direction); +C_LinkGPIO_Direction C_LinkGPIO_getMode(C_LinkGPIOHandle handle, + C_LinkGPIO_Pin pin); + +bool C_LinkGPIO_readPin(C_LinkGPIOHandle handle, C_LinkGPIO_Pin pin); +void C_LinkGPIO_writePin(C_LinkGPIOHandle handle, + C_LinkGPIO_Pin pin, + bool isHigh); + +void C_LinkGPIO_setSIInterrupts(C_LinkGPIOHandle handle, bool isEnabled); + +extern C_LinkGPIOHandle cLinkGPIO; + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_GPIO_H diff --git a/lib/c_bindings/C_LinkMobile.cpp b/lib/c_bindings/C_LinkMobile.cpp new file mode 100644 index 0000000..1a2f462 --- /dev/null +++ b/lib/c_bindings/C_LinkMobile.cpp @@ -0,0 +1,105 @@ +#include "C_LinkMobile.h" +#include "../LinkMobile.hpp" + +extern "C" { + +C_LinkMobileHandle C_LinkMobile_create(u32 timeout, u8 timerId) { + return new LinkMobile(timeout, timerId); +} + +void C_LinkMobile_destroy(C_LinkMobileHandle handle) { + delete static_cast(handle); +} + +bool C_LinkMobile_isActive(C_LinkMobileHandle handle) { + return static_cast(handle)->isActive(); +} + +void C_LinkMobile_activate(C_LinkMobileHandle handle) { + static_cast(handle)->activate(); +} + +void C_LinkMobile_deactivate(C_LinkMobileHandle handle) { + static_cast(handle)->deactivate(); +} + +bool C_LinkMobile_shutdown(C_LinkMobileHandle handle) { + return static_cast(handle)->shutdown(); +} + +bool C_LinkMobile_call(C_LinkMobileHandle handle, const char* phoneNumber) { + return static_cast(handle)->call(phoneNumber); +} + +bool C_LinkMobile_callISP(C_LinkMobileHandle handle, + const char* password, + const char* loginId) { + return static_cast(handle)->callISP(password, loginId); +} + +bool C_LinkMobile_dnsQuery(C_LinkMobileHandle handle, + const char* domainName, + C_LinkMobileDNSQuery* result) { + return static_cast(handle)->dnsQuery( + domainName, reinterpret_cast(result)); +} + +bool C_LinkMobile_openConnection(C_LinkMobileHandle handle, + const u8* ip, + u16 port, + C_LinkMobileConnectionType type, + C_LinkMobileOpenConn* result) { + return static_cast(handle)->openConnection( + ip, port, static_cast(type), + reinterpret_cast(result)); +} + +bool C_LinkMobile_closeConnection(C_LinkMobileHandle handle, + u8 connectionId, + C_LinkMobileConnectionType type, + C_LinkMobileCloseConn* result) { + return static_cast(handle)->closeConnection( + connectionId, static_cast(type), + reinterpret_cast(result)); +} + +bool C_LinkMobile_transfer(C_LinkMobileHandle handle, + C_LinkMobileDataTransfer dataToSend, + C_LinkMobileDataTransfer* result, + u8 connectionId) { + return static_cast(handle)->transfer( + *reinterpret_cast(&dataToSend), + reinterpret_cast(result), connectionId); +} + +bool C_LinkMobile_waitFor(C_LinkMobileHandle handle, void* asyncRequest) { + return static_cast(handle)->waitFor( + static_cast(asyncRequest)); +} + +bool C_LinkMobile_hangUp(C_LinkMobileHandle handle) { + return static_cast(handle)->hangUp(); +} + +C_LinkMobile_State C_LinkMobile_getState(C_LinkMobileHandle handle) { + return static_cast( + static_cast(handle)->getState()); +} + +C_LinkMobile_Role C_LinkMobile_getRole(C_LinkMobileHandle handle) { + return static_cast( + static_cast(handle)->getRole()); +} + +void C_LinkMobile_onVBlank(C_LinkMobileHandle handle) { + static_cast(handle)->_onVBlank(); +} + +void C_LinkMobile_onSerial(C_LinkMobileHandle handle) { + static_cast(handle)->_onSerial(); +} + +void C_LinkMobile_onTimer(C_LinkMobileHandle handle) { + static_cast(handle)->_onTimer(); +} +} diff --git a/lib/c_bindings/C_LinkMobile.h b/lib/c_bindings/C_LinkMobile.h new file mode 100644 index 0000000..7729836 --- /dev/null +++ b/lib/c_bindings/C_LinkMobile.h @@ -0,0 +1,138 @@ +#ifndef C_BINDINGS_LINK_MOBILE_H +#define C_BINDINGS_LINK_MOBILE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef void* C_LinkMobileHandle; + +#define C_LINK_MOBILE_MAX_USER_TRANSFER_LENGTH 254 +#define C_LINK_MOBILE_MAX_COMMAND_TRANSFER_LENGTH 255 +#define C_LINK_MOBILE_MAX_PHONE_NUMBER_LENGTH 32 +#define C_LINK_MOBILE_MAX_LOGIN_ID_LENGTH 32 +#define C_LINK_MOBILE_MAX_PASSWORD_LENGTH 32 +#define C_LINK_MOBILE_MAX_DOMAIN_NAME_LENGTH 253 +#define C_LINK_MOBILE_COMMAND_TRANSFER_BUFFER \ + (C_LINK_MOBILE_MAX_COMMAND_TRANSFER_LENGTH + 4) +#define C_LINK_MOBILE_DEFAULT_TIMEOUT (60 * 10) +#define C_LINK_MOBILE_DEFAULT_TIMER_ID 3 + +typedef enum { + C_LINK_MOBILE_STATE_NEEDS_RESET, + C_LINK_MOBILE_STATE_PINGING, + C_LINK_MOBILE_STATE_WAITING_TO_START, + C_LINK_MOBILE_STATE_STARTING_SESSION, + C_LINK_MOBILE_STATE_ACTIVATING_SIO32, + C_LINK_MOBILE_STATE_WAITING_32BIT_SWITCH, + C_LINK_MOBILE_STATE_READING_CONFIGURATION, + C_LINK_MOBILE_STATE_SESSION_ACTIVE, + C_LINK_MOBILE_STATE_CALL_REQUESTED, + C_LINK_MOBILE_STATE_CALLING, + C_LINK_MOBILE_STATE_CALL_ESTABLISHED, + C_LINK_MOBILE_STATE_ISP_CALL_REQUESTED, + C_LINK_MOBILE_STATE_ISP_CALLING, + C_LINK_MOBILE_STATE_PPP_LOGIN, + C_LINK_MOBILE_STATE_PPP_ACTIVE, + C_LINK_MOBILE_STATE_SHUTDOWN_REQUESTED, + C_LINK_MOBILE_STATE_ENDING_SESSION, + C_LINK_MOBILE_STATE_WAITING_8BIT_SWITCH, + C_LINK_MOBILE_STATE_SHUTDOWN +} C_LinkMobile_State; + +typedef enum { + C_LINK_MOBILE_ROLE_NO_P2P_CONNECTION, + C_LINK_MOBILE_ROLE_CALLER, + C_LINK_MOBILE_ROLE_RECEIVER +} C_LinkMobile_Role; + +typedef enum { + C_LINK_MOBILE_CONNECTION_TYPE_TCP, + C_LINK_MOBILE_CONNECTION_TYPE_UDP +} C_LinkMobileConnectionType; + +typedef struct { + volatile bool completed; + bool success; + u8 data[254]; + u8 size; +} C_LinkMobileDataTransfer; + +typedef struct { + volatile bool completed; + bool success; + u8 ipv4[4]; +} C_LinkMobileDNSQuery; + +typedef struct { + volatile bool completed; + bool success; + u8 connectionId; +} C_LinkMobileOpenConn; + +typedef struct { + volatile bool completed; + bool success; +} C_LinkMobileCloseConn; + +C_LinkMobileHandle C_LinkMobile_create(u32 timeout, u8 timerId); +void C_LinkMobile_destroy(C_LinkMobileHandle handle); + +bool C_LinkMobile_isActive(C_LinkMobileHandle handle); +void C_LinkMobile_activate(C_LinkMobileHandle handle); +void C_LinkMobile_deactivate(C_LinkMobileHandle handle); +bool C_LinkMobile_shutdown(C_LinkMobileHandle handle); + +bool C_LinkMobile_call(C_LinkMobileHandle handle, const char* phoneNumber); +bool C_LinkMobile_callISP(C_LinkMobileHandle handle, + const char* password, + const char* loginId); + +bool C_LinkMobile_dnsQuery(C_LinkMobileHandle handle, + const char* domainName, + C_LinkMobileDNSQuery* result); +bool C_LinkMobile_openConnection(C_LinkMobileHandle handle, + const u8* ip, + u16 port, + C_LinkMobileConnectionType type, + C_LinkMobileOpenConn* result); +bool C_LinkMobile_closeConnection(C_LinkMobileHandle handle, + u8 connectionId, + C_LinkMobileConnectionType type, + C_LinkMobileCloseConn* result); + +bool C_LinkMobile_transfer(C_LinkMobileHandle handle, + C_LinkMobileDataTransfer dataToSend, + C_LinkMobileDataTransfer* result, + u8 connectionId); +bool C_LinkMobile_waitFor(C_LinkMobileHandle handle, void* asyncRequest); +bool C_LinkMobile_hangUp(C_LinkMobileHandle handle); + +C_LinkMobile_State C_LinkMobile_getState(C_LinkMobileHandle handle); +C_LinkMobile_Role C_LinkMobile_getRole(C_LinkMobileHandle handle); + +void C_LinkMobile_onVBlank(C_LinkMobileHandle handle); +void C_LinkMobile_onSerial(C_LinkMobileHandle handle); +void C_LinkMobile_onTimer(C_LinkMobileHandle handle); + +extern C_LinkMobileHandle cLinkMobile; + +inline void C_LINK_MOBILE_ISR_VBLANK() { + C_LinkMobile_onVBlank(cLinkMobile); +} + +inline void C_LINK_MOBILE_ISR_SERIAL() { + C_LinkMobile_onSerial(cLinkMobile); +} + +inline void C_LINK_MOBILE_ISR_TIMER() { + C_LinkMobile_onTimer(cLinkMobile); +} + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_MOBILE_H diff --git a/lib/c_bindings/C_LinkPS2Keyboard.cpp b/lib/c_bindings/C_LinkPS2Keyboard.cpp new file mode 100644 index 0000000..b164b03 --- /dev/null +++ b/lib/c_bindings/C_LinkPS2Keyboard.cpp @@ -0,0 +1,34 @@ +#include "C_LinkPS2Keyboard.h" +#include "../LinkPS2Keyboard.hpp" + +extern "C" { + +C_LinkPS2KeyboardHandle C_LinkPS2Keyboard_create( + C_LinkPS2Keyboard_EventCallback callback) { + return new LinkPS2Keyboard(callback); +} + +void C_LinkPS2Keyboard_destroy(C_LinkPS2KeyboardHandle handle) { + delete static_cast(handle); +} + +bool C_LinkPS2Keyboard_isActive(C_LinkPS2KeyboardHandle handle) { + return static_cast(handle)->isActive(); +} + +void C_LinkPS2Keyboard_activate(C_LinkPS2KeyboardHandle handle) { + static_cast(handle)->activate(); +} + +void C_LinkPS2Keyboard_deactivate(C_LinkPS2KeyboardHandle handle) { + static_cast(handle)->deactivate(); +} + +void C_LinkPS2Keyboard_onVBlank(C_LinkPS2KeyboardHandle handle) { + static_cast(handle)->_onVBlank(); +} + +void C_LinkPS2Keyboard_onSerial(C_LinkPS2KeyboardHandle handle) { + static_cast(handle)->_onSerial(); +} +} diff --git a/lib/c_bindings/C_LinkPS2Keyboard.h b/lib/c_bindings/C_LinkPS2Keyboard.h new file mode 100644 index 0000000..a9721ec --- /dev/null +++ b/lib/c_bindings/C_LinkPS2Keyboard.h @@ -0,0 +1,39 @@ +#ifndef C_BINDINGS_LINK_PS2_KEYBOARD_H +#define C_BINDINGS_LINK_PS2_KEYBOARD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef void (*C_LinkPS2Keyboard_EventCallback)(u8 event); + +typedef void* C_LinkPS2KeyboardHandle; + +C_LinkPS2KeyboardHandle C_LinkPS2Keyboard_create( + C_LinkPS2Keyboard_EventCallback callback); +void C_LinkPS2Keyboard_destroy(C_LinkPS2KeyboardHandle handle); + +bool C_LinkPS2Keyboard_isActive(C_LinkPS2KeyboardHandle handle); +void C_LinkPS2Keyboard_activate(C_LinkPS2KeyboardHandle handle); +void C_LinkPS2Keyboard_deactivate(C_LinkPS2KeyboardHandle handle); + +void C_LinkPS2Keyboard_onVBlank(C_LinkPS2KeyboardHandle handle); +void C_LinkPS2Keyboard_onSerial(C_LinkPS2KeyboardHandle handle); + +extern C_LinkPS2KeyboardHandle cLinkPS2Keyboard; + +inline void C_LINK_PS2_KEYBOARD_ISR_VBLANK() { + C_LinkPS2Keyboard_onVBlank(cLinkPS2Keyboard); +} + +inline void C_LINK_PS2_KEYBOARD_ISR_SERIAL() { + C_LinkPS2Keyboard_onSerial(cLinkPS2Keyboard); +} + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_PS2_KEYBOARD_H diff --git a/lib/c_bindings/C_LinkPS2Mouse.cpp b/lib/c_bindings/C_LinkPS2Mouse.cpp new file mode 100644 index 0000000..557e16e --- /dev/null +++ b/lib/c_bindings/C_LinkPS2Mouse.cpp @@ -0,0 +1,33 @@ +#include "C_LinkPS2Mouse.h" +#include "../LinkPS2Mouse.hpp" + +extern "C" { + +C_LinkPS2MouseHandle C_LinkPS2Mouse_create(u8 waitTimerId) { + return new LinkPS2Mouse(waitTimerId); +} + +void C_LinkPS2Mouse_destroy(C_LinkPS2MouseHandle handle) { + delete static_cast(handle); +} + +bool C_LinkPS2Mouse_isActive(C_LinkPS2MouseHandle handle) { + return static_cast(handle)->isActive(); +} + +void C_LinkPS2Mouse_activate(C_LinkPS2MouseHandle handle) { + static_cast(handle)->activate(); +} + +void C_LinkPS2Mouse_deactivate(C_LinkPS2MouseHandle handle) { + static_cast(handle)->deactivate(); +} + +void C_LinkPS2Mouse_report(C_LinkPS2MouseHandle handle, int data[3]) { + int d[3]; + static_cast(handle)->report(d); + for (u32 i = 0; i < 3; i++) { + data[i] = d[i]; + } +} +} diff --git a/lib/c_bindings/C_LinkPS2Mouse.h b/lib/c_bindings/C_LinkPS2Mouse.h new file mode 100644 index 0000000..876fccc --- /dev/null +++ b/lib/c_bindings/C_LinkPS2Mouse.h @@ -0,0 +1,31 @@ +#ifndef C_BINDINGS_LINK_PS2_MOUSE_H +#define C_BINDINGS_LINK_PS2_MOUSE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef void* C_LinkPS2MouseHandle; + +#define C_LINK_PS2_MOUSE_LEFT_CLICK 0b001 +#define C_LINK_PS2_MOUSE_RIGHT_CLICK 0b010 +#define C_LINK_PS2_MOUSE_MIDDLE_CLICK 0b100 + +C_LinkPS2MouseHandle C_LinkPS2Mouse_create(u8 waitTimerId); +void C_LinkPS2Mouse_destroy(C_LinkPS2MouseHandle handle); + +bool C_LinkPS2Mouse_isActive(C_LinkPS2MouseHandle handle); +void C_LinkPS2Mouse_activate(C_LinkPS2MouseHandle handle); +void C_LinkPS2Mouse_deactivate(C_LinkPS2MouseHandle handle); + +void C_LinkPS2Mouse_report(C_LinkPS2MouseHandle handle, int data[3]); + +extern C_LinkPS2MouseHandle cLinkPS2Mouse; + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_PS2_MOUSE_H diff --git a/lib/c_bindings/C_LinkRawCable.cpp b/lib/c_bindings/C_LinkRawCable.cpp new file mode 100644 index 0000000..f9ca9b5 --- /dev/null +++ b/lib/c_bindings/C_LinkRawCable.cpp @@ -0,0 +1,85 @@ +#include "C_LinkRawCable.h" +#include +#include "../LinkRawCable.hpp" + +extern "C" { + +C_LinkRawCableHandle C_LinkRawCable_create() { + return new LinkRawCable(); +} + +void C_LinkRawCable_destroy(C_LinkRawCableHandle handle) { + delete static_cast(handle); +} + +bool C_LinkRawCable_isActive(C_LinkRawCableHandle handle) { + return static_cast(handle)->isActive(); +} + +void C_LinkRawCable_activate(C_LinkRawCableHandle handle, + C_LinkRawCable_BaudRate baudRate) { + static_cast(handle)->activate( + static_cast(baudRate)); +} + +void C_LinkRawCable_deactivate(C_LinkRawCableHandle handle) { + static_cast(handle)->deactivate(); +} + +C_LinkRawCable_Response C_LinkRawCable_transfer(C_LinkRawCableHandle handle, + u16 data) { + auto response = static_cast(handle)->transfer(data); + C_LinkRawCable_Response cResponse; + memcpy(cResponse.data, response.data, sizeof(response.data)); + cResponse.playerId = response.playerId; + return cResponse; +} + +C_LinkRawCable_Response C_LinkRawCable_transferWithCancel( + C_LinkRawCableHandle handle, + u16 data, + bool (*cancel)()) { + auto response = static_cast(handle)->transfer(data, cancel); + C_LinkRawCable_Response cResponse; + memcpy(cResponse.data, response.data, sizeof(response.data)); + cResponse.playerId = response.playerId; + return cResponse; +} + +void C_LinkRawCable_transferAsync(C_LinkRawCableHandle handle, u16 data) { + static_cast(handle)->transferAsync(data); +} + +C_LinkRawCable_AsyncState C_LinkRawCable_getAsyncState( + C_LinkRawCableHandle handle) { + return static_cast( + static_cast(handle)->getAsyncState()); +} + +C_LinkRawCable_Response C_LinkRawCable_getAsyncData( + C_LinkRawCableHandle handle) { + auto response = static_cast(handle)->getAsyncData(); + C_LinkRawCable_Response cResponse; + memcpy(cResponse.data, response.data, sizeof(response.data)); + cResponse.playerId = response.playerId; + return cResponse; +} + +C_LinkRawCable_BaudRate C_LinkRawCable_getBaudRate( + C_LinkRawCableHandle handle) { + return static_cast( + static_cast(handle)->getBaudRate()); +} + +bool C_LinkRawCable_isMaster(C_LinkRawCableHandle handle) { + return static_cast(handle)->isMaster(); +} + +bool C_LinkRawCable_isReady(C_LinkRawCableHandle handle) { + return static_cast(handle)->isReady(); +} + +void C_LinkRawCable_onSerial(C_LinkRawCableHandle handle) { + static_cast(handle)->_onSerial(); +} +} diff --git a/lib/c_bindings/C_LinkRawCable.h b/lib/c_bindings/C_LinkRawCable.h new file mode 100644 index 0000000..ac81124 --- /dev/null +++ b/lib/c_bindings/C_LinkRawCable.h @@ -0,0 +1,69 @@ +#ifndef C_BINDINGS_LINK_RAW_CABLE_H +#define C_BINDINGS_LINK_RAW_CABLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef void* C_LinkRawCableHandle; + +#define C_LINK_RAW_CABLE_MAX_PLAYERS 4 +#define C_LINK_RAW_CABLE_DISCONNECTED 0xffff + +typedef enum { + C_BAUD_RATE_0, // 9600 bps + C_BAUD_RATE_1, // 38400 bps + C_BAUD_RATE_2, // 57600 bps + C_BAUD_RATE_3 // 115200 bps +} C_LinkRawCable_BaudRate; + +typedef enum { + C_ASYNC_STATE_IDLE, + C_ASYNC_STATE_WAITING, + C_ASYNC_STATE_READY +} C_LinkRawCable_AsyncState; + +typedef struct { + u16 data[4]; + int playerId; +} C_LinkRawCable_Response; + +C_LinkRawCableHandle C_LinkRawCable_create(); +void C_LinkRawCable_destroy(C_LinkRawCableHandle handle); + +bool C_LinkRawCable_isActive(C_LinkRawCableHandle handle); +void C_LinkRawCable_activate(C_LinkRawCableHandle handle, + C_LinkRawCable_BaudRate baudRate); +void C_LinkRawCable_deactivate(C_LinkRawCableHandle handle); + +C_LinkRawCable_Response C_LinkRawCable_transfer(C_LinkRawCableHandle handle, + u16 data); +C_LinkRawCable_Response C_LinkRawCable_transferWithCancel( + C_LinkRawCableHandle handle, + u16 data, + bool (*cancel)()); +void C_LinkRawCable_transferAsync(C_LinkRawCableHandle handle, u16 data); + +C_LinkRawCable_AsyncState C_LinkRawCable_getAsyncState( + C_LinkRawCableHandle handle); +C_LinkRawCable_Response C_LinkRawCable_getAsyncData( + C_LinkRawCableHandle handle); +C_LinkRawCable_BaudRate C_LinkRawCable_getBaudRate(C_LinkRawCableHandle handle); +bool C_LinkRawCable_isMaster(C_LinkRawCableHandle handle); +bool C_LinkRawCable_isReady(C_LinkRawCableHandle handle); + +void C_LinkRawCable_onSerial(C_LinkRawCableHandle handle); + +extern C_LinkRawCableHandle cLinkRawCable; + +inline void C_LINK_RAW_CABLE_ISR_SERIAL() { + C_LinkRawCable_onSerial(cLinkRawCable); +} + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_RAW_CABLE_H diff --git a/lib/c_bindings/C_LinkRawWireless.cpp b/lib/c_bindings/C_LinkRawWireless.cpp new file mode 100644 index 0000000..8445c6b --- /dev/null +++ b/lib/c_bindings/C_LinkRawWireless.cpp @@ -0,0 +1,227 @@ +#include "C_LinkRawWireless.h" +#include "../LinkRawWireless.hpp" + +extern "C" { +C_LinkRawWirelessHandle C_LinkRawWireless_create(void) { + return new LinkRawWireless(); +} + +void C_LinkRawWireless_destroy(C_LinkRawWirelessHandle handle) { + delete static_cast(handle); +} + +bool C_LinkRawWireless_isActive(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->isActive(); +} + +bool C_LinkRawWireless_activate(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->activate(); +} + +bool C_LinkRawWireless_deactivate(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->deactivate(); +} + +bool C_LinkRawWireless_setup(C_LinkRawWirelessHandle handle, + u8 maxPlayers, + u8 maxTransmissions, + u8 waitTimeout, + u32 magic) { + return static_cast(handle)->setup( + maxPlayers, maxTransmissions, waitTimeout, magic); +} + +bool C_LinkRawWireless_broadcast(C_LinkRawWirelessHandle handle, + const char* gameName, + const char* userName, + u16 gameId) { + return static_cast(handle)->broadcast(gameName, userName, + gameId); +} + +bool C_LinkRawWireless_startHost(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->startHost(); +} + +bool C_LinkRawWireless_getSlotStatus( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_SlotStatusResponse* response) { + LinkRawWireless::SlotStatusResponse nativeResponse; + bool success = + static_cast(handle)->getSlotStatus(nativeResponse); + response->nextClientNumber = nativeResponse.nextClientNumber; + response->connectedClientsSize = nativeResponse.connectedClientsSize; + for (u32 i = 0; i < response->connectedClientsSize; i++) { + response->connectedClients[i].deviceId = + nativeResponse.connectedClients[i].deviceId; + response->connectedClients[i].clientNumber = + nativeResponse.connectedClients[i].clientNumber; + } + return success; +} + +bool C_LinkRawWireless_acceptConnections( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_AcceptConnectionsResponse* response) { + LinkRawWireless::AcceptConnectionsResponse nativeResponse; + bool success = + static_cast(handle)->acceptConnections(nativeResponse); + response->connectedClientsSize = nativeResponse.connectedClientsSize; + for (u32 i = 0; i < response->connectedClientsSize; i++) { + response->connectedClients[i].deviceId = + nativeResponse.connectedClients[i].deviceId; + response->connectedClients[i].clientNumber = + nativeResponse.connectedClients[i].clientNumber; + } + return success; +} + +bool C_LinkRawWireless_endHost( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_AcceptConnectionsResponse* response) { + LinkRawWireless::AcceptConnectionsResponse nativeResponse; + bool success = static_cast(handle)->endHost(nativeResponse); + response->connectedClientsSize = nativeResponse.connectedClientsSize; + for (u32 i = 0; i < response->connectedClientsSize; i++) { + response->connectedClients[i].deviceId = + nativeResponse.connectedClients[i].deviceId; + response->connectedClients[i].clientNumber = + nativeResponse.connectedClients[i].clientNumber; + } + return success; +} + +bool C_LinkRawWireless_broadcastReadStart(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->broadcastReadStart(); +} + +bool C_LinkRawWireless_broadcastReadPoll( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_BroadcastReadPollResponse* response) { + LinkRawWireless::BroadcastReadPollResponse nativeResponse; + bool success = + static_cast(handle)->broadcastReadPoll(nativeResponse); + response->serversSize = nativeResponse.serversSize; + for (u32 i = 0; i < response->serversSize; i++) { + response->servers[i].id = nativeResponse.servers[i].id; + response->servers[i].gameId = nativeResponse.servers[i].gameId; + std::memcpy(response->servers[i].gameName, + nativeResponse.servers[i].gameName, + LINK_RAW_WIRELESS_MAX_GAME_NAME_LENGTH + 1); + std::memcpy(response->servers[i].userName, + nativeResponse.servers[i].userName, + LINK_RAW_WIRELESS_MAX_USER_NAME_LENGTH + 1); + response->servers[i].nextClientNumber = + nativeResponse.servers[i].nextClientNumber; + } + return success; +} + +bool C_LinkRawWireless_broadcastReadEnd(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->broadcastReadEnd(); +} + +bool C_LinkRawWireless_connect(C_LinkRawWirelessHandle handle, u16 serverId) { + return static_cast(handle)->connect(serverId); +} + +bool C_LinkRawWireless_keepConnecting( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_ConnectionStatus* response) { + LinkRawWireless::ConnectionStatus nativeResponse; + bool success = + static_cast(handle)->keepConnecting(nativeResponse); + response->phase = + static_cast(nativeResponse.phase); + response->assignedClientNumber = nativeResponse.assignedClientNumber; + return success; +} + +bool C_LinkRawWireless_finishConnection(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->finishConnection(); +} + +bool C_LinkRawWireless_sendData(C_LinkRawWirelessHandle handle, + u32* data, + u32 dataSize, + u32 _bytes) { + std::array dataArray; + std::memcpy(dataArray.data(), data, dataSize * sizeof(u32)); + return static_cast(handle)->sendData(dataArray, dataSize, + _bytes); +} + +bool C_LinkRawWireless_sendDataAndWait( + C_LinkRawWirelessHandle handle, + u32* data, + u32 dataSize, + C_LinkRawWireless_RemoteCommand* remoteCommand, + u32 _bytes) { + std::array dataArray; + LinkRawWireless::RemoteCommand nativeRemoteCommand; + std::memcpy(dataArray.data(), data, dataSize * sizeof(u32)); + bool success = static_cast(handle)->sendDataAndWait( + dataArray, dataSize, nativeRemoteCommand, _bytes); + remoteCommand->success = nativeRemoteCommand.success; + remoteCommand->commandId = nativeRemoteCommand.commandId; + remoteCommand->paramsSize = nativeRemoteCommand.paramsSize; + std::memcpy(remoteCommand->params, nativeRemoteCommand.params, + LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH * sizeof(u32)); + return success; +} + +bool C_LinkRawWireless_receiveData( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_ReceiveDataResponse* response) { + LinkRawWireless::ReceiveDataResponse nativeResponse; + bool success = + static_cast(handle)->receiveData(nativeResponse); + for (u32 i = 0; i < nativeResponse.dataSize; i++) { + response->data[i] = nativeResponse.data[i]; + } + response->dataSize = nativeResponse.dataSize; + for (u32 i = 0; i < LINK_RAW_WIRELESS_MAX_PLAYERS; i++) { + response->sentBytes[i] = nativeResponse.sentBytes[i]; + } + return success; +} + +bool C_LinkRawWireless_wait(C_LinkRawWirelessHandle handle, + C_LinkRawWireless_RemoteCommand* remoteCommand) { + LinkRawWireless::RemoteCommand nativeRemoteCommand; + bool success = + static_cast(handle)->wait(nativeRemoteCommand); + remoteCommand->success = nativeRemoteCommand.success; + remoteCommand->commandId = nativeRemoteCommand.commandId; + remoteCommand->paramsSize = nativeRemoteCommand.paramsSize; + std::memcpy(remoteCommand->params, nativeRemoteCommand.params, + LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH * sizeof(u32)); + return success; +} + +C_LinkRawWireless_State C_LinkRawWireless_getState( + C_LinkRawWirelessHandle handle) { + return static_cast( + static_cast(handle)->getState()); +} + +u32 C_LinkRawWireless_getDeviceTransferLength(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->getDeviceTransferLength(); +} + +bool C_LinkRawWireless_isConnected(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->isConnected(); +} + +bool C_LinkRawWireless_isSessionActive(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->isSessionActive(); +} + +u8 C_LinkRawWireless_playerCount(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->playerCount(); +} + +u8 C_LinkRawWireless_currentPlayerId(C_LinkRawWirelessHandle handle) { + return static_cast(handle)->currentPlayerId(); +} +} diff --git a/lib/c_bindings/C_LinkRawWireless.h b/lib/c_bindings/C_LinkRawWireless.h new file mode 100644 index 0000000..6dfa0c2 --- /dev/null +++ b/lib/c_bindings/C_LinkRawWireless.h @@ -0,0 +1,158 @@ +#ifndef C_BINDINGS_LINK_RAW_WIRELESS_H +#define C_BINDINGS_LINK_RAW_WIRELESS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define C_LINK_RAW_WIRELESS_MAX_PLAYERS 5 +#define C_LINK_RAW_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH 30 +#define C_LINK_RAW_WIRELESS_MAX_CLIENT_TRANSFER_LENGTH 4 +#define C_LINK_RAW_WIRELESS_MAX_GAME_ID 0x7fff +#define C_LINK_RAW_WIRELESS_MAX_GAME_NAME_LENGTH 14 +#define C_LINK_RAW_WIRELESS_MAX_USER_NAME_LENGTH 8 +#define C_LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH 23 + +#define C_LINK_RAW_WIRELESS_MAX_SERVERS 4 + +typedef enum { + C_LINK_RAW_WIRELESS_STATE_NEEDS_RESET, + C_LINK_RAW_WIRELESS_STATE_AUTHENTICATED, + C_LINK_RAW_WIRELESS_STATE_SEARCHING, + C_LINK_RAW_WIRELESS_STATE_SERVING, + C_LINK_RAW_WIRELESS_STATE_CONNECTING, + C_LINK_RAW_WIRELESS_STATE_CONNECTED +} C_LinkRawWireless_State; + +typedef enum { + C_LINK_RAW_WIRELESS_CONNECTION_PHASE_STILL_CONNECTING, + C_LINK_RAW_WIRELESS_CONNECTION_PHASE_ERROR, + C_LINK_RAW_WIRELESS_CONNECTION_PHASE_SUCCESS +} C_LinkRawWireless_ConnectionPhase; + +typedef struct { + bool success; + u32 responses[C_LINK_RAW_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH]; + u32 responsesSize; +} C_LinkRawWireless_CommandResult; + +typedef struct { + bool success; + u8 commandId; + u32 params[C_LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH]; + u32 paramsSize; +} C_LinkRawWireless_RemoteCommand; + +typedef struct { + u16 deviceId; + u8 clientNumber; +} C_LinkRawWireless_ConnectedClient; + +typedef struct { + u8 nextClientNumber; + C_LinkRawWireless_ConnectedClient + connectedClients[C_LINK_RAW_WIRELESS_MAX_PLAYERS]; + u32 connectedClientsSize; +} C_LinkRawWireless_SlotStatusResponse; + +typedef struct { + C_LinkRawWireless_ConnectedClient + connectedClients[C_LINK_RAW_WIRELESS_MAX_PLAYERS]; + u32 connectedClientsSize; +} C_LinkRawWireless_AcceptConnectionsResponse; + +typedef struct { + u16 id; + u16 gameId; + char gameName[C_LINK_RAW_WIRELESS_MAX_GAME_NAME_LENGTH + 1]; + char userName[C_LINK_RAW_WIRELESS_MAX_USER_NAME_LENGTH + 1]; + u8 nextClientNumber; +} C_LinkRawWirelessServer; + +typedef struct { + C_LinkRawWirelessServer servers[C_LINK_RAW_WIRELESS_MAX_SERVERS]; + u32 serversSize; +} C_LinkRawWireless_BroadcastReadPollResponse; + +typedef struct { + C_LinkRawWireless_ConnectionPhase phase; + u8 assignedClientNumber; +} C_LinkRawWireless_ConnectionStatus; + +typedef struct { + u32 sentBytes[C_LINK_RAW_WIRELESS_MAX_PLAYERS]; + u32 data[C_LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH]; + u32 dataSize; +} C_LinkRawWireless_ReceiveDataResponse; + +typedef void* C_LinkRawWirelessHandle; + +C_LinkRawWirelessHandle C_LinkRawWireless_create(void); +void C_LinkRawWireless_destroy(C_LinkRawWirelessHandle handle); + +bool C_LinkRawWireless_isActive(C_LinkRawWirelessHandle handle); +bool C_LinkRawWireless_activate(C_LinkRawWirelessHandle handle); +bool C_LinkRawWireless_deactivate(C_LinkRawWirelessHandle handle); + +bool C_LinkRawWireless_setup(C_LinkRawWirelessHandle handle, + u8 maxPlayers, + u8 maxTransmissions, + u8 waitTimeout, + u32 magic); +bool C_LinkRawWireless_broadcast(C_LinkRawWirelessHandle handle, + const char* gameName, + const char* userName, + u16 gameId); +bool C_LinkRawWireless_startHost(C_LinkRawWirelessHandle handle); +bool C_LinkRawWireless_getSlotStatus( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_SlotStatusResponse* response); +bool C_LinkRawWireless_acceptConnections( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_AcceptConnectionsResponse* response); +bool C_LinkRawWireless_endHost( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_AcceptConnectionsResponse* response); +bool C_LinkRawWireless_broadcastReadStart(C_LinkRawWirelessHandle handle); +bool C_LinkRawWireless_broadcastReadPoll( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_BroadcastReadPollResponse* response); +bool C_LinkRawWireless_broadcastReadEnd(C_LinkRawWirelessHandle handle); +bool C_LinkRawWireless_connect(C_LinkRawWirelessHandle handle, u16 serverId); +bool C_LinkRawWireless_keepConnecting( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_ConnectionStatus* response); +bool C_LinkRawWireless_finishConnection(C_LinkRawWirelessHandle handle); +bool C_LinkRawWireless_sendData(C_LinkRawWirelessHandle handle, + u32* data, + u32 dataSize, + u32 _bytes); +bool C_LinkRawWireless_sendDataAndWait( + C_LinkRawWirelessHandle handle, + u32* data, + u32 dataSize, + C_LinkRawWireless_RemoteCommand* remoteCommand, + u32 _bytes); +bool C_LinkRawWireless_receiveData( + C_LinkRawWirelessHandle handle, + C_LinkRawWireless_ReceiveDataResponse* response); +bool C_LinkRawWireless_wait(C_LinkRawWirelessHandle handle, + C_LinkRawWireless_RemoteCommand* remoteCommand); + +C_LinkRawWireless_State C_LinkRawWireless_getState( + C_LinkRawWirelessHandle handle); +u32 C_LinkRawWireless_getDeviceTransferLength(C_LinkRawWirelessHandle handle); +bool C_LinkRawWireless_isConnected(C_LinkRawWirelessHandle handle); +bool C_LinkRawWireless_isSessionActive(C_LinkRawWirelessHandle handle); +u8 C_LinkRawWireless_playerCount(C_LinkRawWirelessHandle handle); +u8 C_LinkRawWireless_currentPlayerId(C_LinkRawWirelessHandle handle); + +extern C_LinkRawWirelessHandle cRawWireless; + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_RAW_WIRELESS_H diff --git a/lib/c_bindings/C_LinkSPI.cpp b/lib/c_bindings/C_LinkSPI.cpp new file mode 100644 index 0000000..aa7ddf2 --- /dev/null +++ b/lib/c_bindings/C_LinkSPI.cpp @@ -0,0 +1,79 @@ +#include "C_LinkSPI.h" +#include "../LinkSPI.hpp" + +extern "C" { + +C_LinkSPIHandle C_LinkSPI_create() { + return new LinkSPI(); +} + +void C_LinkSPI_destroy(C_LinkSPIHandle handle) { + delete static_cast(handle); +} + +bool C_LinkSPI_isActive(C_LinkSPIHandle handle) { + return static_cast(handle)->isActive(); +} + +void C_LinkSPI_activate(C_LinkSPIHandle handle, + C_LinkSPI_Mode mode, + C_LinkSPI_DataSize dataSize) { + static_cast(handle)->activate( + static_cast(mode), + static_cast(dataSize)); +} + +void C_LinkSPI_deactivate(C_LinkSPIHandle handle) { + static_cast(handle)->deactivate(); +} + +u32 C_LinkSPI_transfer(C_LinkSPIHandle handle, u32 data) { + return static_cast(handle)->transfer(data); +} + +u32 C_LinkSPI_transferWithCancel(C_LinkSPIHandle handle, + u32 data, + bool (*cancel)()) { + return static_cast(handle)->transfer(data, cancel); +} + +void C_LinkSPI_transferAsync(C_LinkSPIHandle handle, u32 data) { + static_cast(handle)->transferAsync(data); +} + +void C_LinkSPI_transferAsyncWithCancel(C_LinkSPIHandle handle, + u32 data, + bool (*cancel)()) { + static_cast(handle)->transferAsync(data, cancel); +} + +C_LinkSPI_AsyncState C_LinkSPI_getAsyncState(C_LinkSPIHandle handle) { + return static_cast( + static_cast(handle)->getAsyncState()); +} + +u32 C_LinkSPI_getAsyncData(C_LinkSPIHandle handle) { + return static_cast(handle)->getAsyncData(); +} + +C_LinkSPI_Mode C_LinkSPI_getMode(C_LinkSPIHandle handle) { + return static_cast(static_cast(handle)->getMode()); +} + +C_LinkSPI_DataSize C_LinkSPI_getDataSize(C_LinkSPIHandle handle) { + return static_cast( + static_cast(handle)->getDataSize()); +} + +void C_LinkSPI_setWaitModeActive(C_LinkSPIHandle handle, bool isActive) { + static_cast(handle)->setWaitModeActive(isActive); +} + +bool C_LinkSPI_isWaitModeActive(C_LinkSPIHandle handle) { + return static_cast(handle)->isWaitModeActive(); +} + +void C_LinkSPI_onSerial(C_LinkSPIHandle handle, bool customAck) { + static_cast(handle)->_onSerial(customAck); +} +} diff --git a/lib/c_bindings/C_LinkSPI.h b/lib/c_bindings/C_LinkSPI.h new file mode 100644 index 0000000..0b20275 --- /dev/null +++ b/lib/c_bindings/C_LinkSPI.h @@ -0,0 +1,70 @@ +#ifndef C_BINDINGS_LINK_SPI_H +#define C_BINDINGS_LINK_SPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef void* C_LinkSPIHandle; + +#define C_LINK_SPI_NO_DATA_32 0xffffffff +#define C_LINK_SPI_NO_DATA_8 0xff +#define C_LINK_SPI_NO_DATA LINK_SPI_NO_DATA_32 + +typedef enum { + C_MODE_SLAVE, + C_MODE_MASTER_256KBPS, + C_MODE_MASTER_2MBPS +} C_LinkSPI_Mode; + +typedef enum { C_SIZE_32BIT, C_SIZE_8BIT } C_LinkSPI_DataSize; + +typedef enum { + C_ASYNC_STATE_IDLE, + C_ASYNC_STATE_WAITING, + C_ASYNC_STATE_READY +} C_LinkSPI_AsyncState; + +C_LinkSPIHandle C_LinkSPI_create(); +void C_LinkSPI_destroy(C_LinkSPIHandle handle); + +bool C_LinkSPI_isActive(C_LinkSPIHandle handle); +void C_LinkSPI_activate(C_LinkSPIHandle handle, + C_LinkSPI_Mode mode, + C_LinkSPI_DataSize dataSize); +void C_LinkSPI_deactivate(C_LinkSPIHandle handle); + +u32 C_LinkSPI_transfer(C_LinkSPIHandle handle, u32 data); +u32 C_LinkSPI_transferWithCancel(C_LinkSPIHandle handle, + u32 data, + bool (*cancel)()); + +void C_LinkSPI_transferAsync(C_LinkSPIHandle handle, u32 data); +void C_LinkSPI_transferAsyncWithCancel(C_LinkSPIHandle handle, + u32 data, + bool (*cancel)()); + +C_LinkSPI_AsyncState C_LinkSPI_getAsyncState(C_LinkSPIHandle handle); +u32 C_LinkSPI_getAsyncData(C_LinkSPIHandle handle); + +C_LinkSPI_Mode C_LinkSPI_getMode(C_LinkSPIHandle handle); +C_LinkSPI_DataSize C_LinkSPI_getDataSize(C_LinkSPIHandle handle); + +void C_LinkSPI_setWaitModeActive(C_LinkSPIHandle handle, bool isActive); +bool C_LinkSPI_isWaitModeActive(C_LinkSPIHandle handle); + +void C_LinkSPI_onSerial(C_LinkSPIHandle handle, bool customAck); + +extern C_LinkSPIHandle cLinkSPI; + +inline void C_LINK_SPI_ISR_SERIAL() { + C_LinkSPI_onSerial(cLinkSPI, false); +} + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_SPI_H diff --git a/lib/c_bindings/C_LinkUART.cpp b/lib/c_bindings/C_LinkUART.cpp new file mode 100644 index 0000000..492b31f --- /dev/null +++ b/lib/c_bindings/C_LinkUART.cpp @@ -0,0 +1,92 @@ +#include "C_LinkUART.h" +#include "../LinkUART.hpp" + +extern "C" { + +C_LinkUARTHandle C_LinkUART_create() { + return new LinkUART(); +} + +void C_LinkUART_destroy(C_LinkUARTHandle handle) { + delete static_cast(handle); +} + +bool C_LinkUART_isActive(C_LinkUARTHandle handle) { + return static_cast(handle)->isActive(); +} + +void C_LinkUART_activate(C_LinkUARTHandle handle, + C_LinkUART_BaudRate baudRate, + C_LinkUART_DataSize dataSize, + C_LinkUART_Parity parity, + bool useCTS) { + static_cast(handle)->activate( + static_cast(baudRate), + static_cast(dataSize), + static_cast(parity), useCTS); +} + +void C_LinkUART_deactivate(C_LinkUARTHandle handle) { + static_cast(handle)->deactivate(); +} + +void C_LinkUART_sendLine(C_LinkUARTHandle handle, const char* string) { + static_cast(handle)->sendLine(string); +} + +void C_LinkUART_sendLineWithCancel(C_LinkUARTHandle handle, + const char* string, + bool (*cancel)()) { + static_cast(handle)->sendLine(string, cancel); +} + +bool C_LinkUART_readLine(C_LinkUARTHandle handle, char* string, u32 limit) { + return static_cast(handle)->readLine(string, limit); +} + +bool C_LinkUART_readLineWithCancel(C_LinkUARTHandle handle, + char* string, + bool (*cancel)(), + u32 limit) { + return static_cast(handle)->readLine(string, cancel, limit); +} + +void C_LinkUART_send(C_LinkUARTHandle handle, + const u8* buffer, + u32 size, + u32 offset) { + static_cast(handle)->send(buffer, size, offset); +} + +u32 C_LinkUART_read(C_LinkUARTHandle handle, u8* buffer, u32 size, u32 offset) { + return static_cast(handle)->read(buffer, size, offset); +} + +bool C_LinkUART_canRead(C_LinkUARTHandle handle) { + return static_cast(handle)->canRead(); +} + +bool C_LinkUART_canSend(C_LinkUARTHandle handle) { + return static_cast(handle)->canSend(); +} + +u32 C_LinkUART_availableForRead(C_LinkUARTHandle handle) { + return static_cast(handle)->availableForRead(); +} + +u32 C_LinkUART_availableForSend(C_LinkUARTHandle handle) { + return static_cast(handle)->availableForSend(); +} + +u8 C_LinkUART_readByte(C_LinkUARTHandle handle) { + return static_cast(handle)->read(); +} + +void C_LinkUART_sendByte(C_LinkUARTHandle handle, u8 data) { + static_cast(handle)->send(data); +} + +void C_LinkUART_onSerial(C_LinkUARTHandle handle) { + static_cast(handle)->_onSerial(); +} +} diff --git a/lib/c_bindings/C_LinkUART.h b/lib/c_bindings/C_LinkUART.h new file mode 100644 index 0000000..521aec8 --- /dev/null +++ b/lib/c_bindings/C_LinkUART.h @@ -0,0 +1,71 @@ +#ifndef C_BINDINGS_LINK_UART_H +#define C_BINDINGS_LINK_UART_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef void* C_LinkUARTHandle; + +typedef enum { + C_BAUD_RATE_0, // 9600 bps + C_BAUD_RATE_1, // 38400 bps + C_BAUD_RATE_2, // 57600 bps + C_BAUD_RATE_3 // 115200 bps +} C_LinkUART_BaudRate; + +typedef enum { C_SIZE_7_BITS, C_SIZE_8_BITS } C_LinkUART_DataSize; + +typedef enum { C_PARITY_NO, C_PARITY_EVEN, C_PARITY_ODD } C_LinkUART_Parity; + +C_LinkUARTHandle C_LinkUART_create(); +void C_LinkUART_destroy(C_LinkUARTHandle handle); + +bool C_LinkUART_isActive(C_LinkUARTHandle handle); +void C_LinkUART_activate(C_LinkUARTHandle handle, + C_LinkUART_BaudRate baudRate, + C_LinkUART_DataSize dataSize, + C_LinkUART_Parity parity, + bool useCTS); +void C_LinkUART_deactivate(C_LinkUARTHandle handle); + +void C_LinkUART_sendLine(C_LinkUARTHandle handle, const char* string); +void C_LinkUART_sendLineWithCancel(C_LinkUARTHandle handle, + const char* string, + bool (*cancel)()); + +bool C_LinkUART_readLine(C_LinkUARTHandle handle, char* string, u32 limit); +bool C_LinkUART_readLineWithCancel(C_LinkUARTHandle handle, + char* string, + bool (*cancel)(), + u32 limit); + +void C_LinkUART_send(C_LinkUARTHandle handle, + const u8* buffer, + u32 size, + u32 offset); +u32 C_LinkUART_read(C_LinkUARTHandle handle, u8* buffer, u32 size, u32 offset); + +bool C_LinkUART_canRead(C_LinkUARTHandle handle); +bool C_LinkUART_canSend(C_LinkUARTHandle handle); +u32 C_LinkUART_availableForRead(C_LinkUARTHandle handle); +u32 C_LinkUART_availableForSend(C_LinkUARTHandle handle); + +u8 C_LinkUART_readByte(C_LinkUARTHandle handle); +void C_LinkUART_sendByte(C_LinkUARTHandle handle, u8 data); + +void C_LinkUART_onSerial(C_LinkUARTHandle handle); + +extern C_LinkUARTHandle cLinkUART; + +inline void C_LINK_SPI_ISR_SERIAL() { + C_LinkUART_onSerial(cLinkUART); +} + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_UART_H diff --git a/lib/c_bindings/C_LinkUniversal.cpp b/lib/c_bindings/C_LinkUniversal.cpp new file mode 100644 index 0000000..1863839 --- /dev/null +++ b/lib/c_bindings/C_LinkUniversal.cpp @@ -0,0 +1,125 @@ +#include "C_LinkUniversal.h" +#include "../LinkUniversal.hpp" + +extern "C" { + +C_LinkUniversalHandle C_LinkUniversal_create( + C_LinkUniversal_Protocol protocol, + const char* gameName, + C_LinkUniversal_CableOptions cableOptions, + C_LinkUniversal_WirelessOptions wirelessOptions, + int randomSeed) { + return new LinkUniversal( + static_cast(protocol), gameName, + {static_cast(cableOptions.baudRate), + cableOptions.timeout, cableOptions.interval, cableOptions.sendTimerId}, + {wirelessOptions.retransmission, wirelessOptions.maxPlayers, + wirelessOptions.timeout, wirelessOptions.interval, + wirelessOptions.sendTimerId, wirelessOptions.asyncACKTimerId}, + randomSeed); +} + +void C_LinkUniversal_destroy(C_LinkUniversalHandle handle) { + delete static_cast(handle); +} + +bool C_LinkUniversal_isActive(C_LinkUniversalHandle handle) { + return static_cast(handle)->isActive(); +} + +void C_LinkUniversal_activate(C_LinkUniversalHandle handle) { + static_cast(handle)->activate(); +} + +void C_LinkUniversal_deactivate(C_LinkUniversalHandle handle) { + static_cast(handle)->deactivate(); +} + +bool C_LinkUniversal_isConnected(C_LinkUniversalHandle handle) { + return static_cast(handle)->isConnected(); +} + +uint8_t C_LinkUniversal_playerCount(C_LinkUniversalHandle handle) { + return static_cast(handle)->playerCount(); +} + +uint8_t C_LinkUniversal_currentPlayerId(C_LinkUniversalHandle handle) { + return static_cast(handle)->currentPlayerId(); +} + +void C_LinkUniversal_sync(C_LinkUniversalHandle handle) { + static_cast(handle)->sync(); +} + +bool C_LinkUniversal_waitFor(C_LinkUniversalHandle handle, uint8_t playerId) { + return static_cast(handle)->waitFor(playerId); +} + +bool C_LinkUniversal_waitForWithCancel(C_LinkUniversalHandle handle, + uint8_t playerId, + bool (*cancel)()) { + return static_cast(handle)->waitFor(playerId, cancel); +} + +bool C_LinkUniversal_canRead(C_LinkUniversalHandle handle, uint8_t playerId) { + return static_cast(handle)->canRead(playerId); +} + +uint16_t C_LinkUniversal_read(C_LinkUniversalHandle handle, uint8_t playerId) { + return static_cast(handle)->read(playerId); +} + +uint16_t C_LinkUniversal_peek(C_LinkUniversalHandle handle, uint8_t playerId) { + return static_cast(handle)->peek(playerId); +} + +bool C_LinkUniversal_send(C_LinkUniversalHandle handle, uint16_t data) { + return static_cast(handle)->send(data); +} + +C_LinkUniversal_State C_LinkUniversal_getState(C_LinkUniversalHandle handle) { + return static_cast( + static_cast(handle)->getState()); +} + +C_LinkUniversal_Mode C_LinkUniversal_getMode(C_LinkUniversalHandle handle) { + return static_cast( + static_cast(handle)->getMode()); +} + +C_LinkUniversal_Protocol C_LinkUniversal_getProtocol( + C_LinkUniversalHandle handle) { + return static_cast( + static_cast(handle)->getProtocol()); +} + +void C_LinkUniversal_setProtocol(C_LinkUniversalHandle handle, + C_LinkUniversal_Protocol protocol) { + static_cast(handle)->setProtocol( + static_cast(protocol)); +} + +uint32_t C_LinkUniversal_getWaitCount(C_LinkUniversalHandle handle) { + return static_cast(handle)->_getWaitCount(); +} + +uint32_t C_LinkUniversal_getSubWaitCount(C_LinkUniversalHandle handle) { + return static_cast(handle)->_getSubWaitCount(); +} + +void C_LinkUniversal_onVBlank(C_LinkUniversalHandle handle) { + static_cast(handle)->_onVBlank(); +} + +void C_LinkUniversal_onSerial(C_LinkUniversalHandle handle) { + static_cast(handle)->_onSerial(); +} + +void C_LinkUniversal_onTimer(C_LinkUniversalHandle handle) { + static_cast(handle)->_onTimer(); +} + +void C_LinkUniversal_onACKTimer(C_LinkUniversalHandle handle) { + static_cast(handle)->_onACKTimer(); +} +} diff --git a/lib/c_bindings/C_LinkUniversal.h b/lib/c_bindings/C_LinkUniversal.h new file mode 100644 index 0000000..c95be34 --- /dev/null +++ b/lib/c_bindings/C_LinkUniversal.h @@ -0,0 +1,112 @@ +#ifndef C_BINDINGS_LINK_UNIVERSAL_H +#define C_BINDINGS_LINK_UNIVERSAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef void* C_LinkUniversalHandle; + +#define C_LINK_UNIVERSAL_DISCONNECTED 0xffff +#define C_LINK_UNIVERSAL_NO_DATA 0x0 + +typedef enum { + C_STATE_INITIALIZING, + C_STATE_WAITING, + C_STATE_CONNECTED +} C_LinkUniversal_State; + +typedef enum { C_MODE_LINK_CABLE, C_MODE_LINK_WIRELESS } C_LinkUniversal_Mode; + +typedef enum { + C_PROTOCOL_AUTODETECT, + C_PROTOCOL_CABLE, + C_PROTOCOL_WIRELESS_AUTO, + C_PROTOCOL_WIRELESS_SERVER, + C_PROTOCOL_WIRELESS_CLIENT +} C_LinkUniversal_Protocol; + +typedef struct { + uint32_t baudRate; + uint32_t timeout; + uint16_t interval; + uint8_t sendTimerId; +} C_LinkUniversal_CableOptions; + +typedef struct { + bool retransmission; + uint32_t maxPlayers; + uint32_t timeout; + uint16_t interval; + uint8_t sendTimerId; + int8_t asyncACKTimerId; +} C_LinkUniversal_WirelessOptions; + +C_LinkUniversalHandle C_LinkUniversal_create( + C_LinkUniversal_Protocol protocol, + const char* gameName, + C_LinkUniversal_CableOptions cableOptions, + C_LinkUniversal_WirelessOptions wirelessOptions, + int randomSeed); +void C_LinkUniversal_destroy(C_LinkUniversalHandle handle); + +bool C_LinkUniversal_isActive(C_LinkUniversalHandle handle); +void C_LinkUniversal_activate(C_LinkUniversalHandle handle); +void C_LinkUniversal_deactivate(C_LinkUniversalHandle handle); + +bool C_LinkUniversal_isConnected(C_LinkUniversalHandle handle); +uint8_t C_LinkUniversal_playerCount(C_LinkUniversalHandle handle); +uint8_t C_LinkUniversal_currentPlayerId(C_LinkUniversalHandle handle); +void C_LinkUniversal_sync(C_LinkUniversalHandle handle); + +bool C_LinkUniversal_waitFor(C_LinkUniversalHandle handle, uint8_t playerId); +bool C_LinkUniversal_waitForWithCancel(C_LinkUniversalHandle handle, + uint8_t playerId, + bool (*cancel)()); +bool C_LinkUniversal_canRead(C_LinkUniversalHandle handle, uint8_t playerId); +uint16_t C_LinkUniversal_read(C_LinkUniversalHandle handle, uint8_t playerId); +uint16_t C_LinkUniversal_peek(C_LinkUniversalHandle handle, uint8_t playerId); + +bool C_LinkUniversal_send(C_LinkUniversalHandle handle, uint16_t data); +C_LinkUniversal_State C_LinkUniversal_getState(C_LinkUniversalHandle handle); +C_LinkUniversal_Mode C_LinkUniversal_getMode(C_LinkUniversalHandle handle); +C_LinkUniversal_Protocol C_LinkUniversal_getProtocol( + C_LinkUniversalHandle handle); + +void C_LinkUniversal_setProtocol(C_LinkUniversalHandle handle, + C_LinkUniversal_Protocol protocol); + +uint32_t C_LinkUniversal_getWaitCount(C_LinkUniversalHandle handle); +uint32_t C_LinkUniversal_getSubWaitCount(C_LinkUniversalHandle handle); + +void C_LinkUniversal_onVBlank(C_LinkUniversalHandle handle); +void C_LinkUniversal_onSerial(C_LinkUniversalHandle handle); +void C_LinkUniversal_onTimer(C_LinkUniversalHandle handle); +void C_LinkUniversal_onACKTimer(C_LinkUniversalHandle handle); + +extern C_LinkUniversalHandle cLinkUniversal; + +inline void C_LINK_UNIVERSAL_ISR_VBLANK() { + C_LinkUniversal_onVBlank(cLinkUniversal); +} + +inline void C_LINK_UNIVERSAL_ISR_SERIAL() { + C_LinkUniversal_onSerial(cLinkUniversal); +} + +inline void C_LINK_UNIVERSAL_ISR_TIMER() { + C_LinkUniversal_onTimer(cLinkUniversal); +} + +inline void C_LINK_UNIVERSAL_ISR_ACK_TIMER() { + C_LinkUniversal_onTimer(cLinkUniversal); +} + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_UNIVERSAL_H diff --git a/lib/c_bindings/C_LinkWireless.cpp b/lib/c_bindings/C_LinkWireless.cpp new file mode 100644 index 0000000..9c7b3c9 --- /dev/null +++ b/lib/c_bindings/C_LinkWireless.cpp @@ -0,0 +1,144 @@ +#include "C_LinkWireless.h" +#include "../LinkWireless.hpp" + +extern "C" { + +C_LinkWirelessHandle C_LinkWireless_create(bool forwarding, + bool retransmission, + u8 maxPlayers, + u32 timeout, + u16 interval, + u8 sendTimerId, + s8 asyncACKTimerId) { + return new LinkWireless(forwarding, retransmission, maxPlayers, timeout, + interval, sendTimerId, asyncACKTimerId); +} + +void C_LinkWireless_destroy(C_LinkWirelessHandle handle) { + delete static_cast(handle); +} + +bool C_LinkWireless_activate(C_LinkWirelessHandle handle) { + return static_cast(handle)->activate(); +} + +bool C_LinkWireless_deactivate(C_LinkWirelessHandle handle) { + return static_cast(handle)->deactivate(); +} + +bool C_LinkWireless_serve(C_LinkWirelessHandle handle, + const char* gameName, + const char* userName, + u16 gameId) { + return static_cast(handle)->serve(gameName, userName, gameId); +} + +bool C_LinkWireless_getServers(C_LinkWirelessHandle handle, + C_LinkWireless_Server servers[]) { + return static_cast(handle)->getServers( + reinterpret_cast(servers)); +} + +bool C_LinkWireless_getServersAsyncStart(C_LinkWirelessHandle handle) { + return static_cast(handle)->getServersAsyncStart(); +} + +bool C_LinkWireless_getServersAsyncEnd(C_LinkWirelessHandle handle, + C_LinkWireless_Server servers[]) { + return static_cast(handle)->getServersAsyncEnd( + reinterpret_cast(servers)); +} + +bool C_LinkWireless_connect(C_LinkWirelessHandle handle, u16 serverId) { + return static_cast(handle)->connect(serverId); +} + +bool C_LinkWireless_keepConnecting(C_LinkWirelessHandle handle) { + return static_cast(handle)->keepConnecting(); +} + +bool C_LinkWireless_send(C_LinkWirelessHandle handle, u16 data) { + return static_cast(handle)->send(data); +} + +bool C_LinkWireless_receive(C_LinkWirelessHandle handle, + C_LinkWireless_Message messages[]) { + return static_cast(handle)->receive( + reinterpret_cast(messages)); +} + +C_LinkWirelessState C_LinkWireless_getState(C_LinkWirelessHandle handle) { + return static_cast( + static_cast(handle)->getState()); +} + +bool C_LinkWireless_isConnected(C_LinkWirelessHandle handle) { + return static_cast(handle)->isConnected(); +} + +u8 C_LinkWireless_playerCount(C_LinkWirelessHandle handle) { + return static_cast(handle)->playerCount(); +} + +u8 C_LinkWireless_currentPlayerId(C_LinkWirelessHandle handle) { + return static_cast(handle)->currentPlayerId(); +} + +C_LinkWireless_Error C_LinkWireless_getLastError(C_LinkWirelessHandle handle, + bool clear) { + return static_cast( + static_cast(handle)->getLastError(clear)); +} + +bool C_LinkWireless_hasActiveAsyncCommand(C_LinkWirelessHandle handle) { + return static_cast(handle)->_hasActiveAsyncCommand(); +} + +bool C_LinkWireless_canSend(C_LinkWirelessHandle handle) { + return static_cast(handle)->_canSend(); +} + +u32 C_LinkWireless_getPendingCount(C_LinkWirelessHandle handle) { + return static_cast(handle)->_getPendingCount(); +} + +u32 C_LinkWireless_lastPacketId(C_LinkWirelessHandle handle) { + return static_cast(handle)->_lastPacketId(); +} + +u32 C_LinkWireless_lastConfirmationFromClient1(C_LinkWirelessHandle handle) { + return static_cast(handle)->_lastConfirmationFromClient1(); +} + +u32 C_LinkWireless_lastPacketIdFromClient1(C_LinkWirelessHandle handle) { + return static_cast(handle)->_lastPacketIdFromClient1(); +} + +u32 C_LinkWireless_lastConfirmationFromServer(C_LinkWirelessHandle handle) { + return static_cast(handle)->_lastConfirmationFromServer(); +} + +u32 C_LinkWireless_lastPacketIdFromServer(C_LinkWirelessHandle handle) { + return static_cast(handle)->_lastPacketIdFromServer(); +} + +u32 C_LinkWireless_nextPendingPacketId(C_LinkWirelessHandle handle) { + return static_cast(handle)->_nextPendingPacketId(); +} + +void C_LinkWireless_onVBlank(C_LinkWirelessHandle handle) { + static_cast(handle)->_onVBlank(); +} + +void C_LinkWireless_onSerial(C_LinkWirelessHandle handle) { + static_cast(handle)->_onSerial(); +} + +void C_LinkWireless_onTimer(C_LinkWirelessHandle handle) { + static_cast(handle)->_onTimer(); +} + +void C_LinkWireless_onACKTimer(C_LinkWirelessHandle handle) { + static_cast(handle)->_onACKTimer(); +} +} diff --git a/lib/c_bindings/C_LinkWireless.h b/lib/c_bindings/C_LinkWireless.h new file mode 100644 index 0000000..d6eb342 --- /dev/null +++ b/lib/c_bindings/C_LinkWireless.h @@ -0,0 +1,145 @@ +#ifndef C_BINDINGS_LINK_WIRELESS_H +#define C_BINDINGS_LINK_WIRELESS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef void* C_LinkWirelessHandle; + +#define C_LINK_WIRELESS_MAX_PLAYERS 5 +#define C_LINK_WIRELESS_MIN_PLAYERS 2 +#define C_LINK_WIRELESS_END 0 +#define C_LINK_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH 22 +#define C_LINK_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH 30 +#define C_LINK_WIRELESS_BROADCAST_LENGTH 6 +#define C_LINK_WIRELESS_BROADCAST_RESPONSE_LENGTH \ + (1 + C_LINK_WIRELESS_BROADCAST_LENGTH) +#define C_LINK_WIRELESS_MAX_SERVERS \ + (C_LINK_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH / \ + C_LINK_WIRELESS_BROADCAST_RESPONSE_LENGTH) +#define C_LINK_WIRELESS_MAX_GAME_ID 0x7fff +#define C_LINK_WIRELESS_MAX_GAME_NAME_LENGTH 14 +#define C_LINK_WIRELESS_MAX_USER_NAME_LENGTH 8 +#define C_LINK_WIRELESS_DEFAULT_TIMEOUT 10 +#define C_LINK_WIRELESS_DEFAULT_INTERVAL 50 +#define C_LINK_WIRELESS_DEFAULT_SEND_TIMER_ID 3 +#define C_LINK_WIRELESS_DEFAULT_ASYNC_ACK_TIMER_ID -1 + +typedef enum { + C_LINK_WIRELESS_STATE_NEEDS_RESET, + C_LINK_WIRELESS_STATE_AUTHENTICATED, + C_LINK_WIRELESS_STATE_SEARCHING, + C_LINK_WIRELESS_STATE_SERVING, + C_LINK_WIRELESS_STATE_CONNECTING, + C_LINK_WIRELESS_STATE_CONNECTED +} C_LinkWirelessState; + +typedef enum { + C_LINK_WIRELESS_ERROR_NONE, + C_LINK_WIRELESS_ERROR_WRONG_STATE, + C_LINK_WIRELESS_ERROR_GAME_NAME_TOO_LONG, + C_LINK_WIRELESS_ERROR_USER_NAME_TOO_LONG, + C_LINK_WIRELESS_ERROR_BUFFER_IS_FULL, + C_LINK_WIRELESS_ERROR_COMMAND_FAILED, + C_LINK_WIRELESS_ERROR_CONNECTION_FAILED, + C_LINK_WIRELESS_ERROR_SEND_DATA_FAILED, + C_LINK_WIRELESS_ERROR_RECEIVE_DATA_FAILED, + C_LINK_WIRELESS_ERROR_ACKNOWLEDGE_FAILED, + C_LINK_WIRELESS_ERROR_TIMEOUT, + C_LINK_WIRELESS_ERROR_REMOTE_TIMEOUT, + C_LINK_WIRELESS_ERROR_BUSY_TRY_AGAIN +} C_LinkWireless_Error; + +typedef struct { + u16 packetId; + u16 data; + u8 playerId; +} C_LinkWireless_Message; + +typedef struct { + u16 id; + u16 gameId; + char gameName[15]; + char userName[9]; + u8 currentPlayerCount; +} C_LinkWireless_Server; + +C_LinkWirelessHandle C_LinkWireless_create(bool forwarding, + bool retransmission, + u8 maxPlayers, + u32 timeout, + u16 interval, + u8 sendTimerId, + s8 asyncACKTimerId); +void C_LinkWireless_destroy(C_LinkWirelessHandle handle); + +bool C_LinkWireless_activate(C_LinkWirelessHandle handle); +bool C_LinkWireless_deactivate(C_LinkWirelessHandle handle); +bool C_LinkWireless_serve(C_LinkWirelessHandle handle, + const char* gameName, + const char* userName, + u16 gameId); + +bool C_LinkWireless_getServers(C_LinkWirelessHandle handle, + C_LinkWireless_Server servers[]); +bool C_LinkWireless_getServersAsyncStart(C_LinkWirelessHandle handle); +bool C_LinkWireless_getServersAsyncEnd(C_LinkWirelessHandle handle, + C_LinkWireless_Server servers[]); + +bool C_LinkWireless_connect(C_LinkWirelessHandle handle, u16 serverId); +bool C_LinkWireless_keepConnecting(C_LinkWirelessHandle handle); + +bool C_LinkWireless_send(C_LinkWirelessHandle handle, u16 data); +bool C_LinkWireless_receive(C_LinkWirelessHandle handle, + C_LinkWireless_Message messages[]); + +C_LinkWirelessState C_LinkWireless_getState(C_LinkWirelessHandle handle); +bool C_LinkWireless_isConnected(C_LinkWirelessHandle handle); +u8 C_LinkWireless_playerCount(C_LinkWirelessHandle handle); +u8 C_LinkWireless_currentPlayerId(C_LinkWirelessHandle handle); + +C_LinkWireless_Error C_LinkWireless_getLastError(C_LinkWirelessHandle handle, + bool clear); + +bool C_LinkWireless_hasActiveAsyncCommand(C_LinkWirelessHandle handle); +bool C_LinkWireless_canSend(C_LinkWirelessHandle handle); + +u32 C_LinkWireless_getPendingCount(C_LinkWirelessHandle handle); +u32 C_LinkWireless_lastPacketId(C_LinkWirelessHandle handle); +u32 C_LinkWireless_lastConfirmationFromClient1(C_LinkWirelessHandle handle); +u32 C_LinkWireless_lastPacketIdFromClient1(C_LinkWirelessHandle handle); +u32 C_LinkWireless_lastConfirmationFromServer(C_LinkWirelessHandle handle); +u32 C_LinkWireless_lastPacketIdFromServer(C_LinkWirelessHandle handle); +u32 C_LinkWireless_nextPendingPacketId(C_LinkWirelessHandle handle); + +void C_LinkWireless_onVBlank(C_LinkWirelessHandle handle); +void C_LinkWireless_onSerial(C_LinkWirelessHandle handle); +void C_LinkWireless_onTimer(C_LinkWirelessHandle handle); +void C_LinkWireless_onACKTimer(C_LinkWirelessHandle handle); + +extern C_LinkWirelessHandle cLinkWireless; + +inline void C_LINK_WIRELESS_ISR_VBLANK() { + C_LinkWireless_onVBlank(cLinkWireless); +} + +inline void C_LINK_WIRELESS_ISR_SERIAL() { + C_LinkWireless_onSerial(cLinkWireless); +} + +inline void C_LINK_WIRELESS_ISR_TIMER() { + C_LinkWireless_onTimer(cLinkWireless); +} + +inline void C_LINK_WIRELESS_ISR_ACK_TIMER() { + C_LinkWireless_onACKTimer(cLinkWireless); +} + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_WIRELESS_H diff --git a/lib/c_bindings/C_LinkWirelessMultiboot.cpp b/lib/c_bindings/C_LinkWirelessMultiboot.cpp new file mode 100644 index 0000000..f5c1e86 --- /dev/null +++ b/lib/c_bindings/C_LinkWirelessMultiboot.cpp @@ -0,0 +1,36 @@ +#include "C_LinkWirelessMultiboot.h" +#include "../LinkWirelessMultiboot.hpp" + +extern "C" { + +C_LinkWirelessMultibootHandle C_LinkWirelessMultiboot_create() { + return new LinkWirelessMultiboot(); +} + +void C_LinkWirelessMultiboot_destroy(C_LinkWirelessMultibootHandle handle) { + delete static_cast(handle); +} + +C_LinkWirelessMultiboot_Result C_LinkWirelessMultiboot_sendRom( + C_LinkWirelessMultibootHandle handle, + const u8* rom, + u32 romSize, + const char* gameName, + const char* userName, + u16 gameId, + u8 players, + C_LinkWirelessMultiboot_CancelCallback cancel) { + auto result = static_cast(handle)->sendRom( + rom, romSize, gameName, userName, gameId, players, + [cancel](LinkWirelessMultiboot::MultibootProgress progress) { + C_LinkWirelessMultiboot_Progress cProgress; + cProgress.state = + static_cast(progress.state); + cProgress.connectedClients = progress.connectedClients; + cProgress.percentage = progress.percentage; + return cancel(cProgress); + }); + + return static_cast(result); +} +} diff --git a/lib/c_bindings/C_LinkWirelessMultiboot.h b/lib/c_bindings/C_LinkWirelessMultiboot.h new file mode 100644 index 0000000..ae7910f --- /dev/null +++ b/lib/c_bindings/C_LinkWirelessMultiboot.h @@ -0,0 +1,65 @@ +#ifndef C_BINDINGS_LINK_WIRELESS_MULTIBOOT_H +#define C_BINDINGS_LINK_WIRELESS_MULTIBOOT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef void* C_LinkWirelessMultibootHandle; + +#define C_LINK_WIRELESS_MULTIBOOT_MIN_ROM_SIZE (0x100 + 0xc0) +#define C_LINK_WIRELESS_MULTIBOOT_MAX_ROM_SIZE (256 * 1024) +#define C_LINK_WIRELESS_MULTIBOOT_MIN_PLAYERS 2 +#define C_LINK_WIRELESS_MULTIBOOT_MAX_PLAYERS 5 + +typedef enum { + C_LINK_WIRELESS_MULTIBOOT_SUCCESS, + C_LINK_WIRELESS_MULTIBOOT_INVALID_SIZE, + C_LINK_WIRELESS_MULTIBOOT_INVALID_PLAYERS, + C_LINK_WIRELESS_MULTIBOOT_CANCELED, + C_LINK_WIRELESS_MULTIBOOT_ADAPTER_NOT_DETECTED, + C_LINK_WIRELESS_MULTIBOOT_BAD_HANDSHAKE, + C_LINK_WIRELESS_MULTIBOOT_CLIENT_DISCONNECTED, + C_LINK_WIRELESS_MULTIBOOT_FAILURE +} C_LinkWirelessMultiboot_Result; + +typedef enum { + C_LINK_WIRELESS_MULTIBOOT_STATE_STOPPED, + C_LINK_WIRELESS_MULTIBOOT_STATE_INITIALIZING, + C_LINK_WIRELESS_MULTIBOOT_STATE_WAITING, + C_LINK_WIRELESS_MULTIBOOT_STATE_PREPARING, + C_LINK_WIRELESS_MULTIBOOT_STATE_SENDING, + C_LINK_WIRELESS_MULTIBOOT_STATE_CONFIRMING +} C_LinkWirelessMultiboot_State; + +typedef struct { + C_LinkWirelessMultiboot_State state; + u32 connectedClients; + u32 percentage; +} C_LinkWirelessMultiboot_Progress; + +typedef bool (*C_LinkWirelessMultiboot_CancelCallback)( + C_LinkWirelessMultiboot_Progress progress); + +C_LinkWirelessMultibootHandle C_LinkWirelessMultiboot_create(); +void C_LinkWirelessMultiboot_destroy(C_LinkWirelessMultibootHandle handle); + +C_LinkWirelessMultiboot_Result C_LinkWirelessMultiboot_sendRom( + C_LinkWirelessMultibootHandle handle, + const u8* rom, + u32 romSize, + const char* gameName, + const char* userName, + u16 gameId, + u8 players, + C_LinkWirelessMultiboot_CancelCallback cancel); + +extern C_LinkWirelessMultibootHandle cLinkWirelessMultiboot; + +#ifdef __cplusplus +} +#endif + +#endif // C_BINDINGS_LINK_WIRELESS_MULTIBOOT_H