some changes
This commit is contained in:
parent
a4b69eb0a1
commit
6973ba305b
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@ Q=@
|
|||
CC=gcc
|
||||
|
||||
GCCCFLAGS=-Wno-format-truncation
|
||||
CFLAGS=-std=c11 -pedantic -g -Wall -pthread -D_GNU_SOURCE
|
||||
CFLAGS=-std=c11 -pedantic -g -Wall -pthread -D_GNU_SOURCE -DVERBOSE
|
||||
LDFLAGS=-lm
|
||||
|
||||
BUILD_DIR=./objects
|
||||
|
|
|
@ -41,7 +41,7 @@ and a client with this one:
|
|||
{
|
||||
"controllers": [
|
||||
{
|
||||
"tag": "Controller"
|
||||
"tag": ["Controller"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -107,8 +107,8 @@ The client configuration specifies what devices the client wants as well as unde
|
|||
{
|
||||
"controllers": [
|
||||
{
|
||||
// (required) Tag of the device to request
|
||||
"tag": "Joystick",
|
||||
// (required) Accepted tags of the device to request
|
||||
"tag": ["Joystick"],
|
||||
// (default: 6969) Vendor code for the virtual device, expects a 4 long hex string
|
||||
"vendor": "dead",
|
||||
// (default: 0420) Product code for the virtual device, expects a 4 long hex string
|
||||
|
|
38
client.c
38
client.c
|
@ -72,7 +72,7 @@ static const JSONAdapter ControllerStateAdapter = {
|
|||
};
|
||||
|
||||
static const JSONPropertyAdapter ControllerAdapterProps[] = {
|
||||
{".tag", &StringAdapter, offsetof(ClientController, tag), default_to_null, NULL },
|
||||
{".tag[]", &StringAdapter, offsetof(ClientController, tags), default_to_null, NULL },
|
||||
{".vendor", &StringAdapter, offsetof(ClientController, device_vendor), default_vendor, tsf_hex_to_i32},
|
||||
{".product", &StringAdapter, offsetof(ClientController, device_product), default_product, tsf_hex_to_i32},
|
||||
{".name", &StringAdapter, offsetof(ClientController, device_name), default_name, NULL },
|
||||
|
@ -94,6 +94,26 @@ static const JSONAdapter ConfigAdapter = {
|
|||
.size = sizeof(ClientConfig),
|
||||
};
|
||||
|
||||
// Print the current config, for debugging purposes
|
||||
static void print_config() {
|
||||
printf("CLIENT: Config\n");
|
||||
printf(" fifo_path: %s\n", config.fifo_path);
|
||||
printf(" retry_delay: %fs\n", timespec_to_double(&config.retry_delay));
|
||||
printf(" controllers: \n");
|
||||
for (size_t i = 0; i < config.controller_count; i++) {
|
||||
ClientController *ctr = &config.controllers[i];
|
||||
printf(" - tags: ['%s'", ctr->tags[0]);
|
||||
for (size_t j = 1; j < ctr->tag_count; j++) {
|
||||
printf(", '%s'", ctr->tags[j]);
|
||||
}
|
||||
printf("]\n");
|
||||
printf(" name: %s\n", ctr->device_name);
|
||||
printf(" vendor: %04x\n", ctr->device_vendor);
|
||||
printf(" product: %04x\n", ctr->device_product);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void destroy_devices(void) {
|
||||
for (int i = 0; i < config.controller_count; i++) {
|
||||
int fd = *(int *)vec_get(&devices_fd, i);
|
||||
|
@ -351,14 +371,20 @@ void setup_server(char *address, uint16_t port) {
|
|||
}
|
||||
|
||||
void build_device_request(void) {
|
||||
char **tags = malloc(config.controller_count * sizeof(char *));
|
||||
TagList * reqs = malloc(config.controller_count * sizeof(TagList *));
|
||||
for (int i = 0; i < config.controller_count; i++) {
|
||||
tags[i] = config.controllers[i].tag;
|
||||
TagList * req = &reqs[i];
|
||||
req->count = config.controllers[i].tag_count;
|
||||
req->tags = malloc(req->count * sizeof(char *));
|
||||
|
||||
for (int j = 0; j < req->count; j++) {
|
||||
req->tags[j] = config.controllers[i].tags[j];
|
||||
}
|
||||
}
|
||||
|
||||
device_request.code = Request;
|
||||
device_request.request_count = config.controller_count;
|
||||
device_request.requests = tags;
|
||||
device_request.requests = reqs;
|
||||
}
|
||||
|
||||
void client_run(char *address, uint16_t port, char *config_path) {
|
||||
|
@ -381,6 +407,10 @@ void client_run(char *address, uint16_t port, char *config_path) {
|
|||
|
||||
json_adapt(jbuf, &ConfigAdapter, &config);
|
||||
|
||||
#ifdef VERBOSE
|
||||
print_config();
|
||||
#endif
|
||||
|
||||
free(cbuf);
|
||||
fclose(configfd);
|
||||
}
|
||||
|
|
3
client.h
3
client.h
|
@ -7,7 +7,8 @@
|
|||
void client_run(char *address, uint16_t port, char *config_path);
|
||||
|
||||
typedef struct {
|
||||
char *tag;
|
||||
char **tags;
|
||||
size_t tag_count;
|
||||
int32_t device_vendor;
|
||||
int32_t device_product;
|
||||
char *device_name;
|
||||
|
|
33
hid.c
33
hid.c
|
@ -172,10 +172,21 @@ void poll_devices_init(void) {
|
|||
available_devices = vec_of(Controller *);
|
||||
}
|
||||
|
||||
// Check if tag match any of the tags specified in the tags array (of length tag_count)
|
||||
bool match_tags(char *tag, char **tags, size_t tag_count) {
|
||||
for (int i = 0; i < tag_count; i++) {
|
||||
if (strcmp(tag, tags[i]) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Block to get a device, this is thread safe
|
||||
// stop: additional condition to check before doing anything,
|
||||
// if the condition is ever found to be true the function will return immediately with a NULL pointer.
|
||||
Controller *get_device(char *tag, bool *stop) {
|
||||
Controller *get_device(char **tags, size_t tag_count, bool *stop) {
|
||||
// Check if we can get one right away
|
||||
pthread_mutex_lock(&devices_mutex);
|
||||
|
||||
|
@ -187,7 +198,7 @@ Controller *get_device(char *tag, bool *stop) {
|
|||
|
||||
for (int i = 0; i < available_devices.len; i++) {
|
||||
Controller *c = *(Controller **)vec_get(&available_devices, i);
|
||||
if (strcmp(c->ctr.tag, tag) == 0) {
|
||||
if (match_tags(c->ctr.tag, tags, tag_count)) {
|
||||
vec_remove(&available_devices, i, NULL);
|
||||
pthread_mutex_unlock(&devices_mutex);
|
||||
return c;
|
||||
|
@ -196,7 +207,7 @@ Controller *get_device(char *tag, bool *stop) {
|
|||
|
||||
for (int i = 0; i < cloneable_devices.len; i++) {
|
||||
Controller *c = *(Controller **)vec_get(&cloneable_devices, i);
|
||||
if (strcmp(c->ctr.tag, tag) == 0) {
|
||||
if (match_tags(c->ctr.tag, tags, tag_count)) {
|
||||
pthread_mutex_unlock(&devices_mutex);
|
||||
return c;
|
||||
}
|
||||
|
@ -229,7 +240,7 @@ void forget_device(Controller *c) {
|
|||
pthread_mutex_lock(&devices_mutex);
|
||||
for (int i = 0; i < cloneable_devices.len; i++) {
|
||||
Controller *d = *(Controller **)vec_get(&cloneable_devices, i);
|
||||
if (d->dev.id == c->dev.id) {
|
||||
if (d->dev.uniq == c->dev.uniq) {
|
||||
vec_remove(&cloneable_devices, i, NULL);
|
||||
break;
|
||||
}
|
||||
|
@ -239,10 +250,10 @@ void forget_device(Controller *c) {
|
|||
|
||||
// Free the name if it was allocated
|
||||
if (c->dev.name != NULL && c->dev.name != DEVICE_DEFAULT_NAME) {
|
||||
printf("HID: Forgetting device '%s' (%016lx)\n", c->dev.name, c->dev.id);
|
||||
printf("HID: Forgetting device '%s' (%016lx)\n", c->dev.name, c->dev.uniq);
|
||||
free(c->dev.name);
|
||||
} else {
|
||||
printf("HID: Forgetting device %016lx\n", c->dev.id);
|
||||
printf("HID: Forgetting device %016lx\n", c->dev.uniq);
|
||||
}
|
||||
|
||||
// try to close the file descriptor, they may be already closed if the device was unpugged.
|
||||
|
@ -253,7 +264,7 @@ void forget_device(Controller *c) {
|
|||
pthread_mutex_lock(&known_devices_mutex);
|
||||
for (int i = 0; i < known_devices.len; i++) {
|
||||
Controller *d = vec_get(&known_devices, i);
|
||||
if (d->dev.id == c->dev.id) {
|
||||
if (d->dev.uniq == c->dev.uniq) {
|
||||
vec_remove(&known_devices, i, NULL);
|
||||
break;
|
||||
}
|
||||
|
@ -343,7 +354,7 @@ void poll_devices(void) {
|
|||
pthread_mutex_lock(&known_devices_mutex);
|
||||
for (int i = 0; i < known_devices.len; i++) {
|
||||
Controller *c = vec_get(&known_devices, i);
|
||||
if (c->dev.id == dev.id) {
|
||||
if (c->dev.uniq == dev.uniq) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -412,7 +423,7 @@ void poll_devices(void) {
|
|||
// Pointer to the device in known_devices
|
||||
Controller *p = vec_get(&known_devices, index);
|
||||
|
||||
printf("HID: New device, %s [%s] (%s: %016lx)\n", name, ctr->tag, input->d_name, dev.id);
|
||||
printf("HID: New device, %s [%s] (%s: %016lx)\n", name, ctr->tag, input->d_name, dev.uniq);
|
||||
|
||||
if (ctr->duplicate) {
|
||||
pthread_mutex_lock(&devices_mutex);
|
||||
|
@ -441,11 +452,11 @@ void poll_devices(void) {
|
|||
// "Execute" a MessageControllerState: set the led color, rumble and flash using the hidraw interface (Dualshock 4 only)
|
||||
void apply_controller_state(Controller *c, MessageControllerState *state) {
|
||||
if (c->ctr.ps4_hidraw && c->dev.hidraw < 0) {
|
||||
printf("HID: Trying to apply controller state on incompatible device (%016lx)\n", c->dev.id);
|
||||
printf("HID: Trying to apply controller state on incompatible device (%016lx)\n", c->dev.uniq);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("HID: (%016lx) Controller state: #%02x%02x%02x flash: (%d, %d) rumble: (%d, %d)\n", c->dev.id, state->led[0],
|
||||
printf("HID: (%016lx) Controller state: #%02x%02x%02x flash: (%d, %d) rumble: (%d, %d)\n", c->dev.uniq, state->led[0],
|
||||
state->led[1], state->led[2], state->flash_on, state->flash_off, state->small_rumble, state->big_rumble);
|
||||
|
||||
uint8_t buf[32] = {0x05, 0xff, 0x00, 0x00};
|
||||
|
|
3
hid.h
3
hid.h
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Unique identifier for devices (provided by linux), May be the mac address
|
||||
|
@ -40,7 +41,7 @@ typedef struct {
|
|||
void *hid_thread(void *arg);
|
||||
void return_device(Controller *c);
|
||||
void forget_device(Controller *c);
|
||||
Controller *get_device(char *tag, bool *stop);
|
||||
Controller *get_device(char **tags, size_t tag_count, bool *stop);
|
||||
void apply_controller_state(Controller *c, MessageControllerState *state);
|
||||
|
||||
#endif
|
||||
|
|
24
json.c
24
json.c
|
@ -732,6 +732,12 @@ static void json_adapt_priv(uint8_t **buf, const JSONAdapter *adapter, void *ptr
|
|||
char *path) {
|
||||
JSONHeader *header = (JSONHeader *)*buf;
|
||||
|
||||
if (header->type == Array) {
|
||||
path[0] = '[';
|
||||
path[1] = ']';
|
||||
path[2] = '\0';
|
||||
}
|
||||
|
||||
if (is_primitive(adapter)) {
|
||||
// The type of a primitive adapter is stored in prop_count
|
||||
JSONType type = adapter->prop_count;
|
||||
|
@ -747,17 +753,21 @@ static void json_adapt_priv(uint8_t **buf, const JSONAdapter *adapter, void *ptr
|
|||
if (type == Boolean) {
|
||||
|
||||
*(bool *)ptr = *(uint64_t *)(*buf) == 1;
|
||||
*buf += 8;
|
||||
|
||||
} else if (type == Number) {
|
||||
|
||||
*(double *)ptr = *(double *)(*buf);
|
||||
*buf += 8;
|
||||
|
||||
} else if (type == String) {
|
||||
|
||||
char *v = malloc(header->len + 1);
|
||||
size_t len = header->len;
|
||||
char *v = malloc(header->len + 1);
|
||||
strncpy(v, (char *)(*buf), header->len);
|
||||
v[header->len] = '\0';
|
||||
*(char **)ptr = v;
|
||||
*buf += align_8(len);
|
||||
|
||||
} else {
|
||||
printf("JSON: Unknown or illegal primitive adapter of type %s\n", json_type_name(type));
|
||||
|
@ -771,12 +781,6 @@ static void json_adapt_priv(uint8_t **buf, const JSONAdapter *adapter, void *ptr
|
|||
json_adapt_set_defaults(adapter, ptr);
|
||||
}
|
||||
|
||||
if (header->type == Array) {
|
||||
path[0] = '[';
|
||||
path[1] = ']';
|
||||
path[2] = '\0';
|
||||
}
|
||||
|
||||
uint8_t buffer_small[64];
|
||||
|
||||
for (int i = 0; i < adapter->prop_count; i++) {
|
||||
|
@ -787,15 +791,17 @@ static void json_adapt_priv(uint8_t **buf, const JSONAdapter *adapter, void *ptr
|
|||
if (header->type == Array) {
|
||||
uint8_t *array_buf = *buf + sizeof(JSONHeader);
|
||||
uint8_t *end = array_buf + header->len;
|
||||
size_t len;
|
||||
|
||||
// Count length of array
|
||||
size_t len;
|
||||
for (len = 0; array_buf < end; len++) {
|
||||
array_buf += align_8(((JSONHeader *)array_buf)->len);
|
||||
array_buf += sizeof(JSONHeader);
|
||||
};
|
||||
|
||||
uint8_t *array_ptr = malloc(len * size);
|
||||
array_buf = *buf + sizeof(JSONHeader);
|
||||
|
||||
array_buf = *buf + sizeof(JSONHeader);
|
||||
for (size_t index = 0; index < len; index++) {
|
||||
path[0] = '.';
|
||||
path[1] = '\0';
|
||||
|
|
96
net.c
96
net.c
|
@ -140,8 +140,8 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
|
|||
dst->request.request_count = *(uint16_t *)(buf + 2);
|
||||
buf += 4; // 1 bytes for code, 1 byte for padding and 2 bytes for count
|
||||
|
||||
int count = dst->request.request_count;
|
||||
char **tags = malloc(count * sizeof(char *));
|
||||
int count = dst->request.request_count;
|
||||
TagList *reqs = malloc(count * sizeof(TagList));
|
||||
// The length of the message, will be updated as we read more.
|
||||
int expected_len = 3;
|
||||
|
||||
|
@ -151,25 +151,37 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
uint16_t str_len = *(uint16_t *)buf;
|
||||
TagList *tags = &reqs[i];
|
||||
tags->count = *(uint16_t *)buf;
|
||||
tags->tags = malloc(tags->count * sizeof(char *));
|
||||
buf += 2;
|
||||
|
||||
expected_len += align_2(str_len);
|
||||
if (len < expected_len) {
|
||||
return -1;
|
||||
for (int j = 0; j < tags->count; j++) {
|
||||
expected_len += 2;
|
||||
if (len < expected_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t str_len = *(uint16_t *)buf;
|
||||
buf += 2;
|
||||
|
||||
expected_len += align_2(str_len);
|
||||
if (len < expected_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *str = malloc(str_len + 1);
|
||||
str[str_len] = '\0';
|
||||
|
||||
strncpy(str, (char *)buf, str_len);
|
||||
|
||||
tags->tags[j] = str;
|
||||
|
||||
buf += align_2(str_len);
|
||||
}
|
||||
|
||||
char *str = malloc(str_len + 1);
|
||||
str[str_len] = '\0';
|
||||
|
||||
strncpy(str, (char *)buf, str_len);
|
||||
|
||||
tags[i] = str;
|
||||
|
||||
buf += align_2(str_len);
|
||||
}
|
||||
|
||||
dst->request.requests = tags;
|
||||
dst->request.requests = reqs;
|
||||
size = expected_len + 1;
|
||||
break;
|
||||
}
|
||||
|
@ -313,31 +325,40 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
|
|||
if (len < expected_len)
|
||||
return -1;
|
||||
|
||||
buf[0] = (uint8_t)msg->code;
|
||||
buf16 = (uint16_t *)(buf + 2);
|
||||
buf16[0] = msg->request.request_count;
|
||||
|
||||
buf += 4;
|
||||
buf16++;
|
||||
buf[0] = (uint8_t)msg->code;
|
||||
buf += 2;
|
||||
*(uint16_t *)buf = msg->request.request_count;
|
||||
buf += 2;
|
||||
|
||||
for (int i = 0; i < msg->request.request_count; i++) {
|
||||
int str_len = strlen(msg->request.requests[i]);
|
||||
int byte_len = align_2(str_len);
|
||||
*buf16++ = str_len;
|
||||
buf = (uint8_t *)buf16;
|
||||
|
||||
expected_len += byte_len + 2;
|
||||
if (len < expected_len) {
|
||||
return -1;
|
||||
uint16_t tag_count = msg->request.requests[i].count;
|
||||
char **tags = msg->request.requests[i].tags;
|
||||
|
||||
*(uint16_t *)buf = tag_count;
|
||||
|
||||
buf += 2;
|
||||
|
||||
for (int j = 0; j < tag_count; j++) {
|
||||
printf("about to strlen\n");
|
||||
int str_len = strlen(tags[j]);
|
||||
printf("len : %i\n", str_len);
|
||||
int byte_len = align_2(str_len);
|
||||
|
||||
expected_len += 2 + byte_len;
|
||||
if (len < expected_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*(uint16_t *)buf = str_len;
|
||||
buf += 2;
|
||||
|
||||
strncpy((char *)buf, tags[j], str_len);
|
||||
buf += byte_len;
|
||||
}
|
||||
|
||||
strncpy((char *)buf, msg->request.requests[i], str_len);
|
||||
buf += byte_len;
|
||||
// Buf has to be aligned here since byte_len is two aligned and we started off two aligned
|
||||
buf16 = (uint16_t *)buf;
|
||||
}
|
||||
|
||||
size = expected_len;
|
||||
size = expected_len + 1;
|
||||
break;
|
||||
}
|
||||
case DeviceDestroy:
|
||||
|
@ -367,7 +388,10 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
|
|||
void msg_free(Message *msg) {
|
||||
if (msg->code == Request) {
|
||||
for (int i = 0; i < msg->request.request_count; i++) {
|
||||
free(msg->request.requests[i]);
|
||||
for (int j = 0; j < msg->request.requests[i].count; j++) {
|
||||
free(msg->request.requests[i].tags[j]);
|
||||
}
|
||||
free(msg->request.requests[i].tags);
|
||||
}
|
||||
free(msg->request.requests);
|
||||
}
|
||||
|
|
12
net.h
12
net.h
|
@ -79,12 +79,18 @@ typedef struct {
|
|||
#define MSS_CONTROLLER_STATE 10
|
||||
|
||||
typedef struct {
|
||||
MessageCode code;
|
||||
char **tags;
|
||||
uint16_t count;
|
||||
} TagList;
|
||||
|
||||
char **requests;
|
||||
typedef struct {
|
||||
MessageCode code;
|
||||
// + 1 byte of padding
|
||||
|
||||
TagList *requests;
|
||||
uint16_t request_count;
|
||||
} MessageRequest;
|
||||
#define MSS_REQUEST(count) (2 + 2 * count)
|
||||
#define MSS_REQUEST(count) (2 + 2 * count + 1)
|
||||
|
||||
typedef struct {
|
||||
MessageCode code;
|
||||
|
|
60
server.c
60
server.c
|
@ -7,6 +7,7 @@
|
|||
#include "util.h"
|
||||
#include "vec.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <linux/input.h>
|
||||
#include <netinet/in.h>
|
||||
|
@ -31,7 +32,8 @@ struct Connection {
|
|||
|
||||
struct DeviceThreadArgs {
|
||||
int index;
|
||||
char *tag;
|
||||
char **tags;
|
||||
size_t tag_count;
|
||||
Controller **controller;
|
||||
struct Connection *conn;
|
||||
};
|
||||
|
@ -86,6 +88,34 @@ static sigset_t empty_sigset;
|
|||
if (sigaction(sig, &(struct sigaction){{SIG_IGN}}, NULL) != 0) \
|
||||
printf("SERVER: can't ignore " #sig ".\n")
|
||||
|
||||
static void print_config() {
|
||||
printf("SERVER: Config\n");
|
||||
printf(" retry_delay: %fs\n", (double)(config.request_timeout) / 1000.0);
|
||||
printf(" poll_interval: %fs\n", timespec_to_double(&config.poll_interval));
|
||||
printf(" controllers:\n");
|
||||
for (size_t i = 0; i < config.controller_count; i++) {
|
||||
ServerConfigController *ctr = &config.controllers[i];
|
||||
printf(" - tag: '%s'\n", ctr->tag);
|
||||
printf(" duplicate: %s\n", ctr->duplicate ? "true" : "false");
|
||||
printf(" ps4_hidraw: %s\n", ctr->ps4_hidraw ? "true" : "false");
|
||||
if (ctr->filter.name != NULL || ctr->filter.js != false || ctr->filter.uniq != 0 || ctr->filter.vendor >= 0 ||
|
||||
ctr->filter.product >= 0) {
|
||||
printf(" filter:\n");
|
||||
if (ctr->filter.name != NULL)
|
||||
printf(" name: '%s'\n", ctr->filter.name);
|
||||
if (ctr->filter.js)
|
||||
printf(" has_js\n");
|
||||
if (ctr->filter.uniq != 0)
|
||||
printf(" uniq: %016lx\n", ctr->filter.uniq);
|
||||
if (ctr->filter.vendor >= 0)
|
||||
printf(" vendor: %04x\n", ctr->filter.vendor);
|
||||
if (ctr->filter.product >= 0)
|
||||
printf(" product: %04x\n", ctr->filter.product);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void device_thread_exit(int _sig) {
|
||||
struct DeviceThreadArgs *args = pthread_getspecific(device_args_key);
|
||||
printf("CONN(%d): [%d] exiting\n", args->conn->id, args->index);
|
||||
|
@ -95,7 +125,11 @@ void device_thread_exit(int _sig) {
|
|||
return_device(ctr);
|
||||
}
|
||||
|
||||
free(args->tag);
|
||||
for (int i = 0; i < args->tag_count; i++) {
|
||||
free(args->tags[i]);
|
||||
}
|
||||
|
||||
free(args->tags);
|
||||
free(args);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
@ -113,7 +147,7 @@ void *device_thread(void *args_) {
|
|||
|
||||
while (true) {
|
||||
*args->controller = NULL;
|
||||
Controller *ctr = get_device(args->tag, &args->conn->closed);
|
||||
Controller *ctr = get_device(args->tags, args->tag_count, &args->conn->closed);
|
||||
if (ctr == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -121,7 +155,7 @@ void *device_thread(void *args_) {
|
|||
dev_info = ctr->dev.device_info;
|
||||
dev_info.index = args->index;
|
||||
|
||||
printf("CONN(%d): [%d] Found suitable [%s] device: '%s' (%016lx)\n", args->conn->id, args->index, args->tag,
|
||||
printf("CONN(%d): [%d] Found suitable [%s] device: '%s' (%016lx)\n", args->conn->id, args->index, ctr->ctr.tag,
|
||||
ctr->dev.name, ctr->dev.id);
|
||||
|
||||
// Send over device info
|
||||
|
@ -319,10 +353,16 @@ void *server_handle_conn(void *args_) {
|
|||
vec_push(&device_controllers, &ctr);
|
||||
|
||||
struct DeviceThreadArgs *dev_args = malloc(sizeof(struct DeviceThreadArgs));
|
||||
dev_args->controller = vec_get(&device_controllers, index);
|
||||
dev_args->tag = strdup(msg.request.requests[i]);
|
||||
dev_args->conn = args;
|
||||
dev_args->index = index;
|
||||
|
||||
dev_args->controller = vec_get(&device_controllers, index);
|
||||
dev_args->tag_count = msg.request.requests[i].count;
|
||||
dev_args->tags = malloc(dev_args->tag_count * sizeof(char *));
|
||||
dev_args->conn = args;
|
||||
dev_args->index = index;
|
||||
|
||||
for (int j = 0; j < dev_args->tag_count; j++) {
|
||||
dev_args->tags[j] = strdup(msg.request.requests[i].tags[j]);
|
||||
}
|
||||
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL, device_thread, dev_args);
|
||||
|
@ -382,6 +422,10 @@ void server_run(uint16_t port, char *config_path) {
|
|||
|
||||
json_adapt(jbuf, &ConfigAdapter, &config);
|
||||
|
||||
#ifdef VERBOSE
|
||||
print_config();
|
||||
#endif
|
||||
|
||||
free(cbuf);
|
||||
fclose(configfd);
|
||||
}
|
||||
|
|
8
util.c
8
util.c
|
@ -27,6 +27,12 @@ uint16_t parse_port(const char *str) {
|
|||
return n;
|
||||
}
|
||||
|
||||
double timespec_to_double(struct timespec *ts) {
|
||||
double secs = ts->tv_sec;
|
||||
secs += ts->tv_nsec / 1000000000;
|
||||
return secs;
|
||||
}
|
||||
|
||||
uint8_t parse_hex_digit(char h) {
|
||||
if (h >= '0' && h <= '9')
|
||||
return h - '0';
|
||||
|
@ -149,7 +155,7 @@ void tsf_hex_to_color(void *arg, void *ptr) {
|
|||
return;
|
||||
}
|
||||
|
||||
uint8_t *color = ptr;
|
||||
uint8_t *color = ptr;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
uint8_t digits[2] = {hex_digit(s[1 + 2 * i]), hex_digit(s[2 + 2 * i])};
|
||||
|
|
3
util.h
3
util.h
|
@ -4,6 +4,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
// Print a formatted message and exit with code 1
|
||||
void panicf(const char *fmt, ...);
|
||||
|
@ -18,6 +19,8 @@ static inline size_t align_4(size_t n) { return (((n - 1) >> 2) + 1) << 2; }
|
|||
// Align n to the next 2 boundary
|
||||
static inline size_t align_2(size_t n) { return (((n - 1) >> 1) + 1) << 1; }
|
||||
uint8_t parse_hex_digit(char h);
|
||||
// Convert timespec to double in seconds mostly for printing.
|
||||
double timespec_to_double(struct timespec *ts);
|
||||
|
||||
void default_to_null(void *ptr);
|
||||
void default_to_false(void *ptr);
|
||||
|
|
Loading…
Reference in New Issue