• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdbool.h>
2 #include <errno.h>
3 #include <time.h>
4 #include <net/if.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <sys/mman.h>
10 
11 #include "calibrator.h"
12 #include "plt.h"
13 #include "ini.h"
14 #include "nvs.h"
15 
16 SECTION(get);
17 SECTION(set);
18 
handle_push_nvs(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)19 static int handle_push_nvs(struct nl80211_state *state,
20             struct nl_cb *cb,
21             struct nl_msg *msg,
22             int argc, char **argv)
23 {
24     void *map = MAP_FAILED;
25     int fd, retval = 0;
26     struct nlattr *key;
27     struct stat filestat;
28 
29     if (argc != 1) {
30         return 1;
31     }
32 
33     fd = open(argv[0], O_RDONLY);
34     if (fd < 0) {
35         perror("Error opening file for reading");
36         return 1;
37     }
38 
39     if (fstat(fd, &filestat) < 0) {
40         perror("Error stating file");
41         return 1;
42     }
43 
44     map = mmap(0, filestat.st_size, PROT_READ, MAP_SHARED, fd, 0);
45     if (map == MAP_FAILED) {
46         perror("Error mmapping the file");
47         goto nla_put_failure;
48     }
49 
50     key = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
51     if (!key) {
52         goto nla_put_failure;
53     }
54 
55     NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_NVS_PUSH);
56     NLA_PUT(msg, WL1271_TM_ATTR_DATA, filestat.st_size, map);
57 
58     nla_nest_end(msg, key);
59 
60     goto cleanup;
61 
62 nla_put_failure:
63     retval = -ENOBUFS;
64 
65 cleanup:
66     if (map != MAP_FAILED) {
67         munmap(map, filestat.st_size);
68     }
69 
70     close(fd);
71 
72     return retval;
73 }
74 
75 COMMAND(set, push_nvs, "<nvs filename>",
76     NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_push_nvs,
77     "Push NVS file into the system");
78 
79 #if 0
80 static int handle_fetch_nvs(struct nl80211_state *state,
81             struct nl_cb *cb,
82             struct nl_msg *msg,
83             int argc, char **argv)
84 {
85     char *end;
86     void *map = MAP_FAILED;
87     int fd, retval = 0;
88     struct nlattr *key;
89     struct stat filestat;
90 
91     if (argc != 0)
92         return 1;
93 
94     key = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
95     if (!key)
96         goto nla_put_failure;
97 
98     NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_NVS_PUSH);
99     NLA_PUT_U32(msg, WL1271_TM_ATTR_IE_ID, WL1271_TM_CMD_NVS_PUSH);
100 
101     nla_nest_end(msg, key);
102 
103     goto cleanup;
104 
105 nla_put_failure:
106     retval = -ENOBUFS;
107 
108 cleanup:
109     if (map != MAP_FAILED)
110         munmap(map, filestat.st_size);
111 
112     close(fd);
113 
114     return retval;
115 }
116 
117 COMMAND(set, fetch_nvs, NULL,
118     NL80211_CMD_TESTMODE, 0, CIB_NETDEV, handle_fetch_nvs,
119     "Send command to fetch NVS file");
120 #endif
get_nvs_mac(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)121 static int get_nvs_mac(struct nl80211_state *state, struct nl_cb *cb,
122             struct nl_msg *msg, int argc, char **argv)
123 {
124     unsigned char mac_buff[12];
125     int fd;
126 
127     argc -= 2;
128     argv += 2;
129 
130     if (argc != 1) {
131         return 2;
132     }
133 
134     fd = open(argv[0], O_RDONLY);
135     if (fd < 0) {
136         perror("Error opening file for reading");
137         return 1;
138     }
139 
140     read(fd, mac_buff, 12);
141 
142     printf("MAC addr from NVS: %02x:%02x:%02x:%02x:%02x:%02x\n",
143         mac_buff[11], mac_buff[10], mac_buff[6],
144         mac_buff[5], mac_buff[4], mac_buff[3]);
145 
146     close(fd);
147 
148     return 0;
149 }
150 
151 COMMAND(get, nvs_mac, "<nvs filename>", 0, 0, CIB_NONE, get_nvs_mac,
152     "Get MAC addr from NVS file (offline)");
153 
154 /*
155  * Sets MAC address in NVS.
156  * The default value for MAC is random where 1 byte zero.
157  */
set_nvs_mac(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)158 static int set_nvs_mac(struct nl80211_state *state, struct nl_cb *cb,
159             struct nl_msg *msg, int argc, char **argv)
160 {
161     unsigned char mac_buff[12];
162     unsigned char in_mac[6];
163     int fd;
164 
165     argc -= 2;
166     argv += 2;
167 
168     if (argc < 1 || (argc == 2 && (strlen(argv[1]) != 17))) {
169         return 2;
170     }
171 
172     if (argc == 2) {
173         sscanf(argv[1], "%2x:%2x:%2x:%2x:%2x:%2x",
174         (unsigned int *)&in_mac[0], (unsigned int *)&in_mac[1],
175         (unsigned int *)&in_mac[2], (unsigned int *)&in_mac[3],
176         (unsigned int *)&in_mac[4], (unsigned int *)&in_mac[5]);
177     } else {
178         srand((unsigned)time(NULL));
179 
180         in_mac[0] = 0x0;
181         in_mac[1] = rand()%256;
182         in_mac[2] = rand()%256;
183         in_mac[3] = rand()%256;
184         in_mac[4] = rand()%256;
185         in_mac[5] = rand()%256;
186     }
187 
188     fd = open(argv[0], O_RDWR);
189     if (fd < 0) {
190         perror("Error opening file for reading");
191         return 1;
192     }
193 
194     read(fd, mac_buff, 12);
195 #if 0
196     printf("Got MAC addr for NVS: %02x:%02x:%02x:%02x:%02x:%02x\n",
197         in_mac[0], in_mac[1], in_mac[2],
198         in_mac[3], in_mac[4], in_mac[5]);
199 
200     printf("Got MAC addr from NVS: %02x:%02x:%02x:%02x:%02x:%02x\n",
201         mac_buff[11], mac_buff[10], mac_buff[6],
202         mac_buff[5], mac_buff[4], mac_buff[3]);
203 #endif
204     mac_buff[11] = in_mac[0];
205     mac_buff[10] = in_mac[1];
206     mac_buff[6]  = in_mac[2];
207     mac_buff[5]  = in_mac[3];
208     mac_buff[4]  = in_mac[4];
209     mac_buff[3]  = in_mac[5];
210 
211     lseek(fd, 0L, 0);
212 
213     write(fd, mac_buff, 12);
214 
215     close(fd);
216 
217     return 0;
218 }
219 
220 COMMAND(set, nvs_mac, "<nvs file> [<mac addr>]", 0, 0, CIB_NONE, set_nvs_mac,
221     "Set MAC addr in NVS file (offline), like XX:XX:XX:XX:XX:XX");
222 
set_ref_nvs(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)223 static int set_ref_nvs(struct nl80211_state *state, struct nl_cb *cb,
224             struct nl_msg *msg, int argc, char **argv)
225 {
226     struct wl12xx_common cmn = {
227         .arch = UNKNOWN_ARCH,
228         .parse_ops = NULL,
229         .dual_mode = DUAL_MODE_UNSET,
230         .done_fem = NO_FEM_PARSED
231     };
232 
233     argc -= 2;
234     argv += 2;
235 
236     if (argc != 1) {
237         return 1;
238     }
239 
240     if (read_ini(*argv, &cmn)) {
241         fprintf(stderr, "Fail to read ini file\n");
242         return 1;
243     }
244 
245     cfg_nvs_ops(&cmn);
246 
247     if (create_nvs_file(&cmn)) {
248         fprintf(stderr, "Fail to create reference NVS file\n");
249         return 1;
250     }
251 #if 0
252     printf("\n\tThe NVS file (%s) is ready\n\tCopy it to %s and "
253         "reboot the system\n\n",
254         NEW_NVS_NAME, CURRENT_NVS_NAME);
255 #endif
256     return 0;
257 }
258 
259 COMMAND(set, ref_nvs, "<ini file>", 0, 0, CIB_NONE, set_ref_nvs,
260     "Create reference NVS file");
261 
set_ref_nvs2(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)262 static int set_ref_nvs2(struct nl80211_state *state, struct nl_cb *cb,
263             struct nl_msg *msg, int argc, char **argv)
264 {
265     struct wl12xx_common cmn = {
266         .arch = UNKNOWN_ARCH,
267         .parse_ops = NULL,
268         .dual_mode = DUAL_MODE_UNSET,
269         .done_fem = NO_FEM_PARSED
270     };
271 
272     argc -= 2;
273     argv += 2;
274 
275     if (argc != 2) {
276         return 1;
277     }
278 
279     if (read_ini(*argv, &cmn)) {
280         return 1;
281     }
282 
283     argv++;
284     if (read_ini(*argv, &cmn)) {
285         return 1;
286     }
287 
288     cfg_nvs_ops(&cmn);
289 
290     if (create_nvs_file(&cmn)) {
291         fprintf(stderr, "Fail to create reference NVS file\n");
292         return 1;
293     }
294 #if 0
295     printf("\n\tThe NVS file (%s) is ready\n\tCopy it to %s and "
296         "reboot the system\n\n",
297         NEW_NVS_NAME, CURRENT_NVS_NAME);
298 #endif
299     return 0;
300 }
301 
302 COMMAND(set, ref_nvs2, "<ini file> <ini file>", 0, 0, CIB_NONE, set_ref_nvs2,
303     "Create reference NVS file for 2 FEMs");
304 
set_upd_nvs(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)305 static int set_upd_nvs(struct nl80211_state *state, struct nl_cb *cb,
306     struct nl_msg *msg, int argc, char **argv)
307 {
308     char *fname = NULL;
309     struct wl12xx_common cmn = {
310         .arch = UNKNOWN_ARCH,
311         .parse_ops = NULL
312     };
313 
314     argc -= 2;
315     argv += 2;
316 
317     if (argc < 1) {
318         return 1;
319     }
320 
321     if (read_ini(*argv, &cmn)) {
322         fprintf(stderr, "Fail to read ini file\n");
323         return 1;
324     }
325 
326     cfg_nvs_ops(&cmn);
327 
328     if (argc == 2) {
329         fname = *++argv;
330     }
331 
332     if (update_nvs_file(fname, &cmn)) {
333         fprintf(stderr, "Fail to update NVS file\n");
334         return 1;
335     }
336 #if 0
337     printf("\n\tThe updated NVS file (%s) is ready\n\tCopy it to %s and "
338         "reboot the system\n\n", NEW_NVS_NAME, CURRENT_NVS_NAME);
339 #endif
340     return 0;
341 }
342 
343 COMMAND(set, upd_nvs, "<ini file> [<nvs file>]", 0, 0, CIB_NONE, set_upd_nvs,
344     "Update values of a NVS from INI file");
345 
get_dump_nvs(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)346 static int get_dump_nvs(struct nl80211_state *state, struct nl_cb *cb,
347             struct nl_msg *msg, int argc, char **argv)
348 {
349     char *fname = NULL;
350     struct wl12xx_common cmn = {
351         .arch = UNKNOWN_ARCH,
352         .parse_ops = NULL
353     };
354 
355     argc -= 2;
356     argv += 2;
357 
358     if (argc > 0) {
359         fname = *argv;
360     }
361 
362     if (dump_nvs_file(fname, &cmn)) {
363         fprintf(stderr, "Fail to dump NVS file\n");
364         return 1;
365     }
366 
367     return 0;
368 }
369 
370 COMMAND(get, dump_nvs, "[<nvs file>]", 0, 0, CIB_NONE, get_dump_nvs,
371     "Dump NVS file, specified by option or current");
372 
set_autofem(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)373 static int set_autofem(struct nl80211_state *state, struct nl_cb *cb,
374             struct nl_msg *msg, int argc, char **argv)
375 {
376     char *fname = NULL;
377     unsigned char val;
378     struct wl12xx_common cmn = {
379         .arch = UNKNOWN_ARCH,
380         .parse_ops = NULL
381     };
382 
383     argc -= 2;
384     argv += 2;
385 
386     if (argc < 1) {
387         fprintf(stderr, "Missing argument\n");
388         return 2;
389     }
390 
391     sscanf(argv[0], "%2x", (unsigned int *)&val);
392 
393     if (argc == 2) {
394         fname = argv[1];
395     }
396 
397     if (set_nvs_file_autofem(fname, val, &cmn)) {
398         fprintf(stderr, "Fail to set AutoFEM\n");
399         return 1;
400     }
401 
402     return 0;
403 }
404 
405 COMMAND(set, autofem, "<0-manual|1-auto> [<nvs file>]", 0, 0, CIB_NONE, set_autofem,
406     "Set Auto FEM detection, where 0 - manual, 1 - auto detection");
407 
set_fem_manuf(struct nl80211_state * state,struct nl_cb * cb,struct nl_msg * msg,int argc,char ** argv)408 static int set_fem_manuf(struct nl80211_state *state, struct nl_cb *cb,
409             struct nl_msg *msg, int argc, char **argv)
410 {
411     char *fname = NULL;
412     unsigned char val;
413     struct wl12xx_common cmn = {
414         .arch = UNKNOWN_ARCH,
415         .parse_ops = NULL
416     };
417 
418     argc -= 2;
419     argv += 2;
420 
421     if (argc < 1) {
422         fprintf(stderr, "Missing argument\n");
423         return 2;
424     }
425 
426     sscanf(argv[0], "%2x", (unsigned int *)&val);
427 
428     if (argc == 2) {
429         fname = argv[1];
430     }
431 
432     if (set_nvs_file_fem_manuf(fname, val, &cmn)) {
433         fprintf(stderr, "Fail to set AutoFEM\n");
434         return 1;
435     }
436 
437     return 0;
438 }
439 
440 COMMAND(set, fem_manuf, "<0|1> [<nvs file>]", 0, 0, CIB_NONE, set_fem_manuf,
441     "Set FEM manufacturer");
442 
443