more refactoring
This commit is contained in:
parent
7d576ee9af
commit
7120e736f6
7 changed files with 165 additions and 184 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
136
src/link.c
136
src/link.c
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
12
src/system.c
12
src/system.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue