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..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,6 +77,7 @@ func parseUSBSysFS(usbDevicePath string, details *PortDetails) error { if err != nil { return err } + serial, err := readLine(filepath.Join(usbDevicePath, "serial")) if err != nil { return err @@ -88,6 +94,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..1876dfc 100644 --- a/enumerator/usb_windows.go +++ b/enumerator/usb_windows.go @@ -18,32 +18,41 @@ 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_(..)){0,1}(\\\\(\\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] + if len(re[0]) > 4 { + details.MI = re[0][3] + } + + if len(re[0]) >= 6 { + 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_(..)){0,1}(\\+(\\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] + + if len(re[0]) > 4 { + details.MI = re[0][3] + } + + if len(re[0]) >= 6 { + details.SerialNumber = re[0][5] } return }