1// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) 2/* 3 * 4 * Management request for mibset/mibget 5 * 6 * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. 7 * -------------------------------------------------------------------- 8 * 9 * linux-wlan 10 * 11 * -------------------------------------------------------------------- 12 * 13 * Inquiries regarding the linux-wlan Open Source project can be 14 * made directly to: 15 * 16 * AbsoluteValue Systems Inc. 17 * info@linux-wlan.com 18 * http://www.linux-wlan.com 19 * 20 * -------------------------------------------------------------------- 21 * 22 * Portions of the development of this software were funded by 23 * Intersil Corporation as part of PRISM(R) chipset product development. 24 * 25 * -------------------------------------------------------------------- 26 * 27 * The functions in this file handle the mibset/mibget management 28 * functions. 29 * 30 * -------------------------------------------------------------------- 31 */ 32 33#include <linux/module.h> 34#include <linux/kernel.h> 35#include <linux/sched.h> 36#include <linux/types.h> 37#include <linux/wireless.h> 38#include <linux/netdevice.h> 39#include <linux/io.h> 40#include <linux/delay.h> 41#include <asm/byteorder.h> 42#include <linux/usb.h> 43#include <linux/bitops.h> 44 45#include "p80211types.h" 46#include "p80211hdr.h" 47#include "p80211mgmt.h" 48#include "p80211conv.h" 49#include "p80211msg.h" 50#include "p80211netdev.h" 51#include "p80211metadef.h" 52#include "p80211metastruct.h" 53#include "hfa384x.h" 54#include "prism2mgmt.h" 55 56#define MIB_TMP_MAXLEN 200 /* Max length of RID record (in bytes). */ 57 58#define F_STA 0x1 /* MIB is supported on stations. */ 59#define F_READ 0x2 /* MIB may be read. */ 60#define F_WRITE 0x4 /* MIB may be written. */ 61 62struct mibrec { 63 u32 did; 64 u16 flag; 65 u16 parm1; 66 u16 parm2; 67 u16 parm3; 68 int (*func)(struct mibrec *mib, 69 int isget, 70 struct wlandevice *wlandev, 71 struct hfa384x *hw, 72 struct p80211msg_dot11req_mibset *msg, void *data); 73}; 74 75static int prism2mib_bytearea2pstr(struct mibrec *mib, 76 int isget, 77 struct wlandevice *wlandev, 78 struct hfa384x *hw, 79 struct p80211msg_dot11req_mibset *msg, 80 void *data); 81 82static int prism2mib_uint32(struct mibrec *mib, 83 int isget, 84 struct wlandevice *wlandev, 85 struct hfa384x *hw, 86 struct p80211msg_dot11req_mibset *msg, void *data); 87 88static int prism2mib_flag(struct mibrec *mib, 89 int isget, 90 struct wlandevice *wlandev, 91 struct hfa384x *hw, 92 struct p80211msg_dot11req_mibset *msg, void *data); 93 94static int prism2mib_wepdefaultkey(struct mibrec *mib, 95 int isget, 96 struct wlandevice *wlandev, 97 struct hfa384x *hw, 98 struct p80211msg_dot11req_mibset *msg, 99 void *data); 100 101static int prism2mib_privacyinvoked(struct mibrec *mib, 102 int isget, 103 struct wlandevice *wlandev, 104 struct hfa384x *hw, 105 struct p80211msg_dot11req_mibset *msg, 106 void *data); 107 108static int 109prism2mib_fragmentationthreshold(struct mibrec *mib, 110 int isget, 111 struct wlandevice *wlandev, 112 struct hfa384x *hw, 113 struct p80211msg_dot11req_mibset *msg, 114 void *data); 115 116static int prism2mib_priv(struct mibrec *mib, 117 int isget, 118 struct wlandevice *wlandev, 119 struct hfa384x *hw, 120 struct p80211msg_dot11req_mibset *msg, void *data); 121 122static struct mibrec mibtab[] = { 123 /* dot11smt MIB's */ 124 {didmib_dot11smt_wepdefaultkeystable_key(1), 125 F_STA | F_WRITE, 126 HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0, 127 prism2mib_wepdefaultkey}, 128 {didmib_dot11smt_wepdefaultkeystable_key(2), 129 F_STA | F_WRITE, 130 HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0, 131 prism2mib_wepdefaultkey}, 132 {didmib_dot11smt_wepdefaultkeystable_key(3), 133 F_STA | F_WRITE, 134 HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0, 135 prism2mib_wepdefaultkey}, 136 {didmib_dot11smt_wepdefaultkeystable_key(4), 137 F_STA | F_WRITE, 138 HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0, 139 prism2mib_wepdefaultkey}, 140 {DIDMIB_DOT11SMT_PRIVACYTABLE_PRIVACYINVOKED, 141 F_STA | F_READ | F_WRITE, 142 HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_PRIVINVOKED, 0, 143 prism2mib_privacyinvoked}, 144 {DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID, 145 F_STA | F_READ | F_WRITE, 146 HFA384x_RID_CNFWEPDEFAULTKEYID, 0, 0, 147 prism2mib_uint32}, 148 {DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED, 149 F_STA | F_READ | F_WRITE, 150 HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_EXCLUDE, 0, 151 prism2mib_flag}, 152 153 /* dot11mac MIB's */ 154 155 {DIDMIB_DOT11MAC_OPERATIONTABLE_MACADDRESS, 156 F_STA | F_READ | F_WRITE, 157 HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0, 158 prism2mib_bytearea2pstr}, 159 {DIDMIB_DOT11MAC_OPERATIONTABLE_RTSTHRESHOLD, 160 F_STA | F_READ | F_WRITE, 161 HFA384x_RID_RTSTHRESH, 0, 0, 162 prism2mib_uint32}, 163 {DIDMIB_DOT11MAC_OPERATIONTABLE_SHORTRETRYLIMIT, 164 F_STA | F_READ, 165 HFA384x_RID_SHORTRETRYLIMIT, 0, 0, 166 prism2mib_uint32}, 167 {DIDMIB_DOT11MAC_OPERATIONTABLE_LONGRETRYLIMIT, 168 F_STA | F_READ, 169 HFA384x_RID_LONGRETRYLIMIT, 0, 0, 170 prism2mib_uint32}, 171 {DIDMIB_DOT11MAC_OPERATIONTABLE_FRAGMENTATIONTHRESHOLD, 172 F_STA | F_READ | F_WRITE, 173 HFA384x_RID_FRAGTHRESH, 0, 0, 174 prism2mib_fragmentationthreshold}, 175 {DIDMIB_DOT11MAC_OPERATIONTABLE_MAXTRANSMITMSDULIFETIME, 176 F_STA | F_READ, 177 HFA384x_RID_MAXTXLIFETIME, 0, 0, 178 prism2mib_uint32}, 179 180 /* dot11phy MIB's */ 181 182 {DIDMIB_DOT11PHY_DSSSTABLE_CURRENTCHANNEL, 183 F_STA | F_READ, 184 HFA384x_RID_CURRENTCHANNEL, 0, 0, 185 prism2mib_uint32}, 186 {DIDMIB_DOT11PHY_TXPOWERTABLE_CURRENTTXPOWERLEVEL, 187 F_STA | F_READ | F_WRITE, 188 HFA384x_RID_TXPOWERMAX, 0, 0, 189 prism2mib_uint32}, 190 191 /* p2Static MIB's */ 192 193 {DIDMIB_P2_STATIC_CNFPORTTYPE, 194 F_STA | F_READ | F_WRITE, 195 HFA384x_RID_CNFPORTTYPE, 0, 0, 196 prism2mib_uint32}, 197 198 /* p2MAC MIB's */ 199 200 {DIDMIB_P2_MAC_CURRENTTXRATE, 201 F_STA | F_READ, 202 HFA384x_RID_CURRENTTXRATE, 0, 0, 203 prism2mib_uint32}, 204 205 /* And finally, lnx mibs */ 206 {DIDMIB_LNX_CONFIGTABLE_RSNAIE, 207 F_STA | F_READ | F_WRITE, 208 HFA384x_RID_CNFWPADATA, 0, 0, 209 prism2mib_priv}, 210 {0, 0, 0, 0, 0, NULL} 211}; 212 213/* 214 * prism2mgmt_mibset_mibget 215 * 216 * Set the value of a mib item. 217 * 218 * Arguments: 219 * wlandev wlan device structure 220 * msgp ptr to msg buffer 221 * 222 * Returns: 223 * 0 success and done 224 * <0 success, but we're waiting for something to finish. 225 * >0 an error occurred while handling the message. 226 * Side effects: 227 * 228 * Call context: 229 * process thread (usually) 230 * interrupt 231 */ 232 233int prism2mgmt_mibset_mibget(struct wlandevice *wlandev, void *msgp) 234{ 235 struct hfa384x *hw = wlandev->priv; 236 int result, isget; 237 struct mibrec *mib; 238 239 u16 which; 240 241 struct p80211msg_dot11req_mibset *msg = msgp; 242 struct p80211itemd *mibitem; 243 244 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 245 msg->resultcode.data = P80211ENUM_resultcode_success; 246 247 /* 248 ** Determine if this is an Access Point or a station. 249 */ 250 251 which = F_STA; 252 253 /* 254 ** Find the MIB in the MIB table. Note that a MIB may be in the 255 ** table twice...once for an AP and once for a station. Make sure 256 ** to get the correct one. Note that DID=0 marks the end of the 257 ** MIB table. 258 */ 259 260 mibitem = (struct p80211itemd *)msg->mibattribute.data; 261 262 for (mib = mibtab; mib->did != 0; mib++) 263 if (mib->did == mibitem->did && (mib->flag & which)) 264 break; 265 266 if (mib->did == 0) { 267 msg->resultcode.data = P80211ENUM_resultcode_not_supported; 268 goto done; 269 } 270 271 /* 272 ** Determine if this is a "mibget" or a "mibset". If this is a 273 ** "mibget", then make sure that the MIB may be read. Otherwise, 274 ** this is a "mibset" so make sure that the MIB may be written. 275 */ 276 277 isget = (msg->msgcode == DIDMSG_DOT11REQ_MIBGET); 278 279 if (isget) { 280 if (!(mib->flag & F_READ)) { 281 msg->resultcode.data = 282 P80211ENUM_resultcode_cant_get_writeonly_mib; 283 goto done; 284 } 285 } else { 286 if (!(mib->flag & F_WRITE)) { 287 msg->resultcode.data = 288 P80211ENUM_resultcode_cant_set_readonly_mib; 289 goto done; 290 } 291 } 292 293 /* 294 ** Execute the MIB function. If things worked okay, then make 295 ** sure that the MIB function also worked okay. If so, and this 296 ** is a "mibget", then the status value must be set for both the 297 ** "mibattribute" parameter and the mib item within the data 298 ** portion of the "mibattribute". 299 */ 300 301 result = mib->func(mib, isget, wlandev, hw, msg, (void *)mibitem->data); 302 303 if (msg->resultcode.data == P80211ENUM_resultcode_success) { 304 if (result != 0) { 305 pr_debug("get/set failure, result=%d\n", result); 306 msg->resultcode.data = 307 P80211ENUM_resultcode_implementation_failure; 308 } else { 309 if (isget) { 310 msg->mibattribute.status = 311 P80211ENUM_msgitem_status_data_ok; 312 mibitem->status = 313 P80211ENUM_msgitem_status_data_ok; 314 } 315 } 316 } 317 318done: 319 return 0; 320} 321 322/* 323 * prism2mib_bytearea2pstr 324 * 325 * Get/set pstr data to/from a byte area. 326 * 327 * MIB record parameters: 328 * parm1 Prism2 RID value. 329 * parm2 Number of bytes of RID data. 330 * parm3 Not used. 331 * 332 * Arguments: 333 * mib MIB record. 334 * isget MIBGET/MIBSET flag. 335 * wlandev wlan device structure. 336 * priv "priv" structure. 337 * hw "hw" structure. 338 * msg Message structure. 339 * data Data buffer. 340 * 341 * Returns: 342 * 0 - Success. 343 * ~0 - Error. 344 * 345 */ 346 347static int prism2mib_bytearea2pstr(struct mibrec *mib, 348 int isget, 349 struct wlandevice *wlandev, 350 struct hfa384x *hw, 351 struct p80211msg_dot11req_mibset *msg, 352 void *data) 353{ 354 int result; 355 struct p80211pstrd *pstr = data; 356 u8 bytebuf[MIB_TMP_MAXLEN]; 357 358 if (isget) { 359 result = 360 hfa384x_drvr_getconfig(hw, mib->parm1, bytebuf, mib->parm2); 361 prism2mgmt_bytearea2pstr(bytebuf, pstr, mib->parm2); 362 } else { 363 memset(bytebuf, 0, mib->parm2); 364 memcpy(bytebuf, pstr->data, pstr->len); 365 result = 366 hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, mib->parm2); 367 } 368 369 return result; 370} 371 372/* 373 * prism2mib_uint32 374 * 375 * Get/set uint32 data. 376 * 377 * MIB record parameters: 378 * parm1 Prism2 RID value. 379 * parm2 Not used. 380 * parm3 Not used. 381 * 382 * Arguments: 383 * mib MIB record. 384 * isget MIBGET/MIBSET flag. 385 * wlandev wlan device structure. 386 * priv "priv" structure. 387 * hw "hw" structure. 388 * msg Message structure. 389 * data Data buffer. 390 * 391 * Returns: 392 * 0 - Success. 393 * ~0 - Error. 394 * 395 */ 396 397static int prism2mib_uint32(struct mibrec *mib, 398 int isget, 399 struct wlandevice *wlandev, 400 struct hfa384x *hw, 401 struct p80211msg_dot11req_mibset *msg, void *data) 402{ 403 int result; 404 u32 *uint32 = data; 405 u8 bytebuf[MIB_TMP_MAXLEN]; 406 u16 *wordbuf = (u16 *)bytebuf; 407 408 if (isget) { 409 result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); 410 *uint32 = *wordbuf; 411 } else { 412 *wordbuf = *uint32; 413 result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); 414 } 415 416 return result; 417} 418 419/* 420 * prism2mib_flag 421 * 422 * Get/set a flag. 423 * 424 * MIB record parameters: 425 * parm1 Prism2 RID value. 426 * parm2 Bit to get/set. 427 * parm3 Not used. 428 * 429 * Arguments: 430 * mib MIB record. 431 * isget MIBGET/MIBSET flag. 432 * wlandev wlan device structure. 433 * priv "priv" structure. 434 * hw "hw" structure. 435 * msg Message structure. 436 * data Data buffer. 437 * 438 * Returns: 439 * 0 - Success. 440 * ~0 - Error. 441 * 442 */ 443 444static int prism2mib_flag(struct mibrec *mib, 445 int isget, 446 struct wlandevice *wlandev, 447 struct hfa384x *hw, 448 struct p80211msg_dot11req_mibset *msg, void *data) 449{ 450 int result; 451 u32 *uint32 = data; 452 u8 bytebuf[MIB_TMP_MAXLEN]; 453 u16 *wordbuf = (u16 *)bytebuf; 454 u32 flags; 455 456 result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); 457 if (result == 0) { 458 flags = *wordbuf; 459 if (isget) { 460 *uint32 = (flags & mib->parm2) ? 461 P80211ENUM_truth_true : P80211ENUM_truth_false; 462 } else { 463 if ((*uint32) == P80211ENUM_truth_true) 464 flags |= mib->parm2; 465 else 466 flags &= ~mib->parm2; 467 *wordbuf = flags; 468 result = 469 hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); 470 } 471 } 472 473 return result; 474} 475 476/* 477 * prism2mib_wepdefaultkey 478 * 479 * Get/set WEP default keys. 480 * 481 * MIB record parameters: 482 * parm1 Prism2 RID value. 483 * parm2 Number of bytes of RID data. 484 * parm3 Not used. 485 * 486 * Arguments: 487 * mib MIB record. 488 * isget MIBGET/MIBSET flag. 489 * wlandev wlan device structure. 490 * priv "priv" structure. 491 * hw "hw" structure. 492 * msg Message structure. 493 * data Data buffer. 494 * 495 * Returns: 496 * 0 - Success. 497 * ~0 - Error. 498 * 499 */ 500 501static int prism2mib_wepdefaultkey(struct mibrec *mib, 502 int isget, 503 struct wlandevice *wlandev, 504 struct hfa384x *hw, 505 struct p80211msg_dot11req_mibset *msg, 506 void *data) 507{ 508 int result; 509 struct p80211pstrd *pstr = data; 510 u8 bytebuf[MIB_TMP_MAXLEN]; 511 u16 len; 512 513 if (isget) { 514 result = 0; /* Should never happen. */ 515 } else { 516 len = (pstr->len > 5) ? HFA384x_RID_CNFWEP128DEFAULTKEY_LEN : 517 HFA384x_RID_CNFWEPDEFAULTKEY_LEN; 518 memset(bytebuf, 0, len); 519 memcpy(bytebuf, pstr->data, pstr->len); 520 result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, len); 521 } 522 523 return result; 524} 525 526/* 527 * prism2mib_privacyinvoked 528 * 529 * Get/set the dot11PrivacyInvoked value. 530 * 531 * MIB record parameters: 532 * parm1 Prism2 RID value. 533 * parm2 Bit value for PrivacyInvoked flag. 534 * parm3 Not used. 535 * 536 * Arguments: 537 * mib MIB record. 538 * isget MIBGET/MIBSET flag. 539 * wlandev wlan device structure. 540 * priv "priv" structure. 541 * hw "hw" structure. 542 * msg Message structure. 543 * data Data buffer. 544 * 545 * Returns: 546 * 0 - Success. 547 * ~0 - Error. 548 * 549 */ 550 551static int prism2mib_privacyinvoked(struct mibrec *mib, 552 int isget, 553 struct wlandevice *wlandev, 554 struct hfa384x *hw, 555 struct p80211msg_dot11req_mibset *msg, 556 void *data) 557{ 558 if (wlandev->hostwep & HOSTWEP_DECRYPT) { 559 if (wlandev->hostwep & HOSTWEP_DECRYPT) 560 mib->parm2 |= HFA384x_WEPFLAGS_DISABLE_RXCRYPT; 561 if (wlandev->hostwep & HOSTWEP_ENCRYPT) 562 mib->parm2 |= HFA384x_WEPFLAGS_DISABLE_TXCRYPT; 563 } 564 565 return prism2mib_flag(mib, isget, wlandev, hw, msg, data); 566} 567 568/* 569 * prism2mib_fragmentationthreshold 570 * 571 * Get/set the fragmentation threshold. 572 * 573 * MIB record parameters: 574 * parm1 Prism2 RID value. 575 * parm2 Not used. 576 * parm3 Not used. 577 * 578 * Arguments: 579 * mib MIB record. 580 * isget MIBGET/MIBSET flag. 581 * wlandev wlan device structure. 582 * priv "priv" structure. 583 * hw "hw" structure. 584 * msg Message structure. 585 * data Data buffer. 586 * 587 * Returns: 588 * 0 - Success. 589 * ~0 - Error. 590 * 591 */ 592 593static int 594prism2mib_fragmentationthreshold(struct mibrec *mib, 595 int isget, 596 struct wlandevice *wlandev, 597 struct hfa384x *hw, 598 struct p80211msg_dot11req_mibset *msg, 599 void *data) 600{ 601 u32 *uint32 = data; 602 603 if (!isget) 604 if ((*uint32) % 2) { 605 netdev_warn(wlandev->netdev, 606 "Attempt to set odd number FragmentationThreshold\n"); 607 msg->resultcode.data = 608 P80211ENUM_resultcode_not_supported; 609 return 0; 610 } 611 612 return prism2mib_uint32(mib, isget, wlandev, hw, msg, data); 613} 614 615/* 616 * prism2mib_priv 617 * 618 * Get/set values in the "priv" data structure. 619 * 620 * MIB record parameters: 621 * parm1 Not used. 622 * parm2 Not used. 623 * parm3 Not used. 624 * 625 * Arguments: 626 * mib MIB record. 627 * isget MIBGET/MIBSET flag. 628 * wlandev wlan device structure. 629 * priv "priv" structure. 630 * hw "hw" structure. 631 * msg Message structure. 632 * data Data buffer. 633 * 634 * Returns: 635 * 0 - Success. 636 * ~0 - Error. 637 * 638 */ 639 640static int prism2mib_priv(struct mibrec *mib, 641 int isget, 642 struct wlandevice *wlandev, 643 struct hfa384x *hw, 644 struct p80211msg_dot11req_mibset *msg, void *data) 645{ 646 struct p80211pstrd *pstr = data; 647 648 switch (mib->did) { 649 case DIDMIB_LNX_CONFIGTABLE_RSNAIE: { 650 /* 651 * This can never work: wpa is on the stack 652 * and has no bytes allocated in wpa.data. 653 */ 654 struct hfa384x_wpa_data wpa; 655 656 if (isget) { 657 hfa384x_drvr_getconfig(hw, 658 HFA384x_RID_CNFWPADATA, 659 (u8 *)&wpa, 660 sizeof(wpa)); 661 pstr->len = 0; 662 } else { 663 wpa.datalen = 0; 664 665 hfa384x_drvr_setconfig(hw, 666 HFA384x_RID_CNFWPADATA, 667 (u8 *)&wpa, 668 sizeof(wpa)); 669 } 670 break; 671 } 672 default: 673 netdev_err(wlandev->netdev, "Unhandled DID 0x%08x\n", mib->did); 674 } 675 676 return 0; 677} 678 679/* 680 * prism2mgmt_pstr2bytestr 681 * 682 * Convert the pstr data in the WLAN message structure into an hfa384x 683 * byte string format. 684 * 685 * Arguments: 686 * bytestr hfa384x byte string data type 687 * pstr wlan message data 688 * 689 * Returns: 690 * Nothing 691 * 692 */ 693 694void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, 695 struct p80211pstrd *pstr) 696{ 697 bytestr->len = cpu_to_le16((u16)(pstr->len)); 698 memcpy(bytestr->data, pstr->data, pstr->len); 699} 700 701/* 702 * prism2mgmt_bytestr2pstr 703 * 704 * Convert the data in an hfa384x byte string format into a 705 * pstr in the WLAN message. 706 * 707 * Arguments: 708 * bytestr hfa384x byte string data type 709 * msg wlan message 710 * 711 * Returns: 712 * Nothing 713 * 714 */ 715 716void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, 717 struct p80211pstrd *pstr) 718{ 719 pstr->len = (u8)(le16_to_cpu(bytestr->len)); 720 memcpy(pstr->data, bytestr->data, pstr->len); 721} 722 723/* 724 * prism2mgmt_bytearea2pstr 725 * 726 * Convert the data in an hfa384x byte area format into a pstr 727 * in the WLAN message. 728 * 729 * Arguments: 730 * bytearea hfa384x byte area data type 731 * msg wlan message 732 * 733 * Returns: 734 * Nothing 735 * 736 */ 737 738void prism2mgmt_bytearea2pstr(u8 *bytearea, struct p80211pstrd *pstr, int len) 739{ 740 pstr->len = (u8)len; 741 memcpy(pstr->data, bytearea, len); 742} 743