RemoteControlDevice.cs
author sl
Sat, 06 Dec 2014 12:13:39 +0100
changeset 24 974f5fdaebfb
parent 23 743cadfacda0
child 25 5f4e0fbb3ea1
permissions -rw-r--r--
Now getting manufacturer and product name.
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@0
    16
	public enum InputDevice
sl@0
    17
	{
sl@0
    18
		Key,
sl@0
    19
		Mouse,
sl@0
    20
		OEM
sl@0
    21
	}
sl@0
    22
sl@0
    23
sl@0
    24
	public enum RemoteControlButton
sl@0
    25
	{
sl@0
    26
		Clear,
sl@0
    27
		Down,
sl@0
    28
		Left,
sl@0
    29
		Digit0,
sl@0
    30
		Digit1,
sl@0
    31
		Digit2,
sl@0
    32
		Digit3,
sl@0
    33
		Digit4,
sl@0
    34
		Digit5,
sl@0
    35
		Digit6,
sl@0
    36
		Digit7,
sl@0
    37
		Digit8,
sl@0
    38
		Digit9,
sl@0
    39
		Enter,
sl@0
    40
		Right,
sl@0
    41
		Up,
sl@0
    42
sl@0
    43
		Back,
sl@0
    44
		ChannelDown,
sl@0
    45
		ChannelUp,
sl@0
    46
		FastForward,
sl@0
    47
		VolumeMute,
sl@0
    48
		Pause,
sl@0
    49
		Play,
sl@0
    50
        PlayPause,
sl@0
    51
		Record,
sl@0
    52
		PreviousTrack,
sl@0
    53
		Rewind,
sl@0
    54
		NextTrack,
sl@0
    55
		Stop,
sl@0
    56
		VolumeDown,
sl@0
    57
		VolumeUp,
sl@0
    58
sl@0
    59
		RecordedTV,
sl@0
    60
		Guide,
sl@0
    61
		LiveTV,
sl@12
    62
		MoreInfo,
sl@12
    63
        Print,
sl@0
    64
		DVDMenu,
sl@0
    65
		DVDAngle,
sl@0
    66
		DVDAudio,
sl@0
    67
		DVDSubtitle,
sl@0
    68
		MyMusic,
sl@0
    69
		MyPictures,
sl@0
    70
		MyVideos,
sl@0
    71
		MyTV,
sl@0
    72
		OEM1,
sl@0
    73
		OEM2,
sl@0
    74
		StandBy,
sl@0
    75
		TVJump,
sl@0
    76
sl@0
    77
		Unknown
sl@0
    78
	}
sl@0
    79
sl@0
    80
sl@0
    81
	#region RemoteControlEventArgs
sl@0
    82
sl@0
    83
	public class RemoteControlEventArgs : EventArgs
