Example #1
0
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
}