I want to connect two devices using Wifi-Direct. One is a pc with Linux (during my test I'm using Linux Mint 17.2), the other is an Android smartphone (Samsung Galaxy S3 with Android 4.3. Not rooted and don't want to root).
Reading a number of guides on the internet, I decided to use wpa_supplicant in Linux and to create an app for Android. This is one of the best guides I found for wpa_supplicant: https://web.archive.org/web/20210114180304/https://processors.wiki.ti.com/index.php/OMAP_Wireless_Connectivity_NLCP_WiFi_Direct_Configuration_Scripts
When I run iw list I see that the "Supported interface modes:" allows P2P_client and P2P_GO. My wpa_supplicant.conf contains:
ctrl_interface=/var/run/wpa_supplicant
update_config=1
ap_scan=1
device_name=My-pc
device_type=1-0050F204-1
driver_param=use_p2p_group_interface=1
p2p_go_intent=15
p2p_go_ht40=1
The app is very similar to this example (it's from a book) https://github.com/retomeier/Wrox-ProfessionalAndroid-4E/blob/9741a8b62005d49519b1decfea21e7213fdd94a3/Snippets_ch18/app/src/main/java/com/professionalandroid/apps/myapplication/WiFiDirectActivity.java
It works as expected. When I try it with two Android devices, they can see each other and connect (it appear the Wifi-Direct icon).
Now I am trying to connect Android and Linux, but I guess I don't really understand how wpa_supplicant works. I also saw this question that is very similar to what I asked, but it doesn't really answer my doubts... Direct Wifi Communication between android smartphone and other devices
My problem is that I can't understand how to do the handshake between the two devices and how to set up the network.
Wpa_supplicant is my problem. I run:
sudo wpa_supplicant -wlan0 -Dnl80211 -c/etc/wpa_supplicant.conf
sudo wpa_cli
But I had a lot of problems:
so I went into /usr/share/dbus-1/system-services and moved away the two files
fi.epitest.hostap.WPASupplicant.service
fi.w1.wpa_supplicant1.service
Now I can
sudo killall wpa_supplicant
and it really dies, disconnecting me from Wifi without reconnecting the following second. Now I can launch wpa_supplicant and the three problems are resolved.
I go into wpa_cli, launch "p2p_find" and at the same time, I enable the search from within the app.
Android and Linux can now see each other.
P2P-DEVICE-FOUND 00:11:22:44:88:ff p2p_dev_addr=00:11:22:44:88:ff
pri_dev_type=10-0050F204-5 name='GT-I9300' config_methods=0x188
dev_capab=0x24 group_capab=0x0 vendor_elems=1 new=0
With "p2p_peers" I can see the cellphone MAC.
> aa:bb:cc:dd:ee:ff
Here I can't go ahead. I tried various possibilities, but none of them worked. My objective is to have Linux as Group Owner.
Seeing that I couldn't connect Android/Linux, I tried to do some practice with Linux/Linux (Linux Mint as GO, Ubuntu as Client), following examples from internet like the ones in the first link. I have a number of problems even here.
In Mint I try
p2p_connect MAC_UBUNTU pin auth
in Ubuntu I try
p2p_connect MAC_MINT PIN_GENERATED_BY_MINT
When I write the psp_connect in Mint, it creates a new interface p2p_wlan0 _0, and it returns
P2P-DEVICE-LOST p2p_dev_addr=MAC_UBUNTU
then the p2p_connect launched from Ubuntu fails.
Question 2.1 Why it switches interface when creating the group?
Question 2.2 What is the correct way to handle this change? After the change I can't p2p_find Ubuntu anymore (I have to wait some time or restart everything)
Question 2.3 Should Ubuntu change it's interface?
Question 2.3 In the new interface I should set the IP for both Ubuntu and Mint... how should I do this with static IPs?
Question 2.4 If I want to set up for example a DHCP server and client?
Question 1.4 And with Android(client) / Linux(GO)?
I worked a lot on this problem and here is the answers that I found:
I wanted Linux as a GO and Android as a client, so what worked for me in Linux is:
// Kill current supplicant and avoid its automatic recreation
system("mv /usr/share/dbus-1/system-services/fi.* .");
system("killall udhcpd");
system("wpa_cli -i wlan0 terminate -B");
usleep(300000);
// Start new supplicant
system("wpa_supplicant -Dnl80211 -iwlan0 -c /etc/p2p_supplicant.conf -B");
system("wpa_cli -iwlan0 p2p_group_add");
system("ifconfig p2p-wlan0-0 192.168.1.2");
// Connect with a peer
for (;;) {
system("wpa_cli -ip2p-wlan0-0 wps_pbc");
system("udhcpd /etc/udhcpd.conf");
// Here start your TCP server on a port
Server server([port]);
server.startServer();
}
N.B. To destroy P2P connection and restart the normal one I use this script:
#!/bin/bash
wpa_cli -i wlan0 terminate -B
wpa_cli -i p2p-wlan0-0 terminate -B
cp ./fi.* /usr/share/dbus-1/system-services/
service network-manager restart
Here the server listens for a connection and the android client connects to it. I used a very easy TCP server found on the first website and it worked like a charm. It's important to start the udhcpd or you won't get the "connected" icon in Android. For the Android side, I followed what I saw on http://developer.android.com/training/connect-devices-wirelessly/wifi-direct.html and it worked perfectly.
Answer 1.2 From wpa_cli you can get a lot of different warnings and errors. I saw that simply calling the function (like I did in the previous snippet) made everything work despite the warnings. I ignored them.
Answer 1.3 The connection using PIN works, when I tried it I wasn't starting the udhcpd and that crashed my connection every time. It was not due to PIN or PBC.
Answer 2.1 Both the server and the client are switching interface. It is a very similar behaviour to what you usually do with sockets. You create a listening socket, somebody connects, you create a new socket to handle that client in a separate thread while the listening socket is still there, waiting for other users. You do the same with interfaces. Starting a wpa_cli that monitors the wlan0 interface and one that monitors the p2p-wlan0-0 interface gives a good idea of what is happening during the change.
Answer 2.2 The client "went" to the other interface and is now ready to receive an IP. Start the DHCP and TCP servers!
Answer 2.3 Don't use static IP. Only only for the server is ok, the client should use a DHCP IP. Maybe there is a way to handle static IPs, but it was not useful for my objectives.
Answer 2.4 Done. That was the problem all along
Answer 1.4 This works perfectly even with Android/linux.
Sorry if I made some mistake in my answer, I still don't get the whole picture of WiFi-Direct connections, I simply hope that this can help someone else.