[X11] Implemented joystick hotplugging
This is a work in progress.
This commit is contained in:
parent
b004dc7a0a
commit
4473c8373e
1 changed files with 118 additions and 50 deletions
|
@ -28,20 +28,29 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
|
|
||||||
namespace OpenTK.Platform.X11
|
namespace OpenTK.Platform.X11
|
||||||
{
|
{
|
||||||
struct X11JoyDetails { }
|
struct X11JoyDetails
|
||||||
|
{
|
||||||
|
public bool IsConnected;
|
||||||
|
}
|
||||||
|
|
||||||
sealed class X11Joystick : IJoystickDriver, IJoystickDriver2, IGamePadDriver
|
sealed class X11Joystick : IJoystickDriver2
|
||||||
{
|
{
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
List<JoystickDevice> sticks = new List<JoystickDevice>();
|
readonly object sync = new object();
|
||||||
IList<JoystickDevice> sticks_readonly;
|
|
||||||
|
readonly FileSystemWatcher watcher = new FileSystemWatcher(JoystickPath);
|
||||||
|
readonly FileSystemWatcher watcher_legacy = new FileSystemWatcher(JoystickPathLegacy);
|
||||||
|
|
||||||
|
readonly Dictionary<int, int> index_to_stick = new Dictionary<int, int>();
|
||||||
|
List<JoystickDevice<X11JoyDetails>> sticks = new List<JoystickDevice<X11JoyDetails>>();
|
||||||
|
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
|
@ -51,12 +60,25 @@ namespace OpenTK.Platform.X11
|
||||||
|
|
||||||
public X11Joystick()
|
public X11Joystick()
|
||||||
{
|
{
|
||||||
sticks_readonly = sticks.AsReadOnly();
|
watcher.Created += JoystickAdded;
|
||||||
|
watcher.Deleted += JoystickRemoved;
|
||||||
|
watcher.EnableRaisingEvents = true;
|
||||||
|
|
||||||
|
watcher_legacy.Created += JoystickAdded;
|
||||||
|
watcher_legacy.Deleted += JoystickRemoved;
|
||||||
|
watcher_legacy.EnableRaisingEvents = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Members
|
||||||
|
|
||||||
|
void OpenJoysticks()
|
||||||
|
{
|
||||||
int number = 0, max_sticks = 25;
|
int number = 0, max_sticks = 25;
|
||||||
while (number < max_sticks)
|
while (number < max_sticks)
|
||||||
{
|
{
|
||||||
JoystickDevice stick = OpenJoystick(JoystickPath, number++);
|
JoystickDevice<X11JoyDetails> stick = OpenJoystick(JoystickPath, number++);
|
||||||
if (stick != null)
|
if (stick != null)
|
||||||
{
|
{
|
||||||
//stick.Description = String.Format("USB Joystick {0} ({1} axes, {2} buttons, {3}{0})",
|
//stick.Description = String.Format("USB Joystick {0} ({1} axes, {2} buttons, {3}{0})",
|
||||||
|
@ -68,7 +90,7 @@ namespace OpenTK.Platform.X11
|
||||||
number = 0;
|
number = 0;
|
||||||
while (number < max_sticks)
|
while (number < max_sticks)
|
||||||
{
|
{
|
||||||
JoystickDevice stick = OpenJoystick(JoystickPathLegacy, number++);
|
JoystickDevice<X11JoyDetails> stick = OpenJoystick(JoystickPathLegacy, number++);
|
||||||
if (stick != null)
|
if (stick != null)
|
||||||
{
|
{
|
||||||
//stick.Description = String.Format("USB Joystick {0} ({1} axes, {2} buttons, {3}{0})",
|
//stick.Description = String.Format("USB Joystick {0} ({1} axes, {2} buttons, {3}{0})",
|
||||||
|
@ -78,20 +100,88 @@ namespace OpenTK.Platform.X11
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetJoystickNumber(string path)
|
||||||
|
{
|
||||||
|
if (path.StartsWith("js"))
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
if (Int32.TryParse(path.Substring(2), out num))
|
||||||
|
{
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JoystickAdded(object sender, FileSystemEventArgs e)
|
||||||
|
{
|
||||||
|
lock (sync)
|
||||||
|
{
|
||||||
|
string file = Path.GetFileName(e.FullPath);
|
||||||
|
int number = GetJoystickNumber(file);
|
||||||
|
if (number != -1)
|
||||||
|
{
|
||||||
|
JoystickDevice<X11JoyDetails> stick = OpenJoystick(e.FullPath, number);
|
||||||
|
|
||||||
|
// Find the first disconnected joystick (if any)
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sticks.Count; i++)
|
||||||
|
{
|
||||||
|
if (!stick.Details.IsConnected)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no disconnected joystick exists, append a new slot
|
||||||
|
if (i == sticks.Count)
|
||||||
|
{
|
||||||
|
sticks.Add(stick);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sticks[i] = stick;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map player index to joystick
|
||||||
|
index_to_stick.Add(index_to_stick.Count, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JoystickRemoved(object sender, FileSystemEventArgs e)
|
||||||
|
{
|
||||||
|
lock (sync)
|
||||||
|
{
|
||||||
|
string file = Path.GetFileName(e.FullPath);
|
||||||
|
int number = GetJoystickNumber(file);
|
||||||
|
if (number != -1)
|
||||||
|
{
|
||||||
|
// Find which joystick id matches this number
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sticks.Count; i++)
|
||||||
|
{
|
||||||
|
if (sticks[i].Id == number)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == sticks.Count)
|
||||||
|
{
|
||||||
|
Debug.Print("[Evdev] Joystick id {0} does not exist.", number);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JoystickDevice<X11JoyDetails> stick = sticks[i];
|
||||||
|
stick.Details.IsConnected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IJoystickDriver
|
|
||||||
|
|
||||||
public int DeviceCount
|
|
||||||
{
|
|
||||||
get { return sticks.Count; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IList<JoystickDevice> Joysticks
|
|
||||||
{
|
|
||||||
get { Poll(); return sticks_readonly; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Poll()
|
public void Poll()
|
||||||
{
|
{
|
||||||
JoystickEvent e;
|
JoystickEvent e;
|
||||||
|
@ -123,13 +213,11 @@ namespace OpenTK.Platform.X11
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Private Members
|
#region Private Members
|
||||||
|
|
||||||
JoystickDevice<X11JoyDetails> OpenJoystick(string base_path, int number)
|
JoystickDevice<X11JoyDetails> OpenJoystick(string base_path, int number)
|
||||||
{
|
{
|
||||||
string path = base_path + number.ToString();
|
string path = Path.Combine(base_path, "js" + number.ToString());
|
||||||
JoystickDevice<X11JoyDetails> stick = null;
|
JoystickDevice<X11JoyDetails> stick = null;
|
||||||
|
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
@ -159,6 +247,10 @@ namespace OpenTK.Platform.X11
|
||||||
UnsafeNativeMethods.ioctl(fd, JoystickIoctlCode.Name128, sb);
|
UnsafeNativeMethods.ioctl(fd, JoystickIoctlCode.Name128, sb);
|
||||||
stick.Description = sb.ToString();
|
stick.Description = sb.ToString();
|
||||||
|
|
||||||
|
stick.Id = number;
|
||||||
|
|
||||||
|
stick.Details.IsConnected = true;
|
||||||
|
|
||||||
Debug.Print("Found joystick on path {0}", path);
|
Debug.Print("Found joystick on path {0}", path);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
@ -196,8 +288,8 @@ namespace OpenTK.Platform.X11
|
||||||
Name128 = (2u << 30) | (0x6A << 8) | (0x13 << 0) | (128 << 16) //JSIOCGNAME(128), which is _IOC(_IO_READ, 'j', 0x13, len)
|
Name128 = (2u << 30) | (0x6A << 8) | (0x13 << 0) | (128 << 16) //JSIOCGNAME(128), which is _IOC(_IO_READ, 'j', 0x13, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly string JoystickPath = "/dev/input/js";
|
static readonly string JoystickPath = "/dev/input";
|
||||||
static readonly string JoystickPathLegacy = "/dev/js";
|
static readonly string JoystickPathLegacy = "/dev";
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
enum OpenFlags
|
enum OpenFlags
|
||||||
|
@ -259,30 +351,6 @@ namespace OpenTK.Platform.X11
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IGamePadDriver Members
|
|
||||||
|
|
||||||
public GamePadCapabilities GetCapabilities(int index)
|
|
||||||
{
|
|
||||||
return new GamePadCapabilities();
|
|
||||||
}
|
|
||||||
|
|
||||||
public GamePadState GetState(int index)
|
|
||||||
{
|
|
||||||
return new GamePadState();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetName(int index)
|
|
||||||
{
|
|
||||||
return String.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SetVibration(int index, float left, float right)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region IJoystickDriver2 Members
|
#region IJoystickDriver2 Members
|
||||||
|
|
||||||
JoystickState IJoystickDriver2.GetState(int index)
|
JoystickState IJoystickDriver2.GetState(int index)
|
||||||
|
|
Loading…
Reference in a new issue