diff --git a/CMakeLists.txt b/CMakeLists.txt index af86fb3..b61ebc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ set(SOURCE_FILES gex/protocol/TinyFrame.c gex/protocol/TinyFrame.h gex/utils/type_coerce.h - gex/gex_defines.h gex/gex_unit.c gex/gex_unit.h) + gex/gex_defines.h gex/gex_unit.c gex/gex_unit.h gex/gex.h) include_directories( gex diff --git a/gex/TF_Integration.c b/gex/TF_Integration.c index 41a32d7..bb36bbf 100644 --- a/gex/TF_Integration.c +++ b/gex/TF_Integration.c @@ -5,6 +5,8 @@ #include #include "TinyFrame.h" + +#define GEX_H // to allow including other headers #include "gex_internal.h" void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, size_t len) diff --git a/gex/gex.h b/gex/gex.h new file mode 100644 index 0000000..b76ff06 --- /dev/null +++ b/gex/gex.h @@ -0,0 +1,13 @@ +// +// Created by MightyPork on 2017/12/19. +// + +#ifndef GEX_H +#define GEX_H + +#include "gex_defines.h" +#include "gex_client.h" +#include "gex_unit.h" +#include "gex_message_types.h" + +#endif //GEX_H diff --git a/gex/gex_client.c b/gex/gex_client.c index 241800b..c4c9fba 100644 --- a/gex/gex_client.c +++ b/gex/gex_client.c @@ -10,6 +10,7 @@ #include #include "TinyFrame.h" +#define GEX_H // to allow including other headers #include "gex_client.h" #include "serial.h" #include "gex_internal.h" @@ -53,7 +54,7 @@ static TF_Result unit_report_lst(TinyFrame *tf, TF_Msg *msg) .payload = (uint8_t *) (msg->data + 2), .len = (uint32_t) (msg->len - 2), .type = rpt_type, - .unit = (lu == NULL) ? fbu : lu, + .unit = (lu == NULL) ? &fbu : lu, }; if (lu && lu->report_handler) { @@ -85,9 +86,10 @@ static TF_Result list_units_lst(TinyFrame *tf, TF_Msg *msg) // append struct gex_unit *lu = malloc(sizeof(struct gex_unit)); lu->next = NULL; - lu->type = "UNKNOWN"; + lu->type = strdup("UNKNOWN"); // TODO lu->name = strdup(buf); lu->callsign = callsign; + lu->gex = gex; lu->report_handler = NULL; if (tail == NULL) { gex->ulu_head = lu; @@ -111,6 +113,12 @@ void GEX_OnReport(GexClient *gex, GexUnit *unit, GexEventListener lst) } } +/** Find a unit */ +GexUnit *GEX_Unit(GexClient *gex, const char *name) +{ + return gex_find_unit_by_name(gex, name); +} + /** Create a instance and connect */ GexClient *GEX_Init(const char *device, int timeout_ms) { @@ -125,6 +133,7 @@ GexClient *GEX_Init(const char *device, int timeout_ms) gex->acm_fd = serial_open(device, false, (timeout_ms + 50) / 100); if (gex->acm_fd == -1) { free(gex); + fprintf(stderr, "FAILED TO CONNECT TO %s!\n", device); return NULL; } @@ -172,7 +181,7 @@ void GEX_Poll(GexClient *gex) void GEX_DeInit(GexClient *gex) { if (gex == NULL) return; - close(gex->acm_fd); + fsync(gex->acm_fd); gex_destroy_unit_lookup(gex); TF_DeInit(gex->tf); free(gex); diff --git a/gex/gex_client.h b/gex/gex_client.h index f32a9a0..83ec77a 100644 --- a/gex/gex_client.h +++ b/gex/gex_client.h @@ -5,6 +5,10 @@ #ifndef GEX_CLIENT_GEX_CLIENT_H #define GEX_CLIENT_GEX_CLIENT_H +#ifndef GEX_H +#error "Include gex.h instead!" +#endif + #include #include #include @@ -22,6 +26,14 @@ */ void GEX_OnReport(GexClient *gex, GexUnit *unit, GexEventListener lst); +/** + * Get a unit, or NULL + * + * @param gex - gex + * @param name - unit name + */ +GexUnit *GEX_Unit(GexClient *gex, const char *name); + /** * Initialize the GEX client * diff --git a/gex/gex_defines.h b/gex/gex_defines.h index 8b617ed..d544713 100644 --- a/gex/gex_defines.h +++ b/gex/gex_defines.h @@ -5,9 +5,15 @@ #ifndef GEX_CLIENT_GEX_DEFINES_H #define GEX_CLIENT_GEX_DEFINES_H +#ifndef GEX_H +#error "Include gex.h instead!" +#endif + #include #include +#include "TinyFrame.h" + typedef TF_ID GexSession; typedef struct gex_client GexClient; diff --git a/gex/gex_helpers.c b/gex/gex_helpers.c index 560ea60..738c2a0 100644 --- a/gex/gex_helpers.c +++ b/gex/gex_helpers.c @@ -3,17 +3,23 @@ // #include +#include +#define GEX_H // to allow including other headers #include "gex_defines.h" #include "gex_helpers.h" /** Delete recursively all GEX callsign look-up table entries */ void gex_destroy_unit_lookup(GexClient *gex) { + assert(gex != NULL); + struct gex_unit *next = gex->ulu_head; while (next != NULL) { struct gex_unit *cur = next; next = next->next; + free(cur->name); + free(cur->type); free(cur); } gex->ulu_head = NULL; @@ -22,6 +28,8 @@ void gex_destroy_unit_lookup(GexClient *gex) /** Get lookup entry for unit name */ struct gex_unit *gex_find_unit_by_callsign(GexClient *gex, uint8_t callsign) { + assert(gex != NULL); + struct gex_unit *next = gex->ulu_head; while (next != NULL) { if (next->callsign == callsign) { @@ -35,6 +43,9 @@ struct gex_unit *gex_find_unit_by_callsign(GexClient *gex, uint8_t callsign) /** Get lookup entry for unit name */ struct gex_unit *gex_find_unit_by_name(GexClient *gex, const char *name) { + assert(gex != NULL); + assert(name != NULL); + struct gex_unit *next = gex->ulu_head; while (next != NULL) { if (strcmp(next->name, name) == 0) { @@ -48,6 +59,8 @@ struct gex_unit *gex_find_unit_by_name(GexClient *gex, const char *name) /** Get callsign for unit name */ uint8_t gex_find_callsign_by_name(GexClient *gex, const char *name) { + assert(gex != NULL); + struct gex_unit *lu = gex_find_unit_by_name(gex, name); return (uint8_t) ((lu == NULL) ? 0 : lu->callsign); } diff --git a/gex/gex_helpers.h b/gex/gex_helpers.h index f138ee1..5d9892a 100644 --- a/gex/gex_helpers.h +++ b/gex/gex_helpers.h @@ -5,6 +5,10 @@ #ifndef GEX_CLIENT_GEX_HELPERS_H #define GEX_CLIENT_GEX_HELPERS_H +#ifndef GEX_H +#error "Include gex.h instead!" +#endif + #include "gex_internal.h" #include "gex_defines.h" diff --git a/gex/gex_message_types.h b/gex/gex_message_types.h index 2e2a60e..9c2cb60 100644 --- a/gex/gex_message_types.h +++ b/gex/gex_message_types.h @@ -5,6 +5,10 @@ #ifndef GEX_CLIENT_GEX_MESSAGE_TYPES_H #define GEX_CLIENT_GEX_MESSAGE_TYPES_H +#ifndef GEX_H +#error "Include gex.h instead!" +#endif + /** * Supported message types (TF_TYPE) */ diff --git a/gex/gex_unit.c b/gex/gex_unit.c index 6b29619..adf8b8c 100644 --- a/gex/gex_unit.c +++ b/gex/gex_unit.c @@ -4,6 +4,8 @@ #include #include + +#define GEX_H // to allow including other headers #include "gex_defines.h" #include "gex_helpers.h" #include "gex_message_types.h" @@ -20,9 +22,12 @@ */ static void GEX_LL_Query(GexUnit *unit, uint8_t cmd, uint8_t *payload, uint32_t len, TF_Listener lst, void *userdata2) { + assert(unit != NULL); + assert(unit->gex != NULL); + GexClient *gex = unit->gex; - uint8_t callsign = gex_find_callsign_by_name(gex, unit); + uint8_t callsign = unit->callsign; assert(callsign != 0); uint8_t *pld = malloc(len + 2); assert(pld != NULL); @@ -48,6 +53,9 @@ static void GEX_LL_Query(GexUnit *unit, uint8_t cmd, uint8_t *payload, uint32_t /** Send with no listener, don't wait for response */ void GEX_Send(GexUnit *unit, uint8_t cmd, uint8_t *payload, uint32_t len) { + assert(unit != NULL); + assert(unit->gex != NULL); + GEX_LL_Query(unit, cmd, payload, len, NULL, NULL); } @@ -55,6 +63,8 @@ void GEX_Send(GexUnit *unit, uint8_t cmd, uint8_t *payload, uint32_t len) static TF_Result sync_query_lst(TinyFrame *tf, TF_Msg *msg) { GexClient *gex = tf->userdata; + assert(gex != NULL); + // clone the message gex->sync_query_response.len = msg->len; gex->sync_query_response.session = msg->frame_id; @@ -70,7 +80,11 @@ static TF_Result sync_query_lst(TinyFrame *tf, TF_Msg *msg) /** Static query */ GexMsg GEX_Query(GexUnit *unit, uint8_t cmd, uint8_t *payload, uint32_t len) { + assert(unit != NULL); + assert(unit->gex != NULL); + GexClient *gex = unit->gex; + gex->sync_query_ok = false; // Default response that will be used if nothing is received @@ -113,6 +127,9 @@ static TF_Result async_query_lst(TinyFrame *tf, TF_Msg *msg) /** Sync query, without poll */ void GEX_QueryAsync(GexUnit *unit, uint8_t cmd, uint8_t *payload, uint32_t len, GexEventListener lst) { + assert(unit != NULL); + assert(unit->gex != NULL); + GexClient *gex = unit->gex; gex->sync_query_ok = false; memset(&gex->sync_query_response, 0, sizeof(GexMsg)); diff --git a/gex/gex_unit.h b/gex/gex_unit.h index 1463320..073fccc 100644 --- a/gex/gex_unit.h +++ b/gex/gex_unit.h @@ -5,6 +5,22 @@ #ifndef GEX_CLIENT_GEX_UNIT_H #define GEX_CLIENT_GEX_UNIT_H +#ifndef GEX_H +#error "Include gex.h instead!" +#endif + +#include "gex_defines.h" +#include +#include + +/** Send with no listener, don't wait for response */ +void GEX_Send(GexUnit *unit, uint8_t cmd, uint8_t *payload, uint32_t len); + +/** Static query */ +GexMsg GEX_Query(GexUnit *unit, uint8_t cmd, uint8_t *payload, uint32_t len); + +/** Sync query, without poll */ +void GEX_QueryAsync(GexUnit *unit, uint8_t cmd, uint8_t *payload, uint32_t len, GexEventListener lst); #endif //GEX_CLIENT_GEX_UNIT_H diff --git a/main.c b/main.c index bf81c32..e6d998a 100644 --- a/main.c +++ b/main.c @@ -1,7 +1,9 @@ #include #include -#include "gex_client.h" #include +#include + +#include "gex.h" static GexClient *gex; @@ -14,18 +16,20 @@ static void sigintHandler(int sig) exit(0); } +#define LED_CMD_TOGGLE 0x02 + int main() { // Bind ^C handler for safe shutdown signal(SIGINT, sigintHandler); gex = GEX_Init("/dev/ttyACM0", 200); - if (!gex) { - fprintf(stderr, "FAILED TO CONNECT, ABORTING!\n"); - exit(1); - } + if (!gex) exit(1); + + GexUnit *led = GEX_Unit(gex, "LED"); + assert(led != NULL); - printf("Hello, World!\n"); + GEX_Send(led, LED_CMD_TOGGLE, NULL, 0); GEX_DeInit(gex); return 0;