blob: d110b362c3bd27b3f0695f6e499bb0321db6f96c [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,
159 "setconfig(ROAMINGMODE) failed. result=%d\n", result);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100160 msg->resultcode.data =
161 P80211ENUM_resultcode_implementation_failure;
162 goto exit;
163 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700164
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100165 /* active or passive? */
166 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
167 hw->ident_sta_fw.minor,
168 hw->ident_sta_fw.variant) >
169 HFA384x_FIRMWARE_VERSION(1, 5, 0)) {
170 if (msg->scantype.data != P80211ENUM_scantype_active)
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100171 word = cpu_to_le16(msg->maxchanneltime.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100172 else
173 word = 0;
174
175 result =
176 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL,
177 word);
178 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000179 netdev_warn(wlandev->netdev,
180 "Passive scan not supported with "
181 "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,
276 "drvr_enable(0) failed. result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700277 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100278 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700279 goto exit;
280 }
281 istmpenable = 1;
282 }
283
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100284 /* Figure out our timeout first Kus, then HZ */
285 timeout = msg->channellist.data.len * msg->maxchanneltime.data;
286 timeout = (timeout * HZ) / 1000;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700287
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100288 /* Issue the scan request */
289 hw->scanflag = 0;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700290
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100291 result = hfa384x_drvr_setconfig(hw,
292 HFA384x_RID_HOSTSCAN, &scanreq,
293 sizeof(hfa384x_HostScanRequest_data_t));
294 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000295 netdev_err(wlandev->netdev,
296 "setconfig(SCANREQUEST) failed. result=%d\n", result);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100297 msg->resultcode.data =
298 P80211ENUM_resultcode_implementation_failure;
299 goto exit;
300 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700301
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100302 /* sleep until info frame arrives */
303 wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700304
305 msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
306 if (hw->scanflag == -1)
307 hw->scanflag = 0;
308
309 msg->numbss.data = hw->scanflag;
310
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100311 hw->scanflag = 0;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700312
313 /* Disable port if we temporarily enabled it. */
314 if (istmpenable) {
315 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100316 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000317 netdev_err(wlandev->netdev,
318 "drvr_disable(0) failed. result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700319 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100320 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700321 goto exit;
322 }
323 }
324
325 /* restore original roaming mode */
326 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
327 roamingmode);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100328 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000329 netdev_err(wlandev->netdev,
330 "setconfig(ROAMMODE) failed. result=%d\n", result);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100331 msg->resultcode.data =
332 P80211ENUM_resultcode_implementation_failure;
333 goto exit;
334 }
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700335
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100336 result = 0;
337 msg->resultcode.data = P80211ENUM_resultcode_success;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700338
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100339exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700340 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
341
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700342 return result;
343}
344
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700345/*----------------------------------------------------------------
346* prism2mgmt_scan_results
347*
348* Retrieve the BSS description for one of the BSSs identified in
349* a scan.
350*
351* Arguments:
352* wlandev wlan device structure
353* msgp ptr to msg buffer
354*
355* Returns:
356* 0 success and done
357* <0 success, but we're waiting for something to finish.
358* >0 an error occurred while handling the message.
359* Side effects:
360*
361* Call context:
362* process thread (usually)
363* interrupt
364----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530365int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700366{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100367 int result = 0;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300368 struct p80211msg_dot11req_scan_results *req;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100369 hfa384x_t *hw = wlandev->priv;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700370 hfa384x_HScanResultSub_t *item = NULL;
371
372 int count;
373
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300374 req = (struct p80211msg_dot11req_scan_results *) msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700375
376 req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
377
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100378 if (!hw->scanresults) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000379 netdev_err(wlandev->netdev,
380 "dot11req_scan_results can only be used after "
381 "a successful dot11req_scan.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700382 result = 2;
383 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
384 goto exit;
385 }
386
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100387 count = (hw->scanresults->framelen - 3) / 32;
Dan Carpenterbb46f132012-04-18 09:48:59 +0300388 if (count > HFA384x_SCANRESULT_MAX)
389 count = HFA384x_SCANRESULT_MAX;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700390
391 if (req->bssindex.data >= count) {
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +0100392 pr_debug("requested index (%d) out of range (%d)\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +0530393 req->bssindex.data, count);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700394 result = 2;
395 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
396 goto exit;
397 }
398
399 item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
400 /* signal and noise */
401 req->signal.status = P80211ENUM_msgitem_status_data_ok;
402 req->noise.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100403 req->signal.data = le16_to_cpu(item->sl);
404 req->noise.data = le16_to_cpu(item->anl);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700405
406 /* BSSID */
407 req->bssid.status = P80211ENUM_msgitem_status_data_ok;
408 req->bssid.data.len = WLAN_BSSID_LEN;
409 memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
410
411 /* SSID */
412 req->ssid.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100413 req->ssid.data.len = le16_to_cpu(item->ssid.len);
Tormod Volden811a37e2013-01-09 22:23:32 +0100414 req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700415 memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
416
417 /* supported rates */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100418 for (count = 0; count < 10; count++)
419 if (item->supprates[count] == 0)
420 break;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700421
422#define REQBASICRATE(N) \
Sebastian Wankerl52070c72013-01-20 16:24:45 +0100423 do { \
424 if ((count >= N) && DOT11_RATE5_ISBASIC_GET( \
425 item->supprates[(N)-1])) { \
426 req->basicrate ## N .data = item->supprates[(N)-1]; \
427 req->basicrate ## N .status = \
428 P80211ENUM_msgitem_status_data_ok; \
429 } \
430 } while (0)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700431
432 REQBASICRATE(1);
433 REQBASICRATE(2);
434 REQBASICRATE(3);
435 REQBASICRATE(4);
436 REQBASICRATE(5);
437 REQBASICRATE(6);
438 REQBASICRATE(7);
439 REQBASICRATE(8);
440
441#define REQSUPPRATE(N) \
Sebastian Wankerl52070c72013-01-20 16:24:45 +0100442 do { \
443 if (count >= N) { \
444 req->supprate ## N .data = item->supprates[(N)-1]; \
445 req->supprate ## N .status = \
446 P80211ENUM_msgitem_status_data_ok; \
447 } \
448 } while (0)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700449
450 REQSUPPRATE(1);
451 REQSUPPRATE(2);
452 REQSUPPRATE(3);
453 REQSUPPRATE(4);
454 REQSUPPRATE(5);
455 REQSUPPRATE(6);
456 REQSUPPRATE(7);
457 REQSUPPRATE(8);
458
459 /* beacon period */
460 req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100461 req->beaconperiod.data = le16_to_cpu(item->bcnint);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700462
463 /* timestamps */
464 req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
465 req->timestamp.data = jiffies;
466 req->localtime.status = P80211ENUM_msgitem_status_data_ok;
467 req->localtime.data = jiffies;
468
469 /* atim window */
470 req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100471 req->ibssatimwindow.data = le16_to_cpu(item->atim);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700472
473 /* Channel */
474 req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100475 req->dschannel.data = le16_to_cpu(item->chid);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700476
477 /* capinfo bits */
Moritz Muehlenhoff18c7f792009-02-18 19:50:07 +0100478 count = le16_to_cpu(item->capinfo);
Karl Reltoncb3126e2010-06-03 23:04:06 +0100479 req->capinfo.status = P80211ENUM_msgitem_status_data_ok;
480 req->capinfo.data = count;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700481
482 /* privacy flag */
483 req->privacy.status = P80211ENUM_msgitem_status_data_ok;
484 req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
485
486 /* cfpollable */
487 req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
488 req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
489
490 /* cfpollreq */
491 req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
492 req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
493
494 /* bsstype */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100495 req->bsstype.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700496 req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100497 P80211ENUM_bsstype_infrastructure : P80211ENUM_bsstype_independent;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700498
499 result = 0;
500 req->resultcode.data = P80211ENUM_resultcode_success;
501
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100502exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700503 return result;
504}
505
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700506/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700507* prism2mgmt_start
508*
509* Start a BSS. Any station can do this for IBSS, only AP for ESS.
510*
511* Arguments:
512* wlandev wlan device structure
513* msgp ptr to msg buffer
514*
515* Returns:
516* 0 success and done
517* <0 success, but we're waiting for something to finish.
518* >0 an error occurred while handling the message.
519* Side effects:
520*
521* Call context:
522* process thread (usually)
523* interrupt
524----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530525int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700526{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100527 int result = 0;
528 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300529 struct p80211msg_dot11req_start *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700530
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100531 p80211pstrd_t *pstr;
532 u8 bytebuf[80];
Himangi Saraogib2119912013-11-02 18:11:44 +0530533 struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100534 u16 word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700535
536 wlandev->macmode = WLAN_MACMODE_NONE;
537
538 /* Set the SSID */
539 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
540
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400541 /*** ADHOC IBSS ***/
542 /* see if current f/w is less than 8c3 */
543 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
544 hw->ident_sta_fw.minor,
545 hw->ident_sta_fw.variant) <
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100546 HFA384x_FIRMWARE_VERSION(0, 8, 3)) {
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400547 /* Ad-Hoc not quite supported on Prism2 */
548 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
549 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700550 goto done;
551 }
552
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700553 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
554
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400555 /*** STATION ***/
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700556 /* Set the REQUIRED config items */
557 /* SSID */
Andrew Elwellef1a0ed2010-02-18 23:56:12 +0100558 pstr = (p80211pstrd_t *) &(msg->ssid.data);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700559 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100560 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
561 bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
562 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000563 netdev_err(wlandev->netdev, "Failed to set CnfOwnSSID\n");
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400564 goto failed;
565 }
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100566 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
567 bytebuf,
568 HFA384x_RID_CNFDESIREDSSID_LEN);
569 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000570 netdev_err(wlandev->netdev, "Failed to set CnfDesiredSSID\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700571 goto failed;
572 }
573
574 /* bsstype - we use the default in the ap firmware */
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400575 /* IBSS port */
576 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700577
578 /* beacon period */
579 word = msg->beaconperiod.data;
Solomon Peachyaaad4302008-10-29 10:42:53 -0400580 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100581 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000582 netdev_err(wlandev->netdev,
583 "Failed to set beacon period=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700584 goto failed;
585 }
586
587 /* dschannel */
588 word = msg->dschannel.data;
589 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100590 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000591 netdev_err(wlandev->netdev,
592 "Failed to set channel=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700593 goto failed;
594 }
595 /* Basic rates */
596 word = p80211rate_to_p2bit(msg->basicrate1.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100597 if (msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700598 word |= p80211rate_to_p2bit(msg->basicrate2.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100599
600 if (msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700601 word |= p80211rate_to_p2bit(msg->basicrate3.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100602
603 if (msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700604 word |= p80211rate_to_p2bit(msg->basicrate4.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100605
606 if (msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700607 word |= p80211rate_to_p2bit(msg->basicrate5.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100608
609 if (msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700610 word |= p80211rate_to_p2bit(msg->basicrate6.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100611
612 if (msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700613 word |= p80211rate_to_p2bit(msg->basicrate7.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100614
615 if (msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700616 word |= p80211rate_to_p2bit(msg->basicrate8.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100617
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700618 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100619 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000620 netdev_err(wlandev->netdev,
621 "Failed to set basicrates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700622 goto failed;
623 }
624
625 /* Operational rates (supprates and txratecontrol) */
626 word = p80211rate_to_p2bit(msg->operationalrate1.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100627 if (msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700628 word |= p80211rate_to_p2bit(msg->operationalrate2.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100629
630 if (msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700631 word |= p80211rate_to_p2bit(msg->operationalrate3.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100632
633 if (msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700634 word |= p80211rate_to_p2bit(msg->operationalrate4.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100635
636 if (msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700637 word |= p80211rate_to_p2bit(msg->operationalrate5.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100638
639 if (msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700640 word |= p80211rate_to_p2bit(msg->operationalrate6.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100641
642 if (msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700643 word |= p80211rate_to_p2bit(msg->operationalrate7.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100644
645 if (msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700646 word |= p80211rate_to_p2bit(msg->operationalrate8.data);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100647
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700648 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100649 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000650 netdev_err(wlandev->netdev,
651 "Failed to set supprates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700652 goto failed;
653 }
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400654
655 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100656 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000657 netdev_err(wlandev->netdev, "Failed to set txrates=%d.\n", word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700658 goto failed;
659 }
660
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700661 /* Set the macmode so the frame setup code knows what to do */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100662 if (msg->bsstype.data == P80211ENUM_bsstype_independent) {
Solomon Peachy5db8dcc2008-10-27 11:14:02 -0400663 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700664 /* lets extend the data length a bit */
665 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
666 }
667
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700668 /* Enable the Port */
669 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100670 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000671 netdev_err(wlandev->netdev,
672 "Enable macport failed, result=%d.\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700673 goto failed;
674 }
675
676 msg->resultcode.data = P80211ENUM_resultcode_success;
677
678 goto done;
679failed:
Moritz Muehlenhoffa7cf7ba2009-02-08 02:01:00 +0100680 pr_debug("Failed to set a config option, result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700681 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
682
683done:
684 result = 0;
685
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700686 return result;
687}
688
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700689/*----------------------------------------------------------------
690* prism2mgmt_readpda
691*
692* Collect the PDA data and put it in the message.
693*
694* Arguments:
695* wlandev wlan device structure
696* msgp ptr to msg buffer
697*
698* Returns:
699* 0 success and done
700* <0 success, but we're waiting for something to finish.
701* >0 an error occurred while handling the message.
702* Side effects:
703*
704* Call context:
705* process thread (usually)
706----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530707int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700708{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100709 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300710 struct p80211msg_p2req_readpda *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100711 int result;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700712
713 /* We only support collecting the PDA when in the FWLOAD
714 * state.
715 */
716 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000717 netdev_err(wlandev->netdev,
718 "PDA may only be read in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700719 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100720 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700721 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
722 } else {
723 /* Call drvr_readpda(), it handles the auxport enable
724 * and validating the returned PDA.
725 */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100726 result = hfa384x_drvr_readpda(hw,
727 msg->pda.data,
728 HFA384x_PDA_LEN_MAX);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700729 if (result) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000730 netdev_err(wlandev->netdev,
731 "hfa384x_drvr_readpda() failed, "
732 "result=%d\n", result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700733
734 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100735 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700736 msg->resultcode.status =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100737 P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700738 return 0;
739 }
740 msg->pda.status = P80211ENUM_msgitem_status_data_ok;
741 msg->resultcode.data = P80211ENUM_resultcode_success;
742 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
743 }
744
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700745 return 0;
746}
747
748/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700749* prism2mgmt_ramdl_state
750*
751* Establishes the beginning/end of a card RAM download session.
752*
753* It is expected that the ramdl_write() function will be called
754* one or more times between the 'enable' and 'disable' calls to
755* this function.
756*
757* Note: This function should not be called when a mac comm port
758* is active.
759*
760* Arguments:
761* wlandev wlan device structure
762* msgp ptr to msg buffer
763*
764* Returns:
765* 0 success and done
766* <0 success, but we're waiting for something to finish.
767* >0 an error occurred while handling the message.
768* Side effects:
769*
770* Call context:
771* process thread (usually)
772----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530773int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700774{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100775 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300776 struct p80211msg_p2req_ramdl_state *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700777
778 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000779 netdev_err(wlandev->netdev,
780 "ramdl_state(): may only be called "
781 "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700782 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100783 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700784 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700785 return 0;
786 }
787
788 /*
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100789 ** Note: Interrupts are locked out if this is an AP and are NOT
790 ** locked out if this is a station.
791 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700792
793 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100794 if (msg->enable.data == P80211ENUM_truth_true) {
795 if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) {
796 msg->resultcode.data =
797 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700798 } else {
799 msg->resultcode.data = P80211ENUM_resultcode_success;
800 }
801 } else {
802 hfa384x_drvr_ramdl_disable(hw);
803 msg->resultcode.data = P80211ENUM_resultcode_success;
804 }
805
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700806 return 0;
807}
808
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700809/*----------------------------------------------------------------
810* prism2mgmt_ramdl_write
811*
812* Writes a buffer to the card RAM using the download state. This
813* is for writing code to card RAM. To just read or write raw data
814* use the aux functions.
815*
816* Arguments:
817* wlandev wlan device structure
818* msgp ptr to msg buffer
819*
820* Returns:
821* 0 success and done
822* <0 success, but we're waiting for something to finish.
823* >0 an error occurred while handling the message.
824* Side effects:
825*
826* Call context:
827* process thread (usually)
828----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530829int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700830{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100831 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300832 struct p80211msg_p2req_ramdl_write *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100833 u32 addr;
834 u32 len;
835 u8 *buf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700836
837 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000838 netdev_err(wlandev->netdev,
839 "ramdl_write(): may only be called "
840 "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700841 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100842 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700843 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700844 return 0;
845 }
846
847 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
848 /* first validate the length */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100849 if (msg->len.data > sizeof(msg->data.data)) {
850 msg->resultcode.status =
851 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700852 return 0;
853 }
854 /* call the hfa384x function to do the write */
855 addr = msg->addr.data;
856 len = msg->len.data;
857 buf = msg->data.data;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100858 if (hfa384x_drvr_ramdl_write(hw, addr, buf, len))
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700859 msg->resultcode.data = P80211ENUM_resultcode_refused;
860
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700861 msg->resultcode.data = P80211ENUM_resultcode_success;
862
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700863 return 0;
864}
865
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700866/*----------------------------------------------------------------
867* prism2mgmt_flashdl_state
868*
869* Establishes the beginning/end of a card Flash download session.
870*
871* It is expected that the flashdl_write() function will be called
872* one or more times between the 'enable' and 'disable' calls to
873* this function.
874*
875* Note: This function should not be called when a mac comm port
876* is active.
877*
878* Arguments:
879* wlandev wlan device structure
880* msgp ptr to msg buffer
881*
882* Returns:
883* 0 success and done
884* <0 success, but we're waiting for something to finish.
885* >0 an error occurred while handling the message.
886* Side effects:
887*
888* Call context:
889* process thread (usually)
890----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +0530891int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700892{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100893 int result = 0;
894 hfa384x_t *hw = wlandev->priv;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -0300895 struct p80211msg_p2req_flashdl_state *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700896
897 if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +1000898 netdev_err(wlandev->netdev,
899 "flashdl_state(): may only be called "
900 "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,
934 "prism2sta_ifstate(fwload) failed,"
935 "P80211ENUM_resultcode=%d\n", 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,
973 "flashdl_write(): may only be called "
974 "in the fwload state.\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700975 msg->resultcode.data =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100976 P80211ENUM_resultcode_implementation_failure;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700977 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700978 return 0;
979 }
980
981 /*
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100982 ** Note: Interrupts are locked out if this is an AP and are NOT
983 ** locked out if this is a station.
984 */
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700985
986 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
987 /* first validate the length */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100988 if (msg->len.data > sizeof(msg->data.data)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700989 msg->resultcode.status =
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100990 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700991 return 0;
992 }
993 /* call the hfa384x function to do the write */
994 addr = msg->addr.data;
995 len = msg->len.data;
996 buf = msg->data.data;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +0100997 if (hfa384x_drvr_flashdl_write(hw, addr, buf, len))
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -0700998 msg->resultcode.data = P80211ENUM_resultcode_refused;
999
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001000 msg->resultcode.data = P80211ENUM_resultcode_success;
1001
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001002 return 0;
1003}
1004
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001005/*----------------------------------------------------------------
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001006* prism2mgmt_autojoin
1007*
1008* Associate with an ESS.
1009*
1010* Arguments:
1011* wlandev wlan device structure
1012* msgp ptr to msg buffer
1013*
1014* Returns:
1015* 0 success and done
1016* <0 success, but we're waiting for something to finish.
1017* >0 an error occurred while handling the message.
1018* Side effects:
1019*
1020* Call context:
1021* process thread (usually)
1022* interrupt
1023----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +05301024int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001025{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001026 hfa384x_t *hw = wlandev->priv;
1027 int result = 0;
1028 u16 reg;
1029 u16 port_type;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -03001030 struct p80211msg_lnxreq_autojoin *msg = msgp;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001031 p80211pstrd_t *pstr;
1032 u8 bytebuf[256];
Himangi Saraogib2119912013-11-02 18:11:44 +05301033 struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001034
1035 wlandev->macmode = WLAN_MACMODE_NONE;
1036
1037 /* Set the SSID */
1038 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
1039
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001040 /* Disable the Port */
1041 hfa384x_drvr_disable(hw, 0);
1042
1043 /*** STATION ***/
1044 /* Set the TxRates */
1045 hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
1046
1047 /* Set the auth type */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001048 if (msg->authtype.data == P80211ENUM_authalg_sharedkey)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001049 reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001050 else
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001051 reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001052
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001053 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
1054
1055 /* Set the ssid */
1056 memset(bytebuf, 0, 256);
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001057 pstr = (p80211pstrd_t *) &(msg->ssid.data);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001058 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001059 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
1060 bytebuf,
1061 HFA384x_RID_CNFDESIREDSSID_LEN);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001062 port_type = HFA384x_PORTTYPE_BSS;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001063 /* Set the PortType */
1064 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
1065
1066 /* Enable the Port */
1067 hfa384x_drvr_enable(hw, 0);
1068
1069 /* Set the resultcode */
1070 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1071 msg->resultcode.data = P80211ENUM_resultcode_success;
1072
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001073 return result;
1074}
1075
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001076/*----------------------------------------------------------------
1077* prism2mgmt_wlansniff
1078*
1079* Start or stop sniffing.
1080*
1081* Arguments:
1082* wlandev wlan device structure
1083* msgp ptr to msg buffer
1084*
1085* Returns:
1086* 0 success and done
1087* <0 success, but we're waiting for something to finish.
1088* >0 an error occurred while handling the message.
1089* Side effects:
1090*
1091* Call context:
1092* process thread (usually)
1093* interrupt
1094----------------------------------------------------------------*/
Mithlesh Thukral297f06c2009-06-10 19:36:11 +05301095int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001096{
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001097 int result = 0;
Edgardo Hamesb6bb56e2010-08-02 16:20:39 -03001098 struct p80211msg_lnxreq_wlansniff *msg = msgp;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001099
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001100 hfa384x_t *hw = wlandev->priv;
1101 u16 word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001102
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001103 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001104 switch (msg->enable.data) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001105 case P80211ENUM_truth_false:
1106 /* Confirm that we're in monitor mode */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001107 if (wlandev->netdev->type == ARPHRD_ETHER) {
1108 msg->resultcode.data =
1109 P80211ENUM_resultcode_invalid_parameters;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001110 result = 0;
1111 goto exit;
1112 }
1113 /* Disable monitor mode */
1114 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001115 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301116 pr_debug("failed to disable monitor mode, result=%d\n",
1117 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001118 goto failed;
1119 }
1120 /* Disable port 0 */
1121 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001122 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301123 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001124 ("failed to disable port 0 after sniffing, result=%d\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301125 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001126 goto failed;
1127 }
1128 /* Clear the driver state */
1129 wlandev->netdev->type = ARPHRD_ETHER;
1130
1131 /* Restore the wepflags */
1132 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001133 HFA384x_RID_CNFWEPFLAGS,
1134 hw->presniff_wepflags);
1135 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301136 pr_debug
1137 ("failed to restore wepflags=0x%04x, result=%d\n",
1138 hw->presniff_wepflags, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001139 goto failed;
1140 }
1141
1142 /* Set the port to its prior type and enable (if necessary) */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001143 if (hw->presniff_port_type != 0) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001144 word = hw->presniff_port_type;
1145 result = hfa384x_drvr_setconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001146 HFA384x_RID_CNFPORTTYPE,
1147 word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001148 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301149 pr_debug
1150 ("failed to restore porttype, result=%d\n",
1151 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001152 goto failed;
1153 }
1154
1155 /* Enable the port */
1156 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001157 if (result) {
Sebastian Wankerl25c97da2013-01-20 16:30:54 +01001158 pr_debug("failed to enable port to presniff setting, result=%d\n",
1159 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001160 goto failed;
1161 }
1162 } else {
1163 result = hfa384x_drvr_disable(hw, 0);
1164
1165 }
1166
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +10001167 netdev_info(wlandev->netdev, "monitor mode disabled\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001168 msg->resultcode.data = P80211ENUM_resultcode_success;
1169 result = 0;
1170 goto exit;
1171 break;
1172 case P80211ENUM_truth_true:
1173 /* Disable the port (if enabled), only check Port 0 */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001174 if (hw->port_enabled[0]) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001175 if (wlandev->netdev->type == ARPHRD_ETHER) {
1176 /* Save macport 0 state */
1177 result = hfa384x_drvr_getconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001178 HFA384x_RID_CNFPORTTYPE,
1179 &(hw->presniff_port_type));
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001180 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301181 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001182 ("failed to read porttype, result=%d\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301183 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001184 goto failed;
1185 }
1186 /* Save the wepflags state */
1187 result = hfa384x_drvr_getconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001188 HFA384x_RID_CNFWEPFLAGS,
1189 &(hw->presniff_wepflags));
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001190 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301191 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001192 ("failed to read wepflags, result=%d\n",
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301193 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001194 goto failed;
1195 }
1196 hfa384x_drvr_stop(hw);
1197 result = hfa384x_drvr_start(hw);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001198 if (result) {
Sebastian Wankerl25c97da2013-01-20 16:30:54 +01001199 pr_debug("failed to restart the card for sniffing, result=%d\n",
1200 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001201 goto failed;
1202 }
1203 } else {
1204 /* Disable the port */
1205 result = hfa384x_drvr_disable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001206 if (result) {
Sebastian Wankerl25c97da2013-01-20 16:30:54 +01001207 pr_debug("failed to enable port for sniffing, result=%d\n",
1208 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001209 goto failed;
1210 }
1211 }
1212 } else {
1213 hw->presniff_port_type = 0;
1214 }
1215
1216 /* Set the channel we wish to sniff */
1217 word = msg->channel.data;
1218 result = hfa384x_drvr_setconfig16(hw,
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001219 HFA384x_RID_CNFOWNCHANNEL,
1220 word);
1221 hw->sniff_channel = word;
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001222
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001223 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301224 pr_debug("failed to set channel %d, result=%d\n",
1225 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001226 goto failed;
1227 }
1228
1229 /* Now if we're already sniffing, we can skip the rest */
1230 if (wlandev->netdev->type != ARPHRD_ETHER) {
1231 /* Set the port type to pIbss */
1232 word = HFA384x_PORTTYPE_PSUEDOIBSS;
1233 result = hfa384x_drvr_setconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001234 HFA384x_RID_CNFPORTTYPE,
1235 word);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001236 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301237 pr_debug
1238 ("failed to set porttype %d, result=%d\n",
1239 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001240 goto failed;
1241 }
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001242 if ((msg->keepwepflags.status ==
1243 P80211ENUM_msgitem_status_data_ok)
1244 && (msg->keepwepflags.data !=
1245 P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001246 /* Set the wepflags for no decryption */
1247 word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001248 HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
1249 result =
1250 hfa384x_drvr_setconfig16(hw,
Andrew Elwellef1a0ed2010-02-18 23:56:12 +01001251 HFA384x_RID_CNFWEPFLAGS,
1252 word);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001253 }
1254
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001255 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301256 pr_debug
Johan Meiringf83dfd02010-11-06 18:23:44 +02001257 ("failed to set wepflags=0x%04x, result=%d\n",
1258 word, result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001259 goto failed;
1260 }
1261 }
1262
1263 /* Do we want to strip the FCS in monitor mode? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001264 if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok)
1265 && (msg->stripfcs.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001266 hw->sniff_fcs = 0;
1267 } else {
1268 hw->sniff_fcs = 1;
1269 }
1270
1271 /* Do we want to truncate the packets? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001272 if (msg->packet_trunc.status ==
1273 P80211ENUM_msgitem_status_data_ok) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001274 hw->sniff_truncate = msg->packet_trunc.data;
1275 } else {
1276 hw->sniff_truncate = 0;
1277 }
1278
1279 /* Enable the port */
1280 result = hfa384x_drvr_enable(hw, 0);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001281 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301282 pr_debug
1283 ("failed to enable port for sniffing, result=%d\n",
1284 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001285 goto failed;
1286 }
1287 /* Enable monitor mode */
1288 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001289 if (result) {
Mithlesh Thukral75f49e02009-05-25 19:06:16 +05301290 pr_debug("failed to enable monitor mode, result=%d\n",
1291 result);
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001292 goto failed;
1293 }
1294
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001295 if (wlandev->netdev->type == ARPHRD_ETHER)
Vitaly Osipov02d9b1e2014-05-18 16:59:36 +10001296 netdev_info(wlandev->netdev, "monitor mode enabled\n");
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001297
1298 /* Set the driver state */
1299 /* Do we want the prism2 header? */
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001300 if ((msg->prismheader.status ==
1301 P80211ENUM_msgitem_status_data_ok)
1302 && (msg->prismheader.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001303 hw->sniffhdr = 0;
1304 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
Moritz Muehlenhoff450238e2009-02-08 02:20:48 +01001305 } else
1306 if ((msg->wlanheader.status ==
1307 P80211ENUM_msgitem_status_data_ok)
1308 && (msg->wlanheader.data == P80211ENUM_truth_true)) {
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001309 hw->sniffhdr = 1;
1310 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1311 } else {
1312 wlandev->netdev->type = ARPHRD_IEEE80211;
1313 }
1314
1315 msg->resultcode.data = P80211ENUM_resultcode_success;
1316 result = 0;
1317 goto exit;
1318 break;
1319 default:
1320 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1321 result = 0;
1322 goto exit;
1323 break;
1324 }
1325
1326failed:
1327 msg->resultcode.data = P80211ENUM_resultcode_refused;
1328 result = 0;
1329exit:
Greg Kroah-Hartman00b3ed12008-10-02 11:29:28 -07001330 return result;
1331}