Platform Utilities

API Documentation

Starting / Stopping the Sandpiper Device Support

struct SPPlatform* SPInitPlatform();

Opens hardware devices and sets up necessary internals so that we can start using the custom video and audio circuitry.

void SPShutdownPlatform(struct SPPlatform* _platform);

Relinquishes control back to the caller by releasing memory. However it will not close the device connections, which the platform driver at /dev/sandpiper handles. This is done so that there is always a visible terminal window and silent audio when an application crashes or exits due to unknown reasons.

Shared Memory Allocation / Deallocation

int SPAllocateBuffer(struct SPPlatform* _platform, struct SPSizeAlloc *_sizealloc);

Allocates a portion of physical memory with proper DMA alignment, and populates the SPSizeAlloc structure with matching physical / CPU address pairs for use with devices and the ARM cores.

void SPFreeBuffer(struct SPPlatform* _platform, struct SPSizeAlloc *_sizealloc);

Hands back the previously allocated buffer.

Input Device Discovery

int SPFindKeyboardDevice();

Searches for a connected keyboard device by scanning /dev/input/event* devices.

Returns: File descriptor for the keyboard device, or -1 if not found.

Usage: The returned file descriptor can be used with poll() and read() to receive keyboard input events in struct input_event format (from linux/input.h).

Example:

#include <poll.h>
#include <linux/input.h>
#include "platform.h"

struct pollfd fds[1];
fds[0].fd = SPFindKeyboardDevice();
fds[0].events = POLLIN;

if (fds[0].fd < 0) {
    printf("No keyboard found\n");
} else {
    // Poll for events
    int ret = poll(fds, 1, 10);
    if (ret > 0) {
        struct input_event ev;
        read(fds[0].fd, &ev, sizeof(ev));
        if (ev.type == EV_KEY) {
            printf("Key: %d, State: %d\n", ev.code, ev.value);
        }
    }
}
int SPFindMouseDevice();

Searches for a connected mouse or touchpad device by scanning /dev/input/event* devices.

Returns: File descriptor for the mouse device, or -1 if not found.

Usage: The returned file descriptor can be used with poll() and read() to receive mouse input events. Mouse events include relative movement (EV_REL) with REL_X/REL_Y axes and button presses (EV_KEY) with BTN_LEFT/BTN_RIGHT/BTN_MIDDLE.

Example:

#include <poll.h>
#include <linux/input.h>
#include "platform.h"

struct pollfd fds[1];
fds[0].fd = SPFindMouseDevice();
fds[0].events = POLLIN;

if (fds[0].fd >= 0) {
    int ret = poll(fds, 1, 10);
    if (ret > 0) {
        struct input_event ev;
        read(fds[0].fd, &ev, sizeof(ev));
        
        if (ev.type == EV_REL) {
            if (ev.code == REL_X)
                printf("Mouse X: %d\n", ev.value);
            else if (ev.code == REL_Y)
                printf("Mouse Y: %d\n", ev.value);
        } else if (ev.type == EV_KEY) {
            printf("Button: %d, State: %d\n", ev.code, ev.value);
        }
    }
}
int SPFindGamepadDevice();

Searches for a connected gamepad or joystick device by scanning /dev/input/event* devices.

Returns: File descriptor for the gamepad device, or -1 if not found.

Usage: The returned file descriptor can be used with poll() and read() to receive gamepad input events. Gamepad events include absolute axis values (EV_ABS) for joysticks and triggers, and button presses (EV_KEY) for face buttons, triggers, and D-pad.

Example:

#include <poll.h>
#include <linux/input.h>
#include "platform.h"

struct pollfd fds[1];
fds[0].fd = SPFindGamepadDevice();
fds[0].events = POLLIN;

if (fds[0].fd >= 0) {
    printf("Gamepad found!\n");
    
    int ret = poll(fds, 1, 10);
    if (ret > 0) {
        struct input_event ev;
        read(fds[0].fd, &ev, sizeof(ev));
        
        if (ev.type == EV_ABS) {
            printf("Axis %d: %d\n", ev.code, ev.value);
        } else if (ev.type == EV_KEY) {
            printf("Button %d: %s\n", ev.code, 
                   ev.value ? "pressed" : "released");
        }
    }
}

Notes on Input Handling