[#59550] external_control_client: Add proper handling of errors with data
diff --git a/tools/external_control_client/include/renode_api.h b/tools/external_control_client/include/renode_api.h
index 72f7c91..8d67831 100644
--- a/tools/external_control_client/include/renode_api.h
+++ b/tools/external_control_client/include/renode_api.h
@@ -15,6 +15,8 @@
ERR_NOT_CONNECTED,
ERR_PERIPHERAL_INIT_FAILED,
ERR_TIMEOUT,
+ ERR_COMMAND_FAILED,
+ ERR_NO_ERROR = -1,
} renode_error_code;
typedef struct {
diff --git a/tools/external_control_client/lib/renode_api.c b/tools/external_control_client/lib/renode_api.c
index 097bb69..b45de96 100644
--- a/tools/external_control_client/lib/renode_api.c
+++ b/tools/external_control_client/lib/renode_api.c
@@ -57,8 +57,6 @@
#define ERROR_DYNAMIC_MESSAGE_SIZE 0x400
-static renode_error_t *create_fatal_error_static(char *message);
-
static void *xmalloc(size_t size)
{
void *result = malloc(size);
@@ -66,27 +64,27 @@
return result;
}
-static renode_error_t *create_connection_failed_error(char *message)
+static renode_error_t *create_error_static(renode_error_code code, char *message)
{
renode_error_t *error = xmalloc(sizeof(renode_error_t));
- error->code = ERR_CONNECTION_FAILED;
+ error->code = code;
error->flags = 0;
error->message = message;
error->data = NULL;
return error;
}
-static renode_error_t *create_fatal_error_static(char *message)
+static renode_error_t *create_error_dynamic(renode_error_code code, char *message)
{
- renode_error_t *error = xmalloc(sizeof(renode_error_t));
- error->code = ERR_FATAL;
- error->flags = 0;
- error->message = message;
- error->data = NULL;
+ renode_error_t *error = create_error_static(code, message);
+ error->flags |= ERROR_FREE_MESSAGE;
return error;
}
-static renode_error_t *create_fatal_error(char *fmt, ...)
+#define create_connection_failed_error(message) create_error_static(ERR_COMMAND_FAILED, (message))
+#define create_fatal_error_static(message) create_error_static(ERR_FATAL, (message))
+
+static renode_error_t *create_error(renode_error_code code, char *fmt, ...)
{
char *message = xmalloc(ERROR_DYNAMIC_MESSAGE_SIZE);
va_list ap;
@@ -94,11 +92,14 @@
vsnprintf(message, ERROR_DYNAMIC_MESSAGE_SIZE, fmt, ap);
va_end(ap);
- renode_error_t *error = create_fatal_error_static(message);
+ renode_error_t *error = create_error_static(code, message);
error->flags |= ERROR_FREE_MESSAGE;
return error;
}
+#define create_fatal_error(...) create_error(ERR_FATAL, __VA_ARGS__)
+#define create_command_failed_error(...) create_error(ERR_COMMAND_FAILED, __VA_ARGS__)
+
void renode_free_error(renode_error_t *error)
{
if (error->flags & ERROR_FREE_MESSAGE) {
@@ -284,6 +285,7 @@
static renode_error_t *renode_receive_response(renode_t *renode, api_command_t expected_command, uint8_t *data_buffer, uint32_t buffer_size, uint32_t *data_size)
{
+ uint8_t *buffer = data_buffer;
uint8_t return_code;
uint8_t command;
*data_size = -1;
@@ -320,10 +322,15 @@
return_error_if_fails(renode_receive_bytes(renode, (uint8_t*)data_size, 4));
if (buffer_size < *data_size) {
- return create_fatal_error_static("Buffer too small");
+ if(return_code == SUCCESS_WITH_DATA)
+ {
+ return create_fatal_error_static("Buffer too small");
+ }
+ buffer = xmalloc(*data_size + 1);
+ buffer[*data_size] = '\0';
}
- return_error_if_fails(renode_receive_bytes(renode, data_buffer, *data_size));
+ return_error_if_fails(renode_receive_bytes(renode, buffer, *data_size));
break;
case INVALID_COMMAND:
case SUCCESS_WITHOUT_DATA:
@@ -333,8 +340,19 @@
return create_fatal_error_static(ERRMSG_UNEXPECTED_RETURN_CODE);
}
- if (return_code == FATAL_ERROR) {
- return create_fatal_error_static("received fatal error");
+ renode_error_code error_code = ERR_NO_ERROR;
+ switch (return_code) {
+ case COMMAND_FAILED:
+ error_code = ERR_COMMAND_FAILED;
+ break;
+ case FATAL_ERROR:
+ error_code = ERR_COMMAND_FAILED;
+ break;
+ default:
+ break;
+ }
+ if (error_code != ERR_NO_ERROR) {
+ return create_error_dynamic(error_code, (char *)buffer);
}
if (return_code == INVALID_COMMAND) {