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 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_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 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 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 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 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 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 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 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 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 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 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 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 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 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