1cb3126e6SKarl Relton /* cfg80211 Interface for prism2_usb module */
26eaf0788STair Rzayev #include "hfa384x.h"
36eaf0788STair Rzayev #include "prism2mgmt.h"
4cb3126e6SKarl Relton 
5d34602deSJustin P. Mattock /* Prism2 channel/frequency/bitrate declarations */
6cb3126e6SKarl Relton static const struct ieee80211_channel prism2_channels[] = {
7cb3126e6SKarl Relton 	{ .center_freq = 2412 },
8cb3126e6SKarl Relton 	{ .center_freq = 2417 },
9cb3126e6SKarl Relton 	{ .center_freq = 2422 },
10cb3126e6SKarl Relton 	{ .center_freq = 2427 },
11cb3126e6SKarl Relton 	{ .center_freq = 2432 },
12cb3126e6SKarl Relton 	{ .center_freq = 2437 },
13cb3126e6SKarl Relton 	{ .center_freq = 2442 },
14cb3126e6SKarl Relton 	{ .center_freq = 2447 },
15cb3126e6SKarl Relton 	{ .center_freq = 2452 },
16cb3126e6SKarl Relton 	{ .center_freq = 2457 },
17cb3126e6SKarl Relton 	{ .center_freq = 2462 },
18cb3126e6SKarl Relton 	{ .center_freq = 2467 },
19cb3126e6SKarl Relton 	{ .center_freq = 2472 },
20cb3126e6SKarl Relton 	{ .center_freq = 2484 },
21cb3126e6SKarl Relton };
22cb3126e6SKarl Relton 
23cb3126e6SKarl Relton static const struct ieee80211_rate prism2_rates[] = {
24cb3126e6SKarl Relton 	{ .bitrate = 10 },
25cb3126e6SKarl Relton 	{ .bitrate = 20 },
26cb3126e6SKarl Relton 	{ .bitrate = 55 },
27cb3126e6SKarl Relton 	{ .bitrate = 110 }
28cb3126e6SKarl Relton };
29cb3126e6SKarl Relton 
30cb3126e6SKarl Relton #define PRISM2_NUM_CIPHER_SUITES 2
31cb3126e6SKarl Relton static const u32 prism2_cipher_suites[PRISM2_NUM_CIPHER_SUITES] = {
32cb3126e6SKarl Relton 	WLAN_CIPHER_SUITE_WEP40,
33cb3126e6SKarl Relton 	WLAN_CIPHER_SUITE_WEP104
34cb3126e6SKarl Relton };
35cb3126e6SKarl Relton 
36cb3126e6SKarl Relton /* prism2 device private data */
37cb3126e6SKarl Relton struct prism2_wiphy_private {
38c9573a8dSsayli karnik 	struct wlandevice *wlandev;
39cb3126e6SKarl Relton 
40cb3126e6SKarl Relton 	struct ieee80211_supported_band band;
41cb3126e6SKarl Relton 	struct ieee80211_channel channels[ARRAY_SIZE(prism2_channels)];
42cb3126e6SKarl Relton 	struct ieee80211_rate rates[ARRAY_SIZE(prism2_rates)];
43cb3126e6SKarl Relton 
44cb3126e6SKarl Relton 	struct cfg80211_scan_request *scan_request;
45cb3126e6SKarl Relton };
46cb3126e6SKarl Relton 
47cb3126e6SKarl Relton static const void * const prism2_wiphy_privid = &prism2_wiphy_privid;
48cb3126e6SKarl Relton 
49cb3126e6SKarl Relton /* Helper Functions */
50cb3126e6SKarl Relton static int prism2_result2err(int prism2_result)
51cb3126e6SKarl Relton {
52cb3126e6SKarl Relton 	int err = 0;
53cb3126e6SKarl Relton 
54cb3126e6SKarl Relton 	switch (prism2_result) {
55cb3126e6SKarl Relton 	case P80211ENUM_resultcode_invalid_parameters:
56cb3126e6SKarl Relton 		err = -EINVAL;
57cb3126e6SKarl Relton 		break;
58cb3126e6SKarl Relton 	case P80211ENUM_resultcode_implementation_failure:
59cb3126e6SKarl Relton 		err = -EIO;
60cb3126e6SKarl Relton 		break;
61cb3126e6SKarl Relton 	case P80211ENUM_resultcode_not_supported:
62cb3126e6SKarl Relton 		err = -EOPNOTSUPP;
63cb3126e6SKarl Relton 		break;
64cb3126e6SKarl Relton 	default:
65cb3126e6SKarl Relton 		err = 0;
66cb3126e6SKarl Relton 		break;
67cb3126e6SKarl Relton 	}
68cb3126e6SKarl Relton 
69cb3126e6SKarl Relton 	return err;
70cb3126e6SKarl Relton }
71cb3126e6SKarl Relton 
72c9573a8dSsayli karnik static int prism2_domibset_uint32(struct wlandevice *wlandev, u32 did, u32 data)
73cb3126e6SKarl Relton {
74b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_mibset msg;
75b26b2325SSergio Paracuellos 	struct p80211item_uint32 *mibitem =
76b26b2325SSergio Paracuellos 			(struct p80211item_uint32 *)&msg.mibattribute.data;
77cb3126e6SKarl Relton 
78cb3126e6SKarl Relton 	msg.msgcode = DIDmsg_dot11req_mibset;
79cb3126e6SKarl Relton 	mibitem->did = did;
80cb3126e6SKarl Relton 	mibitem->data = data;
81cb3126e6SKarl Relton 
82cb3126e6SKarl Relton 	return p80211req_dorequest(wlandev, (u8 *)&msg);
83cb3126e6SKarl Relton }
84cb3126e6SKarl Relton 
85c9573a8dSsayli karnik static int prism2_domibset_pstr32(struct wlandevice *wlandev,
86c1e5f471SJohannes Berg 				  u32 did, u8 len, const u8 *data)
87cb3126e6SKarl Relton {
88b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_mibset msg;
896a50b5afSSergio Paracuellos 	struct p80211item_pstr32 *mibitem =
906a50b5afSSergio Paracuellos 			(struct p80211item_pstr32 *)&msg.mibattribute.data;
91cb3126e6SKarl Relton 
92cb3126e6SKarl Relton 	msg.msgcode = DIDmsg_dot11req_mibset;
93cb3126e6SKarl Relton 	mibitem->did = did;
94cb3126e6SKarl Relton 	mibitem->data.len = len;
95cb3126e6SKarl Relton 	memcpy(mibitem->data.data, data, len);
96cb3126e6SKarl Relton 
97cb3126e6SKarl Relton 	return p80211req_dorequest(wlandev, (u8 *)&msg);
98cb3126e6SKarl Relton }
99cb3126e6SKarl Relton 
100cb3126e6SKarl Relton /* The interface functions, called by the cfg80211 layer */
10155da06ebSTeodora Baluta static int prism2_change_virtual_intf(struct wiphy *wiphy,
102cb3126e6SKarl Relton 				      struct net_device *dev,
103818a986eSJohannes Berg 				      enum nl80211_iftype type,
104cb3126e6SKarl Relton 				      struct vif_params *params)
105cb3126e6SKarl Relton {
106c9573a8dSsayli karnik 	struct wlandevice *wlandev = dev->ml_priv;
107cb3126e6SKarl Relton 	u32 data;
108cb3126e6SKarl Relton 	int result;
109cb3126e6SKarl Relton 	int err = 0;
110cb3126e6SKarl Relton 
111cb3126e6SKarl Relton 	switch (type) {
112cb3126e6SKarl Relton 	case NL80211_IFTYPE_ADHOC:
1138dd82ebeSEdgardo Hames 		if (wlandev->macmode == WLAN_MACMODE_IBSS_STA)
1148dd82ebeSEdgardo Hames 			goto exit;
115cb3126e6SKarl Relton 		wlandev->macmode = WLAN_MACMODE_IBSS_STA;
116cb3126e6SKarl Relton 		data = 0;
117cb3126e6SKarl Relton 		break;
118cb3126e6SKarl Relton 	case NL80211_IFTYPE_STATION:
1198dd82ebeSEdgardo Hames 		if (wlandev->macmode == WLAN_MACMODE_ESS_STA)
1208dd82ebeSEdgardo Hames 			goto exit;
121cb3126e6SKarl Relton 		wlandev->macmode = WLAN_MACMODE_ESS_STA;
122cb3126e6SKarl Relton 		data = 1;
123cb3126e6SKarl Relton 		break;
124cb3126e6SKarl Relton 	default:
125eed88971SAvinash Kumar 		netdev_warn(dev, "Operation mode: %d not support\n", type);
126cb3126e6SKarl Relton 		return -EOPNOTSUPP;
127cb3126e6SKarl Relton 	}
128cb3126e6SKarl Relton 
129cb3126e6SKarl Relton 	/* Set Operation mode to the PORT TYPE RID */
1308aac4d44SDevendra Naga 	result = prism2_domibset_uint32(wlandev,
1318aac4d44SDevendra Naga 					DIDmib_p2_p2Static_p2CnfPortType,
1328aac4d44SDevendra Naga 					data);
133cb3126e6SKarl Relton 
134cb3126e6SKarl Relton 	if (result)
135cb3126e6SKarl Relton 		err = -EFAULT;
136cb3126e6SKarl Relton 
137cb3126e6SKarl Relton 	dev->ieee80211_ptr->iftype = type;
138cb3126e6SKarl Relton 
139cb3126e6SKarl Relton exit:
140cb3126e6SKarl Relton 	return err;
141cb3126e6SKarl Relton }
142cb3126e6SKarl Relton 
14355da06ebSTeodora Baluta static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev,
14434a488c1SBen Hutchings 			  u8 key_index, bool pairwise, const u8 *mac_addr,
1458dd82ebeSEdgardo Hames 			  struct key_params *params)
1468dd82ebeSEdgardo Hames {
147c9573a8dSsayli karnik 	struct wlandevice *wlandev = dev->ml_priv;
148cb3126e6SKarl Relton 	u32 did;
149cb3126e6SKarl Relton 
150cb3126e6SKarl Relton 	int err = 0;
151cb3126e6SKarl Relton 	int result = 0;
152cb3126e6SKarl Relton 
1530ca6d8e7SClaudiu Beznea 	if (key_index >= NUM_WEPKEYS)
1540ca6d8e7SClaudiu Beznea 		return -EINVAL;
1550ca6d8e7SClaudiu Beznea 
156cb3126e6SKarl Relton 	switch (params->cipher) {
157cb3126e6SKarl Relton 	case WLAN_CIPHER_SUITE_WEP40:
158cb3126e6SKarl Relton 	case WLAN_CIPHER_SUITE_WEP104:
159cb3126e6SKarl Relton 		result = prism2_domibset_uint32(wlandev,
160cb3126e6SKarl Relton 						DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
161cb3126e6SKarl Relton 						key_index);
1628dd82ebeSEdgardo Hames 		if (result)
1638dd82ebeSEdgardo Hames 			goto exit;
164cb3126e6SKarl Relton 
165cb3126e6SKarl Relton 		/* send key to driver */
1660ca6d8e7SClaudiu Beznea 		did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(key_index + 1);
167cb3126e6SKarl Relton 
168bb1da756SHimangi Saraogi 		result = prism2_domibset_pstr32(wlandev, did,
169bb1da756SHimangi Saraogi 						params->key_len, params->key);
1708dd82ebeSEdgardo Hames 		if (result)
1718dd82ebeSEdgardo Hames 			goto exit;
172cb3126e6SKarl Relton 		break;
173cb3126e6SKarl Relton 
174cb3126e6SKarl Relton 	default:
175cb3126e6SKarl Relton 		pr_debug("Unsupported cipher suite\n");
176cb3126e6SKarl Relton 		result = 1;
177cb3126e6SKarl Relton 	}
178cb3126e6SKarl Relton 
179cb3126e6SKarl Relton exit:
1808dd82ebeSEdgardo Hames 	if (result)
1818dd82ebeSEdgardo Hames 		err = -EFAULT;
182cb3126e6SKarl Relton 
183cb3126e6SKarl Relton 	return err;
184cb3126e6SKarl Relton }
185cb3126e6SKarl Relton 
18655da06ebSTeodora Baluta static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev,
18755da06ebSTeodora Baluta 			  u8 key_index, bool pairwise,
18855da06ebSTeodora Baluta 			  const u8 *mac_addr, void *cookie,
1898dd82ebeSEdgardo Hames 			  void (*callback)(void *cookie, struct key_params*))
1908dd82ebeSEdgardo Hames {
191c9573a8dSsayli karnik 	struct wlandevice *wlandev = dev->ml_priv;
192cb3126e6SKarl Relton 	struct key_params params;
193cb3126e6SKarl Relton 	int len;
194cb3126e6SKarl Relton 
1958dd82ebeSEdgardo Hames 	if (key_index >= NUM_WEPKEYS)
1968dd82ebeSEdgardo Hames 		return -EINVAL;
197cb3126e6SKarl Relton 
198cb3126e6SKarl Relton 	len = wlandev->wep_keylens[key_index];
199cb3126e6SKarl Relton 	memset(&params, 0, sizeof(params));
200cb3126e6SKarl Relton 
2018dd82ebeSEdgardo Hames 	if (len == 13)
202cb3126e6SKarl Relton 		params.cipher = WLAN_CIPHER_SUITE_WEP104;
2038dd82ebeSEdgardo Hames 	else if (len == 5)
204cb3126e6SKarl Relton 		params.cipher = WLAN_CIPHER_SUITE_WEP104;
2058dd82ebeSEdgardo Hames 	else
2068dd82ebeSEdgardo Hames 		return -ENOENT;
207cb3126e6SKarl Relton 	params.key_len = len;
208cb3126e6SKarl Relton 	params.key = wlandev->wep_keys[key_index];
209aff3ea4eSKarl Relton 	params.seq_len = 0;
210cb3126e6SKarl Relton 
211cb3126e6SKarl Relton 	callback(cookie, &params);
2128dd82ebeSEdgardo Hames 
213cb3126e6SKarl Relton 	return 0;
214cb3126e6SKarl Relton }
215cb3126e6SKarl Relton 
21655da06ebSTeodora Baluta static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev,
21734a488c1SBen Hutchings 			  u8 key_index, bool pairwise, const u8 *mac_addr)
2188dd82ebeSEdgardo Hames {
219c9573a8dSsayli karnik 	struct wlandevice *wlandev = dev->ml_priv;
220cb3126e6SKarl Relton 	u32 did;
221cb3126e6SKarl Relton 	int err = 0;
222cb3126e6SKarl Relton 	int result = 0;
223cb3126e6SKarl Relton 
224cb3126e6SKarl Relton 	/* There is no direct way in the hardware (AFAIK) of removing
22535028fe1SGavin O'Leary 	 * a key, so we will cheat by setting the key to a bogus value
22635028fe1SGavin O'Leary 	 */
22735028fe1SGavin O'Leary 
2280ca6d8e7SClaudiu Beznea 	if (key_index >= NUM_WEPKEYS)
2290ca6d8e7SClaudiu Beznea 		return -EINVAL;
2300ca6d8e7SClaudiu Beznea 
231cb3126e6SKarl Relton 	/* send key to driver */
2320ca6d8e7SClaudiu Beznea 	did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(key_index + 1);
233cb3126e6SKarl Relton 	result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000");
234cb3126e6SKarl Relton 
2358dd82ebeSEdgardo Hames 	if (result)
2368dd82ebeSEdgardo Hames 		err = -EFAULT;
237cb3126e6SKarl Relton 
238cb3126e6SKarl Relton 	return err;
239cb3126e6SKarl Relton }
240cb3126e6SKarl Relton 
24155da06ebSTeodora Baluta static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
2429005fcd8SHarry Wei 				  u8 key_index, bool unicast, bool multicast)
2438dd82ebeSEdgardo Hames {
244c9573a8dSsayli karnik 	struct wlandevice *wlandev = dev->ml_priv;
245cb3126e6SKarl Relton 
246cb3126e6SKarl Relton 	int err = 0;
247cb3126e6SKarl Relton 	int result = 0;
248cb3126e6SKarl Relton 
249cb3126e6SKarl Relton 	result = prism2_domibset_uint32(wlandev,
250cb3126e6SKarl Relton 		DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
251cb3126e6SKarl Relton 		key_index);
252cb3126e6SKarl Relton 
2538dd82ebeSEdgardo Hames 	if (result)
2548dd82ebeSEdgardo Hames 		err = -EFAULT;
255cb3126e6SKarl Relton 
256cb3126e6SKarl Relton 	return err;
257cb3126e6SKarl Relton }
258cb3126e6SKarl Relton 
25955da06ebSTeodora Baluta static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
2603b3a0162SJohannes Berg 			      const u8 *mac, struct station_info *sinfo)
2618dd82ebeSEdgardo Hames {
262c9573a8dSsayli karnik 	struct wlandevice *wlandev = dev->ml_priv;
263b6bb56e6SEdgardo Hames 	struct p80211msg_lnxreq_commsquality quality;
264cb3126e6SKarl Relton 	int result;
265cb3126e6SKarl Relton 
266cb3126e6SKarl Relton 	memset(sinfo, 0, sizeof(*sinfo));
267cb3126e6SKarl Relton 
268e52f2149SSandhya Bankar 	if (!wlandev || (wlandev->msdstate != WLAN_MSD_RUNNING))
269cb3126e6SKarl Relton 		return -EOPNOTSUPP;
270cb3126e6SKarl Relton 
271cb3126e6SKarl Relton 	/* build request message */
272cb3126e6SKarl Relton 	quality.msgcode = DIDmsg_lnxreq_commsquality;
273cb3126e6SKarl Relton 	quality.dbm.data = P80211ENUM_truth_true;
274cb3126e6SKarl Relton 	quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
275cb3126e6SKarl Relton 
276cb3126e6SKarl Relton 	/* send message to nsd */
277e52f2149SSandhya Bankar 	if (!wlandev->mlmerequest)
278cb3126e6SKarl Relton 		return -EOPNOTSUPP;
279cb3126e6SKarl Relton 
2803d049431SEdgardo Hames 	result = wlandev->mlmerequest(wlandev, (struct p80211msg *)&quality);
281cb3126e6SKarl Relton 
282cb3126e6SKarl Relton 	if (result == 0) {
283cb3126e6SKarl Relton 		sinfo->txrate.legacy = quality.txrate.data;
284319090bfSJohannes Berg 		sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
285cb3126e6SKarl Relton 		sinfo->signal = quality.level.data;
286319090bfSJohannes Berg 		sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
287cb3126e6SKarl Relton 	}
288cb3126e6SKarl Relton 
289cb3126e6SKarl Relton 	return result;
290cb3126e6SKarl Relton }
291cb3126e6SKarl Relton 
292bb1da756SHimangi Saraogi static int prism2_scan(struct wiphy *wiphy,
293bb1da756SHimangi Saraogi 		       struct cfg80211_scan_request *request)
294cb3126e6SKarl Relton {
2955d5d7c3bSEmil Goode 	struct net_device *dev;
296cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
297c9573a8dSsayli karnik 	struct wlandevice *wlandev;
298b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_scan msg1;
299b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_scan_results msg2;
30019f798adSKrzysztof Wilczynski 	struct cfg80211_bss *bss;
3011d76250bSAvraham Stern 	struct cfg80211_scan_info info = {};
3021d76250bSAvraham Stern 
303cb3126e6SKarl Relton 	int result;
304cb3126e6SKarl Relton 	int err = 0;
305cb3126e6SKarl Relton 	int numbss = 0;
306cb3126e6SKarl Relton 	int i = 0;
307cb3126e6SKarl Relton 	u8 ie_buf[46];
308cb3126e6SKarl Relton 	int ie_len;
309cb3126e6SKarl Relton 
310cb3126e6SKarl Relton 	if (!request)
311cb3126e6SKarl Relton 		return -EINVAL;
312cb3126e6SKarl Relton 
3135d5d7c3bSEmil Goode 	dev = request->wdev->netdev;
3145d5d7c3bSEmil Goode 	wlandev = dev->ml_priv;
3155d5d7c3bSEmil Goode 
316cb3126e6SKarl Relton 	if (priv->scan_request && priv->scan_request != request)
317cb3126e6SKarl Relton 		return -EBUSY;
318cb3126e6SKarl Relton 
319cb3126e6SKarl Relton 	if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
320eed88971SAvinash Kumar 		netdev_err(dev, "Can't scan in AP mode\n");
321cb3126e6SKarl Relton 		return -EOPNOTSUPP;
322cb3126e6SKarl Relton 	}
323cb3126e6SKarl Relton 
324cb3126e6SKarl Relton 	priv->scan_request = request;
325cb3126e6SKarl Relton 
32689e13b45SSergio Paracuellos 	memset(&msg1, 0x00, sizeof(msg1));
327cb3126e6SKarl Relton 	msg1.msgcode = DIDmsg_dot11req_scan;
328cb3126e6SKarl Relton 	msg1.bsstype.data = P80211ENUM_bsstype_any;
329cb3126e6SKarl Relton 
330625aeb3aSDan Carpenter 	memset(&msg1.bssid.data.data, 0xFF, sizeof(msg1.bssid.data.data));
331cb3126e6SKarl Relton 	msg1.bssid.data.len = 6;
332cb3126e6SKarl Relton 
333cb3126e6SKarl Relton 	if (request->n_ssids > 0) {
334cb3126e6SKarl Relton 		msg1.scantype.data = P80211ENUM_scantype_active;
335cb3126e6SKarl Relton 		msg1.ssid.data.len = request->ssids->ssid_len;
3368aac4d44SDevendra Naga 		memcpy(msg1.ssid.data.data,
3378aac4d44SDevendra Naga 		       request->ssids->ssid, request->ssids->ssid_len);
338cb3126e6SKarl Relton 	} else {
339cb3126e6SKarl Relton 		msg1.scantype.data = 0;
340cb3126e6SKarl Relton 	}
341cb3126e6SKarl Relton 	msg1.probedelay.data = 0;
342cb3126e6SKarl Relton 
343cb3126e6SKarl Relton 	for (i = 0;
344cb3126e6SKarl Relton 		(i < request->n_channels) && i < ARRAY_SIZE(prism2_channels);
345cb3126e6SKarl Relton 		i++)
346cb3126e6SKarl Relton 		msg1.channellist.data.data[i] =
347bb1da756SHimangi Saraogi 			ieee80211_frequency_to_channel(
348bb1da756SHimangi Saraogi 				request->channels[i]->center_freq);
349cb3126e6SKarl Relton 	msg1.channellist.data.len = request->n_channels;
350cb3126e6SKarl Relton 
351cb3126e6SKarl Relton 	msg1.maxchanneltime.data = 250;
352cb3126e6SKarl Relton 	msg1.minchanneltime.data = 200;
353cb3126e6SKarl Relton 
354cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *)&msg1);
355cb3126e6SKarl Relton 	if (result) {
356cb3126e6SKarl Relton 		err = prism2_result2err(msg1.resultcode.data);
357cb3126e6SKarl Relton 		goto exit;
358cb3126e6SKarl Relton 	}
359cb3126e6SKarl Relton 	/* Now retrieve scan results */
360cb3126e6SKarl Relton 	numbss = msg1.numbss.data;
361cb3126e6SKarl Relton 
362cb3126e6SKarl Relton 	for (i = 0; i < numbss; i++) {
3634e5e9d7cSZhao, Gang 		int freq;
3644e5e9d7cSZhao, Gang 
365cb3126e6SKarl Relton 		memset(&msg2, 0, sizeof(msg2));
366cb3126e6SKarl Relton 		msg2.msgcode = DIDmsg_dot11req_scan_results;
367cb3126e6SKarl Relton 		msg2.bssindex.data = i;
368cb3126e6SKarl Relton 
369cb3126e6SKarl Relton 		result = p80211req_dorequest(wlandev, (u8 *)&msg2);
370cb3126e6SKarl Relton 		if ((result != 0) ||
371cb3126e6SKarl Relton 		    (msg2.resultcode.data != P80211ENUM_resultcode_success)) {
372cb3126e6SKarl Relton 			break;
373cb3126e6SKarl Relton 		}
374cb3126e6SKarl Relton 
375cb3126e6SKarl Relton 		ie_buf[0] = WLAN_EID_SSID;
376cb3126e6SKarl Relton 		ie_buf[1] = msg2.ssid.data.len;
377cb3126e6SKarl Relton 		ie_len = ie_buf[1] + 2;
378efffed8eSsayli karnik 		memcpy(&ie_buf[2], &msg2.ssid.data.data, msg2.ssid.data.len);
3794e5e9d7cSZhao, Gang 		freq = ieee80211_channel_to_frequency(msg2.dschannel.data,
38057fbcce3SJohannes Berg 						      NL80211_BAND_2GHZ);
38119f798adSKrzysztof Wilczynski 		bss = cfg80211_inform_bss(wiphy,
3824e5e9d7cSZhao, Gang 			ieee80211_get_channel(wiphy, freq),
3835bc8c1f2SJohannes Berg 			CFG80211_BSS_FTYPE_UNKNOWN,
384efffed8eSsayli karnik 			(const u8 *)&msg2.bssid.data.data,
385cb3126e6SKarl Relton 			msg2.timestamp.data, msg2.capinfo.data,
386cb3126e6SKarl Relton 			msg2.beaconperiod.data,
387cb3126e6SKarl Relton 			ie_buf,
388cb3126e6SKarl Relton 			ie_len,
389cb3126e6SKarl Relton 			(msg2.signal.data - 65536) * 100, /* Conversion to signed type */
390cb3126e6SKarl Relton 			GFP_KERNEL
391cb3126e6SKarl Relton 		);
39219f798adSKrzysztof Wilczynski 
39319f798adSKrzysztof Wilczynski 		if (!bss) {
39419f798adSKrzysztof Wilczynski 			err = -ENOMEM;
39519f798adSKrzysztof Wilczynski 			goto exit;
39619f798adSKrzysztof Wilczynski 		}
39719f798adSKrzysztof Wilczynski 
3985b112d3dSJohannes Berg 		cfg80211_put_bss(wiphy, bss);
399cb3126e6SKarl Relton 	}
400cb3126e6SKarl Relton 
4018dd82ebeSEdgardo Hames 	if (result)
402cb3126e6SKarl Relton 		err = prism2_result2err(msg2.resultcode.data);
403cb3126e6SKarl Relton 
404cb3126e6SKarl Relton exit:
4051d76250bSAvraham Stern 	info.aborted = !!(err);
4061d76250bSAvraham Stern 	cfg80211_scan_done(request, &info);
407cb3126e6SKarl Relton 	priv->scan_request = NULL;
408cb3126e6SKarl Relton 	return err;
409cb3126e6SKarl Relton }
410cb3126e6SKarl Relton 
41155da06ebSTeodora Baluta static int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed)
4128dd82ebeSEdgardo Hames {
413cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
414c9573a8dSsayli karnik 	struct wlandevice *wlandev = priv->wlandev;
415cb3126e6SKarl Relton 	u32 data;
416cb3126e6SKarl Relton 	int result;
417cb3126e6SKarl Relton 	int err = 0;
418cb3126e6SKarl Relton 
419cb3126e6SKarl Relton 	if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
420cb3126e6SKarl Relton 		if (wiphy->rts_threshold == -1)
421cb3126e6SKarl Relton 			data = 2347;
422cb3126e6SKarl Relton 		else
423cb3126e6SKarl Relton 			data = wiphy->rts_threshold;
424cb3126e6SKarl Relton 
4258dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
426cb3126e6SKarl Relton 						DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold,
427cb3126e6SKarl Relton 						data);
428cb3126e6SKarl Relton 		if (result) {
429cb3126e6SKarl Relton 			err = -EFAULT;
430cb3126e6SKarl Relton 			goto exit;
431cb3126e6SKarl Relton 		}
432cb3126e6SKarl Relton 	}
433cb3126e6SKarl Relton 
434cb3126e6SKarl Relton 	if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
435cb3126e6SKarl Relton 		if (wiphy->frag_threshold == -1)
436cb3126e6SKarl Relton 			data = 2346;
437cb3126e6SKarl Relton 		else
438cb3126e6SKarl Relton 			data = wiphy->frag_threshold;
439cb3126e6SKarl Relton 
4408dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
441cb3126e6SKarl Relton 						DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold,
442cb3126e6SKarl Relton 						data);
443cb3126e6SKarl Relton 		if (result) {
444cb3126e6SKarl Relton 			err = -EFAULT;
445cb3126e6SKarl Relton 			goto exit;
446cb3126e6SKarl Relton 		}
447cb3126e6SKarl Relton 	}
448cb3126e6SKarl Relton 
449cb3126e6SKarl Relton exit:
450cb3126e6SKarl Relton 	return err;
451cb3126e6SKarl Relton }
452cb3126e6SKarl Relton 
45355da06ebSTeodora Baluta static int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
4548dd82ebeSEdgardo Hames 			  struct cfg80211_connect_params *sme)
4558dd82ebeSEdgardo Hames {
456c9573a8dSsayli karnik 	struct wlandevice *wlandev = dev->ml_priv;
457cb3126e6SKarl Relton 	struct ieee80211_channel *channel = sme->channel;
458b6bb56e6SEdgardo Hames 	struct p80211msg_lnxreq_autojoin msg_join;
459cb3126e6SKarl Relton 	u32 did;
460cb3126e6SKarl Relton 	int length = sme->ssid_len;
461cb3126e6SKarl Relton 	int chan = -1;
462cb3126e6SKarl Relton 	int is_wep = (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) ||
463cb3126e6SKarl Relton 	    (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104);
464cb3126e6SKarl Relton 	int result;
465cb3126e6SKarl Relton 	int err = 0;
466cb3126e6SKarl Relton 
467cb3126e6SKarl Relton 	/* Set the channel */
468cb3126e6SKarl Relton 	if (channel) {
469cb3126e6SKarl Relton 		chan = ieee80211_frequency_to_channel(channel->center_freq);
4708dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
471cb3126e6SKarl Relton 						DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel,
472cb3126e6SKarl Relton 						chan);
4738dd82ebeSEdgardo Hames 		if (result)
4748dd82ebeSEdgardo Hames 			goto exit;
475cb3126e6SKarl Relton 	}
476cb3126e6SKarl Relton 
477d34602deSJustin P. Mattock 	/* Set the authorization */
478cb3126e6SKarl Relton 	if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ||
479cb3126e6SKarl Relton 	    ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep))
480cb3126e6SKarl Relton 		msg_join.authtype.data = P80211ENUM_authalg_opensystem;
481cb3126e6SKarl Relton 	else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ||
482cb3126e6SKarl Relton 		 ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep))
483cb3126e6SKarl Relton 		msg_join.authtype.data = P80211ENUM_authalg_sharedkey;
4848dd82ebeSEdgardo Hames 	else
485eed88971SAvinash Kumar 		netdev_warn(dev,
4868dd82ebeSEdgardo Hames 			    "Unhandled authorisation type for connect (%d)\n",
4878dd82ebeSEdgardo Hames 			    sme->auth_type);
488cb3126e6SKarl Relton 
489cb3126e6SKarl Relton 	/* Set the encryption - we only support wep */
490cb3126e6SKarl Relton 	if (is_wep) {
491cb3126e6SKarl Relton 		if (sme->key) {
4920ca6d8e7SClaudiu Beznea 			if (sme->key_idx >= NUM_WEPKEYS) {
4930ca6d8e7SClaudiu Beznea 				err = -EINVAL;
4940ca6d8e7SClaudiu Beznea 				goto exit;
4950ca6d8e7SClaudiu Beznea 			}
4960ca6d8e7SClaudiu Beznea 
497cb3126e6SKarl Relton 			result = prism2_domibset_uint32(wlandev,
498cb3126e6SKarl Relton 				DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
499cb3126e6SKarl Relton 				sme->key_idx);
5008dd82ebeSEdgardo Hames 			if (result)
5018dd82ebeSEdgardo Hames 				goto exit;
502cb3126e6SKarl Relton 
503cb3126e6SKarl Relton 			/* send key to driver */
5040ca6d8e7SClaudiu Beznea 			did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(
5050ca6d8e7SClaudiu Beznea 					sme->key_idx + 1);
5068aac4d44SDevendra Naga 			result = prism2_domibset_pstr32(wlandev,
5078aac4d44SDevendra Naga 							did, sme->key_len,
5088aac4d44SDevendra Naga 							(u8 *)sme->key);
5098dd82ebeSEdgardo Hames 			if (result)
5108dd82ebeSEdgardo Hames 				goto exit;
511cb3126e6SKarl Relton 		}
512cb3126e6SKarl Relton 
513cb3126e6SKarl Relton 		/* Assume we should set privacy invoked and exclude unencrypted
51435028fe1SGavin O'Leary 		 * We could possible use sme->privacy here, but the assumption
51535028fe1SGavin O'Leary 		 * seems reasonable anyways
51635028fe1SGavin O'Leary 		 */
5178dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5188dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
519cb3126e6SKarl Relton 						P80211ENUM_truth_true);
5208dd82ebeSEdgardo Hames 		if (result)
5218dd82ebeSEdgardo Hames 			goto exit;
5228dd82ebeSEdgardo Hames 
5238dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5248dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
525cb3126e6SKarl Relton 						P80211ENUM_truth_true);
5268dd82ebeSEdgardo Hames 		if (result)
5278dd82ebeSEdgardo Hames 			goto exit;
528cb3126e6SKarl Relton 
529cb3126e6SKarl Relton 	} else {
5308dd82ebeSEdgardo Hames 		/* Assume we should unset privacy invoked
53135028fe1SGavin O'Leary 		 * and exclude unencrypted
53235028fe1SGavin O'Leary 		 */
5338dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5348dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
535cb3126e6SKarl Relton 						P80211ENUM_truth_false);
5368dd82ebeSEdgardo Hames 		if (result)
5378dd82ebeSEdgardo Hames 			goto exit;
5388dd82ebeSEdgardo Hames 
5398dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5408dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
541cb3126e6SKarl Relton 						P80211ENUM_truth_false);
5428dd82ebeSEdgardo Hames 		if (result)
5438dd82ebeSEdgardo Hames 			goto exit;
544cb3126e6SKarl Relton 	}
545cb3126e6SKarl Relton 
546cb3126e6SKarl Relton 	/* Now do the actual join. Note there is no way that I can
5474f9de774SGavin O'Leary 	 * see to request a specific bssid
5484f9de774SGavin O'Leary 	 */
549cb3126e6SKarl Relton 	msg_join.msgcode = DIDmsg_lnxreq_autojoin;
550cb3126e6SKarl Relton 
551cb3126e6SKarl Relton 	memcpy(msg_join.ssid.data.data, sme->ssid, length);
552cb3126e6SKarl Relton 	msg_join.ssid.data.len = length;
553cb3126e6SKarl Relton 
554cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *)&msg_join);
555cb3126e6SKarl Relton 
556cb3126e6SKarl Relton exit:
5578dd82ebeSEdgardo Hames 	if (result)
5588dd82ebeSEdgardo Hames 		err = -EFAULT;
559cb3126e6SKarl Relton 
560cb3126e6SKarl Relton 	return err;
561cb3126e6SKarl Relton }
562cb3126e6SKarl Relton 
56355da06ebSTeodora Baluta static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev,
5648dd82ebeSEdgardo Hames 			     u16 reason_code)
5658dd82ebeSEdgardo Hames {
566c9573a8dSsayli karnik 	struct wlandevice *wlandev = dev->ml_priv;
567b6bb56e6SEdgardo Hames 	struct p80211msg_lnxreq_autojoin msg_join;
568cb3126e6SKarl Relton 	int result;
569cb3126e6SKarl Relton 	int err = 0;
570cb3126e6SKarl Relton 
571cb3126e6SKarl Relton 	/* Do a join, with a bogus ssid. Thats the only way I can think of */
572cb3126e6SKarl Relton 	msg_join.msgcode = DIDmsg_lnxreq_autojoin;
573cb3126e6SKarl Relton 
574cb3126e6SKarl Relton 	memcpy(msg_join.ssid.data.data, "---", 3);
575cb3126e6SKarl Relton 	msg_join.ssid.data.len = 3;
576cb3126e6SKarl Relton 
577cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *)&msg_join);
578cb3126e6SKarl Relton 
5798dd82ebeSEdgardo Hames 	if (result)
5808dd82ebeSEdgardo Hames 		err = -EFAULT;
581cb3126e6SKarl Relton 
582cb3126e6SKarl Relton 	return err;
583cb3126e6SKarl Relton }
584cb3126e6SKarl Relton 
58555da06ebSTeodora Baluta static int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev,
5868dd82ebeSEdgardo Hames 			    struct cfg80211_ibss_params *params)
5878dd82ebeSEdgardo Hames {
588cb3126e6SKarl Relton 	return -EOPNOTSUPP;
589cb3126e6SKarl Relton }
590cb3126e6SKarl Relton 
59155da06ebSTeodora Baluta static int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
5928dd82ebeSEdgardo Hames {
593cb3126e6SKarl Relton 	return -EOPNOTSUPP;
594cb3126e6SKarl Relton }
595cb3126e6SKarl Relton 
59655da06ebSTeodora Baluta static int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
5975f3b361aSEmil Goode 			       enum nl80211_tx_power_setting type, int mbm)
5988dd82ebeSEdgardo Hames {
599cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
600c9573a8dSsayli karnik 	struct wlandevice *wlandev = priv->wlandev;
601cb3126e6SKarl Relton 	u32 data;
602cb3126e6SKarl Relton 	int result;
603cb3126e6SKarl Relton 	int err = 0;
604cb3126e6SKarl Relton 
6059015e499SChristoph Fritz 	if (type == NL80211_TX_POWER_AUTOMATIC)
606cb3126e6SKarl Relton 		data = 30;
607cb3126e6SKarl Relton 	else
6089015e499SChristoph Fritz 		data = MBM_TO_DBM(mbm);
609cb3126e6SKarl Relton 
610cb3126e6SKarl Relton 	result = prism2_domibset_uint32(wlandev,
611cb3126e6SKarl Relton 		DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel,
612cb3126e6SKarl Relton 		data);
613cb3126e6SKarl Relton 
614cb3126e6SKarl Relton 	if (result) {
615cb3126e6SKarl Relton 		err = -EFAULT;
616cb3126e6SKarl Relton 		goto exit;
617cb3126e6SKarl Relton 	}
618cb3126e6SKarl Relton 
619cb3126e6SKarl Relton exit:
620cb3126e6SKarl Relton 	return err;
621cb3126e6SKarl Relton }
622cb3126e6SKarl Relton 
62355da06ebSTeodora Baluta static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
6245f3b361aSEmil Goode 			       int *dbm)
6258dd82ebeSEdgardo Hames {
626cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
627c9573a8dSsayli karnik 	struct wlandevice *wlandev = priv->wlandev;
628b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_mibget msg;
629b26b2325SSergio Paracuellos 	struct p80211item_uint32 *mibitem;
630cb3126e6SKarl Relton 	int result;
631cb3126e6SKarl Relton 	int err = 0;
632cb3126e6SKarl Relton 
633b26b2325SSergio Paracuellos 	mibitem = (struct p80211item_uint32 *)&msg.mibattribute.data;
634cb3126e6SKarl Relton 	msg.msgcode = DIDmsg_dot11req_mibget;
635cb3126e6SKarl Relton 	mibitem->did =
636cb3126e6SKarl Relton 	    DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
637cb3126e6SKarl Relton 
638cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *)&msg);
639cb3126e6SKarl Relton 
640cb3126e6SKarl Relton 	if (result) {
641cb3126e6SKarl Relton 		err = -EFAULT;
642cb3126e6SKarl Relton 		goto exit;
643cb3126e6SKarl Relton 	}
644cb3126e6SKarl Relton 
645cb3126e6SKarl Relton 	*dbm = mibitem->data;
646cb3126e6SKarl Relton 
647cb3126e6SKarl Relton exit:
648cb3126e6SKarl Relton 	return err;
649cb3126e6SKarl Relton }
650cb3126e6SKarl Relton 
651cb3126e6SKarl Relton /* Interface callback functions, passing data back up to the cfg80211 layer */
652c9573a8dSsayli karnik void prism2_connect_result(struct wlandevice *wlandev, u8 failed)
6538dd82ebeSEdgardo Hames {
6548aac4d44SDevendra Naga 	u16 status = failed ?
6558aac4d44SDevendra Naga 		     WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS;
656cb3126e6SKarl Relton 
657cb3126e6SKarl Relton 	cfg80211_connect_result(wlandev->netdev, wlandev->bssid,
6588dd82ebeSEdgardo Hames 				NULL, 0, NULL, 0, status, GFP_KERNEL);
659cb3126e6SKarl Relton }
660cb3126e6SKarl Relton 
661c9573a8dSsayli karnik void prism2_disconnected(struct wlandevice *wlandev)
6628dd82ebeSEdgardo Hames {
663cb3126e6SKarl Relton 	cfg80211_disconnected(wlandev->netdev, 0, NULL,
66480279fb7SJohannes Berg 			      0, false, GFP_KERNEL);
665cb3126e6SKarl Relton }
666cb3126e6SKarl Relton 
667c9573a8dSsayli karnik void prism2_roamed(struct wlandevice *wlandev)
6688dd82ebeSEdgardo Hames {
669ed9d0102SJouni Malinen 	cfg80211_roamed(wlandev->netdev, NULL, wlandev->bssid,
670cb3126e6SKarl Relton 			NULL, 0, NULL, 0, GFP_KERNEL);
671cb3126e6SKarl Relton }
672cb3126e6SKarl Relton 
673cb3126e6SKarl Relton /* Structures for declaring wiphy interface */
674cb3126e6SKarl Relton static const struct cfg80211_ops prism2_usb_cfg_ops = {
675cb3126e6SKarl Relton 	.change_virtual_intf = prism2_change_virtual_intf,
676cb3126e6SKarl Relton 	.add_key = prism2_add_key,
677cb3126e6SKarl Relton 	.get_key = prism2_get_key,
678cb3126e6SKarl Relton 	.del_key = prism2_del_key,
679cb3126e6SKarl Relton 	.set_default_key = prism2_set_default_key,
680cb3126e6SKarl Relton 	.get_station = prism2_get_station,
681cb3126e6SKarl Relton 	.scan = prism2_scan,
682cb3126e6SKarl Relton 	.set_wiphy_params = prism2_set_wiphy_params,
683cb3126e6SKarl Relton 	.connect = prism2_connect,
684cb3126e6SKarl Relton 	.disconnect = prism2_disconnect,
685cb3126e6SKarl Relton 	.join_ibss = prism2_join_ibss,
686cb3126e6SKarl Relton 	.leave_ibss = prism2_leave_ibss,
687cb3126e6SKarl Relton 	.set_tx_power = prism2_set_tx_power,
688cb3126e6SKarl Relton 	.get_tx_power = prism2_get_tx_power,
689cb3126e6SKarl Relton };
690cb3126e6SKarl Relton 
691cb3126e6SKarl Relton /* Functions to create/free wiphy interface */
692c9573a8dSsayli karnik static struct wiphy *wlan_create_wiphy(struct device *dev, struct wlandevice *wlandev)
693cb3126e6SKarl Relton {
694cb3126e6SKarl Relton 	struct wiphy *wiphy;
695cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv;
6968aac4d44SDevendra Naga 
6978aac4d44SDevendra Naga 	wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(*priv));
698cb3126e6SKarl Relton 	if (!wiphy)
699cb3126e6SKarl Relton 		return NULL;
700cb3126e6SKarl Relton 
701cb3126e6SKarl Relton 	priv = wiphy_priv(wiphy);
702cb3126e6SKarl Relton 	priv->wlandev = wlandev;
703cb3126e6SKarl Relton 	memcpy(priv->channels, prism2_channels, sizeof(prism2_channels));
704cb3126e6SKarl Relton 	memcpy(priv->rates, prism2_rates, sizeof(prism2_rates));
705cb3126e6SKarl Relton 	priv->band.channels = priv->channels;
706cb3126e6SKarl Relton 	priv->band.n_channels = ARRAY_SIZE(prism2_channels);
707cb3126e6SKarl Relton 	priv->band.bitrates = priv->rates;
708cb3126e6SKarl Relton 	priv->band.n_bitrates = ARRAY_SIZE(prism2_rates);
70957fbcce3SJohannes Berg 	priv->band.band = NL80211_BAND_2GHZ;
710aff3ea4eSKarl Relton 	priv->band.ht_cap.ht_supported = false;
71157fbcce3SJohannes Berg 	wiphy->bands[NL80211_BAND_2GHZ] = &priv->band;
712cb3126e6SKarl Relton 
713cb3126e6SKarl Relton 	set_wiphy_dev(wiphy, dev);
714cb3126e6SKarl Relton 	wiphy->privid = prism2_wiphy_privid;
715cb3126e6SKarl Relton 	wiphy->max_scan_ssids = 1;
7168dd82ebeSEdgardo Hames 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
7178dd82ebeSEdgardo Hames 				 | BIT(NL80211_IFTYPE_ADHOC);
718cb3126e6SKarl Relton 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
719cb3126e6SKarl Relton 	wiphy->n_cipher_suites = PRISM2_NUM_CIPHER_SUITES;
720cb3126e6SKarl Relton 	wiphy->cipher_suites = prism2_cipher_suites;
721cb3126e6SKarl Relton 
722f96b36c7SClaudiu Beznea 	if (wiphy_register(wiphy) < 0) {
723f96b36c7SClaudiu Beznea 		wiphy_free(wiphy);
724cb3126e6SKarl Relton 		return NULL;
725f96b36c7SClaudiu Beznea 	}
726cb3126e6SKarl Relton 
727cb3126e6SKarl Relton 	return wiphy;
728cb3126e6SKarl Relton }
729cb3126e6SKarl Relton 
73036d9c250STugce Sirin static void wlan_free_wiphy(struct wiphy *wiphy)
731cb3126e6SKarl Relton {
732cb3126e6SKarl Relton 	wiphy_unregister(wiphy);
733cb3126e6SKarl Relton 	wiphy_free(wiphy);
734cb3126e6SKarl Relton }
735