]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - wl12xx/ti-utils.git/commitdiff
Add autocalibrate command
authorPontus Fuchs <pontus.fuchs@tactel.se>
Tue, 4 Oct 2011 08:17:26 +0000 (10:17 +0200)
committerPontus Fuchs <pontus.fuchs@tactel.se>
Tue, 11 Oct 2011 14:35:13 +0000 (16:35 +0200)
This command will load module, parse ini, tune, txbip in one step.

Reviewed-by: Luciano Coelho <coelho@ti.com>
README
ini.c
ini.h
misc_cmds.c
nvs.c
nvs.h
plt.c
plt.h

diff --git a/README b/README
index 9ab94e95fb440d7d3257e1b64ad6c918860a46cf..f43661af31c4f6c2dcce6df9b2ac07f4ba140c3e 100644 (file)
--- a/README
+++ b/README
@@ -30,81 +30,37 @@ export CROSS_COMPILE=arm-none-linux-gnueabi-
 make
 make install
 
-Make sure that calibrator utility and wl12xx-tool.sh script placed at 
-the same dir.
-
 --- How to calibrate
 
-Native Linux calibration procedure.
-
-       ./wl12xx-tool.sh -c <path to INI file> [<path to firmware directory>]
-
-Android calibration procedure.
-
-       Based on adb utility which comes native with Android SDK
-
-       adb shell "echo Going to stop GUI"
-       adb shell "stop"
-
-       adb shell "echo Create reference NVS"
-       adb shell "calibrator set ref_nvs /data/TQS_D_1.7.ini"
-
-       adb shell "echo Copy reference NVS file"
-       adb shell "cat ./new-nvs.bin > /system/etc/firmware/ti-connectivity/wl1271-nvs.bin"
-
-       adb shell "echo Insert wl12xx SDIO module"
-       adb shell "insmod /system/lib/modules/wl12xx_sdio.ko"
-
-       adb shell "echo Calibrate device"
-       adb shell "calibrator wlan0 plt power_mode on"
-       adb shell "calibrator wlan0 plt tune_channel 0 7"
-       adb shell "calibrator wlan0 plt tx_bip 1 1 1 1 1 1 1 1"
-       adb shell "calibrator wlan0 plt power_mode off"
-
-       adb shell "echo Set MAC address in NVS file"
-       adb shell "calibrator set nvs_mac ./new-nvs.bin 08:00:28:90:64:31"
-
-       adb shell "echo Remove wl12xx modules"
-       adb shell "rmmod wl12xx_sdio wl12xx"
-       adb shell "rmmod wl12xx"
-
-       adb shell "echo Copy calibrated NVS file"
-       adb shell "cat ./new-nvs.bin > /system/etc/firmware/ti-connectivity/wl1271-nvs.bin"
-       adb shell "insmod /system/lib/modules/wl12xx.ko"
+Automatic calibration procedure.
 
-       adb shell "echo Going to start GUI"
-       adb shell "start"
+* Make sure all modules up to wl12xx.ko are loaded. wl12xx_sdio.ko should NOT be loaded.
+* The firmware directory must be writeable.
+* A "plt firmware" must be present in the firmware directory.
 
---- How to calibrate with AutoFEM
+calibrator plt autocalibrate <dev> <kernel mod> <ini> <nvs> <mac>
+       dev             Device name. Probably wlan0
+       kernel mod      Full path to wl12xx_sdio.ko kernel module
+       ini             Full path to Radio param ini file
+       nvs             Full path of nvs file. Must be the real path as wl12xx will load it
 
-The wl12xx driver has ability to use it's NVS file with radio parameters for 2
-different frontend modules. The driver requires firmware at boot time which
-FEM parameters it needs and provides radio parameters according to answer.
+This command will perform the following steps:
 
-There is also scenario when driver decides which radio parameters to give
-to firmware. In such case, 2 parameters should be set. The autofem should be
-0 and fem_manuf should be 0 or 1, depends on FEM manufacturer.
+* Parse the ini and create an nvs without calibration data.
+* Load kernel module.
+* Perform TxBip and update nvs with calibration data.
+* Unload kernel module.
 
-In order to prepare NVS file with radio parameters for 2 FEMs, do follows
+Android example:
+./calibrator plt autocalibrate wlan0 /system/lib/modules/wl12xx_sdio.ko TQS_D_1.7.ini /etc/firmware/ti-connectivity/wl1271-nvs.bin 00:01:02:03:04:05
 
-       ./wl12xx-tool.sh -c2 <path to INI file> [<path to INI file>]
-
-There is option to use the feature manualy. In such case, there is need to set
-AutoFEM flag to 0 and explicitly set fem_manuf flag.
-
-       ./calibrator set autofem <0-manual|1-auto> [<nvs file>]
-       ./calibrator set fem_manuf <0|1> [<nvs file>]
+Native Linux example:
+./calibrator plt autocalibrate wlan0 /lib/modules/wl12xx_sdio.ko TQS_D_1.7.ini /lib/firmware/ti-connectivity/wl1271-nvs.bin 00:01:02:03:04:05
 
 --- How to choose INI file
 
-It is very important to select INI file according to the firmware (see below).
-Those files organized in 3 directories:
-station - currently supported station firmware (wl1271-fw.bin)
-access_point - currently supported access point (wl1271-fw-ap.bin)
-
-For Beagle board and Panda board use ini_files/station/127x/TQS_S_2.6.ini
-For Blaze board with ES2.1 or ES2.1 use ini_files/station/128x/TQS_D_1.7.ini
-
+For Beagle board and Panda board use ini_files/127x/TQS_S_2.6.ini
+For Blaze board with ES2.1 or ES2.1 use ini_files/128x/TQS_D_1.7.ini
 
 --- How to change MAC address in calibrated NVS
 
@@ -118,32 +74,16 @@ If the MAC address missing, the random valid value will be added.
 calibrator get dump_nvs [<nvs filename>]
 
 
---- Firmware files
-
-The firmware files can be reached from git repository
-git://git.kernel.org/pub/scm/linux/kernel/git/dwmw2/linux-firmware.git
-under directory ti-connectivity.
-There are 2 firmware files there:
-wl1271-fw.bin    - station firmware
-wl1271-fw-ap.bin    - access point firmware
-
-
 --- Detailed instructions for calibrator procedures
 
-The following detailed instructions are collection of commands done by
-default calibration procedure.
+Normally you should use the autocalibrate command but it's also possible to
+run each step manually.
 
        TxBip procedure (calibration)
 
 It is important to set MAC address to an interface before the procedure.
 For example, `ifconfig wlan0 hw ether xx:xx:xx:xx:xx:xx'
-There are 2 ways to do it - short where all parameters has default values and
-full where you have to set all parameters manually.
 
-Short way:
-calibrator plt calibrate
-
-Full way:
 calibrator wlan0 plt power_mode on
 calibrator wlan0 plt tx_bip <0|1> <0|1> <0|1> <0|1> <0|1> <0|1> <0|1> <0|1>
 calibrator wlan0 plt power_mode off
diff --git a/ini.c b/ini.c
index e87d499864baf38f2bab5b213f5a78d8c814ba58..9c7b9ad233fddb56d7dbf23b560d5fe90b6881f7 100644 (file)
--- a/ini.c
+++ b/ini.c
@@ -950,6 +950,20 @@ static void ini_dump(struct wl1271_ini *ini)
 }
 #endif
 
+
+static int is_dual_mode(struct wl12xx_ini *p)
+{
+       struct wl1271_ini_general_params *gp = &(p->ini1271.general_params);
+       return gp->dual_mode_select;
+}
+
+static int is_dual_mode_128x(struct wl12xx_ini *p)
+{
+       struct wl128x_ini_general_params *gp = &(p->ini128x.general_params);
+       return gp->dual_mode_select;
+}
+
+
 static struct wl12xx_parse_ops wl1271_parse_ops = {
        .prs_general_prms       = parse_general_prms,
        .prs_band2_prms         = parse_band2_prms,
@@ -957,6 +971,7 @@ static struct wl12xx_parse_ops wl1271_parse_ops = {
        .prs_fem0_band2_prms    = parse_fem0_band2_prms,
        .prs_fem1_band2_prms    = parse_fem1_band2_prms,
        .prs_fem1_band5_prms    = parse_fem1_band5_prms,
+       .is_dual_mode           = is_dual_mode,
 };
 
 static struct wl12xx_parse_ops wl128x_parse_ops = {
@@ -966,8 +981,14 @@ static struct wl12xx_parse_ops wl128x_parse_ops = {
        .prs_fem0_band2_prms    = parse_fem0_band2_prms_128x,
        .prs_fem1_band2_prms    = parse_fem1_band2_prms_128x,
        .prs_fem1_band5_prms    = parse_fem1_band5_prms_128x,
+       .is_dual_mode           = is_dual_mode_128x,
 };
 
+int ini_get_dual_mode(struct wl12xx_common *cmn)
+{
+       return cmn->parse_ops->is_dual_mode(&cmn->ini);
+}
+
 int nvs_get_arch(int file_size, struct wl12xx_common *cmn)
 {
        enum wl12xx_arch arch = UNKNOWN_ARCH;
diff --git a/ini.h b/ini.h
index 0ee785a3f9afd336a8f4679fefed467f8ed07bb9..a3aa8990b7be92c5c4c0a66ab60ff50aeb8e74b4 100644 (file)
--- a/ini.h
+++ b/ini.h
@@ -301,6 +301,7 @@ struct wl12xx_common {
        struct wl12xx_parse_ops *parse_ops;
        struct wl12xx_nvs_ops   *nvs_ops;
        struct wl12xx_ini ini;
+       char *nvs_name;
 };
 
 struct wl12xx_parse_ops {
@@ -312,6 +313,7 @@ struct wl12xx_parse_ops {
        int (*prs_fem0_band2_prms)(char *l, struct wl12xx_ini *p);
        int (*prs_fem1_band2_prms)(char *l, struct wl12xx_ini *p);
        int (*prs_fem1_band5_prms)(char *l, struct wl12xx_ini *p);
+       int (*is_dual_mode)(struct wl12xx_ini *p);
 };
 
 struct wl12xx_nvs_ops {
@@ -324,4 +326,5 @@ int nvs_get_arch(int file_size, struct wl12xx_common *cmn);
 
 int read_ini(const char *filename, struct wl12xx_common *cmn);
 
+int ini_get_dual_mode(struct wl12xx_common *cmn);
 #endif
index 4f9587c58890c785ef6ca6eced776a5391f07dbc..cdfe726590b91d22301ee995fd0a979d5d8d09c4 100644 (file)
@@ -1,6 +1,5 @@
 #include <stdbool.h>
 #include <errno.h>
-#include <time.h>
 #include <net/if.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -156,53 +155,13 @@ COMMAND(get, nvs_mac, "[<nvs filename>]", 0, 0, CIB_NONE, get_nvs_mac,
 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 int 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",
-               &in_mac[0], &in_mac[1],
-               &in_mac[2], &in_mac[3],
-               &in_mac[4], &in_mac[5]);
-       else {
-               srand((unsigned)time(NULL));
-
-               in_mac[0] = 0x0;
-               in_mac[1] = rand();
-               in_mac[2] = rand();
-               in_mac[3] = rand();
-               in_mac[4] = rand();
-               in_mac[5] = rand();
-       }
-
-       fd = open(argv[0], O_RDWR);
-       if (fd < 0) {
-               perror("Error opening file for reading");
-               return 1;
-       }
-
-       read(fd, mac_buff, 12);
-
-       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);
-
+       nvs_set_mac(argv[0], argv[1]);
        return 0;
 }
 
@@ -232,6 +191,7 @@ static int set_ref_nvs(struct nl80211_state *state, struct nl_cb *cb,
 
        cfg_nvs_ops(&cmn);
 
+       cmn.nvs_name = NEW_NVS_NAME;
        if (create_nvs_file(&cmn)) {
                fprintf(stderr, "Fail to create reference NVS file\n");
                return 1;
@@ -270,6 +230,7 @@ static int set_ref_nvs2(struct nl80211_state *state, struct nl_cb *cb,
 
        cfg_nvs_ops(&cmn);
 
+       cmn.nvs_name = NEW_NVS_NAME;
        if (create_nvs_file(&cmn)) {
                fprintf(stderr, "Fail to create reference NVS file\n");
                return 1;
diff --git a/nvs.c b/nvs.c
index 487b1006336c75eccdce50cf9e553fcbdac7f78d..1a293f5c8b35a6a9da31fba11e2c42d8c8cda6b0 100644 (file)
--- a/nvs.c
+++ b/nvs.c
@@ -14,6 +14,7 @@
 #include <unistd.h>
 #include <stdbool.h>
 #include <netinet/in.h>
+#include <time.h>
 
 #include <netlink/netlink.h>
 #include <netlink/msg.h>
@@ -61,6 +62,60 @@ char *get_opt_nvsoutfile(int argc, char **argv)
        return name;
 }
 
+int nvs_set_mac(char *nvsfile, char *mac)
+{
+       unsigned char mac_buff[12];
+       unsigned char in_mac[6];
+       int fd;
+
+       if (mac) {
+               int ret =
+               sscanf(mac, "%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]);
+               if (ret != 6) {
+                       fprintf(stderr, "MAC address is not valid: %s\n", mac);
+                       return -1;
+               }
+       }
+       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;
+               fprintf(stderr, "WARNING: No MAC specified. Using random MAC!");
+       }
+
+       fd = open(nvsfile, O_RDWR);
+       if (fd < 0) {
+               perror("Error opening file for reading");
+               return 1;
+       }
+
+       read(fd, mac_buff, 12);
+       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);
+
+       printf("Writing mac address %s to file %s\n", mac, nvsfile);
+       write(fd, mac_buff, 12);
+
+       close(fd);
+       return 0;
+}
+
+
+
 int nvs_fill_radio_params(int fd, struct wl12xx_ini *ini, char *buf)
 {
        size_t size;
@@ -248,8 +303,6 @@ int file_exist(const char *filename)
 
        ret = stat(filename, &buf);
        if (ret != 0) {
-               fprintf(stderr, "fail to stat file %s (%s)\n", filename,
-                       strerror(errno));
                return -1;
        }
 
@@ -545,7 +598,7 @@ int prepare_nvs_file(void *arg, char *file_name)
        cfg_nvs_ops(&cmn);
 
        /* create new NVS file */
-       new_nvs = open(NEW_NVS_NAME,
+       new_nvs = open(file_name,
                O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
        if (new_nvs < 0) {
                fprintf(stderr, "%s> Unable to open new NVS file\n", __func__);
@@ -644,7 +697,7 @@ int create_nvs_file(struct wl12xx_common *cmn)
        char buf[2048];
 
        /* create new NVS file */
-       new_nvs = open(NEW_NVS_NAME,
+       new_nvs = open(cmn->nvs_name,
                O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
        if (new_nvs < 0) {
                fprintf(stderr, "%s> Unable to open new NVS file\n", __func__);
diff --git a/nvs.h b/nvs.h
index 1d8692cff7f3cb5a2b1c671ad6a92a95c7199521..b8a1ce63f1a4148145769632070c90b250dbad41 100644 (file)
--- a/nvs.h
+++ b/nvs.h
@@ -9,6 +9,8 @@ char *get_opt_nvsoutfile(int argc, char **argv);
 
 int prepare_nvs_file(void *arg, char *file_name);
 
+int nvs_set_mac(char *nvsfile, char *mac);
+
 void cfg_nvs_ops(struct wl12xx_common *cmn);
 
 int create_nvs_file(struct wl12xx_common *cmn);
diff --git a/plt.c b/plt.c
index c9e015a496dbb2129b4b1650a1cfdd892f1c8d12..f3361fd1dff607bd595a7b56a379fad0d9b89359 100644 (file)
--- a/plt.c
+++ b/plt.c
 
 SECTION(plt);
 
+#define CMDBUF_SIZE 200
+static int insmod(char *filename)
+{
+       int ret;
+       char cmd[CMDBUF_SIZE];
+       snprintf(cmd, CMDBUF_SIZE, "%s %s", INSMOD_PATH, filename);
+       ret = system(cmd);
+       if (ret)
+               fprintf(stderr, "Failed to load kernel module using command %s\n", cmd);
+       return ret;
+}
+
+static int rmmod(char *name)
+{
+       char cmd[CMDBUF_SIZE];
+       char *tmp = strdup(name);
+       int i, ret;
+
+       /* "basename" */
+       tmp = strrchr(name, '/');
+       if (!tmp)
+               tmp = name;
+       else
+               tmp++;
+
+       tmp = strdup(tmp);
+       if (!tmp)
+               return -ENOMEM;
+
+       /* strip trailing .ko if there */
+       i = strlen(tmp);
+       if (i < 4)
+               return -EINVAL;
+       if (!strcmp(tmp + i - 3, ".ko"))
+               tmp[i-3] = 0;
+
+       snprintf(cmd, CMDBUF_SIZE, "%s %s", RMMOD_PATH, tmp);
+       ret = system(cmd);
+       if (ret)
+               fprintf(stderr, "Failed to remove kernel module using command %s\n", cmd);
+       free(tmp);
+       return ret;
+}
+
 static void str2mac(unsigned char *pmac, char *pch)
 {
        int i;
@@ -203,6 +247,7 @@ static int calib_valid_handler(struct nl_msg *msg, void *arg)
                }
                printf("++++++++++++++++++++++++\n");
 #endif
+       printf("Writing calibration data to %s\n", (char*) arg);
        if (prepare_nvs_file(prms, arg)) {
                fprintf(stderr, "Fail to prepare calibrated NVS file\n");
                return 2;
@@ -779,22 +824,17 @@ fail_out:
 COMMAND(plt, rx_statistics, NULL, 0, 0, CIB_NONE, plt_rx_statistics,
        "Get Rx statistics\n");
 
-static int plt_calibrate(struct nl80211_state *state, struct nl_cb *cb,
-                       struct nl_msg *msg, int argc, char **argv)
+static int plt_do_calibrate(struct nl80211_state *state, struct nl_cb *cb,
+                       struct nl_msg *msg, int single_dual, char *nvs_file,
+                       char *devname)
 {
        int ret = 0, err;
-       int single_dual = 0;
-
-       if (argc > 2 && (strncmp(argv[2], "dual", 4) ==  0))
-               single_dual = 1;        /* going for dual band calibration */
-       else
-               single_dual = 0;        /* going for single band calibration */
 
        /* power mode on */
        {
-               char *pm_on[4] = { "wlan0", "plt", "power_mode", "on" };
+               char *pm_on[4] = { devname, "plt", "power_mode", "on" };
 
-               err = handle_cmd(state, II_NETDEV, 4, pm_on);
+               err = handle_cmd(state, II_NETDEV, ARRAY_SIZE(pm_on), pm_on);
                if (err < 0) {
                        fprintf(stderr, "Fail to set PLT power mode on\n");
                        ret = err;
@@ -804,11 +844,11 @@ static int plt_calibrate(struct nl80211_state *state, struct nl_cb *cb,
 
        /* tune channel */
        {
-               char *pm_on[5] = {
-                       "wlan0", "plt", "tune_channel", "0", "7"
+               char *tune[5] = {
+                       devname, "plt", "tune_channel", "0", "7"
                };
 
-               err = handle_cmd(state, II_NETDEV, 5, pm_on);
+               err = handle_cmd(state, II_NETDEV, ARRAY_SIZE(tune), tune);
                if (err < 0) {
                        fprintf(stderr, "Fail to tune channel\n");
                        ret = err;
@@ -818,10 +858,11 @@ static int plt_calibrate(struct nl80211_state *state, struct nl_cb *cb,
 
        /* calibrate it */
        {
-               char *prms[11] = {
-                       "wlan0", "plt", "tx_bip", "1", "0", "0", "0",
-                       "0", "0", "0", "0"
+               char *prms[12] = {
+                       devname, "plt", "tx_bip", "1", "0", "0", "0",
+                       "0", "0", "0", "0", nvs_file
                };
+               printf("Calibrate %s\n", nvs_file);
 
                /* set flags in case of dual band */
                if (single_dual) {
@@ -829,9 +870,9 @@ static int plt_calibrate(struct nl80211_state *state, struct nl_cb *cb,
                                prms[9] = prms[10] = "1";
                }
 
-               err = handle_cmd(state, II_NETDEV, 11, prms);
+               err = handle_cmd(state, II_NETDEV, ARRAY_SIZE(prms), prms);
                if (err < 0) {
-                       fprintf(stderr, "Fail to calibrate\n");
+                       fprintf(stderr, "Failed to calibrate\n");
                        ret = err;
                }
        }
@@ -839,11 +880,11 @@ static int plt_calibrate(struct nl80211_state *state, struct nl_cb *cb,
 fail_out:
        /* power mode off */
        {
-               char *prms[4] = { "wlan0", "plt", "power_mode", "off"};
+               char *prms[4] = { devname, "plt", "power_mode", "off"};
 
-               err = handle_cmd(state, II_NETDEV, 4, prms);
+               err = handle_cmd(state, II_NETDEV, ARRAY_SIZE(prms), prms);
                if (err < 0) {
-                       fprintf(stderr, "Fail to set PLT power mode on\n");
+                       fprintf(stderr, "Failed to set PLT power mode on\n");
                        ret = err;
                }
        }
@@ -855,5 +896,109 @@ fail_out_final:
        return 0;
 }
 
+static int plt_calibrate(struct nl80211_state *state, struct nl_cb *cb,
+                       struct nl_msg *msg, int argc, char **argv)
+{
+       int single_dual = 0;
+
+       if (argc > 2 && (strncmp(argv[2], "dual", 4) ==  0))
+               single_dual = 1;        /* going for dual band calibration */
+       else
+               single_dual = 0;        /* going for single band calibration */
+
+       return plt_do_calibrate(state, cb, msg, single_dual, NEW_NVS_NAME,
+                               "wlan0");
+}
+
 COMMAND(plt, calibrate, "[<single|dual>]", 0, 0, CIB_NONE,
        plt_calibrate, "Do calibrate for single or dual band chip\n");
+
+
+static int plt_autocalibrate(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
+       };
+
+       char *devname, *modpath, *inifile1, *macaddr;
+       int single_dual = 0, res;
+
+       argc -= 2;
+       argv += 2;
+
+       if (argc != 5) {
+               return 1;
+       }
+
+       devname = *argv++;
+       argc--;
+
+       modpath = *argv++;
+       argc--;
+
+       inifile1 = *argv++;
+       argc--;
+
+       cmn.nvs_name = get_opt_nvsoutfile(argc--, argv++);
+       macaddr = *argv++;
+       argc--;
+
+       if (file_exist(cmn.nvs_name) >= 0) {
+               fprintf(stderr, "nvs file %s. File already exists. Won't overwrite.\n", cmn.nvs_name);
+               return 0;
+       }
+
+       /* Create ref nvs */
+       if (read_ini(inifile1, &cmn)) {
+               fprintf(stderr, "Failed to read ini file %s\n", inifile1);
+               goto out_removenvs;
+       }
+
+       /* Get nr bands from parsed ini */
+       single_dual = ini_get_dual_mode(&cmn);
+
+       cfg_nvs_ops(&cmn);
+
+       if (create_nvs_file(&cmn)) {
+               fprintf(stderr, "Failed to create reference NVS file\n");
+               return 1;
+       }
+
+       /* Load module */
+       res = insmod(modpath);
+       if (res) {
+               goto out_removenvs;
+       }
+
+       res = plt_do_calibrate(state, cb, msg, single_dual,
+                             cmn.nvs_name, devname);
+       if (res) {
+               goto out_rmmod;
+       }
+
+       res = nvs_set_mac(cmn.nvs_name, macaddr);
+       if (res) {
+               goto out_rmmod;
+       }
+
+       rmmod(modpath);
+       printf("Calibration done for 1 FEM in %s band. Resulting nvs is %s\n",
+              single_dual ? "dual" : "single",
+              cmn.nvs_name);
+       return 0;
+
+out_rmmod:
+       rmmod(modpath);
+
+out_removenvs:
+       fprintf(stderr, "Calibration not complete. Removing half-baked nvs\n");
+       unlink(cmn.nvs_name);
+       return 0;
+
+}
+COMMAND(plt, autocalibrate, "<dev> <module path> <ini file1> <nvs file> <mac addr> ", 0, 0, CIB_NONE,
+       plt_autocalibrate, "Do automatic calibration\n");
diff --git a/plt.h b/plt.h
index 7121beb20bd9b4378c4e058b499da8b56d147680..a4ab82c9fdc6f3a231a564b877461c22ac8d6d1f 100644 (file)
--- a/plt.h
+++ b/plt.h
@@ -2,9 +2,13 @@
 #define __PLT_H
 
 #ifdef ANDROID
-#define CURRENT_NVS_NAME "/system/etc/firmware/ti-connectivity/wl12xx-nvs.bin"
+#define CURRENT_NVS_NAME       "/system/etc/firmware/ti-connectivity/wl12xx-nvs.bin"
+#define INSMOD_PATH            "/system/bin/insmod"
+#define RMMOD_PATH             "/system/bin/rmmod"
 #else
-#define CURRENT_NVS_NAME "/lib/firmware/ti-connectivity/wl12xx-nvs.bin"
+#define CURRENT_NVS_NAME       "/lib/firmware/ti-connectivity/wl12xx-nvs.bin"
+#define INSMOD_PATH            "/sbin/insmod"
+#define RMMOD_PATH             "/sbin/rmmod"
 #endif
 #define NEW_NVS_NAME           "./new-nvs.bin"
 #define NVS_FILE_SIZE_127X     0x390