Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revisionBoth sides next revision
docs:guide-user:base-system:hotplug [2022/02/16 23:43] – [iface] improve formatting of added text a bit vpelletierdocs:guide-user:base-system:hotplug [2024/08/23 10:25] – Avoid duplication/duplicate execution oliv3r
Line 1: Line 1:
 ====== Hotplug ====== ====== Hotplug ======
-Procd (the init system and process management daemon) executes scripts located in ''/etc/hotplug.d/'' when certain events happen, like for example when an interface goes up or down, when a new storage drive is detected, or when a button is pressed.+Procd (the init system and process management daemon) executes scripts located in ''/etc/hotplug.d'' when certain events happen, like for example when an interface goes up or down, when a new storage drive is detected, or when a button is pressed.
 It can be very useful with PPPoE connection or in an unstable network, or to use hardware buttons. It can be very useful with PPPoE connection or in an unstable network, or to use hardware buttons.
  
Line 11: Line 11:
 Which is why most scripts in there use a numeric prefix. Which is why most scripts in there use a numeric prefix.
  
-^ Directory ^ Description ^ +^ Directory     ^ Description                                                                                               
-| **block** | Block device events: device connected/disconnected | +| **block**     | Block device events: device connected/disconnected                                                        
-| **button** | Buttons: not created by default, see [[docs:guide-user:hardware:hardware.button|/etc/rc.button]] instead | +| **button**    | Buttons: not created by default, see [[docs:guide-user:hardware:hardware.button|/etc/rc.button]] instead  
-| **dhcp** | DHCP-related events | +| **dhcp**      | DHCP-related events                                                                                       | 
-| **firewall** | Firewall-related events | +| **dsl**       | DSL modem events                                                                                          
-| **iface** | Interface events: LAN/WAN/etc. is connected/disconnected | +| **firewall**  | Firewall-related events                                                                                   
-| **neigh** | Neighbor discovery | +| **iface**     | Interface events: LAN/WAN/etc. is connected/disconnected                                                  
-| **net** | Network-related events | +| **neigh**     | Neighbor discovery                                                                                        
-| **ntp** | Time sync events: time step, time server stratum change | +| **net**       | Network-related events                                                                                    
-| **tftp** | TFTP-related events | +| **ntp**       | Time sync events: time step, time server stratum change                                                   
-| **usb** | USB devices like 3g-modem and tty* |+| **tftp**      | TFTP-related events                                                                                       | 
 +| **tty**       | TTY-related events, including but not limited to WWAN modems, but pointing directly to TTY interface      
 +| **usb**       | USB devices like 3g-modem and tty*                                                                        | 
 +| **usbmisc**   | Special USB peripherals like printers (scripts in this subsystem have fewer variables available)          |
  
 See also: See also:
