RemoteControlDevice.cs
author sl
Sat, 06 Dec 2014 22:59:55 +0100
changeset 28 6af1cbb3beb4
parent 27 305d2ecd3b1a
child 29 7679a5ab194b
permissions -rw-r--r--
HID Usage Tables fixes.
sl@0
     1
using System;
sl@0
     2
using System.Windows.Forms;
sl@0
     3
using System.Runtime.InteropServices;
sl@0
     4
using System.Diagnostics;
sl@23
     5
using System.Text;
sl@24
     6
using Microsoft.Win32.SafeHandles;
sl@23
     7
sl@8
     8
using Hid.UsageTables;
sl@9
     9
using Win32;
sl@0
    10
sl@23
    11
sl@24
    12
sl@6
    13
namespace Devices.RemoteControl
sl@0
    14
{
sl@6
    15
sl@27
    16
    public enum InputDevice
sl@27
    17
    {
sl@27
    18
        Key,
sl@27
    19
        Mouse,
sl@27
    20
        OEM
sl@27
    21
    }
sl@0
    22
sl@0
    23
sl@27
    24
    public enum RemoteControlButton
sl@27
    25
    {
sl@27
    26
        Clear,
sl@27
    27
        Down,
sl@27
    28
        Left,
sl@27
    29
        Digit0,
sl@27
    30
        Digit1,
sl@27
    31
        Digit2,
sl@27
    32
        Digit3,
sl@27
    33
        Digit4,
sl@27
    34
        Digit5,
sl@27
    35
        Digit6,
sl@27
    36
        Digit7,
sl@27
    37
        Digit8,
sl@27
    38
        Digit9,
sl@27
    39
        Enter,
sl@27
    40
        Right,
sl@27
    41
        Up,
sl@0
    42
sl@27
    43
        Back,
sl@27
    44
        ChannelDown,
sl@27
    45
        ChannelUp,
sl@27
    46
        FastForward,
sl@27
    47
        VolumeMute,
sl@27
    48
        Pause,
sl@27
    49
        Play,
sl@0
    50
        PlayPause,
sl@27
    51
        Record,
sl@27
    52
        PreviousTrack,
sl@27
    53
        Rewind,
sl@27
    54
        NextTrack,
sl@27
    55
        Stop,
sl@27
    56
        VolumeDown,
sl@27
    57
        VolumeUp,
sl@0
    58
sl@27
    59
        RecordedTV,
sl@27
    60
        Guide,
sl@27
    61
        LiveTV,
sl@27
    62
        MoreInfo,
sl@12
    63
        Print,
sl@27
    64
        DVDMenu,
sl@27
    65
        DVDAngle,
sl@27
    66
        DVDAudio,
sl@27
    67
        DVDSubtitle,
sl@27
    68
        MyMusic,
sl@27
    69
        MyPictures,
sl@27
    70
        MyVideos,
sl@27
    71
        MyTV,
sl@27
    72
        OEM1,
sl@27
    73
        OEM2,
sl@27
    74
        StandBy,
sl@27
    75
        TVJump,
sl@0
    76
sl@27
    77
        Unknown
sl@27
    78
    }
sl@0
    79
sl@0
    80
sl@27
    81
    #region RemoteControlEventArgs
sl@0
    82
sl@27
    83
    public class RemoteControlEventArgs : EventArgs
sl@27
    84
    {
sl@3
    85
        RemoteControlButton _rcb;
sl@27
    86
        InputDevice _device;
sl@3
    87
        MceButton iMceButton;
sl@19
    88
        ConsumerControl iConsumerControl;
sl@0
    89
sl@3
    90
        public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
sl@27
    91
        {
sl@19
    92
            SetNullButtons();
sl@19
    93
            //
sl@27
    94
            _rcb = rcb;
sl@27
    95
            _device = device;
sl@27
    96
        }
sl@0
    97
sl@19
    98
        public RemoteControlEventArgs(ConsumerControl aConsumerControl, InputDevice device)
sl@19
    99
        {
sl@19
   100
            SetNullButtons();
sl@19
   101
            //
sl@27
   102
            iConsumerControl = aConsumerControl;
sl@19
   103
            _device = device;
sl@19
   104
        }
sl@19
   105
sl@19
   106
sl@3
   107
        public RemoteControlEventArgs(MceButton mce, InputDevice device)
sl@3
   108
        {
sl@19
   109
            SetNullButtons();
sl@19
   110
            //
sl@27
   111
            iMceButton = mce;
sl@19
   112
            _device = device;
sl@19
   113
        }
sl@19
   114
sl@19
   115
        private void SetNullButtons()
sl@19
   116
        {
sl@19
   117
            iConsumerControl = ConsumerControl.Null;
sl@19
   118
            iMceButton = MceButton.Null;
sl@3
   119
            _rcb = RemoteControlButton.Unknown;
sl@3
   120
        }
sl@0
   121
sl@27
   122
        public RemoteControlEventArgs()
sl@27
   123
        {
sl@3
   124
            iMceButton = MceButton.Null;
sl@27
   125
            _rcb = RemoteControlButton.Unknown;
sl@27
   126
            _device = InputDevice.Key;
sl@27
   127
        }
sl@0
   128
sl@27
   129
        public RemoteControlButton Button
sl@27
   130
        {
sl@27
   131
            get { return _rcb; }
sl@27
   132
            set { _rcb = value; }
sl@27
   133
        }
sl@0
   134
sl@3
   135
        public MceButton MceButton
sl@3
   136
        {
sl@3
   137
            get { return iMceButton; }
sl@3
   138
            set { iMceButton = value; }
sl@3
   139
        }
sl@3
   140
sl@19
   141
        public ConsumerControl ConsumerControl
sl@19
   142
        {
sl@19
   143
            get { return iConsumerControl; }
sl@19
   144
            set { iConsumerControl = value; }
sl@19
   145
        }
sl@19
   146
sl@27
   147
        public InputDevice Device
sl@27
   148
        {
sl@27
   149
            get { return _device; }
sl@27
   150
            set { _device = value; }
sl@27
   151
        }
sl@27
   152
    }
sl@0
   153
sl@27
   154
    #endregion RemoteControlEventArgs
sl@0
   155
sl@0
   156
sl@27
   157
    public sealed class RemoteControlDevice
sl@27
   158
    {
sl@27
   159
        public delegate bool RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
sl@27
   160
        public event RemoteControlDeviceEventHandler ButtonPressed;
sl@0
   161
sl@19
   162
        /// <summary>
sl@19
   163
        /// Return true if the usage was processed.
sl@19
   164
        /// </summary>
sl@19
   165
        /// <param name="aUsage"></param>
sl@19
   166
        /// <returns></returns>
sl@19
   167
        public delegate bool HidUsageHandler(ushort aUsage);
sl@12
   168
sl@0
   169
sl@27
   170
        //-------------------------------------------------------------
sl@27
   171
        // constructors
sl@27
   172
        //-------------------------------------------------------------
sl@0
   173
sl@27
   174
        public RemoteControlDevice(IntPtr aHWND)
sl@27
   175
        {
sl@27
   176
            // Register the input device to receive the commands from the
sl@27
   177
            // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
sl@27
   178
            // for the vendor defined usage page.
sl@27
   179
sl@27
   180
            RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[4];
sl@0
   181
sl@21
   182
            int i = 0;
sl@27
   183
            rid[i].usUsagePage = (ushort)Hid.UsagePage.MceRemote;
sl@21
   184
            rid[i].usUsage = (ushort)Hid.UsageIdMce.MceRemote;
sl@21
   185
            rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21
   186
            rid[i].hwndTarget = aHWND;
sl@0
   187
sl@21
   188
            i++;
sl@21
   189
            rid[i].usUsagePage = (ushort)Hid.UsagePage.Consumer;
sl@28
   190
            rid[i].usUsage = (ushort)Hid.UsageCollectionConsumer.ConsumerControl;
sl@21
   191
            rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21
   192
            rid[i].hwndTarget = aHWND;
sl@0
   193
sl@21
   194
            i++;
sl@21
   195
            rid[i].usUsagePage = (ushort)Hid.UsagePage.Consumer;
sl@28
   196
            rid[i].usUsage = (ushort)Hid.UsageCollectionConsumer.Selection;
sl@21
   197
            rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21
   198
            rid[i].hwndTarget = aHWND;
sl@21
   199
sl@22
   200
            i++;
sl@28
   201
            rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
sl@28
   202
            rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.SystemControl;
sl@22
   203
            rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@22
   204
            rid[i].hwndTarget = aHWND;
sl@21
   205
sl@27
   206
            //i++;
sl@28
   207
            //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
sl@28
   208
            //rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.Keyboard;
sl@27
   209
            //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@27
   210
            //rid[i].hwndTarget = aHWND;
sl@21
   211
sl@21
   212
            //i++;
sl@28
   213
            //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
sl@28
   214
            //rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.Mouse;
sl@21
   215
            //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21
   216
            //rid[i].hwndTarget = aHWND;
sl@21
   217
sl@0
   218
sl@27
   219
            if (!Function.RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0])))
