diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index edfcc8a4b..d48873899 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -2325,4 +2325,14 @@ void p2p_set_own_pref_freq_list(struct p2p_data *p2p, const unsigned int *pref_freq_list, unsigned int size); +/** + * p2p_group_get_common_freqs - Get the group common frequencies + * @group: P2P group context from p2p_group_init() + * @common_freqs: On return will hold the group common frequencies + * @num: On return will hold the number of group common frequencies + * Returns: 0 on success, -1 otherwise + */ +int p2p_group_get_common_freqs(struct p2p_group *group, int *common_freqs, + unsigned int *num); + #endif /* P2P_H */ diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c index 41ca99faa..0d6699346 100644 --- a/src/p2p/p2p_group.c +++ b/src/p2p/p2p_group.c @@ -1071,3 +1071,43 @@ void p2p_loop_on_all_groups(struct p2p_data *p2p, break; } } + + +int p2p_group_get_common_freqs(struct p2p_group *group, int *common_freqs, + unsigned int *num) + +{ + struct p2p_channels intersect, res; + struct p2p_group_member *m; + + if (!group || !common_freqs || !num) + return -1; + + os_memset(&intersect, 0, sizeof(intersect)); + os_memset(&res, 0, sizeof(res)); + + p2p_channels_union(&intersect, &group->p2p->cfg->channels, + &intersect); + + p2p_channels_dump(group->p2p, + "Group common freqs before iterating members", + &intersect); + + for (m = group->members; m; m = m->next) { + struct p2p_device *dev; + + dev = p2p_get_device(group->p2p, m->dev_addr); + if (!dev) + continue; + + p2p_channels_intersect(&intersect, &dev->channels, &res); + intersect = res; + } + + p2p_channels_dump(group->p2p, "Group common channels", &intersect); + + os_memset(common_freqs, 0, *num * sizeof(int)); + *num = p2p_channels_to_freqs(&intersect, common_freqs, *num); + + return 0; +} diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 9c256a5b4..88798e303 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -2606,6 +2606,32 @@ static int freq_included(const struct p2p_channels *channels, unsigned int freq) } +static void wpas_p2p_go_update_common_freqs(struct wpa_supplicant *wpa_s) +{ + unsigned int num = P2P_MAX_CHANNELS; + int *common_freqs; + int ret; + + p2p_go_dump_common_freqs(wpa_s); + common_freqs = os_calloc(num, sizeof(int)); + if (!common_freqs) + return; + + ret = p2p_group_get_common_freqs(wpa_s->p2p_group, common_freqs, &num); + if (ret < 0) { + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Failed to get group common freqs"); + os_free(common_freqs); + return; + } + + os_free(wpa_s->p2p_group_common_freqs); + wpa_s->p2p_group_common_freqs = common_freqs; + wpa_s->p2p_group_common_freqs_num = num; + p2p_go_dump_common_freqs(wpa_s); +} + + /* * Check if the given frequency is one of the possible operating frequencies * set after the completion of the GO Negotiation. @@ -8345,6 +8371,8 @@ static void wpas_p2p_move_go(void *eloop_ctx, void *timeout_ctx) if (!wpa_s->ap_iface || !wpa_s->current_ssid) return; + wpas_p2p_go_update_common_freqs(wpa_s); + /* * First, try a channel switch flow. If it is not supported or fails, * take down the GO and bring it up again. @@ -8373,6 +8401,8 @@ static void wpas_p2p_consider_moving_one_go(struct wpa_supplicant *wpa_s, unsigned int timeout; int freq; + wpas_p2p_go_update_common_freqs(wpa_s); + freq = wpa_s->current_ssid->frequency; for (i = 0, invalid_freq = 0; i < num; i++) { if (freqs[i].freq == freq) {