sl@0
    84
	{
sl@3
    85
        RemoteControlButton _rcb;
sl@0
    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@0
    91
		{
sl@19
    92
            SetNullButtons();
sl@19
    93
            //
sl@0
    94
			_rcb = rcb;
sl@19
    95
			_device = device;            
sl@0
    96
		}
sl@0
    97
sl@19
    98
        public RemoteControlEventArgs(ConsumerControl aConsumerControl, InputDevice device)
sl@19
    99
        {
sl@19
   100
            SetNullButtons();
sl@19
   101
            //
sl@19
   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@19
   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@0
   122
		public RemoteControlEventArgs()
sl@0
   123
		{
sl@3
   124
            iMceButton = MceButton.Null;
sl@0
   125
			_rcb = RemoteControlButton.Unknown;
sl@0
   126
			_device = InputDevice.Key;
sl@0
   127
		}
sl@0
   128
sl@0
   129
		public RemoteControlButton Button
sl@0
   130
		{
sl@0
   131
			get { return _rcb;  }
sl@0
   132
			set { _rcb = value; }
sl@0
   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@0
   147
		public InputDevice Device
sl@0
   148
		{
sl@0
   149
			get { return _device;  }
sl@0
   150
			set { _device = value; }
sl@0
   151
		}
sl@0
   152
	}
sl@0
   153
sl@0
   154
	#endregion RemoteControlEventArgs
sl@0
   155
sl@0
   156
sl@0
   157
	public sealed class RemoteControlDevice
sl@0
   158
	{
sl@19
   159
		public delegate bool RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
sl@0
   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@12
   169
sl@0
   170
		//-------------------------------------------------------------
sl@0
   171
		// constructors
sl@0
   172
		//-------------------------------------------------------------
sl@0
   173
sl@15
   174
		public RemoteControlDevice(IntPtr aHWND)
sl@0
   175
		{
sl@0
   176
			// Register the input device to receive the commands from the
sl@0
   177
			// remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
sl@0
   178
			// for the vendor defined usage page.
sl@0
   179
sl@22
   180
			RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[5];
sl@0
   181
sl@21
   182
            int i = 0;
sl@21
   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@21
   190
            rid[i].usUsage = (ushort)Hid.UsageIdConsumer.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@21
   196
            rid[i].usUsage = (ushort)Hid.UsageIdConsumer.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@22
   201
            rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
sl@22
   202
            rid[i].usUsage = (ushort)Hid.UsageIdGenericDesktop.SystemControl;
sl@22
   203
            rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@22
   204
            rid[i].hwndTarget = aHWND;
sl@21
   205
sl@22
   206
            i++;
sl@22
   207
            rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
sl@22
   208
            rid[i].usUsage = (ushort)Hid.UsageIdGenericDesktop.Keyboard;
sl@22
   209
            rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@22
   210
            rid[i].hwndTarget = aHWND;
sl@21
   211
sl@21
   212
            //i++;
sl@21
   213
            //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
sl@21
   214
            //rid[i].usUsage = (ushort)Hid.UsageIdGenericDesktop.Mouse;
sl@21
   215
            //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21
   216
            //rid[i].hwndTarget = aHWND;
sl@21
   217
sl@0
   218
sl@15
   219
			if (!Function.RegisterRawInputDevices(rid,(uint) rid.Length,(uint) Marshal.SizeOf(rid[0])))
sl@0
   220
			{
sl@15
   221
                throw new ApplicationException("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
sl@0
   222
			}
sl@0
   223
		}
sl@0
   224
sl@0
   225
sl@0
   226
		//-------------------------------------------------------------
sl@0
   227
		// methods
sl@0
   228
		//-------------------------------------------------------------
sl@0
   229
sl@0
   230
		public void ProcessMessage(Message message)
sl@0
   231
		{
sl@0
   232
			switch (message.Msg)
sl@0
   233
			{
sl@15
   234
				case Const.WM_KEYDOWN:
sl@15
   235
                    ProcessKeyDown(message.WParam);
sl@0
   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@0
   240
					ProcessInputCommand(ref message);
sl@0
   241
					break;
sl@0
   242
			}
sl@0
   243
sl@0
   244
		}
sl@0
   245
sl@0
   246
sl@0
   247
		//-------------------------------------------------------------
sl@0
   248
		// methods (helpers)
sl@0
   249
		//-------------------------------------------------------------
sl@0
   250
sl@15
   251
		private void ProcessKeyDown(IntPtr wParam)
sl@0
   252
		{
sl@0
   253
			RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   254
sl@15
   255
            switch (wParam.ToInt32())
sl@0
   256
			{
sl@0
   257
				case (int) Keys.Escape:
sl@0
   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@0
   263
				case (int) Keys.Down:
sl@0
   264
					rcb = RemoteControlButton.Down;
sl@0
   265
					break;
sl@0
   266
				case (int) Keys.Left:
sl@0
   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@0
   275
				case (int) Keys.D0:
sl@0
   276
					rcb = RemoteControlButton.Digit0;
sl@0
   277
					break;
sl@0
   278
				case (int) Keys.D1:
sl@0
   279
					rcb = RemoteControlButton.Digit1;
sl@0
   280
					break;
sl@0
   281
				case (int) Keys.D2:
sl@0
   282
					rcb = RemoteControlButton.Digit2;
sl@0
   283
					break;
sl@0
   284
				case (int) Keys.D3:
sl@0
   285
					rcb = RemoteControlButton.Digit3;
sl@0
   286
					break;
sl@0
   287
				case (int) Keys.D4:
sl@0
   288
					rcb = RemoteControlButton.Digit4;
sl@0
   289
					break;
sl@0
   290
				case (int) Keys.D5:
sl@0
   291
					rcb = RemoteControlButton.Digit5;
sl@0
   292
					break;
sl@0
   293
				case (int) Keys.D6:
sl@0
   294
					rcb = RemoteControlButton.Digit6;
sl@0
   295
					break;
sl@0
   296
				case (int) Keys.D7:
sl@0
   297
					rcb = RemoteControlButton.Digit7;
sl@0
   298
					break;
sl@0
   299
				case (int) Keys.D8:
sl@0
   300
					rcb = RemoteControlButton.Digit8;
sl@0
   301
					break;
sl@0
   302
				case (int) Keys.D9:
sl@0
   303
					rcb = RemoteControlButton.Digit9;
sl@22
   304
                    break;
sl@0
   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@0
   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@19
   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@0
   371
		private void ProcessInputCommand(ref Message message)
sl@0
   372
		{
sl@15
   373
            //We received a WM_INPUT message
sl@7
   374
            Debug.WriteLine("================WM_INPUT================");
sl@6
   375
sl@15
   376
            //Check if we received this message while in background or foreground
sl@15
   377
            if (Macro.GET_RAWINPUT_CODE_WPARAM(message.WParam) == Const.RIM_INPUT)
sl@15
   378
            {
sl@15
   379
                Debug.WriteLine("================FOREGROUND");
sl@15
   380
            }
sl@15
   381
            else if (Macro.GET_RAWINPUT_CODE_WPARAM(message.WParam) == Const.RIM_INPUTSINK)
sl@15
   382
            {
sl@15
   383
                Debug.WriteLine("================BACKGROUND");
sl@15
   384
            }
sl@0
   385
sl@17
   386
            //Declare some pointers
sl@10
   387
            IntPtr rawInputBuffer = IntPtr.Zero;
sl@17
   388
            //My understanding is that this is basically our HID descriptor
sl@17
   389
            IntPtr preParsedData = IntPtr.Zero;
sl@0
   390
sl@10
   391
            try
sl@10
   392
            {
sl@10
   393
                //Fetch raw input
sl@11
   394
                RAWINPUT rawInput = new RAWINPUT();
sl@11
   395
                if (!RawInput.GetRawInputData(message.LParam, ref rawInput, ref rawInputBuffer))
sl@6
   396
                {
sl@6
   397
                    return;
sl@6
   398
                }
sl@6
   399
sl@23
   400
sl@23
   401
sl@10
   402
                //Fetch device info
sl@10
   403
                RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO();
sl@11
   404
                if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
sl@10
   405
                {
sl@10
   406
                    return;
sl@10
   407
                }
sl@22
   408
sl@24
   409
                //Debug
sl@24
   410
                string deviceName = RawInput.GetDeviceName(rawInput.header.hDevice);
sl@24
   411
                Debug.WriteLine("Device name: " + deviceName);
sl@24
   412
                
sl@24
   413
                //Open our device from the device name/path
sl@24
   414
                SafeFileHandle handle=Win32.Function.CreateFile(deviceName,
sl@24
   415
                    Win32.FileAccess.NONE,
sl@24
   416
                    Win32.FileShare.FILE_SHARE_READ|Win32.FileShare.FILE_SHARE_WRITE,
sl@24
   417
                    IntPtr.Zero,
sl@24
   418
                    Win32.CreationDisposition.OPEN_EXISTING,
sl@24
   419
                    Win32.FileFlagsAttributes.FILE_FLAG_OVERLAPPED,
sl@24
   420
                    IntPtr.Zero
sl@24
   421
                    );
sl@24
   422
sl@24
   423
                if (handle.IsInvalid)
sl@24
   424
                {
sl@24
   425
                    Debug.WriteLine("Failed to CreateFile from device name " + Marshal.GetLastWin32Error().ToString());
sl@24
   426
                }
sl@24
   427
                else
sl@24
   428
                {
sl@24
   429
                    //Get manufacturer string
sl@24
   430
                    StringBuilder manufacturerString = new StringBuilder(256);
sl@24
   431
                    bool returnStatus = Win32.Function.HidD_GetManufacturerString(handle, manufacturerString, manufacturerString.Capacity);
sl@24
   432
                    if (returnStatus)
sl@24
   433
                    {
sl@24
   434
                        Debug.WriteLine("Manufacturer: " + manufacturerString.ToString());
sl@24
   435
                    }
sl@24
   436
sl@24
   437
                    //Get product string
sl@24
   438
                    StringBuilder productString = new StringBuilder(256);
sl@24
   439
                    returnStatus = Win32.Function.HidD_GetProductString(handle, productString, productString.Capacity);
sl@24
   440
                    if (returnStatus)
sl@24
   441
                    {
sl@24
   442
                        Debug.WriteLine("Product: " + productString.ToString());
sl@24
   443
                    }
sl@24
   444
sl@24
   445
                    handle.Close();
sl@24
   446
sl@24
   447
                }
sl@11
   448
               
sl@6
   449
sl@24
   450
sl@11
   451
                if (rawInput.header.dwType == Const.RIM_TYPEHID)  //Check that our raw input is HID                        
sl@6
   452
                {
sl@11
   453
                    Debug.WriteLine("WM_INPUT source device is HID.");
sl@11
   454
                    //Get Usage Page and Usage
sl@13
   455
                    Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
sl@10
   456
sl@17
   457
sl@17
   458
                    preParsedData = RawInput.GetPreParsedData(rawInput.header.hDevice);
sl@17
   459
sl@12
   460
                    //
sl@13
   461
                    HidUsageHandler usagePageHandler=null;
sl@12
   462
sl@14
   463
                    //Check if this an MCE remote HID message
sl@21
   464
                    if (deviceInfo.hid.usUsagePage == (ushort)Hid.UsagePage.MceRemote && deviceInfo.hid.usUsage == (ushort)Hid.UsageIdMce.MceRemote)
sl@12
   465
                    {                        
sl@13
   466
                        usagePageHandler = HidMceRemoteHandler;
sl@12
   467
                    }
sl@14
   468
                    //Check if this is a consumer control HID message
sl@21
   469
                    else if (deviceInfo.hid.usUsagePage == (ushort)Hid.UsagePage.Consumer && deviceInfo.hid.usUsage == (ushort)Hid.UsageIdConsumer.ConsumerControl)
sl@12
   470
                    {
sl@13
   471
                        usagePageHandler = HidConsumerDeviceHandler;
sl@12
   472
                    }
sl@14
   473
                    //Unknown HID message
sl@12
   474
                    else
sl@6
   475
                    {
sl@14
   476
                        Debug.WriteLine("Unknown HID message.");
sl@6
   477
                        return;
sl@6
   478
                    }
sl@0
   479
sl@11
   480
                    if (!(rawInput.hid.dwSizeHid > 1     //Make sure our HID msg size more than 1. In fact the first ushort is irrelevant to us for now
sl@11
   481
                        && rawInput.hid.dwCount > 0))    //Check that we have at least one HID msg
sl@3
   482
                    {
sl@11
   483
                        return;
sl@11
   484
                    }
sl@11
   485
sl@11
   486
sl@11
   487
                    //Allocate a buffer for one HID input
sl@17
   488
                    byte[] hidInputReport = new byte[rawInput.hid.dwSizeHid];
sl@11
   489
sl@18
   490
                    Debug.WriteLine("Raw input contains " + rawInput.hid.dwCount + " HID input report(s)");
sl@18
   491
sl@18
   492
                    //For each HID input report in our raw input
sl@11
   493
                    for (int i = 0; i < rawInput.hid.dwCount; i++)
sl@11
   494
                    {
sl@11
   495
                        //Compute the address from which to copy our HID input
sl@11
   496
                        int hidInputOffset = 0;
sl@11
   497
                        unsafe
sl@3
   498
                        {
sl@11
   499
                            byte* source = (byte*)rawInputBuffer;
sl@11
   500
                            source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
sl@11
   501
                            hidInputOffset = (int)source;
sl@11
   502
                        }
sl@11
   503
sl@11
   504
                        //Copy HID input into our buffer
sl@17
   505
                        Marshal.Copy(new IntPtr(hidInputOffset), hidInputReport, 0, (int)rawInput.hid.dwSizeHid);
sl@11
   506
sl@18
   507
                        //Print HID input report in our debug output
sl@18
   508
                        string hidDump = "HID input report: ";
sl@17
   509
                        foreach (byte b in hidInputReport)
sl@11
   510
                        {
sl@11
   511
                            hidDump += b.ToString("X2");
sl@11
   512
                        }
sl@11
   513
                        Debug.WriteLine(hidDump);
sl@11
   514
                        
sl@17
   515
                        //Proper parsing now
sl@18
   516
                        uint usageCount = 1; //Assuming a single usage per input report. Is that correct?
sl@17
   517
                        Win32.USAGE_AND_PAGE[] usages = new Win32.USAGE_AND_PAGE[usageCount];
sl@17
   518
                        Win32.HidStatus status = Win32.Function.HidP_GetUsagesEx(Win32.HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, preParsedData, hidInputReport, (uint)hidInputReport.Length);
sl@17
   519
                        if (status != Win32.HidStatus.HIDP_STATUS_SUCCESS)
sl@17
   520
                        {
sl@17
   521
                            Debug.WriteLine("Could not parse HID data!");
sl@17
   522
                        }
sl@17
   523
                        else
sl@17
   524
                        {
sl@17
   525
                            Debug.WriteLine("UsagePage: 0x" + usages[0].UsagePage.ToString("X4"));
sl@17
   526
                            Debug.WriteLine("Usage: 0x" + usages[0].Usage.ToString("X4"));
sl@18
   527
                            //Call on our Usage Page handler
sl@18
   528
                            usagePageHandler(usages[0].Usage);
sl@17
   529
                        }
sl@3
   530
                    }
sl@11
   531
sl@10
   532
                }
sl@11
   533
                else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
sl@10
   534
                {
sl@11
   535
                    Debug.WriteLine("WM_INPUT source device is Mouse.");
sl@10
   536
                    // do mouse handling...
sl@10
   537
                }
sl@11
   538
                else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
sl@10
   539
                {
sl@11
   540
                    Debug.WriteLine("WM_INPUT source device is Keyboard.");
sl@10
   541
                    // do keyboard handling...
sl@22
   542
                    Debug.WriteLine("Type: " + deviceInfo.keyboard.dwType.ToString());
sl@22
   543
                    Debug.WriteLine("SubType: " + deviceInfo.keyboard.dwSubType.ToString());
sl@22
   544
                    Debug.WriteLine("Mode: " + deviceInfo.keyboard.dwKeyboardMode.ToString());
sl@22
   545
                    Debug.WriteLine("Number of function keys: " + deviceInfo.keyboard.dwNumberOfFunctionKeys.ToString());
sl@22
   546
                    Debug.WriteLine("Number of indicators: " + deviceInfo.keyboard.dwNumberOfIndicators.ToString());
sl@23
   547
                    Debug.WriteLine("Number of keys total: " + deviceInfo.keyboard.dwNumberOfKeysTotal.ToString());
sl@10
   548
                }
sl@10
   549
            }
sl@10
   550
            finally
sl@10
   551
            {
sl@10
   552
                //Always executed when leaving our try block
sl@10
   553
                Marshal.FreeHGlobal(rawInputBuffer);
sl@17
   554
                Marshal.FreeHGlobal(preParsedData);
sl@10
   555
            }
sl@0
   556
		}
sl@0
   557
	}
sl@0
   558
}