sl@27
   220
            {
sl@15
   221
                throw new ApplicationException("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
sl@27
   222
            }
sl@27
   223
        }
sl@0
   224
sl@0
   225
sl@27
   226
        //-------------------------------------------------------------
sl@27
   227
        // methods
sl@27
   228
        //-------------------------------------------------------------
sl@0
   229
sl@27
   230
        public void ProcessMessage(Message message)
sl@27
   231
        {
sl@27
   232
            switch (message.Msg)
sl@27
   233
            {
sl@27
   234
                case Const.WM_KEYDOWN:
sl@15
   235
                    ProcessKeyDown(message.WParam);
sl@27
   236
                    break;
sl@15
   237
                case Const.WM_INPUT:
sl@19
   238
                    //Returning zero means we processed that message.
sl@19
   239
                    message.Result = new IntPtr(0);
sl@27
   240
                    ProcessInputCommand(ref message);
sl@27
   241
                    break;
sl@27
   242
            }
sl@0
   243
sl@27
   244
        }
sl@0
   245
sl@0
   246
sl@27
   247
        //-------------------------------------------------------------
sl@27
   248
        // methods (helpers)
sl@27
   249
        //-------------------------------------------------------------
sl@0
   250
sl@27
   251
        private void ProcessKeyDown(IntPtr wParam)
