github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/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 (b *Backend) reloadRules(subsystemTriggers []string) error { 36 if b.preseed { 37 return nil 38 } 39 40 output, err := exec.Command("udevadm", "control", "--reload-rules").CombinedOutput() 41 if err != nil { 42 return fmt.Errorf("cannot reload udev rules: %s\nudev output:\n%s", err, string(output)) 43 } 44 45 // By default, trigger for all events except the input subsystem since 46 // it can cause noticeable blocked input on, for example, classic 47 // desktop. 48 output, err = exec.Command("udevadm", "trigger", "--subsystem-nomatch=input").CombinedOutput() 49 if err != nil { 50 return fmt.Errorf("cannot run udev triggers: %s\nudev output:\n%s", err, string(output)) 51 } 52 53 // FIXME: track if also should trigger the joystick property if it 54 // wasn't already since we are not able to detect interfaces that are 55 // removed and set subsystemTriggers correctly. When we can, remove 56 // this. Allows joysticks to be removed from the device cgroup on 57 // interface disconnect. 58 inputJoystickTriggered := false 59 60 for _, subsystem := range subsystemTriggers { 61 if subsystem == "input/joystick" { 62 // If one of the interfaces said it uses the input 63 // subsystem for joysticks, then trigger the joystick 64 // events in a way that is specific to joysticks to not 65 // block other inputs. 66 output, err = exec.Command("udevadm", "trigger", "--property-match=ID_INPUT_JOYSTICK=1").CombinedOutput() 67 if err != nil { 68 return fmt.Errorf("cannot run udev triggers for joysticks: %s\nudev output:\n%s", err, string(output)) 69 } 70 inputJoystickTriggered = true 71 } else if subsystem == "input/key" { 72 // If one of the interfaces said it uses the input 73 // subsystem for input keys, then trigger the keys 74 // events in a way that is specific to input keys 75 // to not block other inputs. 76 output, err = exec.Command("udevadm", "trigger", "--property-match=ID_INPUT_KEY=1", "--property-match=ID_INPUT_KEYBOARD!=1").CombinedOutput() 77 if err != nil { 78 return fmt.Errorf("cannot run udev triggers for keys: %s\nudev output:\n%s", err, string(output)) 79 } 80 } else if subsystem != "" { 81 // If one of the interfaces said it uses a subsystem, 82 // then do it too. 83 output, err = exec.Command("udevadm", "trigger", "--subsystem-match="+subsystem).CombinedOutput() 84 if err != nil { 85 return fmt.Errorf("cannot run udev triggers for %s subsystem: %s\nudev output:\n%s", subsystem, err, string(output)) 86 } 87 88 if subsystem == "input" { 89 inputJoystickTriggered = true 90 } 91 } 92 } 93 94 // FIXME: if not already triggered, trigger the joystick property if it 95 // wasn't already since we are not able to detect interfaces that are 96 // removed and set subsystemTriggers correctly. When we can, remove 97 // this. Allows joysticks to be removed from the device cgroup on 98 // interface disconnect. 99 if !inputJoystickTriggered { 100 output, err = exec.Command("udevadm", "trigger", "--property-match=ID_INPUT_JOYSTICK=1").CombinedOutput() 101 if err != nil { 102 return fmt.Errorf("cannot run udev triggers for joysticks: %s\nudev output:\n%s", err, string(output)) 103 } 104 } 105 106 // give our triggered events a chance to be handled before exiting. 107 // Ignore errors since we don't want to error on still pending events. 108 _ = exec.Command("udevadm", "settle", "--timeout=10").Run() 109 110 return nil 111 }