Skip to content

Commit

Permalink
[Linux] Implemented joystick guid detection
Browse files Browse the repository at this point in the history
  • Loading branch information
thefiddler committed Jan 14, 2014
1 parent 73e3b66 commit df7d7ae
Showing 1 changed file with 91 additions and 2 deletions.
93 changes: 91 additions & 2 deletions Source/OpenTK/Platform/X11/X11Joystick.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#region License
#region License
//
// The Open Toolkit Library License
//
Expand Down Expand Up @@ -37,6 +37,7 @@ namespace OpenTK.Platform.X11
{
struct X11JoyDetails
{
public Guid Guid;
public int FileDescriptor;
public JoystickState State;
}
Expand Down Expand Up @@ -159,6 +160,72 @@ void JoystickRemoved(object sender, FileSystemEventArgs e)

#region Private Members

Guid CreateGuid(JoystickDevice<X11JoyDetails> js, string path, int number)
{
byte[] bytes = new byte[16];
for (int i = 0; i < Math.Min(bytes.Length, js.Description.Length); i++)
{
bytes[i] = (byte)js.Description[i];
}
return new Guid(bytes);

#if false // Todo: move to /dev/input/event* from /dev/input/js*
string evdev_path = Path.Combine(Path.GetDirectoryName(path), "event" + number);
if (!File.Exists(evdev_path))
return new Guid();

int event_fd = UnsafeNativeMethods.open(evdev_path, OpenFlags.NonBlock);
if (event_fd < 0)
return new Guid();

try
{
EventInputId id;
if (UnsafeNativeMethods.ioctl(event_fd, EvdevInputId.Id, out id) < 0)
return new Guid();

int i = 0;
byte[] bus = BitConverter.GetBytes(id.BusType);
bytes[i++] = bus[0];
bytes[i++] = bus[1];
bytes[i++] = 0;
bytes[i++] = 0;

if (id.Vendor != 0 && id.Product != 0 && id.Version != 0)
{
byte[] vendor = BitConverter.GetBytes(id.Vendor);
byte[] product = BitConverter.GetBytes(id.Product);
byte[] version = BitConverter.GetBytes(id.Version);
bytes[i++] = vendor[0];
bytes[i++] = vendor[1];
bytes[i++] = 0;
bytes[i++] = 0;
bytes[i++] = product[0];
bytes[i++] = product[1];
bytes[i++] = 0;
bytes[i++] = 0;
bytes[i++] = version[0];
bytes[i++] = version[1];
bytes[i++] = 0;
bytes[i++] = 0;
}
else
{
for (; i < bytes.Length; i++)
{
bytes[i] = (byte)js.Description[i];
}
}

return new Guid(bytes);
}
finally
{
UnsafeNativeMethods.close(event_fd);
}
#endif
}

JoystickDevice<X11JoyDetails> OpenJoystick(string path)
{
JoystickDevice<X11JoyDetails> stick = null;
Expand Down Expand Up @@ -195,7 +262,7 @@ JoystickDevice<X11JoyDetails> OpenJoystick(string path)

stick.Details.FileDescriptor = fd;
stick.Details.State.SetIsConnected(true);
//stick.Details.Guid =
stick.Details.Guid = CreateGuid(stick, path, number);

// Find the first disconnected joystick (if any)
int i;
Expand Down Expand Up @@ -290,6 +357,20 @@ bool IsValid(int index)

#region UnsafeNativeMethods

struct EvdevInputId
{
public ushort BusType;
public ushort Vendor;
public ushort Product;
public ushort Version;
}

enum EvdevIoctlCode : uint
{
Id = ((byte)'E' << 8) | (0x02 << 0) //EVIOCGID, which is _IOR('E', 0x02, struct input_id)
}


struct JoystickEvent
{
public uint Time; // (u32) event timestamp in milliseconds
Expand Down Expand Up @@ -331,6 +412,9 @@ static class UnsafeNativeMethods
[DllImport("libc", SetLastError = true)]
public static extern int ioctl(int d, JoystickIoctlCode request, StringBuilder data);

[DllImport("libc", SetLastError = true)]
public static extern int ioctl(int d, EvdevIoctlCode request, out EvdevInputId data);

[DllImport("libc", SetLastError = true)]
public static extern int open([MarshalAs(UnmanagedType.LPStr)]string pathname, OpenFlags flags);

Expand Down Expand Up @@ -405,6 +489,11 @@ JoystickCapabilities IJoystickDriver2.GetCapabilities(int index)

Guid IJoystickDriver2.GetGuid(int index)
{
if (IsValid(index))
{
JoystickDevice<X11JoyDetails> js = sticks[index_to_stick[index]];
return js.Details.Guid;
}
return new Guid();
}

Expand Down

0 comments on commit df7d7ae

Please sign in to comment.