-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathusbmon.go
89 lines (73 loc) · 1.48 KB
/
usbmon.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package usbmon
import (
"context"
)
type Device struct {
properties map[string]string
}
func (d *Device) Serial() string {
return d.properties["ID_SERIAL_SHORT"]
}
func (d *Device) Properties() map[string]string {
return d.properties
}
func (d *Device) Vendor() string {
return d.properties["ID_VENDOR"]
}
func (d *Device) Action() string {
return d.properties["ACTION"]
}
func (d *Device) Major() string {
return d.properties["MAJOR"]
}
func (d *Device) Minor() string {
return d.properties["MINOR"]
}
func (d *Device) Path() string {
return d.properties["DEVPATH"]
}
func Listen(ctx context.Context) (chan *Device, error) {
return ListenFiltered(ctx)
}
// ListenFiltered returns the usb storage devices that match all the filters passed
// as arguments.
//
// Filters are additive, meaning every device needs to match all the filter arguments.
//
// Example:
func ListenFiltered(ctx context.Context, filters ...Filter) (chan *Device, error) {
m := NewUdevMonitor()
devchan := make(chan *Device)
ch, err := m.DeviceChan(ctx)
if err != nil {
return nil, err
}
go func() {
for {
select {
case <-ctx.Done():
close(devchan)
return
case d := <-ch:
dev := &Device{
properties: d.Properties(),
}
if filters == nil {
devchan <- dev
continue
}
match := true
for _, f := range filters {
if !f.Matches(dev) {
match = false
break
}
}
if match {
devchan <- dev
}
}
}
}()
return devchan, nil
}