|
M_io_layer_t * | M_io_layer_acquire (M_io_t *io, size_t layer_id, const char *name) |
|
void | M_io_layer_release (M_io_layer_t *layer) |
|
M_io_t * | M_io_init (M_io_type_t type) |
|
M_io_type_t | M_io_get_type (M_io_t *io) |
|
M_io_callbacks_t * | M_io_callbacks_create (void) |
|
M_bool | M_io_callbacks_reg_init (M_io_callbacks_t *callbacks, M_bool(*cb_init)(M_io_layer_t *layer)) |
|
M_bool | M_io_callbacks_reg_accept (M_io_callbacks_t *callbacks, M_io_error_t(*cb_accept)(M_io_t *new_conn, M_io_layer_t *orig_layer)) |
|
M_bool | M_io_callbacks_reg_read (M_io_callbacks_t *callbacks, M_io_error_t(*cb_read)(M_io_layer_t *layer, unsigned char *buf, size_t *read_len, M_io_meta_t *meta)) |
|
M_bool | M_io_callbacks_reg_write (M_io_callbacks_t *callbacks, M_io_error_t(*cb_write)(M_io_layer_t *layer, const unsigned char *buf, size_t *write_len, M_io_meta_t *meta)) |
|
M_bool | M_io_callbacks_reg_processevent (M_io_callbacks_t *callbacks, M_bool(*cb_process_event)(M_io_layer_t *layer, M_event_type_t *type)) |
|
M_bool | M_io_callbacks_reg_unregister (M_io_callbacks_t *callbacks, void(*cb_unregister)(M_io_layer_t *layer)) |
|
M_bool | M_io_callbacks_reg_disconnect (M_io_callbacks_t *callbacks, M_bool(*cb_disconnect)(M_io_layer_t *layer)) |
|
M_bool | M_io_callbacks_reg_reset (M_io_callbacks_t *callbacks, M_bool(*cb_reset)(M_io_layer_t *layer)) |
|
M_bool | M_io_callbacks_reg_destroy (M_io_callbacks_t *callbacks, void(*cb_destroy)(M_io_layer_t *layer)) |
|
M_bool | M_io_callbacks_reg_state (M_io_callbacks_t *callbacks, M_io_state_t(*cb_state)(M_io_layer_t *layer)) |
|
M_bool | M_io_callbacks_reg_errormsg (M_io_callbacks_t *callbacks, M_bool(*cb_errormsg)(M_io_layer_t *layer, char *error, size_t err_len)) |
|
void | M_io_callbacks_destroy (M_io_callbacks_t *callbacks) |
|
M_io_layer_t * | M_io_layer_add (M_io_t *io, const char *layer_name, M_io_handle_t *handle, const M_io_callbacks_t *callbacks) |
|
M_io_t * | M_io_layer_get_io (M_io_layer_t *layer) |
|
const char * | M_io_layer_get_name (M_io_layer_t *layer) |
|
M_io_handle_t * | M_io_layer_get_handle (M_io_layer_t *layer) |
|
size_t | M_io_layer_get_index (M_io_layer_t *layer) |
|
M_io_error_t | M_io_layer_read (M_io_t *io, size_t layer_id, unsigned char *buf, size_t *read_len, M_io_meta_t *meta) |
|
M_io_error_t | M_io_layer_write (M_io_t *io, size_t layer_id, const unsigned char *buf, size_t *write_len, M_io_meta_t *meta) |
|
M_bool | M_io_error_is_critical (M_io_error_t err) |
|
void | M_io_layer_softevent_add (M_io_layer_t *layer, M_bool sibling_only, M_event_type_t type, M_io_error_t err) |
|
void | M_io_layer_softevent_clear (M_io_layer_t *layer) |
|
void | M_io_layer_softevent_del (M_io_layer_t *layer, M_bool sibling_only, M_event_type_t type) |
|
void | M_io_set_error (M_io_t *io, M_io_error_t err) |
|
Included using the semi-public header of <mstdlib/io/m_io_layer.h>
This is a semi-public header meant for those writing their own io layers. This could be a low level layer that's not current supported for comms. More commonly it would be intermediate layers to accommodate specific data handling.
Layer Design
Layers are stacked with the application being on top and the comms layer on the bottom (typically comms later is the bottom layer). Layers in between are typically data processing layers. For example, Application, TLS, and network. Where the TLS layer is an intermediate data processing layer.
Intermediate layers are bidirectional with data flowing down and up.
Processing Events Callback
The processevent_cb
set by M_io_callbacks_reg_processevent()
flows upward. From the bottom comms layer through the intermediate layer and then to the application layer. This is where data manipulation coming in can be handled. The callback can either allow the even that trigged it to continue up the layer stack or it can suppress the event so no further processing takes place.
For example, if the intermediate layer doesn't need to do any processing of the data or has completed all processing it will allow the event to propagate up. If the layer needs more data before it can be used by the next layer it will suppress the event so processing the event stops.
A read event from processevent_cb
needs to read the data from the layer under in order to get the data flowing up to process. A write event needs to write any pending data to the layer under in order for it to be sent out. Read flows up and write flows down.
Events always come from the bottom up. Either the lower layer(s) are stating there is data to read, or it is stating data can be written. If there is no processing of read data or no data to write the events would be allowed to propagate upwards so other layers (or the application) can handle the event.
For processing read events, from the processevent_cb
it is necessary to use M_io_layer_read()
like so M_io_layer_read(io, M_io_layer_get_index(layer) - 1, buf, &buf_len, meta);
. Since data is flowing up, the layer under a given layer has the pending read data that needs to be processed.
For processing write events, from the processevent_cb
it is necessary to use M_io_layer_write()
like so M_io_layer_write(io, M_io_layer_get_index(layer) - 1, NULL, NULL, meta);
. Since data is flowing down, the layer under a given layer has needs to write the pending data.
An application would use M_io_read()
and M_io_write()
. These always flow from the top layer down. Since this layer is in the middle we need to always work with the layer beneath.
Read / Write Callbacks
The read_cb
and write_cb
set by M_io_callbacks_reg_read()
and M_io_callbacks_reg_write()
flow down.
A layer above will call M_io_layer_read
or if the top most layer the application would have called M_io_read
. These call the layers read_cb
If there is no read callback registered the layer is skipped and the next layer in the sequence if called. This happens internally. The read_cb
will return any buffered data that has been read and passes it upward. The data is typically buffered via the read event form processevent_cb
.
A layer above will call M_io_layer_write
or if the top most layer the application would have called M_io_write
. These call the layers write_cb
If there is no write callback registered the layer is skipped and the next layer in the sequence if called. This happens internally. The write_cb
will receive and data that needs to be passed down for writing. Typically, the write_cb
will attempt to write the data immediately (after handling any processing) but may need to buffer the data and write more later when the processevent_cb
receives a write event stating layers below can accept data to write.
Examples
Example layers:
- Basic layer that marshals data. Useful for starting a new layer.
- Processing STX+ETX+LRC with ACK/NAK and resending message
- BLE helper layer that handles secure pairing (if necessary) and setting read/write characteristic endpoints.
Basic
#include <mstdlib/io/m_io_layer.h>
struct M_io_handle {
char err[256];
};
{
size_t layer_idx;
size_t write_len;
if (io == NULL || layer_idx == 0)
do {
}
return err;
}
{
M_bool consume = M_FALSE;
if (handle == NULL || io == NULL)
return M_FALSE;
switch (*type) {
break;
err = write_to_next_layer(layer, handle->write_buf);
}
else if (
M_buf_len(handle->write_buf) != 0) {
consume = M_TRUE;
}
}
break;
do {
M_uint8 buf[256] = { 0 };
size_t buf_len = sizeof(buf);
break;
}
break;
break;
break;
}
return consume;
}
{
(void)meta;
if (handle == NULL || buf == NULL || buf_len == NULL || *buf_len == 0)
}
{
(void)meta;
if (handle == NULL || buf == NULL || buf_len == NULL || *buf_len == 0)
err = write_to_next_layer(layer, handle->write_buf);
return err;
}
{
(void)layer;
}
{
(void)layer;
return M_TRUE;
}
{
}
static M_bool error_cb(
M_io_layer_t *layer,
char *error,
size_t err_len)
{
return M_FALSE;
return M_TRUE;
}
void basic_example_layer(
M_io_t *io)
{
if (io == NULL)
return;
}
void M_buf_add_bytes(M_buf_t *buf, const void *bytes, size_t bytes_length)
void M_buf_drop(M_buf_t *buf, size_t num)
struct M_buf M_buf_t
Definition: m_buf.h:77
const char * M_buf_peek(const M_buf_t *buf)
size_t M_buf_len(const M_buf_t *buf)
M_buf_t * M_buf_create(void) M_WARN_UNUSED_RESULT M_MALLOC
void M_buf_cancel(M_buf_t *buf) M_FREE(1)
enum M_event_type M_event_type_t
Definition: m_event.h:189
@ M_EVENT_TYPE_WRITE
Definition: m_event.h:184
@ M_EVENT_TYPE_ACCEPT
Definition: m_event.h:174
@ M_EVENT_TYPE_DISCONNECTED
Definition: m_event.h:176
@ M_EVENT_TYPE_OTHER
Definition: m_event.h:185
@ M_EVENT_TYPE_READ
Definition: m_event.h:175
@ M_EVENT_TYPE_CONNECTED
Definition: m_event.h:173
@ M_EVENT_TYPE_ERROR
Definition: m_event.h:181
size_t M_snprintf(char *buf, size_t size, const char *fmt,...)
M_bool M_io_callbacks_reg_errormsg(M_io_callbacks_t *callbacks, M_bool(*cb_errormsg)(M_io_layer_t *layer, char *error, size_t err_len))
M_bool M_io_callbacks_reg_processevent(M_io_callbacks_t *callbacks, M_bool(*cb_process_event)(M_io_layer_t *layer, M_event_type_t *type))
M_bool M_io_callbacks_reg_read(M_io_callbacks_t *callbacks, M_io_error_t(*cb_read)(M_io_layer_t *layer, unsigned char *buf, size_t *read_len, M_io_meta_t *meta))
M_bool M_io_error_is_critical(M_io_error_t err)
M_io_error_t M_io_layer_write(M_io_t *io, size_t layer_id, const unsigned char *buf, size_t *write_len, M_io_meta_t *meta)
struct M_io_layer M_io_layer_t
Definition: m_io_layer.h:1086
M_io_t * M_io_layer_get_io(M_io_layer_t *layer)
struct M_io_handle M_io_handle_t
Definition: m_io_layer.h:1089
size_t M_io_layer_get_index(M_io_layer_t *layer)
M_io_error_t M_io_layer_read(M_io_t *io, size_t layer_id, unsigned char *buf, size_t *read_len, M_io_meta_t *meta)
void M_io_callbacks_destroy(M_io_callbacks_t *callbacks)
M_bool M_io_callbacks_reg_destroy(M_io_callbacks_t *callbacks, void(*cb_destroy)(M_io_layer_t *layer))
M_bool M_io_callbacks_reg_reset(M_io_callbacks_t *callbacks, M_bool(*cb_reset)(M_io_layer_t *layer))
M_io_layer_t * M_io_layer_add(M_io_t *io, const char *layer_name, M_io_handle_t *handle, const M_io_callbacks_t *callbacks)
struct M_io_callbacks M_io_callbacks_t
Definition: m_io_layer.h:1092
M_io_callbacks_t * M_io_callbacks_create(void)
M_bool M_io_callbacks_reg_unregister(M_io_callbacks_t *callbacks, void(*cb_unregister)(M_io_layer_t *layer))
M_io_handle_t * M_io_layer_get_handle(M_io_layer_t *layer)
M_bool M_io_callbacks_reg_write(M_io_callbacks_t *callbacks, M_io_error_t(*cb_write)(M_io_layer_t *layer, const unsigned char *buf, size_t *write_len, M_io_meta_t *meta))
enum M_io_error M_io_error_t
Definition: m_io.h:93
void M_io_get_error_string(M_io_t *io, char *error, size_t err_len)
struct M_io M_io_t
Definition: m_io.h:59
struct M_io_meta M_io_meta_t
Definition: m_io.h:64
const char * M_io_error_string(M_io_error_t error)
@ M_IO_ERROR_SUCCESS
Definition: m_io.h:69
@ M_IO_ERROR_WOULDBLOCK
Definition: m_io.h:70
@ M_IO_ERROR_INVALID
Definition: m_io.h:83
#define M_MIN(a, b)
Definition: m_math.h:44
void * M_malloc_zero(size_t size) M_ALLOC_SIZE(1) M_WARN_UNUSED_RESULT M_MALLOC
void * M_mem_copy(void *dst, const void *src, size_t size)
void M_free(void *ptr) M_FREE(1)
M_bool M_str_isempty(const char *s) M_WARN_UNUSED_RESULT
M_bool M_str_cpy(char *dest, size_t dest_len, const char *src)
STX + ETX + LRC with ACK / NAK and resending
#include <mstdlib/mstdlib.h>
#include <mstdlib/io/m_io_layer.h>
struct M_io_handle {
M_bool can_write;
size_t resend_cnt;
char err[256];
};
static const char *LAYER_NAME = "STXETXLRCACKNAK";
static const size_t RESEND_MAX = 5;
static const size_t RESEND_INTERVAL = 3*1000;
static const char *STX_STR = "\x02";
static const char *ACK_STR = "\x06";
static const char *NAK_STR = "\x15";
static const unsigned char STX = 0x02;
static const unsigned char ETX = 0x03;
static const unsigned char ACK = 0x06;
static const unsigned char NAK = 0x15;
{
size_t layer_idx;
size_t write_len = 0;
if (layer == NULL || handle == NULL)
if (io == NULL || layer_idx == 0)
write_len = 0;
}
}
return err;
}
{
if (handle->resend_cnt >= RESEND_MAX) {
M_snprintf(handle->err,
sizeof(handle->err),
"Timeout: Exceeded resent attempts");
return;
}
write_int(layer, handle, NULL);
handle->resend_cnt++;
}
{
(void)el;
(void)io;
(void)etype;
M_printf(
"%s: NO RESPONSE!", LAYER_NAME);
resend_message(layer, handle);
}
{
handle->can_write = M_TRUE;
return handle;
}
{
if (handle == NULL)
return;
}
{
size_t len;
return M_TRUE;
if (len != 0) {
resend_message(layer, handle);
return M_TRUE;
}
handle->resend_cnt = 0;
if (len > 1)
handle->can_write = M_TRUE;
if (len > 0)
M_printf(
"%s: Unexpected data was dropped (%zu bytes)", LAYER_NAME, len);
return M_TRUE;
M_printf(
"%s: Message LRC verification failed: dropped (%zu bytes)", LAYER_NAME,
M_parser_len(msg_parser));
write_int(layer, handle, NULL);
}
return M_TRUE;
}
write_int(layer, handle, NULL);
return M_FALSE;
}
{
M_bool discard = M_TRUE;
unsigned char buf[8192] = { 0 };
size_t len;
do {
len = sizeof(buf);
discard = process_message(layer, handle);
}
return discard;
}
{
err = write_int(layer, handle, NULL);
return M_TRUE;
}
return M_FALSE;
}
{
size_t bytes_left;
(void)meta;
if (handle == NULL || buf == NULL || read_len == NULL || *read_len == 0)
process_message(layer, handle);
*read_len =
M_MIN(*read_len, bytes_left);
}
{
size_t mywrite_len = 0;
if (handle == NULL || buf == NULL || buf_len == NULL || *buf_len == 0)
handle->can_write = M_FALSE;
return write_int(layer, handle, meta);
}
{
const char *estr;
switch (*type) {
handle->can_write = M_TRUE;
return handle_write(layer, handle, type);
return handle_read(layer, handle, type);
return M_FALSE;
}
return M_FALSE;
}
static M_bool error_cb(
M_io_layer_t *layer,
char *error,
size_t err_len)
{
return M_FALSE;
return M_TRUE;
}
{
if (handle->resend_timer != NULL)
return M_TRUE;
}
{
(void)layer;
}
{
(void)layer;
return M_TRUE;
}
{
if (layer == NULL)
return;
}
void stxetxlrcacknak_io_layer(
M_io_t *io, M_bool reconnect)
{
}
M_bool stxetxlrcacknak_layer_waiting_for_response(
M_io_t *io)
{
size_t layer_count;
size_t layer_idx;
M_bool ret = M_FALSE;
for (layer_idx=0; layer_idx<layer_count; layer_idx++) {
if (layer == NULL) {
continue;
}
ret = !handle->can_write;
break;
}
return ret;
}
void M_buf_add_byte(M_buf_t *buf, unsigned char byte)
void M_buf_truncate(M_buf_t *buf, size_t length)
M_bool M_event_timer_start(M_event_timer_t *timer, M_uint64 interval_ms)
M_bool M_event_timer_remove(M_event_timer_t *timer)
M_event_timer_t * M_event_timer_add(M_event_t *event, M_event_callback_t callback, void *cb_data)
M_event_t * M_io_get_event(M_io_t *io)
struct M_event M_event_t
Definition: m_event.h:210
M_bool M_event_timer_stop(M_event_timer_t *timer)
struct M_event_timer M_event_timer_t
Definition: m_event.h:203
ssize_t M_printf(const char *fmt,...)
void M_io_layer_softevent_add(M_io_layer_t *layer, M_bool sibling_only, M_event_type_t type, M_io_error_t err)
void M_io_layer_release(M_io_layer_t *layer)
M_bool M_io_callbacks_reg_init(M_io_callbacks_t *callbacks, M_bool(*cb_init)(M_io_layer_t *layer))
M_io_layer_t * M_io_layer_acquire(M_io_t *io, size_t layer_id, const char *name)
size_t M_io_layer_count(M_io_t *io)
@ M_IO_ERROR_TIMEDOUT
Definition: m_io.h:81
unsigned char M_mem_calc_lrc(const void *s, size_t s_len)
size_t M_parser_len(const M_parser_t *parser)
M_bool M_parser_append(M_parser_t *parser, const unsigned char *data, size_t len)
void M_parser_destroy(M_parser_t *parser)
struct M_parser M_parser_t
Definition: m_parser.h:52
size_t M_parser_consume_not_charset(M_parser_t *parser, const unsigned char *charset, size_t charset_len)
const unsigned char * M_parser_peek(const M_parser_t *parser)
M_PARSER_FRAME_ERROR
Definition: m_parser.h:95
M_PARSER_FRAME_ERROR M_parser_read_stxetxlrc_message(M_parser_t *parser, M_parser_t **out, M_uint32 lrc_frame_chars)
size_t M_parser_consume_charset(M_parser_t *parser, const unsigned char *charset, size_t charset_len)
M_parser_t * M_parser_create(M_uint32 flags)
@ M_PARSER_FRAME_ETX
Definition: m_parser.h:91
@ M_PARSER_FLAG_NONE
Definition: m_parser.h:60
@ M_PARSER_FRAME_ERROR_SUCCESS
Definition: m_parser.h:96
@ M_PARSER_FRAME_ERROR_LRC_CALC_FAILED
Definition: m_parser.h:101
BLE Helper
#include <mstdlib/io/m_io_layer.h>
static const char *LAYER_NAME = "BLE_SERVICE_HELPER";
static const char *BLE_SERVICE = "68950001-FBA1-BB3D-A043-647EF78ACD44";
static const char *BLE_CHARACTERISTIC = "68951001-FBA1-BB3D-A043-647EF78ACD44";
struct M_io_handle {
char err[256];
M_bool connected;
};
{
size_t layer_idx;
size_t write_len;
if (io == NULL || layer_idx == 0)
do {
}
return err;
}
{
return write_to_next_layer(layer, write_buf, write_meta);
}
{
return err;
}
{
M_bool consume = M_FALSE;
if (handle == NULL || io == NULL)
return M_FALSE;
switch (*type) {
err = write_pair_check_data(layer, handle->write_buf, handle->write_meta);
break;
}
consume = M_TRUE;
break;
if (!handle->connected) {
consume = M_TRUE;
register_notifications(io, layer, BLE_SERVICE, BLE_CHARACTERISTIC);
break;
}
err = write_to_next_layer(layer, handle->write_buf, handle->write_meta);
}
else if (
M_buf_len(handle->write_buf) != 0) {
consume = M_TRUE;
}
}
break;
do {
M_uint8 buf[256] = { 0 };
size_t buf_len = sizeof(buf);
if (handle->connected) {
consume = M_TRUE;
} else {
handle->connected = M_TRUE;
break;
}
}
break;
}
break;
break;
break;
}
return consume;
}
{
(void)meta;
if (handle == NULL || buf == NULL || buf_len == NULL || *buf_len == 0)
}
{
(void)meta;
if (handle == NULL || buf == NULL || buf_len == NULL || *buf_len == 0)
if (!handle->connected)
err = write_to_next_layer(layer, handle->write_buf, handle->write_meta);
return err;
}
{
(void)layer;
}
{
(void)layer;
return M_TRUE;
}
{
}
static M_bool error_cb(
M_io_layer_t *layer,
char *error,
size_t err_len)
{
return M_FALSE;
return M_TRUE;
}
void ble_helper_io_layer(
M_io_t *io)
{
if (io == NULL)
return;
}
void M_buf_add_str(M_buf_t *buf, const char *str)
void M_io_ble_meta_set_write_type(M_io_t *io, M_io_meta_t *meta, M_io_ble_wtype_t type)
M_io_ble_rtype_t M_io_ble_meta_get_read_type(M_io_t *io, M_io_meta_t *meta)
void M_io_ble_meta_set_service(M_io_t *io, M_io_meta_t *meta, const char *service_uuid)
void M_io_ble_meta_set_notify(M_io_t *io, M_io_meta_t *meta, M_bool enable)
void M_io_ble_meta_set_characteristic(M_io_t *io, M_io_meta_t *meta, const char *characteristic_uuid)
@ M_IO_BLE_WTYPE_REQNOTIFY
Definition: m_io_ble.h:1143
@ M_IO_BLE_WTYPE_WRITE
Definition: m_io_ble.h:1136
@ M_IO_BLE_RTYPE_NOTIFY
Definition: m_io_ble.h:1154
void M_io_meta_destroy(M_io_meta_t *meta)
M_io_meta_t * M_io_meta_create(void)
◆ M_EVENT_HANDLE
#define M_EVENT_HANDLE int |
◆ M_EVENT_INVALID_HANDLE
#define M_EVENT_INVALID_HANDLE -1 |
◆ M_EVENT_SOCKET
#define M_EVENT_SOCKET int |
◆ M_EVENT_INVALID_SOCKET
#define M_EVENT_INVALID_SOCKET -1 |
◆ M_IO_LAYERS_MAX
#define M_IO_LAYERS_MAX 16 |
Maximum number of layers for an I/O object. One reserved for the user layer
◆ M_io_layer_t
◆ M_io_handle_t
◆ M_io_callbacks_t
◆ M_io_layer_acquire()
Find the appropriate layer and grab the handle and lock it.
- Warning
- Locking the layer locks the entire event loop. Only very short operations that will not block should be performed while a layer lock is being held.
- Parameters
-
[in] | io | Pointer to io object |
[in] | layer_id | id of layer to lock, or M_IO_LAYER_FIND_FIRST_ID to search for layer. |
[in] | name | Name of layer to lock. This can be used as a sanity check to ensure the layer id really matches the layer type. Use NULL if name matching is not required. If M_IO_LAYER_FIND_FIRST_ID is used for the layer_id, this parameter cannot be NULL. |
- Returns
- locked io layer, or NULL on failure
- See also
- M_io_layer_release
◆ M_io_layer_release()
Release the lock on the layer
◆ M_io_init()
Initialize a new io object of given type
◆ M_io_get_type()
Get the type of the io object
◆ M_io_callbacks_create()
Create M_io_callbacks_t object that can be passed to M_io_layer_add
◆ M_io_callbacks_reg_init()
Register callback to initialize/begin. Is called when the io object is attached to an event. Mandatory.
◆ M_io_callbacks_reg_accept()
Register callback to accept a new connection. Conditional.
◆ M_io_callbacks_reg_read()
Register callback to read from the connection. Optional if not base layer, required if base layer
◆ M_io_callbacks_reg_write()
Register callback to write to the connection. Optional if not base layer, required if base layer
◆ M_io_callbacks_reg_processevent()
Register callback to process events. Optional. If returns M_TRUE event is consumed and not propagated to the next layer.
◆ M_io_callbacks_reg_unregister()
Register callback that is called when io object is removed from event object. Mandatory
◆ M_io_callbacks_reg_disconnect()
Register callback to start a graceful disconnect sequence. Optional.
◆ M_io_callbacks_reg_reset()
Register callback to reset any state (M_io_handle_t *). Optional.
Will reset the state of the layer for re-connection.
◆ M_io_callbacks_reg_destroy()
Register callback to destroy any state (M_io_handle_t *). Mandatory.
The event loop has already been disassociated from the layer when this callback is called. The layer will not be locked and M_io_layer_acquire will not lock the layer as the layer cannot be locked.
◆ M_io_callbacks_reg_state()
Register callback to get the layer state. Optional if not base layer, required if base layer.
◆ M_io_callbacks_reg_errormsg()
M_bool M_io_callbacks_reg_errormsg |
( |
M_io_callbacks_t * |
callbacks, |
|
|
M_bool(*)(M_io_layer_t *layer, char *error, size_t err_len) |
cb_errormsg |
|
) |
| |
Register callback to get the error message, will be called if cb_state returns M_IO_STATE_ERROR. If registered, cb_state must also be registered
◆ M_io_callbacks_destroy()
Destroy M_io_callbacks_t object
◆ M_io_layer_add()
Add a layer to an io object
◆ M_io_layer_get_io()
Given a layer object, retrieve the M_io_t reference
◆ M_io_layer_get_name()
Given a layer object, retrieve the name of the layer
◆ M_io_layer_get_handle()
Given a layer object, retrieve the implementation-specific handle
◆ M_io_layer_get_index()
Given a layer object, retrieve the index of the layer in the parent M_io_t object
◆ M_io_layer_read()
Perform a read operation at the given layer index
◆ M_io_layer_write()
Perform a write operation at the given layer index
◆ M_io_error_is_critical()
◆ M_io_layer_softevent_add()
Add a soft-event. If sibling_only is true, will only notify next layer and not self. Must specify an error.
◆ M_io_layer_softevent_clear()
Clear all soft events for the current layer
◆ M_io_layer_softevent_del()
Add a soft-event. If sibling_only is true, will only delete the soft event for the next layer up and not self.
◆ M_io_set_error()
Sets the internal error for the IO object. Used within a process events callback if emitting an error