Home | History | Annotate | Download | only in ti-utils
      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