spnav_win32_test

view main.cpp @ 1:55a06a416ca8

removed meaningless comment
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 13 Aug 2013 22:17:00 +0300
parents 21f1554e2884
children
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <signal.h>
4 #include <assert.h>
5 #include <windows.h>
6 extern "C" {
7 #include <hidsdi.h>
8 #include <setupapi.h>
9 }
11 typedef __int16 int16_t;
12 typedef unsigned __int32 uint32_t;
14 #pragma pack(push, 1)
15 union Report {
16 unsigned char type;
18 struct { int16_t x, y, z; } motion;
19 struct { uint32_t state; } button;
20 };
21 #pragma pack(pop)
23 static int WINAPI console_handler(DWORD s);
25 bool done;
27 int main()
28 {
29 HANDLE dev_handle = 0;
30 Report *report = 0;
32 GUID hid_guid;
33 HidD_GetHidGuid(&hid_guid);
35 HDEVINFO devs = SetupDiGetClassDevs(&hid_guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
36 if(!devs) {
37 fprintf(stderr, "failed to retrieve all USB HID devices\n");
38 return 1;
39 }
41 for(int i=0; ; i++) {
42 SP_DEVICE_INTERFACE_DATA dev_data;
43 dev_data.cbSize = sizeof dev_data;
45 if(!SetupDiEnumDeviceInterfaces(devs, 0, &hid_guid, i, &dev_data)) {
46 if(GetLastError() != ERROR_NO_MORE_ITEMS) {
47 fprintf(stderr, "failed to enumarate device %d\n", i);
48 }
49 break;
50 }
52 DWORD bufsz;
53 SetupDiGetDeviceInterfaceDetail(devs, &dev_data, 0, 0, &bufsz, 0);
55 SP_DEVICE_INTERFACE_DETAIL_DATA *dev_details = (SP_DEVICE_INTERFACE_DETAIL_DATA*)malloc(bufsz);
56 assert(dev_details);
57 dev_details->cbSize = sizeof *dev_details;
59 if(!SetupDiGetDeviceInterfaceDetail(devs, &dev_data, dev_details, bufsz, &bufsz, 0)) {
60 int err = GetLastError();
61 fprintf(stderr, "failed to get interface %d details\n", i);
62 continue;
63 }
64 dev_handle = CreateFile(dev_details->DevicePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
65 if(!dev_handle) {
66 fprintf(stderr, "failed to open device file: %s\n", dev_details->DevicePath);
67 free(dev_details);
68 continue;
69 }
70 free(dev_details);
72 HIDD_ATTRIBUTES attr;
73 attr.Size = sizeof attr;
74 if(!HidD_GetAttributes(dev_handle, &attr)) {
75 CloseHandle(dev_handle);
76 dev_handle = 0;
77 continue;
78 }
80 char name[256];
81 if(!HidD_GetProductString(dev_handle, name, sizeof name)) {
82 strcpy(name, "<unknown>");
83 }
85 printf("Device: %x:%x: %s\n", (unsigned int)attr.VendorID, (unsigned int)attr.ProductID, name);
87 if(attr.VendorID == 0x46d && attr.ProductID == 0xc626) {
88 break; // found it
89 }
91 CloseHandle(dev_handle);
92 dev_handle = 0;
93 }
94 SetupDiDestroyDeviceInfoList(devs);
96 if(!dev_handle) {
97 fprintf(stderr, "failed to find matching USB HID device\n");
98 return 1;
99 }
101 printf("device found\n");
102 _HIDP_PREPARSED_DATA *predata;
104 if(!HidD_GetPreparsedData(dev_handle, &predata)) {
105 fprintf(stderr, "failed to get preparsed data(?)\n");
106 goto cleanup;
107 }
109 HIDP_CAPS caps;
110 if(!HidP_GetCaps(predata, &caps)) {
111 fprintf(stderr, "failed to retrieve device capabilities\n");
112 HidD_FreePreparsedData(predata);
113 goto cleanup;
114 }
116 unsigned short num_value_caps = caps.NumberInputValueCaps;
117 HIDP_VALUE_CAPS *value_caps = (HIDP_VALUE_CAPS*)malloc(num_value_caps * sizeof *value_caps);
118 if(!value_caps) {
119 perror("failed to allocate value caps array");
120 HidD_FreePreparsedData(predata);
121 goto cleanup;
122 }
124 if(HidP_GetValueCaps(HidP_Input, value_caps, &num_value_caps, predata) != HIDP_STATUS_SUCCESS) {
125 fprintf(stderr, "failed to retrieve device value capabilities\n");
126 HidD_FreePreparsedData(predata);
127 goto cleanup;
128 }
129 HidD_FreePreparsedData(predata);
131 int min_val = 0;
132 int max_val = 0;
133 for(unsigned int i=0; i<num_value_caps; i++) {
134 printf("Usage page: %d\n", (int)value_caps[i].UsagePage);
135 printf("Report ID: %d\n", (int)value_caps[i].ReportID);
136 printf("Logical range: %d - %d\n", (int)value_caps[i].LogicalMin, (int)value_caps[i].LogicalMax);
137 if(i == 0) {
138 min_val = value_caps[i].LogicalMin;
139 max_val = value_caps[i].LogicalMax;
140 }
141 }
142 int val_range = max_val - min_val;
143 printf("value range: %d\n", val_range);
145 int report_size = caps.InputReportByteLength;
146 if(!(report = (Report*)malloc(report_size))) {
147 perror("failed to allocate input report buffer");
148 goto cleanup;
149 }
151 //signal(SIGINT, sig_handler);
152 if(!SetConsoleCtrlHandler(console_handler, 1)) {
153 fprintf(stderr, "failed to install console control handler\n");
154 }
156 static uint32_t bnstate = 0;
158 while(!done) {
159 if(WaitForSingleObject(dev_handle, INFINITE) != 0) {
160 fprintf(stderr, "error while waiting for device events\n");
161 break;
162 }
164 DWORD num_read;
165 if(!ReadFile(dev_handle, report, report_size, &num_read, 0)) {
166 fprintf(stderr, "failed to read input report\n");
167 continue;
168 }
170 switch(report->type) {
171 case 1: /* translation */
172 {
173 int x = report->motion.x;
174 int y = report->motion.y;
175 int z = report->motion.z;
176 if(val_range != 0) {
177 x = 100 * (x - min_val) / val_range - 50;
178 y = 100 * (y - min_val) / val_range - 50;
179 z = 100 * (z - min_val) / val_range - 50;
180 }
181 printf("MOTION %4d %4d %4d\n", x, y, z);
182 }
183 break;
185 case 2: /* rotation */
186 {
187 int x = report->motion.x;
188 int y = report->motion.y;
189 int z = report->motion.z;
190 if(val_range != 0) {
191 x = 100 * (x - min_val) / val_range - 50;
192 y = 100 * (y - min_val) / val_range - 50;
193 z = 100 * (z - min_val) / val_range - 50;
194 }
195 printf("ROTATE %4d %4d %4d\n", x, y, z);
196 }
197 break;
199 case 3:
200 bnstate = report->button.state;
201 fputs("B: ", stdout);
202 for(int i=0; i<24; i++) {
203 int bn = 23 - i;
204 if(bnstate & (1 << bn)) {
205 fputc('1', stdout);
206 } else {
207 fputc('0', stdout);
208 }
209 }
210 fputc('\n', stdout);
211 break;
213 default:
214 printf("unknown event type: %d\n", (int)report->type);
215 }
216 }
218 cleanup:
219 CloseHandle(dev_handle);
220 return 0;
221 }
223 static int WINAPI console_handler(DWORD s)
224 {
225 if(s == CTRL_C_EVENT) {
226 printf("Caught interrupt signal, quitting...\n");
227 done = true;
228 }
229 return 0;
230 }