refactoring
This commit is contained in:
parent
f7db63b4b3
commit
3aaa30cb63
109
control_tab.c
109
control_tab.c
@ -1,109 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "tcpsocket.h"
|
||||
#include "sockaddr.h"
|
||||
|
||||
#include "tdc_store.h"
|
||||
|
||||
enum {
|
||||
STAT_DISCONNECTED = 0,
|
||||
STAT_CONNECTING,
|
||||
STAT_CONNECTED
|
||||
};
|
||||
|
||||
static GtkWidget *button_connect;
|
||||
static int connect_status = STAT_DISCONNECTED;
|
||||
|
||||
static gint socket_tag;
|
||||
static int socket_fd;
|
||||
|
||||
static void update_connect_button(void)
|
||||
{
|
||||
if (connect_status == STAT_DISCONNECTED)
|
||||
gtk_button_set_label(GTK_BUTTON(button_connect), "Connect");
|
||||
else
|
||||
gtk_button_set_label(GTK_BUTTON(button_connect), "Disconnect");
|
||||
}
|
||||
|
||||
static void read_cb(gpointer data, gint source, GdkInputCondition condition)
|
||||
{
|
||||
if (tdc_parse_data(source) <= 0) {
|
||||
g_warning("gtdc:read_cb:read:%s", g_strerror(errno));
|
||||
connect_status = STAT_DISCONNECTED;
|
||||
update_connect_button();
|
||||
|
||||
gdk_input_remove(socket_tag);
|
||||
close(source);
|
||||
}
|
||||
}
|
||||
|
||||
static void connect_cb(gpointer data, gint source, GdkInputCondition condition)
|
||||
{
|
||||
gdk_input_remove(socket_tag);
|
||||
|
||||
if (tcp_connect_error(source) < 0) {
|
||||
g_warning("gtdc:connect_cb:tcp_connect_error:%s", g_strerror(errno));
|
||||
connect_status = STAT_DISCONNECTED;
|
||||
close(socket_fd);
|
||||
|
||||
} else {
|
||||
connect_status = STAT_CONNECTED;
|
||||
socket_tag = gdk_input_add(socket_fd, GDK_INPUT_READ, read_cb, NULL);
|
||||
|
||||
tdc_flush_vars();
|
||||
tdc_send_hello(source);
|
||||
}
|
||||
|
||||
update_connect_button();
|
||||
}
|
||||
|
||||
static void connect_button_cb(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
switch (connect_status) {
|
||||
case STAT_DISCONNECTED:
|
||||
connect_status = STAT_CONNECTING;
|
||||
|
||||
struct sockaddr_in sa;
|
||||
parse_sockaddr("127.0.0.1:5000", &sa);
|
||||
socket_fd = tcp_connect_nonblock(&sa);
|
||||
|
||||
socket_tag = gdk_input_add(socket_fd, GDK_INPUT_WRITE, connect_cb, NULL);
|
||||
break;
|
||||
|
||||
case STAT_CONNECTING:
|
||||
case STAT_CONNECTED:
|
||||
connect_status = STAT_DISCONNECTED;
|
||||
|
||||
gdk_input_remove(socket_tag);
|
||||
close(socket_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
update_connect_button();
|
||||
}
|
||||
|
||||
gint control_tab_init(GtkNotebook *notebook)
|
||||
{
|
||||
GtkWidget *table = gtk_table_new(10, 10, FALSE);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(table), 10);
|
||||
|
||||
button_connect = gtk_button_new_with_label("Connect");
|
||||
gtk_table_attach(GTK_TABLE(table), button_connect, 0, 1, 0, 1, 0, 0, 10, 10);
|
||||
g_signal_connect(G_OBJECT(button_connect), "clicked", G_CALLBACK(connect_button_cb), NULL);
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - address field
|
||||
* - all_variable_refresh_timer
|
||||
* - graph_variable_refresh_timer
|
||||
* later:
|
||||
* - board select
|
||||
* - connection/protocol details/errors
|
||||
*/
|
||||
|
||||
GtkWidget *label = gtk_label_new(" Control ");
|
||||
return gtk_notebook_append_page(GTK_NOTEBOOK(notebook), table, label);
|
||||
}
|
15
gtdc.c
15
gtdc.c
@ -1,18 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "tdc_store.h"
|
||||
#include "variable_tab.h"
|
||||
#include "gui_variable_tab.h"
|
||||
|
||||
gint control_tab_init(GtkNotebook *notebook);
|
||||
gint graph_tab_init(GtkNotebook *notebook);
|
||||
gint gui_ctrltab_init(GtkNotebook *notebook);
|
||||
gint gui_graphtab_init(GtkNotebook *notebook);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
tdc_init();
|
||||
|
||||
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title(GTK_WINDOW(window), " gTDC v0.1 ");
|
||||
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
|
||||
@ -25,9 +22,9 @@ int main(int argc, char *argv[])
|
||||
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
|
||||
gtk_container_add(GTK_CONTAINER(window), notebook);
|
||||
|
||||
control_tab_init(GTK_NOTEBOOK(notebook));
|
||||
variable_tab_init(GTK_NOTEBOOK(notebook));
|
||||
graph_tab_init(GTK_NOTEBOOK(notebook));
|
||||
gui_ctrltab_init(GTK_NOTEBOOK(notebook));
|
||||
gui_vartab_init(GTK_NOTEBOOK(notebook));
|
||||
gui_graphtab_init(GTK_NOTEBOOK(notebook));
|
||||
|
||||
gtk_widget_show_all(window);
|
||||
gtk_main();
|
||||
|
53
gui_control_tab.c
Normal file
53
gui_control_tab.c
Normal file
@ -0,0 +1,53 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "tdc_parser.h"
|
||||
|
||||
static GtkWidget *button_connect;
|
||||
static int connect_status = STAT_DISCONNECTED;
|
||||
|
||||
static void connect_button_update(int status)
|
||||
{
|
||||
connect_status = status;
|
||||
|
||||
if (status == STAT_DISCONNECTED)
|
||||
gtk_button_set_label(GTK_BUTTON(button_connect), "Connect");
|
||||
else
|
||||
gtk_button_set_label(GTK_BUTTON(button_connect), "Disconnect");
|
||||
}
|
||||
|
||||
static void connect_button_cb(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
switch (connect_status) {
|
||||
case STAT_DISCONNECTED:
|
||||
tdcparser_connect("127.0.0.1:5000", connect_button_update);
|
||||
break;
|
||||
|
||||
case STAT_CONNECTING:
|
||||
case STAT_CONNECTED:
|
||||
tdcparser_disconnect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gint gui_ctrltab_init(GtkNotebook *notebook)
|
||||
{
|
||||
GtkWidget *table = gtk_table_new(10, 10, FALSE);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(table), 10);
|
||||
|
||||
button_connect = gtk_button_new_with_label("Connect");
|
||||
gtk_table_attach(GTK_TABLE(table), button_connect, 0, 1, 0, 1, 0, 0, 10, 10);
|
||||
g_signal_connect(G_OBJECT(button_connect), "clicked", G_CALLBACK(connect_button_cb), NULL);
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - address field
|
||||
* - all_variable_refresh_timer
|
||||
* - graph_variable_refresh_timer
|
||||
* later:
|
||||
* - board select
|
||||
* - connection/protocol details/errors
|
||||
*/
|
||||
|
||||
GtkWidget *label = gtk_label_new(" Control ");
|
||||
return gtk_notebook_append_page(GTK_NOTEBOOK(notebook), table, label);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtkdatabox.h>
|
||||
|
||||
gint graph_tab_init(GtkNotebook *notebook)
|
||||
gint gui_graphtab_init(GtkNotebook *notebook)
|
||||
{
|
||||
GtkWidget *table = gtk_table_new(3, 3, FALSE);
|
||||
GtkWidget *box = gtk_databox_new();
|
@ -1,7 +1,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "tdc_store.h"
|
||||
#include "tdcproto.h"
|
||||
#include "tdc_proto.h"
|
||||
|
||||
enum {
|
||||
COL_ID = 0, /* UINT */
|
||||
@ -37,8 +37,6 @@ static void cell_graph_toggle(GtkCellRendererToggle *cell,
|
||||
gtk_list_store_set(GTK_LIST_STORE(user_data), &it,
|
||||
COL_GRAPH, !toggle,
|
||||
-1);
|
||||
|
||||
tdc_store_update_graphlist();
|
||||
}
|
||||
|
||||
static gboolean header_toggle_update(GtkTreeModel *model,
|
||||
@ -112,11 +110,11 @@ static void cell_value_func(GtkTreeViewColumn *column,
|
||||
gtk_tree_model_get(model, iter, COL_VALUE, &var, -1);
|
||||
|
||||
char buf[32];
|
||||
tdc_store_get_varvalue(var, buf, sizeof(buf), viewmode);
|
||||
tdcvar_get_value(var, buf, sizeof(buf), viewmode);
|
||||
g_object_set(cell, "text", buf, NULL);
|
||||
}
|
||||
|
||||
gint variable_tab_init(GtkNotebook *notebook)
|
||||
gint gui_vartab_init(GtkNotebook *notebook)
|
||||
{
|
||||
list_store = gtk_list_store_new(6,
|
||||
G_TYPE_UINT, G_TYPE_BOOLEAN,
|
||||
@ -178,13 +176,13 @@ gint variable_tab_init(GtkNotebook *notebook)
|
||||
return gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrollbar, label);
|
||||
}
|
||||
|
||||
void vartab_add_var(struct tdc_var *var)
|
||||
void gui_vartab_add_var(struct tdc_var *var)
|
||||
{
|
||||
GtkTreeIter it;
|
||||
gtk_list_store_append(list_store, &it);
|
||||
|
||||
char typestr[32];
|
||||
tdc_store_get_vartype(var, typestr, sizeof(typestr));
|
||||
tdcvar_get_type(var, typestr, sizeof(typestr));
|
||||
|
||||
gtk_list_store_set(list_store, &it,
|
||||
COL_ID, var->id,
|
||||
@ -196,13 +194,14 @@ void vartab_add_var(struct tdc_var *var)
|
||||
-1);
|
||||
}
|
||||
|
||||
void vartab_update_var(struct tdc_var *var)
|
||||
void gui_vartab_update_var(struct tdc_var *var)
|
||||
{
|
||||
// FIXME: don't update *all* columns when *one* value changed
|
||||
// FIXME: don't update *all* columns when only *one* value changed
|
||||
gtk_tree_model_foreach(GTK_TREE_MODEL(list_store), header_toggle_update, NULL);
|
||||
}
|
||||
|
||||
void vartab_remove_all_vars(void)
|
||||
void gui_vartab_remove_var(struct tdc_var *var)
|
||||
{
|
||||
// FIXME: don't remove *all* columns when only *one* should be removed
|
||||
gtk_list_store_clear(list_store);
|
||||
}
|
13
gui_variable_tab.h
Normal file
13
gui_variable_tab.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef VARIABLE_TAB_H_
|
||||
#define VARIABLE_TAB_H_
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "tdc_variable.h"
|
||||
|
||||
gint gui_vartab_init(GtkNotebook *notebook);
|
||||
|
||||
void gui_vartab_add_var(struct tdc_var *var);
|
||||
void gui_vartab_update_var(struct tdc_var *var);
|
||||
void gui_vartab_remove_var(struct tdc_var *var);
|
||||
|
||||
#endif /* VARIABLE_TAB_H_ */
|
260
tdc_parser.c
Normal file
260
tdc_parser.c
Normal file
@ -0,0 +1,260 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "sockaddr.h"
|
||||
#include "tcpsocket.h"
|
||||
|
||||
#include "tdc_parser.h"
|
||||
#include "tdc_proto.h"
|
||||
#include "tdc_store.h"
|
||||
#include "tdc_variable.h"
|
||||
|
||||
static int socket_fd;
|
||||
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);
|
||||
}
|
||||
|
||||
void tdcparser_send_hello(void)
|
||||
{
|
||||
int addr;
|
||||
for (addr = 1; addr < 8; addr++) {
|
||||
struct tdc_pkt_header pkt;
|
||||
pkt.cmd = (addr << 4) | TDC_HELLO;
|
||||
pkt.size = sizeof(pkt);
|
||||
|
||||
tdcparser_send(&pkt);
|
||||
}
|
||||
}
|
||||
|
||||
int tdcparser_send_getvars(int address)
|
||||
{
|
||||
struct tdc_pkt_header pkt;
|
||||
pkt.cmd = (address << 4) | TDC_GETVARS;
|
||||
pkt.size = sizeof(pkt);
|
||||
|
||||
return tdcparser_send(&pkt);
|
||||
}
|
||||
|
||||
static int tdcparser_parse(void)
|
||||
{
|
||||
int address = (socket_stream->data[0] & TDC_ADDRMASK) >> 4;
|
||||
|
||||
int remove = 1;
|
||||
|
||||
switch (socket_stream->data[0] & (TDC_REPLY | TDC_OPCODEMASK)) {
|
||||
case TDC_HELLO: {
|
||||
struct tdc_pkt_header *pkt = (struct tdc_pkt_header *)socket_stream->data;
|
||||
remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_HELLO");
|
||||
/* nothing to do */
|
||||
} break;
|
||||
|
||||
case (TDC_HELLO | TDC_REPLY): {
|
||||
struct tdc_hello_reply *pkt = (struct tdc_hello_reply *)socket_stream->data;
|
||||
remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_HELLO REPLY");
|
||||
if (remove <= 0)
|
||||
break;
|
||||
|
||||
tdcstore_set_name(address, pkt->name);
|
||||
tdcparser_send_getvars(address);
|
||||
} break;
|
||||
|
||||
case TDC_GETVARS: {
|
||||
struct tdc_pkt_header *pkt = (struct tdc_pkt_header *)socket_stream->data;
|
||||
remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVARS");
|
||||
/* nothing to do */
|
||||
} break;
|
||||
|
||||
case (TDC_GETVARS | TDC_REPLY): {
|
||||
struct tdc_getvars_reply *pkt = (struct tdc_getvars_reply *)socket_stream->data;
|
||||
remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt),
|
||||
pkt->name_len, "TDC_GETVARS REPLY");
|
||||
|
||||
if (remove <= 0)
|
||||
break;
|
||||
|
||||
tdcstore_set_var(address, tdcvar_create(pkt->id, pkt->flags, pkt->name, pkt->name_len));
|
||||
} break;
|
||||
|
||||
case TDC_GETVALUE: {
|
||||
struct tdc_getvalue_request *pkt = (struct tdc_getvalue_request *)socket_stream->data;
|
||||
remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVALUE");
|
||||
/* nothing to do */
|
||||
} break;
|
||||
|
||||
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)
|
||||
break;
|
||||
|
||||
struct tdc_var *var = tdcstore_get_var(address, pkt->id);
|
||||
if (var == NULL) {
|
||||
printf("unknown variable %d\n", pkt->id);
|
||||
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)
|
||||
|
||||
if (remove <= 0)
|
||||
break;
|
||||
|
||||
tdcvar_update(var, pkt->data, varsize);
|
||||
tdcstore_trigger_update(address, pkt->id);
|
||||
} 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)
|
||||
break;
|
||||
|
||||
struct tdc_var *var = tdcstore_get_var(address, pkt->id);
|
||||
if (var == NULL) {
|
||||
printf("unknown variable %d\n", pkt->id);
|
||||
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)
|
||||
|
||||
/* nothing to do */
|
||||
} break;
|
||||
|
||||
case (TDC_SETVALUE | TDC_REPLY):
|
||||
break;
|
||||
|
||||
case TDC_REQVALUES: {
|
||||
struct tdc_reqvalues_request *pkt = (struct tdc_reqvalues_request *)socket_stream->data;
|
||||
remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_REQVALUES");
|
||||
/* nothing to do */
|
||||
} break;
|
||||
|
||||
case (TDC_REQVALUES | TDC_REPLY): {
|
||||
struct tdc_reqvalues_reply *pkt = (struct tdc_reqvalues_reply *)socket_stream->data;
|
||||
remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_REQVALUES");
|
||||
if (remove <= 0)
|
||||
break;
|
||||
|
||||
// TODO: output pkt->timestamp, pkt->cnt
|
||||
} break;
|
||||
|
||||
case TDC_TERMINAL:
|
||||
case (TDC_TERMINAL | TDC_REPLY):
|
||||
break;
|
||||
}
|
||||
|
||||
if (remove != 0)
|
||||
g_byte_array_remove_range(socket_stream, 0, (remove > 0) ? remove : -remove);
|
||||
|
||||
return remove;
|
||||
}
|
||||
|
||||
static void tdcparser_read_cb(gpointer data,
|
||||
gint source,
|
||||
GdkInputCondition condition)
|
||||
{
|
||||
char buf[256];
|
||||
int len = read(socket_fd, buf, sizeof(buf));
|
||||
|
||||
if (len > 0) {
|
||||
g_byte_array_append(socket_stream, (guint8 *)buf, len);
|
||||
|
||||
while (socket_stream->len >= 2) {
|
||||
if (tdcparser_parse() == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
g_warning("gtdc:tdcparser_read_cb:read:%s", g_strerror(errno));
|
||||
tdcparser_disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
static void tdcparser_connect_cb(gpointer data,
|
||||
gint source,
|
||||
GdkInputCondition condition)
|
||||
{
|
||||
gdk_input_remove(socket_tag);
|
||||
|
||||
if (tcp_connect_error(source) < 0) {
|
||||
g_warning("gtdc:tdcparser_connect_cb:tcp_connect_error:%s", g_strerror(errno));
|
||||
|
||||
socket_status_cb(STAT_DISCONNECTED);
|
||||
close(socket_fd);
|
||||
|
||||
} else {
|
||||
socket_tag = gdk_input_add(socket_fd, GDK_INPUT_READ, tdcparser_read_cb, NULL);
|
||||
socket_status_cb(STAT_CONNECTED);
|
||||
|
||||
if (socket_stream == NULL)
|
||||
socket_stream = g_byte_array_new();
|
||||
|
||||
else if (socket_stream->len)
|
||||
g_byte_array_remove_range(socket_stream, 0, socket_stream->len);
|
||||
|
||||
tdcstore_flush();
|
||||
tdcparser_send_hello();
|
||||
}
|
||||
}
|
||||
|
||||
void tdcparser_connect(char *addr_str, void (*cb)(int status))
|
||||
{
|
||||
struct sockaddr_in sa;
|
||||
parse_sockaddr(addr_str, &sa);
|
||||
|
||||
socket_status_cb = cb;
|
||||
socket_status_cb(STAT_CONNECTING);
|
||||
|
||||
socket_fd = tcp_connect_nonblock(&sa);
|
||||
socket_tag = gdk_input_add(socket_fd, GDK_INPUT_WRITE, tdcparser_connect_cb, NULL);
|
||||
}
|
||||
|
||||
void tdcparser_disconnect(void)
|
||||
{
|
||||
socket_status_cb(STAT_DISCONNECTED);
|
||||
gdk_input_remove(socket_tag);
|
||||
close(socket_fd);
|
||||
}
|
16
tdc_parser.h
Normal file
16
tdc_parser.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef TDC_PARSER_H_
|
||||
#define TDC_PARSER_H_
|
||||
|
||||
enum {
|
||||
STAT_DISCONNECTED = 0,
|
||||
STAT_CONNECTING,
|
||||
STAT_CONNECTED
|
||||
};
|
||||
|
||||
int tdcparser_send_getvars(int address);
|
||||
void tdcparser_send_hello(void);
|
||||
|
||||
void tdcparser_connect(char *addr_str, void (*cb)(int status));
|
||||
void tdcparser_disconnect(void);
|
||||
|
||||
#endif /* TDC_PARSER_H_ */
|
437
tdc_store.c
437
tdc_store.c
@ -1,432 +1,63 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "tdc_store.h"
|
||||
#include "tdcproto.h"
|
||||
#include "tdc_variable.h"
|
||||
|
||||
#include "variable_tab.h"
|
||||
#include "gui_variable_tab.h"
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
static char *boardname[8];
|
||||
static struct tdc_var *varmap[256];
|
||||
|
||||
static struct tdc_var * var_map[256];
|
||||
static GByteArray *stream;
|
||||
|
||||
void tdc_store_get_varvalue(struct tdc_var *var, char *buf, int size, int viewmode)
|
||||
void tdcstore_set_name(int address, char *name)
|
||||
{
|
||||
switch ((var->flags & TDC_TYPEMASK) | ((viewmode & 0x01) << 8)) {
|
||||
case TDC_UNSIGNED:
|
||||
switch (var->flags & TDC_SIZEMASK) {
|
||||
case 1: snprintf(buf, size, "%u", var->data_uint8);
|
||||
break;
|
||||
if (boardname[address & 0x7] != NULL)
|
||||
free(boardname[address & 0x7]);
|
||||
|
||||
case 2: snprintf(buf, size, "%u", var->data_uint16);
|
||||
break;
|
||||
|
||||
case 4: snprintf(buf, size, "%u", var->data_uint32);
|
||||
break;
|
||||
|
||||
case 8: snprintf(buf, size, "%llu", var->data_uint64);
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TDC_UNSIGNED | 0x100:
|
||||
switch (var->flags & TDC_SIZEMASK) {
|
||||
case 1: snprintf(buf, size, "0x%02x", var->data_uint8);
|
||||
break;
|
||||
|
||||
case 2: snprintf(buf, size, "0x%04x", var->data_uint16);
|
||||
break;
|
||||
|
||||
case 4: snprintf(buf, size, "0x%08x", var->data_uint32);
|
||||
break;
|
||||
|
||||
case 8: snprintf(buf, size, "0x%16llx", var->data_uint64);
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TDC_SIGNED:
|
||||
switch (var->flags & TDC_SIZEMASK) {
|
||||
case 1: snprintf(buf, size, "%d", (int8_t)var->data_uint8);
|
||||
break;
|
||||
|
||||
case 2: snprintf(buf, size, "%d", (int16_t)var->data_uint16);
|
||||
break;
|
||||
|
||||
case 4: snprintf(buf, size, "%d", (int32_t)var->data_uint32);
|
||||
break;
|
||||
|
||||
case 8: snprintf(buf, size, "%lld", (int64_t)var->data_uint64);
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TDC_SIGNED | 0x100:
|
||||
switch (var->flags & TDC_SIZEMASK) {
|
||||
case 1: snprintf(buf, size, "0x%02x", (int8_t)var->data_uint8);
|
||||
break;
|
||||
|
||||
case 2: snprintf(buf, size, "0x%04x", (int16_t)var->data_uint16);
|
||||
break;
|
||||
|
||||
case 4: snprintf(buf, size, "0x%08x", (int32_t)var->data_uint32);
|
||||
break;
|
||||
|
||||
case 8: snprintf(buf, size, "0x%16llx", (int64_t)var->data_uint64);
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TDC_FP:
|
||||
case TDC_FP | 0x100:
|
||||
switch (var->flags & TDC_SIZEMASK) {
|
||||
case sizeof(float):
|
||||
snprintf(buf, size, "%.8f", var->data_float);
|
||||
break;
|
||||
|
||||
case sizeof(double):
|
||||
snprintf(buf, size, "%.12f", var->data_double);
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TDC_FIXED:
|
||||
case TDC_FIXED | 0x100:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
boardname[address & 0x7] = strdup(name);
|
||||
printf("ADDR%d:%s\n", address, boardname[address & 0x7]);
|
||||
}
|
||||
|
||||
void tdc_store_get_vartype(struct tdc_var *var, char *buf, int size)
|
||||
char * tdcstore_get_name(int address)
|
||||
{
|
||||
int pos;
|
||||
int width = (var->flags & TDC_SIZEMASK);
|
||||
return boardname[address & 0x7];
|
||||
}
|
||||
|
||||
switch (var->flags & TDC_TYPEMASK) {
|
||||
case TDC_UNSIGNED:
|
||||
pos = snprintf(buf, size, "uint%d_t", width * 8);
|
||||
break;
|
||||
|
||||
case TDC_SIGNED:
|
||||
pos = snprintf(buf, size, "int%d_t", width * 8);
|
||||
break;
|
||||
|
||||
case TDC_FP:
|
||||
if (width == sizeof(float))
|
||||
pos = snprintf(buf, size, "float");
|
||||
|
||||
else if (size == sizeof(double))
|
||||
pos = snprintf(buf, size, "double");
|
||||
|
||||
else
|
||||
pos = snprintf(buf, size, "fp%d_t", width * 8);
|
||||
break;
|
||||
|
||||
case TDC_FIXED:
|
||||
pos = snprintf(buf, size, "fix%d_t", width * 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
pos = snprintf(buf, size, "???");
|
||||
break;
|
||||
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]);
|
||||
}
|
||||
|
||||
if (var->flags & TDC_READONLY)
|
||||
pos = snprintf(buf + pos, size - pos, " (ro)");
|
||||
varmap[var->id] = var;
|
||||
gui_vartab_add_var(var);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tdc_store_update_graphlist(void)
|
||||
struct tdc_var * tdcstore_get_var(int address, int id)
|
||||
{
|
||||
return varmap[id & 0xFF];
|
||||
}
|
||||
|
||||
static void destroy_var(int id)
|
||||
void tdcstore_trigger_update(int address, int id)
|
||||
{
|
||||
g_free(var_map[id]);
|
||||
var_map[id] = NULL;
|
||||
gui_vartab_update_var(varmap[id & 0xFF]);
|
||||
}
|
||||
|
||||
static void create_var(int id, uint32_t flags, char *name, int len)
|
||||
void tdcstore_flush(void)
|
||||
{
|
||||
id &= 0xFF;
|
||||
|
||||
if (var_map[id] != NULL)
|
||||
destroy_var(id);
|
||||
|
||||
var_map[id] = g_malloc0(sizeof(struct tdc_var) + len + 1);
|
||||
var_map[id]->id = id;
|
||||
var_map[id]->flags = flags;
|
||||
|
||||
strncpy(var_map[id]->name, name, len);
|
||||
var_map[id]->name[len] = '\0';
|
||||
|
||||
vartab_add_var(var_map[id]);
|
||||
}
|
||||
|
||||
static void update_var(int id, uint8_t *data, int len)
|
||||
{
|
||||
memcpy(&(var_map[id & 0xFF]->data_uint8), data, len);
|
||||
|
||||
vartab_update_var(var_map[id & 0xFF]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char * stream_print(void)
|
||||
{
|
||||
int pos = 0, i = 0, j;
|
||||
char *buf = g_malloc(stream->len * 4 + 64);
|
||||
|
||||
while (pos < stream->len) {
|
||||
i += sprintf(buf + i, "%04X: ", pos);
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (pos + j < stream->len)
|
||||
i += sprintf(buf + i, "%02X", stream->data[pos + j]);
|
||||
else
|
||||
i += sprintf(buf + i, " ");
|
||||
|
||||
if (j % 2)
|
||||
buf[i++] = ' ';
|
||||
}
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (pos + j < stream->len) {
|
||||
unsigned char val = stream->data[pos + j];
|
||||
if (val >= 0x20 && val < 0x80)
|
||||
buf[i++] = val;
|
||||
else
|
||||
buf[i++] = '.';
|
||||
} else {
|
||||
buf[i++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
pos += 16;
|
||||
buf[i++] = '\r';
|
||||
buf[i++] = '\n';
|
||||
}
|
||||
buf[i] = 0;
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int parse_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 parse(int fd)
|
||||
{
|
||||
int address = (stream->data[0] & TDC_ADDRMASK) >> 4;
|
||||
|
||||
int remove = 1;
|
||||
|
||||
switch (stream->data[0] & (TDC_REPLY | TDC_OPCODEMASK)) {
|
||||
case TDC_HELLO: {
|
||||
struct tdc_pkt_header *pkt = (struct tdc_pkt_header *)stream->data;
|
||||
remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_HELLO");
|
||||
/* do nothing, we'll never receive TDC_HELLOs */
|
||||
} break;
|
||||
|
||||
case (TDC_HELLO | TDC_REPLY): {
|
||||
struct tdc_hello_reply *pkt = (struct tdc_hello_reply *)stream->data;
|
||||
remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_HELLO REPLY");
|
||||
if (remove <= 0)
|
||||
break;
|
||||
|
||||
printf("ADDR%d: '%32s'\n", address, pkt->name);
|
||||
|
||||
struct tdc_pkt_header pkt2;
|
||||
pkt2.cmd = (address << 4) | TDC_GETVARS;
|
||||
pkt2.size = sizeof(pkt2);
|
||||
write(fd, &pkt2, pkt2.size);
|
||||
|
||||
} break;
|
||||
|
||||
case TDC_GETVARS: {
|
||||
struct tdc_pkt_header *pkt = (struct tdc_pkt_header *)stream->data;
|
||||
remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVARS");
|
||||
/* do nothing, we'll never receive TDC_GETVARSs */
|
||||
} break;
|
||||
|
||||
case (TDC_GETVARS | TDC_REPLY): {
|
||||
struct tdc_getvars_reply *pkt = (struct tdc_getvars_reply *)stream->data;
|
||||
remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt),
|
||||
pkt->name_len, "TDC_GETVARS REPLY");
|
||||
|
||||
if (remove <= 0)
|
||||
break;
|
||||
|
||||
create_var(pkt->id, pkt->flags, pkt->name, pkt->name_len);
|
||||
printf("create_var(%d, 0x%x, '%s', %d)\n",
|
||||
pkt->id, var_map[pkt->id]->flags, var_map[pkt->id]->name, pkt->name_len);
|
||||
} break;
|
||||
|
||||
case TDC_GETVALUE: {
|
||||
struct tdc_getvalue_request *pkt = (struct tdc_getvalue_request *)stream->data;
|
||||
remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVALUE");
|
||||
/* do nothing, we'll never receive TDC_GETVALUEs */
|
||||
} break;
|
||||
|
||||
case (TDC_GETVALUE | TDC_REPLY): {
|
||||
struct tdc_getvalue_reply *pkt = (struct tdc_getvalue_reply *)stream->data;
|
||||
|
||||
/* check base packet */
|
||||
remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVALUE REPLY");
|
||||
if (remove <= 0)
|
||||
break;
|
||||
|
||||
if (var_map[pkt->id & 0xFF] == NULL) {
|
||||
printf("unknown variable %d\n", pkt->id);
|
||||
break;
|
||||
}
|
||||
|
||||
int varsize = (var_map[pkt->id & 0xFF]->flags & TDC_SIZEMASK);
|
||||
remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), varsize, "TDC_GETVALUE REPLY");
|
||||
// TODO: adjust remove on error (valid reply with invalid data size)
|
||||
|
||||
update_var(pkt->id, pkt->data, varsize);
|
||||
} break;
|
||||
|
||||
case TDC_SETVALUE: {
|
||||
struct tdc_setvalue_request *pkt = (struct tdc_setvalue_request *)stream->data;
|
||||
remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_SETVALUE");
|
||||
if (remove <= 0)
|
||||
break;
|
||||
|
||||
if (var_map[pkt->id & 0xFF] == NULL) {
|
||||
printf("unknown variable %d\n", pkt->id);
|
||||
break;
|
||||
}
|
||||
|
||||
int varsize = (var_map[pkt->id & 0xFF]->flags & TDC_SIZEMASK);
|
||||
remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), varsize, "TDC_GETVALUE REPLY");
|
||||
// TODO: adjust remove on error (valid reply with invalid data size)
|
||||
|
||||
/* do nothing, we'll never receive TDC_SETVALUEs */
|
||||
} break;
|
||||
|
||||
case (TDC_SETVALUE | TDC_REPLY):
|
||||
break;
|
||||
|
||||
case TDC_REQVALUES: {
|
||||
struct tdc_reqvalues_request *pkt = (struct tdc_reqvalues_request *)stream->data;
|
||||
remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_REQVALUES");
|
||||
/* do nothing, we'll never receive TDC_REQVALUESs */
|
||||
} break;
|
||||
|
||||
case (TDC_REQVALUES | TDC_REPLY): {
|
||||
struct tdc_reqvalues_reply *pkt = (struct tdc_reqvalues_reply *)stream->data;
|
||||
remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_REQVALUES");
|
||||
if (remove <= 0)
|
||||
break;
|
||||
|
||||
// TODO: output pkt->timestamp, pkt->cnt
|
||||
} break;
|
||||
|
||||
case TDC_TERMINAL:
|
||||
case (TDC_TERMINAL | TDC_REPLY):
|
||||
break;
|
||||
}
|
||||
|
||||
if (remove != 0)
|
||||
g_byte_array_remove_range(stream, 0, (remove > 0) ? remove : -remove);
|
||||
|
||||
return remove;
|
||||
}
|
||||
|
||||
int tdc_parse_data(int fd)
|
||||
{
|
||||
char buf[256];
|
||||
int len = read(fd, buf, sizeof(buf));
|
||||
|
||||
if (len > 0) {
|
||||
g_byte_array_append(stream, (guint8 *)buf, len);
|
||||
|
||||
while (stream->len >= 2) {
|
||||
if (parse(fd) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void tdc_flush_vars(void)
|
||||
{
|
||||
vartab_remove_all_vars();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(var_map); i++) {
|
||||
if (var_map[i] == NULL)
|
||||
continue;
|
||||
|
||||
destroy_var(i);
|
||||
for (i = 0; i < 8; i++) {
|
||||
free(boardname[i]);
|
||||
boardname[i] = NULL;
|
||||
}
|
||||
|
||||
if (stream->len)
|
||||
g_byte_array_remove_range(stream, 0, stream->len);
|
||||
}
|
||||
|
||||
void tdc_send_hello(int fd)
|
||||
{
|
||||
int addr;
|
||||
for (addr = 1; addr < 8; addr++) {
|
||||
struct tdc_pkt_header pkt;
|
||||
pkt.cmd = (addr << 4) | TDC_HELLO;
|
||||
pkt.size = sizeof(pkt);
|
||||
|
||||
write(fd, &pkt, pkt.size);
|
||||
for (i = 0; i < 256; i++) {
|
||||
gui_vartab_remove_var(varmap[i]);
|
||||
tdcvar_destroy(varmap[i]);
|
||||
varmap[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void tdc_init(void)
|
||||
{
|
||||
stream = g_byte_array_new();
|
||||
}
|
||||
|
29
tdc_store.h
29
tdc_store.h
@ -1,29 +1,16 @@
|
||||
#ifndef TDC_STORE_H_
|
||||
#define TDC_STORE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "tdc_variable.h"
|
||||
|
||||
struct tdc_var {
|
||||
uint32_t id;
|
||||
uint32_t flags;
|
||||
union {
|
||||
uint8_t data_uint8;
|
||||
uint16_t data_uint16;
|
||||
uint32_t data_uint32;
|
||||
uint64_t data_uint64;
|
||||
float data_float;
|
||||
double data_double;
|
||||
};
|
||||
char name[0];
|
||||
};
|
||||
void tdcstore_set_name(int address, char *name);
|
||||
char * tdcstore_get_name(int address);
|
||||
|
||||
void tdc_store_get_varvalue(struct tdc_var *var, char *buf, int size, int viewmode);
|
||||
void tdc_store_get_vartype(struct tdc_var *var, char *buf, int size);
|
||||
void tdc_store_update_graphlist(void);
|
||||
int tdcstore_set_var(int address, struct tdc_var *var);
|
||||
struct tdc_var * tdcstore_get_var(int address, int id);
|
||||
|
||||
int tdc_parse_data(int fd);
|
||||
void tdc_flush_vars(void);
|
||||
void tdc_send_hello(int fd);
|
||||
void tdc_init(void);
|
||||
void tdcstore_trigger_update(int address, int id);
|
||||
|
||||
void tdcstore_flush(void);
|
||||
|
||||
#endif /* TDC_STORE_H_ */
|
||||
|
179
tdc_variable.c
Normal file
179
tdc_variable.c
Normal file
@ -0,0 +1,179 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "tdc_proto.h"
|
||||
#include "tdc_variable.h"
|
||||
|
||||
void tdcvar_get_value(struct tdc_var *var, char *buf, int size, int viewmode)
|
||||
{
|
||||
switch ((var->flags & TDC_TYPEMASK) | ((viewmode & 0x01) << 8)) {
|
||||
case TDC_UNSIGNED:
|
||||
switch (var->flags & TDC_SIZEMASK) {
|
||||
case 1: snprintf(buf, size, "%u", var->data_uint8);
|
||||
break;
|
||||
|
||||
case 2: snprintf(buf, size, "%u", var->data_uint16);
|
||||
break;
|
||||
|
||||
case 4: snprintf(buf, size, "%u", var->data_uint32);
|
||||
break;
|
||||
|
||||
case 8: snprintf(buf, size, "%llu", var->data_uint64);
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TDC_UNSIGNED | 0x100:
|
||||
switch (var->flags & TDC_SIZEMASK) {
|
||||
case 1: snprintf(buf, size, "0x%02x", var->data_uint8);
|
||||
break;
|
||||
|
||||
case 2: snprintf(buf, size, "0x%04x", var->data_uint16);
|
||||
break;
|
||||
|
||||
case 4: snprintf(buf, size, "0x%08x", var->data_uint32);
|
||||
break;
|
||||
|
||||
case 8: snprintf(buf, size, "0x%16llx", var->data_uint64);
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TDC_SIGNED:
|
||||
switch (var->flags & TDC_SIZEMASK) {
|
||||
case 1: snprintf(buf, size, "%d", (int8_t)var->data_uint8);
|
||||
break;
|
||||
|
||||
case 2: snprintf(buf, size, "%d", (int16_t)var->data_uint16);
|
||||
break;
|
||||
|
||||
case 4: snprintf(buf, size, "%d", (int32_t)var->data_uint32);
|
||||
break;
|
||||
|
||||
case 8: snprintf(buf, size, "%lld", (int64_t)var->data_uint64);
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TDC_SIGNED | 0x100:
|
||||
switch (var->flags & TDC_SIZEMASK) {
|
||||
case 1: snprintf(buf, size, "0x%02x", (int8_t)var->data_uint8);
|
||||
break;
|
||||
|
||||
case 2: snprintf(buf, size, "0x%04x", (int16_t)var->data_uint16);
|
||||
break;
|
||||
|
||||
case 4: snprintf(buf, size, "0x%08x", (int32_t)var->data_uint32);
|
||||
break;
|
||||
|
||||
case 8: snprintf(buf, size, "0x%16llx", (int64_t)var->data_uint64);
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TDC_FP:
|
||||
case TDC_FP | 0x100:
|
||||
switch (var->flags & TDC_SIZEMASK) {
|
||||
case sizeof(float):
|
||||
snprintf(buf, size, "%.8f", var->data_float);
|
||||
break;
|
||||
|
||||
case sizeof(double):
|
||||
snprintf(buf, size, "%.12f", var->data_double);
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TDC_FIXED:
|
||||
case TDC_FIXED | 0x100:
|
||||
snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void tdcvar_get_type(struct tdc_var *var, char *buf, int size)
|
||||
{
|
||||
int pos;
|
||||
int width = (var->flags & TDC_SIZEMASK);
|
||||
|
||||
switch (var->flags & TDC_TYPEMASK) {
|
||||
case TDC_UNSIGNED:
|
||||
pos = snprintf(buf, size, "uint%d_t", width * 8);
|
||||
break;
|
||||
|
||||
case TDC_SIGNED:
|
||||
pos = snprintf(buf, size, "int%d_t", width * 8);
|
||||
break;
|
||||
|
||||
case TDC_FP:
|
||||
if (width == sizeof(float))
|
||||
pos = snprintf(buf, size, "float");
|
||||
|
||||
else if (size == sizeof(double))
|
||||
pos = snprintf(buf, size, "double");
|
||||
|
||||
else
|
||||
pos = snprintf(buf, size, "fp%d_t", width * 8);
|
||||
break;
|
||||
|
||||
case TDC_FIXED:
|
||||
pos = snprintf(buf, size, "fix%d_t", width * 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
pos = snprintf(buf, size, "???");
|
||||
break;
|
||||
}
|
||||
|
||||
if (var->flags & TDC_READONLY)
|
||||
pos = snprintf(buf + pos, size - pos, " (ro)");
|
||||
}
|
||||
|
||||
struct tdc_var * tdcvar_create(int id, uint32_t flags, char *name, int len)
|
||||
{
|
||||
struct tdc_var *var = g_malloc0(sizeof(struct tdc_var) + len + 1);
|
||||
var->id = id & 0xFF;
|
||||
var->flags = flags;
|
||||
|
||||
strncpy(var->name, name, len);
|
||||
var->name[len] = '\0';
|
||||
|
||||
printf("create_var(%d, 0x%x, '%s', %d)\n", var->id, var->flags, var->name, len);
|
||||
return var;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void tdcvar_destroy(struct tdc_var *var)
|
||||
{
|
||||
g_free(var);
|
||||
}
|
27
tdc_variable.h
Normal file
27
tdc_variable.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef TDC_VARIABLE_H_
|
||||
#define TDC_VARIABLE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct tdc_var {
|
||||
uint32_t id;
|
||||
uint32_t flags;
|
||||
union {
|
||||
uint8_t data_uint8;
|
||||
uint16_t data_uint16;
|
||||
uint32_t data_uint32;
|
||||
uint64_t data_uint64;
|
||||
float data_float;
|
||||
double data_double;
|
||||
};
|
||||
char name[0];
|
||||
};
|
||||
|
||||
void tdcvar_get_value(struct tdc_var *var, char *buf, int size, int viewmode);
|
||||
void tdcvar_get_type(struct tdc_var *var, char *buf, int size);
|
||||
|
||||
struct tdc_var * tdcvar_create(int id, uint32_t flags, char *name, int len);
|
||||
void tdcvar_update(struct tdc_var *var, uint8_t *data, int len);
|
||||
void tdcvar_destroy(struct tdc_var *var);
|
||||
|
||||
#endif /* TDC_VARIABLE_H_ */
|
@ -1,13 +0,0 @@
|
||||
#ifndef VARIABLE_TAB_H_
|
||||
#define VARIABLE_TAB_H_
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "tdc_store.h"
|
||||
|
||||
gint variable_tab_init(GtkNotebook *notebook);
|
||||
|
||||
void vartab_add_var(struct tdc_var *var);
|
||||
void vartab_update_var(struct tdc_var *var);
|
||||
void vartab_remove_all_vars(void);
|
||||
|
||||
#endif /* VARIABLE_TAB_H_ */
|
Loading…
Reference in New Issue
Block a user