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 SECTION(plt); 31 32 static void str2mac(unsigned char *pmac, char *pch) 33 { 34 int i; 35 36 for (i = 0; i < MAC_ADDR_LEN; i++) { 37 pmac[i] = (unsigned char)strtoul(pch, &pch, 16); 38 pch++; 39 } 40 } 41 42 static int plt_power_mode(struct nl80211_state *state, struct nl_cb *cb, 43 struct nl_msg *msg, int argc, char **argv) 44 { 45 struct nlattr *key; 46 unsigned int pmode; 47 48 if (argc != 1) { 49 fprintf(stderr, "%s> Missing arguments\n", __func__); 50 return 2; 51 } 52 53 if (strcmp(argv[0], "on") == 0) { 54 pmode = 1; 55 } else if (strcmp(argv[0], "off") == 0) { 56 pmode = 0; 57 } else { 58 fprintf(stderr, "%s> Invalid parameter\n", __func__); 59 return 2; 60 } 61 62 key = nla_nest_start(msg, NL80211_ATTR_TESTDATA); 63 if (!key) { 64 fprintf(stderr, "%s> fail to nla_nest_start()\n", __func__); 65 return 1; 66 } 67 68 NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_SET_PLT_MODE); 69 NLA_PUT_U32(msg, WL1271_TM_ATTR_PLT_MODE, pmode); 70 71 nla_nest_end(msg, key); 72 73 return 0; 74 75 nla_put_failure: 76 fprintf(stderr, "%s> building message failed\n", __func__); 77 return 2; 78 } 79 80 COMMAND(plt, power_mode, "<on|off>", 81 NL80211_CMD_TESTMODE, 0, CIB_NETDEV, plt_power_mode, 82 "Set PLT power mode\n"); 83 84 static int plt_tune_channel(struct nl80211_state *state, struct nl_cb *cb, 85 struct nl_msg *msg, int argc, char **argv) 86 { 87 struct nlattr *key; 88 struct wl1271_cmd_cal_channel_tune prms; 89 90 if (argc < 1 || argc > 2) { 91 return 1; 92 } 93 94 prms.test.id = TEST_CMD_CHANNEL_TUNE; 95 prms.band = (unsigned char)atoi(argv[0]); 96 prms.channel = (unsigned char)atoi(argv[1]); 97 98 key = nla_nest_start(msg, NL80211_ATTR_TESTDATA); 99 if (!key) { 100 fprintf(stderr, "fail to nla_nest_start()\n"); 101 return 1; 102 } 103 104 NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_TEST); 105 NLA_PUT(msg, WL1271_TM_ATTR_DATA, 106 sizeof(struct wl1271_cmd_cal_channel_tune), 107 &prms); 108 109 nla_nest_end(msg, key); 110 111 return 0; 112 113 nla_put_failure: 114 fprintf(stderr, "%s> building message failed\n", __func__); 115 return 2; 116 } 117 118 COMMAND(plt, tune_channel, "<band> <channel>", 119 NL80211_CMD_TESTMODE, 0, CIB_NETDEV, plt_tune_channel, 120 "Set band and channel for PLT\n"); 121 122 static int plt_ref_point(struct nl80211_state *state, struct nl_cb *cb, 123 struct nl_msg *msg, int argc, char **argv) 124 { 125 struct nlattr *key; 126 struct wl1271_cmd_cal_update_ref_point prms; 127 128 if (argc < 1 || argc > 3){ 129 return 1; 130 } 131 132 prms.test.id = TEST_CMD_UPDATE_PD_REFERENCE_POINT; 133 prms.ref_detector = atoi(argv[0]); 134 prms.ref_power = atoi(argv[1]); 135 prms.sub_band = atoi(argv[2]); 136 137 key = nla_nest_start(msg, NL80211_ATTR_TESTDATA); 138 if (!key) { 139 fprintf(stderr, "fail to nla_nest_start()\n"); 140 return 1; 141 } 142 143 NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_TEST); 144 NLA_PUT(msg, WL1271_TM_ATTR_DATA, sizeof(prms), &prms); 145 146 nla_nest_end(msg, key); 147 148 return 0; 149 150 nla_put_failure: 151 fprintf(stderr, "%s> building message failed\n", __func__); 152 return 2; 153 } 154 155 COMMAND(plt, ref_point, "<voltage> <power> <subband>", 156 NL80211_CMD_TESTMODE, 0, CIB_NETDEV, plt_ref_point, 157 "Set reference point for PLT\n"); 158 159 static int calib_valid_handler(struct nl_msg *msg, void *arg) 160 { 161 struct nlattr *tb[NL80211_ATTR_MAX + 1]; 162 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 163 struct nlattr *td[WL1271_TM_ATTR_MAX + 1]; 164 struct wl1271_cmd_cal_p2g *prms; 165 #if 0 166 int i; unsigned char *pc; 167 #endif 168 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 169 genlmsg_attrlen(gnlh, 0), NULL); 170 171 if (!tb[NL80211_ATTR_TESTDATA]) { 172 fprintf(stderr, "no data!\n"); 173 return NL_SKIP; 174 } 175 176 nla_parse(td, WL1271_TM_ATTR_MAX, nla_data(tb[NL80211_ATTR_TESTDATA]), 177 nla_len(tb[NL80211_ATTR_TESTDATA]), NULL); 178 179 prms = (struct wl1271_cmd_cal_p2g *)nla_data(td[WL1271_TM_ATTR_DATA]); 180 181 if (prms->radio_status) { 182 fprintf(stderr, "Fail to calibrate ith radio status (%d)\n", 183 (signed short)prms->radio_status); 184 return 2; 185 } 186 #if 0 187 printf("%s> id %04x status %04x\ntest id %02x ver %08x len %04x=%d\n", 188 __func__, 189 prms->header.id, prms->header.status, prms->test.id, 190 prms->ver, prms->len, prms->len); 191 192 pc = (unsigned char *)prms->buf; 193 printf("++++++++++++++++++++++++\n"); 194 for (i = 0; i < prms->len; i++) { 195 if (i%0xf == 0) 196 printf("\n"); 197 198 printf("%02x ", *(unsigned char *)pc); 199 pc += 1; 200 } 201 printf("++++++++++++++++++++++++\n"); 202 #endif 203 if (prepare_nvs_file(prms, arg)) { 204 fprintf(stderr, "Fail to prepare calibrated NVS file\n"); 205 return 2; 206 } 207 #if 0 208 printf("\n\tThe NVS file (%s) is ready\n\tCopy it to %s and " 209 "reboot the system\n\n", 210 NEW_NVS_NAME, CURRENT_NVS_NAME); 211 #endif 212 return NL_SKIP; 213 } 214 215 static int plt_tx_bip(struct nl80211_state *state, struct nl_cb *cb, 216 struct nl_msg *msg, int argc, char **argv) 217 { 218 struct nlattr *key; 219 struct wl1271_cmd_cal_p2g prms; 220 int i; 221 char nvs_path[PATH_MAX]; 222 223 if (argc < 8) { 224 fprintf(stderr, "%s> Missing arguments\n", __func__); 225 return 2; 226 } 227 228 if (argc > 8) { 229 strncpy(nvs_path, argv[8], strlen(argv[8])); 230 } else { 231 nvs_path[0] = '\0'; 232 } 233 234 memset(&prms, 0, sizeof(struct wl1271_cmd_cal_p2g)); 235 236 prms.test.id = TEST_CMD_P2G_CAL; 237 for (i = 0; i < 8; i++) { 238 prms.sub_band_mask |= (atoi(argv[i]) & 0x1)<<i; 239 } 240 241 key = nla_nest_start(msg, NL80211_ATTR_TESTDATA); 242 if (!key) { 243 fprintf(stderr, "fail to nla_nest_start()\n"); 244 return 1; 245 } 246 247 NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_TEST); 248 NLA_PUT(msg, WL1271_TM_ATTR_DATA, sizeof(prms), &prms); 249 NLA_PUT_U8(msg, WL1271_TM_ATTR_ANSWER, 1); 250 251 nla_nest_end(msg, key); 252 253 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, calib_valid_handler, nvs_path); 254 255 return 0; 256 257 nla_put_failure: 258 fprintf(stderr, "%s> building message failed\n", __func__); 259 return 2; 260 } 261 262 COMMAND(plt, tx_bip, 263 "<0|1> <0|1> <0|1> <0|1> <0|1> <0|1> <0|1> <0|1> [<nvs file>]", 264 NL80211_CMD_TESTMODE, 0, CIB_NETDEV, plt_tx_bip, 265 "Do calibrate\n"); 266 267 static int plt_tx_tone(struct nl80211_state *state, struct nl_cb *cb, 268 struct nl_msg *msg, int argc, char **argv) 269 { 270 struct nlattr *key; 271 struct wl1271_cmd_cal_tx_tone prms; 272 273 if (argc < 2) { 274 fprintf(stderr, "%s> Missing arguments\n", __func__); 275 return 2; 276 } 277 278 memset(&prms, 0, sizeof(struct wl1271_cmd_cal_tx_tone)); 279 280 prms.test.id = TEST_CMD_TELEC; 281 prms.power = atoi(argv[0]); 282 prms.tone_type = atoi(argv[1]); 283 284 key = nla_nest_start(msg, NL80211_ATTR_TESTDATA); 285 if (!key) { 286 fprintf(stderr, "fail to nla_nest_start()\n"); 287 return 1; 288 } 289 290 NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_TEST); 291 NLA_PUT(msg, WL1271_TM_ATTR_DATA, sizeof(prms), &prms); 292 293 nla_nest_end(msg, key); 294 295 return 0; 296 297 nla_put_failure: 298 fprintf(stderr, "%s> building message failed\n", __func__); 299 return 2; 300 } 301 302 COMMAND(plt, tx_tone, "<power> <tone type>", 303 NL80211_CMD_TESTMODE, 0, CIB_NETDEV, plt_tx_tone, 304 "Do command tx_tone to transmit a tone\n"); 305 306 static int plt_tx_cont(struct nl80211_state *state, struct nl_cb *cb, 307 struct nl_msg *msg, int argc, char **argv) 308 { 309 struct nlattr *key; 310 struct wl1271_cmd_pkt_params prms = { 311 .src_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 312 }; 313 314 if (argc != 15) { 315 return 1; 316 } 317 #if 0 318 printf("%s> delay (%d) rate (%08x) size (%d) amount (%d) power (%d) " 319 "seed (%d) pkt_mode (%d) DCF (%d) GI (%d) preamble (%d) type " 320 "(%d) scramble (%d) CLPC (%d), SeqNbrMode (%d) DestMAC (%s)\n", 321 __func__, 322 atoi(argv[0]), atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), 323 atoi(argv[4]), atoi(argv[5]), atoi(argv[6]), atoi(argv[7]), 324 atoi(argv[8]), atoi(argv[9]), atoi(argv[10]), atoi(argv[11]), 325 atoi(argv[12]), atoi(argv[13]), argv[14] 326 ); 327 #endif 328 memset((void *)&prms, 0, sizeof(struct wl1271_cmd_pkt_params)); 329 330 prms.test.id = TEST_CMD_FCC; 331 prms.delay = atoi(argv[0]); 332 prms.rate = atoi(argv[1]); 333 prms.size = (unsigned short)atoi(argv[2]); 334 prms.amount = (unsigned short)atoi(argv[3]); 335 prms.power = atoi(argv[4]); 336 prms.seed = (unsigned short)atoi(argv[5]); 337 prms.pkt_mode = (unsigned char)atoi(argv[6]); 338 prms.dcf_enable = (unsigned char)atoi(argv[7]); 339 prms.g_interval = (unsigned char)atoi(argv[8]); 340 prms.preamble = (unsigned char)atoi(argv[9]); 341 prms.type = (unsigned char)atoi(argv[10]); 342 prms.scramble = (unsigned char)atoi(argv[11]); 343 prms.clpc_enable = (unsigned char)atoi(argv[12]); 344 prms.seq_nbr_mode = (unsigned char)atoi(argv[13]); 345 str2mac(prms.dst_mac, argv[14]); 346 347 if (get_mac_addr(0, prms.src_mac)) { 348 fprintf(stderr, "fail to get MAC addr\n"); 349 } 350 351 printf("%02X:%02X:%02X:%02X:%02X:%02X\n", 352 prms.src_mac[0], prms.src_mac[1], prms.src_mac[2], 353 prms.src_mac[3], prms.src_mac[4], prms.src_mac[5]); 354 355 key = nla_nest_start(msg, NL80211_ATTR_TESTDATA); 356 if (!key) { 357 fprintf(stderr, "fail to nla_nest_start()\n"); 358 return 1; 359 } 360 361 NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_TEST); 362 NLA_PUT(msg, WL1271_TM_ATTR_DATA, sizeof(prms), &prms); 363 364 nla_nest_end(msg, key); 365 366 return 0; 367 368 nla_put_failure: 369 fprintf(stderr, "%s> building message failed\n", __func__); 370 return 2; 371 } 372 373 COMMAND(plt, tx_cont, "<delay> <rate> <size> <amount> <power>\n\t\t<seed> " 374 "<pkt mode> <DC on/off> <gi> <preamble>\n\t\t<type> <scramble> " 375 "<clpc> <seq nbr mode> <dest mac>", 376 NL80211_CMD_TESTMODE, 0, CIB_NETDEV, plt_tx_cont, 377 "Start Tx Cont\n"); 378 379 static int plt_tx_stop(struct nl80211_state *state, struct nl_cb *cb, 380 struct nl_msg *msg, int argc, char **argv) 381 { 382 struct nlattr *key; 383 struct wl1271_cmd_pkt_params prms; 384 385 prms.test.id = TEST_CMD_STOP_TX; 386 387 key = nla_nest_start(msg, NL80211_ATTR_TESTDATA); 388 if (!key) { 389 fprintf(stderr, "fail to nla_nest_start()\n"); 390 return 1; 391 } 392 393 NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_TEST); 394 NLA_PUT(msg, WL1271_TM_ATTR_DATA, sizeof(prms), &prms); 395 396 nla_nest_end(msg, key); 397 398 return 0; 399 400 nla_put_failure: 401 fprintf(stderr, "%s> building message failed\n", __func__); 402 return 2; 403 } 404 405 COMMAND(plt, tx_stop, NULL, 406 NL80211_CMD_TESTMODE, 0, CIB_NETDEV, plt_tx_stop, 407 "Stop Tx Cont\n"); 408 409 static int plt_start_rx_statcs(struct nl80211_state *state, struct nl_cb *cb, 410 struct nl_msg *msg, int argc, char **argv) 411 { 412 struct nlattr *key; 413 struct wl1271_cmd_pkt_params prms; 414 415 prms.test.id = TEST_CMD_RX_STAT_START; 416 417 key = nla_nest_start(msg, NL80211_ATTR_TESTDATA); 418 if (!key) { 419 fprintf(stderr, "%s> fail to nla_nest_start()\n", __func__); 420 return 1; 421 } 422 423 NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_TEST); 424 NLA_PUT(msg, WL1271_TM_ATTR_DATA, sizeof(prms), &prms); 425 426 nla_nest_end(msg, key); 427 428 return 0; 429 430 nla_put_failure: 431 fprintf(stderr, "%s> building message failed\n", __func__); 432 return 2; 433 } 434 435 COMMAND(plt, start_rx_statcs, NULL, 436 NL80211_CMD_TESTMODE, 0, CIB_NETDEV, plt_start_rx_statcs, 437 "Start Rx statistics collection\n"); 438 439 static int plt_stop_rx_statcs(struct nl80211_state *state, struct nl_cb *cb, 440 struct nl_msg *msg, int argc, char **argv) 441 { 442 struct nlattr *key; 443 struct wl1271_cmd_pkt_params prms; 444 445 prms.test.id = TEST_CMD_RX_STAT_STOP; 446 447 key = nla_nest_start(msg, NL80211_ATTR_TESTDATA); 448 if (!key) { 449 fprintf(stderr, "%s> fail to nla_nest_start()\n", __func__); 450 return 1; 451 } 452 453 NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_TEST); 454 NLA_PUT(msg, WL1271_TM_ATTR_DATA, sizeof(prms), &prms); 455 456 nla_nest_end(msg, key); 457 458 return 0; 459 460 nla_put_failure: 461 fprintf(stderr, "%s> building message failed\n", __func__); 462 return 2; 463 } 464 465 COMMAND(plt, stop_rx_statcs, NULL, 466 NL80211_CMD_TESTMODE, 0, CIB_NETDEV, plt_stop_rx_statcs, 467 "Stop Rx statistics collection\n"); 468 469 static int plt_reset_rx_statcs(struct nl80211_state *state, struct nl_cb *cb, 470 struct nl_msg *msg, int argc, char **argv) 471 { 472 struct nlattr *key; 473 struct wl1271_cmd_pkt_params prms; 474 475 prms.test.id = TEST_CMD_RX_STAT_RESET; 476 477 key = nla_nest_start(msg, NL80211_ATTR_TESTDATA); 478 if (!key) { 479 fprintf(stderr, "%s> fail to nla_nest_start()\n", __func__); 480 return 1; 481 } 482 483 NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_TEST); 484 NLA_PUT(msg, WL1271_TM_ATTR_DATA, sizeof(prms), &prms); 485 486 nla_nest_end(msg, key); 487 488 return 0; 489 490 nla_put_failure: 491 fprintf(stderr, "%s> building message failed\n", __func__); 492 return 2; 493 } 494 495 COMMAND(plt, reset_rx_statcs, NULL, 496 NL80211_CMD_TESTMODE, 0, CIB_NETDEV, plt_reset_rx_statcs, 497 "Reset Rx statistics collection\n"); 498 499 static int display_rx_statcs(struct nl_msg *msg, void *arg) 500 { 501 struct nlattr *tb[NL80211_ATTR_MAX + 1]; 502 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 503 struct nlattr *td[WL1271_TM_ATTR_MAX + 1]; 504 struct wl1271_radio_rx_statcs *prms; 505 506 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 507 genlmsg_attrlen(gnlh, 0), NULL); 508 509 if (!tb[NL80211_ATTR_TESTDATA]) { 510 fprintf(stderr, "no data!\n"); 511 return NL_SKIP; 512 } 513 514 nla_parse(td, WL1271_TM_ATTR_MAX, nla_data(tb[NL80211_ATTR_TESTDATA]), 515 nla_len(tb[NL80211_ATTR_TESTDATA]), NULL); 516 517 prms = 518 (struct wl1271_radio_rx_statcs *) 519 nla_data(td[WL1271_TM_ATTR_DATA]); 520 521 printf("\n\tTotal number of pkts\t- %d\n\tAccepted pkts\t\t- %d\n\t" 522 "FCS error pkts\t\t- %d\n\tAddress mismatch pkts\t- %d\n\t" 523 "Average SNR\t\t- % d dBm\n\tAverage RSSI\t\t- % d dBm\n\n", 524 prms->base_pkt_id, prms->rx_path_statcs.nbr_rx_valid_pkts, 525 prms->rx_path_statcs.nbr_rx_fcs_err_pkts, 526 prms->rx_path_statcs.nbr_rx_plcp_err_pkts, 527 (signed short)prms->rx_path_statcs.ave_snr/8, 528 (signed short)prms->rx_path_statcs.ave_rssi/8); 529 530 return NL_SKIP; 531 } 532 533 static int plt_get_rx_statcs(struct nl80211_state *state, struct nl_cb *cb, 534 struct nl_msg *msg, int argc, char **argv) 535 { 536 struct nlattr *key; 537 struct wl1271_radio_rx_statcs prms; 538 539 prms.test.id = TEST_CMD_RX_STAT_GET; 540 541 key = nla_nest_start(msg, NL80211_ATTR_TESTDATA); 542 if (!key) { 543 fprintf(stderr, "%s> fail to nla_nest_start()\n", __func__); 544 return 1; 545 } 546 547 NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_TEST); 548 NLA_PUT(msg, WL1271_TM_ATTR_DATA, sizeof(prms), &prms); 549 NLA_PUT_U8(msg, WL1271_TM_ATTR_ANSWER, 1); 550 551 nla_nest_end(msg, key); 552 553 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, display_rx_statcs, NULL); 554 555 /* Important: needed gap between tx_start and tx_get */ 556 sleep(2); 557 558 return 0; 559 560 nla_put_failure: 561 fprintf(stderr, "%s> building message failed\n", __func__); 562 return 2; 563 } 564 565 COMMAND(plt, get_rx_statcs, NULL, 566 NL80211_CMD_TESTMODE, 0, CIB_NETDEV, plt_get_rx_statcs, 567 "Get Rx statistics\n"); 568 569 static int plt_rx_statistics(struct nl80211_state *state, struct nl_cb *cb, 570 struct nl_msg *msg, int argc, char **argv) 571 { 572 int ret; 573 574 /* power mode on */ 575 { 576 char *prms[4] = { "wlan0", "plt", "power_mode", "on" }; 577 578 ret = handle_cmd(state, II_NETDEV, 4, prms); 579 if (ret < 0) { 580 fprintf(stderr, "Fail to set PLT power mode on\n"); 581 return 1; 582 } 583 } 584 585 /* start_rx_statcs */ 586 { 587 char *prms[3] = { "wlan0", "plt", "start_rx_statcs" }; 588 589 ret = handle_cmd(state, II_NETDEV, 3, prms); 590 if (ret < 0) { 591 fprintf(stderr, "Fail to start Rx statistics\n"); 592 goto fail_out; 593 } 594 } 595 596 /* get_rx_statcs */ 597 { 598 int err; 599 char *prms[3] = { "wlan0", "plt", "get_rx_statcs" }; 600 601 err = handle_cmd(state, II_NETDEV, 3, prms); 602 if (err < 0) { 603 fprintf(stderr, "Fail to get Rx statistics\n"); 604 ret = err; 605 } 606 } 607 608 609 /* stop_rx_statcs */ 610 { 611 int err; 612 char *prms[3] = { "wlan0", "plt", "stop_rx_statcs" }; 613 614 err = handle_cmd(state, II_NETDEV, 3, prms); 615 if (err < 0) { 616 fprintf(stderr, "Fail to stop Rx statistics\n"); 617 ret = err; 618 } 619 } 620 621 fail_out: 622 /* power mode off */ 623 { 624 int err; 625 char *prms[4] = { "wlan0", "plt", "power_mode", "off"}; 626 627 err = handle_cmd(state, II_NETDEV, 4, prms); 628 if (err < 0) { 629 fprintf(stderr, "Fail to set PLT power mode on\n"); 630 return 1; 631 } 632 } 633 634 if (ret < 0) { 635 return 1; 636 } 637 638 return 0; 639 } 640 641 COMMAND(plt, rx_statistics, NULL, 0, 0, CIB_NONE, plt_rx_statistics, 642 "Get Rx statistics\n"); 643 644 static int plt_calibrate(struct nl80211_state *state, struct nl_cb *cb, 645 struct nl_msg *msg, int argc, char **argv) 646 { 647 int ret = 0, err; 648 int single_dual = 0; 649 650 if (argc > 2 && (strncmp(argv[2], "dual", 4) == 0)) { 651 single_dual = 1; /* going for dual band calibration */ 652 } else { 653 single_dual = 0; /* going for single band calibration */ 654 } 655 656 /* power mode on */ 657 { 658 char *pm_on[4] = { "wlan0", "plt", "power_mode", "on" }; 659 660 err = handle_cmd(state, II_NETDEV, 4, pm_on); 661 if (err < 0) { 662 fprintf(stderr, "Fail to set PLT power mode on\n"); 663 ret = err; 664 goto fail_out_final; 665 } 666 } 667 668 /* tune channel */ 669 { 670 char *pm_on[5] = { 671 "wlan0", "plt", "tune_channel", "0", "7" 672 }; 673 674 err = handle_cmd(state, II_NETDEV, 5, pm_on); 675 if (err < 0) { 676 fprintf(stderr, "Fail to tune channel\n"); 677 ret = err; 678 goto fail_out; 679 } 680 } 681 682 /* calibrate it */ 683 { 684 char *prms[11] = { 685 "wlan0", "plt", "tx_bip", "1", "0", "0", "0", 686 "0", "0", "0", "0" 687 }; 688 689 /* set flags in case of dual band */ 690 if (single_dual) { 691 prms[4] = prms[5] = prms[6] = prms[7] = prms[8] = 692 prms[9] = prms[10] = "1"; 693 } 694 695 err = handle_cmd(state, II_NETDEV, 11, prms); 696 if (err < 0) { 697 fprintf(stderr, "Fail to calibrate\n"); 698 ret = err; 699 } 700 } 701 702 fail_out: 703 /* power mode off */ 704 { 705 char *prms[4] = { "wlan0", "plt", "power_mode", "off"}; 706 707 err = handle_cmd(state, II_NETDEV, 4, prms); 708 if (err < 0) { 709 fprintf(stderr, "Fail to set PLT power mode on\n"); 710 ret = err; 711 } 712 } 713 714 fail_out_final: 715 if (ret < 0) { 716 return 1; 717 } 718 719 return 0; 720 } 721 722 COMMAND(plt, calibrate, "[<single|dual>]", 0, 0, CIB_NONE, 723 plt_calibrate, "Do calibrate for single or dual band chip\n"); 724