diff --git a/gex/gex_client.c b/gex/gex_client.c index 8649d64..9500533 100644 --- a/gex/gex_client.c +++ b/gex/gex_client.c @@ -112,10 +112,19 @@ void GEX_OnReport(GexClient *gex, GexUnit *unit, GexEventListener lst) } } +TinyFrame *GEX_GetTF(GexClient *gex) +{ + return gex->tf; +} + /** Find a unit */ GexUnit *GEX_Unit(GexClient *gex, const char *name) { - return gex_find_unit_by_name(gex, name); + GexUnit *u = gex_find_unit_by_name(gex, name); + if (u == NULL) { + fprintf(stderr, "!! Unit %s not found!\n", name); + } + return u; } /** Create a instance and connect */ diff --git a/gex/gex_client.h b/gex/gex_client.h index 83ec77a..03167ce 100644 --- a/gex/gex_client.h +++ b/gex/gex_client.h @@ -26,6 +26,8 @@ */ void GEX_OnReport(GexClient *gex, GexUnit *unit, GexEventListener lst); +TinyFrame *GEX_GetTF(GexClient *gex); + /** * Get a unit, or NULL * diff --git a/gex/gex_helpers.c b/gex/gex_helpers.c index 738c2a0..f21e943 100644 --- a/gex/gex_helpers.c +++ b/gex/gex_helpers.c @@ -8,6 +8,7 @@ #define GEX_H // to allow including other headers #include "gex_defines.h" #include "gex_helpers.h" +#include "gex_internal.h" /** Delete recursively all GEX callsign look-up table entries */ void gex_destroy_unit_lookup(GexClient *gex) diff --git a/gex/gex_message_types.h b/gex/gex_message_types.h index a5cbbc8..a046cee 100644 --- a/gex/gex_message_types.h +++ b/gex/gex_message_types.h @@ -19,7 +19,7 @@ enum TF_Types_ { MSG_ERROR = 0x02, //!< Generic failure response (when a request fails to execute) MSG_BULK_READ_OFFER = 0x03, //!< Offer of data to read. Payload: u32 total len - MSG_BULK_READ_POLL = 0x04, //!< Request to read a previously announced chunk. + MSG_BULK_READ_POLL = 0x04, //!< Request to read a previously announced chunk. Payload: u32 max chunk MSG_BULK_WRITE_OFFER = 0x05, //!< Offer to receive data in a write transaction. Payload: u32 max size, u32 max chunk MSG_BULK_DATA = 0x06, //!< Writing a chunk, or sending a chunk to master. MSG_BULK_END = 0x07, //!< Bulk transfer is done, no more data to read or write. diff --git a/gex/gex_unit.c b/gex/gex_unit.c index 68b7554..b943af7 100644 --- a/gex/gex_unit.c +++ b/gex/gex_unit.c @@ -134,7 +134,7 @@ static GexMsg GEX_QueryEx(GexUnit *unit, uint8_t cmd, GEX_Poll(gex); if (!gex->squery_ok) { - fprintf(stderr, "No response to query of unit %s!", unit->name); + fprintf(stderr, "No response to query of unit %s!\n", unit->name); } return gex->squery_msg; @@ -200,30 +200,37 @@ uint32_t GEX_BulkRead(GexUnit *unit, GexBulk *bulk) GexMsg resp0 = GEX_Query(unit, bulk->req_cmd, bulk->req_data, bulk->req_len); if (resp0.type == MSG_ERROR) { - fprintf(stderr, "Bulk read rejected! %.*s", resp0.len, (char*)resp0.payload); + fprintf(stderr, "Bulk read rejected! %.*s\n", resp0.len, (char*)resp0.payload); return 0; } if (resp0.type != MSG_BULK_READ_OFFER) { - fprintf(stderr, "Bulk read failed, response not BULK_READ_OFFER!"); + fprintf(stderr, "Bulk read failed, response not BULK_READ_OFFER!\n"); return 0; } + fprintf(stderr, "BR, got offer!\n"); + // Check how much data is available PayloadParser pp = pp_start(resp0.payload, resp0.len, NULL); uint32_t total = pp_u32(&pp); assert(pp.ok); total = MIN(total, bulk->capacity); // clamp... + fprintf(stderr, "Total is %d\n", total); uint32_t at = 0; while (at < total) { + uint8_t buf[10]; + PayloadBuilder pb = pb_start(buf, 10, NULL); + pb_u32(&pb, 512); + GexMsg resp = GEX_QueryEx(unit, MSG_BULK_READ_POLL, - NULL, 0, + buf, (uint32_t) pb_length(&pb), resp0.session, true); if (resp.type == MSG_ERROR) { - fprintf(stderr, "Bulk read failed! %.*s", resp.len, (char *) resp.payload); + fprintf(stderr, "Bulk read failed! %.*s\n", resp.len, (char *) resp.payload); return 0; } @@ -236,7 +243,7 @@ uint32_t GEX_BulkRead(GexUnit *unit, GexBulk *bulk) memcpy(bulk->buffer+at, resp.payload, resp.len); at += resp.len; } else { - fprintf(stderr, "Bulk read failed! Bad response type."); + fprintf(stderr, "Bulk read failed! Bad response type.\n"); return 0; } } @@ -258,12 +265,12 @@ bool GEX_BulkWrite(GexUnit *unit, GexBulk *bulk) GexMsg resp0 = GEX_Query(unit, bulk->req_cmd, bulk->req_data, bulk->req_len); if (resp0.type == MSG_ERROR) { - fprintf(stderr, "Bulk write rejected! %.*s", resp0.len, (char*)resp0.payload); + fprintf(stderr, "Bulk write rejected! %.*s\n", resp0.len, (char*)resp0.payload); return false; } if (resp0.type != MSG_BULK_WRITE_OFFER) { - fprintf(stderr, "Bulk write failed, response not MSG_BULK_WRITE_OFFER!"); + fprintf(stderr, "Bulk write failed, response not MSG_BULK_WRITE_OFFER!\n"); return false; } @@ -273,7 +280,7 @@ bool GEX_BulkWrite(GexUnit *unit, GexBulk *bulk) assert(pp.ok); if (max_size < bulk->len) { - fprintf(stderr, "Write not possible, not enough space."); + fprintf(stderr, "Write not possible, not enough space.\n"); // Inform GEX we're not going to do it GEX_SendEx(unit, MSG_BULK_ABORT, NULL, 0, resp0.session, true); return false; @@ -288,12 +295,12 @@ bool GEX_BulkWrite(GexUnit *unit, GexBulk *bulk) at += chunk; if (resp.type == MSG_ERROR) { - fprintf(stderr, "Bulk write failed! %.*s", resp.len, (char *) resp.payload); + fprintf(stderr, "Bulk write failed! %.*s\n", resp.len, (char *) resp.payload); return false; } if (resp.type != MSG_SUCCESS) { - fprintf(stderr, "Bulk write failed! Bad response type."); + fprintf(stderr, "Bulk write failed! Bad response type.\n"); return false; } } diff --git a/gex/gex_unit.h b/gex/gex_unit.h index 873c05d..7b793b3 100644 --- a/gex/gex_unit.h +++ b/gex/gex_unit.h @@ -27,6 +27,12 @@ static inline void GEX_Send0(GexUnit *unit, uint8_t cmd) /** Static query, send a command and wait for the response */ GexMsg GEX_Query(GexUnit *unit, uint8_t cmd, const uint8_t *payload, uint32_t len); +/** Send a query with no payload */ +static inline GexMsg GEX_Query0(GexUnit *unit, uint8_t cmd) +{ + return GEX_Query(unit, cmd, NULL, 0); +} + /** Asynchronous query with an async listener */ void GEX_QueryAsync(GexUnit *unit, uint8_t cmd, const uint8_t *payload, uint32_t len, GexEventListener lst); diff --git a/main.c b/main.c index 1fbce7f..db25ca8 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "gex.h" @@ -20,6 +21,14 @@ static void sigintHandler(int sig) #define LED_CMD_TOGGLE 0x02 +TF_Result hdl_default(TinyFrame *tf, TF_Msg*msg) +{ + (void)tf; + fprintf(stderr, "TF unhandled msg len %d, type %d, id %d", msg->len, msg->type, msg->frame_id); + hexDump("payload", msg->data, msg->len); + return TF_STAY; +} + int main(void) { // Bind ^C handler for safe shutdown @@ -28,11 +37,39 @@ int main(void) gex = GEX_Init("/dev/ttyACM0", 200); if (!gex) exit(1); - GexUnit *led = GEX_Unit(gex, "LED"); - assert(led != NULL); + TF_AddGenericListener(GEX_GetTF(gex), hdl_default); + + //GexUnit *led = GEX_Unit(gex, "LED"); + //GEX_Send(led, LED_CMD_TOGGLE, NULL, 0); + + GexUnit *test = GEX_Unit(gex, "TEST"); + assert(test != NULL); + + // the "PING" command + GexMsg msg; + + msg = GEX_Query0(test, 0); + assert(msg.type == MSG_SUCCESS); + fprintf(stderr, "\"PING\" cmd: OK.\n"); + + const char *s = "BLOCKCHAIN BUT FOR COWS"; + msg = GEX_Query(test, 1, (const uint8_t *) s, (uint32_t) strlen(s)); + fprintf(stderr, "\"ECHO\" cmd resp: %d, len %d, pld: %.*s\n", msg.type, (int) msg.len, (int) msg.len, (char *) msg.payload); + assert(0==strncmp((char*)msg.payload, s, strlen(s))); - GEX_Send(led, LED_CMD_TOGGLE, NULL, 0); + uint8_t buffr[10000]; + GexBulk br = { + .buffer = buffr, + .capacity = 10000, + .req_cmd = 2, + .req_data = NULL, + .req_len = 0, + }; + uint32_t actuallyRead = GEX_BulkRead(test, &br); + fprintf(stderr, "Read %d bytes:\n", actuallyRead); + fprintf(stderr, "%*.s", actuallyRead, buffr); + fprintf(stderr, "ALL OK, ending.\n"); GEX_DeInit(gex); return 0; }