Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a656e801 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "floss: avrcp: implement send_key method to handle the key event"

parents ac515334 73a92e76
Loading
Loading
Loading
Loading
+97 −13
Original line number Original line Diff line number Diff line
@@ -35,6 +35,8 @@ const EV_KEY: libc::c_int = 0x01;
const EV_REL: libc::c_int = 0x02;
const EV_REL: libc::c_int = 0x02;
const EV_REP: libc::c_int = 0x14;
const EV_REP: libc::c_int = 0x14;


const SYN_REPORT: libc::c_int = 0;

const UI_DEV_CREATE: u64 = nix::request_code_none!(UINPUT_IOCTL_BASE, 1);
const UI_DEV_CREATE: u64 = nix::request_code_none!(UINPUT_IOCTL_BASE, 1);
const UI_DEV_DESTROY: u64 = nix::request_code_none!(UINPUT_IOCTL_BASE, 2);
const UI_DEV_DESTROY: u64 = nix::request_code_none!(UINPUT_IOCTL_BASE, 2);
const UI_SET_EVBIT: u64 =
const UI_SET_EVBIT: u64 =
@@ -69,6 +71,12 @@ struct UInputId {
    version: libc::c_ushort,
    version: libc::c_ushort,
}
}


impl Default for UInputId {
    fn default() -> Self {
        UInputId { bustype: BUS_BLUETOOTH, vendor: 0, product: 0, version: 0 }
    }
}

#[repr(C, packed)]
#[repr(C, packed)]
struct UInputDev {
struct UInputDev {
    name: [libc::c_char; UINPUT_MAX_NAME_SIZE],
    name: [libc::c_char; UINPUT_MAX_NAME_SIZE],
@@ -80,7 +88,20 @@ struct UInputDev {
    absflat: [libc::c_int; ABS_MAX + 1],
    absflat: [libc::c_int; ABS_MAX + 1],
}
}


#[allow(dead_code)]
impl Default for UInputDev {
    fn default() -> Self {
        UInputDev {
            name: [0; UINPUT_MAX_NAME_SIZE],
            id: UInputId::default(),
            ff_effects_max: 0,
            absmax: [0; ABS_MAX + 1],
            absmin: [0; ABS_MAX + 1],
            absfuzz: [0; ABS_MAX + 1],
            absflat: [0; ABS_MAX + 1],
        }
    }
}

impl UInputDev {
impl UInputDev {
    pub fn serialize(&mut self) -> &[u8] {
    pub fn serialize(&mut self) -> &[u8] {
        unsafe {
        unsafe {
@@ -92,6 +113,25 @@ impl UInputDev {
    }
    }
}
}


#[repr(C, packed)]
struct UInputEvent {
    time: libc::timeval,
    event_type: libc::c_ushort,
    code: libc::c_ushort,
    value: libc::c_int,
}

impl UInputEvent {
    pub fn serialize(&mut self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(
                (self as *const UInputEvent) as *const u8,
                mem::size_of::<UInputEvent>(),
            )
        }
    }
}

/// A struct that holds the uinput object. It consists of a file descriptor fetched from the kernel
/// A struct that holds the uinput object. It consists of a file descriptor fetched from the kernel
/// and a device struct which contains the information required to construct an uinput device.
/// and a device struct which contains the information required to construct an uinput device.
pub struct UInput {
pub struct UInput {
@@ -108,18 +148,7 @@ impl Drop for UInput {
impl UInput {
impl UInput {
    /// Create a new UInput object.
    /// Create a new UInput object.
    pub fn new() -> Self {
    pub fn new() -> Self {
        UInput {
        UInput { fd: -1, device: UInputDev::default() }
            fd: -1,
            device: UInputDev {
                name: [0; UINPUT_MAX_NAME_SIZE],
                id: UInputId { bustype: BUS_BLUETOOTH, vendor: 0, product: 0, version: 0 },
                ff_effects_max: 0,
                absmax: [0; ABS_MAX + 1],
                absmin: [0; ABS_MAX + 1],
                absfuzz: [0; ABS_MAX + 1],
                absflat: [0; ABS_MAX + 1],
            },
        }
    }
    }


    /// Return true if uinput is open and a valid fd is retrieved.
    /// Return true if uinput is open and a valid fd is retrieved.
@@ -194,6 +223,61 @@ impl UInput {
                libc::close(self.fd);
                libc::close(self.fd);
            }
            }
            self.fd = -1;
            self.fd = -1;
            self.device = UInputDev::default();
        }
    }

    fn send_event(
        &mut self,
        event_type: libc::c_ushort,
        code: libc::c_ushort,
        value: libc::c_int,
    ) -> i32 {
        let mut event = UInputEvent {
            time: libc::timeval { tv_sec: 0, tv_usec: 0 },
            event_type: event_type,
            code: code,
            value: value,
        };

        unsafe {
            libc::write(
                self.fd,
                event.serialize().as_ptr() as *const libc::c_void,
                mem::size_of::<UInputDev>(),
            )
            .try_into()
            .unwrap()
        }
    }
    }

    /// Send key event to the uinput if the device is initialized.
    pub fn send_key(&mut self, key: u8, value: u8) -> Result<(), String> {
        let mut uinput_key: libc::c_ushort = 0;

        for key_map in KEY_MAP {
            if key_map.avc == key {
                uinput_key = key_map.uinput.try_into().unwrap();
            }
        }

        if uinput_key == 0 {
            return Err(format!("AVRCP key: {} is not supported", key));
        }

        if self.is_initialized() {
            if self.send_event(EV_KEY.try_into().unwrap(), uinput_key, value.into()) < 0
                || self.send_event(EV_SYN.try_into().unwrap(), SYN_REPORT.try_into().unwrap(), 0)
                    < 0
            {
                return Err(format!(
                    "Failed to send uinput event: {}",
                    std::io::Error::last_os_error()
                ));
            }
            return Ok(());
        }

        Err(format!("uinput is not initialized"))
    }
    }
}
}