P2P模块初始化

本文为《深入理解Android Wi-Fi、NFC和GPS卷》读书笔记,Android源码为Android 5.1

android-5.1/external/wpa_supplicant_8/wpa_supplicant/p2p_supplicant.c

int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
{
	struct p2p_config p2p;//p2p变量指向一个p2p_config对象,代表P2P模块的配置信息
	int i;

	if (wpa_s->conf->p2p_disabled)
		return 0;

	//WPA_DRIVER_FLAGS_P2P_CAPABLE代表Wifi驱动对P2P支持的能力
	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE))
		return 0;

	if (global->p2p)
		return 0;

	//初始化并设置p2p_config 对象
	os_memset(&p2p, 0, sizeof(p2p));
	p2p.cb_ctx = wpa_s;
	p2p.debug_print = wpas_p2p_debug_print;
	p2p.p2p_scan = wpas_p2p_scan;
	p2p.send_action = wpas_send_action;
	p2p.send_action_done = wpas_send_action_done;
	p2p.go_neg_completed = wpas_go_neg_completed;
	p2p.go_neg_req_rx = wpas_go_neg_req_rx;
	p2p.dev_found = wpas_dev_found;
	p2p.dev_lost = wpas_dev_lost;
	p2p.find_stopped = wpas_find_stopped;
	p2p.start_listen = wpas_start_listen;
	p2p.stop_listen = wpas_stop_listen;
	p2p.send_probe_resp = wpas_send_probe_resp;
	p2p.sd_request = wpas_sd_request;
	p2p.sd_response = wpas_sd_response;
	p2p.prov_disc_req = wpas_prov_disc_req;
	p2p.prov_disc_resp = wpas_prov_disc_resp;
	p2p.prov_disc_fail = wpas_prov_disc_fail;
	p2p.invitation_process = wpas_invitation_process;
	p2p.invitation_received = wpas_invitation_received;
	p2p.invitation_result = wpas_invitation_result;
	p2p.get_noa = wpas_get_noa;
	p2p.go_connected = wpas_go_connected;
	p2p.presence_resp = wpas_presence_resp;
	p2p.is_concurrent_session_active = wpas_is_concurrent_session_active;
	p2p.is_p2p_in_progress = _wpas_p2p_in_progress;

	//设置P2P Device Address
	os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
	os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
	//设置P2P模块配置信息
	p2p.dev_name = wpa_s->conf->device_name;
	p2p.manufacturer = wpa_s->conf->manufacturer;
	p2p.model_name = wpa_s->conf->model_name;
	p2p.model_number = wpa_s->conf->model_number;
	p2p.serial_number = wpa_s->conf->serial_number;
	if (wpa_s->wps) {
		os_memcpy(p2p.uuid, wpa_s->wps->uuid, 16);
		p2p.config_methods = wpa_s->wps->config_methods;
	}

	//判断wifi驱动是否支持配置文件中设置的operational channel和listen channel
	if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels)) {
		wpa_printf(MSG_ERROR,
			   "P2P: Failed to configure supported channel list");
		return -1;
	}

	//设置Operational Channel信息和listen channel信息
	if (wpa_s->conf->p2p_listen_reg_class &&
	    wpa_s->conf->p2p_listen_channel) {
		p2p.reg_class = wpa_s->conf->p2p_listen_reg_class;
		p2p.channel = wpa_s->conf->p2p_listen_channel;
		p2p.channel_forced = 1;
	} else {
		/*
		 * Pick one of the social channels randomly as the listen
		 * channel.
		 */
		if (p2p_config_get_random_social(&p2p, &p2p.reg_class,
						 &p2p.channel) != 0) {
			wpa_printf(MSG_ERROR,
				   "P2P: Failed to select random social channel as listen channel");
			return -1;
		}
		p2p.channel_forced = 0;
	}
	wpa_printf(MSG_DEBUG, "P2P: Own listen channel: %d:%d",
		   p2p.reg_class, p2p.channel);

	if (wpa_s->conf->p2p_oper_reg_class &&
	    wpa_s->conf->p2p_oper_channel) {
		p2p.op_reg_class = wpa_s->conf->p2p_oper_reg_class;
		p2p.op_channel = wpa_s->conf->p2p_oper_channel;
		p2p.cfg_op_channel = 1;
		wpa_printf(MSG_DEBUG, "P2P: Configured operating channel: "
			   "%d:%d", p2p.op_reg_class, p2p.op_channel);

	} else {
		/*
		 * Use random operation channel from 2.4 GHz band social
		 * channels (1, 6, 11) or band 60 GHz social channel (2) if no
		 * other preference is indicated.
		 */
		if (p2p_config_get_random_social(&p2p, &p2p.op_reg_class,
						 &p2p.op_channel) != 0) {
			wpa_printf(MSG_ERROR,
				   "P2P: Failed to select random social channel as operation channel");
			return -1;
		}
		p2p.cfg_op_channel = 0;
		wpa_printf(MSG_DEBUG, "P2P: Random operating channel: "
			   "%d:%d", p2p.op_reg_class, p2p.op_channel);
	}

	if (wpa_s->conf->p2p_pref_chan && wpa_s->conf->num_p2p_pref_chan) {
		p2p.pref_chan = wpa_s->conf->p2p_pref_chan;
		p2p.num_pref_chan = wpa_s->conf->num_p2p_pref_chan;
	}

	//设置国家码
	if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
		os_memcpy(p2p.country, wpa_s->conf->country, 2);
		p2p.country[2] = 0x04;
	} else
		//配置国家中没有设置国家,所以取值为"XX\x04"
		os_memcpy(p2p.country, "XX\x04", 3);

	os_memcpy(p2p.pri_dev_type, wpa_s->conf->device_type,
		  WPS_DEV_TYPE_LEN);

	p2p.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
	os_memcpy(p2p.sec_dev_type, wpa_s->conf->sec_device_type,
		  p2p.num_sec_dev_types * WPS_DEV_TYPE_LEN);

	//是否支持 concurrent operation
	p2p.concurrent_operations = !!(wpa_s->drv_flags &
				       WPA_DRIVER_FLAGS_P2P_CONCURRENT);

	p2p.max_peers = 100;//最多能保存100个对端P2P Device信息

	//配置文件中没有设置 p2p_ssid_postfix,但 P2pStateMachine在initializeP2pSettings函数中将设置P2P SSID后缀。以笔者的Galaxy Note 2为例,其P2P SSID 后缀为Android_4aa9
	if (wpa_s->conf->p2p_ssid_postfix) {
		p2p.ssid_postfix_len =
			os_strlen(wpa_s->conf->p2p_ssid_postfix);
		if (p2p.ssid_postfix_len > sizeof(p2p.ssid_postfix))
			p2p.ssid_postfix_len = sizeof(p2p.ssid_postfix);
		os_memcpy(p2p.ssid_postfix, wpa_s->conf->p2p_ssid_postfix,
			  p2p.ssid_postfix_len);
	}

	p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss;

	p2p.max_listen = wpa_s->max_remain_on_chan;

	if (wpa_s->conf->p2p_passphrase_len >= 8 &&
	    wpa_s->conf->p2p_passphrase_len <= 63)
		p2p.passphrase_len = wpa_s->conf->p2p_passphrase_len;
	else
		p2p.passphrase_len = 8;

	//global->p2p指向一个p2p_data结构体,它是WPAS中P2P模块的代表
	global->p2p = p2p_init(&p2p);
	if (global->p2p == NULL)
		return -1;
	global->p2p_init_wpa_s = wpa_s;

	for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {//拷贝vendor厂商特定的WSC属性信息
		if (wpa_s->conf->wps_vendor_ext[i] == NULL)
			continue;
		p2p_add_wps_vendor_extension(
			global->p2p, wpa_s->conf->wps_vendor_ext[i]);
	}

	p2p_set_no_go_freq(global->p2p, &wpa_s->conf->p2p_no_go_freq);

	return 0;
}
wpas_p2p_init主要包括:
1.初始化一个p2p_config对象,然后根据 p2p_supplicant.conf文件的信息来设置其中的内容,同时还需要为P2P模块设置一些回调函数
2.调用p2p_init 函数以初始化 P2P模块
先看 drv_flags 变量。WPAS中,Wi-Fi驱动对P2P功能的支持情况就是由它来表述的。其表达含义如下:
android-5.1/external/wpa_supplicant_8/src/drivers/driver.h

