1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Driver for KeyStream 11b/g wireless LAN |
4 | * |
5 | * Copyright (C) 2005-2008 KeyStream Corp. |
6 | * Copyright (C) 2009 Renesas Technology Corp. |
7 | */ |
8 | |
9 | #include <linux/atomic.h> |
10 | #include <linux/completion.h> |
11 | #include <linux/if_arp.h> |
12 | #include <linux/netdevice.h> |
13 | #include <linux/timer.h> |
14 | #include <linux/uaccess.h> |
15 | |
16 | static int wep_on_off; |
17 | #define WEP_OFF 0 |
18 | #define WEP_ON_64BIT 1 |
19 | #define WEP_ON_128BIT 2 |
20 | |
21 | #include "ks_wlan.h" |
22 | #include "ks_hostif.h" |
23 | #include "ks_wlan_ioctl.h" |
24 | |
25 | /* Include Wireless Extension definition and check version */ |
26 | #include <linux/wireless.h> |
27 | #define WIRELESS_SPY /* enable iwspy support */ |
28 | #include <net/iw_handler.h> /* New driver API */ |
29 | |
30 | /* Frequency list (map channels to frequencies) */ |
31 | static const long frequency_list[] = { |
32 | 2412, 2417, 2422, 2427, 2432, 2437, 2442, |
33 | 2447, 2452, 2457, 2462, 2467, 2472, 2484 |
34 | }; |
35 | |
36 | /* A few details needed for WEP (Wireless Equivalent Privacy) */ |
37 | #define MAX_KEY_SIZE 13 /* 128 (?) bits */ |
38 | #define MIN_KEY_SIZE 5 /* 40 bits RC4 - WEP */ |
39 | struct wep_key { |
40 | u16 len; |
41 | u8 key[16]; /* 40-bit and 104-bit keys */ |
42 | }; |
43 | |
44 | /* |
45 | * function prototypes |
46 | */ |
47 | static int ks_wlan_open(struct net_device *dev); |
48 | static void ks_wlan_tx_timeout(struct net_device *dev, unsigned int txqueue); |
49 | static netdev_tx_t ks_wlan_start_xmit(struct sk_buff *skb, struct net_device *dev); |
50 | static int ks_wlan_close(struct net_device *dev); |
51 | static void ks_wlan_set_rx_mode(struct net_device *dev); |
52 | static struct net_device_stats *ks_wlan_get_stats(struct net_device *dev); |
53 | static int ks_wlan_set_mac_address(struct net_device *dev, void *addr); |
54 | static int ks_wlan_netdev_ioctl(struct net_device *dev, struct ifreq *rq, |
55 | int cmd); |
56 | |
57 | static atomic_t update_phyinfo; |
58 | static struct timer_list update_phyinfo_timer; |
59 | static |
60 | int ks_wlan_update_phy_information(struct ks_wlan_private *priv) |
61 | { |
62 | struct iw_statistics *wstats = &priv->wstats; |
63 | |
64 | netdev_dbg(priv->net_dev, "in_interrupt = %ld\n" , in_interrupt()); |
65 | |
66 | if (priv->dev_state < DEVICE_STATE_READY) |
67 | return -EBUSY; /* not finished initialize */ |
68 | |
69 | if (atomic_read(v: &update_phyinfo)) |
70 | return -EPERM; |
71 | |
72 | /* The status */ |
73 | wstats->status = priv->reg.operation_mode; /* Operation mode */ |
74 | |
75 | /* Signal quality and co. But where is the noise level ??? */ |
76 | hostif_sme_enqueue(priv, event: SME_PHY_INFO_REQUEST); |
77 | |
78 | /* interruptible_sleep_on_timeout(&priv->confirm_wait, HZ/2); */ |
79 | if (!wait_for_completion_interruptible_timeout |
80 | (x: &priv->confirm_wait, HZ / 2)) { |
81 | netdev_dbg(priv->net_dev, "wait time out!!\n" ); |
82 | } |
83 | |
84 | atomic_inc(v: &update_phyinfo); |
85 | update_phyinfo_timer.expires = jiffies + HZ; /* 1sec */ |
86 | add_timer(timer: &update_phyinfo_timer); |
87 | |
88 | return 0; |
89 | } |
90 | |
91 | static |
92 | void ks_wlan_update_phyinfo_timeout(struct timer_list *unused) |
93 | { |
94 | pr_debug("in_interrupt = %ld\n" , in_interrupt()); |
95 | atomic_set(v: &update_phyinfo, i: 0); |
96 | } |
97 | |
98 | int ks_wlan_setup_parameter(struct ks_wlan_private *priv, |
99 | unsigned int commit_flag) |
100 | { |
101 | hostif_sme_enqueue(priv, event: SME_STOP_REQUEST); |
102 | |
103 | if (commit_flag & SME_RTS) |
104 | hostif_sme_enqueue(priv, event: SME_RTS_THRESHOLD_REQUEST); |
105 | if (commit_flag & SME_FRAG) |
106 | hostif_sme_enqueue(priv, event: SME_FRAGMENTATION_THRESHOLD_REQUEST); |
107 | |
108 | if (commit_flag & SME_WEP_INDEX) |
109 | hostif_sme_enqueue(priv, event: SME_WEP_INDEX_REQUEST); |
110 | if (commit_flag & SME_WEP_VAL1) |
111 | hostif_sme_enqueue(priv, event: SME_WEP_KEY1_REQUEST); |
112 | if (commit_flag & SME_WEP_VAL2) |
113 | hostif_sme_enqueue(priv, event: SME_WEP_KEY2_REQUEST); |
114 | if (commit_flag & SME_WEP_VAL3) |
115 | hostif_sme_enqueue(priv, event: SME_WEP_KEY3_REQUEST); |
116 | if (commit_flag & SME_WEP_VAL4) |
117 | hostif_sme_enqueue(priv, event: SME_WEP_KEY4_REQUEST); |
118 | if (commit_flag & SME_WEP_FLAG) |
119 | hostif_sme_enqueue(priv, event: SME_WEP_FLAG_REQUEST); |
120 | |
121 | if (commit_flag & SME_RSN) { |
122 | hostif_sme_enqueue(priv, event: SME_RSN_ENABLED_REQUEST); |
123 | hostif_sme_enqueue(priv, event: SME_RSN_MODE_REQUEST); |
124 | } |
125 | if (commit_flag & SME_RSN_MULTICAST) |
126 | hostif_sme_enqueue(priv, event: SME_RSN_MCAST_REQUEST); |
127 | if (commit_flag & SME_RSN_UNICAST) |
128 | hostif_sme_enqueue(priv, event: SME_RSN_UCAST_REQUEST); |
129 | if (commit_flag & SME_RSN_AUTH) |
130 | hostif_sme_enqueue(priv, event: SME_RSN_AUTH_REQUEST); |
131 | |
132 | hostif_sme_enqueue(priv, event: SME_MODE_SET_REQUEST); |
133 | |
134 | hostif_sme_enqueue(priv, event: SME_START_REQUEST); |
135 | |
136 | return 0; |
137 | } |
138 | |
139 | /* |
140 | * Initial Wireless Extension code for Ks_Wlannet driver by : |
141 | * Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00 |
142 | * Conversion to new driver API by : |
143 | * Jean Tourrilhes <jt@hpl.hp.com> - HPL - 26 March 02 |
144 | * Javier also did a good amount of work here, adding some new extensions |
145 | * and fixing my code. Let's just say that without him this code just |
146 | * would not work at all... - Jean II |
147 | */ |
148 | |
149 | static int ks_wlan_get_name(struct net_device *dev, |
150 | struct iw_request_info *info, |
151 | union iwreq_data *cwrq, |
152 | char *) |
153 | { |
154 | struct ks_wlan_private *priv = netdev_priv(dev); |
155 | |
156 | if (priv->sleep_mode == SLP_SLEEP) |
157 | return -EPERM; |
158 | |
159 | /* for SLEEP MODE */ |
160 | if (priv->dev_state < DEVICE_STATE_READY) |
161 | strscpy(cwrq->name, "NOT READY!" , sizeof(cwrq->name)); |
162 | else if (priv->reg.phy_type == D_11B_ONLY_MODE) |
163 | strscpy(cwrq->name, "IEEE 802.11b" , sizeof(cwrq->name)); |
164 | else if (priv->reg.phy_type == D_11G_ONLY_MODE) |
165 | strscpy(cwrq->name, "IEEE 802.11g" , sizeof(cwrq->name)); |
166 | else |
167 | strscpy(cwrq->name, "IEEE 802.11b/g" , sizeof(cwrq->name)); |
168 | |
169 | return 0; |
170 | } |
171 | |
172 | static int ks_wlan_set_freq(struct net_device *dev, |
173 | struct iw_request_info *info, |
174 | union iwreq_data *fwrq, char *) |
175 | { |
176 | struct ks_wlan_private *priv = netdev_priv(dev); |
177 | int channel; |
178 | |
179 | if (priv->sleep_mode == SLP_SLEEP) |
180 | return -EPERM; |
181 | |
182 | /* for SLEEP MODE */ |
183 | /* If setting by frequency, convert to a channel */ |
184 | if ((fwrq->freq.e == 1) && |
185 | (fwrq->freq.m >= 241200000) && (fwrq->freq.m <= 248700000)) { |
186 | int f = fwrq->freq.m / 100000; |
187 | int c = 0; |
188 | |
189 | while ((c < 14) && (f != frequency_list[c])) |
190 | c++; |
191 | /* Hack to fall through... */ |
192 | fwrq->freq.e = 0; |
193 | fwrq->freq.m = c + 1; |
194 | } |
195 | /* Setting by channel number */ |
196 | if ((fwrq->freq.m > 1000) || (fwrq->freq.e > 0)) |
197 | return -EOPNOTSUPP; |
198 | |
199 | channel = fwrq->freq.m; |
200 | /* We should do a better check than that, |
201 | * based on the card capability !!! |
202 | */ |
203 | if ((channel < 1) || (channel > 14)) { |
204 | netdev_dbg(dev, "%s: New channel value of %d is invalid!\n" , |
205 | dev->name, fwrq->freq.m); |
206 | return -EINVAL; |
207 | } |
208 | |
209 | /* Yes ! We can set it !!! */ |
210 | priv->reg.channel = (u8)(channel); |
211 | priv->need_commit |= SME_MODE_SET; |
212 | |
213 | return -EINPROGRESS; /* Call commit handler */ |
214 | } |
215 | |
216 | static int ks_wlan_get_freq(struct net_device *dev, |
217 | struct iw_request_info *info, |
218 | union iwreq_data *fwrq, char *) |
219 | { |
220 | struct ks_wlan_private *priv = netdev_priv(dev); |
221 | int f; |
222 | |
223 | if (priv->sleep_mode == SLP_SLEEP) |
224 | return -EPERM; |
225 | |
226 | /* for SLEEP MODE */ |
227 | if (is_connect_status(status: priv->connect_status)) |
228 | f = (int)priv->current_ap.channel; |
229 | else |
230 | f = (int)priv->reg.channel; |
231 | |
232 | fwrq->freq.m = frequency_list[f - 1] * 100000; |
233 | fwrq->freq.e = 1; |
234 | |
235 | return 0; |
236 | } |
237 | |
238 | static int ks_wlan_set_essid(struct net_device *dev, |
239 | struct iw_request_info *info, |
240 | union iwreq_data *dwrq, char *) |
241 | { |
242 | struct ks_wlan_private *priv = netdev_priv(dev); |
243 | size_t len; |
244 | |
245 | if (priv->sleep_mode == SLP_SLEEP) |
246 | return -EPERM; |
247 | |
248 | /* for SLEEP MODE */ |
249 | /* Check if we asked for `any' */ |
250 | if (!dwrq->essid.flags) { |
251 | /* Just send an empty SSID list */ |
252 | memset(priv->reg.ssid.body, 0, sizeof(priv->reg.ssid.body)); |
253 | priv->reg.ssid.size = 0; |
254 | } else { |
255 | len = dwrq->essid.length; |
256 | /* iwconfig uses nul termination in SSID.. */ |
257 | if (len > 0 && extra[len - 1] == '\0') |
258 | len--; |
259 | |
260 | /* Check the size of the string */ |
261 | if (len > IW_ESSID_MAX_SIZE) |
262 | return -EINVAL; |
263 | |
264 | /* Set the SSID */ |
265 | memset(priv->reg.ssid.body, 0, sizeof(priv->reg.ssid.body)); |
266 | memcpy(priv->reg.ssid.body, extra, len); |
267 | priv->reg.ssid.size = len; |
268 | } |
269 | /* Write it to the card */ |
270 | priv->need_commit |= SME_MODE_SET; |
271 | |
272 | ks_wlan_setup_parameter(priv, commit_flag: priv->need_commit); |
273 | priv->need_commit = 0; |
274 | return 0; |
275 | } |
276 | |
277 | static int ks_wlan_get_essid(struct net_device *dev, |
278 | struct iw_request_info *info, |
279 | union iwreq_data *dwrq, char *) |
280 | { |
281 | struct ks_wlan_private *priv = netdev_priv(dev); |
282 | |
283 | if (priv->sleep_mode == SLP_SLEEP) |
284 | return -EPERM; |
285 | |
286 | /* for SLEEP MODE */ |
287 | /* Note : if dwrq->flags != 0, we should |
288 | * get the relevant SSID from the SSID list... |
289 | */ |
290 | if (priv->reg.ssid.size != 0) { |
291 | /* Get the current SSID */ |
292 | memcpy(extra, priv->reg.ssid.body, priv->reg.ssid.size); |
293 | |
294 | /* If none, we may want to get the one that was set */ |
295 | |
296 | /* Push it out ! */ |
297 | dwrq->essid.length = priv->reg.ssid.size; |
298 | dwrq->essid.flags = 1; /* active */ |
299 | } else { |
300 | dwrq->essid.length = 0; |
301 | dwrq->essid.flags = 0; /* ANY */ |
302 | } |
303 | |
304 | return 0; |
305 | } |
306 | |
307 | static int ks_wlan_set_wap(struct net_device *dev, struct iw_request_info *info, |
308 | union iwreq_data *awrq, char *) |
309 | { |
310 | struct ks_wlan_private *priv = netdev_priv(dev); |
311 | |
312 | if (priv->sleep_mode == SLP_SLEEP) |
313 | return -EPERM; |
314 | |
315 | /* for SLEEP MODE */ |
316 | if (priv->reg.operation_mode != MODE_ADHOC && |
317 | priv->reg.operation_mode != MODE_INFRASTRUCTURE) { |
318 | eth_zero_addr(addr: priv->reg.bssid); |
319 | return -EOPNOTSUPP; |
320 | } |
321 | |
322 | ether_addr_copy(dst: priv->reg.bssid, src: awrq->ap_addr.sa_data); |
323 | if (is_valid_ether_addr(addr: (u8 *)priv->reg.bssid)) |
324 | priv->need_commit |= SME_MODE_SET; |
325 | |
326 | netdev_dbg(dev, "bssid = %pM\n" , priv->reg.bssid); |
327 | |
328 | /* Write it to the card */ |
329 | if (priv->need_commit) { |
330 | priv->need_commit |= SME_MODE_SET; |
331 | return -EINPROGRESS; /* Call commit handler */ |
332 | } |
333 | return 0; |
334 | } |
335 | |
336 | static int ks_wlan_get_wap(struct net_device *dev, struct iw_request_info *info, |
337 | union iwreq_data *awrq, char *) |
338 | { |
339 | struct ks_wlan_private *priv = netdev_priv(dev); |
340 | |
341 | if (priv->sleep_mode == SLP_SLEEP) |
342 | return -EPERM; |
343 | |
344 | /* for SLEEP MODE */ |
345 | if (is_connect_status(status: priv->connect_status)) |
346 | ether_addr_copy(dst: awrq->ap_addr.sa_data, src: priv->current_ap.bssid); |
347 | else |
348 | eth_zero_addr(addr: awrq->ap_addr.sa_data); |
349 | |
350 | awrq->ap_addr.sa_family = ARPHRD_ETHER; |
351 | |
352 | return 0; |
353 | } |
354 | |
355 | static int ks_wlan_set_nick(struct net_device *dev, |
356 | struct iw_request_info *info, |
357 | union iwreq_data *dwrq, char *) |
358 | { |
359 | struct ks_wlan_private *priv = netdev_priv(dev); |
360 | |
361 | if (priv->sleep_mode == SLP_SLEEP) |
362 | return -EPERM; |
363 | |
364 | /* for SLEEP MODE */ |
365 | /* Check the size of the string */ |
366 | if (dwrq->data.length > 16 + 1) |
367 | return -E2BIG; |
368 | |
369 | memset(priv->nick, 0, sizeof(priv->nick)); |
370 | memcpy(priv->nick, extra, dwrq->data.length); |
371 | |
372 | return -EINPROGRESS; /* Call commit handler */ |
373 | } |
374 | |
375 | static int ks_wlan_get_nick(struct net_device *dev, |
376 | struct iw_request_info *info, |
377 | union iwreq_data *dwrq, char *) |
378 | { |
379 | struct ks_wlan_private *priv = netdev_priv(dev); |
380 | |
381 | if (priv->sleep_mode == SLP_SLEEP) |
382 | return -EPERM; |
383 | |
384 | /* for SLEEP MODE */ |
385 | strscpy(extra, priv->nick, 17); |
386 | dwrq->data.length = strlen(extra) + 1; |
387 | |
388 | return 0; |
389 | } |
390 | |
391 | static int ks_wlan_set_rate(struct net_device *dev, |
392 | struct iw_request_info *info, |
393 | union iwreq_data *vwrq, char *) |
394 | { |
395 | struct ks_wlan_private *priv = netdev_priv(dev); |
396 | int i = 0; |
397 | |
398 | if (priv->sleep_mode == SLP_SLEEP) |
399 | return -EPERM; |
400 | |
401 | /* for SLEEP MODE */ |
402 | if (priv->reg.phy_type == D_11B_ONLY_MODE) { |
403 | if (vwrq->bitrate.fixed == 1) { |
404 | switch (vwrq->bitrate.value) { |
405 | case 11000000: |
406 | case 5500000: |
407 | priv->reg.rate_set.body[0] = |
408 | (u8)(vwrq->bitrate.value / 500000); |
409 | break; |
410 | case 2000000: |
411 | case 1000000: |
412 | priv->reg.rate_set.body[0] = |
413 | ((u8)(vwrq->bitrate.value / 500000)) | |
414 | BASIC_RATE; |
415 | break; |
416 | default: |
417 | return -EINVAL; |
418 | } |
419 | priv->reg.tx_rate = TX_RATE_FIXED; |
420 | priv->reg.rate_set.size = 1; |
421 | } else { /* vwrq->fixed == 0 */ |
422 | if (vwrq->bitrate.value > 0) { |
423 | switch (vwrq->bitrate.value) { |
424 | case 11000000: |
425 | priv->reg.rate_set.body[3] = |
426 | TX_RATE_11M; |
427 | i++; |
428 | fallthrough; |
429 | case 5500000: |
430 | priv->reg.rate_set.body[2] = TX_RATE_5M; |
431 | i++; |
432 | fallthrough; |
433 | case 2000000: |
434 | priv->reg.rate_set.body[1] = |
435 | TX_RATE_2M | BASIC_RATE; |
436 | i++; |
437 | fallthrough; |
438 | case 1000000: |
439 | priv->reg.rate_set.body[0] = |
440 | TX_RATE_1M | BASIC_RATE; |
441 | i++; |
442 | break; |
443 | default: |
444 | return -EINVAL; |
445 | } |
446 | priv->reg.tx_rate = TX_RATE_MANUAL_AUTO; |
447 | priv->reg.rate_set.size = i; |
448 | } else { |
449 | priv->reg.rate_set.body[3] = TX_RATE_11M; |
450 | priv->reg.rate_set.body[2] = TX_RATE_5M; |
451 | priv->reg.rate_set.body[1] = |
452 | TX_RATE_2M | BASIC_RATE; |
453 | priv->reg.rate_set.body[0] = |
454 | TX_RATE_1M | BASIC_RATE; |
455 | priv->reg.tx_rate = TX_RATE_FULL_AUTO; |
456 | priv->reg.rate_set.size = 4; |
457 | } |
458 | } |
459 | } else { /* D_11B_ONLY_MODE or D_11BG_COMPATIBLE_MODE */ |
460 | if (vwrq->bitrate.fixed == 1) { |
461 | switch (vwrq->bitrate.value) { |
462 | case 54000000: |
463 | case 48000000: |
464 | case 36000000: |
465 | case 18000000: |
466 | case 9000000: |
467 | priv->reg.rate_set.body[0] = |
468 | (u8)(vwrq->bitrate.value / 500000); |
469 | break; |
470 | case 24000000: |
471 | case 12000000: |
472 | case 11000000: |
473 | case 6000000: |
474 | case 5500000: |
475 | case 2000000: |
476 | case 1000000: |
477 | priv->reg.rate_set.body[0] = |
478 | ((u8)(vwrq->bitrate.value / 500000)) | |
479 | BASIC_RATE; |
480 | break; |
481 | default: |
482 | return -EINVAL; |
483 | } |
484 | priv->reg.tx_rate = TX_RATE_FIXED; |
485 | priv->reg.rate_set.size = 1; |
486 | } else { /* vwrq->fixed == 0 */ |
487 | if (vwrq->bitrate.value > 0) { |
488 | switch (vwrq->bitrate.value) { |
489 | case 54000000: |
490 | priv->reg.rate_set.body[11] = |
491 | TX_RATE_54M; |
492 | i++; |
493 | fallthrough; |
494 | case 48000000: |
495 | priv->reg.rate_set.body[10] = |
496 | TX_RATE_48M; |
497 | i++; |
498 | fallthrough; |
499 | case 36000000: |
500 | priv->reg.rate_set.body[9] = |
501 | TX_RATE_36M; |
502 | i++; |
503 | fallthrough; |
504 | case 24000000: |
505 | case 18000000: |
506 | case 12000000: |
507 | case 11000000: |
508 | case 9000000: |
509 | case 6000000: |
510 | if (vwrq->bitrate.value == 24000000) { |
511 | priv->reg.rate_set.body[8] = |
512 | TX_RATE_18M; |
513 | i++; |
514 | priv->reg.rate_set.body[7] = |
515 | TX_RATE_9M; |
516 | i++; |
517 | priv->reg.rate_set.body[6] = |
518 | TX_RATE_24M | BASIC_RATE; |
519 | i++; |
520 | priv->reg.rate_set.body[5] = |
521 | TX_RATE_12M | BASIC_RATE; |
522 | i++; |
523 | priv->reg.rate_set.body[4] = |
524 | TX_RATE_6M | BASIC_RATE; |
525 | i++; |
526 | priv->reg.rate_set.body[3] = |
527 | TX_RATE_11M | BASIC_RATE; |
528 | i++; |
529 | } else if (vwrq->bitrate.value == 18000000) { |
530 | priv->reg.rate_set.body[7] = |
531 | TX_RATE_18M; |
532 | i++; |
533 | priv->reg.rate_set.body[6] = |
534 | TX_RATE_9M; |
535 | i++; |
536 | priv->reg.rate_set.body[5] = |
537 | TX_RATE_12M | BASIC_RATE; |
538 | i++; |
539 | priv->reg.rate_set.body[4] = |
540 | TX_RATE_6M | BASIC_RATE; |
541 | i++; |
542 | priv->reg.rate_set.body[3] = |
543 | TX_RATE_11M | BASIC_RATE; |
544 | i++; |
545 | } else if (vwrq->bitrate.value == 12000000) { |
546 | priv->reg.rate_set.body[6] = |
547 | TX_RATE_9M; |
548 | i++; |
549 | priv->reg.rate_set.body[5] = |
550 | TX_RATE_12M | BASIC_RATE; |
551 | i++; |
552 | priv->reg.rate_set.body[4] = |
553 | TX_RATE_6M | BASIC_RATE; |
554 | i++; |
555 | priv->reg.rate_set.body[3] = |
556 | TX_RATE_11M | BASIC_RATE; |
557 | i++; |
558 | } else if (vwrq->bitrate.value == 11000000) { |
559 | priv->reg.rate_set.body[5] = |
560 | TX_RATE_9M; |
561 | i++; |
562 | priv->reg.rate_set.body[4] = |
563 | TX_RATE_6M | BASIC_RATE; |
564 | i++; |
565 | priv->reg.rate_set.body[3] = |
566 | TX_RATE_11M | BASIC_RATE; |
567 | i++; |
568 | } else if (vwrq->bitrate.value == 9000000) { |
569 | priv->reg.rate_set.body[4] = |
570 | TX_RATE_9M; |
571 | i++; |
572 | priv->reg.rate_set.body[3] = |
573 | TX_RATE_6M | BASIC_RATE; |
574 | i++; |
575 | } else { /* vwrq->value == 6000000 */ |
576 | priv->reg.rate_set.body[3] = |
577 | TX_RATE_6M | BASIC_RATE; |
578 | i++; |
579 | } |
580 | fallthrough; |
581 | case 5500000: |
582 | priv->reg.rate_set.body[2] = |
583 | TX_RATE_5M | BASIC_RATE; |
584 | i++; |
585 | fallthrough; |
586 | case 2000000: |
587 | priv->reg.rate_set.body[1] = |
588 | TX_RATE_2M | BASIC_RATE; |
589 | i++; |
590 | fallthrough; |
591 | case 1000000: |
592 | priv->reg.rate_set.body[0] = |
593 | TX_RATE_1M | BASIC_RATE; |
594 | i++; |
595 | break; |
596 | default: |
597 | return -EINVAL; |
598 | } |
599 | priv->reg.tx_rate = TX_RATE_MANUAL_AUTO; |
600 | priv->reg.rate_set.size = i; |
601 | } else { |
602 | priv->reg.rate_set.body[11] = TX_RATE_54M; |
603 | priv->reg.rate_set.body[10] = TX_RATE_48M; |
604 | priv->reg.rate_set.body[9] = TX_RATE_36M; |
605 | priv->reg.rate_set.body[8] = TX_RATE_18M; |
606 | priv->reg.rate_set.body[7] = TX_RATE_9M; |
607 | priv->reg.rate_set.body[6] = |
608 | TX_RATE_24M | BASIC_RATE; |
609 | priv->reg.rate_set.body[5] = |
610 | TX_RATE_12M | BASIC_RATE; |
611 | priv->reg.rate_set.body[4] = |
612 | TX_RATE_6M | BASIC_RATE; |
613 | priv->reg.rate_set.body[3] = |
614 | TX_RATE_11M | BASIC_RATE; |
615 | priv->reg.rate_set.body[2] = |
616 | TX_RATE_5M | BASIC_RATE; |
617 | priv->reg.rate_set.body[1] = |
618 | TX_RATE_2M | BASIC_RATE; |
619 | priv->reg.rate_set.body[0] = |
620 | TX_RATE_1M | BASIC_RATE; |
621 | priv->reg.tx_rate = TX_RATE_FULL_AUTO; |
622 | priv->reg.rate_set.size = 12; |
623 | } |
624 | } |
625 | } |
626 | |
627 | priv->need_commit |= SME_MODE_SET; |
628 | |
629 | return -EINPROGRESS; /* Call commit handler */ |
630 | } |
631 | |
632 | static int ks_wlan_get_rate(struct net_device *dev, |
633 | struct iw_request_info *info, |
634 | union iwreq_data *vwrq, char *) |
635 | { |
636 | struct ks_wlan_private *priv = netdev_priv(dev); |
637 | |
638 | netdev_dbg(dev, "in_interrupt = %ld update_phyinfo = %d\n" , |
639 | in_interrupt(), atomic_read(&update_phyinfo)); |
640 | |
641 | if (priv->sleep_mode == SLP_SLEEP) |
642 | return -EPERM; |
643 | |
644 | /* for SLEEP MODE */ |
645 | if (!atomic_read(v: &update_phyinfo)) |
646 | ks_wlan_update_phy_information(priv); |
647 | |
648 | vwrq->bitrate.value = ((priv->current_rate) & RATE_MASK) * 500000; |
649 | vwrq->bitrate.fixed = (priv->reg.tx_rate == TX_RATE_FIXED) ? 1 : 0; |
650 | |
651 | return 0; |
652 | } |
653 | |
654 | static int ks_wlan_set_rts(struct net_device *dev, struct iw_request_info *info, |
655 | union iwreq_data *vwrq, char *) |
656 | { |
657 | struct ks_wlan_private *priv = netdev_priv(dev); |
658 | int rthr = vwrq->rts.value; |
659 | |
660 | if (priv->sleep_mode == SLP_SLEEP) |
661 | return -EPERM; |
662 | |
663 | /* for SLEEP MODE */ |
664 | if (vwrq->rts.disabled) |
665 | rthr = 2347; |
666 | if ((rthr < 0) || (rthr > 2347)) |
667 | return -EINVAL; |
668 | |
669 | priv->reg.rts = rthr; |
670 | priv->need_commit |= SME_RTS; |
671 | |
672 | return -EINPROGRESS; /* Call commit handler */ |
673 | } |
674 | |
675 | static int ks_wlan_get_rts(struct net_device *dev, struct iw_request_info *info, |
676 | union iwreq_data *vwrq, char *) |
677 | { |
678 | struct ks_wlan_private *priv = netdev_priv(dev); |
679 | |
680 | if (priv->sleep_mode == SLP_SLEEP) |
681 | return -EPERM; |
682 | |
683 | /* for SLEEP MODE */ |
684 | vwrq->rts.value = priv->reg.rts; |
685 | vwrq->rts.disabled = (vwrq->rts.value >= 2347); |
686 | vwrq->rts.fixed = 1; |
687 | |
688 | return 0; |
689 | } |
690 | |
691 | static int ks_wlan_set_frag(struct net_device *dev, |
692 | struct iw_request_info *info, |
693 | union iwreq_data *vwrq, char *) |
694 | { |
695 | struct ks_wlan_private *priv = netdev_priv(dev); |
696 | int fthr = vwrq->frag.value; |
697 | |
698 | if (priv->sleep_mode == SLP_SLEEP) |
699 | return -EPERM; |
700 | |
701 | /* for SLEEP MODE */ |
702 | if (vwrq->frag.disabled) |
703 | fthr = 2346; |
704 | if ((fthr < 256) || (fthr > 2346)) |
705 | return -EINVAL; |
706 | |
707 | fthr &= ~0x1; /* Get an even value - is it really needed ??? */ |
708 | priv->reg.fragment = fthr; |
709 | priv->need_commit |= SME_FRAG; |
710 | |
711 | return -EINPROGRESS; /* Call commit handler */ |
712 | } |
713 | |
714 | static int ks_wlan_get_frag(struct net_device *dev, |
715 | struct iw_request_info *info, |
716 | union iwreq_data *vwrq, char *) |
717 | { |
718 | struct ks_wlan_private *priv = netdev_priv(dev); |
719 | |
720 | if (priv->sleep_mode == SLP_SLEEP) |
721 | return -EPERM; |
722 | |
723 | /* for SLEEP MODE */ |
724 | vwrq->frag.value = priv->reg.fragment; |
725 | vwrq->frag.disabled = (vwrq->frag.value >= 2346); |
726 | vwrq->frag.fixed = 1; |
727 | |
728 | return 0; |
729 | } |
730 | |
731 | static int ks_wlan_set_mode(struct net_device *dev, |
732 | struct iw_request_info *info, |
733 | union iwreq_data *uwrq, char *) |
734 | { |
735 | struct ks_wlan_private *priv = netdev_priv(dev); |
736 | |
737 | if (priv->sleep_mode == SLP_SLEEP) |
738 | return -EPERM; |
739 | |
740 | if (uwrq->mode != IW_MODE_ADHOC && |
741 | uwrq->mode != IW_MODE_INFRA) |
742 | return -EINVAL; |
743 | |
744 | priv->reg.operation_mode = (uwrq->mode == IW_MODE_ADHOC) ? |
745 | MODE_ADHOC : MODE_INFRASTRUCTURE; |
746 | priv->need_commit |= SME_MODE_SET; |
747 | |
748 | return -EINPROGRESS; /* Call commit handler */ |
749 | } |
750 | |
751 | static int ks_wlan_get_mode(struct net_device *dev, |
752 | struct iw_request_info *info, |
753 | union iwreq_data *uwrq, char *) |
754 | { |
755 | struct ks_wlan_private *priv = netdev_priv(dev); |
756 | |
757 | if (priv->sleep_mode == SLP_SLEEP) |
758 | return -EPERM; |
759 | |
760 | /* If not managed, assume it's ad-hoc */ |
761 | uwrq->mode = (priv->reg.operation_mode == MODE_INFRASTRUCTURE) ? |
762 | IW_MODE_INFRA : IW_MODE_ADHOC; |
763 | |
764 | return 0; |
765 | } |
766 | |
767 | static int ks_wlan_set_encode(struct net_device *dev, |
768 | struct iw_request_info *info, |
769 | union iwreq_data *dwrq, char *) |
770 | { |
771 | struct ks_wlan_private *priv = netdev_priv(dev); |
772 | struct iw_point *enc = &dwrq->encoding; |
773 | struct wep_key key; |
774 | int index = (enc->flags & IW_ENCODE_INDEX); |
775 | |
776 | if (priv->sleep_mode == SLP_SLEEP) |
777 | return -EPERM; |
778 | |
779 | if (enc->length > MAX_KEY_SIZE) |
780 | return -EINVAL; |
781 | |
782 | /* for SLEEP MODE */ |
783 | if ((index < 0) || (index > 4)) |
784 | return -EINVAL; |
785 | |
786 | index = (index == 0) ? priv->reg.wep_index : (index - 1); |
787 | |
788 | /* Is WEP supported ? */ |
789 | /* Basic checking: do we have a key to set ? */ |
790 | if (enc->length > 0) { |
791 | key.len = (enc->length > MIN_KEY_SIZE) ? |
792 | MAX_KEY_SIZE : MIN_KEY_SIZE; |
793 | priv->reg.privacy_invoked = 0x01; |
794 | priv->need_commit |= SME_WEP_FLAG; |
795 | wep_on_off = (enc->length > MIN_KEY_SIZE) ? |
796 | WEP_ON_128BIT : WEP_ON_64BIT; |
797 | /* Check if the key is not marked as invalid */ |
798 | if (enc->flags & IW_ENCODE_NOKEY) |
799 | return 0; |
800 | |
801 | /* Cleanup */ |
802 | memset(key.key, 0, MAX_KEY_SIZE); |
803 | /* Copy the key in the driver */ |
804 | if (copy_from_user(to: key.key, from: enc->pointer, n: enc->length)) { |
805 | key.len = 0; |
806 | return -EFAULT; |
807 | } |
808 | /* Send the key to the card */ |
809 | priv->reg.wep_key[index].size = key.len; |
810 | memcpy(&priv->reg.wep_key[index].val[0], &key.key[0], |
811 | priv->reg.wep_key[index].size); |
812 | priv->need_commit |= (SME_WEP_VAL1 << index); |
813 | priv->reg.wep_index = index; |
814 | priv->need_commit |= SME_WEP_INDEX; |
815 | } else { |
816 | if (enc->flags & IW_ENCODE_DISABLED) { |
817 | priv->reg.wep_key[0].size = 0; |
818 | priv->reg.wep_key[1].size = 0; |
819 | priv->reg.wep_key[2].size = 0; |
820 | priv->reg.wep_key[3].size = 0; |
821 | priv->reg.privacy_invoked = 0x00; |
822 | if (priv->reg.authenticate_type == AUTH_TYPE_SHARED_KEY) |
823 | priv->need_commit |= SME_MODE_SET; |
824 | |
825 | priv->reg.authenticate_type = AUTH_TYPE_OPEN_SYSTEM; |
826 | wep_on_off = WEP_OFF; |
827 | priv->need_commit |= SME_WEP_FLAG; |
828 | } else { |
829 | /* set_wep_key(priv, index, 0, 0, 1); xxx */ |
830 | if (priv->reg.wep_key[index].size == 0) |
831 | return -EINVAL; |
832 | priv->reg.wep_index = index; |
833 | priv->need_commit |= SME_WEP_INDEX; |
834 | } |
835 | } |
836 | |
837 | /* Commit the changes if needed */ |
838 | if (enc->flags & IW_ENCODE_MODE) |
839 | priv->need_commit |= SME_WEP_FLAG; |
840 | |
841 | if (enc->flags & IW_ENCODE_OPEN) { |
842 | if (priv->reg.authenticate_type == AUTH_TYPE_SHARED_KEY) |
843 | priv->need_commit |= SME_MODE_SET; |
844 | |
845 | priv->reg.authenticate_type = AUTH_TYPE_OPEN_SYSTEM; |
846 | } else if (enc->flags & IW_ENCODE_RESTRICTED) { |
847 | if (priv->reg.authenticate_type == AUTH_TYPE_OPEN_SYSTEM) |
848 | priv->need_commit |= SME_MODE_SET; |
849 | |
850 | priv->reg.authenticate_type = AUTH_TYPE_SHARED_KEY; |
851 | } |
852 | if (priv->need_commit) { |
853 | ks_wlan_setup_parameter(priv, commit_flag: priv->need_commit); |
854 | priv->need_commit = 0; |
855 | } |
856 | return 0; |
857 | } |
858 | |
859 | static int ks_wlan_get_encode(struct net_device *dev, |
860 | struct iw_request_info *info, |
861 | union iwreq_data *dwrq, char *) |
862 | { |
863 | struct ks_wlan_private *priv = netdev_priv(dev); |
864 | struct iw_point *enc = &dwrq->encoding; |
865 | int index = (enc->flags & IW_ENCODE_INDEX) - 1; |
866 | |
867 | if (priv->sleep_mode == SLP_SLEEP) |
868 | return -EPERM; |
869 | |
870 | /* for SLEEP MODE */ |
871 | enc->flags = IW_ENCODE_DISABLED; |
872 | |
873 | /* Check encryption mode */ |
874 | switch (priv->reg.authenticate_type) { |
875 | case AUTH_TYPE_OPEN_SYSTEM: |
876 | enc->flags = IW_ENCODE_OPEN; |
877 | break; |
878 | case AUTH_TYPE_SHARED_KEY: |
879 | enc->flags = IW_ENCODE_RESTRICTED; |
880 | break; |
881 | } |
882 | |
883 | /* Which key do we want ? -1 -> tx index */ |
884 | if ((index < 0) || (index >= 4)) |
885 | index = priv->reg.wep_index; |
886 | if (priv->reg.privacy_invoked) { |
887 | enc->flags &= ~IW_ENCODE_DISABLED; |
888 | /* dwrq->flags |= IW_ENCODE_NOKEY; */ |
889 | } |
890 | enc->flags |= index + 1; |
891 | /* Copy the key to the user buffer */ |
892 | if (index >= 0 && index < 4) { |
893 | enc->length = (priv->reg.wep_key[index].size <= 16) ? |
894 | priv->reg.wep_key[index].size : 0; |
895 | memcpy(extra, priv->reg.wep_key[index].val, enc->length); |
896 | } |
897 | |
898 | return 0; |
899 | } |
900 | |
901 | static int ks_wlan_get_range(struct net_device *dev, |
902 | struct iw_request_info *info, |
903 | union iwreq_data *dwrq, char *) |
904 | { |
905 | struct ks_wlan_private *priv = netdev_priv(dev); |
906 | struct iw_range *range = (struct iw_range *)extra; |
907 | int i, k; |
908 | |
909 | if (priv->sleep_mode == SLP_SLEEP) |
910 | return -EPERM; |
911 | |
912 | /* for SLEEP MODE */ |
913 | dwrq->data.length = sizeof(struct iw_range); |
914 | memset(range, 0, sizeof(*range)); |
915 | range->min_nwid = 0x0000; |
916 | range->max_nwid = 0x0000; |
917 | range->num_channels = 14; |
918 | /* Should be based on cap_rid.country to give only |
919 | * what the current card support |
920 | */ |
921 | k = 0; |
922 | for (i = 0; i < 13; i++) { /* channel 1 -- 13 */ |
923 | range->freq[k].i = i + 1; /* List index */ |
924 | range->freq[k].m = frequency_list[i] * 100000; |
925 | range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */ |
926 | } |
927 | range->num_frequency = k; |
928 | if (priv->reg.phy_type == D_11B_ONLY_MODE || |
929 | priv->reg.phy_type == D_11BG_COMPATIBLE_MODE) { /* channel 14 */ |
930 | range->freq[13].i = 14; /* List index */ |
931 | range->freq[13].m = frequency_list[13] * 100000; |
932 | range->freq[13].e = 1; /* Values in table in MHz -> * 10^5 * 10 */ |
933 | range->num_frequency = 14; |
934 | } |
935 | |
936 | /* Hum... Should put the right values there */ |
937 | range->max_qual.qual = 100; |
938 | range->max_qual.level = 256 - 128; /* 0 dBm? */ |
939 | range->max_qual.noise = 256 - 128; |
940 | range->sensitivity = 1; |
941 | |
942 | if (priv->reg.phy_type == D_11B_ONLY_MODE) { |
943 | range->bitrate[0] = 1e6; |
944 | range->bitrate[1] = 2e6; |
945 | range->bitrate[2] = 5.5e6; |
946 | range->bitrate[3] = 11e6; |
947 | range->num_bitrates = 4; |
948 | } else { /* D_11G_ONLY_MODE or D_11BG_COMPATIBLE_MODE */ |
949 | range->bitrate[0] = 1e6; |
950 | range->bitrate[1] = 2e6; |
951 | range->bitrate[2] = 5.5e6; |
952 | range->bitrate[3] = 11e6; |
953 | |
954 | range->bitrate[4] = 6e6; |
955 | range->bitrate[5] = 9e6; |
956 | range->bitrate[6] = 12e6; |
957 | if (IW_MAX_BITRATES < 9) { |
958 | range->bitrate[7] = 54e6; |
959 | range->num_bitrates = 8; |
960 | } else { |
961 | range->bitrate[7] = 18e6; |
962 | range->bitrate[8] = 24e6; |
963 | range->bitrate[9] = 36e6; |
964 | range->bitrate[10] = 48e6; |
965 | range->bitrate[11] = 54e6; |
966 | |
967 | range->num_bitrates = 12; |
968 | } |
969 | } |
970 | |
971 | /* Set an indication of the max TCP throughput |
972 | * in bit/s that we can expect using this interface. |
973 | * May be use for QoS stuff... Jean II |
974 | */ |
975 | if (i > 2) |
976 | range->throughput = 5000 * 1000; |
977 | else |
978 | range->throughput = 1500 * 1000; |
979 | |
980 | range->min_rts = 0; |
981 | range->max_rts = 2347; |
982 | range->min_frag = 256; |
983 | range->max_frag = 2346; |
984 | |
985 | range->encoding_size[0] = 5; /* WEP: RC4 40 bits */ |
986 | range->encoding_size[1] = 13; /* WEP: RC4 ~128 bits */ |
987 | range->num_encoding_sizes = 2; |
988 | range->max_encoding_tokens = 4; |
989 | |
990 | /* power management not support */ |
991 | range->pmp_flags = IW_POWER_ON; |
992 | range->pmt_flags = IW_POWER_ON; |
993 | range->pm_capa = 0; |
994 | |
995 | /* Transmit Power - values are in dBm( or mW) */ |
996 | range->txpower[0] = -256; |
997 | range->num_txpower = 1; |
998 | range->txpower_capa = IW_TXPOW_DBM; |
999 | /* range->txpower_capa = IW_TXPOW_MWATT; */ |
1000 | |
1001 | range->we_version_source = 21; |
1002 | range->we_version_compiled = WIRELESS_EXT; |
1003 | |
1004 | range->retry_capa = IW_RETRY_ON; |
1005 | range->retry_flags = IW_RETRY_ON; |
1006 | range->r_time_flags = IW_RETRY_ON; |
1007 | |
1008 | /* Experimental measurements - boundary 11/5.5 Mb/s |
1009 | * |
1010 | * Note : with or without the (local->rssi), results |
1011 | * are somewhat different. - Jean II |
1012 | */ |
1013 | range->avg_qual.qual = 50; |
1014 | range->avg_qual.level = 186; /* -70 dBm */ |
1015 | range->avg_qual.noise = 0; |
1016 | |
1017 | /* Event capability (kernel + driver) */ |
1018 | range->event_capa[0] = (IW_EVENT_CAPA_K_0 | |
1019 | IW_EVENT_CAPA_MASK(SIOCGIWAP) | |
1020 | IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); |
1021 | range->event_capa[1] = IW_EVENT_CAPA_K_1; |
1022 | range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVCUSTOM) | |
1023 | IW_EVENT_CAPA_MASK(IWEVMICHAELMICFAILURE)); |
1024 | |
1025 | /* encode extension (WPA) capability */ |
1026 | range->enc_capa = (IW_ENC_CAPA_WPA | |
1027 | IW_ENC_CAPA_WPA2 | |
1028 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP); |
1029 | return 0; |
1030 | } |
1031 | |
1032 | static int ks_wlan_set_power(struct net_device *dev, |
1033 | struct iw_request_info *info, |
1034 | union iwreq_data *vwrq, char *) |
1035 | { |
1036 | struct ks_wlan_private *priv = netdev_priv(dev); |
1037 | |
1038 | if (priv->sleep_mode == SLP_SLEEP) |
1039 | return -EPERM; |
1040 | |
1041 | if (vwrq->power.disabled) { |
1042 | priv->reg.power_mgmt = POWER_MGMT_ACTIVE; |
1043 | } else { |
1044 | if (priv->reg.operation_mode != MODE_INFRASTRUCTURE) |
1045 | return -EINVAL; |
1046 | priv->reg.power_mgmt = POWER_MGMT_SAVE1; |
1047 | } |
1048 | |
1049 | hostif_sme_enqueue(priv, event: SME_POW_MNGMT_REQUEST); |
1050 | |
1051 | return 0; |
1052 | } |
1053 | |
1054 | static int ks_wlan_get_power(struct net_device *dev, |
1055 | struct iw_request_info *info, |
1056 | union iwreq_data *vwrq, char *) |
1057 | { |
1058 | struct ks_wlan_private *priv = netdev_priv(dev); |
1059 | |
1060 | if (priv->sleep_mode == SLP_SLEEP) |
1061 | return -EPERM; |
1062 | /* for SLEEP MODE */ |
1063 | vwrq->power.disabled = (priv->reg.power_mgmt <= 0); |
1064 | |
1065 | return 0; |
1066 | } |
1067 | |
1068 | static int ks_wlan_get_iwstats(struct net_device *dev, |
1069 | struct iw_request_info *info, |
1070 | union iwreq_data *vwrq, char *) |
1071 | { |
1072 | struct ks_wlan_private *priv = netdev_priv(dev); |
1073 | |
1074 | if (priv->sleep_mode == SLP_SLEEP) |
1075 | return -EPERM; |
1076 | /* for SLEEP MODE */ |
1077 | vwrq->qual.qual = 0; /* not supported */ |
1078 | vwrq->qual.level = priv->wstats.qual.level; |
1079 | vwrq->qual.noise = 0; /* not supported */ |
1080 | vwrq->qual.updated = 0; |
1081 | |
1082 | return 0; |
1083 | } |
1084 | |
1085 | /* Note : this is deprecated in favor of IWSCAN */ |
1086 | static int ks_wlan_get_aplist(struct net_device *dev, |
1087 | struct iw_request_info *info, |
1088 | union iwreq_data *dwrq, char *) |
1089 | { |
1090 | struct ks_wlan_private *priv = netdev_priv(dev); |
1091 | struct sockaddr *address = (struct sockaddr *)extra; |
1092 | struct iw_quality qual[LOCAL_APLIST_MAX]; |
1093 | int i; |
1094 | |
1095 | if (priv->sleep_mode == SLP_SLEEP) |
1096 | return -EPERM; |
1097 | /* for SLEEP MODE */ |
1098 | for (i = 0; i < priv->aplist.size; i++) { |
1099 | ether_addr_copy(dst: address[i].sa_data, src: priv->aplist.ap[i].bssid); |
1100 | address[i].sa_family = ARPHRD_ETHER; |
1101 | qual[i].level = 256 - priv->aplist.ap[i].rssi; |
1102 | qual[i].qual = priv->aplist.ap[i].sq; |
1103 | qual[i].noise = 0; /* invalid noise value */ |
1104 | qual[i].updated = 7; |
1105 | } |
1106 | if (i) { |
1107 | dwrq->data.flags = 1; /* Should be define'd */ |
1108 | memcpy(extra + sizeof(struct sockaddr) * i, |
1109 | &qual, sizeof(struct iw_quality) * i); |
1110 | } |
1111 | dwrq->data.length = i; |
1112 | |
1113 | return 0; |
1114 | } |
1115 | |
1116 | static int ks_wlan_set_scan(struct net_device *dev, |
1117 | struct iw_request_info *info, |
1118 | union iwreq_data *wrqu, char *) |
1119 | { |
1120 | struct ks_wlan_private *priv = netdev_priv(dev); |
1121 | struct iw_scan_req *req = NULL; |
1122 | int len; |
1123 | |
1124 | if (priv->sleep_mode == SLP_SLEEP) |
1125 | return -EPERM; |
1126 | |
1127 | /* for SLEEP MODE */ |
1128 | /* specified SSID SCAN */ |
1129 | if (wrqu->data.length == sizeof(struct iw_scan_req) && |
1130 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { |
1131 | req = (struct iw_scan_req *)extra; |
1132 | len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE); |
1133 | priv->scan_ssid_len = len; |
1134 | memcpy(priv->scan_ssid, req->essid, len); |
1135 | } else { |
1136 | priv->scan_ssid_len = 0; |
1137 | } |
1138 | |
1139 | priv->sme_i.sme_flag |= SME_AP_SCAN; |
1140 | hostif_sme_enqueue(priv, event: SME_BSS_SCAN_REQUEST); |
1141 | |
1142 | /* At this point, just return to the user. */ |
1143 | |
1144 | return 0; |
1145 | } |
1146 | |
1147 | static char *ks_wlan_add_leader_event(const char *rsn_leader, char *end_buf, |
1148 | char *current_ev, struct rsn_ie *rsn, |
1149 | struct iw_event *iwe, |
1150 | struct iw_request_info *info) |
1151 | { |
1152 | char buffer[RSN_IE_BODY_MAX * 2 + 30]; |
1153 | char *pbuf; |
1154 | int i; |
1155 | |
1156 | pbuf = &buffer[0]; |
1157 | memset(iwe, 0, sizeof(*iwe)); |
1158 | iwe->cmd = IWEVCUSTOM; |
1159 | memcpy(buffer, rsn_leader, sizeof(rsn_leader) - 1); |
1160 | iwe->u.data.length += sizeof(rsn_leader) - 1; |
1161 | pbuf += sizeof(rsn_leader) - 1; |
1162 | pbuf += sprintf(buf: pbuf, fmt: "%02x" , rsn->id); |
1163 | pbuf += sprintf(buf: pbuf, fmt: "%02x" , rsn->size); |
1164 | iwe->u.data.length += 4; |
1165 | |
1166 | for (i = 0; i < rsn->size; i++) |
1167 | pbuf += sprintf(buf: pbuf, fmt: "%02x" , rsn->body[i]); |
1168 | |
1169 | iwe->u.data.length += rsn->size * 2; |
1170 | |
1171 | return iwe_stream_add_point(info, stream: current_ev, ends: end_buf, iwe, extra: &buffer[0]); |
1172 | } |
1173 | |
1174 | /* |
1175 | * Translate scan data returned from the card to a card independent |
1176 | * format that the Wireless Tools will understand - Jean II |
1177 | */ |
1178 | static inline char *ks_wlan_translate_scan(struct net_device *dev, |
1179 | struct iw_request_info *info, |
1180 | char *current_ev, char *end_buf, |
1181 | struct local_ap *ap) |
1182 | { |
1183 | /* struct ks_wlan_private *priv = (struct ks_wlan_private *)dev->priv; */ |
1184 | static const char rsn_leader[] = "rsn_ie=" ; |
1185 | static const char wpa_leader[] = "wpa_ie=" ; |
1186 | struct iw_event iwe; /* Temporary buffer */ |
1187 | u16 capabilities; |
1188 | char *current_val; /* For rates */ |
1189 | int i; |
1190 | |
1191 | /* First entry *MUST* be the AP MAC address */ |
1192 | iwe.cmd = SIOCGIWAP; |
1193 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
1194 | ether_addr_copy(dst: iwe.u.ap_addr.sa_data, src: ap->bssid); |
1195 | current_ev = iwe_stream_add_event(info, stream: current_ev, |
1196 | ends: end_buf, iwe: &iwe, IW_EV_ADDR_LEN); |
1197 | |
1198 | /* Other entries will be displayed in the order we give them */ |
1199 | |
1200 | /* Add the ESSID */ |
1201 | iwe.u.data.length = ap->ssid.size; |
1202 | if (iwe.u.data.length > 32) |
1203 | iwe.u.data.length = 32; |
1204 | iwe.cmd = SIOCGIWESSID; |
1205 | iwe.u.data.flags = 1; |
1206 | current_ev = iwe_stream_add_point(info, stream: current_ev, |
1207 | ends: end_buf, iwe: &iwe, extra: ap->ssid.body); |
1208 | |
1209 | /* Add mode */ |
1210 | iwe.cmd = SIOCGIWMODE; |
1211 | capabilities = ap->capability; |
1212 | if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { |
1213 | iwe.u.mode = (capabilities & WLAN_CAPABILITY_ESS) ? |
1214 | IW_MODE_INFRA : IW_MODE_ADHOC; |
1215 | current_ev = iwe_stream_add_event(info, stream: current_ev, |
1216 | ends: end_buf, iwe: &iwe, IW_EV_UINT_LEN); |
1217 | } |
1218 | |
1219 | /* Add frequency */ |
1220 | iwe.cmd = SIOCGIWFREQ; |
1221 | iwe.u.freq.m = ap->channel; |
1222 | iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000; |
1223 | iwe.u.freq.e = 1; |
1224 | current_ev = iwe_stream_add_event(info, stream: current_ev, |
1225 | ends: end_buf, iwe: &iwe, IW_EV_FREQ_LEN); |
1226 | |
1227 | /* Add quality statistics */ |
1228 | iwe.cmd = IWEVQUAL; |
1229 | iwe.u.qual.level = 256 - ap->rssi; |
1230 | iwe.u.qual.qual = ap->sq; |
1231 | iwe.u.qual.noise = 0; /* invalid noise value */ |
1232 | current_ev = iwe_stream_add_event(info, stream: current_ev, ends: end_buf, |
1233 | iwe: &iwe, IW_EV_QUAL_LEN); |
1234 | |
1235 | /* Add encryption capability */ |
1236 | iwe.cmd = SIOCGIWENCODE; |
1237 | iwe.u.data.flags = (capabilities & WLAN_CAPABILITY_PRIVACY) ? |
1238 | (IW_ENCODE_ENABLED | IW_ENCODE_NOKEY) : |
1239 | IW_ENCODE_DISABLED; |
1240 | iwe.u.data.length = 0; |
1241 | current_ev = iwe_stream_add_point(info, stream: current_ev, ends: end_buf, |
1242 | iwe: &iwe, extra: ap->ssid.body); |
1243 | |
1244 | /* |
1245 | * Rate : stuffing multiple values in a single event |
1246 | * require a bit more of magic - Jean II |
1247 | */ |
1248 | current_val = current_ev + IW_EV_LCP_LEN; |
1249 | |
1250 | iwe.cmd = SIOCGIWRATE; |
1251 | |
1252 | /* These two flags are ignored... */ |
1253 | iwe.u.bitrate.fixed = 0; |
1254 | iwe.u.bitrate.disabled = 0; |
1255 | |
1256 | /* Max 16 values */ |
1257 | for (i = 0; i < 16; i++) { |
1258 | /* NULL terminated */ |
1259 | if (i >= ap->rate_set.size) |
1260 | break; |
1261 | /* Bit rate given in 500 kb/s units (+ 0x80) */ |
1262 | iwe.u.bitrate.value = ((ap->rate_set.body[i] & 0x7f) * 500000); |
1263 | /* Add new value to event */ |
1264 | current_val = iwe_stream_add_value(info, event: current_ev, |
1265 | value: current_val, ends: end_buf, iwe: &iwe, |
1266 | IW_EV_PARAM_LEN); |
1267 | } |
1268 | /* Check if we added any event */ |
1269 | if ((current_val - current_ev) > IW_EV_LCP_LEN) |
1270 | current_ev = current_val; |
1271 | |
1272 | if (ap->rsn_ie.id == RSN_INFO_ELEM_ID && ap->rsn_ie.size != 0) |
1273 | current_ev = ks_wlan_add_leader_event(rsn_leader, end_buf, |
1274 | current_ev, rsn: &ap->rsn_ie, |
1275 | iwe: &iwe, info); |
1276 | |
1277 | if (ap->wpa_ie.id == WPA_INFO_ELEM_ID && ap->wpa_ie.size != 0) |
1278 | current_ev = ks_wlan_add_leader_event(rsn_leader: wpa_leader, end_buf, |
1279 | current_ev, rsn: &ap->wpa_ie, |
1280 | iwe: &iwe, info); |
1281 | |
1282 | /* |
1283 | * The other data in the scan result are not really |
1284 | * interesting, so for now drop it - Jean II |
1285 | */ |
1286 | return current_ev; |
1287 | } |
1288 | |
1289 | static int ks_wlan_get_scan(struct net_device *dev, |
1290 | struct iw_request_info *info, |
1291 | union iwreq_data *dwrq, char *) |
1292 | { |
1293 | struct ks_wlan_private *priv = netdev_priv(dev); |
1294 | int i; |
1295 | char *current_ev = extra; |
1296 | |
1297 | if (priv->sleep_mode == SLP_SLEEP) |
1298 | return -EPERM; |
1299 | /* for SLEEP MODE */ |
1300 | if (priv->sme_i.sme_flag & SME_AP_SCAN) |
1301 | return -EAGAIN; |
1302 | |
1303 | if (priv->aplist.size == 0) { |
1304 | /* Client error, no scan results... |
1305 | * The caller need to restart the scan. |
1306 | */ |
1307 | return -ENODATA; |
1308 | } |
1309 | |
1310 | /* Read and parse all entries */ |
1311 | for (i = 0; i < priv->aplist.size; i++) { |
1312 | if ((extra + dwrq->data.length) - current_ev <= IW_EV_ADDR_LEN) { |
1313 | dwrq->data.length = 0; |
1314 | return -E2BIG; |
1315 | } |
1316 | /* Translate to WE format this entry */ |
1317 | current_ev = ks_wlan_translate_scan(dev, info, current_ev, |
1318 | end_buf: extra + dwrq->data.length, |
1319 | ap: &priv->aplist.ap[i]); |
1320 | } |
1321 | /* Length of data */ |
1322 | dwrq->data.length = (current_ev - extra); |
1323 | dwrq->data.flags = 0; |
1324 | |
1325 | return 0; |
1326 | } |
1327 | |
1328 | /* called after a bunch of SET operations */ |
1329 | static int ks_wlan_config_commit(struct net_device *dev, |
1330 | struct iw_request_info *info, |
1331 | union iwreq_data *zwrq, |
1332 | char *) |
1333 | { |
1334 | struct ks_wlan_private *priv = netdev_priv(dev); |
1335 | |
1336 | if (!priv->need_commit) |
1337 | return 0; |
1338 | |
1339 | ks_wlan_setup_parameter(priv, commit_flag: priv->need_commit); |
1340 | priv->need_commit = 0; |
1341 | return 0; |
1342 | } |
1343 | |
1344 | /* set association ie params */ |
1345 | static int ks_wlan_set_genie(struct net_device *dev, |
1346 | struct iw_request_info *info, |
1347 | union iwreq_data *dwrq, char *) |
1348 | { |
1349 | struct ks_wlan_private *priv = netdev_priv(dev); |
1350 | |
1351 | if (priv->sleep_mode == SLP_SLEEP) |
1352 | return -EPERM; |
1353 | /* for SLEEP MODE */ |
1354 | return 0; |
1355 | // return -EOPNOTSUPP; |
1356 | } |
1357 | |
1358 | static int ks_wlan_set_auth_mode(struct net_device *dev, |
1359 | struct iw_request_info *info, |
1360 | union iwreq_data *vwrq, char *) |
1361 | { |
1362 | struct ks_wlan_private *priv = netdev_priv(dev); |
1363 | struct iw_param *param = &vwrq->param; |
1364 | int index = (param->flags & IW_AUTH_INDEX); |
1365 | int value = param->value; |
1366 | |
1367 | if (priv->sleep_mode == SLP_SLEEP) |
1368 | return -EPERM; |
1369 | /* for SLEEP MODE */ |
1370 | switch (index) { |
1371 | case IW_AUTH_WPA_VERSION: /* 0 */ |
1372 | switch (value) { |
1373 | case IW_AUTH_WPA_VERSION_DISABLED: |
1374 | priv->wpa.version = value; |
1375 | if (priv->wpa.rsn_enabled) |
1376 | priv->wpa.rsn_enabled = false; |
1377 | priv->need_commit |= SME_RSN; |
1378 | break; |
1379 | case IW_AUTH_WPA_VERSION_WPA: |
1380 | case IW_AUTH_WPA_VERSION_WPA2: |
1381 | priv->wpa.version = value; |
1382 | if (!(priv->wpa.rsn_enabled)) |
1383 | priv->wpa.rsn_enabled = true; |
1384 | priv->need_commit |= SME_RSN; |
1385 | break; |
1386 | default: |
1387 | return -EOPNOTSUPP; |
1388 | } |
1389 | break; |
1390 | case IW_AUTH_CIPHER_PAIRWISE: /* 1 */ |
1391 | switch (value) { |
1392 | case IW_AUTH_CIPHER_NONE: |
1393 | if (priv->reg.privacy_invoked) { |
1394 | priv->reg.privacy_invoked = 0x00; |
1395 | priv->need_commit |= SME_WEP_FLAG; |
1396 | } |
1397 | break; |
1398 | case IW_AUTH_CIPHER_WEP40: |
1399 | case IW_AUTH_CIPHER_TKIP: |
1400 | case IW_AUTH_CIPHER_CCMP: |
1401 | case IW_AUTH_CIPHER_WEP104: |
1402 | if (!priv->reg.privacy_invoked) { |
1403 | priv->reg.privacy_invoked = 0x01; |
1404 | priv->need_commit |= SME_WEP_FLAG; |
1405 | } |
1406 | priv->wpa.pairwise_suite = value; |
1407 | priv->need_commit |= SME_RSN_UNICAST; |
1408 | break; |
1409 | default: |
1410 | return -EOPNOTSUPP; |
1411 | } |
1412 | break; |
1413 | case IW_AUTH_CIPHER_GROUP: /* 2 */ |
1414 | switch (value) { |
1415 | case IW_AUTH_CIPHER_NONE: |
1416 | if (priv->reg.privacy_invoked) { |
1417 | priv->reg.privacy_invoked = 0x00; |
1418 | priv->need_commit |= SME_WEP_FLAG; |
1419 | } |
1420 | break; |
1421 | case IW_AUTH_CIPHER_WEP40: |
1422 | case IW_AUTH_CIPHER_TKIP: |
1423 | case IW_AUTH_CIPHER_CCMP: |
1424 | case IW_AUTH_CIPHER_WEP104: |
1425 | if (!priv->reg.privacy_invoked) { |
1426 | priv->reg.privacy_invoked = 0x01; |
1427 | priv->need_commit |= SME_WEP_FLAG; |
1428 | } |
1429 | priv->wpa.group_suite = value; |
1430 | priv->need_commit |= SME_RSN_MULTICAST; |
1431 | break; |
1432 | default: |
1433 | return -EOPNOTSUPP; |
1434 | } |
1435 | break; |
1436 | case IW_AUTH_KEY_MGMT: /* 3 */ |
1437 | switch (value) { |
1438 | case IW_AUTH_KEY_MGMT_802_1X: |
1439 | case IW_AUTH_KEY_MGMT_PSK: |
1440 | case 0: /* NONE or 802_1X_NO_WPA */ |
1441 | case 4: /* WPA_NONE */ |
1442 | priv->wpa.key_mgmt_suite = value; |
1443 | priv->need_commit |= SME_RSN_AUTH; |
1444 | break; |
1445 | default: |
1446 | return -EOPNOTSUPP; |
1447 | } |
1448 | break; |
1449 | case IW_AUTH_80211_AUTH_ALG: /* 6 */ |
1450 | switch (value) { |
1451 | case IW_AUTH_ALG_OPEN_SYSTEM: |
1452 | priv->wpa.auth_alg = value; |
1453 | priv->reg.authenticate_type = AUTH_TYPE_OPEN_SYSTEM; |
1454 | break; |
1455 | case IW_AUTH_ALG_SHARED_KEY: |
1456 | priv->wpa.auth_alg = value; |
1457 | priv->reg.authenticate_type = AUTH_TYPE_SHARED_KEY; |
1458 | break; |
1459 | case IW_AUTH_ALG_LEAP: |
1460 | default: |
1461 | return -EOPNOTSUPP; |
1462 | } |
1463 | priv->need_commit |= SME_MODE_SET; |
1464 | break; |
1465 | case IW_AUTH_WPA_ENABLED: /* 7 */ |
1466 | priv->wpa.wpa_enabled = value; |
1467 | break; |
1468 | case IW_AUTH_PRIVACY_INVOKED: /* 10 */ |
1469 | if ((value && !priv->reg.privacy_invoked) || |
1470 | (!value && priv->reg.privacy_invoked)) { |
1471 | priv->reg.privacy_invoked = value ? 0x01 : 0x00; |
1472 | priv->need_commit |= SME_WEP_FLAG; |
1473 | } |
1474 | break; |
1475 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: /* 4 */ |
1476 | case IW_AUTH_TKIP_COUNTERMEASURES: /* 5 */ |
1477 | case IW_AUTH_DROP_UNENCRYPTED: /* 8 */ |
1478 | case IW_AUTH_ROAMING_CONTROL: /* 9 */ |
1479 | default: |
1480 | break; |
1481 | } |
1482 | |
1483 | /* return -EINPROGRESS; */ |
1484 | if (priv->need_commit) { |
1485 | ks_wlan_setup_parameter(priv, commit_flag: priv->need_commit); |
1486 | priv->need_commit = 0; |
1487 | } |
1488 | return 0; |
1489 | } |
1490 | |
1491 | static int ks_wlan_get_auth_mode(struct net_device *dev, |
1492 | struct iw_request_info *info, |
1493 | union iwreq_data *vwrq, char *) |
1494 | { |
1495 | struct ks_wlan_private *priv = netdev_priv(dev); |
1496 | struct iw_param *param = &vwrq->param; |
1497 | int index = (param->flags & IW_AUTH_INDEX); |
1498 | |
1499 | if (priv->sleep_mode == SLP_SLEEP) |
1500 | return -EPERM; |
1501 | |
1502 | /* for SLEEP MODE */ |
1503 | /* WPA (not used ?? wpa_supplicant) */ |
1504 | switch (index) { |
1505 | case IW_AUTH_WPA_VERSION: |
1506 | param->value = priv->wpa.version; |
1507 | break; |
1508 | case IW_AUTH_CIPHER_PAIRWISE: |
1509 | param->value = priv->wpa.pairwise_suite; |
1510 | break; |
1511 | case IW_AUTH_CIPHER_GROUP: |
1512 | param->value = priv->wpa.group_suite; |
1513 | break; |
1514 | case IW_AUTH_KEY_MGMT: |
1515 | param->value = priv->wpa.key_mgmt_suite; |
1516 | break; |
1517 | case IW_AUTH_80211_AUTH_ALG: |
1518 | param->value = priv->wpa.auth_alg; |
1519 | break; |
1520 | case IW_AUTH_WPA_ENABLED: |
1521 | param->value = priv->wpa.rsn_enabled; |
1522 | break; |
1523 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: /* OK??? */ |
1524 | case IW_AUTH_TKIP_COUNTERMEASURES: |
1525 | case IW_AUTH_DROP_UNENCRYPTED: |
1526 | default: |
1527 | /* return -EOPNOTSUPP; */ |
1528 | break; |
1529 | } |
1530 | return 0; |
1531 | } |
1532 | |
1533 | /* set encoding token & mode (WPA)*/ |
1534 | static int ks_wlan_set_encode_ext(struct net_device *dev, |
1535 | struct iw_request_info *info, |
1536 | union iwreq_data *dwrq, char *) |
1537 | { |
1538 | struct ks_wlan_private *priv = netdev_priv(dev); |
1539 | struct iw_encode_ext *enc; |
1540 | int index = dwrq->encoding.flags & IW_ENCODE_INDEX; |
1541 | unsigned int commit = 0; |
1542 | struct wpa_key *key; |
1543 | |
1544 | enc = (struct iw_encode_ext *)extra; |
1545 | if (!enc) |
1546 | return -EINVAL; |
1547 | |
1548 | if (priv->sleep_mode == SLP_SLEEP) |
1549 | return -EPERM; |
1550 | |
1551 | /* for SLEEP MODE */ |
1552 | if (index < 1 || index > 4) |
1553 | return -EINVAL; |
1554 | index--; |
1555 | key = &priv->wpa.key[index]; |
1556 | |
1557 | if (dwrq->encoding.flags & IW_ENCODE_DISABLED) |
1558 | key->key_len = 0; |
1559 | |
1560 | key->ext_flags = enc->ext_flags; |
1561 | if (enc->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { |
1562 | priv->wpa.txkey = index; |
1563 | commit |= SME_WEP_INDEX; |
1564 | } else if (enc->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { |
1565 | memcpy(&key->rx_seq[0], &enc->rx_seq[0], IW_ENCODE_SEQ_MAX_SIZE); |
1566 | } |
1567 | |
1568 | ether_addr_copy(dst: &key->addr.sa_data[0], src: &enc->addr.sa_data[0]); |
1569 | |
1570 | switch (enc->alg) { |
1571 | case IW_ENCODE_ALG_NONE: |
1572 | if (priv->reg.privacy_invoked) { |
1573 | priv->reg.privacy_invoked = 0x00; |
1574 | commit |= SME_WEP_FLAG; |
1575 | } |
1576 | key->key_len = 0; |
1577 | |
1578 | break; |
1579 | case IW_ENCODE_ALG_WEP: |
1580 | case IW_ENCODE_ALG_CCMP: |
1581 | if (!priv->reg.privacy_invoked) { |
1582 | priv->reg.privacy_invoked = 0x01; |
1583 | commit |= SME_WEP_FLAG; |
1584 | } |
1585 | if (enc->key_len) { |
1586 | int key_len = clamp_val(enc->key_len, 0, IW_ENCODING_TOKEN_MAX); |
1587 | |
1588 | memcpy(&key->key_val[0], &enc->key[0], key_len); |
1589 | key->key_len = key_len; |
1590 | commit |= (SME_WEP_VAL1 << index); |
1591 | } |
1592 | break; |
1593 | case IW_ENCODE_ALG_TKIP: |
1594 | if (!priv->reg.privacy_invoked) { |
1595 | priv->reg.privacy_invoked = 0x01; |
1596 | commit |= SME_WEP_FLAG; |
1597 | } |
1598 | if (enc->key_len == 32) { |
1599 | memcpy(&key->key_val[0], &enc->key[0], enc->key_len - 16); |
1600 | key->key_len = enc->key_len - 16; |
1601 | if (priv->wpa.key_mgmt_suite == 4) { /* WPA_NONE */ |
1602 | memcpy(&key->tx_mic_key[0], &enc->key[16], 8); |
1603 | memcpy(&key->rx_mic_key[0], &enc->key[16], 8); |
1604 | } else { |
1605 | memcpy(&key->tx_mic_key[0], &enc->key[16], 8); |
1606 | memcpy(&key->rx_mic_key[0], &enc->key[24], 8); |
1607 | } |
1608 | commit |= (SME_WEP_VAL1 << index); |
1609 | } |
1610 | break; |
1611 | default: |
1612 | return -EINVAL; |
1613 | } |
1614 | key->alg = enc->alg; |
1615 | |
1616 | if (commit) { |
1617 | if (commit & SME_WEP_INDEX) |
1618 | hostif_sme_enqueue(priv, event: SME_SET_TXKEY); |
1619 | if (commit & SME_WEP_VAL_MASK) |
1620 | hostif_sme_enqueue(priv, event: SME_SET_KEY1 + index); |
1621 | if (commit & SME_WEP_FLAG) |
1622 | hostif_sme_enqueue(priv, event: SME_WEP_FLAG_REQUEST); |
1623 | } |
1624 | |
1625 | return 0; |
1626 | } |
1627 | |
1628 | /* get encoding token & mode (WPA)*/ |
1629 | static int ks_wlan_get_encode_ext(struct net_device *dev, |
1630 | struct iw_request_info *info, |
1631 | union iwreq_data *dwrq, char *) |
1632 | { |
1633 | struct ks_wlan_private *priv = netdev_priv(dev); |
1634 | |
1635 | if (priv->sleep_mode == SLP_SLEEP) |
1636 | return -EPERM; |
1637 | |
1638 | /* for SLEEP MODE */ |
1639 | /* WPA (not used ?? wpa_supplicant) |
1640 | * struct ks_wlan_private *priv = (struct ks_wlan_private *)dev->priv; |
1641 | * struct iw_encode_ext *enc; |
1642 | * enc = (struct iw_encode_ext *)extra; |
1643 | * int index = dwrq->flags & IW_ENCODE_INDEX; |
1644 | * WPA (not used ?? wpa_supplicant) |
1645 | */ |
1646 | return 0; |
1647 | } |
1648 | |
1649 | static int ks_wlan_set_pmksa(struct net_device *dev, |
1650 | struct iw_request_info *info, |
1651 | union iwreq_data *dwrq, char *) |
1652 | { |
1653 | struct ks_wlan_private *priv = netdev_priv(dev); |
1654 | struct iw_pmksa *pmksa; |
1655 | int i; |
1656 | struct pmk *pmk; |
1657 | struct list_head *ptr; |
1658 | |
1659 | if (priv->sleep_mode == SLP_SLEEP) |
1660 | return -EPERM; |
1661 | |
1662 | /* for SLEEP MODE */ |
1663 | if (!extra) |
1664 | return -EINVAL; |
1665 | |
1666 | pmksa = (struct iw_pmksa *)extra; |
1667 | |
1668 | switch (pmksa->cmd) { |
1669 | case IW_PMKSA_ADD: |
1670 | if (list_empty(head: &priv->pmklist.head)) { |
1671 | for (i = 0; i < PMK_LIST_MAX; i++) { |
1672 | pmk = &priv->pmklist.pmk[i]; |
1673 | if (is_zero_ether_addr(addr: pmk->bssid)) |
1674 | break; |
1675 | } |
1676 | ether_addr_copy(dst: pmk->bssid, src: pmksa->bssid.sa_data); |
1677 | memcpy(pmk->pmkid, pmksa->pmkid, IW_PMKID_LEN); |
1678 | list_add(new: &pmk->list, head: &priv->pmklist.head); |
1679 | priv->pmklist.size++; |
1680 | break; |
1681 | } |
1682 | /* search cache data */ |
1683 | list_for_each(ptr, &priv->pmklist.head) { |
1684 | pmk = list_entry(ptr, struct pmk, list); |
1685 | if (ether_addr_equal(addr1: pmksa->bssid.sa_data, addr2: pmk->bssid)) { |
1686 | memcpy(pmk->pmkid, pmksa->pmkid, IW_PMKID_LEN); |
1687 | list_move(list: &pmk->list, head: &priv->pmklist.head); |
1688 | break; |
1689 | } |
1690 | } |
1691 | /* not find address. */ |
1692 | if (ptr != &priv->pmklist.head) |
1693 | break; |
1694 | /* new cache data */ |
1695 | if (priv->pmklist.size < PMK_LIST_MAX) { |
1696 | for (i = 0; i < PMK_LIST_MAX; i++) { |
1697 | pmk = &priv->pmklist.pmk[i]; |
1698 | if (is_zero_ether_addr(addr: pmk->bssid)) |
1699 | break; |
1700 | } |
1701 | ether_addr_copy(dst: pmk->bssid, src: pmksa->bssid.sa_data); |
1702 | memcpy(pmk->pmkid, pmksa->pmkid, IW_PMKID_LEN); |
1703 | list_add(new: &pmk->list, head: &priv->pmklist.head); |
1704 | priv->pmklist.size++; |
1705 | } else { /* overwrite old cache data */ |
1706 | pmk = list_entry(priv->pmklist.head.prev, struct pmk, |
1707 | list); |
1708 | ether_addr_copy(dst: pmk->bssid, src: pmksa->bssid.sa_data); |
1709 | memcpy(pmk->pmkid, pmksa->pmkid, IW_PMKID_LEN); |
1710 | list_move(list: &pmk->list, head: &priv->pmklist.head); |
1711 | } |
1712 | break; |
1713 | case IW_PMKSA_REMOVE: |
1714 | if (list_empty(head: &priv->pmklist.head)) |
1715 | return -EINVAL; |
1716 | /* search cache data */ |
1717 | list_for_each(ptr, &priv->pmklist.head) { |
1718 | pmk = list_entry(ptr, struct pmk, list); |
1719 | if (ether_addr_equal(addr1: pmksa->bssid.sa_data, addr2: pmk->bssid)) { |
1720 | eth_zero_addr(addr: pmk->bssid); |
1721 | memset(pmk->pmkid, 0, IW_PMKID_LEN); |
1722 | list_del_init(entry: &pmk->list); |
1723 | break; |
1724 | } |
1725 | } |
1726 | /* not find address. */ |
1727 | if (ptr == &priv->pmklist.head) |
1728 | return 0; |
1729 | break; |
1730 | case IW_PMKSA_FLUSH: |
1731 | memset(&priv->pmklist, 0, sizeof(priv->pmklist)); |
1732 | INIT_LIST_HEAD(list: &priv->pmklist.head); |
1733 | for (i = 0; i < PMK_LIST_MAX; i++) |
1734 | INIT_LIST_HEAD(list: &priv->pmklist.pmk[i].list); |
1735 | break; |
1736 | default: |
1737 | return -EINVAL; |
1738 | } |
1739 | |
1740 | hostif_sme_enqueue(priv, event: SME_SET_PMKSA); |
1741 | return 0; |
1742 | } |
1743 | |
1744 | static struct iw_statistics *ks_get_wireless_stats(struct net_device *dev) |
1745 | { |
1746 | struct ks_wlan_private *priv = netdev_priv(dev); |
1747 | struct iw_statistics *wstats = &priv->wstats; |
1748 | |
1749 | if (!atomic_read(v: &update_phyinfo)) |
1750 | return (priv->dev_state < DEVICE_STATE_READY) ? NULL : wstats; |
1751 | |
1752 | /* |
1753 | * Packets discarded in the wireless adapter due to wireless |
1754 | * specific problems |
1755 | */ |
1756 | wstats->discard.nwid = 0; /* Rx invalid nwid */ |
1757 | wstats->discard.code = 0; /* Rx invalid crypt */ |
1758 | wstats->discard.fragment = 0; /* Rx invalid frag */ |
1759 | wstats->discard.retries = 0; /* Tx excessive retries */ |
1760 | wstats->discard.misc = 0; /* Invalid misc */ |
1761 | wstats->miss.beacon = 0; /* Missed beacon */ |
1762 | |
1763 | return wstats; |
1764 | } |
1765 | |
1766 | static int ks_wlan_set_stop_request(struct net_device *dev, |
1767 | struct iw_request_info *info, |
1768 | union iwreq_data *uwrq, char *) |
1769 | { |
1770 | struct ks_wlan_private *priv = netdev_priv(dev); |
1771 | |
1772 | if (priv->sleep_mode == SLP_SLEEP) |
1773 | return -EPERM; |
1774 | |
1775 | /* for SLEEP MODE */ |
1776 | if (!(uwrq->mode)) |
1777 | return -EINVAL; |
1778 | |
1779 | hostif_sme_enqueue(priv, event: SME_STOP_REQUEST); |
1780 | return 0; |
1781 | } |
1782 | |
1783 | #include <linux/ieee80211.h> |
1784 | static int ks_wlan_set_mlme(struct net_device *dev, |
1785 | struct iw_request_info *info, |
1786 | union iwreq_data *dwrq, char *) |
1787 | { |
1788 | struct ks_wlan_private *priv = netdev_priv(dev); |
1789 | struct iw_mlme *mlme = (struct iw_mlme *)extra; |
1790 | union iwreq_data uwrq; |
1791 | |
1792 | uwrq.mode = 1; |
1793 | |
1794 | if (priv->sleep_mode == SLP_SLEEP) |
1795 | return -EPERM; |
1796 | |
1797 | if (mlme->cmd != IW_MLME_DEAUTH && |
1798 | mlme->cmd != IW_MLME_DISASSOC) |
1799 | return -EOPNOTSUPP; |
1800 | |
1801 | if (mlme->cmd == IW_MLME_DEAUTH && |
1802 | mlme->reason_code == WLAN_REASON_MIC_FAILURE) |
1803 | return 0; |
1804 | |
1805 | return ks_wlan_set_stop_request(dev, NULL, uwrq: &uwrq, NULL); |
1806 | } |
1807 | |
1808 | static int ks_wlan_get_firmware_version(struct net_device *dev, |
1809 | struct iw_request_info *info, |
1810 | union iwreq_data *uwrq, char *) |
1811 | { |
1812 | struct iw_point *dwrq = &uwrq->data; |
1813 | struct ks_wlan_private *priv = netdev_priv(dev); |
1814 | |
1815 | dwrq->length = priv->version_size + 1; |
1816 | strscpy(extra, priv->firmware_version, dwrq->length); |
1817 | return 0; |
1818 | } |
1819 | |
1820 | static int ks_wlan_set_preamble(struct net_device *dev, |
1821 | struct iw_request_info *info, |
1822 | union iwreq_data *uwrq, char *) |
1823 | { |
1824 | struct ks_wlan_private *priv = netdev_priv(dev); |
1825 | |
1826 | if (priv->sleep_mode == SLP_SLEEP) |
1827 | return -EPERM; |
1828 | |
1829 | /* for SLEEP MODE */ |
1830 | if (uwrq->mode != LONG_PREAMBLE && uwrq->mode != SHORT_PREAMBLE) |
1831 | return -EINVAL; |
1832 | |
1833 | priv->reg.preamble = uwrq->mode; |
1834 | priv->need_commit |= SME_MODE_SET; |
1835 | return -EINPROGRESS; /* Call commit handler */ |
1836 | } |
1837 | |
1838 | static int ks_wlan_get_preamble(struct net_device *dev, |
1839 | struct iw_request_info *info, |
1840 | union iwreq_data *uwrq, char *) |
1841 | { |
1842 | struct ks_wlan_private *priv = netdev_priv(dev); |
1843 | |
1844 | if (priv->sleep_mode == SLP_SLEEP) |
1845 | return -EPERM; |
1846 | |
1847 | /* for SLEEP MODE */ |
1848 | uwrq->mode = priv->reg.preamble; |
1849 | return 0; |
1850 | } |
1851 | |
1852 | static int ks_wlan_set_power_mgmt(struct net_device *dev, |
1853 | struct iw_request_info *info, |
1854 | union iwreq_data *uwrq, char *) |
1855 | { |
1856 | struct ks_wlan_private *priv = netdev_priv(dev); |
1857 | |
1858 | if (priv->sleep_mode == SLP_SLEEP) |
1859 | return -EPERM; |
1860 | |
1861 | if (uwrq->mode != POWER_MGMT_ACTIVE && |
1862 | uwrq->mode != POWER_MGMT_SAVE1 && |
1863 | uwrq->mode != POWER_MGMT_SAVE2) |
1864 | return -EINVAL; |
1865 | |
1866 | if ((uwrq->mode == POWER_MGMT_SAVE1 || uwrq->mode == POWER_MGMT_SAVE2) && |
1867 | (priv->reg.operation_mode != MODE_INFRASTRUCTURE)) |
1868 | return -EINVAL; |
1869 | |
1870 | priv->reg.power_mgmt = uwrq->mode; |
1871 | hostif_sme_enqueue(priv, event: SME_POW_MNGMT_REQUEST); |
1872 | |
1873 | return 0; |
1874 | } |
1875 | |
1876 | static int ks_wlan_get_power_mgmt(struct net_device *dev, |
1877 | struct iw_request_info *info, |
1878 | union iwreq_data *uwrq, char *) |
1879 | { |
1880 | struct ks_wlan_private *priv = netdev_priv(dev); |
1881 | |
1882 | if (priv->sleep_mode == SLP_SLEEP) |
1883 | return -EPERM; |
1884 | |
1885 | /* for SLEEP MODE */ |
1886 | uwrq->mode = priv->reg.power_mgmt; |
1887 | return 0; |
1888 | } |
1889 | |
1890 | static int ks_wlan_set_scan_type(struct net_device *dev, |
1891 | struct iw_request_info *info, |
1892 | union iwreq_data *uwrq, char *) |
1893 | { |
1894 | struct ks_wlan_private *priv = netdev_priv(dev); |
1895 | |
1896 | if (priv->sleep_mode == SLP_SLEEP) |
1897 | return -EPERM; |
1898 | /* for SLEEP MODE */ |
1899 | |
1900 | if (uwrq->mode != ACTIVE_SCAN && uwrq->mode != PASSIVE_SCAN) |
1901 | return -EINVAL; |
1902 | |
1903 | priv->reg.scan_type = uwrq->mode; |
1904 | return 0; |
1905 | } |
1906 | |
1907 | static int ks_wlan_get_scan_type(struct net_device *dev, |
1908 | struct iw_request_info *info, |
1909 | union iwreq_data *uwrq, char *) |
1910 | { |
1911 | struct ks_wlan_private *priv = netdev_priv(dev); |
1912 | |
1913 | if (priv->sleep_mode == SLP_SLEEP) |
1914 | return -EPERM; |
1915 | /* for SLEEP MODE */ |
1916 | uwrq->mode = priv->reg.scan_type; |
1917 | return 0; |
1918 | } |
1919 | |
1920 | static int ks_wlan_set_beacon_lost(struct net_device *dev, |
1921 | struct iw_request_info *info, |
1922 | union iwreq_data *uwrq, char *) |
1923 | { |
1924 | struct ks_wlan_private *priv = netdev_priv(dev); |
1925 | |
1926 | if (priv->sleep_mode == SLP_SLEEP) |
1927 | return -EPERM; |
1928 | /* for SLEEP MODE */ |
1929 | if (uwrq->mode > BEACON_LOST_COUNT_MAX) |
1930 | return -EINVAL; |
1931 | |
1932 | priv->reg.beacon_lost_count = uwrq->mode; |
1933 | |
1934 | if (priv->reg.operation_mode == MODE_INFRASTRUCTURE) { |
1935 | priv->need_commit |= SME_MODE_SET; |
1936 | return -EINPROGRESS; /* Call commit handler */ |
1937 | } |
1938 | |
1939 | return 0; |
1940 | } |
1941 | |
1942 | static int ks_wlan_get_beacon_lost(struct net_device *dev, |
1943 | struct iw_request_info *info, |
1944 | union iwreq_data *uwrq, char *) |
1945 | { |
1946 | struct ks_wlan_private *priv = netdev_priv(dev); |
1947 | |
1948 | if (priv->sleep_mode == SLP_SLEEP) |
1949 | return -EPERM; |
1950 | /* for SLEEP MODE */ |
1951 | uwrq->mode = priv->reg.beacon_lost_count; |
1952 | return 0; |
1953 | } |
1954 | |
1955 | static int ks_wlan_set_phy_type(struct net_device *dev, |
1956 | struct iw_request_info *info, |
1957 | union iwreq_data *uwrq, char *) |
1958 | { |
1959 | struct ks_wlan_private *priv = netdev_priv(dev); |
1960 | |
1961 | if (priv->sleep_mode == SLP_SLEEP) |
1962 | return -EPERM; |
1963 | |
1964 | if (uwrq->mode != D_11B_ONLY_MODE && |
1965 | uwrq->mode != D_11G_ONLY_MODE && |
1966 | uwrq->mode != D_11BG_COMPATIBLE_MODE) |
1967 | return -EINVAL; |
1968 | |
1969 | /* for SLEEP MODE */ |
1970 | priv->reg.phy_type = uwrq->mode; |
1971 | priv->need_commit |= SME_MODE_SET; |
1972 | return -EINPROGRESS; /* Call commit handler */ |
1973 | } |
1974 | |
1975 | static int ks_wlan_get_phy_type(struct net_device *dev, |
1976 | struct iw_request_info *info, |
1977 | union iwreq_data *uwrq, char *) |
1978 | { |
1979 | struct ks_wlan_private *priv = netdev_priv(dev); |
1980 | |
1981 | if (priv->sleep_mode == SLP_SLEEP) |
1982 | return -EPERM; |
1983 | /* for SLEEP MODE */ |
1984 | uwrq->mode = priv->reg.phy_type; |
1985 | return 0; |
1986 | } |
1987 | |
1988 | static int ks_wlan_set_cts_mode(struct net_device *dev, |
1989 | struct iw_request_info *info, |
1990 | union iwreq_data *uwrq, char *) |
1991 | { |
1992 | struct ks_wlan_private *priv = netdev_priv(dev); |
1993 | |
1994 | if (priv->sleep_mode == SLP_SLEEP) |
1995 | return -EPERM; |
1996 | /* for SLEEP MODE */ |
1997 | if (uwrq->mode != CTS_MODE_FALSE && uwrq->mode != CTS_MODE_TRUE) |
1998 | return -EINVAL; |
1999 | |
2000 | priv->reg.cts_mode = (uwrq->mode == CTS_MODE_FALSE) ? uwrq->mode : |
2001 | (priv->reg.phy_type == D_11G_ONLY_MODE || |
2002 | priv->reg.phy_type == D_11BG_COMPATIBLE_MODE) ? |
2003 | uwrq->mode : !uwrq->mode; |
2004 | |
2005 | priv->need_commit |= SME_MODE_SET; |
2006 | return -EINPROGRESS; /* Call commit handler */ |
2007 | } |
2008 | |
2009 | static int ks_wlan_get_cts_mode(struct net_device *dev, |
2010 | struct iw_request_info *info, |
2011 | union iwreq_data *uwrq, char *) |
2012 | { |
2013 | struct ks_wlan_private *priv = netdev_priv(dev); |
2014 | |
2015 | if (priv->sleep_mode == SLP_SLEEP) |
2016 | return -EPERM; |
2017 | /* for SLEEP MODE */ |
2018 | uwrq->mode = priv->reg.cts_mode; |
2019 | return 0; |
2020 | } |
2021 | |
2022 | static int ks_wlan_set_sleep_mode(struct net_device *dev, |
2023 | struct iw_request_info *info, |
2024 | union iwreq_data *uwrq, char *) |
2025 | { |
2026 | struct ks_wlan_private *priv = netdev_priv(dev); |
2027 | |
2028 | if (uwrq->mode != SLP_SLEEP && |
2029 | uwrq->mode != SLP_ACTIVE) { |
2030 | netdev_err(dev, format: "SET_SLEEP_MODE %d error\n" , uwrq->mode); |
2031 | return -EINVAL; |
2032 | } |
2033 | |
2034 | priv->sleep_mode = uwrq->mode; |
2035 | netdev_info(dev, format: "SET_SLEEP_MODE %d\n" , priv->sleep_mode); |
2036 | |
2037 | if (uwrq->mode == SLP_SLEEP) |
2038 | hostif_sme_enqueue(priv, event: SME_STOP_REQUEST); |
2039 | |
2040 | hostif_sme_enqueue(priv, event: SME_SLEEP_REQUEST); |
2041 | |
2042 | return 0; |
2043 | } |
2044 | |
2045 | static int ks_wlan_get_sleep_mode(struct net_device *dev, |
2046 | struct iw_request_info *info, |
2047 | union iwreq_data *uwrq, char *) |
2048 | { |
2049 | struct ks_wlan_private *priv = netdev_priv(dev); |
2050 | |
2051 | uwrq->mode = priv->sleep_mode; |
2052 | |
2053 | return 0; |
2054 | } |
2055 | |
2056 | static int ks_wlan_set_wps_enable(struct net_device *dev, |
2057 | struct iw_request_info *info, |
2058 | union iwreq_data *uwrq, char *) |
2059 | { |
2060 | struct ks_wlan_private *priv = netdev_priv(dev); |
2061 | |
2062 | if (priv->sleep_mode == SLP_SLEEP) |
2063 | return -EPERM; |
2064 | /* for SLEEP MODE */ |
2065 | if (uwrq->mode != 0 && uwrq->mode != 1) |
2066 | return -EINVAL; |
2067 | |
2068 | priv->wps.wps_enabled = uwrq->mode; |
2069 | hostif_sme_enqueue(priv, event: SME_WPS_ENABLE_REQUEST); |
2070 | |
2071 | return 0; |
2072 | } |
2073 | |
2074 | static int ks_wlan_get_wps_enable(struct net_device *dev, |
2075 | struct iw_request_info *info, |
2076 | union iwreq_data *uwrq, char *) |
2077 | { |
2078 | struct ks_wlan_private *priv = netdev_priv(dev); |
2079 | |
2080 | if (priv->sleep_mode == SLP_SLEEP) |
2081 | return -EPERM; |
2082 | /* for SLEEP MODE */ |
2083 | uwrq->mode = priv->wps.wps_enabled; |
2084 | netdev_info(dev, format: "return=%d\n" , uwrq->mode); |
2085 | |
2086 | return 0; |
2087 | } |
2088 | |
2089 | static int ks_wlan_set_wps_probe_req(struct net_device *dev, |
2090 | struct iw_request_info *info, |
2091 | union iwreq_data *uwrq, char *) |
2092 | { |
2093 | struct iw_point *dwrq = &uwrq->data; |
2094 | u8 *p = extra; |
2095 | unsigned char len; |
2096 | struct ks_wlan_private *priv = netdev_priv(dev); |
2097 | |
2098 | if (priv->sleep_mode == SLP_SLEEP) |
2099 | return -EPERM; |
2100 | |
2101 | /* length check */ |
2102 | if (p[1] + 2 != dwrq->length || dwrq->length > 256) |
2103 | return -EINVAL; |
2104 | |
2105 | priv->wps.ielen = p[1] + 2 + 1; /* IE header + IE + sizeof(len) */ |
2106 | len = p[1] + 2; /* IE header + IE */ |
2107 | |
2108 | memcpy(priv->wps.ie, &len, sizeof(len)); |
2109 | p = memcpy(priv->wps.ie + 1, p, len); |
2110 | |
2111 | netdev_dbg(dev, "%d(%#x): %02X %02X %02X %02X ... %02X %02X %02X\n" , |
2112 | priv->wps.ielen, priv->wps.ielen, p[0], p[1], p[2], p[3], |
2113 | p[priv->wps.ielen - 3], p[priv->wps.ielen - 2], |
2114 | p[priv->wps.ielen - 1]); |
2115 | |
2116 | hostif_sme_enqueue(priv, event: SME_WPS_PROBE_REQUEST); |
2117 | |
2118 | return 0; |
2119 | } |
2120 | |
2121 | static int ks_wlan_set_tx_gain(struct net_device *dev, |
2122 | struct iw_request_info *info, |
2123 | union iwreq_data *uwrq, char *) |
2124 | { |
2125 | struct ks_wlan_private *priv = netdev_priv(dev); |
2126 | |
2127 | if (priv->sleep_mode == SLP_SLEEP) |
2128 | return -EPERM; |
2129 | /* for SLEEP MODE */ |
2130 | if (uwrq->mode > 0xFF) |
2131 | return -EINVAL; |
2132 | |
2133 | priv->gain.tx_gain = (u8)uwrq->mode; |
2134 | priv->gain.tx_mode = (priv->gain.tx_gain < 0xFF) ? 1 : 0; |
2135 | hostif_sme_enqueue(priv, event: SME_SET_GAIN); |
2136 | return 0; |
2137 | } |
2138 | |
2139 | static int ks_wlan_get_tx_gain(struct net_device *dev, |
2140 | struct iw_request_info *info, |
2141 | union iwreq_data *uwrq, char *) |
2142 | { |
2143 | struct ks_wlan_private *priv = netdev_priv(dev); |
2144 | |
2145 | if (priv->sleep_mode == SLP_SLEEP) |
2146 | return -EPERM; |
2147 | /* for SLEEP MODE */ |
2148 | uwrq->mode = priv->gain.tx_gain; |
2149 | hostif_sme_enqueue(priv, event: SME_GET_GAIN); |
2150 | return 0; |
2151 | } |
2152 | |
2153 | static int ks_wlan_set_rx_gain(struct net_device *dev, |
2154 | struct iw_request_info *info, |
2155 | union iwreq_data *uwrq, char *) |
2156 | { |
2157 | struct ks_wlan_private *priv = netdev_priv(dev); |
2158 | |
2159 | if (priv->sleep_mode == SLP_SLEEP) |
2160 | return -EPERM; |
2161 | /* for SLEEP MODE */ |
2162 | if (uwrq->mode > 0xFF) |
2163 | return -EINVAL; |
2164 | |
2165 | priv->gain.rx_gain = (u8)uwrq->mode; |
2166 | priv->gain.rx_mode = (priv->gain.rx_gain < 0xFF) ? 1 : 0; |
2167 | hostif_sme_enqueue(priv, event: SME_SET_GAIN); |
2168 | return 0; |
2169 | } |
2170 | |
2171 | static int ks_wlan_get_rx_gain(struct net_device *dev, |
2172 | struct iw_request_info *info, |
2173 | union iwreq_data *uwrq, char *) |
2174 | { |
2175 | struct ks_wlan_private *priv = netdev_priv(dev); |
2176 | |
2177 | if (priv->sleep_mode == SLP_SLEEP) |
2178 | return -EPERM; |
2179 | /* for SLEEP MODE */ |
2180 | uwrq->mode = priv->gain.rx_gain; |
2181 | hostif_sme_enqueue(priv, event: SME_GET_GAIN); |
2182 | return 0; |
2183 | } |
2184 | |
2185 | static int ks_wlan_get_eeprom_cksum(struct net_device *dev, |
2186 | struct iw_request_info *info, |
2187 | union iwreq_data *uwrq, char *) |
2188 | { |
2189 | struct ks_wlan_private *priv = netdev_priv(dev); |
2190 | |
2191 | uwrq->mode = priv->eeprom_checksum; |
2192 | return 0; |
2193 | } |
2194 | |
2195 | static void print_hif_event(struct net_device *dev, int event) |
2196 | { |
2197 | switch (event) { |
2198 | case HIF_DATA_REQ: |
2199 | netdev_info(dev, format: "HIF_DATA_REQ\n" ); |
2200 | break; |
2201 | case HIF_DATA_IND: |
2202 | netdev_info(dev, format: "HIF_DATA_IND\n" ); |
2203 | break; |
2204 | case HIF_MIB_GET_REQ: |
2205 | netdev_info(dev, format: "HIF_MIB_GET_REQ\n" ); |
2206 | break; |
2207 | case HIF_MIB_GET_CONF: |
2208 | netdev_info(dev, format: "HIF_MIB_GET_CONF\n" ); |
2209 | break; |
2210 | case HIF_MIB_SET_REQ: |
2211 | netdev_info(dev, format: "HIF_MIB_SET_REQ\n" ); |
2212 | break; |
2213 | case HIF_MIB_SET_CONF: |
2214 | netdev_info(dev, format: "HIF_MIB_SET_CONF\n" ); |
2215 | break; |
2216 | case HIF_POWER_MGMT_REQ: |
2217 | netdev_info(dev, format: "HIF_POWER_MGMT_REQ\n" ); |
2218 | break; |
2219 | case HIF_POWER_MGMT_CONF: |
2220 | netdev_info(dev, format: "HIF_POWER_MGMT_CONF\n" ); |
2221 | break; |
2222 | case HIF_START_REQ: |
2223 | netdev_info(dev, format: "HIF_START_REQ\n" ); |
2224 | break; |
2225 | case HIF_START_CONF: |
2226 | netdev_info(dev, format: "HIF_START_CONF\n" ); |
2227 | break; |
2228 | case HIF_CONNECT_IND: |
2229 | netdev_info(dev, format: "HIF_CONNECT_IND\n" ); |
2230 | break; |
2231 | case HIF_STOP_REQ: |
2232 | netdev_info(dev, format: "HIF_STOP_REQ\n" ); |
2233 | break; |
2234 | case HIF_STOP_CONF: |
2235 | netdev_info(dev, format: "HIF_STOP_CONF\n" ); |
2236 | break; |
2237 | case HIF_PS_ADH_SET_REQ: |
2238 | netdev_info(dev, format: "HIF_PS_ADH_SET_REQ\n" ); |
2239 | break; |
2240 | case HIF_PS_ADH_SET_CONF: |
2241 | netdev_info(dev, format: "HIF_PS_ADH_SET_CONF\n" ); |
2242 | break; |
2243 | case HIF_INFRA_SET_REQ: |
2244 | netdev_info(dev, format: "HIF_INFRA_SET_REQ\n" ); |
2245 | break; |
2246 | case HIF_INFRA_SET_CONF: |
2247 | netdev_info(dev, format: "HIF_INFRA_SET_CONF\n" ); |
2248 | break; |
2249 | case HIF_ADH_SET_REQ: |
2250 | netdev_info(dev, format: "HIF_ADH_SET_REQ\n" ); |
2251 | break; |
2252 | case HIF_ADH_SET_CONF: |
2253 | netdev_info(dev, format: "HIF_ADH_SET_CONF\n" ); |
2254 | break; |
2255 | case HIF_AP_SET_REQ: |
2256 | netdev_info(dev, format: "HIF_AP_SET_REQ\n" ); |
2257 | break; |
2258 | case HIF_AP_SET_CONF: |
2259 | netdev_info(dev, format: "HIF_AP_SET_CONF\n" ); |
2260 | break; |
2261 | case HIF_ASSOC_INFO_IND: |
2262 | netdev_info(dev, format: "HIF_ASSOC_INFO_IND\n" ); |
2263 | break; |
2264 | case HIF_MIC_FAILURE_REQ: |
2265 | netdev_info(dev, format: "HIF_MIC_FAILURE_REQ\n" ); |
2266 | break; |
2267 | case HIF_MIC_FAILURE_CONF: |
2268 | netdev_info(dev, format: "HIF_MIC_FAILURE_CONF\n" ); |
2269 | break; |
2270 | case HIF_SCAN_REQ: |
2271 | netdev_info(dev, format: "HIF_SCAN_REQ\n" ); |
2272 | break; |
2273 | case HIF_SCAN_CONF: |
2274 | netdev_info(dev, format: "HIF_SCAN_CONF\n" ); |
2275 | break; |
2276 | case HIF_PHY_INFO_REQ: |
2277 | netdev_info(dev, format: "HIF_PHY_INFO_REQ\n" ); |
2278 | break; |
2279 | case HIF_PHY_INFO_CONF: |
2280 | netdev_info(dev, format: "HIF_PHY_INFO_CONF\n" ); |
2281 | break; |
2282 | case HIF_SLEEP_REQ: |
2283 | netdev_info(dev, format: "HIF_SLEEP_REQ\n" ); |
2284 | break; |
2285 | case HIF_SLEEP_CONF: |
2286 | netdev_info(dev, format: "HIF_SLEEP_CONF\n" ); |
2287 | break; |
2288 | case HIF_PHY_INFO_IND: |
2289 | netdev_info(dev, format: "HIF_PHY_INFO_IND\n" ); |
2290 | break; |
2291 | case HIF_SCAN_IND: |
2292 | netdev_info(dev, format: "HIF_SCAN_IND\n" ); |
2293 | break; |
2294 | case HIF_INFRA_SET2_REQ: |
2295 | netdev_info(dev, format: "HIF_INFRA_SET2_REQ\n" ); |
2296 | break; |
2297 | case HIF_INFRA_SET2_CONF: |
2298 | netdev_info(dev, format: "HIF_INFRA_SET2_CONF\n" ); |
2299 | break; |
2300 | case HIF_ADH_SET2_REQ: |
2301 | netdev_info(dev, format: "HIF_ADH_SET2_REQ\n" ); |
2302 | break; |
2303 | case HIF_ADH_SET2_CONF: |
2304 | netdev_info(dev, format: "HIF_ADH_SET2_CONF\n" ); |
2305 | } |
2306 | } |
2307 | |
2308 | /* get host command history */ |
2309 | static int ks_wlan_hostt(struct net_device *dev, struct iw_request_info *info, |
2310 | union iwreq_data *uwrq, char *) |
2311 | { |
2312 | int i, event; |
2313 | struct ks_wlan_private *priv = netdev_priv(dev); |
2314 | |
2315 | for (i = 63; i >= 0; i--) { |
2316 | event = |
2317 | priv->hostt.buff[(priv->hostt.qtail - 1 - i) % |
2318 | SME_EVENT_BUFF_SIZE]; |
2319 | print_hif_event(dev, event); |
2320 | } |
2321 | return 0; |
2322 | } |
2323 | |
2324 | /* Structures to export the Wireless Handlers */ |
2325 | |
2326 | static const struct iw_priv_args ks_wlan_private_args[] = { |
2327 | /*{ cmd, set_args, get_args, name[16] } */ |
2328 | {KS_WLAN_GET_FIRM_VERSION, IW_PRIV_TYPE_NONE, |
2329 | IW_PRIV_TYPE_CHAR | (128 + 1), "GetFirmwareVer" }, |
2330 | {KS_WLAN_SET_WPS_ENABLE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
2331 | IW_PRIV_TYPE_NONE, "SetWPSEnable" }, |
2332 | {KS_WLAN_GET_WPS_ENABLE, IW_PRIV_TYPE_NONE, |
2333 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "GetW" }, |
2334 | {KS_WLAN_SET_WPS_PROBE_REQ, IW_PRIV_TYPE_BYTE | 2047, IW_PRIV_TYPE_NONE, |
2335 | "SetWPSProbeReq" }, |
2336 | {KS_WLAN_SET_PREAMBLE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
2337 | IW_PRIV_TYPE_NONE, "SetPreamble" }, |
2338 | {KS_WLAN_GET_PREAMBLE, IW_PRIV_TYPE_NONE, |
2339 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "GetPreamble" }, |
2340 | {KS_WLAN_SET_POWER_SAVE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
2341 | IW_PRIV_TYPE_NONE, "SetPowerSave" }, |
2342 | {KS_WLAN_GET_POWER_SAVE, IW_PRIV_TYPE_NONE, |
2343 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "GetPowerSave" }, |
2344 | {KS_WLAN_SET_SCAN_TYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
2345 | IW_PRIV_TYPE_NONE, "SetScanType" }, |
2346 | {KS_WLAN_GET_SCAN_TYPE, IW_PRIV_TYPE_NONE, |
2347 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "GetScanType" }, |
2348 | {KS_WLAN_SET_RX_GAIN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
2349 | IW_PRIV_TYPE_NONE, "SetRxGain" }, |
2350 | {KS_WLAN_GET_RX_GAIN, IW_PRIV_TYPE_NONE, |
2351 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "GetRxGain" }, |
2352 | {KS_WLAN_HOSTT, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | (128 + 1), |
2353 | "hostt" }, |
2354 | {KS_WLAN_SET_BEACON_LOST, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
2355 | IW_PRIV_TYPE_NONE, "SetBeaconLost" }, |
2356 | {KS_WLAN_GET_BEACON_LOST, IW_PRIV_TYPE_NONE, |
2357 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "GetBeaconLost" }, |
2358 | {KS_WLAN_SET_SLEEP_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
2359 | IW_PRIV_TYPE_NONE, "SetSleepMode" }, |
2360 | {KS_WLAN_GET_SLEEP_MODE, IW_PRIV_TYPE_NONE, |
2361 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "GetSleepMode" }, |
2362 | {KS_WLAN_SET_TX_GAIN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
2363 | IW_PRIV_TYPE_NONE, "SetTxGain" }, |
2364 | {KS_WLAN_GET_TX_GAIN, IW_PRIV_TYPE_NONE, |
2365 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "GetTxGain" }, |
2366 | {KS_WLAN_SET_PHY_TYPE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
2367 | IW_PRIV_TYPE_NONE, "SetPhyType" }, |
2368 | {KS_WLAN_GET_PHY_TYPE, IW_PRIV_TYPE_NONE, |
2369 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "GetPhyType" }, |
2370 | {KS_WLAN_SET_CTS_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
2371 | IW_PRIV_TYPE_NONE, "SetCtsMode" }, |
2372 | {KS_WLAN_GET_CTS_MODE, IW_PRIV_TYPE_NONE, |
2373 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "GetCtsMode" }, |
2374 | {KS_WLAN_GET_EEPROM_CKSUM, IW_PRIV_TYPE_NONE, |
2375 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "GetChecksum" }, |
2376 | }; |
2377 | |
2378 | static const iw_handler ks_wlan_handler[] = { |
2379 | IW_HANDLER(SIOCSIWCOMMIT, ks_wlan_config_commit), |
2380 | IW_HANDLER(SIOCGIWNAME, ks_wlan_get_name), |
2381 | IW_HANDLER(SIOCSIWFREQ, ks_wlan_set_freq), |
2382 | IW_HANDLER(SIOCGIWFREQ, ks_wlan_get_freq), |
2383 | IW_HANDLER(SIOCSIWMODE, ks_wlan_set_mode), |
2384 | IW_HANDLER(SIOCGIWMODE, ks_wlan_get_mode), |
2385 | IW_HANDLER(SIOCGIWRANGE, ks_wlan_get_range), |
2386 | IW_HANDLER(SIOCGIWSTATS, ks_wlan_get_iwstats), |
2387 | IW_HANDLER(SIOCSIWAP, ks_wlan_set_wap), |
2388 | IW_HANDLER(SIOCGIWAP, ks_wlan_get_wap), |
2389 | IW_HANDLER(SIOCSIWMLME, ks_wlan_set_mlme), |
2390 | IW_HANDLER(SIOCGIWAPLIST, ks_wlan_get_aplist), |
2391 | IW_HANDLER(SIOCSIWSCAN, ks_wlan_set_scan), |
2392 | IW_HANDLER(SIOCGIWSCAN, ks_wlan_get_scan), |
2393 | IW_HANDLER(SIOCSIWESSID, ks_wlan_set_essid), |
2394 | IW_HANDLER(SIOCGIWESSID, ks_wlan_get_essid), |
2395 | IW_HANDLER(SIOCSIWNICKN, ks_wlan_set_nick), |
2396 | IW_HANDLER(SIOCGIWNICKN, ks_wlan_get_nick), |
2397 | IW_HANDLER(SIOCSIWRATE, ks_wlan_set_rate), |
2398 | IW_HANDLER(SIOCGIWRATE, ks_wlan_get_rate), |
2399 | IW_HANDLER(SIOCSIWRTS, ks_wlan_set_rts), |
2400 | IW_HANDLER(SIOCGIWRTS, ks_wlan_get_rts), |
2401 | IW_HANDLER(SIOCSIWFRAG, ks_wlan_set_frag), |
2402 | IW_HANDLER(SIOCGIWFRAG, ks_wlan_get_frag), |
2403 | IW_HANDLER(SIOCSIWENCODE, ks_wlan_set_encode), |
2404 | IW_HANDLER(SIOCGIWENCODE, ks_wlan_get_encode), |
2405 | IW_HANDLER(SIOCSIWPOWER, ks_wlan_set_power), |
2406 | IW_HANDLER(SIOCGIWPOWER, ks_wlan_get_power), |
2407 | IW_HANDLER(SIOCSIWGENIE, ks_wlan_set_genie), |
2408 | IW_HANDLER(SIOCSIWAUTH, ks_wlan_set_auth_mode), |
2409 | IW_HANDLER(SIOCGIWAUTH, ks_wlan_get_auth_mode), |
2410 | IW_HANDLER(SIOCSIWENCODEEXT, ks_wlan_set_encode_ext), |
2411 | IW_HANDLER(SIOCGIWENCODEEXT, ks_wlan_get_encode_ext), |
2412 | IW_HANDLER(SIOCSIWPMKSA, ks_wlan_set_pmksa), |
2413 | }; |
2414 | |
2415 | /* private_handler */ |
2416 | static const iw_handler ks_wlan_private_handler[] = { |
2417 | NULL, /* 0 */ |
2418 | NULL, /* 1, KS_WLAN_GET_DRIVER_VERSION */ |
2419 | NULL, /* 2 */ |
2420 | ks_wlan_get_firmware_version, /* 3 KS_WLAN_GET_FIRM_VERSION */ |
2421 | ks_wlan_set_wps_enable, /* 4 KS_WLAN_SET_WPS_ENABLE */ |
2422 | ks_wlan_get_wps_enable, /* 5 KS_WLAN_GET_WPS_ENABLE */ |
2423 | ks_wlan_set_wps_probe_req, /* 6 KS_WLAN_SET_WPS_PROBE_REQ */ |
2424 | ks_wlan_get_eeprom_cksum, /* 7 KS_WLAN_GET_CONNECT */ |
2425 | ks_wlan_set_preamble, /* 8 KS_WLAN_SET_PREAMBLE */ |
2426 | ks_wlan_get_preamble, /* 9 KS_WLAN_GET_PREAMBLE */ |
2427 | ks_wlan_set_power_mgmt, /* 10 KS_WLAN_SET_POWER_SAVE */ |
2428 | ks_wlan_get_power_mgmt, /* 11 KS_WLAN_GET_POWER_SAVE */ |
2429 | ks_wlan_set_scan_type, /* 12 KS_WLAN_SET_SCAN_TYPE */ |
2430 | ks_wlan_get_scan_type, /* 13 KS_WLAN_GET_SCAN_TYPE */ |
2431 | ks_wlan_set_rx_gain, /* 14 KS_WLAN_SET_RX_GAIN */ |
2432 | ks_wlan_get_rx_gain, /* 15 KS_WLAN_GET_RX_GAIN */ |
2433 | ks_wlan_hostt, /* 16 KS_WLAN_HOSTT */ |
2434 | NULL, /* 17 */ |
2435 | ks_wlan_set_beacon_lost, /* 18 KS_WLAN_SET_BECAN_LOST */ |
2436 | ks_wlan_get_beacon_lost, /* 19 KS_WLAN_GET_BECAN_LOST */ |
2437 | ks_wlan_set_tx_gain, /* 20 KS_WLAN_SET_TX_GAIN */ |
2438 | ks_wlan_get_tx_gain, /* 21 KS_WLAN_GET_TX_GAIN */ |
2439 | ks_wlan_set_phy_type, /* 22 KS_WLAN_SET_PHY_TYPE */ |
2440 | ks_wlan_get_phy_type, /* 23 KS_WLAN_GET_PHY_TYPE */ |
2441 | ks_wlan_set_cts_mode, /* 24 KS_WLAN_SET_CTS_MODE */ |
2442 | ks_wlan_get_cts_mode, /* 25 KS_WLAN_GET_CTS_MODE */ |
2443 | NULL, /* 26 */ |
2444 | NULL, /* 27 */ |
2445 | ks_wlan_set_sleep_mode, /* 28 KS_WLAN_SET_SLEEP_MODE */ |
2446 | ks_wlan_get_sleep_mode, /* 29 KS_WLAN_GET_SLEEP_MODE */ |
2447 | NULL, /* 30 */ |
2448 | NULL, /* 31 */ |
2449 | }; |
2450 | |
2451 | static const struct iw_handler_def ks_wlan_handler_def = { |
2452 | .num_standard = ARRAY_SIZE(ks_wlan_handler), |
2453 | .num_private = ARRAY_SIZE(ks_wlan_private_handler), |
2454 | .num_private_args = ARRAY_SIZE(ks_wlan_private_args), |
2455 | .standard = ks_wlan_handler, |
2456 | .private = ks_wlan_private_handler, |
2457 | .private_args = ks_wlan_private_args, |
2458 | .get_wireless_stats = ks_get_wireless_stats, |
2459 | }; |
2460 | |
2461 | static int ks_wlan_netdev_ioctl(struct net_device *dev, struct ifreq *rq, |
2462 | int cmd) |
2463 | { |
2464 | int ret; |
2465 | struct iwreq *wrq = (struct iwreq *)rq; |
2466 | |
2467 | switch (cmd) { |
2468 | case SIOCIWFIRSTPRIV + 20: /* KS_WLAN_SET_STOP_REQ */ |
2469 | ret = ks_wlan_set_stop_request(dev, NULL, uwrq: &wrq->u, NULL); |
2470 | break; |
2471 | // All other calls are currently unsupported |
2472 | default: |
2473 | ret = -EOPNOTSUPP; |
2474 | } |
2475 | |
2476 | return ret; |
2477 | } |
2478 | |
2479 | static |
2480 | struct net_device_stats *ks_wlan_get_stats(struct net_device *dev) |
2481 | { |
2482 | struct ks_wlan_private *priv = netdev_priv(dev); |
2483 | |
2484 | if (priv->dev_state < DEVICE_STATE_READY) |
2485 | return NULL; /* not finished initialize */ |
2486 | |
2487 | return &priv->nstats; |
2488 | } |
2489 | |
2490 | static |
2491 | int ks_wlan_set_mac_address(struct net_device *dev, void *addr) |
2492 | { |
2493 | struct ks_wlan_private *priv = netdev_priv(dev); |
2494 | struct sockaddr *mac_addr = (struct sockaddr *)addr; |
2495 | |
2496 | if (netif_running(dev)) |
2497 | return -EBUSY; |
2498 | eth_hw_addr_set(dev, addr: mac_addr->sa_data); |
2499 | ether_addr_copy(dst: priv->eth_addr, src: mac_addr->sa_data); |
2500 | |
2501 | priv->mac_address_valid = false; |
2502 | hostif_sme_enqueue(priv, event: SME_MACADDRESS_SET_REQUEST); |
2503 | netdev_info(dev, format: "ks_wlan: MAC ADDRESS = %pM\n" , priv->eth_addr); |
2504 | return 0; |
2505 | } |
2506 | |
2507 | static |
2508 | void ks_wlan_tx_timeout(struct net_device *dev, unsigned int txqueue) |
2509 | { |
2510 | struct ks_wlan_private *priv = netdev_priv(dev); |
2511 | |
2512 | netdev_dbg(dev, "head(%d) tail(%d)!!\n" , priv->tx_dev.qhead, |
2513 | priv->tx_dev.qtail); |
2514 | if (!netif_queue_stopped(dev)) |
2515 | netif_stop_queue(dev); |
2516 | priv->nstats.tx_errors++; |
2517 | netif_wake_queue(dev); |
2518 | } |
2519 | |
2520 | static |
2521 | netdev_tx_t ks_wlan_start_xmit(struct sk_buff *skb, struct net_device *dev) |
2522 | { |
2523 | struct ks_wlan_private *priv = netdev_priv(dev); |
2524 | int ret; |
2525 | |
2526 | netdev_dbg(dev, "in_interrupt()=%ld\n" , in_interrupt()); |
2527 | |
2528 | if (!skb) { |
2529 | netdev_err(dev, format: "ks_wlan: skb == NULL!!!\n" ); |
2530 | return 0; |
2531 | } |
2532 | if (priv->dev_state < DEVICE_STATE_READY) { |
2533 | dev_kfree_skb(skb); |
2534 | return 0; /* not finished initialize */ |
2535 | } |
2536 | |
2537 | if (netif_running(dev)) |
2538 | netif_stop_queue(dev); |
2539 | |
2540 | ret = hostif_data_request(priv, skb); |
2541 | netif_trans_update(dev); |
2542 | |
2543 | if (ret) |
2544 | netdev_err(dev, format: "hostif_data_request error: =%d\n" , ret); |
2545 | |
2546 | return 0; |
2547 | } |
2548 | |
2549 | void send_packet_complete(struct ks_wlan_private *priv, struct sk_buff *skb) |
2550 | { |
2551 | priv->nstats.tx_packets++; |
2552 | |
2553 | if (netif_queue_stopped(dev: priv->net_dev)) |
2554 | netif_wake_queue(dev: priv->net_dev); |
2555 | |
2556 | if (skb) { |
2557 | priv->nstats.tx_bytes += skb->len; |
2558 | dev_kfree_skb(skb); |
2559 | } |
2560 | } |
2561 | |
2562 | /* |
2563 | * Set or clear the multicast filter for this adaptor. |
2564 | * This routine is not state sensitive and need not be SMP locked. |
2565 | */ |
2566 | static |
2567 | void ks_wlan_set_rx_mode(struct net_device *dev) |
2568 | { |
2569 | struct ks_wlan_private *priv = netdev_priv(dev); |
2570 | |
2571 | if (priv->dev_state < DEVICE_STATE_READY) |
2572 | return; /* not finished initialize */ |
2573 | hostif_sme_enqueue(priv, event: SME_MULTICAST_REQUEST); |
2574 | } |
2575 | |
2576 | static |
2577 | int ks_wlan_open(struct net_device *dev) |
2578 | { |
2579 | struct ks_wlan_private *priv = netdev_priv(dev); |
2580 | |
2581 | priv->cur_rx = 0; |
2582 | |
2583 | if (!priv->mac_address_valid) { |
2584 | netdev_err(dev, format: "ks_wlan : %s Not READY !!\n" , dev->name); |
2585 | return -EBUSY; |
2586 | } |
2587 | netif_start_queue(dev); |
2588 | |
2589 | return 0; |
2590 | } |
2591 | |
2592 | static |
2593 | int ks_wlan_close(struct net_device *dev) |
2594 | { |
2595 | netif_stop_queue(dev); |
2596 | |
2597 | return 0; |
2598 | } |
2599 | |
2600 | /* Operational parameters that usually are not changed. */ |
2601 | /* Time in jiffies before concluding the transmitter is hung. */ |
2602 | #define TX_TIMEOUT (3 * HZ) |
2603 | static const unsigned char dummy_addr[] = { |
2604 | 0x00, 0x0b, 0xe3, 0x00, 0x00, 0x00 |
2605 | }; |
2606 | |
2607 | static const struct net_device_ops ks_wlan_netdev_ops = { |
2608 | .ndo_start_xmit = ks_wlan_start_xmit, |
2609 | .ndo_open = ks_wlan_open, |
2610 | .ndo_stop = ks_wlan_close, |
2611 | .ndo_do_ioctl = ks_wlan_netdev_ioctl, |
2612 | .ndo_set_mac_address = ks_wlan_set_mac_address, |
2613 | .ndo_get_stats = ks_wlan_get_stats, |
2614 | .ndo_tx_timeout = ks_wlan_tx_timeout, |
2615 | .ndo_set_rx_mode = ks_wlan_set_rx_mode, |
2616 | }; |
2617 | |
2618 | int ks_wlan_net_start(struct net_device *dev) |
2619 | { |
2620 | struct ks_wlan_private *priv; |
2621 | /* int rc; */ |
2622 | |
2623 | priv = netdev_priv(dev); |
2624 | priv->mac_address_valid = false; |
2625 | priv->is_device_open = true; |
2626 | priv->need_commit = 0; |
2627 | /* phy information update timer */ |
2628 | atomic_set(v: &update_phyinfo, i: 0); |
2629 | timer_setup(&update_phyinfo_timer, ks_wlan_update_phyinfo_timeout, 0); |
2630 | |
2631 | /* dummy address set */ |
2632 | ether_addr_copy(dst: priv->eth_addr, src: dummy_addr); |
2633 | eth_hw_addr_set(dev, addr: priv->eth_addr); |
2634 | |
2635 | /* The ks_wlan-specific entries in the device structure. */ |
2636 | dev->netdev_ops = &ks_wlan_netdev_ops; |
2637 | dev->wireless_handlers = &ks_wlan_handler_def; |
2638 | dev->watchdog_timeo = TX_TIMEOUT; |
2639 | |
2640 | netif_carrier_off(dev); |
2641 | |
2642 | return 0; |
2643 | } |
2644 | |
2645 | int ks_wlan_net_stop(struct net_device *dev) |
2646 | { |
2647 | struct ks_wlan_private *priv = netdev_priv(dev); |
2648 | |
2649 | priv->is_device_open = false; |
2650 | del_timer_sync(timer: &update_phyinfo_timer); |
2651 | |
2652 | if (netif_running(dev)) |
2653 | netif_stop_queue(dev); |
2654 | |
2655 | return 0; |
2656 | } |
2657 | |
2658 | /** |
2659 | * is_connect_status() - return true if status is 'connected' |
2660 | * @status: high bit is used as FORCE_DISCONNECT, low bits used for |
2661 | * connect status. |
2662 | */ |
2663 | bool is_connect_status(u32 status) |
2664 | { |
2665 | return (status & CONNECT_STATUS_MASK) == CONNECT_STATUS; |
2666 | } |
2667 | |
2668 | /** |
2669 | * is_disconnect_status() - return true if status is 'disconnected' |
2670 | * @status: high bit is used as FORCE_DISCONNECT, low bits used for |
2671 | * disconnect status. |
2672 | */ |
2673 | bool is_disconnect_status(u32 status) |
2674 | { |
2675 | return (status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS; |
2676 | } |
2677 | |