749 lines
20 KiB
Rust
749 lines
20 KiB
Rust
use evdev::{Device, InputEvent, KeyEvent, LedCode, LedEvent};
|
|
use std::collections::BTreeMap;
|
|
use std::fmt::Debug;
|
|
use std::fs;
|
|
use std::time::{Duration, SystemTime};
|
|
|
|
use evdev::uinput::VirtualDevice;
|
|
use evdev::{AttributeSet, KeyCode};
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub enum KeyState {
|
|
Latched(SystemTime),
|
|
Locked,
|
|
None,
|
|
}
|
|
|
|
impl Debug for KeyState {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Latched(arg0) => write!(
|
|
f,
|
|
"Latched {}s",
|
|
arg0.elapsed().unwrap_or_default().as_secs()
|
|
),
|
|
Self::Locked => write!(f, "Locked"),
|
|
Self::None => write!(f, "None"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl KeyState {
|
|
fn transition(&mut self, time: SystemTime, timeout: Duration) {
|
|
*self = match self {
|
|
KeyState::Latched(last_press) => {
|
|
if let Ok(elapsed) = time.duration_since(*last_press)
|
|
&& elapsed < timeout
|
|
{
|
|
KeyState::Locked
|
|
} else {
|
|
KeyState::None
|
|
}
|
|
}
|
|
KeyState::Locked => KeyState::None,
|
|
KeyState::None => KeyState::Latched(time),
|
|
}
|
|
}
|
|
|
|
fn pressed_state(&self) -> i32 {
|
|
match self {
|
|
KeyState::Locked | KeyState::Latched(_) => 1,
|
|
KeyState::None => 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct InternalState {
|
|
modifiers: BTreeMap<KeyCode, KeyState>,
|
|
timeout: Duration,
|
|
}
|
|
|
|
impl InternalState {
|
|
fn transition(&mut self, key: KeyCode, pressed: i32, timestamp: SystemTime) -> Vec<InputEvent> {
|
|
if let Some(key_state) = self.modifiers.get_mut(&key) {
|
|
if pressed == 1 {
|
|
key_state.transition(timestamp, self.timeout);
|
|
}
|
|
return vec![*KeyEvent::new(key, key_state.pressed_state())];
|
|
};
|
|
|
|
let mut events = vec![*KeyEvent::new(key, pressed)];
|
|
for (key, key_state) in self.modifiers.iter_mut() {
|
|
if let KeyState::Latched(_) = key_state {
|
|
*key_state = KeyState::None;
|
|
events.push(*KeyEvent::new(*key, 0));
|
|
}
|
|
}
|
|
|
|
events
|
|
}
|
|
|
|
fn led_state(&self) -> i32 {
|
|
if self.modifiers.values().any(|v| v.pressed_state() > 0) {
|
|
i32::MAX
|
|
} else {
|
|
0
|
|
}
|
|
}
|
|
}
|
|
|
|
fn pick_device() -> Option<Device> {
|
|
evdev::enumerate()
|
|
.map(|(_, device)| device)
|
|
.find(|d| d.name().is_some_and(|name| name.contains("keyboard")))
|
|
}
|
|
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut listen_on_modifiers = vec![];
|
|
let mut timeout = 500;
|
|
if let Some(config) = std::env::args().nth(1) {
|
|
for line in fs::read_to_string(config)?.trim().lines() {
|
|
match line.split_once("=") {
|
|
Some(("modifiers", modifiers)) => {
|
|
for modifier in modifiers.split(",") {
|
|
match modifier_name_to_key_code(modifier) {
|
|
Some(modifier) => listen_on_modifiers.push(modifier),
|
|
None => {
|
|
eprintln!(
|
|
"invalid modifier `{modifier}` supplied in config, valid modifiers are: leftshift, rightshift, leftctrl, rightctrl, compose, leftmeta, fn, capslock, rightmeta"
|
|
);
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Some(("timeout", timeout_str)) => match timeout_str.parse() {
|
|
Ok(milliseconds) => timeout = milliseconds,
|
|
Err(e) => {
|
|
eprintln!(
|
|
"failed to parse locking timeout from config: {e}, `{timeout_str}` supplied"
|
|
);
|
|
std::process::exit(1);
|
|
}
|
|
},
|
|
_ => {
|
|
eprintln!("invalid line in config: `{line}`");
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let (Some(mut keyboard), Some(mut led_sink)) = (pick_device(), pick_device()) else {
|
|
return Ok(());
|
|
};
|
|
while keyboard.grab().is_err() {}
|
|
|
|
println!("Taking over {}", keyboard.name().unwrap_or("keyboard"));
|
|
let keys: AttributeSet<KeyCode> = ALL_KEYS.iter().collect();
|
|
|
|
let mut lollipop_virtual_device = VirtualDevice::builder()?
|
|
.name("lollipop")
|
|
.with_keys(&keys)?
|
|
.build()?;
|
|
|
|
for path in lollipop_virtual_device.enumerate_dev_nodes_blocking()? {
|
|
let path = path?;
|
|
println!("Available as {}", path.display());
|
|
}
|
|
|
|
let mut state = InternalState {
|
|
modifiers: BTreeMap::default(),
|
|
timeout: Duration::from_millis(timeout),
|
|
};
|
|
|
|
if listen_on_modifiers.is_empty() {
|
|
listen_on_modifiers.extend([
|
|
KeyCode::KEY_LEFTSHIFT,
|
|
KeyCode::KEY_LEFTMETA,
|
|
KeyCode::KEY_LEFTCTRL,
|
|
KeyCode::KEY_LEFTALT,
|
|
]);
|
|
}
|
|
|
|
for key in listen_on_modifiers {
|
|
state.modifiers.insert(key, KeyState::None);
|
|
}
|
|
|
|
loop {
|
|
let Ok(events) = keyboard.fetch_events() else {
|
|
continue;
|
|
};
|
|
for event in events {
|
|
if let evdev::EventSummary::Key(key_event, key_code, pressed) = event.destructure() {
|
|
let events = state.transition(key_code, pressed, key_event.timestamp());
|
|
// println!("{state:#?}");
|
|
lollipop_virtual_device.emit(&events)?;
|
|
led_sink.send_events(&[*LedEvent::new(LedCode::LED_CAPSL, state.led_state())])?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn modifier_name_to_key_code(s: &str) -> Option<KeyCode> {
|
|
let ret = match s {
|
|
"leftshift" => KeyCode::KEY_LEFTSHIFT,
|
|
"rightshift" => KeyCode::KEY_RIGHTSHIFT,
|
|
"leftctrl" => KeyCode::KEY_LEFTCTRL,
|
|
"rightctrl" => KeyCode::KEY_RIGHTCTRL,
|
|
"compose" => KeyCode::KEY_COMPOSE,
|
|
"leftmeta" => KeyCode::KEY_LEFTMETA,
|
|
"fn" => KeyCode::KEY_FN,
|
|
"capslock" => KeyCode::KEY_CAPSLOCK,
|
|
"rightmeta" => KeyCode::KEY_RIGHTMETA,
|
|
_ => return None,
|
|
};
|
|
Some(ret)
|
|
}
|
|
|
|
const ALL_KEYS: &[KeyCode] = &[
|
|
KeyCode::KEY_RESERVED,
|
|
KeyCode::KEY_ESC,
|
|
KeyCode::KEY_1,
|
|
KeyCode::KEY_2,
|
|
KeyCode::KEY_3,
|
|
KeyCode::KEY_4,
|
|
KeyCode::KEY_5,
|
|
KeyCode::KEY_6,
|
|
KeyCode::KEY_7,
|
|
KeyCode::KEY_8,
|
|
KeyCode::KEY_9,
|
|
KeyCode::KEY_0,
|
|
KeyCode::KEY_MINUS,
|
|
KeyCode::KEY_EQUAL,
|
|
KeyCode::KEY_BACKSPACE,
|
|
KeyCode::KEY_TAB,
|
|
KeyCode::KEY_Q,
|
|
KeyCode::KEY_W,
|
|
KeyCode::KEY_E,
|
|
KeyCode::KEY_R,
|
|
KeyCode::KEY_T,
|
|
KeyCode::KEY_Y,
|
|
KeyCode::KEY_U,
|
|
KeyCode::KEY_I,
|
|
KeyCode::KEY_O,
|
|
KeyCode::KEY_P,
|
|
KeyCode::KEY_LEFTBRACE,
|
|
KeyCode::KEY_RIGHTBRACE,
|
|
KeyCode::KEY_ENTER,
|
|
KeyCode::KEY_LEFTCTRL,
|
|
KeyCode::KEY_A,
|
|
KeyCode::KEY_S,
|
|
KeyCode::KEY_D,
|
|
KeyCode::KEY_F,
|
|
KeyCode::KEY_G,
|
|
KeyCode::KEY_H,
|
|
KeyCode::KEY_J,
|
|
KeyCode::KEY_K,
|
|
KeyCode::KEY_L,
|
|
KeyCode::KEY_SEMICOLON,
|
|
KeyCode::KEY_APOSTROPHE,
|
|
KeyCode::KEY_GRAVE,
|
|
KeyCode::KEY_LEFTSHIFT,
|
|
KeyCode::KEY_BACKSLASH,
|
|
KeyCode::KEY_Z,
|
|
KeyCode::KEY_X,
|
|
KeyCode::KEY_C,
|
|
KeyCode::KEY_V,
|
|
KeyCode::KEY_B,
|
|
KeyCode::KEY_N,
|
|
KeyCode::KEY_M,
|
|
KeyCode::KEY_COMMA,
|
|
KeyCode::KEY_DOT,
|
|
KeyCode::KEY_SLASH,
|
|
KeyCode::KEY_RIGHTSHIFT,
|
|
KeyCode::KEY_KPASTERISK,
|
|
KeyCode::KEY_LEFTALT,
|
|
KeyCode::KEY_SPACE,
|
|
KeyCode::KEY_CAPSLOCK,
|
|
KeyCode::KEY_F1,
|
|
KeyCode::KEY_F2,
|
|
KeyCode::KEY_F3,
|
|
KeyCode::KEY_F4,
|
|
KeyCode::KEY_F5,
|
|
KeyCode::KEY_F6,
|
|
KeyCode::KEY_F7,
|
|
KeyCode::KEY_F8,
|
|
KeyCode::KEY_F9,
|
|
KeyCode::KEY_F10,
|
|
KeyCode::KEY_NUMLOCK,
|
|
KeyCode::KEY_SCROLLLOCK,
|
|
KeyCode::KEY_KP7,
|
|
KeyCode::KEY_KP8,
|
|
KeyCode::KEY_KP9,
|
|
KeyCode::KEY_KPMINUS,
|
|
KeyCode::KEY_KP4,
|
|
KeyCode::KEY_KP5,
|
|
KeyCode::KEY_KP6,
|
|
KeyCode::KEY_KPPLUS,
|
|
KeyCode::KEY_KP1,
|
|
KeyCode::KEY_KP2,
|
|
KeyCode::KEY_KP3,
|
|
KeyCode::KEY_KP0,
|
|
KeyCode::KEY_KPDOT,
|
|
KeyCode::KEY_ZENKAKUHANKAKU,
|
|
KeyCode::KEY_102ND,
|
|
KeyCode::KEY_F11,
|
|
KeyCode::KEY_F12,
|
|
KeyCode::KEY_RO,
|
|
KeyCode::KEY_KATAKANA,
|
|
KeyCode::KEY_HIRAGANA,
|
|
KeyCode::KEY_HENKAN,
|
|
KeyCode::KEY_KATAKANAHIRAGANA,
|
|
KeyCode::KEY_MUHENKAN,
|
|
KeyCode::KEY_KPJPCOMMA,
|
|
KeyCode::KEY_KPENTER,
|
|
KeyCode::KEY_RIGHTCTRL,
|
|
KeyCode::KEY_KPSLASH,
|
|
KeyCode::KEY_SYSRQ,
|
|
KeyCode::KEY_RIGHTALT,
|
|
KeyCode::KEY_LINEFEED,
|
|
KeyCode::KEY_HOME,
|
|
KeyCode::KEY_UP,
|
|
KeyCode::KEY_PAGEUP,
|
|
KeyCode::KEY_LEFT,
|
|
KeyCode::KEY_RIGHT,
|
|
KeyCode::KEY_END,
|
|
KeyCode::KEY_DOWN,
|
|
KeyCode::KEY_PAGEDOWN,
|
|
KeyCode::KEY_INSERT,
|
|
KeyCode::KEY_DELETE,
|
|
KeyCode::KEY_MACRO,
|
|
KeyCode::KEY_MUTE,
|
|
KeyCode::KEY_VOLUMEDOWN,
|
|
KeyCode::KEY_VOLUMEUP,
|
|
KeyCode::KEY_POWER,
|
|
KeyCode::KEY_KPEQUAL,
|
|
KeyCode::KEY_KPPLUSMINUS,
|
|
KeyCode::KEY_PAUSE,
|
|
KeyCode::KEY_SCALE,
|
|
KeyCode::KEY_KPCOMMA,
|
|
KeyCode::KEY_HANGEUL,
|
|
KeyCode::KEY_HANJA,
|
|
KeyCode::KEY_YEN,
|
|
KeyCode::KEY_LEFTMETA,
|
|
KeyCode::KEY_RIGHTMETA,
|
|
KeyCode::KEY_COMPOSE,
|
|
KeyCode::KEY_STOP,
|
|
KeyCode::KEY_AGAIN,
|
|
KeyCode::KEY_PROPS,
|
|
KeyCode::KEY_UNDO,
|
|
KeyCode::KEY_FRONT,
|
|
KeyCode::KEY_COPY,
|
|
KeyCode::KEY_OPEN,
|
|
KeyCode::KEY_PASTE,
|
|
KeyCode::KEY_FIND,
|
|
KeyCode::KEY_CUT,
|
|
KeyCode::KEY_HELP,
|
|
KeyCode::KEY_MENU,
|
|
KeyCode::KEY_CALC,
|
|
KeyCode::KEY_SETUP,
|
|
KeyCode::KEY_SLEEP,
|
|
KeyCode::KEY_WAKEUP,
|
|
KeyCode::KEY_FILE,
|
|
KeyCode::KEY_SENDFILE,
|
|
KeyCode::KEY_DELETEFILE,
|
|
KeyCode::KEY_XFER,
|
|
KeyCode::KEY_PROG1,
|
|
KeyCode::KEY_PROG2,
|
|
KeyCode::KEY_WWW,
|
|
KeyCode::KEY_MSDOS,
|
|
KeyCode::KEY_COFFEE,
|
|
KeyCode::KEY_DIRECTION,
|
|
KeyCode::KEY_ROTATE_DISPLAY,
|
|
KeyCode::KEY_CYCLEWINDOWS,
|
|
KeyCode::KEY_MAIL,
|
|
KeyCode::KEY_BOOKMARKS,
|
|
KeyCode::KEY_COMPUTER,
|
|
KeyCode::KEY_BACK,
|
|
KeyCode::KEY_FORWARD,
|
|
KeyCode::KEY_CLOSECD,
|
|
KeyCode::KEY_EJECTCD,
|
|
KeyCode::KEY_EJECTCLOSECD,
|
|
KeyCode::KEY_NEXTSONG,
|
|
KeyCode::KEY_PLAYPAUSE,
|
|
KeyCode::KEY_PREVIOUSSONG,
|
|
KeyCode::KEY_STOPCD,
|
|
KeyCode::KEY_RECORD,
|
|
KeyCode::KEY_REWIND,
|
|
KeyCode::KEY_PHONE,
|
|
KeyCode::KEY_ISO,
|
|
KeyCode::KEY_CONFIG,
|
|
KeyCode::KEY_HOMEPAGE,
|
|
KeyCode::KEY_REFRESH,
|
|
KeyCode::KEY_EXIT,
|
|
KeyCode::KEY_MOVE,
|
|
KeyCode::KEY_EDIT,
|
|
KeyCode::KEY_SCROLLUP,
|
|
KeyCode::KEY_SCROLLDOWN,
|
|
KeyCode::KEY_KPLEFTPAREN,
|
|
KeyCode::KEY_KPRIGHTPAREN,
|
|
KeyCode::KEY_NEW,
|
|
KeyCode::KEY_REDO,
|
|
KeyCode::KEY_F13,
|
|
KeyCode::KEY_F14,
|
|
KeyCode::KEY_F15,
|
|
KeyCode::KEY_F16,
|
|
KeyCode::KEY_F17,
|
|
KeyCode::KEY_F18,
|
|
KeyCode::KEY_F19,
|
|
KeyCode::KEY_F20,
|
|
KeyCode::KEY_F21,
|
|
KeyCode::KEY_F22,
|
|
KeyCode::KEY_F23,
|
|
KeyCode::KEY_F24,
|
|
KeyCode::KEY_PLAYCD,
|
|
KeyCode::KEY_PAUSECD,
|
|
KeyCode::KEY_PROG3,
|
|
KeyCode::KEY_PROG4,
|
|
KeyCode::KEY_DASHBOARD,
|
|
KeyCode::KEY_SUSPEND,
|
|
KeyCode::KEY_CLOSE,
|
|
KeyCode::KEY_PLAY,
|
|
KeyCode::KEY_FASTFORWARD,
|
|
KeyCode::KEY_BASSBOOST,
|
|
KeyCode::KEY_PRINT,
|
|
KeyCode::KEY_HP,
|
|
KeyCode::KEY_CAMERA,
|
|
KeyCode::KEY_SOUND,
|
|
KeyCode::KEY_QUESTION,
|
|
KeyCode::KEY_EMAIL,
|
|
KeyCode::KEY_CHAT,
|
|
KeyCode::KEY_SEARCH,
|
|
KeyCode::KEY_CONNECT,
|
|
KeyCode::KEY_FINANCE,
|
|
KeyCode::KEY_SPORT,
|
|
KeyCode::KEY_SHOP,
|
|
KeyCode::KEY_ALTERASE,
|
|
KeyCode::KEY_CANCEL,
|
|
KeyCode::KEY_BRIGHTNESSDOWN,
|
|
KeyCode::KEY_BRIGHTNESSUP,
|
|
KeyCode::KEY_MEDIA,
|
|
KeyCode::KEY_SWITCHVIDEOMODE,
|
|
KeyCode::KEY_KBDILLUMTOGGLE,
|
|
KeyCode::KEY_KBDILLUMDOWN,
|
|
KeyCode::KEY_KBDILLUMUP,
|
|
KeyCode::KEY_SEND,
|
|
KeyCode::KEY_REPLY,
|
|
KeyCode::KEY_FORWARDMAIL,
|
|
KeyCode::KEY_SAVE,
|
|
KeyCode::KEY_DOCUMENTS,
|
|
KeyCode::KEY_BATTERY,
|
|
KeyCode::KEY_BLUETOOTH,
|
|
KeyCode::KEY_WLAN,
|
|
KeyCode::KEY_UWB,
|
|
KeyCode::KEY_UNKNOWN,
|
|
KeyCode::KEY_VIDEO_NEXT,
|
|
KeyCode::KEY_VIDEO_PREV,
|
|
KeyCode::KEY_BRIGHTNESS_CYCLE,
|
|
KeyCode::KEY_BRIGHTNESS_AUTO,
|
|
KeyCode::KEY_DISPLAY_OFF,
|
|
KeyCode::KEY_WWAN,
|
|
KeyCode::KEY_RFKILL,
|
|
KeyCode::KEY_MICMUTE,
|
|
KeyCode::BTN_0,
|
|
KeyCode::BTN_1,
|
|
KeyCode::BTN_2,
|
|
KeyCode::BTN_3,
|
|
KeyCode::BTN_4,
|
|
KeyCode::BTN_5,
|
|
KeyCode::BTN_6,
|
|
KeyCode::BTN_7,
|
|
KeyCode::BTN_8,
|
|
KeyCode::BTN_9,
|
|
KeyCode::BTN_LEFT,
|
|
KeyCode::BTN_RIGHT,
|
|
KeyCode::BTN_MIDDLE,
|
|
KeyCode::BTN_SIDE,
|
|
KeyCode::BTN_EXTRA,
|
|
KeyCode::BTN_FORWARD,
|
|
KeyCode::BTN_BACK,
|
|
KeyCode::BTN_TASK,
|
|
KeyCode::BTN_TRIGGER,
|
|
KeyCode::BTN_THUMB,
|
|
KeyCode::BTN_THUMB2,
|
|
KeyCode::BTN_TOP,
|
|
KeyCode::BTN_TOP2,
|
|
KeyCode::BTN_PINKIE,
|
|
KeyCode::BTN_BASE,
|
|
KeyCode::BTN_BASE2,
|
|
KeyCode::BTN_BASE3,
|
|
KeyCode::BTN_BASE4,
|
|
KeyCode::BTN_BASE5,
|
|
KeyCode::BTN_BASE6,
|
|
KeyCode::BTN_DEAD,
|
|
KeyCode::BTN_SOUTH,
|
|
KeyCode::BTN_EAST,
|
|
KeyCode::BTN_C,
|
|
KeyCode::BTN_NORTH,
|
|
KeyCode::BTN_WEST,
|
|
KeyCode::BTN_Z,
|
|
KeyCode::BTN_TL,
|
|
KeyCode::BTN_TR,
|
|
KeyCode::BTN_TL2,
|
|
KeyCode::BTN_TR2,
|
|
KeyCode::BTN_SELECT,
|
|
KeyCode::BTN_START,
|
|
KeyCode::BTN_MODE,
|
|
KeyCode::BTN_THUMBL,
|
|
KeyCode::BTN_THUMBR,
|
|
KeyCode::BTN_TOOL_PEN,
|
|
KeyCode::BTN_TOOL_RUBBER,
|
|
KeyCode::BTN_TOOL_BRUSH,
|
|
KeyCode::BTN_TOOL_PENCIL,
|
|
KeyCode::BTN_TOOL_AIRBRUSH,
|
|
KeyCode::BTN_TOOL_FINGER,
|
|
KeyCode::BTN_TOOL_MOUSE,
|
|
KeyCode::BTN_TOOL_LENS,
|
|
KeyCode::BTN_TOOL_QUINTTAP,
|
|
KeyCode::BTN_TOUCH,
|
|
KeyCode::BTN_STYLUS,
|
|
KeyCode::BTN_STYLUS2,
|
|
KeyCode::BTN_TOOL_DOUBLETAP,
|
|
KeyCode::BTN_TOOL_TRIPLETAP,
|
|
KeyCode::BTN_TOOL_QUADTAP,
|
|
KeyCode::BTN_GEAR_DOWN,
|
|
KeyCode::BTN_GEAR_UP,
|
|
KeyCode::KEY_OK,
|
|
KeyCode::KEY_SELECT,
|
|
KeyCode::KEY_GOTO,
|
|
KeyCode::KEY_CLEAR,
|
|
KeyCode::KEY_POWER2,
|
|
KeyCode::KEY_OPTION,
|
|
KeyCode::KEY_INFO,
|
|
KeyCode::KEY_TIME,
|
|
KeyCode::KEY_VENDOR,
|
|
KeyCode::KEY_ARCHIVE,
|
|
KeyCode::KEY_PROGRAM,
|
|
KeyCode::KEY_CHANNEL,
|
|
KeyCode::KEY_FAVORITES,
|
|
KeyCode::KEY_EPG,
|
|
KeyCode::KEY_PVR,
|
|
KeyCode::KEY_MHP,
|
|
KeyCode::KEY_LANGUAGE,
|
|
KeyCode::KEY_TITLE,
|
|
KeyCode::KEY_SUBTITLE,
|
|
KeyCode::KEY_ANGLE,
|
|
KeyCode::KEY_ZOOM,
|
|
KeyCode::KEY_FULL_SCREEN,
|
|
KeyCode::KEY_MODE,
|
|
KeyCode::KEY_KEYBOARD,
|
|
KeyCode::KEY_SCREEN,
|
|
KeyCode::KEY_PC,
|
|
KeyCode::KEY_TV,
|
|
KeyCode::KEY_TV2,
|
|
KeyCode::KEY_VCR,
|
|
KeyCode::KEY_VCR2,
|
|
KeyCode::KEY_SAT,
|
|
KeyCode::KEY_SAT2,
|
|
KeyCode::KEY_CD,
|
|
KeyCode::KEY_TAPE,
|
|
KeyCode::KEY_RADIO,
|
|
KeyCode::KEY_TUNER,
|
|
KeyCode::KEY_PLAYER,
|
|
KeyCode::KEY_TEXT,
|
|
KeyCode::KEY_DVD,
|
|
KeyCode::KEY_AUX,
|
|
KeyCode::KEY_MP3,
|
|
KeyCode::KEY_AUDIO,
|
|
KeyCode::KEY_VIDEO,
|
|
KeyCode::KEY_DIRECTORY,
|
|
KeyCode::KEY_LIST,
|
|
KeyCode::KEY_MEMO,
|
|
KeyCode::KEY_CALENDAR,
|
|
KeyCode::KEY_RED,
|
|
KeyCode::KEY_GREEN,
|
|
KeyCode::KEY_YELLOW,
|
|
KeyCode::KEY_BLUE,
|
|
KeyCode::KEY_CHANNELUP,
|
|
KeyCode::KEY_CHANNELDOWN,
|
|
KeyCode::KEY_FIRST,
|
|
KeyCode::KEY_LAST,
|
|
KeyCode::KEY_AB,
|
|
KeyCode::KEY_NEXT,
|
|
KeyCode::KEY_RESTART,
|
|
KeyCode::KEY_SLOW,
|
|
KeyCode::KEY_SHUFFLE,
|
|
KeyCode::KEY_BREAK,
|
|
KeyCode::KEY_PREVIOUS,
|
|
KeyCode::KEY_DIGITS,
|
|
KeyCode::KEY_TEEN,
|
|
KeyCode::KEY_TWEN,
|
|
KeyCode::KEY_VIDEOPHONE,
|
|
KeyCode::KEY_GAMES,
|
|
KeyCode::KEY_ZOOMIN,
|
|
KeyCode::KEY_ZOOMOUT,
|
|
KeyCode::KEY_ZOOMRESET,
|
|
KeyCode::KEY_WORDPROCESSOR,
|
|
KeyCode::KEY_EDITOR,
|
|
KeyCode::KEY_SPREADSHEET,
|
|
KeyCode::KEY_GRAPHICSEDITOR,
|
|
KeyCode::KEY_PRESENTATION,
|
|
KeyCode::KEY_DATABASE,
|
|
KeyCode::KEY_NEWS,
|
|
KeyCode::KEY_VOICEMAIL,
|
|
KeyCode::KEY_ADDRESSBOOK,
|
|
KeyCode::KEY_MESSENGER,
|
|
KeyCode::KEY_DISPLAYTOGGLE,
|
|
KeyCode::KEY_SPELLCHECK,
|
|
KeyCode::KEY_LOGOFF,
|
|
KeyCode::KEY_DOLLAR,
|
|
KeyCode::KEY_EURO,
|
|
KeyCode::KEY_FRAMEBACK,
|
|
KeyCode::KEY_FRAMEFORWARD,
|
|
KeyCode::KEY_CONTEXT_MENU,
|
|
KeyCode::KEY_MEDIA_REPEAT,
|
|
KeyCode::KEY_10CHANNELSUP,
|
|
KeyCode::KEY_10CHANNELSDOWN,
|
|
KeyCode::KEY_IMAGES,
|
|
KeyCode::KEY_DEL_EOL,
|
|
KeyCode::KEY_DEL_EOS,
|
|
KeyCode::KEY_INS_LINE,
|
|
KeyCode::KEY_DEL_LINE,
|
|
KeyCode::KEY_FN,
|
|
KeyCode::KEY_FN_ESC,
|
|
KeyCode::KEY_FN_F1,
|
|
KeyCode::KEY_FN_F2,
|
|
KeyCode::KEY_FN_F3,
|
|
KeyCode::KEY_FN_F4,
|
|
KeyCode::KEY_FN_F5,
|
|
KeyCode::KEY_FN_F6,
|
|
KeyCode::KEY_FN_F7,
|
|
KeyCode::KEY_FN_F8,
|
|
KeyCode::KEY_FN_F9,
|
|
KeyCode::KEY_FN_F10,
|
|
KeyCode::KEY_FN_F11,
|
|
KeyCode::KEY_FN_F12,
|
|
KeyCode::KEY_FN_1,
|
|
KeyCode::KEY_FN_2,
|
|
KeyCode::KEY_FN_D,
|
|
KeyCode::KEY_FN_E,
|
|
KeyCode::KEY_FN_F,
|
|
KeyCode::KEY_FN_S,
|
|
KeyCode::KEY_FN_B,
|
|
KeyCode::KEY_BRL_DOT1,
|
|
KeyCode::KEY_BRL_DOT2,
|
|
KeyCode::KEY_BRL_DOT3,
|
|
KeyCode::KEY_BRL_DOT4,
|
|
KeyCode::KEY_BRL_DOT5,
|
|
KeyCode::KEY_BRL_DOT6,
|
|
KeyCode::KEY_BRL_DOT7,
|
|
KeyCode::KEY_BRL_DOT8,
|
|
KeyCode::KEY_BRL_DOT9,
|
|
KeyCode::KEY_BRL_DOT10,
|
|
KeyCode::KEY_NUMERIC_0,
|
|
KeyCode::KEY_NUMERIC_1,
|
|
KeyCode::KEY_NUMERIC_2,
|
|
KeyCode::KEY_NUMERIC_3,
|
|
KeyCode::KEY_NUMERIC_4,
|
|
KeyCode::KEY_NUMERIC_5,
|
|
KeyCode::KEY_NUMERIC_6,
|
|
KeyCode::KEY_NUMERIC_7,
|
|
KeyCode::KEY_NUMERIC_8,
|
|
KeyCode::KEY_NUMERIC_9,
|
|
KeyCode::KEY_NUMERIC_STAR,
|
|
KeyCode::KEY_NUMERIC_POUND,
|
|
KeyCode::KEY_NUMERIC_A,
|
|
KeyCode::KEY_NUMERIC_B,
|
|
KeyCode::KEY_NUMERIC_C,
|
|
KeyCode::KEY_NUMERIC_D,
|
|
KeyCode::KEY_CAMERA_FOCUS,
|
|
KeyCode::KEY_WPS_BUTTON,
|
|
KeyCode::KEY_TOUCHPAD_TOGGLE,
|
|
KeyCode::KEY_TOUCHPAD_ON,
|
|
KeyCode::KEY_TOUCHPAD_OFF,
|
|
KeyCode::KEY_CAMERA_ZOOMIN,
|
|
KeyCode::KEY_CAMERA_ZOOMOUT,
|
|
KeyCode::KEY_CAMERA_UP,
|
|
KeyCode::KEY_CAMERA_DOWN,
|
|
KeyCode::KEY_CAMERA_LEFT,
|
|
KeyCode::KEY_CAMERA_RIGHT,
|
|
KeyCode::KEY_ATTENDANT_ON,
|
|
KeyCode::KEY_ATTENDANT_OFF,
|
|
KeyCode::KEY_ATTENDANT_TOGGLE,
|
|
KeyCode::KEY_LIGHTS_TOGGLE,
|
|
KeyCode::BTN_DPAD_UP,
|
|
KeyCode::BTN_DPAD_DOWN,
|
|
KeyCode::BTN_DPAD_LEFT,
|
|
KeyCode::BTN_DPAD_RIGHT,
|
|
KeyCode::KEY_ALS_TOGGLE,
|
|
KeyCode::KEY_BUTTONCONFIG,
|
|
KeyCode::KEY_TASKMANAGER,
|
|
KeyCode::KEY_JOURNAL,
|
|
KeyCode::KEY_CONTROLPANEL,
|
|
KeyCode::KEY_APPSELECT,
|
|
KeyCode::KEY_SCREENSAVER,
|
|
KeyCode::KEY_VOICECOMMAND,
|
|
KeyCode::KEY_ASSISTANT,
|
|
KeyCode::KEY_KBD_LAYOUT_NEXT,
|
|
KeyCode::KEY_BRIGHTNESS_MIN,
|
|
KeyCode::KEY_BRIGHTNESS_MAX,
|
|
KeyCode::KEY_KBDINPUTASSIST_PREV,
|
|
KeyCode::KEY_KBDINPUTASSIST_NEXT,
|
|
KeyCode::KEY_KBDINPUTASSIST_PREVGROUP,
|
|
KeyCode::KEY_KBDINPUTASSIST_NEXTGROUP,
|
|
KeyCode::KEY_KBDINPUTASSIST_ACCEPT,
|
|
KeyCode::KEY_KBDINPUTASSIST_CANCEL,
|
|
KeyCode::KEY_RIGHT_UP,
|
|
KeyCode::KEY_RIGHT_DOWN,
|
|
KeyCode::KEY_LEFT_UP,
|
|
KeyCode::KEY_LEFT_DOWN,
|
|
KeyCode::KEY_ROOT_MENU,
|
|
KeyCode::KEY_MEDIA_TOP_MENU,
|
|
KeyCode::KEY_NUMERIC_11,
|
|
KeyCode::KEY_NUMERIC_12,
|
|
KeyCode::KEY_AUDIO_DESC,
|
|
KeyCode::KEY_3D_MODE,
|
|
KeyCode::KEY_NEXT_FAVORITE,
|
|
KeyCode::KEY_STOP_RECORD,
|
|
KeyCode::KEY_PAUSE_RECORD,
|
|
KeyCode::KEY_VOD,
|
|
KeyCode::KEY_UNMUTE,
|
|
KeyCode::KEY_FASTREVERSE,
|
|
KeyCode::KEY_SLOWREVERSE,
|
|
KeyCode::KEY_DATA,
|
|
KeyCode::KEY_ONSCREEN_KEYBOARD,
|
|
KeyCode::KEY_PRIVACY_SCREEN_TOGGLE,
|
|
KeyCode::KEY_SELECTIVE_SCREENSHOT,
|
|
KeyCode::BTN_TRIGGER_HAPPY1,
|
|
KeyCode::BTN_TRIGGER_HAPPY2,
|
|
KeyCode::BTN_TRIGGER_HAPPY3,
|
|
KeyCode::BTN_TRIGGER_HAPPY4,
|
|
KeyCode::BTN_TRIGGER_HAPPY5,
|
|
KeyCode::BTN_TRIGGER_HAPPY6,
|
|
KeyCode::BTN_TRIGGER_HAPPY7,
|
|
KeyCode::BTN_TRIGGER_HAPPY8,
|
|
KeyCode::BTN_TRIGGER_HAPPY9,
|
|
KeyCode::BTN_TRIGGER_HAPPY10,
|
|
KeyCode::BTN_TRIGGER_HAPPY11,
|
|
KeyCode::BTN_TRIGGER_HAPPY12,
|
|
KeyCode::BTN_TRIGGER_HAPPY13,
|
|
KeyCode::BTN_TRIGGER_HAPPY14,
|
|
KeyCode::BTN_TRIGGER_HAPPY15,
|
|
KeyCode::BTN_TRIGGER_HAPPY16,
|
|
KeyCode::BTN_TRIGGER_HAPPY17,
|
|
KeyCode::BTN_TRIGGER_HAPPY18,
|
|
KeyCode::BTN_TRIGGER_HAPPY19,
|
|
KeyCode::BTN_TRIGGER_HAPPY20,
|
|
KeyCode::BTN_TRIGGER_HAPPY21,
|
|
KeyCode::BTN_TRIGGER_HAPPY22,
|
|
KeyCode::BTN_TRIGGER_HAPPY23,
|
|
KeyCode::BTN_TRIGGER_HAPPY24,
|
|
KeyCode::BTN_TRIGGER_HAPPY25,
|
|
KeyCode::BTN_TRIGGER_HAPPY26,
|
|
KeyCode::BTN_TRIGGER_HAPPY27,
|
|
KeyCode::BTN_TRIGGER_HAPPY28,
|
|
KeyCode::BTN_TRIGGER_HAPPY29,
|
|
KeyCode::BTN_TRIGGER_HAPPY30,
|
|
KeyCode::BTN_TRIGGER_HAPPY31,
|
|
KeyCode::BTN_TRIGGER_HAPPY32,
|
|
KeyCode::BTN_TRIGGER_HAPPY33,
|
|
KeyCode::BTN_TRIGGER_HAPPY34,
|
|
KeyCode::BTN_TRIGGER_HAPPY35,
|
|
KeyCode::BTN_TRIGGER_HAPPY36,
|
|
KeyCode::BTN_TRIGGER_HAPPY37,
|
|
KeyCode::BTN_TRIGGER_HAPPY38,
|
|
KeyCode::BTN_TRIGGER_HAPPY39,
|
|
KeyCode::BTN_TRIGGER_HAPPY40,
|
|
];
|