blob: 36a3e1a946d1a7b2121623663b21f4db23ba9ee3 [file] [log] [blame]
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001/* src/prism2/driver/prism2mgmt.c
2*
3* Management request handler functions.
4*
5* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
6* --------------------------------------------------------------------
7*
8* linux-wlan
9*
10* The contents of this file are subject to the Mozilla Public
11* License Version 1.1 (the "License"); you may not use this file
12* except in compliance with the License. You may obtain a copy of
13* the License at http://www.mozilla.org/MPL/
14*
15* Software distributed under the License is distributed on an "AS
16* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17* implied. See the License for the specific language governing
18* rights and limitations under the License.
19*
20* Alternatively, the contents of this file may be used under the
21* terms of the GNU Public License version 2 (the "GPL"), in which
22* case the provisions of the GPL are applicable instead of the
23* above. If you wish to allow the use of your version of this file
24* only under the terms of the GPL and not to allow others to use
25* your version of this file under the MPL, indicate your decision
26* by deleting the provisions above and replace them with the notice
27* and other provisions required by the GPL. If you do not delete
28* the provisions above, a recipient may use your version of this
29* file under either the MPL or the GPL.
30*
31* --------------------------------------------------------------------
32*
33* Inquiries regarding the linux-wlan Open Source project can be
34* made directly to:
35*
36* AbsoluteValue Systems Inc.
37* info@linux-wlan.com
38* http://www.linux-wlan.com
39*
40* --------------------------------------------------------------------
41*
42* Portions of the development of this software were funded by
43* Intersil Corporation as part of PRISM(R) chipset product development.
44*
45* --------------------------------------------------------------------
46*
47* The functions in this file handle management requests sent from
48* user mode.
49*
50* Most of these functions have two separate blocks of code that are
51* conditional on whether this is a station or an AP. This is used
52* to separate out the STA and AP responses to these management primitives.
53* It's a choice (good, bad, indifferent?) to have the code in the same
54* place so it's clear that the same primitive is implemented in both
55* cases but has different behavior.
56*
57* --------------------------------------------------------------------
58*/
59
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070060#include <linux/if_arp.h>
61#include <linux/module.h>
62#include <linux/kernel.h>
63#include <linux/wait.h>
64#include <linux/sched.h>
65#include <linux/types.h>
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070066#include <linux/wireless.h>
67#include <linux/netdevice.h>
68#include <linux/delay.h>
Andrew Elwellef1a0ed2010-02-18 23:56:12 +010069#include <linux/io.h>
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070070#include <asm/byteorder.h>
71#include <linux/random.h>
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070072#include <linux/usb.h>
Moritz Muehlenhoff7f6e0e42009-01-25 21:54:55 +010073#include <linux/bitops.h>
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070074
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070075#include "p80211types.h"
76#include "p80211hdr.h"
77#include "p80211mgmt.h"
78#include "p80211conv.h"
79#include "p80211msg.h"
80#include "p80211netdev.h"
81#include "p80211metadef.h"
82#include "p80211metastruct.h"
83#include "hfa384x.h"
84#include "prism2mgmt.h"
85
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070086/* Converts 802.11 format rate specifications to prism2 */
Moritz Muehlenhoff7f6e0e42009-01-25 21:54:55 +010087#define p80211rate_to_p2bit(n) ((((n)&~BIT(7)) == 2) ? BIT(0) : \
88 (((n)&~BIT(7)) == 4) ? BIT(1) : \
89 (((n)&~BIT(7)) == 11) ? BIT(2) : \
90 (((n)&~BIT(7)) == 22) ? BIT(3) : 0)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070091
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -070092/*----------------------------------------------------------------
93* prism2mgmt_scan
94*
95* Initiate a scan for BSSs.
96*
97* This function corresponds to MLME-scan.request and part of
98* MLME-scan.confirm. As far as I can tell in the standard, there
99* are no restrictions on when a scan.request may be issued. We have
100* to handle in whatever state the driver/MAC happen to be.
101*
102* Arguments:
103* wlandev wlan device structure
104* msgp ptr to msg buffer
105*
106* Returns:
107* 0 success and done
108* <0 success, but we're waiting for something to finish.
109* >0 an error occurred while handling the message.
110* Side effects:
111*
112* Call context:
113* process thread (usually)
114* interrupt
115----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530116int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700117{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100118 int result = 0;
119 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300120 struct p80211msg_dot11req_scan *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100121 u16 roamingmode, word;
122 int i, timeout;
123 int istmpenable = 0;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700124
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100125 hfa384x_HostScanRequest_data_t scanreq;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700126
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100127 /* gatekeeper check */
128 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
129 hw->ident_sta_fw.minor,
130 hw->ident_sta_fw.variant) <
131 HFA384x_FIRMWARE_VERSION(1, 3, 2)) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000132 netdev_err(wlandev->netdev,
133 "HostScan not supported with current firmware (<1.3.2).\n");
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100134 result = 1;
135 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700136 goto exit;
137 }
138
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100139 memset(&scanreq, 0, sizeof(scanreq));
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700140
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100141 /* save current roaming mode */
142 result = hfa384x_drvr_getconfig16(hw,
143 HFA384x_RID_CNFROAMINGMODE,
144 &roamingmode);
145 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000146 netdev_err(wlandev->netdev,
147 "getconfig(ROAMMODE) failed. result=%d\n", result);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100148 msg->resultcode.data =
149 P80211ENUM_resultcode_implementation_failure;
150 goto exit;
151 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700152
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100153 /* drop into mode 3 for the scan */
154 result = hfa384x_drvr_setconfig16(hw,
155 HFA384x_RID_CNFROAMINGMODE,
156 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
157 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000158 netdev_err(wlandev->netdev,
Johannes Stadlinger2cf1ba42014-06-19 21:20:13 +0200159 "setconfig(ROAMINGMODE) failed. result=%d\n",
160 result);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100161 msg->resultcode.data =
162 P80211ENUM_resultcode_implementation_failure;
163 goto exit;
164 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700165
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100166 /* active or passive? */
167 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
168 hw->ident_sta_fw.minor,
169 hw->ident_sta_fw.variant) >
170 HFA384x_FIRMWARE_VERSION(1, 5, 0)) {
171 if (msg->scantype.data != P80211ENUM_scantype_active)
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100172 word = cpu_to_le16(msg->maxchanneltime.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100173 else
174 word = 0;
175
176 result =
177 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL,
178 word);
179 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000180 netdev_warn(wlandev->netdev,
181 "Passive scan not supported with "
182 "current firmware. (<1.5.1)\n");
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100183 }
184 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700185
186 /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
187 word = HFA384x_RATEBIT_2;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100188 scanreq.txRate = cpu_to_le16(word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700189
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100190 /* set up the channel list */
191 word = 0;
192 for (i = 0; i < msg->channellist.data.len; i++) {
193 u8 channel = msg->channellist.data.data[i];
194 if (channel > 14)
195 continue;
196 /* channel 1 is BIT 0 ... channel 14 is BIT 13 */
197 word |= (1 << (channel - 1));
198 }
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100199 scanreq.channelList = cpu_to_le16(word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700200
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100201 /* set up the ssid, if present. */
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100202 scanreq.ssid.len = cpu_to_le16(msg->ssid.data.len);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100203 memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700204
205 /* Enable the MAC port if it's not already enabled */
206 result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100207 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000208 netdev_err(wlandev->netdev,
209 "getconfig(PORTSTATUS) failed. result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700210 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100211 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700212 goto exit;
213 }
214 if (word == HFA384x_PORTSTATUS_DISABLED) {
Solomon Peachyaaad4302008-10-29 10:42:53 -0400215 u16 wordbuf[17];
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700216
217 result = hfa384x_drvr_setconfig16(hw,
Johan Meiringf83dfd02010-11-06 18:23:44 +0200218 HFA384x_RID_CNFROAMINGMODE,
219 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100220 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000221 netdev_err(wlandev->netdev,
222 "setconfig(ROAMINGMODE) failed. result=%d\n",
223 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700224 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100225 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700226 goto exit;
227 }
228 /* Construct a bogus SSID and assign it to OwnSSID and
229 * DesiredSSID
230 */
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100231 wordbuf[0] = cpu_to_le16(WLAN_SSID_MAXLEN);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700232 get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100233 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
234 wordbuf,
235 HFA384x_RID_CNFOWNSSID_LEN);
236 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000237 netdev_err(wlandev->netdev, "Failed to set OwnSSID.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700238 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100239 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700240 goto exit;
241 }
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100242 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
243 wordbuf,
244 HFA384x_RID_CNFDESIREDSSID_LEN);
245 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000246 netdev_err(wlandev->netdev,
247 "Failed to set DesiredSSID.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700248 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100249 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700250 goto exit;
251 }
252 /* bsstype */
253 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100254 HFA384x_RID_CNFPORTTYPE,
255 HFA384x_PORTTYPE_IBSS);
256 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000257 netdev_err(wlandev->netdev,
258 "Failed to set CNFPORTTYPE.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700259 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100260 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700261 goto exit;
262 }
263 /* ibss options */
264 result = hfa384x_drvr_setconfig16(hw,
Johan Meiringf83dfd02010-11-06 18:23:44 +0200265 HFA384x_RID_CREATEIBSS,
266 HFA384x_CREATEIBSS_JOINCREATEIBSS);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100267 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000268 netdev_err(wlandev->netdev,
269 "Failed to set CREATEIBSS.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700270 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100271 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700272 goto exit;
273 }
274 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100275 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000276 netdev_err(wlandev->netdev,
Johannes Stadlinger2cf1ba42014-06-19 21:20:13 +0200277 "drvr_enable(0) failed. result=%d\n",
278 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700279 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100280 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700281 goto exit;
282 }
283 istmpenable = 1;
284 }
285
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100286 /* Figure out our timeout first Kus, then HZ */
287 timeout = msg->channellist.data.len * msg->maxchanneltime.data;
288 timeout = (timeout * HZ) / 1000;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700289
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100290 /* Issue the scan request */
291 hw->scanflag = 0;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700292
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100293 result = hfa384x_drvr_setconfig(hw,
294 HFA384x_RID_HOSTSCAN, &scanreq,
295 sizeof(hfa384x_HostScanRequest_data_t));
296 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000297 netdev_err(wlandev->netdev,
Johannes Stadlinger2cf1ba42014-06-19 21:20:13 +0200298 "setconfig(SCANREQUEST) failed. result=%d\n",
299 result);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100300 msg->resultcode.data =
301 P80211ENUM_resultcode_implementation_failure;
302 goto exit;
303 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700304
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100305 /* sleep until info frame arrives */
306 wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700307
308 msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
309 if (hw->scanflag == -1)
310 hw->scanflag = 0;
311
312 msg->numbss.data = hw->scanflag;
313
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100314 hw->scanflag = 0;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700315
316 /* Disable port if we temporarily enabled it. */
317 if (istmpenable) {
318 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100319 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000320 netdev_err(wlandev->netdev,
Johannes Stadlinger2cf1ba42014-06-19 21:20:13 +0200321 "drvr_disable(0) failed. result=%d\n",
322 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700323 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100324 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700325 goto exit;
326 }
327 }
328
329 /* restore original roaming mode */
330 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
331 roamingmode);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100332 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000333 netdev_err(wlandev->netdev,
334 "setconfig(ROAMMODE) failed. result=%d\n", result);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100335 msg->resultcode.data =
336 P80211ENUM_resultcode_implementation_failure;
337 goto exit;
338 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700339
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100340 result = 0;
341 msg->resultcode.data = P80211ENUM_resultcode_success;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700342
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100343exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700344 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
345
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700346 return result;
347}
348
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700349/*----------------------------------------------------------------
350* prism2mgmt_scan_results
351*
352* Retrieve the BSS description for one of the BSSs identified in
353* a scan.
354*
355* Arguments:
356* wlandev wlan device structure
357* msgp ptr to msg buffer
358*
359* Returns:
360* 0 success and done
361* <0 success, but we're waiting for something to finish.
362* >0 an error occurred while handling the message.
363* Side effects:
364*
365* Call context:
366* process thread (usually)
367* interrupt
368----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530369int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700370{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100371 int result = 0;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300372 struct p80211msg_dot11req_scan_results *req;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100373 hfa384x_t *hw = wlandev->priv;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700374 hfa384x_HScanResultSub_t *item = NULL;
375
376 int count;
377
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300378 req = (struct p80211msg_dot11req_scan_results *) msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700379
380 req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
381
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100382 if (!hw->scanresults) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000383 netdev_err(wlandev->netdev,
384 "dot11req_scan_results can only be used after "
385 "a successful dot11req_scan.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700386 result = 2;
387 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
388 goto exit;
389 }
390
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100391 count = (hw->scanresults->framelen - 3) / 32;
Dan Carpenterbb46f132012-04-18 09:48:59 +0300392 if (count > HFA384x_SCANRESULT_MAX)
393 count = HFA384x_SCANRESULT_MAX;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700394
395 if (req->bssindex.data >= count) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +0100396 pr_debug("requested index (%d) out of range (%d)\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +0530397 req->bssindex.data, count);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700398 result = 2;
399 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
400 goto exit;
401 }
402
403 item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
404 /* signal and noise */
405 req->signal.status = P80211ENUM_msgitem_status_data_ok;
406 req->noise.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100407 req->signal.data = le16_to_cpu(item->sl);
408 req->noise.data = le16_to_cpu(item->anl);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700409
410 /* BSSID */
411 req->bssid.status = P80211ENUM_msgitem_status_data_ok;
412 req->bssid.data.len = WLAN_BSSID_LEN;
413 memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
414
415 /* SSID */
416 req->ssid.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100417 req->ssid.data.len = le16_to_cpu(item->ssid.len);
Tormod Volden811a37e2013-01-09 22:23:32 +0100418 req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700419 memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
420
421 /* supported rates */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100422 for (count = 0; count < 10; count++)
423 if (item->supprates[count] == 0)
424 break;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700425
426#define REQBASICRATE(N) \
Sebastian Wankerl52070c72013-01-20 16:24:45 +0100427 do { \
428 if ((count >= N) && DOT11_RATE5_ISBASIC_GET( \
429 item->supprates[(N)-1])) { \
430 req->basicrate ## N .data = item->supprates[(N)-1]; \
431 req->basicrate ## N .status = \
432 P80211ENUM_msgitem_status_data_ok; \
433 } \
434 } while (0)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700435
436 REQBASICRATE(1);
437 REQBASICRATE(2);
438 REQBASICRATE(3);
439 REQBASICRATE(4);
440 REQBASICRATE(5);
441 REQBASICRATE(6);
442 REQBASICRATE(7);
443 REQBASICRATE(8);
444
445#define REQSUPPRATE(N) \
Sebastian Wankerl52070c72013-01-20 16:24:45 +0100446 do { \
447 if (count >= N) { \
448 req->supprate ## N .data = item->supprates[(N)-1]; \
449 req->supprate ## N .status = \
450 P80211ENUM_msgitem_status_data_ok; \
451 } \
452 } while (0)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700453
454 REQSUPPRATE(1);
455 REQSUPPRATE(2);
456 REQSUPPRATE(3);
457 REQSUPPRATE(4);
458 REQSUPPRATE(5);
459 REQSUPPRATE(6);
460 REQSUPPRATE(7);
461 REQSUPPRATE(8);
462
463 /* beacon period */
464 req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100465 req->beaconperiod.data = le16_to_cpu(item->bcnint);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700466
467 /* timestamps */
468 req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
469 req->timestamp.data = jiffies;
470 req->localtime.status = P80211ENUM_msgitem_status_data_ok;
471 req->localtime.data = jiffies;
472
473 /* atim window */
474 req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100475 req->ibssatimwindow.data = le16_to_cpu(item->atim);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700476
477 /* Channel */
478 req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100479 req->dschannel.data = le16_to_cpu(item->chid);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700480
481 /* capinfo bits */
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100482 count = le16_to_cpu(item->capinfo);
Karl Reltoncb3126e2010-06-03 23:04:06 +0100483 req->capinfo.status = P80211ENUM_msgitem_status_data_ok;
484 req->capinfo.data = count;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700485
486 /* privacy flag */
487 req->privacy.status = P80211ENUM_msgitem_status_data_ok;
488 req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
489
490 /* cfpollable */
491 req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
492 req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
493
494 /* cfpollreq */
495 req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
496 req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
497
498 /* bsstype */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100499 req->bsstype.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700500 req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100501 P80211ENUM_bsstype_infrastructure : P80211ENUM_bsstype_independent;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700502
503 result = 0;
504 req->resultcode.data = P80211ENUM_resultcode_success;
505
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100506exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700507 return result;
508}
509
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700510/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700511* prism2mgmt_start
512*
513* Start a BSS. Any station can do this for IBSS, only AP for ESS.
514*
515* Arguments:
516* wlandev wlan device structure
517* msgp ptr to msg buffer
518*
519* Returns:
520* 0 success and done
521* <0 success, but we're waiting for something to finish.
522* >0 an error occurred while handling the message.
523* Side effects:
524*
525* Call context:
526* process thread (usually)
527* interrupt
528----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530529int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700530{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100531 int result = 0;
532 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300533 struct p80211msg_dot11req_start *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700534
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100535 p80211pstrd_t *pstr;
536 u8 bytebuf[80];
Himangi Saraogib2119912013-11-02 18:11:44 +0530537 struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100538 u16 word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700539
540 wlandev->macmode = WLAN_MACMODE_NONE;
541
542 /* Set the SSID */
543 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
544
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400545 /*** ADHOC IBSS ***/
546 /* see if current f/w is less than 8c3 */
547 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
548 hw->ident_sta_fw.minor,
549 hw->ident_sta_fw.variant) <
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100550 HFA384x_FIRMWARE_VERSION(0, 8, 3)) {
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400551 /* Ad-Hoc not quite supported on Prism2 */
552 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
553 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700554 goto done;
555 }
556
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700557 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
558
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400559 /*** STATION ***/
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700560 /* Set the REQUIRED config items */
561 /* SSID */
Andrew Elwellef1a0ed2010-02-18 23:56:12 +0100562 pstr = (p80211pstrd_t *) &(msg->ssid.data);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700563 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100564 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
565 bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
566 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000567 netdev_err(wlandev->netdev, "Failed to set CnfOwnSSID\n");
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400568 goto failed;
569 }
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100570 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
571 bytebuf,
572 HFA384x_RID_CNFDESIREDSSID_LEN);
573 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000574 netdev_err(wlandev->netdev, "Failed to set CnfDesiredSSID\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700575 goto failed;
576 }
577
578 /* bsstype - we use the default in the ap firmware */
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400579 /* IBSS port */
580 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700581
582 /* beacon period */
583 word = msg->beaconperiod.data;
Solomon Peachyaaad4302008-10-29 10:42:53 -0400584 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100585 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000586 netdev_err(wlandev->netdev,
587 "Failed to set beacon period=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700588 goto failed;
589 }
590
591 /* dschannel */
592 word = msg->dschannel.data;
593 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100594 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000595 netdev_err(wlandev->netdev,
596 "Failed to set channel=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700597 goto failed;
598 }
599 /* Basic rates */
600 word = p80211rate_to_p2bit(msg->basicrate1.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100601 if (msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700602 word |= p80211rate_to_p2bit(msg->basicrate2.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100603
604 if (msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700605 word |= p80211rate_to_p2bit(msg->basicrate3.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100606
607 if (msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700608 word |= p80211rate_to_p2bit(msg->basicrate4.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100609
610 if (msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700611 word |= p80211rate_to_p2bit(msg->basicrate5.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100612
613 if (msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700614 word |= p80211rate_to_p2bit(msg->basicrate6.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100615
616 if (msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700617 word |= p80211rate_to_p2bit(msg->basicrate7.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100618
619 if (msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700620 word |= p80211rate_to_p2bit(msg->basicrate8.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100621
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700622 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100623 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000624 netdev_err(wlandev->netdev,
625 "Failed to set basicrates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700626 goto failed;
627 }
628
629 /* Operational rates (supprates and txratecontrol) */
630 word = p80211rate_to_p2bit(msg->operationalrate1.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100631 if (msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700632 word |= p80211rate_to_p2bit(msg->operationalrate2.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100633
634 if (msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700635 word |= p80211rate_to_p2bit(msg->operationalrate3.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100636
637 if (msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700638 word |= p80211rate_to_p2bit(msg->operationalrate4.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100639
640 if (msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700641 word |= p80211rate_to_p2bit(msg->operationalrate5.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100642
643 if (msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700644 word |= p80211rate_to_p2bit(msg->operationalrate6.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100645
646 if (msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700647 word |= p80211rate_to_p2bit(msg->operationalrate7.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100648
649 if (msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700650 word |= p80211rate_to_p2bit(msg->operationalrate8.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100651
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700652 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100653 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000654 netdev_err(wlandev->netdev,
655 "Failed to set supprates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700656 goto failed;
657 }
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400658
659 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100660 if (result) {
Johannes Stadlinger2cf1ba42014-06-19 21:20:13 +0200661 netdev_err(wlandev->netdev, "Failed to set txrates=%d.\n",
662 word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700663 goto failed;
664 }
665
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700666 /* Set the macmode so the frame setup code knows what to do */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100667 if (msg->bsstype.data == P80211ENUM_bsstype_independent) {
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400668 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700669 /* lets extend the data length a bit */
670 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
671 }
672
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700673 /* Enable the Port */
674 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100675 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000676 netdev_err(wlandev->netdev,
677 "Enable macport failed, result=%d.\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700678 goto failed;
679 }
680
681 msg->resultcode.data = P80211ENUM_resultcode_success;
682
683 goto done;
684failed:
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +0100685 pr_debug("Failed to set a config option, result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700686 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
687
688done:
689 result = 0;
690
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700691 return result;
692}
693
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700694/*----------------------------------------------------------------
695* prism2mgmt_readpda
696*
697* Collect the PDA data and put it in the message.
698*
699* Arguments:
700* wlandev wlan device structure
701* msgp ptr to msg buffer
702*
703* Returns:
704* 0 success and done
705* <0 success, but we're waiting for something to finish.
706* >0 an error occurred while handling the message.
707* Side effects:
708*
709* Call context:
710* process thread (usually)
711----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530712int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700713{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100714 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300715 struct p80211msg_p2req_readpda *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100716 int result;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700717
718 /* We only support collecting the PDA when in the FWLOAD
719 * state.
720 */
721 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000722 netdev_err(wlandev->netdev,
723 "PDA may only be read in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700724 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100725 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700726 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
727 } else {
728 /* Call drvr_readpda(), it handles the auxport enable
729 * and validating the returned PDA.
730 */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100731 result = hfa384x_drvr_readpda(hw,
732 msg->pda.data,
733 HFA384x_PDA_LEN_MAX);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700734 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000735 netdev_err(wlandev->netdev,
736 "hfa384x_drvr_readpda() failed, "
737 "result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700738
739 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100740 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700741 msg->resultcode.status =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100742 P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700743 return 0;
744 }
745 msg->pda.status = P80211ENUM_msgitem_status_data_ok;
746 msg->resultcode.data = P80211ENUM_resultcode_success;
747 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
748 }
749
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700750 return 0;
751}
752
753/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700754* prism2mgmt_ramdl_state
755*
756* Establishes the beginning/end of a card RAM download session.
757*
758* It is expected that the ramdl_write() function will be called
759* one or more times between the 'enable' and 'disable' calls to
760* this function.
761*
762* Note: This function should not be called when a mac comm port
763* is active.
764*
765* Arguments:
766* wlandev wlan device structure
767* msgp ptr to msg buffer
768*
769* Returns:
770* 0 success and done
771* <0 success, but we're waiting for something to finish.
772* >0 an error occurred while handling the message.
773* Side effects:
774*
775* Call context:
776* process thread (usually)
777----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530778int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700779{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100780 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300781 struct p80211msg_p2req_ramdl_state *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700782
783 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000784 netdev_err(wlandev->netdev,
785 "ramdl_state(): may only be called "
786 "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700787 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100788 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700789 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700790 return 0;
791 }
792
793 /*
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100794 ** Note: Interrupts are locked out if this is an AP and are NOT
795 ** locked out if this is a station.
796 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700797
798 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100799 if (msg->enable.data == P80211ENUM_truth_true) {
800 if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) {
801 msg->resultcode.data =
802 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700803 } else {
804 msg->resultcode.data = P80211ENUM_resultcode_success;
805 }
806 } else {
807 hfa384x_drvr_ramdl_disable(hw);
808 msg->resultcode.data = P80211ENUM_resultcode_success;
809 }
810
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700811 return 0;
812}
813
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700814/*----------------------------------------------------------------
815* prism2mgmt_ramdl_write
816*
817* Writes a buffer to the card RAM using the download state. This
818* is for writing code to card RAM. To just read or write raw data
819* use the aux functions.
820*
821* Arguments:
822* wlandev wlan device structure
823* msgp ptr to msg buffer
824*
825* Returns:
826* 0 success and done
827* <0 success, but we're waiting for something to finish.
828* >0 an error occurred while handling the message.
829* Side effects:
830*
831* Call context:
832* process thread (usually)
833----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530834int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700835{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100836 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300837 struct p80211msg_p2req_ramdl_write *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100838 u32 addr;
839 u32 len;
840 u8 *buf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700841
842 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000843 netdev_err(wlandev->netdev,
844 "ramdl_write(): may only be called "
845 "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700846 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100847 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700848 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700849 return 0;
850 }
851
852 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
853 /* first validate the length */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100854 if (msg->len.data > sizeof(msg->data.data)) {
855 msg->resultcode.status =
856 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700857 return 0;
858 }
859 /* call the hfa384x function to do the write */
860 addr = msg->addr.data;
861 len = msg->len.data;
862 buf = msg->data.data;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100863 if (hfa384x_drvr_ramdl_write(hw, addr, buf, len))
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700864 msg->resultcode.data = P80211ENUM_resultcode_refused;
865
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700866 msg->resultcode.data = P80211ENUM_resultcode_success;
867
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700868 return 0;
869}
870
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700871/*----------------------------------------------------------------
872* prism2mgmt_flashdl_state
873*
874* Establishes the beginning/end of a card Flash download session.
875*
876* It is expected that the flashdl_write() function will be called
877* one or more times between the 'enable' and 'disable' calls to
878* this function.
879*
880* Note: This function should not be called when a mac comm port
881* is active.
882*
883* Arguments:
884* wlandev wlan device structure
885* msgp ptr to msg buffer
886*
887* Returns:
888* 0 success and done
889* <0 success, but we're waiting for something to finish.
890* >0 an error occurred while handling the message.
891* Side effects:
892*
893* Call context:
894* process thread (usually)
895----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530896int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700897{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100898 int result = 0;
899 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300900 struct p80211msg_p2req_flashdl_state *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700901
902 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000903 netdev_err(wlandev->netdev,
904 "flashdl_state(): may only be called "
905 "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700906 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100907 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700908 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700909 return 0;
910 }
911
912 /*
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100913 ** Note: Interrupts are locked out if this is an AP and are NOT
914 ** locked out if this is a station.
915 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700916
917 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100918 if (msg->enable.data == P80211ENUM_truth_true) {
919 if (hfa384x_drvr_flashdl_enable(hw)) {
920 msg->resultcode.data =
921 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700922 } else {
923 msg->resultcode.data = P80211ENUM_resultcode_success;
924 }
925 } else {
926 hfa384x_drvr_flashdl_disable(hw);
927 msg->resultcode.data = P80211ENUM_resultcode_success;
928 /* NOTE: At this point, the MAC is in the post-reset
929 * state and the driver is in the fwload state.
930 * We need to get the MAC back into the fwload
931 * state. To do this, we set the nsdstate to HWPRESENT
932 * and then call the ifstate function to redo everything
933 * that got us into the fwload state.
934 */
935 wlandev->msdstate = WLAN_MSD_HWPRESENT;
936 result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
937 if (result != P80211ENUM_resultcode_success) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000938 netdev_err(wlandev->netdev,
939 "prism2sta_ifstate(fwload) failed,"
940 "P80211ENUM_resultcode=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700941 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100942 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700943 result = -1;
944 }
945 }
946
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700947 return 0;
948}
949
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700950/*----------------------------------------------------------------
951* prism2mgmt_flashdl_write
952*
953*
954*
955* Arguments:
956* wlandev wlan device structure
957* msgp ptr to msg buffer
958*
959* Returns:
960* 0 success and done
961* <0 success, but we're waiting for something to finish.
962* >0 an error occurred while handling the message.
963* Side effects:
964*
965* Call context:
966* process thread (usually)
967----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530968int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700969{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100970 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300971 struct p80211msg_p2req_flashdl_write *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100972 u32 addr;
973 u32 len;
974 u8 *buf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700975
976 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000977 netdev_err(wlandev->netdev,
978 "flashdl_write(): may only be called "
979 "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700980 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100981 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700982 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700983 return 0;
984 }
985
986 /*
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100987 ** Note: Interrupts are locked out if this is an AP and are NOT
988 ** locked out if this is a station.
989 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700990
991 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
992 /* first validate the length */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100993 if (msg->len.data > sizeof(msg->data.data)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700994 msg->resultcode.status =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100995 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700996 return 0;
997 }
998 /* call the hfa384x function to do the write */
999 addr = msg->addr.data;
1000 len = msg->len.data;
1001 buf = msg->data.data;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001002 if (hfa384x_drvr_flashdl_write(hw, addr, buf, len))
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001003 msg->resultcode.data = P80211ENUM_resultcode_refused;
1004
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001005 msg->resultcode.data = P80211ENUM_resultcode_success;
1006
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001007 return 0;
1008}
1009
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001010/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001011* prism2mgmt_autojoin
1012*
1013* Associate with an ESS.
1014*
1015* Arguments:
1016* wlandev wlan device structure
1017* msgp ptr to msg buffer
1018*
1019* Returns:
1020* 0 success and done
1021* <0 success, but we're waiting for something to finish.
1022* >0 an error occurred while handling the message.
1023* Side effects:
1024*
1025* Call context:
1026* process thread (usually)
1027* interrupt
1028----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +05301029int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001030{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001031 hfa384x_t *hw = wlandev->priv;
1032 int result = 0;
1033 u16 reg;
1034 u16 port_type;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -03001035 struct p80211msg_lnxreq_autojoin *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001036 p80211pstrd_t *pstr;
1037 u8 bytebuf[256];
Himangi Saraogib2119912013-11-02 18:11:44 +05301038 struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001039
1040 wlandev->macmode = WLAN_MACMODE_NONE;
1041
1042 /* Set the SSID */
1043 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
1044
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001045 /* Disable the Port */
1046 hfa384x_drvr_disable(hw, 0);
1047
1048 /*** STATION ***/
1049 /* Set the TxRates */
1050 hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
1051
1052 /* Set the auth type */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001053 if (msg->authtype.data == P80211ENUM_authalg_sharedkey)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001054 reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001055 else
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001056 reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001057
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001058 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
1059
1060 /* Set the ssid */
1061 memset(bytebuf, 0, 256);
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001062 pstr = (p80211pstrd_t *) &(msg->ssid.data);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001063 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001064 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
1065 bytebuf,
1066 HFA384x_RID_CNFDESIREDSSID_LEN);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001067 port_type = HFA384x_PORTTYPE_BSS;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001068 /* Set the PortType */
1069 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
1070
1071 /* Enable the Port */
1072 hfa384x_drvr_enable(hw, 0);
1073
1074 /* Set the resultcode */
1075 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1076 msg->resultcode.data = P80211ENUM_resultcode_success;
1077
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001078 return result;
1079}
1080
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001081/*----------------------------------------------------------------
1082* prism2mgmt_wlansniff
1083*
1084* Start or stop sniffing.
1085*
1086* Arguments:
1087* wlandev wlan device structure
1088* msgp ptr to msg buffer
1089*
1090* Returns:
1091* 0 success and done
1092* <0 success, but we're waiting for something to finish.
1093* >0 an error occurred while handling the message.
1094* Side effects:
1095*
1096* Call context:
1097* process thread (usually)
1098* interrupt
1099----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +05301100int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001101{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001102 int result = 0;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -03001103 struct p80211msg_lnxreq_wlansniff *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001104
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001105 hfa384x_t *hw = wlandev->priv;
1106 u16 word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001107
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001108 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001109 switch (msg->enable.data) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001110 case P80211ENUM_truth_false:
1111 /* Confirm that we're in monitor mode */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001112 if (wlandev->netdev->type == ARPHRD_ETHER) {
1113 msg->resultcode.data =
1114 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001115 result = 0;
1116 goto exit;
1117 }
1118 /* Disable monitor mode */
1119 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001120 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301121 pr_debug("failed to disable monitor mode, result=%d\n",
1122 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001123 goto failed;
1124 }
1125 /* Disable port 0 */
1126 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001127 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301128 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001129 ("failed to disable port 0 after sniffing, result=%d\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301130 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001131 goto failed;
1132 }
1133 /* Clear the driver state */
1134 wlandev->netdev->type = ARPHRD_ETHER;
1135
1136 /* Restore the wepflags */
1137 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001138 HFA384x_RID_CNFWEPFLAGS,
1139 hw->presniff_wepflags);
1140 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301141 pr_debug
1142 ("failed to restore wepflags=0x%04x, result=%d\n",
1143 hw->presniff_wepflags, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001144 goto failed;
1145 }
1146
1147 /* Set the port to its prior type and enable (if necessary) */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001148 if (hw->presniff_port_type != 0) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001149 word = hw->presniff_port_type;
1150 result = hfa384x_drvr_setconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001151 HFA384x_RID_CNFPORTTYPE,
1152 word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001153 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301154 pr_debug
1155 ("failed to restore porttype, result=%d\n",
1156 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001157 goto failed;
1158 }
1159
1160 /* Enable the port */
1161 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001162 if (result) {
Sebastian Wankerl25c97da2013-01-20 16:30:54 +01001163 pr_debug("failed to enable port to presniff setting, result=%d\n",
1164 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001165 goto failed;
1166 }
1167 } else {
1168 result = hfa384x_drvr_disable(hw, 0);
1169
1170 }
1171
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +10001172 netdev_info(wlandev->netdev, "monitor mode disabled\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001173 msg->resultcode.data = P80211ENUM_resultcode_success;
1174 result = 0;
1175 goto exit;
1176 break;
1177 case P80211ENUM_truth_true:
1178 /* Disable the port (if enabled), only check Port 0 */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001179 if (hw->port_enabled[0]) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001180 if (wlandev->netdev->type == ARPHRD_ETHER) {
1181 /* Save macport 0 state */
1182 result = hfa384x_drvr_getconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001183 HFA384x_RID_CNFPORTTYPE,
1184 &(hw->presniff_port_type));
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001185 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301186 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001187 ("failed to read porttype, result=%d\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301188 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001189 goto failed;
1190 }
1191 /* Save the wepflags state */
1192 result = hfa384x_drvr_getconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001193 HFA384x_RID_CNFWEPFLAGS,
1194 &(hw->presniff_wepflags));
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001195 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301196 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001197 ("failed to read wepflags, result=%d\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301198 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001199 goto failed;
1200 }
1201 hfa384x_drvr_stop(hw);
1202 result = hfa384x_drvr_start(hw);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001203 if (result) {
Sebastian Wankerl25c97da2013-01-20 16:30:54 +01001204 pr_debug("failed to restart the card for sniffing, result=%d\n",
1205 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001206 goto failed;
1207 }
1208 } else {
1209 /* Disable the port */
1210 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001211 if (result) {
Sebastian Wankerl25c97da2013-01-20 16:30:54 +01001212 pr_debug("failed to enable port for sniffing, result=%d\n",
1213 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001214 goto failed;
1215 }
1216 }
1217 } else {
1218 hw->presniff_port_type = 0;
1219 }
1220
1221 /* Set the channel we wish to sniff */
1222 word = msg->channel.data;
1223 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001224 HFA384x_RID_CNFOWNCHANNEL,
1225 word);
1226 hw->sniff_channel = word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001227
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001228 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301229 pr_debug("failed to set channel %d, result=%d\n",
1230 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001231 goto failed;
1232 }
1233
1234 /* Now if we're already sniffing, we can skip the rest */
1235 if (wlandev->netdev->type != ARPHRD_ETHER) {
1236 /* Set the port type to pIbss */
1237 word = HFA384x_PORTTYPE_PSUEDOIBSS;
1238 result = hfa384x_drvr_setconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001239 HFA384x_RID_CNFPORTTYPE,
1240 word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001241 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301242 pr_debug
1243 ("failed to set porttype %d, result=%d\n",
1244 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001245 goto failed;
1246 }
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001247 if ((msg->keepwepflags.status ==
1248 P80211ENUM_msgitem_status_data_ok)
1249 && (msg->keepwepflags.data !=
1250 P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001251 /* Set the wepflags for no decryption */
1252 word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001253 HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
1254 result =
1255 hfa384x_drvr_setconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001256 HFA384x_RID_CNFWEPFLAGS,
1257 word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001258 }
1259
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001260 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301261 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001262 ("failed to set wepflags=0x%04x, result=%d\n",
1263 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001264 goto failed;
1265 }
1266 }
1267
1268 /* Do we want to strip the FCS in monitor mode? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001269 if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok)
1270 && (msg->stripfcs.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001271 hw->sniff_fcs = 0;
1272 } else {
1273 hw->sniff_fcs = 1;
1274 }
1275
1276 /* Do we want to truncate the packets? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001277 if (msg->packet_trunc.status ==
1278 P80211ENUM_msgitem_status_data_ok) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001279 hw->sniff_truncate = msg->packet_trunc.data;
1280 } else {
1281 hw->sniff_truncate = 0;
1282 }
1283
1284 /* Enable the port */
1285 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001286 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301287 pr_debug
1288 ("failed to enable port for sniffing, result=%d\n",
1289 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001290 goto failed;
1291 }
1292 /* Enable monitor mode */
1293 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001294 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301295 pr_debug("failed to enable monitor mode, result=%d\n",
1296 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001297 goto failed;
1298 }
1299
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001300 if (wlandev->netdev->type == ARPHRD_ETHER)
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +10001301 netdev_info(wlandev->netdev, "monitor mode enabled\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001302
1303 /* Set the driver state */
1304 /* Do we want the prism2 header? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001305 if ((msg->prismheader.status ==
1306 P80211ENUM_msgitem_status_data_ok)
1307 && (msg->prismheader.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001308 hw->sniffhdr = 0;
1309 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001310 } else
1311 if ((msg->wlanheader.status ==
1312 P80211ENUM_msgitem_status_data_ok)
1313 && (msg->wlanheader.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001314 hw->sniffhdr = 1;
1315 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1316 } else {
1317 wlandev->netdev->type = ARPHRD_IEEE80211;
1318 }
1319
1320 msg->resultcode.data = P80211ENUM_resultcode_success;
1321 result = 0;
1322 goto exit;
1323 break;
1324 default:
1325 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1326 result = 0;
1327 goto exit;
1328 break;
1329 }
1330
1331failed:
1332 msg->resultcode.data = P80211ENUM_resultcode_refused;
1333 result = 0;
1334exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001335 return result;
1336}