small cleaning up
This commit is contained in:
+1
-1
@@ -26,7 +26,7 @@ set(SOURCE_FILES
|
|||||||
gex/protocol/TinyFrame.c
|
gex/protocol/TinyFrame.c
|
||||||
gex/protocol/TinyFrame.h
|
gex/protocol/TinyFrame.h
|
||||||
gex/utils/type_coerce.h
|
gex/utils/type_coerce.h
|
||||||
gex/gex_defines.h gex/gex_unit.c gex/gex_unit.h gex/gex.h)
|
gex/gex_defines.h gex/gex_unit.c gex/gex_unit.h gex/gex.h gex/gex_bulk.c)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
gex
|
gex
|
||||||
|
|||||||
+144
@@ -0,0 +1,144 @@
|
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/12/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "utils/payload_parser.h"
|
||||||
|
#include "utils/payload_builder.h"
|
||||||
|
|
||||||
|
#define GEX_H
|
||||||
|
#include "gex_bulk.h"
|
||||||
|
#include "gex_internal.h"
|
||||||
|
#include "gex_message_types.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk read from a unit, synchronous
|
||||||
|
*
|
||||||
|
* @param unit - the unit to target
|
||||||
|
* @param bulk - the bulk transport info struct
|
||||||
|
* @return actual number of bytes received.
|
||||||
|
*/
|
||||||
|
uint32_t GEX_BulkRead(GexUnit *unit, GexBulk *bulk)
|
||||||
|
{
|
||||||
|
// fprintf(stderr, "Ask to read:\n");
|
||||||
|
// We ask for the transfer. This is unit specific and can contain information that determines the transferred data
|
||||||
|
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\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!\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+1) { // +1 makes sure we read one past end and trigger the END OF DATA msg
|
||||||
|
uint8_t buf[10];
|
||||||
|
PayloadBuilder pb = pb_start(buf, 10, NULL);
|
||||||
|
pb_u32(&pb, 120); // This selects the chunk size.
|
||||||
|
// FIXME Something is wrong in the poll function, or the transport in general,
|
||||||
|
// because chunks larger than e.g. 128 bytes seem to get stuck half-transferred.
|
||||||
|
// This isn't an issue for events and regular sending, only query responses like here.
|
||||||
|
// This may also cause problems when receiving events while reading a bulk.
|
||||||
|
// It may be best to get rid of the comport and use libusb, after all.
|
||||||
|
|
||||||
|
// fprintf(stderr, "Poll read:\n");
|
||||||
|
GexMsg resp = GEX_QueryEx(unit, MSG_BULK_READ_POLL, buf,
|
||||||
|
(uint32_t) pb_length(&pb), resp0.session, true, true);
|
||||||
|
|
||||||
|
if (resp.type == MSG_ERROR) {
|
||||||
|
fprintf(stderr, "Bulk read failed! %.*s\n", resp.len, (char *) resp.payload);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.type == MSG_BULK_END) {
|
||||||
|
// No more data
|
||||||
|
fprintf(stderr, "Bulk read OK, closed.\n");
|
||||||
|
return at;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.type == MSG_BULK_DATA) {
|
||||||
|
memcpy(bulk->buffer+at, resp.payload, resp.len);
|
||||||
|
at += resp.len;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Bulk read failed! Bad response type.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return at;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk write to a unit, synchronous
|
||||||
|
*
|
||||||
|
* @param unit - the unit to target
|
||||||
|
* @param bulk - the bulk transport info struct
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool GEX_BulkWrite(GexUnit *unit, GexBulk *bulk)
|
||||||
|
{
|
||||||
|
// We ask for the transfer. This is unit specific
|
||||||
|
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\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!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PayloadParser pp = pp_start(resp0.payload, resp0.len, NULL);
|
||||||
|
uint32_t max_size = pp_u32(&pp);
|
||||||
|
uint32_t max_chunk = pp_u32(&pp);
|
||||||
|
assert(pp.ok);
|
||||||
|
|
||||||
|
if (max_size < bulk->len) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t at = 0;
|
||||||
|
while (at < bulk->len) {
|
||||||
|
uint32_t chunk = MIN(max_chunk, bulk->len - at);
|
||||||
|
// fprintf(stderr, "Query at %d, len %d\n", (int)at, (int)chunk);
|
||||||
|
GexMsg resp = GEX_QueryEx(unit, MSG_BULK_DATA, bulk->buffer + at, chunk,
|
||||||
|
resp0.session, true, true);
|
||||||
|
at += chunk;
|
||||||
|
|
||||||
|
if (resp.type == MSG_ERROR) {
|
||||||
|
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.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conclude the transfer
|
||||||
|
GEX_SendEx(unit, MSG_BULK_END, NULL, 0, resp0.session, true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/12/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GEX_CLIENT_GEX_BULK_H
|
||||||
|
#define GEX_CLIENT_GEX_BULK_H
|
||||||
|
|
||||||
|
#ifndef GEX_H
|
||||||
|
#error "Include gex.h instead!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gex_defines.h"
|
||||||
|
#include "gex_unit.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk read from a unit, synchronous
|
||||||
|
*
|
||||||
|
* @param unit - the unit to target
|
||||||
|
* @param bulk - the bulk transport info struct
|
||||||
|
* @return actual number of bytes received.
|
||||||
|
*/
|
||||||
|
uint32_t GEX_BulkRead(GexUnit *unit, GexBulk *bulk);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk write to a unit, synchronous
|
||||||
|
*
|
||||||
|
* @param unit - the unit to target
|
||||||
|
* @param bulk - the bulk transport info struct
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool GEX_BulkWrite(GexUnit *unit, GexBulk *bulk);
|
||||||
|
|
||||||
|
#endif //GEX_CLIENT_GEX_BULK_H
|
||||||
+2
-136
@@ -117,10 +117,10 @@ static TF_Result sync_query_lst(TinyFrame *tf, TF_Msg *msg)
|
|||||||
|
|
||||||
|
|
||||||
/** Static query */
|
/** Static query */
|
||||||
static GexMsg GEX_QueryEx(GexUnit *unit, uint8_t cmd,
|
GexMsg GEX_QueryEx(GexUnit *unit, uint8_t cmd,
|
||||||
const uint8_t *payload, uint32_t len,
|
const uint8_t *payload, uint32_t len,
|
||||||
GexSession session, bool is_reply,
|
GexSession session, bool is_reply,
|
||||||
bool raw_pld)
|
bool raw_pld) // FIXME this is horrible, split to multiple functions or use a struct
|
||||||
{
|
{
|
||||||
assert(unit != NULL);
|
assert(unit != NULL);
|
||||||
assert(unit->gex != NULL);
|
assert(unit->gex != NULL);
|
||||||
@@ -188,137 +188,3 @@ void GEX_QueryAsync(GexUnit *unit, uint8_t cmd, const uint8_t *payload, uint32_t
|
|||||||
// Async query does not poll, instead the user listener is attached to the message
|
// Async query does not poll, instead the user listener is attached to the message
|
||||||
GEX_LL_Query(unit, cmd, payload, len, 0, false, async_query_lst, lst, false);
|
GEX_LL_Query(unit, cmd, payload, len, 0, false, async_query_lst, lst, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------- BULK ----------------------------
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bulk read from a unit, synchronous
|
|
||||||
*
|
|
||||||
* @param unit - the unit to target
|
|
||||||
* @param bulk - the bulk transport info struct
|
|
||||||
* @return actual number of bytes received.
|
|
||||||
*/
|
|
||||||
uint32_t GEX_BulkRead(GexUnit *unit, GexBulk *bulk)
|
|
||||||
{
|
|
||||||
// fprintf(stderr, "Ask to read:\n");
|
|
||||||
// We ask for the transfer. This is unit specific and can contain information that determines the transferred data
|
|
||||||
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\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!\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+1) { // +1 makes sure we read one past end and trigger the END OF DATA msg
|
|
||||||
uint8_t buf[10];
|
|
||||||
PayloadBuilder pb = pb_start(buf, 10, NULL);
|
|
||||||
pb_u32(&pb, 120); // This selects the chunk size.
|
|
||||||
// FIXME Something is wrong in the poll function, or the transport in general,
|
|
||||||
// because chunks larger than e.g. 128 bytes seem to get stuck half-transferred.
|
|
||||||
// This isn't an issue for events and regular sending, only query responses like here.
|
|
||||||
// This may also cause problems when receiving events while reading a bulk.
|
|
||||||
// It may be best to get rid of the comport and use libusb, after all.
|
|
||||||
|
|
||||||
// fprintf(stderr, "Poll read:\n");
|
|
||||||
GexMsg resp = GEX_QueryEx(unit, MSG_BULK_READ_POLL, buf,
|
|
||||||
(uint32_t) pb_length(&pb), resp0.session, true, true);
|
|
||||||
|
|
||||||
if (resp.type == MSG_ERROR) {
|
|
||||||
fprintf(stderr, "Bulk read failed! %.*s\n", resp.len, (char *) resp.payload);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resp.type == MSG_BULK_END) {
|
|
||||||
// No more data
|
|
||||||
fprintf(stderr, "Bulk read OK, closed.\n");
|
|
||||||
return at;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resp.type == MSG_BULK_DATA) {
|
|
||||||
memcpy(bulk->buffer+at, resp.payload, resp.len);
|
|
||||||
at += resp.len;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Bulk read failed! Bad response type.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return at;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bulk write to a unit, synchronous
|
|
||||||
*
|
|
||||||
* @param unit - the unit to target
|
|
||||||
* @param bulk - the bulk transport info struct
|
|
||||||
* @return true on success
|
|
||||||
*/
|
|
||||||
bool GEX_BulkWrite(GexUnit *unit, GexBulk *bulk)
|
|
||||||
{
|
|
||||||
// We ask for the transfer. This is unit specific
|
|
||||||
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\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!\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PayloadParser pp = pp_start(resp0.payload, resp0.len, NULL);
|
|
||||||
uint32_t max_size = pp_u32(&pp);
|
|
||||||
uint32_t max_chunk = pp_u32(&pp);
|
|
||||||
assert(pp.ok);
|
|
||||||
|
|
||||||
if (max_size < bulk->len) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t at = 0;
|
|
||||||
while (at < bulk->len) {
|
|
||||||
uint32_t chunk = MIN(max_chunk, bulk->len - at);
|
|
||||||
// fprintf(stderr, "Query at %d, len %d\n", (int)at, (int)chunk);
|
|
||||||
GexMsg resp = GEX_QueryEx(unit, MSG_BULK_DATA, bulk->buffer + at, chunk,
|
|
||||||
resp0.session, true, true);
|
|
||||||
at += chunk;
|
|
||||||
|
|
||||||
if (resp.type == MSG_ERROR) {
|
|
||||||
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.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conclude the transfer
|
|
||||||
GEX_SendEx(unit, MSG_BULK_END, NULL, 0, resp0.session, true);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -54,4 +54,17 @@ uint32_t GEX_BulkRead(GexUnit *unit, GexBulk *bulk);
|
|||||||
*/
|
*/
|
||||||
bool GEX_BulkWrite(GexUnit *unit, GexBulk *bulk);
|
bool GEX_BulkWrite(GexUnit *unit, GexBulk *bulk);
|
||||||
|
|
||||||
|
|
||||||
|
// extended low level stuff
|
||||||
|
|
||||||
|
/** Static query */
|
||||||
|
GexMsg GEX_QueryEx(GexUnit *unit, uint8_t cmd,
|
||||||
|
const uint8_t *payload, uint32_t len,
|
||||||
|
GexSession session, bool is_reply,
|
||||||
|
bool raw_pld);
|
||||||
|
|
||||||
|
void GEX_SendEx(GexUnit *unit, uint8_t cmd,
|
||||||
|
const uint8_t *payload, uint32_t len,
|
||||||
|
GexSession session, bool is_reply);
|
||||||
|
|
||||||
#endif //GEX_CLIENT_GEX_UNIT_H
|
#endif //GEX_CLIENT_GEX_UNIT_H
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ int main(void)
|
|||||||
// Bind ^C handler for safe shutdown
|
// Bind ^C handler for safe shutdown
|
||||||
signal(SIGINT, sigintHandler);
|
signal(SIGINT, sigintHandler);
|
||||||
|
|
||||||
gex = GEX_Init("/dev/ttyACM0", 100);
|
gex = GEX_Init("/dev/ttyACM0", 200);
|
||||||
if (!gex) exit(1);
|
if (!gex) exit(1);
|
||||||
|
|
||||||
TF_AddGenericListener(GEX_GetTF(gex), hdl_default);
|
TF_AddGenericListener(GEX_GetTF(gex), hdl_default);
|
||||||
|
|||||||
Reference in New Issue
Block a user