/* Driver supports AP mode */
//wifi driver支持AP。它使得P2P设备能扮演GO
#define WPA_DRIVER_FLAGS_AP		0x00000040
/* Driver needs static WEP key setup after association has been completed */
//标志标明association成功后,Kernel driver需要设置WEP key
#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE	0x00000080
/* Driver supports concurrent P2P operations */
#define WPA_DRIVER_FLAGS_P2P_CONCURRENT	0x00000200	//wifi driver支持STA和P2P的并发运行
/* This interface is P2P capable (P2P GO or P2P Client) */
//wifi driver支持P2P
#define WPA_DRIVER_FLAGS_P2P_CAPABLE	0x00000800
/*
 * Driver uses the initial interface for P2P management interface and non-P2P
 * purposes (e.g., connect to infra AP), but this interface cannot be used for
 * P2P group operations.
 */
//P2P包含Device Address和Interface Address两种类型的地址。在实际实现过程中,这两个地址分别代表两个Virtual Interface。 显然,P2P中第一个和一直存在的是拥有Device Address的Virtual Interface。下面这个标志表示该Virtual Interface可以参与P2P管理(除P2P Group Operation之外的工作)工作以及非P2P相关的工作(例如利用这个Virtual Interface加入到一个BSS)。
#define WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P		0x00002000
/*
 * Driver is known to use sane error codes, i.e., when it indicates that
 * something (e.g., association) fails, there was indeed a failure and the
 * operation does not end up getting completed successfully later.
 */
