#include #include #include #include #include #include #include #include "../hgic_def.h" #include "utils.h" #include "fwctrl.h" struct fwctrl_cfgset { char *name; int (*set)(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count); }; struct fwctrl_cfgget { char *name; int (*get)(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin); }; static int hgic_copyfrom_iwreq(struct iwreq *wrqin, char *buf, int len) { int ret = 0; if (len > 0) { memset(buf, 0, len); len = (len <= wrqin->u.data.length ? len : wrqin->u.data.length); if (ACCESS_OK(VERIFY_READ, wrqin->u.data.pointer, wrqin->u.data.length)) { ret = copy_from_user(buf, wrqin->u.data.pointer, len); } else { memcpy(buf, wrqin->u.data.pointer, len); } } return ret; } static void hgic_copyto_iwreq(struct iwreq *wrqin, char *buf, int len) { if (ACCESS_OK(VERIFY_WRITE, wrqin->u.data.pointer, len)) { len = (len <= wrqin->u.data.length ? len : wrqin->u.data.length); if (len > 0 && !__copy_to_user(wrqin->u.data.pointer, buf, len)) { wrqin->u.data.length = (u16)len; } else { wrqin->u.data.length = 0; } } else { if (len > 0) { memcpy(wrqin->u.data.pointer, buf, len); wrqin->u.data.length = (u16)len; } else { wrqin->u.data.length = 0; } } } static int hgic_iwpriv_set_countryregion(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { if (data == NULL) { return -EINVAL; } return hgic_fwctrl_set_countryregion(ctrl, ifidx, data); } static int hgic_iwpriv_set_ssid(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_ssid(ctrl, ifidx, data); } static int hgic_iwpriv_set_bssid(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 bssid[6]; if (data == NULL || ifidx != HGIC_WDEV_ID_STA) { return -EINVAL; } hgic_pick_macaddr(data, bssid); return hgic_fwctrl_set_bssid(ctrl, ifidx, bssid); } static int hgic_iwpriv_set_channel(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { if (data == NULL) { return -EINVAL; } return hgic_fwctrl_set_channel(ctrl, ifidx, simple_strtol(data, 0, 10)); } static int hgic_iwpriv_set_bssid_filter(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_bssid_filter(ctrl, ifidx, data); } static int hgic_iwpriv_set_rts_threshold(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { if (data == NULL) { return -EINVAL; } return hgic_fwctrl_set_rts_threshold(ctrl, ifidx, simple_strtol(data, 0, 10)); } static int hgic_iwpriv_set_frag_threshold(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { if (data == NULL) { return -EINVAL; } return hgic_fwctrl_set_frag_threshold(ctrl, ifidx, simple_strtol(data, 0, 10)); } static int hgic_iwpriv_set_key_mgmt(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_key_mgmt(ctrl, ifidx, data); } static int hgic_iwpriv_set_wpa_psk(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_wpa_psk(ctrl, ifidx, data); } static int hgic_iwpriv_set_freq_range(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 vals[3] = {0, 0, 0}; u32 argcnt = 0; if (data == NULL || strlen(data) == 0) { return -EINVAL; } hgic_pick_values(u32, data, vals, 3); return hgic_fwctrl_set_freq_range(ctrl, ifidx, vals[0], vals[1], vals[2]); } static int hgic_iwpriv_set_bss_bw(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 bss_bw = (u8)simple_strtol(data, 0, 10); return hgic_fwctrl_set_bss_bw(ctrl, ifidx, bss_bw); } static int hgic_iwpriv_set_tx_bw(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 tx_bw = (u8)simple_strtol(data, 0, 10); return hgic_fwctrl_set_tx_bw(ctrl, ifidx, tx_bw); } static int hgic_iwpriv_set_tx_mcs(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 tx_mcs = (u8)simple_strtol(data, 0, 10); return hgic_fwctrl_set_tx_mcs(ctrl, ifidx, tx_mcs); } static int hgic_iwpriv_set_acs(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u16 vals[2] = {0, 0}; u32 argcnt = 0; if (data == NULL || strlen(data) == 0) { return -EINVAL; } hgic_pick_values(u16, data, vals, 2); return hgic_fwctrl_set_acs(ctrl, ifidx, vals[0], vals[1]); } static int hgic_iwpriv_set_bgrssi(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 rssi = (u8)simple_strtol(data, 0, 10); return hgic_fwctrl_set_bgrssi(ctrl, ifidx, rssi); } static int hgic_iwpriv_set_chan_list(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u16 vals[32] = {0}; u32 argcnt = 0; if (data == NULL || strlen(data) == 0) { return -EINVAL; } hgic_pick_values(u16, data, vals, 32); return hgic_fwctrl_set_chan_list(ctrl, ifidx, vals, argcnt); } static int hgic_iwpriv_set_mode(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { if (data == NULL) { return -EINVAL; } return hgic_fwctrl_set_mode(ctrl, ifidx, data); } static int hgic_iwpriv_set_paired_stas(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 *mac = NULL; int len = 0; int ret = 0, i = 0; char *ptr = data; char *p = data; if (data == NULL || strlen(data) == 0) { return -EINVAL; } len = strlen(data); mac = kzalloc(len, GFP_KERNEL); if (mac == NULL) { return -ENOMEM; } hgic_dbg("set paired stas: %s\r\n", data); while (p && *ptr) { p = strchr(ptr, ','); if(p) *p++ = 0; if (hgic_pick_macaddr(ptr, mac + i * 6)) { i++; } else { break; } ptr = p; } hgic_dbg("%d paired stas\r\n", i); ret = hgic_fwctrl_set_paired_stas(ctrl, ifidx, mac, i * 6); kfree(mac); return ret; } static int hgic_iwpriv_set_pairing(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 number = 0; if (data == NULL) { return -EINVAL; } number = simple_strtol(data, 0, 10); return hgic_fwctrl_set_pairing(ctrl, ifidx, number); } static int hgic_iwpriv_set_beacon_int(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 beacon_int = simple_strtol(data, 0, 10); return hgic_fwctrl_set_beacon_int(ctrl, ifidx, beacon_int); } static int hgic_iwpriv_set_radio_onoff(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { ctrl->radio_onoff = (u8)simple_strtol(data, 0, 10); return hgic_fwctrl_radio_onoff(ctrl, ifidx, ctrl->radio_onoff); } static int hgic_iwpriv_join_group(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 addr[6]; u32 aid = 0; if (data == NULL) { return -EINVAL; } hgic_pick_macaddr(data, addr); aid = simple_strtol(data + 18, 0, 10); return hgic_fwctrl_join_group(ctrl, ifidx, addr, aid); } static int hgic_iwpriv_set_ethertype(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u16 type = 0; if (data == NULL) { return -EINVAL; } type = simple_strtol(data, 0, 16); return hgic_fwctrl_set_ethertype(ctrl, ifidx, type); } static int hgic_iwpriv_set_txpower(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u16 type = 0; if (data == NULL) { return -EINVAL; } type = simple_strtol(data, 0, 10); return hgic_fwctrl_set_txpower(ctrl, ifidx, type); } static int hgic_iwpriv_set_aggcnt(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 agg[2]; //tx agg, rx agg u32 argcnt = 0; if (data == NULL) { return -EINVAL; } hgic_pick_values(u8, data, agg, 2); return hgic_fwctrl_set_agg_cnt(ctrl, ifidx, agg); } static int hgic_iwpriv_set_ps_connect(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 vals[2]; u32 argcnt = 0; if (data == NULL) { return -EINVAL; } hgic_pick_values(u8, data, vals, 2); return hgic_fwctrl_set_ps_connect(ctrl, ifidx, vals[0], vals[1]); } static int hgic_iwpriv_set_bss_max_idle(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 max_idle = 0; if (data == NULL) { return -EINVAL; } max_idle = simple_strtol(data, 0, 10); return hgic_fwctrl_set_bss_max_idle(ctrl, ifidx, max_idle); } static int hgic_iwpriv_set_dtim_period(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 period = 0; if (data == NULL) { return -EINVAL; } period = simple_strtol(data, 0, 10); return hgic_fwctrl_set_dtim_period(ctrl, ifidx, period); } static int hgic_iwpriv_set_wkio_mode(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 mode = 0; if (data == NULL) { return -EINVAL; } mode = simple_strtol(data, 0, 10); return hgic_fwctrl_set_wkio_mode(ctrl, ifidx, mode); } static int hgic_iwpriv_set_load_def(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 rst = 0; if (data == NULL) { return -EINVAL; } rst = simple_strtol(data, 0, 10); return hgic_fwctrl_set_load_def(ctrl, ifidx, rst); } static int hgic_iwpriv_set_disassoc_sta(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 addr[6]; if (data == NULL) { return -EINVAL; } hgic_pick_macaddr(data, addr); return hgic_fwctrl_disassoc_sta(ctrl, ifidx, addr); } static int hgic_iwpriv_set_ps_mode(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 mode = 0; if (data == NULL) { return -EINVAL; } mode = simple_strtol(data, 0, 10); return hgic_fwctrl_set_ps_mode(ctrl, ifidx, mode); } static int hgic_iwpriv_set_aplost_time(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 time = 0; if (data == NULL) { return -EINVAL; } time = simple_strtol(data, 0, 10); return hgic_fwctrl_set_aplost_time(ctrl, ifidx, time); } static int hgic_iwpriv_set_unpair(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 addr[6]; hgic_pick_macaddr(data, addr); return hgic_fwctrl_unpair(ctrl, ifidx, addr); } static int hgic_iwpriv_set_auto_chswitch(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 enable = 0; if (data == NULL) { return -EINVAL; } enable = simple_strtol(data, 0, 10); return hgic_fwctrl_set_auto_chswitch(ctrl, ifidx, enable == 1); } static int hgic_iwpriv_set_mcast_key(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { if (data == NULL) { return -EINVAL; } return hgic_fwctrl_set_mcast_key(ctrl, ifidx, data); } static int hgic_iwpriv_set_reassoc_wkhost(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 enable = 0; if (data == NULL) { return -EINVAL; } enable = simple_strtol(data, 0, 10); return hgic_fwctrl_set_reassoc_wkhost(ctrl, ifidx, enable == 1); } static int hgic_iwpriv_set_wakeup_io(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 vals[2] = {0, 0}; u32 argcnt = 0; hgic_pick_values(u8, data, vals, 2); return hgic_fwctrl_set_wakeup_io(ctrl, ifidx, vals[0], vals[1]); } static int hgic_iwpriv_set_dbginfo_output(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 enable = 0; if (data) { enable = simple_strtol(data, 0, 10); } return hgic_fwctrl_set_dbginfo_output(ctrl, ifidx, enable == 1); } static int hgic_iwpriv_set_sysdbg(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { if (data == NULL) { return -EINVAL; } return hgic_fwctrl_set_sysdbg(ctrl, ifidx, data); } static int hgic_iwpriv_set_primary_chan(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 chan = 0; if (data == NULL) { return -EINVAL; } chan = simple_strtol(data, 0, 10); return hgic_fwctrl_set_primary_chan(ctrl, ifidx, chan); } static int hgic_iwpriv_set_autosleep_time(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 time = 0; if (data == NULL) { return -EINVAL; } time = simple_strtol(data, 0, 10); return hgic_fwctrl_set_autosleep_time(ctrl, ifidx, time); } static int hgic_iwpriv_set_super_pwr(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 enable = 0; if (data == NULL) { return -EINVAL; } enable = simple_strtol(data, 0, 10); return hgic_fwctrl_set_super_pwr(ctrl, ifidx, enable); } static int hgic_iwpriv_set_repeater_ssid(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_repeater_ssid(ctrl, ifidx, data); } static int hgic_iwpriv_set_repeater_psk(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_repeater_psk(ctrl, ifidx, data); } static int hgic_iwpriv_set_auto_save(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 enable = 0; if (data == NULL) { return -EINVAL; } enable = simple_strtol(data, 0, 10); return hgic_fwctrl_set_auto_save(ctrl, ifidx, enable); } static int hgic_iwpriv_set_pair_autostop(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 enable = 0; if (data == NULL) { return -EINVAL; } enable = simple_strtol(data, 0, 10); return hgic_fwctrl_set_pair_autostop(ctrl, ifidx, enable); } static int hgic_iwpriv_set_dcdc13v(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 enable = 0; if (data == NULL) { return -EINVAL; } enable = simple_strtol(data, 0, 10); return hgic_fwctrl_set_dcdc13v(ctrl, ifidx, enable); } static int hgic_iwpriv_set_acktmo(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 tmo = 0; if (data == NULL) { return -EINVAL; } tmo = simple_strtol(data, 0, 10); return hgic_fwctrl_set_acktmo(ctrl, ifidx, tmo); } static int hgic_iwpriv_set_pa_pwrctl_dis(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 dis = 0; if (data == NULL) { return -EINVAL; } dis = simple_strtol(data, 0, 10); return hgic_fwctrl_set_pa_pwrctl_dis(ctrl, ifidx, dis); } static int hgic_iwpriv_set_dhcpc(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 en = 0; if (data == NULL) { return -EINVAL; } en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_dhcpc(ctrl, ifidx, en); } static int hgic_iwpriv_set_wkdata_save(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 en = 0; if (data == NULL) { return -EINVAL; } en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_wkdata_save(ctrl, ifidx, en); } static int hgic_iwpriv_set_mcast_txparam(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { struct hgic_mcast_txparam txparam; u8 *vals = (u8 *)&txparam; u32 argcnt = 0; if (data == NULL) { return -EINVAL; } hgic_pick_values(u8, data, vals, 4); return hgic_fwctrl_set_mcast_txparam(ctrl, ifidx, &txparam); } static int hgic_iwpriv_set_resetsta(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 addr[6]; if (data == NULL || ifidx != HGIC_WDEV_ID_STA) { return -EINVAL; } hgic_pick_macaddr(data, addr); return hgic_fwctrl_reset_sta(ctrl, ifidx, addr); } static int hgic_iwpriv_set_ant_auto(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 en = 0; if (data == NULL) { return -EINVAL; } en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_ant_auto(ctrl, ifidx, en); } static int hgic_iwpriv_set_select_ant(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 ant = 0; if (data == NULL) { return -EINVAL; } ant = simple_strtol(data, 0, 10); return hgic_fwctrl_select_ant(ctrl, ifidx, ant); } static int hgic_iwpriv_set_wkhost_reasons(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 argcnt = 0; u8 reasons[33]; if (data == NULL) { return -EINVAL; } memset(reasons, 0, sizeof(reasons)); hgic_pick_values(u8, data, reasons, 32); return hgic_fwctrl_set_wkhost_reasons(ctrl, ifidx, reasons, argcnt + 1); //keep last one is 0. } static int hgic_iwpriv_set_mac_filter(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 en = 0; if (data == NULL) { return -EINVAL; } en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_mac_filter(ctrl, ifidx, en); } static int hgic_iwpriv_set_atcmd(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_atcmd(ctrl, ifidx, data); } static int hgic_iwpriv_set_roaming(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { s8 vals[8]; u32 argcnt = 0; if (data == NULL) { return -EINVAL; } hgic_pick_values(s8, data, vals, sizeof(vals)); return hgic_fwctrl_set_roaming(ctrl, ifidx, vals, argcnt); } static int hgic_iwpriv_set_ap_hide(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 hide = 0; if (data == NULL) { return -EINVAL; } hide = simple_strtol(data, 0, 10); return hgic_fwctrl_set_ap_hide(ctrl, ifidx, hide); } static int hgic_iwpriv_set_max_txcnt(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 txcnt = 0; if (data == NULL) { return -EINVAL; } txcnt = simple_strtol(data, 0, 10); return hgic_fwctrl_set_frm_tx_maxcnt(ctrl, ifidx, txcnt); } static int hgic_iwpriv_set_assert_holdup(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 holdup = 0; if (data == NULL) { return -EINVAL; } holdup = simple_strtol(data, 0, 10); return hgic_fwctrl_set_assert_holdup(ctrl, ifidx, holdup); } static int hgic_iwpriv_set_ap_psmode(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 en = 0; if (data == NULL) { return -EINVAL; } en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_ap_psmode_en(ctrl, ifidx, en); } static int hgic_iwpriv_set_dupfilter_en(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 en = 0; if (data == NULL) { return -EINVAL; } en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_dupfilter_en(ctrl, ifidx, en); } static int hgic_iwpriv_set_dis_1v1m2u(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 en = 0; if (data == NULL) { return -EINVAL; } en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_1v1_m2u_dis(ctrl, ifidx, en); } static int hgic_iwpriv_set_dis_psconnect(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 en = 0; if (data == NULL) { return -EINVAL; } en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_psconnect_dis(ctrl, ifidx, en); } static int hgic_iwpriv_reset(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_reset(ctrl, ifidx); } static int hgic_iwpriv_set_heartbeat(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 ip[4] = {0}; u32 port = 0; u32 ipaddr = 0; u32 period = 0; u32 hb_tmo = 300; sscanf(data, "%d.%d.%d.%d,%d,%d,%d", &ip[0], &ip[1], &ip[2], &ip[3], &port, &period, &hb_tmo); ipaddr = ((ip[0] & 0xff) << 24) | ((ip[1] & 0xff) << 16) | (((ip[2] & 0xff) << 8)) | (ip[3] & 0xff); return hgic_fwctrl_set_ps_heartbeat(ctrl, ifidx, ipaddr, port, period, hb_tmo); } static int hgic_iwpriv_set_heartbeat_resp(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_ps_heartbeat_resp(ctrl, ifidx, data, count); } static int hgic_iwpriv_set_wakeup_data(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_ps_wakeup_data(ctrl, ifidx, data, count); } static int hgic_iwpriv_wakeup_sta(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 mac[6]; hgic_pick_macaddr(data, mac); hgic_err("wakeup sta: %pM\r\n", mac); return hgic_fwctrl_wakeup_sta(ctrl, ifidx, mac); } static int hgic_iwpriv_send_custmgmt(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_send_cust_mgmt(ctrl, ifidx, data, count); } static int hgic_iwpriv_send_mgmtframe(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_send_mgmtframe(ctrl, ifidx, data, count); } static int hgic_iwpriv_set_wkdata_mask(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 len = count > 128 ? 128 : count; return hgic_fwctrl_set_wkdata_mask(ctrl, ifidx, data[0], (u8 *)(data + 1), len - 1); } static int hgic_iwpriv_set_driverdata(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_cust_driver_data(ctrl, ifidx, data, count); } static int hgic_iwpriv_set_freqinfo(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_freqinfo(ctrl, ifidx, data, count); } static int hgic_iwpriv_set_blenc(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int ret = 0; u8 vals[2]; char *args; u32 argcnt = 0; if (memcmp(data, "EN:", 3) == 0) { args = data + 3; hgic_pick_values(u8, args, vals, 2); ret = hgic_fwctrl_set_blenc_en(ctrl, ifidx, vals); } else if (memcmp(data, "DATA:", 5) == 0) { ret = hgic_fwctrl_blenc_send_data(ctrl, ifidx, data + 5, count - 5); } else if (memcmp(data, "DEV_ADDR:", 9) == 0) { ret = hgic_fwctrl_blenc_set_devaddr(ctrl, ifidx, data + 9); } else if (memcmp(data, "ADV_DATA:", 9) == 0) { ret = hgic_fwctrl_blenc_set_advdata(ctrl, ifidx, data + 9, count - 9); } else if (memcmp(data, "SCAN_RESP:", 10) == 0) { ret = hgic_fwctrl_blenc_set_scanresp(ctrl, ifidx, data + 10, count - 10); } else if (memcmp(data, "ADV_INT:", 8) == 0) { ret = hgic_fwctrl_blenc_set_advinterval(ctrl, ifidx, simple_strtol(data + 8, 0, 10)); } else if (memcmp(data, "ADV_EN:", 7) == 0) { ret = hgic_fwctrl_blenc_start_adv(ctrl, ifidx, simple_strtol(data + 7, 0, 10)); } else if (memcmp(data, "HCI_DATA:", 9) == 0) { ret = hgic_fwctrl_send_hci_data(ctrl, data[9], data + 10, count - 10); } else if (memcmp(data, "ADV_FILTER:", 11) == 0) { ret = hgic_fwctrl_set_blenc_adv_filter(ctrl, ifidx, simple_strtol(data + 11, 0, 10)); } else { ret = -1; } return ret ? -EINVAL : 0; } static int hgic_iwpriv_enter_sleep(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int err = 0; u32 vals[2] = {1, 0xffffffff}; u32 argcnt = 0; if (data == NULL) { return -EINVAL; } hgic_pick_values(u32, data, vals, 2); if (vals[0]) { if (!test_bit(HGIC_BUS_FLAGS_SLEEP, &ctrl->bus->flags)) { if(ctrl->fwinfo->version < 0x02000000) vals[0] = 0xffff; hgic_dbg("enter sleep : type:%d, sleep_ms:%d ...\r\n", vals[0], vals[1]); err = hgic_fwctrl_enter_sleep(ctrl, ifidx, vals[0], vals[1]); if (err) { clear_bit(HGIC_BUS_FLAGS_SLEEP, &ctrl->bus->flags); hgic_err("sleep fail, ret=%d\r\n", err); } } } else { hgic_dbg("exit sleep, SLEEP=%d\r\n", test_bit(HGIC_BUS_FLAGS_SLEEP, &ctrl->bus->flags)); if (test_bit(HGIC_BUS_FLAGS_SLEEP, &ctrl->bus->flags)) { clear_bit(HGIC_BUS_FLAGS_SLEEP, &ctrl->bus->flags); if (ctrl->bus->reinit) { ctrl->bus->reinit(ctrl->bus); } err = hgic_fwctrl_enter_sleep(ctrl, ifidx, 0, 0); if (err) { hgic_err("exit sleep fail, ret=%d\r\n", err); } } } return err ? -EINVAL : 0; } static int hgic_iwpriv_set_hwscan(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 argcnt = 0; u16 vals[4]; hgic_pick_values(u16, data, vals, 4); return hgic_fwctrl_set_hwscan(ctrl, ifidx, vals[0], vals[1], vals[2], vals[3]); } static int hgic_iwpriv_set_user_edca(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 ac = data[0]; struct hgic_txq_param txq; memcpy(&txq, data + 1, sizeof(txq)); return hgic_fwctrl_set_user_edca(ctrl, ifidx, ac, &txq); } static int hgic_iwpriv_set_fix_txrate(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 txrate = simple_strtoul(data, 0, 10); return hgic_fwctrl_set_fix_txrate(ctrl, ifidx, txrate); } static int hgic_iwpriv_set_nav_max(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 nav = simple_strtoul(data, 0, 10); return hgic_fwctrl_set_nav_max(ctrl, ifidx, nav); } static int hgic_iwpriv_clear_nav(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_clear_nav(ctrl, ifidx); } static int hgic_iwpriv_set_cca_param(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_cca_param(ctrl, ifidx, (struct hgic_cca_ctl *)data); } static int hgic_iwpriv_set_tx_modulation_gain(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_tx_modulation_gain(ctrl, ifidx, data, count); } static int hgic_iwpriv_set_rts_duration(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int duration = simple_strtol(data, 0, 10); return hgic_fwctrl_set_rts_duration(ctrl, ifidx, duration); } static int hgic_iwpriv_set_disable_print(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int dis = simple_strtol(data, 0, 10); return hgic_fwctrl_set_disable_print(ctrl, ifidx, dis); } static int hgic_iwpriv_set_conn_paironly(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int dis = simple_strtol(data, 0, 10); return hgic_fwctrl_set_conn_paironly(ctrl, ifidx, dis); } static int hgic_iwpriv_set_wait_psmode(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int mode = simple_strtol(data, 0, 10); return hgic_fwctrl_set_wait_psmode(ctrl, ifidx, mode); } static int hgic_iwpriv_set_diffcust_conn(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_diffcust_conn(ctrl, ifidx, en); } static int hgic_iwpriv_set_standby(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 argcnt = 0; u32 vals[2]; if (data == NULL) { return -EINVAL; } hgic_pick_values(u32, data, vals, 2); return hgic_fwctrl_set_standby(ctrl, ifidx, (u8)vals[0], vals[1]); } static int hgic_iwpriv_set_ap_chan_switch(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u8 argcnt = 0; u8 vals[2]; if (data == NULL) { return -EINVAL; } hgic_pick_values(u8, data, vals, 2); return hgic_fwctrl_set_ap_chan_switch(ctrl, ifidx, vals[0], vals[1]); } static int hgic_iwpriv_set_cca_for_ce(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_cca_for_ce(ctrl, ifidx, en); } static int hgic_iwpriv_set_rtc(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 rtc = simple_strtol(data, 0, 10); return hgic_fwctrl_set_rtc(ctrl, ifidx, rtc); } static int hgic_iwpriv_set_apep_padding(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_apep_padding(ctrl, ifidx, en); } static int hgic_iwpriv_set_watchdog(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { u32 en = simple_strtol(data, 0, 10); return hgic_fwctrl_set_watchdog(ctrl, ifidx, en); } static int hgic_iwpriv_set_retry_fallback_cnt(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int cnt = simple_strtol(data, 0, 10); return hgic_fwctrl_set_retry_fallback_cnt(ctrl, ifidx, cnt); } static int hgic_iwpriv_set_fallback_mcs(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { struct hgic_fallback_mcs mcs; u8 argcnt = 0; u8 vals[4]; hgic_pick_values(u8, data, vals, 4); mcs.original_type = vals[0]; mcs.original_mcs = vals[1]; mcs.fallback_type = vals[2]; mcs.fallback_mcs = vals[3]; return hgic_fwctrl_set_fallback_mcs(ctrl, ifidx, &mcs); } static int hgic_iwpriv_set_xosc(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int val = simple_strtol(data, 0, 10); return hgic_fwctrl_set_xosc(ctrl, ifidx, val); } static int hgic_iwpriv_set_freq_cali_period(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int val = simple_strtol(data, 0, 10); return hgic_fwctrl_set_freq_cali_period(ctrl, ifidx, val); } static int hgic_iwpriv_set_customer_dvrdata(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { return hgic_fwctrl_set_bytes(ctrl, ifidx, get_unaligned_le16(data), data + 2, count - 2); } static int hgic_iwpriv_set_max_tx_delay(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int val = simple_strtol(data, 0, 10); return hgic_fwctrl_set_max_tx_delay(ctrl, ifidx, val); } static int hgic_iwpriv_set_heartbeat_int(struct hgic_fwctrl *ctrl, u8 ifidx, char *data, u32 count) { int val = simple_strtol(data, 0, 10); return hgic_fwctrl_set_heartbeat_int(ctrl, ifidx, val); } static struct fwctrl_cfgset hgpriv_sets[] = { {"country_region", hgic_iwpriv_set_countryregion}, {"ssid", hgic_iwpriv_set_ssid}, {"bssid", hgic_iwpriv_set_bssid}, {"channel", hgic_iwpriv_set_channel}, {"rts_threshold", hgic_iwpriv_set_rts_threshold}, {"frag_threshold", hgic_iwpriv_set_frag_threshold}, {"key_mgmt", hgic_iwpriv_set_key_mgmt}, {"wpa_psk", hgic_iwpriv_set_wpa_psk}, {"bssid_filter", hgic_iwpriv_set_bssid_filter}, {"freq_range", hgic_iwpriv_set_freq_range}, {"bss_bw", hgic_iwpriv_set_bss_bw}, {"tx_bw", hgic_iwpriv_set_tx_bw}, {"tx_mcs", hgic_iwpriv_set_tx_mcs}, {"acs", hgic_iwpriv_set_acs}, {"bgrssi", hgic_iwpriv_set_bgrssi}, {"chan_list", hgic_iwpriv_set_chan_list}, {"mode", hgic_iwpriv_set_mode}, {"paired_stas", hgic_iwpriv_set_paired_stas}, {"pairing", hgic_iwpriv_set_pairing}, {"beacon_int", hgic_iwpriv_set_beacon_int}, {"radio_onoff", hgic_iwpriv_set_radio_onoff}, {"join_group", hgic_iwpriv_join_group}, {"ether_type", hgic_iwpriv_set_ethertype}, {"txpower", hgic_iwpriv_set_txpower}, {"agg_cnt", hgic_iwpriv_set_aggcnt}, {"ps_connect", hgic_iwpriv_set_ps_connect}, {"bss_max_idle", hgic_iwpriv_set_bss_max_idle}, {"wkio_mode", hgic_iwpriv_set_wkio_mode}, {"loaddef", hgic_iwpriv_set_load_def}, {"disassoc_sta", hgic_iwpriv_set_disassoc_sta}, {"dtim_period", hgic_iwpriv_set_dtim_period}, {"ps_mode", hgic_iwpriv_set_ps_mode}, {"aplost_time", hgic_iwpriv_set_aplost_time}, {"unpair", hgic_iwpriv_set_unpair}, {"auto_chswitch", hgic_iwpriv_set_auto_chswitch}, {"mcast_key", hgic_iwpriv_set_mcast_key}, {"reassoc_wkhost", hgic_iwpriv_set_reassoc_wkhost}, {"wakeup_io", hgic_iwpriv_set_wakeup_io}, {"dbginfo", hgic_iwpriv_set_dbginfo_output}, {"sysdbg", hgic_iwpriv_set_sysdbg}, {"primary_chan", hgic_iwpriv_set_primary_chan}, {"autosleep_time", hgic_iwpriv_set_autosleep_time}, {"super_pwr", hgic_iwpriv_set_super_pwr}, {"r_ssid", hgic_iwpriv_set_repeater_ssid}, {"r_psk", hgic_iwpriv_set_repeater_psk}, {"auto_save", hgic_iwpriv_set_auto_save}, {"pair_autostop", hgic_iwpriv_set_pair_autostop}, {"dcdc13", hgic_iwpriv_set_dcdc13v}, {"acktmo", hgic_iwpriv_set_acktmo}, {"pa_pwrctl_dis", hgic_iwpriv_set_pa_pwrctl_dis}, {"dhcpc", hgic_iwpriv_set_dhcpc}, {"wkdata_save", hgic_iwpriv_set_wkdata_save}, {"mcast_txparam", hgic_iwpriv_set_mcast_txparam}, {"reset_sta", hgic_iwpriv_set_resetsta}, {"ant_auto", hgic_iwpriv_set_ant_auto}, {"ant_sel", hgic_iwpriv_set_select_ant}, {"wkhost_reason", hgic_iwpriv_set_wkhost_reasons}, {"macfilter", hgic_iwpriv_set_mac_filter}, {"atcmd", hgic_iwpriv_set_atcmd}, {"roaming", hgic_iwpriv_set_roaming}, {"ap_hide", hgic_iwpriv_set_ap_hide}, {"max_txcnt", hgic_iwpriv_set_max_txcnt}, {"assert_holdup", hgic_iwpriv_set_assert_holdup}, {"ap_psmode", hgic_iwpriv_set_ap_psmode}, {"dupfilter", hgic_iwpriv_set_dupfilter_en}, {"dis_1v1m2u", hgic_iwpriv_set_dis_1v1m2u}, {"dis_psconnect", hgic_iwpriv_set_dis_psconnect}, {"reset", hgic_iwpriv_reset}, {"heartbeat", hgic_iwpriv_set_heartbeat}, {"heartbeat_resp", hgic_iwpriv_set_heartbeat_resp}, {"wakeup_data", hgic_iwpriv_set_wakeup_data}, {"wakeup", hgic_iwpriv_wakeup_sta}, {"custmgmt", hgic_iwpriv_send_custmgmt}, {"mgmtframe", hgic_iwpriv_send_mgmtframe}, {"wkdata_mask", hgic_iwpriv_set_wkdata_mask}, {"driverdata", hgic_iwpriv_set_driverdata}, {"freqinfo", hgic_iwpriv_set_freqinfo}, {"blenc", hgic_iwpriv_set_blenc}, {"sleep", hgic_iwpriv_enter_sleep}, {"hwscan", hgic_iwpriv_set_hwscan}, {"user_edca", hgic_iwpriv_set_user_edca}, {"fix_txrate", hgic_iwpriv_set_fix_txrate}, {"nav_max", hgic_iwpriv_set_nav_max}, {"clr_nav", hgic_iwpriv_clear_nav}, {"cca_param", hgic_iwpriv_set_cca_param}, {"tx_modgain", hgic_iwpriv_set_tx_modulation_gain}, {"rts_duration", hgic_iwpriv_set_rts_duration}, {"disable_print", hgic_iwpriv_set_disable_print}, {"conn_paironly", hgic_iwpriv_set_conn_paironly}, {"diffcust_conn", hgic_iwpriv_set_diffcust_conn}, {"wait_psmode", hgic_iwpriv_set_wait_psmode}, {"standby", hgic_iwpriv_set_standby}, {"ap_chansw", hgic_iwpriv_set_ap_chan_switch}, {"cca_ce", hgic_iwpriv_set_cca_for_ce}, {"rtc", hgic_iwpriv_set_rtc}, {"apep_padding", hgic_iwpriv_set_apep_padding}, {"watchdog", hgic_iwpriv_set_watchdog}, {"retry_fallback_cnt", hgic_iwpriv_set_retry_fallback_cnt}, {"fallback_mcs", hgic_iwpriv_set_fallback_mcs}, {"xosc", hgic_iwpriv_set_xosc}, {"freq_cali_period", hgic_iwpriv_set_freq_cali_period}, {"cust_drvdata", hgic_iwpriv_set_customer_dvrdata}, {"max_txdelay", hgic_iwpriv_set_max_tx_delay}, {"heartbeat_int", hgic_iwpriv_set_heartbeat_int}, {NULL,} }; int hgic_iwpriv_set_proc(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int ret = -ENOTSUPP; char *ptr; struct fwctrl_cfgset *set = NULL; char *buff = kmalloc(wrqin->u.data.length + 1, GFP_KERNEL); if (buff == NULL) { hgic_err("kmalloc fail\r\n"); return -ENOMEM; } if (hgic_copyfrom_iwreq(wrqin, buff, wrqin->u.data.length + 1) == 0) { ptr = strchr(buff, '='); if (ptr) { *ptr++ = 0; for (set = hgpriv_sets; set->name; set++) { if (strcmp(buff, set->name) == 0) { ret = set->set(ctrl, ifidx, ptr, wrqin->u.data.length - (ptr - buff)); break; } } } else { hgic_err("invalid set cmd [%s]\r\n", buff); } } else { hgic_err("copy_from_user fail\r\n"); } kfree(buff); return ret; } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// static int hgic_iwpriv_get_scan_list(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int ret = 0; int i = 0; int count = 0; int len = 0; struct hgic_bss_info *bss = NULL; char *buf = kzalloc(1024, GFP_ATOMIC); char *print_buf = kzalloc(4096, GFP_ATOMIC); if (buf == NULL || print_buf == NULL) { if (buf) { kfree(buf); } if (print_buf) { kfree(print_buf); } return -ENOMEM; } ret = hgic_fwctrl_get_scan_list(ctrl, ifidx, buf, 1024); if (ret > 0) { bss = (struct hgic_bss_info *)buf; count = ret / sizeof(struct hgic_bss_info); len += sprintf(print_buf + len, "\r\nBSSID \tSSID \tEncryption\tFrequence\tSignal\n"); for (i = 0; i < count; i++) { len += sprintf(print_buf + len, "%pM\t%s\t%10s\t%10d\t%d\n", bss[i].bssid, bss[i].ssid, bss[i].encrypt ? (bss[i].encrypt == 1 ? "WPA" : "WPA2") : "NONE", bss[i].freq, bss[i].signal); } wrqin->u.data.length = (u16)len; } else { len = 2; } hgic_copyto_iwreq(wrqin, print_buf, len); kfree(buf); kfree(print_buf); return (0); } static int hgic_iwpriv_get_sta_list(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int count = 0; int len = 0; int format = 0; char *ptr; char *buf = kzalloc(2048, GFP_ATOMIC); char *print_buf = kzalloc(4096, GFP_ATOMIC); struct hgic_sta_info *sta = (struct hgic_sta_info *)buf; if (buf == NULL || print_buf == NULL) { if (buf) { kfree(buf); } if (print_buf) { kfree(print_buf); } return -ENOMEM; } hgic_copyfrom_iwreq(wrqin, buf, 8); ptr = strchr(buf, '='); if (ptr) { format = simple_strtol(ptr + 1, 0, 10); } count = hgic_fwctrl_get_sta_list(ctrl, ifidx, (struct hgic_sta_info *)buf, (2048 / sizeof(struct hgic_sta_info))); if (format == 1) { hgic_copyto_iwreq(wrqin, buf, count * sizeof(struct hgic_sta_info)); } else { if (count > 0) { len += sprintf(print_buf, "%d sta:\r\n", count); while (count-- > 0) { len += sprintf(print_buf + len, "aid:%d, %pM, ps:%d, rssi:%d, evm:%d, tx_snr:%d, rx_snr:%d\r\n", sta->aid, sta->addr, sta->ps, (s8)sta->rssi, (s8)sta->evm, (s8)sta->tx_snr, (s8)sta->rx_snr); sta++; } } hgic_copyto_iwreq(wrqin, print_buf, len); } kfree(buf); kfree(print_buf); return (0); } static int hgic_iwpriv_get_mode(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int len = 0; char mode[13]; len = hgic_fwctrl_get_mode(ctrl, ifidx, mode, 12); hgic_copyto_iwreq(wrqin, mode, len); return (0); } static int hgic_iwpriv_get_ssid(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int len = 0; char ssid[33]; len = hgic_fwctrl_get_ssid(ctrl, ifidx, ssid, 32); hgic_copyto_iwreq(wrqin, ssid, len); return (0); } static int hgic_iwpriv_get_bssid(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char buf[24]; char bssid[7]; memset(buf, 0, sizeof(buf)); memset(bssid, 0, sizeof(bssid)); if (hgic_fwctrl_get_bssid(ctrl, ifidx, bssid, 7) > 0) { sprintf(buf, "%pM,%d", bssid, bssid[6]); } hgic_copyto_iwreq(wrqin, buf, strlen(buf)); return (0); } static int hgic_iwpriv_get_wpa_psk(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int len = 0; char *buf = kzalloc(80, GFP_ATOMIC); if (buf == NULL) { return -ENOMEM; } len = hgic_fwctrl_get_wpapsk(ctrl, ifidx, buf, 64); hgic_copyto_iwreq(wrqin, buf, len); kfree(buf); return (0); } static int hgic_iwpriv_get_txpower(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[4]; int txpower = 0; txpower = hgic_fwctrl_get_txpower(ctrl, ifidx); sprintf(str, "%d", txpower); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_bss_bw(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[4]; int bss_bw = 0; bss_bw = hgic_fwctrl_get_bss_bw(ctrl, ifidx); sprintf(str, "%d", bss_bw); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_aggcnt(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[32]; int ret = 0; u8 agg[2]; memset(agg, 0, sizeof(agg)); ret = hgic_fwctrl_get_agg_cnt(ctrl, ifidx, agg, 2); if (ret == 0xff) { sprintf(str, "tx:%d,rx:%d", agg[0], agg[1]); } else { sprintf(str, "tx:%d,rx:0", ret); } hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_chan_list(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int cnt = 0, i = 0; int len = 0; u16 chan_list[16]; char *buf = kzalloc(128, GFP_KERNEL); if (buf) { cnt = hgic_fwctrl_get_chan_list(ctrl, ifidx, chan_list, 16); for (i = 0; i < cnt; i++) { len += sprintf(buf + len, "%d,", chan_list[i]); } hgic_copyto_iwreq(wrqin, buf, len - 1); kfree(buf); } return (0); } static int hgic_iwpriv_get_freq_range(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[32] = {0}; int ret; u32 vals[3]; ret = hgic_fwctrl_get_freq_range(ctrl, ifidx, &vals[0], &vals[1], &vals[2]); if (ret) { sprintf(str, "%d,%d,%d", vals[0], vals[1], vals[2]); } hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_key_mgmt(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int len = 0; char str[32]; len = hgic_fwctrl_get_key_mgmt(ctrl, ifidx, str, 32); hgic_copyto_iwreq(wrqin, str, len); return (0); } static int hgic_iwpriv_get_battery_level(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[4]; int val = 0; val = hgic_fwctrl_get_battery_level(ctrl, ifidx); sprintf(str, "%d", val); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_module_type(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { u16 type = 0; char str[12]; type = (u16)hgic_fwctrl_get_module_type(ctrl, ifidx); if (type) { sprintf(str, "%d", type); hgic_copyto_iwreq(wrqin, str, strlen(str)); } return (0); } static int hgic_iwpriv_get_disassoc_reason(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int reason = 0; reason = hgic_fwctrl_get_disassoc_reason(ctrl, ifidx); sprintf(str, "%d", reason); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_ant_sel(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int ant = 0; ant = hgic_fwctrl_get_ant_sel(ctrl, ifidx); sprintf(str, "%d", ant); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_wkreason(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int reason = 0; reason = hgic_fwctrl_get_wkreason(ctrl, ifidx); sprintf(str, "%d", reason); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_wkdata_buff(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int ret; char *buff = kmalloc(4096, GFP_KERNEL); if (buff) { ret = hgic_fwctrl_get_wkdata_buff(ctrl, ifidx, buff, 4096); hgic_copyto_iwreq(wrqin, buff, ret); kfree(buff); } return (0); } static int hgic_iwpriv_get_temperature(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int temp = hgic_fwctrl_get_temperature(ctrl); sprintf(str, "%d", temp); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_conn_state(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int temp = hgic_fwctrl_get_conn_state(ctrl, ifidx); sprintf(str, "%d", temp); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_sta_count(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int temp = hgic_fwctrl_get_sta_count(ctrl, ifidx); sprintf(str, "%d", temp); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_txq_param(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int ret = -1; struct hgic_txq_param param[4]; ret = hgic_fwctrl_get_txq_param(ctrl, ifidx, param); if (ret == sizeof(param)) { //printk("txq0: %d,%d,%d,%d\r\n", param[0].aifs, param[0].cw_min, param[0].cw_max, param[0].txop); //printk("txq1: %d,%d,%d,%d\r\n", param[1].aifs, param[1].cw_min, param[1].cw_max, param[1].txop); //printk("txq2: %d,%d,%d,%d\r\n", param[2].aifs, param[2].cw_min, param[2].cw_max, param[2].txop); //printk("txq3: %d,%d,%d,%d\r\n", param[3].aifs, param[3].cw_min, param[3].cw_max, param[3].txop); hgic_copyto_iwreq(wrqin, (char *)param, sizeof(param)); } return (ret == sizeof(param)) ? 0 : ret; } static int hgic_iwpriv_get_nav(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int temp = hgic_fwctrl_get_nav(ctrl, ifidx); sprintf(str, "%d", temp); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_rtc(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; u32 rtc = 0; hgic_fwctrl_get_rtc(ctrl, ifidx, (u8 *)&rtc); sprintf(str, "%u", rtc); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_bgrssi(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int ret; char buff[64]; char *ptr; s8 resp[3] = { 0, 0, 0}; ret = hgic_copyfrom_iwreq(wrqin, buff, 64); ptr = strchr(buff, '='); if(ptr == NULL || ret) return -EINVAL; ret = simple_strtoul(ptr + 1, 0, 10); ret = hgic_fwctrl_get_bgrssi(ctrl, ifidx, ret, resp); if (ret == 3) { sprintf(buff, "%d,%d,%d", resp[0], resp[1], resp[2]); hgic_copyto_iwreq(wrqin, buff, strlen(buff)); } return (0); } static int hgic_iwpriv_get_center_freq(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int temp = hgic_fwctrl_get_center_freq(ctrl, ifidx); sprintf(str, "%d", temp); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_acs_result(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int cnt = 0; struct hgic_acs_result *result = kzalloc(32 * sizeof(struct hgic_acs_result), GFP_KERNEL); if (result) { cnt = hgic_fwctrl_get_acs_result(ctrl, ifidx, result, 32); hgic_copyto_iwreq(wrqin, (char *)result, cnt); kfree(result); } return (0); } static int hgic_iwpriv_get_reason_code(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int temp = hgic_fwctrl_get_reason_code(ctrl, ifidx); sprintf(str, "%d", temp); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_status_code(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int temp = hgic_fwctrl_get_status_code(ctrl, ifidx); sprintf(str, "%d", temp); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_dhcpc_result(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { u32 result[6]; int ret = hgic_fwctrl_get_dhcpc_result(ctrl, ifidx, (u8 *)result, sizeof(result)); if (ret == 24) { hgic_copyto_iwreq(wrqin, (char *)result, sizeof(result)); return (0); } return ret; } static int hgic_iwpriv_get_xosc(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int temp = hgic_fwctrl_get_xosc(ctrl, ifidx); sprintf(str, "%d", temp); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static int hgic_iwpriv_get_freq_offset(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int ret; char buff[64]; char *ptr; char addr[6]; ret = hgic_copyfrom_iwreq(wrqin, buff, 64); ptr = strchr(buff, '='); if (ptr == NULL || ret) { return -EINVAL; } hgic_pick_macaddr(ptr + 1, addr); ret = hgic_fwctrl_get_freq_offset(ctrl, ifidx, addr); sprintf(buff, "%d", ret); hgic_copyto_iwreq(wrqin, buff, strlen(buff)); return (0); } static int hgic_iwpriv_get_fwinfo(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { hgic_copyto_iwreq(wrqin, (char *)ctrl->fwinfo, sizeof(struct hgic_fw_info)); return (0); } static int hgic_iwpriv_get_sta_info(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { int ret; char *ptr; char buff[64]; char addr[6]; char format = 0; struct hgic_sta_info stainfo; char *print_buf = kzalloc(512, GFP_ATOMIC); if (print_buf == NULL) { return -ENOMEM; } ret = hgic_copyfrom_iwreq(wrqin, buff, 64); ptr = strchr(buff, '='); if (ptr == NULL || ret) { kfree(print_buf); return -EINVAL; } hgic_pick_macaddr(ptr + 1, addr); ptr = strchr(ptr, ','); if (ptr) { format = simple_strtol(ptr + 1, 0, 10); } ret = hgic_fwctrl_get_sta_info(ctrl, ifidx, addr, &stainfo); if (format == 1) { hgic_copyto_iwreq(wrqin, (char *)&stainfo, ret); } else { if (ret > 0) { ret = sprintf(print_buf, "aid:%d, %pM, ps:%d, rssi:%d, evm:%d, tx_snr:%d, rx_snr:%d\r\n", stainfo.aid, stainfo.addr, stainfo.ps, (s8)stainfo.rssi, (s8)stainfo.evm, (s8)stainfo.tx_snr, (s8)stainfo.rx_snr); } hgic_copyto_iwreq(wrqin, print_buf, ret); } kfree(print_buf); return (0); } static int hgic_iwpriv_get_signal(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { char str[12]; int signal = hgic_fwctrl_get_signal(ctrl, ifidx); sprintf(str, "%d", signal); hgic_copyto_iwreq(wrqin, str, strlen(str)); return (0); } static struct fwctrl_cfgget hgpriv_gets[] = { {"mode", hgic_iwpriv_get_mode}, {"sta_list", hgic_iwpriv_get_sta_list}, {"scan_list", hgic_iwpriv_get_scan_list}, {"ssid", hgic_iwpriv_get_ssid}, {"bssid", hgic_iwpriv_get_bssid}, {"wpa_psk", hgic_iwpriv_get_wpa_psk}, {"txpower", hgic_iwpriv_get_txpower}, {"agg_cnt", hgic_iwpriv_get_aggcnt}, {"bss_bw", hgic_iwpriv_get_bss_bw}, {"chan_list", hgic_iwpriv_get_chan_list}, {"freq_range", hgic_iwpriv_get_freq_range}, {"key_mgmt", hgic_iwpriv_get_key_mgmt}, {"battery_level", hgic_iwpriv_get_battery_level}, {"module_type", hgic_iwpriv_get_module_type}, {"disassoc_reason", hgic_iwpriv_get_disassoc_reason}, {"ant_sel", hgic_iwpriv_get_ant_sel}, {"wkreason", hgic_iwpriv_get_wkreason}, {"wkdata_buff", hgic_iwpriv_get_wkdata_buff}, {"temperature", hgic_iwpriv_get_temperature}, {"conn_state", hgic_iwpriv_get_conn_state}, {"sta_count", hgic_iwpriv_get_sta_count}, {"txq_param", hgic_iwpriv_get_txq_param}, {"nav", hgic_iwpriv_get_nav}, {"rtc", hgic_iwpriv_get_rtc}, {"bgrssi", hgic_iwpriv_get_bgrssi}, {"center_freq", hgic_iwpriv_get_center_freq}, {"acs_result", hgic_iwpriv_get_acs_result}, {"reason_code", hgic_iwpriv_get_reason_code}, {"status_code", hgic_iwpriv_get_status_code}, {"dhcpc_result", hgic_iwpriv_get_dhcpc_result}, {"xosc", hgic_iwpriv_get_xosc}, {"freq_offset", hgic_iwpriv_get_freq_offset}, {"fwinfo", hgic_iwpriv_get_fwinfo}, {"stainfo", hgic_iwpriv_get_sta_info}, {"signal", hgic_iwpriv_get_signal}, {NULL,} }; int hgic_iwpriv_get_proc(struct hgic_fwctrl *ctrl, u8 ifidx, struct iwreq *wrqin) { struct fwctrl_cfgget *get = NULL; char *ptr; char field[130]; memset(field, 0, sizeof(field)); if (hgic_copyfrom_iwreq(wrqin, field, 128) == 0) { ptr = strchr(field, '='); if(ptr) *ptr = 0; for (get = hgpriv_gets; get->name; get++) { if (strcmp(field, get->name) == 0) { return get->get(ctrl, ifidx, wrqin); } } hgic_err("not support: [%s]\r\n", field); } else { hgic_err("copy_from_user fail\r\n"); } return -ENOTSUPP; } int hgic_iwpriv_dump(struct hgic_fwctrl *ctrl, struct iwreq *wrqin) { int len = 0; struct fwctrl_cfgget *get = NULL; struct fwctrl_cfgset *set = NULL; u8 *buf = kmalloc(4096, GFP_KERNEL); if (buf) { len += snprintf(buf + len, 4096 - len, "\r\nset:\r\n"); for (set = hgpriv_sets; set->name; set++) { len += snprintf(buf + len, 4096 - len, " %s\r\n", set->name); } len += snprintf(buf + len, 4096 - len, "get:\r\n"); for (get = hgpriv_gets; get->name; get++) { len += snprintf(buf + len, 4096 - len, " %s\r\n", get->name); } hgic_copyto_iwreq(wrqin, buf, len); kfree(buf); } return len; }