usb-ks

USB Killswitch
git clone git://git.laack.co/usb-ks.git
Log | Files | Refs | README | LICENSE

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 }