xref: /wlan-dirver/qca-wifi-host-cmn/qdf/src/qdf_types.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 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 
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 
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 
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 
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 
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 
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 
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 
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
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
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 
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 
310 QDF_STATUS qdf_uint32_parse(const char *int_str, uint32_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 ((uint32_t)value != value)
320 		return QDF_STATUS_E_RANGE;
321 
322 	*out_int = value;
323 
324 	return QDF_STATUS_SUCCESS;
325 }
326 qdf_export_symbol(qdf_uint32_parse);
327 
328 QDF_STATUS qdf_int64_parse(const char *int_str, int64_t *out_int)
329 {
330 	QDF_STATUS status;
331 	bool negate = false;
332 	uint64_t value = 0;
333 	int64_t signed_value;
334 
335 	status = qdf_int_parse(int_str, &value, &negate);
336 	if (QDF_IS_STATUS_ERROR(status))
337 		return status;
338 
339 	if (negate) {
340 		signed_value = -value;
341 		if (signed_value > 0)
342 			return QDF_STATUS_E_RANGE;
343 	} else {
344 		signed_value = value;
345 		if (signed_value < 0)
346 			return QDF_STATUS_E_RANGE;
347 	}
348 
349 	*out_int = signed_value;
350 
351 	return QDF_STATUS_SUCCESS;
352 }
353 qdf_export_symbol(qdf_int64_parse);
354 
355 QDF_STATUS qdf_uint64_parse(const char *int_str, uint64_t *out_int)
356 {
357 	QDF_STATUS status;
358 	bool negate = false;
359 	uint64_t value = 0;
360 
361 	status = qdf_int_parse(int_str, &value, &negate);
362 	if (QDF_IS_STATUS_ERROR(status))
363 		return status;
364 
365 	if (negate)
366 		return QDF_STATUS_E_RANGE;
367 
368 	*out_int = value;
369 
370 	return QDF_STATUS_SUCCESS;
371 }
372 qdf_export_symbol(qdf_uint64_parse);
373 
374 QDF_STATUS qdf_bool_parse(const char *bool_str, bool *out_bool)
375 {
376 	bool value;
377 
378 	QDF_BUG(bool_str);
379 	if (!bool_str)
380 		return QDF_STATUS_E_INVAL;
381 
382 	QDF_BUG(out_bool);
383 	if (!out_bool)
384 		return QDF_STATUS_E_INVAL;
385 
386 	bool_str = qdf_str_left_trim(bool_str);
387 
388 	switch (bool_str[0]) {
389 	case '1':
390 	case 'y':
391 	case 'Y':
392 		value = true;
393 		break;
394 	case '0':
395 	case 'n':
396 	case 'N':
397 		value = false;
398 		break;
399 	default:
400 		return QDF_STATUS_E_FAILURE;
401 	}
402 
403 	bool_str++;
404 	bool_str = qdf_str_left_trim(bool_str);
405 	if (bool_str[0] != '\0')
406 		return QDF_STATUS_E_FAILURE;
407 
408 	*out_bool = value;
409 
410 	return QDF_STATUS_SUCCESS;
411 }
412 qdf_export_symbol(qdf_bool_parse);
413 
414 QDF_STATUS qdf_mac_parse(const char *mac_str, struct qdf_mac_addr *out_addr)
415 {
416 	QDF_STATUS status;
417 	struct qdf_mac_addr addr;
418 	bool colons;
419 	int i;
420 
421 	QDF_BUG(mac_str);
422 	if (!mac_str)
423 		return QDF_STATUS_E_INVAL;
424 
425 	QDF_BUG(out_addr);
426 	if (!out_addr)
427 		return QDF_STATUS_E_INVAL;
428 
429 	mac_str = qdf_str_left_trim(mac_str);
430 
431 	/* parse leading hex pair */
432 	status = qdf_consume_hex_pair(&mac_str, &addr.bytes[0]);
433 	if (QDF_IS_STATUS_ERROR(status))
434 		return status;
435 
436 	/* dynamically detect colons */
437 	colons = mac_str[0] == ':';
438 
439 	for (i = 1; i < QDF_MAC_ADDR_SIZE; i++) {
440 		/* ensure colon separator if previously detected */
441 		if (colons) {
442 			status = qdf_consume_char(&mac_str, ':');
443 			if (QDF_IS_STATUS_ERROR(status))
444 				return status;
445 		}
446 
447 		/* parse next hex pair */
448 		status = qdf_consume_hex_pair(&mac_str, &addr.bytes[i]);
449 		if (QDF_IS_STATUS_ERROR(status))
450 			return status;
451 	}
452 
453 	mac_str = qdf_str_left_trim(mac_str);
454 	if (mac_str[0] != '\0')
455 		return QDF_STATUS_E_FAILURE;
456 
457 	*out_addr = addr;
458 
459 	return QDF_STATUS_SUCCESS;
460 }
461 qdf_export_symbol(qdf_mac_parse);
462 
463 QDF_STATUS qdf_ipv4_parse(const char *ipv4_str, struct qdf_ipv4_addr *out_addr)
464 {
465 	QDF_STATUS status;
466 	struct qdf_ipv4_addr addr;
467 	int i;
468 
469 	QDF_BUG(ipv4_str);
470 	if (!ipv4_str)
471 		return QDF_STATUS_E_INVAL;
472 
473 	QDF_BUG(out_addr);
474 	if (!out_addr)
475 		return QDF_STATUS_E_INVAL;
476 
477 	ipv4_str = qdf_str_left_trim(ipv4_str);
478 
479 	/* parse leading octet */
480 	status = qdf_consume_octet_dec(&ipv4_str, &addr.bytes[0]);
481 	if (QDF_IS_STATUS_ERROR(status))
482 		return status;
483 
484 	for (i = 1; i < QDF_IPV4_ADDR_SIZE; i++) {
485 		/* ensure dot separator */
486 		status = qdf_consume_char(&ipv4_str, '.');
487 		if (QDF_IS_STATUS_ERROR(status))
488 			return status;
489 
490 		/* parse next octet */
491 		status = qdf_consume_octet_dec(&ipv4_str, &addr.bytes[i]);
492 		if (QDF_IS_STATUS_ERROR(status))
493 			return status;
494 	}
495 
496 	ipv4_str = qdf_str_left_trim(ipv4_str);
497 	if (ipv4_str[0] != '\0')
498 		return QDF_STATUS_E_FAILURE;
499 
500 	*out_addr = addr;
501 
502 	return QDF_STATUS_SUCCESS;
503 }
504 qdf_export_symbol(qdf_ipv4_parse);
505 
506 static inline void qdf_ipv6_apply_zero_comp(struct qdf_ipv6_addr *addr,
507 					    uint8_t hextets,
508 					    uint8_t zero_comp_index)
509 {
510 	/* Given the following hypothetical ipv6 address:
511 	 * |---------------------------------------|
512 	 * | 01 | ab | cd | ef |    |    |    |    |
513 	 * |---------------------------------------|
514 	 *           ^--- zero_comp_index (2)
515 	 * from -----^
516 	 * to ---------------------------^
517 	 * |    hextets (4)    |
518 	 *                     |   zero comp size  |
519 	 *           | to move |
520 	 *
521 	 * We need to apply the zero compression such that we get:
522 	 * |---------------------------------------|
523 	 * | 01 | ab | 00 | 00 | 00 | 00 | cd | ef |
524 	 * |---------------------------------------|
525 	 *           |     zero comp     |
526 	 *                               |  moved  |
527 	 */
528 
529 	size_t zero_comp_size = (QDF_IPV6_ADDR_HEXTET_COUNT - hextets) * 2;
530 	size_t bytes_to_move = (hextets - zero_comp_index) * 2;
531 	uint8_t *from = &addr->bytes[zero_comp_index * 2];
532 	uint8_t *to = from + zero_comp_size;
533 
534 	if (bytes_to_move)
535 		qdf_mem_move(to, from, bytes_to_move);
536 
537 	qdf_mem_zero(from, to - from);
538 }
539 
540 QDF_STATUS qdf_ipv6_parse(const char *ipv6_str, struct qdf_ipv6_addr *out_addr)
541 {
542 	QDF_STATUS status;
543 	struct qdf_ipv6_addr addr;
544 	int8_t zero_comp = -1;
545 	uint8_t hextets_found = 0;
546 
547 	QDF_BUG(ipv6_str);
548 	if (!ipv6_str)
549 		return QDF_STATUS_E_INVAL;
550 
551 	QDF_BUG(out_addr);
552 	if (!out_addr)
553 		return QDF_STATUS_E_INVAL;
554 
555 	ipv6_str = qdf_str_left_trim(ipv6_str);
556 
557 	/* check for leading zero-compression ("::") */
558 	status = qdf_consume_char(&ipv6_str, ':');
559 	if (QDF_IS_STATUS_SUCCESS(status)) {
560 		status = qdf_consume_char(&ipv6_str, ':');
561 		if (QDF_IS_STATUS_SUCCESS(status))
562 			zero_comp = 0;
563 		else
564 			return QDF_STATUS_E_FAILURE;
565 	}
566 
567 	while (hextets_found < QDF_IPV6_ADDR_HEXTET_COUNT) {
568 		uint16_t hextet;
569 
570 		/* parse hextet */
571 		status = qdf_consume_hextet(&ipv6_str, &hextet);
572 		if (QDF_IS_STATUS_ERROR(status)) {
573 			/* we must end with hextet or zero compression */
574 			if (hextets_found != zero_comp)
575 				return QDF_STATUS_E_FAILURE;
576 
577 			break;
578 		}
579 
580 		addr.bytes[hextets_found * 2] = hextet >> 8;
581 		addr.bytes[hextets_found * 2 + 1] = hextet;
582 		hextets_found++;
583 
584 		/* parse ':' char */
585 		status = qdf_consume_char(&ipv6_str, ':');
586 		if (QDF_IS_STATUS_ERROR(status))
587 			break;
588 
589 		/* check for zero compression ("::") */
590 		status = qdf_consume_char(&ipv6_str, ':');
591 		if (QDF_IS_STATUS_SUCCESS(status)) {
592 			/* only one zero compression is allowed */
593 			if (zero_comp >= 0)
594 				return QDF_STATUS_E_FAILURE;
595 
596 			zero_comp = hextets_found;
597 		}
598 	}
599 
600 	ipv6_str = qdf_str_left_trim(ipv6_str);
601 	if (ipv6_str[0] != '\0')
602 		return QDF_STATUS_E_FAILURE;
603 
604 	/* we must have max hextets or a zero compression, but not both */
605 	if (hextets_found < QDF_IPV6_ADDR_HEXTET_COUNT) {
606 		if (zero_comp < 0)
607 			return QDF_STATUS_E_FAILURE;
608 
609 		qdf_ipv6_apply_zero_comp(&addr, hextets_found, zero_comp);
610 	} else if (zero_comp > -1) {
611 		return QDF_STATUS_E_FAILURE;
612 	}
613 
614 	*out_addr = addr;
615 
616 	return QDF_STATUS_SUCCESS;
617 }
618 qdf_export_symbol(qdf_ipv6_parse);
619 
620 QDF_STATUS qdf_int32_array_parse(const char *in_str, int32_t *out_array,
621 				 qdf_size_t array_size, qdf_size_t *out_size)
622 {
623 	QDF_STATUS status;
624 	qdf_size_t size = 0;
625 	bool negate;
626 	uint64_t value;
627 	int64_t signed_value;
628 
629 	QDF_BUG(in_str);
630 	if (!in_str)
631 		return QDF_STATUS_E_INVAL;
632 
633 	QDF_BUG(out_array);
634 	if (!out_array)
635 		return QDF_STATUS_E_INVAL;
636 
637 	QDF_BUG(out_size);
638 	if (!out_size)
639 		return QDF_STATUS_E_INVAL;
640 
641 	while (size < array_size) {
642 		status = __qdf_int_parse_lazy(&in_str, &value, &negate);
643 		if (QDF_IS_STATUS_ERROR(status))
644 			return status;
645 
646 		if (negate) {
647 			signed_value = -value;
648 			if (signed_value > 0)
649 				return QDF_STATUS_E_RANGE;
650 		} else {
651 			signed_value = value;
652 			if (signed_value < 0)
653 				return QDF_STATUS_E_RANGE;
654 		}
655 
656 		in_str = qdf_str_left_trim(in_str);
657 
658 		switch (in_str[0]) {
659 		case ',':
660 			out_array[size++] = signed_value;
661 			in_str++;
662 			break;
663 		case '\0':
664 			out_array[size++] = signed_value;
665 			*out_size = size;
666 			return QDF_STATUS_SUCCESS;
667 		default:
668 			return QDF_STATUS_E_FAILURE;
669 		}
670 	}
671 
672 	return QDF_STATUS_E_FAILURE;
673 }
674 
675 qdf_export_symbol(qdf_int32_array_parse);
676 
677 QDF_STATUS qdf_uint32_array_parse(const char *in_str, uint32_t *out_array,
678 				  qdf_size_t array_size, qdf_size_t *out_size)
679 {
680 	QDF_STATUS status;
681 	bool negate;
682 	qdf_size_t size = 0;
683 	uint64_t value;
684 
685 	QDF_BUG(in_str);
686 	if (!in_str)
687 		return QDF_STATUS_E_INVAL;
688 
689 	QDF_BUG(out_array);
690 	if (!out_array)
691 		return QDF_STATUS_E_INVAL;
692 
693 	QDF_BUG(out_size);
694 	if (!out_size)
695 		return QDF_STATUS_E_INVAL;
696 
697 	while (size < array_size) {
698 		status = __qdf_int_parse_lazy(&in_str, &value, &negate);
699 		if (QDF_IS_STATUS_ERROR(status))
700 			return status;
701 
702 		if ((uint32_t)value != value || negate)
703 			return QDF_STATUS_E_RANGE;
704 
705 		in_str = qdf_str_left_trim(in_str);
706 
707 		switch (in_str[0]) {
708 		case ',':
709 			out_array[size++] = value;
710 			in_str++;
711 			break;
712 		case '\0':
713 			out_array[size++] = value;
714 			*out_size = size;
715 			return QDF_STATUS_SUCCESS;
716 		default:
717 			return QDF_STATUS_E_FAILURE;
718 		}
719 	}
720 
721 	return QDF_STATUS_E_FAILURE;
722 }
723 
724 qdf_export_symbol(qdf_uint32_array_parse);
725 
726 QDF_STATUS qdf_uint16_array_parse(const char *in_str, uint16_t *out_array,
727 				  qdf_size_t array_size, qdf_size_t *out_size)
728 {
729 	QDF_STATUS status;
730 	bool negate;
731 	qdf_size_t size = 0;
732 	uint64_t value;
733 
734 	QDF_BUG(in_str);
735 	if (!in_str)
736 		return QDF_STATUS_E_INVAL;
737 
738 	QDF_BUG(out_array);
739 	if (!out_array)
740 		return QDF_STATUS_E_INVAL;
741 
742 	QDF_BUG(out_size);
743 	if (!out_size)
744 		return QDF_STATUS_E_INVAL;
745 
746 	while (size < array_size) {
747 		status = __qdf_int_parse_lazy(&in_str, &value, &negate);
748 		if (QDF_IS_STATUS_ERROR(status))
749 			return status;
750 
751 		if ((uint16_t)value != value || negate)
752 			return QDF_STATUS_E_RANGE;
753 
754 		in_str = qdf_str_left_trim(in_str);
755 
756 		switch (in_str[0]) {
757 		case ',':
758 			out_array[size++] = value;
759 			in_str++;
760 			break;
761 		case '\0':
762 			out_array[size++] = value;
763 			*out_size = size;
764 			return QDF_STATUS_SUCCESS;
765 		default:
766 			return QDF_STATUS_E_FAILURE;
767 		}
768 	}
769 
770 	return QDF_STATUS_E_FAILURE;
771 }
772 
773 qdf_export_symbol(qdf_uint16_array_parse);
774 
775 QDF_STATUS qdf_uint8_array_parse(const char *in_str, uint8_t *out_array,
776 				 qdf_size_t array_size, qdf_size_t *out_size)
777 {
778 	QDF_STATUS status;
779 	bool negate;
780 	qdf_size_t size = 0;
781 	uint64_t value;
782 
783 	QDF_BUG(in_str);
784 	if (!in_str)
785 		return QDF_STATUS_E_INVAL;
786 
787 	QDF_BUG(out_array);
788 	if (!out_array)
789 		return QDF_STATUS_E_INVAL;
790 
791 	QDF_BUG(out_size);
792 	if (!out_size)
793 		return QDF_STATUS_E_INVAL;
794 
795 	while (size < array_size) {
796 		status = __qdf_int_parse_lazy(&in_str, &value, &negate);
797 		if (QDF_IS_STATUS_ERROR(status))
798 			return status;
799 
800 		if ((uint8_t)value != value || negate)
801 			return QDF_STATUS_E_RANGE;
802 
803 		in_str = qdf_str_left_trim(in_str);
804 
805 		switch (in_str[0]) {
806 		case ',':
807 			out_array[size++] = value;
808 			in_str++;
809 			break;
810 		case '\0':
811 			out_array[size++] = value;
812 			*out_size = size;
813 			return QDF_STATUS_SUCCESS;
814 		default:
815 			return QDF_STATUS_E_FAILURE;
816 		}
817 	}
818 
819 	return QDF_STATUS_E_FAILURE;
820 }
821 
822 qdf_export_symbol(qdf_uint8_array_parse);
823