add slots and fix things

This commit is contained in:
viandoxdev 2023-03-18 18:41:17 +01:00
parent 6973ba305b
commit 6f76aef797
No known key found for this signature in database
GPG Key ID: AF1410C5BC10AA25
8 changed files with 189 additions and 148 deletions

View File

@ -39,9 +39,13 @@ and a client with this one:
```json ```json
{ {
"controllers": [ "slots": [
{ {
"tag": ["Controller"] "controllers": [
{
"tag": "Controller"
}
]
} }
] ]
} }
@ -104,17 +108,24 @@ The client configuration specifies what devices the client wants as well as unde
```js ```js
// Any property can be ommitted, unless specified otherwise // Any property can be ommitted, unless specified otherwise
// The values listed here are examples // The values listed here are examples
// Comments are here to document things, they are not allowed in the actual config
{ {
"controllers": [ // (required) The slots the client has
"slots": [
{ {
// (required) Accepted tags of the device to request // (required) The controllers that are accepted in that slot
"tag": ["Joystick"], "controllers": [
// (default: 6969) Vendor code for the virtual device, expects a 4 long hex string {
"vendor": "dead", // (required) Accepted tags of the device to request
// (default: 0420) Product code for the virtual device, expects a 4 long hex string "tag": ["Joystick"],
"product": "beef", // (default: 6969) Vendor code for the virtual device, expects a 4 long hex string
// (default: "JSFW Virtual Device") Name for the virtual device "vendor": "dead",
"name": "Emanuel" // (default: 0420) Product code for the virtual device, expects a 4 long hex string
"product": "beef",
// (default: "JSFW Virtual Device") Name for the virtual device
"name": "Emanuel"
}
]
} }
], ],
// (default: "/tmp/jsfw_fifo") Path to the fifo for hidraw // (default: "/tmp/jsfw_fifo") Path to the fifo for hidraw
@ -130,7 +141,7 @@ Additionaly messages can be sent to the client's fifo to change the led colors (
// Any property can be ommitted, unless specified otherwise // Any property can be ommitted, unless specified otherwise
// The values listed here are examples // The values listed here are examples
{ {
// (default: 0) Index of the device to send the state to, this is the index in the client configuration controllers list // (default: 0) Index of the slot to send the state to, this is the index in the client configuration controllers list
"index": 1, "index": 1,
// (default: [0, 0]) Setting for the rumble, values are in range 0-255 first element is small rumble, second is big // (default: [0, 0]) Setting for the rumble, values are in range 0-255 first element is small rumble, second is big
"rumble": [255, 0], "rumble": [255, 0],

View File

@ -72,7 +72,7 @@ static const JSONAdapter ControllerStateAdapter = {
}; };
static const JSONPropertyAdapter ControllerAdapterProps[] = { static const JSONPropertyAdapter ControllerAdapterProps[] = {
{".tag[]", &StringAdapter, offsetof(ClientController, tags), default_to_null, NULL }, {".tag", &StringAdapter, offsetof(ClientController, tag), default_to_null, NULL },
{".vendor", &StringAdapter, offsetof(ClientController, device_vendor), default_vendor, tsf_hex_to_i32}, {".vendor", &StringAdapter, offsetof(ClientController, device_vendor), default_vendor, tsf_hex_to_i32},
{".product", &StringAdapter, offsetof(ClientController, device_product), default_product, 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 }, {".name", &StringAdapter, offsetof(ClientController, device_name), default_name, NULL },
@ -83,10 +83,19 @@ static const JSONAdapter ControllerAdapter = {
.size = sizeof(ClientController), .size = sizeof(ClientController),
}; };
static const JSONPropertyAdapter SlotAdapterProps[] = {
{".controllers[]", &ControllerAdapter, offsetof(ClientSlot, controllers), default_to_null, NULL},
};
static const JSONAdapter SlotAdapter = {
.props = SlotAdapterProps,
.prop_count = sizeof(SlotAdapterProps) / sizeof(JSONPropertyAdapter),
.size = sizeof(ClientSlot),
};
static const JSONPropertyAdapter ClientConfigAdapterProps[] = { static const JSONPropertyAdapter ClientConfigAdapterProps[] = {
{".controllers[]", &ControllerAdapter, offsetof(ClientConfig, controllers), default_to_null, NULL }, {".slots[]", &SlotAdapter, offsetof(ClientConfig, slots), default_to_null, NULL },
{".fifo_path", &StringAdapter, offsetof(ClientConfig, fifo_path), default_fifo_path, NULL }, {".fifo_path", &StringAdapter, offsetof(ClientConfig, fifo_path), default_fifo_path, NULL },
{".retry_delay", &NumberAdapter, offsetof(ClientConfig, retry_delay), default_retry_delay, tsf_numsec_to_timespec} {".retry_delay", &NumberAdapter, offsetof(ClientConfig, retry_delay), default_retry_delay, tsf_numsec_to_timespec}
}; };
static const JSONAdapter ConfigAdapter = { static const JSONAdapter ConfigAdapter = {
.props = ClientConfigAdapterProps, .props = ClientConfigAdapterProps,
@ -99,23 +108,23 @@ static void print_config() {
printf("CLIENT: Config\n"); printf("CLIENT: Config\n");
printf(" fifo_path: %s\n", config.fifo_path); printf(" fifo_path: %s\n", config.fifo_path);
printf(" retry_delay: %fs\n", timespec_to_double(&config.retry_delay)); printf(" retry_delay: %fs\n", timespec_to_double(&config.retry_delay));
printf(" controllers: \n"); printf(" slots: \n");
for (size_t i = 0; i < config.controller_count; i++) { for (size_t i = 0; i < config.slot_count; i++) {
ClientController *ctr = &config.controllers[i]; ClientSlot *slot = &config.slots[i];
printf(" - tags: ['%s'", ctr->tags[0]); printf(" - controllers:\n");
for (size_t j = 1; j < ctr->tag_count; j++) { for (size_t j = 0; j < slot->controller_count; j++) {
printf(", '%s'", ctr->tags[j]); ClientController *ctr = &slot->controllers[j];
printf(" - tag: '%s'\n", ctr->tag);
printf(" name: %s\n", ctr->device_name);
printf(" vendor: %04x\n", ctr->device_vendor);
printf(" product: %04x\n", ctr->device_product);
} }
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"); printf("\n");
} }
void destroy_devices(void) { void destroy_devices(void) {
for (int i = 0; i < config.controller_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); MessageDeviceInfo *info = vec_get(&devices_info, i);
@ -135,14 +144,14 @@ bool device_exists(int index) {
return info->code == DeviceInfo; return info->code == DeviceInfo;
} }
void device_destroy(int index) { void device_destroy(int slot) {
if (index >= devices_info.len) { if (slot >= devices_info.len) {
return; return;
} }
int fd = *(int *)vec_get(&devices_fd, index); int fd = *(int *)vec_get(&devices_fd, slot);
MessageDeviceInfo *info = vec_get(&devices_info, index); MessageDeviceInfo *info = vec_get(&devices_info, slot);
if (info->code == DeviceInfo) { if (info->code == DeviceInfo) {
ioctl(fd, UI_DEV_DESTROY); ioctl(fd, UI_DEV_DESTROY);
@ -151,14 +160,14 @@ void device_destroy(int index) {
} }
void device_init(MessageDeviceInfo *dev) { void device_init(MessageDeviceInfo *dev) {
if (dev->index >= 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;
} }
device_destroy(dev->index); device_destroy(dev->slot);
int fd = *(int *)vec_get(&devices_fd, dev->index); int fd = *(int *)vec_get(&devices_fd, dev->slot);
// Abs // Abs
if (dev->abs_count > 0) { if (dev->abs_count > 0) {
@ -193,7 +202,7 @@ void device_init(MessageDeviceInfo *dev) {
} }
} }
ClientController *ctr = &config.controllers[dev->index]; ClientController *ctr = &config.slots[dev->slot].controllers[dev->index];
struct uinput_setup setup = {0}; struct uinput_setup setup = {0};
@ -206,10 +215,10 @@ 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->index); MessageDeviceInfo *dst = vec_get(&devices_info, dev->slot);
memcpy(dst, dev, sizeof(MessageDeviceInfo)); memcpy(dst, dev, sizeof(MessageDeviceInfo));
printf("CLIENT: Got device [%d]: '%s' (abs: %d, rel: %d, key: %d)\n", dev->index, 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_count,
dev->rel_count, dev->key_count); dev->rel_count, dev->key_count);
} }
@ -231,12 +240,12 @@ 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(MessageDeviceReport *report) {
if (!device_exists(report->index)) { if (!device_exists(report->slot)) {
printf("CLIENT: [%d] Got report before device info\n", report->index); printf("CLIENT: [%d] Got report before device info\n", report->slot);
return; return;
} }
MessageDeviceInfo *info = vec_get(&devices_info, report->index); MessageDeviceInfo *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_count != info->abs_count || report->rel_count != info->rel_count || report->key_count != info->key_count) {
printf("CLIENT: Report doesn't match with device info\n"); printf("CLIENT: Report doesn't match with device info\n");
@ -244,25 +253,25 @@ void device_handle_report(MessageDeviceReport *report) {
} }
for (int i = 0; i < report->abs_count; i++) { for (int i = 0; i < report->abs_count; i++) {
if (device_emit(report->index, EV_ABS, info->abs_id[i], report->abs[i]) != 0) { if (device_emit(report->slot, EV_ABS, info->abs_id[i], report->abs[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_count; i++) {
if (device_emit(report->index, EV_REL, info->rel_id[i], report->rel[i]) != 0) { if (device_emit(report->slot, EV_REL, info->rel_id[i], report->rel[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_count; i++) {
if (device_emit(report->index, EV_KEY, info->key_id[i], (uint32_t)(!report->key[i]) - 1) != 0) { if (device_emit(report->slot, EV_KEY, info->key_id[i], (uint32_t)(!report->key[i]) - 1) != 0) {
printf("CLIENT: Error writing key event to uinput\n"); printf("CLIENT: Error writing key event to uinput\n");
} }
} }
// Reports are sent by the server every time the server receives an EV_SYN from the physical device, so we // Reports are sent by the server every time the server receives an EV_SYN from the physical device, so we
// send one when we receive the report to match // send one when we receive the report to match
device_emit(report->index, EV_SYN, 0, 0); device_emit(report->slot, EV_SYN, 0, 0);
} }
void setup_devices(void) { void setup_devices(void) {
@ -272,7 +281,7 @@ void setup_devices(void) {
MessageDeviceInfo no_info = {0}; MessageDeviceInfo no_info = {0};
no_info.code = NoMessage; no_info.code = NoMessage;
for (int i = 0; i < config.controller_count; i++) { for (int i = 0; i < config.slot_count; i++) {
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if (fd < 0) { if (fd < 0) {
perror("CLIENT: Can't open /dev/uinput, aborting now"); perror("CLIENT: Can't open /dev/uinput, aborting now");
@ -371,19 +380,19 @@ void setup_server(char *address, uint16_t port) {
} }
void build_device_request(void) { void build_device_request(void) {
TagList * reqs = malloc(config.controller_count * sizeof(TagList *)); TagList *reqs = malloc(config.slot_count * sizeof(TagList));
for (int i = 0; i < config.controller_count; i++) { for (int i = 0; i < config.slot_count; i++) {
TagList * req = &reqs[i]; TagList *req = &reqs[i];
req->count = config.controllers[i].tag_count; req->count = config.slots[i].controller_count;
req->tags = malloc(req->count * sizeof(char *)); req->tags = malloc(req->count * sizeof(char *));
for (int j = 0; j < req->count; j++) { for (int j = 0; j < req->count; j++) {
req->tags[j] = config.controllers[i].tags[j]; req->tags[j] = config.slots[i].controllers[j].tag;
} }
} }
device_request.code = Request; device_request.code = Request;
device_request.request_count = config.controller_count; device_request.request_count = config.slot_count;
device_request.requests = reqs; device_request.requests = reqs;
} }
@ -490,12 +499,11 @@ 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.code == DeviceInfo) {
if (device_exists(message.device_info.index)) { if (device_exists(message.device_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((MessageDeviceInfo *)&message);
printf("CLIENT: Got device %d\n", message.device_info.index);
} else if (message.code == DeviceReport) { } else if (message.code == DeviceReport) {
device_handle_report((MessageDeviceReport *)&message); device_handle_report((MessageDeviceReport *)&message);
} else if (message.code == DeviceDestroy) { } else if (message.code == DeviceDestroy) {

View File

@ -7,8 +7,7 @@
void client_run(char *address, uint16_t port, char *config_path); void client_run(char *address, uint16_t port, char *config_path);
typedef struct { typedef struct {
char **tags; char *tag;
size_t tag_count;
int32_t device_vendor; int32_t device_vendor;
int32_t device_product; int32_t device_product;
char *device_name; char *device_name;
@ -17,6 +16,11 @@ typedef struct {
typedef struct { typedef struct {
ClientController *controllers; ClientController *controllers;
size_t controller_count; size_t controller_count;
} ClientSlot;
typedef struct {
ClientSlot *slots;
size_t slot_count;
char *fifo_path; char *fifo_path;
struct timespec retry_delay; struct timespec retry_delay;

83
hid.c
View File

@ -167,49 +167,55 @@ bool filter_event(int fd, char *event, ControllerFilter *filter, uniq_t uniq) {
// Initialize vectors for polling // Initialize vectors for polling
void poll_devices_init(void) { void poll_devices_init(void) {
known_devices = vec_of(Controller); known_devices = vec_of(uint64_t);
cloneable_devices = vec_of(Controller *); cloneable_devices = vec_of(Controller);
available_devices = vec_of(Controller *); available_devices = vec_of(Controller);
} }
// Check if tag match any of the tags specified in the tags array (of length tag_count) // Find index of tag that matches any of the tags specified in the tags array (of length tag_count), returns -1 otherwise
bool match_tags(char *tag, char **tags, size_t tag_count) { static int match_tags(char *tag, char **tags, size_t tag_count) {
for (int i = 0; i < tag_count; i++) { for (int i = 0; i < tag_count; i++) {
if (strcmp(tag, tags[i]) == 0) { if (strcmp(tag, tags[i]) == 0) {
return true; return i;
} }
} }
return false; return -1;
} }
// Block to get a device, this is thread safe // Block to get a device, this is thread safe
// stop: additional condition to check before doing anything, // 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. // if the condition is ever found to be true the function will return immediately with a NULL pointer.
Controller *get_device(char **tags, size_t tag_count, bool *stop) { bool get_device(char **tags, size_t tag_count, bool *stop, Controller *res, uint8_t *ref_index) {
// Check if we can get one right away // Check if we can get one right away
pthread_mutex_lock(&devices_mutex); pthread_mutex_lock(&devices_mutex);
while (1) { while (1) {
if (*stop) { if (*stop) {
pthread_mutex_unlock(&devices_mutex); pthread_mutex_unlock(&devices_mutex);
return NULL; return false;
} }
for (int i = 0; i < available_devices.len; i++) { for (int i = 0; i < available_devices.len; i++) {
Controller *c = *(Controller **)vec_get(&available_devices, i); Controller *c = vec_get(&available_devices, i);
if (match_tags(c->ctr.tag, tags, tag_count)) { int index = match_tags(c->ctr.tag, tags, tag_count);
if (index >= 0) {
*ref_index = index;
*res = *c;
vec_remove(&available_devices, i, NULL); vec_remove(&available_devices, i, NULL);
pthread_mutex_unlock(&devices_mutex); pthread_mutex_unlock(&devices_mutex);
return c; return true;
} }
} }
for (int i = 0; i < cloneable_devices.len; i++) { for (int i = 0; i < cloneable_devices.len; i++) {
Controller *c = *(Controller **)vec_get(&cloneable_devices, i); Controller *c = vec_get(&cloneable_devices, i);
if (match_tags(c->ctr.tag, tags, tag_count)) { int index = match_tags(c->ctr.tag, tags, tag_count);
if (index >= 0) {
*ref_index = index;
*res = *c;
pthread_mutex_unlock(&devices_mutex); pthread_mutex_unlock(&devices_mutex);
return c; return true;
} }
} }
@ -226,7 +232,7 @@ void return_device(Controller *c) {
} }
pthread_mutex_lock(&devices_mutex); pthread_mutex_lock(&devices_mutex);
vec_push(&available_devices, &c); vec_push(&available_devices, c);
// Signal that there are new devices // Signal that there are new devices
pthread_cond_broadcast(&devices_cond); pthread_cond_broadcast(&devices_cond);
pthread_mutex_unlock(&devices_mutex); pthread_mutex_unlock(&devices_mutex);
@ -234,26 +240,25 @@ void return_device(Controller *c) {
// Forget about a broken device. This invalidates the reference to the controller // Forget about a broken device. This invalidates the reference to the controller
void forget_device(Controller *c) { void forget_device(Controller *c) {
pthread_mutex_lock(&known_devices_mutex);
// If controller is cloneable we need to remove it from the cloneable list // If controller is cloneable we need to remove it from the cloneable list
if (c->ctr.duplicate) { if (c->ctr.duplicate) {
pthread_mutex_lock(&devices_mutex);
for (int i = 0; i < cloneable_devices.len; i++) { for (int i = 0; i < cloneable_devices.len; i++) {
Controller *d = *(Controller **)vec_get(&cloneable_devices, i); Controller *d = *(Controller **)vec_get(&cloneable_devices, i);
if (d->dev.uniq == c->dev.uniq) { if (d->dev.id == c->dev.id) {
vec_remove(&cloneable_devices, i, NULL); vec_remove(&cloneable_devices, i, NULL);
break; break;
} }
} }
pthread_mutex_unlock(&devices_mutex);
} }
// Free the name if it was allocated // Free the name if it was allocated
if (c->dev.name != NULL && c->dev.name != DEVICE_DEFAULT_NAME) { if (c->dev.name != NULL && c->dev.name != DEVICE_DEFAULT_NAME) {
printf("HID: Forgetting device '%s' (%016lx)\n", c->dev.name, c->dev.uniq); printf("HID: Forgetting device '%s' (%lu)\n", c->dev.name, c->dev.id);
free(c->dev.name); free(c->dev.name);
} else { } else {
printf("HID: Forgetting device %016lx\n", c->dev.uniq); printf("HID: Forgetting device %lu\n", c->dev.id);
} }
// try to close the file descriptor, they may be already closed if the device was unpugged. // try to close the file descriptor, they may be already closed if the device was unpugged.
@ -261,10 +266,9 @@ void forget_device(Controller *c) {
close(c->dev.hidraw); close(c->dev.hidraw);
// Safely remove device from the known device list // Safely remove device from the known device list
pthread_mutex_lock(&known_devices_mutex);
for (int i = 0; i < known_devices.len; i++) { for (int i = 0; i < known_devices.len; i++) {
Controller *d = vec_get(&known_devices, i); uint64_t *id = vec_get(&known_devices, i);
if (d->dev.uniq == c->dev.uniq) { if (*id == c->dev.id) {
vec_remove(&known_devices, i, NULL); vec_remove(&known_devices, i, NULL);
break; break;
} }
@ -272,6 +276,8 @@ void forget_device(Controller *c) {
pthread_mutex_unlock(&known_devices_mutex); pthread_mutex_unlock(&known_devices_mutex);
} }
uint64_t parse_event_name(const char *event) { return atol(event + 5); }
// Find all available devices and pick up on new ones // Find all available devices and pick up on new ones
void poll_devices(void) { void poll_devices(void) {
// loop over all entries of /sys/class/input // loop over all entries of /sys/class/input
@ -287,6 +293,7 @@ void poll_devices(void) {
PhysicalDevice dev; PhysicalDevice dev;
dev.hidraw = -1; dev.hidraw = -1;
dev.uniq = 0; dev.uniq = 0;
dev.id = parse_event_name(input->d_name);
// Open /dev/input/eventXX // Open /dev/input/eventXX
{ {
@ -340,21 +347,14 @@ void poll_devices(void) {
} }
} }
// Get the id
{
struct input_id id;
ioctl(dev.event, EVIOCGID, &id);
dev.id = *(uint64_t *)&id;
}
// Check if we already know of this device // Check if we already know of this device
{ {
found = false; found = false;
pthread_mutex_lock(&known_devices_mutex); pthread_mutex_lock(&known_devices_mutex);
for (int i = 0; i < known_devices.len; i++) { for (int i = 0; i < known_devices.len; i++) {
Controller *c = vec_get(&known_devices, i); uint64_t *id = vec_get(&known_devices, i);
if (c->dev.uniq == dev.uniq) { if (*id == dev.id) {
found = true; found = true;
break; break;
} }
@ -415,25 +415,20 @@ void poll_devices(void) {
Controller c = {.dev = dev, .ctr = *ctr}; Controller c = {.dev = dev, .ctr = *ctr};
pthread_mutex_lock(&known_devices_mutex); pthread_mutex_lock(&known_devices_mutex);
// Index of the device in known_devices vec_push(&known_devices, &c.dev.id);
int index = known_devices.len;
vec_push(&known_devices, &c);
pthread_mutex_unlock(&known_devices_mutex); pthread_mutex_unlock(&known_devices_mutex);
// Pointer to the device in known_devices printf("HID: New device, %s [%s] (%s: %lu)\n", name, ctr->tag, input->d_name, dev.id);
Controller *p = vec_get(&known_devices, index);
printf("HID: New device, %s [%s] (%s: %016lx)\n", name, ctr->tag, input->d_name, dev.uniq);
if (ctr->duplicate) { if (ctr->duplicate) {
pthread_mutex_lock(&devices_mutex); pthread_mutex_lock(&devices_mutex);
vec_push(&cloneable_devices, &p); vec_push(&cloneable_devices, &c);
// Signal that there are new cloneable devices // Signal that there are new cloneable devices
pthread_cond_broadcast(&devices_cond); pthread_cond_broadcast(&devices_cond);
pthread_mutex_unlock(&devices_mutex); pthread_mutex_unlock(&devices_mutex);
} else { } else {
pthread_mutex_lock(&devices_mutex); pthread_mutex_lock(&devices_mutex);
vec_push(&available_devices, &p); vec_push(&available_devices, &c);
// Signal that there are new devices // Signal that there are new devices
pthread_cond_broadcast(&devices_cond); pthread_cond_broadcast(&devices_cond);
pthread_mutex_unlock(&devices_mutex); pthread_mutex_unlock(&devices_mutex);
@ -452,11 +447,11 @@ 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, MessageControllerState *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 (%016lx)\n", c->dev.uniq); printf("HID: Trying to apply controller state on incompatible device (%lu)\n", c->dev.id);
return; return;
} }
printf("HID: (%016lx) Controller state: #%02x%02x%02x flash: (%d, %d) rumble: (%d, %d)\n", c->dev.uniq, state->led[0], printf("HID: (%lu) Controller state: #%02x%02x%02x flash: (%d, %d) rumble: (%d, %d)\n", c->dev.id, state->led[0],
state->led[1], state->led[2], state->flash_on, state->flash_off, state->small_rumble, state->big_rumble); 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}; uint8_t buf[32] = {0x05, 0xff, 0x00, 0x00};

12
hid.h
View File

@ -9,7 +9,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
// Unique identifier for devices (provided by linux), May be the mac address // Unique identifier for devices (provided by linux)
typedef uint64_t uniq_t; typedef uint64_t uniq_t;
// Mapping to go from index to id of events // Mapping to go from index to id of events
@ -38,10 +38,10 @@ typedef struct {
ServerConfigController ctr; ServerConfigController ctr;
} Controller; } Controller;
void *hid_thread(void *arg); 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);
Controller *get_device(char **tags, size_t tag_count, bool *stop); 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, MessageControllerState *state);
#endif #endif

80
net.c
View File

@ -30,23 +30,26 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
MessageCode code = (MessageCode)code_byte; MessageCode code = (MessageCode)code_byte;
uint32_t size = 0; uint32_t size = 0;
uint16_t abs, rel, key, index, *buf16; uint16_t abs, rel, key, *buf16;
uint8_t index, slot;
switch (code) { switch (code) {
case DeviceInfo: case DeviceInfo:
if (len < 7) if (len < 7)
return -1; return -1;
// buf + 2: a byte for code and a byte for padding slot = buf[2];
buf16 = (uint16_t *)(buf + 2); index = buf[3];
index = buf16[0]; // buf + 4: a byte for, code, padding, slot, index
abs = buf16[1]; buf16 = (uint16_t *)(buf + 4);
rel = buf16[2]; abs = buf16[0];
key = buf16[3]; rel = buf16[1];
key = buf16[2];
buf += 12; buf += 12;
if (MSS_DEVICE_INFO(abs, rel, key) > len) if (MSS_DEVICE_INFO(abs, rel, key) > len)
return -1; return -1;
dst->device_info.code = code; dst->device_info.code = code;
dst->device_info.slot = slot;
dst->device_info.index = index; dst->device_info.index = index;
dst->device_info.abs_count = abs; dst->device_info.abs_count = abs;
dst->device_info.rel_count = rel; dst->device_info.rel_count = rel;
@ -83,17 +86,19 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
if (len < 7) if (len < 7)
return -1; return -1;
// buf + 2: a byte for code and a byte of padding slot = buf[2];
buf16 = (uint16_t *)(buf + 2); index = buf[3];
index = buf16[0]; // buf + 4: a byte for, code, padding, slot and index
abs = buf16[1]; buf16 = (uint16_t *)(buf + 4);
rel = buf16[2]; abs = buf16[0];
key = buf16[3]; rel = buf16[1];
key = buf16[2];
buf += 12; buf += 12;
if (len < MSS_DEVICE_REPORT(abs, rel, key)) if (len < MSS_DEVICE_REPORT(abs, rel, key))
return -1; return -1;
dst->device_report.code = code; dst->device_report.code = code;
dst->device_report.slot = slot;
dst->device_report.index = index; dst->device_report.index = index;
dst->device_report.abs_count = abs; dst->device_report.abs_count = abs;
dst->device_report.rel_count = rel; dst->device_report.rel_count = rel;
@ -198,16 +203,19 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
return -1; return -1;
} }
if (size + MAGIC_SIZE > len + 1) { if (align_m(size) + MAGIC_SIZE > len + 1) {
return -1; return -1;
} }
if (*(MAGIC_TYPE *)buf != MAGIC_END) { // WARN: This is technically bad, but should be ok nonetheless
MAGIC_TYPE *mbuf = (MAGIC_TYPE *)align_m((uintptr_t)buf);
if (*mbuf != MAGIC_END) {
printf("NET: Magic not found\n"); printf("NET: Magic not found\n");
return -1; return -1;
} }
return size + 2 * MAGIC_SIZE; 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); // Serialize the message msg in buf, buf must be at least 4 aligned. Returns -1 on error (buf not big enough);
@ -231,15 +239,15 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
if (len < MSS_DEVICE_INFO(abs, rel, key)) if (len < MSS_DEVICE_INFO(abs, rel, key))
return -1; return -1;
// We begin 4 aligned
buf[0] = (uint8_t)msg->code; buf[0] = (uint8_t)msg->code;
// buf + 2: a byte for code and a byte for padding // 1 byte of padding
buf16 = (uint16_t *)(buf + 2); buf[2] = (uint8_t)msg->device_info.slot;
// 2 aligned here buf[3] = (uint8_t)msg->device_info.index;
buf16[0] = msg->device_info.index; // buf + 4: a byte for, code, padding, slot, index
buf16[1] = abs; buf16 = (uint16_t *)(buf + 4);
buf16[2] = rel; buf16[0] = abs;
buf16[3] = key; buf16[1] = rel;
buf16[2] = key;
buf += 12; buf += 12;
// Back to 4 aligned // Back to 4 aligned
@ -278,12 +286,14 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
return -1; return -1;
buf[0] = (uint8_t)msg->code; buf[0] = (uint8_t)msg->code;
// buf + 2: a byte for code and a byte for padding // 1 byte of padding
buf16 = (uint16_t *)(buf + 2); buf[2] = msg->device_report.slot;
buf16[0] = msg->device_report.index; buf[3] = msg->device_report.index;
buf16[1] = abs; // buf + 4: a byte for, code, padding, slot and index
buf16[2] = rel; buf16 = (uint16_t *)(buf + 4);
buf16[3] = key; buf16[0] = abs;
buf16[1] = rel;
buf16[2] = key;
buf += 12; buf += 12;
// We're 4 aligned already // We're 4 aligned already
for (int i = 0; i < abs; i++) { for (int i = 0; i < abs; i++) {
@ -340,9 +350,7 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
buf += 2; buf += 2;
for (int j = 0; j < tag_count; j++) { for (int j = 0; j < tag_count; j++) {
printf("about to strlen\n");
int str_len = strlen(tags[j]); int str_len = strlen(tags[j]);
printf("len : %i\n", str_len);
int byte_len = align_2(str_len); int byte_len = align_2(str_len);
expected_len += 2 + byte_len; expected_len += 2 + byte_len;
@ -376,13 +384,15 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
return -1; return -1;
} }
if (size + MAGIC_SIZE > len) { if (align_m(size) + MAGIC_SIZE > len) {
return -1; return -1;
} }
*(MAGIC_TYPE *)buf = MAGIC_END; MAGIC_TYPE *mbuf = (MAGIC_TYPE *)align_m((uintptr_t)buf);
return size + MAGIC_SIZE * 2; *mbuf = MAGIC_END;
return align_m(size) + MAGIC_SIZE * 2;
} }
void msg_free(Message *msg) { void msg_free(Message *msg) {

9
net.h
View File

@ -11,6 +11,8 @@
#define MAGIC_SIZE sizeof(MAGIC_TYPE) #define MAGIC_SIZE sizeof(MAGIC_TYPE)
static const MAGIC_TYPE MAGIC_BEG = 0xDEADCAFE; static const MAGIC_TYPE MAGIC_BEG = 0xDEADCAFE;
static const MAGIC_TYPE MAGIC_END = 0xCAFEDEAD; 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 { typedef enum {
NoMessage = 0, NoMessage = 0,
@ -26,7 +28,8 @@ typedef struct {
MessageCode code; MessageCode code;
// + 1 byte of padding // + 1 byte of padding
uint16_t index; uint8_t slot;
uint8_t index;
uint16_t abs_count; uint16_t abs_count;
uint16_t rel_count; uint16_t rel_count;
@ -52,7 +55,9 @@ typedef struct {
typedef struct { typedef struct {
MessageCode code; MessageCode code;
// + 1 byte of padding // + 1 byte of padding
uint16_t index;
uint8_t slot;
uint8_t index;
uint16_t abs_count; uint16_t abs_count;
uint16_t rel_count; uint16_t rel_count;

View File

@ -123,6 +123,7 @@ void device_thread_exit(int _sig) {
Controller *ctr = *args->controller; Controller *ctr = *args->controller;
if (ctr != NULL) { if (ctr != NULL) {
return_device(ctr); return_device(ctr);
free(ctr);
} }
for (int i = 0; i < args->tag_count; i++) { for (int i = 0; i < args->tag_count; i++) {
@ -146,16 +147,22 @@ void *device_thread(void *args_) {
MessageDeviceInfo dev_info; MessageDeviceInfo dev_info;
while (true) { while (true) {
if (*args->controller != NULL) {
free(*args->controller);
}
*args->controller = NULL; *args->controller = NULL;
Controller *ctr = get_device(args->tags, args->tag_count, &args->conn->closed); uint8_t controller_index;
if (ctr == NULL) { Controller *ctr = malloc(sizeof(Controller));
if (!get_device(args->tags, args->tag_count, &args->conn->closed, ctr, &controller_index)) {
break; break;
} }
*args->controller = ctr; *args->controller = ctr;
dev_info = ctr->dev.device_info; dev_info = ctr->dev.device_info;
dev_info.index = args->index; dev_info.slot = args->index;
dev_info.index = controller_index;
printf("CONN(%d): [%d] Found suitable [%s] device: '%s' (%016lx)\n", args->conn->id, args->index, ctr->ctr.tag, printf("CONN(%d): [%d] Found suitable [%s] device: '%s' (%lu)\n", args->conn->id, args->index, ctr->ctr.tag,
ctr->dev.name, ctr->dev.id); ctr->dev.name, ctr->dev.id);
// Send over device info // Send over device info
@ -173,7 +180,8 @@ void *device_thread(void *args_) {
report.abs_count = ctr->dev.device_info.abs_count; report.abs_count = ctr->dev.device_info.abs_count;
report.rel_count = ctr->dev.device_info.rel_count; report.rel_count = ctr->dev.device_info.rel_count;
report.key_count = ctr->dev.device_info.key_count; report.key_count = ctr->dev.device_info.key_count;
report.index = args->index; report.slot = args->index;
report.index = controller_index;
while (true) { while (true) {
struct input_event event; struct input_event event;