1143 lines
31 KiB
C
Executable File
1143 lines
31 KiB
C
Executable File
/*
|
|
* Command implementations
|
|
*/
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include "besphy_rf.h"
|
|
|
|
|
|
#define U8_MAX 255
|
|
#define U16_MAX 65535
|
|
|
|
|
|
/* rf cmd length cannot exceed 640 bytes */
|
|
#define RF_LEN_MAX 640
|
|
struct vendor_rf_cmd_t {
|
|
u32 cmd_type;
|
|
u32 cmd_argc;
|
|
u32 cmd_len;
|
|
u8 cmd[0];
|
|
};
|
|
|
|
/* ID - BES_MSG_TEST */
|
|
struct bes_msg_test_t {
|
|
int dummy;
|
|
};
|
|
|
|
/**
|
|
* ID -BES_MSG_SET_SNAP_FRAME
|
|
* bes_msg_set_snap_frame - set SNAP frame format
|
|
* @len: length of SNAP frame, if 0 SNAP frame disabled
|
|
* @frame: SNAP frame format
|
|
*
|
|
* In this structure is difference between user space because
|
|
* format and length have to be hidden
|
|
*
|
|
*/
|
|
struct bes_msg_set_snap_frame_t {
|
|
u8 len;
|
|
u8 frame[0];
|
|
};
|
|
|
|
struct nl_data {
|
|
size_t d_size;
|
|
void *d_data;
|
|
};
|
|
|
|
/* ID - BES_MSG_TEST */
|
|
struct advance_scan_elems {
|
|
u8 scanMode;
|
|
u16 duration;
|
|
};
|
|
|
|
|
|
/**
|
|
* ID - BES_MSG_SET_TX_QUEUE_PARAMS
|
|
* bes_msg_set_txqueue_params - store Tx queue params
|
|
* @user_priority: User priority for which TSPEC negotiated
|
|
* @medium_time: Allowed medium time
|
|
* @expiry_time: The expiry time of MSDU
|
|
*
|
|
*/
|
|
struct bes_msg_set_txqueue_params {
|
|
u8 user_priority;
|
|
u16 medium_time;
|
|
u16 expiry_time;
|
|
};
|
|
|
|
/**
|
|
* ID - BES_MSG_START_STOP_TSM
|
|
* bes_msg_set_start_stop_tsm - To start or stop collecting TSM metrics in
|
|
* bes2600 driver
|
|
* @start: To start or stop collecting TSM metrics
|
|
* @up: up for which metrics to be collected
|
|
* @packetization_delay: Packetization period for this TID
|
|
*
|
|
*/
|
|
struct bes_msg_start_stop_tsm_t {
|
|
u8 start; /*1: To start, 0: To stop*/
|
|
u8 up;
|
|
u16 packetization_delay;
|
|
};
|
|
|
|
/**
|
|
* ID - BES_MSG_SET_POWER_SAVE
|
|
* power_save_elems - To enable/disable legacy power Save
|
|
*/
|
|
struct power_save_elems {
|
|
int powerSave;
|
|
};
|
|
|
|
/**
|
|
* add_ip_offload_t - Parameters related to tcp alive: port, payload length, payload
|
|
*/
|
|
struct add_ip_offload_t {
|
|
uint8_t proto;
|
|
uint16_t dest_port;
|
|
uint16_t payload_len;
|
|
uint8_t payload[0];
|
|
};
|
|
|
|
/**
|
|
* ip_alive_iac_idx - idx of tcp & udp alive stream
|
|
*/
|
|
struct ip_alive_iac_idx {
|
|
int idx;
|
|
};
|
|
|
|
/**
|
|
* ip_alive_period - tcp & udp alive period
|
|
*/
|
|
struct ip_alive_period {
|
|
int period;
|
|
};
|
|
|
|
/**
|
|
* bes_tsm_stats - To retrieve the Transmit Stream Measurement stats
|
|
* @actual_msrmt_start_time: The TSF at the time at which the measurement
|
|
* started
|
|
* @msrmt_duration: Duration for measurement
|
|
* @peer_sta_addr: Peer STA address
|
|
* @tid: TID for which measurements were made
|
|
* @reporting_reason: Reason for report sent
|
|
* @txed_msdu_count: The number of MSDUs transmitted for the specified TID
|
|
* @msdu_discarded_count: The number of discarded MSDUs for the specified TID
|
|
* @msdu_failed_count: The number of failed MSDUs for the specified TID
|
|
* @multi_retry_count: The number of MSDUs which were retried
|
|
* @qos_cfpolls_lost_count: The number of QOS CF polls frames lost
|
|
* @avg_q_delay: Average queue delay
|
|
* @avg_transmit_delay: Average transmit delay
|
|
* @bin0_range: Delay range of the first bin (Bin 0)
|
|
* @bin0: bin0 transmit delay histogram
|
|
* @bin1: bin1 transmit delay histogram
|
|
* @bin2: bin2 transmit delay histogram
|
|
* @bin3: bin3 transmit delay histogram
|
|
* @bin4: bin4 transmit delay histogram
|
|
* @bin5: bin5 transmit delay histogram
|
|
*
|
|
*/
|
|
struct bes_tsm_stats {
|
|
u64 actual_msrmt_start_time;
|
|
u16 msrmt_duration;
|
|
u8 peer_sta_addr[6];
|
|
u8 tid;
|
|
u8 reporting_reason;
|
|
u32 txed_msdu_count;
|
|
u32 msdu_discarded_count;
|
|
u32 msdu_failed_count;
|
|
u32 multi_retry_count;
|
|
u32 qos_cfpolls_lost_count;
|
|
u32 avg_q_delay;
|
|
u32 avg_transmit_delay;
|
|
u8 bin0_range;
|
|
u32 bin0;
|
|
u32 bin1;
|
|
u32 bin2;
|
|
u32 bin3;
|
|
u32 bin4;
|
|
u32 bin5;
|
|
} __packed;
|
|
|
|
struct wsm_tx_power_range {
|
|
int min_power_level;
|
|
int max_power_level;
|
|
u32 stepping;
|
|
};
|
|
|
|
struct vendor_rf_cmd_reply {
|
|
u32 id;
|
|
u32 len;
|
|
char msg[0];
|
|
};
|
|
|
|
struct wifi_power_cali_save_t {
|
|
u16 mode;
|
|
u16 band;
|
|
u16 ch;
|
|
u16 power_cali;
|
|
u16 status; /* 0: fail, 1: success */
|
|
};
|
|
|
|
struct wifi_freq_cali_save_t {
|
|
u16 freq_cali;
|
|
u16 status; /* 0: fail, 1: success */
|
|
};
|
|
|
|
/* code to do everything */
|
|
|
|
static void print_dump(const char *fmt, unsigned int size,
|
|
unsigned int count, const void *buffer)
|
|
{
|
|
int i = 0;
|
|
int rowsize = 16;
|
|
|
|
switch(size) {
|
|
case sizeof(uint32_t):
|
|
while(i < count) {
|
|
printf(fmt, *(uint32_t *)((uint32_t *)buffer + i));
|
|
if (i % rowsize == rowsize - 1)
|
|
printf("\n");
|
|
i++;
|
|
}
|
|
break;
|
|
case sizeof(uint16_t):
|
|
while(i < count) {
|
|
printf(fmt, *(uint16_t *)((uint16_t *)buffer + i));
|
|
if (i % rowsize == rowsize - 1)
|
|
printf("\n");
|
|
i++;
|
|
}
|
|
break;
|
|
case sizeof(uint8_t):
|
|
default:
|
|
while(i < count) {
|
|
printf(fmt, *(uint8_t *)((uint8_t *)buffer + i));
|
|
if (i % rowsize == rowsize - 1)
|
|
printf("\n");
|
|
i++;
|
|
}
|
|
break;
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
static int print_recvmsgs(struct nl_msg *msg, void *arg)
|
|
{
|
|
struct nlattr *tb[NL80211_ATTR_MAX + 2];
|
|
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); /* Gets the payload of the msg */
|
|
struct nlattr *td[BESPHY_TM_ATTR_MAX + 2];
|
|
struct bes_tsm_stats tsm_stats;
|
|
struct wsm_tx_power_range power_range[2];
|
|
int cmd_id = *((int *)arg);
|
|
struct vendor_rf_cmd_reply *rf_cmd_msg;
|
|
struct wifi_power_cali_save_t *wifi_power_cali;
|
|
struct wifi_freq_cali_save_t *wifi_freq_cali;
|
|
|
|
/* get reply message for all nlmsg */
|
|
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
|
genlmsg_attrlen(gnlh, 0), NULL);
|
|
|
|
if (!tb[NL80211_ATTR_TESTDATA] || !tb[NL80211_ATTR_WIPHY]) {
|
|
printf("no data!\n");
|
|
return NL_SKIP;
|
|
}
|
|
|
|
/* get reply message for rf test cmd */
|
|
nla_parse(td, BESPHY_TM_ATTR_MAX, nla_data(tb[NL80211_ATTR_TESTDATA]),
|
|
nla_len(tb[NL80211_ATTR_TESTDATA]), NULL);
|
|
|
|
if (!td[BESPHY_TM_MSG_DATA]) {
|
|
printf("no recvmsgs info\n");
|
|
return NL_SKIP;
|
|
}
|
|
|
|
switch (cmd_id) {
|
|
case BES_MSG_TEST:
|
|
printf("\nphy#%d, the cmd msg_test recvmsgs is:\ndummy = %d\n\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]),
|
|
(*((int *)nla_data(td[BESPHY_TM_MSG_DATA]))));
|
|
break;
|
|
case BES_MSG_GET_TX_POWER_LEVEL:
|
|
printf("\nphy#%d, the cmd get_tx_power_level recvmsgs is:\npower = %d\n\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]),
|
|
(*((int *)nla_data(td[BESPHY_TM_MSG_DATA]))));
|
|
break;
|
|
case BES_MSG_GET_TX_POWER_RANGE:
|
|
memcpy(power_range, (struct wsm_tx_power_range *)nla_data(td[BESPHY_TM_MSG_DATA]),
|
|
sizeof(power_range));
|
|
printf("\nphy#%d, the cmd get_tx_power_range recvmsgs is:\
|
|
\ntxPowerRange[0]:\nmin_power_level = %d, max_power_level = %d, stepping = %u\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]),
|
|
power_range[0].min_power_level, power_range[0].max_power_level,
|
|
power_range[0].stepping);
|
|
printf("txPowerRange[1]:\nmin_power_level = %d, max_power_level = %d, stepping = %u\n",
|
|
power_range[1].min_power_level,
|
|
power_range[1].max_power_level, power_range[1].stepping);
|
|
break;
|
|
case BES_MSG_GET_TSM_PARAMS:
|
|
memcpy(&tsm_stats, (struct bes_tsm_stats *)nla_data(td[BESPHY_TM_MSG_DATA]), sizeof(tsm_stats));
|
|
printf("\nphy#%d, the cmd get_tsm_params recvmsgs is:\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]));
|
|
#if __WORDSIZE == 64
|
|
printf("actual_msrmt_start_time = %lu\n", tsm_stats.actual_msrmt_start_time);
|
|
#else
|
|
printf("actual_msrmt_start_time = %llu\n", tsm_stats.actual_msrmt_start_time);
|
|
#endif
|
|
printf("msrmt_duration = %d\n"
|
|
"peer_sta_addr = %02x:%02x:%02x:%02x:%02x:%02x\ntid = %d\n"
|
|
"reporting_reason = %d\ntxed_msdu_count = %u\n"
|
|
"msdu_discarded_count = %u\nmsdu_failed_count = %u\n"
|
|
"multi_retry_count = %u\nqos_cfpolls_lost_count = %u\n"
|
|
"avg_q_delay = %u\navg_transmit_delay = %u\n"
|
|
"bin0_range = %d\nbin0 = %u\nbin1 = %u\nbin1 = %u\n"
|
|
"bin3 = %u\nbin4 = %u\nbin5 = %u\n\n",
|
|
tsm_stats.msrmt_duration, tsm_stats.peer_sta_addr[0], tsm_stats.peer_sta_addr[1],
|
|
tsm_stats.peer_sta_addr[2], tsm_stats.peer_sta_addr[3], tsm_stats.peer_sta_addr[4],
|
|
tsm_stats.peer_sta_addr[5], tsm_stats.tid, tsm_stats.reporting_reason,
|
|
tsm_stats.txed_msdu_count, tsm_stats.msdu_discarded_count, tsm_stats.msdu_failed_count,
|
|
tsm_stats.multi_retry_count, tsm_stats.qos_cfpolls_lost_count, tsm_stats.avg_q_delay,
|
|
tsm_stats.avg_transmit_delay, tsm_stats.bin0_range, tsm_stats.bin0, tsm_stats.bin1,
|
|
tsm_stats.bin2, tsm_stats.bin3, tsm_stats.bin4, tsm_stats.bin5);
|
|
break;
|
|
case BES_MSG_GET_ROAM_DELAY:
|
|
printf("\nphy#%d, the cmd get_roam_delay recvmsgs is:\nroam_delay = %d\n\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]),
|
|
(*((int *)nla_data(td[BESPHY_TM_MSG_DATA]))));
|
|
break;
|
|
case BES_MSG_ADD_IP_OFFLOAD:
|
|
printf("\nphy#%d, the keep_alive_cfg recvmsgs is:\nkeep_alive_iac_idx = %d\n\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]),
|
|
(*((int *)nla_data(td[BESPHY_TM_MSG_DATA]))));
|
|
break;
|
|
case BES_MSG_VENDOR_RF_CMD:
|
|
rf_cmd_msg = (struct vendor_rf_cmd_reply *)nla_data(td[BESPHY_TM_MSG_DATA]);
|
|
switch (rf_cmd_msg->id) {
|
|
case VENDOR_RF_SIGNALING_CMD:
|
|
printf("\nphy#%d, the vendor signaling cmd recvmsgs is:\n%s\n\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]), rf_cmd_msg->msg);
|
|
break;
|
|
case VENDOR_RF_NOSIGNALING_CMD:
|
|
printf("\nphy#%d, the rf cmd recvmsgs is:\n%s\n\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]), rf_cmd_msg->msg);
|
|
break;
|
|
case VENDOR_RF_SAVE_CMD:
|
|
printf("\nphy#%d, save success.\n\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]));
|
|
break;
|
|
case VENDOR_RF_GET_SAVE_FREQOFFSET_CMD:
|
|
printf("\nphy#%d, freq clai: 0x%04x\n\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]),
|
|
((uint16_t *)rf_cmd_msg->msg)[0]);
|
|
break;
|
|
case VENDOR_RF_GET_SAVE_POWERLEVEL_CMD:
|
|
printf("\nphy#%d, power cali 2g:\n", nla_get_u32(tb[NL80211_ATTR_WIPHY]));
|
|
print_dump("0x%04x ", 2, 3, (uint16_t *)rf_cmd_msg->msg);
|
|
printf("power cali 5g:\n");
|
|
print_dump("0x%04x ", 2, 13, (uint16_t *)rf_cmd_msg->msg + 3);
|
|
break;
|
|
case VENDOR_RF_SAVE_FREQOFFSET_CMD:
|
|
wifi_freq_cali = (struct wifi_freq_cali_save_t *)(rf_cmd_msg->msg);
|
|
printf("\nphy#%d, freqOffset save msg:\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]));
|
|
if (wifi_freq_cali->status)
|
|
printf("success to save freq cali.\n");
|
|
else
|
|
printf("fail to save freq cali.\n");
|
|
printf("freq cali = 0x%04x\n", wifi_freq_cali->freq_cali);
|
|
break;
|
|
case VENDOR_RF_SAVE_POWERLEVEL_CMD:
|
|
wifi_power_cali = (struct wifi_power_cali_save_t *)(rf_cmd_msg->msg);
|
|
printf("\nphy#%d, powerlevel save msg:\n",
|
|
nla_get_u32(tb[NL80211_ATTR_WIPHY]));
|
|
if (wifi_power_cali->status)
|
|
printf("success to save power cali.\n");
|
|
else
|
|
printf("fail to save power cali.\n");
|
|
printf("mode = %u, band = %u, ch = %u, powerlevel = 0x%04x\n",
|
|
wifi_power_cali->mode, wifi_power_cali->band,
|
|
wifi_power_cali->ch, wifi_power_cali->power_cali);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return NL_SKIP;
|
|
}
|
|
|
|
/**
|
|
* rf_itoa() converts rf cmd related numbers to characters.
|
|
* NUM_BIT represents the number of bits occupied
|
|
* by cmd_num and cmd_len after they are converted into strings.
|
|
*/
|
|
#if 0
|
|
#define NUM_BIT 3
|
|
static int rf_itoa(char *rf_cmd, int num)
|
|
{
|
|
int i, j;
|
|
int len;
|
|
char tmp[NUM_BIT + 1];
|
|
if (num > pow(10, NUM_BIT) - 1 || num < 1)
|
|
return -1;
|
|
sprintf(tmp, "%d", num);
|
|
len = strlen(tmp);
|
|
if (len > NUM_BIT || len < 1)
|
|
return -1;
|
|
for (i = 0; i < NUM_BIT -len; i++) {
|
|
rf_cmd[i] = '0';
|
|
}
|
|
for (j = 0; i < NUM_BIT && j < len; i++, j++) {
|
|
rf_cmd[i] = tmp[j];
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
/* Merge all parameters into one pointer. */
|
|
static void str_join(u8 *cat_cmd, const int argc, char **argv)
|
|
{
|
|
char *argv_tmp;
|
|
int i;
|
|
for (i = 0; i < argc; argv++, i++) {
|
|
argv_tmp = *argv;
|
|
while (*argv_tmp != '\0') {
|
|
*cat_cmd++ = *argv_tmp++;
|
|
}
|
|
if (i + 1 == argc) {
|
|
*cat_cmd = '\0';
|
|
} else {
|
|
*cat_cmd++ = ' ';
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Gets the length of all parameters. */
|
|
static u32 get_cmd_len(const int argc, char **argv)
|
|
{
|
|
int i;
|
|
u32 ret = 0;
|
|
if (argc <= 1 || !argv)
|
|
return 0;
|
|
for (i = 0; i < argc; argv++, i++) {
|
|
if (*argv != NULL) {
|
|
ret += strlen(*argv) + 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int do_vendor_rf_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
u32 cmd_len;
|
|
static int id_type = BES_MSG_VENDOR_RF_CMD;
|
|
|
|
cmd_len = get_cmd_len(argc, argv);
|
|
if (!cmd_len || cmd_len > RF_LEN_MAX) {
|
|
goto invalid_para;
|
|
}
|
|
|
|
struct vendor_rf_cmd_t *vendor_cmd = (struct vendor_rf_cmd_t *) malloc(cmd_len + 3 * sizeof(u32));
|
|
if (!vendor_cmd) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (!strcmp(argv[1], "save"))
|
|
vendor_cmd->cmd_type = VENDOR_RF_SAVE_CMD;
|
|
else if (!strcmp(argv[1], "get_save_freqOffset"))
|
|
vendor_cmd->cmd_type = VENDOR_RF_GET_SAVE_FREQOFFSET_CMD;
|
|
else if (!strcmp(argv[1], "get_save_powerlevel"))
|
|
vendor_cmd->cmd_type = VENDOR_RF_GET_SAVE_POWERLEVEL_CMD;
|
|
else if (!strcmp(argv[1], "save_powerlevel"))
|
|
vendor_cmd->cmd_type = VENDOR_RF_SAVE_POWERLEVEL_CMD;
|
|
else if (!strcmp(argv[1], "save_freqOffset"))
|
|
vendor_cmd->cmd_type = VENDOR_RF_SAVE_FREQOFFSET_CMD;
|
|
else
|
|
/* distinguish between signaling or non-signaling in the driver.*/
|
|
vendor_cmd->cmd_type = VENDOR_RF_SIG_NOSIG_MIX;
|
|
|
|
vendor_cmd->cmd_argc = argc;
|
|
vendor_cmd->cmd_len = cmd_len;
|
|
str_join(vendor_cmd->cmd, argc, argv);
|
|
|
|
struct nl_data *data_vendor_cmd = (struct nl_data *) malloc(sizeof(struct nl_data));
|
|
if (!data_vendor_cmd) {
|
|
return -ENOMEM;
|
|
}
|
|
data_vendor_cmd->d_size = cmd_len + 3 * sizeof(u32);
|
|
data_vendor_cmd->d_data = vendor_cmd;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, id_type);
|
|
NLA_PUT_DATA(msg, BESPHY_TM_MSG_DATA, data_vendor_cmd);
|
|
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_recvmsgs, &id_type);
|
|
|
|
free(vendor_cmd);
|
|
vendor_cmd = NULL;
|
|
free(data_vendor_cmd);
|
|
data_vendor_cmd = NULL;
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
/**
|
|
* Convert integer numeric string to a int number,
|
|
* otherwise return false.
|
|
* The number of converted numbers does not exceed the size range of INT.
|
|
*/
|
|
#define ATOI_MAX_BIT 10
|
|
static bool msg_tsm_atoi(const char *str, int *ret)
|
|
{
|
|
if (!str || strlen(str) == 0)
|
|
return false;
|
|
|
|
int i, j;
|
|
int len, sum_tmp;
|
|
bool negative = false;
|
|
int inx_end = 0;
|
|
unsigned int sum = 0;
|
|
unsigned int num_max = pow(2, 31) - 1;
|
|
len = strlen(str);
|
|
|
|
if (str[0] == '-') {
|
|
if (len > 1) {
|
|
negative = true;
|
|
inx_end = 1;
|
|
num_max++;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
int multiple[ATOI_MAX_BIT];
|
|
multiple[ATOI_MAX_BIT - 1] = 1;
|
|
for (i = ATOI_MAX_BIT -2; i >= 0; i--) {
|
|
multiple[i] = 10 * multiple[i + 1];
|
|
}
|
|
|
|
for (i = len - 1, j = ATOI_MAX_BIT -1; i >= inx_end && j >= 0; i--, j--) {
|
|
if (str[i] >= '0' && str[i] <= '9') {
|
|
sum_tmp = (str[i] - '0') * multiple[j];
|
|
if (sum <= sum + sum_tmp && sum + sum_tmp <= num_max)
|
|
sum += sum_tmp;
|
|
else
|
|
return false;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (negative) {
|
|
sum *= -1;
|
|
}
|
|
|
|
if (i >= inx_end) {
|
|
return false;
|
|
} else {
|
|
*ret = sum;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
static int do_msg_test_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
if (argc != 3) {
|
|
goto invalid_para;
|
|
}
|
|
|
|
int dummy_tmp;
|
|
static int id_type = BES_MSG_TEST;
|
|
struct bes_msg_test_t msg_test;
|
|
if (!msg_tsm_atoi(argv[2], &dummy_tmp))
|
|
goto invalid_para;
|
|
|
|
msg_test.dummy = dummy_tmp;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_TEST);
|
|
NLA_PUT_TYPE(msg, struct bes_msg_test_t, BESPHY_TM_MSG_DATA, msg_test);
|
|
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_recvmsgs, &id_type);
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
/**
|
|
* Converts hexadecimal strings to a single byte.
|
|
* The input format is, and each parameter contains one
|
|
* or two hexadecimal characters.
|
|
* such as 25 ab Ac AF 2 3 36
|
|
*/
|
|
static bool hex_str_to_byte(int argc, char **argv, unsigned char *ret)
|
|
{
|
|
if (!ret)
|
|
return false;
|
|
|
|
int i, len;
|
|
for (i = 0; i < argc; i++) {
|
|
if (!argv[i])
|
|
return false;
|
|
|
|
len = strlen(argv[i]);
|
|
if (len > 2 || len < 1)
|
|
return false;
|
|
|
|
/* convert lowercase to uppercase. */
|
|
if(argv[i][len - 1] >= 'a' && argv[i][len - 1] <= 'f')
|
|
argv[i][len - 1] = argv[i][len - 1] & ~0x20;
|
|
|
|
/* convert hexadecimal characters to numbers. */
|
|
if (argv[i][len - 1] >= 'A' && argv[i][len - 1] <= 'F')
|
|
ret[i] = argv[i][len - 1] - 'A' + 10;
|
|
else if (argv[i][len - 1] >= '0' && argv[i][len - 1] <= '9')
|
|
ret[i] = argv[i][len - 1] & ~0x30;
|
|
else
|
|
return false;
|
|
|
|
if (len == 2) {
|
|
if(argv[i][0] >= 'a' && argv[i][0] <= 'f')
|
|
argv[i][0] = argv[i][0] & ~0x20;
|
|
|
|
if (argv[i][0] >= 'A' && argv[i][0] <= 'F')
|
|
ret[i] |= (argv[i][0] - 'A' + 10) << 4;
|
|
else if (argv[i][0] >= '0' && argv[i][0] <= '9')
|
|
ret[i] |= (argv[i][0] & ~0x30) << 4;
|
|
else
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
static int do_set_snap_frame_cmd(struct nl_cb *cb, struct nl_msg *msg, int argc,
|
|
char **argv)
|
|
{
|
|
/* argc contains phy and command name */
|
|
if (argc > U8_MAX + 2 || argc < 3) {
|
|
goto invalid_para;
|
|
}
|
|
|
|
argc -= 2;
|
|
argv += 2;
|
|
|
|
struct bes_msg_set_snap_frame_t *snap_frame = (struct bes_msg_set_snap_frame_t *) malloc(argc + 1);
|
|
if (!snap_frame) {
|
|
return -ENOMEM;
|
|
}
|
|
snap_frame->len = (u8)argc;
|
|
if (!hex_str_to_byte(argc, argv, snap_frame->frame))
|
|
goto invalid_para;
|
|
|
|
struct nl_data *data_snap_frame = (struct nl_data *) malloc(sizeof(struct nl_data));
|
|
if (!data_snap_frame) {
|
|
return -ENOMEM;
|
|
}
|
|
data_snap_frame->d_size = argc + 1;
|
|
data_snap_frame->d_data = snap_frame;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_SET_SNAP_FRAME);
|
|
NLA_PUT_DATA(msg, BESPHY_TM_MSG_DATA, data_snap_frame);
|
|
|
|
free(snap_frame);
|
|
snap_frame = NULL;
|
|
free(data_snap_frame);
|
|
data_snap_frame = NULL;
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
static int do_get_tx_power_level_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
if (argc != 2) {
|
|
goto invalid_para;
|
|
}
|
|
static int id_type = BES_MSG_GET_TX_POWER_LEVEL;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_GET_TX_POWER_LEVEL);
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_DATA, 0);
|
|
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_recvmsgs, &id_type);
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
static int do_get_tx_power_range_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
if (argc != 2) {
|
|
goto invalid_para;
|
|
}
|
|
static int id_type = BES_MSG_GET_TX_POWER_RANGE;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_GET_TX_POWER_RANGE);
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_DATA, 0);
|
|
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_recvmsgs, &id_type);
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
static int do_set_advance_scan_elems_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
if (argc != 4) {
|
|
goto invalid_para;
|
|
}
|
|
|
|
int duration_tmp, len_tmp;
|
|
struct advance_scan_elems scan_elems;
|
|
|
|
if (!msg_tsm_atoi(argv[2], &len_tmp) || !msg_tsm_atoi(argv[3], &duration_tmp))
|
|
goto invalid_para;
|
|
|
|
if (duration_tmp > U16_MAX || duration_tmp < 0) {
|
|
goto invalid_para;
|
|
}
|
|
if (len_tmp > U8_MAX || len_tmp < 0) {
|
|
goto invalid_para;
|
|
}
|
|
|
|
scan_elems.scanMode = (u8)len_tmp;
|
|
scan_elems.duration = (u16)duration_tmp;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_SET_ADVANCE_SCAN_ELEMS);
|
|
NLA_PUT_TYPE(msg, struct advance_scan_elems, BESPHY_TM_MSG_DATA, scan_elems);
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
static int do_set_tx_queue_params_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
if (argc != 5) {
|
|
goto invalid_para;
|
|
}
|
|
|
|
int user_priority_tmp;
|
|
int medium_time_tmp;
|
|
int expiry_time_tmp;
|
|
struct bes_msg_set_txqueue_params txqueue_params;
|
|
|
|
if (!msg_tsm_atoi(argv[2], &user_priority_tmp) ||
|
|
!msg_tsm_atoi(argv[3], &medium_time_tmp) ||
|
|
!msg_tsm_atoi(argv[4], &expiry_time_tmp))
|
|
goto invalid_para;
|
|
|
|
if (user_priority_tmp > U8_MAX || user_priority_tmp < 0)
|
|
goto invalid_para;
|
|
|
|
if (medium_time_tmp > U16_MAX || medium_time_tmp < 0)
|
|
goto invalid_para;
|
|
|
|
if (expiry_time_tmp > U16_MAX || expiry_time_tmp < 0)
|
|
goto invalid_para;
|
|
|
|
txqueue_params.user_priority = (u8)user_priority_tmp;
|
|
txqueue_params.medium_time = (u16)medium_time_tmp;
|
|
txqueue_params.expiry_time = (u16)expiry_time_tmp;
|
|
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_SET_TX_QUEUE_PARAMS);
|
|
NLA_PUT_TYPE(msg, struct bes_msg_set_txqueue_params, BESPHY_TM_MSG_DATA, txqueue_params);
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
static int do_start_stop_tsm_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
if (argc != 5) {
|
|
goto invalid_para;
|
|
}
|
|
|
|
struct bes_msg_start_stop_tsm_t start_stop_tsm;
|
|
int start_tmp;
|
|
int up_tmp;
|
|
int packetization_delay_tmp;
|
|
|
|
if (!msg_tsm_atoi(argv[2], &start_tmp) ||
|
|
!msg_tsm_atoi(argv[3], &up_tmp) ||
|
|
!msg_tsm_atoi(argv[4], &packetization_delay_tmp))
|
|
goto invalid_para;
|
|
|
|
if (start_tmp > U8_MAX || start_tmp < 0)
|
|
goto invalid_para;
|
|
|
|
if (up_tmp > U8_MAX || up_tmp < 0)
|
|
goto invalid_para;
|
|
|
|
if (packetization_delay_tmp > U16_MAX || packetization_delay_tmp < 0)
|
|
goto invalid_para;
|
|
|
|
start_stop_tsm.start = (u8)start_tmp;
|
|
start_stop_tsm.up = (u8)up_tmp;
|
|
start_stop_tsm.packetization_delay = (u16)packetization_delay_tmp;
|
|
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_START_STOP_TSM);
|
|
NLA_PUT_TYPE(msg, struct bes_msg_start_stop_tsm_t, BESPHY_TM_MSG_DATA, start_stop_tsm);
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
static int do_get_tsm_params_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
if (argc != 2) {
|
|
goto invalid_para;
|
|
}
|
|
static int id_type = BES_MSG_GET_TSM_PARAMS;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_GET_TSM_PARAMS);
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_DATA, 0);
|
|
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_recvmsgs, &id_type);
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
static int do_get_roam_delay_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
if (argc != 2) {
|
|
goto invalid_para;
|
|
}
|
|
static int id_type = BES_MSG_GET_ROAM_DELAY;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_GET_ROAM_DELAY);
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_DATA, 0);
|
|
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_recvmsgs, &id_type);
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
static int do_set_power_save_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
if (argc != 3) {
|
|
goto invalid_para;
|
|
}
|
|
|
|
int powerSave_tmp;
|
|
struct power_save_elems power_elems;
|
|
|
|
if (!msg_tsm_atoi(argv[2], &powerSave_tmp))
|
|
goto invalid_para;
|
|
|
|
power_elems.powerSave = powerSave_tmp;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_SET_POWER_SAVE);
|
|
NLA_PUT_TYPE(msg, struct power_save_elems, BESPHY_TM_MSG_DATA, power_elems);
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
static int do_add_ip_offload_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc, char **argv)
|
|
{
|
|
if (argc != 5) {
|
|
goto invalid_para;
|
|
}
|
|
|
|
u8 proto_temp;
|
|
int dest_port_temp;
|
|
int payload_len_temp;
|
|
int data_len;
|
|
static int id_type = BES_MSG_ADD_IP_OFFLOAD;
|
|
|
|
if (!strcmp(argv[2], "udp"))
|
|
proto_temp = 0;
|
|
else if (!strcmp(argv[2], "tcp"))
|
|
proto_temp = 1;
|
|
else
|
|
goto invalid_para;
|
|
|
|
if (!msg_tsm_atoi(argv[3], &dest_port_temp))
|
|
goto invalid_para;
|
|
|
|
if (dest_port_temp > U16_MAX || dest_port_temp < 0)
|
|
goto invalid_para;
|
|
|
|
payload_len_temp = strlen(argv[4]);
|
|
if (payload_len_temp > U16_MAX || payload_len_temp < 0)
|
|
goto invalid_para;
|
|
|
|
data_len = 3 * sizeof(uint16_t) + payload_len_temp + 1;
|
|
struct add_ip_offload_t *add_ip_offload = (struct add_ip_offload_t *) malloc(data_len);
|
|
|
|
if (!add_ip_offload) {
|
|
return -ENOMEM;
|
|
}
|
|
add_ip_offload->proto = proto_temp;
|
|
add_ip_offload->dest_port = (u16)dest_port_temp;
|
|
add_ip_offload->payload_len = (u16)payload_len_temp;
|
|
memcpy(add_ip_offload->payload, argv[4], payload_len_temp + 1);
|
|
|
|
struct nl_data *data_add_ip_offload = (struct nl_data *) malloc(sizeof(struct nl_data));
|
|
if (!data_add_ip_offload) {
|
|
return -ENOMEM;
|
|
}
|
|
data_add_ip_offload->d_size = data_len;
|
|
data_add_ip_offload->d_data = add_ip_offload;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_ADD_IP_OFFLOAD);
|
|
NLA_PUT_DATA(msg, BESPHY_TM_MSG_DATA, data_add_ip_offload);
|
|
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_recvmsgs, &id_type);
|
|
|
|
free(add_ip_offload);
|
|
add_ip_offload = NULL;
|
|
free(data_add_ip_offload);
|
|
data_add_ip_offload = NULL;
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
static int do_del_ip_offload_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
if (argc != 3) {
|
|
goto invalid_para;
|
|
}
|
|
|
|
if (strncmp(argv[0],"wlan", 4)) {
|
|
printf("%s para error, input wlanname\n", argv[0]);
|
|
goto invalid_para;
|
|
}
|
|
|
|
int idx_tmp;
|
|
struct ip_alive_iac_idx iac_idx;
|
|
|
|
if (!msg_tsm_atoi(argv[2], &idx_tmp))
|
|
goto invalid_para;
|
|
|
|
iac_idx.idx = idx_tmp;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_DEL_IP_OFFLOAD);
|
|
NLA_PUT_TYPE(msg, struct ip_alive_iac_idx, BESPHY_TM_MSG_DATA, iac_idx);
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
static int do_set_ip_offload_period_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
if (argc != 3) {
|
|
goto invalid_para;
|
|
}
|
|
|
|
if (strncmp(argv[0],"wlan", 4)) {
|
|
printf("%s para error, input wlanname\n", argv[0]);
|
|
goto invalid_para;
|
|
}
|
|
|
|
int period_tmp;
|
|
struct ip_alive_period alive_period;
|
|
|
|
if (!msg_tsm_atoi(argv[2], &period_tmp))
|
|
goto invalid_para;
|
|
|
|
alive_period.period = period_tmp;
|
|
|
|
NLA_PUT_U32(msg, BESPHY_TM_MSG_ID, BES_MSG_SET_IP_OFFLOAD_PERIOD);
|
|
NLA_PUT_TYPE(msg, struct ip_alive_period, BESPHY_TM_MSG_DATA, alive_period);
|
|
|
|
return 0;
|
|
|
|
invalid_para:
|
|
return -EINVAL;
|
|
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* Print the currently executed test command.
|
|
* And fill command to genlmsg.
|
|
*/
|
|
static int do_besphy_test_cmd(struct nl_cb *cb, struct nl_msg *msg, const int argc,
|
|
char **argv)
|
|
{
|
|
int i, ret;
|
|
if (argv[1]) {
|
|
printf("do_%s: argc=%d, argv: %s ",argv[1], argc - 1, argv[1]);
|
|
} else {
|
|
goto para_input_error;
|
|
}
|
|
for (i = 2; i < argc; i++) {
|
|
if (argv[i]) {
|
|
printf("%s ",argv[i]);
|
|
} else {
|
|
printf("\n");
|
|
goto para_input_error;
|
|
}
|
|
}
|
|
printf("\n");
|
|
|
|
|
|
if (!strcmp(argv[1], "msg_test")) {
|
|
ret = do_msg_test_cmd(cb, msg, argc, argv);
|
|
|
|
} else if (!strcmp(argv[1], "set_snap_frame")) {
|
|
ret = do_set_snap_frame_cmd(cb, msg, argc, argv);
|
|
|
|
} else if (!strcmp(argv[1], "get_tx_power_level")) {
|
|
ret = do_get_tx_power_level_cmd(cb, msg, argc, argv);
|
|
|
|
} else if (!strcmp(argv[1], "get_tx_power_range")) {
|
|
ret = do_get_tx_power_range_cmd(cb, msg, argc, argv);
|
|
|
|
} else if (!strcmp(argv[1], "set_advance_scan_elems")) {
|
|
ret = do_set_advance_scan_elems_cmd(cb, msg, argc, argv);
|
|
|
|
} else if (!strcmp(argv[1], "set_tx_queue_params")) {
|
|
ret = do_set_tx_queue_params_cmd(cb, msg, argc, argv);
|
|
|
|
} else if (!strcmp(argv[1], "start_stop_tsm")) {
|
|
ret = do_start_stop_tsm_cmd(cb, msg, argc, argv);
|
|
|
|
} else if (!strcmp(argv[1], "get_tsm_params")) {
|
|
ret = do_get_tsm_params_cmd(cb, msg, argc, argv);
|
|
|
|
} else if (!strcmp(argv[1], "get_roam_delay")) {
|
|
ret = do_get_roam_delay_cmd(cb, msg, argc, argv);
|
|
|
|
} else if(!strcmp(argv[1], "set_power_save")) {
|
|
ret = do_set_power_save_cmd(cb, msg, argc, argv);
|
|
|
|
} else if(!strcmp(argv[1], "keep_alive_cfg")) {
|
|
ret = do_add_ip_offload_cmd(cb, msg, argc, argv);
|
|
|
|
} else if(!strcmp(argv[1], "del_keep_alive")) {
|
|
ret = do_del_ip_offload_cmd(cb, msg, argc, argv);
|
|
|
|
} else if(!strcmp(argv[1], "keep_alive_peroid")) {
|
|
ret = do_set_ip_offload_period_cmd(cb, msg, argc, argv);
|
|
|
|
} else {
|
|
/**
|
|
* always keep the vendor rf cmd at the end.
|
|
* including signaling and nosignaling
|
|
*/
|
|
ret = do_vendor_rf_cmd(cb, msg, argc, argv);
|
|
}
|
|
|
|
return ret;
|
|
|
|
para_input_error:
|
|
printf("The number of input param is not equal to argc.\n");
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
int do_commands(struct nl_cb *cb, struct nl_msg *msg, const int argc, char **argv)
|
|
{
|
|
int ret = 0;
|
|
if (argc <= 1) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = do_besphy_test_cmd(cb, msg, argc, argv);
|
|
|
|
return ret;
|
|
}
|
|
|