├── VMultiDll ├── hid.lib ├── SetupAPI.Lib ├── hidclass.lib ├── hidparse.lib ├── targetver.h ├── LibPath.txt ├── stdafx.h ├── Dll.cpp ├── vmulticlient.h ├── VMultiDll.vcxproj.filters ├── vmulticommon.h ├── hidport.h ├── VMultiDll.vcxproj └── client.c ├── VMultiTest ├── App.config ├── Properties │ └── AssemblyInfo.cs ├── VMultiTest.csproj └── Program.cs ├── VMultiDllWrapper ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ └── AssemblyInfo.cs ├── MultitouchReport.cs ├── JoystickReport.cs ├── VMultiDllWrapper.csproj ├── KeyboardReport.cs └── VMulti.cs ├── README.md ├── .gitattributes ├── .gitignore └── VMultiDll.sln /VMultiDll/hid.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duzhi5368/FKHIDKeyboardSimTest/HEAD/VMultiDll/hid.lib -------------------------------------------------------------------------------- /VMultiDll/SetupAPI.Lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duzhi5368/FKHIDKeyboardSimTest/HEAD/VMultiDll/SetupAPI.Lib -------------------------------------------------------------------------------- /VMultiDll/hidclass.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duzhi5368/FKHIDKeyboardSimTest/HEAD/VMultiDll/hidclass.lib -------------------------------------------------------------------------------- /VMultiDll/hidparse.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duzhi5368/FKHIDKeyboardSimTest/HEAD/VMultiDll/hidparse.lib -------------------------------------------------------------------------------- /VMultiTest/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /VMultiDllWrapper/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /VMultiDll/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | VMultiDll 2 | ========= 3 | Dll client for [vmulti drivers](https://code.google.com/p/vmulti/). For C# implementations. 4 | 5 | Usage 6 | --------- 7 | Reference VMultiDllWrapper.dll to your C# project and use the VMulti class to update the vmulti devices. 8 | Keep both VMulti.dll and VMultiDllWrapper.dll next to your executable. 9 | 10 | License 11 | --------- 12 | MIT License 13 | -------------------------------------------------------------------------------- /VMultiDll/LibPath.txt: -------------------------------------------------------------------------------- 1 | SetupAPI.Lib C:\Program Files (x86)\Windows Kits\8.0\Lib\win8\um\x86 2 | Hid.lib C:\Program Files (x86)\Windows Kits\8.0\Lib\win8\um\x86 3 | 4 | Hidclass.lib C:\Program Files (x86)\Windows Kits\10\Lib\win7\km\x86 5 | Hidparse.lib C:\Program Files (x86)\Windows Kits\10\Lib\win7\km\x86 6 | 7 | hidparse.sys C:\Windows\System32\drivers 8 | hid.dll C:\Windows\System32 9 | setupapi.dll C:\Windows\System32 10 | advapi32.dll C:\Windows\System32 -------------------------------------------------------------------------------- /VMultiDll/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files: 12 | #include 13 | 14 | 15 | 16 | // TODO: reference additional headers your program requires here 17 | -------------------------------------------------------------------------------- /VMultiDll/Dll.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | 4 | #pragma comment(lib, "hidparse.lib") 5 | #pragma comment(lib, "hidclass.lib") 6 | #pragma comment(lib, "hid.lib") 7 | #pragma comment(lib, "setupapi.lib") 8 | 9 | extern "C" 10 | { 11 | #include "vmulticlient.h" 12 | } 13 | 14 | extern "C" 15 | { 16 | __declspec(dllexport) void __stdcall MyHelloWorld() 17 | { 18 | printf ("Hello World !\n"); 19 | } 20 | } 21 | 22 | extern "C" _declspec(dllexport) int __stdcall MySum(int a, int b) 23 | { 24 | return a + b; 25 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /VMultiDllWrapper/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace VMultiDllWrapper.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /VMultiDll/vmulticlient.h: -------------------------------------------------------------------------------- 1 | #if !defined(_VMULTI_CLIENT_H_) 2 | #define _VMULTI_CLIENT_H_ 3 | 4 | #include "vmulticommon.h" 5 | 6 | typedef struct _vmulti_client_t* pvmulti_client; 7 | 8 | __declspec(dllexport) pvmulti_client vmulti_alloc(void); 9 | 10 | __declspec(dllexport) void vmulti_free(pvmulti_client vmulti); 11 | 12 | __declspec(dllexport) BOOL vmulti_connect(pvmulti_client vmulti,int i); 13 | 14 | __declspec(dllexport) void vmulti_disconnect(pvmulti_client vmulti); 15 | 16 | __declspec(dllexport) BOOL vmulti_update_mouse(pvmulti_client vmulti, BYTE button, USHORT x, USHORT y, BYTE wheelPosition); 17 | 18 | __declspec(dllexport) BOOL vmulti_update_relative_mouse(pvmulti_client vmulti, BYTE button, BYTE x, BYTE y, BYTE wheelPosition); 19 | 20 | __declspec(dllexport) BOOL vmulti_update_digi(pvmulti_client vmulti, BYTE status, USHORT x, USHORT y); 21 | 22 | __declspec(dllexport) BOOL vmulti_update_multitouch(pvmulti_client vmulti, PTOUCH pTouch, BYTE actualCount,BYTE request_type,BYTE report_control_id); 23 | 24 | __declspec(dllexport) BOOL vmulti_update_joystick(pvmulti_client vmulti, USHORT buttons, BYTE hat, BYTE x, BYTE y, BYTE z, BYTE rz, BYTE throttle); 25 | 26 | __declspec(dllexport) BOOL vmulti_update_keyboard(pvmulti_client vmulti, BYTE shiftKeyFlags, BYTE keyCodes[KBD_KEY_CODES]); 27 | 28 | __declspec(dllexport) BOOL vmulti_write_message(pvmulti_client vmulti, VMultiMessageReport* pReport); 29 | 30 | __declspec(dllexport) BOOL vmulti_read_message(pvmulti_client vmulti, VMultiMessageReport* pReport); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /VMultiTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("VMultiTest")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("VMultiTest")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("eaf44028-ee3c-4cc3-960a-02e7fa824cba")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /VMultiDllWrapper/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("VMultiDllWrapper")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("VMultiDllWrapper")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("09ffe03e-bb91-4eda-b3c1-0b3a970fd98c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /VMultiDll/VMultiDll.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | -------------------------------------------------------------------------------- /VMultiDllWrapper/MultitouchReport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace VMultiDllWrapper 8 | { 9 | 10 | public class MultitouchPointerInfo 11 | { 12 | private const byte MULTI_TIPSWITCH_BIT = 1; 13 | private const byte MULTI_IN_RANGE_BIT = 2; 14 | private const byte MULTI_CONFIDENCE_BIT = 4; 15 | 16 | private const uint MULTI_MIN_COORDINATE = 0x0000; 17 | private const uint MULTI_MAX_COORDINATE = 0x7FFF; 18 | 19 | private const uint MULTI_MAX_COUNT = 20; 20 | 21 | public bool Down = false; 22 | public bool Hover = false; 23 | public byte ID = 0; 24 | public double X = 0; 25 | public double Y = 0; 26 | 27 | public MultitouchPointerInfoRaw getPointerInfoRaw() 28 | { 29 | MultitouchPointerInfoRaw info = new MultitouchPointerInfoRaw(); 30 | if (Down) 31 | { 32 | info.Status = MULTI_TIPSWITCH_BIT | MULTI_IN_RANGE_BIT | MULTI_CONFIDENCE_BIT; 33 | } 34 | else if(Hover) 35 | { 36 | info.Status = MULTI_IN_RANGE_BIT | MULTI_CONFIDENCE_BIT; 37 | } 38 | else 39 | { 40 | info.Status = 0; 41 | } 42 | 43 | info.ContactID = this.ID; 44 | info.XValue = (ushort)(X * (double)MULTI_MAX_COORDINATE); 45 | info.YValue = (ushort)(Y * (double)MULTI_MAX_COORDINATE); 46 | info.Width = 20; 47 | info.Height = 30; 48 | 49 | return info; 50 | } 51 | } 52 | 53 | public struct MultitouchPointerInfoRaw 54 | { 55 | public byte Status; 56 | public byte ContactID; 57 | public ushort XValue; 58 | public ushort YValue; 59 | public ushort Width; 60 | public ushort Height; 61 | } 62 | 63 | 64 | public class MultitouchReport 65 | { 66 | private List touches; 67 | 68 | public MultitouchReport(List touches) 69 | { 70 | this.touches = touches; 71 | } 72 | 73 | public MultitouchPointerInfoRaw[] getTouchesRaw() 74 | { 75 | MultitouchPointerInfoRaw[] allTouches = new MultitouchPointerInfoRaw[touches.Count]; 76 | for (int i = 0; i < touches.Count; i++ ) 77 | { 78 | allTouches[i] = touches[i].getPointerInfoRaw(); 79 | } 80 | return allTouches; 81 | } 82 | 83 | public byte getTouchesCountRaw() 84 | { 85 | return (byte)touches.Count; 86 | } 87 | 88 | public byte getRequestType() 89 | { 90 | return 0x01; //REPORTID_MTOUCH 91 | } 92 | 93 | public byte getReportControlId() 94 | { 95 | return 0x40; //REPORTID_CONTROL 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /VMultiDllWrapper/JoystickReport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace VMultiDllWrapper 8 | { 9 | public struct JoystickButtonState 10 | { 11 | public bool A; 12 | public bool B; 13 | public bool X; 14 | public bool Y; 15 | public bool L; 16 | public bool R; 17 | public bool L2; 18 | public bool R2; 19 | public bool Start; 20 | public bool Select; 21 | 22 | public bool Extra1; 23 | public bool Extra2; 24 | public bool Extra3; 25 | public bool Extra4; 26 | public bool Extra5; 27 | public bool Extra6; 28 | 29 | public bool Left; 30 | public bool Right; 31 | public bool Up; 32 | public bool Down; 33 | } 34 | 35 | public class JoystickReport 36 | { 37 | private JoystickButtonState buttonState; 38 | 39 | private double joystickX; 40 | private double joystickY; 41 | 42 | public JoystickReport(JoystickButtonState buttonState, double joystickX, double joystickY) 43 | { 44 | this.buttonState = buttonState; 45 | if (joystickX > 1) 46 | { 47 | joystickX = 1.0; 48 | } 49 | else if (joystickX < -1) 50 | { 51 | joystickX = -1.0; 52 | } 53 | if (joystickY > 1) 54 | { 55 | joystickY = 1.0; 56 | } 57 | else if (joystickY < -1) 58 | { 59 | joystickY = -1.0; 60 | } 61 | this.joystickX = joystickX; 62 | this.joystickY = joystickY; 63 | } 64 | 65 | public ushort getButtonsRaw() 66 | { 67 | ushort result = 0; 68 | if (buttonState.A) 69 | { 70 | result |= 1 << 1; 71 | } 72 | if (buttonState.B) 73 | { 74 | result |= 1 << 2; 75 | } 76 | if (buttonState.X) 77 | { 78 | result |= 1 << 3; 79 | } 80 | if (buttonState.Y) 81 | { 82 | result |= 1 << 4; 83 | } 84 | if (buttonState.L) 85 | { 86 | result |= 1 << 5; 87 | } 88 | if (buttonState.R) 89 | { 90 | result |= 1 << 6; 91 | } 92 | 93 | return result; 94 | } 95 | 96 | public byte getPOVRaw() 97 | { 98 | byte result = 0; 99 | 100 | /* 101 | if (buttonState.Left) 102 | { 103 | result = 129; 104 | }*/ 105 | 106 | return result; 107 | } 108 | 109 | public byte getJoystickXRaw() 110 | { 111 | return (byte)(joystickX * 127); 112 | } 113 | 114 | public byte getJoystickYRaw() 115 | { 116 | return (byte)(joystickY * 127); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /VMultiDllWrapper/VMultiDllWrapper.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {22020466-69C1-488D-B0EB-93DB380F2871} 8 | Library 9 | Properties 10 | VMultiDllWrapper 11 | VMultiDllWrapper 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | ..\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | true 34 | ..\Debug\ 35 | DEBUG;TRACE 36 | full 37 | x86 38 | prompt 39 | MinimumRecommendedRules.ruleset 40 | 41 | 42 | ..\Release\ 43 | TRACE 44 | true 45 | pdbonly 46 | x86 47 | prompt 48 | MinimumRecommendedRules.ruleset 49 | 50 | 51 | true 52 | ..\Debug\ 53 | DEBUG;TRACE 54 | full 55 | x64 56 | prompt 57 | MinimumRecommendedRules.ruleset 58 | 59 | 60 | ..\x64\Release\ 61 | TRACE 62 | true 63 | pdbonly 64 | x64 65 | prompt 66 | MinimumRecommendedRules.ruleset 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | True 83 | True 84 | Settings.settings 85 | 86 | 87 | 88 | 89 | 90 | 91 | SettingsSingleFileGenerator 92 | Settings.Designer.cs 93 | 94 | 95 | 96 | 103 | -------------------------------------------------------------------------------- /VMultiTest/VMultiTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2C96C636-972D-4251-A350-52FB606AF440} 8 | Exe 9 | Properties 10 | VMultiTest 11 | VMultiTest 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | ..\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | ..\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | true 36 | ..\Debug\ 37 | DEBUG;TRACE 38 | full 39 | x86 40 | prompt 41 | MinimumRecommendedRules.ruleset 42 | true 43 | 44 | 45 | ..\Release\ 46 | TRACE 47 | true 48 | pdbonly 49 | x86 50 | prompt 51 | MinimumRecommendedRules.ruleset 52 | true 53 | 54 | 55 | true 56 | ..\Debug\ 57 | DEBUG;TRACE 58 | full 59 | x64 60 | prompt 61 | MinimumRecommendedRules.ruleset 62 | true 63 | 64 | 65 | ..\x64\Release\ 66 | TRACE 67 | true 68 | pdbonly 69 | x64 70 | prompt 71 | MinimumRecommendedRules.ruleset 72 | true 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | {22020466-69c1-488d-b0eb-93db380f2871} 95 | VMultiDllWrapper 96 | 97 | 98 | 99 | 106 | -------------------------------------------------------------------------------- /VMultiDllWrapper/KeyboardReport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace VMultiDllWrapper 8 | { 9 | public enum KeyboardKey : byte 10 | { 11 | A = 0x04, 12 | B = 0x05, 13 | C = 0x06, 14 | D = 0x07, 15 | E = 0x08, 16 | F = 0x09, 17 | G = 0x0A, 18 | H = 0x0B, 19 | I = 0x0C, 20 | J = 0x0D, 21 | K = 0x0E, 22 | L = 0x0F, 23 | M = 0x10, 24 | N = 0x11, 25 | O = 0x12, 26 | P = 0x13, 27 | Q = 0x14, 28 | R = 0x15, 29 | S = 0x16, 30 | T = 0x17, 31 | U = 0x18, 32 | V = 0x19, 33 | W = 0x1A, 34 | X = 0x1B, 35 | Y = 0x1C, 36 | Z = 0x1D, 37 | 38 | 39 | Number1 = 0x1e, 40 | Number2 = 0x1f, 41 | Number3 = 0x20, 42 | Number4 = 0x21, 43 | Number5 = 0x22, 44 | Number6 = 0x23, 45 | Number7 = 0x24, 46 | Number8 = 0x25, 47 | Number9 = 0x26, 48 | Number0 = 0x27, 49 | 50 | Enter = 0x28, 51 | Escape = 0x29, 52 | Backspace = 0x2A, 53 | Tab = 0x2B, 54 | Spacebar = 0x2C, 55 | Subtract = 0x2D, //non-keypad 56 | Equals = 0x2E, //means "=" 57 | OpenBrace = 0x2F, 58 | CloseBrace = 0x30, 59 | Backslash = 0x31, //non-keypad 60 | Hash = 0x32, 61 | Semicolon = 0x33, 62 | Quote = 0x34, 63 | Tilde = 0x35, // 64 | Comma = 0x36, 65 | Dot = 0x37, 66 | ForwardSlash= 0x38, 67 | CapsLock = 0x39, 68 | 69 | F1 = 0x3A, 70 | F2 = 0x3B, 71 | F3 = 0x3C, 72 | F4 = 0x3D, 73 | F5 = 0x3E, 74 | F6 = 0x3F, 75 | F7 = 0x40, 76 | F8 = 0x41, 77 | F9 = 0x42, 78 | F10 = 0x43, 79 | F11 = 0x44, 80 | F12 = 0x45, 81 | 82 | PrintScreen = 0x46, 83 | ScrollLock = 0x47, 84 | Pause = 0x48, 85 | Insert = 0x49, 86 | Home = 0x4A, 87 | PageUp = 0x4B, 88 | Delete = 0x4C, 89 | End = 0x4D, 90 | PageDown = 0x4E, 91 | RightArrow = 0x4F, // is "Arrow" needed? 92 | LeftArrow = 0x50, 93 | DownArrow = 0x51, 94 | UpArrow = 0x52, 95 | NumLock = 0x53, 96 | KeypadDivide = 0x54, 97 | KeypadMultiply = 0x55, 98 | KeypadSubtract = 0x56, 99 | KeypadAdd = 0x57, 100 | KeypadEnter = 0x58, 101 | Keypad1 = 0x59, 102 | Keypad2 = 0x5A, 103 | Keypad3 = 0x5B, 104 | Keypad4 = 0x5C, 105 | Keypad5 = 0x5D, 106 | Keypad6 = 0x5E, 107 | Keypad7 = 0x5F, 108 | Keypad8 = 0x60, 109 | Keypad9 = 0x61, 110 | Keypad0 = 0x62, 111 | KeypadDecimal = 0x63, 112 | KeypadSeparator = 0x64, 113 | KeypadApplication= 0x65 114 | 115 | } 116 | 117 | public enum KeyboardModifier : byte 118 | { 119 | LControl = 1, 120 | LShift = 2, 121 | LAlt = 4, 122 | LWin = 8, 123 | RControl = 16, 124 | RShift = 32, 125 | RAlt = 64, 126 | RWin = 128 127 | } 128 | 129 | public class KeyboardReport 130 | { 131 | private const byte KBD_KEY_CODES = 6; 132 | private HashSet modifiers; 133 | private HashSet pressedKeys; 134 | 135 | public KeyboardReport() 136 | { 137 | modifiers = new HashSet(); 138 | pressedKeys = new HashSet(); 139 | } 140 | 141 | public KeyboardReport(IEnumerable modifiers, IEnumerable pressedKeys) 142 | { 143 | } 144 | 145 | public void keyDown(KeyboardModifier modifier) 146 | { 147 | modifiers.Add(modifier); 148 | } 149 | 150 | public void keyDown(KeyboardKey key) 151 | { 152 | pressedKeys.Add(key); 153 | } 154 | 155 | public void keyUp(KeyboardModifier modifier) 156 | { 157 | modifiers.Remove(modifier); 158 | } 159 | 160 | public void keyUp(KeyboardKey key) 161 | { 162 | pressedKeys.Remove(key); 163 | } 164 | 165 | public byte getRawShiftKeyFlags() 166 | { 167 | byte shiftKeys = 0; 168 | foreach(KeyboardModifier modifier in modifiers) 169 | { 170 | shiftKeys |= (byte)modifier; 171 | } 172 | return shiftKeys; 173 | } 174 | public byte[] getRawKeyCodes() 175 | { 176 | byte[] keyCodes = new byte[KBD_KEY_CODES]; 177 | byte i = 0; 178 | foreach (KeyboardKey key in pressedKeys) 179 | { 180 | if(i<=6) 181 | { 182 | keyCodes[i++] = (byte)key; 183 | } 184 | } 185 | return keyCodes; 186 | } 187 | } 188 | 189 | } 190 | -------------------------------------------------------------------------------- /VMultiTest/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows.Forms; 9 | using System.Windows.Input; 10 | using VMultiDllWrapper; 11 | 12 | namespace VMultiTest 13 | { 14 | class Program 15 | { 16 | static void Main(string[] args) 17 | { 18 | 19 | VMulti vmulti = new VMulti("D:\\Work\\CSharpWork\\VMultiDll-master\\VMultiDll-master\\Debug\\VMultiDll.dll"); 20 | Console.WriteLine("Connect: " + vmulti.connect()); 21 | 22 | System.Threading.Thread.Sleep(3000); 23 | 24 | keyboardTest(vmulti); 25 | 26 | vmulti.disconnect(); 27 | 28 | Console.ReadKey(); 29 | } 30 | 31 | [DllImport("USER32.dll")] 32 | static extern short GetKeyState(int nVirtKey); 33 | 34 | private static void keyboardTest(VMulti vmulti) 35 | { 36 | System.Diagnostics.Process.Start("notepad.exe"); 37 | 38 | System.Threading.Thread.Sleep(3000); 39 | 40 | KeyboardReport report = new KeyboardReport(); 41 | 42 | report.keyDown(KeyboardKey.H); 43 | vmulti.updateKeyboard(report); 44 | report.keyUp(KeyboardKey.H); 45 | report.keyDown(KeyboardKey.E); 46 | vmulti.updateKeyboard(report); 47 | report.keyUp(KeyboardKey.E); 48 | report.keyDown(KeyboardKey.L); 49 | vmulti.updateKeyboard(report); 50 | report.keyUp(KeyboardKey.L); 51 | vmulti.updateKeyboard(report); 52 | report.keyDown(KeyboardKey.L); 53 | vmulti.updateKeyboard(report); 54 | report.keyUp(KeyboardKey.L); 55 | report.keyDown(KeyboardKey.O); 56 | vmulti.updateKeyboard(report); 57 | report.keyUp(KeyboardKey.O); 58 | report.keyDown(KeyboardModifier.LShift); 59 | report.keyDown(KeyboardKey.Number1); 60 | vmulti.updateKeyboard(report); 61 | report.keyUp(KeyboardModifier.LShift); 62 | report.keyUp(KeyboardKey.Number1); 63 | vmulti.updateKeyboard(report); 64 | 65 | System.Threading.Thread.Sleep(4000); 66 | report.keyDown(KeyboardModifier.LWin); 67 | report.keyDown(KeyboardKey.D); 68 | vmulti.updateKeyboard(report); 69 | report.keyUp(KeyboardModifier.LWin); 70 | report.keyUp(KeyboardKey.D); 71 | vmulti.updateKeyboard(report); 72 | } 73 | 74 | private void joystickTest(VMulti vmulti) 75 | { 76 | double i = 0; 77 | bool running = true; 78 | while (running) 79 | { 80 | JoystickButtonState joyButtonState = new JoystickButtonState(); 81 | joyButtonState.A = false; 82 | joyButtonState.X = false; 83 | joyButtonState.Left = false; 84 | 85 | double x = Math.Sin(i); 86 | double y = Math.Cos(i); 87 | 88 | Console.WriteLine("x: " + x + " y: " + y); 89 | 90 | JoystickReport joystickReport = new JoystickReport(joyButtonState, x, y); 91 | 92 | Console.WriteLine("Update Joystick: " + vmulti.updateJoystick(joystickReport)); 93 | 94 | i += 0.1; 95 | 96 | System.Threading.Thread.Sleep(100); 97 | } 98 | } 99 | 100 | private void multitouchTest(VMulti vmulti) 101 | { 102 | double x = 500; 103 | double y = 500; 104 | 105 | while (true) 106 | { 107 | List touches = new List(); 108 | bool spacePressed = Convert.ToBoolean(GetKeyState(0x20) & 0x8000); 109 | MultitouchPointerInfo pointer = new MultitouchPointerInfo(); 110 | 111 | bool rightPressed = Convert.ToBoolean(GetKeyState(0x27) & 0x8000); 112 | if (rightPressed) 113 | x += 10; 114 | bool downPressed = Convert.ToBoolean(GetKeyState(0x28) & 0x8000); 115 | if (downPressed) 116 | y += 10; 117 | bool leftPressed = Convert.ToBoolean(GetKeyState(0x25) & 0x8000); 118 | if (leftPressed) 119 | x -= 10; 120 | bool upPressed = Convert.ToBoolean(GetKeyState(0x26) & 0x8000); 121 | if (upPressed) 122 | y -= 10; 123 | 124 | 125 | if (spacePressed) 126 | { 127 | Console.WriteLine("pressed"); 128 | pointer.Down = true; 129 | } 130 | else 131 | { 132 | pointer.Down = false; 133 | } 134 | 135 | Point mousePos = Control.MousePosition; 136 | Console.WriteLine(mousePos); 137 | pointer.X = x / Screen.PrimaryScreen.Bounds.Width; 138 | pointer.Y = y / Screen.PrimaryScreen.Bounds.Height; 139 | 140 | Console.WriteLine("X: " + pointer.X); 141 | Console.WriteLine("Y: " + pointer.Y); 142 | 143 | touches.Add(pointer); 144 | 145 | MultitouchReport report = new MultitouchReport(touches); 146 | 147 | if (!vmulti.updateMultitouch(report)) 148 | { 149 | Console.WriteLine("fail"); 150 | } 151 | 152 | System.Threading.Thread.Sleep(10); 153 | } 154 | } 155 | 156 | 157 | 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /VMultiDll/vmulticommon.h: -------------------------------------------------------------------------------- 1 | #if !defined(_VMULTI_COMMON_H_) 2 | #define _VMULTI_COMMON_H_ 3 | 4 | #include "minwindef.h" 5 | 6 | // 7 | //These are the device attributes returned by vmulti in response 8 | // to IOCTL_HID_GET_DEVICE_ATTRIBUTES. 9 | // 10 | 11 | #define VMULTI_PID1 0xBA1C 12 | #define VMULTI_VID1 0x001F 13 | 14 | #define VMULTI_PID2 0xBA2C 15 | #define VMULTI_VID2 0x002F 16 | 17 | #define VMULTI_PID3 0xBA3C 18 | #define VMULTI_VID3 0x003F 19 | 20 | #define VMULTI_PID4 0xBA4C 21 | #define VMULTI_VID4 0x004F 22 | 23 | #define VMULTI_PID5 0xBA5C 24 | #define VMULTI_VID5 0x005F 25 | 26 | #define VMULTI_VERSION 0x0001 27 | 28 | // 29 | // These are the report ids 30 | // 31 | 32 | #define REPORTID_MTOUCH 0x01 33 | #define REPORTID_FEATURE 0x02 34 | #define REPORTID_MOUSE 0x03 35 | #define REPORTID_RELATIVE_MOUSE 0x04 36 | #define REPORTID_DIGI 0x05 37 | #define REPORTID_JOYSTICK 0x06 38 | #define REPORTID_KEYBOARD 0x07 39 | #define REPORTID_MESSAGE 0x10 40 | #define REPORTID_CONTROL 0x40 41 | 42 | // 43 | // Control defined report size 44 | // 45 | 46 | #define CONTROL_REPORT_SIZE 0x41 47 | 48 | // 49 | // Report header 50 | // 51 | 52 | #pragma pack(1) 53 | typedef struct _VMULTI_CONTROL_REPORT_HEADER 54 | { 55 | 56 | BYTE ReportID; 57 | 58 | BYTE ReportLength; 59 | 60 | } VMultiControlReportHeader; 61 | #pragma pack() 62 | 63 | // 64 | // Keyboard specific report infomation 65 | // 66 | 67 | #define KBD_LCONTROL_BIT 1 68 | #define KBD_LSHIFT_BIT 2 69 | #define KBD_LALT_BIT 4 70 | #define KBD_LGUI_BIT 8 71 | #define KBD_RCONTROL_BIT 16 72 | #define KBD_RSHIFT_BIT 32 73 | #define KBD_RALT_BIT 64 74 | #define KBD_RGUI_BIT 128 75 | 76 | #define KBD_KEY_CODES 6 77 | 78 | #pragma pack(1) 79 | typedef struct _VMULTI_KEYBOARD_REPORT 80 | { 81 | BYTE ReportID; 82 | // Left Control, Left Shift, Left Alt, Left GUI 83 | // Right Control, Right Shift, Right Alt, Right GUI 84 | BYTE ShiftKeyFlags; 85 | BYTE Reserved; 86 | // See http://www.usb.org/developers/devclass_docs/Hut1_11.pdf 87 | // for a list of key codes 88 | BYTE KeyCodes[KBD_KEY_CODES]; 89 | 90 | } VMultiKeyboardReport; 91 | 92 | typedef struct _VMULTI_KEYBOARD_OUTPUT_REPORT 93 | { 94 | // Num Lock, Caps Lock, Scroll Lock, Compose, Kana 95 | BYTE LedFlags; 96 | } VMultiKeyboardOutputReport; 97 | #pragma pack() 98 | 99 | // 100 | // Joystick specific report infomation 101 | // 102 | #pragma pack(1) 103 | typedef struct _VMULTI_JOYSTICK_REPORT 104 | { 105 | BYTE ReportID; 106 | BYTE Throttle; 107 | BYTE XValue; 108 | BYTE YValue; 109 | BYTE ZValue; 110 | BYTE Hat; 111 | BYTE RZValue; 112 | USHORT Buttons; 113 | } VMultiJoystickReport; 114 | #pragma pack() 115 | 116 | // 117 | // Digitizer specific report infomation 118 | // 119 | 120 | #define DIGI_TIPSWITCH_BIT 1 121 | #define DIGI_IN_RANGE_BIT 2 122 | 123 | #define DIGI_MIN_COORDINATE 0x0000 124 | #define DIGI_MAX_COORDINATE 0x7FFF 125 | 126 | #pragma pack(1) 127 | typedef struct _VMULTI_DIGI_REPORT 128 | { 129 | BYTE ReportID; 130 | BYTE Status; 131 | USHORT XValue; 132 | USHORT YValue; 133 | } VMultiDigiReport; 134 | #pragma pack() 135 | 136 | // 137 | // Mouse specific report information 138 | // 139 | 140 | #define MOUSE_BUTTON_1 0x01 141 | #define MOUSE_BUTTON_2 0x02 142 | #define MOUSE_BUTTON_3 0x04 143 | 144 | #define MOUSE_MIN_COORDINATE 0x0000 145 | #define MOUSE_MAX_COORDINATE 0x7FFF 146 | 147 | #define MIN_WHEEL_POS -127 148 | #define MAX_WHEEL_POS 127 149 | 150 | #pragma pack(1) 151 | typedef struct _VMULTI_MOUSE_REPORT 152 | { 153 | BYTE ReportID; 154 | BYTE Button; 155 | USHORT XValue; 156 | USHORT YValue; 157 | BYTE WheelPosition; 158 | } VMultiMouseReport; 159 | #pragma pack() 160 | 161 | // 162 | // Relative mouse specific report information 163 | // 164 | 165 | #define RELATIVE_MOUSE_MIN_COORDINATE -127 166 | #define RELATIVE_MOUSE_MAX_COORDINATE 127 167 | 168 | #pragma pack(1) 169 | typedef struct _VMULTI_RELATIVE_MOUSE_REPORT 170 | { 171 | BYTE ReportID; 172 | BYTE Button; 173 | BYTE XValue; 174 | BYTE YValue; 175 | BYTE WheelPosition; 176 | } VMultiRelativeMouseReport; 177 | #pragma pack() 178 | 179 | // 180 | // Multitouch specific report information 181 | // 182 | 183 | #define MULTI_TIPSWITCH_BIT 1 184 | #define MULTI_IN_RANGE_BIT 2 185 | #define MULTI_CONFIDENCE_BIT 4 186 | 187 | #define MULTI_MIN_COORDINATE 0x0000 188 | #define MULTI_MAX_COORDINATE 0x7FFF 189 | 190 | #define MULTI_MAX_COUNT 20 191 | 192 | #pragma pack(1) 193 | typedef struct 194 | { 195 | BYTE Status; 196 | BYTE ContactID; 197 | USHORT XValue; 198 | USHORT YValue; 199 | USHORT Width; 200 | USHORT Height; 201 | } 202 | TOUCH, *PTOUCH; 203 | 204 | typedef struct _VMULTI_MULTITOUCH_REPORT 205 | { 206 | BYTE ReportID; 207 | TOUCH Touch[2]; 208 | BYTE ActualCount; 209 | } VMultiMultiTouchReport; 210 | #pragma pack() 211 | 212 | // 213 | // Feature report infomation 214 | // 215 | 216 | #define DEVICE_MODE_MOUSE 0x00 217 | #define DEVICE_MODE_SINGLE_INPUT 0x01 218 | #define DEVICE_MODE_MULTI_INPUT 0x02 219 | 220 | #pragma pack(1) 221 | typedef struct _VMULTI_FEATURE_REPORT 222 | { 223 | BYTE ReportID; 224 | BYTE DeviceMode; 225 | BYTE DeviceIdentifier; 226 | } VMultiFeatureReport; 227 | 228 | typedef struct _VMULTI_MAXCOUNT_REPORT 229 | { 230 | BYTE ReportID; 231 | BYTE MaximumCount; 232 | } VMultiMaxCountReport; 233 | #pragma pack() 234 | 235 | // 236 | // Message specific report information 237 | // 238 | 239 | #define MESSAGE_SIZE 0x20 240 | 241 | #pragma pack(1) 242 | typedef struct _VMULTI_MESSAGE_REPORT 243 | { 244 | BYTE ReportID; 245 | char Message[MESSAGE_SIZE]; 246 | } VMultiMessageReport; 247 | #pragma pack() 248 | 249 | #endif 250 | -------------------------------------------------------------------------------- /VMultiDll/hidport.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 1996 Microsoft Corporation 4 | 5 | Module Name: 6 | 7 | hidmini.h 8 | 9 | Abstract 10 | 11 | Definitions that are common to all HID minidrivers. 12 | 13 | Authors: 14 | 15 | Forrest Foltz 16 | Ervin Peretz 17 | 18 | Environment: 19 | 20 | Kernel mode only 21 | 22 | Revision History: 23 | 24 | 25 | --*/ 26 | 27 | #ifndef __HIDPORT_H__ 28 | #define __HIDPORT_H__ 29 | 30 | #include 31 | #include 32 | 33 | // 34 | // HID_MINIDRIVER_REGISTRATION is a packet of information describing the 35 | // HID minidriver to the class driver. It must be filled in by the minidriver 36 | // and passed to the class driver via HidRegisterMinidriver() from the 37 | // minidriver's DriverEntry() routine. 38 | // 39 | 40 | typedef struct _HID_MINIDRIVER_REGISTRATION { 41 | 42 | // 43 | // Revision must be set to HID_REVISION by the minidriver 44 | // 45 | 46 | ULONG Revision; 47 | 48 | // 49 | // DriverObject is a pointer to the minidriver's DriverObject that it 50 | // received as a DriverEntry() parameter. 51 | // 52 | 53 | PDRIVER_OBJECT DriverObject; 54 | 55 | // 56 | // RegistryPath is a pointer to the minidriver's RegistryPath that it 57 | // received as a DriverEntry() parameter. 58 | // 59 | 60 | PUNICODE_STRING RegistryPath; 61 | 62 | // 63 | // DeviceExtensionSize is the size of the minidriver's per-device 64 | // extension. 65 | // 66 | 67 | ULONG DeviceExtensionSize; 68 | 69 | // 70 | // Either all or none of the devices driven by a given minidriver are polled. 71 | // 72 | BOOLEAN DevicesArePolled; 73 | UCHAR Reserved[3]; 74 | 75 | } HID_MINIDRIVER_REGISTRATION, *PHID_MINIDRIVER_REGISTRATION; 76 | 77 | // 78 | // HID_DEVICE_EXTENSION is the public part of the device extension of a HID 79 | // functional device object. 80 | // 81 | 82 | typedef struct _HID_DEVICE_EXTENSION { 83 | 84 | // 85 | // PhysicalDeviceObject... normally IRPs are not passed to this. 86 | // 87 | 88 | PDEVICE_OBJECT PhysicalDeviceObject; 89 | 90 | // 91 | // NextDeviceObject... IRPs are sent here by the minidriver. Note that 92 | // NextDeviceObject and PhysicalDeviceObject are the same unless someone 93 | // has inserted a 'filter' device object, in which case they are not the 94 | // same. Sending IRPs to NextDeviceObject will hit the filter device 95 | // objects on the way down. 96 | // 97 | 98 | PDEVICE_OBJECT NextDeviceObject; 99 | 100 | // 101 | // MiniDeviceExtension is the per-device extension area for use by 102 | // the minidriver. It's size is determined by the DeviceExtensionSize 103 | // parameter passed in to HidAddDevice(). 104 | // 105 | // So, given a Functional Device Object, a mininidriver finds this 106 | // structure by: 107 | // 108 | // HidDeviceExtension = (PHID_DEVICE_EXTENSION)(Fdo->DeviceExtension); 109 | // 110 | // And of course it's per-device extension is found by: 111 | // 112 | // MiniDeviceExtension = HidDeviceExtension->MiniDeviceExtension; 113 | // 114 | 115 | PVOID MiniDeviceExtension; 116 | 117 | } HID_DEVICE_EXTENSION, *PHID_DEVICE_EXTENSION; 118 | 119 | typedef struct _HID_DEVICE_ATTRIBUTES { 120 | 121 | ULONG Size; 122 | // 123 | // sizeof (struct _HID_DEVICE_ATTRIBUTES) 124 | // 125 | 126 | // 127 | // Vendor ids of this hid device 128 | // 129 | USHORT VendorID; 130 | USHORT ProductID; 131 | USHORT VersionNumber; 132 | USHORT Reserved[11]; 133 | 134 | } HID_DEVICE_ATTRIBUTES, * PHID_DEVICE_ATTRIBUTES; 135 | 136 | 137 | #include 138 | typedef struct _HID_DESCRIPTOR 139 | { 140 | UCHAR bLength; 141 | UCHAR bDescriptorType; 142 | USHORT bcdHID; 143 | UCHAR bCountry; 144 | UCHAR bNumDescriptors; 145 | 146 | /* 147 | * This is an array of one OR MORE descriptors. 148 | */ 149 | struct _HID_DESCRIPTOR_DESC_LIST { 150 | UCHAR bReportType; 151 | USHORT wReportLength; 152 | } DescriptorList [1]; 153 | 154 | } HID_DESCRIPTOR, * PHID_DESCRIPTOR; 155 | #include 156 | 157 | 158 | typedef 159 | VOID 160 | (*HID_SEND_IDLE_CALLBACK)( 161 | PVOID Context 162 | ); 163 | 164 | typedef struct _HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO { 165 | HID_SEND_IDLE_CALLBACK IdleCallback; 166 | PVOID IdleContext; 167 | } HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO, *PHID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO; 168 | 169 | // 170 | // Function prototypes for the HID services exported by the hid class driver 171 | // follow. 172 | // 173 | 174 | NTSTATUS 175 | HidRegisterMinidriver( 176 | __in PHID_MINIDRIVER_REGISTRATION MinidriverRegistration 177 | ); 178 | 179 | // 180 | // Internal IOCTLs for the class/mini driver interface. 181 | // 182 | 183 | #define IOCTL_HID_GET_DEVICE_DESCRIPTOR HID_CTL_CODE(0) 184 | #define IOCTL_HID_GET_REPORT_DESCRIPTOR HID_CTL_CODE(1) 185 | #define IOCTL_HID_READ_REPORT HID_CTL_CODE(2) 186 | #define IOCTL_HID_WRITE_REPORT HID_CTL_CODE(3) 187 | #define IOCTL_HID_GET_STRING HID_CTL_CODE(4) 188 | #define IOCTL_HID_ACTIVATE_DEVICE HID_CTL_CODE(7) 189 | #define IOCTL_HID_DEACTIVATE_DEVICE HID_CTL_CODE(8) 190 | #define IOCTL_HID_GET_DEVICE_ATTRIBUTES HID_CTL_CODE(9) 191 | #define IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST HID_CTL_CODE(10) 192 | 193 | /* 194 | * Codes for HID-specific descriptor types, from HID USB spec. 195 | */ 196 | #define HID_HID_DESCRIPTOR_TYPE 0x21 197 | #define HID_REPORT_DESCRIPTOR_TYPE 0x22 198 | #define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 // for body part associations 199 | 200 | 201 | 202 | /* 203 | * These are string IDs for use with IOCTL_HID_GET_STRING 204 | * They match the string field offsets in Chapter 9 of the USB Spec. 205 | */ 206 | #define HID_STRING_ID_IMANUFACTURER 14 207 | #define HID_STRING_ID_IPRODUCT 15 208 | #define HID_STRING_ID_ISERIALNUMBER 16 209 | 210 | 211 | 212 | #endif // __HIDPORT_H__ 213 | 214 | 215 | -------------------------------------------------------------------------------- /VMultiDll.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VMultiDll", "VMultiDll\VMultiDll.vcxproj", "{3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VMultiDllWrapper", "VMultiDllWrapper\VMultiDllWrapper.csproj", "{22020466-69C1-488D-B0EB-93DB380F2871}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VMultiTest", "VMultiTest\VMultiTest.csproj", "{2C96C636-972D-4251-A350-52FB606AF440}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Debug|Mixed Platforms = Debug|Mixed Platforms 16 | Debug|Win32 = Debug|Win32 17 | Debug|x64 = Debug|x64 18 | Debug|x86 = Debug|x86 19 | Release|Any CPU = Release|Any CPU 20 | Release|Mixed Platforms = Release|Mixed Platforms 21 | Release|Win32 = Release|Win32 22 | Release|x64 = Release|x64 23 | Release|x86 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|Any CPU.ActiveCfg = Debug|Win32 27 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 28 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|Mixed Platforms.Build.0 = Debug|Win32 29 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|Mixed Platforms.Deploy.0 = Debug|Win32 30 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|Win32.ActiveCfg = Debug|Win32 31 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|Win32.Build.0 = Debug|Win32 32 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|Win32.Deploy.0 = Debug|Win32 33 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|x64.ActiveCfg = Debug|x64 34 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|x64.Build.0 = Debug|x64 35 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|x64.Deploy.0 = Debug|x64 36 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|x86.ActiveCfg = Debug|Win32 37 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|x86.Build.0 = Debug|Win32 38 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Debug|x86.Deploy.0 = Debug|Win32 39 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|Any CPU.ActiveCfg = Release|Win32 40 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|Mixed Platforms.ActiveCfg = Release|Win32 41 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|Mixed Platforms.Build.0 = Release|Win32 42 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|Mixed Platforms.Deploy.0 = Release|Win32 43 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|Win32.ActiveCfg = Release|Win32 44 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|Win32.Build.0 = Release|Win32 45 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|Win32.Deploy.0 = Release|Win32 46 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|x64.ActiveCfg = Release|x64 47 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|x64.Build.0 = Release|x64 48 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|x64.Deploy.0 = Release|x64 49 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|x86.ActiveCfg = Release|Win32 50 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|x86.Build.0 = Release|Win32 51 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44}.Release|x86.Deploy.0 = Release|Win32 52 | {22020466-69C1-488D-B0EB-93DB380F2871}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 53 | {22020466-69C1-488D-B0EB-93DB380F2871}.Debug|Any CPU.Build.0 = Debug|Any CPU 54 | {22020466-69C1-488D-B0EB-93DB380F2871}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 55 | {22020466-69C1-488D-B0EB-93DB380F2871}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 56 | {22020466-69C1-488D-B0EB-93DB380F2871}.Debug|Win32.ActiveCfg = Debug|x86 57 | {22020466-69C1-488D-B0EB-93DB380F2871}.Debug|x64.ActiveCfg = Debug|x64 58 | {22020466-69C1-488D-B0EB-93DB380F2871}.Debug|x64.Build.0 = Debug|x64 59 | {22020466-69C1-488D-B0EB-93DB380F2871}.Debug|x86.ActiveCfg = Debug|x86 60 | {22020466-69C1-488D-B0EB-93DB380F2871}.Debug|x86.Build.0 = Debug|x86 61 | {22020466-69C1-488D-B0EB-93DB380F2871}.Release|Any CPU.ActiveCfg = Release|Any CPU 62 | {22020466-69C1-488D-B0EB-93DB380F2871}.Release|Any CPU.Build.0 = Release|Any CPU 63 | {22020466-69C1-488D-B0EB-93DB380F2871}.Release|Mixed Platforms.ActiveCfg = Release|x86 64 | {22020466-69C1-488D-B0EB-93DB380F2871}.Release|Mixed Platforms.Build.0 = Release|x86 65 | {22020466-69C1-488D-B0EB-93DB380F2871}.Release|Win32.ActiveCfg = Release|x86 66 | {22020466-69C1-488D-B0EB-93DB380F2871}.Release|x64.ActiveCfg = Release|x64 67 | {22020466-69C1-488D-B0EB-93DB380F2871}.Release|x64.Build.0 = Release|x64 68 | {22020466-69C1-488D-B0EB-93DB380F2871}.Release|x86.ActiveCfg = Release|x86 69 | {22020466-69C1-488D-B0EB-93DB380F2871}.Release|x86.Build.0 = Release|x86 70 | {2C96C636-972D-4251-A350-52FB606AF440}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 71 | {2C96C636-972D-4251-A350-52FB606AF440}.Debug|Any CPU.Build.0 = Debug|Any CPU 72 | {2C96C636-972D-4251-A350-52FB606AF440}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 73 | {2C96C636-972D-4251-A350-52FB606AF440}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 74 | {2C96C636-972D-4251-A350-52FB606AF440}.Debug|Win32.ActiveCfg = Debug|x86 75 | {2C96C636-972D-4251-A350-52FB606AF440}.Debug|x64.ActiveCfg = Debug|x64 76 | {2C96C636-972D-4251-A350-52FB606AF440}.Debug|x64.Build.0 = Debug|x64 77 | {2C96C636-972D-4251-A350-52FB606AF440}.Debug|x86.ActiveCfg = Debug|x86 78 | {2C96C636-972D-4251-A350-52FB606AF440}.Debug|x86.Build.0 = Debug|x86 79 | {2C96C636-972D-4251-A350-52FB606AF440}.Release|Any CPU.ActiveCfg = Release|Any CPU 80 | {2C96C636-972D-4251-A350-52FB606AF440}.Release|Any CPU.Build.0 = Release|Any CPU 81 | {2C96C636-972D-4251-A350-52FB606AF440}.Release|Mixed Platforms.ActiveCfg = Release|x86 82 | {2C96C636-972D-4251-A350-52FB606AF440}.Release|Mixed Platforms.Build.0 = Release|x86 83 | {2C96C636-972D-4251-A350-52FB606AF440}.Release|Win32.ActiveCfg = Release|x86 84 | {2C96C636-972D-4251-A350-52FB606AF440}.Release|x64.ActiveCfg = Release|x64 85 | {2C96C636-972D-4251-A350-52FB606AF440}.Release|x64.Build.0 = Release|x64 86 | {2C96C636-972D-4251-A350-52FB606AF440}.Release|x86.ActiveCfg = Release|x86 87 | {2C96C636-972D-4251-A350-52FB606AF440}.Release|x86.Build.0 = Release|x86 88 | EndGlobalSection 89 | GlobalSection(SolutionProperties) = preSolution 90 | HideSolutionNode = FALSE 91 | EndGlobalSection 92 | EndGlobal 93 | -------------------------------------------------------------------------------- /VMultiDllWrapper/VMulti.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace VMultiDllWrapper 6 | { 7 | public class VMulti 8 | { 9 | 10 | [DllImport("VMultiDll.dll", CallingConvention = CallingConvention.Cdecl)] 11 | public static extern void MyHelloWorld(); 12 | 13 | [DllImport("VMultiDll.dll", CallingConvention = CallingConvention.Cdecl)] 14 | public static extern int MySum(int a, int b); 15 | [DllImport("VMultiDll.dll", CallingConvention = CallingConvention.Cdecl)] 16 | public static extern IntPtr vmulti_alloc(); 17 | [DllImport("VMultiDll.dll", CallingConvention = CallingConvention.Cdecl)] 18 | public static extern void vmulti_free(IntPtr vmulti); 19 | 20 | [DllImport("VMultiDll.dll", CallingConvention = CallingConvention.Cdecl)] 21 | public static extern bool vmulti_connect(IntPtr vmulti, int i); 22 | 23 | [DllImport("VMultiDll.dll", CallingConvention = CallingConvention.Cdecl)] 24 | public static extern void vmulti_disconnect(IntPtr vmulti); 25 | 26 | [DllImport("VMultiDll.dll", CallingConvention = CallingConvention.Cdecl)] 27 | public static extern bool vmulti_update_joystick(IntPtr vmulti, ushort buttons, byte hat, byte x, byte y, byte z, byte rz, byte throttle); 28 | 29 | [DllImport("VMultiDll.dll", CallingConvention = CallingConvention.Cdecl)] 30 | public static extern bool vmulti_update_multitouch(IntPtr vmulti, MultitouchPointerInfoRaw[] pTouch, byte actualCount, byte request_type, byte report_control_id); 31 | 32 | [DllImport("VMultiDll.dll", CallingConvention = CallingConvention.Cdecl)] 33 | public static extern bool vmulti_update_keyboard(IntPtr vmulti, byte shiftKeyFlags, byte[] keyCodes); 34 | 35 | [DllImport("Kernel32.dll", SetLastError = true)] 36 | private static extern int GetProcAddress(int handle, string funcName); 37 | [DllImport("Kernel32.dll", SetLastError = true, CharSet =CharSet.Unicode)] 38 | private static extern int LoadLibrary(string dllPath); 39 | [DllImport("Kernel32.dll", SetLastError = true)] 40 | private static extern int FreeLibrary(int handle); 41 | 42 | 43 | /* 44 | public delegate void HelloWorld(); 45 | private HelloWorld Pro_HelloWorld { get; set; } 46 | 47 | public delegate IntPtr vmulti_alloc(); 48 | private vmulti_alloc Pro_vmulti_alloc { get; set; } 49 | public delegate void vmulti_free(IntPtr vmulti); 50 | private vmulti_free Pro_vmulti_free { get; set; } 51 | public delegate bool vmulti_connect(IntPtr vmulti, int i); 52 | private vmulti_connect Pro_vmulti_connect { get; set; } 53 | public delegate void vmulti_disconnect(IntPtr vmulti); 54 | private vmulti_disconnect Pro_vmulti_disconnect { get; set; } 55 | public delegate bool vmulti_update_joystick(IntPtr vmulti, ushort buttons, byte hat, byte x, byte y, byte z, byte rz, byte throttle); 56 | private vmulti_update_joystick Pro_vmulti_update_joystick { get; set; } 57 | public delegate bool vmulti_update_multitouch(IntPtr vmulti, MultitouchPointerInfoRaw[] pTouch, byte actualCount, byte request_type, byte report_control_id); 58 | private vmulti_update_multitouch Pro_vmulti_update_multitouch { get; set; } 59 | public delegate bool vmulti_update_keyboard(IntPtr vmulti, byte shiftKeyFlags, byte[] keyCodes); 60 | private vmulti_update_keyboard Pro_vmulti_update_keyboard { get; set; } 61 | */ 62 | private IntPtr vmulti; 63 | private bool connected; 64 | private int nDllHandle = 0; 65 | 66 | /* 67 | private static Delegate GetAddress(int dllMoule,string functionName, Type t) 68 | { 69 | int Addr = GetProcAddress(dllMoule, functionName); 70 | if (Addr == 0) 71 | return null; 72 | else 73 | return Marshal.GetDelegateForFunctionPointer(new IntPtr(Addr), t); 74 | } 75 | private void MyFreeLibrary() 76 | { 77 | if (this.nDllHandle >= 32) 78 | FreeLibrary(this.nDllHandle); 79 | } 80 | private bool MyLoadLibaray(string dllPath) 81 | { 82 | this.nDllHandle = LoadLibrary(dllPath); 83 | if(this.nDllHandle >= 32) 84 | { 85 | this.Pro_HelloWorld = (HelloWorld)GetAddress(nDllHandle, "HelloWorld", typeof(HelloWorld)); 86 | this.Pro_vmulti_alloc = (vmulti_alloc)GetAddress(nDllHandle, "vmulti_alloc", typeof(vmulti_alloc)); 87 | this.Pro_vmulti_free = (vmulti_free)GetAddress(nDllHandle, "vmulti_free", typeof(vmulti_free)); 88 | this.Pro_vmulti_connect = (vmulti_connect)GetAddress(nDllHandle, "vmulti_connect", typeof(vmulti_connect)); 89 | this.Pro_vmulti_disconnect = (vmulti_disconnect)GetAddress(nDllHandle, "vmulti_disconnect", typeof(vmulti_disconnect)); 90 | this.Pro_vmulti_update_joystick = (vmulti_update_joystick)GetAddress(nDllHandle, "vmulti_update_joystick", typeof(vmulti_update_joystick)); 91 | this.Pro_vmulti_update_multitouch = (vmulti_update_multitouch)GetAddress(nDllHandle, "vmulti_update_multitouch", typeof(vmulti_update_multitouch)); 92 | this.Pro_vmulti_update_keyboard = (vmulti_update_keyboard)GetAddress(nDllHandle, "vmulti_update_keyboard", typeof(vmulti_update_keyboard)); 93 | return true; 94 | } 95 | else 96 | { 97 | string strError = Marshal.GetLastWin32Error().ToString(); 98 | throw new Exception("LoadLibrary failed, error code = " + strError); 99 | } 100 | } 101 | */ 102 | 103 | public VMulti(string dllPath) 104 | { 105 | /* 106 | int a = 1; int b = 2; 107 | int c = MySum(a, b); 108 | */ 109 | MyHelloWorld(); 110 | //MyLoadLibaray(dllPath); 111 | vmulti = vmulti_alloc(); 112 | } 113 | 114 | ~VMulti() 115 | { 116 | //MyFreeLibrary(); 117 | } 118 | 119 | public virtual bool isConnected() 120 | { 121 | return this.connected; 122 | } 123 | 124 | public virtual bool connect() 125 | { 126 | return this.connected = vmulti_connect(vmulti, 1); 127 | } 128 | 129 | public virtual void disconnect() 130 | { 131 | if (connected) 132 | { 133 | vmulti_disconnect(vmulti); 134 | } 135 | } 136 | 137 | public virtual bool updateJoystick(JoystickReport report) 138 | { 139 | if (connected) 140 | { 141 | return vmulti_update_joystick(vmulti, report.getButtonsRaw(), 142 | report.getPOVRaw(), report.getJoystickXRaw(), report.getJoystickYRaw(), 0, 128, 0); 143 | } 144 | else 145 | { 146 | return false; 147 | } 148 | } 149 | 150 | public virtual bool updateMultitouch(MultitouchReport report) 151 | { 152 | if (connected) 153 | { 154 | MultitouchPointerInfoRaw[] touches = report.getTouchesRaw(); 155 | return vmulti_update_multitouch(vmulti, touches, 156 | report.getTouchesCountRaw(), report.getRequestType(), report.getReportControlId()); 157 | } 158 | else 159 | { 160 | return false; 161 | } 162 | } 163 | 164 | public virtual bool updateKeyboard(KeyboardReport report) 165 | { 166 | if (connected) 167 | { 168 | return vmulti_update_keyboard(vmulti, 169 | report.getRawShiftKeyFlags(), report.getRawKeyCodes()); 170 | } 171 | else 172 | { 173 | return false; 174 | } 175 | } 176 | 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /VMultiDll/VMultiDll.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {3C94F8A0-8F51-47B6-91E5-FBB0BD3E5C44} 23 | Win32Proj 24 | VMultiDll 25 | 8.1 26 | 27 | 28 | 29 | DynamicLibrary 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | DynamicLibrary 36 | true 37 | v140 38 | Unicode 39 | 40 | 41 | DynamicLibrary 42 | false 43 | v140 44 | true 45 | Unicode 46 | 47 | 48 | DynamicLibrary 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | true 72 | 73 | 74 | true 75 | $(SolutionDir)$(Configuration)\ 76 | $(Configuration)\ 77 | 78 | 79 | true 80 | $(SolutionDir)\$(Configuration)\ 81 | $(Configuration)\ 82 | 83 | 84 | false 85 | $(SolutionDir)\$(Configuration)\ 86 | $(Configuration)\ 87 | 88 | 89 | 90 | 91 | 92 | Level3 93 | Disabled 94 | WIN32;_DEBUG;_WINDOWS;_USRDLL;VMULTIDLL_EXPORTS;%(PreprocessorDefinitions) 95 | MultiThreadedDebug 96 | 97 | 98 | Windows 99 | true 100 | %(AdditionalDependencies) 101 | 102 | 103 | 104 | 105 | 106 | 107 | Level3 108 | Disabled 109 | WIN32;_DEBUG;_WINDOWS;_USRDLL;VMULTIDLL_EXPORTS;%(PreprocessorDefinitions) 110 | MultiThreadedDebug 111 | 112 | 113 | Windows 114 | true 115 | 116 | 117 | 118 | 119 | Level3 120 | 121 | 122 | MaxSpeed 123 | true 124 | true 125 | WIN32;NDEBUG;_WINDOWS;_USRDLL;VMULTIDLL_EXPORTS;%(PreprocessorDefinitions) 126 | MultiThreaded 127 | 128 | 129 | Windows 130 | true 131 | true 132 | true 133 | setupapi.lib;hid.lib;%(AdditionalDependencies) 134 | 135 | 136 | 137 | 138 | Level3 139 | NotUsing 140 | MaxSpeed 141 | true 142 | true 143 | WIN32;NDEBUG;_WINDOWS;_USRDLL;VMULTIDLL_EXPORTS;%(PreprocessorDefinitions) 144 | 145 | 146 | Windows 147 | true 148 | true 149 | true 150 | setupapi.lib;hid.lib;%(AdditionalDependencies) 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /VMultiDll/client.c: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "vmulticlient.h" 9 | 10 | #if __GNUC__ 11 | #define __in 12 | #define __in_ecount(x) 13 | typedef void* PVOID; 14 | typedef PVOID HDEVINFO; 15 | WINHIDSDI BOOL WINAPI HidD_SetOutputReport(HANDLE, PVOID, ULONG); 16 | #endif 17 | 18 | typedef struct _vmulti_client_t 19 | { 20 | HANDLE hControl; 21 | HANDLE hMessage; 22 | BYTE controlReport[CONTROL_REPORT_SIZE]; 23 | } vmulti_client_t; 24 | int id; 25 | int vmul_vid=0x0000; 26 | int vmul_pid=0x0000; 27 | 28 | // 29 | // Function prototypes 30 | // 31 | 32 | HANDLE 33 | SearchMatchingHwID ( 34 | USAGE myUsagePage, 35 | USAGE myUsage 36 | ); 37 | 38 | HANDLE 39 | OpenDeviceInterface ( 40 | HDEVINFO HardwareDeviceInfo, 41 | PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 42 | USAGE myUsagePage, 43 | USAGE myUsage 44 | ); 45 | 46 | BOOLEAN 47 | CheckIfOurDevice( 48 | HANDLE file, 49 | USAGE myUsagePage, 50 | USAGE myUsage 51 | ); 52 | 53 | BOOL 54 | HidOutput( 55 | BOOL useSetOutputReport, 56 | HANDLE file, 57 | PCHAR buffer, 58 | ULONG bufferSize 59 | ); 60 | 61 | // 62 | // Copied this structure from hidport.h 63 | // 64 | 65 | typedef struct _HID_DEVICE_ATTRIBUTES { 66 | 67 | ULONG Size; 68 | // 69 | // sizeof (struct _HID_DEVICE_ATTRIBUTES) 70 | // 71 | // 72 | // Vendor ids of this hid device 73 | // 74 | USHORT VendorID; 75 | USHORT ProductID; 76 | USHORT VersionNumber; 77 | USHORT Reserved[11]; 78 | 79 | } HID_DEVICE_ATTRIBUTES, * PHID_DEVICE_ATTRIBUTES; 80 | 81 | // 82 | // Implementation 83 | // 84 | 85 | pvmulti_client vmulti_alloc(void) 86 | { 87 | return (pvmulti_client)malloc(sizeof(vmulti_client_t)); 88 | } 89 | 90 | void vmulti_free(pvmulti_client vmulti) 91 | { 92 | free(vmulti); 93 | } 94 | 95 | BOOL vmulti_connect(pvmulti_client vmulti,int i) 96 | { 97 | // 98 | // Find the HID devices 99 | // 100 | id=i; 101 | vmulti->hControl = SearchMatchingHwID(0xff00, 0x0001); 102 | if (vmulti->hControl == INVALID_HANDLE_VALUE || vmulti->hControl == NULL) 103 | return FALSE; 104 | vmulti->hMessage = SearchMatchingHwID(0xff00, 0x0002); 105 | if (vmulti->hMessage == INVALID_HANDLE_VALUE || vmulti->hMessage == NULL) 106 | { 107 | vmulti_disconnect(vmulti); 108 | return FALSE; 109 | } 110 | 111 | // 112 | // Set the buffer count to 10 on the message HID 113 | // 114 | 115 | if (!HidD_SetNumInputBuffers(vmulti->hMessage, 10)) 116 | { 117 | printf("failed HidD_SetNumInputBuffers %d\n", GetLastError()); 118 | vmulti_disconnect(vmulti); 119 | return FALSE; 120 | } 121 | 122 | return TRUE; 123 | } 124 | 125 | void vmulti_disconnect(pvmulti_client vmulti) 126 | { 127 | if (vmulti->hControl != NULL) 128 | CloseHandle(vmulti->hControl); 129 | if (vmulti->hMessage != NULL) 130 | CloseHandle(vmulti->hMessage); 131 | vmulti->hControl = NULL; 132 | vmulti->hMessage = NULL; 133 | } 134 | 135 | BOOL vmulti_update_mouse(pvmulti_client vmulti, BYTE button, USHORT x, USHORT y, BYTE wheelPosition) 136 | { 137 | VMultiControlReportHeader* pReport = NULL; 138 | VMultiMouseReport* pMouseReport = NULL; 139 | 140 | if (CONTROL_REPORT_SIZE <= sizeof(VMultiControlReportHeader) + sizeof(VMultiMouseReport)) 141 | { 142 | return FALSE; 143 | } 144 | 145 | // 146 | // Set the report header 147 | // 148 | 149 | pReport = (VMultiControlReportHeader*)vmulti->controlReport; 150 | pReport->ReportID = REPORTID_CONTROL; 151 | pReport->ReportLength = sizeof(VMultiMouseReport); 152 | 153 | // 154 | // Set the input report 155 | // 156 | 157 | pMouseReport = (VMultiMouseReport*)(vmulti->controlReport + sizeof(VMultiControlReportHeader)); 158 | pMouseReport->ReportID = REPORTID_MOUSE; 159 | pMouseReport->Button = button; 160 | pMouseReport->XValue = x; 161 | pMouseReport->YValue = y; 162 | pMouseReport->WheelPosition = wheelPosition; 163 | 164 | // Send the report 165 | return HidOutput(FALSE, vmulti->hControl, (PCHAR)vmulti->controlReport, CONTROL_REPORT_SIZE); 166 | } 167 | 168 | BOOL vmulti_update_relative_mouse(pvmulti_client vmulti, BYTE button, 169 | BYTE x, BYTE y, BYTE wheelPosition) 170 | { 171 | VMultiControlReportHeader* pReport = NULL; 172 | VMultiRelativeMouseReport* pMouseReport = NULL; 173 | 174 | if (CONTROL_REPORT_SIZE <= sizeof(VMultiControlReportHeader) + sizeof(VMultiRelativeMouseReport)) 175 | { 176 | return FALSE; 177 | } 178 | 179 | // 180 | // Set the report header 181 | // 182 | 183 | pReport = (VMultiControlReportHeader*)vmulti->controlReport; 184 | pReport->ReportID = REPORTID_CONTROL; 185 | pReport->ReportLength = sizeof(VMultiRelativeMouseReport); 186 | 187 | // 188 | // Set the input report 189 | // 190 | 191 | pMouseReport = (VMultiRelativeMouseReport*)(vmulti->controlReport + sizeof(VMultiControlReportHeader)); 192 | pMouseReport->ReportID = REPORTID_RELATIVE_MOUSE; 193 | pMouseReport->Button = button; 194 | pMouseReport->XValue = x; 195 | pMouseReport->YValue = y; 196 | pMouseReport->WheelPosition = wheelPosition; 197 | 198 | // Send the report 199 | return HidOutput(FALSE, vmulti->hControl, (PCHAR)vmulti->controlReport, CONTROL_REPORT_SIZE); 200 | } 201 | 202 | BOOL vmulti_update_digi(pvmulti_client vmulti, BYTE status, USHORT x, USHORT y) 203 | { 204 | VMultiControlReportHeader* pReport = NULL; 205 | VMultiDigiReport* pDigiReport = NULL; 206 | 207 | if (CONTROL_REPORT_SIZE <= sizeof(VMultiControlReportHeader) + sizeof(VMultiDigiReport)) 208 | { 209 | return FALSE; 210 | } 211 | 212 | // 213 | // Set the report header 214 | // 215 | 216 | pReport = (VMultiControlReportHeader*)vmulti->controlReport; 217 | pReport->ReportID = REPORTID_CONTROL; 218 | pReport->ReportLength = sizeof(VMultiDigiReport); 219 | 220 | // 221 | // Set the input report 222 | // 223 | 224 | pDigiReport = (VMultiDigiReport*)(vmulti->controlReport + sizeof(VMultiControlReportHeader)); 225 | pDigiReport->ReportID = REPORTID_DIGI; 226 | pDigiReport->Status = status; 227 | pDigiReport->XValue = x; 228 | pDigiReport->YValue = y; 229 | 230 | // Send the report 231 | return HidOutput(FALSE, vmulti->hControl, (PCHAR)vmulti->controlReport, CONTROL_REPORT_SIZE); 232 | } 233 | 234 | BOOL vmulti_update_multitouch(pvmulti_client vmulti, PTOUCH pTouch, BYTE actualCount,BYTE request_type,BYTE report_control_id) 235 | { 236 | VMultiControlReportHeader* pReport = NULL; 237 | VMultiMultiTouchReport* pMultiReport = NULL; 238 | int numberOfTouchesSent = 0; 239 | 240 | if (CONTROL_REPORT_SIZE <= sizeof(VMultiControlReportHeader) + sizeof(VMultiMultiTouchReport)) 241 | return FALSE; 242 | 243 | // 244 | // Set the report header 245 | // 246 | 247 | pReport = (VMultiControlReportHeader*)vmulti->controlReport; 248 | pReport->ReportID = report_control_id; 249 | pReport->ReportLength = sizeof(VMultiMultiTouchReport); 250 | 251 | while (numberOfTouchesSent < actualCount) 252 | { 253 | 254 | // 255 | // Set the input report 256 | // 257 | 258 | pMultiReport = (VMultiMultiTouchReport*)(vmulti->controlReport + sizeof(VMultiControlReportHeader)); 259 | pMultiReport->ReportID = request_type; 260 | memcpy(pMultiReport->Touch, pTouch + numberOfTouchesSent, sizeof(TOUCH)); 261 | if (numberOfTouchesSent <= actualCount - 2) 262 | memcpy(pMultiReport->Touch + 1, pTouch + numberOfTouchesSent + 1, sizeof(TOUCH)); 263 | else 264 | memset(pMultiReport->Touch + 1, 0, sizeof(TOUCH)); 265 | if (numberOfTouchesSent == 0) 266 | pMultiReport->ActualCount = actualCount; 267 | else 268 | pMultiReport->ActualCount = 0; 269 | 270 | // Send the report 271 | if (!HidOutput(TRUE, vmulti->hControl, (PCHAR)vmulti->controlReport, CONTROL_REPORT_SIZE)) 272 | return FALSE; 273 | 274 | numberOfTouchesSent += 2; 275 | } 276 | 277 | return TRUE; 278 | } 279 | 280 | BOOL vmulti_update_joystick(pvmulti_client vmulti, USHORT buttons, BYTE hat, BYTE x, BYTE y, BYTE z, BYTE rz, BYTE throttle) 281 | { 282 | VMultiControlReportHeader* pReport = NULL; 283 | VMultiJoystickReport* pJoystickReport = NULL; 284 | 285 | if (CONTROL_REPORT_SIZE <= sizeof(VMultiControlReportHeader) + sizeof(VMultiJoystickReport)) 286 | { 287 | return FALSE; 288 | } 289 | 290 | // 291 | // Set the report header 292 | // 293 | 294 | pReport = (VMultiControlReportHeader*)vmulti->controlReport; 295 | pReport->ReportID = REPORTID_CONTROL; 296 | pReport->ReportLength = sizeof(VMultiJoystickReport); 297 | 298 | // 299 | // Set the input report 300 | // 301 | 302 | pJoystickReport = (VMultiJoystickReport*)(vmulti->controlReport + sizeof(VMultiControlReportHeader)); 303 | pJoystickReport->ReportID = REPORTID_JOYSTICK; 304 | pJoystickReport->Buttons = buttons; 305 | pJoystickReport->Hat = hat; 306 | pJoystickReport->XValue = x; 307 | pJoystickReport->YValue = y; 308 | pJoystickReport->ZValue = z; 309 | pJoystickReport->RZValue = rz; 310 | pJoystickReport->Throttle = throttle; 311 | 312 | // Send the report 313 | return HidOutput(FALSE, vmulti->hControl, (PCHAR)vmulti->controlReport, CONTROL_REPORT_SIZE); 314 | } 315 | 316 | BOOL vmulti_update_keyboard(pvmulti_client vmulti, BYTE shiftKeyFlags, BYTE keyCodes[KBD_KEY_CODES]) 317 | { 318 | VMultiControlReportHeader* pReport = NULL; 319 | VMultiKeyboardReport* pKeyboardReport = NULL; 320 | 321 | if (CONTROL_REPORT_SIZE <= sizeof(VMultiControlReportHeader) + sizeof(VMultiKeyboardReport)) 322 | { 323 | return FALSE; 324 | } 325 | 326 | // 327 | // Set the report header 328 | // 329 | 330 | pReport = (VMultiControlReportHeader*)vmulti->controlReport; 331 | pReport->ReportID = REPORTID_CONTROL; 332 | pReport->ReportLength = sizeof(VMultiKeyboardReport); 333 | 334 | // 335 | // Set the input report 336 | // 337 | 338 | pKeyboardReport = (VMultiKeyboardReport*)(vmulti->controlReport + sizeof(VMultiControlReportHeader)); 339 | pKeyboardReport->ReportID = REPORTID_KEYBOARD; 340 | pKeyboardReport->ShiftKeyFlags = shiftKeyFlags; 341 | memcpy(pKeyboardReport->KeyCodes, keyCodes, KBD_KEY_CODES); 342 | 343 | // Send the report 344 | return HidOutput(FALSE, vmulti->hControl, (PCHAR)vmulti->controlReport, CONTROL_REPORT_SIZE); 345 | } 346 | 347 | BOOL vmulti_write_message(pvmulti_client vmulti, VMultiMessageReport* pReport) 348 | { 349 | VMultiControlReportHeader* pReportHeader; 350 | ULONG bytesWritten; 351 | 352 | // 353 | // Set the report header 354 | // 355 | 356 | pReportHeader = (VMultiControlReportHeader*)vmulti->controlReport; 357 | pReportHeader->ReportID = REPORTID_CONTROL; 358 | pReportHeader->ReportLength = sizeof(VMultiMessageReport); 359 | 360 | // 361 | // Set the body 362 | // 363 | 364 | pReport->ReportID = REPORTID_MESSAGE; 365 | memcpy(vmulti->controlReport + sizeof(VMultiControlReportHeader), pReport, sizeof(VMultiMessageReport)); 366 | 367 | // 368 | // Write the report 369 | // 370 | 371 | if (!WriteFile(vmulti->hControl, vmulti->controlReport, CONTROL_REPORT_SIZE, &bytesWritten, NULL)) 372 | { 373 | printf("failed WriteFile %d\n", GetLastError()); 374 | return FALSE; 375 | } 376 | 377 | return TRUE; 378 | } 379 | 380 | BOOL vmulti_read_message(pvmulti_client vmulti, VMultiMessageReport* pReport) 381 | { 382 | ULONG bytesRead; 383 | 384 | // 385 | // Read the report 386 | // 387 | 388 | if (!ReadFile(vmulti->hMessage, pReport, sizeof(VMultiMessageReport), &bytesRead, NULL)) 389 | { 390 | printf("failed ReadFile %d\n", GetLastError()); 391 | return FALSE; 392 | } 393 | 394 | return TRUE; 395 | } 396 | 397 | HANDLE 398 | SearchMatchingHwID ( 399 | USAGE myUsagePage, 400 | USAGE myUsage 401 | ) 402 | { 403 | HDEVINFO hardwareDeviceInfo; 404 | SP_DEVICE_INTERFACE_DATA deviceInterfaceData; 405 | SP_DEVINFO_DATA devInfoData; 406 | GUID hidguid; 407 | int i; 408 | 409 | HidD_GetHidGuid(&hidguid); 410 | 411 | hardwareDeviceInfo = 412 | SetupDiGetClassDevs ((LPGUID)&hidguid, 413 | NULL, 414 | NULL, // Define no 415 | (DIGCF_PRESENT | 416 | DIGCF_INTERFACEDEVICE)); 417 | 418 | if (INVALID_HANDLE_VALUE == hardwareDeviceInfo) 419 | { 420 | printf("SetupDiGetClassDevs failed: %x\n", GetLastError()); 421 | return INVALID_HANDLE_VALUE; 422 | } 423 | 424 | deviceInterfaceData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA); 425 | 426 | devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 427 | 428 | // 429 | // Enumerate devices of this interface class 430 | // 431 | 432 | printf("\n....looking for our HID device (with UP=0x%x " 433 | "and Usage=0x%x)\n", myUsagePage, myUsage); 434 | 435 | for (i = 0; SetupDiEnumDeviceInterfaces (hardwareDeviceInfo, 436 | 0, // No care about specific PDOs 437 | (LPGUID)&hidguid, 438 | i, // 439 | &deviceInterfaceData); 440 | i++) 441 | { 442 | 443 | // 444 | // Open the device interface and Check if it is our device 445 | // by matching the Usage page and Usage from Hid_Caps. 446 | // If this is our device then send the hid request. 447 | // 448 | 449 | HANDLE file = OpenDeviceInterface(hardwareDeviceInfo, &deviceInterfaceData, myUsagePage, myUsage); 450 | 451 | if (file != INVALID_HANDLE_VALUE) 452 | { 453 | SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); 454 | return file; 455 | } 456 | 457 | // 458 | //device was not found so loop around. 459 | // 460 | 461 | } 462 | 463 | printf("Failure: Could not find our HID device \n"); 464 | 465 | SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); 466 | 467 | return INVALID_HANDLE_VALUE; 468 | } 469 | 470 | HANDLE 471 | OpenDeviceInterface ( 472 | HDEVINFO hardwareDeviceInfo, 473 | PSP_DEVICE_INTERFACE_DATA deviceInterfaceData, 474 | USAGE myUsagePage, 475 | USAGE myUsage 476 | ) 477 | { 478 | PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = NULL; 479 | 480 | DWORD predictedLength = 0; 481 | DWORD requiredLength = 0; 482 | HANDLE file = INVALID_HANDLE_VALUE; 483 | 484 | SetupDiGetDeviceInterfaceDetail( 485 | hardwareDeviceInfo, 486 | deviceInterfaceData, 487 | NULL, // probing so no output buffer yet 488 | 0, // probing so output buffer length of zero 489 | &requiredLength, 490 | NULL 491 | ); // not interested in the specific dev-node 492 | 493 | predictedLength = requiredLength; 494 | 495 | deviceInterfaceDetailData = 496 | (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc (predictedLength); 497 | 498 | if (!deviceInterfaceDetailData) 499 | { 500 | printf("Error: OpenDeviceInterface: malloc failed\n"); 501 | goto cleanup; 502 | } 503 | 504 | deviceInterfaceDetailData->cbSize = 505 | sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA); 506 | 507 | if (!SetupDiGetDeviceInterfaceDetail( 508 | hardwareDeviceInfo, 509 | deviceInterfaceData, 510 | deviceInterfaceDetailData, 511 | predictedLength, 512 | &requiredLength, 513 | NULL)) 514 | { 515 | printf("Error: SetupDiGetInterfaceDeviceDetail failed\n"); 516 | free (deviceInterfaceDetailData); 517 | goto cleanup; 518 | } 519 | 520 | //wchar_t wstFilePath[512]; 521 | //memset(wstFilePath, 0, 512); 522 | //wsprintf(wstFilePath, L"%s%s", L"D:\\", deviceInterfaceDetailData->DevicePath); 523 | file = CreateFile (deviceInterfaceDetailData->DevicePath, 524 | GENERIC_READ | GENERIC_WRITE, 525 | FILE_SHARE_READ | FILE_SHARE_READ, 526 | NULL, // no SECURITY_ATTRIBUTES structure 527 | OPEN_EXISTING, // No special create flags 528 | 0, // No special attributes 529 | NULL); // No template file 530 | 531 | if (INVALID_HANDLE_VALUE == file) { 532 | printf("Error: CreateFile failed: %d\n", GetLastError()); 533 | goto cleanup; 534 | } 535 | 536 | if (CheckIfOurDevice(file, myUsagePage, myUsage)){ 537 | goto cleanup; 538 | } 539 | 540 | CloseHandle(file); 541 | 542 | file = INVALID_HANDLE_VALUE; 543 | 544 | cleanup: 545 | 546 | free (deviceInterfaceDetailData); 547 | 548 | return file; 549 | 550 | } 551 | 552 | 553 | BOOLEAN 554 | CheckIfOurDevice( 555 | HANDLE file, 556 | USAGE myUsagePage, 557 | USAGE myUsage) 558 | { 559 | PHIDP_PREPARSED_DATA Ppd = NULL; // The opaque parser info describing this device 560 | HIDD_ATTRIBUTES Attributes; // The Attributes of this hid device. 561 | HIDP_CAPS Caps; // The Capabilities of this hid device. 562 | BOOLEAN result = FALSE; 563 | 564 | if (!HidD_GetPreparsedData (file, &Ppd)) 565 | { 566 | printf("Error: HidD_GetPreparsedData failed \n"); 567 | goto cleanup; 568 | } 569 | 570 | if (!HidD_GetAttributes(file, &Attributes)) 571 | { 572 | printf("Error: HidD_GetAttributes failed \n"); 573 | goto cleanup; 574 | } 575 | if(id==1) 576 | { 577 | vmul_vid=VMULTI_VID1; 578 | vmul_pid=VMULTI_PID1; 579 | } 580 | else if(id==2) 581 | { 582 | vmul_vid=VMULTI_VID2; 583 | vmul_pid=VMULTI_PID2; 584 | } 585 | else if(id==3) 586 | { 587 | vmul_vid=VMULTI_VID3; 588 | vmul_pid=VMULTI_PID3; 589 | } 590 | else if(id==4) 591 | { 592 | vmul_vid=VMULTI_VID4; 593 | vmul_pid=VMULTI_PID4; 594 | } 595 | else if(id==5) 596 | { 597 | vmul_vid=VMULTI_VID5; 598 | vmul_pid=VMULTI_PID5; 599 | } 600 | 601 | if (Attributes.VendorID == vmul_vid && Attributes.ProductID == vmul_pid) 602 | { 603 | if (!HidP_GetCaps (Ppd, &Caps)) 604 | { 605 | printf("Error: HidP_GetCaps failed \n"); 606 | goto cleanup; 607 | } 608 | 609 | if ((Caps.UsagePage == myUsagePage) && (Caps.Usage == myUsage)) 610 | { 611 | printf("Success: Found my device.. \n"); 612 | result = TRUE; 613 | } 614 | } 615 | 616 | cleanup: 617 | 618 | if (Ppd != NULL) 619 | { 620 | HidD_FreePreparsedData (Ppd); 621 | } 622 | 623 | return result; 624 | } 625 | 626 | BOOL 627 | HidOutput( 628 | BOOL useSetOutputReport, 629 | HANDLE file, 630 | PCHAR buffer, 631 | ULONG bufferSize 632 | ) 633 | { 634 | ULONG bytesWritten; 635 | if (useSetOutputReport) 636 | { 637 | // 638 | // Send Hid report thru HidD_SetOutputReport API 639 | // 640 | 641 | if (!HidD_SetOutputReport(file, buffer, bufferSize)) 642 | { 643 | printf("failed HidD_SetOutputReport %d\n", GetLastError()); 644 | return FALSE; 645 | } 646 | } 647 | else 648 | { 649 | if (!WriteFile(file, buffer, bufferSize, &bytesWritten, NULL)) 650 | { 651 | printf("failed WriteFile %d\n", GetLastError()); 652 | return FALSE; 653 | } 654 | } 655 | 656 | return TRUE; 657 | } --------------------------------------------------------------------------------