From b1b63505c90505e783ab1010aa73146b7c38142d Mon Sep 17 00:00:00 2001 From: Chris Spencer Date: Thu, 27 Oct 2022 13:47:30 +0100 Subject: [PATCH] Add Android uinput bindings --- libc-test/build.rs | 14 +++ libc-test/semver/android.txt | 45 ++++++++ src/unix/linux_like/android/mod.rs | 175 +++++++++++++++++++++++++++++ 3 files changed, 234 insertions(+) diff --git a/libc-test/build.rs b/libc-test/build.rs index 8573fbc1a07d8..8838c17721ae7 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -1627,6 +1627,7 @@ fn test_android(target: &str) { "linux/seccomp.h", "linux/sched.h", "linux/sockios.h", + "linux/uinput.h", "linux/vm_sockets.h", "linux/wait.h", @@ -1663,6 +1664,17 @@ fn test_android(target: &str) { s if s.ends_with("_nsec") && struct_.starts_with("stat") => s.to_string(), // FIXME: appears that `epoll_event.data` is an union "u64" if struct_ == "epoll_event" => "data.u64".to_string(), + // The following structs have a field called `type` in C, + // but `type` is a Rust keyword, so these fields are translated + // to `type_` in Rust. + "type_" + if struct_ == "input_event" + || struct_ == "input_mask" + || struct_ == "ff_effect" => + { + "type".to_string() + } + s => s.to_string(), } }); @@ -1792,6 +1804,8 @@ fn test_android(target: &str) { (struct_ == "ifaddrs" && field == "ifa_ifu") || // sigval is actually a union, but we pretend it's a struct (struct_ == "sigevent" && field == "sigev_value") || + // this one is an anonymous union + (struct_ == "ff_effect" && field == "u") || // FIXME: `sa_sigaction` has type `sighandler_t` but that type is // incorrect, see: https://github.com/rust-lang/libc/issues/1359 (struct_ == "sigaction" && field == "sa_sigaction") || diff --git a/libc-test/semver/android.txt b/libc-test/semver/android.txt index 6445af0264b56..1e914ae4384b0 100644 --- a/libc-test/semver/android.txt +++ b/libc-test/semver/android.txt @@ -1,3 +1,5 @@ +ABS_CNT +ABS_MAX ADDR_COMPAT_LAYOUT ADDR_LIMIT_32BIT ADDR_LIMIT_3GB @@ -568,6 +570,8 @@ ETXTBSY EUCLEAN EUNATCH EUSERS +EV_CNT +EV_MAX EWOULDBLOCK EXDEV EXFULL @@ -595,6 +599,8 @@ FD_ZERO FF0 FF1 FFDLY +FF_CNT +FF_MAX FILE FILENAME_MAX FIOCLEX @@ -786,6 +792,8 @@ INADDR_LOOPBACK INADDR_NONE INLCR INPCK +INPUT_PROP_CNT +INPUT_PROP_MAX INT_MAX INT_MIN IN_ACCESS @@ -1020,6 +1028,8 @@ IXANY IXOFF IXON JFFS2_SUPER_MAGIC +KEY_CNT +KEY_MAX LC_ADDRESS LC_ADDRESS_MASK LC_ALL @@ -1046,6 +1056,8 @@ LC_TELEPHONE LC_TELEPHONE_MASK LC_TIME LC_TIME_MASK +LED_CNT +LED_MAX LINUX_REBOOT_CMD_CAD_OFF LINUX_REBOOT_CMD_CAD_ON LINUX_REBOOT_CMD_HALT @@ -1170,6 +1182,8 @@ MPOL_F_STATIC_NODES MPOL_INTERLEAVE MPOL_LOCAL MPOL_PREFERRED +MSC_CNT +MSC_MAX MSDOS_SUPER_MAGIC MSG_CMSG_CLOEXEC MSG_CONFIRM @@ -1860,9 +1874,13 @@ REG_PEND REG_STARTEND REG_TRACE REISERFS_SUPER_MAGIC +REL_CNT +REL_MAX RENAME_EXCHANGE RENAME_NOREPLACE RENAME_WHITEOUT +REP_CNT +REP_MAX RLIMIT_AS RLIMIT_CORE RLIMIT_CPU @@ -2131,6 +2149,8 @@ SIOCSIFSLAVE SIOCSRARP SI_LOAD_SHIFT SMB_SUPER_MAGIC +SND_CNT +SND_MAX SOCK_CLOEXEC SOCK_DCCP SOCK_DGRAM @@ -2227,6 +2247,10 @@ ST_NOSUID ST_RDONLY ST_RELATIME ST_SYNCHRONOUS +SW_CNT +SW_MAX +SYN_CNT +SYN_MAX SYS_accept4 SYS_acct SYS_add_key @@ -2579,6 +2603,8 @@ TIOCSWINSZ TMPFS_MAGIC TMP_MAX TOSTOP +UINPUT_MAX_NAME_SIZE +UINPUT_VERSION UIO_MAXIOV USBDEVICE_SUPER_MAGIC USER_PROCESS @@ -2923,6 +2949,15 @@ feof ferror fexecve fflush +ff_condition_effect +ff_constant_effect +ff_effect +ff_envelope +ff_periodic_effect +ff_ramp_effect +ff_replay +ff_rumble_effect +ff_trigger fgetc fgetpos fgets @@ -3045,6 +3080,11 @@ inotify_event inotify_init inotify_init1 inotify_rm_watch +input_absinfo +input_event +input_id +input_keymap_entry +input_mask int16_t int32_t int64_t @@ -3509,6 +3549,11 @@ ttyname_r ucontext_t ucred uid_t +uinput_abs_setup +uinput_ff_erase +uinput_ff_upload +uinput_setup +uinput_user_dev uint16_t uint32_t uint64_t diff --git a/src/unix/linux_like/android/mod.rs b/src/unix/linux_like/android/mod.rs index 683a4c3ef9ae1..c8cd23dd5db8c 100644 --- a/src/unix/linux_like/android/mod.rs +++ b/src/unix/linux_like/android/mod.rs @@ -355,6 +355,133 @@ s! { pub flags: ::__u32, pub nr: ::__s32, } + + // linux/input.h + pub struct input_event { + pub time: ::timeval, + pub type_: ::__u16, + pub code: ::__u16, + pub value: ::__s32, + } + + pub struct input_id { + pub bustype: ::__u16, + pub vendor: ::__u16, + pub product: ::__u16, + pub version: ::__u16, + } + + pub struct input_absinfo { + pub value: ::__s32, + pub minimum: ::__s32, + pub maximum: ::__s32, + pub fuzz: ::__s32, + pub flat: ::__s32, + pub resolution: ::__s32, + } + + pub struct input_keymap_entry { + pub flags: ::__u8, + pub len: ::__u8, + pub index: ::__u16, + pub keycode: ::__u32, + pub scancode: [::__u8; 32], + } + + pub struct input_mask { + pub type_: ::__u32, + pub codes_size: ::__u32, + pub codes_ptr: ::__u64, + } + + pub struct ff_replay { + pub length: ::__u16, + pub delay: ::__u16, + } + + pub struct ff_trigger { + pub button: ::__u16, + pub interval: ::__u16, + } + + pub struct ff_envelope { + pub attack_length: ::__u16, + pub attack_level: ::__u16, + pub fade_length: ::__u16, + pub fade_level: ::__u16, + } + + pub struct ff_constant_effect { + pub level: ::__s16, + pub envelope: ff_envelope, + } + + pub struct ff_ramp_effect { + pub start_level: ::__s16, + pub end_level: ::__s16, + pub envelope: ff_envelope, + } + + pub struct ff_condition_effect { + pub right_saturation: ::__u16, + pub left_saturation: ::__u16, + + pub right_coeff: ::__s16, + pub left_coeff: ::__s16, + + pub deadband: ::__u16, + pub center: ::__s16, + } + + pub struct ff_periodic_effect { + pub waveform: ::__u16, + pub period: ::__u16, + pub magnitude: ::__s16, + pub offset: ::__s16, + pub phase: ::__u16, + + pub envelope: ff_envelope, + + pub custom_len: ::__u32, + pub custom_data: *mut ::__s16, + } + + pub struct ff_rumble_effect { + pub strong_magnitude: ::__u16, + pub weak_magnitude: ::__u16, + } + + pub struct ff_effect { + pub type_: ::__u16, + pub id: ::__s16, + pub direction: ::__u16, + pub trigger: ff_trigger, + pub replay: ff_replay, + // FIXME this is actually a union + #[cfg(target_pointer_width = "64")] + pub u: [u64; 4], + #[cfg(target_pointer_width = "32")] + pub u: [u32; 7], + } + + // linux/uinput.h + pub struct uinput_ff_upload { + pub request_id: ::__u32, + pub retval: ::__s32, + pub effect: ff_effect, + pub old: ff_effect, + } + + pub struct uinput_ff_erase { + pub request_id: ::__u32, + pub retval: ::__s32, + pub effect_id: ::__u32, + } + + pub struct uinput_abs_setup { + pub code: ::__u16, + pub absinfo: input_absinfo, + } } s_no_extra_traits! { @@ -417,6 +544,22 @@ s_no_extra_traits! { pub salg_name: [::c_uchar; 64], } + pub struct uinput_setup { + pub id: input_id, + pub name: [::c_char; UINPUT_MAX_NAME_SIZE], + pub ff_effects_max: ::__u32, + } + + pub struct uinput_user_dev { + pub name: [::c_char; UINPUT_MAX_NAME_SIZE], + pub id: input_id, + pub ff_effects_max: ::__u32, + pub absmax: [::__s32; ABS_CNT], + pub absmin: [::__s32; ABS_CNT], + pub absfuzz: [::__s32; ABS_CNT], + pub absflat: [::__s32; ABS_CNT], + } + /// WARNING: The `PartialEq`, `Eq` and `Hash` implementations of this /// type are unsound and will be removed in the future. #[deprecated( @@ -2173,6 +2316,38 @@ pub const NFT_TRACETYPE_RULE: ::c_int = 3; pub const NFT_NG_INCREMENTAL: ::c_int = 0; pub const NFT_NG_RANDOM: ::c_int = 1; +// linux/input.h +pub const FF_MAX: ::__u16 = 0x7f; +pub const FF_CNT: usize = FF_MAX as usize + 1; + +// linux/input-event-codes.h +pub const INPUT_PROP_MAX: ::__u16 = 0x1f; +pub const INPUT_PROP_CNT: usize = INPUT_PROP_MAX as usize + 1; +pub const EV_MAX: ::__u16 = 0x1f; +pub const EV_CNT: usize = EV_MAX as usize + 1; +pub const SYN_MAX: ::__u16 = 0xf; +pub const SYN_CNT: usize = SYN_MAX as usize + 1; +pub const KEY_MAX: ::__u16 = 0x2ff; +pub const KEY_CNT: usize = KEY_MAX as usize + 1; +pub const REL_MAX: ::__u16 = 0x0f; +pub const REL_CNT: usize = REL_MAX as usize + 1; +pub const ABS_MAX: ::__u16 = 0x3f; +pub const ABS_CNT: usize = ABS_MAX as usize + 1; +pub const SW_MAX: ::__u16 = 0x0f; +pub const SW_CNT: usize = SW_MAX as usize + 1; +pub const MSC_MAX: ::__u16 = 0x07; +pub const MSC_CNT: usize = MSC_MAX as usize + 1; +pub const LED_MAX: ::__u16 = 0x0f; +pub const LED_CNT: usize = LED_MAX as usize + 1; +pub const REP_MAX: ::__u16 = 0x01; +pub const REP_CNT: usize = REP_MAX as usize + 1; +pub const SND_MAX: ::__u16 = 0x07; +pub const SND_CNT: usize = SND_MAX as usize + 1; + +// linux/uinput.h +pub const UINPUT_VERSION: ::c_uint = 5; +pub const UINPUT_MAX_NAME_SIZE: usize = 80; + pub const IFF_TUN: ::c_int = 0x0001; pub const IFF_TAP: ::c_int = 0x0002; pub const IFF_NO_PI: ::c_int = 0x1000;