All xbox buttons are mapped

This commit is contained in:
Denis Benato 2023-12-07 12:46:35 +01:00
parent 773812ff53
commit 3ec34290e6
4 changed files with 200 additions and 82 deletions

View file

@ -230,6 +230,8 @@ void* dev_in_thread_func(void *ptr) {
}
for (;;) {
FD_ZERO(&read_fds);
FD_SET(devs->in_message_pipe_fd, &read_fds);
for (size_t i = 0; i < devs->input_dev_cnt; ++i) {
@ -316,4 +318,4 @@ void* dev_in_thread_func(void *ptr) {
free(devices);
return NULL;
}
}

175
dev_out.c
View file

@ -3,32 +3,131 @@
#include "virt_ds4.h"
static void handle_incoming_message_gamepad_action(
in_message_gamepad_action_t *const msg_payload,
const in_message_gamepad_action_t *const msg_payload,
gamepad_status_t *const inout_gamepad
) {
if (msg_payload == GAMEPAD_ACTION_PRESS_AND_RELEASE_CENTER) {
inout_gamepad->flags |= GAMEPAD_STATUS_FLAGS_PRESS_AND_REALEASE_CENTER;
}
}
static void handle_incoming_message_gamepad_set(
in_message_gamepad_set_element_t *const msg_payload,
const in_message_gamepad_set_element_t *const msg_payload,
gamepad_status_t *const inout_gamepad
) {
}
switch (msg_payload->element) {
case GAMEPAD_BTN_CROSS: {
inout_gamepad->cross = msg_payload->status.btn;
break;
}
case GAMEPAD_BTN_CIRCLE: {
inout_gamepad->circle = msg_payload->status.btn;
break;
}
case GAMEPAD_BTN_SQUARE: {
inout_gamepad->square = msg_payload->status.btn;
break;
}
case GAMEPAD_BTN_TRIANGLE: {
inout_gamepad->triangle = msg_payload->status.btn;
break;
}
case GAMEPAD_BTN_OPTION: {
inout_gamepad->option = msg_payload->status.btn;
break;
}
case GAMEPAD_BTN_SHARE: {
inout_gamepad->share = msg_payload->status.btn;
break;
}
case GAMEPAD_BTN_L1: {
inout_gamepad->l1 = msg_payload->status.btn;
break;
}
case GAMEPAD_BTN_R1: {
inout_gamepad->r1 = msg_payload->status.btn;
break;
}
case GAMEPAD_BTN_L2_TRIGGER: {
inout_gamepad->l2_trigger = msg_payload->status.btn;
break;
}
case GAMEPAD_BTN_R2_TRIGGER: {
inout_gamepad->r2_trigger = msg_payload->status.btn;
break;
}
case GAMEPAD_BTN_L3: {
inout_gamepad->l3 = msg_payload->status.btn;
break;
}
case GAMEPAD_BTN_R3: {
inout_gamepad->r3 = msg_payload->status.btn;
break;
}
case GAMEPAD_LEFT_JOYSTICK_X: {
inout_gamepad->joystick_positions[0][0] = msg_payload->status.btn;
break;
}
case GAMEPAD_LEFT_JOYSTICK_Y: {
inout_gamepad->joystick_positions[0][1] = msg_payload->status.btn;
break;
}
case GAMEPAD_RIGHT_JOYSTICK_X: {
inout_gamepad->joystick_positions[1][0] = msg_payload->status.btn;
break;
}
case GAMEPAD_RIGHT_JOYSTICK_Y: {
inout_gamepad->joystick_positions[1][1] = msg_payload->status.btn;
break;
}
case GAMEPAD_DPAD_X: {
const int8_t v = msg_payload->status.dpad;
static void handle_incoming_message(
in_message_t *const msg,
devices_status_t *const dev_stats
) {
if (msg->type == GAMEPAD_SET_ELEMENT) {
handle_incoming_message_gamepad_set(&msg->data.gamepad_set, dev_stats);
} else if (msg->type == GAMEPAD_ACTION) {
handle_incoming_message_gamepad_action(&msg->data.action, dev_stats);
inout_gamepad->dpad &= 0xF0;
if (v == 0) {
inout_gamepad->dpad |= 0x00;
} else if (v == 1) {
inout_gamepad->dpad |= 0x01;
} else if (v == -1) {
inout_gamepad->dpad |= 0x02;
}
break;
}
case GAMEPAD_DPAD_Y: {
const int8_t v = msg_payload->status.dpad;
inout_gamepad->dpad &= 0x0F;
if (v == 0) {
inout_gamepad->dpad |= 0x00;
} else if (v == 1) {
inout_gamepad->dpad |= 0x20;
} else if (v == -1) {
inout_gamepad->dpad |= 0x10;
}
break;
}
}
}
uint64_t get_timediff_usec(struct timeval past, struct timeval now) {
return 0;
static void handle_incoming_message(
const in_message_t *const msg,
devices_status_t *const dev_stats
) {
if (msg->type == GAMEPAD_SET_ELEMENT) {
handle_incoming_message_gamepad_set(&msg->data.gamepad_set, &dev_stats->gamepad);
} else if (msg->type == GAMEPAD_ACTION) {
handle_incoming_message_gamepad_action(&msg->data.action, &dev_stats->gamepad);
}
}
int64_t get_timediff_usec(struct timeval* past, struct timeval* now) {
const time_t secs_diff = now->tv_sec - past->tv_sec;
// TODO: this is wrong...
const suseconds_t usecs_diff = now->tv_usec - past->tv_usec;
return secs_diff * (int64_t)1000000 + usecs_diff;
}
void *dev_out_thread_func(void *ptr) {
@ -44,8 +143,8 @@ void *dev_out_thread_func(void *ptr) {
} controller_data;
int current_gamepad_fd = -1;
int current_keyboard_fd = -1;
int current_mouse_fd = -1;
//int current_keyboard_fd = -1;
//int current_mouse_fd = -1;
if (current_gamepad == GAMEPAD_DUALSENSE) {
@ -58,8 +157,6 @@ void *dev_out_thread_func(void *ptr) {
}
}
// TODO: stats->gamepad.flags |= GAMEPAD_STATUS_FLAGS_PRESS_AND_REALEASE_CENTER;
struct timeval now = {0};
gettimeofday(&now, NULL);
@ -67,37 +164,48 @@ void *dev_out_thread_func(void *ptr) {
struct timeval mouse_last_hid_report_sent = now;
struct timeval keyboard_last_hid_report_sent = now;
uint8_t tmp_buf[256];
fd_set read_fds;
for (;;) {
FD_ZERO(&read_fds);
if (current_gamepad == GAMEPAD_DUALSENSE) {
} else if (current_gamepad == GAMEPAD_DUALSHOCK) {
}
FD_ZERO(&read_fds);
FD_SET(dev_out->out_message_pipe_fd, &read_fds);
// TODO: FD_SET(current_mouse_fd, &read_fds);
// TODO: FD_SET(current_keyboard_fd, &read_fds);
FD_SET(current_gamepad_fd, &read_fds);
// TODO: calculate the shortest time between multiple device
gettimeofday(&now, NULL);
const int64_t gamepad_timediff_us = get_timediff_usec(&gamepad_last_hid_report_sent, &now);
// calculate the shortest timeout between one of the multiple device will needs to send out its hid report
struct timeval timeout = {
//.tv_sec = (__time_t)devs->timeout_ms / (__time_t)1000,
//.tv_usec = ((__suseconds_t)devs->timeout_ms % (__suseconds_t)1000) * (__suseconds_t)1000000,
.tv_sec = (__time_t)gamepad_timediff_us / (__time_t)1000000,
.tv_usec = (__suseconds_t)gamepad_timediff_us % (__suseconds_t)1000000,
};
gettimeofday(&now, NULL);
int ready_fds = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout);
gamepad_status_qam_quirk(&dev_out->dev_stats.gamepad);
if (ready_fds == -1) {
const int err = errno;
fprintf(stderr, "Error reading devices: %d\n", err);
continue;
} else if (ready_fds == 0) {
// Timeout... simply retry
gettimeofday(&now, NULL);
// timeout: this means a device needs to send out the hid report
int64_t gamepad_time_diff_usecs = get_timediff_usec(&gamepad_last_hid_report_sent, &now);
if (gamepad_time_diff_usecs >= 1250) {
gamepad_last_hid_report_sent = now;
if (current_gamepad == GAMEPAD_DUALSENSE) {
} else if (current_gamepad == GAMEPAD_DUALSHOCK) {
virt_dualshock_compose(&controller_data.ds4, &dev_out->dev_stats.gamepad, tmp_buf);
virt_dualshock_send(&controller_data.ds4, tmp_buf);
}
}
continue;
}
@ -109,7 +217,6 @@ void *dev_out_thread_func(void *ptr) {
} else {
fprintf(stderr, "Error reading from out_message_pipe_fd: got %zu bytes, expected %zu butes", in_message_pipe_read_res, sizeof(in_message_t));
}
}
}

View file

@ -15,16 +15,28 @@ typedef enum in_message_gamepad_btn {
GAMEPAD_BTN_SHARE,
GAMEPAD_BTN_L1,
GAMEPAD_BTN_R1,
GAMEPAD_BTN_L2,
GAMEPAD_BTN_R2,
GAMEPAD_BTN_L2_TRIGGER,
GAMEPAD_BTN_R2_TRIGGER,
GAMEPAD_BTN_L3,
GAMEPAD_BTN_R3,
} __packed in_gamepad_element_t;
GAMEPAD_LEFT_JOYSTICK_X,
GAMEPAD_LEFT_JOYSTICK_Y,
GAMEPAD_RIGHT_JOYSTICK_X,
GAMEPAD_RIGHT_JOYSTICK_Y,
GAMEPAD_DPAD_X,
GAMEPAD_DPAD_Y,
} in_gamepad_element_t;
typedef struct in_message_gamepad_set_element {
in_gamepad_element_t element;
uint8_t status;
} __packed in_message_gamepad_set_element_t;
union {
uint8_t btn;
int32_t joystick_pos;
int8_t dpad; // -1 | 0 | +1
} status;
} in_message_gamepad_set_element_t;
typedef enum in_message_gamepad_action {
GAMEPAD_ACTION_PRESS_AND_RELEASE_CENTER,
@ -33,7 +45,7 @@ typedef enum in_message_gamepad_action {
typedef enum in_in_message_type {
GAMEPAD_SET_ELEMENT,
GAMEPAD_ACTION,
} __packed in_message_type_t;
} in_message_type_t;
typedef struct in_message {
in_message_type_t type;
@ -46,24 +58,24 @@ typedef struct in_message {
in_message_gamepad_set_element_t gamepad_set;
} data;
} __packed in_message_t;
} in_message_t;
typedef struct out_message_rumble {
uint16_t strong_magnitude;
uint16_t weak_magnitude;
} __packed out_message_rumble_t;
} out_message_rumble_t;
typedef struct out_message_leds {
uint8_t r;
uint8_t g;
uint8_t b;
} __packed out_message_leds_t;
} out_message_leds_t;
typedef enum out_message_type {
OUT_MSG_TYPE_RUMBLE = 0,
OUT_MSG_TYPE_LEDS,
} __packed out_message_type_t;
} out_message_type_t;
typedef struct out_message {
out_message_type_t type;
@ -73,4 +85,4 @@ typedef struct out_message {
out_message_leds_t leds;
} data;
} __packed out_message_t;
} out_message_t;

