~ubuntu-branches/ubuntu/trusty/bcmwl/trusty-proposed

« back to all changes in this revision

Viewing changes to src/src/wl/sys/wl_cfg80211_hybrid.c

  • Committer: Package Import Robot
  • Author(s): Alberto Milone
  • Date: 2013-05-15 13:11:43 UTC
  • mfrom: (2.1.7)
  • Revision ID: package-import@ubuntu.com-20130515131143-0i960cfjq3dsst6h
Tags: 6.30.223.30+bdcom-0ubuntu1
* New upstream release.
* debian/dkms.conf.in:
  - Drop patches for Linux 3.2 and 3.4.
* 0006-add-support-for-linux-3.8.0.patch,
  0007-nl80211-move-scan-API-to-wdev.patch:
  - Refresh against new release.
* 0008-add-support-for-linux-3.9.0.patch:
  - Add support for Linux 3.9 (LP: #1157880).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Linux-specific portion of Broadcom 802.11abg Networking Device Driver
 
3
 * cfg80211 interface
 
4
 *
 
5
 * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved.
 
6
 * 
 
7
 * Permission to use, copy, modify, and/or distribute this software for any
 
8
 * purpose with or without fee is hereby granted, provided that the above
 
9
 * copyright notice and this permission notice appear in all copies.
 
10
 * 
 
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 
14
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 
16
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 
17
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
18
 *
 
19
 * $Id: wl_cfg80211.c,v 1.1.6.4 2011-02-11 00:22:09 $
 
20
 */
 
21
 
 
22
#if defined(USE_CFG80211)
 
23
 
 
24
#define LINUX_PORT
 
25
#include <typedefs.h>
 
26
#include <linuxver.h>
 
27
#include <osl.h>
 
28
 
 
29
#include <linux/kernel.h>
 
30
#include <linux/kthread.h>
 
31
#include <linux/netdevice.h>
 
32
#include <linux/ieee80211.h>
 
33
#include <net/cfg80211.h>
 
34
#include <linux/nl80211.h>
 
35
#include <net/rtnetlink.h>
 
36
#include <bcmutils.h>
 
37
#include <bcmendian.h>
 
38
#include <wlioctl.h>
 
39
#include <proto/802.11.h>
 
40
#include <wl_cfg80211_hybrid.h>
 
41
 
 
42
#define EVENT_TYPE(e) dtoh32((e)->event_type)
 
43
#define EVENT_FLAGS(e) dtoh16((e)->flags)
 
44
#define EVENT_STATUS(e) dtoh32((e)->status)
 
45
 
 
46
u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
 
47
 
 
48
static s32 wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 
49
           enum nl80211_iftype type, u32 *flags, struct vif_params *params);
 
50
static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 
51
           struct cfg80211_scan_request *request);
 
52
static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
 
53
static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 
54
           struct cfg80211_ibss_params *params);
 
55
static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
 
56
static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
 
57
           struct net_device *dev, u8 *mac, struct station_info *sinfo);
 
58
static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
 
59
           struct net_device *dev, bool enabled, s32 timeout);
 
60
static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 
61
           struct cfg80211_connect_params *sme);
 
62
static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code);
 
63
 
 
64
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
 
65
static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
 
66
           enum nl80211_tx_power_setting type, s32 dbm);
 
67
#else
 
68
static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
 
69
           enum tx_power_setting type, s32 dbm);
 
70
#endif
 
71
 
 
72
static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
 
73
 
 
74
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
 
75
static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
 
76
           struct net_device *dev, u8 key_idx, bool unicast, bool multicast);
 
77
#else
 
78
static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
 
79
           struct net_device *dev, u8 key_idx);
 
80
#endif
 
81
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
 
82
static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 
83
           u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params);
 
84
static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 
85
           u8 key_idx, bool pairwise, const u8 *mac_addr);
 
86
static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 
87
           u8 key_idx, bool pairwise, const u8 *mac_addr,
 
88
           void *cookie, void (*callback) (void *cookie, struct key_params *params));
 
89
#else
 
90
static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 
91
           u8 key_idx, const u8 *mac_addr, struct key_params *params);
 
92
static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 
93
           u8 key_idx, const u8 *mac_addr);
 
94
static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 
95
           u8 key_idx, const u8 *mac_addr,
 
96
           void *cookie, void (*callback) (void *cookie, struct key_params *params));
 
97
#endif 
 
98
 
 
99
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
 
100
static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
 
101
           struct cfg80211_pmksa *pmksa);
 
102
static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
 
103
           struct cfg80211_pmksa *pmksa);
 
104
static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev);
 
105
#endif
 
106
 
 
107
static s32 wl_create_event_handler(struct wl_cfg80211_priv *wl);
 
108
static void wl_destroy_event_handler(struct wl_cfg80211_priv *wl);
 
109
static s32 wl_event_handler(void *data);
 
110
static void wl_init_eq(struct wl_cfg80211_priv *wl);
 
111
static void wl_flush_eq(struct wl_cfg80211_priv *wl);
 
112
static void wl_lock_eq(struct wl_cfg80211_priv *wl);
 
113
static void wl_unlock_eq(struct wl_cfg80211_priv *wl);
 
114
static void wl_init_eq_lock(struct wl_cfg80211_priv *wl);
 
115
static void wl_init_eloop_handler(struct wl_cfg80211_event_loop *el);
 
116
static struct wl_cfg80211_event_q *wl_deq_event(struct wl_cfg80211_priv *wl);
 
117
static s32 wl_enq_event(struct wl_cfg80211_priv *wl, u32 type,
 
118
        const wl_event_msg_t *msg, void *data);
 
119
static void wl_put_event(struct wl_cfg80211_event_q *e);
 
120
static void wl_wakeup_event(struct wl_cfg80211_priv *wl);
 
121
 
 
122
static s32 wl_notify_connect_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
123
           const wl_event_msg_t *e, void *data);
 
124
static s32 wl_notify_roaming_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
125
           const wl_event_msg_t *e, void *data);
 
126
static s32 wl_notify_scan_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
127
           const wl_event_msg_t *e, void *data);
 
128
static s32 wl_bss_connect_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
129
           const wl_event_msg_t *e, void *data, bool completed);
 
130
static s32 wl_bss_roaming_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
131
           const wl_event_msg_t *e, void *data);
 
132
static s32 wl_notify_mic_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
133
           const wl_event_msg_t *e, void *data);
 
134
 
 
135
static s32 wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf, s32 buf_len);
 
136
static __used s32 wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len);
 
137
static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
 
138
static s32 wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval);
 
139
static s32 wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len);
 
140
 
 
141
static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
 
142
static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
 
143
static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
 
144
 
 
145
static void wl_init_prof(struct wl_cfg80211_profile *prof);
 
146
 
 
147
static s32 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme);
 
148
static s32 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme);
 
149
static s32 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme);
 
150
static s32 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme);
 
151
static s32 wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme);
 
152
static s32 wl_get_assoc_ies(struct wl_cfg80211_priv *wl);
 
153
static void wl_ch_to_chanspec(struct ieee80211_channel *chan,
 
154
            struct wl_join_params *join_params, size_t *join_params_size);
 
155
 
 
156
static void wl_rst_ie(struct wl_cfg80211_priv *wl);
 
157
static __used s32 wl_add_ie(struct wl_cfg80211_priv *wl, u8 t, u8 l, u8 *v);
 
158
static s32 wl_mrg_ie(struct wl_cfg80211_priv *wl, u8 *ie_stream, u16 ie_size);
 
159
static s32 wl_cp_ie(struct wl_cfg80211_priv *wl, u8 *dst, u16 dst_size);
 
160
static u32 wl_get_ielen(struct wl_cfg80211_priv *wl);
 
161
 
 
162
static s32 wl_mode_to_nl80211_iftype(s32 mode);
 
163
 
 
164
static s32 wl_alloc_wdev(struct device *dev, struct wireless_dev **rwdev);
 
165
static void wl_free_wdev(struct wl_cfg80211_priv *wl);
 
166
 
 
167
static s32 wl_inform_bss(struct wl_cfg80211_priv *wl, struct wl_scan_results *bss_list);
 
168
static s32 wl_inform_single_bss(struct wl_cfg80211_priv *wl, struct wl_bss_info *bi);
 
169
static s32 wl_update_bss_info(struct wl_cfg80211_priv *wl);
 
170
 
 
171
static void key_endian_to_device(struct wl_wsec_key *key);
 
172
static void key_endian_to_host(struct wl_wsec_key *key);
 
173
 
 
174
static s32 wl_init_priv_mem(struct wl_cfg80211_priv *wl);
 
175
static void wl_deinit_priv_mem(struct wl_cfg80211_priv *wl);
 
176
 
 
177
static bool wl_is_ibssmode(struct wl_cfg80211_priv *wl);
 
178
 
 
179
static void wl_link_up(struct wl_cfg80211_priv *wl);
 
180
static void wl_link_down(struct wl_cfg80211_priv *wl);
 
181
static s32 wl_set_mode(struct net_device *ndev, s32 iftype);
 
182
 
 
183
static void wl_init_conf(struct wl_cfg80211_conf *conf);
 
184
 
 
185
static s32 wl_update_wiphybands(struct wl_cfg80211_priv *wl);
 
186
 
 
187
static __used s32 wl_update_pmklist(struct net_device *dev,
 
188
                  struct wl_cfg80211_pmk_list *pmk_list, s32 err);
 
189
 
 
190
#if defined(WL_DBGMSG_ENABLE)
 
191
#define WL_DBG_ESTR_MAX 32
 
192
static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
 
193
        "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
 
194
        "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
 
195
        "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
 
196
        "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
 
197
        "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
 
198
        "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
 
199
        "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
 
200
        "PFN_NET_LOST",
 
201
        "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
 
202
        "IBSS_ASSOC",
 
203
        "RADIO", "PSM_WATCHDOG",
 
204
        "PROBREQ_MSG",
 
205
        "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
 
206
        "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
 
207
        "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
 
208
        "IF",
 
209
        "RSSI", "PFN_SCAN_COMPLETE", "ACTION_FRAME", "ACTION_FRAME_COMPLETE",
 
210
};
 
211
#endif                          
 
212
 
 
213
#define CHAN2G(_channel, _freq, _flags) {                       \
 
214
        .band                   = IEEE80211_BAND_2GHZ,          \
 
215
        .center_freq            = (_freq),                      \
 
216
        .hw_value               = (_channel),                   \
 
217
        .flags                  = (_flags),                     \
 
218
        .max_antenna_gain       = 0,                            \
 
219
        .max_power              = 30,                           \
 
220
}
 
221
 
 
222
#define CHAN5G(_channel, _flags) {                              \
 
223
        .band                   = IEEE80211_BAND_5GHZ,          \
 
224
        .center_freq            = 5000 + (5 * (_channel)),      \
 
225
        .hw_value               = (_channel),                   \
 
226
        .flags                  = (_flags),                     \
 
227
        .max_antenna_gain       = 0,                            \
 
228
        .max_power              = 30,                           \
 
229
}
 
230
 
 
231
#define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
 
232
#define RATETAB_ENT(_rateid, _flags) \
 
233
        {                                                               \
 
234
                .bitrate        = RATE_TO_BASE100KBPS(_rateid),     \
 
235
                .hw_value       = (_rateid),                            \
 
236
                .flags          = (_flags),                             \
 
237
        }
 
238
 
 
239
static struct ieee80211_rate __wl_rates[] = {
 
240
        RATETAB_ENT(DOT11_RATE_1M, 0),
 
241
        RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
 
242
        RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
 
243
        RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
 
244
        RATETAB_ENT(DOT11_RATE_6M, 0),
 
245
        RATETAB_ENT(DOT11_RATE_9M, 0),
 
246
        RATETAB_ENT(DOT11_RATE_12M, 0),
 
247
        RATETAB_ENT(DOT11_RATE_18M, 0),
 
248
        RATETAB_ENT(DOT11_RATE_24M, 0),
 
249
        RATETAB_ENT(DOT11_RATE_36M, 0),
 
250
        RATETAB_ENT(DOT11_RATE_48M, 0),
 
251
        RATETAB_ENT(DOT11_RATE_54M, 0),
 
252
};
 
253
 
 
254
#define wl_a_rates              (__wl_rates + 4)
 
255
#define wl_a_rates_size 8
 
256
#define wl_g_rates              (__wl_rates + 0)
 
257
#define wl_g_rates_size 12
 
258
 
 
259
static struct ieee80211_channel __wl_2ghz_channels[] = {
 
260
        CHAN2G(1, 2412, 0),
 
261
        CHAN2G(2, 2417, 0),
 
262
        CHAN2G(3, 2422, 0),
 
263
        CHAN2G(4, 2427, 0),
 
264
        CHAN2G(5, 2432, 0),
 
265
        CHAN2G(6, 2437, 0),
 
266
        CHAN2G(7, 2442, 0),
 
267
        CHAN2G(8, 2447, 0),
 
268
        CHAN2G(9, 2452, 0),
 
269
        CHAN2G(10, 2457, 0),
 
270
        CHAN2G(11, 2462, 0),
 
271
        CHAN2G(12, 2467, 0),
 
272
        CHAN2G(13, 2472, 0),
 
273
        CHAN2G(14, 2484, 0),
 
274
};
 
