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