【修复miracast协商失败问题】

改动 1: 在 p2p_add_device() 中设置 WPS Method

改动位置

文件 : src/p2p/p2p.c
函数 : p2p_add_device()
位置: 约第 912-915 行

改动内容

改动前(原代码):

c 复制代码
if (msg.adv_service_instance)
    dev->flags |= P2P_DEV_P2PS_REPORTED;

return 0;

改动后(新代码):

c 复制代码
if (msg.adv_service_instance)
    dev->flags |= P2P_DEV_P2PS_REPORTED;

if (msg.wps_config_methods & WPS_CONFIG_PUSHBUTTON) {
    dev->wps_method = WPS_PBC;
    dev->oob_pw_id = p2p_wps_method_pw_id(dev->wps_method);
}

return 0;

改动原因分析

问题场景
  1. 首次协商失败: 当对端设备(如 OPPO K7X 手机)通过 Probe Request/Response 被发现时,如果对端支持 PBC(Push Button Configuration),但本地设备没有及时记录这个信息
  2. WPS Method 未设置 : 后续进行 GO Negotiation 时,如果 dev->wps_method 仍然是默认值(可能是 WPS_NOT_READY),会导致协商失败
工作原理
  • p2p_add_device(): 在解析 Probe Request/Response 或 Beacon 帧时调用,用于添加或更新对端设备信息
  • WPS Config Methods : Probe Response 帧中包含 wps_config_methods 字段,指示对端支持的 WPS 配置方法
  • WPS_CONFIG_PUSHBUTTON (0x0080): 表示对端支持 PBC 方法
改动效果
  1. 提前记录 WPS 方法: 在设备发现阶段就记录对端支持的 WPS 方法(PBC)
  2. 避免后续失败 : 当后续进行 GO Negotiation 时,dev->wps_method 已经正确设置,不会因为 WPS_NOT_READY 而失败
  3. 提高首次连接成功率: 特别是对于某些手机(如 OPPO K7X),这个改动能显著提高连接成功率

改动 2: 在接收 Action 帧时设置 Intended Address

改动位置

文件 : wpa_supplicant/p2p_supplicant.c
函数 : wpas_p2p_rx_action()
位置: 约第 7536-7539 行

改动内容

改动前(原代码):

c 复制代码
void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
                        const u8 *sa, const u8 *bssid,
                        u8 category, const u8 *data, size_t len, int freq)
{
    if (wpa_s->global->p2p_disabled)
        return;
    if (wpa_s->global->p2p == NULL)
        return;

    p2p_rx_action(wpa_s->global->p2p, da, sa, bssid, category, data, len,
                  freq);
}

改动后(新代码):

c 复制代码
void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
                        const u8 *sa, const u8 *bssid,
                        u8 category, const u8 *data, size_t len, int freq)
{
    if (wpa_s->global->p2p_disabled)
        return;
    if (wpa_s->global->p2p == NULL)
        return;

    p2p_set_intended_addr(wpa_s->global->p2p,
            wpa_s->p2p_mgmt ?
            wpa_s->parent->own_addr :
            wpa_s->own_addr);
    p2p_rx_action(wpa_s->global->p2p, da, sa, bssid, category, data, len,
                  freq);
}

改动原因分析

Intended Address 的作用
  • Intended P2P Interface Address: 在 P2P GO Negotiation 或 Invitation 流程中,用于指示"将来要使用的 P2P 接口地址"
  • GO Negotiation Request/Response : 这些 Action 帧中包含 Intended P2P Interface Address attribute,告诉对端本设备将要使用的 MAC 地址
问题场景
  1. 多接口环境 : 在某些情况下(特别是使用 p2p_mgmt 接口时),wpa_s->own_addr 可能不是实际要使用的地址
  2. 地址不一致: 如果发送 GO Negotiation Request 时使用的地址和接收 Response 时设置的地址不一致,可能导致协商失败
  3. 首次协商失败: 第一次协商时,可能因为地址设置不正确而导致失败
改动效果
  1. 动态更新地址: 每次接收 Action 帧时,都重新设置 intended address
  2. 正确处理多接口 : 如果有 p2p_mgmt 接口,使用父接口的地址;否则使用当前接口的地址
  3. 确保地址一致性: 保证发送和接收时使用的地址是一致的

两个改动的关系

虽然这两个改动看起来独立,但它们共同解决"首次协商失败"的问题:

  1. 改动 1 (WPS Method): 确保 WPS 配置方法正确设置,避免因 WPS method 不匹配导致的失败
  2. 改动 2 (Intended Address): 确保 P2P 接口地址正确设置,避免因地址不一致导致的失败

两者结合使用,能够显著提高首次 P2P 连接的成功率。


实际影响分析

