diff --git a/usb_ole_windows.go b/usb_ole_windows.go new file mode 100644 index 0000000..128aa86 --- /dev/null +++ b/usb_ole_windows.go @@ -0,0 +1,113 @@ +// +// Copyright 2014-2016 Lars Knudsen, Cristian Maglie. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// + +// +build ignore + +package serial + +import ( + "log" + "regexp" + + ole "github.com/go-ole/go-ole" + "github.com/go-ole/go-ole/oleutil" +) + +func init() { + err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) + if err != nil { + log.Fatal("Init error: ", err) + } +} + +func nativeGetDetailedPortsList() ([]*PortDetails, error) { + unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") + if err != nil { + return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} + } + defer unknown.Release() + + wmi, err := unknown.QueryInterface(ole.IID_IDispatch) + if err != nil { + return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} + } + defer wmi.Release() + + serviceRaw, err := wmi.CallMethod("ConnectServer") + if err != nil { + return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} + } + service := serviceRaw.ToIDispatch() + defer service.Release() + + query := "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0 and Name like '%(COM%'" + queryResult, err := oleutil.CallMethod(service, "ExecQuery", query) + if err != nil { + return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} + } + result := queryResult.ToIDispatch() + defer result.Release() + + countVar, err := result.GetProperty("Count") + if err != nil { + return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} + } + count := int(countVar.Val) + + res := []*PortDetails{} + + // Retrieve all items + for i := 0; i < count; i++ { + itemRaw, err := result.CallMethod("ItemIndex", i) + if err != nil { + return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} + } + item := itemRaw.ToIDispatch() + defer item.Release() + + detail := &PortDetails{} + if err := getPortDetails(item, detail); err != nil { + return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} + } + // SerialPort{Path: path, VendorId: VID, ProductId: PID, DisplayName: displayName.ToString()} + res = append(res, detail) + } + + return res, nil +} + +func getPortDetails(item *ole.IDispatch, res *PortDetails) error { + // Find port name + itemName, err := item.GetProperty("Name") + if err != nil { + return err + } + re := regexp.MustCompile("\\((COM[0-9]+)\\)").FindAllStringSubmatch(itemName.ToString(), 1) + if re == nil || len(re[0]) < 2 { + // Discard items that are not serial ports + return nil + } + res.Name = re[0][1] + + //itemPnPDeviceID, err := item.GetProperty("PnPDeviceID") + //if err != nil { + // return err + //} + //PnPDeviceID := itemPnPDeviceID.ToString() + + itemDeviceID, err := item.GetProperty("DeviceID") + if err != nil { + return err + } + parseDeviceID(itemDeviceID.ToString(), res) + + itemManufacturer, err := item.GetProperty("Product") + if err != nil { + return err + } + res.Manufacturer = itemManufacturer.ToString() + return nil +} diff --git a/usb_windows.go b/usb_windows.go index 32d78e2..c053297 100644 --- a/usb_windows.go +++ b/usb_windows.go @@ -51,6 +51,9 @@ func parseDeviceID(deviceID string, details *PortDetails) { // Other unidentified device type } +// setupapi based +// -------------- + //sys setupDiClassGuidsFromNameInternal(class string, guid *guid, guidSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiClassGuidsFromNameW //sys setupDiGetClassDevs(guid *guid, enumerator *string, hwndParent uintptr, flags uint32) (set devicesSet, err error) = setupapi.SetupDiGetClassDevsW //sys setupDiDestroyDeviceInfoList(set devicesSet) (err error) = setupapi.SetupDiDestroyDeviceInfoList