M7350/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_p2p.c
2024-09-09 08:59:52 +00:00

5915 lines
149 KiB
C
Executable File

/*
* 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 CONFIG_RTL_P2P_SUPPORT
#ifdef __KERNEL__
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/random.h>
#endif
#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, char *data);
struct p2p_cmd_list {
char cmd[32];
p2pcmd_func_t* p2p_cmd_func;
};
char* WSC_STR_PBC="PBC"; // 0x80
char* WSC_STR_KEYIN="keyin"; //0x100
char* WSC_STR_DISPLAY="display pin"; // 0x8
/*--------------debug---------------------*/
/*---------------function declare start------------------ */
char* p2p_find_cmd(char *, char *);
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 peers_opchannel);
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);
// 2013
#ifdef CONFIG_RTL_8812_SUPPORT
if(GET_CHIP_VER(priv)== VERSION_8812E){
UpdateBBRFVal8812(priv,1);
}else
#endif
{
#ifdef CONFIG_RTL_92D_SUPPORT
if (GET_CHIP_VER(priv) == VERSION_8192D) {
UpdateBBRFVal8192DE(priv);
}
#endif
}
// 2013
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);
// 2013
#ifdef CONFIG_RTL_8812_SUPPORT
if(GET_CHIP_VER(priv)== VERSION_8812E){
UpdateBBRFVal8812(priv,44);
}else
#endif
{
#ifdef CONFIG_RTL_92D_SUPPORT
if (GET_CHIP_VER(priv) == VERSION_8192D) {
UpdateBBRFVal8192DE(priv);
}
#endif
}
// 2013
PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0x0);
//RESTORE_INT(flags);
// SMP_UNLOCK(flags);
}
return;
}
#define UTILITY_FUNCTIONS 0 // no meaning
/*--------------------------------
*---------------------------------
*
* utility unctions area
*
*---------------------------------
---------------------------------*/
void generate_random_xy(unsigned char *data,int len)
{
char *String09azAZ="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned char byteList[30];
int idx;
if(len>30)
return;
get_random_bytes((void *)&byteList, len);
for(idx=0;idx<len;idx++){
data[idx] = String09azAZ[byteList[idx]%62];
}
data[len]='\0';
//P2P_DEBUG("return %s\n" ,data);
}
void init_channel_list(struct rtl8192cd_priv *priv)
{
int idx = 0;
memset(&priv->p2pPtr->my_channel_list,0,sizeof(struct p2p_channels));
memcpy(priv->p2pPtr->my_channel_list.country ,"XX" ,2);
priv->p2pPtr->my_channel_list.country[2] = 0x04;
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);
memcpy(&priv->p2pPtr->my_GO_ssid[P2P_WILDCARD_SSID_LEN+2] ,"-RTK",4);
priv->p2pPtr->my_GO_ssid[P2P_WILDCARD_SSID_LEN+2+4]='\0';
#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_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_find_cmd(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]=='=' || data[idx+token_len]==' ')
return (&data[idx+token_len+1]);
else
return (&data[idx+token_len]);
}
src_len--;
idx++;
}
return NULL;
}
//p2p_get_token
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;
}
static int is_zero_ether_addr(const unsigned char *a)
{
return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]);
}
int is_zero_pin_code(const unsigned char *a)
{
return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]| a[6]| a[7]);
}
void p2p_debug_out(unsigned char *label, unsigned char *data, int data_length)
{
int i,j;
int num_blocks;
int block_remainder;
num_blocks = data_length >> 4;
block_remainder = data_length & 15;
if (label)
printk("%s\n", label);
if (data==NULL || data_length==0)
return;
for (i=0; i<num_blocks; i++) {
printk("\t");
for (j=0; j<16; j++)
printk("%02x ", data[j + (i<<4)]);
printk("\n");
}
if (block_remainder > 0) {
printk("\t");
for (j=0; j<block_remainder; j++)
printk("%02x ", data[j+(num_blocks<<4)]);
printk("\n");
}
}
/*
* show value by binary format
*/
void ShowValByBinary(unsigned int ByteIn, char *binary_str ,int len )
{
int idx;
for( idx=0 ; idx < len;idx++){
if(ByteIn & 1<<(len - 1 - idx))
binary_str[idx]='1';
else
binary_str[idx]='0';
}
binary_str[idx+1]='\0';
}
#define P2P_ATTRIBUTE_PARSE 0 // no meaning
/*----------------------------------------------------------------
------------------------------------------------------------------*/
void parse_channel_list(unsigned char* pData , int tag_len ,
struct p2p_device_peer *current_nego_peer)
{
int idx;
int len=tag_len;
int channels;
int reg_class=0;
unsigned char CountryCodeStr[4];
strncpy(CountryCodeStr , pData ,3);
CountryCodeStr[3]='\0';
//P2P_DEBUG(" CountryCode:%s\n", CountryCodeStr);
//P2P_DEBUG(" Channel:");
len -= 3;
pData +=3;
while(len){
//P2P_DEBUG(" op class:%d\n",pData[0]);
channels = pData[1];
for( idx=0 ; idx < channels ;idx++){
if(current_nego_peer)
current_nego_peer->channels_list.reg_class[reg_class].channel[idx]=pData[2+idx];
//P2P_DEBUG(" channel:%d \n",pData[2+idx]);
}
len -= (2+channels);
pData += (2+channels);
reg_class++;
}
}
void parse_device_info(unsigned char* pData , int tag_len ,
struct device_info_s* dev_info_ptr )
{
int TagLenChk=tag_len;
int idx = 0;
unsigned char NoSD=0;
unsigned short WSC_T;
unsigned short WSC_L;
unsigned char DeviceName[33];
/*device address */
//P2P_DEBUG("P2P Device Address:");
//MAC_PRINT(pData);
if(dev_info_ptr){
memcpy(dev_info_ptr->dev_address,pData,6 );
}
pData += 6;
TagLenChk -= 6;
/*config method */
//P2P_DEBUG(" Config method:0x%02X\n",*(unsigned short*)pData);
if(dev_info_ptr){
dev_info_ptr->config_method = *(unsigned short*)pData;
}
pData += 2;
TagLenChk -= 2;
/*Primary Device Type */
if(dev_info_ptr){
memcpy(dev_info_ptr->pri_dev_type , pData , 8);
}
pData += 8;
TagLenChk -= 8;
/*Number of Second Device Type */
NoSD = pData[0];
pData += 1;
TagLenChk -= 1;
if(dev_info_ptr)
dev_info_ptr->sdv_mun = NoSD;
/* N * Second Device Type */
if(NoSD){
for( idx=0 ; idx < NoSD ; idx++){
if(idx < MAX_SEC_DEV_TYPE){ // now we just keep 2 set , take care
if(dev_info_ptr)
memcpy(&dev_info_ptr->sec_dev_type[idx] ,pData,8);
}
pData += 8;
TagLenChk -= 8;
}
}
/* Device Name (WSC TLV(2+2+N))*/
WSC_T = *((unsigned short *)pData); // Tag
pData+=2;
WSC_L = *((unsigned short *)pData); // LEN
if(WSC_T != 0x1011){
P2P_PRINT("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_PRINT("chk!! TagLenChk(%d) should be 0\n",TagLenChk);
P2P_PRINT("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_PRINT(" Device Addr:");
MAC_PRINT(pData);
pData +=6;
EachClientInfoLen -= 6;
/*interface address */
P2P_PRINT(" interface Addr:");
MAC_PRINT(pData);
pData +=6;
EachClientInfoLen -= 6;
/*config method */
P2P_PRINT("Config method:0x%02X\n",*(unsigned int*)pData);
pData +=2;
EachClientInfoLen -= 2;
/*Primary Device Type */
P2P_PRINT(" 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_PRINT(" 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_PRINT("chk!! should be 0x1011\n");
}
pData+=2;
WSC_L = *((unsigned short *)pData);
P2P_PRINT("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_PRINT("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);
P2P_PRINT("GO's bssid=[%02x%02x%02x:%02x%02x%02x]\n",
pData[0],pData[1],pData[2],pData[3],pData[4],pData[5]);
}
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_PRINT(" 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_PRINT(" P2P ifAddr:");
MAC_PRINT(pData);
pData += 6 ;
tag_len -= 6 ;
}
}
if(tag_len){
P2P_PRINT("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_PRINT("Found tag [0x%x], but invalid length!\n", tag);
P2P_PRINT("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_PRINT("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_PRINT("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);
memcpy(thisAttrPrt + 3, priv->p2pPtr->my_channel_list.country,3);
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);
memcpy(thisAttrPrt + 3, priv->p2pPtr->my_channel_list.country,3);
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;
P2P_DEBUG("\n");
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
P2P_DEBUG("RX ,action frame");
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);
txinsn.q_num = MANAGE_QUE_NUM;
txinsn.fr_type = _PRE_ALLOCMEM_;
txinsn.tx_rate = _6M_RATE_;
txinsn.lowest_tx_rate = txinsn.tx_rate;
txinsn.fixed_rate = 1;
pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv);
if (pbuf == NULL)
goto issue_dev_dis_rsp_fail;
txinsn.phdr = get_wlanhdr_from_poll(priv);
if (txinsn.phdr == NULL)
goto issue_dev_dis_rsp_fail;
memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr));
pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION;
pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION;
memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4);
pbuf[6] = P2P_DEV_DISC_RESP;
pbuf[7] = priv->p2pPtr->dev_dis_req_dialog_token ;
thisAttrPrt = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_;
IEStart = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; //anchor
thisAttrPrt = add_Attr_status(priv , thisAttrPrt, &p2pIELen ,status);
IEStart[1] = p2pIELen;
txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf)));
SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION);
memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN);
memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN);
memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN);
if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){
P2P_PRINT("\n");
P2P_DEBUG("TX Device Discovery Rsp success!!\n");
MAC_PRINT(da);
return SUCCESS;
}
issue_dev_dis_rsp_fail:
if (txinsn.phdr)
release_wlanhdr_to_poll(priv, txinsn.phdr);
if (txinsn.pframe)
release_mgtbuf_to_poll(priv, txinsn.pframe);
return FAIL;
}
void p2p_on_device_discovery_req(
struct rtl8192cd_priv *priv ,
struct rx_frinfo *pfrinfo)
{
/*start of action frame content*/
unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN;
unsigned char *IEptr = NULL;
int tmplen = 0;
int foundP2PIE=0;
int p2pIElen = 0 ;
unsigned char *p2pIEPtr = NULL;
int idx;
struct p2p_device_peer *current_nego_peer=NULL;
priv->p2pPtr->dev_dis_req_dialog_token = pframe[7];
/*-----------------------------get P2P IE(start)------------------------------*/
IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_;
tmplen = 0;
for(;;)
{
IEptr = get_ie(IEptr, _P2P_IE_, &tmplen,
pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen);
if(IEptr){
if (!memcmp(IEptr+2, WFA_OUI_PLUS_TYPE, 4)) {
p2pIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4)
p2pIEPtr = IEptr+6 ;
foundP2PIE = 1;
break;
}
}else{
break ;
}
IEptr = IEptr + tmplen +2 ;
}
if(foundP2PIE){
/*only GO need process P2P IE in provision req*/
current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ;
memset((void *)current_nego_peer , 0 ,sizeof(struct p2p_device_peer));
// ID15
IEptr = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_P2P_GROUP_ID , &tmplen);
if(IEptr){
parse_group_id(IEptr , tmplen ,current_nego_peer);
}
if(memcmp(current_nego_peer->group_bssid , GET_MY_HWADDR ,6)){
P2P_DEBUG("bssid no match!!\n");
return;
}
// ID3
IEptr = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_DEVICE_ID , &tmplen);
if(IEptr){
for(idx=0;idx<MAX_P2P_CLIENT_MUN ; idx++){
if(!memcmp(priv->p2pPtr->assocPeers[idx].devInfo.dev_address,IEptr,6)){
// some p2p device (no need assoc) search client that assoc with me
if(priv->p2pPtr->assocPeers[idx].dev_cap & CLIENT_DISCOVERY){
p2p_issue_GO_discovery_req(priv,IEptr);
// we assume client will ack me
p2p_issue_device_discovery_rsp(priv,pfrinfo->sa,P2P_SC_SUCCESS);
return ;
}
}
}
}
}
/*-----------------------------get P2P IE(end)------------------------------*/
p2p_issue_device_discovery_rsp(priv,pfrinfo->sa,P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE);
return ;
}
void p2p_on_device_discovery_rsp(
struct rtl8192cd_priv *priv ,
struct rx_frinfo *pfrinfo)
{
// TODO ?
return;
}
int P2P_on_public_action(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo)
{
/*start of action frame content*/
unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN;
if(memcmp(pfrinfo->da , GET_MY_HWADDR , 6)){
return 0;
}
if(pframe[6] ==P2P_GO_NEG_REQ || pframe[6] ==P2P_GO_NEG_RESP || pframe[6] ==P2P_GO_NEG_CONF){
// let the case on going
if(memcpy(priv->p2pPtr->ongoing_nego_peer.dev_addr,pfrinfo->sa , 6)){
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("RX, 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");
P2P_DEBUG("RX Provision-Discovery Req\n");
p2p_on_provision_req(priv,pfrinfo);
break;
case P2P_PROV_DISC_RSP:
P2P_PRINT("\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);
P2P_DEBUG("target addr=%02x%02x%02x:%02x%02x%02x\n",provision_comm_ptr->dev_address[0]
,provision_comm_ptr->dev_address[1],provision_comm_ptr->dev_address[2],provision_comm_ptr->dev_address[3]
,provision_comm_ptr->dev_address[4],provision_comm_ptr->dev_address[5]);
P2P_DEBUG("target channel=%d \n",provision_comm_ptr->channel);
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 Target 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 at 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;
P2P_DEBUG("RX, Provison Rsp\n");
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;
#ifdef P2P_DEBUGMSG
char *StrTmp;
#endif
priv->p2pPtr->provision_rx_dialog_token = pframe[7];
//P2P_DEBUG("RX, Provision req\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;
#ifdef P2P_DEBUGMSG
if(wscMethod==CONFIG_METHOD_KEYPAD)
StrTmp=WSC_STR_KEYIN;
else if(wscMethod==CONFIG_METHOD_PBC)
StrTmp=WSC_STR_PBC;
else if(wscMethod==CONFIG_METHOD_DISPLAY)
StrTmp=WSC_STR_DISPLAY;
P2P_DEBUG("WSC Method:%02x[peers Req:%s]\n",wscMethod ,StrTmp );
if(wscMethod==0x100){
P2P_DEBUG("\n\n keyin peers PIN code ex: iwpriv wlan0 p2pcmd keypad=%02X%02X%02X%02X%02X%02X,PIN\n\n",
pfrinfo->sa[0],pfrinfo->sa[1],pfrinfo->sa[2],pfrinfo->sa[3],pfrinfo->sa[4],pfrinfo->sa[5]);
}
#endif
}
}
/*-----------------------------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 ,&current_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);
P2P_DEBUG("\n");
if(wscMethod){
priv->p2pPtr->wsc_method_from_target_dev = wscMethod;
#ifdef P2P_DEBUGMSG
if(wscMethod==CONFIG_METHOD_KEYPAD)
StrTmp=WSC_STR_KEYIN;
else if(wscMethod==CONFIG_METHOD_PBC)
StrTmp=WSC_STR_PBC;
else if(wscMethod==CONFIG_METHOD_DISPLAY)
StrTmp=WSC_STR_DISPLAY;
P2P_DEBUG("WSC Method:%02x[peers Req:%s]\n",wscMethod ,StrTmp );
if(wscMethod==CONFIG_METHOD_KEYPAD){
P2P_DEBUG("\n keyin peers PIN: iwpriv wlan0 p2pcmd keypad=%02X%02X%02X%02X%02X%02X,PIN\n\n",
pfrinfo->sa[0],pfrinfo->sa[1],pfrinfo->sa[2],pfrinfo->sa[3],pfrinfo->sa[4],pfrinfo->sa[5]);
}
#endif
/*trigger wscd when i'm GO ; target is dev ; aother way is from web page ; 2013-0828*/
if((P2PMODE == P2P_TMP_GO) && priv->p2pPtr->target_device_role == R_P2P_DEVICE ){
struct p2p_device_peer wsc_peer_t;
P2P_DEBUG("Target is device ; i'm 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*/
P2P_DEBUG("use Tar's PIN\n");
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 */
P2P_DEBUG("use My PIN\n");
wsc_peer_t.device_pass_id = PASS_ID_USER;
}else if(priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_PBC){
/*PBC*/
P2P_DEBUG("use PBC\n");
wsc_peer_t.device_pass_id = PASS_ID_PB;
}else{
P2P_DEBUG("unknow type !!!\n\n");
}
/*indicate wscd satrt WPS procotol*/
P2P_DEBUG("trigger AP mode wscd\n");
indicate_wscd(priv, P2P_TMP_GO , priv->p2pPtr->go_PSK , &wsc_peer_t);
}
}
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_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("TX provison rsp ,OK!\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 ;
call in from web*/
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){
#if 0 //2013-0716 marked ; default pbc be allowed
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;
}
#endif
}
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, P2P_TMP_GO , 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,priv->p2pPtr->target_device_channel);
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, P2P_PRE_CLIENT , 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;
P2P_DEBUG("RX, GO nego Rsp\n");
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 ,&current_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, P2P_PRE_GO , 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 , current_nego_peer->op_channel);
/*indicate wscd change mode ; and satrt WPS procotol*/
indicate_wscd(priv, P2P_PRE_CLIENT , 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("peer's device_pass_id= [%02X] \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;
}
*/
P2P_DEBUG("default allow PBC \n");
/*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_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, P2P_PRE_GO , 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 ,current_nego_peer->op_channel);
// indicate wscd change mode and start WPS
/*start to wsc under enrollee mode*/
indicate_wscd(priv, P2P_PRE_CLIENT , 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;
}
#if 0 // 8812 test
void wps_client_set_spec_bssid(struct rtl8192cd_priv *priv,unsigned char* macaddr)
{
DOT11_WSC_PIN_IND wsc_ind;
if(!memcpy(macaddr,"\x0\x0\x0\x0\x0\x0",6)){
P2P_DEBUG("mac addr = NULL\n");
return;
}
P2P_DEBUG("\n");
wsc_ind.EventId = DOT11_EVENT_WSC_SPEC_MAC_IND;
wsc_ind.IsMoreEvent = 0;
memcpy(wsc_ind.code, macaddr , 6);
wsc_ind.code[6]='\0';
DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_PIN_IND));
event_indicate(priv, NULL, -1);
}
#endif
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 0 // 8812 connect test
if(mode==2){ /*wscd client mode ; we assign target AP's mac addr*/
P2P_DEBUG("call wps_client_set_spec_bssid\n");
wps_client_set_spec_bssid(priv,nego_peer_xx->group_bssid);
}
#endif
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;
#ifdef SMP_SYNC
unsigned long flags = 0;
#endif
P2P_DEBUG("\n");
if( priv->assoc_num == 0){
for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){
if(priv->p2pPtr->assocPeers[idx].inuse){
memset(priv->p2pPtr->assocPeers, 0 ,sizeof(struct assoc_peer)*MAX_P2P_CLIENT_MUN);
priv->p2pPtr->p2p_probe_rsp_ie_len =
p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie);
return;
}
}
}
phead = &priv->asoc_list;
if (!netif_running(priv->dev) || list_empty(phead)) {
return;
}
for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){
if(priv->p2pPtr->assocPeers[idx].inuse){
found = 0;
SMP_LOCK_ASOC_LIST(flags);
plist = phead->next;
while (plist != phead) {
pstat = list_entry(plist, struct stat_info, asoc_list);
plist = plist->next;
if(!memcmp(pstat->hwaddr ,priv->p2pPtr->assocPeers[idx].if_addr ,6)) {
found = 1;
break;
}
}
SMP_UNLOCK_ASOC_LIST(flags);
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("RX , Assoc req\n");
for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){
if(priv->p2pPtr->assocPeers[idx].inuse){
if(!memcmp(priv->p2pPtr->assocPeers[idx].if_addr,sa,6)){
found = 1;
break;
}
}
if(priv->p2pPtr->assocPeers[idx].inuse == 0){
priv->p2pPtr->assocPeers[idx].inuse = 1;
found = 1;
break;
}
}
if(found==0){
// second changes
P2P_chk_assoc_client(priv);
for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){
if(priv->p2pPtr->assocPeers[idx].inuse == 0){
priv->p2pPtr->assocPeers[idx].inuse = 1;
found = 1;
break;
}
}
if(found==0){
P2P_DEBUG("assoc peer full!!,chk!!\n\n\n");
return;
}
}
// ID 2
p2p_sub_ie = p2p_search_tag(IEaddr , IElen , TAG_P2P_CAPABILITY , &tag_len);
if(p2p_sub_ie){
priv->p2pPtr->assocPeers[idx].dev_cap = p2p_sub_ie[0];
priv->p2pPtr->assocPeers[idx].group_cap = p2p_sub_ie[1];
}else{
P2P_DEBUG("can't search TAG_P2P_CAPABILITY\n\n");
return;
}
// ID 13
p2p_sub_ie = p2p_search_tag(IEaddr , IElen , TAG_P2P_DEVICE_INFO , &tag_len);
if(p2p_sub_ie){
parse_device_info(p2p_sub_ie,tag_len, &(priv->p2pPtr->assocPeers[idx].devInfo));
}else{
P2P_DEBUG("can't search TAG_P2P_DEVICE_INFO\n\n");
return;
}
memcpy(priv->p2pPtr->assocPeers[idx].if_addr ,sa, 6);
/*rebuild GO's probe_rsp content ,build Probe_Rsp P2P IE info */
priv->p2pPtr->p2p_probe_rsp_ie_len = p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie);
return;
}
void P2P_on_assoc_rsp(struct rtl8192cd_priv *priv,unsigned char *sa)
{
P2P_DEBUG("RX,Assoc Rsp\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,FALSE);
}else{
issue_probersp(priv, GetAddr2Ptr(pframe), P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN, FALSE,FALSE);
}
}
void p2p_client_remove(struct rtl8192cd_priv *priv , struct stat_info *pstat )
{
int idx=0;
if(P2PMODE!=P2P_TMP_GO){
return;
}
P2P_DEBUG("\n");
for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){
if(priv->p2pPtr->assocPeers[idx].inuse){
if(!memcmp(priv->p2pPtr->assocPeers[idx].if_addr,pstat->hwaddr,6)){
priv->p2pPtr->assocPeers[idx].inuse=0;
priv->p2pPtr->p2p_probe_rsp_ie_len =
p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie);
break;
}
}
}
return;
}
#define SEPARATE4 0 // no meaning
void p2p_init(struct rtl8192cd_priv *priv )
{
if(priv->p2pPtr == NULL){
P2P_DEBUG("first init kmalloc for p2p interface!\n");
priv->p2pPtr = (struct p2p_context*)kmalloc(sizeof(struct p2p_context),GFP_ATOMIC);
if(priv->p2pPtr == NULL){
P2P_DEBUG("\n\n!!!! chk here!!!\n\n\n\n\n");
}else{
memset(priv->p2pPtr,0,sizeof(struct p2p_context));
}
}else{
if(P2PMODE == P2P_CLIENT){
/*the parameter need reset when interface do open and close*/
P2P_DEBUG("reset clientmode_try_connect\n");
priv->p2pPtr->clientmode_try_connect=0;
}
}
P2P_DEBUG("P2P_MODE=[%d]\n",P2PMODE);
P2P_DEBUG("dot11channel=[%d]\n",priv->pmib->dot11RFEntry.dot11channel);
/*setting channel;bandwidth ;ch2ndoffset*/
if(P2PMODE == P2P_DEVICE){
priv->pmib->dot11RFEntry.dot11channel = priv->pmib->p2p_mib.p2p_listen_channel;
priv->pmib->dot11nConfigEntry.dot11nUse40M = 0; // 20Mbandwidth
priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = 0; // don't care
}else
if(P2PMODE == P2P_PRE_GO){
/*temporal AP use 20M bandwitdh*/
priv->pmib->dot11RFEntry.dot11channel = priv->pmib->p2p_mib.p2p_op_channel;
priv->pmib->dot11nConfigEntry.dot11nUse40M = 0; // 20Mbandwidth
priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = 0; // don't care
}else
if(P2PMODE == P2P_TMP_GO){
#if 0 // use default
priv->pmib->dot11RFEntry.dot11channel = priv->pmib->p2p_mib.p2p_op_channel;
priv->pmib->dot11nConfigEntry.dot11nUse40M = 1; // 40M bandwidth
priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = get_ava_2ndchoff(priv,priv->pmib->dot11RFEntry.dot11channel,priv->pmib->dot11nConfigEntry.dot11nUse40M);
#endif
}
/*setting channel;bandwidth ;ch2ndoffset*/
if(priv->p2pPtr->rdyinit){
}else
{
/* do only once ,first one*/
/*generate my GO profile*/
if( memcmp(SSID,"DIRECT-",7) || (SSID_LEN < 9) || (P2PMODE != P2P_TMP_GO)){
generate_GO_ssid(priv);
strcpy(SSID,priv->p2pPtr->my_GO_ssid); //use passPhease from flash mib
}else{
P2P_DEBUG("use mib value as GO ssid\n");
strcpy(priv->p2pPtr->my_GO_ssid,SSID);
priv->p2pPtr->my_GO_ssid_len=SSID_LEN;
}
P2P_DEBUG("my_GO_ssid=[%s]\n",priv->p2pPtr->my_GO_ssid);
P2P_DEBUG("SSID=[%s]\n",SSID);
if(strlen(priv->pmib->dot1180211AuthEntry.dot11PassPhrase)<8){
generate_GO_PSK(priv);
strcpy(priv->pmib->dot1180211AuthEntry.dot11PassPhrase,priv->p2pPtr->go_PSK); //use passPhease from flash mib
}else{
// use the value from flash mib
strcpy(priv->p2pPtr->go_PSK,priv->pmib->dot1180211AuthEntry.dot11PassPhrase); //use passPhease from flash mib
}
P2P_DEBUG("dot11PassPhrase=[%s]\n",priv->pmib->dot1180211AuthEntry.dot11PassPhrase);
P2P_DEBUG("go_PSK=[%s]\n",priv->p2pPtr->go_PSK);
/*1004 test use channel from flash mib or autochannel*/
priv->pmib->p2p_mib.p2p_op_channel = priv->pmib->dot11RFEntry.dot11channel ;
P2P_DEBUG("p2p_op_channel=[%d] copy from dot11channel\n",priv->pmib->p2p_mib.p2p_op_channel);
/*channel list*/
init_channel_list(priv);
/*back up orig 40M/20M and 2ndchoffset*/
priv->p2pPtr->backup_orig_use40M = priv->pmib->dot11nConfigEntry.dot11nUse40M;
priv->p2pPtr->backup_orig_2ndchoffset = priv->pmib->dot11nConfigEntry.dot11n2ndChOffset;
P2P_DEBUG("dot11nUse40M=[%d]\n",priv->pmib->dot11nConfigEntry.dot11nUse40M);
P2P_DEBUG("dot11n2ndChOffset=[%d]\n",priv->pmib->dot11nConfigEntry.dot11n2ndChOffset);
priv->p2pPtr->rdyinit=1;
}
if(P2PMODE == P2P_TMP_GO){
/*it will trigger application to start DHCPD !!*/
P2P_STATE = P2P_S_preGO2GO_DHCPD;
P2P_DEBUG("to start DhcpD\n");
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
}
/*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);
}
/*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);
}
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);
/* 2013-0723 8812 test */
//priv->pshare->working_channel = priv->pmib->p2p_mib.p2p_listen_channel;
//PHY_IQCalibrate(priv);
/* 2013-0723 8812 test */
// 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));/* call P2P_listen_timer() */
}
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 || (OPMODE&WIFI_SITE_MONITOR))
{
if (timer_pending(&priv->p2p_search_timer_t))
del_timer_sync(&priv->p2p_search_timer_t);
/*site survey is going... waitting 3 times passive scna time */
// 2013
P2P_PRINT("wait...\n");
mod_timer(&priv->p2p_search_timer_t, jiffies + RTL_MILISECONDS_TO_JIFFIES(300));
}else{
int idx ;
/*restore below two parameter*/
if(priv->back_available_chnl_num){
for(idx=0;idx<MAX_CHANNEL_NUM;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("dev into listen mode\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(%d)\n",P2P_DISCOVERY-1) ;
if(P2P_DISCOVERY == 4) {
P2P_DISCOVERY = 0;
p2p_show_ss_res(priv);
P2P_DEBUG("P2P_discovery done\n");
if(P2PMODE==P2P_CLIENT){
P2P_PRINT("client connected mode\n");
P2P_STATE = P2P_S_CLIENT_CONNECTED_DHCPC_done;
}else{
//P2P_DEBUG("dev into listen mode\n");
P2P_listen(priv,NULL);
}
}else{
//P2P_DEBUG("dev into listen mode\n");
P2P_listen(priv,NULL);
}
}
if((P2P_STATE == P2P_S_SEARCH) || (P2P_STATE == P2P_S_SCAN)){
//P2P_DEBUG("dev into listen mode\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("Site Servey...\n");
priv->ss_req_ongoing = 1; // set this parameter then SS will do 2 runs or 3 runs
start_clnt_ss(priv);
if (timer_pending(&priv->p2p_search_timer_t))
del_timer_sync(&priv->p2p_search_timer_t);
// if 2G only ch number =11 ; SS_COUNT=ss runs ; stay time = 50ms ; detal time=20ms
// 2013
mod_timer(&priv->p2p_search_timer_t, jiffies + RTL_MILISECONDS_TO_JIFFIES(2000)); /* call p2p_search_timer() */
// if 2G + 5G
//mod_timer(&priv->p2p_search_timer_t, jiffies + RTL_MILISECONDS_TO_JIFFIES(1200)); /* call p2p_search_timer() */
/*
start_clnt_ss will call rtl8192cd_ss_timer to complete site survey
p2p_search_timer will wait rtl8192cd_ss_timer complete site survey then on go
*/
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<MAX_CHANNEL_NUM;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;
//priv->ss_req_ongoing = 1; //this parameter will let SS do 2 runs or 3 runs ; 2013-0619
start_clnt_ss(priv);
if (timer_pending(&priv->p2p_search_timer_t))
del_timer_sync(&priv->p2p_search_timer_t);
// 2013
mod_timer(&priv->p2p_search_timer_t, jiffies + RTL_MILISECONDS_TO_JIFFIES(P2P_SEARCH_TIME_V*3 + 800 )); /* call p2p_search_timer() */
return 0;
}
int P2P_show_status(struct rtl8192cd_priv *priv, unsigned char *data)
{
int idx=0;
if(!(OPMODE&WIFI_P2P_SUPPORT))
PDEBUG("No under P2P mode\n");
P2P_DEBUG("OPMODE: %02x\n",OPMODE);
P2P_DEBUG("P2PMODE: ");
switch(P2PMODE)
{
case P2P_DEVICE:
PDEBUG("P2P_DEVICE\n");
break;
case P2P_PRE_CLIENT:
P2P_DEBUG("P2P_PRE_CLIENT\n");
break;
case P2P_CLIENT:
P2P_DEBUG("P2P_CLIENT\n");
break;
case P2P_PRE_GO:
P2P_DEBUG("P2P_PRE_GO\n");
break;
case P2P_TMP_GO:
P2P_DEBUG("P2P_TMP_GO\n");
break;
default:
P2P_DEBUG("unknow type\n");
}
P2P_DEBUG("P2P Status(%d): ",P2P_STATE);
switch(P2P_STATE)
{
case P2P_S_IDLE:
PDEBUG("IDLE\n");
break;
case P2P_S_SCAN:
PDEBUG("SCAN\n");
break;
case P2P_S_LISTEN:
PDEBUG("LISTEN\n");
break;
case P2P_S_SEARCH:
PDEBUG("SEARCH\n");
break;
case P2P_S_PROVI_TX_REQ:
case P2P_S_PROVI_WAIT_RSP:
case P2P_S_PROVI_RX_RSP:
PDEBUG("Provision procedure active\n");
break;
case P2P_S_PROVI_RX_REQ:
case P2P_S_PROVI_TX_RSP:
PDEBUG("Provision procedure passive\n");
break;
case P2P_S_NEGO_TX_REQ:
case P2P_S_NEGO_WAIT_RSP:
case P2P_S_NEGO_TX_CONF:
PDEBUG("GO nego procedure active\n");
break;
case P2P_S_NEGO_RX_REQ:
case P2P_S_NEGO_TX_RSP:
case P2P_S_NEGO_WAIT_CONF:
PDEBUG("GO nego procedure passive\n");
break;
case P2P_S_CLIENT_CONNECTED_DHCPC:
PDEBUG("P2P client connected\n");
break;
case P2P_S_CLIENT_CONNECTED_DHCPC_done:
PDEBUG("P2P client connected\n");
break;
case P2P_S_preGO2GO_DHCPD:
case P2P_S_preGO2GO_DHCPD_done:
PDEBUG("P2P GO\n");
break;
default:
PDEBUG("unknow type\n");
}
P2P_DEBUG("p2p listen channel=\"%d\"\n",priv->pmib->p2p_mib.p2p_listen_channel);
P2P_DEBUG("p2p operation channel=\"%d\"\n",priv->pmib->p2p_mib.p2p_op_channel);
P2P_DEBUG("p2p intent value=\"%d\"\n",priv->pmib->p2p_mib.p2p_intent);
P2P_DEBUG("p2p device name=\"%s\"\n",priv->pmib->p2p_mib.p2p_device_name);
P2P_DEBUG("p2p pin code=\"%s\"\n",priv->pmib->p2p_mib.p2p_wsc_pin_code);
P2P_DEBUG("GO info\n");
P2P_DEBUG("GO SSID=%s\n",priv->p2pPtr->my_GO_ssid);
P2P_DEBUG("GO PSK=%s\n",priv->p2pPtr->go_PSK);
if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G){
P2P_DEBUG("under PHY_BAND_2G\n");
}
else if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G){
P2P_DEBUG("under PHY_BAND_5G\n");
}
if(P2PMODE == P2P_TMP_GO){
if(priv->p2pPtr->p2p_probe_rsp_ie_len)
debug_out("go rsp IE",priv->p2pPtr->p2p_probe_rsp_ie ,priv->p2pPtr->p2p_probe_rsp_ie_len);
for(idx=0;idx<MAX_P2P_CLIENT_MUN;idx++){
if(priv->p2pPtr->assocPeers[idx].inuse){
P2P_DEBUG("%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 dwellch,6\n");
P2P_PRINT("2)iwpriv wlan0 p2pcmd intent,6\n");
P2P_PRINT("3)iwpriv wlan0 p2pcmd opch,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)
{
/*
discovery = scan(similar site servey) + find
find = (search+listen)*3
search = ch1,ch6,ch11(120ms)
listen = stay at listen channel(1 or 6 or 11) ; stay time = 100ms*(random(1~3))
*/
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 , int peers_opchannel)
{
// unsigned long flags;
// P2P_DEBUG("\n");
//SAVE_INT_AND_CLI(flags);
//SMP_LOCK(flags);
priv->pmib->dot11RFEntry.dot11channel = peers_opchannel;
priv->pshare->working_channel = peers_opchannel;
//PHY_IQCalibrate(priv);// 8812 test
rtl8192cd_close(priv->dev);
OPMODE_VAL(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;
/*clear security */
priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = 0;
priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0;
priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0;
priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 0 ; // support WPA+WPA2
/* clear PSK */
memset(priv->pmib->dot1180211AuthEntry.dot11PassPhrase,0 ,65);
// site suvery all
priv->ss_ssidlen=0;
priv->ss_ssid[0]='\0';
/* set band */
if(priv->pmib->dot11RFEntry.dot11channel <= 11)
priv->pmib->dot11BssType.net_work_type=8+2; // G+N
else
priv->pmib->dot11BssType.net_work_type=8+4; // A+N
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_VAL(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;
if(GOtype == P2P_PRE_GO){
/*temporal AP use 20M bandwitdh*/
priv->pmib->dot11nConfigEntry.dot11nUse40M = 0; // 20Mbandwidth
priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = 0; // don't care
}else if(GOtype == P2P_TMP_GO){
/*when dev mode we use 20m as default;
when back to GO mode use system default value about 20/40 and 2nd ch offset*/
priv->pmib->dot11nConfigEntry.dot11nUse40M = priv->p2pPtr->backup_orig_use40M;
priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = priv->p2pPtr->backup_orig_2ndchoffset;
}
/* 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, P2P_TMP_GO ,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);
// stop wscd
stop_wscd(priv,NULL);
// change back to enrollee mode
indicate_wscd(priv, P2P_PRE_CLIENT ,NULL , NULL);
rtl8192cd_close(priv->dev);
OPMODE_VAL(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;
priv->pmib->dot11nConfigEntry.dot11nUse40M = 0; // 20Mbandwidth
priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = 0; // don't care
/* set band */
priv->pmib->dot11BssType.net_work_type=8+2; //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);
//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 ch[%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[%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-ch[%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[%s]\n",devname);
strcpy(priv->pmib->p2p_mib.p2p_device_name ,devname );
return 0;
}
int p2pcmd_set_pincode(struct rtl8192cd_priv *priv, char *data)
{
//unsigned char macNpin[32];
char *delim=",";
char *strP;
unsigned char TargetMac[6];
unsigned char TargetPin[8];
//strcpy(macNpin, data);
P2P_DEBUG("cmd=[%s]\n",data);
strP=strtok(data,delim); // first get macaddress
if(strP){
P2P_DEBUG("mac=[%s]\n",strP);
rtl_string_to_hex(strP ,TargetMac , strlen(strP));
memcpy(priv->p2pPtr->target_device_addr , TargetPin , 6);
}
strP=strtok(NULL,delim); // fsecond get PIN code
if(strP){
P2P_DEBUG("set PIN=[%s]\n",strP);
//string_to_hex(strP ,TargetPin , strlen(strP));
strcpy(priv->p2pPtr->target_dev_pin_code , strP);
}
return 0;
}
int p2pcmd_set_p2pstatus(struct rtl8192cd_priv *priv, unsigned char *data)
{
int status = _atoi(data , 10);
priv->pmib->p2p_mib.p2p_state = status ;
P2P_DEBUG("set p2p_state to[%d] OK!!\n",status);
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[] = {
{"dwellch",p2pcmd_set_listen_channel}, // setting listen channel, should be 1,6,11
{"intent",p2pcmd_set_intent_value}, // setting intent value
{"opch",p2pcmd_set_op_channel}, // setting operation channel
{"devname",p2pcmd_set_devicename}, // setting device name
{"keypad",p2pcmd_set_pincode}, // setting device name
{"setp2pstatus",p2pcmd_set_p2pstatus}, // setting P2P_STATE
{"asgo",p2pcmd_force_GO}, // force to GO role
{"bakdev",p2pcmd_backtoDev}, // force to device mode
{"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;
if( !(OPMODE&WIFI_P2P_SUPPORT )){
P2P_DEBUG("interface no support P2P now!!!\n");
return 0;
}
for(ix=0; ix<p2pcmdCnt; ix++) {
val = p2p_find_cmd((char *)data, p2p_cmd_tbl_lev1[ix].cmd);
if (val) {
res = p2p_cmd_tbl_lev1[ix].p2p_cmd_func(priv , val) ;
found = 1;
break;
}
}
if(found==0){
P2P_PRINT("usage: \n");
for(ix=0; ix<p2pcmdCnt; ix++)
P2P_PRINT("%s \n", p2p_cmd_tbl_lev1[ix].cmd );
}
return res;
}
#endif /* CONFIG_RTL_P2P_SUPPORT */