func getDeviceDetails(deviceInfoSet C.HDEVINFO, deviceInterfaceData *C.SP_DEVICE_INTERFACE_DATA) *DeviceInfo { devicePath := getCString(func(buffer unsafe.Pointer, size *C.DWORD) unsafe.Pointer { interfaceDetailData := (*C.SP_DEVICE_INTERFACE_DETAIL_DATA_A)(buffer) if interfaceDetailData != nil { interfaceDetailData.cbSize = C.DWORD(unsafe.Sizeof(interfaceDetailData)) } C.SetupDiGetDeviceInterfaceDetailA(deviceInfoSet, deviceInterfaceData, interfaceDetailData, *size, size, nil) if interfaceDetailData != nil { return (unsafe.Pointer)(&interfaceDetailData.DevicePath[0]) } else { return nil } }) if devicePath == "" { return nil } // Make sure this device is of Setup Class "HIDClass" and has a driver bound to it. var i C.DWORD var devinfoData C.SP_DEVINFO_DATA devinfoData.cbSize = C.DWORD(unsafe.Sizeof(devinfoData)) isHID := false for i = 0; ; i++ { if res := C.SetupDiEnumDeviceInfo(deviceInfoSet, i, &devinfoData); res == 0 { break } classStr := getCString(func(buffer unsafe.Pointer, size *C.DWORD) unsafe.Pointer { C.SetupDiGetDeviceRegistryPropertyA(deviceInfoSet, &devinfoData, C.SPDRP_CLASS, nil, (*C.BYTE)(buffer), *size, size) return buffer }) if classStr == "HIDClass" { driverName := getCString(func(buffer unsafe.Pointer, size *C.DWORD) unsafe.Pointer { C.SetupDiGetDeviceRegistryPropertyA(deviceInfoSet, &devinfoData, C.SPDRP_DRIVER, nil, (*C.BYTE)(buffer), *size, size) return buffer }) isHID = driverName != "" break } } if !isHID { return nil } d, _ := ByPath(devicePath) return d }
func enumerate() ([]DeviceDescription, error) { //log.Print("Calling windows backend") k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\services`, registry.QUERY_VALUE) if err != nil { return nil, err } defer k.Close() var result []DeviceDescription for i := 0; i < len(guidArray); i++ { DeviceInfoSet := C.SetupDiGetClassDevs(&guidArray[i], (*C.CHAR)(nil), (*C.struct_HWND__)(nil), C.DIGCF_PRESENT) if C.is_INVALID_HANDLE_VALUE(unsafe.Pointer(DeviceInfoSet)) != 0 { return nil, errors.New(fmt.Sprintf( `Windows: SerialDeviceEnumeratorPrivate::updateInfo() SetupDiGetClassDevs() returned INVALID_HANDLE_VALUE, last error: %d`, int(C.GetLastError()))) } var DeviceIndex C.DWORD = 0 var DeviceInfoData C.SP_DEVINFO_DATA DeviceInfoData.cbSize = C.DWORD(unsafe.Sizeof(DeviceInfoData)) for { if C.SetupDiEnumDeviceInfo(DeviceInfoSet, DeviceIndex, &DeviceInfoData) != C.TRUE { break } DeviceIndex++ name, err := getNativeName(DeviceInfoSet, &DeviceInfoData) if err != nil || len(name) == 0 { continue } if strings.Contains(name, "LPT") { continue } var dev DeviceDescription dev.Name = name dev.ShortName = name if dev.Bus, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_ENUMERATOR_NAME)); err != nil { log.Printf("Error get bus of device %s: %s", name, err.Error()) } if dev.Description, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_DEVICEDESC)); err != nil { log.Printf("Error get Description of device %s: %s", name, err.Error()) } if dev.FriendlyName, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_FRIENDLYNAME)); err != nil { log.Printf("Error get FriendlyName of device %s: %s", name, err.Error()) } if dev.HardwareID, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_HARDWAREID)); err != nil { log.Printf("Error get HardwareID of device %s: %s", name, err.Error()) } if dev.LocationInfo, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_LOCATION_INFORMATION)); err != nil { log.Printf("Error get LocationInfo of device %s: %s", name, err.Error()) } if dev.Manufacturer, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_MFG)); err != nil { log.Printf("Error get Manufacturer of device %s: %s", name, err.Error()) } if dev.SubSystem, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_CLASS)); err != nil { log.Printf("Error get SubSystem of device %s: %s", name, err.Error()) } if dev.Service, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_SERVICE)); err != nil { log.Printf("Error get Service of device %s: %s", name, err.Error()) } if dev.Driver, err = getNativeDriver(dev.Service); err != nil { log.Printf("Error get Driver of device %s: %s", name, err.Error()) } if dev.SystemPath, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_PHYSICAL_DEVICE_OBJECT_NAME)); err != nil { log.Printf("Error get SystemPath of device %s: %s", name, err.Error()) } match := vidpidRegExp.FindStringSubmatch(dev.HardwareID) if len(match) > 1 { var v []byte if v, err = hex.DecodeString(match[1]); err == nil { dev.VendorID = (uint16)(v[0])<<8 + (uint16)(v[1]) } if v, err = hex.DecodeString(match[2]); err == nil { dev.ProductID = (uint16)(v[0])<<8 + (uint16)(v[1]) } } result = append(result, dev) } } return result, nil }