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, rid: mib->parm1, buf: bytebuf, len: mib->parm2);
361 prism2mgmt_bytearea2pstr(bytearea: bytebuf, pstr, len: mib->parm2);
362 } else {
363 memset(bytebuf, 0, mib->parm2);
364 memcpy(bytebuf, pstr->data, pstr->len);
365 result =
366 hfa384x_drvr_setconfig(hw, rid: mib->parm1, buf: bytebuf, len: 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, rid: mib->parm1, val: wordbuf);
410 *uint32 = *wordbuf;
411 } else {
412 *wordbuf = *uint32;
413 result = hfa384x_drvr_setconfig16(hw, rid: mib->parm1, val: *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, rid: mib->parm1, val: 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, rid: mib->parm1, val: *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, rid: mib->parm1, buf: 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(dev: wlandev->netdev,
606 format: "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 buf: (u8 *)&wpa,
660 len: sizeof(wpa));
661 pstr->len = 0;
662 } else {
663 wpa.datalen = 0;
664
665 hfa384x_drvr_setconfig(hw,
666 HFA384x_RID_CNFWPADATA,
667 buf: (u8 *)&wpa,
668 len: sizeof(wpa));
669 }
670 break;
671 }
672 default:
673 netdev_err(dev: wlandev->netdev, format: "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

source code of linux/drivers/staging/wlan-ng/prism2mib.c