1 // SPDX-License-Identifier: GPL-2.0
2 /* cfg80211 Interface for prism2_usb module */
4 #include "prism2mgmt.h"
6 /* Prism2 channel/frequency/bitrate declarations */
7 static const struct ieee80211_channel prism2_channels
[] = {
8 { .center_freq
= 2412 },
9 { .center_freq
= 2417 },
10 { .center_freq
= 2422 },
11 { .center_freq
= 2427 },
12 { .center_freq
= 2432 },
13 { .center_freq
= 2437 },
14 { .center_freq
= 2442 },
15 { .center_freq
= 2447 },
16 { .center_freq
= 2452 },
17 { .center_freq
= 2457 },
18 { .center_freq
= 2462 },
19 { .center_freq
= 2467 },
20 { .center_freq
= 2472 },
21 { .center_freq
= 2484 },
24 static const struct ieee80211_rate prism2_rates
[] = {
31 #define PRISM2_NUM_CIPHER_SUITES 2
32 static const u32 prism2_cipher_suites
[PRISM2_NUM_CIPHER_SUITES
] = {
33 WLAN_CIPHER_SUITE_WEP40
,
34 WLAN_CIPHER_SUITE_WEP104
37 /* prism2 device private data */
38 struct prism2_wiphy_private
{
39 struct wlandevice
*wlandev
;
41 struct ieee80211_supported_band band
;
42 struct ieee80211_channel channels
[ARRAY_SIZE(prism2_channels
)];
43 struct ieee80211_rate rates
[ARRAY_SIZE(prism2_rates
)];
45 struct cfg80211_scan_request
*scan_request
;
48 static const void * const prism2_wiphy_privid
= &prism2_wiphy_privid
;
50 /* Helper Functions */
51 static int prism2_result2err(int prism2_result
)
55 switch (prism2_result
) {
56 case P80211ENUM_resultcode_invalid_parameters
:
59 case P80211ENUM_resultcode_implementation_failure
:
62 case P80211ENUM_resultcode_not_supported
:
73 static int prism2_domibset_uint32(struct wlandevice
*wlandev
,
76 struct p80211msg_dot11req_mibset msg
;
77 struct p80211item_uint32
*mibitem
=
78 (struct p80211item_uint32
*)&msg
.mibattribute
.data
;
80 msg
.msgcode
= DIDMSG_DOT11REQ_MIBSET
;
84 return p80211req_dorequest(wlandev
, (u8
*)&msg
);
87 static int prism2_domibset_pstr32(struct wlandevice
*wlandev
,
88 u32 did
, u8 len
, const u8
*data
)
90 struct p80211msg_dot11req_mibset msg
;
91 struct p80211item_pstr32
*mibitem
=
92 (struct p80211item_pstr32
*)&msg
.mibattribute
.data
;
94 msg
.msgcode
= DIDMSG_DOT11REQ_MIBSET
;
96 mibitem
->data
.len
= len
;
97 memcpy(mibitem
->data
.data
, data
, len
);
99 return p80211req_dorequest(wlandev
, (u8
*)&msg
);
102 /* The interface functions, called by the cfg80211 layer */
103 static int prism2_change_virtual_intf(struct wiphy
*wiphy
,
104 struct net_device
*dev
,
105 enum nl80211_iftype type
,
106 struct vif_params
*params
)
108 struct wlandevice
*wlandev
= dev
->ml_priv
;
114 case NL80211_IFTYPE_ADHOC
:
115 if (wlandev
->macmode
== WLAN_MACMODE_IBSS_STA
)
117 wlandev
->macmode
= WLAN_MACMODE_IBSS_STA
;
120 case NL80211_IFTYPE_STATION
:
121 if (wlandev
->macmode
== WLAN_MACMODE_ESS_STA
)
123 wlandev
->macmode
= WLAN_MACMODE_ESS_STA
;
127 netdev_warn(dev
, "Operation mode: %d not support\n", type
);
131 /* Set Operation mode to the PORT TYPE RID */
132 result
= prism2_domibset_uint32(wlandev
,
133 DIDMIB_P2_STATIC_CNFPORTTYPE
,
139 dev
->ieee80211_ptr
->iftype
= type
;
145 static int prism2_add_key(struct wiphy
*wiphy
, struct net_device
*dev
,
146 u8 key_index
, bool pairwise
, const u8
*mac_addr
,
147 struct key_params
*params
)
149 struct wlandevice
*wlandev
= dev
->ml_priv
;
152 if (key_index
>= NUM_WEPKEYS
)
155 if (params
->cipher
!= WLAN_CIPHER_SUITE_WEP40
&&
156 params
->cipher
!= WLAN_CIPHER_SUITE_WEP104
) {
157 pr_debug("Unsupported cipher suite\n");
161 if (prism2_domibset_uint32(wlandev
,
162 DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID
,
166 /* send key to driver */
167 did
= didmib_dot11smt_wepdefaultkeystable_key(key_index
+ 1);
169 if (prism2_domibset_pstr32(wlandev
, did
, params
->key_len
, params
->key
))
174 static int prism2_get_key(struct wiphy
*wiphy
, struct net_device
*dev
,
175 u8 key_index
, bool pairwise
,
176 const u8
*mac_addr
, void *cookie
,
177 void (*callback
)(void *cookie
, struct key_params
*))
179 struct wlandevice
*wlandev
= dev
->ml_priv
;
180 struct key_params params
;
183 if (key_index
>= NUM_WEPKEYS
)
186 len
= wlandev
->wep_keylens
[key_index
];
187 memset(¶ms
, 0, sizeof(params
));
190 params
.cipher
= WLAN_CIPHER_SUITE_WEP104
;
192 params
.cipher
= WLAN_CIPHER_SUITE_WEP104
;
195 params
.key_len
= len
;
196 params
.key
= wlandev
->wep_keys
[key_index
];
199 callback(cookie
, ¶ms
);
204 static int prism2_del_key(struct wiphy
*wiphy
, struct net_device
*dev
,
205 u8 key_index
, bool pairwise
, const u8
*mac_addr
)
207 struct wlandevice
*wlandev
= dev
->ml_priv
;
212 /* There is no direct way in the hardware (AFAIK) of removing
213 * a key, so we will cheat by setting the key to a bogus value
216 if (key_index
>= NUM_WEPKEYS
)
219 /* send key to driver */
220 did
= didmib_dot11smt_wepdefaultkeystable_key(key_index
+ 1);
221 result
= prism2_domibset_pstr32(wlandev
, did
, 13, "0000000000000");
229 static int prism2_set_default_key(struct wiphy
*wiphy
, struct net_device
*dev
,
230 u8 key_index
, bool unicast
, bool multicast
)
232 struct wlandevice
*wlandev
= dev
->ml_priv
;
234 return prism2_domibset_uint32(wlandev
,
235 DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID
,
239 static int prism2_get_station(struct wiphy
*wiphy
, struct net_device
*dev
,
240 const u8
*mac
, struct station_info
*sinfo
)
242 struct wlandevice
*wlandev
= dev
->ml_priv
;
243 struct p80211msg_lnxreq_commsquality quality
;
246 memset(sinfo
, 0, sizeof(*sinfo
));
248 if (!wlandev
|| (wlandev
->msdstate
!= WLAN_MSD_RUNNING
))
251 /* build request message */
252 quality
.msgcode
= DIDMSG_LNXREQ_COMMSQUALITY
;
253 quality
.dbm
.data
= P80211ENUM_truth_true
;
254 quality
.dbm
.status
= P80211ENUM_msgitem_status_data_ok
;
256 /* send message to nsd */
257 if (!wlandev
->mlmerequest
)
260 result
= wlandev
->mlmerequest(wlandev
, (struct p80211msg
*)&quality
);
263 sinfo
->txrate
.legacy
= quality
.txrate
.data
;
264 sinfo
->filled
|= BIT_ULL(NL80211_STA_INFO_TX_BITRATE
);
265 sinfo
->signal
= quality
.level
.data
;
266 sinfo
->filled
|= BIT_ULL(NL80211_STA_INFO_SIGNAL
);
272 static int prism2_scan(struct wiphy
*wiphy
,
273 struct cfg80211_scan_request
*request
)
275 struct net_device
*dev
;
276 struct prism2_wiphy_private
*priv
= wiphy_priv(wiphy
);
277 struct wlandevice
*wlandev
;
278 struct p80211msg_dot11req_scan msg1
;
279 struct p80211msg_dot11req_scan_results msg2
;
280 struct cfg80211_bss
*bss
;
281 struct cfg80211_scan_info info
= {};
293 dev
= request
->wdev
->netdev
;
294 wlandev
= dev
->ml_priv
;
296 if (priv
->scan_request
&& priv
->scan_request
!= request
)
299 if (wlandev
->macmode
== WLAN_MACMODE_ESS_AP
) {
300 netdev_err(dev
, "Can't scan in AP mode\n");
304 priv
->scan_request
= request
;
306 memset(&msg1
, 0x00, sizeof(msg1
));
307 msg1
.msgcode
= DIDMSG_DOT11REQ_SCAN
;
308 msg1
.bsstype
.data
= P80211ENUM_bsstype_any
;
310 memset(&msg1
.bssid
.data
.data
, 0xFF, sizeof(msg1
.bssid
.data
.data
));
311 msg1
.bssid
.data
.len
= 6;
313 if (request
->n_ssids
> 0) {
314 msg1
.scantype
.data
= P80211ENUM_scantype_active
;
315 msg1
.ssid
.data
.len
= request
->ssids
->ssid_len
;
316 memcpy(msg1
.ssid
.data
.data
,
317 request
->ssids
->ssid
, request
->ssids
->ssid_len
);
319 msg1
.scantype
.data
= 0;
321 msg1
.probedelay
.data
= 0;
324 (i
< request
->n_channels
) && i
< ARRAY_SIZE(prism2_channels
);
326 msg1
.channellist
.data
.data
[i
] =
327 ieee80211_frequency_to_channel(
328 request
->channels
[i
]->center_freq
);
329 msg1
.channellist
.data
.len
= request
->n_channels
;
331 msg1
.maxchanneltime
.data
= 250;
332 msg1
.minchanneltime
.data
= 200;
334 result
= p80211req_dorequest(wlandev
, (u8
*)&msg1
);
336 err
= prism2_result2err(msg1
.resultcode
.data
);
339 /* Now retrieve scan results */
340 numbss
= msg1
.numbss
.data
;
342 for (i
= 0; i
< numbss
; i
++) {
345 memset(&msg2
, 0, sizeof(msg2
));
346 msg2
.msgcode
= DIDMSG_DOT11REQ_SCAN_RESULTS
;
347 msg2
.bssindex
.data
= i
;
349 result
= p80211req_dorequest(wlandev
, (u8
*)&msg2
);
351 (msg2
.resultcode
.data
!= P80211ENUM_resultcode_success
)) {
355 ie_buf
[0] = WLAN_EID_SSID
;
356 ie_buf
[1] = msg2
.ssid
.data
.len
;
357 ie_len
= ie_buf
[1] + 2;
358 memcpy(&ie_buf
[2], &msg2
.ssid
.data
.data
, msg2
.ssid
.data
.len
);
359 freq
= ieee80211_channel_to_frequency(msg2
.dschannel
.data
,
361 bss
= cfg80211_inform_bss(wiphy
,
362 ieee80211_get_channel(wiphy
, freq
),
363 CFG80211_BSS_FTYPE_UNKNOWN
,
364 (const u8
*)&msg2
.bssid
.data
.data
,
365 msg2
.timestamp
.data
, msg2
.capinfo
.data
,
366 msg2
.beaconperiod
.data
,
369 (msg2
.signal
.data
- 65536) * 100, /* Conversion to signed type */
377 cfg80211_put_bss(wiphy
, bss
);
381 err
= prism2_result2err(msg2
.resultcode
.data
);
384 info
.aborted
= !!(err
);
385 cfg80211_scan_done(request
, &info
);
386 priv
->scan_request
= NULL
;
390 static int prism2_set_wiphy_params(struct wiphy
*wiphy
, u32 changed
)
392 struct prism2_wiphy_private
*priv
= wiphy_priv(wiphy
);
393 struct wlandevice
*wlandev
= priv
->wlandev
;
398 if (changed
& WIPHY_PARAM_RTS_THRESHOLD
) {
399 if (wiphy
->rts_threshold
== -1)
402 data
= wiphy
->rts_threshold
;
404 result
= prism2_domibset_uint32(wlandev
,
405 DIDMIB_DOT11MAC_OPERATIONTABLE_RTSTHRESHOLD
,
413 if (changed
& WIPHY_PARAM_FRAG_THRESHOLD
) {
414 if (wiphy
->frag_threshold
== -1)
417 data
= wiphy
->frag_threshold
;
419 result
= prism2_domibset_uint32(wlandev
,
420 DIDMIB_DOT11MAC_OPERATIONTABLE_FRAGMENTATIONTHRESHOLD
,
432 static int prism2_connect(struct wiphy
*wiphy
, struct net_device
*dev
,
433 struct cfg80211_connect_params
*sme
)
435 struct wlandevice
*wlandev
= dev
->ml_priv
;
436 struct ieee80211_channel
*channel
= sme
->channel
;
437 struct p80211msg_lnxreq_autojoin msg_join
;
439 int length
= sme
->ssid_len
;
441 int is_wep
= (sme
->crypto
.cipher_group
== WLAN_CIPHER_SUITE_WEP40
) ||
442 (sme
->crypto
.cipher_group
== WLAN_CIPHER_SUITE_WEP104
);
446 /* Set the channel */
448 chan
= ieee80211_frequency_to_channel(channel
->center_freq
);
449 result
= prism2_domibset_uint32(wlandev
,
450 DIDMIB_DOT11PHY_DSSSTABLE_CURRENTCHANNEL
,
456 /* Set the authorization */
457 if ((sme
->auth_type
== NL80211_AUTHTYPE_OPEN_SYSTEM
) ||
458 ((sme
->auth_type
== NL80211_AUTHTYPE_AUTOMATIC
) && !is_wep
))
459 msg_join
.authtype
.data
= P80211ENUM_authalg_opensystem
;
460 else if ((sme
->auth_type
== NL80211_AUTHTYPE_SHARED_KEY
) ||
461 ((sme
->auth_type
== NL80211_AUTHTYPE_AUTOMATIC
) && is_wep
))
462 msg_join
.authtype
.data
= P80211ENUM_authalg_sharedkey
;
465 "Unhandled authorisation type for connect (%d)\n",
468 /* Set the encryption - we only support wep */
471 if (sme
->key_idx
>= NUM_WEPKEYS
)
474 result
= prism2_domibset_uint32(wlandev
,
475 DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID
,
480 /* send key to driver */
481 did
= didmib_dot11smt_wepdefaultkeystable_key(
483 result
= prism2_domibset_pstr32(wlandev
,
490 /* Assume we should set privacy invoked and exclude unencrypted
491 * We could possible use sme->privacy here, but the assumption
492 * seems reasonable anyways
494 result
= prism2_domibset_uint32(wlandev
,
495 DIDMIB_DOT11SMT_PRIVACYTABLE_PRIVACYINVOKED
,
496 P80211ENUM_truth_true
);
500 result
= prism2_domibset_uint32(wlandev
,
501 DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED
,
502 P80211ENUM_truth_true
);
507 /* Assume we should unset privacy invoked
508 * and exclude unencrypted
510 result
= prism2_domibset_uint32(wlandev
,
511 DIDMIB_DOT11SMT_PRIVACYTABLE_PRIVACYINVOKED
,
512 P80211ENUM_truth_false
);
516 result
= prism2_domibset_uint32(wlandev
,
517 DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED
,
518 P80211ENUM_truth_false
);
523 /* Now do the actual join. Note there is no way that I can
524 * see to request a specific bssid
526 msg_join
.msgcode
= DIDMSG_LNXREQ_AUTOJOIN
;
528 memcpy(msg_join
.ssid
.data
.data
, sme
->ssid
, length
);
529 msg_join
.ssid
.data
.len
= length
;
531 result
= p80211req_dorequest(wlandev
, (u8
*)&msg_join
);
540 static int prism2_disconnect(struct wiphy
*wiphy
, struct net_device
*dev
,
543 struct wlandevice
*wlandev
= dev
->ml_priv
;
544 struct p80211msg_lnxreq_autojoin msg_join
;
548 /* Do a join, with a bogus ssid. Thats the only way I can think of */
549 msg_join
.msgcode
= DIDMSG_LNXREQ_AUTOJOIN
;
551 memcpy(msg_join
.ssid
.data
.data
, "---", 3);
552 msg_join
.ssid
.data
.len
= 3;
554 result
= p80211req_dorequest(wlandev
, (u8
*)&msg_join
);
562 static int prism2_join_ibss(struct wiphy
*wiphy
, struct net_device
*dev
,
563 struct cfg80211_ibss_params
*params
)
568 static int prism2_leave_ibss(struct wiphy
*wiphy
, struct net_device
*dev
)
573 static int prism2_set_tx_power(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
574 enum nl80211_tx_power_setting type
, int mbm
)
576 struct prism2_wiphy_private
*priv
= wiphy_priv(wiphy
);
577 struct wlandevice
*wlandev
= priv
->wlandev
;
582 if (type
== NL80211_TX_POWER_AUTOMATIC
)
585 data
= MBM_TO_DBM(mbm
);
587 result
= prism2_domibset_uint32(wlandev
,
588 DIDMIB_DOT11PHY_TXPOWERTABLE_CURRENTTXPOWERLEVEL
,
600 static int prism2_get_tx_power(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
603 struct prism2_wiphy_private
*priv
= wiphy_priv(wiphy
);
604 struct wlandevice
*wlandev
= priv
->wlandev
;
605 struct p80211msg_dot11req_mibget msg
;
606 struct p80211item_uint32
*mibitem
;
610 mibitem
= (struct p80211item_uint32
*)&msg
.mibattribute
.data
;
611 msg
.msgcode
= DIDMSG_DOT11REQ_MIBGET
;
612 mibitem
->did
= DIDMIB_DOT11PHY_TXPOWERTABLE_CURRENTTXPOWERLEVEL
;
614 result
= p80211req_dorequest(wlandev
, (u8
*)&msg
);
621 *dbm
= mibitem
->data
;
627 /* Interface callback functions, passing data back up to the cfg80211 layer */
628 void prism2_connect_result(struct wlandevice
*wlandev
, u8 failed
)
630 u16 status
= failed
?
631 WLAN_STATUS_UNSPECIFIED_FAILURE
: WLAN_STATUS_SUCCESS
;
633 cfg80211_connect_result(wlandev
->netdev
, wlandev
->bssid
,
634 NULL
, 0, NULL
, 0, status
, GFP_KERNEL
);
637 void prism2_disconnected(struct wlandevice
*wlandev
)
639 cfg80211_disconnected(wlandev
->netdev
, 0, NULL
,
640 0, false, GFP_KERNEL
);
643 void prism2_roamed(struct wlandevice
*wlandev
)
645 struct cfg80211_roam_info roam_info
= {
646 .bssid
= wlandev
->bssid
,
649 cfg80211_roamed(wlandev
->netdev
, &roam_info
, GFP_KERNEL
);
652 /* Structures for declaring wiphy interface */
653 static const struct cfg80211_ops prism2_usb_cfg_ops
= {
654 .change_virtual_intf
= prism2_change_virtual_intf
,
655 .add_key
= prism2_add_key
,
656 .get_key
= prism2_get_key
,
657 .del_key
= prism2_del_key
,
658 .set_default_key
= prism2_set_default_key
,
659 .get_station
= prism2_get_station
,
661 .set_wiphy_params
= prism2_set_wiphy_params
,
662 .connect
= prism2_connect
,
663 .disconnect
= prism2_disconnect
,
664 .join_ibss
= prism2_join_ibss
,
665 .leave_ibss
= prism2_leave_ibss
,
666 .set_tx_power
= prism2_set_tx_power
,
667 .get_tx_power
= prism2_get_tx_power
,
670 /* Functions to create/free wiphy interface */
671 static struct wiphy
*wlan_create_wiphy(struct device
*dev
,
672 struct wlandevice
*wlandev
)
675 struct prism2_wiphy_private
*priv
;
677 wiphy
= wiphy_new(&prism2_usb_cfg_ops
, sizeof(*priv
));
681 priv
= wiphy_priv(wiphy
);
682 priv
->wlandev
= wlandev
;
683 memcpy(priv
->channels
, prism2_channels
, sizeof(prism2_channels
));
684 memcpy(priv
->rates
, prism2_rates
, sizeof(prism2_rates
));
685 priv
->band
.channels
= priv
->channels
;
686 priv
->band
.n_channels
= ARRAY_SIZE(prism2_channels
);
687 priv
->band
.bitrates
= priv
->rates
;
688 priv
->band
.n_bitrates
= ARRAY_SIZE(prism2_rates
);
689 priv
->band
.band
= NL80211_BAND_2GHZ
;
690 priv
->band
.ht_cap
.ht_supported
= false;
691 wiphy
->bands
[NL80211_BAND_2GHZ
] = &priv
->band
;
693 set_wiphy_dev(wiphy
, dev
);
694 wiphy
->privid
= prism2_wiphy_privid
;
695 wiphy
->max_scan_ssids
= 1;
696 wiphy
->interface_modes
= BIT(NL80211_IFTYPE_STATION
)
697 | BIT(NL80211_IFTYPE_ADHOC
);
698 wiphy
->signal_type
= CFG80211_SIGNAL_TYPE_MBM
;
699 wiphy
->n_cipher_suites
= PRISM2_NUM_CIPHER_SUITES
;
700 wiphy
->cipher_suites
= prism2_cipher_suites
;
702 if (wiphy_register(wiphy
) < 0) {
710 static void wlan_free_wiphy(struct wiphy
*wiphy
)
712 wiphy_unregister(wiphy
);