Copyright and namespace.
2 // Copyright (C) 2014-2015 Stéphane Lenclud.
4 // This file is part of SharpLibHid.
6 // SharpDisplayManager is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
11 // SharpDisplayManager is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with SharpDisplayManager. If not, see <http://www.gnu.org/licenses/>.
21 using System.Windows.Forms;
22 using System.Runtime.InteropServices;
23 using System.Diagnostics;
25 using Microsoft.Win32.SafeHandles;
27 using SharpLibHid.Usage;
32 namespace Devices.RemoteControl
35 public enum InputDevice
43 public enum RemoteControlButton
100 #region RemoteControlEventArgs
102 public class RemoteControlEventArgs : EventArgs
104 RemoteControlButton _rcb;
106 WindowsMediaCenterRemoteControl iMceButton;
107 ConsumerControl iConsumerControl;
109 public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
117 public RemoteControlEventArgs(ConsumerControl aConsumerControl, InputDevice device)
121 iConsumerControl = aConsumerControl;
126 public RemoteControlEventArgs(WindowsMediaCenterRemoteControl mce, InputDevice device)
134 private void SetNullButtons()
136 iConsumerControl = ConsumerControl.Null;
137 iMceButton = WindowsMediaCenterRemoteControl.Null;
138 _rcb = RemoteControlButton.Unknown;
141 public RemoteControlEventArgs()
143 iMceButton = WindowsMediaCenterRemoteControl.Null;
144 _rcb = RemoteControlButton.Unknown;
145 _device = InputDevice.Key;
148 public RemoteControlButton Button
151 set { _rcb = value; }
154 public WindowsMediaCenterRemoteControl MceButton
156 get { return iMceButton; }
157 set { iMceButton = value; }
160 public ConsumerControl ConsumerControl
162 get { return iConsumerControl; }
163 set { iConsumerControl = value; }
166 public InputDevice Device
168 get { return _device; }
169 set { _device = value; }
173 #endregion RemoteControlEventArgs
176 public sealed class RemoteControlDevice
178 public delegate bool RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
179 public event RemoteControlDeviceEventHandler ButtonPressed;
182 /// Return true if the usage was processed.
184 /// <param name="aUsage"></param>
185 /// <returns></returns>
186 public delegate bool HidUsageHandler(ushort aUsage);
188 public SharpLibHid.HidHandler iHidHandler;
191 //-------------------------------------------------------------
193 //-------------------------------------------------------------
195 public RemoteControlDevice(IntPtr aHWND)
197 // Register the input device to receive the commands from the
198 // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
199 // for the vendor defined usage page.
201 RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[6];
204 rid[i].usUsagePage = (ushort)SharpLibHid.UsagePage.WindowsMediaCenterRemoteControl;
205 rid[i].usUsage = (ushort)SharpLibHid.UsageCollection.WindowsMediaCenter.WindowsMediaCenterRemoteControl;
206 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
207 rid[i].hwndTarget = aHWND;
210 rid[i].usUsagePage = (ushort)SharpLibHid.UsagePage.Consumer;
211 rid[i].usUsage = (ushort)SharpLibHid.UsageCollection.Consumer.ConsumerControl;
212 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
213 rid[i].hwndTarget = aHWND;
216 rid[i].usUsagePage = (ushort)SharpLibHid.UsagePage.Consumer;
217 rid[i].usUsage = (ushort)SharpLibHid.UsageCollection.Consumer.Selection;
218 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
219 rid[i].hwndTarget = aHWND;
222 rid[i].usUsagePage = (ushort)SharpLibHid.UsagePage.GenericDesktopControls;
223 rid[i].usUsage = (ushort)SharpLibHid.UsageCollection.GenericDesktop.SystemControl;
224 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
225 rid[i].hwndTarget = aHWND;
228 rid[i].usUsagePage = (ushort)SharpLibHid.UsagePage.GenericDesktopControls;
229 rid[i].usUsage = (ushort)SharpLibHid.UsageCollection.GenericDesktop.GamePad;
230 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
231 rid[i].hwndTarget = aHWND;
234 rid[i].usUsagePage = (ushort)SharpLibHid.UsagePage.GenericDesktopControls;
235 rid[i].usUsage = (ushort)SharpLibHid.UsageCollection.GenericDesktop.Keyboard;
236 //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
237 rid[i].hwndTarget = aHWND;
240 //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
241 //rid[i].usUsage = (ushort)Hid.UsageCollection.GenericDesktop.Mouse;
242 //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
243 //rid[i].hwndTarget = aHWND;
246 iHidHandler = new SharpLibHid.HidHandler(rid);
247 if (!iHidHandler.IsRegistered)
249 Debug.WriteLine("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
251 iHidHandler.OnHidEvent += HandleHidEvent;
255 //-------------------------------------------------------------
257 //-------------------------------------------------------------
259 public void ProcessMessage(Message message)
263 case Const.WM_KEYDOWN:
264 ProcessKeyDown(message.WParam);
267 //Returning zero means we processed that message.
268 message.Result = new IntPtr(0);
269 ProcessInputCommand(ref message);
276 //-------------------------------------------------------------
278 //-------------------------------------------------------------
280 private void ProcessKeyDown(IntPtr wParam)
282 RemoteControlButton rcb = RemoteControlButton.Unknown;
284 switch (wParam.ToInt32())
286 case (int)Keys.Escape:
287 rcb = RemoteControlButton.Clear;
290 rcb = RemoteControlButton.Up;
293 rcb = RemoteControlButton.Down;
296 rcb = RemoteControlButton.Left;
298 case (int)Keys.Right:
299 rcb = RemoteControlButton.Right;
301 case (int)Keys.Enter:
302 rcb = RemoteControlButton.Enter;
305 rcb = RemoteControlButton.Digit0;
308 rcb = RemoteControlButton.Digit1;
311 rcb = RemoteControlButton.Digit2;
314 rcb = RemoteControlButton.Digit3;
317 rcb = RemoteControlButton.Digit4;
320 rcb = RemoteControlButton.Digit5;
323 rcb = RemoteControlButton.Digit6;
326 rcb = RemoteControlButton.Digit7;
329 rcb = RemoteControlButton.Digit8;
332 rcb = RemoteControlButton.Digit9;
336 if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
338 Debug.WriteLine("KeyDown: " + rcb.ToString());
339 this.ButtonPressed(this, new RemoteControlEventArgs(rcb, InputDevice.Key));
347 /// <param name="aUsage"></param>
348 private bool HidConsumerDeviceHandler(ushort aUsage)
356 if (Enum.IsDefined(typeof(ConsumerControl), aUsage) && aUsage != 0) //Our button is a known consumer control
358 if (this.ButtonPressed != null)
360 return this.ButtonPressed(this, new RemoteControlEventArgs((ConsumerControl)aUsage, InputDevice.OEM));
366 Debug.WriteLine("Unknown Consumer Control!");
374 /// <param name="aUsage"></param>
375 private bool HidMceRemoteHandler(ushort aUsage)
384 if (Enum.IsDefined(typeof(WindowsMediaCenterRemoteControl), aUsage) && aUsage != 0) //Our button is a known MCE button
386 if (this.ButtonPressed != null)
388 return this.ButtonPressed(this, new RemoteControlEventArgs((WindowsMediaCenterRemoteControl)aUsage, InputDevice.OEM));
394 Debug.WriteLine("Unknown MCE button!");
402 /// <param name="message"></param>
403 private void ProcessInputCommand(ref Message message)
405 //We received a WM_INPUT message
406 Debug.WriteLine("================WM_INPUT================");
408 iHidHandler.ProcessInput(message);
415 /// <param name="aSender"></param>
416 /// <param name="aHidEvent"></param>
417 void HandleHidEvent(object aSender, SharpLibHid.HidEvent aHidEvent)
419 HidUsageHandler usagePageHandler = null;
421 //Check if this an MCE remote HID message
422 if (aHidEvent.UsagePage == (ushort)SharpLibHid.UsagePage.WindowsMediaCenterRemoteControl && aHidEvent.UsageCollection == (ushort)SharpLibHid.UsageCollection.WindowsMediaCenter.WindowsMediaCenterRemoteControl)
424 usagePageHandler = HidMceRemoteHandler;
426 //Check if this is a consumer control HID message
427 else if (aHidEvent.UsagePage == (ushort)SharpLibHid.UsagePage.Consumer && aHidEvent.UsageCollection == (ushort)SharpLibHid.UsageCollection.Consumer.ConsumerControl)
429 usagePageHandler = HidConsumerDeviceHandler;
431 //Unknown HID message
434 Debug.WriteLine("Unknown HID message.");
438 foreach (ushort usage in aHidEvent.Usages)
440 usagePageHandler(usage);