more refactoring

This commit is contained in:
XANTRONIX Development 2020-09-21 15:14:50 -05:00
parent 7d576ee9af
commit 7120e736f6
7 changed files with 165 additions and 184 deletions

View file

@ -12,8 +12,11 @@ static void usage(int argc, char **argv) {
int main(int argc, char **argv) {
skipstone_link *link;
void *buf;
uint16_t len, endpoint;
ssize_t len;
uint16_t endpoint;
if (argc != 2) {
usage(argc, argv);
@ -23,12 +26,15 @@ int main(int argc, char **argv) {
goto error_malloc_buf;
}
if ((link = skipstone_link_open_serial(argv[1])) == NULL) {
if ((link = skipstone_link_open(argv[1])) == NULL) {
goto error_link_open;
}
while (skipstone_link_recv(link, buf, &len, &endpoint, NULL) >= 0) {
printf("Received message %hu bytes for endpoint %hu\n",
while ((len = skipstone_link_recv(link,
buf,
&endpoint,
SKIPSTONE_MESSAGE_MAX_PAYLOAD)) >= 0) {
printf("Received message %zd bytes for endpoint %hu\n",
len, endpoint);
}

View file

@ -9,13 +9,20 @@
#include "../src/util.h"
struct context {
skipstone_link *link;
};
static void usage(int argc, char **argv) {
fprintf(stderr, "usage: %s /dev/rfcommX\n", argv[0]);
exit(1);
}
static int answer_phone_version_message(skipstone_message_service *service,
void *buf, uint16_t size, uint16_t id, void *context) {
void *buf,
uint16_t size,
uint16_t id,
void *context) {
const uint32_t flags = SKIPSTONE_SYSTEM_CLIENT_TELEPHONY
| SKIPSTONE_SYSTEM_CLIENT_SMS
| SKIPSTONE_SYSTEM_CLIENT_ANDROID;
@ -24,7 +31,12 @@ static int answer_phone_version_message(skipstone_message_service *service,
}
static int answer_music_message(skipstone_message_service *service,
void *buf, uint16_t size, uint16_t id, void *context) {
void *buf,
uint16_t size,
uint16_t id,
void *ctx) {
struct context *context = ctx;
uint8_t message[256];
ssize_t len;
@ -39,7 +51,9 @@ static int answer_music_message(skipstone_message_service *service,
goto error_message_pack;
}
skipstone_message_service_queue(service, message, len, 32);
if (skipstone_link_send(context->link, message, 32, len) < 0) {
goto error_link_send;
}
if ((len = skipstone_message_pack(message,
sizeof(message),
@ -54,7 +68,9 @@ static int answer_music_message(skipstone_message_service *service,
goto error_message_pack;
}
skipstone_message_service_queue(service, message, len, 32);
if (skipstone_link_send(context->link, message, 32, len) < 0) {
goto error_link_send;
}
if ((len = skipstone_message_pack(message,
sizeof(message),
@ -65,19 +81,25 @@ static int answer_music_message(skipstone_message_service *service,
goto error_message_pack;
}
skipstone_message_service_queue(service, message, len, 32);
if (skipstone_link_send(context->link, message, 32, len) < 0) {
goto error_link_send;
}
} else {
printf("Got playback command %02x\n", ((uint8_t *)buf)[0]);
}
return 0;
error_link_send:
error_message_pack:
return -1;
}
static int answer_phone_message(skipstone_message_service *service,
void *buf, uint16_t size, uint16_t id, void *context) {
void *buf,
uint16_t size,
uint16_t id,
void *context) {
printf("Got phone command %02x\n", ((uint8_t *)buf)[0]);
return 0;
@ -87,32 +109,31 @@ int main(int argc, char **argv) {
skipstone_link *link;
skipstone_message_service *service;
struct context context;
if (argc != 2) {
usage(argc, argv);
}
if ((link = skipstone_link_open_serial(argv[1])) == NULL) {
perror("skipstone_link_open_serial()");
if ((link = skipstone_link_open(argv[1])) == NULL) {
perror("skipstone_link_open()");
goto error_link_open;
}
if ((service = skipstone_message_service_new()) == NULL) {
if ((service = skipstone_message_service_new(link)) == NULL) {
perror("skipstone_message_service_new()");
goto error_message_service_new;
}
skipstone_message_service_register(service, 17, answer_phone_version_message, NULL);
skipstone_message_service_register(service, 32, answer_music_message, NULL);
skipstone_message_service_register(service, 33, answer_phone_message, NULL);
context.link = link;
skipstone_message_service_register(service, 17, answer_phone_version_message, &context);
skipstone_message_service_register(service, 32, answer_music_message, &context);
skipstone_message_service_register(service, 33, answer_phone_message, &context);
while (1) {
struct timeval timeout = {
.tv_sec = 0,
.tv_usec = 50000
};
if (skipstone_message_service_next_event(service, link, &timeout) < 0) {
perror("skipstone_message_service_next_event()");
if (skipstone_message_service_event_handle(service) < 0) {
perror("skipstone_message_service_event_handle()");
goto error_io;
}

View file

@ -6,14 +6,20 @@
typedef struct _skipstone_link skipstone_link;
skipstone_link *skipstone_link_open_serial(const char *device);
skipstone_link *skipstone_link_open(const char *device);
int skipstone_link_close(skipstone_link *link);
int skipstone_link_send(skipstone_link *link,
void *buf, uint16_t size, uint16_t id);
int skipstone_link_fd(skipstone_link *link);
int skipstone_link_recv(skipstone_link *link,
void *buf, uint16_t *size, uint16_t *id, struct timeval *timeout);
ssize_t skipstone_link_send(skipstone_link *link,
void *buf,
uint16_t id,
size_t size);
ssize_t skipstone_link_recv(skipstone_link *link,
void *buf,
uint16_t *id,
size_t size);
#endif /* _SKIPSTONE_LINK_H */

View file

@ -37,10 +37,12 @@ ssize_t skipstone_message_pack(void *message,
size_t len,
const char *template, ...);
skipstone_message_service *skipstone_message_service_new();
skipstone_message_service *skipstone_message_service_new(skipstone_link *link);
void skipstone_message_service_destroy(skipstone_message_service *service);
skipstone_link *skipstone_message_service_link(skipstone_message_service *service);
int skipstone_message_service_register(skipstone_message_service *service,
uint16_t id,
skipstone_message_handler *handler,
@ -49,12 +51,6 @@ int skipstone_message_service_register(skipstone_message_service *service,
int skipstone_message_service_deregister(skipstone_message_service *service,
uint16_t id);
int skipstone_message_service_queue(skipstone_message_service *service,
void *buf,
uint16_t size,
uint16_t id);
int skipstone_message_service_next_event(skipstone_message_service *service,
skipstone_link *link, struct timeval *timeout);
int skipstone_message_service_event_handle(skipstone_message_service *service);
#endif /* _SKIPSTONE_MESSAGE_H */

View file

@ -7,68 +7,50 @@
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <errno.h>
#include "util.h"
#include <skipstone/link.h>
#include <skipstone/message.h>
enum skipstone_link_type {
SKIPSTONE_WATCH_LINK_SERIAL = 1
};
struct _skipstone_link {
enum skipstone_link_type type;
union {
struct {
int fd;
struct termios attr_old,
attr_new;
} serial;
};
struct termios attrs;
};
skipstone_link *skipstone_link_open_serial(const char *device) {
skipstone_link *skipstone_link_open(const char *device) {
skipstone_link *link;
struct termios t;
if ((link = malloc(sizeof(*link))) == NULL) {
goto error_malloc_link;
}
link->type = SKIPSTONE_WATCH_LINK_SERIAL;
if ((link->serial.fd = open(device, O_RDWR | O_NOCTTY)) < 0) {
if ((link->fd = open(device, O_RDWR | O_NOCTTY)) < 0) {
goto error_open;
}
if (tcgetattr(link->serial.fd, &link->serial.attr_old) < 0) {
if (tcgetattr(link->fd, &link->attrs) < 0) {
goto error_io;
}
memset(&link->serial.attr_new, 0, sizeof(struct termios));
memcpy(&t, &link->attrs, sizeof(t));
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;
cfmakeraw(&t);
cfsetspeed(&t, B115200);
if (tcsetattr(link->serial.fd, TCSANOW, &link->serial.attr_new) < 0) {
if (tcsetattr(link->fd, TCSANOW, &t) < 0) {
goto error_io;
}
if (fcntl(link->serial.fd, F_SETFL, 0) < 0) {
if (fcntl(link->fd, F_SETFL, 0) < 0) {
goto error_io;
}
return link;
error_io:
close(link->serial.fd);
close(link->fd);
error_open:
free(link);
@ -77,108 +59,70 @@ error_malloc_link:
return NULL;
}
static int _watch_link_close_serial(skipstone_link *link) {
if (tcsetattr(link->serial.fd, TCSANOW, &link->serial.attr_old) < 0) {
goto error_io;
}
return close(link->serial.fd);
error_io:
return -1;
}
int skipstone_link_close(skipstone_link *link) {
switch (link->type) {
case SKIPSTONE_WATCH_LINK_SERIAL: {
return _watch_link_close_serial(link);
if (tcsetattr(link->fd, TCSANOW, &link->attrs) < 0) {
goto error_tcsetattr;
}
default: break;
}
return close(link->fd);
error_tcsetattr:
return -1;
}
int skipstone_link_send(skipstone_link *link, void *buf, uint16_t size, uint16_t id) {
int skipstone_link_fd(skipstone_link *link) {
return link->fd;
}
ssize_t skipstone_link_send(skipstone_link *link,
void *buf,
uint16_t id,
size_t size) {
skipstone_message_header header;
ssize_t wrlen;
size_t remaining = (size_t)size,
offset = 0;
ssize_t len;
if (size > SKIPSTONE_MESSAGE_MAX_PAYLOAD) {
errno = EOVERFLOW;
goto error_toobig;
}
header.size = htobe16(size);
header.id = htobe16(id);
if ((wrlen = write(link->serial.fd, &header, sizeof(header))) < 0) {
if ((len = write(link->fd, &header, sizeof(header))) < 0) {
goto error_io;
}
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;
}
return 0;
return write(link->fd, buf, size);
error_io:
error_toobig:
return -1;
}
int skipstone_link_recv(skipstone_link *link,
void *buf, uint16_t *size, uint16_t *id, struct timeval *timeout) {
ssize_t skipstone_link_recv(skipstone_link *link,
void *buf,
uint16_t *id,
size_t size) {
skipstone_message_header header;
ssize_t len_read;
size_t len_wanted, offset = 0;
size_t len;
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) {
if (read(link->fd, &header, sizeof(header)) < 0) {
goto error_io;
}
if (ready == 0) {
return 0;
}
len = be16toh(header.size);
if (len > size) {
errno = EOVERFLOW;
if (read(link->serial.fd, &header, sizeof(header)) < 0) {
goto error_io;
}
len_wanted = (size_t)be16toh(header.size);
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) {
goto error_io;
}
len_wanted -= len_read;
offset += len_read;
}
*size = be16toh(header.size);
*id = be16toh(header.id);
return 1;
return read(link->fd, buf, len);
error_io:
return -1;

View file

@ -16,8 +16,11 @@ struct endpoint {
};
struct _skipstone_message_service {
skipstone_link *link;
skipstone_map *endpoints;
skipstone_queue *pending;
size_t bufsz;
void *buf;
};
@ -97,7 +100,7 @@ error_invalid_template:
return -1;
}
skipstone_message_service *skipstone_message_service_new() {
skipstone_message_service *skipstone_message_service_new(skipstone_link *link) {
skipstone_message_service *service;
if ((service = malloc(sizeof(*service))) == NULL) {
@ -116,6 +119,9 @@ skipstone_message_service *skipstone_message_service_new() {
goto error_queue_new_pending;
}
service->link = link;
service->bufsz = SKIPSTONE_MESSAGE_MAX_PAYLOAD;
return service;
error_queue_new_pending:
@ -143,6 +149,10 @@ void skipstone_message_service_destroy(skipstone_message_service *service) {
return;
}
skipstone_link *skipstone_message_service_link(skipstone_message_service *service) {
return service->link;
}
int skipstone_message_service_register(skipstone_message_service *service,
uint16_t id, skipstone_message_handler *handler, void *context) {
struct endpoint *endpoint;
@ -166,58 +176,54 @@ int skipstone_message_service_deregister(skipstone_message_service *service,
return skipstone_map_set((skipstone_map *)service, id, NULL);
}
int skipstone_message_service_queue(skipstone_message_service *service,
void *buf,
uint16_t size,
uint16_t id) {
skipstone_message_header *message;
if ((message = malloc(sizeof(*message) + size)) == NULL) {
goto error_malloc_message;
}
message->size = size;
message->id = id;
memcpy(message + 1, buf, size);
if (skipstone_queue_add(service->pending, message) < 0) {
goto error_queue_add_pending;
}
return 0;
error_queue_add_pending:
free(message);
error_malloc_message:
return -1;
}
int skipstone_message_service_next_event(skipstone_message_service *service,
skipstone_link *link,
struct timeval *timeout) {
skipstone_message_header *message;
int skipstone_message_service_event_handle(skipstone_message_service *service) {
struct endpoint *endpoint;
uint16_t size, id;
int ready;
if ((ready = skipstone_link_recv(link, service->buf, &size, &id, timeout)) < 0) {
fd_set fds;
struct timeval timeout = {
.tv_sec = 0,
.tv_usec = 50000
};
int fd = skipstone_link_fd(service->link),
ready;
ssize_t len;
uint16_t id;
memset(&fds, '\0', sizeof(fds));
FD_SET(fd, &fds);
if ((ready = select(fd + 1,
&fds,
NULL,
NULL,
&timeout)) < 0) {
goto error_io;
} else if (ready == 0 || !FD_ISSET(fd, &fds)) {
goto done;
}
if ((len = skipstone_link_recv(service->link,
service->buf,
&id,
service->bufsz)) < 0) {
goto error_io;
}
if (ready && (endpoint = skipstone_map_get(service->endpoints, id)) != NULL) {
if (endpoint->handler(service, service->buf, size, id, endpoint->context) < 0) {
goto error_io;
}
}
while (skipstone_queue_remove(service->pending, (void **)&message)) {
if (skipstone_link_send(link, message + 1, message->size, message->id) < 0) {
if ((endpoint = skipstone_map_get(service->endpoints, id)) != NULL) {
if (endpoint->handler(service,
service->buf,
len,
id,
endpoint->context) < 0) {
goto error_io;
}
}
done:
return 0;
error_io:

View file

@ -7,6 +7,8 @@
int skipstone_system_send_client_version(skipstone_message_service *service,
uint32_t flags) {
skipstone_link *link = skipstone_message_service_link(service);
uint8_t message[25];
ssize_t len;
@ -25,16 +27,16 @@ int skipstone_system_send_client_version(skipstone_message_service *service,
goto error_message_pack;
}
if (skipstone_message_service_queue(service,
if (skipstone_link_send(link,
message,
(uint16_t)len,
SKIPSTONE_SYSTEM_ENDPOINT_PHONE_VERSION) < 0) {
goto error_message_service_queue;
SKIPSTONE_SYSTEM_ENDPOINT_PHONE_VERSION,
len) < 0) {
goto error_link_send;
}
return 0;
error_message_service_queue:
error_link_send:
error_message_pack:
return -1;
}