aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/cmd.c
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2010-10-16 12:08:58 -0400
committerLuciano Coelho <coelho@ti.com>2011-01-24 15:11:47 -0500
commit98bdaabbbced007c7eb89cd373f9cb1640635b46 (patch)
treeaa073697f83ff89a2fd64cffa44df84bffac8aff /drivers/net/wireless/wl12xx/cmd.c
parent203c903cbfbdf23bbb3020b9344dd1ffabcfcb53 (diff)
wl12xx: AP-mode high level commands
Add commands to start/stop BSS, add/remove STA and configure encryption keys. Split the encryption commands "set key" and "set default key" into AP and STA specific versions. Signed-off-by: Arik Nemtsov <arik@wizery.com> Reviewed-by: Luciano Coelho <coelho@ti.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/cmd.c')
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c276
1 files changed, 272 insertions, 4 deletions
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 3b7b8f0a200b..f9c5ce91cb12 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -36,6 +36,7 @@
36#include "wl12xx_80211.h" 36#include "wl12xx_80211.h"
37#include "cmd.h" 37#include "cmd.h"
38#include "event.h" 38#include "event.h"
39#include "tx.h"
39 40
40#define WL1271_CMD_FAST_POLL_COUNT 50 41#define WL1271_CMD_FAST_POLL_COUNT 50
41 42
@@ -702,9 +703,9 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
702 wl->basic_rate); 703 wl->basic_rate);
703} 704}
704 705
705int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) 706int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id)
706{ 707{
707 struct wl1271_cmd_set_keys *cmd; 708 struct wl1271_cmd_set_sta_keys *cmd;
708 int ret = 0; 709 int ret = 0;
709 710
710 wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); 711 wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id);
@@ -731,11 +732,42 @@ out:
731 return ret; 732 return ret;
732} 733}
733 734
734int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, 735int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id)
736{
737 struct wl1271_cmd_set_ap_keys *cmd;
738 int ret = 0;
739
740 wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id);
741
742 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
743 if (!cmd) {
744 ret = -ENOMEM;
745 goto out;
746 }
747
748 cmd->hlid = WL1271_AP_BROADCAST_HLID;
749 cmd->key_id = id;
750 cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
751 cmd->key_action = cpu_to_le16(KEY_SET_ID);
752 cmd->key_type = KEY_WEP;
753
754 ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
755 if (ret < 0) {
756 wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret);
757 goto out;
758 }
759
760out:
761 kfree(cmd);
762
763 return ret;
764}
765
766int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
735 u8 key_size, const u8 *key, const u8 *addr, 767 u8 key_size, const u8 *key, const u8 *addr,
736 u32 tx_seq_32, u16 tx_seq_16) 768 u32 tx_seq_32, u16 tx_seq_16)
737{ 769{
738 struct wl1271_cmd_set_keys *cmd; 770 struct wl1271_cmd_set_sta_keys *cmd;
739 int ret = 0; 771 int ret = 0;
740 772
741 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 773 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -788,6 +820,67 @@ out:
788 return ret; 820 return ret;
789} 821}
790 822
823int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
824 u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
825 u16 tx_seq_16)
826{
827 struct wl1271_cmd_set_ap_keys *cmd;
828 int ret = 0;
829 u8 lid_type;
830
831 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
832 if (!cmd)
833 return -ENOMEM;
834
835 if (hlid == WL1271_AP_BROADCAST_HLID) {
836 if (key_type == KEY_WEP)
837 lid_type = WEP_DEFAULT_LID_TYPE;
838 else
839 lid_type = BROADCAST_LID_TYPE;
840 } else {
841 lid_type = UNICAST_LID_TYPE;
842 }
843
844 wl1271_debug(DEBUG_CRYPT, "ap key action: %d id: %d lid: %d type: %d"
845 " hlid: %d", (int)action, (int)id, (int)lid_type,
846 (int)key_type, (int)hlid);
847
848 cmd->lid_key_type = lid_type;
849 cmd->hlid = hlid;
850 cmd->key_action = cpu_to_le16(action);
851 cmd->key_size = key_size;
852 cmd->key_type = key_type;
853 cmd->key_id = id;
854 cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16);
855 cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32);
856
857 if (key_type == KEY_TKIP) {
858 /*
859 * We get the key in the following form:
860 * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
861 * but the target is expecting:
862 * TKIP - RX MIC - TX MIC
863 */
864 memcpy(cmd->key, key, 16);
865 memcpy(cmd->key + 16, key + 24, 8);
866 memcpy(cmd->key + 24, key + 16, 8);
867 } else {
868 memcpy(cmd->key, key, key_size);
869 }
870
871 wl1271_dump(DEBUG_CRYPT, "TARGET AP KEY: ", cmd, sizeof(*cmd));
872
873 ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
874 if (ret < 0) {
875 wl1271_warning("could not set ap keys");
876 goto out;
877 }
878
879out:
880 kfree(cmd);
881 return ret;
882}
883
791int wl1271_cmd_disconnect(struct wl1271 *wl) 884int wl1271_cmd_disconnect(struct wl1271 *wl)
792{ 885{
793 struct wl1271_cmd_disconnect *cmd; 886 struct wl1271_cmd_disconnect *cmd;
@@ -850,3 +943,178 @@ out_free:
850out: 943out:
851 return ret; 944 return ret;
852} 945}
946
947int wl1271_cmd_start_bss(struct wl1271 *wl)
948{
949 struct wl1271_cmd_bss_start *cmd;
950 struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
951 int ret;
952
953 wl1271_debug(DEBUG_CMD, "cmd start bss");
954
955 /*
956 * FIXME: We currently do not support hidden SSID. The real SSID
957 * should be fetched from mac80211 first.
958 */
959 if (wl->ssid_len == 0) {
960 wl1271_warning("Hidden SSID currently not supported for AP");
961 ret = -EINVAL;
962 goto out;
963 }
964
965 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
966 if (!cmd) {
967 ret = -ENOMEM;
968 goto out;
969 }
970
971 memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);
972
973 cmd->aging_period = WL1271_AP_DEF_INACTIV_SEC;
974 cmd->bss_index = WL1271_AP_BSS_INDEX;
975 cmd->global_hlid = WL1271_AP_GLOBAL_HLID;
976 cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID;
977 cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
978 cmd->beacon_interval = cpu_to_le16(wl->beacon_int);
979 cmd->dtim_interval = bss_conf->dtim_period;
980 cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
981 cmd->channel = wl->channel;
982 cmd->ssid_len = wl->ssid_len;
983 cmd->ssid_type = SSID_TYPE_PUBLIC;
984 memcpy(cmd->ssid, wl->ssid, wl->ssid_len);
985
986 switch (wl->band) {
987 case IEEE80211_BAND_2GHZ:
988 cmd->band = RADIO_BAND_2_4GHZ;
989 break;
990 case IEEE80211_BAND_5GHZ:
991 cmd->band = RADIO_BAND_5GHZ;
992 break;
993 default:
994 wl1271_warning("bss start - unknown band: %d", (int)wl->band);
995 cmd->band = RADIO_BAND_2_4GHZ;
996 break;
997 }
998
999 ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0);
1000 if (ret < 0) {
1001 wl1271_error("failed to initiate cmd start bss");
1002 goto out_free;
1003 }
1004
1005out_free:
1006 kfree(cmd);
1007
1008out:
1009 return ret;
1010}
1011
1012int wl1271_cmd_stop_bss(struct wl1271 *wl)
1013{
1014 struct wl1271_cmd_bss_start *cmd;
1015 int ret;
1016
1017 wl1271_debug(DEBUG_CMD, "cmd stop bss");
1018
1019 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1020 if (!cmd) {
1021 ret = -ENOMEM;
1022 goto out;
1023 }
1024
1025 cmd->bss_index = WL1271_AP_BSS_INDEX;
1026
1027 ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0);
1028 if (ret < 0) {
1029 wl1271_error("failed to initiate cmd stop bss");
1030 goto out_free;
1031 }
1032
1033out_free:
1034 kfree(cmd);
1035
1036out:
1037 return ret;
1038}
1039
1040int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
1041{
1042 struct wl1271_cmd_add_sta *cmd;
1043 int ret;
1044
1045 wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid);
1046
1047 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1048 if (!cmd) {
1049 ret = -ENOMEM;
1050 goto out;
1051 }
1052
1053 /* currently we don't support UAPSD */
1054 cmd->sp_len = 0;
1055
1056 memcpy(cmd->addr, sta->addr, ETH_ALEN);
1057 cmd->bss_index = WL1271_AP_BSS_INDEX;
1058 cmd->aid = sta->aid;
1059 cmd->hlid = hlid;
1060
1061 /*
1062 * FIXME: Does STA support QOS? We need to propagate this info from
1063 * hostapd. Currently not that important since this is only used for
1064 * sending the correct flavor of null-data packet in response to a
1065 * trigger.
1066 */
1067 cmd->wmm = 0;
1068
1069 cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,
1070 sta->supp_rates[wl->band]));
1071
1072 wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates);
1073
1074 ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0);
1075 if (ret < 0) {
1076 wl1271_error("failed to initiate cmd add sta");
1077 goto out_free;
1078 }
1079
1080out_free:
1081 kfree(cmd);
1082
1083out:
1084 return ret;
1085}
1086
1087int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
1088{
1089 struct wl1271_cmd_remove_sta *cmd;
1090 int ret;
1091
1092 wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid);
1093
1094 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1095 if (!cmd) {
1096 ret = -ENOMEM;
1097 goto out;
1098 }
1099
1100 cmd->hlid = hlid;
1101 /* We never send a deauth, mac80211 is in charge of this */
1102 cmd->reason_opcode = 0;
1103 cmd->send_deauth_flag = 0;
1104
1105 ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0);
1106 if (ret < 0) {
1107 wl1271_error("failed to initiate cmd remove sta");
1108 goto out_free;
1109 }
1110
1111 ret = wl1271_cmd_wait_for_event(wl, STA_REMOVE_COMPLETE_EVENT_ID);
1112 if (ret < 0)
1113 wl1271_error("cmd remove sta event completion error");
1114
1115out_free:
1116 kfree(cmd);
1117
1118out:
1119 return ret;
1120}