| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2017-01-08 21:29:57 +01:00
										 |  |  | /*  joypad_linux.cpp                                                     */ | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2017-08-27 14:16:55 +02:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2022-01-03 21:27:34 +01:00
										 |  |  | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-21 22:39:03 +01:00
										 |  |  | #ifdef JOYDEV_ENABLED
 | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 21:29:57 +01:00
										 |  |  | #include "joypad_linux.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 15:06:19 +02:00
										 |  |  | #include <dirent.h>
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | #include <linux/input.h>
 | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-15 15:09:48 +01:00
										 |  |  | #ifdef UDEV_ENABLED
 | 
					
						
							| 
									
										
										
										
											2021-02-17 11:28:27 +01:00
										 |  |  | #include "libudev-so_wrap.h"
 | 
					
						
							| 
									
										
										
										
											2016-02-15 15:09:48 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | #define LONG_BITS (sizeof(long) * 8)
 | 
					
						
							|  |  |  | #define test_bit(nr, addr) (((1UL << ((nr) % LONG_BITS)) & ((addr)[(nr) / LONG_BITS])) != 0)
 | 
					
						
							|  |  |  | #define NBITS(x) ((((x)-1) / LONG_BITS) + 1)
 | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-03 23:19:22 +02:00
										 |  |  | #ifdef UDEV_ENABLED
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | static const char *ignore_str = "/dev/input/js"; | 
					
						
							| 
									
										
										
										
											2016-07-03 23:19:22 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | JoypadLinux::Joypad::~Joypad() { | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 	for (int i = 0; i < MAX_ABS; i++) { | 
					
						
							|  |  |  | 		if (abs_info[i]) { | 
					
						
							|  |  |  | 			memdelete(abs_info[i]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | void JoypadLinux::Joypad::reset() { | 
					
						
							| 
									
										
										
										
											2021-08-13 16:31:57 -05:00
										 |  |  | 	dpad = HatMask::CENTER; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	fd = -1; | 
					
						
							|  |  |  | 	for (int i = 0; i < MAX_ABS; i++) { | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		abs_map[i] = -1; | 
					
						
							| 
									
										
										
										
											2021-12-25 09:29:08 +00:00
										 |  |  | 		curr_axis[i] = 0; | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-28 15:19:37 +02:00
										 |  |  | JoypadLinux::JoypadLinux(Input *in) { | 
					
						
							| 
									
										
										
										
											2021-02-17 11:28:27 +01:00
										 |  |  | #ifdef UDEV_ENABLED
 | 
					
						
							| 
									
										
										
										
											2021-02-20 00:13:33 +01:00
										 |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	int dylibloader_verbose = 1; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	int dylibloader_verbose = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	use_udev = initialize_libudev(dylibloader_verbose) == 0; | 
					
						
							| 
									
										
										
										
											2021-02-17 11:28:27 +01:00
										 |  |  | 	if (use_udev) { | 
					
						
							|  |  |  | 		print_verbose("JoypadLinux: udev enabled and loaded successfully."); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		print_verbose("JoypadLinux: udev enabled, but couldn't be loaded. Falling back to /dev/input to detect joypads."); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	print_verbose("JoypadLinux: udev disabled, parsing /dev/input to detect joypads."); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	input = in; | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | 	joy_thread.start(joy_thread_func, this); | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | JoypadLinux::~JoypadLinux() { | 
					
						
							| 
									
										
										
										
											2021-02-10 19:22:13 +01:00
										 |  |  | 	exit_monitor.set(); | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | 	joy_thread.wait_to_finish(); | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 	close_joypad(); | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | void JoypadLinux::joy_thread_func(void *p_user) { | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	if (p_user) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		JoypadLinux *joy = (JoypadLinux *)p_user; | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 		joy->run_joypad_thread(); | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | void JoypadLinux::run_joypad_thread() { | 
					
						
							| 
									
										
										
										
											2016-02-14 15:13:11 +01:00
										 |  |  | #ifdef UDEV_ENABLED
 | 
					
						
							| 
									
										
										
										
											2021-02-17 11:28:27 +01:00
										 |  |  | 	if (use_udev) { | 
					
						
							|  |  |  | 		udev *_udev = udev_new(); | 
					
						
							|  |  |  | 		if (!_udev) { | 
					
						
							|  |  |  | 			use_udev = false; | 
					
						
							| 
									
										
										
										
											2021-02-18 10:28:37 +01:00
										 |  |  | 			ERR_PRINT("Failed getting an udev context, falling back to parsing /dev/input."); | 
					
						
							|  |  |  | 			monitor_joypads(); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			enumerate_joypads(_udev); | 
					
						
							|  |  |  | 			monitor_joypads(_udev); | 
					
						
							|  |  |  | 			udev_unref(_udev); | 
					
						
							| 
									
										
										
										
											2021-02-17 11:28:27 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		monitor_joypads(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-14 15:13:11 +01:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 	monitor_joypads(); | 
					
						
							| 
									
										
										
										
											2016-02-14 15:13:11 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-14 15:13:11 +01:00
										 |  |  | #ifdef UDEV_ENABLED
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | void JoypadLinux::enumerate_joypads(udev *p_udev) { | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	udev_enumerate *enumerate; | 
					
						
							|  |  |  | 	udev_list_entry *devices, *dev_list_entry; | 
					
						
							|  |  |  | 	udev_device *dev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	enumerate = udev_enumerate_new(p_udev); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	udev_enumerate_add_match_subsystem(enumerate, "input"); | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	udev_enumerate_scan_devices(enumerate); | 
					
						
							|  |  |  | 	devices = udev_enumerate_get_list_entry(enumerate); | 
					
						
							|  |  |  | 	udev_list_entry_foreach(dev_list_entry, devices) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		const char *path = udev_list_entry_get_name(dev_list_entry); | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		dev = udev_device_new_from_syspath(p_udev, path); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		const char *devnode = udev_device_get_devnode(dev); | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		if (devnode) { | 
					
						
							|  |  |  | 			String devnode_str = devnode; | 
					
						
							|  |  |  | 			if (devnode_str.find(ignore_str) == -1) { | 
					
						
							| 
									
										
										
										
											2020-02-26 11:28:13 +01:00
										 |  |  | 				MutexLock lock(joy_mutex); | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 				open_joypad(devnode); | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		udev_device_unref(dev); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	udev_enumerate_unref(enumerate); | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | void JoypadLinux::monitor_joypads(udev *p_udev) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	udev_device *dev = nullptr; | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	udev_monitor *mon = udev_monitor_new_from_netlink(p_udev, "udev"); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	udev_monitor_filter_add_match_subsystem_devtype(mon, "input", nullptr); | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	udev_monitor_enable_receiving(mon); | 
					
						
							|  |  |  | 	int fd = udev_monitor_get_fd(mon); | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-10 19:22:13 +01:00
										 |  |  | 	while (!exit_monitor.is_set()) { | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		fd_set fds; | 
					
						
							|  |  |  | 		struct timeval tv; | 
					
						
							|  |  |  | 		int ret; | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		FD_ZERO(&fds); | 
					
						
							|  |  |  | 		FD_SET(fd, &fds); | 
					
						
							|  |  |  | 		tv.tv_sec = 0; | 
					
						
							|  |  |  | 		tv.tv_usec = 0; | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		ret = select(fd + 1, &fds, nullptr, nullptr, &tv); | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		/* Check if our file descriptor has received data. */ | 
					
						
							|  |  |  | 		if (ret > 0 && FD_ISSET(fd, &fds)) { | 
					
						
							|  |  |  | 			/* Make the call to receive the device.
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 			   select() ensured that this will not block. */ | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 			dev = udev_monitor_receive_device(mon); | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:02:50 +02:00
										 |  |  | 			if (dev && udev_device_get_devnode(dev) != nullptr) { | 
					
						
							| 
									
										
										
										
											2020-02-26 11:28:13 +01:00
										 |  |  | 				MutexLock lock(joy_mutex); | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 				String action = udev_device_get_action(dev); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				const char *devnode = udev_device_get_devnode(dev); | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 				if (devnode) { | 
					
						
							|  |  |  | 					String devnode_str = devnode; | 
					
						
							|  |  |  | 					if (devnode_str.find(ignore_str) == -1) { | 
					
						
							| 
									
										
										
										
											2021-04-05 14:09:59 +02:00
										 |  |  | 						if (action == "add") { | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 							open_joypad(devnode); | 
					
						
							| 
									
										
										
										
											2021-04-05 14:09:59 +02:00
										 |  |  | 						} else if (String(action) == "remove") { | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 							close_joypad(get_joy_from_path(devnode)); | 
					
						
							| 
									
										
										
										
											2021-04-05 14:09:59 +02:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 				udev_device_unref(dev); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		usleep(50000); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	udev_monitor_unref(mon); | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-02-14 15:13:11 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | void JoypadLinux::monitor_joypads() { | 
					
						
							| 
									
										
										
										
											2021-02-10 19:22:13 +01:00
										 |  |  | 	while (!exit_monitor.is_set()) { | 
					
						
							| 
									
										
										
										
											2020-02-26 11:28:13 +01:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			MutexLock lock(joy_mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 15:06:19 +02:00
										 |  |  | 			DIR *input_directory; | 
					
						
							|  |  |  | 			input_directory = opendir("/dev/input"); | 
					
						
							|  |  |  | 			if (input_directory) { | 
					
						
							|  |  |  | 				struct dirent *current; | 
					
						
							| 
									
										
										
										
											2020-02-26 11:28:13 +01:00
										 |  |  | 				char fname[64]; | 
					
						
							| 
									
										
										
										
											2021-01-26 15:06:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:02:50 +02:00
										 |  |  | 				while ((current = readdir(input_directory)) != nullptr) { | 
					
						
							| 
									
										
										
										
											2021-01-26 15:06:19 +02:00
										 |  |  | 					if (strncmp(current->d_name, "event", 5) != 0) { | 
					
						
							|  |  |  | 						continue; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					sprintf(fname, "/dev/input/%.*s", 16, current->d_name); | 
					
						
							|  |  |  | 					if (attached_devices.find(fname) == -1) { | 
					
						
							|  |  |  | 						open_joypad(fname); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2020-02-26 11:28:13 +01:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-02-14 15:13:11 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-01-26 15:06:19 +02:00
										 |  |  | 			closedir(input_directory); | 
					
						
							| 
									
										
										
										
											2016-02-14 15:13:11 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		usleep(1000000); // 1s
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | int JoypadLinux::get_joy_from_path(String p_path) const { | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 	for (int i = 0; i < JOYPADS_MAX; i++) { | 
					
						
							|  |  |  | 		if (joypads[i].devpath == p_path) { | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 			return i; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return -2; | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | void JoypadLinux::close_joypad(int p_id) { | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	if (p_id == -1) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		for (int i = 0; i < JOYPADS_MAX; i++) { | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 			close_joypad(i); | 
					
						
							| 
									
										
										
										
											2022-02-16 13:56:32 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} else if (p_id < 0) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 	Joypad &joy = joypads[p_id]; | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	if (joy.fd != -1) { | 
					
						
							|  |  |  | 		close(joy.fd); | 
					
						
							|  |  |  | 		joy.fd = -1; | 
					
						
							| 
									
										
										
										
											2021-07-03 16:17:03 -06:00
										 |  |  | 		attached_devices.remove_at(attached_devices.find(joy.devpath)); | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		input->joy_connection_changed(p_id, false, ""); | 
					
						
							| 
									
										
										
										
											2022-02-16 13:56:32 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-07-21 21:11:34 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | static String _hex_str(uint8_t p_byte) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	static const char *dict = "0123456789abcdef"; | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	char ret[3]; | 
					
						
							|  |  |  | 	ret[2] = 0; | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ret[0] = dict[p_byte >> 4]; | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	ret[1] = dict[p_byte & 0xF]; | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2016-07-21 21:11:34 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | void JoypadLinux::setup_joypad_properties(int p_id) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	Joypad *joy = &joypads[p_id]; | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	unsigned long keybit[NBITS(KEY_MAX)] = { 0 }; | 
					
						
							|  |  |  | 	unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; | 
					
						
							| 
									
										
										
										
											2016-01-02 03:52:44 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int num_buttons = 0; | 
					
						
							|  |  |  | 	int num_axes = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 	if ((ioctl(joy->fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) || | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			(ioctl(joy->fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) { | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	for (int i = BTN_JOYSTICK; i < KEY_MAX; ++i) { | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		if (test_bit(i, keybit)) { | 
					
						
							| 
									
										
										
										
											2016-01-02 03:52:44 +01:00
										 |  |  | 			joy->key_map[i] = num_buttons++; | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for (int i = BTN_MISC; i < BTN_JOYSTICK; ++i) { | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		if (test_bit(i, keybit)) { | 
					
						
							| 
									
										
										
										
											2016-01-02 03:52:44 +01:00
										 |  |  | 			joy->key_map[i] = num_buttons++; | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for (int i = 0; i < ABS_MISC; ++i) { | 
					
						
							|  |  |  | 		/* Skip hats */ | 
					
						
							|  |  |  | 		if (i == ABS_HAT0X) { | 
					
						
							|  |  |  | 			i = ABS_HAT3Y; | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		if (test_bit(i, absbit)) { | 
					
						
							| 
									
										
										
										
											2016-01-02 03:52:44 +01:00
										 |  |  | 			joy->abs_map[i] = num_axes++; | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 			joy->abs_info[i] = memnew(input_absinfo); | 
					
						
							|  |  |  | 			if (ioctl(joy->fd, EVIOCGABS(i), joy->abs_info[i]) < 0) { | 
					
						
							|  |  |  | 				memdelete(joy->abs_info[i]); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 				joy->abs_info[i] = nullptr; | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-15 07:25:35 +02:00
										 |  |  | 	joy->force_feedback = false; | 
					
						
							|  |  |  | 	joy->ff_effect_timestamp = 0; | 
					
						
							|  |  |  | 	unsigned long ffbit[NBITS(FF_CNT)]; | 
					
						
							|  |  |  | 	if (ioctl(joy->fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) != -1) { | 
					
						
							|  |  |  | 		if (test_bit(FF_RUMBLE, ffbit)) { | 
					
						
							|  |  |  | 			joy->force_feedback = true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:22:00 +01:00
										 |  |  | void JoypadLinux::open_joypad(const char *p_path) { | 
					
						
							| 
									
										
										
										
											2017-02-21 17:02:49 +01:00
										 |  |  | 	int joy_num = input->get_unused_joy_id(); | 
					
						
							| 
									
										
										
										
											2016-06-15 07:25:35 +02:00
										 |  |  | 	int fd = open(p_path, O_RDWR | O_NONBLOCK); | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	if (fd != -1 && joy_num != -1) { | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		unsigned long evbit[NBITS(EV_MAX)] = { 0 }; | 
					
						
							|  |  |  | 		unsigned long keybit[NBITS(KEY_MAX)] = { 0 }; | 
					
						
							|  |  |  | 		unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-14 15:13:11 +01:00
										 |  |  | 		// add to attached devices so we don't try to open it again
 | 
					
						
							|  |  |  | 		attached_devices.push_back(String(p_path)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		if ((ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) || | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				(ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) || | 
					
						
							|  |  |  | 				(ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) { | 
					
						
							| 
									
										
										
										
											2016-02-01 13:39:50 +01:00
										 |  |  | 			close(fd); | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:16:35 +01:00
										 |  |  | 		// Check if the device supports basic gamepad events
 | 
					
						
							| 
									
										
										
										
											2022-02-03 22:56:43 -05:00
										 |  |  | 		bool has_abs_left = (test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit)); | 
					
						
							|  |  |  | 		bool has_abs_right = (test_bit(ABS_RX, absbit) && test_bit(ABS_RY, absbit)); | 
					
						
							|  |  |  | 		if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) && (has_abs_left || has_abs_right))) { | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 			close(fd); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		char uid[128]; | 
					
						
							|  |  |  | 		char namebuf[128]; | 
					
						
							|  |  |  | 		String name = ""; | 
					
						
							|  |  |  | 		input_id inpid; | 
					
						
							|  |  |  | 		if (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) >= 0) { | 
					
						
							|  |  |  | 			name = namebuf; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		if (ioctl(fd, EVIOCGID, &inpid) < 0) { | 
					
						
							|  |  |  | 			close(fd); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 		joypads[joy_num].reset(); | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 		Joypad &joy = joypads[joy_num]; | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		joy.fd = fd; | 
					
						
							|  |  |  | 		joy.devpath = String(p_path); | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 		setup_joypad_properties(joy_num); | 
					
						
							| 
									
										
										
										
											2019-03-05 22:17:20 +01:00
										 |  |  | 		sprintf(uid, "%04x%04x", BSWAP16(inpid.bustype), 0); | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		if (inpid.vendor && inpid.product && inpid.version) { | 
					
						
							| 
									
										
										
										
											2019-03-05 22:17:20 +01:00
										 |  |  | 			uint16_t vendor = BSWAP16(inpid.vendor); | 
					
						
							|  |  |  | 			uint16_t product = BSWAP16(inpid.product); | 
					
						
							|  |  |  | 			uint16_t version = BSWAP16(inpid.version); | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor, 0, product, 0, version, 0); | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 			input->joy_connection_changed(joy_num, true, name, uid); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 			String uidname = uid; | 
					
						
							|  |  |  | 			int uidlen = MIN(name.length(), 11); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			for (int i = 0; i < uidlen; i++) { | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 				uidname = uidname + _hex_str(name[i]); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			uidname += "00"; | 
					
						
							|  |  |  | 			input->joy_connection_changed(joy_num, true, name, uidname); | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void JoypadLinux::joypad_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp) { | 
					
						
							|  |  |  | 	Joypad &joy = joypads[p_id]; | 
					
						
							| 
									
										
										
										
											2016-06-15 07:25:35 +02:00
										 |  |  | 	if (!joy.force_feedback || joy.fd == -1 || p_weak_magnitude < 0.f || p_weak_magnitude > 1.f || p_strong_magnitude < 0.f || p_strong_magnitude > 1.f) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (joy.ff_effect_id != -1) { | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 		joypad_vibration_stop(p_id, p_timestamp); | 
					
						
							| 
									
										
										
										
											2016-06-15 07:25:35 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct ff_effect effect; | 
					
						
							|  |  |  | 	effect.type = FF_RUMBLE; | 
					
						
							|  |  |  | 	effect.id = -1; | 
					
						
							|  |  |  | 	effect.u.rumble.weak_magnitude = floor(p_weak_magnitude * (float)0xffff); | 
					
						
							|  |  |  | 	effect.u.rumble.strong_magnitude = floor(p_strong_magnitude * (float)0xffff); | 
					
						
							|  |  |  | 	effect.replay.length = floor(p_duration * 1000); | 
					
						
							|  |  |  | 	effect.replay.delay = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ioctl(joy.fd, EVIOCSFF, &effect) < 0) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct input_event play; | 
					
						
							|  |  |  | 	play.type = EV_FF; | 
					
						
							|  |  |  | 	play.code = effect.id; | 
					
						
							|  |  |  | 	play.value = 1; | 
					
						
							| 
									
										
										
										
											2019-06-19 10:41:07 +02:00
										 |  |  | 	if (write(joy.fd, (const void *)&play, sizeof(play)) == -1) { | 
					
						
							|  |  |  | 		print_verbose("Couldn't write to Joypad device."); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-15 07:25:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	joy.ff_effect_id = effect.id; | 
					
						
							|  |  |  | 	joy.ff_effect_timestamp = p_timestamp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void JoypadLinux::joypad_vibration_stop(int p_id, uint64_t p_timestamp) { | 
					
						
							|  |  |  | 	Joypad &joy = joypads[p_id]; | 
					
						
							| 
									
										
										
										
											2016-06-15 07:25:35 +02:00
										 |  |  | 	if (!joy.force_feedback || joy.fd == -1 || joy.ff_effect_id == -1) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-20 11:01:07 +02:00
										 |  |  | 	if (ioctl(joy.fd, EVIOCRMFF, joy.ff_effect_id) < 0) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-15 07:25:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	joy.ff_effect_id = -1; | 
					
						
							|  |  |  | 	joy.ff_effect_timestamp = p_timestamp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-25 09:29:08 +00:00
										 |  |  | float JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const { | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	int min = p_abs->minimum; | 
					
						
							|  |  |  | 	int max = p_abs->maximum; | 
					
						
							| 
									
										
										
										
											2021-12-25 09:29:08 +00:00
										 |  |  | 	// Convert to a value between -1.0f and 1.0f.
 | 
					
						
							|  |  |  | 	return 2.0f * (p_value - min) / (max - min) - 1.0f; | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-26 15:59:13 +02:00
										 |  |  | void JoypadLinux::process_joypads() { | 
					
						
							| 
									
										
										
										
											2020-02-26 11:28:13 +01:00
										 |  |  | 	if (joy_mutex.try_lock() != OK) { | 
					
						
							| 
									
										
										
										
											2017-03-26 15:59:13 +02:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < JOYPADS_MAX; i++) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (joypads[i].fd == -1) { | 
					
						
							| 
									
										
										
										
											2020-05-10 12:56:01 +02:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		input_event events[32]; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		Joypad *joy = &joypads[i]; | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		int len; | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 		while ((len = read(joy->fd, events, (sizeof events))) > 0) { | 
					
						
							|  |  |  | 			len /= sizeof(events[0]); | 
					
						
							|  |  |  | 			for (int j = 0; j < len; j++) { | 
					
						
							|  |  |  | 				input_event &ev = events[j]; | 
					
						
							| 
									
										
										
										
											2016-02-28 20:20:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// ev may be tainted and out of MAX_KEY range, which will cause
 | 
					
						
							|  |  |  | 				// joy->key_map[ev.code] to crash
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				if (ev.code >= MAX_KEY) { | 
					
						
							| 
									
										
										
										
											2017-03-26 15:59:13 +02:00
										 |  |  | 					return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-02-28 20:20:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 				switch (ev.type) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					case EV_KEY: | 
					
						
							| 
									
										
										
										
											2021-03-25 16:56:12 -04:00
										 |  |  | 						input->joy_button(i, (JoyButton)joy->key_map[ev.code], ev.value); | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 						break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					case EV_ABS: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						switch (ev.code) { | 
					
						
							|  |  |  | 							case ABS_HAT0X: | 
					
						
							|  |  |  | 								if (ev.value != 0) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 									if (ev.value < 0) { | 
					
						
							| 
									
										
										
										
											2021-08-13 16:31:57 -05:00
										 |  |  | 										joy->dpad = (HatMask)((joy->dpad | HatMask::LEFT) & ~HatMask::RIGHT); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 									} else { | 
					
						
							| 
									
										
										
										
											2021-08-13 16:31:57 -05:00
										 |  |  | 										joy->dpad = (HatMask)((joy->dpad | HatMask::RIGHT) & ~HatMask::LEFT); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 									} | 
					
						
							|  |  |  | 								} else { | 
					
						
							| 
									
										
										
										
											2021-08-13 16:31:57 -05:00
										 |  |  | 									joy->dpad &= ~(HatMask::LEFT | HatMask::RIGHT); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-25 16:56:12 -04:00
										 |  |  | 								input->joy_hat(i, (HatMask)joy->dpad); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 								break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							case ABS_HAT0Y: | 
					
						
							|  |  |  | 								if (ev.value != 0) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 									if (ev.value < 0) { | 
					
						
							| 
									
										
										
										
											2021-08-13 16:31:57 -05:00
										 |  |  | 										joy->dpad = (HatMask)((joy->dpad | HatMask::UP) & ~HatMask::DOWN); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 									} else { | 
					
						
							| 
									
										
										
										
											2021-08-13 16:31:57 -05:00
										 |  |  | 										joy->dpad = (HatMask)((joy->dpad | HatMask::DOWN) & ~HatMask::UP); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 									} | 
					
						
							|  |  |  | 								} else { | 
					
						
							| 
									
										
										
										
											2021-08-13 16:31:57 -05:00
										 |  |  | 									joy->dpad &= ~(HatMask::UP | HatMask::DOWN); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-25 16:56:12 -04:00
										 |  |  | 								input->joy_hat(i, (HatMask)joy->dpad); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 								break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							default: | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 								if (ev.code >= MAX_ABS) { | 
					
						
							| 
									
										
										
										
											2019-07-23 09:14:31 +02:00
										 |  |  | 									return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 								if (joy->abs_map[ev.code] != -1 && joy->abs_info[ev.code]) { | 
					
						
							| 
									
										
										
										
											2021-12-25 09:29:08 +00:00
										 |  |  | 									float value = axis_correct(joy->abs_info[ev.code], ev.value); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 									joy->curr_axis[joy->abs_map[ev.code]] = value; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								break; | 
					
						
							| 
									
										
										
										
											2016-01-26 23:04:57 +01:00
										 |  |  | 						} | 
					
						
							|  |  |  | 						break; | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-01-03 02:24:43 +01:00
										 |  |  | 		for (int j = 0; j < MAX_ABS; j++) { | 
					
						
							|  |  |  | 			int index = joy->abs_map[j]; | 
					
						
							|  |  |  | 			if (index != -1) { | 
					
						
							| 
									
										
										
										
											2021-03-25 16:56:12 -04:00
										 |  |  | 				input->joy_axis(i, (JoyAxis)index, joy->curr_axis[index]); | 
					
						
							| 
									
										
										
										
											2016-01-03 02:24:43 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-02-14 15:13:11 +01:00
										 |  |  | 		if (len == 0 || (len < 0 && errno != EAGAIN)) { | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 			close_joypad(i); | 
					
						
							| 
									
										
										
										
											2022-02-16 13:56:32 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-06-15 07:25:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (joy->force_feedback) { | 
					
						
							|  |  |  | 			uint64_t timestamp = input->get_joy_vibration_timestamp(i); | 
					
						
							|  |  |  | 			if (timestamp > joy->ff_effect_timestamp) { | 
					
						
							|  |  |  | 				Vector2 strength = input->get_joy_vibration_strength(i); | 
					
						
							|  |  |  | 				float duration = input->get_joy_vibration_duration(i); | 
					
						
							|  |  |  | 				if (strength.x == 0 && strength.y == 0) { | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 					joypad_vibration_stop(i, timestamp); | 
					
						
							| 
									
										
										
										
											2016-06-15 07:25:35 +02:00
										 |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2017-01-08 17:05:51 -03:00
										 |  |  | 					joypad_vibration_start(i, strength.x, strength.y, duration, timestamp); | 
					
						
							| 
									
										
										
										
											2016-06-15 07:25:35 +02:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-18 19:15:32 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-26 11:28:13 +01:00
										 |  |  | 	joy_mutex.unlock(); | 
					
						
							| 
									
										
										
										
											2015-12-18 06:12:53 +01:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 |