Added USB discovery for Linux
This commit is contained in:
99
usb_linux.go
99
usb_linux.go
@@ -6,7 +6,102 @@
|
|||||||
|
|
||||||
package serial // import "go.bug.st/serial.v1"
|
package serial // import "go.bug.st/serial.v1"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
func nativeGetDetailedPortsList() ([]*PortDetails, error) {
|
func nativeGetDetailedPortsList() ([]*PortDetails, error) {
|
||||||
// TODO
|
// Retrieve the port list
|
||||||
return nil, &PortError{code: FunctionNotImplemented}
|
ports, err := nativeGetPortsList()
|
||||||
|
if err != nil {
|
||||||
|
return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
var res []*PortDetails
|
||||||
|
for _, port := range ports {
|
||||||
|
details, err := nativeGetPortDetails(port)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &PortError{code: ErrorEnumeratingPorts, 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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user