send_with_timeout now uses a 2s per-byte timeout with a deadline loop instead of one long blocking read, checking a cancel event between reads. SerialBridge.disconnect() sets the cancel event before acquiring the lock, so a blocked firmware sweep aborts within ~2s and releases the lock for clean port shutdown.