Skip to content

Commit

Permalink
port: add function for checking and reading port messages
Browse files Browse the repository at this point in the history
Remove duplicate code and add checks.

Signed-off-by: Davide Bettio <davide@uninstall.it>
  • Loading branch information
bettio committed Dec 25, 2023
1 parent 273513f commit 76d4f8c
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 143 deletions.
1 change: 0 additions & 1 deletion doc/src/apidocs/libatomvm/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ Functions
.. doxygenfunction:: port_heap_create_tuple2
.. doxygenfunction:: port_heap_create_tuple3
.. doxygenfunction:: port_heap_create_tuple_n
.. doxygenfunction:: port_is_standard_port_command
.. doxygenfunction:: port_send_message
.. doxygenfunction:: port_send_message_nolock
.. doxygenfunction:: posix_errno_to_term
Expand Down
11 changes: 6 additions & 5 deletions src/libAtomVM/nifs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,8 @@ static NativeHandlerResult process_console_message(Context *ctx, term msg)
AVM_ABORT();
}

GenMessage gen_message;

if (term_is_tuple(msg) && term_get_tuple_arity(msg) == 2 && term_get_tuple_element(msg, 1) == CLOSE_ATOM) {
result = NativeTerminate;
term pid = term_get_tuple_element(msg, 0);
Expand Down Expand Up @@ -1032,11 +1034,10 @@ static NativeHandlerResult process_console_message(Context *ctx, term msg)
}
}

} else if (port_is_standard_port_command(msg)) {

term pid = term_get_tuple_element(msg, 0);
term ref = term_get_tuple_element(msg, 1);
term cmd = term_get_tuple_element(msg, 2);
} else if (port_parse_gen_message(msg, &gen_message) == GenMessageParseOk) {
term pid = gen_message.pid;
term ref = gen_message.ref;
term cmd = gen_message.req;

if (term_is_atom(cmd) && cmd == FLUSH_ATOM) {
fflush(stdout);
Expand Down
40 changes: 21 additions & 19 deletions src/libAtomVM/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,6 @@ void port_ensure_available(Context *ctx, size_t size)
}
}

int port_is_standard_port_command(term t)
{
if (!term_is_tuple(t)) {
return 0;
} else if (term_get_tuple_arity(t) != 3) {
return 0;
} else {
term pid = term_get_tuple_element(t, 0);
term ref = term_get_tuple_element(t, 1);
if (!term_is_pid(pid)) {
return 0;
} else if (!term_is_reference(ref)) {
return 0;
} else {
return 1;
}
}
}

