linuxOS_D21X/source/artinchip/p2p_auto/p2p_auto.c

263 lines
6.8 KiB
C
Raw Normal View History

2025-06-05 06:33:02 +00:00
/*
* Copyright (C) 2025 ArtInChip Technology Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: zrq <ruiqi.zheng@artinchip.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "wpa_ctrl.h"
#define EVENT_BUF_SIZE 512
struct wpa_ctrl *g_wpa_ctrl = NULL;
/* Connect the wpa_supplicant control interface */
static int p2p_connect_wpa_supplicant(char *if_name)
{
char wpas_socket_path[64] = {0};
if (if_name == NULL)
return -1;
snprintf(wpas_socket_path, sizeof(wpas_socket_path), "/var/run/wpa_supplicant/%s", if_name);
g_wpa_ctrl = wpa_ctrl_open(wpas_socket_path);
if (!g_wpa_ctrl) {
perror("[P2P_AUTO]wpa_ctrl_open failed");
return -1;
}
if (wpa_ctrl_attach(g_wpa_ctrl) != 0) {
wpa_ctrl_close(g_wpa_ctrl);
perror("[P2P_AUTO]wpa_ctrl_attach failed");
return -1;
}
return 0;
}
/* Send control cmd and check the response */
static int p2p_send_command(const char *cmd, char *reply_buf, size_t *reply_len)
{
if (cmd == NULL)
return -1;
printf("[P2P_AUTO][CMD] %s\n", cmd);
int ret = wpa_ctrl_request(g_wpa_ctrl, cmd, strlen(cmd), reply_buf, reply_len, NULL);
if (ret < 0) {
fprintf(stderr, "[P2P_AUTO]Command '%s' failed\n", cmd);
return -1;
}
if (reply_buf == NULL || reply_len == NULL)
return 0;
printf("[P2P_AUTO][RESP]: %s\n", reply_buf);
reply_buf[*reply_len] = '\0';
if (strncmp(reply_buf, "OK\n", 3) != 0) {
fprintf(stderr, "[P2P_AUTO]Unexpected reply: %s", reply_buf);
return -1;
}
return 0;
}
/* Start P2P listen */
static int p2p_start_listen(int duration) {
if (duration < 0)
return -1;
char cmd[64] = {0}, reply[EVENT_BUF_SIZE] = {0};
size_t reply_len = sizeof(reply);
snprintf(cmd, sizeof(cmd), "P2P_LISTEN %d", duration);
if (p2p_send_command(cmd, reply, &reply_len) == 0) {
printf("[P2P_AUTO]P2P listening started\n");
} else {
perror("[P2P_AUTO]P2P listen fail");
return -1;
}
return 0;
}
/* connect device */
static void p2p_connect_device(const char *peer_mac) {
char cmd[128] = {0}, reply[EVENT_BUF_SIZE] = {0};
size_t reply_len = EVENT_BUF_SIZE;
snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s pbc", peer_mac);
if (p2p_send_command(cmd, reply, &reply_len) == 0) {
printf("[P2P_AUTO]Accepted invitation from %s\n", peer_mac);
}
}
/* dhcpd/dhcpc */
static void p2p_setup_network(const char *ifname, const char *role) {
char cmd[128] = {0};
if (strcmp(role, "GO") == 0) {
printf("[P2P_AUTO]Acting as Group Owner\n");
snprintf(cmd, sizeof(cmd), "ifconfig %s 192.168.49.1", ifname);
system(cmd);
// Dynamically generate dhcpd configuration files
char conf_path[64] = {0};
snprintf(conf_path, sizeof(conf_path), "/tmp/udhcpd-%s.conf", ifname);
FILE *fp = fopen(conf_path, "w");
if (!fp) {
perror("[P2P_AUTO]Failed to create DHCP config");
return;
}
fprintf(fp,
"start 192.168.49.20\n"
"end 192.168.49.254\n"
"interface %s\n"
"max_leases 86400\n"
"option subnet 255.255.255.0\n"
"option router 192.168.49.1\n"
"option dns 8.8.8.8 8.8.4.4\n",
ifname);
fclose(fp);
memset(cmd, 0, sizeof(cmd));
snprintf(cmd, sizeof(cmd), "udhcpd %s", conf_path);
system(cmd);
usleep(200000);
unlink(conf_path);
} else {
printf("[P2P_AUTO]Acting as Group Client\n");
snprintf(cmd, sizeof(cmd), "udhcpc -i %s", ifname);
system(cmd);
}
usleep(200000);
}
static int p2p_event_handle(char *payload)
{
if (payload == NULL)
return -1;
if (strstr(payload, "P2P-DEVICE-FOUND")) {
char mac[18] = {0}, name[64] = {0};
if (sscanf(payload, "P2P-DEVICE-FOUND %17s p2p_dev_addr=%*s pri_dev_type=%*s name='%63[^']",
mac, name) >= 1) {
printf("[P2P_AUTO][EVENT RES]Discovered device: MAC=%s Name=%s\n", mac, name);
}
} else if (strstr(payload, "P2P-INVITATION-RECEIVED")) {
char sa_mac[18] = {0}, go_mac[18] = {0};
if (sscanf(payload, "P2P-INVITATION-RECEIVED sa=%17s go_dev_addr=%17s", sa_mac, go_mac) == 2) {
printf("[P2P_AUTO][EVENT RES]Received invitation from: SA=%s GO=%s\n", sa_mac, go_mac);
p2p_connect_device(sa_mac);
}
} else if (strstr(payload, "P2P-GO-NEG-REQUEST")) {
char mac[18] = {0};
int dev_passwd_id, go_intent;
if (sscanf(payload, "P2P-GO-NEG-REQUEST %17s dev_passwd_id=%d go_intent=%d",
mac, &dev_passwd_id, &go_intent) >= 3) {
printf("[P2P_AUTO][EVENT RES]GO negotiation request from %s (passwd_id=%d)\n", mac, dev_passwd_id);
}
} else if (strstr(payload, "P2P-GROUP-STARTED")) {
char ifname[32] = {0}, role[4] = {0}, ssid[33] = {0};
if (sscanf(payload, "P2P-GROUP-STARTED %31s %3s ssid=\"%32[^\"]", ifname, role, ssid) >= 2) {
printf("[P2P_AUTO][EVENT RES]Group started: Interface=%s Role=%s SSID=%s\n", ifname, role, ssid);
p2p_setup_network(ifname, role);
return 1;
}
} else if (strstr(payload, "P2P-PROV-DISC-PBC-REQ")) {
char mac[18] = {0}, name[64] = {0};
if (sscanf(payload, "P2P-PROV-DISC-PBC-REQ %17s p2p_dev_addr=%*s %*s name='%63[^']",
mac, name) >= 1) {
printf("[P2P_AUTO][EVENT RES]PBC Request from %s (%s)\n", mac, name);
p2p_connect_device(mac);
}
} else if (strstr(payload, "AP-STA-CONNECTED")) {
char sta_mac[18] = {0}, p2p_dev_addr[18] = {0};
// Two formats
// 1. AP-STA-CONNECTED d2:16:b4:86:4b:ef
// 2. AP-STA-CONNECTED d2:16:b4:86:4b:ef p2p_dev_addr=d2:16:b4:86:cb:ef
if (sscanf(payload, "AP-STA-CONNECTED %17s p2p_dev_addr=%17s", sta_mac, p2p_dev_addr) >= 1) {
printf("[P2P_AUTO][EVENT RES] STA MAC: %s", sta_mac);
if (strlen(p2p_dev_addr) > 0) {
printf(" | P2P Device: %s", p2p_dev_addr);
}
printf("\n");
}
return 1;
}
return 0;
}
/* event loop */
static void p2p_event_loop() {
char event[EVENT_BUF_SIZE] = {0};
size_t event_len;
while (1) {
event_len = EVENT_BUF_SIZE - 1;
if (wpa_ctrl_pending(g_wpa_ctrl) > 0 &&
wpa_ctrl_recv(g_wpa_ctrl, event, &event_len) == 0) {
event[event_len] = '\0';
printf("[P2P_AUTO][RAW EVENT] %s\n", event);
/* Processing log priority tags */
char *payload = event;
if (*payload == '<') {
payload = strchr(payload, '>');
if (payload)
payload++;
}
if (p2p_event_handle(payload) == 1)
return;
}
usleep(200000);
}
}
int main(int argc, char *argv[]) {
if (argc < 3) {
fprintf(stderr, "usage:p2p_auto <interface name> <listen duration> \n"
"eg.p2p_auto p2p-dev-wlan0 120\n");
return -1;
}
char cmd[128] = {0};
// start the wpa_supplicant
snprintf(cmd, sizeof(cmd), "wpa_supplicant -iwlan0 -Dnl80211 -c/etc/wifi/p2p_supplicant.conf &");
system(cmd);
sleep(2);
// connect to wpa_supplicant
if(p2p_connect_wpa_supplicant(argv[1]) < 0) {
return -1;
}
// start p2p listen
if(p2p_start_listen(atoi(argv[2])) < 0) {
wpa_ctrl_detach(g_wpa_ctrl);
wpa_ctrl_close(g_wpa_ctrl);
return -1;
}
// event loop
p2p_event_loop();
wpa_ctrl_detach(g_wpa_ctrl);
wpa_ctrl_close(g_wpa_ctrl);
return 0;
}