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: