summaryrefslogtreecommitdiff
path: root/contrib/ports/unix/port/netif/sio.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2024-10-16 08:10:14 -0600
committerTom Rini <trini@konsulko.com>2024-10-16 08:10:14 -0600
commitf3f86fd1fe0fb288356bff78f8a6fa2edf89e3fc (patch)
treef0a99ea87d92f63895a6d053e3185838ebecf2d0 /contrib/ports/unix/port/netif/sio.c
Squashed 'lib/lwip/lwip/' content from commit 0a0452b2c39b
git-subtree-dir: lib/lwip/lwip git-subtree-split: 0a0452b2c39bdd91e252aef045c115f88f6ca773
Diffstat (limited to 'contrib/ports/unix/port/netif/sio.c')
-rw-r--r--contrib/ports/unix/port/netif/sio.c485
1 files changed, 485 insertions, 0 deletions
diff --git a/contrib/ports/unix/port/netif/sio.c b/contrib/ports/unix/port/netif/sio.c
new file mode 100644
index 00000000000..8d8be9bea9c
--- /dev/null
+++ b/contrib/ports/unix/port/netif/sio.c
@@ -0,0 +1,485 @@
+/* Author: Magnus Ivarsson <magnus.ivarsson@volvo.com> */
+
+/* to get rid of implicit function declarations */
+#define _XOPEN_SOURCE 600
+#define _GNU_SOURCE
+
+/* build with Darwin C extensions not part of POSIX, i.e. FASYNC, SIGIO.
+ we can't use LWIP_UNIX_MACH because extensions need to be turned
+ on before any system headers (which are pulled in through cc.h)
+ are included */
+#if defined(__APPLE__)
+#define _DARWIN_C_SOURCE
+#endif
+
+#include "netif/sio.h"
+#include "netif/fifo.h"
+#include "lwip/debug.h"
+#include "lwip/def.h"
+#include "lwip/sys.h"
+#include "lwip/arch.h"
+#include "lwip/sio.h"
+#include "netif/ppp/ppp_opts.h"
+
+/* Following #undefs are here to keep compiler from issuing warnings
+ about them being double defined. (They are defined in lwip/inet.h
+ as well as the Unix #includes below.) */
+#undef htonl
+#undef ntohl
+#undef htons
+#undef ntohs
+#undef HTONL
+#undef NTOHL
+#undef HTONS
+#undef NTOHS
+
+#include <stdlib.h>
+#include <stdio.h>
+#if defined(LWIP_UNIX_OPENBSD)
+#include <util.h>
+#endif
+#include <termios.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/signal.h>
+#include <sys/types.h>
+
+#ifndef LWIP_HAVE_SLIPIF
+#define LWIP_HAVE_SLIPIF 0
+#endif
+
+#if (PPP_SUPPORT || LWIP_HAVE_SLIPIF) && defined(LWIP_UNIX_LINUX)
+#include <pty.h>
+#endif
+
+/*#define BAUDRATE B19200 */
+/*#define BAUDRATE B57600 */
+#define BAUDRATE B115200
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* for all of you who don't define SIO_DEBUG in debug.h */
+#ifndef SIO_DEBUG
+#define SIO_DEBUG 0
+#endif
+
+
+/* typedef struct siostruct_t */
+/* { */
+/* sio_status_t *sio; */
+/* } siostruct_t; */
+
+/** array of ((siostruct*)netif->state)->sio structs */
+static sio_status_t statusar[4];
+
+#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
+/* --private-functions----------------------------------------------------------------- */
+/**
+ * Signal handler for ttyXX0 to indicate bytes received
+ * one per interface is needed since we cannot send a instance number / pointer as callback argument (?)
+ */
+static void signal_handler_IO_0( int status )
+{
+ LWIP_UNUSED_ARG(status);
+ LWIP_DEBUGF(SIO_DEBUG, ("SigHand: rxSignal channel 0\n"));
+ fifoPut( &statusar[0].myfifo, statusar[0].fd );
+}
+
+/**
+ * Signal handler for ttyXX1 to indicate bytes received
+ * one per interface is needed since we cannot send a instance number / pointer as callback argument (?)
+ */
+static void signal_handler_IO_1( int status )
+{
+ LWIP_UNUSED_ARG(status);
+ LWIP_DEBUGF(SIO_DEBUG, ("SigHand: rxSignal channel 1\n"));
+ fifoPut( &statusar[1].myfifo, statusar[1].fd );
+}
+#endif /* ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */
+
+/**
+* Initiation of serial device
+* @param device string with the device name and path, eg. "/dev/ttyS0"
+* @param devnum device number
+* @param siostat status
+* @return file handle to serial dev.
+*/
+static int sio_init( char * device, int devnum, sio_status_t * siostat )
+{
+ struct termios oldtio,newtio;
+#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
+ struct sigaction saio; /* definition of signal action */
+#endif
+ int fd;
+ LWIP_UNUSED_ARG(siostat);
+ LWIP_UNUSED_ARG(devnum);
+
+ /* open the device to be non-blocking (read will return immediately) */
+ fd = open( device, O_RDWR | O_NOCTTY | O_NONBLOCK );
+ if ( fd < 0 )
+ {
+ perror( device );
+ exit( -1 );
+ }
+
+#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
+ memset(&saio, 0, sizeof(struct sigaction));
+ /* install the signal handler before making the device asynchronous */
+ switch ( devnum )
+ {
+ case 0:
+ LWIP_DEBUGF( SIO_DEBUG, ("sioinit, signal_handler_IO_0\n") );
+ saio.sa_handler = signal_handler_IO_0;
+ break;
+ case 1:
+ LWIP_DEBUGF( SIO_DEBUG, ("sioinit, signal_handler_IO_1\n") );
+ saio.sa_handler = signal_handler_IO_1;
+ break;
+ default:
+ LWIP_DEBUGF( SIO_DEBUG,("sioinit, devnum not allowed\n") );
+ break;
+ }
+
+ sigaction( SIGIO,&saio,NULL );
+
+ /* allow the process to receive SIGIO */
+ if ( fcntl( fd, F_SETOWN, getpid( ) ) != 0)
+ {
+ perror( device );
+ exit( -1 );
+ }
+ /* Make the file descriptor asynchronous (the manual page says only
+ O_APPEND and O_NONBLOCK, will work with F_SETFL...) */
+ if ( fcntl( fd, F_SETFL, FASYNC ) != 0)
+ {
+ perror( device );
+ exit( -1 );
+ }
+#else
+ if ( fcntl( fd, F_SETFL, 0 ) != 0)
+ {
+ perror( device );
+ exit( -1 );
+ }
+
+#endif /* ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */
+
+ tcgetattr( fd,&oldtio ); /* save current port settings */
+ /* set new port settings */
+ /* see 'man termios' for further settings */
+ memset(&newtio, 0, sizeof(newtio));
+ newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD | CRTSCTS;
+ newtio.c_iflag = 0;
+ newtio.c_oflag = 0;
+ newtio.c_lflag = 0; /*ECHO; */
+ newtio.c_cc[VMIN] = 1; /* Read 1 byte at a time, no timer */
+ newtio.c_cc[VTIME] = 0;
+
+ tcsetattr( fd,TCSANOW,&newtio );
+ tcflush( fd, TCIOFLUSH );
+
+ return fd;
+}
+
+/**
+*
+*/
+static void sio_speed( int fd, int speed )
+{
+ struct termios oldtio,newtio;
+ /* int fd; */
+
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_speed[%d]: baudcode:%d enter\n", fd, speed));
+
+ if ( fd < 0 )
+ {
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_speed[%d]: fd ERROR\n", fd));
+ exit( -1 );
+ }
+
+ tcgetattr( fd,&oldtio ); /* get current port settings */
+
+ /* set new port settings
+ * see 'man termios' for further settings */
+ memset(&newtio, 0, sizeof(newtio));
+ newtio.c_cflag = speed | CS8 | CLOCAL | CREAD; /* | CRTSCTS; */
+ newtio.c_iflag = 0;
+ newtio.c_oflag = 0;
+ newtio.c_lflag = 0; /*ECHO; */
+ newtio.c_cc[VMIN] = 1; /* Read 1 byte at a time, no timer */
+ newtio.c_cc[VTIME] = 0;
+
+ tcsetattr( fd,TCSANOW,&newtio );
+ tcflush( fd, TCIOFLUSH );
+
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_speed[%d]: leave\n", fd));
+}
+
+/* --public-functions----------------------------------------------------------------------------- */
+void sio_send( u8_t c, sio_status_t * siostat )
+{
+ /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */
+
+ if ( write( siostat->fd, &c, 1 ) <= 0 )
+ {
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_send[%d]: write refused\n", siostat->fd));
+ }
+}
+
+void sio_send_string( u8_t *str, sio_status_t * siostat )
+{
+ /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */
+ int len = strlen( (const char *)str );
+
+ if ( write( siostat->fd, str, len ) <= 0 )
+ {
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_send_string[%d]: write refused\n", siostat->fd));
+ }
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_send_string[%d]: sent: %s\n", siostat->fd, str));
+}
+
+
+void sio_flush( sio_status_t * siostat )
+{
+ LWIP_UNUSED_ARG(siostat);
+ /* not implemented in unix as it is not needed */
+ /*sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */
+}
+
+
+#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
+/*u8_t sio_recv( struct netif * netif )*/
+u8_t sio_recv( sio_status_t * siostat )
+{
+ /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */
+ return fifoGet( &(siostat->myfifo) );
+}
+
+s16_t sio_poll(sio_status_t * siostat)
+{
+ /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio;*/
+ return fifoGetNonBlock( &(siostat->myfifo) );
+}
+
+
+void sio_expect_string( u8_t *str, sio_status_t * siostat )
+{
+ /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio;*/
+ u8_t c;
+ int finger=0;
+
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_expect_string[%d]: %s\n", siostat->fd, str));
+ while ( 1 )
+ {
+ c=fifoGet( &(siostat->myfifo) );
+ LWIP_DEBUGF(SIO_DEBUG, ("_%c", c));
+ if ( c==str[finger] )
+ {
+ finger++;
+ } else if ( finger > 0 )
+ {
+ /*it might fit in the beginning? */
+ if ( str[0] == c )
+ {
+ finger = 1;
+ }
+ }
+ if ( 0 == str[finger] )
+ break; /* done, we have a match */
+ }
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_expect_string[%d]: [match]\n", siostat->fd));
+}
+#endif /* ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */
+
+#if (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
+u32_t sio_write(sio_status_t * siostat, const u8_t *buf, u32_t size)
+{
+ ssize_t wsz = write( siostat->fd, buf, size );
+ return wsz < 0 ? 0 : wsz;
+}
+
+u32_t sio_read(sio_status_t * siostat, u8_t *buf, u32_t size)
+{
+ ssize_t rsz = read( siostat->fd, buf, size );
+ return rsz < 0 ? 0 : rsz;
+}
+
+void sio_read_abort(sio_status_t * siostat)
+{
+ LWIP_UNUSED_ARG(siostat);
+ printf("sio_read_abort[%d]: not yet implemented for unix\n", siostat->fd);
+}
+#endif /* (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */
+
+sio_fd_t sio_open(u8_t devnum)
+{
+ char dev[20];
+
+ /* would be nice with dynamic memory alloc */
+ sio_status_t * siostate = &statusar[ devnum ];
+/* siostruct_t * tmp; */
+
+
+/* tmp = (siostruct_t*)(netif->state); */
+/* tmp->sio = siostate; */
+
+/* tmp = (siostruct_t*)(netif->state); */
+
+/* ((sio_status_t*)(tmp->sio))->fd = 0; */
+
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_open: for devnum %d\n", devnum));
+
+#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
+ fifoInit( &siostate->myfifo );
+#endif /* ! PPP_SUPPORT */
+
+ snprintf( dev, sizeof(dev), "/dev/ttyS%d", devnum );
+
+ if ( (devnum == 1) || (devnum == 0) )
+ {
+ if ( ( siostate->fd = sio_init( dev, devnum, siostate ) ) == 0 )
+ {
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_open: ERROR opening serial device dev=%s\n", dev));
+ abort( );
+ return NULL;
+ }
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: dev=%s open.\n", siostate->fd, dev));
+ }
+#if PPP_SUPPORT
+ else if (devnum == 2) {
+ pid_t childpid;
+ char name[256];
+ childpid = forkpty(&siostate->fd, name, NULL, NULL);
+ if(childpid < 0) {
+ perror("forkpty");
+ exit (1);
+ }
+ if(childpid == 0) {
+ execl("/usr/sbin/pppd", "pppd",
+ "ms-dns", "198.168.100.7",
+ "local", "crtscts",
+ "debug",
+#ifdef LWIP_PPP_CHAP_TEST
+ "auth",
+ "require-chap",
+ "remotename", "lwip",
+#else
+ "noauth",
+#endif
+#if LWIP_IPV6
+ "+ipv6",
+#endif
+ "192.168.1.1:192.168.1.2",
+ NULL);
+ perror("execl pppd");
+ exit (1);
+ } else {
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: spawned pppd pid %d on %s\n",
+ siostate->fd, childpid, name));
+ }
+
+ }
+#endif
+#if LWIP_HAVE_SLIPIF
+ else if (devnum == 3) {
+ pid_t childpid;
+ /* create PTY pair */
+ siostate->fd = posix_openpt(O_RDWR | O_NOCTTY);
+ if (siostate->fd < 0) {
+ perror("open pty master");
+ exit (1);
+ }
+ if (grantpt(siostate->fd) != 0) {
+ perror("grant pty master");
+ exit (1);
+ }
+ if (unlockpt(siostate->fd) != 0) {
+ perror("unlock pty master");
+ exit (1);
+ }
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: for %s\n",
+ siostate->fd, ptsname(siostate->fd)));
+ /* fork for slattach */
+ childpid = fork();
+ if(childpid < 0) {
+ perror("fork");
+ exit (1);
+ }
+ if(childpid == 0) {
+ /* esteblish SLIP interface on host side connected to PTY slave */
+ execl("/sbin/slattach", "slattach",
+ "-d", "-v", "-L", "-p", "slip",
+ ptsname(siostate->fd),
+ NULL);
+ perror("execl slattach");
+ exit (1);
+ } else {
+ int ret;
+ char buf[1024];
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: spawned slattach pid %d on %s\n",
+ siostate->fd, childpid, ptsname(siostate->fd)));
+ /* wait a moment for slattach startup */
+ sleep(1);
+ /* configure SLIP interface on host side as P2P interface */
+ snprintf(buf, sizeof(buf),
+ "/sbin/ifconfig sl0 mtu %d %s pointopoint %s up",
+ SLIP_MAX_SIZE, "192.168.2.1", "192.168.2.2");
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: system(\"%s\");\n", siostate->fd, buf));
+ ret = system(buf);
+ if (ret < 0) {
+ perror("ifconfig failed");
+ exit(1);
+ }
+ }
+ }
+#endif /* LWIP_HAVE_SLIPIF */
+ else
+ {
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_open: device %s (%d) is not supported\n", dev, devnum));
+ return NULL;
+ }
+
+ return siostate;
+}
+
+/**
+*
+*/
+void sio_change_baud( sioBaudrates baud, sio_status_t * siostat )
+{
+ /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio;*/
+
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_change_baud[%d]\n", siostat->fd));
+
+ switch ( baud )
+ {
+ case SIO_BAUD_9600:
+ sio_speed( siostat->fd, B9600 );
+ break;
+ case SIO_BAUD_19200:
+ sio_speed( siostat->fd, B19200 );
+ break;
+ case SIO_BAUD_38400:
+ sio_speed( siostat->fd, B38400 );
+ break;
+ case SIO_BAUD_57600:
+ sio_speed( siostat->fd, B57600 );
+ break;
+ case SIO_BAUD_115200:
+ sio_speed( siostat->fd, B115200 );
+ break;
+
+ default:
+ LWIP_DEBUGF(SIO_DEBUG, ("sio_change_baud[%d]: Unknown baudrate, code:%d\n",
+ siostat->fd, baud));
+ break;
+ }
+}