275
 
 
276
static struct ieee80211_channel __wl_5ghz_a_channels[] = {
 
277
        CHAN5G(34, 0), CHAN5G(36, 0),
 
278
        CHAN5G(38, 0), CHAN5G(40, 0),
 
279
        CHAN5G(42, 0), CHAN5G(44, 0),
 
280
        CHAN5G(46, 0), CHAN5G(48, 0),
 
281
        CHAN5G(52, 0), CHAN5G(56, 0),
 
282
        CHAN5G(60, 0), CHAN5G(64, 0),
 
283
        CHAN5G(100, 0), CHAN5G(104, 0),
 
284
        CHAN5G(108, 0), CHAN5G(112, 0),
 
285
        CHAN5G(116, 0), CHAN5G(120, 0),
 
286
        CHAN5G(124, 0), CHAN5G(128, 0),
 
287
        CHAN5G(132, 0), CHAN5G(136, 0),
 
288
        CHAN5G(140, 0), CHAN5G(149, 0),
 
289
        CHAN5G(153, 0), CHAN5G(157, 0),
 
290
        CHAN5G(161, 0), CHAN5G(165, 0),
 
291
        CHAN5G(184, 0), CHAN5G(188, 0),
 
292
        CHAN5G(192, 0), CHAN5G(196, 0),
 
293
        CHAN5G(200, 0), CHAN5G(204, 0),
 
294
        CHAN5G(208, 0), CHAN5G(212, 0),
 
295
        CHAN5G(216, 0),
 
296
};
 
297
 
 
298
static struct ieee80211_channel __wl_5ghz_n_channels[] = {
 
299
        CHAN5G(32, 0), CHAN5G(34, 0),
 
300
        CHAN5G(36, 0), CHAN5G(38, 0),
 
301
        CHAN5G(40, 0), CHAN5G(42, 0),
 
302
        CHAN5G(44, 0), CHAN5G(46, 0),
 
303
        CHAN5G(48, 0), CHAN5G(50, 0),
 
304
        CHAN5G(52, 0), CHAN5G(54, 0),
 
305
        CHAN5G(56, 0), CHAN5G(58, 0),
 
306
        CHAN5G(60, 0), CHAN5G(62, 0),
 
307
        CHAN5G(64, 0), CHAN5G(66, 0),
 
308
        CHAN5G(68, 0), CHAN5G(70, 0),
 
309
        CHAN5G(72, 0), CHAN5G(74, 0),
 
310
        CHAN5G(76, 0), CHAN5G(78, 0),
 
311
        CHAN5G(80, 0), CHAN5G(82, 0),
 
312
        CHAN5G(84, 0), CHAN5G(86, 0),
 
313
        CHAN5G(88, 0), CHAN5G(90, 0),
 
314
        CHAN5G(92, 0), CHAN5G(94, 0),
 
315
        CHAN5G(96, 0), CHAN5G(98, 0),
 
316
        CHAN5G(100, 0), CHAN5G(102, 0),
 
317
        CHAN5G(104, 0), CHAN5G(106, 0),
 
318
        CHAN5G(108, 0), CHAN5G(110, 0),
 
319
        CHAN5G(112, 0), CHAN5G(114, 0),
 
320
        CHAN5G(116, 0), CHAN5G(118, 0),
 
321
        CHAN5G(120, 0), CHAN5G(122, 0),
 
322
        CHAN5G(124, 0), CHAN5G(126, 0),
 
323
        CHAN5G(128, 0), CHAN5G(130, 0),
 
324
        CHAN5G(132, 0), CHAN5G(134, 0),
 
325
        CHAN5G(136, 0), CHAN5G(138, 0),
 
326
        CHAN5G(140, 0), CHAN5G(142, 0),
 
327
        CHAN5G(144, 0), CHAN5G(145, 0),
 
328
        CHAN5G(146, 0), CHAN5G(147, 0),
 
329
        CHAN5G(148, 0), CHAN5G(149, 0),
 
330
        CHAN5G(150, 0), CHAN5G(151, 0),
 
331
        CHAN5G(152, 0), CHAN5G(153, 0),
 
332
        CHAN5G(154, 0), CHAN5G(155, 0),
 
333
        CHAN5G(156, 0), CHAN5G(157, 0),
 
334
        CHAN5G(158, 0), CHAN5G(159, 0),
 
335
        CHAN5G(160, 0), CHAN5G(161, 0),
 
336
        CHAN5G(162, 0), CHAN5G(163, 0),
 
337
        CHAN5G(164, 0), CHAN5G(165, 0),
 
338
        CHAN5G(166, 0), CHAN5G(168, 0),
 
339
        CHAN5G(170, 0), CHAN5G(172, 0),
 
340
        CHAN5G(174, 0), CHAN5G(176, 0),
 
341
        CHAN5G(178, 0), CHAN5G(180, 0),
 
342
        CHAN5G(182, 0), CHAN5G(184, 0),
 
343
        CHAN5G(186, 0), CHAN5G(188, 0),
 
344
        CHAN5G(190, 0), CHAN5G(192, 0),
 
345
        CHAN5G(194, 0), CHAN5G(196, 0),
 
346
        CHAN5G(198, 0), CHAN5G(200, 0),
 
347
        CHAN5G(202, 0), CHAN5G(204, 0),
 
348
        CHAN5G(206, 0), CHAN5G(208, 0),
 
349
        CHAN5G(210, 0), CHAN5G(212, 0),
 
350
        CHAN5G(214, 0), CHAN5G(216, 0),
 
351
        CHAN5G(218, 0), CHAN5G(220, 0),
 
352
        CHAN5G(222, 0), CHAN5G(224, 0),
 
353
        CHAN5G(226, 0), CHAN5G(228, 0),
 
354
};
 
355
 
 
356
static struct ieee80211_supported_band __wl_band_2ghz = {
 
357
        .band = IEEE80211_BAND_2GHZ,
 
358
        .channels = __wl_2ghz_channels,
 
359
        .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
 
360
        .bitrates = wl_g_rates,
 
361
        .n_bitrates = wl_g_rates_size,
 
362
};
 
363
 
 
364
static struct ieee80211_supported_band __wl_band_5ghz_a = {
 
365
        .band = IEEE80211_BAND_5GHZ,
 
366
        .channels = __wl_5ghz_a_channels,
 
367
        .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
 
368
        .bitrates = wl_a_rates,
 
369
        .n_bitrates = wl_a_rates_size,
 
370
};
 
371
 
 
372
static struct ieee80211_supported_band __wl_band_5ghz_n = {
 
373
        .band = IEEE80211_BAND_5GHZ,
 
374
        .channels = __wl_5ghz_n_channels,
 
375
        .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
 
376
        .bitrates = wl_a_rates,
 
377
        .n_bitrates = wl_a_rates_size,
 
378
};
 
379
 
 
380
static const u32 __wl_cipher_suites[] = {
 
381
        WLAN_CIPHER_SUITE_WEP40,
 
382
        WLAN_CIPHER_SUITE_WEP104,
 
383
        WLAN_CIPHER_SUITE_TKIP,
 
384
        WLAN_CIPHER_SUITE_CCMP,
 
385
        WLAN_CIPHER_SUITE_AES_CMAC,
 
386
};
 
387
 
 
388
static void key_endian_to_device(struct wl_wsec_key *key)
 
389
{
 
390
        key->index = htod32(key->index);
 
391
        key->len = htod32(key->len);
 
392
        key->algo = htod32(key->algo);
 
393
        key->flags = htod32(key->flags);
 
394
        key->rxiv.hi = htod32(key->rxiv.hi);
 
395
        key->rxiv.lo = htod16(key->rxiv.lo);
 
396
        key->iv_initialized = htod32(key->iv_initialized);
 
397
}
 
398
 
 
399
static void key_endian_to_host(struct wl_wsec_key *key)
 
400
{
 
401
        key->index = dtoh32(key->index);
 
402
        key->len = dtoh32(key->len);
 
403
        key->algo = dtoh32(key->algo);
 
404
        key->flags = dtoh32(key->flags);
 
405
        key->rxiv.hi = dtoh32(key->rxiv.hi);
 
406
        key->rxiv.lo = dtoh16(key->rxiv.lo);
 
407
        key->iv_initialized = dtoh32(key->iv_initialized);
 
408
}
 
409
 
 
410
static s32
 
411
wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
 
412
{
 
413
        struct ifreq ifr;
 
414
        struct wl_ioctl ioc;
 
415
        mm_segment_t fs;
 
416
        s32 err = 0;
 
417
 
 
418
        BUG_ON(len < sizeof(int));
 
419
 
 
420
        memset(&ioc, 0, sizeof(ioc));
 
421
        ioc.cmd = cmd;
 
422
        ioc.buf = arg;
 
423
        ioc.len = len;
 
424
        strcpy(ifr.ifr_name, dev->name);
 
425
        ifr.ifr_data = (caddr_t)&ioc;
 
426
 
 
427
        fs = get_fs();
 
428
        set_fs(get_ds());
 
429
#if defined(WL_USE_NETDEV_OPS)
 
430
        err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
 
431
#else
 
432
        err = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
 
433
#endif
 
434
        set_fs(fs);
 
435
 
 
436
        return err;
 
437
}
 
438
 
 
439
static s32
 
440
wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 
441
                         enum nl80211_iftype type, u32 *flags,
 
442
   struct vif_params *params)
 
443
{
 
444
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
445
        struct wireless_dev *wdev;
 
446
        s32 infra = 0;
 
447
        s32 ap = 0;
 
448
        s32 err = 0;
 
449
 
 
450
        switch (type) {
 
451
        case NL80211_IFTYPE_MONITOR:
 
452
        case NL80211_IFTYPE_WDS:
 
453
                WL_ERR(("type (%d) : currently we do not support this type\n",
 
454
                        type));
 
455
                return -EOPNOTSUPP;
 
456
        case NL80211_IFTYPE_ADHOC:
 
457
                wl->conf->mode = WL_MODE_IBSS;
 
458
                break;
 
459
        case NL80211_IFTYPE_STATION:
 
460
                wl->conf->mode = WL_MODE_BSS;
 
461
                infra = 1;
 
462
                break;
 
463
        default:
 
464
                return -EINVAL;
 
465
        }
 
466
        infra = htod32(infra);
 
467
        ap = htod32(ap);
 
468
        wdev = ndev->ieee80211_ptr;
 
469
        wdev->iftype = type;
 
470
        WL_DBG(("%s : ap (%d), infra (%d)\n", ndev->name, ap, infra));
 
471
        err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
 
472
        if (err) {
 
473
                WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
 
474
                return err;
 
475
        }
 
476
        err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
 
477
        if (err) {
 
478
                WL_ERR(("WLC_SET_AP error (%d)\n", err));
 
479
                return err;
 
480
        }
 
481
 
 
482
        return 0;
 
483
}
 
484
 
 
485
static s32
 
486
wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 
487
                 struct cfg80211_scan_request *request)
 
488
{
 
489
        struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
 
490
        struct cfg80211_ssid *ssids;
 
491
        struct wl_cfg80211_scan_req *sr = wl_to_sr(wl);
 
492
        s32 passive_scan;
 
493
        s32 err = 0;
 
494
 
 
495
        if (request) {          
 
496
                ssids = request->ssids;
 
497
        }
 
498
        else {          
 
499
 
 
500
                ssids = NULL;
 
501
        }
 
502
        wl->scan_request = request;
 
503
 
 
504
        memset(&sr->ssid, 0, sizeof(sr->ssid));
 
505
 
 
506
        if (ssids) {
 
507
                WL_DBG(("ssid \"%s\", ssid_len (%d)\n", ssids->ssid, ssids->ssid_len));
 
508
                sr->ssid.SSID_len = min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
 
509
        }
 
510
 
 
511
        if (sr->ssid.SSID_len) {
 
512
                memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
 
513
                sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
 
514
                WL_DBG(("Specific scan ssid=\"%s\" len=%d\n", sr->ssid.SSID, sr->ssid.SSID_len));
 
515
        } else {
 
516
                WL_DBG(("Broadcast scan\n"));
 
517
        }
 
518
        WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
 
519
        passive_scan = wl->active_scan ? 0 : 1;
 
520
        err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, &passive_scan, sizeof(passive_scan));
 
521
        if (err) {
 
522
                WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
 
523
                goto scan_out;
 
524
        }
 
525
        err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid, sizeof(sr->ssid));
 
526
        if (err) {
 
527
                if (err == -EBUSY) {
 
528
                        WL_INF(("system busy : scan for \"%s\" "
 
529
                                "canceled\n", sr->ssid.SSID));
 
530
                } else {
 
531
                        WL_ERR(("WLC_SCAN error (%d)\n", err));
 
532
                }
 
533
                goto scan_out;
 
534
        }
 
535
 
 
536
        return 0;
 
537
 
 
538
scan_out:
 
539
        wl->scan_request = NULL;
 
540
        return err;
 
541
}
 
542
 
 
543
static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
 
544
{
 
545
        s8 buf[WLC_IOCTL_SMLEN];
 
546
        u32 len;
 
547
        s32 err = 0;
 
548
 
 
549
        val = htod32(val);
 
550
        len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
 
551
        BUG_ON(!len);
 
552
 
 
553
        err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
 
554
        if (err) {
 
555
                WL_ERR(("error (%d)\n", err));
 
556
        }
 
557
 
 
558
        return err;
 
559
}
 
560
 
 
561
static s32
 
562
wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
 
563
{
 
564
        union {
 
565
                s8 buf[WLC_IOCTL_SMLEN];
 
566
                s32 val;
 
567
        } var;
 
568
        u32 len;
 
569
        u32 data_null;
 
570
        s32 err = 0;
 
571
 
 
572
        len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
 
573
        BUG_ON(!len);
 
574
        err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
 
575
        if (err) {
 
576
                WL_ERR(("error (%d)\n", err));
 
577
        }
 
578
        *retval = dtoh32(var.val);
 
579
 
 
580
        return err;
 
581
}
 
