1 /******************************************************************************
3 * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
21 * The full GNU General Public License is included in this distribution in the
22 * file called LICENSE.
24 * Contact Information:
25 * James P. Ketrenos <ipw2100-admin@linux.intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
28 *****************************************************************************/
30 #include <net/mac80211.h>
32 #include "iwl-eeprom.h"
37 #include "iwl-helpers.h"
40 int iwl_send_static_wepkey_cmd(struct iwl_priv
*priv
, u8 send_if_empty
)
43 u8 buff
[sizeof(struct iwl_wep_cmd
) +
44 sizeof(struct iwl_wep_key
) * WEP_KEYS_MAX
];
45 struct iwl_wep_cmd
*wep_cmd
= (struct iwl_wep_cmd
*)buff
;
46 size_t cmd_size
= sizeof(struct iwl_wep_cmd
);
47 struct iwl_host_cmd cmd
= {
50 .meta
.flags
= CMD_ASYNC
,
53 memset(wep_cmd
, 0, cmd_size
+
54 (sizeof(struct iwl_wep_key
) * WEP_KEYS_MAX
));
56 for (i
= 0; i
< WEP_KEYS_MAX
; i
++) {
57 wep_cmd
->key
[i
].key_index
= i
;
58 if (priv
->wep_keys
[i
].key_size
) {
59 wep_cmd
->key
[i
].key_offset
= i
;
62 wep_cmd
->key
[i
].key_offset
= WEP_INVALID_OFFSET
;
65 wep_cmd
->key
[i
].key_size
= priv
->wep_keys
[i
].key_size
;
66 memcpy(&wep_cmd
->key
[i
].key
[3], priv
->wep_keys
[i
].key
,
67 priv
->wep_keys
[i
].key_size
);
70 wep_cmd
->global_key_type
= WEP_KEY_WEP_TYPE
;
71 wep_cmd
->num_keys
= WEP_KEYS_MAX
;
73 cmd_size
+= sizeof(struct iwl_wep_key
) * WEP_KEYS_MAX
;
77 if (not_empty
|| send_if_empty
)
78 return iwl_send_cmd(priv
, &cmd
);
83 int iwl_remove_default_wep_key(struct iwl_priv
*priv
,
84 struct ieee80211_key_conf
*key
)
89 spin_lock_irqsave(&priv
->sta_lock
, flags
);
90 priv
->default_wep_key
--;
91 memset(&priv
->wep_keys
[key
->keyidx
], 0, sizeof(priv
->wep_keys
[0]));
92 ret
= iwl_send_static_wepkey_cmd(priv
, 1);
93 spin_unlock_irqrestore(&priv
->sta_lock
, flags
);
98 int iwl_set_default_wep_key(struct iwl_priv
*priv
,
99 struct ieee80211_key_conf
*keyconf
)
104 keyconf
->flags
&= ~IEEE80211_KEY_FLAG_GENERATE_IV
;
105 keyconf
->hw_key_idx
= keyconf
->keyidx
;
106 priv
->stations
[IWL_AP_ID
].keyinfo
.alg
= ALG_WEP
;
108 spin_lock_irqsave(&priv
->sta_lock
, flags
);
109 priv
->default_wep_key
++;
111 priv
->wep_keys
[keyconf
->keyidx
].key_size
= keyconf
->keylen
;
112 memcpy(&priv
->wep_keys
[keyconf
->keyidx
].key
, &keyconf
->key
,
115 ret
= iwl_send_static_wepkey_cmd(priv
, 0);
116 spin_unlock_irqrestore(&priv
->sta_lock
, flags
);
121 int iwl_set_wep_dynamic_key_info(struct iwl_priv
*priv
,
122 struct ieee80211_key_conf
*keyconf
,
126 __le16 key_flags
= 0;
129 keyconf
->flags
&= ~IEEE80211_KEY_FLAG_GENERATE_IV
;
130 keyconf
->hw_key_idx
= keyconf
->keyidx
;
132 key_flags
|= (STA_KEY_FLG_WEP
| STA_KEY_FLG_MAP_KEY_MSK
);
133 key_flags
|= cpu_to_le16(keyconf
->keyidx
<< STA_KEY_FLG_KEYID_POS
);
134 key_flags
&= ~STA_KEY_FLG_INVALID
;
136 if (keyconf
->keylen
== WEP_KEY_LEN_128
)
137 key_flags
|= STA_KEY_FLG_KEY_SIZE_MSK
;
139 if (sta_id
== priv
->hw_setting
.bcast_sta_id
)
140 key_flags
|= STA_KEY_MULTICAST_MSK
;
142 spin_lock_irqsave(&priv
->sta_lock
, flags
);
144 priv
->stations
[sta_id
].keyinfo
.alg
= keyconf
->alg
;
145 priv
->stations
[sta_id
].keyinfo
.keylen
= keyconf
->keylen
;
146 priv
->stations
[sta_id
].keyinfo
.keyidx
= keyconf
->keyidx
;
148 memcpy(priv
->stations
[sta_id
].keyinfo
.key
,
149 keyconf
->key
, keyconf
->keylen
);
151 memcpy(&priv
->stations
[sta_id
].sta
.key
.key
[3],
152 keyconf
->key
, keyconf
->keylen
);
154 priv
->stations
[sta_id
].sta
.key
.key_offset
= sta_id
% 8; /* FIXME */
155 priv
->stations
[sta_id
].sta
.key
.key_flags
= key_flags
;
157 priv
->stations
[sta_id
].sta
.sta
.modify_mask
= STA_MODIFY_KEY_MASK
;
158 priv
->stations
[sta_id
].sta
.mode
= STA_CONTROL_MODIFY_MSK
;
160 ret
= iwl4965_send_add_station(priv
,
161 &priv
->stations
[sta_id
].sta
, CMD_ASYNC
);
163 spin_unlock_irqrestore(&priv
->sta_lock
, flags
);