]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/staging/rtl8723au/core/rtw_p2p.c
81eebe5b74d9166c4f1b70b520b16313cc8d5b1e
[mirror_ubuntu-artful-kernel.git] / drivers / staging / rtl8723au / core / rtw_p2p.c
1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15 #define _RTW_P2P_C_
16
17 #include <drv_types.h>
18 #include <rtw_p2p.h>
19 #include <rtl8723a_cmd.h>
20 #include <wifi.h>
21
22 #ifdef CONFIG_8723AU_P2P
23
24 static int rtw_p2p_is_channel_list_ok(u8 desired_ch, u8* ch_list, u8 ch_cnt)
25 {
26 int found = 0, i = 0;
27
28 for (i = 0; i < ch_cnt; i++)
29 {
30 if (ch_list[ i ] == desired_ch)
31 {
32 found = 1;
33 break;
34 }
35 }
36 return found;
37 }
38
39 static int is_any_client_associated(struct rtw_adapter *padapter)
40 {
41 return padapter->stapriv.asoc_list_cnt ? true : false;
42 }
43
44 static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
45 {
46 struct list_head *phead, *plist;
47 u32 len = 0;
48 u16 attr_len = 0;
49 u8 tmplen, *pdata_attr, *pstart, *pcur;
50 struct sta_info *psta;
51 struct rtw_adapter *padapter = pwdinfo->padapter;
52 struct sta_priv *pstapriv = &padapter->stapriv;
53
54 DBG_8723A("%s\n", __func__);
55
56 pdata_attr = kzalloc(MAX_P2P_IE_LEN, GFP_ATOMIC);
57
58 pstart = pdata_attr;
59 pcur = pdata_attr;
60
61 spin_lock_bh(&pstapriv->asoc_list_lock);
62 phead = &pstapriv->asoc_list;
63
64 list_for_each(plist, phead) {
65 psta = container_of(plist, struct sta_info, asoc_list);
66
67 if (psta->is_p2p_device)
68 {
69 tmplen = 0;
70
71 pcur++;
72
73 /* P2P device address */
74 memcpy(pcur, psta->dev_addr, ETH_ALEN);
75 pcur += ETH_ALEN;
76
77 /* P2P interface address */
78 memcpy(pcur, psta->hwaddr, ETH_ALEN);
79 pcur += ETH_ALEN;
80
81 *pcur = psta->dev_cap;
82 pcur++;
83
84 /* u16*)(pcur) = cpu_to_be16(psta->config_methods); */
85 put_unaligned_be16(psta->config_methods, pcur);
86 pcur += 2;
87
88 memcpy(pcur, psta->primary_dev_type, 8);
89 pcur += 8;
90
91 *pcur = psta->num_of_secdev_type;
92 pcur++;
93
94 memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type*8);
95 pcur += psta->num_of_secdev_type*8;
96
97 if (psta->dev_name_len>0)
98 {
99 /* u16*)(pcur) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
100 put_unaligned_be16(WPS_ATTR_DEVICE_NAME, pcur);
101 pcur += 2;
102
103 /* u16*)(pcur) = cpu_to_be16(psta->dev_name_len); */
104 put_unaligned_be16(psta->dev_name_len, pcur);
105 pcur += 2;
106
107 memcpy(pcur, psta->dev_name, psta->dev_name_len);
108 pcur += psta->dev_name_len;
109 }
110
111 tmplen = (u8)(pcur-pstart);
112
113 *pstart = (tmplen-1);
114
115 attr_len += tmplen;
116
117 /* pstart += tmplen; */
118 pstart = pcur;
119
120 }
121
122 }
123 spin_unlock_bh(&pstapriv->asoc_list_lock);
124
125 if (attr_len>0)
126 {
127 len = rtw_set_p2p_attr_content23a(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);
128 }
129
130 kfree(pdata_attr);
131
132 return len;
133 }
134
135 static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)
136 {
137 struct xmit_frame *pmgntframe;
138 struct pkt_attrib *pattrib;
139 unsigned char *pframe;
140 struct ieee80211_hdr *pwlanhdr;
141 unsigned short *fctrl;
142 struct rtw_adapter *padapter = pwdinfo->padapter;
143 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
144 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
145 unsigned char category = WLAN_CATEGORY_VENDOR_SPECIFIC;/* P2P action frame */
146 u32 p2poui = cpu_to_be32(P2POUI);
147 u8 oui_subtype = P2P_GO_DISC_REQUEST;
148 u8 dialogToken = 0;
149
150 DBG_8723A("[%s]\n", __func__);
151
152 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
153 {
154 return;
155 }
156
157 /* update attribute */
158 pattrib = &pmgntframe->attrib;
159 update_mgntframe_attrib23a(padapter, pattrib);
160
161 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
162
163 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
164 pwlanhdr = (struct ieee80211_hdr *)pframe;
165
166 fctrl = &pwlanhdr->frame_control;
167 *fctrl = 0;
168
169 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
170 memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
171 memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
172
173 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
174 pmlmeext->mgnt_seq++;
175 SetFrameSubType(pframe, WIFI_ACTION);
176
177 pframe += sizeof(struct ieee80211_hdr_3addr);
178 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
179
180 /* Build P2P action frame header */
181 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
182 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
183 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
184 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
185
186 /* there is no IE in this P2P action frame */
187
188 pattrib->last_txcmdsz = pattrib->pktlen;
189
190 dump_mgntframe23a(padapter, pmgntframe);
191 }
192
193 static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
194 {
195 struct xmit_frame *pmgntframe;
196 struct pkt_attrib *pattrib;
197 unsigned char *pframe;
198 struct ieee80211_hdr *pwlanhdr;
199 unsigned short *fctrl;
200 struct rtw_adapter *padapter = pwdinfo->padapter;
201 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
202 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
203 unsigned char category = WLAN_CATEGORY_PUBLIC;
204 u8 action = P2P_PUB_ACTION_ACTION;
205 u32 p2poui = cpu_to_be32(P2POUI);
206 u8 oui_subtype = P2P_DEVDISC_RESP;
207 u8 p2pie[8] = { 0x00 };
208 u32 p2pielen = 0;
209
210 DBG_8723A("[%s]\n", __func__);
211
212 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
213 {
214 return;
215 }
216
217 /* update attribute */
218 pattrib = &pmgntframe->attrib;
219 update_mgntframe_attrib23a(padapter, pattrib);
220
221 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
222
223 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
224 pwlanhdr = (struct ieee80211_hdr *)pframe;
225
226 fctrl = &pwlanhdr->frame_control;
227 *fctrl = 0;
228
229 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
230 memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);
231 memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);
232
233 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
234 pmlmeext->mgnt_seq++;
235 SetFrameSubType(pframe, WIFI_ACTION);
236
237 pframe += sizeof(struct ieee80211_hdr_3addr);
238 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
239
240 /* Build P2P public action frame header */
241 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
242 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
243 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
244 &pattrib->pktlen);
245 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
246 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
247
248 /* Build P2P IE */
249 /* P2P OUI */
250 p2pielen = 0;
251 p2pie[ p2pielen++ ] = 0x50;
252 p2pie[ p2pielen++ ] = 0x6F;
253 p2pie[ p2pielen++ ] = 0x9A;
254 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
255
256 /* P2P_ATTR_STATUS */
257 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
258
259 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
260
261 pattrib->last_txcmdsz = pattrib->pktlen;
262
263 dump_mgntframe23a(padapter, pmgntframe);
264 }
265
266 static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8* raddr, u8* frame_body, u16 config_method)
267 {
268 struct rtw_adapter *padapter = pwdinfo->padapter;
269 unsigned char category = WLAN_CATEGORY_PUBLIC;
270 u8 action = P2P_PUB_ACTION_ACTION;
271 u8 dialogToken = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */
272 u32 p2poui = cpu_to_be32(P2POUI);
273 u8 oui_subtype = P2P_PROVISION_DISC_RESP;
274 u8 wpsie[ 100 ] = { 0x00 };
275 u8 wpsielen = 0;
276 #ifdef CONFIG_8723AU_P2P
277 u32 wfdielen = 0;
278 #endif /* CONFIG_8723AU_P2P */
279
280 struct xmit_frame *pmgntframe;
281 struct pkt_attrib *pattrib;
282 unsigned char *pframe;
283 struct ieee80211_hdr *pwlanhdr;
284 unsigned short *fctrl;
285 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
286 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
287
288 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
289 return;
290
291 /* update attribute */
292 pattrib = &pmgntframe->attrib;
293 update_mgntframe_attrib23a(padapter, pattrib);
294
295 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
296
297 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
298 pwlanhdr = (struct ieee80211_hdr *)pframe;
299
300 fctrl = &pwlanhdr->frame_control;
301 *fctrl = 0;
302
303 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
304 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
305 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
306
307 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
308 pmlmeext->mgnt_seq++;
309 SetFrameSubType(pframe, WIFI_ACTION);
310
311 pframe += sizeof(struct ieee80211_hdr_3addr);
312 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
313
314 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
315 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
316 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
317 &pattrib->pktlen);
318 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
319 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
320
321 wpsielen = 0;
322 /* WPS OUI */
323 /* u32*) (wpsie) = cpu_to_be32(WPSOUI); */
324 put_unaligned_be32(WPSOUI, wpsie);
325 wpsielen += 4;
326
327 /* Config Method */
328 /* Type: */
329 /* u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD); */
330 put_unaligned_be16(WPS_ATTR_CONF_METHOD, wpsie + wpsielen);
331 wpsielen += 2;
332
333 /* Length: */
334 /* u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002); */
335 put_unaligned_be16(0x0002, wpsie + wpsielen);
336 wpsielen += 2;
337
338 /* Value: */
339 /* u16*) (wpsie + wpsielen) = cpu_to_be16(config_method); */
340 put_unaligned_be16(config_method, wpsie + wpsielen);
341 wpsielen += 2;
342
343 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
344
345 #ifdef CONFIG_8723AU_P2P
346 wfdielen = build_provdisc_resp_wfd_ie(pwdinfo, pframe);
347 pframe += wfdielen;
348 pattrib->pktlen += wfdielen;
349 #endif /* CONFIG_8723AU_P2P */
350
351 pattrib->last_txcmdsz = pattrib->pktlen;
352
353 dump_mgntframe23a(padapter, pmgntframe);
354
355 return;
356 }
357
358 static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
359 {
360 struct xmit_frame *pmgntframe;
361 struct pkt_attrib *pattrib;
362 unsigned char *pframe;
363 struct ieee80211_hdr *pwlanhdr;
364 unsigned short *fctrl;
365 struct rtw_adapter *padapter = pwdinfo->padapter;
366 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
367 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
368 unsigned char category = WLAN_CATEGORY_VENDOR_SPECIFIC;/* P2P action frame */
369 u32 p2poui = cpu_to_be32(P2POUI);
370 u8 oui_subtype = P2P_PRESENCE_RESPONSE;
371 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
372 u8 noa_attr_content[32] = { 0x00 };
373 u32 p2pielen = 0;
374
375 DBG_8723A("[%s]\n", __func__);
376
377 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
378 {
379 return;
380 }
381
382 /* update attribute */
383 pattrib = &pmgntframe->attrib;
384 update_mgntframe_attrib23a(padapter, pattrib);
385
386 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
387
388 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
389 pwlanhdr = (struct ieee80211_hdr *)pframe;
390
391 fctrl = &pwlanhdr->frame_control;
392 *fctrl = 0;
393
394 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
395 memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
396 memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
397
398 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
399 pmlmeext->mgnt_seq++;
400 SetFrameSubType(pframe, WIFI_ACTION);
401
402 pframe += sizeof(struct ieee80211_hdr_3addr);
403 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
404
405 /* Build P2P action frame header */
406 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
407 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
408 &pattrib->pktlen);
409 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
410 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
411
412 /* Add P2P IE header */
413 /* P2P OUI */
414 p2pielen = 0;
415 p2pie[ p2pielen++ ] = 0x50;
416 p2pie[ p2pielen++ ] = 0x6F;
417 p2pie[ p2pielen++ ] = 0x9A;
418 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
419
420 /* Add Status attribute in P2P IE */
421 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
422
423 /* Add NoA attribute in P2P IE */
424 noa_attr_content[0] = 0x1;/* index */
425 noa_attr_content[1] = 0x0;/* CTWindow and OppPS Parameters */
426
427 /* todo: Notice of Absence Descriptor(s) */
428
429 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);
430
431 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie,
432 &pattrib->pktlen);
433
434 pattrib->last_txcmdsz = pattrib->pktlen;
435
436 dump_mgntframe23a(padapter, pmgntframe);
437 }
438
439 u32 build_beacon_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
440 {
441 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
442 u16 capability = 0;
443 u32 len = 0, p2pielen = 0;
444
445 /* P2P OUI */
446 p2pielen = 0;
447 p2pie[ p2pielen++ ] = 0x50;
448 p2pie[ p2pielen++ ] = 0x6F;
449 p2pie[ p2pielen++ ] = 0x9A;
450 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
451
452 /* According to the P2P Specification, the beacon frame should contain 3 P2P attributes */
453 /* 1. P2P Capability */
454 /* 2. P2P Device ID */
455 /* 3. Notice of Absence (NOA) */
456
457 /* P2P Capability ATTR */
458 /* Type: */
459 /* Length: */
460 /* Value: */
461 /* Device Capability Bitmap, 1 byte */
462 /* Be able to participate in additional P2P Groups and */
463 /* support the P2P Invitation Procedure */
464 /* Group Capability Bitmap, 1 byte */
465 capability = P2P_DEVCAP_INVITATION_PROC|P2P_DEVCAP_CLIENT_DISCOVERABILITY;
466 capability |= ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);
467 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
468 capability |= (P2P_GRPCAP_GROUP_FORMATION<<8);
469
470 capability = cpu_to_le16(capability);
471
472 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8*)&capability);
473
474 /* P2P Device ID ATTR */
475 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);
476
477 /* Notice of Absence ATTR */
478 /* Type: */
479 /* Length: */
480 /* Value: */
481
482 /* go_add_noa_attr(pwdinfo); */
483
484 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
485
486 return len;
487 }
488
489 #ifdef CONFIG_8723AU_P2P
490 u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
491 {
492 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
493 u32 len = 0, wfdielen = 0;
494 struct rtw_adapter *padapter = pwdinfo->padapter;
495 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
496 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
497
498 /* WFD OUI */
499 wfdielen = 0;
500 wfdie[ wfdielen++ ] = 0x50;
501 wfdie[ wfdielen++ ] = 0x6F;
502 wfdie[ wfdielen++ ] = 0x9A;
503 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
504
505 /* Commented by Albert 20110812 */
506 /* According to the WFD Specification, the beacon frame should contain 4 WFD attributes */
507 /* 1. WFD Device Information */
508 /* 2. Associated BSSID */
509 /* 3. Coupled Sink Information */
510
511 /* WFD Device Information ATTR */
512 /* Type: */
513 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
514
515 /* Length: */
516 /* Note: In the WFD specification, the size of length field is 2. */
517 put_unaligned_be16(0x0006, wfdie + wfdielen);
518 wfdielen += 2;
519
520 /* Value1: */
521 /* WFD device information */
522
523 if (P2P_ROLE_GO == pwdinfo->role)
524 {
525 if (is_any_client_associated(pwdinfo->padapter))
526 {
527 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) */
528 put_unaligned_be16(pwfd_info->wfd_device_type |
529 WFD_DEVINFO_WSD, wfdie + wfdielen);
530 }
531 else
532 {
533 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
534 put_unaligned_be16(pwfd_info->wfd_device_type |
535 WFD_DEVINFO_SESSION_AVAIL |
536 WFD_DEVINFO_WSD, wfdie + wfdielen);
537 }
538
539 }
540 else
541 {
542 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
543 put_unaligned_be16(pwfd_info->wfd_device_type |
544 WFD_DEVINFO_SESSION_AVAIL |
545 WFD_DEVINFO_WSD, wfdie + wfdielen);
546 }
547
548 wfdielen += 2;
549
550 /* Value2: */
551 /* Session Management Control Port */
552 /* Default TCP port for RTSP messages is 554 */
553 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
554 wfdielen += 2;
555
556 /* Value3: */
557 /* WFD Device Maximum Throughput */
558 /* 300Mbps is the maximum throughput */
559 put_unaligned_be16(300, wfdie + wfdielen);
560 wfdielen += 2;
561
562 /* Associated BSSID ATTR */
563 /* Type: */
564 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
565
566 /* Length: */
567 /* Note: In the WFD specification, the size of length field is 2. */
568 put_unaligned_be16(0x0006, wfdie + wfdielen);
569 wfdielen += 2;
570
571 /* Value: */
572 /* Associated BSSID */
573 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
574 {
575 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
576 }
577 else
578 {
579 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
580 }
581
582 wfdielen += ETH_ALEN;
583
584 /* Coupled Sink Information ATTR */
585 /* Type: */
586 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
587
588 /* Length: */
589 /* Note: In the WFD specification, the size of length field is 2. */
590 put_unaligned_be16(0x0007, wfdie + wfdielen);
591 wfdielen += 2;
592
593 /* Value: */
594 /* Coupled Sink Status bitmap */
595 /* Not coupled/available for Coupling */
596 wfdie[ wfdielen++ ] = 0;
597 /* MAC Addr. */
598 wfdie[ wfdielen++ ] = 0;
599 wfdie[ wfdielen++ ] = 0;
600 wfdie[ wfdielen++ ] = 0;
601 wfdie[ wfdielen++ ] = 0;
602 wfdie[ wfdielen++ ] = 0;
603 wfdie[ wfdielen++ ] = 0;
604
605 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
606
607 return len;
608 }
609
610 u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
611 {
612 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
613 u32 len = 0, wfdielen = 0;
614 struct rtw_adapter *padapter = pwdinfo->padapter;
615 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
616 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
617
618 /* WFD OUI */
619 wfdielen = 0;
620 wfdie[ wfdielen++ ] = 0x50;
621 wfdie[ wfdielen++ ] = 0x6F;
622 wfdie[ wfdielen++ ] = 0x9A;
623 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
624
625 /* Commented by Albert 20110812 */
626 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
627 /* 1. WFD Device Information */
628 /* 2. Associated BSSID */
629 /* 3. Coupled Sink Information */
630
631 /* WFD Device Information ATTR */
632 /* Type: */
633 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
634
635 /* Length: */
636 /* Note: In the WFD specification, the size of length field is 2. */
637 put_unaligned_be16(0x0006, wfdie + wfdielen);
638 wfdielen += 2;
639
640 /* Value1: */
641 /* WFD device information */
642
643 if (1 == pwdinfo->wfd_tdls_enable)
644 {
645 /* WFD primary sink + available for WFD session + WiFi TDLS mode + WSC (WFD Service Discovery) */
646 put_unaligned_be16(pwfd_info->wfd_device_type |
647 WFD_DEVINFO_SESSION_AVAIL |
648 WFD_DEVINFO_WSD |
649 WFD_DEVINFO_PC_TDLS, wfdie + wfdielen);
650 }
651 else
652 {
653 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSC (WFD Service Discovery) */
654 put_unaligned_be16(pwfd_info->wfd_device_type |
655 WFD_DEVINFO_SESSION_AVAIL |
656 WFD_DEVINFO_WSD, wfdie + wfdielen);
657 }
658
659 wfdielen += 2;
660
661 /* Value2: */
662 /* Session Management Control Port */
663 /* Default TCP port for RTSP messages is 554 */
664 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
665 wfdielen += 2;
666
667 /* Value3: */
668 /* WFD Device Maximum Throughput */
669 /* 300Mbps is the maximum throughput */
670 put_unaligned_be16(300, wfdie + wfdielen);
671 wfdielen += 2;
672
673 /* Associated BSSID ATTR */
674 /* Type: */
675 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
676
677 /* Length: */
678 /* Note: In the WFD specification, the size of length field is 2. */
679 put_unaligned_be16(0x0006, wfdie + wfdielen);
680 wfdielen += 2;
681
682 /* Value: */
683 /* Associated BSSID */
684 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
685 {
686 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
687 }
688 else
689 {
690 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
691 }
692
693 wfdielen += ETH_ALEN;
694
695 /* Coupled Sink Information ATTR */
696 /* Type: */
697 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
698
699 /* Length: */
700 /* Note: In the WFD specification, the size of length field is 2. */
701 put_unaligned_be16(0x0007, wfdie + wfdielen);
702 wfdielen += 2;
703
704 /* Value: */
705 /* Coupled Sink Status bitmap */
706 /* Not coupled/available for Coupling */
707 wfdie[ wfdielen++ ] = 0;
708 /* MAC Addr. */
709 wfdie[ wfdielen++ ] = 0;
710 wfdie[ wfdielen++ ] = 0;
711 wfdie[ wfdielen++ ] = 0;
712 wfdie[ wfdielen++ ] = 0;
713 wfdie[ wfdielen++ ] = 0;
714 wfdie[ wfdielen++ ] = 0;
715
716 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
717
718 return len;
719 }
720
721 u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 tunneled)
722 {
723 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
724 u32 len = 0, wfdielen = 0;
725 struct rtw_adapter *padapter = pwdinfo->padapter;
726 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
727 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
728
729 /* WFD OUI */
730 wfdielen = 0;
731 wfdie[ wfdielen++ ] = 0x50;
732 wfdie[ wfdielen++ ] = 0x6F;
733 wfdie[ wfdielen++ ] = 0x9A;
734 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
735
736 /* Commented by Albert 20110812 */
737 /* According to the WFD Specification, the probe response frame should contain 4 WFD attributes */
738 /* 1. WFD Device Information */
739 /* 2. Associated BSSID */
740 /* 3. Coupled Sink Information */
741 /* 4. WFD Session Information */
742
743 /* WFD Device Information ATTR */
744 /* Type: */
745 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
746
747 /* Length: */
748 /* Note: In the WFD specification, the size of length field is 2. */
749 put_unaligned_be16(0x0006, wfdie + wfdielen);
750 wfdielen += 2;
751
752 /* Value1: */
753 /* WFD device information */
754 /* WFD primary sink + available for WFD session + WiFi Direct mode */
755
756 if (true == pwdinfo->session_available)
757 {
758 if (P2P_ROLE_GO == pwdinfo->role)
759 {
760 if (is_any_client_associated(pwdinfo->padapter))
761 {
762 if (pwdinfo->wfd_tdls_enable)
763 {
764 /* TDLS mode + WSD (WFD Service Discovery) */
765 put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
766 }
767 else
768 {
769 /* WiFi Direct mode + WSD (WFD Service Discovery) */
770 put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
771 }
772 }
773 else
774 {
775 if (pwdinfo->wfd_tdls_enable)
776 {
777 /* available for WFD session + TDLS mode + WSD (WFD Service Discovery) */
778 put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
779 }
780 else
781 {
782 /* available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
783 put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
784 }
785 }
786 }
787 else
788 {
789 if (pwdinfo->wfd_tdls_enable)
790 {
791 /* available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
792 put_unaligned_be16(pwfd_info->wfd_device_type |
793 WFD_DEVINFO_SESSION_AVAIL |
794 WFD_DEVINFO_WSD |
795 WFD_DEVINFO_PC_TDLS |
796 WFD_DEVINFO_HDCP_SUPPORT,
797 wfdie + wfdielen);
798 }
799 else
800 {
801
802 /* available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
803 put_unaligned_be16(pwfd_info->wfd_device_type |
804 WFD_DEVINFO_SESSION_AVAIL |
805 WFD_DEVINFO_WSD |
806 WFD_DEVINFO_HDCP_SUPPORT,
807 wfdie + wfdielen);
808 }
809 }
810 }
811 else
812 {
813 if (pwdinfo->wfd_tdls_enable)
814 {
815 put_unaligned_be16(pwfd_info->wfd_device_type |
816 WFD_DEVINFO_WSD |
817 WFD_DEVINFO_PC_TDLS |
818 WFD_DEVINFO_HDCP_SUPPORT,
819 wfdie + wfdielen);
820 }
821 else
822 {
823 put_unaligned_be16(pwfd_info->wfd_device_type |
824 WFD_DEVINFO_WSD |
825 WFD_DEVINFO_HDCP_SUPPORT,
826 wfdie + wfdielen);
827 }
828
829 }
830
831 wfdielen += 2;
832
833 /* Value2: */
834 /* Session Management Control Port */
835 /* Default TCP port for RTSP messages is 554 */
836 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
837 wfdielen += 2;
838
839 /* Value3: */
840 /* WFD Device Maximum Throughput */
841 /* 300Mbps is the maximum throughput */
842 put_unaligned_be16(300, wfdie + wfdielen);
843 wfdielen += 2;
844
845 /* Associated BSSID ATTR */
846 /* Type: */
847 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
848
849 /* Length: */
850 /* Note: In the WFD specification, the size of length field is 2. */
851 put_unaligned_be16(0x0006, wfdie + wfdielen);
852 wfdielen += 2;
853
854 /* Value: */
855 /* Associated BSSID */
856 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
857 {
858 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
859 }
860 else
861 {
862 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
863 }
864
865 wfdielen += ETH_ALEN;
866
867 /* Coupled Sink Information ATTR */
868 /* Type: */
869 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
870
871 /* Length: */
872 /* Note: In the WFD specification, the size of length field is 2. */
873 put_unaligned_be16(0x0007, wfdie + wfdielen);
874 wfdielen += 2;
875
876 /* Value: */
877 /* Coupled Sink Status bitmap */
878 /* Not coupled/available for Coupling */
879 wfdie[ wfdielen++ ] = 0;
880 /* MAC Addr. */
881 wfdie[ wfdielen++ ] = 0;
882 wfdie[ wfdielen++ ] = 0;
883 wfdie[ wfdielen++ ] = 0;
884 wfdie[ wfdielen++ ] = 0;
885 wfdie[ wfdielen++ ] = 0;
886 wfdie[ wfdielen++ ] = 0;
887
888 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
889 {
890 /* WFD Session Information ATTR */
891 /* Type: */
892 wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
893
894 /* Length: */
895 /* Note: In the WFD specification, the size of length field is 2. */
896 put_unaligned_be16(0x0000, wfdie + wfdielen);
897 wfdielen += 2;
898
899 /* Todo: to add the list of WFD device info descriptor in WFD group. */
900
901 }
902
903 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
904
905 return len;
906 }
907
908 u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
909 {
910 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
911 u32 len = 0, wfdielen = 0;
912 struct rtw_adapter *padapter = NULL;
913 struct mlme_priv *pmlmepriv = NULL;
914 struct wifi_display_info *pwfd_info = NULL;
915
916 /* WFD OUI */
917 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
918 {
919 return 0;
920 }
921
922 padapter = pwdinfo->padapter;
923 pmlmepriv = &padapter->mlmepriv;
924 pwfd_info = padapter->wdinfo.wfd_info;
925
926 wfdielen = 0;
927 wfdie[ wfdielen++ ] = 0x50;
928 wfdie[ wfdielen++ ] = 0x6F;
929 wfdie[ wfdielen++ ] = 0x9A;
930 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
931
932 /* Commented by Albert 20110812 */
933 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
934 /* 1. WFD Device Information */
935 /* 2. Associated BSSID */
936 /* 3. Coupled Sink Information */
937
938 /* WFD Device Information ATTR */
939 /* Type: */
940 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
941
942 /* Length: */
943 /* Note: In the WFD specification, the size of length field is 2. */
944 put_unaligned_be16(0x0006, wfdie + wfdielen);
945 wfdielen += 2;
946
947 /* Value1: */
948 /* WFD device information */
949 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
950 put_unaligned_be16(pwfd_info->wfd_device_type |
951 WFD_DEVINFO_SESSION_AVAIL |
952 WFD_DEVINFO_WSD, wfdie + wfdielen);
953 wfdielen += 2;
954
955 /* Value2: */
956 /* Session Management Control Port */
957 /* Default TCP port for RTSP messages is 554 */
958 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
959 wfdielen += 2;
960
961 /* Value3: */
962 /* WFD Device Maximum Throughput */
963 /* 300Mbps is the maximum throughput */
964 put_unaligned_be16(300, wfdie + wfdielen);
965 wfdielen += 2;
966
967 /* Associated BSSID ATTR */
968 /* Type: */
969 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
970
971 /* Length: */
972 /* Note: In the WFD specification, the size of length field is 2. */
973 put_unaligned_be16(0x0006, wfdie + wfdielen);
974 wfdielen += 2;
975
976 /* Value: */
977 /* Associated BSSID */
978 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
979 {
980 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
981 }
982 else
983 {
984 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
985 }
986
987 wfdielen += ETH_ALEN;
988
989 /* Coupled Sink Information ATTR */
990 /* Type: */
991 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
992
993 /* Length: */
994 /* Note: In the WFD specification, the size of length field is 2. */
995 put_unaligned_be16(0x0007, wfdie + wfdielen);
996 wfdielen += 2;
997
998 /* Value: */
999 /* Coupled Sink Status bitmap */
1000 /* Not coupled/available for Coupling */
1001 wfdie[ wfdielen++ ] = 0;
1002 /* MAC Addr. */
1003 wfdie[ wfdielen++ ] = 0;
1004 wfdie[ wfdielen++ ] = 0;
1005 wfdie[ wfdielen++ ] = 0;
1006 wfdie[ wfdielen++ ] = 0;
1007 wfdie[ wfdielen++ ] = 0;
1008 wfdie[ wfdielen++ ] = 0;
1009
1010 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1011
1012 return len;
1013 }
1014
1015 u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1016 {
1017 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1018 u32 len = 0, wfdielen = 0;
1019 struct rtw_adapter *padapter = pwdinfo->padapter;
1020 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1021 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1022
1023 /* WFD OUI */
1024 wfdielen = 0;
1025 wfdie[ wfdielen++ ] = 0x50;
1026 wfdie[ wfdielen++ ] = 0x6F;
1027 wfdie[ wfdielen++ ] = 0x9A;
1028 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1029
1030 /* Commented by Albert 20110812 */
1031 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
1032 /* 1. WFD Device Information */
1033 /* 2. Associated BSSID */
1034 /* 3. Coupled Sink Information */
1035
1036 /* WFD Device Information ATTR */
1037 /* Type: */
1038 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1039
1040 /* Length: */
1041 /* Note: In the WFD specification, the size of length field is 2. */
1042 put_unaligned_be16(0x0006, wfdie + wfdielen);
1043 wfdielen += 2;
1044
1045 /* Value1: */
1046 /* WFD device information */
1047 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1048 put_unaligned_be16(pwfd_info->wfd_device_type |
1049 WFD_DEVINFO_SESSION_AVAIL |
1050 WFD_DEVINFO_WSD, wfdie + wfdielen);
1051 wfdielen += 2;
1052
1053 /* Value2: */
1054 /* Session Management Control Port */
1055 /* Default TCP port for RTSP messages is 554 */
1056 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1057 wfdielen += 2;
1058
1059 /* Value3: */
1060 /* WFD Device Maximum Throughput */
1061 /* 300Mbps is the maximum throughput */
1062 put_unaligned_be16(300, wfdie + wfdielen);
1063 wfdielen += 2;
1064
1065 /* Associated BSSID ATTR */
1066 /* Type: */
1067 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1068
1069 /* Length: */
1070 /* Note: In the WFD specification, the size of length field is 2. */
1071 put_unaligned_be16(0x0006, wfdie + wfdielen);
1072 wfdielen += 2;
1073
1074 /* Value: */
1075 /* Associated BSSID */
1076 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1077 {
1078 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1079 }
1080 else
1081 {
1082 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1083 }
1084
1085 wfdielen += ETH_ALEN;
1086
1087 /* Coupled Sink Information ATTR */
1088 /* Type: */
1089 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1090
1091 /* Length: */
1092 /* Note: In the WFD specification, the size of length field is 2. */
1093 put_unaligned_be16(0x0007, wfdie + wfdielen);
1094 wfdielen += 2;
1095
1096 /* Value: */
1097 /* Coupled Sink Status bitmap */
1098 /* Not coupled/available for Coupling */
1099 wfdie[ wfdielen++ ] = 0;
1100 /* MAC Addr. */
1101 wfdie[ wfdielen++ ] = 0;
1102 wfdie[ wfdielen++ ] = 0;
1103 wfdie[ wfdielen++ ] = 0;
1104 wfdie[ wfdielen++ ] = 0;
1105 wfdie[ wfdielen++ ] = 0;
1106 wfdie[ wfdielen++ ] = 0;
1107
1108 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1109
1110 return len;
1111 }
1112
1113 u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1114 {
1115 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1116 u32 len = 0, wfdielen = 0;
1117 struct rtw_adapter *padapter = pwdinfo->padapter;
1118 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1119 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1120
1121 /* WFD OUI */
1122 wfdielen = 0;
1123 wfdie[ wfdielen++ ] = 0x50;
1124 wfdie[ wfdielen++ ] = 0x6F;
1125 wfdie[ wfdielen++ ] = 0x9A;
1126 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1127
1128 /* Commented by Albert 20110825 */
1129 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1130 /* 1. WFD Device Information */
1131 /* 2. Associated BSSID (Optional) */
1132 /* 3. Local IP Adress (Optional) */
1133
1134 /* WFD Device Information ATTR */
1135 /* Type: */
1136 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1137
1138 /* Length: */
1139 /* Note: In the WFD specification, the size of length field is 2. */
1140 put_unaligned_be16(0x0006, wfdie + wfdielen);
1141 wfdielen += 2;
1142
1143 /* Value1: */
1144 /* WFD device information */
1145 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
1146 put_unaligned_be16(pwfd_info->wfd_device_type |
1147 WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL,
1148 wfdie + wfdielen);
1149 wfdielen += 2;
1150
1151 /* Value2: */
1152 /* Session Management Control Port */
1153 /* Default TCP port for RTSP messages is 554 */
1154 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1155 wfdielen += 2;
1156
1157 /* Value3: */
1158 /* WFD Device Maximum Throughput */
1159 /* 300Mbps is the maximum throughput */
1160 put_unaligned_be16(300, wfdie + wfdielen);
1161 wfdielen += 2;
1162
1163 /* Associated BSSID ATTR */
1164 /* Type: */
1165 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1166
1167 /* Length: */
1168 /* Note: In the WFD specification, the size of length field is 2. */
1169 put_unaligned_be16(0x0006, wfdie + wfdielen);
1170 wfdielen += 2;
1171
1172 /* Value: */
1173 /* Associated BSSID */
1174 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1175 {
1176 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1177 }
1178 else
1179 {
1180 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1181 }
1182
1183 wfdielen += ETH_ALEN;
1184
1185 /* Coupled Sink Information ATTR */
1186 /* Type: */
1187 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1188
1189 /* Length: */
1190 /* Note: In the WFD specification, the size of length field is 2. */
1191 put_unaligned_be16(0x0007, wfdie + wfdielen);
1192 wfdielen += 2;
1193
1194 /* Value: */
1195 /* Coupled Sink Status bitmap */
1196 /* Not coupled/available for Coupling */
1197 wfdie[ wfdielen++ ] = 0;
1198 /* MAC Addr. */
1199 wfdie[ wfdielen++ ] = 0;
1200 wfdie[ wfdielen++ ] = 0;
1201 wfdie[ wfdielen++ ] = 0;
1202 wfdie[ wfdielen++ ] = 0;
1203 wfdie[ wfdielen++ ] = 0;
1204 wfdie[ wfdielen++ ] = 0;
1205
1206 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1207
1208 return len;
1209 }
1210
1211 u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1212 {
1213 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1214 u32 len = 0, wfdielen = 0;
1215 struct rtw_adapter *padapter = pwdinfo->padapter;
1216 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1217 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1218
1219 /* WFD OUI */
1220 wfdielen = 0;
1221 wfdie[ wfdielen++ ] = 0x50;
1222 wfdie[ wfdielen++ ] = 0x6F;
1223 wfdie[ wfdielen++ ] = 0x9A;
1224 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1225
1226 /* Commented by Albert 20110825 */
1227 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1228 /* 1. WFD Device Information */
1229 /* 2. Associated BSSID (Optional) */
1230 /* 3. Local IP Adress (Optional) */
1231
1232 /* WFD Device Information ATTR */
1233 /* Type: */
1234 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1235
1236 /* Length: */
1237 /* Note: In the WFD specification, the size of length field is 2. */
1238 put_unaligned_be16(0x0006, wfdie + wfdielen);
1239 wfdielen += 2;
1240
1241 /* Value1: */
1242 /* WFD device information */
1243 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
1244 put_unaligned_be16(pwfd_info->wfd_device_type |
1245 WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL,
1246 wfdie + wfdielen);
1247 wfdielen += 2;
1248
1249 /* Value2: */
1250 /* Session Management Control Port */
1251 /* Default TCP port for RTSP messages is 554 */
1252 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1253 wfdielen += 2;
1254
1255 /* Value3: */
1256 /* WFD Device Maximum Throughput */
1257 /* 300Mbps is the maximum throughput */
1258 put_unaligned_be16(300, wfdie + wfdielen);
1259 wfdielen += 2;
1260
1261 /* Associated BSSID ATTR */
1262 /* Type: */
1263 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1264
1265 /* Length: */
1266 /* Note: In the WFD specification, the size of length field is 2. */
1267 put_unaligned_be16(0x0006, wfdie + wfdielen);
1268 wfdielen += 2;
1269
1270 /* Value: */
1271 /* Associated BSSID */
1272 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1273 {
1274 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1275 }
1276 else
1277 {
1278 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1279 }
1280
1281 wfdielen += ETH_ALEN;
1282
1283 /* Coupled Sink Information ATTR */
1284 /* Type: */
1285 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1286
1287 /* Length: */
1288 /* Note: In the WFD specification, the size of length field is 2. */
1289 put_unaligned_be16(0x0007, wfdie + wfdielen);
1290 wfdielen += 2;
1291
1292 /* Value: */
1293 /* Coupled Sink Status bitmap */
1294 /* Not coupled/available for Coupling */
1295 wfdie[ wfdielen++ ] = 0;
1296 /* MAC Addr. */
1297 wfdie[ wfdielen++ ] = 0;
1298 wfdie[ wfdielen++ ] = 0;
1299 wfdie[ wfdielen++ ] = 0;
1300 wfdie[ wfdielen++ ] = 0;
1301 wfdie[ wfdielen++ ] = 0;
1302 wfdie[ wfdielen++ ] = 0;
1303
1304 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1305
1306 return len;
1307 }
1308
1309 u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1310 {
1311 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1312 u32 len = 0, wfdielen = 0;
1313 struct rtw_adapter *padapter = pwdinfo->padapter;
1314 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1315 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1316
1317 /* WFD OUI */
1318 wfdielen = 0;
1319 wfdie[ wfdielen++ ] = 0x50;
1320 wfdie[ wfdielen++ ] = 0x6F;
1321 wfdie[ wfdielen++ ] = 0x9A;
1322 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1323
1324 /* Commented by Albert 20110825 */
1325 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1326 /* 1. WFD Device Information */
1327 /* 2. Associated BSSID (Optional) */
1328 /* 3. Local IP Adress (Optional) */
1329
1330 /* WFD Device Information ATTR */
1331 /* Type: */
1332 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1333
1334 /* Length: */
1335 /* Note: In the WFD specification, the size of length field is 2. */
1336 put_unaligned_be16(0x0006, wfdie + wfdielen);
1337 wfdielen += 2;
1338
1339 /* Value1: */
1340 /* WFD device information */
1341 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
1342 put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_WSD |
1343 WFD_DEVINFO_SESSION_AVAIL, wfdie + wfdielen);
1344 wfdielen += 2;
1345
1346 /* Value2: */
1347 /* Session Management Control Port */
1348 /* Default TCP port for RTSP messages is 554 */
1349 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1350 wfdielen += 2;
1351
1352 /* Value3: */
1353 /* WFD Device Maximum Throughput */
1354 /* 300Mbps is the maximum throughput */
1355 put_unaligned_be16(300, wfdie + wfdielen);
1356 wfdielen += 2;
1357
1358 /* Associated BSSID ATTR */
1359 /* Type: */
1360 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1361
1362 /* Length: */
1363 /* Note: In the WFD specification, the size of length field is 2. */
1364 put_unaligned_be16(0x0006, wfdie + wfdielen);
1365 wfdielen += 2;
1366
1367 /* Value: */
1368 /* Associated BSSID */
1369 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1370 {
1371 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1372 }
1373 else
1374 {
1375 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1376 }
1377
1378 wfdielen += ETH_ALEN;
1379
1380 /* Coupled Sink Information ATTR */
1381 /* Type: */
1382 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1383
1384 /* Length: */
1385 /* Note: In the WFD specification, the size of length field is 2. */
1386 put_unaligned_be16(0x0007, wfdie + wfdielen);
1387 wfdielen += 2;
1388
1389 /* Value: */
1390 /* Coupled Sink Status bitmap */
1391 /* Not coupled/available for Coupling */
1392 wfdie[ wfdielen++ ] = 0;
1393 /* MAC Addr. */
1394 wfdie[ wfdielen++ ] = 0;
1395 wfdie[ wfdielen++ ] = 0;
1396 wfdie[ wfdielen++ ] = 0;
1397 wfdie[ wfdielen++ ] = 0;
1398 wfdie[ wfdielen++ ] = 0;
1399 wfdie[ wfdielen++ ] = 0;
1400
1401 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1402
1403 return len;
1404 }
1405
1406 u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1407 {
1408 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1409 u32 len = 0, wfdielen = 0;
1410 struct rtw_adapter *padapter = pwdinfo->padapter;
1411 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1412 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1413
1414 /* WFD OUI */
1415 wfdielen = 0;
1416 wfdie[ wfdielen++ ] = 0x50;
1417 wfdie[ wfdielen++ ] = 0x6F;
1418 wfdie[ wfdielen++ ] = 0x9A;
1419 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1420
1421 /* Commented by Albert 20110825 */
1422 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1423 /* 1. WFD Device Information */
1424 /* 2. Associated BSSID (Optional) */
1425 /* 3. Local IP Adress (Optional) */
1426
1427 /* WFD Device Information ATTR */
1428 /* Type: */
1429 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1430
1431 /* Length: */
1432 /* Note: In the WFD specification, the size of length field is 2. */
1433 put_unaligned_be16(0x0006, wfdie + wfdielen);
1434 wfdielen += 2;
1435
1436 /* Value1: */
1437 /* WFD device information */
1438 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1439 put_unaligned_be16(pwfd_info->wfd_device_type |
1440 WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
1441 wfdie + wfdielen);
1442 wfdielen += 2;
1443
1444 /* Value2: */
1445 /* Session Management Control Port */
1446 /* Default TCP port for RTSP messages is 554 */
1447 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1448 wfdielen += 2;
1449
1450 /* Value3: */
1451 /* WFD Device Maximum Throughput */
1452 /* 300Mbps is the maximum throughput */
1453 put_unaligned_be16(300, wfdie + wfdielen);
1454 wfdielen += 2;
1455
1456 /* Associated BSSID ATTR */
1457 /* Type: */
1458 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1459
1460 /* Length: */
1461 /* Note: In the WFD specification, the size of length field is 2. */
1462 put_unaligned_be16(0x0006, wfdie + wfdielen);
1463 wfdielen += 2;
1464
1465 /* Value: */
1466 /* Associated BSSID */
1467 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1468 {
1469 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1470 }
1471 else
1472 {
1473 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1474 }
1475
1476 wfdielen += ETH_ALEN;
1477
1478 /* Coupled Sink Information ATTR */
1479 /* Type: */
1480 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1481
1482 /* Length: */
1483 /* Note: In the WFD specification, the size of length field is 2. */
1484 put_unaligned_be16(0x0007, wfdie + wfdielen);
1485 wfdielen += 2;
1486
1487 /* Value: */
1488 /* Coupled Sink Status bitmap */
1489 /* Not coupled/available for Coupling */
1490 wfdie[ wfdielen++ ] = 0;
1491 /* MAC Addr. */
1492 wfdie[ wfdielen++ ] = 0;
1493 wfdie[ wfdielen++ ] = 0;
1494 wfdie[ wfdielen++ ] = 0;
1495 wfdie[ wfdielen++ ] = 0;
1496 wfdie[ wfdielen++ ] = 0;
1497 wfdie[ wfdielen++ ] = 0;
1498
1499 if (P2P_ROLE_GO == pwdinfo->role)
1500 {
1501 /* WFD Session Information ATTR */
1502 /* Type: */
1503 wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
1504
1505 /* Length: */
1506 /* Note: In the WFD specification, the size of length field is 2. */
1507 put_unaligned_be16(0x0000, wfdie + wfdielen);
1508 wfdielen += 2;
1509
1510 /* Todo: to add the list of WFD device info descriptor in WFD group. */
1511
1512 }
1513
1514 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1515
1516 return len;
1517 }
1518
1519 u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1520 {
1521 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1522 u32 len = 0, wfdielen = 0;
1523 struct rtw_adapter *padapter = pwdinfo->padapter;
1524 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1525 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1526
1527 /* WFD OUI */
1528 wfdielen = 0;
1529 wfdie[ wfdielen++ ] = 0x50;
1530 wfdie[ wfdielen++ ] = 0x6F;
1531 wfdie[ wfdielen++ ] = 0x9A;
1532 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1533
1534 /* Commented by Albert 20110825 */
1535 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1536 /* 1. WFD Device Information */
1537 /* 2. Associated BSSID (Optional) */
1538 /* 3. Local IP Adress (Optional) */
1539
1540 /* WFD Device Information ATTR */
1541 /* Type: */
1542 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1543
1544 /* Length: */
1545 /* Note: In the WFD specification, the size of length field is 2. */
1546 put_unaligned_be16(0x0006, wfdie + wfdielen);
1547 wfdielen += 2;
1548
1549 /* Value1: */
1550 /* WFD device information */
1551 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1552 put_unaligned_be16(pwfd_info->wfd_device_type |
1553 WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
1554 wfdie + wfdielen);
1555 wfdielen += 2;
1556
1557 /* Value2: */
1558 /* Session Management Control Port */
1559 /* Default TCP port for RTSP messages is 554 */
1560 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1561 wfdielen += 2;
1562
1563 /* Value3: */
1564 /* WFD Device Maximum Throughput */
1565 /* 300Mbps is the maximum throughput */
1566 put_unaligned_be16(300, wfdie + wfdielen);
1567 wfdielen += 2;
1568
1569 /* Associated BSSID ATTR */
1570 /* Type: */
1571 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1572
1573 /* Length: */
1574 /* Note: In the WFD specification, the size of length field is 2. */
1575 put_unaligned_be16(0x0006, wfdie + wfdielen);
1576 wfdielen += 2;
1577
1578 /* Value: */
1579 /* Associated BSSID */
1580 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1581 {
1582 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1583 }
1584 else
1585 {
1586 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1587 }
1588
1589 wfdielen += ETH_ALEN;
1590
1591 /* Coupled Sink Information ATTR */
1592 /* Type: */
1593 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1594
1595 /* Length: */
1596 /* Note: In the WFD specification, the size of length field is 2. */
1597 put_unaligned_be16(0x0007, wfdie + wfdielen);
1598 wfdielen += 2;
1599
1600 /* Value: */
1601 /* Coupled Sink Status bitmap */
1602 /* Not coupled/available for Coupling */
1603 wfdie[ wfdielen++ ] = 0;
1604 /* MAC Addr. */
1605 wfdie[ wfdielen++ ] = 0;
1606 wfdie[ wfdielen++ ] = 0;
1607 wfdie[ wfdielen++ ] = 0;
1608 wfdie[ wfdielen++ ] = 0;
1609 wfdie[ wfdielen++ ] = 0;
1610 wfdie[ wfdielen++ ] = 0;
1611
1612 if (P2P_ROLE_GO == pwdinfo->role)
1613 {
1614 /* WFD Session Information ATTR */
1615 /* Type: */
1616 wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
1617
1618 /* Length: */
1619 /* Note: In the WFD specification, the size of length field is 2. */
1620 put_unaligned_be16(0x0000, wfdie + wfdielen);
1621 wfdielen += 2;
1622
1623 /* Todo: to add the list of WFD device info descriptor in WFD group. */
1624
1625 }
1626
1627 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1628
1629 return len;
1630 }
1631
1632 u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1633 {
1634 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1635 u32 len = 0, wfdielen = 0;
1636 struct rtw_adapter *padapter = pwdinfo->padapter;
1637 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1638 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1639
1640 /* WFD OUI */
1641 wfdielen = 0;
1642 wfdie[ wfdielen++ ] = 0x50;
1643 wfdie[ wfdielen++ ] = 0x6F;
1644 wfdie[ wfdielen++ ] = 0x9A;
1645 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1646
1647 /* Commented by Albert 20110825 */
1648 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1649 /* 1. WFD Device Information */
1650 /* 2. Associated BSSID (Optional) */
1651 /* 3. Local IP Adress (Optional) */
1652
1653 /* WFD Device Information ATTR */
1654 /* Type: */
1655 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1656
1657 /* Length: */
1658 /* Note: In the WFD specification, the size of length field is 2. */
1659 put_unaligned_be16(0x0006, wfdie + wfdielen);
1660 wfdielen += 2;
1661
1662 /* Value1: */
1663 /* WFD device information */
1664 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1665 put_unaligned_be16(pwfd_info->wfd_device_type |
1666 WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
1667 wfdie + wfdielen);
1668 wfdielen += 2;
1669
1670 /* Value2: */
1671 /* Session Management Control Port */
1672 /* Default TCP port for RTSP messages is 554 */
1673 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1674 wfdielen += 2;
1675
1676 /* Value3: */
1677 /* WFD Device Maximum Throughput */
1678 /* 300Mbps is the maximum throughput */
1679 put_unaligned_be16(300, wfdie + wfdielen);
1680 wfdielen += 2;
1681
1682 /* Associated BSSID ATTR */
1683 /* Type: */
1684 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1685
1686 /* Length: */
1687 /* Note: In the WFD specification, the size of length field is 2. */
1688 put_unaligned_be16(0x0006, wfdie + wfdielen);
1689 wfdielen += 2;
1690
1691 /* Value: */
1692 /* Associated BSSID */
1693 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1694 {
1695 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1696 }
1697 else
1698 {
1699 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1700 }
1701
1702 wfdielen += ETH_ALEN;
1703
1704 /* Coupled Sink Information ATTR */
1705 /* Type: */
1706 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1707
1708 /* Length: */
1709 /* Note: In the WFD specification, the size of length field is 2. */
1710 put_unaligned_be16(0x0007, wfdie + wfdielen);
1711 wfdielen += 2;
1712
1713 /* Value: */
1714 /* Coupled Sink Status bitmap */
1715 /* Not coupled/available for Coupling */
1716 wfdie[ wfdielen++ ] = 0;
1717 /* MAC Addr. */
1718 wfdie[ wfdielen++ ] = 0;
1719 wfdie[ wfdielen++ ] = 0;
1720 wfdie[ wfdielen++ ] = 0;
1721 wfdie[ wfdielen++ ] = 0;
1722 wfdie[ wfdielen++ ] = 0;
1723 wfdie[ wfdielen++ ] = 0;
1724
1725 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1726
1727 return len;
1728 }
1729
1730 u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1731 {
1732 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1733 u32 len = 0, wfdielen = 0;
1734 struct rtw_adapter *padapter = pwdinfo->padapter;
1735 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1736 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1737
1738 /* WFD OUI */
1739 wfdielen = 0;
1740 wfdie[ wfdielen++ ] = 0x50;
1741 wfdie[ wfdielen++ ] = 0x6F;
1742 wfdie[ wfdielen++ ] = 0x9A;
1743 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1744
1745 /* Commented by Albert 20110825 */
1746 /* According to the WFD Specification, the provision discovery response frame should contain 3 WFD attributes */
1747 /* 1. WFD Device Information */
1748 /* 2. Associated BSSID (Optional) */
1749 /* 3. Local IP Adress (Optional) */
1750
1751 /* WFD Device Information ATTR */
1752 /* Type: */
1753 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1754
1755 /* Length: */
1756 /* Note: In the WFD specification, the size of length field is 2. */
1757 put_unaligned_be16(0x0006, wfdie + wfdielen);
1758 wfdielen += 2;
1759
1760 /* Value1: */
1761 /* WFD device information */
1762 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1763 put_unaligned_be16(pwfd_info->wfd_device_type |
1764 WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
1765 wfdie + wfdielen);
1766 wfdielen += 2;
1767
1768 /* Value2: */
1769 /* Session Management Control Port */
1770 /* Default TCP port for RTSP messages is 554 */
1771 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1772 wfdielen += 2;
1773
1774 /* Value3: */
1775 /* WFD Device Maximum Throughput */
1776 /* 300Mbps is the maximum throughput */
1777 put_unaligned_be16(300, wfdie + wfdielen);
1778 wfdielen += 2;
1779
1780 /* Associated BSSID ATTR */
1781 /* Type: */
1782 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1783
1784 /* Length: */
1785 /* Note: In the WFD specification, the size of length field is 2. */
1786 put_unaligned_be16(0x0006, wfdie + wfdielen);
1787 wfdielen += 2;
1788
1789 /* Value: */
1790 /* Associated BSSID */
1791 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1792 {
1793 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1794 }
1795 else
1796 {
1797 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1798 }
1799
1800 wfdielen += ETH_ALEN;
1801
1802 /* Coupled Sink Information ATTR */
1803 /* Type: */
1804 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1805
1806 /* Length: */
1807 /* Note: In the WFD specification, the size of length field is 2. */
1808 put_unaligned_be16(0x0007, wfdie + wfdielen);
1809 wfdielen += 2;
1810
1811 /* Value: */
1812 /* Coupled Sink Status bitmap */
1813 /* Not coupled/available for Coupling */
1814 wfdie[ wfdielen++ ] = 0;
1815 /* MAC Addr. */
1816 wfdie[ wfdielen++ ] = 0;
1817 wfdie[ wfdielen++ ] = 0;
1818 wfdie[ wfdielen++ ] = 0;
1819 wfdie[ wfdielen++ ] = 0;
1820 wfdie[ wfdielen++ ] = 0;
1821 wfdie[ wfdielen++ ] = 0;
1822
1823 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1824
1825 return len;
1826 }
1827
1828 #endif /* CONFIG_8723AU_P2P */
1829
1830 u32 build_probe_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
1831 {
1832 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
1833 u32 len = 0, p2pielen = 0;
1834
1835 /* P2P OUI */
1836 p2pielen = 0;
1837 p2pie[ p2pielen++ ] = 0x50;
1838 p2pie[ p2pielen++ ] = 0x6F;
1839 p2pie[ p2pielen++ ] = 0x9A;
1840 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
1841
1842 /* Commented by Albert 20100907 */
1843 /* According to the P2P Specification, the probe response frame should contain 5 P2P attributes */
1844 /* 1. P2P Capability */
1845 /* 2. Extended Listen Timing */
1846 /* 3. Notice of Absence (NOA) (Only GO needs this) */
1847 /* 4. Device Info */
1848 /* 5. Group Info (Only GO need this) */
1849
1850 /* P2P Capability ATTR */
1851 /* Type: */
1852 p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
1853
1854 /* Length: */
1855 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
1856 put_unaligned_le16(0x0002, p2pie + p2pielen);
1857 p2pielen += 2;
1858
1859 /* Value: */
1860 /* Device Capability Bitmap, 1 byte */
1861 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
1862
1863 /* Group Capability Bitmap, 1 byte */
1864 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1865 {
1866 p2pie[ p2pielen ] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);
1867
1868 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
1869 p2pie[ p2pielen ] |= P2P_GRPCAP_GROUP_FORMATION;
1870
1871 p2pielen++;
1872 }
1873 else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE))
1874 {
1875 /* Group Capability Bitmap, 1 byte */
1876 if (pwdinfo->persistent_supported)
1877 p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
1878 else
1879 p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
1880 }
1881
1882 /* Extended Listen Timing ATTR */
1883 /* Type: */
1884 p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
1885
1886 /* Length: */
1887 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004); */
1888 put_unaligned_le16(0x0004, p2pie + p2pielen);
1889 p2pielen += 2;
1890
1891 /* Value: */
1892 /* Availability Period */
1893 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
1894 put_unaligned_le16(0xFFFF, p2pie + p2pielen);
1895 p2pielen += 2;
1896
1897 /* Availability Interval */
1898 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
1899 put_unaligned_le16(0xFFFF, p2pie + p2pielen);
1900 p2pielen += 2;
1901
1902 /* Notice of Absence ATTR */
1903 /* Type: */
1904 /* Length: */
1905 /* Value: */
1906 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1907 {
1908 /* go_add_noa_attr(pwdinfo); */
1909 }
1910
1911 /* Device Info ATTR */
1912 /* Type: */
1913 p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
1914
1915 /* Length: */
1916 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
1917 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
1918 /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
1919 put_unaligned_le16(21 + pwdinfo->device_name_len, p2pie + p2pielen);
1920 p2pielen += 2;
1921
1922 /* Value: */
1923 /* P2P Device Address */
1924 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
1925 p2pielen += ETH_ALEN;
1926
1927 /* Config Method */
1928 /* This field should be big endian. Noted by P2P specification. */
1929 /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); */
1930 put_unaligned_be16(pwdinfo->supported_wps_cm, p2pie + p2pielen);
1931 p2pielen += 2;
1932
1933 /* Primary Device Type */
1934 /* Category ID */
1935 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
1936 put_unaligned_be16(WPS_PDT_CID_MULIT_MEDIA, p2pie + p2pielen);
1937 p2pielen += 2;
1938
1939 /* OUI */
1940 /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
1941 put_unaligned_be32(WPSOUI, p2pie + p2pielen);
1942 p2pielen += 4;
1943
1944 /* Sub Category ID */
1945 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
1946 put_unaligned_be16(WPS_PDT_SCID_MEDIA_SERVER, p2pie + p2pielen);
1947 p2pielen += 2;
1948
1949 /* Number of Secondary Device Types */
1950 p2pie[ p2pielen++ ] = 0x00; /* No Secondary Device Type List */
1951
1952 /* Device Name */
1953 /* Type: */
1954 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
1955 put_unaligned_be16(WPS_ATTR_DEVICE_NAME, p2pie + p2pielen);
1956 p2pielen += 2;
1957
1958 /* Length: */
1959 /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
1960 put_unaligned_be16(pwdinfo->device_name_len, p2pie + p2pielen);
1961 p2pielen += 2;
1962
1963 /* Value: */
1964 memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
1965 p2pielen += pwdinfo->device_name_len;
1966
1967 /* Group Info ATTR */
1968 /* Type: */
1969 /* Length: */
1970 /* Value: */
1971 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1972 {
1973 p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);
1974 }
1975
1976 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
1977
1978 return len;
1979 }
1980
1981 u32 build_prov_disc_request_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf, u8* pssid, u8 ussidlen, u8* pdev_raddr)
1982 {
1983 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
1984 u32 len = 0, p2pielen = 0;
1985
1986 /* P2P OUI */
1987 p2pielen = 0;
1988 p2pie[ p2pielen++ ] = 0x50;
1989 p2pie[ p2pielen++ ] = 0x6F;
1990 p2pie[ p2pielen++ ] = 0x9A;
1991 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
1992
1993 /* Commented by Albert 20110301 */
1994 /* According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
1995 /* 1. P2P Capability */
1996 /* 2. Device Info */
1997 /* 3. Group ID (When joining an operating P2P Group) */
1998
1999 /* P2P Capability ATTR */
2000 /* Type: */
2001 p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
2002
2003 /* Length: */
2004 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
2005 put_unaligned_le16(0x0002, p2pie + p2pielen);
2006 p2pielen += 2;
2007
2008 /* Value: */
2009 /* Device Capability Bitmap, 1 byte */
2010 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
2011
2012 /* Group Capability Bitmap, 1 byte */
2013 if (pwdinfo->persistent_supported)
2014 p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
2015 else
2016 p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
2017
2018 /* Device Info ATTR */
2019 /* Type: */
2020 p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
2021
2022 /* Length: */
2023 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2024 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2025 /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
2026 put_unaligned_le16(21 + pwdinfo->device_name_len, p2pie + p2pielen);
2027 p2pielen += 2;
2028
2029 /* Value: */
2030 /* P2P Device Address */
2031 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
2032 p2pielen += ETH_ALEN;
2033
2034 /* Config Method */
2035 /* This field should be big endian. Noted by P2P specification. */
2036 if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
2037 {
2038 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC); */
2039 put_unaligned_be16(WPS_CONFIG_METHOD_PBC, p2pie + p2pielen);
2040 }
2041 else
2042 {
2043 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); */
2044 put_unaligned_be16(WPS_CONFIG_METHOD_DISPLAY, p2pie + p2pielen);
2045 }
2046
2047 p2pielen += 2;
2048
2049 /* Primary Device Type */
2050 /* Category ID */
2051 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
2052 put_unaligned_be16(WPS_PDT_CID_MULIT_MEDIA, p2pie + p2pielen);
2053 p2pielen += 2;
2054
2055 /* OUI */
2056 /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
2057 put_unaligned_be32(WPSOUI, p2pie + p2pielen);
2058 p2pielen += 4;
2059
2060 /* Sub Category ID */
2061 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
2062 put_unaligned_be16(WPS_PDT_SCID_MEDIA_SERVER, p2pie + p2pielen);
2063 p2pielen += 2;
2064
2065 /* Number of Secondary Device Types */
2066 p2pie[ p2pielen++ ] = 0x00; /* No Secondary Device Type List */
2067
2068 /* Device Name */
2069 /* Type: */
2070 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
2071 put_unaligned_be16(WPS_ATTR_DEVICE_NAME, p2pie + p2pielen);
2072 p2pielen += 2;
2073
2074 /* Length: */
2075 /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
2076 put_unaligned_be16(pwdinfo->device_name_len, p2pie + p2pielen);
2077 p2pielen += 2;
2078
2079 /* Value: */
2080 memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2081 p2pielen += pwdinfo->device_name_len;
2082
2083 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
2084 {
2085 /* Added by Albert 2011/05/19 */
2086 /* In this case, the pdev_raddr is the device address of the group owner. */
2087
2088 /* P2P Group ID ATTR */
2089 /* Type: */
2090 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
2091
2092 /* Length: */
2093 /* u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + ussidlen); */
2094 put_unaligned_le16(ETH_ALEN + ussidlen, p2pie + p2pielen);
2095 p2pielen += 2;
2096
2097 /* Value: */
2098 memcpy(p2pie + p2pielen, pdev_raddr, ETH_ALEN);
2099 p2pielen += ETH_ALEN;
2100
2101 memcpy(p2pie + p2pielen, pssid, ussidlen);
2102 p2pielen += ussidlen;
2103
2104 }
2105
2106 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2107
2108 return len;
2109 }
2110
2111 u32 build_assoc_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)
2112 {
2113 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
2114 u32 len = 0, p2pielen = 0;
2115
2116 /* P2P OUI */
2117 p2pielen = 0;
2118 p2pie[ p2pielen++ ] = 0x50;
2119 p2pie[ p2pielen++ ] = 0x6F;
2120 p2pie[ p2pielen++ ] = 0x9A;
2121 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
2122
2123 /* According to the P2P Specification, the Association response frame should contain 2 P2P attributes */
2124 /* 1. Status */
2125 /* 2. Extended Listen Timing (optional) */
2126
2127 /* Status ATTR */
2128 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);
2129
2130 /* Extended Listen Timing ATTR */
2131 /* Type: */
2132 /* Length: */
2133 /* Value: */
2134
2135 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2136
2137 return len;
2138 }
2139
2140 u32 build_deauth_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
2141 {
2142 u32 len = 0;
2143
2144 return len;
2145 }
2146
2147 u32 process_probe_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2148 {
2149 u8 *p;
2150 u32 ret = false;
2151 u8 *p2pie;
2152 u32 p2pielen = 0;
2153 int ssid_len = 0, rate_cnt = 0;
2154
2155 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
2156 len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_);
2157
2158 if (rate_cnt <= 4)
2159 {
2160 int i, g_rate = 0;
2161
2162 for (i = 0; i < rate_cnt; i++)
2163 {
2164 if (((*(p + 2 + i) & 0xff) != 0x02) &&
2165 ((*(p + 2 + i) & 0xff) != 0x04) &&
2166 ((*(p + 2 + i) & 0xff) != 0x0B) &&
2167 ((*(p + 2 + i) & 0xff) != 0x16))
2168 {
2169 g_rate = 1;
2170 }
2171 }
2172
2173 if (g_rate == 0)
2174 {
2175 /* There is no OFDM rate included in SupportedRates IE of this probe request frame */
2176 /* The driver should response this probe request. */
2177 return ret;
2178 }
2179 }
2180 else
2181 {
2182 /* rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */
2183 /* We should proceed the following check for this probe request. */
2184 }
2185
2186 /* Added comments by Albert 20100906 */
2187 /* There are several items we should check here. */
2188 /* 1. This probe request frame must contain the P2P IE. (Done) */
2189 /* 2. This probe request frame must contain the wildcard SSID. (Done) */
2190 /* 3. Wildcard BSSID. (Todo) */
2191 /* 4. Destination Address. (Done in mgt_dispatcher23a function) */
2192 /* 5. Requested Device Type in WSC IE. (Todo) */
2193 /* 6. Device ID attribute in P2P IE. (Todo) */
2194
2195 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
2196 len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_);
2197
2198 ssid_len &= 0xff; /* Just last 1 byte is valid for ssid len of the probe request */
2199 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2200 {
2201 if ((p2pie = rtw_get_p2p_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_, NULL, &p2pielen)))
2202 {
2203 if ((p) && !memcmp((void *)(p+2), (void *)pwdinfo->p2p_wildcard_ssid, 7))
2204 {
2205 /* todo: */
2206 /* Check Requested Device Type attributes in WSC IE. */
2207 /* Check Device ID attribute in P2P IE */
2208
2209 ret = true;
2210 }
2211 else if ((p != NULL) && (ssid_len == 0))
2212 {
2213 ret = true;
2214 }
2215 }
2216 else
2217 {
2218 /* non -p2p device */
2219 }
2220
2221 }
2222
2223 return ret;
2224 }
2225
2226 u32 process_assoc_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
2227 {
2228 u8 status_code = P2P_STATUS_SUCCESS;
2229 u8 *pbuf, *pattr_content = NULL;
2230 u32 attr_contentlen = 0;
2231 u16 cap_attr = 0;
2232 unsigned short ie_offset;
2233 u8 * ies;
2234 u32 ies_len;
2235 u8 * p2p_ie;
2236 u32 p2p_ielen = 0;
2237 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
2238
2239 if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2240 return P2P_STATUS_FAIL_REQUEST_UNABLE;
2241
2242 if (ieee80211_is_assoc_req(hdr->frame_control))
2243 ie_offset = _ASOCREQ_IE_OFFSET_;
2244 else /* WIFI_REASSOCREQ */
2245 ie_offset = _REASOCREQ_IE_OFFSET_;
2246
2247 ies = pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset;
2248 ies_len = len - sizeof(struct ieee80211_hdr_3addr) - ie_offset;
2249
2250 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2251
2252 if (!p2p_ie)
2253 {
2254 DBG_8723A("[%s] P2P IE not Found!!\n", __func__);
2255 status_code = P2P_STATUS_FAIL_INVALID_PARAM;
2256 }
2257 else
2258 {
2259 DBG_8723A("[%s] P2P IE Found!!\n", __func__);
2260 }
2261
2262 while (p2p_ie)
2263 {
2264 /* Check P2P Capability ATTR */
2265 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*) &attr_contentlen))
2266 {
2267 DBG_8723A("[%s] Got P2P Capability Attr!!\n", __func__);
2268 cap_attr = le16_to_cpu(cap_attr);
2269 psta->dev_cap = cap_attr&0xff;
2270 }
2271
2272 /* Check Extended Listen Timing ATTR */
2273
2274 /* Check P2P Device Info ATTR */
2275 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint*)&attr_contentlen))
2276 {
2277 DBG_8723A("[%s] Got P2P DEVICE INFO Attr!!\n", __func__);
2278 pattr_content = pbuf = kzalloc(attr_contentlen,
2279 GFP_ATOMIC);
2280 if (pattr_content) {
2281 u8 num_of_secdev_type;
2282 u16 dev_name_len;
2283
2284 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, pattr_content, (uint*)&attr_contentlen);
2285
2286 memcpy(psta->dev_addr, pattr_content, ETH_ALEN);/* P2P Device Address */
2287
2288 pattr_content += ETH_ALEN;
2289
2290 memcpy(&psta->config_methods, pattr_content, 2);/* Config Methods */
2291 psta->config_methods = be16_to_cpu(psta->config_methods);
2292
2293 pattr_content += 2;
2294
2295 memcpy(psta->primary_dev_type, pattr_content, 8);
2296
2297 pattr_content += 8;
2298
2299 num_of_secdev_type = *pattr_content;
2300 pattr_content += 1;
2301
2302 if (num_of_secdev_type == 0)
2303 {
2304 psta->num_of_secdev_type = 0;
2305 }
2306 else
2307 {
2308 u32 len;
2309
2310 psta->num_of_secdev_type = num_of_secdev_type;
2311
2312 len = (sizeof(psta->secdev_types_list)<(num_of_secdev_type*8)) ? (sizeof(psta->secdev_types_list)) : (num_of_secdev_type*8);
2313
2314 memcpy(psta->secdev_types_list, pattr_content, len);
2315
2316 pattr_content += (num_of_secdev_type*8);
2317 }
2318
2319 /* dev_name_len = attr_contentlen - ETH_ALEN - 2 - 8 - 1 - (num_of_secdev_type*8); */
2320 psta->dev_name_len = 0;
2321 if (WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(u16*)pattr_content))
2322 {
2323 dev_name_len = be16_to_cpu(*(u16*)(pattr_content+2));
2324
2325 psta->dev_name_len = (sizeof(psta->dev_name)<dev_name_len) ? sizeof(psta->dev_name):dev_name_len;
2326
2327 memcpy(psta->dev_name, pattr_content+4, psta->dev_name_len);
2328 }
2329
2330 kfree(pbuf);
2331
2332 }
2333
2334 }
2335
2336 /* Get the next P2P IE */
2337 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
2338
2339 }
2340
2341 return status_code;
2342 }
2343
2344 u32 process_p2p_devdisc_req23a(struct wifidirect_info *pwdinfo, u8 *pframe,
2345 uint len)
2346 {
2347 u8 *frame_body;
2348 u8 status, dialogToken;
2349 struct sta_info *psta = NULL;
2350 struct rtw_adapter *padapter = pwdinfo->padapter;
2351 struct sta_priv *pstapriv = &padapter->stapriv;
2352 u8 *p2p_ie;
2353 u32 p2p_ielen = 0;
2354 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
2355
2356 frame_body = (unsigned char *)
2357 (pframe + sizeof(struct ieee80211_hdr_3addr));
2358
2359 dialogToken = frame_body[7];
2360 status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
2361
2362 if ((p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
2363 len - _PUBLIC_ACTION_IE_OFFSET_, NULL,
2364 &p2p_ielen))) {
2365 u8 groupid[38] = { 0x00 };
2366 u8 dev_addr[ETH_ALEN] = { 0x00 };
2367 u32 attr_contentlen = 0;
2368
2369 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
2370 P2P_ATTR_GROUP_ID, groupid,
2371 &attr_contentlen)) {
2372 if (!memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
2373 !memcmp(pwdinfo->p2p_group_ssid, groupid + ETH_ALEN,
2374 pwdinfo->p2p_group_ssid_len)) {
2375 attr_contentlen = 0;
2376
2377 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
2378 P2P_ATTR_DEVICE_ID,
2379 dev_addr,
2380 &attr_contentlen)) {
2381 struct list_head *phead, *plist, *ptmp;
2382
2383 spin_lock_bh(&pstapriv->asoc_list_lock);
2384 phead = &pstapriv->asoc_list;
2385
2386 list_for_each_safe(plist, ptmp, phead) {
2387 psta = container_of(plist, struct sta_info, asoc_list);
2388
2389 if (psta->is_p2p_device && (psta->dev_cap&P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
2390 !memcmp(psta->dev_addr, dev_addr, ETH_ALEN))
2391 {
2392 /* spin_unlock_bh(&pstapriv->asoc_list_lock); */
2393 /* issue GO Discoverability Request */
2394 issue_group_disc_req(pwdinfo, psta->hwaddr);
2395 /* spin_lock_bh(&pstapriv->asoc_list_lock); */
2396 status = P2P_STATUS_SUCCESS;
2397 break;
2398 } else {
2399 status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2400 }
2401 }
2402 spin_unlock_bh(&pstapriv->asoc_list_lock);
2403 } else {
2404 status = P2P_STATUS_FAIL_INVALID_PARAM;
2405 }
2406 } else {
2407 status = P2P_STATUS_FAIL_INVALID_PARAM;
2408 }
2409 }
2410 }
2411
2412 /* issue Device Discoverability Response */
2413 issue_p2p_devdisc_resp(pwdinfo, hdr->addr2, status, dialogToken);
2414
2415 return (status == P2P_STATUS_SUCCESS) ? true:false;
2416 }
2417
2418 u32 process_p2p_devdisc_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2419 {
2420 return true;
2421 }
2422
2423 u8 process_p2p_provdisc_req23a(struct wifidirect_info *pwdinfo,
2424 u8 *pframe, uint len)
2425 {
2426 u8 *frame_body;
2427 u8 *wpsie;
2428 u8 *ptr = NULL;
2429 uint wps_ielen = 0, attr_contentlen = 0;
2430 u16 uconfig_method = 0;
2431 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
2432
2433 frame_body = (pframe + sizeof(struct ieee80211_hdr_3addr));
2434
2435 wpsie = rtw_get_wps_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
2436 len - _PUBLIC_ACTION_IE_OFFSET_, NULL,
2437 &wps_ielen);
2438 if (!wpsie)
2439 goto out;
2440
2441 if (!rtw_get_wps_attr_content23a(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD,
2442 (u8 *)&uconfig_method, &attr_contentlen))
2443 goto out;
2444
2445 uconfig_method = be16_to_cpu(uconfig_method);
2446 ptr = pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req;
2447
2448 switch (uconfig_method)
2449 {
2450 case WPS_CM_DISPLYA:
2451 memcpy(ptr, "dis", 3);
2452 break;
2453
2454 case WPS_CM_LABEL:
2455 memcpy(ptr, "lab", 3);
2456 break;
2457
2458 case WPS_CM_PUSH_BUTTON:
2459 memcpy(ptr, "pbc", 3);
2460 break;
2461
2462 case WPS_CM_KEYPAD:
2463 memcpy(ptr, "pad", 3);
2464 break;
2465 }
2466 issue_p2p_provision_resp(pwdinfo, hdr->addr2, frame_body,
2467 uconfig_method);
2468
2469 out:
2470 DBG_8723A("[%s] config method = %s\n", __func__, ptr);
2471
2472 return true;
2473 }
2474
2475 u8 process_p2p_provdisc_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe)
2476 {
2477
2478 return true;
2479 }
2480
2481 static u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
2482 {
2483 u8 i = 0, j = 0;
2484 u8 temp = 0;
2485 u8 ch_no = 0;
2486 ch_content += 3;
2487 ch_cnt -= 3;
2488
2489 while(ch_cnt > 0)
2490 {
2491 ch_content += 1;
2492 ch_cnt -= 1;
2493 temp = *ch_content;
2494 for (i = 0 ; i < temp ; i++, j++)
2495 {
2496 peer_ch_list[j] = *(ch_content + 1 + i);
2497 }
2498 ch_content += (temp + 1);
2499 ch_cnt -= (temp + 1);
2500 ch_no += temp ;
2501 }
2502
2503 return ch_no;
2504 }
2505
2506 static u8 rtw_p2p_ch_inclusion(struct mlme_ext_priv *pmlmeext, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
2507 {
2508 int i = 0, j = 0, temp = 0;
2509 u8 ch_no = 0;
2510
2511 for (i = 0; i < peer_ch_num; i++)
2512 {
2513 for (j = temp; j < pmlmeext->max_chan_nums; j++)
2514 {
2515 if (*(peer_ch_list + i) == pmlmeext->channel_set[ j ].ChannelNum)
2516 {
2517 ch_list_inclusioned[ ch_no++ ] = *(peer_ch_list + i);
2518 temp = j;
2519 break;
2520 }
2521 }
2522 }
2523
2524 return ch_no;
2525 }
2526
2527 u8 process_p2p_group_negotation_req23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2528 {
2529 struct rtw_adapter *padapter = pwdinfo->padapter;
2530 u8 result = P2P_STATUS_SUCCESS;
2531 u32 p2p_ielen = 0, wps_ielen = 0;
2532 u8 * ies;
2533 u32 ies_len;
2534 u8 *p2p_ie;
2535 u8 *wpsie;
2536 u16 wps_devicepassword_id = 0x0000;
2537 uint wps_devicepassword_id_len = 0;
2538 #ifdef CONFIG_8723AU_P2P
2539 u8 wfd_ie[ 128 ] = { 0x00 };
2540 u32 wfd_ielen = 0;
2541 #endif /* CONFIG_8723AU_P2P */
2542
2543 if ((wpsie = rtw_get_wps_ie23a(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen)))
2544 {
2545 /* Commented by Kurt 20120113 */
2546 /* If some device wants to do p2p handshake without sending prov_disc_req */
2547 /* We have to get peer_req_cm from here. */
2548 if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3))
2549 {
2550 rtw_get_wps_attr_content23a(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);
2551 wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
2552
2553 if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2554 {
2555 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2556 }
2557 else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2558 {
2559 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2560 }
2561 else
2562 {
2563 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2564 }
2565 }
2566 }
2567 else
2568 {
2569 DBG_8723A("[%s] WPS IE not Found!!\n", __func__);
2570 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2571 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2572 return result;
2573 }
2574
2575 if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
2576 {
2577 result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2578 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
2579 return result;
2580 }
2581
2582 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2583 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2584
2585 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2586
2587 if (!p2p_ie)
2588 {
2589 DBG_8723A("[%s] P2P IE not Found!!\n", __func__);
2590 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2591 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2592 }
2593
2594 while (p2p_ie)
2595 {
2596 u8 attr_content = 0x00;
2597 u32 attr_contentlen = 0;
2598 u8 ch_content[50] = { 0x00 };
2599 uint ch_cnt = 0;
2600 u8 peer_ch_list[50] = { 0x00 };
2601 u8 peer_ch_num = 0;
2602 u8 ch_list_inclusioned[50] = { 0x00 };
2603 u8 ch_num_inclusioned = 0;
2604 u16 cap_attr;
2605
2606 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
2607
2608 /* Check P2P Capability ATTR */
2609 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen))
2610 cap_attr = le16_to_cpu(cap_attr);
2611
2612 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen))
2613 {
2614 DBG_8723A("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
2615 pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2616
2617 if (pwdinfo->intent == (pwdinfo->peer_intent >> 1))
2618 {
2619 /* Try to match the tie breaker value */
2620 if (pwdinfo->intent == P2P_MAX_INTENT)
2621 {
2622 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2623 result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2624 }
2625 else
2626 {
2627 if (attr_content & 0x01)
2628 {
2629 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2630 }
2631 else
2632 {
2633 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2634 }
2635 }
2636 }
2637 else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))
2638 {
2639 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2640 }
2641 else
2642 {
2643 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2644 }
2645
2646 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2647 {
2648 /* Store the group id information. */
2649 memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2650 memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2651 }
2652 }
2653
2654 attr_contentlen = 0;
2655 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen))
2656 {
2657 if (attr_contentlen != ETH_ALEN)
2658 {
2659 memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2660 }
2661 }
2662
2663 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt))
2664 {
2665 peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
2666 ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2667
2668 if (ch_num_inclusioned == 0)
2669 {
2670 DBG_8723A("[%s] No common channel in channel list!\n", __func__);
2671 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2672 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2673 break;
2674 }
2675
2676 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2677 {
2678 if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2679 ch_list_inclusioned, ch_num_inclusioned))
2680 {
2681 {
2682 u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2683 attr_contentlen = 0;
2684
2685 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2686 {
2687 peer_operating_ch = operatingch_info[4];
2688 }
2689
2690 if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2691 ch_list_inclusioned, ch_num_inclusioned))
2692 {
2693 /**
2694 * Change our operating channel as peer's for compatibility.
2695 */
2696 pwdinfo->operating_channel = peer_operating_ch;
2697 DBG_8723A("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
2698 }
2699 else
2700 {
2701 /* Take first channel of ch_list_inclusioned as operating channel */
2702 pwdinfo->operating_channel = ch_list_inclusioned[0];
2703 DBG_8723A("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
2704 }
2705 }
2706
2707 }
2708 }
2709 }
2710
2711 /* Get the next P2P IE */
2712 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
2713 }
2714
2715 #ifdef CONFIG_8723AU_P2P
2716 /* Added by Albert 20110823 */
2717 /* Try to get the TCP port information when receiving the negotiation request. */
2718 if (rtw_get_wfd_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wfd_ie, &wfd_ielen))
2719 {
2720 u8 attr_content[ 10 ] = { 0x00 };
2721 u32 attr_contentlen = 0;
2722
2723 DBG_8723A("[%s] WFD IE Found!!\n", __func__);
2724 rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
2725 if (attr_contentlen)
2726 {
2727 pwdinfo->wfd_info->peer_rtsp_ctrlport = get_unaligned_be16(attr_content + 2);
2728 DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
2729 }
2730 }
2731 #endif /* CONFIG_8723AU_P2P */
2732
2733 return result;
2734 }
2735
2736 u8 process_p2p_group_negotation_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2737 {
2738 struct rtw_adapter *padapter = pwdinfo->padapter;
2739 u8 result = P2P_STATUS_SUCCESS;
2740 u32 p2p_ielen, wps_ielen;
2741 u8 * ies;
2742 u32 ies_len;
2743 u8 * p2p_ie;
2744 #ifdef CONFIG_8723AU_P2P
2745 u8 wfd_ie[ 128 ] = { 0x00 };
2746 u32 wfd_ielen = 0;
2747 #endif /* CONFIG_8723AU_P2P */
2748
2749 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2750 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2751
2752 /* Be able to know which one is the P2P GO and which one is P2P client. */
2753
2754 if (rtw_get_wps_ie23a(ies, ies_len, NULL, &wps_ielen))
2755 {
2756
2757 }
2758 else
2759 {
2760 DBG_8723A("[%s] WPS IE not Found!!\n", __func__);
2761 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2762 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2763 }
2764
2765 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2766 if (!p2p_ie)
2767 {
2768 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2769 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2770 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2771 }
2772 else
2773 {
2774
2775 u8 attr_content = 0x00;
2776 u32 attr_contentlen = 0;
2777 u8 operatingch_info[5] = { 0x00 };
2778 u8 groupid[ 38 ];
2779 u16 cap_attr;
2780 u8 peer_ch_list[50] = { 0x00 };
2781 u8 peer_ch_num = 0;
2782 u8 ch_list_inclusioned[50] = { 0x00 };
2783 u8 ch_num_inclusioned = 0;
2784
2785 while (p2p_ie) /* Found the P2P IE. */
2786 {
2787
2788 /* Check P2P Capability ATTR */
2789 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen))
2790 cap_attr = le16_to_cpu(cap_attr);
2791
2792 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
2793 if (attr_contentlen == 1)
2794 {
2795 DBG_8723A("[%s] Status = %d\n", __func__, attr_content);
2796 if (attr_content == P2P_STATUS_SUCCESS)
2797 {
2798 /* Do nothing. */
2799 }
2800 else
2801 {
2802 if (P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content) {
2803 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
2804 } else {
2805 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2806 }
2807 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2808 result = attr_content;
2809 break;
2810 }
2811 }
2812
2813 /* Try to get the peer's interface address */
2814 attr_contentlen = 0;
2815 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen))
2816 {
2817 if (attr_contentlen != ETH_ALEN)
2818 {
2819 memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2820 }
2821 }
2822
2823 /* Try to get the peer's intent and tie breaker value. */
2824 attr_content = 0x00;
2825 attr_contentlen = 0;
2826 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen))
2827 {
2828 DBG_8723A("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
2829 pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2830
2831 if (pwdinfo->intent == (pwdinfo->peer_intent >> 1))
2832 {
2833 /* Try to match the tie breaker value */
2834 if (pwdinfo->intent == P2P_MAX_INTENT)
2835 {
2836 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2837 result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2838 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2839 }
2840 else
2841 {
2842 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2843 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2844 if (attr_content & 0x01)
2845 {
2846 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2847 }
2848 else
2849 {
2850 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2851 }
2852 }
2853 }
2854 else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))
2855 {
2856 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2857 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2858 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2859 }
2860 else
2861 {
2862 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2863 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2864 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2865 }
2866
2867 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2868 {
2869 /* Store the group id information. */
2870 memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2871 memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2872
2873 }
2874 }
2875
2876 /* Try to get the operation channel information */
2877
2878 attr_contentlen = 0;
2879 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2880 {
2881 DBG_8723A("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
2882 pwdinfo->peer_operating_ch = operatingch_info[4];
2883 }
2884
2885 /* Try to get the channel list information */
2886 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len))
2887 {
2888 DBG_8723A("[%s] channel list attribute found, len = %d\n", __func__, pwdinfo->channel_list_attr_len);
2889
2890 peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
2891 ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2892
2893 if (ch_num_inclusioned == 0)
2894 {
2895 DBG_8723A("[%s] No common channel in channel list!\n", __func__);
2896 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2897 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2898 break;
2899 }
2900
2901 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2902 {
2903 if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2904 ch_list_inclusioned, ch_num_inclusioned))
2905 {
2906 {
2907 u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2908 attr_contentlen = 0;
2909
2910 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2911 {
2912 peer_operating_ch = operatingch_info[4];
2913 }
2914
2915 if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2916 ch_list_inclusioned, ch_num_inclusioned))
2917 {
2918 /**
2919 * Change our operating channel as peer's for compatibility.
2920 */
2921 pwdinfo->operating_channel = peer_operating_ch;
2922 DBG_8723A("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
2923 }
2924 else
2925 {
2926 /* Take first channel of ch_list_inclusioned as operating channel */
2927 pwdinfo->operating_channel = ch_list_inclusioned[0];
2928 DBG_8723A("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
2929 }
2930 }
2931
2932 }
2933 }
2934
2935 }
2936 else
2937 {
2938 DBG_8723A("[%s] channel list attribute not found!\n", __func__);
2939 }
2940
2941 /* Try to get the group id information if peer is GO */
2942 attr_contentlen = 0;
2943 memset(groupid, 0x00, 38);
2944 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen))
2945 {
2946 memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
2947 memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
2948 }
2949
2950 /* Get the next P2P IE */
2951 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
2952 }
2953
2954 }
2955
2956 #ifdef CONFIG_8723AU_P2P
2957 /* Added by Albert 20111122 */
2958 /* Try to get the TCP port information when receiving the negotiation response. */
2959 if (rtw_get_wfd_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wfd_ie, &wfd_ielen))
2960 {
2961 u8 attr_content[ 10 ] = { 0x00 };
2962 u32 attr_contentlen = 0;
2963
2964 DBG_8723A("[%s] WFD IE Found!!\n", __func__);
2965 rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
2966 if (attr_contentlen)
2967 {
2968 pwdinfo->wfd_info->peer_rtsp_ctrlport = get_unaligned_be16(attr_content + 2);
2969 DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
2970 }
2971 }
2972 #endif /* CONFIG_8723AU_P2P */
2973
2974 return result;
2975 }
2976
2977 u8 process_p2p_group_negotation_confirm23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2978 {
2979 u8 * ies;
2980 u32 ies_len;
2981 u8 * p2p_ie;
2982 u32 p2p_ielen = 0;
2983 u8 result = P2P_STATUS_SUCCESS;
2984 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2985 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2986
2987 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2988 while (p2p_ie) /* Found the P2P IE. */
2989 {
2990 u8 attr_content = 0x00, operatingch_info[5] = { 0x00 };
2991 u8 groupid[ 38 ] = { 0x00 };
2992 u32 attr_contentlen = 0;
2993
2994 pwdinfo->negotiation_dialog_token = 1;
2995 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
2996 if (attr_contentlen == 1)
2997 {
2998 DBG_8723A("[%s] Status = %d\n", __func__, attr_content);
2999 result = attr_content;
3000
3001 if (attr_content == P2P_STATUS_SUCCESS)
3002 {
3003 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
3004
3005 /* Commented by Albert 20100911 */
3006 /* Todo: Need to handle the case which both Intents are the same. */
3007 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3008 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3009 if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1))
3010 {
3011 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3012 }
3013 else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1))
3014 {
3015 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3016 }
3017 else
3018 {
3019 /* Have to compare the Tie Breaker */
3020 if (pwdinfo->peer_intent & 0x01)
3021 {
3022 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3023 }
3024 else
3025 {
3026 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3027 }
3028 }
3029 }
3030 else
3031 {
3032 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3033 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
3034 break;
3035 }
3036 }
3037
3038 /* Try to get the group id information */
3039 attr_contentlen = 0;
3040 memset(groupid, 0x00, 38);
3041 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen))
3042 {
3043 DBG_8723A("[%s] Ssid = %s, ssidlen = %zu\n", __func__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]));
3044 memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
3045 memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
3046 }
3047
3048 attr_contentlen = 0;
3049 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
3050 {
3051 DBG_8723A("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
3052 pwdinfo->peer_operating_ch = operatingch_info[4];
3053 }
3054
3055 /* Get the next P2P IE */
3056 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3057
3058 }
3059
3060 return result;
3061 }
3062
3063 u8 process_p2p_presence_req23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
3064 {
3065 u8 *frame_body;
3066 u8 dialogToken = 0;
3067 u8 status = P2P_STATUS_SUCCESS;
3068 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
3069
3070 frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
3071
3072 dialogToken = frame_body[6];
3073
3074 /* todo: check NoA attribute */
3075
3076 issue_p2p_presence_resp(pwdinfo, hdr->addr2, status, dialogToken);
3077
3078 return true;
3079 }
3080
3081 static void find_phase_handler(struct rtw_adapter *padapter)
3082 {
3083 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3084 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3085 struct cfg80211_ssid ssid;
3086 u8 _status = 0;
3087
3088
3089
3090 memset((unsigned char*)&ssid, 0, sizeof(struct cfg80211_ssid));
3091 memcpy(ssid.ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
3092 ssid.ssid_len = P2P_WILDCARD_SSID_LEN;
3093
3094 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
3095
3096 spin_lock_bh(&pmlmepriv->lock);
3097 _status = rtw_sitesurvey_cmd23a(padapter, &ssid, 1, NULL, 0);
3098 spin_unlock_bh(&pmlmepriv->lock);
3099
3100
3101 }
3102
3103 void p2p_concurrent_handler(struct rtw_adapter* padapter);
3104
3105 static void restore_p2p_state_handler(struct rtw_adapter *padapter)
3106 {
3107 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3108
3109 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
3110 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3111
3112 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3113
3114 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
3115 /* In the P2P client mode, the driver should not switch back to its listen channel */
3116 /* because this P2P client should stay at the operating channel of P2P GO. */
3117 set_channel_bwmode23a(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3118 }
3119 }
3120
3121 static void pre_tx_invitereq_handler(struct rtw_adapter *padapter)
3122 {
3123 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3124
3125 set_channel_bwmode23a(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3126 rtl8723a_mlme_sitesurvey(padapter, 1);
3127 issue23a_probereq_p2p(padapter, NULL);
3128 mod_timer(&pwdinfo->pre_tx_scan_timer,
3129 jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
3130 }
3131
3132 static void pre_tx_provdisc_handler(struct rtw_adapter *padapter)
3133 {
3134 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3135
3136 set_channel_bwmode23a(padapter,
3137 pwdinfo->tx_prov_disc_info.peer_channel_num[0],
3138 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
3139 HT_CHANNEL_WIDTH_20);
3140 rtl8723a_mlme_sitesurvey(padapter, 1);
3141 issue23a_probereq_p2p(padapter, NULL);
3142 mod_timer(&pwdinfo->pre_tx_scan_timer,
3143 jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
3144 }
3145
3146 static void pre_tx_negoreq_handler(struct rtw_adapter *padapter)
3147 {
3148 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3149
3150 set_channel_bwmode23a(padapter,
3151 pwdinfo->nego_req_info.peer_channel_num[0],
3152 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
3153 HT_CHANNEL_WIDTH_20);
3154 rtl8723a_mlme_sitesurvey(padapter, 1);
3155 issue23a_probereq_p2p(padapter, NULL);
3156 mod_timer(&pwdinfo->pre_tx_scan_timer,
3157 jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
3158 }
3159
3160 static void ro_ch_handler(struct rtw_adapter *padapter)
3161 {
3162 struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
3163 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3164 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3165
3166 if (pcfg80211_wdinfo->restore_channel != pmlmeext->cur_channel) {
3167 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
3168 pmlmeext->cur_channel = pcfg80211_wdinfo->restore_channel;
3169
3170 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
3171 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
3172 HT_CHANNEL_WIDTH_20);
3173 }
3174
3175 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3176
3177 pcfg80211_wdinfo->is_ro_ch = false;
3178
3179 DBG_8723A("cfg80211_remain_on_channel_expired\n");
3180
3181 rtw_cfg80211_remain_on_channel_expired(padapter,
3182 pcfg80211_wdinfo->remain_on_ch_cookie,
3183 &pcfg80211_wdinfo->remain_on_ch_channel,
3184 pcfg80211_wdinfo->remain_on_ch_type, GFP_KERNEL);
3185 }
3186
3187 static void ro_ch_timer_process (unsigned long data)
3188 {
3189 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3190
3191 p2p_protocol_wk_cmd23a(adapter, P2P_RO_CH_WK);
3192 }
3193
3194 #ifdef CONFIG_8723AU_P2P
3195 void rtw_append_wfd_ie(struct rtw_adapter *padapter, u8 *buf, u32* len)
3196 {
3197 unsigned char *frame_body;
3198 u8 category, action, OUI_Subtype, dialogToken = 0;
3199 u32 wfdielen = 0;
3200
3201 frame_body = (unsigned char *)(buf + sizeof(struct ieee80211_hdr_3addr));
3202 category = frame_body[0];
3203
3204 if (category == WLAN_CATEGORY_PUBLIC) {
3205 action = frame_body[1];
3206 if (action == ACT_PUBLIC_VENDOR &&
3207 !memcmp(frame_body+2, P2P_OUI23A, 4)) {
3208 OUI_Subtype = frame_body[6];
3209 dialogToken = frame_body[7];
3210 switch (OUI_Subtype)/* OUI Subtype */ {
3211 case P2P_GO_NEGO_REQ:
3212 wfdielen = build_nego_req_wfd_ie(&padapter->wdinfo, buf + (*len));
3213 (*len) += wfdielen;
3214 break;
3215 case P2P_GO_NEGO_RESP:
3216 wfdielen = build_nego_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
3217 (*len) += wfdielen;
3218 break;
3219 case P2P_GO_NEGO_CONF:
3220 wfdielen = build_nego_confirm_wfd_ie(&padapter->wdinfo, buf + (*len));
3221 (*len) += wfdielen;
3222 break;
3223 case P2P_INVIT_REQ:
3224 wfdielen = build_invitation_req_wfd_ie(&padapter->wdinfo, buf + (*len));
3225 (*len) += wfdielen;
3226 break;
3227 case P2P_INVIT_RESP:
3228 wfdielen = build_invitation_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
3229 (*len) += wfdielen;
3230 break;
3231 case P2P_DEVDISC_REQ:
3232 break;
3233 case P2P_DEVDISC_RESP:
3234 break;
3235 case P2P_PROVISION_DISC_REQ:
3236 wfdielen = build_provdisc_req_wfd_ie(&padapter->wdinfo, buf + (*len));
3237 (*len) += wfdielen;
3238 break;
3239 case P2P_PROVISION_DISC_RESP:
3240 wfdielen = build_provdisc_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
3241 (*len) += wfdielen;
3242 break;
3243 default:
3244 break;
3245 }
3246 }
3247 } else if (category == WLAN_CATEGORY_VENDOR_SPECIFIC) {
3248 OUI_Subtype = frame_body[5];
3249 dialogToken = frame_body[6];
3250 } else {
3251 DBG_8723A("%s, action frame category =%d\n", __func__, category);
3252 }
3253 }
3254 #endif
3255
3256 int rtw_p2p_check_frames(struct rtw_adapter *padapter, const u8 *buf, u32 len, u8 tx)
3257 {
3258 int is_p2p_frame = (-1);
3259 unsigned char *frame_body;
3260 u8 category, action, OUI_Subtype, dialogToken = 0;
3261 u8 *p2p_ie = NULL;
3262 uint p2p_ielen = 0;
3263 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
3264
3265 frame_body = (unsigned char *)(buf + sizeof(struct ieee80211_hdr_3addr));
3266 category = frame_body[0];
3267 /* just for check */
3268 if (category == WLAN_CATEGORY_PUBLIC)
3269 {
3270 action = frame_body[1];
3271 if (action == ACT_PUBLIC_VENDOR &&
3272 !memcmp(frame_body+2, P2P_OUI23A, 4)) {
3273 OUI_Subtype = frame_body[6];
3274 dialogToken = frame_body[7];
3275 is_p2p_frame = OUI_Subtype;
3276 p2p_ie = rtw_get_p2p_ie23a(
3277 (u8 *)buf+sizeof(struct ieee80211_hdr_3addr)+_PUBLIC_ACTION_IE_OFFSET_,
3278 len-sizeof(struct ieee80211_hdr_3addr)-_PUBLIC_ACTION_IE_OFFSET_,
3279 NULL, &p2p_ielen);
3280
3281 switch (OUI_Subtype) {/* OUI Subtype */
3282 u8 *cont;
3283 uint cont_len;
3284 case P2P_GO_NEGO_REQ:
3285 DBG_8723A("RTW_%s:P2P_GO_NEGO_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3286 break;
3287 case P2P_GO_NEGO_RESP:
3288 cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3289 DBG_8723A("RTW_%s:P2P_GO_NEGO_RESP, dialogToken =%d, status:%d\n", (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
3290
3291 if (!tx)
3292 pwdev_priv->provdisc_req_issued = false;
3293 break;
3294 case P2P_GO_NEGO_CONF:
3295 cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3296 DBG_8723A("RTW_%s:P2P_GO_NEGO_CONF, dialogToken =%d, status:%d\n",
3297 (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
3298 break;
3299 case P2P_INVIT_REQ:
3300 {
3301 struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
3302 int flags = -1;
3303 int op_ch = 0;
3304
3305 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, NULL, &cont_len)))
3306 flags = *cont;
3307 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
3308 op_ch = *(cont+4);
3309
3310 if (invit_info->token != dialogToken)
3311 rtw_wdev_invit_info_init(invit_info);
3312
3313 invit_info->token = dialogToken;
3314 invit_info->flags = (flags ==-1) ? 0x0 : flags;
3315 invit_info->req_op_ch = op_ch;
3316
3317 DBG_8723A("RTW_%s:P2P_INVIT_REQ, dialogToken =%d, flags:0x%02x, op_ch:%d\n",
3318 (tx) ? "Tx" : "Rx", dialogToken, flags, op_ch);
3319 break;
3320 }
3321 case P2P_INVIT_RESP:
3322 {
3323 struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
3324 int status = -1;
3325 int op_ch = 0;
3326
3327 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len)))
3328 status = *cont;
3329 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
3330 op_ch = *(cont+4);
3331
3332 if (invit_info->token != dialogToken) {
3333 rtw_wdev_invit_info_init(invit_info);
3334 } else {
3335 invit_info->token = 0;
3336 invit_info->status = (status ==-1) ? 0xff : status;
3337 invit_info->rsp_op_ch = op_ch;
3338 }
3339
3340 DBG_8723A("RTW_%s:P2P_INVIT_RESP, dialogToken =%d, status:%d, op_ch:%d\n",
3341 (tx == true)?"Tx":"Rx", dialogToken, status, op_ch);
3342 break;
3343 }
3344 case P2P_DEVDISC_REQ:
3345 DBG_8723A("RTW_%s:P2P_DEVDISC_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3346 break;
3347 case P2P_DEVDISC_RESP:
3348 cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3349 DBG_8723A("RTW_%s:P2P_DEVDISC_RESP, dialogToken =%d, status:%d\n", (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
3350 break;
3351 case P2P_PROVISION_DISC_REQ:
3352 {
3353 size_t frame_body_len = len - sizeof(struct ieee80211_hdr_3addr);
3354 u8 *p2p_ie;
3355 uint p2p_ielen = 0;
3356 uint contentlen = 0;
3357
3358 DBG_8723A("RTW_%s:P2P_PROVISION_DISC_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3359
3360 pwdev_priv->provdisc_req_issued = false;
3361
3362 p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
3363 frame_body_len - _PUBLIC_ACTION_IE_OFFSET_,
3364 NULL, &p2p_ielen);
3365 if (p2p_ie) {
3366 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, NULL, &contentlen))
3367 pwdev_priv->provdisc_req_issued = false;/* case: p2p_client join p2p GO */
3368 else
3369 pwdev_priv->provdisc_req_issued = true;/* case: p2p_devices connection before Nego req. */
3370 }
3371 }
3372 break;
3373 case P2P_PROVISION_DISC_RESP:
3374 DBG_8723A("RTW_%s:P2P_PROVISION_DISC_RESP, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3375 break;
3376 default:
3377 DBG_8723A("RTW_%s:OUI_Subtype =%d, dialogToken =%d\n", (tx == true)?"Tx":"Rx", OUI_Subtype, dialogToken);
3378 break;
3379 }
3380
3381 }
3382
3383 }
3384 else if (category == WLAN_CATEGORY_VENDOR_SPECIFIC)
3385 {
3386 OUI_Subtype = frame_body[5];
3387 dialogToken = frame_body[6];
3388
3389 is_p2p_frame = OUI_Subtype;
3390
3391 switch (OUI_Subtype) {
3392 case P2P_NOTICE_OF_ABSENCE:
3393 DBG_8723A("RTW_%s:P2P_NOTICE_OF_ABSENCE, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3394 break;
3395 case P2P_PRESENCE_REQUEST:
3396 DBG_8723A("RTW_%s:P2P_PRESENCE_REQUEST, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3397 break;
3398 case P2P_PRESENCE_RESPONSE:
3399 DBG_8723A("RTW_%s:P2P_PRESENCE_RESPONSE, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3400 break;
3401 case P2P_GO_DISC_REQUEST:
3402 DBG_8723A("RTW_%s:P2P_GO_DISC_REQUEST, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3403 break;
3404 default:
3405 DBG_8723A("RTW_%s:OUI_Subtype =%d, dialogToken =%d\n", (tx == true)?"TX":"RX", OUI_Subtype, dialogToken);
3406 break;
3407 }
3408
3409 } else {
3410 DBG_8723A("RTW_%s:action frame category =%d\n", (tx == true)?"TX":"RX", category);
3411 }
3412 return is_p2p_frame;
3413 }
3414
3415 void rtw_init_cfg80211_wifidirect_info(struct rtw_adapter *padapter)
3416 {
3417 struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
3418
3419 memset(pcfg80211_wdinfo, 0x00, sizeof(struct cfg80211_wifidirect_info));
3420
3421 setup_timer(&pcfg80211_wdinfo->remain_on_ch_timer,
3422 ro_ch_timer_process, (unsigned long)padapter);
3423 }
3424
3425 void p2p_protocol_wk_hdl23a(struct rtw_adapter *padapter, int intCmdType)
3426 {
3427 switch (intCmdType) {
3428 case P2P_FIND_PHASE_WK:
3429 find_phase_handler(padapter);
3430 break;
3431 case P2P_RESTORE_STATE_WK:
3432 restore_p2p_state_handler(padapter);
3433 break;
3434 case P2P_PRE_TX_PROVDISC_PROCESS_WK:
3435 pre_tx_provdisc_handler(padapter);
3436 break;
3437 case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
3438 pre_tx_invitereq_handler(padapter);
3439 break;
3440 case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
3441 pre_tx_negoreq_handler(padapter);
3442 break;
3443 case P2P_RO_CH_WK:
3444 ro_ch_handler(padapter);
3445 break;
3446 }
3447 }
3448
3449 #ifdef CONFIG_8723AU_P2P
3450 void process_p2p_ps_ie23a(struct rtw_adapter *padapter, u8 *IEs, u32 IELength)
3451 {
3452 u8 * ies;
3453 u32 ies_len;
3454 u8 * p2p_ie;
3455 u32 p2p_ielen = 0;
3456 u8 noa_attr[MAX_P2P_IE_LEN] = { 0x00 };/* NoA length should be n*(13) + 2 */
3457 u32 attr_contentlen = 0;
3458
3459 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3460 u8 find_p2p = false, find_p2p_ps = false;
3461 u8 noa_offset, noa_num, noa_index;
3462
3463
3464
3465 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3466 {
3467 return;
3468 }
3469 if (IELength <= _BEACON_IE_OFFSET_)
3470 return;
3471
3472 ies = IEs + _BEACON_IE_OFFSET_;
3473 ies_len = IELength - _BEACON_IE_OFFSET_;
3474
3475 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
3476
3477 while(p2p_ie)
3478 {
3479 find_p2p = true;
3480 /* Get Notice of Absence IE. */
3481 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, noa_attr, &attr_contentlen))
3482 {
3483 find_p2p_ps = true;
3484 noa_index = noa_attr[0];
3485
3486 if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
3487 (noa_index != pwdinfo->noa_index))/* if index change, driver should reconfigure related setting. */
3488 {
3489 pwdinfo->noa_index = noa_index;
3490 pwdinfo->opp_ps = noa_attr[1] >> 7;
3491 pwdinfo->ctwindow = noa_attr[1] & 0x7F;
3492
3493 noa_offset = 2;
3494 noa_num = 0;
3495 /* NoA length should be n*(13) + 2 */
3496 if (attr_contentlen > 2)
3497 {
3498 while(noa_offset < attr_contentlen)
3499 {
3500 /* memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */
3501 pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
3502 noa_offset += 1;
3503
3504 memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
3505 noa_offset += 4;
3506
3507 memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
3508 noa_offset += 4;
3509
3510 memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
3511 noa_offset += 4;
3512
3513 noa_num++;
3514 }
3515 }
3516 pwdinfo->noa_num = noa_num;
3517
3518 if (pwdinfo->opp_ps == 1)
3519 {
3520 pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
3521 /* driver should wait LPS for entering CTWindow */
3522 if (padapter->pwrctrlpriv.bFwCurrentInPSMode == true)
3523 {
3524 p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 1);
3525 }
3526 }
3527 else if (pwdinfo->noa_num > 0)
3528 {
3529 pwdinfo->p2p_ps_mode = P2P_PS_NOA;
3530 p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 1);
3531 }
3532 else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE)
3533 {
3534 p2p_ps_wk_cmd23a(padapter, P2P_PS_DISABLE, 1);
3535 }
3536 }
3537
3538 break; /* find target, just break. */
3539 }
3540
3541 /* Get the next P2P IE */
3542 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3543
3544 }
3545
3546 if (find_p2p == true)
3547 {
3548 if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && (find_p2p_ps == false))
3549 {
3550 p2p_ps_wk_cmd23a(padapter, P2P_PS_DISABLE, 1);
3551 }
3552 }
3553
3554
3555 }
3556
3557 void p2p_ps_wk_hdl23a(struct rtw_adapter *padapter, u8 p2p_ps_state)
3558 {
3559 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
3560 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3561
3562
3563
3564 /* Pre action for p2p state */
3565 switch (p2p_ps_state)
3566 {
3567 case P2P_PS_DISABLE:
3568 pwdinfo->p2p_ps_state = p2p_ps_state;
3569
3570 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
3571
3572 pwdinfo->noa_index = 0;
3573 pwdinfo->ctwindow = 0;
3574 pwdinfo->opp_ps = 0;
3575 pwdinfo->noa_num = 0;
3576 pwdinfo->p2p_ps_mode = P2P_PS_NONE;
3577 if (padapter->pwrctrlpriv.bFwCurrentInPSMode == true) {
3578 if (pwrpriv->smart_ps == 0) {
3579 pwrpriv->smart_ps = 2;
3580 rtl8723a_set_FwPwrMode_cmd(padapter, padapter->pwrctrlpriv.pwr_mode);
3581 }
3582 }
3583 break;
3584 case P2P_PS_ENABLE:
3585 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
3586 pwdinfo->p2p_ps_state = p2p_ps_state;
3587
3588 if (pwdinfo->ctwindow > 0) {
3589 if (pwrpriv->smart_ps != 0) {
3590 pwrpriv->smart_ps = 0;
3591 DBG_8723A("%s(): Enter CTW, change SmartPS\n", __func__);
3592 rtl8723a_set_FwPwrMode_cmd(padapter, padapter->pwrctrlpriv.pwr_mode);
3593 }
3594 }
3595 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
3596 }
3597 break;
3598 case P2P_PS_SCAN:
3599 case P2P_PS_SCAN_DONE:
3600 case P2P_PS_ALLSTASLEEP:
3601 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
3602 pwdinfo->p2p_ps_state = p2p_ps_state;
3603 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
3604 }
3605 break;
3606 default:
3607 break;
3608 }
3609
3610
3611 }
3612
3613 u8 p2p_ps_wk_cmd23a(struct rtw_adapter*padapter, u8 p2p_ps_state, u8 enqueue)
3614 {
3615 struct cmd_obj *ph2c;
3616 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3617 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3618 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3619 u8 res = _SUCCESS;
3620
3621
3622
3623 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3624 return res;
3625
3626 if (enqueue) {
3627 ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
3628 GFP_ATOMIC);
3629 if (!ph2c) {
3630 res = _FAIL;
3631 goto exit;
3632 }
3633
3634 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)
3635 kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
3636 if (pdrvextra_cmd_parm == NULL) {
3637 kfree(ph2c);
3638 res = _FAIL;
3639 goto exit;
3640 }
3641
3642 pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
3643 pdrvextra_cmd_parm->type_size = p2p_ps_state;
3644 pdrvextra_cmd_parm->pbuf = NULL;
3645
3646 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3647
3648 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
3649 }
3650 else
3651 {
3652 p2p_ps_wk_hdl23a(padapter, p2p_ps_state);
3653 }
3654
3655 exit:
3656
3657
3658
3659 return res;
3660 }
3661 #endif /* CONFIG_8723AU_P2P */
3662
3663 static void reset_ch_sitesurvey_timer_process(unsigned long data)
3664 {
3665 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3666 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3667
3668 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3669 return;
3670
3671 DBG_8723A("[%s] In\n", __func__);
3672 /* Reset the operation channel information */
3673 pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
3674 pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
3675 }
3676
3677 static void reset_ch_sitesurvey_timer_process2(unsigned long data)
3678 {
3679 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3680 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3681
3682 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3683 return;
3684
3685 DBG_8723A("[%s] In\n", __func__);
3686 /* Reset the operation channel information */
3687 pwdinfo->p2p_info.operation_ch[0] = 0;
3688 pwdinfo->p2p_info.scan_op_ch_only = 0;
3689 }
3690
3691 static void restore_p2p_state_timer_process (unsigned long data)
3692 {
3693 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3694 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3695
3696 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3697 return;
3698
3699 p2p_protocol_wk_cmd23a(adapter, P2P_RESTORE_STATE_WK);
3700 }
3701
3702 static void pre_tx_scan_timer_process (unsigned long data)
3703 {
3704 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3705 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3706 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
3707
3708 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3709 return;
3710
3711 spin_lock_bh(&pmlmepriv->lock);
3712
3713 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
3714 {
3715 if (true == pwdinfo->tx_prov_disc_info.benable) /* the provision discovery request frame is trigger to send or not */
3716 {
3717 p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK);
3718 /* issue23a_probereq_p2p(adapter, NULL); */
3719 /* _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); */
3720 }
3721 }
3722 else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
3723 {
3724 if (true == pwdinfo->nego_req_info.benable)
3725 {
3726 p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK);
3727 }
3728 }
3729 else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ))
3730 {
3731 if (true == pwdinfo->invitereq_info.benable)
3732 {
3733 p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK);
3734 }
3735 }
3736 else
3737 {
3738 DBG_8723A("[%s] p2p_state is %d, ignore!!\n", __func__, rtw_p2p_state(pwdinfo));
3739 }
3740
3741 spin_unlock_bh(&pmlmepriv->lock);
3742 }
3743
3744 static void find_phase_timer_process (unsigned long data)
3745 {
3746 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3747 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3748
3749 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3750 return;
3751
3752 adapter->wdinfo.find_phase_state_exchange_cnt++;
3753
3754 p2p_protocol_wk_cmd23a(adapter, P2P_FIND_PHASE_WK);
3755 }
3756
3757 void reset_global_wifidirect_info23a(struct rtw_adapter *padapter)
3758 {
3759 struct wifidirect_info *pwdinfo;
3760
3761 pwdinfo = &padapter->wdinfo;
3762 pwdinfo->persistent_supported = 0;
3763 pwdinfo->session_available = true;
3764 pwdinfo->wfd_tdls_enable = 0;
3765 pwdinfo->wfd_tdls_weaksec = 0;
3766 }
3767
3768 #ifdef CONFIG_8723AU_P2P
3769 int rtw_init_wifi_display_info(struct rtw_adapter* padapter)
3770 {
3771 int res = _SUCCESS;
3772 struct wifi_display_info *pwfd_info = &padapter->wfd_info;
3773
3774 /* Used in P2P and TDLS */
3775 pwfd_info->rtsp_ctrlport = 554;
3776 pwfd_info->peer_rtsp_ctrlport = 0; /* Reset to 0 */
3777 pwfd_info->wfd_enable = false;
3778 pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
3779 pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
3780
3781 /* Used in P2P */
3782 pwfd_info->peer_session_avail = true;
3783 pwfd_info->wfd_pc = false;
3784
3785 /* Used in TDLS */
3786 memset(pwfd_info->ip_address, 0x00, 4);
3787 memset(pwfd_info->peer_ip_address, 0x00, 4);
3788 return res;
3789 }
3790 #endif /* CONFIG_8723AU_P2P */
3791
3792 void rtw_init_wifidirect_timers23a(struct rtw_adapter* padapter)
3793 {
3794 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3795
3796 setup_timer(&pwdinfo->find_phase_timer, find_phase_timer_process,
3797 (unsigned long)padapter);
3798 setup_timer(&pwdinfo->restore_p2p_state_timer,
3799 restore_p2p_state_timer_process, (unsigned long)padapter);
3800 setup_timer(&pwdinfo->pre_tx_scan_timer, pre_tx_scan_timer_process,
3801 (unsigned long)padapter);
3802 setup_timer(&pwdinfo->reset_ch_sitesurvey,
3803 reset_ch_sitesurvey_timer_process, (unsigned long)padapter);
3804 setup_timer(&pwdinfo->reset_ch_sitesurvey2,
3805 reset_ch_sitesurvey_timer_process2,
3806 (unsigned long)padapter);
3807 }
3808
3809 void rtw_init_wifidirect_addrs23a(struct rtw_adapter* padapter, u8 *dev_addr, u8 *iface_addr)
3810 {
3811 #ifdef CONFIG_8723AU_P2P
3812 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3813
3814 /*init device&interface address */
3815 if (dev_addr) {
3816 memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
3817 }
3818 if (iface_addr) {
3819 memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
3820 }
3821 #endif
3822 }
3823
3824 void init_wifidirect_info23a(struct rtw_adapter *padapter, enum P2P_ROLE role)
3825 {
3826 struct wifidirect_info *pwdinfo;
3827 #ifdef CONFIG_8723AU_P2P
3828 struct wifi_display_info *pwfd_info = &padapter->wfd_info;
3829 #endif
3830
3831 pwdinfo = &padapter->wdinfo;
3832
3833 pwdinfo->padapter = padapter;
3834
3835 /* 1, 6, 11 are the social channel defined in the WiFi Direct specification. */
3836 pwdinfo->social_chan[0] = 1;
3837 pwdinfo->social_chan[1] = 6;
3838 pwdinfo->social_chan[2] = 11;
3839 pwdinfo->social_chan[3] = 0; /* channel 0 for scanning ending in site survey function. */
3840
3841 /* Use the channel 11 as the listen channel */
3842 pwdinfo->listen_channel = 11;
3843
3844 if (role == P2P_ROLE_DEVICE)
3845 {
3846 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3847 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3848 pwdinfo->intent = 1;
3849 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
3850 }
3851 else if (role == P2P_ROLE_CLIENT)
3852 {
3853 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3854 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3855 pwdinfo->intent = 1;
3856 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3857 }
3858 else if (role == P2P_ROLE_GO)
3859 {
3860 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3861 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3862 pwdinfo->intent = 15;
3863 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3864 }
3865
3866 /* Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
3867 pwdinfo->support_rate[0] = 0x8c; /* 6(B) */
3868 pwdinfo->support_rate[1] = 0x92; /* 9(B) */
3869 pwdinfo->support_rate[2] = 0x18; /* 12 */
3870 pwdinfo->support_rate[3] = 0x24; /* 18 */
3871 pwdinfo->support_rate[4] = 0x30; /* 24 */
3872 pwdinfo->support_rate[5] = 0x48; /* 36 */
3873 pwdinfo->support_rate[6] = 0x60; /* 48 */
3874 pwdinfo->support_rate[7] = 0x6c; /* 54 */
3875
3876 memcpy((void*) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);
3877
3878 memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
3879 pwdinfo->device_name_len = 0;
3880
3881 memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info));
3882 pwdinfo->invitereq_info.token = 3; /* Token used for P2P invitation request frame. */
3883
3884 memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info));
3885 pwdinfo->inviteresp_info.token = 0;
3886
3887 pwdinfo->profileindex = 0;
3888 memset(&pwdinfo->profileinfo[ 0 ], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
3889
3890 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
3891
3892 pwdinfo->listen_dwell = (u8) ((jiffies % 3) + 1);
3893 /* DBG_8723A("[%s] listen_dwell time is %d00ms\n", __func__, pwdinfo->listen_dwell); */
3894
3895 memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info));
3896 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
3897
3898 memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
3899
3900 pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
3901 pwdinfo->negotiation_dialog_token = 1;
3902
3903 memset(pwdinfo->nego_ssid, 0x00, IEEE80211_MAX_SSID_LEN);
3904 pwdinfo->nego_ssidlen = 0;
3905
3906 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
3907 #ifdef CONFIG_8723AU_P2P
3908 pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC;
3909 pwdinfo->wfd_info = pwfd_info;
3910 #else
3911 pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
3912 #endif /* CONFIG_8723AU_P2P */
3913 pwdinfo->channel_list_attr_len = 0;
3914 memset(pwdinfo->channel_list_attr, 0x00, 100);
3915
3916 memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4);
3917 memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3);
3918 memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
3919 pwdinfo->wfd_tdls_enable = 0;
3920 memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
3921 memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN);
3922
3923 pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
3924 pwdinfo->rx_invitereq_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
3925 pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
3926 pwdinfo->p2p_info.operation_ch[0] = 0;
3927 pwdinfo->p2p_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
3928 pwdinfo->p2p_info.scan_op_ch_only = 0;
3929 }
3930
3931 int rtw_p2p_enable23a(struct rtw_adapter *padapter, enum P2P_ROLE role)
3932 {
3933 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3934 int ret = _SUCCESS;
3935
3936 if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT ||
3937 role == P2P_ROLE_GO) {
3938 /* leave IPS/Autosuspend */
3939 if (_FAIL == rtw_pwr_wakeup(padapter)) {
3940 ret = _FAIL;
3941 goto exit;
3942 }
3943
3944 /* Added by Albert 2011/03/22 */
3945 /* In the P2P mode, the driver should not support the b mode. */
3946 /* So, the Tx packet shouldn't use the CCK rate */
3947 update_tx_basic_rate23a(padapter, WIRELESS_11AGN);
3948
3949 /* Enable P2P function */
3950 init_wifidirect_info23a(padapter, role);
3951
3952 rtw_hal_set_odm_var23a(padapter, HAL_ODM_P2P_STATE, NULL, true);
3953 #ifdef CONFIG_8723AU_P2P
3954 rtw_hal_set_odm_var23a(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, true);
3955 #endif
3956
3957 }
3958 else if (role == P2P_ROLE_DISABLE)
3959 {
3960 if (_FAIL == rtw_pwr_wakeup(padapter)) {
3961 ret = _FAIL;
3962 goto exit;
3963 }
3964
3965 /* Disable P2P function */
3966 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3967 {
3968 del_timer_sync(&pwdinfo->find_phase_timer);
3969 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
3970 del_timer_sync(&pwdinfo->pre_tx_scan_timer);
3971 del_timer_sync(&pwdinfo->reset_ch_sitesurvey);
3972 del_timer_sync(&pwdinfo->reset_ch_sitesurvey2);
3973 reset_ch_sitesurvey_timer_process((unsigned long)padapter);
3974 reset_ch_sitesurvey_timer_process2((unsigned long)padapter);
3975 rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
3976 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
3977 memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
3978 }
3979
3980 rtw_hal_set_odm_var23a(padapter, HAL_ODM_P2P_STATE, NULL, false);
3981 #ifdef CONFIG_8723AU_P2P
3982 rtw_hal_set_odm_var23a(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, false);
3983 #endif
3984
3985 /* Restore to initial setting. */
3986 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
3987 }
3988
3989 exit:
3990 return ret;
3991 }
3992
3993 #endif /* CONFIG_8723AU_P2P */