582
 
 
583
static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
 
584
{
 
585
        s32 err = 0;
 
586
 
 
587
        err = wl_dev_intvar_set(dev, "rtsthresh", rts_threshold);
 
588
        if (err) {
 
589
                WL_ERR(("Error (%d)\n", err));
 
590
                return err;
 
591
        }
 
592
        return err;
 
593
}
 
594
 
 
595
static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
 
596
{
 
597
        s32 err = 0;
 
598
 
 
599
        err = wl_dev_intvar_set(dev, "fragthresh", frag_threshold);
 
600
        if (err) {
 
601
                WL_ERR(("Error (%d)\n", err));
 
602
                return err;
 
603
        }
 
604
        return err;
 
605
}
 
606
 
 
607
static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
 
608
{
 
609
        s32 err = 0;
 
610
        u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
 
611
 
 
612
        retry = htod32(retry);
 
613
        err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
 
614
        if (err) {
 
615
                WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
 
616
                return err;
 
617
        }
 
618
        return err;
 
619
}
 
620
 
 
621
static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 
622
{
 
623
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
624
        struct net_device *ndev = wl_to_ndev(wl);
 
625
        s32 err = 0;
 
626
 
 
627
        if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
 
628
            (wl->conf->rts_threshold != wiphy->rts_threshold)) {
 
629
                wl->conf->rts_threshold = wiphy->rts_threshold;
 
630
                err = wl_set_rts(ndev, wl->conf->rts_threshold);
 
631
                if (!err)
 
632
                        return err;
 
633
        }
 
634
        if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
 
635
            (wl->conf->frag_threshold != wiphy->frag_threshold)) {
 
636
                wl->conf->frag_threshold = wiphy->frag_threshold;
 
637
                err = wl_set_frag(ndev, wl->conf->frag_threshold);
 
638
                if (!err)
 
639
                        return err;
 
640
        }
 
641
        if (changed & WIPHY_PARAM_RETRY_LONG && (wl->conf->retry_long != wiphy->retry_long)) {
 
642
                wl->conf->retry_long = wiphy->retry_long;
 
643
                err = wl_set_retry(ndev, wl->conf->retry_long, true);
 
644
                if (!err)
 
645
                        return err;
 
646
        }
 
647
        if (changed & WIPHY_PARAM_RETRY_SHORT && (wl->conf->retry_short != wiphy->retry_short)) {
 
648
                wl->conf->retry_short = wiphy->retry_short;
 
649
                err = wl_set_retry(ndev, wl->conf->retry_short, false);
 
650
                if (!err) {
 
651
                        return err;
 
652
                }
 
653
        }
 
654
 
 
655
        return err;
 
656
}
 
657
 
 
658
static s32
 
659
wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 
660
                      struct cfg80211_ibss_params *params)
 
661
{
 
662
        struct wl_join_params join_params;
 
663
        size_t join_params_size;
 
664
        s32 val;
 
665
        s32 err = 0;
 
666
 
 
667
        WL_DBG(("\n"));
 
668
 
 
669
        if (params->bssid) {
 
670
                WL_ERR(("Invalid bssid\n"));
 
671
                return -EOPNOTSUPP;
 
672
        }
 
673
 
 
674
        if ((err = wl_dev_intvar_set(dev, "auth", 0))) {
 
675
                return err;
 
676
        }
 
677
        if ((err = wl_dev_intvar_set(dev, "wpa_auth", WPA_AUTH_NONE))) {
 
678
                return err;
 
679
        }
 
680
        if ((err = wl_dev_intvar_get(dev, "wsec", &val))) {
 
681
                return err;
 
682
        }
 
683
        val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED);
 
684
        if ((err = wl_dev_intvar_set(dev, "wsec", val))) {
 
685
                return err;
 
686
        }
 
687
 
 
688
        memset(&join_params, 0, sizeof(join_params));
 
689
        join_params_size = sizeof(join_params.ssid);
 
690
 
 
691
        memcpy((void *)join_params.ssid.SSID, (void *)params->ssid, params->ssid_len);
 
692
        join_params.ssid.SSID_len = htod32(params->ssid_len);
 
693
        if (params->bssid)
 
694
                memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
 
695
        else
 
696
                memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
 
697
 
 
698
        wl_ch_to_chanspec(params->channel, &join_params, &join_params_size);
 
699
 
 
700
        err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
 
701
        if (err) {
 
702
                WL_ERR(("Error (%d)\n", err));
 
703
                return err;
 
704
        }
 
705
        return err;
 
706
}
 
707
 
 
708
static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 
709
{
 
710
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
711
        s32 err = 0;
 
712
 
 
713
        WL_DBG(("\n"));
 
714
 
 
715
        wl_link_down(wl);
 
716
 
 
717
        return err;
 
718
}
 
719
 
 
720
static s32
 
721
wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
 
722
{
 
723
        struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
 
724
        s32 val = 0;
 
725
        s32 err = 0;
 
726
 
 
727
        if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
 
728
                val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
 
729
        else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
 
730
                val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
 
731
        else
 
732
                val = WPA_AUTH_DISABLED;
 
733
        WL_DBG(("setting wpa_auth to 0x%0x\n", val));
 
734
        err = wl_dev_intvar_set(dev, "wpa_auth", val);
 
735
        if (err) {
 
736
                WL_ERR(("set wpa_auth failed (%d)\n", err));
 
737
                return err;
 
738
        }
 
739
        wl->profile->sec.wpa_versions = sme->crypto.wpa_versions;
 
740
        return err;
 
741
}
 
742
 
 
743
static s32
 
744
wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
 
745
{
 
746
        struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
 
747
        s32 val = 0;
 
748
        s32 err = 0;
 
749
 
 
750
        switch (sme->auth_type) {
 
751
        case NL80211_AUTHTYPE_OPEN_SYSTEM:
 
752
                val = 0;
 
753
                WL_DBG(("open system\n"));
 
754
                break;
 
755
        case NL80211_AUTHTYPE_SHARED_KEY:
 
756
                val = 1;
 
757
                WL_DBG(("shared key\n"));
 
758
                break;
 
759
        case NL80211_AUTHTYPE_AUTOMATIC:
 
760
                val = 2;
 
761
                WL_DBG(("automatic\n"));
 
762
                break;
 
763
        case NL80211_AUTHTYPE_NETWORK_EAP:
 
764
                WL_DBG(("network eap\n"));
 
765
        default:
 
766
                val = 2;
 
767
                WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
 
768
                break;
 
769
        }
 
770
 
 
771
        err = wl_dev_intvar_set(dev, "auth", val);
 
772
        if (err) {
 
773
                WL_ERR(("set auth failed (%d)\n", err));
 
774
                return err;
 
775
        }
 
776
 
 
777
        wl->profile->sec.auth_type = sme->auth_type;
 
778
        return err;
 
779
}
 
780
 
 
781
static s32
 
782
wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
 
783
{
 
784
        struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
 
785
        s32 pval = 0;
 
786
        s32 gval = 0;
 
787
        s32 val = 0;
 
788
        s32 err = 0;
 
789
 
 
790
        if (sme->crypto.n_ciphers_pairwise) {
 
791
                switch (sme->crypto.ciphers_pairwise[0]) {
 
792
                case WLAN_CIPHER_SUITE_WEP40:
 
793
                case WLAN_CIPHER_SUITE_WEP104:
 
794
                        pval = WEP_ENABLED;
 
795
                        break;
 
796
                case WLAN_CIPHER_SUITE_TKIP:
 
797
                        pval = TKIP_ENABLED;
 
798
                        break;
 
799
                case WLAN_CIPHER_SUITE_CCMP:
 
800
                        pval = AES_ENABLED;
 
801
                        break;
 
802
                case WLAN_CIPHER_SUITE_AES_CMAC:
 
803
                        pval = AES_ENABLED;
 
804
                        break;
 
805
                default:
 
806
                        WL_ERR(("invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0]));
 
807
                        return -EINVAL;
 
808
                }
 
809
        }
 
810
        if (sme->crypto.cipher_group) {
 
811
                switch (sme->crypto.cipher_group) {
 
812
                case WLAN_CIPHER_SUITE_WEP40:
 
813
                case WLAN_CIPHER_SUITE_WEP104:
 
814
                        gval = WEP_ENABLED;
 
815
                        break;
 
816
                case WLAN_CIPHER_SUITE_TKIP:
 
817
                        gval = TKIP_ENABLED;
 
818
                        break;
 
819
                case WLAN_CIPHER_SUITE_CCMP:
 
820
                        gval = AES_ENABLED;
 
821
                        break;
 
822
                case WLAN_CIPHER_SUITE_AES_CMAC:
 
823
                        gval = AES_ENABLED;
 
824
                        break;
 
825
                default:
 
826
                        WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group));
 
827
                        return -EINVAL;
 
828
                }
 
829
        }
 
830
 
 
831
        if ((err = wl_dev_intvar_get(dev, "wsec", &val))) {
 
832
                return err;
 
833
        }
 
834
        val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED);
 
835
        val |= pval | gval;
 
836
        WL_DBG(("set wsec to %d\n", val));
 
837
        err = wl_dev_intvar_set(dev, "wsec", val);
 
838
        if (err) {
 
839
                WL_ERR(("error (%d)\n", err));
 
840
                return err;
 
841
        }
 
842
 
 
843
        wl->profile->sec.cipher_pairwise = sme->crypto.ciphers_pairwise[0];
 
844
        wl->profile->sec.cipher_group = sme->crypto.cipher_group;
 
845
 
 
846
        return err;
 
847
}
 
848
 
 
849
static s32
 
850
wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
 
851
{
 
852
        struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
 
853
        s32 val = 0;
 
854
        s32 err = 0;
 
855
 
 
856
        if (sme->crypto.n_akm_suites) {
 
857
                err = wl_dev_intvar_get(dev, "wpa_auth", &val);
 
858
                if (err) {
 
859
                        WL_ERR(("could not get wpa_auth (%d)\n", err));
 
860
                        return err;
 
861
                }
 
862
                if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
 
863
                        switch (sme->crypto.akm_suites[0]) {
 
864
                        case WLAN_AKM_SUITE_8021X:
 
865
                                val = WPA_AUTH_UNSPECIFIED;
 
866
                                break;
 
867
                        case WLAN_AKM_SUITE_PSK:
 
868
                                val = WPA_AUTH_PSK;
 
869
                                break;
 
870
                        default:
 
871
                                WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group));
 
872
                                return -EINVAL;
 
873
                        }
 
874
                } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
 
875
                        switch (sme->crypto.akm_suites[0]) {
 
876
                        case WLAN_AKM_SUITE_8021X:
 
877
                                val = WPA2_AUTH_UNSPECIFIED;
 
878
                                break;
 
879
                        case WLAN_AKM_SUITE_PSK:
 
880
                                val = WPA2_AUTH_PSK;
 
881
                                break;
 
882
                        default:
 
883
                                WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group));
 
884
                                return -EINVAL;
 
885
                        }
 
886
                }
 
887
 
 
888
                WL_DBG(("setting wpa_auth to %d\n", val));
 
889
                err = wl_dev_intvar_set(dev, "wpa_auth", val);
 
890
                if (err) {
 
891
                        WL_ERR(("could not set wpa_auth (%d)\n", err));
 
892
                        return err;
 
893
                }
 
894
        }
 
895
 
 
896
        wl->profile->sec.wpa_auth = sme->crypto.akm_suites[0];
 
897
 
 
898
        return err;
 
899
}
 
900
 
 
901
static s32
 
902
wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme)
 
903
{
 
904
        struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
 
905
        struct wl_cfg80211_security *sec;
 
906
        struct wl_wsec_key key;
 
907
        s32 err = 0;
 
908
 
 
909
        WL_DBG(("key len (%d)\n", sme->key_len));
 
910
        if (sme->key_len) {
 
911
                sec = &wl->profile->sec;
 
912
                WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
 
913
                         sec->wpa_versions, sec->cipher_pairwise));
 
914
                if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) &&
 
915
                     (sec->cipher_pairwise &
 
916
                     (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104))) {
 
917
                        memset(&key, 0, sizeof(key));
 
918
                        key.len = (u32) sme->key_len;
 
919
                        key.index = (u32) sme->key_idx;
 
920
                        if (key.len > sizeof(key.data)) {
 
921
                                WL_ERR(("Too long key length (%u)\n", key.len));
 
922
                                return -EINVAL;
 
923
                        }
 
924
                        memcpy(key.data, sme->key, key.len);
 
925
                        key.flags = WL_PRIMARY_KEY;
 
926
                        switch (sec->cipher_pairwise) {
 
927
                        case WLAN_CIPHER_SUITE_WEP40:
 
928
                                key.algo = CRYPTO_ALGO_WEP1;
 
929
                                break;
 
930
                        case WLAN_CIPHER_SUITE_WEP104:
 
931
                                key.algo = CRYPTO_ALGO_WEP128;
 
932
                                break;
 
933
                        default:
 
934
                                WL_ERR(("Invalid algorithm (%d)\n",
 
935
                                        sme->crypto.ciphers_pairwise[0]));
 
936
                                return -EINVAL;
 
937
                        }
 
938
 
 
939
                        WL_DBG(("key length (%d) key index (%d) algo (%d)\n", key.len,
 
940
                                key.index, key.algo));
 
941
                        WL_DBG(("key \"%s\"\n", key.data));
 
942
                        key_endian_to_device(&key);
 
943
                        err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
 
944
                        if (err) {
 
945
                                WL_ERR(("WLC_SET_KEY error (%d)\n", err));
 
946
                                return err;
 
947
                        }
 
948
                }
 
