adam-gui/vendor/go.bug.st/serial/enumerator/usb_linux.go

110 lines
2.7 KiB
Go
Raw Permalink Normal View History

2024-04-29 19:13:50 +02:00
//
// Copyright 2014-2023 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.
//
package enumerator
import (
"bufio"
"fmt"
"os"
"path/filepath"
"go.bug.st/serial"
)
func nativeGetDetailedPortsList() ([]*PortDetails, error) {
// Retrieve the port list
ports, err := serial.GetPortsList()
if err != nil {
return nil, &PortEnumerationError{causedBy: err}
}
var res []*PortDetails
for _, port := range ports {
details, err := nativeGetPortDetails(port)
if err != nil {
return nil, &PortEnumerationError{causedBy: err}
}
res = append(res, details)
}
return res, nil
}
func nativeGetPortDetails(portPath string) (*PortDetails, error) {
portName := filepath.Base(portPath)
devicePath := fmt.Sprintf("/sys/class/tty/%s/device", portName)
if _, err := os.Stat(devicePath); err != nil {
return &PortDetails{}, nil
}
realDevicePath, err := filepath.EvalSymlinks(devicePath)
if err != nil {
return nil, fmt.Errorf("Can't determine real path of %s: %s", devicePath, err.Error())
}
subSystemPath, err := filepath.EvalSymlinks(filepath.Join(realDevicePath, "subsystem"))
if err != nil {
return nil, fmt.Errorf("Can't determine real path of %s: %s", filepath.Join(realDevicePath, "subsystem"), err.Error())
}
subSystem := filepath.Base(subSystemPath)
result := &PortDetails{Name: portPath}
switch subSystem {
case "usb-serial":
err := parseUSBSysFS(filepath.Dir(filepath.Dir(realDevicePath)), result)
return result, err
case "usb":
err := parseUSBSysFS(filepath.Dir(realDevicePath), result)
return result, err
// TODO: other cases?
default:
return result, nil
}
}
func parseUSBSysFS(usbDevicePath string, details *PortDetails) error {
vid, err := readLine(filepath.Join(usbDevicePath, "idVendor"))
if err != nil {
return err
}
pid, err := readLine(filepath.Join(usbDevicePath, "idProduct"))
if err != nil {
return err
}
serial, err := readLine(filepath.Join(usbDevicePath, "serial"))
if err != nil {
return err
}
//manufacturer, err := readLine(filepath.Join(usbDevicePath, "manufacturer"))
//if err != nil {
// return err
//}
//product, err := readLine(filepath.Join(usbDevicePath, "product"))
//if err != nil {
// return err
//}
details.IsUSB = true
details.VID = vid
details.PID = pid
details.SerialNumber = serial
//details.Manufacturer = manufacturer
//details.Product = product
return nil
}
func readLine(filename string) (string, error) {
file, err := os.Open(filename)
if os.IsNotExist(err) {
return "", nil
}
if err != nil {
return "", err
}
defer file.Close()
reader := bufio.NewReader(file)
line, _, err := reader.ReadLine()
return string(line), err
}