usbmon.go (1931B)
1 package usbmon 2 3 import ( 4 "context" 5 "strings" 6 ) 7 8 type Device struct { 9 properties map[string]string 10 } 11 12 func (d *Device) Serial() string { 13 return d.properties["ID_SERIAL_SHORT"] 14 } 15 16 func (d *Device) Properties() map[string]string { 17 return d.properties 18 } 19 20 func (d *Device) Vendor() string { 21 return d.properties["ID_VENDOR"] 22 } 23 24 func (d *Device) Action() string { 25 return d.properties["ACTION"] 26 } 27 28 func (d *Device) Major() string { 29 return d.properties["MAJOR"] 30 } 31 32 func (d *Device) Minor() string { 33 return d.properties["MINOR"] 34 } 35 36 func (d *Device) Path() string { 37 return d.properties["DEVPATH"] 38 } 39 40 func (d *Device) VendorID() string { 41 product := d.properties["PRODUCT"] 42 parts := strings.Split(product, "/") 43 if len(parts) < 2 { 44 return "" 45 } 46 return parts[0] 47 } 48 49 func (d *Device) ProductID() string { 50 product := d.properties["PRODUCT"] 51 parts := strings.Split(product, "/") 52 if len(parts) < 2 { 53 return "" 54 } 55 return parts[1] 56 } 57 58 func Listen(ctx context.Context) (chan *Device, error) { 59 return ListenFiltered(ctx) 60 } 61 62 // ListenFiltered returns the usb storage devices that match all the filters passed 63 // as arguments. 64 // 65 // Filters are additive, meaning every device needs to match all the filter arguments. 66 // 67 // Example: 68 func ListenFiltered(ctx context.Context, filters ...Filter) (chan *Device, error) { 69 m := NewUdevMonitor() 70 devchan := make(chan *Device) 71 ch, ech, err := m.DeviceChan(ctx) 72 if err != nil { 73 return nil, err 74 } 75 76 var lerr error 77 go func() { 78 Loop: 79 for { 80 select { 81 case <-ctx.Done(): 82 close(devchan) 83 return 84 case lerr = <-ech: 85 break Loop 86 case d := <-ch: 87 dev := &Device{ 88 properties: d.Properties(), 89 } 90 91 if filters == nil { 92 devchan <- dev 93 continue 94 } 95 96 match := true 97 for _, f := range filters { 98 if !f.Matches(dev) { 99 match = false 100 break 101 } 102 } 103 104 if match { 105 devchan <- dev 106 } 107 } 108 } 109 }() 110 111 return devchan, lerr 112 }