HidEvent implementation.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/HidEvent.cs Sat Dec 06 21:52:45 2014 +0100
1.3 @@ -0,0 +1,206 @@
1.4 +using System;
1.5 +using System.Windows.Forms;
1.6 +using System.Runtime.InteropServices;
1.7 +using System.Diagnostics;
1.8 +using System.Text;
1.9 +using Microsoft.Win32.SafeHandles;
1.10 +using Win32;
1.11 +using System.Collections.Generic;
1.12 +
1.13 +
1.14 +namespace Hid
1.15 +{
1.16 + /// <summary>
1.17 + /// Represent a HID event.
1.18 + /// </summary>
1.19 + class HidEvent
1.20 + {
1.21 + public bool IsValid { get; private set; }
1.22 + public bool IsForeground { get; private set; }
1.23 + public bool IsBackground { get{return !IsForeground;} }
1.24 + public bool IsMouse { get; private set; }
1.25 + public bool IsKeyboard { get; private set; }
1.26 + public bool IsGeneric { get; private set; }
1.27 +
1.28 + public HidDevice Device { get; private set; }
1.29 +
1.30 + public ushort UsagePage { get; private set; }
1.31 + public ushort UsageCollection { get; private set; }
1.32 + public List<ushort> Usages { get; private set; }
1.33 +
1.34 +
1.35 + /// <summary>
1.36 + /// Initialize an HidEvent from a WM_INPUT message
1.37 + /// </summary>
1.38 + /// <param name="hRawInputDevice">Device Handle as provided by RAWINPUTHEADER.hDevice, typically accessed as rawinput.header.hDevice</param>
1.39 + public HidEvent(Message aMessage)
1.40 + {
1.41 + IsValid = false;
1.42 + IsKeyboard = false;
1.43 + IsGeneric = false;
1.44 +
1.45 + Usages = new List<ushort>();
1.46 +
1.47 + if (aMessage.Msg != Const.WM_INPUT)
1.48 + {
1.49 + //Has to be a WM_INPUT message
1.50 + return;
1.51 + }
1.52 +
1.53 + if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUT)
1.54 + {
1.55 + IsForeground = true;
1.56 + }
1.57 + else if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUTSINK)
1.58 + {
1.59 + IsForeground = false;
1.60 + }
1.61 +
1.62 + //Declare some pointers
1.63 + IntPtr rawInputBuffer = IntPtr.Zero;
1.64 + //My understanding is that this is basically our HID descriptor
1.65 + IntPtr preParsedData = IntPtr.Zero;
1.66 +
1.67 + try
1.68 + {
1.69 + //Fetch raw input
1.70 + RAWINPUT rawInput = new RAWINPUT();
1.71 + if (!RawInput.GetRawInputData(aMessage.LParam, ref rawInput, ref rawInputBuffer))
1.72 + {
1.73 + return;
1.74 + }
1.75 +
1.76 + //Fetch device info
1.77 + RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO();
1.78 + if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
1.79 + {
1.80 + return;
1.81 + }
1.82 +
1.83 + //Get various information about this HID device
1.84 + Device = new Hid.HidDevice(rawInput.header.hDevice);
1.85 +
1.86 + if (rawInput.header.dwType == Const.RIM_TYPEHID) //Check that our raw input is HID
1.87 + {
1.88 + IsGeneric = true;
1.89 +
1.90 + Debug.WriteLine("WM_INPUT source device is HID.");
1.91 + //Get Usage Page and Usage
1.92 + //Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
1.93 + UsagePage = deviceInfo.hid.usUsagePage;
1.94 + UsageCollection = deviceInfo.hid.usUsage;
1.95 +
1.96 + preParsedData = RawInput.GetPreParsedData(rawInput.header.hDevice);
1.97 +
1.98 + 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
1.99 + && rawInput.hid.dwCount > 0)) //Check that we have at least one HID msg
1.100 + {
1.101 + return;
1.102 + }
1.103 +
1.104 + //Allocate a buffer for one HID input
1.105 + byte[] hidInputReport = new byte[rawInput.hid.dwSizeHid];
1.106 +
1.107 + Debug.WriteLine("Raw input contains " + rawInput.hid.dwCount + " HID input report(s)");
1.108 +
1.109 + //For each HID input report in our raw input
1.110 + for (int i = 0; i < rawInput.hid.dwCount; i++)
1.111 + {
1.112 + //Compute the address from which to copy our HID input
1.113 + int hidInputOffset = 0;
1.114 + unsafe
1.115 + {
1.116 + byte* source = (byte*)rawInputBuffer;
1.117 + source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
1.118 + hidInputOffset = (int)source;
1.119 + }
1.120 +
1.121 + //Copy HID input into our buffer
1.122 + Marshal.Copy(new IntPtr(hidInputOffset), hidInputReport, 0, (int)rawInput.hid.dwSizeHid);
1.123 +
1.124 + //Print HID input report in our debug output
1.125 + string hidDump = "HID input report: ";
1.126 + foreach (byte b in hidInputReport)
1.127 + {
1.128 + hidDump += b.ToString("X2");
1.129 + }
1.130 + Debug.WriteLine(hidDump);
1.131 +
1.132 + //Proper parsing now
1.133 + uint usageCount = 1; //Assuming a single usage per input report. Is that correct?
1.134 + Win32.USAGE_AND_PAGE[] usages = new Win32.USAGE_AND_PAGE[usageCount];
1.135 + Win32.HidStatus status = Win32.Function.HidP_GetUsagesEx(Win32.HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, preParsedData, hidInputReport, (uint)hidInputReport.Length);
1.136 + if (status != Win32.HidStatus.HIDP_STATUS_SUCCESS)
1.137 + {
1.138 + Debug.WriteLine("Could not parse HID data!");
1.139 + }
1.140 + else
1.141 + {
1.142 + //Debug.WriteLine("UsagePage: 0x" + usages[0].UsagePage.ToString("X4"));
1.143 + //Debug.WriteLine("Usage: 0x" + usages[0].Usage.ToString("X4"));
1.144 + //Add this usage to our list
1.145 + Usages.Add(usages[0].Usage);
1.146 + }
1.147 + }
1.148 +
1.149 + }
1.150 + else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
1.151 + {
1.152 + IsMouse = true;
1.153 +
1.154 + Debug.WriteLine("WM_INPUT source device is Mouse.");
1.155 + // do mouse handling...
1.156 + }
1.157 + else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
1.158 + {
1.159 + IsKeyboard = true;
1.160 +
1.161 + Debug.WriteLine("WM_INPUT source device is Keyboard.");
1.162 + // do keyboard handling...
1.163 + Debug.WriteLine("Type: " + deviceInfo.keyboard.dwType.ToString());
1.164 + Debug.WriteLine("SubType: " + deviceInfo.keyboard.dwSubType.ToString());
1.165 + Debug.WriteLine("Mode: " + deviceInfo.keyboard.dwKeyboardMode.ToString());
1.166 + Debug.WriteLine("Number of function keys: " + deviceInfo.keyboard.dwNumberOfFunctionKeys.ToString());
1.167 + Debug.WriteLine("Number of indicators: " + deviceInfo.keyboard.dwNumberOfIndicators.ToString());
1.168 + Debug.WriteLine("Number of keys total: " + deviceInfo.keyboard.dwNumberOfKeysTotal.ToString());
1.169 + }
1.170 + }
1.171 + finally
1.172 + {
1.173 + //Always executed when leaving our try block
1.174 + Marshal.FreeHGlobal(rawInputBuffer);
1.175 + Marshal.FreeHGlobal(preParsedData);
1.176 + }
1.177 +
1.178 + IsValid = true;
1.179 + }
1.180 +
1.181 + /// <summary>
1.182 + /// Print information about this device to our debug output.
1.183 + /// </summary>
1.184 + public void DebugWrite()
1.185 + {
1.186 + if (!IsValid)
1.187 + {
1.188 + Debug.WriteLine("==== Invalid HidEvent");
1.189 + return;
1.190 + }
1.191 + Device.DebugWrite();
1.192 + if (IsGeneric) Debug.WriteLine("==== Generic");
1.193 + if (IsKeyboard) Debug.WriteLine("==== Keyboard");
1.194 + if (IsMouse) Debug.WriteLine("==== Mouse");
1.195 + Debug.WriteLine("==== Foreground: " + IsForeground.ToString());
1.196 + Debug.WriteLine("==== UsagePage: 0x" + UsagePage.ToString("X4"));
1.197 + Debug.WriteLine("==== UsageCollection: 0x" + UsageCollection.ToString("X4"));
1.198 + foreach (ushort usage in Usages)
1.199 + {
1.200 + Debug.WriteLine("==== Usage: 0x" + usage.ToString("X4"));
1.201 + }
1.202 + }
1.203 +
1.204 +
1.205 +
1.206 +
1.207 + }
1.208 +
1.209 +}
1.210 \ No newline at end of file
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/HidUsageTables.cs Sat Dec 06 21:52:45 2014 +0100
2.3 @@ -0,0 +1,394 @@
2.4 +//
2.5 +//
2.6 +//
2.7 +
2.8 +namespace Hid
2.9 +{
2.10 + /// <summary>
2.11 + /// From USB HID usage tables.
2.12 + /// http://www.usb.org/developers/hidpage#HID_Usage
2.13 + /// http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf
2.14 + /// </summary>
2.15 + public enum UsagePage : ushort
2.16 + {
2.17 + Undefined = 0,
2.18 + GenericDesktopControl,
2.19 + SimulationControl,
2.20 + VirtualRealityControl,
2.21 + SportControl,
2.22 + GameControl,
2.23 + GenericDeviceControl,
2.24 + Keyboard,
2.25 + LightEmittingDiode,
2.26 + Button,
2.27 + Ordinal,
2.28 + Telephony,
2.29 + Consumer,
2.30 + Digitiser,
2.31 + PhysicalInterfaceDevice = 0x0f,
2.32 + Unicode = 0x10,
2.33 + AlphaNumericDisplay = 0x14,
2.34 + MedicalInstruments = 0x40,
2.35 + MonitorPage0 = 0x80,
2.36 + MonitorPage1,
2.37 + MonitorPage2,
2.38 + MonitorPage3,
2.39 + PowerPage0,
2.40 + PowerPage1,
2.41 + PowerPage2,
2.42 + PowerPage3,
2.43 + BarCodeScanner = 0x8c,
2.44 + Scale,
2.45 + MagneticStripeReader,
2.46 + ReservedPointOfSale,
2.47 + CameraControl,
2.48 + Arcade,
2.49 + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb417079.aspx
2.50 + MceRemote = 0xffbc,
2.51 + TerraTecRemote = 0xffcc
2.52 + }
2.53 +
2.54 + public enum UsageIdGenericDesktop : ushort
2.55 + {
2.56 + Pointer = 0x01,
2.57 + Mouse = 0x02,
2.58 + Joystick = 0x04,
2.59 + GamePad = 0x05,
2.60 + Keyboard = 0x06,
2.61 + KeyPad = 0x07,
2.62 + MultiAxisController = 0x08,
2.63 + TabletPCSystemControls = 0x09,
2.64 + SystemControl = 0x80
2.65 + }
2.66 +
2.67 + public enum UsageIdConsumer : ushort
2.68 + {
2.69 + ConsumerControl = 0x01,
2.70 + NumericKeyPad = 0x02,
2.71 + ProgrammableButtons = 0x03,
2.72 + Microphone = 0x04,
2.73 + Headphone = 0x05,
2.74 + GraphicEqualizer = 0x06,
2.75 + Selection = 0x80,
2.76 + }
2.77 +
2.78 +
2.79 + public enum UsageIdMce: ushort
2.80 + {
2.81 + MceRemote = 0x88
2.82 + }
2.83 +
2.84 +
2.85 +
2.86 + namespace UsageTables
2.87 + {
2.88 + /// <summary>
2.89 + ///
2.90 + /// </summary>
2.91 + public enum MceButton: ushort
2.92 + {
2.93 + /// <summary>
2.94 + /// Not defined by the Microsoft specs.
2.95 + /// </summary>
2.96 + Null = 0x00,
2.97 + GreenStart = 0x0D,
2.98 + ClosedCaptioning = 0x2B,
2.99 + Teletext = 0x5A,
2.100 + TeletextRed = 0x5B,
2.101 + TeletextGreen = 0x5C,
2.102 + TeletextYellow = 0x5D,
2.103 + TeletextBlue = 0x5E,
2.104 + LiveTv = 0x25,
2.105 + Music = 0x47,
2.106 + RecordedTv = 0x48,
2.107 + Pictures = 0x49,
2.108 + Videos = 0x4A,
2.109 + FmRadio = 0x50,
2.110 + Extras = 0x3C,
2.111 + ExtrasApp = 0x3D,
2.112 + DvdMenu = 0x24,
2.113 + DvdAngle = 0x4B,
2.114 + DvdAudio = 0x4C,
2.115 + DvdSubtitle = 0x4D,
2.116 + /// <summary>
2.117 + /// First press action: Ejects a DVD drive.
2.118 + /// <para />
2.119 + /// Second press action: Repeats first press action.
2.120 + /// <para />
2.121 + /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application.
2.122 + /// </summary>
2.123 + Eject = 0x28,
2.124 + DvdTopMenu = 0x43,
2.125 + /// <summary>
2.126 + /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
2.127 + /// Collection (page 0xFFBC, usage 0x88).
2.128 + /// <para />
2.129 + /// Second press action: Repeats message.
2.130 + /// <para />
2.131 + /// Auto-repeat: No
2.132 + /// <para />
2.133 + /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08).
2.134 + /// <para />
2.135 + /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks.
2.136 + /// </summary>
2.137 + Ext0 = 0x32,
2.138 + /// <summary>
2.139 + /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
2.140 + /// Collection (page 0xFFBC, usage 0x88).
2.141 + /// <para />
2.142 + /// Second press action: Repeats message.
2.143 + /// <para />
2.144 + /// Auto-repeat: No
2.145 + /// <para />
2.146 + /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08).
2.147 + /// <para />
2.148 + /// According to HP specs it plays a slide show of all the pictures on your hard disk drive.
2.149 + /// </summary>
2.150 + Ext1 = 0x33,
2.151 + /// <summary>
2.152 + /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
2.153 + /// Collection (page 0xFFBC, usage 0x88).
2.154 + /// <para />
2.155 + /// Second press action: Repeats message.
2.156 + /// <para />
2.157 + /// Auto-repeat: No
2.158 + /// <para />
2.159 + /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08).
2.160 + /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310).
2.161 + /// </summary>
2.162 + Ext2 = 0x34,
2.163 + /// <summary>
2.164 + /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
2.165 + /// Collection (page 0xFFBC, usage 0x88).
2.166 + /// <para />
2.167 + /// Second press action: Repeats message.
2.168 + /// <para />
2.169 + /// Auto-repeat: No
2.170 + /// <para />
2.171 + /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08).
2.172 + /// </summary>
2.173 + Ext3 = 0x35,
2.174 + Ext4 = 0x36,
2.175 + Ext5 = 0x37,
2.176 + Ext6 = 0x38,
2.177 + Ext7 = 0x39,
2.178 + Ext8 = 0x3A,
2.179 + Ext9 = 0x80,
2.180 + Ext10 = 0x81,
2.181 + Ext11 = 0x6F,
2.182 + Zoom = 0x27,
2.183 + ChannelInput = 0x42,
2.184 + SubAudio = 0x2D,
2.185 + Channel10 = 0x3E,
2.186 + Channel11 = 0x3F,
2.187 + Channel12 = 0x40,
2.188 + /// <summary>
2.189 + /// First press action: Generates OEM2 HID message in the Media Center Vendor Specific
2.190 + /// Collection. This button is intended to control the front panel display of home entertainment
2.191 + /// computers. When this button is pressed, the display could be turned on or off, or the display
2.192 + /// mode could change.
2.193 + /// <para />
2.194 + /// Second press action: Repeats message.
2.195 + /// <para />
2.196 + /// Auto-repeat: No
2.197 + /// <para />
2.198 + /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application.
2.199 + /// </summary>
2.200 + Display = 0x4F,
2.201 + /// <summary>
2.202 + /// First press action: To be determined.
2.203 + /// <para />
2.204 + /// Second press action: Repeats message.
2.205 + /// <para />
2.206 + /// Auto-repeat: No
2.207 + /// </summary>
2.208 + Kiosk = 0x6A,
2.209 + NetworkSelection = 0x2C,
2.210 + BlueRayTool = 0x78,
2.211 + ChannelInfo = 0x41,
2.212 + VideoSelection = 0x61
2.213 + }
2.214 +
2.215 + /// <summary>
2.216 + /// Those codes come from experimenting with HP remotes.
2.217 + /// </summary>
2.218 + public enum HpMceButton: ushort
2.219 + {
2.220 + /// <summary>
2.221 + /// Displays visual imagery that is synchronized to the sound of your music tracks.
2.222 + /// <para />
2.223 + /// Second press action: Repeats message.
2.224 + /// <para />
2.225 + /// Auto-repeat: No
2.226 + /// <para />
2.227 + /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08).
2.228 + /// <para />
2.229 + /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks.
2.230 + /// </summary>
2.231 + Visualization = MceButton.Ext0,
2.232 + /// <summary>
2.233 + /// Plays a slide show of all the pictures on your hard disk drive.
2.234 + /// <para />
2.235 + /// Second press action: Repeats message.
2.236 + /// <para />
2.237 + /// Auto-repeat: No
2.238 + /// <para />
2.239 + /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08).
2.240 + /// <para />
2.241 + /// According to HP specs it plays a slide show of all the pictures on your hard disk drive.
2.242 + /// </summary>
2.243 + SlideShow = MceButton.Ext1,
2.244 + /// <summary>
2.245 + /// Eject optical drive.
2.246 + /// <para />
2.247 + /// Second press action: Repeats message.
2.248 + /// <para />
2.249 + /// Auto-repeat: No
2.250 + /// <para />
2.251 + /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08).
2.252 + /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310).
2.253 + /// </summary>
2.254 + Eject = MceButton.Ext2,
2.255 + /// <summary>
2.256 + /// Not sure what this should do.
2.257 + /// <para />
2.258 + /// Second press action: Repeats message.
2.259 + /// <para />
2.260 + /// Auto-repeat: No
2.261 + /// <para />
2.262 + /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08).
2.263 + /// </summary>
2.264 + InputSelection = MceButton.Ext3,
2.265 + }
2.266 +
2.267 + /// <summary>
2.268 + /// Usage Table for Consumer Controls
2.269 + /// 0x0C 0X01
2.270 + /// </summary>
2.271 + public enum ConsumerControl: ushort
2.272 + {
2.273 + Null = 0x0000,
2.274 + //
2.275 + Channel = 0x0086,
2.276 + MediaSelection = 0x0087,
2.277 + MediaSelectComputer = 0x0088,
2.278 + MediaSelectTV = 0x0089,
2.279 + MediaSelectWWW = 0x008A,
2.280 + MediaSelectDVD = 0x008B,
2.281 + MediaSelectTelephone = 0x008C,
2.282 + MediaSelectProgramGuide = 0x008D,
2.283 + MediaSelectVideoPhone = 0x008E,
2.284 + MediaSelectGames = 0x008F,
2.285 + MediaSelectMessages = 0x0090,
2.286 + MediaSelectCD = 0x0091,
2.287 + MediaSelectVCR = 0x0092,
2.288 + MediaSelectTuner = 0x0093,
2.289 + Quit = 0x0094,
2.290 + Help = 0x0095,
2.291 + MediaSelectTape = 0x0096,
2.292 + MediaSelectCable = 0x0097,
2.293 + MediaSelectSatellite = 0x0098,
2.294 + MediaSelectSecurity = 0x0099,
2.295 + MediaSelectHome = 0x009A,
2.296 + MediaSelectCall = 0x009B,
2.297 + ChannelIncrement = 0x009C,
2.298 + ChannelDecrement = 0x009D,
2.299 + MediaSelectSAP = 0x009E,
2.300 + //
2.301 + Play = 0x00B0,
2.302 + Pause = 0x00B1,
2.303 + Record = 0x00B2,
2.304 + FastForward = 0x00B3,
2.305 + Rewind = 0x00B4,
2.306 + ScanNextTrack = 0x00B5,
2.307 + ScanPreviousTrack = 0x00B6,
2.308 + Stop = 0x00B7,
2.309 + Eject = 0x00B8,
2.310 + RandomPlay = 0x00B9,
2.311 + SelectDisc = 0x00BA,
2.312 + EnterDisc = 0x00BB,
2.313 + Repeat = 0x00BC,
2.314 + Tracking = 0x00BD,
2.315 + TrackNormal = 0x00BE,
2.316 + SlowTracking = 0x00BF,
2.317 + FrameForward = 0x00C0,
2.318 + FrameBack = 0x00C1,
2.319 + Mark = 0x00C2,
2.320 + ClearMark = 0x00C3,
2.321 + RepeatFromMark = 0x00C4,
2.322 + ReturnToMark = 0x00C5,
2.323 + SearchMarkForward = 0x00C6,
2.324 + SearchMarkBackwards = 0x00C7,
2.325 + CounterReset = 0x00C8,
2.326 + ShowCounter = 0x00C9,
2.327 + TrackingIncrement = 0x00CA,
2.328 + TrackingDecrement = 0x00CB,
2.329 + StopEject = 0x00CC,
2.330 + PlayPause = 0x00CD,
2.331 + PlaySkip = 0x00CE,
2.332 +
2.333 + /// <summary>
2.334 + /// Audio controls
2.335 + /// </summary>
2.336 + Volume = 0x00E0,
2.337 + Balance = 0x00E1,
2.338 + Mute = 0x00E2,
2.339 + Bass = 0x00E3,
2.340 + Treble = 0x00E4,
2.341 + BassBoost = 0x00E5,
2.342 + SurroundMode = 0x00E6,
2.343 + Loudness = 0x00E7,
2.344 + MPX = 0x00E8,
2.345 + VolumeIncrement = 0x00E9,
2.346 + VolumeDecrement = 0x00EA,
2.347 +
2.348 + //Generic GUI Application Controls
2.349 + GenericGUIApplicationControls = 0x0200,
2.350 + AppCtrlNew = 0x0201,
2.351 + AppCtrlOpen = 0x0202,
2.352 + AppCtrlClose = 0x0203,
2.353 + AppCtrlExit = 0x0204,
2.354 + AppCtrlMaximize = 0x0205,
2.355 + AppCtrlMinimize = 0x0206,
2.356 + AppCtrlSave = 0x0207,
2.357 + AppCtrlPrint = 0x0208,
2.358 + AppCtrlProperties = 0x0209,
2.359 + AppCtrlUndo = 0x021A,
2.360 + AppCtrlCopy = 0x021B,
2.361 + AppCtrlCut = 0x021C,
2.362 + AppCtrlPaste = 0x021D,
2.363 + AppCtrlSelectAll = 0x021E,
2.364 + AppCtrlFind = 0x021F,
2.365 + AppCtrlFindAndReplace = 0x0220,
2.366 + AppCtrlSearch = 0x0221,
2.367 + AppCtrlGoTo = 0x0222,
2.368 + AppCtrlHome = 0x0223,
2.369 + AppCtrlBack = 0x0224,
2.370 + AppCtrlForward = 0x0225,
2.371 + AppCtrlStop = 0x0226,
2.372 + AppCtrlRefresh = 0x0227,
2.373 + AppCtrlPreviousLink = 0x0228,
2.374 + AppCtrlNextLink = 0x0229,
2.375 + AppCtrlBookmarks = 0x022A,
2.376 + AppCtrlHistory = 0x022B,
2.377 + AppCtrlSubscriptions = 0x022C,
2.378 + AppCtrlZoomIn = 0x022D,
2.379 + AppCtrlZoomOut = 0x022E,
2.380 + AppCtrlZoom = 0x022F,
2.381 + AppCtrlFullScreenView = 0x0230,
2.382 + AppCtrlNormalView = 0x0231,
2.383 + AppCtrlViewToggle = 0x0232,
2.384 + AppCtrlScrollUp = 0x0233,
2.385 + AppCtrlScrollDown = 0x0234,
2.386 + AppCtrlScroll = 0x0235,
2.387 + AppCtrlPanLeft = 0x0236,
2.388 + AppCtrlPanRight = 0x0237,
2.389 + AppCtrlPan = 0x0238,
2.390 + AppCtrlNewWindow = 0x0239,
2.391 + AppCtrlTileHorizontally = 0x023A,
2.392 + AppCtrlTileVertically = 0x023B,
2.393 + AppCtrlFormat = 0x023C,
2.394 + AppCtrlEdit = 0x023D,
2.395 + }
2.396 + }
2.397 +}
2.398 \ No newline at end of file
3.1 --- a/HumanInterfaceDevice.cs Sat Dec 06 13:14:16 2014 +0100
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,394 +0,0 @@
3.4 -//
3.5 -//
3.6 -//
3.7 -
3.8 -namespace Hid
3.9 -{
3.10 - /// <summary>
3.11 - /// From USB HID usage tables.
3.12 - /// http://www.usb.org/developers/hidpage#HID_Usage
3.13 - /// http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf
3.14 - /// </summary>
3.15 - public enum UsagePage : ushort
3.16 - {
3.17 - Undefined = 0,
3.18 - GenericDesktopControl,
3.19 - SimulationControl,
3.20 - VirtualRealityControl,
3.21 - SportControl,
3.22 - GameControl,
3.23 - GenericDeviceControl,
3.24 - Keyboard,
3.25 - LightEmittingDiode,
3.26 - Button,
3.27 - Ordinal,
3.28 - Telephony,
3.29 - Consumer,
3.30 - Digitiser,
3.31 - PhysicalInterfaceDevice = 0x0f,
3.32 - Unicode = 0x10,
3.33 - AlphaNumericDisplay = 0x14,
3.34 - MedicalInstruments = 0x40,
3.35 - MonitorPage0 = 0x80,
3.36 - MonitorPage1,
3.37 - MonitorPage2,
3.38 - MonitorPage3,
3.39 - PowerPage0,
3.40 - PowerPage1,
3.41 - PowerPage2,
3.42 - PowerPage3,
3.43 - BarCodeScanner = 0x8c,
3.44 - Scale,
3.45 - MagneticStripeReader,
3.46 - ReservedPointOfSale,
3.47 - CameraControl,
3.48 - Arcade,
3.49 - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb417079.aspx
3.50 - MceRemote = 0xffbc,
3.51 - TerraTecRemote = 0xffcc
3.52 - }
3.53 -
3.54 - public enum UsageIdGenericDesktop : ushort
3.55 - {
3.56 - Pointer = 0x01,
3.57 - Mouse = 0x02,
3.58 - Joystick = 0x04,
3.59 - GamePad = 0x05,
3.60 - Keyboard = 0x06,
3.61 - KeyPad = 0x07,
3.62 - MultiAxisController = 0x08,
3.63 - TabletPCSystemControls = 0x09,
3.64 - SystemControl = 0x80
3.65 - }
3.66 -
3.67 - public enum UsageIdConsumer : ushort
3.68 - {
3.69 - ConsumerControl = 0x01,
3.70 - NumericKeyPad = 0x02,
3.71 - ProgrammableButtons = 0x03,
3.72 - Microphone = 0x04,
3.73 - Headphone = 0x05,
3.74 - GraphicEqualizer = 0x06,
3.75 - Selection = 0x80,
3.76 - }
3.77 -
3.78 -
3.79 - public enum UsageIdMce: ushort
3.80 - {
3.81 - MceRemote = 0x88
3.82 - }
3.83 -
3.84 -
3.85 -
3.86 - namespace UsageTables
3.87 - {
3.88 - /// <summary>
3.89 - ///
3.90 - /// </summary>
3.91 - public enum MceButton: ushort
3.92 - {
3.93 - /// <summary>
3.94 - /// Not defined by the Microsoft specs.
3.95 - /// </summary>
3.96 - Null = 0x00,
3.97 - GreenStart = 0x0D,
3.98 - ClosedCaptioning = 0x2B,
3.99 - Teletext = 0x5A,
3.100 - TeletextRed = 0x5B,
3.101 - TeletextGreen = 0x5C,
3.102 - TeletextYellow = 0x5D,
3.103 - TeletextBlue = 0x5E,
3.104 - LiveTv = 0x25,
3.105 - Music = 0x47,
3.106 - RecordedTv = 0x48,
3.107 - Pictures = 0x49,
3.108 - Videos = 0x4A,
3.109 - FmRadio = 0x50,
3.110 - Extras = 0x3C,
3.111 - ExtrasApp = 0x3D,
3.112 - DvdMenu = 0x24,
3.113 - DvdAngle = 0x4B,
3.114 - DvdAudio = 0x4C,
3.115 - DvdSubtitle = 0x4D,
3.116 - /// <summary>
3.117 - /// First press action: Ejects a DVD drive.
3.118 - /// <para />
3.119 - /// Second press action: Repeats first press action.
3.120 - /// <para />
3.121 - /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application.
3.122 - /// </summary>
3.123 - Eject = 0x28,
3.124 - DvdTopMenu = 0x43,
3.125 - /// <summary>
3.126 - /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
3.127 - /// Collection (page 0xFFBC, usage 0x88).
3.128 - /// <para />
3.129 - /// Second press action: Repeats message.
3.130 - /// <para />
3.131 - /// Auto-repeat: No
3.132 - /// <para />
3.133 - /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08).
3.134 - /// <para />
3.135 - /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks.
3.136 - /// </summary>
3.137 - Ext0 = 0x32,
3.138 - /// <summary>
3.139 - /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
3.140 - /// Collection (page 0xFFBC, usage 0x88).
3.141 - /// <para />
3.142 - /// Second press action: Repeats message.
3.143 - /// <para />
3.144 - /// Auto-repeat: No
3.145 - /// <para />
3.146 - /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08).
3.147 - /// <para />
3.148 - /// According to HP specs it plays a slide show of all the pictures on your hard disk drive.
3.149 - /// </summary>
3.150 - Ext1 = 0x33,
3.151 - /// <summary>
3.152 - /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
3.153 - /// Collection (page 0xFFBC, usage 0x88).
3.154 - /// <para />
3.155 - /// Second press action: Repeats message.
3.156 - /// <para />
3.157 - /// Auto-repeat: No
3.158 - /// <para />
3.159 - /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08).
3.160 - /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310).
3.161 - /// </summary>
3.162 - Ext2 = 0x34,
3.163 - /// <summary>
3.164 - /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
3.165 - /// Collection (page 0xFFBC, usage 0x88).
3.166 - /// <para />
3.167 - /// Second press action: Repeats message.
3.168 - /// <para />
3.169 - /// Auto-repeat: No
3.170 - /// <para />
3.171 - /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08).
3.172 - /// </summary>
3.173 - Ext3 = 0x35,
3.174 - Ext4 = 0x36,
3.175 - Ext5 = 0x37,
3.176 - Ext6 = 0x38,
3.177 - Ext7 = 0x39,
3.178 - Ext8 = 0x3A,
3.179 - Ext9 = 0x80,
3.180 - Ext10 = 0x81,
3.181 - Ext11 = 0x6F,
3.182 - Zoom = 0x27,
3.183 - ChannelInput = 0x42,
3.184 - SubAudio = 0x2D,
3.185 - Channel10 = 0x3E,
3.186 - Channel11 = 0x3F,
3.187 - Channel12 = 0x40,
3.188 - /// <summary>
3.189 - /// First press action: Generates OEM2 HID message in the Media Center Vendor Specific
3.190 - /// Collection. This button is intended to control the front panel display of home entertainment
3.191 - /// computers. When this button is pressed, the display could be turned on or off, or the display
3.192 - /// mode could change.
3.193 - /// <para />
3.194 - /// Second press action: Repeats message.
3.195 - /// <para />
3.196 - /// Auto-repeat: No
3.197 - /// <para />
3.198 - /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application.
3.199 - /// </summary>
3.200 - Display = 0x4F,
3.201 - /// <summary>
3.202 - /// First press action: To be determined.
3.203 - /// <para />
3.204 - /// Second press action: Repeats message.
3.205 - /// <para />
3.206 - /// Auto-repeat: No
3.207 - /// </summary>
3.208 - Kiosk = 0x6A,
3.209 - NetworkSelection = 0x2C,
3.210 - BlueRayTool = 0x78,
3.211 - ChannelInfo = 0x41,
3.212 - VideoSelection = 0x61
3.213 - }
3.214 -
3.215 - /// <summary>
3.216 - /// Those codes come from experimenting with HP remotes.
3.217 - /// </summary>
3.218 - public enum HpMceButton: ushort
3.219 - {
3.220 - /// <summary>
3.221 - /// Displays visual imagery that is synchronized to the sound of your music tracks.
3.222 - /// <para />
3.223 - /// Second press action: Repeats message.
3.224 - /// <para />
3.225 - /// Auto-repeat: No
3.226 - /// <para />
3.227 - /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08).
3.228 - /// <para />
3.229 - /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks.
3.230 - /// </summary>
3.231 - Visualization = MceButton.Ext0,
3.232 - /// <summary>
3.233 - /// Plays a slide show of all the pictures on your hard disk drive.
3.234 - /// <para />
3.235 - /// Second press action: Repeats message.
3.236 - /// <para />
3.237 - /// Auto-repeat: No
3.238 - /// <para />
3.239 - /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08).
3.240 - /// <para />
3.241 - /// According to HP specs it plays a slide show of all the pictures on your hard disk drive.
3.242 - /// </summary>
3.243 - SlideShow = MceButton.Ext1,
3.244 - /// <summary>
3.245 - /// Eject optical drive.
3.246 - /// <para />
3.247 - /// Second press action: Repeats message.
3.248 - /// <para />
3.249 - /// Auto-repeat: No
3.250 - /// <para />
3.251 - /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08).
3.252 - /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310).
3.253 - /// </summary>
3.254 - Eject = MceButton.Ext2,
3.255 - /// <summary>
3.256 - /// Not sure what this should do.
3.257 - /// <para />
3.258 - /// Second press action: Repeats message.
3.259 - /// <para />
3.260 - /// Auto-repeat: No
3.261 - /// <para />
3.262 - /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08).
3.263 - /// </summary>
3.264 - InputSelection = MceButton.Ext3,
3.265 - }
3.266 -
3.267 - /// <summary>
3.268 - /// Usage Table for Consumer Controls
3.269 - /// 0x0C 0X01
3.270 - /// </summary>
3.271 - public enum ConsumerControl: ushort
3.272 - {
3.273 - Null = 0x0000,
3.274 - //
3.275 - Channel = 0x0086,
3.276 - MediaSelection = 0x0087,
3.277 - MediaSelectComputer = 0x0088,
3.278 - MediaSelectTV = 0x0089,
3.279 - MediaSelectWWW = 0x008A,
3.280 - MediaSelectDVD = 0x008B,
3.281 - MediaSelectTelephone = 0x008C,
3.282 - MediaSelectProgramGuide = 0x008D,
3.283 - MediaSelectVideoPhone = 0x008E,
3.284 - MediaSelectGames = 0x008F,
3.285 - MediaSelectMessages = 0x0090,
3.286 - MediaSelectCD = 0x0091,
3.287 - MediaSelectVCR = 0x0092,
3.288 - MediaSelectTuner = 0x0093,
3.289 - Quit = 0x0094,
3.290 - Help = 0x0095,
3.291 - MediaSelectTape = 0x0096,
3.292 - MediaSelectCable = 0x0097,
3.293 - MediaSelectSatellite = 0x0098,
3.294 - MediaSelectSecurity = 0x0099,
3.295 - MediaSelectHome = 0x009A,
3.296 - MediaSelectCall = 0x009B,
3.297 - ChannelIncrement = 0x009C,
3.298 - ChannelDecrement = 0x009D,
3.299 - MediaSelectSAP = 0x009E,
3.300 - //
3.301 - Play = 0x00B0,
3.302 - Pause = 0x00B1,
3.303 - Record = 0x00B2,
3.304 - FastForward = 0x00B3,
3.305 - Rewind = 0x00B4,
3.306 - ScanNextTrack = 0x00B5,
3.307 - ScanPreviousTrack = 0x00B6,
3.308 - Stop = 0x00B7,
3.309 - Eject = 0x00B8,
3.310 - RandomPlay = 0x00B9,
3.311 - SelectDisc = 0x00BA,
3.312 - EnterDisc = 0x00BB,
3.313 - Repeat = 0x00BC,
3.314 - Tracking = 0x00BD,
3.315 - TrackNormal = 0x00BE,
3.316 - SlowTracking = 0x00BF,
3.317 - FrameForward = 0x00C0,
3.318 - FrameBack = 0x00C1,
3.319 - Mark = 0x00C2,
3.320 - ClearMark = 0x00C3,
3.321 - RepeatFromMark = 0x00C4,
3.322 - ReturnToMark = 0x00C5,
3.323 - SearchMarkForward = 0x00C6,
3.324 - SearchMarkBackwards = 0x00C7,
3.325 - CounterReset = 0x00C8,
3.326 - ShowCounter = 0x00C9,
3.327 - TrackingIncrement = 0x00CA,
3.328 - TrackingDecrement = 0x00CB,
3.329 - StopEject = 0x00CC,
3.330 - PlayPause = 0x00CD,
3.331 - PlaySkip = 0x00CE,
3.332 -
3.333 - /// <summary>
3.334 - /// Audio controls
3.335 - /// </summary>
3.336 - Volume = 0x00E0,
3.337 - Balance = 0x00E1,
3.338 - Mute = 0x00E2,
3.339 - Bass = 0x00E3,
3.340 - Treble = 0x00E4,
3.341 - BassBoost = 0x00E5,
3.342 - SurroundMode = 0x00E6,
3.343 - Loudness = 0x00E7,
3.344 - MPX = 0x00E8,
3.345 - VolumeIncrement = 0x00E9,
3.346 - VolumeDecrement = 0x00EA,
3.347 -
3.348 - //Generic GUI Application Controls
3.349 - GenericGUIApplicationControls = 0x0200,
3.350 - AppCtrlNew = 0x0201,
3.351 - AppCtrlOpen = 0x0202,
3.352 - AppCtrlClose = 0x0203,
3.353 - AppCtrlExit = 0x0204,
3.354 - AppCtrlMaximize = 0x0205,
3.355 - AppCtrlMinimize = 0x0206,
3.356 - AppCtrlSave = 0x0207,
3.357 - AppCtrlPrint = 0x0208,
3.358 - AppCtrlProperties = 0x0209,
3.359 - AppCtrlUndo = 0x021A,
3.360 - AppCtrlCopy = 0x021B,
3.361 - AppCtrlCut = 0x021C,
3.362 - AppCtrlPaste = 0x021D,
3.363 - AppCtrlSelectAll = 0x021E,
3.364 - AppCtrlFind = 0x021F,
3.365 - AppCtrlFindAndReplace = 0x0220,
3.366 - AppCtrlSearch = 0x0221,
3.367 - AppCtrlGoTo = 0x0222,
3.368 - AppCtrlHome = 0x0223,
3.369 - AppCtrlBack = 0x0224,
3.370 - AppCtrlForward = 0x0225,
3.371 - AppCtrlStop = 0x0226,
3.372 - AppCtrlRefresh = 0x0227,
3.373 - AppCtrlPreviousLink = 0x0228,
3.374 - AppCtrlNextLink = 0x0229,
3.375 - AppCtrlBookmarks = 0x022A,
3.376 - AppCtrlHistory = 0x022B,
3.377 - AppCtrlSubscriptions = 0x022C,
3.378 - AppCtrlZoomIn = 0x022D,
3.379 - AppCtrlZoomOut = 0x022E,
3.380 - AppCtrlZoom = 0x022F,
3.381 - AppCtrlFullScreenView = 0x0230,
3.382 - AppCtrlNormalView = 0x0231,
3.383 - AppCtrlViewToggle = 0x0232,
3.384 - AppCtrlScrollUp = 0x0233,
3.385 - AppCtrlScrollDown = 0x0234,
3.386 - AppCtrlScroll = 0x0235,
3.387 - AppCtrlPanLeft = 0x0236,
3.388 - AppCtrlPanRight = 0x0237,
3.389 - AppCtrlPan = 0x0238,
3.390 - AppCtrlNewWindow = 0x0239,
3.391 - AppCtrlTileHorizontally = 0x023A,
3.392 - AppCtrlTileVertically = 0x023B,
3.393 - AppCtrlFormat = 0x023C,
3.394 - AppCtrlEdit = 0x023D,
3.395 - }
3.396 - }
3.397 -}
3.398 \ No newline at end of file
4.1 --- a/RemoteControlDevice.cs Sat Dec 06 13:14:16 2014 +0100
4.2 +++ b/RemoteControlDevice.cs Sat Dec 06 21:52:45 2014 +0100
4.3 @@ -13,93 +13,93 @@
4.4 namespace Devices.RemoteControl
4.5 {
4.6
4.7 - public enum InputDevice
4.8 - {
4.9 - Key,
4.10 - Mouse,
4.11 - OEM
4.12 - }
4.13 + public enum InputDevice
4.14 + {
4.15 + Key,
4.16 + Mouse,
4.17 + OEM
4.18 + }
4.19
4.20
4.21 - public enum RemoteControlButton
4.22 - {
4.23 - Clear,
4.24 - Down,
4.25 - Left,
4.26 - Digit0,
4.27 - Digit1,
4.28 - Digit2,
4.29 - Digit3,
4.30 - Digit4,
4.31 - Digit5,
4.32 - Digit6,
4.33 - Digit7,
4.34 - Digit8,
4.35 - Digit9,
4.36 - Enter,
4.37 - Right,
4.38 - Up,
4.39 + public enum RemoteControlButton
4.40 + {
4.41 + Clear,
4.42 + Down,
4.43 + Left,
4.44 + Digit0,
4.45 + Digit1,
4.46 + Digit2,
4.47 + Digit3,
4.48 + Digit4,
4.49 + Digit5,
4.50 + Digit6,
4.51 + Digit7,
4.52 + Digit8,
4.53 + Digit9,
4.54 + Enter,
4.55 + Right,
4.56 + Up,
4.57
4.58 - Back,
4.59 - ChannelDown,
4.60 - ChannelUp,
4.61 - FastForward,
4.62 - VolumeMute,
4.63 - Pause,
4.64 - Play,
4.65 + Back,
4.66 + ChannelDown,
4.67 + ChannelUp,
4.68 + FastForward,
4.69 + VolumeMute,
4.70 + Pause,
4.71 + Play,
4.72 PlayPause,
4.73 - Record,
4.74 - PreviousTrack,
4.75 - Rewind,
4.76 - NextTrack,
4.77 - Stop,
4.78 - VolumeDown,
4.79 - VolumeUp,
4.80 + Record,
4.81 + PreviousTrack,
4.82 + Rewind,
4.83 + NextTrack,
4.84 + Stop,
4.85 + VolumeDown,
4.86 + VolumeUp,
4.87
4.88 - RecordedTV,
4.89 - Guide,
4.90 - LiveTV,
4.91 - MoreInfo,
4.92 + RecordedTV,
4.93 + Guide,
4.94 + LiveTV,
4.95 + MoreInfo,
4.96 Print,
4.97 - DVDMenu,
4.98 - DVDAngle,
4.99 - DVDAudio,
4.100 - DVDSubtitle,
4.101 - MyMusic,
4.102 - MyPictures,
4.103 - MyVideos,
4.104 - MyTV,
4.105 - OEM1,
4.106 - OEM2,
4.107 - StandBy,
4.108 - TVJump,
4.109 + DVDMenu,
4.110 + DVDAngle,
4.111 + DVDAudio,
4.112 + DVDSubtitle,
4.113 + MyMusic,
4.114 + MyPictures,
4.115 + MyVideos,
4.116 + MyTV,
4.117 + OEM1,
4.118 + OEM2,
4.119 + StandBy,
4.120 + TVJump,
4.121
4.122 - Unknown
4.123 - }
4.124 + Unknown
4.125 + }
4.126
4.127
4.128 - #region RemoteControlEventArgs
4.129 + #region RemoteControlEventArgs
4.130
4.131 - public class RemoteControlEventArgs : EventArgs
4.132 - {
4.133 + public class RemoteControlEventArgs : EventArgs
4.134 + {
4.135 RemoteControlButton _rcb;
4.136 - InputDevice _device;
4.137 + InputDevice _device;
4.138 MceButton iMceButton;
4.139 ConsumerControl iConsumerControl;
4.140
4.141 public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
4.142 - {
4.143 + {
4.144 SetNullButtons();
4.145 //
4.146 - _rcb = rcb;
4.147 - _device = device;
4.148 - }
4.149 + _rcb = rcb;
4.150 + _device = device;
4.151 + }
4.152
4.153 public RemoteControlEventArgs(ConsumerControl aConsumerControl, InputDevice device)
4.154 {
4.155 SetNullButtons();
4.156 //
4.157 - iConsumerControl = aConsumerControl;
4.158 + iConsumerControl = aConsumerControl;
4.159 _device = device;
4.160 }
4.161
4.162 @@ -108,7 +108,7 @@
4.163 {
4.164 SetNullButtons();
4.165 //
4.166 - iMceButton = mce;
4.167 + iMceButton = mce;
4.168 _device = device;
4.169 }
4.170
4.171 @@ -119,18 +119,18 @@
4.172 _rcb = RemoteControlButton.Unknown;
4.173 }
4.174
4.175 - public RemoteControlEventArgs()
4.176 - {
4.177 + public RemoteControlEventArgs()
4.178 + {
4.179 iMceButton = MceButton.Null;
4.180 - _rcb = RemoteControlButton.Unknown;
4.181 - _device = InputDevice.Key;
4.182 - }
4.183 + _rcb = RemoteControlButton.Unknown;
4.184 + _device = InputDevice.Key;
4.185 + }
4.186
4.187 - public RemoteControlButton Button
4.188 - {
4.189 - get { return _rcb; }
4.190 - set { _rcb = value; }
4.191 - }
4.192 + public RemoteControlButton Button
4.193 + {
4.194 + get { return _rcb; }
4.195 + set { _rcb = value; }
4.196 + }
4.197
4.198 public MceButton MceButton
4.199 {
4.200 @@ -144,20 +144,20 @@
4.201 set { iConsumerControl = value; }
4.202 }
4.203
4.204 - public InputDevice Device
4.205 - {
4.206 - get { return _device; }
4.207 - set { _device = value; }
4.208 - }
4.209 - }
4.210 + public InputDevice Device
4.211 + {
4.212 + get { return _device; }
4.213 + set { _device = value; }
4.214 + }
4.215 + }
4.216
4.217 - #endregion RemoteControlEventArgs
4.218 + #endregion RemoteControlEventArgs
4.219
4.220
4.221 - public sealed class RemoteControlDevice
4.222 - {
4.223 - public delegate bool RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
4.224 - public event RemoteControlDeviceEventHandler ButtonPressed;
4.225 + public sealed class RemoteControlDevice
4.226 + {
4.227 + public delegate bool RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
4.228 + public event RemoteControlDeviceEventHandler ButtonPressed;
4.229
4.230 /// <summary>
4.231 /// Return true if the usage was processed.
4.232 @@ -165,22 +165,22 @@
4.233 /// <param name="aUsage"></param>
4.234 /// <returns></returns>
4.235 public delegate bool HidUsageHandler(ushort aUsage);
4.236 -
4.237
4.238 - //-------------------------------------------------------------
4.239 - // constructors
4.240 - //-------------------------------------------------------------
4.241
4.242 - public RemoteControlDevice(IntPtr aHWND)
4.243 - {
4.244 - // Register the input device to receive the commands from the
4.245 - // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
4.246 - // for the vendor defined usage page.
4.247 + //-------------------------------------------------------------
4.248 + // constructors
4.249 + //-------------------------------------------------------------
4.250
4.251 - RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[5];
4.252 + public RemoteControlDevice(IntPtr aHWND)
4.253 + {
4.254 + // Register the input device to receive the commands from the
4.255 + // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
4.256 + // for the vendor defined usage page.
4.257 +
4.258 + RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[4];
4.259
4.260 int i = 0;
4.261 - rid[i].usUsagePage = (ushort)Hid.UsagePage.MceRemote;
4.262 + rid[i].usUsagePage = (ushort)Hid.UsagePage.MceRemote;
4.263 rid[i].usUsage = (ushort)Hid.UsageIdMce.MceRemote;
4.264 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
4.265 rid[i].hwndTarget = aHWND;
4.266 @@ -203,11 +203,11 @@
4.267 rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
4.268 rid[i].hwndTarget = aHWND;
4.269
4.270 - i++;
4.271 - rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
4.272 - rid[i].usUsage = (ushort)Hid.UsageIdGenericDesktop.Keyboard;
4.273 - rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
4.274 - rid[i].hwndTarget = aHWND;
4.275 + //i++;
4.276 + //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
4.277 + //rid[i].usUsage = (ushort)Hid.UsageIdGenericDesktop.Keyboard;
4.278 + //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
4.279 + //rid[i].hwndTarget = aHWND;
4.280
4.281 //i++;
4.282 //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
4.283 @@ -216,55 +216,55 @@
4.284 //rid[i].hwndTarget = aHWND;
4.285
4.286
4.287 - if (!Function.RegisterRawInputDevices(rid,(uint) rid.Length,(uint) Marshal.SizeOf(rid[0])))
4.288 - {
4.289 + if (!Function.RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0])))
4.290 + {
4.291 throw new ApplicationException("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
4.292 - }
4.293 - }
4.294 + }
4.295 + }
4.296
4.297
4.298 - //-------------------------------------------------------------
4.299 - // methods
4.300 - //-------------------------------------------------------------
4.301 + //-------------------------------------------------------------
4.302 + // methods
4.303 + //-------------------------------------------------------------
4.304
4.305 - public void ProcessMessage(Message message)
4.306 - {
4.307 - switch (message.Msg)
4.308 - {
4.309 - case Const.WM_KEYDOWN:
4.310 + public void ProcessMessage(Message message)
4.311 + {
4.312 + switch (message.Msg)
4.313 + {
4.314 + case Const.WM_KEYDOWN:
4.315 ProcessKeyDown(message.WParam);
4.316 - break;
4.317 + break;
4.318 case Const.WM_INPUT:
4.319 //Returning zero means we processed that message.
4.320 message.Result = new IntPtr(0);
4.321 - ProcessInputCommand(ref message);
4.322 - break;
4.323 - }
4.324 + ProcessInputCommand(ref message);
4.325 + break;
4.326 + }
4.327
4.328 - }
4.329 + }
4.330
4.331
4.332 - //-------------------------------------------------------------
4.333 - // methods (helpers)
4.334 - //-------------------------------------------------------------
4.335 + //-------------------------------------------------------------
4.336 + // methods (helpers)
4.337 + //-------------------------------------------------------------
4.338
4.339 - private void ProcessKeyDown(IntPtr wParam)
4.340 - {
4.341 - RemoteControlButton rcb = RemoteControlButton.Unknown;
4.342 + private void ProcessKeyDown(IntPtr wParam)
4.343 + {
4.344 + RemoteControlButton rcb = RemoteControlButton.Unknown;
4.345
4.346 switch (wParam.ToInt32())
4.347 - {
4.348 - case (int) Keys.Escape:
4.349 - rcb = RemoteControlButton.Clear;
4.350 + {
4.351 + case (int)Keys.Escape:
4.352 + rcb = RemoteControlButton.Clear;
4.353 break;
4.354 case (int)Keys.Up:
4.355 rcb = RemoteControlButton.Up;
4.356 break;
4.357 - case (int) Keys.Down:
4.358 - rcb = RemoteControlButton.Down;
4.359 - break;
4.360 - case (int) Keys.Left:
4.361 - rcb = RemoteControlButton.Left;
4.362 + case (int)Keys.Down:
4.363 + rcb = RemoteControlButton.Down;
4.364 + break;
4.365 + case (int)Keys.Left:
4.366 + rcb = RemoteControlButton.Left;
4.367 break;
4.368 case (int)Keys.Right:
4.369 rcb = RemoteControlButton.Right;
4.370 @@ -272,44 +272,44 @@
4.371 case (int)Keys.Enter:
4.372 rcb = RemoteControlButton.Enter;
4.373 break;
4.374 - case (int) Keys.D0:
4.375 - rcb = RemoteControlButton.Digit0;
4.376 - break;
4.377 - case (int) Keys.D1:
4.378 - rcb = RemoteControlButton.Digit1;
4.379 - break;
4.380 - case (int) Keys.D2:
4.381 - rcb = RemoteControlButton.Digit2;
4.382 - break;
4.383 - case (int) Keys.D3:
4.384 - rcb = RemoteControlButton.Digit3;
4.385 - break;
4.386 - case (int) Keys.D4:
4.387 - rcb = RemoteControlButton.Digit4;
4.388 - break;
4.389 - case (int) Keys.D5:
4.390 - rcb = RemoteControlButton.Digit5;
4.391 - break;
4.392 - case (int) Keys.D6:
4.393 - rcb = RemoteControlButton.Digit6;
4.394 - break;
4.395 - case (int) Keys.D7:
4.396 - rcb = RemoteControlButton.Digit7;
4.397 - break;
4.398 - case (int) Keys.D8:
4.399 - rcb = RemoteControlButton.Digit8;
4.400 - break;
4.401 - case (int) Keys.D9:
4.402 - rcb = RemoteControlButton.Digit9;
4.403 + case (int)Keys.D0:
4.404 + rcb = RemoteControlButton.Digit0;
4.405 break;
4.406 - }
4.407 + case (int)Keys.D1:
4.408 + rcb = RemoteControlButton.Digit1;
4.409 + break;
4.410 + case (int)Keys.D2:
4.411 + rcb = RemoteControlButton.Digit2;
4.412 + break;
4.413 + case (int)Keys.D3:
4.414 + rcb = RemoteControlButton.Digit3;
4.415 + break;
4.416 + case (int)Keys.D4:
4.417 + rcb = RemoteControlButton.Digit4;
4.418 + break;
4.419 + case (int)Keys.D5:
4.420 + rcb = RemoteControlButton.Digit5;
4.421 + break;
4.422 + case (int)Keys.D6:
4.423 + rcb = RemoteControlButton.Digit6;
4.424 + break;
4.425 + case (int)Keys.D7:
4.426 + rcb = RemoteControlButton.Digit7;
4.427 + break;
4.428 + case (int)Keys.D8:
4.429 + rcb = RemoteControlButton.Digit8;
4.430 + break;
4.431 + case (int)Keys.D9:
4.432 + rcb = RemoteControlButton.Digit9;
4.433 + break;
4.434 + }
4.435
4.436 if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
4.437 {
4.438 Debug.WriteLine("KeyDown: " + rcb.ToString());
4.439 this.ButtonPressed(this, new RemoteControlEventArgs(rcb, InputDevice.Key));
4.440 }
4.441 - }
4.442 + }
4.443
4.444
4.445 /// <summary>
4.446 @@ -356,7 +356,7 @@
4.447 {
4.448 if (this.ButtonPressed != null)
4.449 {
4.450 - return this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)aUsage, InputDevice.OEM));
4.451 + return this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)aUsage, InputDevice.OEM));
4.452 }
4.453 return false;
4.454 }
4.455 @@ -368,156 +368,45 @@
4.456 }
4.457
4.458
4.459 - private void ProcessInputCommand(ref Message message)
4.460 - {
4.461 + private void ProcessInputCommand(ref Message message)
4.462 + {
4.463 //We received a WM_INPUT message
4.464 Debug.WriteLine("================WM_INPUT================");
4.465
4.466 - //Check if we received this message while in background or foreground
4.467 - if (Macro.GET_RAWINPUT_CODE_WPARAM(message.WParam) == Const.RIM_INPUT)
4.468 + Hid.HidEvent hidEvent = new Hid.HidEvent(message);
4.469 + hidEvent.DebugWrite();
4.470 +
4.471 + if (!hidEvent.IsValid || !hidEvent.IsGeneric)
4.472 {
4.473 - Debug.WriteLine("================FOREGROUND");
4.474 - }
4.475 - else if (Macro.GET_RAWINPUT_CODE_WPARAM(message.WParam) == Const.RIM_INPUTSINK)
4.476 - {
4.477 - Debug.WriteLine("================BACKGROUND");
4.478 + Debug.WriteLine("Skipping HID message.");
4.479 + return;
4.480 }
4.481
4.482 - //Declare some pointers
4.483 - IntPtr rawInputBuffer = IntPtr.Zero;
4.484 - //My understanding is that this is basically our HID descriptor
4.485 - IntPtr preParsedData = IntPtr.Zero;
4.486
4.487 - try
4.488 + HidUsageHandler usagePageHandler = null;
4.489 +
4.490 + //Check if this an MCE remote HID message
4.491 + if (hidEvent.UsagePage == (ushort)Hid.UsagePage.MceRemote && hidEvent.UsageCollection == (ushort)Hid.UsageIdMce.MceRemote)
4.492 {
4.493 - //Fetch raw input
4.494 - RAWINPUT rawInput = new RAWINPUT();
4.495 - if (!RawInput.GetRawInputData(message.LParam, ref rawInput, ref rawInputBuffer))
4.496 - {
4.497 - return;
4.498 - }
4.499 + usagePageHandler = HidMceRemoteHandler;
4.500 + }
4.501 + //Check if this is a consumer control HID message
4.502 + else if (hidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer && hidEvent.UsageCollection == (ushort)Hid.UsageIdConsumer.ConsumerControl)
4.503 + {
4.504 + usagePageHandler = HidConsumerDeviceHandler;
4.505 + }
4.506 + //Unknown HID message
4.507 + else
4.508 + {
4.509 + Debug.WriteLine("Unknown HID message.");
4.510 + return;
4.511 + }
4.512
4.513 + foreach (ushort usage in hidEvent.Usages)
4.514 + {
4.515 + usagePageHandler(usage);
4.516 + }
4.517 + }
4.518 + }
4.519 +}
4.520
4.521 -
4.522 - //Fetch device info
4.523 - RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO();
4.524 - if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
4.525 - {
4.526 - return;
4.527 - }
4.528 -
4.529 - //Get various information about this HID device
4.530 - Hid.HidDevice device = new Hid.HidDevice(rawInput.header.hDevice);
4.531 - device.DebugWrite();
4.532 -
4.533 -
4.534 -
4.535 -
4.536 - if (rawInput.header.dwType == Const.RIM_TYPEHID) //Check that our raw input is HID
4.537 - {
4.538 - Debug.WriteLine("WM_INPUT source device is HID.");
4.539 - //Get Usage Page and Usage
4.540 - Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
4.541 -
4.542 -
4.543 - preParsedData = RawInput.GetPreParsedData(rawInput.header.hDevice);
4.544 -
4.545 - //
4.546 - HidUsageHandler usagePageHandler=null;
4.547 -
4.548 - //Check if this an MCE remote HID message
4.549 - if (deviceInfo.hid.usUsagePage == (ushort)Hid.UsagePage.MceRemote && deviceInfo.hid.usUsage == (ushort)Hid.UsageIdMce.MceRemote)
4.550 - {
4.551 - usagePageHandler = HidMceRemoteHandler;
4.552 - }
4.553 - //Check if this is a consumer control HID message
4.554 - else if (deviceInfo.hid.usUsagePage == (ushort)Hid.UsagePage.Consumer && deviceInfo.hid.usUsage == (ushort)Hid.UsageIdConsumer.ConsumerControl)
4.555 - {
4.556 - usagePageHandler = HidConsumerDeviceHandler;
4.557 - }
4.558 - //Unknown HID message
4.559 - else
4.560 - {
4.561 - Debug.WriteLine("Unknown HID message.");
4.562 - return;
4.563 - }
4.564 -
4.565 - 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
4.566 - && rawInput.hid.dwCount > 0)) //Check that we have at least one HID msg
4.567 - {
4.568 - return;
4.569 - }
4.570 -
4.571 -
4.572 - //Allocate a buffer for one HID input
4.573 - byte[] hidInputReport = new byte[rawInput.hid.dwSizeHid];
4.574 -
4.575 - Debug.WriteLine("Raw input contains " + rawInput.hid.dwCount + " HID input report(s)");
4.576 -
4.577 - //For each HID input report in our raw input
4.578 - for (int i = 0; i < rawInput.hid.dwCount; i++)
4.579 - {
4.580 - //Compute the address from which to copy our HID input
4.581 - int hidInputOffset = 0;
4.582 - unsafe
4.583 - {
4.584 - byte* source = (byte*)rawInputBuffer;
4.585 - source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
4.586 - hidInputOffset = (int)source;
4.587 - }
4.588 -
4.589 - //Copy HID input into our buffer
4.590 - Marshal.Copy(new IntPtr(hidInputOffset), hidInputReport, 0, (int)rawInput.hid.dwSizeHid);
4.591 -
4.592 - //Print HID input report in our debug output
4.593 - string hidDump = "HID input report: ";
4.594 - foreach (byte b in hidInputReport)
4.595 - {
4.596 - hidDump += b.ToString("X2");
4.597 - }
4.598 - Debug.WriteLine(hidDump);
4.599 -
4.600 - //Proper parsing now
4.601 - uint usageCount = 1; //Assuming a single usage per input report. Is that correct?
4.602 - Win32.USAGE_AND_PAGE[] usages = new Win32.USAGE_AND_PAGE[usageCount];
4.603 - Win32.HidStatus status = Win32.Function.HidP_GetUsagesEx(Win32.HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, preParsedData, hidInputReport, (uint)hidInputReport.Length);
4.604 - if (status != Win32.HidStatus.HIDP_STATUS_SUCCESS)
4.605 - {
4.606 - Debug.WriteLine("Could not parse HID data!");
4.607 - }
4.608 - else
4.609 - {
4.610 - Debug.WriteLine("UsagePage: 0x" + usages[0].UsagePage.ToString("X4"));
4.611 - Debug.WriteLine("Usage: 0x" + usages[0].Usage.ToString("X4"));
4.612 - //Call on our Usage Page handler
4.613 - usagePageHandler(usages[0].Usage);
4.614 - }
4.615 - }
4.616 -
4.617 - }
4.618 - else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
4.619 - {
4.620 - Debug.WriteLine("WM_INPUT source device is Mouse.");
4.621 - // do mouse handling...
4.622 - }
4.623 - else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
4.624 - {
4.625 - Debug.WriteLine("WM_INPUT source device is Keyboard.");
4.626 - // do keyboard handling...
4.627 - Debug.WriteLine("Type: " + deviceInfo.keyboard.dwType.ToString());
4.628 - Debug.WriteLine("SubType: " + deviceInfo.keyboard.dwSubType.ToString());
4.629 - Debug.WriteLine("Mode: " + deviceInfo.keyboard.dwKeyboardMode.ToString());
4.630 - Debug.WriteLine("Number of function keys: " + deviceInfo.keyboard.dwNumberOfFunctionKeys.ToString());
4.631 - Debug.WriteLine("Number of indicators: " + deviceInfo.keyboard.dwNumberOfIndicators.ToString());
4.632 - Debug.WriteLine("Number of keys total: " + deviceInfo.keyboard.dwNumberOfKeysTotal.ToString());
4.633 - }
4.634 - }
4.635 - finally
4.636 - {
4.637 - //Always executed when leaving our try block
4.638 - Marshal.FreeHGlobal(rawInputBuffer);
4.639 - Marshal.FreeHGlobal(preParsedData);
4.640 - }
4.641 - }
4.642 - }
4.643 -}
5.1 --- a/RemoteControlSample.csproj Sat Dec 06 13:14:16 2014 +0100
5.2 +++ b/RemoteControlSample.csproj Sat Dec 06 21:52:45 2014 +0100
5.3 @@ -127,8 +127,9 @@
5.4 <Compile Include="Form1.cs">
5.5 <SubType>Form</SubType>
5.6 </Compile>
5.7 + <Compile Include="HidEvent.cs" />
5.8 + <Compile Include="HidUsageTables.cs" />
5.9 <Compile Include="HidUtil.cs" />
5.10 - <Compile Include="HumanInterfaceDevice.cs" />
5.11 <Compile Include="RawInput.cs" />
5.12 <Compile Include="RemoteControlDevice.cs">
5.13 <SubType>Code</SubType>