-  * [[docs:guide-user:network:protocol.dhcp#dhcp_client_scripts|DHCP client scripts]] 
   * [[https://github.com/openwrt/openwrt/blob/master/package/system/procd/files/hotplug.json|Buttons, sound devices, serial and USB serial dongles]]   * [[https://github.com/openwrt/openwrt/blob/master/package/system/procd/files/hotplug.json|Buttons, sound devices, serial and USB serial dongles]]
   * [[https://github.com/openwrt/openwrt/blob/master/package/network/services/dnsmasq/files/dhcp-script.sh|DHCP, NDP, TFTP]]   * [[https://github.com/openwrt/openwrt/blob/master/package/network/services/dnsmasq/files/dhcp-script.sh|DHCP, NDP, TFTP]]
 +  * [[docs:guide-user:network:protocol.dhcp#dhcp_client_scripts|DHCP client scripts]]
  
 ===== Usage / Troubleshooting ===== ===== Usage / Troubleshooting =====
Line 48: Line 51:
  
 ===== Event classes / Directories ===== ===== Event classes / Directories =====
 +==== net ====
 +For scripts in **net** directory, these are the (relevant) environmental variables
 +
 +^ Variable name ^ Description ^ 
 +| ACTION | "add" or "remove" noted |
 +| DEVICENAME | configured interface names (br-lan, wlan0, phy1-ap0 |
 +| PATH | Full path |
 +| DEVPATH | full device path (for example "/devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.0/host7/target7:0:0/7:0:0:0/block/sdc/sdc1 " |
 +| DEVTYPE | what the DEVICENAME are names of, ie. br-lan, phy1-ap0 |
 +| INTERFACE | configured interfaces as in DEVTYPE |
 +| SEQNUM | seqnum (a number) |
 +| SUBSYSTEM | always = "net" |
 +| IFINDEX | appears to be related to the configured interfaces. See `ifconfig` |
 +
 ==== block ==== ==== block ====
 For scripts in **block** directory, these are the (relevant) environmental variables For scripts in **block** directory, these are the (relevant) environmental variables
Line 61: Line 78:
 | SEQNUM | seqnum (a number) | | SEQNUM | seqnum (a number) |
 | SUBSYSTEM | seems this is only "block" | | SUBSYSTEM | seems this is only "block" |
 +
 +==== dsl ====
 +For scripts in **dsl** directory, these are the (relevant) environment variables
 +
 +^ Variable name ^ Description ^
 +| DSL_NOTIFICATION_TYPE | ''DSL_STATUS'', ''DSL_INTERFACE_STATUS'', ''DSL_DATARATE_STATUS_US'', ''DSL_DATARATE_STATUS_DS'' |
 +| DSL_LINE_NUMBER | ''0'', ''1'' * |
 +
 +When DSL_NOTIFICATION_TYPE is ''DSL_STATUS'', the following environment variables are set
 +
 +^ Variable name ^ Description ^
 +| DSL_XTU_STATUS | ''ADSL'', ''VDSL'' |
 +| DSL_TC_LAYER_STATUS | ''ATM'', ''EFM'' |
 +| DSL_EFM_TC_CONFIG_US | ''NORMAL'', ''PRE_EMPTION'', ''UNKNOWN'' |
 +| DSL_EFM_TC_CONFIG_DS | ''NORMAL'', ''UNKNOWN'' |
 +
 +When DSL_NOTIFICATION_TYPE is ''DSL_INTERFACE_STATUS'', the following environment variables are set
 +
 +^ Variable name ^ Description ^
 +| DSL_INTERFACE_STATUS | ''DOWN'', ''READY'', ''HANDSHAKE'', ''TRAINING'', ''UP'' |
 +| DSL_BONDING_STATUS | ''INACTIVE'', ''ACTIVE'' * |
 +
 +When DSL_NOTIFICATION_TYPE is ''DSL_DATARATE_STATUS_US'', the following environment variables are set
 +
 +^ Variable name ^ Description ^
 +| DSL_DATARATE_US_BC0 | Upstream data rate in bit/s for Channel 0 |
 +| DSL_DATARATE_US_BC1 | Upstream data rate in bit/s for Channel 1 * |
 +
 +When DSL_NOTIFICATION_TYPE is ''DSL_DATARATE_STATUS_DS'', the following environment variables are set
 +
 +^ Variable name ^ Description ^
 +| DSL_DATARATE_DS_BC0 | Downstream data rate in bit/s for Channel 0 |
 +| DSL_DATARATE_DS_BC1 | Downstream data rate in bit/s for Channel 1 * |
 +
 +NOTE: environment variables marked with an * are only available when channel bonding support is compiled in.
  
 ==== iface ==== ==== iface ====
Line 67: Line 119:
 ^ Variable name ^ Description ^ ^ Variable name ^ Description ^
 | ACTION | ''ifdown'', ''ifup'', ''ifup-failed'', ''ifupdate'', ''free'', ''reload'', ''iflink'', ''create'' | | ACTION | ''ifdown'', ''ifup'', ''ifup-failed'', ''ifupdate'', ''free'', ''reload'', ''iflink'', ''create'' |
-| INTERFACE | Name of the logical interface which went up or down (e.g. ''wan'' or ''ppp0'')| +| INTERFACE | Name of the logical interface which went up or down (e.g. ''wan'' or ''lan'')| 
-| DEVICE | Physical device name which interface went up or down (e.g. ''eth0.1'' or ''br-lan''), when applicable|+| DEVICE | Name of the physical device which went up or down (e.g. ''eth0'' or ''br-lan'' or ''pppoe-wan''), when applicable|
  
 The meaning of most actions should be straightforward, the maybe-not-obvious ones are: The meaning of most actions should be straightforward, the maybe-not-obvious ones are:
 ^ Value ^ Description ^ ^ Value ^ Description ^
 | ''ifup-failed'' | ''ifdown'' event happened while the interface was being brought up | | ''ifup-failed'' | ''ifdown'' event happened while the interface was being brought up |
-| ''free'' | the interface has been removed (inverse of "create") |+| ''free'' | the interface has been removed (inverse of ''create'') |
 | ''iflink'' | the interface reported the presence of a carrier | | ''iflink'' | the interface reported the presence of a carrier |
  
Line 85: Line 137:
  
 ==== ntp ==== ==== ntp ====
 +Variables based on busybox ntpd:
 +
 ^ Variable name ^ description ^ ^ Variable name ^ description ^
 | ACTION | step, stratum, unsync or periodic | | ACTION | step, stratum, unsync or periodic |
 | freq_drift_ppm | ntp variables | | freq_drift_ppm | ntp variables |
-| offset | ntp variables +| offset | Time adjustment done 
-| stratum | ntp variables |+| stratum | Quality (nr of servers to atomic clock) |
 | poll_interval | ntp variables | | poll_interval | ntp variables |
  
-Even without NTP sync, you will receive a "periodic" hotplug event, with stratum=16, about every 11 minutes out of the box.+Even without NTP sync, you will receive a "periodic" hotplug event, with ''stratum=16'', about every 11 minutes out of the box. 
 + 
 +==== tty ==== 
 +^ Variable name ^ description ^ 
 +| ACTION | add, remove, bind, unbind as above | 
 +| DEVICENAME | eg "ttyUSB2"
 +| DEVNAME | only for bind/unbind, eg, "ttyUSB2"
 +| DEVPATH | eg, "/devices/platform/ahb/1b400000.usb/usb2/2-1/2-1:1.3/ttyUSB2"
 +| SEQNUM | (action number since boot for this subsystem) eg 335 | 
 +| SUBSYSTEM | Specific type of device, eg, "usb-serial"
 +| MAJOR | eg 189 | 
 +| MINOR | eg 1 |
  
 ==== usb ==== ==== usb ====
 ^ Variable name ^ description ^ ^ Variable name ^ description ^
-| ACTION | add, remove as above |+| ACTION | add, remove, bind, unbind as above 
 +| DEVICENAME | eg "1-1" |
 | DEVNAME | eg, "bus/usb/001/002" | | DEVNAME | eg, "bus/usb/001/002" |
 +| DEVNUM | eg 002 |
 | DEVPATH | eg, "/devices/platform/ehci-platform/usb1/1-1" | | DEVPATH | eg, "/devices/platform/ehci-platform/usb1/1-1" |
-DEVICENAME | eg "1-1" | +DEVTYPE | eg "usb_device" |
-| DEVNUM | eg 002 | +
-| DRIVER | "usb" |+
 | TYPE | eg 9/0/1 | | TYPE | eg 9/0/1 |
 | PRODUCT | the vendor/productcode/version, eg "424/2640/0" see lsusb | | PRODUCT | the vendor/productcode/version, eg "424/2640/0" see lsusb |
-| SEQNUM | eg 335 |+| SEQNUM | (action number since boot for this subsystem) eg 335 |
 | BUSNUM | eg 001 | | BUSNUM | eg 001 |
 | MAJOR | eg 189 | | MAJOR | eg 189 |
 | MINOR | eg 1 | | MINOR | eg 1 |
 +
 +==== usbmisc ====
 +^ Variable name  ^ description                                             ^
 +| ACTION         | add, remove as above                                    |
 +| DEVNAME        | eg, "bus/usb/001/002"                                   |
 +| DEVPATH        | eg, "/devices/platform/ehci-platform/usb1/1-1"          |
 +| DEVICENAME     | eg "1-1"                                                |
 +| SEQNUM          (action number since boot for this subsystem) eg 335   |
 +| MAJOR          | eg 189                                                  |
 +| MINOR          | eg 1                                                    |
 +
  
 ===== Examples ===== ===== Examples =====
Line 119: Line 195:
  
 Every time an interface goes up then the if/fi statement will be executed. Every time an interface goes up then the if/fi statement will be executed.
- 
-==== Restart wlan on USB WiFi hotplug ==== 
-Niii has posted this quick example for a USB WiFi device hotplug event to trigger an init.d network restart wlan0 script. 
- 
-To determine RTL8188SU_PRODID variable: 
- 
-<code bash># lsusb -v 
-  idVendor           0x0bda Realtek Semiconductor Corp. 
-  idProduct          0x8171 RTL8188SU 802.11n WLAN Adapter 
-  bcdDevice            2.00 
-</code> 
- 
-<code bash> 
-mkdir -p /etc/hotplug.d/usb 
-cat << "EOF" > /etc/hotplug.d/usb/20-rtl8188su 
-BINARY="/sbin/wifi up" 
-RTL8188SU_PRODID="bda/8171/200" 
- 
-if [ "${PRODUCT}" = "${RTL8188SU_PRODID}" ]; then 
-    if [ "${ACTION}" = "add" ]; then 
-        ${BINARY} 
-    fi 
-fi 
-EOF 
-</code> 
  
 ==== Symlink instead of rename a device ==== ==== Symlink instead of rename a device ====
 An other script to create a symlink instead of renaming the device. An other script to create a symlink instead of renaming the device.
-I test if DEVICE_NAME is empty because when I plug usb device I retrieve two add event, and the first come before created device, so symlink fails. 
  
 <code bash> <code bash>
 cat << "EOF" > /etc/hotplug.d/usb/20-cp210x cat << "EOF" > /etc/hotplug.d/usb/20-cp210x
-CP210_PRODID="10c4/ea60/100"+CP210_PRODID='10c4/ea60/100'
 SYMLINK="my_link" SYMLINK="my_link"
  
-if [ "${PRODUCT}" = "${CP210_PRODID}" ]; then +set -eu
-    if [ "${ACTION}" = "add" ]; then +
-          DEVICE_NAME=$(ls /sys/${DEVPATH} | grep tty) +
-          if [ -z ${DEVICE_NAME} ]; then +
-              logger -t hotplug "Warning DEVICE_NAME is empty" +
-              exit +
-          fi +
-          logger -t hotplug "Device name of cp210 is ${DEVICE_NAME}" +
-          ln -s /dev/${DEVICE_NAME} /dev/${SYMLINK} +
-          logger -t hotplug "Symlink from /dev/${DEVICE_NAME} to /dev/${SYMLINK} created" +
-    fi +
-fi+
  
-if [ "${PRODUCT}" = "${CP210_PRODID}" ]; then +if [ "${DEVTYPE:-}" = 'usb_interface' ] && \ 
-    if [ "${ACTION}" = "remove" ]; then +   [ "${PRODUCT:-}" = "${CP210_PRODID}" ]; then 
-        rm /dev/${SYMLINK} + if [ "${ACTION:-}" = 'bind' ]; then 
-        logger -t hotplug "Symlink /dev/${SYMLINK} removed" + if [ -L "/dev/${SYMLINK}" ]; then 
-    fi+ logger -t hotplug "Symlink '/dev/${SYMLINK}' already exists" 
 + exit 0 
 + fi 
 + 
 + DEVICE_NAME="$(find /sys${DEVPATH:-} -maxdepth 1 -type d -iname 'ttyUSB*' -exec basename {} \;)" 
 + if [ -z "${DEVICE_NAME}" ]; then 
 + logger -t hotplug 'Warning: DEVICE_NAME is empty' 
 + exit 0 
 + fi 
 + 
 + logger -t hotplug "Device name of cp210 is '${DEVICE_NAME}'" 
 + ln -s "/dev/${DEVICE_NAME}" "/dev/${SYMLINK}" 
 + logger -t hotplug "Symlink from '/dev/${DEVICE_NAME}' to '/dev/${SYMLINK}' created" 
 + fi 
 + 
 + 
 + if [ "${ACTION:-}" = 'unbind' ]; then 
 + rm "/dev/${SYMLINK}" 
 + logger -t hotplug "Symlink '/dev/${SYMLINK}removed" 
 + fi
 fi fi
 EOF EOF
 </code> </code>
- +==== Script that detects whether plugged usb device is bluetooth or not ====
-==== Script that detects if plugged usb device is bluetooth or not ====+
 <code bash> <code bash>
 cat << "EOF" > /etc/hotplug.d/usb/20-bt_test cat << "EOF" > /etc/hotplug.d/usb/20-bt_test
 BT_PRODID="a12/1/" BT_PRODID="a12/1/"
-BT_PRODID_HOT=`echo ${PRODUCT} | cut -c 1-6`+BT_PRODID_HOT="${PRODUCT::6}"
  
 #logger -t hotplug "PRODUCT ID is ${BT_PRODID_HOT}" #logger -t hotplug "PRODUCT ID is ${BT_PRODID_HOT}"
Line 208: Line 265:
     add)     add)
             # start process             # start process
-        /etc/init.d/mjpg-streamer start+        service mjpg-streamer start
             ;;             ;;
     remove)     remove)
             # stop process             # stop process
-        /etc/init.d/mjpg-streamer stop+        service mjpg-streamer stop
             ;;             ;;
 esac esac
Line 246: Line 303:
  
 ==== Coldplug ==== ==== Coldplug ====
-If you had notice the udev and eudev were removed in the openwrt 18.0.* release, don'be afraid because you still can make the things works.+You may have noticed that the udev and eudev were removed in the openwrt 18.0.* release. Don'worry, because you still can make things work.
 You can use hotplug scripts as coldplug. You can use hotplug scripts as coldplug.
-Pay attention at the ACTION environment variable, at the boot are executed 'bind' actions. +Pay attention to the ACTION environment variable, at boot 'bind' actions are executed
-So, just add this option to hotplug run accordinly.+So, just add this option to hotplug and run accordingly. 
 In my case I used this: In my case I used this:
  
Line 301: Line 359:
   esac   esac
 fi fi
 +EOF
 +</code>
 +
 +==== Log DSL status changes ====
 +If you have a DSL modem you can add logging of DSL status changes and connection data rates.
 +
 +This can be helpful if your DSL connection is affected by Seamless Rate Adaptation (SRA) or
 +Dynamic Line Management (DLM) events; for SRA events data rate changes will be logged, while
 +for DLM events connection status changes will be logged as the modem is forced to retrain and then the new
 +data rates will be logged.
 +
 +<code bash>
 +cat << "EOF" > /etc/hotplug.d/dsl/20-dsl_status
 +case "${DSL_NOTIFICATION_TYPE}" in
 +(DSL_INTERFACE_STATUS)
 +logger -p daemon.notice -t dsl-notify "${DSL_XTU_STATUS} link status: ${DSL_INTERFACE_STATUS}" ;;
 +(DSL_DATARATE_STATUS_US)
 +logger -p daemon.notice -t dsl-notify "DSL upstream actual data rate: ${DSL_DATARATE_US_BC0}" ;;
 +(DSL_DATARATE_STATUS_DS)
 +logger -p daemon.notice -t dsl-notify "DSL downstream actual data rate: ${DSL_DATARATE_DS_BC0}" ;;
 +esac
 +EOF
 +</code>
 +
 +This script assumes that channel bonding is not compiled in to the DSL support.
 +
 +==== Utilize wireless USB adapter ====
 +Restart Wi-Fi when plugging in a wireless USB adapter.
 +
 +<code bash>
 +mkdir -p /etc/hotplug.d/usb
 +cat << "EOF" > /etc/hotplug.d/usb/20-rtl8188su
 +if [ "${PRODUCT}" = "bda/8171/200" ] \
 +&& [ "${ACTION}" = "add" ]
 +then wifi
 +fi
 +EOF
 +</code>
 +
 +The above code matches the following device.
 +
 +<code bash>
 +# lsusb -v
 + idVendor 0x0bda Realtek Semiconductor Corp.
 + idProduct 0x8171 RTL8188SU 802.11n WLAN Adapter
 + bcdDevice 2.00
 +</code>
 +
 +==== Get specific IP address ====
 +Assuming your ISP provides a dynamic IP address.
 +Reconnect until you get the one matching a specific regexp.
 +Delay for 10 seconds between reconnects.
 +Set up [[docs:guide-user:advanced:hotplug_extras|Hotplug extras]] to trigger the script upon connecting WAN interface.
 +
 +<code bash>
 +mkdir -p /etc/hotplug.d/online
 +cat << "EOF" > /etc/hotplug.d/online/10-wan-ipaddr
 +. /lib/functions/network.sh
 +network_flush_cache
 +network_find_wan WAN_IF
 +network_get_ipaddr WAN_ADDR "${WAN_IF}"
 +if [ "${WAN_IF}" != "${INTERFACE}" ]
 +then exit 0
 +fi
 +case ${WAN_ADDR} in
 +(??.???.*) exit 0 ;;
 +esac
 +sleep 10
 +ifup ${INTERFACE}
 EOF EOF
 </code> </code>
  
 ==== Rename interfaces by MAC address ==== ==== Rename interfaces by MAC address ====
-A simple method to configure persistent interface names by MAC address.+Assuming pre-configured upstream interfaces ''wana'' and ''wanb''
 +Set up persistent interface names by MAC address.
  
 <code bash> <code bash>
-uci set network.wan1.ifname="wan1+cat << "EOF> /etc/hotplug.d/iface/00-dev-rename 
-uci set network.wan2.ifname="wan2+dev_rename() { 
-uci -q delete network.wan1_dev +local DEV_CONF="${1}
-uci set network.wan1_dev="device+local DEV_MAC DEV_NAME DEV_ONAME 
-uci set network.wan1_dev.name="wan1+config_get DEV_MAC "${DEV_CONF}mac 
-uci set network.wan1_dev.mac="11:22:33:44:55:66+config_get DEV_NAME "${DEV_CONF}" name 
-uci -q delete network.wan2_dev +DEV_ONAME="$(grep -l -e "${DEV_MAC}" \ 
-uci set network.wan2_dev="device+$(find /sys/class/net/*/device/uevent \ 
-uci set network.wan2_dev.name="wan2+| sed -e "s|/device/uevent$|/address|") \ 
-uci set network.wan2_dev.mac="aa:bb:cc:dd:ee:ff" +| awk -F '/' '{print $5}')" 
-uci commit network+if [ -n "${DEV_MAC}" ] \ 
 +&& [ "${DEV_ONAME}" != "${DEV_NAME}] 
 +then ip link set "${DEV_ONAME}" name "${DEV_NAME}
 +fi 
 +
 +/lib/functions.sh 
 +config_load network 
 +config_foreach dev_rename device 
 +EOF
  
-cat << "EOF" > /etc/rc.local +while read -r DEV_NAME DEV_MAC
-NET_DEVS="$(ls /sys/class/net/*/device/uevent \ +
-    | awk -F '/' '{print $5}')" +
-for NET_DEV0 in ${NET_DEVS}+
 do do
-    NET_MAC0="$(cat /sys/class/net/"${NET_DEV0}"/address)" +uci set network.${DEV_NAME}.device="${DEV_NAME}" 
-    I="0" +uci set network.${DEV_NAME}6.device="${DEV_NAME}" 
-    while uci -q get network.@device["${I}"] > /dev/null +uci -q delete network.${DEV_NAME}_dev 
-    do +uci set network.${DEV_NAME}_dev="device
-        NET_DEV="$(uci -q get network.@device["${I}"].name)+uci set network.${DEV_NAME}_dev.mac="${DEV_MAC}" 
-        NET_MAC="$(uci -q get network.@device["${I}"].mac)" +uci set network.${DEV_NAME}_dev.name="${DEV_NAME}" 
-        if [ -n "${NET_DEV}" -a -n "${NET_MAC}" ] \ +done << EOI 
-        && [ "${NET_MAC}= "${NET_MAC0}" ] +wana 11:22:33:44:55:66 
-        then +wanb aa:bb:cc:dd:ee:ff 
-            ip link set "${NET_DEV0}" down +EOI 
-            ip link set "${NET_DEV0}" name "${NET_DEV}" +uci commit network 
-        fi +service network restart
-    done +
-done +
-/etc/init.d/network reload +
-EOF +
-sh /etc/rc.local+
 </code> </code>
  
 +==== Create deterministic/persistent links to USB-serial devices ====
 +Resulting links will be placed in /dev/serial/by-id and /dev/serial/by-path,
 +with a name structure closely resembling links created by udev, but not fully exact.
 +
 +<code bash>
 +set -o pipefail
 +[ "${ACTION}" = "bind" -o "${ACTION}" = "unbind" ] || exit 0
 +[ "${SUBSYSTEM}" = "usb-serial" ] || exit 0
 +[ -n "${DEVICENAME}" -a -n "${DEVPATH}" ] || exit 1
 +
 +if [ "${ACTION}" = "bind" ]; then
 +        subsystem="$(basename $(readlink /sys${DEVPATH}/../subsystem))"
 +
 +        [ "$subsystem" = "usb" ] || exit 0
 +
 +        replace_whitespace="s/^[ \t]*|[ \t]*$//g; s/[ \t]+/_/g"
 +        manufacturer="$(cat /sys${DEVPATH}/../../manufacturer | sed -E "${replace_whitespace}")" || manufacturer="$(cat /sys${DEVPATH}/../../idVendor)"
 +        product="$(cat /sys${DEVPATH}/../../product | sed -E "${replace_whitespace}")" || product="$(cat /sys${DEVPATH}/../../idProduct)"
 +        serial="$(cat /sys${DEVPATH}/../../serial | sed -E "${replace_whitespace}")"
 +        interface="$(cat /sys${DEVPATH}/../bInterfaceNumber)"
 +        port="$(cat /sys${DEVPATH}/port_number)"
 +
 +        replace_chars="s/[^0-9A-Za-z#+.:=@-]/_/g"
 +        id_link=$(echo "${subsystem}"-"${manufacturer}"_"${product}${serial:+_}${serial}"-if"${interface}${port:+-port}${port}" | sed "${replace_chars}")
 +        path_link=$(echo "${DEVPATH}${port:+-port}${port}" | sed "s%/devices/%%; s%/${DEVICENAME}%%g; ${replace_chars}")
 +
 +        mkdir -p /dev/serial/by-id /dev/serial/by-path
 +        ln -sf "/dev/${DEVICENAME}" "/dev/serial/by-id/${id_link}"
 +        ln -sf "/dev/${DEVICENAME}" "/dev/serial/by-path/${path_link}"
 +elif [ "${ACTION}" = "unbind" ]; then
 +        for link in $(find /dev/serial -type l); do
 +                [ -L ${link} -a "$(readlink ${link})" = "/dev/$DEVICENAME" ] && rm ${link}
 +        done
 +fi
 +</code>
 +[[https://gist.github.com/Leo-PL/b5ee737e49b34c1551dba6c182707c8e|(Source)]]
  • Last modified: 2024/12/19 04:42
  • by pythonic