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