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 17 #include <netlink/genl/genl.h> 18 #include <netlink/genl/family.h> 19 #include <netlink/genl/ctrl.h> 20 #include <netlink/msg.h> 21 #include <netlink/attr.h> 22 #include <linux/wireless.h> 23 #include "nl80211.h" 24 25 #include "calibrator.h" 26 #include "plt.h" 27 #include "ini.h" 28 #include "nvs.h" 29 30 static char *ini_get_line(char *s, int size, FILE *stream, int *line, 31 char **_pos) 32 { 33 char *pos, *end, *sstart; 34 35 while (fgets(s, size, stream)) { 36 s[size - 1] = '\0'; 37 pos = s; 38 39 /* Skip white space from the beginning of line. */ 40 while (*pos == ' ' || *pos == '\t' || *pos == '\r') { 41 pos++; 42 } 43 44 /* Skip comment lines and empty lines */ 45 if (*pos == '#' || *pos == '\n' || *pos == '\0') { 46 continue; 47 } 48 49 /* 50 * Remove # comments unless they are within a double quoted 51 * string. 52 */ 53 sstart = strchr(pos, '"'); 54 if (sstart) { 55 sstart = strrchr(sstart + 1, '"'); 56 } 57 if (!sstart) { 58 sstart = pos; 59 } 60 end = strchr(sstart, '#'); 61 if (end) { 62 *end-- = '\0'; 63 } else { 64 end = pos + strlen(pos) - 1; 65 } 66 67 /* Remove trailing white space. */ 68 while (end > pos && 69 (*end == '\n' || *end == ' ' || *end == '\t' || 70 *end == '\r')) { 71 *end-- = '\0'; 72 } 73 74 if (*pos == '\0') { 75 continue; 76 } 77 78 (*line)++; 79 80 if (_pos) { 81 *_pos = pos; 82 } 83 return pos; 84 } 85 86 if (_pos) { 87 *_pos = NULL; 88 } 89 90 return NULL; 91 } 92 93 static int split_line(char *line, char **name, char **value) 94 { 95 char *pos = line; 96 97 *value = strchr(pos, '='); 98 if (!*value) { 99 fprintf(stderr, "Wrong format of line\n"); 100 return 1; 101 } 102 103 *name = *value; 104 105 (*name)--; 106 while (**name == ' ' || **name == '\t' || **name == '\r') { 107 (*name)--; 108 } 109 110 *++(*name) = '\0'; 111 112 (*value)++; 113 while (**value == ' ' || **value == '\t' || **value == '\r') { 114 (*value)++; 115 } 116 117 return 0; 118 } 119 120 #define COMPARE_N_ADD(temp, str, val, ptr, size) \ 121 if (strncmp(temp, str, sizeof(temp)) == 0) { \ 122 int i; \ 123 unsigned char *p = ptr; \ 124 for (i = 0; i < size; i++) { \ 125 *p = strtol(val, NULL, 16); \ 126 if (i != sizeof(ptr)-1) { \ 127 val += 3; p++; \ 128 } \ 129 } \ 130 return 0; \ 131 } 132 133 #define DBG_COMPARE_N_ADD(temp, str, val, ptr, size) \ 134 if (strncmp(temp, str, sizeof(temp)) == 0) { \ 135 int i; \ 136 unsigned char *p = ptr; \ 137 for (i = 0; i < size; i++) { \ 138 *p = strtol(val, NULL, 16); \ 139 if (i != sizeof(ptr)-1) { \ 140 val += 3; p++; \ 141 } \ 142 } \ 143 p = ptr; \ 144 printf("%s ", temp); \ 145 for (i = 0; i < size; i++) { \ 146 printf("%02X ", *p); \ 147 p++; \ 148 } \ 149 printf("\n"); \ 150 return 0; \ 151 } 152 153 #define COMPARE_N_ADD2(temp, str, val, ptr, size) \ 154 if (strncmp(temp, str, sizeof(temp)) == 0) { \ 155 int i; \ 156 unsigned short *p = ptr; \ 157 for (i = 0; i < size; i++) { \ 158 *p = strtol(val, NULL, 16); \ 159 if (i != sizeof(ptr)-1) { \ 160 val += 5; p++; \ 161 } \ 162 } \ 163 return 0; \ 164 } 165 166 #define DBG_COMPARE_N_ADD2(temp, str, val, ptr, size) \ 167 if (strncmp(temp, str, sizeof(temp)) == 0) { \ 168 int i; \ 169 unsigned short *p = ptr; \ 170 for (i = 0; i < size; i++) { \ 171 *p = strtol(val, NULL, 16); \ 172 if (i != sizeof(ptr)-1) { \ 173 val += 5; p++; \ 174 } \ 175 } \ 176 p = ptr; \ 177 printf("%s ", temp); \ 178 for (i = 0; i < size; i++) { \ 179 printf("%04X ", *p); \ 180 p++; \ 181 } \ 182 printf("\n"); \ 183 return 0; \ 184 } 185 186 static int parse_general_prms(char *l, struct wl12xx_common *cmn, 187 struct wl12xx_ini *p) 188 { 189 char *name, *val; 190 struct wl1271_ini_general_params *gp = &(p->ini1271.general_params); 191 192 if (split_line(l, &name, &val)) { 193 return 1; 194 } 195 196 COMPARE_N_ADD("TXBiPFEMAutoDetect", l, val, 197 &gp->tx_bip_fem_auto_detect, 1); 198 199 COMPARE_N_ADD("TXBiPFEMManufacturer", l, val, 200 &gp->tx_bip_fem_manufacturer, 1); 201 202 COMPARE_N_ADD("RefClk", l, val, &gp->ref_clock, 1); 203 204 COMPARE_N_ADD("SettlingTime", l, val, &gp->settling_time, 1); 205 206 COMPARE_N_ADD("ClockValidOnWakeup", l, val, 207 &gp->clk_valid_on_wakeup, 1); 208 209 COMPARE_N_ADD("DC2DCMode", l, val, &gp->dc2dc_mode, 1); 210 211 COMPARE_N_ADD("Single_Dual_Band_Solution", l, val, 212 &gp->dual_mode_select, 1); 213 214 if (cmn->dual_mode == DUAL_MODE_UNSET) { 215 cmn->dual_mode = gp->dual_mode_select; 216 } 217 else if (cmn->dual_mode != gp->dual_mode_select) { 218 fprintf(stderr, "Error, FEMs with different dual modes\n"); 219 return 1; 220 } 221 222 COMPARE_N_ADD("Settings", l, val, &gp->general_settings, 1); 223 224 COMPARE_N_ADD("SRState", l, val, &gp->sr_state, 1); 225 226 COMPARE_N_ADD("SRF1", l, val, 227 gp->srf1, WL1271_INI_MAX_SMART_REFLEX_PARAM); 228 229 COMPARE_N_ADD("SRF2", l, val, 230 gp->srf2, WL1271_INI_MAX_SMART_REFLEX_PARAM); 231 232 COMPARE_N_ADD("SRF3", l, val, 233 gp->srf3, WL1271_INI_MAX_SMART_REFLEX_PARAM); 234 235 fprintf(stderr, "Unable to parse: (%s)\n", l); 236 237 return 1; 238 } 239 240 static int parse_general_prms_128x(char *l, struct wl12xx_common *cmn, 241 struct wl12xx_ini *p) 242 { 243 char *name, *val; 244 struct wl128x_ini_general_params *gp = 245 &(p->ini128x.general_params); 246 247 if (split_line(l, &name, &val)) { 248 return 1; 249 } 250 251 COMPARE_N_ADD("TXBiPFEMAutoDetect", l, val, 252 &gp->tx_bip_fem_auto_detect, 1); 253 254 COMPARE_N_ADD("TXBiPFEMManufacturer", l, val, 255 &gp->tx_bip_fem_manufacturer, 1); 256 257 COMPARE_N_ADD("RefClk", l, val, &gp->ref_clock, 1); 258 259 COMPARE_N_ADD("SettlingTime", l, val, &gp->settling_time, 1); 260 261 COMPARE_N_ADD("ClockValidOnWakeup", l, val, 262 &gp->clk_valid_on_wakeup, 1); 263 264 COMPARE_N_ADD("TCXO_Clk", l, val, &gp->tcxo_ref_clock, 1); 265 266 COMPARE_N_ADD("TCXO_SettlingTime", l, val, &gp->tcxo_settling_time, 1); 267 268 COMPARE_N_ADD("TCXO_ClockValidOnWakeup", l, val, 269 &gp->tcxo_valid_on_wakeup, 1); 270 271 COMPARE_N_ADD("TCXO_LDO_Voltage", l, val, 272 &gp->tcxo_ldo_voltage, 1); 273 274 COMPARE_N_ADD("Platform_configuration", l, val, 275 &gp->platform_conf, 1); 276 277 COMPARE_N_ADD("Single_Dual_Band_Solution", l, val, 278 &gp->dual_mode_select, 1); 279 280 if (cmn->dual_mode == DUAL_MODE_UNSET) { 281 cmn->dual_mode = gp->dual_mode_select; 282 } else if (cmn->dual_mode != gp->dual_mode_select) { 283 fprintf(stderr, "Error, FEMs with diferent dual modes\n"); 284 return 1; 285 } 286 287 COMPARE_N_ADD("Settings", l, val, 288 gp->general_settings, WL128X_INI_MAX_SETTINGS_PARAM); 289 290 COMPARE_N_ADD("XTALItrimVal", l, val, &gp->xtal_itrim_val, 1); 291 292 COMPARE_N_ADD("SRState", l, val, &gp->sr_state, 1); 293 294 COMPARE_N_ADD("SRF1", l, val, 295 gp->srf1, WL1271_INI_MAX_SMART_REFLEX_PARAM); 296 297 COMPARE_N_ADD("SRF2", l, val, 298 gp->srf2, WL1271_INI_MAX_SMART_REFLEX_PARAM); 299 300 COMPARE_N_ADD("SRF3", l, val, 301 gp->srf3, WL1271_INI_MAX_SMART_REFLEX_PARAM); 302 303 fprintf(stderr, "Unable to parse: (%s)\n", l); 304 305 return 1; 306 } 307 308 static int parse_band2_prms(char *l, struct wl12xx_ini *p) 309 { 310 char *name, *val; 311 struct wl1271_ini_band_params_2 *gp = 312 &(p->ini1271.stat_radio_params_2); 313 314 if (split_line(l, &name, &val)) { 315 return 1; 316 } 317 318 COMPARE_N_ADD("RxTraceInsertionLoss_2_4G", l, val, 319 &gp->rx_trace_insertion_loss, 1); 320 321 COMPARE_N_ADD("TXTraceLoss_2_4G", l, val, 322 &gp->tx_trace_loss, 1); 323 324 COMPARE_N_ADD("RxRssiAndProcessCompensation_2_4G", l, val, 325 gp->rx_rssi_process_compens, 326 WL1271_INI_RSSI_PROCESS_COMPENS_SIZE); 327 328 fprintf(stderr, "Unable to parse: (%s)\n", l); 329 330 return 1; 331 } 332 333 static int parse_band2_prms_128x(char *l, struct wl12xx_ini *p) 334 { 335 char *name, *val; 336 struct wl128x_ini_band_params_2 *gp = &(p->ini128x.stat_radio_params_2); 337 338 if (split_line(l, &name, &val)) { 339 return 1; 340 } 341 342 COMPARE_N_ADD("RxTraceInsertionLoss_2_4G", l, val, 343 &gp->rx_trace_insertion_loss, 1); 344 345 COMPARE_N_ADD("TxTraceLoss_2_4G", l, val, 346 gp->tx_trace_loss, WL1271_INI_CHANNEL_COUNT_2); 347 348 fprintf(stderr, "Unable to parse: (%s)\n", l); 349 350 return 1; 351 } 352 353 static int parse_band5_prms(char *l, struct wl12xx_ini *p) 354 { 355 char *name, *val; 356 struct wl1271_ini_band_params_5 *gp = 357 &(p->ini1271.stat_radio_params_5); 358 359 if (split_line(l, &name, &val)) { 360 return 1; 361 } 362 363 COMPARE_N_ADD("RxTraceInsertionLoss_5G", l, val, 364 gp->rx_trace_insertion_loss, 7); 365 366 COMPARE_N_ADD("TXTraceLoss_5G", l, val, 367 gp->tx_trace_loss, 7); 368 369 COMPARE_N_ADD("RxRssiAndProcessCompensation_5G", l, val, 370 gp->rx_rssi_process_compens, 371 WL1271_INI_RSSI_PROCESS_COMPENS_SIZE); 372 373 fprintf(stderr, "Unable to parse: (%s)\n", l); 374 375 return 1; 376 } 377 378 static int parse_band5_prms_128x(char *l, struct wl12xx_ini *p) 379 { 380 char *name, *val; 381 struct wl128x_ini_band_params_5 *gp = &(p->ini128x.stat_radio_params_5); 382 383 if (split_line(l, &name, &val)) { 384 return 1; 385 } 386 387 COMPARE_N_ADD("RxTraceInsertionLoss_5G", l, val, 388 gp->rx_trace_insertion_loss, 7); 389 390 COMPARE_N_ADD("TxTraceLoss_5G", l, val, 391 gp->tx_trace_loss, 7); 392 393 fprintf(stderr, "Unable to parse: (%s)\n", l); 394 395 return 1; 396 } 397 398 static int parse_fem0_band2_prms(char *l, struct wl12xx_ini *p) 399 { 400 char *name, *val; 401 struct wl1271_ini_fem_params_2 *gp = 402 &(p->ini1271.dyn_radio_params_2[0].params); 403 404 if (split_line(l, &name, &val)) { 405 return 1; 406 } 407 408 COMPARE_N_ADD2("FEM0_TXBiPReferencePDvoltage_2_4G", l, val, 409 &gp->tx_bip_ref_pd_voltage, 1); 410 411 COMPARE_N_ADD("FEM0_TxBiPReferencePower_2_4G", l, val, 412 &gp->tx_bip_ref_power, 1); 413 414 COMPARE_N_ADD("FEM0_TxBiPOffsetdB_2_4G", l, val, 415 &gp->tx_bip_ref_offset, 1); 416 417 COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Normal", l, val, 418 gp->tx_per_rate_pwr_limits_normal, 419 WL1271_INI_RATE_GROUP_COUNT); 420 421 COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Degraded", l, val, 422 gp->tx_per_rate_pwr_limits_degraded, 423 WL1271_INI_RATE_GROUP_COUNT); 424 425 COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Extreme", l, val, 426 gp->tx_per_rate_pwr_limits_extreme, 427 WL1271_INI_RATE_GROUP_COUNT); 428 429 COMPARE_N_ADD("FEM0_DegradedLowToNormalThr_2_4G", l, val, 430 &gp->degraded_low_to_normal_thr, 1); 431 432 COMPARE_N_ADD("FEM0_NormalToDegradedHighThr_2_4G", l, val, 433 &gp->normal_to_degraded_high_thr, 1); 434 435 COMPARE_N_ADD("FEM0_TxPerChannelPowerLimits_2_4G_11b", l, val, 436 gp->tx_per_chan_pwr_limits_11b, 437 WL1271_INI_CHANNEL_COUNT_2); 438 439 COMPARE_N_ADD("FEM0_TxPerChannelPowerLimits_2_4G_OFDM", l, val, 440 gp->tx_per_chan_pwr_limits_ofdm, 441 WL1271_INI_CHANNEL_COUNT_2); 442 443 COMPARE_N_ADD("FEM0_TxPDVsRateOffsets_2_4G", l, val, 444 gp->tx_pd_vs_rate_offsets, 445 WL1271_INI_RATE_GROUP_COUNT); 446 447 COMPARE_N_ADD("FEM0_TxIbiasTable_2_4G", l, val, 448 gp->tx_ibias, 449 WL1271_INI_RATE_GROUP_COUNT); 450 451 COMPARE_N_ADD("FEM0_RxFemInsertionLoss_2_4G", l, val, 452 &gp->rx_fem_insertion_loss, 1); 453 454 fprintf(stderr, "Unable to parse: (%s)\n", l); 455 456 return 1; 457 } 458 459 static int parse_fem0_band2_prms_128x(char *l, struct wl12xx_ini *p) 460 { 461 char *name, *val; 462 struct wl128x_ini_fem_params_2 *gp = 463 &(p->ini128x.dyn_radio_params_2[0].params); 464 465 if (split_line(l, &name, &val)) { 466 return 1; 467 } 468 469 COMPARE_N_ADD2("FEM0_TxBiPReferencePDvoltage_2_4G", l, val, 470 &gp->tx_bip_ref_pd_voltage, 1); 471 472 COMPARE_N_ADD("FEM0_TxBiPReferencePower_2_4G", l, val, 473 &gp->tx_bip_ref_power, 1); 474 475 COMPARE_N_ADD("FEM0_TxBiPOffsetdB_2_4G", l, val, 476 &gp->tx_bip_ref_offset, 1); 477 478 COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Normal", l, val, 479 gp->tx_per_rate_pwr_limits_normal, 480 WL1271_INI_RATE_GROUP_COUNT); 481 482 COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Degraded", l, val, 483 gp->tx_per_rate_pwr_limits_degraded, 484 WL1271_INI_RATE_GROUP_COUNT); 485 486 COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Extreme", l, val, 487 gp->tx_per_rate_pwr_limits_extreme, 488 WL1271_INI_RATE_GROUP_COUNT); 489 490 COMPARE_N_ADD("FEM0_DegradedLowToNormalThr_2_4G", l, val, 491 &gp->degraded_low_to_normal_thr, 1); 492 493 COMPARE_N_ADD("FEM0_NormalToDegradedHighThr_2_4G", l, val, 494 &gp->normal_to_degraded_high_thr, 1); 495 496 COMPARE_N_ADD("FEM0_TxPerChannelPowerLimits_2_4G_11b", l, val, 497 gp->tx_per_chan_pwr_limits_11b, 498 WL1271_INI_CHANNEL_COUNT_2); 499 500 COMPARE_N_ADD("FEM0_TxPerChannelPowerLimits_2_4G_OFDM", l, val, 501 gp->tx_per_chan_pwr_limits_ofdm, 502 WL1271_INI_CHANNEL_COUNT_2); 503 504 COMPARE_N_ADD("FEM0_TxPDVsRateOffsets_2_4G", l, val, 505 gp->tx_pd_vs_rate_offsets, 506 WL1271_INI_RATE_GROUP_COUNT); 507 508 COMPARE_N_ADD("FEM0_TxPDVsChannelOffsets_2_4G", l, val, 509 gp->tx_pd_vs_chan_offsets, 510 WL1271_INI_CHANNEL_COUNT_2); 511 512 COMPARE_N_ADD("FEM0_TxPDVsTemperature_2_4G", l, val, 513 gp->tx_pd_vs_temperature, 514 WL128X_INI_PD_VS_TEMPERATURE_RANGES); 515 516 COMPARE_N_ADD("FEM0_TxIbiasTable_2_4G", l, val, 517 gp->tx_ibias, 518 WL1271_INI_RATE_GROUP_COUNT); 519 520 COMPARE_N_ADD("FEM0_RxFemInsertionLoss_2_4G", l, val, 521 &gp->rx_fem_insertion_loss, 1); 522 523 fprintf(stderr, "Unable to parse: (%s)\n", l); 524 525 return 1; 526 } 527 528 static int parse_fem1_band2_prms(char *l, struct wl12xx_ini *p) 529 { 530 char *name, *val; 531 struct wl1271_ini_fem_params_2 *gp = 532 &(p->ini1271.dyn_radio_params_2[1].params); 533 534 if (split_line(l, &name, &val)) { 535 return 1; 536 } 537 538 COMPARE_N_ADD2("FEM1_TXBiPReferencePDvoltage_2_4G", l, val, 539 &gp->tx_bip_ref_pd_voltage, 1); 540 541 COMPARE_N_ADD("FEM1_TxBiPReferencePower_2_4G", l, val, 542 &gp->tx_bip_ref_power, 1); 543 544 COMPARE_N_ADD("FEM1_TxBiPOffsetdB_2_4G", l, val, 545 &gp->tx_bip_ref_offset, 1); 546 547 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Normal", l, val, 548 gp->tx_per_rate_pwr_limits_normal, 549 WL1271_INI_RATE_GROUP_COUNT); 550 551 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Degraded", l, val, 552 gp->tx_per_rate_pwr_limits_degraded, 553 WL1271_INI_RATE_GROUP_COUNT); 554 555 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Extreme", l, val, 556 gp->tx_per_rate_pwr_limits_extreme, 557 WL1271_INI_RATE_GROUP_COUNT); 558 559 COMPARE_N_ADD("FEM1_DegradedLowToNormalThr_2_4G", l, val, 560 &gp->degraded_low_to_normal_thr, 1); 561 562 COMPARE_N_ADD("FEM1_NormalToDegradedHighThr_2_4G", l, val, 563 &gp->normal_to_degraded_high_thr, 1); 564 565 COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_2_4G_11b", l, val, 566 gp->tx_per_chan_pwr_limits_11b, 567 WL1271_INI_CHANNEL_COUNT_2); 568 569 COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_2_4G_OFDM", l, val, 570 gp->tx_per_chan_pwr_limits_ofdm, 571 WL1271_INI_CHANNEL_COUNT_2); 572 573 COMPARE_N_ADD("FEM1_TxPDVsRateOffsets_2_4G", l, val, 574 gp->tx_pd_vs_rate_offsets, 575 WL1271_INI_RATE_GROUP_COUNT); 576 577 COMPARE_N_ADD("FEM1_TxIbiasTable_2_4G", l, val, 578 gp->tx_ibias, 579 WL1271_INI_RATE_GROUP_COUNT); 580 581 COMPARE_N_ADD("FEM1_RxFemInsertionLoss_2_4G", l, val, 582 &gp->rx_fem_insertion_loss, 1); 583 584 fprintf(stderr, "Unable to parse: (%s)\n", l); 585 586 return 1; 587 } 588 589 static int parse_fem1_band2_prms_128x(char *l, struct wl12xx_ini *p) 590 { 591 char *name, *val; 592 struct wl128x_ini_fem_params_2 *gp = 593 &(p->ini128x.dyn_radio_params_2[1].params); 594 595 if (split_line(l, &name, &val)) { 596 return 1; 597 } 598 599 COMPARE_N_ADD2("FEM1_TxBiPReferencePDvoltage_2_4G", l, val, 600 &gp->tx_bip_ref_pd_voltage, 1); 601 602 COMPARE_N_ADD("FEM1_TxBiPReferencePower_2_4G", l, val, 603 &gp->tx_bip_ref_power, 1); 604 605 COMPARE_N_ADD("FEM1_TxBiPOffsetdB_2_4G", l, val, 606 &gp->tx_bip_ref_offset, 1); 607 608 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Normal", l, val, 609 gp->tx_per_rate_pwr_limits_normal, 610 WL128X_INI_RATE_GROUP_COUNT); 611 612 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Degraded", l, val, 613 gp->tx_per_rate_pwr_limits_degraded, 614 WL128X_INI_RATE_GROUP_COUNT); 615 616 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Extreme", l, val, 617 gp->tx_per_rate_pwr_limits_extreme, 618 WL128X_INI_RATE_GROUP_COUNT); 619 620 COMPARE_N_ADD("FEM1_DegradedLowToNormalThr_2_4G", l, val, 621 &gp->degraded_low_to_normal_thr, 1); 622 623 COMPARE_N_ADD("FEM1_NormalToDegradedHighThr_2_4G", l, val, 624 &gp->normal_to_degraded_high_thr, 1); 625 626 COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_2_4G_11b", l, val, 627 gp->tx_per_chan_pwr_limits_11b, 628 WL1271_INI_CHANNEL_COUNT_2); 629 630 COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_2_4G_OFDM", l, val, 631 gp->tx_per_chan_pwr_limits_ofdm, 632 WL1271_INI_CHANNEL_COUNT_2); 633 634 COMPARE_N_ADD("FEM1_TxPDVsRateOffsets_2_4G", l, val, 635 gp->tx_pd_vs_rate_offsets, 636 WL128X_INI_RATE_GROUP_COUNT); 637 638 COMPARE_N_ADD("FEM1_TxPDVsChannelOffsets_2_4G", l, val, 639 gp->tx_pd_vs_chan_offsets, 640 WL1271_INI_CHANNEL_COUNT_2); 641 642 COMPARE_N_ADD("FEM1_TxPDVsTemperature_2_4G", l, val, 643 gp->tx_pd_vs_temperature, 644 WL128X_INI_PD_VS_TEMPERATURE_RANGES); 645 646 COMPARE_N_ADD("FEM1_TxIbiasTable_2_4G", l, val, 647 gp->tx_ibias, 648 WL128X_INI_RATE_GROUP_COUNT); 649 650 COMPARE_N_ADD("FEM1_RxFemInsertionLoss_2_4G", l, val, 651 &gp->rx_fem_insertion_loss, 1); 652 653 fprintf(stderr, "Unable to parse: (%s)\n", l); 654 655 return 1; 656 } 657 658 static int parse_fem1_band5_prms(char *l, struct wl12xx_ini *p) 659 { 660 char *name, *val; 661 struct wl1271_ini_fem_params_5 *gp = 662 &(p->ini1271.dyn_radio_params_5[1].params); 663 664 if (split_line(l, &name, &val)) { 665 return 1; 666 } 667 668 COMPARE_N_ADD2("FEM1_TXBiPReferencePDvoltage_5G", l, val, 669 gp->tx_bip_ref_pd_voltage, WL1271_INI_SUB_BAND_COUNT_5); 670 671 COMPARE_N_ADD("FEM1_TxBiPReferencePower_5G", l, val, 672 gp->tx_bip_ref_power, WL1271_INI_SUB_BAND_COUNT_5); 673 674 COMPARE_N_ADD("FEM1_TxBiPOffsetdB_5G", l, val, 675 gp->tx_bip_ref_offset, WL1271_INI_SUB_BAND_COUNT_5); 676 677 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Normal", l, val, 678 gp->tx_per_rate_pwr_limits_normal, 679 WL1271_INI_RATE_GROUP_COUNT); 680 681 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Degraded", l, val, 682 gp->tx_per_rate_pwr_limits_degraded, 683 WL1271_INI_RATE_GROUP_COUNT); 684 685 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Extreme", l, val, 686 gp->tx_per_rate_pwr_limits_extreme, 687 WL1271_INI_RATE_GROUP_COUNT); 688 689 COMPARE_N_ADD("FEM1_DegradedLowToNormalThr_5G", l, val, 690 &gp->degraded_low_to_normal_thr, 1); 691 692 COMPARE_N_ADD("FEM1_NormalToDegradedHighThr_5G", l, val, 693 &gp->normal_to_degraded_high_thr, 1); 694 695 COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_5G_OFDM", l, val, 696 gp->tx_per_chan_pwr_limits_ofdm, 697 WL1271_INI_CHANNEL_COUNT_5); 698 699 COMPARE_N_ADD("FEM1_TxPDVsRateOffsets_5G", l, val, 700 gp->tx_pd_vs_rate_offsets, 701 WL1271_INI_RATE_GROUP_COUNT); 702 703 COMPARE_N_ADD("FEM1_TxIbiasTable_5G", l, val, 704 gp->tx_ibias, 705 WL1271_INI_RATE_GROUP_COUNT); 706 707 COMPARE_N_ADD("FEM1_RxFemInsertionLoss_5G", l, val, 708 gp->rx_fem_insertion_loss, WL1271_INI_SUB_BAND_COUNT_5); 709 710 fprintf(stderr, "Unable to parse: (%s)\n", l); 711 712 return 1; 713 } 714 715 static int parse_fem1_band5_prms_128x(char *l, struct wl12xx_ini *p) 716 { 717 char *name, *val; 718 struct wl128x_ini_fem_params_5 *gp = 719 &(p->ini128x.dyn_radio_params_5[1].params); 720 721 if (split_line(l, &name, &val)) { 722 return 1; 723 } 724 725 COMPARE_N_ADD2("FEM1_TxBiPReferencePDvoltage_5G", l, val, 726 gp->tx_bip_ref_pd_voltage, WL1271_INI_SUB_BAND_COUNT_5); 727 728 COMPARE_N_ADD("FEM1_TxBiPReferencePower_5G", l, val, 729 gp->tx_bip_ref_power, WL1271_INI_SUB_BAND_COUNT_5); 730 731 COMPARE_N_ADD("FEM1_TxBiPOffsetdB_5G", l, val, 732 gp->tx_bip_ref_offset, WL1271_INI_SUB_BAND_COUNT_5); 733 734 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Normal", l, val, 735 gp->tx_per_rate_pwr_limits_normal, 736 WL128X_INI_RATE_GROUP_COUNT); 737 738 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Degraded", l, val, 739 gp->tx_per_rate_pwr_limits_degraded, 740 WL128X_INI_RATE_GROUP_COUNT); 741 742 COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Extreme", l, val, 743 gp->tx_per_rate_pwr_limits_extreme, 744 WL128X_INI_RATE_GROUP_COUNT); 745 746 COMPARE_N_ADD("FEM1_DegradedLowToNormalThr_5G", l, val, 747 &gp->degraded_low_to_normal_thr, 1); 748 749 COMPARE_N_ADD("FEM1_NormalToDegradedHighThr_5G", l, val, 750 &gp->normal_to_degraded_high_thr, 1); 751 752 COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_5G_OFDM", l, val, 753 gp->tx_per_chan_pwr_limits_ofdm, 754 WL1271_INI_CHANNEL_COUNT_5); 755 756 COMPARE_N_ADD("FEM1_TxPDVsRateOffsets_5G", l, val, 757 gp->tx_pd_vs_rate_offsets, 758 WL128X_INI_RATE_GROUP_COUNT); 759 760 COMPARE_N_ADD("FEM1_TxPDVsChannelOffsets_5G", l, val, 761 gp->tx_pd_vs_chan_offsets, 762 WL1271_INI_CHANNEL_COUNT_5); 763 764 COMPARE_N_ADD("FEM1_TxPDVsTemperature_5G", l, val, 765 gp->tx_pd_vs_temperature, 766 WL1271_INI_SUB_BAND_COUNT_5 * WL128X_INI_PD_VS_TEMPERATURE_RANGES); 767 768 COMPARE_N_ADD("FEM1_TxIbiasTable_5G", l, val, 769 gp->tx_ibias, 770 WL128X_INI_RATE_GROUP_COUNT); 771 772 COMPARE_N_ADD("FEM1_RxFemInsertionLoss_5G", l, val, 773 gp->rx_fem_insertion_loss, WL1271_INI_SUB_BAND_COUNT_5); 774 775 fprintf(stderr, "Unable to parse: (%s)\n", l); 776 777 return 1; 778 } 779 780 static int parse_fem_prms_128x(char *l, struct wl12xx_ini *p) 781 { 782 char *name, *val; 783 struct wl128x_ini *gp = &p->ini128x; 784 785 if (split_line(l, &name, &val)) { 786 return 1; 787 } 788 789 COMPARE_N_ADD("FemVendorAndOptions", l, val, 790 &gp->fem_vendor_and_options, 1); 791 792 fprintf(stderr, "Unable to parse: (%s)\n", l); 793 794 return 1; 795 } 796 797 static int find_section(const char *l, enum wl1271_ini_section *st, int *cntr, 798 enum wl12xx_arch arch) 799 { 800 if (strncmp("TXBiPFEMAutoDetect", l, 18) == 0) { 801 *st = GENERAL_PRMS; 802 if (arch == WL128X_ARCH) { 803 *cntr = 17; 804 } else { 805 *cntr = 12; 806 } 807 808 return 0; 809 } 810 811 if (strncmp("RxTraceInsertionLoss_2_4G", l, 25) == 0) { 812 *st = BAND2_PRMS; 813 if (arch == WL128X_ARCH){ 814 *cntr = 2; 815 } else { 816 *cntr = 3; 817 } 818 819 return 0; 820 } 821 822 if (strncmp("FemVendorAndOptions", l, 19) == 0) { 823 *st = FEM_PRMS; 824 *cntr = 1; 825 return 0; 826 } 827 828 if (strncmp("RxTraceInsertionLoss_5G", l, 23) == 0) { 829 *st = BAND5_PRMS; 830 if (arch == WL128X_ARCH) { 831 *cntr = 2; 832 } else { 833 *cntr = 3; 834 } 835 836 return 0; 837 } 838 839 if (strncmp("FEM0_TXBiPReferencePDvoltage_2_4G", l, 33) == 0 || 840 strncmp("FEM0_TxBiPReferencePDvoltage_2_4G", l, 33) == 0) { 841 *st = FEM0_BAND2_PRMS; 842 if (arch == WL128X_ARCH) { 843 *cntr = 15; 844 } else { 845 *cntr = 13; 846 } 847 848 return 0; 849 } 850 851 if (strncmp("FEM1_TXBiPReferencePDvoltage_2_4G", l, 33) == 0 || 852 strncmp("FEM1_TxBiPReferencePDvoltage_2_4G", l, 33) == 0) { 853 *st = FEM1_BAND2_PRMS; 854 if (arch == WL128X_ARCH) { 855 *cntr = 15; 856 } else { 857 *cntr = 13; 858 } 859 860 return 0; 861 } 862 863 if (strncmp("FEM1_TXBiPReferencePDvoltage_5G", l, 31) == 0 || 864 strncmp("FEM1_TxBiPReferencePDvoltage_5G", l, 31) == 0) { 865 *st = FEM1_BAND5_PRMS; 866 if (arch == WL128X_ARCH) { 867 *cntr = 14; 868 } else { 869 *cntr = 12; 870 } 871 872 return 0; 873 } 874 875 return 1; 876 } 877 878 static int ini_parse_line(char *l, int nbr, struct wl12xx_common *cmn) 879 { 880 static enum wl1271_ini_section status; 881 static int cntr; 882 883 if (!cntr && find_section(l, &status, &cntr, cmn->arch)) { 884 fprintf(stderr, "Uknown ini section %s\n", l); 885 return 1; 886 } 887 888 switch (status) { 889 case GENERAL_PRMS: /* general parameters */ 890 cntr--; 891 return cmn->parse_ops->prs_general_prms(l, cmn, &cmn->ini); 892 case FEM_PRMS: /* FEM parameters */ 893 if (cmn->arch == WL1271_ARCH) { 894 fprintf(stderr, "The parameter not from 127x architecture\n"); 895 return 1; 896 } 897 cntr--; 898 return parse_fem_prms_128x(l, &cmn->ini); 899 case BAND2_PRMS: /* band 2.4GHz parameters */ 900 cntr--; 901 return cmn->parse_ops->prs_band2_prms(l, &cmn->ini); 902 case BAND5_PRMS: /* band 5GHz parameters */ 903 cntr--; 904 return cmn->parse_ops->prs_band5_prms(l, &cmn->ini); 905 case FEM0_BAND2_PRMS: /* FEM0 band 2.4GHz parameters */ 906 cntr--; 907 return cmn->parse_ops->prs_fem0_band2_prms(l, &cmn->ini); 908 case FEM1_BAND2_PRMS: /* FEM1 band 2.4GHz parameters */ 909 cntr--; 910 return cmn->parse_ops->prs_fem1_band2_prms(l, &cmn->ini); 911 case FEM1_BAND5_PRMS: /* FEM1 band 5GHz parameters */ 912 cntr--; 913 return cmn->parse_ops->prs_fem1_band5_prms(l, &cmn->ini); 914 case UKNOWN_SECTION: 915 /* added because of compilation warning. handeled in find_section() */ 916 break; 917 } 918 919 return 1; 920 } 921 922 #if 0 923 static void ini_dump(struct wl1271_ini *ini) 924 { 925 int i; 926 927 printf("\n"); 928 printf("General params:\n"); 929 printf("ref clock: %02X\n", 930 ini->general_params.ref_clock); 931 printf("settling time: %02X\n", 932 ini->general_params.settling_time); 933 printf("clk valid on wakeup: %02X\n", 934 ini->general_params.clk_valid_on_wakeup); 935 printf("dc2dc mode: %02X\n", 936 ini->general_params.dc2dc_mode); 937 printf("dual band mode: %02X\n", 938 ini->general_params.dual_mode_select); 939 printf("tx bip fem auto detect: %02X\n", 940 ini->general_params.tx_bip_fem_auto_detect); 941 printf("tx bip fem manufacturer: %02X\n", 942 ini->general_params.tx_bip_fem_manufacturer); 943 printf("general settings: %02X\n", 944 ini->general_params.general_settings); 945 printf("sr state: %02X\n", 946 ini->general_params.sr_state); 947 948 printf("srf1:"); 949 for (i = 0; i < WL1271_INI_MAX_SMART_REFLEX_PARAM; i++) 950 printf(" %02X", ini->general_params.srf1[i]); 951 printf("\n"); 952 953 printf("srf2:"); 954 for (i = 0; i < WL1271_INI_MAX_SMART_REFLEX_PARAM; i++) 955 printf(" %02X", ini->general_params.srf2[i]); 956 printf("\n"); 957 958 printf("srf3:"); 959 for (i = 0; i < WL1271_INI_MAX_SMART_REFLEX_PARAM; i++) 960 printf(" %02X", ini->general_params.srf3[i]); 961 printf("\n"); 962 963 printf("Static 2.4 band params:\n"); 964 965 printf("rx trace insertion loss: %02X\n", 966 ini->stat_radio_params_2.rx_trace_insertion_loss); 967 968 printf("rx rssi n process compensation:"); 969 for (i = 0; i < WL1271_INI_RSSI_PROCESS_COMPENS_SIZE; i++) 970 printf(" %02X", 971 ini->stat_radio_params_2.rx_rssi_process_compens[i]); 972 printf("\n"); 973 974 printf("tx trace: %02X\n", 975 ini->stat_radio_params_2.tx_trace_loss); 976 977 printf("Dynamic 2.4 band params for FEM\n"); 978 979 printf("Static 5 band params:\n"); 980 981 printf("rx trace insertion loss:"); 982 for (i = 0; i < WL1271_INI_SUB_BAND_COUNT_5; i++) 983 printf(" %02X", 984 ini->stat_radio_params_5.rx_rssi_process_compens[i]); 985 printf("\n"); 986 987 printf("rx rssi n process compensation:"); 988 for (i = 0; i < WL1271_INI_RSSI_PROCESS_COMPENS_SIZE; i++) 989 printf(" %02X", 990 ini->stat_radio_params_5.rx_rssi_process_compens[i]); 991 printf("\n"); 992 993 printf("tx trace:"); 994 for (i = 0; i < WL1271_INI_SUB_BAND_COUNT_5; i++) 995 printf(" %02X", 996 ini->stat_radio_params_5.tx_trace_loss[i]); 997 printf("\n"); 998 999 printf("Dynamic 5 band params for FEM\n"); 1000 1001 } 1002 #endif 1003 1004 static struct wl12xx_parse_ops wl1271_parse_ops = { 1005 .prs_general_prms = parse_general_prms, 1006 .prs_band2_prms = parse_band2_prms, 1007 .prs_band5_prms = parse_band5_prms, 1008 .prs_fem0_band2_prms = parse_fem0_band2_prms, 1009 .prs_fem1_band2_prms = parse_fem1_band2_prms, 1010 .prs_fem1_band5_prms = parse_fem1_band5_prms, 1011 }; 1012 1013 static struct wl12xx_parse_ops wl128x_parse_ops = { 1014 .prs_general_prms = parse_general_prms_128x, 1015 .prs_band2_prms = parse_band2_prms_128x, 1016 .prs_band5_prms = parse_band5_prms_128x, 1017 .prs_fem0_band2_prms = parse_fem0_band2_prms_128x, 1018 .prs_fem1_band2_prms = parse_fem1_band2_prms_128x, 1019 .prs_fem1_band5_prms = parse_fem1_band5_prms_128x, 1020 }; 1021 1022 int nvs_get_arch(int file_size, struct wl12xx_common *cmn) 1023 { 1024 enum wl12xx_arch arch = UNKNOWN_ARCH; 1025 1026 switch (file_size) { 1027 case WL127X_NVS_FILE_SZ: 1028 arch = WL1271_ARCH; 1029 cmn->parse_ops = &wl1271_parse_ops; 1030 break; 1031 case WL128X_NVS_FILE_SZ: 1032 arch = WL128X_ARCH; 1033 cmn->parse_ops = &wl128x_parse_ops; 1034 break; 1035 } 1036 1037 if (cmn->arch != UNKNOWN_ARCH && cmn->arch != arch) { 1038 cmn->parse_ops = NULL; 1039 return 1; 1040 } 1041 1042 cmn->arch = arch; 1043 1044 return 0; 1045 } 1046 1047 static int ini_get_arch(FILE *f, struct wl12xx_common *cmn) 1048 { 1049 char buf[1024], *pos; 1050 int line = 0; 1051 enum wl12xx_arch arch = UNKNOWN_ARCH; 1052 1053 while (ini_get_line(buf, sizeof(buf), f, &line, &pos)) { 1054 if (strncmp("TCXO_Clk", pos, 8) == 0) { 1055 arch = WL128X_ARCH; 1056 break; 1057 } 1058 } 1059 1060 if (arch == UNKNOWN_ARCH) { 1061 arch = WL1271_ARCH; 1062 } 1063 1064 if (cmn->arch != UNKNOWN_ARCH && cmn->arch != arch) { 1065 return 1; 1066 } 1067 1068 cmn->arch = arch; 1069 1070 if (cmn->arch == WL1271_ARCH) { 1071 cmn->parse_ops = &wl1271_parse_ops; 1072 } else { 1073 cmn->parse_ops = &wl128x_parse_ops; 1074 } 1075 1076 fseek(f, 0L, SEEK_SET); 1077 1078 return 0; 1079 } 1080 1081 int read_ini(const char *filename, struct wl12xx_common *cmn) 1082 { 1083 FILE *f; 1084 char buf[1024], *pos; 1085 int ret = 0, line = 0; 1086 1087 f = fopen(filename, "r"); 1088 if (f == NULL) { 1089 fprintf(stderr, "Unable to open file %s (%s)\n", 1090 filename, strerror(errno)); 1091 return 1; 1092 } 1093 1094 /* check if it 127x or 128x */ 1095 if (ini_get_arch(f, cmn)) { 1096 fprintf(stderr, "Unable to define wireless architecture\n"); 1097 ret = 1; 1098 goto out; 1099 } 1100 1101 /* start parsing */ 1102 while (ini_get_line(buf, sizeof(buf), f, &line, &pos)) { 1103 ret = ini_parse_line(pos, line, cmn); 1104 if (ret) break; 1105 } 1106 1107 out: 1108 fclose(f); 1109 #if 0 1110 ini_dump(ini); 1111 #endif 1112 return ret; 1113 } 1114