I am connecting to a serial port using screen: screen /dev/cu.usbserial-A703XAOG. The device on the other end sends only a carriage return to separate lines. Screen only starts at the beginning of the line when receiving a carriage return, and does not go down a line, and thus overwrites the last line of output with the next line of output.

I can change the icrnl setting of the serial port, and it will convert the carriage return to a line feed. Although screen now goes down a line before writing the next line of output, it doesn't start at the beginning when receiving only a line feed.

I dumped the .termcap file using the Ctrl-A, Ctrl+.. I read up on termcap and I learned that:

If the terminal has a command that moves to the first column of the next line, that command can be given as nw (newline).


So this is my current ~/.screenrc file:

termcap SC nw=^M

Where SC matches the name in the dumped .termcap file.

This does not give the effect that I hoped for. Maybe the termcap command is not the way to go?

How can I make screen go down a line AND start at the beginning when receiving only CR from a serial device?


Here is the output of sudo stty -f /dev/cu.usbserial-A703XAOG -a when screen is connected to the serial port:

speed 9600 baud; 0 rows; 0 columns;
lflags: -icanon -isig iexten -echo echoe echok echoke -echonl echoctl
        -echoprt -altwerase -noflsh -tostop -flusho -pendin -nokerninfo
iflags: -istrip -icrnl -inlcr -igncr -ixon -ixoff -ixany -imaxbel -iutf8
        -ignbrk brkint -inpck ignpar -parmrk
oflags: -opost -onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd -hupcl clocal -cstopb -crtscts -dsrflow
        -dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = ^@; eol2 = ^@;
        erase = ^?; intr = ^C; kill = ^H; lnext = ^V; min = 100;
        quit = ^\; reprint = ^R; start = ^Q; status = ^T; stop = ^S;
        susp = ^Z; time = 2; werase = ^W;


I understand some software may solve this, for example, in PuTTY I would need to enable the "implicit LF in every CR" setting, and in Serial I would need to enable "Interpret Standalone CR as CRLF". But my question is specifically about screen, because that is the software I am using currently to connect to the serial port.


Screen emulates the VT100 terminal, and it should recognize control sequences (source). I need to set "Automatic Linefeed Mode" (also known as new line mode). This should be done using the set mode control sequence with the parameter value 20: ESC [ 20 h.

How can I pass this control sequence to screen?

  • you may have better luck using software like minicom with a serial device – Rafael Kitover Aug 12 '19 at 23:18
  • @RafaelKitover Yes, I understand some software may solve this, but my question is related to screen, because that is the software I am using currently to connect to the serial port. – Michiel van Oosterhout Aug 13 '19 at 7:42
  • 1
    @roaima I have added the serial port settings to my question. – Michiel van Oosterhout Aug 13 '19 at 7:43
  • Thanks. Is stty -a from inside screen any different? – roaima Aug 13 '19 at 8:09
  • Yes, many differences. But that is after running screen, so it's not connected to a serial port, but to Bash. – Michiel van Oosterhout Aug 13 '19 at 10:33

Something that seemed to work for me was to manipulate the pseudo-tty that screen has by sending it the newline mode escape sequence you found, and also giving it an stty command to convert the carriage return to a newline. Use ps a to find the pty:

16947 pts/4    Ss+    0:00 screen -S myscreen /dev/ttyS0

and then give the commands

stty -F $pty  ocrnl
echo -en '\e[20h' >$pty
  • Thanks for the insightful answer. I could already change the settings of the serial port after the connection is open, by executing sudo stty -f /dev/cu.usbserial-A703XAOG icrnl in a separate Terminal tab. Notice that I need to set icrnl, not ocrnl. But trying to send the control sequence to the serial port by executing sudo echo -en '\e[20h' >/dev/cu.usbserial-A703XAOG gives an error: "-bash: /dev/cu.usbserial-A703XAOG: Resource busy". I am running this on macOS. – Michiel van Oosterhout Aug 17 '19 at 18:52
  • 1
    Your sudo echo... will fail because the >/dev/... is being done by the shell before the sudo takes effect. You would need to messily quote it all: sudo sh -c 'echo -en '\''\e[20h'\'' >/dev/...'. But I am operating on the pty that screen creates for every virtual terminal, not the real tty. This makes it easier as I don't need to be root and explains why I used ocrnl rather than icrnl. It seems to work for me on Linux, and I would have thought it should also work on MacOS, though I cannot try. – meuh Aug 17 '19 at 19:10
  • Ok, this makes sense, again, thanks for bringing insight by explaining the details (about sudo and redirection). On macOS, the screen process also has a TTY associated with it: ttys001. So I executed echo -en '\e[20h' >/dev/ttys001 and the result is that in screen this text is literally shown: "\e[20h". I tried to echo a different escape sequence: echo hello\tworld, and the result is "hello world" where the white space is a tab. So there is something with the \e escape sequence that is not right yet. – Michiel van Oosterhout Aug 19 '19 at 8:56
  • 1
    Using \033 instead of \e works. And using the pseudo terminal, I can also use ocrnl instead of icrnl, which makes more sense. – Michiel van Oosterhout Aug 19 '19 at 9:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.