#![cfg(all(feature = "dev-capture", target_os = "linux"))]
use crate::api::common_capnp;
use crate::api::Endpoint;
use crate::api::EvdevInfo;
use crate::mailbox;
use crate::module::vhid;
use evdev_rs::DeviceWrapper;
use hid_io_protocol::*;
const EVDEV2HIDKEY: [(HidIoCommandId, u16); 548] = [
(HidIoCommandId::HidKeyboard, 0x00), (HidIoCommandId::HidKeyboard, 0x29), (HidIoCommandId::HidKeyboard, 0x1E), (HidIoCommandId::HidKeyboard, 0x1F), (HidIoCommandId::HidKeyboard, 0x20), (HidIoCommandId::HidKeyboard, 0x21), (HidIoCommandId::HidKeyboard, 0x22), (HidIoCommandId::HidKeyboard, 0x23), (HidIoCommandId::HidKeyboard, 0x24), (HidIoCommandId::HidKeyboard, 0x25), (HidIoCommandId::HidKeyboard, 0x26), (HidIoCommandId::HidKeyboard, 0x27), (HidIoCommandId::HidKeyboard, 0x2D), (HidIoCommandId::HidKeyboard, 0x2E), (HidIoCommandId::HidKeyboard, 0x2A), (HidIoCommandId::HidKeyboard, 0x2B), (HidIoCommandId::HidKeyboard, 0x14), (HidIoCommandId::HidKeyboard, 0x1A), (HidIoCommandId::HidKeyboard, 0x08), (HidIoCommandId::HidKeyboard, 0x15), (HidIoCommandId::HidKeyboard, 0x17), (HidIoCommandId::HidKeyboard, 0x1C), (HidIoCommandId::HidKeyboard, 0x18), (HidIoCommandId::HidKeyboard, 0x0C), (HidIoCommandId::HidKeyboard, 0x12), (HidIoCommandId::HidKeyboard, 0x13), (HidIoCommandId::HidKeyboard, 0x2F), (HidIoCommandId::HidKeyboard, 0x30), (HidIoCommandId::HidKeyboard, 0x28), (HidIoCommandId::HidKeyboard, 0xE0), (HidIoCommandId::HidKeyboard, 0x04), (HidIoCommandId::HidKeyboard, 0x16), (HidIoCommandId::HidKeyboard, 0x07), (HidIoCommandId::HidKeyboard, 0x09), (HidIoCommandId::HidKeyboard, 0x0A), (HidIoCommandId::HidKeyboard, 0x0B), (HidIoCommandId::HidKeyboard, 0x0D), (HidIoCommandId::HidKeyboard, 0x0E), (HidIoCommandId::HidKeyboard, 0x0F), (HidIoCommandId::HidKeyboard, 0x33), (HidIoCommandId::HidKeyboard, 0x34), (HidIoCommandId::HidKeyboard, 0x35), (HidIoCommandId::HidKeyboard, 0xE1), (HidIoCommandId::HidKeyboard, 0x31), (HidIoCommandId::HidKeyboard, 0x1D), (HidIoCommandId::HidKeyboard, 0x1B), (HidIoCommandId::HidKeyboard, 0x06), (HidIoCommandId::HidKeyboard, 0x19), (HidIoCommandId::HidKeyboard, 0x05), (HidIoCommandId::HidKeyboard, 0x11), (HidIoCommandId::HidKeyboard, 0x10), (HidIoCommandId::HidKeyboard, 0x36), (HidIoCommandId::HidKeyboard, 0x37), (HidIoCommandId::HidKeyboard, 0x38), (HidIoCommandId::HidKeyboard, 0xE5), (HidIoCommandId::HidKeyboard, 0x55), (HidIoCommandId::HidKeyboard, 0xE2), (HidIoCommandId::HidKeyboard, 0x2C), (HidIoCommandId::HidKeyboard, 0x39), (HidIoCommandId::HidKeyboard, 0x3A), (HidIoCommandId::HidKeyboard, 0x3B), (HidIoCommandId::HidKeyboard, 0x3C), (HidIoCommandId::HidKeyboard, 0x3D), (HidIoCommandId::HidKeyboard, 0x3E), (HidIoCommandId::HidKeyboard, 0x3F), (HidIoCommandId::HidKeyboard, 0x40), (HidIoCommandId::HidKeyboard, 0x41), (HidIoCommandId::HidKeyboard, 0x42), (HidIoCommandId::HidKeyboard, 0x43), (HidIoCommandId::HidKeyboard, 0x53), (HidIoCommandId::HidKeyboard, 0x47), (HidIoCommandId::HidKeyboard, 0x5F), (HidIoCommandId::HidKeyboard, 0x60), (HidIoCommandId::HidKeyboard, 0x61), (HidIoCommandId::HidKeyboard, 0x56), (HidIoCommandId::HidKeyboard, 0x5C), (HidIoCommandId::HidKeyboard, 0x5D), (HidIoCommandId::HidKeyboard, 0x5E), (HidIoCommandId::HidKeyboard, 0x57), (HidIoCommandId::HidKeyboard, 0x59), (HidIoCommandId::HidKeyboard, 0x5A), (HidIoCommandId::HidKeyboard, 0x5B), (HidIoCommandId::HidKeyboard, 0x62), (HidIoCommandId::HidKeyboard, 0x63), (HidIoCommandId::Unused, 0), (HidIoCommandId::HidKeyboard, 0x94), (HidIoCommandId::HidKeyboard, 0x64), (HidIoCommandId::HidKeyboard, 0x44), (HidIoCommandId::HidKeyboard, 0x45), (HidIoCommandId::Unused, 0), (HidIoCommandId::HidKeyboard, 0x92), (HidIoCommandId::HidKeyboard, 0x93), (HidIoCommandId::HidKeyboard, 0x8A), (HidIoCommandId::HidKeyboard, 0x88), (HidIoCommandId::HidKeyboard, 0x8B), (HidIoCommandId::Unused, 0), (HidIoCommandId::HidKeyboard, 0x58), (HidIoCommandId::HidKeyboard, 0xE4), (HidIoCommandId::HidKeyboard, 0x54), (HidIoCommandId::HidKeyboard, 0x9A), (HidIoCommandId::HidKeyboard, 0xE6), (HidIoCommandId::Unused, 0), (HidIoCommandId::HidKeyboard, 0x4A), (HidIoCommandId::HidKeyboard, 0x52), (HidIoCommandId::HidKeyboard, 0x4B), (HidIoCommandId::HidKeyboard, 0x50), (HidIoCommandId::HidKeyboard, 0x4F), (HidIoCommandId::HidKeyboard, 0x4D), (HidIoCommandId::HidKeyboard, 0x51), (HidIoCommandId::HidKeyboard, 0x4E), (HidIoCommandId::HidKeyboard, 0x49), (HidIoCommandId::HidKeyboard, 0x4C), (HidIoCommandId::Unused, 0), (HidIoCommandId::HidKeyboard, 0x7F), (HidIoCommandId::HidKeyboard, 0x81), (HidIoCommandId::HidKeyboard, 0x80), (HidIoCommandId::HidConsumerCtrl, 0x030), (HidIoCommandId::HidKeyboard, 0x67), (HidIoCommandId::HidKeyboard, 0xD7), (HidIoCommandId::HidKeyboard, 0x48), (HidIoCommandId::Unused, 0), (HidIoCommandId::HidKeyboard, 0x85), (HidIoCommandId::HidKeyboard, 0x90), (HidIoCommandId::HidKeyboard, 0x91), (HidIoCommandId::HidKeyboard, 0x89), (HidIoCommandId::HidKeyboard, 0xE3), (HidIoCommandId::HidKeyboard, 0xE7), (HidIoCommandId::Unused, 0), (HidIoCommandId::HidKeyboard, 0x78), (HidIoCommandId::HidKeyboard, 0x79), (HidIoCommandId::Unused, 0), (HidIoCommandId::HidKeyboard, 0x7A), (HidIoCommandId::Unused, 0), (HidIoCommandId::HidKeyboard, 0x7C), (HidIoCommandId::HidConsumerCtrl, 0x202), (HidIoCommandId::HidKeyboard, 0x7D), (HidIoCommandId::HidKeyboard, 0x7E), (HidIoCommandId::HidKeyboard, 0x7B), (HidIoCommandId::HidKeyboard, 0x75), (HidIoCommandId::HidKeyboard, 0x76), (HidIoCommandId::HidConsumerCtrl, 0x192), (HidIoCommandId::HidSystemCtrl, 0xA2), (HidIoCommandId::HidSystemCtrl, 0x82), (HidIoCommandId::HidSystemCtrl, 0x83), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::HidKeyboard, 0xB6), (HidIoCommandId::HidKeyboard, 0xB7), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::HidKeyboard, 0x68), (HidIoCommandId::HidKeyboard, 0x69), (HidIoCommandId::HidKeyboard, 0x6A), (HidIoCommandId::HidKeyboard, 0x6B), (HidIoCommandId::HidKeyboard, 0x6C), (HidIoCommandId::HidKeyboard, 0x6D), (HidIoCommandId::HidKeyboard, 0x6E), (HidIoCommandId::HidKeyboard, 0x6F), (HidIoCommandId::HidKeyboard, 0x70), (HidIoCommandId::HidKeyboard, 0x71), (HidIoCommandId::HidKeyboard, 0x72), (HidIoCommandId::HidKeyboard, 0x73), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0), (HidIoCommandId::Unused, 0),
];
fn evdev2basehid(code: evdev_rs::enums::EventCode) -> std::io::Result<(HidIoCommandId, u16)> {
use evdev_rs::enums::EventCode;
match code {
EventCode::EV_KEY(key) => {
let key = key as usize;
let lookup = EVDEV2HIDKEY[key];
if lookup.0 == HidIoCommandId::Unused {
Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
format!(
"No key hid code lookup for ev code: {} {:?} {}",
code, key, lookup.1
),
))
} else {
Ok(lookup)
}
}
_ => Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("No hid code lookup for ev code: {code}"),
)),
}
}
pub struct EvdevDevice {
mailbox: mailbox::Mailbox,
uid: u64,
endpoint: Endpoint,
fd_path: String,
}
impl EvdevDevice {
pub fn new(mailbox: mailbox::Mailbox, fd_path: String) -> std::io::Result<EvdevDevice> {
let file = std::fs::File::open(fd_path.clone())?;
let device = evdev_rs::Device::new_from_file(file)?;
let devtype = device_type(&device, fd_path.clone())?;
let mut evdev_info = EvdevInfo::new(device);
let uid = mailbox
.clone()
.assign_uid(evdev_info.key(), fd_path.clone())
.unwrap();
let mut endpoint = Endpoint::new(devtype, uid);
endpoint.set_evdev_params(evdev_info);
mailbox.clone().register_node(endpoint.clone());
Ok(EvdevDevice {
mailbox,
uid,
endpoint,
fd_path,
})
}
pub fn process(&mut self) -> std::io::Result<()> {
let fd_path = self.fd_path.clone();
let file = std::fs::File::open(fd_path)?;
let mut device = evdev_rs::Device::new_from_file(file)?;
info!("Connection event uid:{} {}", self.uid, device_name(&device));
device.grab(evdev_rs::GrabMode::Grab).unwrap();
let mut event_queue: Vec<evdev_rs::InputEvent> = vec![];
let mut event_queue_command = HidIoCommandId::HidKeyboard; let mut drop_until_next_syn_report = false;
let mut event: std::io::Result<(evdev_rs::ReadStatus, evdev_rs::InputEvent)>;
loop {
event = device.next_event(evdev_rs::ReadFlag::NORMAL | evdev_rs::ReadFlag::BLOCKING);
if event.is_ok() {
let mut result = event.ok().unwrap();
debug!(
"uid:{} {:?} {:?} {}",
self.uid,
&result.1.event_type(),
&result.1.event_code,
&result.1.value
);
match result.0 {
evdev_rs::ReadStatus::Sync => {
warn!("Dropped evdev event! - Attempting to resync...");
while result.0 == evdev_rs::ReadStatus::Sync {
warn!(
"Dropped: uid:{} {:?} {:?} {}",
self.uid,
&result.1.event_type(),
&result.1.event_code,
&result.1.value
);
event = device.next_event(evdev_rs::ReadFlag::SYNC);
if event.is_ok() {
result = event.ok().unwrap();
} else {
return Ok(());
}
}
warn!("Resyncing successful.");
}
evdev_rs::ReadStatus::Success => {
match &result.1.event_code {
evdev_rs::enums::EventCode::EV_SYN(
evdev_rs::enums::EV_SYN::SYN_REPORT,
) => {
if drop_until_next_syn_report {
event_queue = vec![];
drop_until_next_syn_report = false;
} else {
let data = match event_queue_command {
HidIoCommandId::HidKeyboard => {
let mut data = vec![];
for event in event_queue.clone() {
let code = event.event_code;
match evdev2basehid(code) {
Ok(code) => {
if code.0 == HidIoCommandId::HidKeyboard {
if event.value == 1 {
data.push(code.1 as u8);
} else {
data.retain(|&x| x != code.1 as u8);
}
} else {
warn!("Skipping: {:?}", code);
continue;
}
}
Err(msg) => {
warn!("Err: {:?}", msg);
continue;
}
}
}
data
}
_ => {
debug!(
"Ignoring send: uid:{} {:?}",
self.uid, event_queue
);
continue;
}
};
self.mailbox
.try_send_command(
mailbox::Address::DeviceHid { uid: self.uid },
mailbox::Address::All,
event_queue_command,
data,
false,
)
.unwrap();
}
continue;
}
evdev_rs::enums::EventCode::EV_SYN(
evdev_rs::enums::EV_SYN::SYN_DROPPED,
) => {
drop_until_next_syn_report = true;
continue;
}
_ => {}
}
event_queue_command = match self.endpoint.type_() {
common_capnp::NodeType::HidKeyboard => {
if !&result.1.is_type(&evdev_rs::enums::EventType::EV_KEY) {
continue;
}
HidIoCommandId::HidKeyboard
}
common_capnp::NodeType::HidMouse => {
HidIoCommandId::HidMouse
}
common_capnp::NodeType::HidJoystick => {
HidIoCommandId::HidJoystick
}
_ => {
panic!(
"Unknown type for EvdevDevice endpoint node: {:?}",
self.endpoint.type_()
);
}
};
event_queue.push(result.1);
}
}
} else {
let err = event.err().unwrap();
match err.raw_os_error() {
Some(libc::EAGAIN) => continue,
_ => {
info!(
"Disconnection event uid:{} {}",
self.uid,
device_name(&device)
);
return Ok(());
}
}
}
}
}
}
impl Drop for EvdevDevice {
fn drop(&mut self) {
self.mailbox.unregister_node(self.uid);
}
}
fn device_name(device: &evdev_rs::Device) -> String {
let string = format!(
"[{:04x}:{:04x}-{:?}] {} {} {}",
device.vendor_id(),
device.product_id(),
evdev_rs::enums::int_to_bus_type(device.bustype() as u32),
device.name().unwrap_or(""),
device.phys().unwrap_or(""),
device.uniq().unwrap_or(""),
);
string
}
fn device_type(
device: &evdev_rs::Device,
fd_path: String,
) -> std::io::Result<common_capnp::NodeType> {
use evdev_rs::enums::*;
if device.has(&EventCode::EV_KEY(EV_KEY::KEY_F))
|| device.has(&EventCode::EV_KEY(EV_KEY::KEY_J))
{
Ok(common_capnp::NodeType::HidKeyboard)
} else if device.has(&EventCode::EV_KEY(EV_KEY::BTN_LEFT)) {
Ok(common_capnp::NodeType::HidMouse)
} else if device.has(&EventCode::EV_KEY(EV_KEY::BTN_TRIGGER)) {
Ok(common_capnp::NodeType::HidJoystick)
} else {
Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("{fd_path} is not a keyboard, mouse or joystick"),
))
}
}
pub fn supported_ids() -> Vec<HidIoCommandId> {
let ids: Vec<HidIoCommandId> = vec![];
ids
}
pub async fn initialize(_mailbox: mailbox::Mailbox) {
info!("Initializing device/evdev...");
}
pub fn udev_find_input_event_device(
vid: u16,
pid: u16,
subsystem: String,
uniq: String,
timeout: std::time::Duration,
) -> Result<udev::Device, std::io::Error> {
match vhid::uhid::udev_find_device(vid, pid, subsystem, uniq, timeout) {
Ok(device) => {
let mut enumerator = udev::Enumerator::new().unwrap();
enumerator.match_parent(&device).unwrap();
enumerator.match_subsystem("input").unwrap();
for device in enumerator.scan_devices().unwrap() {
let fd_path = format!("/dev/input/{}", device.sysname().to_str().unwrap());
if fd_path.contains("event") {
return Ok(device);
}
}
Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Cound not find input event device...",
))
}
Err(err) => Err(err),
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::logging::setup_logging_lite;
use std::sync::{Arc, RwLock};
#[test]
#[ignore]
fn uhid_evdev_keyboard_test() {
setup_logging_lite().ok();
let name = "evdev-keyboard-nkro-test".to_string();
let mailbox = mailbox::Mailbox {
..Default::default()
};
*mailbox.last_uid.write().unwrap() = 10;
let uniq = nanoid::nanoid!();
let mut keyboard = vhid::uhid::KeyboardNkro::new(
mailbox.clone(),
name,
"".to_string(),
uniq.clone(),
uhid_virt::Bus::USB,
vhid::IC_VID as u32,
vhid::IC_PID_KEYBOARD as u32,
0,
0,
)
.unwrap();
let device = match udev_find_input_event_device(
vhid::IC_VID,
vhid::IC_PID_KEYBOARD,
"input".to_string(),
uniq,
std::time::Duration::new(10, 0),
) {
Ok(device) => device,
Err(err) => {
panic!("Could not find udev device... {}", err);
}
};
while !device.is_initialized() {} let fd_path = format!("/dev/input/{}", device.sysname().to_str().unwrap());
let mut receiver = mailbox.sender.subscribe();
let rt = tokio::runtime::Runtime::new().unwrap();
let status: Arc<RwLock<bool>> = Arc::new(RwLock::new(false));
let status2 = status.clone();
rt.spawn(async move {
let expected_msgs = vec![vec![4], vec![4, 5], vec![5], vec![]];
let mut msg_pos = 0;
loop {
match receiver.recv().await {
Ok(msg) => {
if msg_pos + 1 == expected_msgs.len() {
*(status.clone().write().unwrap()) = true;
continue;
}
if msg.data.data.to_vec() == expected_msgs[msg_pos] {
msg_pos += 1;
} else {
assert!(
msg.data.data.to_vec() == vec![],
"Unexpected message: {:?}",
msg
);
}
}
Err(tokio::sync::broadcast::error::RecvError::Closed) => {
panic!("Mailbox has been closed unexpectedly!");
}
Err(tokio::sync::broadcast::error::RecvError::Lagged(skipped)) => {
panic!(
"Mailbox has received too many messages, lagging by: {}",
skipped
);
}
};
}
});
rt.spawn(async move {
tokio::task::spawn_blocking(move || {
EvdevDevice::new(mailbox.clone(), fd_path)
.unwrap()
.process()
.unwrap();
});
});
rt.block_on(async {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
keyboard.send(vec![4]).unwrap();
keyboard.send(vec![4, 5]).unwrap();
keyboard.send(vec![5]).unwrap();
keyboard.send(vec![]).unwrap();
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
});
rt.shutdown_timeout(std::time::Duration::from_millis(100));
let status: bool = *status2.read().unwrap();
assert!(status, "Test failed");
}
}