sl@27
   252
        {
sl@27
   253
            RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   254
sl@15
   255
            switch (wParam.ToInt32())
sl@27
   256
            {
sl@27
   257
                case (int)Keys.Escape:
sl@27
   258
                    rcb = RemoteControlButton.Clear;
sl@22
   259
                    break;
sl@22
   260
                case (int)Keys.Up:
sl@22
   261
                    rcb = RemoteControlButton.Up;
sl@22
   262
                    break;
sl@27
   263
                case (int)Keys.Down:
sl@27
   264
                    rcb = RemoteControlButton.Down;
sl@27
   265
                    break;
sl@27
   266
                case (int)Keys.Left:
sl@27
   267
                    rcb = RemoteControlButton.Left;
sl@22
   268
                    break;
sl@22
   269
                case (int)Keys.Right:
sl@22
   270
                    rcb = RemoteControlButton.Right;
sl@22
   271
                    break;
sl@22
   272
                case (int)Keys.Enter:
sl@22
   273
                    rcb = RemoteControlButton.Enter;
sl@22
   274
                    break;
sl@27
   275
                case (int)Keys.D0:
sl@27
   276
                    rcb = RemoteControlButton.Digit0;
sl@22
   277
                    break;
sl@27
   278
                case (int)Keys.D1:
sl@27
   279
                    rcb = RemoteControlButton.Digit1;
sl@27
   280
                    break;
sl@27
   281
                case (int)Keys.D2:
sl@27
   282
                    rcb = RemoteControlButton.Digit2;
sl@27
   283
                    break;
sl@27
   284
                case (int)Keys.D3:
sl@27
   285
                    rcb = RemoteControlButton.Digit3;
sl@27
   286
                    break;
sl@27
   287
                case (int)Keys.D4:
sl@27
   288
                    rcb = RemoteControlButton.Digit4;
sl@27
   289
                    break;
sl@27
   290
                case (int)Keys.D5:
sl@27
   291
                    rcb = RemoteControlButton.Digit5;
sl@27
   292
                    break;
sl@27
   293
                case (int)Keys.D6:
sl@27
   294
                    rcb = RemoteControlButton.Digit6;
sl@27
   295
                    break;
sl@27
   296
                case (int)Keys.D7:
sl@27
   297
                    rcb = RemoteControlButton.Digit7;
sl@27
   298
                    break;
sl@27
   299
                case (int)Keys.D8:
sl@27
   300
                    rcb = RemoteControlButton.Digit8;
sl@27
   301
                    break;
sl@27
   302
                case (int)Keys.D9:
sl@27
   303
                    rcb = RemoteControlButton.Digit9;
sl@27
   304
                    break;
sl@27
   305
            }
sl@0
   306
sl@22
   307
            if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
sl@22
   308
            {
sl@22
   309
                Debug.WriteLine("KeyDown: " + rcb.ToString());
sl@20
   310
                this.ButtonPressed(this, new RemoteControlEventArgs(rcb, InputDevice.Key));
sl@22
   311
            }
sl@27
   312
        }
sl@0
   313
