From c2e4f12a12573e1bffe149734888e9750a2d9102 Mon Sep 17 00:00:00 2001 From: "Pascal S. de Kloe" Date: Fri, 6 Oct 2017 03:48:43 +0200 Subject: [PATCH 1/4] List RX ports on Linux. (issue #36) --- list_linux.go | 23 +++++++++++++++++++++++ list_linux_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 list_linux.go create mode 100644 list_linux_test.go diff --git a/list_linux.go b/list_linux.go new file mode 100644 index 0000000..d781f60 --- /dev/null +++ b/list_linux.go @@ -0,0 +1,23 @@ +package serial + +import ( + "path/filepath" + "sort" +) + +// ListRX returns the detected serial ports sorted. +func ListRX() (names []string, err error) { + matches, err := filepath.Glob("/sys/class/tty/*/rx_trig_bytes") + if err != nil { + return nil, err + } + + names = make([]string, len(matches)) + for i, m := range matches { + names[i] = "/dev/" + filepath.Base(filepath.Dir(m)) + } + + sort.Strings(names) + + return +} diff --git a/list_linux_test.go b/list_linux_test.go new file mode 100644 index 0000000..a3e51e3 --- /dev/null +++ b/list_linux_test.go @@ -0,0 +1,38 @@ +package serial + +import ( + "os" + "testing" +) + +func TestListRX(t *testing.T) { + port0 := os.Getenv("PORT0") + port1 := os.Getenv("PORT1") + + names, err := List() + if err != nil { + t.Fatal(err) + } + + for _, name := range names { + t.Log("got", name) + + switch { + case name == port0: + port0 = "" + case name == port1: + port1 = "" + } + + if _, err := os.Lstat(name); err != nil { + t.Errorf("%s: unreachable: %s", name, err) + } + } + + if port0 != "" { + t.Errorf("PORT0=%q not found", port0) + } + if port1 != "" { + t.Errorf("PORT1=%q not found", port1) + } +} From e2deb6ac7ea2a024feb7734d02bedcbb49ce42ee Mon Sep 17 00:00:00 2001 From: "Pascal S. de Kloe" Date: Fri, 6 Oct 2017 03:54:20 +0200 Subject: [PATCH 2/4] Function name typo. --- list_linux_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/list_linux_test.go b/list_linux_test.go index a3e51e3..2ef39e1 100644 --- a/list_linux_test.go +++ b/list_linux_test.go @@ -9,7 +9,7 @@ func TestListRX(t *testing.T) { port0 := os.Getenv("PORT0") port1 := os.Getenv("PORT1") - names, err := List() + names, err := ListRX() if err != nil { t.Fatal(err) } From 47dd4af4b7373625406f7f1605c0c583c089d5c0 Mon Sep 17 00:00:00 2001 From: "Pascal S. de Kloe" Date: Fri, 6 Oct 2017 04:25:31 +0200 Subject: [PATCH 3/4] Resolve device file from uevent (to skip missing device files). --- list_linux.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/list_linux.go b/list_linux.go index d781f60..546d3af 100644 --- a/list_linux.go +++ b/list_linux.go @@ -1,6 +1,9 @@ package serial import ( + "bytes" + "io/ioutil" + "os" "path/filepath" "sort" ) @@ -12,9 +15,18 @@ func ListRX() (names []string, err error) { return nil, err } - names = make([]string, len(matches)) - for i, m := range matches { - names[i] = "/dev/" + filepath.Base(filepath.Dir(m)) + names = make([]string, 0, len(matches)) + for _, m := range matches { + uevent, err := ioutil.ReadFile(filepath.Clean(m + "/../uevent")) + if err != nil && !os.IsNotExist(err) { + return nil, err + } + for _, line := range bytes.Split(uevent, []byte{'\n'}) { + if bytes.HasPrefix(line, []byte("DEVNAME=")) { + names = append(names, "/dev/"+string(line[8:])) + break + } + } } sort.Strings(names) From 9afef3034f5cfae43c0c81fdf6015216e383f81c Mon Sep 17 00:00:00 2001 From: "Pascal S. de Kloe" Date: Fri, 6 Oct 2017 04:34:10 +0200 Subject: [PATCH 4/4] Check for device file existence too. --- list_linux.go | 10 +++++++++- list_linux_test.go | 4 ---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/list_linux.go b/list_linux.go index 546d3af..13b6fe3 100644 --- a/list_linux.go +++ b/list_linux.go @@ -21,12 +21,20 @@ func ListRX() (names []string, err error) { if err != nil && !os.IsNotExist(err) { return nil, err } + + var name string for _, line := range bytes.Split(uevent, []byte{'\n'}) { if bytes.HasPrefix(line, []byte("DEVNAME=")) { - names = append(names, "/dev/"+string(line[8:])) + name = "/dev/" + string(line[8:]) break } } + + if _, err := os.Lstat(name); err == nil { + names = append(names, name) + } else if !os.IsNotExist(err) { + return nil, err + } } sort.Strings(names) diff --git a/list_linux_test.go b/list_linux_test.go index 2ef39e1..b153af6 100644 --- a/list_linux_test.go +++ b/list_linux_test.go @@ -23,10 +23,6 @@ func TestListRX(t *testing.T) { case name == port1: port1 = "" } - - if _, err := os.Lstat(name); err != nil { - t.Errorf("%s: unreachable: %s", name, err) - } } if port0 != "" {