diff --git a/accounts/usbwallet/hub.go b/accounts/usbwallet/hub.go index e67942dbc107..68167c0fcc89 100644 --- a/accounts/usbwallet/hub.go +++ b/accounts/usbwallet/hub.go @@ -27,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/karalabe/usb" + "golang.org/x/exp/slices" ) // LedgerScheme is the protocol scheme prefixing account and wallet URLs. @@ -48,7 +49,7 @@ type Hub struct { scheme string // Protocol scheme prefixing account and wallet URLs. vendorID uint16 // USB vendor identifier used for device discovery productIDs []uint16 // USB product identifiers used for device discovery - usageID uint16 // USB usage page identifier used for macOS device discovery + usageIDs []uint16 // USB usage page identifier used for macOS device discovery endpointID int // USB endpoint identifier used for non-macOS device discovery makeDriver func(log.Logger) driver // Factory method to construct a vendor specific driver @@ -93,22 +94,22 @@ func NewLedgerHub() (*Hub, error) { 0x4011, /* HID + WebUSB Ledger Nano X */ 0x5011, /* HID + WebUSB Ledger Nano S Plus */ 0x6011, /* HID + WebUSB Ledger Nano FTS */ - }, 0xffa0, 0, newLedgerDriver) + }, []uint16{0xffa0, 0}, 2, newLedgerDriver) } // NewTrezorHubWithHID creates a new hardware wallet manager for Trezor devices. func NewTrezorHubWithHID() (*Hub, error) { - return newHub(TrezorScheme, 0x534c, []uint16{0x0001 /* Trezor HID */}, 0xff00, 0, newTrezorDriver) + return newHub(TrezorScheme, 0x534c, []uint16{0x0001 /* Trezor HID */}, []uint16{0xff00}, 0, newTrezorDriver) } // NewTrezorHubWithWebUSB creates a new hardware wallet manager for Trezor devices with // firmware version > 1.8.0 func NewTrezorHubWithWebUSB() (*Hub, error) { - return newHub(TrezorScheme, 0x1209, []uint16{0x53c1 /* Trezor WebUSB */}, 0xffff /* No usage id on webusb, don't match unset (0) */, 0, newTrezorDriver) + return newHub(TrezorScheme, 0x1209, []uint16{0x53c1 /* Trezor WebUSB */}, []uint16{0xffff} /* No usage id on webusb, don't match unset (0) */, 0, newTrezorDriver) } // newHub creates a new hardware wallet manager for generic USB devices. -func newHub(scheme string, vendorID uint16, productIDs []uint16, usageID uint16, endpointID int, makeDriver func(log.Logger) driver) (*Hub, error) { +func newHub(scheme string, vendorID uint16, productIDs []uint16, usageIDs []uint16, endpointID int, makeDriver func(log.Logger) driver) (*Hub, error) { if !usb.Supported() { return nil, errors.New("unsupported platform") } @@ -116,7 +117,7 @@ func newHub(scheme string, vendorID uint16, productIDs []uint16, usageID uint16, scheme: scheme, vendorID: vendorID, productIDs: productIDs, - usageID: usageID, + usageIDs: usageIDs, endpointID: endpointID, makeDriver: makeDriver, quit: make(chan chan error), @@ -184,12 +185,8 @@ func (hub *Hub) refreshWallets() { hub.enumFails.Store(0) for _, info := range infos { - for _, id := range hub.productIDs { - // Windows and Macos use UsageID matching, Linux uses Interface matching - if info.ProductID == id && (info.UsagePage == hub.usageID || info.Interface == hub.endpointID) { - devices = append(devices, info) - break - } + if hub.matchDevice(info) { + devices = append(devices, info) } } if runtime.GOOS == "linux" { @@ -248,6 +245,13 @@ func (hub *Hub) refreshWallets() { } } +func (hub *Hub) matchDevice(info usb.DeviceInfo) bool { + // Windows and Macos use UsageID matching, Linux uses Interface matching + return slices.Contains(hub.productIDs, info.ProductID) && + info.Path != "" && + (slices.Contains(hub.usageIDs, info.UsagePage) || info.Interface == hub.endpointID) +} + // Subscribe implements accounts.Backend, creating an async subscription to // receive notifications on the addition or removal of USB wallets. func (hub *Hub) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription {