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