blob: dbb0da86fb1db953fbdaf0f1ec4d8b6c73884b01 [file] [log] [blame]
#!/bin/sh
# SUBSYSTEM, ACTION, DEVPATH, and FIRMWARE are all provided by the kernel
# when this script is started.
exec >/dev/kmsg 2>&1
. /etc/utils.sh
get_random_mac() {
echo -n $(get_mac_addr_for_interface "$1" | cut -c1-8)
randomdata 0 3 | hexdump -e '3/1 ":%02x"'
}
create_client_interface() {
local interface="$1"
local wlan_mac=$(cat /sys/class/net/"$interface"/address)
local mac=$(mac_addr_increment "$wlan_mac" 1)
local client_interface=$(echo "$interface" | sed s/^wlan/wcli/)
if ! interface_exists "$client_interface"; then
if is_quantenna_interface "$interface"; then
echo "add $client_interface 2" >/sys/class/net/quantenna/vlan
mac=$(get_locally_administered_mac_addr "$mac")
else
local phy=$(find_phy_for_interface "$interface")
iw phy "$phy" interface add "$client_interface" type station
fi
ip link set dev "$client_interface" address "$mac"
fi
# Disable IPv6 autoconfiguration of the interface, which breaks gftests.
# accept_ra means "Accept Router Advertisements, and autoconfigure this
# interface with received data."; disabling this prevents the problematic
# autoconfiguration of routes.
# TODO(rofrankel): Find a way not to need to disable this, e.g. by making it
# so that autoconfigured br0 routes have a lower metric than wcli* routes.
echo 0 >/proc/sys/net/ipv6/conf/wcli0/accept_ra
}
load_firmware() {
echo "Trying firmware '$1'" &&
[ -r "$1" ] &&
echo 1 >/sys/$DEVPATH/loading &&
cat "$1" >/sys/$DEVPATH/data &&
echo 0 >/sys/$DEVPATH/loading &&
echo " ...loaded firmware '$1'"
}
set_mac_address()
{
local interface="$1"
# Set the mac address from values in hnvram.
if is-windcharger; then
case "$interface" in
wan0)
set_mac_from_hnvram wan0 MAC_ADDR1
;;
lan0)
set_mac_from_hnvram lan0 MAC_ADDR2
;;
esac
fi
case "$interface" in
wlan0)
set_mac_from_hnvram wlan0 MAC_ADDR_WIFI
;;
wlan1)
set_mac_from_hnvram wlan1 MAC_ADDR_WIFI2
;;
esac
}
create_secondary_interface() {
local interface="$1"
local suffix="$2"
local mac=$(get_random_mac "$interface")
local secondary_interface="${interface}${suffix}"
if ! interface_exists "$secondary_interface"; then
if is_quantenna_interface "$interface"; then
echo "add $secondary_interface 4" >/sys/class/net/quantenna/vlan
mac=$(get_locally_administered_mac_addr "$mac")
else
local phy=$(find_phy_for_interface "$interface")
iw phy "$phy" interface add "$secondary_interface" type managed
fi
ip link set dev "$secondary_interface" address "$mac"
brctl addif br1 "$secondary_interface"
fi
}
network_add() {
interface="$1"
set_mac_address "$interface"
# At boot or device reset, a net add event is delivered for the primary
# interface. Use this event to create a client interface, which is
# created in user space unlike the primary interface.
if startswith "$interface" "wlan"; then
if is-wireless-client; then
create_client_interface "$interface"
fi
fi
if is-network-box && startswith "$interface" wlan && ! contains "$interface" _portal; then
create_secondary_interface "$interface" _portal
fi
}
case "$SUBSYSTEM-$ACTION" in
input-add)
# BlueZ: adjust repeat speed on remotes
if [ -c "/dev/$DEVNAME" ]; then
echo "hotplug: setting autorepeat on $DEVNAME"
input-repeat -f "/dev/$DEVNAME" -d 600
# Allow user to access input device
chmod 666 "/dev/$DEVNAME"
fi
;;
bluetooth-add)
# BlueZ: Configure hci0 interface link mode
hcidev=${DEVPATH##*/}
if [ "$hcidev" = "hci0" ]; then
echo "hotplug: configuring $hcidev"
hciconfig "$hcidev" lm ACCEPT,MASTER
fi
;;
hidraw-add)
if [ -c "/dev/$DEVNAME" ]; then
echo "Trying gfrm100-rcu-audio for $DEVNAME"
# Allow user to access input device
chmod 666 "/dev/$DEVNAME"
# gfrm100-rcu-audio will exit if not a GFRM100 or daemonize itself
# if it is, so we run it in the foreground. The timeout is for
# safety to not hang the hotplug script, just in case.
timeout 5 setuid appclient:video gfrm100-rcu-audio "/dev/$DEVNAME" 2>&1 | logos "gfrm100_audio"
fi
;;
firmware-add)
echo "hotplug: sys=$SUBSYSTEM act=$ACTION fw=$FIRMWARE dev=$DEVPATH"
register_experiment RwFirmware
if experiment RwFirmware; then
load_firmware "/rw/firmware/$FIRMWARE" ||
load_firmware "/rw/firmware/$(basename "$FIRMWARE")"
else
false # fall back
fi ||
load_firmware "/lib/firmware/$FIRMWARE" ||
echo -1 >"/sys/$DEVPATH/loading"
;;
net-add)
echo "hotplug: net-add if=$INTERFACE act=$ACTION"
network_add "$INTERFACE"
;;
esac
# DirectFB apps listen for an AF_UNIX message for hotplug events, which
# dfb_input_hotplug sends using the ACTION and DEVPATH in the environment.
if [ "$SUBSYSTEM" = "input" ] && [ "$ACTION" = "add" -o "$ACTION" = "remove" ]; then
for dir in /usr/local/bin/directfb/* ; do
if [ -d "$dir" ]; then
export PATH="$PATH":"$dir"
fi
done
if runnable dfb_input_hotplug; then
dfb_input_hotplug
fi
fi