blob: c69ba8219390c176cecb8b05fd8c90b739720a6e [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001#include <termios.h>
2#include <pthread.h>
3#include <sys/un.h>
4#include <stdio.h>
5#include <sys/socket.h>
6#include <errno.h>
7#include <stdlib.h>
8#include <fcntl.h>
9#include <string.h>
10#include <sys/epoll.h>
11#include <netinet/in.h>
12#include <signal.h>
13#include <unistd.h>
14#include <sys/select.h>
15
16#include "ql/ql_uart.h"
17#include "mbtk_type.h"
18
19//#define AT_TYPE_SOCKET
20#define MBTK_LOG
21
22#ifdef MBTK_LOG
23#include "mbtk_log.h"
24#else
25#define LOGE printf
26#define LOGD printf
27#define LOGV printf
28#define LOGI printf
29#endif
30
31#define DATABITS CS8
32#define STOPBITS 0
33#define PARITYON 0
34#define PARITY 0
35
36typedef enum {
37 AT_MODE_SOCK_1 = 0,
38 AT_MODE_SOCK_2,
39 AT_MODE_DEV_1,
40 AT_MODE_DEV_2
41} at_mode_enum;
42
43static int epoll_fd = -1;
44static struct epoll_event epoll_events[20];
45static int at_fd = -1;
46static at_mode_enum at_mode = AT_MODE_SOCK_1;
47
48static char *at_rsp_complete_tag[] = {
49 "OK",
50 "ERROR",
51 "CONNECT",
52 "+CMS ERROR:",
53 "+CME ERROR:",
54 "NO ANSWER",
55 "NO DIALTONE",
56 NULL};
57
58//#ifdef AT_TYPE_SOCKET
59#define TEMP_FAILURE_RETRY(exp) ({ \
60 typeof (exp) _rc; \
61 do { \
62 _rc = (exp); \
63 } while (_rc == -1 && errno == EINTR); \
64 _rc; })
65//#endif
66
67static void at_epoll_change(int is_add,int fd)
68{
69 struct epoll_event ev;
70 memset(&ev,0x0,sizeof(struct epoll_event));
71 ev.data.fd = fd;
72 ev.events = EPOLLIN | EPOLLET;
73 if(is_add)
74 {
75 epoll_ctl(epoll_fd,EPOLL_CTL_ADD,fd,&ev);
76 }
77 else
78 {
79 epoll_ctl(epoll_fd,EPOLL_CTL_DEL,fd,&ev);
80 }
81}
82
83static int at_set_fd_noblock(int fd)
84{
85 // Set O_NONBLOCK
86 int flags = fcntl(fd, F_GETFL, 0);
87 if (flags < 0) {
88 LOGE("Get flags error:%s\n", strerror(errno));
89 return -1;
90 }
91 flags |= O_NONBLOCK;
92 if (fcntl(fd, F_SETFL, flags) < 0) {
93 LOGE("Set flags error:%s\n", strerror(errno));
94 return -1;
95 }
96
97 return 0;
98}
99
100//#ifdef AT_TYPE_SOCKET
101int openSocket(const char* sockname)
102{
103 int sock = socket(AF_UNIX, SOCK_STREAM, 0);
104 if (sock < 0) {
105 LOGE("Error create socket: %s\n", strerror(errno));
106 return -1;
107 }
108 struct sockaddr_un addr;
109 memset(&addr, 0, sizeof(addr));
110 addr.sun_family = AF_UNIX;
111 strncpy(addr.sun_path, sockname, sizeof(addr.sun_path));
112 while (TEMP_FAILURE_RETRY(connect(sock,(const struct sockaddr*)&addr, sizeof(addr))) != 0) {
113 LOGE("Error connect to socket %s: %s, try again", sockname, strerror(errno));
114 sleep(1);
115 }
116
117#if 0
118 int sk_flags = fcntl(sock, F_GETFL, 0);
119 fcntl(sock, F_SETFL, sk_flags | O_NONBLOCK);
120#endif
121
122 return sock;
123}
124
125//#else
126
127static int at_open(char *dev)
128{
129 // Init USB PC port.
130 struct termios ser_settings;
131 int fd = -1;
132
133usb_pc_init:
134 fd = open(dev,O_RDWR);
135 if(fd <= 0)
136 {
137 if(errno == ENODEV)
138 {
139 LOGD("Wait dev[%s] ready...",dev);
140 usleep(500000);
141 goto usb_pc_init;
142 }
143
144 LOGE("Cannot open USB PC port[%s] - [errno = %d]",dev,errno);
145 return -1;
146 }
147
148 tcgetattr(fd, &ser_settings);
149 cfmakeraw(&ser_settings);
150 //ser_settings.c_lflag |= (ECHO | ECHONL);
151 //ser_settings.c_lflag &= ~ECHOCTL;
152 tcsetattr(fd, TCSANOW, &ser_settings);
153
154#if 0
155 if(at_set_fd_noblock(at_fd))
156 {
157 LOGE("at_set_fd_noblock() fail.");
158 return -1;
159 }
160
161 at_epoll_change(1, at_fd);
162#endif
163
164 return fd;
165}
166//#endif
167
168static int adb_port_open(const char *dev, unsigned int baud)
169{
170 int fd;
171
172 while((fd = open(dev, O_RDWR)) < 0)
173 {
174 printf("%s: open %s failed\n", __func__, dev);
175 sleep(1);
176 }
177
178 /* set newtio */
179 struct termios newtio;
180 memset(&newtio, 0, sizeof(newtio));
181#if 0
182 (void)fcntl(fd, F_SETFL, 0);
183 newtio.c_cflag = BAUD | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
184 newtio.c_iflag = IGNPAR;
185 newtio.c_oflag = 0;
186 newtio.c_lflag = 0; /* disable ECHO, ICANON, etc... */
187
188 newtio.c_cc[VERASE] = 0x8; /* del */
189 newtio.c_cc[VEOF] = 4; /* Ctrl-d */
190 newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
191 newtio.c_cc[VEOL] = 0xD; /* '\0' */
192
193 tcflush(fd, TCIFLUSH);
194 tcsetattr(fd, TCSANOW, &newtio);
195#else
196 if (tcflush(fd, TCIOFLUSH) < 0) {
197 printf("Could not flush uart port\n");
198 return -1;
199 }
200
201 newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
202 newtio.c_cc[VMIN] = 1; /* blocking read until 5 chars received */
203 newtio.c_cflag |= (CS8 | CLOCAL | CREAD);
204 newtio.c_iflag = IGNPAR;
205 newtio.c_oflag = 0;
206 newtio.c_lflag = 0;
207
208 int rate = baud; // Default bitrate.
209 switch(rate)
210 {
211 case 300:
212 cfsetospeed(&newtio, B300);
213 cfsetispeed(&newtio, B300);
214 break;
215 case 600:
216 cfsetospeed(&newtio, B600);
217 cfsetispeed(&newtio, B600);
218 break;
219 case 1200:
220 cfsetospeed(&newtio, B1200);
221 cfsetispeed(&newtio, B1200);
222 break;
223 case 2400:
224 cfsetospeed(&newtio, B2400);
225 cfsetispeed(&newtio, B2400);
226 break;
227 case 4800:
228 cfsetospeed(&newtio, B4800);
229 cfsetispeed(&newtio, B4800);
230 break;
231 case 9600:
232 cfsetospeed(&newtio, B9600);
233 cfsetispeed(&newtio, B9600);
234 break;
235 case 19200:
236 cfsetospeed(&newtio, B19200);
237 cfsetispeed(&newtio, B19200);
238 break;
239 case 38400:
240 cfsetospeed(&newtio, B38400);
241 cfsetispeed(&newtio, B38400);
242 break;
243 case 57600:
244 cfsetospeed(&newtio, B57600);
245 cfsetispeed(&newtio, B57600);
246 break;
247 case 115200:
248 cfsetospeed(&newtio, B115200);
249 cfsetispeed(&newtio, B115200);
250 break;
251 case 230400:
252 cfsetospeed(&newtio, B230400);
253 cfsetispeed(&newtio, B230400);
254 break;
255 case 460800:
256 cfsetospeed(&newtio, B460800);
257 cfsetispeed(&newtio, B460800);
258 break;
259 case 921600:
260 cfsetospeed(&newtio, B921600);
261 cfsetispeed(&newtio, B921600);
262 break;
263 case 1500000:
264 cfsetospeed(&newtio, B1500000);
265 cfsetispeed(&newtio, B1500000);
266 break;
267 case 2000000:
268 cfsetospeed(&newtio, B2000000);
269 cfsetispeed(&newtio, B2000000);
270 break;
271 case 3000000:
272 cfsetospeed(&newtio, B3000000);
273 cfsetispeed(&newtio, B3000000);
274 break;
275 case 4000000:
276 cfsetospeed(&newtio, B4000000);
277 cfsetispeed(&newtio, B4000000);
278 break;
279 default:
280 cfsetospeed(&newtio, B115200);
281 cfsetispeed(&newtio, B115200);
282 break;
283 }
284
285 if (tcsetattr(fd, TCSANOW, &newtio) < 0) {
286 printf("Can't set port setting\n");
287 return -1;
288 }
289 /* Blocking behavior */
290 fcntl(fd, F_SETFL, 0);
291#endif
292
293 return fd;
294}
295
296
297static void signal_process(int signal_num) {
298 if(at_fd > 0) {
299 close(at_fd);
300 }
301#ifdef MBTK_LOG
302 LOGD("Exit by sig - %d\n", signal_num);
303#endif
304 exit(0);
305}
306
307static void* read_thread_run( void *arg)
308{
309 //UNUSED(arg);
310
311 char at_rsp[1024];
312 char *ptr;
313 int index;
314 int len;
315 while(at_fd > 0) {
316 memset(at_rsp, 0x0, 1024);
317 index = 0;
318 len = 0;
319 while(1) {
320 if((len = read(at_fd, at_rsp + index, 1024)) > 0) {
321 ptr = at_rsp;
322 while(*ptr == '\r' || *ptr == '\n')
323 {
324 ptr++;
325 }
326 if(strlen(ptr) > 0 && ptr[strlen(ptr) - 1] == '\n') {
327 printf("<%s\n", ptr);
328#ifdef MBTK_LOG
329 LOGV("RSP:%s", ptr);
330#endif
331
332 break;
333 } else {
334 index += len;
335 }
336 } else {
337 LOGE("Read error:%d",errno);
338 return NULL;
339 }
340 }
341 }
342
343 LOGD("read_thread_run() exit.\n");
344 return NULL;
345}
346
347static int read_thread_start()
348{
349 pthread_t tid;
350 pthread_attr_t attr;
351 pthread_attr_init (&attr);
352 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
353 int ret = pthread_create(&tid, &attr, read_thread_run, &attr);
354 if (ret < 0)
355 {
356 LOGE("pthread_create\n");
357 return -1;
358 }
359
360 return 0;
361}
362
363static int at_complete(char *rsp)
364{
365#if 0
366 char *ptr = at_rsp_complete_tag;
367 while(ptr) {
368 LOGD("ptr = %s", ptr);
369 if(strstr(rsp, ptr)) {
370 LOGD("%s , %s", rsp, ptr);
371 return 1;
372 }
373 ptr++;
374 }
375#else
376 int i = 0;
377 while(at_rsp_complete_tag[i]) {
378 LOGD("ptr = %s", at_rsp_complete_tag[i]);
379 if(strstr(rsp, at_rsp_complete_tag[i])) {
380 LOGD("%s , %s", rsp, at_rsp_complete_tag[i]);
381 return 1;
382 }
383 i++;
384 }
385
386#endif
387 return 0;
388}
389
390static void at_rsp_read()
391{
392 char at_rsp[1024];
393 int len = 0;
394 while(1) {
395 memset(at_rsp, 0x0, 1024);
396 if((len = read(at_fd, at_rsp, 1024)) > 0) {
397 printf("%s", at_rsp);
398 if(at_complete(at_rsp)) {
399 break;
400 }
401 } else {
402 printf("Read error:%d\n",errno);
403 break;
404 }
405 }
406}
407
408static void help()
409{
410 printf("at : Enter AT mode(Socket).\n");
411 printf("at <at_cmd>: Send AT command(Socket).\n");
412 printf("at <dev>: Enter AT mode(Device).\n");
413 printf("at <dev> echo: ´®¿ÚÊý¾Ý»ØÏÔ¡£\n");
414 printf("at <dev> <at_cmd>: Send AT command(Device).\n");
415}
416
417static void sig_process(int sig)
418{
419 LOGI("I got signal %d\n", sig);
420 switch(sig)
421 {
422 case SIGINT: // Ctrl + C
423 {
424 LOGI("Exit by SIGINT.\n");
425 exit(0);
426 }
427 case SIGQUIT: // Ctrl + \ (ÀàËÆ SIGINT £¬µ«Òª²úÉúcoreÎļþ)
428 {
429 LOGI("Exit by SIGQUIT.\n");
430 exit(0);
431 }
432 case SIGTERM:// ĬÈÏkill (ͬ SIGKILL £¬µ« SIGKILL ²»¿É²¶»ñ)
433 {
434 LOGI("Exit by SIGTERM.\n");
435 exit(0);
436 }
437 case SIGTSTP:// Ctrl + Z (ͬ SIGSTOP £¬µ« SIGSTOP ²»¿É²¶»ñ)
438 {
439 LOGI("Exit by SIGTSTP.\n");
440 exit(0);
441 }
442 case SIGSEGV: // Èç¿ÕÖ¸Õë
443 {
444 LOGI("Exit by SIGSEGV.\n");
445 exit(0);
446 }
447 default:
448 {
449 LOGI("Unknown sig:%d\n",sig);
450 break;
451 }
452 }
453}
454
455int main(int argc, char *argv[])
456{
457 //UNUSED(argc);
458 //UNUSED(argv);
459 signal(SIGINT, sig_process);
460 signal(SIGQUIT, sig_process);
461 signal(SIGTERM, sig_process);
462 //signal(SIGTSTP, sig_process);
463 //signal(SIGSEGV, sig_process);
464
465#ifdef MBTK_LOG
466 mbtk_log_init("radio", "MBTK_AT");
467 LOGI("mbtk_at start.");
468#endif
469
470 signal(SIGKILL, signal_process);
471 signal(SIGINT, signal_process);
472 signal(SIGQUIT, signal_process);
473 signal(SIGTERM, signal_process);
474
475 char *at_cmd = NULL;
476 bool echo = FALSE;
477 if(argc == 1) {
478 at_mode = AT_MODE_SOCK_1;
479 } else if(argc == 2) {
480 if(!strncasecmp(argv[1], "at", 2)) {
481 at_mode = AT_MODE_SOCK_2;
482 at_cmd = argv[1];
483 } else if(!strncasecmp(argv[1], "/dev/", 5)) {
484 at_mode = AT_MODE_DEV_1;
485 } else {
486 help();
487 return -1;
488 }
489 } else if(argc == 3) {
490 if(!strncasecmp(argv[1], "/dev/", 5) && (!strncasecmp(argv[2], "at", 2) || !strncasecmp(argv[2], "echo", 4))) {
491 at_mode = AT_MODE_DEV_2;
492 if(!strncasecmp(argv[2], "at", 2)) {
493 at_cmd = argv[2];
494 } else {
495 echo = TRUE;
496 }
497 } else {
498 help();
499 return -1;
500 }
501 } else {
502 help();
503 return -1;
504 }
505#if 0
506#ifdef AT_TYPE_SOCKET
507 at_fd = openSocket("/tmp/atcmdmbtk");
508#else
509 at_fd = at_open(argv[1]);
510#endif
511 if(at_fd > 0) {
512#ifdef AT_TYPE_SOCKET
513 if(argc > 1) {
514 char *at_cmd = argv[1];
515#else
516 if(argc > 2) {
517 char *at_cmd = argv[2];
518#endif
519#endif
520
521 if(at_mode == AT_MODE_SOCK_1 || at_mode == AT_MODE_SOCK_2) {
522 at_fd = openSocket("/tmp/atcmdmbtk");
523 } else {
524#if 0
525 at_fd = at_open(argv[1]);
526#else
527 if(echo) {
528 at_fd = adb_port_open(argv[1], 115200);
529 } else {
530 at_fd = at_open(argv[1]);
531 }
532#endif
533 }
534 if(at_fd > 0) {
535 if(at_cmd != NULL) {
536 char *ptr = at_cmd + strlen(at_cmd) - 1;
537 while(ptr >= at_cmd && (*ptr == '\r' || *ptr == '\n'))
538 {
539 *ptr-- = '\0';
540 }
541 // printf("AT:[%ld]%s\n", strlen(at_cmd), at_cmd);
542 if(!strncasecmp(at_cmd, "at", 2))
543 {
544 *(++ptr) = '\r';
545 *(++ptr) = '\n';
546 if(write(at_fd, at_cmd, strlen(at_cmd)) <= 0) {
547 printf("Write error:%d\n", errno);
548 } else {
549 // Read response.
550 at_rsp_read();
551 }
552 } else {
553 printf("AT error!\n");
554 }
555 } else {
556 if(echo) {
557 char read_buff[1024];
558 char write_buff[1024];
559 int len;
560#if 0
561 fd_set fds;
562 int fdcount, nfds = 0;
563 while(1) {
564 FD_SET(at_fd, &fds);
565 if(at_fd > nfds)
566 nfds = at_fd;
567
568 fdcount = select(nfds + 1, &fds, NULL, NULL, NULL);
569 if(fdcount < 0) /* error */
570 {
571 printf("select returned %d, errno %d, continue\r", fdcount, errno);
572 sleep(1);
573 continue;
574 }
575
576 if(FD_ISSET(at_fd, &fds))
577 {
578 FD_CLR(at_fd, &fds);
579 memset(read_buff, 0x0, 1024);
580 if((len = read(at_fd, read_buff, 1024)) > 0) {
581 memset(write_buff, 0x0, 1024);
582 printf("%s\n", read_buff);
583 len = snprintf(write_buff, 1024, "%s\n", read_buff);
584 write(at_fd, write_buff, len);
585 } else {
586 printf("Read error:%d\n",errno);
587 return NULL;
588 }
589 }
590 }
591#else
592 printf("Waitting data!!!\n");
593 while(1) {
594 memset(read_buff, 0x0, 1024);
595 if((len = read(at_fd, read_buff, 1024)) > 0) {
596 memset(write_buff, 0x0, 1024);
597 printf("%s\n", read_buff);
598 len = snprintf(write_buff, 1024, "%s\n", read_buff);
599 write(at_fd, write_buff, len);
600 } else {
601 printf("Read error:%d\n",errno);
602 return NULL;
603 }
604 }
605#endif
606 } else {
607 setbuf(stdout, NULL);
608 read_thread_start();
609 char at_cmd[100];
610 //printf(">>");
611 while(1)
612 {
613 memset(at_cmd, 0x0, 100);
614 if(fgets(at_cmd, 100, stdin))
615 {
616 char *ptr = at_cmd + strlen(at_cmd) - 1;
617 while(ptr >= at_cmd && (*ptr == '\r' || *ptr == '\n'))
618 {
619 *ptr-- = '\0';
620 }
621 // printf("AT:[%ld]%s\n", strlen(at_cmd), at_cmd);
622 if(!strncasecmp(at_cmd, "at", 2))
623 {
624 *(++ptr) = '\r';
625 *(++ptr) = '\n';
626 if(write(at_fd, at_cmd, strlen(at_cmd)) <= 0) {
627 LOGE("Write error:%d",errno);
628 break;
629 }
630 printf(">%s",at_cmd);
631#ifdef MBTK_LOG
632 LOGV("AT:%s",at_cmd);
633#endif
634 } else if(!strcasecmp(at_cmd, "q")) {
635 break;
636 } else {
637 printf("\n");
638 }
639 }
640 }
641 }
642 }
643
644 close(at_fd);
645
646#ifdef MBTK_LOG
647 LOGD("EXIT");
648#endif
649 }
650
651 return 0;
652}