Was trying to get manufacturer string.
2 using System.Windows.Forms;
3 using System.Runtime.InteropServices;
4 using System.Diagnostics;
11 namespace Devices.RemoteControl
14 public enum InputDevice
22 public enum RemoteControlButton
79 #region RemoteControlEventArgs
81 public class RemoteControlEventArgs : EventArgs
83 RemoteControlButton _rcb;
86 ConsumerControl iConsumerControl;
88 public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
96 public RemoteControlEventArgs(ConsumerControl aConsumerControl, InputDevice device)
100 iConsumerControl = aConsumerControl;
105 public RemoteControlEventArgs(MceButton mce, InputDevice device)
113 private void SetNullButtons()
115 iConsumerControl = ConsumerControl.Null;
116 iMceButton = MceButton.Null;
117 _rcb = RemoteControlButton.Unknown;
120 public RemoteControlEventArgs()
122 iMceButton = MceButton.Null;
123 _rcb = RemoteControlButton.Unknown;
124 _device = InputDevice.Key;
127 public RemoteControlButton Button
130 set { _rcb = value; }
133 public MceButton MceButton
135 get { return iMceButton; }
136 set { iMceButton = value; }
139 public ConsumerControl ConsumerControl
141 get { return iConsumerControl; }
142 set { iConsumerControl = value; }
145 public InputDevice Device
147 get { return _device; }
148 set { _device = value; }
152 #endregion RemoteControlEventArgs
155 public sealed class RemoteControlDevice
157 public delegate bool RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
158 public event RemoteControlDeviceEventHandler ButtonPressed;
161 /// Return true if the usage was processed.
163 /// <param name="aUsage"></param>
164 /// <returns></returns>
165 public delegate bool HidUsageHandler(ushort aUsage);
168 //-------------------------------------------------------------
170 //-------------------------------------------------------------
172 public RemoteControlDevice(IntPtr aHWND)
174 // Register the input device to receive the commands from the
175 // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
176 // for the vendor defined usage page.
178 RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[5];
181 rid[i].usUsagePage = (ushort)Hid.UsagePage.MceRemote;
182 rid[i].usUsage = (ushort)Hid.UsageIdMce.MceRemote;
183 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
184 rid[i].hwndTarget = aHWND;
187 rid[i].usUsagePage = (ushort)Hid.UsagePage.Consumer;
188 rid[i].usUsage = (ushort)Hid.UsageIdConsumer.ConsumerControl;
189 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
190 rid[i].hwndTarget = aHWND;
193 rid[i].usUsagePage = (ushort)Hid.UsagePage.Consumer;
194 rid[i].usUsage = (ushort)Hid.UsageIdConsumer.Selection;
195 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
196 rid[i].hwndTarget = aHWND;
199 rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
200 rid[i].usUsage = (ushort)Hid.UsageIdGenericDesktop.SystemControl;
201 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
202 rid[i].hwndTarget = aHWND;
205 rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
206 rid[i].usUsage = (ushort)Hid.UsageIdGenericDesktop.Keyboard;
207 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
208 rid[i].hwndTarget = aHWND;
211 //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
212 //rid[i].usUsage = (ushort)Hid.UsageIdGenericDesktop.Mouse;
213 //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
214 //rid[i].hwndTarget = aHWND;
217 if (!Function.RegisterRawInputDevices(rid,(uint) rid.Length,(uint) Marshal.SizeOf(rid[0])))
219 throw new ApplicationException("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
224 //-------------------------------------------------------------
226 //-------------------------------------------------------------
228 public void ProcessMessage(Message message)
232 case Const.WM_KEYDOWN:
233 ProcessKeyDown(message.WParam);
236 //Returning zero means we processed that message.
237 message.Result = new IntPtr(0);
238 ProcessInputCommand(ref message);
245 //-------------------------------------------------------------
247 //-------------------------------------------------------------
249 private void ProcessKeyDown(IntPtr wParam)
251 RemoteControlButton rcb = RemoteControlButton.Unknown;
253 switch (wParam.ToInt32())
255 case (int) Keys.Escape:
256 rcb = RemoteControlButton.Clear;
259 rcb = RemoteControlButton.Up;
261 case (int) Keys.Down:
262 rcb = RemoteControlButton.Down;
264 case (int) Keys.Left:
265 rcb = RemoteControlButton.Left;
267 case (int)Keys.Right:
268 rcb = RemoteControlButton.Right;
270 case (int)Keys.Enter:
271 rcb = RemoteControlButton.Enter;
274 rcb = RemoteControlButton.Digit0;
277 rcb = RemoteControlButton.Digit1;
280 rcb = RemoteControlButton.Digit2;
283 rcb = RemoteControlButton.Digit3;
286 rcb = RemoteControlButton.Digit4;
289 rcb = RemoteControlButton.Digit5;
292 rcb = RemoteControlButton.Digit6;
295 rcb = RemoteControlButton.Digit7;
298 rcb = RemoteControlButton.Digit8;
301 rcb = RemoteControlButton.Digit9;
305 if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
307 Debug.WriteLine("KeyDown: " + rcb.ToString());
308 this.ButtonPressed(this, new RemoteControlEventArgs(rcb, InputDevice.Key));
316 /// <param name="aUsage"></param>
317 private bool HidConsumerDeviceHandler(ushort aUsage)
325 if (Enum.IsDefined(typeof(ConsumerControl), aUsage) && aUsage != 0) //Our button is a known consumer control
327 if (this.ButtonPressed != null)
329 return this.ButtonPressed(this, new RemoteControlEventArgs((ConsumerControl)aUsage, InputDevice.OEM));
335 Debug.WriteLine("Unknown Consumer Control!");
343 /// <param name="aUsage"></param>
344 private bool HidMceRemoteHandler(ushort aUsage)
353 if (Enum.IsDefined(typeof(MceButton), aUsage) && aUsage != 0) //Our button is a known MCE button
355 if (this.ButtonPressed != null)
357 return this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)aUsage, InputDevice.OEM));
363 Debug.WriteLine("Unknown MCE button!");
369 private void ProcessInputCommand(ref Message message)
371 //We received a WM_INPUT message
372 Debug.WriteLine("================WM_INPUT================");
374 //Check if we received this message while in background or foreground
375 if (Macro.GET_RAWINPUT_CODE_WPARAM(message.WParam) == Const.RIM_INPUT)
377 Debug.WriteLine("================FOREGROUND");
379 else if (Macro.GET_RAWINPUT_CODE_WPARAM(message.WParam) == Const.RIM_INPUTSINK)
381 Debug.WriteLine("================BACKGROUND");
384 //Declare some pointers
385 IntPtr rawInputBuffer = IntPtr.Zero;
386 //My understanding is that this is basically our HID descriptor
387 IntPtr preParsedData = IntPtr.Zero;
392 RAWINPUT rawInput = new RAWINPUT();
393 if (!RawInput.GetRawInputData(message.LParam, ref rawInput, ref rawInputBuffer))
399 //TODO: This needs create file from the device name/path
400 //Get device manufacturer
401 StringBuilder manufacturerString = new StringBuilder(256);
402 bool returnStatus = Win32.Function.HidD_GetManufacturerString(rawInput.header.hDevice, manufacturerString, manufacturerString.Capacity);
405 Debug.WriteLine("Manufacturer name is {0}", manufacturerString.ToString());
411 RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO();
412 if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
418 Debug.WriteLine(RawInput.GetDeviceName(rawInput.header.hDevice));
421 if (rawInput.header.dwType == Const.RIM_TYPEHID) //Check that our raw input is HID
423 Debug.WriteLine("WM_INPUT source device is HID.");
424 //Get Usage Page and Usage
425 Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
428 preParsedData = RawInput.GetPreParsedData(rawInput.header.hDevice);
431 HidUsageHandler usagePageHandler=null;
433 //Check if this an MCE remote HID message
434 if (deviceInfo.hid.usUsagePage == (ushort)Hid.UsagePage.MceRemote && deviceInfo.hid.usUsage == (ushort)Hid.UsageIdMce.MceRemote)
436 usagePageHandler = HidMceRemoteHandler;
438 //Check if this is a consumer control HID message
439 else if (deviceInfo.hid.usUsagePage == (ushort)Hid.UsagePage.Consumer && deviceInfo.hid.usUsage == (ushort)Hid.UsageIdConsumer.ConsumerControl)
441 usagePageHandler = HidConsumerDeviceHandler;
443 //Unknown HID message
446 Debug.WriteLine("Unknown HID message.");
450 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
451 && rawInput.hid.dwCount > 0)) //Check that we have at least one HID msg
457 //Allocate a buffer for one HID input
458 byte[] hidInputReport = new byte[rawInput.hid.dwSizeHid];
460 Debug.WriteLine("Raw input contains " + rawInput.hid.dwCount + " HID input report(s)");
462 //For each HID input report in our raw input
463 for (int i = 0; i < rawInput.hid.dwCount; i++)
465 //Compute the address from which to copy our HID input
466 int hidInputOffset = 0;
469 byte* source = (byte*)rawInputBuffer;
470 source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
471 hidInputOffset = (int)source;
474 //Copy HID input into our buffer
475 Marshal.Copy(new IntPtr(hidInputOffset), hidInputReport, 0, (int)rawInput.hid.dwSizeHid);
477 //Print HID input report in our debug output
478 string hidDump = "HID input report: ";
479 foreach (byte b in hidInputReport)
481 hidDump += b.ToString("X2");
483 Debug.WriteLine(hidDump);
486 uint usageCount = 1; //Assuming a single usage per input report. Is that correct?
487 Win32.USAGE_AND_PAGE[] usages = new Win32.USAGE_AND_PAGE[usageCount];
488 Win32.HidStatus status = Win32.Function.HidP_GetUsagesEx(Win32.HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, preParsedData, hidInputReport, (uint)hidInputReport.Length);
489 if (status != Win32.HidStatus.HIDP_STATUS_SUCCESS)
491 Debug.WriteLine("Could not parse HID data!");
495 Debug.WriteLine("UsagePage: 0x" + usages[0].UsagePage.ToString("X4"));
496 Debug.WriteLine("Usage: 0x" + usages[0].Usage.ToString("X4"));
497 //Call on our Usage Page handler
498 usagePageHandler(usages[0].Usage);
503 else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
505 Debug.WriteLine("WM_INPUT source device is Mouse.");
506 // do mouse handling...
508 else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
510 Debug.WriteLine("WM_INPUT source device is Keyboard.");
511 // do keyboard handling...
512 Debug.WriteLine("Type: " + deviceInfo.keyboard.dwType.ToString());
513 Debug.WriteLine("SubType: " + deviceInfo.keyboard.dwSubType.ToString());
514 Debug.WriteLine("Mode: " + deviceInfo.keyboard.dwKeyboardMode.ToString());
515 Debug.WriteLine("Number of function keys: " + deviceInfo.keyboard.dwNumberOfFunctionKeys.ToString());
516 Debug.WriteLine("Number of indicators: " + deviceInfo.keyboard.dwNumberOfIndicators.ToString());
517 Debug.WriteLine("Number of keys total: " + deviceInfo.keyboard.dwNumberOfKeysTotal.ToString());
522 //Always executed when leaving our try block
523 Marshal.FreeHGlobal(rawInputBuffer);
524 Marshal.FreeHGlobal(preParsedData);