1/* 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 60#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> 66#include <linux/wireless.h> 67#include <linux/netdevice.h> 68#include <linux/delay.h> 69#include <linux/io.h> 70#include <asm/byteorder.h> 71#include <linux/random.h> 72#include <linux/usb.h> 73#include <linux/bitops.h> 74 75#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 86/* Converts 802.11 format rate specifications to prism2 */ 87#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) 91 92/*---------------------------------------------------------------- 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----------------------------------------------------------------*/ 116int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp) 117{ 118 int result = 0; 119 hfa384x_t *hw = wlandev->priv; 120 struct p80211msg_dot11req_scan *msg = msgp; 121 u16 roamingmode, word; 122 int i, timeout; 123 int istmpenable = 0; 124 125 hfa384x_HostScanRequest_data_t scanreq; 126 127 /* 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)) { 132 printk(KERN_ERR 133 "HostScan not supported with current firmware (<1.3.2).\n"); 134 result = 1; 135 msg->resultcode.data = P80211ENUM_resultcode_not_supported; 136 goto exit; 137 } 138 139 memset(&scanreq, 0, sizeof(scanreq)); 140 141 /* save current roaming mode */ 142 result = hfa384x_drvr_getconfig16(hw, 143 HFA384x_RID_CNFROAMINGMODE, 144 &roamingmode); 145 if (result) { 146 printk(KERN_ERR "getconfig(ROAMMODE) failed. result=%d\n", 147 result); 148 msg->resultcode.data = 149 P80211ENUM_resultcode_implementation_failure; 150 goto exit; 151 } 152 153 /* 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) { 158 printk(KERN_ERR "setconfig(ROAMINGMODE) failed. result=%d\n", 159 result); 160 msg->resultcode.data = 161 P80211ENUM_resultcode_implementation_failure; 162 goto exit; 163 } 164 165 /* 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) 171 word = cpu_to_le16(msg->maxchanneltime.data); 172 else 173 word = 0; 174 175 result = 176 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, 177 word); 178 if (result) { 179 printk(KERN_WARNING "Passive scan not supported with " 180 "current firmware. (<1.5.1)\n"); 181 } 182 } 183 184 /* set up the txrate to be 2MBPS. Should be fastest basicrate... */ 185 word = HFA384x_RATEBIT_2; 186 scanreq.txRate = cpu_to_le16(word); 187 188 /* set up the channel list */ 189 word = 0; 190 for (i = 0; i < msg->channellist.data.len; i++) { 191 u8 channel = msg->channellist.data.data[i]; 192 if (channel > 14) 193 continue; 194 /* channel 1 is BIT 0 ... channel 14 is BIT 13 */ 195 word |= (1 << (channel - 1)); 196 } 197 scanreq.channelList = cpu_to_le16(word); 198 199 /* set up the ssid, if present. */ 200 scanreq.ssid.len = cpu_to_le16(msg->ssid.data.len); 201 memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len); 202 203 /* Enable the MAC port if it's not already enabled */ 204 result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word); 205 if (result) { 206 printk(KERN_ERR "getconfig(PORTSTATUS) failed. " 207 "result=%d\n", result); 208 msg->resultcode.data = 209 P80211ENUM_resultcode_implementation_failure; 210 goto exit; 211 } 212 if (word == HFA384x_PORTSTATUS_DISABLED) { 213 u16 wordbuf[17]; 214 215 result = hfa384x_drvr_setconfig16(hw, 216 HFA384x_RID_CNFROAMINGMODE, 217 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM); 218 if (result) { 219 printk(KERN_ERR 220 "setconfig(ROAMINGMODE) failed. result=%d\n", 221 result); 222 msg->resultcode.data = 223 P80211ENUM_resultcode_implementation_failure; 224 goto exit; 225 } 226 /* Construct a bogus SSID and assign it to OwnSSID and 227 * DesiredSSID 228 */ 229 wordbuf[0] = cpu_to_le16(WLAN_SSID_MAXLEN); 230 get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN); 231 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID, 232 wordbuf, 233 HFA384x_RID_CNFOWNSSID_LEN); 234 if (result) { 235 printk(KERN_ERR "Failed to set OwnSSID.\n"); 236 msg->resultcode.data = 237 P80211ENUM_resultcode_implementation_failure; 238 goto exit; 239 } 240 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, 241 wordbuf, 242 HFA384x_RID_CNFDESIREDSSID_LEN); 243 if (result) { 244 printk(KERN_ERR "Failed to set DesiredSSID.\n"); 245 msg->resultcode.data = 246 P80211ENUM_resultcode_implementation_failure; 247 goto exit; 248 } 249 /* bsstype */ 250 result = hfa384x_drvr_setconfig16(hw, 251 HFA384x_RID_CNFPORTTYPE, 252 HFA384x_PORTTYPE_IBSS); 253 if (result) { 254 printk(KERN_ERR "Failed to set CNFPORTTYPE.\n"); 255 msg->resultcode.data = 256 P80211ENUM_resultcode_implementation_failure; 257 goto exit; 258 } 259 /* ibss options */ 260 result = hfa384x_drvr_setconfig16(hw, 261 HFA384x_RID_CREATEIBSS, 262 HFA384x_CREATEIBSS_JOINCREATEIBSS); 263 if (result) { 264 printk(KERN_ERR "Failed to set CREATEIBSS.\n"); 265 msg->resultcode.data = 266 P80211ENUM_resultcode_implementation_failure; 267 goto exit; 268 } 269 result = hfa384x_drvr_enable(hw, 0); 270 if (result) { 271 printk(KERN_ERR "drvr_enable(0) failed. " 272 "result=%d\n", result); 273 msg->resultcode.data = 274 P80211ENUM_resultcode_implementation_failure; 275 goto exit; 276 } 277 istmpenable = 1; 278 } 279 280 /* Figure out our timeout first Kus, then HZ */ 281 timeout = msg->channellist.data.len * msg->maxchanneltime.data; 282 timeout = (timeout * HZ) / 1000; 283 284 /* Issue the scan request */ 285 hw->scanflag = 0; 286 287 result = hfa384x_drvr_setconfig(hw, 288 HFA384x_RID_HOSTSCAN, &scanreq, 289 sizeof(hfa384x_HostScanRequest_data_t)); 290 if (result) { 291 printk(KERN_ERR "setconfig(SCANREQUEST) failed. result=%d\n", 292 result); 293 msg->resultcode.data = 294 P80211ENUM_resultcode_implementation_failure; 295 goto exit; 296 } 297 298 /* sleep until info frame arrives */ 299 wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout); 300 301 msg->numbss.status = P80211ENUM_msgitem_status_data_ok; 302 if (hw->scanflag == -1) 303 hw->scanflag = 0; 304 305 msg->numbss.data = hw->scanflag; 306 307 hw->scanflag = 0; 308 309 /* Disable port if we temporarily enabled it. */ 310 if (istmpenable) { 311 result = hfa384x_drvr_disable(hw, 0); 312 if (result) { 313 printk(KERN_ERR "drvr_disable(0) failed. " 314 "result=%d\n", result); 315 msg->resultcode.data = 316 P80211ENUM_resultcode_implementation_failure; 317 goto exit; 318 } 319 } 320 321 /* restore original roaming mode */ 322 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE, 323 roamingmode); 324 if (result) { 325 printk(KERN_ERR "setconfig(ROAMMODE) failed. result=%d\n", 326 result); 327 msg->resultcode.data = 328 P80211ENUM_resultcode_implementation_failure; 329 goto exit; 330 } 331 332 result = 0; 333 msg->resultcode.data = P80211ENUM_resultcode_success; 334 335exit: 336 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 337 338 return result; 339} 340 341/*---------------------------------------------------------------- 342* prism2mgmt_scan_results 343* 344* Retrieve the BSS description for one of the BSSs identified in 345* a scan. 346* 347* Arguments: 348* wlandev wlan device structure 349* msgp ptr to msg buffer 350* 351* Returns: 352* 0 success and done 353* <0 success, but we're waiting for something to finish. 354* >0 an error occurred while handling the message. 355* Side effects: 356* 357* Call context: 358* process thread (usually) 359* interrupt 360----------------------------------------------------------------*/ 361int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) 362{ 363 int result = 0; 364 struct p80211msg_dot11req_scan_results *req; 365 hfa384x_t *hw = wlandev->priv; 366 hfa384x_HScanResultSub_t *item = NULL; 367 368 int count; 369 370 req = (struct p80211msg_dot11req_scan_results *) msgp; 371 372 req->resultcode.status = P80211ENUM_msgitem_status_data_ok; 373 374 if (!hw->scanresults) { 375 printk(KERN_ERR 376 "dot11req_scan_results can only be used after a successful dot11req_scan.\n"); 377 result = 2; 378 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters; 379 goto exit; 380 } 381 382 count = (hw->scanresults->framelen - 3) / 32; 383 if (count > 32) 384 count = 32; 385 386 if (req->bssindex.data >= count) { 387 pr_debug("requested index (%d) out of range (%d)\n", 388 req->bssindex.data, count); 389 result = 2; 390 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters; 391 goto exit; 392 } 393 394 item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]); 395 /* signal and noise */ 396 req->signal.status = P80211ENUM_msgitem_status_data_ok; 397 req->noise.status = P80211ENUM_msgitem_status_data_ok; 398 req->signal.data = le16_to_cpu(item->sl); 399 req->noise.data = le16_to_cpu(item->anl); 400 401 /* BSSID */ 402 req->bssid.status = P80211ENUM_msgitem_status_data_ok; 403 req->bssid.data.len = WLAN_BSSID_LEN; 404 memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN); 405 406 /* SSID */ 407 req->ssid.status = P80211ENUM_msgitem_status_data_ok; 408 req->ssid.data.len = le16_to_cpu(item->ssid.len); 409 memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); 410 411 /* supported rates */ 412 for (count = 0; count < 10; count++) 413 if (item->supprates[count] == 0) 414 break; 415 416#define REQBASICRATE(N) \ 417 if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \ 418 req->basicrate ## N .data = item->supprates[(N)-1]; \ 419 req->basicrate ## N .status = \ 420 P80211ENUM_msgitem_status_data_ok; \ 421 } 422 423 REQBASICRATE(1); 424 REQBASICRATE(2); 425 REQBASICRATE(3); 426 REQBASICRATE(4); 427 REQBASICRATE(5); 428 REQBASICRATE(6); 429 REQBASICRATE(7); 430 REQBASICRATE(8); 431 432#define REQSUPPRATE(N) \ 433 if (count >= N) { \ 434 req->supprate ## N .data = item->supprates[(N)-1]; \ 435 req->supprate ## N .status = \ 436 P80211ENUM_msgitem_status_data_ok; \ 437 } 438 439 REQSUPPRATE(1); 440 REQSUPPRATE(2); 441 REQSUPPRATE(3); 442 REQSUPPRATE(4); 443 REQSUPPRATE(5); 444 REQSUPPRATE(6); 445 REQSUPPRATE(7); 446 REQSUPPRATE(8); 447 448 /* beacon period */ 449 req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok; 450 req->beaconperiod.data = le16_to_cpu(item->bcnint); 451 452 /* timestamps */ 453 req->timestamp.status = P80211ENUM_msgitem_status_data_ok; 454 req->timestamp.data = jiffies; 455 req->localtime.status = P80211ENUM_msgitem_status_data_ok; 456 req->localtime.data = jiffies; 457 458 /* atim window */ 459 req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok; 460 req->ibssatimwindow.data = le16_to_cpu(item->atim); 461 462 /* Channel */ 463 req->dschannel.status = P80211ENUM_msgitem_status_data_ok; 464 req->dschannel.data = le16_to_cpu(item->chid); 465 466 /* capinfo bits */ 467 count = le16_to_cpu(item->capinfo); 468 req->capinfo.status = P80211ENUM_msgitem_status_data_ok; 469 req->capinfo.data = count; 470 471 /* privacy flag */ 472 req->privacy.status = P80211ENUM_msgitem_status_data_ok; 473 req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count); 474 475 /* cfpollable */ 476 req->cfpollable.status = P80211ENUM_msgitem_status_data_ok; 477 req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count); 478 479 /* cfpollreq */ 480 req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok; 481 req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count); 482 483 /* bsstype */ 484 req->bsstype.status = P80211ENUM_msgitem_status_data_ok; 485 req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ? 486 P80211ENUM_bsstype_infrastructure : P80211ENUM_bsstype_independent; 487 488 result = 0; 489 req->resultcode.data = P80211ENUM_resultcode_success; 490 491exit: 492 return result; 493} 494 495/*---------------------------------------------------------------- 496* prism2mgmt_start 497* 498* Start a BSS. Any station can do this for IBSS, only AP for ESS. 499* 500* Arguments: 501* wlandev wlan device structure 502* msgp ptr to msg buffer 503* 504* Returns: 505* 0 success and done 506* <0 success, but we're waiting for something to finish. 507* >0 an error occurred while handling the message. 508* Side effects: 509* 510* Call context: 511* process thread (usually) 512* interrupt 513----------------------------------------------------------------*/ 514int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) 515{ 516 int result = 0; 517 hfa384x_t *hw = wlandev->priv; 518 struct p80211msg_dot11req_start *msg = msgp; 519 520 p80211pstrd_t *pstr; 521 u8 bytebuf[80]; 522 hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf; 523 u16 word; 524 525 wlandev->macmode = WLAN_MACMODE_NONE; 526 527 /* Set the SSID */ 528 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data)); 529 530 /*** ADHOC IBSS ***/ 531 /* see if current f/w is less than 8c3 */ 532 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, 533 hw->ident_sta_fw.minor, 534 hw->ident_sta_fw.variant) < 535 HFA384x_FIRMWARE_VERSION(0, 8, 3)) { 536 /* Ad-Hoc not quite supported on Prism2 */ 537 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 538 msg->resultcode.data = P80211ENUM_resultcode_not_supported; 539 goto done; 540 } 541 542 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 543 544 /*** STATION ***/ 545 /* Set the REQUIRED config items */ 546 /* SSID */ 547 pstr = (p80211pstrd_t *) &(msg->ssid.data); 548 prism2mgmt_pstr2bytestr(p2bytestr, pstr); 549 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID, 550 bytebuf, HFA384x_RID_CNFOWNSSID_LEN); 551 if (result) { 552 printk(KERN_ERR "Failed to set CnfOwnSSID\n"); 553 goto failed; 554 } 555 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, 556 bytebuf, 557 HFA384x_RID_CNFDESIREDSSID_LEN); 558 if (result) { 559 printk(KERN_ERR "Failed to set CnfDesiredSSID\n"); 560 goto failed; 561 } 562 563 /* bsstype - we use the default in the ap firmware */ 564 /* IBSS port */ 565 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0); 566 567 /* beacon period */ 568 word = msg->beaconperiod.data; 569 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word); 570 if (result) { 571 printk(KERN_ERR "Failed to set beacon period=%d.\n", word); 572 goto failed; 573 } 574 575 /* dschannel */ 576 word = msg->dschannel.data; 577 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word); 578 if (result) { 579 printk(KERN_ERR "Failed to set channel=%d.\n", word); 580 goto failed; 581 } 582 /* Basic rates */ 583 word = p80211rate_to_p2bit(msg->basicrate1.data); 584 if (msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok) 585 word |= p80211rate_to_p2bit(msg->basicrate2.data); 586 587 if (msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok) 588 word |= p80211rate_to_p2bit(msg->basicrate3.data); 589 590 if (msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok) 591 word |= p80211rate_to_p2bit(msg->basicrate4.data); 592 593 if (msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok) 594 word |= p80211rate_to_p2bit(msg->basicrate5.data); 595 596 if (msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok) 597 word |= p80211rate_to_p2bit(msg->basicrate6.data); 598 599 if (msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok) 600 word |= p80211rate_to_p2bit(msg->basicrate7.data); 601 602 if (msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok) 603 word |= p80211rate_to_p2bit(msg->basicrate8.data); 604 605 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word); 606 if (result) { 607 printk(KERN_ERR "Failed to set basicrates=%d.\n", word); 608 goto failed; 609 } 610 611 /* Operational rates (supprates and txratecontrol) */ 612 word = p80211rate_to_p2bit(msg->operationalrate1.data); 613 if (msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok) 614 word |= p80211rate_to_p2bit(msg->operationalrate2.data); 615 616 if (msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok) 617 word |= p80211rate_to_p2bit(msg->operationalrate3.data); 618 619 if (msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok) 620 word |= p80211rate_to_p2bit(msg->operationalrate4.data); 621 622 if (msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok) 623 word |= p80211rate_to_p2bit(msg->operationalrate5.data); 624 625 if (msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok) 626 word |= p80211rate_to_p2bit(msg->operationalrate6.data); 627 628 if (msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok) 629 word |= p80211rate_to_p2bit(msg->operationalrate7.data); 630 631 if (msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok) 632 word |= p80211rate_to_p2bit(msg->operationalrate8.data); 633 634 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word); 635 if (result) { 636 printk(KERN_ERR "Failed to set supprates=%d.\n", word); 637 goto failed; 638 } 639 640 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word); 641 if (result) { 642 printk(KERN_ERR "Failed to set txrates=%d.\n", word); 643 goto failed; 644 } 645 646 /* Set the macmode so the frame setup code knows what to do */ 647 if (msg->bsstype.data == P80211ENUM_bsstype_independent) { 648 wlandev->macmode = WLAN_MACMODE_IBSS_STA; 649 /* lets extend the data length a bit */ 650 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304); 651 } 652 653 /* Enable the Port */ 654 result = hfa384x_drvr_enable(hw, 0); 655 if (result) { 656 printk(KERN_ERR "Enable macport failed, result=%d.\n", result); 657 goto failed; 658 } 659 660 msg->resultcode.data = P80211ENUM_resultcode_success; 661 662 goto done; 663failed: 664 pr_debug("Failed to set a config option, result=%d\n", result); 665 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; 666 667done: 668 result = 0; 669 670 return result; 671} 672 673/*---------------------------------------------------------------- 674* prism2mgmt_readpda 675* 676* Collect the PDA data and put it in the message. 677* 678* Arguments: 679* wlandev wlan device structure 680* msgp ptr to msg buffer 681* 682* Returns: 683* 0 success and done 684* <0 success, but we're waiting for something to finish. 685* >0 an error occurred while handling the message. 686* Side effects: 687* 688* Call context: 689* process thread (usually) 690----------------------------------------------------------------*/ 691int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp) 692{ 693 hfa384x_t *hw = wlandev->priv; 694 struct p80211msg_p2req_readpda *msg = msgp; 695 int result; 696 697 /* We only support collecting the PDA when in the FWLOAD 698 * state. 699 */ 700 if (wlandev->msdstate != WLAN_MSD_FWLOAD) { 701 printk(KERN_ERR 702 "PDA may only be read " "in the fwload state.\n"); 703 msg->resultcode.data = 704 P80211ENUM_resultcode_implementation_failure; 705 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 706 } else { 707 /* Call drvr_readpda(), it handles the auxport enable 708 * and validating the returned PDA. 709 */ 710 result = hfa384x_drvr_readpda(hw, 711 msg->pda.data, 712 HFA384x_PDA_LEN_MAX); 713 if (result) { 714 printk(KERN_ERR 715 "hfa384x_drvr_readpda() failed, " 716 "result=%d\n", result); 717 718 msg->resultcode.data = 719 P80211ENUM_resultcode_implementation_failure; 720 msg->resultcode.status = 721 P80211ENUM_msgitem_status_data_ok; 722 return 0; 723 } 724 msg->pda.status = P80211ENUM_msgitem_status_data_ok; 725 msg->resultcode.data = P80211ENUM_resultcode_success; 726 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 727 } 728 729 return 0; 730} 731 732/*---------------------------------------------------------------- 733* prism2mgmt_ramdl_state 734* 735* Establishes the beginning/end of a card RAM download session. 736* 737* It is expected that the ramdl_write() function will be called 738* one or more times between the 'enable' and 'disable' calls to 739* this function. 740* 741* Note: This function should not be called when a mac comm port 742* is active. 743* 744* Arguments: 745* wlandev wlan device structure 746* msgp ptr to msg buffer 747* 748* Returns: 749* 0 success and done 750* <0 success, but we're waiting for something to finish. 751* >0 an error occurred while handling the message. 752* Side effects: 753* 754* Call context: 755* process thread (usually) 756----------------------------------------------------------------*/ 757int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp) 758{ 759 hfa384x_t *hw = wlandev->priv; 760 struct p80211msg_p2req_ramdl_state *msg = msgp; 761 762 if (wlandev->msdstate != WLAN_MSD_FWLOAD) { 763 printk(KERN_ERR 764 "ramdl_state(): may only be called " 765 "in the fwload state.\n"); 766 msg->resultcode.data = 767 P80211ENUM_resultcode_implementation_failure; 768 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 769 return 0; 770 } 771 772 /* 773 ** Note: Interrupts are locked out if this is an AP and are NOT 774 ** locked out if this is a station. 775 */ 776 777 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 778 if (msg->enable.data == P80211ENUM_truth_true) { 779 if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) { 780 msg->resultcode.data = 781 P80211ENUM_resultcode_implementation_failure; 782 } else { 783 msg->resultcode.data = P80211ENUM_resultcode_success; 784 } 785 } else { 786 hfa384x_drvr_ramdl_disable(hw); 787 msg->resultcode.data = P80211ENUM_resultcode_success; 788 } 789 790 return 0; 791} 792 793/*---------------------------------------------------------------- 794* prism2mgmt_ramdl_write 795* 796* Writes a buffer to the card RAM using the download state. This 797* is for writing code to card RAM. To just read or write raw data 798* use the aux functions. 799* 800* Arguments: 801* wlandev wlan device structure 802* msgp ptr to msg buffer 803* 804* Returns: 805* 0 success and done 806* <0 success, but we're waiting for something to finish. 807* >0 an error occurred while handling the message. 808* Side effects: 809* 810* Call context: 811* process thread (usually) 812----------------------------------------------------------------*/ 813int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp) 814{ 815 hfa384x_t *hw = wlandev->priv; 816 struct p80211msg_p2req_ramdl_write *msg = msgp; 817 u32 addr; 818 u32 len; 819 u8 *buf; 820 821 if (wlandev->msdstate != WLAN_MSD_FWLOAD) { 822 printk(KERN_ERR 823 "ramdl_write(): may only be called " 824 "in the fwload state.\n"); 825 msg->resultcode.data = 826 P80211ENUM_resultcode_implementation_failure; 827 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 828 return 0; 829 } 830 831 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 832 /* first validate the length */ 833 if (msg->len.data > sizeof(msg->data.data)) { 834 msg->resultcode.status = 835 P80211ENUM_resultcode_invalid_parameters; 836 return 0; 837 } 838 /* call the hfa384x function to do the write */ 839 addr = msg->addr.data; 840 len = msg->len.data; 841 buf = msg->data.data; 842 if (hfa384x_drvr_ramdl_write(hw, addr, buf, len)) 843 msg->resultcode.data = P80211ENUM_resultcode_refused; 844 845 msg->resultcode.data = P80211ENUM_resultcode_success; 846 847 return 0; 848} 849 850/*---------------------------------------------------------------- 851* prism2mgmt_flashdl_state 852* 853* Establishes the beginning/end of a card Flash download session. 854* 855* It is expected that the flashdl_write() function will be called 856* one or more times between the 'enable' and 'disable' calls to 857* this function. 858* 859* Note: This function should not be called when a mac comm port 860* is active. 861* 862* Arguments: 863* wlandev wlan device structure 864* msgp ptr to msg buffer 865* 866* Returns: 867* 0 success and done 868* <0 success, but we're waiting for something to finish. 869* >0 an error occurred while handling the message. 870* Side effects: 871* 872* Call context: 873* process thread (usually) 874----------------------------------------------------------------*/ 875int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp) 876{ 877 int result = 0; 878 hfa384x_t *hw = wlandev->priv; 879 struct p80211msg_p2req_flashdl_state *msg = msgp; 880 881 if (wlandev->msdstate != WLAN_MSD_FWLOAD) { 882 printk(KERN_ERR 883 "flashdl_state(): may only be called " 884 "in the fwload state.\n"); 885 msg->resultcode.data = 886 P80211ENUM_resultcode_implementation_failure; 887 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 888 return 0; 889 } 890 891 /* 892 ** Note: Interrupts are locked out if this is an AP and are NOT 893 ** locked out if this is a station. 894 */ 895 896 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 897 if (msg->enable.data == P80211ENUM_truth_true) { 898 if (hfa384x_drvr_flashdl_enable(hw)) { 899 msg->resultcode.data = 900 P80211ENUM_resultcode_implementation_failure; 901 } else { 902 msg->resultcode.data = P80211ENUM_resultcode_success; 903 } 904 } else { 905 hfa384x_drvr_flashdl_disable(hw); 906 msg->resultcode.data = P80211ENUM_resultcode_success; 907 /* NOTE: At this point, the MAC is in the post-reset 908 * state and the driver is in the fwload state. 909 * We need to get the MAC back into the fwload 910 * state. To do this, we set the nsdstate to HWPRESENT 911 * and then call the ifstate function to redo everything 912 * that got us into the fwload state. 913 */ 914 wlandev->msdstate = WLAN_MSD_HWPRESENT; 915 result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload); 916 if (result != P80211ENUM_resultcode_success) { 917 printk(KERN_ERR "prism2sta_ifstate(fwload) failed," 918 "P80211ENUM_resultcode=%d\n", result); 919 msg->resultcode.data = 920 P80211ENUM_resultcode_implementation_failure; 921 result = -1; 922 } 923 } 924 925 return 0; 926} 927 928/*---------------------------------------------------------------- 929* prism2mgmt_flashdl_write 930* 931* 932* 933* Arguments: 934* wlandev wlan device structure 935* msgp ptr to msg buffer 936* 937* Returns: 938* 0 success and done 939* <0 success, but we're waiting for something to finish. 940* >0 an error occurred while handling the message. 941* Side effects: 942* 943* Call context: 944* process thread (usually) 945----------------------------------------------------------------*/ 946int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp) 947{ 948 hfa384x_t *hw = wlandev->priv; 949 struct p80211msg_p2req_flashdl_write *msg = msgp; 950 u32 addr; 951 u32 len; 952 u8 *buf; 953 954 if (wlandev->msdstate != WLAN_MSD_FWLOAD) { 955 printk(KERN_ERR 956 "flashdl_write(): may only be called " 957 "in the fwload state.\n"); 958 msg->resultcode.data = 959 P80211ENUM_resultcode_implementation_failure; 960 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 961 return 0; 962 } 963 964 /* 965 ** Note: Interrupts are locked out if this is an AP and are NOT 966 ** locked out if this is a station. 967 */ 968 969 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 970 /* first validate the length */ 971 if (msg->len.data > sizeof(msg->data.data)) { 972 msg->resultcode.status = 973 P80211ENUM_resultcode_invalid_parameters; 974 return 0; 975 } 976 /* call the hfa384x function to do the write */ 977 addr = msg->addr.data; 978 len = msg->len.data; 979 buf = msg->data.data; 980 if (hfa384x_drvr_flashdl_write(hw, addr, buf, len)) 981 msg->resultcode.data = P80211ENUM_resultcode_refused; 982 983 msg->resultcode.data = P80211ENUM_resultcode_success; 984 985 return 0; 986} 987 988/*---------------------------------------------------------------- 989* prism2mgmt_autojoin 990* 991* Associate with an ESS. 992* 993* Arguments: 994* wlandev wlan device structure 995* msgp ptr to msg buffer 996* 997* Returns: 998* 0 success and done 999* <0 success, but we're waiting for something to finish. 1000* >0 an error occurred while handling the message. 1001* Side effects: 1002* 1003* Call context: 1004* process thread (usually) 1005* interrupt 1006----------------------------------------------------------------*/ 1007int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) 1008{ 1009 hfa384x_t *hw = wlandev->priv; 1010 int result = 0; 1011 u16 reg; 1012 u16 port_type; 1013 struct p80211msg_lnxreq_autojoin *msg = msgp; 1014 p80211pstrd_t *pstr; 1015 u8 bytebuf[256]; 1016 hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf; 1017 1018 wlandev->macmode = WLAN_MACMODE_NONE; 1019 1020 /* Set the SSID */ 1021 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data)); 1022 1023 /* Disable the Port */ 1024 hfa384x_drvr_disable(hw, 0); 1025 1026 /*** STATION ***/ 1027 /* Set the TxRates */ 1028 hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f); 1029 1030 /* Set the auth type */ 1031 if (msg->authtype.data == P80211ENUM_authalg_sharedkey) 1032 reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY; 1033 else 1034 reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; 1035 1036 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg); 1037 1038 /* Set the ssid */ 1039 memset(bytebuf, 0, 256); 1040 pstr = (p80211pstrd_t *) &(msg->ssid.data); 1041 prism2mgmt_pstr2bytestr(p2bytestr, pstr); 1042 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, 1043 bytebuf, 1044 HFA384x_RID_CNFDESIREDSSID_LEN); 1045 port_type = HFA384x_PORTTYPE_BSS; 1046 /* Set the PortType */ 1047 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type); 1048 1049 /* Enable the Port */ 1050 hfa384x_drvr_enable(hw, 0); 1051 1052 /* Set the resultcode */ 1053 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 1054 msg->resultcode.data = P80211ENUM_resultcode_success; 1055 1056 return result; 1057} 1058 1059/*---------------------------------------------------------------- 1060* prism2mgmt_wlansniff 1061* 1062* Start or stop sniffing. 1063* 1064* Arguments: 1065* wlandev wlan device structure 1066* msgp ptr to msg buffer 1067* 1068* Returns: 1069* 0 success and done 1070* <0 success, but we're waiting for something to finish. 1071* >0 an error occurred while handling the message. 1072* Side effects: 1073* 1074* Call context: 1075* process thread (usually) 1076* interrupt 1077----------------------------------------------------------------*/ 1078int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) 1079{ 1080 int result = 0; 1081 struct p80211msg_lnxreq_wlansniff *msg = msgp; 1082 1083 hfa384x_t *hw = wlandev->priv; 1084 u16 word; 1085 1086 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 1087 switch (msg->enable.data) { 1088 case P80211ENUM_truth_false: 1089 /* Confirm that we're in monitor mode */ 1090 if (wlandev->netdev->type == ARPHRD_ETHER) { 1091 msg->resultcode.data = 1092 P80211ENUM_resultcode_invalid_parameters; 1093 result = 0; 1094 goto exit; 1095 } 1096 /* Disable monitor mode */ 1097 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE); 1098 if (result) { 1099 pr_debug("failed to disable monitor mode, result=%d\n", 1100 result); 1101 goto failed; 1102 } 1103 /* Disable port 0 */ 1104 result = hfa384x_drvr_disable(hw, 0); 1105 if (result) { 1106 pr_debug 1107 ("failed to disable port 0 after sniffing, result=%d\n", 1108 result); 1109 goto failed; 1110 } 1111 /* Clear the driver state */ 1112 wlandev->netdev->type = ARPHRD_ETHER; 1113 1114 /* Restore the wepflags */ 1115 result = hfa384x_drvr_setconfig16(hw, 1116 HFA384x_RID_CNFWEPFLAGS, 1117 hw->presniff_wepflags); 1118 if (result) { 1119 pr_debug 1120 ("failed to restore wepflags=0x%04x, result=%d\n", 1121 hw->presniff_wepflags, result); 1122 goto failed; 1123 } 1124 1125 /* Set the port to its prior type and enable (if necessary) */ 1126 if (hw->presniff_port_type != 0) { 1127 word = hw->presniff_port_type; 1128 result = hfa384x_drvr_setconfig16(hw, 1129 HFA384x_RID_CNFPORTTYPE, 1130 word); 1131 if (result) { 1132 pr_debug 1133 ("failed to restore porttype, result=%d\n", 1134 result); 1135 goto failed; 1136 } 1137 1138 /* Enable the port */ 1139 result = hfa384x_drvr_enable(hw, 0); 1140 if (result) { 1141 pr_debug 1142 ("failed to enable port to presniff setting, result=%d\n", 1143 result); 1144 goto failed; 1145 } 1146 } else { 1147 result = hfa384x_drvr_disable(hw, 0); 1148 1149 } 1150 1151 printk(KERN_INFO "monitor mode disabled\n"); 1152 msg->resultcode.data = P80211ENUM_resultcode_success; 1153 result = 0; 1154 goto exit; 1155 break; 1156 case P80211ENUM_truth_true: 1157 /* Disable the port (if enabled), only check Port 0 */ 1158 if (hw->port_enabled[0]) { 1159 if (wlandev->netdev->type == ARPHRD_ETHER) { 1160 /* Save macport 0 state */ 1161 result = hfa384x_drvr_getconfig16(hw, 1162 HFA384x_RID_CNFPORTTYPE, 1163 &(hw->presniff_port_type)); 1164 if (result) { 1165 pr_debug 1166 ("failed to read porttype, result=%d\n", 1167 result); 1168 goto failed; 1169 } 1170 /* Save the wepflags state */ 1171 result = hfa384x_drvr_getconfig16(hw, 1172 HFA384x_RID_CNFWEPFLAGS, 1173 &(hw->presniff_wepflags)); 1174 if (result) { 1175 pr_debug 1176 ("failed to read wepflags, result=%d\n", 1177 result); 1178 goto failed; 1179 } 1180 hfa384x_drvr_stop(hw); 1181 result = hfa384x_drvr_start(hw); 1182 if (result) { 1183 pr_debug 1184 ("failed to restart the card for sniffing, result=%d\n", 1185 result); 1186 goto failed; 1187 } 1188 } else { 1189 /* Disable the port */ 1190 result = hfa384x_drvr_disable(hw, 0); 1191 if (result) { 1192 pr_debug 1193 ("failed to enable port for sniffing, result=%d\n", 1194 result); 1195 goto failed; 1196 } 1197 } 1198 } else { 1199 hw->presniff_port_type = 0; 1200 } 1201 1202 /* Set the channel we wish to sniff */ 1203 word = msg->channel.data; 1204 result = hfa384x_drvr_setconfig16(hw, 1205 HFA384x_RID_CNFOWNCHANNEL, 1206 word); 1207 hw->sniff_channel = word; 1208 1209 if (result) { 1210 pr_debug("failed to set channel %d, result=%d\n", 1211 word, result); 1212 goto failed; 1213 } 1214 1215 /* Now if we're already sniffing, we can skip the rest */ 1216 if (wlandev->netdev->type != ARPHRD_ETHER) { 1217 /* Set the port type to pIbss */ 1218 word = HFA384x_PORTTYPE_PSUEDOIBSS; 1219 result = hfa384x_drvr_setconfig16(hw, 1220 HFA384x_RID_CNFPORTTYPE, 1221 word); 1222 if (result) { 1223 pr_debug 1224 ("failed to set porttype %d, result=%d\n", 1225 word, result); 1226 goto failed; 1227 } 1228 if ((msg->keepwepflags.status == 1229 P80211ENUM_msgitem_status_data_ok) 1230 && (msg->keepwepflags.data != 1231 P80211ENUM_truth_true)) { 1232 /* Set the wepflags for no decryption */ 1233 word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT | 1234 HFA384x_WEPFLAGS_DISABLE_RXCRYPT; 1235 result = 1236 hfa384x_drvr_setconfig16(hw, 1237 HFA384x_RID_CNFWEPFLAGS, 1238 word); 1239 } 1240 1241 if (result) { 1242 pr_debug 1243 ("failed to set wepflags=0x%04x, result=%d\n", 1244 word, result); 1245 goto failed; 1246 } 1247 } 1248 1249 /* Do we want to strip the FCS in monitor mode? */ 1250 if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) 1251 && (msg->stripfcs.data == P80211ENUM_truth_true)) { 1252 hw->sniff_fcs = 0; 1253 } else { 1254 hw->sniff_fcs = 1; 1255 } 1256 1257 /* Do we want to truncate the packets? */ 1258 if (msg->packet_trunc.status == 1259 P80211ENUM_msgitem_status_data_ok) { 1260 hw->sniff_truncate = msg->packet_trunc.data; 1261 } else { 1262 hw->sniff_truncate = 0; 1263 } 1264 1265 /* Enable the port */ 1266 result = hfa384x_drvr_enable(hw, 0); 1267 if (result) { 1268 pr_debug 1269 ("failed to enable port for sniffing, result=%d\n", 1270 result); 1271 goto failed; 1272 } 1273 /* Enable monitor mode */ 1274 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE); 1275 if (result) { 1276 pr_debug("failed to enable monitor mode, result=%d\n", 1277 result); 1278 goto failed; 1279 } 1280 1281 if (wlandev->netdev->type == ARPHRD_ETHER) 1282 printk(KERN_INFO "monitor mode enabled\n"); 1283 1284 /* Set the driver state */ 1285 /* Do we want the prism2 header? */ 1286 if ((msg->prismheader.status == 1287 P80211ENUM_msgitem_status_data_ok) 1288 && (msg->prismheader.data == P80211ENUM_truth_true)) { 1289 hw->sniffhdr = 0; 1290 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; 1291 } else 1292 if ((msg->wlanheader.status == 1293 P80211ENUM_msgitem_status_data_ok) 1294 && (msg->wlanheader.data == P80211ENUM_truth_true)) { 1295 hw->sniffhdr = 1; 1296 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; 1297 } else { 1298 wlandev->netdev->type = ARPHRD_IEEE80211; 1299 } 1300 1301 msg->resultcode.data = P80211ENUM_resultcode_success; 1302 result = 0; 1303 goto exit; 1304 break; 1305 default: 1306 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; 1307 result = 0; 1308 goto exit; 1309 break; 1310 } 1311 1312failed: 1313 msg->resultcode.data = P80211ENUM_resultcode_refused; 1314 result = 0; 1315exit: 1316 return result; 1317} 1318