//该标志主要针对associate操作。当关联操作失败后,如果driver支持该选项,则表明driver能处理失败之后的各种收尾工作(Key、timeout等工作)。否则,WPAS需要自己处理这些事情
#define WPA_DRIVER_FLAGS_SANE_ERROR_CODES		0x00004000
/* Driver supports off-channel TX */
//下面这个标志和off channel机制有关。当802.11 MAC帧通过off channel发送,下面这个标志表示driver会反馈一个发送情况(TX Report)消息给WPAS
#define WPA_DRIVER_FLAGS_OFFCHANNEL_TX			0x00008000
/* Driver indicates TX status events for Deauth/Disassoc frames */
//下面这标志表示Kernel中的driver是否能反馈Deauthentication/Disassociation帧发送情况(TX Report)
#define WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS		0x00020000
下面看数据结构p2p_config和p2p_data
p2p_config定义了20个回调函数。这些回调函数定义了P2P模块和外界交互的接口。在 wpas_p2p_init中,这些回调函数均指向 p2p_supplicant.c 中对应的函数, 例如p2p_scan指向 wpas_p2p_scan,dev_lost指向wpas_dev_lost。
p2p_data指向一个p2p_config对象
p2p_device代表一个P2P设备。其中设备名、Device CapabilityBitmap等信息保存在一个类型为p2p_peer_info 的对象中。
p2p_group代表一个P2P Group的信息,其内部包含一个p2p_group_config对象和一个 p2p_group_member链表。 p2p_group_config表示该Group的配置信息,p2p_group_member代表Group Member即P2P Client的信息。

android-5.1/external/wpa_supplicant_8/src/p2p/p2p.c