949
        }
 
950
        return err;
 
951
}
 
952
 
 
953
static s32
 
954
wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 
955
                    struct cfg80211_connect_params *sme)
 
956
{
 
957
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
958
        struct wl_join_params join_params;
 
959
        size_t join_params_size;
 
960
        char valc;
 
961
        s32 err = 0;
 
962
 
 
963
        if (!sme->ssid) {
 
964
                WL_ERR(("Invalid ssid\n"));
 
965
                return -EOPNOTSUPP;
 
966
        }
 
967
 
 
968
        WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
 
969
 
 
970
        err = wl_set_auth_type(dev, sme);
 
971
        if (err)
 
972
                return err;
 
973
 
 
974
        err = wl_set_wpa_version(dev, sme);
 
975
        if (err)
 
976
                return err;
 
977
 
 
978
        err = wl_set_set_cipher(dev, sme);
 
979
        if (err)
 
980
                return err;
 
981
 
 
982
        err = wl_set_key_mgmt(dev, sme);
 
983
        if (err)
 
984
                return err;
 
985
 
 
986
        err = wl_set_set_sharedkey(dev, sme);
 
987
        if (err)
 
988
                return err;
 
989
 
 
990
        valc = 1;
 
991
        wl_dev_bufvar_set(dev, "wsec_restrict", &valc, 1);
 
992
 
 
993
        if (sme->bssid) {
 
994
                memcpy(wl->profile->bssid, sme->bssid, ETHER_ADDR_LEN);
 
995
        }
 
996
        else {
 
997
                memset(wl->profile->bssid, 0, ETHER_ADDR_LEN);
 
998
        }
 
999
 
 
1000
        memset(&join_params, 0, sizeof(join_params));
 
1001
        join_params_size = sizeof(join_params.ssid);
 
1002
 
 
1003
        join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
 
1004
        memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
 
1005
        join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
 
1006
        memcpy(&join_params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
 
1007
 
 
1008
        memcpy(wl->profile->ssid.SSID, &join_params.ssid.SSID, join_params.ssid.SSID_len);
 
1009
        wl->profile->ssid.SSID_len = join_params.ssid.SSID_len;
 
1010
 
 
1011
        wl_ch_to_chanspec(sme->channel, &join_params, &join_params_size);
 
1012
        WL_DBG(("join_param_size %u\n", (unsigned int)join_params_size));
 
1013
 
 
1014
        if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
 
1015
                WL_DBG(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
 
1016
                        join_params.ssid.SSID_len));
 
1017
        }
 
1018
        err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
 
1019
        if (err) {
 
1020
                WL_ERR(("error (%d)\n", err));
 
1021
                return err;
 
1022
        }
 
1023
 
 
1024
        set_bit(WL_STATUS_CONNECTING, &wl->status);
 
1025
 
 
1026
        return err;
 
1027
}
 
1028
 
 
1029
static s32
 
1030
wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code)
 
1031
{
 
1032
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
1033
        scb_val_t scbval;
 
1034
        s32 err = 0;
 
1035
 
 
1036
        WL_DBG(("Reason %d\n", reason_code));
 
1037
 
 
1038
        if (wl->profile->active) {
 
1039
                scbval.val = reason_code;
 
1040
                memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN);
 
1041
                scbval.val = htod32(scbval.val);
 
1042
                err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
 
1043
                if (err) {
 
1044
                        WL_ERR(("error (%d)\n", err));
 
1045
                        return err;
 
1046
                }
 
1047
        }
 
1048
 
 
1049
        return err;
 
1050
}
 
1051
 
 
1052
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
 
1053
static s32
 
1054
wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, s32 dbm)
 
1055
#else
 
1056
#define NL80211_TX_POWER_AUTOMATIC TX_POWER_AUTOMATIC
 
1057
#define NL80211_TX_POWER_LIMITED TX_POWER_LIMITED
 
1058
#define NL80211_TX_POWER_FIXED TX_POWER_FIXED
 
1059
static s32
 
1060
wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, s32 dbm)
 
1061
#endif
 
1062
{
 
1063
 
 
1064
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
1065
        struct net_device *ndev = wl_to_ndev(wl);
 
1066
        u16 txpwrmw;
 
1067
        s32 err = 0;
 
1068
        s32 disable = 0;
 
1069
 
 
1070
        switch (type) {
 
1071
        case NL80211_TX_POWER_AUTOMATIC:
 
1072
                break;
 
1073
        case NL80211_TX_POWER_LIMITED:
 
1074
                if (dbm < 0) {
 
1075
                        WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
 
1076
                        return -EINVAL;
 
1077
                }
 
1078
                break;
 
1079
        case NL80211_TX_POWER_FIXED:
 
1080
                if (dbm < 0) {
 
1081
                        WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
 
1082
                        return -EINVAL;
 
1083
                }
 
1084
                break;
 
1085
        }
 
1086
 
 
1087
        disable = WL_RADIO_SW_DISABLE << 16;
 
1088
        disable = htod32(disable);
 
1089
        err = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable));
 
1090
        if (err) {
 
1091
                WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
 
1092
                return err;
 
1093
        }
 
1094
 
 
1095
        if (dbm > 0xffff)
 
1096
                txpwrmw = 0xffff;
 
1097
        else
 
1098
                txpwrmw = (u16) dbm;
 
1099
        err = wl_dev_intvar_set(ndev, "qtxpower", (s32) (bcm_mw_to_qdbm(txpwrmw)));
 
1100
        if (err) {
 
1101
                WL_ERR(("qtxpower error (%d)\n", err));
 
1102
                return err;
 
1103
        }
 
1104
        wl->conf->tx_power = dbm;
 
1105
 
 
1106
        return err;
 
1107
}
 
1108
 
 
1109
static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
 
1110
{
 
1111
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
1112
        struct net_device *ndev = wl_to_ndev(wl);
 
1113
        s32 txpwrdbm;
 
1114
        u8 result;
 
1115
        s32 err = 0;
 
1116
 
 
1117
        err = wl_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
 
1118
        if (err) {
 
1119
                WL_ERR(("error (%d)\n", err));
 
1120
                return err;
 
1121
        }
 
1122
        result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
 
1123
        *dbm = (s32) bcm_qdbm_to_mw(result);
 
1124
 
 
1125
        return err;
 
1126
}
 
1127
 
 
1128
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
 
1129
static s32
 
1130
wl_cfg80211_config_default_key(struct wiphy *wiphy,
 
1131
        struct net_device *dev, u8 key_idx, bool unicast, bool multicast)
 
1132
#else
 
1133
static s32
 
1134
wl_cfg80211_config_default_key(struct wiphy *wiphy,
 
1135
        struct net_device *dev, u8 key_idx)
 
1136
#endif
 
1137
{
 
1138
        u32 index;
 
1139
        s32 err = 0;
 
1140
 
 
1141
        WL_DBG(("key index (%d)\n", key_idx));
 
1142
 
 
1143
        index = (u32) key_idx;
 
1144
        index = htod32(index);
 
1145
        err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index, sizeof(index));
 
1146
        if (err) {
 
1147
                WL_DBG(("error (%d)\n", err));
 
1148
        }
 
1149
 
 
1150
        return 0;
 
1151
}
 
1152
 
 
1153
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
 
1154
static s32
 
1155
wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 
1156
                    u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params)
 
1157
#else
 
1158
static s32
 
1159
wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 
1160
                    u8 key_idx, const u8 *mac_addr, struct key_params *params)
 
1161
#endif
 
1162
{
 
1163
        struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
 
1164
        struct wl_wsec_key key;
 
1165
        s32 secval, secnew = 0;
 
1166
        s32 err = 0;
 
1167
 
 
1168
        WL_DBG(("key index %u    len %u\n", (unsigned)key_idx, params->key_len));
 
1169
 
 
1170
        memset(&key, 0, sizeof(key));
 
1171
 
 
1172
        key.index = (u32) key_idx;
 
1173
 
 
1174
        switch (params->cipher) {
 
1175
        case WLAN_CIPHER_SUITE_WEP40:
 
1176
                key.algo = CRYPTO_ALGO_WEP1;
 
1177
                secnew = WEP_ENABLED;
 
1178
                WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
 
1179
                break;
 
1180
        case WLAN_CIPHER_SUITE_WEP104:
 
1181
                key.algo = CRYPTO_ALGO_WEP128;
 
1182
                secnew = WEP_ENABLED;
 
1183
                WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
 
1184
                break;
 
1185
        case WLAN_CIPHER_SUITE_TKIP:
 
1186
                key.algo = CRYPTO_ALGO_TKIP;
 
1187
                secnew = TKIP_ENABLED;
 
1188
                WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
 
1189
                break;
 
1190
        case WLAN_CIPHER_SUITE_AES_CMAC:
 
1191
                key.algo = CRYPTO_ALGO_AES_CCM;
 
1192
                secnew = AES_ENABLED;
 
1193
                WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
 
1194
                break;
 
1195
        case WLAN_CIPHER_SUITE_CCMP:
 
1196
                key.algo = CRYPTO_ALGO_AES_CCM;
 
1197
                secnew = AES_ENABLED;
 
1198
                WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
 
1199
                break;
 
1200
        default:
 
1201
                WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
 
1202
                return -EINVAL;
 
1203
        }
 
1204
 
 
1205
        if (mac_addr) {
 
1206
                if (!ETHER_ISMULTI(mac_addr)) {
 
1207
                        memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
 
1208
                }
 
1209
        }
 
1210
 
 
1211
        key.len = (u32) params->key_len;
 
1212
        if (key.len > sizeof(key.data)) {
 
1213
                WL_ERR(("Too long key length (%u)\n", key.len));
 
1214
                return -EINVAL;
 
1215
        }
 
1216
        memcpy(key.data, params->key, key.len);
 
1217
 
 
1218
        if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
 
1219
                u8 keybuf[8];
 
1220
                memcpy(keybuf, &key.data[24], sizeof(keybuf));
 
1221
                memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
 
1222
                memcpy(&key.data[16], keybuf, sizeof(keybuf));
 
1223
        }
 
1224
 
 
1225
        if (params->seq_len) { 
 
1226
                u8 *ivptr;
 
1227
                if (params->seq_len != 6) {
 
1228
                        WL_ERR(("seq_len %d is unexpected, check implementation.\n",
 
1229
                                params->seq_len));
 
1230
                }
 
1231
                ivptr = (u8 *) params->seq;
 
1232
                key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | (ivptr[3] << 8) | ivptr[2];
 
1233
                key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
 
1234
                key.iv_initialized = true;
 
1235
        }
 
1236
 
 
1237
        key_endian_to_device(&key);
 
1238
        err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
 
1239
        if (err) {
 
1240
                WL_ERR(("WLC_SET_KEY error (%d)\n", err));
 
1241
                return err;
 
1242
        }
 
1243
 
 
1244
        if ((err = wl_dev_intvar_get(dev, "wsec", &secval))) {
 
1245
                return err;
 
1246
        }
 
1247
        if (secnew == WEP_ENABLED) {
 
1248
                secval &= ~(TKIP_ENABLED | AES_ENABLED);
 
1249
        }
 
1250
        else {
 
1251
                secval &= ~(WEP_ENABLED);
 
1252
        }
 
1253
        secval |= secnew;
 
1254
        WL_DBG(("set wsec to %d\n", secval));
 
1255
        err = wl_dev_intvar_set(dev, "wsec", secval);
 
1256
        if (err) {
 
1257
                WL_ERR(("error (%d)\n", err));
 
1258
                return err;
 
1259
        }
 
1260
 
 
1261
        if (mac_addr) {
 
1262
                wl->profile->sec.cipher_pairwise = params->cipher;
 
1263
        }
 
1264
        else {
 
1265
                wl->profile->sec.cipher_group = params->cipher;
 
1266
        }
 
1267
 
 
1268
        return err;
 
1269
}
 
1270
 
 
1271
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
 
1272
static s32
 
1273
wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 
1274
                    u8 key_idx, bool pairwise, const u8 *mac_addr)
 
1275
#else
 
1276
static s32
 
1277
wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 
1278
                    u8 key_idx, const u8 *mac_addr)
 
1279
#endif
 
1280
{
 
1281
        struct wl_wsec_key key;
 
1282
        s32 err = 0;
 
1283
 
 
1284
        WL_DBG(("key index (%d)\n", key_idx));
 
1285
 
 
1286
        memset(&key, 0, sizeof(key));
 
1287
 
 
1288
        key.index = (u32) key_idx;
 
1289
        key.len = 0;
 
1290
        if (mac_addr) {
 
1291
                if (!ETHER_ISMULTI(mac_addr)) {
 
1292
                        memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
 
1293
                }
 
1294
        }
 
1295
        key.algo = CRYPTO_ALGO_OFF;
 
1296
 
 
1297
        key_endian_to_device(&key);
 
1298
        err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
 
1299
        if (err) {
 
1300
                if (err == -EINVAL) {
 
1301
                        if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
 
1302
 
 
1303
                                WL_DBG(("invalid key index (%d)\n", key_idx));
 
1304
                        }
 
1305
                } else {
 
1306
                        WL_ERR(("WLC_SET_KEY error (%d)\n", err));
 
1307
                }
 
1308
                return err;
 
1309
        }
 
1310
 
 
1311
        return err;
 
