nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: extern "C" { nuclear@0: #include nuclear@0: #include nuclear@0: } nuclear@0: nuclear@0: typedef __int16 int16_t; nuclear@0: typedef unsigned __int32 uint32_t; nuclear@0: nuclear@0: /* TODO: notification nuclear@0: Obtain the Windows GUID for HID devices by way of a call to HidD_GetHidGuid() nuclear@0: Clear the contents of a DEV_BROADCAST_DEVICEINTERFACE structure 0. nuclear@0: Assign the members of the structure such that you specify the HID GUID. nuclear@0: Register the application for device notifications by calling the function RegisterDeviceNotification(). nuclear@0: 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. nuclear@0: */ nuclear@0: nuclear@0: #pragma pack(push, 1) nuclear@0: union Report { nuclear@0: unsigned char type; nuclear@0: nuclear@0: struct { int16_t x, y, z; } motion; nuclear@0: struct { uint32_t state; } button; nuclear@0: }; nuclear@0: #pragma pack(pop) nuclear@0: nuclear@0: static int WINAPI console_handler(DWORD s); nuclear@0: nuclear@0: bool done; nuclear@0: nuclear@0: int main() nuclear@0: { nuclear@0: HANDLE dev_handle = 0; nuclear@0: Report *report = 0; nuclear@0: nuclear@0: GUID hid_guid; nuclear@0: HidD_GetHidGuid(&hid_guid); nuclear@0: nuclear@0: HDEVINFO devs = SetupDiGetClassDevs(&hid_guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); nuclear@0: if(!devs) { nuclear@0: fprintf(stderr, "failed to retrieve all USB HID devices\n"); nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: for(int i=0; ; i++) { nuclear@0: SP_DEVICE_INTERFACE_DATA dev_data; nuclear@0: dev_data.cbSize = sizeof dev_data; nuclear@0: nuclear@0: if(!SetupDiEnumDeviceInterfaces(devs, 0, &hid_guid, i, &dev_data)) { nuclear@0: if(GetLastError() != ERROR_NO_MORE_ITEMS) { nuclear@0: fprintf(stderr, "failed to enumarate device %d\n", i); nuclear@0: } nuclear@0: break; nuclear@0: } nuclear@0: nuclear@0: DWORD bufsz; nuclear@0: SetupDiGetDeviceInterfaceDetail(devs, &dev_data, 0, 0, &bufsz, 0); nuclear@0: nuclear@0: SP_DEVICE_INTERFACE_DETAIL_DATA *dev_details = (SP_DEVICE_INTERFACE_DETAIL_DATA*)malloc(bufsz); nuclear@0: assert(dev_details); nuclear@0: dev_details->cbSize = sizeof *dev_details; nuclear@0: nuclear@0: if(!SetupDiGetDeviceInterfaceDetail(devs, &dev_data, dev_details, bufsz, &bufsz, 0)) { nuclear@0: int err = GetLastError(); nuclear@0: fprintf(stderr, "failed to get interface %d details\n", i); nuclear@0: continue; nuclear@0: } nuclear@0: dev_handle = CreateFile(dev_details->DevicePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); nuclear@0: if(!dev_handle) { nuclear@0: fprintf(stderr, "failed to open device file: %s\n", dev_details->DevicePath); nuclear@0: free(dev_details); nuclear@0: continue; nuclear@0: } nuclear@0: free(dev_details); nuclear@0: nuclear@0: HIDD_ATTRIBUTES attr; nuclear@0: attr.Size = sizeof attr; nuclear@0: if(!HidD_GetAttributes(dev_handle, &attr)) { nuclear@0: CloseHandle(dev_handle); nuclear@0: dev_handle = 0; nuclear@0: continue; nuclear@0: } nuclear@0: nuclear@0: char name[256]; nuclear@0: if(!HidD_GetProductString(dev_handle, name, sizeof name)) { nuclear@0: strcpy(name, ""); nuclear@0: } nuclear@0: nuclear@0: printf("Device: %x:%x: %s\n", (unsigned int)attr.VendorID, (unsigned int)attr.ProductID, name); nuclear@0: nuclear@0: if(attr.VendorID == 0x46d && attr.ProductID == 0xc626) { nuclear@0: break; // found it nuclear@0: } nuclear@0: nuclear@0: CloseHandle(dev_handle); nuclear@0: dev_handle = 0; nuclear@0: } nuclear@0: SetupDiDestroyDeviceInfoList(devs); nuclear@0: nuclear@0: if(!dev_handle) { nuclear@0: fprintf(stderr, "failed to find matching USB HID device\n"); nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: printf("device found\n"); nuclear@0: _HIDP_PREPARSED_DATA *predata; nuclear@0: nuclear@0: if(!HidD_GetPreparsedData(dev_handle, &predata)) { nuclear@0: fprintf(stderr, "failed to get preparsed data(?)\n"); nuclear@0: goto cleanup; nuclear@0: } nuclear@0: nuclear@0: HIDP_CAPS caps; nuclear@0: if(!HidP_GetCaps(predata, &caps)) { nuclear@0: fprintf(stderr, "failed to retrieve device capabilities\n"); nuclear@0: HidD_FreePreparsedData(predata); nuclear@0: goto cleanup; nuclear@0: } nuclear@0: nuclear@0: unsigned short num_value_caps = caps.NumberInputValueCaps; nuclear@0: HIDP_VALUE_CAPS *value_caps = (HIDP_VALUE_CAPS*)malloc(num_value_caps * sizeof *value_caps); nuclear@0: if(!value_caps) { nuclear@0: perror("failed to allocate value caps array"); nuclear@0: HidD_FreePreparsedData(predata); nuclear@0: goto cleanup; nuclear@0: } nuclear@0: nuclear@0: if(HidP_GetValueCaps(HidP_Input, value_caps, &num_value_caps, predata) != HIDP_STATUS_SUCCESS) { nuclear@0: fprintf(stderr, "failed to retrieve device value capabilities\n"); nuclear@0: HidD_FreePreparsedData(predata); nuclear@0: goto cleanup; nuclear@0: } nuclear@0: HidD_FreePreparsedData(predata); nuclear@0: nuclear@0: int min_val = 0; nuclear@0: int max_val = 0; nuclear@0: for(unsigned int i=0; itype) { nuclear@0: case 1: /* translation */ nuclear@0: { nuclear@0: int x = report->motion.x; nuclear@0: int y = report->motion.y; nuclear@0: int z = report->motion.z; nuclear@0: if(val_range != 0) { nuclear@0: x = 100 * (x - min_val) / val_range - 50; nuclear@0: y = 100 * (y - min_val) / val_range - 50; nuclear@0: z = 100 * (z - min_val) / val_range - 50; nuclear@0: } nuclear@0: printf("MOTION %4d %4d %4d\n", x, y, z); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case 2: /* rotation */ nuclear@0: { nuclear@0: int x = report->motion.x; nuclear@0: int y = report->motion.y; nuclear@0: int z = report->motion.z; nuclear@0: if(val_range != 0) { nuclear@0: x = 100 * (x - min_val) / val_range - 50; nuclear@0: y = 100 * (y - min_val) / val_range - 50; nuclear@0: z = 100 * (z - min_val) / val_range - 50; nuclear@0: } nuclear@0: printf("ROTATE %4d %4d %4d\n", x, y, z); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case 3: nuclear@0: bnstate = report->button.state; nuclear@0: fputs("B: ", stdout); nuclear@0: for(int i=0; i<24; i++) { nuclear@0: int bn = 23 - i; nuclear@0: if(bnstate & (1 << bn)) { nuclear@0: fputc('1', stdout); nuclear@0: } else { nuclear@0: fputc('0', stdout); nuclear@0: } nuclear@0: } nuclear@0: fputc('\n', stdout); nuclear@0: break; nuclear@0: nuclear@0: default: nuclear@0: printf("unknown event type: %d\n", (int)report->type); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: cleanup: nuclear@0: CloseHandle(dev_handle); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: static int WINAPI console_handler(DWORD s) nuclear@0: { nuclear@0: if(s == CTRL_C_EVENT) { nuclear@0: printf("Caught interrupt signal, quitting...\n"); nuclear@0: done = true; nuclear@0: } nuclear@0: return 0; nuclear@0: }