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
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user