1312
}
 
1313
 
 
1314
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
 
1315
static s32
 
1316
wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 
1317
                    u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
 
1318
                    void (*callback) (void *cookie, struct key_params * params))
 
1319
#else
 
1320
static s32
 
1321
wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 
1322
                    u8 key_idx, const u8 *mac_addr, void *cookie,
 
1323
                    void (*callback) (void *cookie, struct key_params * params))
 
1324
#endif
 
1325
{
 
1326
        struct key_params params;
 
1327
        struct wl_wsec_key key;
 
1328
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
1329
        struct wl_cfg80211_security *sec;
 
1330
        s32 wsec;
 
1331
        s32 err = 0;
 
1332
 
 
1333
        WL_DBG(("key index (%d)\n", key_idx));
 
1334
 
 
1335
        memset(&params, 0, sizeof(params));
 
1336
 
 
1337
        memset(&key, 0, sizeof(key));
 
1338
        key.index = key_idx;
 
1339
        key_endian_to_device(&key);
 
1340
 
 
1341
        if ((err = wl_dev_ioctl(dev, WLC_GET_KEY, &key, sizeof(key)))) {
 
1342
                return err;
 
1343
        }
 
1344
        key_endian_to_host(&key);
 
1345
 
 
1346
        params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
 
1347
        memcpy(params.key, key.data, params.key_len);
 
1348
 
 
1349
        if ((err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec)))) {
 
1350
                return err;
 
1351
        }
 
1352
        wsec = dtoh32(wsec);
 
1353
        switch (wsec) {
 
1354
        case WEP_ENABLED:
 
1355
                sec = &wl->profile->sec;
 
1356
                if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
 
1357
                        params.cipher = WLAN_CIPHER_SUITE_WEP40;
 
1358
                        WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
 
1359
                } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
 
1360
                        params.cipher = WLAN_CIPHER_SUITE_WEP104;
 
1361
                        WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
 
1362
                }
 
1363
                break;
 
1364
        case TKIP_ENABLED:
 
1365
                params.cipher = WLAN_CIPHER_SUITE_TKIP;
 
1366
                WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
 
1367
                break;
 
1368
        case AES_ENABLED:
 
1369
                params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
 
1370
                WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
 
1371
                break;
 
1372
        default:
 
1373
                WL_ERR(("Invalid algo (0x%x)\n", wsec));
 
1374
                return -EINVAL;
 
1375
        }
 
1376
 
 
1377
        callback(cookie, &params);
 
1378
        return err;
 
1379
}
 
1380
 
 
1381
static s32
 
1382
wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 
1383
                        u8 *mac, struct station_info *sinfo)
 
1384
{
 
1385
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
1386
        scb_val_t scb_val;
 
1387
        int rssi;
 
1388
        s32 rate;
 
1389
        s32 err = 0;
 
1390
 
 
1391
        if (memcmp(mac, wl->profile->bssid, ETHER_ADDR_LEN)) {
 
1392
                WL_ERR(("Wrong Mac address\n"));
 
1393
                return -ENOENT;
 
1394
        }
 
1395
 
 
1396
        err = wl_dev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate));
 
1397
        if (err) {
 
1398
                WL_DBG(("Could not get rate (%d)\n", err));
 
1399
        } else {
 
1400
                rate = dtoh32(rate);
 
1401
                sinfo->filled |= STATION_INFO_TX_BITRATE;
 
1402
                sinfo->txrate.legacy = rate * 5;
 
1403
                WL_DBG(("Rate %d Mbps\n", (rate / 2)));
 
1404
        }
 
1405
 
 
1406
        if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
 
1407
                memset(&scb_val, 0, sizeof(scb_val));
 
1408
                err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
 
1409
                if (err) {
 
1410
                        WL_DBG(("Could not get rssi (%d)\n", err));
 
1411
                        return err;
 
1412
                }
 
1413
                rssi = dtoh32(scb_val.val);
 
1414
                sinfo->filled |= STATION_INFO_SIGNAL;
 
1415
                sinfo->signal = rssi;
 
1416
                WL_DBG(("RSSI %d dBm\n", rssi));
 
1417
        }
 
1418
 
 
1419
        return err;
 
1420
}
 
1421
 
 
1422
static s32
 
1423
wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 
1424
                           bool enabled, s32 timeout)
 
1425
{
 
1426
        s32 pm;
 
1427
        s32 err = 0;
 
1428
 
 
1429
        pm = enabled ? PM_FAST : PM_OFF;
 
1430
        pm = htod32(pm);
 
1431
        WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
 
1432
        err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
 
1433
        if (err) {
 
1434
                if (err == -ENODEV)
 
1435
                        WL_DBG(("net_device is not ready yet\n"));
 
1436
                else
 
1437
                        WL_ERR(("error (%d)\n", err));
 
1438
                return err;
 
1439
        }
 
1440
        return err;
 
1441
}
 
1442
 
 
1443
static __used s32
 
1444
wl_update_pmklist(struct net_device *dev, struct wl_cfg80211_pmk_list *pmk_list, s32 err)
 
1445
{
 
1446
        int i, j;
 
1447
 
 
1448
        WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
 
1449
        for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
 
1450
                WL_DBG(("PMKID[%d]: %pM =\n", i,
 
1451
                        &pmk_list->pmkids.pmkid[i].BSSID));
 
1452
                for (j = 0; j < WPA2_PMKID_LEN; j++) {
 
1453
                        WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
 
1454
                }
 
1455
        }
 
1456
        if (!err) {
 
1457
                err = wl_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list, sizeof(*pmk_list));
 
1458
        }
 
1459
 
 
1460
        return err;
 
1461
}
 
1462
 
 
1463
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
 
1464
 
 
1465
static s32
 
1466
wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
 
1467
                      struct cfg80211_pmksa *pmksa)
 
1468
{
 
1469
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
1470
        s32 err = 0;
 
1471
        int i;
 
1472
 
 
1473
        for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
 
1474
                if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ETHER_ADDR_LEN))
 
1475
                        break;
 
1476
        if (i < WL_NUM_PMKIDS_MAX) {
 
1477
                memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
 
1478
                memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
 
1479
                if (i == wl->pmk_list->pmkids.npmkid)
 
1480
                        wl->pmk_list->pmkids.npmkid++;
 
1481
        } else {
 
1482
                err = -EINVAL;
 
1483
        }
 
1484
        WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
 
1485
                &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID));
 
1486
        for (i = 0; i < WPA2_PMKID_LEN; i++) {
 
1487
                WL_DBG(("%02x\n",
 
1488
                        wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].PMKID[i]));
 
1489
        }
 
1490
 
 
1491
        err = wl_update_pmklist(dev, wl->pmk_list, err);
 
1492
 
 
1493
        return err;
 
1494
}
 
1495
 
 
1496
static s32
 
1497
wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
 
1498
                      struct cfg80211_pmksa *pmksa)
 
1499
{
 
1500
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
1501
        struct _pmkid_list pmkid;
 
1502
        s32 err = 0;
 
1503
        int i;
 
1504
 
 
1505
        memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
 
1506
        memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
 
1507
 
 
1508
        WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
 
1509
                &pmkid.pmkid[0].BSSID));
 
1510
        for (i = 0; i < WPA2_PMKID_LEN; i++) {
 
1511
                WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
 
1512
        }
 
1513
 
 
1514
        for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
 
1515
                if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ETHER_ADDR_LEN))
 
1516
                        break;
 
1517
 
 
1518
        if ((wl->pmk_list->pmkids.npmkid > 0) && (i < wl->pmk_list->pmkids.npmkid)) {
 
1519
                memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
 
1520
                for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
 
1521
                        memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
 
1522
                               &wl->pmk_list->pmkids.pmkid[i + 1].BSSID, ETHER_ADDR_LEN);
 
1523
                        memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
 
1524
                               &wl->pmk_list->pmkids.pmkid[i + 1].PMKID, WPA2_PMKID_LEN);
 
1525
                }
 
1526
                wl->pmk_list->pmkids.npmkid--;
 
1527
        } else {
 
1528
                err = -EINVAL;
 
1529
        }
 
1530
 
 
1531
        err = wl_update_pmklist(dev, wl->pmk_list, err);
 
1532
 
 
1533
        return err;
 
1534
 
 
1535
}
 
1536
 
 
1537
static s32
 
1538
wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
 
1539
{
 
1540
        struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
 
1541
        s32 err = 0;
 
1542
 
 
1543
        memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
 
1544
        err = wl_update_pmklist(dev, wl->pmk_list, err);
 
1545
        return err;
 
1546
 
 
1547
}
 
1548
 
 
1549
#endif  
 
1550
 
 
1551
static struct cfg80211_ops wl_cfg80211_ops = {
 
1552
        .change_virtual_intf = wl_cfg80211_change_iface,
 
1553
        .scan = wl_cfg80211_scan,
 
1554
        .set_wiphy_params = wl_cfg80211_set_wiphy_params,
 
1555
        .join_ibss = wl_cfg80211_join_ibss,
 
1556
        .leave_ibss = wl_cfg80211_leave_ibss,
 
1557
        .get_station = wl_cfg80211_get_station,
 
1558
        .set_tx_power = wl_cfg80211_set_tx_power,
 
1559
        .get_tx_power = wl_cfg80211_get_tx_power,
 
1560
        .add_key = wl_cfg80211_add_key,
 
1561
        .del_key = wl_cfg80211_del_key,
 
1562
        .get_key = wl_cfg80211_get_key,
 
1563
        .set_default_key = wl_cfg80211_config_default_key,
 
1564
        .set_power_mgmt = wl_cfg80211_set_power_mgmt,
 
1565
        .connect = wl_cfg80211_connect,
 
1566
        .disconnect = wl_cfg80211_disconnect,
 
1567
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
 
1568
        .set_pmksa = wl_cfg80211_set_pmksa,
 
1569
        .del_pmksa = wl_cfg80211_del_pmksa,
 
1570
        .flush_pmksa = wl_cfg80211_flush_pmksa
 
1571
#endif
 
1572
};
 
1573
 
 
1574
static s32 wl_mode_to_nl80211_iftype(s32 mode)
 
1575
{
 
1576
        s32 err = 0;
 
1577
 
 
1578
        switch (mode) {
 
1579
        case WL_MODE_BSS:
 
1580
                return NL80211_IFTYPE_STATION;
 
1581
        case WL_MODE_IBSS:
 
1582
                return NL80211_IFTYPE_ADHOC;
 
1583
        default:
 
1584
                return NL80211_IFTYPE_UNSPECIFIED;
 
1585
        }
 
1586
 
 
1587
        return err;
 
1588
}
 
1589
 
 
1590
static s32 wl_alloc_wdev(struct device *dev, struct wireless_dev **rwdev)
 
1591
{
 
1592
        struct wireless_dev *wdev;
 
1593
        s32 err = 0;
 
1594
 
 
1595
        wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
 
1596
        if (!wdev) {
 
1597
                WL_ERR(("Could not allocate wireless device\n"));
 
1598
                err = -ENOMEM;
 
1599
                goto early_out;
 
1600
        }
 
1601
        wdev->wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_cfg80211_priv));
 
1602
        if (!wdev->wiphy) {
 
1603
                WL_ERR(("Couldn not allocate wiphy device\n"));
 
1604
                err = -ENOMEM;
 
1605
                goto wiphy_new_out;
 
1606
        }
 
1607
        set_wiphy_dev(wdev->wiphy, dev);
 
1608
        wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
 
1609
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
 
1610
        wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
 
1611
#endif
 
1612
        wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
 
1613
        wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
 
1614
        wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; 
 
1615
        wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
 
1616
        wdev->wiphy->cipher_suites = __wl_cipher_suites;
 
1617
        wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
 
1618
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
 
1619
 
 
1620
        wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
1621
#endif
 
1622
        err = wiphy_register(wdev->wiphy);
 
1623
        if (err < 0) {
 
1624
                WL_ERR(("Couldn not register wiphy device (%d)\n", err));
 
1625
                goto wiphy_register_out;
 
1626
        }
 
1627
 
 
1628
        *rwdev = wdev;
 
1629
        return err;
 
1630
 
 
1631
wiphy_register_out:
 
1632
        wiphy_free(wdev->wiphy);
 
1633
 
 
1634
wiphy_new_out:
 
1635
        kfree(wdev);
 
1636
 
 
1637
early_out:
 
1638
        *rwdev = wdev;
 
1639
        return err;
 
1640
}
 
1641
 
 
1642
static void wl_free_wdev(struct wl_cfg80211_priv *wl)
 
1643
{
 
1644
        struct wireless_dev *wdev = wl_to_wdev(wl);
 
1645
 
 
1646
        if (!wdev) {
 
1647
                WL_ERR(("wdev is invalid\n"));
 
1648
                return;
 
1649
        }
 
1650
        wiphy_unregister(wdev->wiphy);
 
1651
        wiphy_free(wdev->wiphy);
 
1652
        kfree(wdev);
 
1653
        wl_to_wdev(wl) = NULL;
 
1654
}
 
1655
 
 
1656
static s32 wl_inform_bss(struct wl_cfg80211_priv *wl, struct wl_scan_results *bss_list)
 
