diff options
author | Roman Yeryomin <roman@advem.lv> | 2013-05-17 20:40:24 +0300 |
---|---|---|
committer | Roman Yeryomin <roman@advem.lv> | 2013-05-17 20:40:24 +0300 |
commit | e6d87036412b952cb083eff2dc716aee97a771f2 (patch) | |
tree | 273dd3daaa85553832d3cc6d48276229dc7fbe09 /target/linux/realtek/files/drivers/net/wireless/rtl8192e/8192cd_p2p.c | |
parent | a18fec42221baa52fff4c5ffd45ec8f32e3add36 (diff) |
Move to rsdk 3.2.4. Compiles cleanly.
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/drivers/net/wireless/rtl8192e/8192cd_p2p.c')
-rw-r--r-- | target/linux/realtek/files/drivers/net/wireless/rtl8192e/8192cd_p2p.c | 5570 |
1 files changed, 5570 insertions, 0 deletions
diff --git a/target/linux/realtek/files/drivers/net/wireless/rtl8192e/8192cd_p2p.c b/target/linux/realtek/files/drivers/net/wireless/rtl8192e/8192cd_p2p.c new file mode 100644 index 000000000..1b248605d --- /dev/null +++ b/target/linux/realtek/files/drivers/net/wireless/rtl8192e/8192cd_p2p.c @@ -0,0 +1,5570 @@ +/* + * P2P support ; WIFI-DRIECT + * + * $Id: 8192cd_p2p.c,$ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_P2P_C_ + + +#ifdef __KERNEL__ +#include <linux/module.h> +#include <linux/kernel.h> +#endif + +#include <linux/random.h> +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_hw.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" +//#include "./8192cd_util.h" +#include "./8192cd_p2p.h" + +extern UINT8 WSC_IE_OUI[]; + +typedef int p2pcmd_func_t(struct rtl8192cd_priv *priv, unsigned char *data); + +struct p2p_cmd_list { + unsigned char cmd[32]; + p2pcmd_func_t* p2p_cmd_func; +}; + + +/*--------------debug---------------------*/ + + +/*---------------function declare start------------------ */ +char* p2p_get_token(char *, char *); +unsigned char* p2p_search_tag(unsigned char *, int ,unsigned char , int *); +unsigned char* p2p_check_tag(unsigned char *, int , unsigned char , int *); + + +int P2P_scan(struct rtl8192cd_priv *priv, unsigned char *data); +int P2P_search(struct rtl8192cd_priv *priv, unsigned char *data); +int P2P_listen(struct rtl8192cd_priv* priv,unsigned char* data); +void p2p_show_ss_res(struct rtl8192cd_priv *priv); +int P2P_show_status(struct rtl8192cd_priv *priv, unsigned char *data); + +int p2pcmd_enable(struct rtl8192cd_priv *, unsigned char *); +int p2pcmd_discovery(struct rtl8192cd_priv *priv, unsigned char *data); +int p2pcmd_find(struct rtl8192cd_priv *priv, unsigned char *data); +int p2pcmd_set(struct rtl8192cd_priv *priv, unsigned char *data); +int p2pcmd_set_listen_channel(struct rtl8192cd_priv *priv, unsigned char *data); + +int p2pcmd_force_GO(struct rtl8192cd_priv *priv, unsigned char *data); +int p2pcmd_backtoDev(struct rtl8192cd_priv *priv, unsigned char *data); +int p2p_as_GO(struct rtl8192cd_priv *priv, int GOtype); +int p2p_as_preClient(struct rtl8192cd_priv *priv); + + + +int wsc_build_probe_rsp_ie(struct rtl8192cd_priv *priv , + unsigned char *data , unsigned short DEVICE_PASSWORD_ID); + +int p2p_build_probe_req_ie(struct rtl8192cd_priv *priv, unsigned char *data); + + + +void indicate_wscd(struct rtl8192cd_priv *priv , unsigned char mode , + unsigned char *PSK ,struct p2p_device_peer *current_nego_peer); + +void p2p_on_provision_req(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo); +int p2p_issue_provision_rsp(struct rtl8192cd_priv *priv, unsigned char *da); + +int p2p_issue_provision_req(struct rtl8192cd_priv *priv ); +void p2p_on_provision_rsp(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo); + +void p2p_on_GO_nego_req(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo); + +int p2p_issue_GO_nego_rsp(struct rtl8192cd_priv *priv, + struct p2p_device_peer *current_nego_peer); +void p2p_on_GO_nego_conf(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo); +int p2p_issue_GO_nego_req(struct rtl8192cd_priv *priv); + +void p2p_on_GO_nego_rsp(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo); +int p2p_issue_GO_nego_conf(struct rtl8192cd_priv *priv, + struct p2p_device_peer *current_nego_peer); + + + +/*---------------function declare end-------------------- */ + +/*---------------local var declare start------------------ */ + +unsigned char P2P_WILDCARD_SSID[8]="DIRECT-"; + +unsigned char WFA_OUI[WFA_OUI_LEN] = {0x50, 0x6F, 0x9A}; +unsigned char WFA_OUI_PLUS_TYPE[WFA_OUI_PLUS_TYPE_LEN] = {0x50, 0x6F, 0x9A , 0x9}; + +unsigned char WILDCARD_ADDR[MAC_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + +/*---------------local var declare end------------------ */ + + +#define BAND_CONTROL 0 // no meaning + + +/*make sure i am under 2G band when p2p listen mode */ +void stay_on_2G(struct rtl8192cd_priv *priv) +{ + unsigned long flags ; + if (priv->pmib->dot11RFEntry.phyBandSelect != PHY_BAND_2G) + { + P2P_DEBUG(" Switch to 2G Band\n"); + //SAVE_INT_AND_CLI(flags); + //SMP_LOCK(flags); + + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0xf); + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_2G; + priv->pmib->dot11BssType.net_work_type = (WIRELESS_11B|WIRELESS_11G|WIRELESS_11N); + UpdateBBRFVal8192DE(priv); + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0x0); + + //RESTORE_INT(flags); + // SMP_UNLOCK(flags); + + } + + return; + +} + + +void stay_on_5G(struct rtl8192cd_priv *priv) +{ + unsigned long flags ; + if (priv->pmib->dot11RFEntry.phyBandSelect != PHY_BAND_5G) + { + P2P_DEBUG(" Switch to 5G Band\n"); + //SAVE_INT_AND_CLI(flags); + //SMP_LOCK(flags); + // stop BB + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0xf); + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_5G; + priv->pmib->dot11BssType.net_work_type = (WIRELESS_11A|WIRELESS_11N); + UpdateBBRFVal8192DE(priv); + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0x0); + + //RESTORE_INT(flags); + // SMP_UNLOCK(flags); + } + return; +} + + + + + + + +#define UTILITY_FUNCTIONS 0 // no meaning + + +/*-------------------------------- +*--------------------------------- +* +* utility unctions area +* +*--------------------------------- +---------------------------------*/ + +void generate_random_xy(unsigned char *data,int len) +{ + char *String09azAZ="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + unsigned char byteList[30]; + int idx; + if(len>30) + return; + + get_random_bytes((void *)&byteList, len); + for(idx=0;idx<len;idx++){ + data[idx] = String09azAZ[byteList[idx]%62]; + } + data[len]='\0'; + //P2P_DEBUG("return %s\n" ,data); + +} + +void init_channel_list(struct rtl8192cd_priv *priv) +{ + + int idx = 0; + + memset(&priv->p2pPtr->my_channel_list,0,sizeof(struct p2p_channels)); + + memcpy(priv->p2pPtr->my_channel_list.country ,"US " ,3); + + priv->p2pPtr->my_channel_list.reg_class_mun=3; + + priv->p2pPtr->my_channel_list.reg_class[0].reg_class = 81; + priv->p2pPtr->my_channel_list.reg_class[0].channel_mun=11; + for(idx=0;idx<11;idx++) + priv->p2pPtr->my_channel_list.reg_class[0].channel[idx]= idx+1; + + priv->p2pPtr->my_channel_list.reg_class[1].reg_class = 115; + priv->p2pPtr->my_channel_list.reg_class[1].channel_mun=4; + for(idx=0;idx<4;idx++) + priv->p2pPtr->my_channel_list.reg_class[1].channel[idx]= 36 + idx*4; + + priv->p2pPtr->my_channel_list.reg_class[2].reg_class = 124; + priv->p2pPtr->my_channel_list.reg_class[2].channel_mun = 5; + for(idx=0;idx<5;idx++) + priv->p2pPtr->my_channel_list.reg_class[2].channel[idx]= 149 + idx*4; + + priv->p2pPtr->my_channel_list.Id11_len = 3+(2+11)+(2+4)+(2+5); + //P2P_DEBUG("channel list len=%d\n",priv->p2pPtr->my_channel_list.Id11_len); +} + +void generate_GO_ssid(struct rtl8192cd_priv *priv) + +{ + + unsigned char tmpstr[24]; + + generate_random_xy(tmpstr,2); + + memcpy(priv->p2pPtr->ssid_random ,tmpstr ,2); + + memcpy(priv->p2pPtr->my_GO_ssid,P2P_WILDCARD_SSID,P2P_WILDCARD_SSID_LEN); + + memcpy(&priv->p2pPtr->my_GO_ssid[P2P_WILDCARD_SSID_LEN] ,priv->p2pPtr->ssid_random,2); + +#if 0 // add postfix ssid after - + priv->p2pPtr->my_GO_ssid[P2P_WILDCARD_SSID_LEN+2]='-'; + convert_bin_to_str(GET_MY_HWADDR, 6, tmpstr); + memcpy(priv->p2pPtr->my_GO_ssid+P2P_WILDCARD_SSID_LEN+2+1 ,tmpstr,12); + priv->p2pPtr->my_GO_ssid[P2P_WILDCARD_SSID_LEN+2+1+12]='\0'; +#else + priv->p2pPtr->my_GO_ssid[P2P_WILDCARD_SSID_LEN+2]='\0'; + priv->p2pPtr->my_GO_ssid_len = strlen(priv->p2pPtr->my_GO_ssid); +#endif + P2P_DEBUG("GO SSID=%s\n",priv->p2pPtr->my_GO_ssid); + +} + + + +void generate_GO_PSK(struct rtl8192cd_priv *priv) + +{ + unsigned char tmpstr[65]; + generate_random_xy(tmpstr,8); + memcpy(priv->p2pPtr->go_PSK ,tmpstr ,8); + priv->p2pPtr->go_PSK[8]='\0'; + P2P_DEBUG("GO PSK=%s\n",priv->p2pPtr->go_PSK); +} + + +/* + * find a token in a string. If succes, return pointer of token next. If fail, return null + */ +char* p2p_get_token(char *data, char *token) +{ + int idx=0, src_len=strlen(data), token_len=strlen(token); + + while (src_len >= token_len) { + if (!memcmp(&data[idx], token, token_len)){ + if(data[idx+token_len]==','|| data[idx+token_len]=='=') + return (&data[idx+token_len+1]); + else + return (&data[idx+token_len]); + } + src_len--; + idx++; + } + return NULL; +} + + +char *get_config_token(char *data, char *token) +{ + char *ptr=data; + int len=0, idx=0; + + while (*ptr && *ptr != '\n' ) { + if (*ptr == '=') { + if (len <= 1) + return NULL; + memcpy(token, data, len); + + /* delete ending space */ + for (idx=len-1; idx>=0; idx--) { + if (token[idx] != ' ') + break; + } + token[idx+1] = '\0'; + + return ptr+1; + } + len++; + ptr++; + } + return NULL; +} + + +int get_config_value(char *data, char *value) +{ + char *ptr=data; + int len=0, idx, i; + + while (*ptr && *ptr != '\n' && *ptr != '\r') { + len++; + ptr++; + } + + /* delete leading space */ + idx = 0; + while (len-idx > 0) { + if (data[idx] != ' ') + break; + idx++; + } + len -= idx; + + /* delete bracing '"' */ + if (data[idx] == '"') { + for (i=idx+len-1; i>idx; i--) { + if (data[i] == '"') { + idx++; + len = i - idx; + } + break; + } + } + + if (len > 0) { + memcpy(value, &data[idx], len); + value[len] = '\0'; + } + return len; +} + +int is_zero_ether_addr(const unsigned char *a) +{ + return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]); +} + +int is_zero_pin_code(const unsigned char *a) +{ + return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]| a[6]| a[7]); +} +void p2p_debug_out(unsigned char *label, unsigned char *data, int data_length) +{ + int i,j; + int num_blocks; + int block_remainder; + + num_blocks = data_length >> 4; + block_remainder = data_length & 15; + + if (label) + printk("%s\n", label); + + if (data==NULL || data_length==0) + return; + + for (i=0; i<num_blocks; i++) { + printk("\t"); + for (j=0; j<16; j++) + printk("%02x ", data[j + (i<<4)]); + printk("\n"); + } + + if (block_remainder > 0) { + printk("\t"); + for (j=0; j<block_remainder; j++) + printk("%02x ", data[j+(num_blocks<<4)]); + printk("\n"); + } +} + + +/* + * show value by binary format + */ +void ShowValByBinary(unsigned int ByteIn, char *binary_str ,int len ) +{ + int idx; + for( idx=0 ; idx < len;idx++){ + if(ByteIn & 1<<(len - 1 - idx)) + binary_str[idx]='1'; + else + binary_str[idx]='0'; + } + binary_str[idx+1]='\0'; +} + + +#define P2P_ATTRIBUTE_PARSE 0 // no meaning + +/*---------------------------------------------------------------- + ------------------------------------------------------------------*/ + + +void parse_channel_list(unsigned char* pData , int tag_len , + struct p2p_device_peer *current_nego_peer) +{ + int idx; + int len=tag_len; + int channels; + int reg_class=0; + + unsigned char CountryCodeStr[4]; + strncpy(CountryCodeStr , pData ,3); + CountryCodeStr[3]='\0'; + //P2P_DEBUG(" CountryCode:%s\n", CountryCodeStr); + //P2P_DEBUG(" Channel:"); + len -= 3; + pData +=3; + + while(len){ + //P2P_DEBUG(" op class:%d\n",pData[0]); + channels = pData[1]; + for( idx=0 ; idx < channels ;idx++){ + if(current_nego_peer) + current_nego_peer->channels_list.reg_class[reg_class].channel[idx]=pData[2+idx]; + //P2P_DEBUG(" channel:%d \n",pData[2+idx]); + } + len -= (2+channels); + pData += (2+channels); + reg_class++; + } + + +} + +void parse_device_info(unsigned char* pData , int tag_len , + struct device_info_s* dev_info_ptr ) +{ + int TagLenChk=tag_len; + int idx = 0; + unsigned char NoSD=0; + unsigned short WSC_T; + unsigned short WSC_L; + unsigned char DeviceName[33]; + + /*device address */ + //P2P_DEBUG("P2P Device Address:"); + //MAC_PRINT(pData); + if(dev_info_ptr){ + memcpy(dev_info_ptr->dev_address,pData,6 ); + } + + pData += 6; + TagLenChk -= 6; + + /*config method */ + //P2P_DEBUG(" Config method:0x%02X\n",*(unsigned short*)pData); + if(dev_info_ptr){ + dev_info_ptr->config_method = *(unsigned short*)pData; + } + + + pData += 2; + TagLenChk -= 2; + + + /*Primary Device Type */ + if(dev_info_ptr){ + memcpy(dev_info_ptr->pri_dev_type , pData , 8); + } + + pData += 8; + TagLenChk -= 8; + + /*Number of Second Device Type */ + + NoSD = pData[0]; + pData += 1; + TagLenChk -= 1; + + if(dev_info_ptr) + dev_info_ptr->sdv_mun = NoSD; + + /* N * Second Device Type */ + if(NoSD){ + for( idx=0 ; idx < NoSD ; idx++){ + if(idx < MAX_SEC_DEV_TYPE){ // now we just keep 2 set , take care + if(dev_info_ptr) + memcpy(&dev_info_ptr->sec_dev_type[idx] ,pData,8); + } + pData += 8; + TagLenChk -= 8; + } + } + + /* Device Name (WSC TLV(2+2+N))*/ + + WSC_T = *((unsigned short *)pData); // Tag + + pData+=2; + + WSC_L = *((unsigned short *)pData); // LEN + + if(WSC_T != 0x1011) + P2P_DEBUG("chk!! should be 0x1011\n"); + + pData+=2; + strncpy(DeviceName,pData,WSC_L); + DeviceName[WSC_L]='\0'; + + //P2P_DEBUG("Device name:%s\n",DeviceName); + + if(dev_info_ptr){ + strcpy(dev_info_ptr->devname ,DeviceName); + } + + + + TagLenChk -= (4+WSC_L); + if(TagLenChk){ + P2P_DEBUG("chk!! TagLenChk(%d) should be 0\n",TagLenChk); + P2P_DEBUG("tag_len=%d\n",tag_len); + } + + +} + + +void parse_group_info(unsigned char* pData , int tag_len) +{ + int TagLenChk=tag_len; + int EachClientInfoLen=0; + int idx = 0; + unsigned char NoSD=0; + unsigned short WSC_T; + unsigned short WSC_L; + unsigned char DeviceName[33]; + + /* process sum of all p2p clients*/ + while(TagLenChk){ + + /*length of bellowing fields */ + EachClientInfoLen = pData[0]; + pData += 1; + + TagLenChk -= EachClientInfoLen; + + /*device address */ + P2P_DEBUG(" Device Addr:"); + MAC_PRINT(pData); + + + pData +=6; + EachClientInfoLen -= 6; + + /*interface address */ + P2P_DEBUG(" interface Addr:"); + MAC_PRINT(pData); + + pData +=6; + EachClientInfoLen -= 6; + + /*config method */ + P2P_DEBUG("Config method:0x%02X\n",*(unsigned int*)pData); + pData +=2; + EachClientInfoLen -= 2; + + + /*Primary Device Type */ + P2P_DEBUG(" Primary Device Type:category_id=0x%x, oui=%02x%02x%02x%02x, sub_category_id=0x%x\n", + le16_to_cpu(*((unsigned short *)pData)), pData[2],pData[3],pData[4],pData[5], + le16_to_cpu(*((unsigned short *)&pData[6]))); + + pData +=8; + EachClientInfoLen -= 8; + + + /*Number of Second Device Type */ + + NoSD = pData[0]; + pData +=1; + EachClientInfoLen -= 1; + + /* N * Second Device Type */ + if(NoSD){ + for( ; idx < NoSD ; idx++){ + P2P_DEBUG(" Second Device Type:category_id=0x%x, oui=%02x%02x%02x%02x, sub_category_id=0x%x\n", + le16_to_cpu(*((unsigned short *)pData)), pData[2],pData[3],pData[4],pData[5], + le16_to_cpu(*((unsigned short *)&pData[6]))); + + pData +=8; + EachClientInfoLen -= 8; + } + } + + /* Device Name (WSC TLV(2+2+N))*/ + + WSC_T = *((unsigned short *)pData); + if(WSC_T != 0x1011) + P2P_DEBUG("chk!! should be 0x1011\n"); + + + pData+=2; + WSC_L = *((unsigned short *)pData); + P2P_DEBUG("device name len=%d\n",WSC_L); + + + pData+=2; + strncpy(DeviceName,pData,WSC_L); + DeviceName[WSC_L]='\0'; + + + + pData += WSC_L; + EachClientInfoLen -= (4+WSC_L); + + if(EachClientInfoLen) + P2P_DEBUG("chk!! EachClientInfoLen should be 0 now\n"); + + } + + + +} + + +void parse_group_id(unsigned char* pData , int tag_len , + struct p2p_device_peer *current_nego_peer) +{ + /*ID 15*/ + unsigned char StrSSID[33]; + + if(current_nego_peer) + memcpy(current_nego_peer->group_bssid , pData ,6); + + pData += 6; + tag_len -= 6 ; + + /*p2p Device Address */ + strncpy(StrSSID,pData,tag_len); + StrSSID[tag_len]='\0'; + + if(current_nego_peer){ + strcpy(current_nego_peer->group_ssid , StrSSID); + current_nego_peer->group_ssid_len = strlen(current_nego_peer->group_ssid); + } + +} + + +void parse_p2p_interface(unsigned char* pData , int tag_len) +{ + + int idx = 0; + int AddrCnt = 0; + + /*p2p Device Address */ + P2P_DEBUG(" P2P DevAddr:"); + MAC_PRINT(pData); + + + pData += 6 ; + tag_len -= 6 ; + + + /*p2p interface addr count*/ + AddrCnt = pData[0]; + + /* p2p_inter_addr_cnt * inter_addr */ + if(AddrCnt){ + for( ; idx < AddrCnt ; idx++){ + + P2P_DEBUG(" P2P ifAddr:"); + MAC_PRINT(pData); + + pData += 6 ; + tag_len -= 6 ; + } + } + + if(tag_len){ + P2P_DEBUG("chk!! tag_len should be 0 now\n"); + } + + +} + + +void parse_p2p_Capability(void) +{ + + P2P_PRINT("0... .... Reserved\n"); + P2P_PRINT(".0.. .....Reserved\n"); + P2P_PRINT("..1. .... Device Supports P2P Invitation Procedure\n"); + P2P_PRINT("...0 .... Device Limit, able to participate in additional P2P Groups\n"); + P2P_PRINT(".... 0... Infrastructure manamgement NOT upported\n"); + P2P_PRINT(".... .0.. Concurrent operation NOT supported\n"); + P2P_PRINT(".... ..0. Client discoverability NOT supported\n"); + P2P_PRINT(".... ...1 Service discovery supported\n\n"); + + P2P_PRINT("0... .... Reserved\n"); + P2P_PRINT(".0.. .... Not operating as GO in the Provisioning phase\n"); + P2P_PRINT("..0. .... Persistent reconnect NOT supported\n"); + P2P_PRINT("...0 .... Cross connection NOT supported\n"); + P2P_PRINT(".... 0... Intra-BSS distribution NOT supported\n"); + P2P_PRINT(".... .0.. The GO is able to add additional Clients\n"); + P2P_PRINT(".... ..0. Persistent P2P Group supported\n"); + P2P_PRINT(".... ...0 NOT acting as GO\n"); + +} + + +void p2p_cancel_noa(struct rtl8192cd_priv *priv) +{ + if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_NONE) + return; + + cancel_timer2(priv); + P2P_DEBUG("Stop all NoA action!\n"); + if (priv->p2pPtr->noa_list_t.p2p_txpause_flag) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & 0xe0); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 0; + } + + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_NONE; +} + + +void p2p_noa_timer(struct rtl8192cd_priv *priv) +{ + unsigned int cur_tsf, pre_tbtt, offset; + //P2P_DEBUG("\n"); + if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_OPPPS) { + if (priv->p2pPtr->noa_list_t.p2p_txpause_flag) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & 0xe0); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 0; + + cur_tsf = RTL_R32(TSFTR); + pre_tbtt = (cur_tsf / (priv->beacon_period * 1024)) * (priv->beacon_period * 1024); + offset = ((priv->p2pPtr->noa_list_t.CTWindow_OppPs & 0x7f) - 1) * 1024; + setup_timer2(priv, pre_tbtt + offset); + } + else { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | 0x1f); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 1; + + cur_tsf = RTL_R32(TSFTR); + pre_tbtt = (cur_tsf / (priv->beacon_period * 1024)) * (priv->beacon_period * 1024); + setup_timer2(priv, pre_tbtt + (priv->beacon_period * 1024)); + } + } + else if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_NP_NOA) { + if (priv->p2pPtr->noa_list_t.p2p_txpause_flag) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & 0xe0); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 0; + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_NONE; + } + } + else if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_CONT_NOA) { + if (priv->p2pPtr->noa_list_t.p2p_txpause_flag) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & 0xe0); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 0; + offset = priv->p2pPtr->noa_list_t.noa_counter * priv->p2pPtr->noa_list_t.noa_descs.interval; + setup_timer2(priv, priv->p2pPtr->noa_list_t.noa_descs.starttime + offset); + } + else { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | 0x1f); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 1; + offset = priv->p2pPtr->noa_list_t.noa_counter * priv->p2pPtr->noa_list_t.noa_descs.interval + + priv->p2pPtr->noa_list_t.noa_descs.duration; + setup_timer2(priv, priv->p2pPtr->noa_list_t.noa_descs.starttime + offset); + priv->p2pPtr->noa_list_t.noa_counter++; + } + } + else { // priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_NOA + } +} + + +void p2p_process_noa(struct rtl8192cd_priv *priv) +{ + unsigned int cur_tsf, pre_tbtt, offset; + + if ((priv->p2pPtr->noa_list_t.CTWindow_OppPs & 0x80) && ((priv->p2pPtr->noa_list_t.CTWindow_OppPs & 0x7f) != 0)) + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_OPPPS; + else if (priv->p2pPtr->noa_list_t.noa_descs.count == 1) + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_NP_NOA; + else if (priv->p2pPtr->noa_list_t.noa_descs.count == 255) + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_CONT_NOA; + else if (priv->p2pPtr->noa_list_t.noa_descs.count != 0) + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_NOA; + else { + P2P_DEBUG("No NoA parameters!\n\n"); + return; + } + P2P_DEBUG("Start GO PS type of %d\n\n", priv->p2pPtr->noa_list_t.go_ps_type); + + if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_OPPPS) { + cur_tsf = RTL_R32(TSFTR); + pre_tbtt = (cur_tsf / (priv->beacon_period * 1024)) * (priv->beacon_period * 1024); + offset = ((priv->p2pPtr->noa_list_t.CTWindow_OppPs & 0x7f) - 1) * 1024; + setup_timer2(priv, pre_tbtt + offset); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 0; + } + else if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_NP_NOA) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | 0x1f); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 1; + + cur_tsf = RTL_R32(TSFTR); + if (TSF_LESS(cur_tsf, priv->p2pPtr->noa_list_t.noa_descs.starttime)) + setup_timer2(priv, priv->p2pPtr->noa_list_t.noa_descs.starttime + + priv->p2pPtr->noa_list_t.noa_descs.duration); + else + setup_timer2(priv, cur_tsf + priv->p2pPtr->noa_list_t.noa_descs.duration); + } + else if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_CONT_NOA) { + cur_tsf = RTL_R32(TSFTR); + if (TSF_LESS(cur_tsf, priv->p2pPtr->noa_list_t.noa_descs.starttime)) { + setup_timer2(priv, priv->p2pPtr->noa_list_t.noa_descs.starttime); + priv->p2pPtr->noa_list_t.noa_counter = 0; + } + else { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | 0x1f); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 1; + setup_timer2(priv, priv->p2pPtr->noa_list_t.noa_descs.starttime + + priv->p2pPtr->noa_list_t.noa_descs.duration); + priv->p2pPtr->noa_list_t.noa_counter = 1; + } + } + else { // priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_NOA + } +} + + +void parse_p2p_NOA(struct rtl8192cd_priv *priv, unsigned char* pData, int tag_len, int seq) +{ + unsigned int noa_num, u32; + //unsigned int cur_tsf, offset; + + if (pData[0] != priv->p2pPtr->noa_list_t.index) { + p2p_cancel_noa(priv); + priv->p2pPtr->noa_list_t.index = pData[0]; + priv->p2pPtr->noa_list_t.CTWindow_OppPs = pData[1]; + + memset(&priv->p2pPtr->noa_list_t.noa_descs, 0, sizeof(struct noa_desc)); + noa_num = (tag_len - 2) / 13; + if (noa_num) { + priv->p2pPtr->noa_list_t.noa_descs.count = *(pData + 2); + memcpy(&u32, (pData + 2) + 1, 4); + priv->p2pPtr->noa_list_t.noa_descs.duration = le32_to_cpu(u32); + memcpy(&u32, (pData + 2) + 5, 4); + priv->p2pPtr->noa_list_t.noa_descs.interval = le32_to_cpu(u32); + memcpy(&u32, (pData + 2) + 9, 4); + priv->p2pPtr->noa_list_t.noa_descs.starttime = le32_to_cpu(u32); + } + + P2P_DEBUG("Update NoA (seq %d): index %d, OppPs 0x%02x, NoA count %d, duration %d, interval %d, start 0x%08x\n", + seq, + priv->p2pPtr->noa_list_t.index, + priv->p2pPtr->noa_list_t.CTWindow_OppPs, + priv->p2pPtr->noa_list_t.noa_descs.count, + priv->p2pPtr->noa_list_t.noa_descs.duration, + priv->p2pPtr->noa_list_t.noa_descs.interval, + priv->p2pPtr->noa_list_t.noa_descs.starttime); + + p2p_process_noa(priv); + } +} + + +#define P2P_TAG_SEARCH 0 // no meaning + + +/*P2P TLV format: T(1B)L(2B)V(var)*/ +unsigned char* p2p_search_tag(unsigned char *data_be_search, + int data_len,unsigned char tag, int *out_len) +{ + unsigned char id; + unsigned short tag_len; + int size; + + while (data_len > 0) { + memcpy(&id, data_be_search, 1); + memcpy(&tag_len, data_be_search+1, 2); + tag_len = le16_to_cpu(tag_len); + + if (id == tag) { + if (data_len >= (1+2+ tag_len)) { + + *out_len = (int)tag_len; + return (&data_be_search[3]); + } + else { + P2P_DEBUG("Found tag [0x%x], but invalid length!\n", tag); + P2P_DEBUG("data_len=%d , 1+2+tag_len(%d)\n", data_len , tag_len); + break; + } + } + size = 1+2 + tag_len; + data_be_search += size; + data_len -= size; + } + + return NULL; +} + + + +unsigned char *p2p_check_tag(unsigned char *TLV_data, int TLV_len, unsigned char tag, int *o_len) +{ + unsigned char *pData; + int tag_len; +#ifdef P2P_DEBUGMSG + unsigned char tmpstr[50]; + unsigned char tmpstr2[50]; + unsigned short tmp_u16_1; + unsigned short tmp_u16_2; +#endif + + + + pData = p2p_search_tag(TLV_data, TLV_len,tag, &tag_len); + + if (pData == NULL) { + + return NULL; + }else{ + P2P_DEBUG("tag(%d) :", tag); + } + +#ifdef P2P_DEBUGMSG + switch(tag){ + + case TAG_STATUE : + P2P_PRINT(" Status:%d\n",pData[0]); + break; + case TAG_MINOR_RES_CODE : + P2P_PRINT(" Minor reason code: %d\n",pData[0]); + break; + case TAG_P2P_CAPABILITY : + ShowValByBinary(pData[0] , tmpstr , 8); + ShowValByBinary(pData[1] , tmpstr2 , 8); + P2P_PRINT(" p2p Capability: (%s %s)\n",tmpstr,tmpstr2); + parse_p2p_Capability(); + break; + case TAG_DEVICE_ID : + P2P_PRINT(" Device ID: %02x%02x%02x:%02x%02x%02x\n", + pData[0],pData[1],pData[2],pData[3],pData[4],pData[5]); + break; + case TAG_GROUP_OWNER_INTENT : + P2P_PRINT(" Owner Intent: %d , Tie=%d\n",pData[0]>>1 , pData[0]&0x1); + break; + case TAG_CONFIG_TIMEOUT : + P2P_PRINT(" Config Timeout: = (%d,%d)\n",pData[0],pData[1]); + break; + case TAG_LISTEN_CHANNEL : + P2P_PRINT(" Listen Channel: (country code),%d,%d \n",pData[3],pData[4]); + break; + case TAG_P2P_GROUP_BSSID : + P2P_PRINT(" p2p Group BSSID:%02x%02x%02x:%02x%02x%02x\n", + pData[0],pData[1],pData[2],pData[3],pData[4],pData[5]); + break; + case TAG_EXT_LISTEN_TIMING : + tmp_u16_1 = *(unsigned short*)pData; + tmp_u16_2 = *(unsigned short*)(pData+2); + P2P_PRINT(" Extended Listen Timing: (%d ,%d)\n",tmp_u16_1,tmp_u16_2); + break; + case TAG_INTEN_P2P_INTERFACE_ADDR : + P2P_PRINT(" INTENED P2P INTERFACE ADDR=%02x%02x%02x:%02x%02x%02x\n", + pData[0],pData[1],pData[2],pData[3],pData[4],pData[5]); + break; + case TAG_P2P_MANAGEABILITY : + ShowValByBinary(pData[0] , tmpstr , 8); + P2P_PRINT(" P2P Manageability =%s\n",tmpstr); + break; + case TAG_CHANNEL_LIST : + + P2P_PRINT(" Channel List\n"); + parse_channel_list(pData , tag_len ,NULL); + break; + + case TAG_NOTICE_OF_ABSENCE : + //TODO ; more detail + P2P_PRINT(" Notice of Absence\n"); + break; + case TAG_P2P_DEVICE_INFO : + + P2P_PRINT(" P2P Device Info \n"); + parse_device_info(pData,tag_len,NULL); + break; + + case TAG_P2P_GROUP_INFO : + + P2P_PRINT(" p2p Group Info \n"); + parse_group_info(pData,tag_len); + break; + + case TAG_P2P_GROUP_ID : + + P2P_PRINT(" p2p Group ID\n"); + parse_group_id(pData,tag_len,NULL); + break; + + case TAG_P2P_INTERFACE : + + P2P_PRINT(" P2P INTERFACE \n"); + parse_p2p_interface(pData,tag_len); + break; + + case TAG_OPERATION_CHANNEL : + strncpy(tmpstr , pData , 3); + P2P_PRINT(" Operation Channel ,country code=%s operation class=%d ,channel number=%d \n", + tmpstr , pData[3],pData[4]); + break; + case TAG_INVITATION_FLAGS : + ShowValByBinary(pData[0] , tmpstr , 8) ; + P2P_PRINT(" Invitation Flags=%s\n",tmpstr); + break; + default: + P2P_DEBUG("Unknow TAG ID \n"); + break; + } + +#endif + *o_len = tag_len; + return pData; +} + + +#define GET_INFO 0 // no meaning +int p2p_get_role(struct rtl8192cd_priv *priv, + unsigned char *p2p_ie,int p2pIElen ) +{ + unsigned char* p2p_capa; + int tag_len = 0; + + p2p_capa = p2p_search_tag(p2p_ie , p2pIElen , TAG_P2P_CAPABILITY , &tag_len); + + + if(p2p_capa[1] & BIT(0)) + return R_P2P_GO; // GO + else + return R_P2P_DEVICE; // device + +} +void p2p_get_device_info(struct rtl8192cd_priv *priv, + unsigned char *p2p_ie ,int p2pIElen ,struct device_info_s* dev_info_ptr) +{ + unsigned char* p2p_sub_ie; + int tag_len = 0; + + p2p_sub_ie = p2p_search_tag(p2p_ie , p2pIElen , TAG_P2P_DEVICE_INFO , &tag_len); + if(p2p_sub_ie){ + parse_device_info(p2p_sub_ie,tag_len, dev_info_ptr); + }else{ + P2P_DEBUG("can't found DEVICE_INFO\n\n"); + } + +} + +int p2p_get_GO_p2p_info(struct rtl8192cd_priv *priv, + unsigned char *p2p_ie ,int p2pIElen ,struct device_info_s* dev_info_ptr) +{ + unsigned char* p2p_sub_ie=NULL; + int tag_len = 0; + + /*ID3*/ + p2p_sub_ie = p2p_search_tag(p2p_ie , p2pIElen , TAG_DEVICE_ID , &tag_len); + if(p2p_sub_ie ){ + memcpy(dev_info_ptr->dev_address , p2p_sub_ie , 6); + //MAC_PRINT(dev_info_ptr->dev_address); + return SUCCESS; + }else{ + return FAIL; + } +} + +void p2p_get_GO_wsc_info(struct rtl8192cd_priv *priv, + unsigned char *wsc_ie ,int wscIElen ,struct device_info_s *dev_info_ptr) +{ + unsigned char* p2p_sub_ie=NULL; + int tag_len = 0; + + + p2p_sub_ie = search_wsc_tag(wsc_ie, TAG_CONFIG_METHODS, wscIElen, &tag_len); + if(p2p_sub_ie){ + dev_info_ptr->config_method = *(unsigned short *)p2p_sub_ie ; + //P2P_DEBUG("wsc method = %02x\n",dev_info_ptr->config_method); + } + + p2p_sub_ie = search_wsc_tag(wsc_ie, TAG_DEVICE_NAME, wscIElen, &tag_len); + if(p2p_sub_ie){ + memcpy(dev_info_ptr->devname , p2p_sub_ie ,tag_len) ; + dev_info_ptr->devname[tag_len]='\0'; + //P2P_DEBUG("device name = %s\n",dev_info_ptr->devicename); + } + + + +} + + + +#define ADD_P2P_ATTRIBUTE 0 // no meaning + + +unsigned char *wsc_add_tlv(unsigned char *data, unsigned short id, int len, void *val) +{ + unsigned short size = htons(len); + unsigned short tag = htons(id); + + memcpy(data, &tag, 2); + memcpy(data+2, &size, 2); + memcpy(data+4, val, len); + + return (data+4+len); +} + + + +void add_primarydevtype(struct rtl8192cd_priv *priv ,unsigned char * AttrPtr) +{ + + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short shortVal = 0; + + if(OPMODE & WIFI_AP_STATE) + shortVal = P2P_device_category_id_AP; + else + shortVal = P2P_device_category_id_STA; + + memcpy(thisAttrPrt, &shortVal, 2); + + memcpy(thisAttrPrt+2, WSC_IE_OUI, 4); + + shortVal = P2P_device_sub_category_id; + + memcpy(thisAttrPrt+6, &shortVal, 2); + + +} + +unsigned char* add_Attr_status(struct rtl8192cd_priv *priv ,unsigned char * AttrPtr + , unsigned char *p2pIELen ,unsigned char status ) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 1 ; + + thisAttrPrt[0] = TAG_STATUE; + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + thisAttrPrt[3] = status; + + *p2pIELen += (1+3); + thisAttrPrt += (1+3); + + return thisAttrPrt; +} + + +unsigned char* add_Attr_minor_reason(struct rtl8192cd_priv *priv + ,unsigned char * AttrPtr , unsigned char *p2pIELen ,unsigned char reason ) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 1 ; + thisAttrPrt[0] = TAG_MINOR_RES_CODE; + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + thisAttrPrt[3] = reason; + *p2pIELen += (1+3); + thisAttrPrt += (1+3); + return thisAttrPrt; +} + +unsigned char* add_Attr_capability( + struct rtl8192cd_priv *priv ,unsigned char * AttrPtr , + unsigned char *p2pIELen ,struct p2p_device_peer *current_nego_peer) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned char deviceCap = 0; + unsigned char groupCap = 0; + unsigned short attrlen = 2 ; + + /* set devce cap*/ + if(P2PMODE == P2P_TMP_GO || P2PMODE == P2P_CLIENT) + { + deviceCap |= CLIENT_DISCOVERY; + } + + + + /* set group cap*/ + /* i am prepare as GO*/ + if(current_nego_peer && current_nego_peer->role == R_P2P_CLIENT){ + groupCap |= GCAP_IBSS_DIST ; + } + + if(P2PMODE ==P2P_TMP_GO) + { + groupCap |= GCAP_GO; + groupCap |= GCAP_IBSS_DIST ; + } + + + /*when i am pre-go , indicate that it's wps ongoing*/ + if(P2PMODE == P2P_PRE_GO ){ + groupCap |= GCAP_GO_FORMATION; + } + + if(priv->p2pPtr->persistent_go) + groupCap |= GCAP_PRESISTENT_GO; + + if(priv->p2pPtr->p2p_go_limit) + groupCap |= GCAP_GROUP_LIMIT; + + + + thisAttrPrt[0] = TAG_P2P_CAPABILITY; + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + thisAttrPrt[3] = deviceCap; + thisAttrPrt[4] = groupCap; + + *p2pIELen += (2+3); + thisAttrPrt += (2+3); + + + + return thisAttrPrt; + +} + + + + +/* SPEC 1.1 page 83*/ +unsigned char* add_Attr_device_id( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=6; + + thisAttrPrt[0] = TAG_DEVICE_ID; + + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + + memcpy(thisAttrPrt+3 , GET_MY_HWADDR , 6); + + + *p2pIELen+= (6+3); + thisAttrPrt += (6+3); + + return thisAttrPrt; + +} + + +/* SPEC 1.1 page 84*/ +unsigned char* add_Attr_GO_intent(struct rtl8192cd_priv *priv ,unsigned char * AttrPtr + , unsigned char *p2pIELen , int tieBreak) +{ + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 1 ; + unsigned char intent = 0; + + thisAttrPrt[0] = TAG_GROUP_OWNER_INTENT; + + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + + intent = priv->pmib->p2p_mib.p2p_intent<<1; + + if(tieBreak) + intent |= 0x1; + + thisAttrPrt[3] = intent; + + *p2pIELen+= (1+3); + thisAttrPrt += (1+3); + + return thisAttrPrt; +} + +/* SPEC 1.1 page 84*/ +unsigned char* add_Attr_configration_timeout( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , + unsigned char *p2pIELen , int MyRole) +{ + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 2 ; + unsigned short attrlen2 = 2 ; + + + thisAttrPrt[0] = TAG_CONFIG_TIMEOUT; + + attrlen2 = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen2 ,2); + + + if(MyRole==R_P2P_GO){ + thisAttrPrt[3] = 0xff; + thisAttrPrt[4] = 0; + }else{ + thisAttrPrt[3] = 0; + thisAttrPrt[4] = 0xff; + } + + *p2pIELen+= (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + + +/* SPEC 1.1 page 85*/ +unsigned char* add_Attr_listenChannel( + struct rtl8192cd_priv *priv , unsigned char * AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=5; + + thisAttrPrt[0] = TAG_LISTEN_CHANNEL; // ID6 + + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + + + thisAttrPrt[3] = 'U'; + thisAttrPrt[4] = 'S'; + thisAttrPrt[5] = ' '; + thisAttrPrt[6] = 0x51; + thisAttrPrt[7] = priv->pmib->p2p_mib.p2p_listen_channel; + + *p2pIELen+= (5+3); + thisAttrPrt += (5+3); + return thisAttrPrt; + +} + + +/* SPEC 1.1 page 85;include in invitation req,no support now*/ +unsigned char* add_Attr_group_bssid( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + //unsigned short attrlen = 0 ; + P2P_DEBUG("TODO\n"); + + return thisAttrPrt; + +} + +/* SPEC 1.1 page 86*/ +unsigned char* add_Attr_extended_listen_timing( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen, + unsigned short period ,unsigned short interval ) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 4; + unsigned short attrlen2 ; + + thisAttrPrt[0] = TAG_EXT_LISTEN_TIMING; // ID8 + + + attrlen2 = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen2 ,2); + + attrlen2 = cpu_to_le16(period); + memcpy(thisAttrPrt+3 , (void *)&attrlen2 ,2); + + attrlen2 = cpu_to_le16(interval); + memcpy(thisAttrPrt+5 , (void *)&attrlen2 ,2); + + *p2pIELen+= (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + +/* SPEC 1.1 page 87*/ +unsigned char* add_Attr_intended_interface( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=6; + thisAttrPrt[0] = TAG_INTEN_P2P_INTERFACE_ADDR; // ID 9 + + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + + memcpy(thisAttrPrt+3 , GET_MY_HWADDR , 6); + + + *p2pIELen+= (6+3); + thisAttrPrt += (6+3); + + return thisAttrPrt; + +} + +/* SPEC 1.1 page 87*/ +unsigned char* add_Attr_manageability( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + +/* + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 0 ; + P2P_DEBUG("TODO\n"); + + return thisAttrPrt; +*/ + return NULL; +} + + +/* SPEC 1.1 page 88 ; ID 11 */ +unsigned char* add_Attr_channel_list( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=0; + unsigned short attrlen2=0; + int idx = 0; + + thisAttrPrt[0] = TAG_CHANNEL_LIST; // ID 11 + + attrlen2 = priv->p2pPtr->my_channel_list.Id11_len; + attrlen= priv->p2pPtr->my_channel_list.Id11_len; + // P2P_DEBUG("channel list len=%d\n",priv->p2pPtr->my_channel_list.Id11_len); + attrlen2 = cpu_to_le16(attrlen2); + memcpy(&thisAttrPrt[1] , (void *)&attrlen2 ,2); // attri len + + memcpy(&thisAttrPrt[3] , priv->p2pPtr->my_channel_list.country , 3); //country code + + + + thisAttrPrt[6] = priv->p2pPtr->my_channel_list.reg_class[0].reg_class; + thisAttrPrt[7] = priv->p2pPtr->my_channel_list.reg_class[0].channel_mun; + for(idx=0;idx<11;idx++) + thisAttrPrt[8+idx] =priv->p2pPtr->my_channel_list.reg_class[0].channel[idx]; + + thisAttrPrt[19] = priv->p2pPtr->my_channel_list.reg_class[1].reg_class; + thisAttrPrt[20] = priv->p2pPtr->my_channel_list.reg_class[1].channel_mun; + for(idx=0;idx<4;idx++) + thisAttrPrt[21+idx] =priv->p2pPtr->my_channel_list.reg_class[1].channel[idx]; + + thisAttrPrt[25] = priv->p2pPtr->my_channel_list.reg_class[2].reg_class; + thisAttrPrt[26] = priv->p2pPtr->my_channel_list.reg_class[2].channel_mun; + for(idx=0;idx<5;idx++) + thisAttrPrt[27+idx] =priv->p2pPtr->my_channel_list.reg_class[2].channel[idx]; + + + *p2pIELen+= (attrlen+3); + thisAttrPrt += (attrlen+3); + return thisAttrPrt; +} + + +/* SPEC 1.1 page 89*/ +unsigned char* add_Attr_notice_of_absence( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 2; + unsigned short attrlen2 = 0; + + thisAttrPrt[0] = TAG_NOTICE_OF_ABSENCE; // ID 9 + + attrlen2 = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen2 ,2); + + thisAttrPrt[3] = 0; // index + thisAttrPrt[4] = 0; // no oppPS , no CTWindow + + + + *p2pIELen+= (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + +/* SPEC 1.1 page 85*/ +unsigned char* add_Attr_device_info( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + struct wifi_mib *pmib=priv->pmib; + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 0 ; + unsigned short lentmp = 0 ; + //unsigned short u16_tmp = 0 ; + + thisAttrPrt[0] = TAG_P2P_DEVICE_INFO; + + /*fill attr len later*/ + thisAttrPrt+=3 ; // id(1) + len(2) + + /*P2P device address*/ + memcpy(thisAttrPrt , pmib->dot11OperationEntry.hwaddr , 6); + thisAttrPrt+=6 ; + attrlen+=6 ; + + /*config method*/ + memcpy(thisAttrPrt , (void *)&pmib->p2p_mib.p2p_wsc_config_method , 2); + thisAttrPrt+=2 ; + attrlen+=2 ; + + add_primarydevtype(priv,thisAttrPrt); + thisAttrPrt+=8 ; + attrlen+=8 ; + + /* number of second dev type*/ + thisAttrPrt[0]=0; + thisAttrPrt+=1 ; + attrlen+=1 ; + + + /* add Device name ; WSC TLV (2+2+N)*/ + lentmp = strlen( pmib->p2p_mib.p2p_device_name ); + thisAttrPrt = wsc_add_tlv(thisAttrPrt, TAG_DEVICE_NAME, + lentmp, pmib->p2p_mib.p2p_device_name); + attrlen+= (lentmp + 4); + + + /*Attribute len */ + lentmp = cpu_to_le16(attrlen); + memcpy(AttrPtr+1 ,(void *)&lentmp ,2); + + *p2pIELen += (attrlen+3); + //p2p_debug_out("device info content", AttrPtr, attrlen); + return thisAttrPrt; + +} + + + +/* SPEC 1.1 page 93*/ +unsigned char* add_Attr_group_info( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + + unsigned char* tmpPtr = NULL; + int per_desc_len = 0; + int idx ; + unsigned short attrlen = 0 ; + unsigned short attrlen2 = 0 ; + int tmplen = 0 ; + + P2P_DEBUG("\n"); + thisAttrPrt[0] = TAG_P2P_GROUP_INFO; + + thisAttrPrt +=3; + + for(idx=0 ; idx < MAX_P2P_CLIENT_MUN; idx++){ + if(priv->p2pPtr->assocPeers[idx].inuse){ + + per_desc_len=0; + tmpPtr = thisAttrPrt; // keep len addr + thisAttrPrt +=1; // skip len + + memcpy(thisAttrPrt,priv->p2pPtr->assocPeers[idx].devInfo.dev_address,6); + thisAttrPrt +=6; + per_desc_len +=6; + + memcpy(thisAttrPrt,priv->p2pPtr->assocPeers[idx].if_addr,6); + thisAttrPrt +=6; + per_desc_len +=6; + + thisAttrPrt[0]=priv->p2pPtr->assocPeers[idx].dev_cap ; // len ==1 + thisAttrPrt +=1; + per_desc_len +=1; + + memcpy(thisAttrPrt,&priv->p2pPtr->assocPeers[idx].devInfo.config_method,2); + thisAttrPrt +=2; + per_desc_len +=2; + + memcpy(thisAttrPrt,priv->p2pPtr->assocPeers[idx].devInfo.pri_dev_type,8); + thisAttrPrt +=8; + per_desc_len +=8; + + thisAttrPrt[0] = 0 ; // second dev type count == 0 + thisAttrPrt +=1; + per_desc_len +=1; + + + /*device name ; WSC TLV (2+2+N)*/ + tmplen = strlen(priv->p2pPtr->assocPeers[idx].devInfo.devname); + thisAttrPrt = wsc_add_tlv(thisAttrPrt, TAG_DEVICE_NAME, + tmplen, priv->p2pPtr->assocPeers[idx].devInfo.devname); + + per_desc_len += (2+2+tmplen); + + + tmpPtr[0] = per_desc_len; + attrlen += per_desc_len ; + + } + } + + + + attrlen2 = attrlen; + attrlen2 = cpu_to_le16(attrlen2); + memcpy(&AttrPtr[1] , (void *)&attrlen2 ,2); + + + *p2pIELen += (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + +/* SPEC 1.1 page 94*/ +unsigned char* add_Attr_group_id( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + + unsigned short attrlen = 0 ; + unsigned short attrlen2 = 0 ; + + thisAttrPrt[0] = TAG_P2P_GROUP_ID; + + + memcpy(&thisAttrPrt[3] , GET_MY_HWADDR , 6); + attrlen+=6; + + memcpy(&thisAttrPrt[9] , priv->p2pPtr->my_GO_ssid, priv->p2pPtr->my_GO_ssid_len); + attrlen += priv->p2pPtr->my_GO_ssid_len; + + attrlen2 = attrlen; + attrlen2 = cpu_to_le16(attrlen2); + memcpy(&thisAttrPrt[1] , (void *)&attrlen2 ,2); + + + *p2pIELen += (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + + +/* SPEC 1.1 page 94*/ +unsigned char* add_Attr_Target_group_id( struct rtl8192cd_priv *priv , + unsigned char* AttrPtr , unsigned char *p2pIELen , + unsigned char* tarssid , unsigned char* tardevaddr) +{ + + unsigned char* thisAttrPrt = AttrPtr; + + unsigned short attrlen = 0 ; + unsigned short attrlen2 = 0 ; + + thisAttrPrt[0] = TAG_P2P_GROUP_ID; + + + memcpy(&thisAttrPrt[3] , tardevaddr, 6); + attrlen+=6; + + memcpy(&thisAttrPrt[9] , tarssid, strlen(tarssid)); + attrlen += strlen(tarssid) ; + + attrlen2 = attrlen; + attrlen2 = cpu_to_le16(attrlen2); + memcpy(&thisAttrPrt[1] , (void *)&attrlen2 ,2); + + + *p2pIELen += (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + +/* SPEC 1.1 page 95*/ +unsigned char* add_Attr_operation_channel( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=5; + + thisAttrPrt[0] = TAG_OPERATION_CHANNEL; + + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + + + thisAttrPrt[3] = 'U'; + thisAttrPrt[4] = 'S'; + thisAttrPrt[5] = ' '; + + if(priv->pmib->p2p_mib.p2p_op_channel>=1 && priv->pmib->p2p_mib.p2p_op_channel<=14) + thisAttrPrt[6] = 81; + else if(priv->pmib->p2p_mib.p2p_op_channel>=36 && priv->pmib->p2p_mib.p2p_op_channel<=48) + thisAttrPrt[6] = 115; + else if(priv->pmib->p2p_mib.p2p_op_channel>=149 && priv->pmib->p2p_mib.p2p_op_channel<=165) + thisAttrPrt[6] = 124; + + thisAttrPrt[7] = priv->pmib->p2p_mib.p2p_op_channel; + + *p2pIELen+= (5+3); + thisAttrPrt += (5+3); + + return thisAttrPrt; + +} + +/* SPEC 1.1 page 96*/ +unsigned char* add_Attr_invitation_flag( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + P2P_DEBUG("TODO\n"); + return NULL; +} + + +/* SPEC 1.1 page 94*/ +unsigned char* add_Attr_interface( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=0; + unsigned short attrlen2=0; + thisAttrPrt[0] = TAG_P2P_INTERFACE; + + attrlen2 = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen2 ,2); + + + *p2pIELen+= (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + +#define BUILD_IE 0 // no meaning + + +int wsc_build_probe_rsp_ie(struct rtl8192cd_priv *priv , + unsigned char *data , unsigned short DEVICE_PASSWORD_ID) +{ + + + + unsigned char *pMsg; + unsigned char byteVal; + unsigned short shortVal; + unsigned char tmpbuf2[100]; + int len5; + + /*Element ID*/ + data[0] = WSC_IE_ID; + + /*OUI*/ + memcpy(&data[2], WSC_IE_OUI, 4); + pMsg = &data[2+4]; + + /*Version*/ + byteVal = WSC_VER; + pMsg = wsc_add_tlv(pMsg, TAG_VERSION, 1, (void *)&byteVal); + + + /*config state*/ + //fixed to AP mode + byteVal = 2; //configured + + pMsg = wsc_add_tlv(pMsg, TAG_SIMPLE_CONFIG_STATE, 1, (void *)&byteVal); + + // fixed to AP mode + byteVal = RSP_TYPE_AP; + pMsg = wsc_add_tlv(pMsg, TAG_RESPONSE_TYPE2, 1, (void *)&byteVal); + + /*UUID-E*/ + //pMsg = wsc_add_tlv(pMsg, TAG_UUID_E, UUID_LEN, (void *)priv->p2pPtr->uuid); + //pMsg = wsc_add_tlv(pMsg, TAG_MANUFACTURER, strlen(priv->p2pPtr->manufacturer), priv->p2pPtr->manufacturer); + //pMsg = wsc_add_tlv(pMsg, TAG_MODEL_NAME, strlen(priv->p2pPtr->model_name), priv->p2pPtr->model_name); + //pMsg = wsc_add_tlv(pMsg, TAG_MODEL_NUMBER, strlen(priv->p2pPtr->model_num), priv->p2pPtr->model_num); + //pMsg = wsc_add_tlv(pMsg, TAG_SERIAL_NUM, strlen(priv->p2pPtr->serial_num), priv->p2pPtr->serial_num); + + + /*----TAG_PRIMARY_DEVICE_TYPE -----start*/ + + if(OPMODE & WIFI_AP_STATE) + shortVal = P2P_device_category_id_AP; + else + shortVal = P2P_device_category_id_STA; + + memcpy(tmpbuf2, &shortVal, 2); + + memcpy(&tmpbuf2[2], WSC_IE_OUI, 4); + + shortVal = P2P_device_sub_category_id; + memcpy(&tmpbuf2[6], &shortVal, 2); + pMsg = wsc_add_tlv(pMsg, TAG_PRIMARY_DEVICE_TYPE, 8, (void *)tmpbuf2); + + /*----TAG_PRIMARY_DEVICE_TYPE -----end*/ + + /*device name */ + pMsg = wsc_add_tlv(pMsg, TAG_DEVICE_NAME, + strlen(priv->pmib->p2p_mib.p2p_device_name), priv->pmib->p2p_mib.p2p_device_name); + + /*config method*/ + pMsg = wsc_add_tlv(pMsg, TAG_CONFIG_METHODS, 2, (void *)&priv->pmib->p2p_mib.p2p_wsc_config_method); + + shortVal = DEVICE_PASSWORD_ID; + pMsg = wsc_add_tlv(pMsg, TAG_DEVICE_PASSWORD_ID, 2, &shortVal); + + /*Element Length*/ + len5 = (int)(((unsigned long)pMsg)-((unsigned long)data)) -2; + data[1] = (unsigned char)len5; + + return (len5+2); +} + + + +// (TLV , T(1),L(1)) +int p2p_build_probe_rsp_ie(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned char p2pIELen = 0; + unsigned char* thisAttrPrt = data; + + + thisAttrPrt[0]=_P2P_IE_; + + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + + /*ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen ,NULL); + + /*extended listen timing (OPTIONAL)*/ + + /*notice of absence ;shell only tx by GO*/ + + + /*ID13*/ + thisAttrPrt = add_Attr_device_info(priv, thisAttrPrt ,&p2pIELen); + + /*ID14 ,only include by GO*/ + if(P2PMODE == P2P_TMP_GO){ + thisAttrPrt = add_Attr_group_info(priv, thisAttrPrt ,&p2pIELen); + } + + + data[1]=p2pIELen; + + //p2p_debug_out("probe_rsp", data, p2pIELen+2); + + return p2pIELen+2; + +} + + +int p2p_build_probe_req_ie(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + unsigned char p2pIELen=0; + unsigned char* thisAttrPrt = data; + + thisAttrPrt[0]=_P2P_IE_; + + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen += 4; + thisAttrPrt += 4; + + + /*ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen ,NULL); + + /*ID3 ; for search spec address */ + if(!is_zero_ether_addr(priv->p2pPtr->spec_find_dev_addr)) + thisAttrPrt = add_Attr_device_info(priv, thisAttrPrt ,&p2pIELen); + + + /*ID6*/ + thisAttrPrt = add_Attr_listenChannel( priv, thisAttrPrt, &p2pIELen); + + + /*extended listen timing ;(OPTIONAL) no support now*/ + + + /*ID17 ; only include by GO*/ + if(P2PMODE ==P2P_TMP_GO){ + thisAttrPrt = add_Attr_operation_channel( priv, thisAttrPrt, &p2pIELen); + } + + + data[1]= p2pIELen; + + //p2p_debug_out("probe_req", data, p2pIELen+2); + + return p2pIELen+2; + +} + + + + + +int p2p_build_beacon_ie(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + unsigned char p2pIELen = 0; + unsigned char* thisAttrPrt = data; + + P2P_DEBUG("\n"); + thisAttrPrt[0]=_P2P_IE_; + + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + + /*ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen ,NULL); + + /*ID3*/ + thisAttrPrt = add_Attr_device_id(priv, thisAttrPrt ,&p2pIELen); + + data[1]=p2pIELen; + + //p2p_debug_out("beacon p2p IE", data, p2pIELen+2); + + return p2pIELen+2; + +} + +int p2p_build_assocReq_ie(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + unsigned char p2pIELen = 0; + unsigned char* thisAttrPrt = data; + + P2P_DEBUG("\n"); + thisAttrPrt[0]=_P2P_IE_; + + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + + /* ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen ,NULL); + + /* ID13 */ + thisAttrPrt = add_Attr_device_info(priv, thisAttrPrt ,&p2pIELen); + + data[1]=p2pIELen; + + p2p_debug_out("assoc p2p IE", data, p2pIELen+2); + + return p2pIELen+2; + +} + + +int p2p_build_assocRsp_ie(struct rtl8192cd_priv *priv, unsigned char *data + ,unsigned char status) +{ + + unsigned char p2pIELen = 0; + unsigned char* thisAttrPrt = data; + + P2P_DEBUG("\n"); + thisAttrPrt[0]=_P2P_IE_; + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + /*ID0*/ + thisAttrPrt = add_Attr_status(priv , thisAttrPrt, &p2pIELen ,status); + + data[1]=p2pIELen; + + p2p_debug_out("AssocRsp p2p IE", data, p2pIELen+2); + + return p2pIELen+2; + +} + + +int p2p_build_deassoc_ie(struct rtl8192cd_priv *priv, + unsigned char *data ,unsigned char reason) +{ + unsigned char p2pIELen = 0; + unsigned char* thisAttrPrt = data; + P2P_DEBUG("\n"); + thisAttrPrt[0]=_P2P_IE_; + thisAttrPrt+=2; + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + /*ID1*/ + thisAttrPrt = add_Attr_minor_reason( priv, thisAttrPrt, &p2pIELen ,reason); + + data[1]=p2pIELen; + //p2p_debug_out("disassoc p2p IE", data, p2pIELen+2); + return p2pIELen+2; + +} + + +#define HANDLE_P2P_ACTION_FRAME 0 // no meaning + +#define GO_mdoe_handle_P2P_action_frame 0 // no meaning + + +int p2p_issue_GO_discovery_req( + struct rtl8192cd_priv *priv , + unsigned char *da) +{ + + unsigned char *pbuf = NULL; + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_GO_dis_req_fail1; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_GO_dis_req_fail1; + + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + pbuf[0] = _VENDOR_ACTION_ID_; + memcpy(&pbuf[1],WFA_OUI_PLUS_TYPE,4); + pbuf[5] = P2P_GO_DISCOVERY; + + txinsn.fr_len += 6; + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + P2P_PRINT("\n"); + P2P_DEBUG("TX GO discovery Req success!!\n"); + MAC_PRINT(da); + + /*only expect will rx ack, that is all*/ + return SUCCESS; + } + +issue_GO_dis_req_fail1: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + + return FAIL; + + +} + + + + +/* page 68 */ +int p2p_issue_presence_rsp(struct rtl8192cd_priv *priv , unsigned char *da) +{ + + unsigned char *pbuf; + unsigned char *thisAttrPrt; + unsigned char p2pIELen = 0; + unsigned char *P2PIEstart=NULL; + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_presenceRsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_presenceRsp_fail; + + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + pbuf[0] = _VENDOR_ACTION_ID_; + memcpy(&pbuf[1],WFA_OUI_PLUS_TYPE,4); + pbuf[5] = P2P_PRESENCE_RSP; + pbuf[6] = priv->p2pPtr->presence_rx_dialog_token; + + + + /*P2P ID*/ + thisAttrPrt = pbuf + _P2P_ACTION_IE_OFFSET_; + p2pIELen = 0; + P2PIEstart = thisAttrPrt; + + thisAttrPrt[0] = P2P_IE_ID; + thisAttrPrt+=2; // ID + LEN + + /*P2P OUI+TYPE*/ + memcpy(thisAttrPrt, WFA_OUI_PLUS_TYPE, 4); + thisAttrPrt+=4; // OUI LEN + p2pIELen +=4; + + /*ID0*/ + thisAttrPrt = add_Attr_status(priv , thisAttrPrt, &p2pIELen ,P2P_SC_SUCCESS); + + + /*ID12*/ + thisAttrPrt = add_Attr_notice_of_absence(priv , thisAttrPrt, &p2pIELen ); + + P2PIEstart[1] = p2pIELen; + + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + P2P_PRINT("\n"); + P2P_DEBUG("TX Presence Rsp OK\n"); + MAC_PRINT(da); + return SUCCESS; + } + +issue_presenceRsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; + + +} + + +/* page 68 */ +void p2p_on_presence_req(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + + int tmplen=0; + unsigned char* tmpPtr=NULL; + + int foundP2PIE = 0; + unsigned char *P2PIEPtr = NULL ; + int P2PIElen=0; + unsigned char *p2p_sub_ie=NULL; + + priv->p2pPtr->presence_rx_dialog_token = pframe[6] ; + + //========================================================================== + /*get P2P IE*/ + tmpPtr = pframe + _P2P_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + tmpPtr = get_ie(tmpPtr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_ACTION_IE_OFFSET_ - tmplen); + + if(tmpPtr!=NULL){ + if (!memcmp(tmpPtr+2, WFA_OUI_PLUS_TYPE, 4)) { + P2PIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + P2PIEPtr = tmpPtr+6 ; + foundP2PIE = 1; + break; + } + }else{ + break ; + } + tmpPtr = tmpPtr + tmplen +2 ; + } + + if(foundP2PIE){ + p2p_sub_ie = p2p_search_tag(P2PIEPtr, P2PIElen, TAG_NOTICE_OF_ABSENCE, &tmplen); + if (p2p_sub_ie) { + //parse_p2p_NOA(priv, p2p_sub_ie, tmplen, GetSequence(pframe)); + // we don't support PS under GO now , do nothing + } + else { + P2P_DEBUG("can't found NOA IE\n"); + } + + }else{ + P2P_DEBUG("can't found P2P IE\n"); + } + //========================================================================= + //========================================================================== + p2p_issue_presence_rsp(priv,pfrinfo->sa); + + +} + + +// page 109 +int P2P_on_action(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + + unsigned char *pframe=NULL; + pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; //start of action frame content + + switch(pframe[5]){ + + case P2P_NOA: + P2P_PRINT("\n"); + P2P_DEBUG("RX P2P NOA\n"); + if(P2PMODE == P2P_CLIENT){ + + }else{ + P2P_DEBUG("but no under client mode\n"); + } + break; + case P2P_PRESENCE_REQ: + P2P_PRINT("\n"); + P2P_DEBUG("RX P2P Presence Req\n"); + if(P2PMODE == P2P_TMP_GO){ + p2p_on_presence_req(priv,pfrinfo); + }else{ + P2P_DEBUG("but no under GO mode\n"); + } + break; + case P2P_PRESENCE_RSP: + P2P_PRINT("\n"); + P2P_DEBUG("RX P2P Presence Rsp\n"); + if(P2PMODE == P2P_CLIENT){ + + }else{ + P2P_DEBUG("but no under client mode\n"); + } + break; + + case P2P_GO_DISCOVERY: + P2P_PRINT("\n"); + P2P_DEBUG("RX P2P GO DISCOVERY,just ack\n"); + break; + default: + P2P_DEBUG("!!! Unknow type p2p action \n"); + break; + } + return 0; +} + + +#define HANDLE_P2P_PUBLIC_ACTION_FRAME 0 // no meaning + + +int p2p_issue_device_discovery_rsp( + struct rtl8192cd_priv *priv , + unsigned char *da , unsigned char status) +{ + + unsigned char *pbuf = NULL; + unsigned char *IEStart=NULL; + unsigned char *thisAttrPrt=NULL; + unsigned char p2pIELen = 0; + DECLARE_TXINSN(txinsn); + P2P_DEBUG("\n"); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_dev_dis_rsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_dev_dis_rsp_fail; + + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_DEV_DISC_RESP; + pbuf[7] = priv->p2pPtr->dev_dis_req_dialog_token ; + + thisAttrPrt = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; + IEStart = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; //anchor + + thisAttrPrt = add_Attr_status(priv , thisAttrPrt, &p2pIELen ,status); + IEStart[1] = p2pIELen; + + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + P2P_PRINT("\n"); + P2P_DEBUG("TX Device Discovery Rsp success!!\n"); + MAC_PRINT(da); + return SUCCESS; + } + +issue_dev_dis_rsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + + return FAIL; + + +} + + +void p2p_on_device_discovery_req( + struct rtl8192cd_priv *priv , + struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + unsigned char *IEptr = NULL; + int tmplen = 0; + int foundP2PIE=0; + int p2pIElen = 0 ; + unsigned char *p2pIEPtr = NULL; + int idx; + struct p2p_device_peer *current_nego_peer=NULL; + + priv->p2pPtr->dev_dis_req_dialog_token = pframe[7]; + + /*-----------------------------get P2P IE(start)------------------------------*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + IEptr = get_ie(IEptr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr){ + if (!memcmp(IEptr+2, WFA_OUI_PLUS_TYPE, 4)) { + p2pIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + p2pIEPtr = IEptr+6 ; + foundP2PIE = 1; + break; + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + + if(foundP2PIE){ + + /*only GO need process P2P IE in provision req*/ + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + memset((void *)current_nego_peer , 0 ,sizeof(struct p2p_device_peer)); + + // ID15 + IEptr = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_P2P_GROUP_ID , &tmplen); + if(IEptr){ + parse_group_id(IEptr , tmplen ,current_nego_peer); + } + + if(memcmp(current_nego_peer->group_bssid , GET_MY_HWADDR ,6)){ + P2P_DEBUG("bssid no match!!\n"); + return; + } + + // ID3 + IEptr = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_DEVICE_ID , &tmplen); + if(IEptr){ + for(idx=0;idx<MAX_P2P_CLIENT_MUN ; idx++){ + if(!memcmp(priv->p2pPtr->assocPeers[idx].devInfo.dev_address,IEptr,6)){ + // some p2p device (no need assoc) search client that assoc with me + if(priv->p2pPtr->assocPeers[idx].dev_cap & CLIENT_DISCOVERY){ + + p2p_issue_GO_discovery_req(priv,IEptr); + // we assume client will ack me + p2p_issue_device_discovery_rsp(priv,pfrinfo->sa,P2P_SC_SUCCESS); + return ; + } + } + } + } + + } + /*-----------------------------get P2P IE(end)------------------------------*/ + p2p_issue_device_discovery_rsp(priv,pfrinfo->sa,P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE); + return ; + +} + + + +void p2p_on_device_discovery_rsp( + struct rtl8192cd_priv *priv , + struct rx_frinfo *pfrinfo) +{ + // TODO ? + return; +} + +int P2P_on_public_action(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + + if(memcmp(pfrinfo->da , GET_MY_HWADDR , 6)){ + return 0; + } + + if(pframe[6] ==P2P_GO_NEG_REQ || pframe[6] ==P2P_GO_NEG_RESP || pframe[6] ==P2P_GO_NEG_CONF){ + if(P2PMODE != P2P_DEVICE){ + P2P_DEBUG("GO / client don't process GO nego frames\n"); + MAC_PRINT(pfrinfo->sa); + return 0; + } + } + if(pframe[6] == P2P_PROV_DISC_REQ || pframe[6] == P2P_PROV_DISC_RSP){ + if(P2PMODE == P2P_CLIENT){ + P2P_DEBUG("client don't process provision req\n"); + return 0; + } + } + + + + switch(pframe[6]){ + + case P2P_GO_NEG_REQ: + P2P_PRINT("\n\n"); + P2P_DEBUG("RX GO Nogotiation Req\n"); + p2p_on_GO_nego_req(priv,pfrinfo); + break; + case P2P_GO_NEG_RESP: + P2P_PRINT("\n\n"); + P2P_DEBUG("RX GO Nogotiation Rsp\n"); + p2p_on_GO_nego_rsp(priv,pfrinfo); + break; + case P2P_GO_NEG_CONF: + P2P_PRINT("\n\n"); + P2P_DEBUG("RX GO Nogotiation Confirmation\n"); + p2p_on_GO_nego_conf(priv,pfrinfo); + break; + + case P2P_INVITATION_REQ: + P2P_DEBUG("P2P invitation Req\n"); + + break; + case P2P_INVITATION_RESP: + P2P_DEBUG("P2P invitation Rsp\n"); + + break; + + case P2P_DEV_DISC_REQ: + P2P_PRINT("\n\n"); + P2P_DEBUG("Rx Device Discoverability Req\n"); + + if(P2PMODE == P2P_TMP_GO) // process only under GO mode + p2p_on_device_discovery_req(priv,pfrinfo); + + break; + + case P2P_DEV_DISC_RESP: + + P2P_DEBUG("Device Discoverability Rsp\n"); + if(P2PMODE == P2P_CLIENT) // process only under client mode + p2p_on_device_discovery_rsp(priv,pfrinfo); + + break; + + case P2P_PROV_DISC_REQ: + P2P_PRINT("\n\n"); + P2P_DEBUG("RX Provision-Discovery Req\n"); + p2p_on_provision_req(priv,pfrinfo); + break; + case P2P_PROV_DISC_RSP: + P2P_PRINT("\n\n"); + P2P_DEBUG("Rx Provision-Discovery Rsp\n"); + p2p_on_provision_rsp(priv,pfrinfo); + + break; + default: + P2P_DEBUG("!!! Unknow type p2p public action \n"); + break; + } + + return 0; + +} + + +void P2P_1sec_timer(struct rtl8192cd_priv *priv) +{ + //static int p2p_1sec_count = 0; + + if(P2PMODE == P2P_DEVICE){ + + if(priv->p2pPtr->wait2listenState){ + priv->p2pPtr->wait2listenState -- ; + P2P_DEBUG("befor listen(%d)\n",priv->p2pPtr->wait2listenState); + if(priv->p2pPtr->wait2listenState == 0){ + P2P_DEBUG("enter listen\n"); + P2P_listen(priv,NULL); + } + } + + + + /*handle active send provision discovery req*/ + if(priv->p2pPtr->provision_req_timeout){ + priv->p2pPtr->provision_req_timeout--; + + if ((P2P_STATE == P2P_S_PROVI_WAIT_RSP) + && priv->p2pPtr->provision_req_timeout + && (priv->p2pPtr->provision_req_timeout%2 == 0)) + { + p2p_issue_provision_req(priv); + + }else + if((P2P_STATE == P2P_S_PROVI_WAIT_RSP) + && priv->p2pPtr->provision_req_timeout==0){ + + /*timeout ; back to listen mode*/ + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + + } + + /*handle active send provision discovery req*/ + if(priv->p2pPtr->go_nego_on_going_timeout>0){ + priv->p2pPtr->go_nego_on_going_timeout --; + + if(priv->p2pPtr->go_nego_on_going_timeout==0){ + priv->p2pPtr->go_nego_on_going = 0; + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + + if(P2P_STATE == P2P_S_NEGO_WAIT_RSP && priv->p2pPtr->go_nego_on_going){ + if(priv->p2pPtr->go_nego_on_going_timeout%2 == 0){ + p2p_issue_GO_nego_req(priv); + } + } + + } + + /*handle passive rx nego req flow*/ + if(P2P_STATE == P2P_S_NEGO_WAIT_CONF ){ + if(priv->p2pPtr->wait_nego_conf_timeout > 0 ){ + priv->p2pPtr->wait_nego_conf_timeout -- ; + if(priv->p2pPtr->wait_nego_conf_timeout == 0){ + + if(priv->p2pPtr->go_nego_on_going){ + P2P_DEBUG("unlock go_nego_ongoing\n\n"); + priv->p2pPtr->go_nego_on_going = 0; + } + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + } + } + + + } + else if(P2PMODE == P2P_PRE_CLIENT){ + if(priv->p2pPtr->pre_client_timeout >= 0 ){ + + priv->p2pPtr->pre_client_timeout -=1; + + if(priv->p2pPtr->pre_client_timeout == 0){ + P2P_DEBUG(" WPS process exceed %d seconds,back to device mode\n",WSC_MODE_WAIT_TIME); + P2P_STATE = P2P_S_back2dev ; + //p2pcmd_backtoDev(priv,NULL); will bring some error + } + } + } + else if(P2PMODE == P2P_PRE_GO){ + if(priv->p2pPtr->pre_go_timeout >= 0 ){ + priv->p2pPtr->pre_go_timeout -= 1; + if(priv->p2pPtr->pre_go_timeout == 0){ + P2P_DEBUG(" WPS process exceed %d seconds,back to device mode\n",WSC_MODE_WAIT_TIME); + P2P_STATE = P2P_S_back2dev ; + //p2pcmd_backtoDev(priv,NULL); + } + } + } + /* + else if(P2PMODE == P2P_TMP_GO){ + p2p_1sec_count++; + + if(p2p_1sec_count%10 == 0) // 10 seconds check once + P2P_chk_assoc_client(priv); + } + */ + + + return ; +} + + + +#define Active_TX_provision_req 0 // no meaning + +/*P2P discovery related functions*/ +int req_p2p_provision_req(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + struct provision_comm *provision_comm_ptr = (struct provision_comm *)data; + int idx; + int found; + + P2P_DEBUG("trigger from UI ; wsc method=%02x \n", + provision_comm_ptr->wsc_config_method); + + + priv->p2pPtr->requestor = 1; // add 0615 ;for iam dev ;target is GO + + memcpy(priv->p2pPtr->target_device_addr,provision_comm_ptr->dev_address,6); + priv->p2pPtr->target_device_channel = provision_comm_ptr->channel; + P2P_DEBUG("\n\ntarget dev on channel(%d)\n\n",priv->p2pPtr->target_device_channel); + + /*config method ; reference page38*/ + if(provision_comm_ptr->wsc_config_method == CONFIG_METHOD_PBC){ + + priv->p2pPtr->wsc_method_to_target_dev = CONFIG_METHOD_PBC ; + priv->p2pPtr->dev_passwd_to_tar_dev = PASS_ID_PB; /*for nego req use*/ + + }else if(provision_comm_ptr->wsc_config_method == CONFIG_METHOD_PIN + || provision_comm_ptr->wsc_config_method == CONFIG_METHOD_DISPLAY){ + + priv->p2pPtr->wsc_method_to_target_dev = CONFIG_METHOD_KEYPAD ; + priv->p2pPtr->dev_passwd_to_tar_dev = PASS_ID_REG; /*for nego req use*/ + + }else if(provision_comm_ptr->wsc_config_method == CONFIG_METHOD_KEYPAD){ + + priv->p2pPtr->wsc_method_to_target_dev = CONFIG_METHOD_DISPLAY ; + priv->p2pPtr->dev_passwd_to_tar_dev = PASS_ID_USER; /*for nego req use*/ + + } + + + found = 0; + for(idx=0;idx < priv->site_survey.count_backup; idx++){ + if(!memcmp(priv->site_survey.bss_backup[idx].p2paddress ,priv->p2pPtr->target_device_addr ,6)) + { + priv->p2pPtr->target_device_role = priv->site_survey.bss_backup[idx].p2prole ; + strcpy(priv->p2pPtr->target_device_ssid,priv->site_survey.bss_backup[idx].ssid); + found = 1; + } + } + + if(found==0){ + P2P_DEBUG("can't chk dev's role\n"); + return 0; + }else{ + P2P_DEBUG("Target role = %s \n",(priv->p2pPtr->target_device_role==R_P2P_GO?"GO":"dev")); + + } + + // 0329 + if(P2PMODE == P2P_CLIENT || P2PMODE == P2P_TMP_GO){ + P2P_DEBUG("client/GO don't send provision req\n"); + return 0; + } + + /*stay at target dev's channel and wait for provision Rsp*/ + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->p2pPtr->target_device_channel, priv->pshare->offset_2nd_chan); + P2P_DEBUG("Target device is under channel:%d\n",priv->p2pPtr->target_device_channel); + + + /*issue privision req*/ + if(p2p_issue_provision_req(priv)==SUCCESS){ //success + priv->p2pPtr->provision_req_timeout = 10; // per 2second ; total 5times (include first time) + }else{ + P2P_DEBUG("issue_provision_req fail\n"); + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + + return 0; +} + + + +int p2p_issue_provision_req(struct rtl8192cd_priv *priv ) +{ + + unsigned char *pbuf; + unsigned char randomX=0; + + unsigned char *IEStart; + unsigned char *thisAttrPrt; + unsigned char byteVal; + unsigned short shortVal; + unsigned char p2pIELen = 0; + unsigned char *P2PIEstart=NULL; + //P2P_DEBUG("\n"); + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_provosionreq_fail1; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_provosionreq_fail1; + + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_PROV_DISC_REQ; + + get_random_bytes(&randomX , 1); + + priv->p2pPtr->provision_tx_dialog_token = randomX; + + + + pbuf[7] = priv->p2pPtr->provision_tx_dialog_token; + + /*below start is WSC IE content*/ + + /*Element ID*/ + thisAttrPrt = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; + IEStart = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; //anchor + + + thisAttrPrt[0] = WSC_IE_ID; + thisAttrPrt+=2; // ID + LEN + //thisAttrPrt[1] = WSC IE length; + + /*OUI*/ + memcpy(thisAttrPrt, WSC_IE_OUI, 4); + thisAttrPrt += 4; // OUI LEN + + /*Version*/ + byteVal = WSC_VER; + thisAttrPrt = wsc_add_tlv(thisAttrPrt, TAG_VERSION, 1, (void *)&byteVal); + + shortVal = priv->p2pPtr->wsc_method_to_target_dev ; + thisAttrPrt = wsc_add_tlv(thisAttrPrt, TAG_CONFIG_METHODS, 2, (void *)&shortVal); + /*Element Length*/ + IEStart[1] = (int)(((unsigned long)thisAttrPrt)-((unsigned long)IEStart)) - 2; + + /*end of WSC IE content*/ + + if(priv->p2pPtr->target_device_role == R_P2P_GO){ + p2pIELen = 0; + P2PIEstart = thisAttrPrt; + thisAttrPrt[0] = P2P_IE_ID; + thisAttrPrt+=2; // ID + LEN + + /*P2P OUI+TYPE*/ + memcpy(thisAttrPrt, WFA_OUI_PLUS_TYPE, 4); + thisAttrPrt+=4; // OUI LEN + p2pIELen +=4; + + /*p2p device id ; ID2 */ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen,NULL); + + /*p2p group id ; ID13 */ + thisAttrPrt = add_Attr_device_info( priv, thisAttrPrt, &p2pIELen); + + /*p2p group id ; ID15 */ + thisAttrPrt = add_Attr_Target_group_id( priv, thisAttrPrt, + &p2pIELen,priv->p2pPtr->target_device_ssid,priv->p2pPtr->target_device_addr); + + P2PIEstart[1] = p2pIELen; + } + + + + + + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), priv->p2pPtr->target_device_addr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + P2P_PRINT("\n\n"); + P2P_DEBUG("TX Provision_Req OK (My method=%02x)\n",shortVal); + MAC_PRINT(priv->p2pPtr->target_device_addr); + + + P2P_STATE = P2P_S_PROVI_WAIT_RSP; + return SUCCESS; + } + +issue_provosionreq_fail1: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; + + +} + + + +void p2p_on_provision_rsp(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + + int tmplen=0; + int foundWSCIE = 0; + unsigned short wscMethod=0; + + unsigned char* tmpPtr=NULL; + unsigned char *wscIEPtr = NULL ; + int wscIElen=0; + + if(pframe[7] != priv->p2pPtr->provision_tx_dialog_token ) + P2P_DEBUG("provision_req dialog_token=%d , no match\n",priv->p2pPtr->provision_rx_dialog_token); + + //========================================================================== + //========================================================================== + /*get WSC IE*/ + tmpPtr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + tmpPtr = get_ie(tmpPtr, _WPS_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(tmpPtr!=NULL){ + if (!memcmp(tmpPtr+2, WSC_IE_OUI, 4)) { + wscIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + wscIEPtr = tmpPtr+6 ; + foundWSCIE = 1; + break; + } + }else{ + break ; + } + tmpPtr = tmpPtr + tmplen +2 ; + } + + if(foundWSCIE){ + tmpPtr = search_wsc_tag(wscIEPtr, TAG_CONFIG_METHODS, wscIElen, &tmplen); + if(tmpPtr){ + wscMethod = *(unsigned short*)tmpPtr; + if(wscMethod == priv->p2pPtr->wsc_method_to_target_dev){ + priv->p2pPtr->wsc_method_match = 1; + P2P_DEBUG("wsc method=%02x match!!!\n",wscMethod); + }else{ + P2P_DEBUG("wsc method=%02x no match!!!\n\n\n",wscMethod); + priv->p2pPtr->wsc_method_match = 0; + } + } + }else{ + P2P_DEBUG("\n\n no include TAG_CONFIG_METHODS\n\n"); + } + //========================================================================= + //========================================================================== + + priv->p2pPtr->provision_req_timeout = 0; + + // go back listen state + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + + +} + +#define PASSIVE_RX_provision_req 6768 // no meaning + +void p2p_on_provision_req(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + int tmplen=0; + unsigned short wscMethod=0; + unsigned char* IEptr=NULL; + unsigned char *p2pIEPtr = NULL; + int p2pIElen=0; + int foundP2PIE = 0; + + unsigned char *wscIE=NULL ; // for ReAssembly + int wscIElen=0; + int foundWSCIE = 0; + + /*when i am GO will use it*/ + struct p2p_device_peer *current_nego_peer=NULL; + unsigned char *ptrtmp=NULL; + int tag_len; + + priv->p2pPtr->provision_rx_dialog_token = pframe[7]; + //P2P_DEBUG("\n"); + + /*-----------------------------get WSC IE------------------------------*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + IEptr = get_ie(IEptr, _WPS_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WSC_IE_OUI, 4)) { + wscIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + wscIE = IEptr+6 ; + foundWSCIE = 1; + break; + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + if(foundWSCIE){ + IEptr = search_wsc_tag(wscIE, TAG_CONFIG_METHODS, wscIElen, (int *)&tmplen); + wscMethod = *(unsigned short*)IEptr; + if(wscMethod){ + priv->p2pPtr->wsc_method_from_target_dev = wscMethod; + P2P_DEBUG("\n WSC Method:%02x\n\n",wscMethod); + } + } + /*-----------------------------get WSC IE------------------------------*/ + + + /*-----------------------------get P2P IE(start)------------------------------*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + IEptr = get_ie(IEptr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WFA_OUI_PLUS_TYPE, 4)) { + p2pIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + p2pIEPtr = IEptr+6 ; + foundP2PIE = 1; + break; + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + + if(foundP2PIE){ + + /*only GO need process P2P IE in provision req*/ + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + memset((void *)current_nego_peer , 0 ,sizeof(struct p2p_device_peer)); + + /*ID2*/ + ptrtmp = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_P2P_CAPABILITY , &tag_len); + if(ptrtmp){ + current_nego_peer->dev_capab = ptrtmp[0]; + current_nego_peer->group_capab= ptrtmp[1]; + } + + if(ptrtmp[1] & BIT(0)){ + priv->p2pPtr->target_device_role = R_P2P_GO; + P2P_DEBUG("\n target dev should't GO role ,chk!!!\n"); + }else{ + priv->p2pPtr->target_device_role = R_P2P_DEVICE; + } + + if(P2PMODE == P2P_TMP_GO){ + /*ID13*/ + ptrtmp = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_P2P_DEVICE_INFO , &tag_len); + if(ptrtmp){ + parse_device_info(ptrtmp , tag_len ,¤t_nego_peer->peer_device_info); + } + + /*ID15*/ + ptrtmp = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_P2P_GROUP_ID , &tag_len); + if(ptrtmp){ + parse_group_id(ptrtmp , tag_len ,current_nego_peer); + } + + } + } + /*-----------------------------get P2P IE(end)------------------------------*/ + + + /*for indicate UI that have provision Req*/ + P2P_EVENT_INDICATE = P2P_EVENT_RX_PROVI_REQ ; + + //P2P_DEBUG("\n"); + + + p2p_issue_provision_rsp(priv , pfrinfo->sa); + + priv->p2pPtr->requestor = 0; // add 0615 ;for i am GO ;target is dev + +} + + + +int p2p_issue_provision_rsp(struct rtl8192cd_priv *priv, unsigned char *da) +{ + + + unsigned char *pbuf; + + unsigned char *wscStart; + unsigned char *wscPtr; + unsigned char byteVal; + unsigned short shortVal; + DECLARE_TXINSN(txinsn); + P2P_DEBUG("\n"); + //P2P_PRINT("\n\n"); + //P2P_DEBUG("TX Provision RSP \n\n"); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_provosionrsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_provosionrsp_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + //P2P_DEBUG("\n"); + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_PROV_DISC_RSP; + pbuf[7] = priv->p2pPtr->provision_rx_dialog_token; + + + + /*below start is WSC IE content*/ + + /*Element ID*/ + wscPtr = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; + wscStart = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; //anchor + + + wscPtr[0] = WSC_IE_ID; + + wscPtr+=2; // ID + LEN + + + /*OUI*/ + memcpy(wscPtr, WSC_IE_OUI, 4); + wscPtr+=4; // OUI LEN + + /*Version*/ + byteVal = WSC_VER; + wscPtr = wsc_add_tlv(wscPtr, TAG_VERSION, 1, (void *)&byteVal); + + + /*config method*/ + shortVal = priv->p2pPtr->wsc_method_from_target_dev; + wscPtr = wsc_add_tlv(wscPtr, TAG_CONFIG_METHODS, 2, (void *)&shortVal); + //P2P_DEBUG("wsc method=%02x\n",priv->p2pPtr->wsc_method_from_target_dev); + + /*Element Length*/ + wscStart[1] = (int)(((unsigned long)wscPtr)-((unsigned long)wscStart)) - 2; + + txinsn.fr_len += ((int)(((unsigned long)wscPtr)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + //P2P_DEBUG("\n"); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + //P2P_DEBUG("\n"); + return SUCCESS; + } + +issue_provosionrsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; +} + +#define ACTIVE_TX_GO_NEGO_REQ 0 // no meaning + + +/* plus remember to move */ +int req_p2p_wsc_confirm(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + struct __p2p_wsc_confirm *wsc_confirm_ptr = (struct __p2p_wsc_confirm *)data; + + struct p2p_device_peer wsc_peer_t; + + + // for debug + P2P_DEBUG("pincode=[%s]\n",wsc_confirm_ptr->pincode); + P2P_DEBUG("wscMethod=[%02x], from ",wsc_confirm_ptr->wsc_config_method); + MAC_PRINT(wsc_confirm_ptr->dev_address); + // for debug + + /*get PIN code*/ + strcpy(priv->p2pPtr->target_dev_pin_code,wsc_confirm_ptr->pincode); + + if(priv->p2pPtr->wsc_method_match==0){ + P2P_DEBUG("Passive mode,Confirm wsc method\n"); + if(wsc_confirm_ptr->wsc_config_method == CONFIG_METHOD_PBC){ + P2P_DEBUG("PBC,Confirm!!\n"); + priv->p2pPtr->passivemode_pbc_trigger_flag = 1; + } + } + + + + if(priv->p2pPtr->target_device_role == R_P2P_DEVICE && P2PMODE==P2P_DEVICE){ + /* 1)target is dev and i am dev & 2) i issue this nego req*/ + + P2P_DEBUG("\n Target is dev ; i am dev \n"); + /*Use priv->p2pPtr->wsc_method_match for identify + i am active send nego req or not */ + + if(priv->p2pPtr->wsc_method_match==0){ + P2P_DEBUG("Passive mode,Confirm wsc method\n"); + return 0; + }else{ + P2P_DEBUG("Ative mode,Prepare send Go Nego Req!!\n"); + priv->p2pPtr->wsc_method_match=0; + } + + if(memcmp(priv->p2pPtr->target_device_addr ,wsc_confirm_ptr->dev_address ,6 )){ + P2P_DEBUG("dev addr no match, chk!!!!\n\n\n"); + return 0; + } + if(is_zero_ether_addr(wsc_confirm_ptr->dev_address )){ + P2P_DEBUG("dev addr is zero !!!\n\n\n"); + return 0; + } + + /* switch channel to target dev's channel first */ + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->p2pPtr->target_device_channel, priv->pshare->offset_2nd_chan); + + //P2P_DEBUG("Rx wsc confirm ; start Tx nego Req\n"); + if(p2p_issue_GO_nego_req(priv)==SUCCESS){ + priv->p2pPtr->go_nego_on_going = 1; // and P2P_STATE = P2P_S_NEGO_WAIT_RSP; + priv->p2pPtr->go_nego_on_going_timeout = 10 ; + + } + + } + else if(priv->p2pPtr->target_device_role == R_P2P_DEVICE && P2PMODE==P2P_TMP_GO){ + + P2P_DEBUG("\n\ntarget is device and i am GO \n"); + /*target is device and i am GO , wsc method and pin etc is rdy ,*/ + memset(&wsc_peer_t , 0 , sizeof(struct p2p_device_peer)); + + if(priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_KEYPAD){ + + /*target will display ; use Target's PIN*/ + wsc_peer_t.device_pass_id = PASS_ID_REG; + + }else if(priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_PIN || + priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_DISPLAY){ + + /*target will keyin pin ; use My PIN */ + wsc_peer_t.device_pass_id = PASS_ID_USER; + + }else if(priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_PBC){ + + /*PBC*/ + wsc_peer_t.device_pass_id = PASS_ID_PB; + + + }else{ + P2P_DEBUG("unknow type !!!\n\n"); + } + + + + /*indicate wscd satrt WPS procotol*/ + indicate_wscd(priv, MODE_AP_PROXY_REGISTRAR , priv->p2pPtr->go_PSK , &wsc_peer_t); + + + } + else if(priv->p2pPtr->target_device_role == R_P2P_GO && P2PMODE == P2P_DEVICE){ + + /*target is GO and i am device*/ + + P2P_DEBUG("\n\ntarget is GO and i am device \n"); + P2P_DEBUG("\n change to Pre-client and start WPS ,\n"); + p2p_as_preClient(priv); + + memset(&wsc_peer_t , 0 , sizeof(struct p2p_device_peer)); + if(priv->p2pPtr->wsc_method_to_target_dev == CONFIG_METHOD_KEYPAD){ + /*tell target to keyin ; use My PIN */ + wsc_peer_t.device_pass_id = PASS_ID_USER; + + }else if(priv->p2pPtr->wsc_method_to_target_dev==CONFIG_METHOD_PIN || + priv->p2pPtr->wsc_method_to_target_dev==CONFIG_METHOD_DISPLAY){ + + /*tell target to display ; use Target PIN */ + wsc_peer_t.device_pass_id = PASS_ID_REG; + + + }else if(priv->p2pPtr->wsc_method_to_target_dev==CONFIG_METHOD_PBC){ + /* PBC */ + wsc_peer_t.device_pass_id = PASS_ID_PB; + + }else{ + P2P_DEBUG("unknow type !!!\n\n"); + } + + /* indicate wscd change mode and start WPS under client mode */ + indicate_wscd(priv, MODE_CLIENT_UNCONFIG , NULL, &wsc_peer_t); + priv->p2pPtr->pre_client_timeout = WSC_MODE_WAIT_TIME ; + + + } + else{ + P2P_DEBUG("unknow type chk!!!\n\n"); + } + + return 0; +} + +int p2p_issue_GO_nego_req(struct rtl8192cd_priv *priv) +{ + + + unsigned char *pbuf; + unsigned char *thisAttrPrt=NULL; + unsigned char p2pIELen = 0; + + unsigned char *tmpPtr=NULL; + unsigned short shortVal; + unsigned char StrTmp2[40]; + unsigned char My_tie_break; + unsigned char randomX; + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_nego_req_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_nego_req_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_GO_NEG_REQ; + + get_random_bytes(&randomX , 1); + priv->p2pPtr->go_nego_tx_dialog_token = randomX; + pbuf[7] = randomX; + + /* ===== WSC IE content =========*/ + shortVal = priv->p2pPtr->dev_passwd_to_tar_dev; + + if(priv->p2pPtr->dev_passwd_to_tar_dev == PASS_ID_REG){ + P2P_DEBUG("use My PIN \n"); + strcpy(StrTmp2,"PASS_ID_REG"); + }else if(priv->p2pPtr->dev_passwd_to_tar_dev == PASS_ID_USER){ + P2P_DEBUG("use Target's PIN \n"); + strcpy(StrTmp2,"PASS_ID_USER"); + }else if(priv->p2pPtr->dev_passwd_to_tar_dev == PASS_ID_PB){ + strcpy(StrTmp2,"PASS_ID_PB"); + }else{ + P2P_DEBUG("unknow type !!!\n\n"); + } + + + priv->p2pPtr->wsc_ie_req_mun = wsc_build_probe_rsp_ie(priv, priv->p2pPtr->wsc_ie_req ,shortVal); + + memcpy(&pbuf[8] , priv->p2pPtr->wsc_ie_req , priv->p2pPtr->wsc_ie_req_mun); + //p2p_debug_out("GO Nego Req ; WSC IE", priv->p2pPtr->wsc_ie_req ,priv->p2pPtr->wsc_ie_req_mun); + /* ===== WSC IE content =========*/ + + /* ===== P2P IE content =========*/ + thisAttrPrt = pbuf + 8 + priv->p2pPtr->wsc_ie_req_mun ; + tmpPtr = pbuf + 8 + priv->p2pPtr->wsc_ie_req_mun ; + thisAttrPrt[0]=_P2P_IE_; + + /*fill p2p ie total length later(size == 2bytes)*/ + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + + /*id2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen,NULL); + + + get_random_bytes(&My_tie_break , 1); + My_tie_break %= 2; + P2P_DEBUG("(Nego req)Method type:%s,tie_break=%d\n",StrTmp2,My_tie_break); + /* id4*/ + thisAttrPrt = add_Attr_GO_intent( priv, thisAttrPrt, &p2pIELen ,My_tie_break); + + /* id5*/ + thisAttrPrt = add_Attr_configration_timeout( priv, thisAttrPrt, &p2pIELen ,1); + + /* id6*/ + thisAttrPrt = add_Attr_listenChannel( priv, thisAttrPrt, &p2pIELen ); + + /* id8*/ + thisAttrPrt = add_Attr_extended_listen_timing( priv, thisAttrPrt, &p2pIELen ,65535,65535); + + + /* id9*/ + thisAttrPrt = add_Attr_intended_interface( priv, thisAttrPrt, &p2pIELen); + + /* id11*/ + thisAttrPrt = add_Attr_channel_list( priv, thisAttrPrt, &p2pIELen); + + /* id13 */ + thisAttrPrt = add_Attr_device_info( priv, thisAttrPrt, &p2pIELen); + + + /* id17*/ + thisAttrPrt = add_Attr_operation_channel( priv, thisAttrPrt, &p2pIELen); + + + + tmpPtr[1]=p2pIELen; + + //p2p_debug_out("GO Nego Req ; P2P IE", tmpPtr,p2pIELen ); + + + /* ===== total LEN =========*/ + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), priv->p2pPtr->target_device_addr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + P2P_PRINT("\n"); + P2P_DEBUG(" Tx GO nego Req OK\n\n"); + P2P_STATE = P2P_S_NEGO_WAIT_RSP; + return SUCCESS; + } + +issue_nego_req_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; + +} + + + + + + +void p2p_on_GO_nego_rsp(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + unsigned char *ptrtmp = NULL; + unsigned char* IEptr=NULL; + int tmplen=0; + unsigned char *p2pIE; + int p2pIElen=0; + int foundP2PIE = 0; + + unsigned char *wscIE; + int wscIElen=0; + int foundWSCIE = 0; + int tag_len; + struct p2p_device_peer *current_nego_peer=NULL; + + if(priv->p2pPtr->go_nego_on_going && P2P_STATE == P2P_S_NEGO_WAIT_RSP){ + + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + memset(current_nego_peer , 0 , sizeof(struct p2p_device_peer)); + + + }else{ + if(P2P_STATE != P2P_S_NEGO_WAIT_RSP) + P2P_DEBUG("rx nego rsp ; but not at P2P_S_NEGO_WAIT_RSP\n"); + return ; + } + + current_nego_peer->dialog_token = pframe[7]; + if(pframe[7] != priv->p2pPtr->go_nego_tx_dialog_token){ + P2P_DEBUG("go_nego_tx_dialog_token no match!!\n\n\n"); + } + + memcpy(current_nego_peer->dev_addr,pfrinfo->sa,6); + //========================================================================== + /*get WSC IE*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + IEptr = get_ie(IEptr, _WPS_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WSC_IE_OUI, 4)) { + wscIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + wscIE = IEptr+6 ; + foundWSCIE = 1; + break; + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + //========================================================================== + if(foundWSCIE){ + ptrtmp = search_wsc_tag(wscIE, TAG_DEVICE_PASSWORD_ID, wscIElen, &tag_len); + if(ptrtmp){ + current_nego_peer->device_pass_id = *(unsigned short *)ptrtmp; + } + }else{ + current_nego_peer->status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; + P2P_DEBUG("\n\n no include DEVICE PASS ID\n\n"); + } + //========================================================================== + + //========================================================================== + /*get P2P IE*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + for(;;){ + + IEptr = get_ie(IEptr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WFA_OUI_PLUS_TYPE, 4)) { + p2pIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + p2pIE = IEptr+6 ; + foundP2PIE = 1; + //p2p_debug_out("P2P IE", p2pIE, p2pIElen); + break; + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + + if(foundP2PIE){ + + // ID0 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_STATUE , &tag_len); + if(ptrtmp){ + current_nego_peer->status = ptrtmp[0]; + if(current_nego_peer->status){ + P2P_DEBUG("nego fail!! report from target ; status = ( %d ) \n", + current_nego_peer->status); + + P2P_STATE = P2P_S_LISTEN; + return; + } + + } + + // ID2 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_CAPABILITY , &tag_len); + if(ptrtmp){ + current_nego_peer->dev_capab = ptrtmp[0]; + current_nego_peer->group_capab= ptrtmp[1]; + } + + // ID4 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_GROUP_OWNER_INTENT , &tag_len); + if(ptrtmp){ + current_nego_peer->intent_value = ptrtmp[0]>>1; + current_nego_peer->TieBreak = ptrtmp[0]&0x01; + //P2P_DEBUG("Intent T(%d),M(%d) \n", + // current_nego_peer->intent_value,priv->pmib->p2p_mib.p2p_intent); + } + + // ID5 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_CONFIG_TIMEOUT , &tag_len); + if(ptrtmp){ + current_nego_peer->go_config_timeout = ptrtmp[0]; + current_nego_peer->client_config_timeout = ptrtmp[1]; + } + + + + // ID9 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_INTEN_P2P_INTERFACE_ADDR , &tag_len); + if(ptrtmp){ + memcpy(current_nego_peer->p2p_interface_address , ptrtmp ,6); + } + + // ID11 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_CHANNEL_LIST , &tag_len); + if(ptrtmp){ + parse_channel_list(ptrtmp , tag_len ,current_nego_peer); + } + + // ID13 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_DEVICE_INFO , &tag_len); + if(ptrtmp){ + parse_device_info(ptrtmp , tag_len ,¤t_nego_peer->peer_device_info); + } + + // ID15 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_GROUP_ID , &tag_len); + if(ptrtmp){ + //P2P_DEBUG("TAG_P2P_GROUP_ID; len = %d \n",tag_len); + parse_group_id(ptrtmp , tag_len ,current_nego_peer); + } + + // ID17 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_OPERATION_CHANNEL , &tag_len); + if(ptrtmp){ + memcpy(current_nego_peer->op_country , ptrtmp ,3); + current_nego_peer->op_country[3]='\0'; + current_nego_peer->op_class = ptrtmp[3]; + current_nego_peer->op_channel = ptrtmp[4]; + } + + } + + /*determine who is GO/Client by intent value*/ + if((priv->pmib->p2p_mib.p2p_intent==15) + && current_nego_peer->intent_value ==15){ + current_nego_peer->status = P2P_SC_FAIL_BOTH_GO_INTENT_15; + } + if(priv->pmib->p2p_mib.p2p_intent > current_nego_peer->intent_value){ + current_nego_peer->role = R_P2P_CLIENT; + }else if((priv->pmib->p2p_mib.p2p_intent == current_nego_peer->intent_value)){ + + if(current_nego_peer->TieBreak){ + current_nego_peer->role = R_P2P_GO; + }else{ + current_nego_peer->role = R_P2P_CLIENT; + } + }else if(priv->pmib->p2p_mib.p2p_intent < current_nego_peer->intent_value){ + + current_nego_peer->role = R_P2P_GO; + } + + p2p_issue_GO_nego_conf(priv,current_nego_peer); + +} + + +int p2p_issue_GO_nego_conf(struct rtl8192cd_priv *priv, + struct p2p_device_peer *current_nego_peer) +{ + unsigned char *pbuf; + unsigned char *thisAttrPrt=NULL; + unsigned char p2pIELen = 0; + unsigned char *tmpPtr=NULL; + DECLARE_TXINSN(txinsn); + + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_nego_conf_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_nego_conf_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_GO_NEG_CONF; + pbuf[7] = current_nego_peer->dialog_token; + + /* ===== no need include WSC IE content =========*/ + + + /* ===== P2P IE content =========*/ + thisAttrPrt = pbuf + 8 + priv->p2pPtr->wsc_ie_rsp_mun ; + tmpPtr = pbuf + 8 + priv->p2pPtr->wsc_ie_rsp_mun ; + thisAttrPrt[0]=_P2P_IE_; + + /*fill p2p ie total length later(size == 2bytes)*/ + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + /*ID0*/ + thisAttrPrt = add_Attr_status(priv , thisAttrPrt, &p2pIELen ,current_nego_peer->status); + + /*ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen,current_nego_peer); + + /* ID17*/ + if(current_nego_peer->role == R_P2P_CLIENT) // i am GO + thisAttrPrt = add_Attr_operation_channel( priv, thisAttrPrt, &p2pIELen); + + /* ID11*/ + thisAttrPrt = add_Attr_channel_list( priv, thisAttrPrt, &p2pIELen); + + /*ID15*/ + if(current_nego_peer->role == R_P2P_CLIENT) // i am GO + thisAttrPrt = add_Attr_group_id( priv, thisAttrPrt, &p2pIELen); + + + tmpPtr[1]=p2pIELen; + + //p2p_debug_out("p2p IE (nego Rsp)", tmpPtr,p2pIELen ); + + + /* ===== total LEN =========*/ + //txinsn.fr_len += priv->p2pPtr->wsc_ie_tmp_mun; + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), current_nego_peer->dev_addr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + P2P_DEBUG(" TX GO nego Conf ,OK!\n"); + + if(priv->p2pPtr->go_nego_on_going){ + priv->p2pPtr->go_nego_on_going = 0; + } + + priv->p2pPtr->requestor = 1; + if(current_nego_peer->role == R_P2P_CLIENT){ + + /*target dev will as client ; i will work as pre-GO*/ + P2P_DEBUG(" As Pre-GO role for %d seconds\n\n",WSC_MODE_WAIT_TIME); + p2p_as_GO(priv,P2P_PRE_GO); + + /*indicate wscd change mode ; and satrt WPS procotol*/ + indicate_wscd(priv, MODE_AP_PROXY_REGISTRAR , priv->p2pPtr->go_PSK , current_nego_peer); + priv->p2pPtr->pre_go_timeout = WSC_MODE_WAIT_TIME ; + + } + else if(current_nego_peer->role == R_P2P_GO){ + + P2P_DEBUG(" As Pre-client role for %d seconds\n\n",WSC_MODE_WAIT_TIME); + p2p_as_preClient(priv); + + /*indicate wscd change mode ; and satrt WPS procotol*/ + indicate_wscd(priv, WPS_MODE_NO_CHANGE , NULL, current_nego_peer); + priv->p2pPtr->pre_client_timeout = WSC_MODE_WAIT_TIME ; + } + else{ + P2P_DEBUG("unknow type chk!!\n"); + } + + return SUCCESS ; + } + + + + +issue_nego_conf_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; +} + + +#define PASSIVE_RX_GO_NEGO_REQ 0 // no meaning + + + + +void p2p_on_GO_nego_req(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + unsigned char *ptrtmp = NULL; + unsigned char* IEptr=NULL; + int tmplen=0; + + unsigned char p2pIE[256]; + int p2pIElen=0; + int foundP2PIE = 0; + + //unsigned char wscIE[256]; + //int wscIElen=0; + int foundWSCIE = 0; + int tag_len; + struct p2p_device_peer *current_nego_peer=NULL; + + //P2P_DEBUG("\n\n"); + //P2P_STATE = P2P_S_NEGO_RX_REQ ; + + if(priv->p2pPtr->go_nego_on_going){ + if(!memcmp(pfrinfo->sa , priv->p2pPtr->ongoing_nego_peer.dev_addr,6)){ + + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + memset(current_nego_peer , 0 , sizeof(struct p2p_device_peer)); + + }else{ + current_nego_peer = &priv->p2pPtr->others_nego_tar_device ; + current_nego_peer->status = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; + } + + }else{ + priv->p2pPtr->go_nego_on_going = 1; + priv->p2pPtr->go_nego_on_going_timeout = 15; + //P2P_DEBUG("GO_nego with\n"); + //MAC_PRINT(pfrinfo->sa); + + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + memset(current_nego_peer , 0 , sizeof(struct p2p_device_peer)); + } + + current_nego_peer->dialog_token = pframe[7]; + memcpy(current_nego_peer->dev_addr,pfrinfo->sa,6); + //========================================================================== + /*get WSC IE*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + IEptr = get_ie(IEptr, _WPS_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WSC_IE_OUI, 4)) { + //wscIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + //memcpy(wscIE, IEptr+6, wscIElen); + foundWSCIE = 1; + break; + //p2p_debug_out("WSC IE", wscIE, wscIElen); + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + //========================================================================== + if(foundWSCIE){ + ptrtmp = search_wsc_tag(IEptr+6, TAG_DEVICE_PASSWORD_ID, tmplen-4, &tag_len); + if(ptrtmp){ + current_nego_peer->device_pass_id = *(unsigned short *)ptrtmp; + //P2P_DEBUG("\n\nDEVICE PASS ID:%02x\n\n",current_nego_peer->device_pass_id); + } + }else{ + current_nego_peer->status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; + + } + //========================================================================== + + //========================================================================== + /*get P2P IE*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + for(;;){ + + IEptr = get_ie(IEptr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WFA_OUI_PLUS_TYPE, 4)) { + + p2pIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + memcpy(p2pIE, IEptr+6, p2pIElen); + foundP2PIE = 1; + break; + //p2p_debug_out("P2P IE", p2pIE, p2pIElen); + + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + + if(foundP2PIE){ + + // ID2 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_CAPABILITY , &tag_len); + if(ptrtmp){ + current_nego_peer->dev_capab = ptrtmp[0]; + current_nego_peer->group_capab= ptrtmp[1]; + } + + // ID4 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_GROUP_OWNER_INTENT , &tag_len); + if(ptrtmp){ + current_nego_peer->intent_value = ptrtmp[0]>>1; + current_nego_peer->TieBreak = ptrtmp[0]&0x01; + P2P_DEBUG("Intent T(%d),M(%d),Tie break=%d \n", + current_nego_peer->intent_value, + priv->pmib->p2p_mib.p2p_intent, + current_nego_peer->TieBreak); + + } + + // ID6 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_LISTEN_CHANNEL , &tag_len); + if(ptrtmp){ + + current_nego_peer->operating_class = ptrtmp[3]; + current_nego_peer->listen_channle = ptrtmp[4]; + } + + // ID9 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_INTEN_P2P_INTERFACE_ADDR , &tag_len); + if(ptrtmp){ + memcpy(current_nego_peer->p2p_interface_address , ptrtmp ,6); + } + + // ID11 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_CHANNEL_LIST , &tag_len); + if(ptrtmp){ + parse_channel_list(ptrtmp , tag_len ,current_nego_peer); + } + + // ID13 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_DEVICE_INFO , &tag_len); + if(ptrtmp){ + parse_device_info(ptrtmp , tag_len ,&(current_nego_peer->peer_device_info)); + } + + // ID17 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_OPERATION_CHANNEL , &tag_len); + if(ptrtmp){ + memcpy(current_nego_peer->op_country , ptrtmp ,3); + current_nego_peer->op_country[3]='\0'; + current_nego_peer->op_class = ptrtmp[3]; + current_nego_peer->op_channel = ptrtmp[4]; + } + + } + + p2p_issue_GO_nego_rsp(priv,current_nego_peer); + +} + +int p2p_issue_GO_nego_rsp(struct rtl8192cd_priv *priv, + struct p2p_device_peer *current_nego_peer) +{ + + + unsigned char *pbuf; + unsigned char *thisAttrPrt=NULL; + unsigned char p2pIELen = 0; + unsigned char *tmpPtr=NULL; + unsigned short shortVal=0; + int MyRole=0; // GO:1 client:2 + int My_tie_break=0; + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_nego_rsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_nego_rsp_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_GO_NEG_RESP; + pbuf[7] = current_nego_peer->dialog_token; + + /* ===== WSC IE content =========*/ + + if(current_nego_peer->device_pass_id == PASS_ID_USER){ + //P2P_DEBUG("use My PIN \n"); + shortVal = PASS_ID_REG; + }else if(current_nego_peer->device_pass_id == PASS_ID_REG){ + //P2P_DEBUG("use Target's PIN \n"); + shortVal = PASS_ID_USER; + }else if(current_nego_peer->device_pass_id == PASS_ID_PB){ + + shortVal = PASS_ID_PB; + }else{ + P2P_DEBUG("unknow type\n"); + } + + priv->p2pPtr->wsc_ie_rsp_mun = wsc_build_probe_rsp_ie(priv, priv->p2pPtr->wsc_ie_rsp ,shortVal); + + memcpy(&pbuf[8] , priv->p2pPtr->wsc_ie_rsp , priv->p2pPtr->wsc_ie_rsp_mun); + + //p2p_debug_out("wsc ie at nego rsp", priv->p2pPtr->wsc_ie_tmp,priv->p2pPtr->wsc_ie_tmp_mun); + /* ===== WSC IE content =========*/ + + + /*determine who is GO/Client by intent value---start*/ + + + if((priv->pmib->p2p_mib.p2p_intent==15) + && current_nego_peer->intent_value ==15){ + current_nego_peer->status = P2P_SC_FAIL_BOTH_GO_INTENT_15; + } + if(priv->pmib->p2p_mib.p2p_intent > current_nego_peer->intent_value){ + MyRole = R_P2P_GO; + current_nego_peer->role = R_P2P_CLIENT; + }else if((priv->pmib->p2p_mib.p2p_intent == current_nego_peer->intent_value)){ + + if(current_nego_peer->TieBreak){ + MyRole = R_P2P_CLIENT; + My_tie_break=0; + current_nego_peer->role = R_P2P_GO; + }else{ + MyRole = R_P2P_GO; + My_tie_break=1; + current_nego_peer->role = R_P2P_CLIENT; + } + }else if(priv->pmib->p2p_mib.p2p_intent < current_nego_peer->intent_value){ + MyRole = R_P2P_CLIENT; + current_nego_peer->role = R_P2P_GO; + } + + /*determine who is GO/Client by intent value---end */ + + + + /* ===== P2P IE content =========*/ + thisAttrPrt = pbuf + 8 + priv->p2pPtr->wsc_ie_rsp_mun ; + tmpPtr = pbuf + 8 + priv->p2pPtr->wsc_ie_rsp_mun ; + thisAttrPrt[0]=_P2P_IE_; + + /*fill p2p ie total length later(size == 2bytes)*/ + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + + /*ID0*/ + if(current_nego_peer->device_pass_id == PASS_ID_REG){ /*use Target's PIN code*/ + if(is_zero_pin_code(priv->p2pPtr->target_dev_pin_code)){ + P2P_DEBUG("PIN not ready yet\n"); + current_nego_peer->status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; + } + }else + if(current_nego_peer->device_pass_id == PASS_ID_PB){ /*Target will use PBC*/ + if(priv->p2pPtr->passivemode_pbc_trigger_flag == 0){ + P2P_DEBUG("PBC not allow yet\n"); + current_nego_peer->status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; + } + /*else{ + // clean PBC flag + P2P_DEBUG("clean PBC flag\n"); + priv->p2pPtr->passivemode_pbc_trigger_flag = 0; + } + */ + } + + + thisAttrPrt = add_Attr_status(priv , thisAttrPrt, &p2pIELen ,current_nego_peer->status); + + + /*ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen,current_nego_peer); + + + /* ID4*/ + thisAttrPrt = add_Attr_GO_intent( priv, thisAttrPrt, &p2pIELen ,My_tie_break); + + /* ID5*/ + thisAttrPrt = add_Attr_configration_timeout( priv, thisAttrPrt, &p2pIELen ,MyRole); + + /* ID17*/ + if(MyRole == R_P2P_GO) + thisAttrPrt = add_Attr_operation_channel( priv, thisAttrPrt, &p2pIELen); + + /* ID9*/ + thisAttrPrt = add_Attr_intended_interface( priv, thisAttrPrt, &p2pIELen); + + /* ID11*/ + thisAttrPrt = add_Attr_channel_list( priv, thisAttrPrt, &p2pIELen); + + /* ID13*/ + thisAttrPrt = add_Attr_device_info( priv, thisAttrPrt, &p2pIELen); + + /* ID15*/ + if(MyRole == R_P2P_GO) + thisAttrPrt = add_Attr_group_id( priv, thisAttrPrt, &p2pIELen); + + + tmpPtr[1]=p2pIELen; + + //p2p_debug_out("p2p IE (nego Rsp)", tmpPtr,p2pIELen ); + + + /* ===== total LEN =========*/ + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), current_nego_peer->dev_addr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + // send rsp ok ;wait conf + P2P_STATE = P2P_S_NEGO_WAIT_CONF ; + priv->p2pPtr->wait_nego_conf_timeout = 2; + + P2P_DEBUG("TX GO nego Rsp success\n"); + if(current_nego_peer->status!=P2P_SC_SUCCESS){ + + P2P_DEBUG("Intent T(%d),M(%d)\n", + current_nego_peer->intent_value , priv->pmib->p2p_mib.p2p_intent); + + //P2P_DEBUG("My Role:%s\n",(MyRole==R_P2P_GO?"GO":"Client")); + + if(priv->p2pPtr->go_nego_on_going){ + P2P_DEBUG("status = %d\n",current_nego_peer->status); + P2P_DEBUG("unlock go_nego_ongoing\n\n"); + priv->p2pPtr->go_nego_on_going = 0; + } + + } + + return SUCCESS; + } + else{ + P2P_DEBUG("tx nego rsp fail\n"); + } + +issue_nego_rsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; +} + +void p2p_on_GO_nego_conf(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + int tmplen=0; + unsigned char *ptrtmp = NULL; + unsigned char* IEptr=NULL; + unsigned char p2pIE[256]; + int p2pIElen=0; + int foundP2PIE = 0; + int tag_len; + + struct p2p_device_peer *current_nego_peer=NULL; + P2P_PRINT("\n"); + P2P_DEBUG("RX GO_nego_conf\n\n"); + + if(priv->p2pPtr->go_nego_on_going){ + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + }else{ + P2P_DEBUG("no GO nego on going , drop confirm\n\n"); + return ; + } + + if(P2P_STATE != P2P_S_NEGO_WAIT_CONF){ + P2P_DEBUG("rx conf but state is wrong!!\n"); + return ; + }else{ + P2P_STATE = P2P_S_LISTEN; + } + + if(current_nego_peer == NULL){ + P2P_DEBUG("\n"); + return ; + } + + /* check dialog_token */ + if(current_nego_peer->dialog_token != pframe[7]){ + P2P_DEBUG("dialog_token no match!!!\n\n"); + return ; + } + + //========================================================================== + /*get P2P IE*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + for(;;){ + + IEptr = get_ie(IEptr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WFA_OUI_PLUS_TYPE, 4)) { + + p2pIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + memcpy(p2pIE, IEptr+6, p2pIElen); + foundP2PIE = 1; + //p2p_debug_out("P2P IE", p2pIE, p2pIElen); + break; + + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + + //========================================================================== + if(foundP2PIE){ + + // ID0 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_STATUE , &tag_len); + if(ptrtmp){ + current_nego_peer->status = ptrtmp[0]; + if(current_nego_peer->status){ + P2P_DEBUG("nego fail!! report from target ; status = ( %d ) \n\n", + current_nego_peer->status); + return; + } + + } + + // ID2 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_CAPABILITY , &tag_len); + if(ptrtmp){ + current_nego_peer->dev_capab = ptrtmp[0]; + current_nego_peer->group_capab= ptrtmp[1]; + } + + // ID17 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_OPERATION_CHANNEL , &tag_len); + if(ptrtmp){ + memcpy(current_nego_peer->op_country , ptrtmp ,3); + current_nego_peer->op_country[3]='\0'; + current_nego_peer->op_class = ptrtmp[3]; + current_nego_peer->op_channel = ptrtmp[4]; + } + + // ID11 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_CHANNEL_LIST , &tag_len); + if(ptrtmp){ + parse_channel_list(ptrtmp , tag_len ,current_nego_peer); + } + + // ID15 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_GROUP_ID , &tag_len); + if(ptrtmp){ + //P2P_DEBUG("TAG_P2P_GROUP_ID; len = %d \n",tag_len); + parse_group_id(ptrtmp , tag_len ,current_nego_peer); + } + + + } + + + priv->p2pPtr->requestor = 0; + + // nego success + if(current_nego_peer->status == P2P_SC_SUCCESS) + { + + if(current_nego_peer->role == R_P2P_CLIENT){ + + /*target dev will as client ; i will work as pre-GO*/ + P2P_DEBUG(" As Pre-GO role for %d seconds\n\n",WSC_MODE_WAIT_TIME); + p2p_as_GO(priv,P2P_PRE_GO); + + // indicate wscd change mode ; and satrt WPS procotol + indicate_wscd(priv, MODE_AP_PROXY_REGISTRAR , priv->p2pPtr->go_PSK , current_nego_peer); + priv->p2pPtr->pre_go_timeout = WSC_MODE_WAIT_TIME ; + + } + else if(current_nego_peer->role == R_P2P_GO){ + /*i will work as pre-client*/ + P2P_DEBUG(" As Pre-client role for %d seconds\n\n",WSC_MODE_WAIT_TIME); + p2p_as_preClient(priv); + + // indicate wscd change mode and start WPS + + /*start to wsc under enrollee mode*/ + indicate_wscd(priv, MODE_CLIENT_UNCONFIG , NULL, current_nego_peer); + priv->p2pPtr->pre_client_timeout = WSC_MODE_WAIT_TIME ; + } + else{ + P2P_DEBUG("unknow type chk!!\n"); + } + + } + + if(priv->p2pPtr->go_nego_on_going){ + + P2P_DEBUG("unlock go_nego_on_going (Rx nego conf) \n\n\n"); + priv->p2pPtr->go_nego_on_going = 0; + //priv->p2pPtr->go_nego_on_going_timeout = 0; // 2011-0615 add + + } + //========================================================================== + return ; + +} + + +#define EVENT_TO_WSCD 6768 // no meaning + +void stop_wscd(struct rtl8192cd_priv *priv ,unsigned char *data) +{ + + DOT11_WSC_PIN_IND wsc_ind; + + if( priv->p2pPtr->wps_is_ongoing != 1) + return; + + wsc_ind.EventId = DOT11_EVENT_WSC_STOP; + wsc_ind.IsMoreEvent = 0; + + P2P_DEBUG("\n"); + + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, + (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_PIN_IND)); + event_indicate(priv, NULL, 0); + priv->p2pPtr->wps_is_ongoing = 0; +} + +void indicate_wscd(struct rtl8192cd_priv *priv , unsigned char mode , + unsigned char *PSK ,struct p2p_device_peer *nego_peer_xx) +{ + + + struct _DOT11_P2P_INDICATE_WSC p2p_2_wsc_event_t; + memset(&p2p_2_wsc_event_t , 0 ,sizeof(struct _DOT11_P2P_INDICATE_WSC)); + + p2p_2_wsc_event_t.EventId = DOT11_EVENT_WSC_SWITCH_MODE; // 100 + p2p_2_wsc_event_t.IsMoreEvent = 0; + + p2p_2_wsc_event_t.modeSwitch = mode; + P2P_DEBUG(" switch wps mode to %d\n",p2p_2_wsc_event_t.modeSwitch); + + if(PSK){ + strcpy(p2p_2_wsc_event_t.network_key , PSK); + P2P_DEBUG(" psk=%s\n",p2p_2_wsc_event_t.network_key); + }else{ + p2p_2_wsc_event_t.network_key[0]='\0'; + } + + // gossid is use under i am go + strcpy(p2p_2_wsc_event_t.gossid, priv->p2pPtr->my_GO_ssid); + //P2P_DEBUG("gossid=%s\n",p2p_2_wsc_event_t.gossid); + + + /* If p2p_2_wsc_event_t.trigger_method no assigned , + wscd only change mode , will not trigger WPS protocol*/ + if(nego_peer_xx){ + + if(nego_peer_xx->device_pass_id == PASS_ID_USER){ + + // use My PIN + P2P_DEBUG(" use My PIN\n"); + p2p_2_wsc_event_t.whosPINuse = USE_MY_PIN ; + p2p_2_wsc_event_t.trigger_method = P2P_PIN_METHOD; + priv->p2pPtr->wps_is_ongoing = 1; + + }else if(nego_peer_xx->device_pass_id == PASS_ID_REG){ + + // use Target's PIN + P2P_DEBUG(" use Target's PIN=%s\n",priv->p2pPtr->target_dev_pin_code); + p2p_2_wsc_event_t.whosPINuse = USE_TARGET_PIN; + p2p_2_wsc_event_t.trigger_method = P2P_PIN_METHOD; + strcpy(p2p_2_wsc_event_t.PINCode, priv->p2pPtr->target_dev_pin_code); + priv->p2pPtr->wps_is_ongoing = 1; + + }else if(nego_peer_xx->device_pass_id == PASS_ID_PB){ + + P2P_DEBUG(" use PBC\n"); + p2p_2_wsc_event_t.trigger_method = P2P_PBC_METHOD; + priv->p2pPtr->wps_is_ongoing = 1; + + if( priv->p2pPtr->passivemode_pbc_trigger_flag ) + P2P_DEBUG("clean PBC flag\n"); + priv->p2pPtr->passivemode_pbc_trigger_flag = 0; + + }else{ + P2P_DEBUG(" unknow type chk!!\n"); + } + + } + + if(priv->p2pPtr->requestor){ + P2P_DEBUG(" i am requestor\n"); + p2p_2_wsc_event_t.requestor = 1; + }else{ + P2P_DEBUG(" i am not requestor\n"); + } + + + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, + (UINT8 *)&p2p_2_wsc_event_t, sizeof(struct _DOT11_P2P_INDICATE_WSC)); + + event_indicate(priv, NULL, 0); + +} + + +#define GROUP_SESSION_HANDLE 6768 // no meaning + + + + + +void P2P_chk_assoc_client(struct rtl8192cd_priv *priv) +{ + + int idx = 0; + int found = 0; + int needrebuild = 0; + struct list_head *phead, *plist; + struct stat_info *pstat; + + P2P_DEBUG("\n"); + + if( priv->assoc_num == 0){ + for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){ + if(priv->p2pPtr->assocPeers[idx].inuse){ + + memset(priv->p2pPtr->assocPeers, 0 ,sizeof(struct assoc_peer)*MAX_P2P_CLIENT_MUN); + + priv->p2pPtr->p2p_probe_rsp_ie_len = + p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie); + + return; + } + } + } + + phead = &priv->asoc_list; + if (!netif_running(priv->dev) || list_empty(phead)) { + return; + } + + + for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){ + if(priv->p2pPtr->assocPeers[idx].inuse){ + + found = 0; + + phead = &priv->asoc_list; + plist = phead->next; + while (plist != phead) { + + pstat = list_entry(plist, struct stat_info, asoc_list); + + if(!memcmp(pstat->hwaddr ,priv->p2pPtr->assocPeers[idx].if_addr ,6)) + found = 1; + + plist = plist->next; + } + + if(found==0){ + priv->p2pPtr->assocPeers[idx].inuse = 0; + needrebuild = 1; + } + + } + } + + /*rebuild GO's probe_rsp content ,build Probe_Rsp P2P IE info */ + if(needrebuild){ + priv->p2pPtr->p2p_probe_rsp_ie_len = + p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie); + } + + return; + +} + +void P2P_client_on_beacon(struct rtl8192cd_priv *priv, + unsigned char *IEaddr, unsigned int IElen, int seq) +{ + unsigned char* p2p_sub_ie=NULL; + int tag_len = 0; + + + // ID 12 + p2p_sub_ie = p2p_search_tag(IEaddr, IElen, TAG_NOTICE_OF_ABSENCE, &tag_len); + if (p2p_sub_ie) { + //P2P_DEBUG("\n"); + parse_p2p_NOA(priv, p2p_sub_ie, tag_len, seq); + } + else { + //P2P_DEBUG("No TAG_NOTICE_OF_ABSENCE in beacon\n"); + p2p_cancel_noa(priv); + } + return; +} + + + +int P2P_filter_manage_ap(struct rtl8192cd_priv *priv, + unsigned char *IEaddr, unsigned int IElen ) +{ + unsigned char* p2p_sub_ie=NULL; + int tag_len = 0; + // ID10 + p2p_sub_ie = p2p_search_tag(IEaddr , IElen , TAG_P2P_MANAGEABILITY , &tag_len); + + if(p2p_sub_ie){ + P2P_DEBUG("\n"); + if(p2p_sub_ie[0] & BIT(0)) + return 1; + else + return 0; + } + + return 0; + +} + + +void P2P_on_assoc_req(struct rtl8192cd_priv *priv, + unsigned char *IEaddr, unsigned int IElen , unsigned char *sa) +{ + unsigned char* p2p_sub_ie; + int tag_len = 0; + int idx = 0; + int found = 0; + + P2P_DEBUG("\n"); + + for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){ + if(priv->p2pPtr->assocPeers[idx].inuse){ + if(!memcmp(priv->p2pPtr->assocPeers[idx].if_addr,sa,6)){ + found = 1; + break; + } + } + if(priv->p2pPtr->assocPeers[idx].inuse == 0){ + priv->p2pPtr->assocPeers[idx].inuse = 1; + found = 1; + break; + } + } + + if(found==0){ + // second changes + P2P_chk_assoc_client(priv); + + for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){ + if(priv->p2pPtr->assocPeers[idx].inuse == 0){ + priv->p2pPtr->assocPeers[idx].inuse = 1; + found = 1; + break; + } + } + if(found==0){ + P2P_DEBUG("assoc peer full!!,chk!!\n\n\n"); + return; + } + } + + // ID 2 + p2p_sub_ie = p2p_search_tag(IEaddr , IElen , TAG_P2P_CAPABILITY , &tag_len); + if(p2p_sub_ie){ + priv->p2pPtr->assocPeers[idx].dev_cap = p2p_sub_ie[0]; + priv->p2pPtr->assocPeers[idx].group_cap = p2p_sub_ie[1]; + }else{ + + P2P_DEBUG("can't search TAG_P2P_CAPABILITY\n\n"); + return; + } + + + // ID 13 + p2p_sub_ie = p2p_search_tag(IEaddr , IElen , TAG_P2P_DEVICE_INFO , &tag_len); + if(p2p_sub_ie){ + parse_device_info(p2p_sub_ie,tag_len, &(priv->p2pPtr->assocPeers[idx].devInfo)); + }else{ + P2P_DEBUG("can't search TAG_P2P_DEVICE_INFO\n\n"); + return; + } + + memcpy(priv->p2pPtr->assocPeers[idx].if_addr ,sa, 6); + + /*rebuild GO's probe_rsp content ,build Probe_Rsp P2P IE info */ + priv->p2pPtr->p2p_probe_rsp_ie_len = p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie); + + return; + +} + + + +void P2P_on_assoc_rsp(struct rtl8192cd_priv *priv,unsigned char *sa) +{ + P2P_DEBUG("\n"); + memset(priv->p2pPtr->assocPeers,0,sizeof(struct assoc_peer)*MAX_P2P_CLIENT_MUN); + priv->p2pPtr->assocPeers[0].inuse = 1; + memcpy(priv->p2pPtr->assocPeers[0].if_addr,sa,6); + return; + +} + + +void P2P_on_probe_req( + struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, + unsigned char *IEaddr, unsigned int IElen ) +{ + + unsigned char *pframe= get_pframe(pfrinfo); + unsigned char* pData=NULL; + int tag_len ; + + //P2P_PRINT("p2p probe_req from:"); + //MAC_PRINT(GetAddr2Ptr(pframe)); + + /* DA is broadcast addr or my p2p device addr + (default use MY-HW-ADDR as p2p device addrree)*/ + if( memcmp(GetAddr1Ptr(pframe), "\xff\xff\xff\xff\xff\xff", 6) + && memcmp(GetAddr1Ptr(pframe), GET_MY_HWADDR, 6)) + { + P2P_DEBUG("DA mismatch!\n"); + return; + } + + /*chk BSSID(ADDR3) is broadcast MacAddr */ + if( memcmp(GetAddr3Ptr(pframe), "\xff\xff\xff\xff\xff\xff", 6) ){ + P2P_DEBUG("A3 mismatch!\n"); + return; + } + + /*ID3*/ + pData = p2p_search_tag(IEaddr , IElen , TAG_DEVICE_ID , &tag_len); + if(pData){ + if( memcmp(pData , GET_MY_HWADDR , 6)){ + /*this p2p IE include spec device addr for search , and target is not me*/ + return; + } + } + + #if 0 + /*get WSC IE --start*/ + ptmp = pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_; lentmp = 0; + for (;;) + { + ptmp = get_ie(ptmp, _WPS_IE_, &lentmp, (int)(pfrinfo->pktlen - (ptmp - pframe))); + if (ptmp != NULL) { + if (!memcmp(ptmp+2, WSC_IE_OUI, 4)) { + wsc_ie_found = 1; + break; + } + } + else + break; + + ptmp = ptmp + lentmp + 2; + } + if(wsc_ie_found){ + + /*find TAG_PRIMARY_DEVICE_TYPE*/ + pData = search_wsc_tag(ptmp+6, TAG_PRIMARY_DEVICE_TYPE, lentmp-4, &tag_len); + if (pData == NULL) { + P2P_DEBUG("Can't find TAG_PRIMARY_DEVICE_TYPE\n"); + } + } + /*get WSC IE --end*/ + #endif + + if(P2PMODE ==P2P_TMP_GO){ + priv->p2pPtr->probe_rps_to_p2p_dev = 1; + P2P_DEBUG("GO Rsp"); + MAC_PRINT(GetAddr2Ptr(pframe)); + issue_probersp(priv, GetAddr2Ptr(pframe), SSID, SSID_LEN, FALSE); + }else{ + issue_probersp(priv, GetAddr2Ptr(pframe), P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN, FALSE); + } + +} + + +void p2p_client_remove(struct rtl8192cd_priv *priv , struct stat_info *pstat ) +{ + + int idx=0; + if(P2PMODE!=P2P_TMP_GO){ + return; + } + P2P_DEBUG("\n"); + + for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){ + if(priv->p2pPtr->assocPeers[idx].inuse){ + if(!memcmp(priv->p2pPtr->assocPeers[idx].if_addr,pstat->hwaddr,6)){ + priv->p2pPtr->assocPeers[idx].inuse=0; + priv->p2pPtr->p2p_probe_rsp_ie_len = + p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie); + + break; + } + } + } + + return; +} + +#define SEPARATE4 0 // no meaning + +void p2p_init(struct rtl8192cd_priv *priv ) +{ + if(priv->p2pPtr == NULL){ + P2P_DEBUG("first init kmalloc for p2p interface!\n"); + priv->p2pPtr = (struct p2p_context*)kmalloc(sizeof(struct p2p_context),GFP_ATOMIC); + if(priv->p2pPtr == NULL){ + P2P_DEBUG("\n\n!!!! chk here!!!\n\n\n\n\n"); + }else{ + memset(priv->p2pPtr,0,sizeof(struct p2p_context)); + } + } + + P2P_DEBUG("\n"); + + //memset(priv->p2pPtr->target_dev_pin_code,0,9); + + /*build beacon P2P IE */ + if(P2PMODE == P2P_TMP_GO || P2PMODE == P2P_PRE_GO ){ + memset(priv->p2pPtr->assocPeers,0,sizeof(struct assoc_peer)*MAX_P2P_CLIENT_MUN); + } + + /*build Probe_Rsp P2P IE info */ + priv->p2pPtr->p2p_probe_rsp_ie_len = + p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie); + + + /*build Probe_Req P2P IE info */ + priv->p2pPtr->p2p_probe_req_ie_len = + p2p_build_probe_req_ie(priv,priv->p2pPtr->p2p_probe_req_ie); + + + + /*build wsc IE info ;only use under P2P device mode ; under GO(AP) mode it should be + fill by wscd , so take care!!*/ + if(P2PMODE == P2P_DEVICE){ + priv->pmib->wscEntry.probe_rsp_ielen = + wsc_build_probe_rsp_ie(priv, priv->pmib->wscEntry.probe_rsp_ie , PASS_ID_REG); + } + + if(P2PMODE == P2P_CLIENT){ + /*build assocReq P2P IE */ + priv->p2pPtr->p2p_assocReq_ie_len + = p2p_build_assocReq_ie(priv,priv->p2pPtr->p2p_assocReq_ie); + + /*build disAssoc P2P IE */ + priv->p2pPtr->p2p_disass_ie_len + = p2p_build_deassoc_ie(priv,priv->p2pPtr->p2p_disass_ie , minor_case1); + + } + + /*build beacon P2P IE */ + if(P2PMODE == P2P_TMP_GO || P2PMODE == P2P_PRE_GO ){ + + priv->p2pPtr->p2p_beacon_ie_len = + p2p_build_beacon_ie(priv,priv->p2pPtr->p2p_beacon_ie); + + priv->p2pPtr->p2p_assoc_RspIe_len = + p2p_build_assocRsp_ie(priv,priv->p2pPtr->p2p_assoc_RspIe,P2P_SC_SUCCESS); + + } + + + + if(priv->p2pPtr->rdyinit){ + + }else{ + /* do only once ,first one*/ + + /*generate my GO profile*/ + + generate_GO_ssid(priv); + + //generate_GO_PSK(priv); + strcpy(priv->p2pPtr->go_PSK,"12345678"); // for easy test + + + /*channel list*/ + init_channel_list(priv); + + } + + if(priv->p2pPtr->rdyinit==0){ + priv->p2pPtr->rdyinit=1; + } + + //P2P_show_status(priv,NULL); + if(P2PMODE == P2P_DEVICE){ + priv->p2pPtr->wait2listenState = 2; // enter listen mode by 1sec timer + } + +} + + + +int p2pcmd_enable(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + if(P2PMODE == P2P_DEVICE){ + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + return 0; +} + +int P2P_listen(struct rtl8192cd_priv* priv,unsigned char* data) +{ + + /*check if listen channel is in social channel*/ + if(priv->pmib->p2p_mib.p2p_listen_channel !=1 + && priv->pmib->p2p_mib.p2p_listen_channel!=6 + && priv->pmib->p2p_mib.p2p_listen_channel!=11) + { + P2P_DEBUG("invaild listen chn(%d) ; set chn to default =6\n",priv->pmib->p2p_mib.p2p_listen_channel); + priv->pmib->p2p_mib.p2p_listen_channel = 6; + } + + P2P_DEBUG("listen;on chn(%d)\n",priv->pmib->p2p_mib.p2p_listen_channel); + stay_on_2G(priv); + + P2P_STATE = P2P_S_LISTEN; + + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + + SwChnl(priv, priv->pmib->p2p_mib.p2p_listen_channel, priv->pshare->offset_2nd_chan); + + // process receive probe_req frame + + // for assigned how long i will stay in listen state + if(P2P_DISCOVERY){ + unsigned char randomX=0; + get_random_bytes(&randomX , 1); + randomX%=3; + randomX+=1; // 1<= randomX <=3 + if (timer_pending(&priv->p2p_listen_timer_t)) + del_timer_sync(&priv->p2p_listen_timer_t); + + mod_timer(&priv->p2p_listen_timer_t, jiffies + RTL_MILISECONDS_TO_JIFFIES(randomX*100)); + } + + return 0; +} + +void P2P_listen_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + // now is on discovery procedure ; go to next state + if(P2P_DISCOVERY && (P2P_STATE == P2P_S_LISTEN)){ + P2P_DISCOVERY +=1 ; + P2P_PRINT("\n"); + P2P_DEBUG("find phase(%d)\n",P2P_DISCOVERY-1); + P2P_search(priv,NULL); + } + + return ; +} + +/*P2P discovery related functions*/ + +void p2p_search_timer(unsigned long task_priv){ + + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + + + //P2P_DEBUG("\n"); + + if (priv->ss_req_ongoing) + { + if (timer_pending(&priv->p2p_search_timer_t)) + del_timer_sync(&priv->p2p_search_timer_t); + + //P2P_DEBUG("site survey is going...\n"); + mod_timer(&priv->p2p_search_timer_t, jiffies + RTL_SECONDS_TO_JIFFIES(1)); + }else{ + + int idx ; + + /*restore below two parameter*/ + if(priv->back_available_chnl_num){ + + for(idx=0;idx<76;idx++) + priv->available_chnl[idx]=priv->back_available_chnl[idx]; + + priv->available_chnl_num = priv->back_available_chnl_num; + priv->back_available_chnl_num = 0 ; + + } + + + // now is on discovery procedure ; (SCAN) is done go to next state (Listen) + if(P2P_DISCOVERY && (P2P_STATE == P2P_S_SCAN)){ + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + return; + } + + // now is on discovery procedure ; (SEARCH) is done go to next state (Listen) + if(P2P_DISCOVERY && (P2P_STATE == P2P_S_SEARCH)){ + P2P_DEBUG("find phase run (%d) (search,end)\n",P2P_DISCOVERY-1) ; + if(P2P_DISCOVERY == 4) { + + P2P_DISCOVERY = 0; + + p2p_show_ss_res(priv); + + P2P_DEBUG("P2P_discovery completed,back to "); + + if(P2PMODE==P2P_CLIENT){ + P2P_PRINT("client connected mode\n"); + P2P_STATE = P2P_S_CLIENT_CONNECTED_DHCPC_done; + }else{ + P2P_PRINT("device listen\n"); + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + + }else{ + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + } + + if((P2P_STATE == P2P_S_SEARCH) || (P2P_STATE == P2P_S_SCAN)){ + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + + } + +} + +int P2P_scan(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + P2P_STATE = P2P_S_SCAN; + priv->ss_ssidlen = 0; + P2P_DEBUG("start_clnt_ss, ...\n"); + priv->ss_req_ongoing = 1; + start_clnt_ss(priv); + + if (timer_pending(&priv->p2p_search_timer_t)) + del_timer_sync(&priv->p2p_search_timer_t); + + mod_timer(&priv->p2p_search_timer_t, jiffies + RTL_SECONDS_TO_JIFFIES(2)); + + return 0; +} + + +int P2P_search(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + + int idx=0; + + P2P_STATE = P2P_S_SEARCH; + + /*copy below two parameter*/ + for(idx=0;idx<76;idx++) + priv->back_available_chnl[idx]=priv->available_chnl[idx]; + + priv->back_available_chnl_num = priv->available_chnl_num; + + /*copy below two parameter-end*/ + priv->available_chnl[0]=1; + priv->available_chnl[1]=6; + priv->available_chnl[2]=11; + priv->available_chnl_num=3; + + + + priv->ss_ssidlen = 0; + P2P_DEBUG("p2p search ...\n"); + priv->ss_req_ongoing = 1; + start_clnt_ss(priv); + + + if (timer_pending(&priv->p2p_search_timer_t)) + del_timer_sync(&priv->p2p_search_timer_t); + + mod_timer(&priv->p2p_search_timer_t, jiffies + RTL_SECONDS_TO_JIFFIES(2)); + + + return 0; +} + + + + +int P2P_show_status(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int idx=0; + if(!(OPMODE&WIFI_P2P_SUPPORT)) + printk("No under P2P mode\n"); + + printk("OPMODE: %02x\n",OPMODE); + printk("P2PMODE: "); + switch(P2PMODE) + { + case P2P_DEVICE: + printk("P2P_DEVICE\n"); + break; + case P2P_PRE_CLIENT: + printk("P2P_PRE_CLIENT\n"); + break; + + case P2P_CLIENT: + printk("P2P_CLIENT\n"); + break; + + case P2P_PRE_GO: + printk("P2P_PRE_GO\n"); + break; + + case P2P_TMP_GO: + printk("P2P_TMP_GO\n"); + break; + default: + printk("unknow type\n"); + + } + + printk("P2P Status(%d): ",P2P_STATE); + switch(P2P_STATE) + { + case P2P_S_IDLE: + printk("IDLE\n"); + break; + case P2P_S_SCAN: + printk("SCAN\n"); + break; + + case P2P_S_LISTEN: + printk("LISTEN\n"); + break; + + case P2P_S_SEARCH: + printk("SEARCH\n"); + break; + + case P2P_S_PROVI_TX_REQ: + case P2P_S_PROVI_WAIT_RSP: + case P2P_S_PROVI_RX_RSP: + printk("Provision procedure active\n"); + break; + case P2P_S_PROVI_RX_REQ: + case P2P_S_PROVI_TX_RSP: + printk("Provision procedure passive\n"); + break; + case P2P_S_NEGO_TX_REQ: + case P2P_S_NEGO_WAIT_RSP: + case P2P_S_NEGO_TX_CONF: + printk("GO nego procedure active\n"); + break; + case P2P_S_NEGO_RX_REQ: + case P2P_S_NEGO_TX_RSP: + case P2P_S_NEGO_WAIT_CONF: + printk("GO nego procedure passive\n"); + break; + case P2P_S_CLIENT_CONNECTED_DHCPC: + printk("P2P client connected\n"); + break; + case P2P_S_CLIENT_CONNECTED_DHCPC_done: + printk("P2P client connected\n"); + break; + + case P2P_S_preGO2GO_DHCPD: + case P2P_S_preGO2GO_DHCPD_done: + printk("P2P GO\n"); + break; + + default: + printk("unknow type\n"); + + } + + + printk("p2p listen channel=\"%d\"\n",priv->pmib->p2p_mib.p2p_listen_channel); + printk("p2p operation channel=\"%d\"\n",priv->pmib->p2p_mib.p2p_op_channel); + printk("p2p intent value=\"%d\"\n",priv->pmib->p2p_mib.p2p_intent); + printk("p2p device name=\"%s\"\n",priv->pmib->p2p_mib.p2p_device_name); + printk("p2p pin code=\"%s\"\n",priv->pmib->p2p_mib.p2p_wsc_pin_code); + + printk("GO info\n"); + printk("GO SSID=%s\n",priv->p2pPtr->my_GO_ssid); + printk("GO PSK=%s\n",priv->p2pPtr->go_PSK); + + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G){ + printk("under PHY_BAND_2G\n"); + } + else if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G){ + printk("under PHY_BAND_5G\n"); + } + + if(P2PMODE == P2P_TMP_GO){ + if(priv->p2pPtr->p2p_probe_rsp_ie_len) + debug_out("go rsp IE",priv->p2pPtr->p2p_probe_rsp_ie ,priv->p2pPtr->p2p_probe_rsp_ie_len); + + + for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){ + if(priv->p2pPtr->assocPeers[idx].inuse){ + printk("%d) P2P client assoc2me:",idx); + MAC_PRINT(priv->p2pPtr->assocPeers[idx].if_addr); + } + } + + } + + return 0; +} + + + +/* display the result of p2p discovery*/ +void p2p_show_ss_res(struct rtl8192cd_priv *priv) +{ + unsigned char* addrptr; + int idx =0; + //wait SiteSurvey completed + + P2P_PRINT("\n\n"); + P2P_DEBUG("result count=%d\n",priv->site_survey.count_backup); + + if(priv->ss_req_ongoing) { + P2P_PRINT("ss_req_ongoing\n"); + }else{ + + P2P_PRINT("index:"); + P2P_PRINT("address: "); + P2P_PRINT("role: "); + P2P_PRINT("channel:"); + P2P_PRINT("wsc method:"); + P2P_PRINT("name: "); + P2P_PRINT("ssid(only go):\n"); + for(idx=0;idx < priv->site_survey.count_backup; idx++){ + + //if(strlen(priv->site_survey.bss_backup[idx].p2pdevname)==0) + // continue; + + P2P_PRINT("%d ",idx); + addrptr = priv->site_survey.bss_backup[idx].p2paddress; + P2P_PRINT(";%02x%02x%02x:%02x%02x%02x ",addrptr[0],addrptr[1],addrptr[2], + addrptr[3],addrptr[4],addrptr[5]); + + if(priv->site_survey.bss_backup[idx].p2prole == R_P2P_GO) + P2P_PRINT(";GO "); + else if(priv->site_survey.bss_backup[idx].p2prole == R_P2P_DEVICE) + P2P_PRINT(";DEVICE "); + + P2P_PRINT(";%d ",priv->site_survey.bss_backup[idx].channel); + P2P_PRINT(";%02x ",priv->site_survey.bss_backup[idx].p2pwscconfig); + P2P_PRINT("; %s ",priv->site_survey.bss_backup[idx].p2pdevname); + if(priv->site_survey.bss_backup[idx].p2prole == R_P2P_GO) + P2P_PRINT(";%s ",priv->site_survey.bss_backup[idx].ssid); + P2P_PRINT("\n"); + + } + P2P_PRINT("\n\n"); + } + +} + + + +int P2P_show_command(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + + P2P_PRINT("1)iwpriv wlan0 p2pcmd channel,6\n"); + P2P_PRINT("2)iwpriv wlan0 p2pcmd intent,6\n"); + P2P_PRINT("3)iwpriv wlan0 p2pcmd opchannel,6\n"); + P2P_PRINT("4)iwpriv wlan0 p2pcmd devname,rtl8196c-dev\n"); + P2P_PRINT("1~4) need :iwpriv wlan0 p2pcmd apply\n"); + + P2P_PRINT("6)iwpriv wlan0 p2pcmd scan\n"); + P2P_PRINT("7)iwpriv wlan0 p2pcmd search\n"); + P2P_PRINT("8)iwpriv wlan0 p2pcmd listen\n"); + P2P_PRINT("9)iwpriv wlan0 p2pcmd find\n"); + P2P_PRINT("10)iwpriv wlan0 p2pcmd discovery\n"); + P2P_PRINT("\n"); + P2P_PRINT("11)iwpriv wlan0 p2pcmd asgo\n"); + P2P_PRINT("12)iwpriv wlan0 p2pcmd bakdev\n"); + P2P_PRINT("\n"); + P2P_PRINT("13)iwpriv wlan0 p2pcmd status\n"); + + return 0; +} + + + +int p2pcmd_find(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + P2P_PRINT("start P2P find phase\n"); + P2P_DISCOVERY = 1; + priv->site_survey.count = 0; + priv->site_survey.count_backup = 0; + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + return 0; + +} +int p2pcmd_discovery(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + P2P_PRINT("\n"); + P2P_DEBUG("start P2P_discovery.....\n"); + P2P_DISCOVERY = 1; + priv->site_survey.count = 0; + priv->site_survey.count_backup = 0; + P2P_scan(priv,NULL); + + return 0; +} + +#define P2P_MODE_SWITCH 0 // no meaning + +int p2p_as_preClient(struct rtl8192cd_priv *priv) +{ + + // unsigned long flags; + // P2P_DEBUG("\n"); + //SAVE_INT_AND_CLI(flags); + //SMP_LOCK(flags); + + rtl8192cd_close(priv->dev); + OPMODE = (WIFI_P2P_SUPPORT | WIFI_STATION_STATE); + P2PMODE = P2P_PRE_CLIENT; + P2P_STATE = P2P_S_IDLE; + + /* clear SSID */ + memset(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, '\0' , 32); + priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen = 0; + + // site suvery all + priv->ss_ssidlen=0; + + rtl8192cd_open(priv->dev); + + + //RESTORE_INT(flags); + //SMP_UNLOCK(flags); + + return 0; +} + +int p2p_as_GO(struct rtl8192cd_priv *priv, int GOtype){ + + //unsigned long flags; + //SAVE_INT_AND_CLI(flags); + //SMP_LOCK(flags); + + rtl8192cd_close(priv->dev); + OPMODE = (WIFI_P2P_SUPPORT | WIFI_AP_STATE); + + if(GOtype == P2P_PRE_GO) + P2PMODE = P2P_PRE_GO; + else if(GOtype == P2P_TMP_GO) + P2PMODE = P2P_TMP_GO; + + P2P_DEBUG("MY GO SSID:%s\n",priv->p2pPtr->my_GO_ssid); + P2P_DEBUG("MY PSK:%s\n",priv->p2pPtr->go_PSK); + /* set SSID */ + priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen = priv->p2pPtr->my_GO_ssid_len; + memset(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, 0, 32); + memcpy(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, + priv->p2pPtr->my_GO_ssid, priv->p2pPtr->my_GO_ssid_len); + + + + /* set channel */ + //stay_on_2G(priv); + priv->pmib->dot11RFEntry.dot11channel = priv->pmib->p2p_mib.p2p_op_channel; + + /* set band */ + if(priv->pmib->p2p_mib.p2p_op_channel<=11) + priv->pmib->dot11BssType.net_work_type=8+2; // G+N + else + priv->pmib->dot11BssType.net_work_type=8+4; // A+N + + /*set security ;WPA2+AES*/ + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _CCMP_PRIVACY_; + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 8; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA2 ; // support WPA+WPA2 + + /* PSK */ + strcpy(priv->pmib->dot1180211AuthEntry.dot11PassPhrase, priv->p2pPtr->go_PSK); + + rtl8192cd_open(priv->dev); + + /*state change and indicate web server start udhcpd ; only under GO mode; pre GO don't*/ + if(GOtype == P2P_TMP_GO){ + /*it will trigger application to start DHCPD !!*/ + P2P_STATE = P2P_S_preGO2GO_DHCPD; + } + + //RESTORE_INT(flags); + //SMP_UNLOCK(flags); + return 0; +} + +int p2pcmd_force_GO(struct rtl8192cd_priv *priv, unsigned char *data) +{ + p2p_as_GO(priv,P2P_TMP_GO); + // switch wscd mode to AP ;only change mode wps not start yet + indicate_wscd(priv, MODE_AP_PROXY_REGISTRAR ,NULL , NULL); + return 0 ; +} + +int p2pcmd_backtoDev(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + P2P_DEBUG("\nReset to p2p device \n\n\n"); +#if 0 + if(P2PMODE == P2P_CLIENT){ + if(priv->p2pPtr->assocPeers[0].inuse + && !is_zero_ether_addr(priv->p2pPtr->assocPeers[0].if_addr)){ + P2P_DEBUG("\n issue disassoc to :"); + MAC_PRINT(priv->p2pPtr->assocPeers[0].if_addr); + issue_disassoc(priv, priv->p2pPtr->assocPeers[0].if_addr , _RSON_UNSPECIFIED_ ); + } + } +#endif + + //SAVE_INT_AND_CLI(flags); + //SMP_LOCK(flags); + rtl8192cd_close(priv->dev); + + OPMODE = (WIFI_P2P_SUPPORT | WIFI_STATION_STATE); + P2PMODE = P2P_DEVICE; + P2P_STATE = P2P_S_IDLE; + + + /* set SSID */ +// priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen = 0; +// memset(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, 0, 32); + memset(SSID, 0, 32); + SSID_LEN = 0; + + memset(SSID2SCAN, 0, 32); + SSID2SCAN_LEN = 0; + + + /* set channel */ + priv->pmib->dot11RFEntry.dot11channel = priv->pmib->p2p_mib.p2p_listen_channel; + + /* set band */ + //priv->pmib->dot11BssType.net_work_type=8+3; // B+G+N + + /*set security ;WPA2+AES*/ + +// priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = _NO_PRIVACY_; +// priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_; + memset(&priv->pmib->dot1180211AuthEntry , 0 , sizeof(struct Dot1180211AuthEntry)); + + //priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + //priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 8; + + /* PSK */ + //memset(priv->pmib->dot1180211AuthEntry.dot11PassPhrase,0 ,65); + + + /*clean beacon P2P IE */ + priv->p2pPtr->p2p_beacon_ie_len = 0; + + /*make sure i am under 2G band*/ + stay_on_2G(priv); + + + + rtl8192cd_open(priv->dev); + + + //RESTORE_INT(flags); + //SMP_UNLOCK(flags); + + // stop wscd + stop_wscd(priv,NULL); + + // change back to enrollee mode + indicate_wscd(priv, MODE_CLIENT_UNCONFIG ,NULL , NULL); + + + //P2P_listen(priv, NULL); //0408 1sec timer will do it + + //============== + return 0; + +} + + +#define P2P_CONFIGURABILE_PARAMTER 0 // no meaning + +int p2pcmd_set_listen_channel(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int dwekk_chn=_atoi(data , 10); + + if(dwekk_chn !=1 && dwekk_chn!=6 && dwekk_chn!=11){ + P2P_DEBUG("invaild chn(%d) ; set chn to default =6\n",dwekk_chn); + priv->pmib->p2p_mib.p2p_listen_channel = 6 ; + }else{ + priv->pmib->p2p_mib.p2p_listen_channel = dwekk_chn ; + P2P_DEBUG("set listen_channel to (%d) OK!!\n", priv->pmib->p2p_mib.p2p_listen_channel); + } + return 0; + +} + +int p2pcmd_set_intent_value(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int intentVal = _atoi(data , 10); + if(intentVal>15 ||intentVal<0 ){ + P2P_DEBUG("invaild intent value\n"); + }else{ + priv->pmib->p2p_mib.p2p_intent = intentVal ; + P2P_DEBUG("set intentVal to (%d) OK!!\n",priv->pmib->p2p_mib.p2p_intent); + } + return 0; +} + + +int p2pcmd_set_op_channel(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int opchannel = _atoi(data , 10); + priv->pmib->p2p_mib.p2p_op_channel = opchannel ; + P2P_DEBUG("set op channel to (%d) OK!!\n",priv->pmib->p2p_mib.p2p_op_channel); + return 0; +} + + +int p2pcmd_set_devicename(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned char devname[33]; + devname[32]='\0'; + strcpy(devname, data); + P2P_DEBUG("set dev name to %s \n",devname); + strcpy(priv->pmib->p2p_mib.p2p_device_name ,devname ); + return 0; + +} + +int p2pcmd_apply(struct rtl8192cd_priv *priv, unsigned char *data) +{ + p2p_init(priv); + return 0; +} + + +#define P2P_COMMAND_LIST 0 // no meaning + + +struct p2p_cmd_list p2p_cmd_tbl_lev1[] = { + + {"channel",p2pcmd_set_listen_channel}, + {"intent",p2pcmd_set_intent_value}, + {"opchannel",p2pcmd_set_op_channel}, + {"devname",p2pcmd_set_devicename}, + {"asgo",p2pcmd_force_GO}, + {"bakdev",p2pcmd_backtoDev}, + {"apply",p2pcmd_apply}, + {"enable",p2pcmd_enable}, + {"scan",P2P_scan}, + {"listen",P2P_listen}, + {"search",P2P_search}, + {"discovery",p2pcmd_discovery}, + {"find",p2pcmd_find}, + {"status",P2P_show_status}, + {"help",P2P_show_command} + +}; + +int p2pcmdCnt = sizeof(p2p_cmd_tbl_lev1) / sizeof(struct p2p_cmd_list); +int process_p2p_cmd(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + char *val=NULL; + int ix; + int res=0; + int found=0; + + for(ix=0; ix<p2pcmdCnt; ix++) { + val = p2p_get_token((char *)data, p2p_cmd_tbl_lev1[ix].cmd); + if (val) { + res = p2p_cmd_tbl_lev1[ix].p2p_cmd_func(priv , val) ; + found = 1; + break; + } + } + if(found==0){ + P2P_PRINT("usage: \n"); + for(ix=0; ix<p2pcmdCnt; ix++) + P2P_PRINT("%s \n", p2p_cmd_tbl_lev1[ix].cmd ); + } + return res; + +} + + + |