aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/bcmdhd/wldev_common.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/net/wireless/bcmdhd/wldev_common.c
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/net/wireless/bcmdhd/wldev_common.c')
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.c341
1 files changed, 341 insertions, 0 deletions
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c
new file mode 100644
index 00000000000..bb3eaea90d0
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wldev_common.c
@@ -0,0 +1,341 @@
1/*
2 * Common function shared by Linux WEXT, cfg80211 and p2p drivers
3 *
4 * Copyright (C) 1999-2011, Broadcom Corporation
5 *
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
11 *
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
19 *
20 * Notwithstanding the above, under no circumstances may you combine this
21 * software in any way with any other Broadcom software provided under a license
22 * other than the GPL, without Broadcom's express prior written consent.
23 *
24 * $Id: wldev_common.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 $
25 */
26
27#include <linux/module.h>
28#include <linux/netdevice.h>
29
30#include <wldev_common.h>
31#include <bcmutils.h>
32#include <dhd_dbg.h>
33
34#define htod32(i) i
35#define htod16(i) i
36#define dtoh32(i) i
37#define dtoh16(i) i
38#define htodchanspec(i) i
39#define dtohchanspec(i) i
40extern int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd);
41
42s32 wldev_ioctl(
43 struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set)
44{
45 s32 ret = 0;
46 struct wl_ioctl ioc;
47
48 memset(&ioc, 0, sizeof(ioc));
49 ioc.cmd = cmd;
50 ioc.buf = arg;
51 ioc.len = len;
52 ioc.set = set;
53
54 ret = dhd_ioctl_entry_local(dev, &ioc, cmd);
55 return ret;
56}
57
58/* Format a iovar buffer, not bsscfg indexed. The bsscfg index will be
59 * taken care of in dhd_ioctl_entry. Internal use only, not exposed to
60 * wl_iw, wl_cfg80211 and wl_cfgp2p
61 */
62static s32 wldev_mkiovar(
63 s8 *iovar_name, s8 *param, s32 paramlen,
64 s8 *iovar_buf, u32 buflen)
65{
66 s32 iolen = 0;
67
68 iolen = bcm_mkiovar(iovar_name, param, paramlen, iovar_buf, buflen);
69 return iolen;
70}
71
72s32 wldev_iovar_getbuf(
73 struct net_device *dev, s8 *iovar_name,
74 void *param, s32 paramlen, void *buf, s32 buflen)
75{
76 s32 ret = 0;
77 s32 iovar_len = 0;
78
79 iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen);
80 ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE);
81 return ret;
82}
83
84
85s32 wldev_iovar_setbuf(
86 struct net_device *dev, s8 *iovar_name,
87 void *param, s32 paramlen, void *buf, s32 buflen)
88{
89 s32 ret = 0;
90 s32 iovar_len;
91
92 iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen);
93 ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
94 return ret;
95}
96
97s32 wldev_iovar_setint(
98 struct net_device *dev, s8 *iovar, s32 val)
99{
100 s8 iovar_buf[WLC_IOCTL_SMLEN];
101
102 val = htod32(val);
103 memset(iovar_buf, 0, sizeof(iovar_buf));
104 return wldev_iovar_setbuf(dev, iovar, &val, sizeof(val), iovar_buf,
105 sizeof(iovar_buf));
106}
107
108
109s32 wldev_iovar_getint(
110 struct net_device *dev, s8 *iovar, s32 *pval)
111{
112 s8 iovar_buf[WLC_IOCTL_SMLEN];
113 s32 err;
114
115 memset(iovar_buf, 0, sizeof(iovar_buf));
116 err = wldev_iovar_getbuf(dev, iovar, pval, sizeof(*pval), iovar_buf,
117 sizeof(iovar_buf));
118 if (err == 0)
119 {
120 memcpy(pval, iovar_buf, sizeof(*pval));
121 *pval = dtoh32(*pval);
122 }
123 return err;
124}
125
126/** Format a bsscfg indexed iovar buffer. The bsscfg index will be
127 * taken care of in dhd_ioctl_entry. Internal use only, not exposed to
128 * wl_iw, wl_cfg80211 and wl_cfgp2p
129 */
130s32 wldev_mkiovar_bsscfg(
131 const s8 *iovar_name, s8 *param, s32 paramlen,
132 s8 *iovar_buf, s32 buflen, s32 bssidx)
133{
134 const s8 *prefix = "bsscfg:";
135 s8 *p;
136 u32 prefixlen;
137 u32 namelen;
138 u32 iolen;
139
140 if (bssidx == 0) {
141 return wldev_mkiovar((s8*)iovar_name, (s8 *)param, paramlen,
142 (s8 *) iovar_buf, buflen);
143 }
144
145 prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */
146 namelen = (u32) strlen(iovar_name) + 1; /* lengh of iovar name + null */
147 iolen = prefixlen + namelen + sizeof(u32) + paramlen;
148
149 if (buflen < 0 || iolen > (u32)buflen)
150 {
151 DHD_ERROR(("%s: buffer is too short\n", __FUNCTION__));
152 return BCME_BUFTOOSHORT;
153 }
154
155 p = (s8 *)iovar_buf;
156
157 /* copy prefix, no null */
158 memcpy(p, prefix, prefixlen);
159 p += prefixlen;
160
161 /* copy iovar name including null */
162 memcpy(p, iovar_name, namelen);
163 p += namelen;
164
165 /* bss config index as first param */
166 bssidx = htod32(bssidx);
167 memcpy(p, &bssidx, sizeof(u32));
168 p += sizeof(u32);
169
170 /* parameter buffer follows */
171 if (paramlen)
172 memcpy(p, param, paramlen);
173
174 return iolen;
175
176}
177
178s32 wldev_iovar_getbuf_bsscfg(
179 struct net_device *dev, s8 *iovar_name,
180 void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx)
181{
182 s32 ret = 0;
183 s32 iovar_len = 0;
184
185 iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx);
186 ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE);
187 return ret;
188
189}
190
191s32 wldev_iovar_setbuf_bsscfg(
192 struct net_device *dev, s8 *iovar_name,
193 void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx)
194{
195 s32 ret = 0;
196 s32 iovar_len;
197
198 iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx);
199 ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
200 return ret;
201}
202
203s32 wldev_iovar_setint_bsscfg(
204 struct net_device *dev, s8 *iovar, s32 val, s32 bssidx)
205{
206 s8 iovar_buf[WLC_IOCTL_SMLEN];
207
208 val = htod32(val);
209 memset(iovar_buf, 0, sizeof(iovar_buf));
210 return wldev_iovar_setbuf_bsscfg(dev, iovar, &val, sizeof(val), iovar_buf,
211 sizeof(iovar_buf), bssidx);
212}
213
214
215s32 wldev_iovar_getint_bsscfg(
216 struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx)
217{
218 s8 iovar_buf[WLC_IOCTL_SMLEN];
219 s32 err;
220
221 memset(iovar_buf, 0, sizeof(iovar_buf));
222 err = wldev_iovar_getbuf_bsscfg(dev, iovar, pval, sizeof(*pval), iovar_buf,
223 sizeof(iovar_buf), bssidx);
224 if (err == 0)
225 {
226 memcpy(pval, iovar_buf, sizeof(*pval));
227 *pval = dtoh32(*pval);
228 }
229 return err;
230}
231
232int wldev_get_link_speed(
233 struct net_device *dev, int *plink_speed)
234{
235 int error;
236
237 if (!plink_speed)
238 return -ENOMEM;
239 error = wldev_ioctl(dev, WLC_GET_RATE, plink_speed, sizeof(int), 0);
240 if (unlikely(error))
241 return error;
242
243 /* Convert internal 500Kbps to Kbps */
244 *plink_speed *= 500;
245 return error;
246}
247
248int wldev_get_rssi(
249 struct net_device *dev, int *prssi)
250{
251 scb_val_t scb_val;
252 int error;
253
254 if (!prssi)
255 return -ENOMEM;
256 bzero(&scb_val, sizeof(scb_val_t));
257
258 error = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t), 0);
259 if (unlikely(error))
260 return error;
261
262 *prssi = dtoh32(scb_val.val);
263 return error;
264}
265
266int wldev_get_ssid(
267 struct net_device *dev, wlc_ssid_t *pssid)
268{
269 int error;
270
271 if (!pssid)
272 return -ENOMEM;
273 error = wldev_ioctl(dev, WLC_GET_SSID, pssid, sizeof(wlc_ssid_t), 0);
274 if (unlikely(error))
275 return error;
276 pssid->SSID_len = dtoh32(pssid->SSID_len);
277 return error;
278}
279
280int wldev_get_band(
281 struct net_device *dev, uint *pband)
282{
283 int error;
284
285 error = wldev_ioctl(dev, WLC_GET_BAND, pband, sizeof(uint), 0);
286 return error;
287}
288
289int wldev_set_band(
290 struct net_device *dev, uint band)
291{
292 int error = -1;
293
294 if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) {
295 error = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), 1);
296 }
297 return error;
298}
299
300int wldev_set_country(
301 struct net_device *dev, char *country_code)
302{
303 int error = -1;
304 wl_country_t cspec = {{0}, 0, {0}};
305 scb_val_t scbval;
306 char smbuf[WLC_IOCTL_SMLEN];
307
308 if (!country_code)
309 return error;
310
311 error = wldev_iovar_getbuf(dev, "country", &cspec, sizeof(cspec),
312 smbuf, sizeof(smbuf));
313 if (error < 0)
314 DHD_ERROR(("%s: get country failed = %d\n", __FUNCTION__, error));
315
316 if ((error < 0) ||
317 (strncmp(country_code, smbuf, WLC_CNTRY_BUF_SZ) != 0)) {
318 bzero(&scbval, sizeof(scb_val_t));
319 error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), 1);
320 if (error < 0) {
321 DHD_ERROR(("%s: set country failed due to Disassoc error %d\n",
322 __FUNCTION__, error));
323 return error;
324 }
325 }
326 cspec.rev = -1;
327 memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ);
328 memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ);
329 get_customized_country_code((char *)&cspec.country_abbrev, &cspec);
330 error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec),
331 smbuf, sizeof(smbuf));
332 if (error < 0) {
333 DHD_ERROR(("%s: set country for %s as %s rev %d failed\n",
334 __FUNCTION__, country_code, cspec.ccode, cspec.rev));
335 return error;
336 }
337 dhd_bus_country_set(dev, &cspec);
338 DHD_INFO(("%s: set country for %s as %s rev %d\n",
339 __FUNCTION__, country_code, cspec.ccode, cspec.rev));
340 return 0;
341}