P2P: Allow P2P listen being offloaded to the driver/firmware
This allows P2P Listen to be offloaded to device to enhance power saving. To start P2P listen offload, from wpa_cli interface, issue the command: p2p_lo_start <freq> <period> <interval> <count> To stop P2P listen offload, issue the command: p2p_lo_stop Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
35d6655755
commit
a6f5b1937a
15 changed files with 436 additions and 43 deletions
132
src/p2p/p2p.c
132
src/p2p/p2p.c
|
@ -2234,6 +2234,58 @@ struct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p,
|
|||
return buf;
|
||||
}
|
||||
|
||||
static int p2p_build_probe_resp_buf(struct p2p_data *p2p, struct wpabuf *buf,
|
||||
struct wpabuf *ies,
|
||||
const u8 *addr, int rx_freq)
|
||||
{
|
||||
struct ieee80211_mgmt *resp;
|
||||
u8 channel, op_class;
|
||||
|
||||
resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
|
||||
u.probe_resp.variable));
|
||||
|
||||
resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
|
||||
(WLAN_FC_STYPE_PROBE_RESP << 4));
|
||||
os_memcpy(resp->da, addr, ETH_ALEN);
|
||||
os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
|
||||
os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
|
||||
resp->u.probe_resp.beacon_int = host_to_le16(100);
|
||||
/* hardware or low-level driver will setup seq_ctrl and timestamp */
|
||||
resp->u.probe_resp.capab_info =
|
||||
host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
|
||||
WLAN_CAPABILITY_PRIVACY |
|
||||
WLAN_CAPABILITY_SHORT_SLOT_TIME);
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_EID_SSID);
|
||||
wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
|
||||
wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
|
||||
wpabuf_put_u8(buf, 8);
|
||||
wpabuf_put_u8(buf, (60 / 5) | 0x80);
|
||||
wpabuf_put_u8(buf, 90 / 5);
|
||||
wpabuf_put_u8(buf, (120 / 5) | 0x80);
|
||||
wpabuf_put_u8(buf, 180 / 5);
|
||||
wpabuf_put_u8(buf, (240 / 5) | 0x80);
|
||||
wpabuf_put_u8(buf, 360 / 5);
|
||||
wpabuf_put_u8(buf, 480 / 5);
|
||||
wpabuf_put_u8(buf, 540 / 5);
|
||||
|
||||
if (!rx_freq) {
|
||||
channel = p2p->cfg->channel;
|
||||
} else if (p2p_freq_to_channel(rx_freq, &op_class, &channel)) {
|
||||
p2p_err(p2p, "Failed to convert freq to channel");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
|
||||
wpabuf_put_u8(buf, 1);
|
||||
wpabuf_put_u8(buf, channel);
|
||||
|
||||
wpabuf_put_buf(buf, ies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p2p_service_find_asp(struct p2p_data *p2p, const u8 *hash)
|
||||
{
|
||||
|
@ -2267,10 +2319,8 @@ p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
|
|||
{
|
||||
struct ieee802_11_elems elems;
|
||||
struct wpabuf *buf;
|
||||
struct ieee80211_mgmt *resp;
|
||||
struct p2p_message msg;
|
||||
struct wpabuf *ies;
|
||||
u8 channel, op_class;
|
||||
|
||||
if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
|
||||
ParseFailed) {
|
||||
|
@ -2414,49 +2464,12 @@ p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
|
|||
return P2P_PREQ_NOT_PROCESSED;
|
||||
}
|
||||
|
||||
resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
|
||||
u.probe_resp.variable));
|
||||
|
||||
resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
|
||||
(WLAN_FC_STYPE_PROBE_RESP << 4));
|
||||
os_memcpy(resp->da, addr, ETH_ALEN);
|
||||
os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
|
||||
os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
|
||||
resp->u.probe_resp.beacon_int = host_to_le16(100);
|
||||
/* hardware or low-level driver will setup seq_ctrl and timestamp */
|
||||
resp->u.probe_resp.capab_info =
|
||||
host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
|
||||
WLAN_CAPABILITY_PRIVACY |
|
||||
WLAN_CAPABILITY_SHORT_SLOT_TIME);
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_EID_SSID);
|
||||
wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
|
||||
wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
|
||||
wpabuf_put_u8(buf, 8);
|
||||
wpabuf_put_u8(buf, (60 / 5) | 0x80);
|
||||
wpabuf_put_u8(buf, 90 / 5);
|
||||
wpabuf_put_u8(buf, (120 / 5) | 0x80);
|
||||
wpabuf_put_u8(buf, 180 / 5);
|
||||
wpabuf_put_u8(buf, (240 / 5) | 0x80);
|
||||
wpabuf_put_u8(buf, 360 / 5);
|
||||
wpabuf_put_u8(buf, 480 / 5);
|
||||
wpabuf_put_u8(buf, 540 / 5);
|
||||
|
||||
if (!rx_freq) {
|
||||
channel = p2p->cfg->channel;
|
||||
} else if (p2p_freq_to_channel(rx_freq, &op_class, &channel)) {
|
||||
if (p2p_build_probe_resp_buf(p2p, buf, ies, addr, rx_freq)) {
|
||||
wpabuf_free(ies);
|
||||
wpabuf_free(buf);
|
||||
return P2P_PREQ_NOT_PROCESSED;
|
||||
}
|
||||
|
||||
wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
|
||||
wpabuf_put_u8(buf, 1);
|
||||
wpabuf_put_u8(buf, channel);
|
||||
|
||||
wpabuf_put_buf(buf, ies);
|
||||
wpabuf_free(ies);
|
||||
|
||||
p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf, rx_freq);
|
||||
|
@ -2470,12 +2483,18 @@ p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
|
|||
enum p2p_probe_req_status
|
||||
p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
|
||||
const u8 *bssid, const u8 *ie, size_t ie_len,
|
||||
unsigned int rx_freq)
|
||||
unsigned int rx_freq, int p2p_lo_started)
|
||||
{
|
||||
enum p2p_probe_req_status res;
|
||||
|
||||
p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
|
||||
|
||||
if (p2p_lo_started) {
|
||||
p2p_dbg(p2p,
|
||||
"Probe Response is offloaded, do not reply Probe Request");
|
||||
return P2P_PREQ_PROCESSED;
|
||||
}
|
||||
|
||||
res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len, rx_freq);
|
||||
if (res != P2P_PREQ_PROCESSED && res != P2P_PREQ_NOT_PROCESSED)
|
||||
return res;
|
||||
|
@ -5490,3 +5509,34 @@ void p2p_set_own_pref_freq_list(struct p2p_data *p2p,
|
|||
i, p2p->pref_freq_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * p2p_build_probe_resp_template(struct p2p_data *p2p,
|
||||
unsigned int freq)
|
||||
{
|
||||
struct wpabuf *ies, *buf;
|
||||
u8 addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
int ret;
|
||||
|
||||
ies = p2p_build_probe_resp_ies(p2p, NULL, 0);
|
||||
if (!ies) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"CTRL: Failed to build Probe Response IEs");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = wpabuf_alloc(200 + wpabuf_len(ies));
|
||||
if (!buf) {
|
||||
wpabuf_free(ies);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = p2p_build_probe_resp_buf(p2p, buf, ies, addr, freq);
|
||||
wpabuf_free(ies);
|
||||
if (ret) {
|
||||
wpabuf_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue