fxsdk/libfxlink/include/fxlink/defs.h
Lephenixnoir 85d7fcf9e9
libfxlink: fix race condition leading to lost messages
Basically if the calculator sends two messages in a row, it is possible
for a single libusb_handle_events() to get both. And the comm structure
wasn't designed for that, because it could buffer only one message at a
time, which the user needed to read after event handling.

The comm structure now has a 16-message buffer, which should be more
than enough for any single event handling loop. On the user level this
has implications in that fxlink_device_finish_bulk_IN() must be called
*in a loop* after each event handling cycle.

Reported in https://git.planet-casio.com/Lephenixnoir/gint/pulls/27
2024-03-24 19:25:35 +01:00

115 lines
3.5 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.defs: Utility definitions and functions
#pragma once
#include <fxlink/config.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include <poll.h>
static inline int min(int x, int y)
{
return (x < y) ? x : y;
}
static inline int max(int x, int y)
{
return (x > y) ? x : y;
}
static inline int clamp(int x, int min, int max)
{
return (x < min) ? min : (x > max) ? max : x;
}
//---
// Text formatting
//
// We stick to ANSI style and provide 8 colors (foreground and background) with
// bold/italic/dim attributes. The standard ANSI escape translation is provided
// here while the ncurses versions is implemented by the TUI.
//---
enum {
/* Main colors */
FMT_BLACK = 0x01,
FMT_RED = 0x02,
FMT_GREEN = 0x03,
FMT_YELLOW = 0x04,
FMT_BLUE = 0x05,
FMT_MAGENTA = 0x06,
FMT_CYAN = 0x07,
FMT_WHITE = 0x08,
/* Background colors */
FMT_BGBLACK = 0x10,
FMT_BGRED = 0x20,
FMT_BGGREEN = 0x30,
FMT_BGYELLOW = 0x40,
FMT_BGBLUE = 0x50,
FMT_BGMAGENTA = 0x60,
FMT_BGCYAN = 0x70,
FMT_BGWHITE = 0x80,
/* Modifiers */
FMT_BOLD = 0x100,
FMT_DIM = 0x200,
FMT_ITALIC = 0x400,
};
#define fmt_FG(fmt) ((fmt) & 0xf)
#define fmt_BG(fmt) (((fmt) >> 4) & 0xf)
#define fmt_BOLD(fmt) (((fmt) & FMT_BOLD) != 0)
#define fmt_DIM(fmt) (((fmt) & FMT_DIM) != 0)
#define fmt_ITALIC(fmt) (((fmt) & FMT_ITALIC) != 0)
/* Returns the escape sequence that switches to the desired format. The
returned pointer is to a static buffer overwritten on the next call. */
char const *fmt_to_ANSI(int format);
//---
// Misc.
//---
/* Generates a unique name for a file to be stored in `path`, with `name` as a
component and the provided `suffix`. The generated path looks like
<path>/fxlink-<name>-2021.05.09-19h23-1<suffix>
with the `-1` suffix being chosen as to avoid overriding existing files.
Returns a newly-allocated string to be free()'d after use. */
char *fxlink_gen_file_name(char const *path, char const *name,
char const *suffix);
/* Modified poll with a variable number of arrays. */
int fxlink_multipoll(int timeout, struct pollfd *fds1, int count1, ...);
/* Write out the given size (in bytes) in a human-readable form. Returns a
pointer to a statically-allocated string. */
char const *fxlink_size_string(int bytes);
/* Hexdump a data buffer to FILE. */
void fxlink_hexdump(char const *data, int size, FILE *fp);
//---
// Delay
//---
/* An expandable allocated time used to wait for devices */
typedef int delay_t;
/* Builds an empty delay. */
delay_t delay_none(void);
/* Builds a delay that lasts the specified number of seconds. */
delay_t delay_seconds(int seconds);
/* Builds an infinite delay. */
delay_t delay_infinite(void);
/* Returns `true` if the delay has expired; otherwise, waits for a short while
(250 ms), decreases the supplied delay pointer, and returns `false`. Never
returns `true` after waiting (even if the delay just expired) so the caller
can attempt their task one last time before giving up on a timeout. */
bool delay_cycle(delay_t *delay);