@@ -1615,377 +1615,6 @@ EOF
16151615 return 0
16161616}
16171617
1618- # Remove paired BT device by MAC
1619- bt_cleanup_paired_device () {
1620- mac=" $1 "
1621- log_info " Removing paired device: $mac "
1622-
1623- # Non-interactive remove to avoid “AlreadyExists”
1624- bluetoothctl remove " $mac " > /dev/null 2>&1 || true
1625-
1626- # Full Expect cleanup (captures transcript in a logfile)
1627- cleanup_log=" bt_cleanup_${mac} _$( date +%Y%m%d_%H%M%S) .log"
1628- if expect << EOF >"$cleanup_log " 2>&1
1629- log_user 1
1630- spawn bluetoothctl
1631- set timeout 10
1632-
1633- # Match the prompt once, then send all commands in sequence
1634- expect -re "#|\\ [.*\\ ]#" {
1635- send "power on\r"
1636- send "agent off\r"
1637- send "agent NoInputNoOutput\r"
1638- send "default-agent\r"
1639- send "remove $mac \r"
1640- send "quit\r"
1641- }
1642-
1643- expect eof
1644- EOF
1645- then
1646- log_info " Device $mac removed successfully (see $cleanup_log )"
1647- else
1648- log_warn " Failed to remove device $mac (see $cleanup_log )"
1649- fi
1650- }
1651-
1652- # Retry a shell command N times with sleep
1653- retry_command_bt () {
1654- cmd=" $1 "
1655- msg=" $2 "
1656- max=" ${3:- 3} "
1657- count=1
1658- while [ " $count " -le " $max " ]; do
1659- if eval " $cmd " ; then
1660- return 0
1661- fi
1662- log_warn " Retry $count /$max failed: $msg "
1663- count=$(( count + 1 ))
1664- sleep 2
1665- done
1666- return 1
1667- }
1668-
1669- # Check if a device (MAC or Name) is in the whitelist
1670- bt_in_whitelist () {
1671- device_name=" $1 "
1672- device_mac=" $2 "
1673-
1674- whitelist_value=" ${WHITELIST:- } "
1675- log_info " Checking if MAC='$device_mac ' or NAME='$device_name ' is in whitelist: '$whitelist_value '"
1676-
1677- echo " $whitelist_value " | tr -s ' ' ' \n' | while IFS= read -r allowed; do
1678- if [ " $allowed " = " $device_mac " ] || [ " $allowed " = " $device_name " ]; then
1679- log_info " MAC or NAME matched and allowed: $allowed "
1680- return 0
1681- fi
1682- done
1683-
1684- log_info " MAC matched but neither MAC nor NAME in whitelist"
1685- return 1
1686- }
1687- # bt_parse_whitelist <whitelist_file>
1688- # Reads a whitelist file where each line has:
1689- bt_parse_whitelist () {
1690- WHITELIST_ENTRIES=" "
1691- if [ -n " $1 " ] && [ -f " $1 " ]; then
1692- while IFS= read -r line || [ -n " $line " ]; do
1693- case " $line " in
1694- " " |\# * ) continue ;; # Skip blank lines and comments
1695- * ) WHITELIST_ENTRIES=" ${WHITELIST_ENTRIES}${line}
1696- " ;;
1697- esac
1698- done < " $1 "
1699- fi
1700- }
1701-
1702- # bt_in_whitelist <mac> <name>
1703- # Checks if a given device (MAC and optional name) exists
1704- # Returns:
1705- # 0 (success) if found
1706- # 1 (failure) if not found
1707- bt_in_whitelist () {
1708- mac=" $1 "
1709- name=" $2 "
1710-
1711- echo " $WHITELIST_ENTRIES " | while IFS= read -r entry || [ -n " $entry " ]; do
1712- entry_mac=$( echo " $entry " | awk ' {print $1}' )
1713- entry_name=$( echo " $entry " | cut -d' ' -f2-)
1714- if [ " $mac " = " $entry_mac " ] && { [ -z " $entry_name " ] || [ " $name " = " $entry_name " ]; }; then
1715- exit 0
1716- fi
1717- done
1718-
1719- return 1
1720- }
1721-
1722- # bt_scan_devices
1723- # Attempts to detect nearby Bluetooth devices using:
1724- # 1. hcitool scan
1725- # 2. fallback: bluetoothctl scan (via expect)
1726- # Returns:
1727- # 0 - if devices found
1728- # 1 - if no devices found or error
1729- bt_scan_devices () {
1730- timestamp=$( date ' +%Y%m%d_%H%M%S' )
1731- scan_log=" scan_${timestamp} .log"
1732- found_log=" found_devices_${timestamp} .log"
1733-
1734- : > " $scan_log "
1735- : > " $found_log "
1736-
1737- log_info " Detecting Bluetooth adapter..."
1738- hcidev=$( hciconfig | awk ' /^hci/ { print $1 }' | head -n1)
1739- if [ -z " $hcidev " ]; then
1740- log_error " No Bluetooth adapter found"
1741- return 1
1742- fi
1743-
1744- log_info " Using Bluetooth adapter: $hcidev "
1745- hciconfig " $hcidev " up
1746- sleep 1
1747-
1748- log_info " Running Bluetooth scan via hcitool (synchronous)..."
1749- script -q -c " hcitool -i $hcidev scan" " $scan_log "
1750- grep -E ' ^(\s)*([0-9A-F]{2}:){5}[0-9A-F]{2}' " $scan_log " | awk ' {print $1, $2}' > " $found_log "
1751-
1752- if [ -s " $found_log " ]; then
1753- log_info " hcitool scan found devices, skipping bluetoothctl fallback."
1754- return 0
1755- fi
1756-
1757- log_warn " hcitool scan returned nothing. Falling back to bluetoothctl scan..."
1758-
1759- expect << EOF >> "$scan_log "
1760- log_user 0
1761- spawn bluetoothctl
1762- expect -re "#|\\ \[.*\\ \]#" { send "power on\r" }
1763- expect -re "#|\\ \[.*\\ \]#" { send "agent NoInputNoOutput\r" }
1764- expect -re "#|\\ \[.*\\ \]#" { send "default-agent\r" }
1765- expect -re "#|\\ \[.*\\ \]#" { send "scan on\r" }
1766- sleep 10
1767- send "scan off\r"
1768- expect -re "#|\\ \[.*\\ \]#" { send "quit\r" }
1769- EOF
1770-
1771- grep -E " ^\s*\[NEW\] Device" " $scan_log " | awk ' {print $4, substr($0, index($0, $5))}' > " $found_log "
1772-
1773- if [ ! -s " $found_log " ]; then
1774- log_warn " Scan log is empty. Possible issue with bluetoothctl or adapter."
1775- return 1
1776- fi
1777-
1778- return 0
1779- }
1780-
1781- # Pair with Bluetooth device using MAC (with retries and timestamped logs)
1782- bt_pair_with_mac () {
1783- bt_mac=" $1 "
1784- # Replace colons, strip any whitespace so no trailing spaces in filenames
1785- safe_mac=$( echo " $bt_mac " | tr ' :' ' _' | tr -d ' [:space:]' )
1786- max_retries=3
1787- retry=1
1788-
1789- while [ " $retry " -le " $max_retries " ]; do
1790- log_info " Interactive pairing attempt $retry for $bt_mac "
1791- log_file=" $PWD /bt_headless_pair_${safe_mac} _$( date +%s) .log"
1792-
1793- expect -c "
1794- log_user 1
1795- set timeout 30
1796- set bt_mac \" $bt_mac \"
1797-
1798- spawn bluetoothctl
1799-
1800- expect -re {#|\\ \[.*\\ \]#} { send \" power on\r\" }
1801- expect -re {#|\\ \[.*\\ \]#} { send \" agent NoInputNoOutput\r\" }
1802- expect -re {#|\\ \[.*\\ \]#} { send \" default-agent\r\" }
1803- expect -re {#|\\ \[.*\\ \]#} { send \" scan on\r\" }
1804- sleep 10
1805- send \" scan off\r\"
1806- sleep 1
1807- send \" pair \$ bt_mac\r\"
1808-
1809- expect {
1810- -re {Confirm passkey.*yes/no} {
1811- send \" yes\r\"
1812- exp_continue
1813- }
1814- -re {Authorize service.*yes/no} {
1815- send \" yes\r\"
1816- exp_continue
1817- }
1818- timeout {
1819- send \" quit\r\"
1820- exit 0
1821- }
1822- eof {
1823- exit 0
1824- }
1825- }
1826- " > " $log_file " 2>&1
1827-
1828- # Now analyze the log
1829- if grep -q " Pairing successful" " $log_file " ; then
1830- log_pass " Pairing successful with $bt_mac "
1831- return 0
1832- elif grep -q " Failed to pair: org.bluez.Error" " $log_file " ; then
1833- log_warn " Pairing failed with $bt_mac (BlueZ error)"
1834- elif grep -q " AuthenticationCanceled" " $log_file " ; then
1835- log_warn " Pairing canceled with $bt_mac "
1836- else
1837- log_warn " Pairing failed with unknown reason (check $log_file )"
1838- fi
1839-
1840- bt_cleanup_paired_device " $bt_mac "
1841- retry=$(( retry + 1 ))
1842- sleep 2
1843- done
1844-
1845- log_fail " Pairing failed after $max_retries attempts for $bt_mac "
1846- return 1
1847- }
1848-
1849- # Utility to reliably scan and pair Bluetooth devices through a unified workflow of repeated attempts.
1850- retry_scan_and_pair () {
1851- retry=1
1852- max_retries=2
1853-
1854- while [ " $retry " -le " $max_retries " ]; do
1855- log_info " Bluetooth scan attempt $retry ..."
1856- bt_scan_devices
1857-
1858- if [ -n " $BT_MAC " ]; then
1859- log_info " Matching against: BT_NAME='$BT_NAME ', BT_MAC='$BT_MAC ', WHITELIST='$WHITELIST '"
1860- if ! bt_in_whitelist " $BT_MAC " " $BT_NAME " ; then
1861- log_warn " Expected device not found or not in whitelist"
1862- retry=$(( retry + 1 ))
1863- continue
1864- fi
1865- bt_cleanup_paired_device " $BT_MAC "
1866- if bt_pair_with_mac " $BT_MAC " ; then
1867- return 0
1868- fi
1869-
1870- elif [ -n " $BT_NAME " ]; then
1871- matched_mac=$( awk -v name=" $BT_NAME " ' tolower($0) ~ tolower(name) { print $1; exit }' " $SCAN_RESULT " )
1872- if [ -n " $matched_mac " ]; then
1873- log_info " Found matching device by name ($BT_NAME ): $matched_mac "
1874- bt_cleanup_paired_device " $matched_mac "
1875- if bt_pair_with_mac " $matched_mac " ; then
1876- BT_MAC=" $matched_mac "
1877- return 0
1878- fi
1879- else
1880- log_warn " Device with name $BT_NAME not found in scan results"
1881- fi
1882-
1883- else
1884- log_warn " No MAC or device name provided, and whitelist is empty"
1885- fi
1886-
1887- retry=$(( retry + 1 ))
1888- done
1889-
1890- log_fail " Retry scan and pair failed after $max_retries attempts"
1891- return 1
1892- }
1893-
1894- # Post-pairing connection test with bluetoothctl and l2ping fallback
1895- bt_post_pair_connect () {
1896- target_mac=" $1 "
1897- sanitized_mac=$( echo " $target_mac " | tr ' :' ' _' )
1898- timestamp=$( date ' +%Y%m%d_%H%M%S' )
1899- base_logfile=" bt_connect_${sanitized_mac} _${timestamp} "
1900- max_attempts=3
1901- attempt=1
1902-
1903- if bluetoothctl info " $target_mac " | grep -q " Connected: yes" ; then
1904- log_info " Device $target_mac is already connected, skipping explicit connect"
1905- log_pass " Post-pair connection successful"
1906- return 0
1907- fi
1908-
1909- while [ " $attempt " -le " $max_attempts " ]; do
1910- log_info " Attempting to connect post-pair (try $attempt ): $target_mac "
1911- logfile=" ${base_logfile} _attempt${attempt} .log"
1912-
1913- expect << EOF >"$logfile " 2>&1
1914- log_user 1
1915- set timeout 10
1916- spawn bluetoothctl
1917- expect -re "#|\\ [.*\\ ]#" { send "trust $target_mac \r" }
1918- expect -re "#|\\ [.*\\ ]#" { send "connect $target_mac \r" }
1919-
1920- expect {
1921- -re "Connection successful" { exit 0 }
1922- -re "Failed to connect|Device not available" { exit 1 }
1923- timeout { exit 1 }
1924- }
1925- EOF
1926- result=$?
1927- if [ " $result " -eq 0 ]; then
1928- log_pass " Post-pair connection successful"
1929- return 0
1930- fi
1931- log_warn " Connect attempt $attempt failed (check $logfile )"
1932- attempt=$(( attempt + 1 ))
1933- sleep 2
1934- done
1935-
1936- # Fallback to l2ping
1937- log_info " Falling back to l2ping for $target_mac "
1938- l2ping_log=" ${base_logfile} _l2ping_${timestamp} .log"
1939- if command -v l2ping > /dev/null 2>&1 ; then
1940- # Capture all output—even if ping succeeds, we log it
1941- if l2ping -c 3 -t 5 " $target_mac " 2>&1 | tee " $l2ping_log " | grep -q " bytes from" ; then
1942- log_pass " Fallback l2ping succeeded for $target_mac (see $l2ping_log )"
1943- return 0
1944- else
1945- log_warn " l2ping failed or no response for $target_mac (see $l2ping_log )"
1946- fi
1947- else
1948- log_warn " l2ping not available, skipping fallback"
1949- fi
1950- log_fail " Post-pair connection failed for $target_mac "
1951- return 1
1952- }
1953-
1954- # Find MAC address from device name in scan log
1955- bt_find_mac_by_name () {
1956- target=" $1 "
1957- log=" $2 "
1958- grep -i " $target " " $log " | awk ' {print $3}' | head -n1
1959- }
1960-
1961- bt_remove_all_paired_devices () {
1962- log_info " Removing all previously paired Bluetooth devices..."
1963- bluetoothctl paired-devices | awk ' /Device/ {print $2}' | while read -r dev; do
1964- log_info " Removing paired device $dev "
1965- bluetoothctl remove " $dev " > /dev/null
1966- done
1967- }
1968-
1969- # Validate connectivity using l2ping
1970- bt_l2ping_check () {
1971- target_mac=" $1 "
1972- logfile=" $2 "
1973-
1974- if ! command -v l2ping > /dev/null 2>&1 ; then
1975- log_warn " l2ping command not available - skipping"
1976- return 1
1977- fi
1978-
1979- log_info " Running l2ping test for $target_mac "
1980- if l2ping -c 3 -t 5 " $target_mac " >> " $logfile " 2>&1 ; then
1981- log_pass " l2ping to $target_mac succeeded"
1982- return 0
1983- else
1984- log_warn " l2ping to $target_mac failed"
1985- return 1
1986- fi
1987- }
1988-
19891618# ##############################################################################
19901619# get_remoteproc_by_firmware <short-fw-name> [outfile] [all]
19911620# - If outfile is given: append *all* matches as "<path>|<state>|<firmware>|<name>"
0 commit comments