From 5850f35d954a60614962153295b63e7556640c85 Mon Sep 17 00:00:00 2001 From: Aurel Feer Date: Tue, 31 May 2022 17:33:55 +0200 Subject: [PATCH] echo command somewhat working --- include/aos/shelly_client.h | 18 ++++++----- lib/aos/shelly_client.c | 22 +++++++++++-- usr/shelly/shelly.c | 61 +++++++++++++++++++++++++++++++------ usr/shelly/shelly.h | 8 +++++ usr/shelly/shelly_cmd.c | 48 +++++++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 21 deletions(-) create mode 100644 usr/shelly/shelly_cmd.c diff --git a/include/aos/shelly_client.h b/include/aos/shelly_client.h index 8592ca6..4c382b0 100644 --- a/include/aos/shelly_client.h +++ b/include/aos/shelly_client.h @@ -12,14 +12,6 @@ #endif -struct shelly_client_state { - struct ump_send_chan *send_chan; - struct ump_recv_chan *recv_chan; - - struct capref shared_frame; - bool request_ongoing; -}; - enum shelly_msg_type { SHELLY_MSG_PUTCHAR, SHELLY_MSG_GETCHAR, @@ -31,6 +23,16 @@ struct shelly_header { char character; }; +struct shelly_client_state { + struct ump_send_chan *send_chan; + struct ump_recv_chan *recv_chan; + + struct capref shared_frame; + bool request_ongoing; + struct shelly_header * current_request; + + char * buf; +}; errval_t shelly_client_init(void); errval_t shelly_client_getchar(struct aos_rpc * rpc, char * ret); diff --git a/lib/aos/shelly_client.c b/lib/aos/shelly_client.c index 6680547..b3a1c57 100644 --- a/lib/aos/shelly_client.c +++ b/lib/aos/shelly_client.c @@ -16,6 +16,8 @@ errval_t shelly_client_init(void) { waitset_init(&ws); state.request_ongoing = false; + state.buf = NULL; + state.current_request = NULL; //connect to shelly struct aos_rpc *rpc = aos_rpc_get_init_channel(); @@ -41,15 +43,24 @@ static void handle_payload(void *arg, size_t payload_size, void *payload) { } static void handle_response(void *arg, size_t header_size, void *header_buf, size_t payload_size) { - // struct shelly_header *header = header_buf; + struct shelly_header *header = header_buf; SHELLY_CLIENT_DEBUG("[handle_response]\n"); + if (state.current_request->type == SHELLY_MSG_GETCHAR) { + *state.buf = header->character; + } else if (state.current_request->type == SHELLY_MSG_PUTCHAR) { + //nothing to do + } else { + SHELLY_CLIENT_DEBUG("[handle_response] unexpected request type"); + } + ump_recv_payload(state.recv_chan, NULL, handle_payload, NULL); } static void handle_send_completed(void *arg, struct ump_send_queue_entry *entry) { SHELLY_CLIENT_DEBUG("[handle_send_completed]\n"); free((void *)entry->header); + free((void *)entry->payload); free(entry); } @@ -58,14 +69,16 @@ errval_t shelly_client_getchar(struct aos_rpc * rpc, char * ret) { SHELLY_CLIENT_DEBUG("[shelly_client_getchar]\n"); state.request_ongoing = true; + state.buf = ret; struct shelly_header * header = malloc(sizeof(struct shelly_header)); if (header == NULL) return LIB_ERR_MALLOC_FAIL; + state.current_request = header; struct ump_send_queue_entry *entry = malloc(sizeof(struct ump_send_queue_entry)); if (entry == NULL) return LIB_ERR_MALLOC_FAIL; header->type = SHELLY_MSG_GETCHAR; - header->character = '\0'; + header->character = 0; ump_send(state.send_chan, entry, sizeof(struct shelly_header), header, 0, NULL, handle_send_completed, NULL); @@ -80,6 +93,7 @@ errval_t shelly_client_getchar(struct aos_rpc * rpc, char * ret) { abort(); } } + SHELLY_CLIENT_DEBUG("[shelly_client_getchar] done\n"); return SYS_ERR_OK; } @@ -92,13 +106,14 @@ errval_t shelly_client_putchar(struct aos_rpc * rpc, char input) { struct shelly_header * header = malloc(sizeof(struct shelly_header)); if (header == NULL) return LIB_ERR_MALLOC_FAIL; + state.current_request = header; struct ump_send_queue_entry *entry = malloc(sizeof(struct ump_send_queue_entry)); if (entry == NULL) return LIB_ERR_MALLOC_FAIL; header->type = SHELLY_MSG_PUTCHAR; header->character = input; - ump_send(state.send_chan, entry, sizeof(struct shelly_header), header, 1, &input, handle_send_completed, NULL); + ump_send(state.send_chan, entry, sizeof(struct shelly_header), header, 0, NULL, handle_send_completed, NULL); // register response handler ump_recv_header(state.recv_chan, handle_response, NULL); @@ -111,6 +126,7 @@ errval_t shelly_client_putchar(struct aos_rpc * rpc, char input) { abort(); } } + SHELLY_CLIENT_DEBUG("[shelly_client_getchar] done\n"); return SYS_ERR_OK; } diff --git a/usr/shelly/shelly.c b/usr/shelly/shelly.c index 3c13ef2..4c2c285 100644 --- a/usr/shelly/shelly.c +++ b/usr/shelly/shelly.c @@ -22,10 +22,12 @@ //state that is shared for all clients static struct shelly_st_global * global_state; +#include "shelly_cmd.c" + __attribute__((__used__)) -static void shelly_interrupt_handler(void * arg) { +static void handle_lpuart_interrupt(void * arg) { errval_t err; - SHELLY_DEBUG("[shelly_interrupt_handler]\n"); + SHELLY_DEBUG("[handle_lpuart_interrupt]\n"); assert(global_state); char input_char; @@ -34,6 +36,28 @@ static void shelly_interrupt_handler(void * arg) { err = lpuart_putchar(global_state->uart_s, input_char); if (err_is_fail(err)) USER_PANIC_ERR(err, "while trying to put character"); + + if (input_char == ASCII_NL || input_char == ASCII_EOF || input_char == ASCII_CR) { + err = lpuart_putchar(global_state->uart_s, '\n'); + if (err_is_fail(err)) USER_PANIC_ERR(err, "while trying to put character"); + + global_state->buf[global_state->buffer_i] = '\0'; + global_state->buffer_i += 1; + + handle_shelly_cmd(global_state->buf, global_state->buffer_i); + + global_state->buffer_i = 0; + + err = lpuart_putchar(global_state->uart_s, ASCII_EOT); + if (err_is_fail(err)) USER_PANIC_ERR(err, "while trying to put character"); + err = lpuart_putchar(global_state->uart_s, '>'); + if (err_is_fail(err)) USER_PANIC_ERR(err, "while trying to put character"); + } else { + global_state->buf[global_state->buffer_i] = input_char; + global_state->buffer_i += 1; + global_state->buffer_i %= SHELLY_BUF_SIZE; + } + SHELLY_DEBUG("[handle_lpuart_interrupt] done\n"); } static void handle_send_completed(void *arg, struct ump_send_queue_entry *entry) { @@ -45,6 +69,7 @@ static void handle_send_completed(void *arg, struct ump_send_queue_entry *entry) static void send_response(struct shelly_st_local * local_state, errval_t err, size_t payload_size, void *payload) { assert(local_state); + SHELLY_DEBUG("[send_response]\n"); struct shelly_header * header = malloc(sizeof(struct shelly_header)); assert(header); header->type = SHELLY_MSG_RESPONSE; @@ -62,6 +87,7 @@ static void send_response(struct shelly_st_local * local_state, errval_t err, si handle_send_completed, NULL ); + SHELLY_DEBUG("[send_response] done\n"); } static void handle_client_request(void *arg, size_t header_size, void *header_buf, size_t payload_size); @@ -69,9 +95,13 @@ static void handle_payload(void *arg, size_t payload_size, void *payload) { struct shelly_st_local * local_state = arg; assert(local_state); assert(global_state); + + SHELLY_DEBUG("[handle_payload]\n"); + // SHELLY_DEBUG("[handle_payload] client_id=%d\n", local_state->client_id); // listen for the next request on this channel ump_recv_header(local_state->recv_chan, handle_client_request, local_state); + SHELLY_DEBUG("[handle_payload] done\n"); } static void handle_client_request(void *arg, size_t header_size, void *header_buf, size_t payload_size) { @@ -80,6 +110,8 @@ static void handle_client_request(void *arg, size_t header_size, void *header_bu assert(local_state); assert(global_state); + SHELLY_DEBUG("[handle_client_request]\n"); + struct shelly_header * header = (struct shelly_header *) header_buf; if (header->type == SHELLY_MSG_GETCHAR) { @@ -91,12 +123,16 @@ static void handle_client_request(void *arg, size_t header_size, void *header_bu if (err_is_fail(err)) USER_PANIC_ERR(err, "while trying to put character"); } + SHELLY_DEBUG("[handle_client_request] send_response\n"); send_response(local_state, SYS_ERR_OK, 0, NULL); // skip payload + SHELLY_DEBUG("[handle_client_request] skip payload\n"); ump_recv_payload(local_state->recv_chan, NULL, handle_payload, local_state); + SHELLY_DEBUG("[handle_client_request] done\n"); } +__attribute__((__used__)) static errval_t connection_callback(void *arg, struct capref cap) { errval_t err; @@ -112,7 +148,7 @@ static errval_t connection_callback(void *arg, struct capref cap) { // we can run the server on the default waitset since we are dispatching on // it for listening to connections anyways - err = ump_chan_init(UMP_ROLE_SERVER, &local_state->send_chan, &local_state->recv_chan, sizeof(struct shelly_header), cap, get_default_waitset()); + err = ump_chan_init(UMP_ROLE_SERVER, &local_state->send_chan, &local_state->recv_chan, sizeof(struct shelly_header), cap, global_state->ws); if (err_is_fail(err)) return err; // SHELLY_DEBUG("[connection_callback] local_state=%p\n", local_state); @@ -132,6 +168,10 @@ int main(int argc, char *argv[]) global_state = calloc(sizeof(struct shelly_st_global), 1); assert(global_state); + global_state->num_clients = 0; + global_state->buffer_i = 0; + global_state->ws = get_default_waitset(); + //afeer: map lpuart registers struct capref cap_arg0 = { .cnode = cnode_arg, @@ -179,8 +219,9 @@ int main(int argc, char *argv[]) debug_print_cap_at_capref(buf, 256, inter_cap); debug_printf(buf); - struct waitset * ws = get_default_waitset(); - err = inthandler_setup(inter_cap, ws, MKCLOSURE(shelly_interrupt_handler, NULL)); + // struct waitset * ws = calloc(sizeof(struct waitset), 1); + // waitset_init(ws); + err = inthandler_setup(inter_cap, global_state->ws, MKCLOSURE(handle_lpuart_interrupt, NULL)); if (err_is_fail(err)) USER_PANIC_ERR(err, "couln't setup interrupt handler"); SHELLY_DEBUG("setup interrupt handler\n"); @@ -195,13 +236,13 @@ int main(int argc, char *argv[]) SHELLY_DEBUG("enabled lpuart interrupt\n"); - SHELLY_DEBUG("registering as shelly server\n"); - struct ump_binding_server server; - err = ump_binding_register(&server, UMP_SERVER_SHELLY, connection_callback, NULL); - if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to register UMP server"); + // SHELLY_DEBUG("registering as shelly server\n"); + // struct ump_binding_server server; + // err = ump_binding_register(&server, UMP_SERVER_SHELLY, connection_callback, NULL); + // if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to register UMP server"); while (true) { - err = event_dispatch(ws); + err = event_dispatch(global_state->ws); if (err_is_fail(err)) { DEBUG_ERR(err, "in event_dispatch"); abort(); diff --git a/usr/shelly/shelly.h b/usr/shelly/shelly.h index 11c3440..039b823 100644 --- a/usr/shelly/shelly.h +++ b/usr/shelly/shelly.h @@ -22,9 +22,16 @@ #include #include +#define ASCII_NL 10 // < new line +#define ASCII_CR 13 // < carriage return +#define ASCII_EOF 4 // < end of file +#define ASCII_EOT 3 // < end of text + #define SHELLY_BUF_SIZE 2048 //state that is shared for all clients struct shelly_st_global { + struct waitset * ws; + void * lpuart_base; // < virtual address of the lpuart device registers void * gic_base; // < virtual address of the gic device registers @@ -33,6 +40,7 @@ struct shelly_st_global { u_int32_t num_clients; char buf[SHELLY_BUF_SIZE]; + size_t buffer_i; }; //state that different for each client diff --git a/usr/shelly/shelly_cmd.c b/usr/shelly/shelly_cmd.c new file mode 100644 index 0000000..169ec28 --- /dev/null +++ b/usr/shelly/shelly_cmd.c @@ -0,0 +1,48 @@ +#include +#include "shelly.h" + + + +static void shelly_cmd_echo(char* argv[], int argc) { + errval_t err; + SHELLY_DEBUG("[shelly_cmd_echo] argc=%d\n", argc); + + for (int i = 0; argv[1][i] != '\0'; ++i) { + err = lpuart_putchar(global_state->uart_s, argv[1][i]); + if (err_is_fail(err)) USER_PANIC_ERR(err, "while trying to put character"); + } + err = lpuart_putchar(global_state->uart_s, '\0'); + if (err_is_fail(err)) USER_PANIC_ERR(err, "while trying to put character"); +} + +static void handle_shelly_cmd(char* str, size_t len) { + SHELLY_DEBUG("[handle_shelly_cmd] len=%d\n", len); + + if (len <= 1) { + return; + } + + int argc = 1; + for (int i = 0; i < len; ++i) { + if (str[i] == ' ') ++argc; + } + char * argv[argc]; + + const char delim[2] = " "; + + for (int i = 0; i < argc; ++i) { + if (i == 0) { + argv[i] = strtok(str, delim); + } else { + argv[i] = strtok(NULL, delim); + } + SHELLY_DEBUG("[handle_shelly_cmd] arg[%d]=%s\n", i, argv[i]); + } + + if (strcmp(argv[0], "echo") == 0) { + shelly_cmd_echo(argv, argc); + } else { + SHELLY_DEBUG("unknown command %s\n", argv[0]); + } +} +