2013-12-07 14:13:40 +01:00
/* RetroArch - A frontend for libretro.
2015-01-07 17:46:50 +01:00
* Copyright ( C ) 2010 - 2015 - Hans - Kristian Arntzen
2017-01-22 13:40:32 +01:00
* Copyright ( C ) 2011 - 2017 - Daniel De Matteis
2017-10-05 05:18:53 +02:00
*
2013-12-07 14:13:40 +01:00
* RetroArch is free software : you can redistribute it and / or modify it under the terms
* of the GNU General Public License as published by the Free Software Found -
* ation , either version 3 of the License , or ( at your option ) any later version .
*
* RetroArch is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE . See the GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along with RetroArch .
* If not , see < http : //www.gnu.org/licenses/>.
*/
2019-01-01 03:16:33 +03:00
/* TODO/FIXME - set this once the kqueue codepath is implemented and working properly,
* also remove libepoll - shim from the Makefile when that happens . */
2017-11-30 07:28:59 +01:00
# if 1
# define HAVE_EPOLL
# else
# ifdef __linux__
# define HAVE_EPOLL 1
# endif
# if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__)
# define HAVE_KQUEUE 1
# endif
# endif
2013-12-07 14:13:40 +01:00
# include <stdint.h>
# include <string.h>
2015-06-03 17:11:32 +02:00
2015-11-14 22:03:37 +01:00
# include <fcntl.h>
# include <unistd.h>
2013-12-07 14:13:40 +01:00
# include <limits.h>
# include <errno.h>
# include <sys/types.h>
# include <sys/stat.h>
2015-11-14 22:03:37 +01:00
2017-11-30 07:28:59 +01:00
# if defined(HAVE_EPOLL)
2015-12-17 03:02:48 +01:00
# include <sys/epoll.h>
2017-11-30 07:28:59 +01:00
# elif defined(HAVE_KQUEUE)
# include <sys/event.h>
# endif
2019-02-01 09:53:12 -08:00
# include <poll.h>
2021-10-16 19:36:35 +01:00
2013-12-07 14:13:40 +01:00
# include <libudev.h>
2021-05-01 15:37:14 +01:00
# if defined(__linux__)
2013-12-07 14:13:40 +01:00
# include <linux/types.h>
# include <linux/input.h>
2013-12-09 16:56:33 +01:00
# include <linux/kd.h>
2021-05-01 15:37:14 +01:00
# elif defined(__FreeBSD__)
# include <dev/evdev/input.h>
# endif
2013-12-07 14:13:40 +01:00
2016-09-01 18:07:44 +02:00
# ifdef HAVE_CONFIG_H
# include "../../config.h"
# endif
2017-06-03 18:01:27 +02:00
# ifdef HAVE_X11
# include <X11/Xlib.h>
# endif
2015-06-03 17:11:32 +02:00
# include <file/file_path.h>
2016-09-06 00:56:00 +02:00
# include <compat/strl.h>
2016-01-21 02:48:00 +01:00
# include <string/stdstring.h>
2017-05-20 19:44:04 +02:00
# include <retro_miscellaneous.h>
2015-06-03 17:11:32 +02:00
2017-01-10 17:59:48 +01:00
# include "../input_keymaps.h"
2015-11-17 06:46:32 +01:00
# include "../common/linux_common.h"
2015-11-14 09:01:41 +01:00
2019-06-17 15:10:22 +02:00
# include "../../configuration.h"
# include "../../retroarch.h"
2015-11-23 12:03:38 +01:00
# include "../../verbosity.h"
2015-06-03 17:11:32 +02:00
2017-06-12 12:09:19 +02:00
# if defined(HAVE_XKBCOMMON) && defined(HAVE_KMS)
2017-06-07 12:25:10 +02:00
# define UDEV_XKB_HANDLING
# endif
2017-05-20 19:44:04 +02:00
# define UDEV_MAX_KEYS (KEY_MAX + 7) / 8
2013-12-07 16:11:51 +01:00
typedef struct udev_input udev_input_t ;
2013-12-07 22:09:08 +01:00
2017-05-20 19:44:04 +02:00
typedef struct udev_input_device udev_input_device_t ;
2013-12-07 16:11:51 +01:00
2017-06-02 07:57:07 +02:00
enum udev_input_dev_type
{
2017-06-03 18:54:04 +02:00
UDEV_INPUT_KEYBOARD = 0 ,
2017-06-02 07:57:07 +02:00
UDEV_INPUT_MOUSE ,
UDEV_INPUT_TOUCHPAD
} ;
/* NOTE: must be in sync with enum udev_input_dev_type */
static const char * g_dev_type_str [ ] =
{
2021-08-19 15:58:12 -04:00
" ID_INPUT_KEY " ,
2017-06-02 07:57:07 +02:00
" ID_INPUT_MOUSE " ,
" ID_INPUT_TOUCHPAD "
} ;
typedef struct
{
2017-10-05 05:18:53 +02:00
/* If device is "absolute" coords will be in device specific units
and axis min value will be less than max , otherwise coords will be
relative to full viewport and min and max values will be zero . */
2017-10-05 10:00:20 +02:00
int32_t x_abs , y_abs ;
int32_t x_min , y_min ;
int32_t x_max , y_max ;
int32_t x_rel , y_rel ;
2017-12-02 13:24:17 +00:00
bool l , r , m , b4 , b5 ;
2017-06-02 07:57:07 +02:00
bool wu , wd , whu , whd ;
2021-06-26 23:09:47 +01:00
bool pp ;
2017-06-02 07:57:07 +02:00
} udev_input_mouse_t ;
2015-11-29 15:35:34 +01:00
struct udev_input_device
2013-12-07 16:11:51 +01:00
{
2017-05-20 19:44:04 +02:00
void ( * handle_cb ) ( void * data ,
const struct input_event * event , udev_input_device_t * dev ) ;
2020-08-26 15:32:05 +02:00
int fd ;
dev_t dev ;
2017-10-05 05:18:53 +02:00
udev_input_mouse_t mouse ;
2020-08-26 15:32:05 +02:00
enum udev_input_dev_type type ;
char devnode [ PATH_MAX_LENGTH ] ;
2021-09-24 17:31:20 +01:00
char ident [ 255 ] ; /* could be mouse or keyboards store here */
2013-12-07 16:11:51 +01:00
} ;
2017-05-20 19:44:04 +02:00
typedef void ( * device_handle_cb ) ( void * data ,
const struct input_event * event , udev_input_device_t * dev ) ;
2013-12-07 16:11:51 +01:00
struct udev_input
2013-12-07 14:13:40 +01:00
{
2015-12-17 03:02:48 +01:00
struct udev * udev ;
struct udev_monitor * monitor ;
2020-08-30 00:25:21 +02:00
udev_input_device_t * * devices ;
2013-12-07 14:13:40 +01:00
2017-11-30 07:00:09 +01:00
int fd ;
2020-08-30 00:25:21 +02:00
/* OS pointer coords (zeros if we don't have X11) */
int pointer_x ;
int pointer_y ;
2013-12-07 16:11:51 +01:00
unsigned num_devices ;
2017-06-07 12:25:10 +02:00
2020-08-30 04:52:00 +02:00
uint8_t state [ UDEV_MAX_KEYS ] ;
2020-08-30 00:25:21 +02:00
2017-06-07 12:25:10 +02:00
# ifdef UDEV_XKB_HANDLING
bool xkb_handling ;
# endif
2013-12-07 16:11:51 +01:00
} ;
2013-12-07 14:13:40 +01:00
2017-06-07 12:25:10 +02:00
# ifdef UDEV_XKB_HANDLING
int init_xkb ( int fd , size_t size ) ;
void free_xkb ( void ) ;
int handle_xkb ( int code , int value ) ;
# endif
2017-06-19 12:34:01 +02:00
static unsigned input_unify_ev_key_code ( unsigned code )
{
/* input_keymaps_translate_keysym_to_rk does not support the case
2020-09-29 11:23:35 +01:00
* where multiple keysyms translate to the same RETROK_ * code ,
* so unify remote control keysyms to keyboard keysyms here .
*
* Addendum : The rarch_keysym_lut lookup table also becomes
* unusable if more than one keysym translates to the same
* RETROK_ * code , so certain keys must be left unmapped in
* rarch_key_map_linux and instead be handled here */
2017-06-19 12:34:01 +02:00
switch ( code )
{
case KEY_OK :
2020-09-29 11:23:35 +01:00
case KEY_SELECT :
2017-06-19 12:34:01 +02:00
return KEY_ENTER ;
case KEY_BACK :
return KEY_BACKSPACE ;
2020-09-29 11:23:35 +01:00
case KEY_EXIT :
return KEY_CLEAR ;
2017-06-19 12:34:01 +02:00
default :
2020-08-31 03:38:51 +02:00
break ;
2017-06-19 12:34:01 +02:00
}
2020-08-31 03:38:51 +02:00
return code ;
2017-06-19 12:34:01 +02:00
}
2017-05-20 19:44:04 +02:00
static void udev_handle_keyboard ( void * data ,
const struct input_event * event , udev_input_device_t * dev )
{
2017-06-19 12:34:01 +02:00
unsigned keysym ;
2020-08-31 14:04:36 +02:00
udev_input_t * udev = ( udev_input_t * ) data ;
2017-06-07 12:25:10 +02:00
2017-05-20 19:44:04 +02:00
switch ( event - > type )
{
case EV_KEY :
2017-06-19 12:34:01 +02:00
keysym = input_unify_ev_key_code ( event - > code ) ;
2019-06-20 06:26:29 +02:00
if ( event - > value & & video_driver_has_focus ( ) )
2020-08-30 00:25:21 +02:00
BIT_SET ( udev - > state , keysym ) ;
2017-05-20 19:44:04 +02:00
else
2020-08-30 00:25:21 +02:00
BIT_CLEAR ( udev - > state , keysym ) ;
2017-05-20 19:44:04 +02:00
2021-09-13 17:02:40 +01:00
/* TODO/FIXME: The udev driver is incomplete.
* When calling input_keyboard_event ( ) the
* following parameters are omitted :
* - character : the localised Unicode / UTF - 8
* value of the pressed key
* - mod : the current keyboard modifier
* bitmask
* Without these values , input_keyboard_event ( )
* does not function correctly ( e . g . it is
* impossible to use text entry in the menu ) .
* I cannot find any usable reference for
* converting a udev - returned key code into a
* localised Unicode / UTF - 8 value , so for the
* time being we must rely on other sources :
* - If we are using an X11 - based context driver ,
* input_keyboard_event ( ) is handled correctly
* in x11_common : x11_check_window ( )
* - If we are using KMS , input_keyboard_event ( )
* is handled correctly in
* keyboard_event_xkb : handle_xkb ( )
* If neither are available , then just call
* input_keyboard_event ( ) without character and
* mod , and hope for the best . . . */
if ( video_driver_display_type_get ( ) ! = RARCH_DISPLAY_X11 )
{
2017-06-07 12:25:10 +02:00
# ifdef UDEV_XKB_HANDLING
2021-09-13 17:02:40 +01:00
if ( udev - > xkb_handling & & handle_xkb ( keysym , event - > value ) = = 0 )
return ;
2017-06-07 12:25:10 +02:00
# endif
2021-09-13 17:02:40 +01:00
input_keyboard_event ( event - > value ,
input_keymaps_translate_keysym_to_rk ( keysym ) ,
0 , 0 , RETRO_DEVICE_KEYBOARD ) ;
}
2017-06-07 12:25:10 +02:00
2017-05-20 19:44:04 +02:00
break ;
default :
break ;
}
}
2020-08-30 00:25:21 +02:00
static void udev_input_kb_free ( struct udev_input * udev )
2017-05-20 19:44:04 +02:00
{
unsigned i ;
for ( i = 0 ; i < UDEV_MAX_KEYS ; i + + )
2020-08-30 00:25:21 +02:00
udev - > state [ i ] = 0 ;
2017-06-07 12:25:10 +02:00
# ifdef UDEV_XKB_HANDLING
free_xkb ( ) ;
# endif
2017-05-20 19:44:04 +02:00
}
2019-07-12 16:24:09 +02:00
static udev_input_mouse_t * udev_get_mouse (
struct udev_input * udev , unsigned port )
2013-12-07 22:09:08 +01:00
{
2017-06-02 07:57:07 +02:00
unsigned i ;
2017-06-08 18:49:08 +02:00
unsigned mouse_index = 0 ;
settings_t * settings = config_get_ptr ( ) ;
2017-06-02 07:57:07 +02:00
udev_input_mouse_t * mouse = NULL ;
2019-07-12 16:24:09 +02:00
if ( port > = MAX_USERS | | ! video_driver_has_focus ( ) )
2017-06-08 18:49:08 +02:00
return NULL ;
2017-06-02 07:57:07 +02:00
for ( i = 0 ; i < udev - > num_devices ; + + i )
{
2017-06-09 21:17:11 +02:00
if ( udev - > devices [ i ] - > type = = UDEV_INPUT_KEYBOARD )
2017-06-08 18:49:08 +02:00
continue ;
if ( mouse_index = = settings - > uints . input_mouse_index [ port ] )
2017-06-02 07:57:07 +02:00
{
2017-10-05 05:18:53 +02:00
mouse = & udev - > devices [ i ] - > mouse ;
2017-06-02 07:57:07 +02:00
break ;
}
2017-06-08 18:49:08 +02:00
+ + mouse_index ;
2017-06-02 07:57:07 +02:00
}
2015-11-29 06:34:35 +01:00
2017-06-08 18:49:08 +02:00
return mouse ;
}
2017-10-05 10:00:20 +02:00
static void udev_mouse_set_x ( udev_input_mouse_t * mouse , int32_t x , bool abs )
2013-12-07 22:09:08 +01:00
{
2021-06-26 23:09:47 +01:00
video_viewport_t vp ;
2015-11-29 06:34:35 +01:00
2017-10-05 05:18:53 +02:00
if ( abs )
2013-12-07 22:09:08 +01:00
{
2017-10-05 05:18:53 +02:00
mouse - > x_rel + = x - mouse - > x_abs ;
mouse - > x_abs = x ;
}
else
{
mouse - > x_rel + = x ;
if ( video_driver_get_viewport_info ( & vp ) )
{
mouse - > x_abs + = x ;
2013-12-07 22:09:08 +01:00
2017-10-05 05:18:53 +02:00
if ( mouse - > x_abs < vp . x )
mouse - > x_abs = vp . x ;
else if ( mouse - > x_abs > = vp . x + vp . full_width )
mouse - > x_abs = vp . x + vp . full_width - 1 ;
}
}
}
static int16_t udev_mouse_get_x ( const udev_input_mouse_t * mouse )
{
video_viewport_t vp ;
double src_width ;
double x ;
if ( ! video_driver_get_viewport_info ( & vp ) )
return 0 ;
if ( mouse - > x_min < mouse - > x_max ) /* mouse coords are absolute */
src_width = mouse - > x_max - mouse - > x_min + 1 ;
else
src_width = vp . full_width ;
x = ( double ) vp . width / src_width * mouse - > x_rel ;
return x + ( x < 0 ? - 0.5 : 0.5 ) ;
}
2017-10-05 10:00:20 +02:00
static void udev_mouse_set_y ( udev_input_mouse_t * mouse , int32_t y , bool abs )
2017-10-05 05:18:53 +02:00
{
video_viewport_t vp ;
if ( abs )
{
mouse - > y_rel + = y - mouse - > y_abs ;
mouse - > y_abs = y ;
}
else
{
mouse - > y_rel + = y ;
if ( video_driver_get_viewport_info ( & vp ) )
{
mouse - > y_abs + = y ;
if ( mouse - > y_abs < vp . y )
mouse - > y_abs = vp . y ;
else if ( mouse - > y_abs > = vp . y + vp . full_height )
mouse - > y_abs = vp . y + vp . full_height - 1 ;
}
}
}
static int16_t udev_mouse_get_y ( const udev_input_mouse_t * mouse )
{
video_viewport_t vp ;
double src_height ;
double y ;
if ( ! video_driver_get_viewport_info ( & vp ) )
return 0 ;
if ( mouse - > y_min < mouse - > y_max ) /* mouse coords are absolute */
src_height = mouse - > y_max - mouse - > y_min + 1 ;
else
src_height = vp . full_height ;
y = ( double ) vp . height / src_height * mouse - > y_rel ;
return y + ( y < 0 ? - 0.5 : 0.5 ) ;
}
static int16_t udev_mouse_get_pointer_x ( const udev_input_mouse_t * mouse , bool screen )
{
video_viewport_t vp ;
double src_min ;
double src_width ;
int32_t x ;
if ( ! video_driver_get_viewport_info ( & vp ) )
return 0 ;
if ( mouse - > x_min < mouse - > x_max ) /* mouse coords are absolute */
{
src_min = mouse - > x_min ;
src_width = mouse - > x_max - mouse - > x_min + 1 ;
}
else /* mouse coords are viewport relative */
{
src_min = vp . x ;
if ( screen )
src_width = vp . full_width ;
else
src_width = vp . width ;
2013-12-07 14:13:40 +01:00
}
2017-10-05 05:18:53 +02:00
2020-08-31 03:38:51 +02:00
x = - 32767.0 + 65535.0 / src_width * ( mouse - > x_abs - src_min ) ;
2017-10-05 05:18:53 +02:00
x + = ( x < 0 ? - 0.5 : 0.5 ) ;
if ( x < - 0x7fff )
2020-08-31 03:38:51 +02:00
return - 0x7fff ;
2017-10-05 05:18:53 +02:00
else if ( x > 0x7fff )
2020-08-31 03:38:51 +02:00
return 0x7fff ;
2017-10-05 05:18:53 +02:00
return x ;
}
static int16_t udev_mouse_get_pointer_y ( const udev_input_mouse_t * mouse , bool screen )
{
video_viewport_t vp ;
double src_min ;
double src_height ;
int32_t y ;
if ( ! video_driver_get_viewport_info ( & vp ) )
return 0 ;
if ( mouse - > y_min < mouse - > y_max ) /* mouse coords are absolute */
{
src_min = mouse - > y_min ;
src_height = mouse - > y_max - mouse - > y_min + 1 ;
}
else /* mouse coords are viewport relative */
{
src_min = vp . y ;
if ( screen )
src_height = vp . full_height ;
else
src_height = vp . height ;
}
y = - 32767.0 + 65535.0 / src_height * ( mouse - > y_abs - src_min ) ;
y + = ( y < 0 ? - 0.5 : 0.5 ) ;
if ( y < - 0x7fff )
2020-08-31 03:38:51 +02:00
return - 0x7fff ;
2017-10-05 05:18:53 +02:00
else if ( y > 0x7fff )
2020-08-31 03:38:51 +02:00
return 0x7fff ;
2017-10-05 05:18:53 +02:00
return y ;
2013-12-07 16:11:51 +01:00
}
2013-12-07 14:13:40 +01:00
2015-11-29 06:34:35 +01:00
static void udev_handle_mouse ( void * data ,
2015-11-29 15:35:34 +01:00
const struct input_event * event , udev_input_device_t * dev )
2013-12-07 16:11:51 +01:00
{
2017-10-05 05:18:53 +02:00
udev_input_mouse_t * mouse = & dev - > mouse ;
2015-11-29 06:34:35 +01:00
2013-12-07 22:09:08 +01:00
switch ( event - > type )
2013-12-07 14:13:40 +01:00
{
2013-12-07 22:09:08 +01:00
case EV_KEY :
switch ( event - > code )
2013-12-07 14:13:40 +01:00
{
2013-12-07 22:09:08 +01:00
case BTN_LEFT :
2017-06-02 07:57:07 +02:00
mouse - > l = event - > value ;
2013-12-07 22:09:08 +01:00
break ;
2013-12-07 16:11:51 +01:00
2013-12-07 22:09:08 +01:00
case BTN_RIGHT :
2017-06-02 07:57:07 +02:00
mouse - > r = event - > value ;
2013-12-07 22:09:08 +01:00
break ;
2013-12-07 16:11:51 +01:00
2013-12-07 22:09:08 +01:00
case BTN_MIDDLE :
2017-06-02 07:57:07 +02:00
mouse - > m = event - > value ;
2013-12-07 16:11:51 +01:00
break ;
2021-06-26 23:09:47 +01:00
case BTN_TOUCH :
mouse - > pp = event - > value ;
break ;
2017-12-02 13:24:17 +00:00
/*case BTN_??:
mouse - > b4 = event - > value ;
break ; */
/*case BTN_??:
mouse - > b5 = event - > value ;
break ; */
2013-12-07 22:09:08 +01:00
default :
break ;
}
break ;
2013-12-07 16:11:51 +01:00
2013-12-07 22:09:08 +01:00
case EV_REL :
switch ( event - > code )
{
case REL_X :
2017-10-05 05:18:53 +02:00
udev_mouse_set_x ( mouse , event - > value , false ) ;
2013-12-07 22:09:08 +01:00
break ;
case REL_Y :
2017-10-05 05:18:53 +02:00
udev_mouse_set_y ( mouse , event - > value , false ) ;
2013-12-07 16:11:51 +01:00
break ;
2015-03-09 16:23:09 +01:00
case REL_WHEEL :
if ( event - > value = = 1 )
2017-06-02 07:57:07 +02:00
mouse - > wu = 1 ;
2015-03-09 16:23:09 +01:00
else if ( event - > value = = - 1 )
2017-06-02 07:57:07 +02:00
mouse - > wd = 1 ;
2015-03-09 16:23:09 +01:00
break ;
2015-03-12 05:38:37 +01:00
case REL_HWHEEL :
if ( event - > value = = 1 )
2017-06-02 07:57:07 +02:00
mouse - > whu = 1 ;
2015-03-12 05:38:37 +01:00
else if ( event - > value = = - 1 )
2017-06-02 07:57:07 +02:00
mouse - > whd = 1 ;
2017-06-04 21:16:35 +02:00
break ;
2013-12-07 14:13:40 +01:00
}
2017-10-05 05:18:53 +02:00
break ;
case EV_ABS :
switch ( event - > code )
{
case ABS_X :
udev_mouse_set_x ( mouse , event - > value , true ) ;
break ;
case ABS_Y :
udev_mouse_set_y ( mouse , event - > value , true ) ;
break ;
}
break ;
2013-12-07 14:13:40 +01:00
}
2013-12-07 16:11:51 +01:00
}
2021-06-26 23:09:47 +01:00
# define test_bit(array, bit) (array[bit / 8] & (1<<(bit%8)))
2013-12-07 16:11:51 +01:00
2021-06-22 23:00:50 +01:00
static int udev_input_add_device ( udev_input_t * udev ,
2017-06-02 07:57:07 +02:00
enum udev_input_dev_type type , const char * devnode , device_handle_cb cb )
2013-12-07 17:12:25 +01:00
{
2021-09-13 17:02:40 +01:00
unsigned char keycaps [ ( KEY_MAX / 8 ) + 1 ] = { ' \0 ' } ;
unsigned char abscaps [ ( ABS_MAX / 8 ) + 1 ] = { ' \0 ' } ;
2021-09-24 17:31:20 +01:00
unsigned char relcaps [ ( REL_MAX / 8 ) + 1 ] = { ' \0 ' } ;
2021-09-13 17:02:40 +01:00
udev_input_device_t * * tmp = NULL ;
udev_input_device_t * device = NULL ;
int has_absolutes = 0 ;
2021-10-18 03:43:49 +01:00
struct input_absinfo absinfo ;
2021-09-13 17:02:40 +01:00
int fd = - 1 ;
int ret = 0 ;
2017-06-04 21:16:35 +02:00
struct stat st ;
2017-11-30 07:28:59 +01:00
# if defined(HAVE_EPOLL)
2017-06-11 20:44:02 +02:00
struct epoll_event event ;
2017-11-30 07:28:59 +01:00
# elif defined(HAVE_KQUEUE)
struct kevent event ;
# endif
2017-06-04 21:16:35 +02:00
2021-09-13 17:02:40 +01:00
st . st_dev = 0 ;
2014-10-04 15:14:39 +02:00
2013-12-07 17:12:25 +01:00
if ( stat ( devnode , & st ) < 0 )
2021-09-13 17:02:40 +01:00
goto end ;
2013-12-07 17:12:25 +01:00
2014-10-04 15:14:39 +02:00
fd = open ( devnode , O_RDONLY | O_NONBLOCK ) ;
2013-12-07 17:12:25 +01:00
if ( fd < 0 )
2021-09-13 17:02:40 +01:00
goto end ;
2013-12-07 17:12:25 +01:00
2015-11-29 15:35:34 +01:00
device = ( udev_input_device_t * ) calloc ( 1 , sizeof ( * device ) ) ;
2013-12-07 17:12:25 +01:00
if ( ! device )
2021-09-13 17:02:40 +01:00
goto end ;
2013-12-07 17:12:25 +01:00
2015-06-03 17:11:32 +02:00
device - > fd = fd ;
device - > dev = st . st_dev ;
2013-12-07 22:09:08 +01:00
device - > handle_cb = cb ;
2017-06-02 07:57:07 +02:00
device - > type = type ;
2013-12-07 17:12:25 +01:00
strlcpy ( device - > devnode , devnode , sizeof ( device - > devnode ) ) ;
2017-10-05 05:18:53 +02:00
/* UDEV_INPUT_MOUSE may report in absolute coords too */
2018-12-12 18:27:29 +00:00
if ( type = = UDEV_INPUT_MOUSE | | type = = UDEV_INPUT_TOUCHPAD )
2017-10-05 05:18:53 +02:00
{
2021-09-24 17:31:20 +01:00
bool mouse = 0 ;
2021-09-13 17:02:40 +01:00
/* gotta have some buttons! return -1 to skip error logging for this:) */
2021-06-18 03:55:25 +01:00
if ( ioctl ( fd , EVIOCGBIT ( EV_KEY , sizeof ( keycaps ) ) , keycaps ) = = - 1 )
2021-09-13 17:02:40 +01:00
{
ret = - 1 ;
goto end ;
}
2021-09-24 17:31:20 +01:00
if ( ioctl ( fd , EVIOCGBIT ( EV_REL , sizeof ( relcaps ) ) , relcaps ) ! = - 1 )
{
if ( ( test_bit ( relcaps , REL_X ) ) & & ( test_bit ( relcaps , REL_Y ) ) )
{
if ( test_bit ( keycaps , BTN_MOUSE ) )
mouse = 1 ;
}
}
2021-06-26 23:09:47 +01:00
if ( ioctl ( fd , EVIOCGBIT ( EV_ABS , sizeof ( abscaps ) ) , abscaps ) ! = - 1 )
2019-02-03 15:49:35 -08:00
{
2021-09-13 17:02:40 +01:00
if ( ( test_bit ( abscaps , ABS_X ) ) & & ( test_bit ( abscaps , ABS_Y ) ) )
{
/* might be a touchpad... */
if ( test_bit ( keycaps , BTN_TOUCH ) )
{
2021-09-24 17:31:20 +01:00
/* abs device. */
2021-09-13 17:02:40 +01:00
has_absolutes = 1 ;
2021-09-24 17:31:20 +01:00
mouse = 1 ;
2021-09-13 17:02:40 +01:00
}
}
}
device - > mouse . x_min = 0 ;
device - > mouse . y_min = 0 ;
device - > mouse . x_max = 0 ;
device - > mouse . y_max = 0 ;
2021-06-26 23:09:47 +01:00
if ( has_absolutes )
{
2021-09-13 17:02:40 +01:00
if ( ioctl ( fd , EVIOCGABS ( ABS_X ) , & absinfo ) = = - 1 )
goto end ;
device - > mouse . x_min = absinfo . minimum ;
device - > mouse . x_max = absinfo . maximum ;
if ( ioctl ( fd , EVIOCGABS ( ABS_Y ) , & absinfo ) = = - 1 )
goto end ;
device - > mouse . y_min = absinfo . minimum ;
device - > mouse . y_max = absinfo . maximum ;
2021-06-26 23:09:47 +01:00
}
2013-12-07 22:09:08 +01:00
2021-09-24 17:31:20 +01:00
if ( ! mouse )
goto end ;
2021-10-18 03:43:49 +01:00
/* Ive been through the source with a fine tooth comb the dolphin bar must have abs but is not advertising it or has no button so we will add a check here */
if ( ! has_absolutes )
{
if ( ioctl ( fd , EVIOCGABS ( ABS_X ) , & absinfo ) > = 0 )
{
if ( absinfo . minimum < absinfo . maximum )
{
RARCH_LOG ( " [udev]: pointer device with (ABS_X) that failed find with button check found \n " ) ;
device - > mouse . x_min = absinfo . minimum ;
device - > mouse . x_max = absinfo . maximum ;
}
}
if ( ioctl ( fd , EVIOCGABS ( ABS_Y ) , & absinfo ) > = 0 )
{
if ( absinfo . minimum < absinfo . maximum )
{
RARCH_LOG ( " [udev]: pointer device with (ABS_X) that failed find with button check found \n " ) ;
device - > mouse . y_min = absinfo . minimum ;
device - > mouse . y_max = absinfo . maximum ;
}
}
}
2021-09-24 17:31:20 +01:00
}
2021-10-18 03:43:49 +01:00
2021-09-24 17:31:20 +01:00
if ( ioctl ( fd , EVIOCGNAME ( sizeof ( device - > ident ) ) , device - > ident ) < 0 )
device - > ident [ 0 ] = ' \0 ' ;
2021-09-13 17:02:40 +01:00
tmp = ( udev_input_device_t * * ) realloc ( udev - > devices ,
2013-12-07 17:12:25 +01:00
( udev - > num_devices + 1 ) * sizeof ( * udev - > devices ) ) ;
if ( ! tmp )
2021-09-13 17:02:40 +01:00
goto end ;
2013-12-07 17:12:25 +01:00
tmp [ udev - > num_devices + + ] = device ;
2015-07-12 02:44:53 +02:00
udev - > devices = tmp ;
2013-12-07 17:12:25 +01:00
2017-11-30 07:28:59 +01:00
# if defined(HAVE_EPOLL)
2017-06-11 20:44:02 +02:00
event . events = EPOLLIN ;
event . data . ptr = device ;
/* Shouldn't happen, but just check it. */
2017-11-30 07:00:09 +01:00
if ( epoll_ctl ( udev - > fd , EPOLL_CTL_ADD , fd , & event ) < 0 )
2017-06-10 12:07:01 +02:00
{
RARCH_ERR ( " Failed to add FD (%d) to epoll list (%s). \n " ,
fd , strerror ( errno ) ) ;
}
2017-11-30 07:28:59 +01:00
# elif defined(HAVE_KQUEUE)
EV_SET ( & event , fd , EVFILT_READ , EV_ADD , 0 , 0 , LISTENSOCKET ) ;
if ( kevent ( udev - > fd , & event , 1 , NULL , 0 , NULL ) = = - 1 )
{
RARCH_ERR ( " Failed to add FD (%d) to kqueue list (%s). \n " ,
fd , strerror ( errno ) ) ;
}
# endif
2021-09-13 17:02:40 +01:00
ret = 1 ;
2015-07-12 02:44:53 +02:00
2021-09-13 17:02:40 +01:00
end :
/* Free resources in the event of
* an error */
if ( ret ! = 1 )
{
if ( fd > = 0 )
close ( fd ) ;
if ( device )
free ( device ) ;
}
2015-07-12 02:44:53 +02:00
2021-09-13 17:02:40 +01:00
return ret ;
2013-12-07 17:12:25 +01:00
}
2015-02-20 20:56:22 -03:00
static void udev_input_remove_device ( udev_input_t * udev , const char * devnode )
2013-12-07 17:12:25 +01:00
{
unsigned i ;
2015-01-10 01:32:09 +01:00
2013-12-07 17:12:25 +01:00
for ( i = 0 ; i < udev - > num_devices ; i + + )
{
2016-01-21 02:48:00 +01:00
if ( ! string_is_equal ( devnode , udev - > devices [ i ] - > devnode ) )
2015-06-03 18:12:06 +02:00
continue ;
close ( udev - > devices [ i ] - > fd ) ;
free ( udev - > devices [ i ] ) ;
memmove ( udev - > devices + i , udev - > devices + i + 1 ,
( udev - > num_devices - ( i + 1 ) ) * sizeof ( * udev - > devices ) ) ;
udev - > num_devices - - ;
2013-12-07 17:12:25 +01:00
}
}
2015-02-20 20:56:22 -03:00
static void udev_input_handle_hotplug ( udev_input_t * udev )
2013-12-07 17:12:25 +01:00
{
2017-06-02 07:57:07 +02:00
device_handle_cb cb ;
2017-06-03 18:54:04 +02:00
enum udev_input_dev_type dev_type = UDEV_INPUT_KEYBOARD ;
2017-06-19 12:34:01 +02:00
const char * val_key = NULL ;
2017-06-03 18:54:04 +02:00
const char * val_mouse = NULL ;
const char * val_touchpad = NULL ;
const char * action = NULL ;
const char * devnode = NULL ;
2021-09-24 17:31:20 +01:00
int mouse = 0 ;
int check = 0 ;
2017-06-03 18:54:04 +02:00
struct udev_device * dev = udev_monitor_receive_device (
udev - > monitor ) ;
2015-01-10 01:32:09 +01:00
2013-12-07 17:12:25 +01:00
if ( ! dev )
return ;
2017-06-19 12:34:01 +02:00
val_key = udev_device_get_property_value ( dev , " ID_INPUT_KEY " ) ;
2015-06-03 17:11:32 +02:00
val_mouse = udev_device_get_property_value ( dev , " ID_INPUT_MOUSE " ) ;
val_touchpad = udev_device_get_property_value ( dev , " ID_INPUT_TOUCHPAD " ) ;
action = udev_device_get_action ( dev ) ;
devnode = udev_device_get_devnode ( dev ) ;
2013-12-07 17:12:25 +01:00
2018-01-16 22:53:38 +01:00
if ( val_key & & string_is_equal ( val_key , " 1 " ) & & devnode )
2017-06-02 07:57:07 +02:00
{
2017-06-19 12:34:01 +02:00
/* EV_KEY device, can be a keyboard or a remote control device. */
2017-06-03 18:54:04 +02:00
dev_type = UDEV_INPUT_KEYBOARD ;
cb = udev_handle_keyboard ;
2017-06-02 07:57:07 +02:00
}
2018-01-16 22:53:38 +01:00
else if ( val_mouse & & string_is_equal ( val_mouse , " 1 " ) & & devnode )
2017-06-02 07:57:07 +02:00
{
2017-06-03 18:54:04 +02:00
dev_type = UDEV_INPUT_MOUSE ;
cb = udev_handle_mouse ;
2017-06-02 07:57:07 +02:00
}
2018-01-16 22:53:38 +01:00
else if ( val_touchpad & & string_is_equal ( val_touchpad , " 1 " ) & & devnode )
2017-06-02 07:57:07 +02:00
{
2017-06-03 18:54:04 +02:00
dev_type = UDEV_INPUT_TOUCHPAD ;
2017-10-05 05:18:53 +02:00
cb = udev_handle_mouse ;
2017-06-02 07:57:07 +02:00
}
else
2016-04-28 22:50:02 +02:00
goto end ;
2013-12-07 22:09:08 +01:00
2020-06-11 05:37:40 +02:00
/* Hotplug add */
2018-01-16 22:53:38 +01:00
if ( string_is_equal ( action , " add " ) )
2017-06-02 07:57:07 +02:00
udev_input_add_device ( udev , dev_type , devnode , cb ) ;
2020-06-11 05:37:40 +02:00
/* Hotplug remove */
2018-01-16 22:53:38 +01:00
else if ( string_is_equal ( action , " remove " ) )
2015-02-20 20:56:22 -03:00
udev_input_remove_device ( udev , devnode ) ;
2013-12-07 17:12:25 +01:00
2021-09-24 17:31:20 +01:00
/* we need to re index the mouse friendly names when a mouse is hotplugged */
if ( dev_type ! = UDEV_INPUT_KEYBOARD )
{
/*first clear all */
for ( int i = 0 ; i < MAX_USERS ; i + + )
input_config_set_mouse_display_name ( i , " N/A " ) ;
/* Add what devices we have now */
for ( int i = 0 ; i < udev - > num_devices ; + + i )
{
if ( udev - > devices [ i ] - > type ! = UDEV_INPUT_KEYBOARD )
{
input_config_set_mouse_display_name ( mouse , udev - > devices [ i ] - > ident ) ;
mouse + + ;
}
}
}
2013-12-07 17:12:25 +01:00
end :
udev_device_unref ( dev ) ;
}
2017-06-03 18:54:04 +02:00
# ifdef HAVE_X11
2017-06-03 12:46:53 +02:00
static void udev_input_get_pointer_position ( int * x , int * y )
{
2019-07-12 16:24:09 +02:00
if ( video_driver_display_type_get ( ) = = RARCH_DISPLAY_X11 )
{
2019-07-11 09:24:01 +02:00
Window w ;
int p ;
unsigned m ;
Display * display = ( Display * ) video_driver_display_get ( ) ;
Window window = ( Window ) video_driver_window_get ( ) ;
XQueryPointer ( display , window , & w , & w , & p , & p , x , y , & m ) ;
}
}
2017-06-03 12:46:53 +02:00
2019-07-12 16:24:09 +02:00
static void udev_input_adopt_rel_pointer_position_from_mouse (
int * x , int * y , udev_input_mouse_t * mouse )
{
2019-07-11 09:24:01 +02:00
static int noX11DispX = 0 ;
static int noX11DispY = 0 ;
struct video_viewport view ;
bool r = video_driver_get_viewport_info ( & view ) ;
int dx = udev_mouse_get_x ( mouse ) ;
int dy = udev_mouse_get_y ( mouse ) ;
2019-07-12 16:24:09 +02:00
if ( r & & ( dx | | dy ) & &
video_driver_display_type_get ( ) ! = RARCH_DISPLAY_X11 )
{
2019-07-11 09:24:01 +02:00
int minX = view . x ;
int maxX = view . x + view . width ;
int minY = view . y ;
int maxY = view . y + view . height ;
2019-07-11 17:25:57 +02:00
/* Not running in a window. */
2019-07-11 09:24:01 +02:00
noX11DispX = noX11DispX + dx ;
if ( noX11DispX < minX )
noX11DispX = minX ;
if ( noX11DispX > maxX )
noX11DispX = maxX ;
noX11DispY = noX11DispY + dy ;
if ( noX11DispY < minY )
noX11DispY = minY ;
if ( noX11DispY > maxY )
noX11DispY = maxY ;
* x = noX11DispX ;
* y = noX11DispY ;
}
mouse - > x_rel = 0 ;
mouse - > y_rel = 0 ;
2017-06-03 12:46:53 +02:00
}
2017-06-03 18:54:04 +02:00
# endif
2017-06-03 12:46:53 +02:00
2017-06-10 11:58:22 +02:00
static bool udev_input_poll_hotplug_available ( struct udev_monitor * dev )
{
2017-10-05 05:18:53 +02:00
struct pollfd fds ;
2017-06-10 11:58:22 +02:00
2017-10-05 05:18:53 +02:00
fds . fd = udev_monitor_get_fd ( dev ) ;
fds . events = POLLIN ;
fds . revents = 0 ;
2017-06-10 11:58:22 +02:00
return ( poll ( & fds , 1 , 0 ) = = 1 ) & & ( fds . revents & POLLIN ) ;
}
2020-09-01 21:43:19 +02:00
static void udev_input_poll ( void * data )
2013-12-07 16:11:51 +01:00
{
2014-10-04 15:14:39 +02:00
int i , ret ;
2017-11-30 07:28:59 +01:00
# if defined(HAVE_EPOLL)
2014-10-04 15:14:39 +02:00
struct epoll_event events [ 32 ] ;
2017-11-30 07:28:59 +01:00
# elif defined(HAVE_KQUEUE)
struct kevent events [ 32 ] ;
# endif
2017-06-03 18:54:04 +02:00
udev_input_mouse_t * mouse = NULL ;
udev_input_t * udev = ( udev_input_t * ) data ;
2015-01-10 01:32:09 +01:00
2017-06-03 18:54:04 +02:00
# ifdef HAVE_X11
2019-07-11 09:24:01 +02:00
udev_input_get_pointer_position ( & udev - > pointer_x , & udev - > pointer_y ) ;
2017-06-03 18:54:04 +02:00
# endif
2017-06-03 12:46:53 +02:00
2017-06-02 07:57:07 +02:00
for ( i = 0 ; i < udev - > num_devices ; + + i )
{
2017-10-05 05:18:53 +02:00
if ( udev - > devices [ i ] - > type = = UDEV_INPUT_KEYBOARD )
2017-06-09 21:17:11 +02:00
continue ;
2017-10-05 05:18:53 +02:00
mouse = & udev - > devices [ i ] - > mouse ;
2019-07-11 09:24:01 +02:00
# ifdef HAVE_X11
2019-07-12 16:24:09 +02:00
udev_input_adopt_rel_pointer_position_from_mouse (
& udev - > pointer_x , & udev - > pointer_y , mouse ) ;
2019-07-11 09:24:01 +02:00
# else
2017-10-05 05:18:53 +02:00
mouse - > x_rel = 0 ;
mouse - > y_rel = 0 ;
2019-07-11 09:24:01 +02:00
# endif
2017-06-09 21:17:11 +02:00
mouse - > wu = false ;
mouse - > wd = false ;
mouse - > whu = false ;
mouse - > whd = false ;
2017-06-02 07:57:07 +02:00
}
2013-12-07 16:11:51 +01:00
2017-06-10 11:58:22 +02:00
while ( udev - > monitor & & udev_input_poll_hotplug_available ( udev - > monitor ) )
2015-02-20 20:56:22 -03:00
udev_input_handle_hotplug ( udev ) ;
2013-12-07 17:12:25 +01:00
2017-11-30 07:28:59 +01:00
# if defined(HAVE_EPOLL)
2017-11-30 07:00:09 +01:00
ret = epoll_wait ( udev - > fd , events , ARRAY_SIZE ( events ) , 0 ) ;
2017-11-30 07:28:59 +01:00
# elif defined(HAVE_KQUEUE)
{
struct timespec timeoutspec ;
timeoutspec . tv_sec = timeout ;
timeoutspec . tv_nsec = 0 ;
ret = kevent ( udev - > fd , NULL , 0 , events ,
ARRAY_SIZE ( events ) , & timeoutspec ) ;
}
# endif
2013-12-07 16:11:51 +01:00
for ( i = 0 ; i < ret ; i + + )
{
2017-11-30 07:28:59 +01:00
/* TODO/FIXME - add HAVE_EPOLL/HAVE_KQUEUE codepaths here */
2013-12-07 16:11:51 +01:00
if ( events [ i ] . events & EPOLLIN )
{
2014-10-04 15:14:39 +02:00
int j , len ;
2015-01-10 01:32:09 +01:00
struct input_event input_events [ 32 ] ;
2017-11-30 07:28:59 +01:00
# if defined(HAVE_EPOLL)
2015-11-29 15:35:34 +01:00
udev_input_device_t * device = ( udev_input_device_t * ) events [ i ] . data . ptr ;
2017-11-30 07:28:59 +01:00
# elif defined(HAVE_KQUEUE)
udev_input_device_t * device = ( udev_input_device_t * ) events [ i ] . udata ;
# endif
2013-12-07 22:09:08 +01:00
2017-06-03 18:54:04 +02:00
while ( ( len = read ( device - > fd ,
input_events , sizeof ( input_events ) ) ) > 0 )
2013-12-07 22:09:08 +01:00
{
2015-01-10 01:32:09 +01:00
len / = sizeof ( * input_events ) ;
2013-12-07 22:09:08 +01:00
for ( j = 0 ; j < len ; j + + )
2015-01-10 01:32:09 +01:00
device - > handle_cb ( udev , & input_events [ j ] , device ) ;
2013-12-07 22:09:08 +01:00
}
2013-12-07 16:11:51 +01:00
}
}
2013-12-07 14:13:40 +01:00
}
2017-10-05 05:18:53 +02:00
static bool udev_pointer_is_off_window ( const udev_input_t * udev )
2017-07-18 01:16:48 +02:00
{
2017-10-05 05:18:53 +02:00
# ifdef HAVE_X11
2017-07-18 01:16:48 +02:00
struct video_viewport view ;
bool r = video_driver_get_viewport_info ( & view ) ;
if ( r )
2020-06-12 14:12:22 +01:00
r = udev - > pointer_x < 0 | |
udev - > pointer_x > = view . full_width | |
udev - > pointer_y < 0 | |
udev - > pointer_y > = view . full_height ;
2017-07-18 01:16:48 +02:00
return r ;
2017-10-05 05:18:53 +02:00
# else
return false ;
# endif
2017-07-18 01:16:48 +02:00
}
2020-06-10 04:00:40 +02:00
static int16_t udev_lightgun_aiming_state (
udev_input_t * udev , unsigned port , unsigned id )
2017-12-02 13:24:17 +00:00
{
2021-01-18 11:23:44 +00:00
2020-06-10 04:00:40 +02:00
const int edge_detect = 32700 ;
2017-12-02 13:24:17 +00:00
bool inside = false ;
int16_t res_x = 0 ;
int16_t res_y = 0 ;
int16_t res_screen_x = 0 ;
int16_t res_screen_y = 0 ;
2020-06-10 04:00:40 +02:00
udev_input_mouse_t * mouse = udev_get_mouse ( udev , port ) ;
2018-02-06 22:17:32 -05:00
2017-12-02 13:24:17 +00:00
if ( ! mouse )
return 0 ;
2020-06-26 19:47:28 -06:00
res_x = udev_mouse_get_pointer_x ( mouse , false ) ;
res_y = udev_mouse_get_pointer_y ( mouse , false ) ;
2017-12-02 13:24:17 +00:00
2020-06-10 04:00:40 +02:00
inside = ( res_x > = - edge_detect )
& & ( res_y > = - edge_detect )
& & ( res_x < = edge_detect )
& & ( res_y < = edge_detect ) ;
2017-12-02 13:24:17 +00:00
switch ( id )
{
2020-06-10 04:00:40 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X :
return res_x ;
break ;
case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y :
return res_y ;
break ;
case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN :
return ! inside ;
default :
break ;
2017-12-02 13:24:17 +00:00
}
return 0 ;
}
2017-06-03 18:54:04 +02:00
static int16_t udev_mouse_state ( udev_input_t * udev ,
unsigned port , unsigned id , bool screen )
2013-12-07 14:13:40 +01:00
{
2017-06-08 18:49:08 +02:00
udev_input_mouse_t * mouse = udev_get_mouse ( udev , port ) ;
2017-06-02 07:57:07 +02:00
if ( ! mouse )
return 0 ;
2017-07-18 01:16:48 +02:00
if ( id ! = RETRO_DEVICE_ID_MOUSE_X & & id ! = RETRO_DEVICE_ID_MOUSE_Y & &
2017-10-05 05:18:53 +02:00
udev_pointer_is_off_window ( udev ) )
2017-07-18 01:16:48 +02:00
return 0 ;
2013-12-07 14:13:40 +01:00
switch ( id )
{
case RETRO_DEVICE_ID_MOUSE_X :
2017-10-05 05:18:53 +02:00
return screen ? udev - > pointer_x : udev_mouse_get_x ( mouse ) ;
2013-12-07 14:13:40 +01:00
case RETRO_DEVICE_ID_MOUSE_Y :
2017-10-05 05:18:53 +02:00
return screen ? udev - > pointer_y : udev_mouse_get_y ( mouse ) ;
2013-12-07 14:13:40 +01:00
case RETRO_DEVICE_ID_MOUSE_LEFT :
2017-06-02 07:57:07 +02:00
return mouse - > l ;
2013-12-07 14:13:40 +01:00
case RETRO_DEVICE_ID_MOUSE_RIGHT :
2017-06-02 07:57:07 +02:00
return mouse - > r ;
2014-04-25 23:44:53 +02:00
case RETRO_DEVICE_ID_MOUSE_MIDDLE :
2017-06-02 07:57:07 +02:00
return mouse - > m ;
2017-12-02 13:24:17 +00:00
case RETRO_DEVICE_ID_MOUSE_BUTTON_4 :
return mouse - > b4 ;
case RETRO_DEVICE_ID_MOUSE_BUTTON_5 :
return mouse - > b5 ;
2014-08-01 05:34:05 +02:00
case RETRO_DEVICE_ID_MOUSE_WHEELUP :
2017-06-02 07:57:07 +02:00
return mouse - > wu ;
2014-08-01 05:34:05 +02:00
case RETRO_DEVICE_ID_MOUSE_WHEELDOWN :
2017-06-02 07:57:07 +02:00
return mouse - > wd ;
2015-03-12 05:38:37 +01:00
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP :
2017-06-02 07:57:07 +02:00
return mouse - > whu ;
2015-03-12 05:38:37 +01:00
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN :
2017-06-02 07:57:07 +02:00
return mouse - > whd ;
2013-12-07 14:13:40 +01:00
}
2014-10-04 15:14:39 +02:00
return 0 ;
2013-12-07 14:13:40 +01:00
}
2017-12-02 13:24:17 +00:00
static bool udev_keyboard_pressed ( udev_input_t * udev , unsigned key )
{
int bit = rarch_keysym_lut [ key ] ;
2020-08-30 00:25:21 +02:00
return BIT_GET ( udev - > state , bit ) ;
2017-12-02 13:24:17 +00:00
}
2019-06-23 02:34:35 +02:00
static bool udev_mouse_button_pressed (
udev_input_t * udev , unsigned port , unsigned key )
2013-12-07 14:13:40 +01:00
{
2017-06-08 18:49:08 +02:00
udev_input_mouse_t * mouse = udev_get_mouse ( udev , port ) ;
2017-06-02 07:57:07 +02:00
if ( ! mouse )
2017-12-02 13:24:17 +00:00
return false ;
2017-06-02 07:57:07 +02:00
2017-12-02 13:24:17 +00:00
switch ( key )
2013-12-07 14:13:40 +01:00
{
2019-06-23 02:34:35 +02:00
case RETRO_DEVICE_ID_MOUSE_LEFT :
return mouse - > l ;
case RETRO_DEVICE_ID_MOUSE_RIGHT :
return mouse - > r ;
case RETRO_DEVICE_ID_MOUSE_MIDDLE :
return mouse - > m ;
case RETRO_DEVICE_ID_MOUSE_BUTTON_4 :
return mouse - > b4 ;
case RETRO_DEVICE_ID_MOUSE_BUTTON_5 :
return mouse - > b5 ;
case RETRO_DEVICE_ID_MOUSE_WHEELUP :
return mouse - > wu ;
case RETRO_DEVICE_ID_MOUSE_WHEELDOWN :
return mouse - > wd ;
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP :
return mouse - > whu ;
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN :
return mouse - > whd ;
2013-12-07 14:13:40 +01:00
}
2014-10-04 15:14:39 +02:00
2017-12-02 13:24:17 +00:00
return false ;
}
2015-10-10 10:35:45 +02:00
static int16_t udev_pointer_state ( udev_input_t * udev ,
2017-06-02 07:57:07 +02:00
unsigned port , unsigned id , bool screen )
2015-10-10 10:35:45 +02:00
{
2017-10-05 05:18:53 +02:00
udev_input_mouse_t * mouse = udev_get_mouse ( udev , port ) ;
2015-10-10 10:35:45 +02:00
2017-06-02 07:57:07 +02:00
if ( ! mouse )
return 0 ;
2015-10-10 10:35:45 +02:00
switch ( id )
{
case RETRO_DEVICE_ID_POINTER_X :
2017-10-05 05:18:53 +02:00
return udev_mouse_get_pointer_x ( mouse , screen ) ;
2015-10-10 10:35:45 +02:00
case RETRO_DEVICE_ID_POINTER_Y :
2017-10-05 05:18:53 +02:00
return udev_mouse_get_pointer_y ( mouse , screen ) ;
2015-10-10 10:35:45 +02:00
case RETRO_DEVICE_ID_POINTER_PRESSED :
2021-10-16 19:26:40 +01:00
if ( mouse - > x_min < mouse - > x_max )
return mouse - > pp ;
else
return mouse - > l ;
2015-10-10 10:35:45 +02:00
}
return 0 ;
}
2021-04-11 06:37:49 +02:00
static unsigned udev_retro_id_to_rarch ( unsigned id )
2020-07-19 05:07:50 +02:00
{
2021-04-11 06:37:49 +02:00
switch ( id )
2020-07-19 05:07:50 +02:00
{
2021-04-11 06:37:49 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT :
2021-04-11 16:31:46 +02:00
return RARCH_LIGHTGUN_DPAD_RIGHT ;
2021-04-11 06:37:49 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT :
2021-04-11 16:31:46 +02:00
return RARCH_LIGHTGUN_DPAD_LEFT ;
2021-04-11 06:37:49 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP :
2021-04-11 16:31:46 +02:00
return RARCH_LIGHTGUN_DPAD_UP ;
2021-04-11 06:37:49 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN :
2021-04-11 16:31:46 +02:00
return RARCH_LIGHTGUN_DPAD_DOWN ;
2021-04-11 06:37:49 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_SELECT :
return RARCH_LIGHTGUN_SELECT ;
case RETRO_DEVICE_ID_LIGHTGUN_PAUSE :
2021-04-11 16:31:46 +02:00
return RARCH_LIGHTGUN_START ;
2021-04-11 06:37:49 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_RELOAD :
return RARCH_LIGHTGUN_RELOAD ;
case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER :
return RARCH_LIGHTGUN_TRIGGER ;
case RETRO_DEVICE_ID_LIGHTGUN_AUX_A :
2021-04-11 16:31:46 +02:00
return RARCH_LIGHTGUN_AUX_A ;
2021-04-11 06:37:49 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_AUX_B :
2021-04-11 16:31:46 +02:00
return RARCH_LIGHTGUN_AUX_B ;
2021-04-11 06:37:49 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_AUX_C :
2021-04-11 16:31:46 +02:00
return RARCH_LIGHTGUN_AUX_C ;
2021-04-11 06:37:49 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_START :
2021-04-11 16:31:46 +02:00
return RARCH_LIGHTGUN_START ;
2021-04-11 06:37:49 +02:00
default :
2021-04-11 16:31:46 +02:00
break ;
2020-07-19 05:07:50 +02:00
}
2021-04-11 06:37:49 +02:00
2020-07-19 05:07:50 +02:00
return 0 ;
}
2020-08-30 05:29:32 +02:00
static int16_t udev_input_state (
void * data ,
const input_device_driver_t * joypad ,
const input_device_driver_t * sec_joypad ,
2020-02-27 07:33:14 +01:00
rarch_joypad_info_t * joypad_info ,
2017-01-10 17:40:21 +01:00
const struct retro_keybind * * binds ,
2020-08-30 18:47:29 +02:00
bool keyboard_mapping_blocked ,
unsigned port ,
unsigned device ,
unsigned idx ,
unsigned id )
2013-12-07 14:13:40 +01:00
{
2017-01-10 03:44:53 +01:00
udev_input_t * udev = ( udev_input_t * ) data ;
2013-12-07 14:13:40 +01:00
switch ( device )
{
case RETRO_DEVICE_JOYPAD :
2019-06-23 06:09:45 +02:00
if ( id = = RETRO_DEVICE_ID_JOYPAD_MASK )
{
unsigned i ;
2020-09-02 15:26:03 +02:00
int16_t ret = 0 ;
2020-07-19 03:18:12 +02:00
2020-07-14 01:39:07 +02:00
for ( i = 0 ; i < RARCH_FIRST_CUSTOM_BIND ; i + + )
2020-06-11 21:38:58 +02:00
{
2020-07-14 01:39:07 +02:00
if ( binds [ port ] [ i ] . valid )
2020-06-11 21:38:58 +02:00
{
2020-07-19 03:18:12 +02:00
if ( udev_mouse_button_pressed ( udev , port , binds [ port ] [ i ] . mbutton ) )
2020-07-14 01:39:07 +02:00
ret | = ( 1 < < i ) ;
2020-06-11 21:38:58 +02:00
}
}
2020-08-30 18:47:29 +02:00
if ( ! keyboard_mapping_blocked )
2019-06-23 06:09:45 +02:00
{
2020-06-11 21:38:58 +02:00
for ( i = 0 ; i < RARCH_FIRST_CUSTOM_BIND ; i + + )
{
if ( binds [ port ] [ i ] . valid )
2020-06-12 14:12:22 +01:00
{
2020-07-14 01:39:07 +02:00
if ( ( binds [ port ] [ i ] . key < RETROK_LAST ) & &
2020-06-12 16:06:32 +01:00
udev_keyboard_pressed ( udev , binds [ port ] [ i ] . key ) )
ret | = ( 1 < < i ) ;
}
2020-06-11 21:38:58 +02:00
}
2019-06-23 06:09:45 +02:00
}
2019-07-22 01:20:00 +02:00
return ret ;
2019-06-23 06:09:45 +02:00
}
2020-09-02 15:26:03 +02:00
if ( id < RARCH_BIND_LIST_END )
2019-06-23 06:09:45 +02:00
{
2020-09-02 15:26:03 +02:00
if ( binds [ port ] [ id ] . valid )
2020-06-11 21:38:58 +02:00
{
2020-09-02 15:26:03 +02:00
if (
( binds [ port ] [ id ] . key < RETROK_LAST ) & &
udev_keyboard_pressed ( udev , binds [ port ] [ id ] . key )
2021-06-19 07:59:06 +01:00
& & ( ( id ! = RARCH_GAME_FOCUS_TOGGLE )
2021-06-19 08:47:35 +01:00
& & ! keyboard_mapping_blocked )
2021-06-19 07:59:06 +01:00
)
return 1 ;
else if (
2020-09-02 15:26:03 +02:00
( binds [ port ] [ id ] . key < RETROK_LAST ) & &
udev_keyboard_pressed ( udev , binds [ port ] [ id ] . key )
2021-06-19 08:47:35 +01:00
& & ( id = = RARCH_GAME_FOCUS_TOGGLE )
2020-09-02 15:26:03 +02:00
)
return 1 ;
else if ( udev_mouse_button_pressed ( udev , port ,
binds [ port ] [ id ] . mbutton ) )
return 1 ;
2020-06-11 21:38:58 +02:00
}
2019-06-23 06:09:45 +02:00
}
2019-07-22 01:20:00 +02:00
break ;
2013-12-07 14:13:40 +01:00
case RETRO_DEVICE_ANALOG :
2020-06-13 05:25:10 +02:00
if ( binds [ port ] )
2020-08-30 16:57:04 +02:00
{
int id_minus_key = 0 ;
int id_plus_key = 0 ;
unsigned id_minus = 0 ;
unsigned id_plus = 0 ;
int16_t ret = 0 ;
bool id_plus_valid = false ;
bool id_minus_valid = false ;
input_conv_analog_id_to_bind_id ( idx , id , id_minus , id_plus ) ;
id_minus_valid = binds [ port ] [ id_minus ] . valid ;
id_plus_valid = binds [ port ] [ id_plus ] . valid ;
id_minus_key = binds [ port ] [ id_minus ] . key ;
id_plus_key = binds [ port ] [ id_plus ] . key ;
if ( id_plus_valid & & id_plus_key < RETROK_LAST )
{
unsigned sym = rarch_keysym_lut [ ( enum retro_key ) id_plus_key ] ;
if BIT_GET ( udev - > state , sym )
ret = 0x7fff ;
}
if ( id_minus_valid & & id_minus_key < RETROK_LAST )
{
unsigned sym = rarch_keysym_lut [ ( enum retro_key ) id_minus_key ] ;
if ( BIT_GET ( udev - > state , sym ) )
ret + = - 0x7fff ;
}
return ret ;
}
2020-06-23 18:31:40 +02:00
break ;
2013-12-07 14:13:40 +01:00
case RETRO_DEVICE_KEYBOARD :
2017-12-02 13:24:17 +00:00
return ( id < RETROK_LAST ) & & udev_keyboard_pressed ( udev , id ) ;
2013-12-07 14:13:40 +01:00
case RETRO_DEVICE_MOUSE :
2017-06-03 12:46:53 +02:00
case RARCH_DEVICE_MOUSE_SCREEN :
2020-08-31 02:07:43 +02:00
return udev_mouse_state ( udev , port , id ,
device = = RARCH_DEVICE_MOUSE_SCREEN ) ;
2017-12-02 13:24:17 +00:00
2015-10-10 10:35:45 +02:00
case RETRO_DEVICE_POINTER :
case RARCH_DEVICE_POINTER_SCREEN :
2019-02-26 18:22:23 +01:00
if ( idx = = 0 ) /* multi-touch unsupported (for now) */
2020-08-31 02:07:43 +02:00
return udev_pointer_state ( udev , port , id ,
device = = RARCH_DEVICE_POINTER_SCREEN ) ;
2019-02-26 18:22:23 +01:00
break ;
2017-12-02 13:24:17 +00:00
2013-12-07 14:13:40 +01:00
case RETRO_DEVICE_LIGHTGUN :
2017-12-02 13:24:17 +00:00
switch ( id )
{
/*aiming*/
case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X :
case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y :
case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN :
2017-12-03 09:40:36 +00:00
return udev_lightgun_aiming_state ( udev , port , id ) ;
2017-12-02 13:24:17 +00:00
2020-08-31 02:07:43 +02:00
/*buttons*/
2017-12-02 13:24:17 +00:00
case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER :
case RETRO_DEVICE_ID_LIGHTGUN_RELOAD :
case RETRO_DEVICE_ID_LIGHTGUN_AUX_A :
case RETRO_DEVICE_ID_LIGHTGUN_AUX_B :
case RETRO_DEVICE_ID_LIGHTGUN_AUX_C :
case RETRO_DEVICE_ID_LIGHTGUN_START :
case RETRO_DEVICE_ID_LIGHTGUN_SELECT :
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP :
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN :
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT :
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT :
2021-04-11 06:37:49 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_PAUSE : /* deprecated */
2021-04-15 06:55:35 +02:00
{
unsigned new_id = udev_retro_id_to_rarch ( id ) ;
const uint64_t bind_joykey = input_config_binds [ port ] [ new_id ] . joykey ;
const uint64_t bind_joyaxis = input_config_binds [ port ] [ new_id ] . joyaxis ;
const uint64_t autobind_joykey = input_autoconf_binds [ port ] [ new_id ] . joykey ;
const uint64_t autobind_joyaxis = input_autoconf_binds [ port ] [ new_id ] . joyaxis ;
uint16_t port = joypad_info - > joy_idx ;
float axis_threshold = joypad_info - > axis_threshold ;
const uint64_t joykey = ( bind_joykey ! = NO_BTN )
? bind_joykey : autobind_joykey ;
const uint32_t joyaxis = ( bind_joyaxis ! = AXIS_NONE )
? bind_joyaxis : autobind_joyaxis ;
if ( ! keyboard_mapping_blocked )
if ( ( binds [ port ] [ new_id ] . key < RETROK_LAST )
& & udev_keyboard_pressed ( udev , binds [ port ]
[ new_id ] . key ) )
return 1 ;
if ( binds [ port ] [ new_id ] . valid )
{
if ( ( uint16_t ) joykey ! = NO_BTN & & joypad - > button (
port , ( uint16_t ) joykey ) )
return 1 ;
if ( joyaxis ! = AXIS_NONE & &
( ( float ) abs ( joypad - > axis ( port , joyaxis ) )
/ 0x8000 ) > axis_threshold )
return 1 ;
if ( udev_mouse_button_pressed ( udev , port ,
binds [ port ] [ new_id ] . mbutton ) )
return 1 ;
}
}
break ;
2020-08-31 02:07:43 +02:00
/*deprecated*/
2017-12-02 13:24:17 +00:00
case RETRO_DEVICE_ID_LIGHTGUN_X :
{
2017-12-03 09:40:36 +00:00
udev_input_mouse_t * mouse = udev_get_mouse ( udev , port ) ;
2020-06-12 18:28:07 +02:00
if ( mouse )
return udev_mouse_get_x ( mouse ) ;
2017-12-02 13:24:17 +00:00
}
2020-06-12 18:28:07 +02:00
break ;
2017-12-02 13:24:17 +00:00
case RETRO_DEVICE_ID_LIGHTGUN_Y :
{
2017-12-03 09:40:36 +00:00
udev_input_mouse_t * mouse = udev_get_mouse ( udev , port ) ;
2020-06-12 18:28:07 +02:00
if ( mouse )
return udev_mouse_get_y ( mouse ) ;
2017-12-02 13:24:17 +00:00
}
2020-06-12 18:28:07 +02:00
break ;
2017-12-02 13:24:17 +00:00
}
break ;
2013-12-07 14:13:40 +01:00
}
2015-01-10 01:34:16 +01:00
return 0 ;
2013-12-07 14:13:40 +01:00
}
static void udev_input_free ( void * data )
{
2013-12-07 16:11:51 +01:00
unsigned i ;
2013-12-07 14:13:40 +01:00
udev_input_t * udev = ( udev_input_t * ) data ;
2015-01-10 01:32:09 +01:00
2014-10-04 15:14:39 +02:00
if ( ! data | | ! udev )
return ;
2017-11-30 07:00:09 +01:00
if ( udev - > fd > = 0 )
close ( udev - > fd ) ;
2017-06-11 20:44:02 +02:00
2017-11-30 07:00:09 +01:00
udev - > fd = - 1 ;
2013-12-07 16:11:51 +01:00
for ( i = 0 ; i < udev - > num_devices ; i + + )
{
close ( udev - > devices [ i ] - > fd ) ;
free ( udev - > devices [ i ] ) ;
}
free ( udev - > devices ) ;
2013-12-07 14:13:40 +01:00
2015-12-17 03:02:48 +01:00
if ( udev - > monitor )
udev_monitor_unref ( udev - > monitor ) ;
if ( udev - > udev )
udev_unref ( udev - > udev ) ;
2013-12-07 16:11:51 +01:00
2020-08-30 00:25:21 +02:00
udev_input_kb_free ( udev ) ;
2013-12-08 00:56:24 +01:00
2013-12-07 17:12:25 +01:00
free ( udev ) ;
2013-12-07 16:11:51 +01:00
}
2017-06-02 07:57:07 +02:00
static bool open_devices ( udev_input_t * udev ,
enum udev_input_dev_type type , device_handle_cb cb )
2013-12-07 14:13:40 +01:00
{
2017-06-02 07:57:07 +02:00
const char * type_str = g_dev_type_str [ type ] ;
2015-06-03 17:06:22 +02:00
struct udev_list_entry * devs = NULL ;
struct udev_list_entry * item = NULL ;
2015-12-17 03:02:48 +01:00
struct udev_enumerate * enumerate = udev_enumerate_new ( udev - > udev ) ;
2021-09-24 17:31:20 +01:00
2013-12-07 14:13:40 +01:00
if ( ! enumerate )
2013-12-07 16:11:51 +01:00
return false ;
2013-12-07 14:13:40 +01:00
2017-06-02 07:57:07 +02:00
udev_enumerate_add_match_property ( enumerate , type_str , " 1 " ) ;
2021-08-02 12:55:40 +02:00
udev_enumerate_add_match_subsystem ( enumerate , " input " ) ;
2013-12-07 14:13:40 +01:00
udev_enumerate_scan_devices ( enumerate ) ;
devs = udev_enumerate_get_list_entry ( enumerate ) ;
2015-01-12 02:52:52 +01:00
2013-12-07 14:13:40 +01:00
for ( item = devs ; item ; item = udev_list_entry_get_next ( item ) )
{
2015-12-17 03:02:48 +01:00
const char * name = udev_list_entry_get_name ( item ) ;
/* Get the filename of the /sys entry for the device
* and create a udev_device object ( dev ) representing it . */
struct udev_device * dev = udev_device_new_from_syspath ( udev - > udev , name ) ;
const char * devnode = udev_device_get_devnode ( dev ) ;
2013-12-07 14:13:40 +01:00
2013-12-07 17:12:25 +01:00
if ( devnode )
2013-12-07 14:13:40 +01:00
{
2015-01-12 02:52:52 +01:00
int fd = open ( devnode , O_RDONLY | O_NONBLOCK ) ;
2015-09-29 18:08:33 +02:00
2017-06-05 05:18:38 +02:00
if ( fd ! = - 1 )
{
2021-06-22 23:00:50 +01:00
int check = udev_input_add_device ( udev , type , devnode , cb ) ;
2021-06-26 23:09:47 +01:00
if ( check = = 0 )
RARCH_LOG ( " [udev] udev_input_add_device error : %s (%s). \n " ,
2017-06-05 05:18:38 +02:00
devnode , strerror ( errno ) ) ;
2021-06-18 03:55:25 +01:00
2020-06-11 05:37:40 +02:00
( void ) check ;
2017-06-05 05:18:38 +02:00
close ( fd ) ;
}
2013-12-07 14:13:40 +01:00
}
2013-12-07 16:11:51 +01:00
udev_device_unref ( dev ) ;
2013-12-07 14:13:40 +01:00
}
udev_enumerate_unref ( enumerate ) ;
2021-09-24 17:31:20 +01:00
2013-12-07 16:11:51 +01:00
return true ;
2013-12-07 14:13:40 +01:00
}
2017-01-10 17:59:48 +01:00
static void * udev_input_init ( const char * joypad_driver )
2013-12-07 14:13:40 +01:00
{
2021-09-24 17:31:20 +01:00
int mouse = 0 ;
int keyboard = 0 ;
2017-06-11 20:44:02 +02:00
int fd ;
2017-06-28 18:01:04 +02:00
# ifdef UDEV_XKB_HANDLING
gfx_ctx_ident_t ctx_ident ;
# endif
2016-09-18 20:32:16 +02:00
udev_input_t * udev = ( udev_input_t * ) calloc ( 1 , sizeof ( * udev ) ) ;
2015-01-10 01:32:09 +01:00
2013-12-07 14:13:40 +01:00
if ( ! udev )
return NULL ;
2015-12-17 03:02:48 +01:00
udev - > udev = udev_new ( ) ;
if ( ! udev - > udev )
2013-12-07 17:12:25 +01:00
goto error ;
2015-12-17 03:02:48 +01:00
udev - > monitor = udev_monitor_new_from_netlink ( udev - > udev , " udev " ) ;
if ( udev - > monitor )
{
udev_monitor_filter_add_match_subsystem_devtype ( udev - > monitor , " input " , NULL ) ;
udev_monitor_enable_receiving ( udev - > monitor ) ;
}
2013-12-07 17:12:25 +01:00
2017-06-07 12:25:10 +02:00
# ifdef UDEV_XKB_HANDLING
if ( init_xkb ( - 1 , 0 ) = = - 1 )
goto error ;
video_context_driver_get_ident ( & ctx_ident ) ;
2017-07-22 16:08:05 -04:00
udev - > xkb_handling = string_is_equal ( ctx_ident . ident , " kms " ) ;
2017-06-07 12:25:10 +02:00
# endif
2017-11-30 07:28:59 +01:00
# if defined(HAVE_EPOLL)
2017-06-11 20:44:02 +02:00
fd = epoll_create ( 32 ) ;
if ( fd < 0 )
2013-12-07 17:12:25 +01:00
goto error ;
2017-11-30 07:28:59 +01:00
# elif defined(HAVE_KQUEUE)
fd = kqueue ( ) ;
if ( fd = = - 1 )
goto error ;
# endif
2013-12-07 14:13:40 +01:00
2017-11-30 07:00:09 +01:00
udev - > fd = fd ;
2017-06-11 20:44:02 +02:00
2017-06-02 07:57:07 +02:00
if ( ! open_devices ( udev , UDEV_INPUT_KEYBOARD , udev_handle_keyboard ) )
2013-12-07 16:11:51 +01:00
goto error ;
2017-06-02 07:57:07 +02:00
if ( ! open_devices ( udev , UDEV_INPUT_MOUSE , udev_handle_mouse ) )
2013-12-07 16:11:51 +01:00
goto error ;
2013-12-07 14:13:40 +01:00
2017-10-05 05:18:53 +02:00
if ( ! open_devices ( udev , UDEV_INPUT_TOUCHPAD , udev_handle_mouse ) )
2013-12-07 22:09:08 +01:00
goto error ;
2017-10-05 05:18:53 +02:00
/* If using KMS and we forgot this,
2014-10-27 19:00:03 +01:00
* we could lock ourselves out completely . */
2013-12-07 22:09:08 +01:00
if ( ! udev - > num_devices )
2014-01-24 10:19:42 +01:00
RARCH_WARN ( " [udev]: Couldn't open any keyboard, mouse or touchpad. Are permissions set correctly for /dev/input/event*? \n " ) ;
2013-12-07 22:09:08 +01:00
2015-01-12 02:52:52 +01:00
input_keymaps_init_keyboard_lut ( rarch_key_map_linux ) ;
2013-12-09 16:56:33 +01:00
2019-01-01 03:16:33 +03:00
# ifdef __linux__
2015-11-14 22:03:37 +01:00
linux_terminal_disable_input ( ) ;
2019-01-01 03:16:33 +03:00
# endif
2016-01-02 22:28:21 +01:00
2017-06-03 18:01:27 +02:00
# ifndef HAVE_X11
2020-06-11 05:37:40 +02:00
/* TODO/FIXME - this can't be hidden behind a compile-time ifdef */
2017-06-03 18:01:27 +02:00
RARCH_WARN ( " [udev]: Full-screen pointer won't be available. \n " ) ;
# endif
2021-09-24 17:31:20 +01:00
for ( int i = 0 ; i < udev - > num_devices ; + + i )
{
if ( udev - > devices [ i ] - > type ! = UDEV_INPUT_KEYBOARD )
{
RARCH_LOG ( " [udev]: Mouse #%u: \" %s \" (%s). \n " ,
mouse ,
udev - > devices [ i ] - > ident ,
udev - > devices [ i ] - > devnode ) ;
input_config_set_mouse_display_name ( mouse , udev - > devices [ i ] - > ident ) ;
mouse + + ;
}
else
{
RARCH_LOG ( " [udev]: Keyboard #%u: \" %s \" (%s). \n " ,
keyboard ,
udev - > devices [ i ] - > ident ,
udev - > devices [ i ] - > devnode ) ;
keyboard + + ;
}
}
2013-12-07 14:13:40 +01:00
return udev ;
2013-12-07 16:11:51 +01:00
error :
udev_input_free ( udev ) ;
return NULL ;
2013-12-07 14:13:40 +01:00
}
static uint64_t udev_input_get_capabilities ( void * data )
{
return
2014-10-04 15:14:39 +02:00
( 1 < < RETRO_DEVICE_JOYPAD ) |
( 1 < < RETRO_DEVICE_ANALOG ) |
2013-12-07 14:13:40 +01:00
( 1 < < RETRO_DEVICE_KEYBOARD ) |
2014-10-04 15:14:39 +02:00
( 1 < < RETRO_DEVICE_MOUSE ) |
2013-12-07 14:13:40 +01:00
( 1 < < RETRO_DEVICE_LIGHTGUN ) ;
}
2013-12-07 16:11:51 +01:00
static void udev_input_grab_mouse ( void * data , bool state )
{
2017-06-03 18:01:27 +02:00
# ifdef HAVE_X11
2017-06-03 16:26:08 +02:00
Window window ;
2017-06-03 18:54:04 +02:00
Display * display = NULL ;
2017-06-03 16:26:08 +02:00
if ( video_driver_display_type_get ( ) ! = RARCH_DISPLAY_X11 )
{
RARCH_WARN ( " [udev]: Mouse grab/ungrab feature unavailable. \n " ) ;
return ;
}
display = ( Display * ) video_driver_display_get ( ) ;
window = ( Window ) video_driver_window_get ( ) ;
if ( state )
XGrabPointer ( display , window , False ,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask ,
GrabModeAsync , GrabModeAsync , window , None , CurrentTime ) ;
else
XUngrabPointer ( display , CurrentTime ) ;
2017-06-03 18:01:27 +02:00
# else
RARCH_WARN ( " [udev]: Mouse grab/ungrab feature unavailable. \n " ) ;
# endif
2013-12-07 16:11:51 +01:00
}
2014-09-11 07:06:20 +02:00
input_driver_t input_udev = {
2013-12-07 14:13:40 +01:00
udev_input_init ,
udev_input_poll ,
udev_input_state ,
udev_input_free ,
NULL ,
NULL ,
udev_input_get_capabilities ,
" udev " ,
2013-12-07 16:11:51 +01:00
udev_input_grab_mouse ,
2019-01-01 03:16:33 +03:00
# ifdef __linux__
2020-09-02 00:38:11 +02:00
linux_terminal_grab_stdin
2019-01-01 03:16:33 +03:00
# else
2020-09-02 00:38:11 +02:00
NULL
2019-01-01 03:16:33 +03:00
# endif
2013-12-07 14:13:40 +01:00
} ;