struct p2p_data * p2p_init(const struct p2p_config *cfg)
{
	struct p2p_data *p2p;

	if (cfg->max_peers < 1 ||
	    cfg->passphrase_len < 8 || cfg->passphrase_len > 63)
		return NULL;

	//从下面这行代码可看出,一个p2p_data对象的内存分布,该内存将包含一个p2p_data的所有信息以及一个p2p_config对象的所有信息。
	p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg));
	if (p2p == NULL)
		return NULL;
	//将p2p_data的cfg成员变量指向保存p2p_config信息的那块内存地址
	p2p->cfg = (struct p2p_config *) (p2p + 1);
	os_memcpy(p2p->cfg, cfg, sizeof(*cfg));//拷贝传入的p2p_config信息
	if (cfg->dev_name)
		p2p->cfg->dev_name = os_strdup(cfg->dev_name);
	if (cfg->manufacturer)
		p2p->cfg->manufacturer = os_strdup(cfg->manufacturer);
	if (cfg->model_name)
		p2p->cfg->model_name = os_strdup(cfg->model_name);
	if (cfg->model_number)
		p2p->cfg->model_number = os_strdup(cfg->model_number);
	if (cfg->serial_number)
		p2p->cfg->serial_number = os_strdup(cfg->serial_number);
	if (cfg->pref_chan) {
		p2p->cfg->pref_chan = os_malloc(cfg->num_pref_chan *
						sizeof(struct p2p_channel));
		if (p2p->cfg->pref_chan) {
			os_memcpy(p2p->cfg->pref_chan, cfg->pref_chan,
				  cfg->num_pref_chan *
				  sizeof(struct p2p_channel));
		} else
			p2p->cfg->num_pref_chan = 0;
	}

	p2p->min_disc_int = 1;
	p2p->max_disc_int = 3;
	p2p->max_disc_tu = -1;

	//随机获取next_tie_breaker的初值
	//第二个参数1表示next_tie_breaker的字节长度,其类型是u8
	if (os_get_random(&p2p->next_tie_breaker, 1) < 0)
		p2p->next_tie_breaker = 0;
	p2p->next_tie_breaker &= 0x01;
	//设置本机P2P Device的device capability信息
	if (cfg->sd_request)
		p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
	p2p->dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE;
	if (cfg->concurrent_operations)//支持concurrent功能
		p2p->dev_capab |= P2P_DEV_CAPAB_CONCURRENT_OPER;
	p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;

	dl_list_init(&p2p->devices);

	//注册一个超时时间,用来检测是否有不活跃的p2p_device
	eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,
			       p2p_expiration_timeout, p2p, NULL);

	p2p->go_timeout = 100;
	p2p->client_timeout = 20;
	p2p->num_p2p_sd_queries = 0;

	p2p_dbg(p2p, "initialized");
	p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
	p2p_channels_dump(p2p, "cli_channels", &p2p->cfg->cli_channels);

	return p2p;
}
注册Action帧监听事件
android-5.1/external/wpa_supplicant_8/src/drivers/driver_nl80211.c

static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
				       enum nl80211_iftype nlmode)
{
	return wpa_driver_nl80211_set_mode_impl(bss, nlmode, NULL);
}
static int wpa_driver_nl80211_set_mode_impl(
		struct i802_bss *bss,
		enum nl80211_iftype nlmode,
		struct hostapd_freq_params *desired_freq_params)
{
//注意在函数wpa_driver_nl80211_finish_drv_init中,nlmode被设置为NL80211_IFTYPE_STATION
	struct wpa_driver_nl80211_data *drv = bss->drv;
	int ret = -1;
	int i;
	//drv_nlmode的类型为enum nl80211_iftype。drv->nlmode只有为 NL80211_IFTYPE_AP或NL80211_IFTYPE_P2P_GO时, is_ap_interface 函数才返回非0值。 很显然此时 virtual interface的类型不可能是GO。
	int was_ap = is_ap_interface(drv->nlmode);
	int res;
	int mode_switch_res;

	//设置虚拟interface 的类型为 NL80211_IFTYPE_STATION
	mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
	if (mode_switch_res && nlmode == nl80211_get_ifmode(bss))
		mode_switch_res = 0;

	if (mode_switch_res == 0) {
		drv->nlmode = nlmode;
		ret = 0;
		goto done;//设置成功,直接跳转到done处
	}

	if (mode_switch_res == -ENODEV)
		return -1;

	if (nlmode == drv->nlmode) {
		wpa_printf(MSG_DEBUG, "nl80211: Interface already in "
			   "requested mode - ignore error");
		ret = 0;
		goto done; /* Already in the requested mode */
	}

	/* mac80211 doesn't allow mode changes while the device is up, so
	 * take the device down, try to set the mode again, and bring the
	 * device back up.
	 */
	wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting "
		   "interface down");
	for (i = 0; i < 10; i++) {
		res = i802_set_iface_flags(bss, 0);
		if (res == -EACCES || res == -ENODEV)
			break;
		if (res != 0) {
			wpa_printf(MSG_DEBUG, "nl80211: Failed to set "
				   "interface down");
			os_sleep(0, 100000);
			continue;
		}

		/*
		 * Setting the mode will fail for some drivers if the phy is
		 * on a frequency that the mode is disallowed in.
		 */
		if (desired_freq_params) {
			res = i802_set_freq(bss, desired_freq_params);
			if (res) {
				wpa_printf(MSG_DEBUG,
					   "nl80211: Failed to set frequency on interface");
			}
		}

		/* Try to set the mode again while the interface is down */
		mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
		if (mode_switch_res == -EBUSY) {
			wpa_printf(MSG_DEBUG,
				   "nl80211: Delaying mode set while interface going down");
			os_sleep(0, 100000);
			continue;
		}
		ret = mode_switch_res;
		break;
	}

	if (!ret) {
		wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while "
			   "interface is down");
		drv->nlmode = nlmode;
		drv->ignore_if_down_event = 1;
	}

	/* Bring the interface back up */
	res = linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);
	if (res != 0) {
		wpa_printf(MSG_DEBUG,
			   "nl80211: Failed to set interface up after switching mode");
		ret = -1;
	}

done:
	if (ret) {
		wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
			   "from %d failed", nlmode, drv->nlmode);
		return ret;
	}

	if (is_p2p_net_interface(nlmode))
		nl80211_disable_11b_rates(drv, drv->ifindex, 1);
	else if (drv->disabled_11b_rates)
		nl80211_disable_11b_rates(drv, drv->ifindex, 0);

	if (is_ap_interface(nlmode)) {
		nl80211_mgmt_unsubscribe(bss, "start AP");
		/* Setup additional AP mode functionality if needed */
		if (nl80211_setup_ap(bss))
			return -1;
	} else if (was_ap) {
		/* Remove additional AP mode functionality */
		nl80211_teardown_ap(bss);
	} else {
		//本例将执行下面这个函数以取消监听Action帧事件
		//由于之前并未注册,所以此时执行这个函数将没有实际作用
		nl80211_mgmt_unsubscribe(bss, "mode change");
	}

	if (!bss->in_deinit && !is_ap_interface(nlmode) &&
	    nl80211_mgmt_subscribe_non_ap(bss) < 0)//注册对Action帧的监听事件
		wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
			   "frame processing - ignore for now");

	return 0;
}
nl80211_mgmt_subscribe_non_ap 将注册对Action帧的监听事件,其作用就是当设备收到Action帧后,Wi-Fi驱动将发送对应的netlink消息给WPAS。

