-
-
Save larsgk/932232c83d6d21d9040bc6694d6c7b1d to your computer and use it in GitHub Desktop.
Get PnP data (VID, PID, deviceName) from serial ports where available
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
serial "github.com/facchinm/go-serial" | |
"log" | |
"os/exec" | |
"strconv" | |
"strings" | |
) | |
func getPnPDetailsByUdevadm(path string) (*SerialPort, error) { | |
out, err := exec.Command("udevadm", "info", "-q", "path", "-n", path).Output() | |
if err != nil { | |
log.Printf("Error creating exec.Command: %v\n", err) | |
return nil, err | |
} | |
syspath := strings.TrimSpace(string(out)) | |
cmd := exec.Command("udevadm", "info", "--query=property", "-p", syspath) | |
cmdReader, err := cmd.StdoutPipe() | |
if err != nil { | |
log.Printf("Error creating StdoutPipe: %v\n", err) | |
return nil, err | |
} | |
var VID, PID uint16 = 0, 0 | |
var displayName string = "" | |
scanner := bufio.NewScanner(cmdReader) | |
stop := make(chan bool) | |
go func() { | |
for scanner.Scan() { | |
// log.Printf("READ> %s\n", scanner.Text()) | |
keyValue := strings.Split(scanner.Text(), "=") | |
if len(keyValue) > 1 { | |
switch keyValue[0] { | |
case "ID_MODEL", "ID_MODEL_FROM_DATABASE": | |
if len(displayName) == 0 { | |
displayName = keyValue[1] | |
} | |
case "ID_VENDOR_ID": | |
val, _ := strconv.ParseUint(strings.Replace(keyValue[1], "0x", "", 1), 16, 16) | |
VID = uint16(val) | |
case "ID_MODEL_ID": | |
val, _ := strconv.ParseUint(strings.Replace(keyValue[1], "0x", "", 1), 16, 16) | |
PID = uint16(val) | |
} | |
} | |
} | |
stop <- true | |
}() | |
err = cmd.Start() | |
if err != nil { | |
log.Printf("Error starting cmd: %v\n", err) | |
return nil, err | |
} | |
<-stop | |
err = cmd.Wait() | |
if err != nil { | |
log.Printf("Error waiting for cmd: %v\n", err) | |
return nil, err | |
} | |
return &SerialPort{Path: path, VendorId: VID, ProductId: PID, DisplayName: displayName}, err | |
} | |
func GetSerialPortList() ([]SerialPort, error) { | |
serialPorts := []SerialPort{} | |
paths, err := serial.GetPortsList() | |
if err == nil { | |
for _, path := range paths { | |
serialPort, err := getPnPDetailsByUdevadm(path) | |
if err == nil { | |
serialPorts = append(serialPorts, *serialPort) | |
} | |
} | |
} | |
return serialPorts, err | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"github.com/go-ole/go-ole" | |
"github.com/go-ole/go-ole/oleutil" | |
"log" | |
"regexp" | |
"strconv" | |
) | |
func init() { | |
err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) | |
if err != nil { | |
log.Fatal("Init error: ", err) | |
} | |
} | |
func GetSerialPortList() ([]SerialPort, error) { | |
unknown, _ := oleutil.CreateObject("WbemScripting.SWbemLocator") | |
defer unknown.Release() | |
wmi, _ := unknown.QueryInterface(ole.IID_IDispatch) | |
defer wmi.Release() | |
serviceRaw, _ := oleutil.CallMethod(wmi, "ConnectServer") | |
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) | |
serialPorts := []SerialPort{} | |
if err != nil { | |
log.Printf("Error from oleutil.CallMethod: ", err) | |
return nil, err | |
} | |
result := queryResult.ToIDispatch() | |
defer result.Release() | |
countVar, _ := oleutil.GetProperty(result, "Count") | |
count := int(countVar.Val) | |
// Should we filter on VID/PID here or later? | |
for i := 0; i < count; i++ { | |
itemRaw, _ := oleutil.CallMethod(result, "ItemIndex", i) | |
item := itemRaw.ToIDispatch() | |
defer item.Release() | |
displayName, _ := oleutil.GetProperty(item, "Name") | |
re := regexp.MustCompile("\\((COM[0-9]+)\\)").FindAllStringSubmatch(displayName.ToString(), 1) | |
var path string = "" | |
if re != nil && len(re[0]) > 1 { | |
path = re[0][1] | |
} | |
deviceId, _ := oleutil.GetProperty(item, "DeviceID") | |
re = regexp.MustCompile("ID_(....)").FindAllStringSubmatch(deviceId.ToString(), 2) | |
var VID, PID uint16 = 0, 0 | |
if re != nil && len(re) == 2 { | |
if len(re[0]) > 1 { | |
val, _ := strconv.ParseUint(re[0][1], 16, 16) | |
VID = uint16(val) | |
} | |
if len(re[1]) > 1 { | |
val, _ := strconv.ParseUint(re[1][1], 16, 16) | |
PID = uint16(val) | |
} | |
} | |
serialPorts = append(serialPorts, SerialPort{Path: path, VendorId: VID, ProductId: PID, DisplayName: displayName.ToString()}) | |
} | |
return serialPorts, err | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment