/** **************************************************************************************** * * @file rwnx_configparse.c * * Copyright (C) RivieraWaves 2012-2019 * **************************************************************************************** */ #include #include #include "rwnx_defs.h" #include "rwnx_cfgfile.h" /** * */ static const char *rwnx_find_tag(const u8 *file_data, unsigned int file_size, const char *tag_name, unsigned int tag_len) { unsigned int curr, line_start = 0, line_size; RWNX_DBG(RWNX_FN_ENTRY_STR); /* Walk through all the lines of the configuration file */ while (line_start < file_size) { /* Search the end of the current line (or the end of the file) */ for (curr = line_start; curr < file_size; curr++) if (file_data[curr] == '\n') break; /* Compute the line size */ line_size = curr - line_start; /* Check if this line contains the expected tag */ if ((line_size == (strlen(tag_name) + tag_len)) && (!strncmp(&file_data[line_start], tag_name, strlen(tag_name)))) return &file_data[line_start + strlen(tag_name)]; /* Move to next line */ line_start = curr + 1; } /* Tag not found */ return NULL; } /** * Parse the Config file used at init time */ int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename, struct rwnx_conf_file *config) { const struct firmware *config_fw; u8 dflt_mac[ETH_ALEN] = { 0, 111, 111, 111, 111, 0 }; int ret; const u8 *tag_ptr; RWNX_DBG(RWNX_FN_ENTRY_STR); ret = request_firmware(&config_fw, filename, rwnx_hw->dev); if (ret) { printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); return ret; } /* Get MAC Address */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "MAC_ADDR=", strlen("00:00:00:00:00:00")); if (tag_ptr != NULL) { u8 *addr = config->mac_addr; if (sscanf(tag_ptr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", addr + 0, addr + 1, addr + 2, addr + 3, addr + 4, addr + 5) != ETH_ALEN) memcpy(config->mac_addr, dflt_mac, ETH_ALEN); } else memcpy(config->mac_addr, dflt_mac, ETH_ALEN); RWNX_DBG("MAC Address is:\n%pM\n", config->mac_addr); /* Release the configuration file */ release_firmware(config_fw); return 0; } /** * Parse the Config file used at init time */ int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename, struct rwnx_phy_conf_file *config, int path) { const struct firmware *config_fw; int ret; const u8 *tag_ptr; RWNX_DBG(RWNX_FN_ENTRY_STR); ret = request_firmware(&config_fw, filename, rwnx_hw->dev); if (ret) { printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); return ret; } /* Get Trident path mapping */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "TRD_PATH_MAPPING=", strlen("00")); if (tag_ptr != NULL) { u8 val; if (sscanf(tag_ptr, "%hhx", &val) == 1) config->trd.path_mapping = val; else config->trd.path_mapping = path; } else config->trd.path_mapping = path; RWNX_DBG("Trident path mapping is: %d\n", config->trd.path_mapping); /* Get DC offset compensation */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "TX_DC_OFF_COMP=", strlen("00000000")); if (tag_ptr != NULL) { if (sscanf(tag_ptr, "%08x", &config->trd.tx_dc_off_comp) != 1) config->trd.tx_dc_off_comp = 0; } else config->trd.tx_dc_off_comp = 0; RWNX_DBG("TX DC offset compensation is: %08X\n", config->trd.tx_dc_off_comp); /* Get Karst TX IQ compensation value for path0 on 2.4GHz */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "KARST_TX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); if (tag_ptr != NULL) { if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[0]) != 1) config->karst.tx_iq_comp_2_4G[0] = 0x01000000; } else config->karst.tx_iq_comp_2_4G[0] = 0x01000000; RWNX_DBG("Karst TX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[0]); /* Get Karst TX IQ compensation value for path1 on 2.4GHz */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "KARST_TX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); if (tag_ptr != NULL) { if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[1]) != 1) config->karst.tx_iq_comp_2_4G[1] = 0x01000000; } else config->karst.tx_iq_comp_2_4G[1] = 0x01000000; RWNX_DBG("Karst TX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[1]); /* Get Karst RX IQ compensation value for path0 on 2.4GHz */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "KARST_RX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); if (tag_ptr != NULL) { if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[0]) != 1) config->karst.rx_iq_comp_2_4G[0] = 0x01000000; } else config->karst.rx_iq_comp_2_4G[0] = 0x01000000; RWNX_DBG("Karst RX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[0]); /* Get Karst RX IQ compensation value for path1 on 2.4GHz */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "KARST_RX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); if (tag_ptr != NULL) { if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[1]) != 1) config->karst.rx_iq_comp_2_4G[1] = 0x01000000; } else config->karst.rx_iq_comp_2_4G[1] = 0x01000000; RWNX_DBG("Karst RX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[1]); /* Get Karst TX IQ compensation value for path0 on 5GHz */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "KARST_TX_IQ_COMP_5G_PATH_0=", strlen("00000000")); if (tag_ptr != NULL) { if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[0]) != 1) config->karst.tx_iq_comp_5G[0] = 0x01000000; } else config->karst.tx_iq_comp_5G[0] = 0x01000000; RWNX_DBG("Karst TX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[0]); /* Get Karst TX IQ compensation value for path1 on 5GHz */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "KARST_TX_IQ_COMP_5G_PATH_1=", strlen("00000000")); if (tag_ptr != NULL) { if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[1]) != 1) config->karst.tx_iq_comp_5G[1] = 0x01000000; } else config->karst.tx_iq_comp_5G[1] = 0x01000000; RWNX_DBG("Karst TX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[1]); /* Get Karst RX IQ compensation value for path0 on 5GHz */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "KARST_RX_IQ_COMP_5G_PATH_0=", strlen("00000000")); if (tag_ptr != NULL) { if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[0]) != 1) config->karst.rx_iq_comp_5G[0] = 0x01000000; } else config->karst.rx_iq_comp_5G[0] = 0x01000000; RWNX_DBG("Karst RX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[0]); /* Get Karst RX IQ compensation value for path1 on 5GHz */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "KARST_RX_IQ_COMP_5G_PATH_1=", strlen("00000000")); if (tag_ptr != NULL) { if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[1]) != 1) config->karst.rx_iq_comp_5G[1] = 0x01000000; } else config->karst.rx_iq_comp_5G[1] = 0x01000000; RWNX_DBG("Karst RX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[1]); /* Get Karst default path */ tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, "KARST_DEFAULT_PATH=", strlen("00")); if (tag_ptr != NULL) { u8 val; if (sscanf(tag_ptr, "%hhx", &val) == 1) config->karst.path_used = val; else config->karst.path_used = path; } else config->karst.path_used = path; RWNX_DBG("Karst default path is: %d\n", config->karst.path_used); /* Release the configuration file */ release_firmware(config_fw); return 0; }