改动点详细分析
1. 修复 GO Negotiation Response 中缺少 Operating Channel Attribute 的问题
改动位置 : src/p2p/p2p_go_neg.c 第 323-326 行
改动内容:
c
#if 0
} else if (peer && peer->go_state == REMOTE_GO && !p2p->num_pref_freq) {
p2p_dbg(p2p, "Omit Operating Channel attribute");
#endif
原因分析:
- 问题: 当对端设备是 REMOTE_GO(已存在的 GO)且本地没有预设频率偏好时,原代码会省略 Operating Channel attribute。
- 影响 : 某些手机/PC 在收到没有 Operating Channel 的 GO Negotiation Response 时会拒绝连接,导致
P2P-GO-NEG-FAILURE。 - 解决方案 : 通过
#if 0禁用这段逻辑,确保 GO Negotiation Response 总是包含 Operating Channel attribute,提高兼容性。
2. 修复 P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE 状态错误
改动位置 : src/p2p/p2p_go_neg.c 第 837-841 行
改动内容:
c
if (msg.config_methods & WPS_CONFIG_PUSHBUTTON) {
dev->wps_method = WPS_PBC;
dev->oob_pw_id = p2p_wps_method_pw_id(dev->wps_method);
}
原因分析:
- 问题 : 当收到 GO Negotiation Request 时,如果对端使用的是 PBC(Push Button Configuration)方式,但本地没有正确记录
dev->wps_method和dev->oob_pw_id,会导致后续 WPS 流程判断错误,可能返回P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE状态。 - 影响: 即使双方都支持 PBC,也可能因为 WPS method 不匹配而导致协商失败。
- 解决方案 : 在处理 GO Negotiation Request 时,如果检测到对端使用 PBC(
WPS_CONFIG_PUSHBUTTON),立即设置本地 peer 设备的 WPS method 为WPS_PBC,并更新对应的 OOB Password ID,确保双方 WPS 配置一致。
3. 使用手机/电脑的操作信道偏好
改动位置 : src/p2p/p2p_go_neg.c 第 849-870 行
改动内容:
c
if (msg.operating_channel) {
/* Use peer preference if specified and compatible */
int req_freq;
req_freq = p2p_channel_to_freq(
msg.operating_channel[3],
msg.operating_channel[4]);
p2p_dbg(p2p, "Peer operating channel preference: %d MHz",
req_freq);
if (req_freq > 0 &&
p2p_channels_includes(&p2p->cfg->channels,
msg.operating_channel[3],
msg.operating_channel[4])) {
p2p->op_reg_class = msg.operating_channel[3];
p2p->op_channel = msg.operating_channel[4];
p2p_dbg(p2p, "Use peer preference op_class %d channel %d",
p2p->op_reg_class, p2p->op_channel);
}
}
原因分析:
- 问题: 原代码在处理 GO Negotiation Request 时,主要使用本地预设的信道偏好,而忽略了对端(手机/PC)在请求中携带的 Operating Channel preference。
- 影响 :
- 如果手机/PC 明确指定了偏好的信道(例如 5GHz 频段的某个信道),但本地强制使用另一个信道,可能导致:
- 对端不支持本地选择的信道(特别是某些手机只支持部分 5GHz 信道)
- 对端虽然支持但需要切换,增加连接延迟
- 如果手机/PC 明确指定了偏好的信道(例如 5GHz 频段的某个信道),但本地强制使用另一个信道,可能导致:
- 解决方案 :
- 解析对端 GO Negotiation Request 中的 Operating Channel attribute
- 检查该信道是否在本地的可用信道列表中
- 如果兼容,优先使用对端的信道偏好 ,这样可以:
- 提高兼容性(使用对端已知支持的信道)
- 减少信道切换时间
- 提升首次连接成功率
4. 不使用强制信道以避免手机/电脑不支持
改动位置 : src/p2p/p2p_invitation.c 第 283-284 行
改动内容:
c
/* don't use force freq to avoid peer not support */
op_freq = 0;
if (op_freq) {
原因分析:
- 问题 : 在 P2P Invitation 流程中,如果本地有强制频率设置(
op_freq),会强制要求对端使用该频率,但某些手机/PC 可能不支持该频率或需要额外时间切换。 - 影响 :
- 导致 Invitation 失败或连接延迟增加
- 特别是当对端设备已经在一个固定频率上运行时,强制切换频率可能失败
- 解决方案 :
- 在处理 Invitation Request 时,将
op_freq置为 0,不强制使用特定频率 - 让 P2P 协议栈根据双方可用信道列表自动协商最佳信道
- 这样可以避免对端设备不支持强制频率导致的连接失败
- 在处理 Invitation Request 时,将
总结
这个 patch 的核心目标是:提高 Miracast 连接在不同手机/PC 设备上的兼容性和成功率。
关键改进点:
- 保证协议完整性: 总是发送 Operating Channel attribute,避免某些设备拒绝连接
- 正确识别 WPS 方法: 确保 PBC 方式的 WPS method 正确设置,避免状态错误
- 尊重对端信道偏好: 优先使用对端指定的信道,提高兼容性和连接速度
- 避免强制频率冲突: 在 Invitation 流程中不强制频率,让协议栈自动协商
实际效果:
- ✅ 减少
P2P-GO-NEG-FAILURE和P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE错误 - ✅ 提高首次 Miracast 连接成功率
- ✅ 缩短连接建立时间(减少信道切换)
- ✅ 增强对不同品牌手机/PC 的兼容性
c
1.fix neg resp without operating channel attribute
2.fix P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE status error
3.use phone/computer opertating channel
4.don't use force channel to avoid phone/computer not support
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index b1f392e..e31c44a 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -320,8 +320,10 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
p2p->override_pref_op_class,
p2p->override_pref_channel);
+#if 0
} else if (peer && peer->go_state == REMOTE_GO && !p2p->num_pref_freq) {
p2p_dbg(p2p, "Omit Operating Channel attribute");
+#endif
} else {
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
p2p->op_reg_class,
@@ -847,6 +849,11 @@ void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
if (p2p->go_neg_peer && p2p->go_neg_peer == dev)
eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
+ if (msg.config_methods & WPS_CONFIG_PUSHBUTTON) {
+ dev->wps_method = WPS_PBC;
+ dev->oob_pw_id = p2p_wps_method_pw_id(dev->wps_method);
+ }
+
if (dev && dev->flags & P2P_DEV_USER_REJECTED) {
p2p_dbg(p2p, "User has rejected this peer");
status = P2P_SC_FAIL_REJECTED_BY_USER;
@@ -880,6 +887,28 @@ void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
p2p_dbg(p2p, "Use previously configured forced channel settings");
}
}
+ if (msg.operating_channel) {
+ /* Use peer preference if specified and compatible */
+ int req_freq;
+ req_freq = p2p_channel_to_freq(
+ msg.operating_channel[3],
+ msg.operating_channel[4]);
+ p2p_dbg(p2p, "Peer operating channel preference: %d MHz",
+ req_freq);
+ if (req_freq > 0 &&
+ p2p_channels_includes(&p2p->cfg->channels,
+ msg.operating_channel[3],
+ msg.operating_channel[4])) {
+ p2p->op_reg_class = msg.operating_channel[3];
+ p2p->op_channel = msg.operating_channel[4];
+ p2p_dbg(p2p, "Use peer preference op_class %d channel %d",
+ p2p->op_reg_class, p2p->op_channel);
+ }
+ }
dev->flags &= ~P2P_DEV_NOT_YET_READY;
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index a0b7f5f..5dc0a2c 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -283,7 +283,8 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
goto fail;
}
}
-
+ /* don't use force freq to avoid peer not support */
+ op_freq = 0;
if (op_freq) {
p2p_dbg(p2p, "Invitation processing forced frequency %d MHz",
op_freq);