1cb3126e6SKarl Relton /* cfg80211 Interface for prism2_usb module */
2cb3126e6SKarl Relton 
3cb3126e6SKarl Relton 
4d34602deSJustin P. Mattock /* Prism2 channel/frequency/bitrate declarations */
5cb3126e6SKarl Relton static const struct ieee80211_channel prism2_channels[] = {
6cb3126e6SKarl Relton 	{ .center_freq = 2412 },
7cb3126e6SKarl Relton 	{ .center_freq = 2417 },
8cb3126e6SKarl Relton 	{ .center_freq = 2422 },
9cb3126e6SKarl Relton 	{ .center_freq = 2427 },
10cb3126e6SKarl Relton 	{ .center_freq = 2432 },
11cb3126e6SKarl Relton 	{ .center_freq = 2437 },
12cb3126e6SKarl Relton 	{ .center_freq = 2442 },
13cb3126e6SKarl Relton 	{ .center_freq = 2447 },
14cb3126e6SKarl Relton 	{ .center_freq = 2452 },
15cb3126e6SKarl Relton 	{ .center_freq = 2457 },
16cb3126e6SKarl Relton 	{ .center_freq = 2462 },
17cb3126e6SKarl Relton 	{ .center_freq = 2467 },
18cb3126e6SKarl Relton 	{ .center_freq = 2472 },
19cb3126e6SKarl Relton 	{ .center_freq = 2484 },
20cb3126e6SKarl Relton };
21cb3126e6SKarl Relton 
22cb3126e6SKarl Relton static const struct ieee80211_rate prism2_rates[] = {
23cb3126e6SKarl Relton 	{ .bitrate = 10 },
24cb3126e6SKarl Relton 	{ .bitrate = 20 },
25cb3126e6SKarl Relton 	{ .bitrate = 55 },
26cb3126e6SKarl Relton 	{ .bitrate = 110 }
27cb3126e6SKarl Relton };
28cb3126e6SKarl Relton 
29cb3126e6SKarl Relton #define PRISM2_NUM_CIPHER_SUITES 2
30cb3126e6SKarl Relton static const u32 prism2_cipher_suites[PRISM2_NUM_CIPHER_SUITES] = {
31cb3126e6SKarl Relton 	WLAN_CIPHER_SUITE_WEP40,
32cb3126e6SKarl Relton 	WLAN_CIPHER_SUITE_WEP104
33cb3126e6SKarl Relton };
34cb3126e6SKarl Relton 
35cb3126e6SKarl Relton 
36cb3126e6SKarl Relton /* prism2 device private data */
37cb3126e6SKarl Relton struct prism2_wiphy_private {
38cb3126e6SKarl Relton 	wlandevice_t *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 
50cb3126e6SKarl Relton /* Helper Functions */
51cb3126e6SKarl Relton static int prism2_result2err(int prism2_result)
52cb3126e6SKarl Relton {
53cb3126e6SKarl Relton 	int err = 0;
54cb3126e6SKarl Relton 
55cb3126e6SKarl Relton 	switch (prism2_result) {
56cb3126e6SKarl Relton 	case P80211ENUM_resultcode_invalid_parameters:
57cb3126e6SKarl Relton 		err = -EINVAL;
58cb3126e6SKarl Relton 		break;
59cb3126e6SKarl Relton 	case P80211ENUM_resultcode_implementation_failure:
60cb3126e6SKarl Relton 		err = -EIO;
61cb3126e6SKarl Relton 		break;
62cb3126e6SKarl Relton 	case P80211ENUM_resultcode_not_supported:
63cb3126e6SKarl Relton 		err = -EOPNOTSUPP;
64cb3126e6SKarl Relton 		break;
65cb3126e6SKarl Relton 	default:
66cb3126e6SKarl Relton 		err = 0;
67cb3126e6SKarl Relton 		break;
68cb3126e6SKarl Relton 	}
69cb3126e6SKarl Relton 
70cb3126e6SKarl Relton 	return err;
71cb3126e6SKarl Relton }
72cb3126e6SKarl Relton 
73cb3126e6SKarl Relton static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data)
74cb3126e6SKarl Relton {
75b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_mibset msg;
76bb1da756SHimangi Saraogi 	p80211item_uint32_t *mibitem =
77bb1da756SHimangi Saraogi 			(p80211item_uint32_t *) &msg.mibattribute.data;
78cb3126e6SKarl Relton 
79cb3126e6SKarl Relton 	msg.msgcode = DIDmsg_dot11req_mibset;
80cb3126e6SKarl Relton 	mibitem->did = did;
81cb3126e6SKarl Relton 	mibitem->data = data;
82cb3126e6SKarl Relton 
83cb3126e6SKarl Relton 	return p80211req_dorequest(wlandev, (u8 *) &msg);
84cb3126e6SKarl Relton }
85cb3126e6SKarl Relton 
86cb3126e6SKarl Relton static int prism2_domibset_pstr32(wlandevice_t *wlandev,
87c1e5f471SJohannes Berg 				  u32 did, u8 len, const u8 *data)
88cb3126e6SKarl Relton {
89b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_mibset msg;
90bb1da756SHimangi Saraogi 	p80211item_pstr32_t *mibitem =
91bb1da756SHimangi Saraogi 			(p80211item_pstr32_t *) &msg.mibattribute.data;
92cb3126e6SKarl Relton 
93cb3126e6SKarl Relton 	msg.msgcode = DIDmsg_dot11req_mibset;
94cb3126e6SKarl Relton 	mibitem->did = did;
95cb3126e6SKarl Relton 	mibitem->data.len = len;
96cb3126e6SKarl Relton 	memcpy(mibitem->data.data, data, len);
97cb3126e6SKarl Relton 
98cb3126e6SKarl Relton 	return p80211req_dorequest(wlandev, (u8 *) &msg);
99cb3126e6SKarl Relton }
100cb3126e6SKarl Relton 
101cb3126e6SKarl Relton 
102cb3126e6SKarl Relton /* The interface functions, called by the cfg80211 layer */
10355da06ebSTeodora Baluta static int prism2_change_virtual_intf(struct wiphy *wiphy,
104cb3126e6SKarl Relton 				      struct net_device *dev,
105cb3126e6SKarl Relton 				      enum nl80211_iftype type, u32 *flags,
106cb3126e6SKarl Relton 				      struct vif_params *params)
107cb3126e6SKarl Relton {
108cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
109cb3126e6SKarl Relton 	u32 data;
110cb3126e6SKarl Relton 	int result;
111cb3126e6SKarl Relton 	int err = 0;
112cb3126e6SKarl Relton 
113cb3126e6SKarl Relton 	switch (type) {
114cb3126e6SKarl Relton 	case NL80211_IFTYPE_ADHOC:
1158dd82ebeSEdgardo Hames 		if (wlandev->macmode == WLAN_MACMODE_IBSS_STA)
1168dd82ebeSEdgardo Hames 			goto exit;
117cb3126e6SKarl Relton 		wlandev->macmode = WLAN_MACMODE_IBSS_STA;
118cb3126e6SKarl Relton 		data = 0;
119cb3126e6SKarl Relton 		break;
120cb3126e6SKarl Relton 	case NL80211_IFTYPE_STATION:
1218dd82ebeSEdgardo Hames 		if (wlandev->macmode == WLAN_MACMODE_ESS_STA)
1228dd82ebeSEdgardo Hames 			goto exit;
123cb3126e6SKarl Relton 		wlandev->macmode = WLAN_MACMODE_ESS_STA;
124cb3126e6SKarl Relton 		data = 1;
125cb3126e6SKarl Relton 		break;
126cb3126e6SKarl Relton 	default:
127eed88971SAvinash Kumar 		netdev_warn(dev, "Operation mode: %d not support\n", type);
128cb3126e6SKarl Relton 		return -EOPNOTSUPP;
129cb3126e6SKarl Relton 	}
130cb3126e6SKarl Relton 
131cb3126e6SKarl Relton 	/* Set Operation mode to the PORT TYPE RID */
1328aac4d44SDevendra Naga 	result = prism2_domibset_uint32(wlandev,
1338aac4d44SDevendra Naga 					DIDmib_p2_p2Static_p2CnfPortType,
1348aac4d44SDevendra Naga 					data);
135cb3126e6SKarl Relton 
136cb3126e6SKarl Relton 	if (result)
137cb3126e6SKarl Relton 		err = -EFAULT;
138cb3126e6SKarl Relton 
139cb3126e6SKarl Relton 	dev->ieee80211_ptr->iftype = type;
140cb3126e6SKarl Relton 
141cb3126e6SKarl Relton exit:
142cb3126e6SKarl Relton 	return err;
143cb3126e6SKarl Relton }
144cb3126e6SKarl Relton 
14555da06ebSTeodora Baluta static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev,
14634a488c1SBen Hutchings 			  u8 key_index, bool pairwise, const u8 *mac_addr,
1478dd82ebeSEdgardo Hames 			  struct key_params *params)
1488dd82ebeSEdgardo Hames {
149cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
150cb3126e6SKarl Relton 	u32 did;
151cb3126e6SKarl Relton 
152cb3126e6SKarl Relton 	int err = 0;
153cb3126e6SKarl Relton 	int result = 0;
154cb3126e6SKarl Relton 
155cb3126e6SKarl Relton 	switch (params->cipher) {
156cb3126e6SKarl Relton 	case WLAN_CIPHER_SUITE_WEP40:
157cb3126e6SKarl Relton 	case WLAN_CIPHER_SUITE_WEP104:
158cb3126e6SKarl Relton 		result = prism2_domibset_uint32(wlandev,
159cb3126e6SKarl Relton 						DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
160cb3126e6SKarl Relton 						key_index);
1618dd82ebeSEdgardo Hames 		if (result)
1628dd82ebeSEdgardo Hames 			goto exit;
163cb3126e6SKarl Relton 
164cb3126e6SKarl Relton 		/* send key to driver */
165cb3126e6SKarl Relton 		switch (key_index) {
166cb3126e6SKarl Relton 		case 0:
1678dd82ebeSEdgardo Hames 			did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
168cb3126e6SKarl Relton 			break;
169cb3126e6SKarl Relton 
170cb3126e6SKarl Relton 		case 1:
1718dd82ebeSEdgardo Hames 			did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
172cb3126e6SKarl Relton 			break;
173cb3126e6SKarl Relton 
174cb3126e6SKarl Relton 		case 2:
1758dd82ebeSEdgardo Hames 			did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
176cb3126e6SKarl Relton 			break;
177cb3126e6SKarl Relton 
178cb3126e6SKarl Relton 		case 3:
1798dd82ebeSEdgardo Hames 			did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
180cb3126e6SKarl Relton 			break;
181cb3126e6SKarl Relton 
182cb3126e6SKarl Relton 		default:
183cb3126e6SKarl Relton 			err = -EINVAL;
184cb3126e6SKarl Relton 			goto exit;
185cb3126e6SKarl Relton 		}
186cb3126e6SKarl Relton 
187bb1da756SHimangi Saraogi 		result = prism2_domibset_pstr32(wlandev, did,
188bb1da756SHimangi Saraogi 						params->key_len, params->key);
1898dd82ebeSEdgardo Hames 		if (result)
1908dd82ebeSEdgardo Hames 			goto exit;
191cb3126e6SKarl Relton 		break;
192cb3126e6SKarl Relton 
193cb3126e6SKarl Relton 	default:
194cb3126e6SKarl Relton 		pr_debug("Unsupported cipher suite\n");
195cb3126e6SKarl Relton 		result = 1;
196cb3126e6SKarl Relton 	}
197cb3126e6SKarl Relton 
198cb3126e6SKarl Relton exit:
1998dd82ebeSEdgardo Hames 	if (result)
2008dd82ebeSEdgardo Hames 		err = -EFAULT;
201cb3126e6SKarl Relton 
202cb3126e6SKarl Relton 	return err;
203cb3126e6SKarl Relton }
204cb3126e6SKarl Relton 
20555da06ebSTeodora Baluta static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev,
20655da06ebSTeodora Baluta 			  u8 key_index, bool pairwise,
20755da06ebSTeodora Baluta 			  const u8 *mac_addr, void *cookie,
2088dd82ebeSEdgardo Hames 			  void (*callback)(void *cookie, struct key_params*))
2098dd82ebeSEdgardo Hames {
210cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
211cb3126e6SKarl Relton 	struct key_params params;
212cb3126e6SKarl Relton 	int len;
213cb3126e6SKarl Relton 
2148dd82ebeSEdgardo Hames 	if (key_index >= NUM_WEPKEYS)
2158dd82ebeSEdgardo Hames 		return -EINVAL;
216cb3126e6SKarl Relton 
217cb3126e6SKarl Relton 	len = wlandev->wep_keylens[key_index];
218cb3126e6SKarl Relton 	memset(&params, 0, sizeof(params));
219cb3126e6SKarl Relton 
2208dd82ebeSEdgardo Hames 	if (len == 13)
221cb3126e6SKarl Relton 		params.cipher = WLAN_CIPHER_SUITE_WEP104;
2228dd82ebeSEdgardo Hames 	else if (len == 5)
223cb3126e6SKarl Relton 		params.cipher = WLAN_CIPHER_SUITE_WEP104;
2248dd82ebeSEdgardo Hames 	else
2258dd82ebeSEdgardo Hames 		return -ENOENT;
226cb3126e6SKarl Relton 	params.key_len = len;
227cb3126e6SKarl Relton 	params.key = wlandev->wep_keys[key_index];
228aff3ea4eSKarl Relton 	params.seq_len = 0;
229cb3126e6SKarl Relton 
230cb3126e6SKarl Relton 	callback(cookie, &params);
2318dd82ebeSEdgardo Hames 
232cb3126e6SKarl Relton 	return 0;
233cb3126e6SKarl Relton }
234cb3126e6SKarl Relton 
23555da06ebSTeodora Baluta static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev,
23634a488c1SBen Hutchings 			  u8 key_index, bool pairwise, const u8 *mac_addr)
2378dd82ebeSEdgardo Hames {
238cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
239cb3126e6SKarl Relton 	u32 did;
240cb3126e6SKarl Relton 	int err = 0;
241cb3126e6SKarl Relton 	int result = 0;
242cb3126e6SKarl Relton 
243cb3126e6SKarl Relton 	/* There is no direct way in the hardware (AFAIK) of removing
244cb3126e6SKarl Relton 	   a key, so we will cheat by setting the key to a bogus value */
245cb3126e6SKarl Relton 	/* send key to driver */
246cb3126e6SKarl Relton 	switch (key_index) {
247cb3126e6SKarl Relton 	case 0:
248cb3126e6SKarl Relton 		did =
249cb3126e6SKarl Relton 		    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
250cb3126e6SKarl Relton 		break;
251cb3126e6SKarl Relton 
252cb3126e6SKarl Relton 	case 1:
253cb3126e6SKarl Relton 		did =
254cb3126e6SKarl Relton 		    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
255cb3126e6SKarl Relton 		break;
256cb3126e6SKarl Relton 
257cb3126e6SKarl Relton 	case 2:
258cb3126e6SKarl Relton 		did =
259cb3126e6SKarl Relton 		    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
260cb3126e6SKarl Relton 		break;
261cb3126e6SKarl Relton 
262cb3126e6SKarl Relton 	case 3:
263cb3126e6SKarl Relton 		did =
264cb3126e6SKarl Relton 		    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
265cb3126e6SKarl Relton 		break;
266cb3126e6SKarl Relton 
267cb3126e6SKarl Relton 	default:
268cb3126e6SKarl Relton 		err = -EINVAL;
269cb3126e6SKarl Relton 		goto exit;
270cb3126e6SKarl Relton 	}
271cb3126e6SKarl Relton 
272cb3126e6SKarl Relton 	result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000");
273cb3126e6SKarl Relton 
274cb3126e6SKarl Relton exit:
2758dd82ebeSEdgardo Hames 	if (result)
2768dd82ebeSEdgardo Hames 		err = -EFAULT;
277cb3126e6SKarl Relton 
278cb3126e6SKarl Relton 	return err;
279cb3126e6SKarl Relton }
280cb3126e6SKarl Relton 
28155da06ebSTeodora Baluta static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
2829005fcd8SHarry Wei 				  u8 key_index, bool unicast, bool multicast)
2838dd82ebeSEdgardo Hames {
284cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
285cb3126e6SKarl Relton 
286cb3126e6SKarl Relton 	int err = 0;
287cb3126e6SKarl Relton 	int result = 0;
288cb3126e6SKarl Relton 
289cb3126e6SKarl Relton 	result = prism2_domibset_uint32(wlandev,
290cb3126e6SKarl Relton 		DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
291cb3126e6SKarl Relton 		key_index);
292cb3126e6SKarl Relton 
2938dd82ebeSEdgardo Hames 	if (result)
2948dd82ebeSEdgardo Hames 		err = -EFAULT;
295cb3126e6SKarl Relton 
296cb3126e6SKarl Relton 	return err;
297cb3126e6SKarl Relton }
298cb3126e6SKarl Relton 
299cb3126e6SKarl Relton 
30055da06ebSTeodora Baluta static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
3013b3a0162SJohannes Berg 			      const u8 *mac, struct station_info *sinfo)
3028dd82ebeSEdgardo Hames {
303cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
304b6bb56e6SEdgardo Hames 	struct p80211msg_lnxreq_commsquality quality;
305cb3126e6SKarl Relton 	int result;
306cb3126e6SKarl Relton 
307cb3126e6SKarl Relton 	memset(sinfo, 0, sizeof(*sinfo));
308cb3126e6SKarl Relton 
309cb3126e6SKarl Relton 	if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING))
310cb3126e6SKarl Relton 		return -EOPNOTSUPP;
311cb3126e6SKarl Relton 
312cb3126e6SKarl Relton 	/* build request message */
313cb3126e6SKarl Relton 	quality.msgcode = DIDmsg_lnxreq_commsquality;
314cb3126e6SKarl Relton 	quality.dbm.data = P80211ENUM_truth_true;
315cb3126e6SKarl Relton 	quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
316cb3126e6SKarl Relton 
317cb3126e6SKarl Relton 	/* send message to nsd */
318cb3126e6SKarl Relton 	if (wlandev->mlmerequest == NULL)
319cb3126e6SKarl Relton 		return -EOPNOTSUPP;
320cb3126e6SKarl Relton 
3213d049431SEdgardo Hames 	result = wlandev->mlmerequest(wlandev, (struct p80211msg *) &quality);
322cb3126e6SKarl Relton 
323cb3126e6SKarl Relton 
324cb3126e6SKarl Relton 	if (result == 0) {
325cb3126e6SKarl Relton 		sinfo->txrate.legacy = quality.txrate.data;
326cb3126e6SKarl Relton 		sinfo->filled |= STATION_INFO_TX_BITRATE;
327cb3126e6SKarl Relton 		sinfo->signal = quality.level.data;
328cb3126e6SKarl Relton 		sinfo->filled |= STATION_INFO_SIGNAL;
329cb3126e6SKarl Relton 	}
330cb3126e6SKarl Relton 
331cb3126e6SKarl Relton 	return result;
332cb3126e6SKarl Relton }
333cb3126e6SKarl Relton 
334bb1da756SHimangi Saraogi static int prism2_scan(struct wiphy *wiphy,
335bb1da756SHimangi Saraogi 		       struct cfg80211_scan_request *request)
336cb3126e6SKarl Relton {
3375d5d7c3bSEmil Goode 	struct net_device *dev;
338cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
3395d5d7c3bSEmil Goode 	wlandevice_t *wlandev;
340b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_scan msg1;
341b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_scan_results msg2;
34219f798adSKrzysztof Wilczynski 	struct cfg80211_bss *bss;
343cb3126e6SKarl Relton 	int result;
344cb3126e6SKarl Relton 	int err = 0;
345cb3126e6SKarl Relton 	int numbss = 0;
346cb3126e6SKarl Relton 	int i = 0;
347cb3126e6SKarl Relton 	u8 ie_buf[46];
348cb3126e6SKarl Relton 	int ie_len;
349cb3126e6SKarl Relton 
350cb3126e6SKarl Relton 	if (!request)
351cb3126e6SKarl Relton 		return -EINVAL;
352cb3126e6SKarl Relton 
3535d5d7c3bSEmil Goode 	dev = request->wdev->netdev;
3545d5d7c3bSEmil Goode 	wlandev = dev->ml_priv;
3555d5d7c3bSEmil Goode 
356cb3126e6SKarl Relton 	if (priv->scan_request && priv->scan_request != request)
357cb3126e6SKarl Relton 		return -EBUSY;
358cb3126e6SKarl Relton 
359cb3126e6SKarl Relton 	if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
360eed88971SAvinash Kumar 		netdev_err(dev, "Can't scan in AP mode\n");
361cb3126e6SKarl Relton 		return -EOPNOTSUPP;
362cb3126e6SKarl Relton 	}
363cb3126e6SKarl Relton 
364cb3126e6SKarl Relton 	priv->scan_request = request;
365cb3126e6SKarl Relton 
366b6bb56e6SEdgardo Hames 	memset(&msg1, 0x00, sizeof(struct p80211msg_dot11req_scan));
367cb3126e6SKarl Relton 	msg1.msgcode = DIDmsg_dot11req_scan;
368cb3126e6SKarl Relton 	msg1.bsstype.data = P80211ENUM_bsstype_any;
369cb3126e6SKarl Relton 
370625aeb3aSDan Carpenter 	memset(&msg1.bssid.data.data, 0xFF, sizeof(msg1.bssid.data.data));
371cb3126e6SKarl Relton 	msg1.bssid.data.len = 6;
372cb3126e6SKarl Relton 
373cb3126e6SKarl Relton 	if (request->n_ssids > 0) {
374cb3126e6SKarl Relton 		msg1.scantype.data = P80211ENUM_scantype_active;
375cb3126e6SKarl Relton 		msg1.ssid.data.len = request->ssids->ssid_len;
3768aac4d44SDevendra Naga 		memcpy(msg1.ssid.data.data,
3778aac4d44SDevendra Naga 			request->ssids->ssid, request->ssids->ssid_len);
378cb3126e6SKarl Relton 	} else {
379cb3126e6SKarl Relton 		msg1.scantype.data = 0;
380cb3126e6SKarl Relton 	}
381cb3126e6SKarl Relton 	msg1.probedelay.data = 0;
382cb3126e6SKarl Relton 
383cb3126e6SKarl Relton 	for (i = 0;
384cb3126e6SKarl Relton 		(i < request->n_channels) && i < ARRAY_SIZE(prism2_channels);
385cb3126e6SKarl Relton 		i++)
386cb3126e6SKarl Relton 		msg1.channellist.data.data[i] =
387bb1da756SHimangi Saraogi 			ieee80211_frequency_to_channel(
388bb1da756SHimangi Saraogi 				request->channels[i]->center_freq);
389cb3126e6SKarl Relton 	msg1.channellist.data.len = request->n_channels;
390cb3126e6SKarl Relton 
391cb3126e6SKarl Relton 	msg1.maxchanneltime.data = 250;
392cb3126e6SKarl Relton 	msg1.minchanneltime.data = 200;
393cb3126e6SKarl Relton 
394cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *) &msg1);
395cb3126e6SKarl Relton 	if (result) {
396cb3126e6SKarl Relton 		err = prism2_result2err(msg1.resultcode.data);
397cb3126e6SKarl Relton 		goto exit;
398cb3126e6SKarl Relton 	}
399cb3126e6SKarl Relton 	/* Now retrieve scan results */
400cb3126e6SKarl Relton 	numbss = msg1.numbss.data;
401cb3126e6SKarl Relton 
402cb3126e6SKarl Relton 	for (i = 0; i < numbss; i++) {
4034e5e9d7cSZhao, Gang 		int freq;
4044e5e9d7cSZhao, Gang 
405cb3126e6SKarl Relton 		memset(&msg2, 0, sizeof(msg2));
406cb3126e6SKarl Relton 		msg2.msgcode = DIDmsg_dot11req_scan_results;
407cb3126e6SKarl Relton 		msg2.bssindex.data = i;
408cb3126e6SKarl Relton 
409cb3126e6SKarl Relton 		result = p80211req_dorequest(wlandev, (u8 *) &msg2);
410cb3126e6SKarl Relton 		if ((result != 0) ||
411cb3126e6SKarl Relton 		    (msg2.resultcode.data != P80211ENUM_resultcode_success)) {
412cb3126e6SKarl Relton 			break;
413cb3126e6SKarl Relton 		}
414cb3126e6SKarl Relton 
415cb3126e6SKarl Relton 		ie_buf[0] = WLAN_EID_SSID;
416cb3126e6SKarl Relton 		ie_buf[1] = msg2.ssid.data.len;
417cb3126e6SKarl Relton 		ie_len = ie_buf[1] + 2;
418cb3126e6SKarl Relton 		memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len);
4194e5e9d7cSZhao, Gang 		freq = ieee80211_channel_to_frequency(msg2.dschannel.data,
4204e5e9d7cSZhao, Gang 						      IEEE80211_BAND_2GHZ);
42119f798adSKrzysztof Wilczynski 		bss = cfg80211_inform_bss(wiphy,
4224e5e9d7cSZhao, Gang 			ieee80211_get_channel(wiphy, freq),
423cb3126e6SKarl Relton 			(const u8 *) &(msg2.bssid.data.data),
424cb3126e6SKarl Relton 			msg2.timestamp.data, msg2.capinfo.data,
425cb3126e6SKarl Relton 			msg2.beaconperiod.data,
426cb3126e6SKarl Relton 			ie_buf,
427cb3126e6SKarl Relton 			ie_len,
428cb3126e6SKarl Relton 			(msg2.signal.data - 65536) * 100, /* Conversion to signed type */
429cb3126e6SKarl Relton 			GFP_KERNEL
430cb3126e6SKarl Relton 		);
43119f798adSKrzysztof Wilczynski 
43219f798adSKrzysztof Wilczynski 		if (!bss) {
43319f798adSKrzysztof Wilczynski 			err = -ENOMEM;
43419f798adSKrzysztof Wilczynski 			goto exit;
43519f798adSKrzysztof Wilczynski 		}
43619f798adSKrzysztof Wilczynski 
4375b112d3dSJohannes Berg 		cfg80211_put_bss(wiphy, bss);
438cb3126e6SKarl Relton 	}
439cb3126e6SKarl Relton 
4408dd82ebeSEdgardo Hames 	if (result)
441cb3126e6SKarl Relton 		err = prism2_result2err(msg2.resultcode.data);
442cb3126e6SKarl Relton 
443cb3126e6SKarl Relton exit:
444cb3126e6SKarl Relton 	cfg80211_scan_done(request, err ? 1 : 0);
445cb3126e6SKarl Relton 	priv->scan_request = NULL;
446cb3126e6SKarl Relton 	return err;
447cb3126e6SKarl Relton }
448cb3126e6SKarl Relton 
44955da06ebSTeodora Baluta static int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed)
4508dd82ebeSEdgardo Hames {
451cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
452cb3126e6SKarl Relton 	wlandevice_t *wlandev = priv->wlandev;
453cb3126e6SKarl Relton 	u32 data;
454cb3126e6SKarl Relton 	int result;
455cb3126e6SKarl Relton 	int err = 0;
456cb3126e6SKarl Relton 
457cb3126e6SKarl Relton 	if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
458cb3126e6SKarl Relton 		if (wiphy->rts_threshold == -1)
459cb3126e6SKarl Relton 			data = 2347;
460cb3126e6SKarl Relton 		else
461cb3126e6SKarl Relton 			data = wiphy->rts_threshold;
462cb3126e6SKarl Relton 
4638dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
464cb3126e6SKarl Relton 						DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold,
465cb3126e6SKarl Relton 						data);
466cb3126e6SKarl Relton 		if (result) {
467cb3126e6SKarl Relton 			err = -EFAULT;
468cb3126e6SKarl Relton 			goto exit;
469cb3126e6SKarl Relton 		}
470cb3126e6SKarl Relton 	}
471cb3126e6SKarl Relton 
472cb3126e6SKarl Relton 	if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
473cb3126e6SKarl Relton 		if (wiphy->frag_threshold == -1)
474cb3126e6SKarl Relton 			data = 2346;
475cb3126e6SKarl Relton 		else
476cb3126e6SKarl Relton 			data = wiphy->frag_threshold;
477cb3126e6SKarl Relton 
4788dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
479cb3126e6SKarl Relton 						DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold,
480cb3126e6SKarl Relton 						data);
481cb3126e6SKarl Relton 		if (result) {
482cb3126e6SKarl Relton 			err = -EFAULT;
483cb3126e6SKarl Relton 			goto exit;
484cb3126e6SKarl Relton 		}
485cb3126e6SKarl Relton 	}
486cb3126e6SKarl Relton 
487cb3126e6SKarl Relton exit:
488cb3126e6SKarl Relton 	return err;
489cb3126e6SKarl Relton }
490cb3126e6SKarl Relton 
49155da06ebSTeodora Baluta static int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
4928dd82ebeSEdgardo Hames 			  struct cfg80211_connect_params *sme)
4938dd82ebeSEdgardo Hames {
494cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
495cb3126e6SKarl Relton 	struct ieee80211_channel *channel = sme->channel;
496b6bb56e6SEdgardo Hames 	struct p80211msg_lnxreq_autojoin msg_join;
497cb3126e6SKarl Relton 	u32 did;
498cb3126e6SKarl Relton 	int length = sme->ssid_len;
499cb3126e6SKarl Relton 	int chan = -1;
500cb3126e6SKarl Relton 	int is_wep = (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) ||
501cb3126e6SKarl Relton 	    (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104);
502cb3126e6SKarl Relton 	int result;
503cb3126e6SKarl Relton 	int err = 0;
504cb3126e6SKarl Relton 
505cb3126e6SKarl Relton 	/* Set the channel */
506cb3126e6SKarl Relton 	if (channel) {
507cb3126e6SKarl Relton 		chan = ieee80211_frequency_to_channel(channel->center_freq);
5088dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
509cb3126e6SKarl Relton 						DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel,
510cb3126e6SKarl Relton 						chan);
5118dd82ebeSEdgardo Hames 		if (result)
5128dd82ebeSEdgardo Hames 			goto exit;
513cb3126e6SKarl Relton 	}
514cb3126e6SKarl Relton 
515d34602deSJustin P. Mattock 	/* Set the authorization */
516cb3126e6SKarl Relton 	if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ||
517cb3126e6SKarl Relton 		((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep))
518cb3126e6SKarl Relton 			msg_join.authtype.data = P80211ENUM_authalg_opensystem;
519cb3126e6SKarl Relton 	else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ||
520cb3126e6SKarl Relton 		((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep))
521cb3126e6SKarl Relton 			msg_join.authtype.data = P80211ENUM_authalg_sharedkey;
5228dd82ebeSEdgardo Hames 	else
523eed88971SAvinash Kumar 		netdev_warn(dev,
5248dd82ebeSEdgardo Hames 			"Unhandled authorisation type for connect (%d)\n",
5258dd82ebeSEdgardo Hames 			sme->auth_type);
526cb3126e6SKarl Relton 
527cb3126e6SKarl Relton 	/* Set the encryption - we only support wep */
528cb3126e6SKarl Relton 	if (is_wep) {
529cb3126e6SKarl Relton 		if (sme->key) {
530cb3126e6SKarl Relton 			result = prism2_domibset_uint32(wlandev,
531cb3126e6SKarl Relton 				DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
532cb3126e6SKarl Relton 				sme->key_idx);
5338dd82ebeSEdgardo Hames 			if (result)
5348dd82ebeSEdgardo Hames 				goto exit;
535cb3126e6SKarl Relton 
536cb3126e6SKarl Relton 			/* send key to driver */
537cb3126e6SKarl Relton 			switch (sme->key_idx) {
538cb3126e6SKarl Relton 			case 0:
5398dd82ebeSEdgardo Hames 				did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
540cb3126e6SKarl Relton 				break;
541cb3126e6SKarl Relton 
542cb3126e6SKarl Relton 			case 1:
5438dd82ebeSEdgardo Hames 				did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
544cb3126e6SKarl Relton 				break;
545cb3126e6SKarl Relton 
546cb3126e6SKarl Relton 			case 2:
5478dd82ebeSEdgardo Hames 				did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
548cb3126e6SKarl Relton 				break;
549cb3126e6SKarl Relton 
550cb3126e6SKarl Relton 			case 3:
5518dd82ebeSEdgardo Hames 				did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
552cb3126e6SKarl Relton 				break;
553cb3126e6SKarl Relton 
554cb3126e6SKarl Relton 			default:
555cb3126e6SKarl Relton 				err = -EINVAL;
556cb3126e6SKarl Relton 				goto exit;
557cb3126e6SKarl Relton 			}
558cb3126e6SKarl Relton 
5598aac4d44SDevendra Naga 			result = prism2_domibset_pstr32(wlandev,
5608aac4d44SDevendra Naga 							did, sme->key_len,
5618aac4d44SDevendra Naga 							(u8 *)sme->key);
5628dd82ebeSEdgardo Hames 			if (result)
5638dd82ebeSEdgardo Hames 				goto exit;
564cb3126e6SKarl Relton 
565cb3126e6SKarl Relton 		}
566cb3126e6SKarl Relton 
567cb3126e6SKarl Relton 		/* Assume we should set privacy invoked and exclude unencrypted
568cb3126e6SKarl Relton 		   We could possibly use sme->privacy here, but the assumption
569cb3126e6SKarl Relton 		   seems reasonable anyway */
5708dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5718dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
572cb3126e6SKarl Relton 						P80211ENUM_truth_true);
5738dd82ebeSEdgardo Hames 		if (result)
5748dd82ebeSEdgardo Hames 			goto exit;
5758dd82ebeSEdgardo Hames 
5768dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5778dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
578cb3126e6SKarl Relton 						P80211ENUM_truth_true);
5798dd82ebeSEdgardo Hames 		if (result)
5808dd82ebeSEdgardo Hames 			goto exit;
581cb3126e6SKarl Relton 
582cb3126e6SKarl Relton 	} else {
5838dd82ebeSEdgardo Hames 		/* Assume we should unset privacy invoked
5848dd82ebeSEdgardo Hames 		   and exclude unencrypted */
5858dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5868dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
587cb3126e6SKarl Relton 						P80211ENUM_truth_false);
5888dd82ebeSEdgardo Hames 		if (result)
5898dd82ebeSEdgardo Hames 			goto exit;
5908dd82ebeSEdgardo Hames 
5918dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5928dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
593cb3126e6SKarl Relton 						P80211ENUM_truth_false);
5948dd82ebeSEdgardo Hames 		if (result)
5958dd82ebeSEdgardo Hames 			goto exit;
596cb3126e6SKarl Relton 
597cb3126e6SKarl Relton 	}
598cb3126e6SKarl Relton 
599cb3126e6SKarl Relton 	/* Now do the actual join. Note there is no way that I can
600cb3126e6SKarl Relton 	   see to request a specific bssid */
601cb3126e6SKarl Relton 	msg_join.msgcode = DIDmsg_lnxreq_autojoin;
602cb3126e6SKarl Relton 
603cb3126e6SKarl Relton 	memcpy(msg_join.ssid.data.data, sme->ssid, length);
604cb3126e6SKarl Relton 	msg_join.ssid.data.len = length;
605cb3126e6SKarl Relton 
606cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *) &msg_join);
607cb3126e6SKarl Relton 
608cb3126e6SKarl Relton exit:
6098dd82ebeSEdgardo Hames 	if (result)
6108dd82ebeSEdgardo Hames 		err = -EFAULT;
611cb3126e6SKarl Relton 
612cb3126e6SKarl Relton 	return err;
613cb3126e6SKarl Relton }
614cb3126e6SKarl Relton 
61555da06ebSTeodora Baluta static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev,
6168dd82ebeSEdgardo Hames 			     u16 reason_code)
6178dd82ebeSEdgardo Hames {
618cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
619b6bb56e6SEdgardo Hames 	struct p80211msg_lnxreq_autojoin msg_join;
620cb3126e6SKarl Relton 	int result;
621cb3126e6SKarl Relton 	int err = 0;
622cb3126e6SKarl Relton 
623cb3126e6SKarl Relton 
624cb3126e6SKarl Relton 	/* Do a join, with a bogus ssid. Thats the only way I can think of */
625cb3126e6SKarl Relton 	msg_join.msgcode = DIDmsg_lnxreq_autojoin;
626cb3126e6SKarl Relton 
627cb3126e6SKarl Relton 	memcpy(msg_join.ssid.data.data, "---", 3);
628cb3126e6SKarl Relton 	msg_join.ssid.data.len = 3;
629cb3126e6SKarl Relton 
630cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *) &msg_join);
631cb3126e6SKarl Relton 
6328dd82ebeSEdgardo Hames 	if (result)
6338dd82ebeSEdgardo Hames 		err = -EFAULT;
634cb3126e6SKarl Relton 
635cb3126e6SKarl Relton 	return err;
636cb3126e6SKarl Relton }
637cb3126e6SKarl Relton 
638cb3126e6SKarl Relton 
63955da06ebSTeodora Baluta static int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev,
6408dd82ebeSEdgardo Hames 			    struct cfg80211_ibss_params *params)
6418dd82ebeSEdgardo Hames {
642cb3126e6SKarl Relton 	return -EOPNOTSUPP;
643cb3126e6SKarl Relton }
644cb3126e6SKarl Relton 
64555da06ebSTeodora Baluta static int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
6468dd82ebeSEdgardo Hames {
647cb3126e6SKarl Relton 	return -EOPNOTSUPP;
648cb3126e6SKarl Relton }
649cb3126e6SKarl Relton 
650cb3126e6SKarl Relton 
65155da06ebSTeodora Baluta static int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
6525f3b361aSEmil Goode 			       enum nl80211_tx_power_setting type, int mbm)
6538dd82ebeSEdgardo Hames {
654cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
655cb3126e6SKarl Relton 	wlandevice_t *wlandev = priv->wlandev;
656cb3126e6SKarl Relton 	u32 data;
657cb3126e6SKarl Relton 	int result;
658cb3126e6SKarl Relton 	int err = 0;
659cb3126e6SKarl Relton 
6609015e499SChristoph Fritz 	if (type == NL80211_TX_POWER_AUTOMATIC)
661cb3126e6SKarl Relton 		data = 30;
662cb3126e6SKarl Relton 	else
6639015e499SChristoph Fritz 		data = MBM_TO_DBM(mbm);
664cb3126e6SKarl Relton 
665cb3126e6SKarl Relton 	result = prism2_domibset_uint32(wlandev,
666cb3126e6SKarl Relton 		DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel,
667cb3126e6SKarl Relton 		data);
668cb3126e6SKarl Relton 
669cb3126e6SKarl Relton 	if (result) {
670cb3126e6SKarl Relton 		err = -EFAULT;
671cb3126e6SKarl Relton 		goto exit;
672cb3126e6SKarl Relton 	}
673cb3126e6SKarl Relton 
674cb3126e6SKarl Relton exit:
675cb3126e6SKarl Relton 	return err;
676cb3126e6SKarl Relton }
677cb3126e6SKarl Relton 
67855da06ebSTeodora Baluta static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
6795f3b361aSEmil Goode 			       int *dbm)
6808dd82ebeSEdgardo Hames {
681cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
682cb3126e6SKarl Relton 	wlandevice_t *wlandev = priv->wlandev;
683b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_mibget msg;
6848aac4d44SDevendra Naga 	p80211item_uint32_t *mibitem;
685cb3126e6SKarl Relton 	int result;
686cb3126e6SKarl Relton 	int err = 0;
687cb3126e6SKarl Relton 
6888aac4d44SDevendra Naga 	mibitem = (p80211item_uint32_t *) &msg.mibattribute.data;
689cb3126e6SKarl Relton 	msg.msgcode = DIDmsg_dot11req_mibget;
690cb3126e6SKarl Relton 	mibitem->did =
691cb3126e6SKarl Relton 	    DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
692cb3126e6SKarl Relton 
693cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *) &msg);
694cb3126e6SKarl Relton 
695cb3126e6SKarl Relton 	if (result) {
696cb3126e6SKarl Relton 		err = -EFAULT;
697cb3126e6SKarl Relton 		goto exit;
698cb3126e6SKarl Relton 	}
699cb3126e6SKarl Relton 
700cb3126e6SKarl Relton 	*dbm = mibitem->data;
701cb3126e6SKarl Relton 
702cb3126e6SKarl Relton exit:
703cb3126e6SKarl Relton 	return err;
704cb3126e6SKarl Relton }
705cb3126e6SKarl Relton 
706cb3126e6SKarl Relton 
707cb3126e6SKarl Relton 
708cb3126e6SKarl Relton 
709cb3126e6SKarl Relton /* Interface callback functions, passing data back up to the cfg80211 layer */
7108dd82ebeSEdgardo Hames void prism2_connect_result(wlandevice_t *wlandev, u8 failed)
7118dd82ebeSEdgardo Hames {
7128aac4d44SDevendra Naga 	u16 status = failed ?
7138aac4d44SDevendra Naga 		     WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS;
714cb3126e6SKarl Relton 
715cb3126e6SKarl Relton 	cfg80211_connect_result(wlandev->netdev, wlandev->bssid,
7168dd82ebeSEdgardo Hames 				NULL, 0, NULL, 0, status, GFP_KERNEL);
717cb3126e6SKarl Relton }
718cb3126e6SKarl Relton 
7198dd82ebeSEdgardo Hames void prism2_disconnected(wlandevice_t *wlandev)
7208dd82ebeSEdgardo Hames {
721cb3126e6SKarl Relton 	cfg80211_disconnected(wlandev->netdev, 0, NULL,
722cb3126e6SKarl Relton 		0, GFP_KERNEL);
723cb3126e6SKarl Relton }
724cb3126e6SKarl Relton 
7258dd82ebeSEdgardo Hames void prism2_roamed(wlandevice_t *wlandev)
7268dd82ebeSEdgardo Hames {
727ed9d0102SJouni Malinen 	cfg80211_roamed(wlandev->netdev, NULL, wlandev->bssid,
728cb3126e6SKarl Relton 		NULL, 0, NULL, 0, GFP_KERNEL);
729cb3126e6SKarl Relton }
730cb3126e6SKarl Relton 
731cb3126e6SKarl Relton 
732cb3126e6SKarl Relton /* Structures for declaring wiphy interface */
733cb3126e6SKarl Relton static const struct cfg80211_ops prism2_usb_cfg_ops = {
734cb3126e6SKarl Relton 	.change_virtual_intf = prism2_change_virtual_intf,
735cb3126e6SKarl Relton 	.add_key = prism2_add_key,
736cb3126e6SKarl Relton 	.get_key = prism2_get_key,
737cb3126e6SKarl Relton 	.del_key = prism2_del_key,
738cb3126e6SKarl Relton 	.set_default_key = prism2_set_default_key,
739cb3126e6SKarl Relton 	.get_station = prism2_get_station,
740cb3126e6SKarl Relton 	.scan = prism2_scan,
741cb3126e6SKarl Relton 	.set_wiphy_params = prism2_set_wiphy_params,
742cb3126e6SKarl Relton 	.connect = prism2_connect,
743cb3126e6SKarl Relton 	.disconnect = prism2_disconnect,
744cb3126e6SKarl Relton 	.join_ibss = prism2_join_ibss,
745cb3126e6SKarl Relton 	.leave_ibss = prism2_leave_ibss,
746cb3126e6SKarl Relton 	.set_tx_power = prism2_set_tx_power,
747cb3126e6SKarl Relton 	.get_tx_power = prism2_get_tx_power,
748cb3126e6SKarl Relton };
749cb3126e6SKarl Relton 
750cb3126e6SKarl Relton 
751cb3126e6SKarl Relton /* Functions to create/free wiphy interface */
75236d9c250STugce Sirin static struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev)
753cb3126e6SKarl Relton {
754cb3126e6SKarl Relton 	struct wiphy *wiphy;
755cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv;
7568aac4d44SDevendra Naga 
7578aac4d44SDevendra Naga 	wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(*priv));
758cb3126e6SKarl Relton 	if (!wiphy)
759cb3126e6SKarl Relton 		return NULL;
760cb3126e6SKarl Relton 
761cb3126e6SKarl Relton 	priv = wiphy_priv(wiphy);
762cb3126e6SKarl Relton 	priv->wlandev = wlandev;
763cb3126e6SKarl Relton 	memcpy(priv->channels, prism2_channels, sizeof(prism2_channels));
764cb3126e6SKarl Relton 	memcpy(priv->rates, prism2_rates, sizeof(prism2_rates));
765cb3126e6SKarl Relton 	priv->band.channels = priv->channels;
766cb3126e6SKarl Relton 	priv->band.n_channels = ARRAY_SIZE(prism2_channels);
767cb3126e6SKarl Relton 	priv->band.bitrates = priv->rates;
768cb3126e6SKarl Relton 	priv->band.n_bitrates = ARRAY_SIZE(prism2_rates);
769aff3ea4eSKarl Relton 	priv->band.band = IEEE80211_BAND_2GHZ;
770aff3ea4eSKarl Relton 	priv->band.ht_cap.ht_supported = false;
771cb3126e6SKarl Relton 	wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
772cb3126e6SKarl Relton 
773cb3126e6SKarl Relton 	set_wiphy_dev(wiphy, dev);
774cb3126e6SKarl Relton 	wiphy->privid = prism2_wiphy_privid;
775cb3126e6SKarl Relton 	wiphy->max_scan_ssids = 1;
7768dd82ebeSEdgardo Hames 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
7778dd82ebeSEdgardo Hames 				 | BIT(NL80211_IFTYPE_ADHOC);
778cb3126e6SKarl Relton 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
779cb3126e6SKarl Relton 	wiphy->n_cipher_suites = PRISM2_NUM_CIPHER_SUITES;
780cb3126e6SKarl Relton 	wiphy->cipher_suites = prism2_cipher_suites;
781cb3126e6SKarl Relton 
782cb3126e6SKarl Relton 	if (wiphy_register(wiphy) < 0)
783cb3126e6SKarl Relton 		return NULL;
784cb3126e6SKarl Relton 
785cb3126e6SKarl Relton 	return wiphy;
786cb3126e6SKarl Relton }
787cb3126e6SKarl Relton 
788cb3126e6SKarl Relton 
78936d9c250STugce Sirin static void wlan_free_wiphy(struct wiphy *wiphy)
790cb3126e6SKarl Relton {
791cb3126e6SKarl Relton 	wiphy_unregister(wiphy);
792cb3126e6SKarl Relton 	wiphy_free(wiphy);
793cb3126e6SKarl Relton }
794