1cb3126e6SKarl Relton /* cfg80211 Interface for prism2_usb module */
2cb3126e6SKarl Relton 
3cb3126e6SKarl Relton 
4cb3126e6SKarl Relton /* Prism2 channell/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;
76cb3126e6SKarl Relton 	p80211item_uint32_t *mibitem = (p80211item_uint32_t *) &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 
85cb3126e6SKarl Relton static int prism2_domibset_pstr32(wlandevice_t *wlandev,
86cb3126e6SKarl Relton 				  u32 did, u8 len, u8 *data)
87cb3126e6SKarl Relton {
88b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_mibset msg;
89cb3126e6SKarl Relton 	p80211item_pstr32_t *mibitem = (p80211item_pstr32_t *) &msg.mibattribute.data;
90cb3126e6SKarl Relton 
91cb3126e6SKarl Relton 	msg.msgcode = DIDmsg_dot11req_mibset;
92cb3126e6SKarl Relton 	mibitem->did = did;
93cb3126e6SKarl Relton 	mibitem->data.len = len;
94cb3126e6SKarl Relton 	memcpy(mibitem->data.data, data, len);
95cb3126e6SKarl Relton 
96cb3126e6SKarl Relton 	return p80211req_dorequest(wlandev, (u8 *) &msg);
97cb3126e6SKarl Relton }
98cb3126e6SKarl Relton 
99cb3126e6SKarl Relton 
100cb3126e6SKarl Relton /* The interface functions, called by the cfg80211 layer */
101cb3126e6SKarl Relton int prism2_change_virtual_intf(struct wiphy *wiphy,
102cb3126e6SKarl Relton 			       struct net_device *dev,
103cb3126e6SKarl Relton 			       enum nl80211_iftype type, u32 *flags,
104cb3126e6SKarl Relton 			       struct vif_params *params)
105cb3126e6SKarl Relton {
106cb3126e6SKarl Relton 	wlandevice_t *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:
125cb3126e6SKarl Relton 		printk(KERN_WARNING "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 
143cb3126e6SKarl Relton 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 {
147cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
148cb3126e6SKarl Relton 	u32 did;
149cb3126e6SKarl Relton 
150cb3126e6SKarl Relton 	int err = 0;
151cb3126e6SKarl Relton 	int result = 0;
152cb3126e6SKarl Relton 
153cb3126e6SKarl Relton 	switch (params->cipher) {
154cb3126e6SKarl Relton 	case WLAN_CIPHER_SUITE_WEP40:
155cb3126e6SKarl Relton 	case WLAN_CIPHER_SUITE_WEP104:
156cb3126e6SKarl Relton 		result = prism2_domibset_uint32(wlandev,
157cb3126e6SKarl Relton 						DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
158cb3126e6SKarl Relton 						key_index);
1598dd82ebeSEdgardo Hames 		if (result)
1608dd82ebeSEdgardo Hames 			goto exit;
161cb3126e6SKarl Relton 
162cb3126e6SKarl Relton 		/* send key to driver */
163cb3126e6SKarl Relton 		switch (key_index) {
164cb3126e6SKarl Relton 		case 0:
1658dd82ebeSEdgardo Hames 			did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
166cb3126e6SKarl Relton 			break;
167cb3126e6SKarl Relton 
168cb3126e6SKarl Relton 		case 1:
1698dd82ebeSEdgardo Hames 			did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
170cb3126e6SKarl Relton 			break;
171cb3126e6SKarl Relton 
172cb3126e6SKarl Relton 		case 2:
1738dd82ebeSEdgardo Hames 			did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
174cb3126e6SKarl Relton 			break;
175cb3126e6SKarl Relton 
176cb3126e6SKarl Relton 		case 3:
1778dd82ebeSEdgardo Hames 			did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
178cb3126e6SKarl Relton 			break;
179cb3126e6SKarl Relton 
180cb3126e6SKarl Relton 		default:
181cb3126e6SKarl Relton 			err = -EINVAL;
182cb3126e6SKarl Relton 			goto exit;
183cb3126e6SKarl Relton 		}
184cb3126e6SKarl Relton 
185cb3126e6SKarl Relton 		result = prism2_domibset_pstr32(wlandev, did, params->key_len, params->key);
1868dd82ebeSEdgardo Hames 		if (result)
1878dd82ebeSEdgardo Hames 			goto exit;
188cb3126e6SKarl Relton 		break;
189cb3126e6SKarl Relton 
190cb3126e6SKarl Relton 	default:
191cb3126e6SKarl Relton 		pr_debug("Unsupported cipher suite\n");
192cb3126e6SKarl Relton 		result = 1;
193cb3126e6SKarl Relton 	}
194cb3126e6SKarl Relton 
195cb3126e6SKarl Relton exit:
1968dd82ebeSEdgardo Hames 	if (result)
1978dd82ebeSEdgardo Hames 		err = -EFAULT;
198cb3126e6SKarl Relton 
199cb3126e6SKarl Relton 	return err;
200cb3126e6SKarl Relton }
201cb3126e6SKarl Relton 
202cb3126e6SKarl Relton int prism2_get_key(struct wiphy *wiphy, struct net_device *dev,
20334a488c1SBen Hutchings 		   u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie,
2048dd82ebeSEdgardo Hames 		   void (*callback)(void *cookie, struct key_params*))
2058dd82ebeSEdgardo Hames {
206cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
207cb3126e6SKarl Relton 	struct key_params params;
208cb3126e6SKarl Relton 	int len;
209cb3126e6SKarl Relton 
2108dd82ebeSEdgardo Hames 	if (key_index >= NUM_WEPKEYS)
2118dd82ebeSEdgardo Hames 		return -EINVAL;
212cb3126e6SKarl Relton 
213cb3126e6SKarl Relton 	len = wlandev->wep_keylens[key_index];
214cb3126e6SKarl Relton 	memset(&params, 0, sizeof(params));
215cb3126e6SKarl Relton 
2168dd82ebeSEdgardo Hames 	if (len == 13)
217cb3126e6SKarl Relton 		params.cipher = WLAN_CIPHER_SUITE_WEP104;
2188dd82ebeSEdgardo Hames 	else if (len == 5)
219cb3126e6SKarl Relton 		params.cipher = WLAN_CIPHER_SUITE_WEP104;
2208dd82ebeSEdgardo Hames 	else
2218dd82ebeSEdgardo Hames 		return -ENOENT;
222cb3126e6SKarl Relton 	params.key_len = len;
223cb3126e6SKarl Relton 	params.key = wlandev->wep_keys[key_index];
224aff3ea4eSKarl Relton 	params.seq_len = 0;
225cb3126e6SKarl Relton 
226cb3126e6SKarl Relton 	callback(cookie, &params);
2278dd82ebeSEdgardo Hames 
228cb3126e6SKarl Relton 	return 0;
229cb3126e6SKarl Relton }
230cb3126e6SKarl Relton 
231cb3126e6SKarl Relton int prism2_del_key(struct wiphy *wiphy, struct net_device *dev,
23234a488c1SBen Hutchings 		   u8 key_index, bool pairwise, const u8 *mac_addr)
2338dd82ebeSEdgardo Hames {
234cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
235cb3126e6SKarl Relton 	u32 did;
236cb3126e6SKarl Relton 	int err = 0;
237cb3126e6SKarl Relton 	int result = 0;
238cb3126e6SKarl Relton 
239cb3126e6SKarl Relton 	/* There is no direct way in the hardware (AFAIK) of removing
240cb3126e6SKarl Relton 	   a key, so we will cheat by setting the key to a bogus value */
241cb3126e6SKarl Relton 	/* send key to driver */
242cb3126e6SKarl Relton 	switch (key_index) {
243cb3126e6SKarl Relton 	case 0:
244cb3126e6SKarl Relton 		did =
245cb3126e6SKarl Relton 		    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
246cb3126e6SKarl Relton 		break;
247cb3126e6SKarl Relton 
248cb3126e6SKarl Relton 	case 1:
249cb3126e6SKarl Relton 		did =
250cb3126e6SKarl Relton 		    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
251cb3126e6SKarl Relton 		break;
252cb3126e6SKarl Relton 
253cb3126e6SKarl Relton 	case 2:
254cb3126e6SKarl Relton 		did =
255cb3126e6SKarl Relton 		    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
256cb3126e6SKarl Relton 		break;
257cb3126e6SKarl Relton 
258cb3126e6SKarl Relton 	case 3:
259cb3126e6SKarl Relton 		did =
260cb3126e6SKarl Relton 		    DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
261cb3126e6SKarl Relton 		break;
262cb3126e6SKarl Relton 
263cb3126e6SKarl Relton 	default:
264cb3126e6SKarl Relton 		err = -EINVAL;
265cb3126e6SKarl Relton 		goto exit;
266cb3126e6SKarl Relton 	}
267cb3126e6SKarl Relton 
268cb3126e6SKarl Relton 	result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000");
269cb3126e6SKarl Relton 
270cb3126e6SKarl Relton exit:
2718dd82ebeSEdgardo Hames 	if (result)
2728dd82ebeSEdgardo Hames 		err = -EFAULT;
273cb3126e6SKarl Relton 
274cb3126e6SKarl Relton 	return err;
275cb3126e6SKarl Relton }
276cb3126e6SKarl Relton 
277cb3126e6SKarl Relton int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
2789005fcd8SHarry Wei 			   u8 key_index, bool unicast, bool multicast)
2798dd82ebeSEdgardo Hames {
280cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
281cb3126e6SKarl Relton 
282cb3126e6SKarl Relton 	int err = 0;
283cb3126e6SKarl Relton 	int result = 0;
284cb3126e6SKarl Relton 
285cb3126e6SKarl Relton 	result = prism2_domibset_uint32(wlandev,
286cb3126e6SKarl Relton 		DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
287cb3126e6SKarl Relton 		key_index);
288cb3126e6SKarl Relton 
2898dd82ebeSEdgardo Hames 	if (result)
2908dd82ebeSEdgardo Hames 		err = -EFAULT;
291cb3126e6SKarl Relton 
292cb3126e6SKarl Relton 	return err;
293cb3126e6SKarl Relton }
294cb3126e6SKarl Relton 
295cb3126e6SKarl Relton 
296cb3126e6SKarl Relton int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
2978dd82ebeSEdgardo Hames 		       u8 *mac, struct station_info *sinfo)
2988dd82ebeSEdgardo Hames {
299cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
300b6bb56e6SEdgardo Hames 	struct p80211msg_lnxreq_commsquality quality;
301cb3126e6SKarl Relton 	int result;
302cb3126e6SKarl Relton 
303cb3126e6SKarl Relton 	memset(sinfo, 0, sizeof(*sinfo));
304cb3126e6SKarl Relton 
305cb3126e6SKarl Relton 	if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING))
306cb3126e6SKarl Relton 		return -EOPNOTSUPP;
307cb3126e6SKarl Relton 
308cb3126e6SKarl Relton 	/* build request message */
309cb3126e6SKarl Relton 	quality.msgcode = DIDmsg_lnxreq_commsquality;
310cb3126e6SKarl Relton 	quality.dbm.data = P80211ENUM_truth_true;
311cb3126e6SKarl Relton 	quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
312cb3126e6SKarl Relton 
313cb3126e6SKarl Relton 	/* send message to nsd */
314cb3126e6SKarl Relton 	if (wlandev->mlmerequest == NULL)
315cb3126e6SKarl Relton 		return -EOPNOTSUPP;
316cb3126e6SKarl Relton 
3173d049431SEdgardo Hames 	result = wlandev->mlmerequest(wlandev, (struct p80211msg *) &quality);
318cb3126e6SKarl Relton 
319cb3126e6SKarl Relton 
320cb3126e6SKarl Relton 	if (result == 0) {
321cb3126e6SKarl Relton 		sinfo->txrate.legacy = quality.txrate.data;
322cb3126e6SKarl Relton 		sinfo->filled |= STATION_INFO_TX_BITRATE;
323cb3126e6SKarl Relton 		sinfo->signal = quality.level.data;
324cb3126e6SKarl Relton 		sinfo->filled |= STATION_INFO_SIGNAL;
325cb3126e6SKarl Relton 	}
326cb3126e6SKarl Relton 
327cb3126e6SKarl Relton 	return result;
328cb3126e6SKarl Relton }
329cb3126e6SKarl Relton 
33001f8a27eSEmil Goode int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
331cb3126e6SKarl Relton {
3325d5d7c3bSEmil Goode 	struct net_device *dev;
333cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
3345d5d7c3bSEmil Goode 	wlandevice_t *wlandev;
335b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_scan msg1;
336b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_scan_results msg2;
33719f798adSKrzysztof Wilczynski 	struct cfg80211_bss *bss;
338cb3126e6SKarl Relton 	int result;
339cb3126e6SKarl Relton 	int err = 0;
340cb3126e6SKarl Relton 	int numbss = 0;
341cb3126e6SKarl Relton 	int i = 0;
342cb3126e6SKarl Relton 	u8 ie_buf[46];
343cb3126e6SKarl Relton 	int ie_len;
344cb3126e6SKarl Relton 
345cb3126e6SKarl Relton 	if (!request)
346cb3126e6SKarl Relton 		return -EINVAL;
347cb3126e6SKarl Relton 
3485d5d7c3bSEmil Goode 	dev = request->wdev->netdev;
3495d5d7c3bSEmil Goode 	wlandev = dev->ml_priv;
3505d5d7c3bSEmil Goode 
351cb3126e6SKarl Relton 	if (priv->scan_request && priv->scan_request != request)
352cb3126e6SKarl Relton 		return -EBUSY;
353cb3126e6SKarl Relton 
354cb3126e6SKarl Relton 	if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
355cb3126e6SKarl Relton 		printk(KERN_ERR "Can't scan in AP mode\n");
356cb3126e6SKarl Relton 		return -EOPNOTSUPP;
357cb3126e6SKarl Relton 	}
358cb3126e6SKarl Relton 
359cb3126e6SKarl Relton 	priv->scan_request = request;
360cb3126e6SKarl Relton 
361b6bb56e6SEdgardo Hames 	memset(&msg1, 0x00, sizeof(struct p80211msg_dot11req_scan));
362cb3126e6SKarl Relton 	msg1.msgcode = DIDmsg_dot11req_scan;
363cb3126e6SKarl Relton 	msg1.bsstype.data = P80211ENUM_bsstype_any;
364cb3126e6SKarl Relton 
365625aeb3aSDan Carpenter 	memset(&msg1.bssid.data.data, 0xFF, sizeof(msg1.bssid.data.data));
366cb3126e6SKarl Relton 	msg1.bssid.data.len = 6;
367cb3126e6SKarl Relton 
368cb3126e6SKarl Relton 	if (request->n_ssids > 0) {
369cb3126e6SKarl Relton 		msg1.scantype.data = P80211ENUM_scantype_active;
370cb3126e6SKarl Relton 		msg1.ssid.data.len = request->ssids->ssid_len;
3718aac4d44SDevendra Naga 		memcpy(msg1.ssid.data.data,
3728aac4d44SDevendra Naga 			request->ssids->ssid, request->ssids->ssid_len);
373cb3126e6SKarl Relton 	} else {
374cb3126e6SKarl Relton 		msg1.scantype.data = 0;
375cb3126e6SKarl Relton 	}
376cb3126e6SKarl Relton 	msg1.probedelay.data = 0;
377cb3126e6SKarl Relton 
378cb3126e6SKarl Relton 	for (i = 0;
379cb3126e6SKarl Relton 		(i < request->n_channels) && i < ARRAY_SIZE(prism2_channels);
380cb3126e6SKarl Relton 		i++)
381cb3126e6SKarl Relton 		msg1.channellist.data.data[i] =
382cb3126e6SKarl Relton 			ieee80211_frequency_to_channel(request->channels[i]->center_freq);
383cb3126e6SKarl Relton 	msg1.channellist.data.len = request->n_channels;
384cb3126e6SKarl Relton 
385cb3126e6SKarl Relton 	msg1.maxchanneltime.data = 250;
386cb3126e6SKarl Relton 	msg1.minchanneltime.data = 200;
387cb3126e6SKarl Relton 
388cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *) &msg1);
389cb3126e6SKarl Relton 	if (result) {
390cb3126e6SKarl Relton 		err = prism2_result2err(msg1.resultcode.data);
391cb3126e6SKarl Relton 		goto exit;
392cb3126e6SKarl Relton 	}
393cb3126e6SKarl Relton 	/* Now retrieve scan results */
394cb3126e6SKarl Relton 	numbss = msg1.numbss.data;
395cb3126e6SKarl Relton 
396cb3126e6SKarl Relton 	for (i = 0; i < numbss; i++) {
397cb3126e6SKarl Relton 		memset(&msg2, 0, sizeof(msg2));
398cb3126e6SKarl Relton 		msg2.msgcode = DIDmsg_dot11req_scan_results;
399cb3126e6SKarl Relton 		msg2.bssindex.data = i;
400cb3126e6SKarl Relton 
401cb3126e6SKarl Relton 		result = p80211req_dorequest(wlandev, (u8 *) &msg2);
402cb3126e6SKarl Relton 		if ((result != 0) ||
403cb3126e6SKarl Relton 		    (msg2.resultcode.data != P80211ENUM_resultcode_success)) {
404cb3126e6SKarl Relton 			break;
405cb3126e6SKarl Relton 		}
406cb3126e6SKarl Relton 
407cb3126e6SKarl Relton 		ie_buf[0] = WLAN_EID_SSID;
408cb3126e6SKarl Relton 		ie_buf[1] = msg2.ssid.data.len;
409cb3126e6SKarl Relton 		ie_len = ie_buf[1] + 2;
410cb3126e6SKarl Relton 		memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len);
41119f798adSKrzysztof Wilczynski 		bss = cfg80211_inform_bss(wiphy,
412cb3126e6SKarl Relton 			ieee80211_get_channel(wiphy, ieee80211_dsss_chan_to_freq(msg2.dschannel.data)),
413cb3126e6SKarl Relton 			(const u8 *) &(msg2.bssid.data.data),
414cb3126e6SKarl Relton 			msg2.timestamp.data, msg2.capinfo.data,
415cb3126e6SKarl Relton 			msg2.beaconperiod.data,
416cb3126e6SKarl Relton 			ie_buf,
417cb3126e6SKarl Relton 			ie_len,
418cb3126e6SKarl Relton 			(msg2.signal.data - 65536) * 100, /* Conversion to signed type */
419cb3126e6SKarl Relton 			GFP_KERNEL
420cb3126e6SKarl Relton 		);
42119f798adSKrzysztof Wilczynski 
42219f798adSKrzysztof Wilczynski 		if (!bss) {
42319f798adSKrzysztof Wilczynski 			err = -ENOMEM;
42419f798adSKrzysztof Wilczynski 			goto exit;
42519f798adSKrzysztof Wilczynski 		}
42619f798adSKrzysztof Wilczynski 
42719f798adSKrzysztof Wilczynski 		cfg80211_put_bss(bss);
428cb3126e6SKarl Relton 	}
429cb3126e6SKarl Relton 
4308dd82ebeSEdgardo Hames 	if (result)
431cb3126e6SKarl Relton 		err = prism2_result2err(msg2.resultcode.data);
432cb3126e6SKarl Relton 
433cb3126e6SKarl Relton exit:
434cb3126e6SKarl Relton 	cfg80211_scan_done(request, err ? 1 : 0);
435cb3126e6SKarl Relton 	priv->scan_request = NULL;
436cb3126e6SKarl Relton 	return err;
437cb3126e6SKarl Relton }
438cb3126e6SKarl Relton 
4398dd82ebeSEdgardo Hames int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed)
4408dd82ebeSEdgardo Hames {
441cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
442cb3126e6SKarl Relton 	wlandevice_t *wlandev = priv->wlandev;
443cb3126e6SKarl Relton 	u32 data;
444cb3126e6SKarl Relton 	int result;
445cb3126e6SKarl Relton 	int err = 0;
446cb3126e6SKarl Relton 
447cb3126e6SKarl Relton 	if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
448cb3126e6SKarl Relton 		if (wiphy->rts_threshold == -1)
449cb3126e6SKarl Relton 			data = 2347;
450cb3126e6SKarl Relton 		else
451cb3126e6SKarl Relton 			data = wiphy->rts_threshold;
452cb3126e6SKarl Relton 
4538dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
454cb3126e6SKarl Relton 						DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold,
455cb3126e6SKarl Relton 						data);
456cb3126e6SKarl Relton 		if (result) {
457cb3126e6SKarl Relton 			err = -EFAULT;
458cb3126e6SKarl Relton 			goto exit;
459cb3126e6SKarl Relton 		}
460cb3126e6SKarl Relton 	}
461cb3126e6SKarl Relton 
462cb3126e6SKarl Relton 	if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
463cb3126e6SKarl Relton 		if (wiphy->frag_threshold == -1)
464cb3126e6SKarl Relton 			data = 2346;
465cb3126e6SKarl Relton 		else
466cb3126e6SKarl Relton 			data = wiphy->frag_threshold;
467cb3126e6SKarl Relton 
4688dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
469cb3126e6SKarl Relton 						DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold,
470cb3126e6SKarl Relton 						data);
471cb3126e6SKarl Relton 		if (result) {
472cb3126e6SKarl Relton 			err = -EFAULT;
473cb3126e6SKarl Relton 			goto exit;
474cb3126e6SKarl Relton 		}
475cb3126e6SKarl Relton 	}
476cb3126e6SKarl Relton 
477cb3126e6SKarl Relton exit:
478cb3126e6SKarl Relton 	return err;
479cb3126e6SKarl Relton }
480cb3126e6SKarl Relton 
481cb3126e6SKarl Relton int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
4828dd82ebeSEdgardo Hames 		   struct cfg80211_connect_params *sme)
4838dd82ebeSEdgardo Hames {
484cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
485cb3126e6SKarl Relton 	struct ieee80211_channel *channel = sme->channel;
486b6bb56e6SEdgardo Hames 	struct p80211msg_lnxreq_autojoin msg_join;
487cb3126e6SKarl Relton 	u32 did;
488cb3126e6SKarl Relton 	int length = sme->ssid_len;
489cb3126e6SKarl Relton 	int chan = -1;
490cb3126e6SKarl Relton 	int is_wep = (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) ||
491cb3126e6SKarl Relton 	    (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104);
492cb3126e6SKarl Relton 	int result;
493cb3126e6SKarl Relton 	int err = 0;
494cb3126e6SKarl Relton 
495cb3126e6SKarl Relton 	/* Set the channel */
496cb3126e6SKarl Relton 	if (channel) {
497cb3126e6SKarl Relton 		chan = ieee80211_frequency_to_channel(channel->center_freq);
4988dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
499cb3126e6SKarl Relton 						DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel,
500cb3126e6SKarl Relton 						chan);
5018dd82ebeSEdgardo Hames 		if (result)
5028dd82ebeSEdgardo Hames 			goto exit;
503cb3126e6SKarl Relton 	}
504cb3126e6SKarl Relton 
505cb3126e6SKarl Relton 	/* Set the authorisation */
506cb3126e6SKarl Relton 	if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ||
507cb3126e6SKarl Relton 		((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep))
508cb3126e6SKarl Relton 			msg_join.authtype.data = P80211ENUM_authalg_opensystem;
509cb3126e6SKarl Relton 	else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ||
510cb3126e6SKarl Relton 		((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep))
511cb3126e6SKarl Relton 			msg_join.authtype.data = P80211ENUM_authalg_sharedkey;
5128dd82ebeSEdgardo Hames 	else
5138dd82ebeSEdgardo Hames 		printk(KERN_WARNING
5148dd82ebeSEdgardo Hames 			"Unhandled authorisation type for connect (%d)\n",
5158dd82ebeSEdgardo Hames 			sme->auth_type);
516cb3126e6SKarl Relton 
517cb3126e6SKarl Relton 	/* Set the encryption - we only support wep */
518cb3126e6SKarl Relton 	if (is_wep) {
519cb3126e6SKarl Relton 		if (sme->key) {
520cb3126e6SKarl Relton 			result = prism2_domibset_uint32(wlandev,
521cb3126e6SKarl Relton 				DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
522cb3126e6SKarl Relton 				sme->key_idx);
5238dd82ebeSEdgardo Hames 			if (result)
5248dd82ebeSEdgardo Hames 				goto exit;
525cb3126e6SKarl Relton 
526cb3126e6SKarl Relton 			/* send key to driver */
527cb3126e6SKarl Relton 			switch (sme->key_idx) {
528cb3126e6SKarl Relton 			case 0:
5298dd82ebeSEdgardo Hames 				did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
530cb3126e6SKarl Relton 				break;
531cb3126e6SKarl Relton 
532cb3126e6SKarl Relton 			case 1:
5338dd82ebeSEdgardo Hames 				did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
534cb3126e6SKarl Relton 				break;
535cb3126e6SKarl Relton 
536cb3126e6SKarl Relton 			case 2:
5378dd82ebeSEdgardo Hames 				did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
538cb3126e6SKarl Relton 				break;
539cb3126e6SKarl Relton 
540cb3126e6SKarl Relton 			case 3:
5418dd82ebeSEdgardo Hames 				did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
542cb3126e6SKarl Relton 				break;
543cb3126e6SKarl Relton 
544cb3126e6SKarl Relton 			default:
545cb3126e6SKarl Relton 				err = -EINVAL;
546cb3126e6SKarl Relton 				goto exit;
547cb3126e6SKarl Relton 			}
548cb3126e6SKarl Relton 
5498aac4d44SDevendra Naga 			result = prism2_domibset_pstr32(wlandev,
5508aac4d44SDevendra Naga 							did, sme->key_len,
5518aac4d44SDevendra Naga 							(u8 *)sme->key);
5528dd82ebeSEdgardo Hames 			if (result)
5538dd82ebeSEdgardo Hames 				goto exit;
554cb3126e6SKarl Relton 
555cb3126e6SKarl Relton 		}
556cb3126e6SKarl Relton 
557cb3126e6SKarl Relton 		/* Assume we should set privacy invoked and exclude unencrypted
558cb3126e6SKarl Relton 		   We could possibly use sme->privacy here, but the assumption
559cb3126e6SKarl Relton 		   seems reasonable anyway */
5608dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5618dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
562cb3126e6SKarl Relton 						P80211ENUM_truth_true);
5638dd82ebeSEdgardo Hames 		if (result)
5648dd82ebeSEdgardo Hames 			goto exit;
5658dd82ebeSEdgardo Hames 
5668dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5678dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
568cb3126e6SKarl Relton 						P80211ENUM_truth_true);
5698dd82ebeSEdgardo Hames 		if (result)
5708dd82ebeSEdgardo Hames 			goto exit;
571cb3126e6SKarl Relton 
572cb3126e6SKarl Relton 	} else {
5738dd82ebeSEdgardo Hames 		/* Assume we should unset privacy invoked
5748dd82ebeSEdgardo Hames 		   and exclude unencrypted */
5758dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5768dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
577cb3126e6SKarl Relton 						P80211ENUM_truth_false);
5788dd82ebeSEdgardo Hames 		if (result)
5798dd82ebeSEdgardo Hames 			goto exit;
5808dd82ebeSEdgardo Hames 
5818dd82ebeSEdgardo Hames 		result = prism2_domibset_uint32(wlandev,
5828dd82ebeSEdgardo Hames 						DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
583cb3126e6SKarl Relton 						P80211ENUM_truth_false);
5848dd82ebeSEdgardo Hames 		if (result)
5858dd82ebeSEdgardo Hames 			goto exit;
586cb3126e6SKarl Relton 
587cb3126e6SKarl Relton 	}
588cb3126e6SKarl Relton 
589cb3126e6SKarl Relton 	/* Now do the actual join. Note there is no way that I can
590cb3126e6SKarl Relton 	   see to request a specific bssid */
591cb3126e6SKarl Relton 	msg_join.msgcode = DIDmsg_lnxreq_autojoin;
592cb3126e6SKarl Relton 
593cb3126e6SKarl Relton 	memcpy(msg_join.ssid.data.data, sme->ssid, length);
594cb3126e6SKarl Relton 	msg_join.ssid.data.len = length;
595cb3126e6SKarl Relton 
596cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *) &msg_join);
597cb3126e6SKarl Relton 
598cb3126e6SKarl Relton exit:
5998dd82ebeSEdgardo Hames 	if (result)
6008dd82ebeSEdgardo Hames 		err = -EFAULT;
601cb3126e6SKarl Relton 
602cb3126e6SKarl Relton 	return err;
603cb3126e6SKarl Relton }
604cb3126e6SKarl Relton 
605cb3126e6SKarl Relton int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev,
6068dd82ebeSEdgardo Hames 		      u16 reason_code)
6078dd82ebeSEdgardo Hames {
608cb3126e6SKarl Relton 	wlandevice_t *wlandev = dev->ml_priv;
609b6bb56e6SEdgardo Hames 	struct p80211msg_lnxreq_autojoin msg_join;
610cb3126e6SKarl Relton 	int result;
611cb3126e6SKarl Relton 	int err = 0;
612cb3126e6SKarl Relton 
613cb3126e6SKarl Relton 
614cb3126e6SKarl Relton 	/* Do a join, with a bogus ssid. Thats the only way I can think of */
615cb3126e6SKarl Relton 	msg_join.msgcode = DIDmsg_lnxreq_autojoin;
616cb3126e6SKarl Relton 
617cb3126e6SKarl Relton 	memcpy(msg_join.ssid.data.data, "---", 3);
618cb3126e6SKarl Relton 	msg_join.ssid.data.len = 3;
619cb3126e6SKarl Relton 
620cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *) &msg_join);
621cb3126e6SKarl Relton 
6228dd82ebeSEdgardo Hames 	if (result)
6238dd82ebeSEdgardo Hames 		err = -EFAULT;
624cb3126e6SKarl Relton 
625cb3126e6SKarl Relton 	return err;
626cb3126e6SKarl Relton }
627cb3126e6SKarl Relton 
628cb3126e6SKarl Relton 
629cb3126e6SKarl Relton int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev,
6308dd82ebeSEdgardo Hames 		     struct cfg80211_ibss_params *params)
6318dd82ebeSEdgardo Hames {
632cb3126e6SKarl Relton 	return -EOPNOTSUPP;
633cb3126e6SKarl Relton }
634cb3126e6SKarl Relton 
6358dd82ebeSEdgardo Hames int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
6368dd82ebeSEdgardo Hames {
637cb3126e6SKarl Relton 	return -EOPNOTSUPP;
638cb3126e6SKarl Relton }
639cb3126e6SKarl Relton 
640cb3126e6SKarl Relton 
6419015e499SChristoph Fritz int prism2_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type,
6429015e499SChristoph Fritz 			int mbm)
6438dd82ebeSEdgardo Hames {
644cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
645cb3126e6SKarl Relton 	wlandevice_t *wlandev = priv->wlandev;
646cb3126e6SKarl Relton 	u32 data;
647cb3126e6SKarl Relton 	int result;
648cb3126e6SKarl Relton 	int err = 0;
649cb3126e6SKarl Relton 
6509015e499SChristoph Fritz 	if (type == NL80211_TX_POWER_AUTOMATIC)
651cb3126e6SKarl Relton 		data = 30;
652cb3126e6SKarl Relton 	else
6539015e499SChristoph Fritz 		data = MBM_TO_DBM(mbm);
654cb3126e6SKarl Relton 
655cb3126e6SKarl Relton 	result = prism2_domibset_uint32(wlandev,
656cb3126e6SKarl Relton 		DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel,
657cb3126e6SKarl Relton 		data);
658cb3126e6SKarl Relton 
659cb3126e6SKarl Relton 	if (result) {
660cb3126e6SKarl Relton 		err = -EFAULT;
661cb3126e6SKarl Relton 		goto exit;
662cb3126e6SKarl Relton 	}
663cb3126e6SKarl Relton 
664cb3126e6SKarl Relton exit:
665cb3126e6SKarl Relton 	return err;
666cb3126e6SKarl Relton }
667cb3126e6SKarl Relton 
6688dd82ebeSEdgardo Hames int prism2_get_tx_power(struct wiphy *wiphy, int *dbm)
6698dd82ebeSEdgardo Hames {
670cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
671cb3126e6SKarl Relton 	wlandevice_t *wlandev = priv->wlandev;
672b6bb56e6SEdgardo Hames 	struct p80211msg_dot11req_mibget msg;
6738aac4d44SDevendra Naga 	p80211item_uint32_t *mibitem;
674cb3126e6SKarl Relton 	int result;
675cb3126e6SKarl Relton 	int err = 0;
676cb3126e6SKarl Relton 
6778aac4d44SDevendra Naga 	mibitem = (p80211item_uint32_t *) &msg.mibattribute.data;
678cb3126e6SKarl Relton 	msg.msgcode = DIDmsg_dot11req_mibget;
679cb3126e6SKarl Relton 	mibitem->did =
680cb3126e6SKarl Relton 	    DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
681cb3126e6SKarl Relton 
682cb3126e6SKarl Relton 	result = p80211req_dorequest(wlandev, (u8 *) &msg);
683cb3126e6SKarl Relton 
684cb3126e6SKarl Relton 	if (result) {
685cb3126e6SKarl Relton 		err = -EFAULT;
686cb3126e6SKarl Relton 		goto exit;
687cb3126e6SKarl Relton 	}
688cb3126e6SKarl Relton 
689cb3126e6SKarl Relton 	*dbm = mibitem->data;
690cb3126e6SKarl Relton 
691cb3126e6SKarl Relton exit:
692cb3126e6SKarl Relton 	return err;
693cb3126e6SKarl Relton }
694cb3126e6SKarl Relton 
695cb3126e6SKarl Relton 
696cb3126e6SKarl Relton 
697cb3126e6SKarl Relton 
698cb3126e6SKarl Relton /* Interface callback functions, passing data back up to the cfg80211 layer */
6998dd82ebeSEdgardo Hames void prism2_connect_result(wlandevice_t *wlandev, u8 failed)
7008dd82ebeSEdgardo Hames {
7018aac4d44SDevendra Naga 	u16 status = failed ?
7028aac4d44SDevendra Naga 		     WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS;
703cb3126e6SKarl Relton 
704cb3126e6SKarl Relton 	cfg80211_connect_result(wlandev->netdev, wlandev->bssid,
7058dd82ebeSEdgardo Hames 				NULL, 0, NULL, 0, status, GFP_KERNEL);
706cb3126e6SKarl Relton }
707cb3126e6SKarl Relton 
7088dd82ebeSEdgardo Hames void prism2_disconnected(wlandevice_t *wlandev)
7098dd82ebeSEdgardo Hames {
710cb3126e6SKarl Relton 	cfg80211_disconnected(wlandev->netdev, 0, NULL,
711cb3126e6SKarl Relton 		0, GFP_KERNEL);
712cb3126e6SKarl Relton }
713cb3126e6SKarl Relton 
7148dd82ebeSEdgardo Hames void prism2_roamed(wlandevice_t *wlandev)
7158dd82ebeSEdgardo Hames {
716ed9d0102SJouni Malinen 	cfg80211_roamed(wlandev->netdev, NULL, wlandev->bssid,
717cb3126e6SKarl Relton 		NULL, 0, NULL, 0, GFP_KERNEL);
718cb3126e6SKarl Relton }
719cb3126e6SKarl Relton 
720cb3126e6SKarl Relton 
721cb3126e6SKarl Relton /* Structures for declaring wiphy interface */
722cb3126e6SKarl Relton static const struct cfg80211_ops prism2_usb_cfg_ops = {
723cb3126e6SKarl Relton 	.change_virtual_intf = prism2_change_virtual_intf,
724cb3126e6SKarl Relton 	.add_key = prism2_add_key,
725cb3126e6SKarl Relton 	.get_key = prism2_get_key,
726cb3126e6SKarl Relton 	.del_key = prism2_del_key,
727cb3126e6SKarl Relton 	.set_default_key = prism2_set_default_key,
728cb3126e6SKarl Relton 	.get_station = prism2_get_station,
729cb3126e6SKarl Relton 	.scan = prism2_scan,
730cb3126e6SKarl Relton 	.set_wiphy_params = prism2_set_wiphy_params,
731cb3126e6SKarl Relton 	.connect = prism2_connect,
732cb3126e6SKarl Relton 	.disconnect = prism2_disconnect,
733cb3126e6SKarl Relton 	.join_ibss = prism2_join_ibss,
734cb3126e6SKarl Relton 	.leave_ibss = prism2_leave_ibss,
735cb3126e6SKarl Relton 	.set_tx_power = prism2_set_tx_power,
736cb3126e6SKarl Relton 	.get_tx_power = prism2_get_tx_power,
737cb3126e6SKarl Relton };
738cb3126e6SKarl Relton 
739cb3126e6SKarl Relton 
740cb3126e6SKarl Relton /* Functions to create/free wiphy interface */
741cb3126e6SKarl Relton struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev)
742cb3126e6SKarl Relton {
743cb3126e6SKarl Relton 	struct wiphy *wiphy;
744cb3126e6SKarl Relton 	struct prism2_wiphy_private *priv;
7458aac4d44SDevendra Naga 
7468aac4d44SDevendra Naga 	wiphy = wiphy_new(&prism2_usb_cfg_ops, sizeof(*priv));
747cb3126e6SKarl Relton 	if (!wiphy)
748cb3126e6SKarl Relton 		return NULL;
749cb3126e6SKarl Relton 
750cb3126e6SKarl Relton 	priv = wiphy_priv(wiphy);
751cb3126e6SKarl Relton 	priv->wlandev = wlandev;
752cb3126e6SKarl Relton 	memcpy(priv->channels, prism2_channels, sizeof(prism2_channels));
753cb3126e6SKarl Relton 	memcpy(priv->rates, prism2_rates, sizeof(prism2_rates));
754cb3126e6SKarl Relton 	priv->band.channels = priv->channels;
755cb3126e6SKarl Relton 	priv->band.n_channels = ARRAY_SIZE(prism2_channels);
756cb3126e6SKarl Relton 	priv->band.bitrates = priv->rates;
757cb3126e6SKarl Relton 	priv->band.n_bitrates = ARRAY_SIZE(prism2_rates);
758aff3ea4eSKarl Relton 	priv->band.band = IEEE80211_BAND_2GHZ;
759aff3ea4eSKarl Relton 	priv->band.ht_cap.ht_supported = false;
760cb3126e6SKarl Relton 	wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
761cb3126e6SKarl Relton 
762cb3126e6SKarl Relton 	set_wiphy_dev(wiphy, dev);
763cb3126e6SKarl Relton 	wiphy->privid = prism2_wiphy_privid;
764cb3126e6SKarl Relton 	wiphy->max_scan_ssids = 1;
7658dd82ebeSEdgardo Hames 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
7668dd82ebeSEdgardo Hames 				 | BIT(NL80211_IFTYPE_ADHOC);
767cb3126e6SKarl Relton 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
768cb3126e6SKarl Relton 	wiphy->n_cipher_suites = PRISM2_NUM_CIPHER_SUITES;
769cb3126e6SKarl Relton 	wiphy->cipher_suites = prism2_cipher_suites;
770cb3126e6SKarl Relton 
771cb3126e6SKarl Relton 	if (wiphy_register(wiphy) < 0)
772cb3126e6SKarl Relton 		return NULL;
773cb3126e6SKarl Relton 
774cb3126e6SKarl Relton 	return wiphy;
775cb3126e6SKarl Relton }
776cb3126e6SKarl Relton 
777cb3126e6SKarl Relton 
778cb3126e6SKarl Relton void wlan_free_wiphy(struct wiphy *wiphy)
779cb3126e6SKarl Relton {
780cb3126e6SKarl Relton 	wiphy_unregister(wiphy);
781cb3126e6SKarl Relton 	wiphy_free(wiphy);
782cb3126e6SKarl Relton }
783