# HG changeset patch # User John Tsiombikas # Date 1373160109 -10800 # Node ID 21f1554e28842bf4f4daffc4f2ad6c5f98118d0b initial commit diff -r 000000000000 -r 21f1554e2884 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sun Jul 07 04:21:49 2013 +0300 @@ -0,0 +1,6 @@ +\.o$ +\.d$ +\.swp$ +\.suo$ +^Debug/ +^Release/ diff -r 000000000000 -r 21f1554e2884 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Jul 07 04:21:49 2013 +0300 @@ -0,0 +1,238 @@ +#include +#include +#include +#include +#include +extern "C" { +#include +#include +} + +typedef __int16 int16_t; +typedef unsigned __int32 uint32_t; + +/* TODO: notification + Obtain the Windows GUID for HID devices by way of a call to HidD_GetHidGuid() + Clear the contents of a DEV_BROADCAST_DEVICEINTERFACE structure 0. + Assign the members of the structure such that you specify the HID GUID. + Register the application for device notifications by calling the function RegisterDeviceNotification(). + 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. +*/ + +#pragma pack(push, 1) +union Report { + unsigned char type; + + struct { int16_t x, y, z; } motion; + struct { uint32_t state; } button; +}; +#pragma pack(pop) + +static int WINAPI console_handler(DWORD s); + +bool done; + +int main() +{ + HANDLE dev_handle = 0; + Report *report = 0; + + GUID hid_guid; + HidD_GetHidGuid(&hid_guid); + + HDEVINFO devs = SetupDiGetClassDevs(&hid_guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if(!devs) { + fprintf(stderr, "failed to retrieve all USB HID devices\n"); + return 1; + } + + for(int i=0; ; i++) { + SP_DEVICE_INTERFACE_DATA dev_data; + dev_data.cbSize = sizeof dev_data; + + if(!SetupDiEnumDeviceInterfaces(devs, 0, &hid_guid, i, &dev_data)) { + if(GetLastError() != ERROR_NO_MORE_ITEMS) { + fprintf(stderr, "failed to enumarate device %d\n", i); + } + break; + } + + DWORD bufsz; + SetupDiGetDeviceInterfaceDetail(devs, &dev_data, 0, 0, &bufsz, 0); + + SP_DEVICE_INTERFACE_DETAIL_DATA *dev_details = (SP_DEVICE_INTERFACE_DETAIL_DATA*)malloc(bufsz); + assert(dev_details); + dev_details->cbSize = sizeof *dev_details; + + if(!SetupDiGetDeviceInterfaceDetail(devs, &dev_data, dev_details, bufsz, &bufsz, 0)) { + int err = GetLastError(); + fprintf(stderr, "failed to get interface %d details\n", i); + continue; + } + dev_handle = CreateFile(dev_details->DevicePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if(!dev_handle) { + fprintf(stderr, "failed to open device file: %s\n", dev_details->DevicePath); + free(dev_details); + continue; + } + free(dev_details); + + HIDD_ATTRIBUTES attr; + attr.Size = sizeof attr; + if(!HidD_GetAttributes(dev_handle, &attr)) { + CloseHandle(dev_handle); + dev_handle = 0; + continue; + } + + char name[256]; + if(!HidD_GetProductString(dev_handle, name, sizeof name)) { + strcpy(name, ""); + } + + printf("Device: %x:%x: %s\n", (unsigned int)attr.VendorID, (unsigned int)attr.ProductID, name); + + if(attr.VendorID == 0x46d && attr.ProductID == 0xc626) { + break; // found it + } + + CloseHandle(dev_handle); + dev_handle = 0; + } + SetupDiDestroyDeviceInfoList(devs); + + if(!dev_handle) { + fprintf(stderr, "failed to find matching USB HID device\n"); + return 1; + } + + printf("device found\n"); + _HIDP_PREPARSED_DATA *predata; + + if(!HidD_GetPreparsedData(dev_handle, &predata)) { + fprintf(stderr, "failed to get preparsed data(?)\n"); + goto cleanup; + } + + HIDP_CAPS caps; + if(!HidP_GetCaps(predata, &caps)) { + fprintf(stderr, "failed to retrieve device capabilities\n"); + HidD_FreePreparsedData(predata); + goto cleanup; + } + + unsigned short num_value_caps = caps.NumberInputValueCaps; + HIDP_VALUE_CAPS *value_caps = (HIDP_VALUE_CAPS*)malloc(num_value_caps * sizeof *value_caps); + if(!value_caps) { + perror("failed to allocate value caps array"); + HidD_FreePreparsedData(predata); + goto cleanup; + } + + if(HidP_GetValueCaps(HidP_Input, value_caps, &num_value_caps, predata) != HIDP_STATUS_SUCCESS) { + fprintf(stderr, "failed to retrieve device value capabilities\n"); + HidD_FreePreparsedData(predata); + goto cleanup; + } + HidD_FreePreparsedData(predata); + + int min_val = 0; + int max_val = 0; + for(unsigned int i=0; itype) { + case 1: /* translation */ + { + int x = report->motion.x; + int y = report->motion.y; + int z = report->motion.z; + if(val_range != 0) { + x = 100 * (x - min_val) / val_range - 50; + y = 100 * (y - min_val) / val_range - 50; + z = 100 * (z - min_val) / val_range - 50; + } + printf("MOTION %4d %4d %4d\n", x, y, z); + } + break; + + case 2: /* rotation */ + { + int x = report->motion.x; + int y = report->motion.y; + int z = report->motion.z; + if(val_range != 0) { + x = 100 * (x - min_val) / val_range - 50; + y = 100 * (y - min_val) / val_range - 50; + z = 100 * (z - min_val) / val_range - 50; + } + printf("ROTATE %4d %4d %4d\n", x, y, z); + } + break; + + case 3: + bnstate = report->button.state; + fputs("B: ", stdout); + for(int i=0; i<24; i++) { + int bn = 23 - i; + if(bnstate & (1 << bn)) { + fputc('1', stdout); + } else { + fputc('0', stdout); + } + } + fputc('\n', stdout); + break; + + default: + printf("unknown event type: %d\n", (int)report->type); + } + } + +cleanup: + CloseHandle(dev_handle); + return 0; +} + +static int WINAPI console_handler(DWORD s) +{ + if(s == CTRL_C_EVENT) { + printf("Caught interrupt signal, quitting...\n"); + done = true; + } + return 0; +} \ No newline at end of file diff -r 000000000000 -r 21f1554e2884 spnav_winapi_test.sln --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spnav_winapi_test.sln Sun Jul 07 04:21:49 2013 +0300 @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spnav_winapi_test", "spnav_winapi_test.vcproj", "{023D90F5-CE0A-412F-96F4-0B17444D21BB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {023D90F5-CE0A-412F-96F4-0B17444D21BB}.Debug|Win32.ActiveCfg = Debug|Win32 + {023D90F5-CE0A-412F-96F4-0B17444D21BB}.Debug|Win32.Build.0 = Debug|Win32 + {023D90F5-CE0A-412F-96F4-0B17444D21BB}.Release|Win32.ActiveCfg = Release|Win32 + {023D90F5-CE0A-412F-96F4-0B17444D21BB}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff -r 000000000000 -r 21f1554e2884 spnav_winapi_test.vcproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spnav_winapi_test.vcproj Sun Jul 07 04:21:49 2013 +0300 @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +