linux/drivers/staging/r8188eu/core/rtw_p2p.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2007 - 2011 Realtek Corporation. */
   3
   4#define _RTW_P2P_C_
   5
   6#include "../include/drv_types.h"
   7#include "../include/rtw_p2p.h"
   8#include "../include/wifi.h"
   9
  10static int rtw_p2p_is_channel_list_ok(u8 desired_ch, u8 *ch_list, u8 ch_cnt)
  11{
  12        int found = 0, i = 0;
  13
  14        for (i = 0; i < ch_cnt; i++) {
  15                if (ch_list[i] == desired_ch) {
  16                        found = 1;
  17                        break;
  18                }
  19        }
  20        return found;
  21}
  22
  23static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
  24{
  25        struct list_head *phead, *plist;
  26        u32 len = 0;
  27        u16 attr_len = 0;
  28        u8 tmplen, *pdata_attr, *pstart, *pcur;
  29        struct sta_info *psta = NULL;
  30        struct adapter *padapter = pwdinfo->padapter;
  31        struct sta_priv *pstapriv = &padapter->stapriv;
  32
  33        DBG_88E("%s\n", __func__);
  34
  35        pdata_attr = kzalloc(MAX_P2P_IE_LEN, GFP_KERNEL);
  36
  37        pstart = pdata_attr;
  38        pcur = pdata_attr;
  39
  40        spin_lock_bh(&pstapriv->asoc_list_lock);
  41        phead = &pstapriv->asoc_list;
  42        plist = phead->next;
  43
  44        /* look up sta asoc_queue */
  45        while (phead != plist) {
  46                psta = container_of(plist, struct sta_info, asoc_list);
  47
  48                plist = plist->next;
  49
  50                if (psta->is_p2p_device) {
  51                        tmplen = 0;
  52
  53                        pcur++;
  54
  55                        /* P2P device address */
  56                        memcpy(pcur, psta->dev_addr, ETH_ALEN);
  57                        pcur += ETH_ALEN;
  58
  59                        /* P2P interface address */
  60                        memcpy(pcur, psta->hwaddr, ETH_ALEN);
  61                        pcur += ETH_ALEN;
  62
  63                        *pcur = psta->dev_cap;
  64                        pcur++;
  65
  66                        /* u16*)(pcur) = cpu_to_be16(psta->config_methods); */
  67                        RTW_PUT_BE16(pcur, psta->config_methods);
  68                        pcur += 2;
  69
  70                        memcpy(pcur, psta->primary_dev_type, 8);
  71                        pcur += 8;
  72
  73                        *pcur = psta->num_of_secdev_type;
  74                        pcur++;
  75
  76                        memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type * 8);
  77                        pcur += psta->num_of_secdev_type * 8;
  78
  79                        if (psta->dev_name_len > 0) {
  80                                /* u16*)(pcur) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
  81                                RTW_PUT_BE16(pcur, WPS_ATTR_DEVICE_NAME);
  82                                pcur += 2;
  83
  84                                /* u16*)(pcur) = cpu_to_be16(psta->dev_name_len); */
  85                                RTW_PUT_BE16(pcur, psta->dev_name_len);
  86                                pcur += 2;
  87
  88                                memcpy(pcur, psta->dev_name, psta->dev_name_len);
  89                                pcur += psta->dev_name_len;
  90                        }
  91
  92                        tmplen = (u8)(pcur - pstart);
  93
  94                        *pstart = (tmplen - 1);
  95
  96                        attr_len += tmplen;
  97
  98                        /* pstart += tmplen; */
  99                        pstart = pcur;
 100                }
 101        }
 102        spin_unlock_bh(&pstapriv->asoc_list_lock);
 103
 104        if (attr_len > 0)
 105                len = rtw_set_p2p_attr_content(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);
 106
 107        kfree(pdata_attr);
 108        return len;
 109}
 110
 111static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)
 112{
 113        struct xmit_frame                       *pmgntframe;
 114        struct pkt_attrib                       *pattrib;
 115        unsigned char                                   *pframe;
 116        struct rtw_ieee80211_hdr        *pwlanhdr;
 117        __le16 *fctrl;
 118        struct adapter *padapter = pwdinfo->padapter;
 119        struct xmit_priv                        *pxmitpriv = &padapter->xmitpriv;
 120        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 121        unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */
 122        __be32  p2poui = cpu_to_be32(P2POUI);
 123        u8      oui_subtype = P2P_GO_DISC_REQUEST;
 124        u8      dialogToken = 0;
 125
 126        DBG_88E("[%s]\n", __func__);
 127
 128        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 129        if (!pmgntframe)
 130                return;
 131
 132        /* update attribute */
 133        pattrib = &pmgntframe->attrib;
 134        update_mgntframe_attrib(padapter, pattrib);
 135
 136        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 137
 138        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 139        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
 140
 141        fctrl = &pwlanhdr->frame_ctl;
 142        *(fctrl) = 0;
 143
 144        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
 145        memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
 146        memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
 147
 148        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
 149        pmlmeext->mgnt_seq++;
 150        SetFrameSubType(pframe, WIFI_ACTION);
 151
 152        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
 153        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
 154
 155        /* Build P2P action frame header */
 156        pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
 157        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
 158        pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
 159        pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
 160
 161        /* there is no IE in this P2P action frame */
 162
 163        pattrib->last_txcmdsz = pattrib->pktlen;
 164
 165        dump_mgntframe(padapter, pmgntframe);
 166}
 167
 168static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
 169{
 170        struct xmit_frame                       *pmgntframe;
 171        struct pkt_attrib                       *pattrib;
 172        unsigned char                                   *pframe;
 173        struct rtw_ieee80211_hdr        *pwlanhdr;
 174        __le16 *fctrl;
 175        struct adapter *padapter = pwdinfo->padapter;
 176        struct xmit_priv                        *pxmitpriv = &padapter->xmitpriv;
 177        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 178        unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
 179        u8                      action = P2P_PUB_ACTION_ACTION;
 180        __be32                  p2poui = cpu_to_be32(P2POUI);
 181        u8                      oui_subtype = P2P_DEVDISC_RESP;
 182        u8 p2pie[8] = { 0x00 };
 183        u32 p2pielen = 0;
 184
 185        DBG_88E("[%s]\n", __func__);
 186
 187        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 188        if (!pmgntframe)
 189                return;
 190
 191        /* update attribute */
 192        pattrib = &pmgntframe->attrib;
 193        update_mgntframe_attrib(padapter, pattrib);
 194
 195        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 196
 197        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 198        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
 199
 200        fctrl = &pwlanhdr->frame_ctl;
 201        *(fctrl) = 0;
 202
 203        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
 204        memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);
 205        memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);
 206
 207        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
 208        pmlmeext->mgnt_seq++;
 209        SetFrameSubType(pframe, WIFI_ACTION);
 210
 211        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
 212        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
 213
 214        /* Build P2P public action frame header */
 215        pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
 216        pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
 217        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
 218        pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
 219        pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
 220
 221        /* Build P2P IE */
 222        /*      P2P OUI */
 223        p2pielen = 0;
 224        p2pie[p2pielen++] = 0x50;
 225        p2pie[p2pielen++] = 0x6F;
 226        p2pie[p2pielen++] = 0x9A;
 227        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
 228
 229        /*  P2P_ATTR_STATUS */
 230        p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
 231
 232        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
 233
 234        pattrib->last_txcmdsz = pattrib->pktlen;
 235
 236        dump_mgntframe(padapter, pmgntframe);
 237}
 238
 239static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8 *raddr, u8 *frame_body, u16 config_method)
 240{
 241        struct adapter *padapter = pwdinfo->padapter;
 242        unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
 243        u8                      action = P2P_PUB_ACTION_ACTION;
 244        u8                      dialogToken = frame_body[7];    /*      The Dialog Token of provisioning discovery request frame. */
 245        __be32                  p2poui = cpu_to_be32(P2POUI);
 246        u8                      oui_subtype = P2P_PROVISION_DISC_RESP;
 247        u8                      wpsie[100] = { 0x00 };
 248        u8                      wpsielen = 0;
 249        struct xmit_frame                       *pmgntframe;
 250        struct pkt_attrib                       *pattrib;
 251        unsigned char                                   *pframe;
 252        struct rtw_ieee80211_hdr        *pwlanhdr;
 253        __le16 *fctrl;
 254        struct xmit_priv                        *pxmitpriv = &padapter->xmitpriv;
 255        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 256
 257        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 258        if (!pmgntframe)
 259                return;
 260
 261        /* update attribute */
 262        pattrib = &pmgntframe->attrib;
 263        update_mgntframe_attrib(padapter, pattrib);
 264
 265        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 266
 267        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 268        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
 269
 270        fctrl = &pwlanhdr->frame_ctl;
 271        *(fctrl) = 0;
 272
 273        memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
 274        memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
 275        memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
 276
 277        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
 278        pmlmeext->mgnt_seq++;
 279        SetFrameSubType(pframe, WIFI_ACTION);
 280
 281        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
 282        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
 283
 284        pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
 285        pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
 286        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
 287        pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
 288        pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
 289
 290        wpsielen = 0;
 291        /*      WPS OUI */
 292        RTW_PUT_BE32(wpsie, WPSOUI);
 293        wpsielen += 4;
 294
 295        /*      Config Method */
 296        /*      Type: */
 297        RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD);
 298        wpsielen += 2;
 299
 300        /*      Length: */
 301        RTW_PUT_BE16(wpsie + wpsielen, 0x0002);
 302        wpsielen += 2;
 303
 304        /*      Value: */
 305        RTW_PUT_BE16(wpsie + wpsielen, config_method);
 306        wpsielen += 2;
 307
 308        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
 309
 310        pattrib->last_txcmdsz = pattrib->pktlen;
 311
 312        dump_mgntframe(padapter, pmgntframe);
 313}
 314
 315static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
 316{
 317        struct xmit_frame                       *pmgntframe;
 318        struct pkt_attrib                       *pattrib;
 319        unsigned char                                   *pframe;
 320        struct rtw_ieee80211_hdr        *pwlanhdr;
 321        __le16 *fctrl;
 322        struct adapter *padapter = pwdinfo->padapter;
 323        struct xmit_priv                        *pxmitpriv = &padapter->xmitpriv;
 324        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 325        unsigned char category = RTW_WLAN_CATEGORY_P2P;/* P2P action frame */
 326        __be32  p2poui = cpu_to_be32(P2POUI);
 327        u8      oui_subtype = P2P_PRESENCE_RESPONSE;
 328        u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
 329        u8 noa_attr_content[32] = { 0x00 };
 330        u32 p2pielen = 0;
 331
 332        DBG_88E("[%s]\n", __func__);
 333
 334        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
 335        if (!pmgntframe)
 336                return;
 337
 338        /* update attribute */
 339        pattrib = &pmgntframe->attrib;
 340        update_mgntframe_attrib(padapter, pattrib);
 341
 342        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
 343
 344        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 345        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
 346
 347        fctrl = &pwlanhdr->frame_ctl;
 348        *(fctrl) = 0;
 349
 350        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
 351        memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
 352        memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
 353
 354        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
 355        pmlmeext->mgnt_seq++;
 356        SetFrameSubType(pframe, WIFI_ACTION);
 357
 358        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
 359        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
 360
 361        /* Build P2P action frame header */
 362        pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
 363        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
 364        pframe = rtw_set_fixed_ie(pframe, 1, &oui_subtype, &pattrib->pktlen);
 365        pframe = rtw_set_fixed_ie(pframe, 1, &dialogToken, &pattrib->pktlen);
 366
 367        /* Add P2P IE header */
 368        /*      P2P OUI */
 369        p2pielen = 0;
 370        p2pie[p2pielen++] = 0x50;
 371        p2pie[p2pielen++] = 0x6F;
 372        p2pie[p2pielen++] = 0x9A;
 373        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
 374
 375        /* Add Status attribute in P2P IE */
 376        p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
 377
 378        /* Add NoA attribute in P2P IE */
 379        noa_attr_content[0] = 0x1;/* index */
 380        noa_attr_content[1] = 0x0;/* CTWindow and OppPS Parameters */
 381
 382        /* todo: Notice of Absence Descriptor(s) */
 383
 384        p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);
 385
 386        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
 387
 388        pattrib->last_txcmdsz = pattrib->pktlen;
 389
 390        dump_mgntframe(padapter, pmgntframe);
 391}
 392
 393u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
 394{
 395        u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
 396        u16 capability = 0;
 397        u32 len = 0, p2pielen = 0;
 398        __le16 le_tmp;
 399
 400        /*      P2P OUI */
 401        p2pielen = 0;
 402        p2pie[p2pielen++] = 0x50;
 403        p2pie[p2pielen++] = 0x6F;
 404        p2pie[p2pielen++] = 0x9A;
 405        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
 406
 407        /*      According to the P2P Specification, the beacon frame should contain 3 P2P attributes */
 408        /*      1. P2P Capability */
 409        /*      2. P2P Device ID */
 410        /*      3. Notice of Absence (NOA) */
 411
 412        /*      P2P Capability ATTR */
 413        /*      Type: */
 414        /*      Length: */
 415        /*      Value: */
 416        /*      Device Capability Bitmap, 1 byte */
 417        /*      Be able to participate in additional P2P Groups and */
 418        /*      support the P2P Invitation Procedure */
 419        /*      Group Capability Bitmap, 1 byte */
 420        capability = P2P_DEVCAP_INVITATION_PROC | P2P_DEVCAP_CLIENT_DISCOVERABILITY;
 421        capability |=  ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);
 422        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
 423                capability |= (P2P_GRPCAP_GROUP_FORMATION << 8);
 424
 425        le_tmp = cpu_to_le16(capability);
 426        p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8 *)&le_tmp);
 427
 428        /*  P2P Device ID ATTR */
 429        p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);
 430
 431        /*  Notice of Absence ATTR */
 432        /*      Type: */
 433        /*      Length: */
 434        /*      Value: */
 435
 436        pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
 437        return len;
 438}
 439
 440u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
 441{
 442        u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
 443        u32 len = 0, p2pielen = 0;
 444
 445        /*      P2P OUI */
 446        p2pielen = 0;
 447        p2pie[p2pielen++] = 0x50;
 448        p2pie[p2pielen++] = 0x6F;
 449        p2pie[p2pielen++] = 0x9A;
 450        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
 451
 452        /*      Commented by Albert 20100907 */
 453        /*      According to the P2P Specification, the probe response frame should contain 5 P2P attributes */
 454        /*      1. P2P Capability */
 455        /*      2. Extended Listen Timing */
 456        /*      3. Notice of Absence (NOA)      (Only GO needs this) */
 457        /*      4. Device Info */
 458        /*      5. Group Info   (Only GO need this) */
 459
 460        /*      P2P Capability ATTR */
 461        /*      Type: */
 462        p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
 463
 464        /*      Length: */
 465        /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
 466        RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
 467        p2pielen += 2;
 468
 469        /*      Value: */
 470        /*      Device Capability Bitmap, 1 byte */
 471        p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
 472
 473        /*      Group Capability Bitmap, 1 byte */
 474        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
 475                p2pie[p2pielen] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);
 476
 477                if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
 478                        p2pie[p2pielen] |= P2P_GRPCAP_GROUP_FORMATION;
 479
 480                p2pielen++;
 481        } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
 482                /*      Group Capability Bitmap, 1 byte */
 483                if (pwdinfo->persistent_supported)
 484                        p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
 485                else
 486                        p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
 487        }
 488
 489        /*      Extended Listen Timing ATTR */
 490        /*      Type: */
 491        p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
 492
 493        /*      Length: */
 494        /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004); */
 495        RTW_PUT_LE16(p2pie + p2pielen, 0x0004);
 496        p2pielen += 2;
 497
 498        /*      Value: */
 499        /*      Availability Period */
 500        /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
 501        RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
 502        p2pielen += 2;
 503
 504        /*      Availability Interval */
 505        /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
 506        RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
 507        p2pielen += 2;
 508
 509        /*  Notice of Absence ATTR */
 510        /*      Type: */
 511        /*      Length: */
 512        /*      Value: */
 513
 514        /*      Device Info ATTR */
 515        /*      Type: */
 516        p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
 517
 518        /*      Length: */
 519        /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
 520        /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
 521        /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
 522        RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
 523        p2pielen += 2;
 524
 525        /*      Value: */
 526        /*      P2P Device Address */
 527        memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
 528        p2pielen += ETH_ALEN;
 529
 530        /*      Config Method */
 531        /*      This field should be big endian. Noted by P2P specification. */
 532        /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); */
 533        RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm);
 534        p2pielen += 2;
 535
 536        /*      Primary Device Type */
 537        /*      Category ID */
 538        /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
 539        RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
 540        p2pielen += 2;
 541
 542        /*      OUI */
 543        /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
 544        RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
 545        p2pielen += 4;
 546
 547        /*      Sub Category ID */
 548        /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
 549        RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
 550        p2pielen += 2;
 551
 552        /*      Number of Secondary Device Types */
 553        p2pie[p2pielen++] = 0x00;       /*      No Secondary Device Type List */
 554
 555        /*      Device Name */
 556        /*      Type: */
 557        /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
 558        RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
 559        p2pielen += 2;
 560
 561        /*      Length: */
 562        /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
 563        RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
 564        p2pielen += 2;
 565
 566        /*      Value: */
 567        memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
 568        p2pielen += pwdinfo->device_name_len;
 569
 570        /*  Group Info ATTR */
 571        /*      Type: */
 572        /*      Length: */
 573        /*      Value: */
 574        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
 575                p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);
 576
 577        pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
 578
 579        return len;
 580}
 581
 582u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
 583{
 584        u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
 585        u32 len = 0, p2pielen = 0;
 586
 587        /*      P2P OUI */
 588        p2pielen = 0;
 589        p2pie[p2pielen++] = 0x50;
 590        p2pie[p2pielen++] = 0x6F;
 591        p2pie[p2pielen++] = 0x9A;
 592        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
 593
 594        /*      Commented by Albert 20110301 */
 595        /*      According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
 596        /*      1. P2P Capability */
 597        /*      2. Device Info */
 598        /*      3. Group ID (When joining an operating P2P Group) */
 599
 600        /*      P2P Capability ATTR */
 601        /*      Type: */
 602        p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
 603
 604        /*      Length: */
 605        /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
 606        RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
 607        p2pielen += 2;
 608
 609        /*      Value: */
 610        /*      Device Capability Bitmap, 1 byte */
 611        p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
 612
 613        /*      Group Capability Bitmap, 1 byte */
 614        if (pwdinfo->persistent_supported)
 615                p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
 616        else
 617                p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
 618
 619        /*      Device Info ATTR */
 620        /*      Type: */
 621        p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
 622
 623        /*      Length: */
 624        /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
 625        /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
 626        /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
 627        RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
 628        p2pielen += 2;
 629
 630        /*      Value: */
 631        /*      P2P Device Address */
 632        memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
 633        p2pielen += ETH_ALEN;
 634
 635        /*      Config Method */
 636        /*      This field should be big endian. Noted by P2P specification. */
 637        if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC) {
 638                /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC); */
 639                RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_PBC);
 640        } else {
 641                /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); */
 642                RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_DISPLAY);
 643        }
 644
 645        p2pielen += 2;
 646
 647        /*      Primary Device Type */
 648        /*      Category ID */
 649        /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
 650        RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
 651        p2pielen += 2;
 652
 653        /*      OUI */
 654        /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
 655        RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
 656        p2pielen += 4;
 657
 658        /*      Sub Category ID */
 659        /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
 660        RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
 661        p2pielen += 2;
 662
 663        /*      Number of Secondary Device Types */
 664        p2pie[p2pielen++] = 0x00;       /*      No Secondary Device Type List */
 665
 666        /*      Device Name */
 667        /*      Type: */
 668        /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
 669        RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
 670        p2pielen += 2;
 671
 672        /*      Length: */
 673        /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
 674        RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
 675        p2pielen += 2;
 676
 677        /*      Value: */
 678        memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
 679        p2pielen += pwdinfo->device_name_len;
 680
 681        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
 682                /*      Added by Albert 2011/05/19 */
 683                /*      In this case, the pdev_raddr is the device address of the group owner. */
 684
 685                /*      P2P Group ID ATTR */
 686                /*      Type: */
 687                p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
 688
 689                /*      Length: */
 690                /* u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + ussidlen); */
 691                RTW_PUT_LE16(p2pie + p2pielen, ETH_ALEN + ussidlen);
 692                p2pielen += 2;
 693
 694                /*      Value: */
 695                memcpy(p2pie + p2pielen, pdev_raddr, ETH_ALEN);
 696                p2pielen += ETH_ALEN;
 697
 698                memcpy(p2pie + p2pielen, pssid, ussidlen);
 699                p2pielen += ussidlen;
 700        }
 701
 702        pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
 703
 704        return len;
 705}
 706
 707u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)
 708{
 709        u8 p2pie[MAX_P2P_IE_LEN] = { 0x00 };
 710        u32 len = 0, p2pielen = 0;
 711
 712        /*      P2P OUI */
 713        p2pielen = 0;
 714        p2pie[p2pielen++] = 0x50;
 715        p2pie[p2pielen++] = 0x6F;
 716        p2pie[p2pielen++] = 0x9A;
 717        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
 718
 719        /*  According to the P2P Specification, the Association response frame should contain 2 P2P attributes */
 720        /*      1. Status */
 721        /*      2. Extended Listen Timing (optional) */
 722
 723        /*      Status ATTR */
 724        p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);
 725
 726        /*  Extended Listen Timing ATTR */
 727        /*      Type: */
 728        /*      Length: */
 729        /*      Value: */
 730
 731        pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &len);
 732
 733        return len;
 734}
 735
 736u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
 737{
 738        u8 *p;
 739        u32 ret = false;
 740        u8 *p2pie;
 741        u32     p2pielen = 0;
 742        int ssid_len = 0, rate_cnt = 0;
 743
 744        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
 745                        len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
 746
 747        if (rate_cnt <= 4) {
 748                int i, g_rate = 0;
 749
 750                for (i = 0; i < rate_cnt; i++) {
 751                        if (((*(p + 2 + i) & 0xff) != 0x02) &&
 752                            ((*(p + 2 + i) & 0xff) != 0x04) &&
 753                            ((*(p + 2 + i) & 0xff) != 0x0B) &&
 754                            ((*(p + 2 + i) & 0xff) != 0x16))
 755                                g_rate = 1;
 756                }
 757
 758                if (g_rate == 0) {
 759                        /*      There is no OFDM rate included in SupportedRates IE of this probe request frame */
 760                        /*      The driver should response this probe request. */
 761                        return ret;
 762                }
 763        } else {
 764                /*      rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */
 765                /*      We should proceed the following check for this probe request. */
 766        }
 767
 768        /*      Added comments by Albert 20100906 */
 769        /*      There are several items we should check here. */
 770        /*      1. This probe request frame must contain the P2P IE. (Done) */
 771        /*      2. This probe request frame must contain the wildcard SSID. (Done) */
 772        /*      3. Wildcard BSSID. (Todo) */
 773        /*      4. Destination Address. (Done in mgt_dispatcher function) */
 774        /*      5. Requested Device Type in WSC IE. (Todo) */
 775        /*      6. Device ID attribute in P2P IE. (Todo) */
 776
 777        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
 778                        len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
 779
 780        ssid_len &= 0xff;       /*      Just last 1 byte is valid for ssid len of the probe request */
 781        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
 782                p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_, NULL, &p2pielen);
 783                if (p2pie) {
 784                        if (p && !memcmp((void *)(p + 2), (void *)pwdinfo->p2p_wildcard_ssid, 7)) {
 785                                /* todo: */
 786                                /* Check Requested Device Type attributes in WSC IE. */
 787                                /* Check Device ID attribute in P2P IE */
 788
 789                                ret = true;
 790                        } else if (p && ssid_len == 0) {
 791                                ret = true;
 792                        }
 793                } else {
 794                        /* non -p2p device */
 795                }
 796        }
 797
 798        return ret;
 799}
 800
 801u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
 802{
 803        u8 status_code = P2P_STATUS_SUCCESS;
 804        u8 *pbuf, *pattr_content = NULL;
 805        u32 attr_contentlen = 0;
 806        u16 cap_attr = 0;
 807        unsigned short  frame_type, ie_offset = 0;
 808        u8 *ies;
 809        u32 ies_len;
 810        u8 *p2p_ie;
 811        u32     p2p_ielen = 0;
 812        __be16 be_tmp;
 813        __le16 le_tmp;
 814
 815        if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
 816                return P2P_STATUS_FAIL_REQUEST_UNABLE;
 817
 818        frame_type = GetFrameSubType(pframe);
 819        if (frame_type == WIFI_ASSOCREQ)
 820                ie_offset = _ASOCREQ_IE_OFFSET_;
 821        else /*  WIFI_REASSOCREQ */
 822                ie_offset = _REASOCREQ_IE_OFFSET_;
 823
 824        ies = pframe + WLAN_HDR_A3_LEN + ie_offset;
 825        ies_len = len - WLAN_HDR_A3_LEN - ie_offset;
 826
 827        p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
 828
 829        if (!p2p_ie) {
 830                DBG_88E("[%s] P2P IE not Found!!\n", __func__);
 831                status_code =  P2P_STATUS_FAIL_INVALID_PARAM;
 832        } else {
 833                DBG_88E("[%s] P2P IE Found!!\n", __func__);
 834        }
 835
 836        while (p2p_ie) {
 837                /* Check P2P Capability ATTR */
 838                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&le_tmp, (uint *)&attr_contentlen)) {
 839                        DBG_88E("[%s] Got P2P Capability Attr!!\n", __func__);
 840                        cap_attr = le16_to_cpu(le_tmp);
 841                        psta->dev_cap = cap_attr & 0xff;
 842                }
 843
 844                /* Check Extended Listen Timing ATTR */
 845
 846                /* Check P2P Device Info ATTR */
 847                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint *)&attr_contentlen)) {
 848                        DBG_88E("[%s] Got P2P DEVICE INFO Attr!!\n", __func__);
 849                        pattr_content = kzalloc(attr_contentlen, GFP_KERNEL);
 850                        pbuf = pattr_content;
 851                        if (pattr_content) {
 852                                u8 num_of_secdev_type;
 853                                u16 dev_name_len;
 854
 855                                rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, pattr_content, (uint *)&attr_contentlen);
 856
 857                                memcpy(psta->dev_addr,  pattr_content, ETH_ALEN);/* P2P Device Address */
 858
 859                                pattr_content += ETH_ALEN;
 860
 861                                memcpy(&be_tmp, pattr_content, 2);/* Config Methods */
 862                                psta->config_methods = be16_to_cpu(be_tmp);
 863
 864                                pattr_content += 2;
 865
 866                                memcpy(psta->primary_dev_type, pattr_content, 8);
 867
 868                                pattr_content += 8;
 869
 870                                num_of_secdev_type = *pattr_content;
 871                                pattr_content += 1;
 872
 873                                if (num_of_secdev_type == 0) {
 874                                        psta->num_of_secdev_type = 0;
 875                                } else {
 876                                        u32 len;
 877
 878                                        psta->num_of_secdev_type = num_of_secdev_type;
 879
 880                                        len = (sizeof(psta->secdev_types_list) < (num_of_secdev_type * 8)) ?
 881                                              (sizeof(psta->secdev_types_list)) : (num_of_secdev_type * 8);
 882
 883                                        memcpy(psta->secdev_types_list, pattr_content, len);
 884
 885                                        pattr_content += (num_of_secdev_type * 8);
 886                                }
 887
 888                                psta->dev_name_len = 0;
 889                                if (WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(__be16 *)pattr_content)) {
 890                                        dev_name_len = be16_to_cpu(*(__be16 *)(pattr_content + 2));
 891
 892                                        psta->dev_name_len = (sizeof(psta->dev_name) < dev_name_len) ? sizeof(psta->dev_name) : dev_name_len;
 893
 894                                        memcpy(psta->dev_name, pattr_content + 4, psta->dev_name_len);
 895                                }
 896                                kfree(pbuf);
 897                        }
 898                }
 899
 900                /* Get the next P2P IE */
 901                p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
 902        }
 903
 904        return status_code;
 905}
 906
 907u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
 908{
 909        u8 *frame_body;
 910        u8 status, dialogToken;
 911        struct sta_info *psta = NULL;
 912        struct adapter *padapter = pwdinfo->padapter;
 913        struct sta_priv *pstapriv = &padapter->stapriv;
 914        u8 *p2p_ie;
 915        u32     p2p_ielen = 0;
 916
 917        frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
 918
 919        dialogToken = frame_body[7];
 920        status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
 921
 922        p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
 923        if (p2p_ie) {
 924                u8 groupid[38] = { 0x00 };
 925                u8 dev_addr[ETH_ALEN] = { 0x00 };
 926                u32     attr_contentlen = 0;
 927
 928                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
 929                        if (!memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
 930                            !memcmp(pwdinfo->p2p_group_ssid, groupid + ETH_ALEN, pwdinfo->p2p_group_ssid_len)) {
 931                                attr_contentlen = 0;
 932                                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_ID, dev_addr, &attr_contentlen)) {
 933                                        struct list_head *phead, *plist;
 934
 935                                        spin_lock_bh(&pstapriv->asoc_list_lock);
 936                                        phead = &pstapriv->asoc_list;
 937                                        plist = phead->next;
 938
 939                                        /* look up sta asoc_queue */
 940                                        while (phead != plist) {
 941                                                psta = container_of(plist, struct sta_info, asoc_list);
 942
 943                                                plist = plist->next;
 944
 945                                                if (psta->is_p2p_device && (psta->dev_cap & P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
 946                                                    !memcmp(psta->dev_addr, dev_addr, ETH_ALEN)) {
 947                                                        /* issue GO Discoverability Request */
 948                                                        issue_group_disc_req(pwdinfo, psta->hwaddr);
 949                                                        status = P2P_STATUS_SUCCESS;
 950                                                        break;
 951                                                } else {
 952                                                        status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
 953                                                }
 954                                        }
 955                                        spin_unlock_bh(&pstapriv->asoc_list_lock);
 956                                } else {
 957                                        status = P2P_STATUS_FAIL_INVALID_PARAM;
 958                                }
 959                        } else {
 960                                status = P2P_STATUS_FAIL_INVALID_PARAM;
 961                        }
 962                }
 963        }
 964
 965        /* issue Device Discoverability Response */
 966        issue_p2p_devdisc_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
 967
 968        return (status == P2P_STATUS_SUCCESS) ? true : false;
 969}
 970
 971u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
 972{
 973        return true;
 974}
 975
 976u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo,  u8 *pframe, uint len)
 977{
 978        u8 *frame_body;
 979        u8 *wpsie;
 980        uint    wps_ielen = 0, attr_contentlen = 0;
 981        u16     uconfig_method = 0;
 982        __be16 be_tmp;
 983
 984        frame_body = (pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
 985
 986        wpsie = rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
 987        if (wpsie) {
 988                if (rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD, (u8 *)&be_tmp, &attr_contentlen)) {
 989                        uconfig_method = be16_to_cpu(be_tmp);
 990                        switch (uconfig_method) {
 991                        case WPS_CM_DISPLYA:
 992                                memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
 993                                break;
 994                        case WPS_CM_LABEL:
 995                                memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "lab", 3);
 996                                break;
 997                        case WPS_CM_PUSH_BUTTON:
 998                                memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
 999                                break;
1000                        case WPS_CM_KEYPAD:
1001                                memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
1002                                break;
1003                        }
1004                        issue_p2p_provision_resp(pwdinfo, GetAddr2Ptr(pframe), frame_body, uconfig_method);
1005                }
1006        }
1007        DBG_88E("[%s] config method = %s\n", __func__, pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
1008        return true;
1009}
1010
1011u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo,  u8 *pframe)
1012{
1013        return true;
1014}
1015
1016static u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
1017{
1018        u8 i = 0, j = 0;
1019        u8 temp = 0;
1020        u8 ch_no = 0;
1021        ch_content += 3;
1022        ch_cnt -= 3;
1023
1024        while (ch_cnt > 0) {
1025                ch_content += 1;
1026                ch_cnt -= 1;
1027                temp = *ch_content;
1028                for (i = 0 ; i < temp ; i++, j++)
1029                        peer_ch_list[j] = *(ch_content + 1 + i);
1030                ch_content += (temp + 1);
1031                ch_cnt -= (temp + 1);
1032                ch_no += temp;
1033        }
1034
1035        return ch_no;
1036}
1037
1038static u8 rtw_p2p_ch_inclusion(struct mlme_ext_priv *pmlmeext, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
1039{
1040        int     i = 0, j = 0, temp = 0;
1041        u8 ch_no = 0;
1042
1043        for (i = 0; i < peer_ch_num; i++) {
1044                for (j = temp; j < pmlmeext->max_chan_nums; j++) {
1045                        if (*(peer_ch_list + i) == pmlmeext->channel_set[j].ChannelNum) {
1046                                ch_list_inclusioned[ch_no++] = *(peer_ch_list + i);
1047                                temp = j;
1048                                break;
1049                        }
1050                }
1051        }
1052
1053        return ch_no;
1054}
1055
1056u8 process_p2p_group_negotation_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
1057{
1058        struct adapter *padapter = pwdinfo->padapter;
1059        u8      result = P2P_STATUS_SUCCESS;
1060        u32     p2p_ielen = 0, wps_ielen = 0;
1061        u8 *ies;
1062        u32 ies_len;
1063        u8 *p2p_ie;
1064        u8 *wpsie;
1065        u16             wps_devicepassword_id = 0x0000;
1066        uint    wps_devicepassword_id_len = 0;
1067        __be16 be_tmp;
1068
1069        wpsie = rtw_get_wps_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen);
1070        if (wpsie) {
1071                /*      Commented by Kurt 20120113 */
1072                /*      If some device wants to do p2p handshake without sending prov_disc_req */
1073                /*      We have to get peer_req_cm from here. */
1074                if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
1075                        rtw_get_wps_attr_content(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len);
1076                        wps_devicepassword_id = be16_to_cpu(be_tmp);
1077
1078                        if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
1079                                memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
1080                        else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
1081                                memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
1082                        else
1083                                memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
1084                }
1085        } else {
1086                DBG_88E("[%s] WPS IE not Found!!\n", __func__);
1087                result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
1088                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
1089                return result;
1090        }
1091
1092        if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) {
1093                result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
1094                rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
1095                return result;
1096        }
1097
1098        ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
1099        ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
1100
1101        p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
1102
1103        if (!p2p_ie) {
1104                DBG_88E("[%s] P2P IE not Found!!\n", __func__);
1105                result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
1106                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
1107        }
1108
1109        while (p2p_ie) {
1110                u8      attr_content = 0x00;
1111                u32     attr_contentlen = 0;
1112                u8      ch_content[50] = { 0x00 };
1113                uint    ch_cnt = 0;
1114                u8      peer_ch_list[50] = { 0x00 };
1115                u8      peer_ch_num = 0;
1116                u8      ch_list_inclusioned[50] = { 0x00 };
1117                u8      ch_num_inclusioned = 0;
1118
1119                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
1120
1121                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen)) {
1122                        DBG_88E("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
1123                        pwdinfo->peer_intent = attr_content;    /*      include both intent and tie breaker values. */
1124
1125                        if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
1126                                /*      Try to match the tie breaker value */
1127                                if (pwdinfo->intent == P2P_MAX_INTENT) {
1128                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
1129                                        result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
1130                                } else {
1131                                        if (attr_content & 0x01)
1132                                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
1133                                        else
1134                                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
1135                                }
1136                        } else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) {
1137                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
1138                        } else {
1139                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
1140                        }
1141
1142                        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1143                                /*      Store the group id information. */
1144                                memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
1145                                memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
1146                        }
1147                }
1148
1149                attr_contentlen = 0;
1150                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
1151                        if (attr_contentlen != ETH_ALEN)
1152                                memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
1153                }
1154
1155                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt)) {
1156                        peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
1157                        ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
1158
1159                        if (ch_num_inclusioned == 0) {
1160                                DBG_88E("[%s] No common channel in channel list!\n", __func__);
1161                                result = P2P_STATUS_FAIL_NO_COMMON_CH;
1162                                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
1163                                break;
1164                        }
1165
1166                        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1167                                if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
1168                                    ch_list_inclusioned, ch_num_inclusioned)) {
1169                                        u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
1170                                        attr_contentlen = 0;
1171
1172                                        if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
1173                                                peer_operating_ch = operatingch_info[4];
1174
1175                                        if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
1176                                                               ch_list_inclusioned, ch_num_inclusioned)) {
1177                                                /**
1178                                                 *      Change our operating channel as peer's for compatibility.
1179                                                 */
1180                                                pwdinfo->operating_channel = peer_operating_ch;
1181                                                DBG_88E("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
1182                                        } else {
1183                                                /*  Take first channel of ch_list_inclusioned as operating channel */
1184                                                pwdinfo->operating_channel = ch_list_inclusioned[0];
1185                                                DBG_88E("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
1186                                        }
1187                                }
1188                        }
1189                }
1190
1191                /* Get the next P2P IE */
1192                p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
1193        }
1194        return result;
1195}
1196
1197u8 process_p2p_group_negotation_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
1198{
1199        struct adapter *padapter = pwdinfo->padapter;
1200        u8      result = P2P_STATUS_SUCCESS;
1201        u32     p2p_ielen, wps_ielen;
1202        u8 *ies;
1203        u32 ies_len;
1204        u8 *p2p_ie;
1205
1206        ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
1207        ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
1208
1209        /*      Be able to know which one is the P2P GO and which one is P2P client. */
1210
1211        if (rtw_get_wps_ie(ies, ies_len, NULL, &wps_ielen)) {
1212        } else {
1213                DBG_88E("[%s] WPS IE not Found!!\n", __func__);
1214                result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
1215                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
1216        }
1217
1218        p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
1219        if (!p2p_ie) {
1220                rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
1221                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
1222                result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
1223        } else {
1224                u8      attr_content = 0x00;
1225                u32     attr_contentlen = 0;
1226                u8      operatingch_info[5] = { 0x00 };
1227                u8      groupid[38];
1228                u8      peer_ch_list[50] = { 0x00 };
1229                u8      peer_ch_num = 0;
1230                u8      ch_list_inclusioned[50] = { 0x00 };
1231                u8      ch_num_inclusioned = 0;
1232
1233                while (p2p_ie) {        /*      Found the P2P IE. */
1234                        rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
1235                        if (attr_contentlen == 1) {
1236                                DBG_88E("[%s] Status = %d\n", __func__, attr_content);
1237                                if (attr_content == P2P_STATUS_SUCCESS) {
1238                                        /*      Do nothing. */
1239                                } else {
1240                                        if (P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content) {
1241                                                rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
1242                                        } else {
1243                                                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
1244                                        }
1245                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
1246                                        result = attr_content;
1247                                        break;
1248                                }
1249                        }
1250
1251                        /*      Try to get the peer's interface address */
1252                        attr_contentlen = 0;
1253                        if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen)) {
1254                                if (attr_contentlen != ETH_ALEN)
1255                                        memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
1256                        }
1257
1258                        /*      Try to get the peer's intent and tie breaker value. */
1259                        attr_content = 0x00;
1260                        attr_contentlen = 0;
1261                        if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen)) {
1262                                DBG_88E("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
1263                                pwdinfo->peer_intent = attr_content;    /*      include both intent and tie breaker values. */
1264
1265                                if (pwdinfo->intent == (pwdinfo->peer_intent >> 1)) {
1266                                        /*      Try to match the tie breaker value */
1267                                        if (pwdinfo->intent == P2P_MAX_INTENT) {
1268                                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
1269                                                result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
1270                                                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
1271                                        } else {
1272                                                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
1273                                                rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
1274                                                if (attr_content & 0x01)
1275                                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
1276                                                else
1277                                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
1278                                        }
1279                                } else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1)) {
1280                                        rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
1281                                        rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
1282                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
1283                                } else {
1284                                        rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
1285                                        rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
1286                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
1287                                }
1288
1289                                if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1290                                        /*      Store the group id information. */
1291                                        memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
1292                                        memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
1293                                }
1294                        }
1295
1296                        /*      Try to get the operation channel information */
1297
1298                        attr_contentlen = 0;
1299                        if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
1300                                DBG_88E("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
1301                                pwdinfo->peer_operating_ch = operatingch_info[4];
1302                        }
1303
1304                        /*      Try to get the channel list information */
1305                        if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len)) {
1306                                DBG_88E("[%s] channel list attribute found, len = %d\n", __func__,  pwdinfo->channel_list_attr_len);
1307
1308                                peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
1309                                ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
1310
1311                                if (ch_num_inclusioned == 0) {
1312                                        DBG_88E("[%s] No common channel in channel list!\n", __func__);
1313                                        result = P2P_STATUS_FAIL_NO_COMMON_CH;
1314                                        rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
1315                                        break;
1316                                }
1317
1318                                if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1319                                        if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
1320                                            ch_list_inclusioned, ch_num_inclusioned)) {
1321                                                u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
1322                                                attr_contentlen = 0;
1323
1324                                                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
1325                                                        peer_operating_ch = operatingch_info[4];
1326
1327                                                if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
1328                                                    ch_list_inclusioned, ch_num_inclusioned)) {
1329                                                        /**
1330                                                         *      Change our operating channel as peer's for compatibility.
1331                                                         */
1332                                                        pwdinfo->operating_channel = peer_operating_ch;
1333                                                        DBG_88E("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
1334                                                } else {
1335                                                        /*  Take first channel of ch_list_inclusioned as operating channel */
1336                                                        pwdinfo->operating_channel = ch_list_inclusioned[0];
1337                                                        DBG_88E("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
1338                                                }
1339                                        }
1340                                }
1341                        } else {
1342                                DBG_88E("[%s] channel list attribute not found!\n", __func__);
1343                        }
1344
1345                        /*      Try to get the group id information if peer is GO */
1346                        attr_contentlen = 0;
1347                        memset(groupid, 0x00, 38);
1348                        if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
1349                                memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
1350                                memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
1351                        }
1352
1353                        /* Get the next P2P IE */
1354                        p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
1355                }
1356        }
1357        return result;
1358}
1359
1360u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
1361{
1362        u8 *ies;
1363        u32 ies_len;
1364        u8 *p2p_ie;
1365        u32     p2p_ielen = 0;
1366        u8      result = P2P_STATUS_SUCCESS;
1367        ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
1368        ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
1369
1370        p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
1371        while (p2p_ie) {        /*      Found the P2P IE. */
1372                u8      attr_content = 0x00, operatingch_info[5] = { 0x00 };
1373                u8      groupid[38] = { 0x00 };
1374                u32     attr_contentlen = 0;
1375
1376                pwdinfo->negotiation_dialog_token = 1;
1377                rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
1378                if (attr_contentlen == 1) {
1379                        DBG_88E("[%s] Status = %d\n", __func__, attr_content);
1380                        result = attr_content;
1381
1382                        if (attr_content == P2P_STATUS_SUCCESS) {
1383                                u8      bcancelled = 0;
1384
1385                                _cancel_timer(&pwdinfo->restore_p2p_state_timer, &bcancelled);
1386
1387                                /*      Commented by Albert 20100911 */
1388                                /*      Todo: Need to handle the case which both Intents are the same. */
1389                                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
1390                                rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
1391                                if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1)) {
1392                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
1393                                } else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1)) {
1394                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
1395                                } else {
1396                                        /*      Have to compare the Tie Breaker */
1397                                        if (pwdinfo->peer_intent & 0x01)
1398                                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
1399                                        else
1400                                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
1401                                }
1402                        } else {
1403                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
1404                                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
1405                                break;
1406                        }
1407                }
1408
1409                /*      Try to get the group id information */
1410                attr_contentlen = 0;
1411                memset(groupid, 0x00, 38);
1412                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen)) {
1413                        DBG_88E("[%s] Ssid = %s, ssidlen = %zu\n", __func__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]));
1414                        memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
1415                        memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
1416                }
1417
1418                attr_contentlen = 0;
1419                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
1420                        DBG_88E("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
1421                        pwdinfo->peer_operating_ch = operatingch_info[4];
1422                }
1423
1424                /* Get the next P2P IE */
1425                p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
1426        }
1427        return result;
1428}
1429
1430u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
1431{
1432        u8 *frame_body;
1433        u8 dialogToken = 0;
1434        u8 status = P2P_STATUS_SUCCESS;
1435
1436        frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
1437
1438        dialogToken = frame_body[6];
1439
1440        /* todo: check NoA attribute */
1441
1442        issue_p2p_presence_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
1443
1444        return true;
1445}
1446
1447static void find_phase_handler(struct adapter *padapter)
1448{
1449        struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
1450        struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
1451        struct ndis_802_11_ssid ssid;
1452
1453        memset((unsigned char *)&ssid, 0, sizeof(struct ndis_802_11_ssid));
1454        memcpy(ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
1455        ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
1456
1457        rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
1458
1459        spin_lock_bh(&pmlmepriv->lock);
1460        spin_unlock_bh(&pmlmepriv->lock);
1461
1462}
1463
1464void p2p_concurrent_handler(struct adapter *padapter);
1465
1466static void restore_p2p_state_handler(struct adapter *padapter)
1467{
1468        struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
1469
1470        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
1471                rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
1472        rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
1473
1474        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
1475                /*      In the P2P client mode, the driver should not switch back to its listen channel */
1476                /*      because this P2P client should stay at the operating channel of P2P GO. */
1477                set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
1478        }
1479
1480}
1481
1482static void pre_tx_invitereq_handler(struct adapter *padapter)
1483{
1484        struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
1485        u8      val8 = 1;
1486
1487        set_channel_bwmode(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
1488        SetHwReg8188EU(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
1489        issue_probereq_p2p(padapter, NULL);
1490        _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
1491
1492}
1493
1494static void pre_tx_provdisc_handler(struct adapter *padapter)
1495{
1496        struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
1497        u8      val8 = 1;
1498
1499        set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
1500        SetHwReg8188EU(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
1501        issue_probereq_p2p(padapter, NULL);
1502        _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
1503
1504}
1505
1506static void pre_tx_negoreq_handler(struct adapter *padapter)
1507{
1508        struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
1509        u8      val8 = 1;
1510
1511        set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
1512        SetHwReg8188EU(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
1513        issue_probereq_p2p(padapter, NULL);
1514        _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
1515
1516}
1517
1518void p2p_protocol_wk_hdl(struct adapter *padapter, int intCmdType)
1519{
1520
1521        switch (intCmdType) {
1522        case P2P_FIND_PHASE_WK:
1523                find_phase_handler(padapter);
1524                break;
1525        case P2P_RESTORE_STATE_WK:
1526                restore_p2p_state_handler(padapter);
1527                break;
1528        case P2P_PRE_TX_PROVDISC_PROCESS_WK:
1529                pre_tx_provdisc_handler(padapter);
1530                break;
1531        case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
1532                pre_tx_invitereq_handler(padapter);
1533                break;
1534        case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
1535                pre_tx_negoreq_handler(padapter);
1536                break;
1537        }
1538
1539}
1540
1541void process_p2p_ps_ie(struct adapter *padapter, u8 *IEs, u32 IELength)
1542{
1543        u8 *ies;
1544        u32 ies_len;
1545        u8 *p2p_ie;
1546        u32     p2p_ielen = 0;
1547        u8      noa_attr[MAX_P2P_IE_LEN] = { 0x00 };/*  NoA length should be n*(13) + 2 */
1548        u32     attr_contentlen = 0;
1549
1550        struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
1551        u8      find_p2p = false, find_p2p_ps = false;
1552        u8      noa_offset, noa_num, noa_index;
1553
1554        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1555                return;
1556        if (IELength <= _BEACON_IE_OFFSET_)
1557                return;
1558
1559        ies = IEs + _BEACON_IE_OFFSET_;
1560        ies_len = IELength - _BEACON_IE_OFFSET_;
1561
1562        p2p_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &p2p_ielen);
1563
1564        while (p2p_ie) {
1565                find_p2p = true;
1566                /*  Get Notice of Absence IE. */
1567                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, noa_attr, &attr_contentlen)) {
1568                        find_p2p_ps = true;
1569                        noa_index = noa_attr[0];
1570
1571                        if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
1572                            (noa_index != pwdinfo->noa_index)) { /*  if index change, driver should reconfigure related setting. */
1573                                pwdinfo->noa_index = noa_index;
1574                                pwdinfo->opp_ps = noa_attr[1] >> 7;
1575                                pwdinfo->ctwindow = noa_attr[1] & 0x7F;
1576
1577                                noa_offset = 2;
1578                                noa_num = 0;
1579                                /*  NoA length should be n*(13) + 2 */
1580                                if (attr_contentlen > 2) {
1581                                        while (noa_offset < attr_contentlen) {
1582                                                /* memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */
1583                                                pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
1584                                                noa_offset += 1;
1585
1586                                                memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
1587                                                noa_offset += 4;
1588
1589                                                memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
1590                                                noa_offset += 4;
1591
1592                                                memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
1593                                                noa_offset += 4;
1594
1595                                                noa_num++;
1596                                        }
1597                                }
1598                                pwdinfo->noa_num = noa_num;
1599
1600                                if (pwdinfo->opp_ps == 1) {
1601                                        pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
1602                                        /*  driver should wait LPS for entering CTWindow */
1603                                        if (padapter->pwrctrlpriv.bFwCurrentInPSMode)
1604                                                p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
1605                                } else if (pwdinfo->noa_num > 0) {
1606                                        pwdinfo->p2p_ps_mode = P2P_PS_NOA;
1607                                        p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
1608                                } else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
1609                                        p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
1610                                }
1611                        }
1612
1613                        break; /*  find target, just break. */
1614                }
1615
1616                /* Get the next P2P IE */
1617                p2p_ie = rtw_get_p2p_ie(p2p_ie + p2p_ielen, ies_len - (p2p_ie - ies + p2p_ielen), NULL, &p2p_ielen);
1618        }
1619
1620        if (find_p2p) {
1621                if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && !find_p2p_ps)
1622                        p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
1623        }
1624
1625}
1626
1627void p2p_ps_wk_hdl(struct adapter *padapter, u8 p2p_ps_state)
1628{
1629        struct pwrctrl_priv             *pwrpriv = &padapter->pwrctrlpriv;
1630        struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
1631
1632        /*  Pre action for p2p state */
1633        switch (p2p_ps_state) {
1634        case P2P_PS_DISABLE:
1635                pwdinfo->p2p_ps_state = p2p_ps_state;
1636
1637                SetHwReg8188EU(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
1638
1639                pwdinfo->noa_index = 0;
1640                pwdinfo->ctwindow = 0;
1641                pwdinfo->opp_ps = 0;
1642                pwdinfo->noa_num = 0;
1643                pwdinfo->p2p_ps_mode = P2P_PS_NONE;
1644                if (padapter->pwrctrlpriv.bFwCurrentInPSMode) {
1645                        if (pwrpriv->smart_ps == 0) {
1646                                pwrpriv->smart_ps = 2;
1647                                SetHwReg8188EU(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&padapter->pwrctrlpriv.pwr_mode));
1648                        }
1649                }
1650                break;
1651        case P2P_PS_ENABLE:
1652                if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
1653                        pwdinfo->p2p_ps_state = p2p_ps_state;
1654
1655                        if (pwdinfo->ctwindow > 0) {
1656                                if (pwrpriv->smart_ps != 0) {
1657                                        pwrpriv->smart_ps = 0;
1658                                        DBG_88E("%s(): Enter CTW, change SmartPS\n", __func__);
1659                                        SetHwReg8188EU(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&padapter->pwrctrlpriv.pwr_mode));
1660                                }
1661                        }
1662                        SetHwReg8188EU(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
1663                }
1664                break;
1665        case P2P_PS_SCAN:
1666        case P2P_PS_SCAN_DONE:
1667        case P2P_PS_ALLSTASLEEP:
1668                if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
1669                        pwdinfo->p2p_ps_state = p2p_ps_state;
1670                        SetHwReg8188EU(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
1671                }
1672                break;
1673        default:
1674                break;
1675        }
1676
1677}
1678
1679u8 p2p_ps_wk_cmd(struct adapter *padapter, u8 p2p_ps_state, u8 enqueue)
1680{
1681        struct cmd_obj  *ph2c;
1682        struct drvextra_cmd_parm        *pdrvextra_cmd_parm;
1683        struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
1684        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1685        u8      res = _SUCCESS;
1686
1687        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1688                return res;
1689
1690        if (enqueue) {
1691                ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1692                if (!ph2c) {
1693                        res = _FAIL;
1694                        goto exit;
1695                }
1696
1697                pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
1698                if (!pdrvextra_cmd_parm) {
1699                        kfree(ph2c);
1700                        res = _FAIL;
1701                        goto exit;
1702                }
1703
1704                pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
1705                pdrvextra_cmd_parm->type_size = p2p_ps_state;
1706                pdrvextra_cmd_parm->pbuf = NULL;
1707
1708                init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1709
1710                res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1711        } else {
1712                p2p_ps_wk_hdl(padapter, p2p_ps_state);
1713        }
1714
1715exit:
1716
1717        return res;
1718}
1719
1720static void reset_ch_sitesurvey_timer_process(struct timer_list *t)
1721{
1722        struct adapter *adapter = from_timer(adapter, t, pwrctrlpriv.pwr_state_check_timer);
1723        struct  wifidirect_info         *pwdinfo = &adapter->wdinfo;
1724
1725        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1726                return;
1727
1728        DBG_88E("[%s] In\n", __func__);
1729        /*      Reset the operation channel information */
1730        pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
1731        pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
1732}
1733
1734static void reset_ch_sitesurvey_timer_process2(struct timer_list *t)
1735{
1736        struct adapter *adapter = from_timer(adapter, t, pwrctrlpriv.pwr_state_check_timer);
1737        struct  wifidirect_info         *pwdinfo = &adapter->wdinfo;
1738
1739        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1740                return;
1741
1742        DBG_88E("[%s] In\n", __func__);
1743        /*      Reset the operation channel information */
1744        pwdinfo->p2p_info.operation_ch[0] = 0;
1745        pwdinfo->p2p_info.scan_op_ch_only = 0;
1746}
1747
1748static void restore_p2p_state_timer_process(struct timer_list *t)
1749{
1750        struct adapter *adapter = from_timer(adapter, t, wdinfo.restore_p2p_state_timer);
1751        struct  wifidirect_info         *pwdinfo = &adapter->wdinfo;
1752
1753        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1754                return;
1755
1756        p2p_protocol_wk_cmd(adapter, P2P_RESTORE_STATE_WK);
1757}
1758
1759static void pre_tx_scan_timer_process(struct timer_list *t)
1760{
1761        struct adapter *adapter = from_timer(adapter, t, wdinfo.pre_tx_scan_timer);
1762        struct  wifidirect_info *pwdinfo = &adapter->wdinfo;
1763        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1764
1765        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1766                return;
1767
1768        spin_lock_bh(&pmlmepriv->lock);
1769
1770        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
1771                if (pwdinfo->tx_prov_disc_info.benable) {       /*      the provision discovery request frame is trigger to send or not */
1772                        p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK);
1773                        /* issue_probereq_p2p(adapter, NULL); */
1774                        /* _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); */
1775                }
1776        } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
1777                if (pwdinfo->nego_req_info.benable)
1778                        p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK);
1779        } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
1780                if (pwdinfo->invitereq_info.benable)
1781                        p2p_protocol_wk_cmd(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK);
1782        } else {
1783                DBG_88E("[%s] p2p_state is %d, ignore!!\n", __func__, rtw_p2p_state(pwdinfo));
1784        }
1785
1786        spin_unlock_bh(&pmlmepriv->lock);
1787}
1788
1789static void find_phase_timer_process(struct timer_list *t)
1790{
1791        struct adapter *adapter = from_timer(adapter, t, wdinfo.find_phase_timer);
1792        struct  wifidirect_info         *pwdinfo = &adapter->wdinfo;
1793
1794        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1795                return;
1796
1797        adapter->wdinfo.find_phase_state_exchange_cnt++;
1798
1799        p2p_protocol_wk_cmd(adapter, P2P_FIND_PHASE_WK);
1800}
1801
1802void reset_global_wifidirect_info(struct adapter *padapter)
1803{
1804        struct wifidirect_info  *pwdinfo;
1805
1806        pwdinfo = &padapter->wdinfo;
1807        pwdinfo->persistent_supported = 0;
1808        pwdinfo->session_available = true;
1809        pwdinfo->wfd_tdls_enable = 0;
1810        pwdinfo->wfd_tdls_weaksec = 0;
1811}
1812
1813void rtw_init_wifidirect_timers(struct adapter *padapter)
1814{
1815        struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1816
1817        timer_setup(&pwdinfo->find_phase_timer, find_phase_timer_process, 0);
1818        timer_setup(&pwdinfo->restore_p2p_state_timer, restore_p2p_state_timer_process, 0);
1819        timer_setup(&pwdinfo->pre_tx_scan_timer, pre_tx_scan_timer_process, 0);
1820        timer_setup(&pwdinfo->reset_ch_sitesurvey, reset_ch_sitesurvey_timer_process, 0);
1821        timer_setup(&pwdinfo->reset_ch_sitesurvey2, reset_ch_sitesurvey_timer_process2, 0);
1822}
1823
1824void rtw_init_wifidirect_addrs(struct adapter *padapter, u8 *dev_addr, u8 *iface_addr)
1825{
1826        struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1827
1828        /*init device&interface address */
1829        if (dev_addr)
1830                memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
1831        if (iface_addr)
1832                memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
1833}
1834
1835void init_wifidirect_info(struct adapter *padapter, enum P2P_ROLE role)
1836{
1837        struct wifidirect_info  *pwdinfo;
1838
1839        pwdinfo = &padapter->wdinfo;
1840        pwdinfo->padapter = padapter;
1841
1842        /*      1, 6, 11 are the social channel defined in the WiFi Direct specification. */
1843        pwdinfo->social_chan[0] = 1;
1844        pwdinfo->social_chan[1] = 6;
1845        pwdinfo->social_chan[2] = 11;
1846        pwdinfo->social_chan[3] = 0;    /*      channel 0 for scanning ending in site survey function. */
1847
1848        /*      Use the channel 11 as the listen channel */
1849        pwdinfo->listen_channel = 11;
1850
1851        if (role == P2P_ROLE_DEVICE) {
1852                rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
1853                rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
1854                pwdinfo->intent = 1;
1855                rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
1856        } else if (role == P2P_ROLE_CLIENT) {
1857                rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
1858                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
1859                pwdinfo->intent = 1;
1860                rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
1861        } else if (role == P2P_ROLE_GO) {
1862                rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
1863                rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
1864                pwdinfo->intent = 15;
1865                rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
1866        }
1867
1868/*      Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
1869        pwdinfo->support_rate[0] = 0x8c;        /*      6(B) */
1870        pwdinfo->support_rate[1] = 0x92;        /*      9(B) */
1871        pwdinfo->support_rate[2] = 0x18;        /*      12 */
1872        pwdinfo->support_rate[3] = 0x24;        /*      18 */
1873        pwdinfo->support_rate[4] = 0x30;        /*      24 */
1874        pwdinfo->support_rate[5] = 0x48;        /*      36 */
1875        pwdinfo->support_rate[6] = 0x60;        /*      48 */
1876        pwdinfo->support_rate[7] = 0x6c;        /*      54 */
1877
1878        memcpy(pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);
1879
1880        memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
1881        pwdinfo->device_name_len = 0;
1882
1883        memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info));
1884        pwdinfo->invitereq_info.token = 3;      /*      Token used for P2P invitation request frame. */
1885
1886        memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info));
1887        pwdinfo->inviteresp_info.token = 0;
1888
1889        pwdinfo->profileindex = 0;
1890        memset(&pwdinfo->profileinfo[0], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
1891
1892        rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
1893
1894        pwdinfo->listen_dwell = (u8)((jiffies % 3) + 1);
1895
1896        memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info));
1897        pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
1898
1899        memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
1900
1901        pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
1902        pwdinfo->negotiation_dialog_token = 1;
1903
1904        memset(pwdinfo->nego_ssid, 0x00, WLAN_SSID_MAXLEN);
1905        pwdinfo->nego_ssidlen = 0;
1906
1907        pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
1908        pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
1909        pwdinfo->channel_list_attr_len = 0;
1910        memset(pwdinfo->channel_list_attr, 0x00, 100);
1911
1912        memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4);
1913        memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3);
1914        memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
1915        pwdinfo->wfd_tdls_enable = 0;
1916        memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
1917        memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN);
1918
1919        pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
1920        pwdinfo->rx_invitereq_info.operation_ch[1] = 0; /*      Used to indicate the scan end in site survey function */
1921        pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
1922        pwdinfo->p2p_info.operation_ch[0] = 0;
1923        pwdinfo->p2p_info.operation_ch[1] = 0;                  /*      Used to indicate the scan end in site survey function */
1924        pwdinfo->p2p_info.scan_op_ch_only = 0;
1925}
1926
1927int rtw_p2p_enable(struct adapter *padapter, enum P2P_ROLE role)
1928{
1929        int ret = _SUCCESS;
1930        struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1931
1932        if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT || role == P2P_ROLE_GO) {
1933                /* leave IPS/Autosuspend */
1934                if (_FAIL == rtw_pwr_wakeup(padapter)) {
1935                        ret = _FAIL;
1936                        goto exit;
1937                }
1938
1939                /*      Added by Albert 2011/03/22 */
1940                /*      In the P2P mode, the driver should not support the b mode. */
1941                /*      So, the Tx packet shouldn't use the CCK rate */
1942                update_tx_basic_rate(padapter, (WIRELESS_11G | WIRELESS_11_24N));
1943
1944                /* Enable P2P function */
1945                init_wifidirect_info(padapter, role);
1946
1947                rtl8188e_SetHalODMVar(padapter, HAL_ODM_P2P_STATE, NULL, true);
1948        } else if (role == P2P_ROLE_DISABLE) {
1949                if (_FAIL == rtw_pwr_wakeup(padapter)) {
1950                        ret = _FAIL;
1951                        goto exit;
1952                }
1953
1954                /* Disable P2P function */
1955                if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
1956                        _cancel_timer_ex(&pwdinfo->find_phase_timer);
1957                        _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
1958                        _cancel_timer_ex(&pwdinfo->pre_tx_scan_timer);
1959                        _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
1960                        _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey2);
1961                        rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
1962                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
1963                        memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
1964                }
1965
1966                rtl8188e_SetHalODMVar(padapter, HAL_ODM_P2P_STATE, NULL, false);
1967
1968                /* Restore to initial setting. */
1969                update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
1970        }
1971
1972exit:
1973        return ret;
1974}
1975