source: trunk/tools/alcons/alcons.c @ 349

Last change on this file since 349 was 231, checked in by max@…, 7 years ago

Add a serial port multiplexer, usable to communicate with the
ALMOS-MKH kernel over a serial port.

File size: 7.0 KB
Line 
1/*
2 *******************************************************************************
3 * Authors:
4 *     Maxime Villard, 2017
5 *     Jankovic Marco, 01/07/2014
6 *******************************************************************************
7 */
8
9#include "common.h"
10
11/*
12 * tab containing all the slave side of a dev/pts
13 * this part is swappable with other device
14 */
15int slave_fd[NB_CHANNELS];
16
17/*
18 * tab containing all the masters that come from /dev/pts/ptmx
19 * this part is swappable with other device
20 */
21int master_fd[NB_CHANNELS];
22
23/*
24 * file descriptor of fifo rx and tx
25 * file descriptor device_fd
26 * nb_channels to multiplex
27 */
28int fifo_rx_fd;
29int fifo_tx_fd;
30
31#if TEST_BENCH
32int test_rx_fd; // file descriptor that simulates RX buffer
33int test_tx_fd; // file descriptor that simulates TX buffer
34#else
35int device_fd;
36#endif
37
38pthread_t tid[3];
39
40/*
41 * Function that opens an xterm. You need a master side and a slave side.
42 * master_fd -> contains master fd from /dev/ptmx
43 * slavename -> slave name from /dev/pts
44 */
45static int exec_xterm(int *master_fd, char *slavename, int tty_id)
46{
47        char buf[64];
48        char tty_name[64];
49
50        *master_fd = posix_openpt(O_RDWR);
51        grantpt(*master_fd);
52        unlockpt(*master_fd);
53
54        if (ptsname_r(*master_fd, slavename, 64) != 0)
55                perror("ptsname_r");
56
57        printf("-> master_fd: %d\n", *master_fd);
58        printf("-> slavename: %s\n", slavename);
59
60        snprintf(buf, sizeof(buf), "-S%s/%d", strrchr(slavename,'/')+1, *master_fd);
61        snprintf(tty_name, sizeof(buf), "tty_%d", tty_id);
62        if (!fork()) {
63                execlp("xterm", "xterm",
64                                buf,
65                                "-T", tty_name,
66                                "-bg", "black",
67                                "-fg", "green",
68                                "-geometry", "80x25",
69                                NULL);
70                _exit(1);
71        }
72
73        return 0;
74}
75
76/*
77 * Function that closes all file descriptors, kills all the threads and resets
78 * the rs 232 port.
79 */
80void termination_handler(int signum)
81{
82        int i;
83        printf("termination handler %d \n",signum);
84
85        for (i = 0; i < 3; i++) {
86                if (pthread_kill(tid[i], SIGTERM) < 0)
87                        err(1, "pthread_kill");
88        }
89
90        if (close(fifo_rx_fd) < 0)
91                err(1, "close");
92        if (close(fifo_tx_fd) < 0)
93                err(1, "close");
94
95#if TEST_BENCH
96        if (close(test_tx_fd) < 0)
97                err(1, "close");
98        if (close(test_rx_fd) < 0)
99                err(1, "close");
100#else
101        if (close(device_fd) < 0)
102                err(1, "close");
103#endif
104
105        for (i = 0; i < NB_CHANNELS; i++) {
106                if (close(slave_fd[i]) < 0)
107                        err(1, "close");
108                if (close(master_fd[i]) < 0)
109                        err(1, "close");
110        }
111
112        exit(0);
113}
114
115static void init_tio(struct termios *tio)
116{
117        // Input flags - Turn off input processing
118        // convert break to null byte, no CR to NL translation,
119        // no NL to CR translation, don't mark parity errors or breaks
120        // no input parity check, don't strip high bit off,
121        // no XON/XOFF software flow control
122        tio->c_cflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON | CRTSCTS);
123        tio->c_cflag |= (CLOCAL | CREAD);
124
125        // Output flags - Turn off output processing
126        // // no CR to NL translation, no NL to CR-NL translation,
127        // // no NL to CR translation, no column 0 CR suppression,
128        // // no Ctrl-D suppression, no fill characters, no case mapping,
129        // // no local output processing
130        tio->c_oflag &=~(OCRNL | ONLCR | ONLRET | ONOCR | OFILL | OLCUC | OPOST);
131        tio->c_oflag = 0;
132
133        //// No line processing:
134        //// echo off, echo newline off, canonical mode off,
135        //// extended input processing off, signal chars off
136        ////
137        tio->c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
138
139        ////
140        //// Turn off character processing
141        //// clear current char size mask, no parity checking,
142        //// no output processing, force 8 bit input
143        //// 8N1
144        ////
145        tio->c_cflag &= ~(CSIZE |PARENB|CSTOPB);
146        tio->c_cflag |= CS8;
147        ////
148
149        tio->c_iflag &= ~(IXON | IXOFF | IXANY | INPCK | ISTRIP );
150
151        ////
152        //// One input byte is enough to return from read()
153        //// Inter-character timer off
154        ////
155        tio->c_cc[VMIN]  = 1;
156        tio->c_cc[VTIME] = 0;
157
158        /* set baudrate */
159        if (cfsetispeed(tio, BAUDRATE) < 0 || cfsetospeed(tio, BAUDRATE) < 0)
160                err(1, "error setting baudrate");
161}
162
163int main(void)
164{
165        char slavename[NB_CHANNELS][64];
166        int i;
167        char buf[64];
168
169        pthread_attr_t thread_attr;
170
171        /******************** signal handler ****************/
172        sigset_t sig_set;
173        sigset_t sig_set_act;
174
175        sigemptyset(&sig_set);
176        sigfillset(&sig_set);
177        sigdelset(&sig_set, SIGINT);
178        sigprocmask(SIG_BLOCK, &sig_set, NULL);
179
180        sigemptyset(&sig_set_act);
181
182        struct sigaction action;
183        action.sa_handler = termination_handler;
184        action.sa_mask = sig_set_act;
185        action.sa_flags = 0;
186        sigaction(SIGINT, &action, NULL);
187
188        /****************************************************/
189        printf("[+] device path: %s\n", DEVICE_PATH);
190        printf("[+] nb_channels: %d\n", NB_CHANNELS);
191
192        /*
193         * Opening 2 FIFOs: one fifo for input data and the other one for
194         * output data.
195         */
196        if (mkfifo(FIFO_RX, S_IRWXU) < 0)
197                err(1, "mkfifo");
198        if (mkfifo(FIFO_TX, S_IRWXU) < 0)
199                err(1, "mkfifo");
200
201        if ((fifo_rx_fd = open(FIFO_RX, O_RDWR|O_SYNC|O_NONBLOCK, 0777)) < 0)
202                err(1, "open");
203        if ((fifo_tx_fd = open(FIFO_TX, O_RDWR|O_SYNC|O_NONBLOCK, 0777)) < 0)
204                err(1, "open");
205        /*******************************************************************/
206
207        printf("[+] Opening the xterms\n");
208
209        for (i = 0; i < NB_CHANNELS; i++) {
210                exec_xterm(&master_fd[i], slavename[i], i);
211                slave_fd[i] = open(slavename[i], O_RDWR|O_SYNC, 0777);
212                do {
213                        read(slave_fd[i], buf, 1);
214                } while (*buf != '\n' && *buf != '\r');
215        }
216
217#if TEST_BENCH
218        printf("opening test files\n");
219        if (mkfifo("test_rx.txt", S_IRWXU) < 0)
220                err(1, "mkfifo");
221        if (mkfifo("test_tx.txt", S_IRWXU) < 0)
222                err(1, "mkfifo");
223        if ((test_rx_fd = open("test_rx.txt", O_RDWR|O_SYNC|O_NONBLOCK, 0777)) < 0)
224                err(1, "open");
225        if ((test_tx_fd = open("test_tx.txt", O_RDWR|O_SYNC|O_NONBLOCK, 0777)) < 0)
226                err(1, "open");
227#else
228        printf("[+] Opening %s\n", DEVICE_PATH);
229        if ((device_fd = open(DEVICE_PATH, O_RDWR|O_NOCTTY|O_NDELAY)) < 0)
230                err(1, "open");
231        fcntl(device_fd, F_SETFL, 0);
232
233        /*
234         * Set the rs232 port
235         */
236        struct termios newtio;
237
238        printf("[+] Setting %s rs232 port\n", DEVICE_PATH);
239
240        memset(&newtio, 0, sizeof(newtio));
241        init_tio(&newtio);
242
243        if (tcsetattr(device_fd, TCSAFLUSH, &newtio) < 0)
244                err(1, "tcsetattr");
245#endif
246
247        printf("[+] Launching the threads\n");
248
249        /*
250         * Initialize the thread attributes.
251         */
252        if (pthread_attr_init(&thread_attr) != 0)
253                err(1, "pthread_attr_init");
254        if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) != 0)
255                err(1, "pthread_attr_setdetachstate");
256
257        /*
258         * Launch the threads.
259         */
260        if (pthread_create(tid, &thread_attr, thread_mux_demux, NULL) != 0)
261                err(1, "pthread_create");
262        if (pthread_create(tid + 1, &thread_attr, thread_read_rx, NULL) != 0)
263                err(1, "pthread_create");
264        if (pthread_create(tid + 2, &thread_attr, thread_write_tx, NULL) != 0)
265                err(1, "pthread_create");
266
267#if TEST_BENCH
268        char buftest[2];
269        unsigned char pkt[PACKET_SIZE];
270
271        sleep(1);
272
273        while (1) {
274                printf("ttyid> ");
275
276                buftest[0] = getchar();
277                buftest[1] = '\n';
278                getchar();
279
280                pkt[PKT_TTY] = 0x80 | atoi(buftest);
281
282                printf("cmd> ");
283                do {
284                        pkt[PKT_DAT] = getchar();
285                        write(test_rx_fd, pkt, PACKET_SIZE);
286                } while (pkt[PKT_DAT] != '\n');
287        }
288#else
289        while(1)
290                sleep(1);
291#endif
292
293        return 0;
294}
295
Note: See TracBrowser for help on using the repository browser.