1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2017 Realtek Corporation.
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
19 #ifdef CONFIG_P2P
20
rtw_p2p_is_channel_list_ok(u8 desired_ch,u8 * ch_list,u8 ch_cnt)21 int rtw_p2p_is_channel_list_ok(u8 desired_ch, u8 *ch_list, u8 ch_cnt)
22 {
23 int found = 0, i = 0;
24
25 for (i = 0; i < ch_cnt; i++) {
26 if (ch_list[i] == desired_ch) {
27 found = 1;
28 break;
29 }
30 }
31 return found ;
32 }
33
is_any_client_associated(_adapter * padapter)34 int is_any_client_associated(_adapter *padapter)
35 {
36 return padapter->stapriv.asoc_list_cnt ? _TRUE : _FALSE;
37 }
38
go_add_group_info_attr(struct wifidirect_info * pwdinfo,u8 * pbuf)39 static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
40 {
41 _irqL irqL;
42 _list *phead, *plist;
43 u32 len = 0;
44 u16 attr_len = 0;
45 u8 tmplen, *pdata_attr, *pstart, *pcur;
46 struct sta_info *psta = NULL;
47 _adapter *padapter = pwdinfo->padapter;
48 struct sta_priv *pstapriv = &padapter->stapriv;
49
50 RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
51
52 pdata_attr = rtw_zmalloc(MAX_P2P_IE_LEN);
53
54 if (NULL == pdata_attr) {
55 RTW_INFO("%s pdata_attr malloc failed\n", __FUNCTION__);
56 goto _exit;
57 }
58
59 pstart = pdata_attr;
60 pcur = pdata_attr;
61
62 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
63 phead = &pstapriv->asoc_list;
64 plist = get_next(phead);
65
66 /* look up sta asoc_queue */
67 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
68 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
69
70 plist = get_next(plist);
71
72
73 if (psta->is_p2p_device) {
74 tmplen = 0;
75
76 pcur++;
77
78 /* P2P device address */
79 _rtw_memcpy(pcur, psta->dev_addr, ETH_ALEN);
80 pcur += ETH_ALEN;
81
82 /* P2P interface address */
83 _rtw_memcpy(pcur, psta->cmn.mac_addr, ETH_ALEN);
84 pcur += ETH_ALEN;
85
86 *pcur = psta->dev_cap;
87 pcur++;
88
89 /* *(u16*)(pcur) = cpu_to_be16(psta->config_methods); */
90 RTW_PUT_BE16(pcur, psta->config_methods);
91 pcur += 2;
92
93 _rtw_memcpy(pcur, psta->primary_dev_type, 8);
94 pcur += 8;
95
96 *pcur = psta->num_of_secdev_type;
97 pcur++;
98
99 _rtw_memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type * 8);
100 pcur += psta->num_of_secdev_type * 8;
101
102 if (psta->dev_name_len > 0) {
103 /* *(u16*)(pcur) = cpu_to_be16( WPS_ATTR_DEVICE_NAME ); */
104 RTW_PUT_BE16(pcur, WPS_ATTR_DEVICE_NAME);
105 pcur += 2;
106
107 /* *(u16*)(pcur) = cpu_to_be16( psta->dev_name_len ); */
108 RTW_PUT_BE16(pcur, psta->dev_name_len);
109 pcur += 2;
110
111 _rtw_memcpy(pcur, psta->dev_name, psta->dev_name_len);
112 pcur += psta->dev_name_len;
113 }
114
115
116 tmplen = (u8)(pcur - pstart);
117
118 *pstart = (tmplen - 1);
119
120 attr_len += tmplen;
121
122 /* pstart += tmplen; */
123 pstart = pcur;
124
125 }
126
127
128 }
129 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
130
131 if (attr_len > 0)
132 len = rtw_set_p2p_attr_content(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);
133
134 rtw_mfree(pdata_attr, MAX_P2P_IE_LEN);
135
136 _exit:
137 return len;
138
139 }
140
issue_group_disc_req(struct wifidirect_info * pwdinfo,u8 * da)141 static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)
142 {
143 struct xmit_frame *pmgntframe;
144 struct pkt_attrib *pattrib;
145 unsigned char *pframe;
146 struct rtw_ieee80211_hdr *pwlanhdr;
147 unsigned short *fctrl;
148 _adapter *padapter = pwdinfo->padapter;
149 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
150 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
151 unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */
152 u32 p2poui = cpu_to_be32(P2POUI);
153 u8 oui_subtype = P2P_GO_DISC_REQUEST;
154 u8 dialogToken = 0;
155
156 RTW_INFO("[%s]\n", __FUNCTION__);
157
158 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
159 if (pmgntframe == NULL)
160 return;
161
162 /* update attribute */
163 pattrib = &pmgntframe->attrib;
164 update_mgntframe_attrib(padapter, pattrib);
165
166 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
167
168 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
169 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
170
171 fctrl = &(pwlanhdr->frame_ctl);
172 *(fctrl) = 0;
173
174 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
175 _rtw_memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
176 _rtw_memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
177
178 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
179 pmlmeext->mgnt_seq++;
180 set_frame_sub_type(pframe, WIFI_ACTION);
181
182 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
183 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
184
185 /* Build P2P action frame header */
186 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
187 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
188 pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
189 pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
190
191 /* there is no IE in this P2P action frame */
192
193 pattrib->last_txcmdsz = pattrib->pktlen;
194
195 dump_mgntframe(padapter, pmgntframe);
196
197 }
198
issue_p2p_devdisc_resp(struct wifidirect_info * pwdinfo,u8 * da,u8 status,u8 dialogToken)199 static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
200 {
201 struct xmit_frame *pmgntframe;
202 struct pkt_attrib *pattrib;
203 unsigned char *pframe;
204 struct rtw_ieee80211_hdr *pwlanhdr;
205 unsigned short *fctrl;
206 _adapter *padapter = pwdinfo->padapter;
207 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
208 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
209 unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
210 u8 action = P2P_PUB_ACTION_ACTION;
211 u32 p2poui = cpu_to_be32(P2POUI);
212 u8 oui_subtype = P2P_DEVDISC_RESP;
213 u8 p2pie[8] = { 0x00 };
214 u32 p2pielen = 0;
215
216 RTW_INFO("[%s]\n", __FUNCTION__);
217
218 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
219 if (pmgntframe == NULL)
220 return;
221
222 /* update attribute */
223 pattrib = &pmgntframe->attrib;
224 update_mgntframe_attrib(padapter, pattrib);
225
226 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
227
228 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
229 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
230
231 fctrl = &(pwlanhdr->frame_ctl);
232 *(fctrl) = 0;
233
234 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
235 _rtw_memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);
236 _rtw_memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);
237
238 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
239 pmlmeext->mgnt_seq++;
240 set_frame_sub_type(pframe, WIFI_ACTION);
241
242 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
243 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
244
245 /* Build P2P public action frame header */
246 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
247 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
248 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
249 pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
250 pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
251
252
253 /* Build P2P IE */
254 /* P2P OUI */
255 p2pielen = 0;
256 p2pie[p2pielen++] = 0x50;
257 p2pie[p2pielen++] = 0x6F;
258 p2pie[p2pielen++] = 0x9A;
259 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
260
261 /* P2P_ATTR_STATUS */
262 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
263
264 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
265
266 pattrib->last_txcmdsz = pattrib->pktlen;
267
268 dump_mgntframe(padapter, pmgntframe);
269
270 }
271
issue_p2p_provision_resp(struct wifidirect_info * pwdinfo,u8 * raddr,u8 * frame_body,u16 config_method)272 static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8 *raddr, u8 *frame_body, u16 config_method)
273 {
274 _adapter *padapter = pwdinfo->padapter;
275 unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
276 u8 action = P2P_PUB_ACTION_ACTION;
277 u8 dialogToken = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */
278 u32 p2poui = cpu_to_be32(P2POUI);
279 u8 oui_subtype = P2P_PROVISION_DISC_RESP;
280 u8 wpsie[100] = { 0x00 };
281 u8 wpsielen = 0;
282 #ifdef CONFIG_WFD
283 u32 wfdielen = 0;
284 #endif
285
286 struct xmit_frame *pmgntframe;
287 struct pkt_attrib *pattrib;
288 unsigned char *pframe;
289 struct rtw_ieee80211_hdr *pwlanhdr;
290 unsigned short *fctrl;
291 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
292 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
293
294
295 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
296 if (pmgntframe == NULL)
297 return;
298
299 /* update attribute */
300 pattrib = &pmgntframe->attrib;
301 update_mgntframe_attrib(padapter, pattrib);
302
303 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
304
305 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
306 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
307
308 fctrl = &(pwlanhdr->frame_ctl);
309 *(fctrl) = 0;
310
311 _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
312 _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
313 _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
314
315 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
316 pmlmeext->mgnt_seq++;
317 set_frame_sub_type(pframe, WIFI_ACTION);
318
319 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
320 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
321
322 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
323 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
324 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
325 pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
326 pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
327
328 wpsielen = 0;
329 /* WPS OUI */
330 /* *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI ); */
331 RTW_PUT_BE32(wpsie, WPSOUI);
332 wpsielen += 4;
333
334 #if 0
335 /* WPS version */
336 /* Type: */
337 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
338 wpsielen += 2;
339
340 /* Length: */
341 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
342 wpsielen += 2;
343
344 /* Value: */
345 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
346 #endif
347
348 /* Config Method */
349 /* Type: */
350 /* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD ); */
351 RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD);
352 wpsielen += 2;
353
354 /* Length: */
355 /* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 ); */
356 RTW_PUT_BE16(wpsie + wpsielen, 0x0002);
357 wpsielen += 2;
358
359 /* Value: */
360 /* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( config_method ); */
361 RTW_PUT_BE16(wpsie + wpsielen, config_method);
362 wpsielen += 2;
363
364 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
365
366 #ifdef CONFIG_WFD
367 wfdielen = build_provdisc_resp_wfd_ie(pwdinfo, pframe);
368 pframe += wfdielen;
369 pattrib->pktlen += wfdielen;
370 #endif
371
372 pattrib->last_txcmdsz = pattrib->pktlen;
373
374 dump_mgntframe(padapter, pmgntframe);
375
376 return;
377
378 }
379
issue_p2p_presence_resp(struct wifidirect_info * pwdinfo,u8 * da,u8 status,u8 dialogToken)380 static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
381 {
382 struct xmit_frame *pmgntframe;
383 struct pkt_attrib *pattrib;
384 unsigned char *pframe;
385 struct rtw_ieee80211_hdr *pwlanhdr;
386 unsigned short *fctrl;
387 _adapter *padapter = pwdinfo->padapter;
388 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
389 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
390 unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */
391 u32 p2poui = cpu_to_be32(P2POUI);
392 u8 oui_subtype = P2P_PRESENCE_RESPONSE;
393 u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
394 u8 noa_attr_content[32] = { 0x00 };
395 u32 p2pielen = 0;
396
397 RTW_INFO("[%s]\n", __FUNCTION__);
398
399 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
400 if (pmgntframe == NULL)
401 return;
402
403 /* update attribute */
404 pattrib = &pmgntframe->attrib;
405 update_mgntframe_attrib(padapter, pattrib);
406
407 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
408
409 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
410 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
411
412 fctrl = &(pwlanhdr->frame_ctl);
413 *(fctrl) = 0;
414
415 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
416 _rtw_memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
417 _rtw_memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
418
419 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
420 pmlmeext->mgnt_seq++;
421 set_frame_sub_type(pframe, WIFI_ACTION);
422
423 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
424 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
425
426 /* Build P2P action frame header */
427 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
428 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
429 pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
430 pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
431
432
433 /* Add P2P IE header */
434 /* P2P OUI */
435 p2pielen = 0;
436 p2pie[p2pielen++] = 0x50;
437 p2pie[p2pielen++] = 0x6F;
438 p2pie[p2pielen++] = 0x9A;
439 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
440
441 /* Add Status attribute in P2P IE */
442 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
443
444 /* Add NoA attribute in P2P IE */
445 noa_attr_content[0] = 0x1;/* index */
446 noa_attr_content[1] = 0x0;/* CTWindow and OppPS Parameters */
447
448 /* todo: Notice of Absence Descriptor(s) */
449
450 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);
451
452
453
454 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &(pattrib->pktlen));
455
456
457 pattrib->last_txcmdsz = pattrib->pktlen;
458
459 dump_mgntframe(padapter, pmgntframe);
460
461 }
462
build_beacon_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)463 u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
464 {
465 u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
466 u16 capability = 0;
467 u32 len = 0, p2pielen = 0;
468
469
470 /* P2P OUI */
471 p2pielen = 0;
472 p2pie[p2pielen++] = 0x50;
473 p2pie[p2pielen++] = 0x6F;
474 p2pie[p2pielen++] = 0x9A;
475 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
476
477
478 /* According to the P2P Specification, the beacon frame should contain 3 P2P attributes */
479 /* 1. P2P Capability */
480 /* 2. P2P Device ID */
481 /* 3. Notice of Absence ( NOA ) */
482
483 /* P2P Capability ATTR */
484 /* Type: */
485 /* Length: */
486 /* Value: */
487 /* Device Capability Bitmap, 1 byte */
488 /* Be able to participate in additional P2P Groups and */
489 /* support the P2P Invitation Procedure */
490 /* Group Capability Bitmap, 1 byte */
491 capability = P2P_DEVCAP_INVITATION_PROC | P2P_DEVCAP_CLIENT_DISCOVERABILITY;
492 capability |= ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);
493 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
494 capability |= (P2P_GRPCAP_GROUP_FORMATION << 8);
495
496 capability = cpu_to_le16(capability);
497
498 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8 *)&capability);
499
500
501 /* P2P Device ID ATTR */
502 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);
503
504
505 /* Notice of Absence ATTR */
506 /* Type: */
507 /* Length: */
508 /* Value: */
509
510 /* go_add_noa_attr(pwdinfo); */
511
512
513 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
514
515
516 return len;
517
518 }
519
520 #ifdef CONFIG_WFD
build_beacon_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)521 u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
522 {
523 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
524 u16 val16 = 0;
525 u32 len = 0, wfdielen = 0;
526 _adapter *padapter = pwdinfo->padapter;
527 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
528 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
529
530 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
531 goto exit;
532
533 /* WFD OUI */
534 wfdielen = 0;
535 wfdie[wfdielen++] = 0x50;
536 wfdie[wfdielen++] = 0x6F;
537 wfdie[wfdielen++] = 0x9A;
538 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
539
540 /* Commented by Albert 20110812 */
541 /* According to the WFD Specification, the beacon frame should contain 4 WFD attributes */
542 /* 1. WFD Device Information */
543 /* 2. Associated BSSID */
544 /* 3. Coupled Sink Information */
545
546
547 /* WFD Device Information ATTR */
548 /* Type: */
549 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
550
551 /* Length: */
552 /* Note: In the WFD specification, the size of length field is 2. */
553 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
554 wfdielen += 2;
555
556 /* Value1: */
557 /* WFD device information */
558
559 if (P2P_ROLE_GO == pwdinfo->role) {
560 if (is_any_client_associated(pwdinfo->padapter)) {
561 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) */
562 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD;
563 RTW_PUT_BE16(wfdie + wfdielen, val16);
564 } else {
565 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
566 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
567 RTW_PUT_BE16(wfdie + wfdielen, val16);
568 }
569
570 } else {
571 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
572 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
573 RTW_PUT_BE16(wfdie + wfdielen, val16);
574 }
575
576 wfdielen += 2;
577
578 /* Value2: */
579 /* Session Management Control Port */
580 /* Default TCP port for RTSP messages is 554 */
581 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
582 wfdielen += 2;
583
584 /* Value3: */
585 /* WFD Device Maximum Throughput */
586 /* 300Mbps is the maximum throughput */
587 RTW_PUT_BE16(wfdie + wfdielen, 300);
588 wfdielen += 2;
589
590 /* Associated BSSID ATTR */
591 /* Type: */
592 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
593
594 /* Length: */
595 /* Note: In the WFD specification, the size of length field is 2. */
596 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
597 wfdielen += 2;
598
599 /* Value: */
600 /* Associated BSSID */
601 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
602 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
603 else
604 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
605
606 wfdielen += ETH_ALEN;
607
608 /* Coupled Sink Information ATTR */
609 /* Type: */
610 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
611
612 /* Length: */
613 /* Note: In the WFD specification, the size of length field is 2. */
614 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
615 wfdielen += 2;
616
617 /* Value: */
618 /* Coupled Sink Status bitmap */
619 /* Not coupled/available for Coupling */
620 wfdie[wfdielen++] = 0;
621 /* MAC Addr. */
622 wfdie[wfdielen++] = 0;
623 wfdie[wfdielen++] = 0;
624 wfdie[wfdielen++] = 0;
625 wfdie[wfdielen++] = 0;
626 wfdie[wfdielen++] = 0;
627 wfdie[wfdielen++] = 0;
628
629 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
630
631 exit:
632 return len;
633 }
634
build_probe_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)635 u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
636 {
637 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
638 u16 val16 = 0;
639 u32 len = 0, wfdielen = 0;
640 _adapter *padapter = pwdinfo->padapter;
641 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
642 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
643
644 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
645 goto exit;
646
647 /* WFD OUI */
648 wfdielen = 0;
649 wfdie[wfdielen++] = 0x50;
650 wfdie[wfdielen++] = 0x6F;
651 wfdie[wfdielen++] = 0x9A;
652 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
653
654 /* Commented by Albert 20110812 */
655 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
656 /* 1. WFD Device Information */
657 /* 2. Associated BSSID */
658 /* 3. Coupled Sink Information */
659
660
661 /* WFD Device Information ATTR */
662 /* Type: */
663 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
664
665 /* Length: */
666 /* Note: In the WFD specification, the size of length field is 2. */
667 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
668 wfdielen += 2;
669
670 /* Value1: */
671 /* WFD device information */
672
673 if (1 == pwdinfo->wfd_tdls_enable) {
674 /* WFD primary sink + available for WFD session + WiFi TDLS mode + WSC ( WFD Service Discovery ) */
675 val16 = pwfd_info->wfd_device_type |
676 WFD_DEVINFO_SESSION_AVAIL |
677 WFD_DEVINFO_WSD |
678 WFD_DEVINFO_PC_TDLS;
679 RTW_PUT_BE16(wfdie + wfdielen, val16);
680 } else {
681 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSC ( WFD Service Discovery ) */
682 val16 = pwfd_info->wfd_device_type |
683 WFD_DEVINFO_SESSION_AVAIL |
684 WFD_DEVINFO_WSD;
685 RTW_PUT_BE16(wfdie + wfdielen, val16);
686 }
687
688 wfdielen += 2;
689
690 /* Value2: */
691 /* Session Management Control Port */
692 /* Default TCP port for RTSP messages is 554 */
693 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
694 wfdielen += 2;
695
696 /* Value3: */
697 /* WFD Device Maximum Throughput */
698 /* 300Mbps is the maximum throughput */
699 RTW_PUT_BE16(wfdie + wfdielen, 300);
700 wfdielen += 2;
701
702 /* Associated BSSID ATTR */
703 /* Type: */
704 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
705
706 /* Length: */
707 /* Note: In the WFD specification, the size of length field is 2. */
708 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
709 wfdielen += 2;
710
711 /* Value: */
712 /* Associated BSSID */
713 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
714 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
715 else
716 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
717
718 wfdielen += ETH_ALEN;
719
720 /* Coupled Sink Information ATTR */
721 /* Type: */
722 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
723
724 /* Length: */
725 /* Note: In the WFD specification, the size of length field is 2. */
726 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
727 wfdielen += 2;
728
729 /* Value: */
730 /* Coupled Sink Status bitmap */
731 /* Not coupled/available for Coupling */
732 wfdie[wfdielen++] = 0;
733 /* MAC Addr. */
734 wfdie[wfdielen++] = 0;
735 wfdie[wfdielen++] = 0;
736 wfdie[wfdielen++] = 0;
737 wfdie[wfdielen++] = 0;
738 wfdie[wfdielen++] = 0;
739 wfdie[wfdielen++] = 0;
740
741 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
742
743 exit:
744 return len;
745 }
746
build_probe_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf,u8 tunneled)747 u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 tunneled)
748 {
749 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
750 u32 len = 0, wfdielen = 0;
751 _adapter *padapter = pwdinfo->padapter;
752 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
753 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
754 u16 v16 = 0;
755
756 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
757 goto exit;
758
759 /* WFD OUI */
760 wfdielen = 0;
761 wfdie[wfdielen++] = 0x50;
762 wfdie[wfdielen++] = 0x6F;
763 wfdie[wfdielen++] = 0x9A;
764 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
765
766 /* Commented by Albert 20110812 */
767 /* According to the WFD Specification, the probe response frame should contain 4 WFD attributes */
768 /* 1. WFD Device Information */
769 /* 2. Associated BSSID */
770 /* 3. Coupled Sink Information */
771 /* 4. WFD Session Information */
772
773
774 /* WFD Device Information ATTR */
775 /* Type: */
776 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
777
778 /* Length: */
779 /* Note: In the WFD specification, the size of length field is 2. */
780 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
781 wfdielen += 2;
782
783 /* Value1: */
784 /* WFD device information */
785 /* WFD primary sink + available for WFD session + WiFi Direct mode */
786
787 if (_TRUE == pwdinfo->session_available) {
788 if (P2P_ROLE_GO == pwdinfo->role) {
789 if (is_any_client_associated(pwdinfo->padapter)) {
790 if (pwdinfo->wfd_tdls_enable) {
791 /* TDLS mode + WSD ( WFD Service Discovery ) */
792 v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT;
793 RTW_PUT_BE16(wfdie + wfdielen, v16);
794 } else {
795 /* WiFi Direct mode + WSD ( WFD Service Discovery ) */
796 v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT;
797 RTW_PUT_BE16(wfdie + wfdielen, v16);
798 }
799 } else {
800 if (pwdinfo->wfd_tdls_enable) {
801 /* available for WFD session + TDLS mode + WSD ( WFD Service Discovery ) */
802 v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT;
803 RTW_PUT_BE16(wfdie + wfdielen, v16);
804 } else {
805 /* available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
806 v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT;
807 RTW_PUT_BE16(wfdie + wfdielen, v16);
808 }
809 }
810 } else {
811 if (pwdinfo->wfd_tdls_enable) {
812 /* available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
813 v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT;
814 RTW_PUT_BE16(wfdie + wfdielen, v16);
815 } else {
816 /* available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
817 v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT;
818 RTW_PUT_BE16(wfdie + wfdielen, v16);
819 }
820 }
821 } else {
822 if (pwdinfo->wfd_tdls_enable) {
823 v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT;
824 RTW_PUT_BE16(wfdie + wfdielen, v16);
825 } else {
826 v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT;
827 RTW_PUT_BE16(wfdie + wfdielen, v16);
828 }
829 }
830
831 wfdielen += 2;
832
833 /* Value2: */
834 /* Session Management Control Port */
835 /* Default TCP port for RTSP messages is 554 */
836 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
837 wfdielen += 2;
838
839 /* Value3: */
840 /* WFD Device Maximum Throughput */
841 /* 300Mbps is the maximum throughput */
842 RTW_PUT_BE16(wfdie + wfdielen, 300);
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 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
852 wfdielen += 2;
853
854 /* Value: */
855 /* Associated BSSID */
856 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
857 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
858 else
859 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
860
861 wfdielen += ETH_ALEN;
862
863 /* Coupled Sink Information ATTR */
864 /* Type: */
865 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
866
867 /* Length: */
868 /* Note: In the WFD specification, the size of length field is 2. */
869 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
870 wfdielen += 2;
871
872 /* Value: */
873 /* Coupled Sink Status bitmap */
874 /* Not coupled/available for Coupling */
875 wfdie[wfdielen++] = 0;
876 /* MAC Addr. */
877 wfdie[wfdielen++] = 0;
878 wfdie[wfdielen++] = 0;
879 wfdie[wfdielen++] = 0;
880 wfdie[wfdielen++] = 0;
881 wfdie[wfdielen++] = 0;
882 wfdie[wfdielen++] = 0;
883
884 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
885 /* WFD Session Information ATTR */
886 /* Type: */
887 wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;
888
889 /* Length: */
890 /* Note: In the WFD specification, the size of length field is 2. */
891 RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
892 wfdielen += 2;
893
894 /* Todo: to add the list of WFD device info descriptor in WFD group. */
895
896 }
897 #ifdef CONFIG_CONCURRENT_MODE
898 #ifdef CONFIG_TDLS
899 {
900 int i;
901 _adapter *iface = NULL;
902 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
903
904 for (i = 0; i < dvobj->iface_nums; i++) {
905 iface = dvobj->padapters[i];
906 if ((iface) && rtw_is_adapter_up(iface)) {
907 if (iface == padapter)
908 continue;
909
910 if ((tunneled == 0) && (iface->wdinfo.wfd_tdls_enable == 1)) {
911 /* Alternative MAC Address ATTR
912 Type: */
913 wfdie[wfdielen++] = WFD_ATTR_ALTER_MAC;
914
915 /* Length:
916 Note: In the WFD specification, the size of length field is 2.*/
917 RTW_PUT_BE16(wfdie + wfdielen, ETH_ALEN);
918 wfdielen += 2;
919
920 /* Value:
921 Alternative MAC Address*/
922 _rtw_memcpy(wfdie + wfdielen, adapter_mac_addr(iface), ETH_ALEN);
923 wfdielen += ETH_ALEN;
924 }
925 }
926 }
927 }
928
929 #endif /* CONFIG_TDLS*/
930 #endif /* CONFIG_CONCURRENT_MODE */
931
932 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
933
934 exit:
935 return len;
936 }
937
build_assoc_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)938 u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
939 {
940 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
941 u16 val16 = 0;
942 u32 len = 0, wfdielen = 0;
943 _adapter *padapter = NULL;
944 struct mlme_priv *pmlmepriv = NULL;
945 struct wifi_display_info *pwfd_info = NULL;
946
947 padapter = pwdinfo->padapter;
948 pmlmepriv = &padapter->mlmepriv;
949 pwfd_info = padapter->wdinfo.wfd_info;
950
951 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
952 goto exit;
953
954 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
955 goto exit;
956
957 /* WFD OUI */
958 wfdielen = 0;
959 wfdie[wfdielen++] = 0x50;
960 wfdie[wfdielen++] = 0x6F;
961 wfdie[wfdielen++] = 0x9A;
962 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
963
964 /* Commented by Albert 20110812 */
965 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
966 /* 1. WFD Device Information */
967 /* 2. Associated BSSID */
968 /* 3. Coupled Sink Information */
969
970
971 /* WFD Device Information ATTR */
972 /* Type: */
973 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
974
975 /* Length: */
976 /* Note: In the WFD specification, the size of length field is 2. */
977 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
978 wfdielen += 2;
979
980 /* Value1: */
981 /* WFD device information */
982 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
983 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
984 RTW_PUT_BE16(wfdie + wfdielen, val16);
985 wfdielen += 2;
986
987 /* Value2: */
988 /* Session Management Control Port */
989 /* Default TCP port for RTSP messages is 554 */
990 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
991 wfdielen += 2;
992
993 /* Value3: */
994 /* WFD Device Maximum Throughput */
995 /* 300Mbps is the maximum throughput */
996 RTW_PUT_BE16(wfdie + wfdielen, 300);
997 wfdielen += 2;
998
999 /* Associated BSSID ATTR */
1000 /* Type: */
1001 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1002
1003 /* Length: */
1004 /* Note: In the WFD specification, the size of length field is 2. */
1005 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1006 wfdielen += 2;
1007
1008 /* Value: */
1009 /* Associated BSSID */
1010 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1011 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1012 else
1013 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1014
1015 wfdielen += ETH_ALEN;
1016
1017 /* Coupled Sink Information ATTR */
1018 /* Type: */
1019 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1020
1021 /* Length: */
1022 /* Note: In the WFD specification, the size of length field is 2. */
1023 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1024 wfdielen += 2;
1025
1026 /* Value: */
1027 /* Coupled Sink Status bitmap */
1028 /* Not coupled/available for Coupling */
1029 wfdie[wfdielen++] = 0;
1030 /* MAC Addr. */
1031 wfdie[wfdielen++] = 0;
1032 wfdie[wfdielen++] = 0;
1033 wfdie[wfdielen++] = 0;
1034 wfdie[wfdielen++] = 0;
1035 wfdie[wfdielen++] = 0;
1036 wfdie[wfdielen++] = 0;
1037
1038 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1039
1040 exit:
1041 return len;
1042 }
1043
build_assoc_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1044 u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1045 {
1046 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1047 u32 len = 0, wfdielen = 0;
1048 u16 val16 = 0;
1049 _adapter *padapter = pwdinfo->padapter;
1050 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1051 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1052
1053 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1054 goto exit;
1055
1056 /* WFD OUI */
1057 wfdielen = 0;
1058 wfdie[wfdielen++] = 0x50;
1059 wfdie[wfdielen++] = 0x6F;
1060 wfdie[wfdielen++] = 0x9A;
1061 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1062
1063 /* Commented by Albert 20110812 */
1064 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
1065 /* 1. WFD Device Information */
1066 /* 2. Associated BSSID */
1067 /* 3. Coupled Sink Information */
1068
1069
1070 /* WFD Device Information ATTR */
1071 /* Type: */
1072 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1073
1074 /* Length: */
1075 /* Note: In the WFD specification, the size of length field is 2. */
1076 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1077 wfdielen += 2;
1078
1079 /* Value1: */
1080 /* WFD device information */
1081 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1082 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1083 RTW_PUT_BE16(wfdie + wfdielen, val16);
1084 wfdielen += 2;
1085
1086 /* Value2: */
1087 /* Session Management Control Port */
1088 /* Default TCP port for RTSP messages is 554 */
1089 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1090 wfdielen += 2;
1091
1092 /* Value3: */
1093 /* WFD Device Maximum Throughput */
1094 /* 300Mbps is the maximum throughput */
1095 RTW_PUT_BE16(wfdie + wfdielen, 300);
1096 wfdielen += 2;
1097
1098 /* Associated BSSID ATTR */
1099 /* Type: */
1100 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1101
1102 /* Length: */
1103 /* Note: In the WFD specification, the size of length field is 2. */
1104 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1105 wfdielen += 2;
1106
1107 /* Value: */
1108 /* Associated BSSID */
1109 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1110 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1111 else
1112 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1113
1114 wfdielen += ETH_ALEN;
1115
1116 /* Coupled Sink Information ATTR */
1117 /* Type: */
1118 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1119
1120 /* Length: */
1121 /* Note: In the WFD specification, the size of length field is 2. */
1122 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1123 wfdielen += 2;
1124
1125 /* Value: */
1126 /* Coupled Sink Status bitmap */
1127 /* Not coupled/available for Coupling */
1128 wfdie[wfdielen++] = 0;
1129 /* MAC Addr. */
1130 wfdie[wfdielen++] = 0;
1131 wfdie[wfdielen++] = 0;
1132 wfdie[wfdielen++] = 0;
1133 wfdie[wfdielen++] = 0;
1134 wfdie[wfdielen++] = 0;
1135 wfdie[wfdielen++] = 0;
1136
1137 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1138
1139 exit:
1140 return len;
1141 }
1142
build_nego_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1143 u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1144 {
1145 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1146 u32 len = 0, wfdielen = 0;
1147 u16 val16 = 0;
1148 _adapter *padapter = pwdinfo->padapter;
1149 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1150 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1151
1152 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1153 goto exit;
1154
1155 /* WFD OUI */
1156 wfdielen = 0;
1157 wfdie[wfdielen++] = 0x50;
1158 wfdie[wfdielen++] = 0x6F;
1159 wfdie[wfdielen++] = 0x9A;
1160 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1161
1162 /* Commented by Albert 20110825 */
1163 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1164 /* 1. WFD Device Information */
1165 /* 2. Associated BSSID ( Optional ) */
1166 /* 3. Local IP Adress ( Optional ) */
1167
1168
1169 /* WFD Device Information ATTR */
1170 /* Type: */
1171 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1172
1173 /* Length: */
1174 /* Note: In the WFD specification, the size of length field is 2. */
1175 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1176 wfdielen += 2;
1177
1178 /* Value1: */
1179 /* WFD device information */
1180 /* WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */
1181 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
1182 RTW_PUT_BE16(wfdie + wfdielen, val16);
1183 wfdielen += 2;
1184
1185 /* Value2: */
1186 /* Session Management Control Port */
1187 /* Default TCP port for RTSP messages is 554 */
1188 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1189 wfdielen += 2;
1190
1191 /* Value3: */
1192 /* WFD Device Maximum Throughput */
1193 /* 300Mbps is the maximum throughput */
1194 RTW_PUT_BE16(wfdie + wfdielen, 300);
1195 wfdielen += 2;
1196
1197 /* Associated BSSID ATTR */
1198 /* Type: */
1199 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1200
1201 /* Length: */
1202 /* Note: In the WFD specification, the size of length field is 2. */
1203 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1204 wfdielen += 2;
1205
1206 /* Value: */
1207 /* Associated BSSID */
1208 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1209 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1210 else
1211 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1212
1213 wfdielen += ETH_ALEN;
1214
1215 /* Coupled Sink Information ATTR */
1216 /* Type: */
1217 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1218
1219 /* Length: */
1220 /* Note: In the WFD specification, the size of length field is 2. */
1221 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1222 wfdielen += 2;
1223
1224 /* Value: */
1225 /* Coupled Sink Status bitmap */
1226 /* Not coupled/available for Coupling */
1227 wfdie[wfdielen++] = 0;
1228 /* MAC Addr. */
1229 wfdie[wfdielen++] = 0;
1230 wfdie[wfdielen++] = 0;
1231 wfdie[wfdielen++] = 0;
1232 wfdie[wfdielen++] = 0;
1233 wfdie[wfdielen++] = 0;
1234 wfdie[wfdielen++] = 0;
1235
1236 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1237
1238 exit:
1239 return len;
1240 }
1241
build_nego_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1242 u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1243 {
1244 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1245 u32 len = 0, wfdielen = 0;
1246 u16 val16 = 0;
1247 _adapter *padapter = pwdinfo->padapter;
1248 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1249 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1250
1251 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1252 goto exit;
1253
1254 /* WFD OUI */
1255 wfdielen = 0;
1256 wfdie[wfdielen++] = 0x50;
1257 wfdie[wfdielen++] = 0x6F;
1258 wfdie[wfdielen++] = 0x9A;
1259 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1260
1261 /* Commented by Albert 20110825 */
1262 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1263 /* 1. WFD Device Information */
1264 /* 2. Associated BSSID ( Optional ) */
1265 /* 3. Local IP Adress ( Optional ) */
1266
1267
1268 /* WFD Device Information ATTR */
1269 /* Type: */
1270 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1271
1272 /* Length: */
1273 /* Note: In the WFD specification, the size of length field is 2. */
1274 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1275 wfdielen += 2;
1276
1277 /* Value1: */
1278 /* WFD device information */
1279 /* WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */
1280 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
1281 RTW_PUT_BE16(wfdie + wfdielen, val16);
1282 wfdielen += 2;
1283
1284 /* Value2: */
1285 /* Session Management Control Port */
1286 /* Default TCP port for RTSP messages is 554 */
1287 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1288 wfdielen += 2;
1289
1290 /* Value3: */
1291 /* WFD Device Maximum Throughput */
1292 /* 300Mbps is the maximum throughput */
1293 RTW_PUT_BE16(wfdie + wfdielen, 300);
1294 wfdielen += 2;
1295
1296 /* Associated BSSID ATTR */
1297 /* Type: */
1298 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1299
1300 /* Length: */
1301 /* Note: In the WFD specification, the size of length field is 2. */
1302 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1303 wfdielen += 2;
1304
1305 /* Value: */
1306 /* Associated BSSID */
1307 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1308 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1309 else
1310 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1311
1312 wfdielen += ETH_ALEN;
1313
1314 /* Coupled Sink Information ATTR */
1315 /* Type: */
1316 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1317
1318 /* Length: */
1319 /* Note: In the WFD specification, the size of length field is 2. */
1320 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1321 wfdielen += 2;
1322
1323 /* Value: */
1324 /* Coupled Sink Status bitmap */
1325 /* Not coupled/available for Coupling */
1326 wfdie[wfdielen++] = 0;
1327 /* MAC Addr. */
1328 wfdie[wfdielen++] = 0;
1329 wfdie[wfdielen++] = 0;
1330 wfdie[wfdielen++] = 0;
1331 wfdie[wfdielen++] = 0;
1332 wfdie[wfdielen++] = 0;
1333 wfdie[wfdielen++] = 0;
1334
1335
1336 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1337
1338 exit:
1339 return len;
1340 }
1341
build_nego_confirm_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1342 u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1343 {
1344 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1345 u32 len = 0, wfdielen = 0;
1346 u16 val16 = 0;
1347 _adapter *padapter = pwdinfo->padapter;
1348 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1349 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1350
1351 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1352 goto exit;
1353
1354 /* WFD OUI */
1355 wfdielen = 0;
1356 wfdie[wfdielen++] = 0x50;
1357 wfdie[wfdielen++] = 0x6F;
1358 wfdie[wfdielen++] = 0x9A;
1359 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1360
1361 /* Commented by Albert 20110825 */
1362 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1363 /* 1. WFD Device Information */
1364 /* 2. Associated BSSID ( Optional ) */
1365 /* 3. Local IP Adress ( Optional ) */
1366
1367
1368 /* WFD Device Information ATTR */
1369 /* Type: */
1370 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1371
1372 /* Length: */
1373 /* Note: In the WFD specification, the size of length field is 2. */
1374 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1375 wfdielen += 2;
1376
1377 /* Value1: */
1378 /* WFD device information */
1379 /* WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available */
1380 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
1381 RTW_PUT_BE16(wfdie + wfdielen, val16);
1382 wfdielen += 2;
1383
1384 /* Value2: */
1385 /* Session Management Control Port */
1386 /* Default TCP port for RTSP messages is 554 */
1387 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1388 wfdielen += 2;
1389
1390 /* Value3: */
1391 /* WFD Device Maximum Throughput */
1392 /* 300Mbps is the maximum throughput */
1393 RTW_PUT_BE16(wfdie + wfdielen, 300);
1394 wfdielen += 2;
1395
1396 /* Associated BSSID ATTR */
1397 /* Type: */
1398 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1399
1400 /* Length: */
1401 /* Note: In the WFD specification, the size of length field is 2. */
1402 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1403 wfdielen += 2;
1404
1405 /* Value: */
1406 /* Associated BSSID */
1407 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1408 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1409 else
1410 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1411
1412 wfdielen += ETH_ALEN;
1413
1414 /* Coupled Sink Information ATTR */
1415 /* Type: */
1416 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1417
1418 /* Length: */
1419 /* Note: In the WFD specification, the size of length field is 2. */
1420 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1421 wfdielen += 2;
1422
1423 /* Value: */
1424 /* Coupled Sink Status bitmap */
1425 /* Not coupled/available for Coupling */
1426 wfdie[wfdielen++] = 0;
1427 /* MAC Addr. */
1428 wfdie[wfdielen++] = 0;
1429 wfdie[wfdielen++] = 0;
1430 wfdie[wfdielen++] = 0;
1431 wfdie[wfdielen++] = 0;
1432 wfdie[wfdielen++] = 0;
1433 wfdie[wfdielen++] = 0;
1434
1435
1436 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1437
1438 exit:
1439 return len;
1440 }
1441
build_invitation_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1442 u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1443 {
1444 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1445 u32 len = 0, wfdielen = 0;
1446 u16 val16 = 0;
1447 _adapter *padapter = pwdinfo->padapter;
1448 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1449 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1450
1451 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1452 goto exit;
1453
1454 /* WFD OUI */
1455 wfdielen = 0;
1456 wfdie[wfdielen++] = 0x50;
1457 wfdie[wfdielen++] = 0x6F;
1458 wfdie[wfdielen++] = 0x9A;
1459 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1460
1461 /* Commented by Albert 20110825 */
1462 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1463 /* 1. WFD Device Information */
1464 /* 2. Associated BSSID ( Optional ) */
1465 /* 3. Local IP Adress ( Optional ) */
1466
1467
1468 /* WFD Device Information ATTR */
1469 /* Type: */
1470 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1471
1472 /* Length: */
1473 /* Note: In the WFD specification, the size of length field is 2. */
1474 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1475 wfdielen += 2;
1476
1477 /* Value1: */
1478 /* WFD device information */
1479 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1480 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1481 RTW_PUT_BE16(wfdie + wfdielen, val16);
1482 wfdielen += 2;
1483
1484 /* Value2: */
1485 /* Session Management Control Port */
1486 /* Default TCP port for RTSP messages is 554 */
1487 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1488 wfdielen += 2;
1489
1490 /* Value3: */
1491 /* WFD Device Maximum Throughput */
1492 /* 300Mbps is the maximum throughput */
1493 RTW_PUT_BE16(wfdie + wfdielen, 300);
1494 wfdielen += 2;
1495
1496 /* Associated BSSID ATTR */
1497 /* Type: */
1498 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1499
1500 /* Length: */
1501 /* Note: In the WFD specification, the size of length field is 2. */
1502 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1503 wfdielen += 2;
1504
1505 /* Value: */
1506 /* Associated BSSID */
1507 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1508 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1509 else
1510 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1511
1512 wfdielen += ETH_ALEN;
1513
1514 /* Coupled Sink Information ATTR */
1515 /* Type: */
1516 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1517
1518 /* Length: */
1519 /* Note: In the WFD specification, the size of length field is 2. */
1520 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1521 wfdielen += 2;
1522
1523 /* Value: */
1524 /* Coupled Sink Status bitmap */
1525 /* Not coupled/available for Coupling */
1526 wfdie[wfdielen++] = 0;
1527 /* MAC Addr. */
1528 wfdie[wfdielen++] = 0;
1529 wfdie[wfdielen++] = 0;
1530 wfdie[wfdielen++] = 0;
1531 wfdie[wfdielen++] = 0;
1532 wfdie[wfdielen++] = 0;
1533 wfdie[wfdielen++] = 0;
1534
1535 if (P2P_ROLE_GO == pwdinfo->role) {
1536 /* WFD Session Information ATTR */
1537 /* Type: */
1538 wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;
1539
1540 /* Length: */
1541 /* Note: In the WFD specification, the size of length field is 2. */
1542 RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
1543 wfdielen += 2;
1544
1545 /* Todo: to add the list of WFD device info descriptor in WFD group. */
1546
1547 }
1548
1549 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1550
1551 exit:
1552 return len;
1553 }
1554
build_invitation_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1555 u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1556 {
1557 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1558 u16 val16 = 0;
1559 u32 len = 0, wfdielen = 0;
1560 _adapter *padapter = pwdinfo->padapter;
1561 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1562 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1563
1564 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1565 goto exit;
1566
1567 /* WFD OUI */
1568 wfdielen = 0;
1569 wfdie[wfdielen++] = 0x50;
1570 wfdie[wfdielen++] = 0x6F;
1571 wfdie[wfdielen++] = 0x9A;
1572 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1573
1574 /* Commented by Albert 20110825 */
1575 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1576 /* 1. WFD Device Information */
1577 /* 2. Associated BSSID ( Optional ) */
1578 /* 3. Local IP Adress ( Optional ) */
1579
1580
1581 /* WFD Device Information ATTR */
1582 /* Type: */
1583 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1584
1585 /* Length: */
1586 /* Note: In the WFD specification, the size of length field is 2. */
1587 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1588 wfdielen += 2;
1589
1590 /* Value1: */
1591 /* WFD device information */
1592 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1593 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1594 RTW_PUT_BE16(wfdie + wfdielen, val16);
1595 wfdielen += 2;
1596
1597 /* Value2: */
1598 /* Session Management Control Port */
1599 /* Default TCP port for RTSP messages is 554 */
1600 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1601 wfdielen += 2;
1602
1603 /* Value3: */
1604 /* WFD Device Maximum Throughput */
1605 /* 300Mbps is the maximum throughput */
1606 RTW_PUT_BE16(wfdie + wfdielen, 300);
1607 wfdielen += 2;
1608
1609 /* Associated BSSID ATTR */
1610 /* Type: */
1611 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1612
1613 /* Length: */
1614 /* Note: In the WFD specification, the size of length field is 2. */
1615 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1616 wfdielen += 2;
1617
1618 /* Value: */
1619 /* Associated BSSID */
1620 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1621 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1622 else
1623 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1624
1625 wfdielen += ETH_ALEN;
1626
1627 /* Coupled Sink Information ATTR */
1628 /* Type: */
1629 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1630
1631 /* Length: */
1632 /* Note: In the WFD specification, the size of length field is 2. */
1633 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1634 wfdielen += 2;
1635
1636 /* Value: */
1637 /* Coupled Sink Status bitmap */
1638 /* Not coupled/available for Coupling */
1639 wfdie[wfdielen++] = 0;
1640 /* MAC Addr. */
1641 wfdie[wfdielen++] = 0;
1642 wfdie[wfdielen++] = 0;
1643 wfdie[wfdielen++] = 0;
1644 wfdie[wfdielen++] = 0;
1645 wfdie[wfdielen++] = 0;
1646 wfdie[wfdielen++] = 0;
1647
1648 if (P2P_ROLE_GO == pwdinfo->role) {
1649 /* WFD Session Information ATTR */
1650 /* Type: */
1651 wfdie[wfdielen++] = WFD_ATTR_SESSION_INFO;
1652
1653 /* Length: */
1654 /* Note: In the WFD specification, the size of length field is 2. */
1655 RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
1656 wfdielen += 2;
1657
1658 /* Todo: to add the list of WFD device info descriptor in WFD group. */
1659
1660 }
1661
1662 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1663
1664 exit:
1665 return len;
1666 }
1667
build_provdisc_req_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1668 u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1669 {
1670 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1671 u32 len = 0, wfdielen = 0;
1672 u16 val16 = 0;
1673 _adapter *padapter = pwdinfo->padapter;
1674 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1675 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1676
1677 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1678 goto exit;
1679
1680 /* WFD OUI */
1681 wfdielen = 0;
1682 wfdie[wfdielen++] = 0x50;
1683 wfdie[wfdielen++] = 0x6F;
1684 wfdie[wfdielen++] = 0x9A;
1685 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1686
1687 /* Commented by Albert 20110825 */
1688 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1689 /* 1. WFD Device Information */
1690 /* 2. Associated BSSID ( Optional ) */
1691 /* 3. Local IP Adress ( Optional ) */
1692
1693
1694 /* WFD Device Information ATTR */
1695 /* Type: */
1696 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1697
1698 /* Length: */
1699 /* Note: In the WFD specification, the size of length field is 2. */
1700 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1701 wfdielen += 2;
1702
1703 /* Value1: */
1704 /* WFD device information */
1705 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1706 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1707 RTW_PUT_BE16(wfdie + wfdielen, val16);
1708 wfdielen += 2;
1709
1710 /* Value2: */
1711 /* Session Management Control Port */
1712 /* Default TCP port for RTSP messages is 554 */
1713 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1714 wfdielen += 2;
1715
1716 /* Value3: */
1717 /* WFD Device Maximum Throughput */
1718 /* 300Mbps is the maximum throughput */
1719 RTW_PUT_BE16(wfdie + wfdielen, 300);
1720 wfdielen += 2;
1721
1722 /* Associated BSSID ATTR */
1723 /* Type: */
1724 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1725
1726 /* Length: */
1727 /* Note: In the WFD specification, the size of length field is 2. */
1728 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1729 wfdielen += 2;
1730
1731 /* Value: */
1732 /* Associated BSSID */
1733 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1734 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1735 else
1736 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1737
1738 wfdielen += ETH_ALEN;
1739
1740 /* Coupled Sink Information ATTR */
1741 /* Type: */
1742 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1743
1744 /* Length: */
1745 /* Note: In the WFD specification, the size of length field is 2. */
1746 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1747 wfdielen += 2;
1748
1749 /* Value: */
1750 /* Coupled Sink Status bitmap */
1751 /* Not coupled/available for Coupling */
1752 wfdie[wfdielen++] = 0;
1753 /* MAC Addr. */
1754 wfdie[wfdielen++] = 0;
1755 wfdie[wfdielen++] = 0;
1756 wfdie[wfdielen++] = 0;
1757 wfdie[wfdielen++] = 0;
1758 wfdie[wfdielen++] = 0;
1759 wfdie[wfdielen++] = 0;
1760
1761
1762 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1763
1764 exit:
1765 return len;
1766 }
1767
build_provdisc_resp_wfd_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1768 u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1769 {
1770 u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };
1771 u32 len = 0, wfdielen = 0;
1772 u16 val16 = 0;
1773 _adapter *padapter = pwdinfo->padapter;
1774 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1775 struct wifi_display_info *pwfd_info = padapter->wdinfo.wfd_info;
1776
1777 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
1778 goto exit;
1779
1780 /* WFD OUI */
1781 wfdielen = 0;
1782 wfdie[wfdielen++] = 0x50;
1783 wfdie[wfdielen++] = 0x6F;
1784 wfdie[wfdielen++] = 0x9A;
1785 wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */
1786
1787 /* Commented by Albert 20110825 */
1788 /* According to the WFD Specification, the provision discovery response frame should contain 3 WFD attributes */
1789 /* 1. WFD Device Information */
1790 /* 2. Associated BSSID ( Optional ) */
1791 /* 3. Local IP Adress ( Optional ) */
1792
1793
1794 /* WFD Device Information ATTR */
1795 /* Type: */
1796 wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;
1797
1798 /* Length: */
1799 /* Note: In the WFD specification, the size of length field is 2. */
1800 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1801 wfdielen += 2;
1802
1803 /* Value1: */
1804 /* WFD device information */
1805 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery ) */
1806 val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
1807 RTW_PUT_BE16(wfdie + wfdielen, val16);
1808 wfdielen += 2;
1809
1810 /* Value2: */
1811 /* Session Management Control Port */
1812 /* Default TCP port for RTSP messages is 554 */
1813 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport);
1814 wfdielen += 2;
1815
1816 /* Value3: */
1817 /* WFD Device Maximum Throughput */
1818 /* 300Mbps is the maximum throughput */
1819 RTW_PUT_BE16(wfdie + wfdielen, 300);
1820 wfdielen += 2;
1821
1822 /* Associated BSSID ATTR */
1823 /* Type: */
1824 wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;
1825
1826 /* Length: */
1827 /* Note: In the WFD specification, the size of length field is 2. */
1828 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
1829 wfdielen += 2;
1830
1831 /* Value: */
1832 /* Associated BSSID */
1833 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
1834 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
1835 else
1836 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1837
1838 wfdielen += ETH_ALEN;
1839
1840 /* Coupled Sink Information ATTR */
1841 /* Type: */
1842 wfdie[wfdielen++] = WFD_ATTR_COUPLED_SINK_INFO;
1843
1844 /* Length: */
1845 /* Note: In the WFD specification, the size of length field is 2. */
1846 RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
1847 wfdielen += 2;
1848
1849 /* Value: */
1850 /* Coupled Sink Status bitmap */
1851 /* Not coupled/available for Coupling */
1852 wfdie[wfdielen++] = 0;
1853 /* MAC Addr. */
1854 wfdie[wfdielen++] = 0;
1855 wfdie[wfdielen++] = 0;
1856 wfdie[wfdielen++] = 0;
1857 wfdie[wfdielen++] = 0;
1858 wfdie[wfdielen++] = 0;
1859 wfdie[wfdielen++] = 0;
1860
1861 rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1862
1863 exit:
1864 return len;
1865 }
1866 #endif /* CONFIG_WFD */
1867
build_probe_resp_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)1868 u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1869 {
1870 u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
1871 u32 len = 0, p2pielen = 0;
1872
1873 /* P2P OUI */
1874 p2pielen = 0;
1875 p2pie[p2pielen++] = 0x50;
1876 p2pie[p2pielen++] = 0x6F;
1877 p2pie[p2pielen++] = 0x9A;
1878 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
1879
1880 /* Commented by Albert 20100907 */
1881 /* According to the P2P Specification, the probe response frame should contain 5 P2P attributes */
1882 /* 1. P2P Capability */
1883 /* 2. Extended Listen Timing */
1884 /* 3. Notice of Absence ( NOA ) ( Only GO needs this ) */
1885 /* 4. Device Info */
1886 /* 5. Group Info ( Only GO need this ) */
1887
1888 /* P2P Capability ATTR */
1889 /* Type: */
1890 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
1891
1892 /* Length: */
1893 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 ); */
1894 RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
1895 p2pielen += 2;
1896
1897 /* Value: */
1898 /* Device Capability Bitmap, 1 byte */
1899 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
1900
1901 /* Group Capability Bitmap, 1 byte */
1902 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1903 p2pie[p2pielen] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);
1904
1905 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
1906 p2pie[p2pielen] |= P2P_GRPCAP_GROUP_FORMATION;
1907
1908 p2pielen++;
1909 } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
1910 /* Group Capability Bitmap, 1 byte */
1911 if (pwdinfo->persistent_supported)
1912 p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
1913 else
1914 p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
1915 }
1916
1917 /* Extended Listen Timing ATTR */
1918 /* Type: */
1919 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
1920
1921 /* Length: */
1922 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 ); */
1923 RTW_PUT_LE16(p2pie + p2pielen, 0x0004);
1924 p2pielen += 2;
1925
1926 /* Value: */
1927 /* Availability Period */
1928 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF ); */
1929 RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
1930 p2pielen += 2;
1931
1932 /* Availability Interval */
1933 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF ); */
1934 RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
1935 p2pielen += 2;
1936
1937
1938 /* Notice of Absence ATTR */
1939 /* Type: */
1940 /* Length: */
1941 /* Value: */
1942 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1943 /* go_add_noa_attr(pwdinfo); */
1944 }
1945
1946 /* Device Info ATTR */
1947 /* Type: */
1948 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
1949
1950 /* Length: */
1951 /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
1952 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
1953 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len ); */
1954 RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
1955 p2pielen += 2;
1956
1957 /* Value: */
1958 /* P2P Device Address */
1959 _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
1960 p2pielen += ETH_ALEN;
1961
1962 /* Config Method */
1963 /* This field should be big endian. Noted by P2P specification. */
1964 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm ); */
1965 RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm);
1966 p2pielen += 2;
1967
1968 {
1969 /* Primary Device Type */
1970 /* Category ID */
1971 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA ); */
1972 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
1973 p2pielen += 2;
1974
1975 /* OUI */
1976 /* *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); */
1977 RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
1978 p2pielen += 4;
1979
1980 /* Sub Category ID */
1981 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER ); */
1982 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
1983 p2pielen += 2;
1984 }
1985
1986 /* Number of Secondary Device Types */
1987 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
1988
1989 /* Device Name */
1990 /* Type: */
1991 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME ); */
1992 RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
1993 p2pielen += 2;
1994
1995 /* Length: */
1996 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len ); */
1997 RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
1998 p2pielen += 2;
1999
2000 /* Value: */
2001 _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2002 p2pielen += pwdinfo->device_name_len;
2003
2004 /* Group Info ATTR */
2005 /* Type: */
2006 /* Length: */
2007 /* Value: */
2008 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2009 p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);
2010
2011
2012 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2013
2014
2015 return len;
2016
2017 }
2018
build_prov_disc_request_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pbuf,u8 * pssid,u8 ussidlen,u8 * pdev_raddr)2019 u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
2020 {
2021 u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
2022 u32 len = 0, p2pielen = 0;
2023
2024 /* P2P OUI */
2025 p2pielen = 0;
2026 p2pie[p2pielen++] = 0x50;
2027 p2pie[p2pielen++] = 0x6F;
2028 p2pie[p2pielen++] = 0x9A;
2029 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2030
2031 /* Commented by Albert 20110301 */
2032 /* According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
2033 /* 1. P2P Capability */
2034 /* 2. Device Info */
2035 /* 3. Group ID ( When joining an operating P2P Group ) */
2036
2037 /* P2P Capability ATTR */
2038 /* Type: */
2039 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2040
2041 /* Length: */
2042 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 ); */
2043 RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
2044 p2pielen += 2;
2045
2046 /* Value: */
2047 /* Device Capability Bitmap, 1 byte */
2048 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2049
2050 /* Group Capability Bitmap, 1 byte */
2051 if (pwdinfo->persistent_supported)
2052 p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
2053 else
2054 p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
2055
2056
2057 /* Device Info ATTR */
2058 /* Type: */
2059 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2060
2061 /* Length: */
2062 /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2063 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2064 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len ); */
2065 RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
2066 p2pielen += 2;
2067
2068 /* Value: */
2069 /* P2P Device Address */
2070 _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
2071 p2pielen += ETH_ALEN;
2072
2073 /* Config Method */
2074 /* This field should be big endian. Noted by P2P specification. */
2075 if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC) {
2076 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_PBC ); */
2077 RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_PBC);
2078 } else {
2079 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY ); */
2080 RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_DISPLAY);
2081 }
2082
2083 p2pielen += 2;
2084
2085 /* Primary Device Type */
2086 /* Category ID */
2087 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA ); */
2088 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
2089 p2pielen += 2;
2090
2091 /* OUI */
2092 /* *(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); */
2093 RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
2094 p2pielen += 4;
2095
2096 /* Sub Category ID */
2097 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER ); */
2098 RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
2099 p2pielen += 2;
2100
2101 /* Number of Secondary Device Types */
2102 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
2103
2104 /* Device Name */
2105 /* Type: */
2106 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME ); */
2107 RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
2108 p2pielen += 2;
2109
2110 /* Length: */
2111 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len ); */
2112 RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
2113 p2pielen += 2;
2114
2115 /* Value: */
2116 _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2117 p2pielen += pwdinfo->device_name_len;
2118
2119 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2120 /* Added by Albert 2011/05/19 */
2121 /* In this case, the pdev_raddr is the device address of the group owner. */
2122
2123 /* P2P Group ID ATTR */
2124 /* Type: */
2125 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2126
2127 /* Length: */
2128 /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + ussidlen ); */
2129 RTW_PUT_LE16(p2pie + p2pielen, ETH_ALEN + ussidlen);
2130 p2pielen += 2;
2131
2132 /* Value: */
2133 _rtw_memcpy(p2pie + p2pielen, pdev_raddr, ETH_ALEN);
2134 p2pielen += ETH_ALEN;
2135
2136 _rtw_memcpy(p2pie + p2pielen, pssid, ussidlen);
2137 p2pielen += ussidlen;
2138
2139 }
2140
2141 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2142
2143
2144 return len;
2145
2146 }
2147
2148
build_assoc_resp_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pbuf,u8 status_code)2149 u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)
2150 {
2151 u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
2152 u32 len = 0, p2pielen = 0;
2153
2154 /* P2P OUI */
2155 p2pielen = 0;
2156 p2pie[p2pielen++] = 0x50;
2157 p2pie[p2pielen++] = 0x6F;
2158 p2pie[p2pielen++] = 0x9A;
2159 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2160
2161 /* According to the P2P Specification, the Association response frame should contain 2 P2P attributes */
2162 /* 1. Status */
2163 /* 2. Extended Listen Timing (optional) */
2164
2165
2166 /* Status ATTR */
2167 p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);
2168
2169
2170 /* Extended Listen Timing ATTR */
2171 /* Type: */
2172 /* Length: */
2173 /* Value: */
2174
2175
2176 pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2177
2178 return len;
2179
2180 }
2181
build_deauth_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pbuf)2182 u32 build_deauth_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
2183 {
2184 u32 len = 0;
2185
2186 return len;
2187 }
2188
process_probe_req_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2189 u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2190 {
2191 u8 *p;
2192 u32 ret = _FALSE;
2193 u8 *p2pie;
2194 u32 p2pielen = 0;
2195 int ssid_len = 0, rate_cnt = 0;
2196
2197 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
2198 len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
2199
2200 if (rate_cnt <= 4) {
2201 int i, g_rate = 0;
2202
2203 for (i = 0; i < rate_cnt; i++) {
2204 if (((*(p + 2 + i) & 0xff) != 0x02) &&
2205 ((*(p + 2 + i) & 0xff) != 0x04) &&
2206 ((*(p + 2 + i) & 0xff) != 0x0B) &&
2207 ((*(p + 2 + i) & 0xff) != 0x16))
2208 g_rate = 1;
2209 }
2210
2211 if (g_rate == 0) {
2212 /* There is no OFDM rate included in SupportedRates IE of this probe request frame */
2213 /* The driver should response this probe request. */
2214 return ret;
2215 }
2216 } else {
2217 /* rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */
2218 /* We should proceed the following check for this probe request. */
2219 }
2220
2221 /* Added comments by Albert 20100906 */
2222 /* There are several items we should check here. */
2223 /* 1. This probe request frame must contain the P2P IE. (Done) */
2224 /* 2. This probe request frame must contain the wildcard SSID. (Done) */
2225 /* 3. Wildcard BSSID. (Todo) */
2226 /* 4. Destination Address. ( Done in mgt_dispatcher function ) */
2227 /* 5. Requested Device Type in WSC IE. (Todo) */
2228 /* 6. Device ID attribute in P2P IE. (Todo) */
2229
2230 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
2231 len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
2232
2233 ssid_len &= 0xff; /* Just last 1 byte is valid for ssid len of the probe request */
2234 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2235 p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_ , len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_ , NULL, &p2pielen);
2236 if (p2pie) {
2237 if ((p != NULL) && _rtw_memcmp((void *)(p + 2), (void *) pwdinfo->p2p_wildcard_ssid , 7)) {
2238 /* todo: */
2239 /* Check Requested Device Type attributes in WSC IE. */
2240 /* Check Device ID attribute in P2P IE */
2241
2242 ret = _TRUE;
2243 } else if ((p != NULL) && (ssid_len == 0))
2244 ret = _TRUE;
2245 } else {
2246 /* non -p2p device */
2247 }
2248
2249 }
2250
2251
2252 return ret;
2253
2254 }
2255
process_assoc_req_p2p_ie(struct wifidirect_info * pwdinfo,u8 * pframe,uint len,struct sta_info * psta)2256 u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
2257 {
2258 u8 status_code = P2P_STATUS_SUCCESS;
2259 u8 *pbuf, *pattr_content = NULL;
2260 u32 attr_contentlen = 0;
2261 u16 cap_attr = 0;
2262 unsigned short frame_type, ie_offset = 0;
2263 u8 *ies;
2264 u32 ies_len;
2265 u8 *p2p_ie;
2266 u32 p2p_ielen = 0;
2267
2268 if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2269 return P2P_STATUS_FAIL_REQUEST_UNABLE;
2270
2271 frame_type = get_frame_sub_type(pframe);
2272 if (frame_type == WIFI_ASSOCREQ)
2273 ie_offset = _ASOCREQ_IE_OFFSET_;
2274 else /* WIFI_REASSOCREQ */
2275 ie_offset = _REASOCREQ_IE_OFFSET_;
2276
2277 ies = pframe + WLAN_HDR_A3_LEN + ie_offset;
2278 ies_len = len - WLAN_HDR_A3_LEN - ie_offset;
2279
2280 p2p_ie = rtw_get_p2p_ie(ies , ies_len , NULL, &p2p_ielen);
2281
2282 if (!p2p_ie) {
2283 RTW_INFO("[%s] P2P IE not Found!!\n", __FUNCTION__);
2284 status_code = P2P_STATUS_FAIL_INVALID_PARAM;
2285 } else
2286 RTW_INFO("[%s] P2P IE Found!!\n", __FUNCTION__);
2287
2288 while (p2p_ie) {
2289 /* Check P2P Capability ATTR */
2290 attr_contentlen = sizeof(cap_attr);
2291 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *) &attr_contentlen)) {
2292 RTW_INFO("[%s] Got P2P Capability Attr!!\n", __FUNCTION__);
2293 cap_attr = le16_to_cpu(cap_attr);
2294 psta->dev_cap = cap_attr & 0xff;
2295 }
2296
2297 /* Check Extended Listen Timing ATTR */
2298
2299
2300 /* Check P2P Device Info ATTR */
2301 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint *)&attr_contentlen)) {
2302 RTW_INFO("[%s] Got P2P DEVICE INFO Attr!!\n", __FUNCTION__);
2303 pattr_content = pbuf = rtw_zmalloc(attr_contentlen);
2304 if (pattr_content) {
2305 u8 num_of_secdev_type;
2306 u16 dev_name_len;
2307
2308 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO , pattr_content, (uint *)&attr_contentlen);
2309
2310 _rtw_memcpy(psta->dev_addr, pattr_content, ETH_ALEN);/* P2P Device Address */
2311
2312 pattr_content += ETH_ALEN;
2313
2314 _rtw_memcpy(&psta->config_methods, pattr_content, 2);/* Config Methods */
2315 psta->config_methods = be16_to_cpu(psta->config_methods);
2316
2317 pattr_content += 2;
2318
2319 _rtw_memcpy(psta->primary_dev_type, pattr_content, 8);
2320
2321 pattr_content += 8;
2322
2323 num_of_secdev_type = *pattr_content;
2324 pattr_content += 1;
2325
2326 if (num_of_secdev_type == 0)
2327 psta->num_of_secdev_type = 0;
2328 else {
2329 u32 len;
2330
2331 psta->num_of_secdev_type = num_of_secdev_type;
2332
2333 len = (sizeof(psta->secdev_types_list) < (num_of_secdev_type * 8)) ? (sizeof(psta->secdev_types_list)) : (num_of_secdev_type * 8);
2334
2335 _rtw_memcpy(psta->secdev_types_list, pattr_content, len);
2336
2337 pattr_content += (num_of_secdev_type * 8);
2338 }
2339
2340
2341 /* dev_name_len = attr_contentlen - ETH_ALEN - 2 - 8 - 1 - (num_of_secdev_type*8); */
2342 psta->dev_name_len = 0;
2343 if (WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(u16 *)pattr_content)) {
2344 dev_name_len = be16_to_cpu(*(u16 *)(pattr_content + 2));
2345
2346 psta->dev_name_len = (sizeof(psta->dev_name) < dev_name_len) ? sizeof(psta->dev_name) : dev_name_len;
2347
2348 _rtw_memcpy(psta->dev_name, pattr_content + 4, psta->dev_name_len);
2349 }
2350
2351 rtw_mfree(pbuf, attr_contentlen);
2352
2353 }
2354
2355 }
2356
2357 /* Get the next P2P IE */
2358 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2359
2360 }
2361
2362 return status_code;
2363
2364 }
2365
process_p2p_devdisc_req(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2366 u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2367 {
2368 u8 *frame_body;
2369 u8 status, dialogToken;
2370 struct sta_info *psta = NULL;
2371 _adapter *padapter = pwdinfo->padapter;
2372 struct sta_priv *pstapriv = &padapter->stapriv;
2373 u8 *p2p_ie;
2374 u32 p2p_ielen = 0;
2375
2376 frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2377
2378 dialogToken = frame_body[7];
2379 status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
2380
2381 p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
2382 if (p2p_ie) {
2383 u8 groupid[38] = { 0x00 };
2384 u8 dev_addr[ETH_ALEN] = { 0x00 };
2385 u32 attr_contentlen = 0;
2386
2387 attr_contentlen = sizeof(groupid);
2388 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
2389 if (_rtw_memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
2390 _rtw_memcmp(pwdinfo->p2p_group_ssid, groupid + ETH_ALEN, pwdinfo->p2p_group_ssid_len)) {
2391 attr_contentlen = sizeof(dev_addr);
2392 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_ID, dev_addr, &attr_contentlen)) {
2393 _irqL irqL;
2394 _list *phead, *plist;
2395
2396 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2397 phead = &pstapriv->asoc_list;
2398 plist = get_next(phead);
2399
2400 /* look up sta asoc_queue */
2401 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
2402 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
2403
2404 plist = get_next(plist);
2405
2406 if (psta->is_p2p_device && (psta->dev_cap & P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
2407 _rtw_memcmp(psta->dev_addr, dev_addr, ETH_ALEN)) {
2408
2409 /* _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); */
2410 /* issue GO Discoverability Request */
2411 issue_group_disc_req(pwdinfo, psta->cmn.mac_addr);
2412 /* _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); */
2413
2414 status = P2P_STATUS_SUCCESS;
2415
2416 break;
2417 } else
2418 status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2419
2420 }
2421 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2422
2423 } else
2424 status = P2P_STATUS_FAIL_INVALID_PARAM;
2425
2426 } else
2427 status = P2P_STATUS_FAIL_INVALID_PARAM;
2428
2429 }
2430
2431 }
2432
2433
2434 /* issue Device Discoverability Response */
2435 issue_p2p_devdisc_resp(pwdinfo, get_addr2_ptr(pframe), status, dialogToken);
2436
2437
2438 return (status == P2P_STATUS_SUCCESS) ? _TRUE : _FALSE;
2439
2440 }
2441
process_p2p_devdisc_resp(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2442 u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2443 {
2444 return _TRUE;
2445 }
2446
process_p2p_provdisc_req(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2447 u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2448 {
2449 u8 *frame_body;
2450 u8 *wpsie;
2451 uint wps_ielen = 0, attr_contentlen = 0;
2452 u16 uconfig_method = 0;
2453
2454
2455 frame_body = (pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2456
2457 wpsie = rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
2458 if (wpsie) {
2459 attr_contentlen = sizeof(uconfig_method);
2460 if (rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD , (u8 *) &uconfig_method, &attr_contentlen)) {
2461 uconfig_method = be16_to_cpu(uconfig_method);
2462 switch (uconfig_method) {
2463 case WPS_CM_DISPLYA: {
2464 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2465 break;
2466 }
2467 case WPS_CM_LABEL: {
2468 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "lab", 3);
2469 break;
2470 }
2471 case WPS_CM_PUSH_BUTTON: {
2472 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2473 break;
2474 }
2475 case WPS_CM_KEYPAD: {
2476 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2477 break;
2478 }
2479 }
2480 issue_p2p_provision_resp(pwdinfo, get_addr2_ptr(pframe), frame_body, uconfig_method);
2481 }
2482 }
2483 RTW_INFO("[%s] config method = %s\n", __FUNCTION__, pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
2484 return _TRUE;
2485
2486 }
2487
process_p2p_provdisc_resp(struct wifidirect_info * pwdinfo,u8 * pframe)2488 u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe)
2489 {
2490
2491 return _TRUE;
2492 }
2493
rtw_p2p_get_peer_ch_list(struct wifidirect_info * pwdinfo,u8 * ch_content,u8 ch_cnt,u8 * peer_ch_list)2494 u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
2495 {
2496 u8 i = 0, j = 0;
2497 u8 temp = 0;
2498 u8 ch_no = 0;
2499 ch_content += 3;
2500 ch_cnt -= 3;
2501
2502 while (ch_cnt > 0) {
2503 ch_content += 1;
2504 ch_cnt -= 1;
2505 temp = *ch_content;
2506 for (i = 0 ; i < temp ; i++, j++)
2507 peer_ch_list[j] = *(ch_content + 1 + i);
2508 ch_content += (temp + 1);
2509 ch_cnt -= (temp + 1);
2510 ch_no += temp ;
2511 }
2512
2513 return ch_no;
2514 }
2515
rtw_p2p_ch_inclusion(_adapter * adapter,u8 * peer_ch_list,u8 peer_ch_num,u8 * ch_list_inclusioned)2516 u8 rtw_p2p_ch_inclusion(_adapter *adapter, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
2517 {
2518 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
2519 int i = 0, j = 0, temp = 0;
2520 u8 ch_no = 0;
2521
2522 for (i = 0; i < peer_ch_num; i++) {
2523 for (j = temp; j < rfctl->max_chan_nums; j++) {
2524 if (*(peer_ch_list + i) == rfctl->channel_set[j].ChannelNum) {
2525 ch_list_inclusioned[ch_no++] = *(peer_ch_list + i);
2526 temp = j;
2527 break;
2528 }
2529 }
2530 }
2531
2532 return ch_no;
2533 }
2534
process_p2p_group_negotation_req(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2535 u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2536 {
2537 _adapter *padapter = pwdinfo->padapter;
2538 u8 result = P2P_STATUS_SUCCESS;
2539 u32 p2p_ielen = 0, wps_ielen = 0;
2540 u8 *ies;
2541 u32 ies_len;
2542 u8 *p2p_ie;
2543 u8 *wpsie;
2544 u16 wps_devicepassword_id = 0x0000;
2545 uint wps_devicepassword_id_len = 0;
2546 #ifdef CONFIG_WFD
2547 #ifdef CONFIG_TDLS
2548 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
2549 #endif /* CONFIG_TDLS */
2550 #endif /* CONFIG_WFD */
2551 wpsie = rtw_get_wps_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
2552 if (wpsie) {
2553 /* Commented by Kurt 20120113 */
2554 /* If some device wants to do p2p handshake without sending prov_disc_req */
2555 /* We have to get peer_req_cm from here. */
2556 if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
2557 wps_devicepassword_id_len = sizeof(wps_devicepassword_id);
2558 rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8 *) &wps_devicepassword_id, &wps_devicepassword_id_len);
2559 wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
2560
2561 if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2562 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2563 else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2564 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2565 else
2566 _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2567 }
2568 } else {
2569 RTW_INFO("[%s] WPS IE not Found!!\n", __FUNCTION__);
2570 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2571 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2572 return result ;
2573 }
2574
2575 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2576 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2577
2578 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
2579
2580 if (!p2p_ie) {
2581 RTW_INFO("[%s] P2P IE not Found!!\n", __FUNCTION__);
2582 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2583 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2584 }
2585
2586 while (p2p_ie) {
2587 u8 attr_content = 0x00;
2588 u32 attr_contentlen = 0;
2589 u8 ch_content[100] = { 0x00 };
2590 uint ch_cnt = 0;
2591 u8 peer_ch_list[100] = { 0x00 };
2592 u8 peer_ch_num = 0;
2593 u8 ch_list_inclusioned[100] = { 0x00 };
2594 u8 ch_num_inclusioned = 0;
2595 u16 cap_attr;
2596 u8 listen_ch_attr[5] = { 0x00 };
2597
2598 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
2599
2600 /* Check P2P Capability ATTR */
2601 attr_contentlen = sizeof(cap_attr);
2602 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *)&attr_contentlen)) {
2603 cap_attr = le16_to_cpu(cap_attr);
2604
2605 #if defined(CONFIG_WFD) && defined(CONFIG_TDLS)
2606 if (!(cap_attr & P2P_GRPCAP_INTRABSS))
2607 ptdlsinfo->ap_prohibited = _TRUE;
2608 #endif /* defined(CONFIG_WFD) && defined(CONFIG_TDLS) */
2609 }
2610
2611 attr_contentlen = sizeof(attr_content);
2612 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen)) {
2613 RTW_INFO("[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01);
2614 pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2615
2616 if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
2617 /* Try to match the tie breaker value */
2618 if (pwdinfo->intent == P2P_MAX_INTENT) {
2619 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2620 result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2621 } else {
2622 if (attr_content & 0x01)
2623 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2624 else
2625 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2626 }
2627 } else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))
2628 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2629 else
2630 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2631
2632 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2633 /* Store the group id information. */
2634 _rtw_memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2635 _rtw_memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2636 }
2637 }
2638
2639 attr_contentlen = sizeof(listen_ch_attr);
2640 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, (u8 *)listen_ch_attr, (uint *) &attr_contentlen) && attr_contentlen == 5)
2641 pwdinfo->nego_req_info.peer_ch = listen_ch_attr[4];
2642
2643 RTW_INFO(FUNC_ADPT_FMT" listen channel :%u\n", FUNC_ADPT_ARG(padapter), pwdinfo->nego_req_info.peer_ch);
2644
2645 attr_contentlen = sizeof(pwdinfo->p2p_peer_interface_addr);
2646 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
2647 if (attr_contentlen != ETH_ALEN)
2648 _rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2649 }
2650
2651 ch_cnt = sizeof(ch_content);
2652 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt)) {
2653 peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
2654 ch_num_inclusioned = rtw_p2p_ch_inclusion(padapter, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2655
2656 if (ch_num_inclusioned == 0) {
2657 RTW_INFO("[%s] No common channel in channel list!\n", __FUNCTION__);
2658 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2659 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2660 break;
2661 }
2662
2663 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2664 if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2665 ch_list_inclusioned, ch_num_inclusioned)) {
2666 #ifdef CONFIG_CONCURRENT_MODE
2667 if (rtw_mi_check_status(padapter, MI_LINKED)
2668 && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
2669 RTW_INFO("[%s] desired channel NOT Found!\n", __FUNCTION__);
2670 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2671 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2672 break;
2673 } else
2674 #endif /* CONFIG_CONCURRENT_MODE */
2675 {
2676 u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2677
2678 attr_contentlen = sizeof(operatingch_info);
2679 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2680 peer_operating_ch = operatingch_info[4];
2681
2682 if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2683 ch_list_inclusioned, ch_num_inclusioned)) {
2684 /**
2685 * Change our operating channel as peer's for compatibility.
2686 */
2687 pwdinfo->operating_channel = peer_operating_ch;
2688 RTW_INFO("[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);
2689 } else {
2690 /* Take first channel of ch_list_inclusioned as operating channel */
2691 pwdinfo->operating_channel = ch_list_inclusioned[0];
2692 RTW_INFO("[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);
2693 }
2694 }
2695
2696 }
2697 }
2698 }
2699
2700 /* Get the next P2P IE */
2701 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2702 }
2703
2704 if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) {
2705 result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2706 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
2707 return result;
2708 }
2709
2710 #ifdef CONFIG_WFD
2711 rtw_process_wfd_ies(padapter, pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, __func__);
2712 #endif
2713
2714 return result ;
2715 }
2716
process_p2p_group_negotation_resp(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2717 u8 process_p2p_group_negotation_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2718 {
2719 _adapter *padapter = pwdinfo->padapter;
2720 u8 result = P2P_STATUS_SUCCESS;
2721 u32 p2p_ielen, wps_ielen;
2722 u8 *ies;
2723 u32 ies_len;
2724 u8 *p2p_ie;
2725 #ifdef CONFIG_WFD
2726 #ifdef CONFIG_TDLS
2727 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
2728 #endif /* CONFIG_TDLS */
2729 #endif /* CONFIG_WFD */
2730
2731 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2732 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2733
2734 /* Be able to know which one is the P2P GO and which one is P2P client. */
2735
2736 if (rtw_get_wps_ie(ies, ies_len, NULL, &wps_ielen)) {
2737
2738 } else {
2739 RTW_INFO("[%s] WPS IE not Found!!\n", __FUNCTION__);
2740 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2741 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2742 }
2743
2744 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
2745 if (!p2p_ie) {
2746 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2747 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2748 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2749 } else {
2750
2751 u8 attr_content = 0x00;
2752 u32 attr_contentlen = 0;
2753 u8 operatingch_info[5] = { 0x00 };
2754 u8 groupid[38];
2755 u16 cap_attr;
2756 u8 peer_ch_list[100] = { 0x00 };
2757 u8 peer_ch_num = 0;
2758 u8 ch_list_inclusioned[100] = { 0x00 };
2759 u8 ch_num_inclusioned = 0;
2760
2761 while (p2p_ie) { /* Found the P2P IE. */
2762
2763 /* Check P2P Capability ATTR */
2764 attr_contentlen = sizeof(cap_attr);
2765 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *)&attr_contentlen)) {
2766 cap_attr = le16_to_cpu(cap_attr);
2767 #ifdef CONFIG_TDLS
2768 if (!(cap_attr & P2P_GRPCAP_INTRABSS))
2769 ptdlsinfo->ap_prohibited = _TRUE;
2770 #endif /* CONFIG_TDLS */
2771 }
2772
2773 attr_contentlen = sizeof(attr_content);
2774 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
2775 if (attr_contentlen == 1) {
2776 RTW_INFO("[%s] Status = %d\n", __FUNCTION__, attr_content);
2777 if (attr_content == P2P_STATUS_SUCCESS) {
2778 /* Do nothing. */
2779 } else {
2780 if (P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content)
2781 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
2782 else
2783 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2784 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2785 result = attr_content;
2786 break;
2787 }
2788 }
2789
2790 /* Try to get the peer's interface address */
2791 attr_contentlen = sizeof(pwdinfo->p2p_peer_interface_addr);
2792 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
2793 if (attr_contentlen != ETH_ALEN)
2794 _rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2795 }
2796
2797 /* Try to get the peer's intent and tie breaker value. */
2798 attr_content = 0x00;
2799 attr_contentlen = sizeof(attr_content);
2800 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen)) {
2801 RTW_INFO("[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01);
2802 pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2803
2804 if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
2805 /* Try to match the tie breaker value */
2806 if (pwdinfo->intent == P2P_MAX_INTENT) {
2807 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2808 result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2809 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2810 } else {
2811 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2812 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2813 if (attr_content & 0x01)
2814 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2815 else
2816 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2817 }
2818 } else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) {
2819 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2820 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2821 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2822 } else {
2823 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2824 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2825 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2826 }
2827
2828 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2829 /* Store the group id information. */
2830 _rtw_memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2831 _rtw_memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2832
2833 }
2834 }
2835
2836 /* Try to get the operation channel information */
2837
2838 attr_contentlen = sizeof(operatingch_info);
2839 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
2840 RTW_INFO("[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4]);
2841 pwdinfo->peer_operating_ch = operatingch_info[4];
2842 }
2843
2844 /* Try to get the channel list information */
2845 pwdinfo->channel_list_attr_len = sizeof(pwdinfo->channel_list_attr);
2846 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len)) {
2847 RTW_INFO("[%s] channel list attribute found, len = %d\n", __FUNCTION__, pwdinfo->channel_list_attr_len);
2848
2849 peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
2850 ch_num_inclusioned = rtw_p2p_ch_inclusion(padapter, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2851
2852 if (ch_num_inclusioned == 0) {
2853 RTW_INFO("[%s] No common channel in channel list!\n", __FUNCTION__);
2854 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2855 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2856 break;
2857 }
2858
2859 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2860 if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2861 ch_list_inclusioned, ch_num_inclusioned)) {
2862 #ifdef CONFIG_CONCURRENT_MODE
2863 if (rtw_mi_check_status(padapter, MI_LINKED)
2864 && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
2865 RTW_INFO("[%s] desired channel NOT Found!\n", __FUNCTION__);
2866 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2867 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2868 break;
2869 } else
2870 #endif /* CONFIG_CONCURRENT_MODE */
2871 {
2872 u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2873 attr_contentlen = sizeof(operatingch_info);
2874
2875 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2876 peer_operating_ch = operatingch_info[4];
2877
2878 if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2879 ch_list_inclusioned, ch_num_inclusioned)) {
2880 /**
2881 * Change our operating channel as peer's for compatibility.
2882 */
2883 pwdinfo->operating_channel = peer_operating_ch;
2884 RTW_INFO("[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);
2885 } else {
2886 /* Take first channel of ch_list_inclusioned as operating channel */
2887 pwdinfo->operating_channel = ch_list_inclusioned[0];
2888 RTW_INFO("[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);
2889 }
2890 }
2891
2892 }
2893 }
2894
2895 } else
2896 RTW_INFO("[%s] channel list attribute not found!\n", __FUNCTION__);
2897
2898 /* Try to get the group id information if peer is GO */
2899 _rtw_memset(groupid, 0x00, 38);
2900 attr_contentlen = sizeof(groupid);
2901 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
2902 _rtw_memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
2903 _rtw_memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
2904 }
2905
2906 /* Get the next P2P IE */
2907 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2908 }
2909
2910 }
2911
2912 #ifdef CONFIG_WFD
2913 rtw_process_wfd_ies(padapter, pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, __func__);
2914 #endif
2915
2916 return result ;
2917
2918 }
2919
process_p2p_group_negotation_confirm(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)2920 u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2921 {
2922 #ifdef CONFIG_CONCURRENT_MODE
2923 _adapter *padapter = pwdinfo->padapter;
2924 struct roch_info *prochinfo = &padapter->rochinfo;
2925 #endif
2926 u8 *ies;
2927 u32 ies_len;
2928 u8 *p2p_ie;
2929 u32 p2p_ielen = 0;
2930 u8 result = P2P_STATUS_SUCCESS;
2931 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2932 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2933
2934 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
2935 while (p2p_ie) { /* Found the P2P IE. */
2936 u8 attr_content = 0x00, operatingch_info[5] = { 0x00 };
2937 u8 groupid[38] = { 0x00 };
2938 u32 attr_contentlen = 0;
2939
2940 pwdinfo->negotiation_dialog_token = 1;
2941 attr_contentlen = sizeof(attr_content);
2942 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
2943 if (attr_contentlen == 1) {
2944 RTW_INFO("[%s] Status = %d\n", __FUNCTION__, attr_content);
2945 result = attr_content;
2946
2947 if (attr_content == P2P_STATUS_SUCCESS) {
2948
2949 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
2950
2951 /* Commented by Albert 20100911 */
2952 /* Todo: Need to handle the case which both Intents are the same. */
2953 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2954 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2955 if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1))
2956 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2957 else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1))
2958 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2959 else {
2960 /* Have to compare the Tie Breaker */
2961 if (pwdinfo->peer_intent & 0x01)
2962 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2963 else
2964 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2965 }
2966
2967 #ifdef CONFIG_CONCURRENT_MODE
2968 if (rtw_mi_check_status(padapter, MI_LINKED)
2969 && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
2970 /* Switch back to the AP channel soon. */
2971 _set_timer(&prochinfo->ap_roch_ch_switch_timer, 100);
2972 }
2973 #endif
2974 } else {
2975 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2976 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2977 break;
2978 }
2979 }
2980
2981 /* Try to get the group id information */
2982 _rtw_memset(groupid, 0x00, 38);
2983 attr_contentlen = sizeof(groupid);
2984 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
2985 RTW_INFO("[%s] Ssid = %s, ssidlen = %zu\n", __FUNCTION__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]));
2986 _rtw_memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
2987 _rtw_memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
2988 }
2989
2990 attr_contentlen = sizeof(operatingch_info);
2991 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
2992 RTW_INFO("[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4]);
2993 pwdinfo->peer_operating_ch = operatingch_info[4];
2994 }
2995
2996 /* Get the next P2P IE */
2997 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2998
2999 }
3000
3001 return result ;
3002 }
3003
process_p2p_presence_req(struct wifidirect_info * pwdinfo,u8 * pframe,uint len)3004 u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
3005 {
3006 u8 *frame_body;
3007 u8 dialogToken = 0;
3008 u8 status = P2P_STATUS_SUCCESS;
3009
3010 frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
3011
3012 dialogToken = frame_body[6];
3013
3014 /* todo: check NoA attribute */
3015
3016 issue_p2p_presence_resp(pwdinfo, get_addr2_ptr(pframe), status, dialogToken);
3017
3018 return _TRUE;
3019 }
3020
find_phase_handler(_adapter * padapter)3021 void find_phase_handler(_adapter *padapter)
3022 {
3023 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3024 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3025 struct sitesurvey_parm parm;
3026 _irqL irqL;
3027 u8 _status = 0;
3028
3029
3030 rtw_init_sitesurvey_parm(padapter, &parm);
3031 _rtw_memcpy(&parm.ssid[0].Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
3032 parm.ssid[0].SsidLength = P2P_WILDCARD_SSID_LEN;
3033 parm.ssid_num = 1;
3034
3035 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
3036
3037 _enter_critical_bh(&pmlmepriv->lock, &irqL);
3038 _status = rtw_sitesurvey_cmd(padapter, &parm);
3039 _exit_critical_bh(&pmlmepriv->lock, &irqL);
3040
3041
3042 }
3043
restore_p2p_state_handler(_adapter * padapter)3044 void restore_p2p_state_handler(_adapter *padapter)
3045 {
3046 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3047
3048 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
3049 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3050
3051 #ifdef CONFIG_CONCURRENT_MODE
3052 if (rtw_mi_check_status(padapter, MI_LINKED)) {
3053 u8 union_ch = rtw_mi_get_union_chan(padapter);
3054 u8 union_bw = rtw_mi_get_union_bw(padapter);
3055 u8 union_offset = rtw_mi_get_union_offset(padapter);
3056
3057 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP)) {
3058 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
3059 rtw_back_opch(padapter);
3060 }
3061 }
3062 #endif
3063
3064 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3065
3066 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
3067 #ifdef CONFIG_CONCURRENT_MODE
3068 rtw_concurrent_handler(padapter);
3069 #else
3070 /* In the P2P client mode, the driver should not switch back to its listen channel */
3071 /* because this P2P client should stay at the operating channel of P2P GO. */
3072 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3073 #endif
3074 }
3075 }
3076
pre_tx_invitereq_handler(_adapter * padapter)3077 void pre_tx_invitereq_handler(_adapter *padapter)
3078 {
3079 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3080 u8 val8 = 1;
3081
3082 set_channel_bwmode(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3083 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3084 issue_probereq_p2p(padapter, NULL);
3085 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3086
3087 }
3088
pre_tx_provdisc_handler(_adapter * padapter)3089 void pre_tx_provdisc_handler(_adapter *padapter)
3090 {
3091 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3092 u8 val8 = 1;
3093
3094 set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3095 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3096 issue_probereq_p2p(padapter, NULL);
3097 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3098
3099 }
3100
pre_tx_negoreq_handler(_adapter * padapter)3101 void pre_tx_negoreq_handler(_adapter *padapter)
3102 {
3103 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3104 u8 val8 = 1;
3105
3106 set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3107 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3108 issue_probereq_p2p(padapter , NULL);
3109 /* WIN Phone only accept unicast probe request when nego back */
3110 issue_probereq_p2p(padapter , pwdinfo->nego_req_info.peerDevAddr);
3111 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3112
3113 }
3114
3115 #ifdef CONFIG_IOCTL_CFG80211
3116
3117 #if 0
3118 static void rtw_change_p2pie_op_ch(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
3119 {
3120 u8 *ies, *p2p_ie;
3121 u32 ies_len, p2p_ielen;
3122
3123 #ifdef CONFIG_MCC_MODE
3124 if (MCC_EN(padapter))
3125 return;
3126 #endif /* CONFIG_MCC_MODE */
3127
3128 ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3129 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3130
3131 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3132
3133 while (p2p_ie) {
3134 u32 attr_contentlen = 0;
3135 u8 *pattr = NULL;
3136
3137 /* Check P2P_ATTR_OPERATING_CH */
3138 attr_contentlen = 0;
3139 pattr = NULL;
3140 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
3141 if (pattr != NULL)
3142 *(pattr + 4) = ch;
3143
3144 /* Get the next P2P IE */
3145 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3146 }
3147 }
3148 #endif
3149
3150 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
rtw_change_p2pie_ch_list(_adapter * padapter,const u8 * frame_body,u32 len,u8 ch)3151 static void rtw_change_p2pie_ch_list(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
3152 {
3153 u8 *ies, *p2p_ie;
3154 u32 ies_len, p2p_ielen;
3155
3156 #ifdef CONFIG_MCC_MODE
3157 if (MCC_EN(padapter))
3158 return;
3159 #endif /* CONFIG_MCC_MODE */
3160
3161 ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3162 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3163
3164 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3165
3166 while (p2p_ie) {
3167 u32 attr_contentlen = 0;
3168 u8 *pattr = NULL;
3169
3170 /* Check P2P_ATTR_CH_LIST */
3171 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
3172 if (pattr != NULL) {
3173 int i;
3174 u32 num_of_ch;
3175 u8 *pattr_temp = pattr + 3 ;
3176
3177 attr_contentlen -= 3;
3178
3179 while (attr_contentlen > 0) {
3180 num_of_ch = *(pattr_temp + 1);
3181
3182 for (i = 0; i < num_of_ch; i++)
3183 *(pattr_temp + 2 + i) = ch;
3184
3185 pattr_temp += (2 + num_of_ch);
3186 attr_contentlen -= (2 + num_of_ch);
3187 }
3188 }
3189
3190 /* Get the next P2P IE */
3191 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3192 }
3193 }
3194 #endif
3195
3196 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
rtw_chk_p2pie_ch_list_with_buddy(_adapter * padapter,const u8 * frame_body,u32 len)3197 static bool rtw_chk_p2pie_ch_list_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
3198 {
3199 bool fit = _FALSE;
3200 u8 *ies, *p2p_ie;
3201 u32 ies_len, p2p_ielen;
3202 u8 union_ch = rtw_mi_get_union_chan(padapter);
3203
3204 ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3205 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3206
3207 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3208
3209 while (p2p_ie) {
3210 u32 attr_contentlen = 0;
3211 u8 *pattr = NULL;
3212
3213 /* Check P2P_ATTR_CH_LIST */
3214 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
3215 if (pattr != NULL) {
3216 int i;
3217 u32 num_of_ch;
3218 u8 *pattr_temp = pattr + 3 ;
3219
3220 attr_contentlen -= 3;
3221
3222 while (attr_contentlen > 0) {
3223 num_of_ch = *(pattr_temp + 1);
3224
3225 for (i = 0; i < num_of_ch; i++) {
3226 if (*(pattr_temp + 2 + i) == union_ch) {
3227 RTW_INFO(FUNC_ADPT_FMT" ch_list fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), union_ch);
3228 fit = _TRUE;
3229 break;
3230 }
3231 }
3232
3233 pattr_temp += (2 + num_of_ch);
3234 attr_contentlen -= (2 + num_of_ch);
3235 }
3236 }
3237
3238 /* Get the next P2P IE */
3239 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3240 }
3241
3242 return fit;
3243 }
3244
3245 #if defined(CONFIG_P2P_INVITE_IOT)
rtw_chk_p2pie_op_ch_with_buddy(_adapter * padapter,const u8 * frame_body,u32 len)3246 static bool rtw_chk_p2pie_op_ch_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
3247 {
3248 bool fit = _FALSE;
3249 u8 *ies, *p2p_ie;
3250 u32 ies_len, p2p_ielen;
3251 u8 union_ch = rtw_mi_get_union_chan(padapter);
3252
3253 ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3254 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3255
3256 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3257
3258 while (p2p_ie) {
3259 u32 attr_contentlen = 0;
3260 u8 *pattr = NULL;
3261
3262 /* Check P2P_ATTR_OPERATING_CH */
3263 attr_contentlen = 0;
3264 pattr = NULL;
3265 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
3266 if (pattr != NULL) {
3267 if (*(pattr + 4) == union_ch) {
3268 RTW_INFO(FUNC_ADPT_FMT" op_ch fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), union_ch);
3269 fit = _TRUE;
3270 break;
3271 }
3272 }
3273
3274 /* Get the next P2P IE */
3275 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3276 }
3277
3278 return fit;
3279 }
3280 #endif
3281
rtw_cfg80211_adjust_p2pie_channel(_adapter * padapter,const u8 * frame_body,u32 len)3282 static void rtw_cfg80211_adjust_p2pie_channel(_adapter *padapter, const u8 *frame_body, u32 len)
3283 {
3284 u8 *ies, *p2p_ie;
3285 u32 ies_len, p2p_ielen;
3286 u8 union_ch = rtw_mi_get_union_chan(padapter);
3287
3288 #ifdef CONFIG_MCC_MODE
3289 if (MCC_EN(padapter))
3290 return;
3291 #endif /* CONFIG_MCC_MODE */
3292
3293 ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3294 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3295
3296 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3297
3298 while (p2p_ie) {
3299 u32 attr_contentlen = 0;
3300 u8 *pattr = NULL;
3301
3302 /* Check P2P_ATTR_CH_LIST */
3303 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
3304 if (pattr != NULL) {
3305 int i;
3306 u32 num_of_ch;
3307 u8 *pattr_temp = pattr + 3 ;
3308
3309 attr_contentlen -= 3;
3310
3311 while (attr_contentlen > 0) {
3312 num_of_ch = *(pattr_temp + 1);
3313
3314 for (i = 0; i < num_of_ch; i++) {
3315 if (*(pattr_temp + 2 + i) && *(pattr_temp + 2 + i) != union_ch) {
3316 #ifdef RTW_SINGLE_WIPHY
3317 RTW_ERR("replace ch_list:%u with:%u\n", *(pattr_temp + 2 + i), union_ch);
3318 #endif
3319 *(pattr_temp + 2 + i) = union_ch; /*forcing to the same channel*/
3320 }
3321 }
3322
3323 pattr_temp += (2 + num_of_ch);
3324 attr_contentlen -= (2 + num_of_ch);
3325 }
3326 }
3327
3328 /* Check P2P_ATTR_OPERATING_CH */
3329 attr_contentlen = 0;
3330 pattr = NULL;
3331 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
3332 if (pattr != NULL) {
3333 if (*(pattr + 4) && *(pattr + 4) != union_ch) {
3334 #ifdef RTW_SINGLE_WIPHY
3335 RTW_ERR("replace op_ch:%u with:%u\n", *(pattr + 4), union_ch);
3336 #endif
3337 *(pattr + 4) = union_ch; /*forcing to the same channel */
3338 }
3339 }
3340
3341 /* Get the next P2P IE */
3342 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3343
3344 }
3345
3346 }
3347 #endif
3348
3349 #ifdef CONFIG_WFD
rtw_xframe_build_wfd_ie(struct xmit_frame * xframe)3350 u32 rtw_xframe_build_wfd_ie(struct xmit_frame *xframe)
3351 {
3352 _adapter *adapter = xframe->padapter;
3353 struct wifidirect_info *wdinfo = &adapter->wdinfo;
3354 u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
3355 u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
3356 u8 *frame_tail = frame + xframe->attrib.pktlen;
3357 u8 category, action, OUI_Subtype, dialogToken = 0;
3358 u32 wfdielen = 0;
3359
3360 category = frame_body[0];
3361 if (category == RTW_WLAN_CATEGORY_PUBLIC) {
3362 action = frame_body[1];
3363 if (action == ACT_PUBLIC_VENDOR
3364 && _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
3365 ) {
3366 OUI_Subtype = frame_body[6];
3367 dialogToken = frame_body[7];
3368
3369 switch (OUI_Subtype) {
3370 case P2P_GO_NEGO_REQ:
3371 wfdielen = build_nego_req_wfd_ie(wdinfo, frame_tail);
3372 break;
3373 case P2P_GO_NEGO_RESP:
3374 wfdielen = build_nego_resp_wfd_ie(wdinfo, frame_tail);
3375 break;
3376 case P2P_GO_NEGO_CONF:
3377 wfdielen = build_nego_confirm_wfd_ie(wdinfo, frame_tail);
3378 break;
3379 case P2P_INVIT_REQ:
3380 wfdielen = build_invitation_req_wfd_ie(wdinfo, frame_tail);
3381 break;
3382 case P2P_INVIT_RESP:
3383 wfdielen = build_invitation_resp_wfd_ie(wdinfo, frame_tail);
3384 break;
3385 case P2P_PROVISION_DISC_REQ:
3386 wfdielen = build_provdisc_req_wfd_ie(wdinfo, frame_tail);
3387 break;
3388 case P2P_PROVISION_DISC_RESP:
3389 wfdielen = build_provdisc_resp_wfd_ie(wdinfo, frame_tail);
3390 break;
3391 case P2P_DEVDISC_REQ:
3392 case P2P_DEVDISC_RESP:
3393 default:
3394 break;
3395 }
3396
3397 }
3398 } else if (category == RTW_WLAN_CATEGORY_P2P) {
3399 OUI_Subtype = frame_body[5];
3400 dialogToken = frame_body[6];
3401
3402 #ifdef CONFIG_DEBUG_CFG80211
3403 RTW_INFO("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n"
3404 , cpu_to_be32(*((u32 *)(frame_body + 1))), OUI_Subtype, dialogToken);
3405 #endif
3406
3407 switch (OUI_Subtype) {
3408 case P2P_NOTICE_OF_ABSENCE:
3409 break;
3410 case P2P_PRESENCE_REQUEST:
3411 break;
3412 case P2P_PRESENCE_RESPONSE:
3413 break;
3414 case P2P_GO_DISC_REQUEST:
3415 break;
3416 default:
3417 break;
3418 }
3419 } else
3420 RTW_INFO("%s, action frame category=%d\n", __func__, category);
3421
3422 xframe->attrib.pktlen += wfdielen;
3423
3424 return wfdielen;
3425 }
3426 #endif /* CONFIG_WFD */
3427
rtw_xframe_del_wfd_ie(struct xmit_frame * xframe)3428 bool rtw_xframe_del_wfd_ie(struct xmit_frame *xframe)
3429 {
3430 #define DBG_XFRAME_DEL_WFD_IE 0
3431 u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
3432 u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
3433 u8 *frame_tail = frame + xframe->attrib.pktlen;
3434 u8 category, action, OUI_Subtype;
3435 u8 *ies = NULL;
3436 uint ies_len_ori = 0;
3437 uint ies_len = 0;
3438
3439 category = frame_body[0];
3440 if (category == RTW_WLAN_CATEGORY_PUBLIC) {
3441 action = frame_body[1];
3442 if (action == ACT_PUBLIC_VENDOR
3443 && _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
3444 ) {
3445 OUI_Subtype = frame_body[6];
3446
3447 switch (OUI_Subtype) {
3448 case P2P_GO_NEGO_REQ:
3449 case P2P_GO_NEGO_RESP:
3450 case P2P_GO_NEGO_CONF:
3451 case P2P_INVIT_REQ:
3452 case P2P_INVIT_RESP:
3453 case P2P_PROVISION_DISC_REQ:
3454 case P2P_PROVISION_DISC_RESP:
3455 ies = frame_body + 8;
3456 ies_len_ori = frame_tail - (frame_body + 8);
3457 break;
3458 }
3459 }
3460 }
3461
3462 if (ies && ies_len_ori) {
3463 ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_XFRAME_DEL_WFD_IE ? __func__ : NULL);
3464 xframe->attrib.pktlen -= (ies_len_ori - ies_len);
3465 }
3466
3467 return ies_len_ori != ies_len;
3468 }
3469
3470 /*
3471 * rtw_xframe_chk_wfd_ie -
3472 *
3473 */
rtw_xframe_chk_wfd_ie(struct xmit_frame * xframe)3474 void rtw_xframe_chk_wfd_ie(struct xmit_frame *xframe)
3475 {
3476 _adapter *adapter = xframe->padapter;
3477 #ifdef CONFIG_IOCTL_CFG80211
3478 struct wifidirect_info *wdinfo = &adapter->wdinfo;
3479 #endif
3480 u8 build = 0;
3481 u8 del = 0;
3482
3483 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
3484 del = 1;
3485
3486 #ifdef CONFIG_IOCTL_CFG80211
3487 if (wdinfo->wfd_info->wfd_enable == _TRUE)
3488 #endif
3489 del = build = 1;
3490
3491 if (del)
3492 rtw_xframe_del_wfd_ie(xframe);
3493
3494 #ifdef CONFIG_WFD
3495 if (build)
3496 rtw_xframe_build_wfd_ie(xframe);
3497 #endif
3498 }
3499
dump_p2p_attr_ch_list(u8 * p2p_ie,uint p2p_ielen,u8 * buf,u32 buf_len)3500 u8 *dump_p2p_attr_ch_list(u8 *p2p_ie, uint p2p_ielen, u8 *buf, u32 buf_len)
3501 {
3502 uint attr_contentlen = 0;
3503 u8 *pattr = NULL;
3504 int w_sz = 0;
3505 u8 ch_cnt = 0;
3506 u8 ch_list[40];
3507
3508 pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, &attr_contentlen);
3509 if (pattr != NULL) {
3510 int i, j;
3511 u32 num_of_ch;
3512 u8 *pattr_temp = pattr + 3 ;
3513
3514 attr_contentlen -= 3;
3515
3516 _rtw_memset(ch_list, 0, 40);
3517
3518 while (attr_contentlen > 0) {
3519 num_of_ch = *(pattr_temp + 1);
3520
3521 for (i = 0; i < num_of_ch; i++) {
3522 for (j = 0; j < ch_cnt; j++) {
3523 if (ch_list[j] == *(pattr_temp + 2 + i))
3524 break;
3525 }
3526 if (j >= ch_cnt)
3527 ch_list[ch_cnt++] = *(pattr_temp + 2 + i);
3528
3529 }
3530
3531 pattr_temp += (2 + num_of_ch);
3532 attr_contentlen -= (2 + num_of_ch);
3533 }
3534
3535 for (j = 0; j < ch_cnt; j++) {
3536 if (j == 0)
3537 w_sz += snprintf(buf + w_sz, buf_len - w_sz, "%u", ch_list[j]);
3538 else if (ch_list[j] - ch_list[j - 1] != 1)
3539 w_sz += snprintf(buf + w_sz, buf_len - w_sz, ", %u", ch_list[j]);
3540 else if (j != ch_cnt - 1 && ch_list[j + 1] - ch_list[j] == 1) {
3541 /* empty */
3542 } else
3543 w_sz += snprintf(buf + w_sz, buf_len - w_sz, "-%u", ch_list[j]);
3544 }
3545 }
3546 return buf;
3547 }
3548
3549 /*
3550 * return _TRUE if requester is GO, _FALSE if responder is GO
3551 */
rtw_p2p_nego_intent_compare(u8 req,u8 resp)3552 bool rtw_p2p_nego_intent_compare(u8 req, u8 resp)
3553 {
3554 if (req >> 1 == resp >> 1)
3555 return req & 0x01 ? _TRUE : _FALSE;
3556 else if (req >> 1 > resp >> 1)
3557 return _TRUE;
3558 else
3559 return _FALSE;
3560 }
3561
rtw_p2p_check_frames(_adapter * padapter,const u8 * buf,u32 len,u8 tx)3562 int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx)
3563 {
3564 int is_p2p_frame = (-1);
3565 unsigned char *frame_body;
3566 u8 category, action, OUI_Subtype, dialogToken = 0;
3567 u8 *p2p_ie = NULL;
3568 uint p2p_ielen = 0;
3569 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
3570 int status = -1;
3571 u8 ch_list_buf[128] = {'\0'};
3572 int op_ch = -1;
3573 int listen_ch = -1;
3574 u8 intent = 0;
3575 u8 *iaddr = NULL;
3576 u8 *gbssid = NULL;
3577
3578 frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));
3579 category = frame_body[0];
3580 /* just for check */
3581 if (category == RTW_WLAN_CATEGORY_PUBLIC) {
3582 action = frame_body[1];
3583 if (action == ACT_PUBLIC_VENDOR
3584 && _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
3585 ) {
3586 OUI_Subtype = frame_body[6];
3587 dialogToken = frame_body[7];
3588 is_p2p_frame = OUI_Subtype;
3589
3590 #ifdef CONFIG_DEBUG_CFG80211
3591 RTW_INFO("ACTION_CATEGORY_PUBLIC: ACT_PUBLIC_VENDOR, OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
3592 cpu_to_be32(*((u32 *)(frame_body + 2))), OUI_Subtype, dialogToken);
3593 #endif
3594
3595 p2p_ie = rtw_get_p2p_ie(
3596 (u8 *)buf + sizeof(struct rtw_ieee80211_hdr_3addr) + _PUBLIC_ACTION_IE_OFFSET_
3597 , len - sizeof(struct rtw_ieee80211_hdr_3addr) - _PUBLIC_ACTION_IE_OFFSET_
3598 , NULL, &p2p_ielen);
3599
3600 switch (OUI_Subtype) { /* OUI Subtype */
3601 u8 *cont;
3602 uint cont_len;
3603 case P2P_GO_NEGO_REQ: {
3604 struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
3605
3606 if (tx) {
3607 #ifdef CONFIG_DRV_ISSUE_PROV_REQ /* IOT FOR S2 */
3608 if (pwdev_priv->provdisc_req_issued == _FALSE)
3609 rtw_cfg80211_issue_p2p_provision_request(padapter, buf, len);
3610 #endif /* CONFIG_DRV_ISSUE_PROV_REQ */
3611
3612 /* pwdev_priv->provdisc_req_issued = _FALSE; */
3613
3614 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3615 if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3616 rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
3617 #endif
3618 }
3619
3620 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
3621 if (cont)
3622 op_ch = *(cont + 4);
3623 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, NULL, &cont_len);
3624 if (cont)
3625 listen_ch = *(cont + 4);
3626 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len);
3627 if (cont)
3628 intent = *cont;
3629 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, NULL, &cont_len);
3630 if (cont && cont_len == 6)
3631 iaddr = cont;
3632
3633 if (nego_info->token != dialogToken)
3634 rtw_wdev_nego_info_init(nego_info);
3635
3636 _rtw_memcpy(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN);
3637 if (iaddr)
3638 _rtw_memcpy(tx ? nego_info->iface_addr : nego_info->peer_iface_addr, iaddr, ETH_ALEN);
3639 nego_info->active = tx ? 1 : 0;
3640 nego_info->token = dialogToken;
3641 nego_info->req_op_ch = op_ch;
3642 nego_info->req_listen_ch = listen_ch;
3643 nego_info->req_intent = intent;
3644 nego_info->state = 0;
3645
3646 dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
3647 RTW_INFO("RTW_%s:P2P_GO_NEGO_REQ, dialogToken=%d, intent:%u%s, listen_ch:%d, op_ch:%d, ch_list:%s"
3648 , (tx == _TRUE) ? "Tx" : "Rx" , dialogToken , (intent >> 1) , intent & 0x1 ? "+" : "-" , listen_ch , op_ch , ch_list_buf);
3649 if (iaddr)
3650 _RTW_INFO(", iaddr:"MAC_FMT, MAC_ARG(iaddr));
3651 _RTW_INFO("\n");
3652
3653 if (!tx) {
3654 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3655 if (rtw_mi_check_status(padapter, MI_LINKED)
3656 && rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE
3657 && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
3658 RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
3659 rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
3660 }
3661 #endif
3662 }
3663
3664 break;
3665 }
3666 case P2P_GO_NEGO_RESP: {
3667 struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
3668
3669 if (tx) {
3670 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3671 if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3672 rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
3673 #endif
3674 }
3675
3676 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
3677 if (cont)
3678 op_ch = *(cont + 4);
3679 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len);
3680 if (cont)
3681 intent = *cont;
3682 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3683 if (cont)
3684 status = *cont;
3685 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, NULL, &cont_len);
3686 if (cont && cont_len == 6)
3687 iaddr = cont;
3688
3689 if (nego_info->token == dialogToken && nego_info->state == 0
3690 && _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE
3691 ) {
3692 if (iaddr)
3693 _rtw_memcpy(tx ? nego_info->iface_addr : nego_info->peer_iface_addr, iaddr, ETH_ALEN);
3694 nego_info->status = (status == -1) ? 0xff : status;
3695 nego_info->rsp_op_ch = op_ch;
3696 nego_info->rsp_intent = intent;
3697 nego_info->state = 1;
3698 if (status != 0)
3699 nego_info->token = 0; /* init */
3700 }
3701
3702 dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
3703 RTW_INFO("RTW_%s:P2P_GO_NEGO_RESP, dialogToken=%d, intent:%u%s, status:%d, op_ch:%d, ch_list:%s"
3704 , (tx == _TRUE) ? "Tx" : "Rx", dialogToken, (intent >> 1), intent & 0x1 ? "+" : "-", status, op_ch, ch_list_buf);
3705 if (iaddr)
3706 _RTW_INFO(", iaddr:"MAC_FMT, MAC_ARG(iaddr));
3707 _RTW_INFO("\n");
3708
3709 if (!tx) {
3710 pwdev_priv->provdisc_req_issued = _FALSE;
3711 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3712 if (rtw_mi_check_status(padapter, MI_LINKED)
3713 && rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE
3714 && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
3715 RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
3716 rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
3717 }
3718 #endif
3719 }
3720
3721 break;
3722 }
3723 case P2P_GO_NEGO_CONF: {
3724 struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
3725 bool is_go = _FALSE;
3726
3727 if (tx) {
3728 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3729 if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3730 rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
3731 #endif
3732 }
3733
3734 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
3735 if (cont)
3736 op_ch = *(cont + 4);
3737 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3738 if (cont)
3739 status = *cont;
3740
3741 if (nego_info->token == dialogToken && nego_info->state == 1
3742 && _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE
3743 ) {
3744 nego_info->status = (status == -1) ? 0xff : status;
3745 nego_info->conf_op_ch = (op_ch == -1) ? 0 : op_ch;
3746 nego_info->state = 2;
3747
3748 if (status == 0) {
3749 if (rtw_p2p_nego_intent_compare(nego_info->req_intent, nego_info->rsp_intent) ^ !tx)
3750 is_go = _TRUE;
3751 }
3752
3753 nego_info->token = 0; /* init */
3754 }
3755
3756 dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
3757 RTW_INFO("RTW_%s:P2P_GO_NEGO_CONF, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s\n"
3758 , (tx == _TRUE) ? "Tx" : "Rx", dialogToken, status, op_ch, ch_list_buf);
3759
3760 if (!tx) {
3761 }
3762
3763 break;
3764 }
3765 case P2P_INVIT_REQ: {
3766 struct rtw_wdev_invit_info *invit_info = &pwdev_priv->invit_info;
3767 int flags = -1;
3768
3769 if (tx) {
3770 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3771 if (rtw_mi_check_status(padapter, MI_LINKED)
3772 && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3773 rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
3774 #endif
3775 }
3776
3777 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, NULL, &cont_len);
3778 if (cont)
3779 flags = *cont;
3780 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
3781 if (cont)
3782 op_ch = *(cont + 4);
3783 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, NULL, &cont_len);
3784 if (cont && cont_len == 6)
3785 gbssid = cont;
3786
3787 if (invit_info->token != dialogToken)
3788 rtw_wdev_invit_info_init(invit_info);
3789
3790 _rtw_memcpy(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN);
3791 if (gbssid)
3792 _rtw_memcpy(invit_info->group_bssid, gbssid, ETH_ALEN);
3793 invit_info->active = tx ? 1 : 0;
3794 invit_info->token = dialogToken;
3795 invit_info->flags = (flags == -1) ? 0x0 : flags;
3796 invit_info->req_op_ch = op_ch;
3797 invit_info->state = 0;
3798
3799 dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
3800 RTW_INFO("RTW_%s:P2P_INVIT_REQ, dialogToken=%d, flags:0x%02x, op_ch:%d, ch_list:%s"
3801 , (tx == _TRUE) ? "Tx" : "Rx", dialogToken, flags, op_ch, ch_list_buf);
3802 if (gbssid)
3803 _RTW_INFO(", gbssid:"MAC_FMT, MAC_ARG(gbssid));
3804 _RTW_INFO("\n");
3805
3806 if (!tx) {
3807 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3808 if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
3809 #if defined(CONFIG_P2P_INVITE_IOT)
3810 if (op_ch != -1 && rtw_chk_p2pie_op_ch_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
3811 RTW_INFO(FUNC_ADPT_FMT" op_ch:%u has no intersect with buddy\n", FUNC_ADPT_ARG(padapter), op_ch);
3812 rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
3813 } else
3814 #endif
3815 if (rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
3816 RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
3817 rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
3818 }
3819 }
3820 #endif
3821 }
3822
3823 break;
3824 }
3825 case P2P_INVIT_RESP: {
3826 struct rtw_wdev_invit_info *invit_info = &pwdev_priv->invit_info;
3827
3828 if (tx) {
3829 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3830 if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3831 rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
3832 #endif
3833 }
3834
3835 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3836 if (cont) {
3837 #ifdef CONFIG_P2P_INVITE_IOT
3838 if (tx && *cont == 7) {
3839 RTW_INFO("TX_P2P_INVITE_RESP, status is no common channel, change to unknown group\n");
3840 *cont = 8; /* unknow group status */
3841 }
3842 #endif /* CONFIG_P2P_INVITE_IOT */
3843 status = *cont;
3844 }
3845 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
3846 if (cont)
3847 op_ch = *(cont + 4);
3848 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, NULL, &cont_len);
3849 if (cont && cont_len == 6)
3850 gbssid = cont;
3851
3852 if (invit_info->token == dialogToken && invit_info->state == 0
3853 && _rtw_memcmp(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE
3854 ) {
3855 invit_info->status = (status == -1) ? 0xff : status;
3856 invit_info->rsp_op_ch = op_ch;
3857 invit_info->state = 1;
3858 invit_info->token = 0; /* init */
3859 }
3860
3861 dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
3862 RTW_INFO("RTW_%s:P2P_INVIT_RESP, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s"
3863 , (tx == _TRUE) ? "Tx" : "Rx", dialogToken, status, op_ch, ch_list_buf);
3864 if (gbssid)
3865 _RTW_INFO(", gbssid:"MAC_FMT, MAC_ARG(gbssid));
3866 _RTW_INFO("\n");
3867
3868 if (!tx) {
3869 }
3870
3871 break;
3872 }
3873 case P2P_DEVDISC_REQ:
3874 RTW_INFO("RTW_%s:P2P_DEVDISC_REQ, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
3875 break;
3876 case P2P_DEVDISC_RESP:
3877 cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3878 RTW_INFO("RTW_%s:P2P_DEVDISC_RESP, dialogToken=%d, status:%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken, cont ? *cont : -1);
3879 break;
3880 case P2P_PROVISION_DISC_REQ: {
3881 size_t frame_body_len = len - sizeof(struct rtw_ieee80211_hdr_3addr);
3882 u8 *p2p_ie;
3883 uint p2p_ielen = 0;
3884 uint contentlen = 0;
3885
3886 RTW_INFO("RTW_%s:P2P_PROVISION_DISC_REQ, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
3887
3888 /* if(tx) */
3889 {
3890 pwdev_priv->provdisc_req_issued = _FALSE;
3891
3892 p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
3893 if (p2p_ie) {
3894
3895 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, NULL, &contentlen)) {
3896 pwdev_priv->provdisc_req_issued = _FALSE;/* case: p2p_client join p2p GO */
3897 } else {
3898 #ifdef CONFIG_DEBUG_CFG80211
3899 RTW_INFO("provdisc_req_issued is _TRUE\n");
3900 #endif /*CONFIG_DEBUG_CFG80211*/
3901 pwdev_priv->provdisc_req_issued = _TRUE;/* case: p2p_devices connection before Nego req. */
3902 }
3903
3904 }
3905 }
3906 }
3907 break;
3908 case P2P_PROVISION_DISC_RESP:
3909 RTW_INFO("RTW_%s:P2P_PROVISION_DISC_RESP, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
3910 break;
3911 default:
3912 RTW_INFO("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", OUI_Subtype, dialogToken);
3913 break;
3914 }
3915
3916 }
3917
3918 } else if (category == RTW_WLAN_CATEGORY_P2P) {
3919 OUI_Subtype = frame_body[5];
3920 dialogToken = frame_body[6];
3921
3922 #ifdef CONFIG_DEBUG_CFG80211
3923 RTW_INFO("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
3924 cpu_to_be32(*((u32 *)(frame_body + 1))), OUI_Subtype, dialogToken);
3925 #endif
3926
3927 is_p2p_frame = OUI_Subtype;
3928
3929 switch (OUI_Subtype) {
3930 case P2P_NOTICE_OF_ABSENCE:
3931 RTW_INFO("RTW_%s:P2P_NOTICE_OF_ABSENCE, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
3932 break;
3933 case P2P_PRESENCE_REQUEST:
3934 RTW_INFO("RTW_%s:P2P_PRESENCE_REQUEST, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
3935 break;
3936 case P2P_PRESENCE_RESPONSE:
3937 RTW_INFO("RTW_%s:P2P_PRESENCE_RESPONSE, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
3938 break;
3939 case P2P_GO_DISC_REQUEST:
3940 RTW_INFO("RTW_%s:P2P_GO_DISC_REQUEST, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
3941 break;
3942 default:
3943 RTW_INFO("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", OUI_Subtype, dialogToken);
3944 break;
3945 }
3946
3947 }
3948
3949 return is_p2p_frame;
3950 }
3951 #endif /* CONFIG_IOCTL_CFG80211 */
3952
p2p_protocol_wk_hdl(_adapter * padapter,int intCmdType,u8 * buf)3953 s32 p2p_protocol_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf)
3954 {
3955 int ret = H2C_SUCCESS;
3956
3957 switch (intCmdType) {
3958 case P2P_FIND_PHASE_WK:
3959 find_phase_handler(padapter);
3960 break;
3961
3962 case P2P_RESTORE_STATE_WK:
3963 restore_p2p_state_handler(padapter);
3964 break;
3965
3966 case P2P_PRE_TX_PROVDISC_PROCESS_WK:
3967 #ifdef CONFIG_CONCURRENT_MODE
3968 if (rtw_mi_check_status(padapter, MI_LINKED))
3969 rtw_concurrent_handler(padapter);
3970 else
3971 pre_tx_provdisc_handler(padapter);
3972 #else
3973 pre_tx_provdisc_handler(padapter);
3974 #endif
3975 break;
3976
3977 case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
3978 #ifdef CONFIG_CONCURRENT_MODE
3979 if (rtw_mi_check_status(padapter, MI_LINKED))
3980 rtw_concurrent_handler(padapter);
3981 else
3982 pre_tx_invitereq_handler(padapter);
3983 #else
3984 pre_tx_invitereq_handler(padapter);
3985 #endif
3986 break;
3987
3988 case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
3989 #ifdef CONFIG_CONCURRENT_MODE
3990 if (rtw_mi_check_status(padapter, MI_LINKED))
3991 rtw_concurrent_handler(padapter);
3992 else
3993 pre_tx_negoreq_handler(padapter);
3994 #else
3995 pre_tx_negoreq_handler(padapter);
3996 #endif
3997 break;
3998
3999 default:
4000 rtw_warn_on(1);
4001 break;
4002 }
4003
4004 return ret;
4005 }
4006
process_p2p_cross_connect_ie(PADAPTER padapter,u8 * IEs,u32 IELength)4007 int process_p2p_cross_connect_ie(PADAPTER padapter, u8 *IEs, u32 IELength)
4008 {
4009 int ret = _TRUE;
4010 u8 *ies;
4011 u32 ies_len;
4012 u8 *p2p_ie;
4013 u32 p2p_ielen = 0;
4014 u8 p2p_attr[MAX_P2P_IE_LEN] = { 0x00 };/* NoA length should be n*(13) + 2 */
4015 u32 attr_contentlen = 0;
4016
4017
4018
4019 if (IELength <= _BEACON_IE_OFFSET_)
4020 return ret;
4021
4022 ies = IEs + _BEACON_IE_OFFSET_;
4023 ies_len = IELength - _BEACON_IE_OFFSET_;
4024
4025 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
4026
4027 while (p2p_ie) {
4028 /* Get P2P Manageability IE. */
4029 attr_contentlen = sizeof(p2p_attr);
4030 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_MANAGEABILITY, p2p_attr, &attr_contentlen)) {
4031 if ((p2p_attr[0] & (BIT(0) | BIT(1))) == 0x01)
4032 ret = _FALSE;
4033 break;
4034 }
4035 /* Get the next P2P IE */
4036 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
4037 }
4038
4039 return ret;
4040 }
4041
4042 #ifdef CONFIG_P2P_PS
process_p2p_ps_ie(PADAPTER padapter,u8 * IEs,u32 IELength)4043 void process_p2p_ps_ie(PADAPTER padapter, u8 *IEs, u32 IELength)
4044 {
4045 u8 *ies;
4046 u32 ies_len;
4047 u8 *p2p_ie;
4048 u32 p2p_ielen = 0;
4049 u8 *noa_attr; /* NoA length should be n*(13) + 2 */
4050 u32 attr_contentlen = 0;
4051
4052 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4053 u8 find_p2p = _FALSE, find_p2p_ps = _FALSE;
4054 u8 noa_offset, noa_num, noa_index;
4055
4056
4057 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4058 return;
4059 #ifdef CONFIG_CONCURRENT_MODE
4060 #ifndef CONFIG_FW_MULTI_PORT_SUPPORT
4061 if (padapter->hw_port != HW_PORT0)
4062 return;
4063 #endif
4064 #endif
4065 if (IELength <= _BEACON_IE_OFFSET_)
4066 return;
4067
4068 ies = IEs + _BEACON_IE_OFFSET_;
4069 ies_len = IELength - _BEACON_IE_OFFSET_;
4070
4071 p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
4072
4073 while (p2p_ie) {
4074 find_p2p = _TRUE;
4075 /* Get Notice of Absence IE. */
4076 noa_attr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, NULL, &attr_contentlen);
4077 if (noa_attr) {
4078 find_p2p_ps = _TRUE;
4079 noa_index = noa_attr[0];
4080
4081 if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
4082 (noa_index != pwdinfo->noa_index)) { /* if index change, driver should reconfigure related setting. */
4083 pwdinfo->noa_index = noa_index;
4084 pwdinfo->opp_ps = noa_attr[1] >> 7;
4085 if (pwdinfo->opp_ps != 1)
4086 pwdinfo->ctwindow = 0;
4087 else
4088 pwdinfo->ctwindow = noa_attr[1] & 0x7F;
4089 noa_offset = 2;
4090 noa_num = 0;
4091 /* NoA length should be n*(13) + 2 */
4092 if (attr_contentlen > 2 && (attr_contentlen - 2) % 13 == 0) {
4093 while (noa_offset < attr_contentlen && noa_num < P2P_MAX_NOA_NUM) {
4094 /* _rtw_memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */
4095 pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
4096 noa_offset += 1;
4097
4098 _rtw_memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
4099 noa_offset += 4;
4100
4101 _rtw_memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
4102 noa_offset += 4;
4103
4104 _rtw_memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
4105 noa_offset += 4;
4106
4107 noa_num++;
4108 }
4109 }
4110 pwdinfo->noa_num = noa_num;
4111
4112 if (pwdinfo->opp_ps == 1) {
4113 pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
4114 /* driver should wait LPS for entering CTWindow */
4115 if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
4116 p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
4117 } else if (pwdinfo->noa_num > 0) {
4118 pwdinfo->p2p_ps_mode = P2P_PS_NOA;
4119 p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
4120 } else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE)
4121 p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
4122 }
4123
4124 break; /* find target, just break. */
4125 }
4126
4127 /* Get the next P2P IE */
4128 p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
4129
4130 }
4131
4132 if (find_p2p == _TRUE) {
4133 if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && (find_p2p_ps == _FALSE))
4134 p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
4135 }
4136
4137 }
4138
p2p_ps_wk_hdl(_adapter * padapter,u8 p2p_ps_state)4139 void p2p_ps_wk_hdl(_adapter *padapter, u8 p2p_ps_state)
4140 {
4141 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
4142 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4143 u32 ps_deny = 0;
4144
4145 /* Pre action for p2p state */
4146 switch (p2p_ps_state) {
4147 case P2P_PS_DISABLE:
4148 pwdinfo->p2p_ps_state = p2p_ps_state;
4149
4150 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4151
4152 #ifdef CONFIG_LPS
4153 if (pwdinfo->opp_ps == 1) {
4154 if (pwrpriv->smart_ps == 0) {
4155 pwrpriv->smart_ps = 2;
4156 if (pwrpriv->pwr_mode != PS_MODE_ACTIVE)
4157 rtw_exec_lps(padapter, pwrpriv->pwr_mode);
4158 }
4159 }
4160 #endif /* CONFIG_LPS */
4161
4162 pwdinfo->noa_index = 0;
4163 pwdinfo->ctwindow = 0;
4164 pwdinfo->opp_ps = 0;
4165 pwdinfo->noa_num = 0;
4166 pwdinfo->p2p_ps_mode = P2P_PS_NONE;
4167
4168 break;
4169 case P2P_PS_ENABLE:
4170 _enter_pwrlock(&adapter_to_pwrctl(padapter)->lock);
4171 ps_deny = rtw_ps_deny_get(padapter);
4172 _exit_pwrlock(&adapter_to_pwrctl(padapter)->lock);
4173
4174 if ((ps_deny & (PS_DENY_SCAN | PS_DENY_JOIN))
4175 || rtw_mi_check_fwstate(padapter, (WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING))) {
4176 pwdinfo->p2p_ps_mode = P2P_PS_NONE;
4177 RTW_DBG(FUNC_ADPT_FMT" Block P2P PS under site survey or LINKING\n", FUNC_ADPT_ARG(padapter));
4178 return;
4179 }
4180 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
4181 #ifdef CONFIG_MCC_MODE
4182 if (MCC_EN(padapter)) {
4183 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
4184 RTW_INFO("P2P PS enble under MCC\n");
4185 rtw_warn_on(1);
4186 }
4187
4188 }
4189 #endif /* CONFIG_MCC_MODE */
4190 pwdinfo->p2p_ps_state = p2p_ps_state;
4191
4192 #ifdef CONFIG_LPS
4193 if (pwdinfo->ctwindow > 0) {
4194 if (pwrpriv->smart_ps != 0) {
4195 pwrpriv->smart_ps = 0;
4196 RTW_INFO("%s(): Enter CTW, change SmartPS\n", __FUNCTION__);
4197 if (pwrpriv->pwr_mode != PS_MODE_ACTIVE)
4198 rtw_exec_lps(padapter, pwrpriv->pwr_mode);
4199 }
4200 }
4201 #endif /* CONFIG_LPS */
4202
4203 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4204 }
4205 break;
4206 case P2P_PS_SCAN:
4207 case P2P_PS_SCAN_DONE:
4208 case P2P_PS_ALLSTASLEEP:
4209 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
4210 pwdinfo->p2p_ps_state = p2p_ps_state;
4211 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4212 }
4213 break;
4214 default:
4215 break;
4216 }
4217
4218 #ifdef CONFIG_MCC_MODE
4219 rtw_hal_mcc_process_noa(padapter);
4220 #endif /* CONFIG_MCC_MODE */
4221 }
4222
p2p_ps_wk_cmd(_adapter * padapter,u8 p2p_ps_state,u8 enqueue)4223 u8 p2p_ps_wk_cmd(_adapter *padapter, u8 p2p_ps_state, u8 enqueue)
4224 {
4225 struct cmd_obj *ph2c;
4226 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4227 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4228 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4229 u8 res = _SUCCESS;
4230
4231
4232 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
4233 #ifdef CONFIG_CONCURRENT_MODE
4234 #ifndef CONFIG_FW_MULTI_PORT_SUPPORT
4235 || (padapter->hw_port != HW_PORT0)
4236 #endif
4237 #endif
4238 )
4239 return res;
4240
4241 if (enqueue) {
4242 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4243 if (ph2c == NULL) {
4244 res = _FAIL;
4245 goto exit;
4246 }
4247
4248 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4249 if (pdrvextra_cmd_parm == NULL) {
4250 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
4251 res = _FAIL;
4252 goto exit;
4253 }
4254
4255 pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
4256 pdrvextra_cmd_parm->type = p2p_ps_state;
4257 pdrvextra_cmd_parm->size = 0;
4258 pdrvextra_cmd_parm->pbuf = NULL;
4259
4260 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4261
4262 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4263 } else
4264 p2p_ps_wk_hdl(padapter, p2p_ps_state);
4265
4266 exit:
4267
4268
4269 return res;
4270
4271 }
4272 #endif /* CONFIG_P2P_PS */
4273
reset_ch_sitesurvey_timer_process(void * FunctionContext)4274 static void reset_ch_sitesurvey_timer_process(void *FunctionContext)
4275 {
4276 _adapter *adapter = (_adapter *)FunctionContext;
4277 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4278
4279 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4280 return;
4281
4282 RTW_INFO("[%s] In\n", __FUNCTION__);
4283 /* Reset the operation channel information */
4284 pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
4285 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
4286 pwdinfo->rx_invitereq_info.operation_ch[1] = 0;
4287 pwdinfo->rx_invitereq_info.operation_ch[2] = 0;
4288 pwdinfo->rx_invitereq_info.operation_ch[3] = 0;
4289 #endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
4290 pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
4291 }
4292
reset_ch_sitesurvey_timer_process2(void * FunctionContext)4293 static void reset_ch_sitesurvey_timer_process2(void *FunctionContext)
4294 {
4295 _adapter *adapter = (_adapter *)FunctionContext;
4296 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4297
4298 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4299 return;
4300
4301 RTW_INFO("[%s] In\n", __FUNCTION__);
4302 /* Reset the operation channel information */
4303 pwdinfo->p2p_info.operation_ch[0] = 0;
4304 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
4305 pwdinfo->p2p_info.operation_ch[1] = 0;
4306 pwdinfo->p2p_info.operation_ch[2] = 0;
4307 pwdinfo->p2p_info.operation_ch[3] = 0;
4308 #endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
4309 pwdinfo->p2p_info.scan_op_ch_only = 0;
4310 }
4311
restore_p2p_state_timer_process(void * FunctionContext)4312 static void restore_p2p_state_timer_process(void *FunctionContext)
4313 {
4314 _adapter *adapter = (_adapter *)FunctionContext;
4315 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4316
4317 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4318 return;
4319
4320 p2p_protocol_wk_cmd(adapter, P2P_RESTORE_STATE_WK);
4321 }
4322
pre_tx_scan_timer_process(void * FunctionContext)4323 static void pre_tx_scan_timer_process(void *FunctionContext)
4324 {
4325 _adapter *adapter = (_adapter *) FunctionContext;
4326 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4327 _irqL irqL;
4328 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
4329
4330 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4331 return;
4332
4333 _enter_critical_bh(&pmlmepriv->lock, &irqL);
4334
4335
4336 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
4337 if (_TRUE == pwdinfo->tx_prov_disc_info.benable) { /* the provision discovery request frame is trigger to send or not */
4338 p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK);
4339 /* issue_probereq_p2p(adapter, NULL); */
4340 /* _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); */
4341 }
4342 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
4343 if (_TRUE == pwdinfo->nego_req_info.benable)
4344 p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK);
4345 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
4346 if (_TRUE == pwdinfo->invitereq_info.benable)
4347 p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK);
4348 } else
4349 RTW_INFO("[%s] p2p_state is %d, ignore!!\n", __FUNCTION__, rtw_p2p_state(pwdinfo));
4350
4351 _exit_critical_bh(&pmlmepriv->lock, &irqL);
4352 }
4353
find_phase_timer_process(void * FunctionContext)4354 static void find_phase_timer_process(void *FunctionContext)
4355 {
4356 _adapter *adapter = (_adapter *)FunctionContext;
4357 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4358
4359 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4360 return;
4361
4362 adapter->wdinfo.find_phase_state_exchange_cnt++;
4363
4364 p2p_protocol_wk_cmd(adapter, P2P_FIND_PHASE_WK);
4365 }
4366
reset_global_wifidirect_info(_adapter * padapter)4367 void reset_global_wifidirect_info(_adapter *padapter)
4368 {
4369 struct wifidirect_info *pwdinfo;
4370
4371 pwdinfo = &padapter->wdinfo;
4372 pwdinfo->persistent_supported = 0;
4373 pwdinfo->session_available = _TRUE;
4374 rtw_tdls_wfd_enable(padapter, 0);
4375 pwdinfo->wfd_tdls_weaksec = _TRUE;
4376 }
4377
4378 #ifdef CONFIG_WFD
rtw_init_wifi_display_info(_adapter * padapter)4379 int rtw_init_wifi_display_info(_adapter *padapter)
4380 {
4381 int res = _SUCCESS;
4382 struct wifi_display_info *pwfd_info = &padapter->wfd_info;
4383
4384 /* Used in P2P and TDLS */
4385 pwfd_info->init_rtsp_ctrlport = 554;
4386 #ifdef CONFIG_IOCTL_CFG80211
4387 pwfd_info->rtsp_ctrlport = 0;
4388 #else
4389 pwfd_info->rtsp_ctrlport = pwfd_info->init_rtsp_ctrlport; /* set non-zero value for legacy wfd */
4390 #endif
4391 pwfd_info->tdls_rtsp_ctrlport = 0;
4392 pwfd_info->peer_rtsp_ctrlport = 0; /* Reset to 0 */
4393 pwfd_info->wfd_enable = _FALSE;
4394 pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
4395 pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
4396
4397 /* Used in P2P */
4398 pwfd_info->peer_session_avail = _TRUE;
4399 pwfd_info->wfd_pc = _FALSE;
4400
4401 /* Used in TDLS */
4402 _rtw_memset(pwfd_info->ip_address, 0x00, 4);
4403 _rtw_memset(pwfd_info->peer_ip_address, 0x00, 4);
4404 return res;
4405
4406 }
4407
rtw_wfd_enable(_adapter * adapter,bool on)4408 inline void rtw_wfd_enable(_adapter *adapter, bool on)
4409 {
4410 struct wifi_display_info *wfdinfo = &adapter->wfd_info;
4411
4412 if (on) {
4413 wfdinfo->rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;
4414 wfdinfo->wfd_enable = _TRUE;
4415
4416 } else {
4417 wfdinfo->wfd_enable = _FALSE;
4418 wfdinfo->rtsp_ctrlport = 0;
4419 }
4420 }
4421
rtw_wfd_set_ctrl_port(_adapter * adapter,u16 port)4422 inline void rtw_wfd_set_ctrl_port(_adapter *adapter, u16 port)
4423 {
4424 struct wifi_display_info *wfdinfo = &adapter->wfd_info;
4425
4426 wfdinfo->init_rtsp_ctrlport = port;
4427 if (wfdinfo->wfd_enable == _TRUE)
4428 wfdinfo->rtsp_ctrlport = port;
4429 if (adapter->wdinfo.wfd_tdls_enable == 1)
4430 wfdinfo->tdls_rtsp_ctrlport = port;
4431 }
4432
rtw_tdls_wfd_enable(_adapter * adapter,bool on)4433 inline void rtw_tdls_wfd_enable(_adapter *adapter, bool on)
4434 {
4435 struct wifi_display_info *wfdinfo = &adapter->wfd_info;
4436
4437 if (on) {
4438 wfdinfo->tdls_rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;
4439 adapter->wdinfo.wfd_tdls_enable = 1;
4440
4441 } else {
4442 adapter->wdinfo.wfd_tdls_enable = 0;
4443 wfdinfo->tdls_rtsp_ctrlport = 0;
4444 }
4445 }
4446
rtw_append_beacon_wfd_ie(_adapter * adapter,u8 * pbuf)4447 u32 rtw_append_beacon_wfd_ie(_adapter *adapter, u8 *pbuf)
4448 {
4449 struct wifidirect_info *wdinfo = &adapter->wdinfo;
4450 struct mlme_priv *mlme = &adapter->mlmepriv;
4451 u8 build_ie_by_self = 0;
4452 u32 len = 0;
4453
4454 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4455 goto exit;
4456
4457 #ifdef CONFIG_IOCTL_CFG80211
4458 if (_TRUE == wdinfo->wfd_info->wfd_enable)
4459 #endif
4460 build_ie_by_self = 1;
4461
4462 if (build_ie_by_self)
4463 len = build_beacon_wfd_ie(wdinfo, pbuf);
4464 #ifdef CONFIG_IOCTL_CFG80211
4465 else if (mlme->wfd_beacon_ie && mlme->wfd_beacon_ie_len > 0) {
4466 len = mlme->wfd_beacon_ie_len;
4467 _rtw_memcpy(pbuf, mlme->wfd_beacon_ie, len);
4468 }
4469 #endif
4470
4471 exit:
4472 return len;
4473 }
4474
rtw_append_probe_req_wfd_ie(_adapter * adapter,u8 * pbuf)4475 u32 rtw_append_probe_req_wfd_ie(_adapter *adapter, u8 *pbuf)
4476 {
4477 struct wifidirect_info *wdinfo = &adapter->wdinfo;
4478 struct mlme_priv *mlme = &adapter->mlmepriv;
4479 u8 build_ie_by_self = 0;
4480 u32 len = 0;
4481
4482 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4483 goto exit;
4484
4485 #ifdef CONFIG_IOCTL_CFG80211
4486 if (_TRUE == wdinfo->wfd_info->wfd_enable)
4487 #endif
4488 build_ie_by_self = 1;
4489
4490 if (build_ie_by_self)
4491 len = build_probe_req_wfd_ie(wdinfo, pbuf);
4492 #ifdef CONFIG_IOCTL_CFG80211
4493 else if (mlme->wfd_probe_req_ie && mlme->wfd_probe_req_ie_len > 0) {
4494 len = mlme->wfd_probe_req_ie_len;
4495 _rtw_memcpy(pbuf, mlme->wfd_probe_req_ie, len);
4496 }
4497 #endif
4498
4499 exit:
4500 return len;
4501 }
4502
rtw_append_probe_resp_wfd_ie(_adapter * adapter,u8 * pbuf)4503 u32 rtw_append_probe_resp_wfd_ie(_adapter *adapter, u8 *pbuf)
4504 {
4505 struct wifidirect_info *wdinfo = &adapter->wdinfo;
4506 struct mlme_priv *mlme = &adapter->mlmepriv;
4507 u8 build_ie_by_self = 0;
4508 u32 len = 0;
4509
4510 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4511 goto exit;
4512
4513 #ifdef CONFIG_IOCTL_CFG80211
4514 if (_TRUE == wdinfo->wfd_info->wfd_enable)
4515 #endif
4516 build_ie_by_self = 1;
4517
4518 if (build_ie_by_self)
4519 len = build_probe_resp_wfd_ie(wdinfo, pbuf, 0);
4520 #ifdef CONFIG_IOCTL_CFG80211
4521 else if (mlme->wfd_probe_resp_ie && mlme->wfd_probe_resp_ie_len > 0) {
4522 len = mlme->wfd_probe_resp_ie_len;
4523 _rtw_memcpy(pbuf, mlme->wfd_probe_resp_ie, len);
4524 }
4525 #endif
4526
4527 exit:
4528 return len;
4529 }
4530
rtw_append_assoc_req_wfd_ie(_adapter * adapter,u8 * pbuf)4531 u32 rtw_append_assoc_req_wfd_ie(_adapter *adapter, u8 *pbuf)
4532 {
4533 struct wifidirect_info *wdinfo = &adapter->wdinfo;
4534 struct mlme_priv *mlme = &adapter->mlmepriv;
4535 u8 build_ie_by_self = 0;
4536 u32 len = 0;
4537
4538 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4539 goto exit;
4540
4541 #ifdef CONFIG_IOCTL_CFG80211
4542 if (_TRUE == wdinfo->wfd_info->wfd_enable)
4543 #endif
4544 build_ie_by_self = 1;
4545
4546 if (build_ie_by_self)
4547 len = build_assoc_req_wfd_ie(wdinfo, pbuf);
4548 #ifdef CONFIG_IOCTL_CFG80211
4549 else if (mlme->wfd_assoc_req_ie && mlme->wfd_assoc_req_ie_len > 0) {
4550 len = mlme->wfd_assoc_req_ie_len;
4551 _rtw_memcpy(pbuf, mlme->wfd_assoc_req_ie, len);
4552 }
4553 #endif
4554
4555 exit:
4556 return len;
4557 }
4558
rtw_append_assoc_resp_wfd_ie(_adapter * adapter,u8 * pbuf)4559 u32 rtw_append_assoc_resp_wfd_ie(_adapter *adapter, u8 *pbuf)
4560 {
4561 struct wifidirect_info *wdinfo = &adapter->wdinfo;
4562 struct mlme_priv *mlme = &adapter->mlmepriv;
4563 u8 build_ie_by_self = 0;
4564 u32 len = 0;
4565
4566 if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4567 goto exit;
4568
4569 #ifdef CONFIG_IOCTL_CFG80211
4570 if (_TRUE == wdinfo->wfd_info->wfd_enable)
4571 #endif
4572 build_ie_by_self = 1;
4573
4574 if (build_ie_by_self)
4575 len = build_assoc_resp_wfd_ie(wdinfo, pbuf);
4576 #ifdef CONFIG_IOCTL_CFG80211
4577 else if (mlme->wfd_assoc_resp_ie && mlme->wfd_assoc_resp_ie_len > 0) {
4578 len = mlme->wfd_assoc_resp_ie_len;
4579 _rtw_memcpy(pbuf, mlme->wfd_assoc_resp_ie, len);
4580 }
4581 #endif
4582
4583 exit:
4584 return len;
4585 }
4586
4587 #endif /* CONFIG_WFD */
4588
rtw_init_wifidirect_timers(_adapter * padapter)4589 void rtw_init_wifidirect_timers(_adapter *padapter)
4590 {
4591 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4592
4593 rtw_init_timer(&pwdinfo->find_phase_timer, padapter, find_phase_timer_process, padapter);
4594 rtw_init_timer(&pwdinfo->restore_p2p_state_timer, padapter, restore_p2p_state_timer_process, padapter);
4595 rtw_init_timer(&pwdinfo->pre_tx_scan_timer, padapter, pre_tx_scan_timer_process, padapter);
4596 rtw_init_timer(&pwdinfo->reset_ch_sitesurvey, padapter, reset_ch_sitesurvey_timer_process, padapter);
4597 rtw_init_timer(&pwdinfo->reset_ch_sitesurvey2, padapter, reset_ch_sitesurvey_timer_process2, padapter);
4598 }
4599
rtw_init_wifidirect_addrs(_adapter * padapter,u8 * dev_addr,u8 * iface_addr)4600 void rtw_init_wifidirect_addrs(_adapter *padapter, u8 *dev_addr, u8 *iface_addr)
4601 {
4602 #ifdef CONFIG_P2P
4603 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4604
4605 /*init device&interface address */
4606 if (dev_addr)
4607 _rtw_memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
4608 if (iface_addr)
4609 _rtw_memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
4610 #endif
4611 }
4612
init_wifidirect_info(_adapter * padapter,enum P2P_ROLE role)4613 void init_wifidirect_info(_adapter *padapter, enum P2P_ROLE role)
4614 {
4615 struct wifidirect_info *pwdinfo;
4616 #ifdef CONFIG_WFD
4617 struct wifi_display_info *pwfd_info = &padapter->wfd_info;
4618 #endif
4619 pwdinfo = &padapter->wdinfo;
4620
4621 pwdinfo->padapter = padapter;
4622
4623 /* 1, 6, 11 are the social channel defined in the WiFi Direct specification. */
4624 pwdinfo->social_chan[0] = 1;
4625 pwdinfo->social_chan[1] = 6;
4626 pwdinfo->social_chan[2] = 11;
4627 pwdinfo->social_chan[3] = 0; /* channel 0 for scanning ending in site survey function. */
4628
4629 if (role != P2P_ROLE_DISABLE
4630 && pwdinfo->driver_interface != DRIVER_CFG80211
4631 ) {
4632 #ifdef CONFIG_CONCURRENT_MODE
4633 u8 union_ch = 0;
4634
4635 if (rtw_mi_check_status(padapter, MI_LINKED))
4636 union_ch = rtw_mi_get_union_chan(padapter);
4637
4638 if (union_ch != 0 &&
4639 (union_ch == 1 || union_ch == 6 || union_ch == 11)
4640 ) {
4641 /* Use the AP's channel as the listen channel */
4642 /* This will avoid the channel switch between AP's channel and listen channel */
4643 pwdinfo->listen_channel = union_ch;
4644 } else
4645 #endif /* CONFIG_CONCURRENT_MODE */
4646 {
4647 /* Use the channel 11 as the listen channel */
4648 pwdinfo->listen_channel = 11;
4649 }
4650 }
4651
4652 if (role == P2P_ROLE_DEVICE) {
4653 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4654 #ifdef CONFIG_CONCURRENT_MODE
4655 if (rtw_mi_check_status(padapter, MI_LINKED))
4656 rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
4657 else
4658 #endif
4659 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
4660
4661 pwdinfo->intent = 1;
4662 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
4663 } else if (role == P2P_ROLE_CLIENT) {
4664 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4665 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
4666 pwdinfo->intent = 1;
4667 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
4668 } else if (role == P2P_ROLE_GO) {
4669 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
4670 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
4671 pwdinfo->intent = 15;
4672 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
4673 }
4674
4675 /* Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 ) */
4676 pwdinfo->support_rate[0] = 0x8c; /* 6(B) */
4677 pwdinfo->support_rate[1] = 0x92; /* 9(B) */
4678 pwdinfo->support_rate[2] = 0x18; /* 12 */
4679 pwdinfo->support_rate[3] = 0x24; /* 18 */
4680 pwdinfo->support_rate[4] = 0x30; /* 24 */
4681 pwdinfo->support_rate[5] = 0x48; /* 36 */
4682 pwdinfo->support_rate[6] = 0x60; /* 48 */
4683 pwdinfo->support_rate[7] = 0x6c; /* 54 */
4684
4685 _rtw_memcpy((void *) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);
4686
4687 _rtw_memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
4688 pwdinfo->device_name_len = 0;
4689
4690 _rtw_memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info));
4691 pwdinfo->invitereq_info.token = 3; /* Token used for P2P invitation request frame. */
4692
4693 _rtw_memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info));
4694 pwdinfo->inviteresp_info.token = 0;
4695
4696 pwdinfo->profileindex = 0;
4697 _rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
4698
4699 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
4700
4701 pwdinfo->listen_dwell = (u8)((rtw_get_current_time() % 3) + 1);
4702 /* RTW_INFO( "[%s] listen_dwell time is %d00ms\n", __FUNCTION__, pwdinfo->listen_dwell ); */
4703
4704 _rtw_memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info));
4705 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
4706
4707 _rtw_memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
4708
4709 pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
4710 pwdinfo->negotiation_dialog_token = 1;
4711
4712 _rtw_memset(pwdinfo->nego_ssid, 0x00, WLAN_SSID_MAXLEN);
4713 pwdinfo->nego_ssidlen = 0;
4714
4715 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
4716 #ifdef CONFIG_WFD
4717 pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC;
4718 pwdinfo->wfd_info = pwfd_info;
4719 #else
4720 pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
4721 #endif /* CONFIG_WFD */
4722 pwdinfo->channel_list_attr_len = 0;
4723 _rtw_memset(pwdinfo->channel_list_attr, 0x00, 100);
4724
4725 _rtw_memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4);
4726 _rtw_memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3);
4727 _rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
4728 #ifdef CONFIG_CONCURRENT_MODE
4729 #ifdef CONFIG_IOCTL_CFG80211
4730 pwdinfo->ext_listen_interval = 1000; /* The interval to be available with legacy AP during p2p0-find/scan */
4731 pwdinfo->ext_listen_period = 3000; /* The time period to be available for P2P during nego */
4732 #else /* !CONFIG_IOCTL_CFG80211 */
4733 /* pwdinfo->ext_listen_interval = 3000; */
4734 /* pwdinfo->ext_listen_period = 400; */
4735 pwdinfo->ext_listen_interval = 1000;
4736 pwdinfo->ext_listen_period = 1000;
4737 #endif /* !CONFIG_IOCTL_CFG80211 */
4738 #endif
4739
4740 /* Commented by Kurt 20130319
4741 * For WiDi purpose: Use CFG80211 interface but controled WFD/RDS frame by driver itself. */
4742 #ifdef CONFIG_IOCTL_CFG80211
4743 pwdinfo->driver_interface = DRIVER_CFG80211;
4744 #else
4745 pwdinfo->driver_interface = DRIVER_WEXT;
4746 #endif /* CONFIG_IOCTL_CFG80211 */
4747
4748 pwdinfo->wfd_tdls_enable = 0;
4749 _rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
4750 _rtw_memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN);
4751
4752 pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
4753 pwdinfo->rx_invitereq_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
4754 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
4755 pwdinfo->rx_invitereq_info.operation_ch[2] = 0;
4756 pwdinfo->rx_invitereq_info.operation_ch[3] = 0;
4757 pwdinfo->rx_invitereq_info.operation_ch[4] = 0;
4758 #endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
4759 pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
4760 pwdinfo->p2p_info.operation_ch[0] = 0;
4761 pwdinfo->p2p_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
4762 #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
4763 pwdinfo->p2p_info.operation_ch[2] = 0;
4764 pwdinfo->p2p_info.operation_ch[3] = 0;
4765 pwdinfo->p2p_info.operation_ch[4] = 0;
4766 #endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
4767 pwdinfo->p2p_info.scan_op_ch_only = 0;
4768 }
4769
_rtw_p2p_set_role(struct wifidirect_info * wdinfo,enum P2P_ROLE role)4770 void _rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role)
4771 {
4772 if (wdinfo->role != role) {
4773 wdinfo->role = role;
4774 rtw_mi_update_iface_status(&(wdinfo->padapter->mlmepriv), 0);
4775 }
4776 }
4777
4778 #ifdef CONFIG_DBG_P2P
4779
4780 /**
4781 * rtw_p2p_role_txt - Get the p2p role name as a text string
4782 * @role: P2P role
4783 * Returns: The state name as a printable text string
4784 */
rtw_p2p_role_txt(enum P2P_ROLE role)4785 const char *rtw_p2p_role_txt(enum P2P_ROLE role)
4786 {
4787 switch (role) {
4788 case P2P_ROLE_DISABLE:
4789 return "P2P_ROLE_DISABLE";
4790 case P2P_ROLE_DEVICE:
4791 return "P2P_ROLE_DEVICE";
4792 case P2P_ROLE_CLIENT:
4793 return "P2P_ROLE_CLIENT";
4794 case P2P_ROLE_GO:
4795 return "P2P_ROLE_GO";
4796 default:
4797 return "UNKNOWN";
4798 }
4799 }
4800
4801 /**
4802 * rtw_p2p_state_txt - Get the p2p state name as a text string
4803 * @state: P2P state
4804 * Returns: The state name as a printable text string
4805 */
rtw_p2p_state_txt(enum P2P_STATE state)4806 const char *rtw_p2p_state_txt(enum P2P_STATE state)
4807 {
4808 switch (state) {
4809 case P2P_STATE_NONE:
4810 return "P2P_STATE_NONE";
4811 case P2P_STATE_IDLE:
4812 return "P2P_STATE_IDLE";
4813 case P2P_STATE_LISTEN:
4814 return "P2P_STATE_LISTEN";
4815 case P2P_STATE_SCAN:
4816 return "P2P_STATE_SCAN";
4817 case P2P_STATE_FIND_PHASE_LISTEN:
4818 return "P2P_STATE_FIND_PHASE_LISTEN";
4819 case P2P_STATE_FIND_PHASE_SEARCH:
4820 return "P2P_STATE_FIND_PHASE_SEARCH";
4821 case P2P_STATE_TX_PROVISION_DIS_REQ:
4822 return "P2P_STATE_TX_PROVISION_DIS_REQ";
4823 case P2P_STATE_RX_PROVISION_DIS_RSP:
4824 return "P2P_STATE_RX_PROVISION_DIS_RSP";
4825 case P2P_STATE_RX_PROVISION_DIS_REQ:
4826 return "P2P_STATE_RX_PROVISION_DIS_REQ";
4827 case P2P_STATE_GONEGO_ING:
4828 return "P2P_STATE_GONEGO_ING";
4829 case P2P_STATE_GONEGO_OK:
4830 return "P2P_STATE_GONEGO_OK";
4831 case P2P_STATE_GONEGO_FAIL:
4832 return "P2P_STATE_GONEGO_FAIL";
4833 case P2P_STATE_RECV_INVITE_REQ_MATCH:
4834 return "P2P_STATE_RECV_INVITE_REQ_MATCH";
4835 case P2P_STATE_PROVISIONING_ING:
4836 return "P2P_STATE_PROVISIONING_ING";
4837 case P2P_STATE_PROVISIONING_DONE:
4838 return "P2P_STATE_PROVISIONING_DONE";
4839 case P2P_STATE_TX_INVITE_REQ:
4840 return "P2P_STATE_TX_INVITE_REQ";
4841 case P2P_STATE_RX_INVITE_RESP_OK:
4842 return "P2P_STATE_RX_INVITE_RESP_OK";
4843 case P2P_STATE_RECV_INVITE_REQ_DISMATCH:
4844 return "P2P_STATE_RECV_INVITE_REQ_DISMATCH";
4845 case P2P_STATE_RECV_INVITE_REQ_GO:
4846 return "P2P_STATE_RECV_INVITE_REQ_GO";
4847 case P2P_STATE_RECV_INVITE_REQ_JOIN:
4848 return "P2P_STATE_RECV_INVITE_REQ_JOIN";
4849 case P2P_STATE_RX_INVITE_RESP_FAIL:
4850 return "P2P_STATE_RX_INVITE_RESP_FAIL";
4851 case P2P_STATE_RX_INFOR_NOREADY:
4852 return "P2P_STATE_RX_INFOR_NOREADY";
4853 case P2P_STATE_TX_INFOR_NOREADY:
4854 return "P2P_STATE_TX_INFOR_NOREADY";
4855 default:
4856 return "UNKNOWN";
4857 }
4858 }
4859
dbg_rtw_p2p_set_state(struct wifidirect_info * wdinfo,enum P2P_STATE state,const char * caller,int line)4860 void dbg_rtw_p2p_set_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)
4861 {
4862 if (!_rtw_p2p_chk_state(wdinfo, state)) {
4863 enum P2P_STATE old_state = _rtw_p2p_state(wdinfo);
4864 _rtw_p2p_set_state(wdinfo, state);
4865 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_state from %s to %s\n", caller, line
4866 , rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))
4867 );
4868 } else {
4869 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_state to same state %s\n", caller, line
4870 , rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))
4871 );
4872 }
4873 }
dbg_rtw_p2p_set_pre_state(struct wifidirect_info * wdinfo,enum P2P_STATE state,const char * caller,int line)4874 void dbg_rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)
4875 {
4876 if (_rtw_p2p_pre_state(wdinfo) != state) {
4877 enum P2P_STATE old_state = _rtw_p2p_pre_state(wdinfo);
4878 _rtw_p2p_set_pre_state(wdinfo, state);
4879 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_pre_state from %s to %s\n", caller, line
4880 , rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))
4881 );
4882 } else {
4883 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_pre_state to same state %s\n", caller, line
4884 , rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))
4885 );
4886 }
4887 }
4888 #if 0
4889 void dbg_rtw_p2p_restore_state(struct wifidirect_info *wdinfo, const char *caller, int line)
4890 {
4891 if (wdinfo->pre_p2p_state != -1) {
4892 RTW_INFO("[CONFIG_DBG_P2P]%s:%d restore from %s to %s\n", caller, line
4893 , p2p_state_str[wdinfo->p2p_state], p2p_state_str[wdinfo->pre_p2p_state]
4894 );
4895 _rtw_p2p_restore_state(wdinfo);
4896 } else {
4897 RTW_INFO("[CONFIG_DBG_P2P]%s:%d restore no pre state, cur state %s\n", caller, line
4898 , p2p_state_str[wdinfo->p2p_state]
4899 );
4900 }
4901 }
4902 #endif
dbg_rtw_p2p_set_role(struct wifidirect_info * wdinfo,enum P2P_ROLE role,const char * caller,int line)4903 void dbg_rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role, const char *caller, int line)
4904 {
4905 if (wdinfo->role != role) {
4906 enum P2P_ROLE old_role = wdinfo->role;
4907 _rtw_p2p_set_role(wdinfo, role);
4908 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_role from %s to %s\n", caller, line
4909 , rtw_p2p_role_txt(old_role), rtw_p2p_role_txt(wdinfo->role)
4910 );
4911 } else {
4912 RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_role to same role %s\n", caller, line
4913 , rtw_p2p_role_txt(wdinfo->role)
4914 );
4915 }
4916 }
4917 #endif /* CONFIG_DBG_P2P */
4918
4919
rtw_p2p_enable(_adapter * padapter,enum P2P_ROLE role)4920 int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role)
4921 {
4922 int ret = _SUCCESS;
4923 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4924 #ifdef CONFIG_CONCURRENT_MODE
4925 struct roch_info *prochinfo = &padapter->rochinfo;
4926 #endif
4927
4928 if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT || role == P2P_ROLE_GO) {
4929 #if defined(CONFIG_CONCURRENT_MODE) && (!defined(RTW_P2P_GROUP_INTERFACE) || !RTW_P2P_GROUP_INTERFACE)
4930 /* Commented by Albert 2011/12/30 */
4931 /* The driver just supports 1 P2P group operation. */
4932 /* So, this function will do nothing if the buddy adapter had enabled the P2P function. */
4933 /*if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))
4934 return ret;*/
4935 /* Only selected interface can be P2P interface */
4936 if (padapter->iface_id != padapter->registrypriv.sel_p2p_iface) {
4937 RTW_ERR("%s, iface_id:%d is not P2P interface!\n", __func__, padapter->iface_id);
4938 ret = _FAIL;
4939 return ret;
4940 }
4941 #endif /* CONFIG_CONCURRENT_MODE */
4942
4943 /* leave IPS/Autosuspend */
4944 if (_FAIL == rtw_pwr_wakeup(padapter)) {
4945 ret = _FAIL;
4946 goto exit;
4947 }
4948
4949 /* Added by Albert 2011/03/22 */
4950 /* In the P2P mode, the driver should not support the b mode. */
4951 /* So, the Tx packet shouldn't use the CCK rate */
4952 #ifdef CONFIG_IOCTL_CFG80211
4953 if (rtw_cfg80211_iface_has_p2p_group_cap(padapter))
4954 #endif
4955 update_tx_basic_rate(padapter, WIRELESS_11AGN);
4956
4957 /* Enable P2P function */
4958 init_wifidirect_info(padapter, role);
4959
4960 #ifdef CONFIG_IOCTL_CFG80211
4961 if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
4962 adapter_wdev_data(padapter)->p2p_enabled = _TRUE;
4963 #endif
4964
4965 rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, _TRUE);
4966 #ifdef CONFIG_WFD
4967 if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
4968 rtw_hal_set_odm_var(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, _TRUE);
4969 #endif
4970
4971 } else if (role == P2P_ROLE_DISABLE) {
4972
4973 #ifdef CONFIG_IOCTL_CFG80211
4974 if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
4975 adapter_wdev_data(padapter)->p2p_enabled = _FALSE;
4976 #endif
4977
4978 pwdinfo->listen_channel = 0;
4979
4980 /* Disable P2P function */
4981 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
4982 _cancel_timer_ex(&pwdinfo->find_phase_timer);
4983 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
4984 _cancel_timer_ex(&pwdinfo->pre_tx_scan_timer);
4985 _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
4986 _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey2);
4987 reset_ch_sitesurvey_timer_process(padapter);
4988 reset_ch_sitesurvey_timer_process2(padapter);
4989 #ifdef CONFIG_CONCURRENT_MODE
4990 _cancel_timer_ex(&prochinfo->ap_roch_ch_switch_timer);
4991 #endif
4992 rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
4993 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_NONE);
4994 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
4995 _rtw_memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
4996
4997 /* Remove profiles in wifidirect_info structure. */
4998 _rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
4999 pwdinfo->profileindex = 0;
5000 }
5001
5002 rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, _FALSE);
5003 #ifdef CONFIG_WFD
5004 if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
5005 rtw_hal_set_odm_var(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, _FALSE);
5006 #endif
5007
5008 if (_FAIL == rtw_pwr_wakeup(padapter)) {
5009 ret = _FAIL;
5010 goto exit;
5011 }
5012
5013 /* Restore to initial setting. */
5014 update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
5015
5016 /* For WiDi purpose. */
5017 #ifdef CONFIG_IOCTL_CFG80211
5018 pwdinfo->driver_interface = DRIVER_CFG80211;
5019 #else
5020 pwdinfo->driver_interface = DRIVER_WEXT;
5021 #endif /* CONFIG_IOCTL_CFG80211 */
5022
5023 }
5024
5025 exit:
5026 return ret;
5027 }
5028
5029 #endif /* CONFIG_P2P */
5030