Commit | Line | Data |
---|---|---|
13a9930d WS |
1 | /* |
2 | * Driver for KeyStream wireless LAN cards. | |
3 | * | |
13a9930d WS |
4 | * Copyright (C) 2005-2008 KeyStream Corp. |
5 | * Copyright (C) 2009 Renesas Technology Corp. | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
c5d9a030 WS |
8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | |
13a9930d WS |
10 | */ |
11 | ||
12 | #include "ks_wlan.h" | |
13a9930d WS |
13 | #include "ks_hostif.h" |
14 | #include "eap_packet.h" | |
15 | #include "michael_mic.h" | |
16 | ||
17 | #include <linux/if_ether.h> | |
18 | #include <linux/if_arp.h> | |
19 | ||
20 | /* Include Wireless Extension definition and check version */ | |
13a9930d | 21 | #include <net/iw_handler.h> /* New driver API */ |
13a9930d | 22 | |
20c4f9c5 WS |
23 | extern int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, |
24 | unsigned long size, | |
25 | void (*complete_handler) (void *arg1, void *arg2), | |
26 | void *arg1, void *arg2); | |
13a9930d WS |
27 | extern void send_packet_complete(void *, void *); |
28 | ||
feedcf1a WS |
29 | extern void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv); |
30 | extern int ks_wlan_hw_power_save(struct ks_wlan_private *priv); | |
13a9930d WS |
31 | |
32 | /* macro */ | |
33 | #define inc_smeqhead(priv) \ | |
34 | ( priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE ) | |
35 | #define inc_smeqtail(priv) \ | |
36 | ( priv->sme_i.qtail = (priv->sme_i.qtail + 1) % SME_EVENT_BUFF_SIZE ) | |
37 | #define cnt_smeqbody(priv) \ | |
38 | (((priv->sme_i.qtail + SME_EVENT_BUFF_SIZE) - (priv->sme_i.qhead)) % SME_EVENT_BUFF_SIZE ) | |
39 | ||
40 | #define KS_WLAN_MEM_FLAG (GFP_ATOMIC) | |
41 | ||
42 | static | |
feedcf1a | 43 | inline u8 get_BYTE(struct ks_wlan_private *priv) |
13a9930d WS |
44 | { |
45 | u8 data; | |
46 | data = *(priv->rxp)++; | |
47 | /* length check in advance ! */ | |
48 | --(priv->rx_size); | |
49 | return data; | |
50 | } | |
51 | ||
52 | static | |
feedcf1a | 53 | inline u16 get_WORD(struct ks_wlan_private *priv) |
13a9930d WS |
54 | { |
55 | u16 data; | |
20c4f9c5 | 56 | data = (get_BYTE(priv) & 0xff); |
13a9930d WS |
57 | data |= ((get_BYTE(priv) << 8) & 0xff00); |
58 | return data; | |
59 | } | |
60 | ||
61 | static | |
feedcf1a | 62 | inline u32 get_DWORD(struct ks_wlan_private *priv) |
13a9930d WS |
63 | { |
64 | u32 data; | |
20c4f9c5 | 65 | data = (get_BYTE(priv) & 0xff); |
13a9930d WS |
66 | data |= ((get_BYTE(priv) << 8) & 0x0000ff00); |
67 | data |= ((get_BYTE(priv) << 16) & 0x00ff0000); | |
68 | data |= ((get_BYTE(priv) << 24) & 0xff000000); | |
69 | return data; | |
70 | } | |
71 | ||
9afe11e9 | 72 | static void ks_wlan_hw_wakeup_task(struct work_struct *work) |
13a9930d | 73 | { |
20c4f9c5 WS |
74 | struct ks_wlan_private *priv = |
75 | container_of(work, struct ks_wlan_private, ks_wlan_wakeup_task); | |
13a9930d | 76 | int ps_status = atomic_read(&priv->psstatus.status); |
9d29f14d | 77 | long time_left; |
13a9930d | 78 | |
20c4f9c5 | 79 | if (ps_status == PS_SNOOZE) { |
13a9930d | 80 | ks_wlan_hw_wakeup_request(priv); |
9d29f14d NMG |
81 | time_left = wait_for_completion_interruptible_timeout( |
82 | &priv->psstatus.wakeup_wait, | |
83 | msecs_to_jiffies(20)); | |
84 | if (time_left <= 0) { | |
85 | DPRINTK(1, "wake up timeout or interrupted !!!\n"); | |
13a9930d WS |
86 | schedule_work(&priv->ks_wlan_wakeup_task); |
87 | return; | |
88 | } | |
20c4f9c5 WS |
89 | } else { |
90 | DPRINTK(1, "ps_status=%d\n", ps_status); | |
13a9930d WS |
91 | } |
92 | ||
93 | /* power save */ | |
20c4f9c5 WS |
94 | if (atomic_read(&priv->sme_task.count) > 0) { |
95 | DPRINTK(4, "sme task enable.\n"); | |
13a9930d WS |
96 | tasklet_enable(&priv->sme_task); |
97 | } | |
98 | } | |
99 | ||
100 | static | |
feedcf1a | 101 | int ks_wlan_do_power_save(struct ks_wlan_private *priv) |
13a9930d | 102 | { |
20c4f9c5 | 103 | int rc = 0; |
13a9930d | 104 | |
20c4f9c5 | 105 | DPRINTK(4, "psstatus.status=%d\n", atomic_read(&priv->psstatus.status)); |
13a9930d | 106 | |
20c4f9c5 | 107 | if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { |
13a9930d | 108 | hostif_sme_enqueue(priv, SME_POW_MNGMT_REQUEST); |
20c4f9c5 | 109 | } else { |
13a9930d WS |
110 | priv->dev_state = DEVICE_STATE_READY; |
111 | } | |
13a9930d WS |
112 | return rc; |
113 | } | |
114 | ||
115 | static | |
feedcf1a | 116 | int get_current_ap(struct ks_wlan_private *priv, struct link_ap_info_t *ap_info) |
13a9930d WS |
117 | { |
118 | struct local_ap_t *ap; | |
13a9930d | 119 | union iwreq_data wrqu; |
20c4f9c5 WS |
120 | struct net_device *netdev = priv->net_dev; |
121 | int rc = 0; | |
13a9930d | 122 | |
20c4f9c5 | 123 | DPRINTK(3, "\n"); |
13a9930d WS |
124 | ap = &(priv->current_ap); |
125 | ||
20c4f9c5 WS |
126 | if ((priv->connect_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS) { |
127 | memset(ap, 0, sizeof(struct local_ap_t)); | |
13a9930d WS |
128 | return 1; |
129 | } | |
130 | ||
131 | /* bssid */ | |
20c4f9c5 | 132 | memcpy(&(ap->bssid[0]), &(ap_info->bssid[0]), ETH_ALEN); |
13a9930d | 133 | /* essid */ |
20c4f9c5 WS |
134 | memcpy(&(ap->ssid.body[0]), &(priv->reg.ssid.body[0]), |
135 | priv->reg.ssid.size); | |
13a9930d WS |
136 | ap->ssid.size = priv->reg.ssid.size; |
137 | /* rate_set */ | |
20c4f9c5 WS |
138 | memcpy(&(ap->rate_set.body[0]), &(ap_info->rate_set.body[0]), |
139 | ap_info->rate_set.size); | |
13a9930d | 140 | ap->rate_set.size = ap_info->rate_set.size; |
20c4f9c5 | 141 | if (ap_info->ext_rate_set.size) { |
13a9930d WS |
142 | /* rate_set */ |
143 | memcpy(&(ap->rate_set.body[ap->rate_set.size]), | |
144 | &(ap_info->ext_rate_set.body[0]), | |
145 | ap_info->ext_rate_set.size); | |
146 | ap->rate_set.size += ap_info->ext_rate_set.size; | |
147 | } | |
148 | /* channel */ | |
149 | ap->channel = ap_info->ds_parameter.channel; | |
150 | /* rssi */ | |
151 | ap->rssi = ap_info->rssi; | |
152 | /* sq */ | |
153 | ap->sq = ap_info->sq; | |
154 | /* noise */ | |
155 | ap->noise = ap_info->noise; | |
156 | /* capability */ | |
157 | ap->capability = ap_info->capability; | |
158 | /* rsn */ | |
20c4f9c5 WS |
159 | if ((ap_info->rsn_mode & RSN_MODE_WPA2) |
160 | && (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2)) { | |
13a9930d | 161 | ap->rsn_ie.id = 0x30; |
20c4f9c5 | 162 | if (ap_info->rsn.size <= RSN_IE_BODY_MAX) { |
13a9930d | 163 | ap->rsn_ie.size = ap_info->rsn.size; |
20c4f9c5 WS |
164 | memcpy(&(ap->rsn_ie.body[0]), &(ap_info->rsn.body[0]), |
165 | ap_info->rsn.size); | |
166 | } else { | |
13a9930d | 167 | ap->rsn_ie.size = RSN_IE_BODY_MAX; |
20c4f9c5 WS |
168 | memcpy(&(ap->rsn_ie.body[0]), &(ap_info->rsn.body[0]), |
169 | RSN_IE_BODY_MAX); | |
13a9930d | 170 | } |
20c4f9c5 WS |
171 | } else if ((ap_info->rsn_mode & RSN_MODE_WPA) |
172 | && (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA)) { | |
13a9930d | 173 | ap->wpa_ie.id = 0xdd; |
20c4f9c5 | 174 | if (ap_info->rsn.size <= RSN_IE_BODY_MAX) { |
13a9930d | 175 | ap->wpa_ie.size = ap_info->rsn.size; |
20c4f9c5 WS |
176 | memcpy(&(ap->wpa_ie.body[0]), &(ap_info->rsn.body[0]), |
177 | ap_info->rsn.size); | |
178 | } else { | |
13a9930d | 179 | ap->wpa_ie.size = RSN_IE_BODY_MAX; |
20c4f9c5 WS |
180 | memcpy(&(ap->wpa_ie.body[0]), &(ap_info->rsn.body[0]), |
181 | RSN_IE_BODY_MAX); | |
13a9930d | 182 | } |
20c4f9c5 | 183 | } else { |
13a9930d WS |
184 | ap->rsn_ie.id = 0; |
185 | ap->rsn_ie.size = 0; | |
186 | ap->wpa_ie.id = 0; | |
187 | ap->wpa_ie.size = 0; | |
188 | } | |
189 | ||
13a9930d WS |
190 | wrqu.data.length = 0; |
191 | wrqu.data.flags = 0; | |
192 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | |
20c4f9c5 | 193 | if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { |
13a9930d WS |
194 | memcpy(wrqu.ap_addr.sa_data, |
195 | &(priv->current_ap.bssid[0]), ETH_ALEN); | |
20c4f9c5 WS |
196 | DPRINTK(3, |
197 | "IWEVENT: connect bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", | |
198 | (unsigned char)wrqu.ap_addr.sa_data[0], | |
199 | (unsigned char)wrqu.ap_addr.sa_data[1], | |
200 | (unsigned char)wrqu.ap_addr.sa_data[2], | |
201 | (unsigned char)wrqu.ap_addr.sa_data[3], | |
202 | (unsigned char)wrqu.ap_addr.sa_data[4], | |
203 | (unsigned char)wrqu.ap_addr.sa_data[5]); | |
13a9930d WS |
204 | wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL); |
205 | } | |
20c4f9c5 WS |
206 | DPRINTK(4, "\n Link AP\n"); |
207 | DPRINTK(4, " bssid=%02X:%02X:%02X:%02X:%02X:%02X\n \ | |
13a9930d | 208 | essid=%s\n rate_set=%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X\n channel=%d\n \ |
20c4f9c5 WS |
209 | rssi=%d\n sq=%d\n capability=%04X\n", ap->bssid[0], ap->bssid[1], ap->bssid[2], ap->bssid[3], ap->bssid[4], ap->bssid[5], &(ap->ssid.body[0]), ap->rate_set.body[0], ap->rate_set.body[1], ap->rate_set.body[2], ap->rate_set.body[3], ap->rate_set.body[4], ap->rate_set.body[5], ap->rate_set.body[6], ap->rate_set.body[7], ap->channel, ap->rssi, ap->sq, ap->capability); |
210 | DPRINTK(4, "\n Link AP\n rsn.mode=%d\n rsn.size=%d\n", | |
211 | ap_info->rsn_mode, ap_info->rsn.size); | |
212 | DPRINTK(4, "\n ext_rate_set_size=%d\n rate_set_size=%d\n", | |
213 | ap_info->ext_rate_set.size, ap_info->rate_set.size); | |
13a9930d WS |
214 | |
215 | return rc; | |
216 | } | |
217 | ||
218 | static | |
20c4f9c5 WS |
219 | int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, |
220 | struct local_ap_t *ap) | |
13a9930d WS |
221 | { |
222 | unsigned char *bp; | |
20c4f9c5 WS |
223 | int bsize, offset; |
224 | int rc = 0; | |
13a9930d | 225 | |
20c4f9c5 WS |
226 | DPRINTK(3, "\n"); |
227 | memset(ap, 0, sizeof(struct local_ap_t)); | |
13a9930d WS |
228 | |
229 | /* bssid */ | |
20c4f9c5 | 230 | memcpy(&(ap->bssid[0]), &(ap_info->bssid[0]), ETH_ALEN); |
13a9930d WS |
231 | /* rssi */ |
232 | ap->rssi = ap_info->rssi; | |
233 | /* sq */ | |
234 | ap->sq = ap_info->sq; | |
235 | /* noise */ | |
236 | ap->noise = ap_info->noise; | |
237 | /* capability */ | |
238 | ap->capability = ap_info->capability; | |
239 | /* channel */ | |
240 | ap->channel = ap_info->ch_info; | |
241 | ||
242 | bp = &(ap_info->body[0]); | |
243 | bsize = ap_info->body_size; | |
244 | offset = 0; | |
245 | ||
20c4f9c5 | 246 | while (bsize > offset) { |
13a9930d | 247 | /* DPRINTK(4, "Element ID=%d \n",*bp); */ |
20c4f9c5 WS |
248 | switch (*bp) { |
249 | case 0: /* ssid */ | |
250 | if (*(bp + 1) <= SSID_MAX_SIZE) { | |
251 | ap->ssid.size = *(bp + 1); | |
252 | } else { | |
253 | DPRINTK(1, "size over :: ssid size=%d \n", | |
254 | *(bp + 1)); | |
13a9930d WS |
255 | ap->ssid.size = SSID_MAX_SIZE; |
256 | } | |
20c4f9c5 | 257 | memcpy(&(ap->ssid.body[0]), bp + 2, ap->ssid.size); |
13a9930d | 258 | break; |
20c4f9c5 WS |
259 | case 1: /* rate */ |
260 | case 50: /* ext rate */ | |
261 | if ((*(bp + 1) + ap->rate_set.size) <= | |
262 | RATE_SET_MAX_SIZE) { | |
263 | memcpy(&(ap->rate_set.body[ap->rate_set.size]), | |
264 | bp + 2, *(bp + 1)); | |
265 | ap->rate_set.size += *(bp + 1); | |
266 | } else { | |
13a9930d | 267 | DPRINTK(1, "size over :: rate size=%d \n", |
20c4f9c5 WS |
268 | (*(bp + 1) + ap->rate_set.size)); |
269 | memcpy(&(ap->rate_set.body[ap->rate_set.size]), | |
270 | bp + 2, | |
13a9930d | 271 | RATE_SET_MAX_SIZE - ap->rate_set.size); |
20c4f9c5 WS |
272 | ap->rate_set.size += |
273 | (RATE_SET_MAX_SIZE - ap->rate_set.size); | |
13a9930d WS |
274 | } |
275 | break; | |
20c4f9c5 | 276 | case 3: /* DS parameter */ |
13a9930d | 277 | break; |
20c4f9c5 | 278 | case 48: /* RSN(WPA2) */ |
13a9930d | 279 | ap->rsn_ie.id = *bp; |
20c4f9c5 WS |
280 | if (*(bp + 1) <= RSN_IE_BODY_MAX) { |
281 | ap->rsn_ie.size = *(bp + 1); | |
282 | } else { | |
283 | DPRINTK(1, "size over :: rsn size=%d \n", | |
284 | *(bp + 1)); | |
13a9930d WS |
285 | ap->rsn_ie.size = RSN_IE_BODY_MAX; |
286 | } | |
20c4f9c5 | 287 | memcpy(&(ap->rsn_ie.body[0]), bp + 2, ap->rsn_ie.size); |
13a9930d | 288 | break; |
20c4f9c5 WS |
289 | case 221: /* WPA */ |
290 | if (!memcmp(bp + 2, "\x00\x50\xf2\x01", 4)) { /* WPA OUI check */ | |
13a9930d | 291 | ap->wpa_ie.id = *bp; |
20c4f9c5 WS |
292 | if (*(bp + 1) <= RSN_IE_BODY_MAX) { |
293 | ap->wpa_ie.size = *(bp + 1); | |
294 | } else { | |
295 | DPRINTK(1, | |
296 | "size over :: wpa size=%d \n", | |
297 | *(bp + 1)); | |
13a9930d WS |
298 | ap->wpa_ie.size = RSN_IE_BODY_MAX; |
299 | } | |
20c4f9c5 WS |
300 | memcpy(&(ap->wpa_ie.body[0]), bp + 2, |
301 | ap->wpa_ie.size); | |
13a9930d WS |
302 | } |
303 | break; | |
304 | ||
20c4f9c5 WS |
305 | case 2: /* FH parameter */ |
306 | case 4: /* CF parameter */ | |
307 | case 5: /* TIM */ | |
308 | case 6: /* IBSS parameter */ | |
309 | case 7: /* Country */ | |
310 | case 42: /* ERP information */ | |
311 | case 47: /* Reserve ID 47 Broadcom AP */ | |
13a9930d WS |
312 | break; |
313 | default: | |
20c4f9c5 | 314 | DPRINTK(4, "unknown Element ID=%d \n", *bp); |
13a9930d WS |
315 | break; |
316 | } | |
20c4f9c5 WS |
317 | offset += 2; /* id & size field */ |
318 | offset += *(bp + 1); /* +size offset */ | |
319 | bp += (*(bp + 1) + 2); /* pointer update */ | |
13a9930d WS |
320 | } |
321 | ||
322 | return rc; | |
323 | } | |
324 | ||
325 | static | |
feedcf1a | 326 | void hostif_data_indication(struct ks_wlan_private *priv) |
13a9930d | 327 | { |
20c4f9c5 | 328 | unsigned int rx_ind_size; /* indicate data size */ |
13a9930d | 329 | struct sk_buff *skb; |
20c4f9c5 WS |
330 | unsigned short auth_type; |
331 | unsigned char temp[256]; | |
13a9930d | 332 | |
20c4f9c5 | 333 | unsigned char RecvMIC[8]; |
13a9930d WS |
334 | char buf[128]; |
335 | struct ether_hdr *eth_hdr; | |
336 | unsigned short eth_proto; | |
337 | unsigned long now; | |
338 | struct mic_failure_t *mic_failure; | |
339 | struct ieee802_1x_hdr *aa1x_hdr; | |
340 | struct wpa_eapol_key *eap_key; | |
341 | struct michel_mic_t michel_mic; | |
13a9930d | 342 | union iwreq_data wrqu; |
13a9930d | 343 | |
20c4f9c5 | 344 | DPRINTK(3, "\n"); |
13a9930d WS |
345 | |
346 | /* min length check */ | |
347 | if (priv->rx_size <= ETH_HLEN) { | |
20c4f9c5 | 348 | DPRINTK(3, "rx_size = %d\n", priv->rx_size); |
13a9930d WS |
349 | priv->nstats.rx_errors++; |
350 | return; | |
351 | } | |
352 | ||
20c4f9c5 WS |
353 | auth_type = get_WORD(priv); /* AuthType */ |
354 | get_WORD(priv); /* Reserve Area */ | |
13a9930d WS |
355 | |
356 | eth_hdr = (struct ether_hdr *)(priv->rxp); | |
357 | eth_proto = ntohs(eth_hdr->h_proto); | |
20c4f9c5 | 358 | DPRINTK(3, "ether protocol = %04X\n", eth_proto); |
13a9930d WS |
359 | |
360 | /* source address check */ | |
20c4f9c5 | 361 | if (!memcmp(&priv->eth_addr[0], eth_hdr->h_source, ETH_ALEN)) { |
13a9930d | 362 | DPRINTK(1, "invalid : source is own mac address !!\n"); |
20c4f9c5 WS |
363 | DPRINTK(1, |
364 | "eth_hdrernet->h_dest=%02X:%02X:%02X:%02X:%02X:%02X\n", | |
365 | eth_hdr->h_source[0], eth_hdr->h_source[1], | |
366 | eth_hdr->h_source[2], eth_hdr->h_source[3], | |
367 | eth_hdr->h_source[4], eth_hdr->h_source[5]); | |
13a9930d WS |
368 | priv->nstats.rx_errors++; |
369 | return; | |
370 | } | |
371 | ||
372 | /* for WPA */ | |
20c4f9c5 WS |
373 | if (auth_type != TYPE_DATA && priv->wpa.rsn_enabled) { |
374 | if (memcmp(ð_hdr->h_source[0], &priv->eth_addr[0], ETH_ALEN)) { /* source address check */ | |
375 | if (eth_hdr->h_dest_snap != eth_hdr->h_source_snap) { | |
376 | DPRINTK(1, "invalid data format\n"); | |
13a9930d WS |
377 | priv->nstats.rx_errors++; |
378 | return; | |
379 | } | |
20c4f9c5 WS |
380 | if (((auth_type == TYPE_PMK1 |
381 | && priv->wpa.pairwise_suite == | |
382 | IW_AUTH_CIPHER_TKIP) || (auth_type == TYPE_GMK1 | |
383 | && priv->wpa. | |
384 | group_suite == | |
385 | IW_AUTH_CIPHER_TKIP) | |
386 | || (auth_type == TYPE_GMK2 | |
387 | && priv->wpa.group_suite == | |
388 | IW_AUTH_CIPHER_TKIP)) | |
389 | && priv->wpa.key[auth_type - 1].key_len) { | |
390 | DPRINTK(4, "TKIP: protocol=%04X: size=%u\n", | |
391 | eth_proto, priv->rx_size); | |
13a9930d | 392 | /* MIC save */ |
20c4f9c5 WS |
393 | memcpy(&RecvMIC[0], |
394 | (priv->rxp) + ((priv->rx_size) - 8), 8); | |
13a9930d | 395 | priv->rx_size = priv->rx_size - 8; |
20c4f9c5 WS |
396 | if (auth_type > 0 && auth_type < 4) { /* auth_type check */ |
397 | MichaelMICFunction(&michel_mic, (uint8_t *) priv->wpa.key[auth_type - 1].rx_mic_key, (uint8_t *) priv->rxp, (int)priv->rx_size, (uint8_t) 0, /* priority */ | |
398 | (uint8_t *) | |
399 | michel_mic.Result); | |
13a9930d | 400 | } |
20c4f9c5 | 401 | if (memcmp(michel_mic.Result, RecvMIC, 8)) { |
13a9930d WS |
402 | now = jiffies; |
403 | mic_failure = &priv->wpa.mic_failure; | |
404 | /* MIC FAILURE */ | |
20c4f9c5 WS |
405 | if (mic_failure->last_failure_time && |
406 | (now - | |
407 | mic_failure->last_failure_time) / | |
408 | HZ >= 60) { | |
409 | mic_failure->failure = 0; | |
13a9930d | 410 | } |
20c4f9c5 WS |
411 | DPRINTK(4, "MIC FAILURE \n"); |
412 | if (mic_failure->failure == 0) { | |
413 | mic_failure->failure = 1; | |
414 | mic_failure->counter = 0; | |
415 | } else if (mic_failure->failure == 1) { | |
416 | mic_failure->failure = 2; | |
13a9930d | 417 | mic_failure->counter = |
20c4f9c5 WS |
418 | (uint16_t) ((now - |
419 | mic_failure-> | |
420 | last_failure_time) | |
421 | / HZ); | |
422 | if (!mic_failure->counter) /* mic_failure counter value range 1-60 */ | |
423 | mic_failure->counter = | |
424 | 1; | |
13a9930d | 425 | } |
20c4f9c5 WS |
426 | priv->wpa.mic_failure. |
427 | last_failure_time = now; | |
13a9930d | 428 | /* needed parameters: count, keyid, key type, TSC */ |
20c4f9c5 WS |
429 | sprintf(buf, |
430 | "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=" | |
13a9930d | 431 | "%02x:%02x:%02x:%02x:%02x:%02x)", |
20c4f9c5 WS |
432 | auth_type - 1, |
433 | eth_hdr-> | |
434 | h_dest[0] & 0x01 ? "broad" : | |
435 | "uni", eth_hdr->h_source[0], | |
436 | eth_hdr->h_source[1], | |
437 | eth_hdr->h_source[2], | |
438 | eth_hdr->h_source[3], | |
439 | eth_hdr->h_source[4], | |
440 | eth_hdr->h_source[5]); | |
13a9930d WS |
441 | memset(&wrqu, 0, sizeof(wrqu)); |
442 | wrqu.data.length = strlen(buf); | |
20c4f9c5 WS |
443 | DPRINTK(4, |
444 | "IWEVENT:MICHAELMICFAILURE\n"); | |
445 | wireless_send_event(priv->net_dev, | |
446 | IWEVCUSTOM, &wrqu, | |
447 | buf); | |
13a9930d WS |
448 | return; |
449 | } | |
450 | } | |
451 | } | |
452 | } | |
453 | ||
20c4f9c5 WS |
454 | if ((priv->connect_status & FORCE_DISCONNECT) || |
455 | priv->wpa.mic_failure.failure == 2) { | |
13a9930d WS |
456 | return; |
457 | } | |
458 | ||
459 | /* check 13th byte at rx data */ | |
20c4f9c5 WS |
460 | switch (*(priv->rxp + 12)) { |
461 | case 0xAA: /* SNAP */ | |
13a9930d | 462 | rx_ind_size = priv->rx_size - 6; |
20c4f9c5 WS |
463 | skb = dev_alloc_skb(rx_ind_size); |
464 | DPRINTK(4, "SNAP, rx_ind_size = %d\n", rx_ind_size); | |
465 | ||
466 | if (skb) { | |
467 | memcpy(skb_put(skb, 12), priv->rxp, 12); /* 8802/FDDI MAC copy */ | |
468 | /* (SNAP+UI..) skip */ | |
469 | memcpy(skb_put(skb, rx_ind_size - 12), priv->rxp + 18, rx_ind_size - 12); /* copy after Type */ | |
470 | ||
471 | aa1x_hdr = (struct ieee802_1x_hdr *)(priv->rxp + 20); | |
472 | if (aa1x_hdr->type == IEEE802_1X_TYPE_EAPOL_KEY | |
473 | && priv->wpa.rsn_enabled) { | |
474 | eap_key = | |
475 | (struct wpa_eapol_key *)(aa1x_hdr + 1); | |
13a9930d WS |
476 | atomic_set(&priv->psstatus.snooze_guard, 1); |
477 | } | |
478 | ||
479 | /* rx indication */ | |
480 | skb->dev = priv->net_dev; | |
20c4f9c5 | 481 | skb->protocol = eth_type_trans(skb, skb->dev); |
13a9930d WS |
482 | priv->nstats.rx_packets++; |
483 | priv->nstats.rx_bytes += rx_ind_size; | |
484 | skb->dev->last_rx = jiffies; | |
20c4f9c5 | 485 | netif_rx(skb); |
13a9930d | 486 | } else { |
20c4f9c5 | 487 | printk(KERN_WARNING |
95d2a324 | 488 | "ks_wlan: Memory squeeze, dropping packet.\n"); |
13a9930d WS |
489 | priv->nstats.rx_dropped++; |
490 | } | |
491 | break; | |
20c4f9c5 | 492 | case 0xF0: /* NETBEUI/NetBIOS */ |
13a9930d | 493 | rx_ind_size = (priv->rx_size + 2); |
20c4f9c5 WS |
494 | skb = dev_alloc_skb(rx_ind_size); |
495 | DPRINTK(3, "NETBEUI/NetBIOS rx_ind_size=%d\n", rx_ind_size); | |
13a9930d | 496 | |
20c4f9c5 WS |
497 | if (skb) { |
498 | memcpy(skb_put(skb, 12), priv->rxp, 12); /* 8802/FDDI MAC copy */ | |
13a9930d | 499 | |
20c4f9c5 WS |
500 | temp[0] = (((rx_ind_size - 12) >> 8) & 0xff); /* NETBEUI size add */ |
501 | temp[1] = ((rx_ind_size - 12) & 0xff); | |
502 | memcpy(skb_put(skb, 2), temp, 2); | |
13a9930d | 503 | |
20c4f9c5 | 504 | memcpy(skb_put(skb, rx_ind_size - 14), priv->rxp + 12, rx_ind_size - 14); /* copy after Type */ |
13a9930d | 505 | |
20c4f9c5 WS |
506 | aa1x_hdr = (struct ieee802_1x_hdr *)(priv->rxp + 14); |
507 | if (aa1x_hdr->type == IEEE802_1X_TYPE_EAPOL_KEY | |
508 | && priv->wpa.rsn_enabled) { | |
509 | eap_key = | |
510 | (struct wpa_eapol_key *)(aa1x_hdr + 1); | |
13a9930d WS |
511 | atomic_set(&priv->psstatus.snooze_guard, 1); |
512 | } | |
513 | ||
514 | /* rx indication */ | |
515 | skb->dev = priv->net_dev; | |
20c4f9c5 | 516 | skb->protocol = eth_type_trans(skb, skb->dev); |
13a9930d WS |
517 | priv->nstats.rx_packets++; |
518 | priv->nstats.rx_bytes += rx_ind_size; | |
519 | skb->dev->last_rx = jiffies; | |
20c4f9c5 | 520 | netif_rx(skb); |
13a9930d | 521 | } else { |
20c4f9c5 | 522 | printk(KERN_WARNING |
95d2a324 | 523 | "ks_wlan: Memory squeeze, dropping packet.\n"); |
13a9930d WS |
524 | priv->nstats.rx_dropped++; |
525 | } | |
526 | break; | |
20c4f9c5 WS |
527 | default: /* other rx data */ |
528 | DPRINTK(2, "invalid data format\n"); | |
13a9930d WS |
529 | priv->nstats.rx_errors++; |
530 | } | |
531 | } | |
532 | ||
533 | static | |
feedcf1a | 534 | void hostif_mib_get_confirm(struct ks_wlan_private *priv) |
13a9930d | 535 | { |
20c4f9c5 WS |
536 | struct net_device *dev = priv->net_dev; |
537 | uint32_t mib_status; | |
538 | uint32_t mib_attribute; | |
539 | uint16_t mib_val_size; | |
540 | uint16_t mib_val_type; | |
13a9930d WS |
541 | |
542 | DPRINTK(3, "\n"); | |
543 | ||
20c4f9c5 WS |
544 | mib_status = get_DWORD(priv); /* MIB status */ |
545 | mib_attribute = get_DWORD(priv); /* MIB atttibute */ | |
546 | mib_val_size = get_WORD(priv); /* MIB value size */ | |
547 | mib_val_type = get_WORD(priv); /* MIB value type */ | |
13a9930d WS |
548 | |
549 | if (mib_status != 0) { | |
550 | /* in case of error */ | |
20c4f9c5 WS |
551 | DPRINTK(1, "attribute=%08X, status=%08X\n", mib_attribute, |
552 | mib_status); | |
13a9930d WS |
553 | return; |
554 | } | |
555 | ||
556 | switch (mib_attribute) { | |
557 | case DOT11_MAC_ADDRESS: | |
558 | /* MAC address */ | |
20c4f9c5 | 559 | DPRINTK(3, " mib_attribute=DOT11_MAC_ADDRESS\n"); |
13a9930d WS |
560 | hostif_sme_enqueue(priv, SME_GET_MAC_ADDRESS); |
561 | memcpy(priv->eth_addr, priv->rxp, ETH_ALEN); | |
562 | priv->mac_address_valid = 1; | |
563 | dev->dev_addr[0] = priv->eth_addr[0]; | |
564 | dev->dev_addr[1] = priv->eth_addr[1]; | |
565 | dev->dev_addr[2] = priv->eth_addr[2]; | |
566 | dev->dev_addr[3] = priv->eth_addr[3]; | |
567 | dev->dev_addr[4] = priv->eth_addr[4]; | |
568 | dev->dev_addr[5] = priv->eth_addr[5]; | |
569 | dev->dev_addr[6] = 0x00; | |
570 | dev->dev_addr[7] = 0x00; | |
20c4f9c5 WS |
571 | printk(KERN_INFO |
572 | "ks_wlan: MAC ADDRESS = %02x:%02x:%02x:%02x:%02x:%02x\n", | |
573 | priv->eth_addr[0], priv->eth_addr[1], priv->eth_addr[2], | |
574 | priv->eth_addr[3], priv->eth_addr[4], priv->eth_addr[5]); | |
13a9930d WS |
575 | break; |
576 | case DOT11_PRODUCT_VERSION: | |
577 | /* firmware version */ | |
20c4f9c5 | 578 | DPRINTK(3, " mib_attribute=DOT11_PRODUCT_VERSION\n"); |
13a9930d WS |
579 | priv->version_size = priv->rx_size; |
580 | memcpy(priv->firmware_version, priv->rxp, priv->rx_size); | |
581 | priv->firmware_version[priv->rx_size] = '\0'; | |
20c4f9c5 WS |
582 | printk(KERN_INFO "ks_wlan: firmware ver. = %s\n", |
583 | priv->firmware_version); | |
13a9930d WS |
584 | hostif_sme_enqueue(priv, SME_GET_PRODUCT_VERSION); |
585 | /* wake_up_interruptible_all(&priv->confirm_wait); */ | |
586 | complete(&priv->confirm_wait); | |
587 | break; | |
588 | case LOCAL_GAIN: | |
589 | memcpy(&priv->gain, priv->rxp, sizeof(priv->gain)); | |
20c4f9c5 WS |
590 | DPRINTK(3, "TxMode=%d, RxMode=%d, TxGain=%d, RxGain=%d\n", |
591 | priv->gain.TxMode, priv->gain.RxMode, priv->gain.TxGain, | |
592 | priv->gain.RxGain); | |
13a9930d WS |
593 | break; |
594 | case LOCAL_EEPROM_SUM: | |
595 | memcpy(&priv->eeprom_sum, priv->rxp, sizeof(priv->eeprom_sum)); | |
20c4f9c5 WS |
596 | DPRINTK(1, "eeprom_sum.type=%x, eeprom_sum.result=%x\n", |
597 | priv->eeprom_sum.type, priv->eeprom_sum.result); | |
598 | if (priv->eeprom_sum.type == 0) { | |
13a9930d | 599 | priv->eeprom_checksum = EEPROM_CHECKSUM_NONE; |
20c4f9c5 WS |
600 | } else if (priv->eeprom_sum.type == 1) { |
601 | if (priv->eeprom_sum.result == 0) { | |
13a9930d WS |
602 | priv->eeprom_checksum = EEPROM_NG; |
603 | printk("LOCAL_EEPROM_SUM NG\n"); | |
20c4f9c5 | 604 | } else if (priv->eeprom_sum.result == 1) { |
13a9930d WS |
605 | priv->eeprom_checksum = EEPROM_OK; |
606 | } | |
20c4f9c5 | 607 | } else { |
13a9930d WS |
608 | printk("LOCAL_EEPROM_SUM error!\n"); |
609 | } | |
610 | break; | |
611 | default: | |
20c4f9c5 | 612 | DPRINTK(1, "mib_attribute=%08x\n", (unsigned int)mib_attribute); |
13a9930d WS |
613 | break; |
614 | } | |
615 | } | |
616 | ||
617 | static | |
feedcf1a | 618 | void hostif_mib_set_confirm(struct ks_wlan_private *priv) |
13a9930d | 619 | { |
20c4f9c5 WS |
620 | uint32_t mib_status; /* +04 MIB Status */ |
621 | uint32_t mib_attribute; /* +08 MIB attribute */ | |
13a9930d | 622 | |
20c4f9c5 | 623 | DPRINTK(3, "\n"); |
13a9930d | 624 | |
20c4f9c5 WS |
625 | mib_status = get_DWORD(priv); /* MIB Status */ |
626 | mib_attribute = get_DWORD(priv); /* MIB attribute */ | |
13a9930d WS |
627 | |
628 | if (mib_status != 0) { | |
629 | /* in case of error */ | |
20c4f9c5 WS |
630 | DPRINTK(1, "error :: attribute=%08X, status=%08X\n", |
631 | mib_attribute, mib_status); | |
13a9930d WS |
632 | } |
633 | ||
634 | switch (mib_attribute) { | |
635 | case DOT11_RTS_THRESHOLD: | |
636 | hostif_sme_enqueue(priv, SME_RTS_THRESHOLD_CONFIRM); | |
637 | break; | |
638 | case DOT11_FRAGMENTATION_THRESHOLD: | |
639 | hostif_sme_enqueue(priv, SME_FRAGMENTATION_THRESHOLD_CONFIRM); | |
640 | break; | |
641 | case DOT11_WEP_DEFAULT_KEY_ID: | |
20c4f9c5 | 642 | if (!priv->wpa.wpa_enabled) |
13a9930d WS |
643 | hostif_sme_enqueue(priv, SME_WEP_INDEX_CONFIRM); |
644 | break; | |
645 | case DOT11_WEP_DEFAULT_KEY_VALUE1: | |
20c4f9c5 WS |
646 | DPRINTK(2, "DOT11_WEP_DEFAULT_KEY_VALUE1:mib_status=%d\n", |
647 | (int)mib_status); | |
648 | if (priv->wpa.rsn_enabled) | |
13a9930d WS |
649 | hostif_sme_enqueue(priv, SME_SET_PMK_TSC); |
650 | else | |
651 | hostif_sme_enqueue(priv, SME_WEP_KEY1_CONFIRM); | |
652 | break; | |
653 | case DOT11_WEP_DEFAULT_KEY_VALUE2: | |
20c4f9c5 WS |
654 | DPRINTK(2, "DOT11_WEP_DEFAULT_KEY_VALUE2:mib_status=%d\n", |
655 | (int)mib_status); | |
656 | if (priv->wpa.rsn_enabled) | |
13a9930d WS |
657 | hostif_sme_enqueue(priv, SME_SET_GMK1_TSC); |
658 | else | |
659 | hostif_sme_enqueue(priv, SME_WEP_KEY2_CONFIRM); | |
660 | break; | |
661 | case DOT11_WEP_DEFAULT_KEY_VALUE3: | |
20c4f9c5 WS |
662 | DPRINTK(2, "DOT11_WEP_DEFAULT_KEY_VALUE3:mib_status=%d\n", |
663 | (int)mib_status); | |
664 | if (priv->wpa.rsn_enabled) | |
13a9930d WS |
665 | hostif_sme_enqueue(priv, SME_SET_GMK2_TSC); |
666 | else | |
667 | hostif_sme_enqueue(priv, SME_WEP_KEY3_CONFIRM); | |
668 | break; | |
669 | case DOT11_WEP_DEFAULT_KEY_VALUE4: | |
20c4f9c5 WS |
670 | DPRINTK(2, "DOT11_WEP_DEFAULT_KEY_VALUE4:mib_status=%d\n", |
671 | (int)mib_status); | |
672 | if (!priv->wpa.rsn_enabled) | |
13a9930d WS |
673 | hostif_sme_enqueue(priv, SME_WEP_KEY4_CONFIRM); |
674 | break; | |
675 | case DOT11_PRIVACY_INVOKED: | |
20c4f9c5 | 676 | if (!priv->wpa.rsn_enabled) |
13a9930d WS |
677 | hostif_sme_enqueue(priv, SME_WEP_FLAG_CONFIRM); |
678 | break; | |
679 | case DOT11_RSN_ENABLED: | |
20c4f9c5 WS |
680 | DPRINTK(2, "DOT11_RSN_ENABLED:mib_status=%d\n", |
681 | (int)mib_status); | |
13a9930d WS |
682 | hostif_sme_enqueue(priv, SME_RSN_ENABLED_CONFIRM); |
683 | break; | |
684 | case LOCAL_RSN_MODE: | |
685 | hostif_sme_enqueue(priv, SME_RSN_MODE_CONFIRM); | |
686 | break; | |
687 | case LOCAL_MULTICAST_ADDRESS: | |
688 | hostif_sme_enqueue(priv, SME_MULTICAST_REQUEST); | |
689 | break; | |
690 | case LOCAL_MULTICAST_FILTER: | |
691 | hostif_sme_enqueue(priv, SME_MULTICAST_CONFIRM); | |
692 | break; | |
693 | case LOCAL_CURRENTADDRESS: | |
694 | priv->mac_address_valid = 1; | |
695 | break; | |
696 | case DOT11_RSN_CONFIG_MULTICAST_CIPHER: | |
20c4f9c5 WS |
697 | DPRINTK(2, "DOT11_RSN_CONFIG_MULTICAST_CIPHER:mib_status=%d\n", |
698 | (int)mib_status); | |
13a9930d WS |
699 | hostif_sme_enqueue(priv, SME_RSN_MCAST_CONFIRM); |
700 | break; | |
701 | case DOT11_RSN_CONFIG_UNICAST_CIPHER: | |
20c4f9c5 WS |
702 | DPRINTK(2, "DOT11_RSN_CONFIG_UNICAST_CIPHER:mib_status=%d\n", |
703 | (int)mib_status); | |
13a9930d WS |
704 | hostif_sme_enqueue(priv, SME_RSN_UCAST_CONFIRM); |
705 | break; | |
706 | case DOT11_RSN_CONFIG_AUTH_SUITE: | |
20c4f9c5 WS |
707 | DPRINTK(2, "DOT11_RSN_CONFIG_AUTH_SUITE:mib_status=%d\n", |
708 | (int)mib_status); | |
13a9930d WS |
709 | hostif_sme_enqueue(priv, SME_RSN_AUTH_CONFIRM); |
710 | break; | |
711 | case DOT11_PMK_TSC: | |
20c4f9c5 | 712 | DPRINTK(2, "DOT11_PMK_TSC:mib_status=%d\n", (int)mib_status); |
13a9930d WS |
713 | break; |
714 | case DOT11_GMK1_TSC: | |
20c4f9c5 WS |
715 | DPRINTK(2, "DOT11_GMK1_TSC:mib_status=%d\n", (int)mib_status); |
716 | if (atomic_read(&priv->psstatus.snooze_guard)) { | |
13a9930d WS |
717 | atomic_set(&priv->psstatus.snooze_guard, 0); |
718 | } | |
719 | break; | |
720 | case DOT11_GMK2_TSC: | |
20c4f9c5 WS |
721 | DPRINTK(2, "DOT11_GMK2_TSC:mib_status=%d\n", (int)mib_status); |
722 | if (atomic_read(&priv->psstatus.snooze_guard)) { | |
13a9930d WS |
723 | atomic_set(&priv->psstatus.snooze_guard, 0); |
724 | } | |
725 | break; | |
726 | case LOCAL_PMK: | |
20c4f9c5 | 727 | DPRINTK(2, "LOCAL_PMK:mib_status=%d\n", (int)mib_status); |
13a9930d WS |
728 | break; |
729 | case LOCAL_GAIN: | |
20c4f9c5 | 730 | DPRINTK(2, "LOCAL_GAIN:mib_status=%d\n", (int)mib_status); |
13a9930d WS |
731 | break; |
732 | #ifdef WPS | |
733 | case LOCAL_WPS_ENABLE: | |
20c4f9c5 | 734 | DPRINTK(2, "LOCAL_WPS_ENABLE:mib_status=%d\n", (int)mib_status); |
13a9930d WS |
735 | break; |
736 | case LOCAL_WPS_PROBE_REQ: | |
20c4f9c5 WS |
737 | DPRINTK(2, "LOCAL_WPS_PROBE_REQ:mib_status=%d\n", |
738 | (int)mib_status); | |
13a9930d WS |
739 | break; |
740 | #endif /* WPS */ | |
741 | case LOCAL_REGION: | |
20c4f9c5 WS |
742 | DPRINTK(2, "LOCAL_REGION:mib_status=%d\n", (int)mib_status); |
743 | default: | |
13a9930d WS |
744 | break; |
745 | } | |
746 | } | |
747 | ||
748 | static | |
feedcf1a | 749 | void hostif_power_mngmt_confirm(struct ks_wlan_private *priv) |
13a9930d | 750 | { |
20c4f9c5 | 751 | DPRINTK(3, "\n"); |
13a9930d | 752 | |
20c4f9c5 WS |
753 | if (priv->reg.powermgt > POWMGT_ACTIVE_MODE && |
754 | priv->reg.operation_mode == MODE_INFRASTRUCTURE) { | |
13a9930d WS |
755 | atomic_set(&priv->psstatus.confirm_wait, 0); |
756 | priv->dev_state = DEVICE_STATE_SLEEP; | |
757 | ks_wlan_hw_power_save(priv); | |
20c4f9c5 | 758 | } else { |
13a9930d | 759 | priv->dev_state = DEVICE_STATE_READY; |
13a9930d WS |
760 | } |
761 | ||
762 | } | |
763 | ||
764 | static | |
feedcf1a | 765 | void hostif_sleep_confirm(struct ks_wlan_private *priv) |
13a9930d | 766 | { |
20c4f9c5 | 767 | DPRINTK(3, "\n"); |
13a9930d | 768 | |
20c4f9c5 WS |
769 | atomic_set(&priv->sleepstatus.doze_request, 1); |
770 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq, | |
771 | &priv->ks_wlan_hw.rw_wq, 1); | |
13a9930d WS |
772 | } |
773 | ||
774 | static | |
feedcf1a | 775 | void hostif_start_confirm(struct ks_wlan_private *priv) |
13a9930d WS |
776 | { |
777 | #ifdef WPS | |
20c4f9c5 WS |
778 | union iwreq_data wrqu; |
779 | wrqu.data.length = 0; | |
780 | wrqu.data.flags = 0; | |
781 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | |
782 | if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { | |
783 | memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); | |
784 | DPRINTK(3, "IWEVENT: disconnect\n"); | |
785 | wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); | |
786 | } | |
13a9930d | 787 | #endif |
20c4f9c5 | 788 | DPRINTK(3, " scan_ind_count=%d\n", priv->scan_ind_count); |
13a9930d WS |
789 | hostif_sme_enqueue(priv, SME_START_CONFIRM); |
790 | } | |
791 | ||
792 | static | |
feedcf1a | 793 | void hostif_connect_indication(struct ks_wlan_private *priv) |
13a9930d WS |
794 | { |
795 | unsigned short connect_code; | |
20c4f9c5 WS |
796 | unsigned int tmp = 0; |
797 | unsigned int old_status = priv->connect_status; | |
798 | struct net_device *netdev = priv->net_dev; | |
13a9930d | 799 | union iwreq_data wrqu0; |
13a9930d WS |
800 | connect_code = get_WORD(priv); |
801 | ||
20c4f9c5 WS |
802 | switch (connect_code) { |
803 | case RESULT_CONNECT: /* connect */ | |
804 | DPRINTK(3, "connect :: scan_ind_count=%d\n", | |
805 | priv->scan_ind_count); | |
806 | if (!(priv->connect_status & FORCE_DISCONNECT)) | |
13a9930d WS |
807 | netif_carrier_on(netdev); |
808 | tmp = FORCE_DISCONNECT & priv->connect_status; | |
809 | priv->connect_status = tmp + CONNECT_STATUS; | |
810 | break; | |
20c4f9c5 WS |
811 | case RESULT_DISCONNECT: /* disconnect */ |
812 | DPRINTK(3, "disconnect :: scan_ind_count=%d\n", | |
813 | priv->scan_ind_count); | |
13a9930d WS |
814 | netif_carrier_off(netdev); |
815 | tmp = FORCE_DISCONNECT & priv->connect_status; | |
816 | priv->connect_status = tmp + DISCONNECT_STATUS; | |
817 | break; | |
818 | default: | |
20c4f9c5 WS |
819 | DPRINTK(1, "unknown connect_code=%d :: scan_ind_count=%d\n", |
820 | connect_code, priv->scan_ind_count); | |
13a9930d WS |
821 | netif_carrier_off(netdev); |
822 | tmp = FORCE_DISCONNECT & priv->connect_status; | |
823 | priv->connect_status = tmp + DISCONNECT_STATUS; | |
824 | break; | |
825 | } | |
826 | ||
827 | get_current_ap(priv, (struct link_ap_info_t *)priv->rxp); | |
20c4f9c5 WS |
828 | if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS && |
829 | (old_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS) { | |
13a9930d WS |
830 | /* for power save */ |
831 | atomic_set(&priv->psstatus.snooze_guard, 0); | |
20c4f9c5 | 832 | atomic_set(&priv->psstatus.confirm_wait, 0); |
13a9930d WS |
833 | } |
834 | ks_wlan_do_power_save(priv); | |
835 | ||
13a9930d WS |
836 | wrqu0.data.length = 0; |
837 | wrqu0.data.flags = 0; | |
838 | wrqu0.ap_addr.sa_family = ARPHRD_ETHER; | |
20c4f9c5 WS |
839 | if ((priv->connect_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS && |
840 | (old_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { | |
13a9930d | 841 | memset(wrqu0.ap_addr.sa_data, '\0', ETH_ALEN); |
20c4f9c5 WS |
842 | DPRINTK(3, "IWEVENT: disconnect\n"); |
843 | DPRINTK(3, "disconnect :: scan_ind_count=%d\n", | |
844 | priv->scan_ind_count); | |
13a9930d WS |
845 | wireless_send_event(netdev, SIOCGIWAP, &wrqu0, NULL); |
846 | } | |
20c4f9c5 | 847 | priv->scan_ind_count = 0; |
13a9930d WS |
848 | } |
849 | ||
850 | static | |
feedcf1a | 851 | void hostif_scan_indication(struct ks_wlan_private *priv) |
13a9930d WS |
852 | { |
853 | int i; | |
854 | struct ap_info_t *ap_info; | |
855 | ||
20c4f9c5 | 856 | DPRINTK(3, "scan_ind_count = %d\n", priv->scan_ind_count); |
13a9930d WS |
857 | ap_info = (struct ap_info_t *)(priv->rxp); |
858 | ||
20c4f9c5 WS |
859 | if (priv->scan_ind_count != 0) { |
860 | for (i = 0; i < priv->aplist.size; i++) { /* bssid check */ | |
861 | if (!memcmp | |
862 | (&(ap_info->bssid[0]), | |
863 | &(priv->aplist.ap[i].bssid[0]), ETH_ALEN)) { | |
864 | if (ap_info->frame_type == | |
865 | FRAME_TYPE_PROBE_RESP) | |
866 | get_ap_information(priv, ap_info, | |
867 | &(priv->aplist. | |
868 | ap[i])); | |
13a9930d WS |
869 | return; |
870 | } | |
871 | } | |
872 | } | |
873 | priv->scan_ind_count++; | |
20c4f9c5 WS |
874 | if (priv->scan_ind_count < LOCAL_APLIST_MAX + 1) { |
875 | DPRINTK(4, " scan_ind_count=%d :: aplist.size=%d\n", | |
876 | priv->scan_ind_count, priv->aplist.size); | |
877 | get_ap_information(priv, (struct ap_info_t *)(priv->rxp), | |
878 | &(priv->aplist. | |
879 | ap[priv->scan_ind_count - 1])); | |
13a9930d | 880 | priv->aplist.size = priv->scan_ind_count; |
20c4f9c5 WS |
881 | } else { |
882 | DPRINTK(4, " count over :: scan_ind_count=%d\n", | |
883 | priv->scan_ind_count); | |
13a9930d | 884 | } |
13a9930d WS |
885 | |
886 | } | |
887 | ||
888 | static | |
feedcf1a | 889 | void hostif_stop_confirm(struct ks_wlan_private *priv) |
13a9930d | 890 | { |
20c4f9c5 WS |
891 | unsigned int tmp = 0; |
892 | unsigned int old_status = priv->connect_status; | |
893 | struct net_device *netdev = priv->net_dev; | |
13a9930d WS |
894 | union iwreq_data wrqu0; |
895 | ||
20c4f9c5 WS |
896 | DPRINTK(3, "\n"); |
897 | if (priv->dev_state == DEVICE_STATE_SLEEP) | |
13a9930d | 898 | priv->dev_state = DEVICE_STATE_READY; |
13a9930d WS |
899 | |
900 | /* disconnect indication */ | |
20c4f9c5 | 901 | if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { |
13a9930d WS |
902 | netif_carrier_off(netdev); |
903 | tmp = FORCE_DISCONNECT & priv->connect_status; | |
904 | priv->connect_status = tmp | DISCONNECT_STATUS; | |
905 | printk("IWEVENT: disconnect\n"); | |
906 | ||
907 | wrqu0.data.length = 0; | |
908 | wrqu0.data.flags = 0; | |
909 | wrqu0.ap_addr.sa_family = ARPHRD_ETHER; | |
20c4f9c5 WS |
910 | if ((priv->connect_status & CONNECT_STATUS_MASK) == |
911 | DISCONNECT_STATUS | |
912 | && (old_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { | |
13a9930d | 913 | memset(wrqu0.ap_addr.sa_data, '\0', ETH_ALEN); |
20c4f9c5 | 914 | DPRINTK(3, "IWEVENT: disconnect\n"); |
13a9930d | 915 | printk("IWEVENT: disconnect\n"); |
20c4f9c5 WS |
916 | DPRINTK(3, "disconnect :: scan_ind_count=%d\n", |
917 | priv->scan_ind_count); | |
13a9930d WS |
918 | wireless_send_event(netdev, SIOCGIWAP, &wrqu0, NULL); |
919 | } | |
20c4f9c5 | 920 | priv->scan_ind_count = 0; |
13a9930d WS |
921 | } |
922 | ||
923 | hostif_sme_enqueue(priv, SME_STOP_CONFIRM); | |
924 | } | |
925 | ||
926 | static | |
feedcf1a | 927 | void hostif_ps_adhoc_set_confirm(struct ks_wlan_private *priv) |
13a9930d | 928 | { |
20c4f9c5 WS |
929 | DPRINTK(3, "\n"); |
930 | priv->infra_status = 0; /* infrastructure mode cancel */ | |
13a9930d WS |
931 | hostif_sme_enqueue(priv, SME_MODE_SET_CONFIRM); |
932 | ||
933 | } | |
934 | ||
935 | static | |
feedcf1a | 936 | void hostif_infrastructure_set_confirm(struct ks_wlan_private *priv) |
13a9930d WS |
937 | { |
938 | uint16_t result_code; | |
20c4f9c5 | 939 | DPRINTK(3, "\n"); |
13a9930d | 940 | result_code = get_WORD(priv); |
20c4f9c5 WS |
941 | DPRINTK(3, "result code = %d\n", result_code); |
942 | priv->infra_status = 1; /* infrastructure mode set */ | |
13a9930d WS |
943 | hostif_sme_enqueue(priv, SME_MODE_SET_CONFIRM); |
944 | } | |
945 | ||
946 | static | |
feedcf1a | 947 | void hostif_adhoc_set_confirm(struct ks_wlan_private *priv) |
13a9930d | 948 | { |
20c4f9c5 WS |
949 | DPRINTK(3, "\n"); |
950 | priv->infra_status = 1; /* infrastructure mode set */ | |
13a9930d WS |
951 | hostif_sme_enqueue(priv, SME_MODE_SET_CONFIRM); |
952 | } | |
953 | ||
954 | static | |
feedcf1a | 955 | void hostif_associate_indication(struct ks_wlan_private *priv) |
13a9930d | 956 | { |
13a9930d WS |
957 | struct association_request_t *assoc_req; |
958 | struct association_response_t *assoc_resp; | |
959 | unsigned char *pb; | |
960 | union iwreq_data wrqu; | |
961 | char buf[IW_CUSTOM_MAX]; | |
962 | char *pbuf = &buf[0]; | |
963 | int i; | |
964 | ||
965 | static const char associnfo_leader0[] = "ASSOCINFO(ReqIEs="; | |
966 | static const char associnfo_leader1[] = " RespIEs="; | |
967 | ||
20c4f9c5 | 968 | DPRINTK(3, "\n"); |
13a9930d | 969 | assoc_req = (struct association_request_t *)(priv->rxp); |
20c4f9c5 WS |
970 | assoc_resp = (struct association_response_t *)(assoc_req + 1); |
971 | pb = (unsigned char *)(assoc_resp + 1); | |
13a9930d WS |
972 | |
973 | memset(&wrqu, 0, sizeof(wrqu)); | |
20c4f9c5 WS |
974 | memcpy(pbuf, associnfo_leader0, sizeof(associnfo_leader0) - 1); |
975 | wrqu.data.length += sizeof(associnfo_leader0) - 1; | |
976 | pbuf += sizeof(associnfo_leader0) - 1; | |
13a9930d WS |
977 | |
978 | for (i = 0; i < assoc_req->reqIEs_size; i++) | |
20c4f9c5 WS |
979 | pbuf += sprintf(pbuf, "%02x", *(pb + i)); |
980 | wrqu.data.length += (assoc_req->reqIEs_size) * 2; | |
13a9930d | 981 | |
20c4f9c5 WS |
982 | memcpy(pbuf, associnfo_leader1, sizeof(associnfo_leader1) - 1); |
983 | wrqu.data.length += sizeof(associnfo_leader1) - 1; | |
984 | pbuf += sizeof(associnfo_leader1) - 1; | |
13a9930d WS |
985 | |
986 | pb += assoc_req->reqIEs_size; | |
987 | for (i = 0; i < assoc_resp->respIEs_size; i++) | |
20c4f9c5 WS |
988 | pbuf += sprintf(pbuf, "%02x", *(pb + i)); |
989 | wrqu.data.length += (assoc_resp->respIEs_size) * 2; | |
13a9930d WS |
990 | |
991 | pbuf += sprintf(pbuf, ")"); | |
992 | wrqu.data.length += 1; | |
993 | ||
20c4f9c5 | 994 | DPRINTK(3, "IWEVENT:ASSOCINFO\n"); |
13a9930d | 995 | wireless_send_event(priv->net_dev, IWEVCUSTOM, &wrqu, buf); |
13a9930d WS |
996 | } |
997 | ||
998 | static | |
feedcf1a | 999 | void hostif_bss_scan_confirm(struct ks_wlan_private *priv) |
13a9930d WS |
1000 | { |
1001 | unsigned int result_code; | |
13a9930d WS |
1002 | struct net_device *dev = priv->net_dev; |
1003 | union iwreq_data wrqu; | |
13a9930d | 1004 | result_code = get_DWORD(priv); |
20c4f9c5 WS |
1005 | DPRINTK(2, "result=%d :: scan_ind_count=%d\n", result_code, |
1006 | priv->scan_ind_count); | |
13a9930d WS |
1007 | |
1008 | priv->sme_i.sme_flag &= ~SME_AP_SCAN; | |
1009 | hostif_sme_enqueue(priv, SME_BSS_SCAN_CONFIRM); | |
1010 | ||
13a9930d WS |
1011 | wrqu.data.length = 0; |
1012 | wrqu.data.flags = 0; | |
20c4f9c5 | 1013 | DPRINTK(3, "IWEVENT: SCAN CONFIRM\n"); |
13a9930d | 1014 | wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); |
20c4f9c5 | 1015 | priv->scan_ind_count = 0; |
13a9930d WS |
1016 | } |
1017 | ||
1018 | static | |
feedcf1a | 1019 | void hostif_phy_information_confirm(struct ks_wlan_private *priv) |
13a9930d WS |
1020 | { |
1021 | struct iw_statistics *wstats = &priv->wstats; | |
20c4f9c5 | 1022 | unsigned char rssi, signal, noise; |
13a9930d WS |
1023 | unsigned char LinkSpeed; |
1024 | unsigned int TransmittedFrameCount, ReceivedFragmentCount; | |
1025 | unsigned int FailedCount, FCSErrorCount; | |
1026 | ||
20c4f9c5 | 1027 | DPRINTK(3, "\n"); |
13a9930d WS |
1028 | rssi = get_BYTE(priv); |
1029 | signal = get_BYTE(priv); | |
1030 | noise = get_BYTE(priv); | |
1031 | LinkSpeed = get_BYTE(priv); | |
1032 | TransmittedFrameCount = get_DWORD(priv); | |
1033 | ReceivedFragmentCount = get_DWORD(priv); | |
1034 | FailedCount = get_DWORD(priv); | |
1035 | FCSErrorCount = get_DWORD(priv); | |
1036 | ||
1037 | DPRINTK(4, "phyinfo confirm rssi=%d signal=%d\n", rssi, signal); | |
1038 | priv->current_rate = (LinkSpeed & RATE_MASK); | |
1039 | wstats->qual.qual = signal; | |
1040 | wstats->qual.level = 256 - rssi; | |
20c4f9c5 | 1041 | wstats->qual.noise = 0; /* invalid noise value */ |
13a9930d WS |
1042 | wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; |
1043 | ||
20c4f9c5 | 1044 | DPRINTK(3, "\n rssi=%u\n signal=%u\n LinkSpeed=%ux500Kbps\n \ |
13a9930d | 1045 | TransmittedFrameCount=%u\n ReceivedFragmentCount=%u\n FailedCount=%u\n \ |
20c4f9c5 | 1046 | FCSErrorCount=%u\n", rssi, signal, LinkSpeed, TransmittedFrameCount, ReceivedFragmentCount, FailedCount, FCSErrorCount); |
13a9930d WS |
1047 | |
1048 | /* wake_up_interruptible_all(&priv->confirm_wait); */ | |
1049 | complete(&priv->confirm_wait); | |
1050 | } | |
1051 | ||
1052 | static | |
feedcf1a | 1053 | void hostif_mic_failure_confirm(struct ks_wlan_private *priv) |
13a9930d | 1054 | { |
20c4f9c5 | 1055 | DPRINTK(3, "mic_failure=%u\n", priv->wpa.mic_failure.failure); |
13a9930d WS |
1056 | hostif_sme_enqueue(priv, SME_MIC_FAILURE_CONFIRM); |
1057 | } | |
1058 | ||
13a9930d | 1059 | static |
feedcf1a | 1060 | void hostif_event_check(struct ks_wlan_private *priv) |
13a9930d WS |
1061 | { |
1062 | unsigned short event; | |
1063 | ||
1064 | DPRINTK(4, "\n"); | |
20c4f9c5 | 1065 | event = get_WORD(priv); /* get event */ |
13a9930d WS |
1066 | switch (event) { |
1067 | case HIF_DATA_IND: | |
1068 | hostif_data_indication(priv); | |
1069 | break; | |
1070 | case HIF_MIB_GET_CONF: | |
1071 | hostif_mib_get_confirm(priv); | |
1072 | break; | |
1073 | case HIF_MIB_SET_CONF: | |
1074 | hostif_mib_set_confirm(priv); | |
1075 | break; | |
1076 | case HIF_POWERMGT_CONF: | |
1077 | hostif_power_mngmt_confirm(priv); | |
1078 | break; | |
1079 | case HIF_SLEEP_CONF: | |
1080 | hostif_sleep_confirm(priv); | |
1081 | break; | |
1082 | case HIF_START_CONF: | |
1083 | hostif_start_confirm(priv); | |
1084 | break; | |
1085 | case HIF_CONNECT_IND: | |
1086 | hostif_connect_indication(priv); | |
1087 | break; | |
1088 | case HIF_STOP_CONF: | |
1089 | hostif_stop_confirm(priv); | |
1090 | break; | |
1091 | case HIF_PS_ADH_SET_CONF: | |
1092 | hostif_ps_adhoc_set_confirm(priv); | |
1093 | break; | |
1094 | case HIF_INFRA_SET_CONF: | |
1095 | case HIF_INFRA_SET2_CONF: | |
1096 | hostif_infrastructure_set_confirm(priv); | |
1097 | break; | |
1098 | case HIF_ADH_SET_CONF: | |
1099 | case HIF_ADH_SET2_CONF: | |
1100 | hostif_adhoc_set_confirm(priv); | |
1101 | break; | |
1102 | case HIF_ASSOC_INFO_IND: | |
1103 | hostif_associate_indication(priv); | |
1104 | break; | |
1105 | case HIF_MIC_FAILURE_CONF: | |
1106 | hostif_mic_failure_confirm(priv); | |
1107 | break; | |
1108 | case HIF_SCAN_CONF: | |
1109 | hostif_bss_scan_confirm(priv); | |
1110 | break; | |
1111 | case HIF_PHY_INFO_CONF: | |
1112 | case HIF_PHY_INFO_IND: | |
1113 | hostif_phy_information_confirm(priv); | |
1114 | break; | |
1115 | case HIF_SCAN_IND: | |
1116 | hostif_scan_indication(priv); | |
1117 | break; | |
1118 | case HIF_AP_SET_CONF: | |
1119 | default: | |
1120 | //DPRINTK(1, "undefined event[%04X]\n", event); | |
1121 | printk("undefined event[%04X]\n", event); | |
1122 | /* wake_up_all(&priv->confirm_wait); */ | |
1123 | complete(&priv->confirm_wait); | |
1124 | break; | |
1125 | } | |
1126 | ||
1127 | /* add event to hostt buffer */ | |
1128 | priv->hostt.buff[priv->hostt.qtail] = event; | |
20c4f9c5 | 1129 | priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE; |
13a9930d WS |
1130 | } |
1131 | ||
1132 | #define CHECK_ALINE(size) (size%4 ? (size+(4-(size%4))):size) | |
1133 | ||
feedcf1a | 1134 | int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) |
13a9930d | 1135 | { |
20c4f9c5 | 1136 | unsigned int packet_len = 0; |
13a9930d | 1137 | |
20c4f9c5 WS |
1138 | unsigned char *buffer = NULL; |
1139 | unsigned int length = 0; | |
13a9930d | 1140 | struct hostif_data_request_t *pp; |
20c4f9c5 WS |
1141 | unsigned char *p; |
1142 | int result = 0; | |
13a9930d WS |
1143 | unsigned short eth_proto; |
1144 | struct ether_hdr *eth_hdr; | |
1145 | struct michel_mic_t michel_mic; | |
20c4f9c5 | 1146 | unsigned short keyinfo = 0; |
13a9930d WS |
1147 | struct ieee802_1x_hdr *aa1x_hdr; |
1148 | struct wpa_eapol_key *eap_key; | |
1149 | struct ethhdr *eth; | |
1150 | ||
1151 | packet_len = packet->len; | |
1152 | if (packet_len > ETH_FRAME_LEN) { | |
20c4f9c5 | 1153 | DPRINTK(1, "bad length packet_len=%d \n", packet_len); |
13a9930d WS |
1154 | dev_kfree_skb(packet); |
1155 | return -1; | |
1156 | } | |
1157 | ||
20c4f9c5 WS |
1158 | if (((priv->connect_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS) |
1159 | || (priv->connect_status & FORCE_DISCONNECT) | |
1160 | || priv->wpa.mic_failure.stop) { | |
1161 | DPRINTK(3, " DISCONNECT\n"); | |
1162 | if (netif_queue_stopped(priv->net_dev)) | |
13a9930d | 1163 | netif_wake_queue(priv->net_dev); |
20c4f9c5 | 1164 | if (packet) |
13a9930d WS |
1165 | dev_kfree_skb(packet); |
1166 | ||
1167 | return 0; | |
1168 | } | |
1169 | ||
1170 | /* for PowerSave */ | |
20c4f9c5 WS |
1171 | if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) { /* power save wakeup */ |
1172 | if (!netif_queue_stopped(priv->net_dev)) | |
13a9930d | 1173 | netif_stop_queue(priv->net_dev); |
13a9930d WS |
1174 | } |
1175 | ||
1176 | DPRINTK(4, "skb_buff length=%d\n", packet_len); | |
20c4f9c5 WS |
1177 | pp = (struct hostif_data_request_t *) |
1178 | kmalloc(hif_align_size(sizeof(*pp) + 6 + packet_len + 8), | |
1179 | KS_WLAN_MEM_FLAG); | |
13a9930d | 1180 | |
20c4f9c5 | 1181 | if (pp == NULL) { |
13a9930d WS |
1182 | DPRINTK(3, "allocate memory failed..\n"); |
1183 | dev_kfree_skb(packet); | |
1184 | return -2; | |
1185 | } | |
1186 | ||
1187 | p = (unsigned char *)pp->data; | |
1188 | ||
1189 | buffer = packet->data; | |
1190 | length = packet->len; | |
1191 | ||
1192 | /* packet check */ | |
1193 | eth = (struct ethhdr *)packet->data; | |
20c4f9c5 | 1194 | if (memcmp(&priv->eth_addr[0], eth->h_source, ETH_ALEN)) { |
13a9930d WS |
1195 | DPRINTK(1, "invalid mac address !!\n"); |
1196 | DPRINTK(1, "ethernet->h_source=%02X:%02X:%02X:%02X:%02X:%02X\n", | |
20c4f9c5 WS |
1197 | eth->h_source[0], eth->h_source[1], eth->h_source[2], |
1198 | eth->h_source[3], eth->h_source[4], eth->h_source[5]); | |
aeaf5d86 CIK |
1199 | dev_kfree_skb(packet); |
1200 | kfree(pp); | |
13a9930d WS |
1201 | return -3; |
1202 | } | |
1203 | ||
1204 | /* MAC address copy */ | |
20c4f9c5 | 1205 | memcpy(p, buffer, 12); /* DST/SRC MAC address */ |
13a9930d WS |
1206 | p += 12; |
1207 | buffer += 12; | |
1208 | length -= 12; | |
1209 | /* EtherType/Length check */ | |
20c4f9c5 | 1210 | if (*(buffer + 1) + (*buffer << 8) > 1500) { |
13a9930d | 1211 | /* ProtocolEAP = *(buffer+1) + (*buffer << 8); */ |
20c4f9c5 | 1212 | /* DPRINTK(2, "Send [SNAP]Type %x\n",ProtocolEAP); */ |
13a9930d | 1213 | /* SAP/CTL/OUI(6 byte) add */ |
20c4f9c5 WS |
1214 | *p++ = 0xAA; /* DSAP */ |
1215 | *p++ = 0xAA; /* SSAP */ | |
1216 | *p++ = 0x03; /* CTL */ | |
1217 | *p++ = 0x00; /* OUI ("000000") */ | |
1218 | *p++ = 0x00; /* OUI ("000000") */ | |
1219 | *p++ = 0x00; /* OUI ("000000") */ | |
13a9930d WS |
1220 | packet_len += 6; |
1221 | } else { | |
20c4f9c5 WS |
1222 | DPRINTK(4, "DIX\n"); |
1223 | /* Length(2 byte) delete */ | |
13a9930d WS |
1224 | buffer += 2; |
1225 | length -= 2; | |
1226 | packet_len -= 2; | |
1227 | } | |
1228 | ||
1229 | /* pp->data copy */ | |
1230 | memcpy(p, buffer, length); | |
1231 | ||
1232 | p += length; | |
1233 | ||
1234 | /* for WPA */ | |
1235 | eth_hdr = (struct ether_hdr *)&pp->data[0]; | |
1236 | eth_proto = ntohs(eth_hdr->h_proto); | |
1237 | ||
1238 | /* for MIC FAILUER REPORT check */ | |
20c4f9c5 WS |
1239 | if (eth_proto == ETHER_PROTOCOL_TYPE_EAP |
1240 | && priv->wpa.mic_failure.failure > 0) { | |
1241 | aa1x_hdr = (struct ieee802_1x_hdr *)(eth_hdr + 1); | |
1242 | if (aa1x_hdr->type == IEEE802_1X_TYPE_EAPOL_KEY) { | |
1243 | eap_key = (struct wpa_eapol_key *)(aa1x_hdr + 1); | |
1244 | keyinfo = ntohs(eap_key->key_info); | |
13a9930d WS |
1245 | } |
1246 | } | |
1247 | ||
20c4f9c5 WS |
1248 | if (priv->wpa.rsn_enabled && priv->wpa.key[0].key_len) { |
1249 | if (eth_proto == ETHER_PROTOCOL_TYPE_EAP | |
1250 | && !(priv->wpa.key[1].key_len) | |
1251 | && !(priv->wpa.key[2].key_len) | |
1252 | && !(priv->wpa.key[3].key_len)) { | |
1253 | pp->auth_type = cpu_to_le16((uint16_t) TYPE_AUTH); /* no encryption */ | |
1254 | } else { | |
1255 | if (priv->wpa.pairwise_suite == IW_AUTH_CIPHER_TKIP) { | |
1256 | MichaelMICFunction(&michel_mic, (uint8_t *) priv->wpa.key[0].tx_mic_key, (uint8_t *) & pp->data[0], (int)packet_len, (uint8_t) 0, /* priority */ | |
1257 | (uint8_t *) michel_mic. | |
1258 | Result); | |
13a9930d WS |
1259 | memcpy(p, michel_mic.Result, 8); |
1260 | length += 8; | |
1261 | packet_len += 8; | |
1262 | p += 8; | |
20c4f9c5 WS |
1263 | pp->auth_type = |
1264 | cpu_to_le16((uint16_t) TYPE_DATA); | |
13a9930d | 1265 | |
20c4f9c5 WS |
1266 | } else if (priv->wpa.pairwise_suite == |
1267 | IW_AUTH_CIPHER_CCMP) { | |
1268 | pp->auth_type = | |
1269 | cpu_to_le16((uint16_t) TYPE_DATA); | |
13a9930d WS |
1270 | } |
1271 | } | |
20c4f9c5 WS |
1272 | } else { |
1273 | if (eth_proto == ETHER_PROTOCOL_TYPE_EAP) | |
1274 | pp->auth_type = cpu_to_le16((uint16_t) TYPE_AUTH); | |
13a9930d | 1275 | else |
20c4f9c5 | 1276 | pp->auth_type = cpu_to_le16((uint16_t) TYPE_DATA); |
13a9930d WS |
1277 | } |
1278 | ||
1279 | /* header value set */ | |
20c4f9c5 WS |
1280 | pp->header.size = |
1281 | cpu_to_le16((uint16_t) | |
1282 | (sizeof(*pp) - sizeof(pp->header.size) + packet_len)); | |
1283 | pp->header.event = cpu_to_le16((uint16_t) HIF_DATA_REQ); | |
13a9930d WS |
1284 | |
1285 | /* tx request */ | |
20c4f9c5 WS |
1286 | result = |
1287 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp) + packet_len), | |
1288 | (void *)send_packet_complete, (void *)priv, | |
1289 | (void *)packet); | |
13a9930d WS |
1290 | |
1291 | /* MIC FAILUER REPORT check */ | |
20c4f9c5 WS |
1292 | if (eth_proto == ETHER_PROTOCOL_TYPE_EAP |
1293 | && priv->wpa.mic_failure.failure > 0) { | |
1294 | if (keyinfo & WPA_KEY_INFO_ERROR | |
1295 | && keyinfo & WPA_KEY_INFO_REQUEST) { | |
1296 | DPRINTK(3, " MIC ERROR Report SET : %04X\n", keyinfo); | |
13a9930d WS |
1297 | hostif_sme_enqueue(priv, SME_MIC_FAILURE_REQUEST); |
1298 | } | |
20c4f9c5 WS |
1299 | if (priv->wpa.mic_failure.failure == 2) |
1300 | priv->wpa.mic_failure.stop = 1; | |
13a9930d WS |
1301 | } |
1302 | ||
1303 | return result; | |
1304 | } | |
1305 | ||
13a9930d WS |
1306 | #define ps_confirm_wait_inc(priv) do{if(atomic_read(&priv->psstatus.status) > PS_ACTIVE_SET){ \ |
1307 | atomic_inc(&priv->psstatus.confirm_wait); \ | |
1308 | /* atomic_set(&priv->psstatus.status, PS_CONF_WAIT);*/ \ | |
1309 | } }while(0) | |
13a9930d WS |
1310 | |
1311 | static | |
20c4f9c5 WS |
1312 | void hostif_mib_get_request(struct ks_wlan_private *priv, |
1313 | unsigned long mib_attribute) | |
13a9930d WS |
1314 | { |
1315 | struct hostif_mib_get_request_t *pp; | |
1316 | ||
1317 | DPRINTK(3, "\n"); | |
1318 | ||
1319 | /* make primitive */ | |
20c4f9c5 WS |
1320 | pp = (struct hostif_mib_get_request_t *) |
1321 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1322 | if (pp == NULL) { | |
1323 | DPRINTK(3, "allocate memory failed..\n"); | |
13a9930d WS |
1324 | return; |
1325 | } | |
20c4f9c5 WS |
1326 | pp->header.size = |
1327 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1328 | pp->header.event = cpu_to_le16((uint16_t) HIF_MIB_GET_REQ); | |
1329 | pp->mib_attribute = cpu_to_le32((uint32_t) mib_attribute); | |
13a9930d WS |
1330 | |
1331 | /* send to device request */ | |
1332 | ps_confirm_wait_inc(priv); | |
20c4f9c5 | 1333 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
13a9930d WS |
1334 | } |
1335 | ||
1336 | static | |
20c4f9c5 WS |
1337 | void hostif_mib_set_request(struct ks_wlan_private *priv, |
1338 | unsigned long mib_attribute, unsigned short size, | |
1339 | unsigned short type, void *vp) | |
13a9930d WS |
1340 | { |
1341 | struct hostif_mib_set_request_t *pp; | |
1342 | ||
20c4f9c5 | 1343 | DPRINTK(3, "\n"); |
13a9930d WS |
1344 | |
1345 | if (priv->dev_state < DEVICE_STATE_BOOT) { | |
20c4f9c5 | 1346 | DPRINTK(3, "DeviceRemove\n"); |
13a9930d WS |
1347 | return; |
1348 | } | |
1349 | ||
1350 | /* make primitive */ | |
20c4f9c5 WS |
1351 | pp = (struct hostif_mib_set_request_t *) |
1352 | kmalloc(hif_align_size(sizeof(*pp) + size), KS_WLAN_MEM_FLAG); | |
1353 | if (pp == NULL) { | |
13a9930d WS |
1354 | DPRINTK(3, "allocate memory failed..\n"); |
1355 | return; | |
1356 | } | |
1357 | ||
20c4f9c5 WS |
1358 | pp->header.size = |
1359 | cpu_to_le16((uint16_t) | |
1360 | (sizeof(*pp) - sizeof(pp->header.size) + size)); | |
1361 | pp->header.event = cpu_to_le16((uint16_t) HIF_MIB_SET_REQ); | |
1362 | pp->mib_attribute = cpu_to_le32((uint32_t) mib_attribute); | |
1363 | pp->mib_value.size = cpu_to_le16((uint16_t) size); | |
1364 | pp->mib_value.type = cpu_to_le16((uint16_t) type); | |
13a9930d WS |
1365 | memcpy(&pp->mib_value.body, vp, size); |
1366 | ||
1367 | /* send to device request */ | |
1368 | ps_confirm_wait_inc(priv); | |
20c4f9c5 WS |
1369 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp) + size), NULL, NULL, |
1370 | NULL); | |
13a9930d WS |
1371 | } |
1372 | ||
1373 | static | |
20c4f9c5 | 1374 | void hostif_start_request(struct ks_wlan_private *priv, unsigned char mode) |
13a9930d WS |
1375 | { |
1376 | struct hostif_start_request_t *pp; | |
1377 | ||
20c4f9c5 | 1378 | DPRINTK(3, "\n"); |
13a9930d WS |
1379 | |
1380 | /* make primitive */ | |
20c4f9c5 WS |
1381 | pp = (struct hostif_start_request_t *) |
1382 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1383 | if (pp == NULL) { | |
13a9930d WS |
1384 | DPRINTK(3, "allocate memory failed..\n"); |
1385 | return; | |
1386 | } | |
20c4f9c5 WS |
1387 | pp->header.size = |
1388 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1389 | pp->header.event = cpu_to_le16((uint16_t) HIF_START_REQ); | |
1390 | pp->mode = cpu_to_le16((uint16_t) mode); | |
13a9930d WS |
1391 | |
1392 | /* send to device request */ | |
1393 | ps_confirm_wait_inc(priv); | |
1394 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); | |
1395 | ||
1396 | priv->aplist.size = 0; | |
20c4f9c5 | 1397 | priv->scan_ind_count = 0; |
13a9930d WS |
1398 | } |
1399 | ||
1400 | static | |
feedcf1a | 1401 | void hostif_ps_adhoc_set_request(struct ks_wlan_private *priv) |
13a9930d WS |
1402 | { |
1403 | struct hostif_ps_adhoc_set_request_t *pp; | |
1404 | uint16_t capability; | |
1405 | ||
20c4f9c5 | 1406 | DPRINTK(3, "\n"); |
13a9930d WS |
1407 | |
1408 | /* make primitive */ | |
20c4f9c5 WS |
1409 | pp = (struct hostif_ps_adhoc_set_request_t *) |
1410 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1411 | if (pp == NULL) { | |
13a9930d WS |
1412 | DPRINTK(3, "allocate memory failed..\n"); |
1413 | return; | |
1414 | } | |
1415 | memset(pp, 0, sizeof(*pp)); | |
20c4f9c5 WS |
1416 | pp->header.size = |
1417 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1418 | pp->header.event = cpu_to_le16((uint16_t) HIF_PS_ADH_SET_REQ); | |
1419 | pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type)); | |
1420 | pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode)); | |
1421 | pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type)); | |
1422 | pp->channel = cpu_to_le16((uint16_t) (priv->reg.channel)); | |
13a9930d | 1423 | pp->rate_set.size = priv->reg.rate_set.size; |
20c4f9c5 WS |
1424 | memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0], |
1425 | priv->reg.rate_set.size); | |
13a9930d WS |
1426 | |
1427 | capability = 0x0000; | |
20c4f9c5 | 1428 | if (priv->reg.preamble == SHORT_PREAMBLE) { |
13a9930d WS |
1429 | /* short preamble */ |
1430 | capability |= BSS_CAP_SHORT_PREAMBLE; | |
1431 | } | |
20c4f9c5 WS |
1432 | capability &= ~(BSS_CAP_PBCC); /* pbcc not support */ |
1433 | if (priv->reg.phy_type != D_11B_ONLY_MODE) { | |
1434 | capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */ | |
1435 | capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM */ | |
13a9930d | 1436 | } |
20c4f9c5 | 1437 | pp->capability = cpu_to_le16((uint16_t) capability); |
13a9930d WS |
1438 | |
1439 | /* send to device request */ | |
1440 | ps_confirm_wait_inc(priv); | |
1441 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); | |
1442 | } | |
1443 | ||
1444 | static | |
feedcf1a | 1445 | void hostif_infrastructure_set_request(struct ks_wlan_private *priv) |
13a9930d WS |
1446 | { |
1447 | struct hostif_infrastructure_set_request_t *pp; | |
1448 | uint16_t capability; | |
1449 | ||
20c4f9c5 | 1450 | DPRINTK(3, "ssid.size=%d \n", priv->reg.ssid.size); |
13a9930d WS |
1451 | |
1452 | /* make primitive */ | |
20c4f9c5 WS |
1453 | pp = (struct hostif_infrastructure_set_request_t *) |
1454 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1455 | if (pp == NULL) { | |
13a9930d WS |
1456 | DPRINTK(3, "allocate memory failed..\n"); |
1457 | return; | |
1458 | } | |
20c4f9c5 WS |
1459 | pp->header.size = |
1460 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1461 | pp->header.event = cpu_to_le16((uint16_t) HIF_INFRA_SET_REQ); | |
1462 | pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type)); | |
1463 | pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode)); | |
1464 | pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type)); | |
13a9930d WS |
1465 | |
1466 | pp->rate_set.size = priv->reg.rate_set.size; | |
20c4f9c5 WS |
1467 | memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0], |
1468 | priv->reg.rate_set.size); | |
13a9930d WS |
1469 | pp->ssid.size = priv->reg.ssid.size; |
1470 | memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size); | |
1471 | ||
1472 | capability = 0x0000; | |
20c4f9c5 | 1473 | if (priv->reg.preamble == SHORT_PREAMBLE) { |
13a9930d WS |
1474 | /* short preamble */ |
1475 | capability |= BSS_CAP_SHORT_PREAMBLE; | |
1476 | } | |
20c4f9c5 WS |
1477 | capability &= ~(BSS_CAP_PBCC); /* pbcc not support */ |
1478 | if (priv->reg.phy_type != D_11B_ONLY_MODE) { | |
1479 | capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */ | |
1480 | capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */ | |
13a9930d | 1481 | } |
20c4f9c5 WS |
1482 | pp->capability = cpu_to_le16((uint16_t) capability); |
1483 | pp->beacon_lost_count = | |
1484 | cpu_to_le16((uint16_t) (priv->reg.beacon_lost_count)); | |
1485 | pp->auth_type = cpu_to_le16((uint16_t) (priv->reg.authenticate_type)); | |
13a9930d WS |
1486 | |
1487 | pp->channel_list.body[0] = 1; | |
1488 | pp->channel_list.body[1] = 8; | |
1489 | pp->channel_list.body[2] = 2; | |
1490 | pp->channel_list.body[3] = 9; | |
1491 | pp->channel_list.body[4] = 3; | |
1492 | pp->channel_list.body[5] = 10; | |
1493 | pp->channel_list.body[6] = 4; | |
1494 | pp->channel_list.body[7] = 11; | |
1495 | pp->channel_list.body[8] = 5; | |
1496 | pp->channel_list.body[9] = 12; | |
1497 | pp->channel_list.body[10] = 6; | |
1498 | pp->channel_list.body[11] = 13; | |
1499 | pp->channel_list.body[12] = 7; | |
20c4f9c5 | 1500 | if (priv->reg.phy_type == D_11G_ONLY_MODE) { |
13a9930d | 1501 | pp->channel_list.size = 13; |
20c4f9c5 | 1502 | } else { |
13a9930d WS |
1503 | pp->channel_list.body[13] = 14; |
1504 | pp->channel_list.size = 14; | |
1505 | } | |
1506 | ||
1507 | /* send to device request */ | |
1508 | ps_confirm_wait_inc(priv); | |
20c4f9c5 | 1509 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
13a9930d WS |
1510 | } |
1511 | ||
9afe11e9 | 1512 | static void hostif_infrastructure_set2_request(struct ks_wlan_private *priv) |
13a9930d WS |
1513 | { |
1514 | struct hostif_infrastructure_set2_request_t *pp; | |
1515 | uint16_t capability; | |
1516 | ||
20c4f9c5 | 1517 | DPRINTK(2, "ssid.size=%d \n", priv->reg.ssid.size); |
13a9930d WS |
1518 | |
1519 | /* make primitive */ | |
20c4f9c5 WS |
1520 | pp = (struct hostif_infrastructure_set2_request_t *) |
1521 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1522 | if (pp == NULL) { | |
13a9930d WS |
1523 | DPRINTK(3, "allocate memory failed..\n"); |
1524 | return; | |
1525 | } | |
20c4f9c5 WS |
1526 | pp->header.size = |
1527 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1528 | pp->header.event = cpu_to_le16((uint16_t) HIF_INFRA_SET2_REQ); | |
1529 | pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type)); | |
1530 | pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode)); | |
1531 | pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type)); | |
13a9930d WS |
1532 | |
1533 | pp->rate_set.size = priv->reg.rate_set.size; | |
20c4f9c5 WS |
1534 | memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0], |
1535 | priv->reg.rate_set.size); | |
13a9930d WS |
1536 | pp->ssid.size = priv->reg.ssid.size; |
1537 | memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size); | |
1538 | ||
1539 | capability = 0x0000; | |
20c4f9c5 | 1540 | if (priv->reg.preamble == SHORT_PREAMBLE) { |
13a9930d WS |
1541 | /* short preamble */ |
1542 | capability |= BSS_CAP_SHORT_PREAMBLE; | |
1543 | } | |
20c4f9c5 WS |
1544 | capability &= ~(BSS_CAP_PBCC); /* pbcc not support */ |
1545 | if (priv->reg.phy_type != D_11B_ONLY_MODE) { | |
1546 | capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */ | |
1547 | capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */ | |
13a9930d | 1548 | } |
20c4f9c5 WS |
1549 | pp->capability = cpu_to_le16((uint16_t) capability); |
1550 | pp->beacon_lost_count = | |
1551 | cpu_to_le16((uint16_t) (priv->reg.beacon_lost_count)); | |
1552 | pp->auth_type = cpu_to_le16((uint16_t) (priv->reg.authenticate_type)); | |
13a9930d WS |
1553 | |
1554 | pp->channel_list.body[0] = 1; | |
1555 | pp->channel_list.body[1] = 8; | |
1556 | pp->channel_list.body[2] = 2; | |
1557 | pp->channel_list.body[3] = 9; | |
1558 | pp->channel_list.body[4] = 3; | |
1559 | pp->channel_list.body[5] = 10; | |
1560 | pp->channel_list.body[6] = 4; | |
1561 | pp->channel_list.body[7] = 11; | |
1562 | pp->channel_list.body[8] = 5; | |
1563 | pp->channel_list.body[9] = 12; | |
1564 | pp->channel_list.body[10] = 6; | |
1565 | pp->channel_list.body[11] = 13; | |
1566 | pp->channel_list.body[12] = 7; | |
20c4f9c5 | 1567 | if (priv->reg.phy_type == D_11G_ONLY_MODE) { |
13a9930d | 1568 | pp->channel_list.size = 13; |
20c4f9c5 | 1569 | } else { |
13a9930d WS |
1570 | pp->channel_list.body[13] = 14; |
1571 | pp->channel_list.size = 14; | |
1572 | } | |
1573 | ||
1574 | memcpy(pp->bssid, priv->reg.bssid, ETH_ALEN); | |
1575 | ||
1576 | /* send to device request */ | |
1577 | ps_confirm_wait_inc(priv); | |
20c4f9c5 | 1578 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
13a9930d WS |
1579 | } |
1580 | ||
1581 | static | |
feedcf1a | 1582 | void hostif_adhoc_set_request(struct ks_wlan_private *priv) |
13a9930d WS |
1583 | { |
1584 | struct hostif_adhoc_set_request_t *pp; | |
1585 | uint16_t capability; | |
1586 | ||
1587 | DPRINTK(3, "\n"); | |
1588 | ||
1589 | /* make primitive */ | |
20c4f9c5 WS |
1590 | pp = (struct hostif_adhoc_set_request_t *) |
1591 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1592 | if (pp == NULL) { | |
13a9930d WS |
1593 | DPRINTK(3, "allocate memory failed..\n"); |
1594 | return; | |
1595 | } | |
1596 | memset(pp, 0, sizeof(*pp)); | |
20c4f9c5 WS |
1597 | pp->header.size = |
1598 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1599 | pp->header.event = cpu_to_le16((uint16_t) HIF_ADH_SET_REQ); | |
1600 | pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type)); | |
1601 | pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode)); | |
1602 | pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type)); | |
1603 | pp->channel = cpu_to_le16((uint16_t) (priv->reg.channel)); | |
13a9930d | 1604 | pp->rate_set.size = priv->reg.rate_set.size; |
20c4f9c5 WS |
1605 | memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0], |
1606 | priv->reg.rate_set.size); | |
13a9930d WS |
1607 | pp->ssid.size = priv->reg.ssid.size; |
1608 | memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size); | |
1609 | ||
1610 | capability = 0x0000; | |
20c4f9c5 | 1611 | if (priv->reg.preamble == SHORT_PREAMBLE) { |
13a9930d WS |
1612 | /* short preamble */ |
1613 | capability |= BSS_CAP_SHORT_PREAMBLE; | |
1614 | } | |
20c4f9c5 WS |
1615 | capability &= ~(BSS_CAP_PBCC); /* pbcc not support */ |
1616 | if (priv->reg.phy_type != D_11B_ONLY_MODE) { | |
1617 | capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */ | |
1618 | capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */ | |
13a9930d | 1619 | } |
20c4f9c5 | 1620 | pp->capability = cpu_to_le16((uint16_t) capability); |
13a9930d WS |
1621 | |
1622 | /* send to device request */ | |
1623 | ps_confirm_wait_inc(priv); | |
20c4f9c5 | 1624 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
13a9930d WS |
1625 | } |
1626 | ||
1627 | static | |
feedcf1a | 1628 | void hostif_adhoc_set2_request(struct ks_wlan_private *priv) |
13a9930d WS |
1629 | { |
1630 | struct hostif_adhoc_set2_request_t *pp; | |
1631 | uint16_t capability; | |
1632 | ||
1633 | DPRINTK(3, "\n"); | |
1634 | ||
1635 | /* make primitive */ | |
20c4f9c5 WS |
1636 | pp = (struct hostif_adhoc_set2_request_t *) |
1637 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1638 | if (pp == NULL) { | |
13a9930d WS |
1639 | DPRINTK(3, "allocate memory failed..\n"); |
1640 | return; | |
1641 | } | |
1642 | memset(pp, 0, sizeof(*pp)); | |
20c4f9c5 WS |
1643 | pp->header.size = |
1644 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1645 | pp->header.event = cpu_to_le16((uint16_t) HIF_ADH_SET_REQ); | |
1646 | pp->phy_type = cpu_to_le16((uint16_t) (priv->reg.phy_type)); | |
1647 | pp->cts_mode = cpu_to_le16((uint16_t) (priv->reg.cts_mode)); | |
1648 | pp->scan_type = cpu_to_le16((uint16_t) (priv->reg.scan_type)); | |
13a9930d | 1649 | pp->rate_set.size = priv->reg.rate_set.size; |
20c4f9c5 WS |
1650 | memcpy(&pp->rate_set.body[0], &priv->reg.rate_set.body[0], |
1651 | priv->reg.rate_set.size); | |
13a9930d WS |
1652 | pp->ssid.size = priv->reg.ssid.size; |
1653 | memcpy(&pp->ssid.body[0], &priv->reg.ssid.body[0], priv->reg.ssid.size); | |
1654 | ||
1655 | capability = 0x0000; | |
20c4f9c5 | 1656 | if (priv->reg.preamble == SHORT_PREAMBLE) { |
13a9930d WS |
1657 | /* short preamble */ |
1658 | capability |= BSS_CAP_SHORT_PREAMBLE; | |
1659 | } | |
20c4f9c5 WS |
1660 | capability &= ~(BSS_CAP_PBCC); /* pbcc not support */ |
1661 | if (priv->reg.phy_type != D_11B_ONLY_MODE) { | |
1662 | capability |= BSS_CAP_SHORT_SLOT_TIME; /* ShortSlotTime support */ | |
1663 | capability &= ~(BSS_CAP_DSSS_OFDM); /* DSSS OFDM not support */ | |
13a9930d | 1664 | } |
20c4f9c5 | 1665 | pp->capability = cpu_to_le16((uint16_t) capability); |
13a9930d WS |
1666 | |
1667 | pp->channel_list.body[0] = priv->reg.channel; | |
1668 | pp->channel_list.size = 1; | |
1669 | memcpy(pp->bssid, priv->reg.bssid, ETH_ALEN); | |
1670 | ||
1671 | /* send to device request */ | |
1672 | ps_confirm_wait_inc(priv); | |
20c4f9c5 | 1673 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
13a9930d WS |
1674 | } |
1675 | ||
1676 | static | |
20c4f9c5 | 1677 | void hostif_stop_request(struct ks_wlan_private *priv) |
13a9930d WS |
1678 | { |
1679 | struct hostif_stop_request_t *pp; | |
1680 | ||
20c4f9c5 | 1681 | DPRINTK(3, "\n"); |
13a9930d WS |
1682 | |
1683 | /* make primitive */ | |
20c4f9c5 WS |
1684 | pp = (struct hostif_stop_request_t *) |
1685 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1686 | if (pp == NULL) { | |
1687 | DPRINTK(3, "allocate memory failed..\n"); | |
13a9930d WS |
1688 | return; |
1689 | } | |
20c4f9c5 WS |
1690 | pp->header.size = |
1691 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1692 | pp->header.event = cpu_to_le16((uint16_t) HIF_STOP_REQ); | |
13a9930d WS |
1693 | |
1694 | /* send to device request */ | |
1695 | ps_confirm_wait_inc(priv); | |
20c4f9c5 | 1696 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
13a9930d WS |
1697 | } |
1698 | ||
1699 | static | |
20c4f9c5 | 1700 | void hostif_phy_information_request(struct ks_wlan_private *priv) |
13a9930d WS |
1701 | { |
1702 | struct hostif_phy_information_request_t *pp; | |
1703 | ||
20c4f9c5 | 1704 | DPRINTK(3, "\n"); |
13a9930d WS |
1705 | |
1706 | /* make primitive */ | |
20c4f9c5 WS |
1707 | pp = (struct hostif_phy_information_request_t *) |
1708 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1709 | if (pp == NULL) { | |
13a9930d WS |
1710 | DPRINTK(3, "allocate memory failed..\n"); |
1711 | return; | |
1712 | } | |
20c4f9c5 WS |
1713 | pp->header.size = |
1714 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1715 | pp->header.event = cpu_to_le16((uint16_t) HIF_PHY_INFO_REQ); | |
1716 | if (priv->reg.phy_info_timer) { | |
1717 | pp->type = cpu_to_le16((uint16_t) TIME_TYPE); | |
1718 | pp->time = cpu_to_le16((uint16_t) (priv->reg.phy_info_timer)); | |
1719 | } else { | |
1720 | pp->type = cpu_to_le16((uint16_t) NORMAL_TYPE); | |
1721 | pp->time = cpu_to_le16((uint16_t) 0); | |
13a9930d WS |
1722 | } |
1723 | ||
1724 | /* send to device request */ | |
1725 | ps_confirm_wait_inc(priv); | |
20c4f9c5 | 1726 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
13a9930d WS |
1727 | } |
1728 | ||
1729 | static | |
20c4f9c5 WS |
1730 | void hostif_power_mngmt_request(struct ks_wlan_private *priv, |
1731 | unsigned long mode, unsigned long wake_up, | |
1732 | unsigned long receiveDTIMs) | |
13a9930d WS |
1733 | { |
1734 | struct hostif_power_mngmt_request_t *pp; | |
1735 | ||
20c4f9c5 WS |
1736 | DPRINTK(3, "mode=%lu wake_up=%lu receiveDTIMs=%lu\n", mode, wake_up, |
1737 | receiveDTIMs); | |
13a9930d | 1738 | /* make primitive */ |
20c4f9c5 WS |
1739 | pp = (struct hostif_power_mngmt_request_t *) |
1740 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1741 | if (pp == NULL) { | |
1742 | DPRINTK(3, "allocate memory failed..\n"); | |
13a9930d WS |
1743 | return; |
1744 | } | |
20c4f9c5 WS |
1745 | pp->header.size = |
1746 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1747 | pp->header.event = cpu_to_le16((uint16_t) HIF_POWERMGT_REQ); | |
1748 | pp->mode = cpu_to_le32((uint32_t) mode); | |
1749 | pp->wake_up = cpu_to_le32((uint32_t) wake_up); | |
1750 | pp->receiveDTIMs = cpu_to_le32((uint32_t) receiveDTIMs); | |
13a9930d WS |
1751 | |
1752 | /* send to device request */ | |
1753 | ps_confirm_wait_inc(priv); | |
20c4f9c5 | 1754 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
13a9930d WS |
1755 | } |
1756 | ||
1757 | static | |
20c4f9c5 | 1758 | void hostif_sleep_request(struct ks_wlan_private *priv, unsigned long mode) |
13a9930d WS |
1759 | { |
1760 | struct hostif_sleep_request_t *pp; | |
1761 | ||
20c4f9c5 | 1762 | DPRINTK(3, "mode=%lu \n", mode); |
13a9930d | 1763 | |
20c4f9c5 | 1764 | if (mode == SLP_SLEEP) { |
13a9930d | 1765 | /* make primitive */ |
20c4f9c5 WS |
1766 | pp = (struct hostif_sleep_request_t *) |
1767 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1768 | if (pp == NULL) { | |
1769 | DPRINTK(3, "allocate memory failed..\n"); | |
13a9930d WS |
1770 | return; |
1771 | } | |
20c4f9c5 WS |
1772 | pp->header.size = |
1773 | cpu_to_le16((uint16_t) | |
1774 | (sizeof(*pp) - sizeof(pp->header.size))); | |
1775 | pp->header.event = cpu_to_le16((uint16_t) HIF_SLEEP_REQ); | |
13a9930d WS |
1776 | |
1777 | /* send to device request */ | |
1778 | ps_confirm_wait_inc(priv); | |
20c4f9c5 WS |
1779 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, |
1780 | NULL); | |
1781 | } else if (mode == SLP_ACTIVE) { | |
1782 | atomic_set(&priv->sleepstatus.wakeup_request, 1); | |
1783 | queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq, | |
1784 | &priv->ks_wlan_hw.rw_wq, 1); | |
1785 | } else { | |
1786 | DPRINTK(3, "invalid mode %ld \n", mode); | |
13a9930d WS |
1787 | return; |
1788 | } | |
1789 | } | |
1790 | ||
13a9930d | 1791 | static |
20c4f9c5 WS |
1792 | void hostif_bss_scan_request(struct ks_wlan_private *priv, |
1793 | unsigned long scan_type, uint8_t * scan_ssid, | |
1794 | uint8_t scan_ssid_len) | |
13a9930d WS |
1795 | { |
1796 | struct hostif_bss_scan_request_t *pp; | |
1797 | ||
20c4f9c5 | 1798 | DPRINTK(2, "\n"); |
13a9930d | 1799 | /* make primitive */ |
20c4f9c5 WS |
1800 | pp = (struct hostif_bss_scan_request_t *) |
1801 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1802 | if (pp == NULL) { | |
1803 | DPRINTK(3, "allocate memory failed..\n"); | |
13a9930d WS |
1804 | return; |
1805 | } | |
20c4f9c5 WS |
1806 | pp->header.size = |
1807 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1808 | pp->header.event = cpu_to_le16((uint16_t) HIF_SCAN_REQ); | |
13a9930d WS |
1809 | pp->scan_type = scan_type; |
1810 | ||
20c4f9c5 WS |
1811 | pp->ch_time_min = cpu_to_le32((uint32_t) 110); /* default value */ |
1812 | pp->ch_time_max = cpu_to_le32((uint32_t) 130); /* default value */ | |
13a9930d WS |
1813 | pp->channel_list.body[0] = 1; |
1814 | pp->channel_list.body[1] = 8; | |
1815 | pp->channel_list.body[2] = 2; | |
1816 | pp->channel_list.body[3] = 9; | |
1817 | pp->channel_list.body[4] = 3; | |
1818 | pp->channel_list.body[5] = 10; | |
1819 | pp->channel_list.body[6] = 4; | |
1820 | pp->channel_list.body[7] = 11; | |
1821 | pp->channel_list.body[8] = 5; | |
1822 | pp->channel_list.body[9] = 12; | |
1823 | pp->channel_list.body[10] = 6; | |
1824 | pp->channel_list.body[11] = 13; | |
1825 | pp->channel_list.body[12] = 7; | |
20c4f9c5 | 1826 | if (priv->reg.phy_type == D_11G_ONLY_MODE) { |
13a9930d | 1827 | pp->channel_list.size = 13; |
20c4f9c5 | 1828 | } else { |
13a9930d WS |
1829 | pp->channel_list.body[13] = 14; |
1830 | pp->channel_list.size = 14; | |
1831 | } | |
1832 | pp->ssid.size = 0; | |
1833 | ||
1834 | /* specified SSID SCAN */ | |
20c4f9c5 | 1835 | if (scan_ssid_len > 0 && scan_ssid_len <= 32) { |
13a9930d WS |
1836 | pp->ssid.size = scan_ssid_len; |
1837 | memcpy(&pp->ssid.body[0], scan_ssid, scan_ssid_len); | |
1838 | } | |
1839 | ||
13a9930d WS |
1840 | /* send to device request */ |
1841 | ps_confirm_wait_inc(priv); | |
20c4f9c5 | 1842 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
13a9930d WS |
1843 | |
1844 | priv->aplist.size = 0; | |
20c4f9c5 | 1845 | priv->scan_ind_count = 0; |
13a9930d WS |
1846 | } |
1847 | ||
1848 | static | |
20c4f9c5 WS |
1849 | void hostif_mic_failure_request(struct ks_wlan_private *priv, |
1850 | unsigned short failure_count, | |
1851 | unsigned short timer) | |
13a9930d WS |
1852 | { |
1853 | struct hostif_mic_failure_request_t *pp; | |
1854 | ||
20c4f9c5 | 1855 | DPRINTK(3, "count=%d :: timer=%d\n", failure_count, timer); |
13a9930d | 1856 | /* make primitive */ |
20c4f9c5 WS |
1857 | pp = (struct hostif_mic_failure_request_t *) |
1858 | kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); | |
1859 | if (pp == NULL) { | |
1860 | DPRINTK(3, "allocate memory failed..\n"); | |
13a9930d WS |
1861 | return; |
1862 | } | |
20c4f9c5 WS |
1863 | pp->header.size = |
1864 | cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); | |
1865 | pp->header.event = cpu_to_le16((uint16_t) HIF_MIC_FAILURE_REQ); | |
1866 | pp->failure_count = cpu_to_le16((uint16_t) failure_count); | |
1867 | pp->timer = cpu_to_le16((uint16_t) timer); | |
13a9930d WS |
1868 | |
1869 | /* send to device request */ | |
1870 | ps_confirm_wait_inc(priv); | |
20c4f9c5 | 1871 | ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); |
13a9930d WS |
1872 | } |
1873 | ||
1874 | /* Device I/O Recieve indicate */ | |
20c4f9c5 WS |
1875 | static void devio_rec_ind(struct ks_wlan_private *priv, unsigned char *p, |
1876 | unsigned int size) | |
13a9930d WS |
1877 | { |
1878 | if (priv->device_open_status) { | |
20c4f9c5 | 1879 | spin_lock(&priv->dev_read_lock); /* request spin lock */ |
13a9930d WS |
1880 | priv->dev_data[atomic_read(&priv->rec_count)] = p; |
1881 | priv->dev_size[atomic_read(&priv->rec_count)] = size; | |
1882 | ||
1883 | if (atomic_read(&priv->event_count) != DEVICE_STOCK_COUNT) { | |
1884 | /* rx event count inc */ | |
1885 | atomic_inc(&priv->event_count); | |
1886 | } | |
1887 | atomic_inc(&priv->rec_count); | |
20c4f9c5 | 1888 | if (atomic_read(&priv->rec_count) == DEVICE_STOCK_COUNT) |
13a9930d WS |
1889 | atomic_set(&priv->rec_count, 0); |
1890 | ||
20c4f9c5 | 1891 | wake_up_interruptible_all(&priv->devread_wait); |
13a9930d WS |
1892 | |
1893 | /* release spin lock */ | |
1894 | spin_unlock(&priv->dev_read_lock); | |
1895 | } | |
1896 | } | |
1897 | ||
20c4f9c5 WS |
1898 | void hostif_receive(struct ks_wlan_private *priv, unsigned char *p, |
1899 | unsigned int size) | |
13a9930d | 1900 | { |
20c4f9c5 | 1901 | DPRINTK(4, "\n"); |
13a9930d WS |
1902 | |
1903 | devio_rec_ind(priv, p, size); | |
1904 | ||
1905 | priv->rxp = p; | |
1906 | priv->rx_size = size; | |
1907 | ||
20c4f9c5 WS |
1908 | if (get_WORD(priv) == priv->rx_size) { /* length check !! */ |
1909 | hostif_event_check(priv); /* event check */ | |
13a9930d WS |
1910 | } |
1911 | } | |
1912 | ||
13a9930d | 1913 | static |
feedcf1a | 1914 | void hostif_sme_set_wep(struct ks_wlan_private *priv, int type) |
13a9930d WS |
1915 | { |
1916 | uint32_t val; | |
20c4f9c5 | 1917 | switch (type) { |
13a9930d | 1918 | case SME_WEP_INDEX_REQUEST: |
20c4f9c5 | 1919 | val = cpu_to_le32((uint32_t) (priv->reg.wep_index)); |
13a9930d | 1920 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_ID, |
20c4f9c5 | 1921 | sizeof(val), MIB_VALUE_TYPE_INT, &val); |
13a9930d WS |
1922 | break; |
1923 | case SME_WEP_KEY1_REQUEST: | |
20c4f9c5 WS |
1924 | if (!priv->wpa.wpa_enabled) |
1925 | hostif_mib_set_request(priv, | |
1926 | DOT11_WEP_DEFAULT_KEY_VALUE1, | |
1927 | priv->reg.wep_key[0].size, | |
1928 | MIB_VALUE_TYPE_OSTRING, | |
1929 | &priv->reg.wep_key[0].val[0]); | |
13a9930d WS |
1930 | break; |
1931 | case SME_WEP_KEY2_REQUEST: | |
20c4f9c5 WS |
1932 | if (!priv->wpa.wpa_enabled) |
1933 | hostif_mib_set_request(priv, | |
1934 | DOT11_WEP_DEFAULT_KEY_VALUE2, | |
1935 | priv->reg.wep_key[1].size, | |
1936 | MIB_VALUE_TYPE_OSTRING, | |
13a9930d WS |
1937 | &priv->reg.wep_key[1].val[0]); |
1938 | break; | |
1939 | case SME_WEP_KEY3_REQUEST: | |
20c4f9c5 WS |
1940 | if (!priv->wpa.wpa_enabled) |
1941 | hostif_mib_set_request(priv, | |
1942 | DOT11_WEP_DEFAULT_KEY_VALUE3, | |
1943 | priv->reg.wep_key[2].size, | |
1944 | MIB_VALUE_TYPE_OSTRING, | |
1945 | &priv->reg.wep_key[2].val[0]); | |
13a9930d WS |
1946 | break; |
1947 | case SME_WEP_KEY4_REQUEST: | |
20c4f9c5 WS |
1948 | if (!priv->wpa.wpa_enabled) |
1949 | hostif_mib_set_request(priv, | |
1950 | DOT11_WEP_DEFAULT_KEY_VALUE4, | |
1951 | priv->reg.wep_key[3].size, | |
1952 | MIB_VALUE_TYPE_OSTRING, | |
13a9930d WS |
1953 | &priv->reg.wep_key[3].val[0]); |
1954 | break; | |
1955 | case SME_WEP_FLAG_REQUEST: | |
20c4f9c5 | 1956 | val = cpu_to_le32((uint32_t) (priv->reg.privacy_invoked)); |
13a9930d | 1957 | hostif_mib_set_request(priv, DOT11_PRIVACY_INVOKED, |
20c4f9c5 | 1958 | sizeof(val), MIB_VALUE_TYPE_BOOL, &val); |
13a9930d WS |
1959 | break; |
1960 | } | |
1961 | ||
20c4f9c5 | 1962 | return; |
13a9930d WS |
1963 | } |
1964 | ||
1965 | struct wpa_suite_t { | |
1966 | unsigned short size; | |
1967 | unsigned char suite[4][CIPHER_ID_LEN]; | |
20c4f9c5 | 1968 | } __attribute__ ((packed)); |
13a9930d WS |
1969 | |
1970 | struct rsn_mode_t { | |
1971 | uint32_t rsn_mode; | |
1972 | uint16_t rsn_capability; | |
20c4f9c5 | 1973 | } __attribute__ ((packed)); |
13a9930d WS |
1974 | |
1975 | static | |
feedcf1a | 1976 | void hostif_sme_set_rsn(struct ks_wlan_private *priv, int type) |
13a9930d WS |
1977 | { |
1978 | struct wpa_suite_t wpa_suite; | |
1979 | struct rsn_mode_t rsn_mode; | |
1980 | uint32_t val; | |
1981 | ||
20c4f9c5 | 1982 | memset(&wpa_suite, 0, sizeof(wpa_suite)); |
13a9930d | 1983 | |
20c4f9c5 | 1984 | switch (type) { |
13a9930d | 1985 | case SME_RSN_UCAST_REQUEST: |
20c4f9c5 WS |
1986 | wpa_suite.size = cpu_to_le16((uint16_t) 1); |
1987 | switch (priv->wpa.pairwise_suite) { | |
13a9930d | 1988 | case IW_AUTH_CIPHER_NONE: |
20c4f9c5 WS |
1989 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
1990 | memcpy(&wpa_suite.suite[0][0], | |
1991 | CIPHER_ID_WPA2_NONE, CIPHER_ID_LEN); | |
13a9930d | 1992 | else |
20c4f9c5 WS |
1993 | memcpy(&wpa_suite.suite[0][0], |
1994 | CIPHER_ID_WPA_NONE, CIPHER_ID_LEN); | |
13a9930d WS |
1995 | break; |
1996 | case IW_AUTH_CIPHER_WEP40: | |
20c4f9c5 WS |
1997 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
1998 | memcpy(&wpa_suite.suite[0][0], | |
1999 | CIPHER_ID_WPA2_WEP40, CIPHER_ID_LEN); | |
13a9930d | 2000 | else |
20c4f9c5 WS |
2001 | memcpy(&wpa_suite.suite[0][0], |
2002 | CIPHER_ID_WPA_WEP40, CIPHER_ID_LEN); | |
13a9930d WS |
2003 | break; |
2004 | case IW_AUTH_CIPHER_TKIP: | |
20c4f9c5 WS |
2005 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2006 | memcpy(&wpa_suite.suite[0][0], | |
2007 | CIPHER_ID_WPA2_TKIP, CIPHER_ID_LEN); | |
13a9930d | 2008 | else |
20c4f9c5 WS |
2009 | memcpy(&wpa_suite.suite[0][0], |
2010 | CIPHER_ID_WPA_TKIP, CIPHER_ID_LEN); | |
13a9930d WS |
2011 | break; |
2012 | case IW_AUTH_CIPHER_CCMP: | |
20c4f9c5 WS |
2013 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2014 | memcpy(&wpa_suite.suite[0][0], | |
2015 | CIPHER_ID_WPA2_CCMP, CIPHER_ID_LEN); | |
13a9930d | 2016 | else |
20c4f9c5 WS |
2017 | memcpy(&wpa_suite.suite[0][0], |
2018 | CIPHER_ID_WPA_CCMP, CIPHER_ID_LEN); | |
13a9930d WS |
2019 | break; |
2020 | case IW_AUTH_CIPHER_WEP104: | |
20c4f9c5 WS |
2021 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2022 | memcpy(&wpa_suite.suite[0][0], | |
2023 | CIPHER_ID_WPA2_WEP104, CIPHER_ID_LEN); | |
13a9930d | 2024 | else |
20c4f9c5 WS |
2025 | memcpy(&wpa_suite.suite[0][0], |
2026 | CIPHER_ID_WPA_WEP104, CIPHER_ID_LEN); | |
13a9930d WS |
2027 | break; |
2028 | } | |
2029 | ||
2030 | hostif_mib_set_request(priv, DOT11_RSN_CONFIG_UNICAST_CIPHER, | |
20c4f9c5 WS |
2031 | sizeof(wpa_suite.size) + |
2032 | CIPHER_ID_LEN * wpa_suite.size, | |
13a9930d WS |
2033 | MIB_VALUE_TYPE_OSTRING, &wpa_suite); |
2034 | break; | |
2035 | case SME_RSN_MCAST_REQUEST: | |
20c4f9c5 | 2036 | switch (priv->wpa.group_suite) { |
13a9930d | 2037 | case IW_AUTH_CIPHER_NONE: |
20c4f9c5 WS |
2038 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2039 | memcpy(&wpa_suite.suite[0][0], | |
2040 | CIPHER_ID_WPA2_NONE, CIPHER_ID_LEN); | |
13a9930d | 2041 | else |
20c4f9c5 WS |
2042 | memcpy(&wpa_suite.suite[0][0], |
2043 | CIPHER_ID_WPA_NONE, CIPHER_ID_LEN); | |
13a9930d WS |
2044 | break; |
2045 | case IW_AUTH_CIPHER_WEP40: | |
20c4f9c5 WS |
2046 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2047 | memcpy(&wpa_suite.suite[0][0], | |
2048 | CIPHER_ID_WPA2_WEP40, CIPHER_ID_LEN); | |
13a9930d | 2049 | else |
20c4f9c5 WS |
2050 | memcpy(&wpa_suite.suite[0][0], |
2051 | CIPHER_ID_WPA_WEP40, CIPHER_ID_LEN); | |
13a9930d WS |
2052 | break; |
2053 | case IW_AUTH_CIPHER_TKIP: | |
20c4f9c5 WS |
2054 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2055 | memcpy(&wpa_suite.suite[0][0], | |
2056 | CIPHER_ID_WPA2_TKIP, CIPHER_ID_LEN); | |
13a9930d | 2057 | else |
20c4f9c5 WS |
2058 | memcpy(&wpa_suite.suite[0][0], |
2059 | CIPHER_ID_WPA_TKIP, CIPHER_ID_LEN); | |
13a9930d WS |
2060 | break; |
2061 | case IW_AUTH_CIPHER_CCMP: | |
20c4f9c5 WS |
2062 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2063 | memcpy(&wpa_suite.suite[0][0], | |
2064 | CIPHER_ID_WPA2_CCMP, CIPHER_ID_LEN); | |
13a9930d | 2065 | else |
20c4f9c5 WS |
2066 | memcpy(&wpa_suite.suite[0][0], |
2067 | CIPHER_ID_WPA_CCMP, CIPHER_ID_LEN); | |
13a9930d WS |
2068 | break; |
2069 | case IW_AUTH_CIPHER_WEP104: | |
20c4f9c5 WS |
2070 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2071 | memcpy(&wpa_suite.suite[0][0], | |
2072 | CIPHER_ID_WPA2_WEP104, CIPHER_ID_LEN); | |
13a9930d | 2073 | else |
20c4f9c5 WS |
2074 | memcpy(&wpa_suite.suite[0][0], |
2075 | CIPHER_ID_WPA_WEP104, CIPHER_ID_LEN); | |
13a9930d WS |
2076 | break; |
2077 | } | |
2078 | ||
2079 | hostif_mib_set_request(priv, DOT11_RSN_CONFIG_MULTICAST_CIPHER, | |
2080 | CIPHER_ID_LEN, MIB_VALUE_TYPE_OSTRING, | |
20c4f9c5 | 2081 | &wpa_suite.suite[0][0]); |
13a9930d WS |
2082 | break; |
2083 | case SME_RSN_AUTH_REQUEST: | |
20c4f9c5 WS |
2084 | wpa_suite.size = cpu_to_le16((uint16_t) 1); |
2085 | switch (priv->wpa.key_mgmt_suite) { | |
13a9930d | 2086 | case IW_AUTH_KEY_MGMT_802_1X: |
20c4f9c5 WS |
2087 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2088 | memcpy(&wpa_suite.suite[0][0], | |
2089 | KEY_MGMT_ID_WPA2_1X, KEY_MGMT_ID_LEN); | |
13a9930d | 2090 | else |
20c4f9c5 WS |
2091 | memcpy(&wpa_suite.suite[0][0], |
2092 | KEY_MGMT_ID_WPA_1X, KEY_MGMT_ID_LEN); | |
13a9930d WS |
2093 | break; |
2094 | case IW_AUTH_KEY_MGMT_PSK: | |
20c4f9c5 WS |
2095 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2096 | memcpy(&wpa_suite.suite[0][0], | |
2097 | KEY_MGMT_ID_WPA2_PSK, KEY_MGMT_ID_LEN); | |
13a9930d | 2098 | else |
20c4f9c5 WS |
2099 | memcpy(&wpa_suite.suite[0][0], |
2100 | KEY_MGMT_ID_WPA_PSK, KEY_MGMT_ID_LEN); | |
13a9930d WS |
2101 | break; |
2102 | case 0: | |
20c4f9c5 WS |
2103 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2104 | memcpy(&wpa_suite.suite[0][0], | |
2105 | KEY_MGMT_ID_WPA2_NONE, KEY_MGMT_ID_LEN); | |
13a9930d | 2106 | else |
20c4f9c5 WS |
2107 | memcpy(&wpa_suite.suite[0][0], |
2108 | KEY_MGMT_ID_WPA_NONE, KEY_MGMT_ID_LEN); | |
13a9930d WS |
2109 | break; |
2110 | case 4: | |
20c4f9c5 WS |
2111 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) |
2112 | memcpy(&wpa_suite.suite[0][0], | |
2113 | KEY_MGMT_ID_WPA2_WPANONE, | |
2114 | KEY_MGMT_ID_LEN); | |
13a9930d | 2115 | else |
20c4f9c5 WS |
2116 | memcpy(&wpa_suite.suite[0][0], |
2117 | KEY_MGMT_ID_WPA_WPANONE, | |
2118 | KEY_MGMT_ID_LEN); | |
13a9930d WS |
2119 | break; |
2120 | } | |
2121 | ||
2122 | hostif_mib_set_request(priv, DOT11_RSN_CONFIG_AUTH_SUITE, | |
20c4f9c5 WS |
2123 | sizeof(wpa_suite.size) + |
2124 | KEY_MGMT_ID_LEN * wpa_suite.size, | |
13a9930d WS |
2125 | MIB_VALUE_TYPE_OSTRING, &wpa_suite); |
2126 | break; | |
2127 | case SME_RSN_ENABLED_REQUEST: | |
20c4f9c5 | 2128 | val = cpu_to_le32((uint32_t) (priv->wpa.rsn_enabled)); |
13a9930d | 2129 | hostif_mib_set_request(priv, DOT11_RSN_ENABLED, |
20c4f9c5 | 2130 | sizeof(val), MIB_VALUE_TYPE_BOOL, &val); |
13a9930d WS |
2131 | break; |
2132 | case SME_RSN_MODE_REQUEST: | |
20c4f9c5 WS |
2133 | if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA2) { |
2134 | rsn_mode.rsn_mode = | |
2135 | cpu_to_le32((uint32_t) RSN_MODE_WPA2); | |
2136 | rsn_mode.rsn_capability = cpu_to_le16((uint16_t) 0); | |
2137 | } else if (priv->wpa.version == IW_AUTH_WPA_VERSION_WPA) { | |
2138 | rsn_mode.rsn_mode = | |
2139 | cpu_to_le32((uint32_t) RSN_MODE_WPA); | |
2140 | rsn_mode.rsn_capability = cpu_to_le16((uint16_t) 0); | |
2141 | } else { | |
2142 | rsn_mode.rsn_mode = | |
2143 | cpu_to_le32((uint32_t) RSN_MODE_NONE); | |
2144 | rsn_mode.rsn_capability = cpu_to_le16((uint16_t) 0); | |
13a9930d | 2145 | } |
20c4f9c5 WS |
2146 | hostif_mib_set_request(priv, LOCAL_RSN_MODE, sizeof(rsn_mode), |
2147 | MIB_VALUE_TYPE_OSTRING, &rsn_mode); | |
13a9930d WS |
2148 | break; |
2149 | ||
2150 | } | |
2151 | return; | |
2152 | } | |
2153 | ||
2154 | static | |
feedcf1a | 2155 | void hostif_sme_mode_setup(struct ks_wlan_private *priv) |
13a9930d WS |
2156 | { |
2157 | unsigned char rate_size; | |
2158 | unsigned char rate_octet[RATE_SET_MAX_SIZE]; | |
20c4f9c5 | 2159 | int i = 0; |
13a9930d | 2160 | |
20c4f9c5 WS |
2161 | /* rate setting if rate segging is auto for changing phy_type (#94) */ |
2162 | if (priv->reg.tx_rate == TX_RATE_FULL_AUTO) { | |
2163 | if (priv->reg.phy_type == D_11B_ONLY_MODE) { | |
13a9930d WS |
2164 | priv->reg.rate_set.body[3] = TX_RATE_11M; |
2165 | priv->reg.rate_set.body[2] = TX_RATE_5M; | |
20c4f9c5 WS |
2166 | priv->reg.rate_set.body[1] = TX_RATE_2M | BASIC_RATE; |
2167 | priv->reg.rate_set.body[0] = TX_RATE_1M | BASIC_RATE; | |
13a9930d | 2168 | priv->reg.rate_set.size = 4; |
20c4f9c5 | 2169 | } else { /* D_11G_ONLY_MODE or D_11BG_COMPATIBLE_MODE */ |
13a9930d WS |
2170 | priv->reg.rate_set.body[11] = TX_RATE_54M; |
2171 | priv->reg.rate_set.body[10] = TX_RATE_48M; | |
2172 | priv->reg.rate_set.body[9] = TX_RATE_36M; | |
2173 | priv->reg.rate_set.body[8] = TX_RATE_18M; | |
2174 | priv->reg.rate_set.body[7] = TX_RATE_9M; | |
20c4f9c5 WS |
2175 | priv->reg.rate_set.body[6] = TX_RATE_24M | BASIC_RATE; |
2176 | priv->reg.rate_set.body[5] = TX_RATE_12M | BASIC_RATE; | |
2177 | priv->reg.rate_set.body[4] = TX_RATE_6M | BASIC_RATE; | |
2178 | priv->reg.rate_set.body[3] = TX_RATE_11M | BASIC_RATE; | |
2179 | priv->reg.rate_set.body[2] = TX_RATE_5M | BASIC_RATE; | |
2180 | priv->reg.rate_set.body[1] = TX_RATE_2M | BASIC_RATE; | |
2181 | priv->reg.rate_set.body[0] = TX_RATE_1M | BASIC_RATE; | |
13a9930d WS |
2182 | priv->reg.rate_set.size = 12; |
2183 | } | |
2184 | } | |
2185 | ||
2186 | /* rate mask by phy setting */ | |
20c4f9c5 WS |
2187 | if (priv->reg.phy_type == D_11B_ONLY_MODE) { |
2188 | for (i = 0; i < priv->reg.rate_set.size; i++) { | |
2189 | if (IS_11B_RATE(priv->reg.rate_set.body[i])) { | |
2190 | if ((priv->reg.rate_set.body[i] & RATE_MASK) >= | |
2191 | TX_RATE_5M) | |
2192 | rate_octet[i] = | |
2193 | priv->reg.rate_set. | |
2194 | body[i] & RATE_MASK; | |
13a9930d | 2195 | else |
20c4f9c5 WS |
2196 | rate_octet[i] = |
2197 | priv->reg.rate_set.body[i]; | |
2198 | } else | |
13a9930d WS |
2199 | break; |
2200 | } | |
2201 | ||
20c4f9c5 WS |
2202 | } else { /* D_11G_ONLY_MODE or D_11BG_COMPATIBLE_MODE */ |
2203 | for (i = 0; i < priv->reg.rate_set.size; i++) { | |
2204 | if (IS_11BG_RATE(priv->reg.rate_set.body[i])) { | |
2205 | if (IS_OFDM_EXT_RATE | |
2206 | (priv->reg.rate_set.body[i])) | |
2207 | rate_octet[i] = | |
2208 | priv->reg.rate_set. | |
2209 | body[i] & RATE_MASK; | |
13a9930d | 2210 | else |
20c4f9c5 WS |
2211 | rate_octet[i] = |
2212 | priv->reg.rate_set.body[i]; | |
2213 | } else | |
13a9930d WS |
2214 | break; |
2215 | } | |
2216 | } | |
2217 | rate_size = i; | |
20c4f9c5 WS |
2218 | if (rate_size == 0) { |
2219 | if (priv->reg.phy_type == D_11G_ONLY_MODE) | |
2220 | rate_octet[0] = TX_RATE_6M | BASIC_RATE; | |
13a9930d | 2221 | else |
20c4f9c5 | 2222 | rate_octet[0] = TX_RATE_2M | BASIC_RATE; |
13a9930d WS |
2223 | rate_size = 1; |
2224 | } | |
2225 | ||
2226 | /* rate set update */ | |
2227 | priv->reg.rate_set.size = rate_size; | |
2228 | memcpy(&priv->reg.rate_set.body[0], &rate_octet[0], rate_size); | |
2229 | ||
20c4f9c5 | 2230 | switch (priv->reg.operation_mode) { |
13a9930d WS |
2231 | case MODE_PSEUDO_ADHOC: |
2232 | /* Pseudo Ad-Hoc mode */ | |
2233 | hostif_ps_adhoc_set_request(priv); | |
2234 | break; | |
2235 | case MODE_INFRASTRUCTURE: | |
2236 | /* Infrastructure mode */ | |
20c4f9c5 | 2237 | if (!is_valid_ether_addr((u8 *) priv->reg.bssid)) { |
13a9930d | 2238 | hostif_infrastructure_set_request(priv); |
20c4f9c5 | 2239 | } else { |
13a9930d | 2240 | hostif_infrastructure_set2_request(priv); |
20c4f9c5 WS |
2241 | DPRINTK(2, |
2242 | "Infra bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", | |
2243 | priv->reg.bssid[0], priv->reg.bssid[1], | |
2244 | priv->reg.bssid[2], priv->reg.bssid[3], | |
2245 | priv->reg.bssid[4], priv->reg.bssid[5]); | |
13a9930d WS |
2246 | } |
2247 | break; | |
2248 | case MODE_ADHOC: | |
2249 | /* IEEE802.11 Ad-Hoc mode */ | |
20c4f9c5 | 2250 | if (!is_valid_ether_addr((u8 *) priv->reg.bssid)) { |
13a9930d | 2251 | hostif_adhoc_set_request(priv); |
20c4f9c5 | 2252 | } else { |
13a9930d | 2253 | hostif_adhoc_set2_request(priv); |
20c4f9c5 WS |
2254 | DPRINTK(2, |
2255 | "Adhoc bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", | |
2256 | priv->reg.bssid[0], priv->reg.bssid[1], | |
2257 | priv->reg.bssid[2], priv->reg.bssid[3], | |
2258 | priv->reg.bssid[4], priv->reg.bssid[5]); | |
13a9930d WS |
2259 | } |
2260 | break; | |
2261 | default: | |
2262 | break; | |
2263 | } | |
2264 | ||
20c4f9c5 | 2265 | return; |
13a9930d WS |
2266 | } |
2267 | ||
2268 | static | |
feedcf1a | 2269 | void hostif_sme_multicast_set(struct ks_wlan_private *priv) |
13a9930d WS |
2270 | { |
2271 | ||
20c4f9c5 | 2272 | struct net_device *dev = priv->net_dev; |
13a9930d | 2273 | int mc_count; |
13a9930d | 2274 | struct netdev_hw_addr *ha; |
20c4f9c5 | 2275 | char set_address[NIC_MAX_MCAST_LIST * ETH_ALEN]; |
13a9930d | 2276 | unsigned long filter_type; |
f88e6d33 | 2277 | int i = 0; |
13a9930d | 2278 | |
20c4f9c5 | 2279 | DPRINTK(3, "\n"); |
13a9930d WS |
2280 | |
2281 | spin_lock(&priv->multicast_spin); | |
2282 | ||
20c4f9c5 WS |
2283 | memset(set_address, 0, NIC_MAX_MCAST_LIST * ETH_ALEN); |
2284 | ||
2285 | if (dev->flags & IFF_PROMISC) { | |
2286 | filter_type = cpu_to_le32((uint32_t) MCAST_FILTER_PROMISC); | |
2287 | hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER, | |
2288 | sizeof(filter_type), MIB_VALUE_TYPE_BOOL, | |
2289 | &filter_type); | |
2290 | } else if ((netdev_mc_count(dev) > NIC_MAX_MCAST_LIST) | |
2291 | || (dev->flags & IFF_ALLMULTI)) { | |
2292 | filter_type = cpu_to_le32((uint32_t) MCAST_FILTER_MCASTALL); | |
2293 | hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER, | |
2294 | sizeof(filter_type), MIB_VALUE_TYPE_BOOL, | |
2295 | &filter_type); | |
2296 | } else { | |
2297 | if (priv->sme_i.sme_flag & SME_MULTICAST) { | |
13a9930d | 2298 | mc_count = netdev_mc_count(dev); |
13a9930d | 2299 | netdev_for_each_mc_addr(ha, dev) { |
20c4f9c5 WS |
2300 | memcpy(&set_address[i * ETH_ALEN], ha->addr, |
2301 | ETH_ALEN); | |
f88e6d33 | 2302 | i++; |
13a9930d | 2303 | } |
13a9930d WS |
2304 | priv->sme_i.sme_flag &= ~SME_MULTICAST; |
2305 | hostif_mib_set_request(priv, LOCAL_MULTICAST_ADDRESS, | |
20c4f9c5 WS |
2306 | (ETH_ALEN * mc_count), |
2307 | MIB_VALUE_TYPE_OSTRING, | |
2308 | &set_address[0]); | |
2309 | } else { | |
2310 | filter_type = | |
2311 | cpu_to_le32((uint32_t) MCAST_FILTER_MCAST); | |
13a9930d | 2312 | priv->sme_i.sme_flag |= SME_MULTICAST; |
20c4f9c5 WS |
2313 | hostif_mib_set_request(priv, LOCAL_MULTICAST_FILTER, |
2314 | sizeof(filter_type), | |
2315 | MIB_VALUE_TYPE_BOOL, | |
2316 | &filter_type); | |
13a9930d WS |
2317 | } |
2318 | } | |
2319 | ||
2320 | spin_unlock(&priv->multicast_spin); | |
2321 | ||
2322 | } | |
2323 | ||
2324 | static | |
feedcf1a | 2325 | void hostif_sme_powermgt_set(struct ks_wlan_private *priv) |
13a9930d | 2326 | { |
20c4f9c5 | 2327 | unsigned long mode, wake_up, receiveDTIMs; |
13a9930d | 2328 | |
20c4f9c5 WS |
2329 | DPRINTK(3, "\n"); |
2330 | switch (priv->reg.powermgt) { | |
13a9930d WS |
2331 | case POWMGT_ACTIVE_MODE: |
2332 | mode = POWER_ACTIVE; | |
2333 | wake_up = 0; | |
2334 | receiveDTIMs = 0; | |
2335 | break; | |
2336 | case POWMGT_SAVE1_MODE: | |
20c4f9c5 | 2337 | if (priv->reg.operation_mode == MODE_INFRASTRUCTURE) { |
13a9930d WS |
2338 | mode = POWER_SAVE; |
2339 | wake_up = 0; | |
2340 | receiveDTIMs = 0; | |
2341 | } else { | |
2342 | mode = POWER_ACTIVE; | |
2343 | wake_up = 0; | |
2344 | receiveDTIMs = 0; | |
2345 | } | |
2346 | break; | |
2347 | case POWMGT_SAVE2_MODE: | |
20c4f9c5 | 2348 | if (priv->reg.operation_mode == MODE_INFRASTRUCTURE) { |
13a9930d WS |
2349 | mode = POWER_SAVE; |
2350 | wake_up = 0; | |
2351 | receiveDTIMs = 1; | |
2352 | } else { | |
2353 | mode = POWER_ACTIVE; | |
2354 | wake_up = 0; | |
2355 | receiveDTIMs = 0; | |
2356 | } | |
2357 | break; | |
2358 | default: | |
2359 | mode = POWER_ACTIVE; | |
2360 | wake_up = 0; | |
2361 | receiveDTIMs = 0; | |
2362 | break; | |
2363 | } | |
2364 | hostif_power_mngmt_request(priv, mode, wake_up, receiveDTIMs); | |
2365 | ||
2366 | return; | |
2367 | } | |
2368 | ||
2369 | static | |
feedcf1a | 2370 | void hostif_sme_sleep_set(struct ks_wlan_private *priv) |
13a9930d | 2371 | { |
20c4f9c5 WS |
2372 | DPRINTK(3, "\n"); |
2373 | switch (priv->sleep_mode) { | |
13a9930d WS |
2374 | case SLP_SLEEP: |
2375 | hostif_sleep_request(priv, priv->sleep_mode); | |
2376 | break; | |
2377 | case SLP_ACTIVE: | |
2378 | hostif_sleep_request(priv, priv->sleep_mode); | |
2379 | break; | |
2380 | default: | |
2381 | break; | |
2382 | } | |
2383 | ||
2384 | return; | |
2385 | } | |
2386 | ||
2387 | static | |
feedcf1a | 2388 | void hostif_sme_set_key(struct ks_wlan_private *priv, int type) |
13a9930d WS |
2389 | { |
2390 | uint32_t val; | |
20c4f9c5 | 2391 | switch (type) { |
13a9930d | 2392 | case SME_SET_FLAG: |
20c4f9c5 | 2393 | val = cpu_to_le32((uint32_t) (priv->reg.privacy_invoked)); |
13a9930d | 2394 | hostif_mib_set_request(priv, DOT11_PRIVACY_INVOKED, |
20c4f9c5 | 2395 | sizeof(val), MIB_VALUE_TYPE_BOOL, &val); |
13a9930d WS |
2396 | break; |
2397 | case SME_SET_TXKEY: | |
20c4f9c5 | 2398 | val = cpu_to_le32((uint32_t) (priv->wpa.txkey)); |
13a9930d | 2399 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_ID, |
20c4f9c5 | 2400 | sizeof(val), MIB_VALUE_TYPE_INT, &val); |
13a9930d WS |
2401 | break; |
2402 | case SME_SET_KEY1: | |
2403 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE1, | |
20c4f9c5 WS |
2404 | priv->wpa.key[0].key_len, |
2405 | MIB_VALUE_TYPE_OSTRING, | |
2406 | &priv->wpa.key[0].key_val[0]); | |
13a9930d WS |
2407 | break; |
2408 | case SME_SET_KEY2: | |
2409 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE2, | |
20c4f9c5 WS |
2410 | priv->wpa.key[1].key_len, |
2411 | MIB_VALUE_TYPE_OSTRING, | |
2412 | &priv->wpa.key[1].key_val[0]); | |
13a9930d WS |
2413 | break; |
2414 | case SME_SET_KEY3: | |
2415 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE3, | |
20c4f9c5 WS |
2416 | priv->wpa.key[2].key_len, |
2417 | MIB_VALUE_TYPE_OSTRING, | |
2418 | &priv->wpa.key[2].key_val[0]); | |
13a9930d WS |
2419 | break; |
2420 | case SME_SET_KEY4: | |
2421 | hostif_mib_set_request(priv, DOT11_WEP_DEFAULT_KEY_VALUE4, | |
20c4f9c5 WS |
2422 | priv->wpa.key[3].key_len, |
2423 | MIB_VALUE_TYPE_OSTRING, | |
2424 | &priv->wpa.key[3].key_val[0]); | |
13a9930d WS |
2425 | break; |
2426 | case SME_SET_PMK_TSC: | |
2427 | hostif_mib_set_request(priv, DOT11_PMK_TSC, | |
2428 | WPA_RX_SEQ_LEN, MIB_VALUE_TYPE_OSTRING, | |
20c4f9c5 | 2429 | &priv->wpa.key[0].rx_seq[0]); |
13a9930d WS |
2430 | break; |
2431 | case SME_SET_GMK1_TSC: | |
2432 | hostif_mib_set_request(priv, DOT11_GMK1_TSC, | |
2433 | WPA_RX_SEQ_LEN, MIB_VALUE_TYPE_OSTRING, | |
20c4f9c5 | 2434 | &priv->wpa.key[1].rx_seq[0]); |
13a9930d WS |
2435 | break; |
2436 | case SME_SET_GMK2_TSC: | |
2437 | hostif_mib_set_request(priv, DOT11_GMK2_TSC, | |
2438 | WPA_RX_SEQ_LEN, MIB_VALUE_TYPE_OSTRING, | |
20c4f9c5 | 2439 | &priv->wpa.key[2].rx_seq[0]); |
13a9930d WS |
2440 | break; |
2441 | } | |
2442 | return; | |
2443 | } | |
2444 | ||
2445 | static | |
feedcf1a | 2446 | void hostif_sme_set_pmksa(struct ks_wlan_private *priv) |
13a9930d WS |
2447 | { |
2448 | struct pmk_cache_t { | |
2449 | uint16_t size; | |
2450 | struct { | |
20c4f9c5 WS |
2451 | uint8_t bssid[ETH_ALEN]; |
2452 | uint8_t pmkid[IW_PMKID_LEN]; | |
2453 | } __attribute__ ((packed)) list[PMK_LIST_MAX]; | |
2454 | } __attribute__ ((packed)) pmkcache; | |
13a9930d WS |
2455 | struct pmk_t *pmk; |
2456 | struct list_head *ptr; | |
2457 | int i; | |
2458 | ||
20c4f9c5 WS |
2459 | DPRINTK(4, "pmklist.size=%d\n", priv->pmklist.size); |
2460 | i = 0; | |
2461 | list_for_each(ptr, &priv->pmklist.head) { | |
13a9930d | 2462 | pmk = list_entry(ptr, struct pmk_t, list); |
20c4f9c5 | 2463 | if (i < PMK_LIST_MAX) { |
13a9930d | 2464 | memcpy(pmkcache.list[i].bssid, pmk->bssid, ETH_ALEN); |
20c4f9c5 WS |
2465 | memcpy(pmkcache.list[i].pmkid, pmk->pmkid, |
2466 | IW_PMKID_LEN); | |
13a9930d WS |
2467 | i++; |
2468 | } | |
2469 | } | |
20c4f9c5 | 2470 | pmkcache.size = cpu_to_le16((uint16_t) (priv->pmklist.size)); |
13a9930d | 2471 | hostif_mib_set_request(priv, LOCAL_PMK, |
20c4f9c5 WS |
2472 | sizeof(priv->pmklist.size) + (ETH_ALEN + |
2473 | IW_PMKID_LEN) * | |
2474 | (priv->pmklist.size), MIB_VALUE_TYPE_OSTRING, | |
2475 | &pmkcache); | |
13a9930d WS |
2476 | } |
2477 | ||
2478 | /* execute sme */ | |
2479 | static | |
feedcf1a | 2480 | void hostif_sme_execute(struct ks_wlan_private *priv, int event) |
13a9930d WS |
2481 | { |
2482 | uint32_t val; | |
2483 | ||
20c4f9c5 | 2484 | DPRINTK(3, "event=%d\n", event); |
13a9930d WS |
2485 | switch (event) { |
2486 | case SME_START: | |
20c4f9c5 | 2487 | if (priv->dev_state == DEVICE_STATE_BOOT) { |
13a9930d WS |
2488 | hostif_mib_get_request(priv, DOT11_MAC_ADDRESS); |
2489 | } | |
2490 | break; | |
2491 | case SME_MULTICAST_REQUEST: | |
2492 | hostif_sme_multicast_set(priv); | |
2493 | break; | |
2494 | case SME_MACADDRESS_SET_REQUEST: | |
2495 | hostif_mib_set_request(priv, LOCAL_CURRENTADDRESS, ETH_ALEN, | |
20c4f9c5 WS |
2496 | MIB_VALUE_TYPE_OSTRING, |
2497 | &priv->eth_addr[0]); | |
13a9930d WS |
2498 | break; |
2499 | case SME_BSS_SCAN_REQUEST: | |
20c4f9c5 WS |
2500 | hostif_bss_scan_request(priv, priv->reg.scan_type, |
2501 | priv->scan_ssid, priv->scan_ssid_len); | |
13a9930d WS |
2502 | break; |
2503 | case SME_POW_MNGMT_REQUEST: | |
2504 | hostif_sme_powermgt_set(priv); | |
2505 | break; | |
2506 | case SME_PHY_INFO_REQUEST: | |
2507 | hostif_phy_information_request(priv); | |
2508 | break; | |
2509 | case SME_MIC_FAILURE_REQUEST: | |
20c4f9c5 WS |
2510 | if (priv->wpa.mic_failure.failure == 1) { |
2511 | hostif_mic_failure_request(priv, | |
2512 | priv->wpa.mic_failure. | |
2513 | failure - 1, 0); | |
2514 | } else if (priv->wpa.mic_failure.failure == 2) { | |
2515 | hostif_mic_failure_request(priv, | |
2516 | priv->wpa.mic_failure. | |
2517 | failure - 1, | |
2518 | priv->wpa.mic_failure. | |
2519 | counter); | |
2520 | } else | |
2521 | DPRINTK(4, | |
2522 | "SME_MIC_FAILURE_REQUEST: failure count=%u error?\n", | |
13a9930d WS |
2523 | priv->wpa.mic_failure.failure); |
2524 | break; | |
2525 | case SME_MIC_FAILURE_CONFIRM: | |
20c4f9c5 WS |
2526 | if (priv->wpa.mic_failure.failure == 2) { |
2527 | if (priv->wpa.mic_failure.stop) | |
13a9930d WS |
2528 | priv->wpa.mic_failure.stop = 0; |
2529 | priv->wpa.mic_failure.failure = 0; | |
20c4f9c5 | 2530 | hostif_start_request(priv, priv->reg.operation_mode); |
13a9930d WS |
2531 | } |
2532 | break; | |
2533 | case SME_GET_MAC_ADDRESS: | |
20c4f9c5 | 2534 | if (priv->dev_state == DEVICE_STATE_BOOT) { |
13a9930d WS |
2535 | hostif_mib_get_request(priv, DOT11_PRODUCT_VERSION); |
2536 | } | |
2537 | break; | |
2538 | case SME_GET_PRODUCT_VERSION: | |
20c4f9c5 | 2539 | if (priv->dev_state == DEVICE_STATE_BOOT) { |
13a9930d WS |
2540 | priv->dev_state = DEVICE_STATE_PREINIT; |
2541 | } | |
2542 | break; | |
2543 | case SME_STOP_REQUEST: | |
2544 | hostif_stop_request(priv); | |
2545 | break; | |
2546 | case SME_RTS_THRESHOLD_REQUEST: | |
20c4f9c5 | 2547 | val = cpu_to_le32((uint32_t) (priv->reg.rts)); |
13a9930d | 2548 | hostif_mib_set_request(priv, DOT11_RTS_THRESHOLD, |
20c4f9c5 | 2549 | sizeof(val), MIB_VALUE_TYPE_INT, &val); |
13a9930d WS |
2550 | break; |
2551 | case SME_FRAGMENTATION_THRESHOLD_REQUEST: | |
20c4f9c5 | 2552 | val = cpu_to_le32((uint32_t) (priv->reg.fragment)); |
13a9930d | 2553 | hostif_mib_set_request(priv, DOT11_FRAGMENTATION_THRESHOLD, |
20c4f9c5 | 2554 | sizeof(val), MIB_VALUE_TYPE_INT, &val); |
13a9930d | 2555 | break; |
20c4f9c5 WS |
2556 | case SME_WEP_INDEX_REQUEST: |
2557 | case SME_WEP_KEY1_REQUEST: | |
2558 | case SME_WEP_KEY2_REQUEST: | |
2559 | case SME_WEP_KEY3_REQUEST: | |
2560 | case SME_WEP_KEY4_REQUEST: | |
2561 | case SME_WEP_FLAG_REQUEST: | |
2562 | hostif_sme_set_wep(priv, event); | |
13a9930d | 2563 | break; |
20c4f9c5 WS |
2564 | case SME_RSN_UCAST_REQUEST: |
2565 | case SME_RSN_MCAST_REQUEST: | |
2566 | case SME_RSN_AUTH_REQUEST: | |
2567 | case SME_RSN_ENABLED_REQUEST: | |
13a9930d | 2568 | case SME_RSN_MODE_REQUEST: |
20c4f9c5 | 2569 | hostif_sme_set_rsn(priv, event); |
13a9930d | 2570 | break; |
20c4f9c5 WS |
2571 | case SME_SET_FLAG: |
2572 | case SME_SET_TXKEY: | |
2573 | case SME_SET_KEY1: | |
2574 | case SME_SET_KEY2: | |
2575 | case SME_SET_KEY3: | |
2576 | case SME_SET_KEY4: | |
2577 | case SME_SET_PMK_TSC: | |
2578 | case SME_SET_GMK1_TSC: | |
13a9930d | 2579 | case SME_SET_GMK2_TSC: |
20c4f9c5 | 2580 | hostif_sme_set_key(priv, event); |
13a9930d WS |
2581 | break; |
2582 | case SME_SET_PMKSA: | |
2583 | hostif_sme_set_pmksa(priv); | |
2584 | break; | |
2585 | #ifdef WPS | |
2586 | case SME_WPS_ENABLE_REQUEST: | |
2587 | hostif_mib_set_request(priv, LOCAL_WPS_ENABLE, | |
2588 | sizeof(priv->wps.wps_enabled), | |
20c4f9c5 WS |
2589 | MIB_VALUE_TYPE_INT, |
2590 | &priv->wps.wps_enabled); | |
13a9930d WS |
2591 | break; |
2592 | case SME_WPS_PROBE_REQUEST: | |
2593 | hostif_mib_set_request(priv, LOCAL_WPS_PROBE_REQ, | |
2594 | priv->wps.ielen, | |
2595 | MIB_VALUE_TYPE_OSTRING, priv->wps.ie); | |
2596 | break; | |
2597 | #endif /* WPS */ | |
2598 | case SME_MODE_SET_REQUEST: | |
2599 | hostif_sme_mode_setup(priv); | |
2600 | break; | |
2601 | case SME_SET_GAIN: | |
2602 | hostif_mib_set_request(priv, LOCAL_GAIN, | |
20c4f9c5 WS |
2603 | sizeof(priv->gain), |
2604 | MIB_VALUE_TYPE_OSTRING, &priv->gain); | |
13a9930d WS |
2605 | break; |
2606 | case SME_GET_GAIN: | |
2607 | hostif_mib_get_request(priv, LOCAL_GAIN); | |
2608 | break; | |
2609 | case SME_GET_EEPROM_CKSUM: | |
2610 | priv->eeprom_checksum = EEPROM_FW_NOT_SUPPORT; /* initialize */ | |
2611 | hostif_mib_get_request(priv, LOCAL_EEPROM_SUM); | |
2612 | break; | |
2613 | case SME_START_REQUEST: | |
20c4f9c5 | 2614 | hostif_start_request(priv, priv->reg.operation_mode); |
13a9930d WS |
2615 | break; |
2616 | case SME_START_CONFIRM: | |
2617 | /* for power save */ | |
2618 | atomic_set(&priv->psstatus.snooze_guard, 0); | |
20c4f9c5 WS |
2619 | atomic_set(&priv->psstatus.confirm_wait, 0); |
2620 | if (priv->dev_state == DEVICE_STATE_PREINIT) { | |
13a9930d WS |
2621 | priv->dev_state = DEVICE_STATE_INIT; |
2622 | } | |
2623 | /* wake_up_interruptible_all(&priv->confirm_wait); */ | |
2624 | complete(&priv->confirm_wait); | |
2625 | break; | |
2626 | case SME_SLEEP_REQUEST: | |
2627 | hostif_sme_sleep_set(priv); | |
2628 | break; | |
2629 | case SME_SET_REGION: | |
20c4f9c5 | 2630 | val = cpu_to_le32((uint32_t) (priv->region)); |
13a9930d | 2631 | hostif_mib_set_request(priv, LOCAL_REGION, |
20c4f9c5 | 2632 | sizeof(val), MIB_VALUE_TYPE_INT, &val); |
13a9930d WS |
2633 | break; |
2634 | case SME_MULTICAST_CONFIRM: | |
2635 | case SME_BSS_SCAN_CONFIRM: | |
2636 | case SME_POW_MNGMT_CONFIRM: | |
2637 | case SME_PHY_INFO_CONFIRM: | |
2638 | case SME_STOP_CONFIRM: | |
2639 | case SME_RTS_THRESHOLD_CONFIRM: | |
2640 | case SME_FRAGMENTATION_THRESHOLD_CONFIRM: | |
20c4f9c5 WS |
2641 | case SME_WEP_INDEX_CONFIRM: |
2642 | case SME_WEP_KEY1_CONFIRM: | |
2643 | case SME_WEP_KEY2_CONFIRM: | |
2644 | case SME_WEP_KEY3_CONFIRM: | |
2645 | case SME_WEP_KEY4_CONFIRM: | |
2646 | case SME_WEP_FLAG_CONFIRM: | |
2647 | case SME_RSN_UCAST_CONFIRM: | |
2648 | case SME_RSN_MCAST_CONFIRM: | |
2649 | case SME_RSN_AUTH_CONFIRM: | |
2650 | case SME_RSN_ENABLED_CONFIRM: | |
13a9930d WS |
2651 | case SME_RSN_MODE_CONFIRM: |
2652 | case SME_MODE_SET_CONFIRM: | |
2653 | break; | |
2654 | case SME_TERMINATE: | |
2655 | default: | |
2656 | break; | |
2657 | } | |
2658 | } | |
2659 | ||
2660 | static | |
20c4f9c5 | 2661 | void hostif_sme_task(unsigned long dev) |
13a9930d | 2662 | { |
feedcf1a | 2663 | struct ks_wlan_private *priv = (struct ks_wlan_private *)dev; |
13a9930d | 2664 | |
20c4f9c5 | 2665 | DPRINTK(3, "\n"); |
13a9930d | 2666 | |
20c4f9c5 WS |
2667 | if (priv->dev_state >= DEVICE_STATE_BOOT) { |
2668 | if (0 < cnt_smeqbody(priv) | |
2669 | && priv->dev_state >= DEVICE_STATE_BOOT) { | |
2670 | hostif_sme_execute(priv, | |
2671 | priv->sme_i.event_buff[priv->sme_i. | |
2672 | qhead]); | |
13a9930d WS |
2673 | inc_smeqhead(priv); |
2674 | if (0 < cnt_smeqbody(priv)) | |
20c4f9c5 | 2675 | tasklet_schedule(&priv->sme_task); |
13a9930d WS |
2676 | } |
2677 | } | |
2678 | return; | |
2679 | } | |
2680 | ||
2681 | /* send to Station Management Entity module */ | |
feedcf1a | 2682 | void hostif_sme_enqueue(struct ks_wlan_private *priv, unsigned short event) |
13a9930d | 2683 | { |
20c4f9c5 | 2684 | DPRINTK(3, "\n"); |
13a9930d WS |
2685 | |
2686 | /* enqueue sme event */ | |
2687 | if (cnt_smeqbody(priv) < (SME_EVENT_BUFF_SIZE - 1)) { | |
2688 | priv->sme_i.event_buff[priv->sme_i.qtail] = event; | |
2689 | inc_smeqtail(priv); | |
2690 | //DPRINTK(3,"inc_smeqtail \n"); | |
2691 | #ifdef KS_WLAN_DEBUG | |
2692 | if (priv->sme_i.max_event_count < cnt_smeqbody(priv)) | |
2693 | priv->sme_i.max_event_count = cnt_smeqbody(priv); | |
2694 | #endif /* KS_WLAN_DEBUG */ | |
2695 | } else { | |
2696 | /* in case of buffer overflow */ | |
2697 | //DPRINTK(2,"sme queue buffer overflow\n"); | |
2698 | printk("sme queue buffer overflow\n"); | |
2699 | } | |
2700 | ||
2701 | tasklet_schedule(&priv->sme_task); | |
2702 | ||
2703 | } | |
2704 | ||
20c4f9c5 | 2705 | int hostif_init(struct ks_wlan_private *priv) |
13a9930d | 2706 | { |
20c4f9c5 | 2707 | int rc = 0; |
13a9930d WS |
2708 | int i; |
2709 | ||
20c4f9c5 | 2710 | DPRINTK(3, "\n"); |
13a9930d | 2711 | |
20c4f9c5 WS |
2712 | priv->aplist.size = 0; |
2713 | for (i = 0; i < LOCAL_APLIST_MAX; i++) | |
2714 | memset(&(priv->aplist.ap[i]), 0, sizeof(struct local_ap_t)); | |
13a9930d WS |
2715 | priv->infra_status = 0; |
2716 | priv->current_rate = 4; | |
2717 | priv->connect_status = DISCONNECT_STATUS; | |
2718 | ||
2719 | spin_lock_init(&priv->multicast_spin); | |
2720 | ||
2721 | spin_lock_init(&priv->dev_read_lock); | |
20c4f9c5 | 2722 | init_waitqueue_head(&priv->devread_wait); |
13a9930d WS |
2723 | priv->dev_count = 0; |
2724 | atomic_set(&priv->event_count, 0); | |
2725 | atomic_set(&priv->rec_count, 0); | |
2726 | ||
2727 | /* for power save */ | |
2728 | atomic_set(&priv->psstatus.status, PS_NONE); | |
2729 | atomic_set(&priv->psstatus.confirm_wait, 0); | |
2730 | atomic_set(&priv->psstatus.snooze_guard, 0); | |
2731 | /* init_waitqueue_head(&priv->psstatus.wakeup_wait); */ | |
2732 | init_completion(&priv->psstatus.wakeup_wait); | |
2733 | //INIT_WORK(&priv->ks_wlan_wakeup_task, ks_wlan_hw_wakeup_task, (void *)priv); | |
2734 | INIT_WORK(&priv->ks_wlan_wakeup_task, ks_wlan_hw_wakeup_task); | |
2735 | ||
2736 | /* WPA */ | |
2737 | memset(&(priv->wpa), 0, sizeof(priv->wpa)); | |
2738 | priv->wpa.rsn_enabled = 0; | |
2739 | priv->wpa.mic_failure.failure = 0; | |
2740 | priv->wpa.mic_failure.last_failure_time = 0; | |
2741 | priv->wpa.mic_failure.stop = 0; | |
2742 | memset(&(priv->pmklist), 0, sizeof(priv->pmklist)); | |
2743 | INIT_LIST_HEAD(&priv->pmklist.head); | |
20c4f9c5 | 2744 | for (i = 0; i < PMK_LIST_MAX; i++) |
13a9930d WS |
2745 | INIT_LIST_HEAD(&priv->pmklist.pmk[i].list); |
2746 | ||
2747 | priv->sme_i.sme_status = SME_IDLE; | |
2748 | priv->sme_i.qhead = priv->sme_i.qtail = 0; | |
2749 | #ifdef KS_WLAN_DEBUG | |
2750 | priv->sme_i.max_event_count = 0; | |
2751 | #endif | |
20c4f9c5 | 2752 | spin_lock_init(&priv->sme_i.sme_spin); |
13a9930d WS |
2753 | priv->sme_i.sme_flag = 0; |
2754 | ||
2755 | tasklet_init(&priv->sme_task, hostif_sme_task, (unsigned long)priv); | |
2756 | ||
2757 | return rc; | |
2758 | } | |
2759 | ||
20c4f9c5 | 2760 | void hostif_exit(struct ks_wlan_private *priv) |
13a9930d WS |
2761 | { |
2762 | tasklet_kill(&priv->sme_task); | |
2763 | return; | |
2764 | } |