@@ -104,6 +104,16 @@ func (s *scanner) ScanDevices() ([]*types.Device, error) {
104104 devpath = strings.TrimSuffix(devpath, "/"+parts[i])
105105
106106 if device, ok := devicesMap[devpath]; ok {
107+ // vendor and product IDs may be set at child or
108+ // parent levels. If a child doesn't have one, get
109+ // it from the parent.
110+ if v.VendorID == "" {
111+ v.VendorID = device.VendorID
112+ }
113+ if v.ProductID == "" {
114+ v.ProductID = device.ProductID
115+ }
116+
107117 v.Parent = device
108118 device.Children = append(device.Children, v)
109119 break
@@ -133,6 +143,13 @@ func (s *scanner) getDevice(path string) (*types.Device, error) {
133143 Parent: nil,
134144 }
135145
146+ if id, ok := s.readId(filepath.Join(filepath.Dir(path), "idVendor")); ok {
147+ device.VendorID = id
148+ }
149+ if id, ok := s.readId(filepath.Join(filepath.Dir(path), "idProduct")); ok {
150+ device.ProductID = id
151+ }
152+
136153 err = s.readUeventFile(path, device)
137154 if err != nil {
138155 return nil, err
@@ -141,6 +158,30 @@ func (s *scanner) getDevice(path string) (*types.Device, error) {
141158 return device, nil
142159}
143160
161+ func (s *scanner) readId(path string) (string, bool) {
162+ _, err := s.opts.devicesRoot.Stat(path)
163+ if err != nil {
164+ return "", false
165+ }
166+
167+ f, err := s.opts.devicesRoot.Open(path)
168+ if err != nil {
169+ return "", false
170+ }
171+
172+ defer func() {
173+ if err := f.Close(); err != nil {
174+ slog.Debug("cannot close ID file", "error", err)
175+ }
176+ }()
177+
178+ d, err := io.ReadAll(io.LimitReader(f, maxDevSize))
179+ if err != nil {
180+ return "", false
181+ }
182+ return strings.Trim(string(d), "\n\r\t "), true
183+ }
184+
144185func (s *scanner) readAttrs(path string) (map[string]string, error) {
145186 attrs := map[string]string{}
146187 files, err := fs.ReadDir(s.opts.devicesRoot.FS(), path)
0 commit comments