<!-- READY FOR REVIEW -->
#Seriali reali e simulate su Linux
<abstract>
Su linux è possibile simulare coppie di porte seriali interconnesse tra di loro
</abstract>
Installare il package socat
<code>
sudo apt-get install socat
</code>
Il comando seguente crea due porte seriali interconnesse tra di loro con un link virtuale:
<pre class="terminal">
sudo socat PTY,link=/dev/ttyS10 PTY,link=/dev/ttyS11
</pre>
poichè i due devices si trovano sotto la directory /dev per poterli accedere
occorre avere i privilegi di superutente.
Tuttavia non vi' è nessun vincolo che imponga di usare la /dev
(e anche i nomi sono in realtà liberi), quindi,
per evitare il fastidio del sudo, basta creare i devices sotto /tmp.
Oltretutto, essendo sotto /tmp, i nuovi devices non sopravviveranno al prossimo reboot.
Con un qualunque programma (screen minicom lanciati in due terminali virtuali separati)
e' possibile effettuare un test di funzionalità:
<pre class="terminal">
sudo screen /dev/ttyS10
sudo screen /dev/ttyS11
</pre>
##Come accedere ad una seriale da un programma scritto in C
Una porta seriale virtuale è vista come un semplice device a carattere, quindi non richiede
speciali considerazioni quando è acceduta da un programma in C.
Il programma va bene anche una porta seriale fisica, al netto del settaggio dei
parametri di velocita', bit di start/stop e parità: come si vede il bit rate
è comunque stabilito da un costante
#define BAUDRATE B9600
anche se per le porte virtuali questo valore è ininfluente.
##Programma di esempio
<pre class="prettyprint" "lang-c">
/**
* Serial port example.
* Compile with: g++ serialtest.cpp -lpthread -o serialtest
*
* taken from Cymait http://cymait.com
**/
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
#include <termios.h>
#define BUFFER_SIZE 128
#define BAUDRATE B9600
struct Td {
int fd;
char buf[128];
bool exit;
};
void usage(char* cmd)
{
std::cerr << "usage: " << cmd << " slave|master [device, only in slave mode]" << std::endl;
exit(1);
}
void* reader_thread(void* pointer)
{
Td *d = (Td *) pointer;
long fd = d->fd;
char inputbyte;
unsigned n = 0;
while (d->exit != true) {
if (read(fd, &inputbyte, 1) == 1) {
fprintf (stderr, "[%d]: %02x\n", n, inputbyte);
n++;
if (inputbyte == 'X') break;
} else
break;
}
std::cerr << "Terminating thread..." << std::endl;
d->exit = true;
close (0);
return 0;
}
int main (int argc, char** argv)
{
if (argc < 2) usage(argv[0]);
int fd = 0;
fd = open(argv[1], O_RDWR);
if (fd == -1) {
perror ("error opening file");
return 1;
} else
std::cerr << argv[1] << " successfully opened." << std::endl;
/* serial port parameters */
struct termios newtio = {0};
struct termios oldtio;
tcgetattr(fd, &oldtio);
// remove local echo
newtio = oldtio;
newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
newtio.c_iflag = 0;
newtio.c_oflag = 0;
newtio.c_lflag = 0;
newtio.c_cc[VMIN] = 1;
newtio.c_cc[VTIME] = 0;
newtio.c_lflag &= ~(ICANON | ECHO); // disable local echo
tcflush(fd, TCIFLUSH);
cfsetispeed(&newtio, BAUDRATE);
cfsetospeed(&newtio, BAUDRATE);
tcsetattr(fd, TCSANOW, &newtio);
Td data;
data.fd = fd; data.exit = false;
/* start reader thread */
pthread_t thread;
pthread_create(&thread, 0, reader_thread, (void*) &data);
/* read from stdin and send it to the serial port */
unsigned n = 0;
while (data.exit != true) {
//std::cin >> c;
char x = getchar();
if (write(fd, &x, 1) != 1) {
perror ("writing");
break;
} else {
fprintf (stderr, "[%d]: %02x\n", n, x);
}
n++;
}
close(fd);
return 0;
}
</pre>
##Link interessanti sull'argomento
* [Virtual Serial Port for Linux](https://stackoverflow.com/questions/52187/virtual-serial-port-for-linux)
* [HowTo: Virtual Serial Ports on Linux using socat, and more](https://justcheckingonall.wordpress.com/2009/06/09/howto-vsp-socat/)
* [Some useful socat commands](http://technostuff.blogspot.com/2008/10/some-useful-socat-commands.html)
* [Socat examples](https://github.com/craSH/socat/blob/master/EXAMPLES)
* [Socat explained](http://lorgor.blogspot.com/2009/11/socat.html)
* [Serial sockets](http://www.drdobbs.com/embedded-systems/serial-sockets/240149514)
* [Serial port redirection from Windows to Linux with socat](https://lb9mg.no/2015/07/09/serial-port-redirection-from-windows-to-linux-with-socat/)
* [SOCAT - The most comprehensive networking utility](http://aplawrence.com/Girish/socat.html)
@include='bio_andrea_montefusco'
2018 Ⓒ TanzoLab