//---------------------------------------------------------------------------// // ==>/[_]\ fxlink: A community communication tool for CASIO calculators. // // |:::| Made by Lephe' as part of the fxSDK. // // \___/ License: 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 /* 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);