✅ 正面影响

  1. 提高首次连接成功率:

    • 解决了首次协商总是失败的问题
    • 特别是对某些手机设备(如 OPPO K7X)的连接成功率显著提升
  2. 更早的 WPS 方法识别:

    • 在设备发现阶段就识别并记录 WPS 方法
    • 避免后续协商时的状态错误
  3. 地址管理改进:

    • 动态更新 intended address
    • 在多接口环境中正确工作

⚠️ 潜在考虑

  1. 性能影响(轻微):

    • 每次接收 Action 帧时都设置 intended address
    • 但这个操作开销很小,影响可以忽略
  2. 地址设置的时机:

    • 目前是在接收时设置,理论上应该在发送前设置
    • 但考虑到 Action 帧的处理流程,在接收时设置也是合理的

⚠️ 改动 2: Intended Address 设置 - 潜在问题

分析

当前实现
c 复制代码
p2p_set_intended_addr(wpa_s->global->p2p,
        wpa_s->p2p_mgmt ?
        wpa_s->parent->own_addr :
        wpa_s->own_addr);
潜在问题
  1. 设置时机可能不合适:

    • 每次接收 Action 帧时都设置 intended address
    • 但这个地址应该是"将来要使用的接口地址",应该在发送 GO Negotiation Request 之前设置,而不是接收时设置
    • 虽然不一定会导致问题,但逻辑上不够清晰
  2. 与其他设置位置的冲突:

    • 代码中还有其他地方设置 intended address(例如第 875、887 行)
    • 频繁覆盖可能导致地址不一致
  3. p2p_mgmt 接口处理:

    • 逻辑是:如果有 p2p_mgmt 接口,使用父接口地址;否则使用当前接口地址
    • 这个逻辑是合理的,但需要确保 parent 不是 NULL

建议的改进

方案 1: 添加空指针检查
c 复制代码
p2p_set_intended_addr(wpa_s->global->p2p,
        wpa_s->p2p_mgmt && wpa_s->parent ?
        wpa_s->parent->own_addr :
        wpa_s->own_addr);
方案 2: 只在特定时机设置

只在接收 GO Negotiation Request 或 Invitation Request 时设置,而不是所有 Action 帧:

c 复制代码
/* Only set intended address when receiving GO Negotiation or Invitation */
if (category == WLAN_ACTION_P2P_GO_NEG_REQ ||
    category == WLAN_ACTION_P2P_INV_REQ) {
    p2p_set_intended_addr(wpa_s->global->p2p,
            wpa_s->p2p_mgmt && wpa_s->parent ?
            wpa_s->parent->own_addr :
            wpa_s->own_addr);
}
方案 3: 检查是否真的需要

查看是否有必要在接收时设置,或者应该在发送前统一设置。


c 复制代码
    1. fix first negotiation always fail. 2. fix oppo k7x almost cannot conneced.
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 27fd8e5..f0c31f1 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -903,6 +903,11 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
 	if (msg.adv_service_instance)
 		dev->flags |= P2P_DEV_P2PS_REPORTED;
 
+	if (msg.wps_config_methods & WPS_CONFIG_PUSHBUTTON) {
+		dev->wps_method = WPS_PBC;
+		dev->oob_pw_id = p2p_wps_method_pw_id(dev->wps_method);
+	}
+
 	return 0;
 }
 
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
old mode 100755
new mode 100644
index d19c7d7..473c612
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -6763,6 +6763,10 @@ void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
 	if (wpa_s->global->p2p == NULL)
 		return;
 
+	p2p_set_intended_addr(wpa_s->global->p2p,
+			wpa_s->p2p_mgmt ?
+			wpa_s->parent->own_addr :
+			wpa_s->own_addr);
 	p2p_rx_action(wpa_s->global->p2p, da, sa, bssid, category, data, len,
 		      freq);
 }
相关推荐
Coder_Boy_2 小时前
基于SpringAI的智能平台基座开发-(六)
java·数据库·人工智能·spring·langchain·langchain4j
热爱专研AI的学妹2 小时前
数眼搜索API与博查技术特性深度对比:实时性与数据完整性的核心差异
大数据·开发语言·数据库·人工智能·python
hopsky2 小时前
ShardingSphere功能简介
数据库·sql
QQ__17646198242 小时前
Ubuntu系统创建新用户与删除用户
linux·运维·服务器
talenteddriver2 小时前
mysql: MySQL索引和排序相关名词概念汇总
数据库·mysql
渣渣盟3 小时前
Linux邮件服务器快速搭建指南
linux·服务器·开发语言
6极地诈唬3 小时前
【PG漫步】DELETE不会改变本地文件的大小,VACUUM也不会
linux·服务器·数据库
谷雨不太卷3 小时前
Linux_文件权限
linux·运维·服务器
MZWeiei4 小时前
Redis持久化机制中的 AOF机制简单介绍
数据库·redis
Elastic 中国社区官方博客4 小时前
Elasticsearch:在 X-mas 吃一些更健康的东西
android·大数据·数据库·人工智能·elasticsearch·搜索引擎·全文检索