View file

@ -15,34 +15,34 @@ void xbox360_ev_map(const evdev_collected_t *const coll, int in_messages_pipe_fd
if (coll->ev[i].code == BTN_EAST) {
current_message.data.gamepad_set.element = (settings->nintendo_layout) ? GAMEPAD_BTN_CROSS : GAMEPAD_BTN_CIRCLE;
current_message.data.gamepad_set.status = coll->ev[i].value;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == BTN_NORTH) {
current_message.data.gamepad_set.element = (settings->nintendo_layout) ? GAMEPAD_BTN_TRIANGLE : GAMEPAD_BTN_SQUARE;
current_message.data.gamepad_set.status = coll->ev[i].value;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == BTN_SOUTH) {
current_message.data.gamepad_set.element = (settings->nintendo_layout) ? GAMEPAD_BTN_CIRCLE : GAMEPAD_BTN_CROSS;
current_message.data.gamepad_set.status = coll->ev[i].value;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == BTN_WEST) {
current_message.data.gamepad_set.element = (settings->nintendo_layout) ? GAMEPAD_BTN_SQUARE : GAMEPAD_BTN_TRIANGLE;
current_message.data.gamepad_set.status = coll->ev[i].value;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == BTN_SELECT) {
current_message.data.gamepad_set.element = GAMEPAD_BTN_OPTION;
current_message.data.gamepad_set.status = coll->ev[i].value;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == BTN_START) {
current_message.data.gamepad_set.element = GAMEPAD_BTN_SHARE;
current_message.data.gamepad_set.status = coll->ev[i].value;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == BTN_TR) {
current_message.data.gamepad_set.element = GAMEPAD_BTN_R1;
current_message.data.gamepad_set.status = coll->ev[i].value;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == BTN_TL) {
current_message.data.gamepad_set.element = GAMEPAD_BTN_L1;
current_message.data.gamepad_set.status = coll->ev[i].value;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == BTN_THUMBR) {
current_message.data.gamepad_set.element = GAMEPAD_BTN_R3;
current_message.data.gamepad_set.status = coll->ev[i].value;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == BTN_THUMBL) {
current_message.data.gamepad_set.element = GAMEPAD_BTN_L3;
current_message.data.gamepad_set.status = coll->ev[i].value;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == BTN_MODE) {
current_message.type = GAMEPAD_ACTION;
current_message.data.action = GAMEPAD_ACTION_PRESS_AND_RELEASE_CENTER;
@ -50,41 +50,38 @@ void xbox360_ev_map(const evdev_collected_t *const coll, int in_messages_pipe_fd
// send the button event over the pipe
last_write_res = write(in_messages_pipe_fd, (void*)&current_message, sizeof(in_message_t));
} /*else if (coll->ev[i].type == EV_ABS) {
} else if (coll->ev[i].type == EV_ABS) {
current_message.type = GAMEPAD_SET_ELEMENT;
if (coll->ev[i].code == ABS_X) {
stats->gamepad.joystick_positions[0][0] = (int32_t)coll->ev[i].value;
current_message.data.gamepad_set.element = GAMEPAD_LEFT_JOYSTICK_X;
current_message.data.gamepad_set.status.joystick_pos = (int32_t)coll->ev[i].value;
} else if (coll->ev[i].code == ABS_Y) {
stats->gamepad.joystick_positions[0][1] = (int32_t)coll->ev[i].value;
current_message.data.gamepad_set.element = GAMEPAD_LEFT_JOYSTICK_X;
current_message.data.gamepad_set.status.joystick_pos = (int32_t)coll->ev[i].value;
} else if (coll->ev[i].code == ABS_RX) {
stats->gamepad.joystick_positions[1][0] = (int32_t)coll->ev[i].value;
current_message.data.gamepad_set.element = GAMEPAD_RIGHT_JOYSTICK_X;
current_message.data.gamepad_set.status.joystick_pos = (int32_t)coll->ev[i].value;
} else if (coll->ev[i].code == ABS_RY) {
stats->gamepad.joystick_positions[1][1] = (int32_t)coll->ev[i].value;
current_message.data.gamepad_set.element = GAMEPAD_RIGHT_JOYSTICK_Y;
current_message.data.gamepad_set.status.joystick_pos = (int32_t)coll->ev[i].value;
} else if (coll->ev[i].code == ABS_Z) {
stats->gamepad.l2_trigger = (int32_t)coll->ev[i].value;
current_message.data.gamepad_set.element = GAMEPAD_BTN_L2_TRIGGER;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == ABS_RZ) {
stats->gamepad.r2_trigger = (int32_t)coll->ev[i].value;
current_message.data.gamepad_set.element = GAMEPAD_BTN_R2_TRIGGER;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == ABS_HAT0X) {
const int v = coll->ev[i].value;
stats->gamepad.dpad &= 0xF0;
if (v == 0) {
stats->gamepad.dpad |= 0x00;
} else if (v == 1) {
stats->gamepad.dpad |= 0x01;
} else if (v == -1) {
stats->gamepad.dpad |= 0x02;
}
current_message.data.gamepad_set.element = GAMEPAD_DPAD_X;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} else if (coll->ev[i].code == ABS_HAT0Y) {
const int v = coll->ev[i].value;
stats->gamepad.dpad &= 0x0F;
if (v == 0) {
stats->gamepad.dpad |= 0x00;
} else if (v == 1) {
stats->gamepad.dpad |= 0x20;
} else if (v == -1) {
stats->gamepad.dpad |= 0x10;
}
current_message.data.gamepad_set.element = GAMEPAD_DPAD_Y;
current_message.data.gamepad_set.status.btn = coll->ev[i].value;
}
} */
// send the button event over the pipe
last_write_res = write(in_messages_pipe_fd, (void*)&current_message, sizeof(in_message_t));
}
if (last_write_res != sizeof(in_message_t)) {
fprintf(stderr, "Unable to write data to the in_message pipe: %zd\n", last_write_res);