sl@0: using System;
sl@0: using System.Windows.Forms;
sl@0: using System.Runtime.InteropServices;
sl@0: using System.Diagnostics;
sl@23: using System.Text;
sl@24: using Microsoft.Win32.SafeHandles;
sl@23:
sl@8: using Hid.UsageTables;
sl@9: using Win32;
sl@0:
sl@23:
sl@24:
sl@6: namespace Devices.RemoteControl
sl@0: {
sl@6:
sl@27: public enum InputDevice
sl@27: {
sl@27: Key,
sl@27: Mouse,
sl@27: OEM
sl@27: }
sl@0:
sl@0:
sl@27: public enum RemoteControlButton
sl@27: {
sl@27: Clear,
sl@27: Down,
sl@27: Left,
sl@27: Digit0,
sl@27: Digit1,
sl@27: Digit2,
sl@27: Digit3,
sl@27: Digit4,
sl@27: Digit5,
sl@27: Digit6,
sl@27: Digit7,
sl@27: Digit8,
sl@27: Digit9,
sl@27: Enter,
sl@27: Right,
sl@27: Up,
sl@0:
sl@27: Back,
sl@27: ChannelDown,
sl@27: ChannelUp,
sl@27: FastForward,
sl@27: VolumeMute,
sl@27: Pause,
sl@27: Play,
sl@0: PlayPause,
sl@27: Record,
sl@27: PreviousTrack,
sl@27: Rewind,
sl@27: NextTrack,
sl@27: Stop,
sl@27: VolumeDown,
sl@27: VolumeUp,
sl@0:
sl@27: RecordedTV,
sl@27: Guide,
sl@27: LiveTV,
sl@27: MoreInfo,
sl@12: Print,
sl@27: DVDMenu,
sl@27: DVDAngle,
sl@27: DVDAudio,
sl@27: DVDSubtitle,
sl@27: MyMusic,
sl@27: MyPictures,
sl@27: MyVideos,
sl@27: MyTV,
sl@27: OEM1,
sl@27: OEM2,
sl@27: StandBy,
sl@27: TVJump,
sl@0:
sl@27: Unknown
sl@27: }
sl@0:
sl@0:
sl@27: #region RemoteControlEventArgs
sl@0:
sl@27: public class RemoteControlEventArgs : EventArgs
sl@27: {
sl@3: RemoteControlButton _rcb;
sl@27: InputDevice _device;
sl@3: MceButton iMceButton;
sl@19: ConsumerControl iConsumerControl;
sl@0:
sl@3: public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
sl@27: {
sl@19: SetNullButtons();
sl@19: //
sl@27: _rcb = rcb;
sl@27: _device = device;
sl@27: }
sl@0:
sl@19: public RemoteControlEventArgs(ConsumerControl aConsumerControl, InputDevice device)
sl@19: {
sl@19: SetNullButtons();
sl@19: //
sl@27: iConsumerControl = aConsumerControl;
sl@19: _device = device;
sl@19: }
sl@19:
sl@19:
sl@3: public RemoteControlEventArgs(MceButton mce, InputDevice device)
sl@3: {
sl@19: SetNullButtons();
sl@19: //
sl@27: iMceButton = mce;
sl@19: _device = device;
sl@19: }
sl@19:
sl@19: private void SetNullButtons()
sl@19: {
sl@19: iConsumerControl = ConsumerControl.Null;
sl@19: iMceButton = MceButton.Null;
sl@3: _rcb = RemoteControlButton.Unknown;
sl@3: }
sl@0:
sl@27: public RemoteControlEventArgs()
sl@27: {
sl@3: iMceButton = MceButton.Null;
sl@27: _rcb = RemoteControlButton.Unknown;
sl@27: _device = InputDevice.Key;
sl@27: }
sl@0:
sl@27: public RemoteControlButton Button
sl@27: {
sl@27: get { return _rcb; }
sl@27: set { _rcb = value; }
sl@27: }
sl@0:
sl@3: public MceButton MceButton
sl@3: {
sl@3: get { return iMceButton; }
sl@3: set { iMceButton = value; }
sl@3: }
sl@3:
sl@19: public ConsumerControl ConsumerControl
sl@19: {
sl@19: get { return iConsumerControl; }
sl@19: set { iConsumerControl = value; }
sl@19: }
sl@19:
sl@27: public InputDevice Device
sl@27: {
sl@27: get { return _device; }
sl@27: set { _device = value; }
sl@27: }
sl@27: }
sl@0:
sl@27: #endregion RemoteControlEventArgs
sl@0:
sl@0:
sl@27: public sealed class RemoteControlDevice
sl@27: {
sl@27: public delegate bool RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
sl@27: public event RemoteControlDeviceEventHandler ButtonPressed;
sl@0:
sl@19: ///
sl@19: /// Return true if the usage was processed.
sl@19: ///
sl@19: ///
sl@19: ///
sl@19: public delegate bool HidUsageHandler(ushort aUsage);
sl@12:
sl@0:
sl@27: //-------------------------------------------------------------
sl@27: // constructors
sl@27: //-------------------------------------------------------------
sl@0:
sl@27: public RemoteControlDevice(IntPtr aHWND)
sl@27: {
sl@27: // Register the input device to receive the commands from the
sl@27: // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
sl@27: // for the vendor defined usage page.
sl@27:
sl@27: RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[4];
sl@0:
sl@21: int i = 0;
sl@27: rid[i].usUsagePage = (ushort)Hid.UsagePage.MceRemote;
sl@21: rid[i].usUsage = (ushort)Hid.UsageIdMce.MceRemote;
sl@21: rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21: rid[i].hwndTarget = aHWND;
sl@0:
sl@21: i++;
sl@21: rid[i].usUsagePage = (ushort)Hid.UsagePage.Consumer;
sl@28: rid[i].usUsage = (ushort)Hid.UsageCollectionConsumer.ConsumerControl;
sl@21: rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21: rid[i].hwndTarget = aHWND;
sl@0:
sl@21: i++;
sl@21: rid[i].usUsagePage = (ushort)Hid.UsagePage.Consumer;
sl@28: rid[i].usUsage = (ushort)Hid.UsageCollectionConsumer.Selection;
sl@21: rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21: rid[i].hwndTarget = aHWND;
sl@21:
sl@22: i++;
sl@28: rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
sl@28: rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.SystemControl;
sl@22: rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@22: rid[i].hwndTarget = aHWND;
sl@21:
sl@27: //i++;
sl@28: //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
sl@28: //rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.Keyboard;
sl@27: //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@27: //rid[i].hwndTarget = aHWND;
sl@21:
sl@21: //i++;
sl@28: //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
sl@28: //rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.Mouse;
sl@21: //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21: //rid[i].hwndTarget = aHWND;
sl@21:
sl@0:
sl@27: if (!Function.RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0])))
sl@27: {
sl@15: throw new ApplicationException("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
sl@27: }
sl@27: }
sl@0:
sl@0:
sl@27: //-------------------------------------------------------------
sl@27: // methods
sl@27: //-------------------------------------------------------------
sl@0:
sl@27: public void ProcessMessage(Message message)
sl@27: {
sl@27: switch (message.Msg)
sl@27: {
sl@27: case Const.WM_KEYDOWN:
sl@15: ProcessKeyDown(message.WParam);
sl@27: break;
sl@15: case Const.WM_INPUT:
sl@19: //Returning zero means we processed that message.
sl@19: message.Result = new IntPtr(0);
sl@27: ProcessInputCommand(ref message);
sl@27: break;
sl@27: }
sl@0:
sl@27: }
sl@0:
sl@0:
sl@27: //-------------------------------------------------------------
sl@27: // methods (helpers)
sl@27: //-------------------------------------------------------------
sl@0:
sl@27: private void ProcessKeyDown(IntPtr wParam)
sl@27: {
sl@27: RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0:
sl@15: switch (wParam.ToInt32())
sl@27: {
sl@27: case (int)Keys.Escape:
sl@27: rcb = RemoteControlButton.Clear;
sl@22: break;
sl@22: case (int)Keys.Up:
sl@22: rcb = RemoteControlButton.Up;
sl@22: break;
sl@27: case (int)Keys.Down:
sl@27: rcb = RemoteControlButton.Down;
sl@27: break;
sl@27: case (int)Keys.Left:
sl@27: rcb = RemoteControlButton.Left;
sl@22: break;
sl@22: case (int)Keys.Right:
sl@22: rcb = RemoteControlButton.Right;
sl@22: break;
sl@22: case (int)Keys.Enter:
sl@22: rcb = RemoteControlButton.Enter;
sl@22: break;
sl@27: case (int)Keys.D0:
sl@27: rcb = RemoteControlButton.Digit0;
sl@22: break;
sl@27: case (int)Keys.D1:
sl@27: rcb = RemoteControlButton.Digit1;
sl@27: break;
sl@27: case (int)Keys.D2:
sl@27: rcb = RemoteControlButton.Digit2;
sl@27: break;
sl@27: case (int)Keys.D3:
sl@27: rcb = RemoteControlButton.Digit3;
sl@27: break;
sl@27: case (int)Keys.D4:
sl@27: rcb = RemoteControlButton.Digit4;
sl@27: break;
sl@27: case (int)Keys.D5:
sl@27: rcb = RemoteControlButton.Digit5;
sl@27: break;
sl@27: case (int)Keys.D6:
sl@27: rcb = RemoteControlButton.Digit6;
sl@27: break;
sl@27: case (int)Keys.D7:
sl@27: rcb = RemoteControlButton.Digit7;
sl@27: break;
sl@27: case (int)Keys.D8:
sl@27: rcb = RemoteControlButton.Digit8;
sl@27: break;
sl@27: case (int)Keys.D9:
sl@27: rcb = RemoteControlButton.Digit9;
sl@27: break;
sl@27: }
sl@0:
sl@22: if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
sl@22: {
sl@22: Debug.WriteLine("KeyDown: " + rcb.ToString());
sl@20: this.ButtonPressed(this, new RemoteControlEventArgs(rcb, InputDevice.Key));
sl@22: }
sl@27: }
sl@0:
sl@0:
sl@12: ///
sl@12: ///
sl@12: ///
sl@12: ///
sl@19: private bool HidConsumerDeviceHandler(ushort aUsage)
sl@12: {
sl@12: if (aUsage == 0)
sl@12: {
sl@12: //Just skip those
sl@19: return false;
sl@12: }
sl@12:
sl@12: if (Enum.IsDefined(typeof(ConsumerControl), aUsage) && aUsage != 0) //Our button is a known consumer control
sl@12: {
sl@12: if (this.ButtonPressed != null)
sl@12: {
sl@19: return this.ButtonPressed(this, new RemoteControlEventArgs((ConsumerControl)aUsage, InputDevice.OEM));
sl@12: }
sl@19: return false;
sl@12: }
sl@12: else
sl@12: {
sl@12: Debug.WriteLine("Unknown Consumer Control!");
sl@19: return false;
sl@12: }
sl@12: }
sl@12:
sl@12: ///
sl@12: ///
sl@12: ///
sl@12: ///
sl@19: private bool HidMceRemoteHandler(ushort aUsage)
sl@12: {
sl@12: if (aUsage == 0)
sl@12: {
sl@12: //Just skip those
sl@19: return false;
sl@12: }
sl@12:
sl@12:
sl@12: if (Enum.IsDefined(typeof(MceButton), aUsage) && aUsage != 0) //Our button is a known MCE button
sl@12: {
sl@12: if (this.ButtonPressed != null)
sl@12: {
sl@27: return this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)aUsage, InputDevice.OEM));
sl@12: }
sl@19: return false;
sl@12: }
sl@12: else
sl@12: {
sl@12: Debug.WriteLine("Unknown MCE button!");
sl@19: return false;
sl@12: }
sl@12: }
sl@12:
sl@0:
sl@27: private void ProcessInputCommand(ref Message message)
sl@27: {
sl@15: //We received a WM_INPUT message
sl@7: Debug.WriteLine("================WM_INPUT================");
sl@6:
sl@27: Hid.HidEvent hidEvent = new Hid.HidEvent(message);
sl@27: hidEvent.DebugWrite();
sl@27:
sl@27: if (!hidEvent.IsValid || !hidEvent.IsGeneric)
sl@15: {
sl@27: Debug.WriteLine("Skipping HID message.");
sl@27: return;
sl@15: }
sl@0:
sl@0:
sl@27: HidUsageHandler usagePageHandler = null;
sl@27:
sl@27: //Check if this an MCE remote HID message
sl@27: if (hidEvent.UsagePage == (ushort)Hid.UsagePage.MceRemote && hidEvent.UsageCollection == (ushort)Hid.UsageIdMce.MceRemote)
sl@10: {
sl@27: usagePageHandler = HidMceRemoteHandler;
sl@27: }
sl@27: //Check if this is a consumer control HID message
sl@28: else if (hidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer && hidEvent.UsageCollection == (ushort)Hid.UsageCollectionConsumer.ConsumerControl)
sl@27: {
sl@27: usagePageHandler = HidConsumerDeviceHandler;
sl@27: }
sl@27: //Unknown HID message
sl@27: else
sl@27: {
sl@27: Debug.WriteLine("Unknown HID message.");
sl@27: return;
sl@27: }
sl@6:
sl@27: foreach (ushort usage in hidEvent.Usages)
sl@27: {
sl@27: usagePageHandler(usage);
sl@27: }
sl@27: }
sl@27: }
sl@27: }
sl@23: