-
Notifications
You must be signed in to change notification settings - Fork 33
SerialServer: allow clients to be non-sequential #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
chrisguikema
wants to merge
3
commits into
seL4:master
Choose a base branch
from
chrisguikema:serial_server_client_badges
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+195
−29
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,20 +24,24 @@ | |
| #include "server_virtqueue.h" | ||
|
|
||
| #define ESCAPE_CHAR '@' | ||
| #define MAX_CLIENTS 12 | ||
| #define MAX_CLIENTS 10 | ||
| #define MAX_BADGE MAX_CLIENTS | ||
| #define CLIENT_OUTPUT_BUFFER_SIZE 4096 | ||
|
|
||
| #define CTRL_C 0x03 | ||
| #define CTRL_Z 0x1A | ||
|
|
||
| /* TODO: have the MultiSharedData template generate a header with these */ | ||
| void getchar_emit(unsigned int id) WEAK; | ||
| seL4_Word getchar_enumerate_badge(unsigned int id) WEAK; | ||
| unsigned int getchar_num_badges() WEAK; | ||
| void *getchar_buf(unsigned int id) WEAK; | ||
| void *processed_batch_buf(unsigned int id) WEAK; | ||
| void *raw_batch_buf(unsigned int id) WEAK; | ||
| int getchar_largest_badge(void) WEAK; | ||
| enum putchar_interfaces { | ||
| RAW_PUTCHAR, | ||
| PROCESSED_PUTCHAR, | ||
| RAW_BATCH, | ||
| PROCESSED_BATCH, | ||
| NUM_PUTCHAR_INTERFACES, | ||
| }; | ||
|
|
||
| typedef seL4_Word(*enumerate_badge_t)(unsigned int); | ||
| typedef unsigned int (*num_badges_t)(void); | ||
| typedef void *(*get_buf_t)(seL4_Word); | ||
|
|
||
| typedef struct getchar_buffer { | ||
| uint32_t head; | ||
|
|
@@ -53,6 +57,18 @@ typedef struct getchar_client { | |
| uint32_t last_head; | ||
| } getchar_client_t; | ||
|
|
||
| typedef struct putchar_client { | ||
| unsigned int client_id; | ||
| client_buffer_t *buf; | ||
| } putchar_client_t; | ||
|
|
||
| typedef struct putchar_info { | ||
| enumerate_badge_t enumerate_badge; | ||
| num_badges_t num_badges; | ||
| get_buf_t get_buf; | ||
| const char *name; | ||
| } putchar_info_t; | ||
|
|
||
| static ps_io_ops_t io_ops; | ||
|
|
||
| static int last_out = -1; | ||
|
|
@@ -68,18 +84,46 @@ static int has_data = 0; | |
| static int num_getchar_clients = 0; | ||
| static getchar_client_t *getchar_clients = NULL; | ||
|
|
||
| static putchar_client_t **putchar_clients; | ||
| static int num_putchar_clients[NUM_PUTCHAR_INTERFACES]; | ||
|
|
||
| static putchar_info_t putchar_information[NUM_PUTCHAR_INTERFACES] = { | ||
| { | ||
| .num_badges = raw_putchar_num_badges, | ||
| .enumerate_badge = raw_putchar_enumerate_badge, | ||
| .get_buf = NULL, | ||
| .name = "raw_putchar", | ||
| }, | ||
| { | ||
| .num_badges = processed_putchar_num_badges, | ||
| .enumerate_badge = processed_putchar_enumerate_badge, | ||
| .get_buf = NULL, | ||
| .name = "processed_putchar", | ||
| }, | ||
| { | ||
| .num_badges = raw_batch_num_badges, | ||
| .enumerate_badge = raw_batch_enumerate_badge, | ||
| .get_buf = raw_batch_buf, | ||
| .name = "raw_batch", | ||
| }, | ||
| { | ||
| .num_badges = processed_batch_num_badges, | ||
| .enumerate_badge = processed_batch_enumerate_badge, | ||
| .get_buf = processed_batch_buf, | ||
| .name = "processed_batch", | ||
| }, | ||
| }; | ||
|
|
||
| /* We predefine output colours for clients */ | ||
| const char *all_output_colours[2][MAX_CLIENTS] = { | ||
| { | ||
| /* Processed streams */ | ||
| ANSI_COLOR(RED), | ||
| ANSI_COLOR(GREEN), | ||
| ANSI_COLOR(BLUE), | ||
| ANSI_COLOR(MAGENTA), | ||
| ANSI_COLOR(YELLOW), | ||
| ANSI_COLOR(CYAN), | ||
| ANSI_COLOR(RED, BOLD) | ||
| ANSI_COLOR(GREEN, BOLD), | ||
| ANSI_COLOR(BLUE, BOLD), | ||
| ANSI_COLOR(MAGENTA, BOLD), | ||
| ANSI_COLOR(YELLOW, BOLD), | ||
|
|
@@ -88,13 +132,11 @@ const char *all_output_colours[2][MAX_CLIENTS] = { | |
| { | ||
| /* Raw streams */ | ||
| ANSI_COLOR2(RED, WHITE), | ||
| ANSI_COLOR2(GREEN, WHITE), | ||
| ANSI_COLOR2(BLUE, WHITE), | ||
| ANSI_COLOR2(MAGENTA, WHITE), | ||
| ANSI_COLOR2(YELLOW, WHITE), | ||
| ANSI_COLOR2(CYAN, WHITE), | ||
| ANSI_COLOR2(RED, WHITE, BOLD) | ||
| ANSI_COLOR2(GREEN, WHITE, BOLD), | ||
| ANSI_COLOR2(BLUE, WHITE, BOLD), | ||
| ANSI_COLOR2(MAGENTA, WHITE, BOLD), | ||
| ANSI_COLOR2(YELLOW, WHITE, BOLD), | ||
|
|
@@ -176,7 +218,7 @@ static int is_newline(const uint8_t *c) | |
| return (c[0] == '\r' && c[1] == '\n') || (c[0] == '\n' && c[1] == '\r'); | ||
| } | ||
|
|
||
| static int active_client = 0; | ||
| static int active_client = -2; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe make |
||
| static int active_multiclients = 0; | ||
|
|
||
| /* Try coalescing client output. This is intended for use with | ||
|
|
@@ -313,9 +355,40 @@ static void internal_putchar(int b, int c) | |
| error = serial_unlock(); | ||
| } | ||
|
|
||
| static getchar_client_t *getchar_client_from_badge(int badge) | ||
| { | ||
| for (int i = 0; i < num_getchar_clients; i++) { | ||
| if (getchar_clients[i].client_id == badge) { | ||
| return &getchar_clients[i]; | ||
| } | ||
| } | ||
| return NULL; | ||
| } | ||
|
|
||
| static putchar_client_t *putchar_client_from_badge(int badge, int interface) | ||
| { | ||
| if (interface >= NUM_PUTCHAR_INTERFACES) { | ||
| ZF_LOGW("Interface number %d is invalid", interface); | ||
| return NULL; | ||
| } | ||
| putchar_client_t *putchar_intf_clients = putchar_clients[interface]; | ||
| int num_clients = num_putchar_clients[interface]; | ||
|
|
||
| for (int i = 0; i < num_clients; i++) { | ||
| if (putchar_intf_clients[i].client_id == badge) { | ||
| return &putchar_intf_clients[i]; | ||
| } | ||
| } | ||
| return NULL; | ||
| } | ||
|
|
||
| static void internal_raw_putchar(int id, int c) | ||
| { | ||
| getchar_client_t *client = &getchar_clients[id]; | ||
| getchar_client_t *client = getchar_client_from_badge(id); | ||
| if (NULL == client) { | ||
| ZF_LOGW("Client with badge %d not found", id); | ||
| return; | ||
| } | ||
| uint32_t next_tail = (client->buf->tail + 1) % sizeof(client->buf->buf); | ||
| if (next_tail == client->buf->head) { | ||
| /* full */ | ||
|
|
@@ -406,24 +479,29 @@ static void handle_char(uint8_t c) | |
| last_out = -1; | ||
| printf(COLOR_RESET "\r\n --- SerialServer help ---" | ||
| "\r\n Escape char: %c" | ||
| "\r\n 0 - %-2d switches input to that client" | ||
| "\r\n # - switches to client #" | ||
| "\r\n ? shows this help" | ||
| "\r\n s dump seL4 scheduler (depends on CONFIG_DEBUG_BUILD)" | ||
| "\r\n m simultaneous multi-client input" | ||
| "\r\n d switch between debugging modes" | ||
| "\r\n 0: no debugging" | ||
| "\r\n 1: debug multi-input mode output coalescing" | ||
| "\r\n 2: debug flush_buffer_line" | ||
| "\r\n", ESCAPE_CHAR, num_getchar_clients - 1); | ||
| "\r\n", ESCAPE_CHAR); | ||
| statemachine = 1; | ||
| break; | ||
| default: | ||
| last_out = -1; | ||
| statemachine = 1; | ||
| if (c >= '0' && c < '0' + num_getchar_clients) { | ||
| if (c >= '0' && c <= '9') { | ||
| int client = c - '0'; | ||
| printf(COLOR_RESET "\r\nSwitching input to %d\r\n", client); | ||
| active_client = client; | ||
| int badge = client + 1; | ||
| if (NULL == getchar_client_from_badge(badge)) { | ||
| printf(COLOR_RESET "\r\nClient %d is not valid\r\n", client); | ||
| } else { | ||
| printf(COLOR_RESET "\r\nSwitching input to %d\r\n", client); | ||
| active_client = badge; | ||
| } | ||
| } else { | ||
| printf(COLOR_RESET "\r\nInvalid SerialServer command: %c" | ||
| "\r\nType %c? for help" | ||
|
|
@@ -523,12 +601,47 @@ void pre_init(void) | |
| getchar_clients = calloc(num_getchar_clients, sizeof(getchar_client_t)); | ||
| for (int i = 0; i < num_getchar_clients; i++) { | ||
| unsigned int badge = getchar_enumerate_badge(i); | ||
| assert(badge <= num_getchar_clients); | ||
| if (badge > MAX_BADGE || !badge) { | ||
| ZF_LOGE("getchar badge %d invalid. " | ||
| "Set client's interface_attributes to a value " | ||
| "between 1 and %d", badge, MAX_BADGE); | ||
| continue; | ||
| } | ||
| getchar_clients[i].client_id = badge; | ||
| getchar_clients[i].buf = getchar_buf(badge); | ||
| getchar_clients[i].last_head = -1; | ||
|
|
||
| if (-2 == active_client) { | ||
| active_client = badge; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| putchar_clients = calloc(NUM_PUTCHAR_INTERFACES, sizeof(putchar_client_t *)); | ||
| ZF_LOGF_IF(NULL == putchar_clients, "Failed to calloc putchar clients"); | ||
|
|
||
| for (int i = 0; i < NUM_PUTCHAR_INTERFACES; i++) { | ||
| putchar_info_t putchar_info = putchar_information[i]; | ||
| if (putchar_info.num_badges) { | ||
| num_putchar_clients[i] = putchar_info.num_badges(); | ||
| putchar_clients[i] = calloc(num_putchar_clients[i], sizeof(putchar_client_t)); | ||
| ZF_LOGF_IF(NULL == putchar_clients[i], "Failed to calloc putchar client entry"); | ||
| for (int j = 0; j < num_putchar_clients[i]; j++) { | ||
| unsigned int badge = putchar_info.enumerate_badge(j); | ||
| if (badge > MAX_BADGE || !badge) { | ||
| ZF_LOGE("%s badge %d invalid. " | ||
| "Set client's interface_attributes to a value " | ||
| "between 1 and %d", putchar_info.name, badge, MAX_BADGE); | ||
| continue; | ||
| } | ||
| putchar_clients[i][j].client_id = badge; | ||
| if (putchar_info.get_buf) { | ||
| putchar_clients[i][j].buf = putchar_info.get_buf(badge); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| plat_post_init(&(io_ops.irq_ops)); | ||
| /* Start regular heartbeat of 500ms */ | ||
| timeout_periodic(0, 500000000); | ||
|
|
@@ -549,30 +662,49 @@ seL4_Word processed_putchar_get_sender_id(void) WEAK; | |
| void processed_putchar_putchar(int c) | ||
| { | ||
| seL4_Word n = processed_putchar_get_sender_id(); | ||
| putchar_client_t *client = putchar_client_from_badge(n, PROCESSED_PUTCHAR); | ||
| if (NULL == client) { | ||
| ZF_LOGW("Client with badge %d not found", n); | ||
| return; | ||
| } | ||
|
|
||
| if (c == '\n') { | ||
| internal_putchar(n, '\r'); | ||
| internal_putchar(client->client_id - 1, '\r'); | ||
| } | ||
| internal_putchar((int)n, c); | ||
| internal_putchar((int)client->client_id - 1, c); | ||
| } | ||
|
|
||
| seL4_Word raw_putchar_get_sender_id(void) WEAK; | ||
| void raw_putchar_putchar(int c) | ||
| { | ||
| seL4_Word n = raw_putchar_get_sender_id(); | ||
| internal_putchar((int)n + MAX_CLIENTS, c); | ||
| putchar_client_t *client = putchar_client_from_badge(n, RAW_PUTCHAR); | ||
| if (NULL == client) { | ||
| ZF_LOGW("Client with badge %d not found", n); | ||
| return; | ||
| } | ||
|
|
||
| internal_putchar((int)client->client_id - 1 + MAX_CLIENTS, c); | ||
| } | ||
|
|
||
| seL4_Word processed_batch_get_sender_id(void) WEAK; | ||
| void processed_batch_batch(void) | ||
| { | ||
| seL4_Word n = processed_batch_get_sender_id(); | ||
| client_buffer_t *putchar_buf = processed_batch_buf(n); | ||
| putchar_client_t *client = putchar_client_from_badge(n, PROCESSED_BATCH); | ||
| if (NULL == client) { | ||
| ZF_LOGW("Client with badge %d not found", n); | ||
| return; | ||
| } | ||
|
|
||
| client_buffer_t *putchar_buf = client->buf; | ||
|
|
||
| while (putchar_buf->head != putchar_buf->tail) { | ||
| char ch = putchar_buf->buf[putchar_buf->head]; | ||
| if (ch == '\n') { | ||
| internal_putchar(n, '\r'); | ||
| internal_putchar(client->client_id - 1, '\r'); | ||
| } | ||
| internal_putchar((int)n, ch); | ||
| internal_putchar((int)client->client_id - 1, ch); | ||
| putchar_buf->head = (putchar_buf->head + 1) % sizeof(putchar_buf->buf); | ||
| } | ||
| } | ||
|
|
@@ -581,10 +713,17 @@ seL4_Word raw_batch_get_sender_id(void) WEAK; | |
| void raw_batch_batch(void) | ||
| { | ||
| seL4_Word n = raw_batch_get_sender_id(); | ||
| client_buffer_t *putchar_buf = raw_batch_buf(n); | ||
| putchar_client_t *client = putchar_client_from_badge(n, RAW_BATCH); | ||
| if (NULL == client) { | ||
| ZF_LOGW("Client with badge %d not found", n); | ||
| return; | ||
| } | ||
|
|
||
| client_buffer_t *putchar_buf = client->buf; | ||
|
|
||
| while (putchar_buf->head != putchar_buf->tail) { | ||
| char ch = putchar_buf->buf[putchar_buf->head]; | ||
| internal_putchar((int)n + MAX_CLIENTS, ch); | ||
| internal_putchar((int)client->client_id - 1 + MAX_CLIENTS, ch); | ||
| putchar_buf->head = (putchar_buf->head + 1) % sizeof(putchar_buf->buf); | ||
| } | ||
| } | ||
|
|
||
21 changes: 21 additions & 0 deletions
21
components/SerialServer/templates/seL4SerialServer.template.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| /* | ||
| * Copyright 2022, DornerWorks | ||
| * | ||
| * SPDX-License-Identifier: BSD-2-Clause | ||
| */ | ||
|
|
||
| void getchar_emit(unsigned int id) WEAK; | ||
| seL4_Word getchar_enumerate_badge(unsigned int id) WEAK; | ||
| seL4_Word raw_putchar_enumerate_badge(unsigned int id) WEAK; | ||
| seL4_Word raw_batch_enumerate_badge(unsigned int id) WEAK; | ||
| seL4_Word processed_putchar_enumerate_badge(unsigned int id) WEAK; | ||
| seL4_Word processed_batch_enumerate_badge(unsigned int id) WEAK; | ||
| unsigned int getchar_num_badges() WEAK; | ||
| unsigned int raw_putchar_num_badges() WEAK; | ||
| unsigned int raw_batch_num_badges() WEAK; | ||
| unsigned int processed_putchar_num_badges() WEAK; | ||
| unsigned int processed_batch_num_badges() WEAK; | ||
| void *getchar_buf(seL4_Word client_id) WEAK; | ||
| void *processed_batch_buf(seL4_Word client_id) WEAK; | ||
| void *raw_batch_buf(seL4_Word client_id) WEAK; | ||
| int getchar_largest_badge(void) WEAK; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a note in the code here, what drives this limit? I think it would help to get the background for people new to the code. Increasing this is not trivially possible.