More code consoludation. Supporting multiple HID input per message.
authorsl
Sat, 08 Nov 2014 12:01:19 +0100
changeset 112ff6dbe0d356
parent 10 17f8421146ba
child 12 ff7a8955f82d
More code consoludation. Supporting multiple HID input per message.
HumanInterfaceDevice.cs
RemoteControlDevice.cs
     1.1 --- a/HumanInterfaceDevice.cs	Fri Nov 07 22:12:22 2014 +0100
     1.2 +++ b/HumanInterfaceDevice.cs	Sat Nov 08 12:01:19 2014 +0100
     1.3 @@ -64,7 +64,7 @@
     1.4          /// <summary>
     1.5          ///
     1.6          /// </summary>
     1.7 -        public enum MceButton
     1.8 +        public enum MceButton: ushort
     1.9          {
    1.10              /// <summary>
    1.11              /// Not defined by the Microsoft specs.
    1.12 @@ -188,6 +188,9 @@
    1.13              VideoSelection          =   0x61
    1.14          }
    1.15  
    1.16 +        /// <summary>
    1.17 +        /// Those codes come from experimenting with HP remotes.
    1.18 +        /// </summary>
    1.19          public enum HpMceButton: ushort
    1.20          {
    1.21              /// <summary>
     2.1 --- a/RemoteControlDevice.cs	Fri Nov 07 22:12:22 2014 +0100
     2.2 +++ b/RemoteControlDevice.cs	Sat Nov 08 12:01:19 2014 +0100
     2.3 @@ -353,94 +353,101 @@
     2.4              try
     2.5              {
     2.6                  //Fetch raw input
     2.7 -                RAWINPUT raw = new RAWINPUT();
     2.8 -                if (!RawInput.GetRawInputData(message.LParam, ref raw, ref rawInputBuffer))
     2.9 +                RAWINPUT rawInput = new RAWINPUT();
    2.10 +                if (!RawInput.GetRawInputData(message.LParam, ref rawInput, ref rawInputBuffer))
    2.11                  {
    2.12                      return;
    2.13                  }
    2.14  
    2.15                  //Fetch device info
    2.16                  RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO();
    2.17 -                if (!RawInput.GetDeviceInfo(raw.header.hDevice, ref deviceInfo))
    2.18 +                if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
    2.19                  {
    2.20                      return;
    2.21                  }
    2.22 +               
    2.23  
    2.24 -                //Check type of input device and quite if we don't like it
    2.25 -                switch (deviceInfo.dwType)
    2.26 +                if (rawInput.header.dwType == Const.RIM_TYPEHID)  //Check that our raw input is HID                        
    2.27                  {
    2.28 -                    case Const.RIM_TYPEHID:
    2.29 -                        Debug.WriteLine("WM_INPUT source device is HID.");
    2.30 -                        break;
    2.31 -                    case Const.RIM_TYPEMOUSE:
    2.32 -                        Debug.WriteLine("WM_INPUT source device is Mouse.");
    2.33 -                        return;
    2.34 -                    case Const.RIM_TYPEKEYBOARD:
    2.35 -                        Debug.WriteLine("WM_INPUT source device is Keyboard.");
    2.36 -                        return;
    2.37 -                    default:
    2.38 -                        Debug.WriteLine("WM_INPUT source device is Unknown.");
    2.39 -                        return;
    2.40 -                }
    2.41 -
    2.42 -                //Get Usage Page and Usage
    2.43 -                Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
    2.44 -
    2.45 -
    2.46 -                if (raw.header.dwType == Const.RIM_TYPEHID  //Check that our raw input is HID
    2.47 -                    && raw.hid.dwSizeHid > 1    //Make sure our HID msg size more than 1. In fact the first ushort is irrelevant to us for now
    2.48 -                    && raw.hid.dwCount > 0)     //Check that we have at least one HID msg
    2.49 -                {
    2.50 -                    //TODO: for each HID message
    2.51 -
    2.52 -                    //Allocate a buffer for one HID message
    2.53 -                    byte[] bRawData = new byte[raw.hid.dwSizeHid];
    2.54 -
    2.55 -                    //Compute the address from which to copy our HID message
    2.56 -                    int pRawData = 0;
    2.57 -                    unsafe
    2.58 -                    {
    2.59 -                        byte* source = (byte*)rawInputBuffer;
    2.60 -                        source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID);
    2.61 -                        pRawData = (int)source;
    2.62 -                    }
    2.63 -
    2.64 -                    //Copy HID message into our buffer
    2.65 -                    Marshal.Copy(new IntPtr(pRawData), bRawData, 0, raw.hid.dwSizeHid);
    2.66 -                    //bRawData[0] //Not sure what's the meaning of the code at offset 0
    2.67 -                    //TODO: check size before access
    2.68 -                    int rawData = bRawData[1]; //Get button code
    2.69 -                    //Print HID codes in our debug output
    2.70 -                    string hidDump = "HID " + raw.hid.dwCount + "/" + raw.hid.dwSizeHid + ":";
    2.71 -                    foreach (byte b in bRawData)
    2.72 -                    {
    2.73 -                        hidDump += b.ToString("X2");
    2.74 -                    }
    2.75 -                    Debug.WriteLine(hidDump);
    2.76 -
    2.77 +                    Debug.WriteLine("WM_INPUT source device is HID.");
    2.78 +                    //Get Usage Page and Usage
    2.79 +                    Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
    2.80  
    2.81                      //Make sure both usage page and usage are matching MCE remote
    2.82 +                    //TODO: handle more that just MCE usage page.
    2.83                      if (deviceInfo.hid.usUsagePage != (ushort)Hid.UsagePage.MceRemote || deviceInfo.hid.usUsage != (ushort)Hid.UsageId.MceRemoteUsage)
    2.84                      {
    2.85                          Debug.WriteLine("Not MCE remote page and usage.");
    2.86                          return;
    2.87                      }
    2.88  
    2.89 -                    if (Enum.IsDefined(typeof(MceButton), rawData) && rawData != 0) //Our button is a known MCE button
    2.90 +                    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
    2.91 +                        && rawInput.hid.dwCount > 0))    //Check that we have at least one HID msg
    2.92                      {
    2.93 -                        if (this.ButtonPressed != null) //What's that?
    2.94 +                        return;
    2.95 +                    }
    2.96 +
    2.97 +
    2.98 +                    //Allocate a buffer for one HID input
    2.99 +                    byte[] hidInput = new byte[rawInput.hid.dwSizeHid];
   2.100 +
   2.101 +                    //For each HID input in our raw input
   2.102 +                    for (int i = 0; i < rawInput.hid.dwCount; i++)
   2.103 +                    {
   2.104 +                        //Compute the address from which to copy our HID input
   2.105 +                        int hidInputOffset = 0;
   2.106 +                        unsafe
   2.107                          {
   2.108 -                            this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)rawData, GetDevice(message.LParam.ToInt32())));
   2.109 +                            byte* source = (byte*)rawInputBuffer;
   2.110 +                            source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
   2.111 +                            hidInputOffset = (int)source;
   2.112 +                        }
   2.113 +
   2.114 +                        //Copy HID input into our buffer
   2.115 +                        Marshal.Copy(new IntPtr(hidInputOffset), hidInput, 0, rawInput.hid.dwSizeHid);
   2.116 +
   2.117 +                        //Print HID raw input in our debug output
   2.118 +                        string hidDump = "HID " + rawInput.hid.dwCount + "/" + rawInput.hid.dwSizeHid + ":";
   2.119 +                        foreach (byte b in hidInput)
   2.120 +                        {
   2.121 +                            hidDump += b.ToString("X2");
   2.122 +                        }
   2.123 +                        Debug.WriteLine(hidDump);
   2.124 +                        
   2.125 +                        ushort usage = 0;
   2.126 +                        //hidInput[0] //Not sure what's the meaning of the code at offset 0
   2.127 +                        if (hidInput.Length == 2)
   2.128 +                        {
   2.129 +                            //Single byte code
   2.130 +                            usage = hidInput[1]; //Get button code
   2.131 +                        }
   2.132 +                        else if (hidInput.Length > 2) //Defensive
   2.133 +                        {
   2.134 +                            //Assuming double bytes code
   2.135 +                            usage = (ushort)((hidInput[1] << 2) + hidInput[2]);
   2.136 +                        }
   2.137 +
   2.138 +                        //
   2.139 +                        if (Enum.IsDefined(typeof(MceButton), usage) && usage != 0) //Our button is a known MCE button
   2.140 +                        {
   2.141 +                            if (this.ButtonPressed != null) //What's that?
   2.142 +                            {
   2.143 +                                this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)usage, InputDevice.OEM));
   2.144 +                            }
   2.145                          }
   2.146                      }
   2.147 +
   2.148                  }
   2.149 -                else if (raw.header.dwType == Const.RIM_TYPEMOUSE)
   2.150 +                else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
   2.151                  {
   2.152 +                    Debug.WriteLine("WM_INPUT source device is Mouse.");
   2.153                      // do mouse handling...
   2.154                  }
   2.155 -                else if (raw.header.dwType == Const.RIM_TYPEKEYBOARD)
   2.156 +                else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
   2.157                  {
   2.158 +                    Debug.WriteLine("WM_INPUT source device is Keyboard.");
   2.159                      // do keyboard handling...
   2.160 +
   2.161                  }
   2.162              }
   2.163              finally