1657
{
 
1658
        struct wl_bss_info *bi = NULL;  
 
1659
        s32 err = 0;
 
1660
        int i;
 
1661
 
 
1662
        if (bss_list->version != WL_BSS_INFO_VERSION) {
 
1663
                WL_ERR(("Version %d != WL_BSS_INFO_VERSION\n", bss_list->version));
 
1664
                return -EOPNOTSUPP;
 
1665
        }
 
1666
        WL_DBG(("scanned AP count (%d)\n", bss_list->count));
 
1667
        bi = next_bss(bss_list, bi);
 
1668
        for_each_bss(bss_list, bi, i) {
 
1669
                err = wl_inform_single_bss(wl, bi);
 
1670
                if (err)
 
1671
                        break;
 
1672
        }
 
1673
        return err;
 
1674
}
 
1675
 
 
1676
static s32 wl_inform_single_bss(struct wl_cfg80211_priv *wl, struct wl_bss_info *bi)
 
1677
{
 
1678
        struct wiphy *wiphy = wl_to_wiphy(wl);
 
1679
        struct ieee80211_mgmt *mgmt;
 
1680
        struct ieee80211_channel *channel;
 
1681
        struct wl_cfg80211_bss_info *notif_bss_info;
 
1682
        struct wl_cfg80211_scan_req *sr = wl_to_sr(wl);
 
1683
        struct beacon_proberesp *beacon_proberesp;
 
1684
        s32 mgmt_type;
 
1685
        u32 signal;
 
1686
        u32 freq;
 
1687
        s32 err = 0;
 
1688
 
 
1689
        if (dtoh32(bi->length) > WL_BSS_INFO_MAX) {
 
1690
                WL_DBG(("Beacon is larger than buffer. Discarding\n"));
 
1691
                return err;
 
1692
        }
 
1693
        notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(u8) +
 
1694
                                 WL_BSS_INFO_MAX, GFP_KERNEL);
 
1695
        if (!notif_bss_info) {
 
1696
                WL_ERR(("notif_bss_info alloc failed\n"));
 
1697
                return -ENOMEM;
 
1698
        }
 
1699
        mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
 
1700
        notif_bss_info->channel = bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(bi->chanspec);
 
1701
 
 
1702
        notif_bss_info->rssi = bi->RSSI;
 
1703
        memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
 
1704
        mgmt_type = wl->active_scan ?   IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
 
1705
        if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
 
1706
                mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
 
1707
        }
 
1708
        beacon_proberesp = wl->active_scan ? (struct beacon_proberesp *)&mgmt->u.probe_resp :
 
1709
                           (struct beacon_proberesp *)&mgmt->u.beacon;
 
1710
        beacon_proberesp->timestamp = 0;
 
1711
        beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
 
1712
        beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
 
1713
        wl_rst_ie(wl);
 
1714
 
 
1715
        wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
 
1716
        wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
 
1717
                 offsetof(struct wl_cfg80211_bss_info, frame_buf));
 
1718
        notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, u.beacon.variable) +
 
1719
                                    wl_get_ielen(wl);
 
1720
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
 
1721
        freq = ieee80211_channel_to_frequency(notif_bss_info->channel,
 
1722
                (notif_bss_info->channel <= CH_MAX_2G_CHANNEL) ?
 
1723
                IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ);
 
1724
#else
 
1725
        freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
 
1726
#endif
 
1727
        channel = ieee80211_get_channel(wiphy, freq);
 
1728
 
 
1729
        WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
 
1730
                bi->SSID, notif_bss_info->rssi, notif_bss_info->channel,
 
1731
                mgmt->u.beacon.capab_info, &bi->BSSID));
 
1732
 
 
1733
        signal = notif_bss_info->rssi * 100;
 
1734
        if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
 
1735
            le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL)) {
 
1736
                WL_ERR(("cfg80211_inform_bss_frame error\n"));
 
1737
                kfree(notif_bss_info);
 
1738
                return -EINVAL;
 
1739
        }
 
1740
        kfree(notif_bss_info);
 
1741
 
 
1742
        return err;
 
1743
}
 
1744
 
 
1745
static s32
 
1746
wl_notify_connect_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
1747
                         const wl_event_msg_t *e, void *data)
 
1748
{
 
1749
        s32 err = 0;
 
1750
        u32 event = EVENT_TYPE(e);
 
1751
        u16 flags = EVENT_FLAGS(e);
 
1752
        u32 status = EVENT_STATUS(e);
 
1753
 
 
1754
        WL_DBG(("\n"));
 
1755
 
 
1756
        if (!wl_is_ibssmode(wl)) {
 
1757
                if (event == WLC_E_LINK && (flags & WLC_EVENT_MSG_LINK)) {
 
1758
                        wl_link_up(wl);
 
1759
                        wl_bss_connect_done(wl, ndev, e, data, true);
 
1760
                        wl->profile->active = true;
 
1761
                }
 
1762
                else if ((event == WLC_E_LINK && ~(flags & WLC_EVENT_MSG_LINK)) ||
 
1763
                        event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
 
1764
                        cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
 
1765
                        clear_bit(WL_STATUS_CONNECTED, &wl->status);
 
1766
                        wl_link_down(wl);
 
1767
                        wl_init_prof(wl->profile);
 
1768
                }
 
1769
                else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
 
1770
                        wl_bss_connect_done(wl, ndev, e, data, false);
 
1771
                }
 
1772
                else {
 
1773
                        WL_DBG(("no action (BSS mode)\n"));
 
1774
                }
 
1775
        }
 
1776
        else {
 
1777
                if (event == WLC_E_JOIN) {
 
1778
                        WL_DBG(("joined in IBSS network\n"));
 
1779
                }
 
1780
                if (event == WLC_E_START) {
 
1781
                        WL_DBG(("started IBSS network\n"));
 
1782
                }
 
1783
                if (event == WLC_E_JOIN || event == WLC_E_START) {
 
1784
                        wl_link_up(wl);
 
1785
                        wl_get_assoc_ies(wl);
 
1786
                        memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
 
1787
                        wl_update_bss_info(wl);
 
1788
                        cfg80211_ibss_joined(ndev, (u8 *)&wl->bssid, GFP_KERNEL);
 
1789
                        set_bit(WL_STATUS_CONNECTED, &wl->status);
 
1790
                        wl->profile->active = true;
 
1791
                }
 
1792
                else if ((event == WLC_E_LINK && ~(flags & WLC_EVENT_MSG_LINK)) ||
 
1793
                        event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
 
1794
                        clear_bit(WL_STATUS_CONNECTED, &wl->status);
 
1795
                        wl_link_down(wl);
 
1796
                        wl_init_prof(wl->profile);
 
1797
                }
 
1798
                else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
 
1799
                        WL_DBG(("no action - join fail (IBSS mode)\n"));
 
1800
                }
 
1801
                else {
 
1802
                        WL_DBG(("no action (IBSS mode)\n"));
 
1803
                }
 
1804
        }
 
1805
 
 
1806
        return err;
 
1807
}
 
1808
 
 
1809
static s32
 
1810
wl_notify_roaming_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
1811
                         const wl_event_msg_t *e, void *data)
 
1812
{
 
1813
        s32 err = 0;
 
1814
        u32 status = EVENT_STATUS(e);
 
1815
 
 
1816
        WL_DBG(("\n"));
 
1817
 
 
1818
        if (status == WLC_E_STATUS_SUCCESS) {
 
1819
                err = wl_bss_roaming_done(wl, ndev, e, data);
 
1820
                wl->profile->active = true;
 
1821
        }
 
1822
 
 
1823
        return err;
 
1824
}
 
1825
 
 
1826
static __used s32
 
1827
wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
 
1828
{
 
1829
        struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
 
1830
        u32 buflen;
 
1831
 
 
1832
        buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
 
1833
        BUG_ON(!buflen);
 
1834
 
 
1835
        return wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen);
 
1836
}
 
1837
 
 
1838
static s32
 
1839
wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf, s32 buf_len)
 
1840
{
 
1841
        struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
 
1842
        u32 len;
 
1843
        s32 err = 0;
 
1844
 
 
1845
        len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
 
1846
        BUG_ON(!len);
 
1847
        err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf, WL_IOCTL_LEN_MAX);
 
1848
        if (err) {
 
1849
                WL_ERR(("error (%d)\n", err));
 
1850
                return err;
 
1851
        }
 
1852
        memcpy(buf, wl->ioctl_buf, buf_len);
 
1853
 
 
1854
        return err;
 
1855
}
 
1856
 
 
1857
static s32 wl_get_assoc_ies(struct wl_cfg80211_priv *wl)
 
1858
{
 
1859
        struct net_device *ndev = wl_to_ndev(wl);
 
1860
        struct wl_cfg80211_assoc_ielen *assoc_info;
 
1861
        struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
 
1862
        u32 req_len;
 
1863
        u32 resp_len;
 
1864
        s32 err = 0;
 
1865
 
 
1866
        err = wl_dev_bufvar_get(ndev, "assoc_info", wl->extra_buf, WL_ASSOC_INFO_MAX);
 
1867
        if (err) {
 
1868
                WL_ERR(("could not get assoc info (%d)\n", err));
 
1869
                return err;
 
1870
        }
 
1871
        assoc_info = (struct wl_cfg80211_assoc_ielen *)wl->extra_buf;
 
1872
        req_len = assoc_info->req_len;
 
1873
        resp_len = assoc_info->resp_len;
 
1874
        if (req_len) {
 
1875
                err = wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf, WL_ASSOC_INFO_MAX);
 
1876
                if (err) {
 
1877
                        WL_ERR(("could not get assoc req (%d)\n", err));
 
1878
                        return err;
 
1879
                }
 
1880
                conn_info->req_ie_len = req_len;
 
1881
                conn_info->req_ie =
 
1882
                    kmemdup(wl->extra_buf, conn_info->req_ie_len, GFP_KERNEL);
 
1883
        } else {
 
1884
                conn_info->req_ie_len = 0;
 
1885
                conn_info->req_ie = NULL;
 
1886
        }
 
1887
        if (resp_len) {
 
1888
                err = wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf, WL_ASSOC_INFO_MAX);
 
1889
                if (err) {
 
1890
                        WL_ERR(("could not get assoc resp (%d)\n", err));
 
1891
                        return err;
 
1892
                }
 
1893
                conn_info->resp_ie_len = resp_len;
 
1894
                conn_info->resp_ie =
 
1895
                    kmemdup(wl->extra_buf, conn_info->resp_ie_len, GFP_KERNEL);
 
1896
        } else {
 
1897
                conn_info->resp_ie_len = 0;
 
1898
                conn_info->resp_ie = NULL;
 
1899
        }
 
1900
        WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
 
1901
                conn_info->resp_ie_len));
 
1902
 
 
1903
        return err;
 
1904
}
 
1905
 
 
1906
static void wl_ch_to_chanspec(struct ieee80211_channel *chan, struct wl_join_params *join_params,
 
1907
        size_t *join_params_size)
 
1908
{
 
1909
        chanspec_t chanspec = 0;
 
1910
 
 
1911
        if (chan) {
 
1912
                join_params->params.chanspec_num = 1;
 
1913
                join_params->params.chanspec_list[0] =
 
1914
                    ieee80211_frequency_to_channel(chan->center_freq);
 
1915
 
 
1916
                if (chan->band == IEEE80211_BAND_2GHZ) {
 
1917
                        chanspec |= WL_CHANSPEC_BAND_2G;
 
1918
                }
 
1919
                else if (chan->band == IEEE80211_BAND_5GHZ) {
 
1920
                        chanspec |= WL_CHANSPEC_BAND_5G;
 
1921
                }
 
1922
                else {
 
1923
                        WL_ERR(("Unknown band\n"));
 
1924
                        BUG();
 
1925
                }
 
1926
 
 
1927
                chanspec |= WL_CHANSPEC_BW_20;
 
1928
 
 
1929
                *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
 
1930
                        join_params->params.chanspec_num * sizeof(chanspec_t);
 
1931
 
 
1932
                join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
 
1933
                join_params->params.chanspec_list[0] |= chanspec;
 
1934
                join_params->params.chanspec_list[0] =
 
1935
                    htodchanspec(join_params->params.chanspec_list[0]);
 
1936
 
 
1937
                join_params->params.chanspec_num = htod32(join_params->params.chanspec_num);
 
1938
 
 
1939
                WL_DBG(("join_params->params.chanspec_list[0]= %#X, channel %d, chanspec %#X\n",
 
1940
                        join_params->params.chanspec_list[0],
 
1941
                        join_params->params.chanspec_list[0], chanspec));
 
1942
        }
 
1943
}
 
1944
 
 
1945
static s32 wl_update_bss_info(struct wl_cfg80211_priv *wl)
 
1946
{
 
1947
        struct cfg80211_bss *bss;
 
1948
        struct wl_bss_info *bi;
 
1949
        struct wlc_ssid *ssid;
 
1950
        struct bcm_tlv *tim;
 
1951
        s32 dtim_period;
 
1952
        size_t ie_len;
 
1953
        u8 *ie;
 
1954
        s32 err = 0;
 
1955
 
 
1956
        ssid = &wl->profile->ssid;
 
1957
        bss = cfg80211_get_bss(wl_to_wiphy(wl), NULL, (s8 *)&wl->bssid,
 
1958
              ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
 
1959
 
 
1960
        rtnl_lock();
 
1961
        if (!bss) {
 
1962
                WL_DBG(("Could not find the AP\n"));
 
1963
                *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
 
1964
                err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO, wl->extra_buf,
 
1965
                                   WL_EXTRA_BUF_MAX);
 
1966
                if (err) {
 
1967
                        WL_ERR(("Could not get bss info %d\n", err));
 
1968
                        goto update_bss_info_out;
 
1969
                }
 
1970
                bi = (struct wl_bss_info *)(wl->extra_buf + 4);
 
1971
                if (memcmp(&bi->BSSID, &wl->bssid, ETHER_ADDR_LEN)) {
 
1972
                        err = -EIO;
 
1973
                        goto update_bss_info_out;
 
1974
                }
 
1975
                err = wl_inform_single_bss(wl, bi);
 
1976
                if (err)
 
1977
                        goto update_bss_info_out;
 
1978
 
 
1979
                ie = ((u8 *)bi) + bi->ie_offset;
 
1980
                ie_len = bi->ie_length;
 
1981
        } else {
 
1982
                WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
 
1983
                ie = bss->information_elements;
 
1984
                ie_len = bss->len_information_elements;
 
1985
                cfg80211_put_bss(bss);
 
1986
        }
 
1987
 
 
1988
        tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
 
1989
        if (tim) {
 
1990
                dtim_period = tim->data[1];
 
1991
        } else {
 
1992
 
 
1993
                err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_DTIMPRD,
 
1994
                        &dtim_period, sizeof(dtim_period));
 
1995
                if (err) {
 
1996
                        WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
 
1997
                        goto update_bss_info_out;
 
1998
                }
 
1999
        }
 
2000
 
 
2001
update_bss_info_out:
 
2002
        rtnl_unlock();
 
2003
        return err;
 
2004
}
 
2005
 
 
2006
static s32
 
2007
wl_bss_roaming_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
2008
                    const wl_event_msg_t *e, void *data)
 
2009
{
 
2010
        struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
 
2011
        s32 err = 0;
 
2012
 
 
2013
        wl_get_assoc_ies(wl);
 
2014
        memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
 
2015
        wl_update_bss_info(wl);
 
2016
        cfg80211_roamed(ndev,
 
2017
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)
 
2018
                        NULL,    
 
2019
#endif
 
2020
                        (u8 *)&wl->bssid,
 
2021
                        conn_info->req_ie, conn_info->req_ie_len,
 
2022
                        conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
 
2023
        WL_DBG(("Report roaming result\n"));
 
2024
 
 
2025
        set_bit(WL_STATUS_CONNECTED, &wl->status);
 
2026
 
 
2027
        return err;
 
2028
}
 
2029
 
 
2030
static s32
 
2031
wl_bss_connect_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
2032
                    const wl_event_msg_t *e, void *data, bool completed)
 
2033
{
 
2034
        struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
 
2035
        s32 err = 0;
 
2036
 
 
2037
        wl_get_assoc_ies(wl);
 
2038
        memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
 
2039
        wl_update_bss_info(wl);
 
2040
 
 
2041
        WL_DBG(("Reporting BSS network join result \"%s\"\n", wl->profile->ssid.SSID));
 
2042
        if (test_and_clear_bit(WL_STATUS_CONNECTING, &wl->status)) {
 
2043
                cfg80211_connect_result(ndev, (u8 *)&wl->bssid, conn_info->req_ie,
 
2044
                    conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len,
 
2045
                    completed ? WLAN_STATUS_SUCCESS : WLAN_STATUS_AUTH_TIMEOUT, GFP_KERNEL);
 
2046
                WL_DBG(("connection %s\n", completed ? "succeeded" : "failed"));
 
2047
        }
 
2048
        else {
 
2049
                cfg80211_roamed(ndev,
 
2050
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)
 
2051
                        NULL, 
 
2052
#endif
 
2053
                     (u8 *)&wl->bssid,  conn_info->req_ie, conn_info->req_ie_len,
 
2054
                     conn_info->resp_ie, conn_info->resp_ie_len,        GFP_KERNEL);
 
2055
                WL_DBG(("roaming result\n"));
 
2056
        }
 
2057
        set_bit(WL_STATUS_CONNECTED, &wl->status);
 
2058
 
 
2059
        return err;
 
2060
}
 
2061
 
 
2062
static s32
 
2063
wl_notify_mic_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
2064
                     const wl_event_msg_t *e, void *data)
 
2065
{
 
2066
        u16 flags = EVENT_FLAGS(e);
 
2067
        enum nl80211_key_type key_type;
 
2068
 
 
2069
        WL_DBG(("\n"));
 
2070
 
 
2071
        rtnl_lock();
 
2072
        if (flags & WLC_EVENT_MSG_GROUP)
 
2073
                key_type = NL80211_KEYTYPE_GROUP;
 
2074
        else
 
2075
                key_type = NL80211_KEYTYPE_PAIRWISE;
 
2076
 
 
2077
        cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1, NULL, GFP_KERNEL);
 
2078
        rtnl_unlock();
 
2079
 
 
2080
        return 0;
 
2081
}
 
2082
 
 
2083
static s32
 
2084
wl_notify_scan_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
 
2085
                      const wl_event_msg_t *e, void *data)
 
2086
{
 
2087
        struct channel_info channel_inform;
 
2088
        struct wl_scan_results *bss_list;
 
2089
        u32 buflen;
 
2090
        s32 err = 0;
 
2091
 
 
2092
        WL_DBG(("\n"));
 
2093
 
 
2094
        rtnl_lock();
 
2095
        err = wl_dev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform, sizeof(channel_inform));
 
2096
        if (err) {
 
2097
                WL_ERR(("scan busy (%d)\n", err));
 
2098
                goto scan_done_out;
 
2099
        }
 
2100
        channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
 
2101
        if (channel_inform.scan_channel) {
 
2102
 
 
2103
                WL_DBG(("channel_inform.scan_channel (%d)\n",   channel_inform.scan_channel));
 
2104
        }
 
2105
 
 
2106
        for (buflen = WL_SCAN_BUF_BASE; ; ) {
 
2107
                bss_list = (struct wl_scan_results *) kmalloc(buflen, GFP_KERNEL);
 
2108
                if (!bss_list) {
 
2109
                        WL_ERR(("%s Out of memory for scan results, (%d)\n", ndev->name, err));
 
2110
                        goto scan_done_out;
 
2111
                }
 
2112
                memset(bss_list, 0, buflen);
 
2113
                bss_list->buflen = htod32(buflen);
 
2114
                err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, buflen);
 
2115
                if (!err) {
 
2116
                        break;
 
2117
                }
 
2118
                else if (err == -E2BIG) {
 
2119
                        kfree(bss_list);
 
2120
                        buflen *= 2;
 
2121
                }
 
2122
                else {
 
2123
                        WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
 
2124
                        kfree(bss_list);
 
2125
                        err = -EINVAL;
 
2126
                        goto scan_done_out;
 
2127
                }
 
2128
        }
 
2129
 
 
2130
        bss_list->buflen = dtoh32(bss_list->buflen);
 
2131
        bss_list->version = dtoh32(bss_list->version);
 
2132
        bss_list->count = dtoh32(bss_list->count);
 
2133
 
 
2134
        err = wl_inform_bss(wl, bss_list);
 
2135
        kfree(bss_list);
 
2136
 
 
2137
scan_done_out:
 
2138
        if (wl->scan_request) {
 
2139
                cfg80211_scan_done(wl->scan_request, false);
 
2140
                wl->scan_request = NULL;
 
2141
        }
 
2142
        rtnl_unlock();
 
2143
        return err;
 
2144
}
 
2145
 
 
2146
static void wl_init_conf(struct wl_cfg80211_conf *conf)
 
2147
{
 
2148
        conf->mode = (u32)-1;
 
2149
        conf->frag_threshold = (u32)-1;
 
2150
        conf->rts_threshold = (u32)-1;
 
2151
        conf->retry_short = (u32)-1;
 
2152
        conf->retry_long = (u32)-1;
 
2153
        conf->tx_power = -1;
 
2154
}
 
2155
 
 
2156
static void wl_init_prof(struct wl_cfg80211_profile *prof)
 
2157
{
 
2158
        memset(prof, 0, sizeof(*prof));
 
2159
}
 
2160
 
 
2161
static void wl_init_eloop_handler(struct wl_cfg80211_event_loop *el)
 
2162
{
 
2163
        memset(el, 0, sizeof(*el));
 
2164
        el->handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
 
2165
        el->handler[WLC_E_JOIN] = wl_notify_connect_status;
 
2166
        el->handler[WLC_E_START] = wl_notify_connect_status;
 
2167
        el->handler[WLC_E_LINK] = wl_notify_connect_status;
 
2168
        el->handler[WLC_E_NDIS_LINK] = wl_notify_connect_status;
 
2169
        el->handler[WLC_E_SET_SSID] = wl_notify_connect_status;
 
2170
        el->handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
 
2171
        el->handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
 
2172
        el->handler[WLC_E_ROAM] = wl_notify_roaming_status;
 
2173
        el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
 
2174
}
 
2175
 
 
2176
static s32 wl_init_priv_mem(struct wl_cfg80211_priv *wl)
 