sl@0
   314
sl@12
   315
        /// <summary>
sl@12
   316
        /// 
sl@12
   317
        /// </summary>
sl@12
   318
        /// <param name="aUsage"></param>
sl@19
   319
        private bool HidConsumerDeviceHandler(ushort aUsage)
sl@12
   320
        {
sl@12
   321
            if (aUsage == 0)
sl@12
   322
            {
sl@12
   323
                //Just skip those
sl@19
   324
                return false;
sl@12
   325
            }
sl@12
   326
sl@12
   327
            if (Enum.IsDefined(typeof(ConsumerControl), aUsage) && aUsage != 0) //Our button is a known consumer control
sl@12
   328
            {
sl@12
   329
                if (this.ButtonPressed != null)
sl@12
   330
                {
sl@19
   331
                    return this.ButtonPressed(this, new RemoteControlEventArgs((ConsumerControl)aUsage, InputDevice.OEM));
sl@12
   332
                }
sl@19
   333
                return false;
sl@12
   334
            }
sl@12
   335
            else
sl@12
   336
            {
sl@12
   337
                Debug.WriteLine("Unknown Consumer Control!");
sl@19
   338
                return false;
sl@12
   339
            }
sl@12
   340
        }
sl@12
   341
sl@12
   342
        /// <summary>
sl@12
   343
        /// 
sl@12
   344
        /// </summary>
sl@12
   345
        /// <param name="aUsage"></param>
sl@19
   346
        private bool HidMceRemoteHandler(ushort aUsage)
sl@12
   347
        {
sl@12
   348
            if (aUsage == 0)
sl@12
   349
            {
sl@12
   350
                //Just skip those
sl@19
   351
                return false;
sl@12
   352
            }
sl@12
   353
sl@12
   354
sl@12
   355
            if (Enum.IsDefined(typeof(MceButton), aUsage) && aUsage != 0) //Our button is a known MCE button
sl@12
   356
            {
sl@12
   357
                if (this.ButtonPressed != null)
sl@12
   358
                {
sl@27
   359
                    return this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)aUsage, InputDevice.OEM));
sl@12
   360
                }
sl@19
   361
                return false;
sl@12
   362
            }
sl@12
   363
            else
sl@12
   364
            {
sl@12
   365
                Debug.WriteLine("Unknown MCE button!");
sl@19
   366
                return false;
sl@12
   367
            }
sl@12
   368
        }
sl@12
   369
sl@0
   370
sl@27
   371
        private void ProcessInputCommand(ref Message message)
sl@27
   372
        {
sl@15
   373
            //We received a WM_INPUT message
sl@7
   374
            Debug.WriteLine("================WM_INPUT================");
sl@6
   375
sl@27
   376
            Hid.HidEvent hidEvent = new Hid.HidEvent(message);
sl@27
   377
            hidEvent.DebugWrite();
sl@27
   378
sl@27
   379
            if (!hidEvent.IsValid || !hidEvent.IsGeneric)
sl@15
   380
            {
sl@27
   381
                Debug.WriteLine("Skipping HID message.");
sl@27
   382
                return;
sl@15
   383
            }
sl@0
   384
sl@0
   385
sl@27
   386
            HidUsageHandler usagePageHandler = null;
sl@27
   387
sl@27
   388
            //Check if this an MCE remote HID message
sl@27
   389
            if (hidEvent.UsagePage == (ushort)Hid.UsagePage.MceRemote && hidEvent.UsageCollection == (ushort)Hid.UsageIdMce.MceRemote)
sl@10
   390
            {
sl@27
   391
                usagePageHandler = HidMceRemoteHandler;
sl@27
   392
            }
sl@27
   393
            //Check if this is a consumer control HID message
sl@28
   394
            else if (hidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer && hidEvent.UsageCollection == (ushort)Hid.UsageCollectionConsumer.ConsumerControl)
sl@27
   395
            {
sl@27
   396
                usagePageHandler = HidConsumerDeviceHandler;
sl@27
   397
            }
sl@27
   398
            //Unknown HID message
sl@27
   399
            else
sl@27
   400
            {
sl@27
   401
                Debug.WriteLine("Unknown HID message.");
sl@27
   402
                return;
sl@27
   403
            }
sl@6
   404
sl@27
   405
            foreach (ushort usage in hidEvent.Usages)
sl@27
   406
            {
sl@27
   407
                usagePageHandler(usage);
sl@27
   408
            }
sl@27
   409
        }
sl@27
   410
    }
sl@27
   411
}
sl@23
   412