24 #pragma warning( disable : 4996 )
28 #define PRINT_ERROR(M)
29 #define PRINTF_ERROR(M, ...)
30 #define PRINT_SYSCALL_ERROR(M)
32 #define PRINT_ERROR(M) do { if (za_verbose) { fprintf(stderr, "(%s: %d) " M\
33 "\n", __FILE__, __LINE__); } } while(0)
34 #define PRINTF_ERROR(M, ...) do { if (za_verbose) { fprintf(stderr,\
35 "(%s: %d) " M "\n", __FILE__, __LINE__, __VA_ARGS__); } } while(0)
36 #define PRINT_SYSCALL_ERROR(M) do { if (za_verbose) { fprintf(stderr,\
37 "(%s: %d) [ERROR] " M " failed with error code %d.\n",\
38 __FILE__, __LINE__, GetLastError()); } } while(0)
40 #define SYSCALL(F) do { if ((F) == 0) {\
41 PRINT_SYSCALL_ERROR(#F); return Z_ERROR_SYSTEM_ERROR; } } while(0)
42 #define MIN(A, B) (((A) < (B)) ? (A) : (B))
44 int za_connect(z_port *port,
const char *port_name)
47 COMMTIMEOUTS timeouts;
49 if (port_name == NULL)
54 *port = CreateFileA(port_name,
55 GENERIC_READ | GENERIC_WRITE,
59 FILE_ATTRIBUTE_NORMAL,
61 if (*port == INVALID_HANDLE_VALUE)
67 SYSCALL(GetCommState(*port, &dcb));
68 dcb.DCBlength =
sizeof(DCB);
69 dcb.BaudRate = 115200;
72 dcb.fOutxCtsFlow = FALSE;
73 dcb.fOutxDsrFlow = FALSE;
74 dcb.fDtrControl = DTR_CONTROL_DISABLE;
75 dcb.fDsrSensitivity = FALSE;
76 dcb.fTXContinueOnXoff = TRUE;
79 dcb.fErrorChar = FALSE;
81 dcb.fRtsControl = RTS_CONTROL_DISABLE;
82 dcb.fAbortOnError = FALSE;
87 dcb.Parity = NOPARITY;
88 dcb.StopBits = ONESTOPBIT;
89 SYSCALL(SetCommState(*port, &dcb));
91 timeouts.ReadIntervalTimeout = MAXDWORD;
92 timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
94 timeouts.WriteTotalTimeoutMultiplier = 0;
95 timeouts.WriteTotalTimeoutConstant = 100;
96 SYSCALL(SetCommTimeouts(*port, &timeouts));
107 int za_send(z_port port,
const char *command)
119 if (command[0] !=
'/')
121 SYSCALL(WriteFile(port,
"/", 1, &nlast, NULL));
125 length = (DWORD) strlen(command);
126 SYSCALL(WriteFile(port, command, length, &nlast, NULL));
133 if (length == 0 || command[length-1] !=
'\n')
135 SYSCALL(WriteFile(port,
"\n", 1, &nlast, NULL));
150 int za_receive(z_port port,
char *destination,
int length)
158 SYSCALL(ReadFile(port, &c, 1, &nlast, NULL));
167 if (destination != NULL)
169 destination[nread] = c;
175 PRINTF_ERROR(
"[ERROR] Read destination buffer not large "
176 "enough. Recommended size: 256B. Your size: %dB.",
186 PRINT_ERROR(
"[ERROR] Reply too short. It is likely that "
187 "only a partial reply was read.");
190 if (destination != NULL)
192 destination[nread] =
'\0';
203 if (baud != 9600 && baud != 19200 && baud != 38400 && baud != 57600
206 PRINTF_ERROR(
"[ERROR] Invalid baud rate. Valid rates are "
207 "9600, 19200, 38400, 57600, and 115200 (default).\n"
208 "Your rate: %d.", baud);
212 SYSCALL(GetCommState(port, &dcb));
214 SYSCALL(SetCommState(port, &dcb));
231 COMMTIMEOUTS timeouts;
233 SYSCALL(PurgeComm(port, PURGE_RXCLEAR));
234 SYSCALL(GetCommTimeouts(port, &timeouts));
235 old_timeout = timeouts.ReadTotalTimeoutConstant;
236 timeouts.ReadTotalTimeoutConstant = 100;
237 SYSCALL(SetCommTimeouts(port, &timeouts));
241 SYSCALL(ReadFile(port, &c, 1, &nread, NULL));
245 timeouts.ReadTotalTimeoutConstant = old_timeout;
246 SYSCALL(SetCommTimeouts(port, &timeouts));
251 #elif defined(__unix__) || defined(__APPLE__)
253 #include <sys/stat.h>
254 #include <sys/types.h>
259 #define PRINT_ERROR(M)
260 #define PRINTF_ERROR(M, ...)
261 #define PRINT_SYSCALL_ERROR(M)
263 #define PRINT_ERROR(M) do { if (za_verbose) { fprintf(stderr, "(%s: %d) " M\
264 "\n", __FILE__, __LINE__); } } while(0)
265 #define PRINTF_ERROR(M, ...) do { if (za_verbose) { fprintf(stderr,\
266 "(%s: %d) " M "\n", __FILE__, __LINE__, __VA_ARGS__); } } while(0)
268 #define PRINT_SYSCALL_ERROR(M) do { if (za_verbose) {\
269 fprintf(stderr, "(%s: %d) [ERROR] " M " failed: %s.\n",\
270 __FILE__, __LINE__, strerror(errno)); } } while(0)
278 #define SYSCALL(F) do { if ((F) < 0) { PRINT_SYSCALL_ERROR(#F);\
279 return Z_ERROR_SYSTEM_ERROR; } } while(0)
281 int za_connect(z_port *port,
const char *port_name)
283 struct termios tio, orig_tio;
285 if (port == NULL || port_name == NULL)
287 PRINT_ERROR(
"[ERROR] port and port_name cannot be NULL.");
292 SYSCALL(*port = open(port_name, O_RDWR | O_NOCTTY));
293 SYSCALL(tcgetattr(*port, &orig_tio));
294 memcpy(&tio, &orig_tio,
sizeof(
struct termios));
297 tio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR
298 | IGNCR | ICRNL | IXON);
299 tio.c_oflag &= ~OPOST;
300 tio.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
301 tio.c_cflag &= ~(CSIZE | PARENB);
303 tio.c_cflag = CS8|CREAD|CLOCAL;
316 SYSCALL(cfsetospeed(&tio, B115200) & cfsetispeed(&tio, B115200));
318 while(memcmp(&orig_tio, &tio,
sizeof(
struct termios)) != 0)
320 SYSCALL(tcsetattr(*port, TCSAFLUSH, &tio));
321 SYSCALL(tcgetattr(*port, &orig_tio));
340 int za_send(z_port port,
const char *command)
352 if (command[0] !=
'/')
354 SYSCALL(nlast = write(port,
"/", 1));
357 length = strlen(command);
358 SYSCALL(nlast = write(port, command, length));
362 PRINTF_ERROR(
"[ERROR] write did not write entire message: "
363 "could only write %d bytes of %d.", nlast, length);
367 if (length == 0 || command[length-1] !=
'\n')
369 SYSCALL(nlast = write(port,
"\n", 1));
376 int za_receive(z_port port,
char *destination,
int length)
384 SYSCALL(nlast = (
int) read(port, &c, 1));
393 if (destination != NULL)
395 destination[nread] = c;
401 PRINTF_ERROR(
"[ERROR] Read destination buffer not large "
402 "enough. Recommended size: 256B. Your size: %dB.",
412 PRINT_ERROR(
"[ERROR] Reply too short. It is likely that "
413 "only a partial reply was read.");
416 if (destination != NULL)
418 destination[nread] =
'\0';
447 PRINTF_ERROR(
"[ERROR] Invalid baud rate. Valid rates are "
448 "9600, 19200, 38400, 57600, and 115200 (default).\n"
449 "Your rate: %d.", baud);
453 SYSCALL(tcgetattr(port, &tio));
454 SYSCALL(cfsetospeed(&tio, tbaud) & cfsetispeed(&tio, tbaud));
455 SYSCALL(tcsetattr(port, TCSAFLUSH, &tio));
467 SYSCALL(tcgetattr(port, &tio));
468 old_timeout = tio.c_cc[VTIME];
470 SYSCALL(tcsetattr(port, TCSANOW, &tio));
473 SYSCALL(tcflush(port, TCIFLUSH));
474 while(read(port, &c, 1) > 0);
477 tio.c_cc[VTIME] = old_timeout;
478 SYSCALL(tcsetattr(port, TCSANOW, &tio));
490 const char delim,
size_t destination_length)
494 for(i = 0; source[i] != delim && source[i] !=
'\0'
495 && i < destination_length - 1; i++)
497 destination[i] = source[i];
500 destination[i] =
'\0';
512 if (strlen(reply) < 18)
514 PRINTF_ERROR(
"[ERROR] Reply could not be decoded: shorter than expected. "
515 "It is likely that only a partial reply was read.\n"
516 "Reply value: %s", reply);
540 destination->
axis_number = (int) strtol(buffer, NULL, 10);
549 PRINTF_ERROR(
"[ERROR] Reply could not be decoded: reply flags too "
550 "long. Maximum length: %lu. Your length: %lu. Reply flags "
551 "value: %s\n.",
sizeof(destination->
reply_flags), offset,
565 PRINTF_ERROR(
"[ERROR] Reply could not be decoded: device status too "
566 "long. Expected length: %lu. Your length: %lu. Device status "
582 PRINTF_ERROR(
"[ERROR] Reply could not be decoded: warning flags too "
583 "long. Expected length: %lu. Your length: %lu. Warning flags "
595 length = strlen(reply);
598 PRINTF_ERROR(
"[ERROR] Reply could not be decoded: response data too "
599 "long. Maximum length: %lu. Your length: %lu. Data: %s.\n",
615 if (strlen(reply) < 13)
617 PRINTF_ERROR(
"[ERROR] Reply could not be decoded: shorter than expected. "
618 "It is likely that only a partial reply was read.\n"
619 "Reply value: %s", reply);
643 destination->
axis_number = (int) strtol(buffer, NULL, 10);
655 PRINTF_ERROR(
"[ERROR] Reply could not be decoded: device status too "
656 "long. Expected length: %lu. Your length: %lu. Device status "
672 PRINTF_ERROR(
"[ERROR] Reply could not be decoded: warning flags too "
673 "long. Expected length: %lu. Your length: %lu. Warning flags "
692 if (strlen(reply) < 7)
694 PRINTF_ERROR(
"[ERROR] Reply could not be decoded: shorter than expected. "
695 "It is likely that only a partial reply was read.\n"
696 "Reply value: %s", reply);
720 destination->
axis_number = (int) strtol(buffer, NULL, 10);
731 length = strlen(reply);
734 PRINTF_ERROR(
"[ERROR] Reply could not be decoded: response data too "
735 "long. Maximum length: %lu. Your length: %lu. Data: %s.\n",
760 if (destination == NULL || reply == NULL)
762 PRINT_ERROR(
"[ERROR] decoding requires both a non-NULL destination "
763 "and reply to decode.");
767 if (strlen(reply) == 0)
769 PRINT_ERROR(
"[ERROR] Reply could not be decoded: no data.");
772 message_type = reply[0];
784 PRINTF_ERROR(
"[ERROR] Reply could not be decoded: unexpected "
785 "message type. Valid types are '@' (reply), '!' (alert), "
786 "and '#' (info). Your type: '%c'. \n", message_type);
GeneratorWrapper< T > value(T &&value)
@ Z_ERROR_COULD_NOT_DECODE
@ Z_ERROR_INVALID_BAUDRATE
@ Z_ERROR_BUFFER_TOO_SMALL
int za_connect(z_port *port, const char *port_name)
int za_setbaud(z_port port, int baud)
void za_set_verbose(int value)
#define PRINT_SYSCALL_ERROR(M)
int za_receive(z_port port, char *destination, int length)
int za_decode(struct za_reply *destination, const char *reply, size_t sMaxSz)
int za_send(z_port port, const char *command, size_t sMaxSz)
int za_drain(z_port port)
#define PRINTF_ERROR(M,...)
int za_disconnect(z_port port)
static int decode_reply(struct za_reply *destination, char *reply)
static size_t copy_until_delim(char *destination, const char *source, const char delim, size_t destination_length)
static int decode_alert(struct za_reply *destination, char *reply)
static int decode_info(struct za_reply *destination, char *reply)
Provides a set of functions for interacting with Zaber devices in the ASCII protocol.