Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
nu11secur1ty
GitHub Repository: nu11secur1ty/Kali-Linux
Path: blob/master/ALFA-W1F1/RTL8814AU/core/rtw_p2p.c
1307 views
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
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
34
int is_any_client_associated(_adapter *padapter)
35
{
36
return padapter->stapriv.asoc_list_cnt ? _TRUE : _FALSE;
37
}
38
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
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
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
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
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
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
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, _FW_LINKED) == _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
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, _FW_LINKED) == _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
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, _FW_LINKED) == _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
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, _FW_LINKED) == _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
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, _FW_LINKED) == _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
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, _FW_LINKED) == _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
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, _FW_LINKED) == _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
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, _FW_LINKED) == _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
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, _FW_LINKED) == _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
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, _FW_LINKED) == _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
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, _FW_LINKED) == _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
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, _FW_LINKED) == _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
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
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
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
2182
u32 build_deauth_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
2183
{
2184
u32 len = 0;
2185
2186
return len;
2187
}
2188
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
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
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *) &attr_contentlen)) {
2291
RTW_INFO("[%s] Got P2P Capability Attr!!\n", __FUNCTION__);
2292
cap_attr = le16_to_cpu(cap_attr);
2293
psta->dev_cap = cap_attr & 0xff;
2294
}
2295
2296
/* Check Extended Listen Timing ATTR */
2297
2298
2299
/* Check P2P Device Info ATTR */
2300
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint *)&attr_contentlen)) {
2301
RTW_INFO("[%s] Got P2P DEVICE INFO Attr!!\n", __FUNCTION__);
2302
pattr_content = pbuf = rtw_zmalloc(attr_contentlen);
2303
if (pattr_content) {
2304
u8 num_of_secdev_type;
2305
u16 dev_name_len;
2306
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
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
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
2388
if (_rtw_memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
2389
_rtw_memcmp(pwdinfo->p2p_group_ssid, groupid + ETH_ALEN, pwdinfo->p2p_group_ssid_len)) {
2390
attr_contentlen = 0;
2391
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_ID, dev_addr, &attr_contentlen)) {
2392
_irqL irqL;
2393
_list *phead, *plist;
2394
2395
_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2396
phead = &pstapriv->asoc_list;
2397
plist = get_next(phead);
2398
2399
/* look up sta asoc_queue */
2400
while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
2401
psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
2402
2403
plist = get_next(plist);
2404
2405
if (psta->is_p2p_device && (psta->dev_cap & P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
2406
_rtw_memcmp(psta->dev_addr, dev_addr, ETH_ALEN)) {
2407
2408
/* _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); */
2409
/* issue GO Discoverability Request */
2410
issue_group_disc_req(pwdinfo, psta->cmn.mac_addr);
2411
/* _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); */
2412
2413
status = P2P_STATUS_SUCCESS;
2414
2415
break;
2416
} else
2417
status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2418
2419
}
2420
_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
2421
2422
} else
2423
status = P2P_STATUS_FAIL_INVALID_PARAM;
2424
2425
} else
2426
status = P2P_STATUS_FAIL_INVALID_PARAM;
2427
2428
}
2429
2430
}
2431
2432
2433
/* issue Device Discoverability Response */
2434
issue_p2p_devdisc_resp(pwdinfo, get_addr2_ptr(pframe), status, dialogToken);
2435
2436
2437
return (status == P2P_STATUS_SUCCESS) ? _TRUE : _FALSE;
2438
2439
}
2440
2441
u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2442
{
2443
return _TRUE;
2444
}
2445
2446
u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2447
{
2448
u8 *frame_body;
2449
u8 *wpsie;
2450
uint wps_ielen = 0, attr_contentlen = 0;
2451
u16 uconfig_method = 0;
2452
2453
2454
frame_body = (pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2455
2456
wpsie = rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
2457
if (wpsie) {
2458
if (rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD , (u8 *) &uconfig_method, &attr_contentlen)) {
2459
uconfig_method = be16_to_cpu(uconfig_method);
2460
switch (uconfig_method) {
2461
case WPS_CM_DISPLYA: {
2462
_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2463
break;
2464
}
2465
case WPS_CM_LABEL: {
2466
_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "lab", 3);
2467
break;
2468
}
2469
case WPS_CM_PUSH_BUTTON: {
2470
_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2471
break;
2472
}
2473
case WPS_CM_KEYPAD: {
2474
_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2475
break;
2476
}
2477
}
2478
issue_p2p_provision_resp(pwdinfo, get_addr2_ptr(pframe), frame_body, uconfig_method);
2479
}
2480
}
2481
RTW_INFO("[%s] config method = %s\n", __FUNCTION__, pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
2482
return _TRUE;
2483
2484
}
2485
2486
u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe)
2487
{
2488
2489
return _TRUE;
2490
}
2491
2492
u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
2493
{
2494
u8 i = 0, j = 0;
2495
u8 temp = 0;
2496
u8 ch_no = 0;
2497
ch_content += 3;
2498
ch_cnt -= 3;
2499
2500
while (ch_cnt > 0) {
2501
ch_content += 1;
2502
ch_cnt -= 1;
2503
temp = *ch_content;
2504
for (i = 0 ; i < temp ; i++, j++)
2505
peer_ch_list[j] = *(ch_content + 1 + i);
2506
ch_content += (temp + 1);
2507
ch_cnt -= (temp + 1);
2508
ch_no += temp ;
2509
}
2510
2511
return ch_no;
2512
}
2513
2514
u8 rtw_p2p_ch_inclusion(_adapter *adapter, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
2515
{
2516
struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
2517
int i = 0, j = 0, temp = 0;
2518
u8 ch_no = 0;
2519
2520
for (i = 0; i < peer_ch_num; i++) {
2521
for (j = temp; j < rfctl->max_chan_nums; j++) {
2522
if (*(peer_ch_list + i) == rfctl->channel_set[j].ChannelNum) {
2523
ch_list_inclusioned[ch_no++] = *(peer_ch_list + i);
2524
temp = j;
2525
break;
2526
}
2527
}
2528
}
2529
2530
return ch_no;
2531
}
2532
2533
u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2534
{
2535
_adapter *padapter = pwdinfo->padapter;
2536
u8 result = P2P_STATUS_SUCCESS;
2537
u32 p2p_ielen = 0, wps_ielen = 0;
2538
u8 *ies;
2539
u32 ies_len;
2540
u8 *p2p_ie;
2541
u8 *wpsie;
2542
u16 wps_devicepassword_id = 0x0000;
2543
uint wps_devicepassword_id_len = 0;
2544
#ifdef CONFIG_WFD
2545
#ifdef CONFIG_TDLS
2546
struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
2547
#endif /* CONFIG_TDLS */
2548
#endif /* CONFIG_WFD */
2549
wpsie = rtw_get_wps_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
2550
if (wpsie) {
2551
/* Commented by Kurt 20120113 */
2552
/* If some device wants to do p2p handshake without sending prov_disc_req */
2553
/* We have to get peer_req_cm from here. */
2554
if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
2555
rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8 *) &wps_devicepassword_id, &wps_devicepassword_id_len);
2556
wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
2557
2558
if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2559
_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2560
else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2561
_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2562
else
2563
_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2564
}
2565
} else {
2566
RTW_INFO("[%s] WPS IE not Found!!\n", __FUNCTION__);
2567
result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2568
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2569
return result ;
2570
}
2571
2572
ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2573
ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2574
2575
p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
2576
2577
if (!p2p_ie) {
2578
RTW_INFO("[%s] P2P IE not Found!!\n", __FUNCTION__);
2579
result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2580
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2581
}
2582
2583
while (p2p_ie) {
2584
u8 attr_content = 0x00;
2585
u32 attr_contentlen = 0;
2586
u8 ch_content[100] = { 0x00 };
2587
uint ch_cnt = 0;
2588
u8 peer_ch_list[100] = { 0x00 };
2589
u8 peer_ch_num = 0;
2590
u8 ch_list_inclusioned[100] = { 0x00 };
2591
u8 ch_num_inclusioned = 0;
2592
u16 cap_attr;
2593
u8 listen_ch_attr[5] = { 0x00 };
2594
2595
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
2596
2597
/* Check P2P Capability ATTR */
2598
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *)&attr_contentlen)) {
2599
cap_attr = le16_to_cpu(cap_attr);
2600
2601
#if defined(CONFIG_WFD) && defined(CONFIG_TDLS)
2602
if (!(cap_attr & P2P_GRPCAP_INTRABSS))
2603
ptdlsinfo->ap_prohibited = _TRUE;
2604
#endif /* defined(CONFIG_WFD) && defined(CONFIG_TDLS) */
2605
}
2606
2607
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen)) {
2608
RTW_INFO("[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01);
2609
pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2610
2611
if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
2612
/* Try to match the tie breaker value */
2613
if (pwdinfo->intent == P2P_MAX_INTENT) {
2614
rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2615
result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2616
} else {
2617
if (attr_content & 0x01)
2618
rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2619
else
2620
rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2621
}
2622
} else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))
2623
rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2624
else
2625
rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2626
2627
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2628
/* Store the group id information. */
2629
_rtw_memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2630
_rtw_memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2631
}
2632
}
2633
2634
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, (u8 *)listen_ch_attr, (uint *) &attr_contentlen) && attr_contentlen == 5)
2635
pwdinfo->nego_req_info.peer_ch = listen_ch_attr[4];
2636
2637
RTW_INFO(FUNC_ADPT_FMT" listen channel :%u\n", FUNC_ADPT_ARG(padapter), pwdinfo->nego_req_info.peer_ch);
2638
2639
attr_contentlen = 0;
2640
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
2641
if (attr_contentlen != ETH_ALEN)
2642
_rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2643
}
2644
2645
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt)) {
2646
peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
2647
ch_num_inclusioned = rtw_p2p_ch_inclusion(padapter, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2648
2649
if (ch_num_inclusioned == 0) {
2650
RTW_INFO("[%s] No common channel in channel list!\n", __FUNCTION__);
2651
result = P2P_STATUS_FAIL_NO_COMMON_CH;
2652
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2653
break;
2654
}
2655
2656
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2657
if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2658
ch_list_inclusioned, ch_num_inclusioned)) {
2659
#ifdef CONFIG_CONCURRENT_MODE
2660
if (rtw_mi_check_status(padapter, MI_LINKED)
2661
&& padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
2662
RTW_INFO("[%s] desired channel NOT Found!\n", __FUNCTION__);
2663
result = P2P_STATUS_FAIL_NO_COMMON_CH;
2664
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2665
break;
2666
} else
2667
#endif /* CONFIG_CONCURRENT_MODE */
2668
{
2669
u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2670
attr_contentlen = 0;
2671
2672
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2673
peer_operating_ch = operatingch_info[4];
2674
2675
if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2676
ch_list_inclusioned, ch_num_inclusioned)) {
2677
/**
2678
* Change our operating channel as peer's for compatibility.
2679
*/
2680
pwdinfo->operating_channel = peer_operating_ch;
2681
RTW_INFO("[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);
2682
} else {
2683
/* Take first channel of ch_list_inclusioned as operating channel */
2684
pwdinfo->operating_channel = ch_list_inclusioned[0];
2685
RTW_INFO("[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);
2686
}
2687
}
2688
2689
}
2690
}
2691
}
2692
2693
/* Get the next P2P IE */
2694
p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2695
}
2696
2697
if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) {
2698
result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2699
rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
2700
return result;
2701
}
2702
2703
#ifdef CONFIG_WFD
2704
rtw_process_wfd_ies(padapter, pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, __func__);
2705
#endif
2706
2707
return result ;
2708
}
2709
2710
u8 process_p2p_group_negotation_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2711
{
2712
_adapter *padapter = pwdinfo->padapter;
2713
u8 result = P2P_STATUS_SUCCESS;
2714
u32 p2p_ielen, wps_ielen;
2715
u8 *ies;
2716
u32 ies_len;
2717
u8 *p2p_ie;
2718
#ifdef CONFIG_WFD
2719
#ifdef CONFIG_TDLS
2720
struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
2721
#endif /* CONFIG_TDLS */
2722
#endif /* CONFIG_WFD */
2723
2724
ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2725
ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2726
2727
/* Be able to know which one is the P2P GO and which one is P2P client. */
2728
2729
if (rtw_get_wps_ie(ies, ies_len, NULL, &wps_ielen)) {
2730
2731
} else {
2732
RTW_INFO("[%s] WPS IE not Found!!\n", __FUNCTION__);
2733
result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2734
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2735
}
2736
2737
p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
2738
if (!p2p_ie) {
2739
rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2740
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2741
result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2742
} else {
2743
2744
u8 attr_content = 0x00;
2745
u32 attr_contentlen = 0;
2746
u8 operatingch_info[5] = { 0x00 };
2747
u8 groupid[38];
2748
u16 cap_attr;
2749
u8 peer_ch_list[100] = { 0x00 };
2750
u8 peer_ch_num = 0;
2751
u8 ch_list_inclusioned[100] = { 0x00 };
2752
u8 ch_num_inclusioned = 0;
2753
2754
while (p2p_ie) { /* Found the P2P IE. */
2755
2756
/* Check P2P Capability ATTR */
2757
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *)&attr_contentlen)) {
2758
cap_attr = le16_to_cpu(cap_attr);
2759
#ifdef CONFIG_TDLS
2760
if (!(cap_attr & P2P_GRPCAP_INTRABSS))
2761
ptdlsinfo->ap_prohibited = _TRUE;
2762
#endif /* CONFIG_TDLS */
2763
}
2764
2765
rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
2766
if (attr_contentlen == 1) {
2767
RTW_INFO("[%s] Status = %d\n", __FUNCTION__, attr_content);
2768
if (attr_content == P2P_STATUS_SUCCESS) {
2769
/* Do nothing. */
2770
} else {
2771
if (P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content)
2772
rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
2773
else
2774
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2775
rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2776
result = attr_content;
2777
break;
2778
}
2779
}
2780
2781
/* Try to get the peer's interface address */
2782
attr_contentlen = 0;
2783
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
2784
if (attr_contentlen != ETH_ALEN)
2785
_rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2786
}
2787
2788
/* Try to get the peer's intent and tie breaker value. */
2789
attr_content = 0x00;
2790
attr_contentlen = 0;
2791
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen)) {
2792
RTW_INFO("[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01);
2793
pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2794
2795
if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
2796
/* Try to match the tie breaker value */
2797
if (pwdinfo->intent == P2P_MAX_INTENT) {
2798
rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2799
result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2800
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2801
} else {
2802
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2803
rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2804
if (attr_content & 0x01)
2805
rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2806
else
2807
rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2808
}
2809
} else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) {
2810
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2811
rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2812
rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2813
} else {
2814
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2815
rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2816
rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2817
}
2818
2819
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2820
/* Store the group id information. */
2821
_rtw_memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2822
_rtw_memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2823
2824
}
2825
}
2826
2827
/* Try to get the operation channel information */
2828
2829
attr_contentlen = 0;
2830
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
2831
RTW_INFO("[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4]);
2832
pwdinfo->peer_operating_ch = operatingch_info[4];
2833
}
2834
2835
/* Try to get the channel list information */
2836
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len)) {
2837
RTW_INFO("[%s] channel list attribute found, len = %d\n", __FUNCTION__, pwdinfo->channel_list_attr_len);
2838
2839
peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
2840
ch_num_inclusioned = rtw_p2p_ch_inclusion(padapter, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2841
2842
if (ch_num_inclusioned == 0) {
2843
RTW_INFO("[%s] No common channel in channel list!\n", __FUNCTION__);
2844
result = P2P_STATUS_FAIL_NO_COMMON_CH;
2845
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2846
break;
2847
}
2848
2849
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2850
if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2851
ch_list_inclusioned, ch_num_inclusioned)) {
2852
#ifdef CONFIG_CONCURRENT_MODE
2853
if (rtw_mi_check_status(padapter, MI_LINKED)
2854
&& padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
2855
RTW_INFO("[%s] desired channel NOT Found!\n", __FUNCTION__);
2856
result = P2P_STATUS_FAIL_NO_COMMON_CH;
2857
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2858
break;
2859
} else
2860
#endif /* CONFIG_CONCURRENT_MODE */
2861
{
2862
u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2863
attr_contentlen = 0;
2864
2865
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2866
peer_operating_ch = operatingch_info[4];
2867
2868
if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2869
ch_list_inclusioned, ch_num_inclusioned)) {
2870
/**
2871
* Change our operating channel as peer's for compatibility.
2872
*/
2873
pwdinfo->operating_channel = peer_operating_ch;
2874
RTW_INFO("[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);
2875
} else {
2876
/* Take first channel of ch_list_inclusioned as operating channel */
2877
pwdinfo->operating_channel = ch_list_inclusioned[0];
2878
RTW_INFO("[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);
2879
}
2880
}
2881
2882
}
2883
}
2884
2885
} else
2886
RTW_INFO("[%s] channel list attribute not found!\n", __FUNCTION__);
2887
2888
/* Try to get the group id information if peer is GO */
2889
attr_contentlen = 0;
2890
_rtw_memset(groupid, 0x00, 38);
2891
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
2892
_rtw_memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
2893
_rtw_memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
2894
}
2895
2896
/* Get the next P2P IE */
2897
p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2898
}
2899
2900
}
2901
2902
#ifdef CONFIG_WFD
2903
rtw_process_wfd_ies(padapter, pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, __func__);
2904
#endif
2905
2906
return result ;
2907
2908
}
2909
2910
u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2911
{
2912
#ifdef CONFIG_CONCURRENT_MODE
2913
_adapter *padapter = pwdinfo->padapter;
2914
#endif
2915
u8 *ies;
2916
u32 ies_len;
2917
u8 *p2p_ie;
2918
u32 p2p_ielen = 0;
2919
u8 result = P2P_STATUS_SUCCESS;
2920
ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2921
ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2922
2923
p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
2924
while (p2p_ie) { /* Found the P2P IE. */
2925
u8 attr_content = 0x00, operatingch_info[5] = { 0x00 };
2926
u8 groupid[38] = { 0x00 };
2927
u32 attr_contentlen = 0;
2928
2929
pwdinfo->negotiation_dialog_token = 1;
2930
rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
2931
if (attr_contentlen == 1) {
2932
RTW_INFO("[%s] Status = %d\n", __FUNCTION__, attr_content);
2933
result = attr_content;
2934
2935
if (attr_content == P2P_STATUS_SUCCESS) {
2936
2937
_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
2938
2939
/* Commented by Albert 20100911 */
2940
/* Todo: Need to handle the case which both Intents are the same. */
2941
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2942
rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2943
if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1))
2944
rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2945
else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1))
2946
rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2947
else {
2948
/* Have to compare the Tie Breaker */
2949
if (pwdinfo->peer_intent & 0x01)
2950
rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2951
else
2952
rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2953
}
2954
2955
#ifdef CONFIG_CONCURRENT_MODE
2956
if (rtw_mi_check_status(padapter, MI_LINKED)
2957
&& padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
2958
/* Switch back to the AP channel soon. */
2959
_set_timer(&pwdinfo->ap_p2p_switch_timer, 100);
2960
}
2961
#endif
2962
} else {
2963
rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2964
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2965
break;
2966
}
2967
}
2968
2969
/* Try to get the group id information */
2970
attr_contentlen = 0;
2971
_rtw_memset(groupid, 0x00, 38);
2972
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
2973
RTW_INFO("[%s] Ssid = %s, ssidlen = %zu\n", __FUNCTION__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]));
2974
_rtw_memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
2975
_rtw_memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
2976
}
2977
2978
attr_contentlen = 0;
2979
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
2980
RTW_INFO("[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4]);
2981
pwdinfo->peer_operating_ch = operatingch_info[4];
2982
}
2983
2984
/* Get the next P2P IE */
2985
p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
2986
2987
}
2988
2989
return result ;
2990
}
2991
2992
u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2993
{
2994
u8 *frame_body;
2995
u8 dialogToken = 0;
2996
u8 status = P2P_STATUS_SUCCESS;
2997
2998
frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2999
3000
dialogToken = frame_body[6];
3001
3002
/* todo: check NoA attribute */
3003
3004
issue_p2p_presence_resp(pwdinfo, get_addr2_ptr(pframe), status, dialogToken);
3005
3006
return _TRUE;
3007
}
3008
3009
void find_phase_handler(_adapter *padapter)
3010
{
3011
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3012
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3013
struct sitesurvey_parm parm;
3014
_irqL irqL;
3015
u8 _status = 0;
3016
3017
3018
rtw_init_sitesurvey_parm(padapter, &parm);
3019
_rtw_memcpy(&parm.ssid[0].Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
3020
parm.ssid[0].SsidLength = P2P_WILDCARD_SSID_LEN;
3021
parm.ssid_num = 1;
3022
3023
rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
3024
3025
_enter_critical_bh(&pmlmepriv->lock, &irqL);
3026
_status = rtw_sitesurvey_cmd(padapter, &parm);
3027
_exit_critical_bh(&pmlmepriv->lock, &irqL);
3028
3029
3030
}
3031
3032
void p2p_concurrent_handler(_adapter *padapter);
3033
3034
void restore_p2p_state_handler(_adapter *padapter)
3035
{
3036
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3037
3038
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
3039
rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3040
3041
#ifdef CONFIG_CONCURRENT_MODE
3042
if (rtw_mi_check_status(padapter, MI_LINKED)) {
3043
u8 union_ch = rtw_mi_get_union_chan(padapter);
3044
u8 union_bw = rtw_mi_get_union_bw(padapter);
3045
u8 union_offset = rtw_mi_get_union_offset(padapter);
3046
3047
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP)) {
3048
set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
3049
rtw_back_opch(padapter);
3050
}
3051
}
3052
#endif
3053
3054
rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3055
3056
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
3057
#ifdef CONFIG_CONCURRENT_MODE
3058
p2p_concurrent_handler(padapter);
3059
#else
3060
/* In the P2P client mode, the driver should not switch back to its listen channel */
3061
/* because this P2P client should stay at the operating channel of P2P GO. */
3062
set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3063
#endif
3064
}
3065
}
3066
3067
void pre_tx_invitereq_handler(_adapter *padapter)
3068
{
3069
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3070
u8 val8 = 1;
3071
3072
set_channel_bwmode(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3073
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3074
issue_probereq_p2p(padapter, NULL);
3075
_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3076
3077
}
3078
3079
void pre_tx_provdisc_handler(_adapter *padapter)
3080
{
3081
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3082
u8 val8 = 1;
3083
3084
set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3085
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3086
issue_probereq_p2p(padapter, NULL);
3087
_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3088
3089
}
3090
3091
void pre_tx_negoreq_handler(_adapter *padapter)
3092
{
3093
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3094
u8 val8 = 1;
3095
3096
set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3097
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3098
issue_probereq_p2p(padapter , NULL);
3099
/* WIN Phone only accept unicast probe request when nego back */
3100
issue_probereq_p2p(padapter , pwdinfo->nego_req_info.peerDevAddr);
3101
_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3102
3103
}
3104
3105
#ifdef CONFIG_CONCURRENT_MODE
3106
void p2p_concurrent_handler(_adapter *padapter)
3107
{
3108
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3109
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3110
u8 val8;
3111
3112
#ifdef CONFIG_IOCTL_CFG80211
3113
if (pwdinfo->driver_interface == DRIVER_CFG80211
3114
&& !rtw_cfg80211_get_is_roch(padapter))
3115
return;
3116
#endif
3117
3118
if (rtw_mi_check_status(padapter, MI_LINKED)) {
3119
u8 union_ch = rtw_mi_get_union_chan(padapter);
3120
u8 union_bw = rtw_mi_get_union_bw(padapter);
3121
u8 union_offset = rtw_mi_get_union_offset(padapter);
3122
3123
pwdinfo->operating_channel = union_ch;
3124
3125
if (pwdinfo->driver_interface == DRIVER_CFG80211) {
3126
RTW_INFO("%s, switch ch back to union=%u,%u, %u\n"
3127
, __func__, union_ch, union_bw, union_offset);
3128
set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
3129
rtw_back_opch(padapter);
3130
3131
} else if (pwdinfo->driver_interface == DRIVER_WEXT) {
3132
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
3133
/* Now, the driver stays on the AP's channel. */
3134
/* If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel. */
3135
if (pwdinfo->ext_listen_period > 0) {
3136
RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period);
3137
3138
if (union_ch != pwdinfo->listen_channel) {
3139
rtw_leave_opch(padapter);
3140
set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3141
}
3142
3143
rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3144
3145
if (!rtw_mi_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) {
3146
val8 = 1;
3147
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3148
}
3149
/* Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not. */
3150
_set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_period);
3151
}
3152
3153
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) ||
3154
rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) ||
3155
(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE) ||
3156
rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) {
3157
/* Now, the driver is in the listen state of P2P mode. */
3158
RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval);
3159
3160
/* Commented by Albert 2012/11/01 */
3161
/* If the AP's channel is the same as the listen channel, we should still be in the listen state */
3162
/* Other P2P device is still able to find this device out even this device is in the AP's channel. */
3163
/* So, configure this device to be able to receive the probe request frame and set it to listen state. */
3164
if (union_ch != pwdinfo->listen_channel) {
3165
3166
set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
3167
if (!rtw_mi_check_status(padapter, MI_AP_MODE)) {
3168
val8 = 0;
3169
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3170
}
3171
rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
3172
rtw_back_opch(padapter);
3173
}
3174
3175
/* Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not. */
3176
_set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval);
3177
3178
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) {
3179
/* The driver had finished the P2P handshake successfully. */
3180
val8 = 0;
3181
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3182
set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
3183
rtw_back_opch(padapter);
3184
3185
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
3186
val8 = 1;
3187
set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3188
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3189
issue_probereq_p2p(padapter, NULL);
3190
_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3191
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE) {
3192
val8 = 1;
3193
set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3194
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3195
issue_probereq_p2p(padapter, NULL);
3196
_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
3197
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ) && pwdinfo->invitereq_info.benable == _TRUE) {
3198
/*
3199
val8 = 1;
3200
set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3201
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3202
issue_probereq_p2p(padapter, NULL);
3203
_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
3204
*/
3205
}
3206
}
3207
} else {
3208
/* In p2p+softap. When in P2P_STATE_GONEGO_OK, not back to listen channel.*/
3209
if (!rtw_p2p_chk_state(pwdinfo , P2P_STATE_GONEGO_OK) || padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3210
set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3211
else
3212
RTW_INFO("%s, buddy not linked, go nego ok, not back to listen channel\n", __func__);
3213
}
3214
3215
}
3216
#endif
3217
3218
#ifdef CONFIG_IOCTL_CFG80211
3219
u8 roch_stay_in_cur_chan(_adapter *padapter)
3220
{
3221
int i;
3222
_adapter *iface;
3223
struct mlme_priv *pmlmepriv;
3224
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3225
u8 rst = _FALSE;
3226
3227
for (i = 0; i < dvobj->iface_nums; i++) {
3228
iface = dvobj->padapters[i];
3229
if (iface) {
3230
pmlmepriv = &iface->mlmepriv;
3231
3232
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING | WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE) == _TRUE) {
3233
RTW_INFO(ADPT_FMT"- _FW_UNDER_LINKING |WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE (mlme state:0x%x)\n",
3234
ADPT_ARG(iface), get_fwstate(&iface->mlmepriv));
3235
rst = _TRUE;
3236
break;
3237
}
3238
#ifdef CONFIG_AP_MODE
3239
if (MLME_IS_AP(iface) || MLME_IS_MESH(iface)) {
3240
if (rtw_ap_sta_states_check(iface) == _TRUE) {
3241
rst = _TRUE;
3242
break;
3243
}
3244
}
3245
#endif
3246
}
3247
}
3248
3249
return rst;
3250
}
3251
3252
static int ro_ch_handler(_adapter *adapter, u8 *buf)
3253
{
3254
int ret = H2C_SUCCESS;
3255
struct p2p_roch_parm *roch_parm = (struct p2p_roch_parm *)buf;
3256
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
3257
struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &adapter->cfg80211_wdinfo;
3258
#ifdef CONFIG_CONCURRENT_MODE
3259
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
3260
#ifdef RTW_ROCH_BACK_OP
3261
struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3262
#endif
3263
#endif
3264
u8 ready_on_channel = _FALSE;
3265
u8 remain_ch;
3266
unsigned int duration;
3267
3268
_enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);
3269
3270
if (rtw_cfg80211_get_is_roch(adapter) != _TRUE)
3271
goto exit;
3272
3273
remain_ch = (u8)ieee80211_frequency_to_channel(roch_parm->ch.center_freq);
3274
duration = roch_parm->duration;
3275
3276
RTW_INFO(FUNC_ADPT_FMT" ch:%u duration:%d, cookie:0x%llx\n"
3277
, FUNC_ADPT_ARG(adapter), remain_ch, roch_parm->duration, roch_parm->cookie);
3278
3279
if (roch_parm->wdev && roch_parm->cookie) {
3280
if (pcfg80211_wdinfo->ro_ch_wdev != roch_parm->wdev) {
3281
RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n"
3282
, FUNC_ADPT_ARG(adapter), pcfg80211_wdinfo->ro_ch_wdev, roch_parm->wdev);
3283
rtw_warn_on(1);
3284
}
3285
3286
if (pcfg80211_wdinfo->remain_on_ch_cookie != roch_parm->cookie) {
3287
RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n"
3288
, FUNC_ADPT_ARG(adapter), pcfg80211_wdinfo->remain_on_ch_cookie, roch_parm->cookie);
3289
rtw_warn_on(1);
3290
}
3291
}
3292
3293
if (roch_stay_in_cur_chan(adapter) == _TRUE) {
3294
remain_ch = rtw_mi_get_union_chan(adapter);
3295
RTW_INFO(FUNC_ADPT_FMT" stay in union ch:%d\n", FUNC_ADPT_ARG(adapter), remain_ch);
3296
}
3297
3298
#ifdef CONFIG_CONCURRENT_MODE
3299
if (rtw_mi_check_status(adapter, MI_LINKED) && (0 != rtw_mi_get_union_chan(adapter))) {
3300
if ((remain_ch != rtw_mi_get_union_chan(adapter)) && !check_fwstate(&adapter->mlmepriv, _FW_LINKED)) {
3301
if (remain_ch != pmlmeext->cur_channel
3302
#ifdef RTW_ROCH_BACK_OP
3303
|| ATOMIC_READ(&pwdev_priv->switch_ch_to) == 1
3304
#endif
3305
) {
3306
rtw_leave_opch(adapter);
3307
3308
#ifdef RTW_ROCH_BACK_OP
3309
RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, duration - pwdinfo->ext_listen_interval);
3310
ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);
3311
_set_timer(&pwdinfo->ap_p2p_switch_timer, duration - pwdinfo->ext_listen_interval);
3312
#endif
3313
}
3314
}
3315
ready_on_channel = _TRUE;
3316
} else
3317
#endif /* CONFIG_CONCURRENT_MODE */
3318
{
3319
if (remain_ch != rtw_get_oper_ch(adapter))
3320
ready_on_channel = _TRUE;
3321
}
3322
3323
if (ready_on_channel == _TRUE) {
3324
#ifndef RTW_SINGLE_WIPHY
3325
if (!check_fwstate(&adapter->mlmepriv, _FW_LINKED))
3326
#endif
3327
{
3328
#ifdef CONFIG_CONCURRENT_MODE
3329
if (rtw_get_oper_ch(adapter) != remain_ch)
3330
#endif
3331
{
3332
/* if (!padapter->mlmepriv.LinkDetectInfo.bBusyTraffic) */
3333
set_channel_bwmode(adapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3334
}
3335
}
3336
}
3337
3338
#ifdef CONFIG_BT_COEXIST
3339
rtw_btcoex_ScanNotify(adapter, _TRUE);
3340
#endif
3341
3342
RTW_INFO("%s, set ro ch timer, duration=%d\n", __func__, duration);
3343
_set_timer(&pcfg80211_wdinfo->remain_on_ch_timer, duration);
3344
3345
exit:
3346
_exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);
3347
3348
return ret;
3349
}
3350
3351
static int cancel_ro_ch_handler(_adapter *padapter, u8 *buf)
3352
{
3353
int ret = H2C_SUCCESS;
3354
struct p2p_roch_parm *roch_parm = (struct p2p_roch_parm *)buf;
3355
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
3356
struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
3357
struct wireless_dev *wdev;
3358
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3359
u8 ch, bw, offset;
3360
3361
_enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);
3362
3363
if (rtw_cfg80211_get_is_roch(padapter) != _TRUE)
3364
goto exit;
3365
3366
if (roch_parm->wdev && roch_parm->cookie) {
3367
if (pcfg80211_wdinfo->ro_ch_wdev != roch_parm->wdev) {
3368
RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n"
3369
, FUNC_ADPT_ARG(padapter), pcfg80211_wdinfo->ro_ch_wdev, roch_parm->wdev);
3370
rtw_warn_on(1);
3371
}
3372
3373
if (pcfg80211_wdinfo->remain_on_ch_cookie != roch_parm->cookie) {
3374
RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n"
3375
, FUNC_ADPT_ARG(padapter), pcfg80211_wdinfo->remain_on_ch_cookie, roch_parm->cookie);
3376
rtw_warn_on(1);
3377
}
3378
}
3379
3380
#if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE)
3381
_cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
3382
ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
3383
#endif
3384
3385
if (rtw_mi_get_ch_setting_union(padapter, &ch, &bw, &offset) != 0) {
3386
if (0)
3387
RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
3388
FUNC_ADPT_ARG(padapter), ch, bw, offset);
3389
} else if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->listen_channel) {
3390
ch = pwdinfo->listen_channel;
3391
bw = CHANNEL_WIDTH_20;
3392
offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3393
if (0)
3394
RTW_INFO(FUNC_ADPT_FMT" back to listen ch - ch:%u, bw:%u, offset:%u\n",
3395
FUNC_ADPT_ARG(padapter), ch, bw, offset);
3396
} else {
3397
ch = pcfg80211_wdinfo->restore_channel;
3398
bw = CHANNEL_WIDTH_20;
3399
offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
3400
if (0)
3401
RTW_INFO(FUNC_ADPT_FMT" back to restore ch - ch:%u, bw:%u, offset:%u\n",
3402
FUNC_ADPT_ARG(padapter), ch, bw, offset);
3403
}
3404
3405
set_channel_bwmode(padapter, ch, offset, bw);
3406
rtw_back_opch(padapter);
3407
3408
rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3409
#ifdef CONFIG_DEBUG_CFG80211
3410
RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
3411
#endif
3412
3413
wdev = pcfg80211_wdinfo->ro_ch_wdev;
3414
3415
rtw_cfg80211_set_is_roch(padapter, _FALSE);
3416
pcfg80211_wdinfo->ro_ch_wdev = NULL;
3417
rtw_cfg80211_set_last_ro_ch_time(padapter);
3418
3419
rtw_cfg80211_remain_on_channel_expired(wdev
3420
, pcfg80211_wdinfo->remain_on_ch_cookie
3421
, &pcfg80211_wdinfo->remain_on_ch_channel
3422
, pcfg80211_wdinfo->remain_on_ch_type, GFP_KERNEL);
3423
3424
RTW_INFO("cfg80211_remain_on_channel_expired cookie:0x%llx\n"
3425
, pcfg80211_wdinfo->remain_on_ch_cookie);
3426
3427
#ifdef CONFIG_BT_COEXIST
3428
rtw_btcoex_ScanNotify(padapter, _FALSE);
3429
#endif
3430
3431
exit:
3432
_exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);
3433
3434
return ret;
3435
}
3436
3437
static void ro_ch_timer_process(void *FunctionContext)
3438
{
3439
_adapter *adapter = (_adapter *)FunctionContext;
3440
3441
p2p_cancel_roch_cmd(adapter, 0, NULL, 0);
3442
}
3443
3444
#if 0
3445
static void rtw_change_p2pie_op_ch(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
3446
{
3447
u8 *ies, *p2p_ie;
3448
u32 ies_len, p2p_ielen;
3449
3450
#ifdef CONFIG_MCC_MODE
3451
if (MCC_EN(padapter))
3452
return;
3453
#endif /* CONFIG_MCC_MODE */
3454
3455
ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3456
ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3457
3458
p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3459
3460
while (p2p_ie) {
3461
u32 attr_contentlen = 0;
3462
u8 *pattr = NULL;
3463
3464
/* Check P2P_ATTR_OPERATING_CH */
3465
attr_contentlen = 0;
3466
pattr = NULL;
3467
pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
3468
if (pattr != NULL)
3469
*(pattr + 4) = ch;
3470
3471
/* Get the next P2P IE */
3472
p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3473
}
3474
}
3475
#endif
3476
3477
#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3478
static void rtw_change_p2pie_ch_list(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
3479
{
3480
u8 *ies, *p2p_ie;
3481
u32 ies_len, p2p_ielen;
3482
3483
#ifdef CONFIG_MCC_MODE
3484
if (MCC_EN(padapter))
3485
return;
3486
#endif /* CONFIG_MCC_MODE */
3487
3488
ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3489
ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3490
3491
p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3492
3493
while (p2p_ie) {
3494
u32 attr_contentlen = 0;
3495
u8 *pattr = NULL;
3496
3497
/* Check P2P_ATTR_CH_LIST */
3498
pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
3499
if (pattr != NULL) {
3500
int i;
3501
u32 num_of_ch;
3502
u8 *pattr_temp = pattr + 3 ;
3503
3504
attr_contentlen -= 3;
3505
3506
while (attr_contentlen > 0) {
3507
num_of_ch = *(pattr_temp + 1);
3508
3509
for (i = 0; i < num_of_ch; i++)
3510
*(pattr_temp + 2 + i) = ch;
3511
3512
pattr_temp += (2 + num_of_ch);
3513
attr_contentlen -= (2 + num_of_ch);
3514
}
3515
}
3516
3517
/* Get the next P2P IE */
3518
p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3519
}
3520
}
3521
#endif
3522
3523
#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3524
static bool rtw_chk_p2pie_ch_list_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
3525
{
3526
bool fit = _FALSE;
3527
u8 *ies, *p2p_ie;
3528
u32 ies_len, p2p_ielen;
3529
u8 union_ch = rtw_mi_get_union_chan(padapter);
3530
3531
ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3532
ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3533
3534
p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3535
3536
while (p2p_ie) {
3537
u32 attr_contentlen = 0;
3538
u8 *pattr = NULL;
3539
3540
/* Check P2P_ATTR_CH_LIST */
3541
pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
3542
if (pattr != NULL) {
3543
int i;
3544
u32 num_of_ch;
3545
u8 *pattr_temp = pattr + 3 ;
3546
3547
attr_contentlen -= 3;
3548
3549
while (attr_contentlen > 0) {
3550
num_of_ch = *(pattr_temp + 1);
3551
3552
for (i = 0; i < num_of_ch; i++) {
3553
if (*(pattr_temp + 2 + i) == union_ch) {
3554
RTW_INFO(FUNC_ADPT_FMT" ch_list fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), union_ch);
3555
fit = _TRUE;
3556
break;
3557
}
3558
}
3559
3560
pattr_temp += (2 + num_of_ch);
3561
attr_contentlen -= (2 + num_of_ch);
3562
}
3563
}
3564
3565
/* Get the next P2P IE */
3566
p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3567
}
3568
3569
return fit;
3570
}
3571
3572
#if defined(CONFIG_P2P_INVITE_IOT)
3573
static bool rtw_chk_p2pie_op_ch_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
3574
{
3575
bool fit = _FALSE;
3576
u8 *ies, *p2p_ie;
3577
u32 ies_len, p2p_ielen;
3578
u8 union_ch = rtw_mi_get_union_chan(padapter);
3579
3580
ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3581
ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3582
3583
p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3584
3585
while (p2p_ie) {
3586
u32 attr_contentlen = 0;
3587
u8 *pattr = NULL;
3588
3589
/* Check P2P_ATTR_OPERATING_CH */
3590
attr_contentlen = 0;
3591
pattr = NULL;
3592
pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
3593
if (pattr != NULL) {
3594
if (*(pattr + 4) == union_ch) {
3595
RTW_INFO(FUNC_ADPT_FMT" op_ch fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), union_ch);
3596
fit = _TRUE;
3597
break;
3598
}
3599
}
3600
3601
/* Get the next P2P IE */
3602
p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3603
}
3604
3605
return fit;
3606
}
3607
#endif
3608
3609
static void rtw_cfg80211_adjust_p2pie_channel(_adapter *padapter, const u8 *frame_body, u32 len)
3610
{
3611
u8 *ies, *p2p_ie;
3612
u32 ies_len, p2p_ielen;
3613
u8 union_ch = rtw_mi_get_union_chan(padapter);
3614
3615
#ifdef CONFIG_MCC_MODE
3616
if (MCC_EN(padapter))
3617
return;
3618
#endif /* CONFIG_MCC_MODE */
3619
3620
ies = (u8 *)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
3621
ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
3622
3623
p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
3624
3625
while (p2p_ie) {
3626
u32 attr_contentlen = 0;
3627
u8 *pattr = NULL;
3628
3629
/* Check P2P_ATTR_CH_LIST */
3630
pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint *)&attr_contentlen);
3631
if (pattr != NULL) {
3632
int i;
3633
u32 num_of_ch;
3634
u8 *pattr_temp = pattr + 3 ;
3635
3636
attr_contentlen -= 3;
3637
3638
while (attr_contentlen > 0) {
3639
num_of_ch = *(pattr_temp + 1);
3640
3641
for (i = 0; i < num_of_ch; i++) {
3642
if (*(pattr_temp + 2 + i) && *(pattr_temp + 2 + i) != union_ch) {
3643
#ifdef RTW_SINGLE_WIPHY
3644
RTW_ERR("replace ch_list:%u with:%u\n", *(pattr_temp + 2 + i), union_ch);
3645
#endif
3646
*(pattr_temp + 2 + i) = union_ch; /*forcing to the same channel*/
3647
}
3648
}
3649
3650
pattr_temp += (2 + num_of_ch);
3651
attr_contentlen -= (2 + num_of_ch);
3652
}
3653
}
3654
3655
/* Check P2P_ATTR_OPERATING_CH */
3656
attr_contentlen = 0;
3657
pattr = NULL;
3658
pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint *)&attr_contentlen);
3659
if (pattr != NULL) {
3660
if (*(pattr + 4) && *(pattr + 4) != union_ch) {
3661
#ifdef RTW_SINGLE_WIPHY
3662
RTW_ERR("replace op_ch:%u with:%u\n", *(pattr + 4), union_ch);
3663
#endif
3664
*(pattr + 4) = union_ch; /*forcing to the same channel */
3665
}
3666
}
3667
3668
/* Get the next P2P IE */
3669
p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
3670
3671
}
3672
3673
}
3674
#endif
3675
3676
#ifdef CONFIG_WFD
3677
u32 rtw_xframe_build_wfd_ie(struct xmit_frame *xframe)
3678
{
3679
_adapter *adapter = xframe->padapter;
3680
struct wifidirect_info *wdinfo = &adapter->wdinfo;
3681
u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
3682
u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
3683
u8 *frame_tail = frame + xframe->attrib.pktlen;
3684
u8 category, action, OUI_Subtype, dialogToken = 0;
3685
u32 wfdielen = 0;
3686
3687
category = frame_body[0];
3688
if (category == RTW_WLAN_CATEGORY_PUBLIC) {
3689
action = frame_body[1];
3690
if (action == ACT_PUBLIC_VENDOR
3691
&& _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
3692
) {
3693
OUI_Subtype = frame_body[6];
3694
dialogToken = frame_body[7];
3695
3696
switch (OUI_Subtype) {
3697
case P2P_GO_NEGO_REQ:
3698
wfdielen = build_nego_req_wfd_ie(wdinfo, frame_tail);
3699
break;
3700
case P2P_GO_NEGO_RESP:
3701
wfdielen = build_nego_resp_wfd_ie(wdinfo, frame_tail);
3702
break;
3703
case P2P_GO_NEGO_CONF:
3704
wfdielen = build_nego_confirm_wfd_ie(wdinfo, frame_tail);
3705
break;
3706
case P2P_INVIT_REQ:
3707
wfdielen = build_invitation_req_wfd_ie(wdinfo, frame_tail);
3708
break;
3709
case P2P_INVIT_RESP:
3710
wfdielen = build_invitation_resp_wfd_ie(wdinfo, frame_tail);
3711
break;
3712
case P2P_PROVISION_DISC_REQ:
3713
wfdielen = build_provdisc_req_wfd_ie(wdinfo, frame_tail);
3714
break;
3715
case P2P_PROVISION_DISC_RESP:
3716
wfdielen = build_provdisc_resp_wfd_ie(wdinfo, frame_tail);
3717
break;
3718
case P2P_DEVDISC_REQ:
3719
case P2P_DEVDISC_RESP:
3720
default:
3721
break;
3722
}
3723
3724
}
3725
} else if (category == RTW_WLAN_CATEGORY_P2P) {
3726
OUI_Subtype = frame_body[5];
3727
dialogToken = frame_body[6];
3728
3729
#ifdef CONFIG_DEBUG_CFG80211
3730
RTW_INFO("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n"
3731
, cpu_to_be32(*((u32 *)(frame_body + 1))), OUI_Subtype, dialogToken);
3732
#endif
3733
3734
switch (OUI_Subtype) {
3735
case P2P_NOTICE_OF_ABSENCE:
3736
break;
3737
case P2P_PRESENCE_REQUEST:
3738
break;
3739
case P2P_PRESENCE_RESPONSE:
3740
break;
3741
case P2P_GO_DISC_REQUEST:
3742
break;
3743
default:
3744
break;
3745
}
3746
} else
3747
RTW_INFO("%s, action frame category=%d\n", __func__, category);
3748
3749
xframe->attrib.pktlen += wfdielen;
3750
3751
return wfdielen;
3752
}
3753
#endif /* CONFIG_WFD */
3754
3755
bool rtw_xframe_del_wfd_ie(struct xmit_frame *xframe)
3756
{
3757
#define DBG_XFRAME_DEL_WFD_IE 0
3758
u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
3759
u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
3760
u8 *frame_tail = frame + xframe->attrib.pktlen;
3761
u8 category, action, OUI_Subtype;
3762
u8 *ies = NULL;
3763
uint ies_len_ori = 0;
3764
uint ies_len = 0;
3765
3766
category = frame_body[0];
3767
if (category == RTW_WLAN_CATEGORY_PUBLIC) {
3768
action = frame_body[1];
3769
if (action == ACT_PUBLIC_VENDOR
3770
&& _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
3771
) {
3772
OUI_Subtype = frame_body[6];
3773
3774
switch (OUI_Subtype) {
3775
case P2P_GO_NEGO_REQ:
3776
case P2P_GO_NEGO_RESP:
3777
case P2P_GO_NEGO_CONF:
3778
case P2P_INVIT_REQ:
3779
case P2P_INVIT_RESP:
3780
case P2P_PROVISION_DISC_REQ:
3781
case P2P_PROVISION_DISC_RESP:
3782
ies = frame_body + 8;
3783
ies_len_ori = frame_tail - (frame_body + 8);
3784
break;
3785
}
3786
}
3787
}
3788
3789
if (ies && ies_len_ori) {
3790
ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_XFRAME_DEL_WFD_IE ? __func__ : NULL);
3791
xframe->attrib.pktlen -= (ies_len_ori - ies_len);
3792
}
3793
3794
return ies_len_ori != ies_len;
3795
}
3796
3797
/*
3798
* rtw_xframe_chk_wfd_ie -
3799
*
3800
*/
3801
void rtw_xframe_chk_wfd_ie(struct xmit_frame *xframe)
3802
{
3803
_adapter *adapter = xframe->padapter;
3804
#ifdef CONFIG_IOCTL_CFG80211
3805
struct wifidirect_info *wdinfo = &adapter->wdinfo;
3806
#endif
3807
u8 build = 0;
3808
u8 del = 0;
3809
3810
if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
3811
del = 1;
3812
3813
#ifdef CONFIG_IOCTL_CFG80211
3814
if (wdinfo->wfd_info->wfd_enable == _TRUE)
3815
#endif
3816
del = build = 1;
3817
3818
if (del)
3819
rtw_xframe_del_wfd_ie(xframe);
3820
3821
#ifdef CONFIG_WFD
3822
if (build)
3823
rtw_xframe_build_wfd_ie(xframe);
3824
#endif
3825
}
3826
3827
u8 *dump_p2p_attr_ch_list(u8 *p2p_ie, uint p2p_ielen, u8 *buf, u32 buf_len)
3828
{
3829
uint attr_contentlen = 0;
3830
u8 *pattr = NULL;
3831
int w_sz = 0;
3832
u8 ch_cnt = 0;
3833
u8 ch_list[40];
3834
3835
pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, &attr_contentlen);
3836
if (pattr != NULL) {
3837
int i, j;
3838
u32 num_of_ch;
3839
u8 *pattr_temp = pattr + 3 ;
3840
3841
attr_contentlen -= 3;
3842
3843
_rtw_memset(ch_list, 0, 40);
3844
3845
while (attr_contentlen > 0) {
3846
num_of_ch = *(pattr_temp + 1);
3847
3848
for (i = 0; i < num_of_ch; i++) {
3849
for (j = 0; j < ch_cnt; j++) {
3850
if (ch_list[j] == *(pattr_temp + 2 + i))
3851
break;
3852
}
3853
if (j >= ch_cnt)
3854
ch_list[ch_cnt++] = *(pattr_temp + 2 + i);
3855
3856
}
3857
3858
pattr_temp += (2 + num_of_ch);
3859
attr_contentlen -= (2 + num_of_ch);
3860
}
3861
3862
for (j = 0; j < ch_cnt; j++) {
3863
if (j == 0)
3864
w_sz += snprintf(buf + w_sz, buf_len - w_sz, "%u", ch_list[j]);
3865
else if (ch_list[j] - ch_list[j - 1] != 1)
3866
w_sz += snprintf(buf + w_sz, buf_len - w_sz, ", %u", ch_list[j]);
3867
else if (j != ch_cnt - 1 && ch_list[j + 1] - ch_list[j] == 1) {
3868
/* empty */
3869
} else
3870
w_sz += snprintf(buf + w_sz, buf_len - w_sz, "-%u", ch_list[j]);
3871
}
3872
}
3873
return buf;
3874
}
3875
3876
/*
3877
* return _TRUE if requester is GO, _FALSE if responder is GO
3878
*/
3879
bool rtw_p2p_nego_intent_compare(u8 req, u8 resp)
3880
{
3881
if (req >> 1 == resp >> 1)
3882
return req & 0x01 ? _TRUE : _FALSE;
3883
else if (req >> 1 > resp >> 1)
3884
return _TRUE;
3885
else
3886
return _FALSE;
3887
}
3888
3889
int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx)
3890
{
3891
int is_p2p_frame = (-1);
3892
unsigned char *frame_body;
3893
u8 category, action, OUI_Subtype, dialogToken = 0;
3894
u8 *p2p_ie = NULL;
3895
uint p2p_ielen = 0;
3896
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
3897
int status = -1;
3898
u8 ch_list_buf[128] = {'\0'};
3899
int op_ch = -1;
3900
int listen_ch = -1;
3901
u8 intent = 0;
3902
u8 *iaddr = NULL;
3903
u8 *gbssid = NULL;
3904
3905
frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));
3906
category = frame_body[0];
3907
/* just for check */
3908
if (category == RTW_WLAN_CATEGORY_PUBLIC) {
3909
action = frame_body[1];
3910
if (action == ACT_PUBLIC_VENDOR
3911
&& _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
3912
) {
3913
OUI_Subtype = frame_body[6];
3914
dialogToken = frame_body[7];
3915
is_p2p_frame = OUI_Subtype;
3916
3917
#ifdef CONFIG_DEBUG_CFG80211
3918
RTW_INFO("ACTION_CATEGORY_PUBLIC: ACT_PUBLIC_VENDOR, OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
3919
cpu_to_be32(*((u32 *)(frame_body + 2))), OUI_Subtype, dialogToken);
3920
#endif
3921
3922
p2p_ie = rtw_get_p2p_ie(
3923
(u8 *)buf + sizeof(struct rtw_ieee80211_hdr_3addr) + _PUBLIC_ACTION_IE_OFFSET_
3924
, len - sizeof(struct rtw_ieee80211_hdr_3addr) - _PUBLIC_ACTION_IE_OFFSET_
3925
, NULL, &p2p_ielen);
3926
3927
switch (OUI_Subtype) { /* OUI Subtype */
3928
u8 *cont;
3929
uint cont_len;
3930
case P2P_GO_NEGO_REQ: {
3931
struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
3932
3933
if (tx) {
3934
#ifdef CONFIG_DRV_ISSUE_PROV_REQ /* IOT FOR S2 */
3935
if (pwdev_priv->provdisc_req_issued == _FALSE)
3936
rtw_cfg80211_issue_p2p_provision_request(padapter, buf, len);
3937
#endif /* CONFIG_DRV_ISSUE_PROV_REQ */
3938
3939
/* pwdev_priv->provdisc_req_issued = _FALSE; */
3940
3941
#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3942
if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3943
rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
3944
#endif
3945
}
3946
3947
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
3948
if (cont)
3949
op_ch = *(cont + 4);
3950
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, NULL, &cont_len);
3951
if (cont)
3952
listen_ch = *(cont + 4);
3953
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len);
3954
if (cont)
3955
intent = *cont;
3956
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, NULL, &cont_len);
3957
if (cont && cont_len == 6)
3958
iaddr = cont;
3959
3960
if (nego_info->token != dialogToken)
3961
rtw_wdev_nego_info_init(nego_info);
3962
3963
_rtw_memcpy(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN);
3964
if (iaddr)
3965
_rtw_memcpy(tx ? nego_info->iface_addr : nego_info->peer_iface_addr, iaddr, ETH_ALEN);
3966
nego_info->active = tx ? 1 : 0;
3967
nego_info->token = dialogToken;
3968
nego_info->req_op_ch = op_ch;
3969
nego_info->req_listen_ch = listen_ch;
3970
nego_info->req_intent = intent;
3971
nego_info->state = 0;
3972
3973
dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
3974
RTW_INFO("RTW_%s:P2P_GO_NEGO_REQ, dialogToken=%d, intent:%u%s, listen_ch:%d, op_ch:%d, ch_list:%s"
3975
, (tx == _TRUE) ? "Tx" : "Rx" , dialogToken , (intent >> 1) , intent & 0x1 ? "+" : "-" , listen_ch , op_ch , ch_list_buf);
3976
if (iaddr)
3977
_RTW_INFO(", iaddr:"MAC_FMT, MAC_ARG(iaddr));
3978
_RTW_INFO("\n");
3979
3980
if (!tx) {
3981
#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3982
if (rtw_mi_check_status(padapter, MI_LINKED)
3983
&& rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE
3984
&& padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
3985
RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
3986
rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
3987
}
3988
#endif
3989
}
3990
3991
break;
3992
}
3993
case P2P_GO_NEGO_RESP: {
3994
struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
3995
3996
if (tx) {
3997
#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
3998
if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
3999
rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
4000
#endif
4001
}
4002
4003
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
4004
if (cont)
4005
op_ch = *(cont + 4);
4006
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len);
4007
if (cont)
4008
intent = *cont;
4009
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
4010
if (cont)
4011
status = *cont;
4012
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENDED_IF_ADDR, NULL, &cont_len);
4013
if (cont && cont_len == 6)
4014
iaddr = cont;
4015
4016
if (nego_info->token == dialogToken && nego_info->state == 0
4017
&& _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE
4018
) {
4019
if (iaddr)
4020
_rtw_memcpy(tx ? nego_info->iface_addr : nego_info->peer_iface_addr, iaddr, ETH_ALEN);
4021
nego_info->status = (status == -1) ? 0xff : status;
4022
nego_info->rsp_op_ch = op_ch;
4023
nego_info->rsp_intent = intent;
4024
nego_info->state = 1;
4025
if (status != 0)
4026
nego_info->token = 0; /* init */
4027
}
4028
4029
dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4030
RTW_INFO("RTW_%s:P2P_GO_NEGO_RESP, dialogToken=%d, intent:%u%s, status:%d, op_ch:%d, ch_list:%s"
4031
, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, (intent >> 1), intent & 0x1 ? "+" : "-", status, op_ch, ch_list_buf);
4032
if (iaddr)
4033
_RTW_INFO(", iaddr:"MAC_FMT, MAC_ARG(iaddr));
4034
_RTW_INFO("\n");
4035
4036
if (!tx) {
4037
pwdev_priv->provdisc_req_issued = _FALSE;
4038
#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4039
if (rtw_mi_check_status(padapter, MI_LINKED)
4040
&& rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE
4041
&& padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
4042
RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
4043
rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
4044
}
4045
#endif
4046
}
4047
4048
break;
4049
}
4050
case P2P_GO_NEGO_CONF: {
4051
struct rtw_wdev_nego_info *nego_info = &pwdev_priv->nego_info;
4052
bool is_go = _FALSE;
4053
4054
if (tx) {
4055
#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4056
if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
4057
rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
4058
#endif
4059
}
4060
4061
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
4062
if (cont)
4063
op_ch = *(cont + 4);
4064
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
4065
if (cont)
4066
status = *cont;
4067
4068
if (nego_info->token == dialogToken && nego_info->state == 1
4069
&& _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE
4070
) {
4071
nego_info->status = (status == -1) ? 0xff : status;
4072
nego_info->conf_op_ch = (op_ch == -1) ? 0 : op_ch;
4073
nego_info->state = 2;
4074
4075
if (status == 0) {
4076
if (rtw_p2p_nego_intent_compare(nego_info->req_intent, nego_info->rsp_intent) ^ !tx)
4077
is_go = _TRUE;
4078
}
4079
4080
nego_info->token = 0; /* init */
4081
}
4082
4083
dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4084
RTW_INFO("RTW_%s:P2P_GO_NEGO_CONF, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s\n"
4085
, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, status, op_ch, ch_list_buf);
4086
4087
if (!tx) {
4088
}
4089
4090
break;
4091
}
4092
case P2P_INVIT_REQ: {
4093
struct rtw_wdev_invit_info *invit_info = &pwdev_priv->invit_info;
4094
int flags = -1;
4095
4096
if (tx) {
4097
#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4098
if (rtw_mi_check_status(padapter, MI_LINKED)
4099
&& padapter->registrypriv.full_ch_in_p2p_handshake == 0)
4100
rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
4101
#endif
4102
}
4103
4104
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, NULL, &cont_len);
4105
if (cont)
4106
flags = *cont;
4107
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
4108
if (cont)
4109
op_ch = *(cont + 4);
4110
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, NULL, &cont_len);
4111
if (cont && cont_len == 6)
4112
gbssid = cont;
4113
4114
if (invit_info->token != dialogToken)
4115
rtw_wdev_invit_info_init(invit_info);
4116
4117
_rtw_memcpy(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN);
4118
if (gbssid)
4119
_rtw_memcpy(invit_info->group_bssid, gbssid, ETH_ALEN);
4120
invit_info->active = tx ? 1 : 0;
4121
invit_info->token = dialogToken;
4122
invit_info->flags = (flags == -1) ? 0x0 : flags;
4123
invit_info->req_op_ch = op_ch;
4124
invit_info->state = 0;
4125
4126
dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4127
RTW_INFO("RTW_%s:P2P_INVIT_REQ, dialogToken=%d, flags:0x%02x, op_ch:%d, ch_list:%s"
4128
, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, flags, op_ch, ch_list_buf);
4129
if (gbssid)
4130
_RTW_INFO(", gbssid:"MAC_FMT, MAC_ARG(gbssid));
4131
_RTW_INFO("\n");
4132
4133
if (!tx) {
4134
#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4135
if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
4136
#if defined(CONFIG_P2P_INVITE_IOT)
4137
if (op_ch != -1 && rtw_chk_p2pie_op_ch_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
4138
RTW_INFO(FUNC_ADPT_FMT" op_ch:%u has no intersect with buddy\n", FUNC_ADPT_ARG(padapter), op_ch);
4139
rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
4140
} else
4141
#endif
4142
if (rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
4143
RTW_INFO(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
4144
rtw_change_p2pie_ch_list(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr), 0);
4145
}
4146
}
4147
#endif
4148
}
4149
4150
break;
4151
}
4152
case P2P_INVIT_RESP: {
4153
struct rtw_wdev_invit_info *invit_info = &pwdev_priv->invit_info;
4154
4155
if (tx) {
4156
#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
4157
if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
4158
rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len - sizeof(struct rtw_ieee80211_hdr_3addr));
4159
#endif
4160
}
4161
4162
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
4163
if (cont) {
4164
#ifdef CONFIG_P2P_INVITE_IOT
4165
if (tx && *cont == 7) {
4166
RTW_INFO("TX_P2P_INVITE_RESP, status is no common channel, change to unknown group\n");
4167
*cont = 8; /* unknow group status */
4168
}
4169
#endif /* CONFIG_P2P_INVITE_IOT */
4170
status = *cont;
4171
}
4172
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len);
4173
if (cont)
4174
op_ch = *(cont + 4);
4175
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, NULL, &cont_len);
4176
if (cont && cont_len == 6)
4177
gbssid = cont;
4178
4179
if (invit_info->token == dialogToken && invit_info->state == 0
4180
&& _rtw_memcmp(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : get_addr2_ptr(buf), ETH_ALEN) == _TRUE
4181
) {
4182
invit_info->status = (status == -1) ? 0xff : status;
4183
invit_info->rsp_op_ch = op_ch;
4184
invit_info->state = 1;
4185
invit_info->token = 0; /* init */
4186
}
4187
4188
dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
4189
RTW_INFO("RTW_%s:P2P_INVIT_RESP, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s"
4190
, (tx == _TRUE) ? "Tx" : "Rx", dialogToken, status, op_ch, ch_list_buf);
4191
if (gbssid)
4192
_RTW_INFO(", gbssid:"MAC_FMT, MAC_ARG(gbssid));
4193
_RTW_INFO("\n");
4194
4195
if (!tx) {
4196
}
4197
4198
break;
4199
}
4200
case P2P_DEVDISC_REQ:
4201
RTW_INFO("RTW_%s:P2P_DEVDISC_REQ, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
4202
break;
4203
case P2P_DEVDISC_RESP:
4204
cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
4205
RTW_INFO("RTW_%s:P2P_DEVDISC_RESP, dialogToken=%d, status:%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken, cont ? *cont : -1);
4206
break;
4207
case P2P_PROVISION_DISC_REQ: {
4208
size_t frame_body_len = len - sizeof(struct rtw_ieee80211_hdr_3addr);
4209
u8 *p2p_ie;
4210
uint p2p_ielen = 0;
4211
uint contentlen = 0;
4212
4213
RTW_INFO("RTW_%s:P2P_PROVISION_DISC_REQ, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
4214
4215
/* if(tx) */
4216
{
4217
pwdev_priv->provdisc_req_issued = _FALSE;
4218
4219
p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
4220
if (p2p_ie) {
4221
4222
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, NULL, &contentlen)) {
4223
pwdev_priv->provdisc_req_issued = _FALSE;/* case: p2p_client join p2p GO */
4224
} else {
4225
#ifdef CONFIG_DEBUG_CFG80211
4226
RTW_INFO("provdisc_req_issued is _TRUE\n");
4227
#endif /*CONFIG_DEBUG_CFG80211*/
4228
pwdev_priv->provdisc_req_issued = _TRUE;/* case: p2p_devices connection before Nego req. */
4229
}
4230
4231
}
4232
}
4233
}
4234
break;
4235
case P2P_PROVISION_DISC_RESP:
4236
RTW_INFO("RTW_%s:P2P_PROVISION_DISC_RESP, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
4237
break;
4238
default:
4239
RTW_INFO("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", OUI_Subtype, dialogToken);
4240
break;
4241
}
4242
4243
}
4244
4245
} else if (category == RTW_WLAN_CATEGORY_P2P) {
4246
OUI_Subtype = frame_body[5];
4247
dialogToken = frame_body[6];
4248
4249
#ifdef CONFIG_DEBUG_CFG80211
4250
RTW_INFO("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
4251
cpu_to_be32(*((u32 *)(frame_body + 1))), OUI_Subtype, dialogToken);
4252
#endif
4253
4254
is_p2p_frame = OUI_Subtype;
4255
4256
switch (OUI_Subtype) {
4257
case P2P_NOTICE_OF_ABSENCE:
4258
RTW_INFO("RTW_%s:P2P_NOTICE_OF_ABSENCE, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
4259
break;
4260
case P2P_PRESENCE_REQUEST:
4261
RTW_INFO("RTW_%s:P2P_PRESENCE_REQUEST, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
4262
break;
4263
case P2P_PRESENCE_RESPONSE:
4264
RTW_INFO("RTW_%s:P2P_PRESENCE_RESPONSE, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
4265
break;
4266
case P2P_GO_DISC_REQUEST:
4267
RTW_INFO("RTW_%s:P2P_GO_DISC_REQUEST, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", dialogToken);
4268
break;
4269
default:
4270
RTW_INFO("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx == _TRUE) ? "Tx" : "Rx", OUI_Subtype, dialogToken);
4271
break;
4272
}
4273
4274
}
4275
4276
return is_p2p_frame;
4277
}
4278
4279
void rtw_init_cfg80211_wifidirect_info(_adapter *padapter)
4280
{
4281
struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
4282
4283
_rtw_memset(pcfg80211_wdinfo, 0x00, sizeof(struct cfg80211_wifidirect_info));
4284
4285
rtw_init_timer(&pcfg80211_wdinfo->remain_on_ch_timer, padapter, ro_ch_timer_process, padapter);
4286
}
4287
#endif /* CONFIG_IOCTL_CFG80211 */
4288
4289
s32 p2p_protocol_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf)
4290
{
4291
int ret = H2C_SUCCESS;
4292
4293
switch (intCmdType) {
4294
case P2P_FIND_PHASE_WK:
4295
find_phase_handler(padapter);
4296
break;
4297
4298
case P2P_RESTORE_STATE_WK:
4299
restore_p2p_state_handler(padapter);
4300
break;
4301
4302
case P2P_PRE_TX_PROVDISC_PROCESS_WK:
4303
#ifdef CONFIG_CONCURRENT_MODE
4304
if (rtw_mi_check_status(padapter, MI_LINKED))
4305
p2p_concurrent_handler(padapter);
4306
else
4307
pre_tx_provdisc_handler(padapter);
4308
#else
4309
pre_tx_provdisc_handler(padapter);
4310
#endif
4311
break;
4312
4313
case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
4314
#ifdef CONFIG_CONCURRENT_MODE
4315
if (rtw_mi_check_status(padapter, MI_LINKED))
4316
p2p_concurrent_handler(padapter);
4317
else
4318
pre_tx_invitereq_handler(padapter);
4319
#else
4320
pre_tx_invitereq_handler(padapter);
4321
#endif
4322
break;
4323
4324
case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
4325
#ifdef CONFIG_CONCURRENT_MODE
4326
if (rtw_mi_check_status(padapter, MI_LINKED))
4327
p2p_concurrent_handler(padapter);
4328
else
4329
pre_tx_negoreq_handler(padapter);
4330
#else
4331
pre_tx_negoreq_handler(padapter);
4332
#endif
4333
break;
4334
4335
#ifdef CONFIG_CONCURRENT_MODE
4336
case P2P_AP_P2P_CH_SWITCH_PROCESS_WK:
4337
p2p_concurrent_handler(padapter);
4338
break;
4339
#endif
4340
4341
#ifdef CONFIG_IOCTL_CFG80211
4342
case P2P_RO_CH_WK:
4343
ret = ro_ch_handler(padapter, buf);
4344
break;
4345
case P2P_CANCEL_RO_CH_WK:
4346
ret = cancel_ro_ch_handler(padapter, buf);
4347
break;
4348
#endif
4349
4350
default:
4351
rtw_warn_on(1);
4352
break;
4353
}
4354
4355
return ret;
4356
}
4357
4358
int process_p2p_cross_connect_ie(PADAPTER padapter, u8 *IEs, u32 IELength)
4359
{
4360
int ret = _TRUE;
4361
u8 *ies;
4362
u32 ies_len;
4363
u8 *p2p_ie;
4364
u32 p2p_ielen = 0;
4365
u8 p2p_attr[MAX_P2P_IE_LEN] = { 0x00 };/* NoA length should be n*(13) + 2 */
4366
u32 attr_contentlen = 0;
4367
4368
4369
4370
if (IELength <= _BEACON_IE_OFFSET_)
4371
return ret;
4372
4373
ies = IEs + _BEACON_IE_OFFSET_;
4374
ies_len = IELength - _BEACON_IE_OFFSET_;
4375
4376
p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
4377
4378
while (p2p_ie) {
4379
/* Get P2P Manageability IE. */
4380
if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_MANAGEABILITY, p2p_attr, &attr_contentlen)) {
4381
if ((p2p_attr[0] & (BIT(0) | BIT(1))) == 0x01)
4382
ret = _FALSE;
4383
break;
4384
}
4385
/* Get the next P2P IE */
4386
p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
4387
}
4388
4389
return ret;
4390
}
4391
4392
#ifdef CONFIG_P2P_PS
4393
void process_p2p_ps_ie(PADAPTER padapter, u8 *IEs, u32 IELength)
4394
{
4395
u8 *ies;
4396
u32 ies_len;
4397
u8 *p2p_ie;
4398
u32 p2p_ielen = 0;
4399
u8 *noa_attr; /* NoA length should be n*(13) + 2 */
4400
u32 attr_contentlen = 0;
4401
4402
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4403
u8 find_p2p = _FALSE, find_p2p_ps = _FALSE;
4404
u8 noa_offset, noa_num, noa_index;
4405
4406
4407
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4408
return;
4409
#ifdef CONFIG_CONCURRENT_MODE
4410
#ifndef CONFIG_FW_MULTI_PORT_SUPPORT
4411
if (padapter->hw_port != HW_PORT0)
4412
return;
4413
#endif
4414
#endif
4415
if (IELength <= _BEACON_IE_OFFSET_)
4416
return;
4417
4418
ies = IEs + _BEACON_IE_OFFSET_;
4419
ies_len = IELength - _BEACON_IE_OFFSET_;
4420
4421
p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
4422
4423
while (p2p_ie) {
4424
find_p2p = _TRUE;
4425
/* Get Notice of Absence IE. */
4426
noa_attr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, NULL, &attr_contentlen);
4427
if (noa_attr) {
4428
find_p2p_ps = _TRUE;
4429
noa_index = noa_attr[0];
4430
4431
if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
4432
(noa_index != pwdinfo->noa_index)) { /* if index change, driver should reconfigure related setting. */
4433
pwdinfo->noa_index = noa_index;
4434
pwdinfo->opp_ps = noa_attr[1] >> 7;
4435
pwdinfo->ctwindow = noa_attr[1] & 0x7F;
4436
4437
noa_offset = 2;
4438
noa_num = 0;
4439
/* NoA length should be n*(13) + 2 */
4440
if (attr_contentlen > 2 && (attr_contentlen - 2) % 13 == 0) {
4441
while (noa_offset < attr_contentlen && noa_num < P2P_MAX_NOA_NUM) {
4442
/* _rtw_memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */
4443
pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
4444
noa_offset += 1;
4445
4446
_rtw_memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
4447
noa_offset += 4;
4448
4449
_rtw_memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
4450
noa_offset += 4;
4451
4452
_rtw_memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
4453
noa_offset += 4;
4454
4455
noa_num++;
4456
}
4457
}
4458
pwdinfo->noa_num = noa_num;
4459
4460
if (pwdinfo->opp_ps == 1) {
4461
pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
4462
/* driver should wait LPS for entering CTWindow */
4463
if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
4464
p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
4465
} else if (pwdinfo->noa_num > 0) {
4466
pwdinfo->p2p_ps_mode = P2P_PS_NOA;
4467
p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
4468
} else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE)
4469
p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
4470
}
4471
4472
break; /* find target, just break. */
4473
}
4474
4475
/* Get the next P2P IE */
4476
p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
4477
4478
}
4479
4480
if (find_p2p == _TRUE) {
4481
if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && (find_p2p_ps == _FALSE))
4482
p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
4483
}
4484
4485
}
4486
4487
void p2p_ps_wk_hdl(_adapter *padapter, u8 p2p_ps_state)
4488
{
4489
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
4490
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4491
u32 ps_deny = 0;
4492
4493
/* Pre action for p2p state */
4494
switch (p2p_ps_state) {
4495
case P2P_PS_DISABLE:
4496
pwdinfo->p2p_ps_state = p2p_ps_state;
4497
4498
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4499
4500
pwdinfo->noa_index = 0;
4501
pwdinfo->ctwindow = 0;
4502
pwdinfo->opp_ps = 0;
4503
pwdinfo->noa_num = 0;
4504
pwdinfo->p2p_ps_mode = P2P_PS_NONE;
4505
if (pwrpriv->bFwCurrentInPSMode == _TRUE) {
4506
if (pwrpriv->smart_ps == 0) {
4507
pwrpriv->smart_ps = 2;
4508
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));
4509
}
4510
}
4511
break;
4512
case P2P_PS_ENABLE:
4513
_enter_pwrlock(&adapter_to_pwrctl(padapter)->lock);
4514
ps_deny = rtw_ps_deny_get(padapter);
4515
_exit_pwrlock(&adapter_to_pwrctl(padapter)->lock);
4516
4517
if ((ps_deny & (PS_DENY_SCAN | PS_DENY_JOIN))
4518
|| rtw_mi_check_fwstate(padapter, (_FW_UNDER_SURVEY | _FW_UNDER_LINKING))) {
4519
pwdinfo->p2p_ps_mode = P2P_PS_NONE;
4520
RTW_DBG(FUNC_ADPT_FMT" Block P2P PS under site survey or LINKING\n", FUNC_ADPT_ARG(padapter));
4521
return;
4522
}
4523
if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
4524
#ifdef CONFIG_MCC_MODE
4525
if (MCC_EN(padapter)) {
4526
if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
4527
RTW_INFO("P2P PS enble under MCC\n");
4528
rtw_warn_on(1);
4529
}
4530
4531
}
4532
#endif /* CONFIG_MCC_MODE */
4533
pwdinfo->p2p_ps_state = p2p_ps_state;
4534
4535
if (pwdinfo->ctwindow > 0) {
4536
if (pwrpriv->smart_ps != 0) {
4537
pwrpriv->smart_ps = 0;
4538
RTW_INFO("%s(): Enter CTW, change SmartPS\n", __FUNCTION__);
4539
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));
4540
}
4541
}
4542
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4543
}
4544
break;
4545
case P2P_PS_SCAN:
4546
case P2P_PS_SCAN_DONE:
4547
case P2P_PS_ALLSTASLEEP:
4548
if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
4549
pwdinfo->p2p_ps_state = p2p_ps_state;
4550
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
4551
}
4552
break;
4553
default:
4554
break;
4555
}
4556
4557
#ifdef CONFIG_MCC_MODE
4558
rtw_hal_mcc_process_noa(padapter);
4559
#endif /* CONFIG_MCC_MODE */
4560
}
4561
4562
u8 p2p_ps_wk_cmd(_adapter *padapter, u8 p2p_ps_state, u8 enqueue)
4563
{
4564
struct cmd_obj *ph2c;
4565
struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4566
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4567
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4568
u8 res = _SUCCESS;
4569
4570
4571
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
4572
#ifdef CONFIG_CONCURRENT_MODE
4573
#ifndef CONFIG_FW_MULTI_PORT_SUPPORT
4574
|| (padapter->hw_port != HW_PORT0)
4575
#endif
4576
#endif
4577
)
4578
return res;
4579
4580
if (enqueue) {
4581
ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4582
if (ph2c == NULL) {
4583
res = _FAIL;
4584
goto exit;
4585
}
4586
4587
pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4588
if (pdrvextra_cmd_parm == NULL) {
4589
rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
4590
res = _FAIL;
4591
goto exit;
4592
}
4593
4594
pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
4595
pdrvextra_cmd_parm->type = p2p_ps_state;
4596
pdrvextra_cmd_parm->size = 0;
4597
pdrvextra_cmd_parm->pbuf = NULL;
4598
4599
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
4600
4601
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
4602
} else
4603
p2p_ps_wk_hdl(padapter, p2p_ps_state);
4604
4605
exit:
4606
4607
4608
return res;
4609
4610
}
4611
#endif /* CONFIG_P2P_PS */
4612
4613
static void reset_ch_sitesurvey_timer_process(void *FunctionContext)
4614
{
4615
_adapter *adapter = (_adapter *)FunctionContext;
4616
struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4617
4618
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4619
return;
4620
4621
RTW_INFO("[%s] In\n", __FUNCTION__);
4622
/* Reset the operation channel information */
4623
pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
4624
#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
4625
pwdinfo->rx_invitereq_info.operation_ch[1] = 0;
4626
pwdinfo->rx_invitereq_info.operation_ch[2] = 0;
4627
pwdinfo->rx_invitereq_info.operation_ch[3] = 0;
4628
#endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
4629
pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
4630
}
4631
4632
static void reset_ch_sitesurvey_timer_process2(void *FunctionContext)
4633
{
4634
_adapter *adapter = (_adapter *)FunctionContext;
4635
struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4636
4637
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4638
return;
4639
4640
RTW_INFO("[%s] In\n", __FUNCTION__);
4641
/* Reset the operation channel information */
4642
pwdinfo->p2p_info.operation_ch[0] = 0;
4643
#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
4644
pwdinfo->p2p_info.operation_ch[1] = 0;
4645
pwdinfo->p2p_info.operation_ch[2] = 0;
4646
pwdinfo->p2p_info.operation_ch[3] = 0;
4647
#endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
4648
pwdinfo->p2p_info.scan_op_ch_only = 0;
4649
}
4650
4651
static void restore_p2p_state_timer_process(void *FunctionContext)
4652
{
4653
_adapter *adapter = (_adapter *)FunctionContext;
4654
struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4655
4656
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4657
return;
4658
4659
p2p_protocol_wk_cmd(adapter, P2P_RESTORE_STATE_WK);
4660
}
4661
4662
static void pre_tx_scan_timer_process(void *FunctionContext)
4663
{
4664
_adapter *adapter = (_adapter *) FunctionContext;
4665
struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4666
_irqL irqL;
4667
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
4668
4669
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4670
return;
4671
4672
_enter_critical_bh(&pmlmepriv->lock, &irqL);
4673
4674
4675
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
4676
if (_TRUE == pwdinfo->tx_prov_disc_info.benable) { /* the provision discovery request frame is trigger to send or not */
4677
p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK);
4678
/* issue_probereq_p2p(adapter, NULL); */
4679
/* _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); */
4680
}
4681
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
4682
if (_TRUE == pwdinfo->nego_req_info.benable)
4683
p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK);
4684
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
4685
if (_TRUE == pwdinfo->invitereq_info.benable)
4686
p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK);
4687
} else
4688
RTW_INFO("[%s] p2p_state is %d, ignore!!\n", __FUNCTION__, rtw_p2p_state(pwdinfo));
4689
4690
_exit_critical_bh(&pmlmepriv->lock, &irqL);
4691
}
4692
4693
static void find_phase_timer_process(void *FunctionContext)
4694
{
4695
_adapter *adapter = (_adapter *)FunctionContext;
4696
struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4697
4698
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4699
return;
4700
4701
adapter->wdinfo.find_phase_state_exchange_cnt++;
4702
4703
p2p_protocol_wk_cmd(adapter, P2P_FIND_PHASE_WK);
4704
}
4705
4706
#ifdef CONFIG_CONCURRENT_MODE
4707
void ap_p2p_switch_timer_process(void *FunctionContext)
4708
{
4709
_adapter *adapter = (_adapter *)FunctionContext;
4710
struct wifidirect_info *pwdinfo = &adapter->wdinfo;
4711
#ifdef CONFIG_IOCTL_CFG80211
4712
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
4713
#endif
4714
4715
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4716
return;
4717
4718
#ifdef CONFIG_IOCTL_CFG80211
4719
ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
4720
#endif
4721
4722
p2p_protocol_wk_cmd(adapter, P2P_AP_P2P_CH_SWITCH_PROCESS_WK);
4723
}
4724
#endif
4725
4726
void reset_global_wifidirect_info(_adapter *padapter)
4727
{
4728
struct wifidirect_info *pwdinfo;
4729
4730
pwdinfo = &padapter->wdinfo;
4731
pwdinfo->persistent_supported = 0;
4732
pwdinfo->session_available = _TRUE;
4733
rtw_tdls_wfd_enable(padapter, 0);
4734
pwdinfo->wfd_tdls_weaksec = _TRUE;
4735
}
4736
4737
#ifdef CONFIG_WFD
4738
int rtw_init_wifi_display_info(_adapter *padapter)
4739
{
4740
int res = _SUCCESS;
4741
struct wifi_display_info *pwfd_info = &padapter->wfd_info;
4742
4743
/* Used in P2P and TDLS */
4744
pwfd_info->init_rtsp_ctrlport = 554;
4745
#ifdef CONFIG_IOCTL_CFG80211
4746
pwfd_info->rtsp_ctrlport = 0;
4747
#else
4748
pwfd_info->rtsp_ctrlport = pwfd_info->init_rtsp_ctrlport; /* set non-zero value for legacy wfd */
4749
#endif
4750
pwfd_info->tdls_rtsp_ctrlport = 0;
4751
pwfd_info->peer_rtsp_ctrlport = 0; /* Reset to 0 */
4752
pwfd_info->wfd_enable = _FALSE;
4753
pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
4754
pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
4755
4756
/* Used in P2P */
4757
pwfd_info->peer_session_avail = _TRUE;
4758
pwfd_info->wfd_pc = _FALSE;
4759
4760
/* Used in TDLS */
4761
_rtw_memset(pwfd_info->ip_address, 0x00, 4);
4762
_rtw_memset(pwfd_info->peer_ip_address, 0x00, 4);
4763
return res;
4764
4765
}
4766
4767
inline void rtw_wfd_enable(_adapter *adapter, bool on)
4768
{
4769
struct wifi_display_info *wfdinfo = &adapter->wfd_info;
4770
4771
if (on) {
4772
wfdinfo->rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;
4773
wfdinfo->wfd_enable = _TRUE;
4774
4775
} else {
4776
wfdinfo->wfd_enable = _FALSE;
4777
wfdinfo->rtsp_ctrlport = 0;
4778
}
4779
}
4780
4781
inline void rtw_wfd_set_ctrl_port(_adapter *adapter, u16 port)
4782
{
4783
struct wifi_display_info *wfdinfo = &adapter->wfd_info;
4784
4785
wfdinfo->init_rtsp_ctrlport = port;
4786
if (wfdinfo->wfd_enable == _TRUE)
4787
wfdinfo->rtsp_ctrlport = port;
4788
if (adapter->wdinfo.wfd_tdls_enable == 1)
4789
wfdinfo->tdls_rtsp_ctrlport = port;
4790
}
4791
4792
inline void rtw_tdls_wfd_enable(_adapter *adapter, bool on)
4793
{
4794
struct wifi_display_info *wfdinfo = &adapter->wfd_info;
4795
4796
if (on) {
4797
wfdinfo->tdls_rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;
4798
adapter->wdinfo.wfd_tdls_enable = 1;
4799
4800
} else {
4801
adapter->wdinfo.wfd_tdls_enable = 0;
4802
wfdinfo->tdls_rtsp_ctrlport = 0;
4803
}
4804
}
4805
4806
u32 rtw_append_beacon_wfd_ie(_adapter *adapter, u8 *pbuf)
4807
{
4808
struct wifidirect_info *wdinfo = &adapter->wdinfo;
4809
struct mlme_priv *mlme = &adapter->mlmepriv;
4810
u8 build_ie_by_self = 0;
4811
u32 len = 0;
4812
4813
if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4814
goto exit;
4815
4816
#ifdef CONFIG_IOCTL_CFG80211
4817
if (_TRUE == wdinfo->wfd_info->wfd_enable)
4818
#endif
4819
build_ie_by_self = 1;
4820
4821
if (build_ie_by_self)
4822
len = build_beacon_wfd_ie(wdinfo, pbuf);
4823
#ifdef CONFIG_IOCTL_CFG80211
4824
else if (mlme->wfd_beacon_ie && mlme->wfd_beacon_ie_len > 0) {
4825
len = mlme->wfd_beacon_ie_len;
4826
_rtw_memcpy(pbuf, mlme->wfd_beacon_ie, len);
4827
}
4828
#endif
4829
4830
exit:
4831
return len;
4832
}
4833
4834
u32 rtw_append_probe_req_wfd_ie(_adapter *adapter, u8 *pbuf)
4835
{
4836
struct wifidirect_info *wdinfo = &adapter->wdinfo;
4837
struct mlme_priv *mlme = &adapter->mlmepriv;
4838
u8 build_ie_by_self = 0;
4839
u32 len = 0;
4840
4841
if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4842
goto exit;
4843
4844
#ifdef CONFIG_IOCTL_CFG80211
4845
if (_TRUE == wdinfo->wfd_info->wfd_enable)
4846
#endif
4847
build_ie_by_self = 1;
4848
4849
if (build_ie_by_self)
4850
len = build_probe_req_wfd_ie(wdinfo, pbuf);
4851
#ifdef CONFIG_IOCTL_CFG80211
4852
else if (mlme->wfd_probe_req_ie && mlme->wfd_probe_req_ie_len > 0) {
4853
len = mlme->wfd_probe_req_ie_len;
4854
_rtw_memcpy(pbuf, mlme->wfd_probe_req_ie, len);
4855
}
4856
#endif
4857
4858
exit:
4859
return len;
4860
}
4861
4862
u32 rtw_append_probe_resp_wfd_ie(_adapter *adapter, u8 *pbuf)
4863
{
4864
struct wifidirect_info *wdinfo = &adapter->wdinfo;
4865
struct mlme_priv *mlme = &adapter->mlmepriv;
4866
u8 build_ie_by_self = 0;
4867
u32 len = 0;
4868
4869
if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4870
goto exit;
4871
4872
#ifdef CONFIG_IOCTL_CFG80211
4873
if (_TRUE == wdinfo->wfd_info->wfd_enable)
4874
#endif
4875
build_ie_by_self = 1;
4876
4877
if (build_ie_by_self)
4878
len = build_probe_resp_wfd_ie(wdinfo, pbuf, 0);
4879
#ifdef CONFIG_IOCTL_CFG80211
4880
else if (mlme->wfd_probe_resp_ie && mlme->wfd_probe_resp_ie_len > 0) {
4881
len = mlme->wfd_probe_resp_ie_len;
4882
_rtw_memcpy(pbuf, mlme->wfd_probe_resp_ie, len);
4883
}
4884
#endif
4885
4886
exit:
4887
return len;
4888
}
4889
4890
u32 rtw_append_assoc_req_wfd_ie(_adapter *adapter, u8 *pbuf)
4891
{
4892
struct wifidirect_info *wdinfo = &adapter->wdinfo;
4893
struct mlme_priv *mlme = &adapter->mlmepriv;
4894
u8 build_ie_by_self = 0;
4895
u32 len = 0;
4896
4897
if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4898
goto exit;
4899
4900
#ifdef CONFIG_IOCTL_CFG80211
4901
if (_TRUE == wdinfo->wfd_info->wfd_enable)
4902
#endif
4903
build_ie_by_self = 1;
4904
4905
if (build_ie_by_self)
4906
len = build_assoc_req_wfd_ie(wdinfo, pbuf);
4907
#ifdef CONFIG_IOCTL_CFG80211
4908
else if (mlme->wfd_assoc_req_ie && mlme->wfd_assoc_req_ie_len > 0) {
4909
len = mlme->wfd_assoc_req_ie_len;
4910
_rtw_memcpy(pbuf, mlme->wfd_assoc_req_ie, len);
4911
}
4912
#endif
4913
4914
exit:
4915
return len;
4916
}
4917
4918
u32 rtw_append_assoc_resp_wfd_ie(_adapter *adapter, u8 *pbuf)
4919
{
4920
struct wifidirect_info *wdinfo = &adapter->wdinfo;
4921
struct mlme_priv *mlme = &adapter->mlmepriv;
4922
u8 build_ie_by_self = 0;
4923
u32 len = 0;
4924
4925
if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
4926
goto exit;
4927
4928
#ifdef CONFIG_IOCTL_CFG80211
4929
if (_TRUE == wdinfo->wfd_info->wfd_enable)
4930
#endif
4931
build_ie_by_self = 1;
4932
4933
if (build_ie_by_self)
4934
len = build_assoc_resp_wfd_ie(wdinfo, pbuf);
4935
#ifdef CONFIG_IOCTL_CFG80211
4936
else if (mlme->wfd_assoc_resp_ie && mlme->wfd_assoc_resp_ie_len > 0) {
4937
len = mlme->wfd_assoc_resp_ie_len;
4938
_rtw_memcpy(pbuf, mlme->wfd_assoc_resp_ie, len);
4939
}
4940
#endif
4941
4942
exit:
4943
return len;
4944
}
4945
4946
#endif /* CONFIG_WFD */
4947
4948
void rtw_init_wifidirect_timers(_adapter *padapter)
4949
{
4950
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4951
4952
rtw_init_timer(&pwdinfo->find_phase_timer, padapter, find_phase_timer_process, padapter);
4953
rtw_init_timer(&pwdinfo->restore_p2p_state_timer, padapter, restore_p2p_state_timer_process, padapter);
4954
rtw_init_timer(&pwdinfo->pre_tx_scan_timer, padapter, pre_tx_scan_timer_process, padapter);
4955
rtw_init_timer(&pwdinfo->reset_ch_sitesurvey, padapter, reset_ch_sitesurvey_timer_process, padapter);
4956
rtw_init_timer(&pwdinfo->reset_ch_sitesurvey2, padapter, reset_ch_sitesurvey_timer_process2, padapter);
4957
#ifdef CONFIG_CONCURRENT_MODE
4958
rtw_init_timer(&pwdinfo->ap_p2p_switch_timer, padapter, ap_p2p_switch_timer_process, padapter);
4959
#endif
4960
}
4961
4962
void rtw_init_wifidirect_addrs(_adapter *padapter, u8 *dev_addr, u8 *iface_addr)
4963
{
4964
#ifdef CONFIG_P2P
4965
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4966
4967
/*init device&interface address */
4968
if (dev_addr)
4969
_rtw_memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
4970
if (iface_addr)
4971
_rtw_memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
4972
#endif
4973
}
4974
4975
void init_wifidirect_info(_adapter *padapter, enum P2P_ROLE role)
4976
{
4977
struct wifidirect_info *pwdinfo;
4978
#ifdef CONFIG_WFD
4979
struct wifi_display_info *pwfd_info = &padapter->wfd_info;
4980
#endif
4981
pwdinfo = &padapter->wdinfo;
4982
4983
pwdinfo->padapter = padapter;
4984
4985
/* 1, 6, 11 are the social channel defined in the WiFi Direct specification. */
4986
pwdinfo->social_chan[0] = 1;
4987
pwdinfo->social_chan[1] = 6;
4988
pwdinfo->social_chan[2] = 11;
4989
pwdinfo->social_chan[3] = 0; /* channel 0 for scanning ending in site survey function. */
4990
4991
if (role != P2P_ROLE_DISABLE
4992
&& pwdinfo->driver_interface != DRIVER_CFG80211
4993
) {
4994
#ifdef CONFIG_CONCURRENT_MODE
4995
u8 union_ch = 0;
4996
4997
if (rtw_mi_check_status(padapter, MI_LINKED))
4998
union_ch = rtw_mi_get_union_chan(padapter);
4999
5000
if (union_ch != 0 &&
5001
(union_ch == 1 || union_ch == 6 || union_ch == 11)
5002
) {
5003
/* Use the AP's channel as the listen channel */
5004
/* This will avoid the channel switch between AP's channel and listen channel */
5005
pwdinfo->listen_channel = union_ch;
5006
} else
5007
#endif /* CONFIG_CONCURRENT_MODE */
5008
{
5009
/* Use the channel 11 as the listen channel */
5010
pwdinfo->listen_channel = 11;
5011
}
5012
}
5013
5014
if (role == P2P_ROLE_DEVICE) {
5015
rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
5016
#ifdef CONFIG_CONCURRENT_MODE
5017
if (rtw_mi_check_status(padapter, MI_LINKED))
5018
rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
5019
else
5020
#endif
5021
rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
5022
5023
pwdinfo->intent = 1;
5024
rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
5025
} else if (role == P2P_ROLE_CLIENT) {
5026
rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
5027
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
5028
pwdinfo->intent = 1;
5029
rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
5030
} else if (role == P2P_ROLE_GO) {
5031
rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
5032
rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
5033
pwdinfo->intent = 15;
5034
rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
5035
}
5036
5037
/* Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 ) */
5038
pwdinfo->support_rate[0] = 0x8c; /* 6(B) */
5039
pwdinfo->support_rate[1] = 0x92; /* 9(B) */
5040
pwdinfo->support_rate[2] = 0x18; /* 12 */
5041
pwdinfo->support_rate[3] = 0x24; /* 18 */
5042
pwdinfo->support_rate[4] = 0x30; /* 24 */
5043
pwdinfo->support_rate[5] = 0x48; /* 36 */
5044
pwdinfo->support_rate[6] = 0x60; /* 48 */
5045
pwdinfo->support_rate[7] = 0x6c; /* 54 */
5046
5047
_rtw_memcpy((void *) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);
5048
5049
_rtw_memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
5050
pwdinfo->device_name_len = 0;
5051
5052
_rtw_memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info));
5053
pwdinfo->invitereq_info.token = 3; /* Token used for P2P invitation request frame. */
5054
5055
_rtw_memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info));
5056
pwdinfo->inviteresp_info.token = 0;
5057
5058
pwdinfo->profileindex = 0;
5059
_rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
5060
5061
rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
5062
5063
pwdinfo->listen_dwell = (u8)((rtw_get_current_time() % 3) + 1);
5064
/* RTW_INFO( "[%s] listen_dwell time is %d00ms\n", __FUNCTION__, pwdinfo->listen_dwell ); */
5065
5066
_rtw_memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info));
5067
pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
5068
5069
_rtw_memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
5070
5071
pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
5072
pwdinfo->negotiation_dialog_token = 1;
5073
5074
_rtw_memset(pwdinfo->nego_ssid, 0x00, WLAN_SSID_MAXLEN);
5075
pwdinfo->nego_ssidlen = 0;
5076
5077
pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
5078
#ifdef CONFIG_WFD
5079
pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC;
5080
pwdinfo->wfd_info = pwfd_info;
5081
#else
5082
pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
5083
#endif /* CONFIG_WFD */
5084
pwdinfo->channel_list_attr_len = 0;
5085
_rtw_memset(pwdinfo->channel_list_attr, 0x00, 100);
5086
5087
_rtw_memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4);
5088
_rtw_memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3);
5089
_rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
5090
#ifdef CONFIG_CONCURRENT_MODE
5091
#ifdef CONFIG_IOCTL_CFG80211
5092
pwdinfo->ext_listen_interval = 1000; /* The interval to be available with legacy AP during p2p0-find/scan */
5093
pwdinfo->ext_listen_period = 3000; /* The time period to be available for P2P during nego */
5094
#else /* !CONFIG_IOCTL_CFG80211 */
5095
/* pwdinfo->ext_listen_interval = 3000; */
5096
/* pwdinfo->ext_listen_period = 400; */
5097
pwdinfo->ext_listen_interval = 1000;
5098
pwdinfo->ext_listen_period = 1000;
5099
#endif /* !CONFIG_IOCTL_CFG80211 */
5100
#endif
5101
5102
/* Commented by Kurt 20130319
5103
* For WiDi purpose: Use CFG80211 interface but controled WFD/RDS frame by driver itself. */
5104
#ifdef CONFIG_IOCTL_CFG80211
5105
pwdinfo->driver_interface = DRIVER_CFG80211;
5106
#else
5107
pwdinfo->driver_interface = DRIVER_WEXT;
5108
#endif /* CONFIG_IOCTL_CFG80211 */
5109
5110
pwdinfo->wfd_tdls_enable = 0;
5111
_rtw_memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
5112
_rtw_memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN);
5113
5114
pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
5115
pwdinfo->rx_invitereq_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
5116
#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5117
pwdinfo->rx_invitereq_info.operation_ch[2] = 0;
5118
pwdinfo->rx_invitereq_info.operation_ch[3] = 0;
5119
pwdinfo->rx_invitereq_info.operation_ch[4] = 0;
5120
#endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
5121
pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
5122
pwdinfo->p2p_info.operation_ch[0] = 0;
5123
pwdinfo->p2p_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
5124
#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
5125
pwdinfo->p2p_info.operation_ch[2] = 0;
5126
pwdinfo->p2p_info.operation_ch[3] = 0;
5127
pwdinfo->p2p_info.operation_ch[4] = 0;
5128
#endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
5129
pwdinfo->p2p_info.scan_op_ch_only = 0;
5130
}
5131
5132
void _rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role)
5133
{
5134
if (wdinfo->role != role) {
5135
wdinfo->role = role;
5136
rtw_mi_update_iface_status(&(wdinfo->padapter->mlmepriv), 0);
5137
}
5138
}
5139
5140
#ifdef CONFIG_DBG_P2P
5141
5142
/**
5143
* rtw_p2p_role_txt - Get the p2p role name as a text string
5144
* @role: P2P role
5145
* Returns: The state name as a printable text string
5146
*/
5147
const char *rtw_p2p_role_txt(enum P2P_ROLE role)
5148
{
5149
switch (role) {
5150
case P2P_ROLE_DISABLE:
5151
return "P2P_ROLE_DISABLE";
5152
case P2P_ROLE_DEVICE:
5153
return "P2P_ROLE_DEVICE";
5154
case P2P_ROLE_CLIENT:
5155
return "P2P_ROLE_CLIENT";
5156
case P2P_ROLE_GO:
5157
return "P2P_ROLE_GO";
5158
default:
5159
return "UNKNOWN";
5160
}
5161
}
5162
5163
/**
5164
* rtw_p2p_state_txt - Get the p2p state name as a text string
5165
* @state: P2P state
5166
* Returns: The state name as a printable text string
5167
*/
5168
const char *rtw_p2p_state_txt(enum P2P_STATE state)
5169
{
5170
switch (state) {
5171
case P2P_STATE_NONE:
5172
return "P2P_STATE_NONE";
5173
case P2P_STATE_IDLE:
5174
return "P2P_STATE_IDLE";
5175
case P2P_STATE_LISTEN:
5176
return "P2P_STATE_LISTEN";
5177
case P2P_STATE_SCAN:
5178
return "P2P_STATE_SCAN";
5179
case P2P_STATE_FIND_PHASE_LISTEN:
5180
return "P2P_STATE_FIND_PHASE_LISTEN";
5181
case P2P_STATE_FIND_PHASE_SEARCH:
5182
return "P2P_STATE_FIND_PHASE_SEARCH";
5183
case P2P_STATE_TX_PROVISION_DIS_REQ:
5184
return "P2P_STATE_TX_PROVISION_DIS_REQ";
5185
case P2P_STATE_RX_PROVISION_DIS_RSP:
5186
return "P2P_STATE_RX_PROVISION_DIS_RSP";
5187
case P2P_STATE_RX_PROVISION_DIS_REQ:
5188
return "P2P_STATE_RX_PROVISION_DIS_REQ";
5189
case P2P_STATE_GONEGO_ING:
5190
return "P2P_STATE_GONEGO_ING";
5191
case P2P_STATE_GONEGO_OK:
5192
return "P2P_STATE_GONEGO_OK";
5193
case P2P_STATE_GONEGO_FAIL:
5194
return "P2P_STATE_GONEGO_FAIL";
5195
case P2P_STATE_RECV_INVITE_REQ_MATCH:
5196
return "P2P_STATE_RECV_INVITE_REQ_MATCH";
5197
case P2P_STATE_PROVISIONING_ING:
5198
return "P2P_STATE_PROVISIONING_ING";
5199
case P2P_STATE_PROVISIONING_DONE:
5200
return "P2P_STATE_PROVISIONING_DONE";
5201
case P2P_STATE_TX_INVITE_REQ:
5202
return "P2P_STATE_TX_INVITE_REQ";
5203
case P2P_STATE_RX_INVITE_RESP_OK:
5204
return "P2P_STATE_RX_INVITE_RESP_OK";
5205
case P2P_STATE_RECV_INVITE_REQ_DISMATCH:
5206
return "P2P_STATE_RECV_INVITE_REQ_DISMATCH";
5207
case P2P_STATE_RECV_INVITE_REQ_GO:
5208
return "P2P_STATE_RECV_INVITE_REQ_GO";
5209
case P2P_STATE_RECV_INVITE_REQ_JOIN:
5210
return "P2P_STATE_RECV_INVITE_REQ_JOIN";
5211
case P2P_STATE_RX_INVITE_RESP_FAIL:
5212
return "P2P_STATE_RX_INVITE_RESP_FAIL";
5213
case P2P_STATE_RX_INFOR_NOREADY:
5214
return "P2P_STATE_RX_INFOR_NOREADY";
5215
case P2P_STATE_TX_INFOR_NOREADY:
5216
return "P2P_STATE_TX_INFOR_NOREADY";
5217
default:
5218
return "UNKNOWN";
5219
}
5220
}
5221
5222
void dbg_rtw_p2p_set_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)
5223
{
5224
if (!_rtw_p2p_chk_state(wdinfo, state)) {
5225
enum P2P_STATE old_state = _rtw_p2p_state(wdinfo);
5226
_rtw_p2p_set_state(wdinfo, state);
5227
RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_state from %s to %s\n", caller, line
5228
, rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))
5229
);
5230
} else {
5231
RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_state to same state %s\n", caller, line
5232
, rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))
5233
);
5234
}
5235
}
5236
void dbg_rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)
5237
{
5238
if (_rtw_p2p_pre_state(wdinfo) != state) {
5239
enum P2P_STATE old_state = _rtw_p2p_pre_state(wdinfo);
5240
_rtw_p2p_set_pre_state(wdinfo, state);
5241
RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_pre_state from %s to %s\n", caller, line
5242
, rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))
5243
);
5244
} else {
5245
RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_pre_state to same state %s\n", caller, line
5246
, rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))
5247
);
5248
}
5249
}
5250
#if 0
5251
void dbg_rtw_p2p_restore_state(struct wifidirect_info *wdinfo, const char *caller, int line)
5252
{
5253
if (wdinfo->pre_p2p_state != -1) {
5254
RTW_INFO("[CONFIG_DBG_P2P]%s:%d restore from %s to %s\n", caller, line
5255
, p2p_state_str[wdinfo->p2p_state], p2p_state_str[wdinfo->pre_p2p_state]
5256
);
5257
_rtw_p2p_restore_state(wdinfo);
5258
} else {
5259
RTW_INFO("[CONFIG_DBG_P2P]%s:%d restore no pre state, cur state %s\n", caller, line
5260
, p2p_state_str[wdinfo->p2p_state]
5261
);
5262
}
5263
}
5264
#endif
5265
void dbg_rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role, const char *caller, int line)
5266
{
5267
if (wdinfo->role != role) {
5268
enum P2P_ROLE old_role = wdinfo->role;
5269
_rtw_p2p_set_role(wdinfo, role);
5270
RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_role from %s to %s\n", caller, line
5271
, rtw_p2p_role_txt(old_role), rtw_p2p_role_txt(wdinfo->role)
5272
);
5273
} else {
5274
RTW_INFO("[CONFIG_DBG_P2P]%s:%d set_role to same role %s\n", caller, line
5275
, rtw_p2p_role_txt(wdinfo->role)
5276
);
5277
}
5278
}
5279
#endif /* CONFIG_DBG_P2P */
5280
5281
5282
int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role)
5283
{
5284
int ret = _SUCCESS;
5285
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5286
5287
if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT || role == P2P_ROLE_GO) {
5288
#if defined(CONFIG_CONCURRENT_MODE) && (!defined(RTW_P2P_GROUP_INTERFACE) || !RTW_P2P_GROUP_INTERFACE)
5289
/* Commented by Albert 2011/12/30 */
5290
/* The driver just supports 1 P2P group operation. */
5291
/* So, this function will do nothing if the buddy adapter had enabled the P2P function. */
5292
/*if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))
5293
return ret;*/
5294
/*The buddy adapter had enabled the P2P function.*/
5295
if (rtw_mi_buddy_stay_in_p2p_mode(padapter))
5296
return ret;
5297
#endif /* CONFIG_CONCURRENT_MODE */
5298
5299
/* leave IPS/Autosuspend */
5300
if (_FAIL == rtw_pwr_wakeup(padapter)) {
5301
ret = _FAIL;
5302
goto exit;
5303
}
5304
5305
/* Added by Albert 2011/03/22 */
5306
/* In the P2P mode, the driver should not support the b mode. */
5307
/* So, the Tx packet shouldn't use the CCK rate */
5308
#ifdef CONFIG_IOCTL_CFG80211
5309
if (rtw_cfg80211_iface_has_p2p_group_cap(padapter))
5310
#endif
5311
update_tx_basic_rate(padapter, WIRELESS_11AGN);
5312
5313
/* Enable P2P function */
5314
init_wifidirect_info(padapter, role);
5315
5316
#ifdef CONFIG_IOCTL_CFG80211
5317
if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
5318
adapter_wdev_data(padapter)->p2p_enabled = _TRUE;
5319
#endif
5320
5321
rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, _TRUE);
5322
#ifdef CONFIG_WFD
5323
if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
5324
rtw_hal_set_odm_var(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, _TRUE);
5325
#endif
5326
5327
} else if (role == P2P_ROLE_DISABLE) {
5328
5329
#ifdef CONFIG_IOCTL_CFG80211
5330
if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
5331
adapter_wdev_data(padapter)->p2p_enabled = _FALSE;
5332
#endif
5333
5334
pwdinfo->listen_channel = 0;
5335
5336
/* Disable P2P function */
5337
if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
5338
_cancel_timer_ex(&pwdinfo->find_phase_timer);
5339
_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
5340
_cancel_timer_ex(&pwdinfo->pre_tx_scan_timer);
5341
_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
5342
_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey2);
5343
reset_ch_sitesurvey_timer_process(padapter);
5344
reset_ch_sitesurvey_timer_process2(padapter);
5345
#ifdef CONFIG_CONCURRENT_MODE
5346
_cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
5347
#endif
5348
rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
5349
rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_NONE);
5350
rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
5351
_rtw_memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
5352
5353
/* Remove profiles in wifidirect_info structure. */
5354
_rtw_memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
5355
pwdinfo->profileindex = 0;
5356
}
5357
5358
rtw_hal_set_odm_var(padapter, HAL_ODM_P2P_STATE, NULL, _FALSE);
5359
#ifdef CONFIG_WFD
5360
if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
5361
rtw_hal_set_odm_var(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, _FALSE);
5362
#endif
5363
5364
if (_FAIL == rtw_pwr_wakeup(padapter)) {
5365
ret = _FAIL;
5366
goto exit;
5367
}
5368
5369
/* Restore to initial setting. */
5370
update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
5371
5372
/* For WiDi purpose. */
5373
#ifdef CONFIG_IOCTL_CFG80211
5374
pwdinfo->driver_interface = DRIVER_CFG80211;
5375
#else
5376
pwdinfo->driver_interface = DRIVER_WEXT;
5377
#endif /* CONFIG_IOCTL_CFG80211 */
5378
5379
}
5380
5381
exit:
5382
return ret;
5383
}
5384
5385
#endif /* CONFIG_P2P */
5386
5387