1 /*
2  * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "qdf_mem.h"
21 #include "qdf_module.h"
22 #include "qdf_status.h"
23 #include "qdf_str.h"
24 #include "qdf_trace.h"
25 #include "qdf_types.h"
26 
qdf_opmode_str(const enum QDF_OPMODE opmode)27 const char *qdf_opmode_str(const enum QDF_OPMODE opmode)
28 {
29 	switch (opmode) {
30 	case QDF_STA_MODE:
31 		return "STA";
32 	case QDF_SAP_MODE:
33 		return "SAP";
34 	case QDF_P2P_CLIENT_MODE:
35 		return "P2P Client";
36 	case QDF_P2P_GO_MODE:
37 		return "P2P GO";
38 	case QDF_FTM_MODE:
39 		return "FTM";
40 	case QDF_IBSS_MODE:
41 		return "IBSS";
42 	case QDF_MONITOR_MODE:
43 		return "Monitor";
44 	case QDF_P2P_DEVICE_MODE:
45 		return "P2P Device";
46 	case QDF_OCB_MODE:
47 		return "OCB";
48 	case QDF_EPPING_MODE:
49 		return "EPPing";
50 	case QDF_QVIT_MODE:
51 		return "QVIT";
52 	case QDF_NDI_MODE:
53 		return "NDI";
54 	case QDF_WDS_MODE:
55 		return "WDS";
56 	case QDF_BTAMP_MODE:
57 		return "BTAMP";
58 	case QDF_AHDEMO_MODE:
59 		return "AHDEMO";
60 	case QDF_TDLS_MODE:
61 		return "TDLS";
62 	case QDF_NAN_DISC_MODE:
63 		return "NAN";
64 	default:
65 		return "Invalid operating mode";
66 	}
67 }
68 
qdf_consume_char(const char ** str,char c)69 static QDF_STATUS qdf_consume_char(const char **str, char c)
70 {
71 	if ((*str)[0] != c)
72 		return QDF_STATUS_E_FAILURE;
73 
74 	(*str)++;
75 
76 	return QDF_STATUS_SUCCESS;
77 }
78 
qdf_consume_dec(const char ** str,uint8_t * out_digit)79 static QDF_STATUS qdf_consume_dec(const char **str, uint8_t *out_digit)
80 {
81 	uint8_t c = (*str)[0];
82 
83 	if (c >= '0' && c <= '9')
84 		*out_digit = c - '0';
85 	else
86 		return QDF_STATUS_E_FAILURE;
87 
88 	(*str)++;
89 
90 	return QDF_STATUS_SUCCESS;
91 }
92 
qdf_consume_hex(const char ** str,uint8_t * out_nibble)93 static QDF_STATUS qdf_consume_hex(const char **str, uint8_t *out_nibble)
94 {
95 	uint8_t c = (*str)[0];
96 
97 	if (c >= '0' && c <= '9')
98 		*out_nibble = c - '0';
99 	else if (c >= 'a' && c <= 'f')
100 		*out_nibble = c - 'a' + 10;
101 	else if (c >= 'A' && c <= 'F')
102 		*out_nibble = c - 'A' + 10;
103 	else
104 		return QDF_STATUS_E_FAILURE;
105 
106 	(*str)++;
107 
108 	return QDF_STATUS_SUCCESS;
109 }
110 
qdf_consume_octet_dec(const char ** str,uint8_t * out_octet)111 static QDF_STATUS qdf_consume_octet_dec(const char **str, uint8_t *out_octet)
112 {
113 	uint8_t len = 0;
114 	uint16_t octet = 0;
115 	int i;
116 
117 	/* consume up to 3 decimal digits */
118 	for (i = 0; i < 3; i++) {
119 		uint8_t digit;
120 
121 		if (QDF_IS_STATUS_ERROR(qdf_consume_dec(str, &digit)))
122 			break;
123 
124 		len++;
125 		octet = octet * 10 + digit;
126 	}
127 
128 	/* require at least 1 digit */
129 	if (!len)
130 		return QDF_STATUS_E_FAILURE;
131 
132 	if (octet > 255) {
133 		(*str) -= len;
134 		return QDF_STATUS_E_FAILURE;
135 	}
136 
137 	*out_octet = octet;
138 
139 	return QDF_STATUS_SUCCESS;
140 }
141 
qdf_consume_hex_pair(const char ** str,uint8_t * out_byte)142 static QDF_STATUS qdf_consume_hex_pair(const char **str, uint8_t *out_byte)
143 {
144 	QDF_STATUS status;
145 	uint8_t hi, low;
146 
147 	status = qdf_consume_hex(str, &hi);
148 	if (QDF_IS_STATUS_ERROR(status))
149 		return status;
150 
151 	status = qdf_consume_hex(str, &low);
152 	if (QDF_IS_STATUS_ERROR(status)) {
153 		(*str)--;
154 		return status;
155 	}
156 
157 	*out_byte = hi << 4 | low;
158 
159 	return QDF_STATUS_SUCCESS;
160 }
161 
qdf_consume_hextet(const char ** str,uint16_t * out_hextet)162 static QDF_STATUS qdf_consume_hextet(const char **str, uint16_t *out_hextet)
163 {
164 	uint8_t len = 0;
165 	uint16_t hextet = 0;
166 	int i;
167 
168 	/* consume up to 4 hex digits */
169 	for (i = 0; i < 4; i++) {
170 		uint8_t digit;
171 
172 		if (QDF_IS_STATUS_ERROR(qdf_consume_hex(str, &digit)))
173 			break;
174 
175 		len++;
176 		hextet = (hextet << 4) + digit;
177 	}
178 
179 	/* require at least 1 digit */
180 	if (!len)
181 		return QDF_STATUS_E_FAILURE;
182 
183 	/* no need to check for overflow */
184 
185 	*out_hextet = hextet;
186 
187 	return QDF_STATUS_SUCCESS;
188 }
189 
qdf_consume_radix(const char ** str,uint8_t * out_radix)190 static QDF_STATUS qdf_consume_radix(const char **str, uint8_t *out_radix)
191 {
192 	if ((*str)[0] == '0') {
193 		switch ((*str)[1]) {
194 		case 'b':
195 			*out_radix = 2;
196 			*str += 2;
197 			break;
198 		case 'o':
199 			*out_radix = 8;
200 			*str += 2;
201 			break;
202 		case 'x':
203 			*out_radix = 16;
204 			*str += 2;
205 			break;
206 		default:
207 			*out_radix = 10;
208 			break;
209 		}
210 
211 		return QDF_STATUS_SUCCESS;
212 	}
213 
214 	if (*str[0] >= '0' && *str[0] <= '9') {
215 		*out_radix = 10;
216 		return QDF_STATUS_SUCCESS;
217 	}
218 
219 	return QDF_STATUS_E_FAILURE;
220 }
221 
222 static QDF_STATUS
__qdf_int_parse_lazy(const char ** int_str,uint64_t * out_int,bool * out_negate)223 __qdf_int_parse_lazy(const char **int_str, uint64_t *out_int, bool *out_negate)
224 {
225 	QDF_STATUS status;
226 	bool negate = false;
227 	uint8_t radix;
228 	uint8_t digit;
229 	uint64_t value = 0;
230 	uint64_t next_value;
231 	const char *str = *int_str;
232 
233 	str = qdf_str_left_trim(str);
234 
235 	status = qdf_consume_char(&str, '-');
236 	if (QDF_IS_STATUS_SUCCESS(status))
237 		negate = true;
238 	else
239 		qdf_consume_char(&str, '+');
240 
241 	status = qdf_consume_radix(&str, &radix);
242 	if (QDF_IS_STATUS_ERROR(status))
243 		return status;
244 
245 	while (QDF_IS_STATUS_SUCCESS(qdf_consume_hex(&str, &digit))) {
246 		if (digit >= radix)
247 			return QDF_STATUS_E_FAILURE;
248 
249 		next_value = value * radix + digit;
250 		if (next_value < value)
251 			return QDF_STATUS_E_RANGE;
252 
253 		value = next_value;
254 	}
255 
256 	*int_str = str;
257 	*out_negate = negate;
258 	*out_int = value;
259 
260 	return QDF_STATUS_SUCCESS;
261 }
262 
263 static QDF_STATUS
qdf_int_parse(const char * int_str,uint64_t * out_int,bool * out_negate)264 qdf_int_parse(const char *int_str, uint64_t *out_int, bool *out_negate)
265 {
266 	QDF_STATUS status;
267 	bool negate;
268 	uint64_t value;
269 
270 	QDF_BUG(int_str);
271 	if (!int_str)
272 		return QDF_STATUS_E_INVAL;
273 
274 	QDF_BUG(out_int);
275 	if (!out_int)
276 		return QDF_STATUS_E_INVAL;
277 
278 	status = __qdf_int_parse_lazy(&int_str, &value, &negate);
279 	if (QDF_IS_STATUS_ERROR(status))
280 		return status;
281 
282 	int_str = qdf_str_left_trim(int_str);
283 	if (int_str[0] != '\0')
284 		return QDF_STATUS_E_FAILURE;
285 
286 	*out_negate = negate;
287 	*out_int = value;
288 
289 	return QDF_STATUS_SUCCESS;
290 }
291 
qdf_int32_parse(const char * int_str,int32_t * out_int)292 QDF_STATUS qdf_int32_parse(const char *int_str, int32_t *out_int)
293 {
294 	QDF_STATUS status;
295 	int64_t value;
296 
297 	status = qdf_int64_parse(int_str, &value);
298 	if (QDF_IS_STATUS_ERROR(status))
299 		return status;
300 
301 	if ((int32_t)value != value)
302 		return QDF_STATUS_E_RANGE;
303 
304 	*out_int = value;
305 
306 	return QDF_STATUS_SUCCESS;
307 }
308 qdf_export_symbol(qdf_int32_parse);
309 
qdf_uint8_parse(const char * int_str,uint8_t * out_int)310 QDF_STATUS qdf_uint8_parse(const char *int_str, uint8_t *out_int)
311 {
312 	QDF_STATUS status;
313 	uint64_t value;
314 
315 	status = qdf_uint64_parse(int_str, &value);
316 	if (QDF_IS_STATUS_ERROR(status))
317 		return status;
318 
319 	if ((uint8_t)value != value)
320 		return QDF_STATUS_E_RANGE;
321 
322 	*out_int = value;
323 
324 	return QDF_STATUS_SUCCESS;
325 }
326 
327 qdf_export_symbol(qdf_uint8_parse);
328 
qdf_uint16_parse(const char * int_str,uint16_t * out_int)329 QDF_STATUS qdf_uint16_parse(const char *int_str, uint16_t *out_int)
330 {
331 	QDF_STATUS status;
332 	uint64_t value;
333 
334 	status = qdf_uint64_parse(int_str, &value);
335 	if (QDF_IS_STATUS_ERROR(status))
336 		return status;
337 
338 	if ((uint16_t)value != value)
339 		return QDF_STATUS_E_RANGE;
340 
341 	*out_int = value;
342 
343 	return QDF_STATUS_SUCCESS;
344 }
345 
346 qdf_export_symbol(qdf_uint16_parse);
347 
qdf_uint32_parse(const char * int_str,uint32_t * out_int)348 QDF_STATUS qdf_uint32_parse(const char *int_str, uint32_t *out_int)
349 {
350 	QDF_STATUS status;
351 	uint64_t value;
352 
353 	status = qdf_uint64_parse(int_str, &value);
354 	if (QDF_IS_STATUS_ERROR(status))
355 		return status;
356 
357 	if ((uint32_t)value != value)
358 		return QDF_STATUS_E_RANGE;
359 
360 	*out_int = value;
361 
362 	return QDF_STATUS_SUCCESS;
363 }
364 qdf_export_symbol(qdf_uint32_parse);
365 
qdf_int64_parse(const char * int_str,int64_t * out_int)366 QDF_STATUS qdf_int64_parse(const char *int_str, int64_t *out_int)
367 {
368 	QDF_STATUS status;
369 	bool negate = false;
370 	uint64_t value = 0;
371 	int64_t signed_value;
372 
373 	status = qdf_int_parse(int_str, &value, &negate);
374 	if (QDF_IS_STATUS_ERROR(status))
375 		return status;
376 
377 	if (negate) {
378 		signed_value = -value;
379 		if (signed_value > 0)
380 			return QDF_STATUS_E_RANGE;
381 	} else {
382 		signed_value = value;
383 		if (signed_value < 0)
384 			return QDF_STATUS_E_RANGE;
385 	}
386 
387 	*out_int = signed_value;
388 
389 	return QDF_STATUS_SUCCESS;
390 }
391 qdf_export_symbol(qdf_int64_parse);
392 
qdf_uint64_parse(const char * int_str,uint64_t * out_int)393 QDF_STATUS qdf_uint64_parse(const char *int_str, uint64_t *out_int)
394 {
395 	QDF_STATUS status;
396 	bool negate = false;
397 	uint64_t value = 0;
398 
399 	status = qdf_int_parse(int_str, &value, &negate);
400 	if (QDF_IS_STATUS_ERROR(status))
401 		return status;
402 
403 	if (negate)
404 		return QDF_STATUS_E_RANGE;
405 
406 	*out_int = value;
407 
408 	return QDF_STATUS_SUCCESS;
409 }
410 qdf_export_symbol(qdf_uint64_parse);
411 
qdf_bool_parse(const char * bool_str,bool * out_bool)412 QDF_STATUS qdf_bool_parse(const char *bool_str, bool *out_bool)
413 {
414 	bool value;
415 
416 	QDF_BUG(bool_str);
417 	if (!bool_str)
418 		return QDF_STATUS_E_INVAL;
419 
420 	QDF_BUG(out_bool);
421 	if (!out_bool)
422 		return QDF_STATUS_E_INVAL;
423 
424 	bool_str = qdf_str_left_trim(bool_str);
425 
426 	switch (bool_str[0]) {
427 	case '1':
428 	case 'y':
429 	case 'Y':
430 		value = true;
431 		break;
432 	case '0':
433 	case 'n':
434 	case 'N':
435 		value = false;
436 		break;
437 	default:
438 		return QDF_STATUS_E_FAILURE;
439 	}
440 
441 	bool_str++;
442 	bool_str = qdf_str_left_trim(bool_str);
443 	if (bool_str[0] != '\0')
444 		return QDF_STATUS_E_FAILURE;
445 
446 	*out_bool = value;
447 
448 	return QDF_STATUS_SUCCESS;
449 }
450 qdf_export_symbol(qdf_bool_parse);
451 
qdf_mac_parse(const char * mac_str,struct qdf_mac_addr * out_addr)452 QDF_STATUS qdf_mac_parse(const char *mac_str, struct qdf_mac_addr *out_addr)
453 {
454 	QDF_STATUS status;
455 	struct qdf_mac_addr addr;
456 	bool colons;
457 	int i;
458 
459 	QDF_BUG(mac_str);
460 	if (!mac_str)
461 		return QDF_STATUS_E_INVAL;
462 
463 	QDF_BUG(out_addr);
464 	if (!out_addr)
465 		return QDF_STATUS_E_INVAL;
466 
467 	mac_str = qdf_str_left_trim(mac_str);
468 
469 	/* parse leading hex pair */
470 	status = qdf_consume_hex_pair(&mac_str, &addr.bytes[0]);
471 	if (QDF_IS_STATUS_ERROR(status))
472 		return status;
473 
474 	/* dynamically detect colons */
475 	colons = mac_str[0] == ':';
476 
477 	for (i = 1; i < QDF_MAC_ADDR_SIZE; i++) {
478 		/* ensure colon separator if previously detected */
479 		if (colons) {
480 			status = qdf_consume_char(&mac_str, ':');
481 			if (QDF_IS_STATUS_ERROR(status))
482 				return status;
483 		}
484 
485 		/* parse next hex pair */
486 		status = qdf_consume_hex_pair(&mac_str, &addr.bytes[i]);
487 		if (QDF_IS_STATUS_ERROR(status))
488 			return status;
489 	}
490 
491 	mac_str = qdf_str_left_trim(mac_str);
492 	if (mac_str[0] != '\0')
493 		return QDF_STATUS_E_FAILURE;
494 
495 	*out_addr = addr;
496 
497 	return QDF_STATUS_SUCCESS;
498 }
499 qdf_export_symbol(qdf_mac_parse);
500 
qdf_ipv4_parse(const char * ipv4_str,struct qdf_ipv4_addr * out_addr)501 QDF_STATUS qdf_ipv4_parse(const char *ipv4_str, struct qdf_ipv4_addr *out_addr)
502 {
503 	QDF_STATUS status;
504 	struct qdf_ipv4_addr addr;
505 	int i;
506 
507 	QDF_BUG(ipv4_str);
508 	if (!ipv4_str)
509 		return QDF_STATUS_E_INVAL;
510 
511 	QDF_BUG(out_addr);
512 	if (!out_addr)
513 		return QDF_STATUS_E_INVAL;
514 
515 	ipv4_str = qdf_str_left_trim(ipv4_str);
516 
517 	/* parse leading octet */
518 	status = qdf_consume_octet_dec(&ipv4_str, &addr.bytes[0]);
519 	if (QDF_IS_STATUS_ERROR(status))
520 		return status;
521 
522 	for (i = 1; i < QDF_IPV4_ADDR_SIZE; i++) {
523 		/* ensure dot separator */
524 		status = qdf_consume_char(&ipv4_str, '.');
525 		if (QDF_IS_STATUS_ERROR(status))
526 			return status;
527 
528 		/* parse next octet */
529 		status = qdf_consume_octet_dec(&ipv4_str, &addr.bytes[i]);
530 		if (QDF_IS_STATUS_ERROR(status))
531 			return status;
532 	}
533 
534 	ipv4_str = qdf_str_left_trim(ipv4_str);
535 	if (ipv4_str[0] != '\0')
536 		return QDF_STATUS_E_FAILURE;
537 
538 	*out_addr = addr;
539 
540 	return QDF_STATUS_SUCCESS;
541 }
542 qdf_export_symbol(qdf_ipv4_parse);
543 
qdf_ipv6_apply_zero_comp(struct qdf_ipv6_addr * addr,uint8_t hextets,uint8_t zero_comp_index)544 static inline void qdf_ipv6_apply_zero_comp(struct qdf_ipv6_addr *addr,
545 					    uint8_t hextets,
546 					    uint8_t zero_comp_index)
547 {
548 	/* Given the following hypothetical ipv6 address:
549 	 * |---------------------------------------|
550 	 * | 01 | ab | cd | ef |    |    |    |    |
551 	 * |---------------------------------------|
552 	 *           ^--- zero_comp_index (2)
553 	 * from -----^
554 	 * to ---------------------------^
555 	 * |    hextets (4)    |
556 	 *                     |   zero comp size  |
557 	 *           | to move |
558 	 *
559 	 * We need to apply the zero compression such that we get:
560 	 * |---------------------------------------|
561 	 * | 01 | ab | 00 | 00 | 00 | 00 | cd | ef |
562 	 * |---------------------------------------|
563 	 *           |     zero comp     |
564 	 *                               |  moved  |
565 	 */
566 
567 	size_t zero_comp_size = (QDF_IPV6_ADDR_HEXTET_COUNT - hextets) * 2;
568 	size_t bytes_to_move = (hextets - zero_comp_index) * 2;
569 	uint8_t *from = &addr->bytes[zero_comp_index * 2];
570 	uint8_t *to = from + zero_comp_size;
571 
572 	if (bytes_to_move)
573 		qdf_mem_move(to, from, bytes_to_move);
574 
575 	qdf_mem_zero(from, to - from);
576 }
577 
qdf_ipv6_parse(const char * ipv6_str,struct qdf_ipv6_addr * out_addr)578 QDF_STATUS qdf_ipv6_parse(const char *ipv6_str, struct qdf_ipv6_addr *out_addr)
579 {
580 	QDF_STATUS status;
581 	struct qdf_ipv6_addr addr;
582 	int8_t zero_comp = -1;
583 	uint8_t hextets_found = 0;
584 
585 	QDF_BUG(ipv6_str);
586 	if (!ipv6_str)
587 		return QDF_STATUS_E_INVAL;
588 
589 	QDF_BUG(out_addr);
590 	if (!out_addr)
591 		return QDF_STATUS_E_INVAL;
592 
593 	ipv6_str = qdf_str_left_trim(ipv6_str);
594 
595 	/* check for leading zero-compression ("::") */
596 	status = qdf_consume_char(&ipv6_str, ':');
597 	if (QDF_IS_STATUS_SUCCESS(status)) {
598 		status = qdf_consume_char(&ipv6_str, ':');
599 		if (QDF_IS_STATUS_SUCCESS(status))
600 			zero_comp = 0;
601 		else
602 			return QDF_STATUS_E_FAILURE;
603 	}
604 
605 	while (hextets_found < QDF_IPV6_ADDR_HEXTET_COUNT) {
606 		uint16_t hextet;
607 
608 		/* parse hextet */
609 		status = qdf_consume_hextet(&ipv6_str, &hextet);
610 		if (QDF_IS_STATUS_ERROR(status)) {
611 			/* we must end with hextet or zero compression */
612 			if (hextets_found != zero_comp)
613 				return QDF_STATUS_E_FAILURE;
614 
615 			break;
616 		}
617 
618 		addr.bytes[hextets_found * 2] = hextet >> 8;
619 		addr.bytes[hextets_found * 2 + 1] = hextet;
620 		hextets_found++;
621 
622 		/* parse ':' char */
623 		status = qdf_consume_char(&ipv6_str, ':');
624 		if (QDF_IS_STATUS_ERROR(status))
625 			break;
626 
627 		/* check for zero compression ("::") */
628 		status = qdf_consume_char(&ipv6_str, ':');
629 		if (QDF_IS_STATUS_SUCCESS(status)) {
630 			/* only one zero compression is allowed */
631 			if (zero_comp >= 0)
632 				return QDF_STATUS_E_FAILURE;
633 
634 			zero_comp = hextets_found;
635 		}
636 	}
637 
638 	ipv6_str = qdf_str_left_trim(ipv6_str);
639 	if (ipv6_str[0] != '\0')
640 		return QDF_STATUS_E_FAILURE;
641 
642 	/* we must have max hextets or a zero compression, but not both */
643 	if (hextets_found < QDF_IPV6_ADDR_HEXTET_COUNT) {
644 		if (zero_comp < 0)
645 			return QDF_STATUS_E_FAILURE;
646 
647 		qdf_ipv6_apply_zero_comp(&addr, hextets_found, zero_comp);
648 	} else if (zero_comp > -1) {
649 		return QDF_STATUS_E_FAILURE;
650 	}
651 
652 	*out_addr = addr;
653 
654 	return QDF_STATUS_SUCCESS;
655 }
656 qdf_export_symbol(qdf_ipv6_parse);
657 
qdf_int32_array_parse(const char * in_str,int32_t * out_array,qdf_size_t array_size,qdf_size_t * out_size)658 QDF_STATUS qdf_int32_array_parse(const char *in_str, int32_t *out_array,
659 				 qdf_size_t array_size, qdf_size_t *out_size)
660 {
661 	QDF_STATUS status;
662 	qdf_size_t size = 0;
663 	bool negate;
664 	uint64_t value;
665 	int64_t signed_value;
666 
667 	QDF_BUG(in_str);
668 	if (!in_str)
669 		return QDF_STATUS_E_INVAL;
670 
671 	QDF_BUG(out_array);
672 	if (!out_array)
673 		return QDF_STATUS_E_INVAL;
674 
675 	QDF_BUG(out_size);
676 	if (!out_size)
677 		return QDF_STATUS_E_INVAL;
678 
679 	while (size < array_size) {
680 		status = __qdf_int_parse_lazy(&in_str, &value, &negate);
681 		if (QDF_IS_STATUS_ERROR(status))
682 			return status;
683 
684 		if (negate) {
685 			signed_value = -value;
686 			if (signed_value > 0)
687 				return QDF_STATUS_E_RANGE;
688 		} else {
689 			signed_value = value;
690 			if (signed_value < 0)
691 				return QDF_STATUS_E_RANGE;
692 		}
693 
694 		in_str = qdf_str_left_trim(in_str);
695 
696 		switch (in_str[0]) {
697 		case ',':
698 			out_array[size++] = signed_value;
699 			in_str++;
700 			break;
701 		case '\0':
702 			out_array[size++] = signed_value;
703 			*out_size = size;
704 			return QDF_STATUS_SUCCESS;
705 		default:
706 			return QDF_STATUS_E_FAILURE;
707 		}
708 	}
709 
710 	return QDF_STATUS_E_FAILURE;
711 }
712 
713 qdf_export_symbol(qdf_int32_array_parse);
714 
qdf_uint32_array_parse(const char * in_str,uint32_t * out_array,qdf_size_t array_size,qdf_size_t * out_size)715 QDF_STATUS qdf_uint32_array_parse(const char *in_str, uint32_t *out_array,
716 				  qdf_size_t array_size, qdf_size_t *out_size)
717 {
718 	QDF_STATUS status;
719 	bool negate;
720 	qdf_size_t size = 0;
721 	uint64_t value;
722 
723 	QDF_BUG(in_str);
724 	if (!in_str)
725 		return QDF_STATUS_E_INVAL;
726 
727 	QDF_BUG(out_array);
728 	if (!out_array)
729 		return QDF_STATUS_E_INVAL;
730 
731 	QDF_BUG(out_size);
732 	if (!out_size)
733 		return QDF_STATUS_E_INVAL;
734 
735 	while (size < array_size) {
736 		status = __qdf_int_parse_lazy(&in_str, &value, &negate);
737 		if (QDF_IS_STATUS_ERROR(status))
738 			return status;
739 
740 		if ((uint32_t)value != value || negate)
741 			return QDF_STATUS_E_RANGE;
742 
743 		in_str = qdf_str_left_trim(in_str);
744 
745 		switch (in_str[0]) {
746 		case ',':
747 			out_array[size++] = value;
748 			in_str++;
749 			break;
750 		case '\0':
751 			out_array[size++] = value;
752 			*out_size = size;
753 			return QDF_STATUS_SUCCESS;
754 		default:
755 			return QDF_STATUS_E_FAILURE;
756 		}
757 	}
758 
759 	return QDF_STATUS_E_FAILURE;
760 }
761 
762 qdf_export_symbol(qdf_uint32_array_parse);
763 
qdf_uint16_array_parse(const char * in_str,uint16_t * out_array,qdf_size_t array_size,qdf_size_t * out_size)764 QDF_STATUS qdf_uint16_array_parse(const char *in_str, uint16_t *out_array,
765 				  qdf_size_t array_size, qdf_size_t *out_size)
766 {
767 	QDF_STATUS status;
768 	bool negate;
769 	qdf_size_t size = 0;
770 	uint64_t value;
771 
772 	QDF_BUG(in_str);
773 	if (!in_str)
774 		return QDF_STATUS_E_INVAL;
775 
776 	QDF_BUG(out_array);
777 	if (!out_array)
778 		return QDF_STATUS_E_INVAL;
779 
780 	QDF_BUG(out_size);
781 	if (!out_size)
782 		return QDF_STATUS_E_INVAL;
783 
784 	while (size < array_size) {
785 		status = __qdf_int_parse_lazy(&in_str, &value, &negate);
786 		if (QDF_IS_STATUS_ERROR(status))
787 			return status;
788 
789 		if ((uint16_t)value != value || negate)
790 			return QDF_STATUS_E_RANGE;
791 
792 		in_str = qdf_str_left_trim(in_str);
793 
794 		switch (in_str[0]) {
795 		case ',':
796 			out_array[size++] = value;
797 			in_str++;
798 			break;
799 		case '\0':
800 			out_array[size++] = value;
801 			*out_size = size;
802 			return QDF_STATUS_SUCCESS;
803 		default:
804 			return QDF_STATUS_E_FAILURE;
805 		}
806 	}
807 
808 	return QDF_STATUS_E_FAILURE;
809 }
810 
811 qdf_export_symbol(qdf_uint16_array_parse);
812 
qdf_uint8_array_parse(const char * in_str,uint8_t * out_array,qdf_size_t array_size,qdf_size_t * out_size)813 QDF_STATUS qdf_uint8_array_parse(const char *in_str, uint8_t *out_array,
814 				 qdf_size_t array_size, qdf_size_t *out_size)
815 {
816 	QDF_STATUS status;
817 	bool negate;
818 	qdf_size_t size = 0;
819 	uint64_t value;
820 
821 	QDF_BUG(in_str);
822 	if (!in_str)
823 		return QDF_STATUS_E_INVAL;
824 
825 	QDF_BUG(out_array);
826 	if (!out_array)
827 		return QDF_STATUS_E_INVAL;
828 
829 	QDF_BUG(out_size);
830 	if (!out_size)
831 		return QDF_STATUS_E_INVAL;
832 
833 	while (size < array_size) {
834 		status = __qdf_int_parse_lazy(&in_str, &value, &negate);
835 		if (QDF_IS_STATUS_ERROR(status))
836 			return status;
837 
838 		if ((uint8_t)value != value || negate)
839 			return QDF_STATUS_E_RANGE;
840 
841 		in_str = qdf_str_left_trim(in_str);
842 
843 		switch (in_str[0]) {
844 		case ',':
845 			out_array[size++] = value;
846 			in_str++;
847 			break;
848 		case '\0':
849 			out_array[size++] = value;
850 			*out_size = size;
851 			return QDF_STATUS_SUCCESS;
852 		default:
853 			return QDF_STATUS_E_FAILURE;
854 		}
855 	}
856 
857 	return QDF_STATUS_E_FAILURE;
858 }
859 
860 qdf_export_symbol(qdf_uint8_array_parse);
861