Skip to content

Instantly share code, notes, and snippets.

@galvesribeiro
Created May 7, 2016 02:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save galvesribeiro/33675d6e707df8639f6ca3cbaae8c8c0 to your computer and use it in GitHub Desktop.
Save galvesribeiro/33675d6e707df8639f6ca3cbaae8c8c0 to your computer and use it in GitHub Desktop.
Input providers
public abstract class GenericInputProvider : ITouchProvider, IKeyboardInputProvider
{
public event Action<TouchData> Touch;
public event Action<Keys> KeyPressed;
public event Action<Keys> KeyReleased;
private string _keyboardDevice;
private string _touchDevice;
private int _touchFd = -1;
private int _keyboardFd = -1;
private bool _isListeningToTouch;
public bool IsListeningToTouch
{
get { return _isListeningToTouch; }
set
{
if (!string.IsNullOrWhiteSpace(_touchDevice) && _isListeningToTouch != value)
{
_isListeningToTouch = value;
if (_isListeningToTouch)
{
_touchFd = NativeOpen(_touchDevice, 2);
if (_touchFd < 0)
throw new InvalidOperationException($"Unable to open touch device {_touchDevice}. Return code {_touchFd}.");
ListenToTouch();
}
else
{
NativeClose(_touchFd);
}
}
}
}
private bool _isListeningToKeys;
public bool IsListeningToKeys
{
get { return _isListeningToKeys; }
set
{
if (!string.IsNullOrWhiteSpace(_keyboardDevice) && _isListeningToKeys != value)
{
_isListeningToKeys = value;
if (_isListeningToKeys)
{
_keyboardFd = NativeOpen(_keyboardDevice, 2);
if (_keyboardFd < 0)
throw new InvalidOperationException($"Unable to open keyboard device {_keyboardDevice}. Return code {_keyboardFd}.");
ListenToKeyboard();
}
else
{
NativeClose(_keyboardFd);
}
}
}
}
public GenericInputProvider(string keyboardDevice, string touchDevice = "")
{
if (string.IsNullOrWhiteSpace(keyboardDevice))
throw new ArgumentNullException("keyboardDevice");
_keyboardDevice = keyboardDevice;
_touchDevice = touchDevice;
}
private void ListenToTouch()
{
new Thread(new ThreadStart(() =>
{
var ev = new InputEvent[64];
var size = Marshal.SizeOf(typeof(InputEvent));
var totalSize = size * 64;
var buffer_ptr = Marshal.AllocHGlobal(totalSize);
while (_isListeningToTouch)
{
var rd = NativeRead(_touchFd, buffer_ptr, totalSize);
if (rd > size)
{
var eventNum = rd / size;
var event_ptr = buffer_ptr;
var touchData = new TouchData();
for (int i = 0; i < eventNum; i++)
{
var entry = new InputEvent();
Marshal.PtrToStructure(event_ptr, entry);
event_ptr = IntPtr.Add(event_ptr, size);
if (entry.type == 0x00) //EV_SYN
continue;
if (entry.type == 0x01 && entry.code == 0x14A) //EV_TOUCH
{
if (entry.value == 1)
{
touchData.Type = TouchEventType.Down;
}
else if (entry.value == 0)
{
touchData.Type = TouchEventType.Up;
}
}
else if (entry.type == 0x03) //EV_ABS
{
if (touchData.Type == TouchEventType.None)
{
touchData.Type = TouchEventType.Move;
}
if (entry.code == 0x00)
{
touchData.X = entry.value;
}
else if (entry.code == 0x01)
{
touchData.Y = entry.value;
}
}
//Console.WriteLine($"[Touch] code {entry.code} | type {entry.type} | value {entry.value}");
}
if (Touch != null && Touch.GetInvocationList().Length > 0)
Touch(touchData);
}
//Thread.Sleep(300);
}
//Marshal.FreeHGlobal(buffer_ptr);
})).Start();
}
private void ListenToKeyboard()
{
new Thread(new ThreadStart(() => {
var ev = new InputEvent[64];
var size = Marshal.SizeOf(typeof(InputEvent));
var totalSize = size * 64;
var buffer_ptr = Marshal.AllocHGlobal(totalSize);
while (_isListeningToKeys)
{
var rd = NativeRead(_keyboardFd, buffer_ptr, totalSize);
if (rd > size)
{
var eventNum = rd / size;
var event_ptr = buffer_ptr;
for (int i = 0; i < eventNum; i++)
{
var entry = new InputEvent();
Marshal.PtrToStructure(event_ptr, entry);
event_ptr = IntPtr.Add(event_ptr, size);
if (entry.type == 0x00) //EV_SYN
continue;
if (entry.type == 1)
{
if (entry.value == 1 && KeyPressed != null &&
KeyPressed.GetInvocationList().Length > 0)
{
KeyPressed(GetKey(entry.code));
}
else
if (entry.value == 0 && KeyReleased != null &&
KeyReleased.GetInvocationList().Length > 0)
{
KeyReleased(GetKey(entry.code));
}
}
}
}
//Thread.Sleep(300);
}
})).Start();
}
protected abstract Keys GetKey(int nativeKeyValue);
#region Native
private const string LIBC = "libc";
[DllImport(LIBC, EntryPoint = "open")]
private static extern int NativeOpen([In()] [MarshalAs(UnmanagedType.LPStr)] string file, int oflag);
[DllImport(LIBC, EntryPoint = "close")]
private static extern int NativeClose(int fd);
[DllImport(LIBC, EntryPoint = "read", CallingConvention = CallingConvention.Cdecl)]
private static extern int NativeRead(int fd, IntPtr buf, int nbytes);
[StructLayout(LayoutKind.Sequential)]
private struct InputEvent
{
public int Seconds;
public int Microseconds;
public ushort type;
public ushort code;
public int value;
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment