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