1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * lws-minimal-raw-file
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Written in 2010-2019 by Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * This file is made available under the Creative Commons CC0 1.0
7*1c60b9acSAndroid Build Coastguard Worker * Universal Public Domain Dedication.
8*1c60b9acSAndroid Build Coastguard Worker *
9*1c60b9acSAndroid Build Coastguard Worker * This demonstrates dealing with a serial port
10*1c60b9acSAndroid Build Coastguard Worker */
11*1c60b9acSAndroid Build Coastguard Worker
12*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
13*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
14*1c60b9acSAndroid Build Coastguard Worker #include <signal.h>
15*1c60b9acSAndroid Build Coastguard Worker #include <sys/types.h>
16*1c60b9acSAndroid Build Coastguard Worker #include <sys/stat.h>
17*1c60b9acSAndroid Build Coastguard Worker #include <fcntl.h>
18*1c60b9acSAndroid Build Coastguard Worker
19*1c60b9acSAndroid Build Coastguard Worker #include <termios.h>
20*1c60b9acSAndroid Build Coastguard Worker #include <sys/ioctl.h>
21*1c60b9acSAndroid Build Coastguard Worker
22*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__)
23*1c60b9acSAndroid Build Coastguard Worker #include <asm/ioctls.h>
24*1c60b9acSAndroid Build Coastguard Worker #include <linux/serial.h>
25*1c60b9acSAndroid Build Coastguard Worker #endif
26*1c60b9acSAndroid Build Coastguard Worker
27*1c60b9acSAndroid Build Coastguard Worker struct raw_vhd {
28*1c60b9acSAndroid Build Coastguard Worker lws_sorted_usec_list_t sul;
29*1c60b9acSAndroid Build Coastguard Worker struct lws *wsi;
30*1c60b9acSAndroid Build Coastguard Worker int filefd;
31*1c60b9acSAndroid Build Coastguard Worker };
32*1c60b9acSAndroid Build Coastguard Worker
33*1c60b9acSAndroid Build Coastguard Worker static char filepath[256];
34*1c60b9acSAndroid Build Coastguard Worker
35*1c60b9acSAndroid Build Coastguard Worker static void
sul_cb(lws_sorted_usec_list_t * sul)36*1c60b9acSAndroid Build Coastguard Worker sul_cb(lws_sorted_usec_list_t *sul)
37*1c60b9acSAndroid Build Coastguard Worker {
38*1c60b9acSAndroid Build Coastguard Worker struct raw_vhd *v = lws_container_of(sul, struct raw_vhd, sul);
39*1c60b9acSAndroid Build Coastguard Worker
40*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(v->wsi);
41*1c60b9acSAndroid Build Coastguard Worker
42*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(lws_get_context(v->wsi), 0, &v->sul, sul_cb,
43*1c60b9acSAndroid Build Coastguard Worker 2 * LWS_USEC_PER_SEC);
44*1c60b9acSAndroid Build Coastguard Worker }
45*1c60b9acSAndroid Build Coastguard Worker
46*1c60b9acSAndroid Build Coastguard Worker static int
callback_raw_test(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)47*1c60b9acSAndroid Build Coastguard Worker callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason,
48*1c60b9acSAndroid Build Coastguard Worker void *user, void *in, size_t len)
49*1c60b9acSAndroid Build Coastguard Worker {
50*1c60b9acSAndroid Build Coastguard Worker struct raw_vhd *vhd = (struct raw_vhd *)lws_protocol_vh_priv_get(
51*1c60b9acSAndroid Build Coastguard Worker lws_get_vhost(wsi), lws_get_protocol(wsi));
52*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__)
53*1c60b9acSAndroid Build Coastguard Worker struct serial_struct s_s;
54*1c60b9acSAndroid Build Coastguard Worker #endif
55*1c60b9acSAndroid Build Coastguard Worker lws_sock_file_fd_type u;
56*1c60b9acSAndroid Build Coastguard Worker struct termios tio;
57*1c60b9acSAndroid Build Coastguard Worker uint8_t buf[1024];
58*1c60b9acSAndroid Build Coastguard Worker int n;
59*1c60b9acSAndroid Build Coastguard Worker
60*1c60b9acSAndroid Build Coastguard Worker switch (reason) {
61*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_PROTOCOL_INIT:
62*1c60b9acSAndroid Build Coastguard Worker vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
63*1c60b9acSAndroid Build Coastguard Worker lws_get_protocol(wsi), sizeof(struct raw_vhd));
64*1c60b9acSAndroid Build Coastguard Worker vhd->filefd = lws_open(filepath, O_RDWR);
65*1c60b9acSAndroid Build Coastguard Worker if (vhd->filefd == -1) {
66*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Unable to open %s\n", filepath);
67*1c60b9acSAndroid Build Coastguard Worker
68*1c60b9acSAndroid Build Coastguard Worker return 1;
69*1c60b9acSAndroid Build Coastguard Worker }
70*1c60b9acSAndroid Build Coastguard Worker
71*1c60b9acSAndroid Build Coastguard Worker tcflush(vhd->filefd, TCIOFLUSH);
72*1c60b9acSAndroid Build Coastguard Worker
73*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__)
74*1c60b9acSAndroid Build Coastguard Worker if (ioctl(vhd->filefd, TIOCGSERIAL, &s_s) == 0) {
75*1c60b9acSAndroid Build Coastguard Worker s_s.closing_wait = ASYNC_CLOSING_WAIT_NONE;
76*1c60b9acSAndroid Build Coastguard Worker ioctl(vhd->filefd, TIOCSSERIAL, &s_s);
77*1c60b9acSAndroid Build Coastguard Worker }
78*1c60b9acSAndroid Build Coastguard Worker #endif
79*1c60b9acSAndroid Build Coastguard Worker
80*1c60b9acSAndroid Build Coastguard Worker /* enforce suitable tty state */
81*1c60b9acSAndroid Build Coastguard Worker
82*1c60b9acSAndroid Build Coastguard Worker memset(&tio, 0, sizeof tio);
83*1c60b9acSAndroid Build Coastguard Worker if (tcgetattr(vhd->filefd, &tio)) {
84*1c60b9acSAndroid Build Coastguard Worker close(vhd->filefd);
85*1c60b9acSAndroid Build Coastguard Worker vhd->filefd = -1;
86*1c60b9acSAndroid Build Coastguard Worker return -1;
87*1c60b9acSAndroid Build Coastguard Worker }
88*1c60b9acSAndroid Build Coastguard Worker
89*1c60b9acSAndroid Build Coastguard Worker cfsetispeed(&tio, B115200);
90*1c60b9acSAndroid Build Coastguard Worker cfsetospeed(&tio, B115200);
91*1c60b9acSAndroid Build Coastguard Worker
92*1c60b9acSAndroid Build Coastguard Worker tio.c_lflag &= (tcflag_t)~(ISIG | ICANON | IEXTEN | ECHO |
93*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__)
94*1c60b9acSAndroid Build Coastguard Worker XCASE |
95*1c60b9acSAndroid Build Coastguard Worker #endif
96*1c60b9acSAndroid Build Coastguard Worker ECHOE | ECHOK | ECHONL | ECHOCTL | ECHOKE);
97*1c60b9acSAndroid Build Coastguard Worker tio.c_iflag &= (tcflag_t)~(INLCR | IGNBRK | IGNPAR | IGNCR | ICRNL |
98*1c60b9acSAndroid Build Coastguard Worker IMAXBEL | IXON | IXOFF | IXANY
99*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__)
100*1c60b9acSAndroid Build Coastguard Worker | IUCLC
101*1c60b9acSAndroid Build Coastguard Worker #endif
102*1c60b9acSAndroid Build Coastguard Worker | 0xff);
103*1c60b9acSAndroid Build Coastguard Worker tio.c_oflag = 0;
104*1c60b9acSAndroid Build Coastguard Worker
105*1c60b9acSAndroid Build Coastguard Worker tio.c_cc[VMIN] = 1;
106*1c60b9acSAndroid Build Coastguard Worker tio.c_cc[VTIME] = 0;
107*1c60b9acSAndroid Build Coastguard Worker tio.c_cc[VEOF] = 1;
108*1c60b9acSAndroid Build Coastguard Worker tio.c_cflag = tio.c_cflag & (unsigned long) ~(
109*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__)
110*1c60b9acSAndroid Build Coastguard Worker CBAUD |
111*1c60b9acSAndroid Build Coastguard Worker #endif
112*1c60b9acSAndroid Build Coastguard Worker CSIZE | CSTOPB | PARENB | CRTSCTS);
113*1c60b9acSAndroid Build Coastguard Worker tio.c_cflag |= 0x1412 | CS8 | CREAD | CLOCAL;
114*1c60b9acSAndroid Build Coastguard Worker
115*1c60b9acSAndroid Build Coastguard Worker tcsetattr(vhd->filefd, TCSANOW, &tio);
116*1c60b9acSAndroid Build Coastguard Worker
117*1c60b9acSAndroid Build Coastguard Worker u.filefd = (lws_filefd_type)(long long)vhd->filefd;
118*1c60b9acSAndroid Build Coastguard Worker if (!lws_adopt_descriptor_vhost(lws_get_vhost(wsi),
119*1c60b9acSAndroid Build Coastguard Worker LWS_ADOPT_RAW_FILE_DESC, u,
120*1c60b9acSAndroid Build Coastguard Worker "raw-test", NULL)) {
121*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Failed to adopt fifo descriptor\n");
122*1c60b9acSAndroid Build Coastguard Worker close(vhd->filefd);
123*1c60b9acSAndroid Build Coastguard Worker vhd->filefd = -1;
124*1c60b9acSAndroid Build Coastguard Worker
125*1c60b9acSAndroid Build Coastguard Worker return 1;
126*1c60b9acSAndroid Build Coastguard Worker }
127*1c60b9acSAndroid Build Coastguard Worker
128*1c60b9acSAndroid Build Coastguard Worker break;
129*1c60b9acSAndroid Build Coastguard Worker
130*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_PROTOCOL_DESTROY:
131*1c60b9acSAndroid Build Coastguard Worker if (vhd && vhd->filefd != -1)
132*1c60b9acSAndroid Build Coastguard Worker close(vhd->filefd);
133*1c60b9acSAndroid Build Coastguard Worker break;
134*1c60b9acSAndroid Build Coastguard Worker
135*1c60b9acSAndroid Build Coastguard Worker /* callbacks related to raw file descriptor */
136*1c60b9acSAndroid Build Coastguard Worker
137*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_ADOPT_FILE:
138*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("LWS_CALLBACK_RAW_ADOPT_FILE\n");
139*1c60b9acSAndroid Build Coastguard Worker vhd->wsi = wsi;
140*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(lws_get_context(wsi), 0, &vhd->sul, sul_cb, 1);
141*1c60b9acSAndroid Build Coastguard Worker break;
142*1c60b9acSAndroid Build Coastguard Worker
143*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_RX_FILE:
144*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("LWS_CALLBACK_RAW_RX_FILE\n");
145*1c60b9acSAndroid Build Coastguard Worker n = (int)read(vhd->filefd, buf, sizeof(buf));
146*1c60b9acSAndroid Build Coastguard Worker if (n < 0) {
147*1c60b9acSAndroid Build Coastguard Worker lwsl_err("Reading from %s failed\n", filepath);
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker return 1;
150*1c60b9acSAndroid Build Coastguard Worker }
151*1c60b9acSAndroid Build Coastguard Worker lwsl_hexdump_level(LLL_NOTICE, buf, (unsigned int)n);
152*1c60b9acSAndroid Build Coastguard Worker break;
153*1c60b9acSAndroid Build Coastguard Worker
154*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_CLOSE_FILE:
155*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("LWS_CALLBACK_RAW_CLOSE_FILE\n");
156*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&vhd->sul);
157*1c60b9acSAndroid Build Coastguard Worker break;
158*1c60b9acSAndroid Build Coastguard Worker
159*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_WRITEABLE_FILE:
160*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("LWS_CALLBACK_RAW_WRITEABLE_FILE\n");
161*1c60b9acSAndroid Build Coastguard Worker if (lws_write(wsi, (uint8_t *)"hello-this-is-written-every-couple-of-seconds\r\n", 47, LWS_WRITE_RAW) != 47)
162*1c60b9acSAndroid Build Coastguard Worker return -1;
163*1c60b9acSAndroid Build Coastguard Worker break;
164*1c60b9acSAndroid Build Coastguard Worker
165*1c60b9acSAndroid Build Coastguard Worker default:
166*1c60b9acSAndroid Build Coastguard Worker break;
167*1c60b9acSAndroid Build Coastguard Worker }
168*1c60b9acSAndroid Build Coastguard Worker
169*1c60b9acSAndroid Build Coastguard Worker return 0;
170*1c60b9acSAndroid Build Coastguard Worker }
171*1c60b9acSAndroid Build Coastguard Worker
172*1c60b9acSAndroid Build Coastguard Worker static struct lws_protocols protocols[] = {
173*1c60b9acSAndroid Build Coastguard Worker { "raw-test", callback_raw_test, 0, 0, 0, NULL, 0 },
174*1c60b9acSAndroid Build Coastguard Worker LWS_PROTOCOL_LIST_TERM
175*1c60b9acSAndroid Build Coastguard Worker };
176*1c60b9acSAndroid Build Coastguard Worker
177*1c60b9acSAndroid Build Coastguard Worker static int interrupted;
178*1c60b9acSAndroid Build Coastguard Worker
sigint_handler(int sig)179*1c60b9acSAndroid Build Coastguard Worker void sigint_handler(int sig)
180*1c60b9acSAndroid Build Coastguard Worker {
181*1c60b9acSAndroid Build Coastguard Worker interrupted = 1;
182*1c60b9acSAndroid Build Coastguard Worker }
183*1c60b9acSAndroid Build Coastguard Worker
main(int argc,const char ** argv)184*1c60b9acSAndroid Build Coastguard Worker int main(int argc, const char **argv)
185*1c60b9acSAndroid Build Coastguard Worker {
186*1c60b9acSAndroid Build Coastguard Worker struct lws_context_creation_info info;
187*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context;
188*1c60b9acSAndroid Build Coastguard Worker const char *p;
189*1c60b9acSAndroid Build Coastguard Worker int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
190*1c60b9acSAndroid Build Coastguard Worker /* for LLL_ verbosity above NOTICE to be built into lws,
191*1c60b9acSAndroid Build Coastguard Worker * lws must have been configured and built with
192*1c60b9acSAndroid Build Coastguard Worker * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
193*1c60b9acSAndroid Build Coastguard Worker /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
194*1c60b9acSAndroid Build Coastguard Worker /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
195*1c60b9acSAndroid Build Coastguard Worker /* | LLL_DEBUG */;
196*1c60b9acSAndroid Build Coastguard Worker
197*1c60b9acSAndroid Build Coastguard Worker signal(SIGINT, sigint_handler);
198*1c60b9acSAndroid Build Coastguard Worker
199*1c60b9acSAndroid Build Coastguard Worker if ((p = lws_cmdline_option(argc, argv, "-d")))
200*1c60b9acSAndroid Build Coastguard Worker logs = atoi(p);
201*1c60b9acSAndroid Build Coastguard Worker
202*1c60b9acSAndroid Build Coastguard Worker lws_set_log_level(logs, NULL);
203*1c60b9acSAndroid Build Coastguard Worker lwsl_user("LWS minimal raw serial\n");
204*1c60b9acSAndroid Build Coastguard Worker if (argc < 2) {
205*1c60b9acSAndroid Build Coastguard Worker lwsl_user("Usage: %s <serial device> "
206*1c60b9acSAndroid Build Coastguard Worker " eg, /dev/ttyUSB0\n", argv[0]);
207*1c60b9acSAndroid Build Coastguard Worker
208*1c60b9acSAndroid Build Coastguard Worker return 1;
209*1c60b9acSAndroid Build Coastguard Worker }
210*1c60b9acSAndroid Build Coastguard Worker
211*1c60b9acSAndroid Build Coastguard Worker signal(SIGINT, sigint_handler);
212*1c60b9acSAndroid Build Coastguard Worker
213*1c60b9acSAndroid Build Coastguard Worker memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
214*1c60b9acSAndroid Build Coastguard Worker info.port = CONTEXT_PORT_NO_LISTEN_SERVER; /* no listen socket for demo */
215*1c60b9acSAndroid Build Coastguard Worker info.protocols = protocols;
216*1c60b9acSAndroid Build Coastguard Worker
217*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(filepath, argv[1], sizeof(filepath));
218*1c60b9acSAndroid Build Coastguard Worker
219*1c60b9acSAndroid Build Coastguard Worker context = lws_create_context(&info);
220*1c60b9acSAndroid Build Coastguard Worker if (!context) {
221*1c60b9acSAndroid Build Coastguard Worker lwsl_err("lws init failed\n");
222*1c60b9acSAndroid Build Coastguard Worker return 1;
223*1c60b9acSAndroid Build Coastguard Worker }
224*1c60b9acSAndroid Build Coastguard Worker
225*1c60b9acSAndroid Build Coastguard Worker while (n >= 0 && !interrupted)
226*1c60b9acSAndroid Build Coastguard Worker n = lws_service(context, 0);
227*1c60b9acSAndroid Build Coastguard Worker
228*1c60b9acSAndroid Build Coastguard Worker lws_context_destroy(context);
229*1c60b9acSAndroid Build Coastguard Worker
230*1c60b9acSAndroid Build Coastguard Worker return 0;
231*1c60b9acSAndroid Build Coastguard Worker }
232