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