P2P: Add initial support for driver-based P2P management
This adds partial callbacks and events to allow P2P management to be implemented in a driver/firmware. This is not yet complete and is very much subject to change in the future.
This commit is contained in:
parent
f981eabcf0
commit
3ac17eba31
6 changed files with 1242 additions and 8 deletions
|
@ -683,6 +683,17 @@ struct wpa_bss_params {
|
||||||
#define WPA_STA_SHORT_PREAMBLE BIT(2)
|
#define WPA_STA_SHORT_PREAMBLE BIT(2)
|
||||||
#define WPA_STA_MFP BIT(3)
|
#define WPA_STA_MFP BIT(3)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct p2p_params - P2P parameters for driver-based P2P management
|
||||||
|
*/
|
||||||
|
struct p2p_params {
|
||||||
|
const char *dev_name;
|
||||||
|
u8 pri_dev_type[8];
|
||||||
|
#define DRV_MAX_SEC_DEV_TYPES 5
|
||||||
|
u8 sec_dev_type[DRV_MAX_SEC_DEV_TYPES][8];
|
||||||
|
size_t num_sec_dev_types;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct wpa_driver_ops - Driver interface API definition
|
* struct wpa_driver_ops - Driver interface API definition
|
||||||
*
|
*
|
||||||
|
@ -1956,6 +1967,222 @@ struct wpa_driver_ops {
|
||||||
* to speed up various operations.
|
* to speed up various operations.
|
||||||
*/
|
*/
|
||||||
const char * (*get_radio_name)(void *priv);
|
const char * (*get_radio_name)(void *priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_find - Start P2P Device Discovery
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @timeout: Timeout for find operation in seconds or 0 for no timeout
|
||||||
|
* @type: Device Discovery type (enum p2p_discovery_type)
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
int (*p2p_find)(void *priv, unsigned int timeout, int type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_stop_find - Stop P2P Device Discovery
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
int (*p2p_stop_find)(void *priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_listen - Start P2P Listen state for specified duration
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @timeout: Listen state duration in milliseconds
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This function can be used to request the P2P module to keep the
|
||||||
|
* device discoverable on the listen channel for an extended set of
|
||||||
|
* time. At least in its current form, this is mainly used for testing
|
||||||
|
* purposes and may not be of much use for normal P2P operations.
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
int (*p2p_listen)(void *priv, unsigned int timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_connect - Start P2P group formation (GO negotiation)
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @peer_addr: MAC address of the peer P2P client
|
||||||
|
* @wps_method: enum p2p_wps_method value indicating config method
|
||||||
|
* @go_intent: Local GO intent value (1..15)
|
||||||
|
* @own_interface_addr: Intended interface address to use with the
|
||||||
|
* group
|
||||||
|
* @force_freq: The only allowed channel frequency in MHz or 0
|
||||||
|
* @persistent_group: Whether to create persistent group
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
int (*p2p_connect)(void *priv, const u8 *peer_addr, int wps_method,
|
||||||
|
int go_intent, const u8 *own_interface_addr,
|
||||||
|
unsigned int force_freq, int persistent_group);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wps_success_cb - Report successfully completed WPS provisioning
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @peer_addr: Peer address
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This function is used to report successfully completed WPS
|
||||||
|
* provisioning during group formation in both GO/Registrar and
|
||||||
|
* client/Enrollee roles.
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
int (*wps_success_cb)(void *priv, const u8 *peer_addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_group_formation_failed - Report failed WPS provisioning
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This function is used to report failed group formation. This can
|
||||||
|
* happen either due to failed WPS provisioning or due to 15 second
|
||||||
|
* timeout during the provisioning phase.
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
int (*p2p_group_formation_failed)(void *priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_set_params - Set P2P parameters
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @params: P2P parameters
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
int (*p2p_set_params)(void *priv, const struct p2p_params *params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_prov_disc_req - Send Provision Discovery Request
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @peer_addr: MAC address of the peer P2P client
|
||||||
|
* @config_methods: WPS Config Methods value (only one bit set)
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This function can be used to request a discovered P2P peer to
|
||||||
|
* display a PIN (config_methods = WPS_CONFIG_DISPLAY) or be prepared
|
||||||
|
* to enter a PIN from us (config_methods = WPS_CONFIG_KEYPAD). The
|
||||||
|
* Provision Discovery Request frame is transmitted once immediately
|
||||||
|
* and if no response is received, the frame will be sent again
|
||||||
|
* whenever the target device is discovered during device dsicovery
|
||||||
|
* (start with a p2p_find() call). Response from the peer is indicated
|
||||||
|
* with the EVENT_P2P_PROV_DISC_RESPONSE event.
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
int (*p2p_prov_disc_req)(void *priv, const u8 *peer_addr,
|
||||||
|
u16 config_methods);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_sd_request - Schedule a service discovery query
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @dst: Destination peer or %NULL to apply for all peers
|
||||||
|
* @tlvs: P2P Service Query TLV(s)
|
||||||
|
* Returns: Reference to the query or 0 on failure
|
||||||
|
*
|
||||||
|
* Response to the query is indicated with the
|
||||||
|
* EVENT_P2P_SD_RESPONSE driver event.
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
u64 (*p2p_sd_request)(void *priv, const u8 *dst,
|
||||||
|
const struct wpabuf *tlvs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_sd_cancel_request - Cancel a pending service discovery query
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @req: Query reference from p2p_sd_request()
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
int (*p2p_sd_cancel_request)(void *priv, u64 req);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_sd_response - Send response to a service discovery query
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @freq: Frequency from EVENT_P2P_SD_REQUEST event
|
||||||
|
* @dst: Destination address from EVENT_P2P_SD_REQUEST event
|
||||||
|
* @dialog_token: Dialog token from EVENT_P2P_SD_REQUEST event
|
||||||
|
* @resp_tlvs: P2P Service Response TLV(s)
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This function is called as a response to the request indicated with
|
||||||
|
* the EVENT_P2P_SD_REQUEST driver event.
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
int (*p2p_sd_response)(void *priv, int freq, const u8 *dst,
|
||||||
|
u8 dialog_token,
|
||||||
|
const struct wpabuf *resp_tlvs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_service_update - Indicate a change in local services
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*
|
||||||
|
* This function needs to be called whenever there is a change in
|
||||||
|
* availability of the local services. This will increment the
|
||||||
|
* Service Update Indicator value which will be used in SD Request and
|
||||||
|
* Response frames.
|
||||||
|
*
|
||||||
|
* This function is only used if the driver implements P2P management,
|
||||||
|
* i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
|
||||||
|
* struct wpa_driver_capa.
|
||||||
|
*/
|
||||||
|
int (*p2p_service_update)(void *priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_reject - Reject peer device (explicitly block connections)
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @addr: MAC address of the peer
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
int (*p2p_reject)(void *priv, const u8 *addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_invite - Invite a P2P Device into a group
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @peer: Device Address of the peer P2P Device
|
||||||
|
* @role: Local role in the group
|
||||||
|
* @bssid: Group BSSID or %NULL if not known
|
||||||
|
* @ssid: Group SSID
|
||||||
|
* @ssid_len: Length of ssid in octets
|
||||||
|
* @go_dev_addr: Forced GO Device Address or %NULL if none
|
||||||
|
* @persistent_group: Whether this is to reinvoke a persistent group
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
int (*p2p_invite)(void *priv, const u8 *peer, int role,
|
||||||
|
const u8 *bssid, const u8 *ssid, size_t ssid_len,
|
||||||
|
const u8 *go_dev_addr, int persistent_group);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2314,7 +2541,39 @@ enum wpa_event_type {
|
||||||
* station was lost. Detection can be through massive transmission
|
* station was lost. Detection can be through massive transmission
|
||||||
* failures for example.
|
* failures for example.
|
||||||
*/
|
*/
|
||||||
EVENT_STATION_LOW_ACK
|
EVENT_STATION_LOW_ACK,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVENT_P2P_DEV_FOUND - Report a discovered P2P device
|
||||||
|
*
|
||||||
|
* This event is used only if the driver implements P2P management
|
||||||
|
* internally. Event data is stored in
|
||||||
|
* union wpa_event_data::p2p_dev_found.
|
||||||
|
*/
|
||||||
|
EVENT_P2P_DEV_FOUND,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVENT_P2P_GO_NEG_REQ_RX - Report reception of GO Negotiation Request
|
||||||
|
*
|
||||||
|
* This event is used only if the driver implements P2P management
|
||||||
|
* internally. Event data is stored in
|
||||||
|
* union wpa_event_data::p2p_go_neg_req_rx.
|
||||||
|
*/
|
||||||
|
EVENT_P2P_GO_NEG_REQ_RX,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVENT_P2P_GO_NEG_COMPLETED - Report completion of GO Negotiation
|
||||||
|
*
|
||||||
|
* This event is used only if the driver implements P2P management
|
||||||
|
* internally. Event data is stored in
|
||||||
|
* union wpa_event_data::p2p_go_neg_completed.
|
||||||
|
*/
|
||||||
|
EVENT_P2P_GO_NEG_COMPLETED,
|
||||||
|
|
||||||
|
EVENT_P2P_PROV_DISC_REQUEST,
|
||||||
|
EVENT_P2P_PROV_DISC_RESPONSE,
|
||||||
|
EVENT_P2P_SD_REQUEST,
|
||||||
|
EVENT_P2P_SD_RESPONSE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2768,6 +3027,66 @@ union wpa_event_data {
|
||||||
struct low_ack {
|
struct low_ack {
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
} low_ack;
|
} low_ack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct p2p_dev_found - Data for EVENT_P2P_DEV_FOUND
|
||||||
|
*/
|
||||||
|
struct p2p_dev_found {
|
||||||
|
const u8 *addr;
|
||||||
|
const u8 *dev_addr;
|
||||||
|
const u8 *pri_dev_type;
|
||||||
|
const char *dev_name;
|
||||||
|
u16 config_methods;
|
||||||
|
u8 dev_capab;
|
||||||
|
u8 group_capab;
|
||||||
|
} p2p_dev_found;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct p2p_go_neg_req_rx - Data for EVENT_P2P_GO_NEG_REQ_RX
|
||||||
|
*/
|
||||||
|
struct p2p_go_neg_req_rx {
|
||||||
|
const u8 *src;
|
||||||
|
u16 dev_passwd_id;
|
||||||
|
} p2p_go_neg_req_rx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct p2p_go_neg_completed - Data for EVENT_P2P_GO_NEG_COMPLETED
|
||||||
|
*/
|
||||||
|
struct p2p_go_neg_completed {
|
||||||
|
struct p2p_go_neg_results *res;
|
||||||
|
} p2p_go_neg_completed;
|
||||||
|
|
||||||
|
struct p2p_prov_disc_req {
|
||||||
|
const u8 *peer;
|
||||||
|
u16 config_methods;
|
||||||
|
const u8 *dev_addr;
|
||||||
|
const u8 *pri_dev_type;
|
||||||
|
const char *dev_name;
|
||||||
|
u16 supp_config_methods;
|
||||||
|
u8 dev_capab;
|
||||||
|
u8 group_capab;
|
||||||
|
} p2p_prov_disc_req;
|
||||||
|
|
||||||
|
struct p2p_prov_disc_resp {
|
||||||
|
const u8 *peer;
|
||||||
|
u16 config_methods;
|
||||||
|
} p2p_prov_disc_resp;
|
||||||
|
|
||||||
|
struct p2p_sd_req {
|
||||||
|
int freq;
|
||||||
|
const u8 *sa;
|
||||||
|
u8 dialog_token;
|
||||||
|
u16 update_indic;
|
||||||
|
const u8 *tlvs;
|
||||||
|
size_t tlvs_len;
|
||||||
|
} p2p_sd_req;
|
||||||
|
|
||||||
|
struct p2p_sd_resp {
|
||||||
|
const u8 *sa;
|
||||||
|
u16 update_indic;
|
||||||
|
const u8 *tlvs;
|
||||||
|
size_t tlvs_len;
|
||||||
|
} p2p_sd_resp;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3311,5 +3311,19 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
|
||||||
NULL /* set_p2p_powersave */,
|
NULL /* set_p2p_powersave */,
|
||||||
NULL /* ampdu */,
|
NULL /* ampdu */,
|
||||||
NULL /* set_intra_bss */,
|
NULL /* set_intra_bss */,
|
||||||
NULL /* get_radio_name */
|
NULL /* get_radio_name */,
|
||||||
|
NULL /* p2p_find */,
|
||||||
|
NULL /* p2p_stop_find */,
|
||||||
|
NULL /* p2p_listen */,
|
||||||
|
NULL /* p2p_connect */,
|
||||||
|
NULL /* wps_success_cb */,
|
||||||
|
NULL /* p2p_group_formation_failed */,
|
||||||
|
NULL /* p2p_set_params */,
|
||||||
|
NULL /* p2p_prov_disc_req */,
|
||||||
|
NULL /* p2p_sd_request */,
|
||||||
|
NULL /* p2p_sd_cancel_request */,
|
||||||
|
NULL /* p2p_sd_response */,
|
||||||
|
NULL /* p2p_service_update */,
|
||||||
|
NULL /* p2p_reject */,
|
||||||
|
NULL /* p2p_invite */
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "crypto/sha1.h"
|
#include "crypto/sha1.h"
|
||||||
#include "l2_packet/l2_packet.h"
|
#include "l2_packet/l2_packet.h"
|
||||||
|
#include "p2p/p2p.h"
|
||||||
|
#include "wps/wps.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,6 +109,19 @@ struct wpa_driver_test_data {
|
||||||
unsigned int remain_on_channel_duration;
|
unsigned int remain_on_channel_duration;
|
||||||
|
|
||||||
int current_freq;
|
int current_freq;
|
||||||
|
|
||||||
|
struct p2p_data *p2p;
|
||||||
|
unsigned int off_channel_freq;
|
||||||
|
struct wpabuf *pending_action_tx;
|
||||||
|
u8 pending_action_src[ETH_ALEN];
|
||||||
|
u8 pending_action_dst[ETH_ALEN];
|
||||||
|
u8 pending_action_bssid[ETH_ALEN];
|
||||||
|
unsigned int pending_action_freq;
|
||||||
|
unsigned int pending_listen_freq;
|
||||||
|
unsigned int pending_listen_duration;
|
||||||
|
int pending_p2p_scan;
|
||||||
|
struct sockaddr *probe_from;
|
||||||
|
socklen_t probe_from_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,6 +131,7 @@ static int wpa_driver_test_attach(struct wpa_driver_test_data *drv,
|
||||||
static void wpa_driver_test_close_test_socket(
|
static void wpa_driver_test_close_test_socket(
|
||||||
struct wpa_driver_test_data *drv);
|
struct wpa_driver_test_data *drv);
|
||||||
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx);
|
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||||
|
static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv);
|
||||||
|
|
||||||
|
|
||||||
static void test_driver_free_bss(struct test_driver_bss *bss)
|
static void test_driver_free_bss(struct test_driver_bss *bss)
|
||||||
|
@ -469,6 +485,34 @@ static int wpa_driver_test_send_mlme(void *priv, const u8 *data,
|
||||||
event.tx_status.ack = ret >= 0;
|
event.tx_status.ack = ret >= 0;
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
|
wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
|
||||||
|
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
if (drv->p2p &&
|
||||||
|
WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
|
||||||
|
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
|
||||||
|
if (drv->pending_action_tx == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - "
|
||||||
|
"no pending operation");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_memcmp(hdr->addr1, drv->pending_action_dst, ETH_ALEN) !=
|
||||||
|
0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - "
|
||||||
|
"unknown destination address");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_free(drv->pending_action_tx);
|
||||||
|
drv->pending_action_tx = NULL;
|
||||||
|
|
||||||
|
p2p_send_action_cb(drv->p2p, drv->pending_action_freq,
|
||||||
|
drv->pending_action_dst,
|
||||||
|
drv->pending_action_src,
|
||||||
|
drv->pending_action_bssid,
|
||||||
|
ret >= 0);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,6 +559,10 @@ static void test_driver_scan(struct wpa_driver_test_data *drv,
|
||||||
event.rx_probe_req.ie = ie;
|
event.rx_probe_req.ie = ie;
|
||||||
event.rx_probe_req.ie_len = ielen;
|
event.rx_probe_req.ie_len = ielen;
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, &event);
|
wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, &event);
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
if (drv->p2p)
|
||||||
|
p2p_probe_req_rx(drv->p2p, sa, ie, ielen);
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
}
|
}
|
||||||
|
|
||||||
dl_list_for_each(bss, &drv->bss, struct test_driver_bss, list) {
|
dl_list_for_each(bss, &drv->bss, struct test_driver_bss, list) {
|
||||||
|
@ -1274,7 +1322,23 @@ static void wpa_driver_test_poll(void *eloop_ctx, void *timeout_ctx)
|
||||||
|
|
||||||
static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
{
|
{
|
||||||
|
struct wpa_driver_test_data *drv = eloop_ctx;
|
||||||
wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
|
wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
|
||||||
|
if (drv->pending_p2p_scan && drv->p2p) {
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < drv->num_scanres; i++) {
|
||||||
|
struct wpa_scan_res *bss = drv->scanres[i];
|
||||||
|
if (p2p_scan_res_handler(drv->p2p, bss->bssid,
|
||||||
|
bss->freq, bss->level,
|
||||||
|
(const u8 *) (bss + 1),
|
||||||
|
bss->ie_len) > 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p2p_scan_res_handled(drv->p2p);
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
|
return;
|
||||||
|
}
|
||||||
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1852,6 +1916,8 @@ static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
|
||||||
{
|
{
|
||||||
int freq = 0, own_freq;
|
int freq = 0, own_freq;
|
||||||
union wpa_event_data event;
|
union wpa_event_data event;
|
||||||
|
const struct ieee80211_mgmt *mgmt;
|
||||||
|
u16 fc;
|
||||||
struct test_driver_bss *bss;
|
struct test_driver_bss *bss;
|
||||||
|
|
||||||
bss = dl_list_first(&drv->bss, struct test_driver_bss, list);
|
bss = dl_list_first(&drv->bss, struct test_driver_bss, list);
|
||||||
|
@ -1889,12 +1955,10 @@ static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
|
||||||
event.mlme_rx.freq = freq;
|
event.mlme_rx.freq = freq;
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_MLME_RX, &event);
|
wpa_supplicant_event(drv->ctx, EVENT_MLME_RX, &event);
|
||||||
|
|
||||||
if (drv->probe_req_report && data_len >= 24) {
|
|
||||||
const struct ieee80211_mgmt *mgmt;
|
|
||||||
u16 fc;
|
|
||||||
|
|
||||||
mgmt = (const struct ieee80211_mgmt *) data;
|
mgmt = (const struct ieee80211_mgmt *) data;
|
||||||
fc = le_to_host16(mgmt->frame_control);
|
fc = le_to_host16(mgmt->frame_control);
|
||||||
|
|
||||||
|
if (drv->probe_req_report && data_len >= 24) {
|
||||||
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
|
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
|
||||||
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) {
|
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) {
|
||||||
os_memset(&event, 0, sizeof(event));
|
os_memset(&event, 0, sizeof(event));
|
||||||
|
@ -1904,8 +1968,29 @@ static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
|
||||||
data_len - (mgmt->u.probe_req.variable - data);
|
data_len - (mgmt->u.probe_req.variable - data);
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ,
|
wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ,
|
||||||
&event);
|
&event);
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
if (drv->p2p)
|
||||||
|
p2p_probe_req_rx(drv->p2p, mgmt->sa,
|
||||||
|
event.rx_probe_req.ie,
|
||||||
|
event.rx_probe_req.ie_len);
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
if (drv->p2p &&
|
||||||
|
WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
|
||||||
|
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
|
||||||
|
size_t hdr_len;
|
||||||
|
hdr_len = (const u8 *)
|
||||||
|
&mgmt->u.action.u.vs_public_action.action - data;
|
||||||
|
p2p_rx_action(drv->p2p, mgmt->da, mgmt->sa, mgmt->bssid,
|
||||||
|
mgmt->u.action.category,
|
||||||
|
&mgmt->u.action.u.vs_public_action.action,
|
||||||
|
data_len - hdr_len, freq);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1921,6 +2006,29 @@ static void wpa_driver_test_scan_cmd(struct wpa_driver_test_data *drv,
|
||||||
bss = dl_list_first(&drv->bss, struct test_driver_bss, list);
|
bss = dl_list_first(&drv->bss, struct test_driver_bss, list);
|
||||||
|
|
||||||
/* data: optional [ STA-addr | ' ' | IEs(hex) ] */
|
/* data: optional [ STA-addr | ' ' | IEs(hex) ] */
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
if (drv->probe_req_report && drv->p2p && data_len) {
|
||||||
|
const char *d = (const char *) data;
|
||||||
|
u8 sa[ETH_ALEN];
|
||||||
|
u8 ie[512];
|
||||||
|
size_t ielen;
|
||||||
|
|
||||||
|
if (hwaddr_aton(d, sa))
|
||||||
|
return;
|
||||||
|
d += 18;
|
||||||
|
while (*d == ' ')
|
||||||
|
d++;
|
||||||
|
ielen = os_strlen(d) / 2;
|
||||||
|
if (ielen > sizeof(ie))
|
||||||
|
ielen = sizeof(ie);
|
||||||
|
if (hexstr2bin(d, ie, ielen) < 0)
|
||||||
|
ielen = 0;
|
||||||
|
drv->probe_from = from;
|
||||||
|
drv->probe_from_len = fromlen;
|
||||||
|
p2p_probe_req_rx(drv->p2p, sa, ie, ielen);
|
||||||
|
drv->probe_from = NULL;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
if (!drv->ibss)
|
if (!drv->ibss)
|
||||||
return;
|
return;
|
||||||
|
@ -2077,6 +2185,12 @@ static void wpa_driver_test_deinit(void *priv)
|
||||||
struct test_client_socket *cli, *prev;
|
struct test_client_socket *cli, *prev;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
if (drv->p2p)
|
||||||
|
p2p_deinit(drv->p2p);
|
||||||
|
wpabuf_free(drv->pending_action_tx);
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
cli = drv->cli;
|
cli = drv->cli;
|
||||||
while (cli) {
|
while (cli) {
|
||||||
prev = cli;
|
prev = cli;
|
||||||
|
@ -2280,6 +2394,13 @@ static int wpa_driver_test_set_param(void *priv, const char *param)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_CLIENT_MLME */
|
#endif /* CONFIG_CLIENT_MLME */
|
||||||
|
|
||||||
|
if (os_strstr(param, "p2p_mgmt=1")) {
|
||||||
|
wpa_printf(MSG_DEBUG, "test_driver: Use internal P2P "
|
||||||
|
"management");
|
||||||
|
if (wpa_driver_test_init_p2p(drv) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2388,6 +2509,8 @@ static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa)
|
||||||
WPA_DRIVER_AUTH_LEAP;
|
WPA_DRIVER_AUTH_LEAP;
|
||||||
if (drv->use_mlme)
|
if (drv->use_mlme)
|
||||||
capa->flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME;
|
capa->flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME;
|
||||||
|
if (drv->p2p)
|
||||||
|
capa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT;
|
||||||
capa->flags |= WPA_DRIVER_FLAGS_AP;
|
capa->flags |= WPA_DRIVER_FLAGS_AP;
|
||||||
capa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
|
capa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
|
||||||
capa->flags |= WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE;
|
capa->flags |= WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE;
|
||||||
|
@ -2640,6 +2763,33 @@ static int wpa_driver_test_send_action(void *priv, unsigned int freq,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
static void test_send_action_cb(void *eloop_ctx, void *timeout_ctx)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = eloop_ctx;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (drv->pending_action_tx == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (drv->off_channel_freq != drv->pending_action_freq) {
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Pending Action frame TX "
|
||||||
|
"waiting for another freq=%u",
|
||||||
|
drv->pending_action_freq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Sending pending Action frame to "
|
||||||
|
MACSTR, MAC2STR(drv->pending_action_dst));
|
||||||
|
res = wpa_driver_test_send_action(drv, drv->pending_action_freq, 0,
|
||||||
|
drv->pending_action_dst,
|
||||||
|
drv->pending_action_src,
|
||||||
|
drv->pending_action_bssid,
|
||||||
|
wpabuf_head(drv->pending_action_tx),
|
||||||
|
wpabuf_len(drv->pending_action_tx));
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
|
|
||||||
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx)
|
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
{
|
{
|
||||||
struct wpa_driver_test_data *drv = eloop_ctx;
|
struct wpa_driver_test_data *drv = eloop_ctx;
|
||||||
|
@ -2650,9 +2800,13 @@ static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
os_memset(&data, 0, sizeof(data));
|
os_memset(&data, 0, sizeof(data));
|
||||||
data.remain_on_channel.freq = drv->remain_on_channel_freq;
|
data.remain_on_channel.freq = drv->remain_on_channel_freq;
|
||||||
data.remain_on_channel.duration = drv->remain_on_channel_duration;
|
data.remain_on_channel.duration = drv->remain_on_channel_duration;
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_CANCEL_REMAIN_ON_CHANNEL, &data);
|
|
||||||
|
if (drv->p2p)
|
||||||
|
drv->off_channel_freq = 0;
|
||||||
|
|
||||||
drv->remain_on_channel_freq = 0;
|
drv->remain_on_channel_freq = 0;
|
||||||
|
|
||||||
|
wpa_supplicant_event(drv->ctx, EVENT_CANCEL_REMAIN_ON_CHANNEL, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2683,6 +2837,18 @@ static int wpa_driver_test_remain_on_channel(void *priv, unsigned int freq,
|
||||||
data.remain_on_channel.duration = duration;
|
data.remain_on_channel.duration = duration;
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_REMAIN_ON_CHANNEL, &data);
|
wpa_supplicant_event(drv->ctx, EVENT_REMAIN_ON_CHANNEL, &data);
|
||||||
|
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
if (drv->p2p) {
|
||||||
|
drv->off_channel_freq = drv->remain_on_channel_freq;
|
||||||
|
test_send_action_cb(drv, NULL);
|
||||||
|
if (drv->off_channel_freq == drv->pending_listen_freq) {
|
||||||
|
p2p_listen_cb(drv->p2p, drv->pending_listen_freq,
|
||||||
|
drv->pending_listen_duration);
|
||||||
|
drv->pending_listen_freq = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2710,6 +2876,455 @@ static int wpa_driver_test_probe_req_report(void *priv, int report)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
|
||||||
|
static int wpa_driver_test_p2p_find(void *priv, unsigned int timeout, int type)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = priv;
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout);
|
||||||
|
if (!drv->p2p)
|
||||||
|
return -1;
|
||||||
|
return p2p_find(drv->p2p, timeout, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_test_p2p_stop_find(void *priv)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = priv;
|
||||||
|
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||||
|
if (!drv->p2p)
|
||||||
|
return -1;
|
||||||
|
p2p_stop_find(drv->p2p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_test_p2p_listen(void *priv, unsigned int timeout)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = priv;
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout);
|
||||||
|
if (!drv->p2p)
|
||||||
|
return -1;
|
||||||
|
return p2p_listen(drv->p2p, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_test_p2p_connect(void *priv, const u8 *peer_addr,
|
||||||
|
int wps_method, int go_intent,
|
||||||
|
const u8 *own_interface_addr,
|
||||||
|
unsigned int force_freq,
|
||||||
|
int persistent_group)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = priv;
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR " wps_method=%d "
|
||||||
|
"go_intent=%d "
|
||||||
|
"own_interface_addr=" MACSTR " force_freq=%u "
|
||||||
|
"persistent_group=%d)",
|
||||||
|
__func__, MAC2STR(peer_addr), wps_method, go_intent,
|
||||||
|
MAC2STR(own_interface_addr), force_freq, persistent_group);
|
||||||
|
if (!drv->p2p)
|
||||||
|
return -1;
|
||||||
|
return p2p_connect(drv->p2p, peer_addr, wps_method, go_intent,
|
||||||
|
own_interface_addr, force_freq, persistent_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_test_wps_success_cb(void *priv, const u8 *peer_addr)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = priv;
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR ")",
|
||||||
|
__func__, MAC2STR(peer_addr));
|
||||||
|
if (!drv->p2p)
|
||||||
|
return -1;
|
||||||
|
p2p_wps_success_cb(drv->p2p, peer_addr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_test_p2p_group_formation_failed(void *priv)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = priv;
|
||||||
|
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||||
|
if (!drv->p2p)
|
||||||
|
return -1;
|
||||||
|
p2p_group_formation_failed(drv->p2p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_test_p2p_set_params(void *priv,
|
||||||
|
const struct p2p_params *params)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = priv;
|
||||||
|
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||||
|
if (!drv->p2p)
|
||||||
|
return -1;
|
||||||
|
if (p2p_set_dev_name(drv->p2p, params->dev_name) < 0 ||
|
||||||
|
p2p_set_pri_dev_type(drv->p2p, params->pri_dev_type) < 0 ||
|
||||||
|
p2p_set_sec_dev_types(drv->p2p, params->sec_dev_type,
|
||||||
|
params->num_sec_dev_types) < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = ctx;
|
||||||
|
struct wpa_driver_scan_params params;
|
||||||
|
int ret;
|
||||||
|
struct wpabuf *wps_ie, *ies;
|
||||||
|
int social_channels[] = { 2412, 2437, 2462, 0, 0 };
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(type=%d freq=%d)",
|
||||||
|
__func__, type, freq);
|
||||||
|
|
||||||
|
os_memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
/* P2P Wildcard SSID */
|
||||||
|
params.num_ssids = 1;
|
||||||
|
params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
|
||||||
|
params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
|
||||||
|
|
||||||
|
#if 0 /* TODO: WPS IE */
|
||||||
|
wpa_s->wps->dev.p2p = 1;
|
||||||
|
wps_ie = wps_build_probe_req_ie(0, &wpa_s->wps->dev, wpa_s->wps->uuid,
|
||||||
|
WPS_REQ_ENROLLEE);
|
||||||
|
#else
|
||||||
|
wps_ie = wpabuf_alloc(1);
|
||||||
|
#endif
|
||||||
|
if (wps_ie == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ies = wpabuf_alloc(wpabuf_len(wps_ie) + 100);
|
||||||
|
if (ies == NULL) {
|
||||||
|
wpabuf_free(wps_ie);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
wpabuf_put_buf(ies, wps_ie);
|
||||||
|
wpabuf_free(wps_ie);
|
||||||
|
|
||||||
|
p2p_scan_ie(drv->p2p, ies);
|
||||||
|
|
||||||
|
params.extra_ies = wpabuf_head(ies);
|
||||||
|
params.extra_ies_len = wpabuf_len(ies);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case P2P_SCAN_SOCIAL:
|
||||||
|
params.freqs = social_channels;
|
||||||
|
break;
|
||||||
|
case P2P_SCAN_FULL:
|
||||||
|
break;
|
||||||
|
case P2P_SCAN_SPECIFIC:
|
||||||
|
social_channels[0] = freq;
|
||||||
|
social_channels[1] = 0;
|
||||||
|
params.freqs = social_channels;
|
||||||
|
break;
|
||||||
|
case P2P_SCAN_SOCIAL_PLUS_ONE:
|
||||||
|
social_channels[3] = freq;
|
||||||
|
params.freqs = social_channels;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
drv->pending_p2p_scan = 1;
|
||||||
|
ret = wpa_driver_test_scan(drv, ¶ms);
|
||||||
|
|
||||||
|
wpabuf_free(ies);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int test_send_action(void *ctx, unsigned int freq, const u8 *dst,
|
||||||
|
const u8 *src, const u8 *bssid, const u8 *buf,
|
||||||
|
size_t len, unsigned int wait_time)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = ctx;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(freq=%u dst=" MACSTR " src=" MACSTR
|
||||||
|
" bssid=" MACSTR " len=%d",
|
||||||
|
__func__, freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
|
||||||
|
(int) len);
|
||||||
|
if (freq <= 0) {
|
||||||
|
wpa_printf(MSG_WARNING, "P2P: No frequency specified for "
|
||||||
|
"action frame TX");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drv->pending_action_tx) {
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Dropped pending Action frame TX "
|
||||||
|
"to " MACSTR, MAC2STR(drv->pending_action_dst));
|
||||||
|
wpabuf_free(drv->pending_action_tx);
|
||||||
|
}
|
||||||
|
drv->pending_action_tx = wpabuf_alloc(len);
|
||||||
|
if (drv->pending_action_tx == NULL)
|
||||||
|
return -1;
|
||||||
|
wpabuf_put_data(drv->pending_action_tx, buf, len);
|
||||||
|
os_memcpy(drv->pending_action_src, src, ETH_ALEN);
|
||||||
|
os_memcpy(drv->pending_action_dst, dst, ETH_ALEN);
|
||||||
|
os_memcpy(drv->pending_action_bssid, bssid, ETH_ALEN);
|
||||||
|
drv->pending_action_freq = freq;
|
||||||
|
|
||||||
|
if (drv->off_channel_freq == freq) {
|
||||||
|
/* Already on requested channel; send immediately */
|
||||||
|
/* TODO: Would there ever be need to extend the current
|
||||||
|
* duration on the channel? */
|
||||||
|
eloop_cancel_timeout(test_send_action_cb, drv, NULL);
|
||||||
|
eloop_register_timeout(0, 0, test_send_action_cb, drv, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Schedule Action frame to be transmitted "
|
||||||
|
"once the driver gets to the requested channel");
|
||||||
|
if (wpa_driver_test_remain_on_channel(drv, freq, wait_time) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Failed to request driver "
|
||||||
|
"to remain on channel (%u MHz) for Action "
|
||||||
|
"Frame TX", freq);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_send_action_done(void *ctx)
|
||||||
|
{
|
||||||
|
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = ctx;
|
||||||
|
union wpa_event_data event;
|
||||||
|
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||||
|
os_memset(&event, 0, sizeof(event));
|
||||||
|
event.p2p_go_neg_completed.res = res;
|
||||||
|
wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_COMPLETED, &event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = ctx;
|
||||||
|
union wpa_event_data event;
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(src=" MACSTR ")", __func__, MAC2STR(src));
|
||||||
|
os_memset(&event, 0, sizeof(event));
|
||||||
|
event.p2p_go_neg_req_rx.src = src;
|
||||||
|
event.p2p_go_neg_req_rx.dev_passwd_id = dev_passwd_id;
|
||||||
|
wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_REQ_RX, &event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_dev_found(void *ctx, const u8 *addr, const u8 *dev_addr,
|
||||||
|
const u8 *pri_dev_type, const char *dev_name,
|
||||||
|
u16 config_methods, u8 dev_capab, u8 group_capab)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = ctx;
|
||||||
|
union wpa_event_data event;
|
||||||
|
char devtype[WPS_DEV_TYPE_BUFSIZE];
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(" MACSTR " p2p_dev_addr=" MACSTR
|
||||||
|
" pri_dev_type=%s name='%s' config_methods=0x%x "
|
||||||
|
"dev_capab=0x%x group_capab=0x%x)",
|
||||||
|
__func__, MAC2STR(addr), MAC2STR(dev_addr),
|
||||||
|
wps_dev_type_bin2str(pri_dev_type, devtype,
|
||||||
|
sizeof(devtype)),
|
||||||
|
dev_name, config_methods, dev_capab, group_capab);
|
||||||
|
|
||||||
|
os_memset(&event, 0, sizeof(event));
|
||||||
|
event.p2p_dev_found.addr = addr;
|
||||||
|
event.p2p_dev_found.dev_addr = dev_addr;
|
||||||
|
event.p2p_dev_found.pri_dev_type = pri_dev_type;
|
||||||
|
event.p2p_dev_found.dev_name = dev_name;
|
||||||
|
event.p2p_dev_found.config_methods = config_methods;
|
||||||
|
event.p2p_dev_found.dev_capab = dev_capab;
|
||||||
|
event.p2p_dev_found.group_capab = group_capab;
|
||||||
|
wpa_supplicant_event(drv->ctx, EVENT_P2P_DEV_FOUND, &event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int test_start_listen(void *ctx, unsigned int freq,
|
||||||
|
unsigned int duration,
|
||||||
|
const struct wpabuf *probe_resp_ie)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = ctx;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(freq=%u duration=%u)",
|
||||||
|
__func__, freq, duration);
|
||||||
|
|
||||||
|
if (wpa_driver_test_probe_req_report(drv, 1) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
drv->pending_listen_freq = freq;
|
||||||
|
drv->pending_listen_duration = duration;
|
||||||
|
|
||||||
|
if (wpa_driver_test_remain_on_channel(drv, freq, duration) < 0) {
|
||||||
|
drv->pending_listen_freq = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_stop_listen(void *ctx)
|
||||||
|
{
|
||||||
|
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int test_send_probe_resp(void *ctx, const struct wpabuf *buf)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = ctx;
|
||||||
|
char resp[512], *pos, *end;
|
||||||
|
int ret;
|
||||||
|
const struct ieee80211_mgmt *mgmt;
|
||||||
|
const u8 *ie, *ie_end;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||||
|
wpa_hexdump_buf(MSG_MSGDUMP, "Probe Response", buf);
|
||||||
|
if (wpabuf_len(buf) < 24)
|
||||||
|
return -1;
|
||||||
|
if (!drv->probe_from) {
|
||||||
|
wpa_printf(MSG_DEBUG, "%s: probe_from not set", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = resp;
|
||||||
|
end = resp + sizeof(resp);
|
||||||
|
|
||||||
|
mgmt = wpabuf_head(buf);
|
||||||
|
|
||||||
|
/* reply: SCANRESP BSSID SSID IEs */
|
||||||
|
ret = os_snprintf(pos, end - pos, "SCANRESP " MACSTR " ",
|
||||||
|
MAC2STR(mgmt->bssid));
|
||||||
|
if (ret < 0 || ret >= end - pos)
|
||||||
|
return -1;
|
||||||
|
pos += ret;
|
||||||
|
|
||||||
|
ie = mgmt->u.probe_resp.variable;
|
||||||
|
ie_end = wpabuf_head_u8(buf) + wpabuf_len(buf);
|
||||||
|
if (ie_end - ie < 2 || ie[0] != WLAN_EID_SSID ||
|
||||||
|
ie + 2 + ie[1] > ie_end)
|
||||||
|
return -1;
|
||||||
|
pos += wpa_snprintf_hex(pos, end - pos, ie + 2, ie[1]);
|
||||||
|
|
||||||
|
ret = os_snprintf(pos, end - pos, " ");
|
||||||
|
if (ret < 0 || ret >= end - pos)
|
||||||
|
return -1;
|
||||||
|
pos += ret;
|
||||||
|
pos += wpa_snprintf_hex(pos, end - pos, ie, ie_end - ie);
|
||||||
|
|
||||||
|
sendto(drv->test_socket, resp, pos - resp, 0,
|
||||||
|
drv->probe_from, drv->probe_from_len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
|
||||||
|
u16 update_indic, const u8 *tlvs, size_t tlvs_len)
|
||||||
|
{
|
||||||
|
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_sd_response(void *ctx, const u8 *sa, u16 update_indic,
|
||||||
|
const u8 *tlvs, size_t tlvs_len)
|
||||||
|
{
|
||||||
|
wpa_printf(MSG_DEBUG, "%s", __func__);
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods,
|
||||||
|
const u8 *dev_addr, const u8 *pri_dev_type,
|
||||||
|
const char *dev_name, u16 supp_config_methods,
|
||||||
|
u8 dev_capab, u8 group_capab)
|
||||||
|
{
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)",
|
||||||
|
__func__, MAC2STR(peer), config_methods);
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
|
||||||
|
{
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)",
|
||||||
|
__func__, MAC2STR(peer), config_methods);
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
struct p2p_config p2p;
|
||||||
|
unsigned int r;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
os_memset(&p2p, 0, sizeof(p2p));
|
||||||
|
p2p.msg_ctx = drv->ctx;
|
||||||
|
p2p.cb_ctx = drv;
|
||||||
|
p2p.p2p_scan = test_p2p_scan;
|
||||||
|
p2p.send_action = test_send_action;
|
||||||
|
p2p.send_action_done = test_send_action_done;
|
||||||
|
p2p.go_neg_completed = test_go_neg_completed;
|
||||||
|
p2p.go_neg_req_rx = test_go_neg_req_rx;
|
||||||
|
p2p.dev_found = test_dev_found;
|
||||||
|
p2p.start_listen = test_start_listen;
|
||||||
|
p2p.stop_listen = test_stop_listen;
|
||||||
|
p2p.send_probe_resp = test_send_probe_resp;
|
||||||
|
p2p.sd_request = test_sd_request;
|
||||||
|
p2p.sd_response = test_sd_response;
|
||||||
|
p2p.prov_disc_req = test_prov_disc_req;
|
||||||
|
p2p.prov_disc_resp = test_prov_disc_resp;
|
||||||
|
|
||||||
|
os_memcpy(p2p.dev_addr, drv->own_addr, ETH_ALEN);
|
||||||
|
|
||||||
|
p2p.reg_class = 12; /* TODO: change depending on location */
|
||||||
|
/*
|
||||||
|
* Pick one of the social channels randomly as the listen
|
||||||
|
* channel.
|
||||||
|
*/
|
||||||
|
os_get_random((u8 *) &r, sizeof(r));
|
||||||
|
p2p.channel = 1 + (r % 3) * 5;
|
||||||
|
|
||||||
|
/* TODO: change depending on location */
|
||||||
|
p2p.op_reg_class = 12;
|
||||||
|
/*
|
||||||
|
* For initial tests, pick the operation channel randomly.
|
||||||
|
* TODO: Use scan results (etc.) to select the best channel.
|
||||||
|
*/
|
||||||
|
p2p.op_channel = 1 + r % 11;
|
||||||
|
|
||||||
|
os_memcpy(p2p.country, "US ", 3);
|
||||||
|
|
||||||
|
/* FIX: fetch available channels from the driver */
|
||||||
|
p2p.channels.reg_classes = 1;
|
||||||
|
p2p.channels.reg_class[0].reg_class = 12; /* US/12 = 2.4 GHz band */
|
||||||
|
p2p.channels.reg_class[0].channels = 11;
|
||||||
|
for (i = 0; i < 11; i++)
|
||||||
|
p2p.channels.reg_class[0].channel[i] = i + 1;
|
||||||
|
|
||||||
|
p2p.max_peers = 100;
|
||||||
|
|
||||||
|
drv->p2p = p2p_init(&p2p);
|
||||||
|
if (drv->p2p == NULL)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
#else /* CONFIG_P2P */
|
||||||
|
wpa_printf(MSG_INFO, "driver_test: P2P support not included");
|
||||||
|
return -1;
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const struct wpa_driver_ops wpa_driver_test_ops = {
|
const struct wpa_driver_ops wpa_driver_test_ops = {
|
||||||
"test",
|
"test",
|
||||||
"wpa_supplicant test driver",
|
"wpa_supplicant test driver",
|
||||||
|
@ -2758,4 +3373,14 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
|
||||||
.remain_on_channel = wpa_driver_test_remain_on_channel,
|
.remain_on_channel = wpa_driver_test_remain_on_channel,
|
||||||
.cancel_remain_on_channel = wpa_driver_test_cancel_remain_on_channel,
|
.cancel_remain_on_channel = wpa_driver_test_cancel_remain_on_channel,
|
||||||
.probe_req_report = wpa_driver_test_probe_req_report,
|
.probe_req_report = wpa_driver_test_probe_req_report,
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
.p2p_find = wpa_driver_test_p2p_find,
|
||||||
|
.p2p_stop_find = wpa_driver_test_p2p_stop_find,
|
||||||
|
.p2p_listen = wpa_driver_test_p2p_listen,
|
||||||
|
.p2p_connect = wpa_driver_test_p2p_connect,
|
||||||
|
.wps_success_cb = wpa_driver_test_wps_success_cb,
|
||||||
|
.p2p_group_formation_failed =
|
||||||
|
wpa_driver_test_p2p_group_formation_failed,
|
||||||
|
.p2p_set_params = wpa_driver_test_p2p_set_params,
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
};
|
};
|
||||||
|
|
|
@ -547,4 +547,133 @@ static inline int wpa_drv_ampdu(struct wpa_supplicant *wpa_s, int ampdu)
|
||||||
return wpa_s->driver->ampdu(wpa_s->drv_priv, ampdu);
|
return wpa_s->driver->ampdu(wpa_s->drv_priv, ampdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_p2p_find(struct wpa_supplicant *wpa_s,
|
||||||
|
unsigned int timeout, int type)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_find)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_find(wpa_s->drv_priv, timeout, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_p2p_stop_find(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_stop_find)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_stop_find(wpa_s->drv_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_p2p_listen(struct wpa_supplicant *wpa_s,
|
||||||
|
unsigned int timeout)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_listen)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_listen(wpa_s->drv_priv, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_p2p_connect(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *peer_addr, int wps_method,
|
||||||
|
int go_intent,
|
||||||
|
const u8 *own_interface_addr,
|
||||||
|
unsigned int force_freq,
|
||||||
|
int persistent_group)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_connect)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_connect(wpa_s->drv_priv, peer_addr,
|
||||||
|
wps_method, go_intent,
|
||||||
|
own_interface_addr, force_freq,
|
||||||
|
persistent_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_wps_success_cb(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *peer_addr)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->wps_success_cb)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->wps_success_cb(wpa_s->drv_priv, peer_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
wpa_drv_p2p_group_formation_failed(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_group_formation_failed)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_group_formation_failed(wpa_s->drv_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_p2p_set_params(struct wpa_supplicant *wpa_s,
|
||||||
|
const struct p2p_params *params)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_set_params)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_set_params(wpa_s->drv_priv, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_p2p_prov_disc_req(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *peer_addr,
|
||||||
|
u16 config_methods)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_prov_disc_req)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_prov_disc_req(wpa_s->drv_priv, peer_addr,
|
||||||
|
config_methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u64 wpa_drv_p2p_sd_request(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *dst,
|
||||||
|
const struct wpabuf *tlvs)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_sd_request)
|
||||||
|
return 0;
|
||||||
|
return wpa_s->driver->p2p_sd_request(wpa_s->drv_priv, dst, tlvs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s,
|
||||||
|
u64 req)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_sd_cancel_request)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_sd_cancel_request(wpa_s->drv_priv, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_p2p_sd_response(struct wpa_supplicant *wpa_s,
|
||||||
|
int freq, const u8 *dst,
|
||||||
|
u8 dialog_token,
|
||||||
|
const struct wpabuf *resp_tlvs)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_sd_response)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_sd_response(wpa_s->drv_priv, freq, dst,
|
||||||
|
dialog_token, resp_tlvs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_p2p_service_update(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_service_update)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_service_update(wpa_s->drv_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_p2p_reject(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *addr)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_reject)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_reject(wpa_s->drv_priv, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_p2p_invite(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *peer, int role, const u8 *bssid,
|
||||||
|
const u8 *ssid, size_t ssid_len,
|
||||||
|
const u8 *go_dev_addr,
|
||||||
|
int persistent_group)
|
||||||
|
{
|
||||||
|
if (!wpa_s->driver->p2p_invite)
|
||||||
|
return -1;
|
||||||
|
return wpa_s->driver->p2p_invite(wpa_s->drv_priv, peer, role, bssid,
|
||||||
|
ssid, ssid_len, go_dev_addr,
|
||||||
|
persistent_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* DRIVER_I_H */
|
#endif /* DRIVER_I_H */
|
||||||
|
|
|
@ -1950,6 +1950,50 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
data->rx_probe_req.ie,
|
data->rx_probe_req.ie,
|
||||||
data->rx_probe_req.ie_len);
|
data->rx_probe_req.ie_len);
|
||||||
break;
|
break;
|
||||||
|
case EVENT_P2P_DEV_FOUND:
|
||||||
|
wpas_dev_found(wpa_s, data->p2p_dev_found.addr,
|
||||||
|
data->p2p_dev_found.dev_addr,
|
||||||
|
data->p2p_dev_found.pri_dev_type,
|
||||||
|
data->p2p_dev_found.dev_name,
|
||||||
|
data->p2p_dev_found.config_methods,
|
||||||
|
data->p2p_dev_found.dev_capab,
|
||||||
|
data->p2p_dev_found.group_capab);
|
||||||
|
break;
|
||||||
|
case EVENT_P2P_GO_NEG_REQ_RX:
|
||||||
|
wpas_go_neg_req_rx(wpa_s, data->p2p_go_neg_req_rx.src,
|
||||||
|
data->p2p_go_neg_req_rx.dev_passwd_id);
|
||||||
|
break;
|
||||||
|
case EVENT_P2P_GO_NEG_COMPLETED:
|
||||||
|
wpas_go_neg_completed(wpa_s, data->p2p_go_neg_completed.res);
|
||||||
|
break;
|
||||||
|
case EVENT_P2P_PROV_DISC_REQUEST:
|
||||||
|
wpas_prov_disc_req(wpa_s, data->p2p_prov_disc_req.peer,
|
||||||
|
data->p2p_prov_disc_req.config_methods,
|
||||||
|
data->p2p_prov_disc_req.dev_addr,
|
||||||
|
data->p2p_prov_disc_req.pri_dev_type,
|
||||||
|
data->p2p_prov_disc_req.dev_name,
|
||||||
|
data->p2p_prov_disc_req.supp_config_methods,
|
||||||
|
data->p2p_prov_disc_req.dev_capab,
|
||||||
|
data->p2p_prov_disc_req.group_capab);
|
||||||
|
break;
|
||||||
|
case EVENT_P2P_PROV_DISC_RESPONSE:
|
||||||
|
wpas_prov_disc_resp(wpa_s, data->p2p_prov_disc_resp.peer,
|
||||||
|
data->p2p_prov_disc_resp.config_methods);
|
||||||
|
break;
|
||||||
|
case EVENT_P2P_SD_REQUEST:
|
||||||
|
wpas_sd_request(wpa_s, data->p2p_sd_req.freq,
|
||||||
|
data->p2p_sd_req.sa,
|
||||||
|
data->p2p_sd_req.dialog_token,
|
||||||
|
data->p2p_sd_req.update_indic,
|
||||||
|
data->p2p_sd_req.tlvs,
|
||||||
|
data->p2p_sd_req.tlvs_len);
|
||||||
|
break;
|
||||||
|
case EVENT_P2P_SD_RESPONSE:
|
||||||
|
wpas_sd_response(wpa_s, data->p2p_sd_resp.sa,
|
||||||
|
data->p2p_sd_resp.update_indic,
|
||||||
|
data->p2p_sd_resp.tlvs,
|
||||||
|
data->p2p_sd_resp.tlvs_len);
|
||||||
|
break;
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
#ifdef CONFIG_CLIENT_MLME
|
#ifdef CONFIG_CLIENT_MLME
|
||||||
case EVENT_MLME_RX: {
|
case EVENT_MLME_RX: {
|
||||||
|
|
|
@ -642,6 +642,8 @@ void wpas_send_action_tx_status(struct wpa_supplicant *wpa_s, const u8 *dst,
|
||||||
{
|
{
|
||||||
if (wpa_s->global->p2p_disabled)
|
if (wpa_s->global->p2p_disabled)
|
||||||
return;
|
return;
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return;
|
||||||
|
|
||||||
if (wpa_s->pending_action_tx == NULL) {
|
if (wpa_s->pending_action_tx == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - no "
|
wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - no "
|
||||||
|
@ -1050,6 +1052,8 @@ static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Group Formation timed out");
|
wpa_printf(MSG_DEBUG, "P2P: Group Formation timed out");
|
||||||
if (wpa_s->global->p2p)
|
if (wpa_s->global->p2p)
|
||||||
p2p_group_formation_failed(wpa_s->global->p2p);
|
p2p_group_formation_failed(wpa_s->global->p2p);
|
||||||
|
else if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
wpa_drv_p2p_group_formation_failed(wpa_s);
|
||||||
wpas_group_formation_completed(wpa_s, 0);
|
wpas_group_formation_completed(wpa_s, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1623,6 +1627,8 @@ void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic,
|
||||||
void * wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst,
|
void * wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst,
|
||||||
const struct wpabuf *tlvs)
|
const struct wpabuf *tlvs)
|
||||||
{
|
{
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return (void *) wpa_drv_p2p_sd_request(wpa_s, dst, tlvs);
|
||||||
return p2p_sd_request(wpa_s->global->p2p, dst, tlvs);
|
return p2p_sd_request(wpa_s->global->p2p, dst, tlvs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1649,6 +1655,8 @@ void * wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst,
|
||||||
|
|
||||||
int wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, void *req)
|
int wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, void *req)
|
||||||
{
|
{
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return wpa_drv_p2p_sd_cancel_request(wpa_s, (u64) req);
|
||||||
return p2p_sd_cancel_request(wpa_s->global->p2p, req);
|
return p2p_sd_cancel_request(wpa_s->global->p2p, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1657,6 +1665,11 @@ void wpas_p2p_sd_response(struct wpa_supplicant *wpa_s, int freq,
|
||||||
const u8 *dst, u8 dialog_token,
|
const u8 *dst, u8 dialog_token,
|
||||||
const struct wpabuf *resp_tlvs)
|
const struct wpabuf *resp_tlvs)
|
||||||
{
|
{
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
|
||||||
|
wpa_drv_p2p_sd_response(wpa_s, freq, dst, dialog_token,
|
||||||
|
resp_tlvs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
p2p_sd_response(wpa_s->global->p2p, freq, dst, dialog_token,
|
p2p_sd_response(wpa_s->global->p2p, freq, dst, dialog_token,
|
||||||
resp_tlvs);
|
resp_tlvs);
|
||||||
}
|
}
|
||||||
|
@ -1664,6 +1677,10 @@ void wpas_p2p_sd_response(struct wpa_supplicant *wpa_s, int freq,
|
||||||
|
|
||||||
void wpas_p2p_sd_service_update(struct wpa_supplicant *wpa_s)
|
void wpas_p2p_sd_service_update(struct wpa_supplicant *wpa_s)
|
||||||
{
|
{
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
|
||||||
|
wpa_drv_p2p_service_update(wpa_s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
p2p_sd_service_update(wpa_s->global->p2p);
|
p2p_sd_service_update(wpa_s->global->p2p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2247,6 +2264,39 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
|
||||||
if (global->p2p)
|
if (global->p2p)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
|
||||||
|
struct p2p_params params;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Use driver-based P2P management");
|
||||||
|
os_memset(¶ms, 0, sizeof(params));
|
||||||
|
params.dev_name = wpa_s->conf->device_name;
|
||||||
|
if (wpa_s->conf->device_type &&
|
||||||
|
wps_dev_type_str2bin(wpa_s->conf->device_type,
|
||||||
|
params.pri_dev_type) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "P2P: Invalid device_type");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAX_SEC_DEVICE_TYPES; i++) {
|
||||||
|
if (wpa_s->conf->sec_device_type[i] == NULL)
|
||||||
|
continue;
|
||||||
|
if (wps_dev_type_str2bin(
|
||||||
|
wpa_s->conf->sec_device_type[i],
|
||||||
|
params.sec_dev_type[
|
||||||
|
params.num_sec_dev_types]) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "P2P: Invalid "
|
||||||
|
"sec_device_type");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
params.num_sec_dev_types++;
|
||||||
|
if (params.num_sec_dev_types == DRV_MAX_SEC_DEV_TYPES)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (wpa_drv_p2p_set_params(wpa_s, ¶ms) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
os_memset(&p2p, 0, sizeof(p2p));
|
os_memset(&p2p, 0, sizeof(p2p));
|
||||||
p2p.msg_ctx = wpa_s;
|
p2p.msg_ctx = wpa_s;
|
||||||
p2p.cb_ctx = wpa_s;
|
p2p.cb_ctx = wpa_s;
|
||||||
|
@ -2466,6 +2516,12 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
|
||||||
int go_intent, const u8 *own_interface_addr,
|
int go_intent, const u8 *own_interface_addr,
|
||||||
unsigned int force_freq, int persistent_group)
|
unsigned int force_freq, int persistent_group)
|
||||||
{
|
{
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
|
||||||
|
return wpa_drv_p2p_connect(wpa_s, peer_addr, wps_method,
|
||||||
|
go_intent, own_interface_addr,
|
||||||
|
force_freq, persistent_group);
|
||||||
|
}
|
||||||
|
|
||||||
return p2p_connect(wpa_s->global->p2p, peer_addr, wps_method,
|
return p2p_connect(wpa_s->global->p2p, peer_addr, wps_method,
|
||||||
go_intent, own_interface_addr, force_freq,
|
go_intent, own_interface_addr, force_freq,
|
||||||
persistent_group);
|
persistent_group);
|
||||||
|
@ -2478,6 +2534,9 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s,
|
||||||
int go_intent, const u8 *own_interface_addr,
|
int go_intent, const u8 *own_interface_addr,
|
||||||
unsigned int force_freq, int persistent_group)
|
unsigned int force_freq, int persistent_group)
|
||||||
{
|
{
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return p2p_authorize(wpa_s->global->p2p, peer_addr, wps_method,
|
return p2p_authorize(wpa_s->global->p2p, peer_addr, wps_method,
|
||||||
go_intent, own_interface_addr, force_freq,
|
go_intent, own_interface_addr, force_freq,
|
||||||
persistent_group);
|
persistent_group);
|
||||||
|
@ -2907,6 +2966,9 @@ static int wpas_p2p_listen_start(struct wpa_supplicant *wpa_s,
|
||||||
if (timeout > wpa_s->max_remain_on_chan)
|
if (timeout > wpa_s->max_remain_on_chan)
|
||||||
timeout = wpa_s->max_remain_on_chan;
|
timeout = wpa_s->max_remain_on_chan;
|
||||||
|
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return wpa_drv_p2p_listen(wpa_s, timeout);
|
||||||
|
|
||||||
return p2p_listen(wpa_s->global->p2p, timeout);
|
return p2p_listen(wpa_s->global->p2p, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3284,6 +3346,9 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
|
||||||
struct p2p_group *group;
|
struct p2p_group *group;
|
||||||
struct p2p_group_config *cfg;
|
struct p2p_group_config *cfg;
|
||||||
|
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
cfg = os_zalloc(sizeof(*cfg));
|
cfg = os_zalloc(sizeof(*cfg));
|
||||||
if (cfg == NULL)
|
if (cfg == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3322,6 +3387,8 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
NULL);
|
NULL);
|
||||||
if (wpa_s->global->p2p)
|
if (wpa_s->global->p2p)
|
||||||
p2p_wps_success_cb(wpa_s->global->p2p, peer_addr);
|
p2p_wps_success_cb(wpa_s->global->p2p, peer_addr);
|
||||||
|
else if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
wpa_drv_wps_success_cb(wpa_s, peer_addr);
|
||||||
wpas_group_formation_completed(wpa_s, 1);
|
wpas_group_formation_completed(wpa_s, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3341,6 +3408,11 @@ int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
|
||||||
|
return wpa_drv_p2p_prov_disc_req(wpa_s, peer_addr,
|
||||||
|
config_methods);
|
||||||
|
}
|
||||||
|
|
||||||
if (wpa_s->global->p2p == NULL)
|
if (wpa_s->global->p2p == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -3374,6 +3446,9 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
|
||||||
wpas_p2p_clear_pending_action_tx(wpa_s);
|
wpas_p2p_clear_pending_action_tx(wpa_s);
|
||||||
wpa_s->p2p_long_listen = 0;
|
wpa_s->p2p_long_listen = 0;
|
||||||
|
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return wpa_drv_p2p_find(wpa_s, timeout, type);
|
||||||
|
|
||||||
return p2p_find(wpa_s->global->p2p, timeout, type);
|
return p2p_find(wpa_s->global->p2p, timeout, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3385,6 +3460,11 @@ void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s)
|
||||||
eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
|
eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
|
||||||
eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
|
eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
|
||||||
|
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
|
||||||
|
wpa_drv_p2p_stop_find(wpa_s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
p2p_stop_find(wpa_s->global->p2p);
|
p2p_stop_find(wpa_s->global->p2p);
|
||||||
|
|
||||||
wpas_p2p_remove_pending_group_interface(wpa_s);
|
wpas_p2p_remove_pending_group_interface(wpa_s);
|
||||||
|
@ -3497,6 +3577,9 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
|
||||||
{
|
{
|
||||||
wpa_s->p2p_long_listen = 0;
|
wpa_s->p2p_long_listen = 0;
|
||||||
|
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return wpa_drv_p2p_reject(wpa_s, addr);
|
||||||
|
|
||||||
return p2p_reject(wpa_s->global->p2p, addr);
|
return p2p_reject(wpa_s->global->p2p, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3532,6 +3615,11 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
}
|
}
|
||||||
wpa_s->pending_invite_ssid_id = ssid->id;
|
wpa_s->pending_invite_ssid_id = ssid->id;
|
||||||
|
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid,
|
||||||
|
ssid->ssid, ssid->ssid_len,
|
||||||
|
go_dev_addr, 1);
|
||||||
|
|
||||||
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
|
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
|
||||||
ssid->ssid, ssid->ssid_len, 0, go_dev_addr, 1);
|
ssid->ssid, ssid->ssid_len, 0, go_dev_addr, 1);
|
||||||
}
|
}
|
||||||
|
@ -3581,6 +3669,11 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
|
||||||
}
|
}
|
||||||
wpa_s->parent->pending_invite_ssid_id = -1;
|
wpa_s->parent->pending_invite_ssid_id = -1;
|
||||||
|
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid,
|
||||||
|
ssid->ssid, ssid->ssid_len,
|
||||||
|
go_dev_addr, 0);
|
||||||
|
|
||||||
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
|
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
|
||||||
ssid->ssid, ssid->ssid_len, wpa_s->assoc_freq,
|
ssid->ssid, ssid->ssid_len, wpa_s->assoc_freq,
|
||||||
go_dev_addr, 0);
|
go_dev_addr, 0);
|
||||||
|
@ -3638,6 +3731,9 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
|
||||||
int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
|
int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
|
||||||
u32 interval1, u32 duration2, u32 interval2)
|
u32 interval1, u32 duration2, u32 interval2)
|
||||||
{
|
{
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (wpa_s->wpa_state < WPA_ASSOCIATED ||
|
if (wpa_s->wpa_state < WPA_ASSOCIATED ||
|
||||||
wpa_s->current_ssid == NULL ||
|
wpa_s->current_ssid == NULL ||
|
||||||
wpa_s->current_ssid->mode != WPAS_MODE_INFRA)
|
wpa_s->current_ssid->mode != WPAS_MODE_INFRA)
|
||||||
|
@ -3652,6 +3748,9 @@ int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
|
||||||
int wpas_p2p_ext_listen(struct wpa_supplicant *wpa_s, unsigned int period,
|
int wpas_p2p_ext_listen(struct wpa_supplicant *wpa_s, unsigned int period,
|
||||||
unsigned int interval)
|
unsigned int interval)
|
||||||
{
|
{
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return p2p_ext_listen(wpa_s->global->p2p, period, interval);
|
return p2p_ext_listen(wpa_s->global->p2p, period, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3694,6 +3793,8 @@ void wpas_p2p_deauth_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
{
|
{
|
||||||
if (wpa_s->global->p2p_disabled)
|
if (wpa_s->global->p2p_disabled)
|
||||||
return;
|
return;
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return;
|
||||||
|
|
||||||
p2p_deauth_notif(wpa_s->global->p2p, bssid, reason_code, ie, ie_len);
|
p2p_deauth_notif(wpa_s->global->p2p, bssid, reason_code, ie, ie_len);
|
||||||
}
|
}
|
||||||
|
@ -3704,6 +3805,8 @@ void wpas_p2p_disassoc_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
{
|
{
|
||||||
if (wpa_s->global->p2p_disabled)
|
if (wpa_s->global->p2p_disabled)
|
||||||
return;
|
return;
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return;
|
||||||
|
|
||||||
p2p_disassoc_notif(wpa_s->global->p2p, bssid, reason_code, ie, ie_len);
|
p2p_disassoc_notif(wpa_s->global->p2p, bssid, reason_code, ie, ie_len);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue