USB detection for Windows (alternative implementation with OLE)
This commit is contained in:
113
usb_ole_windows.go
Normal file
113
usb_ole_windows.go
Normal file
@@ -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
|
||||||
|
}
|
||||||
@@ -51,6 +51,9 @@ func parseDeviceID(deviceID string, details *PortDetails) {
|
|||||||
// Other unidentified device type
|
// Other unidentified device type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setupapi based
|
||||||
|
// --------------
|
||||||
|
|
||||||
//sys setupDiClassGuidsFromNameInternal(class string, guid *guid, guidSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiClassGuidsFromNameW
|
//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 setupDiGetClassDevs(guid *guid, enumerator *string, hwndParent uintptr, flags uint32) (set devicesSet, err error) = setupapi.SetupDiGetClassDevsW
|
||||||
//sys setupDiDestroyDeviceInfoList(set devicesSet) (err error) = setupapi.SetupDiDestroyDeviceInfoList
|
//sys setupDiDestroyDeviceInfoList(set devicesSet) (err error) = setupapi.SetupDiDestroyDeviceInfoList
|
||||||
|
|||||||
Reference in New Issue
Block a user