root/Apple Wireless Keyboard Helper/trunk/Misuzilla.Applications.AppleWirelessKeyboardHelper/Helper.cs

Revision 677, 10.5 kB (checked in by tomoyo, 9 months ago)

* 一旦DLRのバージョンを戻した
* 新型USに対応したつもり

  • Property svn:keywords set to Id
Line 
1using System;
2using System.Diagnostics;
3using System.IO;
4using System.Runtime.InteropServices;
5using System.Windows.Forms;
6using Microsoft.Win32.SafeHandles;
7using WiimoteLib;
8
9namespace Misuzilla.Applications.AppleWirelessKeyboardHelper
10{
11    internal class Helper : IDisposable
12    {
13        public event EventHandler<AppleKeyboardEventArgs> FnKeyCombinationDown;
14        public event EventHandler<AppleKeyboardEventArgs> KeyDown;
15        public event EventHandler<AppleKeyboardEventArgs> KeyUp;
16        public event EventHandler<KeyEventArgs> SpecialKeyDown;
17
18        public event EventHandler Disconnected;
19
20        public Boolean CurrentPowerButtonIsDown;
21        public AppleKeyboardKeys CurrentKeyState;
22
23        private Stream _stream;
24        private Win32.HookHandle _hHook;
25
26        private const UInt32 VIDApple = 0x5ac;
27        private const UInt32 PIDAppleKeyboardJIS = 0x222;
28        private const UInt32 PIDAppleWirelessKeyboardUS = 0x22c;
29        private const UInt32 PIDAppleWirelessKeyboardUS_MC184LL = 0x239;
30        private const UInt32 PIDAppleWirelessKeyboardFR = 0x22d;
31        private const UInt32 PIDAppleWirelessKeyboardJIS = 0x22e;
32        private const UInt32 PIDAppleWirelessKeyboardJIS_MC184JA = 0x23b;
33        private const UInt32 PIDAppleKeyboardWithoutTenKeyUS = 0x21d;
34
35        /// <summary>
36        ///
37        /// </summary>
38        internal Boolean Start()
39        {
40            if (_stream != null)
41                throw new InvalidOperationException("�w���p�[�͂��łɎ�s���ł��B");
42
43            Guid guid;
44            HIDImports.HidD_GetHidGuid(out guid);
45
46            IntPtr hDevInfo = HIDImports.SetupDiGetClassDevs(ref guid, null, IntPtr.Zero, HIDImports.DIGCF_DEVICEINTERFACE);
47            HIDImports.SP_DEVICE_INTERFACE_DATA diData = new HIDImports.SP_DEVICE_INTERFACE_DATA();
48            diData.cbSize = Marshal.SizeOf(diData);
49
50            UInt32 index = 0;
51            while (HIDImports.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref guid, index++, ref diData))
52            {
53                HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA diDetail = new HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA();
54                diDetail.cbSize = (IntPtr.Size == 8) ? (UInt32)8 : 5; // x64:8, x86:5
55
56                UInt32 size;
57                HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, IntPtr.Zero, 0, out size, IntPtr.Zero);
58                if (HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, ref diDetail, size, out size, IntPtr.Zero))
59                {
60                    Debug.WriteLine("Device: " + diDetail.DevicePath); Debug.Indent();
61                    SafeFileHandle mHandle = HIDImports.CreateFile(diDetail.DevicePath, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, HIDImports.EFileAttributes.Overlapped, IntPtr.Zero);
62                    HIDImports.HIDD_ATTRIBUTES attrib = new HIDImports.HIDD_ATTRIBUTES();
63                    attrib.Size = Marshal.SizeOf(attrib);
64                    if (HIDImports.HidD_GetAttributes(mHandle.DangerousGetHandle(), ref attrib))
65                    {
66                        Debug.WriteLine(String.Format("VendorID:{0:x}, ProductID:{1:x}, VersionNumber:{2:x}", attrib.VendorID, attrib.ProductID, attrib.VersionNumber));
67                        if (attrib.VendorID == VIDApple &&
68                             (attrib.ProductID == PIDAppleWirelessKeyboardUS ||
69                              attrib.ProductID == PIDAppleWirelessKeyboardJIS ||
70                              attrib.ProductID == PIDAppleKeyboardJIS ||
71                              attrib.ProductID == PIDAppleWirelessKeyboardFR ||
72                              //attrib.ProductID == PIDAppleKeyboardWithoutTenKeyUS ||
73                              attrib.ProductID == PIDAppleWirelessKeyboardJIS_MC184JA ||
74                              attrib.ProductID == PIDAppleWirelessKeyboardUS_MC184LL
75                        ))
76                        {
77                            _stream = new FileStream(mHandle, FileAccess.ReadWrite, 22, true);
78                            //break;
79                        }
80                        else
81                        {
82                            mHandle.Close();
83                        }
84                    }
85                    Debug.Unindent();
86                }
87            }
88
89            if (_stream != null)
90            {
91                Byte[] buffer = new Byte[22];
92                _stream.BeginRead(buffer, 0, buffer.Length, SpecialKeyStateChanged, buffer);
93                return true;
94            }
95            else
96            {
97                // Not Connected
98                return false;
99            }
100        }
101
102        public Boolean Hook()
103        {
104            if (_hHook != null)
105                throw new InvalidOperationException("�t�b�N�͂��łɎ�s�������܂��B");
106
107            // hook
108            Win32.HookProcedure = KeyboardHookProc;
109            _hHook = Win32.SetWindowsHookEx(Win32.WH_KEYBOARD_LL, Win32.HookProcedure, Win32.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
110
111            return !_hHook.IsInvalid;
112        }
113
114        private void OnSpecialKeyDown()
115        {
116            if (SpecialKeyDown != null)
117                SpecialKeyDown(this, new KeyEventArgs(CurrentPowerButtonIsDown, CurrentKeyState));
118        }
119       
120        private void OnFnKeyCombinationDown(AppleKeyboardKeys appleKeyState, Keys key, Win32.KeyboardHookEventStruct keyEventStruct)
121        {
122            if (FnKeyCombinationDown != null)
123                FnKeyCombinationDown(this, new AppleKeyboardEventArgs(appleKeyState, key, keyEventStruct));
124        }
125       
126        private Boolean OnKeyDown(AppleKeyboardKeys appleKeyState, Keys key, Win32.KeyboardHookEventStruct keyEventStruct)
127        {
128            if (KeyDown != null)
129            {
130                AppleKeyboardEventArgs eArgs = new AppleKeyboardEventArgs(appleKeyState, key, keyEventStruct);
131                KeyDown(this, eArgs);
132                return eArgs.Handled;
133            }
134            else
135            {
136                return false;
137            }
138        }
139       
140        private Boolean OnKeyUp(AppleKeyboardKeys appleKeyState, Keys key, Win32.KeyboardHookEventStruct keyEventStruct)
141        {
142            if (KeyUp != null)
143            {
144                AppleKeyboardEventArgs eArgs = new AppleKeyboardEventArgs(appleKeyState, key, keyEventStruct);
145                KeyUp(this, eArgs);
146                return eArgs.Handled;
147            }
148            else
149            {
150                return false;
151            }
152        }
153
154        private IntPtr KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
155        {
156            Win32.KeyboardHookEventStruct keyEventStruct = (Win32.KeyboardHookEventStruct)Marshal.PtrToStructure(lParam, typeof(Win32.KeyboardHookEventStruct));
157            //Debug.WriteLine(String.Format("{0}, {1}, {2}", nCode, wParam, lParam));
158            Debug.WriteLine(keyEventStruct);
159           
160            switch ((Keys)keyEventStruct.wVk)
161            {
162                case Keys.LShiftKey:
163                case Keys.RShiftKey:
164                case Keys.LMenu:
165                case Keys.RMenu:
166                case Keys.LControlKey:
167                case Keys.RControlKey:
168                    return Win32.CallNextHookEx(_hHook, nCode, wParam, lParam);
169            }
170
171            // ���������������͖�������            if (keyEventStruct.dwExtraInfo != (IntPtr)0x37564)
172            {
173                Boolean handled = false;
174                switch ((Int32) wParam)
175                {
176                    case Win32.WM_KEYUP:
177                        handled = OnKeyUp(CurrentKeyState, Keys.None, keyEventStruct);
178                        break;
179                    case Win32.WM_KEYDOWN:
180                        handled = OnKeyDown(CurrentKeyState, Keys.None, keyEventStruct);
181                        break;
182                }
183                if (handled)
184                    return (IntPtr) 1;
185
186                if ((CurrentKeyState & AppleKeyboardKeys.Fn) == AppleKeyboardKeys.Fn)
187                {
188                    if ((Int32) wParam == Win32.WM_KEYDOWN || (Int32) wParam == Win32.WM_SYSKEYDOWN) // KEYDOWN
189                        OnFnKeyCombinationDown(CurrentKeyState, (Keys) keyEventStruct.wVk, keyEventStruct);
190                    //else if ((Int32)wParam == Win32.WM_KEYUP || (Int32)wParam == Win32.WM_SYSKEYUP) // KEYUP
191                    //    OnFnKeyCombinationUp(CurrentKeyState, (Keys)keyEventStruct.wVk, keyEventStruct);
192                    return (IntPtr) 1;
193                }
194            }
195            return Win32.CallNextHookEx(_hHook, nCode, wParam, lParam);
196        }
197
198        private void SpecialKeyStateChanged(IAsyncResult ar)
199        {
200            if (_stream == null || !ar.IsCompleted)
201                return;
202
203            try
204            {
205                _stream.EndRead(ar);
206            }
207            catch (OperationCanceledException) { }
208            catch (IOException ioe)
209            {
210                // restart (reconnected)
211                Debug.WriteLine("Restart: " + ioe.Message);
212                if (Disconnected != null)
213                    Disconnected(this, EventArgs.Empty);
214                return;
215            }
216
217            Byte[] buffer = ar.AsyncState as Byte[];
218            foreach (Byte b in buffer)
219                Debug.Write(String.Format("{0:x2} ", b));
220
221            if (buffer[0] == 0x11)
222            {
223                Debug.Write((AppleKeyboardKeys) buffer[1]);
224                CurrentKeyState = (AppleKeyboardKeys) buffer[1];
225            }
226            else if (buffer[0] == 0x13)
227            {
228                Debug.Write(buffer[1] == 1 ? "Power (Down)" : "Power (Up)");
229                CurrentPowerButtonIsDown = (buffer[1] == 1);
230            }
231
232            OnSpecialKeyDown();
233
234            Debug.WriteLine("");
235
236            _stream.BeginRead(buffer, 0, buffer.Length, SpecialKeyStateChanged, buffer);
237        }
238
239        public void Unhook()
240        {
241            if (_hHook != null && !_hHook.IsInvalid)
242            {
243                _hHook.Dispose();
244            }
245            _hHook = null;
246        }
247       
248        public void Shutdown()
249        {
250            if (_stream != null)
251            {
252                _stream.Close();
253                _stream = null;
254            }
255        }
256
257        #region IDisposable �����o
258
259        public void Dispose()
260        {
261            Unhook();
262            Shutdown();
263        }
264
265        #endregion
266    }
267}
Note: See TracBrowser for help on using the browser.