mirror of
https://git.planet-casio.com/Lephenixnoir/fxsdk.git
synced 2024-12-29 13:03:37 +01:00
150 lines
6 KiB
C
150 lines
6 KiB
C
//---------------------------------------------------------------------------//
|
|
// ==>/[_]\ fxlink: A community communication tool for CASIO calculators. //
|
|
// |:::| Made by Lephe' as part of the fxSDK. //
|
|
// \___/ License: MIT <https://opensource.org/licenses/MIT> //
|
|
//---------------------------------------------------------------------------//
|
|
// fxlink.protocol: Basic fxlink-specific communications procotol
|
|
//
|
|
// This header implements fxlink's run-of-the-mill communications protocol.
|
|
// Messages are typed with an application/type pair and their length must be
|
|
// announced in the header. In most modes when a message with an application
|
|
// field other than "fxlink" is specified, an external executable is invoked,
|
|
// which provides a basic form of automation.
|
|
//
|
|
// Message headers are transferred in little-endian format but some message
|
|
// types are defined to have big-endian contents to avoid excessive amounts of
|
|
// work on the calculator side.
|
|
//---
|
|
|
|
/* TODO: fxlink protocol: avoid having to specify message length in header */
|
|
|
|
#pragma once
|
|
#include <fxlink/defs.h>
|
|
|
|
/* Message. The header consists of every field but the `data` pointer, and it
|
|
must arrive entirely within the first transaction for a message to be
|
|
recognized. */
|
|
struct fxlink_message {
|
|
/* Protocol version, in format 0x0000MMmm */
|
|
uint32_t version;
|
|
/* Total size of message, in bytes (excluding this header) */
|
|
uint32_t size;
|
|
/* Size of individual transfers (usually 2048 bytes) */
|
|
/* TODO: fxlink protocol: get rid of transfer size field (blank it out) */
|
|
uint32_t transfer_size;
|
|
|
|
/* Application name (NUL-padded but might not be NUL-terminated) */
|
|
char application[16];
|
|
/* Message type (NUL-padded but might not be NUL-terminated) */
|
|
char type[16];
|
|
|
|
/** End of actual header in protocol **/
|
|
|
|
/* Padding for alignment */
|
|
int _padding;
|
|
/* Pointer to message data, with `size` bytes */
|
|
void *data;
|
|
};
|
|
|
|
#define FXLINK_MESSAGE_HEADER_SIZE (offsetof(struct fxlink_message, _padding))
|
|
|
|
/* Subheader for the built-in image message type. */
|
|
struct fxlink_message_image_header {
|
|
/* Image width and height, in pixels */
|
|
uint32_t width;
|
|
uint32_t height;
|
|
/* Pixel format, one of the FXLINK_MESSAGE_IMAGE_* values below */
|
|
int pixel_format;
|
|
};
|
|
|
|
enum {
|
|
/* Image is an array of big-endian uint16_t values with RGB565 format */
|
|
FXLINK_MESSAGE_IMAGE_RGB565,
|
|
/* Image is an array of bits in black-and-white format */
|
|
FXLINK_MESSAGE_IMAGE_MONO,
|
|
/* Image is two consecutive mono arrays, one for light, one for dark */
|
|
FXLINK_MESSAGE_IMAGE_GRAY,
|
|
};
|
|
|
|
/* Format for raw decoded images to be used with other APIs. */
|
|
struct fxlink_message_image_raw {
|
|
/* Width and height in pixels */
|
|
int width;
|
|
int height;
|
|
/* Allocated array of `height` pointers, each pointing to `3*width` bytes
|
|
of memory containing the RGB data of pixels from left to right. */
|
|
uint8_t **data;
|
|
};
|
|
|
|
/* Check whether a message has a certain application and type. If type is NULL,
|
|
checks the application only (any type is accepted). */
|
|
bool fxlink_message_is_apptype(struct fxlink_message const *message,
|
|
char const *application, char const *type);
|
|
|
|
/* Check if a message is one of common built-in fxlink messages. */
|
|
#define fxlink_message_is_fxlink_text(MESSAGE) \
|
|
fxlink_message_is_apptype(MESSAGE, "fxlink", "text")
|
|
#define fxlink_message_is_fxlink_image(MESSAGE) \
|
|
fxlink_message_is_apptype(MESSAGE, "fxlink", "image")
|
|
#define fxlink_message_is_fxlink_video(MESSAGE) \
|
|
fxlink_message_is_apptype(MESSAGE, "fxlink", "video")
|
|
|
|
/* Decode an image message into a raw image structure. */
|
|
struct fxlink_message_image_raw *fxlink_message_image_decode(
|
|
struct fxlink_message const *msg);
|
|
|
|
/* Free a raw image structure. */
|
|
void fxlink_message_image_raw_free(struct fxlink_message_image_raw *raw);
|
|
|
|
/* Free memory associated with a message. If free_data is true, also frees the
|
|
internal data buffer. You should set the flag for messages you received. */
|
|
void fxlink_message_free(struct fxlink_message *message, bool free_data);
|
|
|
|
//---
|
|
// Tools for crafting and receiving messages
|
|
//---
|
|
|
|
/* Data for an inbound or outbound transfer in progress. This structure can be
|
|
created as soon as a header has been received or filled. */
|
|
struct fxlink_transfer {
|
|
/* Message header and data buffer */
|
|
struct fxlink_message msg;
|
|
/* Transfer direction (FXLINK_TRANSFER_{IN,OUT}) */
|
|
uint8_t direction;
|
|
/* Size of data sent or received so far */
|
|
int processed_size;
|
|
/* Whether we own msg.data and should free(3) it */
|
|
bool own_data;
|
|
};
|
|
|
|
enum {
|
|
/* Transfer is inbound (calculator -> fxlink) */
|
|
FXLINK_TRANSFER_IN,
|
|
/* Transfer is outbound (fxlink -> calculator) */
|
|
FXLINK_TRANSFER_OUT,
|
|
};
|
|
|
|
/* Make an inbound transfer structure starting with the provided data (the data
|
|
obtained in the first IN transaction to be decoded). This function grabs the
|
|
header from the data, allocates a buffer of a suitable size and starts
|
|
saving the message's contents. Returns NULL on error (invalid or incomplete
|
|
header, out of memory, etc). */
|
|
struct fxlink_transfer *fxlink_transfer_make_IN(void *data, int size);
|
|
|
|
/* If the provided IN transfer is finished, extract the message and free the
|
|
transfer (do not fxlink_transfer_free(tr) later!). Returns NULL if the
|
|
transfer isn't finished yet. */
|
|
struct fxlink_message *fxlink_transfer_finish_IN(struct fxlink_transfer *tr);
|
|
|
|
/* Append data to a previously-initialized inbound transfer. */
|
|
void fxlink_transfer_receive(struct fxlink_transfer *tr, void *data, int size);
|
|
|
|
/* Make an outbound transfer structure. */
|
|
struct fxlink_transfer *fxlink_transfer_make_OUT(char const *application,
|
|
char const *type, void const *data, int size, bool own_data);
|
|
|
|
/* Check whether a transfer is complete. */
|
|
bool fxlink_transfer_complete(struct fxlink_transfer const *tr);
|
|
|
|
/* Free a transfer structure and associated data. */
|
|
void fxlink_transfer_free(struct fxlink_transfer *tr);
|