Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1452 chris 1
#region License
2
//
3
// The Open Toolkit Library License
4
//
5
// Copyright (c) 2006 - 2008 the Open Toolkit library, except where noted.
6
//
7
// Permission is hereby granted, free of charge, to any person obtaining a copy
8
// of this software and associated documentation files (the "Software"), to deal
9
// in the Software without restriction, including without limitation the rights to 
10
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11
// the Software, and to permit persons to whom the Software is furnished to do
12
// so, subject to the following conditions:
13
//
14
// The above copyright notice and this permission notice shall be included in all
15
// copies or substantial portions of the Software.
16
//
17
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
// OTHER DEALINGS IN THE SOFTWARE.
25
//
26
#endregion
27
 
28
using System;
29
using System.Collections.Generic;
30
using System.Diagnostics;
31
using System.Runtime.InteropServices;
32
using OpenTK.Input;
33
 
34
namespace OpenTK.Platform.X11
35
{
36
    struct X11JoyDetails { }
37
 
38
    sealed class X11Joystick : IJoystickDriver
39
    {
40
        #region Fields
41
 
42
        List<JoystickDevice> sticks = new List<JoystickDevice>();
43
        IList<JoystickDevice> sticks_readonly;
44
 
45
        bool disposed;
46
 
47
        #endregion
48
 
49
        #region Constructors
50
 
51
        public X11Joystick()
52
        {
53
            sticks_readonly = sticks.AsReadOnly();
54
 
55
            int number = 0, max_sticks = 25;
56
            while (number < max_sticks)
57
            {
58
                JoystickDevice stick = OpenJoystick(JoystickPath, number++);
59
                if (stick != null)
60
                {
61
                    stick.Description = String.Format("USB Joystick {0} ({1} axes, {2} buttons, {3}{0})",
62
                        number, stick.Axis.Count, stick.Button.Count, JoystickPath);
63
                    sticks.Add(stick);
64
                }
65
            }
66
 
67
            number = 0;
68
            while (number < max_sticks)
69
            {
70
                JoystickDevice stick = OpenJoystick(JoystickPathLegacy, number++);
71
                if (stick != null)
72
                {
73
                    stick.Description = String.Format("USB Joystick {0} ({1} axes, {2} buttons, {3}{0})",
74
                        number, stick.Axis.Count, stick.Button.Count, JoystickPathLegacy);
75
                    sticks.Add(stick);
76
                }
77
            }
78
        }
79
 
80
        #endregion
81
 
82
        #region IJoystickDriver
83
 
84
        public int DeviceCount
85
        {
86
            get { return sticks.Count; }
87
        }
88
 
89
        public IList<JoystickDevice> Joysticks
90
        {
91
            get { return sticks_readonly; }
92
        }
93
 
94
        public void Poll()
95
        {
96
            JoystickEvent e;
97
 
98
            foreach (JoystickDevice js in sticks)
99
            {
100
                unsafe
101
                {
102
                    while ((long)UnsafeNativeMethods.read(js.Id, (void*)&e, (UIntPtr)sizeof(JoystickEvent)) > 0)
103
                    {
104
                        e.Type &= ~JoystickEventType.Init;
105
 
106
                        switch (e.Type)
107
                        {
108
                            case JoystickEventType.Axis:
109
                                // Flip vertical axes so that +1 point up.
110
                                if (e.Number % 2 == 0)
111
                                    js.SetAxis((JoystickAxis)e.Number, e.Value / 32767.0f);
112
                                else
113
                                    js.SetAxis((JoystickAxis)e.Number, -e.Value / 32767.0f);
114
                                break;
115
 
116
                            case JoystickEventType.Button:
117
                                js.SetButton((JoystickButton)e.Number, e.Value != 0);
118
                                break;
119
                        }
120
                    }
121
                }
122
            }
123
        }
124
 
125
        #endregion
126
 
127
        #region Private Members
128
 
129
        JoystickDevice<X11JoyDetails> OpenJoystick(string base_path, int number)
130
        {
131
            string path = base_path + number.ToString();
132
            JoystickDevice<X11JoyDetails> stick = null;
133
 
134
            int fd = -1;
135
            try
136
            {
137
                fd = UnsafeNativeMethods.open(path, OpenFlags.NonBlock);
138
                if (fd == -1)
139
                    return null;
140
 
141
                // Check joystick driver version (must be 1.0+)
142
                int driver_version = 0x00000800;
143
                UnsafeNativeMethods.ioctl(fd, JoystickIoctlCode.Version, ref driver_version);
144
                if (driver_version < 0x00010000)
145
                    return null;
146
 
147
                // Get number of joystick axes
148
                int axes = 0;
149
                UnsafeNativeMethods.ioctl(fd, JoystickIoctlCode.Axes, ref axes);
150
 
151
                // Get number of joystick buttons
152
                int buttons = 0;
153
                UnsafeNativeMethods.ioctl(fd, JoystickIoctlCode.Buttons, ref buttons);
154
 
155
                stick = new JoystickDevice<X11JoyDetails>(fd, axes, buttons);
156
                Debug.Print("Found joystick on path {0}", path);
157
            }
158
            finally
159
            {
160
                if (stick == null && fd != -1)
161
                    UnsafeNativeMethods.close(fd);
162
            }
163
 
164
            return stick;
165
        }
166
 
167
        #region UnsafeNativeMethods
168
 
169
        struct JoystickEvent
170
        {
171
            public uint Time;    // (u32) event timestamp in milliseconds
172
            public short Value;  // (s16) value
173
            public JoystickEventType Type;    // (u8)  event type
174
            public byte Number;  // (u8)  axis/button number
175
        }
176
 
177
        [Flags]
178
        enum JoystickEventType : byte
179
        {
180
            Button = 0x01,    // button pressed/released
181
            Axis = 0x02,      // joystick moved
182
            Init = 0x80       // initial state of device
183
        }
184
 
185
        enum JoystickIoctlCode : uint
186
        {
187
            Version = 0x80046a01,
188
            Axes = 0x80016a11,
189
            Buttons = 0x80016a12
190
        }
191
 
192
        static readonly string JoystickPath = "/dev/input/js";
193
        static readonly string JoystickPathLegacy = "/dev/js";
194
 
195
        [Flags]
196
        enum OpenFlags
197
        {
198
            NonBlock = 0x00000800
199
        }
200
 
201
        static class UnsafeNativeMethods
202
        {
203
            [DllImport("libc", SetLastError = true)]
204
            public static extern int ioctl(int d, JoystickIoctlCode request, ref int data);
205
 
206
            [DllImport("libc", SetLastError = true)]
207
            public static extern int open([MarshalAs(UnmanagedType.LPStr)]string pathname, OpenFlags flags);
208
 
209
            [DllImport("libc", SetLastError = true)]
210
            public static extern int close(int fd);
211
 
212
            [DllImport("libc", SetLastError = true)]
213
            unsafe public static extern IntPtr read(int fd, void* buffer, UIntPtr count);
214
        }
215
 
216
        #endregion
217
 
218
        #endregion
219
 
220
        #region IDisposable Members
221
 
222
        public void Dispose()
223
        {
224
            Dispose(true);
225
            GC.SuppressFinalize(this);
226
        }
227
 
228
        void Dispose(bool manual)
229
        {
230
            if (!disposed)
231
            {
232
                if (manual)
233
                {
234
                }
235
 
236
                foreach (JoystickDevice js in sticks)
237
                {
238
                    UnsafeNativeMethods.close(js.Id);
239
                }
240
 
241
                disposed = true;
242
            }
243
        }
244
 
245
        ~X11Joystick()
246
        {
247
            Dispose(false);
248
        }
249
 
250
        #endregion
251
    }
252
}