Add evdev keyboard handler. Untested and unused for now
This commit is contained in:
parent
f3796756bc
commit
a35ee381d0
|
@ -0,0 +1,483 @@
|
|||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
|
||||
using static BizHawk.Common.EvDevImports;
|
||||
using static BizHawk.Common.FildesImports;
|
||||
|
||||
namespace BizHawk.Bizware.Input
|
||||
{
|
||||
internal static class EvDevKeyInput
|
||||
{
|
||||
private struct EvDevKeyboard
|
||||
{
|
||||
public uint DriverVersion;
|
||||
public ushort IdBus;
|
||||
public ushort IdVendor;
|
||||
public ushort IdProduct;
|
||||
public ushort IdVersion;
|
||||
public string Name;
|
||||
public int Fd;
|
||||
public string Path;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var verMajor = DriverVersion >> 16;
|
||||
var verMinor = DriverVersion >> 8 & 0xFF;
|
||||
var varRev = DriverVersion & 0xFF;
|
||||
return $"{Name} ({verMajor}.{verMinor}.{varRev} {IdBus:X4}/{IdVendor:X4}/{IdProduct:X4}/{IdVersion:X4})";
|
||||
}
|
||||
}
|
||||
|
||||
private static bool _isInit;
|
||||
private static FileSystemWatcher? _fileSystemWatcher;
|
||||
private static readonly Dictionary<string, EvDevKeyboard> _keyboards = new();
|
||||
|
||||
private static readonly object _lockObj = new();
|
||||
|
||||
private static List<int> DecodeBits(Span<byte> bits)
|
||||
{
|
||||
var result = new List<int>(bits.Length * 8);
|
||||
for (var i = 0; i < bits.Length; i++)
|
||||
{
|
||||
var b = bits[i];
|
||||
var bitPos = i * 8;
|
||||
for (var j = 0; j < 8; j++)
|
||||
{
|
||||
if (b.Bit(j))
|
||||
{
|
||||
result.Add(bitPos + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static unsafe void MaybeAddKeyboard(string path)
|
||||
{
|
||||
if (_keyboards.ContainsKey(path))
|
||||
{
|
||||
// already have this, ignore
|
||||
return;
|
||||
}
|
||||
|
||||
var fd = open(path, OpenFlags.O_RDONLY | OpenFlags.O_NONBLOCK | OpenFlags.O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var version = 0u;
|
||||
var id = stackalloc ushort[4];
|
||||
var str = stackalloc byte[256];
|
||||
new Span<ushort>(id, 4).Clear();
|
||||
new Span<byte>(str, 256).Clear();
|
||||
|
||||
// if any of these fail, the device was either removed or garbage
|
||||
if (ioctl(fd, new(EVIOCGVERSION), &version) == -1 ||
|
||||
ioctl(fd, new(EVIOCGID), id) == -1 ||
|
||||
ioctl(fd, new(EVIOCGNAME(256)), str) == -1)
|
||||
{
|
||||
_ = close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
str[255] = 0; // not trusting this remains nul terminated
|
||||
var name = Marshal.PtrToStringAnsi(new(str))!;
|
||||
|
||||
const int eventBitBufferSize = (int)EvDevEventType.EV_MAX / 8 + 1;
|
||||
var eventBits = stackalloc byte[eventBitBufferSize];
|
||||
new Span<byte>(eventBits, eventBitBufferSize).Clear();
|
||||
if (ioctl(fd, new(EVIOCGBIT(EvDevEventType.EV_SYN, (int)EvDevEventType.EV_MAX)), eventBits) == -1)
|
||||
{
|
||||
_ = close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
var supportedEvents = DecodeBits(new(eventBits, eventBitBufferSize));
|
||||
if (!supportedEvents.Contains((int)EvDevEventType.EV_KEY))
|
||||
{
|
||||
// we only care about keyboards
|
||||
_ = close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
const int keyBitBufferSize = (int)EvDevKeyCode.KEY_MAX / 8 + 1;
|
||||
var keyBits = stackalloc byte[keyBitBufferSize];
|
||||
new Span<byte>(keyBits, keyBitBufferSize).Clear();
|
||||
if (ioctl(fd, new(EVIOCGBIT(EvDevEventType.EV_KEY, (int)EvDevKeyCode.KEY_MAX)), keyBits) == -1)
|
||||
{
|
||||
_ = close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
var supportedKeys = DecodeBits(new(keyBits, keyBitBufferSize));
|
||||
if (supportedKeys.Count == 0)
|
||||
{
|
||||
// probably garbage
|
||||
return;
|
||||
}
|
||||
|
||||
if (name.IndexOf("keyboard", StringComparison.InvariantCultureIgnoreCase) == -1)
|
||||
{
|
||||
// probably not be a keyboard
|
||||
// TODO: do some better heuristics here (maybe check if supportedKeys has A-Z?)
|
||||
return;
|
||||
}
|
||||
|
||||
var keyboard = new EvDevKeyboard
|
||||
{
|
||||
DriverVersion = version,
|
||||
IdBus = id[0],
|
||||
IdProduct = id[1],
|
||||
IdVendor = id[2],
|
||||
IdVersion = id[3],
|
||||
Name = name,
|
||||
Fd = fd,
|
||||
Path = path,
|
||||
};
|
||||
|
||||
Console.WriteLine($"Added keyboard {keyboard}");
|
||||
_keyboards.Add(path, keyboard);
|
||||
}
|
||||
|
||||
private static void MaybeRemoveKeyboard(string path)
|
||||
{
|
||||
if (_keyboards.TryGetValue(path, out var keyboard))
|
||||
{
|
||||
_ = close(keyboard.Fd);
|
||||
Console.WriteLine($"Removed keyboard {keyboard}");
|
||||
_keyboards.Remove(path);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnWatcherEvent(object _, FileSystemEventArgs e)
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
if (!_isInit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
|
||||
switch (e.ChangeType)
|
||||
{
|
||||
case WatcherChangeTypes.Created:
|
||||
case WatcherChangeTypes.Changed:
|
||||
MaybeAddKeyboard(e.FullPath);
|
||||
break;
|
||||
case WatcherChangeTypes.Deleted:
|
||||
MaybeRemoveKeyboard(e.FullPath);
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine($"Unexpected watcher event {e.ChangeType}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if (OSTailoredCode.CurrentOS != OSTailoredCode.DistinctOS.Linux)
|
||||
{
|
||||
// also supported in BSDs, I think OSTailoredCode.CurrentOS is Linux for BSDs?
|
||||
throw new NotSupportedException("evdev is Linux only");
|
||||
}
|
||||
|
||||
lock (_lockObj)
|
||||
{
|
||||
Deinitialize();
|
||||
|
||||
_fileSystemWatcher = new("/dev/input/", "event*")
|
||||
{
|
||||
NotifyFilter = NotifyFilters.FileName | NotifyFilters.Attributes,
|
||||
};
|
||||
|
||||
_fileSystemWatcher.Created += OnWatcherEvent;
|
||||
_fileSystemWatcher.Changed += OnWatcherEvent;
|
||||
_fileSystemWatcher.Deleted += OnWatcherEvent;
|
||||
_fileSystemWatcher.EnableRaisingEvents = true;
|
||||
|
||||
var evFns = Directory.GetFiles("/dev/input/", "event*");
|
||||
foreach (var fn in evFns)
|
||||
{
|
||||
MaybeAddKeyboard(fn);
|
||||
}
|
||||
|
||||
_isInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Deinitialize()
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
_fileSystemWatcher?.Dispose();
|
||||
_fileSystemWatcher = null;
|
||||
|
||||
foreach (var keyboard in _keyboards.Values)
|
||||
{
|
||||
_ = close(keyboard.Fd);
|
||||
}
|
||||
|
||||
_keyboards.Clear();
|
||||
_isInit = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<KeyEvent> Update()
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
if (!_isInit)
|
||||
{
|
||||
return Enumerable.Empty<KeyEvent>();
|
||||
}
|
||||
|
||||
var kbEvent = default(EvDevKeyboardEvent);
|
||||
var kbEventSize = (IntPtr)Marshal.SizeOf<EvDevKeyboardEvent>();
|
||||
var kbsToClose = new List<string>();
|
||||
Span<byte> keyChanges = stackalloc byte[(int)EvDevKeyCode.KEY_CNT];
|
||||
keyChanges.Clear();
|
||||
|
||||
foreach (var keyboard in _keyboards.Values)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var res = read(keyboard.Fd, &kbEvent, kbEventSize);
|
||||
if (res == (IntPtr)(-1))
|
||||
{
|
||||
// this is actually errno, despite the Win32 name
|
||||
var errno = Marshal.GetLastWin32Error();
|
||||
|
||||
const int EAGAIN = 11;
|
||||
const int ENODEV = 19;
|
||||
|
||||
// EAGAIN means there's no more events left to read (generally expected)
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// ENODEV means the device is gone
|
||||
if (errno == ENODEV)
|
||||
{
|
||||
kbsToClose.Add(keyboard.Path);
|
||||
break;
|
||||
}
|
||||
|
||||
Debug.WriteLine($"Unexpected error reading keyboards: {errno}");
|
||||
break;
|
||||
}
|
||||
|
||||
if (res != kbEventSize)
|
||||
{
|
||||
Debug.WriteLine("Unexpected incomplete read");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (kbEvent.type != EvDevEventType.EV_KEY)
|
||||
{
|
||||
// don't care for non-EV_KEY events
|
||||
continue;
|
||||
}
|
||||
|
||||
if (kbEvent.code > EvDevKeyCode.KEY_MAX)
|
||||
{
|
||||
Debug.WriteLine($"Unexpected event code {kbEvent.code}");
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (kbEvent.value)
|
||||
{
|
||||
case EvDevKeyValue.KeyUp:
|
||||
keyChanges[(int)kbEvent.code] = 1;
|
||||
break;
|
||||
case EvDevKeyValue.KeyDown:
|
||||
case EvDevKeyValue.KeyRepeat:
|
||||
keyChanges[(int)kbEvent.code] = 2;
|
||||
break;
|
||||
default:
|
||||
Debug.WriteLine($"Unexpected event value {kbEvent.value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var path in kbsToClose)
|
||||
{
|
||||
MaybeRemoveKeyboard(path);
|
||||
}
|
||||
|
||||
var keyEvents = new List<KeyEvent>();
|
||||
for (var i = 0; i < (int)EvDevKeyCode.KEY_CNT; i++)
|
||||
{
|
||||
if (keyChanges[i] != 0 &&
|
||||
KeyEnumMap.TryGetValue((EvDevKeyCode)i, out var key))
|
||||
{
|
||||
keyEvents.Add(new(key, keyChanges[i] == 1));
|
||||
}
|
||||
}
|
||||
|
||||
return keyEvents;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<EvDevKeyCode, DistinctKey> KeyEnumMap = new()
|
||||
{
|
||||
[EvDevKeyCode.KEY_ESC] = DistinctKey.Escape,
|
||||
[EvDevKeyCode.KEY_1] = DistinctKey.D1,
|
||||
[EvDevKeyCode.KEY_2] = DistinctKey.D2,
|
||||
[EvDevKeyCode.KEY_3] = DistinctKey.D3,
|
||||
[EvDevKeyCode.KEY_4] = DistinctKey.D4,
|
||||
[EvDevKeyCode.KEY_5] = DistinctKey.D5,
|
||||
[EvDevKeyCode.KEY_6] = DistinctKey.D6,
|
||||
[EvDevKeyCode.KEY_7] = DistinctKey.D7,
|
||||
[EvDevKeyCode.KEY_8] = DistinctKey.D8,
|
||||
[EvDevKeyCode.KEY_9] = DistinctKey.D9,
|
||||
[EvDevKeyCode.KEY_0] = DistinctKey.D0,
|
||||
[EvDevKeyCode.KEY_MINUS] = DistinctKey.OemMinus,
|
||||
[EvDevKeyCode.KEY_EQUAL] = DistinctKey.OemPlus,
|
||||
[EvDevKeyCode.KEY_BACKSPACE] = DistinctKey.Back,
|
||||
[EvDevKeyCode.KEY_TAB] = DistinctKey.Tab,
|
||||
[EvDevKeyCode.KEY_Q] = DistinctKey.Q,
|
||||
[EvDevKeyCode.KEY_W] = DistinctKey.W,
|
||||
[EvDevKeyCode.KEY_E] = DistinctKey.E,
|
||||
[EvDevKeyCode.KEY_R] = DistinctKey.R,
|
||||
[EvDevKeyCode.KEY_T] = DistinctKey.T,
|
||||
[EvDevKeyCode.KEY_Y] = DistinctKey.Y,
|
||||
[EvDevKeyCode.KEY_U] = DistinctKey.U,
|
||||
[EvDevKeyCode.KEY_I] = DistinctKey.I,
|
||||
[EvDevKeyCode.KEY_O] = DistinctKey.O,
|
||||
[EvDevKeyCode.KEY_P] = DistinctKey.P,
|
||||
[EvDevKeyCode.KEY_LEFTBRACE] = DistinctKey.OemOpenBrackets,
|
||||
[EvDevKeyCode.KEY_RIGHTBRACE] = DistinctKey.OemCloseBrackets,
|
||||
[EvDevKeyCode.KEY_ENTER] = DistinctKey.Enter,
|
||||
[EvDevKeyCode.KEY_LEFTCTRL] = DistinctKey.LeftCtrl,
|
||||
[EvDevKeyCode.KEY_A] = DistinctKey.A,
|
||||
[EvDevKeyCode.KEY_S] = DistinctKey.S,
|
||||
[EvDevKeyCode.KEY_D] = DistinctKey.D,
|
||||
[EvDevKeyCode.KEY_F] = DistinctKey.F,
|
||||
[EvDevKeyCode.KEY_G] = DistinctKey.G,
|
||||
[EvDevKeyCode.KEY_H] = DistinctKey.H,
|
||||
[EvDevKeyCode.KEY_J] = DistinctKey.J,
|
||||
[EvDevKeyCode.KEY_K] = DistinctKey.K,
|
||||
[EvDevKeyCode.KEY_L] = DistinctKey.L,
|
||||
[EvDevKeyCode.KEY_SEMICOLON] = DistinctKey.OemSemicolon,
|
||||
[EvDevKeyCode.KEY_APOSTROPHE] = DistinctKey.OemQuotes,
|
||||
[EvDevKeyCode.KEY_GRAVE] = DistinctKey.OemTilde,
|
||||
[EvDevKeyCode.KEY_LEFTSHIFT] = DistinctKey.LeftShift,
|
||||
[EvDevKeyCode.KEY_BACKSLASH] = DistinctKey.OemBackslash,
|
||||
[EvDevKeyCode.KEY_Z] = DistinctKey.Z,
|
||||
[EvDevKeyCode.KEY_X] = DistinctKey.X,
|
||||
[EvDevKeyCode.KEY_C] = DistinctKey.C,
|
||||
[EvDevKeyCode.KEY_V] = DistinctKey.V,
|
||||
[EvDevKeyCode.KEY_B] = DistinctKey.B,
|
||||
[EvDevKeyCode.KEY_N] = DistinctKey.N,
|
||||
[EvDevKeyCode.KEY_M] = DistinctKey.M,
|
||||
[EvDevKeyCode.KEY_COMMA] = DistinctKey.OemComma,
|
||||
[EvDevKeyCode.KEY_DOT] = DistinctKey.OemPeriod,
|
||||
[EvDevKeyCode.KEY_SLASH] = DistinctKey.OemQuestion,
|
||||
[EvDevKeyCode.KEY_RIGHTSHIFT] = DistinctKey.RightShift,
|
||||
[EvDevKeyCode.KEY_KPASTERISK] = DistinctKey.Multiply,
|
||||
[EvDevKeyCode.KEY_LEFTALT] = DistinctKey.LeftAlt,
|
||||
[EvDevKeyCode.KEY_SPACE] = DistinctKey.Space,
|
||||
[EvDevKeyCode.KEY_CAPSLOCK] = DistinctKey.CapsLock,
|
||||
[EvDevKeyCode.KEY_F1] = DistinctKey.F1,
|
||||
[EvDevKeyCode.KEY_F2] = DistinctKey.F2,
|
||||
[EvDevKeyCode.KEY_F3] = DistinctKey.F3,
|
||||
[EvDevKeyCode.KEY_F4] = DistinctKey.F4,
|
||||
[EvDevKeyCode.KEY_F5] = DistinctKey.F5,
|
||||
[EvDevKeyCode.KEY_F6] = DistinctKey.F6,
|
||||
[EvDevKeyCode.KEY_F7] = DistinctKey.F7,
|
||||
[EvDevKeyCode.KEY_F8] = DistinctKey.F8,
|
||||
[EvDevKeyCode.KEY_F9] = DistinctKey.F9,
|
||||
[EvDevKeyCode.KEY_F10] = DistinctKey.F10,
|
||||
[EvDevKeyCode.KEY_NUMLOCK] = DistinctKey.NumLock,
|
||||
[EvDevKeyCode.KEY_SCROLLLOCK] = DistinctKey.Scroll,
|
||||
[EvDevKeyCode.KEY_KP7] = DistinctKey.NumPad7,
|
||||
[EvDevKeyCode.KEY_KP8] = DistinctKey.NumPad8,
|
||||
[EvDevKeyCode.KEY_KP9] = DistinctKey.NumPad9,
|
||||
[EvDevKeyCode.KEY_KPMINUS] = DistinctKey.Subtract,
|
||||
[EvDevKeyCode.KEY_KP4] = DistinctKey.NumPad4,
|
||||
[EvDevKeyCode.KEY_KP5] = DistinctKey.NumPad5,
|
||||
[EvDevKeyCode.KEY_KP6] = DistinctKey.NumPad6,
|
||||
[EvDevKeyCode.KEY_KPPLUS] = DistinctKey.Add,
|
||||
[EvDevKeyCode.KEY_KP1] = DistinctKey.NumPad1,
|
||||
[EvDevKeyCode.KEY_KP2] = DistinctKey.NumPad2,
|
||||
[EvDevKeyCode.KEY_KP3] = DistinctKey.NumPad3,
|
||||
[EvDevKeyCode.KEY_KPDOT] = DistinctKey.Decimal,
|
||||
[EvDevKeyCode.KEY_102ND] = DistinctKey.Oem102,
|
||||
[EvDevKeyCode.KEY_F11] = DistinctKey.F11,
|
||||
[EvDevKeyCode.KEY_F12] = DistinctKey.F12,
|
||||
[EvDevKeyCode.KEY_KPENTER] = DistinctKey.NumPadEnter,
|
||||
[EvDevKeyCode.KEY_RIGHTCTRL] = DistinctKey.RightCtrl,
|
||||
[EvDevKeyCode.KEY_KPSLASH] = DistinctKey.Divide,
|
||||
[EvDevKeyCode.KEY_RIGHTALT] = DistinctKey.RightAlt,
|
||||
[EvDevKeyCode.KEY_LINEFEED] = DistinctKey.LineFeed,
|
||||
[EvDevKeyCode.KEY_HOME] = DistinctKey.Home,
|
||||
[EvDevKeyCode.KEY_UP] = DistinctKey.Up,
|
||||
[EvDevKeyCode.KEY_PAGEUP] = DistinctKey.PageUp,
|
||||
[EvDevKeyCode.KEY_LEFT] = DistinctKey.Left,
|
||||
[EvDevKeyCode.KEY_RIGHT] = DistinctKey.Right,
|
||||
[EvDevKeyCode.KEY_END] = DistinctKey.End,
|
||||
[EvDevKeyCode.KEY_DOWN] = DistinctKey.Down,
|
||||
[EvDevKeyCode.KEY_PAGEDOWN] = DistinctKey.PageDown,
|
||||
[EvDevKeyCode.KEY_INSERT] = DistinctKey.Insert,
|
||||
[EvDevKeyCode.KEY_DELETE] = DistinctKey.Delete,
|
||||
[EvDevKeyCode.KEY_MUTE] = DistinctKey.VolumeMute,
|
||||
[EvDevKeyCode.KEY_VOLUMEDOWN] = DistinctKey.VolumeDown,
|
||||
[EvDevKeyCode.KEY_VOLUMEUP] = DistinctKey.VolumeUp,
|
||||
[EvDevKeyCode.KEY_LEFTMETA] = DistinctKey.LWin,
|
||||
[EvDevKeyCode.KEY_RIGHTMETA] = DistinctKey.RWin,
|
||||
[EvDevKeyCode.KEY_STOP] = DistinctKey.BrowserStop,
|
||||
[EvDevKeyCode.KEY_HELP] = DistinctKey.Help,
|
||||
[EvDevKeyCode.KEY_SLEEP] = DistinctKey.Sleep,
|
||||
[EvDevKeyCode.KEY_PROG1] = DistinctKey.LaunchApplication1,
|
||||
[EvDevKeyCode.KEY_PROG2] = DistinctKey.LaunchApplication2,
|
||||
[EvDevKeyCode.KEY_MAIL] = DistinctKey.LaunchMail,
|
||||
[EvDevKeyCode.KEY_BACK] = DistinctKey.BrowserBack,
|
||||
[EvDevKeyCode.KEY_FORWARD] = DistinctKey.BrowserForward,
|
||||
[EvDevKeyCode.KEY_NEXTSONG] = DistinctKey.MediaNextTrack,
|
||||
[EvDevKeyCode.KEY_PLAYPAUSE] = DistinctKey.MediaPlayPause,
|
||||
[EvDevKeyCode.KEY_PREVIOUSSONG] = DistinctKey.MediaPreviousTrack,
|
||||
[EvDevKeyCode.KEY_STOPCD] = DistinctKey.MediaStop,
|
||||
[EvDevKeyCode.KEY_HOMEPAGE] = DistinctKey.BrowserHome,
|
||||
[EvDevKeyCode.KEY_REFRESH] = DistinctKey.BrowserRefresh,
|
||||
[EvDevKeyCode.KEY_F13] = DistinctKey.F13,
|
||||
[EvDevKeyCode.KEY_F14] = DistinctKey.F14,
|
||||
[EvDevKeyCode.KEY_F15] = DistinctKey.F15,
|
||||
[EvDevKeyCode.KEY_F16] = DistinctKey.F16,
|
||||
[EvDevKeyCode.KEY_F17] = DistinctKey.F17,
|
||||
[EvDevKeyCode.KEY_F18] = DistinctKey.F18,
|
||||
[EvDevKeyCode.KEY_F19] = DistinctKey.F19,
|
||||
[EvDevKeyCode.KEY_F20] = DistinctKey.F20,
|
||||
[EvDevKeyCode.KEY_F21] = DistinctKey.F21,
|
||||
[EvDevKeyCode.KEY_F22] = DistinctKey.F22,
|
||||
[EvDevKeyCode.KEY_F23] = DistinctKey.F23,
|
||||
[EvDevKeyCode.KEY_F24] = DistinctKey.F24,
|
||||
[EvDevKeyCode.KEY_PLAY] = DistinctKey.Play,
|
||||
[EvDevKeyCode.KEY_PRINT] = DistinctKey.Print,
|
||||
[EvDevKeyCode.KEY_SEARCH] = DistinctKey.BrowserSearch,
|
||||
[EvDevKeyCode.KEY_CANCEL] = DistinctKey.Cancel,
|
||||
[EvDevKeyCode.KEY_MEDIA] = DistinctKey.SelectMedia,
|
||||
[EvDevKeyCode.KEY_SELECT] = DistinctKey.Select,
|
||||
[EvDevKeyCode.KEY_FAVORITES] = DistinctKey.BrowserFavorites,
|
||||
[EvDevKeyCode.KEY_CLEAR] = DistinctKey.Clear,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,639 @@
|
|||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// a lot of this is take from https://github.com/afshin-parsa/evdev-sharp
|
||||
|
||||
namespace BizHawk.Common
|
||||
{
|
||||
public static class EvDevImports
|
||||
{
|
||||
public enum EvDevEventType : ushort
|
||||
{
|
||||
EV_SYN = 0x00,
|
||||
EV_KEY = 0x01,
|
||||
EV_REL = 0x02,
|
||||
EV_ABS = 0x03,
|
||||
EV_MSC = 0x04,
|
||||
EV_SW = 0x05,
|
||||
EV_LED = 0x11,
|
||||
EV_SND = 0x12,
|
||||
EV_REP = 0x14,
|
||||
EV_FF = 0x15,
|
||||
EV_PWR = 0x16,
|
||||
EV_FF_STATUS = 0x17,
|
||||
EV_MAX = 0x1f,
|
||||
EV_CNT = EV_MAX + 1,
|
||||
}
|
||||
|
||||
public enum EvDevKeyCode : ushort
|
||||
{
|
||||
KEY_RESERVED = 0,
|
||||
KEY_ESC = 1,
|
||||
KEY_1 = 2,
|
||||
KEY_2 = 3,
|
||||
KEY_3 = 4,
|
||||
KEY_4 = 5,
|
||||
KEY_5 = 6,
|
||||
KEY_6 = 7,
|
||||
KEY_7 = 8,
|
||||
KEY_8 = 9,
|
||||
KEY_9 = 10,
|
||||
KEY_0 = 11,
|
||||
KEY_MINUS = 12,
|
||||
KEY_EQUAL = 13,
|
||||
KEY_BACKSPACE = 14,
|
||||
KEY_TAB = 15,
|
||||
KEY_Q = 16,
|
||||
KEY_W = 17,
|
||||
KEY_E = 18,
|
||||
KEY_R = 19,
|
||||
KEY_T = 20,
|
||||
KEY_Y = 21,
|
||||
KEY_U = 22,
|
||||
KEY_I = 23,
|
||||
KEY_O = 24,
|
||||
KEY_P = 25,
|
||||
KEY_LEFTBRACE = 26,
|
||||
KEY_RIGHTBRACE = 27,
|
||||
KEY_ENTER = 28,
|
||||
KEY_LEFTCTRL = 29,
|
||||
KEY_A = 30,
|
||||
KEY_S = 31,
|
||||
KEY_D = 32,
|
||||
KEY_F = 33,
|
||||
KEY_G = 34,
|
||||
KEY_H = 35,
|
||||
KEY_J = 36,
|
||||
KEY_K = 37,
|
||||
KEY_L = 38,
|
||||
KEY_SEMICOLON = 39,
|
||||
KEY_APOSTROPHE = 40,
|
||||
KEY_GRAVE = 41,
|
||||
KEY_LEFTSHIFT = 42,
|
||||
KEY_BACKSLASH = 43,
|
||||
KEY_Z = 44,
|
||||
KEY_X = 45,
|
||||
KEY_C = 46,
|
||||
KEY_V = 47,
|
||||
KEY_B = 48,
|
||||
KEY_N = 49,
|
||||
KEY_M = 50,
|
||||
KEY_COMMA = 51,
|
||||
KEY_DOT = 52,
|
||||
KEY_SLASH = 53,
|
||||
KEY_RIGHTSHIFT = 54,
|
||||
KEY_KPASTERISK = 55,
|
||||
KEY_LEFTALT = 56,
|
||||
KEY_SPACE = 57,
|
||||
KEY_CAPSLOCK = 58,
|
||||
KEY_F1 = 59,
|
||||
KEY_F2 = 60,
|
||||
KEY_F3 = 61,
|
||||
KEY_F4 = 62,
|
||||
KEY_F5 = 63,
|
||||
KEY_F6 = 64,
|
||||
KEY_F7 = 65,
|
||||
KEY_F8 = 66,
|
||||
KEY_F9 = 67,
|
||||
KEY_F10 = 68,
|
||||
KEY_NUMLOCK = 69,
|
||||
KEY_SCROLLLOCK = 70,
|
||||
KEY_KP7 = 71,
|
||||
KEY_KP8 = 72,
|
||||
KEY_KP9 = 73,
|
||||
KEY_KPMINUS = 74,
|
||||
KEY_KP4 = 75,
|
||||
KEY_KP5 = 76,
|
||||
KEY_KP6 = 77,
|
||||
KEY_KPPLUS = 78,
|
||||
KEY_KP1 = 79,
|
||||
KEY_KP2 = 80,
|
||||
KEY_KP3 = 81,
|
||||
KEY_KP0 = 82,
|
||||
KEY_KPDOT = 83,
|
||||
KEY_ZENKAKUHANKAKU = 85,
|
||||
KEY_102ND = 86,
|
||||
KEY_F11 = 87,
|
||||
KEY_F12 = 88,
|
||||
KEY_RO = 89,
|
||||
KEY_KATAKANA = 90,
|
||||
KEY_HIRAGANA = 91,
|
||||
KEY_HENKAN = 92,
|
||||
KEY_KATAKANAHIRAGANA = 93,
|
||||
KEY_MUHENKAN = 94,
|
||||
KEY_KPJPCOMMA = 95,
|
||||
KEY_KPENTER = 96,
|
||||
KEY_RIGHTCTRL = 97,
|
||||
KEY_KPSLASH = 98,
|
||||
KEY_SYSRQ = 99,
|
||||
KEY_RIGHTALT = 100,
|
||||
KEY_LINEFEED = 101,
|
||||
KEY_HOME = 102,
|
||||
KEY_UP = 103,
|
||||
KEY_PAGEUP = 104,
|
||||
KEY_LEFT = 105,
|
||||
KEY_RIGHT = 106,
|
||||
KEY_END = 107,
|
||||
KEY_DOWN = 108,
|
||||
KEY_PAGEDOWN = 109,
|
||||
KEY_INSERT = 110,
|
||||
KEY_DELETE = 111,
|
||||
KEY_MACRO = 112,
|
||||
KEY_MUTE = 113,
|
||||
KEY_VOLUMEDOWN = 114,
|
||||
KEY_VOLUMEUP = 115,
|
||||
KEY_POWER = 116,
|
||||
KEY_KPEQUAL = 117,
|
||||
KEY_KPPLUSMINUS = 118,
|
||||
KEY_PAUSE = 119,
|
||||
KEY_SCALE = 120,
|
||||
KEY_KPCOMMA = 121,
|
||||
KEY_HANGEUL = 122,
|
||||
KEY_HANGUEL = KEY_HANGEUL,
|
||||
KEY_HANJA = 123,
|
||||
KEY_YEN = 124,
|
||||
KEY_LEFTMETA = 125,
|
||||
KEY_RIGHTMETA = 126,
|
||||
KEY_COMPOSE = 127,
|
||||
KEY_STOP = 128,
|
||||
KEY_AGAIN = 129,
|
||||
KEY_PROPS = 130,
|
||||
KEY_UNDO = 131,
|
||||
KEY_FRONT = 132,
|
||||
KEY_COPY = 133,
|
||||
KEY_OPEN = 134,
|
||||
KEY_PASTE = 135,
|
||||
KEY_FIND = 136,
|
||||
KEY_CUT = 137,
|
||||
KEY_HELP = 138,
|
||||
KEY_MENU = 139,
|
||||
KEY_CALC = 140,
|
||||
KEY_SETUP = 141,
|
||||
KEY_SLEEP = 142,
|
||||
KEY_WAKEUP = 143,
|
||||
KEY_FILE = 144,
|
||||
KEY_SENDFILE = 145,
|
||||
KEY_DELETEFILE = 146,
|
||||
KEY_XFER = 147,
|
||||
KEY_PROG1 = 148,
|
||||
KEY_PROG2 = 149,
|
||||
KEY_WWW = 150,
|
||||
KEY_MSDOS = 151,
|
||||
KEY_COFFEE = 152,
|
||||
KEY_SCREENLOCK = KEY_COFFEE,
|
||||
KEY_ROTATE_DISPLAY = 153,
|
||||
KEY_DIRECTION = KEY_ROTATE_DISPLAY,
|
||||
KEY_CYCLEWINDOWS = 154,
|
||||
KEY_MAIL = 155,
|
||||
KEY_BOOKMARKS = 156,
|
||||
KEY_COMPUTER = 157,
|
||||
KEY_BACK = 158,
|
||||
KEY_FORWARD = 159,
|
||||
KEY_CLOSECD = 160,
|
||||
KEY_EJECTCD = 161,
|
||||
KEY_EJECTCLOSECD = 162,
|
||||
KEY_NEXTSONG = 163,
|
||||
KEY_PLAYPAUSE = 164,
|
||||
KEY_PREVIOUSSONG = 165,
|
||||
KEY_STOPCD = 166,
|
||||
KEY_RECORD = 167,
|
||||
KEY_REWIND = 168,
|
||||
KEY_PHONE = 169,
|
||||
KEY_ISO = 170,
|
||||
KEY_CONFIG = 171,
|
||||
KEY_HOMEPAGE = 172,
|
||||
KEY_REFRESH = 173,
|
||||
KEY_EXIT = 174,
|
||||
KEY_MOVE = 175,
|
||||
KEY_EDIT = 176,
|
||||
KEY_SCROLLUP = 177,
|
||||
KEY_SCROLLDOWN = 178,
|
||||
KEY_KPLEFTPAREN = 179,
|
||||
KEY_KPRIGHTPAREN = 180,
|
||||
KEY_NEW = 181,
|
||||
KEY_REDO = 182,
|
||||
KEY_F13 = 183,
|
||||
KEY_F14 = 184,
|
||||
KEY_F15 = 185,
|
||||
KEY_F16 = 186,
|
||||
KEY_F17 = 187,
|
||||
KEY_F18 = 188,
|
||||
KEY_F19 = 189,
|
||||
KEY_F20 = 190,
|
||||
KEY_F21 = 191,
|
||||
KEY_F22 = 192,
|
||||
KEY_F23 = 193,
|
||||
KEY_F24 = 194,
|
||||
KEY_PLAYCD = 200,
|
||||
KEY_PAUSECD = 201,
|
||||
KEY_PROG3 = 202,
|
||||
KEY_PROG4 = 203,
|
||||
KEY_DASHBOARD = 204,
|
||||
KEY_SUSPEND = 205,
|
||||
KEY_CLOSE = 206,
|
||||
KEY_PLAY = 207,
|
||||
KEY_FASTFORWARD = 208,
|
||||
KEY_BASSBOOST = 209,
|
||||
KEY_PRINT = 210,
|
||||
KEY_HP = 211,
|
||||
KEY_CAMERA = 212,
|
||||
KEY_SOUND = 213,
|
||||
KEY_QUESTION = 214,
|
||||
KEY_EMAIL = 215,
|
||||
KEY_CHAT = 216,
|
||||
KEY_SEARCH = 217,
|
||||
KEY_CONNECT = 218,
|
||||
KEY_FINANCE = 219,
|
||||
KEY_SPORT = 220,
|
||||
KEY_SHOP = 221,
|
||||
KEY_ALTERASE = 222,
|
||||
KEY_CANCEL = 223,
|
||||
KEY_BRIGHTNESSDOWN = 224,
|
||||
KEY_BRIGHTNESSUP = 225,
|
||||
KEY_MEDIA = 226,
|
||||
KEY_SWITCHVIDEOMODE = 227,
|
||||
KEY_KBDILLUMTOGGLE = 228,
|
||||
KEY_KBDILLUMDOWN = 229,
|
||||
KEY_KBDILLUMUP = 230,
|
||||
KEY_SEND = 231,
|
||||
KEY_REPLY = 232,
|
||||
KEY_FORWARDMAIL = 233,
|
||||
KEY_SAVE = 234,
|
||||
KEY_DOCUMENTS = 235,
|
||||
KEY_BATTERY = 236,
|
||||
KEY_BLUETOOTH = 237,
|
||||
KEY_WLAN = 238,
|
||||
KEY_UWB = 239,
|
||||
KEY_UNKNOWN = 240,
|
||||
KEY_VIDEO_NEXT = 241,
|
||||
KEY_VIDEO_PREV = 242,
|
||||
KEY_BRIGHTNESS_CYCLE = 243,
|
||||
KEY_BRIGHTNESS_AUTO = 244,
|
||||
KEY_BRIGHTNESS_ZERO = KEY_BRIGHTNESS_AUTO,
|
||||
KEY_DISPLAY_OFF = 245,
|
||||
KEY_WWAN = 246,
|
||||
KEY_WIMAX = KEY_WWAN,
|
||||
KEY_RFKILL = 247,
|
||||
KEY_MICMUTE = 248,
|
||||
BTN_MISC = 0x100,
|
||||
BTN_0 = 0x100,
|
||||
BTN_1 = 0x101,
|
||||
BTN_2 = 0x102,
|
||||
BTN_3 = 0x103,
|
||||
BTN_4 = 0x104,
|
||||
BTN_5 = 0x105,
|
||||
BTN_6 = 0x106,
|
||||
BTN_7 = 0x107,
|
||||
BTN_8 = 0x108,
|
||||
BTN_9 = 0x109,
|
||||
BTN_MOUSE = 0x110,
|
||||
BTN_LEFT = 0x110,
|
||||
BTN_RIGHT = 0x111,
|
||||
BTN_MIDDLE = 0x112,
|
||||
BTN_SIDE = 0x113,
|
||||
BTN_EXTRA = 0x114,
|
||||
BTN_FORWARD = 0x115,
|
||||
BTN_BACK = 0x116,
|
||||
BTN_TASK = 0x117,
|
||||
BTN_JOYSTICK = 0x120,
|
||||
BTN_TRIGGER = 0x120,
|
||||
BTN_THUMB = 0x121,
|
||||
BTN_THUMB2 = 0x122,
|
||||
BTN_TOP = 0x123,
|
||||
BTN_TOP2 = 0x124,
|
||||
BTN_PINKIE = 0x125,
|
||||
BTN_BASE = 0x126,
|
||||
BTN_BASE2 = 0x127,
|
||||
BTN_BASE3 = 0x128,
|
||||
BTN_BASE4 = 0x129,
|
||||
BTN_BASE5 = 0x12a,
|
||||
BTN_BASE6 = 0x12b,
|
||||
BTN_DEAD = 0x12f,
|
||||
BTN_GAMEPAD = 0x130,
|
||||
BTN_SOUTH = 0x130,
|
||||
BTN_A = BTN_SOUTH,
|
||||
BTN_EAST = 0x131,
|
||||
BTN_B = BTN_EAST,
|
||||
BTN_C = 0x132,
|
||||
BTN_NORTH = 0x133,
|
||||
BTN_X = BTN_NORTH,
|
||||
BTN_WEST = 0x134,
|
||||
BTN_Y = BTN_WEST,
|
||||
BTN_Z = 0x135,
|
||||
BTN_TL = 0x136,
|
||||
BTN_TR = 0x137,
|
||||
BTN_TL2 = 0x138,
|
||||
BTN_TR2 = 0x139,
|
||||
BTN_SELECT = 0x13a,
|
||||
BTN_START = 0x13b,
|
||||
BTN_MODE = 0x13c,
|
||||
BTN_THUMBL = 0x13d,
|
||||
BTN_THUMBR = 0x13e,
|
||||
BTN_DIGI = 0x140,
|
||||
BTN_TOOL_PEN = 0x140,
|
||||
BTN_TOOL_RUBBER = 0x141,
|
||||
BTN_TOOL_BRUSH = 0x142,
|
||||
BTN_TOOL_PENCIL = 0x143,
|
||||
BTN_TOOL_AIRBRUSH = 0x144,
|
||||
BTN_TOOL_FINGER = 0x145,
|
||||
BTN_TOOL_MOUSE = 0x146,
|
||||
BTN_TOOL_LENS = 0x147,
|
||||
BTN_TOOL_QUINTTAP = 0x148,
|
||||
BTN_STYLUS3 = 0x149,
|
||||
BTN_TOUCH = 0x14a,
|
||||
BTN_STYLUS = 0x14b,
|
||||
BTN_STYLUS2 = 0x14c,
|
||||
BTN_TOOL_DOUBLETAP = 0x14d,
|
||||
BTN_TOOL_TRIPLETAP = 0x14e,
|
||||
BTN_TOOL_QUADTAP = 0x14f,
|
||||
BTN_WHEEL = 0x150,
|
||||
BTN_GEAR_DOWN = 0x150,
|
||||
BTN_GEAR_UP = 0x151,
|
||||
KEY_OK = 0x160,
|
||||
KEY_SELECT = 0x161,
|
||||
KEY_GOTO = 0x162,
|
||||
KEY_CLEAR = 0x163,
|
||||
KEY_POWER2 = 0x164,
|
||||
KEY_OPTION = 0x165,
|
||||
KEY_INFO = 0x166,
|
||||
KEY_TIME = 0x167,
|
||||
KEY_VENDOR = 0x168,
|
||||
KEY_ARCHIVE = 0x169,
|
||||
KEY_PROGRAM = 0x16a,
|
||||
KEY_CHANNEL = 0x16b,
|
||||
KEY_FAVORITES = 0x16c,
|
||||
KEY_EPG = 0x16d,
|
||||
KEY_PVR = 0x16e,
|
||||
KEY_MHP = 0x16f,
|
||||
KEY_LANGUAGE = 0x170,
|
||||
KEY_TITLE = 0x171,
|
||||
KEY_SUBTITLE = 0x172,
|
||||
KEY_ANGLE = 0x173,
|
||||
KEY_ZOOM = 0x174,
|
||||
KEY_MODE = 0x175,
|
||||
KEY_KEYBOARD = 0x176,
|
||||
KEY_SCREEN = 0x177,
|
||||
KEY_PC = 0x178,
|
||||
KEY_TV = 0x179,
|
||||
KEY_TV2 = 0x17a,
|
||||
KEY_VCR = 0x17b,
|
||||
KEY_VCR2 = 0x17c,
|
||||
KEY_SAT = 0x17d,
|
||||
KEY_SAT2 = 0x17e,
|
||||
KEY_CD = 0x17f,
|
||||
KEY_TAPE = 0x180,
|
||||
KEY_RADIO = 0x181,
|
||||
KEY_TUNER = 0x182,
|
||||
KEY_PLAYER = 0x183,
|
||||
KEY_TEXT = 0x184,
|
||||
KEY_DVD = 0x185,
|
||||
KEY_AUX = 0x186,
|
||||
KEY_MP3 = 0x187,
|
||||
KEY_AUDIO = 0x188,
|
||||
KEY_VIDEO = 0x189,
|
||||
KEY_DIRECTORY = 0x18a,
|
||||
KEY_LIST = 0x18b,
|
||||
KEY_MEMO = 0x18c,
|
||||
KEY_CALENDAR = 0x18d,
|
||||
KEY_RED = 0x18e,
|
||||
KEY_GREEN = 0x18f,
|
||||
KEY_YELLOW = 0x190,
|
||||
KEY_BLUE = 0x191,
|
||||
KEY_CHANNELUP = 0x192,
|
||||
KEY_CHANNELDOWN = 0x193,
|
||||
KEY_FIRST = 0x194,
|
||||
KEY_LAST = 0x195,
|
||||
KEY_AB = 0x196,
|
||||
KEY_NEXT = 0x197,
|
||||
KEY_RESTART = 0x198,
|
||||
KEY_SLOW = 0x199,
|
||||
KEY_SHUFFLE = 0x19a,
|
||||
KEY_BREAK = 0x19b,
|
||||
KEY_PREVIOUS = 0x19c,
|
||||
KEY_DIGITS = 0x19d,
|
||||
KEY_TEEN = 0x19e,
|
||||
KEY_TWEN = 0x19f,
|
||||
KEY_VIDEOPHONE = 0x1a0,
|
||||
KEY_GAMES = 0x1a1,
|
||||
KEY_ZOOMIN = 0x1a2,
|
||||
KEY_ZOOMOUT = 0x1a3,
|
||||
KEY_ZOOMRESET = 0x1a4,
|
||||
KEY_WORDPROCESSOR = 0x1a5,
|
||||
KEY_EDITOR = 0x1a6,
|
||||
KEY_SPREADSHEET = 0x1a7,
|
||||
KEY_GRAPHICSEDITOR = 0x1a8,
|
||||
KEY_PRESENTATION = 0x1a9,
|
||||
KEY_DATABASE = 0x1aa,
|
||||
KEY_NEWS = 0x1ab,
|
||||
KEY_VOICEMAIL = 0x1ac,
|
||||
KEY_ADDRESSBOOK = 0x1ad,
|
||||
KEY_MESSENGER = 0x1ae,
|
||||
KEY_DISPLAYTOGGLE = 0x1af,
|
||||
KEY_BRIGHTNESS_TOGGLE = KEY_DISPLAYTOGGLE,
|
||||
KEY_SPELLCHECK = 0x1b0,
|
||||
KEY_LOGOFF = 0x1b1,
|
||||
KEY_DOLLAR = 0x1b2,
|
||||
KEY_EURO = 0x1b3,
|
||||
KEY_FRAMEBACK = 0x1b4,
|
||||
KEY_FRAMEFORWARD = 0x1b5,
|
||||
KEY_CONTEXT_MENU = 0x1b6,
|
||||
KEY_MEDIA_REPEAT = 0x1b7,
|
||||
KEY_10CHANNELSUP = 0x1b8,
|
||||
KEY_10CHANNELSDOWN = 0x1b9,
|
||||
KEY_IMAGES = 0x1ba,
|
||||
KEY_DEL_EOL = 0x1c0,
|
||||
KEY_DEL_EOS = 0x1c1,
|
||||
KEY_INS_LINE = 0x1c2,
|
||||
KEY_DEL_LINE = 0x1c3,
|
||||
KEY_FN = 0x1d0,
|
||||
KEY_FN_ESC = 0x1d1,
|
||||
KEY_FN_F1 = 0x1d2,
|
||||
KEY_FN_F2 = 0x1d3,
|
||||
KEY_FN_F3 = 0x1d4,
|
||||
KEY_FN_F4 = 0x1d5,
|
||||
KEY_FN_F5 = 0x1d6,
|
||||
KEY_FN_F6 = 0x1d7,
|
||||
KEY_FN_F7 = 0x1d8,
|
||||
KEY_FN_F8 = 0x1d9,
|
||||
KEY_FN_F9 = 0x1da,
|
||||
KEY_FN_F10 = 0x1db,
|
||||
KEY_FN_F11 = 0x1dc,
|
||||
KEY_FN_F12 = 0x1dd,
|
||||
KEY_FN_1 = 0x1de,
|
||||
KEY_FN_2 = 0x1df,
|
||||
KEY_FN_D = 0x1e0,
|
||||
KEY_FN_E = 0x1e1,
|
||||
KEY_FN_F = 0x1e2,
|
||||
KEY_FN_S = 0x1e3,
|
||||
KEY_FN_B = 0x1e4,
|
||||
KEY_BRL_DOT1 = 0x1f1,
|
||||
KEY_BRL_DOT2 = 0x1f2,
|
||||
KEY_BRL_DOT3 = 0x1f3,
|
||||
KEY_BRL_DOT4 = 0x1f4,
|
||||
KEY_BRL_DOT5 = 0x1f5,
|
||||
KEY_BRL_DOT6 = 0x1f6,
|
||||
KEY_BRL_DOT7 = 0x1f7,
|
||||
KEY_BRL_DOT8 = 0x1f8,
|
||||
KEY_BRL_DOT9 = 0x1f9,
|
||||
KEY_BRL_DOT10 = 0x1fa,
|
||||
KEY_NUMERIC_0 = 0x200,
|
||||
KEY_NUMERIC_1 = 0x201,
|
||||
KEY_NUMERIC_2 = 0x202,
|
||||
KEY_NUMERIC_3 = 0x203,
|
||||
KEY_NUMERIC_4 = 0x204,
|
||||
KEY_NUMERIC_5 = 0x205,
|
||||
KEY_NUMERIC_6 = 0x206,
|
||||
KEY_NUMERIC_7 = 0x207,
|
||||
KEY_NUMERIC_8 = 0x208,
|
||||
KEY_NUMERIC_9 = 0x209,
|
||||
KEY_NUMERIC_STAR = 0x20a,
|
||||
KEY_NUMERIC_POUND = 0x20b,
|
||||
KEY_NUMERIC_A = 0x20c,
|
||||
KEY_NUMERIC_B = 0x20d,
|
||||
KEY_NUMERIC_C = 0x20e,
|
||||
KEY_NUMERIC_D = 0x20f,
|
||||
KEY_CAMERA_FOCUS = 0x210,
|
||||
KEY_WPS_BUTTON = 0x211,
|
||||
KEY_TOUCHPAD_TOGGLE = 0x212,
|
||||
KEY_TOUCHPAD_ON = 0x213,
|
||||
KEY_TOUCHPAD_OFF = 0x214,
|
||||
KEY_CAMERA_ZOOMIN = 0x215,
|
||||
KEY_CAMERA_ZOOMOUT = 0x216,
|
||||
KEY_CAMERA_UP = 0x217,
|
||||
KEY_CAMERA_DOWN = 0x218,
|
||||
KEY_CAMERA_LEFT = 0x219,
|
||||
KEY_CAMERA_RIGHT = 0x21a,
|
||||
KEY_ATTENDANT_ON = 0x21b,
|
||||
KEY_ATTENDANT_OFF = 0x21c,
|
||||
KEY_ATTENDANT_TOGGLE = 0x21d,
|
||||
KEY_LIGHTS_TOGGLE = 0x21e,
|
||||
BTN_DPAD_UP = 0x220,
|
||||
BTN_DPAD_DOWN = 0x221,
|
||||
BTN_DPAD_LEFT = 0x222,
|
||||
BTN_DPAD_RIGHT = 0x223,
|
||||
KEY_ALS_TOGGLE = 0x230,
|
||||
KEY_BUTTONCONFIG = 0x240,
|
||||
KEY_TASKMANAGER = 0x241,
|
||||
KEY_JOURNAL = 0x242,
|
||||
KEY_CONTROLPANEL = 0x243,
|
||||
KEY_APPSELECT = 0x244,
|
||||
KEY_SCREENSAVER = 0x245,
|
||||
KEY_VOICECOMMAND = 0x246,
|
||||
KEY_ASSISTANT = 0x247,
|
||||
KEY_BRIGHTNESS_MIN = 0x250,
|
||||
KEY_BRIGHTNESS_MAX = 0x251,
|
||||
KEY_KBDINPUTASSIST_PREV = 0x260,
|
||||
KEY_KBDINPUTASSIST_NEXT = 0x261,
|
||||
KEY_KBDINPUTASSIST_PREVGROUP = 0x262,
|
||||
KEY_KBDINPUTASSIST_NEXTGROUP = 0x263,
|
||||
KEY_KBDINPUTASSIST_ACCEPT = 0x264,
|
||||
KEY_KBDINPUTASSIST_CANCEL = 0x265,
|
||||
KEY_RIGHT_UP = 0x266,
|
||||
KEY_RIGHT_DOWN = 0x267,
|
||||
KEY_LEFT_UP = 0x268,
|
||||
KEY_LEFT_DOWN = 0x269,
|
||||
KEY_ROOT_MENU = 0x26a,
|
||||
KEY_MEDIA_TOP_MENU = 0x26b,
|
||||
KEY_NUMERIC_11 = 0x26c,
|
||||
KEY_NUMERIC_12 = 0x26d,
|
||||
KEY_AUDIO_DESC = 0x26e,
|
||||
KEY_3D_MODE = 0x26f,
|
||||
KEY_NEXT_FAVORITE = 0x270,
|
||||
KEY_STOP_RECORD = 0x271,
|
||||
KEY_PAUSE_RECORD = 0x272,
|
||||
KEY_VOD = 0x273,
|
||||
KEY_UNMUTE = 0x274,
|
||||
KEY_FASTREVERSE = 0x275,
|
||||
KEY_SLOWREVERSE = 0x276,
|
||||
KEY_DATA = 0x277,
|
||||
KEY_ONSCREEN_KEYBOARD = 0x278,
|
||||
BTN_TRIGGER_HAPPY = 0x2c0,
|
||||
BTN_TRIGGER_HAPPY1 = 0x2c0,
|
||||
BTN_TRIGGER_HAPPY2 = 0x2c1,
|
||||
BTN_TRIGGER_HAPPY3 = 0x2c2,
|
||||
BTN_TRIGGER_HAPPY4 = 0x2c3,
|
||||
BTN_TRIGGER_HAPPY5 = 0x2c4,
|
||||
BTN_TRIGGER_HAPPY6 = 0x2c5,
|
||||
BTN_TRIGGER_HAPPY7 = 0x2c6,
|
||||
BTN_TRIGGER_HAPPY8 = 0x2c7,
|
||||
BTN_TRIGGER_HAPPY9 = 0x2c8,
|
||||
BTN_TRIGGER_HAPPY10 = 0x2c9,
|
||||
BTN_TRIGGER_HAPPY11 = 0x2ca,
|
||||
BTN_TRIGGER_HAPPY12 = 0x2cb,
|
||||
BTN_TRIGGER_HAPPY13 = 0x2cc,
|
||||
BTN_TRIGGER_HAPPY14 = 0x2cd,
|
||||
BTN_TRIGGER_HAPPY15 = 0x2ce,
|
||||
BTN_TRIGGER_HAPPY16 = 0x2cf,
|
||||
BTN_TRIGGER_HAPPY17 = 0x2d0,
|
||||
BTN_TRIGGER_HAPPY18 = 0x2d1,
|
||||
BTN_TRIGGER_HAPPY19 = 0x2d2,
|
||||
BTN_TRIGGER_HAPPY20 = 0x2d3,
|
||||
BTN_TRIGGER_HAPPY21 = 0x2d4,
|
||||
BTN_TRIGGER_HAPPY22 = 0x2d5,
|
||||
BTN_TRIGGER_HAPPY23 = 0x2d6,
|
||||
BTN_TRIGGER_HAPPY24 = 0x2d7,
|
||||
BTN_TRIGGER_HAPPY25 = 0x2d8,
|
||||
BTN_TRIGGER_HAPPY26 = 0x2d9,
|
||||
BTN_TRIGGER_HAPPY27 = 0x2da,
|
||||
BTN_TRIGGER_HAPPY28 = 0x2db,
|
||||
BTN_TRIGGER_HAPPY29 = 0x2dc,
|
||||
BTN_TRIGGER_HAPPY30 = 0x2dd,
|
||||
BTN_TRIGGER_HAPPY31 = 0x2de,
|
||||
BTN_TRIGGER_HAPPY32 = 0x2df,
|
||||
BTN_TRIGGER_HAPPY33 = 0x2e0,
|
||||
BTN_TRIGGER_HAPPY34 = 0x2e1,
|
||||
BTN_TRIGGER_HAPPY35 = 0x2e2,
|
||||
BTN_TRIGGER_HAPPY36 = 0x2e3,
|
||||
BTN_TRIGGER_HAPPY37 = 0x2e4,
|
||||
BTN_TRIGGER_HAPPY38 = 0x2e5,
|
||||
BTN_TRIGGER_HAPPY39 = 0x2e6,
|
||||
BTN_TRIGGER_HAPPY40 = 0x2e7,
|
||||
KEY_MIN_INTERESTING = KEY_MUTE,
|
||||
KEY_MAX = 0x2ff,
|
||||
KEY_CNT = KEY_MAX + 1,
|
||||
}
|
||||
|
||||
public enum EvDevKeyValue : int
|
||||
{
|
||||
KeyUp = 0,
|
||||
KeyDown = 1,
|
||||
KeyRepeat = 2
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct EvDevKeyboardEvent
|
||||
{
|
||||
public IntPtr tv_sec;
|
||||
public IntPtr tv_usec;
|
||||
public EvDevEventType type;
|
||||
public EvDevKeyCode code;
|
||||
public EvDevKeyValue value;
|
||||
}
|
||||
|
||||
private const uint IOC_READ = 2;
|
||||
private const uint IOC_EV_TYPE = 'E';
|
||||
private static uint EVIOCG(long nr, long size)
|
||||
=> (uint)((IOC_READ << 30) | (size << 16) | (IOC_EV_TYPE << 8) | nr);
|
||||
|
||||
public static uint EVIOCGNAME(long len) => EVIOCG( 0x06, len);
|
||||
public static uint EVIOCGPHYS(long len) => EVIOCG( 0x07, len);
|
||||
public static uint EVIOCGUNIQ(long len) => EVIOCG( 0x08, len);
|
||||
public static uint EVIOCGPROP(long len) => EVIOCG(0x09, len);
|
||||
public static uint EVIOCGBIT(EvDevEventType ev, long len) => EVIOCG(0x20 + (long)ev, len);
|
||||
public static uint EVIOCGABS(int abs) => EVIOCG(0x40 + abs, 24);
|
||||
|
||||
public const uint EVIOCGVERSION = 0x80044501;
|
||||
public const uint EVIOCGID = 0x80084502;
|
||||
public const uint EVIOCGREP = 0x80084503;
|
||||
public const uint EVIOCSREP = 0x40084503;
|
||||
public const uint EVIOCGKEYCODE = 0x80084504;
|
||||
public const uint EVIOCGKEYCODE_V2 = 0x80284504;
|
||||
public const uint EVIOCSKEYCODE = 0x40084504;
|
||||
public const uint EVIOCSKEYCODE_V2 = 0x40284504;
|
||||
|
||||
[DllImport("libc")]
|
||||
public static extern unsafe int ioctl(int fd, UIntPtr request, void* data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Common
|
||||
{
|
||||
public static class FildesImports
|
||||
{
|
||||
[Flags]
|
||||
public enum OpenFlags : int
|
||||
{
|
||||
O_RDONLY = 0,
|
||||
O_WRONLY = 1,
|
||||
O_RDWR = 2,
|
||||
// O_LARGEFILE = 0,
|
||||
O_CREAT = 0x40,
|
||||
O_EXCL = 0x80,
|
||||
O_NOCTTY = 0x100,
|
||||
O_TRUNC = 0x200,
|
||||
O_APPEND = 0x400,
|
||||
O_NONBLOCK = 0x800,
|
||||
O_NDELAY = O_NONBLOCK,
|
||||
O_DSYNC = 0x1000,
|
||||
O_ASYNC = 0x2000,
|
||||
O_DIRECT = 0x4000,
|
||||
O_DIRECTORY = 0x10000,
|
||||
O_NOFOLLOW = 0x20000,
|
||||
O_NOATIME = 0x40000,
|
||||
O_CLOEXEC = 0x80000,
|
||||
O_SYNC = 0x100000 | O_DSYNC,
|
||||
O_PATH = 0x200000,
|
||||
O_TMPFILE = 0x400000 | O_DIRECTORY,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum OpenMode : int
|
||||
{
|
||||
S_IXOTH = 0x1,
|
||||
S_IWOTH = 0x2,
|
||||
S_IROTH = 0x4,
|
||||
S_IRWXO = S_IROTH | S_IWOTH | S_IXOTH,
|
||||
S_IXGRP = 0x8,
|
||||
S_IWGRP = 0x10,
|
||||
S_IRGRP = 0x20,
|
||||
S_IRWXG = S_IRGRP | S_IWGRP | S_IXGRP,
|
||||
S_IXUSR = 0x40,
|
||||
S_IWUSR = 0x80,
|
||||
S_IRUSR = 0x100,
|
||||
S_IRWXU = S_IRUSR | S_IWUSR | S_IXUSR,
|
||||
S_ISVTX = 0x200,
|
||||
S_ISGID = 0x400,
|
||||
S_ISUID = 0x800,
|
||||
}
|
||||
|
||||
[DllImport("libc")]
|
||||
public static extern int open(string pathname, OpenFlags flags);
|
||||
|
||||
[DllImport("libc")]
|
||||
public static extern int open(string pathname, OpenFlags flags, OpenMode mode);
|
||||
|
||||
[DllImport("libc")]
|
||||
public static extern int close(int fd);
|
||||
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
public static extern unsafe IntPtr read(int fd, void* buf, IntPtr count);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue