blob: ac2ebc65c5c4c1ba72204b92de18f239e24eaec3 [file] [log] [blame]
#include <stdbool.h>
#include <errno.h>
#include <time.h>
#include <net/if.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "calibrator.h"
#include "plt.h"
#include "ini.h"
#include "nvs.h"
SECTION(get);
SECTION(set);
static int handle_push_nvs(struct nl80211_state *state,
struct nl_cb *cb,
struct nl_msg *msg,
int argc, char **argv)
{
void *map = MAP_FAILED;
int fd, retval = 0;
struct nlattr *key;
struct stat filestat;
if (argc != 1) {
return 1;
}
fd = open(argv[0], O_RDONLY);
if (fd < 0) {
perror("Error opening file for reading");
return 1;
}
if (fstat(fd, &filestat) < 0) {
perror("Error stating file");
return 1;
}
map = mmap(0, filestat.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
perror("Error mmapping the file");
goto nla_put_failure;
}
key = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
if (!key) {
goto nla_put_failure;
}
NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_NVS_PUSH);
NLA_PUT(msg, WL1271_TM_ATTR_DATA, filestat.st_size, map);
nla_nest_end(msg, key);
goto cleanup;
nla_put_failure:
retval = -ENOBUFS;
cleanup:
if (map != MAP_FAILED) {
munmap(map, filestat.st_size);
}
close(fd);
return retval;
}
COMMAND(set, push_nvs, "<nvs filename>",
NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_push_nvs,
"Push NVS file into the system");
#if 0
static int handle_fetch_nvs(struct nl80211_state *state,
struct nl_cb *cb,
struct nl_msg *msg,
int argc, char **argv)
{
char *end;
void *map = MAP_FAILED;
int fd, retval = 0;
struct nlattr *key;
struct stat filestat;
if (argc != 0)
return 1;
key = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
if (!key)
goto nla_put_failure;
NLA_PUT_U32(msg, WL1271_TM_ATTR_CMD_ID, WL1271_TM_CMD_NVS_PUSH);
NLA_PUT_U32(msg, WL1271_TM_ATTR_IE_ID, WL1271_TM_CMD_NVS_PUSH);
nla_nest_end(msg, key);
goto cleanup;
nla_put_failure:
retval = -ENOBUFS;
cleanup:
if (map != MAP_FAILED)
munmap(map, filestat.st_size);
close(fd);
return retval;
}
COMMAND(set, fetch_nvs, NULL,
NL80211_CMD_TESTMODE, 0, CIB_NETDEV, handle_fetch_nvs,
"Send command to fetch NVS file");
#endif
static int get_nvs_mac(struct nl80211_state *state, struct nl_cb *cb,
struct nl_msg *msg, int argc, char **argv)
{
unsigned char mac_buff[12];
int fd;
argc -= 2;
argv += 2;
if (argc != 1) {
return 2;
}
fd = open(argv[0], O_RDONLY);
if (fd < 0) {
perror("Error opening file for reading");
return 1;
}
read(fd, mac_buff, 12);
printf("MAC addr from NVS: %02x:%02x:%02x:%02x:%02x:%02x\n",
mac_buff[11], mac_buff[10], mac_buff[6],
mac_buff[5], mac_buff[4], mac_buff[3]);
close(fd);
return 0;
}
COMMAND(get, nvs_mac, "<nvs filename>", 0, 0, CIB_NONE, get_nvs_mac,
"Get MAC addr from NVS file (offline)");
/*
* Sets MAC address in NVS.
* The default value for MAC is random where 1 byte zero.
*/
static int set_nvs_mac(struct nl80211_state *state, struct nl_cb *cb,
struct nl_msg *msg, int argc, char **argv)
{
unsigned char mac_buff[12];
unsigned char in_mac[6];
int fd;
argc -= 2;
argv += 2;
if (argc < 1 || (argc == 2 && (strlen(argv[1]) != 17))) {
return 2;
}
if (argc == 2) {
sscanf(argv[1], "%2x:%2x:%2x:%2x:%2x:%2x",
(unsigned int *)&in_mac[0], (unsigned int *)&in_mac[1],
(unsigned int *)&in_mac[2], (unsigned int *)&in_mac[3],
(unsigned int *)&in_mac[4], (unsigned int *)&in_mac[5]);
} else {
srand((unsigned)time(NULL));
in_mac[0] = 0x0;
in_mac[1] = rand()%256;
in_mac[2] = rand()%256;
in_mac[3] = rand()%256;
in_mac[4] = rand()%256;
in_mac[5] = rand()%256;
}
fd = open(argv[0], O_RDWR);
if (fd < 0) {
perror("Error opening file for reading");
return 1;
}
read(fd, mac_buff, 12);
#if 0
printf("Got MAC addr for NVS: %02x:%02x:%02x:%02x:%02x:%02x\n",
in_mac[0], in_mac[1], in_mac[2],
in_mac[3], in_mac[4], in_mac[5]);
printf("Got MAC addr from NVS: %02x:%02x:%02x:%02x:%02x:%02x\n",
mac_buff[11], mac_buff[10], mac_buff[6],
mac_buff[5], mac_buff[4], mac_buff[3]);
#endif
mac_buff[11] = in_mac[0];
mac_buff[10] = in_mac[1];
mac_buff[6] = in_mac[2];
mac_buff[5] = in_mac[3];
mac_buff[4] = in_mac[4];
mac_buff[3] = in_mac[5];
lseek(fd, 0L, 0);
write(fd, mac_buff, 12);
close(fd);
return 0;
}
COMMAND(set, nvs_mac, "<nvs file> [<mac addr>]", 0, 0, CIB_NONE, set_nvs_mac,
"Set MAC addr in NVS file (offline), like XX:XX:XX:XX:XX:XX");
static int set_ref_nvs(struct nl80211_state *state, struct nl_cb *cb,
struct nl_msg *msg, int argc, char **argv)
{
struct wl12xx_common cmn = {
.arch = UNKNOWN_ARCH,
.parse_ops = NULL,
.dual_mode = DUAL_MODE_UNSET,
.done_fem = NO_FEM_PARSED
};
argc -= 2;
argv += 2;
if (argc != 1) {
return 1;
}
if (read_ini(*argv, &cmn)) {
fprintf(stderr, "Fail to read ini file\n");
return 1;
}
cfg_nvs_ops(&cmn);
if (create_nvs_file(&cmn)) {
fprintf(stderr, "Fail to create reference NVS file\n");
return 1;
}
#if 0
printf("\n\tThe NVS file (%s) is ready\n\tCopy it to %s and "
"reboot the system\n\n",
NEW_NVS_NAME, CURRENT_NVS_NAME);
#endif
return 0;
}
COMMAND(set, ref_nvs, "<ini file>", 0, 0, CIB_NONE, set_ref_nvs,
"Create reference NVS file");
static int set_ref_nvs2(struct nl80211_state *state, struct nl_cb *cb,
struct nl_msg *msg, int argc, char **argv)
{
struct wl12xx_common cmn = {
.arch = UNKNOWN_ARCH,
.parse_ops = NULL,
.dual_mode = DUAL_MODE_UNSET,
.done_fem = NO_FEM_PARSED
};
argc -= 2;
argv += 2;
if (argc != 2) {
return 1;
}
if (read_ini(*argv, &cmn)) {
return 1;
}
argv++;
if (read_ini(*argv, &cmn)) {
return 1;
}
cfg_nvs_ops(&cmn);
if (create_nvs_file(&cmn)) {
fprintf(stderr, "Fail to create reference NVS file\n");
return 1;
}
#if 0
printf("\n\tThe NVS file (%s) is ready\n\tCopy it to %s and "
"reboot the system\n\n",
NEW_NVS_NAME, CURRENT_NVS_NAME);
#endif
return 0;
}
COMMAND(set, ref_nvs2, "<ini file> <ini file>", 0, 0, CIB_NONE, set_ref_nvs2,
"Create reference NVS file for 2 FEMs");
static int set_upd_nvs(struct nl80211_state *state, struct nl_cb *cb,
struct nl_msg *msg, int argc, char **argv)
{
char *fname = NULL;
struct wl12xx_common cmn = {
.arch = UNKNOWN_ARCH,
.parse_ops = NULL
};
argc -= 2;
argv += 2;
if (argc < 1) {
return 1;
}
if (read_ini(*argv, &cmn)) {
fprintf(stderr, "Fail to read ini file\n");
return 1;
}
cfg_nvs_ops(&cmn);
if (argc == 2) {
fname = *++argv;
}
if (update_nvs_file(fname, &cmn)) {
fprintf(stderr, "Fail to update NVS file\n");
return 1;
}
#if 0
printf("\n\tThe updated NVS file (%s) is ready\n\tCopy it to %s and "
"reboot the system\n\n", NEW_NVS_NAME, CURRENT_NVS_NAME);
#endif
return 0;
}
COMMAND(set, upd_nvs, "<ini file> [<nvs file>]", 0, 0, CIB_NONE, set_upd_nvs,
"Update values of a NVS from INI file");
static int get_dump_nvs(struct nl80211_state *state, struct nl_cb *cb,
struct nl_msg *msg, int argc, char **argv)
{
char *fname = NULL;
struct wl12xx_common cmn = {
.arch = UNKNOWN_ARCH,
.parse_ops = NULL
};
argc -= 2;
argv += 2;
if (argc > 0) {
fname = *argv;
}
if (dump_nvs_file(fname, &cmn)) {
fprintf(stderr, "Fail to dump NVS file\n");
return 1;
}
return 0;
}
COMMAND(get, dump_nvs, "[<nvs file>]", 0, 0, CIB_NONE, get_dump_nvs,
"Dump NVS file, specified by option or current");
static int set_autofem(struct nl80211_state *state, struct nl_cb *cb,
struct nl_msg *msg, int argc, char **argv)
{
char *fname = NULL;
unsigned char val;
struct wl12xx_common cmn = {
.arch = UNKNOWN_ARCH,
.parse_ops = NULL
};
argc -= 2;
argv += 2;
if (argc < 1) {
fprintf(stderr, "Missing argument\n");
return 2;
}
sscanf(argv[0], "%2x", (unsigned int *)&val);
if (argc == 2) {
fname = argv[1];
}
if (set_nvs_file_autofem(fname, val, &cmn)) {
fprintf(stderr, "Fail to set AutoFEM\n");
return 1;
}
return 0;
}
COMMAND(set, autofem, "<0-manual|1-auto> [<nvs file>]", 0, 0, CIB_NONE, set_autofem,
"Set Auto FEM detection, where 0 - manual, 1 - auto detection");
static int set_fem_manuf(struct nl80211_state *state, struct nl_cb *cb,
struct nl_msg *msg, int argc, char **argv)
{
char *fname = NULL;
unsigned char val;
struct wl12xx_common cmn = {
.arch = UNKNOWN_ARCH,
.parse_ops = NULL
};
argc -= 2;
argv += 2;
if (argc < 1) {
fprintf(stderr, "Missing argument\n");
return 2;
}
sscanf(argv[0], "%2x", (unsigned int *)&val);
if (argc == 2) {
fname = argv[1];
}
if (set_nvs_file_fem_manuf(fname, val, &cmn)) {
fprintf(stderr, "Fail to set AutoFEM\n");
return 1;
}
return 0;
}
COMMAND(set, fem_manuf, "<0|1> [<nvs file>]", 0, 0, CIB_NONE, set_fem_manuf,
"Set FEM manufacturer");