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