bulk kinda works (reading oly so far)Ã
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "TinyFrame.h"
|
#include "TinyFrame.h"
|
||||||
|
#include "utils/hexdump.h"
|
||||||
|
|
||||||
#include "gex.h"
|
#include "gex.h"
|
||||||
#include "gex_internal.h"
|
#include "gex_internal.h"
|
||||||
@@ -14,6 +15,8 @@ void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, size_t len)
|
|||||||
GexClient *gc = tf->userdata;
|
GexClient *gc = tf->userdata;
|
||||||
assert(gc->acm_fd != 0);
|
assert(gc->acm_fd != 0);
|
||||||
|
|
||||||
|
hexDump("TF_Write", buff, (uint32_t)len);
|
||||||
|
|
||||||
ssize_t rv = write(gc->acm_fd, buff, len);
|
ssize_t rv = write(gc->acm_fd, buff, len);
|
||||||
if (rv != (ssize_t)len) {
|
if (rv != (ssize_t)len) {
|
||||||
fprintf(stderr, "ERROR %d in TF write: %s\n", errno, strerror(errno));
|
fprintf(stderr, "ERROR %d in TF write: %s\n", errno, strerror(errno));
|
||||||
|
|||||||
+30
-7
@@ -8,6 +8,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <utils/hexdump.h>
|
||||||
#include "TinyFrame.h"
|
#include "TinyFrame.h"
|
||||||
|
|
||||||
#define GEX_H // to allow including other headers
|
#define GEX_H // to allow including other headers
|
||||||
@@ -138,7 +139,8 @@ GexClient *GEX_Init(const char *device, int timeout_ms)
|
|||||||
|
|
||||||
// --- Open the device ---
|
// --- Open the device ---
|
||||||
gex->acm_device = device;
|
gex->acm_device = device;
|
||||||
gex->acm_fd = serial_open(device, false, (timeout_ms + 50) / 100);
|
gex->ser_timeout = timeout_ms;
|
||||||
|
gex->acm_fd = serial_open(device);
|
||||||
if (gex->acm_fd == -1) {
|
if (gex->acm_fd == -1) {
|
||||||
free(gex);
|
free(gex);
|
||||||
fprintf(stderr, "FAILED TO CONNECT TO %s!\n", device);
|
fprintf(stderr, "FAILED TO CONNECT TO %s!\n", device);
|
||||||
@@ -177,12 +179,33 @@ void GEX_Poll(GexClient *gex)
|
|||||||
|
|
||||||
assert(gex != NULL);
|
assert(gex != NULL);
|
||||||
|
|
||||||
ssize_t len = read(gex->acm_fd, pollbuffer, TF_MAX_PAYLOAD_RX); // TODO wait only for expect amount?
|
bool first = true;
|
||||||
if (len < 0) {
|
|
||||||
fprintf(stderr, "ERROR %d in GEX Poll: %s\n", errno, strerror(errno));
|
do {
|
||||||
} else {
|
if (first) serial_shouldwait(gex->acm_fd, gex->ser_timeout);
|
||||||
TF_Accept(gex->tf, pollbuffer, (size_t) len);
|
ssize_t len = read(gex->acm_fd, pollbuffer, TF_MAX_PAYLOAD_RX);
|
||||||
}
|
if (first) {
|
||||||
|
serial_noblock(gex->acm_fd);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
fprintf(stderr, "ERROR %d in GEX Poll: %s\n", errno, strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (len == 0) {
|
||||||
|
fprintf(stderr,"No more data to read.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "rx %d bytes\n", (int) len);
|
||||||
|
hexDump("TF_Receive", pollbuffer, (uint32_t) len);
|
||||||
|
|
||||||
|
TF_Accept(gex->tf, pollbuffer, (size_t) len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Free the struct */
|
/** Free the struct */
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ struct gex_client {
|
|||||||
const char *acm_device; //!< Comport device name, might be used to reconnect (?)
|
const char *acm_device; //!< Comport device name, might be used to reconnect (?)
|
||||||
int acm_fd; //!< Open comport file descriptor
|
int acm_fd; //!< Open comport file descriptor
|
||||||
bool connected; //!< Flag that we're currently connected to the comport
|
bool connected; //!< Flag that we're currently connected to the comport
|
||||||
|
uint32_t ser_timeout; //!< Timeout for read()/write()
|
||||||
|
|
||||||
// synchronous query "hacks"
|
// synchronous query "hacks"
|
||||||
bool squery_ok; //!< flag that the query response was received
|
bool squery_ok; //!< flag that the query response was received
|
||||||
|
|||||||
+51
-39
@@ -24,33 +24,47 @@
|
|||||||
* @param lst - TF listener to handle the response, can be NULL
|
* @param lst - TF listener to handle the response, can be NULL
|
||||||
* @param userdata2 userdata2 argument for the TF listener's message
|
* @param userdata2 userdata2 argument for the TF listener's message
|
||||||
*/
|
*/
|
||||||
static void GEX_LL_Query(GexUnit *unit,
|
static void GEX_LL_Query(GexUnit *unit, uint8_t cmd,
|
||||||
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,
|
||||||
TF_Listener lst, void *userdata2)
|
TF_Listener lst, void *userdata2,
|
||||||
|
bool raw_pld)
|
||||||
{
|
{
|
||||||
assert(unit != NULL);
|
assert(unit != NULL);
|
||||||
assert(unit->gex != NULL);
|
assert(unit->gex != NULL);
|
||||||
|
|
||||||
|
fprintf(stderr, "raw pld? %d\n", raw_pld);
|
||||||
|
|
||||||
GexClient *gex = unit->gex;
|
GexClient *gex = unit->gex;
|
||||||
|
|
||||||
uint8_t callsign = unit->callsign;
|
uint8_t callsign = 0;
|
||||||
assert(callsign != 0);
|
uint8_t *pld = NULL;
|
||||||
uint8_t *pld = malloc(len + 2);
|
|
||||||
|
if (!raw_pld) {
|
||||||
|
callsign = unit->callsign;
|
||||||
|
assert(callsign != 0);
|
||||||
|
pld = malloc(len + 2);
|
||||||
|
} else {
|
||||||
|
pld = malloc(len);
|
||||||
|
}
|
||||||
|
|
||||||
assert(pld != NULL);
|
assert(pld != NULL);
|
||||||
{
|
{
|
||||||
// prefix the actual payload with the callsign and command bytes.
|
if (!raw_pld) {
|
||||||
// TODO provide TF API for sending the payload externally in smaller chunks? Will avoid the malloc here
|
// prefix the actual payload with the callsign and command bytes.
|
||||||
pld[0] = callsign;
|
// TODO provide TF API for sending the payload externally in smaller chunks? Will avoid the malloc here
|
||||||
pld[1] = cmd;
|
pld[0] = callsign;
|
||||||
memcpy(pld + 2, payload, len);
|
pld[1] = cmd;
|
||||||
|
memcpy(pld + 2, payload, len);
|
||||||
|
} else {
|
||||||
|
memcpy(pld, payload, len);
|
||||||
|
}
|
||||||
|
|
||||||
TF_Msg msg;
|
TF_Msg msg;
|
||||||
TF_ClearMsg(&msg);
|
TF_ClearMsg(&msg);
|
||||||
msg.type = MSG_UNIT_REQUEST;
|
msg.type = (raw_pld ? cmd : (uint8_t) MSG_UNIT_REQUEST);
|
||||||
msg.data = pld;
|
msg.data = pld;
|
||||||
msg.len = (TF_LEN) (len + 2);
|
msg.len = (TF_LEN) (len + (raw_pld?0:2));
|
||||||
msg.userdata = unit;
|
msg.userdata = unit;
|
||||||
msg.userdata2 = userdata2;
|
msg.userdata2 = userdata2;
|
||||||
msg.frame_id = session;
|
msg.frame_id = session;
|
||||||
@@ -66,10 +80,7 @@ void GEX_Send(GexUnit *unit, uint8_t cmd, const uint8_t *payload, uint32_t len)
|
|||||||
assert(unit != NULL);
|
assert(unit != NULL);
|
||||||
assert(unit->gex != NULL);
|
assert(unit->gex != NULL);
|
||||||
|
|
||||||
GEX_LL_Query(unit, cmd,
|
GEX_LL_Query(unit, cmd, payload, len, 0, false, NULL, NULL, false);
|
||||||
payload, len,
|
|
||||||
0, false,
|
|
||||||
NULL, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Send with no listener, don't wait for response */
|
/** Send with no listener, don't wait for response */
|
||||||
@@ -80,10 +91,7 @@ void GEX_SendEx(GexUnit *unit, uint8_t cmd,
|
|||||||
assert(unit != NULL);
|
assert(unit != NULL);
|
||||||
assert(unit->gex != NULL);
|
assert(unit->gex != NULL);
|
||||||
|
|
||||||
GEX_LL_Query(unit, cmd,
|
GEX_LL_Query(unit, cmd, payload, len, session, is_reply, NULL, NULL, false);
|
||||||
payload, len,
|
|
||||||
session, is_reply,
|
|
||||||
NULL, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** listener for the synchronous query functionality */
|
/** listener for the synchronous query functionality */
|
||||||
@@ -92,6 +100,8 @@ static TF_Result sync_query_lst(TinyFrame *tf, TF_Msg *msg)
|
|||||||
GexClient *gex = tf->userdata;
|
GexClient *gex = tf->userdata;
|
||||||
assert(gex != NULL);
|
assert(gex != NULL);
|
||||||
|
|
||||||
|
fprintf(stderr, "sync query lst called <-\n");
|
||||||
|
|
||||||
// clone the message
|
// clone the message
|
||||||
gex->squery_msg.len = msg->len;
|
gex->squery_msg.len = msg->len;
|
||||||
gex->squery_msg.unit = msg->userdata;
|
gex->squery_msg.unit = msg->userdata;
|
||||||
@@ -109,7 +119,8 @@ static TF_Result sync_query_lst(TinyFrame *tf, TF_Msg *msg)
|
|||||||
/** Static query */
|
/** Static query */
|
||||||
static GexMsg GEX_QueryEx(GexUnit *unit, uint8_t cmd,
|
static 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)
|
||||||
{
|
{
|
||||||
assert(unit != NULL);
|
assert(unit != NULL);
|
||||||
assert(unit->gex != NULL);
|
assert(unit->gex != NULL);
|
||||||
@@ -126,10 +137,7 @@ static GexMsg GEX_QueryEx(GexUnit *unit, uint8_t cmd,
|
|||||||
gex->squery_msg.len = (uint32_t) strlen("TIMEOUT");
|
gex->squery_msg.len = (uint32_t) strlen("TIMEOUT");
|
||||||
gex->squery_msg.payload = gex->squery_buffer;
|
gex->squery_msg.payload = gex->squery_buffer;
|
||||||
|
|
||||||
GEX_LL_Query(unit, cmd,
|
GEX_LL_Query(unit, cmd, payload, len, session, is_reply, sync_query_lst, NULL, raw_pld);
|
||||||
payload, len,
|
|
||||||
session, is_reply,
|
|
||||||
sync_query_lst, NULL);
|
|
||||||
|
|
||||||
GEX_Poll(gex);
|
GEX_Poll(gex);
|
||||||
|
|
||||||
@@ -145,7 +153,7 @@ GexMsg GEX_Query(GexUnit *unit, uint8_t cmd, const uint8_t *payload, uint32_t le
|
|||||||
{
|
{
|
||||||
assert(unit != NULL);
|
assert(unit != NULL);
|
||||||
assert(unit->gex != NULL);
|
assert(unit->gex != NULL);
|
||||||
return GEX_QueryEx(unit, cmd, payload, len, 0, false);
|
return GEX_QueryEx(unit, cmd, payload, len, 0, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -178,10 +186,7 @@ void GEX_QueryAsync(GexUnit *unit, uint8_t cmd, const uint8_t *payload, uint32_t
|
|||||||
assert(unit->gex != NULL);
|
assert(unit->gex != NULL);
|
||||||
|
|
||||||
// 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,
|
GEX_LL_Query(unit, cmd, payload, len, 0, false, async_query_lst, lst, false);
|
||||||
payload, len,
|
|
||||||
0, false,
|
|
||||||
async_query_lst, lst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------- BULK ----------------------------
|
// ---------------------------- BULK ----------------------------
|
||||||
@@ -196,6 +201,7 @@ void GEX_QueryAsync(GexUnit *unit, uint8_t cmd, const uint8_t *payload, uint32_t
|
|||||||
*/
|
*/
|
||||||
uint32_t GEX_BulkRead(GexUnit *unit, GexBulk *bulk)
|
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
|
// 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);
|
GexMsg resp0 = GEX_Query(unit, bulk->req_cmd, bulk->req_data, bulk->req_len);
|
||||||
|
|
||||||
@@ -220,14 +226,19 @@ uint32_t GEX_BulkRead(GexUnit *unit, GexBulk *bulk)
|
|||||||
fprintf(stderr, "Total is %d\n", total);
|
fprintf(stderr, "Total is %d\n", total);
|
||||||
|
|
||||||
uint32_t at = 0;
|
uint32_t at = 0;
|
||||||
while (at < total) {
|
while (at < total+1) { // +1 makes sure we read one past end and trigger the END OF DATA msg
|
||||||
uint8_t buf[10];
|
uint8_t buf[10];
|
||||||
PayloadBuilder pb = pb_start(buf, 10, NULL);
|
PayloadBuilder pb = pb_start(buf, 10, NULL);
|
||||||
pb_u32(&pb, 512);
|
pb_u32(&pb, 128); // This selects the chunk size.
|
||||||
|
// FIXME Something is wrong in the poll function, or the transport in general,
|
||||||
|
// because chunks larger than e.g. 130 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.
|
||||||
|
|
||||||
GexMsg resp = GEX_QueryEx(unit, MSG_BULK_READ_POLL,
|
fprintf(stderr, "Poll read:\n");
|
||||||
buf, (uint32_t) pb_length(&pb),
|
GexMsg resp = GEX_QueryEx(unit, MSG_BULK_READ_POLL, buf,
|
||||||
resp0.session, true);
|
(uint32_t) pb_length(&pb), resp0.session, true, true);
|
||||||
|
|
||||||
if (resp.type == MSG_ERROR) {
|
if (resp.type == MSG_ERROR) {
|
||||||
fprintf(stderr, "Bulk read failed! %.*s\n", resp.len, (char *) resp.payload);
|
fprintf(stderr, "Bulk read failed! %.*s\n", resp.len, (char *) resp.payload);
|
||||||
@@ -236,6 +247,7 @@ uint32_t GEX_BulkRead(GexUnit *unit, GexBulk *bulk)
|
|||||||
|
|
||||||
if (resp.type == MSG_BULK_END) {
|
if (resp.type == MSG_BULK_END) {
|
||||||
// No more data
|
// No more data
|
||||||
|
fprintf(stderr, "Bulk read OK, closed.\n");
|
||||||
return at;
|
return at;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,9 +301,9 @@ bool GEX_BulkWrite(GexUnit *unit, GexBulk *bulk)
|
|||||||
uint32_t at = 0;
|
uint32_t at = 0;
|
||||||
while (at < bulk->len) {
|
while (at < bulk->len) {
|
||||||
uint32_t chunk = MIN(max_chunk, bulk->len - at);
|
uint32_t chunk = MIN(max_chunk, bulk->len - at);
|
||||||
GexMsg resp = GEX_QueryEx(unit, MSG_BULK_DATA,
|
fprintf(stderr, "Query at %d, len %d\n", (int)at, (int)chunk);
|
||||||
bulk->buffer+at, chunk,
|
GexMsg resp = GEX_QueryEx(unit, MSG_BULK_DATA, bulk->buffer + at, chunk,
|
||||||
resp0.session, true);
|
resp0.session, true, true);
|
||||||
at += chunk;
|
at += chunk;
|
||||||
|
|
||||||
if (resp.type == MSG_ERROR) {
|
if (resp.type == MSG_ERROR) {
|
||||||
|
|||||||
+35
-19
@@ -27,8 +27,8 @@ static int set_interface_attribs(int fd, int speed, int parity)
|
|||||||
tty.c_lflag = 0; // no signaling chars, no echo,
|
tty.c_lflag = 0; // no signaling chars, no echo,
|
||||||
// no canonical processing
|
// no canonical processing
|
||||||
tty.c_oflag = 0; // no remapping, no delays
|
tty.c_oflag = 0; // no remapping, no delays
|
||||||
tty.c_cc[VMIN] = 0; // read doesn't block
|
tty.c_cc[VMIN] = 0; // read doesn't block
|
||||||
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
tty.c_cc[VTIME] = 2; // 0.2 seconds read timeout
|
||||||
|
|
||||||
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
|
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
|
||||||
|
|
||||||
@@ -46,23 +46,8 @@ static int set_interface_attribs(int fd, int speed, int parity)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_blocking(int fd, bool should_block, int read_timeout_0s1)
|
|
||||||
{
|
|
||||||
struct termios tty;
|
|
||||||
memset(&tty, 0, sizeof tty);
|
|
||||||
if (tcgetattr(fd, &tty) != 0) {
|
|
||||||
fprintf(stderr, "error %d from tggetattr\n", errno);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tty.c_cc[VMIN] = (cc_t) (should_block ? 1 : 0);
|
int serial_open(const char *device)
|
||||||
tty.c_cc[VTIME] = (cc_t) read_timeout_0s1;
|
|
||||||
|
|
||||||
if (tcsetattr(fd, TCSANOW, &tty) != 0)
|
|
||||||
fprintf(stderr, "error %d setting term attributes\n", errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
int serial_open(const char *device, bool blocking, int timeout_0s1)
|
|
||||||
{
|
{
|
||||||
int fd = open (device, O_RDWR | O_NOCTTY | O_SYNC);
|
int fd = open (device, O_RDWR | O_NOCTTY | O_SYNC);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@@ -71,7 +56,38 @@ int serial_open(const char *device, bool blocking, int timeout_0s1)
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_interface_attribs(fd, B115200, 0);
|
set_interface_attribs(fd, B115200, 0);
|
||||||
set_blocking (fd, blocking, timeout_0s1);
|
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serial_noblock(int fd)
|
||||||
|
{
|
||||||
|
struct termios tty;
|
||||||
|
memset(&tty, 0, sizeof tty);
|
||||||
|
if (tcgetattr(fd, &tty) != 0) {
|
||||||
|
fprintf(stderr, "error %d from tggetattr\n", errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty.c_cc[VMIN] = (cc_t) 0;
|
||||||
|
tty.c_cc[VTIME] = (cc_t) 0;
|
||||||
|
|
||||||
|
if (tcsetattr(fd, TCSANOW, &tty) != 0)
|
||||||
|
fprintf(stderr, "error %d setting term attributes\n", errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_shouldwait(int fd, int ms)
|
||||||
|
{
|
||||||
|
struct termios tty;
|
||||||
|
memset(&tty, 0, sizeof tty);
|
||||||
|
if (tcgetattr(fd, &tty) != 0) {
|
||||||
|
fprintf(stderr, "error %d from tggetattr\n", errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty.c_cc[VMIN] = (cc_t) 0;
|
||||||
|
tty.c_cc[VTIME] = (cc_t) (ms+50/100);
|
||||||
|
|
||||||
|
if (tcsetattr(fd, TCSANOW, &tty) != 0)
|
||||||
|
fprintf(stderr, "error %d setting term attributes\n", errno);
|
||||||
|
}
|
||||||
|
|||||||
+5
-3
@@ -8,10 +8,12 @@
|
|||||||
* Open a serial port
|
* Open a serial port
|
||||||
*
|
*
|
||||||
* @param device - device to open, e.g. /dev/ttyACM0
|
* @param device - device to open, e.g. /dev/ttyACM0
|
||||||
* @param blocking - true for `read()` to block until at least 1 byte is read
|
|
||||||
* @param timeout_0s1 - timeout for `read()` - if blocking, starts after the first character
|
|
||||||
* @return file descriptor
|
* @return file descriptor
|
||||||
*/
|
*/
|
||||||
int serial_open(const char *device, bool blocking, int timeout_0s1);
|
int serial_open(const char *device);
|
||||||
|
|
||||||
|
void serial_shouldwait(int fd, int ms);
|
||||||
|
|
||||||
|
void serial_noblock(int fd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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", 200);
|
gex = GEX_Init("/dev/ttyACM0", 100);
|
||||||
if (!gex) exit(1);
|
if (!gex) exit(1);
|
||||||
|
|
||||||
TF_AddGenericListener(GEX_GetTF(gex), hdl_default);
|
TF_AddGenericListener(GEX_GetTF(gex), hdl_default);
|
||||||
@@ -67,7 +67,7 @@ int main(void)
|
|||||||
};
|
};
|
||||||
uint32_t actuallyRead = GEX_BulkRead(test, &br);
|
uint32_t actuallyRead = GEX_BulkRead(test, &br);
|
||||||
fprintf(stderr, "Read %d bytes:\n", actuallyRead);
|
fprintf(stderr, "Read %d bytes:\n", actuallyRead);
|
||||||
fprintf(stderr, "%*.s", actuallyRead, buffr);
|
fprintf(stderr, "%.*s", actuallyRead, buffr);
|
||||||
|
|
||||||
fprintf(stderr, "ALL OK, ending.\n");
|
fprintf(stderr, "ALL OK, ending.\n");
|
||||||
GEX_DeInit(gex);
|
GEX_DeInit(gex);
|
||||||
|
|||||||
Reference in New Issue
Block a user