[RAMEN9610-20413][9610] wlbt: SCSC Driver version 10.6.1.0
[GitHub/MotorolaMobilityLLC/kernel-slsi.git] / drivers / net / wireless / scsc / mib_text_convert.c
1 /******************************************************************************
2 *
3 * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd and its Licensors.
4 * All rights reserved.
5 *
6 *****************************************************************************/
7
8 #include "debug.h"
9 #include "mib_text_convert.h"
10
11 #define CSR_TOUPPER(character) (((character) >= 'a') && ((character) <= 'z') ? ((character) - 0x20) : (character))
12
13 static inline bool CsrIsSpace(u8 c)
14 {
15 switch (c) {
16 case '\t':
17 case '\n':
18 case '\f':
19 case '\r':
20 case ' ':
21 return true;
22 default:
23 return false;
24 }
25 }
26
27 static inline char *CsrStrDup(const char *string)
28 {
29 if (string != NULL) {
30 u32 len = strlen(string) + 1;
31
32 return memcpy(kmalloc(len, GFP_KERNEL), string, len);
33 }
34 return NULL;
35 }
36
37 static int CsrStrNICmp(const char *string1,
38 const char *string2,
39 size_t count)
40 {
41 u32 index;
42 int returnValue = 0;
43
44 for (index = 0; index < count; index++) {
45 if (CSR_TOUPPER(string1[index]) != CSR_TOUPPER(string2[index])) {
46 if (CSR_TOUPPER(string1[index]) > CSR_TOUPPER(string2[index]))
47 returnValue = 1;
48 else
49 returnValue = -1;
50 break;
51 }
52 if (string1[index] == '\0')
53 break;
54 }
55 return returnValue;
56 }
57
58 static bool CsrHexStrToUint8(const char *string, u8 *returnValue)
59 {
60 u16 currentIndex = 0;
61
62 *returnValue = 0;
63 if ((string[currentIndex] == '0') && (CSR_TOUPPER(string[currentIndex + 1]) == 'X'))
64 string += 2;
65 if (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) {
66 while (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) {
67 *returnValue = (u8)(*returnValue * 16 + (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) ? string[currentIndex] - '0' : CSR_TOUPPER(string[currentIndex]) - 'A' + 10));
68 currentIndex++;
69 if (currentIndex >= 2)
70 break;
71 }
72 return true;
73 }
74 return false;
75 }
76
77 static bool CsrHexStrToUint16(const char *string, u16 *returnValue)
78 {
79 u16 currentIndex = 0;
80
81 *returnValue = 0;
82 if ((string[currentIndex] == '0') && (CSR_TOUPPER(string[currentIndex + 1]) == 'X'))
83 string += 2;
84 if (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) {
85 while (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) {
86 *returnValue = (u16)(*returnValue * 16 + (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) ? string[currentIndex] - '0' : CSR_TOUPPER(string[currentIndex]) - 'A' + 10));
87 currentIndex++;
88 if (currentIndex >= 4)
89 break;
90 }
91 return true;
92 }
93 return false;
94 }
95
96 static bool CsrHexStrToUint32(const char *string, u32 *returnValue)
97 {
98 u16 currentIndex = 0;
99
100 *returnValue = 0;
101 if ((string[currentIndex] == '0') && (CSR_TOUPPER(string[currentIndex + 1]) == 'X'))
102 string += 2;
103 if (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) {
104 while (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) || ((CSR_TOUPPER(string[currentIndex]) >= 'A') && (CSR_TOUPPER(string[currentIndex]) <= 'F'))) {
105 *returnValue = *returnValue * 16 + (((string[currentIndex] >= '0') && (string[currentIndex] <= '9')) ? string[currentIndex] - '0' : CSR_TOUPPER(string[currentIndex]) - 'A' + 10);
106 currentIndex++;
107 if (currentIndex >= 8)
108 break;
109 }
110 return true;
111 }
112 return false;
113 }
114
115 static bool CsrWifiMibConvertStrToUint16(const char *str, u16 *returnValue)
116 {
117 u16 currentIndex = 0;
118
119 if (str[1] == 'x')
120 return CsrHexStrToUint16(str, returnValue);
121
122 *returnValue = 0;
123 if ((str[currentIndex] >= '0') && (str[currentIndex] <= '9')) {
124 while (str[currentIndex] >= '0' && str[currentIndex] <= '9') {
125 *returnValue *= 10;
126 *returnValue += (u8)str[currentIndex++] - '0';
127 }
128 return true;
129 }
130 return false;
131 }
132
133 static bool CsrWifiMibConvertStrToUint32(const char *str, u32 *returnValue)
134 {
135 u16 currentIndex = 0;
136
137 if (str[1] == 'x')
138 return CsrHexStrToUint32(str, returnValue);
139
140 *returnValue = 0;
141 if ((str[currentIndex] >= '0') && (str[currentIndex] <= '9')) {
142 while (str[currentIndex] >= '0' && str[currentIndex] <= '9') {
143 *returnValue *= 10;
144 *returnValue += (u8)str[currentIndex++] - '0';
145 }
146 return true;
147 }
148 return false;
149 }
150
151 static bool CsrWifiMibConvertTextParseLine(const char *linestr, struct slsi_mib_data *mibDataSet, struct slsi_mib_data *mibDataGet)
152 {
153 struct slsi_mib_entry entry;
154 bool result = true;
155 size_t equals = 0;
156 size_t dot1 = 0;
157 size_t dot2 = 0;
158 size_t trimmedIndex = 0;
159 char *trimmed = kmalloc(strlen(linestr) + 1, GFP_KERNEL);
160 const char *current_char = linestr;
161 bool processingStr = false;
162
163 memset(&entry, 0x00, sizeof(entry));
164 while (current_char[0] != '\0') {
165 if (current_char[0] == '"')
166 processingStr = !processingStr;
167 if (!processingStr) {
168 if (current_char[0] == '#')
169 break;
170 if (CsrIsSpace((u8)current_char[0])) {
171 current_char++;
172 continue;
173 }
174 if (!equals && (current_char[0] == '.')) {
175 if (!dot1) {
176 dot1 = trimmedIndex;
177 } else if (!dot2) {
178 dot2 = trimmedIndex;
179 } else {
180 SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') only 2 indexes supported", trimmed);
181 result = false;
182 }
183 }
184 if (!equals && (current_char[0] == '='))
185 equals = trimmedIndex;
186 }
187 trimmed[trimmedIndex++] = current_char[0];
188
189 current_char++;
190 }
191 trimmed[trimmedIndex] = '\0';
192
193 if (strlen(trimmed) == 0) {
194 kfree(trimmed);
195 return result;
196 }
197
198 if (result) {
199 char sep = trimmed[dot1 ? dot1 : equals];
200
201 if (dot1 || equals)
202 trimmed[dot1 ? dot1 : equals] = '\0';
203 trimmed[dot1 ? dot1 : equals] = sep;
204
205 if (!CsrWifiMibConvertStrToUint16(trimmed, &entry.psid)) {
206 SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert <psid> failed", trimmed);
207 result = false;
208 }
209 if (dot1 && !CsrWifiMibConvertStrToUint16(&trimmed[dot1 + 1], &entry.index[0])) {
210 SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert <index 1> failed", trimmed);
211 result = false;
212 }
213 if (dot2 && !CsrWifiMibConvertStrToUint16(&trimmed[dot2 + 1], &entry.index[1])) {
214 SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert <index 2> failed", trimmed);
215 result = false;
216 }
217
218 if (result && !equals && mibDataGet) {
219 entry.value.type = SLSI_MIB_TYPE_NONE;
220 (void)slsi_mib_encode(mibDataGet, &entry);
221 }
222
223 if (result && equals && mibDataSet) {
224 char *data = &trimmed[equals + 1];
225 /*SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') psid:%d, index1:%d, index2:%d, data '%s'", trimmed, entry.psid, entry.index[0], entry.index[1], data); */
226 if (CsrStrNICmp(data, "true", 4) == 0) {
227 entry.value.type = SLSI_MIB_TYPE_BOOL;
228 entry.value.u.boolValue = 1;
229 } else if (CsrStrNICmp(data, "false", 5) == 0) {
230 entry.value.type = SLSI_MIB_TYPE_BOOL;
231 entry.value.u.boolValue = 0;
232 } else if (data[0] == '"') {
233 /* Null Terminated String */
234 entry.value.type = SLSI_MIB_TYPE_OCTET;
235 entry.value.u.octetValue.dataLength = (u32)strlen(&data[1]);
236 entry.value.u.octetValue.data = (u8 *)CsrStrDup(&data[1]);
237 entry.value.u.octetValue.data[entry.value.u.octetValue.dataLength - 1] = '\0';
238 } else if (data[0] == '[') {
239 /* Octet String */
240 size_t i;
241 u16 octetLen = ((u16)strlen(&data[1]) - 1) / 2;
242
243 entry.value.type = SLSI_MIB_TYPE_OCTET;
244 entry.value.u.octetValue.dataLength = octetLen;
245 entry.value.u.octetValue.data = kmalloc(entry.value.u.octetValue.dataLength + 1, GFP_KERNEL);
246 for (i = 0; i < octetLen; i++)
247 if (!CsrHexStrToUint8(&data[1 + (i * 2)], &entry.value.u.octetValue.data[i])) {
248 SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert Hex Bytes <data> failed", trimmed);
249 result = false;
250 break;
251 }
252 entry.value.u.octetValue.data[octetLen] = '\0'; /* Make sure the Octet Stream is NULL terminated in case it is interpreted as a String */
253 } else if (data[0] == '-') {
254 /* Negative Integer Value */
255 entry.value.type = SLSI_MIB_TYPE_INT;
256 if (!CsrWifiMibConvertStrToUint32(&data[1], &entry.value.u.uintValue)) {
257 SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert Integer <data> failed", trimmed);
258 result = false;
259 } else {
260 entry.value.u.intValue = (s32)(0 - (u32)entry.value.u.uintValue);
261 }
262 } else if (!CsrWifiMibConvertStrToUint32(data, &entry.value.u.uintValue)) {
263 SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine('%s') Convert Unsigned Integer <data> failed", trimmed);
264 result = false;
265 } else {
266 entry.value.type = SLSI_MIB_TYPE_UINT;
267 }
268 if (result)
269 (void)slsi_mib_encode(mibDataSet, &entry);
270 if (entry.value.type == SLSI_MIB_TYPE_OCTET)
271 kfree(entry.value.u.octetValue.data);
272 }
273 }
274
275 kfree(trimmed);
276
277 return result;
278 }
279
280 static bool CsrWifiMibConvertTextAppend(const char *mibText, struct slsi_mib_data *mibDataSet, struct slsi_mib_data *mibDataGet)
281 {
282 bool result = true;
283 const char *lineStart = mibText;
284 const char *lineEnd = mibText;
285
286 if (mibText == NULL)
287 return false;
288
289 while (lineEnd[0] != '\0') {
290 if ((lineEnd[0] == '\n') || (lineEnd[0] == '\r') || (lineEnd[1] == '\0')) {
291 size_t strSize = (size_t)(lineEnd - lineStart);
292
293 if ((lineEnd[1] == '\0'))
294 strSize++;
295 if (strSize > 2) {
296 char *line = kmalloc(strSize + 1, GFP_KERNEL);
297 (void)strncpy(line, lineStart, strSize);
298 line[strSize] = '\0';
299 if (!CsrWifiMibConvertTextParseLine(line, mibDataSet, mibDataGet)) {
300 SLSI_ERR_NODEV("CsrWifiMibConvertTextParseLine() Failed for line '%s'", line);
301 result = false;
302 }
303 kfree(line);
304 }
305 lineEnd++;
306 lineStart = lineEnd;
307 continue;
308 }
309 lineEnd++;
310 }
311
312 return result;
313 }
314
315 bool CsrWifiMibConvertText(const char *mibText, struct slsi_mib_data *mibDataSet, struct slsi_mib_data *mibDataGet)
316 {
317 if (mibDataSet) {
318 mibDataSet->data = NULL;
319 mibDataSet->dataLength = 0;
320 }
321 if (mibDataGet) {
322 mibDataGet->data = NULL;
323 mibDataGet->dataLength = 0;
324 }
325
326 return CsrWifiMibConvertTextAppend(mibText, mibDataSet, mibDataGet);
327 }