From d16f2c93b83c284530f2f52ea4f59847fa9ff6d9 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Sun, 28 Aug 2022 10:13:44 -0500 Subject: [PATCH] improve focus-send Fall back to `dash` on macOS, because `bash` randomly drops serial input, causing the tool to hang. Flush the command buffer before sending the requested command. A failed upload session can cause characters to remain in the command buffer. Redirect stdin instead of using a separate file descriptor. Also do this before running `stty`. This allows the `stty` settings to actually take effect on macOS, which seems to reset the termios state of serial devices upon the last close of the device. Tested on macOS 10.15 and Ubuntu 20.04. Signed-off-by: Taylor Yu --- bin/focus-send | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/bin/focus-send b/bin/focus-send index d300bd84..a733f8fa 100755 --- a/bin/focus-send +++ b/bin/focus-send @@ -17,14 +17,22 @@ set -e OS=$(uname -s) +# igncr absorbs CR from Focus CRLF line endings +# -echo is needed because raw doesn't turn it off on Linux +STTY_ARGS="9600 raw igncr -echo" + case ${OS} in Linux) DEVICE="${DEVICE:-/dev/ttyACM0}" - stty -F "${DEVICE}" 9600 raw -echo ;; Darwin) + # bash on macOS has a bug that randomly drops serial input + if [ -n "$BASH_VERSION" ] && [ -x /bin/dash ]; then + # Prevent loop in case someone exported it + export -n BASH_VERSION + exec /bin/dash "$0" "$@" + fi DEVICE="${DEVICE:-/dev/cu.usbmodemCkbio01E}" - stty -f "${DEVICE}" 9600 raw -echo ;; *) echo "Error Unknown OS : ${OS}" >&2 @@ -32,14 +40,24 @@ case ${OS} in ;; esac +# Redirect prior to running stty, because macOS sometimes resets termios +# state upon last close of a terminal device. +exec < "${DEVICE}" +# shellcheck disable=SC2086 # intentional word splitting +stty $STTY_ARGS -exec 3<"${DEVICE}" -echo "$@" >"${DEVICE}" +wait_dot () { + while read -r line; do + if [ "${line}" = "." ]; then + break + fi + echo "${line}" + done +} -while read -r line <&3; do - line="$(echo -n "${line}" | tr -d '\r')" - if [ "${line}" == "." ]; then - break - fi - echo "${line}" -done +# Flush any invalid commands out of input buffer. +# This could happen after a failed upload. +echo ' ' > "${DEVICE}" +wait_dot +echo "$@" >"${DEVICE}" +wait_dot