blob: 45f932ff124705a21d3fd1d43b001a7065909366 [file] [log] [blame]
xf.libdd93d52023-05-12 07:10:14 -07001
2#include <stdio.h>
3#include <unistd.h>
4#include <fcntl.h>
5#include <termios.h>
6#include <sys/time.h>
7#include <string.h>
8#include <errno.h>
9#include "LogInfo.h"
10#include "CSerial.h"
11
12/*******************************************************************************
13 * 宏定义 *
14 *******************************************************************************/
15#define DEV_RSP_COUNT (1024)
16
17/*******************************************************************************
18 * 全局变量 *
19 *******************************************************************************/
20static int m_fd;
21static char rspBufex[DEV_RSP_COUNT] = {0};
22
23/*******************************************************************************
24 * 函数声明 *
25 *******************************************************************************/
26static ssize_t SendAT(const char *pData, size_t length);
27static ssize_t ReadAT(BYTE *pbyReadBuffer, size_t dwReadCount);
28
29
30/*******************************************************************************
31 * 内部函数 *
32 *******************************************************************************/
33/**
34 * @brief 发送AT命令
35 * @param pData 入参,AT命令写入缓冲区
36 * @param length 入参,AT命令长度
37 * @return 成功返回成功写入的字节数,失败返回-1
38 * @retval
39 * @note length不计算结尾\0
40 * @warning
41 */
42static ssize_t SendAT(const char *pData, size_t length)
43{
44 ssize_t dwBytesWritten = -1;
45 ssize_t writeCount = 0;
46 struct timeval timeout;
47 fd_set fds, temps;
48 int result = 0;
49
50 if (m_fd < 0)
51 {
52 return -1;
53 }
54 if (pData != NULL)
55 {
56 LogInfo("pData= (%s) length = %ld ", pData, length);
57 }
58
59 // gettimeofday(&end, NULL);
60 // gettimeofday(&begin, NULL);
61 FD_ZERO(&fds);
62 FD_SET(m_fd, &fds);
63 /* 超时不能在此设置!
64 因为调用select后,结构体timeval的成员tv_sec和tv_usec的值将被替换为超时前剩余时间.
65 调用select函数前,每次都需要初始化timeval结构体变量.
66 timeout.tv_sec = 1;
67 timeout.tv_usec = 0; */
68
69 while (1)
70 {
71 /* 将准备好的fd_set变量reads的内容复制到temps变量,因为调用select函数后,除了发生变化的fd对应位外,
72 剩下的所有位都将初始化为0,为了记住初始值,必须经过这种复制过程。*/
73 temps = fds;
74 // 设置超时
75 timeout.tv_sec = 1;
76 timeout.tv_usec = 0;
77 // 调用select函数
78 result = select(m_fd + 1, NULL, &temps, NULL, &timeout);
79 if (result <= 0)
80 {
81 if (0 == result)
82 {
83 LogInfo("timeout");
84 }
85 else
86 {
87 LogInfo("select() error");
88 }
89 break;
90 // return -1;
91 }
92 else
93 {
94 // 判断m_fd是否可写,若可写,写入数据
95 if (FD_ISSET(m_fd, &temps))
96 {
97 dwBytesWritten = write(m_fd, pData + writeCount, length - writeCount);
98 LogInfo("pData= (%s) dwBytesWritten = %ld ", pData, dwBytesWritten);
99 if (dwBytesWritten > 0)
100 {
101 writeCount += dwBytesWritten;
102 if (writeCount >= length)
103 {
104 break;
105 }
106 }
107 if (dwBytesWritten < 0 && errno != EINTR)
108 {
109 printf("SendAT:: write error, dwBytesWritten = %ld, %s\r\n", dwBytesWritten, strerror(errno));
110 break;
111 }
112 }
113 }
114 }
115
116 if (dwBytesWritten > 0)
117 {
118 return dwBytesWritten;
119 }
120 else
121 {
122 return -1;
123 }
124}
125
126/**
127 * @brief 接收AT命令应答
128 * @param pbyReadBuffer 出参,应答读取缓冲区
129 * @param dwReadCount 入参,应答读取长度
130 * @return 成功返回成功写入的字节数,失败返回-1
131 * @retval
132 * @note
133 * @warning
134 */
135static ssize_t ReadAT(BYTE *pbyReadBuffer, size_t dwReadCount)
136{
137 ssize_t dwBytesRead = -1;
138 ssize_t readCount = 0;
139 int result;
140 fd_set fds, temps;
141 struct timeval timeout;
142
143 if (m_fd < 0)
144 {
145 return -1;
146 }
147 LogInfo("ReadAT start");
148
149 FD_ZERO(&fds);
150 FD_SET(m_fd, &fds);
151
152 while (1)
153 {
154 temps = fds;
155 // 设置超时
156 timeout.tv_sec = 1;
157 timeout.tv_usec = 0;
158 // 调用select函数
159 result = select(m_fd + 1, &temps, NULL, NULL, &timeout);
160 if (result <= 0)
161 {
162 if (0 == result)
163 {
164 LogInfo("timeout");
165 }
166 else
167 {
168 LogInfo("select() error");
169 }
170 return -1;
171 }
172 else
173 {
174 // 判断m_fd是否可读,若可读,读取数据
175 if (FD_ISSET(m_fd, &temps))
176 {
177 dwBytesRead = read(m_fd, pbyReadBuffer + readCount, dwReadCount - readCount);
178 LogInfo("pData= (%s) dwBytesWritten = %ld ", pbyReadBuffer, dwBytesRead);
179 if (dwBytesRead > 0)
180 {
181 readCount += dwBytesRead;
182 if (readCount >= dwReadCount)
183 {
184 break;
185 }
186 }
187 if (dwBytesRead < 0 && errno != EINTR)
188 {
189 printf("ReadAT::read error, dwBytesRead = %ld, %s\r\n", dwBytesRead, strerror(errno));
190 break;
191 }
192 }
193 }
194 }
195
196 if (dwBytesRead > 0)
197 {
198 return dwBytesRead;
199 }
200 else
201 {
202 return -1;
203 }
204}
205
206
207/*******************************************************************************
208 * 外部函数 *
209 *******************************************************************************/
210/**
211 * @brief 打开设备文件,并设置波特率等参数
212 * @param portName 入参,端口名
213 * @return 成功返回0,失败返回-1
214 * @retval
215 * @note
216 * @warning
217 */
218int Open(const char *portName)
219{
220 // char portname_full[20] = "/dev/";
221 // strcat(portname_full, portName);
222 // portName = +portName ;
223
224 struct termios attr;
225 int flags;
226
227 if (portName != NULL)
228 {
229 LogInfo("portname = (%s)", portName);
230 }
231 m_fd = open(portName, O_RDWR | O_NONBLOCK | O_NOCTTY | O_TRUNC);
232 if (m_fd < 0)
233 {
234 LogInfo("Open m_fd < 0 m_fd = %d\n", m_fd);
235 return -1;
236 }
237 else
238 {
239 LogInfo("Open m_fd > 0 m_fd = %d\n", m_fd);
240 }
241 tcflush(m_fd, TCIOFLUSH); // clear serial data
242 if (tcgetattr(m_fd, &attr) < 0)
243 {
244 close(m_fd);
245 return -1;
246 }
247 attr.c_iflag = IXON | IXOFF;
248 attr.c_oflag = 0;
249 attr.c_cflag &= ~(CSIZE | CFLAGS_TO_CLEAR | CFLAGS_HARDFLOW);
250 attr.c_cflag |= (CS8 | CFLAGS_TO_SET);
251 attr.c_cflag |= CFLAGS_HARDFLOW;
252 attr.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ISIG);
253 attr.c_lflag &= ~OPOST;
254 int i;
255#ifdef _POSIX_VDISABLE
256 attr.c_cc[0] = _POSIX_VDISABLE;
257#else
258 attr.c_cc[0] = fpathconf(m_fd, _PC_VDISABLE);
259#endif
260
261 for (i = 1; i < NCCS; i++)
262 {
263 attr.c_cc[i] = attr.c_cc[0];
264 }
265
266 attr.c_cc[VMIN] = 0;
267 attr.c_cc[VTIME] = 5;
268 cfsetispeed(&attr, BAUDRATE);
269 cfsetospeed(&attr, BAUDRATE);
270 if (tcsetattr(m_fd, TCSANOW, &attr) < 0)
271 {
272 close(m_fd);
273 return -1;
274 }
275 flags = fcntl(m_fd, F_GETFL, 0);
276 if (flags < 0)
277 {
278 close(m_fd);
279 return -1;
280 }
281 if (fcntl(m_fd, F_SETFL, flags) < 0)
282 {
283 close(m_fd);
284 return -1;
285 }
286 // m_isOpen = true;
287 // StartRead();
288 return 0;
289}
290
291/**
292 * @brief 关闭设备文件
293 * @param 无
294 * @return 成功关闭返回0,否则返回-1
295 * @retval
296 * @note
297 * @warning
298 */
299int Close()
300{
301 tcflush(m_fd, TCIOFLUSH); // clear serial data
302 if (m_fd > 0)
303 {
304 // printf("close m_fd\n");
305 close(m_fd);
306 }
307 else
308 {
309 printf("%s:: close->else\n", __FUNCTION__);
310 return -1;
311 }
312 m_fd = 0;
313 return 0;
314}
315
316/**
317 * @brief 发送AT命令并读取返回值
318 * @param Dev_tty 入参,打开的AT口设备路径
319 * @param AtString 入参,发送的AT命令字符串
320 * @param RebackString 出参,AT命令返回的字符串
321 * @return 成功返回0,失败返回-1
322 * @retval
323 * @note
324 * @warning
325 */
326int SendATString(const char *Dev_tty, const char *AtString, char *RebackString)
327{
328 BYTE tmp[1024] = {0};
329
330 printf("%s:: Before Open port, (%s)\n", __FUNCTION__, Dev_tty);
331 if (-1 == (Open(Dev_tty)))
332 {
333 if (AtString != NULL)
334 {
335 LogInfo("SendATString Failed AtString = (%s)", AtString);
336 }
337 printf("%s:: Open port error\r\n", __FUNCTION__);
338 return -1;
339 }
340 if (AtString != NULL)
341 {
342 LogInfo("SendATString OK, AtString = (%s)", AtString);
343 }
344
345 LogInfo("Before SendAT");
346 if(SendAT(AtString, strlen(AtString)) < 0)
347 {
348 LogInfo("SendAT failed");
349 Close();
350 return -1;
351 }
352 LogInfo("After SendAT");
353
354 ReadAT(tmp, 1024);
355 LogInfo("out ReadAT");
356
357 memcpy(RebackString, tmp, 1024);
358 LogInfo("after memcpy");
359
360 Close();
361 return 0;
362}
363
364/**
365 * @brief 发送数据
366 * @param pbyWriteBuffer 入参,写入数据缓冲区
367 * @param dwWriteCount 入参,写入数据长度
368 * @param dwSleepAfterAction 入参,
369 * @param dwTimeoutCount 入参,超时时间,单位秒
370 * @return 成功返回TRUE,失败返回FALSE
371 * @retval
372 * @note
373 * @warning
374 */
375BOOL SendData(const BYTE *pbyWriteBuffer, size_t dwWriteCount, DWORD dwSleepAfterAction, DWORD dwTimeoutCount)
376{
377 ssize_t sBytesWritten = -1;
378 ssize_t writeCount = 0;
379 struct timeval timeout;
380 fd_set fds, temps;
381 int result = 0;
382 // int count = 0; // 超时计数
383
384 LogInfo("writecount %d, timeout %d s", dwWriteCount, dwTimeoutCount);
385 if (m_fd < 0)
386 {
387 LogInfo("m_fd < 0");
388 return FALSE;
389 }
390
391 FD_ZERO(&fds);
392 FD_SET(m_fd, &fds);
393
394 tcflush(m_fd, TCIOFLUSH); // clear serial data
395
396 if (dwTimeoutCount < 10)
397 {
398 dwTimeoutCount = 10;
399 }
400 /* 超时不能在此设置!
401 因为调用select后,结构体timeval的成员tv_sec和tv_usec的值将被替换为超时前剩余时间.
402 调用select函数前,每次都需要初始化timeval结构体变量.
403 timeout.tv_sec = 1;
404 timeout.tv_usec = 0; */
405
406 while (1)
407 {
408 /*将准备好的fd_set变量reads的内容复制到temps变量,因为调用select函数后,除了发生变化的fd对应位外,
409 剩下的所有位都将初始化为0,为了记住初始值,必须经过这种复制过程。*/
410 temps = fds;
411 // 设置超时
412 timeout.tv_sec = dwTimeoutCount;
413 timeout.tv_usec = 0;
414 // 调用select函数
415 result = select(m_fd + 1, NULL, &temps, NULL, &timeout);
416 LogInfo("select result = %d ", result);
417 if (-1 == result)
418 {
419 LogInfo("select() error\n");
420 perror("SendData:: select() error\n");
421 break;
422 }
423 else if (0 == result)
424 {
425 puts("SendData:: timeout\r\n");
426 break;
427 }
428 else
429 {
430 // 判断m_fd是否可写,若可写,写入数据
431 if (FD_ISSET(m_fd, &temps))
432 {
433 sBytesWritten = write(m_fd, (char *)pbyWriteBuffer + writeCount, dwWriteCount - writeCount);
434 LogInfo("pbyWriteBuffer= (%s) dwBytesWritten = %ld ", pbyWriteBuffer, sBytesWritten);
435 if (sBytesWritten > 0)
436 {
437 writeCount += sBytesWritten;
438 if (writeCount >= dwWriteCount)
439 {
440 return TRUE; // complete success
441 }
442 }
443 else
444 {
445 if (sBytesWritten < 0 && errno != EINTR)
446 {
447 printf("SendData::write error, dwBytesWritten = %ld, %s\r\n", sBytesWritten, strerror(errno));
448 }
449 return FALSE;
450 }
451 }
452 }
453 }
454 return FALSE;
455}
456
457/**
458 * @brief 接收数据
459 * @param pbyReadBuffer 入参,读取数据缓冲区
460 * @param dwReadCount 入参,读取数据长度
461 * @param dwSleepAfterAction 入参,
462 * @param dwTimeoutCount 入参,超时时间,单位秒
463 * @return 成功返回TRUE,失败返回FALSE
464 * @retval
465 * @note
466 * @warning
467 */
468BOOL ReadData(BYTE *pbyReadBuffer, size_t dwReadCount, DWORD dwSleepAfterAction, DWORD dwTimeoutCount)
469{
470 ssize_t sBytesReadn = -1;
471 ssize_t readCount = 0;
472 int result;
473 fd_set fds, temps;
474 struct timeval timeout;
475 // int readCount = 0;
476 // int count = 0; // 超时计数
477
478 LogInfo("ReadData reacount %d, timeout %d s\n", dwReadCount, dwTimeoutCount);
479 if (m_fd < 0)
480 {
481 LogInfo("m_fd < 0");
482 return -1;
483 }
484
485 FD_ZERO(&fds);
486 FD_SET(m_fd, &fds);
487
488 if (dwTimeoutCount < 10)
489 {
490 dwTimeoutCount = 10;
491 }
492
493 while (1)
494 {
495 temps = fds;
496 timeout.tv_sec = dwTimeoutCount;
497 timeout.tv_usec = 0;
498
499 result = select(m_fd + 1, &temps, NULL, NULL, &timeout);
500 LogInfo("select result = %d ", result);
501 if (-1 == result)
502 {
503 LogInfo("select() error\n");
504 perror("ReadData:: select() error\n");
505 break;
506 }
507 else if (0 == result)
508 {
509 puts("ReadData:: timeout\n");
510 break;
511 }
512 else
513 {
514 // 判断m_fd是否可读,若可读,读取数据
515 if (FD_ISSET(m_fd, &temps))
516 {
517 sBytesReadn = read(m_fd, pbyReadBuffer + readCount, dwReadCount - readCount);
518 LogInfo("pbyReadBuffer= (%s) sBytesReadn = %ld ", pbyReadBuffer, sBytesReadn);
519 if (sBytesReadn > 0)
520 {
521 readCount += sBytesReadn;
522 if (readCount >= dwReadCount)
523 {
524 return TRUE; // complete success
525 }
526 }
527 else
528 {
529 if (sBytesReadn < 0 && errno != EINTR)
530 {
531 printf("ReadData::read error, sBytesReadn = %ld, %s\r\n", sBytesReadn, strerror(errno));
532 }
533 return FALSE;
534 }
535 }
536 }
537 }
538 return FALSE;
539}
540
541/**
542 * @brief 接收数据缓冲
543 * @param dwReadCount 入参,读取数据长度
544 * @param dwSleepAfterAction 入参,
545 * @param dwTimeoutCount 入参,超时时间,单位秒
546 * @return 成功返回读取的数据指针,失败返回NULL
547 * @retval
548 * @note
549 * @warning
550 */
551BYTE *ReadDataExtraFuncB(DWORD dwReadCount, DWORD dwSleepAfterAction, DWORD dwTimeoutCount)
552{
553 ssize_t sBytesReadn = -1;
554 ssize_t readCount = 0;
555 int result;
556 fd_set fds, temps;
557 struct timeval timeout;
558
559 LogInfo("readcount %d, timeout %d s", dwReadCount, dwTimeoutCount);
560
561 memset(rspBufex, 0, DEV_RSP_COUNT);
562
563 if (m_fd < 0)
564 {
565 LogInfo("m_fd < 0");
566 return rspBufex;
567 }
568
569 FD_ZERO(&fds);
570 FD_SET(m_fd, &fds);
571
572 if (dwTimeoutCount < 10)
573 {
574 dwTimeoutCount = 10;
575 }
576
577 while (1)
578 {
579 temps = fds;
580 timeout.tv_sec = dwTimeoutCount;
581 timeout.tv_usec = 0;
582
583 result = select(m_fd + 1, &fds, NULL, NULL, &timeout);
584 LogInfo("select result = %d ", result);
585 if (-1 == result)
586 {
587 LogInfo("select() error\n");
588 perror("ReadDataExtraFuncB:: select() error\n");
589 break;
590 }
591 else if (0 == result)
592 {
593 puts("ReadDataExtraFuncB:: timeout\n");
594 break;
595 }
596 else
597 {
598 // 判断m_fd是否可读,若可读,读取数据
599 if (FD_ISSET(m_fd, &temps))
600 {
601 sBytesReadn = read(m_fd, rspBufex + readCount, DEV_RSP_COUNT - readCount);
602 LogInfo("pbyReadBuffer= (%s) sBytesReadn = %ld ", rspBufex, sBytesReadn);
603 if (sBytesReadn > 0)
604 {
605 readCount += sBytesReadn;
606 printf("ReadDataExtraFuncB:: readCount = %ld, dwReadCount = %d \r\n", readCount, dwReadCount);
607 if (readCount >= dwReadCount)
608 {
609 break; // complete success
610 }
611 }
612 else
613 {
614 if (sBytesReadn < 0 && errno != EINTR)
615 {
616 printf("ReadData::read error, sBytesReadn = %ld, %s\r\n", sBytesReadn, strerror(errno));
617 }
618 break;
619 }
620 }
621 }
622 }
623 LogInfo("rspBufex = (%s)", rspBufex);
624
625 return rspBufex;
626}