From b52df192cccab19610305cb824157323c9d5bd67 Mon Sep 17 00:00:00 2001 From: Ben <57039667+ben-qnimble@users.noreply.github.com> Date: Mon, 18 Oct 2021 10:30:20 -0400 Subject: [PATCH 1/3] Report Interface Number in Windows and Linux --- enumerator/enumerator.go | 1 + enumerator/usb_linux.go | 5 +++++ enumerator/usb_windows.go | 18 ++++++++++-------- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/enumerator/enumerator.go b/enumerator/enumerator.go index 6f0f32d..a253a17 100644 --- a/enumerator/enumerator.go +++ b/enumerator/enumerator.go @@ -15,6 +15,7 @@ type PortDetails struct { IsUSB bool VID string PID string + MI string SerialNumber string // Manufacturer string diff --git a/enumerator/usb_linux.go b/enumerator/usb_linux.go index bad2323..15b20d7 100644 --- a/enumerator/usb_linux.go +++ b/enumerator/usb_linux.go @@ -72,6 +72,10 @@ func parseUSBSysFS(usbDevicePath string, details *PortDetails) error { if err != nil { return err } + mi, err := readLine(filepath.Join(usbDevicePath, "bInterfaceNumber")) + if err != nil { + return err + } serial, err := readLine(filepath.Join(usbDevicePath, "serial")) if err != nil { return err @@ -88,6 +92,7 @@ func parseUSBSysFS(usbDevicePath string, details *PortDetails) error { details.IsUSB = true details.VID = vid details.PID = pid + details.MI = mi details.SerialNumber = serial //details.Manufacturer = manufacturer //details.Product = product diff --git a/enumerator/usb_windows.go b/enumerator/usb_windows.go index b69e115..8b5f172 100644 --- a/enumerator/usb_windows.go +++ b/enumerator/usb_windows.go @@ -18,32 +18,34 @@ import ( func parseDeviceID(deviceID string, details *PortDetails) { // Windows stock USB-CDC driver if len(deviceID) >= 3 && deviceID[:3] == "USB" { - re := regexp.MustCompile("VID_(....)&PID_(....)(\\\\(\\w+)$)?").FindAllStringSubmatch(deviceID, -1) - if re == nil || len(re[0]) < 2 { + re := regexp.MustCompile("VID_(....)&PID_(....)&MI_(..)(\\\\(\\w+)$)?").FindAllStringSubmatch(deviceID, -1) + if re == nil || len(re[0]) < 3 { // Silently ignore unparsable strings return } details.IsUSB = true details.VID = re[0][1] details.PID = re[0][2] - if len(re[0]) >= 4 { - details.SerialNumber = re[0][4] + details.MI = re[0][3] + if len(re[0]) >= 5 { + details.SerialNumber = re[0][5] } return } // FTDI driver if len(deviceID) >= 7 && deviceID[:7] == "FTDIBUS" { - re := regexp.MustCompile("VID_(....)\\+PID_(....)(\\+(\\w+))?").FindAllStringSubmatch(deviceID, -1) - if re == nil || len(re[0]) < 2 { + re := regexp.MustCompile("VID_(....)\\+PID_(....)+MI_(..)(\\+(\\w+))?").FindAllStringSubmatch(deviceID, -1) + if re == nil || len(re[0]) < 3 { // Silently ignore unparsable strings return } details.IsUSB = true details.VID = re[0][1] details.PID = re[0][2] - if len(re[0]) >= 4 { - details.SerialNumber = re[0][4] + details.MI = re[0][3] + if len(re[0]) >= 5 { + details.SerialNumber = re[0][5] } return } From 60f5d256968562c294e47e5878e3ce3e92e3a8ad Mon Sep 17 00:00:00 2001 From: Ben <57039667+ben-qnimble@users.noreply.github.com> Date: Wed, 27 Oct 2021 18:02:42 -0400 Subject: [PATCH 2/3] Fix issue with serial number not reporting in windows because MI parsing forced. Now it is optional in regex --- enumerator/usb_windows.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/enumerator/usb_windows.go b/enumerator/usb_windows.go index 8b5f172..1876dfc 100644 --- a/enumerator/usb_windows.go +++ b/enumerator/usb_windows.go @@ -18,7 +18,7 @@ import ( func parseDeviceID(deviceID string, details *PortDetails) { // Windows stock USB-CDC driver if len(deviceID) >= 3 && deviceID[:3] == "USB" { - re := regexp.MustCompile("VID_(....)&PID_(....)&MI_(..)(\\\\(\\w+)$)?").FindAllStringSubmatch(deviceID, -1) + re := regexp.MustCompile("VID_(....)&PID_(....)(?:&MI_(..)){0,1}(\\\\(\\w+)$)?").FindAllStringSubmatch(deviceID, -1) if re == nil || len(re[0]) < 3 { // Silently ignore unparsable strings return @@ -26,8 +26,11 @@ func parseDeviceID(deviceID string, details *PortDetails) { details.IsUSB = true details.VID = re[0][1] details.PID = re[0][2] - details.MI = re[0][3] - if len(re[0]) >= 5 { + if len(re[0]) > 4 { + details.MI = re[0][3] + } + + if len(re[0]) >= 6 { details.SerialNumber = re[0][5] } return @@ -35,7 +38,7 @@ func parseDeviceID(deviceID string, details *PortDetails) { // FTDI driver if len(deviceID) >= 7 && deviceID[:7] == "FTDIBUS" { - re := regexp.MustCompile("VID_(....)\\+PID_(....)+MI_(..)(\\+(\\w+))?").FindAllStringSubmatch(deviceID, -1) + re := regexp.MustCompile("VID_(....)\\+PID_(....)(?:+MI_(..)){0,1}(\\+(\\w+))?").FindAllStringSubmatch(deviceID, -1) if re == nil || len(re[0]) < 3 { // Silently ignore unparsable strings return @@ -43,8 +46,12 @@ func parseDeviceID(deviceID string, details *PortDetails) { details.IsUSB = true details.VID = re[0][1] details.PID = re[0][2] - details.MI = re[0][3] - if len(re[0]) >= 5 { + + if len(re[0]) > 4 { + details.MI = re[0][3] + } + + if len(re[0]) >= 6 { details.SerialNumber = re[0][5] } return From 20c09dec06af530a339d9e469cb7faba8cb2219a Mon Sep 17 00:00:00 2001 From: Ben <57039667+ben-qnimble@users.noreply.github.com> Date: Wed, 27 Oct 2021 20:14:12 -0400 Subject: [PATCH 3/3] Fix mistake in parsing interface number under linux --- enumerator/usb_linux.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/enumerator/usb_linux.go b/enumerator/usb_linux.go index 15b20d7..e84169f 100644 --- a/enumerator/usb_linux.go +++ b/enumerator/usb_linux.go @@ -12,7 +12,7 @@ import ( "os" "path/filepath" - "go.bug.st/serial" + "github.com/ben-qnimble/go-serial" ) func nativeGetDetailedPortsList() ([]*PortDetails, error) { @@ -50,12 +50,17 @@ func nativeGetPortDetails(portPath string) (*PortDetails, error) { subSystem := filepath.Base(subSystemPath) result := &PortDetails{Name: portPath} + mi, err := readLine(filepath.Join(realDevicePath, "bInterfaceNumber")) + if err != nil { + return nil, fmt.Errorf("Can't determine interface number of %s: %s", filepath.Join(realDevicePath, "bInterfaceNumber"), err.Error()) + } + switch subSystem { case "usb-serial": - err := parseUSBSysFS(filepath.Dir(filepath.Dir(realDevicePath)), result) + err := parseUSBSysFS(filepath.Dir(filepath.Dir(realDevicePath)), result, mi) return result, err case "usb": - err := parseUSBSysFS(filepath.Dir(realDevicePath), result) + err := parseUSBSysFS(filepath.Dir(realDevicePath), result, mi) return result, err // TODO: other cases? default: @@ -63,7 +68,7 @@ func nativeGetPortDetails(portPath string) (*PortDetails, error) { } } -func parseUSBSysFS(usbDevicePath string, details *PortDetails) error { +func parseUSBSysFS(usbDevicePath string, details *PortDetails, mi string) error { vid, err := readLine(filepath.Join(usbDevicePath, "idVendor")) if err != nil { return err @@ -72,10 +77,7 @@ func parseUSBSysFS(usbDevicePath string, details *PortDetails) error { if err != nil { return err } - mi, err := readLine(filepath.Join(usbDevicePath, "bInterfaceNumber")) - if err != nil { - return err - } + serial, err := readLine(filepath.Join(usbDevicePath, "serial")) if err != nil { return err