• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
str2mac(unsigned char * pmac,char * pch)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 
plt_power_mode(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
plt_tune_channel(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
plt_ref_point(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
calib_valid_handler(struct nl_msg * msg,void * arg)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 
plt_tx_bip(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
plt_tx_tone(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
plt_tx_cont(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
plt_tx_stop(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
plt_start_rx_statcs(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
plt_stop_rx_statcs(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
plt_reset_rx_statcs(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
display_rx_statcs(struct nl_msg * msg,void * arg)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 
plt_get_rx_statcs(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
plt_rx_statistics(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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 
plt_calibrate(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)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