2177
{
 
2178
        wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
 
2179
        if (!wl->conf) {
 
2180
                WL_ERR(("wl_cfg80211_conf alloc failed\n"));
 
2181
                goto init_priv_mem_out;
 
2182
        }
 
2183
        wl->profile = (void *)kzalloc(sizeof(*wl->profile), GFP_KERNEL);
 
2184
        if (!wl->profile) {
 
2185
                WL_ERR(("wl_cfg80211_profile alloc failed\n"));
 
2186
                goto init_priv_mem_out;
 
2187
        }
 
2188
        wl->scan_req_int = (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
 
2189
        if (!wl->scan_req_int) {
 
2190
                WL_ERR(("Scan req alloc failed\n"));
 
2191
                goto init_priv_mem_out;
 
2192
        }
 
2193
        wl->ioctl_buf = (void *)kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
 
2194
        if (!wl->ioctl_buf) {
 
2195
                WL_ERR(("Ioctl buf alloc failed\n"));
 
2196
                goto init_priv_mem_out;
 
2197
        }
 
2198
        wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
 
2199
        if (!wl->extra_buf) {
 
2200
                WL_ERR(("Extra buf alloc failed\n"));
 
2201
                goto init_priv_mem_out;
 
2202
        }
 
2203
 
 
2204
        wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
 
2205
        if (!wl->pmk_list) {
 
2206
                WL_ERR(("pmk list alloc failed\n"));
 
2207
                goto init_priv_mem_out;
 
2208
        }
 
2209
 
 
2210
        return 0;
 
2211
 
 
2212
init_priv_mem_out:
 
2213
        wl_deinit_priv_mem(wl);
 
2214
 
 
2215
        return -ENOMEM;
 
2216
}
 
2217
 
 
2218
static void wl_deinit_priv_mem(struct wl_cfg80211_priv *wl)
 
2219
{
 
2220
        kfree(wl->conf);
 
2221
        wl->conf = NULL;
 
2222
        kfree(wl->profile);
 
2223
        wl->profile = NULL;
 
2224
        kfree(wl->scan_req_int);
 
2225
        wl->scan_req_int = NULL;
 
2226
        kfree(wl->ioctl_buf);
 
2227
        wl->ioctl_buf = NULL;
 
2228
        kfree(wl->extra_buf);
 
2229
        wl->extra_buf = NULL;
 
2230
        kfree(wl->pmk_list);
 
2231
        wl->pmk_list = NULL;
 
2232
}
 
2233
 
 
2234
static s32 wl_create_event_handler(struct wl_cfg80211_priv *wl)
 
2235
{
 
2236
        sema_init(&wl->event_sync, 0);
 
2237
        wl->event_tsk = kthread_run(wl_event_handler, wl, "wl_event_handler");
 
2238
        if (IS_ERR(wl->event_tsk)) {
 
2239
                wl->event_tsk = NULL;
 
2240
                WL_ERR(("failed to create event thread\n"));
 
2241
                return -ENOMEM;
 
2242
        }
 
2243
        return 0;
 
2244
}
 
2245
 
 
2246
static void wl_destroy_event_handler(struct wl_cfg80211_priv *wl)
 
2247
{
 
2248
        if (wl->event_tsk) {
 
2249
                send_sig(SIGTERM, wl->event_tsk, 1);
 
2250
                kthread_stop(wl->event_tsk);
 
2251
                wl->event_tsk = NULL;
 
2252
        }
 
2253
}
 
2254
 
 
2255
static s32 wl_init_cfg80211_priv(struct wl_cfg80211_priv *wl, struct wireless_dev *wdev)
 
2256
{
 
2257
        s32 err = 0;
 
2258
 
 
2259
        wl->wdev = wdev;
 
2260
 
 
2261
        wl->scan_request = NULL;
 
2262
        wl->active_scan = true;
 
2263
        wl_init_eq(wl);
 
2264
        err = wl_init_priv_mem(wl);
 
2265
        if (err)
 
2266
                return err;
 
2267
 
 
2268
        if (wl_create_event_handler(wl))
 
2269
                return -ENOMEM;
 
2270
 
 
2271
        wl_init_eloop_handler(&wl->el);
 
2272
 
 
2273
        if (err)
 
2274
                return err;
 
2275
 
 
2276
        wl_init_conf(wl->conf);
 
2277
        wl_init_prof(wl->profile);
 
2278
        wl_link_down(wl);
 
2279
 
 
2280
        return err;
 
2281
}
 
2282
 
 
2283
static void wl_deinit_cfg80211_priv(struct wl_cfg80211_priv *wl)
 
2284
{
 
2285
        wl_destroy_event_handler(wl);
 
2286
        wl_flush_eq(wl);
 
2287
        wl_link_down(wl);
 
2288
        wl_deinit_priv_mem(wl);
 
2289
}
 
2290
 
 
2291
s32 wl_cfg80211_attach(struct net_device *ndev, struct device *dev)
 
2292
{
 
2293
        struct wireless_dev *wdev;
 
2294
        struct wl_cfg80211_priv *wl;
 
2295
        s32 err = 0;
 
2296
 
 
2297
        if (!ndev) {
 
2298
                WL_ERR(("ndev is invaild\n"));
 
2299
                return -ENODEV;
 
2300
        }
 
2301
 
 
2302
        err = wl_alloc_wdev(dev, &wdev);
 
2303
        if (err < 0) {
 
2304
                return err;
 
2305
        }
 
2306
 
 
2307
        wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
 
2308
        wl = wdev_to_wl(wdev);
 
2309
        ndev->ieee80211_ptr = wdev;
 
2310
        SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
 
2311
        wdev->netdev = ndev;
 
2312
        err = wl_init_cfg80211_priv(wl, wdev);
 
2313
        if (err) {
 
2314
                WL_ERR(("Failed to init iwm_priv (%d)\n", err));
 
2315
                goto cfg80211_attach_out;
 
2316
        }
 
2317
 
 
2318
        if (!err) {
 
2319
                WL_INF(("Registered CFG80211 phy\n"));
 
2320
        }
 
2321
        return err;
 
2322
 
 
2323
cfg80211_attach_out:
 
2324
        wl_free_wdev(wl);
 
2325
        return err;
 
2326
}
 
2327
 
 
2328
void wl_cfg80211_detach(struct net_device *ndev)
 
2329
{
 
2330
        struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
 
2331
 
 
2332
        wl_deinit_cfg80211_priv(wl);
 
2333
        wl_free_wdev(wl);
 
2334
}
 
2335
 
 
2336
static void wl_wakeup_event(struct wl_cfg80211_priv *wl)
 
2337
{
 
2338
        up(&wl->event_sync);
 
2339
}
 
2340
 
 
2341
static s32 wl_event_handler(void *data)
 
2342
{
 
2343
        struct wl_cfg80211_priv *wl = (struct wl_cfg80211_priv *)data;
 
2344
        struct wl_cfg80211_event_q *e;
 
2345
 
 
2346
        allow_signal(SIGTERM);
 
2347
        while (!down_interruptible(&wl->event_sync)) {
 
2348
                if (kthread_should_stop())
 
2349
                        break;
 
2350
                e = wl_deq_event(wl);
 
2351
                if (!e) {
 
2352
                        WL_ERR(("eqeue empty..\n"));
 
2353
                        BUG();
 
2354
                }
 
2355
                WL_DBG(("event type (%d)\n", e->etype));
 
2356
                if (wl->el.handler[e->etype]) {
 
2357
                        wl->el.handler[e->etype] (wl, wl_to_ndev(wl), &e->emsg, e->edata);
 
2358
                } else {
 
2359
                        WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
 
2360
                }
 
2361
                wl_put_event(e);
 
2362
        }
 
2363
        WL_DBG(("%s was terminated\n", __func__));
 
2364
        return 0;
 
2365
}
 
2366
 
 
2367
void
 
2368
wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
 
2369
{
 
2370
 
 
2371
        u32 event_type = EVENT_TYPE(e);
 
2372
 
 
2373
        struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
 
2374
#if defined(WL_DBGMSG_ENABLE)
 
2375
        s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
 
2376
            wl_dbg_estr[event_type] : (s8 *) "Unknown";
 
2377
        WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
 
2378
#endif                          
 
2379
        if (!wl_enq_event(wl, event_type, e, data))
 
2380
                wl_wakeup_event(wl);
 
2381
}
 
2382
 
 
2383
static void wl_init_eq(struct wl_cfg80211_priv *wl)
 
2384
{
 
2385
        wl_init_eq_lock(wl);
 
2386
        INIT_LIST_HEAD(&wl->eq_list);
 
2387
}
 
2388
 
 
2389
static void wl_flush_eq(struct wl_cfg80211_priv *wl)
 
2390
{
 
2391
        struct wl_cfg80211_event_q *e;
 
2392
 
 
2393
        wl_lock_eq(wl);
 
2394
        while (!list_empty(&wl->eq_list)) {
 
2395
                e = list_first_entry(&wl->eq_list, struct wl_cfg80211_event_q, eq_list);
 
2396
                list_del(&e->eq_list);
 
2397
                kfree(e);
 
2398
        }
 
2399
        wl_unlock_eq(wl);
 
2400
}
 
2401
 
 
2402
static struct wl_cfg80211_event_q *wl_deq_event(struct wl_cfg80211_priv *wl)
 
2403
{
 
2404
        struct wl_cfg80211_event_q *e = NULL;
 
2405
 
 
2406
        wl_lock_eq(wl);
 
2407
        if (!list_empty(&wl->eq_list)) {
 
2408
                e = list_first_entry(&wl->eq_list, struct wl_cfg80211_event_q, eq_list);
 
2409
                list_del(&e->eq_list);
 
2410
        }
 
2411
        wl_unlock_eq(wl);
 
2412
 
 
2413
        return e;
 
2414
}
 
2415
 
 
2416
static s32
 
2417
wl_enq_event(struct wl_cfg80211_priv *wl, u32 event, const wl_event_msg_t *msg, void *data)
 
2418
{
 
2419
        struct wl_cfg80211_event_q *e;
 
2420
        s32 err = 0;
 
2421
 
 
2422
        e = kzalloc(sizeof(struct wl_cfg80211_event_q), GFP_ATOMIC);
 
2423
        if (!e) {
 
2424
                WL_ERR(("event alloc failed\n"));
 
2425
                return -ENOMEM;
 
2426
        }
 
2427
 
 
2428
        e->etype = event;
 
2429
        memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
 
2430
        if (data) {
 
2431
        }
 
2432
 
 
2433
        spin_lock(&wl->eq_lock);
 
2434
        list_add_tail(&e->eq_list, &wl->eq_list);
 
2435
        spin_unlock(&wl->eq_lock);
 
2436
 
 
2437
        return err;
 
2438
}
 
2439
 
 
2440
static void wl_put_event(struct wl_cfg80211_event_q *e)
 
2441
{
 
2442
        kfree(e);
 
2443
}
 
2444
 
 
2445
static s32 wl_set_mode(struct net_device *ndev, s32 iftype)
 
2446
{
 
2447
        s32 infra = 0;
 
2448
        s32 ap = 0;
 
2449
        s32 err = 0;
 
2450
 
 
2451
        switch (iftype) {
 
2452
        case NL80211_IFTYPE_MONITOR:
 
2453
        case NL80211_IFTYPE_WDS:
 
2454
                WL_ERR(("type (%d) : currently we do not support this mode\n",
 
2455
                        iftype));
 
2456
                err = -EINVAL;
 
2457
                return err;
 
2458
        case NL80211_IFTYPE_ADHOC:
 
2459
                break;
 
2460
        case NL80211_IFTYPE_STATION:
 
2461
                infra = 1;
 
2462
                break;
 
2463
        default:
 
2464
                err = -EINVAL;
 
2465
                WL_ERR(("invalid type (%d)\n", iftype));
 
2466
                return err;
 
2467
        }
 
2468
        infra = htod32(infra);
 
2469
        ap = htod32(ap);
 
2470
        WL_DBG(("%s ap (%d), infra (%d)\n", ndev->name, ap, infra));
 
2471
        err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
 
2472
        if (err) {
 
2473
                WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
 
2474
                return err;
 
2475
        }
 
2476
        err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
 
2477
        if (err) {
 
2478
                WL_ERR(("WLC_SET_AP error (%d)\n", err));
 
2479
                return err;
 
2480
        }
 
2481
 
 
2482
        return 0;
 
2483
}
 
2484
 
 
2485
static s32 wl_update_wiphybands(struct wl_cfg80211_priv *wl)
 
2486
{
 
2487
        struct wiphy *wiphy;
 
2488
        s32 phy_list;
 
2489
        s8 phy;
 
2490
        s32 err = 0;
 
2491
 
 
2492
        err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_PHYLIST, &phy_list, sizeof(phy_list));
 
2493
        if (err) {
 
2494
                WL_ERR(("error (%d)\n", err));
 
2495
                return err;
 
2496
        }
 
2497
 
 
2498
        phy = ((char *)&phy_list)[0];
 
2499
        WL_DBG(("%c phy\n", phy));
 
2500
 
 
2501
        if (phy == 'n' || phy == 'a') {
 
2502
                wiphy = wl_to_wiphy(wl);
 
2503
                wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
 
2504
        }
 
2505
 
 
2506
        return err;
 
2507
}
 
2508
 
 
2509
s32 wl_cfg80211_up(struct net_device *ndev)
 
2510
{
 
2511
        struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
 
2512
        s32 err = 0;
 
2513
        struct wireless_dev *wdev = ndev->ieee80211_ptr;
 
2514
 
 
2515
        wl_set_mode(ndev, wdev->iftype);
 
2516
 
 
2517
        err = wl_update_wiphybands(wl);
 
2518
 
 
2519
        return err;
 
2520
}
 
2521
 
 
2522
s32 wl_cfg80211_down(struct net_device *ndev)
 
2523
{
 
2524
        struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
 
2525
        s32 err = 0;
 
2526
 
 
2527
        if (wl->scan_request) {
 
2528
                cfg80211_scan_done(wl->scan_request, true);     
 
2529
                wl->scan_request = NULL;
 
2530
        }
 
2531
 
 
2532
        return err;
 
2533
}
 
2534
 
 
2535
static bool wl_is_ibssmode(struct wl_cfg80211_priv *wl)
 
2536
{
 
2537
        return wl->conf->mode == WL_MODE_IBSS;
 
2538
}
 
2539
 
 
2540
static void wl_rst_ie(struct wl_cfg80211_priv *wl)
 
2541
{
 
2542
        struct wl_cfg80211_ie *ie = wl_to_ie(wl);
 
2543
 
 
2544
        ie->offset = 0;
 
2545
}
 
2546
 
 
2547
static __used s32 wl_add_ie(struct wl_cfg80211_priv *wl, u8 t, u8 l, u8 *v)
 
2548
{
 
2549
        struct wl_cfg80211_ie *ie = wl_to_ie(wl);
 
2550
        s32 err = 0;
 
2551
 
 
2552
        if (ie->offset + l + 2 > WL_TLV_INFO_MAX) {
 
2553
                WL_ERR(("ei crosses buffer boundary\n"));
 
2554
                return -ENOSPC;
 
2555
        }
 
2556
        ie->buf[ie->offset] = t;
 
2557
        ie->buf[ie->offset + 1] = l;
 
2558
        memcpy(&ie->buf[ie->offset + 2], v, l);
 
2559
        ie->offset += l + 2;
 
2560
 
 
2561
        return err;
 
2562
}
 
2563
 
 
2564
static s32 wl_mrg_ie(struct wl_cfg80211_priv *wl, u8 *ie_stream, u16 ie_size)
 
2565
{
 
2566
        struct wl_cfg80211_ie *ie = wl_to_ie(wl);
 
2567
        s32 err = 0;
 
2568
 
 
2569
        if (ie->offset + ie_size > WL_TLV_INFO_MAX) {
 
2570
                WL_ERR(("ei_stream crosses buffer boundary\n"));
 
2571
                return -ENOSPC;
 
2572
        }
 
2573
        memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
 
2574
        ie->offset += ie_size;
 
2575
 
 
2576
        return err;
 
2577
}
 
2578
 
 
2579
static s32 wl_cp_ie(struct wl_cfg80211_priv *wl, u8 *dst, u16 dst_size)
 
2580
{
 
2581
        struct wl_cfg80211_ie *ie = wl_to_ie(wl);
 
2582
        s32 err = 0;
 
2583
 
 
2584
        if (ie->offset > dst_size) {
 
2585
                WL_ERR(("dst_size is not enough\n"));
 
2586
                return -ENOSPC;
 
2587
        }
 
2588
        memcpy(dst, &ie->buf[0], ie->offset);
 
2589
 
 
2590
        return err;
 
2591
}
 
2592
 
 
2593
static u32 wl_get_ielen(struct wl_cfg80211_priv *wl)
 
2594
{
 
2595
        struct wl_cfg80211_ie *ie = wl_to_ie(wl);
 
2596
 
 
2597
        return ie->offset;
 
2598
}
 
2599
 
 
2600
static void wl_link_up(struct wl_cfg80211_priv *wl)
 
2601
{
 
2602
        WL_DBG(("\n"));
 
2603
}
 
2604
 
 
2605
static void wl_link_down(struct wl_cfg80211_priv *wl)
 
2606
{
 
2607
        struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
 
2608
 
 
2609
        WL_DBG(("\n"));
 
2610
 
 
2611
        kfree(conn_info->req_ie);
 
2612
        conn_info->req_ie = NULL;
 
2613
        conn_info->req_ie_len = 0;
 
2614
        kfree(conn_info->resp_ie);
 
2615
        conn_info->resp_ie = NULL;
 
2616
        conn_info->resp_ie_len = 0;
 
2617
}
 
2618
 
 
2619
static void wl_lock_eq(struct wl_cfg80211_priv *wl)
 
2620
{
 
2621
        spin_lock_irq(&wl->eq_lock);
 
2622
}
 
2623
 
 
2624
static void wl_unlock_eq(struct wl_cfg80211_priv *wl)
 
2625
{
 
2626
        spin_unlock_irq(&wl->eq_lock);
 
2627
}
 
2628
 
 
2629
static void wl_init_eq_lock(struct wl_cfg80211_priv *wl)
 
2630
{
 
2631
        spin_lock_init(&wl->eq_lock);
 
2632
}
 
2633
 
 
2634
#endif