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