extra \x0D appended when echo \0x0A
If you want bytes to be transmitted as-is across a serial connection both ways, you need to tell the system it's not to be used as a terminal device, either by detaching the tty line discipline from it or by issuing:
stty raw -echo < /dev/ttyS2
In your case, it was the onlcr
attribute which is enabled by default on tty device that was causing the LF to CRLF conversion on output. You can disable all output processing including ocrnl
with stty -opost
, but that leaves all the input processing for data transmitted in the other direction.
You're not indicating which shell, echo
or printf
implementation you're using but note that the -n
, -e
options are not standard, and the behaviour of printf
or echo
when an argument contains \x
is unspecified.
Several implementations of printf
in their format argument expand \xHH
to the byte of value 0xHH.
In those
printf "\xAA\xEE\x0A\x%02x" $i
Would expand \xAA
to the byte 0xAA and for \x
would either expand that to byte 0 or to \x
literally or complain that hex digits are missing. So you'd end up with <0xaa><0xee><LF>\x01
in $a
for instance.
Some echo
implementations do also interpret \xHH
sequences (some only when passed a -e
option).
Here, if you wanted to be portable, you'd do:
a=$(printf '\\252\\356\\012\\%03o' "$i")
printf "$a" > /dev/ttyS2
Or:
a=$(printf '\\0252\\0356\\0012\\0%03o' "$i")
printf %b "$a" > /dev/ttyS2
(standard printf
supports \ooo
octal sequences in the format, and a %b
format which is meant to emulate the kind of expansions some echo
implementations do with or without -e
, and where the octal sequences are expressed as \0ooo
).
You also want to make sure the first printf
doesn't output a NUL byte, as except for zsh
, shells cannot store NUL bytes in their variable (don't do for instance).a=$(printf '\0 or \x00 or \u0000')
With zsh
:
bytes=(0xaa 0xee 0x0a $i)
set +o multibyte
printf %s ${(#)bytes} > /dev/ttyS2
That data could be stored in a variable with either:
printf -v data %s ${(#)bytes}
or
data=${(#j[])bytes}
But more generally, if you want to manipulate data with arbitrary byte values, you may want to use a proper programming language, even if it's an interpreted one like perl
or python
.
Another approach would be to use tools like xxd
that can convert back and forth between a binary form and a text hex dump.
printf aaee0a%02d "$i" | xxd -p -r > /dev/ttyS1
You need to disable newline conversion:
stty -F /dev/ttyS2 -onlcr
or, for strict POSIX stty
:
stty -onlcr < /dev/ttyS2