P2P: Add P2P information for Doxygen docs
Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
f2e03085d7
commit
f765701faf
6 changed files with 746 additions and 1 deletions
6
doc/.gitignore
vendored
6
doc/.gitignore
vendored
|
@ -3,6 +3,12 @@ hostapd.eps
|
||||||
hostapd.png
|
hostapd.png
|
||||||
html
|
html
|
||||||
latex
|
latex
|
||||||
|
p2p_arch.eps
|
||||||
|
p2p_arch.png
|
||||||
|
p2p_arch2.eps
|
||||||
|
p2p_arch2.png
|
||||||
|
p2p_sm.eps
|
||||||
|
p2p_sm.png
|
||||||
wpa_supplicant.eps
|
wpa_supplicant.eps
|
||||||
wpa_supplicant.png
|
wpa_supplicant.png
|
||||||
wpa_supplicant-devel.pdf
|
wpa_supplicant-devel.pdf
|
||||||
|
|
11
doc/Makefile
11
doc/Makefile
|
@ -7,10 +7,16 @@ all: docs
|
||||||
fig2dev -L png -m 3 $*.fig | pngtopnm | pnmscale 0.4 | pnmtopng \
|
fig2dev -L png -m 3 $*.fig | pngtopnm | pnmscale 0.4 | pnmtopng \
|
||||||
> $*.png
|
> $*.png
|
||||||
|
|
||||||
|
%.png: %.dot
|
||||||
|
dot $*.dot -Tpng -o $*.png
|
||||||
|
|
||||||
|
%.eps: %.dot
|
||||||
|
dot $*.dot -Tps -o $*.eps
|
||||||
|
|
||||||
_wpa_supplicant.png: wpa_supplicant.png
|
_wpa_supplicant.png: wpa_supplicant.png
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
docs-pics: wpa_supplicant.png wpa_supplicant.eps hostapd.png hostapd.eps
|
docs-pics: wpa_supplicant.png wpa_supplicant.eps hostapd.png hostapd.eps p2p_sm.png p2p_sm.eps p2p_arch.png p2p_arch.eps p2p_arch2.png p2p_arch2.eps
|
||||||
|
|
||||||
docs: docs-pics
|
docs: docs-pics
|
||||||
(cd ..; doxygen doc/doxygen.conf; cd doc)
|
(cd ..; doxygen doc/doxygen.conf; cd doc)
|
||||||
|
@ -25,6 +31,9 @@ clean:
|
||||||
rm -f wpa_supplicant.eps wpa_supplicant.png
|
rm -f wpa_supplicant.eps wpa_supplicant.png
|
||||||
rm -f _wpa_supplicant.png
|
rm -f _wpa_supplicant.png
|
||||||
rm -f hostapd.eps hostapd.png
|
rm -f hostapd.eps hostapd.png
|
||||||
|
rm -f p2p_sm.eps p2p_sm.png
|
||||||
|
rm -f p2p_arch.eps p2p_arch.png
|
||||||
|
rm -f p2p_arch2.eps p2p_arch2.png
|
||||||
rm -f doxygen.warnings
|
rm -f doxygen.warnings
|
||||||
rm -rf html latex
|
rm -rf html latex
|
||||||
rm -f wpa_supplicant-devel.pdf
|
rm -f wpa_supplicant-devel.pdf
|
||||||
|
|
498
doc/p2p.doxygen
Normal file
498
doc/p2p.doxygen
Normal file
|
@ -0,0 +1,498 @@
|
||||||
|
/**
|
||||||
|
\page p2p Wi-Fi Direct - P2P module
|
||||||
|
|
||||||
|
Wi-Fi Direct functionality is implemented any many levels in the WLAN
|
||||||
|
stack from low-level driver operations to high-level GUI design. This
|
||||||
|
document covers the parts that can be user by %wpa_supplicant. However,
|
||||||
|
it should be noted that alternative designs are also possible, so some
|
||||||
|
of the functionality may reside in other components in the system.
|
||||||
|
|
||||||
|
The driver (or WLAN firmware/hardware) is expected to handle low-level
|
||||||
|
operations related to P2P Power Management and channel scheduling. In
|
||||||
|
addition, support for virtual network interface and data frame
|
||||||
|
processing is done inside the driver. Configuration for these
|
||||||
|
low-level operations is defined in the driver interface:
|
||||||
|
src/drivers/driver.h. This defines both the commands and events used to
|
||||||
|
interact with the driver.
|
||||||
|
|
||||||
|
P2P module implements higher layer functionality for management P2P
|
||||||
|
groups. It takes care of Device Discovery, Service Discovery, Group
|
||||||
|
Owner Negotiation, P2P Invitation. In addition, it maintains
|
||||||
|
information about neighboring P2P Devices. This module could be used
|
||||||
|
in designs that do not use %wpa_supplicant and it could also reside
|
||||||
|
inside the driver/firmware component. P2P module API is defined in
|
||||||
|
src/p2p/p2p.h.
|
||||||
|
|
||||||
|
Provisioning step of Group Formation is implemented using WPS
|
||||||
|
(src/wps/wps.h).
|
||||||
|
|
||||||
|
%wpa_supplicant includes code in interact with both the P2P module
|
||||||
|
(wpa_supplicant/p2p_supplicant.c) and WPS
|
||||||
|
(wpa_supplicant/wps_supplicant.c). The driver operations are passed
|
||||||
|
through these files, i.e., core P2P or WPS code does not interact
|
||||||
|
directly with the driver interface.
|
||||||
|
|
||||||
|
|
||||||
|
\section p2p_arch P2P architecture
|
||||||
|
|
||||||
|
P2P functionality affects many areas of the system architecture. This
|
||||||
|
section shows couple of examples on the location of main P2P
|
||||||
|
components. In the diagrams below, green arrows are used to show
|
||||||
|
communication paths from the P2P module to upper layer management
|
||||||
|
functionality and all the way to a GUI that user could use to manage
|
||||||
|
P2P connections. Blue arrows show the path taken for lower layer
|
||||||
|
operations. Glue code is used to bind the P2P module API to the rest
|
||||||
|
of the system to provide access both towards upper and lower layer
|
||||||
|
functionality.
|
||||||
|
|
||||||
|
\subsection p2p_arch_mac80211 P2P architecture with Linux/mac80211/ath9k
|
||||||
|
|
||||||
|
An architecture where the P2P module resides inside the
|
||||||
|
%wpa_supplicant process is used with Linux mac80211-based drivers,
|
||||||
|
e.g., ath9k. The following diagram shows the main components related
|
||||||
|
to P2P functionality in such an architecture.
|
||||||
|
|
||||||
|
\image html p2p_arch.png "P2P module within wpa_supplicant"
|
||||||
|
\image latex p2p_arch.eps "P2P module within wpa_supplicant" width=15cm
|
||||||
|
|
||||||
|
\subsection p2p_arch_umac P2P architecture with UMAC
|
||||||
|
|
||||||
|
The following diagram shows the main components related to P2P
|
||||||
|
functionality in an architecture where the P2P module resides inside
|
||||||
|
the kernel IEEE 802.11 stack (UMAC in the figure).
|
||||||
|
|
||||||
|
\image html p2p_arch2.png "P2P module in kernel
|
||||||
|
\image latex p2p_arch2.eps "P2P module in kernel" width=15cm
|
||||||
|
|
||||||
|
|
||||||
|
\section p2p_module P2P module
|
||||||
|
|
||||||
|
P2P module manages discovery and group formation with a single state
|
||||||
|
machine, i.e., only a single operation per device can be in progress
|
||||||
|
at any given time. The following diagram describes the P2P state
|
||||||
|
machine. For clarity, it does not include state transitions on
|
||||||
|
operation timeouts to the IDLE state. The states that are marked with
|
||||||
|
dotted ellipse are listed for clarity to describe the protocol
|
||||||
|
functionality for Device Discovery phase, but are not used in the
|
||||||
|
implementation (the SEARCH state is used to manage the initial Scan
|
||||||
|
and the alternating Listen and Search states within Find).
|
||||||
|
|
||||||
|
\image html p2p_sm.png "P2P module state machine"
|
||||||
|
\image latex p2p_sm.eps "P2P module state machine" width=15cm
|
||||||
|
|
||||||
|
\subsection p2p_module_api P2P module API
|
||||||
|
|
||||||
|
P2P module API is defined in src/p2p/p2p.h. The API consists of
|
||||||
|
functions for requesting operations and for providing event
|
||||||
|
notifications. Similar set of callback functions are configured with
|
||||||
|
struct p2p_config to provide callback functions that P2P module can
|
||||||
|
use to request operations and to provide event notifications. In
|
||||||
|
addition, there are number of generic helper functions that can be
|
||||||
|
used for P2P related operations.
|
||||||
|
|
||||||
|
These are the main functions for an upper layer management entity to
|
||||||
|
request P2P operations:
|
||||||
|
- p2p_find()
|
||||||
|
- p2p_stop_find()
|
||||||
|
- p2p_listen()
|
||||||
|
- p2p_connect()
|
||||||
|
- p2p_reject()
|
||||||
|
- p2p_prov_disc_req()
|
||||||
|
- p2p_sd_request()
|
||||||
|
- p2p_sd_cancel_request()
|
||||||
|
- p2p_sd_response()
|
||||||
|
- p2p_sd_service_update()
|
||||||
|
- p2p_invite()
|
||||||
|
|
||||||
|
These are the main callback functions for P2P module to provide event
|
||||||
|
notifications to the upper layer management entity:
|
||||||
|
|
||||||
|
- p2p_config::dev_found()
|
||||||
|
- p2p_config::go_neg_req_rx()
|
||||||
|
- p2p_config::go_neg_completed()
|
||||||
|
- p2p_config::sd_request()
|
||||||
|
- p2p_config::sd_response()
|
||||||
|
- p2p_config::prov_disc_req()
|
||||||
|
- p2p_config::prov_disc_resp()
|
||||||
|
- p2p_config::invitation_process()
|
||||||
|
- p2p_config::invitation_received()
|
||||||
|
- p2p_config::invitation_result()
|
||||||
|
|
||||||
|
The P2P module uses following functions to request lower layer driver
|
||||||
|
operations:
|
||||||
|
|
||||||
|
- p2p_config::p2p_scan()
|
||||||
|
- p2p_config::send_probe_resp()
|
||||||
|
- p2p_config::send_action()
|
||||||
|
- p2p_config::send_action_done()
|
||||||
|
- p2p_config::start_listen()
|
||||||
|
- p2p_config::stop_listen()
|
||||||
|
|
||||||
|
Events from lower layer driver operations are delivered to the P2P
|
||||||
|
module with following functions:
|
||||||
|
|
||||||
|
- p2p_probe_req_rx()
|
||||||
|
- p2p_rx_action()
|
||||||
|
- p2p_scan_res_handler()
|
||||||
|
- p2p_scan_res_handled()
|
||||||
|
- p2p_send_action_cb()
|
||||||
|
- p2p_listen_cb()
|
||||||
|
|
||||||
|
In addition to the per-device state, the P2P module maintains
|
||||||
|
per-group state for group owners. This is initialized with a call to
|
||||||
|
p2p_group_init() when a group is created and deinitialized with
|
||||||
|
p2p_group_deinit(). The upper layer GO management entity uses
|
||||||
|
following functions to interact with the P2P per-group state:
|
||||||
|
|
||||||
|
- p2p_group_notif_assoc()
|
||||||
|
- p2p_group_notif_disassoc()
|
||||||
|
- p2p_group_notif_formation_done()
|
||||||
|
- p2p_group_match_dev_type()
|
||||||
|
|
||||||
|
The P2P module will use following callback function to update P2P IE
|
||||||
|
for GO Beacon and Probe Response frames:
|
||||||
|
|
||||||
|
- p2p_group_config::ie_update()
|
||||||
|
|
||||||
|
|
||||||
|
\section p2p_driver P2P driver operations (low-level interface)
|
||||||
|
|
||||||
|
The following driver wrapper functions are needed for P2P in addition
|
||||||
|
to the standard station/AP mode operations when the P2P module resides
|
||||||
|
within %wpa_supplicant:
|
||||||
|
- wpa_driver_ops::if_add()
|
||||||
|
- wpa_driver_ops::if_remove()
|
||||||
|
- wpa_driver_ops::alloc_interface_addr()
|
||||||
|
- wpa_driver_ops::release_interface_addr()
|
||||||
|
- wpa_driver_ops::remain_on_channel()
|
||||||
|
- wpa_driver_ops::cancel_remain_on_channel()
|
||||||
|
- wpa_driver_ops::send_action()
|
||||||
|
- wpa_driver_ops::probe_req_report()
|
||||||
|
- wpa_driver_ops::disable_11b_rates()
|
||||||
|
|
||||||
|
The following driver wrapper events are needed for P2P in addition to
|
||||||
|
the standard station/AP mode events when the P2P module resides within
|
||||||
|
%wpa_supplicant:
|
||||||
|
- wpa_event_type::EVENT_RX_ACTION
|
||||||
|
- wpa_event_type::EVENT_REMAIN_ON_CHANNEL
|
||||||
|
- wpa_event_type::EVENT_CANCEL_REMAIN_ON_CHANNEL
|
||||||
|
- wpa_event_type::EVENT_RX_PROBE_REQ
|
||||||
|
|
||||||
|
The following driver wrapper functions are needed for P2P in addition
|
||||||
|
to the standard station/AP mode operations when the P2P module resides
|
||||||
|
in the driver or firmware:
|
||||||
|
- wpa_driver_ops::if_add()
|
||||||
|
- wpa_driver_ops::if_remove()
|
||||||
|
- wpa_driver_ops::alloc_interface_addr()
|
||||||
|
- wpa_driver_ops::release_interface_addr()
|
||||||
|
- wpa_driver_ops::disable_11b_rates()
|
||||||
|
- wpa_driver_ops::p2p_find()
|
||||||
|
- wpa_driver_ops::p2p_stop_find()
|
||||||
|
- wpa_driver_ops::p2p_listen()
|
||||||
|
- wpa_driver_ops::p2p_connect()
|
||||||
|
- wpa_driver_ops::p2p_reject()
|
||||||
|
- wpa_driver_ops::wps_success_cb()
|
||||||
|
- wpa_driver_ops::p2p_group_formation_failed()
|
||||||
|
- wpa_driver_ops::p2p_set_params()
|
||||||
|
|
||||||
|
The following driver wrapper events are needed for P2P in addition to
|
||||||
|
the standard station/AP mode events when the P2P module resides in the
|
||||||
|
driver or firmware:
|
||||||
|
- wpa_event_type::EVENT_P2P_DEV_FOUND
|
||||||
|
- wpa_event_type::EVENT_P2P_GO_NEG_REQ_RX
|
||||||
|
- wpa_event_type::EVENT_P2P_GO_NEG_COMPLETED
|
||||||
|
|
||||||
|
|
||||||
|
\section p2p_go_neg P2P device discovery and group formation
|
||||||
|
|
||||||
|
This section shows an example sequence of operations that can be used
|
||||||
|
to implement P2P device discovery and group formation. The function
|
||||||
|
calls are described based on the P2P module API. The exact design for
|
||||||
|
the glue code outside the P2P module depends on the architecture used
|
||||||
|
in the system.
|
||||||
|
|
||||||
|
An upper layer management entity starts P2P device discovery by
|
||||||
|
calling p2p_find(). The P2P module start the discovery by requesting a
|
||||||
|
full scan to be completed by calling p2p_config::p2p_scan(). Results
|
||||||
|
from the scan will be reported by calling p2p_scan_res_handler() and
|
||||||
|
after last result, the scan result processing is terminated with a
|
||||||
|
call to p2p_scan_res_handled(). The P2P peers that are found during
|
||||||
|
the full scan are reported with the p2p_config::dev_found() callback.
|
||||||
|
|
||||||
|
After the full scan, P2P module start alternating between Listen and
|
||||||
|
Search states until the device discovery operation times out or
|
||||||
|
terminated, e.g., with a call to p2p_stop_find().
|
||||||
|
|
||||||
|
When going into the Listen state, the P2P module requests the driver
|
||||||
|
to be configured to be awake on the listen channel with a call to
|
||||||
|
p2p_config::start_listen(). The glue code using the P2P module may
|
||||||
|
implement this, e.g., by using remain-on-channel low-level driver
|
||||||
|
functionality for off-channel operation. Once the driver is available
|
||||||
|
on the requested channel, notification of this is delivered by calling
|
||||||
|
p2p_listen_cb(). The Probe Request frames that are received during the
|
||||||
|
Listen period are delivered to the P2P module by calling
|
||||||
|
p2p_config::p2p_probe_req_rx() and P2P module request a response to
|
||||||
|
these to be sent by using p2p_config::send_probe_resp() callback
|
||||||
|
function. If a group owner negotiation from another P2P device is
|
||||||
|
received during the device discovery phase, that is indicated to the
|
||||||
|
upper layer code with the p2p_config::go_neg_req_tx() callback.
|
||||||
|
|
||||||
|
The Search state is implemented by using the normal scan interface,
|
||||||
|
i.e., the P2P module will call p2p_config::p2p_scan() just like in the
|
||||||
|
full scan phase described. Similarly, scan results from the search
|
||||||
|
operation will be delivered to the P2P module using the
|
||||||
|
p2p_scan_res_handler() and p2p_scan_res_handled() functions.
|
||||||
|
|
||||||
|
Once the upper layer management entity has found a peer with which it
|
||||||
|
wants to connect by forming a new group, it initiates group owner
|
||||||
|
negotiation by calling p2p_connect(). Before doing this, the upper
|
||||||
|
layer code is responsible for asking the user to provide the PIN to be
|
||||||
|
used during the provisioning step with the peer or the push button
|
||||||
|
press for PBC mode. The glue code will need to figure out the intended
|
||||||
|
interface address for the group before group owner negotiation can be
|
||||||
|
started.
|
||||||
|
|
||||||
|
Optional Provision Discovery mechanism can be used to request the peer
|
||||||
|
to display a PIN for the local device to enter (and vice versa). Upper
|
||||||
|
layer management entity can request the specific mechanism by calling
|
||||||
|
p2p_prov_disc_req(). The response to this will be reported with the
|
||||||
|
p2p_config::prov_disc_resp() callback. If the peer device started
|
||||||
|
Provision Discovery, an accepted request will be reported with the
|
||||||
|
p2p_config::prov_disc_req() callback. The P2P module will
|
||||||
|
automatically accept the Provision Discovery for display and keypad
|
||||||
|
methods, but it is up to the upper layer manegement entity to actually
|
||||||
|
generate the PIN and to configure it with following p2p_connect() call
|
||||||
|
to actually authorize the connection.
|
||||||
|
|
||||||
|
The P2P module will use p2p_config::send_action() callback to request
|
||||||
|
lower layer code to transmit an Action frame during group owner
|
||||||
|
negotiation. p2p_send_action_cb() is used to report the result of
|
||||||
|
transmission. If the peer is not reachable, the P2P module will try to
|
||||||
|
find it by alternating between Action frame send and Listen
|
||||||
|
states. The Listen state for this phase will be used similarly to the
|
||||||
|
Listen state during device discovery as described above.
|
||||||
|
|
||||||
|
Once the group owner negotiation has been completed, its results will
|
||||||
|
be reported with the p2p_config::go_neg_completed() callback. The
|
||||||
|
upper layer management code or the glue code using the P2P module API
|
||||||
|
is responsible for creating a new group interface and starting
|
||||||
|
provisioning step at this point by configuring WPS Registrar or
|
||||||
|
Enrollee functionality based on the reported group owner negotiation
|
||||||
|
results. The upper layer code is also responsible for timing out WPS
|
||||||
|
provisioning if it cannot be completed in 15 seconds.
|
||||||
|
|
||||||
|
Successful completion of the WPS provisioning is reported with a call
|
||||||
|
to p2p_wps_success_cb(). The P2P module will clear its group formation
|
||||||
|
state at this point and allows new group formation attempts to be
|
||||||
|
started. The upper layer management code is responsible for configuring
|
||||||
|
the GO to accept associations from devices and the client to connect to
|
||||||
|
the GO with the provisioned credentials. GO is also responsible for
|
||||||
|
calling p2p_group_notif_formation_done() as described below.
|
||||||
|
|
||||||
|
If the WPS provisioning step fails or times out, this is reported with
|
||||||
|
a call to p2p_group_formation_failed(). The P2P module will clear its
|
||||||
|
group formation state at this point and allows new group formation
|
||||||
|
attempts to be started. The upper layer management code is responsible
|
||||||
|
for removing the group interface for the failed group.
|
||||||
|
|
||||||
|
|
||||||
|
\section p2p_sd P2P service discovery
|
||||||
|
|
||||||
|
P2P protocol includes service discovery functionality that can be used
|
||||||
|
to discover which services are provided by the peers before forming a
|
||||||
|
group. This leverages the Generic Advertisement Service (GAS) protocol
|
||||||
|
from IEEE 802.11u and P2P vendor-specific contents inside the Native
|
||||||
|
GAS messages.
|
||||||
|
|
||||||
|
The P2P module takes care of GAS encapsulation, fragmentation, and
|
||||||
|
actual transmission and reception of the Action frames needed for
|
||||||
|
service discovery. The user of the P2P module is responsible for
|
||||||
|
providing P2P specific Service Request TLV(s) for queries and Service
|
||||||
|
Response TLV(s) for responses.
|
||||||
|
|
||||||
|
\subsection p2p_sd_query Quering services of peers
|
||||||
|
|
||||||
|
Service discovery is implemented by processing pending queries as a
|
||||||
|
part of the device discovery phase. p2p_sd_request() function is used
|
||||||
|
to schedule service discovery queries to a specific peer or to all
|
||||||
|
discovered peers. p2p_sd_cancel_request() can be used to cancel a
|
||||||
|
scheduled query. Queries that are specific to a single peer will be
|
||||||
|
removed automatically after the response has been received.
|
||||||
|
|
||||||
|
After the service discovery queries have been queued, device discovery
|
||||||
|
is started with a call to p2p_find(). The pending service discovery
|
||||||
|
queries are then sent whenever a peer is discovered during the find
|
||||||
|
operation. Responses to the queries will be reported with the
|
||||||
|
p2p_config::sd_response() callback.
|
||||||
|
|
||||||
|
\subsection p2p_sd_response Replying to service discovery queries from peers
|
||||||
|
|
||||||
|
The received service discovery requests will be indicated with the
|
||||||
|
p2p_config::sd_request() callback. The response to the query is sent
|
||||||
|
by calling p2p_sd_response().
|
||||||
|
|
||||||
|
\subsection p2p_sd_indicator Service update indicator
|
||||||
|
|
||||||
|
P2P service discovery provides a mechanism to notify peers about
|
||||||
|
changes in available services. This works by incrementing Service
|
||||||
|
Update Indicator value whenever there is a change in the
|
||||||
|
services. This value is included in all SD request and response
|
||||||
|
frames. The value received from the peers will be included in the
|
||||||
|
p2p_config::sd_request() and p2p_config::sd_response() callbacks. The
|
||||||
|
value to be sent to the peers is incremented with a call to
|
||||||
|
p2p_sd_service_update() whenever availibility of the local services
|
||||||
|
changes.
|
||||||
|
|
||||||
|
|
||||||
|
\section p2p_go P2P group owner
|
||||||
|
|
||||||
|
This section describes how P2P module can be used for managing
|
||||||
|
per-group information in a group owner. The function calls are
|
||||||
|
described based on the P2P module API. The exact design for the glue
|
||||||
|
code outside the P2P module depends on the architecture used in the
|
||||||
|
system.
|
||||||
|
|
||||||
|
When a P2P group interface is created in group owner role, per-group
|
||||||
|
data is initialized with p2p_group_init(). This call provides a
|
||||||
|
pointer to the per-device P2P module context and configures the
|
||||||
|
per-group operation. The configured p2p_group_config::ie_update()
|
||||||
|
callback is used to set the initial P2P IE for Beacon and Probe
|
||||||
|
Response frames in the group owner. The AP mode implementation may use
|
||||||
|
this information to add IEs into the frames.
|
||||||
|
|
||||||
|
Once the group formation has been completed (or if it is skipped in
|
||||||
|
case of manual group setup), p2p_group_notif_formation_done() is
|
||||||
|
called. This will allow the P2P module to update the P2P IE for
|
||||||
|
Beacon and Probe Response frames.
|
||||||
|
|
||||||
|
The SME/MLME code that managements IEEE 802.11 association processing
|
||||||
|
needs to inform P2P module whenever a P2P client associates or
|
||||||
|
disassociates with the group. This is done by calling
|
||||||
|
p2p_group_notif_assoc() and p2p_group_notif_disassoc(). The P2P module
|
||||||
|
manages a list of group members and updates the P2P Group Information
|
||||||
|
subelement in the P2P IE based on the information from the P2P
|
||||||
|
clients. The p2p_group_config::ie_update() callback is used whenever
|
||||||
|
the P2P IE in Probe Response frames needs to be changed.
|
||||||
|
|
||||||
|
The SME/MLME code that takes care of replying to Probe Request frames
|
||||||
|
can use p2p_group_match_dev_type() to check whether the Probe Request
|
||||||
|
frame request a reply only from groups that include a specific device
|
||||||
|
type in one of the clients or GO. A match will be reported if the
|
||||||
|
Probe Request does not request a specific device type, so this
|
||||||
|
function can be used to filter or received Probe Request frames and
|
||||||
|
only the ones that result in non-zero return value need to be replied.
|
||||||
|
|
||||||
|
When the P2P group interface for GO role is removed,
|
||||||
|
p2p_group_deinit() is used to deinitialize the per-group P2P module
|
||||||
|
state.
|
||||||
|
|
||||||
|
|
||||||
|
\section p2p_ctrl_iface P2P control interface
|
||||||
|
|
||||||
|
%wpa_supplicant \ref ctrl_iface_page "control interface" can be used
|
||||||
|
to manage P2P functionality from an external program (e.g., a GUI or a
|
||||||
|
system configuration manager). This interface can be used directly
|
||||||
|
through the control interface backend mechanism (e.g., local domain
|
||||||
|
sockets on Linux) or with help of wpa_cli (e.g., from a script).
|
||||||
|
|
||||||
|
The following P2P-related commands are available:
|
||||||
|
- \ref ctrl_iface_P2P_FIND P2P_FIND
|
||||||
|
- \ref ctrl_iface_P2P_STOP_FIND P2P_STOP_FIND
|
||||||
|
- \ref ctrl_iface_P2P_CONNECT P2P_CONNECT
|
||||||
|
- \ref ctrl_iface_P2P_LISTEN P2P_LISTEN
|
||||||
|
- \ref ctrl_iface_P2P_GROUP_REMOVE P2P_GROUP_REMOVE
|
||||||
|
- \ref ctrl_iface_P2P_GROUP_ADD P2P_GROUP_ADD
|
||||||
|
- \ref ctrl_iface_P2P_PROV_DISC P2P_PROV_DISC
|
||||||
|
- \ref ctrl_iface_P2P_SERV_DISC_REQ P2P_SERV_DISC_REQ
|
||||||
|
- \ref ctrl_iface_P2P_SERV_DISC_CANCEL_REQ P2P_SERV_DISC_CANCEL_REQ
|
||||||
|
- \ref ctrl_iface_P2P_SERV_DISC_RESP P2P_SERV_DISC_RESP
|
||||||
|
- \ref ctrl_iface_P2P_SERVICE_UPDATE P2P_SERVICE_UPDATE
|
||||||
|
- \ref ctrl_iface_P2P_SERV_DISC_EXTERNAL P2P_SERV_DISC_EXTERNAL
|
||||||
|
- \ref ctrl_iface_P2P_REJECT P2P_REJECT
|
||||||
|
- \ref ctrl_iface_P2P_INVITE P2P_INVITE
|
||||||
|
|
||||||
|
The following P2P-related events are used:
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_DEVICE_FOUND P2P-DEVICE-FOUND
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_GO_NEG_REQUEST P2P-GO-NEG-REQUEST
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_GO_NEG_SUCCESS P2P-GO-NEG-SUCCESS
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_GO_NEG_FAILURE P2P-GO-NEG-FAILURE
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_GROUP_FORMATION_SUCCESS P2P-GROUP-FORMATION-SUCCESS
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_GROUP_FORMATION_FAILURE P2P-GROUP-FORMATION-FAILURE
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_GROUP_STARTED P2P-GROUP-STARTED
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_GROUP_REMOVED P2P-GROUP-REMOVED
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_PROV_DISC_SHOW_PIN P2P-PROV-DISC-SHOW-PIN
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_PROV_DISC_ENTER_PIN P2P-PROV-DISC-ENTER-PIN
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_SERV_DISC_REQ P2P-SERV-DISC-REQ
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_SERV_DISC_RESP P2P-SERV-DISC-RESP
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_INVITATION_RECEIVED P2P-INVITATION-RECEIVED
|
||||||
|
- \ref ctrl_iface_event_P2P_EVENT_INVITATION_RESULT P2P-INVITATION-RESULT
|
||||||
|
|
||||||
|
|
||||||
|
\subsection p2p_wpa_gui GUI example (wpa_gui)
|
||||||
|
|
||||||
|
wpa_gui has an example implementation of a GUI that could be used to
|
||||||
|
manage P2P operations. The P2P related functionality is contained
|
||||||
|
mostly in wpa_supplicant/wpa_gui-qt4/peers.cpp and it shows how the
|
||||||
|
control interface commands and events can be used.
|
||||||
|
|
||||||
|
|
||||||
|
\subsection p2p_wpa_cli wpa_cli example
|
||||||
|
|
||||||
|
wpa_cli can be used to control %wpa_supplicant in interactive
|
||||||
|
mode. The following sessions show examples of commands used for
|
||||||
|
device discovery and group formation. The lines starting with "> " are
|
||||||
|
commands from the user (followed by command result indication) and
|
||||||
|
lines starting with "<2>" are event messages from %wpa_supplicant.
|
||||||
|
|
||||||
|
P2P device "Wireless Client":
|
||||||
|
|
||||||
|
\verbatim
|
||||||
|
> p2p_find
|
||||||
|
OK
|
||||||
|
> <2>P2P-DEVICE-FOUND 02:40:61:c2:f3:b7 p2p_dev_addr=02:40:61:c2:f3:b7
|
||||||
|
pri_dev_type=1-0050F204-1 name='Wireless Client 2' config_methods=0x18c
|
||||||
|
dev_capab=0x1 group_capab=0x0
|
||||||
|
<2>P2P-GO-NEG-REQUEST 02:40:61:c2:f3:b7
|
||||||
|
<2>P2P-GO-NEG-REQUEST 02:40:61:c2:f3:b7
|
||||||
|
> p2p_connect 02:40:61:c2:f3:b7 pbc
|
||||||
|
OK
|
||||||
|
<2>P2P-GO-NEG-SUCCESS
|
||||||
|
<2>P2P-GROUP-FORMATION-SUCCESS
|
||||||
|
<2>P2P-GROUP-STARTED sta0-p2p-0 client DIRECT-vM
|
||||||
|
> interface
|
||||||
|
Available interfaces:
|
||||||
|
sta0-p2p-0
|
||||||
|
sta0
|
||||||
|
> p2p_group_remove sta0-p2p-0
|
||||||
|
<2>P2P-GROUP-REMOVED sta0-p2p-0 client
|
||||||
|
OK
|
||||||
|
> term
|
||||||
|
OK
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
|
||||||
|
P2P device "Wireless Client2" (which ended up operating in GO role):
|
||||||
|
|
||||||
|
\verbatim
|
||||||
|
> p2p_find
|
||||||
|
OK
|
||||||
|
<2>P2P-DEVICE-FOUND 02:f0:bc:44:87:62 p2p_dev_addr=02:f0:bc:44:87:62
|
||||||
|
pri_dev_type=1-0050F204-1 name='Wireless Client' config_methods=0x18c
|
||||||
|
dev_capab=0x1 group_capab=0x0
|
||||||
|
> p2p_connect 02:f0:bc:44:87:62 pbc
|
||||||
|
OK
|
||||||
|
<2>P2P-GO-NEG-SUCCESS
|
||||||
|
<2>P2P-GROUP-FORMATION-SUCCESS
|
||||||
|
<2>P2P-GROUP-STARTED sta1-p2p-0 GO DIRECT-vM
|
||||||
|
> interface
|
||||||
|
Available interfaces:
|
||||||
|
sta1-p2p-0
|
||||||
|
sta1
|
||||||
|
> p2p_group_remove sta1-p2p-0
|
||||||
|
<2>P2P-GROUP-REMOVED sta1-p2p-0 GO
|
||||||
|
OK
|
||||||
|
> term
|
||||||
|
OK
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
*/
|
85
doc/p2p_arch.dot
Normal file
85
doc/p2p_arch.dot
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
digraph p2p_arch {
|
||||||
|
ranksep=.75;
|
||||||
|
size = "7.5,7.5";
|
||||||
|
|
||||||
|
edge [dir=none];
|
||||||
|
|
||||||
|
subgraph cluster_wpa_gui {
|
||||||
|
label = "wpa_gui";
|
||||||
|
|
||||||
|
status -> Qt;
|
||||||
|
scan -> Qt;
|
||||||
|
network -> Qt;
|
||||||
|
Qt -> peers;
|
||||||
|
Qt -> WPS;
|
||||||
|
Qt -> gui_ctrl;
|
||||||
|
|
||||||
|
gui_ctrl [label="ctrl i/f"];
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_wpa_supplicant {
|
||||||
|
label = "wpa_supplicant"
|
||||||
|
|
||||||
|
ctrl_iface [label="ctrl i/f"];
|
||||||
|
authenticator [label="Authenticator"];
|
||||||
|
supplicant [label="Supplicant"];
|
||||||
|
driver_iface [label="driver i/f"];
|
||||||
|
p2p_module [label="P2P\nmodule"];
|
||||||
|
wps_registrar [label="WPS\nRegistrar"];
|
||||||
|
wps_enrollee [label="WPS\nEnrollee"];
|
||||||
|
mgmt_entity [label="Management\nentity"];
|
||||||
|
|
||||||
|
ctrl_iface -> mgmt_entity;
|
||||||
|
p2p_module -> mgmt_entity;
|
||||||
|
wps_registrar -> mgmt_entity;
|
||||||
|
wps_enrollee -> mgmt_entity;
|
||||||
|
mgmt_entity -> authenticator;
|
||||||
|
mgmt_entity -> supplicant;
|
||||||
|
mgmt_entity -> driver_iface;
|
||||||
|
|
||||||
|
{ rank = same; mgmt_entity; p2p_module; }
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_wpa_cli {
|
||||||
|
label = "wpa_cli -a"
|
||||||
|
|
||||||
|
wpa_cli_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_dnsmasq {
|
||||||
|
label = "dnsmasq"
|
||||||
|
|
||||||
|
dnsmasq;
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_dhclient {
|
||||||
|
label = "dhclient"
|
||||||
|
|
||||||
|
dhclient;
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_kernel {
|
||||||
|
label = "Linux kernel"
|
||||||
|
|
||||||
|
cfg80211 -> mac80211;
|
||||||
|
netdev -> mac80211;
|
||||||
|
mac80211 -> ath9k;
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_ctrl -> ctrl_iface;
|
||||||
|
wpa_cli_action -> ctrl_iface;
|
||||||
|
|
||||||
|
driver_iface -> cfg80211;
|
||||||
|
|
||||||
|
wpa_cli_action -> dnsmasq;
|
||||||
|
wpa_cli_action -> dhclient;
|
||||||
|
|
||||||
|
dnsmasq -> netdev;
|
||||||
|
dhclient -> netdev;
|
||||||
|
|
||||||
|
edge [color=blue,dir=both];
|
||||||
|
p2p_module -> mgmt_entity -> driver_iface -> cfg80211 -> mac80211 -> ath9k;
|
||||||
|
|
||||||
|
edge [color=green,dir=both];
|
||||||
|
peers -> Qt -> gui_ctrl -> ctrl_iface -> mgmt_entity -> p2p_module;
|
||||||
|
}
|
85
doc/p2p_arch2.dot
Normal file
85
doc/p2p_arch2.dot
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
digraph p2p_arch2 {
|
||||||
|
ranksep=.75;
|
||||||
|
size = "7.5,7.5";
|
||||||
|
|
||||||
|
edge [dir=none];
|
||||||
|
|
||||||
|
subgraph cluster_wpa_gui {
|
||||||
|
label = "wpa_gui";
|
||||||
|
|
||||||
|
status -> Qt;
|
||||||
|
scan -> Qt;
|
||||||
|
network -> Qt;
|
||||||
|
Qt -> peers;
|
||||||
|
Qt -> WPS;
|
||||||
|
Qt -> gui_ctrl;
|
||||||
|
|
||||||
|
gui_ctrl [label="ctrl i/f"];
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_wpa_supplicant {
|
||||||
|
label = "wpa_supplicant"
|
||||||
|
|
||||||
|
ctrl_iface [label="ctrl i/f"];
|
||||||
|
authenticator [label="Authenticator"];
|
||||||
|
supplicant [label="Supplicant"];
|
||||||
|
driver_iface [label="driver i/f"];
|
||||||
|
wps_registrar [label="WPS\nRegistrar"];
|
||||||
|
wps_enrollee [label="WPS\nEnrollee"];
|
||||||
|
mgmt_entity [label="Management\nentity"];
|
||||||
|
|
||||||
|
ctrl_iface -> mgmt_entity;
|
||||||
|
wps_registrar -> mgmt_entity;
|
||||||
|
wps_enrollee -> mgmt_entity;
|
||||||
|
mgmt_entity -> authenticator;
|
||||||
|
mgmt_entity -> supplicant;
|
||||||
|
mgmt_entity -> driver_iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_wpa_cli {
|
||||||
|
label = "wpa_cli -a"
|
||||||
|
|
||||||
|
wpa_cli_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_dnsmasq {
|
||||||
|
label = "dnsmasq"
|
||||||
|
|
||||||
|
dnsmasq;
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_dhclient {
|
||||||
|
label = "dhclient"
|
||||||
|
|
||||||
|
dhclient;
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_kernel {
|
||||||
|
label = "Kernel"
|
||||||
|
|
||||||
|
ioctl -> umac;
|
||||||
|
netdev -> umac;
|
||||||
|
umac -> p2p_module;
|
||||||
|
p2p_module [label="P2P\nmodule"];
|
||||||
|
umac -> driver;
|
||||||
|
|
||||||
|
{ rank = same; umac; p2p_module; }
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_ctrl -> ctrl_iface;
|
||||||
|
wpa_cli_action -> ctrl_iface;
|
||||||
|
|
||||||
|
driver_iface -> ioctl;
|
||||||
|
|
||||||
|
wpa_cli_action -> dnsmasq;
|
||||||
|
wpa_cli_action -> dhclient;
|
||||||
|
|
||||||
|
dnsmasq -> netdev;
|
||||||
|
dhclient -> netdev;
|
||||||
|
|
||||||
|
edge [color=blue,dir=both];
|
||||||
|
p2p_module -> umac -> driver;
|
||||||
|
|
||||||
|
edge [color=green,dir=both];
|
||||||
|
peers -> Qt -> gui_ctrl -> ctrl_iface -> mgmt_entity -> driver_iface -> ioctl -> umac -> p2p_module;
|
||||||
|
}
|
62
doc/p2p_sm.dot
Normal file
62
doc/p2p_sm.dot
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
digraph p2p {
|
||||||
|
ranksep=.75;
|
||||||
|
size = "8.5,7.5";
|
||||||
|
|
||||||
|
start -> IDLE;
|
||||||
|
start [label="Init",shape=none];
|
||||||
|
|
||||||
|
/* Discovery: Scan followed by Find(SEARCH,LISTEN) */
|
||||||
|
subgraph cluster_0 {
|
||||||
|
label="Discovery";
|
||||||
|
color=lightgrey;
|
||||||
|
node [color=blue];
|
||||||
|
/* SCAN and LISTEN currently not used in the implementation */
|
||||||
|
SCAN [style=dotted];
|
||||||
|
LISTEN [style=dotted];
|
||||||
|
|
||||||
|
SCAN -> LISTEN;
|
||||||
|
LISTEN -> SEARCH -> LISTEN [style=dotted];
|
||||||
|
SEARCH -> SD_DURING_FIND [label="Peer SD capab\nand no info", weight=100];
|
||||||
|
SD_DURING_FIND -> SEARCH [label="RX SD Resp\nor timeout", weight=100];
|
||||||
|
SEARCH -> PROV_DISC_DURING_FIND [label="Prov Disc cmd\nand no Resp", weight=100];
|
||||||
|
PROV_DISC_DURING_FIND -> SEARCH [label="RX Prov Disc Resp\nor timeout", weight=100];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Group Formation */
|
||||||
|
subgraph cluster_1 {
|
||||||
|
label="Group Formation";
|
||||||
|
color=lightgrey;
|
||||||
|
node [color=green];
|
||||||
|
|
||||||
|
CONNECT -> CONNECT_LISTEN [style=dotted,weight=100];
|
||||||
|
CONNECT_LISTEN -> CONNECT [style=dotted,weight=100];
|
||||||
|
CONNECT -> WAIT_PEER_IDLE [label="RX GO Neg Resp\n(info unavail)"];
|
||||||
|
WAIT_PEER_IDLE -> WAIT_PEER_CONNECT [style=dotted,weight=100];
|
||||||
|
WAIT_PEER_CONNECT -> WAIT_PEER_IDLE [style=dotted,weight=100];
|
||||||
|
|
||||||
|
CONNECT -> GO_NEG [label="RX GO Neg Resp\n(success)", weight=10];
|
||||||
|
CONNECT_LISTEN -> GO_NEG [label="RX GO Neg Req or\nTX GO Neg Resp"];
|
||||||
|
WAIT_PEER_CONNECT -> GO_NEG [label="RX GO Neg Req"];
|
||||||
|
GO_NEG -> PROVISIONING [label="TX/RX GO Neg Conf"];
|
||||||
|
}
|
||||||
|
|
||||||
|
PROVISIONING -> IDLE [label="WPS\nsuccess"];
|
||||||
|
|
||||||
|
/* External triggers */
|
||||||
|
IDLE -> SCAN [label="Find cmd",weight=20];
|
||||||
|
IDLE -> CONNECT [label="Connect cmd",weight=20];
|
||||||
|
IDLE -> LISTEN_ONLY [label="Listen cmd"];
|
||||||
|
|
||||||
|
/* Timeouts */
|
||||||
|
/*
|
||||||
|
edge [color=red];
|
||||||
|
WAIT_PEER_IDLE -> IDLE [label="timeout", weight=0];
|
||||||
|
WAIT_PEER_CONNECT -> IDLE [label="timeout", weight=0];
|
||||||
|
CONNECT -> IDLE [label="timeout", weight=0];
|
||||||
|
CONNECT_LISTEN -> IDLE [label="timeout", weight=0];
|
||||||
|
GO_NEG -> IDLE [label="timeout", weight=0];
|
||||||
|
PROVISIONING -> IDLE [label="timeout", weight=0];
|
||||||
|
LISTEN_ONLY -> IDLE [label="timeout", weight=0];
|
||||||
|
SEARCH -> IDLE [label="timeout", weight=0];
|
||||||
|
*/
|
||||||
|
}
|
Loading…
Reference in a new issue