static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
{
	struct wpa_driver_nl80211_data *drv = bss->drv;
	int ret = 0;

	//下面这个函数将注册libnl回调事件到event loop。当WPAS收到对应的netlink消息后,process_bss_event函数将被调用
	if (nl80211_alloc_mgmt_handle(bss))
		return -1;
	wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
		   "handle %p", bss->nl_mgmt);

	if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
		u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4);

		/* register for any AUTH message */
		nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0);
	}

#ifdef CONFIG_INTERWORKING
	/* QoS Map Configure */
	if (nl80211_register_action_frame(bss, (u8 *) "\x01\x04", 2) < 0)
		ret = -1;
#endif /* CONFIG_INTERWORKING */
#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)
	//注册对GAS Pubic Action帧的监听,Service Discovery和它有关
	/* GAS Initial Request */
	if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)
		ret = -1;
	/* GAS Initial Response */
	if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0)
		ret = -1;
	/* GAS Comeback Request */
	if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0)
		ret = -1;
	/* GAS Comeback Response */
	if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
		ret = -1;
	/* Protected GAS Initial Request */
	if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0a", 2) < 0)
		ret = -1;
	/* Protected GAS Initial Response */
	if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0b", 2) < 0)
		ret = -1;
	/* Protected GAS Comeback Request */
	if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0c", 2) < 0)
		ret = -1;
	/* Protected GAS Comeback Response */
	if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0d", 2) < 0)
		ret = -1;
#endif /* CONFIG_P2P || CONFIG_INTERWORKING */
#ifdef CONFIG_P2P
	//注册对P2P Public Action 帧的监听,第二个参数中的04-09-50-6F-9A-09指明了P2P Public Action帧Frame Body的Category、Action Field、OUI、OUI-Type 的取值,即只有收到的Frame Body对应字段分别等于上述指定值的Action帧,Wi-Fi驱动才会发送netlink消息给WPAS。
	/* P2P Public Action */
	if (nl80211_register_action_frame(bss,
					  (u8 *) "\x04\x09\x50\x6f\x9a\x09",
					  6) < 0)
		ret = -1;
	/* P2P Action */
	//注册对P2P Action帧的监听,第二个参数中7F-50-6F-9A-09指明了Action 帧Frame Body的Category和OUI。根据802.11规范,7F代表Vendor Specific,50-6F-9A是WFA的OUI,最后一个09代表P2P。
	if (nl80211_register_action_frame(bss,
					  (u8 *) "\x7f\x50\x6f\x9a\x09",
					  5) < 0)
		ret = -1;
#endif /* CONFIG_P2P */
#ifdef CONFIG_IEEE80211W
	/* SA Query Response */
	if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0)
		ret = -1;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_TDLS
	if ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) {
		/* TDLS Discovery Response */
		if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0e", 2) <
		    0)
			ret = -1;
	}
#endif /* CONFIG_TDLS */

	/* FT Action frames */
	if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
		ret = -1;
	else
		drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
			WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;

	/* WNM - BSS Transition Management Request */
	if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0)
		ret = -1;
	/* WNM-Sleep Mode Response */
	if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0)
		ret = -1;

#ifdef CONFIG_HS20
	/* WNM-Notification */
	if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x1a", 2) < 0)
		ret = -1;
#endif /* CONFIG_HS20 */

	nl80211_mgmt_handle_register_eloop(bss);

	return ret;
}
由上述代码可知 nl80211_mgmt_subscribe_non_ap在P2P方面注册了两种类型的帧监听事件。
P2P Pubic Action帧监听事件:根据P2P规范,目前使用的均是802.11 Public Action帧,即Category的值为0x04。目前GON、P2P Invitation、Provision Discovery以及Device Discoverability使用P2P Public Action帧
P2P Action帧监听事件:这种类型的帧属于802.11 Action帧的一种,其Category取值为0x7F,OUI指定为WFA的OUI(即50-6F-9A),而OUI-Type指定为P2P(取值为0x09)。 目前Notice of Absence、P2P Presence、GO Discoverability使用P2P Action帧。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值