github.com/rigado/snapd@v2.42.5-go-mod+incompatible/interfaces/udev/udev.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2018 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package udev 21 22 import ( 23 "fmt" 24 "os/exec" 25 ) 26 27 // ReloadRules runs three commands that reload udev rule database. 28 // 29 // The commands are: udevadm control --reload-rules 30 // udevadm trigger --subsystem-nomatch=input 31 // udevadm settle --timeout=3 32 // and optionally trigger other subsystems as defined in the interfaces. Eg: 33 // udevadm trigger --subsystem-match=input 34 // udevadm trigger --property-match=ID_INPUT_JOYSTICK=1 35 func ReloadRules(subsystemTriggers []string) error { 36 output, err := exec.Command("udevadm", "control", "--reload-rules").CombinedOutput() 37 if err != nil { 38 return fmt.Errorf("cannot reload udev rules: %s\nudev output:\n%s", err, string(output)) 39 } 40 41 // By default, trigger for all events except the input subsystem since 42 // it can cause noticeable blocked input on, for example, classic 43 // desktop. 44 output, err = exec.Command("udevadm", "trigger", "--subsystem-nomatch=input").CombinedOutput() 45 if err != nil { 46 return fmt.Errorf("cannot run udev triggers: %s\nudev output:\n%s", err, string(output)) 47 } 48 49 // FIXME: track if also should trigger the joystick property if it 50 // wasn't already since we are not able to detect interfaces that are 51 // removed and set subsystemTriggers correctly. When we can, remove 52 // this. Allows joysticks to be removed from the device cgroup on 53 // interface disconnect. 54 inputJoystickTriggered := false 55 56 for _, subsystem := range subsystemTriggers { 57 if subsystem == "input/joystick" { 58 // If one of the interfaces said it uses the input 59 // subsystem for joysticks, then trigger the joystick 60 // events in a way that is specific to joysticks to not 61 // block other inputs. 62 output, err = exec.Command("udevadm", "trigger", "--property-match=ID_INPUT_JOYSTICK=1").CombinedOutput() 63 if err != nil { 64 return fmt.Errorf("cannot run udev triggers for joysticks: %s\nudev output:\n%s", err, string(output)) 65 } 66 inputJoystickTriggered = true 67 } else if subsystem == "input/key" { 68 // If one of the interfaces said it uses the input 69 // subsystem for input keys, then trigger the keys 70 // events in a way that is specific to input keys 71 // to not block other inputs. 72 output, err = exec.Command("udevadm", "trigger", "--property-match=ID_INPUT_KEY=1", "--property-match=ID_INPUT_KEYBOARD!=1").CombinedOutput() 73 if err != nil { 74 return fmt.Errorf("cannot run udev triggers for keys: %s\nudev output:\n%s", err, string(output)) 75 } 76 } else if subsystem != "" { 77 // If one of the interfaces said it uses a subsystem, 78 // then do it too. 79 output, err = exec.Command("udevadm", "trigger", "--subsystem-match="+subsystem).CombinedOutput() 80 if err != nil { 81 return fmt.Errorf("cannot run udev triggers for %s subsystem: %s\nudev output:\n%s", subsystem, err, string(output)) 82 } 83 84 if subsystem == "input" { 85 inputJoystickTriggered = true 86 } 87 } 88 } 89 90 // FIXME: if not already triggered, trigger the joystick property if it 91 // wasn't already since we are not able to detect interfaces that are 92 // removed and set subsystemTriggers correctly. When we can, remove 93 // this. Allows joysticks to be removed from the device cgroup on 94 // interface disconnect. 95 if !inputJoystickTriggered { 96 output, err = exec.Command("udevadm", "trigger", "--property-match=ID_INPUT_JOYSTICK=1").CombinedOutput() 97 if err != nil { 98 return fmt.Errorf("cannot run udev triggers for joysticks: %s\nudev output:\n%s", err, string(output)) 99 } 100 } 101 102 // give our triggered events a chance to be handled before exiting. 103 // Ignore errors since we don't want to error on still pending events. 104 _ = exec.Command("udevadm", "settle", "--timeout=10").Run() 105 106 return nil 107 }