2017-11-23 17:22:36 +00:00
|
|
|
#include <stdlib.h>
|
2017-11-21 00:59:27 +00:00
|
|
|
#include <string.h>
|
2017-11-21 22:24:52 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/ioctl.h>
|
2017-11-29 20:33:01 -06:00
|
|
|
#include <sys/select.h>
|
2017-11-24 17:43:03 +00:00
|
|
|
#include "util.h"
|
2017-11-21 00:59:27 +00:00
|
|
|
|
2017-11-23 17:22:36 +00:00
|
|
|
#include <skipstone/link.h>
|
|
|
|
#include <skipstone/message.h>
|
2017-11-21 00:59:27 +00:00
|
|
|
|
2017-11-23 17:22:36 +00:00
|
|
|
enum skipstone_link_type {
|
2017-11-21 00:59:27 +00:00
|
|
|
SKIPSTONE_WATCH_LINK_SERIAL = 1
|
|
|
|
};
|
|
|
|
|
2017-11-23 17:22:36 +00:00
|
|
|
struct _skipstone_link {
|
|
|
|
enum skipstone_link_type type;
|
2017-11-21 00:59:27 +00:00
|
|
|
|
|
|
|
union {
|
2017-11-21 22:24:52 +00:00
|
|
|
struct {
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
struct termios attr_old,
|
|
|
|
attr_new;
|
|
|
|
} serial;
|
2017-11-21 00:59:27 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2017-11-23 17:22:36 +00:00
|
|
|
skipstone_link *skipstone_link_open_serial(const char *device) {
|
|
|
|
skipstone_link *link;
|
2017-11-21 00:59:27 +00:00
|
|
|
|
|
|
|
if ((link = malloc(sizeof(*link))) == NULL) {
|
|
|
|
goto error_malloc_link;
|
|
|
|
}
|
|
|
|
|
2017-11-21 22:24:52 +00:00
|
|
|
link->type = SKIPSTONE_WATCH_LINK_SERIAL;
|
|
|
|
|
|
|
|
if ((link->serial.fd = open(device, O_RDWR | O_NOCTTY)) < 0) {
|
|
|
|
goto error_open;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tcgetattr(link->serial.fd, &link->serial.attr_old) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&link->serial.attr_new, 0, sizeof(struct termios));
|
2017-11-21 00:59:27 +00:00
|
|
|
|
2017-11-21 22:24:52 +00:00
|
|
|
link->serial.attr_new.c_cflag = CS8 | HUPCL;
|
|
|
|
link->serial.attr_new.c_ispeed = B115200;
|
|
|
|
link->serial.attr_new.c_ospeed = B115200;
|
|
|
|
link->serial.attr_new.c_iflag = IGNPAR;
|
|
|
|
link->serial.attr_new.c_oflag = 0;
|
|
|
|
link->serial.attr_new.c_lflag = 0;
|
|
|
|
link->serial.attr_new.c_cc[VTIME] = 0;
|
|
|
|
link->serial.attr_new.c_cc[VMIN] = 1;
|
|
|
|
|
|
|
|
if (tcsetattr(link->serial.fd, TCSANOW, &link->serial.attr_new) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fcntl(link->serial.fd, F_SETFL, 0) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
2017-11-21 00:59:27 +00:00
|
|
|
|
|
|
|
return link;
|
|
|
|
|
2017-11-21 22:24:52 +00:00
|
|
|
error_io:
|
|
|
|
close(link->serial.fd);
|
|
|
|
|
|
|
|
error_open:
|
|
|
|
free(link);
|
|
|
|
|
2017-11-21 00:59:27 +00:00
|
|
|
error_malloc_link:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-11-23 17:22:36 +00:00
|
|
|
static int _watch_link_close_serial(skipstone_link *link) {
|
2017-11-21 22:24:52 +00:00
|
|
|
if (tcsetattr(link->serial.fd, TCSANOW, &link->serial.attr_old) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
return close(link->serial.fd);
|
2017-11-21 00:59:27 +00:00
|
|
|
|
2017-11-21 22:24:52 +00:00
|
|
|
error_io:
|
|
|
|
return -1;
|
2017-11-21 00:59:27 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 17:22:36 +00:00
|
|
|
int skipstone_link_close(skipstone_link *link) {
|
2017-11-21 22:24:52 +00:00
|
|
|
switch (link->type) {
|
|
|
|
case SKIPSTONE_WATCH_LINK_SERIAL: {
|
|
|
|
return _watch_link_close_serial(link);
|
|
|
|
}
|
2017-11-21 00:59:27 +00:00
|
|
|
|
2017-11-21 22:24:52 +00:00
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
2017-11-21 00:59:27 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 18:02:38 +00:00
|
|
|
int skipstone_link_send(skipstone_link *link, void *buf, uint16_t size, uint16_t id) {
|
|
|
|
skipstone_message_header header;
|
2017-11-21 22:24:52 +00:00
|
|
|
|
2017-11-21 23:30:25 +00:00
|
|
|
ssize_t wrlen;
|
|
|
|
|
|
|
|
size_t remaining = (size_t)size,
|
|
|
|
offset = 0;
|
|
|
|
|
2017-11-21 22:24:52 +00:00
|
|
|
if (size > SKIPSTONE_MESSAGE_MAX_PAYLOAD) {
|
|
|
|
goto error_toobig;
|
|
|
|
}
|
|
|
|
|
2017-11-23 18:02:38 +00:00
|
|
|
header.size = htobe16(size);
|
|
|
|
header.id = htobe16(id);
|
2017-11-21 22:24:52 +00:00
|
|
|
|
2017-11-21 23:30:25 +00:00
|
|
|
if ((wrlen = write(link->serial.fd, &header, sizeof(header))) < 0) {
|
2017-11-21 22:24:52 +00:00
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2017-11-21 23:30:25 +00:00
|
|
|
while (remaining) {
|
|
|
|
if ((wrlen = write(link->serial.fd, (uint8_t *)buf + offset, remaining)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
remaining -= (size_t)wrlen;
|
|
|
|
offset += (size_t)wrlen;
|
2017-11-21 22:24:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
error_toobig:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-11-29 20:33:01 -06:00
|
|
|
int skipstone_link_recv(skipstone_link *link,
|
|
|
|
void *buf, uint16_t *size, uint16_t *id, struct timeval *timeout) {
|
2017-11-23 18:02:38 +00:00
|
|
|
skipstone_message_header header;
|
2017-11-21 22:24:52 +00:00
|
|
|
|
2017-11-22 20:29:00 +00:00
|
|
|
ssize_t len_read;
|
|
|
|
size_t len_wanted, offset = 0;
|
2017-11-21 22:24:52 +00:00
|
|
|
|
2017-11-29 20:33:01 -06:00
|
|
|
fd_set fds;
|
|
|
|
int ready;
|
|
|
|
|
|
|
|
FD_ZERO(&fds);
|
|
|
|
FD_SET(link->serial.fd, &fds);
|
|
|
|
|
|
|
|
if ((ready = select(1 + link->serial.fd, &fds, NULL, NULL, timeout)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ready == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-11-22 20:29:00 +00:00
|
|
|
if (read(link->serial.fd, &header, sizeof(header)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
2017-11-21 22:24:52 +00:00
|
|
|
|
2017-11-22 20:29:00 +00:00
|
|
|
len_wanted = (size_t)be16toh(header.size);
|
2017-11-21 22:24:52 +00:00
|
|
|
|
2017-11-22 20:29:00 +00:00
|
|
|
if (len_wanted > SKIPSTONE_MESSAGE_MAX_PAYLOAD) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (len_wanted) {
|
|
|
|
if ((len_read = read(link->serial.fd, (uint8_t *)buf + offset, len_wanted)) < 0) {
|
2017-11-21 22:24:52 +00:00
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2017-11-22 20:29:00 +00:00
|
|
|
len_wanted -= len_read;
|
|
|
|
offset += len_read;
|
|
|
|
}
|
2017-11-21 22:24:52 +00:00
|
|
|
|
2017-11-23 18:02:38 +00:00
|
|
|
*size = be16toh(header.size);
|
|
|
|
*id = be16toh(header.id);
|
2017-11-21 22:24:52 +00:00
|
|
|
|
2017-11-29 20:33:01 -06:00
|
|
|
return 1;
|
2017-11-21 00:59:27 +00:00
|
|
|
|
2017-11-21 22:24:52 +00:00
|
|
|
error_io:
|
|
|
|
return -1;
|
2017-11-21 00:59:27 +00:00
|
|
|
}
|