project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp: Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem. sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately. sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades. sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for fastboot. Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
4039 lines
124 KiB
C
4039 lines
124 KiB
C
#include <linux/module.h>
|
|
#include <linux/kobject.h>
|
|
#include <linux/kthread.h>
|
|
#include <linux/dcache.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/rtnetlink.h>
|
|
#include <net/net_namespace.h>
|
|
#include "apollo.h"
|
|
#include "bh.h"
|
|
#include "hwio.h"
|
|
#include "wsm.h"
|
|
#include "sbus.h"
|
|
#include "debug.h"
|
|
#include "apollo_plat.h"
|
|
#include "sta.h"
|
|
#include "ap.h"
|
|
#include "scan.h"
|
|
#include "module_fs.h"
|
|
#include "svn_version.h"
|
|
#include "internal_cmd.h"
|
|
#ifdef CONFIG_ATBM_MOULE_FS
|
|
#define PARAMAS_SET BIT(0)
|
|
#define PARAMAS_ON BIT(1)
|
|
static bool enable_echo = true;
|
|
static int num_echo = -1;
|
|
|
|
#define ATBM_SHOW_MSG_MAX_SIZE PAGE_SIZE
|
|
|
|
|
|
#define ATBM_CODE__EXAMPLE_CODE 0
|
|
#define ATBM_CODE__MAX 1
|
|
|
|
extern struct atbm_common *g_hw_priv;
|
|
|
|
#define atbm_show_init(show,_buff) rcu_assign_pointer((show)->show_buff,_buff); \
|
|
(show)->show_count = 0; \
|
|
(show)->show_size = ATBM_SHOW_MSG_MAX_SIZE; \
|
|
(show)->overflow = 0
|
|
#define atbm_show_deinit(show) rcu_assign_pointer((show)->show_buff,NULL); \
|
|
(show)->show_count = 0; \
|
|
(show)->show_size=0; \
|
|
(show)->overflow = 0
|
|
#define atbm_module_show_put(_show,...) \
|
|
do{ \
|
|
int ret = 0; \
|
|
char *_show_buff; \
|
|
rcu_read_lock(); \
|
|
_show_buff = rcu_dereference((_show)->show_buff); \
|
|
if((_show_buff == NULL)||((_show)->overflow == 1) || ((_show)->show_size<=(_show)->show_count)){\
|
|
if(_show_buff) atbm_printk_debug("overflow(%d),show_size(%d),show_count(%d)\n",(_show)->overflow,(_show)->show_size,(_show)->show_count); \
|
|
rcu_read_unlock(); \
|
|
break; \
|
|
} \
|
|
ret = snprintf(_show_buff+(_show)->show_count,(_show)->show_size-(_show)->show_count,__VA_ARGS__); \
|
|
if(ret>=0){ \
|
|
(_show)->show_count+=ret; \
|
|
if((_show)->show_count >= (_show)->show_size){ \
|
|
(_show)->show_count = (_show)->show_size; \
|
|
(_show)->overflow = 1; \
|
|
} \
|
|
} \
|
|
else{ \
|
|
(_show)->overflow = 1; \
|
|
atbm_printk_always("buff overflow(%d)(%d)\n",(_show)->show_size,(_show)->show_count); \
|
|
} \
|
|
rcu_read_unlock(); \
|
|
}while(0)
|
|
|
|
#define atbm_module_put(_show,_src,_len) \
|
|
do{ \
|
|
char *_show_buff; \
|
|
if((_show)->show_count+_len>(_show)->show_size) \
|
|
(_show)->overflow = 1; \
|
|
if((_show)->overflow) break; \
|
|
rcu_read_lock(); \
|
|
_show_buff = rcu_dereference((_show)->show_buff); \
|
|
if(_show_buff == NULL){ \
|
|
rcu_read_unlock(); \
|
|
break; \
|
|
} \
|
|
memcpy(_show_buff+(_show)->show_count,_src,_len); \
|
|
(_show)->show_count += _len; \
|
|
rcu_read_unlock(); \
|
|
}while(0)
|
|
|
|
struct mutex atbm_module_fs_lock;
|
|
#define atbm_modulefs_lock_int() mutex_init(&atbm_module_fs_lock)
|
|
#define atbm_modulefs_lock() mutex_lock(&atbm_module_fs_lock)
|
|
#define atbm_modulefs_unlock() mutex_unlock(&atbm_module_fs_lock)
|
|
#define atbm_modulefs_trylock() mutex_trylock(&atbm_module_fs_lock)
|
|
#define atbm_modulefs_lock_release() mutex_destroy(&atbm_module_fs_lock)
|
|
#define atbm_modulefs_lock_check() lockdep_assert_held(&atbm_module_fs_lock)
|
|
|
|
struct atbm_module_show
|
|
{
|
|
char __rcu *show_buff;
|
|
int show_count;
|
|
int show_size;
|
|
int overflow;
|
|
};
|
|
|
|
struct atbm_sting_s{
|
|
const char *string;
|
|
const char *string_pos;
|
|
struct hlist_node hnode;
|
|
bool found;
|
|
unsigned int len;
|
|
unsigned int params;
|
|
bool (*string_func)(const char *pos_l,const char *pos_r,void *priv);
|
|
void *priv;
|
|
};
|
|
#define ATBM_STRING_MAX_LEN 32
|
|
#define ATBM_STRING_HASHBITS 4
|
|
#define ATBM_STRING_HASHENTRIES (1 << ATBM_STRING_HASHBITS)
|
|
|
|
#define ATBM_STRING_TABLE_INIT(_string,_string_func,_priv) \
|
|
{ \
|
|
.string = _string, \
|
|
.string_pos = NULL, \
|
|
.found = 0, \
|
|
.len = 0, \
|
|
.params = 0, \
|
|
.string_func = _string_func, \
|
|
.priv = _priv, \
|
|
}
|
|
/*
|
|
*
|
|
*atbm log level control fs
|
|
*
|
|
*/
|
|
u32 atbm_printk_mask = ATBM_PRINTK_DEFAULT_MASK;
|
|
module_param(atbm_printk_mask, int, 0644);
|
|
|
|
struct atbm_printk_mask_table_s {
|
|
const char *mask_string;
|
|
const char *mask_info;
|
|
u32 mask_val;
|
|
struct hlist_node string_hnode;
|
|
};
|
|
#define ATBM_PRINTK_MAX_STRING_LEN 32
|
|
#define ATBM_PRINTK_HASHBITS 4
|
|
#define ATBM_PRINTK_HASHENTRIES (1 << ATBM_PRINTK_HASHBITS)
|
|
#define LOG_ON "ON"
|
|
#define LOG_OFF "OFF"
|
|
#define LOG_ALL "OPEN_ALL"
|
|
#define LOG_DEFAULT "DEFAULT"
|
|
#define LOG_CLEAR "CLEAR"
|
|
#define ATBM_BRA_L '['
|
|
#define ATBM_BRA_R ']'
|
|
#define ATBM_ANG_L '<'
|
|
#define ATBM_ANG_R '>'
|
|
|
|
#define ATBM_PARAML ATBM_BRA_L
|
|
#define ATBM_PARAMR ATBM_BRA_R
|
|
#define ATBM_PARAML_S ATBM_ANG_L
|
|
#define ATBM_PARAMR_S ATBM_ANG_R
|
|
|
|
#define atbm_string_invalid(_header) (((_header) != ATBM_SPACE)&&((_header) != ATBM_LINEF)&&((_header) != ATBM_ENTER)&&((_header) != ATBM_TAIL))
|
|
#define OPTION_TABLE_INIT(string,val) \
|
|
{ \
|
|
.opton_string = string, \
|
|
.option_val = val, \
|
|
}
|
|
#define LOG_TABLE_INIT(string,info,val) \
|
|
{ \
|
|
.mask_string = string, \
|
|
.mask_info = info, \
|
|
.mask_val = val, \
|
|
}
|
|
struct atbm_option_table_s {
|
|
const char *opton_string;
|
|
u32 option_val;
|
|
};
|
|
|
|
struct hlist_head atbm_printk_hash_head[ATBM_PRINTK_HASHENTRIES];
|
|
static const struct atbm_option_table_s option_table[]={
|
|
OPTION_TABLE_INIT(LOG_ON,1),
|
|
OPTION_TABLE_INIT(LOG_OFF,0),
|
|
};
|
|
static struct atbm_printk_mask_table_s printk_mask_table[] = {
|
|
LOG_TABLE_INIT("LOG_ERR", "output err level log",ATBM_PRINTK_MASK_ERR),
|
|
LOG_TABLE_INIT("LOG_WARN","output warn level log",ATBM_PRINTK_MASK_WARN),
|
|
LOG_TABLE_INIT("LOG_INIT","output init level log",ATBM_PRINTK_MASK_INIT),
|
|
LOG_TABLE_INIT("LOG_EXIT","output exit level log",ATBM_PRINTK_MASK_EXIT),
|
|
LOG_TABLE_INIT("LOG_BUS", "output bus level log",ATBM_PRINTK_MASK_BUS),
|
|
LOG_TABLE_INIT("LOG_SCAN","output scan level log",ATBM_PRINTK_MASK_SCAN),
|
|
LOG_TABLE_INIT("LOG_P2P", "output p2p level log",ATBM_PRINTK_MASK_P2P),
|
|
LOG_TABLE_INIT("LOG_MGMT","output mgmt level log",ATBM_PRINTK_MASK_MGMT),
|
|
LOG_TABLE_INIT("LOG_LMAC","output lmac level log",ATBM_PRINTK_MASK_LMAC),
|
|
LOG_TABLE_INIT("LOG_AGG", "output agg level log",ATBM_PRINTK_MASK_AGG),
|
|
LOG_TABLE_INIT("LOG_AP", "output ap level log",ATBM_PRINTK_MASK_AP),
|
|
LOG_TABLE_INIT("LOG_STA", "output sta level log",ATBM_PRINTK_MASK_STA),
|
|
LOG_TABLE_INIT("LOG_SMT", "output smart config level log",ATBM_PRINTK_MASK_SMARTCONFIG),
|
|
LOG_TABLE_INIT("LOG_WEXT","output wext level log",ATBM_PRINTK_MASK_WEXT),
|
|
LOG_TABLE_INIT("LOG_TX", "output tx level log",ATBM_PRINTK_MASK_TX),
|
|
LOG_TABLE_INIT("LOG_RX", "output rx level log",ATBM_PRINTK_MASK_RX),
|
|
LOG_TABLE_INIT("LOG_PM", "output pm level log",ATBM_PRINTK_MASK_PM),
|
|
LOG_TABLE_INIT("LOG_PLATFORM","output platform level log",ATBM_PRINTK_MASK_PLATFROM),
|
|
LOG_TABLE_INIT("LOG_BH", "output bh level log",ATBM_PRINTK_MASK_BH),
|
|
LOG_TABLE_INIT("LOG_CFG80211","output cfg80211 level log",ATBM_PRINTK_MASK_CFG80211),
|
|
LOG_TABLE_INIT("LOG_DEBUG","output cfg80211 level log",ATBM_PRINTK_MASK_DEBUG),
|
|
};
|
|
/*
|
|
*
|
|
*atbm cmd fs control
|
|
*
|
|
*/
|
|
struct atbm_store_cmd_code {
|
|
const char *label;
|
|
const char *cmd_info;
|
|
void __rcu *cmd_private;
|
|
bool (*code_cmd)(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len);
|
|
ssize_t (*show_cmd)(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,char *buf,bool show);
|
|
bool echo_enable;
|
|
bool echo_ready;
|
|
struct atbm_module_show echo;
|
|
struct hlist_node hnode;
|
|
struct list_head lhead;
|
|
};
|
|
#define ATBM_SCAN_HASHBITS ATBM_COMMON_HASHBITS
|
|
#define ATBM_SCAN_HASHENTRIES (1 << ATBM_SCAN_HASHBITS)
|
|
|
|
struct atbm_conf_ifname{
|
|
u8 if_name[IFNAMSIZ];
|
|
u8 size;
|
|
};
|
|
|
|
struct atbm_conf_channels{
|
|
u8 *channels;
|
|
u8 n_channels;
|
|
};
|
|
|
|
struct atbm_conf_ssids{
|
|
struct cfg80211_ssid *ssids;
|
|
u8 n_ssids;
|
|
};
|
|
|
|
struct atbm_conf_macs{
|
|
struct ieee80211_internal_mac *mac;
|
|
u8 n_macs;
|
|
};
|
|
|
|
struct atbm_conf_ies{
|
|
u8 *ies;
|
|
u8 ie_len;
|
|
u8 atbm_ie;
|
|
};
|
|
struct atbm_conf_integer{
|
|
int *integers;
|
|
u8 n_integers;
|
|
};
|
|
struct atbm_conf_string
|
|
{
|
|
char *strings;
|
|
struct hlist_node hnode;
|
|
bool set;
|
|
};
|
|
struct atbm_config_string_hash
|
|
{
|
|
struct hlist_head hlist_head[ATBM_COMMON_HASHENTRIES];
|
|
bool empty;
|
|
};
|
|
struct atbm_module_ap_conf{
|
|
struct atbm_conf_ifname ifname;
|
|
struct atbm_conf_channels channel;
|
|
struct atbm_conf_ssids ssid;
|
|
struct atbm_conf_macs bssid;
|
|
};
|
|
struct atbm_module_set_mode_conf{
|
|
struct atbm_conf_ifname ifname;
|
|
struct atbm_conf_channels channel;
|
|
enum ieee80211_internal_iftype iftype;
|
|
};
|
|
struct atbm_module_halt_conf{
|
|
struct atbm_conf_ifname ifname;
|
|
};
|
|
struct atbm_scan_params{
|
|
struct atbm_conf_channels channels;
|
|
struct atbm_conf_ssids ssids;
|
|
struct atbm_conf_macs macs;
|
|
struct atbm_conf_ies ies;
|
|
bool positive;
|
|
};
|
|
struct atbm_start_monitor_params{
|
|
struct atbm_conf_channels channel;
|
|
u8 channeltype;
|
|
};
|
|
|
|
struct atbm_stainfo_req_params{
|
|
enum nl80211_iftype type;
|
|
struct atbm_conf_macs req_mac;
|
|
u8 req_channel;
|
|
u8 req_rssi;
|
|
u8 req_rate;
|
|
u8 req_txrxbytes;
|
|
u8 req_ssid;
|
|
};
|
|
|
|
struct atbm_wsm_req_parmas{
|
|
u8 req_adaptive;
|
|
u8 req_pwrdcxo;
|
|
u8 req_pwr;
|
|
int txpwr_dcxo[4];
|
|
u8 dcxo_index;
|
|
int txpwr;
|
|
};
|
|
struct atbm_probe_request{
|
|
struct atbm_conf_ies ies;
|
|
struct atbm_conf_integer n_request;
|
|
};
|
|
|
|
struct atbm_sta_listen{
|
|
struct atbm_conf_ifname ifname;
|
|
struct atbm_conf_channels channel;
|
|
};
|
|
|
|
struct atbm_ap_set_beacon{
|
|
struct atbm_conf_ifname ifname;
|
|
struct atbm_conf_ies ies;
|
|
};
|
|
|
|
struct atbm_special_freq{
|
|
struct atbm_conf_integer channel;
|
|
struct atbm_conf_integer freq;
|
|
};
|
|
struct atbm_channel_auto_select{
|
|
struct atbm_conf_integer start_channel;
|
|
struct atbm_conf_integer end_channel;
|
|
struct atbm_conf_integer version;
|
|
struct atbm_conf_channels channels;
|
|
};
|
|
|
|
struct atbm_echo_params{
|
|
int num;
|
|
};
|
|
#define ATBM_CMD_MAX_STRING_LEN 32
|
|
#define ATBM_CMD_HASHBITS 4
|
|
#define ATBM_CMD_HASHENTRIES (1 << ATBM_CMD_HASHBITS)
|
|
|
|
#define ATBM_CODE_STR__ATTR_EXAMPLE_INFO "show example"
|
|
#define ATBM_CODE_STR__ATTR_HELP_INFO "show all cmd help info"
|
|
#define ATBM_CODE_STR__ATTR_SCAN_INFO "sta scan: scan channel=[1][2][3] ssid=[ap1][ap2] private=[ie]or<ie> mac=[mac1][mac2]"
|
|
#define ATBM_CODE_STR__ATTR_START_MONITOR_INFO "start_monitor: start_monitor channel=[x]"
|
|
#define ATBM_CODE_STR__ATTR_STOP_MONITOR_INFO "stop monitor:stop_monitor"
|
|
#define ATBM_CODE_STR__ATTR_ENABLE_ECHO_INFO "enable echo parmas:enable_echo num_echo=[1]"
|
|
#define ATBM_CODE_STR__ATTR_DISABLE_ECHO_INFO "disable echo:disable_echo"
|
|
#define ATBM_CODE_STR__ATTR_AP_INFO_INFO "get ap info:ap_info req=[rssi][channel[toprate][txrxbytes][ssid]"
|
|
#define ATBM_CODE_STR__ATTR_STA_INFO_INFO "get ap info:sta_info req=[rssi][channel[toprate][txrxbytes][ssid] mac=[mac1][mac2]"
|
|
#define ATBM_CODE_STR__ATTR_WSM_CMD_INFRO "wsm cmd:wsm_cmd adaptive=[on or off] txpwr_dcxo=[M][H][L][dcxo] txpwr=[power]"
|
|
#define ATBM_CODE_STR__ATTR_MONITOR_SEND_PROBER_INFO "monitor/sta interface send probe request send_probe num=[number of probe request] private=[ie]"
|
|
#ifdef CONFIG_ATBM_STA_LISTEN
|
|
#define ATBM_CODE_STR__ATTR_STA_LISTEN_INFO "sta_listen: sta_listen ifname=[wlan0 or p2p0 or other] channel=[x]"
|
|
#endif
|
|
#define ATBM_CODE_STR__ATTR_AP_BEACON_SPECIAL_IFFO "set_beacon: ap mode set special beacon,set_beacon ifname=[wlan0 of p2p0] special=[some special ie]"
|
|
|
|
#define ATBM_CODE_STR__ATTR_SET_FREQ_INFO "set_freq: set special freq,set_freq channel=[xx],freq=[2300~2600]"
|
|
#define ATBM_CODE_STR__ATTR_CLEAR_FREQ_INFO "clear_freq: clear special freq,clear_freq channel=[xx]"
|
|
#define ATBM_CODE_STR__ATTR_CHIP_VER_INFO "chip_ver: get the version of the current running chip(6032/6038/6032i)"
|
|
#define ATBM_CODE_STR__ATTR_CH_SELECT_INFO "auto channel select:channel_select start=[x] end=[y] version=[0 or 1]"
|
|
#define ATBM_CODE_STR__ATTR_STA_SPECIAL_SCAN_INFO "special_scan:channel=[1][2][3] ssid=[ap1] private=[ie] positive=[true or false]"
|
|
#define ATBM_CODE_STR__ATTR_CHIP_VERSION_INFO "chip_version:get version of current running chip"
|
|
#define ATBM_CODE_STR__ATTR_AP_CONF_INFO "set ap configs:ap_config ifname=[xxx] channel=[x] ssid=[ap] bssid=[xx:xx:xx:xx:xx:xx]"
|
|
#define ATBM_CODE_STR__ATTR_SET_MODE_INFO "set if mode:set_mode ifname=[xxxx] mode=[managed/monitor] channel=[x]"
|
|
#define ATBM_CODE_STR__ATTR_HALT_INFO "halt:halt ifname[xxxx]"
|
|
|
|
|
|
#define ATBM_CODE_STR__ATTR_EXAMPLE "example"
|
|
#define ATBM_CODE_STR__ATTR_HELP "help"
|
|
#define ATBM_CODE_STR__ATTR_ENABLE_ECHO "enable_echo"
|
|
#define ATBM_CODE_STR__ATTR_DISABLE_ECHO "disable_echo"
|
|
#define ATBM_CODE_STR__ATTR_SCAN "scan"
|
|
#define ATBM_CODE_STR__ATTR_START_MONITOR "start_monitor"
|
|
#define ATBM_CODE_STR__ATTR_STOP_MONITOR "stop_monitor"
|
|
#define ATBM_CODE_STR__ATTR_AP_INFO "ap_info"
|
|
#define ATBM_CODE_STR__ATTR_STA_INFO "sta_info"
|
|
#define ATBM_CODE_STR__ATTR_WSM_CMD "wsm_cmd"
|
|
#define ATBM_CODE_STR__ATTR_MONITOR_SEND_PROBER "send_probe"
|
|
#ifdef CONFIG_ATBM_STA_LISTEN
|
|
#define ATBM_CODE_STR__ATTR_STA_LISTEN "sta_listen"
|
|
#endif
|
|
#define ATBM_CODE_STR__ATTR_AP_BEACON_SPECIAL "set_beacon"
|
|
#define ATBM_CODE_STR__ATTR_SET_FREQ "set_freq"
|
|
#define ATBM_CODE_STR__ATTR_CLEAR_FREQ "clear_freq"
|
|
#define ATBM_CODE_STR__ATTR_CHIP_VER "chip_ver"
|
|
#define ATBM_CODE_STR__ATTR_CH_SELECT "channel_select"
|
|
#define ATBM_CODE_STR__ATTR_STA_SPECIAL_SCAN "special_scan"
|
|
#define ATBM_CODE_STR__ATTR_CHIP_VERSION "chip_version"
|
|
#define ATBM_CODE_STR__ATTR_AP_CONF "ap_config"
|
|
#define ATBM_CODE_STR__ATTR_SET_MODE "set_mode"
|
|
#define ATBM_CODE_STR__ATTR_HALT "halt"
|
|
|
|
|
|
|
|
struct hlist_head atbm_cmd_hash_head[ATBM_CMD_HASHENTRIES];
|
|
struct list_head atbm_cmd_echo_ready_list;
|
|
static char *backup_show = NULL;
|
|
static int backup_show_size = 0;
|
|
static int ready_list_num = 0;
|
|
|
|
#define ATBM_CMD_INIT(cmd_code,info,_store_cmd,_show_cmd)\
|
|
{ \
|
|
.label = cmd_code, \
|
|
.cmd_info = info, \
|
|
.code_cmd = _store_cmd, \
|
|
.show_cmd = _show_cmd, \
|
|
.cmd_private = NULL, \
|
|
}
|
|
static bool atbm_module_attr_echo_enable(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len);
|
|
static bool atbm_module_attr_echo_disable(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len);
|
|
static bool atbm_module_attr_example(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len);
|
|
static bool atbm_module_attr_help(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len);
|
|
static bool atbm_module_attr_scan(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len);
|
|
static ssize_t atbm_module_attr_default_show(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_code,char *buf,bool show);
|
|
static bool atbm_module_attr_start_monitor(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len);
|
|
static ssize_t atbm_module_attr_start_monitor_show(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,char *buf,bool show);
|
|
static ssize_t atbm_module_attr_stop_monitor_show(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,char *buf,bool show);
|
|
static bool atbm_module_attr_stop_monitor(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
static bool atbm_module_attr_ap_info(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
static bool atbm_module_attr_sta_info(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
static bool atbm_module_attr_wsm_cmd(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
|
|
static bool atbm_module_attr_send_probe_request(struct atbm_common *hw_priv,
|
|
struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
#ifdef CONFIG_ATBM_STA_LISTEN
|
|
static bool atbm_module_attr_sta_listen(struct atbm_common *hw_priv,
|
|
struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
#endif
|
|
static bool atbm_module_attr_ap_set_beacon(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
static bool atbm_module_attr_sta_special_scan(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
|
|
static bool atbm_module_attr_set_freq(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
static bool atbm_module_attr_clear_freq(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
static ssize_t atbm_module_attr_channel_select_show(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,char *buf,bool show);
|
|
static bool atbm_module_attr_channel_select(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
static bool atbm_module_attr_chip_version(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
#ifdef CONFIG_ATBM_SUPPORT_AP_CONFIG
|
|
static bool atbm_module_attr_set_ap_config(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
#endif
|
|
static bool atbm_module_attr_set_mode(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
static bool atbm_module_attr_halt(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len);
|
|
|
|
struct atbm_store_cmd_code cmd_code_buff[]={
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_HELP,ATBM_CODE_STR__ATTR_HELP_INFO,atbm_module_attr_help,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_EXAMPLE,ATBM_CODE_STR__ATTR_EXAMPLE_INFO,atbm_module_attr_example,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_DISABLE_ECHO,ATBM_CODE_STR__ATTR_DISABLE_ECHO_INFO,atbm_module_attr_echo_disable,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_ENABLE_ECHO,ATBM_CODE_STR__ATTR_ENABLE_ECHO_INFO,atbm_module_attr_echo_enable,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_SCAN,ATBM_CODE_STR__ATTR_SCAN_INFO,atbm_module_attr_scan,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_START_MONITOR,ATBM_CODE_STR__ATTR_START_MONITOR_INFO,atbm_module_attr_start_monitor,atbm_module_attr_start_monitor_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_STOP_MONITOR,ATBM_CODE_STR__ATTR_STOP_MONITOR_INFO,atbm_module_attr_stop_monitor,atbm_module_attr_stop_monitor_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_AP_INFO,ATBM_CODE_STR__ATTR_AP_INFO_INFO,atbm_module_attr_ap_info,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_STA_INFO,ATBM_CODE_STR__ATTR_STA_INFO_INFO,atbm_module_attr_sta_info,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_WSM_CMD,ATBM_CODE_STR__ATTR_WSM_CMD_INFRO,atbm_module_attr_wsm_cmd,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_MONITOR_SEND_PROBER,ATBM_CODE_STR__ATTR_MONITOR_SEND_PROBER_INFO,atbm_module_attr_send_probe_request,atbm_module_attr_default_show),
|
|
#ifdef CONFIG_ATBM_STA_LISTEN
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_STA_LISTEN,ATBM_CODE_STR__ATTR_STA_LISTEN_INFO,atbm_module_attr_sta_listen,atbm_module_attr_default_show),
|
|
#endif
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_AP_BEACON_SPECIAL,ATBM_CODE_STR__ATTR_AP_BEACON_SPECIAL_IFFO,atbm_module_attr_ap_set_beacon,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_STA_SPECIAL_SCAN,ATBM_CODE_STR__ATTR_STA_SPECIAL_SCAN_INFO,atbm_module_attr_sta_special_scan,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_SET_FREQ,ATBM_CODE_STR__ATTR_SET_FREQ_INFO,atbm_module_attr_set_freq,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_CLEAR_FREQ,ATBM_CODE_STR__ATTR_CLEAR_FREQ_INFO,atbm_module_attr_clear_freq,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_CH_SELECT,ATBM_CODE_STR__ATTR_CH_SELECT_INFO,atbm_module_attr_channel_select,atbm_module_attr_channel_select_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_CHIP_VERSION,ATBM_CODE_STR__ATTR_CHIP_VERSION_INFO,atbm_module_attr_chip_version,atbm_module_attr_default_show),
|
|
#ifdef CONFIG_ATBM_SUPPORT_AP_CONFIG
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_AP_CONF,ATBM_CODE_STR__ATTR_AP_CONF_INFO,atbm_module_attr_set_ap_config,atbm_module_attr_default_show),
|
|
#endif
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_SET_MODE,ATBM_CODE_STR__ATTR_SET_MODE_INFO,atbm_module_attr_set_mode,atbm_module_attr_default_show),
|
|
ATBM_CMD_INIT(ATBM_CODE_STR__ATTR_HALT,ATBM_CODE_STR__ATTR_HALT_INFO,atbm_module_attr_halt,atbm_module_attr_default_show),
|
|
};
|
|
|
|
static unsigned int atbm_hash_string_len(const char *pos,unsigned int pos_len)
|
|
{
|
|
unsigned int i;
|
|
unsigned int j;
|
|
|
|
if(pos == NULL){
|
|
return 0;
|
|
}
|
|
for(i = 0;i<pos_len;i++){
|
|
if(pos[i] != ATBM_SPACE)
|
|
continue;
|
|
for(j = i;j<pos_len;j++){
|
|
if(pos[j] != ATBM_SPACE)
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
static int atbm_cmd_string_split(const char *pos,int len,const char **pos_l,const char **pos_r)
|
|
{
|
|
int i = 0;
|
|
int j = 0;
|
|
const char *l = NULL;
|
|
const char *r = NULL;
|
|
char next_pos;
|
|
|
|
if(len == 0){
|
|
return -1;
|
|
}
|
|
atbm_printk_debug("%s:%d %s\n",__func__,len,pos);
|
|
for(i = 0;i<len;i++){
|
|
|
|
if((pos[i] == ATBM_PARAMR)||(pos[i] == ATBM_PARAMR_S)){
|
|
atbm_printk_debug("%s:left pos err\n",__func__);
|
|
return -1;
|
|
}
|
|
|
|
if((pos[i] != ATBM_PARAML)&&(pos[i] != ATBM_PARAML_S)){
|
|
continue;
|
|
}
|
|
l = &pos[i];
|
|
next_pos = pos[i] == ATBM_PARAML ? ATBM_PARAMR:ATBM_PARAMR_S;
|
|
for(j = i+1;j<len;j++){
|
|
|
|
if((pos[j] == ATBM_PARAML)||(pos[j] == ATBM_PARAML_S)){
|
|
atbm_printk_debug("%s:right pos err\n",__func__);
|
|
return -1;
|
|
}
|
|
|
|
if(pos[j] != next_pos){
|
|
continue;
|
|
}
|
|
r = &pos[j];
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if((l == NULL) && (r == NULL)){
|
|
return 0;
|
|
}else if((l == NULL) || (r == NULL)){
|
|
return -1;
|
|
}
|
|
|
|
*pos_l = l;
|
|
*pos_r = r;
|
|
|
|
return *l == ATBM_PARAML ? 1: 2;
|
|
}
|
|
static bool atbm_string_parase_echo(const char *pos_l,const char *pos_r,void *priv)
|
|
{
|
|
#define ECHO_ENABLE "enable"
|
|
#define ECHO_DISABLE "disable"
|
|
struct atbm_store_cmd_code *cmd_store = (struct atbm_store_cmd_code *)priv;
|
|
|
|
if(pos_r <= pos_l){
|
|
atbm_printk_debug("%s:len err\n",__func__);
|
|
return false;
|
|
}
|
|
|
|
if((strlen(ECHO_ENABLE) == pos_r-pos_l)&&(!memcmp(ECHO_ENABLE,pos_l, pos_r-pos_l))){
|
|
atbm_printk_debug("%s:echo enanle\n",__func__);
|
|
cmd_store->echo_enable = true;
|
|
}else if((strlen(ECHO_DISABLE) == pos_r-pos_l)&&(!memcmp(ECHO_DISABLE,pos_l, pos_r-pos_l))){
|
|
atbm_printk_debug("%s:echo disable\n",__func__);
|
|
cmd_store->echo_enable = false;
|
|
}else {
|
|
atbm_printk_debug("%s:unkown echo %s\n",__func__,pos_l);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
static bool atbm_string_parase(struct atbm_store_cmd_code *cmd_store,struct atbm_sting_s *string_table,unsigned int table_size,const char *string,unsigned int string_len)
|
|
{
|
|
#define CMD_ECHO_STR "echo="
|
|
unsigned int index = 0;
|
|
const char *pos = string;
|
|
const char *pos_end = string+string_len;
|
|
const char *nospace_pos;
|
|
const char *target_pos;
|
|
struct hlist_head *hhead;
|
|
struct hlist_node *node;
|
|
struct hlist_head atbm_string_hash_head[ATBM_STRING_HASHENTRIES];
|
|
struct atbm_sting_s *string_node;
|
|
struct atbm_sting_s echo_str;
|
|
unsigned int hash_index = 0;
|
|
|
|
if(table_size < 0){
|
|
return false;
|
|
}
|
|
|
|
memset(&echo_str,0,sizeof(struct atbm_sting_s));
|
|
|
|
echo_str.string = CMD_ECHO_STR;
|
|
echo_str.priv = cmd_store;
|
|
echo_str.string_func = atbm_string_parase_echo;
|
|
atbm_common_hash_list_init(atbm_string_hash_head,ATBM_STRING_HASHENTRIES);
|
|
/*
|
|
*first add echo string
|
|
*/
|
|
hash_index = atbm_hash_index(echo_str.string,strlen(echo_str.string),ATBM_STRING_HASHBITS);
|
|
hlist_add_head(&echo_str.hnode,&atbm_string_hash_head[hash_index]);
|
|
|
|
/*
|
|
*second add requset string
|
|
*/
|
|
for(index = 0;index<table_size;index++){
|
|
unsigned int hash_index = atbm_hash_index(string_table[index].string,
|
|
strlen(string_table[index].string),ATBM_STRING_HASHBITS);
|
|
if(strlen(string_table[index].string) > ATBM_STRING_MAX_LEN){
|
|
atbm_printk_err("%s %d ,ERROR !!! strlen(string_table[index].string) = %d > 16\n",
|
|
__func__,__LINE__,strlen(string_table[index].string));
|
|
return false;
|
|
}
|
|
hhead = &atbm_string_hash_head[hash_index];
|
|
|
|
hlist_for_each(node,hhead){
|
|
string_node = hlist_entry(node,struct atbm_sting_s,hnode);
|
|
if ((!strncmp(string_node->string, string_table[index].string, strlen(string_table[index].string)))&&
|
|
(strlen(string_table[index].string) == strlen(string_node->string))){
|
|
atbm_printk_debug("%s:string_node(%s) already in list\n",__func__,string_node->string);
|
|
return false;
|
|
}
|
|
}
|
|
hlist_add_head(&string_table[index].hnode,&atbm_string_hash_head[hash_index]);
|
|
atbm_printk_debug("%s:[%s]->[%d]\n",__func__,string_table[index].string,hash_index);
|
|
}
|
|
|
|
atbm_printk_debug("%s:len:%d tring:%s\n",__func__,string_len,pos);
|
|
while(pos<pos_end){
|
|
next_str:
|
|
/*
|
|
*pos <= pos_end will return null,and break the loop
|
|
*/
|
|
nospace_pos = atbm_skip_space(pos,pos_end-pos);
|
|
|
|
if(nospace_pos == NULL){
|
|
atbm_printk_debug("%s nospace_pos == NULL\n",__func__);
|
|
return pos == string ? false: true;
|
|
}
|
|
|
|
pos = nospace_pos;
|
|
atbm_printk_debug("%s:len:%zu nospace_pos:%s\n",__func__,pos_end-pos,nospace_pos);
|
|
if(pos[0] == ATBM_TAIL)
|
|
return pos == string?false: true;
|
|
else if((pos[0] == ATBM_LINEF)||(pos[0] == ATBM_ENTER))
|
|
return pos == string?false: true;
|
|
/*
|
|
*find the postion of cmd end =
|
|
*/
|
|
target_pos = memchr(pos, ATBM_EQUAL, pos_end-pos);
|
|
if(target_pos == NULL){
|
|
atbm_printk_always("%s:can not cmd =\n",__func__);
|
|
return false;
|
|
}
|
|
atbm_printk_debug("%s:len:%zu,str %s\n",__func__,target_pos-pos+1,pos);
|
|
hhead = atbm_hash_list(pos,target_pos-pos+1,atbm_string_hash_head,ATBM_STRING_HASHBITS);
|
|
|
|
if(hhead == NULL){
|
|
atbm_printk_always("%s:hhead = NULL\n",__func__);
|
|
return false;
|
|
}
|
|
hlist_for_each(node,hhead){
|
|
|
|
string_node = hlist_entry(node,struct atbm_sting_s,hnode);
|
|
atbm_printk_debug("%s:string_node(%s)(%zu),target:%zu:%s\n",__func__,
|
|
string_node->string,strlen(string_node->string),target_pos-pos+1,pos);
|
|
if ((!strncmp(pos, string_node->string,target_pos-pos+1))&&
|
|
(strlen(string_node->string) == target_pos-pos+1)){
|
|
|
|
const char *tmp_pos = NULL;
|
|
if(string_node->found == true){
|
|
atbm_printk_debug("%s:fund same string(%s)\n",__func__,string_node->string);
|
|
return false;
|
|
}
|
|
tmp_pos = atbm_skip_space(target_pos+1,string_len - (target_pos+1-string));
|
|
|
|
if(tmp_pos == NULL){
|
|
atbm_printk_always("%s:tmp_pos == NULL\n",__func__);
|
|
return false;
|
|
}
|
|
string_node->found = true;
|
|
string_node->string_pos = tmp_pos;
|
|
string_node->len = pos_end-tmp_pos;
|
|
|
|
if((tmp_pos[0] != ATBM_PARAML)&&(tmp_pos[0] != ATBM_PARAML_S)){
|
|
/*
|
|
*find the postion of cmd end,use space between tow string
|
|
*some cmd not need space ,so find enter or end of line
|
|
*/
|
|
pos = memchr(tmp_pos, ATBM_SPACE, pos_end-tmp_pos);
|
|
if(pos == NULL){
|
|
pos = memchr(tmp_pos, ATBM_ENTER, pos_end-tmp_pos);
|
|
if(pos == NULL)
|
|
pos = memchr(tmp_pos, ATBM_LINEF, pos_end-tmp_pos);
|
|
}
|
|
if(string_node->string_func){
|
|
if(pos == NULL) pos=pos_end;
|
|
if(string_node->string_func(tmp_pos,pos,string_node->priv) == false){
|
|
atbm_printk_err("%s:[%s] err tmp_pos (%p) pos (%p) %s\n",__func__,string_node->string,tmp_pos,pos,pos);
|
|
return false;
|
|
}
|
|
}
|
|
string_node->params = 1;
|
|
}else {
|
|
const char *pos_l;
|
|
const char *pos_r;
|
|
int res = 0;
|
|
|
|
pos_r = tmp_pos;
|
|
pos_l = tmp_pos;
|
|
while(pos_r<pos_end){
|
|
|
|
res = atbm_cmd_string_split(pos_l,pos_end-pos_l,&pos_l,&pos_r);
|
|
|
|
if(res<=0){
|
|
atbm_printk_err("%s not find l and r %s\n",__func__,pos);
|
|
return false;
|
|
}
|
|
if((pos_r-pos_l) == 1){
|
|
atbm_printk_err("%s param is null %s\n",__func__,pos);
|
|
return false;
|
|
}
|
|
string_node->params++;
|
|
if(string_node->string_func){
|
|
if(string_node->string_func(pos_l+1,pos_r,string_node->priv) == false){
|
|
atbm_printk_err("%s:[%s] err pos_l (%p) pos_r (%p) %s\n",__func__,string_node->string,pos_l+1,pos_r,pos_l+1);
|
|
return false;
|
|
}
|
|
}
|
|
pos_r++;
|
|
pos_l = pos_r;
|
|
|
|
if((pos_l[0]!=ATBM_PARAML)&&(pos_l[0]!=ATBM_PARAML_S)){
|
|
if(atbm_string_invalid(pos_l[0])){
|
|
atbm_printk_err("%s param format err %s\n",__func__,pos);
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
pos = pos_r;
|
|
}
|
|
|
|
|
|
if(pos == NULL)
|
|
pos = pos_end;
|
|
else
|
|
string_node->len = pos-tmp_pos;
|
|
atbm_printk_debug("[%s]:len %d,pos %s\n",string_node->string,string_node->len,string_node->string_pos);
|
|
goto next_str;
|
|
}
|
|
}
|
|
|
|
atbm_printk_always("%s:string is err %s\n",__func__,pos);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
static void *atbm_store_cmd_init_cmd_private(struct atbm_store_cmd_code *cmd_store,int len,gfp_t gfp)
|
|
{
|
|
void *cmd_private;
|
|
|
|
cmd_private = rcu_dereference(cmd_store->cmd_private);
|
|
if(cmd_private){
|
|
if(cmd_store->show_cmd)
|
|
cmd_store->show_cmd(atbm_hw_priv_dereference(),cmd_store,NULL,false);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
synchronize_rcu();
|
|
|
|
atbm_kfree(cmd_private);
|
|
}
|
|
|
|
cmd_private = atbm_kzalloc(len,gfp);
|
|
|
|
return cmd_private;
|
|
}
|
|
static struct hlist_head *atbm_cmd_hash_list(const char *string,unsigned int len)
|
|
{
|
|
return atbm_hash_list(string,len,atbm_cmd_hash_head,ATBM_CMD_HASHBITS);
|
|
}
|
|
|
|
|
|
static struct atbm_store_cmd_code *atbm_store_cmd_find_cmd(const char *pos,unsigned int pos_len)
|
|
{
|
|
unsigned char string_len = 0;
|
|
struct hlist_head *hlist = NULL;
|
|
struct atbm_store_cmd_code *cmd_code;
|
|
struct hlist_node *node;
|
|
|
|
if(ATBM_CMD_MAX_STRING_LEN<pos_len){
|
|
atbm_printk_always("%s:[%s] pos_len is too long\n",__func__,pos);
|
|
return NULL;
|
|
}
|
|
|
|
string_len = atbm_hash_string_len(pos,pos_len);
|
|
|
|
if(string_len == 0){
|
|
atbm_printk_always("%s:[%s] cmd len err\n",__func__,pos);
|
|
return NULL;
|
|
}
|
|
|
|
hlist = atbm_cmd_hash_list(pos,string_len);
|
|
|
|
hlist_for_each(node,hlist){
|
|
cmd_code = hlist_entry(node,struct atbm_store_cmd_code,hnode);
|
|
if ((!strncmp(pos, cmd_code->label, string_len))&&
|
|
(string_len == strlen(cmd_code->label))){
|
|
return cmd_code;
|
|
}
|
|
}
|
|
atbm_printk_always("%s:[%s] can not fund\n",__func__,pos);
|
|
return NULL;
|
|
}
|
|
static bool atbm_store_cmd_init_show(struct atbm_module_show *show)
|
|
{
|
|
char *show_buff;
|
|
|
|
if((show_buff = rcu_dereference(show->show_buff)) == NULL){
|
|
show_buff = atbm_kzalloc(ATBM_SHOW_MSG_MAX_SIZE,GFP_KERNEL);
|
|
}
|
|
|
|
if(show_buff == NULL){
|
|
return false;
|
|
}
|
|
atbm_show_deinit(show);
|
|
atbm_show_init(show,show_buff);
|
|
|
|
return true;
|
|
}
|
|
|
|
static void atbm_store_cmd_deinit_show(struct atbm_module_show *show)
|
|
{
|
|
char *show_buff = rcu_dereference(show->show_buff);
|
|
|
|
atbm_show_deinit(show);
|
|
if(show_buff){
|
|
synchronize_rcu();
|
|
atbm_kfree(show_buff);
|
|
atbm_printk_debug("%s:free(%p)\n",__func__,show_buff);
|
|
}
|
|
}
|
|
static ssize_t atbm_module_attr_default_show(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_code,char *buf,bool show)
|
|
{
|
|
struct atbm_module_show echo_show;
|
|
atbm_show_init(&echo_show,buf);
|
|
if(show == true)
|
|
atbm_module_show_put(&echo_show,cmd_code->echo.show_buff);
|
|
return echo_show.show_count;
|
|
}
|
|
static bool atbm_module_attr_example(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len)
|
|
{
|
|
u8 index = 0;
|
|
atbm_module_show_put(&cmd_store->echo,"atbm module cmd example\n");
|
|
for (index = 0;index<64;index++){
|
|
atbm_module_show_put(&cmd_store->echo,"trace[%d]=[%d]\n",index,hw_priv->multrx_trace[index]);
|
|
}
|
|
atbm_module_show_put(&cmd_store->echo,"\n");
|
|
atbm_printk_always( "%s\n",__func__);
|
|
return true;
|
|
}
|
|
static bool atbm_module_attr_help(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len)
|
|
{
|
|
unsigned int index = 0;
|
|
struct atbm_module_show *show = &cmd_store->echo;
|
|
|
|
atbm_module_show_put(show,LIGHT"Atbm Cmd Help-->:"NORMAL ENTER);
|
|
for(index = 0;index<ARRAY_SIZE(cmd_code_buff);index++){
|
|
atbm_module_show_put(show,LIGHT"[%s]"NORMAL":%s\n",cmd_code_buff[index].label,cmd_code_buff[index].cmd_info);
|
|
}
|
|
atbm_printk_always( "%s\n",__func__);
|
|
return true;
|
|
}
|
|
|
|
|
|
static struct ieee80211_sub_if_data * atbm_module_get_sdata_by_name(const char *name)
|
|
{
|
|
struct net_device *net_dev = NULL;
|
|
struct ieee80211_sub_if_data *sdata;
|
|
|
|
ASSERT_RTNL();
|
|
net_dev = __dev_get_by_name(&init_net,name);
|
|
|
|
if((net_dev == NULL)||
|
|
(net_dev->ieee80211_ptr == NULL) ||
|
|
(net_dev->ieee80211_ptr->wiphy == NULL)){
|
|
return NULL;
|
|
}
|
|
|
|
if (net_dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
|
|
return NULL;
|
|
|
|
sdata = IEEE80211_DEV_TO_SUB_IF(net_dev);
|
|
|
|
if (!strncmp(sdata->name, name, IFNAMSIZ))
|
|
return sdata;
|
|
|
|
atbm_printk_err("%s: can not get(%s) dev\n",__func__,name);
|
|
return NULL;
|
|
}
|
|
static bool atbm_module_config_ifname(const char *posl,const char *posr,void *priv)
|
|
{
|
|
struct atbm_conf_ifname *conf_ifname = (struct atbm_conf_ifname *)priv;
|
|
u8 len = posr - posl;
|
|
|
|
atbm_printk_debug("%s:posl(%p),posr(%p) %s\n",__func__,posl,posr,posl);
|
|
|
|
if(conf_ifname == NULL){
|
|
atbm_printk_err("%s:priv NULL(%p),\n",__func__,priv);
|
|
return false;
|
|
}
|
|
|
|
if(conf_ifname->size != 0){
|
|
atbm_printk_err("%s:if name has been set\n",__func__);
|
|
return false;
|
|
}
|
|
|
|
if(len > IFNAMSIZ){
|
|
atbm_printk_err("%s:if name size too long\n",__func__);
|
|
return false;
|
|
}
|
|
|
|
memcpy(conf_ifname->if_name,posl,len);
|
|
conf_ifname->size = len;
|
|
|
|
return true;
|
|
}
|
|
static bool atbm_module_config_integers(const char *posl,const char *posr,void *priv)
|
|
{
|
|
struct atbm_conf_integer *integers = (struct atbm_conf_integer *)priv;
|
|
|
|
int *new_integers = integers->integers;
|
|
int *pos_integers = NULL;
|
|
int interge_index = 0;
|
|
|
|
if(priv == NULL){
|
|
atbm_printk_err("%s:priv NULL(%p),\n",__func__,priv);
|
|
return false;
|
|
}
|
|
|
|
if(integers->n_integers == 0xff ){
|
|
atbm_printk_err("%s:integers too mach(%d)\n",__func__,integers->n_integers);
|
|
return false;
|
|
}
|
|
|
|
if(new_integers && integers->n_integers){
|
|
new_integers = atbm_krealloc(integers->integers,(integers->n_integers+1)*sizeof(int),GFP_KERNEL);
|
|
|
|
if(new_integers == NULL){
|
|
atbm_printk_err("%s:integers alloc err(%d)\n",__func__,integers->n_integers);
|
|
return false;
|
|
}
|
|
}else {
|
|
new_integers = atbm_kzalloc(sizeof(int),GFP_KERNEL);
|
|
|
|
if(new_integers == NULL){
|
|
atbm_printk_err("%s:integers alloc err(%d)\n",__func__,integers->n_integers);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
integers->integers = new_integers;
|
|
|
|
pos_integers = integers->integers + integers->n_integers;
|
|
|
|
if(atbm_accsii_to_int(posl,posr-posl,&interge_index) == false){
|
|
atbm_printk_err("%s:interge_index (%d) err\n",__func__,interge_index);
|
|
return false;
|
|
}
|
|
|
|
integers->n_integers++;
|
|
*pos_integers = interge_index;
|
|
|
|
return true;
|
|
}
|
|
static bool atbm_module_config_channels(const char *posl,const char *posr,void *priv)
|
|
{
|
|
struct atbm_conf_channels *channels = (struct atbm_conf_channels *)priv;
|
|
|
|
u8 *new_channels = channels->channels;
|
|
u8 *pos_channel;
|
|
int channel_index = 0;
|
|
|
|
atbm_printk_debug("%s:posl(%p),posr(%p) %s\n",__func__,posl,posr,posl);
|
|
if(priv == NULL){
|
|
atbm_printk_err("%s:priv NULL(%p),\n",__func__,priv);
|
|
return false;
|
|
}
|
|
if(channels->n_channels>=ATBM_MAX_SCAN_CHANNEL){
|
|
atbm_printk_err("%s:channles too mach(%d)\n",__func__,channels->n_channels);
|
|
return false;
|
|
}
|
|
|
|
if((posr - posl <= 0) || (posr-posl>2)){
|
|
atbm_printk_err("%s:channles len err\n",__func__);
|
|
return false;
|
|
}
|
|
|
|
if(new_channels && channels->n_channels){
|
|
|
|
new_channels = atbm_krealloc(channels->channels,channels->n_channels+1,GFP_KERNEL);
|
|
if(new_channels == NULL){
|
|
atbm_printk_err("%s:channles alloc err\n",__func__);
|
|
return false;
|
|
}
|
|
|
|
}else {
|
|
new_channels = atbm_kzalloc(1,GFP_KERNEL);
|
|
|
|
if(new_channels == NULL){
|
|
atbm_printk_err("%s:channles kzalloc err\n",__func__);
|
|
return false;
|
|
}
|
|
}
|
|
channels->channels = new_channels;
|
|
pos_channel = new_channels+channels->n_channels;
|
|
|
|
if(atbm_accsii_to_int(posl,posr-posl,&channel_index) == false){
|
|
atbm_printk_err("%s:channel_index (%d) err\n",__func__,channel_index);
|
|
return false;
|
|
}
|
|
|
|
if(channel_index>50){
|
|
atbm_printk_err("%s:channel_index (%d) err\n",__func__,channel_index);
|
|
return false;
|
|
}
|
|
|
|
channels->n_channels++;
|
|
*pos_channel = (u8)channel_index;
|
|
return true;
|
|
}
|
|
static bool atbm_module_config_ssids(const char *posl,const char *posr,void *priv)
|
|
{
|
|
struct atbm_conf_ssids *ssids = (struct atbm_conf_ssids *)priv;
|
|
struct cfg80211_ssid *new_ssid = ssids->ssids;
|
|
struct cfg80211_ssid *pos_ssid = NULL;
|
|
|
|
atbm_printk_debug("%s:posl(%p),posr(%p) %s\n",__func__,posl,posr,posl);
|
|
if(priv == NULL){
|
|
atbm_printk_err("%s:priv NULL(%p),\n",__func__,priv);
|
|
return false;
|
|
}
|
|
if(ssids->n_ssids>=ATBM_MAX_SCAN_SSID){
|
|
atbm_printk_err("%s:ssid to mach(%d)\n",__func__,ssids->n_ssids);
|
|
return false;
|
|
}
|
|
if((posr - posl <= 0) || (posr-posl>IEEE80211_MAX_SSID_LEN)){
|
|
atbm_printk_err("%s:channles len err\n",__func__);
|
|
return false;
|
|
}
|
|
|
|
if(new_ssid&&ssids->n_ssids){
|
|
new_ssid = atbm_krealloc(ssids->ssids,sizeof(struct cfg80211_ssid)*(ssids->n_ssids+1),GFP_KERNEL);
|
|
if(new_ssid == NULL){
|
|
atbm_printk_err("%s:channles realloc err\n",__func__);
|
|
return false;
|
|
}
|
|
}else {
|
|
new_ssid = atbm_kzalloc(sizeof(struct cfg80211_ssid),GFP_KERNEL);
|
|
|
|
if(new_ssid == NULL){
|
|
atbm_printk_err("%s:channles kzalloc err\n",__func__);
|
|
return false;
|
|
}
|
|
}
|
|
ssids->ssids = new_ssid;
|
|
pos_ssid = new_ssid + ssids->n_ssids;
|
|
|
|
memcpy(pos_ssid->ssid,posl,posr-posl);
|
|
pos_ssid->ssid_len = posr-posl;
|
|
ssids->n_ssids++;
|
|
|
|
atbm_printk_always("%s: ssid (%s) ssid_len(%d) n_ssids(%d)\n",__func__,pos_ssid->ssid,pos_ssid->ssid_len,ssids->n_ssids);
|
|
return true;
|
|
}
|
|
|
|
static bool atbm_module_config_macs(const char *posl,const char *posr,void *priv)
|
|
{
|
|
struct atbm_conf_macs *macs = (struct atbm_conf_macs *)priv;
|
|
|
|
struct ieee80211_internal_mac *new_mac = macs->mac;
|
|
struct ieee80211_internal_mac *pos_mac = NULL;
|
|
int i;
|
|
u8 hex;
|
|
u8 mac_begin = 0;
|
|
u8 mac_len = 0;
|
|
|
|
atbm_printk_debug("%s:posl(%p),posr(%p) %s\n",__func__,posl,posr,posl);
|
|
if(priv == NULL){
|
|
atbm_printk_err("%s:priv NULL(%p),\n",__func__,priv);
|
|
return false;
|
|
}
|
|
if(posr-posl != 17){
|
|
atbm_printk_err("%s:mac len err(%zu),\n",__func__,posr-posl);
|
|
return false;
|
|
}
|
|
if(macs->n_macs>=ATBM_MAX_SCAN_MAC_FILTER){
|
|
atbm_printk_err("%s:mac to mach(%d),\n",__func__,macs->n_macs);
|
|
return false;
|
|
}
|
|
if(macs->n_macs&&new_mac){
|
|
new_mac = atbm_krealloc(macs->mac,sizeof(struct ieee80211_internal_mac)*(macs->n_macs+1),GFP_KERNEL);
|
|
|
|
if(new_mac == NULL){
|
|
atbm_printk_err("%s:mac realloc err\n",__func__);
|
|
return false;
|
|
}
|
|
}else {
|
|
new_mac = atbm_kzalloc(sizeof(struct ieee80211_internal_mac),GFP_KERNEL);
|
|
|
|
if(new_mac == NULL){
|
|
atbm_printk_err("%s:mac kzalloc err\n",__func__);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
macs->mac = new_mac;
|
|
pos_mac = macs->mac+macs->n_macs;
|
|
|
|
for(i=0;i<posr-posl;i++){
|
|
|
|
if(posl[i] == ':'){
|
|
mac_len++;
|
|
mac_begin = 0;
|
|
continue;
|
|
}
|
|
|
|
if(mac_len>=6){
|
|
atbm_printk_err("%s:mac len,%d\n",__func__,mac_len);
|
|
return false;
|
|
}
|
|
|
|
if(mac_begin>1){
|
|
atbm_printk_err("%s:mac err,mac_begin %d\n",__func__,mac_begin);
|
|
return false;
|
|
}
|
|
if (atbm_accsii_to_hex(posl[i],&hex) == false){
|
|
atbm_printk_err("%s:scan_macs %d\n",__func__,posl[i]);
|
|
return false;
|
|
}
|
|
pos_mac->mac[mac_len] *= 16;
|
|
|
|
pos_mac->mac[mac_len] += hex;
|
|
|
|
mac_begin++;
|
|
}
|
|
|
|
if(mac_len != 5){
|
|
atbm_printk_err("%s:mac len err %d\n",__func__,mac_len);
|
|
return false;
|
|
}
|
|
macs->n_macs++;
|
|
atbm_printk_always("%s:mac[%pM]\n",__func__,pos_mac->mac);
|
|
return true;
|
|
}
|
|
static bool atbm_module_config_ies(const char *posl,const char *posr,void *priv)
|
|
{
|
|
struct atbm_conf_ies *ies = (struct atbm_conf_ies *)priv;
|
|
u8 *ie_pos = NULL;
|
|
u32 atbm_oui = ATBM_PRIVATE_OUI;
|
|
atbm_printk_debug("%s:posl(%p),posr(%p) %s\n",__func__,posl,posr,posl);
|
|
|
|
if(priv == NULL){
|
|
atbm_printk_err("%s:priv NULL(%p),\n",__func__,priv);
|
|
return false;
|
|
}
|
|
if(ies->ie_len){
|
|
atbm_printk_err("%s:only surport one ien",__func__);
|
|
return false;
|
|
}
|
|
if((posr - posl <= 0) || (posr-posl>255)){
|
|
atbm_printk_err("%s:special len err\n",__func__);
|
|
return false;
|
|
}
|
|
|
|
ies->ies = atbm_kzalloc(posr-posl+(ies->atbm_ie ? 6:0),GFP_KERNEL);
|
|
|
|
if(ies->ies == NULL){
|
|
atbm_printk_err("%s:mac kzalloc err\n",__func__);
|
|
return false;
|
|
}
|
|
ie_pos = ies->ies;
|
|
if(ies->atbm_ie){
|
|
*ie_pos++ = ATBM_WLAN_EID_PRIVATE;
|
|
*ie_pos++ = posr-posl+4;
|
|
memcpy(ie_pos,&atbm_oui,4);
|
|
ie_pos+=4;
|
|
}
|
|
memcpy(ie_pos,posl,posr-posl);
|
|
ies->ie_len = posr-posl + (ies->atbm_ie ? 6:0);
|
|
|
|
return true;
|
|
}
|
|
static bool atbm_module_config_string(const char *posl,const char *posr,void *priv)
|
|
{
|
|
struct atbm_config_string_hash *string_list = (struct atbm_config_string_hash *)priv;
|
|
struct atbm_conf_string *string_node;
|
|
int len = posr-posl;
|
|
struct hlist_head *hhead;
|
|
struct hlist_node *node;
|
|
|
|
if(string_list == NULL){
|
|
atbm_printk_err("%s:string_list == NULL \n",__func__);
|
|
return false;
|
|
}
|
|
|
|
if(len <= 0){
|
|
atbm_printk_err("%s:len <= 0\n",__func__);
|
|
return false;
|
|
}
|
|
if(string_list->empty == true){
|
|
atbm_printk_err("%s:string_list is empry\n",__func__);
|
|
return false;
|
|
}
|
|
|
|
hhead = atbm_hash_list(posl,len,string_list->hlist_head,ATBM_COMMON_HASHBITS);
|
|
|
|
|
|
hlist_for_each(node,hhead){
|
|
string_node = hlist_entry(node,struct atbm_conf_string,hnode);
|
|
|
|
if ((!strncmp(posl, string_node->strings,len))&&
|
|
(strlen(string_node->strings) == len)){
|
|
|
|
if(string_node->set == true){
|
|
atbm_printk_err("%s:[%s] has been set\n",__func__,string_node->strings);
|
|
return false;
|
|
}
|
|
|
|
string_node->set = true;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
atbm_printk_err("%s:[%s] not found\n",__func__,posl);
|
|
return false;
|
|
}
|
|
static void atbm_module_config_string_hash_int(struct atbm_config_string_hash *string_list)
|
|
{
|
|
string_list->empty = true;
|
|
atbm_common_hash_list_init(string_list->hlist_head,ATBM_COMMON_HASHENTRIES);
|
|
}
|
|
|
|
static void atbm_module_config_string_hash_insert(struct atbm_config_string_hash *string_list,
|
|
struct atbm_conf_string *string_node)
|
|
{
|
|
unsigned int hash_index = atbm_hash_index(string_node->strings,strlen(string_node->strings),ATBM_COMMON_HASHBITS);
|
|
hlist_add_head(&string_node->hnode,&string_list->hlist_head[hash_index]);
|
|
string_list->empty = false;
|
|
}
|
|
|
|
static void atbm_module_config_mult_string_hash(struct atbm_config_string_hash *string_list,size_t n_string,...)
|
|
{
|
|
size_t index = 0;
|
|
va_list args;
|
|
struct atbm_conf_string *string_node;
|
|
|
|
atbm_module_config_string_hash_int(string_list);
|
|
|
|
va_start(args, n_string);
|
|
for(index = 0;index < n_string ;index ++){
|
|
string_node = va_arg(args,struct atbm_conf_string *);
|
|
atbm_module_config_string_hash_insert(string_list,string_node);
|
|
}
|
|
va_end(args);
|
|
}
|
|
static bool atbm_module_echo_enable_num_echo(const char *posl,const char *posr,void *priv)
|
|
{
|
|
struct atbm_echo_params *echo_params = (struct atbm_echo_params *)priv;
|
|
atbm_printk_debug("%s:posl(%p),posr(%p) %s\n",__func__,posl,posr,posl);
|
|
|
|
if(priv == NULL){
|
|
atbm_printk_err("%s:priv NULL(%p),\n",__func__,priv);
|
|
return false;
|
|
}
|
|
|
|
if(echo_params->num != -1){
|
|
atbm_printk_err("%s:echo_params->num err(%d),\n",__func__,echo_params->num);
|
|
return false;
|
|
}
|
|
|
|
if((posr - posl <= 0) || (posr-posl>5)){
|
|
atbm_printk_err("%s: params too long\n",__func__);
|
|
return false;
|
|
}
|
|
|
|
if(atbm_accsii_to_int(posl,posr-posl,&echo_params->num) == false){
|
|
atbm_printk_err("%s:echo_params->num (%d) err\n",__func__,echo_params->num);
|
|
echo_params->num = -1;
|
|
return false;
|
|
}
|
|
|
|
if((echo_params->num<0)&&(echo_params->num != -1)){
|
|
atbm_printk_err("%s:echo_params->num (%d) is negtive\n",__func__,echo_params->num);
|
|
echo_params->num = -1;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
static bool atbm_module_attr_echo_enable(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len)
|
|
{
|
|
bool res = true;
|
|
const char* info = buf;
|
|
void *cmd_private = NULL;
|
|
struct atbm_echo_params *echo_params;
|
|
|
|
enable_echo = true;
|
|
cmd_store->echo_enable = true;
|
|
|
|
cmd_private = atbm_store_cmd_init_cmd_private(cmd_store,sizeof(struct atbm_echo_params),GFP_KERNEL);
|
|
|
|
if(cmd_private == NULL){
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
echo_params = (struct atbm_echo_params *)cmd_private;
|
|
echo_params->num = -1;
|
|
rcu_assign_pointer(cmd_store->cmd_private,cmd_private);
|
|
|
|
|
|
info = atbm_skip_space(buf,len);
|
|
|
|
/*
|
|
*parmas start end and channels
|
|
*/
|
|
if(info){
|
|
#define NUM_ECHO "num_echo="
|
|
struct atbm_sting_s req_string[]={
|
|
ATBM_STRING_TABLE_INIT(NUM_ECHO,atbm_module_echo_enable_num_echo,cmd_store->cmd_private),
|
|
};
|
|
if(atbm_string_parase(cmd_store,req_string,ARRAY_SIZE(req_string),info,len-(info-buf))==false){
|
|
atbm_printk_always("%s:channel_select %s err\n",__func__,info);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
num_echo = echo_params->num;
|
|
res = true;
|
|
atbm_printk_err("%s:num_echo(%d)\n",__func__,num_echo);
|
|
exit:
|
|
if(cmd_private){
|
|
atbm_kfree(cmd_private);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static bool atbm_module_attr_echo_disable(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len)
|
|
{
|
|
bool res = true;
|
|
|
|
if(buf != NULL || len != 0){
|
|
atbm_printk_err("%s:len(%d)(%p) err\n",__func__,len,buf);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
enable_echo = false;
|
|
cmd_store->echo_enable = true;
|
|
exit:
|
|
return res;
|
|
}
|
|
|
|
static bool atbm_module_attr_scan_action_process(const char *posl,const char *posr,void *priv)
|
|
{
|
|
#define POS "true"
|
|
#define PAS "false"
|
|
|
|
struct atbm_scan_params *scan_params = (struct atbm_scan_params *)priv;
|
|
size_t len = posr - posl;
|
|
|
|
if(posr-posl > 5){
|
|
atbm_printk_err("%s:(%zu)\n",__func__,posr-posl);
|
|
return false;
|
|
}
|
|
|
|
if((len==strlen(POS))&&(!strncmp(posl,POS,len))){
|
|
atbm_printk_debug("%s:positive scan\n",__func__);
|
|
scan_params->positive = true;
|
|
}else if((len==strlen(PAS))&&(!strncmp(posl,PAS,len))){
|
|
atbm_printk_debug("%s:passive scan\n",__func__);
|
|
scan_params->positive = false;
|
|
}else {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
static bool atbm_module_attr_scan_paras_scan(struct atbm_store_cmd_code *cmd_store,const char *buf,int len,struct atbm_scan_params *scan_params)
|
|
{
|
|
#define SCAN_CHANNEL "channel="
|
|
#define SCAN_SSID "ssid="
|
|
#define SCAN_PRIVATE "private="
|
|
#define SCAN_MAC "mac="
|
|
#define SCAN_POS "positive="
|
|
|
|
const char* scan_info = buf;
|
|
|
|
struct atbm_sting_s scan_string[]={
|
|
ATBM_STRING_TABLE_INIT(SCAN_CHANNEL,atbm_module_config_channels,&scan_params->channels),
|
|
ATBM_STRING_TABLE_INIT(SCAN_SSID,atbm_module_config_ssids,&scan_params->ssids),
|
|
ATBM_STRING_TABLE_INIT(SCAN_PRIVATE,atbm_module_config_ies,&scan_params->ies),
|
|
ATBM_STRING_TABLE_INIT(SCAN_MAC,atbm_module_config_macs,&scan_params->macs),
|
|
ATBM_STRING_TABLE_INIT(SCAN_POS,atbm_module_attr_scan_action_process,scan_params),
|
|
};
|
|
memset(scan_params,0,sizeof(struct atbm_scan_params));
|
|
scan_info = atbm_skip_space(buf,len);
|
|
scan_params->ies.atbm_ie = 1;
|
|
if(scan_info){
|
|
atbm_printk_debug("%s:scan_info %s\n",__func__,scan_info);
|
|
if(atbm_string_parase(cmd_store,scan_string,ARRAY_SIZE(scan_string),scan_info,len-(scan_info-buf))==false){
|
|
atbm_printk_always("%s:scan_info %s err\n",__func__,scan_info);
|
|
goto err;
|
|
}
|
|
}
|
|
return true;
|
|
err:
|
|
|
|
if(scan_params->channels.channels)
|
|
atbm_kfree(scan_params->channels.channels);
|
|
if(scan_params->macs.mac)
|
|
atbm_kfree(scan_params->macs.mac);
|
|
if(scan_params->ies.ies)
|
|
atbm_kfree(scan_params->ies.ies);
|
|
if(scan_params->ssids.ssids)
|
|
atbm_kfree(scan_params->ssids.ssids);
|
|
|
|
memset(scan_params,0,sizeof(struct atbm_scan_params));
|
|
return false;
|
|
}
|
|
bool atbm_module_attr_scan_result_handle(struct ieee80211_hw *hw,struct atbm_internal_scan_results_req *req,
|
|
struct ieee80211_internal_scan_sta *sta)
|
|
{
|
|
struct atbm_store_cmd_code *cmd_store = req->priv;
|
|
|
|
atbm_module_show_put(&cmd_store->echo,"ssid=[%s]"ATBM_SPACE_STR,(char*)sta->ssid);
|
|
atbm_module_show_put(&cmd_store->echo,"bssid=["ATBM_MACSTR"]" ATBM_SPACE_STR,ATBM_MAC2STR(sta->bssid));
|
|
atbm_module_show_put(&cmd_store->echo,"signal=[%d]"ATBM_SPACE_STR,sta->signal);
|
|
atbm_module_show_put(&cmd_store->echo,"channel=[%d]"ATBM_SPACE_STR ATBM_LINEF_STR,sta->channel);
|
|
req->n_stas ++;
|
|
|
|
return true;
|
|
}
|
|
static bool atbm_module_attr_scan(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len)
|
|
{
|
|
struct atbm_scan_params scan_params;
|
|
struct ieee80211_sub_if_data *sdata = NULL;
|
|
struct ieee80211_sub_if_data *sdata_tmp = NULL;
|
|
struct ieee80211_local *local = hw_to_local(hw_priv->hw);
|
|
struct ieee80211_internal_scan_request internal_scan;
|
|
struct atbm_internal_scan_results_req results_req;
|
|
int i = 0;
|
|
bool res = true;
|
|
|
|
atbm_printk_debug("%s:%d:%s\n",__func__,len,buf);
|
|
|
|
memset(&scan_params,0,sizeof(struct atbm_scan_params));
|
|
scan_params.ies.atbm_ie = 1;
|
|
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
if(atbm_module_attr_scan_paras_scan(cmd_store,buf,len,&scan_params) == false){
|
|
atbm_printk_always("%s scan params err\n",__func__);
|
|
res = false;
|
|
goto err_params;
|
|
}
|
|
|
|
rtnl_lock();
|
|
|
|
list_for_each_entry(sdata_tmp, &local->interfaces, list){
|
|
if (sdata_tmp->vif.type != NL80211_IFTYPE_STATION){
|
|
continue;
|
|
}
|
|
|
|
if(!ieee80211_sdata_running(sdata_tmp)){
|
|
continue;
|
|
}
|
|
|
|
sdata = sdata_tmp;
|
|
break;
|
|
}
|
|
if(sdata == NULL){
|
|
atbm_printk_err("%s:no staion running\n",__func__);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
atbm_printk_always("triger [%s] to scan\n",sdata->name);
|
|
memset(&internal_scan,0,sizeof(struct ieee80211_internal_scan_request));
|
|
|
|
if(scan_params.ssids.n_ssids){
|
|
for(i = 0;i<scan_params.ssids.n_ssids;i++){
|
|
atbm_printk_debug("%s: ssid[%s][%d]\n",__func__,scan_params.ssids.ssids[i].ssid,scan_params.ssids.ssids[i].ssid_len);
|
|
}
|
|
}
|
|
if(scan_params.macs.n_macs){
|
|
for(i = 0;i<scan_params.macs.n_macs;i++){
|
|
atbm_printk_debug("%s: mac[%pM]\n",__func__,scan_params.macs.mac[i].mac);
|
|
}
|
|
}
|
|
if(scan_params.channels.n_channels){
|
|
for(i = 0;i<scan_params.channels.n_channels;i++){
|
|
atbm_printk_debug("%s: channel[%d]\n",__func__,scan_params.channels.channels[i]);
|
|
}
|
|
}
|
|
internal_scan.macs = scan_params.macs.mac;
|
|
internal_scan.n_macs = scan_params.macs.n_macs;
|
|
internal_scan.channels = scan_params.channels.channels;
|
|
internal_scan.n_channels = scan_params.channels.n_channels;
|
|
internal_scan.ssids = scan_params.ssids.ssids;
|
|
internal_scan.n_ssids = scan_params.ssids.n_ssids;
|
|
internal_scan.ies = scan_params.ies.ies;
|
|
internal_scan.ie_len = scan_params.ies.ie_len;
|
|
internal_scan.no_cck = true;
|
|
|
|
rcu_assign_pointer(internal_scan.result_handle,NULL);
|
|
rcu_assign_pointer(internal_scan.priv,NULL);
|
|
if(atbm_internal_cmd_scan_triger(sdata, &internal_scan) == false){
|
|
res = false;
|
|
goto err;
|
|
}
|
|
atbm_printk_always( "%s\n",__func__);
|
|
atbm_printk_always("%s:channel(%p)\n",__func__,scan_params.channels.channels);
|
|
memset(&results_req,0,sizeof(struct atbm_internal_scan_results_req));
|
|
|
|
results_req.flush = true;
|
|
results_req.priv = cmd_store;
|
|
results_req.result_handle = atbm_module_attr_scan_result_handle;
|
|
|
|
if(ieee80211_scan_internal_req_results(sdata->local,&results_req) == false){
|
|
atbm_printk_err("%s:scan results err\n",__func__);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
res = true;
|
|
err:
|
|
rtnl_unlock();
|
|
err_params:
|
|
if(scan_params.channels.channels)
|
|
atbm_kfree(scan_params.channels.channels);
|
|
if(scan_params.ies.ies)
|
|
atbm_kfree(scan_params.ies.ies);
|
|
if(scan_params.macs.mac)
|
|
atbm_kfree(scan_params.macs.mac);
|
|
if(scan_params.ssids.ssids)
|
|
atbm_kfree(scan_params.ssids.ssids);
|
|
return res;
|
|
}
|
|
|
|
static bool atbm_module_attr_start_monitor(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,const char *buf,int len)
|
|
{
|
|
#define MONITOR_CHANNEL "channel="
|
|
#define MONITOR_CHTYPE "channeltype="
|
|
struct ieee80211_sub_if_data *sdata = NULL;
|
|
struct ieee80211_sub_if_data *sdata_tmp = NULL;
|
|
struct ieee80211_local *local = hw_to_local(hw_priv->hw);
|
|
struct atbm_start_monitor_params monitor_params;
|
|
const char* monitor_info = buf;
|
|
struct ieee80211_internal_monitor_req req;
|
|
bool res = true;
|
|
|
|
memset(&monitor_params,0,sizeof(struct atbm_start_monitor_params));
|
|
memset(&req,0,sizeof(struct ieee80211_internal_monitor_req));
|
|
|
|
monitor_info = atbm_skip_space(buf,len);
|
|
|
|
if(monitor_info){
|
|
struct atbm_conf_string ht20 = {.strings = "HT20",.set = false};
|
|
struct atbm_conf_string ht40 = {.strings = "HT40",.set = false};
|
|
struct atbm_config_string_hash string_hash;
|
|
struct atbm_sting_s monitor_string[]={
|
|
ATBM_STRING_TABLE_INIT(MONITOR_CHANNEL,atbm_module_config_channels,&monitor_params.channel),
|
|
ATBM_STRING_TABLE_INIT(MONITOR_CHTYPE,atbm_module_config_string,&string_hash),
|
|
};
|
|
|
|
atbm_module_config_string_hash_int(&string_hash);
|
|
atbm_module_config_string_hash_insert(&string_hash,&ht20);
|
|
atbm_module_config_string_hash_insert(&string_hash,&ht40);
|
|
|
|
atbm_printk_debug("%s:scan_info %s\n",__func__,monitor_info);
|
|
if(atbm_string_parase(cmd_store,monitor_string,ARRAY_SIZE(monitor_string),monitor_info,len-(monitor_info-buf))==false){
|
|
atbm_printk_err("%s:monitor %s err\n",__func__,monitor_info);
|
|
res = false;
|
|
goto exit_nolock;
|
|
}
|
|
|
|
if(monitor_params.channel.n_channels != 1){
|
|
atbm_printk_err("%s:channel %d ++++err\n",__func__,monitor_params.channel.n_channels);
|
|
res = false;
|
|
goto exit_nolock;
|
|
}
|
|
|
|
req.ch = monitor_params.channel.channels[0];
|
|
req.chtype = 0;
|
|
}else {
|
|
atbm_printk_err("%s:monitor need channel\n",__func__);
|
|
goto exit_nolock;
|
|
}
|
|
|
|
if(req.ch == 0){
|
|
goto exit_nolock;
|
|
}
|
|
rtnl_lock();
|
|
|
|
list_for_each_entry(sdata_tmp, &local->interfaces, list){
|
|
|
|
if (sdata_tmp->vif.type == NL80211_IFTYPE_MONITOR){
|
|
atbm_printk_err("%s:monitor already exit\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if(!ieee80211_sdata_running(sdata_tmp)){
|
|
continue;
|
|
}
|
|
|
|
sdata = sdata_tmp;
|
|
break;
|
|
}
|
|
|
|
if(sdata == NULL){
|
|
atbm_printk_err("%s:no staion running\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
res = atbm_internal_cmd_monitor_req(sdata,&req);
|
|
|
|
atbm_printk_debug("triger [%s] to monitor (%d)\n",sdata->name,res);
|
|
exit:
|
|
rtnl_unlock();
|
|
exit_nolock:
|
|
if(monitor_params.channel.channels)
|
|
atbm_kfree(monitor_params.channel.channels);
|
|
|
|
return res;
|
|
}
|
|
static bool atbm_module_attr_stop_monitor(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
struct ieee80211_sub_if_data *sdata = NULL;
|
|
struct ieee80211_sub_if_data *sdata_tmp = NULL;
|
|
struct ieee80211_local *local = hw_to_local(hw_priv->hw);
|
|
bool res = true;
|
|
const char* monitor_info = buf;
|
|
|
|
monitor_info = atbm_skip_space(buf,len);
|
|
|
|
if(monitor_info){
|
|
atbm_printk_debug("%s:scan_info %s\n",__func__,monitor_info);
|
|
if(atbm_string_parase(cmd_store,NULL,0,monitor_info,len-(monitor_info-buf))==false){
|
|
atbm_printk_always("%s:stop monitor %s err\n",__func__,monitor_info);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
rtnl_lock();
|
|
|
|
list_for_each_entry(sdata_tmp, &local->interfaces, list){
|
|
|
|
if (sdata_tmp->vif.type != NL80211_IFTYPE_MONITOR){
|
|
atbm_printk_err("%s:monitor already exit\n",__func__);
|
|
continue;
|
|
}
|
|
|
|
if(!ieee80211_sdata_running(sdata_tmp)){
|
|
continue;
|
|
}
|
|
|
|
sdata = sdata_tmp;
|
|
break;
|
|
}
|
|
|
|
if(sdata == NULL){
|
|
rtnl_unlock();
|
|
atbm_printk_err("%s:no staion running\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
res = atbm_internal_cmd_stop_monitor(sdata);
|
|
|
|
atbm_printk_debug("triger [%s] to monitor (%d)\n",sdata->name,res);
|
|
|
|
rtnl_unlock();
|
|
exit:
|
|
return res;
|
|
}
|
|
static ssize_t atbm_module_attr_stop_monitor_show(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,char *buf,bool show)
|
|
{
|
|
return atbm_module_attr_default_show(hw_priv,cmd_store,buf,show);
|
|
}
|
|
|
|
static ssize_t atbm_module_attr_start_monitor_show(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,char *buf,bool show)
|
|
{
|
|
return atbm_module_attr_default_show(hw_priv,cmd_store,buf,show);
|
|
}
|
|
|
|
static bool atbm_module_sta_info_insert(struct atbm_store_cmd_code *cmd_store,struct ieee80211_internal_sta_info *stainfo)
|
|
{
|
|
|
|
atbm_module_show_put(&cmd_store->echo,"ifname[%s]"ATBM_SPACE_STR,stainfo->sdata->name);
|
|
atbm_module_show_put(&cmd_store->echo,"mac[%pM]"ATBM_SPACE_STR,stainfo->mac);
|
|
if(IEEE80211_INTERNAL_STA_FLAGS_SSID&stainfo->filled){
|
|
atbm_module_show_put(&cmd_store->echo,"ssid[%s]"ATBM_SPACE_STR,stainfo->ssid);
|
|
atbm_module_show_put(&cmd_store->echo,"ssid_len[%d]"ATBM_SPACE_STR,stainfo->ssid_len);
|
|
}
|
|
if(IEEE80211_INTERNAL_STA_FLAGS_CHANNEL&stainfo->filled){
|
|
atbm_module_show_put(&cmd_store->echo,"channel[%d]"ATBM_SPACE_STR,stainfo->channel);
|
|
atbm_module_show_put(&cmd_store->echo,"channel_type[%d]"ATBM_SPACE_STR,stainfo->channel_type);
|
|
}
|
|
if(IEEE80211_INTERNAL_STA_FLAGS_SIGNAL&stainfo->filled){
|
|
atbm_module_show_put(&cmd_store->echo,"signal[%d]"ATBM_SPACE_STR,stainfo->signal);
|
|
atbm_module_show_put(&cmd_store->echo,"avg_signal[%d]"ATBM_SPACE_STR,stainfo->avg_signal);
|
|
}
|
|
if(IEEE80211_INTERNAL_STA_FLAGS_TXRXBYTE&stainfo->filled){
|
|
atbm_module_show_put(&cmd_store->echo,"rxbytes[%ld]"ATBM_SPACE_STR,stainfo->rx_bytes);
|
|
atbm_module_show_put(&cmd_store->echo,"txbytes[%ld]"ATBM_SPACE_STR,stainfo->tx_bytes);
|
|
}
|
|
if(IEEE80211_INTERNAL_STA_FLAGS_TOPRATE&stainfo->filled){
|
|
atbm_module_show_put(&cmd_store->echo,"toprate[%d]"ATBM_SPACE_STR,stainfo->top_rate);
|
|
}
|
|
|
|
atbm_module_show_put(&cmd_store->echo,ATBM_LINEF_STR);
|
|
return true;
|
|
}
|
|
static bool atbm_module_ap_info_handle(struct ieee80211_internal_sta_info *stainfo,void *priv)
|
|
{
|
|
struct atbm_store_cmd_code *cmd_store = (struct atbm_store_cmd_code *)priv;
|
|
|
|
if(cmd_store == NULL){
|
|
return false;
|
|
}
|
|
|
|
if(stainfo->sdata->vif.type != NL80211_IFTYPE_STATION){
|
|
return false;
|
|
}
|
|
atbm_module_sta_info_insert(cmd_store,stainfo);
|
|
return true;
|
|
}
|
|
static bool atbm_module_sta_info_req_spilt(struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
#define REQ_MAC "mac="
|
|
#define REQ_INFO "req="
|
|
|
|
struct atbm_stainfo_req_params *req = cmd_store->cmd_private;
|
|
struct atbm_conf_string rssi = {.strings = "rssi",.set = false};
|
|
struct atbm_conf_string toprate = {.strings = "toprate",.set = false};
|
|
struct atbm_conf_string channel = {.strings = "channel",.set = false};
|
|
struct atbm_conf_string txrxbytes = {.strings = "txrxbytes",.set = false};
|
|
struct atbm_conf_string ssid = {.strings = "ssid",.set = false};
|
|
struct atbm_config_string_hash string_hash;
|
|
|
|
struct atbm_sting_s req_string[]={
|
|
ATBM_STRING_TABLE_INIT(REQ_MAC,atbm_module_config_macs,&req->req_mac),
|
|
ATBM_STRING_TABLE_INIT(REQ_INFO,atbm_module_config_string,&string_hash),
|
|
};
|
|
|
|
atbm_module_config_string_hash_int(&string_hash);
|
|
atbm_module_config_string_hash_insert(&string_hash,&rssi);
|
|
atbm_module_config_string_hash_insert(&string_hash,&toprate);
|
|
atbm_module_config_string_hash_insert(&string_hash,&channel);
|
|
atbm_module_config_string_hash_insert(&string_hash,&txrxbytes);
|
|
atbm_module_config_string_hash_insert(&string_hash,&ssid);
|
|
|
|
if(atbm_string_parase(cmd_store,req_string,ARRAY_SIZE(req_string),buf,len) == false){
|
|
goto err;
|
|
}
|
|
|
|
if(rssi.set)
|
|
req->req_rssi = 1;
|
|
if(toprate.set)
|
|
req->req_rate = 1;
|
|
if(channel.set)
|
|
req->req_channel = 1;
|
|
if(txrxbytes.set)
|
|
req->req_txrxbytes = 1;
|
|
if(ssid.set)
|
|
req->req_ssid = 1;
|
|
|
|
return true;
|
|
err:
|
|
if(req){
|
|
if(req->req_mac.mac){
|
|
atbm_kfree(req->req_mac.mac);
|
|
}
|
|
req->req_mac.mac = NULL;
|
|
req->req_mac.n_macs = 0;
|
|
}
|
|
return false;
|
|
}
|
|
static bool atbm_module_attr_ap_info(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
struct ieee80211_internal_sta_req req;
|
|
bool res = true;
|
|
const char* ap_info = buf;
|
|
void *cmd_private = NULL;
|
|
struct atbm_stainfo_req_params *req_params = NULL;
|
|
|
|
cmd_private = atbm_store_cmd_init_cmd_private(cmd_store,sizeof(struct atbm_stainfo_req_params),GFP_KERNEL);
|
|
|
|
if(cmd_private == NULL){
|
|
goto err;
|
|
}
|
|
|
|
rcu_assign_pointer(cmd_store->cmd_private,cmd_private);
|
|
ap_info = atbm_skip_space(buf,len);
|
|
|
|
req_params = cmd_private;
|
|
req_params->req_channel = false;
|
|
req_params->req_rate = false;
|
|
req_params->req_rssi = false;
|
|
req_params->req_txrxbytes = false;
|
|
req_params->type = NL80211_IFTYPE_STATION;
|
|
|
|
if(ap_info){
|
|
atbm_printk_debug("%s:ap_info %s\n",__func__,ap_info);
|
|
if(atbm_module_sta_info_req_spilt(cmd_store,ap_info,len-(ap_info-buf))==false){
|
|
atbm_printk_always("%s:ap_info %s err\n",__func__,ap_info);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
}
|
|
memset(&req,0,sizeof(struct ieee80211_internal_sta_req));
|
|
|
|
req.sta_handle = atbm_module_ap_info_handle;
|
|
req.priv = cmd_store;
|
|
|
|
if(req_params->req_channel)
|
|
req.req_flag |=IEEE80211_INTERNAL_STA_FLAGS_CHANNEL;
|
|
if(req_params->req_rssi)
|
|
req.req_flag |=IEEE80211_INTERNAL_STA_FLAGS_SIGNAL;
|
|
if(req_params->req_txrxbytes)
|
|
req.req_flag |=IEEE80211_INTERNAL_STA_FLAGS_TXRXBYTE;
|
|
if(req_params->req_rate)
|
|
req.req_flag |=IEEE80211_INTERNAL_STA_FLAGS_TOPRATE;
|
|
if(req_params->req_ssid)
|
|
req.req_flag |=IEEE80211_INTERNAL_STA_FLAGS_SSID;
|
|
if(req.req_flag == 0)
|
|
req.req_flag = (u32)-1;
|
|
|
|
req.n_macs = req_params->req_mac.n_macs;
|
|
req.macs = req_params->req_mac.mac;
|
|
req.type = NL80211_IFTYPE_STATION;
|
|
res = atbm_internal_cmd_stainfo(hw_to_local(hw_priv->hw),&req);
|
|
err:
|
|
if(req_params){
|
|
if(req_params->req_mac.mac)
|
|
atbm_kfree(req_params->req_mac.mac);
|
|
atbm_kfree(req_params);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
}
|
|
return res;
|
|
}
|
|
static bool atbm_module_sta_info_handle(struct ieee80211_internal_sta_info *stainfo,void *priv)
|
|
{
|
|
struct atbm_store_cmd_code *cmd_store = (struct atbm_store_cmd_code *)priv;
|
|
|
|
if(cmd_store == NULL){
|
|
return false;
|
|
}
|
|
|
|
if(stainfo->sdata->vif.type!= NL80211_IFTYPE_AP){
|
|
return false;
|
|
}
|
|
|
|
atbm_module_sta_info_insert(cmd_store,stainfo);
|
|
return false;
|
|
}
|
|
|
|
static bool atbm_module_attr_sta_info(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
struct ieee80211_internal_sta_req req;
|
|
bool res = true;
|
|
const char* sta_info = buf;
|
|
void *cmd_private = NULL;
|
|
struct atbm_stainfo_req_params *req_params = NULL;
|
|
|
|
cmd_private = atbm_store_cmd_init_cmd_private(cmd_store,sizeof(struct atbm_stainfo_req_params),GFP_KERNEL);
|
|
|
|
if(cmd_private == NULL){
|
|
goto err;
|
|
}
|
|
|
|
rcu_assign_pointer(cmd_store->cmd_private,cmd_private);
|
|
req_params = cmd_private;
|
|
req_params->type = NL80211_IFTYPE_AP;
|
|
req_params->req_channel = false;
|
|
req_params->req_rate = false;
|
|
req_params->req_rssi = false;
|
|
req_params->req_txrxbytes = false;
|
|
sta_info = atbm_skip_space(buf,len);
|
|
|
|
if(sta_info){
|
|
atbm_printk_debug("%s:scan_info %s\n",__func__,sta_info);
|
|
if(atbm_module_sta_info_req_spilt(cmd_store,sta_info,len-(sta_info-buf))==false){
|
|
atbm_printk_always("%s:scan_info %s err\n",__func__,sta_info);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
}
|
|
memset(&req,0,sizeof(struct ieee80211_internal_sta_req));
|
|
|
|
req.sta_handle = atbm_module_sta_info_handle;
|
|
req.priv = cmd_store;
|
|
|
|
if(req_params->req_channel)
|
|
req.req_flag |=IEEE80211_INTERNAL_STA_FLAGS_CHANNEL;
|
|
if(req_params->req_rssi)
|
|
req.req_flag |=IEEE80211_INTERNAL_STA_FLAGS_SIGNAL;
|
|
if(req_params->req_txrxbytes)
|
|
req.req_flag |=IEEE80211_INTERNAL_STA_FLAGS_TXRXBYTE;
|
|
if(req_params->req_rate)
|
|
req.req_flag |=IEEE80211_INTERNAL_STA_FLAGS_TOPRATE;
|
|
if(req_params->req_ssid)
|
|
req.req_flag |=IEEE80211_INTERNAL_STA_FLAGS_SSID;
|
|
if(req.req_flag == 0)
|
|
req.req_flag = (u32)-1;
|
|
|
|
req.type = NL80211_IFTYPE_AP;
|
|
req.n_macs = req_params->req_mac.n_macs;
|
|
req.macs = req_params->req_mac.mac;
|
|
res = atbm_internal_cmd_stainfo(hw_to_local(hw_priv->hw),&req);
|
|
err:
|
|
if(req_params){
|
|
if(req_params->req_mac.mac)
|
|
atbm_kfree(req_params->req_mac.mac);
|
|
atbm_kfree(req_params);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
}
|
|
return res;
|
|
}
|
|
static bool atbm_module_wsm_adaptive_process(const char *posl,const char *posr,void *priv)
|
|
{
|
|
#define ADAPTIVE_ON "on"
|
|
#define ADAPTIVE_OFF "off"
|
|
struct atbm_wsm_req_parmas *wsm_req = (struct atbm_wsm_req_parmas *)priv;
|
|
u8 len = posr - posl;
|
|
|
|
atbm_printk_debug("%s:posl(%p),posr(%p) %s\n",__func__,posl,posr,posl);
|
|
|
|
if(posl>=posr){
|
|
atbm_printk_err("%s:posr(%p),posl(%p)\n",__func__,posr,posl);
|
|
return false;
|
|
}
|
|
|
|
if(wsm_req->req_adaptive != 0){
|
|
atbm_printk_err("%s:double req return err\n",__func__);
|
|
return false;
|
|
}
|
|
|
|
wsm_req->req_adaptive |= PARAMAS_SET;
|
|
|
|
if((strlen(ADAPTIVE_ON) == len)&&(memcmp(ADAPTIVE_ON,posl,len) == 0)){
|
|
wsm_req->req_adaptive |= PARAMAS_ON;
|
|
atbm_printk_debug("adaptive on\n");
|
|
}else if((strlen(ADAPTIVE_OFF) == len)&&(memcmp(ADAPTIVE_OFF,posl,len) == 0)){
|
|
wsm_req->req_adaptive &= ~PARAMAS_ON;
|
|
atbm_printk_debug("adaptive off\n");
|
|
}else {
|
|
atbm_printk_err("%s:err %s\n",__func__,posl);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool atbm_module_wsm_txpwr_dcxo_process(const char *posl,const char *posr,void *priv)
|
|
{
|
|
struct atbm_wsm_req_parmas *wsm_req = (struct atbm_wsm_req_parmas *)priv;
|
|
u8 len = posr - posl;
|
|
|
|
atbm_printk_debug("%s:posl(%p),posr(%p) %s\n",__func__,posl,posr,posl);
|
|
|
|
if(posl>=posr){
|
|
atbm_printk_err("%s:posr(%p),posl(%p)\n",__func__,posr,posl);
|
|
return false;
|
|
}
|
|
|
|
if(wsm_req->dcxo_index >= 4){
|
|
atbm_printk_err("%s:wsm_req->dcxo_index err (%d)\n",__func__,wsm_req->dcxo_index);
|
|
return false;
|
|
}
|
|
|
|
wsm_req->req_pwrdcxo |= PARAMAS_SET;
|
|
|
|
if(atbm_accsii_to_int(posl,len,&wsm_req->txpwr_dcxo[wsm_req->dcxo_index]) == false){
|
|
atbm_printk_err("%s:dcxo vall err %s\n",__func__,posl);
|
|
return false;
|
|
}
|
|
|
|
wsm_req->dcxo_index ++ ;
|
|
return true;
|
|
}
|
|
|
|
static bool atbm_module_wsm_txpwr_process(const char *posl,const char *posr,void *priv)
|
|
{
|
|
struct atbm_wsm_req_parmas *wsm_req = (struct atbm_wsm_req_parmas *)priv;
|
|
u8 len = posr - posl;
|
|
|
|
atbm_printk_debug("%s:posl(%p),posr(%p) %s\n",__func__,posl,posr,posl);
|
|
|
|
if(posl>=posr){
|
|
atbm_printk_err("%s:posr(%p),posl(%p)\n",__func__,posr,posl);
|
|
return false;
|
|
}
|
|
|
|
if(wsm_req->req_pwr != 0){
|
|
atbm_printk_err("%s:double req return err\n",__func__);
|
|
return false;
|
|
}
|
|
|
|
wsm_req->req_pwr |= PARAMAS_SET;
|
|
|
|
if(atbm_accsii_to_int(posl,len,&wsm_req->txpwr) == false){
|
|
atbm_printk_err("%s:txpwr vall err %s\n",__func__,posl);
|
|
return false;
|
|
}
|
|
atbm_printk_debug("%s:txpwr(%d)\n",__func__,wsm_req->txpwr);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
*wsm cmd:wsm_cmd adaptive=[on or off] txpwr_dcxo=[M][H][L][dcxo] txpwr=[power]
|
|
*/
|
|
static bool atbm_module_wsm_cmd_info_spilt(struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
#define REQ_ADAPTIVE "adaptive="
|
|
#define REQ_TXPWR_DCXO "txpwr_dcxo="
|
|
#define REQ_TXPWR "txpwr="
|
|
bool res = true;
|
|
|
|
struct atbm_sting_s req_string[]={
|
|
ATBM_STRING_TABLE_INIT(REQ_ADAPTIVE,atbm_module_wsm_adaptive_process,cmd_store->cmd_private),
|
|
ATBM_STRING_TABLE_INIT(REQ_TXPWR_DCXO,atbm_module_wsm_txpwr_dcxo_process,cmd_store->cmd_private),
|
|
ATBM_STRING_TABLE_INIT(REQ_TXPWR,atbm_module_wsm_txpwr_process,cmd_store->cmd_private),
|
|
};
|
|
|
|
if(atbm_string_parase(cmd_store,req_string,ARRAY_SIZE(req_string),buf,len) == false){
|
|
res = false;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
static bool atbm_module_attr_wsm_cmd(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
const char* wsm_info = NULL;
|
|
struct atbm_wsm_req_parmas *wsm_req;
|
|
void *cmd_private = NULL;
|
|
bool res=true;
|
|
|
|
|
|
cmd_private = atbm_store_cmd_init_cmd_private(cmd_store,sizeof(struct atbm_wsm_req_parmas),GFP_KERNEL);
|
|
|
|
if(cmd_private == NULL){
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
wsm_req = (struct atbm_wsm_req_parmas *)cmd_private;
|
|
rcu_assign_pointer(cmd_store->cmd_private,cmd_private);
|
|
wsm_req->req_adaptive = 0;
|
|
wsm_req->req_pwr = 0;
|
|
wsm_req->req_pwrdcxo = 0;
|
|
|
|
wsm_info = atbm_skip_space(buf,len);
|
|
|
|
if(wsm_info == NULL){
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
res = atbm_module_wsm_cmd_info_spilt(cmd_store,buf,len);
|
|
|
|
if(res == false){
|
|
goto err;
|
|
}
|
|
|
|
if(wsm_req->req_adaptive){
|
|
struct ieee80211_internal_wsm_adaptive adaptive;
|
|
|
|
adaptive.enable = !!(wsm_req->req_adaptive&PARAMAS_ON);
|
|
|
|
res = atbm_internal_wsm_adaptive(hw_priv,&adaptive);
|
|
|
|
if(res == false){
|
|
atbm_printk_err("%s:set adaptive err\n",__func__);
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
if(wsm_req->req_pwrdcxo){
|
|
struct ieee80211_internal_wsm_txpwr_dcxo txpwr_dcxo;
|
|
|
|
if(wsm_req->dcxo_index != 4){
|
|
atbm_printk_err("%s:set req_pwrdcxo too short\n",__func__);
|
|
goto err;
|
|
}
|
|
txpwr_dcxo.txpwr_L = wsm_req->txpwr_dcxo[0];
|
|
txpwr_dcxo.txpwr_M = wsm_req->txpwr_dcxo[1];
|
|
txpwr_dcxo.txpwr_H = wsm_req->txpwr_dcxo[2];
|
|
txpwr_dcxo.dcxo = wsm_req->txpwr_dcxo[3];
|
|
|
|
res = atbm_internal_wsm_txpwr_dcxo(hw_priv,&txpwr_dcxo);
|
|
|
|
if(res == false){
|
|
atbm_printk_err("%s:set txpwr_dcxo err\n",__func__);
|
|
goto err;
|
|
}
|
|
}
|
|
if(wsm_req->req_pwr){
|
|
struct ieee80211_internal_wsm_txpwr txpwr;
|
|
|
|
txpwr.txpwr_indx = wsm_req->txpwr;
|
|
|
|
res = atbm_internal_wsm_txpwr(hw_priv,&txpwr);
|
|
|
|
if(res == false){
|
|
atbm_printk_err("%s:set txpwr err\n",__func__);
|
|
goto err;
|
|
}
|
|
}
|
|
err:
|
|
if(cmd_private){
|
|
atbm_kfree(cmd_private);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
static bool atbm_module_send_probe_request_spilt(struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
#define REQ_NUM "num="
|
|
#define REQ_IE "private="
|
|
bool res = true;
|
|
struct atbm_probe_request *request = (struct atbm_probe_request *)cmd_store->cmd_private;
|
|
|
|
struct atbm_sting_s req_string[]={
|
|
ATBM_STRING_TABLE_INIT(REQ_NUM,atbm_module_config_integers,&request->n_request),
|
|
ATBM_STRING_TABLE_INIT(REQ_IE,atbm_module_config_ies,&request->ies),
|
|
};
|
|
|
|
if(atbm_string_parase(cmd_store,req_string,ARRAY_SIZE(req_string),buf,len) == false){
|
|
res = false;
|
|
}
|
|
|
|
if(request->n_request.n_integers == 0){
|
|
request->n_request.integers = atbm_kzalloc(sizeof(int),GFP_KERNEL);
|
|
if(request->n_request.integers != NULL){
|
|
request->n_request.integers[0] = 1;
|
|
request->n_request.n_integers = 1;
|
|
}else {
|
|
res = false;
|
|
}
|
|
}else if(request->n_request.n_integers > 1){
|
|
res = false;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static bool atbm_module_attr_send_probe_request(struct atbm_common *hw_priv,
|
|
struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
void *cmd_private = NULL;
|
|
struct atbm_probe_request *request = NULL;
|
|
bool res = true;
|
|
const char* request_info = NULL;
|
|
struct ieee80211_sub_if_data *sdata = NULL;
|
|
struct ieee80211_sub_if_data *sdata_tmp = NULL;
|
|
struct ieee80211_local *local = hw_to_local(hw_priv->hw);
|
|
int i = 0;
|
|
|
|
|
|
cmd_private = atbm_store_cmd_init_cmd_private(cmd_store,sizeof(struct atbm_probe_request),GFP_KERNEL);
|
|
|
|
if(cmd_private == NULL){
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
request = (struct atbm_probe_request *)cmd_private;
|
|
rcu_assign_pointer(cmd_store->cmd_private,cmd_private);
|
|
|
|
request_info = atbm_skip_space(buf,len);
|
|
|
|
if(request_info == NULL){
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
res = atbm_module_send_probe_request_spilt(cmd_store,buf,len);
|
|
|
|
if(res == false){
|
|
goto err;
|
|
}
|
|
|
|
rtnl_lock();
|
|
|
|
list_for_each_entry(sdata_tmp, &local->interfaces, list){
|
|
#ifndef AP_MODE_SEND_PROBE_REQ
|
|
if ((sdata_tmp->vif.type != NL80211_IFTYPE_MONITOR)&&(sdata_tmp->vif.type != NL80211_IFTYPE_STATION)){
|
|
atbm_printk_err("%s:monitor already exit\n",__func__);
|
|
continue;
|
|
}
|
|
#endif
|
|
if(!ieee80211_sdata_running(sdata_tmp)){
|
|
continue;
|
|
}
|
|
#ifdef AP_MODE_SEND_PROBE_REQ
|
|
if(sdata_tmp->vif.type == NL80211_IFTYPE_AP){
|
|
goto ap_mode;
|
|
}
|
|
#endif
|
|
if(sdata_tmp->vif.type == NL80211_IFTYPE_STATION){
|
|
struct atbm_vif *priv = (struct atbm_vif *)sdata_tmp->vif.drv_priv;
|
|
|
|
if(atomic_read(&priv->enabled) == 0)
|
|
continue;
|
|
if(priv->join_status != ATBM_APOLLO_JOIN_STATUS_STA_LISTEN)
|
|
continue;
|
|
}
|
|
#ifdef AP_MODE_SEND_PROBE_REQ
|
|
ap_mode:
|
|
#endif
|
|
sdata = sdata_tmp;
|
|
break;
|
|
}
|
|
|
|
if(sdata == NULL){
|
|
rtnl_unlock();
|
|
atbm_printk_err("%s:no staion running\n",__func__);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
atbm_printk_err("triger [%s] to monitor/sta to send probe(%d),ie_len(%d)\n",sdata->name,request->n_request.integers[0],request->ies.ie_len);
|
|
for(i = 0;i<request->n_request.integers[0];i++){
|
|
ieee80211_send_special_probe_req(sdata, NULL, NULL,
|
|
0, request->ies.ies, request->ies.ie_len);
|
|
}
|
|
|
|
rtnl_unlock();
|
|
err:
|
|
if(cmd_private){
|
|
request = cmd_private;
|
|
if(request->ies.ies)
|
|
atbm_kfree(request->ies.ies);
|
|
if(request->n_request.integers)
|
|
atbm_kfree(request->n_request.integers);
|
|
atbm_kfree(cmd_private);
|
|
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
}
|
|
return res;
|
|
}
|
|
#ifdef CONFIG_ATBM_STA_LISTEN
|
|
static bool atbm_module_sta_listen_spilt(struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
#define LISTEN_IFNAME "ifname="
|
|
#define LISTEN_CHANNEL "channel="
|
|
bool res = true;
|
|
struct atbm_sta_listen *sta_listen = (struct atbm_sta_listen *)cmd_store->cmd_private;
|
|
struct atbm_sting_s req_string[]={
|
|
ATBM_STRING_TABLE_INIT(LISTEN_IFNAME,atbm_module_config_ifname,&sta_listen->ifname),
|
|
ATBM_STRING_TABLE_INIT(LISTEN_CHANNEL,atbm_module_config_channels,&sta_listen->channel),
|
|
};
|
|
|
|
if(atbm_string_parase(cmd_store,req_string,ARRAY_SIZE(req_string),buf,len) == false){
|
|
res = false;
|
|
}
|
|
|
|
if(sta_listen->ifname.size == 0)
|
|
res = false;
|
|
if(sta_listen->channel.n_channels != 1)
|
|
res = false;
|
|
return res;
|
|
}
|
|
|
|
static bool atbm_module_attr_sta_listen(struct atbm_common *hw_priv,
|
|
struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
struct atbm_sta_listen *sta_listen;
|
|
void *cmd_private = NULL;
|
|
bool res = true;
|
|
const char* request_info = NULL;
|
|
|
|
struct ieee80211_sub_if_data *sdata = NULL;
|
|
struct ieee80211_sub_if_data *sdata_tmp = NULL;
|
|
struct ieee80211_local *local = hw_to_local(hw_priv->hw);
|
|
|
|
cmd_private = atbm_store_cmd_init_cmd_private(cmd_store,sizeof(struct atbm_sta_listen),GFP_KERNEL);
|
|
|
|
if(cmd_private == NULL){
|
|
goto err;
|
|
}
|
|
|
|
sta_listen = (struct atbm_sta_listen *)cmd_private;
|
|
|
|
rcu_assign_pointer(cmd_store->cmd_private,cmd_private);
|
|
|
|
request_info = atbm_skip_space(buf,len);
|
|
if(request_info == NULL){
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
res = atbm_module_sta_listen_spilt(cmd_store,buf,len);
|
|
|
|
if(res == false){
|
|
goto err;
|
|
}
|
|
rtnl_lock();
|
|
|
|
list_for_each_entry(sdata_tmp, &local->interfaces, list){
|
|
|
|
if (sdata_tmp->vif.type != NL80211_IFTYPE_STATION){
|
|
atbm_printk_err("%s:not sta\n",__func__);
|
|
continue;
|
|
}
|
|
|
|
if(!ieee80211_sdata_running(sdata_tmp)){
|
|
continue;
|
|
}
|
|
|
|
if(memcmp(sdata_tmp->name,sta_listen->ifname.if_name,IFNAMSIZ)){
|
|
continue;
|
|
}
|
|
sdata = sdata_tmp;
|
|
break;
|
|
}
|
|
|
|
if(sdata == NULL){
|
|
rtnl_unlock();
|
|
atbm_printk_err("%s:no staion running\n",__func__);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
atbm_printk_err("%s:[%s] enter sta listen mode\n",__func__,sdata->name);
|
|
if(ieee80211_set_sta_channel(sdata,sta_listen->channel.channels[0]) != 0)
|
|
res = false;
|
|
rtnl_unlock();
|
|
err:
|
|
if(cmd_private){
|
|
if(sta_listen->channel.channels)
|
|
atbm_kfree(sta_listen->channel.channels);
|
|
atbm_kfree(cmd_private);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
#endif
|
|
|
|
static bool atbm_module_ap_set_beacon_spilt(struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
#define AP_IFNAME "ifname="
|
|
#define AP_SPECIAL "special="
|
|
bool res = true;
|
|
struct atbm_ap_set_beacon *ap_beacon = (struct atbm_ap_set_beacon *)cmd_store->cmd_private;
|
|
struct atbm_sting_s req_string[]={
|
|
ATBM_STRING_TABLE_INIT(AP_IFNAME,atbm_module_config_ifname,&ap_beacon->ifname),
|
|
ATBM_STRING_TABLE_INIT(AP_SPECIAL,atbm_module_config_ies,&ap_beacon->ies),
|
|
};
|
|
|
|
if(atbm_string_parase(cmd_store,req_string,ARRAY_SIZE(req_string),buf,len) == false){
|
|
res = false;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static bool atbm_module_attr_ap_set_beacon(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
struct atbm_ap_set_beacon *ap_beacon = NULL;
|
|
void *cmd_private = NULL;
|
|
bool res = true;
|
|
const char* request_info = NULL;
|
|
|
|
struct ieee80211_sub_if_data *sdata = NULL;
|
|
struct ieee80211_sub_if_data *sdata_tmp = NULL;
|
|
struct ieee80211_local *local = hw_to_local(hw_priv->hw);
|
|
|
|
cmd_private = atbm_store_cmd_init_cmd_private(cmd_store,sizeof(struct atbm_ap_set_beacon),GFP_KERNEL);
|
|
|
|
if(cmd_private == NULL){
|
|
goto err;
|
|
}
|
|
|
|
ap_beacon = (struct atbm_ap_set_beacon *)cmd_private;
|
|
rcu_assign_pointer(cmd_store->cmd_private,cmd_private);
|
|
|
|
request_info = atbm_skip_space(buf,len);
|
|
if(request_info == NULL){
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
res = atbm_module_ap_set_beacon_spilt(cmd_store,buf,len);
|
|
|
|
if(res == false){
|
|
goto err;
|
|
}
|
|
|
|
if(ap_beacon->ifname.size == 0){
|
|
atbm_printk_err("%s: ifname not set\n",__func__);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
if(ap_beacon->ies.ie_len == 0){
|
|
atbm_printk_err("%s: special ie not set\n",__func__);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
rtnl_lock();
|
|
list_for_each_entry(sdata_tmp, &local->interfaces, list){
|
|
|
|
if (sdata_tmp->vif.type != NL80211_IFTYPE_AP){
|
|
continue;
|
|
}
|
|
|
|
if(!ieee80211_sdata_running(sdata_tmp)){
|
|
continue;
|
|
}
|
|
|
|
if(memcmp(sdata_tmp->name,ap_beacon->ifname.if_name,IFNAMSIZ)){
|
|
continue;
|
|
}
|
|
sdata = sdata_tmp;
|
|
break;
|
|
}
|
|
|
|
if(sdata == NULL){
|
|
rtnl_unlock();
|
|
atbm_printk_err("%s:[%s] is not running\n",__func__,ap_beacon->ifname.if_name);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
rtnl_unlock();
|
|
atbm_printk_debug("%s:[%s],len[%zu] to beacon\n",__func__,ap_beacon->ifname.if_name,(size_t)ap_beacon->ies.ie_len);
|
|
res = ieee80211_ap_update_special_beacon(sdata,ap_beacon->ies.ies,ap_beacon->ies.ie_len);
|
|
err:
|
|
if(ap_beacon){
|
|
if(ap_beacon->ies.ies)
|
|
atbm_kfree(ap_beacon->ies.ies);
|
|
ap_beacon->ies.ies = NULL;
|
|
atbm_kfree(ap_beacon);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
static bool atbm_module_attr_sta_special_scan(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
bool res = true;
|
|
struct atbm_scan_params scan_params;
|
|
struct ieee80211_sub_if_data *sdata = NULL;
|
|
struct ieee80211_sub_if_data *sdata_tmp = NULL;
|
|
struct ieee80211_local *local = hw_to_local(hw_priv->hw);
|
|
int i = 0;
|
|
|
|
atbm_printk_debug("%s:%d:%s\n",__func__,len,buf);
|
|
rtnl_lock();
|
|
|
|
memset(&scan_params,0,sizeof(struct atbm_scan_params));
|
|
|
|
scan_params.ies.atbm_ie = 1;
|
|
if(atbm_module_attr_scan_paras_scan(cmd_store,buf,len,&scan_params) == false){
|
|
atbm_printk_always("%s scan params err\n",__func__);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
list_for_each_entry(sdata_tmp, &local->interfaces, list){
|
|
if (sdata_tmp->vif.type != NL80211_IFTYPE_STATION){
|
|
continue;
|
|
}
|
|
|
|
if(!ieee80211_sdata_running(sdata_tmp)){
|
|
continue;
|
|
}
|
|
|
|
sdata = sdata_tmp;
|
|
break;
|
|
}
|
|
if(sdata == NULL){
|
|
res = false;
|
|
atbm_printk_err("%s:no staion running\n",__func__);
|
|
goto err;
|
|
}
|
|
atbm_printk_always("triger [%s] to scan\n",sdata->name);
|
|
|
|
if(scan_params.ssids.n_ssids){
|
|
for(i = 0;i<scan_params.ssids.n_ssids;i++){
|
|
atbm_printk_debug("%s: ssid[%s][%d]\n",__func__,scan_params.ssids.ssids[i].ssid,scan_params.ssids.ssids[i].ssid_len);
|
|
}
|
|
}
|
|
if(scan_params.macs.n_macs){
|
|
for(i = 0;i<scan_params.macs.n_macs;i++){
|
|
atbm_printk_debug("%s: mac[%pM]\n",__func__,scan_params.macs.mac[i].mac);
|
|
}
|
|
}
|
|
if(scan_params.channels.n_channels){
|
|
for(i = 0;i<scan_params.channels.n_channels;i++){
|
|
atbm_printk_debug("%s: channel[%d]\n",__func__,scan_params.channels.channels[i]);
|
|
}
|
|
}
|
|
|
|
atbm_printk_always( "%s\n",__func__);
|
|
atbm_printk_always("%s:channel(%p)\n",__func__,scan_params.channels.channels);
|
|
|
|
if(scan_params.positive == true){
|
|
u8 *scan_ssid = NULL;
|
|
size_t scan_ssid_len = 0;
|
|
|
|
if(scan_params.ssids.n_ssids){
|
|
scan_ssid = scan_params.ssids.ssids[0].ssid;
|
|
scan_ssid_len = scan_params.ssids.ssids[0].ssid_len;
|
|
}
|
|
res = ieee80211_sta_triger_positive_scan(sdata,scan_params.channels.channels,scan_params.channels.n_channels,
|
|
scan_ssid,scan_ssid_len,scan_params.ies.ies,scan_params.ies.ie_len,NULL);
|
|
}else {
|
|
res = ieee80211_sta_triger_passive_scan(sdata,scan_params.channels.channels,scan_params.channels.n_channels);
|
|
}
|
|
err:
|
|
rtnl_unlock();
|
|
if(scan_params.channels.channels)
|
|
atbm_kfree(scan_params.channels.channels);
|
|
if(scan_params.ies.ies)
|
|
atbm_kfree(scan_params.ies.ies);
|
|
if(scan_params.macs.mac)
|
|
atbm_kfree(scan_params.macs.mac);
|
|
if(scan_params.ssids.ssids)
|
|
atbm_kfree(scan_params.ssids.ssids);
|
|
return res;
|
|
}
|
|
static bool atbm_module_attr_set_freq(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
#define FREQ_CHANNEL "channel="
|
|
#define FREQ_FREQ "freq="
|
|
struct atbm_special_freq *set_freq;
|
|
void *cmd_private = NULL;
|
|
bool res = true;
|
|
const char* request_info = NULL;
|
|
struct ieee80211_internal_set_freq_req req;
|
|
|
|
cmd_private = atbm_store_cmd_init_cmd_private(cmd_store,sizeof(struct atbm_special_freq),GFP_KERNEL);
|
|
|
|
if(cmd_private == NULL){
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
set_freq = (struct atbm_special_freq *)cmd_private;
|
|
|
|
rcu_assign_pointer(cmd_store->cmd_private,cmd_private);
|
|
|
|
request_info = atbm_skip_space(buf,len);
|
|
if(request_info == NULL){
|
|
res = false;
|
|
goto err;
|
|
}
|
|
/*
|
|
*parase channel and freq
|
|
*/
|
|
if(1){
|
|
struct atbm_sting_s req_string[]={
|
|
ATBM_STRING_TABLE_INIT(FREQ_CHANNEL,atbm_module_config_integers,&set_freq->channel),
|
|
ATBM_STRING_TABLE_INIT(FREQ_FREQ,atbm_module_config_integers,&set_freq->freq),
|
|
};
|
|
res = atbm_string_parase(cmd_store,req_string,ARRAY_SIZE(req_string),buf,len);
|
|
if(res == false){
|
|
atbm_printk_err("%s:atbm_string_parase err\n",__func__);
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
if(set_freq->channel.n_integers != 1){
|
|
atbm_printk_err("%s: channel not set\n",__func__);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
if(set_freq->freq.n_integers != 1){
|
|
atbm_printk_err("%s: freq not set\n",__func__);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
req.channel_num = set_freq->channel.integers[0];
|
|
req.freq = set_freq->freq.integers[0];
|
|
req.set = true;
|
|
rtnl_lock();
|
|
res = atbm_internal_freq_set(hw_priv->hw,&req);
|
|
rtnl_unlock();
|
|
err:
|
|
if(cmd_private){
|
|
if(set_freq->channel.integers)
|
|
atbm_kfree(set_freq->channel.integers);
|
|
if(set_freq->freq.integers)
|
|
atbm_kfree(set_freq->freq.integers);
|
|
atbm_kfree(cmd_private);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
}
|
|
#undef FREQ_CHANNEL
|
|
#undef FREQ_FREQ
|
|
return res;
|
|
}
|
|
static bool atbm_module_attr_clear_freq(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
#define FREQ_CHANNEL "channel="
|
|
struct atbm_special_freq *set_freq;
|
|
void *cmd_private = NULL;
|
|
bool res = true;
|
|
const char* request_info = NULL;
|
|
struct ieee80211_internal_set_freq_req req;
|
|
|
|
cmd_private = atbm_store_cmd_init_cmd_private(cmd_store,sizeof(struct atbm_special_freq),GFP_KERNEL);
|
|
|
|
if(cmd_private == NULL){
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
set_freq = (struct atbm_special_freq *)cmd_private;
|
|
|
|
rcu_assign_pointer(cmd_store->cmd_private,cmd_private);
|
|
|
|
request_info = atbm_skip_space(buf,len);
|
|
if(request_info == NULL){
|
|
res = false;
|
|
goto err;
|
|
}
|
|
/*
|
|
*parase channel
|
|
*/
|
|
if(1){
|
|
struct atbm_sting_s req_string[]={
|
|
ATBM_STRING_TABLE_INIT(FREQ_CHANNEL,atbm_module_config_integers,&set_freq->channel),
|
|
};
|
|
res = atbm_string_parase(cmd_store,req_string,ARRAY_SIZE(req_string),buf,len);
|
|
if(res == false){
|
|
atbm_printk_err("%s:atbm_string_parase err\n",__func__);
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
|
|
if(set_freq->channel.n_integers != 1){
|
|
atbm_printk_err("%s: channel not set\n",__func__);
|
|
res = false;
|
|
goto err;
|
|
}
|
|
|
|
req.channel_num = set_freq->channel.integers[0];
|
|
req.set = false;
|
|
|
|
rtnl_lock();
|
|
res = atbm_internal_freq_set(hw_priv->hw,&req);
|
|
rtnl_unlock();
|
|
err:
|
|
if(cmd_private){
|
|
if(set_freq->channel.integers)
|
|
atbm_kfree(set_freq->channel.integers);
|
|
atbm_kfree(cmd_private);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
}
|
|
#undef FREQ_CHANNEL
|
|
#undef FREQ_FREQ
|
|
return res;
|
|
}
|
|
static ssize_t atbm_module_attr_channel_select_show(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,char *buf,bool show)
|
|
{
|
|
return atbm_module_attr_default_show(hw_priv,cmd_store,buf,show);
|
|
}
|
|
static bool atbm_module_attr_channel_select(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
#define CH_START "start="
|
|
#define CH_END "end="
|
|
#define CH_LIST "channels="
|
|
#define CH_VER "version="
|
|
struct atbm_channel_auto_select *select=NULL;
|
|
struct ieee80211_sub_if_data *sdata = NULL;
|
|
struct ieee80211_sub_if_data *sdata_tmp = NULL;
|
|
struct ieee80211_local *local = hw_to_local(hw_priv->hw);
|
|
struct ieee80211_internal_channel_auto_select_req req;
|
|
struct ieee80211_internal_channel_auto_select_results results;
|
|
// u8 ignor_channels[2]; // = {13,14};
|
|
bool res = true;
|
|
const char* select_info = buf;
|
|
void *cmd_private = NULL;
|
|
int i;
|
|
|
|
rtnl_lock();
|
|
cmd_private = atbm_store_cmd_init_cmd_private(cmd_store,sizeof(struct atbm_channel_auto_select),GFP_KERNEL);
|
|
|
|
if(cmd_private == NULL){
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
select = (struct atbm_channel_auto_select *)cmd_private;
|
|
|
|
rcu_assign_pointer(cmd_store->cmd_private,cmd_private);
|
|
|
|
|
|
select_info = atbm_skip_space(buf,len);
|
|
|
|
/*
|
|
*parmas start end and channels
|
|
*/
|
|
if(select_info){
|
|
struct atbm_sting_s req_string[]={
|
|
ATBM_STRING_TABLE_INIT(CH_START,atbm_module_config_integers,&select->start_channel),
|
|
ATBM_STRING_TABLE_INIT(CH_END,atbm_module_config_integers,&select->end_channel),
|
|
ATBM_STRING_TABLE_INIT(CH_LIST,atbm_module_config_channels,&select->channels),
|
|
ATBM_STRING_TABLE_INIT(CH_VER,atbm_module_config_integers,&select->version),
|
|
};
|
|
if(atbm_string_parase(cmd_store,req_string,ARRAY_SIZE(req_string),select_info,len-(select_info-buf))==false){
|
|
atbm_printk_always("%s:channel_select %s err\n",__func__,select_info);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
}
|
|
/*
|
|
*get channel list
|
|
*if set channel list , using the channel setting
|
|
*if set channel start and end , using the channel between start and end
|
|
*if not set channel ,using all surported channel
|
|
*/
|
|
if(select->end_channel.n_integers ^ select->start_channel.n_integers){
|
|
atbm_printk_err("%s: start or end err\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if(select->channels.n_channels){
|
|
if(select->end_channel.n_integers){
|
|
atbm_printk_err("%s: channel list and start_end both set\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
}
|
|
if(select->channels.n_channels){
|
|
for(i = 0;i<select->channels.n_channels;i++){
|
|
if(ieee8011_channel_valid(hw_priv->hw,select->channels.channels[i]) == false){
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
}
|
|
}else if(select->end_channel.n_integers){
|
|
|
|
if(select->end_channel.n_integers != 1){
|
|
atbm_printk_err("%s:end err\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if(select->start_channel.n_integers != 1){
|
|
atbm_printk_err("%s:end err\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if(select->end_channel.integers[0] <= select->start_channel.integers[0]){
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if(select->end_channel.integers[0] - select->start_channel.integers[0] >= IEEE80211_ATBM_MAX_SCAN_CHANNEL_INDEX){
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
select->channels.channels = atbm_kmalloc(select->end_channel.integers[0] - select->start_channel.integers[0]+1,GFP_KERNEL);
|
|
|
|
if(select->channels.channels == NULL){
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
select->channels.n_channels = select->end_channel.integers[0] - select->start_channel.integers[0] +1;
|
|
for(i = 0; i< select->channels.n_channels;i++){
|
|
if(ieee8011_channel_valid(hw_priv->hw,select->start_channel.integers[0]+i) == false){
|
|
atbm_printk_err("%s:select->start_channel errL\n",__func__);
|
|
goto exit;
|
|
}
|
|
select->channels.channels[i] = select->start_channel.integers[0]+i;
|
|
}
|
|
}else{
|
|
select->channels.channels = ieee8011_get_channel_list(hw_priv->hw,(size_t*)&select->channels.n_channels);
|
|
|
|
if(select->channels.channels == NULL){
|
|
atbm_printk_err("%s: select->channels == NULL\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
list_for_each_entry(sdata_tmp, &local->interfaces, list){
|
|
|
|
if (sdata_tmp->vif.type != NL80211_IFTYPE_STATION){
|
|
continue;
|
|
}
|
|
|
|
if(!ieee80211_sdata_running(sdata_tmp)){
|
|
continue;
|
|
}
|
|
|
|
sdata = sdata_tmp;
|
|
break;
|
|
}
|
|
|
|
if(sdata == NULL){
|
|
atbm_printk_err("%s:no staion running\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
memset(&req,0,sizeof(struct ieee80211_internal_channel_auto_select_req));
|
|
memset(&results,0,sizeof(struct ieee80211_internal_channel_auto_select_results));
|
|
|
|
results.ignore_channels = NULL;//ignor_channels;
|
|
results.ignore_n_channels = 0;//ARRAY_SIZE(ignor_channels);
|
|
results.channels = select->channels.channels;
|
|
results.n_channels = select->channels.n_channels;
|
|
if(select->version.n_integers == 0)
|
|
results.version = 1;
|
|
else if(select->version.n_integers == 1)
|
|
results.version = select->version.integers[0];
|
|
else {
|
|
atbm_printk_err("%s:version err\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
/*
|
|
*triger channel scan
|
|
*/
|
|
if(atbm_internal_channel_auto_select(sdata,&req) == false){
|
|
atbm_printk_err("%s:channel auto select err\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
/*
|
|
*get results
|
|
*/
|
|
if(atbm_internal_channel_auto_select_results(sdata,&results) == false){
|
|
atbm_printk_err("%s:channel results err\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
atbm_module_show_put(&cmd_store->echo,"suggest_channel=[%d]"ATBM_LINEF_STR,results.susgest_channel);
|
|
for(i = 0;i<select->channels.n_channels;i++){
|
|
struct ieee80211_channel *ch = ieee8011_chnum_to_channel(hw_priv->hw,select->channels.channels[i]);
|
|
atbm_module_show_put(&cmd_store->echo,"channel[%d] ap_count[%d] ratio[%d] weight[%d] special_freq[%s]"ATBM_LINEF_STR,select->channels.channels[i],
|
|
results.n_aps[select->channels.channels[i]-1],results.busy_ratio[select->channels.channels[i]-1],
|
|
results.weight[select->channels.channels[i]-1],channel_in_special(ch) == true?"true":"false");
|
|
}
|
|
atbm_printk_debug("triger [%s] auto channel select (%d)\n",sdata->name,res);
|
|
exit:
|
|
#undef CH_START
|
|
#undef CH_END
|
|
#undef CH_LIST
|
|
#undef CH_VER
|
|
rtnl_unlock();
|
|
if(cmd_private){
|
|
|
|
if(select->channels.channels)
|
|
atbm_kfree(select->channels.channels);
|
|
if(select->start_channel.integers)
|
|
atbm_kfree(select->start_channel.integers);
|
|
if(select->end_channel.integers)
|
|
atbm_kfree(select->end_channel.integers);
|
|
if(select->version.integers)
|
|
atbm_kfree(select->version.integers);
|
|
atbm_kfree(cmd_private);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
}
|
|
return res;
|
|
}
|
|
static bool atbm_module_attr_chip_version(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
const char* select_info = buf;
|
|
bool res = true;
|
|
struct ieee80211_internal_req_chip chip_info;
|
|
select_info = atbm_skip_space(buf,len);
|
|
|
|
memset(&chip_info,0,sizeof(struct ieee80211_internal_req_chip));
|
|
|
|
if(select_info){
|
|
if(atbm_string_parase(cmd_store,NULL,0,select_info,len-(select_info-buf))==false){
|
|
atbm_printk_always("%s:chip_version %s err\n",__func__,select_info);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
chip_info.flags |= IEEE80211_INTERNAL_REQ_CHIP_FLAGS__CHIP_VER;
|
|
|
|
if(atbm_internal_request_chip_cap(hw_priv->hw,&chip_info) == false){
|
|
atbm_printk_always("%s: get chip_version\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if(chip_info.chip_version == NULL)
|
|
chip_info.chip_version = "unkown";
|
|
|
|
atbm_module_show_put(&cmd_store->echo,"chip_version[%s]\n",chip_info.chip_version);
|
|
exit:
|
|
|
|
return res;
|
|
}
|
|
#ifdef CONFIG_ATBM_SUPPORT_AP_CONFIG
|
|
/*
|
|
*set ap configs:ap_config ifname=[xxx] channel=[x] ssid=[ap] bssid=[xx:xx:xx:xx:xx:xx]
|
|
*/
|
|
static bool atbm_module_attr_set_ap_config(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
bool res = true;
|
|
struct atbm_module_ap_conf ap_config;
|
|
const char* select_info = buf;
|
|
struct ieee80211_sub_if_data *sdata = NULL;
|
|
struct ieee80211_internal_ap_conf conf_req;
|
|
|
|
rtnl_lock();
|
|
|
|
select_info = atbm_skip_space(buf,len);
|
|
memset(&ap_config,0,sizeof(struct atbm_module_ap_conf));
|
|
memset(&conf_req,0,sizeof(struct ieee80211_internal_ap_conf));
|
|
|
|
if(select_info){
|
|
#define CONF_IFNAME "ifname="
|
|
#define CONF_CHANNEL "channel="
|
|
#define CONF_SSID "ssid="
|
|
#define CONF_BSSID "bssid="
|
|
#define CONF_IES "ies="
|
|
|
|
struct atbm_sting_s req_string[]={
|
|
ATBM_STRING_TABLE_INIT(CONF_IFNAME,atbm_module_config_ifname,&ap_config.ifname),
|
|
ATBM_STRING_TABLE_INIT(CONF_CHANNEL,atbm_module_config_channels,&ap_config.channel),
|
|
ATBM_STRING_TABLE_INIT(CONF_SSID,atbm_module_config_ssids,&ap_config.ssid),
|
|
ATBM_STRING_TABLE_INIT(CONF_BSSID,atbm_module_config_macs,&ap_config.bssid),
|
|
ATBM_STRING_TABLE_INIT(CONF_IES,atbm_module_config_ies,NULL),
|
|
};
|
|
|
|
if(atbm_string_parase(cmd_store,req_string,ARRAY_SIZE(req_string),select_info,len-(select_info-buf))==false){
|
|
atbm_printk_always("%s:ap config %s err\n",__func__,select_info);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
}else {
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if(ap_config.ifname.size == 0){
|
|
atbm_printk_err("%s:ifname is null\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
sdata = atbm_module_get_sdata_by_name(ap_config.ifname.if_name);
|
|
|
|
if(sdata == NULL){
|
|
atbm_printk_err("%s:[%s] not found\n",__func__,ap_config.ifname.if_name);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if((ap_config.channel.n_channels >1) ||
|
|
(ap_config.ssid.n_ssids >1) ||
|
|
(ap_config.bssid.n_macs >1)){
|
|
atbm_printk_err("%s:config err\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if((ap_config.channel.n_channels == 0)&&
|
|
(ap_config.ssid.n_ssids == 0) &&
|
|
(ap_config.bssid.n_macs == 0)){
|
|
atbm_printk_err("%s:config clear\n",__func__);
|
|
res = atbm_internal_update_ap_conf(sdata,NULL,true);
|
|
goto exit;
|
|
}
|
|
|
|
atbm_printk_debug("n_channels(%d),n_macs(%d),n_ssids(%d)\n",ap_config.channel.n_channels,
|
|
ap_config.bssid.n_macs,ap_config.ssid.n_ssids);
|
|
if(ap_config.channel.n_channels)
|
|
conf_req.channel = ap_config.channel.channels[0];
|
|
if(ap_config.bssid.n_macs)
|
|
memcpy(conf_req.bssid,ap_config.bssid.mac[0].mac,6);
|
|
if(ap_config.ssid.n_ssids){
|
|
memcpy(conf_req.ssid,ap_config.ssid.ssids[0].ssid,ap_config.ssid.ssids[0].ssid_len);
|
|
conf_req.ssid_len = ap_config.ssid.ssids[0].ssid_len;
|
|
}
|
|
res = atbm_internal_update_ap_conf(sdata,&conf_req,false);
|
|
exit:
|
|
rtnl_unlock();
|
|
#undef CONF_IFNAME
|
|
#undef CONF_CHANNEL
|
|
#undef CONF_SSID
|
|
#undef CONF_BSSID
|
|
if(ap_config.bssid.mac)
|
|
atbm_kfree(ap_config.bssid.mac);
|
|
if(ap_config.channel.channels)
|
|
atbm_kfree(ap_config.channel.channels);
|
|
if(ap_config.ssid.ssids)
|
|
atbm_kfree(ap_config.ssid.ssids);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
return res;
|
|
}
|
|
#endif
|
|
/*
|
|
*set_mode:ap_config ifname=[xxx] mode=[managed/monior] channel=[x]
|
|
*/
|
|
|
|
static bool atbm_module_attr_set_mode(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
#define MODE_IFNAME "ifname="
|
|
#define MODE_CHANNEL "channel="
|
|
#define MODE_TYPE "mode="
|
|
struct atbm_module_set_mode_conf conf_mode;
|
|
const char* select_info = buf;
|
|
struct ieee80211_sub_if_data *sdata = NULL;
|
|
struct ieee80211_internal_iftype_req req;
|
|
struct atbm_config_string_hash string_hash;
|
|
struct atbm_conf_string managed = {.strings = "managed",.set = false};
|
|
struct atbm_conf_string monitor = {.strings = "monitor",.set = false};
|
|
struct atbm_sting_s monitor_string[]={
|
|
ATBM_STRING_TABLE_INIT(MODE_IFNAME,atbm_module_config_ifname,&conf_mode.ifname),
|
|
ATBM_STRING_TABLE_INIT(MODE_CHANNEL,atbm_module_config_channels,&conf_mode.channel),
|
|
ATBM_STRING_TABLE_INIT(MODE_TYPE,atbm_module_config_string,&string_hash),
|
|
};
|
|
bool res = true;
|
|
|
|
rtnl_lock();
|
|
|
|
select_info = atbm_skip_space(buf,len);
|
|
|
|
if(select_info == NULL){
|
|
atbm_printk_err("%s:need params\n",__func__);
|
|
res = false;
|
|
|
|
goto exit;
|
|
}
|
|
memset(&req,0,sizeof(struct ieee80211_internal_iftype_req));
|
|
memset(&conf_mode,0,sizeof(struct atbm_module_set_mode_conf));
|
|
atbm_module_config_mult_string_hash(&string_hash,2,&managed,&monitor);
|
|
|
|
if(atbm_string_parase(cmd_store,monitor_string,ARRAY_SIZE(monitor_string),select_info,len-(select_info-buf))==false){
|
|
atbm_printk_always("%s:ap config %s err\n",__func__,select_info);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if(conf_mode.ifname.size == 0){
|
|
atbm_printk_err("%s:ifname is null\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if(((managed.set == true) ^ (monitor.set == true)) == 0){
|
|
atbm_printk_err("%s:mode is null\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if(conf_mode.channel.n_channels > 1){
|
|
atbm_printk_always("%s:n_channels %d err\n",__func__,conf_mode.channel.n_channels);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
sdata = atbm_module_get_sdata_by_name(conf_mode.ifname.if_name);
|
|
|
|
if(sdata == NULL){
|
|
atbm_printk_err("%s:[%s] not found\n",__func__,conf_mode.ifname.if_name);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
if(conf_mode.channel.n_channels == 1)
|
|
req.channel = conf_mode.channel.channels[0];
|
|
if(managed.set == true)
|
|
req.if_type = IEEE80211_INTERNAL_IFTYPE_REQ__MANAGED;
|
|
else if(monitor.set == true)
|
|
req.if_type = IEEE80211_INTERNAL_IFTYPE_REQ__MONITOR;
|
|
|
|
res = atbm_internal_cmd_req_iftype(sdata,&req);
|
|
exit:
|
|
if(conf_mode.channel.channels)
|
|
atbm_kfree(conf_mode.channel.channels);
|
|
rtnl_unlock();
|
|
#undef MODE_IFNAME
|
|
#undef MODE_CHANNEL
|
|
#undef MODE_TYPE
|
|
return res;
|
|
}
|
|
static bool atbm_module_attr_halt(struct atbm_common *hw_priv,struct atbm_store_cmd_code *cmd_store,
|
|
const char *buf,int len)
|
|
{
|
|
#define HALT_IFNAME "ifname="
|
|
bool res = true;
|
|
struct atbm_module_halt_conf halt_conf;
|
|
const char* select_info = buf;
|
|
struct atbm_sting_s halt_string[]={
|
|
ATBM_STRING_TABLE_INIT(HALT_IFNAME,atbm_module_config_ifname,&halt_conf.ifname),
|
|
};
|
|
struct ieee80211_sub_if_data *sdata = NULL;
|
|
|
|
rtnl_lock();
|
|
memset(&halt_conf,0,sizeof(struct atbm_module_halt_conf));
|
|
select_info = atbm_skip_space(buf,len);
|
|
if(select_info == NULL){
|
|
atbm_printk_err("%s:need params\n",__func__);
|
|
res = false;
|
|
|
|
goto exit;
|
|
}
|
|
|
|
if(atbm_string_parase(cmd_store,halt_string,ARRAY_SIZE(halt_string),select_info,len-(select_info-buf))==false){
|
|
atbm_printk_always("%s:ap config %s err\n",__func__,select_info);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
if(halt_conf.ifname.size == 0){
|
|
atbm_printk_err("%s:ifname is null\n",__func__);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
sdata = atbm_module_get_sdata_by_name(halt_conf.ifname.if_name);
|
|
|
|
if(sdata == NULL){
|
|
atbm_printk_err("%s:[%s] not found\n",__func__,halt_conf.ifname.if_name);
|
|
res = false;
|
|
goto exit;
|
|
}
|
|
|
|
atbm_bh_halt(sdata->local->hw.priv);
|
|
exit:
|
|
rtnl_unlock();
|
|
return res;
|
|
#undef HALT_IFNAME
|
|
}
|
|
static bool atbm_store_cmd_is_ready(struct atbm_store_cmd_code *cmd_store)
|
|
{
|
|
struct atbm_store_cmd_code *ready_cmd;
|
|
|
|
list_for_each_entry(ready_cmd, &atbm_cmd_echo_ready_list, lhead){
|
|
if((ready_cmd->label == cmd_store->label)&&
|
|
(ready_cmd->code_cmd == cmd_store->code_cmd))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
static void atbm_store_cmd_echo_done(struct atbm_store_cmd_code *cmd_store)
|
|
{
|
|
char *cmd_private;
|
|
if(cmd_store->echo_ready == false){
|
|
atbm_printk_always( "%s not in ready list\n",cmd_store->label);
|
|
WARN_ON(atbm_store_cmd_is_ready(cmd_store) == true);
|
|
}else {
|
|
list_del(&cmd_store->lhead);
|
|
ready_list_num--;
|
|
WARN_ON(ready_list_num<0);
|
|
}
|
|
cmd_private = rcu_dereference(cmd_store->cmd_private);
|
|
rcu_assign_pointer(cmd_store->cmd_private,NULL);
|
|
if(cmd_private){
|
|
synchronize_rcu();
|
|
atbm_kfree(cmd_private);
|
|
atbm_printk_always("%s:free cmd_private(%p)\n",__func__,cmd_private);
|
|
}
|
|
cmd_store->cmd_private = NULL;
|
|
cmd_store->echo_ready = false;
|
|
}
|
|
static void atbm_store_cmd_echo_ready(struct atbm_store_cmd_code *cmd_store)
|
|
{
|
|
if(cmd_store->echo_ready == true){
|
|
atbm_printk_always( "%s already in ready list\n",cmd_store->label);
|
|
WARN_ON(atbm_store_cmd_is_ready(cmd_store) == false);
|
|
return;
|
|
}
|
|
|
|
cmd_store->echo_ready = true;
|
|
|
|
if((num_echo == -1) || (num_echo>ready_list_num)){
|
|
|
|
}else if((!list_empty(&atbm_cmd_echo_ready_list))){
|
|
struct atbm_store_cmd_code *cmd_code =
|
|
list_first_entry(&atbm_cmd_echo_ready_list, struct atbm_store_cmd_code,
|
|
lhead);
|
|
if(cmd_code->show_cmd)
|
|
cmd_code->show_cmd(atbm_hw_priv_dereference(),cmd_code,NULL,false);
|
|
atbm_store_cmd_echo_done(cmd_code);
|
|
atbm_store_cmd_deinit_show(&cmd_code->echo);
|
|
}else if(num_echo != 0){
|
|
WARN_ON(1);
|
|
}
|
|
ready_list_num ++;
|
|
list_add_tail(&cmd_store->lhead,&atbm_cmd_echo_ready_list);
|
|
}
|
|
|
|
static ssize_t atbm_module_decode_common_store(const char *buf, size_t n)
|
|
{
|
|
const char *p;
|
|
const char *code_end = NULL;
|
|
int code_len = 0;
|
|
int left_len = 0;
|
|
size_t len = n;
|
|
struct atbm_store_cmd_code *store_code;
|
|
|
|
p = atbm_skip_space(buf,n);
|
|
|
|
if(p == NULL){
|
|
atbm_printk_always("%s:all space %s\n",__func__,buf);
|
|
return -EINVAL;
|
|
}
|
|
len -= p-buf;
|
|
/*
|
|
*find the postion of cmd end,use space between tow string
|
|
*some cmd not need space ,so find enter or end of line
|
|
*/
|
|
code_end = memchr(buf, ATBM_SPACE, len);
|
|
if(code_end == NULL){
|
|
code_end = memchr(buf, ATBM_ENTER, len);
|
|
if(code_end == NULL)
|
|
code_end = memchr(buf, ATBM_LINEF, len);
|
|
}
|
|
if(code_end == NULL){
|
|
atbm_printk_always("%s:can not fine aline\n",__func__);
|
|
}
|
|
code_len = code_end ? code_end - p : len;
|
|
if(code_len<=0){
|
|
atbm_printk_always("%s code_len err\n",__func__);
|
|
return -EINVAL;
|
|
}
|
|
left_len = len - code_len;
|
|
|
|
if(left_len<0){
|
|
atbm_printk_always("%s left_len err\n",__func__);
|
|
return -EINVAL;
|
|
}
|
|
store_code = atbm_store_cmd_find_cmd(p,code_len);
|
|
|
|
if(store_code == NULL){
|
|
atbm_printk_always("%s:can not find cmd\n",__func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if(store_code->code_cmd == NULL){
|
|
atbm_printk_err("%s %d ,ERROR !!! store_code->code_cmd is NULL\n",__func__,__LINE__);
|
|
return -EINVAL;
|
|
}
|
|
p = atbm_skip_space(code_end,left_len);
|
|
if(p == NULL){
|
|
left_len = 0;
|
|
}else {
|
|
left_len -= p-code_end;
|
|
}
|
|
if(left_len<0){
|
|
atbm_printk_always("%s left_len err,params err\n",__func__);
|
|
return -EINVAL;
|
|
}
|
|
if(atbm_store_cmd_init_show(&store_code->echo) == false){
|
|
atbm_printk_always("%s show buff init err\n",__func__);
|
|
return -EINVAL;
|
|
}
|
|
/*
|
|
*set default enable_echo
|
|
*/
|
|
store_code->echo_enable = enable_echo;
|
|
|
|
if(store_code->code_cmd(atbm_hw_priv_dereference(),store_code,p,left_len) == true){
|
|
if(store_code->echo_enable == true){
|
|
atbm_module_show_put(&store_code->echo,"%s[%s]\n",store_code->label,"OK");
|
|
atbm_store_cmd_echo_ready(store_code);
|
|
}else{
|
|
if(store_code->show_cmd)
|
|
store_code->show_cmd(atbm_hw_priv_dereference(),store_code,NULL,false);
|
|
atbm_store_cmd_echo_done(store_code);
|
|
atbm_store_cmd_deinit_show(&store_code->echo);
|
|
}
|
|
}else {
|
|
if(store_code->echo_enable == true){
|
|
atbm_module_show_put(&store_code->echo,"%s[%s]\n",store_code->label,"ERR");
|
|
}
|
|
atbm_store_cmd_echo_done(store_code);
|
|
atbm_store_cmd_deinit_show(&store_code->echo);
|
|
|
|
return -EINVAL;
|
|
}
|
|
return n;
|
|
}
|
|
static ssize_t atbm_module_cmd_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
const char *buf, size_t n)
|
|
{
|
|
ssize_t mg_size = 0;
|
|
atbm_modulefs_lock();
|
|
atbm_module_muxlock();
|
|
if(atbm_hw_priv_dereference() == NULL){
|
|
mg_size = -EINVAL;
|
|
goto exit;
|
|
}
|
|
mg_size = atbm_module_decode_common_store(buf,n);
|
|
exit:
|
|
atbm_module_muxunlock();
|
|
atbm_modulefs_unlock();
|
|
return mg_size;
|
|
}
|
|
|
|
static u8 atbm_write_backup_commond(char *show_buffer)
|
|
{
|
|
u8 i = 0;
|
|
char *ptr = NULL;
|
|
char back_command[][10]={
|
|
{"ap_info"},
|
|
{"NULL"}
|
|
};
|
|
for(i = 0 ; strncmp(back_command[i],"NULL",4) != 0 ; i++ ){
|
|
ptr = strstr(show_buffer,back_command[i]);
|
|
if(ptr)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
static ssize_t atbm_module_cmd_show(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
ssize_t len = 0;
|
|
u8* show_buff = NULL;
|
|
ssize_t show_len = 0;
|
|
atbm_modulefs_lock();
|
|
atbm_module_muxlock();
|
|
show_buff = atbm_kzalloc(ATBM_SHOW_MSG_MAX_SIZE, GFP_KERNEL);
|
|
while (!list_empty(&atbm_cmd_echo_ready_list)) {
|
|
struct atbm_store_cmd_code *cmd_code =
|
|
list_first_entry(&atbm_cmd_echo_ready_list, struct atbm_store_cmd_code,
|
|
lhead);
|
|
|
|
if(cmd_code->show_cmd)
|
|
show_len = cmd_code->show_cmd(atbm_hw_priv_dereference(),cmd_code,show_buff,show_buff ? true:false);
|
|
if(show_buff){
|
|
if((show_len)&&(len+show_len<ATBM_SHOW_MSG_MAX_SIZE)){
|
|
memcpy(buf+len,show_buff,show_len);
|
|
len += show_len;
|
|
}
|
|
}
|
|
show_len = 0;
|
|
atbm_store_cmd_echo_done(cmd_code);
|
|
atbm_store_cmd_deinit_show(&cmd_code->echo);
|
|
}
|
|
if(len&&show_buff&&atbm_write_backup_commond(show_buff)){
|
|
if(WARN_ON(len>ATBM_SHOW_MSG_MAX_SIZE))
|
|
len = ATBM_SHOW_MSG_MAX_SIZE;
|
|
memset(backup_show,0,ATBM_SHOW_MSG_MAX_SIZE);
|
|
memcpy(backup_show,show_buff,len);
|
|
backup_show_size = len;
|
|
}
|
|
atbm_module_muxunlock();
|
|
atbm_modulefs_unlock();
|
|
if(show_buff)
|
|
atbm_kfree(show_buff);
|
|
return len;
|
|
}
|
|
|
|
static void atbm_module_cmd_init(void)
|
|
{
|
|
unsigned int index = 0;
|
|
|
|
INIT_LIST_HEAD(&atbm_cmd_echo_ready_list);
|
|
atbm_common_hash_list_init(atbm_cmd_hash_head,ATBM_CMD_HASHENTRIES);
|
|
|
|
for(index = 0;index<ARRAY_SIZE(cmd_code_buff);index++){
|
|
unsigned int hash_index = atbm_hash_index(cmd_code_buff[index].label,
|
|
strlen(cmd_code_buff[index].label),ATBM_CMD_HASHBITS);
|
|
|
|
if(strlen(cmd_code_buff[index].label) > ATBM_CMD_MAX_STRING_LEN){
|
|
atbm_printk_err("%s %d ,ERROR !!! strlen(%s)=%d > 32\n",
|
|
__func__,__LINE__,cmd_code_buff[index].label,strlen(cmd_code_buff[index].label));
|
|
return;
|
|
}
|
|
hlist_add_head(&cmd_code_buff[index].hnode,&atbm_cmd_hash_head[hash_index]);
|
|
cmd_code_buff[index].echo_ready = false;
|
|
atbm_store_cmd_deinit_show(&cmd_code_buff[index].echo);
|
|
atbm_printk_debug("%s:[%s]->[%d]\n",__func__,cmd_code_buff[index].label,hash_index);
|
|
}
|
|
|
|
backup_show = atbm_kzalloc(ATBM_SHOW_MSG_MAX_SIZE, GFP_KERNEL);
|
|
WARN_ON(backup_show == NULL);
|
|
backup_show_size = 0;
|
|
}
|
|
|
|
static void atbm_module_cmd_exit(void)
|
|
{
|
|
while (!list_empty(&atbm_cmd_echo_ready_list)) {
|
|
struct atbm_store_cmd_code *cmd_code =
|
|
list_first_entry(&atbm_cmd_echo_ready_list, struct atbm_store_cmd_code,
|
|
lhead);
|
|
if(cmd_code->show_cmd)
|
|
cmd_code->show_cmd(atbm_hw_priv_dereference(),cmd_code,NULL,false);
|
|
atbm_store_cmd_echo_done(cmd_code);
|
|
atbm_store_cmd_deinit_show(&cmd_code->echo);
|
|
}
|
|
|
|
if(backup_show){
|
|
atbm_kfree(backup_show);
|
|
}
|
|
backup_show = NULL;
|
|
backup_show_size = 0;
|
|
}
|
|
static void atbm_module_firmware_caps_show(struct atbm_module_show *show_buff,struct atbm_common *hw_priv)
|
|
{
|
|
#define WSM_CAP(cap) !!(hw_priv->wsm_caps.firmwareCap&cap)
|
|
|
|
atbm_module_show_put(show_buff,LIGHT"Firmare Cap:"NORMAL ENTER);
|
|
atbm_module_show_put(show_buff,"PRIVATE_IE [%d]\n" ,WSM_CAP(CAPABILITIES_ATBM_PRIVATE_IE));
|
|
atbm_module_show_put(show_buff,"NVR_IPC [%d]\n" ,WSM_CAP(CAPABILITIES_NVR_IPC));
|
|
atbm_module_show_put(show_buff,"NO_CONFIRM [%d]\n" ,WSM_CAP(CAPABILITIES_NO_CONFIRM));
|
|
atbm_module_show_put(show_buff,"SDIO_PATCH [%d]\n" ,WSM_CAP(CAPABILITIES_SDIO_PATCH));
|
|
atbm_module_show_put(show_buff,"NO_BACKOFF [%d]\n" ,WSM_CAP(CAPABILITIES_NO_BACKOFF));
|
|
atbm_module_show_put(show_buff,"CFO [%d]\n" ,WSM_CAP(CAPABILITIES_CFO));
|
|
atbm_module_show_put(show_buff,"AGC [%d]\n" ,WSM_CAP(CAPABILITIES_AGC));
|
|
atbm_module_show_put(show_buff,"TXCAL [%d]\n" ,WSM_CAP(CAPABILITIES_TXCAL));
|
|
atbm_module_show_put(show_buff,"CTS_BUG [%d]\n" ,WSM_CAP(CAPABILITIES_CTS_BUG));
|
|
atbm_module_show_put(show_buff,"MONITOR [%d]\n" ,WSM_CAP(CAPABILITIES_MONITOR));
|
|
atbm_module_show_put(show_buff,"CUSTOM [%d]\n" ,WSM_CAP(CAPABILITIES_CUSTOM));
|
|
atbm_module_show_put(show_buff,"SMARTCONFIG [%d]\n" ,WSM_CAP(CAPABILITIES_SMARTCONFIG));
|
|
atbm_module_show_put(show_buff,"ETF [%d]\n" ,WSM_CAP(CAPABILITIES_ETF));
|
|
atbm_module_show_put(show_buff,"LMAC_RATECTL[%d]\n" ,WSM_CAP(CAPABILITIES_LMAC_RATECTL));
|
|
atbm_module_show_put(show_buff,"LMAC_TPC [%d]\n" ,WSM_CAP(CAPABILITIES_LMAC_TPC));
|
|
atbm_module_show_put(show_buff,"LMAC_TEMPC [%d]\n" ,WSM_CAP(CAPABILITIES_LMAC_TEMPC));
|
|
atbm_module_show_put(show_buff,"USE_IPC [%d]\n" ,WSM_CAP(CAPABILITIES_USE_IPC));
|
|
atbm_module_show_put(show_buff,"OUTER_PA [%d]\n" ,WSM_CAP(CAPABILITIES_OUTER_PA));
|
|
atbm_module_show_put(show_buff,"HW_CHECKSUM [%d]\n" ,WSM_CAP(CAPABILITIES_HW_CHECKSUM));
|
|
atbm_module_show_put(show_buff,"MULTI_RX [%d]\n" ,WSM_CAP(CAPABILITIES_SINGLE_CHANNEL_MULTI_RX));
|
|
atbm_module_show_put(show_buff,"USB_RECOVERY_BUG [%d]\n" ,WSM_CAP(CAPABILITIES_USB_RECOVERY_BUG));
|
|
atbm_module_show_put(show_buff,"POWER_CONSUMPTION [%d]\n" ,WSM_CAP(CAPABILITIES_POWER_CONSUMPTION));
|
|
atbm_module_show_put(show_buff,"RSSI_DECIDE_TXPOWER [%d]\n" ,WSM_CAP(CAPABILITIES_RSSI_DECIDE_TXPOWER));
|
|
atbm_module_show_put(show_buff,"RTS_LONG_DUR [%d]\n" ,WSM_CAP(CAPABILITIES_RTS_LONG_DURATION));
|
|
atbm_module_show_put(show_buff,"TX_CFO_PPM_CORRECTION [%d]\n" ,WSM_CAP(CAPABILITIES_TX_CFO_PPM_CORRECTION));
|
|
atbm_module_show_put(show_buff,"NOISE_SET_DCXO [%d]\n" ,WSM_CAP(CAPABILITIES_NOISE_SET_DCXO));
|
|
}
|
|
extern char * get_chip_type(void);
|
|
static void atbm_module_driver_caps_show(struct atbm_module_show *show_buff,struct atbm_common *hw_priv)
|
|
{
|
|
atbm_module_show_put(show_buff,LIGHT"Driver Cap:"NORMAL ENTER);
|
|
#ifdef USB_BUS
|
|
atbm_module_show_put(show_buff,"HIF_TYPE [%s]\n","USB");
|
|
#endif
|
|
#ifdef SDIO_BUS
|
|
atbm_module_show_put(show_buff,"HIF_TYPE [%s]\n","SDIO");
|
|
#endif
|
|
#ifdef SPI_BUS
|
|
atbm_module_show_put(show_buff,"HIF_TYPE [%s]\n","SPI");
|
|
#endif
|
|
#ifdef ATBM_NOT_SUPPORT_40M_CHW
|
|
atbm_module_show_put(show_buff,"HW_CHW [%s]\n","20M");
|
|
#else
|
|
atbm_module_show_put(show_buff,"HW_CHW [%s]\n","40M");
|
|
#endif
|
|
#ifdef CONFIG_ATBM_5G_PRETEND_2G
|
|
atbm_module_show_put(show_buff,"BAND_SUPPORT[%s]\n","5G and 2G");
|
|
#else
|
|
atbm_module_show_put(show_buff,"BAND_SUPPORT[%s]\n","only 2G");
|
|
#endif
|
|
atbm_module_show_put(show_buff,"CHIP NAME [%s]\n",get_chip_type());
|
|
}
|
|
static ssize_t atbm_module_show_system_info(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct atbm_module_show sys_show;
|
|
struct atbm_common *hw_priv = NULL;
|
|
|
|
atbm_show_init(&sys_show,buf);
|
|
|
|
atbm_module_muxlock();
|
|
if(atbm_hw_priv_dereference() == NULL){
|
|
atbm_module_show_put(&sys_show,"system info not exit,please plug chip\n");
|
|
goto exit;
|
|
}
|
|
hw_priv = atbm_hw_priv_dereference();
|
|
atbm_module_show_put(&sys_show,LIGHT"DriverVer [%d]"NORMAL ENTER ,DRIVER_VER);
|
|
atbm_module_show_put(&sys_show,LIGHT"FirmwareVer [%d]"NORMAL ENTER ,hw_priv->wsm_caps.firmwareVersion);
|
|
atbm_module_firmware_caps_show(&sys_show,hw_priv);
|
|
atbm_module_driver_caps_show(&sys_show,hw_priv);
|
|
exit:
|
|
atbm_module_muxunlock();
|
|
|
|
return sys_show.show_count;
|
|
}
|
|
static ssize_t atbm_module_show_backup_info(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
ssize_t size = 0;
|
|
|
|
atbm_modulefs_lock();
|
|
atbm_module_muxlock();
|
|
if(backup_show && backup_show_size){
|
|
size = backup_show_size;
|
|
if(WARN_ON(size > ATBM_SHOW_MSG_MAX_SIZE))
|
|
size = ATBM_SHOW_MSG_MAX_SIZE;
|
|
memcpy(buf,backup_show,ATBM_SHOW_MSG_MAX_SIZE);
|
|
}
|
|
atbm_module_muxunlock();
|
|
atbm_modulefs_unlock();
|
|
|
|
return size;
|
|
}
|
|
|
|
|
|
static ssize_t atbm_module_show_get_efuse(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct atbm_module_show sys_show;
|
|
struct atbm_common *hw_priv = NULL;
|
|
struct efuse_headr efuse_data;
|
|
|
|
atbm_show_init(&sys_show,buf);
|
|
memset(&efuse_data,0, sizeof(struct efuse_headr));
|
|
atbm_module_muxlock();
|
|
if(atbm_hw_priv_dereference() == NULL){
|
|
atbm_module_show_put(&sys_show,"atbm_module_show_get_efuse:system info not exit,please plug chip\n");
|
|
goto exit;
|
|
}
|
|
hw_priv = atbm_hw_priv_dereference();
|
|
if (wsm_get_efuse_data(hw_priv, &efuse_data, sizeof(efuse_data)) == 0){
|
|
if(memcmp(&hw_priv->efuse,&efuse_data,sizeof(efuse_data)) != 0){
|
|
atbm_printk_err("atbm_module_show_get_efuse:efsue not same ! \n");
|
|
}
|
|
}else{
|
|
atbm_printk_err("get efsue error! \n");
|
|
goto exit;
|
|
}
|
|
atbm_module_show_put(&sys_show,"dcxo[%d]\n" ,efuse_data.dcxo_trim);
|
|
atbm_module_show_put(&sys_show,"gain1[%d]\n" ,efuse_data.delta_gain1);
|
|
atbm_module_show_put(&sys_show,"gain2[%d]\n" ,efuse_data.delta_gain2);
|
|
atbm_module_show_put(&sys_show,"gain3[%d]\n" ,efuse_data.delta_gain3);
|
|
atbm_module_show_put(&sys_show,"mac[%02x:%02x:%02x:%02x:%02x:%02x]\n",
|
|
efuse_data.mac[0],efuse_data.mac[1],efuse_data.mac[2]
|
|
,efuse_data.mac[3],efuse_data.mac[4],efuse_data.mac[5]);
|
|
|
|
exit:
|
|
atbm_module_muxunlock();
|
|
return sys_show.show_count;
|
|
}
|
|
|
|
static ssize_t atbm_module_show_first_efuse(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct atbm_module_show sys_show;
|
|
struct atbm_common *hw_priv = NULL;
|
|
struct efuse_headr efuse_data;
|
|
|
|
atbm_show_init(&sys_show,buf);
|
|
memset(&efuse_data,0, sizeof(struct efuse_headr));
|
|
atbm_module_muxlock();
|
|
if(atbm_hw_priv_dereference() == NULL){
|
|
atbm_module_show_put(&sys_show,"atbm_module_show_get_efuse:system info not exit,please plug chip\n");
|
|
goto exit;
|
|
}
|
|
hw_priv = atbm_hw_priv_dereference();
|
|
if (wsm_get_efuse_first_data(hw_priv, &efuse_data, sizeof(efuse_data)) != 0){
|
|
atbm_printk_err("get first efsue error! \n");
|
|
goto exit;
|
|
}
|
|
atbm_module_show_put(&sys_show,"dcxo[%d]\n" ,efuse_data.dcxo_trim);
|
|
atbm_module_show_put(&sys_show,"gain1[%d]\n" ,efuse_data.delta_gain1);
|
|
atbm_module_show_put(&sys_show,"gain2[%d]\n" ,efuse_data.delta_gain2);
|
|
atbm_module_show_put(&sys_show,"gain3[%d]\n" ,efuse_data.delta_gain3);
|
|
atbm_module_show_put(&sys_show,"mac[%02x:%02x:%02x:%02x:%02x:%02x]\n",
|
|
efuse_data.mac[0],efuse_data.mac[1],efuse_data.mac[2]
|
|
,efuse_data.mac[3],efuse_data.mac[4],efuse_data.mac[5]);
|
|
|
|
exit:
|
|
atbm_module_muxunlock();
|
|
return sys_show.show_count;
|
|
}
|
|
|
|
|
|
static ssize_t atbm_module_show_remain_efuse(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct atbm_module_show sys_show;
|
|
struct atbm_common *hw_priv = NULL;
|
|
int remainBit = 0;
|
|
|
|
atbm_show_init(&sys_show,buf);
|
|
|
|
atbm_module_muxlock();
|
|
if(atbm_hw_priv_dereference() == NULL){
|
|
atbm_module_show_put(&sys_show,"atbm_module_show_get_efuse:system info not exit,please plug chip\n");
|
|
goto exit;
|
|
}
|
|
hw_priv = atbm_hw_priv_dereference();
|
|
if(wsm_get_efuse_remain_bit(hw_priv, &remainBit, sizeof(int)) != 0){
|
|
atbm_printk_err("get efsue reamin space error! \n");
|
|
goto exit;
|
|
}
|
|
|
|
atbm_module_show_put(&sys_show,"reamin Efuse[%d bit]\n" ,remainBit);
|
|
|
|
|
|
exit:
|
|
atbm_module_muxunlock();
|
|
return sys_show.show_count;
|
|
}
|
|
|
|
static ssize_t atbm_module_show_cfg_power(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct atbm_module_show sys_show;
|
|
struct atbm_common *hw_priv = NULL;
|
|
struct cfg_txpower_t configured_txpower;
|
|
int i,ret;
|
|
const char *ratebuf[11] = {"b_1M_2M",
|
|
"b_5_5M_11M",
|
|
"g_6M_n_6_5M",
|
|
"g_9M",
|
|
"g_12M_n_13M",
|
|
"g_18M_n_19_5M",
|
|
"g_24M_n_26M",
|
|
"g_36M_n_39M",
|
|
"g_48M_n_52M",
|
|
"g_54M_n_58_5M",
|
|
"n_65M"};
|
|
|
|
memset(&configured_txpower,0, sizeof(configured_txpower));
|
|
|
|
atbm_show_init(&sys_show,buf);
|
|
|
|
atbm_module_muxlock();
|
|
if(atbm_hw_priv_dereference() == NULL){
|
|
atbm_module_show_put(&sys_show,"atbm_module_show_get_efuse:system info not exit,please plug chip\n");
|
|
goto exit;
|
|
}
|
|
hw_priv = atbm_hw_priv_dereference();
|
|
#if defined(CONFIG_TXPOWER_DCXO_VALUE) || defined(CONFIG_RATE_TXPOWER)
|
|
if ((ret = wsm_get_cfg_txpower(hw_priv, (void *)&configured_txpower, sizeof(configured_txpower))) == 0){
|
|
for(i=0;i<sizeof(configured_txpower.set_txpwr_delta_gain);i++)
|
|
atbm_module_show_put(&sys_show,"delta_gain%d:%d\n",i+1,configured_txpower.set_txpwr_delta_gain[i]);
|
|
for(i=0;i<sizeof(configured_txpower.set_b_txpwr_delta_gain);i++)
|
|
atbm_module_show_put(&sys_show,"b_gain%d:%d\n",i+1,configured_txpower.set_b_txpwr_delta_gain[i]);
|
|
for(i=0;i<sizeof(configured_txpower.set_gn_txpwr_delta_gain);i++)
|
|
atbm_module_show_put(&sys_show,"gn_gain%d:%d\n",i+1,configured_txpower.set_gn_txpwr_delta_gain[i]);
|
|
atbm_module_show_put(&sys_show,"\n\n");
|
|
for(i=0;i<sizeof(configured_txpower.different_rate_txpower_mode);i++)
|
|
atbm_module_show_put(&sys_show,"%s:%d\n",ratebuf[i],configured_txpower.different_rate_txpower_mode[i]);
|
|
for(i=0;i<sizeof(configured_txpower.different_rate_txpower_mode_40M);i++)
|
|
atbm_module_show_put(&sys_show,"%s_40M:%d\n",ratebuf[i],configured_txpower.different_rate_txpower_mode_40M[i]);
|
|
}
|
|
else{
|
|
atbm_printk_err("read configured tx power failed\n");
|
|
}
|
|
#else
|
|
atbm_printk_err("undefine CONFIG_RATE_TXPOWER or CONFIG_TXPOWER_DCXO_VALUE,so Not support\n");
|
|
#endif
|
|
|
|
exit:
|
|
atbm_module_muxunlock();
|
|
return sys_show.show_count;
|
|
}
|
|
|
|
|
|
|
|
static struct hlist_head *atbm_printk_hash_list(const char *string,unsigned int len)
|
|
{
|
|
return atbm_hash_list(string,len,atbm_printk_hash_head,ATBM_PRINTK_HASHBITS);
|
|
}
|
|
static struct atbm_printk_mask_table_s *atbm_printk_find_mask_table(const char *pos,unsigned int pos_len)
|
|
{
|
|
unsigned int string_len = 0;
|
|
struct hlist_head *printk_hlist = NULL;
|
|
struct atbm_printk_mask_table_s *printk_node;
|
|
struct hlist_node *node;
|
|
|
|
if(ATBM_PRINTK_MAX_STRING_LEN<pos_len){
|
|
atbm_printk_always("%s:[%d] pos_len err\n",__func__,pos_len);
|
|
return NULL;
|
|
}
|
|
|
|
string_len = atbm_hash_string_len(pos,pos_len);
|
|
if(string_len == 0){
|
|
atbm_printk_always("%s:[%s] string_len err\n",__func__,pos);
|
|
return NULL;
|
|
}
|
|
|
|
printk_hlist = atbm_printk_hash_list(pos,string_len);
|
|
|
|
hlist_for_each(node,printk_hlist){
|
|
printk_node = hlist_entry(node,struct atbm_printk_mask_table_s,string_hnode);
|
|
if ((strlen(printk_node->mask_string)==string_len)&&
|
|
(!strncmp(pos, printk_node->mask_string, string_len))){
|
|
return printk_node;
|
|
}
|
|
}
|
|
atbm_printk_always("%s:[%s] can not fund\n",__func__,pos);
|
|
return NULL;
|
|
}
|
|
static ssize_t atbm_module_printk_mask_show(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct atbm_module_show sys_show;
|
|
u8 log_index = 0;
|
|
atbm_show_init(&sys_show,buf);
|
|
|
|
atbm_module_show_put(&sys_show,LIGHT"Debug Level Help--->"NORMAL ENTER);
|
|
for(log_index = 0;log_index<ARRAY_SIZE(printk_mask_table);log_index++){
|
|
atbm_module_show_put(&sys_show,LIGHT"[%s]"NORMAL":%s\n",
|
|
printk_mask_table[log_index].mask_string,
|
|
printk_mask_table[log_index].mask_info);
|
|
}
|
|
atbm_module_show_put(&sys_show,LIGHT"Current Log Level--->"NORMAL ENTER);
|
|
for(log_index = 0;log_index<ARRAY_SIZE(printk_mask_table);log_index++){
|
|
if((printk_mask_table[log_index].mask_val)&atbm_printk_mask){
|
|
atbm_module_show_put(&sys_show,"[%s]\n",printk_mask_table[log_index].mask_string);
|
|
}
|
|
}
|
|
return sys_show.show_count;
|
|
}
|
|
static bool atbm_str_usefull(const char *target)
|
|
{
|
|
return (target[0] == ATBM_UNUSED ? false:true);
|
|
}
|
|
static bool atbm_module_printk_mask_parase(const char *mask_str,ssize_t msg_len)
|
|
{
|
|
const char *pos = mask_str;
|
|
const char *nospace_pos = mask_str;
|
|
const char *pos_end = mask_str+msg_len;
|
|
const char *val_pos;
|
|
ssize_t usefull_len = msg_len;
|
|
ssize_t skip_len = 0;
|
|
const struct atbm_printk_mask_table_s *table = NULL;
|
|
|
|
while(pos<pos_end){
|
|
|
|
nospace_pos = atbm_skip_space(pos,pos_end-pos);
|
|
|
|
if(nospace_pos == NULL){
|
|
atbm_printk_always("%s nospace_pos == NULL\n",__func__);
|
|
return pos == mask_str ? false: true;
|
|
}
|
|
|
|
pos = nospace_pos;
|
|
usefull_len = pos_end-pos;
|
|
|
|
if(pos[0] == ATBM_TAIL){
|
|
return pos == mask_str ? false: true;
|
|
}else if((pos[0] == ATBM_LINEF)||(pos[0] == ATBM_ENTER)){
|
|
return pos == mask_str ? false: true;
|
|
}else if((!strncmp(pos,LOG_DEFAULT,strlen(LOG_DEFAULT)))&&(!atbm_string_invalid(pos[strlen(LOG_DEFAULT)]))){
|
|
atbm_printk_mask = ATBM_PRINTK_DEFAULT_MASK;
|
|
skip_len = strlen(LOG_DEFAULT);
|
|
}else if((!strncmp(pos,LOG_CLEAR,strlen(LOG_CLEAR)))&&(!atbm_string_invalid(pos[strlen(LOG_CLEAR)]))){
|
|
skip_len = strlen(LOG_CLEAR);
|
|
atbm_printk_mask = ATBM_PRINTK_CLEAR;
|
|
}else if((!strncmp(pos,LOG_ALL,strlen(LOG_ALL)))&&(!atbm_string_invalid(pos[strlen(LOG_ALL)]))){
|
|
skip_len = strlen(LOG_ALL);
|
|
atbm_printk_mask = ATBM_PRINTK_ALL;
|
|
}
|
|
else if(memchr(pos, ATBM_EQUAL, pos_end - pos) == NULL){
|
|
return false;
|
|
}else {
|
|
u8 index = 0;
|
|
/*
|
|
*find '='
|
|
*/
|
|
val_pos = memchr(pos, ATBM_EQUAL, pos_end - pos);
|
|
if((val_pos == NULL) || (pos == val_pos) || (pos_end == val_pos)){
|
|
atbm_printk_always("can not find = %s:%s\n",pos,val_pos);
|
|
return false;
|
|
}
|
|
|
|
table = atbm_printk_find_mask_table(pos,val_pos - pos);
|
|
|
|
if(table == NULL){
|
|
atbm_printk_always("can not find hash tabel:%s\n",pos);
|
|
return false;
|
|
}
|
|
|
|
val_pos++;
|
|
val_pos = atbm_skip_space(val_pos,usefull_len-(val_pos-pos));
|
|
if(val_pos == NULL){
|
|
atbm_printk_always("must be ON or OFF:%s\n",val_pos);
|
|
return false;
|
|
}
|
|
/*
|
|
*len > strlen("ON")
|
|
*/
|
|
if(pos_end - val_pos<strlen(LOG_ON)){
|
|
atbm_printk_always("%s len is not enough %s\n",__func__,val_pos);
|
|
return false;
|
|
}
|
|
/*
|
|
*is on or off
|
|
*/
|
|
for(index = 0;index<ARRAY_SIZE(option_table);index++){
|
|
const char*option_pos = NULL;
|
|
u8 option_len = 0;
|
|
if((option_pos = strstr(val_pos,option_table[index].opton_string)) == NULL){
|
|
continue;
|
|
}
|
|
|
|
if(option_pos != val_pos){
|
|
atbm_printk_always("option_pos(%s),val_pos(%s)\n",option_pos,val_pos);
|
|
continue;
|
|
}
|
|
|
|
option_len += strlen(option_table[index].opton_string);
|
|
|
|
/*
|
|
*between cmd is space
|
|
*/
|
|
if(atbm_string_invalid(val_pos[option_len])){
|
|
atbm_printk_always("option format err [%s][%s]\n",pos,val_pos);
|
|
continue;
|
|
}
|
|
atbm_printk_always("[%s=%s]--->[%s=%s]\n",table->mask_string,atbm_printk_mask&table->mask_val?LOG_ON:LOG_OFF,
|
|
table->mask_string,option_table[index].opton_string);
|
|
val_pos += option_len;
|
|
if(option_table[index].option_val){
|
|
atbm_printk_mask |= table->mask_val;
|
|
}else {
|
|
atbm_printk_mask &= ~table->mask_val;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if(index == ARRAY_SIZE(option_table)){
|
|
atbm_printk_always("option not found [%s][%s]\n",pos,val_pos);
|
|
return false;
|
|
}
|
|
skip_len = val_pos-pos;
|
|
}
|
|
|
|
pos += skip_len;
|
|
}
|
|
return pos == mask_str ? false: true;
|
|
}
|
|
static ssize_t atbm_module_printk_mask_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
const char *buf, size_t n)
|
|
{
|
|
const char *p_enter = NULL;
|
|
const char *p = NULL;
|
|
const char *nospace_pos = NULL;
|
|
const char *pos = buf;
|
|
const char *pos_end = buf+n;
|
|
ssize_t line_len = 0;
|
|
ssize_t msg_len;
|
|
ssize_t len_left = n;
|
|
|
|
atbm_printk_always("[%s]:%s\n",__func__,buf);
|
|
do {
|
|
if(pos>=pos_end){
|
|
atbm_printk_always("%s end 1\n",__func__);
|
|
break;
|
|
}
|
|
pos = atbm_skip_space(pos,len_left);
|
|
if(pos == NULL){
|
|
atbm_printk_always("pos (%s) err\n",buf);
|
|
break;
|
|
}
|
|
if (pos[0] == ATBM_TAIL){
|
|
break;
|
|
}
|
|
/*
|
|
*find line of the file
|
|
*linux:\n
|
|
*windows:\r\n
|
|
*mac \r
|
|
*/
|
|
p_enter = memchr(pos, ATBM_LINEF, len_left);
|
|
if(p_enter == NULL){
|
|
p_enter = memchr(pos, ATBM_ENTER, len_left);
|
|
}
|
|
if(p_enter == NULL){
|
|
atbm_printk_always("%s:can not fine aline\n",__func__);
|
|
}
|
|
line_len = p_enter ? p_enter - pos : len_left;
|
|
|
|
if(line_len<=0){
|
|
atbm_printk_always("%s end 2\n",__func__);
|
|
break;
|
|
}
|
|
|
|
p = pos;
|
|
/*
|
|
*pos pointer next line
|
|
*/
|
|
if(p_enter == NULL){
|
|
pos += line_len;
|
|
}else {
|
|
pos += (line_len+1);
|
|
}
|
|
|
|
if(pos > pos_end){
|
|
atbm_printk_always("%s pos > pos_end\n",__func__);
|
|
break;
|
|
}
|
|
|
|
len_left = pos_end-pos;
|
|
|
|
msg_len = line_len;
|
|
/*
|
|
*skip header space
|
|
*/
|
|
nospace_pos = atbm_skip_space(p,msg_len);
|
|
|
|
if(nospace_pos == NULL){
|
|
atbm_printk_always("%s nospace_pos == NULL\n",__func__);
|
|
continue;
|
|
}
|
|
|
|
msg_len -= nospace_pos-p;
|
|
|
|
p = nospace_pos;
|
|
/*
|
|
*'#' means unusefull
|
|
*/
|
|
if(atbm_str_usefull(p) == false){
|
|
atbm_printk_always("%s p is not usefull\n",__func__);
|
|
continue;
|
|
}
|
|
if(atbm_module_printk_mask_parase(p,msg_len) == false){
|
|
atbm_printk_always("%s parase err\n",__func__);
|
|
return -EINVAL;
|
|
}
|
|
}while(1);
|
|
return pos != pos_end ? n:-EINVAL;
|
|
}
|
|
static void atbm_module_printk_init(void)
|
|
{
|
|
unsigned int index = 0;
|
|
|
|
atbm_common_hash_list_init(atbm_printk_hash_head,ATBM_PRINTK_HASHENTRIES);
|
|
|
|
for(index = 0;index<ARRAY_SIZE(printk_mask_table);index++){
|
|
unsigned int hash_index = atbm_hash_index(printk_mask_table[index].mask_string,
|
|
strlen(printk_mask_table[index].mask_string),ATBM_PRINTK_HASHBITS);
|
|
|
|
if(strlen(printk_mask_table[index].mask_string) > ATBM_PRINTK_MAX_STRING_LEN){
|
|
atbm_printk_err("%s %d ,ERROR !!! strlen(%s)=%d > 32\n",
|
|
__func__,__LINE__,printk_mask_table[index].mask_string,strlen(printk_mask_table[index].mask_string));
|
|
return;
|
|
}
|
|
atbm_printk_debug("%s:[%s]->[%d]\n",__func__,printk_mask_table[index].mask_string,hash_index);
|
|
hlist_add_head(&printk_mask_table[index].string_hnode,&atbm_printk_hash_head[hash_index]);
|
|
}
|
|
}
|
|
|
|
static struct kobject *atbm_module_kobj = NULL;
|
|
|
|
static struct kobj_attribute atbm_module_common_attr = __ATTR(atbm_cmd, 0644,atbm_module_cmd_show,atbm_module_cmd_store);
|
|
static struct kobj_attribute atbm_module_sysinfo_attr = __ATTR(atbm_sys, 0444,atbm_module_show_system_info, NULL);
|
|
static struct kobj_attribute atbm_module_common_backup_attr = __ATTR(atbm_sys_backup, 0444,atbm_module_show_backup_info, NULL);
|
|
static struct kobj_attribute atbm_module_getefuse_attr = __ATTR(atbm_efuse, 0444,atbm_module_show_get_efuse, NULL);
|
|
static struct kobj_attribute atbm_module_getfirsyefuse_attr = __ATTR(atbm_first_efuse, 0444,atbm_module_show_first_efuse, NULL);
|
|
static struct kobj_attribute atbm_module_remainefuse_attr = __ATTR(atbm_remainEfuseSpace, 0444,atbm_module_show_remain_efuse, NULL);
|
|
static struct kobj_attribute atbm_module_get_rate_power = __ATTR(atbm_get_cfg_power, 0444,atbm_module_show_cfg_power, NULL);
|
|
|
|
static struct kobj_attribute atbm_module_printk_mask = __ATTR(atbm_printk_mask, 0644,atbm_module_printk_mask_show, atbm_module_printk_mask_store);
|
|
|
|
static struct attribute *atbm_module_attribute_group[]= {
|
|
&atbm_module_common_attr.attr,
|
|
&atbm_module_common_backup_attr.attr,
|
|
&atbm_module_sysinfo_attr.attr,
|
|
&atbm_module_printk_mask.attr,
|
|
&atbm_module_getefuse_attr.attr,
|
|
&atbm_module_getfirsyefuse_attr.attr,
|
|
&atbm_module_remainefuse_attr.attr,
|
|
&atbm_module_get_rate_power.attr,
|
|
NULL,
|
|
};
|
|
static struct attribute_group atbm_module_attr_group = {
|
|
.attrs = atbm_module_attribute_group,
|
|
};
|
|
|
|
int atbm_module_attribute_init(void)
|
|
{
|
|
int error;
|
|
struct kobject *parent = atbm_module_parent;
|
|
|
|
atbm_module_kobj = kobject_create_and_add("atbmfs",parent);
|
|
if (!atbm_module_kobj){
|
|
return -EINVAL;
|
|
}
|
|
error = sysfs_create_group(atbm_module_kobj, &atbm_module_attr_group);
|
|
if (error)
|
|
kobject_put(atbm_module_kobj);
|
|
atbm_modulefs_lock_int();
|
|
atbm_module_printk_init();
|
|
atbm_module_cmd_init();
|
|
return error;
|
|
}
|
|
void atbm_module_attribute_exit(void)
|
|
{
|
|
if(atbm_module_kobj == NULL)
|
|
return;
|
|
sysfs_remove_group(atbm_module_kobj, &atbm_module_attr_group);
|
|
kobject_put(atbm_module_kobj);
|
|
atbm_modulefs_lock();
|
|
atbm_module_cmd_exit();
|
|
atbm_modulefs_unlock();
|
|
atbm_modulefs_lock_release();
|
|
}
|
|
#endif
|