/* * 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 #include #endif #include #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;idxp2pPtr->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 0) { printk("\t"); for (j=0; jchannels_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;idxp2pPtr->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;idxp2pPtr->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;idxp2pPtr->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;idxp2pPtr->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;idxp2pPtr->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;idxp2pPtr->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;idxp2pPtr->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