blob: f90f7da41d687de65c50b8bd9773288b244e0f80 [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,
Johannes Stadlinger17b37542014-06-19 21:20:14 +0200181 "Passive scan not supported with current firmware. (<1.5.1)\n");
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100182 }
183 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700184
185 /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
186 word = HFA384x_RATEBIT_2;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100187 scanreq.txRate = cpu_to_le16(word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700188
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100189 /* set up the channel list */
190 word = 0;
191 for (i = 0; i < msg->channellist.data.len; i++) {
192 u8 channel = msg->channellist.data.data[i];
193 if (channel > 14)
194 continue;
195 /* channel 1 is BIT 0 ... channel 14 is BIT 13 */
196 word |= (1 << (channel - 1));
197 }
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100198 scanreq.channelList = cpu_to_le16(word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700199
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100200 /* set up the ssid, if present. */
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100201 scanreq.ssid.len = cpu_to_le16(msg->ssid.data.len);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100202 memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700203
204 /* Enable the MAC port if it's not already enabled */
205 result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100206 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000207 netdev_err(wlandev->netdev,
208 "getconfig(PORTSTATUS) failed. result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700209 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100210 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700211 goto exit;
212 }
213 if (word == HFA384x_PORTSTATUS_DISABLED) {
Solomon Peachyaaad4302008-10-29 10:42:53 -0400214 u16 wordbuf[17];
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700215
216 result = hfa384x_drvr_setconfig16(hw,
Johan Meiringf83dfd02010-11-06 18:23:44 +0200217 HFA384x_RID_CNFROAMINGMODE,
218 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100219 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000220 netdev_err(wlandev->netdev,
221 "setconfig(ROAMINGMODE) failed. result=%d\n",
222 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700223 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100224 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700225 goto exit;
226 }
227 /* Construct a bogus SSID and assign it to OwnSSID and
228 * DesiredSSID
229 */
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100230 wordbuf[0] = cpu_to_le16(WLAN_SSID_MAXLEN);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700231 get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100232 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
233 wordbuf,
234 HFA384x_RID_CNFOWNSSID_LEN);
235 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000236 netdev_err(wlandev->netdev, "Failed to set OwnSSID.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700237 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100238 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700239 goto exit;
240 }
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100241 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
242 wordbuf,
243 HFA384x_RID_CNFDESIREDSSID_LEN);
244 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000245 netdev_err(wlandev->netdev,
246 "Failed to set DesiredSSID.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700247 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100248 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700249 goto exit;
250 }
251 /* bsstype */
252 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100253 HFA384x_RID_CNFPORTTYPE,
254 HFA384x_PORTTYPE_IBSS);
255 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000256 netdev_err(wlandev->netdev,
257 "Failed to set CNFPORTTYPE.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700258 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100259 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700260 goto exit;
261 }
262 /* ibss options */
263 result = hfa384x_drvr_setconfig16(hw,
Johan Meiringf83dfd02010-11-06 18:23:44 +0200264 HFA384x_RID_CREATEIBSS,
265 HFA384x_CREATEIBSS_JOINCREATEIBSS);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100266 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000267 netdev_err(wlandev->netdev,
268 "Failed to set CREATEIBSS.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700269 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100270 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700271 goto exit;
272 }
273 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100274 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000275 netdev_err(wlandev->netdev,
Johannes Stadlinger2cf1ba42014-06-19 21:20:13 +0200276 "drvr_enable(0) failed. result=%d\n",
277 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700278 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100279 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700280 goto exit;
281 }
282 istmpenable = 1;
283 }
284
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100285 /* Figure out our timeout first Kus, then HZ */
286 timeout = msg->channellist.data.len * msg->maxchanneltime.data;
287 timeout = (timeout * HZ) / 1000;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700288
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100289 /* Issue the scan request */
290 hw->scanflag = 0;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700291
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100292 result = hfa384x_drvr_setconfig(hw,
293 HFA384x_RID_HOSTSCAN, &scanreq,
294 sizeof(hfa384x_HostScanRequest_data_t));
295 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000296 netdev_err(wlandev->netdev,
Johannes Stadlinger2cf1ba42014-06-19 21:20:13 +0200297 "setconfig(SCANREQUEST) failed. result=%d\n",
298 result);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100299 msg->resultcode.data =
300 P80211ENUM_resultcode_implementation_failure;
301 goto exit;
302 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700303
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100304 /* sleep until info frame arrives */
305 wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700306
307 msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
308 if (hw->scanflag == -1)
309 hw->scanflag = 0;
310
311 msg->numbss.data = hw->scanflag;
312
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100313 hw->scanflag = 0;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700314
315 /* Disable port if we temporarily enabled it. */
316 if (istmpenable) {
317 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100318 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000319 netdev_err(wlandev->netdev,
Johannes Stadlinger2cf1ba42014-06-19 21:20:13 +0200320 "drvr_disable(0) failed. result=%d\n",
321 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700322 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100323 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700324 goto exit;
325 }
326 }
327
328 /* restore original roaming mode */
329 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
330 roamingmode);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100331 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000332 netdev_err(wlandev->netdev,
333 "setconfig(ROAMMODE) failed. result=%d\n", result);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100334 msg->resultcode.data =
335 P80211ENUM_resultcode_implementation_failure;
336 goto exit;
337 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700338
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100339 result = 0;
340 msg->resultcode.data = P80211ENUM_resultcode_success;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700341
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100342exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700343 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
344
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700345 return result;
346}
347
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700348/*----------------------------------------------------------------
349* prism2mgmt_scan_results
350*
351* Retrieve the BSS description for one of the BSSs identified in
352* a scan.
353*
354* Arguments:
355* wlandev wlan device structure
356* msgp ptr to msg buffer
357*
358* Returns:
359* 0 success and done
360* <0 success, but we're waiting for something to finish.
361* >0 an error occurred while handling the message.
362* Side effects:
363*
364* Call context:
365* process thread (usually)
366* interrupt
367----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530368int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700369{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100370 int result = 0;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300371 struct p80211msg_dot11req_scan_results *req;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100372 hfa384x_t *hw = wlandev->priv;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700373 hfa384x_HScanResultSub_t *item = NULL;
374
375 int count;
376
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300377 req = (struct p80211msg_dot11req_scan_results *) msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700378
379 req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
380
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100381 if (!hw->scanresults) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000382 netdev_err(wlandev->netdev,
Johannes Stadlinger17b37542014-06-19 21:20:14 +0200383 "dot11req_scan_results can only be used after a successful dot11req_scan.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700384 result = 2;
385 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
386 goto exit;
387 }
388
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100389 count = (hw->scanresults->framelen - 3) / 32;
Dan Carpenterbb46f132012-04-18 09:48:59 +0300390 if (count > HFA384x_SCANRESULT_MAX)
391 count = HFA384x_SCANRESULT_MAX;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700392
393 if (req->bssindex.data >= count) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +0100394 pr_debug("requested index (%d) out of range (%d)\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +0530395 req->bssindex.data, count);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700396 result = 2;
397 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
398 goto exit;
399 }
400
401 item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
402 /* signal and noise */
403 req->signal.status = P80211ENUM_msgitem_status_data_ok;
404 req->noise.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100405 req->signal.data = le16_to_cpu(item->sl);
406 req->noise.data = le16_to_cpu(item->anl);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700407
408 /* BSSID */
409 req->bssid.status = P80211ENUM_msgitem_status_data_ok;
410 req->bssid.data.len = WLAN_BSSID_LEN;
411 memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
412
413 /* SSID */
414 req->ssid.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100415 req->ssid.data.len = le16_to_cpu(item->ssid.len);
Tormod Volden811a37e2013-01-09 22:23:32 +0100416 req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700417 memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
418
419 /* supported rates */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100420 for (count = 0; count < 10; count++)
421 if (item->supprates[count] == 0)
422 break;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700423
424#define REQBASICRATE(N) \
Sebastian Wankerl52070c72013-01-20 16:24:45 +0100425 do { \
426 if ((count >= N) && DOT11_RATE5_ISBASIC_GET( \
427 item->supprates[(N)-1])) { \
428 req->basicrate ## N .data = item->supprates[(N)-1]; \
429 req->basicrate ## N .status = \
430 P80211ENUM_msgitem_status_data_ok; \
431 } \
432 } while (0)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700433
434 REQBASICRATE(1);
435 REQBASICRATE(2);
436 REQBASICRATE(3);
437 REQBASICRATE(4);
438 REQBASICRATE(5);
439 REQBASICRATE(6);
440 REQBASICRATE(7);
441 REQBASICRATE(8);
442
443#define REQSUPPRATE(N) \
Sebastian Wankerl52070c72013-01-20 16:24:45 +0100444 do { \
445 if (count >= N) { \
446 req->supprate ## N .data = item->supprates[(N)-1]; \
447 req->supprate ## N .status = \
448 P80211ENUM_msgitem_status_data_ok; \
449 } \
450 } while (0)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700451
452 REQSUPPRATE(1);
453 REQSUPPRATE(2);
454 REQSUPPRATE(3);
455 REQSUPPRATE(4);
456 REQSUPPRATE(5);
457 REQSUPPRATE(6);
458 REQSUPPRATE(7);
459 REQSUPPRATE(8);
460
461 /* beacon period */
462 req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100463 req->beaconperiod.data = le16_to_cpu(item->bcnint);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700464
465 /* timestamps */
466 req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
467 req->timestamp.data = jiffies;
468 req->localtime.status = P80211ENUM_msgitem_status_data_ok;
469 req->localtime.data = jiffies;
470
471 /* atim window */
472 req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100473 req->ibssatimwindow.data = le16_to_cpu(item->atim);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700474
475 /* Channel */
476 req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100477 req->dschannel.data = le16_to_cpu(item->chid);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700478
479 /* capinfo bits */
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100480 count = le16_to_cpu(item->capinfo);
Karl Reltoncb3126e2010-06-03 23:04:06 +0100481 req->capinfo.status = P80211ENUM_msgitem_status_data_ok;
482 req->capinfo.data = count;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700483
484 /* privacy flag */
485 req->privacy.status = P80211ENUM_msgitem_status_data_ok;
486 req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
487
488 /* cfpollable */
489 req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
490 req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
491
492 /* cfpollreq */
493 req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
494 req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
495
496 /* bsstype */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100497 req->bsstype.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700498 req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100499 P80211ENUM_bsstype_infrastructure : P80211ENUM_bsstype_independent;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700500
501 result = 0;
502 req->resultcode.data = P80211ENUM_resultcode_success;
503
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100504exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700505 return result;
506}
507
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700508/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700509* prism2mgmt_start
510*
511* Start a BSS. Any station can do this for IBSS, only AP for ESS.
512*
513* Arguments:
514* wlandev wlan device structure
515* msgp ptr to msg buffer
516*
517* Returns:
518* 0 success and done
519* <0 success, but we're waiting for something to finish.
520* >0 an error occurred while handling the message.
521* Side effects:
522*
523* Call context:
524* process thread (usually)
525* interrupt
526----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530527int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700528{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100529 int result = 0;
530 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300531 struct p80211msg_dot11req_start *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700532
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100533 p80211pstrd_t *pstr;
534 u8 bytebuf[80];
Himangi Saraogib2119912013-11-02 18:11:44 +0530535 struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100536 u16 word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700537
538 wlandev->macmode = WLAN_MACMODE_NONE;
539
540 /* Set the SSID */
541 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
542
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400543 /*** ADHOC IBSS ***/
544 /* see if current f/w is less than 8c3 */
545 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
546 hw->ident_sta_fw.minor,
547 hw->ident_sta_fw.variant) <
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100548 HFA384x_FIRMWARE_VERSION(0, 8, 3)) {
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400549 /* Ad-Hoc not quite supported on Prism2 */
550 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
551 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700552 goto done;
553 }
554
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700555 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
556
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400557 /*** STATION ***/
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700558 /* Set the REQUIRED config items */
559 /* SSID */
Andrew Elwellef1a0ed2010-02-18 23:56:12 +0100560 pstr = (p80211pstrd_t *) &(msg->ssid.data);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700561 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100562 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
563 bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
564 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000565 netdev_err(wlandev->netdev, "Failed to set CnfOwnSSID\n");
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400566 goto failed;
567 }
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100568 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
569 bytebuf,
570 HFA384x_RID_CNFDESIREDSSID_LEN);
571 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000572 netdev_err(wlandev->netdev, "Failed to set CnfDesiredSSID\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700573 goto failed;
574 }
575
576 /* bsstype - we use the default in the ap firmware */
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400577 /* IBSS port */
578 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700579
580 /* beacon period */
581 word = msg->beaconperiod.data;
Solomon Peachyaaad4302008-10-29 10:42:53 -0400582 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100583 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000584 netdev_err(wlandev->netdev,
585 "Failed to set beacon period=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700586 goto failed;
587 }
588
589 /* dschannel */
590 word = msg->dschannel.data;
591 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100592 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000593 netdev_err(wlandev->netdev,
594 "Failed to set channel=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700595 goto failed;
596 }
597 /* Basic rates */
598 word = p80211rate_to_p2bit(msg->basicrate1.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100599 if (msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700600 word |= p80211rate_to_p2bit(msg->basicrate2.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100601
602 if (msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700603 word |= p80211rate_to_p2bit(msg->basicrate3.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100604
605 if (msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700606 word |= p80211rate_to_p2bit(msg->basicrate4.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100607
608 if (msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700609 word |= p80211rate_to_p2bit(msg->basicrate5.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100610
611 if (msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700612 word |= p80211rate_to_p2bit(msg->basicrate6.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100613
614 if (msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700615 word |= p80211rate_to_p2bit(msg->basicrate7.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100616
617 if (msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700618 word |= p80211rate_to_p2bit(msg->basicrate8.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100619
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700620 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100621 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000622 netdev_err(wlandev->netdev,
623 "Failed to set basicrates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700624 goto failed;
625 }
626
627 /* Operational rates (supprates and txratecontrol) */
628 word = p80211rate_to_p2bit(msg->operationalrate1.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100629 if (msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700630 word |= p80211rate_to_p2bit(msg->operationalrate2.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100631
632 if (msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700633 word |= p80211rate_to_p2bit(msg->operationalrate3.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100634
635 if (msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700636 word |= p80211rate_to_p2bit(msg->operationalrate4.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100637
638 if (msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700639 word |= p80211rate_to_p2bit(msg->operationalrate5.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100640
641 if (msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700642 word |= p80211rate_to_p2bit(msg->operationalrate6.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100643
644 if (msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700645 word |= p80211rate_to_p2bit(msg->operationalrate7.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100646
647 if (msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700648 word |= p80211rate_to_p2bit(msg->operationalrate8.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100649
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700650 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100651 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000652 netdev_err(wlandev->netdev,
653 "Failed to set supprates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700654 goto failed;
655 }
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400656
657 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100658 if (result) {
Johannes Stadlinger2cf1ba42014-06-19 21:20:13 +0200659 netdev_err(wlandev->netdev, "Failed to set txrates=%d.\n",
660 word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700661 goto failed;
662 }
663
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700664 /* Set the macmode so the frame setup code knows what to do */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100665 if (msg->bsstype.data == P80211ENUM_bsstype_independent) {
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400666 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700667 /* lets extend the data length a bit */
668 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
669 }
670
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700671 /* Enable the Port */
672 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100673 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000674 netdev_err(wlandev->netdev,
675 "Enable macport failed, result=%d.\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700676 goto failed;
677 }
678
679 msg->resultcode.data = P80211ENUM_resultcode_success;
680
681 goto done;
682failed:
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +0100683 pr_debug("Failed to set a config option, result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700684 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
685
686done:
687 result = 0;
688
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700689 return result;
690}
691
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700692/*----------------------------------------------------------------
693* prism2mgmt_readpda
694*
695* Collect the PDA data and put it in the message.
696*
697* Arguments:
698* wlandev wlan device structure
699* msgp ptr to msg buffer
700*
701* Returns:
702* 0 success and done
703* <0 success, but we're waiting for something to finish.
704* >0 an error occurred while handling the message.
705* Side effects:
706*
707* Call context:
708* process thread (usually)
709----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530710int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700711{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100712 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300713 struct p80211msg_p2req_readpda *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100714 int result;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700715
716 /* We only support collecting the PDA when in the FWLOAD
717 * state.
718 */
719 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000720 netdev_err(wlandev->netdev,
721 "PDA may only be read in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700722 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100723 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700724 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
725 } else {
726 /* Call drvr_readpda(), it handles the auxport enable
727 * and validating the returned PDA.
728 */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100729 result = hfa384x_drvr_readpda(hw,
730 msg->pda.data,
731 HFA384x_PDA_LEN_MAX);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700732 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000733 netdev_err(wlandev->netdev,
Johannes Stadlinger17b37542014-06-19 21:20:14 +0200734 "hfa384x_drvr_readpda() failed, result=%d\n",
735 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700736
737 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100738 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700739 msg->resultcode.status =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100740 P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700741 return 0;
742 }
743 msg->pda.status = P80211ENUM_msgitem_status_data_ok;
744 msg->resultcode.data = P80211ENUM_resultcode_success;
745 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
746 }
747
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700748 return 0;
749}
750
751/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700752* prism2mgmt_ramdl_state
753*
754* Establishes the beginning/end of a card RAM download session.
755*
756* It is expected that the ramdl_write() function will be called
757* one or more times between the 'enable' and 'disable' calls to
758* this function.
759*
760* Note: This function should not be called when a mac comm port
761* is active.
762*
763* Arguments:
764* wlandev wlan device structure
765* msgp ptr to msg buffer
766*
767* Returns:
768* 0 success and done
769* <0 success, but we're waiting for something to finish.
770* >0 an error occurred while handling the message.
771* Side effects:
772*
773* Call context:
774* process thread (usually)
775----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530776int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700777{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100778 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300779 struct p80211msg_p2req_ramdl_state *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700780
781 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000782 netdev_err(wlandev->netdev,
Johannes Stadlinger17b37542014-06-19 21:20:14 +0200783 "ramdl_state(): may only be called in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700784 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100785 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700786 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700787 return 0;
788 }
789
790 /*
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100791 ** Note: Interrupts are locked out if this is an AP and are NOT
792 ** locked out if this is a station.
793 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700794
795 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100796 if (msg->enable.data == P80211ENUM_truth_true) {
797 if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) {
798 msg->resultcode.data =
799 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700800 } else {
801 msg->resultcode.data = P80211ENUM_resultcode_success;
802 }
803 } else {
804 hfa384x_drvr_ramdl_disable(hw);
805 msg->resultcode.data = P80211ENUM_resultcode_success;
806 }
807
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700808 return 0;
809}
810
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700811/*----------------------------------------------------------------
812* prism2mgmt_ramdl_write
813*
814* Writes a buffer to the card RAM using the download state. This
815* is for writing code to card RAM. To just read or write raw data
816* use the aux functions.
817*
818* Arguments:
819* wlandev wlan device structure
820* msgp ptr to msg buffer
821*
822* Returns:
823* 0 success and done
824* <0 success, but we're waiting for something to finish.
825* >0 an error occurred while handling the message.
826* Side effects:
827*
828* Call context:
829* process thread (usually)
830----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530831int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700832{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100833 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300834 struct p80211msg_p2req_ramdl_write *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100835 u32 addr;
836 u32 len;
837 u8 *buf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700838
839 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000840 netdev_err(wlandev->netdev,
Johannes Stadlinger17b37542014-06-19 21:20:14 +0200841 "ramdl_write(): may only be called in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700842 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100843 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700844 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700845 return 0;
846 }
847
848 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
849 /* first validate the length */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100850 if (msg->len.data > sizeof(msg->data.data)) {
851 msg->resultcode.status =
852 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700853 return 0;
854 }
855 /* call the hfa384x function to do the write */
856 addr = msg->addr.data;
857 len = msg->len.data;
858 buf = msg->data.data;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100859 if (hfa384x_drvr_ramdl_write(hw, addr, buf, len))
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700860 msg->resultcode.data = P80211ENUM_resultcode_refused;
861
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700862 msg->resultcode.data = P80211ENUM_resultcode_success;
863
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700864 return 0;
865}
866
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700867/*----------------------------------------------------------------
868* prism2mgmt_flashdl_state
869*
870* Establishes the beginning/end of a card Flash download session.
871*
872* It is expected that the flashdl_write() function will be called
873* one or more times between the 'enable' and 'disable' calls to
874* this function.
875*
876* Note: This function should not be called when a mac comm port
877* is active.
878*
879* Arguments:
880* wlandev wlan device structure
881* msgp ptr to msg buffer
882*
883* Returns:
884* 0 success and done
885* <0 success, but we're waiting for something to finish.
886* >0 an error occurred while handling the message.
887* Side effects:
888*
889* Call context:
890* process thread (usually)
891----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530892int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700893{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100894 int result = 0;
895 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300896 struct p80211msg_p2req_flashdl_state *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700897
898 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000899 netdev_err(wlandev->netdev,
Johannes Stadlinger17b37542014-06-19 21:20:14 +0200900 "flashdl_state(): may only be called in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700901 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100902 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700903 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700904 return 0;
905 }
906
907 /*
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100908 ** Note: Interrupts are locked out if this is an AP and are NOT
909 ** locked out if this is a station.
910 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700911
912 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100913 if (msg->enable.data == P80211ENUM_truth_true) {
914 if (hfa384x_drvr_flashdl_enable(hw)) {
915 msg->resultcode.data =
916 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700917 } else {
918 msg->resultcode.data = P80211ENUM_resultcode_success;
919 }
920 } else {
921 hfa384x_drvr_flashdl_disable(hw);
922 msg->resultcode.data = P80211ENUM_resultcode_success;
923 /* NOTE: At this point, the MAC is in the post-reset
924 * state and the driver is in the fwload state.
925 * We need to get the MAC back into the fwload
926 * state. To do this, we set the nsdstate to HWPRESENT
927 * and then call the ifstate function to redo everything
928 * that got us into the fwload state.
929 */
930 wlandev->msdstate = WLAN_MSD_HWPRESENT;
931 result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
932 if (result != P80211ENUM_resultcode_success) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000933 netdev_err(wlandev->netdev,
Johannes Stadlinger17b37542014-06-19 21:20:14 +0200934 "prism2sta_ifstate(fwload) failed, P80211ENUM_resultcode=%d\n",
935 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700936 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100937 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700938 result = -1;
939 }
940 }
941
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700942 return 0;
943}
944
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700945/*----------------------------------------------------------------
946* prism2mgmt_flashdl_write
947*
948*
949*
950* Arguments:
951* wlandev wlan device structure
952* msgp ptr to msg buffer
953*
954* Returns:
955* 0 success and done
956* <0 success, but we're waiting for something to finish.
957* >0 an error occurred while handling the message.
958* Side effects:
959*
960* Call context:
961* process thread (usually)
962----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530963int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700964{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100965 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300966 struct p80211msg_p2req_flashdl_write *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100967 u32 addr;
968 u32 len;
969 u8 *buf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700970
971 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000972 netdev_err(wlandev->netdev,
Johannes Stadlinger17b37542014-06-19 21:20:14 +0200973 "flashdl_write(): may only be called in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700974 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100975 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700976 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700977 return 0;
978 }
979
980 /*
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100981 ** Note: Interrupts are locked out if this is an AP and are NOT
982 ** locked out if this is a station.
983 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700984
985 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
986 /* first validate the length */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100987 if (msg->len.data > sizeof(msg->data.data)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700988 msg->resultcode.status =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100989 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700990 return 0;
991 }
992 /* call the hfa384x function to do the write */
993 addr = msg->addr.data;
994 len = msg->len.data;
995 buf = msg->data.data;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100996 if (hfa384x_drvr_flashdl_write(hw, addr, buf, len))
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700997 msg->resultcode.data = P80211ENUM_resultcode_refused;
998
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700999 msg->resultcode.data = P80211ENUM_resultcode_success;
1000
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001001 return 0;
1002}
1003
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001004/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001005* prism2mgmt_autojoin
1006*
1007* Associate with an ESS.
1008*
1009* Arguments:
1010* wlandev wlan device structure
1011* msgp ptr to msg buffer
1012*
1013* Returns:
1014* 0 success and done
1015* <0 success, but we're waiting for something to finish.
1016* >0 an error occurred while handling the message.
1017* Side effects:
1018*
1019* Call context:
1020* process thread (usually)
1021* interrupt
1022----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +05301023int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001024{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001025 hfa384x_t *hw = wlandev->priv;
1026 int result = 0;
1027 u16 reg;
1028 u16 port_type;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -03001029 struct p80211msg_lnxreq_autojoin *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001030 p80211pstrd_t *pstr;
1031 u8 bytebuf[256];
Himangi Saraogib2119912013-11-02 18:11:44 +05301032 struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001033
1034 wlandev->macmode = WLAN_MACMODE_NONE;
1035
1036 /* Set the SSID */
1037 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
1038
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001039 /* Disable the Port */
1040 hfa384x_drvr_disable(hw, 0);
1041
1042 /*** STATION ***/
1043 /* Set the TxRates */
1044 hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
1045
1046 /* Set the auth type */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001047 if (msg->authtype.data == P80211ENUM_authalg_sharedkey)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001048 reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001049 else
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001050 reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001051
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001052 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
1053
1054 /* Set the ssid */
1055 memset(bytebuf, 0, 256);
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001056 pstr = (p80211pstrd_t *) &(msg->ssid.data);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001057 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001058 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
1059 bytebuf,
1060 HFA384x_RID_CNFDESIREDSSID_LEN);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001061 port_type = HFA384x_PORTTYPE_BSS;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001062 /* Set the PortType */
1063 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
1064
1065 /* Enable the Port */
1066 hfa384x_drvr_enable(hw, 0);
1067
1068 /* Set the resultcode */
1069 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1070 msg->resultcode.data = P80211ENUM_resultcode_success;
1071
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001072 return result;
1073}
1074
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001075/*----------------------------------------------------------------
1076* prism2mgmt_wlansniff
1077*
1078* Start or stop sniffing.
1079*
1080* Arguments:
1081* wlandev wlan device structure
1082* msgp ptr to msg buffer
1083*
1084* Returns:
1085* 0 success and done
1086* <0 success, but we're waiting for something to finish.
1087* >0 an error occurred while handling the message.
1088* Side effects:
1089*
1090* Call context:
1091* process thread (usually)
1092* interrupt
1093----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +05301094int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001095{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001096 int result = 0;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -03001097 struct p80211msg_lnxreq_wlansniff *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001098
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001099 hfa384x_t *hw = wlandev->priv;
1100 u16 word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001101
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001102 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001103 switch (msg->enable.data) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001104 case P80211ENUM_truth_false:
1105 /* Confirm that we're in monitor mode */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001106 if (wlandev->netdev->type == ARPHRD_ETHER) {
1107 msg->resultcode.data =
1108 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001109 result = 0;
1110 goto exit;
1111 }
1112 /* Disable monitor mode */
1113 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001114 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301115 pr_debug("failed to disable monitor mode, result=%d\n",
1116 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001117 goto failed;
1118 }
1119 /* Disable port 0 */
1120 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001121 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301122 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001123 ("failed to disable port 0 after sniffing, result=%d\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301124 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001125 goto failed;
1126 }
1127 /* Clear the driver state */
1128 wlandev->netdev->type = ARPHRD_ETHER;
1129
1130 /* Restore the wepflags */
1131 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001132 HFA384x_RID_CNFWEPFLAGS,
1133 hw->presniff_wepflags);
1134 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301135 pr_debug
1136 ("failed to restore wepflags=0x%04x, result=%d\n",
1137 hw->presniff_wepflags, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001138 goto failed;
1139 }
1140
1141 /* Set the port to its prior type and enable (if necessary) */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001142 if (hw->presniff_port_type != 0) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001143 word = hw->presniff_port_type;
1144 result = hfa384x_drvr_setconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001145 HFA384x_RID_CNFPORTTYPE,
1146 word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001147 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301148 pr_debug
1149 ("failed to restore porttype, result=%d\n",
1150 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001151 goto failed;
1152 }
1153
1154 /* Enable the port */
1155 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001156 if (result) {
Sebastian Wankerl25c97da2013-01-20 16:30:54 +01001157 pr_debug("failed to enable port to presniff setting, result=%d\n",
1158 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001159 goto failed;
1160 }
1161 } else {
1162 result = hfa384x_drvr_disable(hw, 0);
1163
1164 }
1165
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +10001166 netdev_info(wlandev->netdev, "monitor mode disabled\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001167 msg->resultcode.data = P80211ENUM_resultcode_success;
1168 result = 0;
1169 goto exit;
1170 break;
1171 case P80211ENUM_truth_true:
1172 /* Disable the port (if enabled), only check Port 0 */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001173 if (hw->port_enabled[0]) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001174 if (wlandev->netdev->type == ARPHRD_ETHER) {
1175 /* Save macport 0 state */
1176 result = hfa384x_drvr_getconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001177 HFA384x_RID_CNFPORTTYPE,
1178 &(hw->presniff_port_type));
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001179 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301180 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001181 ("failed to read porttype, result=%d\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301182 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001183 goto failed;
1184 }
1185 /* Save the wepflags state */
1186 result = hfa384x_drvr_getconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001187 HFA384x_RID_CNFWEPFLAGS,
1188 &(hw->presniff_wepflags));
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001189 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301190 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001191 ("failed to read wepflags, result=%d\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301192 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001193 goto failed;
1194 }
1195 hfa384x_drvr_stop(hw);
1196 result = hfa384x_drvr_start(hw);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001197 if (result) {
Sebastian Wankerl25c97da2013-01-20 16:30:54 +01001198 pr_debug("failed to restart the card for sniffing, result=%d\n",
1199 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001200 goto failed;
1201 }
1202 } else {
1203 /* Disable the port */
1204 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001205 if (result) {
Sebastian Wankerl25c97da2013-01-20 16:30:54 +01001206 pr_debug("failed to enable port for sniffing, result=%d\n",
1207 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001208 goto failed;
1209 }
1210 }
1211 } else {
1212 hw->presniff_port_type = 0;
1213 }
1214
1215 /* Set the channel we wish to sniff */
1216 word = msg->channel.data;
1217 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001218 HFA384x_RID_CNFOWNCHANNEL,
1219 word);
1220 hw->sniff_channel = word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001221
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001222 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301223 pr_debug("failed to set channel %d, result=%d\n",
1224 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001225 goto failed;
1226 }
1227
1228 /* Now if we're already sniffing, we can skip the rest */
1229 if (wlandev->netdev->type != ARPHRD_ETHER) {
1230 /* Set the port type to pIbss */
1231 word = HFA384x_PORTTYPE_PSUEDOIBSS;
1232 result = hfa384x_drvr_setconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001233 HFA384x_RID_CNFPORTTYPE,
1234 word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001235 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301236 pr_debug
1237 ("failed to set porttype %d, result=%d\n",
1238 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001239 goto failed;
1240 }
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001241 if ((msg->keepwepflags.status ==
1242 P80211ENUM_msgitem_status_data_ok)
1243 && (msg->keepwepflags.data !=
1244 P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001245 /* Set the wepflags for no decryption */
1246 word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001247 HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
1248 result =
1249 hfa384x_drvr_setconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001250 HFA384x_RID_CNFWEPFLAGS,
1251 word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001252 }
1253
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001254 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301255 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001256 ("failed to set wepflags=0x%04x, result=%d\n",
1257 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001258 goto failed;
1259 }
1260 }
1261
1262 /* Do we want to strip the FCS in monitor mode? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001263 if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok)
1264 && (msg->stripfcs.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001265 hw->sniff_fcs = 0;
1266 } else {
1267 hw->sniff_fcs = 1;
1268 }
1269
1270 /* Do we want to truncate the packets? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001271 if (msg->packet_trunc.status ==
1272 P80211ENUM_msgitem_status_data_ok) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001273 hw->sniff_truncate = msg->packet_trunc.data;
1274 } else {
1275 hw->sniff_truncate = 0;
1276 }
1277
1278 /* Enable the port */
1279 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001280 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301281 pr_debug
1282 ("failed to enable port for sniffing, result=%d\n",
1283 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001284 goto failed;
1285 }
1286 /* Enable monitor mode */
1287 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001288 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301289 pr_debug("failed to enable monitor mode, result=%d\n",
1290 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001291 goto failed;
1292 }
1293
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001294 if (wlandev->netdev->type == ARPHRD_ETHER)
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +10001295 netdev_info(wlandev->netdev, "monitor mode enabled\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001296
1297 /* Set the driver state */
1298 /* Do we want the prism2 header? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001299 if ((msg->prismheader.status ==
1300 P80211ENUM_msgitem_status_data_ok)
1301 && (msg->prismheader.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001302 hw->sniffhdr = 0;
1303 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001304 } else
1305 if ((msg->wlanheader.status ==
1306 P80211ENUM_msgitem_status_data_ok)
1307 && (msg->wlanheader.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001308 hw->sniffhdr = 1;
1309 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1310 } else {
1311 wlandev->netdev->type = ARPHRD_IEEE80211;
1312 }
1313
1314 msg->resultcode.data = P80211ENUM_resultcode_success;
1315 result = 0;
1316 goto exit;
1317 break;
1318 default:
1319 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1320 result = 0;
1321 goto exit;
1322 break;
1323 }
1324
1325failed:
1326 msg->resultcode.data = P80211ENUM_resultcode_refused;
1327 result = 0;
1328exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001329 return result;
1330}