spnav_win32_test
changeset 0:21f1554e2884
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 07 Jul 2013 04:21:49 +0300 |
parents | |
children | 55a06a416ca8 |
files | .hgignore main.cpp spnav_winapi_test.sln spnav_winapi_test.vcproj |
diffstat | 4 files changed, 461 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Sun Jul 07 04:21:49 2013 +0300 1.3 @@ -0,0 +1,6 @@ 1.4 +\.o$ 1.5 +\.d$ 1.6 +\.swp$ 1.7 +\.suo$ 1.8 +^Debug/ 1.9 +^Release/
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/main.cpp Sun Jul 07 04:21:49 2013 +0300 2.3 @@ -0,0 +1,238 @@ 2.4 +#include <stdio.h> 2.5 +#include <stdlib.h> 2.6 +#include <signal.h> 2.7 +#include <assert.h> 2.8 +#include <windows.h> 2.9 +extern "C" { 2.10 +#include <hidsdi.h> 2.11 +#include <setupapi.h> 2.12 +} 2.13 + 2.14 +typedef __int16 int16_t; 2.15 +typedef unsigned __int32 uint32_t; 2.16 + 2.17 +/* TODO: notification 2.18 + Obtain the Windows GUID for HID devices by way of a call to HidD_GetHidGuid() 2.19 + Clear the contents of a DEV_BROADCAST_DEVICEINTERFACE structure 0. 2.20 + Assign the members of the structure such that you specify the HID GUID. 2.21 + Register the application for device notifications by calling the function RegisterDeviceNotification(). 2.22 + If the previous step returns an invalid handle, then an error has occurred, and the function should return an error. Otherwise, the return is successful. 2.23 +*/ 2.24 + 2.25 +#pragma pack(push, 1) 2.26 +union Report { 2.27 + unsigned char type; 2.28 + 2.29 + struct { int16_t x, y, z; } motion; 2.30 + struct { uint32_t state; } button; 2.31 +}; 2.32 +#pragma pack(pop) 2.33 + 2.34 +static int WINAPI console_handler(DWORD s); 2.35 + 2.36 +bool done; 2.37 + 2.38 +int main() 2.39 +{ 2.40 + HANDLE dev_handle = 0; 2.41 + Report *report = 0; 2.42 + 2.43 + GUID hid_guid; 2.44 + HidD_GetHidGuid(&hid_guid); 2.45 + 2.46 + HDEVINFO devs = SetupDiGetClassDevs(&hid_guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 2.47 + if(!devs) { 2.48 + fprintf(stderr, "failed to retrieve all USB HID devices\n"); 2.49 + return 1; 2.50 + } 2.51 + 2.52 + for(int i=0; ; i++) { 2.53 + SP_DEVICE_INTERFACE_DATA dev_data; 2.54 + dev_data.cbSize = sizeof dev_data; 2.55 + 2.56 + if(!SetupDiEnumDeviceInterfaces(devs, 0, &hid_guid, i, &dev_data)) { 2.57 + if(GetLastError() != ERROR_NO_MORE_ITEMS) { 2.58 + fprintf(stderr, "failed to enumarate device %d\n", i); 2.59 + } 2.60 + break; 2.61 + } 2.62 + 2.63 + DWORD bufsz; 2.64 + SetupDiGetDeviceInterfaceDetail(devs, &dev_data, 0, 0, &bufsz, 0); 2.65 + 2.66 + SP_DEVICE_INTERFACE_DETAIL_DATA *dev_details = (SP_DEVICE_INTERFACE_DETAIL_DATA*)malloc(bufsz); 2.67 + assert(dev_details); 2.68 + dev_details->cbSize = sizeof *dev_details; 2.69 + 2.70 + if(!SetupDiGetDeviceInterfaceDetail(devs, &dev_data, dev_details, bufsz, &bufsz, 0)) { 2.71 + int err = GetLastError(); 2.72 + fprintf(stderr, "failed to get interface %d details\n", i); 2.73 + continue; 2.74 + } 2.75 + dev_handle = CreateFile(dev_details->DevicePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); 2.76 + if(!dev_handle) { 2.77 + fprintf(stderr, "failed to open device file: %s\n", dev_details->DevicePath); 2.78 + free(dev_details); 2.79 + continue; 2.80 + } 2.81 + free(dev_details); 2.82 + 2.83 + HIDD_ATTRIBUTES attr; 2.84 + attr.Size = sizeof attr; 2.85 + if(!HidD_GetAttributes(dev_handle, &attr)) { 2.86 + CloseHandle(dev_handle); 2.87 + dev_handle = 0; 2.88 + continue; 2.89 + } 2.90 + 2.91 + char name[256]; 2.92 + if(!HidD_GetProductString(dev_handle, name, sizeof name)) { 2.93 + strcpy(name, "<unknown>"); 2.94 + } 2.95 + 2.96 + printf("Device: %x:%x: %s\n", (unsigned int)attr.VendorID, (unsigned int)attr.ProductID, name); 2.97 + 2.98 + if(attr.VendorID == 0x46d && attr.ProductID == 0xc626) { 2.99 + break; // found it 2.100 + } 2.101 + 2.102 + CloseHandle(dev_handle); 2.103 + dev_handle = 0; 2.104 + } 2.105 + SetupDiDestroyDeviceInfoList(devs); 2.106 + 2.107 + if(!dev_handle) { 2.108 + fprintf(stderr, "failed to find matching USB HID device\n"); 2.109 + return 1; 2.110 + } 2.111 + 2.112 + printf("device found\n"); 2.113 + _HIDP_PREPARSED_DATA *predata; 2.114 + 2.115 + if(!HidD_GetPreparsedData(dev_handle, &predata)) { 2.116 + fprintf(stderr, "failed to get preparsed data(?)\n"); 2.117 + goto cleanup; 2.118 + } 2.119 + 2.120 + HIDP_CAPS caps; 2.121 + if(!HidP_GetCaps(predata, &caps)) { 2.122 + fprintf(stderr, "failed to retrieve device capabilities\n"); 2.123 + HidD_FreePreparsedData(predata); 2.124 + goto cleanup; 2.125 + } 2.126 + 2.127 + unsigned short num_value_caps = caps.NumberInputValueCaps; 2.128 + HIDP_VALUE_CAPS *value_caps = (HIDP_VALUE_CAPS*)malloc(num_value_caps * sizeof *value_caps); 2.129 + if(!value_caps) { 2.130 + perror("failed to allocate value caps array"); 2.131 + HidD_FreePreparsedData(predata); 2.132 + goto cleanup; 2.133 + } 2.134 + 2.135 + if(HidP_GetValueCaps(HidP_Input, value_caps, &num_value_caps, predata) != HIDP_STATUS_SUCCESS) { 2.136 + fprintf(stderr, "failed to retrieve device value capabilities\n"); 2.137 + HidD_FreePreparsedData(predata); 2.138 + goto cleanup; 2.139 + } 2.140 + HidD_FreePreparsedData(predata); 2.141 + 2.142 + int min_val = 0; 2.143 + int max_val = 0; 2.144 + for(unsigned int i=0; i<num_value_caps; i++) { 2.145 + printf("Usage page: %d\n", (int)value_caps[i].UsagePage); 2.146 + printf("Report ID: %d\n", (int)value_caps[i].ReportID); 2.147 + printf("Logical range: %d - %d\n", (int)value_caps[i].LogicalMin, (int)value_caps[i].LogicalMax); 2.148 + if(i == 0) { 2.149 + min_val = value_caps[i].LogicalMin; 2.150 + max_val = value_caps[i].LogicalMax; 2.151 + } 2.152 + } 2.153 + int val_range = max_val - min_val; 2.154 + printf("value range: %d\n", val_range); 2.155 + 2.156 + int report_size = caps.InputReportByteLength; 2.157 + if(!(report = (Report*)malloc(report_size))) { 2.158 + perror("failed to allocate input report buffer"); 2.159 + goto cleanup; 2.160 + } 2.161 + 2.162 + //signal(SIGINT, sig_handler); 2.163 + if(!SetConsoleCtrlHandler(console_handler, 1)) { 2.164 + fprintf(stderr, "failed to install console control handler\n"); 2.165 + } 2.166 + 2.167 + static uint32_t bnstate = 0; 2.168 + 2.169 + while(!done) { 2.170 + if(WaitForSingleObject(dev_handle, INFINITE) != 0) { 2.171 + fprintf(stderr, "error while waiting for device events\n"); 2.172 + break; 2.173 + } 2.174 + 2.175 + DWORD num_read; 2.176 + if(!ReadFile(dev_handle, report, report_size, &num_read, 0)) { 2.177 + fprintf(stderr, "failed to read input report\n"); 2.178 + continue; 2.179 + } 2.180 + 2.181 + switch(report->type) { 2.182 + case 1: /* translation */ 2.183 + { 2.184 + int x = report->motion.x; 2.185 + int y = report->motion.y; 2.186 + int z = report->motion.z; 2.187 + if(val_range != 0) { 2.188 + x = 100 * (x - min_val) / val_range - 50; 2.189 + y = 100 * (y - min_val) / val_range - 50; 2.190 + z = 100 * (z - min_val) / val_range - 50; 2.191 + } 2.192 + printf("MOTION %4d %4d %4d\n", x, y, z); 2.193 + } 2.194 + break; 2.195 + 2.196 + case 2: /* rotation */ 2.197 + { 2.198 + int x = report->motion.x; 2.199 + int y = report->motion.y; 2.200 + int z = report->motion.z; 2.201 + if(val_range != 0) { 2.202 + x = 100 * (x - min_val) / val_range - 50; 2.203 + y = 100 * (y - min_val) / val_range - 50; 2.204 + z = 100 * (z - min_val) / val_range - 50; 2.205 + } 2.206 + printf("ROTATE %4d %4d %4d\n", x, y, z); 2.207 + } 2.208 + break; 2.209 + 2.210 + case 3: 2.211 + bnstate = report->button.state; 2.212 + fputs("B: ", stdout); 2.213 + for(int i=0; i<24; i++) { 2.214 + int bn = 23 - i; 2.215 + if(bnstate & (1 << bn)) { 2.216 + fputc('1', stdout); 2.217 + } else { 2.218 + fputc('0', stdout); 2.219 + } 2.220 + } 2.221 + fputc('\n', stdout); 2.222 + break; 2.223 + 2.224 + default: 2.225 + printf("unknown event type: %d\n", (int)report->type); 2.226 + } 2.227 + } 2.228 + 2.229 +cleanup: 2.230 + CloseHandle(dev_handle); 2.231 + return 0; 2.232 +} 2.233 + 2.234 +static int WINAPI console_handler(DWORD s) 2.235 +{ 2.236 + if(s == CTRL_C_EVENT) { 2.237 + printf("Caught interrupt signal, quitting...\n"); 2.238 + done = true; 2.239 + } 2.240 + return 0; 2.241 +} 2.242 \ No newline at end of file
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/spnav_winapi_test.sln Sun Jul 07 04:21:49 2013 +0300 3.3 @@ -0,0 +1,20 @@ 3.4 + 3.5 +Microsoft Visual Studio Solution File, Format Version 10.00 3.6 +# Visual Studio 2008 3.7 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spnav_winapi_test", "spnav_winapi_test.vcproj", "{023D90F5-CE0A-412F-96F4-0B17444D21BB}" 3.8 +EndProject 3.9 +Global 3.10 + GlobalSection(SolutionConfigurationPlatforms) = preSolution 3.11 + Debug|Win32 = Debug|Win32 3.12 + Release|Win32 = Release|Win32 3.13 + EndGlobalSection 3.14 + GlobalSection(ProjectConfigurationPlatforms) = postSolution 3.15 + {023D90F5-CE0A-412F-96F4-0B17444D21BB}.Debug|Win32.ActiveCfg = Debug|Win32 3.16 + {023D90F5-CE0A-412F-96F4-0B17444D21BB}.Debug|Win32.Build.0 = Debug|Win32 3.17 + {023D90F5-CE0A-412F-96F4-0B17444D21BB}.Release|Win32.ActiveCfg = Release|Win32 3.18 + {023D90F5-CE0A-412F-96F4-0B17444D21BB}.Release|Win32.Build.0 = Release|Win32 3.19 + EndGlobalSection 3.20 + GlobalSection(SolutionProperties) = preSolution 3.21 + HideSolutionNode = FALSE 3.22 + EndGlobalSection 3.23 +EndGlobal
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/spnav_winapi_test.vcproj Sun Jul 07 04:21:49 2013 +0300 4.3 @@ -0,0 +1,197 @@ 4.4 +<?xml version="1.0" encoding="Windows-1252"?> 4.5 +<VisualStudioProject 4.6 + ProjectType="Visual C++" 4.7 + Version="9.00" 4.8 + Name="spnav_winapi_test" 4.9 + ProjectGUID="{023D90F5-CE0A-412F-96F4-0B17444D21BB}" 4.10 + RootNamespace="spnav_winapi_test" 4.11 + Keyword="Win32Proj" 4.12 + TargetFrameworkVersion="196613" 4.13 + > 4.14 + <Platforms> 4.15 + <Platform 4.16 + Name="Win32" 4.17 + /> 4.18 + </Platforms> 4.19 + <ToolFiles> 4.20 + </ToolFiles> 4.21 + <Configurations> 4.22 + <Configuration 4.23 + Name="Debug|Win32" 4.24 + OutputDirectory="$(SolutionDir)$(ConfigurationName)" 4.25 + IntermediateDirectory="$(ConfigurationName)" 4.26 + ConfigurationType="1" 4.27 + CharacterSet="2" 4.28 + > 4.29 + <Tool 4.30 + Name="VCPreBuildEventTool" 4.31 + /> 4.32 + <Tool 4.33 + Name="VCCustomBuildTool" 4.34 + /> 4.35 + <Tool 4.36 + Name="VCXMLDataGeneratorTool" 4.37 + /> 4.38 + <Tool 4.39 + Name="VCWebServiceProxyGeneratorTool" 4.40 + /> 4.41 + <Tool 4.42 + Name="VCMIDLTool" 4.43 + /> 4.44 + <Tool 4.45 + Name="VCCLCompilerTool" 4.46 + Optimization="0" 4.47 + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" 4.48 + MinimalRebuild="true" 4.49 + BasicRuntimeChecks="3" 4.50 + RuntimeLibrary="3" 4.51 + UsePrecompiledHeader="0" 4.52 + WarningLevel="3" 4.53 + DebugInformationFormat="4" 4.54 + DisableSpecificWarnings="4996;4244" 4.55 + /> 4.56 + <Tool 4.57 + Name="VCManagedResourceCompilerTool" 4.58 + /> 4.59 + <Tool 4.60 + Name="VCResourceCompilerTool" 4.61 + /> 4.62 + <Tool 4.63 + Name="VCPreLinkEventTool" 4.64 + /> 4.65 + <Tool 4.66 + Name="VCLinkerTool" 4.67 + AdditionalDependencies="hid.lib setupapi.lib" 4.68 + LinkIncremental="2" 4.69 + GenerateDebugInformation="true" 4.70 + SubSystem="1" 4.71 + TargetMachine="1" 4.72 + /> 4.73 + <Tool 4.74 + Name="VCALinkTool" 4.75 + /> 4.76 + <Tool 4.77 + Name="VCManifestTool" 4.78 + /> 4.79 + <Tool 4.80 + Name="VCXDCMakeTool" 4.81 + /> 4.82 + <Tool 4.83 + Name="VCBscMakeTool" 4.84 + /> 4.85 + <Tool 4.86 + Name="VCFxCopTool" 4.87 + /> 4.88 + <Tool 4.89 + Name="VCAppVerifierTool" 4.90 + /> 4.91 + <Tool 4.92 + Name="VCPostBuildEventTool" 4.93 + /> 4.94 + </Configuration> 4.95 + <Configuration 4.96 + Name="Release|Win32" 4.97 + OutputDirectory="$(SolutionDir)$(ConfigurationName)" 4.98 + IntermediateDirectory="$(ConfigurationName)" 4.99 + ConfigurationType="1" 4.100 + CharacterSet="2" 4.101 + WholeProgramOptimization="1" 4.102 + > 4.103 + <Tool 4.104 + Name="VCPreBuildEventTool" 4.105 + /> 4.106 + <Tool 4.107 + Name="VCCustomBuildTool" 4.108 + /> 4.109 + <Tool 4.110 + Name="VCXMLDataGeneratorTool" 4.111 + /> 4.112 + <Tool 4.113 + Name="VCWebServiceProxyGeneratorTool" 4.114 + /> 4.115 + <Tool 4.116 + Name="VCMIDLTool" 4.117 + /> 4.118 + <Tool 4.119 + Name="VCCLCompilerTool" 4.120 + Optimization="2" 4.121 + EnableIntrinsicFunctions="true" 4.122 + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" 4.123 + RuntimeLibrary="2" 4.124 + EnableFunctionLevelLinking="true" 4.125 + UsePrecompiledHeader="0" 4.126 + WarningLevel="3" 4.127 + DebugInformationFormat="3" 4.128 + DisableSpecificWarnings="4996;4244" 4.129 + /> 4.130 + <Tool 4.131 + Name="VCManagedResourceCompilerTool" 4.132 + /> 4.133 + <Tool 4.134 + Name="VCResourceCompilerTool" 4.135 + /> 4.136 + <Tool 4.137 + Name="VCPreLinkEventTool" 4.138 + /> 4.139 + <Tool 4.140 + Name="VCLinkerTool" 4.141 + AdditionalDependencies="hid.lib setupapi.lib" 4.142 + LinkIncremental="1" 4.143 + GenerateDebugInformation="true" 4.144 + SubSystem="1" 4.145 + OptimizeReferences="2" 4.146 + EnableCOMDATFolding="2" 4.147 + TargetMachine="1" 4.148 + /> 4.149 + <Tool 4.150 + Name="VCALinkTool" 4.151 + /> 4.152 + <Tool 4.153 + Name="VCManifestTool" 4.154 + /> 4.155 + <Tool 4.156 + Name="VCXDCMakeTool" 4.157 + /> 4.158 + <Tool 4.159 + Name="VCBscMakeTool" 4.160 + /> 4.161 + <Tool 4.162 + Name="VCFxCopTool" 4.163 + /> 4.164 + <Tool 4.165 + Name="VCAppVerifierTool" 4.166 + /> 4.167 + <Tool 4.168 + Name="VCPostBuildEventTool" 4.169 + /> 4.170 + </Configuration> 4.171 + </Configurations> 4.172 + <References> 4.173 + </References> 4.174 + <Files> 4.175 + <Filter 4.176 + Name="Source Files" 4.177 + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" 4.178 + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" 4.179 + > 4.180 + <File 4.181 + RelativePath=".\main.cpp" 4.182 + > 4.183 + </File> 4.184 + </Filter> 4.185 + <Filter 4.186 + Name="Header Files" 4.187 + Filter="h;hpp;hxx;hm;inl;inc;xsd" 4.188 + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" 4.189 + > 4.190 + </Filter> 4.191 + <Filter 4.192 + Name="Resource Files" 4.193 + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" 4.194 + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" 4.195 + > 4.196 + </Filter> 4.197 + </Files> 4.198 + <Globals> 4.199 + </Globals> 4.200 +</VisualStudioProject>