1 /* 2 * PLT utility for wireless chip supported by TI's driver wl12xx 3 * 4 * See README and COPYING for more details. 5 */ 6 7 #include <sys/ioctl.h> 8 #include <errno.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <sys/stat.h> 13 #include <fcntl.h> 14 #include <unistd.h> 15 #include <stdbool.h> 16 #include <netinet/in.h> 17 18 #include <netlink/netlink.h> 19 #include <netlink/msg.h> 20 #include <netlink/attr.h> 21 #include <linux/wireless.h> 22 #include "nl80211.h" 23 24 #include "calibrator.h" 25 #include "plt.h" 26 #include "ini.h" 27 /* 2048 - it should be enough for any chip, until... 22dec2010 */ 28 #define BUF_SIZE_4_NVS_FILE 2048 29 30 static const char if_name_fmt[] = "wlan%d"; 31 32 int nvs_fill_radio_params(int fd, struct wl12xx_ini *ini, char *buf) 33 { 34 int size; 35 struct wl1271_ini *gp; 36 37 if (ini) { 38 gp = &ini->ini1271; 39 } 40 41 size = sizeof(struct wl1271_ini); 42 43 if (ini) { /* for reference NVS */ 44 unsigned char *c = (unsigned char *)gp; 45 int i; 46 47 for (i = 0; i < size; i++) { 48 write(fd, c++, 1); 49 } 50 } else { 51 char *p = buf + 0x1D4; 52 write(fd, (const void *)p, size); 53 } 54 55 return 0; 56 } 57 58 static int nvs_fill_radio_params_128x(int fd, struct wl12xx_ini *ini, char *buf) 59 { 60 int size; 61 struct wl128x_ini *gp = &ini->ini128x; 62 63 size = sizeof(struct wl128x_ini); 64 65 if (ini) { /* for reference NVS */ 66 unsigned char *c = (unsigned char *)gp; 67 int i; 68 69 for (i = 0; i < size; i++) { 70 write(fd, c++, 1); 71 } 72 73 } else { 74 char *p = buf + 0x1D4; 75 write(fd, p, size); 76 } 77 78 return 0; 79 } 80 81 int nvs_set_autofem(int fd, char *buf, unsigned char val) 82 { 83 int size; 84 struct wl1271_ini *gp; 85 unsigned char *c; 86 int i; 87 88 if (buf == NULL) { 89 return 1; 90 } 91 92 gp = (struct wl1271_ini *)(buf+0x1d4); 93 gp->general_params.tx_bip_fem_auto_detect = val; 94 95 size = sizeof(struct wl1271_ini); 96 97 c = (unsigned char *)gp; 98 99 for (i = 0; i < size; i++) { 100 write(fd, c++, 1); 101 } 102 103 return 0; 104 } 105 106 int nvs_set_autofem_128x(int fd, char *buf, unsigned char val) 107 { 108 int size; 109 struct wl128x_ini *gp; 110 unsigned char *c; 111 int i; 112 113 if (buf == NULL) { 114 return 1; 115 } 116 117 gp = (struct wl128x_ini *)(buf+0x1d4); 118 gp->general_params.tx_bip_fem_auto_detect = val; 119 120 size = sizeof(struct wl128x_ini); 121 122 c = (unsigned char *)gp; 123 124 for (i = 0; i < size; i++) { 125 write(fd, c++, 1); 126 } 127 128 return 0; 129 } 130 131 int nvs_set_fem_manuf(int fd, char *buf, unsigned char val) 132 { 133 int size; 134 struct wl1271_ini *gp; 135 unsigned char *c; 136 int i; 137 138 if (buf == NULL) { 139 return 1; 140 } 141 142 gp = (struct wl1271_ini *)(buf+0x1d4); 143 gp->general_params.tx_bip_fem_manufacturer = val; 144 145 size = sizeof(struct wl1271_ini); 146 147 c = (unsigned char *)gp; 148 149 for (i = 0; i < size; i++) { 150 write(fd, c++, 1); 151 } 152 153 return 0; 154 } 155 156 int nvs_set_fem_manuf_128x(int fd, char *buf, unsigned char val) 157 { 158 int size; 159 struct wl128x_ini *gp; 160 unsigned char *c; 161 int i; 162 163 if (buf == NULL) { 164 return 1; 165 } 166 167 gp = (struct wl128x_ini *)(buf+0x1d4); 168 gp->general_params.tx_bip_fem_manufacturer = val; 169 170 size = sizeof(struct wl128x_ini); 171 172 c = (unsigned char *)gp; 173 174 for (i = 0; i < size; i++) { 175 write(fd, c++, 1); 176 } 177 178 return 0; 179 } 180 181 static struct wl12xx_nvs_ops wl1271_nvs_ops = { 182 .nvs_fill_radio_prms = nvs_fill_radio_params, 183 .nvs_set_autofem = nvs_set_autofem, 184 .nvs_set_fem_manuf = nvs_set_fem_manuf, 185 }; 186 187 static struct wl12xx_nvs_ops wl128x_nvs_ops = { 188 .nvs_fill_radio_prms = nvs_fill_radio_params_128x, 189 .nvs_set_autofem = nvs_set_autofem_128x, 190 .nvs_set_fem_manuf = nvs_set_fem_manuf_128x, 191 }; 192 193 int get_mac_addr(int ifc_num, unsigned char *mac_addr) 194 { 195 int s; 196 struct ifreq ifr; 197 #if 0 198 if (ifc_num < 0 || ifc_num >= ETH_DEV_MAX) 199 return 1; 200 #endif 201 s = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 202 if (s < 0) { 203 fprintf(stderr, "unable to socket (%s)\n", strerror(errno)); 204 return 1; 205 } 206 207 memset(&ifr, 0, sizeof(struct ifreq)); 208 sprintf(ifr.ifr_name, if_name_fmt, ifc_num) ; 209 if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { 210 fprintf(stderr, "unable to ioctl (%s)\n", strerror(errno)); 211 close(s); 212 return 1; 213 } 214 215 close(s); 216 217 memcpy(mac_addr, &ifr.ifr_ifru.ifru_hwaddr.sa_data[0], 6); 218 219 return 0; 220 } 221 222 int file_exist(const char *filename) 223 { 224 struct stat buf; 225 int ret; 226 227 if (filename == NULL) { 228 fprintf(stderr, "wrong parameter\n"); 229 return -1; 230 } 231 232 ret = stat(filename, &buf); 233 if (ret != 0) { 234 fprintf(stderr, "fail to stat file %s (%s)\n", filename, 235 strerror(errno)); 236 return -1; 237 } 238 239 return (int)buf.st_size; 240 } 241 242 void cfg_nvs_ops(struct wl12xx_common *cmn) 243 { 244 if (cmn->arch == WL1271_ARCH) { 245 cmn->nvs_ops = &wl1271_nvs_ops; 246 } else { 247 cmn->nvs_ops = &wl128x_nvs_ops; 248 } 249 } 250 251 static int read_from_current_nvs(const char *nvs_file, 252 char *buf, int size, int *nvs_sz) 253 { 254 int curr_nvs, ret; 255 256 curr_nvs = open(nvs_file, O_RDONLY, S_IRUSR | S_IWUSR); 257 if (curr_nvs < 0) { 258 fprintf(stderr, "%s> Unable to open NVS file for reference " 259 "(%s)\n", __func__, strerror(errno)); 260 return 1; 261 } 262 263 ret = read(curr_nvs, buf, size); 264 if (ret < 0) { 265 fprintf(stderr, "Fail to read file %s (%s)", nvs_file, 266 strerror(errno)); 267 close(curr_nvs); 268 return 1; 269 } 270 271 if (nvs_sz) { 272 *nvs_sz = ret; 273 } 274 275 close(curr_nvs); 276 277 //printf("Read NVS file (%s) of size %d\n", nvs_file, ret); 278 279 return 0; 280 } 281 282 static int read_nvs(const char *nvs_file, char *buf, 283 int size, int *nvs_sz) 284 { 285 int fl_sz; 286 char file2read[FILENAME_MAX]; 287 288 if (nvs_file == NULL || strlen(nvs_file) < 2) { 289 printf("\nThe path to NVS file not provided, " 290 "use default (%s)\n", CURRENT_NVS_NAME); 291 292 strncpy(file2read, CURRENT_NVS_NAME, strlen(CURRENT_NVS_NAME)); 293 294 } else 295 strncpy(file2read, nvs_file, strlen(nvs_file)); 296 297 fl_sz = file_exist(file2read); 298 if (fl_sz < 0) { 299 fprintf(stderr, "File %s not exists\n", CURRENT_NVS_NAME); 300 return 1; 301 } 302 303 return read_from_current_nvs(file2read, buf, size, nvs_sz); 304 } 305 306 static int fill_nvs_def_rx_params(int fd) 307 { 308 unsigned char type = eNVS_RADIO_RX_PARAMETERS; 309 unsigned short length = NVS_RX_PARAM_LENGTH; 310 int i; 311 312 /* Rx type */ 313 write(fd, &type, 1); 314 315 /* Rx length */ 316 write(fd, &length, 2); 317 318 type = DEFAULT_EFUSE_VALUE; /* just reuse of var */ 319 for (i = 0; i < NVS_RX_PARAM_LENGTH; i++) { 320 write(fd, &type, 1); 321 } 322 323 return 0; 324 } 325 326 static void nvs_parse_data(const unsigned char *buf, 327 struct wl1271_cmd_cal_p2g *pdata, unsigned int *pver) 328 { 329 #define BUFFER_INDEX (buf_idx + START_PARAM_INDEX + info_idx) 330 unsigned short buf_idx; 331 unsigned char tlv_type; 332 unsigned short tlv_len; 333 unsigned short info_idx; 334 unsigned int nvsTypeInfo; 335 unsigned char nvs_ver_oct_idx; 336 unsigned char shift; 337 338 for (buf_idx = 0; buf_idx < NVS_TOTAL_LENGTH;) { 339 tlv_type = buf[buf_idx]; 340 341 /* fill the correct mode to fill the NVS struct buffer */ 342 /* if the tlv_type is the last type break from the loop */ 343 switch (tlv_type) { 344 case eNVS_RADIO_TX_PARAMETERS: 345 nvsTypeInfo = eNVS_RADIO_TX_TYPE_PARAMETERS_INFO; 346 break; 347 case eNVS_RADIO_RX_PARAMETERS: 348 nvsTypeInfo = eNVS_RADIO_RX_TYPE_PARAMETERS_INFO; 349 break; 350 case eNVS_VERSION: 351 for (*pver = 0, nvs_ver_oct_idx = 0; 352 nvs_ver_oct_idx < NVS_VERSION_PARAMETER_LENGTH; 353 nvs_ver_oct_idx++) { 354 shift = 8 * (NVS_VERSION_PARAMETER_LENGTH - 355 1 - nvs_ver_oct_idx); 356 *pver += ((buf[buf_idx + START_PARAM_INDEX + 357 nvs_ver_oct_idx]) << shift); 358 } 359 break; 360 case eTLV_LAST: 361 default: 362 return; 363 } 364 365 tlv_len = (buf[buf_idx + START_LENGTH_INDEX + 1] << 8) + 366 buf[buf_idx + START_LENGTH_INDEX]; 367 368 /* if TLV type is not NVS ver fill the NVS according */ 369 /* to the mode TX/RX */ 370 if ((eNVS_RADIO_TX_PARAMETERS == tlv_type) || 371 (eNVS_RADIO_RX_PARAMETERS == tlv_type)) { 372 pdata[nvsTypeInfo].type = tlv_type; 373 pdata[nvsTypeInfo].len = tlv_len; 374 375 for (info_idx = 0; (info_idx < tlv_len) && 376 (BUFFER_INDEX < NVS_TOTAL_LENGTH); 377 info_idx++) { 378 pdata[nvsTypeInfo].buf[info_idx] = 379 buf[BUFFER_INDEX]; 380 } 381 } 382 383 /* increment to the next TLV */ 384 buf_idx += START_PARAM_INDEX + tlv_len; 385 } 386 } 387 388 static int nvs_fill_version(int fd, unsigned int *pdata) 389 { 390 unsigned char tmp = eNVS_VERSION; 391 unsigned short tmp2 = NVS_VERSION_PARAMETER_LENGTH; 392 393 write(fd, &tmp, 1); 394 395 write(fd, &tmp2, 2); 396 397 tmp = (*pdata >> 16) & 0xff; 398 write(fd, &tmp, 1); 399 400 tmp = (*pdata >> 8) & 0xff; 401 write(fd, &tmp, 1); 402 403 tmp = *pdata & 0xff; 404 write(fd, &tmp, 1); 405 406 return 0; 407 } 408 409 static int nvs_fill_old_rx_data(int fd, const unsigned char *buf, 410 unsigned short len) 411 { 412 unsigned short idx; 413 unsigned char rx_type; 414 415 /* RX BiP type */ 416 rx_type = eNVS_RADIO_RX_PARAMETERS; 417 write(fd, &rx_type, 1); 418 419 /* RX BIP Length */ 420 write(fd, &len, 2); 421 422 for (idx = 0; idx < len; idx++) { 423 write(fd, &(buf[idx]), 1); 424 } 425 426 return 0; 427 } 428 429 static int nvs_upd_nvs_part(int fd, char *buf) 430 { 431 char *p = buf; 432 433 write(fd, p, 0x1D4); 434 435 return 0; 436 } 437 438 static int nvs_fill_nvs_part(int fd) 439 { 440 int i; 441 unsigned char mac_addr[MAC_ADDR_LEN] = { 442 0x0b, 0xad, 0xde, 0xad, 0xbe, 0xef 443 }; 444 __le16 nvs_tx_sz = NVS_TX_PARAM_LENGTH; 445 __le32 nvs_ver = 0x0; 446 const unsigned char vals[] = { 447 0x0, 0x1, 0x6d, 0x54, 0x71, eTLV_LAST, eNVS_RADIO_TX_PARAMETERS 448 }; 449 450 write(fd, &vals[1], 1); 451 write(fd, &vals[2], 1); 452 write(fd, &vals[3], 1); 453 #if 0 454 if (get_mac_addr(0, mac_addr)) { 455 fprintf(stderr, "%s> Fail to get mac address\n", __func__); 456 return 1; 457 } 458 #endif 459 /* write down MAC address in new NVS file */ 460 write(fd, &mac_addr[5], 1); 461 write(fd, &mac_addr[4], 1); 462 write(fd, &mac_addr[3], 1); 463 write(fd, &mac_addr[2], 1); 464 465 write(fd, &vals[1], 1); 466 write(fd, &vals[4], 1); 467 write(fd, &vals[3], 1); 468 469 write(fd, &mac_addr[1], 1); 470 write(fd, &mac_addr[0], 1); 471 472 write(fd, &vals[0], 1); 473 write(fd, &vals[0], 1); 474 475 /* fill end burst transaction zeros */ 476 for (i = 0; i < NVS_END_BURST_TRANSACTION_LENGTH; i++) { 477 write(fd, &vals[0], 1); 478 } 479 480 /* fill zeros to Align TLV start address */ 481 for (i = 0; i < NVS_ALING_TLV_START_ADDRESS_LENGTH; i++) { 482 write(fd, &vals[0], 1); 483 } 484 485 /* Fill Tx calibration part */ 486 write(fd, &vals[6], 1); 487 write(fd, &nvs_tx_sz, 2); 488 489 for (i = 0; i < nvs_tx_sz; i++) { 490 write(fd, &vals[0], 1); 491 } 492 493 /* Fill Rx calibration part */ 494 fill_nvs_def_rx_params(fd); 495 496 /* fill NVS version */ 497 if (nvs_fill_version(fd, &nvs_ver)) { 498 fprintf(stderr, "Fail to fill version\n"); 499 } 500 501 /* fill end of NVS */ 502 write(fd, &vals[5], 1); /* eTLV_LAST */ 503 write(fd, &vals[5], 1); /* eTLV_LAST */ 504 write(fd, &vals[0], 1); 505 write(fd, &vals[0], 1); 506 507 return 0; 508 } 509 510 int prepare_nvs_file(void *arg, char *file_name) 511 { 512 int new_nvs, i, nvs_size; 513 unsigned char mac_addr[MAC_ADDR_LEN]; 514 struct wl1271_cmd_cal_p2g *pdata; 515 struct wl1271_cmd_cal_p2g old_data[eNUMBER_RADIO_TYPE_PARAMETERS_INFO]; 516 char buf[2048]; 517 unsigned char *p; 518 struct wl12xx_common cmn = { 519 .arch = UNKNOWN_ARCH, 520 .parse_ops = NULL 521 }; 522 523 const unsigned char vals[] = { 524 0x0, 0x1, 0x6d, 0x54, 0x71, eTLV_LAST, eNVS_RADIO_TX_PARAMETERS 525 }; 526 527 if (arg == NULL) { 528 fprintf(stderr, "%s> Missing args\n", __func__); 529 return 1; 530 } 531 532 if (read_nvs(file_name, buf, BUF_SIZE_4_NVS_FILE, &nvs_size)) { 533 return 1; 534 } 535 536 switch (nvs_size) { 537 case NVS_FILE_SIZE_127X: 538 cmn.arch = WL1271_ARCH; 539 break; 540 case NVS_FILE_SIZE_128X: 541 cmn.arch = WL128X_ARCH; 542 break; 543 default: 544 fprintf(stderr, "%s> Wrong file size\n", __func__); 545 return 1; 546 } 547 548 cfg_nvs_ops(&cmn); 549 550 /* create new NVS file */ 551 new_nvs = open(NEW_NVS_NAME, 552 O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 553 if (new_nvs < 0) { 554 fprintf(stderr, "%s> Unable to open new NVS file\n", __func__); 555 return 1; 556 } 557 558 write(new_nvs, &vals[1], 1); 559 write(new_nvs, &vals[2], 1); 560 write(new_nvs, &vals[3], 1); 561 562 if (get_mac_addr(0, mac_addr)) { 563 fprintf(stderr, "%s> Fail to get mac addr\n", __func__); 564 close(new_nvs); 565 return 1; 566 } 567 568 /* write down MAC address in new NVS file */ 569 write(new_nvs, &mac_addr[5], 1); 570 write(new_nvs, &mac_addr[4], 1); 571 write(new_nvs, &mac_addr[3], 1); 572 write(new_nvs, &mac_addr[2], 1); 573 574 write(new_nvs, &vals[1], 1); 575 write(new_nvs, &vals[4], 1); 576 write(new_nvs, &vals[3], 1); 577 578 write(new_nvs, &mac_addr[1], 1); 579 write(new_nvs, &mac_addr[0], 1); 580 581 write(new_nvs, &vals[0], 1); 582 write(new_nvs, &vals[0], 1); 583 584 /* fill end burst transaction zeros */ 585 for (i = 0; i < NVS_END_BURST_TRANSACTION_LENGTH; i++) { 586 write(new_nvs, &vals[0], 1); 587 } 588 589 /* fill zeros to Align TLV start address */ 590 for (i = 0; i < NVS_ALING_TLV_START_ADDRESS_LENGTH; i++) { 591 write(new_nvs, &vals[0], 1); 592 } 593 594 /* Fill TxBip */ 595 pdata = (struct wl1271_cmd_cal_p2g *)arg; 596 597 write(new_nvs, &vals[6], 1); 598 write(new_nvs, &pdata->len, 2); 599 600 p = (unsigned char *)&(pdata->buf); 601 for (i = 0; i < pdata->len; i++) { 602 write(new_nvs, p++, 1); 603 } 604 605 { 606 unsigned int old_ver; 607 #if 0 608 { 609 unsigned char *p = (unsigned char *)buf; 610 for (old_ver = 0; old_ver < 1024; old_ver++) { 611 if (old_ver%16 == 0) 612 printf("\n"); 613 printf("%02x ", *p++); 614 } 615 } 616 #endif 617 memset(old_data, 0, 618 sizeof(struct wl1271_cmd_cal_p2g)* 619 eNUMBER_RADIO_TYPE_PARAMETERS_INFO); 620 nvs_parse_data((const unsigned char *)&buf[NVS_PRE_PARAMETERS_LENGTH], 621 old_data, &old_ver); 622 623 nvs_fill_old_rx_data(new_nvs, 624 old_data[eNVS_RADIO_RX_TYPE_PARAMETERS_INFO].buf, 625 old_data[eNVS_RADIO_RX_TYPE_PARAMETERS_INFO].len); 626 } 627 628 /* fill NVS version */ 629 if (nvs_fill_version(new_nvs, &pdata->ver)) { 630 fprintf(stderr, "Fail to fill version\n"); 631 } 632 633 /* fill end of NVS */ 634 write(new_nvs, &vals[5], 1); /* eTLV_LAST */ 635 write(new_nvs, &vals[5], 1); /* eTLV_LAST */ 636 write(new_nvs, &vals[0], 1); 637 write(new_nvs, &vals[0], 1); 638 639 /* fill radio params */ 640 if (cmn.nvs_ops->nvs_fill_radio_prms(new_nvs, NULL, buf)) { 641 fprintf(stderr, "Fail to fill radio params\n"); 642 } 643 644 close(new_nvs); 645 646 return 0; 647 } 648 649 int create_nvs_file(struct wl12xx_common *cmn) 650 { 651 int new_nvs, res = 0; 652 char buf[2048]; 653 654 /* create new NVS file */ 655 new_nvs = open(NEW_NVS_NAME, 656 O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 657 if (new_nvs < 0) { 658 fprintf(stderr, "%s> Unable to open new NVS file\n", __func__); 659 return 1; 660 } 661 662 /* fill nvs part */ 663 if (nvs_fill_nvs_part(new_nvs)) { 664 fprintf(stderr, "Fail to fill NVS part\n"); 665 res = 1; 666 667 goto out; 668 } 669 670 /* fill radio params */ 671 if (cmn->nvs_ops->nvs_fill_radio_prms(new_nvs, &cmn->ini, buf)) { 672 fprintf(stderr, "Fail to fill radio params\n"); 673 res = 1; 674 } 675 676 out: 677 close(new_nvs); 678 679 return res; 680 } 681 682 int update_nvs_file(const char *nvs_file, struct wl12xx_common *cmn) 683 { 684 int new_nvs, res = 0; 685 char buf[2048]; 686 687 res = read_nvs(nvs_file, buf, BUF_SIZE_4_NVS_FILE, NULL); 688 if (res) { 689 return 1; 690 } 691 692 /* create new NVS file */ 693 new_nvs = open(NEW_NVS_NAME, 694 O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 695 if (new_nvs < 0) { 696 fprintf(stderr, "%s> Unable to open new NVS file\n", __func__); 697 return 1; 698 } 699 700 /* fill nvs part */ 701 if (nvs_upd_nvs_part(new_nvs, buf)) { 702 fprintf(stderr, "Fail to fill NVS part\n"); 703 res = 1; 704 705 goto out; 706 } 707 708 /* fill radio params */ 709 if (cmn->nvs_ops->nvs_fill_radio_prms(new_nvs, &cmn->ini, buf)) { 710 printf("Fail to fill radio params\n"); 711 res = 1; 712 } 713 714 out: 715 close(new_nvs); 716 717 return res; 718 } 719 720 int dump_nvs_file(const char *nvs_file, struct wl12xx_common *cmn) 721 { 722 int sz=0, size; 723 char buf[2048]; 724 unsigned char *p = (unsigned char *)buf; 725 726 if (read_nvs(nvs_file, buf, BUF_SIZE_4_NVS_FILE, &size)) { 727 return 1; 728 } 729 730 printf("\nThe size is %d bytes\n", size); 731 732 for ( ; sz < size; sz++) { 733 if (sz%16 == 0) { 734 printf("\n %04X ", sz); 735 } 736 printf("%02x ", *p++); 737 } 738 printf("\n"); 739 740 return 0; 741 } 742 743 int set_nvs_file_autofem(const char *nvs_file, unsigned char val, 744 struct wl12xx_common *cmn) 745 { 746 int new_nvs, res = 0; 747 char buf[2048]; 748 int nvs_file_sz; 749 750 res = read_nvs(nvs_file, buf, BUF_SIZE_4_NVS_FILE, &nvs_file_sz); 751 if (res) { 752 return 1; 753 } 754 755 if (nvs_get_arch(nvs_file_sz, cmn)) { 756 fprintf(stderr, "Fail to define architecture\n"); 757 return 1; 758 } 759 760 cfg_nvs_ops(cmn); 761 762 /* create new NVS file */ 763 new_nvs = open(NEW_NVS_NAME, 764 O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 765 if (new_nvs < 0) { 766 fprintf(stderr, "%s> Unable to open new NVS file\n", __func__); 767 return 1; 768 } 769 770 /* fill nvs part */ 771 if (nvs_upd_nvs_part(new_nvs, buf)) { 772 fprintf(stderr, "Fail to fill NVS part\n"); 773 res = 1; 774 775 goto out; 776 } 777 778 /* fill radio params */ 779 if (cmn->nvs_ops->nvs_set_autofem(new_nvs, buf, val)) { 780 printf("Fail to fill radio params\n"); 781 res = 1; 782 } 783 784 out: 785 close(new_nvs); 786 787 return res; 788 } 789 790 int set_nvs_file_fem_manuf(const char *nvs_file, unsigned char val, 791 struct wl12xx_common *cmn) 792 { 793 int new_nvs, res = 0; 794 char buf[2048]; 795 int nvs_file_sz; 796 797 res = read_nvs(nvs_file, buf, BUF_SIZE_4_NVS_FILE, &nvs_file_sz); 798 if (res) { 799 return 1; 800 } 801 802 if (nvs_get_arch(nvs_file_sz, cmn)) { 803 fprintf(stderr, "Fail to define architecture\n"); 804 return 1; 805 } 806 807 cfg_nvs_ops(cmn); 808 809 /* create new NVS file */ 810 new_nvs = open(NEW_NVS_NAME, 811 O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 812 if (new_nvs < 0) { 813 fprintf(stderr, "%s> Unable to open new NVS file\n", __func__); 814 return 1; 815 } 816 817 /* fill nvs part */ 818 if (nvs_upd_nvs_part(new_nvs, buf)) { 819 fprintf(stderr, "Fail to fill NVS part\n"); 820 res = 1; 821 822 goto out; 823 } 824 825 /* fill radio params */ 826 if (cmn->nvs_ops->nvs_set_fem_manuf(new_nvs, buf, val)) { 827 printf("Fail to fill radio params\n"); 828 res = 1; 829 } 830 831 out: 832 close(new_nvs); 833 834 return res; 835 } 836 837