diff --git a/80-playstation-no-libinput.rules b/80-playstation-no-libinput.rules deleted file mode 100644 index 23c66ac..0000000 --- a/80-playstation-no-libinput.rules +++ /dev/null @@ -1,2 +0,0 @@ -ACTION=="add|change", KERNEL=="event[0-9]*", ATTRS{name}=="Wireless Controller Touchpad", ENV{LIBINPUT_IGNORE_DEVICE}="1" -ACTION=="add|change", KERNEL=="event[0-9]*", ATTRS{name}=="Wireless Edge Controller Touchpad", ENV{LIBINPUT_IGNORE_DEVICE}="1" \ No newline at end of file diff --git a/99-js-block.rules b/99-js-block.rules deleted file mode 100644 index da1ef16..0000000 --- a/99-js-block.rules +++ /dev/null @@ -1 +0,0 @@ -KERNEL=="js[0-9]*|event[0-9]*", SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="028e", MODE="000", GROUP="root", TAG="", RUN+="/bin/chmod 000 /dev/input/%k" \ No newline at end of file diff --git a/99-xbox360-block.rules b/99-xbox360-block.rules deleted file mode 100644 index b4e576a..0000000 --- a/99-xbox360-block.rules +++ /dev/null @@ -1 +0,0 @@ -ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="045E", ATTRS{idProduct}=="028E", RUN+="/bin/sh -c 'echo 0 > /sys$DEVPATH/authorized'" \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 9aeeb08..d85d929 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,13 +13,10 @@ set(ROGUE_EXECUTABLE_NAME "rogue-enemy") set(STRAY_EXECUTABLE_NAME "stray-ally") set(ALLINONE_EXECUTABLE_NAME "allynone") -find_package(PkgConfig REQUIRED) # Include functions provided by PkgConfig module. - set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) add_executable(${ROGUE_EXECUTABLE_NAME} - dev_timer.c dev_evdev.c dev_iio.c dev_hidraw.c @@ -38,10 +35,7 @@ add_executable(${STRAY_EXECUTABLE_NAME} settings.c virt_ds4.c virt_ds5.c - virt_mouse.c - virt_kbd.c devices_status.c - rogue_enemy.c ) add_executable(${ALLINONE_EXECUTABLE_NAME} @@ -50,10 +44,7 @@ add_executable(${ALLINONE_EXECUTABLE_NAME} settings.c virt_ds4.c virt_ds5.c - virt_mouse.c - virt_kbd.c devices_status.c - dev_timer.c dev_evdev.c dev_iio.c dev_hidraw.c @@ -67,7 +58,7 @@ add_executable(${ALLINONE_EXECUTABLE_NAME} set_property(TARGET ${ALLINONE_EXECUTABLE_NAME} PROPERTY C_STANDARD 17) -target_link_libraries(${ALLINONE_EXECUTABLE_NAME} PRIVATE Threads::Threads -levdev -ludev -lconfig -lm -lz) +target_link_libraries(${ALLINONE_EXECUTABLE_NAME} PRIVATE Threads::Threads -levdev -ludev -lconfig -lm) set_target_properties(${ALLINONE_EXECUTABLE_NAME} PROPERTIES LINKER_LANGUAGE C) @@ -83,7 +74,7 @@ install(TARGETS ${ROGUE_EXECUTABLE_NAME} DESTINATION bin) set_property(TARGET ${STRAY_EXECUTABLE_NAME} PROPERTY C_STANDARD 17) -target_link_libraries(${STRAY_EXECUTABLE_NAME} PRIVATE Threads::Threads -levdev -ludev -lconfig -lm -lz) +target_link_libraries(${STRAY_EXECUTABLE_NAME} PRIVATE Threads::Threads -levdev -ludev -lconfig -lm) set_target_properties(${STRAY_EXECUTABLE_NAME} PROPERTIES LINKER_LANGUAGE C) diff --git a/References/Ally/left_back_paddle.log b/References/Ally/left_back_paddle.log deleted file mode 100644 index 65dbadb..0000000 --- a/References/Ally/left_back_paddle.log +++ /dev/null @@ -1,22 +0,0 @@ -Event: time 1702734480.395212, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70069 -Event: time 1702734480.395212, type 1 (EV_KEY), code 184 (KEY_F14), value 1 -Event: time 1702734480.395212, -------------- SYN_REPORT ------------ -Event: time 1702734480.666881, type 1 (EV_KEY), code 184 (KEY_F14), value 2 -Event: time 1702734480.666881, -------------- SYN_REPORT ------------ -Event: time 1702734480.703572, type 1 (EV_KEY), code 184 (KEY_F14), value 2 -Event: time 1702734480.703572, -------------- SYN_REPORT ------------ -Event: time 1702734480.740210, type 1 (EV_KEY), code 184 (KEY_F14), value 2 -Event: time 1702734480.740210, -------------- SYN_REPORT ------------ -Event: time 1702734480.776877, type 1 (EV_KEY), code 184 (KEY_F14), value 2 -Event: time 1702734480.776877, -------------- SYN_REPORT ------------ -Event: time 1702734480.813547, type 1 (EV_KEY), code 184 (KEY_F14), value 2 -Event: time 1702734480.813547, -------------- SYN_REPORT ------------ -Event: time 1702734480.850210, type 1 (EV_KEY), code 184 (KEY_F14), value 2 -Event: time 1702734480.850210, -------------- SYN_REPORT ------------ -Event: time 1702734480.890215, type 1 (EV_KEY), code 184 (KEY_F14), value 2 -Event: time 1702734480.890215, -------------- SYN_REPORT ------------ -Event: time 1702734480.930212, type 1 (EV_KEY), code 184 (KEY_F14), value 2 -Event: time 1702734480.930212, -------------- SYN_REPORT ------------ -Event: time 1702734480.943181, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70069 -Event: time 1702734480.943181, type 1 (EV_KEY), code 184 (KEY_F14), value 0 -Event: time 1702734480.943181, -------------- SYN_REPORT ------------ \ No newline at end of file diff --git a/References/Ally/left_screen_button_long.log b/References/Ally/left_screen_button_long.log deleted file mode 100644 index d3d1b69..0000000 --- a/References/Ally/left_screen_button_long.log +++ /dev/null @@ -1,18 +0,0 @@ -Event: time 1702734659.559525, type 4 (EV_MSC), code 4 (MSC_SCAN), value 700e0 -Event: time 1702734659.559525, type 1 (EV_KEY), code 29 (KEY_LEFTCTRL), value 1 -Event: time 1702734659.559525, -------------- SYN_REPORT ------------ -Event: time 1702734659.560490, type 4 (EV_MSC), code 4 (MSC_SCAN), value 700e2 -Event: time 1702734659.560490, type 1 (EV_KEY), code 56 (KEY_LEFTALT), value 1 -Event: time 1702734659.560490, -------------- SYN_REPORT ------------ -Event: time 1702734659.561435, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7004c -Event: time 1702734659.561435, type 1 (EV_KEY), code 111 (KEY_DELETE), value 1 -Event: time 1702734659.561435, -------------- SYN_REPORT ------------ -Event: time 1702734659.562485, type 4 (EV_MSC), code 4 (MSC_SCAN), value 700e0 -Event: time 1702734659.562485, type 1 (EV_KEY), code 29 (KEY_LEFTCTRL), value 0 -Event: time 1702734659.562485, -------------- SYN_REPORT ------------ -Event: time 1702734659.563486, type 4 (EV_MSC), code 4 (MSC_SCAN), value 700e2 -Event: time 1702734659.563486, type 1 (EV_KEY), code 56 (KEY_LEFTALT), value 0 -Event: time 1702734659.563486, -------------- SYN_REPORT ------------ -Event: time 1702734659.565433, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7004c -Event: time 1702734659.565433, type 1 (EV_KEY), code 111 (KEY_DELETE), value 0 -Event: time 1702734659.565433, -------------- SYN_REPORT ------------ diff --git a/References/Ally/left_screen_button_short.log b/References/Ally/left_screen_button_short.log deleted file mode 100644 index e42715c..0000000 --- a/References/Ally/left_screen_button_short.log +++ /dev/null @@ -1,6 +0,0 @@ -Event: time 1702734692.300847, type 4 (EV_MSC), code 4 (MSC_SCAN), value ff3100a6 -Event: time 1702734692.300847, type 1 (EV_KEY), code 186 (KEY_F16), value 1 -Event: time 1702734692.300847, -------------- SYN_REPORT ------------ -Event: time 1702734692.301778, type 4 (EV_MSC), code 4 (MSC_SCAN), value ff3100a6 -Event: time 1702734692.301778, type 1 (EV_KEY), code 186 (KEY_F16), value 0 -Event: time 1702734692.301778, -------------- SYN_REPORT ------------ diff --git a/References/Ally/right_back_paddle.log b/References/Ally/right_back_paddle.log deleted file mode 100644 index b5d833b..0000000 --- a/References/Ally/right_back_paddle.log +++ /dev/null @@ -1,14 +0,0 @@ -Event: time 1702734541.227670, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7006a -Event: time 1702734541.227670, type 1 (EV_KEY), code 185 (KEY_F15), value 1 -Event: time 1702734541.227670, -------------- SYN_REPORT ------------ -Event: time 1702734541.490206, type 1 (EV_KEY), code 185 (KEY_F15), value 2 -Event: time 1702734541.490206, -------------- SYN_REPORT ------------ -Event: time 1702734541.530208, type 1 (EV_KEY), code 185 (KEY_F15), value 2 -Event: time 1702734541.530208, -------------- SYN_REPORT ------------ -Event: time 1702734541.570205, type 1 (EV_KEY), code 185 (KEY_F15), value 2 -Event: time 1702734541.570205, -------------- SYN_REPORT ------------ -Event: time 1702734541.606872, type 1 (EV_KEY), code 185 (KEY_F15), value 2 -Event: time 1702734541.606872, -------------- SYN_REPORT ------------ -Event: time 1702734541.640678, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7006a -Event: time 1702734541.640678, type 1 (EV_KEY), code 185 (KEY_F15), value 0 -Event: time 1702734541.640678, -------------- SYN_REPORT ------------ diff --git a/References/Ally/right_screen_button_long.log b/References/Ally/right_screen_button_long.log deleted file mode 100644 index 24492de..0000000 --- a/References/Ally/right_screen_button_long.log +++ /dev/null @@ -1,17 +0,0 @@ -Event: time 1702734610.835523, type 4 (EV_MSC), code 4 (MSC_SCAN), value ff3100a7 -Event: time 1702734610.835523, type 1 (EV_KEY), code 187 (KEY_F17), value 1 -Event: time 1702734610.835523, -------------- SYN_REPORT ------------ -Event: time 1702734610.836480, type 4 (EV_MSC), code 4 (MSC_SCAN), value ff3100a7 -Event: time 1702734610.836480, type 1 (EV_KEY), code 187 (KEY_F17), value 0 -Event: time 1702734610.836480, -------------- SYN_REPORT ------------ - - -F17 appears before release - - -Event: time 1702734611.433499, type 4 (EV_MSC), code 4 (MSC_SCAN), value ff3100a8 -Event: time 1702734611.433499, type 1 (EV_KEY), code 188 (KEY_F18), value 1 -Event: time 1702734611.433499, -------------- SYN_REPORT ------------ -Event: time 1702734611.434434, type 4 (EV_MSC), code 4 (MSC_SCAN), value ff3100a8 -Event: time 1702734611.434434, type 1 (EV_KEY), code 188 (KEY_F18), value 0 -Event: time 1702734611.434434, -------------- SYN_REPORT ------------ diff --git a/References/Ally/right_screen_button_short.log b/References/Ally/right_screen_button_short.log deleted file mode 100644 index 8f4ad4d..0000000 --- a/References/Ally/right_screen_button_short.log +++ /dev/null @@ -1,6 +0,0 @@ -Event: time 1702734588.908929, type 4 (EV_MSC), code 4 (MSC_SCAN), value ff310038 -Event: time 1702734588.908929, type 1 (EV_KEY), code 148 (KEY_PROG1), value 1 -Event: time 1702734588.908929, -------------- SYN_REPORT ------------ -Event: time 1702734588.909906, type 4 (EV_MSC), code 4 (MSC_SCAN), value ff310038 -Event: time 1702734588.909906, type 1 (EV_KEY), code 148 (KEY_PROG1), value 0 -Event: time 1702734588.909906, -------------- SYN_REPORT ------------ diff --git a/allynone.c b/allynone.c index e95d6a7..8f39900 100644 --- a/allynone.c +++ b/allynone.c @@ -10,66 +10,51 @@ #include "rog_ally.h" #include "legion_go.h" -#include +/* +logic_t global_logic; + +static output_dev_t out_gamepadd_dev = { + .logic = &global_logic, +}; + +void sig_handler(int signo) +{ + if (signo == SIGINT) { + logic_request_termination(&global_logic); + printf("Received SIGINT\n"); + } +} +*/ static const char* configuration_file = "/etc/ROGueENEMY/config.cfg"; -int main(int argc, char ** argv) { - // Lock all current and future pages from preventing of being paged to swap - const int lockall_res = mlockall( MCL_CURRENT | MCL_FUTURE ); - if (lockall_res) { - fprintf(stderr, "mlockall failed: %d", lockall_res); - } +controller_settings_t settings; +int main(int argc, char ** argv) { int ret = 0; - // fill in configuration from file: automatic fallback to default - dev_in_settings_t in_settings = { - .enable_qam = true, - .ff_gain = 0xFFFF, - .rumble_on_mode_switch = true, - .m1m2_mode = 0, - .touchbar = true, - .enable_thermal_profiles_switching = false, - .default_thermal_profile = -1, - .enable_leds_commands = false, - .enable_imu = true, - .imu_polling_interface = true, - }; - - load_in_config(&in_settings, configuration_file); - - dev_out_settings_t out_settings = { - .default_gamepad = 0, - .nintendo_layout = false, - .gamepad_leds_control = true, - .gamepad_rumble_control = true, - .controller_bluetooth = false, - .dualsense_edge = false, - .swap_y_z = false, - .invert_x = false, - .gyro_to_analog_activation_treshold = 16, - .gyro_to_analog_mapping = 4, - }; - - load_out_config(&out_settings, configuration_file); + init_config(&settings); + fill_config(&settings, configuration_file); input_dev_composite_t* in_devs = NULL; - - char bname[256]; - if (dmi_board_name(bname, sizeof(bname)) < 0) { + + int dmi_name_fd = open("/sys/class/dmi/id/board_name", O_RDONLY | O_NONBLOCK); + if (dmi_name_fd < 0) { fprintf(stderr, "Cannot get the board name\n"); return EXIT_FAILURE; } + char bname[256]; + memset(bname, 0, sizeof(bname)); + read(dmi_name_fd, bname, sizeof(bname)); if (strstr(bname, "RC71L") != NULL) { printf("Running in an Asus ROG Ally device\n"); - in_devs = rog_ally_device_def(&in_settings); + in_devs = rog_ally_device_def(&settings); } else if (strstr(bname, "LNVNB161216")) { printf("Running in an Lenovo Legion Go device\n"); - in_devs = legion_go_device_def(); + in_devs = legion_go_device_def(&settings); } - + close(dmi_name_fd); int dev_in_thread_creation = -1; int dev_out_thread_creation = -1; @@ -120,12 +105,12 @@ int main(int argc, char ** argv) { .out_message_pipe_fd = out_message_pipes[0], } } - }, - .settings = in_settings, + } }; // populate the output device thread data dev_out_data_t dev_out_thread_data = { + .gamepad = GAMEPAD_DUALSENSE, .flags = 0x00000000U, .communication = { .type = ipc_unix_pipe, @@ -135,8 +120,7 @@ int main(int argc, char ** argv) { .out_message_pipe_fd = out_message_pipes[1], } } - }, - .settings = out_settings, + } }; pthread_t dev_in_thread; diff --git a/config.cfg.default b/config.cfg.default index 245f287..a6ff041 100644 --- a/config.cfg.default +++ b/config.cfg.default @@ -1,20 +1,5 @@ enable_qam = true; -ff_gain = 255; +ff_gain = 100; nintendo_layout = false; -default_gamepad = 1; -rumble_on_mode_switch = true; -gamepad_rumble_control = true; -gamepad_leds_control = true; -m1m2_mode = 1; -gyro_to_analog_mapping = 5; -gyro_to_analog_activation_treshold = 1; -touchbar = true; -controller_bluetooth = true; -dualsense_edge = false; -swap_y_z = true; -invert_x = true; -enable_thermal_profiles_switching = true; -default_thermal_profile = 3; -enable_leds_commands = true; -enable_imu = true; -imu_polling_interface = true; \ No newline at end of file +gamepad_output_device = 1; +rumble_dedicated_thread = false; \ No newline at end of file diff --git a/dev_evdev.c b/dev_evdev.c index 2dbba3f..107db4f 100644 --- a/dev_evdev.c +++ b/dev_evdev.c @@ -2,7 +2,6 @@ #include static const char *input_path = "/dev/input/"; -static const char *hidden_input_path = "/dev/input/.hidden/"; static pthread_mutex_t input_acquire_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -134,17 +133,6 @@ int dev_evdev_open( int open_sysfs_idx = -1; - struct stat st = {0}; - - if (stat(hidden_input_path, &st) == -1) { - printf("Directory %s does not exits -- creating it\n", hidden_input_path); - if (mkdir(hidden_input_path, 0700) == 0) { - printf("Directory %s creates successfully", hidden_input_path); - } else { - fprintf(stderr, "Error creating %s directory: %d\n", hidden_input_path, errno); - } - } - const int mutex_lock_res = pthread_mutex_lock(&input_acquire_mutex); if (mutex_lock_res != 0) { fprintf(stderr, "Cannot lock input mutex: %d\n", mutex_lock_res); @@ -158,13 +146,6 @@ int dev_evdev_open( goto dev_evdev_open_err; } - char *const hidden_path = malloc(MAX_PATH_LEN); - if (path == NULL) { - free(path); - res = -ENOMEM; - goto dev_evdev_open_err; - } - DIR *d; struct dirent *dir; d = opendir(input_path); @@ -178,7 +159,6 @@ int dev_evdev_open( continue; } - snprintf(hidden_path, MAX_PATH_LEN - 1, "%s%s", hidden_input_path, dir->d_name); snprintf(path, MAX_PATH_LEN - 1, "%s%s", input_path, dir->d_name); //printf("Testing for device %s\n", path); @@ -219,17 +199,6 @@ int dev_evdev_open( continue; } - if (rename(path, hidden_path) != 0) { - fprintf(stderr, "Unable to move the device: %d\n", errno); - libevdev_free(*out_evdev); - close(fd); - continue; - } else { - if (chmod(hidden_path, 000) != 0) { - fprintf(stderr, "Unable to perform chmod 000 to opened device\n"); - } - } - // register the device as being opened already open_paths[open_sysfs_idx].sysfs_path = path; open_paths[open_sysfs_idx].fd = fd; diff --git a/dev_hidraw.c b/dev_hidraw.c index 4f04f04..bb8d1c9 100644 --- a/dev_hidraw.c +++ b/dev_hidraw.c @@ -82,7 +82,7 @@ int dev_hidraw_open( //printf("Testing for device %s\n", path); // try to open the device, if it cannot be opened to go the next - int fd = open(path, O_RDWR | O_NONBLOCK); + int fd = open(path, O_RDWR); if (fd < 0) { //fprintf(stderr, "Cannot open %s, device skipped.\n", path); continue; diff --git a/dev_in.c b/dev_in.c index 3f2418e..4956b18 100644 --- a/dev_in.c +++ b/dev_in.c @@ -5,16 +5,14 @@ #include "message.h" #include "dev_evdev.h" #include "dev_iio.h" -#include "dev_timer.h" - -#include +#include +#include typedef enum dev_in_type { DEV_IN_TYPE_NONE, DEV_IN_TYPE_HIDRAW, DEV_IN_TYPE_IIO, DEV_IN_TYPE_EV, - DEV_IN_TYPE_TIMER, } dev_in_type_t; typedef struct dev_in_iio { @@ -25,10 +23,6 @@ typedef struct dev_in_iio { typedef struct dev_in_hidraw { dev_hidraw_t *hidrawdev; - - hidraw_callbacks_t callbacks; - - void* user_data; } dev_in_hidraw_t; typedef struct dev_in_ev { @@ -46,29 +40,12 @@ typedef struct dev_in_ev { struct ff_effect ff_effect; - ev_callbacks_t callbacks; - - void* user_data; - } dev_in_ev_t; -typedef struct dev_in_timer { - - dev_timer_t* timer; - - const char* name; - - timer_callbacks_t callbacks; - - void* user_data; - -} dev_in_timer_t; - typedef union dev_in_aggr { dev_in_ev_t evdev; dev_in_iio_t iio; dev_in_hidraw_t hidraw; - dev_in_timer_t timer; } dev_in_aggr_t; typedef struct dev_in { @@ -91,30 +68,7 @@ static int map_message_from_iio(dev_in_iio_t *const in_iio, in_message_t *const goto send_message_from_iio_err; } - if (res != 24) { - fprintf(stderr, "Invalid read lenght\n"); - res = -EIO; - goto send_message_from_iio_err; - } - - uint16_t *const scan_elements = (uint16_t*)&data[0]; - int64_t *const timestamp = (int64_t*)&data[16]; // either that or (int64_t*)&data[12] - - messages[0].type = GAMEPAD_SET_ELEMENT; - messages[0].data.gamepad_set.element = GAMEPAD_ACCELEROMETER; - messages[1].data.gamepad_set.status.accel.sample_timestamp_ns = *timestamp; - messages[0].data.gamepad_set.status.accel.x = scan_elements[0]; - messages[0].data.gamepad_set.status.accel.y = (uint16_t)(-1) * scan_elements[2]; - messages[0].data.gamepad_set.status.accel.z = scan_elements[1]; - - messages[1].type = GAMEPAD_SET_ELEMENT; - messages[1].data.gamepad_set.element = GAMEPAD_GYROSCOPE; - messages[1].data.gamepad_set.status.gyro.sample_timestamp_ns = *timestamp; - messages[1].data.gamepad_set.status.gyro.x = scan_elements[3]; - messages[1].data.gamepad_set.status.gyro.y = (uint16_t)(-1) * scan_elements[5]; - messages[1].data.gamepad_set.status.gyro.z = scan_elements[4]; - - res = 2; + res = 0; send_message_from_iio_err: return res; @@ -166,25 +120,7 @@ fill_message_from_evdev_err_completed: return res; } -static int timer_open_device( - const dev_in_settings_t *const in_settings, - const timer_filters_t *const in_filters, - dev_in_timer_t *const out_dev -) { - int res = dev_timer_open(in_filters, &out_dev->timer); - if (res != 0) { - fprintf(stderr, "Unable to open the timer device: %d\n", res); - goto timer_open_device_err; - } - - printf("Opened timer device: %s\n", in_filters->name); - -timer_open_device_err: - return res; -} - static int hidraw_open_device( - const dev_in_settings_t *const in_settings, const hidraw_filters_t *const in_filters, dev_in_hidraw_t *const out_dev ) { @@ -205,7 +141,6 @@ iio_open_device_err: } static int iio_open_device( - const dev_in_settings_t *const in_settings, const iio_filters_t *const in_filters, dev_in_iio_t *const out_dev ) { @@ -229,7 +164,6 @@ iio_open_device_err: } static int evdev_open_device( - const dev_in_settings_t *const in_settings, const uinput_filters_t *const in_filters, dev_in_ev_t *const out_dev ) { @@ -262,14 +196,14 @@ static int evdev_open_device( out_dev->ff_effect.type = FF_RUMBLE; out_dev->ff_effect.id = -1; out_dev->ff_effect.replay.delay = 0; - out_dev->ff_effect.replay.length = 1000; + out_dev->ff_effect.replay.length = 5000; out_dev->ff_effect.u.rumble.strong_magnitude = 0x0000; out_dev->ff_effect.u.rumble.weak_magnitude = 0x0000; const struct input_event gain = { .type = EV_FF, .code = FF_GAIN, - .value = in_settings->ff_gain, + .value = 0xFFFF, // TODO: give the user the ability to change this }; const int gain_set_res = write(libevdev_get_fd(out_dev->evdev), (const void*)&gain, sizeof(gain)); @@ -298,11 +232,7 @@ static void hidraw_close_device(dev_in_hidraw_t *const out_hidraw) { dev_hidraw_close(out_hidraw->hidrawdev); } -static void timer_close_device(dev_in_timer_t *const out_hidraw) { - dev_timer_close(out_hidraw->timer); -} - -static void handle_rumble_device(const dev_in_settings_t *const conf, dev_in_ev_t *const in_dev, const out_message_rumble_t *const in_rumble_msg) { +static void handle_rumble_device(dev_in_ev_t *const in_dev, const out_message_rumble_t *const in_rumble_msg) { if (!in_dev->has_rumble_support) { return; } @@ -351,57 +281,10 @@ static void handle_rumble_device(const dev_in_settings_t *const conf, dev_in_ev_ } } -static void handle_rumble(const dev_in_settings_t *const conf, dev_in_t *const in_devs, size_t in_devs_count, const out_message_rumble_t *const in_rumble_msg) { +static void handle_rumble(dev_in_t *const in_devs, size_t in_devs_count, const out_message_rumble_t *const in_rumble_msg) { for (size_t i = 0; i < in_devs_count; ++i) { if (in_devs[i].type == DEV_IN_TYPE_EV) { - handle_rumble_device( - conf, - &in_devs[i].dev.evdev, - in_rumble_msg - ); - } - } -} - -static void handle_leds(const dev_in_settings_t *const conf, dev_in_t *const in_devs, size_t in_devs_count, const out_message_leds_t *const in_leds_msg) { - for (size_t i = 0; i < in_devs_count; ++i) { - if (in_devs[i].type == DEV_IN_TYPE_HIDRAW) { - in_devs[i].dev.hidraw.callbacks.leds_callback( - conf, - in_devs[i].dev.hidraw.hidrawdev->fd, - in_leds_msg->r, - in_leds_msg->g, - in_leds_msg->b, - in_devs[i].dev.hidraw.user_data - ); - } - } -} - -static void handle_timeout( - const dev_in_settings_t *const conf, - dev_in_t *const in_devs, - size_t in_devs_count, - const char* name, - uint64_t expirations -) { - for (size_t i = 0; i < in_devs_count; ++i) { - if (in_devs[i].type == DEV_IN_TYPE_EV) { - in_devs[i].dev.evdev.callbacks.timeout_callback( - conf, - in_devs[i].dev.evdev.evdev, - name, - expirations, - in_devs[i].dev.evdev.user_data - ); - } else if (in_devs[i].type == DEV_IN_TYPE_HIDRAW) { - in_devs[i].dev.hidraw.callbacks.timeout_callback( - conf, - dev_hidraw_get_fd(in_devs[i].dev.hidraw.hidrawdev), - name, - expirations, - in_devs[i].dev.hidraw.user_data - ); + handle_rumble_device(&in_devs[i].dev.evdev, in_rumble_msg); } } } @@ -409,7 +292,7 @@ static void handle_timeout( static int open_socket(struct sockaddr_un *serveraddr) { int res = -ENODEV; - int sd = socket(AF_UNIX, SOCK_STREAM, 0); + int sd = socket(AF_UNIX, SOCK_SEQPACKET, 0); if (sd < 0) { res = sd; @@ -431,15 +314,23 @@ void* dev_in_thread_func(void *ptr) { dev_in_data_t *const dev_in_data = (dev_in_data_t*)ptr; void* platform_data; - const int platform_init_res = dev_in_data->input_dev_decl->init_fn(&dev_in_data->settings, &platform_data); + const int platform_init_res = dev_in_data->input_dev_decl->init_fn(&platform_data); if (platform_init_res != 0) { fprintf(stderr, "Error setting up platform data: %d\n", platform_init_res); } + struct timeval timeout = { + .tv_sec = (__time_t)dev_in_data->timeout_ms / (__time_t)1000, + .tv_usec = ((__suseconds_t)dev_in_data->timeout_ms % (__suseconds_t)1000) * (__suseconds_t)1000000, + }; + fd_set read_fds; const size_t max_devices = dev_in_data->input_dev_decl->dev_count; + in_message_t* controller_msg = malloc(sizeof(in_message_t) * 4); + size_t controller_msg_avail = controller_msg == NULL ? 0 : 4; + dev_in_t* const devices = malloc(sizeof(dev_in_t) * max_devices); if (devices == NULL) { fprintf(stderr, "Unable to allocate memory to hold devices -- aborting input thread\n"); @@ -473,8 +364,6 @@ void* dev_in_thread_func(void *ptr) { continue; } } - - FD_SET(dev_in_data->communication.endpoint.socket.fd, &read_fds); } for (size_t i = 0; i < max_devices; ++i) { @@ -485,86 +374,36 @@ void* dev_in_thread_func(void *ptr) { FD_SET(dev_iio_get_buffer_fd(devices[i].dev.iio.iiodev), &read_fds); } else if (devices[i].type == DEV_IN_TYPE_HIDRAW) { FD_SET(dev_hidraw_get_fd(devices[i].dev.hidraw.hidrawdev), &read_fds); - } else if (devices[i].type == DEV_IN_TYPE_TIMER) { - FD_SET(dev_timer_get_fd(devices[i].dev.timer.timer), &read_fds); } else if (devices[i].type == DEV_IN_TYPE_NONE) { const input_dev_type_t d_type = dev_in_data->input_dev_decl->dev[i]->dev_type; if (d_type == input_dev_type_uinput) { fprintf(stderr, "Device (evdev) %zu not found -- Attempt reconnection for device named %s\n", i, dev_in_data->input_dev_decl->dev[i]->filters.ev.name); - const int open_res = evdev_open_device( - &dev_in_data->settings, - &dev_in_data->input_dev_decl->dev[i]->filters.ev, - &devices[i].dev.evdev - ); - + const int open_res = evdev_open_device(&dev_in_data->input_dev_decl->dev[i]->filters.ev, &devices[i].dev.evdev); if (open_res == 0) { devices[i].type = DEV_IN_TYPE_EV; - devices[i].dev.evdev.user_data = dev_in_data->input_dev_decl->dev[i]->user_data; - devices[i].dev.evdev.callbacks = dev_in_data->input_dev_decl->dev[i]->map.ev_callbacks; // device is now connected, query it in select FD_SET(libevdev_get_fd(devices[i].dev.evdev.evdev), &read_fds); } } else if (d_type == input_dev_type_iio) { fprintf(stderr, "Device (iio) %zu not found -- Attempt reconnection for device named %s\n", i, dev_in_data->input_dev_decl->dev[i]->filters.iio.name); - - const int open_res = iio_open_device( - &dev_in_data->settings, - &dev_in_data->input_dev_decl->dev[i]->filters.iio, - &devices[i].dev.iio - ); - + + const int open_res = iio_open_device(&dev_in_data->input_dev_decl->dev[i]->filters.iio, &devices[i].dev.iio); if (open_res == 0) { devices[i].type = DEV_IN_TYPE_IIO; - - // device is now connected, query it in select - FD_SET(dev_iio_get_buffer_fd(devices[i].dev.iio.iiodev), &read_fds); } } else if (d_type == input_dev_type_hidraw) { fprintf(stderr, "Device (hidraw) %zu not found -- Attempt reconnection for device %x:%x\n", i, dev_in_data->input_dev_decl->dev[i]->filters.hidraw.pid, dev_in_data->input_dev_decl->dev[i]->filters.hidraw.vid); - - const int open_res = hidraw_open_device( - &dev_in_data->settings, - &dev_in_data->input_dev_decl->dev[i]->filters.hidraw, - &devices[i].dev.hidraw - ); - + + const int open_res = hidraw_open_device(&dev_in_data->input_dev_decl->dev[i]->filters.hidraw, &devices[i].dev.hidraw); if (open_res == 0) { - devices[i].dev.hidraw.callbacks = dev_in_data->input_dev_decl->dev[i]->map.hidraw_callbacks; - devices[i].dev.hidraw.user_data = dev_in_data->input_dev_decl->dev[i]->user_data; devices[i].type = DEV_IN_TYPE_HIDRAW; - - // device is now connected, query it in select - FD_SET(dev_hidraw_get_fd(devices[i].dev.hidraw.hidrawdev), &read_fds); - } - } else if (d_type == input_dev_type_timer) { - fprintf(stderr, "Device (timer) %zu not found -- Attempt to create it with name %s\n", i, dev_in_data->input_dev_decl->dev[i]->filters.timer.name); - - const int open_res = timer_open_device( - &dev_in_data->settings, - &dev_in_data->input_dev_decl->dev[i]->filters.timer, - &devices[i].dev.timer - ); - - if (open_res == 0) { - devices[i].dev.timer.callbacks = dev_in_data->input_dev_decl->dev[i]->map.timer_callbacks; - devices[i].dev.timer.user_data = dev_in_data->input_dev_decl->dev[i]->user_data; - devices[i].dev.timer.name = dev_in_data->input_dev_decl->dev[i]->filters.timer.name; - devices[i].type = DEV_IN_TYPE_TIMER; - - // device is now connected, query it in select - FD_SET(dev_timer_get_fd(devices[i].dev.timer.timer), &read_fds); } } } } - struct timeval timeout = { - .tv_sec = (__time_t)dev_in_data->timeout_ms / (__time_t)1000, - .tv_usec = ((__suseconds_t)dev_in_data->timeout_ms % (__suseconds_t)1000) * (__suseconds_t)1000000, - }; - int ready_fds = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); if (ready_fds == -1) { @@ -573,7 +412,6 @@ void* dev_in_thread_func(void *ptr) { continue; } else if (ready_fds == 0) { // Timeout... simply retry - printf("TIMEOUT\n"); continue; } @@ -590,22 +428,18 @@ void* dev_in_thread_func(void *ptr) { const ssize_t out_message_pipe_read_res = read(out_message_fd, (void*)&out_msg, sizeof(out_message_t)); if (out_message_pipe_read_res == sizeof(out_message_t)) { if (out_msg.type == OUT_MSG_TYPE_RUMBLE) { - handle_rumble(&dev_in_data->settings, devices, max_devices, &out_msg.data.rumble); + handle_rumble(devices, max_devices, &out_msg.data.rumble); } else if (out_msg.type == OUT_MSG_TYPE_LEDS) { // first inform the platform - const int platform_leds_res = dev_in_data->input_dev_decl->leds_fn( - &dev_in_data->settings, - out_msg.data.leds.r, out_msg.data.leds.g, - out_msg.data.leds.b, platform_data - ); + const int platform_leds_res = dev_in_data->input_dev_decl->leds_fn(out_msg.data.leds.r, out_msg.data.leds.g, out_msg.data.leds.b, platform_data); if (platform_leds_res != 0) { fprintf(stderr, "Error in changing platform LEDs: %d\n", platform_leds_res); } - handle_leds(&dev_in_data->settings, devices, max_devices, &out_msg.data.leds); + // TODO: handle_leds() } } else { - fprintf(stderr, "Error reading from out_message_pipe_fd: got %zu bytes, expected %zu bytes\n", out_message_pipe_read_res, sizeof(out_message_t)); + fprintf(stderr, "Error reading from out_message_pipe_fd: got %zu bytes, expected %zu butes\n", out_message_pipe_read_res, sizeof(out_message_t)); // in case of an error reschedule to socket for reconnection if (dev_in_data->communication.type == ipc_client_socket) { @@ -624,8 +458,6 @@ void* dev_in_thread_func(void *ptr) { fd = dev_iio_get_buffer_fd(devices[i].dev.iio.iiodev); } else if (devices[i].type == DEV_IN_TYPE_HIDRAW) { fd = dev_hidraw_get_fd(devices[i].dev.hidraw.hidrawdev); - } else if (devices[i].type == DEV_IN_TYPE_TIMER) { - fd = dev_timer_get_fd(devices[i].dev.timer.timer); } else { continue; } @@ -634,92 +466,55 @@ void* dev_in_thread_func(void *ptr) { continue; } - in_message_t controller_msg[MAX_IN_MESSAGES]; - size_t controller_msg_avail = sizeof(controller_msg) / sizeof(in_message_t); - int controller_msg_count = -EIO; + int controller_msg_count = -ENOMEM; + while (controller_msg_count == -ENOMEM) { + // the following part fills controller_msg and writes in controller_msg_count an error or the number of messages to be sent to the output device + if (devices[i].type == DEV_IN_TYPE_EV) { + evdev_collected_t coll = { + .ev_count = 0 + }; - // the following part fills controller_msg and writes in controller_msg_count an error or the number of messages to be sent to the output device - if (devices[i].type == DEV_IN_TYPE_EV) { - evdev_collected_t coll = { - .ev_count = 0 - }; + controller_msg_count = fill_message_from_evdev(&devices[i].dev.evdev, &coll); + if (controller_msg_count != 0) { + fprintf(stderr, "Unable to fill input_event(s) for device %zd: %d -- Will reconnect the device\n", i, controller_msg_count); + evdev_close_device(&devices[i].dev.evdev); + devices[i].type = DEV_IN_TYPE_NONE; + continue; + } - controller_msg_count = fill_message_from_evdev(&devices[i].dev.evdev, &coll); - if (controller_msg_count != 0) { - fprintf(stderr, "Unable to fill input_event(s) for device %zd: %d -- Will reconnect the device\n", i, controller_msg_count); - evdev_close_device(&devices[i].dev.evdev); - devices[i].type = DEV_IN_TYPE_NONE; - continue; + controller_msg_count = dev_in_data->input_dev_decl->dev[i]->map.ev_input_map_fn(&coll, controller_msg, controller_msg_avail, dev_in_data->input_dev_decl->dev[i]->user_data); + } else if (devices[i].type == DEV_IN_TYPE_IIO) { + controller_msg_count = map_message_from_iio(&devices[i].dev.iio, controller_msg, controller_msg_avail); + if (controller_msg_count != 0) { + fprintf(stderr, "Error in performing operations for device %zd: %d -- Will reconnect to the device\n", i, controller_msg_count); + iio_close_device(&devices[i].dev.iio); + devices[i].type = DEV_IN_TYPE_NONE; + continue; + } + } else if (devices[i].type == DEV_IN_TYPE_HIDRAW) { + controller_msg_count = dev_in_data->input_dev_decl->dev[i]->map.hidraw_input_map_fn(dev_hidraw_get_fd(devices[i].dev.hidraw.hidrawdev), controller_msg, controller_msg_avail, dev_in_data->input_dev_decl->dev[i]->user_data); + if (controller_msg_count != 0) { + fprintf(stderr, "Error in performing operations for device %zd: %d -- Will reconnect to the device\n", i, controller_msg_count); + hidraw_close_device(&devices[i].dev.hidraw); + devices[i].type = DEV_IN_TYPE_NONE; + continue; + } } - controller_msg_count = devices[i].dev.evdev.callbacks.input_map_fn( - &dev_in_data->settings, - &coll, - &controller_msg[0], - controller_msg_avail, - devices[i].dev.evdev.user_data - ); - } else if (devices[i].type == DEV_IN_TYPE_IIO) { - controller_msg_count = map_message_from_iio( - &devices[i].dev.iio, - &controller_msg[0], - controller_msg_avail - ); - - if (controller_msg_count < 0) { - fprintf(stderr, "Error in reading iio buffer for device %zd: %d -- Will reconnect to the device\n", i, controller_msg_count); - iio_close_device(&devices[i].dev.iio); - devices[i].type = DEV_IN_TYPE_NONE; - continue; + // attempt to acquire more memory + if (controller_msg_count == -ENOMEM) { + printf("Map function reported not enough memory, allocating new one...\n"); + const size_t tmp_controller_msg_avail = controller_msg_avail * 2; + in_message_t *tmp_controller_msg = malloc(sizeof(in_message_t) * tmp_controller_msg_avail); + if (tmp_controller_msg == NULL) { + fprintf(stderr, "Could not allocate new memory -- will retry\n"); + } else { + printf("Allocated new memory to fill the buffer\n"); + free(controller_msg); + controller_msg = tmp_controller_msg; + controller_msg_avail = tmp_controller_msg_avail; + } } - } else if (devices[i].type == DEV_IN_TYPE_HIDRAW) { - controller_msg_count = devices[i].dev.hidraw.callbacks.map_callback( - &dev_in_data->settings, - fd, - &controller_msg[0], - controller_msg_avail, - devices[i].dev.hidraw.user_data - ); - - if (controller_msg_count < 0) { - fprintf(stderr, "Error in performing operations for device %zd: %d -- Will reconnect to the device\n", i, controller_msg_count); - hidraw_close_device(&devices[i].dev.hidraw); - devices[i].type = DEV_IN_TYPE_NONE; - continue; - } - } else if (devices[i].type == DEV_IN_TYPE_TIMER) { - uint64_t expirations; - ssize_t num_read = read(fd, &expirations, sizeof(uint64_t)); - if (num_read != sizeof(uint64_t)) { - fprintf(stderr, "Error in reading expirations from timer device %zd: %d -- Will reconnect to the device\n", i, controller_msg_count); - timer_close_device(&devices[i].dev.timer); - devices[i].type = DEV_IN_TYPE_NONE; - continue; - } - - controller_msg_count = devices[i].dev.timer.callbacks.map_fn( - &dev_in_data->settings, - fd, - expirations, - &controller_msg[0], - controller_msg_avail, - devices[i].dev.timer.user_data - ); - - if (controller_msg_count < 0) { - fprintf(stderr, "Error in timer device %zd: %d -- Will reconnect to the device\n", i, controller_msg_count); - timer_close_device(&devices[i].dev.timer); - devices[i].type = DEV_IN_TYPE_NONE; - continue; - } - - handle_timeout( - &dev_in_data->settings, - devices, - max_devices, - devices[i].dev.timer.name, - expirations - ); } // send messages (if any) @@ -728,22 +523,18 @@ void* dev_in_thread_func(void *ptr) { } if (dev_in_data->communication.type == ipc_client_socket) { - for (int msg_idx = 0; msg_idx < controller_msg_count; ++msg_idx) { - const int write_res = write(dev_in_data->communication.endpoint.socket.fd, (void*)&controller_msg[msg_idx], sizeof(in_message_t)); - if (write_res < 0) { - fprintf(stderr, "Error in writing input event messages: %d -- connection will be drop and retried\n", write_res); + const int write_res = write(dev_in_data->communication.endpoint.socket.fd, (void*)&controller_msg[0], sizeof(in_message_t) * controller_msg_count); + if (write_res < 0) { + fprintf(stderr, "Error in writing input event messages: %d -- connection will be drop and retried\n", write_res); - // in case of an error reschedule to socket for reconnection - close(dev_in_data->communication.endpoint.socket.fd); - dev_in_data->communication.endpoint.socket.fd = -1; - } + // in case of an error reschedule to socket for reconnection + close(dev_in_data->communication.endpoint.socket.fd); + dev_in_data->communication.endpoint.socket.fd = -1; } } else if (dev_in_data->communication.type == ipc_unix_pipe) { - for (int msg_idx = 0; msg_idx < controller_msg_count; ++msg_idx) { - const int write_res = write(dev_in_data->communication.endpoint.pipe.in_message_pipe_fd, (void*)&controller_msg[msg_idx], sizeof(in_message_t)); - if (write_res < 0) { - fprintf(stderr, "Error in writing input event messages: %d\n", write_res); - } + const int write_res = write(dev_in_data->communication.endpoint.pipe.in_message_pipe_fd, (void*)&controller_msg[0], sizeof(in_message_t) * controller_msg_count); + if (write_res < 0) { + fprintf(stderr, "Error in writing input event messages: %d\n", write_res); } } } @@ -779,16 +570,14 @@ void* dev_in_thread_func(void *ptr) { } else if (devices[i].type == DEV_IN_TYPE_HIDRAW) { hidraw_close_device(&devices[i].dev.hidraw); devices[i].type = DEV_IN_TYPE_NONE; - } else if (devices[i].type == DEV_IN_TYPE_TIMER) { - timer_close_device(&devices[i].dev.timer); - devices[i].type = DEV_IN_TYPE_NONE; } } + // TODO: free every fd free(devices); if (platform_init_res != 0) { - dev_in_data->input_dev_decl->deinit_fn(&dev_in_data->settings, &platform_data); + dev_in_data->input_dev_decl->deinit_fn(&platform_data); } return NULL; diff --git a/dev_in.h b/dev_in.h index 85aa114..1fd470f 100644 --- a/dev_in.h +++ b/dev_in.h @@ -3,9 +3,6 @@ #include "ipc.h" #include "message.h" #include "input_dev.h" -#include "settings.h" - -#define MAX_IN_MESSAGES 8 #define DEV_IN_FLAG_EXIT 0x00000001U @@ -20,8 +17,6 @@ typedef struct dev_in_data { ipc_t communication; - dev_in_settings_t settings; - volatile uint32_t flags; } dev_in_data_t; diff --git a/dev_out.c b/dev_out.c index e81afc0..458ceca 100644 --- a/dev_out.c +++ b/dev_out.c @@ -5,11 +5,8 @@ #include "message.h" #include "virt_ds4.h" #include "virt_ds5.h" -#include "virt_mouse.h" -#include "virt_kbd.h" static void handle_incoming_message_gamepad_action( - const dev_out_settings_t *const in_settings, const in_message_gamepad_action_t *const msg_payload, gamepad_status_t *const inout_gamepad ) { @@ -20,64 +17,25 @@ static void handle_incoming_message_gamepad_action( } } -static void handle_incoming_message_mouse_event( - const dev_out_settings_t *const in_settings, - const in_message_mouse_event_t *const msg_payload, - mouse_status_t *const inout_mouse -) { - if (msg_payload->type == MOUSE_ELEMENT_X) { - inout_mouse->x += msg_payload->value; - } else if (msg_payload->type == MOUSE_ELEMENT_Y) { - inout_mouse->y += msg_payload->value; - } else if (msg_payload->type == MOUSE_BTN_LEFT) { - inout_mouse->btn_left = msg_payload->value; - } else if (msg_payload->type == MOUSE_BTN_MIDDLE) { - inout_mouse->btn_middle = msg_payload->value; - } else if (msg_payload->type == MOUSE_BTN_RIGHT) { - inout_mouse->btn_right = msg_payload->value; - } -} - static void handle_incoming_message_gamepad_set( - const dev_out_settings_t *const in_settings, const in_message_gamepad_set_element_t *const msg_payload, gamepad_status_t *const inout_gamepad ) { switch (msg_payload->element) { case GAMEPAD_BTN_CROSS: { - if (!in_settings->nintendo_layout) { - inout_gamepad->cross = msg_payload->status.btn; - } else { - inout_gamepad->circle = msg_payload->status.btn; - } - + inout_gamepad->cross = msg_payload->status.btn; break; } case GAMEPAD_BTN_CIRCLE: { - if (in_settings->nintendo_layout) { - inout_gamepad->cross = msg_payload->status.btn; - } else { - inout_gamepad->circle = msg_payload->status.btn; - } - + inout_gamepad->circle = msg_payload->status.btn; break; } case GAMEPAD_BTN_SQUARE: { - if (in_settings->nintendo_layout) { - inout_gamepad->triangle = msg_payload->status.btn; - } else { - inout_gamepad->square = msg_payload->status.btn; - } - + inout_gamepad->square = msg_payload->status.btn; break; } case GAMEPAD_BTN_TRIANGLE: { - if (!in_settings->nintendo_layout) { - inout_gamepad->triangle = msg_payload->status.btn; - } else { - inout_gamepad->square = msg_payload->status.btn; - } - + inout_gamepad->triangle = msg_payload->status.btn; break; } case GAMEPAD_BTN_OPTION: { @@ -132,14 +90,6 @@ static void handle_incoming_message_gamepad_set( inout_gamepad->touchpad_press = msg_payload->status.btn; break; } - case GAMEPAD_BTN_JOIN_LEFT_ANALOG_AND_GYROSCOPE: { - inout_gamepad->join_left_analog_and_gyroscope = msg_payload->status.btn; - break; - } - case GAMEPAD_BTN_JOIN_RIGHT_ANALOG_AND_GYROSCOPE: { - inout_gamepad->join_right_analog_and_gyroscope = msg_payload->status.btn; - break; - } case GAMEPAD_LEFT_JOYSTICK_X: { inout_gamepad->joystick_positions[0][0] = msg_payload->status.joystick_pos; break; @@ -184,32 +134,6 @@ static void handle_incoming_message_gamepad_set( break; } - case GAMEPAD_GYROSCOPE: { - inout_gamepad->last_gyro_motion_timestamp_ns = msg_payload->status.gyro.sample_timestamp_ns; - inout_gamepad->raw_gyro[0] = in_settings->invert_x ? (int16_t)(-1) * msg_payload->status.gyro.x : msg_payload->status.gyro.x; - inout_gamepad->raw_gyro[1] = in_settings->swap_y_z ? msg_payload->status.gyro.z : msg_payload->status.gyro.y; - inout_gamepad->raw_gyro[2] = in_settings->swap_y_z ? msg_payload->status.gyro.y : msg_payload->status.gyro.z; - break; - } - case GAMEPAD_ACCELEROMETER: { - inout_gamepad->last_accel_motion_timestamp_ns = msg_payload->status.accel.sample_timestamp_ns; - inout_gamepad->raw_accel[0] = in_settings->invert_x ? (int16_t)(-1) * msg_payload->status.accel.x : msg_payload->status.accel.x; - inout_gamepad->raw_accel[1] = in_settings->swap_y_z ? msg_payload->status.accel.z : msg_payload->status.accel.y; - inout_gamepad->raw_accel[2] = in_settings->swap_y_z ? msg_payload->status.accel.y : msg_payload->status.accel.z; - break; - } - case GAMEPAD_TOUCHPAD_TOUCH_ACTIVE: { - inout_gamepad->touchpad_touch_num = msg_payload->status.touchpad_active.status; - break; - } - case GAMEPAD_TOUCHPAD_X: { - inout_gamepad->touchpad_x = msg_payload->status.touchpad_x.value; - break; - } - case GAMEPAD_TOUCHPAD_Y: { - inout_gamepad->touchpad_y = msg_payload->status.touchpad_y.value; - break; - } default: { fprintf(stderr, "Unknown gamepad element: %d\n", msg_payload->element); break; @@ -217,174 +141,24 @@ static void handle_incoming_message_gamepad_set( } } -static void handle_incoming_message_keyboard_set( - const dev_out_settings_t *const in_settings, - const in_message_keyboard_set_element_t *const msg_payload, - keyboard_status_t *const inout_kbd -) { - switch (msg_payload->type) { - case KEYBOARD_KEY_Q: - inout_kbd->q = msg_payload->value; - break; - case KEYBOARD_KEY_W: - inout_kbd->w = msg_payload->value; - break; - case KEYBOARD_KEY_E: - inout_kbd->e = msg_payload->value; - break; - case KEYBOARD_KEY_R: - inout_kbd->r = msg_payload->value; - break; - case KEYBOARD_KEY_T: - inout_kbd->t = msg_payload->value; - break; - case KEYBOARD_KEY_Y: - inout_kbd->y = msg_payload->value; - break; - case KEYBOARD_KEY_U: - inout_kbd->u = msg_payload->value; - break; - case KEYBOARD_KEY_I: - inout_kbd->i = msg_payload->value; - break; - case KEYBOARD_KEY_O: - inout_kbd->o = msg_payload->value; - break; - case KEYBOARD_KEY_P: - inout_kbd->p = msg_payload->value; - break; - case KEYBOARD_KEY_A: - inout_kbd->a = msg_payload->value; - break; - case KEYBOARD_KEY_S: - inout_kbd->s = msg_payload->value; - break; - case KEYBOARD_KEY_D: - inout_kbd->d = msg_payload->value; - break; - case KEYBOARD_KEY_F: - inout_kbd->f = msg_payload->value; - break; - case KEYBOARD_KEY_G: - inout_kbd->g = msg_payload->value; - break; - case KEYBOARD_KEY_H: - inout_kbd->h = msg_payload->value; - break; - case KEYBOARD_KEY_J: - inout_kbd->j = msg_payload->value; - break; - case KEYBOARD_KEY_K: - inout_kbd->k = msg_payload->value; - break; - case KEYBOARD_KEY_L: - inout_kbd->l = msg_payload->value; - break; - case KEYBOARD_KEY_Z: - inout_kbd->z = msg_payload->value; - break; - case KEYBOARD_KEY_X: - inout_kbd->x = msg_payload->value; - break; - case KEYBOARD_KEY_C: - inout_kbd->c = msg_payload->value; - break; - case KEYBOARD_KEY_V: - inout_kbd->v = msg_payload->value; - break; - case KEYBOARD_KEY_B: - inout_kbd->b = msg_payload->value; - break; - case KEYBOARD_KEY_N: - inout_kbd->n = msg_payload->value; - break; - case KEYBOARD_KEY_M: - inout_kbd->m = msg_payload->value; - break; - case KEYBOARD_KEY_UP: - inout_kbd->up = msg_payload->value; - break; - case KEYBOARD_KEY_DOWN: - inout_kbd->down = msg_payload->value; - break; - case KEYBOARD_KEY_LEFT: - inout_kbd->left = msg_payload->value; - break; - case KEYBOARD_KEY_RIGHT: - inout_kbd->right = msg_payload->value; - break; - case KEYBOARD_KEY_NUM_0: - inout_kbd->num_0 = msg_payload->value; - break; - case KEYBOARD_KEY_NUM_1: - inout_kbd->num_1 = msg_payload->value; - break; - case KEYBOARD_KEY_NUM_2: - inout_kbd->num_2 = msg_payload->value; - break; - case KEYBOARD_KEY_NUM_3: - inout_kbd->num_3 = msg_payload->value; - break; - case KEYBOARD_KEY_NUM_4: - inout_kbd->num_4 = msg_payload->value; - break; - case KEYBOARD_KEY_NUM_5: - inout_kbd->num_5 = msg_payload->value; - break; - case KEYBOARD_KEY_NUM_6: - inout_kbd->num_6 = msg_payload->value; - break; - case KEYBOARD_KEY_NUM_7: - inout_kbd->num_7 = msg_payload->value; - break; - case KEYBOARD_KEY_NUM_8: - inout_kbd->num_8 = msg_payload->value; - break; - case KEYBOARD_KEY_NUM_9: - inout_kbd->num_9 = msg_payload->value; - break; - case KEYBOARD_KEY_LCRTL: - inout_kbd->lctrl = msg_payload->value; - break; - default: - fprintf(stderr, "key not implemented\n"); - } -} - static void handle_incoming_message( - const dev_out_settings_t *const in_settings, const in_message_t *const msg, devices_status_t *const dev_stats ) { if (msg->type == GAMEPAD_SET_ELEMENT) { - handle_incoming_message_gamepad_set( - in_settings, - &msg->data.gamepad_set, - &dev_stats->gamepad - ); + handle_incoming_message_gamepad_set(&msg->data.gamepad_set, &dev_stats->gamepad); } else if (msg->type == GAMEPAD_ACTION) { - handle_incoming_message_gamepad_action( - in_settings, - &msg->data.action, - &dev_stats->gamepad - ); - } else if (msg->type == MOUSE_EVENT) { - handle_incoming_message_mouse_event( - in_settings, - &msg->data.mouse_event, - &dev_stats->mouse - ); - } else if (msg->type == KEYBOARD_SET_ELEMENT) { - handle_incoming_message_keyboard_set( - in_settings, - &msg->data.kbd_set, - &dev_stats->kbd - ); + handle_incoming_message_gamepad_action(&msg->data.action, &dev_stats->gamepad); } } -int64_t get_timediff_nsec(const struct timespec *const start, const struct timespec *const end) { - return (end->tv_sec - start->tv_sec) * 1000000000LL + (end->tv_nsec - start->tv_nsec); +int64_t get_timediff_usec(const struct timeval *const past, const struct timeval *const now) { + struct timeval tdiff; + timersub(now, past, &tdiff); + + //const int64_t sgn = ((now->tv_sec > past->tv_sec) || ((now->tv_sec == past->tv_sec) && (now->tv_usec > past->tv_usec))) ? -1 : +1; + + return (int64_t)(tdiff.tv_sec) * (int64_t)1000000 + (int64_t)(tdiff.tv_usec); } void *dev_out_thread_func(void *ptr) { @@ -393,96 +167,41 @@ void *dev_out_thread_func(void *ptr) { // Initialize device devices_status_init(&dev_out_data->dev_stats); - dev_out_gamepad_device_t current_gamepad = GAMEPAD_DUALSENSE; - - switch (dev_out_data->settings.default_gamepad) { - case 1: - current_gamepad = GAMEPAD_DUALSENSE; - break; - case 2: - current_gamepad = GAMEPAD_DUALSHOCK; - break; - - default: - current_gamepad = GAMEPAD_DUALSENSE; - break; - } - - int current_gamepad_fd = -1; - int current_keyboard_fd = -1; - int current_mouse_fd = -1; + dev_out_gamepad_device_t current_gamepad = dev_out_data->gamepad; union { virt_dualshock_t ds4; virt_dualsense_t ds5; } controller_data; - virt_mouse_t mouse_data; - const int mouse_init_res = virt_mouse_init(&mouse_data); - if (mouse_init_res < 0) { - fprintf(stderr, "Unable to initialize virtual mouse -- will continue regardless\n"); - } else { - current_mouse_fd = virt_mouse_get_fd(&mouse_data); - printf("Mouse initialized: fd=%d\n", current_mouse_fd); - } - - virt_kbd_t keyboard_data; - const int kbd_init_res = virt_kbd_init(&keyboard_data); - if (kbd_init_res < 0) { - fprintf(stderr, "Unable to initialize virtual keyboard -- will continue regardless\n"); - } else { - current_keyboard_fd = virt_kbd_get_fd(&keyboard_data); - printf("Keyboard initialized: fd=%d\n", current_keyboard_fd); - } - - bool high_hz_avail = false; - const char *const avail_freq = inline_read_file("/sys/bus/iio/devices/iio:device0/", "name"); - if ((avail_freq != NULL) && (strstr(avail_freq, "1600.0") != NULL)) { - printf("High iio sampling frequency available: 1600.0 Hz"); - high_hz_avail = true; - } - - const int64_t kbd_report_timing_us = high_hz_avail ? 1125 : 2025; - const int64_t mouse_report_timing_us = high_hz_avail ? 950 : 1650; - const int64_t gamepad_report_timing_us = high_hz_avail ? 1250 : 2500; + int current_gamepad_fd = -1; + //int current_keyboard_fd = -1; + //int current_mouse_fd = -1; if (current_gamepad == GAMEPAD_DUALSENSE) { - const int ds5_init_res = virt_dualsense_init( - &controller_data.ds5, - dev_out_data->settings.controller_bluetooth, - dev_out_data->settings.dualsense_edge, - dev_out_data->settings.gyro_to_analog_activation_treshold, - dev_out_data->settings.gyro_to_analog_mapping - ); - + const int ds5_init_res = virt_dualsense_init(&controller_data.ds5); if (ds5_init_res != 0) { fprintf(stderr, "Unable to initialize the DualSense device: %d\n", ds5_init_res); } else { current_gamepad_fd = virt_dualsense_get_fd(&controller_data.ds5); - printf("DualSense initialized: fd=%d, bluetooth=%s\n", current_gamepad_fd, dev_out_data->settings.controller_bluetooth ? "true" : "false"); + printf("DualSense initialized: fd=%d\n", current_gamepad_fd); } } else if (current_gamepad == GAMEPAD_DUALSHOCK) { - const int ds4_init_res = virt_dualshock_init( - &controller_data.ds4, - dev_out_data->settings.controller_bluetooth, - dev_out_data->settings.gyro_to_analog_activation_treshold, - dev_out_data->settings.gyro_to_analog_mapping - ); - + const int ds4_init_res = virt_dualshock_init(&controller_data.ds4); if (ds4_init_res != 0) { fprintf(stderr, "Unable to initialize the DualShock device: %d\n", ds4_init_res); } else { current_gamepad_fd = virt_dualshock_get_fd(&controller_data.ds4); - printf("DualShock initialized: fd=%d, bluetooth=%s\n", current_gamepad_fd, dev_out_data->settings.controller_bluetooth ? "true" : "false"); + printf("DualShock initialized: fd=%d\n", current_gamepad_fd); } } - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); + struct timeval now = {0}; + gettimeofday(&now, NULL); - struct timespec gamepad_last_hid_report_sent = now; - struct timespec mouse_last_hid_report_sent = now; - struct timespec keyboard_last_hid_report_sent = now; + struct timeval gamepad_last_hid_report_sent = now; + //struct timeval mouse_last_hid_report_sent = now; + //struct timeval keyboard_last_hid_report_sent = now; uint8_t tmp_buf[256]; @@ -493,13 +212,9 @@ void *dev_out_thread_func(void *ptr) { break; } - clock_gettime(CLOCK_MONOTONIC, &now); - - const int64_t gamepad_time_diff_usecs = get_timediff_nsec(&gamepad_last_hid_report_sent, &now) / 1000; - const int64_t mouse_time_diff_usecs = get_timediff_nsec(&mouse_last_hid_report_sent, &now) / 1000; - const int64_t kbd_time_diff_usecs = get_timediff_nsec(&keyboard_last_hid_report_sent, &now) / 1000; - - if ((current_gamepad_fd > 0) && (gamepad_time_diff_usecs >= gamepad_report_timing_us)) { + gettimeofday(&now, NULL); + 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) { @@ -509,234 +224,159 @@ void *dev_out_thread_func(void *ptr) { virt_dualshock_compose(&controller_data.ds4, &dev_out_data->dev_stats.gamepad, tmp_buf); virt_dualshock_send(&controller_data.ds4, tmp_buf); } - } - - if ((current_mouse_fd > 0) && (mouse_time_diff_usecs >= mouse_report_timing_us)) { - mouse_last_hid_report_sent = now; + } else { + FD_ZERO(&read_fds); - virt_mouse_send(&mouse_data, &dev_out_data->dev_stats.mouse, NULL); - - // reset mouse movements now - dev_out_data->dev_stats.mouse.x = 0; - dev_out_data->dev_stats.mouse.y = 0; - } - - if ((current_keyboard_fd > 0) && (kbd_time_diff_usecs >= kbd_report_timing_us)) { - keyboard_last_hid_report_sent = now; - - virt_kbd_send(&keyboard_data, &dev_out_data->dev_stats.kbd, NULL); - } - - - // once here no output device needs to send out its report - FD_ZERO(&read_fds); - - if (dev_out_data->communication.type == ipc_unix_pipe) { - FD_SET(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, &read_fds); - } else if (dev_out_data->communication.type == ipc_server_sockets) { - if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) { - for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) { - const int fd = dev_out_data->communication.endpoint.ssocket.clients[i]; - if (fd > 0) { - FD_SET(fd, &read_fds); - } - } - - pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex); - } - } - - if (current_mouse_fd > 0) { - FD_SET(current_mouse_fd, &read_fds); - } - - if (current_keyboard_fd > 0) { - FD_SET(current_keyboard_fd, &read_fds); - } - - if (current_gamepad_fd > 0) { - FD_SET(current_gamepad_fd, &read_fds); - } - - const int64_t timeout_gamepad_time_diff_usecs = (current_gamepad_fd > 0) ? gamepad_report_timing_us - gamepad_time_diff_usecs : 5000; - const int64_t timeout_mouse_time_diff_usecs = (current_mouse_fd > 0) ? mouse_report_timing_us - mouse_time_diff_usecs : 5000; - const int64_t timeout_kbd_time_diff_usecs = (current_keyboard_fd > 0) ? kbd_report_timing_us - kbd_time_diff_usecs : 5000; - - int64_t next_timing_out_device_diff_usecs = 5000; - - if ((timeout_kbd_time_diff_usecs > 0) && (timeout_kbd_time_diff_usecs < next_timing_out_device_diff_usecs)) { - next_timing_out_device_diff_usecs = timeout_kbd_time_diff_usecs; - } - - if ((timeout_mouse_time_diff_usecs > 0) && (timeout_mouse_time_diff_usecs < next_timing_out_device_diff_usecs)) { - next_timing_out_device_diff_usecs = timeout_mouse_time_diff_usecs; - } - - if ((timeout_gamepad_time_diff_usecs > 0) && (timeout_gamepad_time_diff_usecs < next_timing_out_device_diff_usecs)) { - next_timing_out_device_diff_usecs = timeout_gamepad_time_diff_usecs; - } - - // 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)next_timing_out_device_diff_usecs / (__time_t)1000000, - .tv_usec = (__suseconds_t)next_timing_out_device_diff_usecs % (__suseconds_t)1000000, - }; - - int ready_fds = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); - gamepad_status_qam_quirk_ext_time(&dev_out_data->dev_stats.gamepad); - - if (ready_fds == -1) { - const int err = errno; - fprintf(stderr, "Error reading events for output devices: %d\n", err); - usleep(1000); - continue; - } else if (ready_fds == 0) { - // timeout: do nothing but continue. next iteration will take care - continue; - } - - if ((current_gamepad_fd > 0) && (FD_ISSET(current_gamepad_fd, &read_fds))) { - const uint64_t prev_leds_events_count = dev_out_data->dev_stats.gamepad.leds_events_count; - const uint64_t prev_motors_events_count = dev_out_data->dev_stats.gamepad.rumble_events_count; - - out_message_t out_msgs[4]; - size_t out_msgs_count = 0; - if (current_gamepad == GAMEPAD_DUALSENSE) { - virt_dualsense_event(&controller_data.ds5, &dev_out_data->dev_stats.gamepad); - } else if (current_gamepad == GAMEPAD_DUALSHOCK) { - virt_dualshock_event(&controller_data.ds4, &dev_out_data->dev_stats.gamepad); - } - - const uint64_t current_leds_events_count = dev_out_data->dev_stats.gamepad.leds_events_count; - const uint64_t current_motors_events_count = dev_out_data->dev_stats.gamepad.rumble_events_count; - - if (current_leds_events_count != prev_leds_events_count) { - const out_message_t msg = { - .type = OUT_MSG_TYPE_LEDS, - .data = { - .leds = { - .r = dev_out_data->dev_stats.gamepad.leds_colors[0], - .g = dev_out_data->dev_stats.gamepad.leds_colors[1], - .b = dev_out_data->dev_stats.gamepad.leds_colors[2], - } - } - }; - - if (dev_out_data->settings.gamepad_leds_control) { - out_msgs[out_msgs_count++] = msg; - } - } - - if (current_motors_events_count != prev_motors_events_count) { - const out_message_t msg = { - .type = OUT_MSG_TYPE_RUMBLE, - .data = { - .rumble = { - .motors_left = dev_out_data->dev_stats.gamepad.motors_intensity[0], - .motors_right = dev_out_data->dev_stats.gamepad.motors_intensity[1], - } - } - }; - - if (dev_out_data->settings.gamepad_rumble_control) { - out_msgs[out_msgs_count++] = msg; - } - } - - // send out game-generated events to sockets if (dev_out_data->communication.type == ipc_unix_pipe) { - for (int msg_idx = 0; msg_idx < out_msgs_count; ++msg_idx) { - const int write_res = write(dev_out_data->communication.endpoint.pipe.out_message_pipe_fd, (void*)&out_msgs[msg_idx], sizeof(out_message_t)); - if (write_res != sizeof(out_message_t)) { - fprintf(stderr, "Error in writing out_message to out_message_pipe: %d\n", write_res); - } - } + FD_SET(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, &read_fds); } else if (dev_out_data->communication.type == ipc_server_sockets) { if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) { for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) { - if (dev_out_data->communication.endpoint.ssocket.clients[i] > 0) { - for (int msg_idx = 0; msg_idx < out_msgs_count; ++msg_idx) { - const int write_res = write(dev_out_data->communication.endpoint.ssocket.clients[i], (void*)&out_msgs[msg_idx], sizeof(out_message_t)); - if (write_res != sizeof(out_message_t)) { + const int fd = dev_out_data->communication.endpoint.ssocket.clients[i]; + if (fd > 0) { + FD_SET(fd, &read_fds); + } + } + + pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex); + } + } + + // TODO: FD_SET(current_mouse_fd, &read_fds); + // TODO: FD_SET(current_keyboard_fd, &read_fds); + FD_SET(current_gamepad_fd, &read_fds); + + // 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)gamepad_time_diff_usecs / (__time_t)1000000, + .tv_usec = (__suseconds_t)gamepad_time_diff_usecs % (__suseconds_t)1000000, + }; + + int ready_fds = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); + gamepad_status_qam_quirk_ext_time(&dev_out_data->dev_stats.gamepad, &now); + + if (ready_fds == -1) { + const int err = errno; + fprintf(stderr, "Error reading events for output devices: %d\n", err); + continue; + } else if (ready_fds == 0) { + // timeout: do nothing but continue. next iteration will take care + continue; + } + + + if (FD_ISSET(current_gamepad_fd, &read_fds)) { + const uint64_t prev_leds_events_count = dev_out_data->dev_stats.gamepad.leds_events_count; + const uint64_t prev_motors_events_count = dev_out_data->dev_stats.gamepad.rumble_events_count; + + out_message_t out_msgs[4]; + size_t out_msgs_count = 0; + if (current_gamepad == GAMEPAD_DUALSENSE) { + virt_dualsense_event(&controller_data.ds5, &dev_out_data->dev_stats.gamepad); + } else if (current_gamepad == GAMEPAD_DUALSHOCK) { + virt_dualshock_event(&controller_data.ds4, &dev_out_data->dev_stats.gamepad); + } + + const uint64_t current_leds_events_count = dev_out_data->dev_stats.gamepad.leds_events_count; + const uint64_t current_motors_events_count = dev_out_data->dev_stats.gamepad.rumble_events_count; + + if (current_leds_events_count != prev_leds_events_count) { + const out_message_t msg = { + .type = OUT_MSG_TYPE_LEDS, + .data = { + .leds = { + .r = dev_out_data->dev_stats.gamepad.leds_colors[0], + .g = dev_out_data->dev_stats.gamepad.leds_colors[1], + .b = dev_out_data->dev_stats.gamepad.leds_colors[2], + } + } + }; + + out_msgs[out_msgs_count++] = msg; + } + + if (current_motors_events_count != prev_motors_events_count) { + const out_message_t msg = { + .type = OUT_MSG_TYPE_RUMBLE, + .data = { + .rumble = { + .motors_left = dev_out_data->dev_stats.gamepad.motors_intensity[0], + .motors_right = dev_out_data->dev_stats.gamepad.motors_intensity[1], + } + } + }; + + out_msgs[out_msgs_count++] = msg; + } + + // send out game-generated events to sockets + int fd = -1; + const size_t bytes_to_send = sizeof(out_message_t) * out_msgs_count; + + if (dev_out_data->communication.type == ipc_unix_pipe) { + const int write_res = write(dev_out_data->communication.endpoint.pipe.out_message_pipe_fd, (void*)&out_msgs, bytes_to_send); + if (write_res != bytes_to_send) { + fprintf(stderr, "Error in writing out_message to out_message_pipe: %d\n", write_res); + } + } else if (dev_out_data->communication.type == ipc_server_sockets) { + if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) { + for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) { + if (dev_out_data->communication.endpoint.ssocket.clients[i] > 0) { + const int write_res = write(dev_out_data->communication.endpoint.ssocket.clients[i], (void*)&out_msgs, bytes_to_send); + if (write_res != bytes_to_send) { fprintf(stderr, "Error in writing out_message to socket number %d: %d\n", i, write_res); close(dev_out_data->communication.endpoint.ssocket.clients[i]); dev_out_data->communication.endpoint.ssocket.clients[i] = -1; } } } - } + pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex); + } + } + } + + // read and handle incoming data: this data is packed into in_message_t + if (dev_out_data->communication.type == ipc_unix_pipe) { + if (FD_ISSET(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, &read_fds)) { + in_message_t incoming_message; + const size_t in_message_pipe_read_res = read(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, (void*)&incoming_message, sizeof(in_message_t)); + if (in_message_pipe_read_res == sizeof(in_message_t)) { + handle_incoming_message(&incoming_message, &dev_out_data->dev_stats); + } else { + fprintf(stderr, "Error reading from in_message_pipe_fd: got %zu bytes, expected %zu butes\n", in_message_pipe_read_res, sizeof(in_message_t)); + } + } + } else if (dev_out_data->communication.type == ipc_server_sockets) { + if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) { + for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) { + const int fd = dev_out_data->communication.endpoint.ssocket.clients[i]; + if ((fd > 0) && (FD_ISSET(fd, &read_fds))) { + in_message_t incoming_message; + const size_t in_message_pipe_read_res = read(fd, (void*)&incoming_message, sizeof(in_message_t)); + if (in_message_pipe_read_res == sizeof(in_message_t)) { + handle_incoming_message(&incoming_message, &dev_out_data->dev_stats); + } else { + fprintf(stderr, "Error reading from socket number %d: got %zu bytes, expected %zu butes\n", i, in_message_pipe_read_res, sizeof(in_message_t)); + close(dev_out_data->communication.endpoint.ssocket.clients[i]); + dev_out_data->communication.endpoint.ssocket.clients[i] = -1; + } + } + } + pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex); } } - } - if ((current_keyboard_fd > 0) && (FD_ISSET(current_keyboard_fd, &read_fds))) { - // TODO: read keyboard events - } - - if ((current_mouse_fd > 0) && (FD_ISSET(current_mouse_fd, &read_fds))) { - // TODO: read mouse events - } - - // read and handle incoming data: this data is packed into in_message_t - if (dev_out_data->communication.type == ipc_unix_pipe) { - if (FD_ISSET(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, &read_fds)) { - in_message_t incoming_message; - const size_t in_message_pipe_read_res = read(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, (void*)&incoming_message, sizeof(in_message_t)); - if (in_message_pipe_read_res == sizeof(in_message_t)) { - handle_incoming_message( - &dev_out_data->settings, - &incoming_message, - &dev_out_data->dev_stats - ); - } else { - fprintf(stderr, "Error reading from in_message_pipe_fd: got %zu bytes, expected %zu bytes\n", in_message_pipe_read_res, sizeof(in_message_t)); - } - } - } else if (dev_out_data->communication.type == ipc_server_sockets) { - if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) { - for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) { - const int fd = dev_out_data->communication.endpoint.ssocket.clients[i]; - if ((fd > 0) && (FD_ISSET(fd, &read_fds))) { - in_message_t incoming_message; - const size_t in_message_pipe_read_res = read(fd, (void*)&incoming_message, sizeof(in_message_t)); - if (in_message_pipe_read_res == sizeof(in_message_t)) { - handle_incoming_message( - &dev_out_data->settings, - &incoming_message, - &dev_out_data->dev_stats - ); - } else { - fprintf(stderr, "Error reading from socket number %d: got %zu bytes, expected %zu bytes\n", i, in_message_pipe_read_res, sizeof(in_message_t)); - close(dev_out_data->communication.endpoint.ssocket.clients[i]); - dev_out_data->communication.endpoint.ssocket.clients[i] = -1; - } - } - } - pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex); - } } } - // close the gamepad output device - if (current_gamepad_fd > 0) { - if (current_gamepad == GAMEPAD_DUALSENSE) { - virt_dualsense_close(&controller_data.ds5); - } else if (current_gamepad == GAMEPAD_DUALSHOCK) { - virt_dualshock_close(&controller_data.ds4); - } - } - - // close the mouse device - if (current_mouse_fd > 0) { - virt_mouse_close(&mouse_data); - } - - // close the keyboard device - if (current_keyboard_fd > 0) { - virt_kbd_close(&keyboard_data); + // close the output device + if (current_gamepad == GAMEPAD_DUALSENSE) { + virt_dualsense_close(&controller_data.ds5); + } else if (current_gamepad == GAMEPAD_DUALSHOCK) { + virt_dualshock_close(&controller_data.ds4); } // end communication diff --git a/dev_out.h b/dev_out.h index f804e44..a0c249c 100644 --- a/dev_out.h +++ b/dev_out.h @@ -3,7 +3,6 @@ #include "ipc.h" #include "message.h" #include "devices_status.h" -#include "settings.h" #define DEV_OUT_FLAG_EXIT 0x00000001U @@ -17,9 +16,9 @@ typedef struct dev_out_data { ipc_t communication; - devices_status_t dev_stats; + dev_out_gamepad_device_t gamepad; - dev_out_settings_t settings; + devices_status_t dev_stats; volatile uint32_t flags; diff --git a/dev_timer.c b/dev_timer.c deleted file mode 100644 index bcbd23a..0000000 --- a/dev_timer.c +++ /dev/null @@ -1,67 +0,0 @@ -#include "dev_timer.h" - -int dev_timer_open( - const timer_filters_t *const in_filters, - dev_timer_t **const out_dev -) { - int res = -ENODEV; - - *out_dev = malloc(sizeof(dev_timer_t)); - if (*out_dev == NULL) { - res = -ENOMEM; - goto dev_timer_open_err; - } - - memset(*out_dev, 0, sizeof(dev_timer_t)); - - const int fd = timerfd_create(CLOCK_MONOTONIC, 0); - if (fd < 0) { - res = errno < 0 ? errno : -1 * errno; - if (res == 0) { - res = fd; - } - goto dev_timer_open_err; - } - - (*out_dev)->fd = fd; - if (in_filters->ticktime_ms != 0) { - (*out_dev)->timer_spec.it_value.tv_sec = in_filters->ticktime_ms / (__time_t)1000; - (*out_dev)->timer_spec.it_value.tv_nsec = (in_filters->ticktime_ms % (__syscall_slong_t)1000) * (__syscall_slong_t)1000000; - (*out_dev)->timer_spec.it_interval.tv_sec = in_filters->ticktime_ms / (__time_t)1000; - (*out_dev)->timer_spec.it_interval.tv_nsec = (in_filters->ticktime_ms % (__syscall_slong_t)1000) * (__syscall_slong_t)1000000; - } else { - (*out_dev)->timer_spec.it_value.tv_sec = 0; - (*out_dev)->timer_spec.it_value.tv_nsec = in_filters->ticktime_ns; - (*out_dev)->timer_spec.it_interval.tv_sec = 0; - (*out_dev)->timer_spec.it_interval.tv_nsec = in_filters->ticktime_ns; - } - - if (timerfd_settime((*out_dev)->fd, 0, &(*out_dev)->timer_spec, NULL) < 0) { - res = errno < 0 ? errno : -1 * errno; - if (res == 0) { - res = -EIO; - } - goto dev_timer_open_err; - } - - res = 0; - -dev_timer_open_err: - if (res != 0) { - if (fd > 0) { - close(fd); - } - - free(*out_dev); - } - - return res; -} - -void dev_timer_close(dev_timer_t *const inout_dev) { - close(inout_dev->fd); -} - -int dev_timer_get_fd(const dev_timer_t *const in_dev) { - return in_dev->fd; -} diff --git a/dev_timer.h b/dev_timer.h deleted file mode 100644 index 41c6ba5..0000000 --- a/dev_timer.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "input_dev.h" - -typedef struct dev_timer { - struct itimerspec timer_spec; - - int fd; -} dev_timer_t; - -int dev_timer_open( - const timer_filters_t *const in_filters, - dev_timer_t **const out_dev -); - -void dev_timer_close(dev_timer_t *const inout_dev); - -int dev_timer_get_fd(const dev_timer_t *const in_dev); diff --git a/devices_status.c b/devices_status.c index ef12fba..bd67963 100644 --- a/devices_status.c +++ b/devices_status.c @@ -1,63 +1,7 @@ #include "devices_status.h" -#include void kbd_status_init(keyboard_status_t *const stats) { stats->connected = true; - - stats->q = 0; - stats->w = 0; - stats->e = 0; - stats->r = 0; - stats->t = 0; - stats->y = 0; - stats->u = 0; - stats->i = 0; - stats->o = 0; - stats->p = 0; - stats->a = 0; - stats->s = 0; - stats->d = 0; - stats->f = 0; - stats->g = 0; - stats->h = 0; - stats->j = 0; - stats->k = 0; - stats->l = 0; - stats->z = 0; - stats->x = 0; - stats->c = 0; - stats->v = 0; - stats->b = 0; - stats->n = 0; - stats->m = 0; - - stats->num_1 = 0; - stats->num_2 = 0; - stats->num_3 = 0; - stats->num_4 = 0; - stats->num_5 = 0; - stats->num_6 = 0; - stats->num_7 = 0; - stats->num_8 = 0; - stats->num_9 = 0; - stats->num_0 = 0; - - stats->up = 0; - stats->down = 0; - stats->left = 0; - stats->right = 0; - - stats->lctrl = 0; -} - -void mouse_status_init(mouse_status_t *const stats) { - stats->connected = true; - - stats->x = 0; - stats->y = 0; - stats->btn_left = 0; - stats->btn_middle = 0; - stats->btn_right = 0; } void gamepad_status_init(gamepad_status_t *const stats) { @@ -95,19 +39,13 @@ void gamepad_status_init(gamepad_status_t *const stats) { stats->leds_colors[0] = 0; stats->leds_colors[1] = 0; stats->leds_colors[2] = 0; - stats->touchpad_touch_num = -1; - stats->touchpad_x = 0; - stats->touchpad_y = 0; - stats->join_left_analog_and_gyroscope = 0; - stats->join_right_analog_and_gyroscope = 0; stats->flags = 0; } void devices_status_init(devices_status_t *const stats) { - pthread_mutex_init(&stats->mutex, NULL); gamepad_status_init(&stats->gamepad); kbd_status_init(&stats->kbd); - mouse_status_init(&stats->mouse); + // TODO: mouse init } void gamepad_status_qam_quirk(gamepad_status_t *const gamepad_stats) { @@ -168,15 +106,13 @@ void gamepad_status_qam_quirk(gamepad_status_t *const gamepad_stats) { } } -void gamepad_status_qam_quirk_ext_time(gamepad_status_t *const gamepad_stats) { +void gamepad_status_qam_quirk_ext_time(gamepad_status_t *const gamepad_stats, struct timeval *now) { static struct timeval press_time; if (gamepad_stats->flags & GAMEPAD_STATUS_FLAGS_PRESS_AND_REALEASE_CENTER) { - struct timeval now; - gettimeofday(&now, NULL); // Calculate elapsed time in milliseconds - const int64_t elapsed_time = (now.tv_sec - press_time.tv_sec) * 1000 + - (now.tv_usec - press_time.tv_usec) / 1000; + const int64_t elapsed_time = (now->tv_sec - press_time.tv_sec) * 1000 + + (now->tv_usec - press_time.tv_usec) / 1000; if (gamepad_stats->center) { // If the center button is pressed and at least X ms have passed diff --git a/devices_status.h b/devices_status.h index 6c55136..8d39b26 100644 --- a/devices_status.h +++ b/devices_status.h @@ -46,12 +46,8 @@ typedef struct gamepad_status { uint8_t touchpad_press; - int16_t touchpad_touch_num; // touchpad is inactive when this is -1 - int16_t touchpad_x; // 0 to 1920 - int16_t touchpad_y; // 0 to 1080 - - int64_t last_gyro_motion_timestamp_ns; - int64_t last_accel_motion_timestamp_ns; + struct timeval last_gyro_motion_time; + struct timeval last_accel_motion_time; double gyro[3]; // | x, y, z| right-hand-rules -- in rad/s double accel[3]; // | x, y, z| positive: right, up, towards player -- in m/s^2 @@ -65,39 +61,14 @@ typedef struct gamepad_status { uint64_t leds_events_count; uint8_t leds_colors[3]; // r | g | b - uint8_t join_left_analog_and_gyroscope; - uint8_t join_right_analog_and_gyroscope; - volatile uint32_t flags; } gamepad_status_t; typedef struct keyboard_status { bool connected; - - uint8_t q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m; - - uint8_t num_1, num_2, num_3, num_4, num_5, num_6, num_7, num_8, num_9, num_0; - - uint8_t up, down, left, right; - - uint8_t lctrl; - } keyboard_status_t; - -typedef struct mouse_status { - bool connected; - - int32_t x; - int32_t y; - - uint8_t btn_left; - uint8_t btn_middle; - uint8_t btn_right; - -} mouse_status_t; - typedef struct devices_status { // this mutex MUST be grabbed when reading and/or writing below properties pthread_mutex_t mutex; @@ -106,12 +77,8 @@ typedef struct devices_status { keyboard_status_t kbd; - mouse_status_t mouse; - } devices_status_t; -void mouse_status_init(mouse_status_t *const stats); - void kbd_status_init(keyboard_status_t *const stats); void gamepad_status_init(gamepad_status_t *const stats); @@ -120,4 +87,4 @@ void devices_status_init(devices_status_t *const stats); void gamepad_status_qam_quirk(gamepad_status_t *const gamepad_stats); -void gamepad_status_qam_quirk_ext_time(gamepad_status_t *const gamepad_stats); +void gamepad_status_qam_quirk_ext_time(gamepad_status_t *const gamepad_stats, struct timeval *now); diff --git a/input_dev.h b/input_dev.h index 39d7e62..edbbde0 100644 --- a/input_dev.h +++ b/input_dev.h @@ -1,7 +1,6 @@ #pragma once #include "message.h" -#include "settings.h" #undef INCLUDE_INPUT_DEBUG #undef IGNORE_INPUT_SCAN @@ -18,26 +17,13 @@ typedef struct evdev_collected { * A function with this signature grapbs input_event data and sends to the pipe messages * constructed from that data. */ -typedef int (*ev_map)( - const dev_in_settings_t *const conf, - const evdev_collected_t *const e, - in_message_t *const messages, - size_t messages_len, - void* user_data -); -typedef void (*ev_timer)( - const dev_in_settings_t *const conf, - struct libevdev* evdev, - const char* const timer_name, - uint64_t expired, - void* user_data -); +typedef int (*ev_map)(const evdev_collected_t *const e, in_message_t *const messages, size_t messages_len, void* user_data); +typedef int (*hidraw_map)(int hidraw_fd, in_message_t *const messages, size_t messages_len, void* user_data); typedef enum input_dev_type { input_dev_type_uinput, input_dev_type_iio, input_dev_type_hidraw, - input_dev_type_timer, } input_dev_type_t; typedef struct hidraw_filters { @@ -54,44 +40,13 @@ typedef struct iio_filters { const char name[256]; } iio_filters_t; -typedef int (*hidraw_map)( - const dev_in_settings_t *const conf, - int hidraw_fd, - in_message_t *const messages, - size_t messages_len, - void* user_data -); +typedef int (*hidraw_set_leds)(uint8_t r, uint8_t g, uint8_t b, void* user_data); -typedef int (*hidraw_set_leds)( - const dev_in_settings_t *const conf, - int hidraw_fd, - uint8_t r, - uint8_t g, - uint8_t b, - void* user_data -); - -typedef int (*hidraw_rumble)( - const dev_in_settings_t *const conf, - int hidraw_fd, - uint8_t left_motor, - uint8_t right_motor, - void* user_data -); - -typedef void (*hidraw_timer)( - const dev_in_settings_t *const conf, - int fd, - const char* const timer_name, - uint64_t expired, - void* user_data -); +typedef int (*hidraw_rumble)(uint8_t left_motor, uint8_t right_motor, void* user_data); typedef struct hidraw_callbacks { hidraw_set_leds leds_callback; hidraw_rumble rumble_callback; - hidraw_map map_callback; - hidraw_timer timeout_callback; } hidraw_callbacks_t; typedef struct iio_settings { @@ -99,23 +54,6 @@ typedef struct iio_settings { int8_t post_matrix[3][3]; } iio_settings_t; -typedef int (*timer_map)(const dev_in_settings_t *const conf, int timer_fd, uint64_t expirations, in_message_t *const messages, size_t messages_len, void* user_data); - -typedef struct timer_callbacks { - timer_map map_fn; -} timer_callbacks_t; - -typedef struct ev_callbacks { - ev_map input_map_fn; - ev_timer timeout_callback; -} ev_callbacks_t; - -typedef struct timer_filters { - char name[128]; - uint64_t ticktime_ms; - uint64_t ticktime_ns; -} timer_filters_t; - typedef struct input_dev { input_dev_type_t dev_type; @@ -123,25 +61,23 @@ typedef struct input_dev { uinput_filters_t ev; iio_filters_t iio; hidraw_filters_t hidraw; - timer_filters_t timer; } filters; void* user_data; union input_dev_map { iio_settings_t iio_settings; - ev_callbacks_t ev_callbacks; - hidraw_callbacks_t hidraw_callbacks; - timer_callbacks_t timer_callbacks; + ev_map ev_input_map_fn; + hidraw_map hidraw_input_map_fn; } map; } input_dev_t; -typedef int (*platform_init)(const dev_in_settings_t *const conf, void** platform_data); +typedef int (*platform_init)(void** platform_data); -typedef void (*platform_deinit)(const dev_in_settings_t *const conf, void** platform_data); +typedef void (*platform_deinit)(void** platform_data); -typedef int (*platform_leds)(const dev_in_settings_t *const conf, uint8_t r, uint8_t g, uint8_t b, void* platform_data); +typedef int (*platform_leds)(uint8_t r, uint8_t g, uint8_t b, void* platform_data); typedef struct input_dev_composite { diff --git a/legion_go.c b/legion_go.c index 6d5c33e..4f942df 100644 --- a/legion_go.c +++ b/legion_go.c @@ -11,12 +11,12 @@ static input_dev_t in_xbox_dev = { } }, .map = { - .ev_callbacks = { - .input_map_fn = xbox360_ev_map, - }, + .ev_input_map_fn = xbox360_ev_map, } }; +static xbox360_settings_t x360_cfg; + static input_dev_t in_iio_dev = { .dev_type = input_dev_type_iio, .filters = { @@ -40,7 +40,7 @@ static struct llg_hidraw_data { uint8_t last_packet[64]; } llg_hidraw_user_data; -static int llg_hidraw_map(const dev_in_settings_t *const conf, int hidraw_fd, in_message_t *const messages, size_t messages_len, void* user_data) { +static int llg_hidraw_map(int hidraw_fd, in_message_t *const messages, size_t messages_len, void* user_data) { struct llg_hidraw_data *const llg_data = (struct llg_hidraw_data*)user_data; int msg_count = 0; @@ -84,9 +84,7 @@ static input_dev_t in_hidraw_dev = { }, .user_data = (void*)&llg_hidraw_user_data, .map = { - .hidraw_callbacks = { - .map_callback = llg_hidraw_map, - } + .hidraw_input_map_fn = llg_hidraw_map, }, }; @@ -94,7 +92,7 @@ typedef struct legion_go_platform { int _pad; } legion_go_platform_t; -static int legion_platform_init(const dev_in_settings_t *const conf, void** platform_data) { +static int legion_platform_init(void** platform_data) { int res = -EINVAL; legion_go_platform_t *const llg_platform = malloc(sizeof(legion_go_platform_t)); @@ -111,12 +109,12 @@ legion_platform_init_err: return res; } -static void legion_platform_deinit(const dev_in_settings_t *const conf, void** platform_data) { +static void legion_platform_deinit(void** platform_data) { free(*platform_data); *platform_data = NULL; } -int legion_platform_leds(const dev_in_settings_t *const conf, uint8_t r, uint8_t g, uint8_t b, void* platform_data) { +int legion_platform_leds(uint8_t r, uint8_t g, uint8_t b, void* platform_data) { return 0; } @@ -133,7 +131,10 @@ input_dev_composite_t legion_composite = { }; -input_dev_composite_t* legion_go_device_def(void) { +input_dev_composite_t* legion_go_device_def(const controller_settings_t *const settings) { + x360_cfg.nintendo_layout = settings->nintendo_layout; + + in_xbox_dev.user_data = (void*)&x360_cfg; return &legion_composite; } diff --git a/legion_go.h b/legion_go.h index 847a0a6..712459c 100644 --- a/legion_go.h +++ b/legion_go.h @@ -3,4 +3,4 @@ #include "input_dev.h" #include "settings.h" -input_dev_composite_t* legion_go_device_def(void); +input_dev_composite_t* legion_go_device_def(const controller_settings_t *const settings); diff --git a/main.c b/main.c index a598955..4c350a2 100644 --- a/main.c +++ b/main.c @@ -10,33 +10,15 @@ #include "rog_ally.h" #include "legion_go.h" -#include - static const char* configuration_file = "/etc/ROGueENEMY/config.cfg"; -int main(int argc, char ** argv) { - // Lock all current and future pages from preventing of being paged to swap - const int lockall_res = mlockall( MCL_CURRENT | MCL_FUTURE ); - if (lockall_res) { - fprintf(stderr, "mlockall failed: %d", lockall_res); - } +controller_settings_t settings; +int main(int argc, char ** argv) { int ret = 0; - dev_in_settings_t in_settings = { - .enable_qam = true, - .ff_gain = 0xFFFF, - .rumble_on_mode_switch = true, - .m1m2_mode = 1, - .touchbar = true, - .enable_thermal_profiles_switching = false, - .default_thermal_profile = -1, - .enable_leds_commands = false, - .enable_imu = true, - .imu_polling_interface = true, - }; - - load_in_config(&in_settings, configuration_file); + init_config(&settings); + fill_config(&settings, configuration_file); input_dev_composite_t* in_devs = NULL; @@ -51,10 +33,10 @@ int main(int argc, char ** argv) { read(dmi_name_fd, bname, sizeof(bname)); if (strstr(bname, "RC71L") != NULL) { printf("Running in an Asus ROG Ally device\n"); - in_devs = rog_ally_device_def(&in_settings); + in_devs = rog_ally_device_def(&settings); } else if (strstr(bname, "LNVNB161216")) { printf("Running in an Lenovo Legion Go device\n"); - in_devs = legion_go_device_def(); + in_devs = legion_go_device_def(&settings); } close(dmi_name_fd); @@ -73,54 +55,13 @@ int main(int argc, char ** argv) { } }, } - }, - .settings = in_settings, + } }; - // fill in configuration from file: automatic fallback to default - load_in_config(&dev_in_thread_data.settings, configuration_file); - //memset(&dev_in_thread_data.communication.endpoint.socket.serveraddr, 0, sizeof(dev_in_thread_data.communication.endpoint.socket.serveraddr)); - // Initialize pthread attributes (default values) - struct sched_param param; - pthread_attr_t attr; - ret = pthread_attr_init(&attr); - if (ret) { - printf("init pthread attributes failed\n"); - goto main_err; - } - - // Set a specific stack size - ret = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 8192); - if (ret) { - printf("pthread setstacksize failed\n"); - goto main_err; - } - - // Set scheduler policy and priority of pthread - ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO); - if (ret) { - printf("pthread setschedpolicy failed\n"); - goto main_err; - } - param.sched_priority = 80; - ret = pthread_attr_setschedparam(&attr, ¶m); - if (ret) { - printf("pthread setschedparam failed\n"); - goto main_err; - } - - // Use scheduling parameters of attr - ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); - if (ret) { - printf("pthread setinheritsched failed\n"); - goto main_err; - } - - pthread_t dev_in_thread; - const int dev_in_thread_creation = pthread_create(&dev_in_thread, &attr, dev_in_thread_func, (void*)(&dev_in_thread_data)); + const int dev_in_thread_creation = pthread_create(&dev_in_thread, NULL, dev_in_thread_func, (void*)(&dev_in_thread_data)); if (dev_in_thread_creation != 0) { fprintf(stderr, "Error creating dev_in thread: %d\n", dev_in_thread_creation); ret = -1; diff --git a/message.h b/message.h index 7f91be8..91bc3b2 100644 --- a/message.h +++ b/message.h @@ -24,8 +24,6 @@ typedef enum in_message_gamepad_btn { GAMEPAD_BTN_L5, GAMEPAD_BTN_R5, GAMEPAD_BTN_TOUCHPAD, - GAMEPAD_BTN_JOIN_LEFT_ANALOG_AND_GYROSCOPE, - GAMEPAD_BTN_JOIN_RIGHT_ANALOG_AND_GYROSCOPE, GAMEPAD_LEFT_JOYSTICK_X, GAMEPAD_LEFT_JOYSTICK_Y, @@ -34,142 +32,36 @@ typedef enum in_message_gamepad_btn { GAMEPAD_DPAD_X, GAMEPAD_DPAD_Y, - - GAMEPAD_GYROSCOPE, - GAMEPAD_ACCELEROMETER, - - GAMEPAD_TOUCHPAD_X, - GAMEPAD_TOUCHPAD_Y, - GAMEPAD_TOUCHPAD_TOUCH_ACTIVE, } in_gamepad_element_t; -typedef struct in_message_gamepad_touchpad_x { - int16_t value; -} in_message_gamepad_touchpad_x_t; - -typedef struct in_message_gamepad_touchpad_y { - int16_t value; -} in_message_gamepad_touchpad_y_t; - -typedef struct in_message_gamepad_touchpad_active { - int16_t status; -} in_message_gamepad_touchpad_active_t; - -typedef struct in_message_gamepad_gyro { - int64_t sample_timestamp_ns; - - uint16_t x; - uint16_t y; - uint16_t z; -} in_message_gamepad_gyro_t; - -typedef struct in_message_gamepad_accel { - int64_t sample_timestamp_ns; - - uint16_t x; - uint16_t y; - uint16_t z; -} in_message_gamepad_accel_t; - typedef struct in_message_gamepad_set_element { in_gamepad_element_t element; union { uint8_t btn; int32_t joystick_pos; int8_t dpad; // -1 | 0 | +1 - in_message_gamepad_accel_t accel; - in_message_gamepad_gyro_t gyro; - in_message_gamepad_touchpad_active_t touchpad_active; - in_message_gamepad_touchpad_x_t touchpad_x; - in_message_gamepad_touchpad_y_t touchpad_y; } status; } in_message_gamepad_set_element_t; -typedef enum mouse_element { - MOUSE_ELEMENT_X, - MOUSE_ELEMENT_Y, - MOUSE_BTN_LEFT, - MOUSE_BTN_MIDDLE, - MOUSE_BTN_RIGHT, -} mouse_element_t; - -typedef struct in_message_mouse_event { - mouse_element_t type; - int32_t value; -} in_message_mouse_event_t; - typedef enum in_message_gamepad_action { GAMEPAD_ACTION_PRESS_AND_RELEASE_CENTER, GAMEPAD_ACTION_OPEN_STEAM_QAM, } in_message_gamepad_action_t; -typedef enum kbd_element { - KEYBOARD_KEY_Q, - KEYBOARD_KEY_W, - KEYBOARD_KEY_E, - KEYBOARD_KEY_R, - KEYBOARD_KEY_T, - KEYBOARD_KEY_Y, - KEYBOARD_KEY_U, - KEYBOARD_KEY_I, - KEYBOARD_KEY_O, - KEYBOARD_KEY_P, - KEYBOARD_KEY_A, - KEYBOARD_KEY_S, - KEYBOARD_KEY_D, - KEYBOARD_KEY_F, - KEYBOARD_KEY_G, - KEYBOARD_KEY_H, - KEYBOARD_KEY_J, - KEYBOARD_KEY_K, - KEYBOARD_KEY_L, - KEYBOARD_KEY_Z, - KEYBOARD_KEY_X, - KEYBOARD_KEY_C, - KEYBOARD_KEY_V, - KEYBOARD_KEY_B, - KEYBOARD_KEY_N, - KEYBOARD_KEY_M, - KEYBOARD_KEY_UP, - KEYBOARD_KEY_DOWN, - KEYBOARD_KEY_LEFT, - KEYBOARD_KEY_RIGHT, - KEYBOARD_KEY_NUM_1, - KEYBOARD_KEY_NUM_2, - KEYBOARD_KEY_NUM_3, - KEYBOARD_KEY_NUM_4, - KEYBOARD_KEY_NUM_5, - KEYBOARD_KEY_NUM_6, - KEYBOARD_KEY_NUM_7, - KEYBOARD_KEY_NUM_8, - KEYBOARD_KEY_NUM_9, - KEYBOARD_KEY_NUM_0, - KEYBOARD_KEY_LCRTL, -} kbd_element_t; - -typedef struct in_message_keyboard_set_element { - kbd_element_t type; - uint8_t value; -} in_message_keyboard_set_element_t; - typedef enum in_in_message_type { GAMEPAD_SET_ELEMENT, GAMEPAD_ACTION, - MOUSE_EVENT, - KEYBOARD_SET_ELEMENT, } in_message_type_t; typedef struct in_message { in_message_type_t type; union { + //imu_in_message_t imu; + in_message_gamepad_action_t action; in_message_gamepad_set_element_t gamepad_set; - - in_message_mouse_event_t mouse_event; - - in_message_keyboard_set_element_t kbd_set; } data; } in_message_t; diff --git a/platform.c b/platform.c new file mode 100644 index 0000000..dee1d51 --- /dev/null +++ b/platform.c @@ -0,0 +1,276 @@ +#include +#include +#include + +#include + +#include "platform.h" + +static const char* const platform_input_path = "/sys/devices/platform/asus-mcu.0/input/mode"; + +static int hidraw_cycle_to_mode(const char* const path, int controller_mode) { + int res = 0; + + if ((controller_mode < 0) || (controller_mode > 2)) { + res = -EINVAL; + goto hidraw_cycle_to_mode_err_mode; + } + + const char* hidraw_subdir = "/hidraw/"; + + const unsigned long len = strlen(path) + strlen(hidraw_subdir) + 64; + char* hidraw_path = malloc(len + 1); + if (hidraw_path == NULL) { + res = -ENOMEM; + goto hidraw_cycle_to_mode_err_path; + } + + memset(hidraw_path, 0, len + 1); + strcat(hidraw_path, path); + strcat(hidraw_path, hidraw_subdir); + + DIR *d; + struct dirent *dir; + d = opendir(hidraw_path); + if (d) { + while ((dir = readdir(d)) != NULL) { + if (strstr(dir->d_name, "hidraw") == NULL) { // h as in hidraw + continue; + } + + memset(hidraw_path, 0, len + 1); + strcat(hidraw_path, "/dev/"); + strcat(hidraw_path, dir->d_name); + + //strcat(hidraw_path, dir->d_name); + //strcat(hidraw_path, "/dev"); + + printf("Using hidraw located at: %s\n", hidraw_path); + + int fd = open(hidraw_path, O_RDWR); + if (fd == -1) { + fprintf(stderr, "Error opening hidraw device %s\n", hidraw_path); + + res = -EIO; + + goto hidraw_cycle_to_mode_err; + } + + for (int i = 0; i < 23; ++i) { + const int write_res = write(fd, &rc71l_mode_switch_commands[controller_mode][i][0], 64); + if (write_res != 64) { + fprintf(stderr, "Error writing packet %d/23: %d bytes sent, 64 expected\n", i, write_res); + break; + } + } + + close(fd); + + if (res == 0) { + printf("Control messages sent successfully.\n"); + } else { + goto hidraw_cycle_to_mode_err; + } + + } + } + + + +hidraw_cycle_to_mode_err: + free(hidraw_path); + +hidraw_cycle_to_mode_err_path: +hidraw_cycle_to_mode_err_mode: + return res; +} + +static char* find_device(struct udev *udev) { + struct udev_enumerate *const enumerate = udev_enumerate_new(udev); + if (enumerate == NULL) { + fprintf(stderr, "Error in udev_enumerate_new: mode switch will not be available.\n"); + return NULL; + } + + const int add_match_subsystem_res = udev_enumerate_add_match_subsystem(enumerate, "hid"); + if (add_match_subsystem_res != 0) { + fprintf(stderr, "Error in udev_enumerate_add_match_subsystem: %d\n", add_match_subsystem_res); + + udev_enumerate_unref(enumerate); + + return NULL; + } + + const int add_match_sysattr_res = udev_enumerate_add_match_sysattr(enumerate, "gamepad_mode", NULL); + if (add_match_sysattr_res != 0) { + fprintf(stderr, "Error in udev_enumerate_add_match_sysattr: %d\n", add_match_sysattr_res); + + udev_enumerate_unref(enumerate); + + return NULL; + } + + const int enumerate_scan_devices_res = udev_enumerate_scan_devices(enumerate); + if (enumerate_scan_devices_res != 0) { + fprintf(stderr, "Error in udev_enumerate_scan_devices: %d\n", enumerate_scan_devices_res); + + udev_enumerate_unref(enumerate); + + return NULL; + } + + struct udev_list_entry *const udev_lst_frst = udev_enumerate_get_list_entry(enumerate); + + struct udev_list_entry *list_entry = NULL; + udev_list_entry_foreach(list_entry, udev_lst_frst) { + const char* const name = udev_list_entry_get_name(list_entry); + + const unsigned long len = strlen(name) + 1; + char *const result = malloc(len); + memset(result, 0, len); + strncat(result, name, len - 1); + + udev_enumerate_unref(enumerate); + + return result; + } + + udev_enumerate_unref(enumerate); + return NULL; +} + +int init_platform(rc71l_platform_t *const platform) { + platform->udev = NULL; + + if (access(platform_input_path, F_OK) != 0) { + fprintf(stderr, "Unable to find the MCU platform mode file %s: asus-mcu not found.\n", platform_input_path); + + /* create udev object */ + platform->udev = udev_new(); + if (platform->udev == NULL) { + fprintf(stderr, "Cannot create udev context: mode switch will not be available.\n"); + platform->mode = -1; + return -ENOENT; + } + + char *const dev_name = find_device(platform->udev); + if (dev_name == NULL) { + fprintf(stderr, "Cannot locate asus-mcu device: mode switch will not be available.\n"); + platform->mode = -1; + return -ENOENT; + } else { + printf("Asus MCU over hidraw: %s -- mode will be reset\n", dev_name); + + platform->platform_mode = rc71l_platform_mode_hidraw; + platform->modes_count = 2; + platform->mode = 0; + + // reset to mode 0: game mode + const int reset_res = hidraw_cycle_to_mode(dev_name, 0); + if (reset_res != 0) { + fprintf(stderr, "Unable to reset Asus MCU over hidraw: %d -- Asus MCU will be unavailable.\n", reset_res); + + free(dev_name); + + return -EIO; + } + + // find_device does malloc + free(dev_name); + + return 0; + } + + return -ENOENT; + } + + FILE* mode_file = fopen(platform_input_path, "r"); + if (mode_file == NULL) { + fprintf(stderr, "Unable to open the MCU platform mode file %s: modes cannot be switched.\n", platform_input_path); + platform->mode = -1; + return -EINVAL; + } + + char mode_str[12]; + unsigned long read_bytes = fread((void*)&mode_str[0], 1, sizeof(mode_str), mode_file); + if (read_bytes < 1) { + fprintf(stderr, "Unable to read the MCU platform mode file %s: no bytes.\n", platform_input_path); + fclose(mode_file); + platform->mode = -1; + return -EINVAL; + } + + platform->mode = strtoul(&mode_str[0], NULL, 10); + + fclose(mode_file); + + printf("Asus MCU platform found: current mode %lu\n", platform->mode); + platform->modes_count = 2; + + platform->platform_mode = rc71l_platform_mode_asus_mcu; + + return 0; +} + +int cycle_mode(rc71l_platform_t *const platform) { + if (platform == NULL) { + return -ENOENT; + } + + char new_mode_str[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + }; + + unsigned long new_mode = (platform->mode + 1) % platform->modes_count; + sprintf(new_mode_str, "%lu\n", new_mode); + + if (platform->platform_mode == rc71l_platform_mode_hidraw) { + char *const dev_name = find_device(platform->udev); + if (dev_name == NULL) { + fprintf(stderr, "Unable to locate Asus MCU hidraw to mode-switch. Mode will not be switched.\n"); + return -ENOENT; + } + + const int next_mode = (platform->mode + 1) % platform->modes_count; + + const int reset_res = hidraw_cycle_to_mode(dev_name, next_mode); + if (reset_res != 0) { + fprintf(stderr, "Unable to change mode of Asus MCU over hidraw: %d.\n", reset_res); + } + + free(dev_name); + + platform->mode = next_mode; + + printf("Used hidraw to switch Asus MCU to mode %lu\n", platform->mode); + + return reset_res; + } else if (platform->platform_mode == rc71l_platform_mode_asus_mcu) { + FILE* mode_file = fopen(platform_input_path, "w"); + if (mode_file == NULL) { + fprintf(stderr, "Unable to open the MCU platform mode file %s: modes cannot be switched.\n", platform_input_path); + return -1; + } + + size_t len = strlen(new_mode_str); + const int write_bytes = fwrite((void*)&new_mode_str[0], 1, len, mode_file); + if (write_bytes < len) { + fprintf(stderr, "Error writing new mode: expected to write %d bytes, %d written.\n", (int)len, (int)write_bytes); + return -EIO; + } + + platform->mode = new_mode; + + printf("Used asus-mcu to switch Asus MCU to mode %lu\n", platform->mode); + + fclose(mode_file); + } + + return -ENOENT; +} + +int is_mouse_mode(rc71l_platform_t *const platform) { + return platform != NULL ? platform->mode == 1 : 0; +} diff --git a/platform.h b/platform.h new file mode 100644 index 0000000..26cbf0f --- /dev/null +++ b/platform.h @@ -0,0 +1,23 @@ +#pragma once + +#include "rogue_enemy.h" + +typedef enum rc71l_platform_mode { + rc71l_platform_mode_hidraw, + rc71l_platform_mode_asus_mcu, +} rc71l_platform_mode_t; + +typedef struct rc71l_platform { + struct udev *udev; + + rc71l_platform_mode_t platform_mode; + + unsigned long mode; + unsigned int modes_count; +} rc71l_platform_t; + +int init_platform(rc71l_platform_t *const platform); + +int cycle_mode(rc71l_platform_t *const platform); + +int is_mouse_mode(rc71l_platform_t *const platform); diff --git a/rog_ally.c b/rog_ally.c index 6bbce76..0d261a7 100644 --- a/rog_ally.c +++ b/rog_ally.c @@ -1,988 +1,527 @@ #include "rog_ally.h" #include "input_dev.h" #include "dev_hidraw.h" -#include "message.h" #include "xbox360.h" -#include -static const char iio_base_path[] = "/sys/bus/iio/devices/iio:device0/"; - -enum rc71l_leds_mode { - ROG_ALLY_MODE_STATIC = 0, - ROG_ALLY_MODE_BREATHING = 1, - ROG_ALLY_MODE_COLOR_CYCLE = 2, - ROG_ALLY_MODE_RAINBOW = 3, - ROG_ALLY_MODE_STROBING = 10, - ROG_ALLY_MODE_DIRECT = 0xFF, -} rc71l_leds_mode_t; - -enum rc71l_leds_speed { - ROG_ALLY_SPEED_MIN = 0xE1, - ROG_ALLY_SPEED_MED = 0xEB, - ROG_ALLY_SPEED_MAX = 0xF5 -} rc71l_leds_speed_t; - -enum rc71l_leds_direction { - ROG_ALLY_DIRECTION_RIGHT = 0x00, - ROG_ALLY_DIRECTION_LEFT = 0x01 -} rc71l_leds_direction_t; - -struct rc71l_platform; - -typedef struct rc71l_xbox360_user_data { - struct rc71l_platform* parent; - - uint64_t accounted_mode_switches; - - uint64_t mode_switched; - - uint64_t timeout_after_mode_switch; - - bool mode_switch_rumbling; - - struct ff_effect mode_switch_rumble_effect; - -} rc71l_xbox360_user_data_t; - -typedef struct rc71l_asus_kbd_user_data { - struct rc71l_platform* parent; - - struct udev *udev; - - int m1, m2; -} rc71l_asus_kbd_user_data_t; - -typedef struct rc71l_asus_hidraw_user_data { - struct rc71l_platform* parent; - -} rc71l_asus_hidraw_user_data_t; - -typedef struct rc71l_timer_user_data { - struct rc71l_platform* parent; - -} rc71l_timer_user_data_t; - -rc71l_timer_user_data_t timer_user_data; - -typedef struct rc71l_platform { - rc71l_asus_kbd_user_data_t* kbd_user_data; - - rc71l_xbox360_user_data_t* xbox360_user_data; - - rc71l_timer_user_data_t* timer_data; - - rc71l_asus_hidraw_user_data_t* hidraw_user_data; - - struct { - uint8_t r; - uint8_t g; - uint8_t b; - } static_led_color; - - uint64_t thermal_profile_expired; - size_t current_thermal_profile; - size_t next_thermal_profile; - -} rc71l_platform_t; - -static rc71l_asus_hidraw_user_data_t hidraw_userdata = { - .parent = NULL, -}; - -static rc71l_asus_kbd_user_data_t asus_userdata = { - .parent = NULL, - .udev = NULL, - .m1 = 0, - .m2 = 0, -}; - -static rc71l_xbox360_user_data_t controller_user_data = { - .accounted_mode_switches = 0, - .mode_switched = 0, - .timeout_after_mode_switch = 0, - .mode_switch_rumbling = false, - .mode_switch_rumble_effect = { - .type = FF_RUMBLE, - .id = -1, - .replay = { - .delay = 0x00, - .length = 50 +/* + * USB buffers to be used in a control transfer to make the joystick change buttons mode and scancodes + * 0 is default (game_mode with back buttons sending F17 and F18 instead of F15 for both as when unconfigured) + * 1 is mouse mode: back buttons still are F17 and F18 + * 2 is macro mode: the default when back paddles are chords. to be avoided as pressing those will break others buttons status. + */ +static const uint8_t rc71l_mode_switch_commands[][23][64] = { + { + { + 0x5A, 0xD1, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - .u = { - .rumble = { - .strong_magnitude = 0xFFFF, - .weak_magnitude = 0xFFFF, - } + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x01, 0x2C, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8C, 0x88, 0x76, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x02, 0x2C, 0x01, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x23, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x03, 0x2C, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x04, 0x2C, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x05, 0x2C, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x31, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x06, 0x2C, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x4D, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x07, 0x2C, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x08, 0x2C, 0x02, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x09, 0x2C, 0x01, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x06, 0x02, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x04, 0x04, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x05, 0x04, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + } + }, + { + { + 0x5A, 0xD1, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x01, 0x2C, 0x02, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x99, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8C, 0x88, 0x76, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x02, 0x2C, 0x02, 0x00, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9B, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x03, 0x2C, 0x02, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x04, 0x2C, 0x02, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x05, 0x2C, 0x02, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x76, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x31, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x06, 0x2C, 0x02, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x4D, 0x00, 0x00, 0x00, 0x02, 0x00, 0x96, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x07, 0x2C, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x08, 0x2C, 0x02, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x09, 0x2C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x88, 0x0D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x06, 0x02, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x04, 0x04, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x05, 0x04, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + } + }, + { + { + 0x5A, 0xD1, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x01, 0x2C, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8C, 0x88, 0x76, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x02, 0x2C, 0x01, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x23, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x03, 0x2C, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x04, 0x2C, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x05, 0x2C, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x31, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x06, 0x2C, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x4D, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x07, 0x2C, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x08, 0x2C, 0x02, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x02, 0x09, 0x2C, 0x01, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x0F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x06, 0x02, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x04, 0x04, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x5A, 0xD1, 0x05, 0x04, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }; -static rc71l_platform_t hw_platform = { - .kbd_user_data = &asus_userdata, - .xbox360_user_data = &controller_user_data, - .timer_data = &timer_user_data, - .hidraw_user_data = &hidraw_userdata, - .static_led_color = { - .r = 0x40, - .g = 0x40, - .b = 0x40, - }, - .current_thermal_profile = 0, - .next_thermal_profile = 0, -}; - -static char* find_kernel_sysfs_device_path(struct udev *udev) { - struct udev_enumerate *const enumerate = udev_enumerate_new(udev); - if (enumerate == NULL) { - fprintf(stderr, "Error in udev_enumerate_new: mode switch will not be available.\n"); - return NULL; - } - - const int add_match_subsystem_res = udev_enumerate_add_match_subsystem(enumerate, "hid"); - if (add_match_subsystem_res != 0) { - fprintf(stderr, "Error in udev_enumerate_add_match_subsystem: %d\n", add_match_subsystem_res); - - udev_enumerate_unref(enumerate); - - return NULL; - } - - const int add_match_sysattr_res = udev_enumerate_add_match_sysattr(enumerate, "gamepad_mode", NULL); - if (add_match_sysattr_res != 0) { - fprintf(stderr, "Error in udev_enumerate_add_match_sysattr: %d\n", add_match_sysattr_res); - - udev_enumerate_unref(enumerate); - - return NULL; - } - - const int enumerate_scan_devices_res = udev_enumerate_scan_devices(enumerate); - if (enumerate_scan_devices_res != 0) { - fprintf(stderr, "Error in udev_enumerate_scan_devices: %d\n", enumerate_scan_devices_res); - - udev_enumerate_unref(enumerate); - - return NULL; - } - - struct udev_list_entry *const udev_lst_frst = udev_enumerate_get_list_entry(enumerate); - - struct udev_list_entry *list_entry = NULL; - udev_list_entry_foreach(list_entry, udev_lst_frst) { - const char* const name = udev_list_entry_get_name(list_entry); - - const unsigned long len = strlen(name) + 1; - char *const result = malloc(len); - memset(result, 0, len); - strncat(result, name, len - 1); - - udev_enumerate_unref(enumerate); - - return result; - } - - udev_enumerate_unref(enumerate); - return NULL; -} - -static int get_next_mode(int current_mode) { - if (current_mode == 1) - return 2; - else if (current_mode == 2) - return 1; - /* - // TODO: luke has yet to complete the mapping for mode 3, use only 1 and 2 for now - if (current_mode == 2) - return 3; - if (current_mode == 3) - return 1; - */ - else - fprintf(stderr, "Invalid current mode: %d -- 1 (gamepad) will be set\n", current_mode); - - return 1; -} - -static int asus_kbd_ev_map( - const dev_in_settings_t *const conf, - const evdev_collected_t *const e, - in_message_t *const messages, - size_t messages_len, - void* user_data -) { - rc71l_asus_kbd_user_data_t *const asus_kbd_user_data = (rc71l_asus_kbd_user_data_t*)user_data; +int asus_kbd_ev_map(const evdev_collected_t *const e, in_message_t *const messages, size_t messages_len, void* user_data) { int written_msg = 0; - for (size_t i = 0; i < e->ev_count; ++i) { - if (e->ev[i].type == EV_KEY) { - if (e->ev[i].value > 1) { - continue; + if ( // this is what happens at release of the left-screen button of the ROG Ally + (e->ev_count == 2) && + (e->ev[0].type == EV_MSC) && + (e->ev[0].code == MSC_SCAN) && + (e->ev[0].value == -13565786) && + (e->ev[1].type == EV_KEY) && + (e->ev[1].code == KEY_F16) && + (e->ev[1].value == 1) + ) { + const in_message_t current_message = { + .type = GAMEPAD_ACTION, + .data = { + .action = GAMEPAD_ACTION_PRESS_AND_RELEASE_CENTER, + } + }; + + messages[written_msg++] = current_message; + } else if ( // this is what happens at release of the right-screen button of the ROG Ally + (e->ev_count == 2) && + (e->ev[0].type == EV_MSC) && + (e->ev[0].code == MSC_SCAN) && + (e->ev[0].value == -13565896) && + (e->ev[1].type == EV_KEY) && + (e->ev[1].code == KEY_PROG1) && + (e->ev[1].value == 1) + ) { + const in_message_t current_message = { + .type = GAMEPAD_ACTION, + .data = { + .action = GAMEPAD_ACTION_OPEN_STEAM_QAM, + } + }; + + messages[written_msg++] = current_message; + } else if ( + (e->ev_count == 2) && + (e->ev[0].type == EV_MSC) && + (e->ev[0].code == MSC_SCAN) && + (e->ev[0].value == 458860) && + (e->ev[1].type == EV_KEY) && + (e->ev[1].code == KEY_F17) + ) { + const in_message_t current_message = { + .type = GAMEPAD_SET_ELEMENT, + .data = { + .gamepad_set = { + .element = GAMEPAD_BTN_L5, + .status = { + .btn = e->ev[1].value, + } + } + } + }; + + messages[written_msg++] = current_message; + } else if ( + (e->ev_count == 2) && + (e->ev[0].type == EV_MSC) && + (e->ev[0].code == MSC_SCAN) && + (e->ev[0].value == 458861) && + (e->ev[1].type == EV_KEY) && + (e->ev[1].code == KEY_F18) + ) { + const in_message_t current_message = { + .type = GAMEPAD_SET_ELEMENT, + .data = { + .gamepad_set = { + .element = GAMEPAD_BTN_R5, + .status = { + .btn = e->ev[1].value, + } + } } + }; - if (e->ev[i].code == KEY_F14) { - // this is left back paddle, works as expected - - if (e->ev[i].value == 0) { - asus_kbd_user_data->m1 -= (asus_kbd_user_data->m1 == 0) ? 0 : 1; - } else if (e->ev[i].value == 1) { - asus_kbd_user_data->m1 += 1; - } - - if (conf->m1m2_mode == 0) { - const in_message_t current_message = { - .type = GAMEPAD_SET_ELEMENT, - .data = { - .gamepad_set = { - .element = GAMEPAD_BTN_L4, - .status = { - .btn = e->ev[1].value, - } - } - } - }; - - messages[written_msg++] = current_message; - } else if (conf->m1m2_mode == 1) { - const in_message_t current_message = { - .type = GAMEPAD_SET_ELEMENT, - .data = { - .gamepad_set = { - .element = GAMEPAD_BTN_TOUCHPAD, - .status = { - .btn = (asus_kbd_user_data->m1 + asus_kbd_user_data->m2) == 0 ? 0 : 1, - } - } - } - }; - - messages[written_msg++] = current_message; - } else if (conf->m1m2_mode == 2) { - const in_message_t current_message = { - .type = GAMEPAD_SET_ELEMENT, - .data = { - .gamepad_set = { - .element = GAMEPAD_BTN_JOIN_LEFT_ANALOG_AND_GYROSCOPE, - .status = { - .btn = e->ev[1].value, - } - } - } - }; - - messages[written_msg++] = current_message; - } - } else if (e->ev[i].code == KEY_F15) { - // this is right back paddle, works as expected - - if (e->ev[i].value == 0) { - asus_kbd_user_data->m2 -= (asus_kbd_user_data->m2 == 0) ? 0 : 1; - } else if (e->ev[i].value == 1) { - asus_kbd_user_data->m2 += 1; - } - - if (conf->m1m2_mode == 0) { - const in_message_t current_message = { - .type = GAMEPAD_SET_ELEMENT, - .data = { - .gamepad_set = { - .element = GAMEPAD_BTN_R4, - .status = { - .btn = e->ev[1].value, - } - } - } - }; - - messages[written_msg++] = current_message; - } else if (conf->m1m2_mode == 1) { - const in_message_t current_message = { - .type = GAMEPAD_SET_ELEMENT, - .data = { - .gamepad_set = { - .element = GAMEPAD_BTN_TOUCHPAD, - .status = { - .btn = (asus_kbd_user_data->m1 + asus_kbd_user_data->m2) == 0 ? 0 : 1, - } - } - } - }; - - messages[written_msg++] = current_message; - } else if (conf->m1m2_mode == 2) { - const in_message_t current_message = { - .type = GAMEPAD_SET_ELEMENT, - .data = { - .gamepad_set = { - .element = GAMEPAD_BTN_JOIN_RIGHT_ANALOG_AND_GYROSCOPE, - .status = { - .btn = e->ev[1].value, - } - } - } - }; - - messages[written_msg++] = current_message; - } - } else if ((e->ev[i].code == KEY_F16) && (e->ev[i].value != 0)) { - // this is left screen button, on release both 0 and 1 events are emitted so just discard the 0 - const in_message_t current_message = { - .type = GAMEPAD_ACTION, - .data = { - .action = GAMEPAD_ACTION_PRESS_AND_RELEASE_CENTER, - } - }; - - messages[written_msg++] = current_message; - } else if ((e->ev[i].code == KEY_PROG1) && (e->ev[i].value != 0)) { - // this is right screen button, on short release both 0 and 1 events are emitted so just discard the 0 - if (conf->enable_qam) { - const in_message_t current_message = { - .type = GAMEPAD_ACTION, - .data = { - .action = GAMEPAD_ACTION_OPEN_STEAM_QAM, - } - }; - - messages[written_msg++] = current_message; - } - } else if ((e->ev[i].code == KEY_F18) && (e->ev[i].value != 0)) { - // this is right screen button, on long release both 0 and 1 events are emitted so just discard the 0 - - } else if ((e->ev[i].code == KEY_DELETE) && (e->ev[i].value != 0)) { - // this is left screen button, on long release both 0 and 1 events are emitted so just discard the 0 - - if (conf->enable_thermal_profiles_switching) { - asus_kbd_user_data->parent->next_thermal_profile = asus_kbd_user_data->parent->current_thermal_profile + 1; - - printf("Requested switch to thermal profile %d\n", (int)asus_kbd_user_data->parent->next_thermal_profile); - } - } else if ((e->ev[i].code == KEY_F17) && (e->ev[i].value != 0)) { - // this is right screen button, on long press, after passing short threshold both 0 and 1 events are emitted so just discard the 0 - - // change controller mode - if (asus_kbd_user_data == NULL) { - fprintf(stderr, "asus keyboard user data unavailable -- skipping mode change\n"); - continue; - } - - char *const kernel_sysfs = find_kernel_sysfs_device_path(asus_kbd_user_data->udev); - if (kernel_sysfs == NULL) { - fprintf(stderr, "Kernel interface to Asus MCU not found -- skipping mode change\n"); - continue; - } - - printf("Asus MCU kernel interface found at %s -- switching mode\n", kernel_sysfs); - - const size_t tmp_path_max_len = strlen(kernel_sysfs) + 256; - char *tmp_path = malloc(tmp_path_max_len); - - if (tmp_path != NULL) { - memset(tmp_path, 0, tmp_path_max_len); - snprintf(tmp_path, tmp_path_max_len - 1, "%s/gamepad_mode", kernel_sysfs); - - int gamepad_mode_fd = open(tmp_path, O_RDONLY); - if (gamepad_mode_fd > 0) { - char current_mode_str[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int current_mode_read_res = read(gamepad_mode_fd, (void*)current_mode_str, sizeof(current_mode_str)); - if (current_mode_read_res > 0) { - close(gamepad_mode_fd); - - int current_mode; - sscanf(current_mode_str, "%d", ¤t_mode); - - const int new_mode = get_next_mode(current_mode); - printf("Current mode is set to %d (read from %s) -- switching to %d\n", current_mode, current_mode_str, new_mode); - - char new_mode_str[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - snprintf(new_mode_str, sizeof(new_mode_str) - 1, "%d", new_mode); - gamepad_mode_fd = open(tmp_path, O_WRONLY); - if (gamepad_mode_fd > 0) { - if (write(gamepad_mode_fd, new_mode_str, strlen(new_mode_str)) > 0) { - printf("Controller mode switched successfully to %s\n", new_mode_str); - - asus_kbd_user_data->parent->xbox360_user_data->mode_switched++; - } else { - fprintf(stderr, "Unable to switch controller mode to %s: %d -- expect bugs\n", new_mode_str, errno); - } - close(gamepad_mode_fd); - } else { - fprintf(stderr, "Unable to open gamepad mode file to switch mode: %d\n", errno); - } - } else { - close(gamepad_mode_fd); - fprintf(stderr, "Unable to read gamepad_mode file to get current mode: %d\n", errno); - } - } else { - fprintf(stderr, "Unable to open gamepad_mode file in read-only mode to get current mode: %d\n", errno); - } - - free(tmp_path); - } else { - fprintf(stderr, "Unable to allocate enough memory\n"); - } - - free(kernel_sysfs); - } else if (e->ev[i].code == BTN_LEFT) { - const in_message_t current_message = { - .type = MOUSE_EVENT, - .data = { - .mouse_event = { - .type = MOUSE_BTN_LEFT, - .value = e->ev[i].value, - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == BTN_MIDDLE) { - const in_message_t current_message = { - .type = MOUSE_EVENT, - .data = { - .mouse_event = { - .type = MOUSE_BTN_MIDDLE, - .value = e->ev[i].value, - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == BTN_RIGHT) { - const in_message_t current_message = { - .type = MOUSE_EVENT, - .data = { - .mouse_event = { - .type = MOUSE_BTN_RIGHT, - .value = e->ev[i].value, - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_LEFTCTRL) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_LCRTL, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_Q) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_Q, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_W) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_W, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_E) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_E, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_R) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_R, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_T) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_T, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_Y) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_Y, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_U) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_U, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_I) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_I, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_O) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_O, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_P) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_P, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_A) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_A, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_S) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_S, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_D) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_D, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_F) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_F, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_G) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_G, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_H) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_H, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_J) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_J, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_K) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_K, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_L) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_L, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_Z) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_Z, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_X) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_X, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_C) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_C, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_V) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_V, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_B) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_B, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_N) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_N, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_M) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_M, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_0) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_NUM_0, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_1) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_NUM_1, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_2) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_NUM_2, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_3) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_NUM_3, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_4) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_NUM_4, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_5) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_NUM_5, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_6) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_NUM_6, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_7) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_NUM_7, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_8) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_NUM_8, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_9) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_NUM_9, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_UP) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_UP, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_DOWN) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_DOWN, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_LEFT) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_LEFT, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == KEY_RIGHT) { - const in_message_t current_message = { - .type = KEYBOARD_SET_ELEMENT, - .data = { - .kbd_set = { - .type = KEYBOARD_KEY_RIGHT, - .value = e->ev[i].value - } - } - }; - - messages[written_msg++] = current_message; - } - } else if (e->ev[i].type == EV_REL) { - if (e->ev[i].code == REL_X) { - const in_message_t current_message = { - .type = MOUSE_EVENT, - .data = { - .mouse_event = { - .type = MOUSE_ELEMENT_X, - .value = e->ev[i].value, - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == REL_Y) { - const in_message_t current_message = { - .type = MOUSE_EVENT, - .data = { - .mouse_event = { - .type = MOUSE_ELEMENT_Y, - .value = e->ev[i].value, - } - } - }; - - messages[written_msg++] = current_message; - } - } + messages[written_msg++] = current_message; } return written_msg; } +static hidraw_filters_t n_key_hidraw_filters = { + .pid = 0x1abe, + .vid = 0x0b05, + .rdesc_size = 167, // 48 83 167 +}; + static input_dev_t in_iio_dev = { .dev_type = input_dev_type_iio, .filters = { @@ -1014,108 +553,6 @@ static input_dev_t in_iio_dev = { //.input_filter_fn = input_filter_imu_identity, }; -static void rc71l_timer_touchscreen( - const dev_in_settings_t *const conf, - struct libevdev* evdev, - const char* const timer_name, - uint64_t expired, - void* user_data -) { - -} - -static int touchscreen_ev_map( - const dev_in_settings_t *const conf, - const evdev_collected_t *const e, - in_message_t *const messages, - size_t messages_len, - void* user_data -) { - int written_msg = 0; - - for (size_t i = 0; i < e->ev_count; ++i) { - if (e->ev[i].type == EV_ABS) { - if (e->ev[i].code == ABS_MT_TRACKING_ID) { - const in_message_t current_message = { - .type = GAMEPAD_SET_ELEMENT, - .data = { - .gamepad_set = { - .element = GAMEPAD_TOUCHPAD_TOUCH_ACTIVE, - .status = { - .touchpad_active = { - .status = e->ev[i].value, - } - } - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == ABS_MT_POSITION_X) { - const in_message_t current_message = { - .type = GAMEPAD_SET_ELEMENT, - .data = { - .gamepad_set = { - .element = GAMEPAD_TOUCHPAD_X, - .status = { - .touchpad_x = { - .value = e->ev[i].value, - } - } - } - } - }; - - messages[written_msg++] = current_message; - } else if (e->ev[i].code == ABS_MT_POSITION_Y) { - const in_message_t current_message = { - .type = GAMEPAD_SET_ELEMENT, - .data = { - .gamepad_set = { - .element = GAMEPAD_TOUCHPAD_Y, - .status = { - .touchpad_y = { - .value = e->ev[i].value, - } - } - } - } - }; - - messages[written_msg++] = current_message; - } - } - } - - return written_msg; -} - -static input_dev_t in_touchscreen_dev = { - .dev_type = input_dev_type_uinput, - .filters = { - .ev = { - .name = "NVTK0603:00 0603:F200" - } - }, - .user_data = NULL, - .map = { - .ev_callbacks = { - .input_map_fn = touchscreen_ev_map, - .timeout_callback = rc71l_timer_touchscreen, - }, - } -}; - -static void rc71l_timer_asus_kbd( - const dev_in_settings_t *const conf, - struct libevdev* evdev, - const char* const timer_name, - uint64_t expired, - void* user_data -) { - -} - static input_dev_t in_asus_kb_1_dev = { .dev_type = input_dev_type_uinput, .filters = { @@ -1123,12 +560,8 @@ static input_dev_t in_asus_kb_1_dev = { .name = "Asus Keyboard" } }, - .user_data = (void*)&asus_userdata, .map = { - .ev_callbacks = { - .input_map_fn = asus_kbd_ev_map, - .timeout_callback = rc71l_timer_asus_kbd, - }, + .ev_input_map_fn = asus_kbd_ev_map, } }; @@ -1139,12 +572,8 @@ static input_dev_t in_asus_kb_2_dev = { .name = "Asus Keyboard" } }, - .user_data = (void*)&asus_userdata, .map = { - .ev_callbacks = { - .input_map_fn = asus_kbd_ev_map, - .timeout_callback = rc71l_timer_asus_kbd, - }, + .ev_input_map_fn = asus_kbd_ev_map, } }; @@ -1155,96 +584,11 @@ static input_dev_t in_asus_kb_3_dev = { .name = "Asus Keyboard" } }, - .user_data = &asus_userdata, .map = { - .ev_callbacks = { - .input_map_fn = asus_kbd_ev_map, - .timeout_callback = rc71l_timer_asus_kbd, - }, + .ev_input_map_fn = asus_kbd_ev_map, } }; -static void rc71l_timer_xbox360( - const dev_in_settings_t *const conf, - struct libevdev* evdev, - const char* const timer_name, - uint64_t expired, - void* user_data -) { - if (strcmp(timer_name, "RC71L_timer") != 0) { - return; - } - - rc71l_xbox360_user_data_t *const xbox360_data = (rc71l_xbox360_user_data_t*)user_data; - - if (conf->rumble_on_mode_switch) { - if (xbox360_data->accounted_mode_switches != xbox360_data->mode_switched) { - const int fd = libevdev_get_fd(evdev); - - xbox360_data->accounted_mode_switches = xbox360_data->mode_switched; - - xbox360_data->mode_switch_rumbling = true; - - // load the new effect data - xbox360_data->mode_switch_rumble_effect.u.rumble.strong_magnitude = 0xFFFF; - xbox360_data->mode_switch_rumble_effect.u.rumble.weak_magnitude = 0xFFFF; - - // upload the new effect to the device - const int effect_upload_res = ioctl(fd, EVIOCSFF, &xbox360_data->mode_switch_rumble_effect); - if (effect_upload_res == 0) { - struct input_event rumble_stop = { - .type = EV_FF, - .code = xbox360_data->mode_switch_rumble_effect.id, - .value = 0, - }; - - const int rumble_stop_res = write(fd, (const void*) &rumble_stop, sizeof(rumble_stop)); - if (rumble_stop_res != sizeof(rumble_stop)) { - fprintf(stderr, "Unable to stop the previous rumble: %d\n", rumble_stop_res); - } - - const struct input_event rumble_play = { - .type = EV_FF, - .code = xbox360_data->mode_switch_rumble_effect.id, - .value = 1, - }; - - const int effect_start_res = write(fd, (const void*)&rumble_play, sizeof(rumble_play)); - if (effect_start_res != sizeof(rumble_play)) { - fprintf(stderr, "Unable to write input event starting the mode-switch rumble: %d\n", effect_start_res); - } - } else { - fprintf(stderr, "Unable to update force-feedback effect for mode-switch rumble: %d\n", effect_upload_res); - - xbox360_data->mode_switch_rumble_effect.id = -1; - } - } else if (xbox360_data->mode_switch_rumbling) { - const int fd = libevdev_get_fd(evdev); - - xbox360_data->timeout_after_mode_switch++; - - if (xbox360_data->timeout_after_mode_switch >= 10) { - xbox360_data->mode_switch_rumbling = false; - - if (xbox360_data->mode_switch_rumble_effect.id != -1) { - /* - struct input_event rumble_stop = { - .type = EV_FF, - .code = xbox360_data->mode_switch_rumble_effect.id, - .value = 0, - }; - - const int rumble_stop_res = write(fd, (const void*) &rumble_stop, sizeof(rumble_stop)); - if (rumble_stop_res != sizeof(rumble_stop)) { - fprintf(stderr, "Unable to stop the previous rumble: %d\n", rumble_stop_res); - } - */ - } - } - } - } -} - static input_dev_t in_xbox_dev = { .dev_type = input_dev_type_uinput, .filters = { @@ -1252,834 +596,183 @@ static input_dev_t in_xbox_dev = { .name = "Microsoft X-Box 360 pad" } }, - .user_data = &controller_user_data, .map = { - .ev_callbacks = { - .input_map_fn = xbox360_ev_map, - .timeout_callback = rc71l_timer_xbox360, - }, + .ev_input_map_fn = xbox360_ev_map, } }; -static int rc71l_hidraw_map(const dev_in_settings_t *const conf, int hidraw_fd, in_message_t *const messages, size_t messages_len, void* user_data) { - uint8_t data[256]; - const int read_res = read(hidraw_fd, data, sizeof(data)); +static xbox360_settings_t x360_cfg; - if (read_res < 0) { - return -EIO; - } - - //printf("Got %d bytes from Asus MCU\n", read_res); // either 6 or 32 +typedef enum rc71l_platform_mode { + rc71l_platform_mode_hidraw, + rc71l_platform_mode_linux_and_asusctl, +} rc71l_platform_mode_t; - return 0; -} +typedef struct rc71l_platform { + rc71l_platform_mode_t platform_mode; + + union { + dev_hidraw_t *hidraw; + } platform; -static int rc71l_hidraw_rumble(const dev_in_settings_t *const conf, int hidraw_fd, uint8_t left_motor, uint8_t right_motor, void* user_data) { - return 0; -} + unsigned long mode; + unsigned int modes_count; +} rc71l_platform_t; -static int rc71l_hidraw_set_leds_inner(int hidraw_fd, uint8_t r, uint8_t g, uint8_t b) { - const uint8_t colors_buf[] = { - 0x5A, 0xB3, 0x00, ROG_ALLY_MODE_STATIC, r, g, b, 0x00, ROG_ALLY_DIRECTION_RIGHT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; +enum rc71l_leds_mode { + ROG_ALLY_MODE_STATIC = 0, + ROG_ALLY_MODE_BREATHING = 1, + ROG_ALLY_MODE_COLOR_CYCLE = 2, + ROG_ALLY_MODE_RAINBOW = 3, + ROG_ALLY_MODE_STROBING = 10, + ROG_ALLY_MODE_DIRECT = 0xFF, +} rc71l_leds_mode_t; - if (write(hidraw_fd, colors_buf, sizeof(colors_buf)) != 64) { - fprintf(stderr, "Unable to send LEDs color command change (1)\n"); - goto rc71l_hidraw_set_leds_inner_err; - } +enum rc71l_leds_speed { + ROG_ALLY_SPEED_MIN = 0xE1, + ROG_ALLY_SPEED_MED = 0xEB, + ROG_ALLY_SPEED_MAX = 0xF5 +} rc71l_leds_speed_t; - return 0; +enum rc71l_leds_direction { + ROG_ALLY_DIRECTION_RIGHT = 0x00, + ROG_ALLY_DIRECTION_LEFT = 0x01 +} rc71l_leds_direction_t; -rc71l_hidraw_set_leds_inner_err: - return -EIO; -} +static int rc71l_platform_init(void** platform_data) { + int res = -EINVAL; -static int rc71l_hidraw_set_leds(const dev_in_settings_t *const conf, int hidraw_fd, uint8_t r, uint8_t g, uint8_t b, void* user_data) { - rc71l_asus_hidraw_user_data_t *const hidraw_data = (rc71l_asus_hidraw_user_data_t*)user_data; - if (hidraw_data == NULL) { - return -ENOENT; - } + rc71l_platform_t *const platform = malloc(sizeof(rc71l_platform_t)); + if (platform == NULL) { + fprintf(stderr, "Unable to setup platform\n"); + res = -ENOMEM; + goto rc71l_platform_init_err; + } - if ( - (hidraw_data->parent->static_led_color.r == r) && - (hidraw_data->parent->static_led_color.g == g) && - (hidraw_data->parent->static_led_color.b == b) - ) { - return 0; - } + *platform_data = (void*)platform; - hidraw_data->parent->static_led_color.r = r; - hidraw_data->parent->static_led_color.g = g; - hidraw_data->parent->static_led_color.b = b; + res = dev_hidraw_open(&n_key_hidraw_filters, &platform->platform.hidraw); + if (res != 0) { + fprintf(stderr, "Unable to open the ROG ally hidraw main device...\n"); + free(*platform_data); + *platform_data = NULL; + goto rc71l_platform_init_err; + } - const int res = conf->enable_leds_commands ? rc71l_hidraw_set_leds_inner( - hidraw_fd, - hidraw_data->parent->static_led_color.r, - hidraw_data->parent->static_led_color.g, - hidraw_data->parent->static_led_color.b - ) : 0; + uint8_t rdesc[256]; + size_t rdesc_sz; + res = dev_hidraw_get_rdesc(platform->platform.hidraw, rdesc, sizeof(rdesc), &rdesc_sz); + if (res != 0) { + fprintf(stderr, "Unable to get rc71l rdesc\n"); + goto rc71l_platform_init_err; + } - if (res != 0) { - fprintf(stderr, "Error setting leds: %d\n", res); - } + platform->platform_mode = rc71l_platform_mode_hidraw; - return res; -} + const int fd = dev_hidraw_get_fd(platform->platform.hidraw); +/* -#if defined(MANAGE_EPP) -#define PROFILES_COUNT 4 -#else -#define PROFILES_COUNT 3 -#endif + const uint8_t hidraw_buf[] = { + 0x5D, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54, 0x65, 0x63, 0x68, 0x2E, 0x49, 0x6E, 0x63, 0x2E, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; -#if defined(MANAGE_EPP) -static const char* epp[PROFILES_COUNT] = { - "/bin/bash -c 'shopt -s nullglob; echo \"power\" | tee /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference'", - "/bin/bash -c 'shopt -s nullglob; echo \"balance_performance\" | tee /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference'", - "/bin/bash -c 'shopt -s nullglob; echo \"balance_power\" | tee /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference'", - "/bin/bash -c 'shopt -s nullglob; echo \"performance\" | tee /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference'" -}; -#endif + write(fd, hidraw_buf, sizeof(hidraw_buf)); +*/ + for (int i = 0; i < 23; ++i) { + const int write_res = write(fd, &rc71l_mode_switch_commands[0][i][0], 64); + if (write_res != 64) { + fprintf(stderr, "Error writing packet %d/23: %d bytes sent, 64 expected\n", i, write_res); + break; + } + } -static const char* profiles[PROFILES_COUNT] = { - "asusctl profile -P Quiet", - "asusctl profile -P Balanced", -#if defined(MANAGE_EPP) - "asusctl profile -P Performance", -#endif - "asusctl profile -P Performance", -}; - -static const struct { - uint8_t r; - uint8_t g; - uint8_t b; -} colors[PROFILES_COUNT] = { - { - .r = 0x00, // Blue - .g = 0x00, - .b = 0xFF, - }, - { - .r = 0x00, // Green - .g = 0xFF, - .b = 0x00, - }, -#if defined(MANAGE_EPP) - { - .r = 0xFF, // Almost-orange/yellow - .g = 0xBF, - .b = 0x00, - }, -#endif - { - .r = 0xFF, // Red - .g = 0x00, - .b = 0x00, - } -}; - -static void rc71l_hidraw_timer( - const dev_in_settings_t *const conf, - int hidraw_fd, - const char* const timer_name, - uint64_t expired, - void* user_data -) { - // one tick is 60ms, avoid all other timers - if (strcmp(timer_name, "RC71L_timer") != 0) { - return; - } - - rc71l_asus_hidraw_user_data_t *const hidraw_data = (rc71l_asus_hidraw_user_data_t*)user_data; - if (hidraw_data == NULL) { - return; - } - - if (conf->enable_thermal_profiles_switching) { - if (hidraw_data->parent->current_thermal_profile != hidraw_data->parent->next_thermal_profile) { - if (hidraw_data->parent->thermal_profile_expired == 0) { - ++hidraw_data->parent->thermal_profile_expired; - uint64_t thermal_profile_index = hidraw_data->parent->next_thermal_profile % PROFILES_COUNT; - - const int change_thermal_result = system(profiles[thermal_profile_index]); - if (change_thermal_result == 0) { - #if defined(MANAGE_EPP) - const int change_amd_pstate_epp = system(epp[thermal_profile_index]); - if (change_amd_pstate_epp == 0) { - const int leds_set = rc71l_hidraw_set_leds_inner( - hidraw_fd, - colors[thermal_profile_index].r, - colors[thermal_profile_index].g, - colors[thermal_profile_index].b - ); - - if (leds_set != 0) { - fprintf(stderr, "Error setting leds to tell the user about the new profile: %d\n", leds_set); - } - } else { - fprintf( - stderr, - "Error setting the new AMD P-State hint with '%s': %d\n", - epp[thermal_profile_index], - change_amd_pstate_epp - ); - } - #else - const int leds_set = rc71l_hidraw_set_leds_inner( - hidraw_fd, - colors[thermal_profile_index].r, - colors[thermal_profile_index].g, - colors[thermal_profile_index].b - ); - - if (leds_set != 0) { - fprintf(stderr, "Error setting leds to tell the user about the new profile: %d\n", leds_set); - } - #endif - } else { - fprintf( - stderr, - "Error setting the new thermal profile with '%s': %d\n", - profiles[thermal_profile_index], - change_thermal_result - ); - } - } else { - ++hidraw_data->parent->thermal_profile_expired; - - if (hidraw_data->parent->thermal_profile_expired > 18) { - hidraw_data->parent->current_thermal_profile = hidraw_data->parent->next_thermal_profile; - hidraw_data->parent->thermal_profile_expired = 0; - rc71l_hidraw_set_leds_inner( - hidraw_fd, - hidraw_data->parent->static_led_color.r, - hidraw_data->parent->static_led_color.g, - hidraw_data->parent->static_led_color.b - ); - } - } - } - } -} - -static input_dev_t nkey_dev = { - .dev_type = input_dev_type_hidraw, - .filters = { - .hidraw = { - .pid = 0x1abe, - .vid = 0x0b05, - .rdesc_size = 167, // 48 83 167 - } - }, - .user_data = (void*)&hidraw_userdata, - .map = { - .hidraw_callbacks = { - .leds_callback = rc71l_hidraw_set_leds, - .rumble_callback = rc71l_hidraw_rumble, - .map_callback = rc71l_hidraw_map, - .timeout_callback = rc71l_hidraw_timer, - } - } -}; - -static int rc71l_platform_init(const dev_in_settings_t *const conf, void** platform_data) { - int res = -EINVAL; - - rc71l_platform_t *const platform = &hw_platform; - *platform_data = (void*)platform; - - // setup asus keyboard(s) user_data - platform->kbd_user_data->parent = platform; - platform->xbox360_user_data->parent = platform; - platform->timer_data->parent = platform; - platform->kbd_user_data->udev = udev_new(); - platform->hidraw_user_data->parent = platform; - if (platform->kbd_user_data->udev == NULL) { - fprintf(stderr, "Unable to initialize udev\n"); - res = -ENOMEM; - goto rc71l_platform_init_err; - } - - res = 0; - - if (conf->enable_leds_commands) { - char command_str[64] = "\0"; - sprintf( - command_str, - "asusctl led-mode static -c %02X%02X%02X", - platform->static_led_color.r, - platform->static_led_color.g, - platform->static_led_color.b - ); - - const int led_mode_cmd_result = system(command_str); - if (led_mode_cmd_result != 0) { - fprintf( - stderr, - "Error setting led mode to static over asusctl: %d\n", - led_mode_cmd_result - ); - - res = led_mode_cmd_result; - goto rc71l_platform_init_err; - } - - memset(command_str, 0, sizeof(command_str)); - sprintf(command_str, "asusctl -k high"); - - const int led_brightness_cmd_result = system(command_str); - if (led_brightness_cmd_result != 0) { - fprintf( - stderr, - "Error setting led brightness over asusctl: %d\n", - led_brightness_cmd_result - ); - - res = led_brightness_cmd_result; - goto rc71l_platform_init_err; - } - } + printf("ROG Ally platform will be managed over hidraw. I'm sorry fluke.\n"); rc71l_platform_init_err: - return res; + return res; } -static void rc71l_platform_deinit(const dev_in_settings_t *const conf, void** platform_data) { - rc71l_platform_t *const platform = (rc71l_platform_t *)(*platform_data); +static void rc71l_platform_deinit(void** platform_data) { + rc71l_platform_t *const platform = (rc71l_platform_t *)(*platform_data); - if (platform_data != NULL) { - if (platform->kbd_user_data != NULL) { - udev_unref(platform->kbd_user_data->udev); - } - } + if ((platform->platform_mode == rc71l_platform_mode_hidraw) && (platform->platform.hidraw != NULL)) { + dev_hidraw_close(platform->platform.hidraw); + platform->platform.hidraw = NULL; + } - *platform_data = NULL; + free(platform); + *platform_data = NULL; } -static int rc71l_platform_leds(const dev_in_settings_t *const conf, uint8_t r, uint8_t g, uint8_t b, void* platform_data) { - rc71l_platform_t *const platform = (rc71l_platform_t*)platform_data; +static int rc71l_platform_leds(uint8_t r, uint8_t g, uint8_t b, void* platform_data) { + rc71l_platform_t *const platform = (rc71l_platform_t *)platform_data; + if (platform == NULL) { + return -EINVAL; + } - // hidraw is used for now - return 0; + const uint8_t brightness_buf[] = { + 0x5A, 0xBA, 0xC5, 0xC4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + uint8_t colors_buf[] = { + 0x5A, 0xB3, 0x00, ROG_ALLY_MODE_STATIC, r, g, b, 0x00, ROG_ALLY_DIRECTION_RIGHT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +/* + const uint8_t save_mode[] = { + 0x5A, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +*/ + if ((platform->platform_mode == rc71l_platform_mode_hidraw) && (platform->platform.hidraw != NULL)) { + int fd = dev_hidraw_get_fd(platform->platform.hidraw); + + if (write(fd, brightness_buf, sizeof(brightness_buf)) != 64) { + fprintf(stderr, "Unable to send LEDs brightness (1) command change\n"); + goto rc71l_platform_leds_err; + } + + if (write(fd, colors_buf, sizeof(colors_buf)) != 64) { + fprintf(stderr, "Unable to send LEDs color command change (1)\n"); + goto rc71l_platform_leds_err; + } +/* + colors_buf[0x00] = 0x5A; + colors_buf[0x01] = 0xB5; + if (write(fd, colors_buf, sizeof(colors_buf)) != 64) { + fprintf(stderr, "Unable to send LEDs color command change (2)\n"); + goto rc71l_platform_leds_err; + } + + if (write(fd, save_mode, sizeof(save_mode)) != 64) { + fprintf(stderr, "Unable to send LEDs save mode command\n"); + goto rc71l_platform_leds_err; + } +*/ + return 0; + } + +rc71l_platform_leds_err: + return -EINVAL; } - - -typedef struct dev_iio { - char* path; - char* name; - uint32_t flags; - - FILE* accel_x_fd; - FILE* accel_y_fd; - FILE* accel_z_fd; - - double accel_scale_x; - double accel_scale_y; - double accel_scale_z; - - FILE* anglvel_x_fd; - FILE* anglvel_y_fd; - FILE* anglvel_z_fd; - - double anglvel_scale_x; - double anglvel_scale_y; - double anglvel_scale_z; - - double temp_scale; - - double outer_temp_scale; - - double mount_matrix[3][3]; - - double anglvel_sampling_rate_hz; - double accel_sampling_rate_hz; -} dev_old_iio_t; - -static dev_old_iio_t* dev_old_iio_create(const char* path) { - dev_old_iio_t *iio = malloc(sizeof(dev_old_iio_t)); - if (iio == NULL) { - return NULL; - } - - iio->anglvel_x_fd = NULL; - iio->anglvel_y_fd = NULL; - iio->anglvel_z_fd = NULL; - iio->accel_x_fd = NULL; - iio->accel_y_fd = NULL; - iio->accel_z_fd = NULL; - - iio->accel_scale_x = 0.0f; - iio->accel_scale_y = 0.0f; - iio->accel_scale_z = 0.0f; - iio->anglvel_scale_x = 0.0f; - iio->anglvel_scale_y = 0.0f; - iio->anglvel_scale_z = 0.0f; - iio->temp_scale = 0.0f; - - iio->outer_temp_scale = 0.0; - - double mm[3][3] = - // this is the correct matrix: - { - {-1.0, 0.0, 0.0}, - {0.0, 1.0, 0.0}, - {0.0, 0.0, 1.0} - }; - - // store the mount matrix - memcpy(iio->mount_matrix, mm, sizeof(mm)); - - const long path_len = strlen(path) + 1; - iio->path = malloc(path_len); - if (iio->path == NULL) { - fprintf(stderr, "Cannot allocate %ld bytes for device name, device skipped.\n", path_len); - free(iio); - iio = NULL; - goto dev_old_iio_create_err; - } - strcpy(iio->path, path); - - // ============================================= DEVICE NAME ================================================ - iio->name = inline_read_file(iio->path, "/name"); - if (iio->name == NULL) { - fprintf(stderr, "Unable to read iio device name.\n"); - free(iio); - iio = NULL; - goto dev_old_iio_create_err; - } else { - int idx = strlen(iio->name) - 1; - if ((iio->name[idx] == '\n') || ((iio->name[idx] == '\t'))) { - iio->name[idx] = '\0'; - } - } - // ========================================================================================================== - - // ========================================== in_anglvel_scale ============================================== - { - const char* preferred_scale = LSB_PER_RAD_S_2000_DEG_S_STR; - const char *scale_main_file = "/in_anglvel_scale"; - - char* const anglvel_scale = inline_read_file(iio->path, scale_main_file); - if (anglvel_scale != NULL) { - iio->anglvel_scale_x = iio->anglvel_scale_y = iio->anglvel_scale_z = strtod(anglvel_scale, NULL); - free((void*)anglvel_scale); - - if (inline_write_file(iio->path, scale_main_file, preferred_scale, strlen(preferred_scale)) >= 0) { - iio->anglvel_scale_x = iio->anglvel_scale_y = iio->anglvel_scale_z = LSB_PER_RAD_S_2000_DEG_S; - printf("anglvel scale changed to %f for device %s\n", iio->anglvel_scale_x, iio->name); - } else { - fprintf(stderr, "Unable to set preferred in_anglvel_scale for device %s.\n", iio->name); - } - } else { - // TODO: what about if those are split in in_anglvel_{x,y,z}_scale? - fprintf(stderr, "Unable to read in_anglvel_scale from path %s%s.\n", iio->path, scale_main_file); - - free(iio); - iio = NULL; - goto dev_old_iio_create_err; - } - } - // ========================================================================================================== - - // =========================================== in_accel_scale =============================================== - { - const char* preferred_scale = LSB_PER_16G_STR; - const char *scale_main_file = "/in_accel_scale"; - - char* const accel_scale = inline_read_file(iio->path, scale_main_file); - if (accel_scale != NULL) { - iio->accel_scale_x = iio->accel_scale_y = iio->accel_scale_z = strtod(accel_scale, NULL); - free((void*)accel_scale); - - if (inline_write_file(iio->path, scale_main_file, preferred_scale, strlen(preferred_scale)) >= 0) { - iio->accel_scale_x = iio->accel_scale_y = iio->accel_scale_z = LSB_PER_16G; - printf("accel scale changed to %f for device %s\n", iio->accel_scale_x, iio->name); - } else { - fprintf(stderr, "Unable to set preferred in_accel_scale for device %s.\n", iio->name); - } - } else { - // TODO: what about if those are plit in in_accel_{x,y,z}_scale? - fprintf(stderr, "Unable to read in_accel_scale file from path %s%s.\n", iio->path, scale_main_file); - - free(iio); - iio = NULL; - goto dev_old_iio_create_err; - } - } - // ========================================================================================================== - - // ============================================= temp_scale ================================================= - { - char* const accel_scale = inline_read_file(iio->path, "/in_temp_scale"); - if (accel_scale != NULL) { - iio->temp_scale = strtod(accel_scale, NULL); - free((void*)accel_scale); - } else { - fprintf(stderr, "Unable to read in_accel_scale file from path %s%s.\n", iio->path, "/in_accel_scale"); - - free(iio); - iio = NULL; - goto dev_old_iio_create_err; - } - } - // ========================================================================================================== - - // ======================================= anglvel_sampling_rate_hz ========================================== - { - const char *const avail_freq = inline_read_file(iio->path, "/in_anglvel_sampling_frequency_available"); - - const char* preferred_scale = PREFERRED_SAMPLING_FREQ_STR; - double new_freq = PREFERRED_SAMPLING_FREQ; - if ((avail_freq != NULL) && (strstr(avail_freq, "1600.0"))) { - preferred_scale = PREFERRED_SAMPLING_FREQ_HIGH_HZ_STR; - new_freq = PREFERRED_SAMPLING_FREQ_HIGH_HZ; - } - - const char *scale_main_file = "/in_anglvel_sampling_frequency"; - - char* const accel_scale = inline_read_file(iio->path, scale_main_file); - if (accel_scale != NULL) { - iio->anglvel_sampling_rate_hz = strtod(accel_scale, NULL); - free((void*)accel_scale); - - if (inline_write_file(iio->path, scale_main_file, preferred_scale, strlen(preferred_scale)) >= 0) { - iio->anglvel_sampling_rate_hz = new_freq; - printf("anglvel sampling rate changed to %f for device %s\n", iio->accel_scale_x, iio->name); - } else { - fprintf(stderr, "Unable to set preferred in_anglvel_sampling_frequency for device %s.\n", iio->name); - } - } else { - fprintf(stderr, "Unable to read in_anglvel_sampling_frequency file from path %s%s.\n", iio->path, scale_main_file); - - free(iio); - iio = NULL; - goto dev_old_iio_create_err; - } - } - // ========================================================================================================== - - // ======================================= accel_sampling_rate_hz ========================================== - { - const char *const avail_freq = inline_read_file(iio->path, "/in_accel_sampling_frequency_available"); - - const char* preferred_scale = PREFERRED_SAMPLING_FREQ_STR; - double new_freq = PREFERRED_SAMPLING_FREQ; - if ((avail_freq != NULL) && (strstr(avail_freq, "1600.0"))) { - preferred_scale = PREFERRED_SAMPLING_FREQ_HIGH_HZ_STR; - new_freq = PREFERRED_SAMPLING_FREQ_HIGH_HZ; - } - - const char *scale_main_file = "/in_accel_sampling_frequency"; - - char* const accel_scale = inline_read_file(iio->path, scale_main_file); - if (accel_scale != NULL) { - iio->accel_sampling_rate_hz = strtod(accel_scale, NULL); - free((void*)accel_scale); - - if (inline_write_file(iio->path, scale_main_file, preferred_scale, strlen(preferred_scale)) >= 0) { - iio->accel_sampling_rate_hz = new_freq; - printf("accel sampling rate changed to %f for device %s\n", iio->accel_scale_x, iio->name); - } else { - fprintf(stderr, "Unable to set preferred in_accel_sampling_frequency for device %s.\n", iio->name); - } - } else { - fprintf(stderr, "Unable to read in_accel_sampling_frequency file from path %s%s.\n", iio->path, scale_main_file); - - free(iio); - iio = NULL; - goto dev_old_iio_create_err; - } - } - // ========================================================================================================== - - const size_t tmp_sz = path_len + 128 + 1; - char* const tmp = malloc(tmp_sz); - - memset(tmp, 0, tmp_sz); - strcat(tmp, iio->path); - strcat(tmp, "/in_accel_x_raw"); - iio->accel_x_fd = fopen(tmp, "r"); - - memset(tmp, 0, tmp_sz); - strcat(tmp, iio->path); - strcat(tmp, "/in_accel_y_raw"); - iio->accel_y_fd = fopen(tmp, "r"); - - memset(tmp, 0, tmp_sz); - strcat(tmp, iio->path); - strcat(tmp, "/in_accel_z_raw"); - iio->accel_z_fd = fopen(tmp, "r"); - - memset(tmp, 0, tmp_sz); - strcat(tmp, iio->path); - strcat(tmp, "/in_anglvel_x_raw"); - iio->anglvel_x_fd = fopen(tmp, "r"); - - memset(tmp, 0, tmp_sz); - strcat(tmp, iio->path); - strcat(tmp, "/in_anglvel_y_raw"); - iio->anglvel_y_fd = fopen(tmp, "r"); - - memset(tmp, 0, tmp_sz); - strcat(tmp, iio->path); - strcat(tmp, "/in_anglvel_z_raw"); - iio->anglvel_z_fd = fopen(tmp, "r"); - - free(tmp); - - printf( - "anglvel scale: x=%f, y=%f, z=%f | accel scale: x=%f, y=%f, z=%f\n", - iio->anglvel_scale_x, - iio->anglvel_scale_y, - iio->anglvel_scale_z, - iio->accel_scale_x, - iio->accel_scale_y, - iio->accel_scale_z - ); - - // give time to change the scale - sleep(4); - -dev_old_iio_create_err: - return iio; -} - -static void dev_old_iio_destroy(dev_old_iio_t* iio) { - fclose(iio->accel_x_fd); - fclose(iio->accel_y_fd); - fclose(iio->accel_z_fd); - fclose(iio->anglvel_x_fd); - fclose(iio->anglvel_y_fd); - fclose(iio->anglvel_z_fd); - free(iio->name); - free(iio->path); - free(iio); -} - -const char* dev_old_iio_get_name(const dev_old_iio_t* iio) { - return iio->name; -} - -const char* dev_old_iio_get_path(const dev_old_iio_t* iio) { - return iio->path; -} - -static void multiplyMatrixVector(const double matrix[3][3], const double vector[3], double result[3]) { - result[0] = matrix[0][0] * vector[0] + matrix[1][0] * vector[1] + matrix[2][0] * vector[2]; - result[1] = matrix[0][1] * vector[0] + matrix[1][1] * vector[1] + matrix[2][1] * vector[2]; - result[2] = matrix[0][2] * vector[0] + matrix[1][2] * vector[1] + matrix[2][2] * vector[2]; -} - -int dev_old_iio_read_imu(const dev_old_iio_t *const iio, in_message_t *const messages) { - int res = 0; - - struct timespec tp; - if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) { - perror("Error getting time"); - return res; // Handle the error appropriately in your application - } - - const uint64_t nanoseconds = (tp.tv_sec * 1000000000ULL) + tp.tv_nsec; - - uint16_t accel_x_raw = 0, accel_y_raw = 0, accel_z_raw = 0; - uint16_t gyro_x_raw = 0, gyro_y_raw = 0, gyro_z_raw = 0; - - char tmp[128]; - - - if (iio->accel_x_fd != NULL) { - rewind(iio->accel_x_fd); - memset((void*)&tmp[0], 0, sizeof(tmp)); - const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->accel_x_fd); - if (tmp_read >= 0) { - accel_x_raw = strtol(&tmp[0], NULL, 10); - } else { - fprintf(stderr, "While reading accel(x): %d\n", tmp_read); - goto dev_old_iio_read_imu_err; - } - } - - if (iio->accel_y_fd != NULL) { - rewind(iio->accel_y_fd); - memset((void*)&tmp[0], 0, sizeof(tmp)); - const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->accel_y_fd); - if (tmp_read >= 0) { - accel_y_raw = strtol(&tmp[0], NULL, 10); - } else { - fprintf(stderr, "While reading accel(y): %d\n", tmp_read); - goto dev_old_iio_read_imu_err; - } - } - - if (iio->accel_z_fd != NULL) { - rewind(iio->accel_z_fd); - memset((void*)&tmp[0], 0, sizeof(tmp)); - const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->accel_z_fd); - if (tmp_read >= 0) { - accel_z_raw = strtol(&tmp[0], NULL, 10); - } else { - fprintf(stderr, "While reading accel(z): %d\n", tmp_read); - goto dev_old_iio_read_imu_err; - } - } - - if (iio->anglvel_x_fd != NULL) { - rewind(iio->anglvel_x_fd); - memset((void*)&tmp[0], 0, sizeof(tmp)); - const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->anglvel_x_fd); - if (tmp_read >= 0) { - gyro_x_raw = strtol(&tmp[0], NULL, 10); - } else { - fprintf(stderr, "While reading anglvel(x): %d\n", tmp_read); - goto dev_old_iio_read_imu_err; - } - } - - if (iio->anglvel_y_fd != NULL) { - rewind(iio->anglvel_y_fd); - memset((void*)&tmp[0], 0, sizeof(tmp)); - const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->anglvel_y_fd); - if (tmp_read >= 0) { - gyro_y_raw = strtol(&tmp[0], NULL, 10); - } else { - fprintf(stderr, "While reading anglvel(y): %d\n", tmp_read); - goto dev_old_iio_read_imu_err; - } - } - - if (iio->anglvel_z_fd != NULL) { - rewind(iio->anglvel_z_fd); - memset((void*)&tmp[0], 0, sizeof(tmp)); - const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->anglvel_z_fd); - if (tmp_read >= 0) { - gyro_z_raw = strtol(&tmp[0], NULL, 10); - } else { - fprintf(stderr, "While reading anglvel(z): %d\n", tmp_read); - goto dev_old_iio_read_imu_err; - } - } - - messages[0].type = GAMEPAD_SET_ELEMENT; - messages[0].data.gamepad_set.element = GAMEPAD_ACCELEROMETER; - messages[1].data.gamepad_set.status.accel.sample_timestamp_ns = nanoseconds; - messages[0].data.gamepad_set.status.accel.x = (uint16_t)(-1) * accel_x_raw; - messages[0].data.gamepad_set.status.accel.y = accel_y_raw; - messages[0].data.gamepad_set.status.accel.z = accel_z_raw; - - messages[1].type = GAMEPAD_SET_ELEMENT; - messages[1].data.gamepad_set.element = GAMEPAD_GYROSCOPE; - messages[1].data.gamepad_set.status.gyro.sample_timestamp_ns = nanoseconds; - messages[1].data.gamepad_set.status.gyro.x = (uint16_t)(-1) * gyro_x_raw; - messages[1].data.gamepad_set.status.gyro.y = gyro_y_raw; - messages[1].data.gamepad_set.status.gyro.z = gyro_z_raw; - - res = 2; - -dev_old_iio_read_imu_err: - return res; -} - -typedef struct bmc150_accel_user_data { - dev_old_iio_t *iio; - char* name; - uint64_t errors; -} bmc150_accel_user_data_t; - -static bmc150_accel_user_data_t bmc150_timer_data = { - .iio = NULL, - .name = NULL, - .errors = 0, -}; - -int rc71l_bmc150_accel_timer_map(const dev_in_settings_t *const conf, int timer_fd, uint64_t expirations, in_message_t *const messages, size_t messages_len, void* user_data) { - bmc150_accel_user_data_t *const timer_data = (bmc150_accel_user_data_t*)user_data; - - static const uint64_t max_attempts = 250000000; - - if (timer_data == NULL) { - return 0; - } - - if (timer_data->iio == NULL) { - if (timer_data->errors < max_attempts) { - // try to open the device and give up after some errors - timer_data->iio = dev_old_iio_create(iio_base_path); - - if (timer_data->iio == NULL) { - timer_data->errors++; - - if (timer_data->errors == max_attempts) { - fprintf(stderr, "Max attempts to acquire bmc150 accel driver reached.\n"); - } - } - } - - return 0; - } else { - // read the device and fill data from that - return dev_old_iio_read_imu(timer_data->iio, messages); - } - - return 0; -} - -input_dev_t bmc150_timer_dev = { - .dev_type = input_dev_type_timer, - .filters = { - .timer = { - .name = "RC71L_bmc150-accel_timer", - .ticktime_ms = 0, - .ticktime_ns = 1250000 - } - }, - .user_data = &bmc150_timer_data, - .map = { - .timer_callbacks = { - .map_fn = rc71l_bmc150_accel_timer_map, - } - } -}; - -int rc71l_timer_map(const dev_in_settings_t *const conf, int timer_fd, uint64_t expirations, in_message_t *const messages, size_t messages_len, void* user_data) { - rc71l_timer_user_data_t *const timer_data = (rc71l_timer_user_data_t*)user_data; - rc71l_platform_t *const platform_data = timer_data->parent; - - if (platform_data == NULL) { - return 0; - } - - return 0; -} - -input_dev_t timer_dev = { - .dev_type = input_dev_type_timer, - .filters = { - .timer = { - .name = "RC71L_timer", - .ticktime_ms = 60, - .ticktime_ns = 0, - } - }, - .user_data = &timer_user_data, - .map = { - .timer_callbacks = { - .map_fn = rc71l_timer_map, - } - } -}; - input_dev_composite_t rc71l_composite = { .dev = { &in_xbox_dev, + &in_iio_dev, &in_asus_kb_1_dev, &in_asus_kb_2_dev, &in_asus_kb_3_dev, - &timer_dev, }, .dev_count = 5, .init_fn = rc71l_platform_init, @@ -2087,41 +780,9 @@ input_dev_composite_t rc71l_composite = { .leds_fn = rc71l_platform_leds, }; -input_dev_composite_t* rog_ally_device_def(const dev_in_settings_t *const conf) { - if (conf->enable_imu) { - const char *const avail_freq = inline_read_file(iio_base_path, "/in_accel_sampling_frequency_available"); - if ((avail_freq != NULL) && (strstr(avail_freq, "1600.0"))) { - printf("Using high sampling rate mode"); - bmc150_timer_dev.filters.timer.ticktime_ns = 625000; - } +input_dev_composite_t* rog_ally_device_def(const controller_settings_t *const settings) { + x360_cfg.nintendo_layout = settings->nintendo_layout; - bmc150_timer_data.name = inline_read_file(iio_base_path, "name"); - if ((bmc150_timer_data.name != NULL) && (strcmp(bmc150_timer_data.name, "bmi323"))) { - printf("Old bmc150-accel-i2c for bmi323 device has been selected! Are you running a neptune kernel?\n"); - rc71l_composite.dev[rc71l_composite.dev_count++] = &bmc150_timer_dev; - } else if ((conf->imu_polling_interface)) { - if (bmc150_timer_data.name != NULL) { - printf("Forced polling on a %s, suspend/resume issues?\n", bmc150_timer_data.name); - rc71l_composite.dev[rc71l_composite.dev_count++] = &bmc150_timer_dev; - } - } else { - printf("Using the newer upstreamed bmi323-imu driver\n"); - rc71l_composite.dev[rc71l_composite.dev_count++] = &in_iio_dev; - } - } - - if (conf->touchbar) { - rc71l_composite.dev[rc71l_composite.dev_count++] = &in_touchscreen_dev; - } - - if ((conf->enable_leds_commands) || (conf->enable_thermal_profiles_switching)) { - rc71l_composite.dev[rc71l_composite.dev_count++] = &nkey_dev; - } - - if ((conf->enable_thermal_profiles_switching) && (conf->default_thermal_profile >= 0)) { - hw_platform.current_thermal_profile = 0xFFFFFFFFFFFFFFFF; - hw_platform.next_thermal_profile = conf->default_thermal_profile % PROFILES_COUNT; - } - - return &rc71l_composite; + in_xbox_dev.user_data = (void*)&x360_cfg; + return &rc71l_composite; } diff --git a/rog_ally.h b/rog_ally.h index 9152b22..26af9b0 100644 --- a/rog_ally.h +++ b/rog_ally.h @@ -3,4 +3,4 @@ #include "input_dev.h" #include "settings.h" -input_dev_composite_t* rog_ally_device_def(const dev_in_settings_t *const settings); +input_dev_composite_t* rog_ally_device_def(const controller_settings_t *const settings); diff --git a/rogue-enemy_iio_buffer_off.sh b/rogue-enemy_iio_buffer_off.sh deleted file mode 100644 index c18677c..0000000 --- a/rogue-enemy_iio_buffer_off.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -for i in /sys/bus/iio/devices/* ; do - if [ -d "$i" ]; then - if [ -f "$i/name" ]; then - name=$(cat "$i/name") - if [ "$name" = "bmi323-imu" ]; then - # bind fake hrtimer to to the iio device - echo "void" > "$i/trigger/current_trigger" - - # enable the buffer - echo 0 > "$i/buffer0/enable" - - echo "bmi323-imu buffer started" - fi - fi - fi -done diff --git a/rogue-enemy_iio_buffer_on.sh b/rogue-enemy_iio_buffer_on.sh deleted file mode 100644 index b86c376..0000000 --- a/rogue-enemy_iio_buffer_on.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash -modprobe industrialio-sw-trigger -modprobe iio-trig-sysfs -modprobe iio-trig-hrtimer - -# hrtimer -if [ ! -d "/home/config" ]; then - mkdir -p /home/config -fi - -mount -t configfs none /home/config -mkdir -p /home/config/iio/triggers/hrtimer/rogue - -# set sampling frequency for rogue -for i in /sys/bus/iio/devices/* ; do - if [ -d "$i" ]; then - if [ -f "$i/name" ]; then - name=$(cat "$i/name") - if [ "$name" = "rogue" ]; then - echo "1600" > "$i/sampling_frequency" - fi - fi - fi -done - -# set the gyroscope -for i in /sys/bus/iio/devices/* ; do - if [ -d "$i" ]; then - if [ -f "$i/name" ]; then - name=$(cat "$i/name") - if [ "$name" = "bmi323-imu" ]; then - - # change chip sampling frequency - echo "1600.000000" > "$i/in_accel_sampling_frequency" - echo "1600.000000" > "$i/in_anglvel_sampling_frequency" - - # enable accel data acquisition - echo 1 > "$i/scan_elements/in_accel_x_en" - echo 1 > "$i/scan_elements/in_accel_y_en" - echo 1 > "$i/scan_elements/in_accel_z_en" - - # enable gyroscope data acquisition - echo 1 > "$i/scan_elements/in_anglvel_x_en" - echo 1 > "$i/scan_elements/in_anglvel_y_en" - echo 1 > "$i/scan_elements/in_anglvel_z_en" - - # enable timestamp reporting - echo 1 > "$i/scan_elements/in_timestamp_en" - - # bind rogue hrtimer to to the iio device - echo "rogue" > "$i/trigger/current_trigger" - - # enable the buffer - echo 1 > "$i/buffer0/enable" - - echo "bmi323-imu buffer started" - fi - fi - fi -done diff --git a/rogue_enemy.c b/rogue_enemy.c index 4f7fe04..218b4ff 100644 --- a/rogue_enemy.c +++ b/rogue_enemy.c @@ -5,124 +5,3 @@ int32_t div_round_closest(int32_t x, int32_t divisor) { const int32_t __d = divisor; return ((__x) > 0) == ((__d) > 0) ? (((__x) + ((__d) / 2)) / (__d)) : (((__x) - ((__d) / 2)) / (__d)); } - -int64_t div_round_closest_i64(int64_t x, int64_t divisor) { - const int64_t __x = x; - const int64_t __d = divisor; - return ((__x) > 0) == ((__d) > 0) ? (((__x) + ((__d) / 2)) / (__d)) : (((__x) - ((__d) / 2)) / (__d)); -} - -int64_t min_max_clamp(int64_t value, int64_t min, int64_t max) { - if (value <= min) { - return min; - } else if (value >= max) { - return max; - } - - return value; -} - -int64_t absolute_value(int64_t value) { - if (value < 0) { - return (int64_t)-1 * value; - } - - return value; -} - -ssize_t dmi_board_name(char *const buf, size_t buf_len) { -int dmi_name_fd = open("/sys/class/dmi/id/board_name", O_RDONLY | O_NONBLOCK); - if (dmi_name_fd < 0) { - return -1; - } - - memset(buf, 0, buf_len); - const ssize_t ret = read(dmi_name_fd, buf, buf_len); - close(dmi_name_fd); - - return ret; -} - -char* inline_read_file(const char* base_path, const char *file) { - char* res = NULL; - char* fdir = NULL; - long len = 0; - - len = strlen(base_path) + strlen(file) + 1; - fdir = malloc(len); - if (fdir == NULL) { - fprintf(stderr, "Cannot allocate %ld bytes for device path, device skipped.\n", len); - goto read_file_err; - } - strcpy(fdir, base_path); - strcat(fdir, file); - - if (access(fdir, F_OK) == 0) { - FILE* fp = fopen(fdir, "r"); - if (fp != NULL) { - fseek(fp, 0L, SEEK_END); - len = ftell(fp); - rewind(fp); - - len += 1; - res = malloc(len); - if (res != NULL) { - unsigned long read_bytes = fread(res, 1, len, fp); - printf("Read %lu bytes from file %s\n", read_bytes, fdir); - } else { - fprintf(stderr, "Cannot allocate %ld bytes for %s content.\n", len, fdir); - } - - fclose(fp); - } else { - fprintf(stderr, "Cannot open file %s.\n", fdir); - } - } else { - fprintf(stderr, "File %s does not exists.\n", fdir); - } - - free(fdir); - fdir = NULL; - -read_file_err: - return res; -} - -int inline_write_file(const char* base_path, const char *file, const void* buf, size_t buf_sz) { - char* fdir = NULL; - - int res = 0; - - const size_t len = strlen(base_path) + strlen(file) + 1; - fdir = malloc(len); - if (fdir == NULL) { - fprintf(stderr, "Cannot allocate %ld bytes for device path, device skipped.\n", len); - goto inline_write_file_err; - } - strcpy(fdir, base_path); - strcat(fdir, file); - - if (access(fdir, F_OK) == 0) { - FILE* fp = fopen(fdir, "w"); - if (fp != NULL) { - res = fwrite(buf, 1, buf_sz, fp); - if (res >= buf_sz) { - printf("Written %d bytes to file %s\n", res, fdir); - } else { - fprintf(stderr, "Cannot write to %s: %d.\n", fdir, res); - } - - fclose(fp); - } else { - fprintf(stderr, "Cannot open file %s.\n", fdir); - } - } else { - fprintf(stderr, "File %s does not exists.\n", fdir); - } - - free(fdir); - fdir = NULL; - -inline_write_file_err: - return res; -} diff --git a/rogue_enemy.h b/rogue_enemy.h index 3643faf..1e7cfac 100644 --- a/rogue_enemy.h +++ b/rogue_enemy.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -42,22 +41,12 @@ #include -#include - -#include - #define LSB_PER_RAD_S_2000_DEG_S ((double)0.001064724) #define LSB_PER_RAD_S_2000_DEG_S_STR "0.001064724" #define LSB_PER_16G ((double)0.004785) #define LSB_PER_16G_STR "0.004785" -#define PREFERRED_SAMPLING_FREQ ((double)800.000000) -#define PREFERRED_SAMPLING_FREQ_STR "800.000000" - -#define PREFERRED_SAMPLING_FREQ_HIGH_HZ ((double)1600.000000) -#define PREFERRED_SAMPLING_FREQ_HIGH_HZ_STR "1600.000000" - // courtesy of linux kernel #ifndef __packed #define __packed __attribute__((packed)) @@ -65,15 +54,3 @@ // also courtesy of linux kernel int32_t div_round_closest(int32_t x, int32_t divisor); - -int64_t div_round_closest_i64(int64_t x, int64_t divisor); - -int64_t min_max_clamp(int64_t value, int64_t min, int64_t max); - -int64_t absolute_value(int64_t value); - -ssize_t dmi_board_name(char *const buf, size_t buf_len); - -char* inline_read_file(const char* base_path, const char *file); - -int inline_write_file(const char* base_path, const char *file, const void* buf, size_t buf_sz); \ No newline at end of file diff --git a/settings.c b/settings.c index 8db164b..f1fc8a0 100644 --- a/settings.c +++ b/settings.c @@ -2,182 +2,68 @@ #include -void load_in_config(dev_in_settings_t *const out_conf, const char* const filepath) { +void init_config(controller_settings_t *const conf) { + conf->ff_gain = 100; + conf->enable_qam = 0; + conf->nintendo_layout = 0; + conf->gamepad_output_device = 1; + conf->rumble_dedicated_thread = 0; +} + +int fill_config(controller_settings_t *const conf, const char* file) { + int res = 0; + config_t cfg; + config_init(&cfg); - const int config_read_res = config_read_file(&cfg, filepath); + const int config_read_res = config_read_file(&cfg, file); if (config_read_res != CONFIG_TRUE) { fprintf(stderr, "Error in reading config file: %s\n", config_error_text(&cfg)); - goto load_in_config_err; + goto fill_config_err; } int enable_qam; if (config_lookup_bool(&cfg, "enable_qam", &enable_qam) != CONFIG_FALSE) { - out_conf->enable_qam = enable_qam; + conf->enable_qam = enable_qam; } else { fprintf(stderr, "enable_qam (bool) configuration not found. Default value will be used.\n"); } - int rumble_on_mode_switch; - if (config_lookup_bool(&cfg, "rumble_on_mode_switch", &rumble_on_mode_switch) != CONFIG_FALSE) { - out_conf->rumble_on_mode_switch = rumble_on_mode_switch; - } else { - fprintf(stderr, "rumble_on_mode_switch (bool) configuration not found. Default value will be used.\n"); - } - int ff_gain; if (config_lookup_int(&cfg, "ff_gain", &ff_gain) != CONFIG_FALSE) { - if (ff_gain <= 0xFF) { - out_conf->ff_gain = (ff_gain == 0) ? 0x0000 : ((uint16_t)ff_gain << (uint16_t)8) | (uint16_t)0x00FF; + if (ff_gain <= 100) { + conf->ff_gain = (ff_gain == 100) ? 0xFFFF : ((int)0xFFFF / 100) * ff_gain; } else { - fprintf(stderr, "ff_gain (int) must be a number between 0 and 255"); + fprintf(stderr, "ff_gain (int) must be a number between 0 and 100"); } } else { fprintf(stderr, "ff_gain (int) configuration not found. Default value will be used.\n"); } - int m1m2_mode; - if (config_lookup_int(&cfg, "m1m2_mode", &m1m2_mode) != CONFIG_FALSE) { - if (m1m2_mode <= 2) { - out_conf->m1m2_mode = m1m2_mode; - } else { - fprintf(stderr, "m1m2_mode (int) must be a number between 0 and 2"); - } - } else { - fprintf(stderr, "m1m2_mode (int) configuration not found. Default value will be used.\n"); - } - - int touchbar; - if (config_lookup_bool(&cfg, "touchbar", &touchbar) != CONFIG_FALSE) { - out_conf->touchbar = touchbar; - } else { - fprintf(stderr, "touchbar (bool) configuration not found. Default value will be used.\n"); - } - - int enable_thermal_profiles_switching; - if (config_lookup_bool(&cfg, "enable_thermal_profiles_switching", &enable_thermal_profiles_switching) != CONFIG_FALSE) { - out_conf->enable_thermal_profiles_switching = enable_thermal_profiles_switching; - } else { - fprintf(stderr, "enable_thermal_profiles_switching (bool) configuration not found. Default value will be used.\n"); - } - - int default_thermal_profile; - if (config_lookup_int(&cfg, "default_thermal_profile", &default_thermal_profile) != CONFIG_FALSE) { - out_conf->default_thermal_profile = default_thermal_profile; - } else { - fprintf(stderr, "default_thermal_profile (int) configuration not found. Default value will be used.\n"); - } - - int enable_leds_commands; - if (config_lookup_bool(&cfg, "enable_leds_commands", &enable_leds_commands) != CONFIG_FALSE) { - out_conf->enable_leds_commands = enable_leds_commands; - } else { - fprintf(stderr, "enable_leds_commands (bool) configuration not found. Default value will be used.\n"); - } - - int enable_imu; - if (config_lookup_bool(&cfg, "enable_imu", &enable_imu) != CONFIG_FALSE) { - out_conf->enable_imu = enable_imu; - } else { - fprintf(stderr, "enable_imu (bool) configuration not found. Default value will be used.\n"); - } - - int imu_polling_interface; - if (config_lookup_bool(&cfg, "imu_polling_interface", &imu_polling_interface) != CONFIG_FALSE) { - out_conf->imu_polling_interface = imu_polling_interface; - } else { - fprintf(stderr, "imu_polling_interface (bool) configuration not found. Default value will be used.\n"); - } - - config_destroy(&cfg); - -load_in_config_err: - return; -} - -void load_out_config(dev_out_settings_t *const out_conf, const char* const filepath) { - config_t cfg; - config_init(&cfg); - - const int config_read_res = config_read_file(&cfg, filepath); - if (config_read_res != CONFIG_TRUE) { - fprintf(stderr, "Error in reading config file: %s\n", config_error_text(&cfg)); - goto load_out_config_err; - } - int nintendo_layout; if (config_lookup_bool(&cfg, "nintendo_layout", &nintendo_layout) != CONFIG_FALSE) { - out_conf->nintendo_layout = nintendo_layout; + conf->nintendo_layout = nintendo_layout; } else { fprintf(stderr, "nintendo_layout (bool) configuration not found. Default value will be used.\n"); } - int default_gamepad; - if (config_lookup_int(&cfg, "default_gamepad", &default_gamepad) != CONFIG_FALSE) { - out_conf->default_gamepad = default_gamepad % 3; + int gamepad_output_device; + if (config_lookup_int(&cfg, "gamepad_output_device", &gamepad_output_device) != CONFIG_FALSE) { + conf->gamepad_output_device = gamepad_output_device; } else { - fprintf(stderr, "default_gamepad (int) configuration not found. Default value will be used.\n"); + fprintf(stderr, "gamepad_output_device (int) configuration not found. Default value will be used.\n"); } - int gamepad_leds_control; - if (config_lookup_bool(&cfg, "gamepad_leds_control", &gamepad_leds_control) != CONFIG_FALSE) { - out_conf->gamepad_leds_control = gamepad_leds_control; + int rumble_dedicated_thread; + if (config_lookup_bool(&cfg, "rumble_dedicated_thread", &rumble_dedicated_thread) != CONFIG_FALSE) { + conf->rumble_dedicated_thread = rumble_dedicated_thread; } else { - fprintf(stderr, "gamepad_leds_control (bool) configuration not found. Default value will be used.\n"); - } - - int gamepad_rumble_control; - if (config_lookup_bool(&cfg, "gamepad_rumble_control", &gamepad_rumble_control) != CONFIG_FALSE) { - out_conf->gamepad_rumble_control = gamepad_rumble_control; - } else { - fprintf(stderr, "gamepad_rumble_control (bool) configuration not found. Default value will be used.\n"); - } - - int controller_bluetooth; - if (config_lookup_bool(&cfg, "controller_bluetooth", &controller_bluetooth) != CONFIG_FALSE) { - out_conf->controller_bluetooth = controller_bluetooth; - } else { - fprintf(stderr, "controller_bluetooth (bool) configuration not found. Default value will be used.\n"); - } - - int dualsense_edge; - if (config_lookup_bool(&cfg, "dualsense_edge", &dualsense_edge) != CONFIG_FALSE) { - out_conf->dualsense_edge = dualsense_edge; - } else { - fprintf(stderr, "dualsense_edge (bool) configuration not found. Default value will be used.\n"); - } - - int swap_y_z; - if (config_lookup_bool(&cfg, "swap_y_z", &swap_y_z) != CONFIG_FALSE) { - out_conf->swap_y_z = swap_y_z; - } else { - fprintf(stderr, "swap_y_z (bool) configuration not found. Default value will be used.\n"); - } - - int invert_x; - if (config_lookup_bool(&cfg, "invert_x", &invert_x) != CONFIG_FALSE) { - out_conf->invert_x = invert_x; - } else { - fprintf(stderr, "invert_x (bool) configuration not found. Default value will be used.\n"); - } - - int gyro_to_analog_activation_treshold; - if (config_lookup_int(&cfg, "gyro_to_analog_activation_treshold", &gyro_to_analog_activation_treshold) != CONFIG_FALSE) { - out_conf->gyro_to_analog_activation_treshold = gyro_to_analog_activation_treshold; - } else { - fprintf(stderr, "gyro_to_analog_activation_treshold (int) configuration not found. Default value will be used.\n"); - } - - int gyro_to_analog_mapping; - if (config_lookup_int(&cfg, "gyro_to_analog_mapping", &gyro_to_analog_mapping) != CONFIG_FALSE) { - out_conf->gyro_to_analog_mapping = gyro_to_analog_mapping == 0 ? 1 : gyro_to_analog_mapping; - } else { - fprintf(stderr, "gyro_to_analog_mapping (int) configuration not found. Default value will be used.\n"); + fprintf(stderr, "rumble_dedicated_thread (bool) configuration not found. Default value will be used.\n"); } config_destroy(&cfg); -load_out_config_err: - return; +fill_config_err: + return res; } diff --git a/settings.h b/settings.h index 867a831..517ef82 100644 --- a/settings.h +++ b/settings.h @@ -2,32 +2,22 @@ #include "rogue_enemy.h" -typedef struct dev_in_settings { - bool enable_qam; - bool rumble_on_mode_switch; +typedef struct controller_settings { uint16_t ff_gain; - uint8_t m1m2_mode; - bool touchbar; - bool enable_thermal_profiles_switching; - int default_thermal_profile; - bool enable_leds_commands; - bool enable_imu; - bool imu_polling_interface; -} dev_in_settings_t; + int enable_qam; + int nintendo_layout; -void load_in_config(dev_in_settings_t *const out_conf, const char* const filepath); + /** + * 0 is virtual evdev + * 1 is DualSense + * 2 is DualShock + * 3 is Xbox one + */ + int gamepad_output_device; -typedef struct dev_out_settings { - bool nintendo_layout; - uint8_t default_gamepad; - bool gamepad_leds_control; - bool gamepad_rumble_control; - bool controller_bluetooth; - bool dualsense_edge; - bool swap_y_z; - bool invert_x; - int gyro_to_analog_activation_treshold; - int gyro_to_analog_mapping; -} dev_out_settings_t; + int rumble_dedicated_thread; +} controller_settings_t; -void load_out_config(dev_out_settings_t *const out_conf, const char* const filepath); \ No newline at end of file +void init_config(controller_settings_t *const conf); + +int fill_config(controller_settings_t *const conf, const char* file); diff --git a/stray_ally.c b/stray_ally.c index dd39718..8020d5b 100644 --- a/stray_ally.c +++ b/stray_ally.c @@ -7,33 +7,18 @@ #include "dev_out.h" #include "settings.h" -#include +#include "rog_ally.h" +#include "legion_go.h" static const char* configuration_file = "/etc/ROGueENEMY/config.cfg"; -int main(int argc, char ** argv) { - // Lock all current and future pages from preventing of being paged to swap - const int lockall_res = mlockall( MCL_CURRENT | MCL_FUTURE ); - if (lockall_res) { - fprintf(stderr, "mlockall failed: %d", lockall_res); - } +controller_settings_t settings; +int main(int argc, char ** argv) { int ret = 0; - dev_out_settings_t out_settings = { - .default_gamepad = 0, - .nintendo_layout = false, - .gamepad_leds_control = true, - .gamepad_rumble_control = true, - .controller_bluetooth = false, - .dualsense_edge = false, - .swap_y_z = false, - .invert_x = false, - .gyro_to_analog_activation_treshold = 16, - .gyro_to_analog_mapping = 4, - }; - - load_out_config(&out_settings, configuration_file); + init_config(&settings); + fill_config(&settings, configuration_file); // Create a signal set containing only SIGTERM sigset_t mask; @@ -65,49 +50,11 @@ int main(int argc, char ** argv) { } } }, - .settings = out_settings, + .gamepad = GAMEPAD_DUALSENSE, }; - load_out_config(&dev_out_thread_data.settings, configuration_file); - - // Initialize pthread attributes (default values) - struct sched_param param; - pthread_attr_t attr; - ret = pthread_attr_init(&attr); - if (ret) { - printf("init pthread attributes failed\n"); - goto main_err; - } - - // Set a specific stack size - ret = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 8192); - if (ret) { - printf("pthread setstacksize failed\n"); - goto main_err; - } - - // Set scheduler policy and priority of pthread - ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO); - if (ret) { - printf("pthread setschedpolicy failed\n"); - goto main_err; - } - param.sched_priority = 80; - ret = pthread_attr_setschedparam(&attr, ¶m); - if (ret) { - printf("pthread setschedparam failed\n"); - goto main_err; - } - - // Use scheduling parameters of attr - ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); - if (ret) { - printf("pthread setinheritsched failed\n"); - goto main_err; - } - pthread_t dev_out_thread; - const int dev_out_thread_creation = pthread_create(&dev_out_thread, &attr, dev_out_thread_func, (void*)(&dev_out_thread_data)); + const int dev_out_thread_creation = pthread_create(&dev_out_thread, NULL, dev_out_thread_func, (void*)(&dev_out_thread_data)); if (dev_out_thread_creation != 0) { fprintf(stderr, "Error creating dev_out thread: %d\n", dev_out_thread_creation); ret = -1; @@ -124,7 +71,7 @@ int main(int argc, char ** argv) { int sd=-1; struct sockaddr_un serveraddr; do { - sd = socket(AF_UNIX, SOCK_STREAM, 0); + sd = socket(AF_UNIX, SOCK_SEQPACKET, 0); if (sd < 0) { fprintf(stderr, "socket() failed"); diff --git a/virt_ds4.c b/virt_ds4.c index 3ff8b3c..b615aaa 100644 --- a/virt_ds4.c +++ b/virt_ds4.c @@ -1,7 +1,12 @@ #include "virt_ds4.h" #include "message.h" +#include #include +#include +#include +#include +#include #define DS4_GYRO_RES_PER_DEG_S 1024 #define DS4_ACC_RES_PER_G 8192 @@ -12,24 +17,6 @@ #define DS4_OUTPUT_VALID_FLAG0_LED 0x02 #define DS4_OUTPUT_VALID_FLAG0_LED_BLINK 0x04 -#define DS4_INPUT_REPORT_USB 0x01 -#define DS4_INPUT_REPORT_USB_SIZE 64 -#define DS4_INPUT_REPORT_BT 0x11 -#define DS4_INPUT_REPORT_BT_SIZE 78 -#define DS4_OUTPUT_REPORT_USB 0x05 -#define DS4_OUTPUT_REPORT_USB_SIZE 32 -#define DS4_OUTPUT_REPORT_BT 0x11 -#define DS4_OUTPUT_REPORT_BT_SIZE 78 - -#define DS4_FEATURE_REPORT_CALIBRATION 0x02 -#define DS4_FEATURE_REPORT_CALIBRATION_SIZE 37 -#define DS4_FEATURE_REPORT_CALIBRATION_BT 0x05 -#define DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE 41 -#define DS4_FEATURE_REPORT_FIRMWARE_INFO 0xa3 -#define DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE 49 -#define DS4_FEATURE_REPORT_PAIRING_INFO 0x12 -#define DS4_FEATURE_REPORT_PAIRING_INFO_SIZE 16 - static const uint16_t gyro_pitch_bias = 0xfff9; static const uint16_t gyro_yaw_bias = 0x0009; static const uint16_t gyro_roll_bias = 0xfff9; @@ -50,17 +37,6 @@ static const uint16_t acc_z_minus = 0xe086; static const char* path = "/dev/uhid"; -/* Seed values for DualShock4 / DualSense CRC32 for different report types. */ -static uint8_t PS_INPUT_CRC32_SEED = 0xA1; -static uint8_t PS_OUTPUT_CRC32_SEED = 0xA2; -static uint8_t PS_FEATURE_CRC32_SEED = 0xA3; - -static uint32_t crc32_le(uint32_t crc_initial, const uint8_t *const buf, size_t len) { - return crc32(crc_initial ^ 0xffffffff, buf, len) ^ 0xffffffff; -} - -static const uint8_t MAC_ADDR[] = { 0xf2, 0xa5, 0x71, 0x68, 0xaf, 0xdc }; - static unsigned char rdesc[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x05, /* Usage (Gamepad), */ @@ -315,37 +291,6 @@ static unsigned char rdesc[] = { 0xC0 /* End Collection */ }; -static unsigned char rdesc_bt[] = { -0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, -0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x04, 0x81, 0x02, 0x09, 0x39, 0x15, 0x00, 0x25, -0x07, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x05, 0x09, 0x19, 0x01, 0x29, 0x0e, 0x15, 0x00, 0x25, -0x01, 0x75, 0x01, 0x95, 0x0e, 0x81, 0x02, 0x75, 0x06, 0x95, 0x01, 0x81, 0x01, 0x05, 0x01, 0x09, -0x33, 0x09, 0x34, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x02, 0x81, 0x02, 0x06, 0x04, -0xff, 0x85, 0x02, 0x09, 0x24, 0x95, 0x24, 0xb1, 0x02, 0x85, 0xa3, 0x09, 0x25, 0x95, 0x30, 0xb1, -0x02, 0x85, 0x05, 0x09, 0x26, 0x95, 0x28, 0xb1, 0x02, 0x85, 0x06, 0x09, 0x27, 0x95, 0x34, 0xb1, -0x02, 0x85, 0x07, 0x09, 0x28, 0x95, 0x30, 0xb1, 0x02, 0x85, 0x08, 0x09, 0x29, 0x95, 0x2f, 0xb1, -0x02, 0x85, 0x09, 0x09, 0x2a, 0x95, 0x13, 0xb1, 0x02, 0x06, 0x03, 0xff, 0x85, 0x03, 0x09, 0x21, -0x95, 0x26, 0xb1, 0x02, 0x85, 0x04, 0x09, 0x22, 0x95, 0x2e, 0xb1, 0x02, 0x85, 0xf0, 0x09, 0x47, -0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf1, 0x09, 0x48, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf2, 0x09, 0x49, -0x95, 0x0f, 0xb1, 0x02, 0x06, 0x00, 0xff, 0x85, 0x11, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, -0x75, 0x08, 0x95, 0x4d, 0x81, 0x02, 0x09, 0x21, 0x91, 0x02, 0x85, 0x12, 0x09, 0x22, 0x95, 0x8d, -0x81, 0x02, 0x09, 0x23, 0x91, 0x02, 0x85, 0x13, 0x09, 0x24, 0x95, 0xcd, 0x81, 0x02, 0x09, 0x25, -0x91, 0x02, 0x85, 0x14, 0x09, 0x26, 0x96, 0x0d, 0x01, 0x81, 0x02, 0x09, 0x27, 0x91, 0x02, 0x85, -0x15, 0x09, 0x28, 0x96, 0x4d, 0x01, 0x81, 0x02, 0x09, 0x29, 0x91, 0x02, 0x85, 0x16, 0x09, 0x2a, -0x96, 0x8d, 0x01, 0x81, 0x02, 0x09, 0x2b, 0x91, 0x02, 0x85, 0x17, 0x09, 0x2c, 0x96, 0xcd, 0x01, -0x81, 0x02, 0x09, 0x2d, 0x91, 0x02, 0x85, 0x18, 0x09, 0x2e, 0x96, 0x0d, 0x02, 0x81, 0x02, 0x09, -0x2f, 0x91, 0x02, 0x85, 0x19, 0x09, 0x30, 0x96, 0x22, 0x02, 0x81, 0x02, 0x09, 0x31, 0x91, 0x02, -0x06, 0x80, 0xff, 0x85, 0x82, 0x09, 0x22, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x83, 0x09, 0x23, 0xb1, -0x02, 0x85, 0x84, 0x09, 0x24, 0xb1, 0x02, 0x85, 0x90, 0x09, 0x30, 0xb1, 0x02, 0x85, 0x91, 0x09, -0x31, 0xb1, 0x02, 0x85, 0x92, 0x09, 0x32, 0xb1, 0x02, 0x85, 0x93, 0x09, 0x33, 0xb1, 0x02, 0x85, -0x94, 0x09, 0x34, 0xb1, 0x02, 0x85, 0xa0, 0x09, 0x40, 0xb1, 0x02, 0x85, 0xa4, 0x09, 0x44, 0xb1, -0x02, 0x85, 0xa7, 0x09, 0x45, 0xb1, 0x02, 0x85, 0xa8, 0x09, 0x45, 0xb1, 0x02, 0x85, 0xa9, 0x09, -0x45, 0xb1, 0x02, 0x85, 0xaa, 0x09, 0x45, 0xb1, 0x02, 0x85, 0xab, 0x09, 0x45, 0xb1, 0x02, 0x85, -0xac, 0x09, 0x45, 0xb1, 0x02, 0x85, 0xad, 0x09, 0x45, 0xb1, 0x02, 0x85, 0xb3, 0x09, 0x45, 0xb1, -0x02, 0x85, 0xb4, 0x09, 0x46, 0xb1, 0x02, 0x85, 0xb5, 0x09, 0x47, 0xb1, 0x02, 0x85, 0xd0, 0x09, -0x40, 0xb1, 0x02, 0x85, 0xd4, 0x09, 0x44, 0xb1, 0x02, 0xc0, 0x00 -}; - static int uhid_write(int fd, const struct uhid_event *ev) { ssize_t ret; @@ -363,25 +308,21 @@ static int uhid_write(int fd, const struct uhid_event *ev) } } -static int create(int fd, bool bluetooth) +static int create(int fd) { struct uhid_event ev; memset(&ev, 0, sizeof(ev)); ev.type = UHID_CREATE; strcpy((char*)ev.u.create.name, "Sony Corp. DualShock 4 [CUH-ZCT2x]"); - ev.u.create.rd_data = bluetooth ? rdesc_bt : rdesc; - ev.u.create.rd_size = bluetooth ? sizeof(rdesc_bt) : sizeof(rdesc); - ev.u.create.bus = bluetooth ? BUS_BLUETOOTH : BUS_USB; + ev.u.create.rd_data = rdesc; + ev.u.create.rd_size = sizeof(rdesc); + ev.u.create.bus = BUS_USB; ev.u.create.vendor = 0x054C; ev.u.create.product = 0x09CC; ev.u.create.version = 0; ev.u.create.country = 0; - sprintf((char*)ev.u.create.uniq, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", - MAC_ADDR[5], MAC_ADDR[4], MAC_ADDR[3], MAC_ADDR[2], MAC_ADDR[1], MAC_ADDR[0] - ); - return uhid_write(fd, &ev); } @@ -429,23 +370,15 @@ static ds4_dpad_status_t ds4_dpad_from_gamepad(uint8_t dpad) { return DPAD_RELEASED; } -int virt_dualshock_init( - virt_dualshock_t *const out_gamepad, - bool bluetooth, - int64_t gyro_to_analog_activation_treshold, - int64_t gyro_to_analog_mapping -) { +int virt_dualshock_init(virt_dualshock_t *const out_gamepad) { int ret = 0; - out_gamepad->gyro_to_analog_activation_treshold = absolute_value(gyro_to_analog_activation_treshold); - out_gamepad->gyro_to_analog_mapping = gyro_to_analog_mapping; out_gamepad->dt_sum = 0; out_gamepad->dt_buffer_current = 0; memset(out_gamepad->dt_buffer, 0, sizeof(out_gamepad->dt_buffer)); out_gamepad->debug = false; out_gamepad->empty_reports = 0; out_gamepad->last_time = 0; - out_gamepad->bluetooth = bluetooth; out_gamepad->fd = open(path, O_RDWR | O_CLOEXEC /* | O_NONBLOCK */); if (out_gamepad->fd < 0) { @@ -454,7 +387,7 @@ int virt_dualshock_init( goto virt_dualshock_init_err; } - ret = create(out_gamepad->fd, out_gamepad->bluetooth); + ret = create(out_gamepad->fd); if (ret) { fprintf(stderr, "Error creating uhid device: %d\n", ret); close(out_gamepad->fd); @@ -519,57 +452,57 @@ int virt_dualshock_event(virt_dualshock_t *const gamepad, gamepad_status_t *cons if (ev.u.output.rtype != UHID_OUTPUT_REPORT) return 0; - if ( - (!gamepad->bluetooth) && (ev.u.output.size != DS4_OUTPUT_REPORT_USB_SIZE) && - (gamepad->bluetooth) && (ev.u.output.size != DS4_OUTPUT_REPORT_BT_SIZE) - ) { - fprintf( - stderr, - "Invalid data length: got %d, expected %d\n", - (int)ev.u.output.size, - (gamepad->bluetooth) ? DS4_OUTPUT_REPORT_BT_SIZE : DS4_OUTPUT_REPORT_USB_SIZE - ); + /* + if (ds4->update_rumble) { + * Select classic rumble style haptics and enable it. * + common->valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_MOTOR; + common->motor_left = ds4->motor_left; + common->motor_right = ds4->motor_right; + ds4->update_rumble = false; + } + + if (ds4->update_lightbar) { + common->valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_LED; + * Comptabile behavior with hid-sony, which used a dummy global LED to + * allow enabling/disabling the lightbar. The global LED maps to + * lightbar_enabled. + * + common->lightbar_red = ds4->lightbar_enabled ? ds4->lightbar_red : 0; + common->lightbar_green = ds4->lightbar_enabled ? ds4->lightbar_green : 0; + common->lightbar_blue = ds4->lightbar_enabled ? ds4->lightbar_blue : 0; + ds4->update_lightbar = false; + } + + if (ds4->update_lightbar_blink) { + common->valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_LED_BLINK; + common->lightbar_blink_on = ds4->lightbar_blink_on; + common->lightbar_blink_off = ds4->lightbar_blink_off; + ds4->update_lightbar_blink = false; + } + */ + + if (ev.u.output.size != 32) { + fprintf(stderr, "Invalid data length: got %d, expected 32\n", (int)ev.u.output.size); return 0; } // first byte is report-id which is 0x01 - if ( - (!gamepad->bluetooth) && (ev.u.output.data[0] != DS4_OUTPUT_REPORT_USB) && - (gamepad->bluetooth) && ((ev.u.output.data[0] != DS4_OUTPUT_REPORT_BT) && (ev.u.output.data[0] < 0x10)) - ) { - fprintf( - stderr, - "Unrecognised report-id: got 0x%x expected 0x%x\n", - (int)ev.u.output.data[0], - (gamepad->bluetooth) ? DS4_OUTPUT_REPORT_BT : DS4_OUTPUT_REPORT_USB - ); + if (ev.u.output.data[0] != 0x05) { + fprintf(stderr, "Unrecognised report-id: %d\n", (int)ev.u.output.data[0]); return 0; } - // When using bluetooth, the first byte after the reportID is uint8_t seq_tag, - // while the next one is uint8_t tag, following bytes are the same. - size_t offset = 1; - if ((gamepad->bluetooth) && (ev.u.output.data[0] > 0x10)) { - offset = 2; - } else if ((gamepad->bluetooth) && (ev.u.output.data[0] == 0x02)) { - offset = 3; - } else if ((gamepad->bluetooth) && (ev.u.output.data[0] == 0x01)) { - offset = 1; - } - - const uint8_t *const common_report = &ev.u.output.data[offset]; - - const uint8_t valid_flag0 = common_report[0]; - const uint8_t valid_flag1 = common_report[1]; - const uint8_t reserved = common_report[2]; - const uint8_t motor_right = common_report[3]; - const uint8_t motor_left = common_report[4]; - const uint8_t lightbar_red = common_report[5]; - const uint8_t lightbar_green = common_report[6]; - const uint8_t lightbar_blue = common_report[7]; - const uint8_t lightbar_blink_on = common_report[8]; - const uint8_t lightbar_blink_off = common_report[9]; + const uint8_t valid_flag0 = ev.u.output.data[1]; + const uint8_t valid_flag1 = ev.u.output.data[2]; + const uint8_t reserved = ev.u.output.data[3]; + const uint8_t motor_right = ev.u.output.data[4]; + const uint8_t motor_left = ev.u.output.data[5]; + const uint8_t lightbar_red = ev.u.output.data[6]; + const uint8_t lightbar_green = ev.u.output.data[7]; + const uint8_t lightbar_blue = ev.u.output.data[8]; + const uint8_t lightbar_blink_on = ev.u.output.data[9]; + const uint8_t lightbar_blink_off = ev.u.output.data[10]; if ((valid_flag0 & DS4_OUTPUT_VALID_FLAG0_LED)) { out_device_status->leds_colors[0] = lightbar_red; @@ -610,40 +543,32 @@ int virt_dualshock_event(virt_dualshock_t *const gamepad, gamepad_status_t *cons } if (ev.u.get_report.rnum == 18) { - struct uhid_event mac_addr_response = { + const struct uhid_event mac_addr_response = { .type = UHID_GET_REPORT_REPLY, .u = { .get_report_reply = { - .size = DS4_FEATURE_REPORT_PAIRING_INFO_SIZE, + .size = 16, .id = ev.u.get_report.id, .err = 0, .data = { - DS4_FEATURE_REPORT_PAIRING_INFO, - MAC_ADDR[0], MAC_ADDR[1], MAC_ADDR[2], MAC_ADDR[3], MAC_ADDR[4], MAC_ADDR[5], - 0x08, + 0x12, 0xf2, 0xa5, 0x71, 0x68, 0xaf, 0xdc, 0x08, 0x25, 0x00, 0x4c, 0x46, 0x49, 0x0e, 0x41, 0x00 } } } }; - if (gamepad->bluetooth) { - uint32_t crc = crc32_le(0xFFFFFFFFU, (const uint8_t*)&PS_FEATURE_CRC32_SEED, sizeof(PS_FEATURE_CRC32_SEED)); - crc = ~crc32_le(crc, (const Bytef *)&mac_addr_response.u.get_report_reply.data[0], mac_addr_response.u.get_report_reply.size - 4); - memcpy(&mac_addr_response.u.get_report_reply.data[mac_addr_response.u.get_report_reply.size - sizeof(crc)], &crc, sizeof(crc)); - } - uhid_write(gamepad->fd, &mac_addr_response); - } else if (ev.u.get_report.rnum == DS4_FEATURE_REPORT_FIRMWARE_INFO) { - struct uhid_event firmware_info_response = { + } else if (ev.u.get_report.rnum == 0xa3) { + const struct uhid_event firmware_info_response = { .type = UHID_GET_REPORT_REPLY, .u = { .get_report_reply = { - .size = DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE, + .size = 49, .id = ev.u.get_report.id, .err = 0, .data = { - DS4_FEATURE_REPORT_FIRMWARE_INFO, 0x53, 0x65, 0x70, 0x20, 0x32, 0x31, 0x20, + 0xa3, 0x53, 0x65, 0x70, 0x20, 0x32, 0x31, 0x20, 0x32, 0x30, 0x31, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x34, 0x3a, 0x35, 0x30, 0x3a, 0x35, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -655,32 +580,22 @@ int virt_dualshock_event(virt_dualshock_t *const gamepad, gamepad_status_t *cons } }; - if (gamepad->bluetooth) { - uint32_t crc = crc32_le(0xFFFFFFFFU, (const uint8_t*)&PS_FEATURE_CRC32_SEED, sizeof(PS_FEATURE_CRC32_SEED)); - crc = ~crc32_le(crc, (const Bytef *)&firmware_info_response.u.get_report_reply.data[0], firmware_info_response.u.get_report_reply.size - 4); - memcpy(&firmware_info_response.u.get_report_reply.data[firmware_info_response.u.get_report_reply.size - sizeof(crc)], &crc, sizeof(crc)); - } - uhid_write(gamepad->fd, &firmware_info_response); - } else if ( - ((gamepad->bluetooth) && (ev.u.get_report.rnum == DS4_FEATURE_REPORT_CALIBRATION_BT)) || - ((!gamepad->bluetooth) && (ev.u.get_report.rnum == DS4_FEATURE_REPORT_CALIBRATION)) - ) { // dualshock4_get_calibration_data - struct uhid_event calibration_response = { + } else if (ev.u.get_report.rnum == 0x02) { // dualshock4_get_calibration_data + struct uhid_event firmware_info_response = { .type = UHID_GET_REPORT_REPLY, .u = { .get_report_reply = { - .size = gamepad->bluetooth ? DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE : DS4_FEATURE_REPORT_CALIBRATION_SIZE, + .size = 37, .id = ev.u.get_report.id, .err = 0, .data = { - gamepad->bluetooth ? DS4_FEATURE_REPORT_CALIBRATION_BT : DS4_FEATURE_REPORT_CALIBRATION, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, + } } } @@ -690,31 +605,25 @@ int virt_dualshock_event(virt_dualshock_t *const gamepad, gamepad_status_t *cons // speed_2x = speed_2x*DS4_GYRO_RES_PER_DEG_S; calculated by the kernel will be 1080. // As a consequence sens_numer (for every axis) is 1080*1024. // that number will be 1105920 - memcpy((void*)&calibration_response.u.get_report_reply.data[1], (const void*)&gyro_pitch_bias, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[3], (const void*)&gyro_yaw_bias, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[5], (const void*)&gyro_roll_bias, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[7], (const void*)&gyro_pitch_plus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[9], (const void*)&gyro_pitch_minus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[11], (const void*)&gyro_yaw_plus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[13], (const void*)&gyro_yaw_minus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[15], (const void*)&gyro_roll_plus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[17], (const void*)&gyro_roll_minus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[19], (const void*)&gyro_speed_plus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[21], (const void*)&gyro_speed_minus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[23], (const void*)&acc_x_plus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[25], (const void*)&acc_x_minus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[27], (const void*)&acc_y_plus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[29], (const void*)&acc_y_minus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[31], (const void*)&acc_z_plus, sizeof(int16_t)); - memcpy((void*)&calibration_response.u.get_report_reply.data[33], (const void*)&acc_z_minus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[1], (const void*)&gyro_pitch_bias, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[3], (const void*)&gyro_yaw_bias, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[5], (const void*)&gyro_roll_bias, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[7], (const void*)&gyro_pitch_plus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[9], (const void*)&gyro_pitch_minus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[11], (const void*)&gyro_yaw_plus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[13], (const void*)&gyro_yaw_minus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[15], (const void*)&gyro_roll_plus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[17], (const void*)&gyro_roll_minus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[19], (const void*)&gyro_speed_plus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[21], (const void*)&gyro_speed_minus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[23], (const void*)&acc_x_plus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[25], (const void*)&acc_x_minus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[27], (const void*)&acc_y_plus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[29], (const void*)&acc_y_minus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[31], (const void*)&acc_z_plus, sizeof(int16_t)); + memcpy((void*)&firmware_info_response.u.get_report_reply.data[33], (const void*)&acc_z_minus, sizeof(int16_t)); - if (gamepad->bluetooth) { - uint32_t crc = crc32_le(0xFFFFFFFFU, (const uint8_t*)&PS_FEATURE_CRC32_SEED, sizeof(PS_FEATURE_CRC32_SEED)); - crc = ~crc32_le(crc, (const Bytef *)&calibration_response.u.get_report_reply.data[0], calibration_response.u.get_report_reply.size - 4); - memcpy(&calibration_response.u.get_report_reply.data[calibration_response.u.get_report_reply.size - sizeof(crc)], &crc, sizeof(crc)); - } - - uhid_write(gamepad->fd, &calibration_response); + uhid_write(gamepad->fd, &firmware_info_response); } break; @@ -733,9 +642,9 @@ void virt_dualshock_close(virt_dualshock_t *const out_gamepad) { * This function arranges HID packets as described on https://www.psdevwiki.com/ps4/DS4-USB */ void virt_dualshock_compose(virt_dualshock_t *const gamepad, gamepad_status_t *const in_device_status, uint8_t *const out_buf) { - const int64_t time_us = in_device_status->last_gyro_motion_timestamp_ns / (int64_t)1000; + const int64_t time_us = in_device_status->last_gyro_motion_time.tv_sec * 1000000 + in_device_status->last_gyro_motion_time.tv_usec; - const int64_t delta_time = time_us - gamepad->last_time; + const int delta_time = time_us - gamepad->last_time; gamepad->last_time = time_us; // find the average Δt in the last 30 non-zero inputs; @@ -786,82 +695,78 @@ void virt_dualshock_compose(virt_dualshock_t *const gamepad, gamepad_status_t *c * * as we know sens_numer is 0, hence calib_data is zero. */ + /* + const int16_t g_x = ((in_device_status->gyro[0]) * ((double)(180.0)/(double)(M_PI))) / (double)DS4_GYRO_RES_PER_DEG_S; + const int16_t g_y = ((in_device_status->gyro[1]) * ((double)(180.0)/(double)(M_PI))) / (double)DS4_GYRO_RES_PER_DEG_S; + const int16_t g_z = ((in_device_status->gyro[2]) * ((double)(180.0)/(double)(M_PI))) / (double)DS4_GYRO_RES_PER_DEG_S; + const int16_t a_x = ((in_device_status->accel[0]) / ((double)9.8)) / (double)DS4_ACC_RES_PER_G; // TODO: IDK how to test... + const int16_t a_y = ((in_device_status->accel[1]) / ((double)9.8)) / (double)DS4_ACC_RES_PER_G; // TODO: IDK how to test... + const int16_t a_z = ((in_device_status->accel[2]) / ((double)9.8)) / (double)DS4_ACC_RES_PER_G; // TODO: IDK how to test... + */ + + /* + const int16_t g_x = (in_device_status->gyro[0]) / LSB_PER_RAD_S_2000_DEG_S; + const int16_t g_y = (in_device_status->gyro[1]) / LSB_PER_RAD_S_2000_DEG_S; + const int16_t g_z = (in_device_status->gyro[2]) / LSB_PER_RAD_S_2000_DEG_S; + const int16_t a_x = (in_device_status->accel[0]) / LSB_PER_16G; // TODO: IDK how to test... + const int16_t a_y = (in_device_status->accel[1]) / LSB_PER_16G; // TODO: IDK how to test... + const int16_t a_z = (in_device_status->accel[2]) / LSB_PER_16G; // TODO: IDK how to test... + */ const int16_t g_x = in_device_status->raw_gyro[0]; - const int16_t g_y = in_device_status->raw_gyro[1]; - const int16_t g_z = in_device_status->raw_gyro[2]; + const int16_t g_y = (int16_t)(-1) * in_device_status->raw_gyro[1]; // Swap Y and Z + const int16_t g_z = (int16_t)(-1) * in_device_status->raw_gyro[2]; // Swap Y and Z const int16_t a_x = in_device_status->raw_accel[0]; - const int16_t a_y = in_device_status->raw_accel[1]; - const int16_t a_z = in_device_status->raw_accel[2]; + const int16_t a_y = (int16_t)(-1) * in_device_status->raw_accel[1]; // Swap Y and Z + const int16_t a_z = (int16_t)(-1) * in_device_status->raw_accel[2]; // Swap Y and Z - const int64_t contrib_x = ((int64_t)g_y / (int64_t)gamepad->gyro_to_analog_mapping); - const int64_t contrib_y = ((int64_t)g_x / (int64_t)gamepad->gyro_to_analog_mapping); - - out_buf[0] = gamepad->bluetooth ? DS4_INPUT_REPORT_BT : DS4_INPUT_REPORT_USB; // [00] report ID (0x01) - - uint8_t *const out_shifted_buf = gamepad->bluetooth ? &out_buf[2] : &out_buf[0]; - - out_shifted_buf[1] = ((uint64_t)((int64_t)in_device_status->joystick_positions[0][0] + (int64_t)32768) >> (uint64_t)8); // L stick, X axis - out_shifted_buf[2] = ((uint64_t)((int64_t)in_device_status->joystick_positions[0][1] + (int64_t)32768) >> (uint64_t)8); // L stick, Y axis - out_shifted_buf[3] = ((uint64_t)((int64_t)in_device_status->joystick_positions[1][0] + (int64_t)32768) >> (uint64_t)8); // R stick, X axis - out_shifted_buf[4] = ((uint64_t)((int64_t)in_device_status->joystick_positions[1][1] + (int64_t)32768) >> (uint64_t)8); // R stick, Y axis - out_shifted_buf[5] = + out_buf[0] = 0x01; // [00] report ID (0x01) + out_buf[1] = ((uint64_t)((int64_t)in_device_status->joystick_positions[0][0] + (int64_t)32768) >> (uint64_t)8); // L stick, X axis + out_buf[2] = ((uint64_t)((int64_t)in_device_status->joystick_positions[0][1] + (int64_t)32768) >> (uint64_t)8); // L stick, Y axis + out_buf[3] = ((uint64_t)((int64_t)in_device_status->joystick_positions[1][0] + (int64_t)32768) >> (uint64_t)8); // R stick, X axis + out_buf[4] = ((uint64_t)((int64_t)in_device_status->joystick_positions[1][1] + (int64_t)32768) >> (uint64_t)8); // R stick, Y axis + out_buf[5] = (in_device_status->triangle ? 0x80 : 0x00) | (in_device_status->circle ? 0x40 : 0x00) | (in_device_status->cross ? 0x20 : 0x00) | (in_device_status->square ? 0x10 : 0x00) | (uint8_t)ds4_dpad_from_gamepad(in_device_status->dpad); - out_shifted_buf[6] = + out_buf[6] = (in_device_status->r3 ? 0x80 : 0x00) | (in_device_status->l3 ? 0x40 : 0x00) | (in_device_status->share ? 0x20 : 0x00) | (in_device_status->option ? 0x10 : 0x00) | - /*(in_device_status->r2_trigger > 200 ? 0x08 : 0x00)*/ 0x00 | - /*(in_device_status->l2_trigger > 200 ? 0x04 : 0x00)*/ 0x00 | + (in_device_status->r2_trigger > 200 ? 0x08 : 0x00) | + (in_device_status->l2_trigger > 200 ? 0x04 : 0x00) | (in_device_status->r1 ? 0x02 : 0x00) | (in_device_status->l1 ? 0x01 : 0x00); - if (in_device_status->join_left_analog_and_gyroscope) { - if (absolute_value(contrib_x) > gamepad->gyro_to_analog_activation_treshold) { - out_shifted_buf[1] = min_max_clamp((int64_t)127 + (((int64_t)out_shifted_buf[1] - (int64_t)127) + contrib_x), 0, 255); - } - - if (absolute_value(contrib_y) >= gamepad->gyro_to_analog_activation_treshold) { - out_shifted_buf[2] = min_max_clamp((int64_t)127 + (((int64_t)out_shifted_buf[2] - (int64_t)127) + contrib_y), 0, 255); - } - } - - if (in_device_status->join_right_analog_and_gyroscope) { - if (absolute_value(contrib_x) >= gamepad->gyro_to_analog_activation_treshold) { - out_shifted_buf[3] = min_max_clamp((int64_t)127 + (((int64_t)out_shifted_buf[3] - (int64_t)127) + contrib_x), 0, 255); - } - - if (absolute_value(contrib_y) >= gamepad->gyro_to_analog_activation_treshold) { - out_shifted_buf[4] = min_max_clamp((int64_t)127 + (((int64_t)out_shifted_buf[4] - (int64_t)127) + contrib_y), 0, 255); - } - } + /* + static uint8_t counter = 0; + buf[7] = (((counter++) % (uint8_t)64) << ((uint8_t)2)) | get_buttons_byte3_by_gs(&gs); + */ - out_shifted_buf[7] = in_device_status->center ? 0x01 : 0x00; + out_buf[7] = in_device_status->center ? 0x01 : 0x00; - out_shifted_buf[8] = in_device_status->l2_trigger; - out_shifted_buf[9] = in_device_status->r2_trigger; - memcpy(&out_shifted_buf[10], ×tamp, sizeof(timestamp)); - out_shifted_buf[12] = 0x20; // [12] battery level | this is called sensor_temparature in the kernel driver but is never used... - memcpy(&out_shifted_buf[13], &g_x, sizeof(int16_t)); - memcpy(&out_shifted_buf[15], &g_y, sizeof(int16_t)); - memcpy(&out_shifted_buf[17], &g_z, sizeof(int16_t)); - memcpy(&out_shifted_buf[19], &a_x, sizeof(int16_t)); - memcpy(&out_shifted_buf[21], &a_y, sizeof(int16_t)); - memcpy(&out_shifted_buf[23], &a_z, sizeof(int16_t)); + out_buf[8] = in_device_status->l2_trigger; + out_buf[9] = in_device_status->r2_trigger; + memcpy(&out_buf[10], ×tamp, sizeof(timestamp)); + out_buf[12] = 0x20; // [12] battery level | this is called sensor_temparature in the kernel driver but is never used... + memcpy(&out_buf[13], &g_x, sizeof(int16_t)); + memcpy(&out_buf[15], &g_y, sizeof(int16_t)); + memcpy(&out_buf[17], &g_z, sizeof(int16_t)); + memcpy(&out_buf[19], &a_x, sizeof(int16_t)); + memcpy(&out_buf[21], &a_y, sizeof(int16_t)); + memcpy(&out_buf[23], &a_z, sizeof(int16_t)); - out_shifted_buf[30] = 0x1b; // no headset attached + out_buf[30] = 0x1b; // no headset attached - out_shifted_buf[62] = 0x80; // IDK... it seems constant... - out_shifted_buf[57] = 0x80; // IDK... it seems constant... - out_shifted_buf[53] = 0x80; // IDK... it seems constant... - out_shifted_buf[48] = 0x80; // IDK... it seems constant... - out_shifted_buf[35] = 0x80; // IDK... it seems constant... - out_shifted_buf[44] = 0x80; // IDK... it seems constant... + out_buf[62] = 0x80; // IDK... it seems constant... + out_buf[57] = 0x80; // IDK... it seems constant... + out_buf[53] = 0x80; // IDK... it seems constant... + out_buf[48] = 0x80; // IDK... it seems constant... + out_buf[35] = 0x80; // IDK... it seems constant... + out_buf[44] = 0x80; // IDK... it seems constant... } int virt_dualshock_send(virt_dualshock_t *const gamepad, uint8_t *const out_buf) { @@ -869,18 +774,12 @@ int virt_dualshock_send(virt_dualshock_t *const gamepad, uint8_t *const out_buf) .type = UHID_INPUT2, .u = { .input2 = { - .size = gamepad->bluetooth ? DS4_INPUT_REPORT_BT_SIZE : DS4_INPUT_REPORT_USB_SIZE, + .size = 64, } } }; memcpy(&l.u.input2.data[0], &out_buf[0], l.u.input2.size); - if (gamepad->bluetooth) { - uint32_t crc = crc32_le(0xFFFFFFFFU, (const uint8_t*)&PS_INPUT_CRC32_SEED, sizeof(PS_INPUT_CRC32_SEED)); - crc = ~crc32_le(crc, (const uint8_t *)&l.u.input2.data[0], l.u.input2.size - 4); - memcpy(&l.u.input2.data[l.u.input2.size - sizeof(crc)], &crc, sizeof(crc)); - } - return uhid_write(gamepad->fd, &l); } diff --git a/virt_ds4.h b/virt_ds4.h index d69a583..986e011 100644 --- a/virt_ds4.h +++ b/virt_ds4.h @@ -13,46 +13,22 @@ typedef struct virt_dualshock { bool debug; - bool bluetooth; - uint32_t dt_sum; uint8_t dt_buffer_current; uint32_t dt_buffer[30]; uint32_t empty_reports; - int64_t last_time; - - int64_t gyro_to_analog_activation_treshold; - int64_t gyro_to_analog_mapping; + uint64_t last_time; } virt_dualshock_t; -int virt_dualshock_init( - virt_dualshock_t *const gamepad, - bool bluetooth, - int64_t gyro_to_analog_activation_treshold, - int64_t gyro_to_analog_mapping -); +int virt_dualshock_init(virt_dualshock_t *const gamepad); -int virt_dualshock_get_fd( - virt_dualshock_t *const gamepad -); +int virt_dualshock_get_fd(virt_dualshock_t *const gamepad); -int virt_dualshock_event( - virt_dualshock_t *const gamepad, - gamepad_status_t *const out_device_status -); +int virt_dualshock_event(virt_dualshock_t *const gamepad, gamepad_status_t *const out_device_status); -void virt_dualshock_compose( - virt_dualshock_t *const gamepad, - gamepad_status_t *const in_device_status, - uint8_t *const out_buf -); +void virt_dualshock_compose(virt_dualshock_t *const gamepad, gamepad_status_t *const in_device_status, uint8_t *const out_buf); -int virt_dualshock_send( - virt_dualshock_t *const gamepad, - uint8_t *const out_buf -); +int virt_dualshock_send(virt_dualshock_t *const gamepad, uint8_t *const out_buf); -void virt_dualshock_close( - virt_dualshock_t *const gamepad -); +void virt_dualshock_close(virt_dualshock_t *const gamepad); diff --git a/virt_ds5.c b/virt_ds5.c index 2f34d0a..3117d1d 100644 --- a/virt_ds5.c +++ b/virt_ds5.c @@ -1,8 +1,12 @@ #include "virt_ds5.h" #include "message.h" -#include "rogue_enemy.h" +#include #include +#include +#include +#include +#include #define DS_FEATURE_REPORT_PAIRING_INFO 0x09 #define DS_FEATURE_REPORT_PAIRING_INFO_SIZE 20 @@ -15,12 +19,6 @@ #define DS_INPUT_REPORT_USB 0x01 #define DS_INPUT_REPORT_USB_SIZE 64 -#define DS_INPUT_REPORT_BT 0x31 -#define DS_INPUT_REPORT_BT_SIZE 78 -#define DS_OUTPUT_REPORT_USB 0x02 -#define DS_OUTPUT_REPORT_USB_SIZE 63 -#define DS_OUTPUT_REPORT_BT 0x31 -#define DS_OUTPUT_REPORT_BT_SIZE 78 #define DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT 0x02 @@ -31,1012 +29,37 @@ #define DS5_SPEC_DELTA_TIME 4096.0f -static uint32_t crc32_le(uint32_t crc_initial, const uint8_t *const buf, size_t len) { - return crc32(crc_initial ^ 0xffffffff, buf, len) ^ 0xffffffff; -} - -/* Seed values for DualShock4 / DualSense CRC32 for different report types. */ -static uint8_t PS_INPUT_CRC32_SEED = 0xA1; -static uint8_t PS_OUTPUT_CRC32_SEED = 0xA2; -static uint8_t PS_FEATURE_CRC32_SEED = 0xA3; - -#define DS5_EDGE_NAME "Sony Interactive Entertainment DualSense Edge Wireless Controller" -#define DS5_EDGE_VERSION 256 -#define DS5_EDGE_VENDOR 0x054C -#define DS5_EDGE_PRODUCT 0x0DF2 - -#define DS5_NAME "Sony Interactive Entertainment DualSense Wireless Controller" -#define DS5_VERSION 0x8111 -#define DS5_VENDOR 0x054C -#define DS5_PRODUCT 0x0ce6 - static const char* path = "/dev/uhid"; //static const char* const MAC_ADDR_STR = "e8:47:3a:d6:e7:74"; static const uint8_t MAC_ADDR[] = { 0x74, 0xe7, 0xd6, 0x3a, 0x47, 0xe8 }; -static unsigned char rdesc_edge[] = { - 0x05, - 0x01, // Usage Page (Generic Desktop) 0 - 0x09, - 0x05, // Usage (Game Pad) 2 - 0xA1, - 0x01, // Collection (Application) 4 - 0x85, - 0x01, // Report ID (1) 6 - 0x09, - 0x30, // Usage (X) 8 - 0x09, - 0x31, // Usage (Y) 10 - 0x09, - 0x32, // Usage (Z) 12 - 0x09, - 0x35, // Usage (Rz) 14 - 0x09, - 0x33, // Usage (Rx) 16 - 0x09, - 0x34, // Usage (Ry) 18 - 0x15, - 0x00, // Logical Minimum (0) 20 - 0x26, - 0xFF, - 0x00, // Logical Maximum (255) 22 - 0x75, - 0x08, // Report Size (8) 25 - 0x95, - 0x06, // Report Count (6) 27 - 0x81, - 0x02, // Input (Data,Var,Abs) 29 - 0x06, - 0x00, - 0xFF, // Usage Page (Vendor Defined Page 1) 31 - 0x09, - 0x20, // Usage (Vendor Usage 0x20) 34 - 0x95, - 0x01, // Report Count (1) 36 - 0x81, - 0x02, // Input (Data,Var,Abs) 38 - 0x05, - 0x01, // Usage Page (Generic Desktop) 40 - 0x09, - 0x39, // Usage (Hat switch) 42 - 0x15, - 0x00, // Logical Minimum (0) 44 - 0x25, - 0x07, // Logical Maximum (7) 46 - 0x35, - 0x00, // Physical Minimum (0) 48 - 0x46, - 0x3B, - 0x01, // Physical Maximum (315) 50 - 0x65, - 0x14, // Unit (EnglishRotation: deg) 53 - 0x75, - 0x04, // Report Size (4) 55 - 0x95, - 0x01, // Report Count (1) 57 - 0x81, - 0x42, // Input (Data,Var,Abs,Null) 59 - 0x65, - 0x00, // Unit (None) 61 - 0x05, - 0x09, // Usage Page (Button) 63 - 0x19, - 0x01, // Usage Minimum (1) 65 - 0x29, - 0x0F, // Usage Maximum (15) 67 - 0x15, - 0x00, // Logical Minimum (0) 69 - 0x25, - 0x01, // Logical Maximum (1) 71 - 0x75, - 0x01, // Report Size (1) 73 - 0x95, - 0x0F, // Report Count (15) 75 - 0x81, - 0x02, // Input (Data,Var,Abs) 77 - 0x06, - 0x00, - 0xFF, // Usage Page (Vendor Defined Page 1) 79 - 0x09, - 0x21, // Usage (Vendor Usage 0x21) 82 - 0x95, - 0x0D, // Report Count (13) 84 - 0x81, - 0x02, // Input (Data,Var,Abs) 86 - 0x06, - 0x00, - 0xFF, // Usage Page (Vendor Defined Page 1) 88 - 0x09, - 0x22, // Usage (Vendor Usage 0x22) 91 - 0x15, - 0x00, // Logical Minimum (0) 93 - 0x26, - 0xFF, - 0x00, // Logical Maximum (255) 95 - 0x75, - 0x08, // Report Size (8) 98 - 0x95, - 0x34, // Report Count (52) 100 - 0x81, - 0x02, // Input (Data,Var,Abs) 102 - 0x85, - 0x02, // Report ID (2) 104 - 0x09, - 0x23, // Usage (Vendor Usage 0x23) 106 - 0x95, - 0x3F, // Report Count (63) 108 - 0x91, - 0x02, // Output (Data,Var,Abs) 110 - 0x85, - 0x05, // Report ID (5) 112 - 0x09, - 0x33, // Usage (Vendor Usage 0x33) 114 - 0x95, - 0x28, // Report Count (40) 116 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 118 - 0x85, - 0x08, // Report ID (8) 120 - 0x09, - 0x34, // Usage (Vendor Usage 0x34) 122 - 0x95, - 0x2F, // Report Count (47) 124 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 126 - 0x85, - 0x09, // Report ID (9) 128 - 0x09, - 0x24, // Usage (Vendor Usage 0x24) 130 - 0x95, - 0x13, // Report Count (19) 132 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 134 - 0x85, - 0x0A, // Report ID (10) 136 - 0x09, - 0x25, // Usage (Vendor Usage 0x25) 138 - 0x95, - 0x1A, // Report Count (26) 140 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 142 - 0x85, - 0x20, // Report ID (32) 144 - 0x09, - 0x26, // Usage (Vendor Usage 0x26) 146 - 0x95, - 0x3F, // Report Count (63) 148 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 150 - 0x85, - 0x21, // Report ID (33) 152 - 0x09, - 0x27, // Usage (Vendor Usage 0x27) 154 - 0x95, - 0x04, // Report Count (4) 156 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 158 - 0x85, - 0x22, // Report ID (34) 160 - 0x09, - 0x40, // Usage (Vendor Usage 0x40) 162 - 0x95, - 0x3F, // Report Count (63) 164 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 166 - 0x85, - 0x80, // Report ID (128) 168 - 0x09, - 0x28, // Usage (Vendor Usage 0x28) 170 - 0x95, - 0x3F, // Report Count (63) 172 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 174 - 0x85, - 0x81, // Report ID (129) 176 - 0x09, - 0x29, // Usage (Vendor Usage 0x29) 178 - 0x95, - 0x3F, // Report Count (63) 180 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 182 - 0x85, - 0x82, // Report ID (130) 184 - 0x09, - 0x2A, // Usage (Vendor Usage 0x2a) 186 - 0x95, - 0x09, // Report Count (9) 188 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 190 - 0x85, - 0x83, // Report ID (131) 192 - 0x09, - 0x2B, // Usage (Vendor Usage 0x2b) 194 - 0x95, - 0x3F, // Report Count (63) 196 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 198 - 0x85, - 0x84, // Report ID (132) 200 - 0x09, - 0x2C, // Usage (Vendor Usage 0x2c) 202 - 0x95, - 0x3F, // Report Count (63) 204 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 206 - 0x85, - 0x85, // Report ID (133) 208 - 0x09, - 0x2D, // Usage (Vendor Usage 0x2d) 210 - 0x95, - 0x02, // Report Count (2) 212 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 214 - 0x85, - 0xA0, // Report ID (160) 216 - 0x09, - 0x2E, // Usage (Vendor Usage 0x2e) 218 - 0x95, - 0x01, // Report Count (1) 220 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 222 - 0x85, - 0xE0, // Report ID (224) 224 - 0x09, - 0x2F, // Usage (Vendor Usage 0x2f) 226 - 0x95, - 0x3F, // Report Count (63) 228 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 230 - 0x85, - 0xF0, // Report ID (240) 232 - 0x09, - 0x30, // Usage (Vendor Usage 0x30) 234 - 0x95, - 0x3F, // Report Count (63) 236 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 238 - 0x85, - 0xF1, // Report ID (241) 240 - 0x09, - 0x31, // Usage (Vendor Usage 0x31) 242 - 0x95, - 0x3F, // Report Count (63) 244 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 246 - 0x85, - 0xF2, // Report ID (242) 248 - 0x09, - 0x32, // Usage (Vendor Usage 0x32) 250 - 0x95, - 0x34, // Report Count (52) 252 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 254 - 0x85, - 0xF4, // Report ID (244) 256 - 0x09, - 0x35, // Usage (Vendor Usage 0x35) 258 - 0x95, - 0x3F, // Report Count (63) 260 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 262 - 0x85, - 0xF5, // Report ID (245) 264 - 0x09, - 0x36, // Usage (Vendor Usage 0x36) 266 - 0x95, - 0x03, // Report Count (3) 268 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 270 - 0x85, - 0x60, // Report ID (96) 272 - 0x09, - 0x41, // Usage (Vendor Usage 0x41) 274 - 0x95, - 0x3F, // Report Count (63) 276 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 278 - 0x85, - 0x61, // Report ID (97) 280 - 0x09, - 0x42, // Usage (Vendor Usage 0x42) 282 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 284 - 0x85, - 0x62, // Report ID (98) 286 - 0x09, - 0x43, // Usage (Vendor Usage 0x43) 288 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 290 - 0x85, - 0x63, // Report ID (99) 292 - 0x09, - 0x44, // Usage (Vendor Usage 0x44) 294 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 296 - 0x85, - 0x64, // Report ID (100) 298 - 0x09, - 0x45, // Usage (Vendor Usage 0x45) 300 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 302 - 0x85, - 0x65, // Report ID (101) 304 - 0x09, - 0x46, // Usage (Vendor Usage 0x46) 306 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 308 - 0x85, - 0x68, // Report ID (104) 310 - 0x09, - 0x47, // Usage (Vendor Usage 0x47) 312 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 314 - 0x85, - 0x70, // Report ID (112) 316 - 0x09, - 0x48, // Usage (Vendor Usage 0x48) 318 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 320 - 0x85, - 0x71, // Report ID (113) 322 - 0x09, - 0x49, // Usage (Vendor Usage 0x49) 324 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 326 - 0x85, - 0x72, // Report ID (114) 328 - 0x09, - 0x4A, // Usage (Vendor Usage 0x4a) 330 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 332 - 0x85, - 0x73, // Report ID (115) 334 - 0x09, - 0x4B, // Usage (Vendor Usage 0x4b) 336 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 338 - 0x85, - 0x74, // Report ID (116) 340 - 0x09, - 0x4C, // Usage (Vendor Usage 0x4c) 342 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 344 - 0x85, - 0x75, // Report ID (117) 346 - 0x09, - 0x4D, // Usage (Vendor Usage 0x4d) 348 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 350 - 0x85, - 0x76, // Report ID (118) 352 - 0x09, - 0x4E, // Usage (Vendor Usage 0x4e) 354 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 356 - 0x85, - 0x77, // Report ID (119) 358 - 0x09, - 0x4F, // Usage (Vendor Usage 0x4f) 360 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 362 - 0x85, - 0x78, // Report ID (120) 364 - 0x09, - 0x50, // Usage (Vendor Usage 0x50) 366 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 368 - 0x85, - 0x79, // Report ID (121) 370 - 0x09, - 0x51, // Usage (Vendor Usage 0x51) 372 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 374 - 0x85, - 0x7A, // Report ID (122) 376 - 0x09, - 0x52, // Usage (Vendor Usage 0x52) 378 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 380 - 0x85, - 0x7B, // Report ID (123) 382 - 0x09, - 0x53, // Usage (Vendor Usage 0x53) 384 - 0xB1, - 0x02, // Feature (Data,Var,Abs) 386 - 0xC0, // End Collection 388 -}; - -static unsigned char rdesc_edge_bt[] = { - 0x05, - 0x01, - 0x09, - 0x05, - 0xA1, - 0x01, - 0x85, - 0x01, - 0x09, - 0x30, - 0x09, - 0x31, - 0x09, - 0x32, - 0x09, - 0x35, - 0x15, - 0x00, - 0x26, - 0xFF, - 0x00, - 0x75, - 0x08, - 0x95, - 0x04, - 0x81, - 0x02, - 0x09, - 0x39, - 0x15, - 0x00, - 0x25, - 0x07, - 0x35, - 0x00, - 0x46, - 0x3B, - 0x01, - 0x65, - 0x14, - 0x75, - 0x04, - 0x95, - 0x01, - 0x81, - 0x42, - 0x65, - 0x00, - 0x05, - 0x09, - 0x19, - 0x01, - 0x29, - 0x0E, - 0x15, - 0x00, - 0x25, - 0x01, - 0x75, - 0x01, - 0x95, - 0x0E, - 0x81, - 0x02, - 0x75, - 0x06, - 0x95, - 0x01, - 0x81, - 0x01, - 0x05, - 0x01, - 0x09, - 0x33, - 0x09, - 0x34, - 0x15, - 0x00, - 0x26, - 0xFF, - 0x00, - 0x75, - 0x08, - 0x95, - 0x02, - 0x81, - 0x02, - 0x06, - 0x00, - 0xFF, - 0x15, - 0x00, - 0x26, - 0xFF, - 0x00, - 0x75, - 0x08, - 0x95, - 0x4D, - 0x85, - 0x31, - 0x09, - 0x31, - 0x91, - 0x02, - 0x09, - 0x3B, - 0x81, - 0x02, - 0x85, - 0x32, - 0x09, - 0x32, - 0x95, - 0x8D, - 0x91, - 0x02, - 0x85, - 0x33, - 0x09, - 0x33, - 0x95, - 0xCD, - 0x91, - 0x02, - 0x85, - 0x34, - 0x09, - 0x34, - 0x96, - 0x0D, - 0x01, - 0x91, - 0x02, - 0x85, - 0x35, - 0x09, - 0x35, - 0x96, - 0x4D, - 0x01, - 0x91, - 0x02, - 0x85, - 0x36, - 0x09, - 0x36, - 0x96, - 0x8D, - 0x01, - 0x91, - 0x02, - 0x85, - 0x37, - 0x09, - 0x37, - 0x96, - 0xCD, - 0x01, - 0x91, - 0x02, - 0x85, - 0x38, - 0x09, - 0x38, - 0x96, - 0x0D, - 0x02, - 0x91, - 0x02, - 0x85, - 0x39, - 0x09, - 0x39, - 0x96, - 0x22, - 0x02, - 0x91, - 0x02, - 0x06, - 0x80, - 0xFF, - 0x85, - 0x05, - 0x09, - 0x33, - 0x95, - 0x28, - 0xB1, - 0x02, - 0x85, - 0x08, - 0x09, - 0x34, - 0x95, - 0x2F, - 0xB1, - 0x02, - 0x85, - 0x09, - 0x09, - 0x24, - 0x95, - 0x13, - 0xB1, - 0x02, - 0x85, - 0x20, - 0x09, - 0x26, - 0x95, - 0x3F, - 0xB1, - 0x02, - 0x85, - 0x22, - 0x09, - 0x40, - 0x95, - 0x3F, - 0xB1, - 0x02, - 0x85, - 0x80, - 0x09, - 0x28, - 0x95, - 0x3F, - 0xB1, - 0x02, - 0x85, - 0x81, - 0x09, - 0x29, - 0x95, - 0x3F, - 0xB1, - 0x02, - 0x85, - 0x82, - 0x09, - 0x2A, - 0x95, - 0x09, - 0xB1, - 0x02, - 0x85, - 0x83, - 0x09, - 0x2B, - 0x95, - 0x3F, - 0xB1, - 0x02, - 0x85, - 0xF1, - 0x09, - 0x31, - 0x95, - 0x3F, - 0xB1, - 0x02, - 0x85, - 0xF2, - 0x09, - 0x32, - 0x95, - 0x34, - 0xB1, - 0x02, - 0x85, - 0xF0, - 0x09, - 0x30, - 0x95, - 0x3F, - 0xB1, - 0x02, - 0x85, - 0x60, - 0x09, - 0x41, - 0x95, - 0x3F, - 0xB1, - 0x02, - 0x85, - 0x61, - 0x09, - 0x42, - 0xB1, - 0x02, - 0x85, - 0x62, - 0x09, - 0x43, - 0xB1, - 0x02, - 0x85, - 0x63, - 0x09, - 0x44, - 0xB1, - 0x02, - 0x85, - 0x64, - 0x09, - 0x45, - 0xB1, - 0x02, - 0x85, - 0x65, - 0x09, - 0x46, - 0xB1, - 0x02, - 0x85, - 0x68, - 0x09, - 0x47, - 0xB1, - 0x02, - 0x85, - 0x70, - 0x09, - 0x48, - 0xB1, - 0x02, - 0x85, - 0x71, - 0x09, - 0x49, - 0xB1, - 0x02, - 0x85, - 0x72, - 0x09, - 0x4A, - 0xB1, - 0x02, - 0x85, - 0x73, - 0x09, - 0x4B, - 0xB1, - 0x02, - 0x85, - 0x74, - 0x09, - 0x4C, - 0xB1, - 0x02, - 0x85, - 0x75, - 0x09, - 0x4D, - 0xB1, - 0x02, - 0x85, - 0x76, - 0x09, - 0x4E, - 0xB1, - 0x02, - 0x85, - 0x77, - 0x09, - 0x4F, - 0xB1, - 0x02, - 0x85, - 0x78, - 0x09, - 0x50, - 0xB1, - 0x02, - 0x85, - 0x79, - 0x09, - 0x51, - 0xB1, - 0x02, - 0x85, - 0x7A, - 0x09, - 0x52, - 0xB1, - 0x02, - 0x85, - 0x7B, - 0x09, - 0x53, - 0xB1, - 0x02, - 0x85, - 0xF4, - 0x09, - 0x2C, - 0x95, - 0x3F, - 0xB1, - 0x02, - 0x85, - 0xF5, - 0x09, - 0x2D, - 0x95, - 0x07, - 0xB1, - 0x02, - 0x85, - 0xF6, - 0x09, - 0x2E, - 0x96, - 0x22, - 0x02, - 0xB1, - 0x02, - 0x85, - 0xF7, - 0x09, - 0x2F, - 0x95, - 0x07, - 0xB1, - 0x02, - 0xC0, - 0x00, -}; - static unsigned char rdesc[] = { - 0x05, 0x01, // Usage Page (Generic Desktop) 0 - 0x09, 0x05, // Usage (Game Pad) 2 - 0xa1, 0x01, // Collection (Application) 4 - 0x85, 0x01, // Report ID (1) 6 - 0x09, 0x30, // Usage (X) 8 - 0x09, 0x31, // Usage (Y) 10 - 0x09, 0x32, // Usage (Z) 12 - 0x09, 0x35, // Usage (Rz) 14 - 0x09, 0x33, // Usage (Rx) 16 - 0x09, 0x34, // Usage (Ry) 18 - 0x15, 0x00, // Logical Minimum (0) 20 - 0x26, 0xff, 0x00, // Logical Maximum (255) 22 - 0x75, 0x08, // Report Size (8) 25 - 0x95, 0x06, // Report Count (6) 27 - 0x81, 0x02, // Input (Data,Var,Abs) 29 - 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 31 - 0x09, 0x20, // Usage (Vendor Usage 0x20) 34 - 0x95, 0x01, // Report Count (1) 36 - 0x81, 0x02, // Input (Data,Var,Abs) 38 - 0x05, 0x01, // Usage Page (Generic Desktop) 40 - 0x09, 0x39, // Usage (Hat switch) 42 - 0x15, 0x00, // Logical Minimum (0) 44 - 0x25, 0x07, // Logical Maximum (7) 46 - 0x35, 0x00, // Physical Minimum (0) 48 - 0x46, 0x3b, 0x01, // Physical Maximum (315) 50 - 0x65, 0x14, // Unit (EnglishRotation: deg) 53 - 0x75, 0x04, // Report Size (4) 55 - 0x95, 0x01, // Report Count (1) 57 - 0x81, 0x42, // Input (Data,Var,Abs,Null) 59 - 0x65, 0x00, // Unit (None) 61 - 0x05, 0x09, // Usage Page (Button) 63 - 0x19, 0x01, // Usage Minimum (1) 65 - 0x29, 0x0f, // Usage Maximum (15) 67 - 0x15, 0x00, // Logical Minimum (0) 69 - 0x25, 0x01, // Logical Maximum (1) 71 - 0x75, 0x01, // Report Size (1) 73 - 0x95, 0x0f, // Report Count (15) 75 - 0x81, 0x02, // Input (Data,Var,Abs) 77 - 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 79 - 0x09, 0x21, // Usage (Vendor Usage 0x21) 82 - 0x95, 0x0d, // Report Count (13) 84 - 0x81, 0x02, // Input (Data,Var,Abs) 86 - 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 88 - 0x09, 0x22, // Usage (Vendor Usage 0x22) 91 - 0x15, 0x00, // Logical Minimum (0) 93 - 0x26, 0xff, 0x00, // Logical Maximum (255) 95 - 0x75, 0x08, // Report Size (8) 98 - 0x95, 0x34, // Report Count (52) 100 - 0x81, 0x02, // Input (Data,Var,Abs) 102 - 0x85, 0x02, // Report ID (2) 104 - 0x09, 0x23, // Usage (Vendor Usage 0x23) 106 - 0x95, 0x2f, // Report Count (47) 108 - 0x91, 0x02, // Output (Data,Var,Abs) 110 - 0x85, 0x05, // Report ID (5) 112 - 0x09, 0x33, // Usage (Vendor Usage 0x33) 114 - 0x95, 0x28, // Report Count (40) 116 - 0xb1, 0x02, // Feature (Data,Var,Abs) 118 - 0x85, 0x08, // Report ID (8) 120 - 0x09, 0x34, // Usage (Vendor Usage 0x34) 122 - 0x95, 0x2f, // Report Count (47) 124 - 0xb1, 0x02, // Feature (Data,Var,Abs) 126 - 0x85, 0x09, // Report ID (9) 128 - 0x09, 0x24, // Usage (Vendor Usage 0x24) 130 - 0x95, 0x13, // Report Count (19) 132 - 0xb1, 0x02, // Feature (Data,Var,Abs) 134 - 0x85, 0x0a, // Report ID (10) 136 - 0x09, 0x25, // Usage (Vendor Usage 0x25) 138 - 0x95, 0x1a, // Report Count (26) 140 - 0xb1, 0x02, // Feature (Data,Var,Abs) 142 - 0x85, 0x20, // Report ID (32) 144 - 0x09, 0x26, // Usage (Vendor Usage 0x26) 146 - 0x95, 0x3f, // Report Count (63) 148 - 0xb1, 0x02, // Feature (Data,Var,Abs) 150 - 0x85, 0x21, // Report ID (33) 152 - 0x09, 0x27, // Usage (Vendor Usage 0x27) 154 - 0x95, 0x04, // Report Count (4) 156 - 0xb1, 0x02, // Feature (Data,Var,Abs) 158 - 0x85, 0x22, // Report ID (34) 160 - 0x09, 0x40, // Usage (Vendor Usage 0x40) 162 - 0x95, 0x3f, // Report Count (63) 164 - 0xb1, 0x02, // Feature (Data,Var,Abs) 166 - 0x85, 0x80, // Report ID (128) 168 - 0x09, 0x28, // Usage (Vendor Usage 0x28) 170 - 0x95, 0x3f, // Report Count (63) 172 - 0xb1, 0x02, // Feature (Data,Var,Abs) 174 - 0x85, 0x81, // Report ID (129) 176 - 0x09, 0x29, // Usage (Vendor Usage 0x29) 178 - 0x95, 0x3f, // Report Count (63) 180 - 0xb1, 0x02, // Feature (Data,Var,Abs) 182 - 0x85, 0x82, // Report ID (130) 184 - 0x09, 0x2a, // Usage (Vendor Usage 0x2a) 186 - 0x95, 0x09, // Report Count (9) 188 - 0xb1, 0x02, // Feature (Data,Var,Abs) 190 - 0x85, 0x83, // Report ID (131) 192 - 0x09, 0x2b, // Usage (Vendor Usage 0x2b) 194 - 0x95, 0x3f, // Report Count (63) 196 - 0xb1, 0x02, // Feature (Data,Var,Abs) 198 - 0x85, 0x84, // Report ID (132) 200 - 0x09, 0x2c, // Usage (Vendor Usage 0x2c) 202 - 0x95, 0x3f, // Report Count (63) 204 - 0xb1, 0x02, // Feature (Data,Var,Abs) 206 - 0x85, 0x85, // Report ID (133) 208 - 0x09, 0x2d, // Usage (Vendor Usage 0x2d) 210 - 0x95, 0x02, // Report Count (2) 212 - 0xb1, 0x02, // Feature (Data,Var,Abs) 214 - 0x85, 0xa0, // Report ID (160) 216 - 0x09, 0x2e, // Usage (Vendor Usage 0x2e) 218 - 0x95, 0x01, // Report Count (1) 220 - 0xb1, 0x02, // Feature (Data,Var,Abs) 222 - 0x85, 0xe0, // Report ID (224) 224 - 0x09, 0x2f, // Usage (Vendor Usage 0x2f) 226 - 0x95, 0x3f, // Report Count (63) 228 - 0xb1, 0x02, // Feature (Data,Var,Abs) 230 - 0x85, 0xf0, // Report ID (240) 232 - 0x09, 0x30, // Usage (Vendor Usage 0x30) 234 - 0x95, 0x3f, // Report Count (63) 236 - 0xb1, 0x02, // Feature (Data,Var,Abs) 238 - 0x85, 0xf1, // Report ID (241) 240 - 0x09, 0x31, // Usage (Vendor Usage 0x31) 242 - 0x95, 0x3f, // Report Count (63) 244 - 0xb1, 0x02, // Feature (Data,Var,Abs) 246 - 0x85, 0xf2, // Report ID (242) 248 - 0x09, 0x32, // Usage (Vendor Usage 0x32) 250 - 0x95, 0x0f, // Report Count (15) 252 - 0xb1, 0x02, // Feature (Data,Var,Abs) 254 - 0x85, 0xf4, // Report ID (244) 256 - 0x09, 0x35, // Usage (Vendor Usage 0x35) 258 - 0x95, 0x3f, // Report Count (63) 260 - 0xb1, 0x02, // Feature (Data,Var,Abs) 262 - 0x85, 0xf5, // Report ID (245) 264 - 0x09, 0x36, // Usage (Vendor Usage 0x36) 266 - 0x95, 0x03, // Report Count (3) 268 - 0xb1, 0x02, // Feature (Data,Var,Abs) 270 - 0xc0, // End Collection 272 -}; - -static unsigned char rdesc_bt[] = { -0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, -0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x04, 0x81, 0x02, 0x09, 0x39, 0x15, 0x00, 0x25, -0x07, 0x35, 0x00, 0x46, 0x3b, 0x01, 0x65, 0x14, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x65, 0x00, -0x05, 0x09, 0x19, 0x01, 0x29, 0x0e, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0e, 0x81, 0x02, -0x75, 0x06, 0x95, 0x01, 0x81, 0x01, 0x05, 0x01, 0x09, 0x33, 0x09, 0x34, 0x15, 0x00, 0x26, 0xff, -0x00, 0x75, 0x08, 0x95, 0x02, 0x81, 0x02, 0x06, 0x00, 0xff, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, -0x08, 0x95, 0x4d, 0x85, 0x31, 0x09, 0x31, 0x91, 0x02, 0x09, 0x3b, 0x81, 0x02, 0x85, 0x32, 0x09, -0x32, 0x95, 0x8d, 0x91, 0x02, 0x85, 0x33, 0x09, 0x33, 0x95, 0xcd, 0x91, 0x02, 0x85, 0x34, 0x09, -0x34, 0x96, 0x0d, 0x01, 0x91, 0x02, 0x85, 0x35, 0x09, 0x35, 0x96, 0x4d, 0x01, 0x91, 0x02, 0x85, -0x36, 0x09, 0x36, 0x96, 0x8d, 0x01, 0x91, 0x02, 0x85, 0x37, 0x09, 0x37, 0x96, 0xcd, 0x01, 0x91, -0x02, 0x85, 0x38, 0x09, 0x38, 0x96, 0x0d, 0x02, 0x91, 0x02, 0x85, 0x39, 0x09, 0x39, 0x96, 0x22, -0x02, 0x91, 0x02, 0x06, 0x80, 0xff, 0x85, 0x05, 0x09, 0x33, 0x95, 0x28, 0xb1, 0x02, 0x85, 0x08, -0x09, 0x34, 0x95, 0x2f, 0xb1, 0x02, 0x85, 0x09, 0x09, 0x24, 0x95, 0x13, 0xb1, 0x02, 0x85, 0x20, -0x09, 0x26, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x22, 0x09, 0x40, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x80, -0x09, 0x28, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x81, 0x09, 0x29, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x82, -0x09, 0x2a, 0x95, 0x09, 0xb1, 0x02, 0x85, 0x83, 0x09, 0x2b, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf1, -0x09, 0x31, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf2, 0x09, 0x32, 0x95, 0x0f, 0xb1, 0x02, 0x85, 0xf0, -0x09, 0x30, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf4, 0x09, 0x2c, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf5, -0x09, 0x2d, 0x95, 0x07, 0xb1, 0x02, 0x85, 0xf6, 0x09, 0x2e, 0x96, 0x22, 0x02, 0xb1, 0x02, 0x85, -0xf7, 0x09, 0x2f, 0x95, 0x07, 0xb1, 0x02, 0xc0, 0x00 + 0x05, 0x01, 0x09, 0x05, 0xA1, 0x01, 0x85, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, + 0x09, 0x33, 0x09, 0x34, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x06, 0x81, 0x02, 0x06, + 0x00, 0xFF, 0x09, 0x20, 0x95, 0x01, 0x81, 0x02, 0x05, 0x01, 0x09, 0x39, 0x15, 0x00, 0x25, 0x07, + 0x35, 0x00, 0x46, 0x3B, 0x01, 0x65, 0x14, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x65, 0x00, 0x05, + 0x09, 0x19, 0x01, 0x29, 0x0F, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0F, 0x81, 0x02, 0x06, + 0x00, 0xFF, 0x09, 0x21, 0x95, 0x0D, 0x81, 0x02, 0x06, 0x00, 0xFF, 0x09, 0x22, 0x15, 0x00, 0x26, + 0xFF, 0x00, 0x75, 0x08, 0x95, 0x34, 0x81, 0x02, 0x85, 0x02, 0x09, 0x23, 0x95, 0x3F, 0x91, 0x02, + 0x85, 0x05, 0x09, 0x33, 0x95, 0x28, 0xB1, 0x02, 0x85, 0x08, 0x09, 0x34, 0x95, 0x2F, 0xB1, 0x02, + 0x85, 0x09, 0x09, 0x24, 0x95, 0x13, 0xB1, 0x02, 0x85, 0x0A, 0x09, 0x25, 0x95, 0x1A, 0xB1, 0x02, + 0x85, 0x20, 0x09, 0x26, 0x95, 0x3F, 0xB1, 0x02, 0x85, 0x21, 0x09, 0x27, 0x95, 0x04, 0xB1, 0x02, + 0x85, 0x22, 0x09, 0x40, 0x95, 0x3F, 0xB1, 0x02, 0x85, 0x80, 0x09, 0x28, 0x95, 0x3F, 0xB1, 0x02, + 0x85, 0x81, 0x09, 0x29, 0x95, 0x3F, 0xB1, 0x02, 0x85, 0x82, 0x09, 0x2A, 0x95, 0x09, 0xB1, 0x02, + 0x85, 0x83, 0x09, 0x2B, 0x95, 0x3F, 0xB1, 0x02, 0x85, 0x84, 0x09, 0x2C, 0x95, 0x3F, 0xB1, 0x02, + 0x85, 0x85, 0x09, 0x2D, 0x95, 0x02, 0xB1, 0x02, 0x85, 0xA0, 0x09, 0x2E, 0x95, 0x01, 0xB1, 0x02, + 0x85, 0xE0, 0x09, 0x2F, 0x95, 0x3F, 0xB1, 0x02, 0x85, 0xF0, 0x09, 0x30, 0x95, 0x3F, 0xB1, 0x02, + 0x85, 0xF1, 0x09, 0x31, 0x95, 0x3F, 0xB1, 0x02, 0x85, 0xF2, 0x09, 0x32, 0x95, 0x34, 0xB1, 0x02, + 0x85, 0xF4, 0x09, 0x35, 0x95, 0x3F, 0xB1, 0x02, 0x85, 0xF5, 0x09, 0x36, 0x95, 0x03, 0xB1, 0x02, + 0x85, 0x60, 0x09, 0x41, 0x95, 0x3F, 0xB1, 0x02, 0x85, 0x61, 0x09, 0x42, 0xB1, 0x02, 0x85, 0x62, + 0x09, 0x43, 0xB1, 0x02, 0x85, 0x63, 0x09, 0x44, 0xB1, 0x02, 0x85, 0x64, 0x09, 0x45, 0xB1, 0x02, + 0x85, 0x65, 0x09, 0x46, 0xB1, 0x02, 0x85, 0x68, 0x09, 0x47, 0xB1, 0x02, 0x85, 0x70, 0x09, 0x48, + 0xB1, 0x02, 0x85, 0x71, 0x09, 0x49, 0xB1, 0x02, 0x85, 0x72, 0x09, 0x4A, 0xB1, 0x02, 0x85, 0x73, + 0x09, 0x4B, 0xB1, 0x02, 0x85, 0x74, 0x09, 0x4C, 0xB1, 0x02, 0x85, 0x75, 0x09, 0x4D, 0xB1, 0x02, + 0x85, 0x76, 0x09, 0x4E, 0xB1, 0x02, 0x85, 0x77, 0x09, 0x4F, 0xB1, 0x02, 0x85, 0x78, 0x09, 0x50, + 0xB1, 0x02, 0x85, 0x79, 0x09, 0x51, 0xB1, 0x02, 0x85, 0x7A, 0x09, 0x52, 0xB1, 0x02, 0x85, 0x7B, + 0x09, 0x53, 0xB1, 0x02, 0xC0 }; static int uhid_write(int fd, const struct uhid_event *ev) @@ -1056,38 +79,22 @@ static int uhid_write(int fd, const struct uhid_event *ev) } } -static int create(int fd, bool bluetooth, bool dualsense_edge) +static int create(int fd) { struct uhid_event ev; - char uniq[sizeof(ev.u.create.uniq)]; - sprintf(uniq, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", - MAC_ADDR[5], MAC_ADDR[4], MAC_ADDR[3], MAC_ADDR[2], MAC_ADDR[1], MAC_ADDR[0] - ); - memset(&ev, 0, sizeof(ev)); ev.type = UHID_CREATE; - - if (dualsense_edge) { - strcpy((char*)ev.u.create.name, DS5_EDGE_NAME); - } else { - strcpy((char*)ev.u.create.name, DS5_NAME); - } - - if (dualsense_edge) { - ev.u.create.rd_data = bluetooth ? rdesc_edge_bt : rdesc_edge; - ev.u.create.rd_size = bluetooth ? sizeof(rdesc_edge_bt) : sizeof(rdesc_edge); - } else { - ev.u.create.rd_data = bluetooth ? rdesc_bt : rdesc; - ev.u.create.rd_size = bluetooth ? sizeof(rdesc_bt) : sizeof(rdesc); - } - - ev.u.create.bus = bluetooth ? BUS_BLUETOOTH : BUS_USB; - ev.u.create.vendor = dualsense_edge ? DS5_EDGE_VENDOR : DS5_VENDOR; - ev.u.create.product = dualsense_edge ? DS5_EDGE_PRODUCT : DS5_PRODUCT; - ev.u.create.version = dualsense_edge ? DS5_EDGE_VERSION : DS5_VERSION; + strcpy((char*)ev.u.create.name, "Sony Interactive Entertainment DualSense Wireless Controller"); + ev.u.create.rd_data = rdesc; + ev.u.create.rd_size = sizeof(rdesc); + ev.u.create.bus = BUS_USB; + ev.u.create.vendor = 0x054C; + ev.u.create.product = 0x0df2; + ev.u.create.version = 0; ev.u.create.country = 0; - memcpy(&ev.u.create.uniq, (void*)uniq, sizeof(uniq)); + memset(&ev.u.create.uniq, 0, sizeof(ev.u.create.uniq)); + memcpy(&ev.u.create.uniq, (void*)MAC_ADDR, sizeof(MAC_ADDR)); return uhid_write(fd, &ev); } @@ -1102,19 +109,9 @@ static void destroy(int fd) uhid_write(fd, &ev); } -int virt_dualsense_init( - virt_dualsense_t *const out_gamepad, - bool bluetooth, - bool dualsense_edge, - int64_t gyro_to_analog_activation_treshold, - int64_t gyro_to_analog_mapping -) { +int virt_dualsense_init(virt_dualsense_t *const out_gamepad) { int ret = 0; - out_gamepad->gyro_to_analog_activation_treshold = absolute_value(gyro_to_analog_activation_treshold); - out_gamepad->gyro_to_analog_mapping = gyro_to_analog_mapping; - out_gamepad->edge_model = dualsense_edge; - out_gamepad->bluetooth = bluetooth; out_gamepad->dt_sum = 0; out_gamepad->dt_buffer_current = 0; memset(out_gamepad->dt_buffer, 0, sizeof(out_gamepad->dt_buffer)); @@ -1130,7 +127,7 @@ int virt_dualsense_init( goto virt_dualshock_init_err; } - ret = create(out_gamepad->fd, bluetooth, dualsense_edge); + ret = create(out_gamepad->fd); if (ret) { fprintf(stderr, "Error creating uhid device: %d\n", ret); close(out_gamepad->fd); @@ -1197,89 +194,56 @@ int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *cons if (ev.u.output.rtype != UHID_OUTPUT_REPORT) return 0; - if (ev.u.output.size == 48) { - fprintf(stderr, "Ignored a 48 bytes report on purpose\n"); - } - - //if (ev.u.output.size != 48) - if ( - (!gamepad->bluetooth) && (ev.u.output.size != DS_OUTPUT_REPORT_USB_SIZE) && - (gamepad->bluetooth) && (ev.u.output.size != DS_OUTPUT_REPORT_BT_SIZE) - ) { - fprintf( - stderr, - "Invalid data length: got %d, expected %d\n", - (int)ev.u.output.size, - (gamepad->bluetooth) ? DS_OUTPUT_REPORT_BT_SIZE : DS_OUTPUT_REPORT_USB_SIZE - ); + if (ev.u.output.size != 48) { + fprintf(stderr, "Invalid data length: got %d, expected 48\n", (int)ev.u.output.size); return 0; } // first byte is report-id which is 0x01 - if ( - (!gamepad->bluetooth) && (ev.u.output.data[0] != DS_OUTPUT_REPORT_USB) && - (gamepad->bluetooth) && ((ev.u.output.data[0] != DS_OUTPUT_REPORT_BT) && (ev.u.output.data[0] < 0x10)) - ) { - fprintf( - stderr, - "Unrecognised report-id: got 0x%x expected 0x%x\n", - (int)ev.u.output.data[0], - (gamepad->bluetooth) ? DS_OUTPUT_REPORT_BT : DS_OUTPUT_REPORT_USB - ); + if (ev.u.output.data[0] != 0x02) { + fprintf(stderr, "Unrecognised report-id: got 0x%x expected 0x02\n", (int)ev.u.output.data[0]); return 0; } - // When using bluetooth, the first byte after the reportID is uint8_t seq_tag, - // while the next one is uint8_t tag, following bytes are the same. - size_t offset = 1; - if ((gamepad->bluetooth) && (ev.u.output.data[0] > 0x10)) { - offset = 2; - } else if ((gamepad->bluetooth) && (ev.u.output.data[0] == 0x02)) { - offset = 3; - } else if ((gamepad->bluetooth) && (ev.u.output.data[0] == 0x01)) { - offset = 1; - } - - const uint8_t *const common_report = &ev.u.output.data[offset]; - - const uint8_t valid_flag0 = common_report[0]; - const uint8_t valid_flag1 = common_report[1]; + const uint8_t valid_flag0 = ev.u.output.data[1]; + const uint8_t valid_flag1 = ev.u.output.data[2]; // For DualShock 4 compatibility mode. - const uint8_t motor_right = common_report[2]; - const uint8_t motor_left = common_report[3]; + const uint8_t motor_right = ev.u.output.data[3]; + const uint8_t motor_left = ev.u.output.data[4]; // Audio controls - const uint8_t reserved[4] = { common_report[4], common_report[5], common_report[6], common_report[7]}; - const uint8_t mute_button_led = common_report[8]; + const uint8_t reserved[4] = { ev.u.output.data[5], ev.u.output.data[6], ev.u.output.data[7], ev.u.output.data[8]}; + const uint8_t mute_button_led = ev.u.output.data[9]; - uint8_t power_save_control = common_report[9]; + uint8_t power_save_control = ev.u.output.data[10]; uint8_t reserved2[28]; // LEDs and lightbar - uint8_t valid_flag2 = common_report[38]; - uint8_t reserved3[2] = {common_report[39], common_report[40]}; - uint8_t lightbar_setup = common_report[41]; - uint8_t led_brightness = common_report[42]; - uint8_t player_leds = common_report[43]; - uint8_t lightbar_red = common_report[44]; - uint8_t lightbar_green = common_report[45]; - uint8_t lightbar_blue = common_report[46]; + uint8_t valid_flag2 = ev.u.output.data[39]; + uint8_t reserved3[2] = {ev.u.output.data[40], ev.u.output.data[41]}; + uint8_t lightbar_setup = ev.u.output.data[42]; + uint8_t led_brightness = ev.u.output.data[43]; + uint8_t player_leds = ev.u.output.data[44]; + uint8_t lightbar_red = ev.u.output.data[45]; + uint8_t lightbar_green = ev.u.output.data[46]; + uint8_t lightbar_blue = ev.u.output.data[47]; - if ((valid_flag2 & DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2) || (valid_flag0 & DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION)) { - uint8_t motors_shift = valid_flag2 & DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2 ? 0 : 1; - out_device_status->motors_intensity[0] = (motor_left << motors_shift) | ((motors_shift > 0) ? ((motor_left == 0) ? 0 : 1) : 0); - out_device_status->motors_intensity[1] = (motor_right << motors_shift) | ((motors_shift > 0) ? ((motor_right == 0) ? 0 : 1) : 0); - ++out_device_status->rumble_events_count; + if ((valid_flag0 & DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT)) { + if (/*(valid_flag2 & DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2) ||*/ (valid_flag0 & DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION)) { + out_device_status->motors_intensity[0] = motor_left; + out_device_status->motors_intensity[1] = motor_right; + ++out_device_status->rumble_events_count; - if (gamepad->debug) { - printf( - "Updated rumble -- motor_left: %d, motor_right: %d, valid_flag0; %d, valid_flag1: %d\n", - motor_left, - motor_right, - valid_flag0, - valid_flag1 - ); + if (gamepad->debug) { + printf( + "Updated rumble -- motor_left: %d, motor_right: %d, valid_flag0; %d, valid_flag1: %d\n", + motor_left, + motor_right, + valid_flag0, + valid_flag1 + ); + } } } @@ -1299,7 +263,7 @@ int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *cons case UHID_GET_REPORT: //fprintf(stderr, "UHID_GET_REPORT from uhid-dev, report=%d\n", ev.u.get_report.rnum); if (ev.u.get_report.rnum == DS_FEATURE_REPORT_PAIRING_INFO) { - struct uhid_event mac_addr_response = { + const struct uhid_event mac_addr_response = { .type = UHID_GET_REPORT_REPLY, .u = { .get_report_reply = { @@ -1317,15 +281,9 @@ int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *cons } }; - if (gamepad->bluetooth) { - uint32_t crc = crc32_le(0xFFFFFFFFU, (const uint8_t*)&PS_FEATURE_CRC32_SEED, sizeof(PS_FEATURE_CRC32_SEED)); - crc = ~crc32_le(crc, (const Bytef *)&mac_addr_response.u.get_report_reply.data[0], mac_addr_response.u.get_report_reply.size - 4); - memcpy(&mac_addr_response.u.get_report_reply.data[mac_addr_response.u.get_report_reply.size - sizeof(crc)], &crc, sizeof(crc)); - } - uhid_write(fd, &mac_addr_response); } else if (ev.u.get_report.rnum == DS_FEATURE_REPORT_FIRMWARE_INFO) { - struct uhid_event firmware_info_response = { + const struct uhid_event firmware_info_response = { .type = UHID_GET_REPORT_REPLY, .u = { .get_report_reply = { @@ -1343,15 +301,9 @@ int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *cons } }; - if (gamepad->bluetooth) { - uint32_t crc = crc32_le(0xFFFFFFFFU, (const uint8_t*)&PS_FEATURE_CRC32_SEED, sizeof(PS_FEATURE_CRC32_SEED)); - crc = ~crc32_le(crc, (const Bytef *)&firmware_info_response.u.get_report_reply.data[0], firmware_info_response.u.get_report_reply.size - 4); - memcpy(&firmware_info_response.u.get_report_reply.data[firmware_info_response.u.get_report_reply.size - sizeof(crc)], &crc, sizeof(crc)); - } - uhid_write(fd, &firmware_info_response); } else if (ev.u.get_report.rnum == DS_FEATURE_REPORT_CALIBRATION) { - struct uhid_event calibration_response = { + struct uhid_event firmware_info_response = { .type = UHID_GET_REPORT_REPLY, .u = { .get_report_reply = { @@ -1368,13 +320,7 @@ int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *cons } }; - if (gamepad->bluetooth) { - uint32_t crc = crc32_le(0xFFFFFFFFU, (const uint8_t*)&PS_FEATURE_CRC32_SEED, sizeof(PS_FEATURE_CRC32_SEED)); - crc = ~crc32_le(crc, (const Bytef *)&calibration_response.u.get_report_reply.data[0], calibration_response.u.get_report_reply.size - 4); - memcpy(&calibration_response.u.get_report_reply.data[calibration_response.u.get_report_reply.size - sizeof(crc)], &crc, sizeof(crc)); - } - - uhid_write(fd, &calibration_response); + uhid_write(fd, &firmware_info_response); } break; @@ -1424,9 +370,9 @@ void virt_dualsense_close(virt_dualsense_t *const out_gamepad) { } void virt_dualsense_compose(virt_dualsense_t *const gamepad, gamepad_status_t *const in_device_status, uint8_t *const out_buf) { - const int64_t time_us = in_device_status->last_gyro_motion_timestamp_ns / (int64_t)1000; + const int64_t time_us = in_device_status->last_gyro_motion_time.tv_sec * 1000000 + in_device_status->last_gyro_motion_time.tv_usec; - const int64_t delta_time = time_us - gamepad->last_time; + const int delta_time = time_us - gamepad->last_time; gamepad->last_time = time_us; // find the average Δt in the last 30 non-zero inputs; @@ -1454,109 +400,79 @@ void virt_dualsense_compose(virt_dualsense_t *const gamepad, gamepad_status_t *c const uint32_t timestamp = sim_time + (int)((double)gamepad->empty_reports * DS5_SPEC_DELTA_TIME); const int16_t g_x = in_device_status->raw_gyro[0]; - const int16_t g_y = in_device_status->raw_gyro[1]; - const int16_t g_z = in_device_status->raw_gyro[2]; + const int16_t g_y = (int16_t)(-1) * in_device_status->raw_gyro[1]; // Swap Y and Z + const int16_t g_z = (int16_t)(-1) * in_device_status->raw_gyro[2]; // Swap Y and Z const int16_t a_x = in_device_status->raw_accel[0]; - const int16_t a_y = in_device_status->raw_accel[1]; - const int16_t a_z = in_device_status->raw_accel[2]; + const int16_t a_y = (int16_t)(-1) * in_device_status->raw_accel[1]; // Swap Y and Z + const int16_t a_z = (int16_t)(-1) * in_device_status->raw_accel[2]; // Swap Y and Z - const int64_t contrib_x = ((int64_t)g_y / (int64_t)gamepad->gyro_to_analog_mapping); - const int64_t contrib_y = ((int64_t)g_x / (int64_t)gamepad->gyro_to_analog_mapping); - out_buf[0] = gamepad->bluetooth ? DS_INPUT_REPORT_BT : DS_INPUT_REPORT_USB; // [00] report ID (0x01) - - uint8_t *const out_shifted_buf = gamepad->bluetooth ? &out_buf[1] : &out_buf[0]; - out_shifted_buf[1] = ((uint64_t)((int64_t)in_device_status->joystick_positions[0][0] + (int64_t)32768) >> (uint64_t)8); // L stick, X axis - out_shifted_buf[2] = ((uint64_t)((int64_t)in_device_status->joystick_positions[0][1] + (int64_t)32768) >> (uint64_t)8); // L stick, Y axis - out_shifted_buf[3] = ((uint64_t)((int64_t)in_device_status->joystick_positions[1][0] + (int64_t)32768) >> (uint64_t)8); // R stick, X axis - out_shifted_buf[4] = ((uint64_t)((int64_t)in_device_status->joystick_positions[1][1] + (int64_t)32768) >> (uint64_t)8); // R stick, Y axis - - if (in_device_status->join_left_analog_and_gyroscope) { - if (absolute_value(contrib_x) > gamepad->gyro_to_analog_activation_treshold) { - out_shifted_buf[1] = min_max_clamp((int64_t)127 + (((int64_t)out_shifted_buf[1] - (int64_t)127) + contrib_x), 0, 255); - } - - if (absolute_value(contrib_y) >= gamepad->gyro_to_analog_activation_treshold) { - out_shifted_buf[2] = min_max_clamp((int64_t)127 + (((int64_t)out_shifted_buf[2] - (int64_t)127) + contrib_y), 0, 255); - } - } - - if (in_device_status->join_right_analog_and_gyroscope) { - if (absolute_value(contrib_x) >= gamepad->gyro_to_analog_activation_treshold) { - out_shifted_buf[3] = min_max_clamp((int64_t)127 + (((int64_t)out_shifted_buf[3] - (int64_t)127) + contrib_x), 0, 255); - } - - if (absolute_value(contrib_y) >= gamepad->gyro_to_analog_activation_treshold) { - out_shifted_buf[4] = min_max_clamp((int64_t)127 + (((int64_t)out_shifted_buf[4] - (int64_t)127) + contrib_y), 0, 255); - } - } - - out_shifted_buf[5] = in_device_status->l2_trigger; // Z - out_shifted_buf[6] = in_device_status->r2_trigger; // RZ - out_shifted_buf[7] = gamepad->seq_num++; // seq_number - out_shifted_buf[8] = (in_device_status->square ? 0x10 : 0x00) | + out_buf[0] = DS_INPUT_REPORT_USB; // [00] report ID (0x01) + out_buf[1] = ((uint64_t)((int64_t)in_device_status->joystick_positions[0][0] + (int64_t)32768) >> (uint64_t)8); // L stick, X axis + out_buf[2] = ((uint64_t)((int64_t)in_device_status->joystick_positions[0][1] + (int64_t)32768) >> (uint64_t)8); // L stick, Y axis + out_buf[3] = ((uint64_t)((int64_t)in_device_status->joystick_positions[1][0] + (int64_t)32768) >> (uint64_t)8); // R stick, X axis + out_buf[4] = ((uint64_t)((int64_t)in_device_status->joystick_positions[1][1] + (int64_t)32768) >> (uint64_t)8); // R stick, Y axis + out_buf[5] = in_device_status->l2_trigger; // Z + out_buf[6] = in_device_status->r2_trigger; // RZ + out_buf[7] = gamepad->seq_num++; // seq_number + out_buf[8] = (in_device_status->square ? 0x10 : 0x00) | (in_device_status->cross ? 0x20 : 0x00) | (in_device_status->circle ? 0x40 : 0x00) | (in_device_status->triangle ? 0x80 : 0x00) | (uint8_t)ds5_dpad_from_gamepad(in_device_status->dpad); - out_shifted_buf[9] = (in_device_status->l1 ? 0x01 : 0x00) | + out_buf[9] = (in_device_status->l1 ? 0x01 : 0x00) | (in_device_status->r1 ? 0x02 : 0x00) | - /*(in_device_status->l2_trigger >= 225 ? 0x04 : 0x00)*/ 0x00 | - /*(in_device_status->r2_trigger >= 225 ? 0x08 : 0x00)*/ 0x00 | + (in_device_status->l2_trigger >= 225 ? 0x04 : 0x00) | + (in_device_status->r2_trigger >= 225 ? 0x08 : 0x00) | (in_device_status->option ? 0x10 : 0x00) | (in_device_status->share ? 0x20 : 0x00) | (in_device_status->l3 ? 0x40 : 0x00) | (in_device_status->r3 ? 0x80 : 0x00); // mic button press is 0x04, touchpad press is 0x02 - out_shifted_buf[10] = ((gamepad->edge_model) && (in_device_status->l5) ? 0x40 : 0x00) | - ((gamepad->edge_model) && (in_device_status->r5) ? 0x80 : 0x00) | - ((gamepad->edge_model) && (in_device_status->l4) ? 0x10 : 0x00) | - ((gamepad->edge_model) && (in_device_status->r4) ? 0x20 : 0x00) | + out_buf[10] = (in_device_status->l5 ? 0x40 : 0x00) | + (in_device_status->r5 ? 0x80 : 0x00) | + (in_device_status->l4 ? 0x10 : 0x00) | + (in_device_status->r4 ? 0x20 : 0x00) | (in_device_status->touchpad_press ? 0x02 : 0x00) | (in_device_status->center ? 0x01 : 0x00); //buf[11] = ; //buf[12] = 0x20; // [12] battery level | this is called sensor_temparature in the kernel driver but is never used... - memcpy(&out_shifted_buf[16], &g_x, sizeof(int16_t)); - memcpy(&out_shifted_buf[18], &g_y, sizeof(int16_t)); - memcpy(&out_shifted_buf[20], &g_z, sizeof(int16_t)); - memcpy(&out_shifted_buf[22], &a_x, sizeof(int16_t)); - memcpy(&out_shifted_buf[24], &a_y, sizeof(int16_t)); - memcpy(&out_shifted_buf[26], &a_z, sizeof(int16_t)); - memcpy(&out_shifted_buf[28], ×tamp, sizeof(timestamp)); + memcpy(&out_buf[16], &g_x, sizeof(int16_t)); + memcpy(&out_buf[18], &g_y, sizeof(int16_t)); + memcpy(&out_buf[20], &g_z, sizeof(int16_t)); + memcpy(&out_buf[22], &a_x, sizeof(int16_t)); + memcpy(&out_buf[24], &a_y, sizeof(int16_t)); + memcpy(&out_buf[26], &a_z, sizeof(int16_t)); + memcpy(&out_buf[28], ×tamp, sizeof(timestamp)); - // point of contact number 0 - out_shifted_buf[33] = (in_device_status->touchpad_touch_num == -1) ? 0x80 : 0x7F; //contact - out_shifted_buf[34] = in_device_status->touchpad_x & (int16_t)0x00FF; //x_lo - out_shifted_buf[35] = (((in_device_status->touchpad_x & (int16_t)0x0F00) >> (int16_t)8) | ((in_device_status->touchpad_y & (int16_t)0x000F) << (int16_t)4)); // x_hi:4 y_lo:4 - out_shifted_buf[36] = (in_device_status->touchpad_y & (int16_t)0x0FF0) >> (int16_t)4; //y_hi + // TODO: when touch is detected send 0x7F, when not 0x80 + out_buf[33] = 0x80; //touch0 active? + out_buf[37] = 0x80; //touch1 active? - // point of contact number 1 - out_shifted_buf[37] = 0x80; //contact - out_shifted_buf[38] = 0x00; //x_lo - out_shifted_buf[39] = 0x00; //x_hi:4 y_lo:4 - out_shifted_buf[40] = 0x00; //y_hi +/* + buf[30] = 0x1b; // no headset attached +*/ + out_buf[62] = 0x80; // IDK... it seems constant... + out_buf[57] = 0x80; // IDK... it seems constant... + out_buf[53] = 0x80; // IDK... it seems constant... + out_buf[48] = 0x80; // IDK... it seems constant... + out_buf[35] = 0x80; // IDK... it seems constant... + out_buf[44] = 0x80; // IDK... it seems constant... } -int virt_dualsense_send(virt_dualsense_t *const gamepad, uint8_t *const out_shifted_buf) { +int virt_dualsense_send(virt_dualsense_t *const gamepad, uint8_t *const out_buf) { struct uhid_event l = { .type = UHID_INPUT2, .u = { .input2 = { - .size = gamepad->bluetooth ? DS_INPUT_REPORT_BT_SIZE : DS_INPUT_REPORT_USB_SIZE, + .size = 64, } } }; - - memcpy(&l.u.input2.data[0], &out_shifted_buf[0], l.u.input2.size); - - if (gamepad->bluetooth) { - uint32_t crc = crc32_le(0xFFFFFFFFU, (const uint8_t*)&PS_INPUT_CRC32_SEED, sizeof(PS_INPUT_CRC32_SEED)); - crc = ~crc32_le(crc, (const uint8_t *)&l.u.input2.data[0], l.u.input2.size - 4); - memcpy(&l.u.input2.data[l.u.input2.size - sizeof(crc)], &crc, sizeof(crc)); - } + memcpy(&l.u.input2.data[0], &out_buf[0], l.u.input2.size); return uhid_write(gamepad->fd, &l); } diff --git a/virt_ds5.h b/virt_ds5.h index e4b01e3..61a4c5d 100644 --- a/virt_ds5.h +++ b/virt_ds5.h @@ -13,10 +13,6 @@ typedef struct virt_dualsense { bool debug; - bool bluetooth; - - bool edge_model; - uint8_t seq_num; uint32_t dt_sum; @@ -24,41 +20,18 @@ typedef struct virt_dualsense { uint32_t dt_buffer[30]; uint32_t empty_reports; - int64_t last_time; - - int64_t gyro_to_analog_activation_treshold; - int64_t gyro_to_analog_mapping; + uint64_t last_time; } virt_dualsense_t; -int virt_dualsense_init( - virt_dualsense_t *const gamepad, - bool bluetooth, - bool dualsense_edge, - int64_t gyro_to_analog_activation_treshold, - int64_t gyro_to_analog_mapping -); +int virt_dualsense_init(virt_dualsense_t *const gamepad); -int virt_dualsense_get_fd( - virt_dualsense_t *const gamepad -); +int virt_dualsense_get_fd(virt_dualsense_t *const gamepad); -int virt_dualsense_event( - virt_dualsense_t *const gamepad, - gamepad_status_t *const out_device_status -); +int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *const out_device_status); -void virt_dualsense_compose( - virt_dualsense_t *const gamepad, - gamepad_status_t *const in_device_status, - uint8_t *const out_buf -); +void virt_dualsense_compose(virt_dualsense_t *const gamepad, gamepad_status_t *const in_device_status, uint8_t *const out_buf); -int virt_dualsense_send( - virt_dualsense_t *const gamepad, - uint8_t *const out_buf -); +int virt_dualsense_send(virt_dualsense_t *const gamepad, uint8_t *const out_buf); -void virt_dualsense_close( - virt_dualsense_t *const gamepad -); +void virt_dualsense_close(virt_dualsense_t *const gamepad); diff --git a/virt_kbd.c b/virt_kbd.c deleted file mode 100644 index 7a7ca3a..0000000 --- a/virt_kbd.c +++ /dev/null @@ -1,411 +0,0 @@ -#include "virt_kbd.h" -#include "message.h" -#include - -int virt_kbd_init(virt_kbd_t *const kbd) { - int ret = -EINVAL; - - memset(kbd, 0, sizeof(virt_kbd_t)); - - int fd = open("/dev/uinput", O_RDWR); - if(fd < 0) { - ret = errno; - goto virt_mouse_init_err; - } - - ioctl(fd, UI_SET_EVBIT, EV_REL); - ioctl(fd, UI_SET_EVBIT, EV_KEY); - ioctl(fd, UI_SET_EVBIT, EV_MSC); - ioctl(fd, UI_SET_EVBIT, EV_SYN); - ioctl(fd, UI_SET_MSCBIT, MSC_TIMESTAMP); - ioctl(fd, UI_SET_KEYBIT, KEY_Q); - ioctl(fd, UI_SET_KEYBIT, KEY_W); - ioctl(fd, UI_SET_KEYBIT, KEY_E); - ioctl(fd, UI_SET_KEYBIT, KEY_R); - ioctl(fd, UI_SET_KEYBIT, KEY_T); - ioctl(fd, UI_SET_KEYBIT, KEY_Y); - ioctl(fd, UI_SET_KEYBIT, KEY_U); - ioctl(fd, UI_SET_KEYBIT, KEY_I); - ioctl(fd, UI_SET_KEYBIT, KEY_O); - ioctl(fd, UI_SET_KEYBIT, KEY_P); - ioctl(fd, UI_SET_KEYBIT, KEY_A); - ioctl(fd, UI_SET_KEYBIT, KEY_S); - ioctl(fd, UI_SET_KEYBIT, KEY_D); - ioctl(fd, UI_SET_KEYBIT, KEY_F); - ioctl(fd, UI_SET_KEYBIT, KEY_G); - ioctl(fd, UI_SET_KEYBIT, KEY_H); - ioctl(fd, UI_SET_KEYBIT, KEY_J); - ioctl(fd, UI_SET_KEYBIT, KEY_K); - ioctl(fd, UI_SET_KEYBIT, KEY_L); - ioctl(fd, UI_SET_KEYBIT, KEY_Z); - ioctl(fd, UI_SET_KEYBIT, KEY_X); - ioctl(fd, UI_SET_KEYBIT, KEY_C); - ioctl(fd, UI_SET_KEYBIT, KEY_V); - ioctl(fd, UI_SET_KEYBIT, KEY_B); - ioctl(fd, UI_SET_KEYBIT, KEY_N); - ioctl(fd, UI_SET_KEYBIT, KEY_M); - ioctl(fd, UI_SET_KEYBIT, KEY_0); - ioctl(fd, UI_SET_KEYBIT, KEY_1); - ioctl(fd, UI_SET_KEYBIT, KEY_2); - ioctl(fd, UI_SET_KEYBIT, KEY_3); - ioctl(fd, UI_SET_KEYBIT, KEY_4); - ioctl(fd, UI_SET_KEYBIT, KEY_5); - ioctl(fd, UI_SET_KEYBIT, KEY_6); - ioctl(fd, UI_SET_KEYBIT, KEY_7); - ioctl(fd, UI_SET_KEYBIT, KEY_8); - ioctl(fd, UI_SET_KEYBIT, KEY_9); - ioctl(fd, UI_SET_KEYBIT, KEY_UP); - ioctl(fd, UI_SET_KEYBIT, KEY_DOWN); - ioctl(fd, UI_SET_KEYBIT, KEY_LEFT); - ioctl(fd, UI_SET_KEYBIT, KEY_RIGHT); - //ioctl(fd, UI_SET_KEYBIT, KEY_); - - struct uinput_setup dev = {0}; - strncpy(dev.name, VIRT_KBD_DEV_NAME, UINPUT_MAX_NAME_SIZE-1); - dev.id.bustype = BUS_VIRTUAL; - dev.id.vendor = VIRT_KBD_DEV_VENDOR_ID; - dev.id.product = VIRT_KBD_DEV_PRODUCT_ID; - dev.id.version = VIRT_KBD_DEV_VERSION; - - if(ioctl(fd, UI_DEV_SETUP, &dev) < 0) { - ret = errno > 0 ? errno : -1 * errno; - ret = ret == 0 ? -EIO : ret; - goto virt_mouse_init_err; - } - - if(ioctl(fd, UI_DEV_CREATE) < 0) { - ret = errno > 0 ? errno : -1 * errno; - ret = ret == 0 ? -EIO : ret; - goto virt_mouse_init_err; - } - - // initialization ok - kbd->fd = fd; - ret = 0; - -virt_mouse_init_err: - if (ret != 0) { - kbd->fd = -1; - close(fd); - } - - return ret; -} - -int virt_kbd_get_fd(virt_kbd_t *const kbd) { - return kbd->fd; -} - -int virt_kbd_send(virt_kbd_t *const kbd, keyboard_status_t *const status, struct timeval *const now) { - int res = 0; - - size_t events_count = 0; - struct input_event events[12]; - - struct input_event tmp_ev; - - tmp_ev.type = EV_KEY; - - if (status->q != kbd->prev_q) { - tmp_ev.code = KEY_Q; - tmp_ev.value = kbd->prev_q = status->q; - events[events_count++] = tmp_ev; - } - - if (status->w != kbd->prev_w) { - tmp_ev.code = KEY_W; - tmp_ev.value = kbd->prev_w = status->w; - events[events_count++] = tmp_ev; - } - - if (status->e != kbd->prev_e) { - tmp_ev.code = KEY_E; - tmp_ev.value = kbd->prev_e = status->e; - events[events_count++] = tmp_ev; - } - - if (status->r != kbd->prev_r) { - tmp_ev.code = KEY_R; - tmp_ev.value = kbd->prev_r = status->r; - events[events_count++] = tmp_ev; - } - - if (status->t != kbd->prev_t) { - tmp_ev.code = KEY_T; - tmp_ev.value = kbd->prev_t = status->t; - events[events_count++] = tmp_ev; - } - - if (status->y != kbd->prev_y) { - tmp_ev.code = KEY_Y; - tmp_ev.value = kbd->prev_y = status->y; - events[events_count++] = tmp_ev; - } - - if (status->u != kbd->prev_u) { - tmp_ev.code = KEY_U; - tmp_ev.value = kbd->prev_u = status->u; - events[events_count++] = tmp_ev; - } - - if (status->i != kbd->prev_i) { - tmp_ev.code = KEY_I; - tmp_ev.value = kbd->prev_i = status->i; - events[events_count++] = tmp_ev; - } - - if (status->o != kbd->prev_o) { - tmp_ev.code = KEY_O; - tmp_ev.value = kbd->prev_o = status->o; - events[events_count++] = tmp_ev; - } - - if (status->p != kbd->prev_p) { - tmp_ev.code = KEY_P; - tmp_ev.value = kbd->prev_p = status->p; - events[events_count++] = tmp_ev; - } - - if (status->a != kbd->prev_a) { - tmp_ev.code = KEY_A; - tmp_ev.value = kbd->prev_a = status->a; - events[events_count++] = tmp_ev; - } - - if (status->s != kbd->prev_s) { - tmp_ev.code = KEY_S; - tmp_ev.value = kbd->prev_s = status->s; - events[events_count++] = tmp_ev; - } - - - if (status->d != kbd->prev_d) { - tmp_ev.code = KEY_D; - tmp_ev.value = kbd->prev_d = status->d; - events[events_count++] = tmp_ev; - } - - if (status->f != kbd->prev_f) { - tmp_ev.code = KEY_F; - tmp_ev.value = kbd->prev_f = status->f; - events[events_count++] = tmp_ev; - } - - if (status->g != kbd->prev_g) { - tmp_ev.code = KEY_G; - tmp_ev.value = kbd->prev_g = status->g; - events[events_count++] = tmp_ev; - } - - if (status->h != kbd->prev_h) { - tmp_ev.code = KEY_H; - tmp_ev.value = kbd->prev_h = status->h; - events[events_count++] = tmp_ev; - } - - if (status->j != kbd->prev_j) { - tmp_ev.code = KEY_J; - tmp_ev.value = kbd->prev_j = status->j; - events[events_count++] = tmp_ev; - } - - if (status->k != kbd->prev_k) { - tmp_ev.code = KEY_K; - tmp_ev.value = kbd->prev_k = status->k; - events[events_count++] = tmp_ev; - } - - if (status->l != kbd->prev_l) { - tmp_ev.code = KEY_L; - tmp_ev.value = kbd->prev_l = status->l; - events[events_count++] = tmp_ev; - } - - if (status->z != kbd->prev_z) { - tmp_ev.code = KEY_Z; - tmp_ev.value = kbd->prev_z = status->z; - events[events_count++] = tmp_ev; - } - - if (status->x != kbd->prev_x) { - tmp_ev.code = KEY_X; - tmp_ev.value = kbd->prev_x = status->x; - events[events_count++] = tmp_ev; - } - - if (status->c != kbd->prev_c) { - tmp_ev.code = KEY_C; - tmp_ev.value = kbd->prev_c = status->c; - events[events_count++] = tmp_ev; - } - - if (status->v != kbd->prev_v) { - tmp_ev.code = KEY_V; - tmp_ev.value = kbd->prev_v = status->v; - events[events_count++] = tmp_ev; - } - - if (status->b != kbd->prev_b) { - tmp_ev.code = KEY_B; - tmp_ev.value = kbd->prev_b = status->b; - events[events_count++] = tmp_ev; - } - - if (status->n != kbd->prev_n) { - tmp_ev.code = KEY_N; - tmp_ev.value = kbd->prev_n = status->n; - events[events_count++] = tmp_ev; - } - - if (status->m != kbd->prev_m) { - tmp_ev.code = KEY_M; - tmp_ev.value = kbd->prev_m = status->m; - events[events_count++] = tmp_ev; - } - - if (status->num_0 != kbd->prev_num_0) { - tmp_ev.code = KEY_0; - tmp_ev.value = kbd->prev_num_0 = status->num_0; - events[events_count++] = tmp_ev; - } - - if (status->num_1 != kbd->prev_num_1) { - tmp_ev.code = KEY_1; - tmp_ev.value = kbd->prev_num_1 = status->num_1; - events[events_count++] = tmp_ev; - } - - if (status->num_2 != kbd->prev_num_2) { - tmp_ev.code = KEY_2; - tmp_ev.value = kbd->prev_num_2 = status->num_2; - events[events_count++] = tmp_ev; - } - - if (status->num_3 != kbd->prev_num_3) { - tmp_ev.code = KEY_3; - tmp_ev.value = kbd->prev_num_3 = status->num_3; - events[events_count++] = tmp_ev; - } - - if (status->num_4 != kbd->prev_num_4) { - tmp_ev.code = KEY_4; - tmp_ev.value = kbd->prev_num_4 = status->num_4; - events[events_count++] = tmp_ev; - } - - if (status->num_5 != kbd->prev_num_5) { - tmp_ev.code = KEY_5; - tmp_ev.value = kbd->prev_num_5 = status->num_5; - events[events_count++] = tmp_ev; - } - - if (status->num_6 != kbd->prev_num_6) { - tmp_ev.code = KEY_6; - tmp_ev.value = kbd->prev_num_6 = status->num_6; - events[events_count++] = tmp_ev; - } - - if (status->num_7 != kbd->prev_num_7) { - tmp_ev.code = KEY_7; - tmp_ev.value = kbd->prev_num_7 = status->num_7; - events[events_count++] = tmp_ev; - } - - if (status->num_8 != kbd->prev_num_8) { - tmp_ev.code = KEY_8; - tmp_ev.value = kbd->prev_num_8 = status->num_8; - events[events_count++] = tmp_ev; - } - - if (status->num_9 != kbd->prev_num_9) { - tmp_ev.code = KEY_9; - tmp_ev.value = kbd->prev_num_9 = status->num_9; - events[events_count++] = tmp_ev; - } - - if (status->lctrl != kbd->prev_lctrl) { - tmp_ev.code = KEY_LEFTCTRL; - tmp_ev.value = kbd->prev_lctrl = status->lctrl; - events[events_count++] = tmp_ev; - } - - if (status->up != kbd->prev_up) { - tmp_ev.code = KEY_UP; - tmp_ev.value = kbd->prev_up = status->up; - events[events_count++] = tmp_ev; - } - - if (status->down != kbd->prev_down) { - tmp_ev.code = KEY_DOWN; - tmp_ev.value = kbd->prev_down = status->down; - events[events_count++] = tmp_ev; - } - - if (status->left != kbd->prev_left) { - tmp_ev.code = KEY_LEFT; - tmp_ev.value = kbd->prev_left = status->left; - events[events_count++] = tmp_ev; - } - - if (status->right != kbd->prev_right) { - tmp_ev.code = KEY_RIGHT; - tmp_ev.value = kbd->prev_right = status->right; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } - } - - #if 0 - const struct input_event timestamp_ev = { - .code = MSC_TIMESTAMP, - .type = EV_MSC, - .value = (now.tv_sec - secAtInit)*1000000 + (now.tv_usec - usecAtInit), - .time = now, - }; - const ssize_t timestamp_written = write(fd, (void*)×tamp_ev, sizeof(timestamp_ev)); - if (timestamp_written != sizeof(timestamp_ev)) { - fprintf(stderr, "Error in sync: written %ld bytes out of %ld\n", timestamp_written, sizeof(timestamp_ev)); - } - #endif - - if (events_count > 0) { - struct timeval t; - if (now != NULL) { - t = *now; - } else { - gettimeofday(&t, NULL); - } - - struct input_event syn_ev = { - .code = SYN_REPORT, - .type = EV_SYN, - .value = 0, - .time = t, - }; - syn_ev.time.tv_usec += 1; - - events[events_count++] = syn_ev; - - for (size_t i = 0; i < events_count; ++i) { - if (i != (events_count - 1)) { - events[i].time = t; - } - - const ssize_t sync_written = write(kbd->fd, (void*)&events[i], sizeof(struct input_event)); - if (sync_written != sizeof(syn_ev)) { - fprintf(stderr, "Error in sync: written %ld bytes out of %ld\n", sync_written, sizeof(syn_ev)); - res = errno; - res = res < 0 ? res : -1*res; - res = res == 0 ? -EIO : res; - goto virt_kbd_send_err; - } - } - } -virt_kbd_send_err: - return res; -} - -void virt_kbd_close(virt_kbd_t *const kbd) { - close(kbd->fd); -} \ No newline at end of file diff --git a/virt_kbd.h b/virt_kbd.h deleted file mode 100644 index 542039a..0000000 --- a/virt_kbd.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include "message.h" -#include "devices_status.h" - -#define VIRT_KBD_DEV_NAME "ROGueENEMY - kbd" -#define VIRT_KBD_DEV_VENDOR_ID 0x108c -#define VIRT_KBD_DEV_PRODUCT_ID 0x0323 -#define VIRT_KBD_DEV_VERSION 0x0111 - -typedef struct virt_kbd { - int fd; - - uint8_t prev_q; - uint8_t prev_w; - uint8_t prev_e; - uint8_t prev_r; - uint8_t prev_t; - uint8_t prev_y; - uint8_t prev_u; - uint8_t prev_i; - uint8_t prev_o; - uint8_t prev_p; - uint8_t prev_a; - uint8_t prev_s; - uint8_t prev_d; - uint8_t prev_f; - uint8_t prev_g; - uint8_t prev_h; - uint8_t prev_j; - uint8_t prev_k; - uint8_t prev_l; - uint8_t prev_z; - uint8_t prev_x; - uint8_t prev_c; - uint8_t prev_v; - uint8_t prev_b; - uint8_t prev_n; - uint8_t prev_m; - - uint8_t prev_num_1; - uint8_t prev_num_2; - uint8_t prev_num_3; - uint8_t prev_num_4; - uint8_t prev_num_5; - uint8_t prev_num_6; - uint8_t prev_num_7; - uint8_t prev_num_8; - uint8_t prev_num_9; - uint8_t prev_num_0; - - uint8_t prev_up; - uint8_t prev_down; - uint8_t prev_left; - uint8_t prev_right; - - uint8_t prev_lctrl; - -} virt_kbd_t; - -int virt_kbd_init(virt_kbd_t *const mouse); - -int virt_kbd_get_fd(virt_kbd_t *const mouse); - -int virt_kbd_send(virt_kbd_t *const mouse, keyboard_status_t *const status, struct timeval *const now); - -void virt_kbd_close(virt_kbd_t *const mouse); \ No newline at end of file diff --git a/virt_mouse.c b/virt_mouse.c deleted file mode 100644 index ff02eaf..0000000 --- a/virt_mouse.c +++ /dev/null @@ -1,163 +0,0 @@ -#include "virt_mouse.h" - -int virt_mouse_init(virt_mouse_t *const mouse) { - int ret = -EINVAL; - - mouse->status_recv = 0; - - int fd = open("/dev/uinput", O_RDWR); - if(fd < 0) { - ret = errno; - goto virt_mouse_init_err; - } - - ioctl(fd, UI_SET_EVBIT, EV_REL); - ioctl(fd, UI_SET_EVBIT, EV_KEY); - ioctl(fd, UI_SET_EVBIT, EV_MSC); - ioctl(fd, UI_SET_EVBIT, EV_SYN); - ioctl(fd, UI_SET_MSCBIT, MSC_TIMESTAMP); - ioctl(fd, UI_SET_KEYBIT, BTN_LEFT); - ioctl(fd, UI_SET_KEYBIT, BTN_MIDDLE); - ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT); - ioctl(fd, UI_SET_RELBIT, REL_X); - ioctl(fd, UI_SET_RELBIT, REL_Y); - ioctl(fd, UI_SET_RELBIT, REL_WHEEL); - ioctl(fd, UI_SET_RELBIT, REL_WHEEL_HI_RES); - - struct uinput_setup dev = {0}; - strncpy(dev.name, VIRT_MOUSE_DEV_NAME, UINPUT_MAX_NAME_SIZE-1); - dev.id.bustype = BUS_VIRTUAL; - dev.id.vendor = VIRT_MOUSE_DEV_VENDOR_ID; - dev.id.product = VIRT_MOUSE_DEV_PRODUCT_ID; - dev.id.version = VIRT_MOUSE_DEV_VERSION; - - if(ioctl(fd, UI_DEV_SETUP, &dev) < 0) { - ret = errno > 0 ? errno : -1 * errno; - ret = ret == 0 ? -EIO : ret; - goto virt_mouse_init_err; - } - - if(ioctl(fd, UI_DEV_CREATE) < 0) { - ret = errno > 0 ? errno : -1 * errno; - ret = ret == 0 ? -EIO : ret; - goto virt_mouse_init_err; - } - - // initialization ok - mouse->prev_btn_left = 0; - mouse->prev_btn_right = 0; - mouse->prev_btn_middle = 0; - mouse->fd = fd; - ret = 0; - -virt_mouse_init_err: - if (ret != 0) { - mouse->fd = -1; - close(fd); - } - - return ret; -} - -int virt_mouse_get_fd(virt_mouse_t *const mouse) { - return mouse->fd; -} - -int virt_mouse_send(virt_mouse_t *const mouse, mouse_status_t *const status, struct timeval *const now) { - int res = 0; - - size_t events_count = 0; - struct input_event events[12]; - - struct input_event tmp_ev; - tmp_ev.type = EV_REL; - - if (status->x != 0) { - tmp_ev.code = REL_X; - tmp_ev.value = status->x; - events[events_count++] = tmp_ev; - } - - if (status->y != 0) { - tmp_ev.code = REL_Y; - tmp_ev.value = status->y; - events[events_count++] = tmp_ev; - } - - tmp_ev.type = EV_KEY; - - if (status->btn_left != mouse->prev_btn_left) { - mouse->prev_btn_left = status->btn_left; - tmp_ev.code = BTN_LEFT; - tmp_ev.value = status->btn_left; - events[events_count++] = tmp_ev; - } - - if (status->btn_middle != mouse->prev_btn_middle) { - mouse->prev_btn_middle = status->btn_middle; - tmp_ev.code = BTN_MIDDLE; - tmp_ev.value = status->btn_middle; - events[events_count++] = tmp_ev; - } - - if (status->btn_right != mouse->prev_btn_right) { - mouse->prev_btn_right = status->btn_right; - tmp_ev.code = BTN_RIGHT; - tmp_ev.value = status->btn_right; - events[events_count++] = tmp_ev; - } - - #if 0 - const struct input_event timestamp_ev = { - .code = MSC_TIMESTAMP, - .type = EV_MSC, - .value = (now.tv_sec - secAtInit)*1000000 + (now.tv_usec - usecAtInit), - .time = now, - }; - const ssize_t timestamp_written = write(fd, (void*)×tamp_ev, sizeof(timestamp_ev)); - if (timestamp_written != sizeof(timestamp_ev)) { - fprintf(stderr, "Error in sync: written %ld bytes out of %ld\n", timestamp_written, sizeof(timestamp_ev)); - } - #endif - - if (events_count > 0) { - struct timeval t; - if (now != NULL) { - t = *now; - } else { - gettimeofday(&t, NULL); - } - - struct input_event syn_ev = { - .code = SYN_REPORT, - .type = EV_SYN, - .value = 0, - .time = t, - }; - syn_ev.time.tv_usec += 1; - - events[events_count++] = syn_ev; - - for (size_t i = 0; i < events_count; ++i) { - if (i != (events_count - 1)) { - events[i].time = t; - } - - const ssize_t sync_written = write(mouse->fd, (void*)&events[i], sizeof(struct input_event)); - if (sync_written != sizeof(syn_ev)) { - fprintf(stderr, "Error in sync: written %ld bytes out of %ld\n", sync_written, sizeof(syn_ev)); - res = errno; - res = res < 0 ? res : -1*res; - res = res == 0 ? -EIO : res; - goto virt_mouse_send_err; - } - } - } - -virt_mouse_send_err: - return res; -} - -void virt_mouse_close(virt_mouse_t *const mouse) { - close(mouse->fd); -} \ No newline at end of file diff --git a/virt_mouse.h b/virt_mouse.h deleted file mode 100644 index 2c6477a..0000000 --- a/virt_mouse.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "message.h" -#include "devices_status.h" - -#define VIRT_MOUSE_DEV_NAME "ROGueENEMY - mouse" -#define VIRT_MOUSE_DEV_VENDOR_ID 0x108c -#define VIRT_MOUSE_DEV_PRODUCT_ID 0x0323 -#define VIRT_MOUSE_DEV_VERSION 0x0111 - -typedef struct virt_mouse { - int fd; - - uint8_t prev_btn_left; - uint8_t prev_btn_right; - uint8_t prev_btn_middle; - - uint64_t status_recv; - -} virt_mouse_t; - -int virt_mouse_init(virt_mouse_t *const mouse); - -int virt_mouse_get_fd(virt_mouse_t *const mouse); - -int virt_mouse_send(virt_mouse_t *const mouse, mouse_status_t *const status, struct timeval *const now); - -void virt_mouse_close(virt_mouse_t *const mouse); \ No newline at end of file diff --git a/xbox360.c b/xbox360.c index 5f72592..bb0de29 100644 --- a/xbox360.c +++ b/xbox360.c @@ -1,13 +1,8 @@ #include "xbox360.h" #include "message.h" -int xbox360_ev_map( - const dev_in_settings_t *const conf, - const evdev_collected_t *const coll, - in_message_t *const messages, - size_t messages_len, - void* user_data -) { +int xbox360_ev_map(const evdev_collected_t *const coll, in_message_t *const messages, size_t messages_len, void* user_data) { + const xbox360_settings_t *const settings = (xbox360_settings_t*)user_data; int written_msg = 0; for (uint32_t i = 0; i < coll->ev_count; ++i) { @@ -17,16 +12,16 @@ int xbox360_ev_map( }; if (coll->ev[i].code == BTN_EAST) { - current_message.data.gamepad_set.element = GAMEPAD_BTN_CIRCLE; + current_message.data.gamepad_set.element = (settings->nintendo_layout) ? GAMEPAD_BTN_CROSS : GAMEPAD_BTN_CIRCLE; 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 = GAMEPAD_BTN_SQUARE; + current_message.data.gamepad_set.element = (settings->nintendo_layout) ? GAMEPAD_BTN_TRIANGLE : GAMEPAD_BTN_SQUARE; 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 = GAMEPAD_BTN_CROSS; + current_message.data.gamepad_set.element = (settings->nintendo_layout) ? GAMEPAD_BTN_CIRCLE : GAMEPAD_BTN_CROSS; 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 = GAMEPAD_BTN_TRIANGLE; + current_message.data.gamepad_set.element = (settings->nintendo_layout) ? GAMEPAD_BTN_SQUARE : GAMEPAD_BTN_TRIANGLE; 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; diff --git a/xbox360.h b/xbox360.h index 2df7ec8..824c30f 100644 --- a/xbox360.h +++ b/xbox360.h @@ -2,10 +2,8 @@ #include "input_dev.h" -int xbox360_ev_map( - const dev_in_settings_t *const conf, - const evdev_collected_t *const coll, - in_message_t *const messages, - size_t messages_len, - void* user_data -); +typedef struct xbox360_settings { + bool nintendo_layout; +} xbox360_settings_t; + +int xbox360_ev_map(const evdev_collected_t *const coll, in_message_t *const messages, size_t messages_len, void* user_data);