diff --git a/dev_in.c b/dev_in.c index 28f8735..b880d79 100644 --- a/dev_in.c +++ b/dev_in.c @@ -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; -} \ No newline at end of file +} diff --git a/dev_out.c b/dev_out.c index 883cfcc..83a893c 100644 --- a/dev_out.c +++ b/dev_out.c @@ -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)); } - } } diff --git a/message.h b/message.h index 4f1fb53..1fe3349 100644 --- a/message.h +++ b/message.h @@ -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; diff --git a/xbox360.c b/xbox360.c index 265a344..6bb53f3 100644 --- a/xbox360.c +++ b/xbox360.c @@ -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*)¤t_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*)¤t_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);