From f2ac3923e7face810acf7d8e3ce2ca0608e8c843 Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Wed, 19 Mar 2008 02:54:27 +0100 Subject: [PATCH] refactoring --- tdc_parser.c | 139 ++++++++++++++++++++++++----------- tdc_parser.h | 7 +- tdc_store.c | 195 +++++++++++++++++++++++++++++++++++++++---------- tdc_store.h | 14 ++-- tdc_variable.c | 2 +- tdc_variable.h | 1 + 6 files changed, 269 insertions(+), 89 deletions(-) diff --git a/tdc_parser.c b/tdc_parser.c index a7c8cbd..c6d967a 100644 --- a/tdc_parser.c +++ b/tdc_parser.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -19,34 +20,6 @@ static gint socket_tag; static void (*socket_status_cb)(int status); static GByteArray *socket_stream; -static int check_size_helper(int available, - int packet_size, - int expected_base_size, - int packet_data_size, - const char *name) -{ - /* not enough data in buffer */ - if (available < expected_base_size) { - printf("received incomplete %s\n", name); - return 0; - } - - /* retest, after we know that packet_data_size is valid */ - if (available < (expected_base_size + packet_data_size)) { - printf("received incomplete %s\n", name); - return 0; - } - - /* packet has wrong size */ - if (packet_size != (expected_base_size + packet_data_size)) { - printf("received invalid %s\n", name); - return -1; - } - -// printf("received %s\n", name); - return packet_size; -} - static int tdcparser_send(struct tdc_pkt_header *pkt) { return write(socket_fd, pkt, pkt->size); @@ -73,6 +46,77 @@ int tdcparser_send_getvars(int address) return tdcparser_send(&pkt); } +int tdcparser_send_getvalue(int address, int id) +{ + struct tdc_getvalue_request pkt; + pkt.cmd = (address << 4) | TDC_GETVALUE; + pkt.size = sizeof(pkt); + pkt.id = (id & 0xFF); + + return tdcparser_send((struct tdc_pkt_header *)&pkt); +} + +int tdcparser_send_setvalue(int address, int id) +{ + struct tdc_var *var = tdcstore_get_var(address, id); + if (var == NULL) + return -1; + + int datasize = (var->flags & TDC_SIZEMASK); + + struct tdc_setvalue_request *pkt; + pkt = g_malloc0(sizeof(struct tdc_setvalue_request) + datasize); + + pkt->cmd = (address << 4) | TDC_SETVALUE; + pkt->size = sizeof(pkt) + datasize; + pkt->id = (id & 0xFF); + memcpy(pkt->data, &var->data, datasize); + + int retval = tdcparser_send((struct tdc_pkt_header *)pkt); + g_free(pkt); + + return retval; +} + +int tdcparser_send_request(int address, int interval, uint32_t *bitmap) +{ + struct tdc_reqvalues_request pkt; + pkt.cmd = (address << 4) | TDC_REQVALUES; + pkt.size = sizeof(pkt); + pkt.interval = interval; + memcpy(pkt.varmap, bitmap, sizeof(pkt.varmap)); + + return tdcparser_send((struct tdc_pkt_header *)&pkt); +} + +static int check_size_helper(int available, + int packet_size, + int expected_base_size, + int packet_data_size, + const char *name) +{ + /* not enough data in buffer */ + if (available < expected_base_size) { +// printf("received incomplete %s\n", name); + return 0; + } + + /* retest, after we know that packet_data_size is valid */ + if (available < (expected_base_size + packet_data_size)) { +// printf("received incomplete %s\n", name); + return 0; + } + + /* packet has wrong size */ + if (packet_size != (expected_base_size + packet_data_size)) { +// printf("received invalid %s\n", name); + return -1; + } + +// printf("received %s\n", name); + return packet_size; +} + static int tdcparser_parse(void) { int address = (socket_stream->data[0] & TDC_ADDRMASK) >> 4; @@ -92,7 +136,8 @@ static int tdcparser_parse(void) if (remove <= 0) break; - tdcstore_set_name(address, pkt->name); + tdcstore_create_board(address, pkt->name); + tdcstore_refresh_values(address, 250); tdcparser_send_getvars(address); } break; @@ -110,7 +155,7 @@ static int tdcparser_parse(void) if (remove <= 0) break; - tdcstore_set_var(address, tdcvar_create(pkt->id, pkt->flags, pkt->name, pkt->name_len)); + tdcstore_create_var(address, tdcvar_create(pkt->id, pkt->flags, pkt->name, pkt->name_len)); } break; case TDC_GETVALUE: { @@ -121,44 +166,52 @@ static int tdcparser_parse(void) case (TDC_GETVALUE | TDC_REPLY): { struct tdc_getvalue_reply *pkt = (struct tdc_getvalue_reply *)socket_stream->data; - - /* check base packet */ - remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVALUE REPLY"); - if (remove <= 0) + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVALUE REPLY (1)"); + /* at this point: invalid packet */ + if (remove > 0) + remove = 1; + /* retry with more bytes */ + else if (remove == 0) break; + /* base packet is complete, but exact size is wrong, get it from storage */ struct tdc_var *var = tdcstore_get_var(address, pkt->id); if (var == NULL) { printf("unknown variable %d\n", pkt->id); + remove = 1; break; } int varsize = (var->flags & TDC_SIZEMASK); - remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), varsize, "TDC_GETVALUE REPLY"); - // TODO: adjust remove on error (valid reply with invalid data size) - + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), varsize, "TDC_GETVALUE REPLY (2)"); if (remove <= 0) break; - tdcvar_update(var, pkt->data, varsize); - tdcstore_trigger_update(address, pkt->id); + tdcstore_update_var(address, pkt->id, pkt->data, varsize); } break; case TDC_SETVALUE: { struct tdc_setvalue_request *pkt = (struct tdc_setvalue_request *)socket_stream->data; - remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_SETVALUE"); - if (remove <= 0) + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_SETVALUE REPLY (1)"); + /* at this point: invalid packet */ + if (remove > 0) + remove = 1; + /* retry with more bytes */ + else if (remove == 0) break; + /* base packet is complete, but exact size is wrong, get it from storage */ struct tdc_var *var = tdcstore_get_var(address, pkt->id); if (var == NULL) { printf("unknown variable %d\n", pkt->id); + remove = 1; break; } int varsize = (var->flags & TDC_SIZEMASK); - remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), varsize, "TDC_GETVALUE REPLY"); - // TODO: adjust remove on error (valid reply with invalid data size) + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), varsize, "TDC_SETVALUE REPLY (2)"); + if (remove <= 0) + break; /* nothing to do */ } break; diff --git a/tdc_parser.h b/tdc_parser.h index 207c730..fee3e23 100644 --- a/tdc_parser.h +++ b/tdc_parser.h @@ -1,14 +1,19 @@ #ifndef TDC_PARSER_H_ #define TDC_PARSER_H_ +#include + enum { STAT_DISCONNECTED = 0, STAT_CONNECTING, STAT_CONNECTED }; -int tdcparser_send_getvars(int address); void tdcparser_send_hello(void); +int tdcparser_send_getvars(int address); +int tdcparser_send_getvalue(int address, int id); +int tdcparser_send_setvalue(int address, int id); +int tdcparser_send_request(int address, int interval, uint32_t *bitmap); void tdcparser_connect(char *addr_str, void (*cb)(int status)); void tdcparser_disconnect(void); diff --git a/tdc_store.c b/tdc_store.c index e6df648..dd9886b 100644 --- a/tdc_store.c +++ b/tdc_store.c @@ -1,63 +1,180 @@ +#include #include #include #include +#include "tdc_parser.h" +#include "tdc_proto.h" #include "tdc_store.h" #include "tdc_variable.h" #include "gui_variable_tab.h" -static char *boardname[8]; -static struct tdc_var *varmap[256]; +struct tdc_board { + char name[32]; + struct tdc_var *varmap[256]; -void tdcstore_set_name(int address, char *name) + int refresh_graph_interval; + int refresh_interval; + gint refresh_tag; +}; + +static struct tdc_board *board_arr[8]; + +struct tdc_board * tdcstore_get_board(int address) { - if (boardname[address & 0x7] != NULL) - free(boardname[address & 0x7]); - - boardname[address & 0x7] = strdup(name); - printf("ADDR%d:%s\n", address, boardname[address & 0x7]); -} - -char * tdcstore_get_name(int address) -{ - return boardname[address & 0x7]; -} - -int tdcstore_set_var(int address, struct tdc_var *var) -{ - if (varmap[var->id] != NULL) { - gui_vartab_remove_var(var); - tdcvar_destroy(varmap[var->id]); - } - - varmap[var->id] = var; - gui_vartab_add_var(var); - - return 0; + return board_arr[address & 0x7]; } struct tdc_var * tdcstore_get_var(int address, int id) { - return varmap[id & 0xFF]; + struct tdc_board *board = tdcstore_get_board(address); + return (board != NULL) ? board->varmap[id & 0xFF] : NULL; } -void tdcstore_trigger_update(int address, int id) +static int tdcstore_destroy_var(struct tdc_board *board, int id) { - gui_vartab_update_var(varmap[id & 0xFF]); + struct tdc_var *var = board->varmap[id & 0xFF]; + if (var == NULL) + return -1; + + gui_vartab_remove_var(var); + tdcvar_destroy(var); + + board->varmap[id & 0xFF] = NULL; + return 0; +} + +static int tdcstore_destroy_board(int address) +{ + struct tdc_board *board = tdcstore_get_board(address); + if (board == NULL) + return -1; + + int i; + for (i = 0; i < 256; i++) { + if (board->varmap[i] == NULL) + continue; + + tdcstore_destroy_var(board, i); + } + + g_free(board); + board_arr[address & 0x7] = NULL; + return 0; +} + +void tdcstore_create_board(int address, char *name) +{ + struct tdc_board *old = tdcstore_get_board(address); + if (old != NULL) + tdcstore_destroy_board(address); + + struct tdc_board *board = g_malloc0(sizeof(struct tdc_board)); + strncpy(board->name, name, 32); + + printf("ADDR%d:%s\n", address, board->name); + board_arr[address & 0x7] = board; +} + +int tdcstore_create_var(int address, struct tdc_var *var) +{ + struct tdc_board *board = tdcstore_get_board(address); + if (board == NULL) + return -1; + + struct tdc_var *old = tdcstore_get_var(address, var->id); + if (old != NULL) + tdcstore_destroy_var(board, var->id); + + board->varmap[var->id] = var; + gui_vartab_add_var(var); + return 0; +} + +int tdcstore_update_var(int address, int id, uint8_t *data, int len) +{ + struct tdc_var *var = tdcstore_get_var(address, id); + if (var == NULL) + return -1; + + tdcvar_update(var, data, len); + gui_vartab_update_var(var); + return 0; +} + +static gint refresh_helper(gpointer data) +{ + int i; + int address = (int)data; + + for (i = 0; i < 256; i++) { + struct tdc_var *var = tdcstore_get_var(address, i); + /* unknown var, or value updated via refresh_graph */ + if ((var == NULL) || (var->flags & TDC_GUI_GRAPH)) + continue; + + /* error while sending -> bail out, disable timeout */ + if (tdcparser_send_getvalue(address, i) < 0) + return FALSE; + } + return TRUE; +} + +int tdcstore_refresh_values(int address, int interval) +{ + struct tdc_board *board = tdcstore_get_board(address); + if (board == NULL) + return -1; + + int old_interval = board->refresh_interval; + if (old_interval != 0) + g_source_remove(board->refresh_tag); + + board->refresh_tag = g_timeout_add(interval, refresh_helper, (gpointer)address); + return 0; +} + +static void tdcstore_get_bitmap(int address, uint32_t *bitmap) +{ + int i, cnt = 0; + uint32_t tmp = 0; + + for (i = 0; i < 256; i++) { + struct tdc_var *var = tdcstore_get_var(address, i); + if ((var != NULL) && (var->flags & TDC_GUI_GRAPH)) + tmp = (tmp << 1) | 0x01; + else + tmp = (tmp << 1); + + cnt = (cnt +1) % 32; + if (cnt == 0) { + bitmap[i >> 5] = tmp; + tmp = 0; + } + } +} + +int tdcstore_graph_refresh(int address, int interval) +{ + struct tdc_board *board = tdcstore_get_board(address); + if (board == NULL) + return -1; + + if (interval == -1) + interval = board->refresh_graph_interval; + + uint32_t bitmap[8]; + tdcstore_get_bitmap(address, bitmap); + tdcparser_send_request(address, interval, bitmap); + + board->refresh_graph_interval = interval; + return 0; } void tdcstore_flush(void) { int i; - for (i = 0; i < 8; i++) { - free(boardname[i]); - boardname[i] = NULL; - } - - for (i = 0; i < 256; i++) { - gui_vartab_remove_var(varmap[i]); - tdcvar_destroy(varmap[i]); - varmap[i] = NULL; - } + for (i = 0; i < 8; i++) + tdcstore_destroy_board(i); } diff --git a/tdc_store.h b/tdc_store.h index d048960..f614c0a 100644 --- a/tdc_store.h +++ b/tdc_store.h @@ -1,15 +1,19 @@ #ifndef TDC_STORE_H_ #define TDC_STORE_H_ +#include #include "tdc_variable.h" -void tdcstore_set_name(int address, char *name); -char * tdcstore_get_name(int address); - -int tdcstore_set_var(int address, struct tdc_var *var); +struct tdc_board * tdcstore_get_board(int address); struct tdc_var * tdcstore_get_var(int address, int id); -void tdcstore_trigger_update(int address, int id); +void tdcstore_create_board(int address, char *name); + +int tdcstore_create_var(int address, struct tdc_var *var); +int tdcstore_update_var(int address, int id, uint8_t *data, int len); + +int tdcstore_refresh_values(int address, int interval); +int tdcstore_graph_refresh(int address, int interval); void tdcstore_flush(void); diff --git a/tdc_variable.c b/tdc_variable.c index 7e541ac..27320fd 100644 --- a/tdc_variable.c +++ b/tdc_variable.c @@ -170,7 +170,7 @@ void tdcvar_update(struct tdc_var *var, uint8_t *data, int len) if ((var->flags & TDC_SIZEMASK) != len) return; - memcpy(&var->data_uint8, data, len); + memcpy(&var->data, data, len); } void tdcvar_destroy(struct tdc_var *var) diff --git a/tdc_variable.h b/tdc_variable.h index a6f7468..ec8f8b5 100644 --- a/tdc_variable.h +++ b/tdc_variable.h @@ -7,6 +7,7 @@ struct tdc_var { uint32_t id; uint32_t flags; union { + uint8_t data; uint8_t data_uint8; uint16_t data_uint16; uint32_t data_uint32;