Files
wlan-ap/feeds/mcu/mcu/files/mcu.hotplug
Piotr Dymacz 6462efd6bc mcu: execute host side support script for firmware type
This adds support for executing a host side support script per firmware
type (in our case, full MCU firmware name is a combination of two terms:
'version__type', e.g. 'zephyr-v3.3.x__hci_uart') which currently runs on
the MCU. Additionally, support for calling the init script with 'stop'
argument is included.

The host side support scripts will be placed in '/etc/mcu.d/' and should
have executable flag set and be named after the firmware type, with 'sh'
extension (e.g. 'hci_uart.sh'). This solution assumes also that PID of a
running, related service will be stored in '/var/run/mcu.SN.pid' where
'SN' is the associated MCU serial number.

Signed-off-by: Piotr Dymacz <pepe2k@gmail.com>
2023-03-20 08:26:50 +01:00

137 lines
3.0 KiB
Bash

#!/bin/sh
. /lib/functions.sh
. /lib/functions/mcu.sh
MCU_SCRIPT_NAME="mcu-hotplug"
MCU_CFG_FOUND="0"
mcu_hotplug_setup() {
local sn
local fw_type
local disabled
local sn_dev="$2"
local uart="$3"
SECT="$1"
MCU_SYSINFO_OUTPUT=""
MCU_IMGLIST_OUTPUT=""
[ "$MCU_CFG_FOUND" = "1" ] && return 0
config_get sn "$SECT" sn
[ "$sn" != "$sn_dev" ] && return 0
MCU_SCRIPT_NAME="mcu-hotplug.${SECT}"
MCU_CFG_FOUND="1"
mcu_logi "found matching config section '$SECT'"
# Section disabled?
config_get_bool disabled "$SECT" disabled "0"
[ "$disabled" = "1" ] && {
mcu_logw "section is disabled in config"
return 0
}
# Stop related service
[ -f "/var/run/mcu.${sn}.pid" ] && {
kill "$(cat "/var/run/mcu.${sn}.pid" 2>/dev/null)" \
> /dev/null 2>&1
rm -f "/var/run/mcu.${sn}.pid" > /dev/null 2>&1
}
mcu_sn_check_and_update "$sn" "$uart"
[ $? -ne 0 ] && return 1
mcu_fw_check_and_update "$uart"
[ $? -ne 0 ] && return 1
fw_type="$(uci -q get "mcu.${SECT}.firmware" | awk -F '__' '{print $2}')"
[ -n "$fw_type" ] || return 0
[ -x "${MCU_HS_DIR}/${fw_type}.sh" ] && \
"${MCU_HS_DIR}/${fw_type}.sh" "$SECT"
}
# We are looking for ttyACM with specific product name and USB VID:PID
[ "$ACTION" = "add" -a \
"$DRIVER" = "cdc_acm" -a \
"$DEVTYPE" = "usb_interface" ] && {
usb_path="/sys/bus/usb/devices/"
dev="$(echo "$DEVICENAME" | cut -d ':' -f 1)"
[ -n "$dev" ] || return 1
p="$(cat "${usb_path}/${dev}/product" 2>/dev/null)"
id="$(cat "${usb_path}/${dev}/idVendor" 2>/dev/null)"
id="${id}$(cat "${usb_path}//${dev}/idProduct" 2>/dev/null)"
sn="$(cat "${usb_path}/${dev}/serial" 2>/dev/null)"
[ "$p" = "$MCUBOOT_USB_PRODUCT" -a \
"$id" = "$MCUBOOT_USB_VID_PID" ] || return 0
mcu_logi "found compatible MCU with S/N '$sn' at USB bus '$dev'"
# We expect just a single ttyACM interface
usb_path="/sys/bus/usb/devices/${dev}*/tty/*"
for tty in $usb_path; do
[ -c "/dev/$(basename "$tty")" ] && {
uart_path="/dev/$(basename "$tty")"
break
}
done
[ -n "$uart_path" ] || {
mcu_loge "failed to find ttyACM interface"
return 1
}
# Try to acquire lock (init script might be handling this device)
exec 9>"$MCU_FLOCK_FILE" || return 1
flock -n 9 || {
mcu_logd "lock taken by init script, skipping"
return 1
}
config_load mcu
config_foreach mcu_hotplug_setup mcu "$sn" "$uart_path"
# Add new config section for this MCU if no matching found (by S/N)
[ "$MCU_CFG_FOUND" = "0" ] && {
MCU_SCRIPT_NAME="mcu-hotplug"
sect="${sn:0:8}_usb"
mcu_logi "no matching MCU config found, adding new (disabled): '$sect'"
[ -d /etc/config-shadow ] && {
uci -c /etc/config-shadow -q batch <<-EOF
set mcu.${sect}=mcu
set mcu.${sect}.interface=usb
set mcu.${sect}.bootloader=mcuboot
set mcu.${sect}.sn=$sn
set mcu.${sect}.disabled=1
EOF
uci -c /etc/config-shadow -q commit mcu
}
uci -q batch <<-EOF
set mcu.${sect}=mcu
set mcu.${sect}.interface=usb
set mcu.${sect}.bootloader=mcuboot
set mcu.${sect}.sn=$sn
set mcu.${sect}.disabled=1
EOF
uci -q commit mcu
flock -u 9
return 0
}
flock -u 9
}