Hotplug -- Örökség
Az aktuális megközelítésről a Hotplug cikkben olvashat. A “hotplug2” démet 2013-ban eltávolították (r36987) és helyettesítve procd. |
- https://dev.openwrt.org/browser/branches/attitude_adjustment/package/hotplug2 - a hotplug2 package forráskódja
A Hotplug2 egy esemény alrendszer Linuxhoz. A hagyományos udev és hotplug szolgáltatások előnyeit egyesíti magában, de sokkal kisebb méretben, ezért ideális beágyazott rendszerekhez, mint az OpenWrt. Lényegében a Hotplug2 arra való, hogy meghatározott rendszeresemények esetén - pl. egy hálózati interfész be- vagy kikapcsolása, egy USB eszköz csatlakoztatása, vagy egy gomb megnyomása, - scripteket hajtson végre.
Rendkívül hasznos lehet pédául egy instabil PPPoE kapcsolat esetén, ahol napjában többször is megváltozhat az eszköz IP címe. A hardware.button is a hotplug-ot használja.
A Hotplug2 az OpenWrt 'Kamikaze' 7.06-os verziójában jelent meg, és az 'Attitude Adjustment' az utolsó verzió amiben támogatott.
A r36987 változtatással bevezetésre került a procd , ami a következő verzióban teljes egészében le fogja váltani a hotplug-ot. Sajnos a procd-ről még annyi dokumentáció sincs mint a hotplug-ról... A r37132 -ben a hotplug2 csomag kikerült a default csomagok közül, így ez a leírás a legújabb verziókra nem érvényes, át kell állni a procd -re. See r37336: procd: make old button hotplug rules work until all packages are migrated |
Mi az a hotplug?
Jó open source szokás szerint a hotplug-ról alig fellelhető valami dokumentáció. Chris Lumens weboldalán található egy általános leírás az eredeti hotplug-ról, azonban a hotplug2 működése kicsit eltérő.
Működése
A hotplug alrendszer alapja a /sbin/hotplug2
program, mely egy szolgáltatásként folyamatosan fut. Ha valami rendszeresemény történik, akkor a kernel továbbítja azt a hotplug2-nek. A program az eseményeket az ún. rules fájl szerint dolgozza fel. Ez egy olyan szabálygyűjtemény, amiben a különböző típusú eseményekhez különböző végrehajtandó utasítások vannak rendelve. A rules fájloknak egyedi szintaxisa van.
Normál működéskor a rendszer a /etc/hotplug2.rules
fájlban leírt szabályokat alkalmazza. Ezek értelmében a különböző alrendszerek (pl. net, usb, button) eseményei a /sbin/hotplug-call
scriptnek lesznek továbbítva, paraméterként az alrendszer neve adódik át. Ez nem csinál mást, minthogy ABC-sorrendben meghívja az /etc/hotplug.d/
könyvtáron belül az adott alrendszer könyvtárában lévő összes scriptet.
Például, egy hálózati interfész be- vagy kikapcsolásakor az /etc/hotplug.d/iface/
könyvtárban lévő összes script név szerinti sorrendben lefut. Megegyezés szerint minden hotplug script neve két számjegyű számmal kezdődik, így egyszerűen biztosítható, hogy mindig a megfelelő sorrendben fussanak le. Ezért a hálózat interfészekhez tartozó eseményscriptek elnevezési sémája: /etc/hotplug.d/iface/<nn>-<scriptneve>
pl.: 00-netstate
, 20-firewall
.
Használata
1. Rules fájlok
Az események feldolgozását a hotplug2
a default rules fájllal kezdi.
Az /etc/hotplug2.rules
fájl tartalmazza a használható események típusait, ezek jelenleg: net, input, button, usb, ieee13945, block, atm, zaptel és tty.
FIGYELEM! Az angol leírásban található utasítás, miszerint ki kell törölni a ^
jelet, hogy engedélyezzük az eseményeket az adott alrendszerhez, NEM IGAZ, és hibás működéshez vezethet!
$include /etc/hotplug2-common.rules SUBSYSTEM ~~ (^net$|^input$|^button$|^usb$|^ieee1394$|^block$|^atm$|^zaptel$|^tty$) { exec /sbin/hotplug-call %SUBSYSTEM% } DEVICENAME == watchdog { exec /sbin/watchdog -t 5 /dev/watchdog next-event }
A fájl első sora egy include
direktíva, azt jelenti, hogy a hotplug2 a /etc/hotplug2-common.rules
fájlban lévő szabályokat is végre fogja hajtani.
2. Hotplug scriptek
Az események használatához egyszerűen helyezzük a hotplug-scriptet a megfelelő alrendszer alkönyvtárába /etc/hotplug.d/
könyvtáron belül, és az automatikusan el fog indulni az adott típusú esemény hatására. A fájlt nn-scriptnév
formában nevezzük el, ahol az nn
egy kétjegyű számot jelöl.
3. Event változók
Az eseményekről további informácókat a következő shell változók tartalmaznak. Ezek az eseményscripten belül használhatóak, értéküket a keretrendszer automatikusan beállítja. Erről a folyamatról a fórumban található egy részletes gondolatmenet: How does hotplug work for network interfaces?
Változónév | Leírás | Értékek | |
---|---|---|---|
ACTION | Az esemény azonosítója, értékei az esemény forrásától függnek. | ||
Kernel forrású eseményeknél (pl. usb alrendszer): add - eszköz csatlakoztatvaremove - eszköz eltávolítvachange - ?move - ?online - ?offline - ? | |||
netifd forrású eseményeknél (iface alrendszer): ifup - hálózati eszköz feléledt ifdown - hálózati eszköz lekapcsoltifupdate - ? | |||
button alrendszer eseményeinél: pressed - gomb megnyomva released - gomb elengedve | |||
DEVPATH | Az eseményt kiváltó eszköz belső elérési útja a /sys fájlrenszeren belül | ||
SUBSYSTEM | Az alrendszer azonosítója ami az eseményt küldte, pl. usb, button, stb. | ||
SEQNUM | Az esemény sorszáma, pl. hibakereséshez | ||
DEVNAME | Az eszköz elérési útja a /dev fájlrendszeren belül (ha van) | ||
DEVICENAME | Az eszköz “barátságos” neve, ha van | ||
FIRMWARE | Ez a változó akkor van beállítva, ha az eszköz firmware betöltését igényli. Ezt a megfelelő szabály lekezeli a rules fájlban. | ||
INTERFACE | A logikai interfész neve amin a változás történt. | iface típus esetén pl. “wan” vagy “ppp0” usb alrendszernél interface 0 class code (decimális)más alrendszer esetén specifikus azonosító | |
DEVICE | iface alrendszernél a fizikai eszköz neve aminek az állapota változott.Más alrendszernél az eszköz elérése a /proc fájlrendszerben | iface alrendszernél pl. eth0.1 vagy br-lan |
|
PRODUCT | Eszközazonosító | usb alrendszernél USB vendor, product, és version code (hexa) | |
TYPE | Az eszköz típusa | usb alrendszernél device class code (decimális) | |
BUTTON | Csak button alrendszernél, a gomb azonosítója amit megnyomtak. | BTN_0 , BTN_1 … BTN_9 , reset , wps | |
SEEN | Csak button alrendszernél, valami idő alapú változó, nem világos, hogy mi. |
Példák
Save the example script at /etc/hotplug.d/iface/99-my-action
.
#!/bin/sh
[ “$ACTION” = ifup ] && {
logger -t button-hotplug Device: $DEVICE / Action: $ACTION
} |
Every time an interface goes up then the if/fi statement will be executed.
→ hardware.button makes ample use of hotplug.
Niii has posted this quick example for a USB WiFi device hotplug event to trigger an init.d network restart wlan0 script.
For determine RTL8188SU_PRODID variable, use “lsusb -v”:
idVendor 0x0bda Realtek Semiconductor Corp. idProduct 0x8171 RTL8188SU 802.11n WLAN Adapter bcdDevice 2.00
/etc/hotplug.d/usb/20-rtl8188su
#!/bin/sh
BINARY=“/sbin/wifi up”
RTL8188SU_PRODID=“bda/8171/200”
if [ “${PRODUCT}” = “${RTL8188SU_PRODID}” ]; then
if [ “${ACTION}” = “add” ]; then
${BINARY}
fi
fi |
/etc/hotplug.d/usb/20-cp210x
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.
#!/bin/sh
CP210_PRODID=“10c4/ea60/100”
SYMLINK=“my_link”
if [ “${PRODUCT}” = “${CP210_PRODID}” ];
then 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 [ “${ACTION}” = “remove” ];
then
rm /dev/${SYMLINK}
logger -t Hotplug Symlink /dev/${SYMLINK} removed
fi
fi |
Script that detects if plugged usb device is bluetooth or not.
#!/bin/sh
BT_PRODID=“a12/1/”
BT_PRODID_HOT=`echo $PRODUCT | cut -c 1-6`
#logger -t HOTPLUG “PRODUCT ID is” $BT_PRODID_HOT
if [ “$BT_PRODID_HOT” = “$BT_PRODID” ]; then
if [ “$ACTION” = “add” ]; then
logger -t HOTPLUG “bluetooth device has been plugged in!”
if [ “$BSBTID_NEW” = “$BSBTID_OLD” ]; then
logger -t HOTPLUG “bluetooth device hasn't changed”
else
logger -t HOTPLUG “bluetooth device has changed”
fi
fi
if [ “$ACTION” = “remove” ]; then
logger -t HOTPLUG “bluetooth device has been removed!”
fi
else
logger -t HOTPLUG “USB device is not bluetooth”
fi |
Auto start mjpg-streamer when an usb camera is plugged in.
Firstly, remove '^' before 'input' in /etc/hotplug2.rules
to enable Hotplug execute script(s) in /etc/hotplug.d/input
.
Secondly, add /etc/hotplug.d/input/30-mjpg-streamer
case "$ACTION" in add) # start process /etc/init.d/mjpg-streamer start ;; remove) # stop process /etc/init.d/mjpg-streamer stop ;; esac
Hibakeresés
If you wish to troubleshoot hotplug of some type of device this can be done via simple debug script. For example to troubleshoot adding and removing of any type of usb devices simple create this /etc/hotplug.d/usb/10-usb_debug script with all variables:
#!/bin/sh logger -t DEBUG "hotplug usb: action='$ACTION' devicename='$DEVICENAME' devname='$DEVNAME' devpath='$DEVPATH' product='$PRODUCT' type='$TYPE' interface='$INTERFACE'"
or this one with only essential ones used:
#!/bin/sh logger -t DEBUG "hotplug usb: action='$ACTION' product='$PRODUCT' type='$TYPE' interface='$INTERFACE'"
So with debuging enabled here is how it looks like when you plug two different usb bluetooth dongles:
action='add' product='a12/1/1915' type='224/1/1' interface='' action='add' product='a12/1/1915' type='224/1/1' interface='224/1/1' action='add' product='a12/1/1915' type='224/1/1' interface='224/1/1' action='add' product='a12/1/1915' type='224/1/1' interface='254/1/0' action='remove' product='a12/1/1915' type='224/1/1' interface='224/1/1' action='remove' product='a12/1/1915' type='224/1/1' interface='224/1/1' action='remove' product='a12/1/1915' type='224/1/1' interface='254/1/0' action='remove' product='a12/1/1915' type='224/1/1' interface='' action='add' product='a12/1/134' type='224/1/1' interface='' action='add' product='a12/1/134' type='224/1/1' interface='224/1/1' action='add' product='a12/1/134' type='224/1/1' interface='224/1/1'
So my using some (maybe flawed) logic we can deduce that match bluetooth is possible if we use product='a12/1*'