term port_heap_create_tuple2(Heap *heap, term a, term b)
{
term terms[2];
Expand Down Expand Up @@ -123,3 +104,24 @@ term port_heap_create_reply(Heap *heap, term ref, term payload)
{
return port_heap_create_tuple2(heap, ref, payload);
}

enum GenMessageParseResult port_parse_gen_message(term msg, GenMessage *gen_message)
{
if (UNLIKELY(!term_is_tuple(msg) || term_get_tuple_arity(msg) != 3)) {
return GenMessageParseError;
}

gen_message->pid = term_get_tuple_element(msg, 0);
if (UNLIKELY(!term_is_pid(gen_message->pid))) {
return GenMessageParseError;
}

gen_message->ref = term_get_tuple_element(msg, 1);
if (UNLIKELY(!term_is_reference(gen_message->ref))) {
return GenMessageParseError;
}

gen_message->req = term_get_tuple_element(msg, 2);

return GenMessageParseOk;
}
18 changes: 17 additions & 1 deletion src/libAtomVM/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ static inline term port_create_reply(Context *ctx, term ref, term payload)
void port_send_message(GlobalContext *glb, term pid, term msg);
void port_send_message_nolock(GlobalContext *glb, term pid, term msg);
void port_ensure_available(Context *ctx, size_t size);
int port_is_standard_port_command(term msg);

// Helper to send a message from NIFs or from the native handler.
static inline void port_send_reply(Context *ctx, term pid, term ref, term payload)
Expand All @@ -83,6 +82,23 @@ static inline void port_send_reply(Context *ctx, term pid, term ref, term payloa
port_send_message(ctx->global, pid, reply);
}

typedef struct
{
term from;
term req;

term pid;
term ref;
} GenMessage;

enum GenMessageParseResult
{
GenMessageParseOk,
GenMessageParseError
};

enum GenMessageParseResult port_parse_gen_message(term msg, GenMessage *gen_message);

#ifdef __cplusplus
}
#endif
Expand Down
28 changes: 16 additions & 12 deletions src/platforms/esp32/components/avm_builtins/gpio_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "module.h"
#include "nifs.h"
#include "platform_defaultatoms.h"
#include "port.h"
#include "scheduler.h"
#include "term.h"
#include "utils.h"
Expand Down Expand Up @@ -477,35 +478,39 @@ static term create_pair(Context *ctx, term term1, term term2)
static NativeHandlerResult consume_gpio_mailbox(Context *ctx)
{
Message *message = mailbox_first(&ctx->mailbox);
term msg = message->message;
term pid = term_get_tuple_element(msg, 0);
term req = term_get_tuple_element(msg, 2);
term cmd_term = term_get_tuple_element(req, 0);
GenMessage gen_message;
if (UNLIKELY(port_parse_gen_message(message->message, &gen_message) != GenMessageParseOk)) {
ESP_LOGW(TAG, "Received invalid message.");
mailbox_remove_message(&ctx->mailbox, &ctx->heap);
return NativeContinue;
}

term cmd_term = term_get_tuple_element(gen_message.req, 0);

int local_process_id = term_to_local_process_id(pid);
int local_process_id = term_to_local_process_id(gen_message.pid);

term ret;

enum gpio_cmd cmd = interop_atom_term_select_int(gpio_cmd_table, cmd_term, ctx->global);
switch (cmd) {
case GPIOSetLevelCmd:
ret = gpiodriver_set_level(ctx, req);
ret = gpiodriver_set_level(ctx, gen_message.req);
break;

case GPIOSetDirectionCmd:
ret = gpiodriver_set_direction(ctx, req);
ret = gpiodriver_set_direction(ctx, gen_message.req);
break;

case GPIOReadCmd:
ret = gpiodriver_read(req);
ret = gpiodriver_read(gen_message.req);
break;

case GPIOSetIntCmd:
ret = gpiodriver_set_int(ctx, local_process_id, req);
ret = gpiodriver_set_int(ctx, local_process_id, gen_message.req);
break;

case GPIORemoveIntCmd:
ret = gpiodriver_remove_int(ctx, req);
ret = gpiodriver_remove_int(ctx, gen_message.req);
break;

case GPIOCloseCmd:
Expand All @@ -521,8 +526,7 @@ static NativeHandlerResult consume_gpio_mailbox(Context *ctx)
if (UNLIKELY(memory_ensure_free_with_roots(ctx, 3, 1, &ret, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
ret_msg = OUT_OF_MEMORY_ATOM;
} else {
term ref = term_get_tuple_element(msg, 1);
ret_msg = create_pair(ctx, ref, ret);
ret_msg = create_pair(ctx, gen_message.ref, ret);
}

globalcontext_send_message(ctx->global, local_process_id, ret_msg);
Expand Down
30 changes: 16 additions & 14 deletions src/platforms/esp32/components/avm_builtins/i2c_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -546,45 +546,48 @@ static term create_pair(Context *ctx, term term1, term term2)
static NativeHandlerResult i2cdriver_consume_mailbox(Context *ctx)
{
Message *message = mailbox_first(&ctx->mailbox);
term msg = message->message;
term pid = term_get_tuple_element(msg, 0);
term req = term_get_tuple_element(msg, 2);
GenMessage gen_message;
if (UNLIKELY(port_parse_gen_message(message->message, &gen_message) != GenMessageParseOk)) {
ESP_LOGW(TAG, "Received invalid message.");
mailbox_remove_message(&ctx->mailbox, &ctx->heap);
return NativeContinue;
}

#ifdef ENABLE_TRACE
TRACE("message: ");
term_display(stdout, msg, ctx);
TRACE("\n");
#endif

term cmd_term = term_get_tuple_element(req, 0);
term cmd_term = term_get_tuple_element(gen_message.req, 0);

int local_process_id = term_to_local_process_id(pid);
int local_process_id = term_to_local_process_id(gen_message.pid);

term ret;

enum i2c_cmd cmd = interop_atom_term_select_int(cmd_table, cmd_term, ctx->global);
switch (cmd) {
case I2CBeginTransmissionCmd:
ret = i2cdriver_begin_transmission(ctx, pid, req);
ret = i2cdriver_begin_transmission(ctx, gen_message.pid, gen_message.req);
break;

case I2CEndTransmissionCmd:
ret = i2cdriver_end_transmission(ctx, pid);
ret = i2cdriver_end_transmission(ctx, gen_message.pid);
break;

case I2CWriteByteCmd:
ret = i2cdriver_write_byte(ctx, pid, req);
ret = i2cdriver_write_byte(ctx, gen_message.pid, gen_message.req);
break;

case I2CReadBytesCmd:
ret = i2cdriver_read_bytes(ctx, pid, req);
ret = i2cdriver_read_bytes(ctx, gen_message.pid, gen_message.req);
break;

case I2CWriteBytesCmd:
if (term_get_tuple_arity(req) == 2) {
ret = i2cdriver_qwrite_bytes(ctx, pid, req);
if (term_get_tuple_arity(gen_message.req) == 2) {
ret = i2cdriver_qwrite_bytes(ctx, gen_message.pid, gen_message.req);
} else {
ret = i2cdriver_write_bytes(ctx, pid, req);
ret = i2cdriver_write_bytes(ctx, gen_message.pid, gen_message.req);
}
break;
case I2CCloseCmd:
Expand All @@ -601,8 +604,7 @@ static NativeHandlerResult i2cdriver_consume_mailbox(Context *ctx)
if (UNLIKELY(memory_ensure_free_with_roots(ctx, 3, 1, &ret, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
ret_msg = OUT_OF_MEMORY_ATOM;
} else {
term ref = term_get_tuple_element(msg, 1);
ret_msg = create_pair(ctx, ref, ret);
ret_msg = create_pair(ctx, gen_message.ref, ret);
}

globalcontext_send_message(ctx->global, local_process_id, ret_msg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ static NativeHandlerResult consume_mailbox(Context *ctx)
return NativeContinue;
}

//TODO: port this code to standard port (and gen_message)
term pid = term_get_tuple_element(msg, 0);
term ref = term_get_tuple_element(msg, 1);
term cmd = term_get_tuple_element(msg, 2);
Expand Down
Loading

0 comments on commit 76d4f8c

Please sign in to comment.