pretty much done with the ser conversion, one bug left (recursive struct (de)serialization)

This commit is contained in:
viandoxdev 2023-05-09 22:12:46 +02:00
parent eec4668856
commit f6c5e749a6
No known key found for this signature in database
GPG Key ID: AF1410C5BC10AA25
12 changed files with 713 additions and 689 deletions

View File

@ -2,7 +2,7 @@ Q=@
CC=gcc CC=gcc
GCCCFLAGS=-Wno-format-truncation GCCCFLAGS=-Wno-format-truncation
CFLAGS=-std=c11 -pedantic -g -Wall -pthread -D_GNU_SOURCE CFLAGS=-std=gnu11 -pedantic -g -Wall -pthread -D_GNU_SOURCE -fsanitize=address
LDFLAGS=-lm LDFLAGS=-lm
# The root for /sys and /dev needs to be moved in docker, this should stay empty in most cases # The root for /sys and /dev needs to be moved in docker, this should stay empty in most cases

152
client.c
View File

@ -37,13 +37,13 @@ static struct pollfd *socket_poll = &poll_fds[1];
static int fifo = -1; static int fifo = -1;
static int sock = -1; static int sock = -1;
// static to avoid having this on the stack because a message is about 2kb in memory // static to avoid having this on the stack because a message is about 2kb in memory
static Message message; static DeviceMessage message;
static Vec devices_fd; static Vec devices_fd;
static Vec devices_info; static Vec devices_info;
static ClientConfig config; static ClientConfig config;
static MessageRequest device_request; static DeviceRequest device_request;
static void default_fifo_path(void *ptr) { *(char **)ptr = (char *)FIFO_PATH; } static void default_fifo_path(void *ptr) { *(char **)ptr = (char *)FIFO_PATH; }
static void default_retry_delay(void *ptr) { *(struct timespec *)ptr = CONNECTION_RETRY_DELAY; } static void default_retry_delay(void *ptr) { *(struct timespec *)ptr = CONNECTION_RETRY_DELAY; }
@ -58,17 +58,17 @@ static void default_to_white(void *ptr) {
} }
static const JSONPropertyAdapter ControllerStateAdapterProps[] = { static const JSONPropertyAdapter ControllerStateAdapterProps[] = {
{".led_color", &StringAdapter, offsetof(MessageControllerState, led), default_to_white, tsf_hex_to_color }, {".led_color", &StringAdapter, offsetof(DeviceControllerState, led), default_to_white, tsf_hex_to_color },
{".rumble.0", &NumberAdapter, offsetof(MessageControllerState, small_rumble), default_to_zero_u8, tsf_num_to_u8_clamp}, {".rumble.0", &NumberAdapter, offsetof(DeviceControllerState, small_rumble), default_to_zero_u8, tsf_num_to_u8_clamp},
{".rumble.1", &NumberAdapter, offsetof(MessageControllerState, big_rumble), default_to_zero_u8, tsf_num_to_u8_clamp}, {".rumble.1", &NumberAdapter, offsetof(DeviceControllerState, big_rumble), default_to_zero_u8, tsf_num_to_u8_clamp},
{".flash.0", &NumberAdapter, offsetof(MessageControllerState, flash_on), default_to_zero_u8, tsf_num_to_u8_clamp}, {".flash.0", &NumberAdapter, offsetof(DeviceControllerState, flash_on), default_to_zero_u8, tsf_num_to_u8_clamp},
{".flash.1", &NumberAdapter, offsetof(MessageControllerState, flash_off), default_to_zero_u8, tsf_num_to_u8_clamp}, {".flash.1", &NumberAdapter, offsetof(DeviceControllerState, flash_off), default_to_zero_u8, tsf_num_to_u8_clamp},
{".index", &NumberAdapter, offsetof(MessageControllerState, index), default_to_zero_u32, tsf_num_to_int } {".index", &NumberAdapter, offsetof(DeviceControllerState, index), default_to_zero_u32, tsf_num_to_int }
}; };
static const JSONAdapter ControllerStateAdapter = { static const JSONAdapter ControllerStateAdapter = {
.props = (JSONPropertyAdapter *)ControllerStateAdapterProps, .props = (JSONPropertyAdapter *)ControllerStateAdapterProps,
.prop_count = sizeof(ControllerStateAdapterProps) / sizeof(JSONPropertyAdapter), .prop_count = sizeof(ControllerStateAdapterProps) / sizeof(JSONPropertyAdapter),
.size = sizeof(MessageControllerState), .size = sizeof(DeviceControllerState),
}; };
static const JSONPropertyAdapter ControllerAdapterProps[] = { static const JSONPropertyAdapter ControllerAdapterProps[] = {
@ -127,12 +127,12 @@ static void print_config() {
void destroy_devices(void) { void destroy_devices(void) {
for (int i = 0; i < config.slot_count; i++) { for (int i = 0; i < config.slot_count; i++) {
int fd = *(int *)vec_get(&devices_fd, i); int fd = *(int *)vec_get(&devices_fd, i);
MessageDeviceInfo *info = vec_get(&devices_info, i); DeviceInfo *info = vec_get(&devices_info, i);
if (info->code == DeviceInfo) { if (info->tag == DeviceTagInfo) {
ioctl(fd, UI_DEV_DESTROY); ioctl(fd, UI_DEV_DESTROY);
info->code = NoMessage; info->tag = DeviceTagNone;
} }
} }
} }
@ -142,8 +142,8 @@ bool device_exists(int index) {
return false; return false;
} }
MessageDeviceInfo *info = vec_get(&devices_info, index); DeviceInfo *info = vec_get(&devices_info, index);
return info->code == DeviceInfo; return info->tag == DeviceTagInfo;
} }
void device_destroy(int slot) { void device_destroy(int slot) {
@ -153,15 +153,15 @@ void device_destroy(int slot) {
int fd = *(int *)vec_get(&devices_fd, slot); int fd = *(int *)vec_get(&devices_fd, slot);
MessageDeviceInfo *info = vec_get(&devices_info, slot); DeviceInfo *info = vec_get(&devices_info, slot);
if (info->code == DeviceInfo) { if (info->tag == DeviceTagInfo) {
ioctl(fd, UI_DEV_DESTROY); ioctl(fd, UI_DEV_DESTROY);
info->code = NoMessage; info->tag = DeviceTagNone;
} }
} }
void device_init(MessageDeviceInfo *dev) { void device_init(DeviceInfo *dev) {
if (dev->slot >= devices_info.len) { if (dev->slot >= devices_info.len) {
printf("CLIENT: Got wrong device index\n"); printf("CLIENT: Got wrong device index\n");
return; return;
@ -172,35 +172,36 @@ void device_init(MessageDeviceInfo *dev) {
int fd = *(int *)vec_get(&devices_fd, dev->slot); int fd = *(int *)vec_get(&devices_fd, dev->slot);
// Abs // Abs
if (dev->abs_count > 0) { if (dev->abs.len > 0) {
ioctl(fd, UI_SET_EVBIT, EV_ABS); ioctl(fd, UI_SET_EVBIT, EV_ABS);
for (int i = 0; i < dev->abs_count; i++) { for (int i = 0; i < dev->abs.len; i++) {
struct uinput_abs_setup setup = {0}; struct uinput_abs_setup setup = {0};
setup.code = dev->abs_id[i]; Abs abs = dev->abs.data[i];
setup.absinfo.minimum = dev->abs_min[i]; setup.code = abs.id;
setup.absinfo.maximum = dev->abs_max[i]; setup.absinfo.minimum = abs.min;
setup.absinfo.fuzz = dev->abs_fuzz[i]; setup.absinfo.maximum = abs.max;
setup.absinfo.flat = dev->abs_flat[i]; setup.absinfo.fuzz = abs.fuzz;
setup.absinfo.resolution = dev->abs_res[i]; setup.absinfo.flat = abs.flat;
setup.absinfo.resolution = abs.res;
setup.absinfo.value = 0; setup.absinfo.value = 0;
ioctl(fd, UI_ABS_SETUP, &setup); ioctl(fd, UI_ABS_SETUP, &setup);
} }
} }
// Rel // Rel
if (dev->rel_count > 0) { if (dev->rel.len > 0) {
ioctl(fd, UI_SET_EVBIT, EV_REL); ioctl(fd, UI_SET_EVBIT, EV_REL);
for (int i = 0; i < dev->rel_count; i++) { for (int i = 0; i < dev->rel.len; i++) {
ioctl(fd, UI_SET_RELBIT, dev->rel_id[i]); ioctl(fd, UI_SET_RELBIT, dev->rel.data[i].id);
} }
} }
// Key // Key
if (dev->key_count > 0) { if (dev->key.len > 0) {
ioctl(fd, UI_SET_EVBIT, EV_KEY); ioctl(fd, UI_SET_EVBIT, EV_KEY);
for (int i = 0; i < dev->key_count; i++) { for (int i = 0; i < dev->key.len; i++) {
ioctl(fd, UI_SET_KEYBIT, dev->key_id[i]); ioctl(fd, UI_SET_KEYBIT, dev->key.data[i].id);
} }
} }
@ -217,11 +218,11 @@ void device_init(MessageDeviceInfo *dev) {
ioctl(fd, UI_DEV_SETUP, &setup); ioctl(fd, UI_DEV_SETUP, &setup);
ioctl(fd, UI_DEV_CREATE); ioctl(fd, UI_DEV_CREATE);
MessageDeviceInfo *dst = vec_get(&devices_info, dev->slot); DeviceInfo *dst = vec_get(&devices_info, dev->slot);
memcpy(dst, dev, sizeof(MessageDeviceInfo)); memcpy(dst, dev, sizeof(DeviceInfo));
printf("CLIENT: Got device [%d]: '%s' (abs: %d, rel: %d, key: %d)\n", dev->slot, ctr->device_name, dev->abs_count, printf("CLIENT: Got device [%d]: '%s' (abs: %d, rel: %d, key: %d)\n", dev->slot, ctr->device_name, dev->abs.len, dev->rel.len,
dev->rel_count, dev->key_count); dev->key.len);
} }
// Send an event to uinput, device must exist // Send an event to uinput, device must exist
@ -241,33 +242,34 @@ bool device_emit(int index, uint16_t type, uint16_t id, uint32_t value) {
} }
// Update device with report // Update device with report
void device_handle_report(MessageDeviceReport *report) { void device_handle_report(DeviceReport *report) {
if (!device_exists(report->slot)) { if (!device_exists(report->slot)) {
printf("CLIENT: [%d] Got report before device info\n", report->slot); printf("CLIENT: [%d] Got report before device info\n", report->slot);
return; return;
} }
MessageDeviceInfo *info = vec_get(&devices_info, report->slot); DeviceInfo *info = vec_get(&devices_info, report->slot);
if (report->abs_count != info->abs_count || report->rel_count != info->rel_count || report->key_count != info->key_count) { if (report->abs.len != info->abs.len || report->rel.len != info->rel.len || report->key.len != info->key.len) {
printf("CLIENT: Report doesn't match with device info\n"); printf("CLIENT: Report doesn't match with device info (expected %u/%u/%u, got %u/%u/%u)\n", info->abs.len, info->rel.len,
info->key.len, report->abs.len, report->rel.len, report->key.len);
return; return;
} }
for (int i = 0; i < report->abs_count; i++) { for (int i = 0; i < report->abs.len; i++) {
if (device_emit(report->slot, EV_ABS, info->abs_id[i], report->abs[i]) != 0) { if (device_emit(report->slot, EV_ABS, info->abs.data[i].id, report->abs.data[i]) != 0) {
printf("CLIENT: Error writing abs event to uinput\n"); printf("CLIENT: Error writing abs event to uinput\n");
} }
} }
for (int i = 0; i < report->rel_count; i++) { for (int i = 0; i < report->rel.len; i++) {
if (device_emit(report->slot, EV_REL, info->rel_id[i], report->rel[i]) != 0) { if (device_emit(report->slot, EV_REL, info->rel.data[i].id, report->rel.data[i]) != 0) {
printf("CLIENT: Error writing rel event to uinput\n"); printf("CLIENT: Error writing rel event to uinput\n");
} }
} }
for (int i = 0; i < report->key_count; i++) { for (int i = 0; i < report->key.len; i++) {
if (device_emit(report->slot, EV_KEY, info->key_id[i], (uint32_t)(!report->key[i]) - 1) != 0) { if (device_emit(report->slot, EV_KEY, info->key.data[i].id, (uint32_t)(!report->key.data[i]) - 1) != 0) {
printf("CLIENT: Error writing key event to uinput\n"); printf("CLIENT: Error writing key event to uinput\n");
} }
} }
@ -278,10 +280,10 @@ void device_handle_report(MessageDeviceReport *report) {
void setup_devices(void) { void setup_devices(void) {
devices_fd = vec_of(int); devices_fd = vec_of(int);
devices_info = vec_of(MessageDeviceInfo); devices_info = vec_of(DeviceInfo);
MessageDeviceInfo no_info = {0}; DeviceInfo no_info = {0};
no_info.code = NoMessage; no_info.tag = DeviceTagNone;
for (int i = 0; i < config.slot_count; i++) { for (int i = 0; i < config.slot_count; i++) {
int fd = open(FSROOT "/dev/uinput", O_WRONLY | O_NONBLOCK); int fd = open(FSROOT "/dev/uinput", O_WRONLY | O_NONBLOCK);
@ -350,9 +352,9 @@ void connect_server(void) {
socket_poll->fd = sock; socket_poll->fd = sock;
printf("CLIENT: Connected !\n"); printf("CLIENT: Connected !\n");
uint8_t buf[2048] __attribute__((aligned(4))) = {0}; uint8_t buf[2048] __attribute__((aligned(8))) = {0};
int len = msg_serialize(buf, 2048, (Message *)&device_request); int len = msg_device_serialize(buf, 2048, (DeviceMessage *)&device_request);
if (len > 0) { if (len > 0) {
if (send(sock, buf, len, 0) > 0) { if (send(sock, buf, len, 0) > 0) {
printf("CLIENT: Sent device request\n"); printf("CLIENT: Sent device request\n");
@ -382,20 +384,20 @@ void setup_server(char *address, uint16_t port) {
} }
void build_device_request(void) { void build_device_request(void) {
TagList *reqs = malloc(config.slot_count * sizeof(TagList)); device_request.tag = DeviceTagRequest;
device_request.requests.len = config.slot_count;
device_request.requests.data = malloc(config.slot_count * sizeof(TagList));
for (int i = 0; i < config.slot_count; i++) { for (int i = 0; i < config.slot_count; i++) {
TagList *req = &reqs[i]; TagList *list = &device_request.requests.data[i];
req->count = config.slots[i].controller_count; list->tags.len = config.slots[i].controller_count;
req->tags = malloc(req->count * sizeof(char *)); list->tags.data = malloc(list->tags.len * sizeof(typeof(*list->tags.data)));
for (int j = 0; j < req->count; j++) { for (int j = 0; j < list->tags.len; j++) {
req->tags[j] = config.slots[i].controllers[j].tag; char *name = config.slots[i].controllers[j].tag;
list->tags.data[j].name.len = strlen(name);
list->tags.data[j].name.data = name;
} }
} }
device_request.code = Request;
device_request.request_count = config.slot_count;
device_request.requests = reqs;
} }
void client_run(char *address, uint16_t port, char *config_path) { void client_run(char *address, uint16_t port, char *config_path) {
@ -431,10 +433,10 @@ void client_run(char *address, uint16_t port, char *config_path) {
setup_devices(); setup_devices();
setup_server(address, port); setup_server(address, port);
uint8_t buf[2048] __attribute__((aligned(4))); uint8_t buf[2048] __attribute__((aligned(8)));
uint8_t json_buf[2048] __attribute__((aligned(8))); uint8_t json_buf[2048] __attribute__((aligned(8)));
while (1) { while (true) {
int rc = poll(poll_fds, 2, -1); int rc = poll(poll_fds, 2, -1);
if (rc < 0) { if (rc < 0) {
perror("CLIENT: Error on poll"); perror("CLIENT: Error on poll");
@ -451,11 +453,11 @@ void client_run(char *address, uint16_t port, char *config_path) {
if (rc < 0) { if (rc < 0) {
printf("CLIENT: Error when parsing fifo message as json (%s at index %lu)\n", json_strerr(), json_errloc()); printf("CLIENT: Error when parsing fifo message as json (%s at index %lu)\n", json_strerr(), json_errloc());
} else { } else {
MessageControllerState msg; DeviceControllerState msg;
msg.code = ControllerState; msg.tag = DeviceTagControllerState;
json_adapt(json_buf, &ControllerStateAdapter, &msg); json_adapt(json_buf, &ControllerStateAdapter, &msg);
int len = msg_serialize(buf, 2048, (Message *)&msg); int len = msg_device_serialize(buf, 2048, (DeviceMessage *)&msg);
if (len > 0) { if (len > 0) {
if (send(sock, buf, len, 0) > 0) { if (send(sock, buf, len, 0) > 0) {
printf("CLIENT: Sent controller state: #%02x%02x%02x flash: (%d, %d) rumble: " printf("CLIENT: Sent controller state: #%02x%02x%02x flash: (%d, %d) rumble: "
@ -479,7 +481,7 @@ void client_run(char *address, uint16_t port, char *config_path) {
continue; continue;
} }
int msg_len = msg_deserialize(buf, len, &message); int msg_len = msg_device_deserialize(buf, len, &message);
// We've got data from the server // We've got data from the server
if (msg_len < 0) { if (msg_len < 0) {
recv(sock, buf, 2048, 0); recv(sock, buf, 2048, 0);
@ -500,15 +502,15 @@ void client_run(char *address, uint16_t port, char *config_path) {
recv(sock, buf, msg_len, 0); recv(sock, buf, msg_len, 0);
if (message.code == DeviceInfo) { if (message.tag == DeviceTagInfo) {
if (device_exists(message.device_info.slot)) { if (device_exists(message.info.slot)) {
printf("CLIENT: Got more than one device info for same device\n"); printf("CLIENT: Got more than one device info for same device\n");
} }
device_init((MessageDeviceInfo *)&message); device_init((DeviceInfo *)&message);
} else if (message.code == DeviceReport) { } else if (message.tag == DeviceTagReport) {
device_handle_report((MessageDeviceReport *)&message); device_handle_report((DeviceReport *)&message);
} else if (message.code == DeviceDestroy) { } else if (message.tag == DeviceTagDestroy) {
device_destroy(message.destroy.index); device_destroy(message.destroy.index);
printf("CLIENT: Lost device %d\n", message.destroy.index); printf("CLIENT: Lost device %d\n", message.destroy.index);
} else { } else {

35
hid.c
View File

@ -55,10 +55,10 @@ uniq_t parse_uniq(char uniq[17]) {
// Finish setup of a partially initialized device (set device_info and mapping) // Finish setup of a partially initialized device (set device_info and mapping)
void setup_device(PhysicalDevice *dev) { void setup_device(PhysicalDevice *dev) {
dev->device_info.code = DeviceInfo; dev->device_info.tag = DeviceTagInfo;
dev->device_info.abs_count = 0; dev->device_info.abs.len = 0;
dev->device_info.rel_count = 0; dev->device_info.rel.len = 0;
dev->device_info.key_count = 0; dev->device_info.key.len = 0;
for (int i = 0; i < ABS_CNT; i++) for (int i = 0; i < ABS_CNT; i++)
dev->mapping.abs_indices[i] = -1; dev->mapping.abs_indices[i] = -1;
@ -93,26 +93,27 @@ void setup_device(PhysicalDevice *dev) {
struct input_absinfo abs; struct input_absinfo abs;
ioctl(dev->event, EVIOCGABS(i), &abs); ioctl(dev->event, EVIOCGABS(i), &abs);
uint16_t index = dev->device_info.abs_count++; uint16_t index = dev->device_info.abs.len++;
dev->device_info.abs_min[index] = abs.minimum; Abs *dev_abs = &dev->device_info.abs.data[index];
dev->device_info.abs_max[index] = abs.maximum; dev_abs->min = abs.minimum;
dev->device_info.abs_fuzz[index] = abs.fuzz; dev_abs->max = abs.maximum;
dev->device_info.abs_flat[index] = abs.flat; dev_abs->fuzz = abs.fuzz;
dev->device_info.abs_res[index] = abs.resolution; dev_abs->flat = abs.flat;
dev_abs->res = abs.resolution;
dev_abs->id = i;
// Bidirectional mapping id <-> index // Bidirectional mapping id <-> index
// We need this to avoid wasting space in packets because ids are sparse // We need this to avoid wasting space in packets because ids are sparse
dev->device_info.abs_id[index] = i; dev->mapping.abs_indices[i] = index;
dev->mapping.abs_indices[i] = index;
} else if (type == EV_REL) { } else if (type == EV_REL) {
uint16_t index = dev->device_info.rel_count++; uint16_t index = dev->device_info.rel.len++;
dev->device_info.rel_id[index] = i; dev->device_info.rel.data[index].id = i;
dev->mapping.rel_indices[i] = index; dev->mapping.rel_indices[i] = index;
} else if (type == EV_KEY) { } else if (type == EV_KEY) {
uint16_t index = dev->device_info.key_count++; uint16_t index = dev->device_info.key.len++;
dev->device_info.key_id[index] = i; dev->device_info.key.data[index].id = i;
dev->mapping.key_indices[i] = index; dev->mapping.key_indices[i] = index;
} }
} }
@ -445,7 +446,7 @@ void poll_devices(void) {
} }
// "Execute" a MessageControllerState: set the led color, rumble and flash using the hidraw interface (Dualshock 4 only) // "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) { void apply_controller_state(Controller *c, DeviceControllerState *state) {
if (c->ctr.ps4_hidraw && c->dev.hidraw < 0) { if (c->ctr.ps4_hidraw && c->dev.hidraw < 0) {
printf("HID: Trying to apply controller state on incompatible device (%lu)\n", c->dev.id); printf("HID: Trying to apply controller state on incompatible device (%lu)\n", c->dev.id);
return; return;

4
hid.h
View File

@ -30,7 +30,7 @@ typedef struct {
uint64_t id; uint64_t id;
char *name; char *name;
DeviceMap mapping; DeviceMap mapping;
MessageDeviceInfo device_info; DeviceInfo device_info;
} PhysicalDevice; } PhysicalDevice;
typedef struct { typedef struct {
@ -42,6 +42,6 @@ void *hid_thread(void *arg);
void return_device(Controller *c); void return_device(Controller *c);
void forget_device(Controller *c); void forget_device(Controller *c);
bool get_device(char **tags, size_t tag_count, bool *stop, Controller *res, uint8_t *index); bool get_device(char **tags, size_t tag_count, bool *stop, Controller *res, uint8_t *index);
void apply_controller_state(Controller *c, MessageControllerState *state); void apply_controller_state(Controller *c, DeviceControllerState *state);
#endif #endif

600
net.c
View File

@ -1,434 +1,286 @@
// Generated file, do not edit (its not like it'll explode if you do, but its better not to)
#include "net.h" #include "net.h"
#include "util.h"
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
// Deserialize the message in buf, buf must be at least 4 aligned. Returns -1 on error, otherwise returns 0 int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) {
// and writes result to dst const byte *base_buf = buf;
int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) { if(len < 2 * MSG_MAGIC_SIZE)
{
if (len <= MAGIC_SIZE) {
return -1;
}
if (*(MAGIC_TYPE *)buf != MAGIC_BEG) {
printf("NET: No magic in message\n");
return -1;
}
buf += MAGIC_SIZE;
len -= MAGIC_SIZE;
}
// Decrement len so that it becomes the len of the data without the code.
if (len-- < 1)
return -1; return -1;
// This ensures that only a byte is read instead of a full enum value *(MsgMagic*)buf = MSG_MAGIC_START;
uint8_t code_byte = buf[0]; buf += MSG_MAGIC_SIZE;
MessageCode code = (MessageCode)code_byte; switch(msg->tag) {
uint32_t size = 0; case DeviceTagNone:
break;
uint16_t abs, rel, key, *buf16; case DeviceTagInfo: {
uint8_t index, slot; *(uint16_t *)buf = DeviceTagInfo;
*(uint16_t *)&buf[2] = msg->info.key.len;
switch (code) { *(uint8_t *)&buf[4] = msg->info.slot;
case DeviceInfo: *(uint8_t *)&buf[5] = msg->info.index;
if (len < 7) *(uint8_t *)&buf[6] = msg->info.abs.len;
return -1; *(uint8_t *)&buf[7] = msg->info.rel.len;
slot = buf[2]; buf += 8;
index = buf[3]; for(size_t i = 0; i < msg->info.abs.len; i++) {
// buf + 4: a byte for, code, padding, slot, index typeof(msg->info.abs.data[i]) e0 = msg->info.abs.data[i];
buf16 = (uint16_t *)(buf + 4); *(uint32_t *)&buf[0] = e0.min;
abs = buf16[0]; *(uint32_t *)&buf[4] = e0.max;
rel = buf16[1]; *(uint32_t *)&buf[8] = e0.fuzz;
key = buf16[2]; *(uint32_t *)&buf[12] = e0.flat;
buf += 12; *(uint32_t *)&buf[16] = e0.res;
if (MSS_DEVICE_INFO(abs, rel, key) > len) *(uint16_t *)&buf[20] = e0.id;
return -1;
dst->device_info.code = code;
dst->device_info.slot = slot;
dst->device_info.index = index;
dst->device_info.abs_count = abs;
dst->device_info.rel_count = rel;
dst->device_info.key_count = key;
// SOA in c but serialized as AOS
for (int i = 0; i < abs; i++) {
// buf + 4: 2 bytes for id and 2 bytes of padding
uint32_t *buf32 = (uint32_t *)(buf + 4);
dst->device_info.abs_id[i] = *(uint16_t *)buf;
dst->device_info.abs_min[i] = buf32[0];
dst->device_info.abs_max[i] = buf32[1];
dst->device_info.abs_fuzz[i] = buf32[2];
dst->device_info.abs_flat[i] = buf32[3];
dst->device_info.abs_res[i] = buf32[4];
buf += 24; buf += 24;
} }
for(size_t i = 0; i < msg->info.rel.len; i++) {
for (int i = 0; i < rel; i++) { typeof(msg->info.rel.data[i]) e0 = msg->info.rel.data[i];
dst->device_info.rel_id[i] = *(uint16_t *)buf; *(uint16_t *)&buf[0] = e0.id;
buf += 2; buf += 2;
} }
for(size_t i = 0; i < msg->info.key.len; i++) {
for (int i = 0; i < key; i++) { typeof(msg->info.key.data[i]) e0 = msg->info.key.data[i];
dst->device_info.key_id[i] = *(uint16_t *)buf; *(uint16_t *)&buf[0] = e0.id;
buf += 2; buf += 2;
} }
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
size = MSS_DEVICE_INFO(abs, rel, key) + 1;
break; break;
case DeviceReport: }
if (len < 7) case DeviceTagReport: {
return -1; *(uint16_t *)buf = DeviceTagReport;
*(uint16_t *)&buf[2] = msg->report.key.len;
slot = buf[2]; *(uint8_t *)&buf[4] = msg->report.slot;
index = buf[3]; *(uint8_t *)&buf[5] = msg->report.index;
// buf + 4: a byte for, code, padding, slot and index *(uint8_t *)&buf[6] = msg->report.abs.len;
buf16 = (uint16_t *)(buf + 4); *(uint8_t *)&buf[7] = msg->report.rel.len;
abs = buf16[0]; buf += 8;
rel = buf16[1]; for(size_t i = 0; i < msg->report.abs.len; i++) {
key = buf16[2]; typeof(msg->report.abs.data[i]) e0 = msg->report.abs.data[i];
buf += 12; *(uint32_t *)&buf[0] = e0;
if (len < MSS_DEVICE_REPORT(abs, rel, key))
return -1;
dst->device_report.code = code;
dst->device_report.slot = slot;
dst->device_report.index = index;
dst->device_report.abs_count = abs;
dst->device_report.rel_count = rel;
dst->device_report.key_count = key;
for (int i = 0; i < abs; i++) {
dst->device_report.abs[i] = *(uint32_t *)buf;
buf += 4; buf += 4;
} }
for(size_t i = 0; i < msg->report.rel.len; i++) {
for (int i = 0; i < rel; i++) { typeof(msg->report.rel.data[i]) e0 = msg->report.rel.data[i];
dst->device_report.rel[i] = *(uint32_t *)buf; *(uint32_t *)&buf[0] = e0;
buf += 4; buf += 4;
} }
for(size_t i = 0; i < msg->report.key.len; i++) {
for (int i = 0; i < key; i++) typeof(msg->report.key.data[i]) e0 = msg->report.key.data[i];
dst->device_report.key[i] = *(buf++); *(uint8_t *)&buf[0] = e0;
buf += 1;
buf += align_4(key) - key; }
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
size = MSS_DEVICE_REPORT(abs, rel, key) + 1;
break; break;
case ControllerState: }
if (len < MSS_CONTROLLER_STATE) case DeviceTagControllerState: {
return -1; *(uint16_t *)buf = DeviceTagControllerState;
*(uint16_t *)&buf[2] = msg->controller_state.index;
dst->code = code; *(uint8_t *)&buf[4] = msg->controller_state.led[0];
dst->controller_state.index = *(uint16_t *)(buf + 2); *(uint8_t *)&buf[5] = msg->controller_state.led[1];
dst->controller_state.led[0] = buf[4]; *(uint8_t *)&buf[6] = msg->controller_state.led[2];
dst->controller_state.led[1] = buf[5]; *(uint8_t *)&buf[7] = msg->controller_state.small_rumble;
dst->controller_state.led[2] = buf[6]; *(uint8_t *)&buf[8] = msg->controller_state.big_rumble;
dst->controller_state.small_rumble = buf[7]; *(uint8_t *)&buf[9] = msg->controller_state.flash_on;
dst->controller_state.big_rumble = buf[8]; *(uint8_t *)&buf[10] = msg->controller_state.flash_off;
dst->controller_state.flash_on = buf[9]; buf += 16;
dst->controller_state.flash_off = buf[10];
size = MSS_CONTROLLER_STATE + 1;
buf += size;
break; break;
case Request: { }
if (len < 3) case DeviceTagRequest: {
return -1; *(uint16_t *)buf = DeviceTagRequest;
msg->request._version = 1UL;
dst->code = code; *(uint64_t *)&buf[8] = msg->request._version;
dst->request.request_count = *(uint16_t *)(buf + 2); *(uint16_t *)&buf[16] = msg->request.requests.len;
buf += 4; // 1 bytes for code, 1 byte for padding and 2 bytes for count buf += 18;
for(size_t i = 0; i < msg->request.requests.len; i++) {
int count = dst->request.request_count; typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i];
TagList *reqs = malloc(count * sizeof(TagList)); *(uint16_t *)&buf[0] = e0.tags.len;
// The length of the message, will be updated as we read more.
int expected_len = 3;
for (int i = 0; i < dst->request.request_count; i++) {
expected_len += 2;
if (len < expected_len) {
return -1;
}
TagList *tags = &reqs[i];
tags->count = *(uint16_t *)buf;
tags->tags = malloc(tags->count * sizeof(char *));
buf += 2; buf += 2;
for(size_t i = 0; i < e0.tags.len; i++) {
for (int j = 0; j < tags->count; j++) { typeof(e0.tags.data[i]) e1 = e0.tags.data[i];
expected_len += 2; *(uint16_t *)&buf[0] = e1.name.len;
if (len < expected_len) {
return -1;
}
uint16_t str_len = *(uint16_t *)buf;
buf += 2; buf += 2;
for(size_t i = 0; i < e1.name.len; i++) {
expected_len += align_2(str_len); typeof(e1.name.data[i]) e2 = e1.name.data[i];
if (len < expected_len) { *(char *)&buf[0] = e2;
return -1; buf += 1;
} }
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 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);
} }
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1);
} }
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
dst->request.requests = reqs;
size = expected_len + 1;
break; break;
} }
case DeviceDestroy: case DeviceTagDestroy: {
if (len < MSS_DESTROY) *(uint16_t *)buf = DeviceTagDestroy;
return -1; *(uint16_t *)&buf[2] = msg->destroy.index;
buf += 8;
dst->code = code;
dst->destroy.index = *(uint16_t *)(buf + 2);
size = MSS_DESTROY + 1;
buf += size;
break; break;
default:
return -1;
} }
if (align_m(size) + MAGIC_SIZE > len + 1) {
return -1;
} }
*(MsgMagic*)buf = MSG_MAGIC_END;
// WARN: This is technically bad, but should be ok nonetheless buf += MSG_MAGIC_SIZE;
MAGIC_TYPE *mbuf = (MAGIC_TYPE *)align_m((uintptr_t)buf); if(buf > base_buf + len)
if (*mbuf != MAGIC_END) {
printf("NET: Magic not found\n");
return -1; return -1;
} return (int)(buf - base_buf);
return align_m(size) + 2 * MAGIC_SIZE;
} }
// Serialize the message msg in buf, buf must be at least 4 aligned. Returns -1 on error (buf not big enough); int msg_device_deserialize(const byte *buf, size_t len, DeviceMessage *msg) {
int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) { const byte *base_buf = buf;
// If len is less than the two magic and the code we can't serialize any message if(len < 2 * MSG_MAGIC_SIZE)
if (len < MAGIC_SIZE * 2 + 1)
return -1; return -1;
if(*(MsgMagic*)buf != MSG_MAGIC_START)
*(MAGIC_TYPE *)buf = MAGIC_BEG; return -1;
buf += MAGIC_SIZE; buf += MSG_MAGIC_SIZE;
len -= MAGIC_SIZE + 1; DeviceTag tag = *(uint16_t*)buf;
switch(tag) {
uint16_t abs, rel, key, *buf16; case DeviceTagNone:
uint32_t size; break;
case DeviceTagInfo: {
switch (msg->code) { msg->tag = DeviceTagInfo;
case DeviceInfo: msg->info.key.len = *(uint16_t *)&buf[2];
abs = msg->device_info.abs_count; msg->info.slot = *(uint8_t *)&buf[4];
rel = msg->device_info.rel_count; msg->info.index = *(uint8_t *)&buf[5];
key = msg->device_info.key_count; msg->info.abs.len = *(uint8_t *)&buf[6];
if (len < MSS_DEVICE_INFO(abs, rel, key)) msg->info.rel.len = *(uint8_t *)&buf[7];
return -1; buf += 8;
for(size_t i = 0; i < msg->info.abs.len; i++) {
buf[0] = (uint8_t)msg->code; typeof(&msg->info.abs.data[i]) e0 = &msg->info.abs.data[i];
// 1 byte of padding e0->min = *(uint32_t *)&buf[0];
buf[2] = (uint8_t)msg->device_info.slot; e0->max = *(uint32_t *)&buf[4];
buf[3] = (uint8_t)msg->device_info.index; e0->fuzz = *(uint32_t *)&buf[8];
// buf + 4: a byte for, code, padding, slot, index e0->flat = *(uint32_t *)&buf[12];
buf16 = (uint16_t *)(buf + 4); e0->res = *(uint32_t *)&buf[16];
buf16[0] = abs; e0->id = *(uint16_t *)&buf[20];
buf16[1] = rel;
buf16[2] = key;
buf += 12;
// Back to 4 aligned
for (int i = 0; i < abs; i++) {
// buf + 4: 2 bytes for id and 2 bytes of padding
uint32_t *buf32 = (uint32_t *)(buf + 4);
*(uint16_t *)buf = msg->device_info.abs_id[i];
buf32[0] = msg->device_info.abs_min[i];
buf32[1] = msg->device_info.abs_max[i];
buf32[2] = msg->device_info.abs_fuzz[i];
buf32[3] = msg->device_info.abs_flat[i];
buf32[4] = msg->device_info.abs_res[i];
buf += 24; buf += 24;
} }
// Still 4 aligned for(size_t i = 0; i < msg->info.rel.len; i++) {
for (int i = 0; i < rel; i++) { typeof(&msg->info.rel.data[i]) e0 = &msg->info.rel.data[i];
*(uint16_t *)buf = msg->device_info.rel_id[i]; e0->id = *(uint16_t *)&buf[0];
buf += 2; buf += 2;
} }
for(size_t i = 0; i < msg->info.key.len; i++) {
for (int i = 0; i < key; i++) { typeof(&msg->info.key.data[i]) e0 = &msg->info.key.data[i];
*(uint16_t *)buf = msg->device_info.key_id[i]; e0->id = *(uint16_t *)&buf[0];
buf += 2; buf += 2;
} }
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
size = MSS_DEVICE_INFO(abs, rel, key) + 1;
break; break;
case DeviceReport: }
abs = msg->device_report.abs_count; case DeviceTagReport: {
rel = msg->device_report.rel_count; msg->tag = DeviceTagReport;
key = msg->device_report.key_count; msg->report.key.len = *(uint16_t *)&buf[2];
if (len < MSS_DEVICE_REPORT(abs, rel, key)) msg->report.slot = *(uint8_t *)&buf[4];
return -1; msg->report.index = *(uint8_t *)&buf[5];
msg->report.abs.len = *(uint8_t *)&buf[6];
buf[0] = (uint8_t)msg->code; msg->report.rel.len = *(uint8_t *)&buf[7];
// 1 byte of padding buf += 8;
buf[2] = msg->device_report.slot; for(size_t i = 0; i < msg->report.abs.len; i++) {
buf[3] = msg->device_report.index; typeof(&msg->report.abs.data[i]) e0 = &msg->report.abs.data[i];
// buf + 4: a byte for, code, padding, slot and index *e0 = *(uint32_t *)&buf[0];
buf16 = (uint16_t *)(buf + 4);
buf16[0] = abs;
buf16[1] = rel;
buf16[2] = key;
buf += 12;
// We're 4 aligned already
for (int i = 0; i < abs; i++) {
*(uint32_t *)buf = msg->device_report.abs[i];
buf += 4; buf += 4;
} }
// Still 4 aligned for(size_t i = 0; i < msg->report.rel.len; i++) {
for (int i = 0; i < rel; i++) { typeof(&msg->report.rel.data[i]) e0 = &msg->report.rel.data[i];
*(uint32_t *)buf = msg->device_report.rel[i]; *e0 = *(uint32_t *)&buf[0];
buf += 4; buf += 4;
} }
// Doesn't matter since we're writing individual bytes for(size_t i = 0; i < msg->report.key.len; i++) {
for (int i = 0; i < key; i++) typeof(&msg->report.key.data[i]) e0 = &msg->report.key.data[i];
*(buf++) = msg->device_report.key[i]; *e0 = *(uint8_t *)&buf[0];
buf += 1;
size = MSS_DEVICE_REPORT(abs, rel, key) + 1; }
buf += align_4(key) - key; buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
break; break;
case ControllerState: }
if (len < MSS_CONTROLLER_STATE) case DeviceTagControllerState: {
return -1; msg->tag = DeviceTagControllerState;
msg->controller_state.index = *(uint16_t *)&buf[2];
buf[0] = (uint8_t)msg->code; msg->controller_state.led[0] = *(uint8_t *)&buf[4];
msg->controller_state.led[1] = *(uint8_t *)&buf[5];
*(uint16_t *)(buf + 2) = msg->controller_state.index; msg->controller_state.led[2] = *(uint8_t *)&buf[6];
msg->controller_state.small_rumble = *(uint8_t *)&buf[7];
buf[4] = msg->controller_state.led[0]; msg->controller_state.big_rumble = *(uint8_t *)&buf[8];
buf[5] = msg->controller_state.led[1]; msg->controller_state.flash_on = *(uint8_t *)&buf[9];
buf[6] = msg->controller_state.led[2]; msg->controller_state.flash_off = *(uint8_t *)&buf[10];
buf[7] = msg->controller_state.small_rumble; buf += 16;
buf[8] = msg->controller_state.big_rumble;
buf[9] = msg->controller_state.flash_on;
buf[10] = msg->controller_state.flash_off;
size = MSS_CONTROLLER_STATE + 1;
buf += size;
break; break;
case Request: { }
int expected_len = MSS_REQUEST(msg->request.request_count); case DeviceTagRequest: {
if (len < expected_len) msg->tag = DeviceTagRequest;
return -1; msg->request._version = *(uint64_t *)&buf[8];
msg->request.requests.len = *(uint16_t *)&buf[16];
buf[0] = (uint8_t)msg->code; buf += 18;
buf += 2; msg->request.requests.data = malloc(msg->request.requests.len * sizeof(typeof(*msg->request.requests.data)));
*(uint16_t *)buf = msg->request.request_count; for(size_t i = 0; i < msg->request.requests.len; i++) {
buf += 2; typeof(&msg->request.requests.data[i]) e0 = &msg->request.requests.data[i];
e0->tags.len = *(uint16_t *)&buf[0];
for (int i = 0; i < msg->request.request_count; i++) {
uint16_t tag_count = msg->request.requests[i].count;
char **tags = msg->request.requests[i].tags;
*(uint16_t *)buf = tag_count;
buf += 2; buf += 2;
e0->tags.data = malloc(e0->tags.len * sizeof(typeof(*e0->tags.data)));
for (int j = 0; j < tag_count; j++) { for(size_t i = 0; i < e0->tags.len; i++) {
int str_len = strlen(tags[j]); typeof(&e0->tags.data[i]) e1 = &e0->tags.data[i];
int byte_len = align_2(str_len); e1->name.len = *(uint16_t *)&buf[0];
expected_len += 2 + byte_len;
if (len < expected_len) {
return -1;
}
*(uint16_t *)buf = str_len;
buf += 2; buf += 2;
e1->name.data = malloc(e1->name.len * sizeof(typeof(*e1->name.data)));
strncpy((char *)buf, tags[j], str_len); for(size_t i = 0; i < e1->name.len; i++) {
buf += byte_len; typeof(&e1->name.data[i]) e2 = &e1->name.data[i];
*e2 = *(char *)&buf[0];
buf += 1;
}
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1);
} }
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1);
} }
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
size = expected_len + 1; if(msg->request._version != 1UL) {
break; printf("Mismatched version: peers aren't the same version, expected 1 got %lu.\n", msg->request._version);
} msg_device_free(msg);
case DeviceDestroy:
if (len < MSS_DESTROY)
return -1; return -1;
}
buf[0] = (uint8_t)msg->code;
*(uint16_t *)(buf + 2) = msg->controller_state.index;
size = MSS_DESTROY + 1;
buf += size;
break; break;
default: }
printf("ERR(msg_serialize): Trying to serialize unknown message of code %d\n", msg->code); case DeviceTagDestroy: {
msg->tag = DeviceTagDestroy;
msg->destroy.index = *(uint16_t *)&buf[2];
buf += 8;
break;
}
}
if(*(MsgMagic*)buf != MSG_MAGIC_END) {
msg_device_free(msg);
return -1; return -1;
} }
buf += MSG_MAGIC_SIZE;
if (align_m(size) + MAGIC_SIZE > len) { if(buf > base_buf + len) {
msg_device_free(msg);
return -1; return -1;
} }
return (int)(buf - base_buf);
MAGIC_TYPE *mbuf = (MAGIC_TYPE *)align_m((uintptr_t)buf);
*mbuf = MAGIC_END;
return align_m(size) + MAGIC_SIZE * 2;
} }
void msg_free(Message *msg) { void msg_device_free(DeviceMessage *msg) {
if (msg->code == Request) { switch(msg->tag) {
for (int i = 0; i < msg->request.request_count; i++) { case DeviceTagNone:
for (int j = 0; j < msg->request.requests[i].count; j++) { break;
free(msg->request.requests[i].tags[j]); case DeviceTagInfo: {
break;
}
case DeviceTagReport: {
break;
}
case DeviceTagControllerState: {
break;
}
case DeviceTagRequest: {
for(size_t i = 0; i < msg->request.requests.len; i++) {
typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i];
for(size_t i = 0; i < e0.tags.len; i++) {
typeof(e0.tags.data[i]) e1 = e0.tags.data[i];
free(e1.name.data);
} }
free(msg->request.requests[i].tags); free(e0.tags.data);
}
free(msg->request.requests);
}
}
void print_message_buffer(const uint8_t *buf, int len) {
bool last_beg = false;
for (int i = 0; i < len; i++) {
if (i + MAGIC_SIZE <= len) {
MAGIC_TYPE magic = *(MAGIC_TYPE *)(&buf[i]);
if (magic == MAGIC_BEG) {
printf(" \033[32m%08X\033[0m", magic);
i += MAGIC_SIZE - 1;
last_beg = true;
continue;
} else if (magic == MAGIC_END) {
printf(" \033[32m%08X\033[0m", magic);
i += MAGIC_SIZE - 1;
continue;
}
}
if (last_beg) {
last_beg = false;
printf(" \033[034m%02X\033[0m", buf[i]);
} else {
printf(" %02X", buf[i]);
} }
free(msg->request.requests.data);
break;
}
case DeviceTagDestroy: {
break;
}
} }
} }

217
net.h
View File

@ -1,122 +1,133 @@
// vi:ft=c // Generated file, do not edit (its not like it'll explode if you do, but its better not to)
#ifndef NET_H_ #ifndef NET_H
#define NET_H_ #define NET_H
#include "util.h"
#include <linux/input-event-codes.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#define MAGIC_TYPE uint32_t typedef unsigned char byte;
#define MAGIC_SIZE sizeof(MAGIC_TYPE) typedef uint64_t MsgMagic;
static const MAGIC_TYPE MAGIC_BEG = 0xDEADCAFE;
static const MAGIC_TYPE MAGIC_END = 0xCAFEDEAD;
// Align n to the next MAGIC boundary
static inline size_t align_m(uintptr_t n) { return (((n - 1) >> 2) + 1) << 2; }
typedef enum { #define MSG_MAGIC_SIZE sizeof(MsgMagic)
NoMessage = 0, static const MsgMagic MSG_MAGIC_START = 0xCAFEF00DBEEFDEAD;
DeviceInfo = 1, static const MsgMagic MSG_MAGIC_END = 0xF00DBEEFCAFEDEAD;
DeviceReport = 2,
DeviceDestroy = 3,
ControllerState = 4,
Request = 5,
} MessageCode;
// Alignment 4 typedef struct Abs {
typedef struct { uint16_t id;
MessageCode code; uint32_t min;
// + 1 byte of padding uint32_t max;
uint32_t fuzz;
uint32_t flat;
uint32_t res;
} Abs;
uint8_t slot; typedef struct Key {
uint8_t index; uint16_t id;
} Key;
uint16_t abs_count; typedef struct Rel {
uint16_t rel_count; uint16_t id;
uint16_t key_count; } Rel;
uint16_t abs_id[ABS_CNT]; typedef struct Tag {
// + 2 bytes of padding per abs struct {
uint32_t abs_min[ABS_CNT]; uint16_t len;
uint32_t abs_max[ABS_CNT]; char *data;
uint32_t abs_fuzz[ABS_CNT]; } name;
uint32_t abs_flat[ABS_CNT]; } Tag;
uint32_t abs_res[ABS_CNT];
uint16_t rel_id[REL_CNT]; typedef struct TagList {
struct {
uint16_t key_id[KEY_CNT]; uint16_t len;
} MessageDeviceInfo; struct Tag *data;
#define MSS_DEVICE_INFO(abs, rel, key) (10 + abs * 24 + rel * 2 + key * 2 + 1) } tags;
// MSS -> Message Serialized Size:
// Size of the data of the message when serialized (no alignment / padding)
// 4 aligned
typedef struct {
MessageCode code;
// + 1 byte of padding
uint8_t slot;
uint8_t index;
uint16_t abs_count;
uint16_t rel_count;
uint16_t key_count;
uint32_t abs[ABS_CNT];
uint32_t rel[REL_CNT];
uint8_t key[KEY_CNT];
} MessageDeviceReport;
#define MSS_DEVICE_REPORT(abs, rel, key) (11 + abs * 4 + rel * 4 + align_4(key))
// 1 aligned
typedef struct {
MessageCode code;
// + 1 byte of padding
uint16_t index;
uint8_t led[3];
uint8_t small_rumble;
uint8_t big_rumble;
uint8_t flash_on;
uint8_t flash_off;
} MessageControllerState;
#define MSS_CONTROLLER_STATE 10
typedef struct {
char **tags;
uint16_t count;
} TagList; } TagList;
typedef struct { // Device
MessageCode code;
// + 1 byte of padding
TagList *requests; typedef enum DeviceTag {
uint16_t request_count; DeviceTagNone = 0,
} MessageRequest; DeviceTagInfo = 1,
#define MSS_REQUEST(count) (2 + 2 * count + 1) DeviceTagReport = 2,
DeviceTagControllerState = 3,
DeviceTagRequest = 4,
DeviceTagDestroy = 5,
} DeviceTag;
typedef struct { typedef struct DeviceInfo {
MessageCode code; DeviceTag tag;
// + 1 byte of padding uint8_t slot;
uint8_t index;
struct {
uint8_t len;
struct Abs data[64];
} abs;
struct {
uint8_t len;
struct Rel data[16];
} rel;
struct {
uint16_t len;
struct Key data[768];
} key;
} DeviceInfo;
typedef struct DeviceReport {
DeviceTag tag;
uint8_t slot;
uint8_t index;
struct {
uint8_t len;
uint32_t data[64];
} abs;
struct {
uint8_t len;
uint32_t data[16];
} rel;
struct {
uint16_t len;
uint8_t data[768];
} key;
} DeviceReport;
typedef struct DeviceControllerState {
DeviceTag tag;
uint16_t index; uint16_t index;
} MessageDestroy; uint8_t led[3];
#define MSS_DESTROY 3 uint8_t small_rumble;
uint8_t big_rumble;
uint8_t flash_on;
uint8_t flash_off;
} DeviceControllerState;
typedef union { typedef struct DeviceRequest {
MessageCode code; DeviceTag tag;
MessageRequest request; struct {
MessageDestroy destroy; uint16_t len;
MessageDeviceInfo device_info; struct TagList *data;
MessageDeviceReport device_report; } requests;
MessageControllerState controller_state; uint64_t _version;
} Message; } DeviceRequest;
int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst); typedef struct DeviceDestroy {
int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg); DeviceTag tag;
void msg_free(Message *msg); uint16_t index;
void print_message_buffer(const uint8_t *buf, int len); } DeviceDestroy;
typedef union DeviceMessage {
DeviceTag tag;
DeviceInfo info;
DeviceReport report;
DeviceControllerState controller_state;
DeviceRequest request;
DeviceDestroy destroy;
} DeviceMessage;
// Serialize the message msg to buffer dst of size len, returns the length of the serialized message, or -1 on error (buffer overflow)
int msg_device_serialize(byte *dst, size_t len, DeviceMessage *msg);
// Deserialize the message in the buffer src of size len into dst, return the length of the serialized message or -1 on error.
int msg_device_deserialize(const byte *src, size_t len, DeviceMessage *dst);
// Free the message (created by msg_device_deserialize)
void msg_device_free(DeviceMessage *msg);
#endif #endif

68
net.ser
View File

@ -1,63 +1,3 @@
// Abs -> { whatever: u16, field1: { a: (invalid)[^1] }, field2: A[1] }
// AbsArr -> { whatever: u16, field1: { a: (invalid)[^1] }, field2: A[1] }&[]
// AbsArrArr -> { whatever: u16, field1: { a: (invalid)[^1] }, field2: A[1] }&[]&[][4]
// A -> { a: (invalid)[^1] }
// AA -> { a: (invalid)[^1] }[1]
// RBASIC -> (invalid)
// RM1 -> (invalid)
// RM2 -> (invalid)
// RM3 -> (invalid)
// R1 -> (invalid)&[4]&[]
// R2 -> (invalid)&[4]
// R3 -> (invalid)&[4]
// R4 -> (invalid)
// R5 -> (invalid)
// SA -> { field: { field: SA } }
// SC -> { field: SC&[] }
// Node -> { data: u8, children: Node&[] }
// Recur -> { field: Recur }
// SB -> { field: { field: SB } }
// bool -> bool
// char -> char
// i16 -> i16
// i32 -> i32
// i64 -> i64
// i8 -> i8
// u16 -> u16
// u32 -> u32
// u64 -> u64
// u8 -> u8
// Struct Layout: S2
// field[0].field.len align(2) size(2)
// field[1].field.len align(2) size(2)
// field[0].field.data align(0) size(0)
// field[1].field.data align(0) size(0)
// Struct Layout: SC
// field.len align(2) size(2)
// field.data align(0) size(0)
// Struct Layout: Node
// children.len align(2) size(2)
// data align(1) size(1)
// children.data align(0) size(0)
// Struct Layout: S1
// field.len align(1) size(1)
// field.data align(0) size(0)
// Struct Layout: Abs
// whatever align(2) size(2)
// Struct Layout: S3
// field.len align(2) size(2)
// field.data align(0) size(0)
// Struct Layout: Rel
// a align(2) size(2)
struct Abs { struct Abs {
id: u16, id: u16,
min: u32, min: u32,
@ -83,6 +23,11 @@ struct Tag {
name: char[], name: char[],
} }
struct TagList {
tags: Tag[],
}
version(1);
messages Device { messages Device {
Info { Info {
slot: u8, slot: u8,
@ -110,8 +55,7 @@ messages Device {
} }
#[versioned] #[versioned]
Request { Request {
requests: Tag[][], requests: TagList[],
request_count: u16,
} }
Destroy { Destroy {
index: u16, index: u16,

View File

@ -166,3 +166,19 @@ char *pascal_to_snake_case(StringSlice str) {
return res.data; return res.data;
} }
char *snake_case_to_screaming_snake_case(StringSlice str) {
CharVec res = vec_init();
vec_grow(&res, str.len + 4);
for(size_t i = 0; i < str.len; i++) {
char c = str.ptr[i];
if('a' <= c && c <= 'z') {
vec_push(&res, c - 'a' + 'A');
} else {
vec_push(&res, c);
}
}
vec_push(&res, '\0');
return res.data;
}

View File

@ -41,6 +41,7 @@ void wt_format(Writer *w, const char *fmt, ...);
// Define the structs of a program in the correct order (respecting direct dependencies) // Define the structs of a program in the correct order (respecting direct dependencies)
void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObject *)); void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObject *));
char *pascal_to_snake_case(StringSlice str); char *pascal_to_snake_case(StringSlice str);
char *snake_case_to_screaming_snake_case(StringSlice str);
// Check if c is aligned to alignment to // Check if c is aligned to alignment to
static inline bool calign_is_aligned(CurrentAlignment c, Alignment to) { static inline bool calign_is_aligned(CurrentAlignment c, Alignment to) {

View File

@ -195,6 +195,10 @@ void write_struct(Writer *w, StructObject *obj) {
wt_format(w, "} %.*s;\n\n", obj->name.len, obj->name.ptr); wt_format(w, "} %.*s;\n\n", obj->name.len, obj->name.ptr);
} }
void write_align(Writer *w, const char *var, const Alignment align, size_t indent) {
wt_format(w, "%*s%s = (byte*)(((((uintptr_t)%s - 1) >> %u) + 1) << %u);\n", indent, "", var, var, align.po2, align.po2);
}
void write_accessor(Writer *w, TypeObject *base_type, FieldAccessor fa, bool ptr) { void write_accessor(Writer *w, TypeObject *base_type, FieldAccessor fa, bool ptr) {
if (fa.indices.len == 0) if (fa.indices.len == 0)
return; return;
@ -245,6 +249,37 @@ void write_accessor(Writer *w, TypeObject *base_type, FieldAccessor fa, bool ptr
} }
} }
bool is_field_accessor_heap_array(FieldAccessor fa, TypeObject *base_type) {
if (fa.indices.len == 0)
return base_type->kind == TypeArray && base_type->type.array.heap;
// In the case of a heap array the last index will choose between length and data,
// but since we only care about the array
fa.indices.len--;
TypeObject *t = base_type;
for (size_t i = 0; i < fa.indices.len; i++) {
uint64_t index = fa.indices.data[i];
if (t->kind == TypeStruct) {
StructObject *st = (StructObject *)&t->type.struct_;
t = st->fields.data[index].type;
} else if (t->kind == TypeArray) {
if (t->type.array.sizing == SizingMax) {
if (index == 0) {
return false;
} else {
t = t->type.array.type;
}
} else {
t = t->type.array.type;
}
}
}
return t->kind == TypeArray && t->type.array.heap;
}
void write_type_serialization( void write_type_serialization(
Writer *w, const char *base, bool ptr, Layout *layout, CurrentAlignment al, Hashmap *layouts, size_t indent, size_t depth Writer *w, const char *base, bool ptr, Layout *layout, CurrentAlignment al, Hashmap *layouts, size_t indent, size_t depth
) { ) {
@ -275,14 +310,15 @@ void write_type_serialization(
for (; i < layout->fields.len; i++) { for (; i < layout->fields.len; i++) {
FieldAccessor farr = layout->fields.data[i]; FieldAccessor farr = layout->fields.data[i];
wt_format(w, "%*sfor(size_t i = 0; i < %s", indent, "", base);
FieldAccessor flen = field_accessor_clone(&farr); FieldAccessor flen = field_accessor_clone(&farr);
// Access the length instead of data // Access the length instead of data
flen.indices.data[flen.indices.len - 1] = 0; flen.indices.data[flen.indices.len - 1] = 0;
wt_format(w, "%*sfor(size_t i = 0; i < %s", indent, "", base);
write_accessor(w, layout->type, flen, ptr); write_accessor(w, layout->type, flen, ptr);
field_accessor_drop(flen); field_accessor_drop(flen);
char *vname = msprintf("e%lu", depth); char *vname = msprintf("e%lu", depth);
wt_format(w, "; i++) {\n%*stypeof(%s", indent, "", base); wt_format(w, "; i++) {\n%*stypeof(%s", indent + INDENT, "", base);
write_accessor(w, layout->type, farr, ptr); write_accessor(w, layout->type, farr, ptr);
wt_format(w, "[i]) %s = %s", vname, base); wt_format(w, "[i]) %s = %s", vname, base);
write_accessor(w, layout->type, farr, ptr); write_accessor(w, layout->type, farr, ptr);
@ -303,7 +339,7 @@ void write_type_serialization(
wt_format(w, "%*s}\n", indent, ""); wt_format(w, "%*s}\n", indent, "");
free(vname); free(vname);
} }
wt_format(w, "%*sbuf = (byte*)(((uintptr_t)buf - %u) & -%u);\n", indent, "", align.mask, align.value); write_align(w, "buf", align, indent);
} else { } else {
offset += calign_to(al, align); offset += calign_to(al, align);
wt_format(w, "%*sbuf += %lu;\n", indent, "", offset); wt_format(w, "%*sbuf += %lu;\n", indent, "", offset);
@ -346,10 +382,20 @@ void write_type_deserialization(
for (; i < layout->fields.len; i++) { for (; i < layout->fields.len; i++) {
FieldAccessor farr = layout->fields.data[i]; FieldAccessor farr = layout->fields.data[i];
wt_format(w, "%*sfor(size_t i = 0; i < %s", indent, "", base);
FieldAccessor flen = field_accessor_clone(&farr); FieldAccessor flen = field_accessor_clone(&farr);
// Access the length instead of data // Access the length instead of data
flen.indices.data[flen.indices.len - 1] = 0; flen.indices.data[flen.indices.len - 1] = 0;
if (is_field_accessor_heap_array(farr, layout->type)) {
wt_format(w, "%*s%s", indent, "", base);
write_accessor(w, layout->type, farr, ptr);
wt_format(w, " = malloc(%s", base);
write_accessor(w, layout->type, flen, ptr);
wt_format(w, " * sizeof(typeof(*%s", base);
write_accessor(w, layout->type, farr, ptr);
wt_format(w, ")));\n");
}
wt_format(w, "%*sfor(size_t i = 0; i < %s", indent, "", base);
write_accessor(w, layout->type, flen, ptr); write_accessor(w, layout->type, flen, ptr);
field_accessor_drop(flen); field_accessor_drop(flen);
char *vname = msprintf("e%lu", depth); char *vname = msprintf("e%lu", depth);
@ -374,24 +420,86 @@ void write_type_deserialization(
wt_format(w, "%*s}\n", indent, ""); wt_format(w, "%*s}\n", indent, "");
free(vname); free(vname);
} }
wt_format(w, "%*sbuf = (byte*)(((uintptr_t)buf - %u) & -%u);\n", indent, "", align.mask, align.value); write_align(w, "buf", align, indent);
} else { } else {
offset += calign_to(al, align); offset += calign_to(al, align);
wt_format(w, "%*sbuf += %lu;\n", indent, "", offset); wt_format(w, "%*sbuf += %lu;\n", indent, "", offset);
} }
} }
int write_type_free(Writer *w, const char *base, TypeObject *type, size_t indent, size_t depth) {
if (type->kind == TypePrimitif) {
return 0;
} else if (type->kind == TypeArray) {
BufferedWriter b = buffered_writer_init();
Writer *w2 = (Writer *)&b;
int total = 0;
wt_format(w2, "%*sfor(size_t i = 0; i < ", indent, "");
if (type->type.array.sizing == SizingMax) {
wt_format(w2, "%s.len; i++) {\n", base);
wt_format(w2, "%*stypeof(%s.data[i]) e%lu = %s.data[i];\n", indent + INDENT, "", base, depth, base);
} else {
wt_format(w2, "%lu; i++) {\n", type->type.array.size);
wt_format(w2, "%*stypeof(%s[i]) e%lu = %s[i];\n", indent + INDENT, "", base, depth, base);
}
char *new_base = msprintf("e%lu", depth);
total += write_type_free(w2, new_base, type->type.array.type, indent + INDENT, depth + 1);
free(new_base);
wt_format(w2, "%*s}\n", indent, "");
if (total > 0) {
wt_write(w, b.buf.data, b.buf.len);
}
buffered_writer_drop(b);
if (type->type.array.heap) {
wt_format(w, "%*sfree(%s.data);\n", indent, "", base);
total++;
}
return total;
} else if (type->kind == TypeStruct) {
StructObject *s = (StructObject *)&type->type.struct_;
int total = 0;
for (size_t i = 0; i < s->fields.len; i++) {
Field f = s->fields.data[i];
char *new_base = msprintf("%s.%.*s", base, f.name.len, f.name.ptr);
total += write_type_free(w, new_base, f.type, indent, depth);
free(new_base);
}
return total;
}
return 0;
}
void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
char *uc_name = snake_case_to_screaming_snake_case((StringSlice){.ptr = name, .len = strlen(name)});
wt_format( wt_format(
header, header,
"// Generated file, do not edit (its not like it'll explode if you do, but its better not to)\n" "// Generated file, do not edit (its not like it'll explode if you do, but its better not to)\n"
"#ifndef %s_H\n"
"#define %s_H\n"
"#include <stdint.h>\n" "#include <stdint.h>\n"
"#include <stdlib.h>\n" "#include <stdlib.h>\n"
"#include <stdbool.h>\n" "#include <stdbool.h>\n"
"\n" "\n"
"typedef unsigned char byte;\n" "typedef unsigned char byte;\n"
"typedef uint64_t MsgMagic;\n"
"\n" "\n"
"#define MSG_MAGIC_SIZE sizeof(MsgMagic)\n"
"static const MsgMagic MSG_MAGIC_START = 0xCAFEF00DBEEFDEAD;\n"
"static const MsgMagic MSG_MAGIC_END = 0xF00DBEEFCAFEDEAD;\n"
"\n",
uc_name,
uc_name
); );
free(uc_name);
wt_format( wt_format(
source, source,
"// Generated file, do not edit (its not like it'll explode if you do, but its better not to)\n" "// Generated file, do not edit (its not like it'll explode if you do, but its better not to)\n"
@ -407,7 +515,16 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
MessagesObject msgs = p->messages.data[i]; MessagesObject msgs = p->messages.data[i];
wt_format(header, "// %.*s\n\n", msgs.name.len, msgs.name.ptr); wt_format(header, "// %.*s\n\n", msgs.name.len, msgs.name.ptr);
wt_format(header, "typedef enum %.*sTag {\n", msgs.name.len, msgs.name.ptr); wt_format(
header,
"typedef enum %.*sTag {\n%*s%.*sTagNone = 0,\n",
msgs.name.len,
msgs.name.ptr,
INDENT,
"",
msgs.name.len,
msgs.name.ptr
);
for (size_t j = 0; j < msgs.messages.len; j++) { for (size_t j = 0; j < msgs.messages.len; j++) {
wt_format( wt_format(
header, header,
@ -418,7 +535,7 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
msgs.name.ptr, msgs.name.ptr,
msgs.messages.data[j].name.len, msgs.messages.data[j].name.len,
msgs.messages.data[j].name.ptr, msgs.messages.data[j].name.ptr,
j j + 1
); );
} }
wt_format(header, "} %.*sTag;\n\n", msgs.name.len, msgs.name.ptr); wt_format(header, "} %.*sTag;\n\n", msgs.name.len, msgs.name.ptr);
@ -477,6 +594,15 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
msgs.name.len, msgs.name.len,
msgs.name.ptr msgs.name.ptr
); );
wt_format(
header,
"// Free the message (created by msg_%s_deserialize)\n"
"void msg_%s_free(%.*sMessage *msg);\n",
name,
name,
msgs.name.len,
msgs.name.ptr
);
char *tag_type = msprintf("%.*sTag", msgs.name.len, msgs.name.ptr); char *tag_type = msprintf("%.*sTag", msgs.name.len, msgs.name.ptr);
PointerVec message_tos = vec_init(); PointerVec message_tos = vec_init();
@ -509,8 +635,13 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
msgs.name.ptr msgs.name.ptr
); );
wt_format(source, "%*sbyte *base_buf = buf;\n%*s%s tag = msg->tag;\n", INDENT, "", INDENT, "", tag_type); wt_format(source, "%*sconst byte *base_buf = buf;\n", INDENT, "");
wt_format(source, "%*sswitch(tag) {\n", INDENT, ""); wt_format(source, "%*sif(len < 2 * MSG_MAGIC_SIZE)\n", INDENT, "");
wt_format(source, "%*sreturn -1;\n", INDENT * 2, "");
wt_format(source, "%*s*(MsgMagic*)buf = MSG_MAGIC_START;\n", INDENT, "");
wt_format(source, "%*sbuf += MSG_MAGIC_SIZE;\n", INDENT, "");
wt_format(source, "%*sswitch(msg->tag) {\n", INDENT, "");
wt_format(source, "%*scase %sNone:\n%*sbreak;\n", INDENT, "", tag_type, INDENT * 2, "");
for (size_t j = 0; j < msgs.messages.len; j++) { for (size_t j = 0; j < msgs.messages.len; j++) {
MessageObject m = msgs.messages.data[j]; MessageObject m = msgs.messages.data[j];
@ -541,7 +672,10 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
free(snake_case_name); free(snake_case_name);
} }
wt_format(source, "%*s}\n", INDENT, ""); wt_format(source, "%*s}\n", INDENT, "");
wt_format(source, "%*sbuf = (byte*)(((uintptr_t)buf - %u) & -%u);\n", INDENT, "", ALIGN_8.mask, ALIGN_8.value); wt_format(source, "%*s*(MsgMagic*)buf = MSG_MAGIC_END;\n", INDENT, "");
wt_format(source, "%*sbuf += MSG_MAGIC_SIZE;\n", INDENT, "");
wt_format(source, "%*sif(buf > base_buf + len)\n", INDENT, "");
wt_format(source, "%*sreturn -1;\n", INDENT * 2, "");
wt_format(source, "%*sreturn (int)(buf - base_buf);\n", INDENT, ""); wt_format(source, "%*sreturn (int)(buf - base_buf);\n", INDENT, "");
wt_format(source, "}\n"); wt_format(source, "}\n");
} }
@ -555,8 +689,16 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
msgs.name.ptr msgs.name.ptr
); );
wt_format(source, "%*sconst byte *base_buf = buf;\n%*s%s tag = *(uint16_t*)buf;\n", INDENT, "", INDENT, "", tag_type); wt_format(source, "%*sconst byte *base_buf = buf;\n", INDENT, "");
wt_format(source, "%*sif(len < 2 * MSG_MAGIC_SIZE)\n", INDENT, "");
wt_format(source, "%*sreturn -1;\n", INDENT * 2, "");
wt_format(source, "%*sif(*(MsgMagic*)buf != MSG_MAGIC_START)\n", INDENT, "");
wt_format(source, "%*sreturn -1;\n", INDENT * 2, "");
wt_format(source, "%*sbuf += MSG_MAGIC_SIZE;\n", INDENT, "");
wt_format(source, "%*s%s tag = *(uint16_t*)buf;\n", INDENT, "", tag_type);
wt_format(source, "%*sswitch(tag) {\n", INDENT, ""); wt_format(source, "%*sswitch(tag) {\n", INDENT, "");
wt_format(source, "%*scase %sNone:\n%*sbreak;\n", INDENT, "", tag_type, INDENT * 2, "");
for (size_t j = 0; j < msgs.messages.len; j++) { for (size_t j = 0; j < msgs.messages.len; j++) {
MessageObject m = msgs.messages.data[j]; MessageObject m = msgs.messages.data[j];
@ -579,19 +721,12 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
0 0
); );
if (m.attributes & Attr_versioned) { if (m.attributes & Attr_versioned) {
wt_format( wt_format(source, "%*sif(msg->%s._version != %luUL) {\n", INDENT * 2, "", snake_case_name, msgs.version);
source, wt_format(source, "%*sprintf(\"Mismatched version: peers aren't the same version", INDENT * 3, "");
"%*sif(msg->%s._version != %luUL) {\n%*sprintf(\"Mismatched message version: peers aren't the same " wt_format(source, ", expected %lu got %%lu.\\n\", msg->%s._version);\n", msgs.version, snake_case_name);
"version.\\n\");\n%*s}\n", wt_format(source, "%*smsg_%s_free(msg);\n", INDENT * 3, "", name);
INDENT * 2, wt_format(source, "%*sreturn -1;\n", INDENT * 3, "");
"", wt_format(source, "%*s}\n", INDENT * 2, "");
snake_case_name,
msgs.version,
INDENT * 3,
"",
INDENT * 2,
""
);
} }
wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, ""); wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, "");
@ -599,10 +734,43 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
free(snake_case_name); free(snake_case_name);
} }
wt_format(source, "%*s}\n", INDENT, ""); wt_format(source, "%*s}\n", INDENT, "");
wt_format(source, "%*sif(*(MsgMagic*)buf != MSG_MAGIC_END) {\n", INDENT, "");
wt_format(source, "%*smsg_%s_free(msg);\n", INDENT * 2, "", name);
wt_format(source, "%*sreturn -1;\n", INDENT * 2, "");
wt_format(source, "%*s}\n", INDENT, "");
wt_format(source, "%*sbuf += MSG_MAGIC_SIZE;\n", INDENT, "");
wt_format(source, "%*sif(buf > base_buf + len) {\n", INDENT, "");
wt_format(source, "%*smsg_%s_free(msg);\n", INDENT * 2, "", name);
wt_format(source, "%*sreturn -1;\n", INDENT * 2, "");
wt_format(source, "%*s}\n", INDENT, "");
wt_format(source, "%*sreturn (int)(buf - base_buf);\n", INDENT, ""); wt_format(source, "%*sreturn (int)(buf - base_buf);\n", INDENT, "");
wt_format(source, "}\n"); wt_format(source, "}\n");
} }
{
wt_format(source, "\nvoid msg_%s_free(%.*sMessage *msg) {\n", name, msgs.name.len, msgs.name.ptr);
wt_format(source, "%*sswitch(msg->tag) {\n", INDENT, "");
wt_format(source, "%*scase %sNone:\n%*sbreak;\n", INDENT, "", tag_type, INDENT * 2, "");
for (size_t j = 0; j < msgs.messages.len; j++) {
MessageObject m = msgs.messages.data[j];
TypeObject *mtype = message_tos.data[j];
char *snake_case_name = pascal_to_snake_case(m.name);
char *base = msprintf("msg->%s", snake_case_name);
wt_format(source, "%*scase %s%.*s: {\n", INDENT, "", tag_type, m.name.len, m.name.ptr);
write_type_free(source, base, mtype, INDENT * 2, 0);
wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, "");
free(base);
free(snake_case_name);
}
wt_format(source, "%*s}\n", INDENT, "");
wt_format(source, "}\n");
}
for (size_t j = 0; j < message_tos.len; j++) { for (size_t j = 0; j < message_tos.len; j++) {
TypeObject *to = message_tos.data[j]; TypeObject *to = message_tos.data[j];
StructObject *s = (StructObject *)&to->type.struct_; StructObject *s = (StructObject *)&to->type.struct_;
@ -616,6 +784,8 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
free(tag_type); free(tag_type);
free(name); free(name);
} }
wt_format(header, "#endif\n");
} }
typedef struct { typedef struct {

View File

@ -11,7 +11,7 @@
#define PRIMITIF_TO(name, al) \ #define PRIMITIF_TO(name, al) \
const TypeObject PRIMITIF_##name = {.kind = TypePrimitif, .align = _ALIGN_##al, .type.primitif = Primitif_##name} const TypeObject PRIMITIF_##name = {.kind = TypePrimitif, .align = _ALIGN_##al, .type.primitif = Primitif_##name}
PRIMITIF_TO(u8, 2); PRIMITIF_TO(u8, 1);
PRIMITIF_TO(u16, 2); PRIMITIF_TO(u16, 2);
PRIMITIF_TO(u32, 4); PRIMITIF_TO(u32, 4);
PRIMITIF_TO(u64, 8); PRIMITIF_TO(u64, 8);
@ -444,7 +444,7 @@ static uint64_t get_ast_number_value(EvaluationContext *ctx, AstNumber number) {
// If the constant is invalid we make up a value to continue checking for errors // If the constant is invalid we make up a value to continue checking for errors
// (Since it is invalid there already has been at least one and we know this code // (Since it is invalid there already has been at least one and we know this code
// can't go to the next stage) // can't go to the next stage)
return c->valid ? c->valid : 0; return c->valid ? c->value : 0;
} else { } else {
// This constant doesn't exist: raise an error and return dummy value to continue // This constant doesn't exist: raise an error and return dummy value to continue
vec_push(&ctx->errors, err_unknown(number.token.span, ATConstant, ident)); vec_push(&ctx->errors, err_unknown(number.token.span, ATConstant, ident));

View File

@ -118,6 +118,33 @@ static void print_config() {
printf("\n"); printf("\n");
} }
void print_message_buffer(const uint8_t *buf, int len) {
bool last_beg = false;
for (int i = 0; i < len; i++) {
if (i + MSG_MAGIC_SIZE <= len) {
MsgMagic magic = *(MsgMagic *)(&buf[i]);
if (magic == MSG_MAGIC_START) {
printf(" \033[32m%08lX\033[0m", magic);
i += MSG_MAGIC_SIZE - 1;
last_beg = true;
continue;
} else if (magic == MSG_MAGIC_END) {
printf(" \033[32m%08lX\033[0m", magic);
i += MSG_MAGIC_SIZE - 1;
continue;
}
}
if (last_beg) {
last_beg = false;
printf(" \033[034m%04X\033[0m", *(uint16_t*)&buf[i]);
i++;
} else {
printf(" %02X", buf[i]);
}
}
}
void device_thread_exit(int _sig) { void device_thread_exit(int _sig) {
struct DeviceThreadArgs *args = pthread_getspecific(device_args_key); struct DeviceThreadArgs *args = pthread_getspecific(device_args_key);
printf("CONN(%d): [%d] exiting\n", args->conn->id, args->index); printf("CONN(%d): [%d] exiting\n", args->conn->id, args->index);
@ -145,8 +172,8 @@ void *device_thread(void *args_) {
TRAP_IGN(SIGPIPE); TRAP_IGN(SIGPIPE);
TRAP(SIGTERM, device_thread_exit); TRAP(SIGTERM, device_thread_exit);
uint8_t buf[2048] __attribute__((aligned(4))) = {0}; uint8_t buf[2048] __attribute__((aligned(4))) = {0};
MessageDeviceInfo dev_info; DeviceInfo dev_info;
while (true) { while (true) {
if (*args->controller != NULL) { if (*args->controller != NULL) {
@ -169,21 +196,21 @@ void *device_thread(void *args_) {
// Send over device info // Send over device info
{ {
int len = msg_serialize(buf, 2048, (Message *)&dev_info); int len = msg_device_serialize(buf, 2048, (DeviceMessage *)&dev_info);
if (write(args->conn->socket, buf, len) == -1) { if (write(args->conn->socket, buf, len) == -1) {
printf("CONN(%d): [%d] Couldn't send device info\n", args->conn->id, args->index); printf("CONN(%d): [%d] Couldn't send device info\n", args->conn->id, args->index);
break; break;
} }
} }
MessageDeviceReport report = {0}; DeviceReport report = {0};
report.code = DeviceReport; report.tag = DeviceTagReport;
report.abs_count = ctr->dev.device_info.abs_count; report.abs.len = ctr->dev.device_info.abs.len;
report.rel_count = ctr->dev.device_info.rel_count; report.rel.len = ctr->dev.device_info.rel.len;
report.key_count = ctr->dev.device_info.key_count; report.key.len = ctr->dev.device_info.key.len;
report.slot = args->index; report.slot = args->index;
report.index = controller_index; report.index = controller_index;
while (true) { while (true) {
struct input_event event; struct input_event event;
@ -203,13 +230,12 @@ void *device_thread(void *args_) {
} }
if (event.type == EV_SYN) { if (event.type == EV_SYN) {
int len = msg_serialize(buf, 2048, (Message *)&report); int len = msg_device_serialize(buf, 2048, (DeviceMessage *)&report);
if (len < 0) { if (len < 0) {
printf("CONN(%d): [%d] Couldn't serialize report %d\n", args->conn->id, args->index, len); printf("CONN(%d): [%d] Couldn't serialize report %d\n", args->conn->id, args->index, len);
continue; continue;
}; };
send(args->conn->socket, buf, len, 0); send(args->conn->socket, buf, len, 0);
} else if (event.type == EV_ABS) { } else if (event.type == EV_ABS) {
int index = ctr->dev.mapping.abs_indices[event.code]; int index = ctr->dev.mapping.abs_indices[event.code];
@ -219,7 +245,7 @@ void *device_thread(void *args_) {
continue; continue;
}; };
report.abs[index] = event.value; report.abs.data[index] = event.value;
} else if (event.type == EV_REL) { } else if (event.type == EV_REL) {
int index = ctr->dev.mapping.rel_indices[event.code]; int index = ctr->dev.mapping.rel_indices[event.code];
@ -228,7 +254,7 @@ void *device_thread(void *args_) {
continue; continue;
}; };
report.rel[index] = event.value; report.rel.data[index] = event.value;
} else if (event.type == EV_KEY) { } else if (event.type == EV_KEY) {
int index = ctr->dev.mapping.key_indices[event.code]; int index = ctr->dev.mapping.key_indices[event.code];
@ -236,17 +262,17 @@ void *device_thread(void *args_) {
printf("CONN(%d): [%d] Invalid key\n", args->conn->id, args->index); printf("CONN(%d): [%d] Invalid key\n", args->conn->id, args->index);
continue; continue;
}; };
report.key[index] = !!event.value; report.key.data[index] = !!event.value;
} }
} }
// Send device destroy message // Send device destroy message
{ {
MessageDestroy dstr; DeviceDestroy dstr;
dstr.code = DeviceDestroy; dstr.tag = DeviceTagDestroy;
dstr.index = args->index; dstr.index = args->index;
int len = msg_serialize(buf, 2048, (Message *)&dstr); int len = msg_device_serialize(buf, 2048, (DeviceMessage *)&dstr);
if (write(args->conn->socket, buf, len) == -1) { if (write(args->conn->socket, buf, len) == -1) {
printf("CONN(%d): [%d] Couldn't send device destroy message\n", args->conn->id, args->index); printf("CONN(%d): [%d] Couldn't send device destroy message\n", args->conn->id, args->index);
break; break;
@ -310,7 +336,7 @@ void *server_handle_conn(void *args_) {
if (len <= 0) { if (len <= 0) {
closing_message = "Lost peer (from recv)"; closing_message = "Lost peer (from recv)";
goto conn_end; goto conn_end;
} else if (len > 1 + MAGIC_SIZE * 2) { } else if (len > 1) {
printf("CONN(%d): Got message: ", args->id); printf("CONN(%d): Got message: ", args->id);
printf("\n"); printf("\n");
} else { } else {
@ -318,10 +344,10 @@ void *server_handle_conn(void *args_) {
} }
// Parse message // Parse message
Message msg; DeviceMessage msg;
int msg_len = msg_deserialize(buf, len, &msg); int msg_len = msg_device_deserialize(buf, len, &msg);
if (msg_len < 0) { if (msg_len < 0) {
if (len > 1 + MAGIC_SIZE * 2) { if (len > 1) {
printf("CONN(%d): Couldn't parse message: ", args->id); printf("CONN(%d): Couldn't parse message: ", args->id);
print_message_buffer(buf, len); print_message_buffer(buf, len);
printf("\n"); printf("\n");
@ -332,7 +358,7 @@ void *server_handle_conn(void *args_) {
} }
// Handle message // Handle message
if (msg.code == ControllerState) { if (msg.tag == DeviceTagControllerState) {
int i = msg.controller_state.index; int i = msg.controller_state.index;
if (i >= device_controllers.len) { if (i >= device_controllers.len) {
printf("CONN(%d): Invalid controller index in controller state message\n", args->id); printf("CONN(%d): Invalid controller index in controller state message\n", args->id);
@ -346,10 +372,10 @@ void *server_handle_conn(void *args_) {
} }
apply_controller_state(ctr, &msg.controller_state); apply_controller_state(ctr, &msg.controller_state);
} else if (msg.code == Request) { } else if (msg.tag == DeviceTagRequest) {
if (got_request) { if (got_request) {
printf("CONN(%d): Illegal Request message after initial request\n", args->id); printf("CONN(%d): Illegal Request message after initial request\n", args->id);
msg_free(&msg); msg_device_free(&msg);
continue; continue;
} }
@ -357,7 +383,7 @@ void *server_handle_conn(void *args_) {
printf("CONN(%d): Got client request\n", args->id); printf("CONN(%d): Got client request\n", args->id);
for (int i = 0; i < msg.request.request_count; i++) { for (int i = 0; i < msg.request.requests.len; i++) {
int index = device_controllers.len; int index = device_controllers.len;
Controller *ctr = NULL; Controller *ctr = NULL;
vec_push(&device_controllers, &ctr); vec_push(&device_controllers, &ctr);
@ -365,13 +391,14 @@ void *server_handle_conn(void *args_) {
struct DeviceThreadArgs *dev_args = malloc(sizeof(struct DeviceThreadArgs)); struct DeviceThreadArgs *dev_args = malloc(sizeof(struct DeviceThreadArgs));
dev_args->controller = vec_get(&device_controllers, index); dev_args->controller = vec_get(&device_controllers, index);
dev_args->tag_count = msg.request.requests[i].count; dev_args->tag_count = msg.request.requests.data[i].tags.len;
dev_args->tags = malloc(dev_args->tag_count * sizeof(char *)); dev_args->tags = malloc(dev_args->tag_count * sizeof(char *));
dev_args->conn = args; dev_args->conn = args;
dev_args->index = index; dev_args->index = index;
for (int j = 0; j < dev_args->tag_count; j++) { for (int j = 0; j < dev_args->tag_count; j++) {
dev_args->tags[j] = strdup(msg.request.requests[i].tags[j]); Tag t = msg.request.requests.data[i].tags.data[j];
dev_args->tags[j] = strndup(t.name.data, t.name.len);
} }
pthread_t thread; pthread_t thread;
@ -379,7 +406,7 @@ void *server_handle_conn(void *args_) {
vec_push(&device_threads, &thread); vec_push(&device_threads, &thread);
} }
msg_free(&msg); msg_device_free(&msg);
} else { } else {
printf("CONN(%d): Illegal message\n", args->id); printf("CONN(%d): Illegal message\n", args->id);
} }