├── .gitignore ├── CONTRIBUTORS ├── CryptoSettings.props ├── CustomBuild ├── mc.props ├── mc.targets └── mc.xml ├── Globals ├── Globals.vcxproj ├── Globals.vcxproj.filters ├── Interface.h ├── ReadMe.txt ├── Version.h ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── HIDEmulator.sln ├── HidEmulator ├── Driver.props ├── Driver32.props ├── Driver64.props ├── Emulator.cpp ├── Emulator.h ├── EmulatorContext.cpp ├── EmulatorContext.h ├── EmulatorState.cpp ├── EmulatorState.h ├── HID.h ├── HIDReportData.h ├── HidDescriptor.h ├── HidEmulator.cpp ├── HidEmulator.hid ├── HidEmulator.rc ├── HidEmulator.vcxproj ├── HidEmulator.vcxproj.filters ├── HidEmulatorCodes.h ├── HidEmulatorKmdf.cpp ├── HidEmulatorKmdf.def ├── HidEmulatorKmdf.rc ├── HidEmulatorKmdf.vcxproj ├── HidEmulatorKmdf.vcxproj.filters ├── HidEmulatorKmdfCodes.mc ├── HidReportDescriptor.h ├── Signer.vcxproj ├── Signer.vcxproj.filters ├── StdDescriptors.h ├── WdfObjectDeleter.cpp ├── WdfObjectDeleter.h ├── WdfObjectLock.cpp ├── WdfObjectLock.h ├── WdfRequestCompleter.cpp ├── WdfRequestCompleter.h ├── WdfRequestRequeuer.cpp ├── WdfRequestRequeuer.h ├── inf │ ├── amd64 │ │ └── HidEmulator.inf │ └── i386 │ │ └── HidEmulator.inf ├── stdafx.cpp └── stdafx.h ├── Installer ├── DriverPackage.cpp ├── DriverPackage.h ├── Installer.cpp ├── Installer.def ├── Installer.h ├── Installer.vcxproj ├── Installer.vcxproj.filters ├── InstallerBase.cpp ├── InstallerBase.h ├── InstallerCodes.mc ├── InstanceEnumerator.cpp ├── InstanceEnumerator.h ├── LastErrorPreserver.cpp ├── LastErrorPreserver.h ├── NonPnpDevnode.cpp ├── NonPnpDevnode.h ├── PreprocFlags.h ├── ReadMe.txt ├── RestartRequiredTracker.h ├── ServiceControlManager.cpp ├── ServiceControlManager.h ├── ServiceHandle.cpp ├── ServiceHandle.h ├── SystemInfoClass.cpp ├── SystemInfoClass.h ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── InstallerApp ├── InstallerApp.cpp ├── InstallerApp.rc ├── InstallerApp.vcxproj ├── InstallerApp.vcxproj.filters ├── ReadMe.txt ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── LICENSE ├── OcuInterface ├── AutoLocker.cpp ├── AutoLocker.h ├── FocusAppInfo.cpp ├── FocusAppInfo.h ├── ObjPool.cpp ├── ObjPool.h ├── OcuHidInstance.cpp ├── OcuHidInstance.h ├── OcuIcon.cpp ├── OcuIcon.h ├── OcuIconWindowClass.cpp ├── OcuIconWindowClass.h ├── OcuImage.cpp ├── OcuImage.h ├── OcuInterface.cpp ├── OcuInterface.h ├── OcuInterface.vcxproj ├── OcuInterface.vcxproj.filters ├── OcuInterfaceCodes.mc ├── Overlapped.cpp ├── Overlapped.h ├── PreprocFlags.h ├── ReadMe.txt ├── hidpi.h ├── hidsdi.h ├── hidusage.h ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── OverlayHarness ├── GdiplusInitializer.cpp ├── GdiplusInitializer.h ├── OverlayHarness.cpp ├── OverlayHarness.rc ├── OverlayHarness.vcxproj ├── OverlayHarness.vcxproj.filters ├── ReadMe.txt ├── ResourcePng.cpp ├── ResourcePng.h ├── ResourceStream.cpp ├── ResourceStream.h ├── circle_icons │ ├── circle_01.png │ ├── circle_02.png │ ├── circle_03.png │ ├── circle_04.png │ ├── circle_05.png │ ├── circle_06.png │ ├── circle_07.png │ ├── circle_08.png │ ├── circle_09.png │ ├── circle_10.png │ ├── circle_11.png │ ├── circle_12.png │ ├── circle_13.png │ ├── circle_14.png │ ├── circle_15.png │ └── circle_16.png ├── resource.h ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── Resource └── Certificate │ ├── DigiCert Assured ID Root CA.crt │ ├── MakeTestCert.bat │ └── Readme.txt ├── TestHarness ├── ReadMe.txt ├── TestHarness.cpp ├── TestHarness.vcxproj ├── TestHarness.vcxproj.filters ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── TouchDisplay ├── ReadMe.txt ├── TouchDisplay.cpp ├── TouchDisplay.h ├── TouchDisplay.ico ├── TouchDisplay.rc ├── TouchDisplay.vcxproj ├── TouchDisplay.vcxproj.filters ├── TouchRepresentation.cpp ├── TouchRepresentation.h ├── resource.h ├── small.ico ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── WinDDK.props ├── contrib ├── amd64 │ └── hid.lib └── i386 │ └── hid.lib ├── newdev ├── ReadMe.txt ├── newdev.cpp ├── newdev.def ├── newdev.h ├── newdev.vcxproj ├── newdev.vcxproj.filters ├── stdafx.cpp └── stdafx.h └── tools ├── HCLIENT.EXE └── dt ├── BatSys.upg ├── Dt.exe ├── PwrDev.upg ├── Tparse.dll ├── Tparse.lib ├── VESACmnd.upg ├── VESAVC.upg ├── andisp.upg ├── andisply.hid ├── button.upg ├── consume.upg ├── delimit.hid ├── desktop.upg ├── digit.hid ├── digit.upg ├── display.hid ├── dt.ini ├── gaming.upg ├── joystk.hid ├── kbd.upg ├── keybrd.hid ├── leds.upg ├── mon_enum.upg ├── monitor.hid ├── monitor.upg ├── mouse.hid ├── ordinal.upg ├── pwr.hid ├── readme.txt ├── remote.hid ├── sim.upg ├── sports.upg ├── tele.hid ├── tele.upg ├── unicode.upg ├── vendor1.upg └── vr.upg /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.log 3 | *.dbg 4 | *.opensdf 5 | *.sdf 6 | Release/ 7 | Debug/ 8 | *.CppClean.log 9 | *.unsuccessfulbuild 10 | *.suo 11 | ipch 12 | MSG00001.bin 13 | HidEmulator/HidEmulatorKmdfCodes.h 14 | HidEmulator/HidEmulatorKmdfCodes.rc 15 | Installer/InstallerCodes.h 16 | Installer/InstallerCodes.rc 17 | OcuInterface/OcuInterfaceCodes.h 18 | OcuInterface/OcuInterfaceCodes.rc 19 | *.user 20 | InstallerApp/InstallerApp.aps 21 | *.aps 22 | -------------------------------------------------------------------------------- /CryptoSettings.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | En1Fm1ksp; 6 | $(SolutionDir)Resource\Certificate\DigiCert Assured ID Root CA.crt 7 | 1 8 | 9 | 10 | 11 | 12 | 13 | $(CertPass) 14 | 15 | 16 | $(XSCPath) 17 | 18 | 19 | $(CrossSign) 20 | 21 | 22 | -------------------------------------------------------------------------------- /CustomBuild/mc.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | BeforeClCompile 6 | 7 | 8 | 9 | _SelectedFiles;ResolveAssemblyReferences;$(McCompilerDependsOn) 10 | 11 | 12 | 13 | true 14 | $(TargetFileName) 15 | $(ProjectDir) 16 | $(ProjectDir) 17 | $(ProjectDir) 18 | 19 | h 20 | 21 | mc.exe [AllOptions] [AdditionalOptions] [Inputs] 22 | %(HeaderOutputPath)%(Filename).%(HFileExtension) 23 | %(ResourceOutputPath)%(Filename).rc 24 | %(DbgCDest)%(Filename).dbg 25 | true 26 | Compiling messages... 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /CustomBuild/mc.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | McCompile 8 | 9 | 10 | 11 | 12 | $(ComputeLinkInputsTargets); 13 | ComputeMcCompilerOutput; 14 | 15 | 16 | 20 | $(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml 21 | 22 | 30 | 31 | 32 | 33 | 34 | 35 | @(McCompiler, '|') 36 | 37 | 38 | 39 | 40 | 41 | 42 | 45 | 49 | 67 | 68 | 69 | 70 | 71 | 74 | 75 | <_EmbedManagedResourceFile Include="@(McCompiler->Metadata('Outputs')->Distinct()->ClearMetadata())" Condition="'%(McCompiler.ExcludedFromBuild)' != 'true'"/> 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Globals/Globals.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 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | 35 | 36 | Source Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /Globals/Interface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // HID vendor ID: 4 | #define OCUHID_VENDOR_ID 0xF182 5 | 6 | // Leap Motion HID Product ID 7 | #define OCUHID_EMULATED_DEVICE 0x1000 8 | 9 | // HID Interface 10 | #define OCUHID_INTERFACE_VERSION 1 11 | 12 | // Maximum simaltaneous touch report count 13 | #define MAX_TOUCHREPORT_COUNT 2 14 | 15 | // Report identifiers: 16 | enum 17 | { 18 | REPORTID_FINGERS = 1, 19 | REPORTID_MAXIMUMCOUNT, 20 | REPORTID_FEATURE, 21 | REPORTID_MOUSE, 22 | REPORTID_SYNTHESIZE, 23 | REPORTID_RESETTOUCHSTATE, 24 | REPORTID_RESETMOUSESTATE, 25 | REPORTID_NULL 26 | }; 27 | 28 | // This is the mode of operation that the HidEmulator is going to operate in. 29 | // These modes are documented in MSDN, but their operating mode is pretty straightforward: 30 | // 31 | // The mouse input mode means that the device will be treated like a mouse with a continuous 32 | // presence on screen. Signalling may be differential or absolute (but is typically absolute). 33 | // Mouse input mode also means that the mouse report descriptor is used, instead of the touch 34 | // descriptor. 35 | // 36 | // The single touch input mode means that only one contact point is interpreted, and the other 37 | // inputs will be ignored. Otherwise it functions the same as multitouch. 38 | // 39 | // In mulititouch mode, full multitouch capabilities are available. More than one contact is 40 | // supported, as long as each contact has its own contact identifier. 41 | enum DevInMode 42 | { 43 | MODE_MOUSE, 44 | MODE_SINGLE_TOUCH, 45 | MODE_MULTI_TOUCH 46 | }; 47 | 48 | #pragma pack(push, 1) 49 | 50 | /// 51 | /// Feature report header, included as a base class in feature reporting 52 | /// types. This choice allows feature reports to be written to directly 53 | /// without clobbering the ReportID, which is required for the OS to process 54 | /// the feature report correctly. 55 | /// 56 | struct HID_INPUT_REPORT 57 | { 58 | UCHAR ReportID; 59 | }; 60 | 61 | /// 62 | /// Report used to describe the maximum number of contact points this device supports 63 | /// 64 | struct HID_MAXIMUM_COUNT: 65 | HID_INPUT_REPORT 66 | { 67 | UCHAR MaxCount; 68 | UCHAR DeviceIndex; 69 | }; 70 | 71 | /// 72 | /// Report used to assign the input mode or, optionally, query the current input mode 73 | /// 74 | struct HID_INPUT_MODE: 75 | HID_INPUT_REPORT 76 | { 77 | UCHAR InputMode; 78 | UCHAR DeviceIndex; 79 | }; 80 | 81 | // Logical maximum for finger report. The logical maximum is used to refer to the domain of report coordinates. 82 | #define FINGER_REPORT_LMAX 4095 83 | 84 | /// 85 | /// A finger report. This is a single discrete input event, describing an atomic state of a single finger. 86 | /// 87 | union HID_FINGER_REPORT 88 | { 89 | struct 90 | { 91 | unsigned TipSwitch:1; 92 | unsigned InRange:1; 93 | unsigned Reserved2:6; 94 | }; 95 | struct 96 | { 97 | UCHAR bStatus; 98 | UCHAR bContactId; 99 | USHORT cxData; 100 | USHORT cyData; 101 | USHORT wXData; 102 | USHORT wYData; 103 | }; 104 | }; 105 | 106 | /// 107 | /// This is a full gesture report. It includes a report identifier and up to MAX_TOUCHREPORT_COUNT 108 | /// touch reports. 109 | /// 110 | struct HID_GESTURE_REPORT: 111 | HID_INPUT_REPORT 112 | { 113 | // The actual contact structures 114 | HID_FINGER_REPORT contacts[MAX_TOUCHREPORT_COUNT]; 115 | 116 | // The actual number of inputs in the contacts structure 117 | UCHAR ActualInputs; 118 | }; 119 | 120 | // Assert some properties about the gesture report: 121 | static_assert( (long long)(char*)&((HID_FINGER_REPORT*)0)->cxData == 2ULL, "Offsets incorrect for the HID gesture report." ); 122 | 123 | // The logical maximum of mouse report payload 124 | #define MOUSE_REPORT_LMAX 32767 125 | 126 | /// 127 | /// The mouse report structure, for use when the device input mode is set to mouse 128 | /// 129 | struct HID_MOUSE_REPORT: 130 | HID_INPUT_REPORT 131 | { 132 | union 133 | { 134 | struct 135 | { 136 | // Left mouse button 137 | unsigned Button1:1; 138 | 139 | // Right mouse button 140 | unsigned Button2:1; 141 | 142 | // Ignored, set to zero 143 | unsigned Reserved:6; 144 | }; 145 | struct 146 | { 147 | // Flags, corresponding to the first structure in this union 148 | BYTE Flags; 149 | WORD x; 150 | WORD y; 151 | }; 152 | }; 153 | }; 154 | 155 | /// 156 | /// This is used when the report is REPORTID_RESETTOUCHSTATE. It indicates 157 | /// the contact ID of the touch input to be reset. Up to MAX_TOUCHREPORT_COUNT 158 | /// may be sent at once. 159 | /// 160 | struct HID_RESET_REPORT 161 | { 162 | UCHAR ResetContactID[MAX_TOUCHREPORT_COUNT]; 163 | UCHAR ActualInputs; 164 | }; 165 | 166 | // Validate position: 167 | static_assert( (long long)(char*)&((HID_MOUSE_REPORT*)0)->x == 2ULL, "Incorrect offset in mouse report descriptor" ); 168 | 169 | /// 170 | /// Synthesis report. The synthesis report is an omnibus structure that includes a report identifier and all 171 | /// of the possible reports that may either be generated by the HID emulator. 172 | /// 173 | struct HID_SYNTEHSIZE_REPORT: 174 | HID_INPUT_REPORT 175 | { 176 | union 177 | { 178 | UCHAR SynthesizedReportID; 179 | 180 | HID_GESTURE_REPORT GestureReport; 181 | HID_MOUSE_REPORT MouseReport; 182 | HID_RESET_REPORT ResetReport; 183 | 184 | // This field is not used directly; rather, its presence here is to ensure that the length 185 | // of the parent structure is 64 bytes. 186 | UCHAR RawInput[64]; 187 | }; 188 | }; 189 | 190 | #pragma pack(pop) 191 | -------------------------------------------------------------------------------- /Globals/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : Globals Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this Globals library project for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your Globals application. 9 | 10 | 11 | Globals.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | Globals.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | 25 | ///////////////////////////////////////////////////////////////////////////// 26 | 27 | StdAfx.h, StdAfx.cpp 28 | These files are used to build a precompiled header (PCH) file 29 | named Globals.pch and a precompiled types file named StdAfx.obj. 30 | 31 | ///////////////////////////////////////////////////////////////////////////// 32 | Other notes: 33 | 34 | AppWizard uses "TODO:" comments to indicate parts of the source code you 35 | should add to or customize. 36 | 37 | ///////////////////////////////////////////////////////////////////////////// 38 | -------------------------------------------------------------------------------- /Globals/Version.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Version information used everywhere 4 | #define OCS_MAJ(x) (((x) & 0xF0000000) >> 28) 5 | #define OCS_MIN(x) (((x) & 0x0F000000) >> 24) 6 | #define OCS_REV(x) (((x) & 0x00FFFFFF) >> 0) 7 | 8 | #define OCS_VER(maj, min, rev) (((maj) << 28) | ((min) << 24) | rev) 9 | 10 | #define HIDEMULATOR_VERSION OCS_VER(0, 8, 2) 11 | -------------------------------------------------------------------------------- /Globals/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | -------------------------------------------------------------------------------- /Globals/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "targetver.h" 4 | -------------------------------------------------------------------------------- /Globals/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | -------------------------------------------------------------------------------- /HidEmulator/Driver.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | $(WINDDK)bin\selfsign;$(ExecutablePath) 7 | $(WINDDK)inc\crt;$(WINDDK)inc\api;$(WINDDK)inc\ddk;$(IncludePath) 8 | 9 | 10 | 11 | $(WinDDK)inc\ddk;$(WinDDK)inc\api;$(WinDDK)inc\crt;$(WinDDK)inc\wdf\kmdf\1.9;%(AdditionalIncludeDirectories) 12 | 13 | 14 | BufferOverflowK.lib;ntoskrnl.lib;hal.lib;wmilib.lib;sehupd.lib;nt.lib;hidclass.lib;%(AdditionalDependencies) 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /HidEmulator/Driver32.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | $(WinDDK)lib\Crt\i386;$(WinDDK)lib\wnet\i386;$(WinDDK)lib\wdf\kmdf\i386\1.9;%(AdditionalLibraryDirectories) 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /HidEmulator/Driver64.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | $(WinDDK)lib\Crt\amd64;$(WinDDK)lib\wnet\amd64;$(WinDDK)lib\wdf\kmdf\amd64\1.9;%(AdditionalLibraryDirectories) 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /HidEmulator/Emulator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "HIDDescriptor.h" 3 | #include "EmulatorState.h" 4 | 5 | /// 6 | /// The core implementation of the HidEmulator 7 | /// 8 | /// 9 | /// The HidEmulator works using two ping-pong queues: One from the synthesis source, and one from the 10 | /// HID class driver. Requests from the client are put in the synthesis queue, and as read requests 11 | /// come in from the HID class driver, packets are dequeued from the synthesis queue and read into the 12 | /// requests from the class driver. A typical idle state is for the ReadQueue to have a few packets 13 | /// (typically two, but the number of read packets is system-configuable) and for the SynthQueue to 14 | /// be empty. If the ReadQueue is empty and the number of packets in the SynthQueue is increasing, 15 | /// it indicates that the system is being overdriven. You really need to drive the system quite fast 16 | /// to achive this case, but if it happens, severe performance penalties will be the result. 17 | /// 18 | class CEmulator 19 | { 20 | public: 21 | /// 22 | /// Constructs a new emulator with the given device object as the hDevice of that emulator 23 | /// 24 | CEmulator(WDFDEVICE hDevice); 25 | ~CEmulator(void); 26 | 27 | private: 28 | // Reflexive device pointer: 29 | WDFDEVICE m_hDevice; 30 | 31 | // Reflexive IO target 32 | WDFIOTARGET IoTarget; 33 | 34 | // Collection of IO operations to be fed into hidclass 35 | WDFQUEUE SynthQueue; 36 | 37 | // Collection of IRPs awaiting fulfillment from hidclass 38 | WDFQUEUE ReadQueue; 39 | 40 | // Input mode: 41 | DevInMode InputMode; 42 | 43 | // Emulator state: 44 | CEmulatorState m_state; 45 | 46 | private: 47 | /// 48 | /// Satisfies a matched read request and synthesis request 49 | /// 50 | /// Set to true if the initiator is a synthesis operation 51 | void Satisfy(WDFREQUEST ReadRequest, WDFREQUEST SynthRequest, bool bSynthesisInitiator); 52 | 53 | /// 54 | /// Either queues the specified request to the specified queue, or attempts to use the request to 55 | /// synthesize an input 56 | /// 57 | template 58 | void SatisfyOrEnqueue(WDFREQUEST Request); 59 | 60 | /// 61 | /// Gets the descriptor that describes the device, including an indication of the number of 62 | /// report descriptors. 63 | /// 64 | void GetDeviceDescriptor(WDFREQUEST Request); 65 | 66 | /// 67 | /// Gets general attributes describe the device 68 | /// 69 | void GetDeviceAttributes(WDFREQUEST Request); 70 | 71 | /// 72 | /// Gets the one and only report descriptor describing the reports generated by the device. 73 | /// The output of this handler is used by the HID class to create child devices. 74 | /// 75 | void GetReportDescriptor(WDFREQUEST Request); 76 | 77 | /// 78 | /// String recovery request handler 79 | /// 80 | void GetString(WDFREQUEST Request); 81 | 82 | /// 83 | /// Feature get method 84 | /// 85 | void GetFeature(WDFREQUEST Request); 86 | 87 | /// 88 | /// Feature set method 89 | /// 90 | void SetFeature(WDFREQUEST Request); 91 | 92 | public: 93 | const CEmulatorState& GetState(void) const {return m_state;} 94 | 95 | /// 96 | /// Causes a request to be pended to this emulator's own internal queue for later synthesis. 97 | /// Useful for debugging, but also used by CEmulatorContext to restore state in the event of 98 | /// unexpected client termination. 99 | /// 100 | NTSTATUS QueueSynthesisToSelf(const HID_SYNTEHSIZE_REPORT& report); 101 | 102 | // Generic handlers: 103 | NTSTATUS DeviceControlInternal(PDEVICE_OBJECT DeviceObject, PIRP Irp); 104 | EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL EvtInternalDeviceControl; 105 | }; 106 | 107 | // Make type information available: 108 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CEmulator, GetDeviceContext) 109 | 110 | // Forward declarations: 111 | EVT_WDF_OBJECT_CONTEXT_CLEANUP EvtEmulatorCleanup; 112 | EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL EvtInternalDeviceControl; 113 | -------------------------------------------------------------------------------- /HidEmulator/EmulatorContext.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "EmulatorContext.h" 3 | #include "Emulator.h" 4 | 5 | CEmulatorContext::CEmulatorContext(CEmulator* pParent): 6 | m_pParent(pParent) 7 | { 8 | } 9 | 10 | CEmulatorContext::~CEmulatorContext(void) 11 | { 12 | HID_SYNTEHSIZE_REPORT report; 13 | memset(&report, 0, sizeof(report)); 14 | report.SynthesizedReportID = REPORTID_RESETTOUCHSTATE; 15 | 16 | // Run through each state in the touchState array: 17 | for(BYTE i = 0; i < ARRAYSIZE(m_state.touchState); i++) 18 | { 19 | auto& cur = m_state.touchState[i]; 20 | if(!cur.TipSwitch) 21 | // No need to reset this finger: 22 | continue; 23 | 24 | // The finger needs to have a regenerated state that is equal 25 | // to the current position, minus whatever keys are assigned at 26 | // this moment. 27 | auto& reset = report.ResetReport; 28 | reset.ResetContactID[reset.ActualInputs] = i; 29 | 30 | if(++reset.ActualInputs == 2) 31 | // Emulate this report. 32 | { 33 | m_pParent->QueueSynthesisToSelf(report); 34 | reset.ActualInputs = 0; 35 | } 36 | } 37 | 38 | // Tail case, if there's anything still unsynthesized 39 | if(report.ResetReport.ActualInputs) 40 | m_pParent->QueueSynthesisToSelf(report); 41 | 42 | // Reset mouse events as needed 43 | if(m_state.mouseState.Button1 || m_state.mouseState.Button2) 44 | { 45 | report.SynthesizedReportID = REPORTID_RESETMOUSESTATE; 46 | m_pParent->QueueSynthesisToSelf(report); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /HidEmulator/EmulatorContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "EmulatorState.h" 3 | 4 | class CEmulator; 5 | 6 | /// 7 | /// Unused. If a way was needed to track individual clients, this class would provide it. 8 | /// Currently, it is difficult to track who has handles open to the HidEmualtor because the 9 | /// HID class driver does not allow direct handles to be opened to the device, nor does it 10 | /// notify the device when a handle is opened or closed. 11 | /// 12 | class CEmulatorContext 13 | { 14 | public: 15 | CEmulatorContext(CEmulator* pParent); 16 | ~CEmulatorContext(void); 17 | 18 | private: 19 | // The parent emulator of this context 20 | CEmulator* m_pParent; 21 | 22 | // State known to the system that is due to this emulator context: 23 | CEmulatorState m_state; 24 | }; 25 | 26 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CEmulatorContext, GetFileObjectContext) 27 | -------------------------------------------------------------------------------- /HidEmulator/EmulatorState.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "EmulatorState.h" 3 | 4 | CEmulatorState::CEmulatorState(void) 5 | { 6 | } 7 | 8 | CEmulatorState::~CEmulatorState(void) 9 | { 10 | } 11 | -------------------------------------------------------------------------------- /HidEmulator/EmulatorState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// 4 | /// Kernel-mode state tracking structure of the HID emulator. 5 | /// 6 | /// 7 | /// In the event that a client goes away, it may be necessary to reset the state of the HID emualtor. 8 | /// In that case, up-events are sent to the operating system for each contact point currently down 9 | /// on the screen, thereby freeing any "stuck mouse" situation that may arise if an application crashes 10 | /// while synthesizing a touch event. 11 | /// 12 | /// Note also that only those states that are due to a particular client are reset. No touch events 13 | /// are synthesized to an "up" state if a client crashes, provided that client is not currently the cause 14 | /// of a finger press. 15 | /// 16 | class CEmulatorState 17 | { 18 | public: 19 | CEmulatorState(void); 20 | ~CEmulatorState(void); 21 | 22 | public: 23 | // Current state of each fingertip. This is defined as the last input synthesized on the interface. 24 | HID_FINGER_REPORT touchState[16]; 25 | 26 | // Current mouse state, as synthesized by the client. 27 | HID_MOUSE_REPORT mouseState; 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /HidEmulator/HidDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma pack(push, 1) 3 | 4 | #define __INCLUDE_FROM_USB_DRIVER 5 | #define __INCLUDE_FROM_HID_DRIVER 6 | #define USB_CAN_BE_DEVICE 7 | 8 | #include "HID.h" 9 | #include "HIDReportData.h" 10 | #include "HidReportDescriptor.h" 11 | 12 | /// 13 | /// This is a static global definition of the HID descriptor. 14 | /// 15 | /// 16 | /// The HID descriptor is a top-level descriptor that provides one piece of information: 17 | /// A description of the report descriptor. The report descriptor has the rest of the 18 | /// information about the device. 19 | /// 20 | static USB_HID_StdDescriptor_HID_t g_hidDesc = 21 | { 22 | 0x09, // length of HID descriptor 23 | 0x21, // descriptor type == HID 0x21 24 | 0x0100, // hid spec release 25 | 0x00, // country code == Not Specified 26 | 0x01, // number of HID class descriptors 27 | 28 | HID_DTYPE_Report, // descriptor type 29 | sizeof(g_reportDesc) // total length of report descriptor 30 | }; 31 | 32 | // The length of the report descriptor is pretty important as it is a spec-defined value. 33 | // This assertion ensures that the length constraint is met. 34 | static_assert(sizeof(g_hidDesc) == 9, "HID descriptor size not precisely 9"); 35 | 36 | #pragma pack(pop) 37 | -------------------------------------------------------------------------------- /HidEmulator/HidEmulator.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | // Forward declarations: 4 | void Unload(PDRIVER_OBJECT DriverObject); 5 | NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject); 6 | NTSTATUS PassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp); 7 | NTSTATUS PowerPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp); 8 | 9 | // Driver entrypoint 10 | extern "C" 11 | NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) 12 | { 13 | NTSTATUS status; 14 | 15 | // Default almost everything: 16 | for each(auto*& p in DriverObject->MajorFunction) 17 | p = PassThrough; 18 | 19 | // Power IRP is special: 20 | DriverObject->MajorFunction[IRP_MJ_POWER] = PowerPassThrough; 21 | 22 | // AddDevice and Unload methods must be added, but here, do nothing. 23 | DriverObject->DriverExtension->AddDevice = AddDevice; 24 | DriverObject->DriverUnload = Unload; 25 | 26 | // Register with the HID minidriver. No driver extension is required so its size is 27 | // set to zero. 28 | HID_MINIDRIVER_REGISTRATION reg; 29 | memset(®, 0, sizeof(reg)); 30 | reg.Revision = HID_REVISION; 31 | reg.DriverObject = DriverObject; 32 | reg.RegistryPath = RegistryPath; 33 | reg.DeviceExtensionSize = 0; 34 | reg.DevicesArePolled = false; 35 | 36 | // Invoke the minidriver registration routine. The reason we don't implement this 37 | // whole driver with the KMDF is because of this call: The HID port driver wants 38 | // ownership of the device extension, and KMDF wants the same thing, so the two 39 | // contend. Resolution of this contention is had by installing the KMDF driver as 40 | // a lower filter to this driver. 41 | status = HidRegisterMinidriver(®); 42 | if(!NT_SUCCESS(status)) 43 | { 44 | OcsDebugPrint("Failed to register the mini driver (0x%08x)", status); 45 | return status; 46 | } 47 | 48 | OcsDebugPrint("OcuSpec WDF HID Emulator loaded"); 49 | return status; 50 | } 51 | 52 | /// 53 | /// Unload routine for the driver 54 | /// 55 | void Unload(PDRIVER_OBJECT DriverObject) 56 | { 57 | OcsDebugPrint("OcuSpec HID Emulator unloaded"); 58 | } 59 | 60 | NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT FunctionalDeviceObject) 61 | { 62 | // Do nothing except return success 63 | OcsDebugPrint("WDF AddDevice invoked"); 64 | return STATUS_SUCCESS; 65 | } 66 | 67 | NTSTATUS PassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp) 68 | { 69 | // The passthrough routine does just that: It copies the current IRP stack location 70 | // to the next one, and allows the next driver in the chain to handle the request. 71 | IoSkipCurrentIrpStackLocation(Irp); 72 | return IoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp); 73 | } 74 | 75 | NTSTATUS PowerPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp) 76 | { 77 | // The power pass-through operation is a little different. We need to indicate to 78 | // the power manager that it can start the next power IRP (for this driver), and then 79 | // we copy the current stack location to next and handle things as expected. 80 | PoStartNextPowerIrp(Irp); 81 | IoCopyCurrentIrpStackLocationToNext(Irp); 82 | return PoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp); 83 | } -------------------------------------------------------------------------------- /HidEmulator/HidEmulator.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/HidEmulator/HidEmulator.hid -------------------------------------------------------------------------------- /HidEmulator/HidEmulator.rc: -------------------------------------------------------------------------------- 1 | #include "../Globals/Version.h" 2 | #include "afxres.h" 3 | 4 | ///////////////////////////////////////////////////////////////////////////// 5 | // 6 | // Version 7 | // 8 | 9 | #undef OCS_VER 10 | #define OCS_VER(maj, min, rev) maj,min,rev 11 | 12 | VS_VERSION_INFO VERSIONINFO 13 | FILEVERSION HIDEMULATOR_VERSION 14 | PRODUCTVERSION HIDEMULATOR_VERSION 15 | FILEFLAGSMASK 0x17L 16 | #ifdef _DEBUG 17 | FILEFLAGS 0x1L 18 | #else 19 | FILEFLAGS 0x0L 20 | #endif 21 | FILEOS 0x4L 22 | FILETYPE 0x3L 23 | FILESUBTYPE 0x7L 24 | BEGIN 25 | BLOCK "StringFileInfo" 26 | BEGIN 27 | #undef OCS_VER 28 | #define OCS_VER(maj, min, rev) #maj ", " #min ", " #rev 29 | BLOCK "040904b0" 30 | BEGIN 31 | VALUE "CompanyName", "Leap Motion, Inc." 32 | VALUE "FileDescription", "Touch input emulation driver" 33 | VALUE "FileVersion", HIDEMULATOR_VERSION 34 | VALUE "InternalName", "HIDEmulator" 35 | VALUE "LegalCopyright", "Copyright (C) 2012-2013" 36 | VALUE "OriginalFilename", "HidEmulator.sys" 37 | VALUE "ProductName", "HidEmulator" 38 | VALUE "ProductVersion", HIDEMULATOR_VERSION 39 | END 40 | END 41 | BLOCK "VarFileInfo" 42 | BEGIN 43 | VALUE "Translation", 0x409, 1200 44 | END 45 | END -------------------------------------------------------------------------------- /HidEmulator/HidEmulator.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {aa41bb4f-d699-4469-a8d3-7797e281c709} 6 | 7 | 8 | {f009a1e1-6122-48a4-8681-90f15d0148b7} 9 | 10 | 11 | {f12ff0da-5a37-4f56-ba29-41e2283ee589} 12 | 13 | 14 | 15 | 16 | Resource Files 17 | 18 | 19 | 20 | 21 | Source Files 22 | 23 | 24 | Source Files 25 | 26 | 27 | 28 | 29 | Header Files 30 | 31 | 32 | Header Files 33 | 34 | 35 | -------------------------------------------------------------------------------- /HidEmulator/HidEmulatorCodes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // 3 | // Status values are 32 bit values layed out as follows: 4 | // 5 | // 3 2 1 0 6 | // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 7 | // +---+-+-------------------------+-------------------------------+ 8 | // |Sev|C| Facility | Code | 9 | // +---+-+-------------------------+-------------------------------+ 10 | // 11 | // where 12 | // 13 | // Sev - is the severity code 14 | // 15 | // 00 - Success 16 | // 01 - Informational 17 | // 10 - Warning 18 | // 11 - Error 19 | // 20 | // C - is the Customer code flag 21 | // 22 | // Facility - is the facility code 23 | // 24 | // Code - is the facility's status code 25 | // 26 | // 27 | // Values are 32 bit values laid out as follows: 28 | // 29 | // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 30 | // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 31 | // +---+-+-+-----------------------+-------------------------------+ 32 | // |Sev|C|R| Facility | Code | 33 | // +---+-+-+-----------------------+-------------------------------+ 34 | // 35 | // where 36 | // 37 | // Sev - is the severity code 38 | // 39 | // 00 - Success 40 | // 01 - Informational 41 | // 10 - Warning 42 | // 11 - Error 43 | // 44 | // C - is the Customer code flag 45 | // 46 | // R - is a reserved bit 47 | // 48 | // Facility - is the facility code 49 | // 50 | // Code - is the facility's status code 51 | // 52 | // 53 | // Define the facility codes 54 | // 55 | 56 | 57 | // 58 | // Define the severity codes 59 | // 60 | #define OVL_STATUS_WARNING 0x2 61 | #define OVL_STATUS_SUCCESS 0x0 62 | #define OVL_STATUS_INFORMATION 0x1 63 | #define OVL_STATUS_ERROR 0x3 64 | 65 | 66 | // 67 | // MessageId: eHidInstFailure 68 | // 69 | // MessageText: 70 | // 71 | // General failure condition 72 | // 73 | #define eHidInstFailure ((eHidStatus)0xE0000000L) 74 | 75 | -------------------------------------------------------------------------------- /HidEmulator/HidEmulatorKmdf.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | EXPORTS 3 | DriverEntry -------------------------------------------------------------------------------- /HidEmulator/HidEmulatorKmdf.rc: -------------------------------------------------------------------------------- 1 | #include "../Globals/Version.h" 2 | 3 | ///////////////////////////////////////////////////////////////////////////// 4 | // 5 | // Version 6 | // 7 | 8 | #undef OCS_VER 9 | #define OCS_VER(maj, min, rev) maj,min,rev 10 | 11 | VS_VERSION_INFO VERSIONINFO 12 | FILEVERSION HIDEMULATOR_VERSION 13 | PRODUCTVERSION HIDEMULATOR_VERSION 14 | FILEFLAGSMASK 0x17L 15 | #ifdef _DEBUG 16 | FILEFLAGS 0x1L 17 | #else 18 | FILEFLAGS 0x0L 19 | #endif 20 | FILEOS 0x4L 21 | FILETYPE 0x3L 22 | FILESUBTYPE 0x7L 23 | BEGIN 24 | BLOCK "StringFileInfo" 25 | BEGIN 26 | #undef OCS_VER 27 | #define OCS_VER(maj, min, rev) #maj ", " #min ", " #rev 28 | BLOCK "040904b0" 29 | BEGIN 30 | VALUE "CompanyName", "Leap Motion, Inc." 31 | VALUE "FileDescription", "Kernel-mode user input redirection driver" 32 | VALUE "FileVersion", HIDEMULATOR_VERSION 33 | VALUE "InternalName", "KuirKbdFltr" 34 | VALUE "LegalCopyright", "Copyright (C) 2012-2013" 35 | VALUE "OriginalFilename", "HidEmulator.sys" 36 | VALUE "ProductName", "HidEmulator" 37 | VALUE "ProductVersion", HIDEMULATOR_VERSION 38 | END 39 | END 40 | BLOCK "VarFileInfo" 41 | BEGIN 42 | VALUE "Translation", 0x409, 1200 43 | END 44 | END -------------------------------------------------------------------------------- /HidEmulator/HidEmulatorKmdf.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {aa41bb4f-d699-4469-a8d3-7797e281c709} 6 | 7 | 8 | {f009a1e1-6122-48a4-8681-90f15d0148b7} 9 | 10 | 11 | {f12ff0da-5a37-4f56-ba29-41e2283ee589} 12 | 13 | 14 | {a7e18323-5f56-48ba-b204-a45de42f3ea9} 15 | 16 | 17 | 18 | 19 | Resource Files 20 | 21 | 22 | Resource Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | 55 | 56 | Header Files 57 | 58 | 59 | Header Files 60 | 61 | 62 | Header Files 63 | 64 | 65 | HID 66 | 67 | 68 | HID 69 | 70 | 71 | Header Files 72 | 73 | 74 | HID 75 | 76 | 77 | Header Files 78 | 79 | 80 | Header Files 81 | 82 | 83 | Header Files 84 | 85 | 86 | Header Files 87 | 88 | 89 | Header Files 90 | 91 | 92 | Header Files 93 | 94 | 95 | Header Files 96 | 97 | 98 | 99 | 100 | Resource Files 101 | 102 | 103 | 104 | 105 | Resource Files 106 | 107 | 108 | -------------------------------------------------------------------------------- /HidEmulator/HidEmulatorKmdfCodes.mc: -------------------------------------------------------------------------------- 1 | ;#pragma once 2 | ;// 3 | ;// Status values are 32 bit values layed out as follows: 4 | ;// 5 | ;// 3 2 1 0 6 | ;// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 7 | ;// +---+-+-------------------------+-------------------------------+ 8 | ;// |Sev|C| Facility | Code | 9 | ;// +---+-+-------------------------+-------------------------------+ 10 | ;// 11 | ;// where 12 | ;// 13 | ;// Sev - is the severity code 14 | ;// 15 | ;// 00 - Success 16 | ;// 01 - Informational 17 | ;// 10 - Warning 18 | ;// 11 - Error 19 | ;// 20 | ;// C - is the Customer code flag 21 | ;// 22 | ;// Facility - is the facility code 23 | ;// 24 | ;// Code - is the facility's status code 25 | ;// 26 | 27 | MessageIdTypedef=eHidStatus 28 | 29 | SeverityNames=( 30 | Success = 0x0 : OCUHID_STATUS_SUCCESS 31 | Informational = 0x1 : OCUHID_STATUS_INFORMATION 32 | Warning = 0x2 : OCUHID_STATUS_WARNING 33 | Error = 0x3 : OCUHID_STATUS_ERROR 34 | ) 35 | 36 | FacilityNames=( 37 | HidEm = 0x0 38 | ) 39 | 40 | MessageId=0 41 | Severity=Error 42 | Facility=HidEm 43 | SymbolicName=eHidInstFailure 44 | Language=English 45 | General failure condition 46 | . 47 | -------------------------------------------------------------------------------- /HidEmulator/Signer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {24de9df6-b408-4edf-a900-6d1d09815be4} 6 | 7 | 8 | {cf825af8-972d-454f-81ef-53ad28c03ece} 9 | 10 | 11 | 12 | 13 | i386 14 | 15 | 16 | amd64 17 | 18 | 19 | -------------------------------------------------------------------------------- /HidEmulator/WdfObjectDeleter.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "WdfObjectDeleter.h" 3 | 4 | CWdfObjectDeleter::CWdfObjectDeleter(WDFOBJECT Object): 5 | Object(Object) 6 | { 7 | } 8 | 9 | CWdfObjectDeleter::~CWdfObjectDeleter(void) 10 | { 11 | if(Object) 12 | // Delete the object 13 | WdfObjectDelete(Object); 14 | } 15 | -------------------------------------------------------------------------------- /HidEmulator/WdfObjectDeleter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// 4 | /// RAII object deleter 5 | /// 6 | class CWdfObjectDeleter 7 | { 8 | public: 9 | /// 10 | /// Deletes the passed object if it's still attached when this deleter is destroyed 11 | /// 12 | /// The object to be deleted 13 | CWdfObjectDeleter(WDFOBJECT Object); 14 | ~CWdfObjectDeleter(void); 15 | 16 | private: 17 | // The object to be deleted 18 | WDFOBJECT Object; 19 | 20 | public: 21 | /// 22 | /// Prevents this deleter from deleting the underlying request 23 | /// 24 | void Steal(void) 25 | { 26 | Object = nullptr; 27 | } 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /HidEmulator/WdfObjectLock.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "WdfObjectLock.h" 3 | 4 | CWdfObjectLock::CWdfObjectLock(WDFOBJECT obj): 5 | m_obj(obj) 6 | { 7 | // Acquire a lock on the object 8 | WdfObjectAcquireLock(m_obj); 9 | } 10 | 11 | CWdfObjectLock::~CWdfObjectLock(void) 12 | { 13 | // Logical inverse: Release the already-acquired lock 14 | WdfObjectReleaseLock(m_obj); 15 | } 16 | -------------------------------------------------------------------------------- /HidEmulator/WdfObjectLock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// 4 | /// RAII-style object lock 5 | /// 6 | class CWdfObjectLock 7 | { 8 | public: 9 | /// 10 | /// Locks the passed object, and saves it to be unlocked on destruction 11 | /// 12 | /// The object to be locked 13 | CWdfObjectLock(WDFOBJECT obj); 14 | ~CWdfObjectLock(void); 15 | 16 | WDFOBJECT m_obj; 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /HidEmulator/WdfRequestCompleter.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "WdfRequestCompleter.h" 3 | 4 | CWdfRequestCompleter::CWdfRequestCompleter(WDFREQUEST Request): 5 | Request(Request), 6 | Status(STATUS_SUCCESS) 7 | { 8 | } 9 | 10 | CWdfRequestCompleter::~CWdfRequestCompleter(void) 11 | { 12 | // Complete the packet unconditionally based on the current status value. 13 | WdfRequestComplete(Request, Status); 14 | } 15 | -------------------------------------------------------------------------------- /HidEmulator/WdfRequestCompleter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// 4 | /// Enables a request to be completed automatically at scope exit 5 | /// 6 | class CWdfRequestCompleter 7 | { 8 | public: 9 | CWdfRequestCompleter(WDFREQUEST Request); 10 | ~CWdfRequestCompleter(void); 11 | 12 | WDFREQUEST Request; 13 | NTSTATUS Status; 14 | 15 | /// 16 | /// Sets the status that the attached request should be completed with 17 | /// when this instance is destroyed 18 | /// 19 | /// The status to be assigned 20 | void SetStatus(NTSTATUS status) {Status = status;} 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /HidEmulator/WdfRequestRequeuer.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "WdfRequestRequeuer.h" 3 | 4 | CWdfRequestRequeuer::CWdfRequestRequeuer(WDFREQUEST Request, WDFQUEUE Queue): 5 | Request(Request), 6 | Queue(Queue) 7 | { 8 | } 9 | 10 | CWdfRequestRequeuer::~CWdfRequestRequeuer(void) 11 | { 12 | // Based on the status code (presumably of some other operation) we decide 13 | // what to do with our packet. Broadly, we only want to complete the packet 14 | // if the status was successful. Otherwise we put it into the queue, or if 15 | // the packet needs to go back to the queue it came from, we can just use 16 | // the requeue request. 17 | 18 | if(NT_SUCCESS(Status)) 19 | // Gets completed successfully 20 | WdfRequestComplete(Request, Status); 21 | else if(Queue) 22 | // Goes on to a new queue 23 | WdfRequestForwardToIoQueue(Request, Queue); 24 | else 25 | // Goes back to where it came from. 26 | WdfRequestRequeue(Request); 27 | } 28 | -------------------------------------------------------------------------------- /HidEmulator/WdfRequestRequeuer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// 4 | /// Enables automatic requeuing of a request to the specified queue under certain conditions. 5 | /// 6 | /// 7 | /// NT_STATUS(Success) -> Complete Request with a status value of Success 8 | /// otherwise -> Return Request to the specified queue, based on queueing behavior 9 | /// 10 | class CWdfRequestRequeuer 11 | { 12 | public: 13 | /// The request to be managed 14 | /// 15 | /// The queue to which should be returned, or nullptr if WdfRequestRequeue 16 | /// should be called instead 17 | /// 18 | CWdfRequestRequeuer(WDFREQUEST Request, WDFQUEUE Queue = nullptr); 19 | ~CWdfRequestRequeuer(void); 20 | 21 | private: 22 | // This is the request that will be queued 23 | WDFREQUEST Request; 24 | 25 | // This is the queue to which the request will be queued 26 | WDFQUEUE Queue; 27 | 28 | public: 29 | NTSTATUS Status; 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /HidEmulator/inf/amd64/HidEmulator.inf: -------------------------------------------------------------------------------- 1 | ; Copyright (c) 2012-2013 Leap Motion, Inc. All rights Reserved 2 | [Version] 3 | Signature="$WINDOWS NT$" 4 | Class=System 5 | ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318} 6 | Provider=%MSFT% 7 | DriverVer=07/15/2013,1.0.1.4 8 | CatalogFile=HidEmulator.cat 9 | 10 | [DestinationDirs] 11 | DefaultDestDir = 12 12 | 13 | [SourceDisksNames] 14 | 1 = %DiskId1%,,,"" 15 | 16 | [SourceDisksFiles] 17 | HidEmulator.sys = 1,, 18 | HidEmulatorKmdf.sys = 1,, 19 | 20 | ;***************************************** 21 | ; HidEmulator Install Section 22 | ;***************************************** 23 | 24 | [Manufacturer] 25 | %StdMfg%=Standard,NTamd64 26 | 27 | [Standard.NTamd64] 28 | ; HidEmulator fake device node pnp id 29 | %HidEmulator_Device.DeviceDesc%=HidEmulator_Device,HID\OcsEmulator 30 | 31 | [HidEmulator_Device.NT] 32 | CopyFiles=Drivers_Dir 33 | 34 | [HidEmulator_Device.NT.HW] 35 | AddReg=LowerFilter_AddReg 36 | 37 | [Drivers_Dir] 38 | HidEmulator.sys 39 | HidEmulatorKmdf.sys 40 | 41 | ;-------------- 42 | ; Kmdf is installed as a lower filter to the HidEmulator driver 43 | [LowerFilter_AddReg] 44 | HKR,,LowerFilters,0x00010000,HidEmulatorKmdf 45 | 46 | ;-------------- Service installation 47 | [HidEmulator_Device.NT.Services] 48 | AddService = HidEmulator,803,HidEmulator_Service_Inst ; SPSVCINST_TAGTOFRONT | SPSVCINST_ASSOCSERVICE | SPSVCSINST_STARTSERVICE 49 | AddService = HidEmulatorKmdf,0,HidEmulatorKmdf_Service_Inst 50 | 51 | ; -------------- HID Emulator driver service install sections 52 | [HidEmulator_Service_Inst] 53 | DisplayName = %HidEmulator.SVCDESC% 54 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 55 | StartType = 3 ; SERVICE_DEMAND_START 56 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 57 | ServiceBinary = %12%\HidEmulator.sys 58 | AddReg = HidEmulator_Service_Inst.Reg 59 | 60 | [HidEmulator_Service_Inst.Reg] 61 | HKR,,Tag,0x00010001,0x00000001 62 | HKR,,EventMessageFile,0x00000000,%12%\HidEmulator.sys 63 | HKR,,TypesSupported,0x00010001,7 64 | 65 | ; -------------- HID Emulator Kmdf driver service install sections 66 | [HidEmulatorKmdf_Service_Inst] 67 | DisplayName = %HidEmulatorKmdf.SVCDESC% 68 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 69 | StartType = 3 ; SERVICE_DEMAND_START 70 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 71 | ServiceBinary = %12%\HidEmulatorKmdf.sys 72 | AddReg = HidEmulatorKmdf_Service_Inst.Reg 73 | 74 | [HidEmulatorKmdf_Service_Inst.Reg] 75 | HKR,,Tag,0x00010001,0x00000001 76 | HKR,,EventMessageFile,0x00000000,%12%\HidEmulatorKmdf.sys 77 | HKR,,TypesSupported,0x00010001,7 78 | 79 | [Strings] 80 | MSFT = "Leap Motion, Inc." 81 | StdMfg = "Leap Motion, Inc." 82 | DiskId1 = "Leap Motion Installation Disk #1" 83 | HidEmulator_Device.DeviceDesc = "Leap Motion gesture emulation device driver" 84 | HidEmulator.SVCDESC = "HidEmulator Leap Motion Miniport" 85 | HidEmulatorKmdf.SVCDESC = "HidEmulatorKmdf Lower Filter" 86 | -------------------------------------------------------------------------------- /HidEmulator/inf/i386/HidEmulator.inf: -------------------------------------------------------------------------------- 1 | ; Copyright (c) 2012-2013 Leap Motion, Inc. All rights Reserved 2 | [Version] 3 | Signature="$WINDOWS NT$" 4 | Class=System 5 | ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318} 6 | Provider=%MSFT% 7 | DriverVer=07/15/2013,1.0.1.4 8 | CatalogFile=HidEmulator.cat 9 | 10 | [DestinationDirs] 11 | DefaultDestDir = 12 12 | 13 | [SourceDisksNames] 14 | 1 = %DiskId1%,,,"" 15 | 16 | [SourceDisksFiles] 17 | HidEmulator.sys = 1,, 18 | HidEmulatorKmdf.sys = 1,, 19 | 20 | ;***************************************** 21 | ; HidEmulator Install Section 22 | ;***************************************** 23 | 24 | [Manufacturer] 25 | %StdMfg%=Standard 26 | 27 | [Standard] 28 | ; HidEmulator fake device node pnp id 29 | %HidEmulator_Device.DeviceDesc%=HidEmulator_Device,HID\OcsEmulator 30 | 31 | [HidEmulator_Device.NT] 32 | CopyFiles=Drivers_Dir 33 | 34 | [HidEmulator_Device.NT.HW] 35 | AddReg=LowerFilter_AddReg 36 | 37 | [Drivers_Dir] 38 | HidEmulator.sys 39 | HidEmulatorKmdf.sys 40 | 41 | ;-------------- 42 | ; Kmdf is installed as a lower filter to the HidEmulator driver 43 | [LowerFilter_AddReg] 44 | HKR,,LowerFilters,0x00010000,HidEmulatorKmdf 45 | 46 | ;-------------- Service installation 47 | [HidEmulator_Device.NT.Services] 48 | AddService = HidEmulator,803,HidEmulator_Service_Inst ; SPSVCINST_TAGTOFRONT | SPSVCINST_ASSOCSERVICE | SPSVCSINST_STARTSERVICE 49 | AddService = HidEmulatorKmdf,0,HidEmulatorKmdf_Service_Inst 50 | 51 | ; -------------- HID Emulator driver service install sections 52 | [HidEmulator_Service_Inst] 53 | DisplayName = %HidEmulator.SVCDESC% 54 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 55 | StartType = 3 ; SERVICE_DEMAND_START 56 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 57 | ServiceBinary = %12%\HidEmulator.sys 58 | AddReg = HidEmulator_Service_Inst.Reg 59 | 60 | [HidEmulator_Service_Inst.Reg] 61 | HKR,,Tag,0x00010001,0x00000001 62 | HKR,,EventMessageFile,0x00000000,%12%\HidEmulator.sys 63 | HKR,,TypesSupported,0x00010001,7 64 | 65 | ; -------------- HID Emulator Kmdf driver service install sections 66 | [HidEmulatorKmdf_Service_Inst] 67 | DisplayName = %HidEmulatorKmdf.SVCDESC% 68 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 69 | StartType = 3 ; SERVICE_DEMAND_START 70 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 71 | ServiceBinary = %12%\HidEmulatorKmdf.sys 72 | AddReg = HidEmulatorKmdf_Service_Inst.Reg 73 | 74 | [HidEmulatorKmdf_Service_Inst.Reg] 75 | HKR,,Tag,0x00010001,0x00000001 76 | HKR,,EventMessageFile,0x00000000,%12%\HidEmulatorKmdf.sys 77 | HKR,,TypesSupported,0x00010001,7 78 | 79 | [Strings] 80 | MSFT = "Leap Motion, Inc." 81 | StdMfg = "Leap Motion, Inc." 82 | DiskId1 = "Leap Motion Installation Disk #1" 83 | HidEmulator_Device.DeviceDesc = "Leap Motion gesture emulation device driver" 84 | HidEmulator.SVCDESC = "HidEmulator Leap Motion Miniport" 85 | HidEmulatorKmdf.SVCDESC = "HidEmulatorKmdf Lower Filter" 86 | -------------------------------------------------------------------------------- /HidEmulator/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | // Standard destructor. Not used, and so, not implemented. Should assert in debug mode. 4 | void __cdecl operator delete(void* pMemory) 5 | { 6 | ASSERT(false); 7 | } -------------------------------------------------------------------------------- /HidEmulator/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define KMDF_VERSION_MAJOR 1 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | // WDF stuff: 10 | #include 11 | #include "usbdi.h" 12 | #include "usbdlib.h" 13 | #include 14 | 15 | extern "C" { 16 | #include 17 | } 18 | 19 | #if DBG 20 | #define OcsDebugPrint(msg, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, msg "\n", __VA_ARGS__) 21 | #else 22 | #define OcsDebugPrint(msg, ...) 23 | #endif 24 | 25 | // Marker definitions, defined to nothing here to prevent compilation malfunctions 26 | #define __INCLUDE_FROM_USB_DRIVER 27 | #define __INCLUDE_FROM_HID_DRIVER 28 | #define USB_CAN_BE_DEVICE 29 | 30 | #define ATTR_PACKED 31 | #define ATTR_CONST 32 | #define ATTR_NON_NULL_PTR_ARG(x) 33 | 34 | #define GET_NEXT_DEVICE_OBJECT(DO) \ 35 | (((PHID_DEVICE_EXTENSION)(DO)->DeviceExtension)->NextDeviceObject) 36 | 37 | // Vendor identifier (must be requested) 38 | #define OEM_VENDOR_ID 'SUCO' 39 | 40 | // Some generic typdefs, for use by the HID headers 41 | typedef char int8_t; 42 | typedef BYTE uint8_t; 43 | typedef WORD uint16_t; 44 | typedef DWORD uint32_t; 45 | 46 | // Forward declaration of placement new 47 | inline void* operator new(size_t, void* p) {return p;} 48 | 49 | // Internal headers: 50 | #include "../Globals/Interface.h" 51 | -------------------------------------------------------------------------------- /Installer/DriverPackage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "DriverPackage.h" 5 | 6 | DWORD DoInstallPackage(const wchar_t* infPath, BOOL& needReboot) { 7 | // Use DifX to install drivers on the new devnode: 8 | return DriverPackageInstallW( 9 | infPath, 10 | DRIVER_PACKAGE_ONLY_IF_DEVICE_PRESENT, 11 | nullptr, 12 | &needReboot 13 | ); 14 | } 15 | 16 | DWORD DoUninstallPackage(const wchar_t* infPath, BOOL& needReboot) { 17 | DWORD err = DriverPackageUninstallW( 18 | infPath, 19 | DRIVER_PACKAGE_DELETE_FILES, 20 | nullptr, 21 | &needReboot 22 | ); 23 | 24 | switch(err) { 25 | case ERROR_DRIVER_PACKAGE_NOT_IN_STORE: 26 | // That's OK, it wasn't installed so it cannot be removed. No problem. 27 | break; 28 | default: 29 | return err; 30 | } 31 | return 0; 32 | } -------------------------------------------------------------------------------- /Installer/DriverPackage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | DWORD DoInstallPackage(const wchar_t* infPath, BOOL& needReboot); 4 | 5 | DWORD DoUninstallPackage(const wchar_t* infPath, BOOL& needReboot); -------------------------------------------------------------------------------- /Installer/Installer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Installer.h" 3 | #include "InstallerBase.h" 4 | #include "LastErrorPreserver.h" 5 | 6 | enum eHidStatus { 7 | }; 8 | 9 | eHidStatus PerformOperation(const wchar_t* pInfPath, void (CInstallerBase::*pMember)()) 10 | { 11 | // This class is declared first to ensure that its destructor is called last 12 | CLastErrorPreserver gle; 13 | 14 | try { 15 | // Installer base initialization: 16 | CInstallerBase base(pInfPath); 17 | 18 | // Perform the operation proper 19 | (base.*pMember)(); 20 | 21 | // If restart is required we'll return here to indicate that: 22 | if(base.IsRestartRequired()) 23 | throw eHidInstRestartRequired; 24 | } catch(eHidStatus rs) { 25 | // Done, capture the last error so it's restored after the CInstallerBase destructor 26 | // call is made and then return here. 27 | return gle.CaptureLastError(), rs; 28 | } 29 | 30 | return (eHidStatus)0; 31 | } 32 | 33 | eHidStatus OcuHidInstall(const wchar_t* pInfPath) 34 | { 35 | return PerformOperation(pInfPath, &CInstallerBase::Install); 36 | } 37 | 38 | eHidStatus OcuHidUpdate(const wchar_t* pInfPath) 39 | { 40 | return PerformOperation(pInfPath, &CInstallerBase::Update); 41 | } 42 | 43 | eHidStatus OcuHidUninstall(const wchar_t* pInfPath) 44 | { 45 | return PerformOperation(pInfPath, &CInstallerBase::Uninstall); 46 | } 47 | -------------------------------------------------------------------------------- /Installer/Installer.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | EXPORTS 3 | OcuHidInstall 4 | OcuHidUpdate 5 | OcuHidUninstall -------------------------------------------------------------------------------- /Installer/Installer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "InstallerCodes.h" 3 | 4 | struct OcuHidInfo { 5 | DWORD version; 6 | }; 7 | 8 | /// 9 | /// Installs the HidEmulator nondevice driver 10 | /// 11 | /// The path to the HidEmulator INF file 12 | /// A HID status value 13 | extern "C" eHidStatus OcuHidInstall(const wchar_t* pInfPath); 14 | 15 | /// 16 | /// Updates the HidEmulator nondevice driver 17 | /// 18 | /// The path to the HidEmulator INF file 19 | /// A HID status value 20 | extern "C" eHidStatus OcuHidUpdate(const wchar_t* pInfPath); 21 | 22 | /// 23 | /// Uninstalls the HidEmulator nondevice driver 24 | /// 25 | /// The path to the HidEmulator INF file 26 | /// A HID status value 27 | extern "C" eHidStatus OcuHidUninstall(const wchar_t* pInfPath); -------------------------------------------------------------------------------- /Installer/Installer.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 | 20 | Resource Files 21 | 22 | 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | Header Files 59 | 60 | 61 | Header Files 62 | 63 | 64 | Header Files 65 | 66 | 67 | 68 | 69 | Source Files 70 | 71 | 72 | Source Files 73 | 74 | 75 | Source Files 76 | 77 | 78 | Source Files 79 | 80 | 81 | Source Files 82 | 83 | 84 | Source Files 85 | 86 | 87 | Source Files 88 | 89 | 90 | Source Files 91 | 92 | 93 | Source Files 94 | 95 | 96 | Source Files 97 | 98 | 99 | 100 | 101 | Resource Files 102 | 103 | 104 | 105 | 106 | Resource Files 107 | 108 | 109 | -------------------------------------------------------------------------------- /Installer/InstallerBase.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "InstallerBase.h" 3 | #include "DriverPackage.h" 4 | #include "InstanceEnumerator.h" 5 | #include "NonPnpDevnode.h" 6 | #include "ServiceControlManager.h" 7 | #include "SystemInfoClass.h" 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | CInstallerBase::CInstallerBase(const wchar_t* pInfPath): 14 | m_infPath(pInfPath ? pInfPath : L"HidEmulator.inf"), 15 | m_bMustCopy(false) 16 | { 17 | // Convert the INF path to an absolute path, if needed: 18 | if(PathIsRelative(m_infPath.c_str())) 19 | { 20 | wchar_t relToWhat[MAX_PATH + 1]; 21 | if(!GetModuleFileNameW(nullptr, relToWhat, NUMBER_OF(relToWhat))) 22 | // Assume that we must copy. 23 | { 24 | m_bMustCopy = true; 25 | return; 26 | } 27 | 28 | // Extract the name portion of the executable path: 29 | wchar_t* pName = PathFindFileNameW(relToWhat); 30 | 31 | // Kill the filename part if it is set: 32 | size_t len; 33 | if(pName != relToWhat) 34 | len = pName - relToWhat; 35 | else 36 | // Otherwise, use the CWD as the path name: 37 | { 38 | // Get the current working directory 39 | GetCurrentDirectory(MAX_PATH, relToWhat); 40 | 41 | // Get the length of the working directory 42 | len = wcslen(relToWhat); 43 | 44 | // Add a trailing backslash 45 | relToWhat[len++] = '\\'; 46 | } 47 | 48 | // Null-terminate 49 | relToWhat[len] = 0; 50 | 51 | // Prepend the inf path with the relative location: 52 | m_infPath.insert(m_infPath.begin(), relToWhat, relToWhat + len); 53 | } 54 | 55 | // Determine if the supplied path is on a network drive. PNP cannot install drivers 56 | // from networked locations, so copying to a local device becomes necessary. 57 | m_bMustCopy = !!PathIsNetworkPath(m_infPath.c_str()); 58 | } 59 | 60 | CInstallerBase::~CInstallerBase(void) 61 | { 62 | } 63 | 64 | void CInstallerBase::Install(void) 65 | { 66 | // Destroy all existing devices. This triggers an unload of our driver and enables us to tinker 67 | // safely with the device configuration. 68 | { 69 | InstanceEnumerator ie; 70 | while(ie.Next()) 71 | ie.DestroyCurrent(); 72 | 73 | if(ie.IsRestartRequired()) 74 | RequireRestart(); 75 | } 76 | 77 | // The SYSTEM device class is where the device will be installed 78 | std::shared_ptr hInfo(new SystemInfoClass); 79 | 80 | // We next create an empty devnode where the ocuhid legacy device may be attached. 81 | // This empty devnode will then be characterized with a PNPID (by us) and then we let PNP 82 | // find and load the driver from there. This is basically what the add/remove hardware wizard 83 | // does when you add legacy hardware. 84 | NonPnpDevnode devNode(hInfo); 85 | 86 | // Perform the actual installation: 87 | BOOL needReboot; 88 | DWORD rs = DoInstallPackage(m_infPath.c_str(), needReboot); 89 | switch(rs) 90 | { 91 | case ERROR_NO_SUCH_DEVINST: 92 | break; 93 | default: 94 | if(FAILED(rs)) 95 | { 96 | SetLastError(rs); 97 | throw eHidInstDriverPackageRejected; 98 | } 99 | } 100 | 101 | // Now we can release the devnode: 102 | devNode.Release(); 103 | 104 | // Now we'll select the device: 105 | if(needReboot) 106 | RequireRestart(); 107 | } 108 | 109 | void CInstallerBase::Update(void) 110 | { 111 | InstanceEnumerator ie; 112 | if(!ie.Next()) 113 | throw eHidInstNoDevsToUpdate; 114 | 115 | // Now we just perform an installation: 116 | Install(); 117 | } 118 | 119 | void CInstallerBase::Uninstall(void) 120 | { 121 | // Removal of all detected devices: 122 | { 123 | InstanceEnumerator ie; 124 | while(ie.Next()) 125 | ie.DestroyCurrent(); 126 | if(ie.IsRestartRequired()) 127 | RequireRestart(); 128 | } 129 | 130 | { 131 | // Service destruction: 132 | ServiceControlManager scm; 133 | 134 | // Now the services proper may be deleted--we don't care if this operation fails: 135 | try { 136 | scm.DeleteOcuHidService(L"HidEmulator"); 137 | } catch(...) {} 138 | 139 | try { 140 | scm.DeleteOcuHidService(L"HidEmulatorKmdf"); 141 | } catch(...) {} 142 | 143 | // Propagate the restart flag out: 144 | if(scm.IsRestartRequired()) 145 | RequireRestart(); 146 | } 147 | 148 | // Package uninstallation: 149 | BOOL needReboot; 150 | DWORD rs = DoUninstallPackage(m_infPath.c_str(), needReboot); 151 | if(FAILED(rs)) 152 | { 153 | SetLastError(rs); 154 | throw eHidInstFailedToRemovePackage; 155 | } 156 | 157 | if(needReboot) 158 | RequireRestart(); 159 | } 160 | -------------------------------------------------------------------------------- /Installer/InstallerBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "RestartRequiredTracker.h" 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | using namespace std::tr1; 8 | 9 | enum eHidStatus; 10 | 11 | class CInstallerBase: 12 | public RestartRequiredTracker 13 | { 14 | public: 15 | /// 16 | /// Initialization for the initializer base 17 | /// 18 | /// The path to the HidEmulator INF file. 19 | CInstallerBase(const wchar_t* pInfPath); 20 | ~CInstallerBase(void); 21 | 22 | private: 23 | // Set if the INF path is in a directory that PNP cannot install from, such as a network drive. 24 | bool m_bMustCopy; 25 | 26 | // INF path: 27 | wstring m_infPath; 28 | 29 | private: 30 | /// 31 | /// Utility routine for deleting services 32 | /// 33 | void DeleteOcuHidService(const wchar_t* lpwcsName); 34 | 35 | public: 36 | // Mutator methods: 37 | void SetInfPath(const wchar_t* pwcsInfPath); 38 | 39 | /// 40 | /// Obtains the version number of the currently installed HID emulator, or zero if one could not be found 41 | /// 42 | DWORD GetDriverVersion(void); 43 | 44 | /// 45 | /// Installs the HidEmulator nondevice driver 46 | /// 47 | void Install(void); 48 | 49 | /// 50 | /// Updates the HidEmulator nondevice driver 51 | /// 52 | void Update(void); 53 | 54 | /// 55 | /// Uninstalls the HidEmulator nondevice driver 56 | /// 57 | void Uninstall(void); 58 | }; 59 | 60 | -------------------------------------------------------------------------------- /Installer/InstallerCodes.mc: -------------------------------------------------------------------------------- 1 | ;#pragma once 2 | ;enum eHidStatus; 3 | 4 | MessageIdTypedef=eHidStatus 5 | 6 | SeverityNames=( 7 | Success = 0x0 : OCUHID_STATUS_SUCCESS 8 | Informational = 0x1 : OCUHID_STATUS_INFORMATION 9 | Warning = 0x2 : OCUHID_STATUS_WARNING 10 | Error = 0x3 : OCUHID_STATUS_ERROR 11 | ) 12 | 13 | FacilityNames=( 14 | HidInst = 0x1 15 | ) 16 | 17 | MessageId=0 18 | Severity=Success 19 | Facility=HidInst 20 | SymbolicName=eHidInstSuccess 21 | Language=English 22 | Installation operation was successful 23 | . 24 | 25 | 26 | MessageId=0 27 | Severity=Informational 28 | Facility=HidInst 29 | SymbolicName=eHidInstRestartRequired 30 | Language=English 31 | Installation operation was successful, but a reboot will be required 32 | . 33 | 34 | MessageId= 35 | SymbolicName=eHidInstNoDevsToUpdate 36 | Language=English 37 | The update operation did not update anything because no OcuHid devices were identified 38 | . 39 | 40 | 41 | MessageId=0 42 | Severity=Warning 43 | SymbolicName=eHidInstServiceConfQueryFail 44 | Language=English 45 | Failed to query the service configuration in order to determine the binaries that must be deleted. The service was removed, but its binaries 46 | may still be present on the system. 47 | . 48 | 49 | 50 | MessageId=0 51 | Severity=Error 52 | Facility=HidInst 53 | SymbolicName=eHidInstRequiresElevation 54 | Language=English 55 | Installation, upgrade, and uninstallation operations all require Administrator privileges to succeed 56 | . 57 | 58 | MessageId= 59 | SymbolicName=eHidInstNewdevNotFound 60 | Language=English 61 | Could not find and/or load newdev.dll 62 | . 63 | 64 | MessageId= 65 | SymbolicName=eHidInstNewdevEntrypointNotFound 66 | Language=English 67 | Could not find UpdateDriverForPlugAndPlayDevicesW in newdev.dll 68 | . 69 | 70 | MessageId= 71 | SymbolicName=eHidInstSysClassNotFound 72 | Language=English 73 | The built-in SYSTEM device class could not be loaded with a call to SetupDiCreateDeviceInfoListExW 74 | . 75 | 76 | MessageId= 77 | SymbolicName=eHidInstDevCreateFail 78 | Language=English 79 | Failed to create an empty device node 80 | . 81 | 82 | MessageId= 83 | SymbolicName=eHidInstDevIDAssignFail 84 | Language=English 85 | Failed to assign the hardware ID to the null devnode created as part of the install process 86 | . 87 | 88 | MessageId= 89 | SymbolicName=eHidInstUserCancel 90 | Language=English 91 | Failed to install the device due to a user cancellation 92 | . 93 | 94 | MessageId= 95 | SymbolicName=eHidInstSCManOpenFailed 96 | Language=English 97 | Failed to open the service control manager for administrative access 98 | . 99 | 100 | MessageId= 101 | SymbolicName=eHidInstServiceOpenFailed 102 | Language=English 103 | Failed to open the OcuHid service itself for deletion 104 | . 105 | 106 | MessageId= 107 | SymbolicName=eHidInstServiceDeleteFailed 108 | Language=English 109 | Failed to delete the service, or mark it for deletion at next reboot 110 | . 111 | 112 | MessageId= 113 | SymbolicName=eHidInstTempPathCreateFail 114 | Language=English 115 | Failed to create a temporary path for installer files, you might try copying these files manually to a 116 | local directory and running the install operation again. 117 | . 118 | 119 | MessageId= 120 | SymbolicName=eHidInstCompatDriverFindFail 121 | Language=English 122 | Failed to find a compatible driver for a null device node. 123 | . 124 | 125 | MessageId= 126 | SymbolicName=eHidInstDriverSelectFail 127 | Language=English 128 | Failed to set the selected driver after the install process was completed 129 | . 130 | 131 | MessageId= 132 | SymbolicName=eHidInstInfoListBuildFail 133 | Language=English 134 | Failed to build a list of compatible drivers for the created null device node. 135 | . 136 | 137 | MessageId= 138 | SymbolicName=eHidInstCopyOEMFail 139 | Language=English 140 | Failed to copy the INF into the local machine's INF repository, the INF file appears 141 | to be missing. 142 | . 143 | 144 | MessageId= 145 | SymbolicName=eHidInstINFDependencyMissing 146 | Language=English 147 | The INF file appears to be present, but one or more of its dependencies is missing. 148 | Cannot copy the INF unless all of its dependencies are present. Check the inf's CAT 149 | file to verify that all files are present and available. 150 | . 151 | 152 | MessageId= 153 | SymbolicName=eHidInstInstallSelectionFailed 154 | Language=English 155 | Failed to install a driver, even after successfully indicating the device where the 156 | driver was to be placed and the driver to be placed on that device. This may indicate 157 | that the driver is not actually compatible with the hardware it's being installed on. 158 | . 159 | 160 | MessageId= 161 | SymbolicName=eHidInstUpdateFailFromNetwork 162 | Language=English 163 | Cannot install the specified driver; it is on a network share. Move the driver to 164 | a local directory and try again. 165 | . 166 | 167 | MessageId= 168 | SymbolicName=eHidInstFailedToSelectDevice 169 | Language=English 170 | Failed to select a located device driver to a created HidEmulator devnode 171 | . 172 | 173 | MessageId= 174 | SymbolicName=eHidInstDeviceRegistrationFailed 175 | Language=English 176 | Failed to register a device after successfully creating it 177 | . 178 | 179 | MessageId= 180 | SymbolicName=eHidInstDriverPackageRejected 181 | Language=English 182 | The DIFxAPI rejected our request to install the driver package. Manual installation will 183 | be necessary. 184 | . 185 | 186 | 187 | MessageId= 188 | SymbolicName=eHidInstFailedToRemovePackage 189 | Language=English 190 | The DIFxAPI refused to uninstall the driver package 191 | . 192 | -------------------------------------------------------------------------------- /Installer/InstanceEnumerator.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "InstanceEnumerator.h" 3 | 4 | InstanceEnumerator::InstanceEnumerator(std::shared_ptr hInfo): 5 | m_hInfo(hInfo), 6 | m_i(0) 7 | { 8 | // Set up the info structure that we will use to query for information 9 | memset(&m_info, 0, sizeof(m_info)); 10 | m_info.cbSize = sizeof(m_info); 11 | } 12 | 13 | InstanceEnumerator::~InstanceEnumerator(void) 14 | { 15 | } 16 | 17 | bool InstanceEnumerator::Next(void) { 18 | // Enumerate to the devnode matching our device ID: 19 | while(SetupDiEnumDeviceInfo(*m_hInfo, m_i++, &m_info)) 20 | { 21 | wchar_t buf[MAX_PATH]; 22 | DWORD dwType = REG_SZ; 23 | DWORD reqSize; 24 | 25 | // This is a routine that gets a requested device property. The device 26 | // property we're interested in for this call is the hardware identifier, 27 | // because we'd like to match the hardware identifier to the hardware ID 28 | // that the Hid emulator uses 29 | if(!SetupDiGetDeviceRegistryPropertyW( 30 | *m_hInfo, 31 | &m_info, 32 | SPDRP_HARDWAREID, 33 | &dwType, 34 | (LPBYTE)buf, 35 | sizeof(buf), 36 | &reqSize 37 | ) 38 | ) 39 | // Failed to get this HWID, try the next one. 40 | continue; 41 | 42 | if(!wcscmp(buf, gc_pnpID)) 43 | return true; 44 | } 45 | return false; 46 | } 47 | 48 | void InstanceEnumerator::DestroyCurrent(void) { 49 | SetupDiCallClassInstaller(DIF_REMOVE, *this, &Current()); 50 | 51 | // Do we need to restart now? 52 | SP_DEVINSTALL_PARAMS params; 53 | params.cbSize = sizeof(params); 54 | SetupDiGetDeviceInstallParams(*this, &Current(), ¶ms); 55 | 56 | if(params.Flags & (DI_NEEDREBOOT | DI_NEEDRESTART)) 57 | RequireRestart(); 58 | } -------------------------------------------------------------------------------- /Installer/InstanceEnumerator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "RestartRequiredTracker.h" 4 | #include "SystemInfoClass.h" 5 | 6 | class InstanceEnumerator: 7 | public RestartRequiredTracker 8 | { 9 | public: 10 | InstanceEnumerator(std::shared_ptr hInfo = std::shared_ptr(new SystemInfoClass(L"root\\system"))); 11 | ~InstanceEnumerator(void); 12 | 13 | private: 14 | // Infoclass, used during enumeration 15 | std::shared_ptr m_hInfo; 16 | 17 | // The index, and the last-recovered SP_DEVINFO_DATA 18 | DWORD m_i; 19 | SP_DEVINFO_DATA m_info; 20 | 21 | public: 22 | // Accessor methods: 23 | SP_DEVINFO_DATA& Current(void) {return m_info;} 24 | 25 | /// 26 | /// Finds the next matching Leap ID 27 | /// 28 | bool Next(void); 29 | 30 | /// 31 | /// Destroyes the currently enumerated device 32 | /// 33 | void DestroyCurrent(void); 34 | 35 | operator std::shared_ptr(void) const {return m_hInfo;} 36 | operator HDEVINFO(void) const {return *m_hInfo;} 37 | }; 38 | 39 | -------------------------------------------------------------------------------- /Installer/LastErrorPreserver.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "LastErrorPreserver.h" 3 | 4 | CLastErrorPreserver::~CLastErrorPreserver(void) 5 | { 6 | // Restore the last error code 7 | SetLastError(m_lastError); 8 | } 9 | -------------------------------------------------------------------------------- /Installer/LastErrorPreserver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// 4 | /// This ensures that the last error recovered in the constructor call 5 | /// is preserved when the function exit. This is imporant for functions 6 | /// that must preserve error information, but must also run cleanup logic 7 | /// that may change the thread error code. 8 | /// 9 | class CLastErrorPreserver 10 | { 11 | public: 12 | ~CLastErrorPreserver(void); 13 | 14 | private: 15 | DWORD m_lastError; 16 | 17 | public: 18 | void CaptureLastError(void) 19 | { 20 | m_lastError = GetLastError(); 21 | } 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /Installer/NonPnpDevnode.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "NonPnpDevnode.h" 3 | #include "SystemInfoClass.h" 4 | 5 | NonPnpDevnode::NonPnpDevnode(void): 6 | m_hInfo(nullptr), 7 | released(false) 8 | { 9 | } 10 | 11 | NonPnpDevnode::NonPnpDevnode(std::shared_ptr hInfo): 12 | m_hInfo(hInfo), 13 | released(false) 14 | { 15 | memset((PSP_DEVINFO_DATA)this, 0, sizeof(SP_DEVINFO_DATA)); 16 | cbSize = sizeof(SP_DEVINFO_DATA); 17 | 18 | // Create an infoset to hold our single device: 19 | if(!SetupDiCreateDeviceInfoW(*hInfo, L"SYSTEM", &GUID_DEVCLASS_SYSTEM, nullptr, nullptr, DICD_GENERATE_ID, this)) 20 | throw eHidInstDevCreateFail; 21 | 22 | // Here's where the HWID is assigned. This is how PNP knows what to attach to the newly created devnode. 23 | if(!SetupDiSetDeviceRegistryPropertyW(*m_hInfo, this, SPDRP_HARDWAREID, (LPCBYTE)gc_pnpID, gc_pnpIDLen)) 24 | throw eHidInstDevIDAssignFail; 25 | 26 | // Now, we need to let PNP know that this is a device, so that it will actually try to find drivers 27 | if(!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, *m_hInfo, this)) 28 | throw eHidInstDeviceRegistrationFailed; 29 | } 30 | 31 | NonPnpDevnode::NonPnpDevnode(std::shared_ptr hInfo, const SP_DEVINFO_DATA& data): 32 | SP_DEVINFO_DATA(data), 33 | m_hInfo(hInfo), 34 | released(false) 35 | { 36 | } 37 | 38 | 39 | NonPnpDevnode::~NonPnpDevnode(void) 40 | { 41 | if(!released) 42 | SetupDiCallClassInstaller(DIF_REMOVE, *m_hInfo, this); 43 | } 44 | 45 | void NonPnpDevnode::Associate(void) { 46 | // Construct a set of supported drivers. This list will include the driver that we installed earlier with 47 | // the earlier call to SetupCopyOEMInf. 48 | if(!SetupDiBuildDriverInfoList(*m_hInfo, this, SPDIT_COMPATDRIVER)) 49 | throw eHidInstInfoListBuildFail; 50 | 51 | // Arbitrarily select the first driver. There really should be only one driver anyway 52 | SP_DRVINFO_DATA driverInfo; 53 | memset(&driverInfo, 0, sizeof(driverInfo)); 54 | driverInfo.cbSize = sizeof(driverInfo); 55 | 56 | DWORD i = 0; 57 | for(; SetupDiEnumDriverInfo(*m_hInfo, this, SPDIT_COMPATDRIVER, i, &driverInfo); i++) { 58 | } 59 | 60 | if(!i) 61 | throw eHidInstCompatDriverFindFail; 62 | 63 | // Assign the selected driver to this device. 64 | if(!SetupDiSetSelectedDriver(*m_hInfo, this, &driverInfo)) 65 | throw eHidInstDriverSelectFail; 66 | 67 | DWORD bReboot = false; 68 | 69 | // Now, even though we have been operating on devInfo for most of this function, we still need 70 | // to indicate to the SetupAPI that we want to call some class installers on this device by making 71 | // this call. That's what this call does--it tells SetupAPI about our intent. 72 | if(!SetupDiSetSelectedDevice(*m_hInfo, this)) 73 | throw eHidInstFailedToSelectDevice; 74 | } -------------------------------------------------------------------------------- /Installer/NonPnpDevnode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class SystemInfoClassBase; 5 | 6 | class NonPnpDevnode: 7 | public SP_DEVINFO_DATA 8 | { 9 | public: 10 | NonPnpDevnode(void); 11 | NonPnpDevnode(std::shared_ptr hInfo); 12 | NonPnpDevnode(std::shared_ptr hInfo, const SP_DEVINFO_DATA& data); 13 | ~NonPnpDevnode(void); 14 | 15 | private: 16 | std::shared_ptr m_hInfo; 17 | bool released; 18 | 19 | public: 20 | /// 21 | /// Attempts to associate this non-PNP DevNode with the HidEmulator device driver 22 | /// 23 | void Associate(void); 24 | 25 | /// 26 | /// Prevents the destructor from attempting to delete this devnode 27 | /// 28 | void Release(void) { 29 | released = true; 30 | } 31 | 32 | void operator=(NonPnpDevnode&& rhs) { 33 | *(PSP_DEVINFO_DATA)this = rhs; 34 | m_hInfo = rhs.m_hInfo; 35 | released = rhs.released; 36 | rhs.released = true; 37 | } 38 | }; 39 | 40 | -------------------------------------------------------------------------------- /Installer/PreprocFlags.h: -------------------------------------------------------------------------------- 1 | // This contains preprocessor flags that may be used to control how installation 2 | // operations perform. 3 | -------------------------------------------------------------------------------- /Installer/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : InstallerLib Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this InstallerLib library project for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your InstallerLib application. 9 | 10 | 11 | InstallerLib.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | InstallerLib.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | 25 | ///////////////////////////////////////////////////////////////////////////// 26 | 27 | StdAfx.h, StdAfx.cpp 28 | These files are used to build a precompiled header (PCH) file 29 | named InstallerLib.pch and a precompiled types file named StdAfx.obj. 30 | 31 | ///////////////////////////////////////////////////////////////////////////// 32 | Other notes: 33 | 34 | AppWizard uses "TODO:" comments to indicate parts of the source code you 35 | should add to or customize. 36 | 37 | ///////////////////////////////////////////////////////////////////////////// 38 | -------------------------------------------------------------------------------- /Installer/RestartRequiredTracker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class RestartRequiredTracker 3 | { 4 | public: 5 | RestartRequiredTracker(void): 6 | m_restartRequired(false) 7 | {} 8 | 9 | private: 10 | bool m_restartRequired; 11 | 12 | protected: 13 | void RequireRestart(void) { 14 | m_restartRequired = true; 15 | } 16 | 17 | public: 18 | // Accessor methods: 19 | bool IsRestartRequired(void) const {return m_restartRequired;} 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /Installer/ServiceControlManager.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ServiceControlManager.h" 3 | #include "ServiceHandle.h" 4 | #include 5 | 6 | using namespace std; 7 | 8 | ServiceControlManager::ServiceControlManager(void): 9 | m_hMngr(OpenSCManagerW(nullptr, SERVICES_ACTIVE_DATABASEW, SC_MANAGER_ALL_ACCESS)) 10 | { 11 | if(!m_hMngr) 12 | throw eHidInstSCManOpenFailed; 13 | } 14 | 15 | ServiceControlManager::~ServiceControlManager(void) 16 | { 17 | if(m_hMngr) 18 | CloseServiceHandle(m_hMngr); 19 | } 20 | 21 | void ServiceControlManager::DeleteOcuHidService(const wchar_t* lpwcsName) 22 | { 23 | vector configBuf; 24 | QUERY_SERVICE_CONFIGW config; 25 | { 26 | // Open a handle to the HidEmulator service proper. 27 | ServiceHandle hSrv(*this, lpwcsName); 28 | 29 | // Determine how many bytes will be needed to our service binaries. 30 | DWORD cbNeeded; 31 | QueryServiceConfigW(hSrv, NULL, 0, &cbNeeded); 32 | if(!cbNeeded) 33 | throw eHidInstServiceConfQueryFail; 34 | 35 | // Path length acquired, query the service configuration, which will get us 36 | // the path to service binaries. 37 | configBuf.resize(cbNeeded + 1); 38 | if( 39 | cbNeeded && 40 | !QueryServiceConfigW( 41 | hSrv, 42 | (LPQUERY_SERVICE_CONFIG)&configBuf[0], 43 | cbNeeded, 44 | &cbNeeded 45 | ) 46 | ) 47 | throw eHidInstServiceConfQueryFail; 48 | config = (QUERY_SERVICE_CONFIGW&)configBuf[0]; 49 | 50 | // Attempt to delete the service: 51 | if(!DeleteService(hSrv)) 52 | switch(GetLastError()) 53 | { 54 | case ERROR_SERVICE_MARKED_FOR_DELETE: 55 | // Service already marked for deletion, nothing further required at this point. 56 | break; 57 | default: 58 | throw eHidInstServiceDeleteFailed; 59 | } 60 | } 61 | 62 | // Delete the service binaries from the system: 63 | { 64 | TCHAR wcSysRoot[MAX_PATH]; 65 | TCHAR wcFullPath[MAX_PATH]; 66 | 67 | // Recover system root 68 | GetWindowsDirectoryW(wcSysRoot, MAX_PATH); 69 | 70 | // Create the full path: 71 | swprintf_s(wcFullPath, ARRAYSIZE(wcFullPath), L"%s\\%s", wcSysRoot, config.lpBinaryPathName); 72 | 73 | // Verify that the full path exists before we try to delete it. 74 | if(PathFileExistsW(wcFullPath)) 75 | // Delete the file now if we can 76 | if(!DeleteFileW(wcFullPath)) 77 | // File in use. Delay deletion until reboot. 78 | MoveFileEx(wcFullPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); 79 | } 80 | } -------------------------------------------------------------------------------- /Installer/ServiceControlManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "RestartRequiredTracker.h" 3 | 4 | class ServiceControlManager: 5 | public RestartRequiredTracker 6 | { 7 | public: 8 | ServiceControlManager(void); 9 | ~ServiceControlManager(void); 10 | 11 | private: 12 | // Service manager handle: 13 | SC_HANDLE m_hMngr; 14 | 15 | public: 16 | /// 17 | /// Deletes a HIDEmulator driver service 18 | /// 19 | /// The driver service name 20 | void DeleteOcuHidService(const wchar_t* lpwcsName); 21 | 22 | operator SC_HANDLE(void) const {return m_hMngr;} 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /Installer/ServiceHandle.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ServiceHandle.h" 3 | #include "ServiceControlManager.h" 4 | 5 | ServiceHandle::ServiceHandle(ServiceControlManager& scm, const wchar_t* name): 6 | m_hSrv(OpenServiceW(scm, name, GENERIC_ALL)) 7 | { 8 | if(!m_hSrv) 9 | throw eHidInstServiceOpenFailed; 10 | } 11 | 12 | ServiceHandle::~ServiceHandle(void) 13 | { 14 | if(m_hSrv) 15 | CloseServiceHandle(m_hSrv); 16 | } 17 | -------------------------------------------------------------------------------- /Installer/ServiceHandle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class ServiceControlManager; 4 | 5 | class ServiceHandle 6 | { 7 | public: 8 | ServiceHandle(ServiceControlManager& scm, const wchar_t* name); 9 | ~ServiceHandle(void); 10 | 11 | private: 12 | SC_HANDLE m_hSrv; 13 | 14 | public: 15 | operator SC_HANDLE(void) const {return m_hSrv;} 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /Installer/SystemInfoClass.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "SystemInfoClass.h" 3 | 4 | SystemInfoClassBase::SystemInfoClassBase(void): 5 | m_hInfo(INVALID_HANDLE_VALUE) 6 | { 7 | } 8 | 9 | SystemInfoClassBase::~SystemInfoClassBase(void) { 10 | if(m_hInfo != INVALID_HANDLE_VALUE) 11 | SetupDiDestroyDeviceInfoList(m_hInfo); 12 | } -------------------------------------------------------------------------------- /Installer/SystemInfoClass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class __declspec(uuid("4d36e97d-e325-11ce-bfc1-08002be10318")) SystemSetupClass; 4 | class __declspec(uuid("88bae032-5a81-49f0-bc3d-a4ff138216d6")) UsbSetupClass; 5 | 6 | class SystemInfoClassBase { 7 | protected: 8 | SystemInfoClassBase(void); 9 | 10 | public: 11 | virtual ~SystemInfoClassBase(void); 12 | 13 | protected: 14 | HDEVINFO m_hInfo; 15 | 16 | public: 17 | operator HDEVINFO(void) const {return m_hInfo;} 18 | }; 19 | 20 | template 21 | class SystemInfoClass: 22 | public SystemInfoClassBase 23 | { 24 | public: 25 | /// 26 | /// Creates an empty infoclass based on the SYSTEM infoclass 27 | /// 28 | SystemInfoClass(void) { 29 | // The SYSTEM device class is where the device will be installed 30 | m_hInfo = SetupDiCreateDeviceInfoListExW(&__uuidof(T), nullptr, nullptr, nullptr); 31 | if(m_hInfo == INVALID_HANDLE_VALUE) 32 | throw eHidInstSysClassNotFound; 33 | } 34 | 35 | /// 36 | /// Creates a system device information set based on the passed enumerator 37 | /// 38 | SystemInfoClass(const wchar_t* enumerator) { 39 | // Enumerate the root tree to find the one that must be updated 40 | m_hInfo = SetupDiGetClassDevsW(&__uuidof(T), L"root\\system", nullptr, 0); 41 | if(m_hInfo == INVALID_HANDLE_VALUE) 42 | throw eHidInstSysClassNotFound; 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /Installer/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | const wchar_t gc_pnpID[] = L"HID\\OcsEmulator"; 4 | const DWORD gc_pnpIDLen = sizeof(gc_pnpID); -------------------------------------------------------------------------------- /Installer/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "targetver.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "../newdev/newdev.h" 9 | #include "PreprocFlags.h" 10 | #include 11 | #include "InstallerCodes.h" 12 | 13 | #define NUMBER_OF(x) (sizeof(x) / sizeof((x)[0])) 14 | 15 | // The PNP ID that the HIDEmulator uses: 16 | extern const wchar_t gc_pnpID[]; 17 | extern const DWORD gc_pnpIDLen; -------------------------------------------------------------------------------- /Installer/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | -------------------------------------------------------------------------------- /InstallerApp/InstallerApp.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "../Installer/Installer.h" 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | void PrintUsage(size_t argc, const wchar_t* argv[]) 10 | { 11 | wcout 12 | << "Usage: " << argv[0] << " [{install | update | uninstall | show} [infname]]" << endl 13 | << endl 14 | << " This application installs the Leap Motion HID legacy device. It MUST be run in" << endl 15 | << " administrator mode, because it has to create a new device. By default, if no" << endl 16 | << " option is specified, an installation will be attempted" << endl 17 | << endl 18 | << " The only difference between the install and update operations is that update" << endl 19 | << " will fail if the driver is not currently installed." << endl; 20 | } 21 | 22 | int wmain(int argc, const wchar_t* argv[]) 23 | { 24 | eHidStatus rs; 25 | auto op = argc < 2 ? L"install" : argv[1]; 26 | auto op2 = argc < 3 ? nullptr : argv[2]; 27 | 28 | // Switch based on the requested operation 29 | if(!wcscmp(op, L"install")) 30 | { 31 | cout << "Installing, this could take a few minutes..."; 32 | rs = OcuHidInstall(op2); 33 | } 34 | else if(!wcscmp(op, L"update")) 35 | { 36 | cout << "Updating, this could take a few minutes and may require a reboot..."; 37 | rs = OcuHidUpdate(op2); 38 | } 39 | else if(!wcscmp(op, L"uninstall")) 40 | { 41 | cout << "Uninstalling, this could take a few minutes and may require a reboot..."; 42 | rs = OcuHidUninstall(op2); 43 | } 44 | else if(!wcscmp(op, L"toggle")) 45 | { 46 | cout << "Installing, and then immediately uninstalling..."; 47 | rs = OcuHidInstall(op2); 48 | if(SUCCEEDED(rs)) 49 | rs = OcuHidUninstall(op2); 50 | } 51 | else 52 | { 53 | PrintUsage(argc, argv); 54 | return -1; 55 | } 56 | 57 | // Show some error information based on the results of the install 58 | int gle = GetLastError(); 59 | if(SUCCEEDED(rs)) 60 | if(rs == eHidInstRestartRequired) 61 | cout << "Successful, but a reboot will be required" << endl; 62 | else 63 | cout << "Successful" << endl; 64 | else 65 | { 66 | wchar_t* errmsg = nullptr; 67 | 68 | // Installer.dll has error message strings compiled in as a resource section. We 69 | // can use FormatMessage to get this information and format the return code correctly. 70 | FormatMessage( 71 | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER, 72 | GetModuleHandle(L"Installer.dll"), 73 | rs, 74 | 0, 75 | (LPWSTR)&errmsg, 76 | 0, 77 | nullptr 78 | ); 79 | 80 | // Print the result literals: 81 | cout << "Error, result was 0x" << setw(8) << setfill('0') << hex << rs << endl; 82 | wcout << L"Error text: " << (errmsg ? errmsg : L"(null)"); 83 | if(errmsg) 84 | LocalFree(errmsg); 85 | 86 | if(gle) 87 | { 88 | // Format the system error code 89 | FormatMessage( 90 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 91 | nullptr, 92 | gle, 93 | 0, 94 | (LPWSTR)&errmsg, 95 | 0, 96 | nullptr 97 | ); 98 | cout << "GetLastError: " << gle << endl; 99 | wcout << L"System error text: " << (errmsg ? errmsg : L"(null)"); 100 | if(errmsg) 101 | LocalFree(errmsg); 102 | } 103 | else 104 | cout << "No GetLastError information" << endl; 105 | } 106 | 107 | return rs; 108 | } 109 | 110 | -------------------------------------------------------------------------------- /InstallerApp/InstallerApp.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/InstallerApp/InstallerApp.rc -------------------------------------------------------------------------------- /InstallerApp/InstallerApp.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 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | 40 | 41 | Resource Files 42 | 43 | 44 | 45 | 46 | Resource Files 47 | 48 | 49 | -------------------------------------------------------------------------------- /InstallerApp/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : Installer Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this Installer application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your Installer application. 9 | 10 | 11 | Installer.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | Installer.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | Installer.cpp 25 | This is the main application source file. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other standard files: 29 | 30 | StdAfx.h, StdAfx.cpp 31 | These files are used to build a precompiled header (PCH) file 32 | named Installer.pch and a precompiled types file named StdAfx.obj. 33 | 34 | ///////////////////////////////////////////////////////////////////////////// 35 | Other notes: 36 | 37 | AppWizard uses "TODO:" comments to indicate parts of the source code you 38 | should add to or customize. 39 | 40 | ///////////////////////////////////////////////////////////////////////////// 41 | -------------------------------------------------------------------------------- /InstallerApp/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | -------------------------------------------------------------------------------- /InstallerApp/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "targetver.h" 4 | #include 5 | #include -------------------------------------------------------------------------------- /InstallerApp/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | -------------------------------------------------------------------------------- /OcuInterface/AutoLocker.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "AutoLocker.h" 3 | 4 | CAutoLocker::CAutoLocker(HANDLE hLock): 5 | m_hLock(hLock) 6 | { 7 | // Acquire the passed lock 8 | WaitForSingleObject(m_hLock, INFINITE); 9 | } 10 | 11 | CAutoLocker::~CAutoLocker(void) 12 | { 13 | // Release the mutex. This makes the assumption that the mutex was acquired, 14 | // which is typically a safe assumption unless the application is shutting down. 15 | ReleaseMutex(m_hLock); 16 | } 17 | -------------------------------------------------------------------------------- /OcuInterface/AutoLocker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// 4 | /// RIAA autolocker class, which locks the passed mutex on initialization, 5 | /// and unlocks it when it leaves scope 6 | /// 7 | class CAutoLocker 8 | { 9 | public: 10 | /// 11 | /// Locks the passed mutex 12 | /// 13 | /// The lock handle to be locked. The wait timeout is set to INFINITE. 14 | CAutoLocker(HANDLE hLock); 15 | ~CAutoLocker(void); 16 | 17 | // The handle to the lock which will be release 18 | HANDLE m_hLock; 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /OcuInterface/FocusAppInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "FocusAppInfo.h" 3 | 4 | CFocusAppInfo::CFocusAppInfo(void): 5 | m_hFocus(nullptr) 6 | { 7 | } 8 | 9 | CFocusAppInfo::~CFocusAppInfo(void) 10 | { 11 | } 12 | 13 | eHidStatus CFocusAppInfo::Update(void) 14 | { 15 | // Get the actual top window: 16 | m_hFocus = GetForegroundWindow(); 17 | if(!m_hFocus) 18 | return eHidIntrNoFocusWindow; 19 | 20 | // Get the root parent of the top window: 21 | m_hFocus = GetAncestor(m_hFocus, GA_ROOT); 22 | 23 | // Get the PID and TID about the window: 24 | m_tid = GetWindowThreadProcessId(m_hFocus, &m_pid); 25 | 26 | // Window position and extent information: 27 | WINDOWINFO wi; 28 | wi.cbSize = sizeof(wi); 29 | 30 | // Get information about the focus window 31 | GetWindowInfo(m_hFocus, &wi); 32 | m_rcWindow = wi.rcWindow; 33 | m_rcClient = wi.rcClient; 34 | 35 | // Title window acquisition: 36 | m_windowTitle.resize(MAX_PATH); 37 | m_windowTitle.resize( 38 | GetWindowTextW( 39 | m_hFocus, 40 | &m_windowTitle[0], 41 | MAX_PATH 42 | ) 43 | ); 44 | 45 | // Owner path acquisition: 46 | HANDLE hProcess = OpenProcess( 47 | PROCESS_VM_READ | PROCESS_QUERY_LIMITED_INFORMATION, 48 | false, 49 | m_pid 50 | ); 51 | if(hProcess) 52 | { 53 | // Owner EXE path allows a maximum of MAX_PATH characters 54 | m_ownerExePath.resize(MAX_PATH); 55 | 56 | // Resize the path according to the number of returned characters 57 | m_ownerExePath.resize( 58 | // Get the module name of the process we just opened 59 | GetProcessImageFileNameW( 60 | hProcess, 61 | &m_ownerExePath[0], 62 | MAX_PATH 63 | ) 64 | ); 65 | 66 | // Done with the process, close the handle 67 | CloseHandle(hProcess); 68 | 69 | // Extract just the process name: 70 | m_ownerExeName = PathFindFileNameW(m_ownerExePath.c_str()); 71 | } 72 | 73 | return eHidIntrSuccess; 74 | } 75 | 76 | wostream& operator<<(wostream& wos, CFocusAppInfo& rhs) 77 | { 78 | // Just output details about the focus application. 79 | return 80 | wos << "Extent: " << "(" << rhs.m_rcWindow.left << ", " << rhs.m_rcWindow.top << ") to (" 81 | << rhs.m_rcWindow.right << ", " << rhs.m_rcWindow.bottom << ")" << endl 82 | << "Window title: " << rhs.m_windowTitle << endl 83 | << "Process name: " << rhs.m_ownerExeName << endl 84 | << "Process path: " << rhs.m_ownerExePath << endl; 85 | } 86 | -------------------------------------------------------------------------------- /OcuInterface/FocusAppInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | enum eHidStatus; 8 | 9 | /// 10 | /// Stores and retrieves information about the currently focused window 11 | /// 12 | class CFocusAppInfo 13 | { 14 | public: 15 | CFocusAppInfo(void); 16 | ~CFocusAppInfo(void); 17 | 18 | public: 19 | /// 20 | /// A handle to the window that currently has focus 21 | /// 22 | HWND m_hFocus; 23 | 24 | /// 25 | /// The process ID of the process that owns this window 26 | /// 27 | DWORD m_pid; 28 | 29 | /// 30 | /// The thread ID of the thread that owns this window 31 | /// 32 | DWORD m_tid; 33 | 34 | // Window extent information 35 | RECT m_rcWindow; 36 | RECT m_rcClient; 37 | 38 | /// 39 | /// The title of the target window 40 | /// 41 | wstring m_windowTitle; 42 | 43 | /// 44 | /// The name of the process that owns the focus window 45 | /// 46 | wstring m_ownerExeName; 47 | 48 | /// 49 | /// The full path to the process's executable 50 | /// 51 | wstring m_ownerExePath; 52 | 53 | public: 54 | /// 55 | /// Gets information about the currently focused window 56 | /// 57 | eHidStatus Update(void); 58 | }; 59 | 60 | /// 61 | /// Debug stream manipulator for dumping the contents of this structure 62 | /// 63 | wostream& operator<<(wostream& os, CFocusAppInfo& rhs); -------------------------------------------------------------------------------- /OcuInterface/ObjPool.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "ObjPool.h" 3 | -------------------------------------------------------------------------------- /OcuInterface/ObjPool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | using std::set; 5 | 6 | template 7 | class CObjPool 8 | { 9 | public: 10 | ~CObjPool(void) 11 | { 12 | for each(T* cur in m_pool) 13 | delete cur; 14 | } 15 | 16 | private: 17 | // This is the collection of objects that have already been allocated 18 | set m_allocated; 19 | 20 | // These are objects that are waiting to be allocated 21 | set m_pool; 22 | 23 | public: 24 | /// 25 | /// Creates a new object to be used by the caller, or returns an object 26 | /// from the pool of known objects. 27 | /// 28 | /// An object of type T 29 | T* Create(void) 30 | { 31 | T* pRetVal; 32 | if(m_pool.size()) 33 | { 34 | auto q = m_pool.begin(); 35 | pRetVal = *q; 36 | m_pool.erase(q); 37 | } 38 | else 39 | pRetVal = new T; 40 | m_allocated.insert(pRetVal); 41 | return pRetVal; 42 | } 43 | 44 | /// 45 | /// Frees the passed object by returning it to the pool 46 | /// 47 | void Free(T* pObj) 48 | { 49 | m_allocated.erase(pObj); 50 | m_pool.insert(pObj); 51 | } 52 | }; 53 | 54 | -------------------------------------------------------------------------------- /OcuInterface/OcuHidInstance.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ObjPool.h" 3 | #include "OcuInterfaceCodes.h" 4 | #include "Overlapped.h" 5 | #include "../Globals/Interface.h" 6 | #include 7 | 8 | using std::map; 9 | 10 | class COcuIcon; 11 | class COcuImage; 12 | 13 | /// 14 | /// Represents a single instance of a HID emulator 15 | /// 16 | /// 17 | /// A single instance of a HID emulator is represented by the system as a single logical device. Such a 18 | /// device may be independently calibrated or configured to render on a particular monitor using multidigimon. 19 | /// The instance may also potentially be invalid. Instances of this class should not be used unless the call 20 | /// to Initialize succeeds. 21 | /// 22 | class COcuHidInstance 23 | { 24 | public: 25 | /// 26 | /// Creates a HID instance with a given device and asynchronous state 27 | /// 28 | /// A handle to the device to be created 29 | /// Set if the created instance should operate in asynchronous mode 30 | /// 31 | /// In asynchronous operation, the passed handle must have been opened with FILE_FLAG_OVERLAPPED. Afterwards, 32 | /// any IO operations invoked on this instance will complete immediately. The underlying implementation makes 33 | /// use of IO completion ports, which result in the creation of a separate worker thread to handle dispatching 34 | /// of pended OVERLAPPED instances. 35 | /// 36 | COcuHidInstance(HANDLE hDevice, bool bAsynchronous); 37 | ~COcuHidInstance(void); 38 | 39 | /// 40 | /// This is the frequency with which input reports are synthesized for metaoperations, in milliseconds 41 | /// 42 | static const DWORD sc_frequency = 100; 43 | 44 | /// 45 | /// This is the initialization operation. Call this before attempting to operate on a HID instance 46 | /// 47 | eHidStatus Initialize(void); 48 | 49 | private: 50 | // Device handle itself: 51 | HANDLE m_hDevice; 52 | 53 | // True if this device is asynchronous 54 | bool m_bAsynchronous; 55 | 56 | // Completion port used with asynchronous IO 57 | HANDLE m_hCompletionPort; 58 | 59 | // Thread properties of the thread used with the completion port: 60 | HANDLE m_hCompletionThread; 61 | DWORD m_dwCompletionTid; 62 | 63 | // OVERLAPPED structures used in pending operations: 64 | HANDLE m_hLock; 65 | mutable CObjPool m_overlapPool; 66 | 67 | // True if this is an ocuhid instance: 68 | bool m_bIsOcuHid; 69 | 70 | private: 71 | /// 72 | /// Completion thread main entrypoint, for use during asynchronous operation 73 | /// 74 | static DWORD __stdcall CompletionThread(void* pObj) 75 | { 76 | return ((COcuHidInstance*)pObj)->DoCompletionThread(); 77 | } 78 | 79 | /// 80 | /// Completion thread main entrypoint 81 | /// 82 | DWORD DoCompletionThread(void); 83 | 84 | public: 85 | /// 86 | /// Safely sends an IOCTL_HID_SET_OUTPUT_REPORT 87 | /// 88 | /// 89 | /// The result of the DeviceIoControl call 90 | /// 91 | /// 92 | /// Asynchronous IO prevents us from using HidD_SetOutputReport, as this 93 | /// routine assumes that the handle will be synchronous. 94 | /// 95 | bool SendOutputReport(const HID_SYNTEHSIZE_REPORT& report, bool block = false) const; 96 | 97 | /// 98 | /// Synthesizes a number of "contact lifted" messages 99 | /// 100 | /// The number of points to be lifted 101 | void LiftAll(UCHAR nPoints) const; 102 | 103 | public: 104 | // Accessor methods: 105 | HANDLE GetHandle(void) const {return m_hDevice;} 106 | 107 | /// 108 | /// True if the parent HID instance is an Leap Motion HID instance 109 | /// 110 | bool IsOcuHid(void) const {return m_bIsOcuHid;} 111 | 112 | /// 113 | /// Creates a new icon with the specified touch identifier 114 | /// 115 | eHidStatus CreateIcon(COcuIcon*& pIcon); 116 | 117 | /// 118 | /// Emulates a zoom gesture at the specified screen offsets: 119 | /// 120 | /// The proportionally centered X coordinate 121 | /// The proportionally centered Y coordinate 122 | /// The total distance to move 123 | /// Total time to complete the gesture, in milliseconds 124 | eHidStatus Zoom(double fx, double fy, double extent, double interval) const; 125 | 126 | /// 127 | /// Sends an arbitrary forged report down to the lower-level driver 128 | /// 129 | /// The index of the finger on which the report is to be sent 130 | /// 131 | /// Set to true to turn on the tip switch. The tip switch is translated to a left mouse click by the HID stack. 132 | /// 133 | /// The x coordinate of the cursor 134 | /// The y coordinate of the cursor 135 | /// The width of the contact pad for the cursor 136 | /// The height of the contact pad for the cursor 137 | eHidStatus SendReport(BYTE bContactID, bool TipSwitch, double fx, double fy, double cx = 0.0, double cy = 0.0) const; 138 | 139 | /// 140 | /// Sends a mouse event with the specified parameters 141 | /// 142 | eHidStatus SendReportMouse(bool LButtonDown, bool RButtonDown, double fx, double fy) const; 143 | }; 144 | 145 | -------------------------------------------------------------------------------- /OcuInterface/OcuIcon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class COcuHidInstance; 4 | class COcuImage; 5 | 6 | /// 7 | /// Represents a single icon to be rendered as an overlay somewhere on screen. 8 | /// 9 | /// 10 | /// An icon is rendered as a layered window. Layered windows have special operating system acceleration and can be 11 | /// transparent. The icon is renderd using a topmost window set to have a transparency flag set. The operating 12 | /// system even handles the task of passing mouse messages down to windows occluded by this icon. 13 | /// 14 | class COcuIcon 15 | { 16 | public: 17 | /// 18 | /// Creates a new icon with the specified instance as the initial parent. 19 | /// 20 | COcuIcon(const COcuHidInstance* pParent); 21 | ~COcuIcon(void); 22 | 23 | private: 24 | // This is the parent emulator device. 25 | const COcuHidInstance* m_pParent; 26 | 27 | // The image currently in use with this icon 28 | COcuImage* m_pImage; 29 | 30 | // This is the window handle corresponding to this overlay icon 31 | HWND m_hWnd; 32 | 33 | // These parameters are used to decide where, on screen, to render the icon 34 | int m_iDisplayIndex; 35 | POINT m_baseOffset; 36 | SIZE m_displayExtent; 37 | 38 | // The current relative position of this icon: 39 | double m_fx; 40 | double m_fy; 41 | 42 | public: 43 | // Accessor methods: 44 | HWND GetHwnd(void) const {return m_hWnd;} 45 | 46 | /// 47 | /// Sets the display this icon should appear on. 48 | /// 49 | /// The desired display index. Currently, only a value of zero is supported 50 | /// The parent HID emulator. This must correspond to the requested display index 51 | /// 52 | /// Currently, because the underlying device driver does not support rendering on anything except the 53 | /// primary display, all values except 0 will generate an error. Optimally, the only parameter that 54 | /// would be passed would be the parent HID instance. 55 | /// 56 | eHidStatus SetIconDisplayIndex(int iDisplayIndex, const COcuHidInstance* pParent); 57 | 58 | /// 59 | /// Sets the visibility of this icon 60 | /// 61 | void SetVisibility(bool bVisible); 62 | 63 | /// 64 | /// Updates the location of this icon, in screen-relative coordinates 65 | /// 66 | /// 67 | /// The position parameters must be bound in the range [0, 1). The coordinate (0, 0) corresponds to the 68 | /// top-left corner of the screen, and (1, 1) is just beyond the bottom-right corner. 69 | /// 70 | void SetPosition(double fx, double fy); 71 | 72 | /// 73 | /// Sends a report for this contact point at the contact point's current location 74 | /// 75 | eHidStatus SendReport(BYTE bContactID, bool TipSwitch, double cx = 0.0, double cy = 0.0) const; 76 | 77 | /// 78 | /// Updates the image used by this icon 79 | /// 80 | /// Set to true if the icon should be updated before the function returns 81 | void SetImage(COcuImage* pImage, bool update = true); 82 | 83 | /// 84 | /// Notifies this OcuIcon that its parent image has been updated 85 | /// 86 | eHidStatus Update(void); 87 | 88 | /// 89 | /// Window procedure for this instance. Should default everything and not be called directly 90 | /// 91 | LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam); 92 | }; -------------------------------------------------------------------------------- /OcuInterface/OcuIconWindowClass.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "OcuIconWindowClass.h" 3 | #include "OcuIcon.h" 4 | 5 | // This instance ensures that class registration occurs as one of the setup operations 6 | // for the image we're a part of. The class will remain available until global deinitializers 7 | // are called. 8 | COcuIconWindowClass COcuIconWindowClass::s_instance; 9 | 10 | COcuIconWindowClass::COcuIconWindowClass(void) 11 | { 12 | // Set up the class structure. 13 | 14 | m_wndClass.style = 15 | CS_NOCLOSE | // No close button 16 | CS_SAVEBITS; // Required to enable click-through transparency 17 | 18 | // Window procedure is defined at the end of this file 19 | m_wndClass.lpfnWndProc = WindowProc; 20 | 21 | // We need enough space to store a pointer to the COcuIcon that will drive the window 22 | m_wndClass.cbWndExtra = sizeof(COcuIcon*); 23 | 24 | // No class-specific data required 25 | m_wndClass.cbClsExtra = 0; 26 | 27 | // The remainder of these are alld efault values 28 | m_wndClass.hInstance = nullptr; 29 | m_wndClass.hIcon = nullptr; 30 | m_wndClass.hCursor = nullptr; 31 | m_wndClass.hbrBackground = nullptr; 32 | m_wndClass.lpszMenuName = nullptr; 33 | 34 | // The name of the class will be locally defined as OcuOverlay 35 | m_wndClass.lpszClassName = L"OcuOverlay"; 36 | 37 | // Finally, conduct the registration. 38 | m_atom = RegisterClass(&m_wndClass); 39 | } 40 | 41 | COcuIconWindowClass::~COcuIconWindowClass(void) 42 | { 43 | // Clean up the window class. 44 | UnregisterClass(L"OcuOverlay", nullptr); 45 | } 46 | 47 | LRESULT CALLBACK COcuIconWindowClass::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 48 | { 49 | // Get a pointer to the COcuIcon instance. 50 | LONG_PTR val = GetWindowLongPtr(hwnd, GWLP_USERDATA); 51 | 52 | // If the pointer is non-null, control is passed to the icon itself. 53 | // Otherwise, we allow the default window procedure to handle this message. 54 | return 55 | val ? 56 | ((COcuIcon*)val)->WindowProc(uMsg, wParam, lParam) : 57 | DefWindowProc(hwnd, uMsg, wParam, lParam); 58 | } -------------------------------------------------------------------------------- /OcuInterface/OcuIconWindowClass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// 4 | /// This is a utility class that registers the OcuIcon window class. Do not use it directly. 5 | /// 6 | class COcuIconWindowClass 7 | { 8 | private: 9 | static COcuIconWindowClass s_instance; 10 | 11 | COcuIconWindowClass(void); 12 | ~COcuIconWindowClass(void); 13 | 14 | private: 15 | // The actual class definition: 16 | WNDCLASSW m_wndClass; 17 | 18 | // The window class atom: 19 | ATOM m_atom; 20 | 21 | public: 22 | // The window class procedure: 23 | static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 24 | 25 | public: 26 | /// 27 | /// The class atom used to create windows of this class 28 | /// 29 | static ATOM GetAtom(void) {return s_instance.m_atom;} 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /OcuInterface/OcuImage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | using std::set; 7 | using std::vector; 8 | using std::unique_ptr; 9 | 10 | enum eHidStatus; 11 | class COcuIcon; 12 | class COcuHidInstance; 13 | 14 | /// 15 | /// Represents a single icon registered with the OcuInterface. Do not construct this class directly; 16 | /// rather, construct it by calling . 17 | /// 18 | class COcuImage 19 | { 20 | public: 21 | COcuImage(COcuHidInstance* pParent); 22 | ~COcuImage(void); 23 | 24 | private: 25 | COcuHidInstance* m_pParent; 26 | 27 | // The DC representing this image 28 | HDC m_hDC; 29 | 30 | // The hot spot point and image properties: 31 | POINT m_hotspot; 32 | SIZEL m_size; 33 | 34 | // All registered icons: 35 | set m_icons; 36 | 37 | /// 38 | /// Registers (or unregisters) the passed icon with this image. 39 | /// 40 | void Register(COcuIcon* pIcon, bool bRegister); 41 | 42 | public: 43 | // Accessor methods: 44 | HDC GetDC(void) const {return m_hDC;} 45 | POINT GetHotspot(void) const {return m_hotspot;} 46 | DWORD GetWidth(void) const {return m_size.cx;} 47 | DWORD GetHeight(void) const {return m_size.cy;} 48 | 49 | /// 50 | /// Sets the "hot spot" for this icon. Initially, the hot spot is the geometric center of the icon. 51 | /// 52 | void SetHotspot(DWORD x, DWORD y); 53 | 54 | /// 55 | /// Constructs a DC from the passed image file 56 | /// 57 | eHidStatus SetImage(const wchar_t* pwcsFileName, const POINT* pHotspot = nullptr); 58 | 59 | /// 60 | /// Constructs a DC from the passed Gdi+ bitmap 61 | /// 62 | /// The Gdi+ bitmap containing the desired image data 63 | /// The hot spot for the image. If left null, it will default to the geometric center. 64 | eHidStatus SetImage(Gdiplus::Bitmap& src, const POINT* pHotspot = nullptr); 65 | 66 | /// 67 | /// Constructs a DC to be used with this image from the passed rectangular array of pixels 68 | /// 69 | /// The width of the passed image 70 | /// The height of the passed image 71 | /// The distance, in bytes, between successive rows of the image. May potentially be negative. 72 | /// The hot spot for the image. If left null, it will default to the geometric center. 73 | /// A pointer to the first scan line in the source image 74 | eHidStatus SetImage(LONG width, LONG height, int pitch, const void* pScan0, const POINT* pHotspot = nullptr, Gdiplus::PixelFormat PixelFormat = PixelFormat32bppARGB); 75 | 76 | /// 77 | /// Sets the DC used as a source for this image 78 | /// 79 | /// The hot spot for the image. If left null, it will default to the geometric center. 80 | /// 81 | /// The passed DC must have been created with CreateCompatibleDC. Once assigned, this class 82 | /// takes responsibility for the cleanup of the HDC and the HBITMAP attached to it 83 | /// 84 | void SetDC(HDC hDc, const POINT* pHotspot = nullptr); 85 | 86 | /// 87 | /// Triggers a cascading update to all attached icons 88 | /// 89 | eHidStatus Update(void); 90 | 91 | // Friend declarations: 92 | friend class COcuIcon; 93 | }; 94 | 95 | -------------------------------------------------------------------------------- /OcuInterface/OcuInterface.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "OcuInterface.h" 3 | #include "OcuHidInstance.h" 4 | #include 5 | 6 | using namespace std; 7 | 8 | // These are preprocessor definitions copied from Windows kernel-mode header files. They're pasted here in 9 | // order to make it 10 | #define FILE_DEVICE_KEYBOARD 0x0000000b 11 | #define METHOD_NEITHER 3 12 | #define FILE_ANY_ACCESS 0 13 | 14 | #define CTL_CODE( DeviceType, Function, Method, Access ) ( \ 15 | ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ 16 | ) 17 | 18 | #define HID_CTL_CODE(id) CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS) 19 | #define IOCTL_HID_GET_DEVICE_DESCRIPTOR HID_CTL_CODE(0) 20 | 21 | COcuInterface::COcuInterface(bool bAsynchronous): 22 | m_lastErr(0), 23 | m_bAsynchronous(bAsynchronous) 24 | { 25 | // Recover the GUID of the HID device class. This GUID identifies all HID-compliant devices on 26 | // the system, and Leap Motion is among them. 27 | GUID hidGuid; 28 | HidD_GetHidGuid(&hidGuid); 29 | 30 | // Open handle to root PNP node. The root PNP node is the parent of all PNP devices, and 31 | // it's called /root. The OcuSpec emulator device isn't a true device, so its parent will 32 | // be the root node. 33 | auto root = SetupDiGetClassDevs(&hidGuid, nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 34 | if(root == INVALID_HANDLE_VALUE) 35 | { 36 | m_lastErr = GetLastError(); 37 | return; 38 | } 39 | 40 | // Set up the structure to get device interface data. The device interface provides a standardized 41 | // way of naming a device driver for access by a usermode client. HID defines its own device interface 42 | // and that's the one we will be using. 43 | SP_DEVICE_INTERFACE_DATA deviceInfoData; 44 | deviceInfoData.cbSize = sizeof(deviceInfoData); 45 | 46 | // Begin enumerating all known devices on the system. 47 | vector buf; 48 | for( 49 | DWORD i = 0; 50 | SetupDiEnumDeviceInterfaces(root, nullptr, &hidGuid, i, &deviceInfoData); 51 | i++ 52 | ) 53 | { 54 | // First, we need to get the length of the detail information that will be required. 55 | DWORD reqLen = 0; 56 | SetupDiGetDeviceInterfaceDetail(root, &deviceInfoData, nullptr, 0, &reqLen, nullptr); 57 | 58 | // Now that we know the required length, we allocate a buffer and read the details. 59 | buf.resize(reqLen); 60 | SP_DEVICE_INTERFACE_DETAIL_DATA& detail = (SP_DEVICE_INTERFACE_DETAIL_DATA&)buf[0]; 61 | detail.cbSize = sizeof(detail); 62 | if(!SetupDiGetDeviceInterfaceDetail(root, &deviceInfoData, &detail, reqLen, &reqLen, nullptr)) 63 | continue; 64 | 65 | // Now that we have the path to device, we can try to open it for writing. The only method 66 | // we use on the returned handle is DeviceIoControl, so the GENERIC_WRITE is the only permission 67 | // that we need. 68 | HANDLE hDev = CreateFile( 69 | detail.DevicePath, 70 | GENERIC_WRITE, 71 | FILE_SHARE_READ | FILE_SHARE_WRITE, 72 | nullptr, 73 | OPEN_EXISTING, 74 | m_bAsynchronous ? FILE_FLAG_OVERLAPPED : 0, 75 | nullptr 76 | ); 77 | if(hDev == INVALID_HANDLE_VALUE) 78 | continue; 79 | 80 | // We were able to open this device. At this point, it may or may not be a HID device--we 81 | // won't know until later--but we need to record this handle for now. 82 | push_back(new COcuHidInstance(hDev, m_bAsynchronous)); 83 | } 84 | } 85 | 86 | COcuInterface::~COcuInterface(void) 87 | { 88 | // Destructor call. Any unclaimed interface must be destroyed 89 | // to prevent resource leaks. 90 | for each(auto q in *this) 91 | delete q; 92 | } 93 | 94 | COcuHidInstance* COcuInterface::GetFirstCompliantInterface(void) 95 | { 96 | eHidStatus rs; 97 | 98 | // All we do here is to enumerate our own local set of devices 99 | // and then return the first device that appears to initialize 100 | // correctly. This routine is offered as a convenience on those 101 | // systems were it is well known that only one OcuEmulator device 102 | // will be present. 103 | for(auto q = begin(); q != end(); q++) 104 | { 105 | auto cur = *q; 106 | 107 | // If we succeed in initializing a particular instance, we remove 108 | // it from our collection and reeturn it. 109 | if(SUCCEEDED(rs = cur->Initialize())) 110 | return erase(q), cur; 111 | } 112 | 113 | // Nothing found, return here. 114 | return nullptr; 115 | } -------------------------------------------------------------------------------- /OcuInterface/OcuInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "FocusAppInfo.h" 3 | #include "OcuHidInstance.h" 4 | #include 5 | 6 | using std::vector; 7 | 8 | class COcuHidInstance; 9 | class COcuIcon; 10 | class COcuImage; 11 | 12 | class COcuInterface: 13 | public vector 14 | { 15 | public: 16 | /// 17 | /// Creates a new interface for enumerating HID instances 18 | /// 19 | /// Set to true if calls to input synthesis should be performed asynchronously 20 | /// 21 | /// Asynchronous IO is supported in Leap Motion HID by using I/O completion ports and an additional dispatcher thread to handle 22 | /// resource cleanup. 23 | /// 24 | COcuInterface(bool bAsynchronous = false); 25 | ~COcuInterface(void); 26 | 27 | private: 28 | DWORD m_lastErr; 29 | bool m_bAsynchronous; 30 | 31 | public: 32 | bool Ok(void) const {return !m_lastErr;} 33 | DWORD GetLastErr(void) const {return m_lastErr;} 34 | 35 | /// 36 | /// Removes the first compliant COcuHidInstance from this collection and returns it. The caller is responsible 37 | /// for deleting the returned pointer. 38 | /// 39 | COcuHidInstance* GetFirstCompliantInterface(void); 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /OcuInterface/OcuInterface.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 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | Header Files 59 | 60 | 61 | Header Files 62 | 63 | 64 | Header Files 65 | 66 | 67 | Header Files 68 | 69 | 70 | 71 | 72 | Source Files 73 | 74 | 75 | Source Files 76 | 77 | 78 | Source Files 79 | 80 | 81 | Source Files 82 | 83 | 84 | Source Files 85 | 86 | 87 | Source Files 88 | 89 | 90 | Source Files 91 | 92 | 93 | Source Files 94 | 95 | 96 | Source Files 97 | 98 | 99 | Source Files 100 | 101 | 102 | 103 | 104 | Resource Files 105 | 106 | 107 | 108 | 109 | Resource Files 110 | 111 | 112 | -------------------------------------------------------------------------------- /OcuInterface/OcuInterfaceCodes.mc: -------------------------------------------------------------------------------- 1 | ;#pragma once 2 | ;enum eHidStatus; 3 | 4 | MessageIdTypedef=eHidStatus 5 | 6 | SeverityNames=( 7 | Success = 0x0 : OCUHID_STATUS_SUCCESS 8 | Informational = 0x1 : OCUHID_STATUS_INFORMATION 9 | Warning = 0x2 : OCUHID_STATUS_WARNING 10 | Error = 0x3 : OCUHID_STATUS_ERROR 11 | ) 12 | 13 | FacilityNames=( 14 | HidIntr = 0x2 15 | ) 16 | 17 | Messageid=0 18 | Severity=Success 19 | Facility=HidIntr 20 | SymbolicName=eHidIntrSuccess 21 | Language=English 22 | The operation completed successfully. 23 | . 24 | 25 | MessageId=0 26 | Severity=Warning 27 | Facility=HidIntr 28 | SymbolicName=eHidIntrGestureOverflow 29 | Language=English 30 | The gesture had to be aborted because one of the input contact points passed beyond the boundaries of the screen 31 | . 32 | 33 | MessageId=0 34 | Severity=Error 35 | Facility=HidIntr 36 | SymbolicName=eHidIntrIoctlFailed 37 | Language=English 38 | Communication failed with the Hid emulator 39 | . 40 | 41 | MessageId= 42 | SymbolicName=eHidIntrNotOcuHid 43 | Language=English 44 | This HID instance is a HID device, but not a Leap Motion HidEmulator 45 | . 46 | 47 | MessageId= 48 | SymbolicName=eHidIntrHidAttributeQueryFail 49 | Language=English 50 | Failed to query the HID instance attributes on this device 51 | . 52 | 53 | MessageId= 54 | SymbolicName=eHidIntrCompletionPortCreateFail 55 | Language=English 56 | Failed to create a completion port for asynchronous IO 57 | . 58 | 59 | MessageId= 60 | SymbolicName=eHidIntrCompletionThreadNotCreated 61 | Language=English 62 | Failed to create a thread to wait on the completion port 63 | . 64 | 65 | MessageId= 66 | SymbolicName=eHidIntrNotRespondingProperly 67 | Language=English 68 | The device appears to be a Leap Motion HidEmulator, but isn't responding to write reports correctly 69 | . 70 | 71 | MessageId= 72 | SymbolicName=eHidIntrHbitmapCreateFail 73 | Language=English 74 | Failed to create an HBITMAP 75 | . 76 | 77 | MessageId= 78 | SymbolicName=eHidIntrUpdateLayeredWindowFailed 79 | Language=English 80 | Call to UpdateLayeredWindow failed for an overlay icon 81 | . 82 | 83 | MessageId= 84 | SymbolicName=eHidIntrIndexOutOfBounds 85 | Language=English 86 | The specified display index is out of bounds 87 | . 88 | 89 | MessageId= 90 | SymbolicName=eHidIntrNoFocusWindow 91 | Language=English 92 | Could not identify the window that currently has focus 93 | . 94 | 95 | MessageId= 96 | SymbolicName=eHidIntrPixelFormatNotRecognized 97 | Language=English 98 | The passed pixel format was not recognized 99 | . 100 | 101 | MessageId= 102 | SymbolicName=eHidIntrCreateDibSectionFailed 103 | Language=English 104 | Failed to create a DIB section to hold the passed image data 105 | . 106 | 107 | MessageId= 108 | SymbolicName=eHidIntrFailedToLoad 109 | Language=English 110 | Failed to load the specified image file. This may be because the image doesn't exist, resource shortages 111 | on the system, or the file itself could be corrupted or of an unsupported format. 112 | . 113 | 114 | MessageId= 115 | SymbolicName=eHidIntrFailedToLock 116 | Language=English 117 | Failed to lock the bits of the source image. The image file could be corrupted, or there may not be enough 118 | system resources to lock bits. 119 | . 120 | -------------------------------------------------------------------------------- /OcuInterface/Overlapped.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "Overlapped.h" 3 | 4 | COverlapped::COverlapped(void) 5 | { 6 | // The entire overlapped structure should be set to zero before 7 | // we proceed. Lingering nonzero values can have strange effects 8 | // on consumers who may use this structure without checking it first. 9 | memset((LPOVERLAPPED)this, 0, sizeof(OVERLAPPED)); 10 | 11 | // Create a default, auto-resetting, anonymous event 12 | hEvent = CreateEvent(nullptr, false, false, nullptr); 13 | } 14 | 15 | COverlapped::~COverlapped(void) 16 | { 17 | // Only close the event if it has been created 18 | if(hEvent) 19 | CloseHandle(hEvent); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /OcuInterface/Overlapped.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// 4 | /// This is a managed overlapped structure. It automatically cleans up the event 5 | /// handle associated with the OVERLAPPED structure so that it may be automatically 6 | /// freed when no longer needed. 7 | /// 8 | class COverlapped: 9 | public OVERLAPPED 10 | { 11 | public: 12 | COverlapped(void); 13 | ~COverlapped(void); 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /OcuInterface/PreprocFlags.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// This flag should be set to 0 if the interface should never try to send more 4 | /// that one input in an individual input report, effectively forcing the input 5 | /// mode to serial. This debugging flag is useful if you are trying to identify 6 | /// defects in the hybrid packet format. 7 | /// 8 | /// Recommended value: 1 9 | #define OCUINT_ALLOW_HYBRID_SYNTHESIS 0 -------------------------------------------------------------------------------- /OcuInterface/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : OcuInterface Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this OcuInterface library project for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your OcuInterface application. 9 | 10 | 11 | OcuInterface.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | OcuInterface.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | 25 | ///////////////////////////////////////////////////////////////////////////// 26 | 27 | StdAfx.h, StdAfx.cpp 28 | These files are used to build a precompiled header (PCH) file 29 | named OcuInterface.pch and a precompiled types file named StdAfx.obj. 30 | 31 | ///////////////////////////////////////////////////////////////////////////// 32 | Other notes: 33 | 34 | AppWizard uses "TODO:" comments to indicate parts of the source code you 35 | should add to or customize. 36 | 37 | ///////////////////////////////////////////////////////////////////////////// 38 | -------------------------------------------------------------------------------- /OcuInterface/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | -------------------------------------------------------------------------------- /OcuInterface/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "targetver.h" 4 | 5 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | extern "C" { 13 | #include "hidsdi.h" 14 | } 15 | 16 | #include "../Globals/Interface.h" 17 | #include "OcuInterfaceCodes.h" 18 | #include "PreprocFlags.h" 19 | 20 | // These are extracted from hidclass.h: 21 | #define IOCTL_HID_SET_OUTPUT_REPORT 0xb0195 -------------------------------------------------------------------------------- /OcuInterface/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 | -------------------------------------------------------------------------------- /OverlayHarness/GdiplusInitializer.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "GdiplusInitializer.h" 3 | 4 | using namespace Gdiplus; 5 | 6 | GdiplusInitializer::GdiplusInitializer(void) 7 | { 8 | GdiplusStartupInput gdiplusStartupInput; 9 | GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); 10 | } 11 | 12 | 13 | GdiplusInitializer::~GdiplusInitializer(void) 14 | { 15 | GdiplusShutdown(m_gdiplusToken); 16 | } 17 | -------------------------------------------------------------------------------- /OverlayHarness/GdiplusInitializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class GdiplusInitializer 3 | { 4 | public: 5 | GdiplusInitializer(void); 6 | ~GdiplusInitializer(void); 7 | 8 | private: 9 | ULONG_PTR m_gdiplusToken; 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /OverlayHarness/OverlayHarness.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "resource.h" 3 | #include "ResourcePng.h" 4 | #include "GdiplusInitializer.h" 5 | #include 6 | #include "../OcuInterface/OcuInterface.h" 7 | #include "../OcuInterface/OcuIcon.h" 8 | #include "../OcuInterface/OcuImage.h" 9 | #include 10 | 11 | using namespace Gdiplus; 12 | using namespace std; 13 | 14 | COcuIcon* g_pIcon1; 15 | COcuIcon* g_pIcon2; 16 | 17 | CResourcePng* g_pCircles[16]; 18 | COcuImage* g_pImages[16]; 19 | 20 | // The current index on g_pIcon 21 | int g_iconIndex = 14; 22 | int g_time = 0; 23 | 24 | // Timer routine to update the above global icon: 25 | void CALLBACK ChangeIcon(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) 26 | { 27 | g_time++; 28 | g_iconIndex = (g_iconIndex + 1) % 16; 29 | 30 | g_pIcon1->SetImage(g_pImages[g_iconIndex]); 31 | g_pIcon1->SetPosition( 32 | 0.5 + cos(g_time / 40.0f) / 2.0, 33 | 0.5 + sin(g_time / 40.0f) / 2.0 34 | ); 35 | g_pIcon1->Update(); 36 | 37 | g_pIcon2->SetImage(g_pImages[g_iconIndex]); 38 | g_pIcon2->SetPosition( 39 | 0.5 + cos(10 + g_time / 50.0f) / 2.0, 40 | 0.5 + sin(10 + g_time / 50.0f) / 2.0 41 | ); 42 | g_pIcon2->Update(); 43 | } 44 | 45 | int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* lpCmdLine, int nCmdShow) 46 | { 47 | // Initialize GDI+ 48 | GdiplusInitializer init; 49 | 50 | COcuHidInstance* hid = COcuInterface().GetFirstCompliantInterface(); 51 | if(!hid) 52 | { 53 | cout << "No compliant interfaces found" << endl; 54 | return 0; 55 | } 56 | 57 | int ids[] = 58 | { 59 | IDB_CIRCLE01, IDB_CIRCLE02, IDB_CIRCLE03, IDB_CIRCLE04, 60 | IDB_CIRCLE05, IDB_CIRCLE06, IDB_CIRCLE07, IDB_CIRCLE08, 61 | IDB_CIRCLE09, IDB_CIRCLE10, IDB_CIRCLE11, IDB_CIRCLE12, 62 | IDB_CIRCLE13, IDB_CIRCLE14, IDB_CIRCLE15, IDB_CIRCLE16 63 | }; 64 | for(int i = 0; i < 16; i++) 65 | { 66 | g_pCircles[i] = new CResourcePng(hInstance, ids[i]); 67 | HDC hdc = g_pCircles[i]->ConstructDC(); 68 | 69 | COcuImage*& pImg = g_pImages[i]; 70 | pImg = new COcuImage(hid); 71 | 72 | // There are a few options here: A direct call to SetDC, 73 | // or the convenience routine SetImage. 74 | pImg->SetDC(hdc); 75 | 76 | // Example call that could be made instead of SetDC: 77 | // pImg->SetImage(L"C:\\path\\to\\image.png"); 78 | 79 | // Call update no matter what 80 | pImg->Update(); 81 | } 82 | 83 | // Create a single overlay icon: 84 | hid->CreateIcon(g_pIcon1); 85 | hid->CreateIcon(g_pIcon2); 86 | 87 | // Timer is set to give us a periodic refresh that may be trapped. 88 | SetTimer(g_pIcon1->GetHwnd(), 0, 50, ChangeIcon); 89 | 90 | // Main message loop. 91 | for(MSG msg; GetMessage(&msg, nullptr, 0, 0) > 0; ) 92 | { 93 | TranslateMessage(&msg); 94 | DispatchMessage(&msg); 95 | } 96 | 97 | return 0; 98 | } 99 | 100 | -------------------------------------------------------------------------------- /OverlayHarness/OverlayHarness.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/OverlayHarness.rc -------------------------------------------------------------------------------- /OverlayHarness/OverlayHarness.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 | {338424d6-90df-4c0c-b4d9-9547754db6e3} 18 | 19 | 20 | 21 | 22 | 23 | circle_icons 24 | 25 | 26 | circle_icons 27 | 28 | 29 | circle_icons 30 | 31 | 32 | circle_icons 33 | 34 | 35 | circle_icons 36 | 37 | 38 | circle_icons 39 | 40 | 41 | circle_icons 42 | 43 | 44 | circle_icons 45 | 46 | 47 | circle_icons 48 | 49 | 50 | circle_icons 51 | 52 | 53 | circle_icons 54 | 55 | 56 | circle_icons 57 | 58 | 59 | circle_icons 60 | 61 | 62 | circle_icons 63 | 64 | 65 | circle_icons 66 | 67 | 68 | circle_icons 69 | 70 | 71 | Resource Files 72 | 73 | 74 | 75 | 76 | Header Files 77 | 78 | 79 | Header Files 80 | 81 | 82 | Header Files 83 | 84 | 85 | Header Files 86 | 87 | 88 | Header Files 89 | 90 | 91 | Header Files 92 | 93 | 94 | 95 | 96 | Source Files 97 | 98 | 99 | Source Files 100 | 101 | 102 | Source Files 103 | 104 | 105 | Source Files 106 | 107 | 108 | Source Files 109 | 110 | 111 | 112 | 113 | Resource Files 114 | 115 | 116 | -------------------------------------------------------------------------------- /OverlayHarness/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : OverlayHarness Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this OverlayHarness application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your OverlayHarness application. 9 | 10 | 11 | OverlayHarness.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | OverlayHarness.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | OverlayHarness.cpp 25 | This is the main application source file. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other standard files: 29 | 30 | StdAfx.h, StdAfx.cpp 31 | These files are used to build a precompiled header (PCH) file 32 | named OverlayHarness.pch and a precompiled types file named StdAfx.obj. 33 | 34 | ///////////////////////////////////////////////////////////////////////////// 35 | Other notes: 36 | 37 | AppWizard uses "TODO:" comments to indicate parts of the source code you 38 | should add to or customize. 39 | 40 | ///////////////////////////////////////////////////////////////////////////// 41 | -------------------------------------------------------------------------------- /OverlayHarness/ResourcePng.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "ResourcePng.h" 3 | #include "ResourceStream.h" 4 | 5 | using namespace Gdiplus; 6 | 7 | CResourcePng::CResourcePng(HINSTANCE hInstance, LPCWSTR lpPngName): 8 | Gdiplus::Bitmap(&CResourceStream(hInstance, lpPngName, L"PNG")) 9 | { 10 | } 11 | 12 | CResourcePng::CResourcePng(HINSTANCE hInstance, int intResource): 13 | Gdiplus::Bitmap(&CResourceStream(hInstance, MAKEINTRESOURCE(intResource), L"PNG")) 14 | { 15 | } 16 | 17 | CResourcePng::~CResourcePng(void) 18 | { 19 | } 20 | 21 | HDC CResourcePng::ConstructDC(void) 22 | { 23 | // Create the objects to be returned: 24 | HDC retVal = CreateCompatibleDC(nullptr); 25 | 26 | // Attempt to transform the source bits to the destination space: 27 | BitmapData bitmapData; 28 | LockBits(&Rect(0, 0, GetWidth(), GetHeight()), ImageLockModeRead, PixelFormat32bppARGB, &bitmapData); 29 | 30 | // Construct an information header based on the locked bits: 31 | BITMAPINFO info; 32 | auto& hdr = info.bmiHeader; 33 | hdr.biSize = sizeof(hdr); 34 | 35 | switch(bitmapData.PixelFormat) 36 | { 37 | case PixelFormat32bppARGB: 38 | hdr.biWidth = bitmapData.Width; 39 | hdr.biHeight = bitmapData.Height; 40 | hdr.biPlanes = 1; 41 | hdr.biBitCount = 32; 42 | hdr.biCompression = BI_RGB; 43 | hdr.biSizeImage = 0; 44 | hdr.biXPelsPerMeter = 0; 45 | hdr.biYPelsPerMeter = 0; 46 | hdr.biClrUsed = 0; 47 | hdr.biClrImportant = 0; 48 | break; 49 | default: 50 | DeleteDC(retVal); 51 | UnlockBits(&bitmapData); 52 | return nullptr; 53 | } 54 | 55 | // Attempt to perform the copy operation 56 | RGBQUAD* pvBits; 57 | HBITMAP hBitmap = CreateDIBSection( 58 | retVal, 59 | &info, 60 | DIB_RGB_COLORS, 61 | (void**)&pvBits, 62 | nullptr, 63 | 0 64 | ); 65 | if(!hBitmap) 66 | { 67 | DeleteDC(retVal); 68 | return nullptr; 69 | } 70 | 71 | SelectObject(retVal, hBitmap); 72 | memcpy( 73 | pvBits, 74 | bitmapData.Scan0, 75 | bitmapData.Height * bitmapData.Stride 76 | ); 77 | 78 | // Alpha channel must be premultiplied alpha in order to be blended correctly. 79 | // The premultiplication is done here. 80 | for(size_t i = bitmapData.Height * bitmapData.Width; i--;) 81 | { 82 | int alpha = pvBits[i].rgbReserved; 83 | pvBits[i].rgbRed = pvBits[i].rgbRed * alpha >> 8; 84 | pvBits[i].rgbGreen = pvBits[i].rgbGreen * alpha >> 8; 85 | pvBits[i].rgbBlue = pvBits[i].rgbBlue * alpha >> 8; 86 | } 87 | 88 | // Release memory regardless, we can't keep it here. 89 | UnlockBits(&bitmapData); 90 | return retVal; 91 | } -------------------------------------------------------------------------------- /OverlayHarness/ResourcePng.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Gdiplus.h" 3 | 4 | /// 5 | /// Convenience class for loading a resource-stored PNG into an HBITMAP 6 | /// 7 | class CResourcePng: 8 | public Gdiplus::Bitmap 9 | { 10 | public: 11 | CResourcePng(HINSTANCE hInstance, LPCWSTR lpPngName); 12 | CResourcePng(HINSTANCE hInstance, int intResource); 13 | ~CResourcePng(void); 14 | 15 | private: 16 | 17 | public: 18 | HDC ConstructDC(void); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /OverlayHarness/ResourceStream.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "ResourceStream.h" 3 | 4 | CResourceStream::CResourceStream(HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType): 5 | m_refCt(1), 6 | m_hRsrc(FindResource(hModule, lpName, lpType)), 7 | m_pData((const char*)LoadResource(hModule, m_hRsrc)), 8 | m_len(SizeofResource(hModule, m_hRsrc)), 9 | m_offset(0) 10 | { 11 | } 12 | 13 | CResourceStream::~CResourceStream(void) 14 | { 15 | if(m_hRsrc) 16 | FreeResource(m_hRsrc); 17 | } 18 | -------------------------------------------------------------------------------- /OverlayHarness/ResourceStream.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class CResourceStream: 4 | public IStream 5 | { 6 | public: 7 | CResourceStream(HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType); 8 | ~CResourceStream(void); 9 | 10 | private: 11 | ULONG m_refCt; 12 | 13 | HRSRC m_hRsrc; 14 | const char* m_pData; 15 | unsigned long long m_len; 16 | unsigned long long m_offset; 17 | 18 | public: 19 | virtual HRESULT STDMETHODCALLTYPE Read(void *pv, ULONG cb, ULONG *pcbRead) 20 | { 21 | ULONG read = min(cb, (ULONG)(m_len - m_offset)); 22 | memcpy(pv, m_pData + m_offset, read); 23 | if(pcbRead) 24 | *pcbRead = read; 25 | 26 | m_offset += read; 27 | return read < cb ? S_FALSE : S_OK; 28 | } 29 | 30 | virtual HRESULT STDMETHODCALLTYPE Write(const void *pv, ULONG cb, ULONG *pcbWritten) {return STG_E_ACCESSDENIED;} 31 | 32 | virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) 33 | { 34 | switch(dwOrigin) 35 | { 36 | case STREAM_SEEK_SET: 37 | m_offset = dlibMove.QuadPart; 38 | break; 39 | case STREAM_SEEK_CUR: 40 | m_offset += dlibMove.QuadPart; 41 | break; 42 | case STREAM_SEEK_END: 43 | m_offset = m_len - dlibMove.QuadPart; 44 | break; 45 | default: 46 | return E_INVALIDARG; 47 | } 48 | 49 | if(plibNewPosition) 50 | plibNewPosition->QuadPart = m_offset; 51 | return S_OK; 52 | } 53 | 54 | virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) {return E_NOTIMPL;} 55 | 56 | virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) 57 | { 58 | cb.QuadPart = min(cb.QuadPart, m_len - m_offset); 59 | HRESULT rs = pstm->Write(m_pData + m_offset, (ULONG)cb.QuadPart, &pcbWritten->LowPart); 60 | 61 | pcbWritten->HighPart = 0; 62 | *pcbRead = *pcbWritten; 63 | return rs; 64 | } 65 | 66 | virtual HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags) {return S_OK;} 67 | virtual HRESULT STDMETHODCALLTYPE Revert(void) {return S_OK;} 68 | virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;} 69 | virtual HRESULT STDMETHODCALLTYPE UnlockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;} 70 | virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG *pstatstg, DWORD grfStatFlag) 71 | { 72 | memset(pstatstg, 0, sizeof(*pstatstg)); 73 | pstatstg->pwcsName = nullptr; 74 | pstatstg->type = STGTY_STREAM; 75 | pstatstg->cbSize.QuadPart = m_len; 76 | pstatstg->grfMode = STGM_READ; 77 | return S_OK; 78 | } 79 | 80 | virtual HRESULT STDMETHODCALLTYPE Clone(IStream **ppstm) 81 | { 82 | return E_NOTIMPL; 83 | } 84 | 85 | // IUnknown methods: 86 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) 87 | { 88 | return E_NOTIMPL; 89 | } 90 | 91 | virtual ULONG STDMETHODCALLTYPE AddRef(void) 92 | { 93 | return ++m_refCt; 94 | } 95 | 96 | virtual ULONG STDMETHODCALLTYPE Release(void) 97 | { 98 | return 99 | !--m_refCt ? 100 | delete this, 0 : 101 | m_refCt; 102 | } 103 | }; 104 | 105 | -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_01.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_02.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_03.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_04.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_05.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_06.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_07.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_08.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_09.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_10.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_11.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_12.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_13.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_14.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_15.png -------------------------------------------------------------------------------- /OverlayHarness/circle_icons/circle_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/circle_icons/circle_16.png -------------------------------------------------------------------------------- /OverlayHarness/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/OverlayHarness/resource.h -------------------------------------------------------------------------------- /OverlayHarness/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | using namespace Gdiplus; 4 | 5 | HINSTANCE g_hInstance; 6 | 7 | int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) 8 | { 9 | UINT num = 0; // number of image encoders 10 | UINT size = 0; // size of the image encoder array in bytes 11 | 12 | ImageCodecInfo* pImageCodecInfo = NULL; 13 | 14 | GetImageEncodersSize(&num, &size); 15 | if(size == 0) 16 | return -1; // Failure 17 | 18 | pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); 19 | if(pImageCodecInfo == NULL) 20 | return -1; // Failure 21 | 22 | GetImageEncoders(num, size, pImageCodecInfo); 23 | 24 | for(UINT j = 0; j < num; ++j) 25 | { 26 | if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) 27 | { 28 | *pClsid = pImageCodecInfo[j].Clsid; 29 | free(pImageCodecInfo); 30 | return j; // Success 31 | } 32 | } 33 | 34 | free(pImageCodecInfo); 35 | return -1; // Failure 36 | } 37 | -------------------------------------------------------------------------------- /OverlayHarness/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "targetver.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | extern HINSTANCE g_hInstance; 11 | int GetEncoderClsid(const WCHAR* format, CLSID* pClsid); -------------------------------------------------------------------------------- /OverlayHarness/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /Resource/Certificate/DigiCert Assured ID Root CA.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFNDCCAxygAwIBAgIKYRyyigAAAAAAJjANBgkqhkiG9w0BAQUFADB/MQswCQYD 3 | VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe 4 | MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3Nv 5 | ZnQgQ29kZSBWZXJpZmljYXRpb24gUm9vdDAeFw0xMTA0MTUxOTQxMzdaFw0yMTA0 6 | MTUxOTUxMzdaMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx 7 | GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFz 8 | c3VyZWQgSUQgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB 9 | AK0OFc7kQ4BcsYfzt2D5cRKlrtwmlIiq9M71IDkoWGAM+IDaqRWVMmE8tbEohIqK 10 | 3J8KDIMXeo+QrIrneVNcMYQq9g+YMjZ2zN7dPKii72r7IfJSYd+fINcf4rHZ/hhk 11 | 0hJbX/lYGDW8R82hNvlrf9SwOD7BG8OMM9nYLxj+KA+zp4PWw25EwGE1lhb+WZyL 12 | dm3X8aJLDSv/C3LanmDQjpA1xnhVhyChz+VtCshJfDGYM2wi6YfQMlqiuhOCEe05 13 | F52ZOnKh5vqk2dUXMXWuhX0irj8BRob2KHnIsdrkVxfEfhwOsLSSplazvbKX7aqn 14 | 8LfFqD+VFtD/oZbrCF8Yd08CAwEAAaOByzCByDARBgNVHSAECjAIMAYGBFUdIAAw 15 | CwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEXroq/0ksuC 16 | MS1Ri6enIZ3zbcgPMB8GA1UdIwQYMBaAFGL7CiFbf0NuEdoJVFBr9dKWcfGeMFUG 17 | A1UdHwROMEwwSqBIoEaGRGh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3Js 18 | L3Byb2R1Y3RzL01pY3Jvc29mdENvZGVWZXJpZlJvb3QuY3JsMA0GCSqGSIb3DQEB 19 | BQUAA4ICAQBc9bItAs7tAbU1EtgT96pAFMehXKCKVe1+VepqxFcXb9BHIkI2WO/F 20 | rGHF9ixSzmrmyA2F2rM0Qg6kAiUYJnK5Kk6lfksW8qDkDESc4k2a9HTw+SemaZAx 21 | wkRlQ0jHSGnQ/IQJ8oYUCsIploV/EeuHExdu0+xr/x1XirF7HqWgfOmiemjl+sax 22 | YdZyY/o3kWODVZn4HWFPDG+j97yxFSrMjYXjFBfvfklEP7AiwPCsvi/b4QyGsPRY 23 | XFoQqUvN80SKRlIIPgpiEOlFlQS3i41LB09QDbe75/uMonh4xsU7dmOyz+UhhFpm 24 | /OBMeYNOz6jucAWGWHzCnNc8o608fnZiXIfQ7XzVxVsUIfS+daJ10unhWtAgMHhB 25 | Yk1rXm4bFxAkSthYh3XQFddiu/0YVmWEJWGXf6rUnfTzXW2gMcLhngKsPpDDMn7o 26 | MpA0FtCLFM+VrM7ljFSiZbi/7RhqVwc+0+eaSi8IGgQcSYcaiuYbCKNl2BwxxQ2c 27 | urNo3fRQdhYGdf7EA+fRPt/chi4QAn5mEpZTTnrzNlh5sSBC2JY/Nb4/jvKZl0P1 28 | 5AzhPGhyjI1J11pStXP7ejWUOmGwhILASIXBlzLTm3JfoNI0j37wRnzyjHKUxwew 29 | 17WyMLgZZfCcgyewoKvQonJ+BQ+zrt25W5tCvMMmY0VrhvEdRkPtyA== 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /Resource/Certificate/MakeTestCert.bat: -------------------------------------------------------------------------------- 1 | :: Ensure that this is run within a VS command prompt, to ensure that the makecert and pvk2pfx 2 | :: tools are available. 3 | makecert -r -pe -n "CN=OcuSpecTest" -sv OcuSpec.pvk OcuSpec.cer 4 | erase *.pfx 5 | pvk2pfx -pvk OcuSpec.pvk -spc OcuSpec.cer -pfx OcuSpec.pfx -po "password" -------------------------------------------------------------------------------- /Resource/Certificate/Readme.txt: -------------------------------------------------------------------------------- 1 | This directory, by default, contains a self-signed certificate not protected by any type of password. If you would like to use a real software signing certificate (as is required for driver distribution) simply replace the test-signing certificate shown here with the code signing certificate of your choosing. The Microsoft Verisign Class 3 cross-signing certificate is already provided here. 2 | 3 | Be sure that the appropriate cross signing certificate is also available to the catalog file generator, or you will not be able to install drivers. 4 | 5 | Finally, if your code signing certificate is protected by a password, be sure to set the "CertPass" environment macro to this password in the Visual Studio property sheet, reachable here: 6 | 7 | View->Property Manager 8 | Find "CryptoSettings" 9 | Right-click, Properties 10 | User Macros 11 | Double-click "CertPass" 12 | Change password as required 13 | 14 | All of the certificates in this directory can be regenerated by running "MakeTestCert.bat" in a Visual Studio command prompt. -------------------------------------------------------------------------------- /TestHarness/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : TestHarness Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this TestHarness application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your TestHarness application. 9 | 10 | 11 | TestHarness.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | TestHarness.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | TestHarness.cpp 25 | This is the main application source file. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other standard files: 29 | 30 | StdAfx.h, StdAfx.cpp 31 | These files are used to build a precompiled header (PCH) file 32 | named TestHarness.pch and a precompiled types file named StdAfx.obj. 33 | 34 | ///////////////////////////////////////////////////////////////////////////// 35 | Other notes: 36 | 37 | AppWizard uses "TODO:" comments to indicate parts of the source code you 38 | should add to or customize. 39 | 40 | ///////////////////////////////////////////////////////////////////////////// 41 | -------------------------------------------------------------------------------- /TestHarness/TestHarness.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "../OcuInterface/OcuInterface.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #define MAX_CONTACTS 3 11 | 12 | enum eMenuOption 13 | { 14 | eMOFingerTap, 15 | eMOFingerTapSlow, 16 | eMOFingerTwoTap, 17 | eMOTryZoom, 18 | eMOTryZoomExit, 19 | eMOSimulateMouse, 20 | eMORingOfMultiTouch, 21 | eMORingOfTouch, 22 | eMOExit 23 | }; 24 | 25 | eMenuOption PrintMenu() 26 | { 27 | for(;;) 28 | { 29 | char* types[] = 30 | { 31 | "250ms finger tap at (0.5, 0.5)", 32 | "750ms finger tap at (0.5, 0.5)", 33 | "250ms finger two-tap at (0.5, 0.5) and (0.5, 0.6)", 34 | "Slow zoom at (0.5, 0.5)", 35 | "Slow zoom at (0.5, 0.5) then exit", 36 | "Simulate a mouse click at (0.5, 0.5)", 37 | "Ring of multitouch operations centered on (0.5, 0.5)", 38 | "Ring of touch operations centered on (0.5, 0.5)" 39 | }; 40 | 41 | cout << "Choose from one of the following to simulate:" << endl; 42 | for(size_t i = 0; i < ARRAYSIZE(types); i++) 43 | cout << setw(2) << i << ") " << types[i] << endl; 44 | 45 | char c; 46 | cin >> c; 47 | 48 | if('0' <= c && c <= '9') 49 | return (eMenuOption)(eMOFingerTap + c - '0'); 50 | 51 | switch(c) 52 | { 53 | case 'x': 54 | return eMOExit; 55 | } 56 | } 57 | } 58 | 59 | void PrintErrorText(eHidStatus rs) 60 | { 61 | wchar_t* errmsg = nullptr; 62 | FormatMessage( 63 | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER, 64 | GetModuleHandle(nullptr), 65 | rs, 66 | 0, 67 | (LPWSTR)&errmsg, 68 | 0, 69 | nullptr 70 | ); 71 | 72 | cout << "Error, result was 0x" << setw(8) << setfill('0') << hex << rs << endl; 73 | wcout << L"Error text: " << (errmsg ? errmsg : L"(null)") << endl; 74 | if(errmsg) 75 | LocalFree(errmsg); 76 | } 77 | 78 | int main(int argc, char* argv[]) 79 | { 80 | COcuHidInstance* ocuhid = nullptr; 81 | 82 | // Focus application window test: 83 | { 84 | CFocusAppInfo info; 85 | Sleep(1000); 86 | info.Update(); 87 | wcout << info; 88 | } 89 | 90 | COcuInterface ocu(true); 91 | { 92 | // Eliminate anything that isn't an ocuHID interface: 93 | for(auto q = ocu.begin(); q != ocu.end();) 94 | if(FAILED((*q)->Initialize())) 95 | q = ocu.erase(q); 96 | else 97 | q++; 98 | 99 | cout << "Detected " << ocu.size() << " Leap Motion HID interfaces" << endl; 100 | if(!ocu.size()) 101 | { 102 | _getch(); 103 | return -1; 104 | } 105 | 106 | ocuhid = ocu[0]; 107 | } 108 | 109 | auto type = PrintMenu(); 110 | cout << "Waiting 1s before starting..."; 111 | Sleep(1000); 112 | cout << "OK" << endl; 113 | 114 | for(;;) 115 | { 116 | eHidStatus rs; 117 | switch(type) 118 | { 119 | case eMOFingerTap: 120 | case eMOFingerTapSlow: 121 | rs = ocuhid->SendReport(0, true, 0.5, 0.5); 122 | if(SUCCEEDED(rs)) 123 | cout << "Simulating touch click. Down..."; 124 | else 125 | break; 126 | Sleep(type == eMOFingerTapSlow ? 750 : 250); 127 | rs = ocuhid->SendReport(0, false, 0.5, 0.5); 128 | if(SUCCEEDED(rs)) 129 | cout << "up" << endl; 130 | break; 131 | case eMOFingerTwoTap: 132 | rs = ocuhid->SendReport(0, true, 0.5, 0.5); 133 | if(!SUCCEEDED(rs)) 134 | break; 135 | cout << "Simulating touch click. Down, "; 136 | 137 | rs = ocuhid->SendReport(1, true, 0.6, 0.5); 138 | if(!SUCCEEDED(rs)) 139 | break; 140 | cout << "Down..." << endl; 141 | 142 | Sleep(250); 143 | 144 | rs = ocuhid->SendReport(0, false, 0.5, 0.5); 145 | if(SUCCEEDED(rs)) 146 | break; 147 | cout << "Up, "; 148 | 149 | rs = ocuhid->SendReport(1, false, 0.6, 0.5); 150 | if(SUCCEEDED(rs)) 151 | break; 152 | cout << "Up" << endl; 153 | break; 154 | case eMOTryZoom: 155 | case eMOTryZoomExit: 156 | rs = ocuhid->Zoom(0.5, 0.5, 0.1, 2000.0); 157 | if(type == eMOTryZoomExit) 158 | return 0; 159 | break; 160 | case eMOSimulateMouse: 161 | rs = ocuhid->SendReportMouse(true, false, 0.5, 0.5); 162 | if(SUCCEEDED(rs)) 163 | cout << "Simulating mouse click. Down..."; 164 | else 165 | break; 166 | Sleep(250); 167 | rs = ocuhid->SendReportMouse(false, false, 0.5, 0.5); 168 | if(SUCCEEDED(rs)) 169 | cout << "up" << endl; 170 | break; 171 | case eMORingOfMultiTouch: 172 | case eMORingOfTouch: 173 | for(byte cid = 0; ;) 174 | { 175 | double x = 0.5 + 0.1 * sin(cid * M_PI * 2 / 7); 176 | double y = 0.5 + 0.1 * cos(cid * M_PI * 2 / 7); 177 | 178 | bool bDown = type == eMORingOfMultiTouch ? cid < MAX_CONTACTS : cid & 1; 179 | byte touch = type == eMORingOfMultiTouch ? cid % MAX_CONTACTS : 0; 180 | 181 | rs = ocuhid->SendReport(touch, bDown, x, y); 182 | if(SUCCEEDED(rs)) 183 | cout << "Touch (" << 184 | (int)(x * 100) << ", " << 185 | (int)(y * 100) << ") " << 186 | setw(2) << (int)touch << " " << (bDown ? "down" : "up") << endl; 187 | else 188 | break; 189 | 190 | Sleep(250); 191 | cid = (cid + 1) % (MAX_CONTACTS * 2); 192 | } 193 | break; 194 | case eMOExit: 195 | return 0; 196 | } 197 | Sleep(1000); 198 | 199 | if(!SUCCEEDED(rs)) 200 | cout << "Failed to write to the HID, error was " << setw(8) << hex << rs << ", gle was " << GetLastError() << endl; 201 | } 202 | 203 | return 0; 204 | } 205 | 206 | -------------------------------------------------------------------------------- /TestHarness/TestHarness.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 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | -------------------------------------------------------------------------------- /TestHarness/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // TestHarness.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /TestHarness/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "targetver.h" 4 | 5 | #include 6 | #include 7 | #define _USE_MATH_DEFINES 8 | -------------------------------------------------------------------------------- /TestHarness/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 | 10 | -------------------------------------------------------------------------------- /TouchDisplay/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | WIN32 APPLICATION : TouchDisplay Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this TouchDisplay application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your TouchDisplay application. 9 | 10 | 11 | TouchDisplay.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | TouchDisplay.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | TouchDisplay.cpp 25 | This is the main application source file. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | AppWizard has created the following resources: 29 | 30 | TouchDisplay.rc 31 | This is a listing of all of the Microsoft Windows resources that the 32 | program uses. It includes the icons, bitmaps, and cursors that are stored 33 | in the RES subdirectory. This file can be directly edited in Microsoft 34 | Visual C++. 35 | 36 | Resource.h 37 | This is the standard header file, which defines new resource IDs. 38 | Microsoft Visual C++ reads and updates this file. 39 | 40 | TouchDisplay.ico 41 | This is an icon file, which is used as the application's icon (32x32). 42 | This icon is included by the main resource file TouchDisplay.rc. 43 | 44 | small.ico 45 | This is an icon file, which contains a smaller version (16x16) 46 | of the application's icon. This icon is included by the main resource 47 | file TouchDisplay.rc. 48 | 49 | ///////////////////////////////////////////////////////////////////////////// 50 | Other standard files: 51 | 52 | StdAfx.h, StdAfx.cpp 53 | These files are used to build a precompiled header (PCH) file 54 | named TouchDisplay.pch and a precompiled types file named StdAfx.obj. 55 | 56 | ///////////////////////////////////////////////////////////////////////////// 57 | Other notes: 58 | 59 | AppWizard uses "TODO:" comments to indicate parts of the source code you 60 | should add to or customize. 61 | 62 | ///////////////////////////////////////////////////////////////////////////// 63 | -------------------------------------------------------------------------------- /TouchDisplay/TouchDisplay.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | -------------------------------------------------------------------------------- /TouchDisplay/TouchDisplay.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/TouchDisplay/TouchDisplay.ico -------------------------------------------------------------------------------- /TouchDisplay/TouchDisplay.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/TouchDisplay/TouchDisplay.rc -------------------------------------------------------------------------------- /TouchDisplay/TouchDisplay.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 | 20 | Resource Files 21 | 22 | 23 | Resource Files 24 | 25 | 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | 55 | 56 | Resource Files 57 | 58 | 59 | -------------------------------------------------------------------------------- /TouchDisplay/TouchRepresentation.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "TouchRepresentation.h" 3 | 4 | TouchRepresentation::TouchRepresentation(HWND relTo, const TOUCHINPUT& input): 5 | m_bMouseClick(false), 6 | m_dwID(input.dwID) 7 | { 8 | m_pt.x = input.x / 100; 9 | m_pt.y = input.y / 100; 10 | 11 | // Translate to screen coordinates 12 | ScreenToClient(relTo, &m_pt); 13 | } 14 | 15 | TouchRepresentation::TouchRepresentation(const POINT& pt): 16 | m_bMouseClick(true), 17 | m_pt(pt), 18 | m_dwID(~0) 19 | { 20 | } 21 | 22 | bool TouchRepresentation::Translate(vector& out, HWND relTo, WPARAM wParam, LPARAM lParam) 23 | { 24 | TOUCHINPUT rs[16]; 25 | if(!GetTouchInputInfo((HTOUCHINPUT)lParam, ARRAYSIZE(rs), rs, sizeof(rs[0]))) 26 | return false; 27 | 28 | for(size_t i = 0; i < (wParam & 0xFFFF); i++) 29 | out.push_back(TouchRepresentation(relTo, rs[i])); 30 | return true; 31 | } -------------------------------------------------------------------------------- /TouchDisplay/TouchRepresentation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | using std::vector; 5 | 6 | class TouchRepresentation 7 | { 8 | public: 9 | TouchRepresentation(HWND relTo, const TOUCHINPUT& input); 10 | TouchRepresentation(const POINT& pt); 11 | 12 | private: 13 | bool m_bMouseClick; 14 | POINT m_pt; 15 | DWORD m_dwID; 16 | 17 | public: 18 | bool IsMouseClick(void) const {return m_bMouseClick;} 19 | int GetX(void) const {return m_pt.x;} 20 | int GetY(void) const {return m_pt.y;} 21 | DWORD GetID(void) const {return m_dwID;} 22 | 23 | static bool Translate(vector& out, HWND relTo, WPARAM wParam, LPARAM lParam); 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /TouchDisplay/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/TouchDisplay/resource.h -------------------------------------------------------------------------------- /TouchDisplay/small.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/TouchDisplay/small.ico -------------------------------------------------------------------------------- /TouchDisplay/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // TouchDisplay.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /TouchDisplay/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "targetver.h" 4 | 5 | // Windows Header Files: 6 | #include 7 | 8 | // C RunTime Header Files 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifndef ASSERT 15 | #define ASSERT _ASSERT 16 | #endif 17 | -------------------------------------------------------------------------------- /TouchDisplay/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 | -------------------------------------------------------------------------------- /WinDDK.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | C:\WinDDK\7600.16385.1\ 6 | 7 | 8 | 9 | 10 | WINDDK_DIR="$(WINDDK)";%(PreprocessorDefinitions) 11 | 12 | 13 | 14 | 15 | $(WINDDK) 16 | 17 | 18 | -------------------------------------------------------------------------------- /contrib/amd64/hid.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/contrib/amd64/hid.lib -------------------------------------------------------------------------------- /contrib/i386/hid.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/contrib/i386/hid.lib -------------------------------------------------------------------------------- /newdev/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | IMPORT LIBRARY: newdev Project Overview 3 | ======================================================================== 4 | 5 | This is an import library for newdev.dll which supplies to the Installer a few 6 | import names that would have to be delay-linked otherwise. -------------------------------------------------------------------------------- /newdev/newdev.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "newdev.h" 3 | 4 | BOOL WINAPI InstallSelectedDriver( 5 | HWND hwndParent, 6 | HDEVINFO DeviceInfoSet, 7 | LPCTSTR Reserved, 8 | BOOL Backup, 9 | PDWORD bReboot 10 | ) 11 | { 12 | // This return will never be hit. The only purpose of this project is to enable dependencies 13 | // to dynamically link (instead of delay-load) with newdev.dll 14 | return false; 15 | } 16 | -------------------------------------------------------------------------------- /newdev/newdev.def: -------------------------------------------------------------------------------- 1 | LIBRARY newdev.dll 2 | EXPORTS 3 | InstallSelectedDriver -------------------------------------------------------------------------------- /newdev/newdev.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" { 4 | 5 | BOOL WINAPI InstallSelectedDriver( 6 | HWND hwndParent, 7 | HDEVINFO DeviceInfoSet, 8 | LPCTSTR Reserved, 9 | BOOL Backup, 10 | PDWORD bReboot 11 | ); 12 | 13 | } -------------------------------------------------------------------------------- /newdev/newdev.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 | 20 | Resource Files 21 | 22 | 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /newdev/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | -------------------------------------------------------------------------------- /newdev/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include -------------------------------------------------------------------------------- /tools/HCLIENT.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/HCLIENT.EXE -------------------------------------------------------------------------------- /tools/dt/BatSys.upg: -------------------------------------------------------------------------------- 1 | Battery System 2 | NORMAL 3 | 00 Undefined 4 | 01 SMBBatteryMode 5 | 02 SMBBatteryStatus 6 | 03 SMBAlarmWarning 7 | 04 SMBChargerMode 8 | 05 SMBChargerStatus 9 | 06 SMBChargerSpecInfo 10 | 07 SMBSelectorState 11 | 08 SMBSelectorPreset 12 | 09 SMBSelectorInfo 13 | 0A-0F Reserved 14 | 10 OptionalMfgFunction1 15 | 11 OptionalMfgFunction2 16 | 12 OptionalMfgFunction3 17 | 13 OptionalMfgFunction4 18 | 14 OptionalMfgFunction5 19 | 15 ConnectionToSMBus 20 | 16 OutputConnection 21 | 17 ChargerConnection 22 | 18 BatteryInsertion 23 | 19 Usenext 24 | 1A OKToUse 25 | 1B-27 Reserved 26 | 28 ManufacturerAccess 27 | 29 RemainingCapacityLimit 28 | 2A RemainingTimeLimit 29 | 2B AtRate 30 | 2C CapacityMode 31 | 2D BroadcastToCharger 32 | 2E PrimaryBattery 33 | 2F ChargeController 34 | 30-3F Reserved 35 | 40 TerminateCharge 36 | 41 TermminateDischarge 37 | 42 BelowRemainingCapacityLimit 38 | 43 RemainingTimeLimitExpired 39 | 44 Charging 40 | 45 Discharging 41 | 46 FullyCharged 42 | 47 FullyDischarged 43 | 48 ConditionningFlag 44 | 49 AtRateOK 45 | 4A SMBErrorCode 46 | 4B NeedReplacement 47 | 4C-5F Reserved 48 | 60 AtRateTimeToFull 49 | 61 AtRateTimeToEmpty 50 | 62 AverageCurrent 51 | 63 Maxerror 52 | 64 RelativeStateOfCharge 53 | 65 AbsoluteStateOfCharge 54 | 66 RemainingCapacity 55 | 67 FullChargeCapacity 56 | 68 RunTimeToEmpty 57 | 69 AverageTimeToEmpty 58 | 6A AverageTimeToFull 59 | 6B CycleCount 60 | 6C-7F Reserved 61 | 80 BattPackModelLevel 62 | 81 InternalChargeController 63 | 82 PrimaryBatterySupport 64 | 83 DesignCapacity 65 | 84 SpecificationInfo 66 | 85 ManufacturerDate 67 | 86 SerialNumber 68 | 87 iManufacturerName 69 | 88 iDevicename 70 | 89 iDeviceChemistery 71 | 8A iManufacturerData 72 | 8B Rechargeable 73 | 8C WarningCapacityLimit 74 | 8D CapacityGranularity1 75 | 8E CapacityGranularity2 76 | 8F-AF Reserved 77 | B0-BF Reserved 78 | C0 InhibitCharge 79 | C1 EnablePolling 80 | C2 ResetToZero 81 | C3-CF Reserved 82 | D0 ACPresent 83 | D1 BatteryPresent 84 | D2 PowerFail 85 | D3 AlarmInhibited 86 | D4 ThermistorUnderRange 87 | D5 ThermistorHot 88 | D6 ThermistorCold 89 | D7 ThermistorOverRange 90 | D8 VoltageOutOfRange 91 | D9 CurrentOutOfRange 92 | DA CurrentNotRegulated 93 | DB VoltageNotRegulated 94 | DC MasterMode 95 | DD ChargerBattery/HostControlled 96 | DE-EF Reserved 97 | F0 ChargerSpecInfo 98 | F1 ChargerSpecRef 99 | F2 Level2 100 | F3 Level3 101 | F2-FF Reserved 102 | -------------------------------------------------------------------------------- /tools/dt/Dt.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/Dt.exe -------------------------------------------------------------------------------- /tools/dt/PwrDev.upg: -------------------------------------------------------------------------------- 1 | Power Device 2 | NORMAL 3 | 00 Undefined 4 | 01 iName 5 | 02 PresentStatus 6 | 03 ChangedStatus 7 | 04 UPS 8 | 05 PowerSupply 9 | 06-0F Reserved 10 | 10 BatterySystem 11 | 11 BatterySystemID 12 | 12 Battery 13 | 13 BatteryID 14 | 14 Charger 15 | 15 ChargerID 16 | 16 PowerConverter 17 | 17 PowerConverterID 18 | 18 OutletSystem 19 | 19 OutletSystemID 20 | 1A Input 21 | 1B InputID 22 | 1C Output 23 | 1D OutputID 24 | 1E Flow 25 | 1F FlowID 26 | 20 Outlet 27 | 21 OutletID 28 | 22 Gang 29 | 23 GangID 30 | 24 Sink 31 | 25 SinkID 32 | 26-2F Reserved 33 | 30 Voltage 34 | 31 Current 35 | 32 Frequency 36 | 33 ApparentPower 37 | 34 ActivePower 38 | 35 PercentLoad 39 | 36 Temperature 40 | 37 Humidity 41 | 38-3F Reserved 42 | 40 ConfigVoltage 43 | 41 ConfigCurrent 44 | 42 ConfigFrequency 45 | 43 ConfigApparentPower 46 | 44 ConfigActivePower 47 | 45 ConfigPercentLoad 48 | 46 ConfigTemperature 49 | 47 ConfigHumidity 50 | 48-4F Reserved 51 | 50 SwitchOnControl 52 | 51 SwitchOffControl 53 | 52 ToggleControl 54 | 53 LowVoltageTransfer 55 | 54 HighVoltageTransfer 56 | 55 DelayBeforeReboot 57 | 56 DelayBeforeStartup 58 | 57 DelayBeforeShutdown 59 | 58 Test 60 | 59 Vendorspecificcommand 61 | 5A-5F Reserved 62 | 60 Present 63 | 61 Good 64 | 62 InternalFailure 65 | 63 VoltageOutOfRange 66 | 64 FrequencyOutOfRange 67 | 65 Overload 68 | 66 OverCharged 69 | 67 OverTemperature 70 | 68 ShutdownRequested 71 | 69 ShutdownImminent 72 | 6A VendorSpecificAnswerValid 73 | 6B SwitchOn/Off 74 | 6C Switcheble 75 | 6D Used 76 | 6E Boost 77 | 6F Buck 78 | 70 Initialized 79 | 71 Tested 80 | 71-FF Reserved 81 | -------------------------------------------------------------------------------- /tools/dt/Tparse.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/Tparse.dll -------------------------------------------------------------------------------- /tools/dt/Tparse.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/Tparse.lib -------------------------------------------------------------------------------- /tools/dt/VESACmnd.upg: -------------------------------------------------------------------------------- 1 | VESA Command 2 | NORMAL 3 | 00 Undefined 4 | 01 Settings 5 | 02 Degauss 6 | 03-FFFF Reserved 7 | -------------------------------------------------------------------------------- /tools/dt/VESAVC.upg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/VESAVC.upg -------------------------------------------------------------------------------- /tools/dt/andisp.upg: -------------------------------------------------------------------------------- 1 | Alphnumeric Display 2 | NORMAL 3 | 00 Undefined 4 | 01 Alphanumeric Display 5 | 02-1F Reserved 6 | 20 Display Attributes Report 7 | 21 ASCII Character Set 8 | 22 Data Read Back 9 | 23 Font Read Back 10 | 24 Display Control Report 11 | 25 Clear Display 12 | 26 Display Enable 13 | 27 Screen Saver Delay 14 | 28 Screen Saver Enable 15 | 29 Vertical Scroll 16 | 2A Horizontal Scroll 17 | 2B Character Report 18 | 2C Display Data 19 | 2D Display Status 20 | 2E Stat Not Ready 21 | 2F Stat Ready 22 | 30 Err Not a loadable character 23 | 31 Err Font data cannot be read 24 | 32 Cursor Position Report 25 | 33 Row 26 | 34 Column 27 | 35 Rows 28 | 36 Columns 29 | 37 Cursor Pixel Positioning 30 | 38 Cursor Mode 31 | 39 Cursor Enable 32 | 3A Cursor Blink 33 | 3B Font Report 34 | 3C Font Data 35 | 3D Character Width 36 | 3E Character Height 37 | 3F Character Spacing Horizontal 38 | 40 Character Spacing Vertical 39 | 41 Unicode Character Set 40 | 42-FFFF Reserved 41 | -------------------------------------------------------------------------------- /tools/dt/andisply.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/andisply.hid -------------------------------------------------------------------------------- /tools/dt/button.upg: -------------------------------------------------------------------------------- 1 | Button 2 | REPEATING 3 | 00 No Buttons Pressed 4 | 01 Button 5 | -------------------------------------------------------------------------------- /tools/dt/consume.upg: -------------------------------------------------------------------------------- 1 | Consumer Devices 2 | NORMAL 3 | 00 Unassigned 4 | 01 Consumer Control 5 | 02 Numeric Key Pad 6 | 04-1F Reserved 7 | 20 +10 8 | 21 +100 9 | 22 AM/PM 10 | 23-3F Reserved 11 | 30 Power 12 | 31 Reset 13 | 32 Sleep 14 | 33 Sleep After 15 | 34 Sleep Mode 16 | 35 Illumination 17 | 36 Function Buttons 18 | 37-3F Reserved 19 | 40 Menu 20 | 41 Menu Pick 21 | 42 Menu Up 22 | 43 Menu Down 23 | 44 Menu Left 24 | 45 Menu Right 25 | 46 Menu Escape 26 | 47 Menu Value Increase 27 | 48 Menu Value Decrease 28 | 49-5F Reserved 29 | 60 Data On Screen 30 | 61 Closed Caption 31 | 62 Closed Caption Select 32 | 63 VCR/TV 33 | 64 Broadcast Mode 34 | 65 Snapshot 35 | 66 Still 36 | 67-7F Reserved 37 | 80 Selection 38 | 81 Assign Selection 39 | 82 Mode Step 40 | 83 Recall Last 41 | 84 Enter Channel 42 | 85 Order Movie 43 | 86 Channel 44 | 87 Media Selection 45 | 88 Media Select Computer 46 | 89 Media Select TV 47 | 8A Media Select WWW 48 | 8B Media Select DVD 49 | 8C Media Select Telephone 50 | 8D Media Select Program Guide 51 | 8E Media Select Video Phone 52 | 8F Media Select Games 53 | 90 Media Select Messages 54 | 91 Media Select CD 55 | 92 Media Select VCR 56 | 93 Media Select Tuner 57 | 94 Quit 58 | 95 Help 59 | 96 Media Select Tape 60 | 97 Media Select Cable 61 | 98 Media Select Satellite 62 | 99 Media Select Security 63 | 9A Media Select Home 64 | 9B Media Select Call 65 | 9C Channel Increment 66 | 9D Channel Decrement 67 | 9E-9F Reserved 68 | A0 VCR Plus 69 | A1 Once 70 | A2 Daily 71 | A3 Weekly 72 | A4 Monthly 73 | A5-AF Reserved 74 | B0 Play 75 | B1 Pause 76 | B2 Record 77 | B3 Fast Forward 78 | B4 Rewind 79 | B5 Scan Next Track 80 | B6 Scan Previous Track 81 | B7 Stop 82 | B8 Eject 83 | B9 Random Play 84 | BA Select Disc 85 | BB Enter Disc 86 | BC Repeat 87 | BD Tracking 88 | BE Track Normal 89 | BF Slow Tracking 90 | C0 Frame Forward 91 | C1 Frame Back 92 | C2 Mark 93 | C3 Clear Mark 94 | C4 Repeat From Mark 95 | C5 Return To Mark 96 | C6 Search Mark Forward 97 | C7 Search Mark Backwards 98 | C8 Counter Reset 99 | C9 Show Counter 100 | CA Tracking Increment 101 | CB Tracking Decrement 102 | CC-DF Reserved 103 | E0 Volume 104 | E1 Balance 105 | E2 Mute 106 | E3 Bass 107 | E4 Treble 108 | E5 Bass Boost 109 | E6 Surround Mode 110 | E7 Loudness 111 | E8 MPX 112 | E9 Volume Up 113 | EA Volume Down 114 | EB-EF Reserved 115 | F0 Speed Select 116 | F1 Playback Speed 117 | F2 Standard Play 118 | F3 Long Play 119 | F4 Extended Play 120 | F5 Slow 121 | F6-FF Reserved 122 | 100 Fan Enable 123 | 101 Fan Speed 124 | 102 Light 125 | 103 Light Illumination Level 126 | 104 Climate Control Enable 127 | 105 Room Temperature 128 | 106 Security Enable 129 | 107 Fire Alarm 130 | 108 Police Alarm 131 | 109-FFFF Reserved 132 | -------------------------------------------------------------------------------- /tools/dt/delimit.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/delimit.hid -------------------------------------------------------------------------------- /tools/dt/desktop.upg: -------------------------------------------------------------------------------- 1 | Generic Desktop 2 | NORMAL 3 | 00 Undefined 4 | 01 Pointer 5 | 02 Mouse 6 | 03 Reserved 7 | 04 Joystick 8 | 05 Game Pad 9 | 06 Keyboard 10 | 07 Keypad 11 | 08-2F Reserved 12 | 30 X 13 | 31 Y 14 | 32 Z 15 | 33 Rx 16 | 34 Ry 17 | 35 Rz 18 | 36 Slider 19 | 37 Dial 20 | 38 Wheel 21 | 39 Hat switch 22 | 3A Counted Buffer 23 | 3B Byte Count 24 | 3C Motion Wakeup 25 | 3D-3F Reserved 26 | 40 Vx 27 | 41 Vy 28 | 42 Vz 29 | 43 Vbrx 30 | 44 Vbry 31 | 45 Vbrx 32 | 46 Vno 33 | 47-7F Reserved 34 | 80 System Control 35 | 81 System Power Down 36 | 82 System Sleep 37 | 83 System Wake Up 38 | 84 System Context Menu 39 | 85 System Main Menu 40 | 86 System App Menu 41 | 87 System Help Menu 42 | 88 System Menu Exit 43 | 89 System Menu Select 44 | 8A System Menu Right 45 | 8B System Menu Left 46 | 8C System Menu Up 47 | 8D System Menu Down 48 | 8E-FFFF Reserved 49 | -------------------------------------------------------------------------------- /tools/dt/digit.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/digit.hid -------------------------------------------------------------------------------- /tools/dt/digit.upg: -------------------------------------------------------------------------------- 1 | Digitizers 2 | NORMAL 3 | 00 Undefined 4 | 01 Digitizer 5 | 02 Pen 6 | 03 Light Pen 7 | 04 Touch Screen 8 | 05 Touch Pad 9 | 06 White Board 10 | 07 Coordinate Measuring Machine 11 | 08 3-D Digitizer 12 | 09 Stereo Plotter 13 | 0A Articulated Arm 14 | 0B Armature 15 | 0C Multiple Point Digitizer 16 | 0D Free Space Wand 17 | 0E-1F Reserved 18 | 20 Stylus 19 | 21 Puck 20 | 22 Finger 21 | 23-2F Reserved 22 | 30 Tip Pressure 23 | 31 Barrel Pressure 24 | 32 In Range 25 | 33 Touch 26 | 34 Untouch 27 | 35 Tap 28 | 36 Quality 29 | 37 Data Valid 30 | 38 Transducer Index 31 | 39 Tablet Function Keys 32 | 3A Program Change Keys 33 | 3B Battery Strength 34 | 3C Invert 35 | 3D X Tilt 36 | 3E Y Tilt 37 | 3F Azimuth 38 | 40 Altitude 39 | 41 Twist 40 | 42 Tip Switch 41 | 43 Secondary Tip Switch 42 | 44 Barrel Switch 43 | 45 Eraser 44 | 46 Tablet Pick 45 | 47-FFFF Reserved -------------------------------------------------------------------------------- /tools/dt/display.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/display.hid -------------------------------------------------------------------------------- /tools/dt/dt.ini: -------------------------------------------------------------------------------- 1 | [UsagePages] 2 | Count=21 3 | UP0=01,Generic Desktop,desktop.upg 4 | UP1=02,Simulation Controls,sim.upg 5 | UP2=03,VR Controls,vr.upg 6 | UP3=04,Sports Controls,sports.upg 7 | UP4=05,Gaming Controls,gaming.upg 8 | UP5=07,Keyboard,kbd.upg 9 | UP6=08,LEDs,leds.upg 10 | UP7=09,Button,button.upg 11 | UP8=10,Ordinals,ordinal.upg 12 | UP9=11,Telephony Devices,tele.upg 13 | UP10=12,Consumer Devices,consume.upg 14 | UP11=13,Digitizers,digit.upg 15 | UP12=16,Unicode,unicode.upg 16 | UP13=20,Alphnumeric Display,andisp.upg 17 | UP14=128,Monitor,monitor.upg 18 | UP15=129,Monitor Enumerated Values,mon_enum.upg 19 | UP16=130,VESA Virtual Controls,VESAVC.upg 20 | UP17=131,VESA Command,VESACmnd.upg 21 | UP18=132,Power Device,pwrdev.upg 22 | UP19=133,Battery System,batsys.upg 23 | UP20=65280,Vendor Defined Page 1,vendor1.upg 24 | 25 | 26 | -------------------------------------------------------------------------------- /tools/dt/gaming.upg: -------------------------------------------------------------------------------- 1 | Gaming Controls 2 | NORMAL 3 | 00 Undefined 4 | 01 3D Game Controller 5 | 02 Pinball Device 6 | 03 Gun Device 7 | 04-1F Reserved 8 | 20 Point of View 9 | 21 Turn Right/Left 10 | 22 Pitch Right/Left 11 | 23 Roll Forward/Backward 12 | 24 Move Right/Left 13 | 25 Move Forward/Backward 14 | 26 Move Up/Down 15 | 27 Lean Right/Left 16 | 28 Lean Forward/Backward 17 | 29 Height of POV 18 | 2A Flipper 19 | 2B Secondary Flipper 20 | 2C Bump 21 | 2D New Game 22 | 2E Shoot Ball 23 | 2F Player 24 | 30 Gun Bolt 25 | 31 Gun Clip 26 | 32 Gun Selector 27 | 33 Gun Single Shot 28 | 34 Gun Burst 29 | 35 Gun Automatic 30 | 36 Gun Safety 31 | 37-FFFF reserved -------------------------------------------------------------------------------- /tools/dt/joystk.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/joystk.hid -------------------------------------------------------------------------------- /tools/dt/kbd.upg: -------------------------------------------------------------------------------- 1 | Keyboard 2 | NORMAL 3 | 00 Reserved (no event indicated) 4 | 01 Keyboard ErrorRollOver 5 | 02 Keyboard POSTFail 6 | 03 Keyboard ErrorUndefine 7 | 04 Keyboard a and A 8 | 05 Keyboard b and B 9 | 06 Keyboard c and C 10 | 07 Keyboard d and D 11 | 08 Keyboard e and E 12 | 09 Keyboard f and F 13 | 0A Keyboard g and G 14 | 0B Keyboard h and H 15 | 0C Keyboard i and I 16 | 0D Keyboard j and J 17 | 0E Keyboard k and K 18 | 0F Keyboard l and L 19 | 10 Keyboard m and M 20 | 11 Keyboard n and N 21 | 12 Keyboard o and O 22 | 13 Keyboard p and P 23 | 14 Keyboard q and Q 24 | 15 Keyboard r and R 25 | 16 Keyboard s and S 26 | 17 Keyboard t and T 27 | 18 Keyboard u and U 28 | 19 Keyboard v and V 29 | 1A Keyboard w and W 30 | 1B Keyboard x and X 31 | 1C Keyboard y and Y 32 | 1D Keyboard z and Z 33 | 1E Keyboard 1 and ! 34 | 1F Keyboard 2 and @ 35 | 20 Keyboard 3 and # 36 | 21 Keyboard 4 and $ 37 | 22 Keyboard 5 and % 38 | 23 Keyboard 6 and ^ 39 | 24 Keyboard 7 and & 40 | 25 Keyboard 8 and * 41 | 26 Keyboard 9 and ( 42 | 27 Keyboard 0 and ) 43 | 28 Keyboard Return (ENTER) 44 | 29 Keyboard ESCAPE 45 | 2A Keyboard DELETE (Backspace) 46 | 2B Keyboard Tab 47 | 2C Keyboard Spacebar 48 | 2D Keyboard - and (underscore) 49 | 2E Keyboard = and + 50 | 2F Keyboard [ and { 51 | 30 Keyboard ] and } 52 | 31 Keyboard \ and | 53 | 32 Keyboard Non-US # and ~ 54 | 33 Keyboard ; and : 55 | 34 Keyboard ' and " 56 | 35 Keyboard Grave Accent and Tilde 57 | 36 Keyboard, and < 58 | 37 Keyboard . and > 59 | 38 Keyboard / and ? 60 | 39 Keyboard Caps Lock 61 | 3A Keyboard F1 62 | 3B Keyboard F2 63 | 3C Keyboard F3 64 | 3D Keyboard F4 65 | 3E Keyboard F5 66 | 3F Keyboard F6 67 | 40 Keyboard F7 68 | 41 Keyboard F8 69 | 42 Keyboard F9 70 | 43 Keyboard F10 71 | 44 Keyboard F11 72 | 45 Keyboard F12 73 | 46 Keyboard PrintScreen 74 | 47 Keyboard Scroll Lock 75 | 48 Keyboard Pause 76 | 49 Keyboard Insert 77 | 4A Keyboard Home 78 | 4B Keyboard PageUp 79 | 4C Keyboard Delete Forward 80 | 4D Keyboard End 81 | 4E Keyboard PageDown 82 | 4F Keyboard RightArrow 83 | 50 Keyboard LeftArrow 84 | 51 Keyboard DownArrow 85 | 52 Keyboard UpArrow 86 | 53 Keypad Num Lock and Clear 87 | 54 Keypad / 88 | 55 Keypad * 89 | 56 Keypad - 90 | 57 Keypad + 91 | 58 Keypad ENTER 92 | 59 Keypad 1 and End 93 | 5A Keypad 2 and Down Arrow 94 | 5B Keypad 3 and PageDn 95 | 5C Keypad 4 and Left Arrow 96 | 5D Keypad 5 97 | 5E Keypad 6 and Right Arrow 98 | 5F Keypad 7 and Home 99 | 60 Keypad 8 and Up Arrow 100 | 61 Keypad 9 and PageUp 101 | 62 Keypad 0 and Insert 102 | 63 Keypad . and Delete 103 | 64 Keyboard Non-US \ and | 104 | 65 Keyboard Application 105 | 66 Keyboard Power 106 | 67 Keypad = 107 | 68 Keyboard F13 108 | 69 Keyboard F14 109 | 6A Keyboard F15 110 | 6B Keyboard F16 111 | 6C Keyboard F17 112 | 6D Keyboard F18 113 | 6E Keyboard F19 114 | 6F Keyboard F20 115 | 70 Keyboard F21 116 | 71 Keyboard F22 117 | 72 Keyboard F23 118 | 73 Keyboard F24 119 | 74 Keyboard Execute 120 | 75 Keyboard Help 121 | 76 Keyboard Menu 122 | 77 Keyboard Select 123 | 78 Keyboard Stop 124 | 79 Keyboard Again 125 | 7A Keyboard Undo 126 | 7B Keyboard Cut 127 | 7C Keyboard Copy 128 | 7D Keyboard Paste 129 | 7E Keyboard Find 130 | 7F Keyboard Mute 131 | 80 Keyboard Volume Up 132 | 81 Keyboard Volume Down 133 | 82 Keyboard Locking Caps Lock 134 | 83 Keyboard Locking Num Lock 135 | 84 Keyboard Locking Scroll Lock 136 | 85 Keypad Comma 137 | 86 Keypad Equal Sign 138 | 87 Keyboard Kanji1 139 | 88 Keyboard Kanji2 140 | 89 Keyboard Kanji3 141 | 8A Keyboard Kanji4 142 | 8B Keyboard Kanji5 143 | 8C Keyboard Kanji6 144 | 8D Keyboard Kanji7 145 | 8E Keyboard Kanji8 146 | 8F Keyboard Kanji9 147 | 90 Keyboard LANG1 148 | 91 Keyboard LANG2 149 | 92 Keyboard LANG3 150 | 93 Keyboard LANG4 151 | 94 Keyboard LANG5 152 | 95 Keyboard LANG6 153 | 96 Keyboard LANG7 154 | 97 Keyboard LANG8 155 | 98 Keyboard LANG9 156 | 99 Keyboard Alternate Erase 157 | 9A Keyboard SysReq/Attention 158 | 9B Keyboard Cancel 159 | 9C Keyboard Clear 160 | 9D Keyboard Prior 161 | 9E Keyboard Return 162 | 9F Keyboard Separator 163 | A0 Keyboard Out 164 | A1 Keyboard Oper 165 | A2 Keyboard Clear/Again 166 | A3 Keyboard CrSel/Props 167 | A4 Keyboard ExSel 168 | A5-DF Reserved 169 | E0 Keyboard LeftControl 170 | E1 Keyboard LeftShift 171 | E2 Keyboard LeftAlt 172 | E3 Keyboard Left GUI 173 | E4 Keyboard RightControl 174 | E5 Keyboard RightShift 175 | E6 Keyboard RightAlt 176 | E7 Keyboard Right GUI 177 | E8-FFFF Reserved 178 | -------------------------------------------------------------------------------- /tools/dt/keybrd.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/keybrd.hid -------------------------------------------------------------------------------- /tools/dt/leds.upg: -------------------------------------------------------------------------------- 1 | LEDs 2 | NORMAL 3 | 00 Undefined 4 | 01 Num Lock 5 | 02 Caps Lock 6 | 03 Scroll Lock 7 | 04 Compose 8 | 05 Kana 9 | 06 Power 10 | 07 Shift 11 | 08 Do Not Disturb 12 | 09 Mute 13 | 0A Tone Enable 14 | 0B High Cut Filter 15 | 0C Low Cut Filter 16 | 0D Equalizer Enable 17 | 0E Sound Field On 18 | 0F Surround field On 19 | 10 Repeat 20 | 11 Stereo 21 | 12 Sampling Rate Detect 22 | 13 Spinning 23 | 14 CAV 24 | 15 CLV 25 | 16 Recording Format Detect 26 | 17 Off-Hook 27 | 18 Ring 28 | 19 Message Waiting 29 | 1A Data Mode 30 | 1B Battery Operation 31 | 1C Battery OK 32 | 1D Battery Low 33 | 1E Speaker 34 | 1F Head Set 35 | 20 Hold 36 | 21 Microphone 37 | 22 Coverage 38 | 23 Night Mode 39 | 24 Send Calls 40 | 25 Call Pickup 41 | 26 Conference 42 | 27 Stand-by 43 | 28 Camera On 44 | 29 Camera Off 45 | 2A On-Line 46 | 2B Off-Line 47 | 2C Busy 48 | 2D Ready 49 | 2E Paper-Out 50 | 2F Paper-Jam 51 | 30 Remote 52 | 31 Forward 53 | 32 Reverse 54 | 33 Stop 55 | 34 Rewind 56 | 35 Fast Forward 57 | 36 Play 58 | 37 Pause 59 | 38 Record 60 | 39 Error 61 | 3A Usage Selected Indicator 62 | 3B Usage In Use Indicator 63 | 3C Usage Multi Mode Indicator 64 | 3D Indicator On 65 | 3E Indicator Flash 66 | 3F Indicator Slow Blink 67 | 40 Indicator Fast Blink 68 | 41 Indicator Off 69 | 42 Flash On Time 70 | 43 Slow Blink On Time 71 | 44 Slow Blink Off Time 72 | 45 Fast Blink On Time 73 | 46 Fast Blink Off Time 74 | 47 Usage Indicator Color 75 | 48 Red 76 | 49 Green 77 | 4A Amber 78 | 4B Generic Indicator 79 | 4C-FFFF Reserved -------------------------------------------------------------------------------- /tools/dt/mon_enum.upg: -------------------------------------------------------------------------------- 1 | Monitor Enumerated Values 2 | REPEATING0 3 | 00 unassigned 4 | 01 ENUM 5 | -------------------------------------------------------------------------------- /tools/dt/monitor.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/monitor.hid -------------------------------------------------------------------------------- /tools/dt/monitor.upg: -------------------------------------------------------------------------------- 1 | Monitor 2 | NORMAL 3 | 00 Undefined 4 | 01 Monitor Control 5 | 02 EDID Information 6 | 03 VDIF Information 7 | 04 VESA Version 8 | 05 On Screen Display 9 | 06 Auto Size Center 10 | 07 Polarity Horz Synch 11 | 08 Polarity Vert Synch 12 | 09 Sync Type 13 | 0A Screen Position 14 | 0B Horizontal Frequency 15 | 0C Vertical Frequency 16 | 0D-FFFF Reserved 17 | -------------------------------------------------------------------------------- /tools/dt/mouse.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/mouse.hid -------------------------------------------------------------------------------- /tools/dt/ordinal.upg: -------------------------------------------------------------------------------- 1 | Ordinals 2 | REPEATING 3 | 00 Unused 4 | 01 Instance -------------------------------------------------------------------------------- /tools/dt/pwr.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/pwr.hid -------------------------------------------------------------------------------- /tools/dt/remote.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/remote.hid -------------------------------------------------------------------------------- /tools/dt/sim.upg: -------------------------------------------------------------------------------- 1 | Simulation Controls 2 | NORMAL 3 | 00 Undefined 4 | 01 Flight Simulation Device 5 | 02 Automobile Simulation Device 6 | 03 Tank Simulation Device 7 | 04 Spaceship Simulation Device 8 | 05 Submarine Simulation Device 9 | 06 Sailing Simulation Device 10 | 07 Motorcycle Simulation Device 11 | 08 Sports Simulation Device 12 | 09 Airplane Simulation Device 13 | 0A Helicopter Simulation Device 14 | 0B Magic Carpet Simulation Device 15 | 0C Bicycle 16 | 0D-1F reserved 17 | 20 Flight Control Stick 18 | 21 Flight Stick 19 | 22 Cyclic Control 20 | 23 Cyclic Trim 21 | 24 Flight Yoke 22 | 25 Track Control 23 | 26 Driving Control 24 | 27-CF reserved 25 | B0 Aileron 26 | B1 Aileron Trim 27 | B2 Anti-Torque Control 28 | B3 Auto-pilot enable 29 | B4 Chaff Release 30 | B5 Collective Control 31 | B6 Dive Brake 32 | B7 Electronic Counter Measures 33 | B8 Elevator 34 | B9 Elevator Trim 35 | BA Rudder 36 | BB Throttle 37 | BC Flight Communication 38 | BD Flare Release 39 | BE Landing Gear 40 | BF Toe Brake 41 | C0 Trigger 42 | C1 Weapons Arm 43 | C2 Weapons Select 44 | C3 Wing Flaps 45 | C4 Accelerator 46 | C5 Brake 47 | C6 Clutch 48 | C7 Shifter 49 | C8 Steering 50 | C9 Turret Direction 51 | CA Barrel Elevation 52 | CB Dive Plane 53 | CC Ballast 54 | CD Bicycle Crank 55 | CE Handle Bars 56 | CF Front Brake 57 | D0 Rear Brake 58 | D1-FFFF reserved 59 | -------------------------------------------------------------------------------- /tools/dt/sports.upg: -------------------------------------------------------------------------------- 1 | Sports Controls 2 | NORMAL 3 | 00 Unidentified 4 | 01 Baseball Bat 5 | 02 Golf Club 6 | 03 Rowing Machine 7 | 04 Treadmill 8 | 05-2F Reserved 9 | 30 Oar 10 | 31 Slope 11 | 32 Rate 12 | 33 Stick Speed 13 | 34 Stick Face Angle 14 | 35 Stick Heel/Toe 15 | 36 Stick Follow Through 16 | 37 Stick Tempo 17 | 38 Stick Type 18 | 39 Stick Height 19 | 3A-4F Reserved 20 | 50 Putter 21 | 51 1 Iron 22 | 52 2 Iron 23 | 53 3 Iron 24 | 54 4 Iron 25 | 55 5 Iron 26 | 56 6 Iron 27 | 57 7 Iron 28 | 58 8 Iron 29 | 59 9 Iron 30 | 59 10 Iron 31 | 5A 11 Iron 32 | 5B Sand Wedge 33 | 5C Loft Wedge 34 | 5D Power Wedge 35 | 5E 1 Wood 36 | 5F 3 Wood 37 | 60 5 Wood 38 | 61 7 Wood 39 | 62 9 Wood 40 | 63-FFFF reserved -------------------------------------------------------------------------------- /tools/dt/tele.hid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leapmotion/mt-windows/74854757730c9801766883d13ed97bd9fb1b45bf/tools/dt/tele.hid -------------------------------------------------------------------------------- /tools/dt/tele.upg: -------------------------------------------------------------------------------- 1 | Telephony Devices 2 | NORMAL 3 | 00 Unassigned 4 | 01 Phone 5 | 02 Answering Machine 6 | 03 Message Controls 7 | 04 Handset 8 | 05 Headset 9 | 06 Telephony Key Pad 10 | 07 Programmable Button 11 | 08-1F Reserved 12 | 20 Hook Switch 13 | 21 Flash 14 | 22 Feature 15 | 23 Hold 16 | 24 Redial 17 | 25 Transfer 18 | 26 Drop 19 | 27 Park 20 | 28 Forward Calls 21 | 29 Alternate Function 22 | 2A Line 23 | 2B Speaker Phone 24 | 2C Conference 25 | 2D Ring Enable 26 | 2E Ring Select 27 | 2F Phone Mute 28 | 30 Caller ID 29 | 31-4F Reserved 30 | 50 Speed Dial 31 | 51 Store Number 32 | 52 Recall Number 33 | 53 Phone Directory 34 | 54-6F Reserved 35 | 70 Voice Mail 36 | 71 Screen Calls 37 | 72 Do Not Disturb 38 | 73 Message 39 | 74 Answer On/Off 40 | 75-8F Reserved 41 | 90 Inside Dial Tone 42 | 91 Outside Dial Tone 43 | 92 Inside Ring Tone 44 | 93 Outside Ring Tone 45 | 94 Priority Ring Tone 46 | 95 Inside Ringback 47 | 96 Priority Ringback 48 | 97 Line Busy Tone 49 | 98 Reorder Tone 50 | 99 Call Waiting Tone 51 | 9A Confirmation Tone 1 52 | 9B Confirmation Tone 2 53 | 9C Tones Off 54 | 9D-AF Reserved 55 | B0 Phone Key 0 56 | B1 Phone Key 1 57 | B2 Phone Key 2 58 | B3 Phone Key 3 59 | B4 Phone Key 4 60 | B5 Phone Key 5 61 | B6 Phone Key 6 62 | B7 Phone Key 7 63 | B8 Phone Key 8 64 | B9 Phone Key 9 65 | BA Phone Key Star 66 | BB Phone Key Pound 67 | BC Phone Key A 68 | BD Phone Key B 69 | BE Phone Key C 70 | BF Phone Key D 71 | C0-FFFF Reserved -------------------------------------------------------------------------------- /tools/dt/unicode.upg: -------------------------------------------------------------------------------- 1 | Unicode 2 | REPEATING 3 | 00 Unicode Char 0 4 | 00 Unicode Char -------------------------------------------------------------------------------- /tools/dt/vendor1.upg: -------------------------------------------------------------------------------- 1 | Vendor Defined Page 1 2 | NORMAL 3 | 00 Undefined 4 | 01 Vendor Usage 1 5 | 02 Vendor Usage 2 6 | 03-FFFF Reserved 7 | -------------------------------------------------------------------------------- /tools/dt/vr.upg: -------------------------------------------------------------------------------- 1 | VR Controls 2 | NORMAL 3 | 00 Unidentified 4 | 01 Belt 5 | 02 Body Suit 6 | 03 Flexor 7 | 04 Glove 8 | 05 Head Tracker 9 | 06 Head Mounted Display 10 | 07 Hand Tracker 11 | 08 Oculometer 12 | 09 Vest 13 | 0A Animatronic Device 14 | 0B-1F Reserved 15 | 20 Stereo Enable 16 | 21 Display Enable 17 | 22-FFFF Reserved 18 | --------------------------------------------------------------------------------