1 /* cfg80211 Interface for prism2_usb module */
4 /* Prism2 channell/frequency/bitrate declarations */
5 static const struct ieee80211_channel prism2_channels
[] = {
6 { .center_freq
= 2412 },
7 { .center_freq
= 2417 },
8 { .center_freq
= 2422 },
9 { .center_freq
= 2427 },
10 { .center_freq
= 2432 },
11 { .center_freq
= 2437 },
12 { .center_freq
= 2442 },
13 { .center_freq
= 2447 },
14 { .center_freq
= 2452 },
15 { .center_freq
= 2457 },
16 { .center_freq
= 2462 },
17 { .center_freq
= 2467 },
18 { .center_freq
= 2472 },
19 { .center_freq
= 2484 },
22 static const struct ieee80211_rate prism2_rates
[] = {
29 #define PRISM2_NUM_CIPHER_SUITES 2
30 static const u32 prism2_cipher_suites
[PRISM2_NUM_CIPHER_SUITES
] = {
31 WLAN_CIPHER_SUITE_WEP40
,
32 WLAN_CIPHER_SUITE_WEP104
36 /* prism2 device private data */
37 struct prism2_wiphy_private
{
38 wlandevice_t
*wlandev
;
40 struct ieee80211_supported_band band
;
41 struct ieee80211_channel channels
[ARRAY_SIZE(prism2_channels
)];
42 struct ieee80211_rate rates
[ARRAY_SIZE(prism2_rates
)];
44 struct cfg80211_scan_request
*scan_request
;
47 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(wlandevice_t
*wlandev
, u32 did
, u32 data
)
75 struct p80211msg_dot11req_mibset msg
;
76 p80211item_uint32_t
*mibitem
= (p80211item_uint32_t
*) &msg
.mibattribute
.data
;
78 msg
.msgcode
= DIDmsg_dot11req_mibset
;
82 return p80211req_dorequest(wlandev
, (u8
*) &msg
);
85 static int prism2_domibset_pstr32(wlandevice_t
*wlandev
,
86 u32 did
, u8 len
, u8
*data
)
88 struct p80211msg_dot11req_mibset msg
;
89 p80211item_pstr32_t
*mibitem
= (p80211item_pstr32_t
*) &msg
.mibattribute
.data
;
91 msg
.msgcode
= DIDmsg_dot11req_mibset
;
93 mibitem
->data
.len
= len
;
94 memcpy(mibitem
->data
.data
, data
, len
);
96 return p80211req_dorequest(wlandev
, (u8
*) &msg
);
100 /* The interface functions, called by the cfg80211 layer */
101 int prism2_change_virtual_intf(struct wiphy
*wiphy
,
102 struct net_device
*dev
,
103 enum nl80211_iftype type
, u32
*flags
,
104 struct vif_params
*params
)
106 wlandevice_t
*wlandev
= dev
->ml_priv
;
112 case NL80211_IFTYPE_ADHOC
:
113 if (wlandev
->macmode
== WLAN_MACMODE_IBSS_STA
)
115 wlandev
->macmode
= WLAN_MACMODE_IBSS_STA
;
118 case NL80211_IFTYPE_STATION
:
119 if (wlandev
->macmode
== WLAN_MACMODE_ESS_STA
)
121 wlandev
->macmode
= WLAN_MACMODE_ESS_STA
;
125 printk(KERN_WARNING
"Operation mode: %d not support\n", type
);
129 /* Set Operation mode to the PORT TYPE RID */
130 result
= prism2_domibset_uint32(wlandev
, DIDmib_p2_p2Static_p2CnfPortType
, data
);
135 dev
->ieee80211_ptr
->iftype
= type
;
141 int prism2_add_key(struct wiphy
*wiphy
, struct net_device
*dev
,
142 u8 key_index
, bool pairwise
, const u8
*mac_addr
,
143 struct key_params
*params
)
145 wlandevice_t
*wlandev
= dev
->ml_priv
;
151 switch (params
->cipher
) {
152 case WLAN_CIPHER_SUITE_WEP40
:
153 case WLAN_CIPHER_SUITE_WEP104
:
154 result
= prism2_domibset_uint32(wlandev
,
155 DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID
,
160 /* send key to driver */
163 did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0
;
167 did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1
;
171 did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2
;
175 did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3
;
183 result
= prism2_domibset_pstr32(wlandev
, did
, params
->key_len
, params
->key
);
189 pr_debug("Unsupported cipher suite\n");
200 int prism2_get_key(struct wiphy
*wiphy
, struct net_device
*dev
,
201 u8 key_index
, bool pairwise
, const u8
*mac_addr
, void *cookie
,
202 void (*callback
)(void *cookie
, struct key_params
*))
204 wlandevice_t
*wlandev
= dev
->ml_priv
;
205 struct key_params params
;
208 if (key_index
>= NUM_WEPKEYS
)
211 len
= wlandev
->wep_keylens
[key_index
];
212 memset(¶ms
, 0, sizeof(params
));
215 params
.cipher
= WLAN_CIPHER_SUITE_WEP104
;
217 params
.cipher
= WLAN_CIPHER_SUITE_WEP104
;
220 params
.key_len
= len
;
221 params
.key
= wlandev
->wep_keys
[key_index
];
224 callback(cookie
, ¶ms
);
229 int prism2_del_key(struct wiphy
*wiphy
, struct net_device
*dev
,
230 u8 key_index
, bool pairwise
, const u8
*mac_addr
)
232 wlandevice_t
*wlandev
= dev
->ml_priv
;
237 /* There is no direct way in the hardware (AFAIK) of removing
238 a key, so we will cheat by setting the key to a bogus value */
239 /* send key to driver */
243 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0
;
248 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1
;
253 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2
;
258 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3
;
266 result
= prism2_domibset_pstr32(wlandev
, did
, 13, "0000000000000");
275 int prism2_set_default_key(struct wiphy
*wiphy
, struct net_device
*dev
,
276 u8 key_index
, bool unicast
, bool multicast
)
278 wlandevice_t
*wlandev
= dev
->ml_priv
;
283 result
= prism2_domibset_uint32(wlandev
,
284 DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID
,
294 int prism2_get_station(struct wiphy
*wiphy
, struct net_device
*dev
,
295 u8
*mac
, struct station_info
*sinfo
)
297 wlandevice_t
*wlandev
= dev
->ml_priv
;
298 struct p80211msg_lnxreq_commsquality quality
;
301 memset(sinfo
, 0, sizeof(*sinfo
));
303 if ((wlandev
== NULL
) || (wlandev
->msdstate
!= WLAN_MSD_RUNNING
))
306 /* build request message */
307 quality
.msgcode
= DIDmsg_lnxreq_commsquality
;
308 quality
.dbm
.data
= P80211ENUM_truth_true
;
309 quality
.dbm
.status
= P80211ENUM_msgitem_status_data_ok
;
311 /* send message to nsd */
312 if (wlandev
->mlmerequest
== NULL
)
315 result
= wlandev
->mlmerequest(wlandev
, (struct p80211msg
*) &quality
);
319 sinfo
->txrate
.legacy
= quality
.txrate
.data
;
320 sinfo
->filled
|= STATION_INFO_TX_BITRATE
;
321 sinfo
->signal
= quality
.level
.data
;
322 sinfo
->filled
|= STATION_INFO_SIGNAL
;
328 int prism2_scan(struct wiphy
*wiphy
, struct net_device
*dev
,
329 struct cfg80211_scan_request
*request
)
331 struct prism2_wiphy_private
*priv
= wiphy_priv(wiphy
);
332 wlandevice_t
*wlandev
= dev
->ml_priv
;
333 struct p80211msg_dot11req_scan msg1
;
334 struct p80211msg_dot11req_scan_results msg2
;
335 struct cfg80211_bss
*bss
;
346 if (priv
->scan_request
&& priv
->scan_request
!= request
)
349 if (wlandev
->macmode
== WLAN_MACMODE_ESS_AP
) {
350 printk(KERN_ERR
"Can't scan in AP mode\n");
354 priv
->scan_request
= request
;
356 memset(&msg1
, 0x00, sizeof(struct p80211msg_dot11req_scan
));
357 msg1
.msgcode
= DIDmsg_dot11req_scan
;
358 msg1
.bsstype
.data
= P80211ENUM_bsstype_any
;
360 memset(&msg1
.bssid
.data
.data
, 0xFF, sizeof(msg1
.bssid
.data
.data
));
361 msg1
.bssid
.data
.len
= 6;
363 if (request
->n_ssids
> 0) {
364 msg1
.scantype
.data
= P80211ENUM_scantype_active
;
365 msg1
.ssid
.data
.len
= request
->ssids
->ssid_len
;
366 memcpy(msg1
.ssid
.data
.data
, request
->ssids
->ssid
, request
->ssids
->ssid_len
);
368 msg1
.scantype
.data
= 0;
370 msg1
.probedelay
.data
= 0;
373 (i
< request
->n_channels
) && i
< ARRAY_SIZE(prism2_channels
);
375 msg1
.channellist
.data
.data
[i
] =
376 ieee80211_frequency_to_channel(request
->channels
[i
]->center_freq
);
377 msg1
.channellist
.data
.len
= request
->n_channels
;
379 msg1
.maxchanneltime
.data
= 250;
380 msg1
.minchanneltime
.data
= 200;
382 result
= p80211req_dorequest(wlandev
, (u8
*) &msg1
);
384 err
= prism2_result2err(msg1
.resultcode
.data
);
387 /* Now retrieve scan results */
388 numbss
= msg1
.numbss
.data
;
390 for (i
= 0; i
< numbss
; i
++) {
391 memset(&msg2
, 0, sizeof(msg2
));
392 msg2
.msgcode
= DIDmsg_dot11req_scan_results
;
393 msg2
.bssindex
.data
= i
;
395 result
= p80211req_dorequest(wlandev
, (u8
*) &msg2
);
397 (msg2
.resultcode
.data
!= P80211ENUM_resultcode_success
)) {
401 ie_buf
[0] = WLAN_EID_SSID
;
402 ie_buf
[1] = msg2
.ssid
.data
.len
;
403 ie_len
= ie_buf
[1] + 2;
404 memcpy(&ie_buf
[2], &(msg2
.ssid
.data
.data
), msg2
.ssid
.data
.len
);
405 bss
= cfg80211_inform_bss(wiphy
,
406 ieee80211_get_channel(wiphy
, ieee80211_dsss_chan_to_freq(msg2
.dschannel
.data
)),
407 (const u8
*) &(msg2
.bssid
.data
.data
),
408 msg2
.timestamp
.data
, msg2
.capinfo
.data
,
409 msg2
.beaconperiod
.data
,
412 (msg2
.signal
.data
- 65536) * 100, /* Conversion to signed type */
421 cfg80211_put_bss(bss
);
425 err
= prism2_result2err(msg2
.resultcode
.data
);
428 cfg80211_scan_done(request
, err
? 1 : 0);
429 priv
->scan_request
= NULL
;
433 int prism2_set_wiphy_params(struct wiphy
*wiphy
, u32 changed
)
435 struct prism2_wiphy_private
*priv
= wiphy_priv(wiphy
);
436 wlandevice_t
*wlandev
= priv
->wlandev
;
441 if (changed
& WIPHY_PARAM_RTS_THRESHOLD
) {
442 if (wiphy
->rts_threshold
== -1)
445 data
= wiphy
->rts_threshold
;
447 result
= prism2_domibset_uint32(wlandev
,
448 DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold
,
456 if (changed
& WIPHY_PARAM_FRAG_THRESHOLD
) {
457 if (wiphy
->frag_threshold
== -1)
460 data
= wiphy
->frag_threshold
;
462 result
= prism2_domibset_uint32(wlandev
,
463 DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold
,
475 int prism2_connect(struct wiphy
*wiphy
, struct net_device
*dev
,
476 struct cfg80211_connect_params
*sme
)
478 wlandevice_t
*wlandev
= dev
->ml_priv
;
479 struct ieee80211_channel
*channel
= sme
->channel
;
480 struct p80211msg_lnxreq_autojoin msg_join
;
482 int length
= sme
->ssid_len
;
484 int is_wep
= (sme
->crypto
.cipher_group
== WLAN_CIPHER_SUITE_WEP40
) ||
485 (sme
->crypto
.cipher_group
== WLAN_CIPHER_SUITE_WEP104
);
489 /* Set the channel */
491 chan
= ieee80211_frequency_to_channel(channel
->center_freq
);
492 result
= prism2_domibset_uint32(wlandev
,
493 DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel
,
499 /* Set the authorisation */
500 if ((sme
->auth_type
== NL80211_AUTHTYPE_OPEN_SYSTEM
) ||
501 ((sme
->auth_type
== NL80211_AUTHTYPE_AUTOMATIC
) && !is_wep
))
502 msg_join
.authtype
.data
= P80211ENUM_authalg_opensystem
;
503 else if ((sme
->auth_type
== NL80211_AUTHTYPE_SHARED_KEY
) ||
504 ((sme
->auth_type
== NL80211_AUTHTYPE_AUTOMATIC
) && is_wep
))
505 msg_join
.authtype
.data
= P80211ENUM_authalg_sharedkey
;
508 "Unhandled authorisation type for connect (%d)\n",
511 /* Set the encryption - we only support wep */
514 result
= prism2_domibset_uint32(wlandev
,
515 DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID
,
520 /* send key to driver */
521 switch (sme
->key_idx
) {
523 did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0
;
527 did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1
;
531 did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2
;
535 did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3
;
543 result
= prism2_domibset_pstr32(wlandev
, did
, sme
->key_len
, (u8
*) sme
->key
);
549 /* Assume we should set privacy invoked and exclude unencrypted
550 We could possibly use sme->privacy here, but the assumption
551 seems reasonable anyway */
552 result
= prism2_domibset_uint32(wlandev
,
553 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked
,
554 P80211ENUM_truth_true
);
558 result
= prism2_domibset_uint32(wlandev
,
559 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted
,
560 P80211ENUM_truth_true
);
565 /* Assume we should unset privacy invoked
566 and exclude unencrypted */
567 result
= prism2_domibset_uint32(wlandev
,
568 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked
,
569 P80211ENUM_truth_false
);
573 result
= prism2_domibset_uint32(wlandev
,
574 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted
,
575 P80211ENUM_truth_false
);
581 /* Now do the actual join. Note there is no way that I can
582 see to request a specific bssid */
583 msg_join
.msgcode
= DIDmsg_lnxreq_autojoin
;
585 memcpy(msg_join
.ssid
.data
.data
, sme
->ssid
, length
);
586 msg_join
.ssid
.data
.len
= length
;
588 result
= p80211req_dorequest(wlandev
, (u8
*) &msg_join
);
597 int prism2_disconnect(struct wiphy
*wiphy
, struct net_device
*dev
,
600 wlandevice_t
*wlandev
= dev
->ml_priv
;
601 struct p80211msg_lnxreq_autojoin msg_join
;
606 /* Do a join, with a bogus ssid. Thats the only way I can think of */
607 msg_join
.msgcode
= DIDmsg_lnxreq_autojoin
;
609 memcpy(msg_join
.ssid
.data
.data
, "---", 3);
610 msg_join
.ssid
.data
.len
= 3;
612 result
= p80211req_dorequest(wlandev
, (u8
*) &msg_join
);
621 int prism2_join_ibss(struct wiphy
*wiphy
, struct net_device
*dev
,
622 struct cfg80211_ibss_params
*params
)
627 int prism2_leave_ibss(struct wiphy
*wiphy
, struct net_device
*dev
)
633 int prism2_set_tx_power(struct wiphy
*wiphy
, enum nl80211_tx_power_setting type
,
636 struct prism2_wiphy_private
*priv
= wiphy_priv(wiphy
);
637 wlandevice_t
*wlandev
= priv
->wlandev
;
642 if (type
== NL80211_TX_POWER_AUTOMATIC
)
645 data
= MBM_TO_DBM(mbm
);
647 result
= prism2_domibset_uint32(wlandev
,
648 DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel
,
660 int prism2_get_tx_power(struct wiphy
*wiphy
, int *dbm
)
662 struct prism2_wiphy_private
*priv
= wiphy_priv(wiphy
);
663 wlandevice_t
*wlandev
= priv
->wlandev
;
664 struct p80211msg_dot11req_mibget msg
;
665 p80211item_uint32_t
*mibitem
= (p80211item_uint32_t
*) &msg
.mibattribute
.data
;
669 msg
.msgcode
= DIDmsg_dot11req_mibget
;
671 DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel
;
673 result
= p80211req_dorequest(wlandev
, (u8
*) &msg
);
680 *dbm
= mibitem
->data
;
689 /* Interface callback functions, passing data back up to the cfg80211 layer */
690 void prism2_connect_result(wlandevice_t
*wlandev
, u8 failed
)
692 u16 status
= failed
? WLAN_STATUS_UNSPECIFIED_FAILURE
: WLAN_STATUS_SUCCESS
;
694 cfg80211_connect_result(wlandev
->netdev
, wlandev
->bssid
,
695 NULL
, 0, NULL
, 0, status
, GFP_KERNEL
);
698 void prism2_disconnected(wlandevice_t
*wlandev
)
700 cfg80211_disconnected(wlandev
->netdev
, 0, NULL
,
704 void prism2_roamed(wlandevice_t
*wlandev
)
706 cfg80211_roamed(wlandev
->netdev
, NULL
, wlandev
->bssid
,
707 NULL
, 0, NULL
, 0, GFP_KERNEL
);
711 /* Structures for declaring wiphy interface */
712 static const struct cfg80211_ops prism2_usb_cfg_ops
= {
713 .change_virtual_intf
= prism2_change_virtual_intf
,
714 .add_key
= prism2_add_key
,
715 .get_key
= prism2_get_key
,
716 .del_key
= prism2_del_key
,
717 .set_default_key
= prism2_set_default_key
,
718 .get_station
= prism2_get_station
,
720 .set_wiphy_params
= prism2_set_wiphy_params
,
721 .connect
= prism2_connect
,
722 .disconnect
= prism2_disconnect
,
723 .join_ibss
= prism2_join_ibss
,
724 .leave_ibss
= prism2_leave_ibss
,
725 .set_tx_power
= prism2_set_tx_power
,
726 .get_tx_power
= prism2_get_tx_power
,
730 /* Functions to create/free wiphy interface */
731 struct wiphy
*wlan_create_wiphy(struct device
*dev
, wlandevice_t
*wlandev
)
734 struct prism2_wiphy_private
*priv
;
735 wiphy
= wiphy_new(&prism2_usb_cfg_ops
, sizeof(struct prism2_wiphy_private
));
739 priv
= wiphy_priv(wiphy
);
740 priv
->wlandev
= wlandev
;
741 memcpy(priv
->channels
, prism2_channels
, sizeof(prism2_channels
));
742 memcpy(priv
->rates
, prism2_rates
, sizeof(prism2_rates
));
743 priv
->band
.channels
= priv
->channels
;
744 priv
->band
.n_channels
= ARRAY_SIZE(prism2_channels
);
745 priv
->band
.bitrates
= priv
->rates
;
746 priv
->band
.n_bitrates
= ARRAY_SIZE(prism2_rates
);
747 priv
->band
.band
= IEEE80211_BAND_2GHZ
;
748 priv
->band
.ht_cap
.ht_supported
= false;
749 wiphy
->bands
[IEEE80211_BAND_2GHZ
] = &priv
->band
;
751 set_wiphy_dev(wiphy
, dev
);
752 wiphy
->privid
= prism2_wiphy_privid
;
753 wiphy
->max_scan_ssids
= 1;
754 wiphy
->interface_modes
= BIT(NL80211_IFTYPE_STATION
)
755 | BIT(NL80211_IFTYPE_ADHOC
);
756 wiphy
->signal_type
= CFG80211_SIGNAL_TYPE_MBM
;
757 wiphy
->n_cipher_suites
= PRISM2_NUM_CIPHER_SUITES
;
758 wiphy
->cipher_suites
= prism2_cipher_suites
;
760 if (wiphy_register(wiphy
) < 0)
767 void wlan_free_wiphy(struct wiphy
*wiphy
)
769 wiphy_unregister(wiphy
);