1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "vendor_channel.h"
17
18 #include <stddef.h>
19 #include <sys/types.h>
20
21 #include "errno.h"
22 #include "securec.h"
23 #include "string.h"
24 #include "telephony_log_c.h"
25 #include "unistd.h"
26 #include "vendor_util.h"
27
28 static char g_buffer[MAX_RESPONSE_LEN + 1];
29 static char *g_bufferCur = g_buffer;
30
FindEndOfLine(char * cur)31 static char *FindEndOfLine(char *cur)
32 {
33 char *endLine = cur;
34 int32_t count = 2;
35 if (endLine == NULL) {
36 return NULL;
37 }
38 if (endLine[0] == '>' && endLine[1] == ' ' && endLine[count] == '\0') {
39 return endLine + count;
40 }
41 while (*endLine != '\0' && *endLine != '\r' && *endLine != '\n') {
42 endLine++;
43 }
44 return (*endLine != '\0') ? endLine : NULL;
45 }
46
SkipUnUseChar(void)47 static void SkipUnUseChar(void)
48 {
49 while (*g_bufferCur == '\r' || *g_bufferCur == '\n') {
50 g_bufferCur++;
51 }
52 }
53
ClearCurBuffer(char ** processed)54 static void ClearCurBuffer(char **processed)
55 {
56 if (processed == NULL) {
57 return;
58 }
59 g_buffer[0] = '\0';
60 g_bufferCur = g_buffer;
61 *processed = g_bufferCur;
62 }
63
ProcessLastResponse(char ** processed)64 static char *ProcessLastResponse(char **processed)
65 {
66 if (processed == NULL) {
67 return NULL;
68 }
69 char *endLine = NULL;
70 if (*g_bufferCur == '\0') {
71 ClearCurBuffer(processed);
72 } else {
73 SkipUnUseChar();
74 endLine = FindEndOfLine(g_bufferCur);
75 if (endLine == NULL) {
76 TELEPHONY_LOGE("g_bufferCur endLine is null\n");
77 size_t len;
78 len = strlen(g_bufferCur);
79 (void)memmove_s(g_buffer, MAX_RESPONSE_LEN + 1, g_bufferCur, len + 1);
80 *processed = g_buffer + len;
81 g_bufferCur = g_buffer;
82 }
83 }
84 return endLine;
85 }
86
ReadResponse(int32_t atFd)87 const char *ReadResponse(int32_t atFd)
88 {
89 ssize_t size;
90 char *processed = NULL;
91 char *endEol = NULL;
92 char *ret = NULL;
93 // process last response data
94 endEol = ProcessLastResponse(&processed);
95 while (endEol == NULL) {
96 if (MAX_RESPONSE_LEN == (processed - &g_buffer[0])) {
97 ClearCurBuffer(&processed);
98 }
99 do {
100 size = read(atFd, processed, (MAX_RESPONSE_LEN - (processed - &g_buffer[0])));
101 } while (size < 0 && errno == EINTR);
102 if (size > 0) {
103 processed[size] = '\0';
104 SkipUnUseChar();
105 endEol = FindEndOfLine(g_bufferCur);
106 processed += size;
107 } else if (size == 0) {
108 TELEPHONY_LOGE("atchannel: EOF reached");
109 return NULL;
110 } else {
111 TELEPHONY_LOGE("read error %{public}s", strerror(errno));
112 return NULL;
113 }
114 }
115 *endEol = '\0';
116 ret = g_bufferCur;
117 g_bufferCur = endEol + 1;
118 return ret;
119 }
120
WriteATCommand(const char * s,int32_t isPdu,int32_t atFd)121 int32_t WriteATCommand(const char *s, int32_t isPdu, int32_t atFd)
122 {
123 if (s == NULL) {
124 return AT_ERR_GENERIC;
125 }
126 ssize_t ret;
127 size_t i = 0;
128 size_t len = strlen(s);
129 if (atFd < 0) {
130 return AT_ERR_CHANNEL_CLOSED;
131 }
132
133 while (i < len) {
134 do {
135 ret = write(atFd, s + i, len - i);
136 } while (ret < 0 && errno == EINTR);
137
138 if (ret < 0) {
139 return AT_ERR_GENERIC;
140 }
141 i += ret;
142 }
143 if (isPdu != 0) {
144 do {
145 ret = write(atFd, "\x1A", 1);
146 } while ((ret < 0 && errno == EINTR) || (ret == 0));
147 } else {
148 do {
149 ret = write(atFd, "\r", 1);
150 } while ((ret < 0 && errno == EINTR) || (ret == 0));
151 }
152 if (ret < 0) {
153 return AT_ERR_GENERIC;
154 }
155 return VENDOR_SUCCESS;
156 }
157