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