Skip to content

Commit aa86941

Browse files
committed
apfpv device toggle
1 parent 2b2d41d commit aa86941

File tree

2 files changed

+266
-12
lines changed

2 files changed

+266
-12
lines changed

gsmenu.sh

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,12 @@ case "$@" in
599599
"get gs apfpv password")
600600
nmcli -t connection show apfpv0 --show-secrets | grep 802-11-wireless-security.psk: | cut -d : -f2
601601
;;
602+
"get gs apfpv wlx"*)
603+
grep -q autoconnect=false $(grep -l $4 /etc/NetworkManager/system-connections/apfpv*.nmconnection) && echo 0 || echo 1
604+
;;
605+
"get gs apfpv status wlx"*)
606+
nmcli -t device status | grep $5 | grep -q :connected: && echo Connected || echo Disconnected
607+
;;
602608
"set gs apfpv ssid"*)
603609
if [ "$GSMENU_VTX_DETECTED" -eq "1" ]; then
604610
$SSH 'fw_setenv wlanssid "'$5'"'
@@ -610,7 +616,10 @@ case "$@" in
610616
CONN_NAME="apfpv$INDEX"
611617
if nmcli connection show "$CONN_NAME" &>/dev/null; then
612618
nmcli connection modify "$CONN_NAME" ssid "$5"
613-
nmcli -w 15 connection up "$CONN_NAME"
619+
if [ $($0 get gs apfpv $IFACE) = 1 ]
620+
then
621+
nmcli -w 0 connection up "$CONN_NAME"
622+
fi
614623
fi
615624
INDEX=$((INDEX + 1))
616625
done
@@ -626,12 +635,35 @@ case "$@" in
626635
CONN_NAME="apfpv$INDEX"
627636
if nmcli connection show "$CONN_NAME" &>/dev/null; then
628637
nmcli connection modify "$CONN_NAME" wifi-sec.psk "$5"
629-
nmcli -w 15 connection up "$CONN_NAME"
638+
if [ $($0 get gs apfpv $IFACE) = 1 ]
639+
then
640+
nmcli -w 0 connection up "$CONN_NAME"
641+
fi
630642
fi
631643
INDEX=$((INDEX + 1))
632644
done
633645
;;
634646

647+
"set gs apfpv wlx"*)
648+
conn=$(basename -s .nmconnection $(grep -l $4 /etc/NetworkManager/system-connections/apfpv*.nmconnection))
649+
if [ $5 = "on" ]
650+
then
651+
nmcli connection modify "$conn" connection.autoconnect yes
652+
nmcli connection up "$conn"
653+
else
654+
nmcli connection modify "$conn" connection.autoconnect no
655+
nmcli connection down "$conn"
656+
fi
657+
;;
658+
"set gs apfpv reset")
659+
CONNECTIONS=$(nmcli -t c show | grep ^apfpv | cut -d : -f1)
660+
for CONN_NAME in $CONNECTIONS; do
661+
if nmcli connection show "$CONN_NAME" &>/dev/null; then
662+
nmcli connection down "$CONN_NAME"
663+
nmcli connection delete "$CONN_NAME"
664+
fi
665+
done
666+
;;
635667
"get air alink"*)
636668
get_alink_value $4
637669
;;
@@ -688,11 +720,7 @@ case "$@" in
688720
;;
689721

690722
"get gs system rx_mode")
691-
if nmcli connection show apfpv0 &>/dev/null; then
692-
nmcli -t connection show apfpv0 | grep connection.autoconnect: | grep -q yes && echo "apfpv" || echo "wfb"
693-
else
694-
echo wfb
695-
fi
723+
systemctl is-enabled --quiet wifibroadcast && echo wfb || echo apfpv
696724
;;
697725
"get gs system gs_rendering")
698726
[ "$(grep ^render /config/setup.txt | cut -d ' ' -f 3)" = "ground" ] && echo 1 || echo 0
@@ -715,27 +743,30 @@ case "$@" in
715743
systemctl disable wifibroadcast.service
716744
systemctl disable [email protected]
717745
systemctl disable alink_gs.service
746+
rmmod 8812eu
747+
rmmod 88XXau_wfb
748+
modprobe 8812eu
749+
modprobe 88XXau_wfb
718750
# list every wifi interface wlx or wlan expect wlan0
719751
WIFI_IFACES=$(ip -o link show | awk -F': ' '{print $2}' | grep '^wlx' | grep -v "^$EXCLUDE_IFACE$")
720752
INDEX=0
721753
for IFACE in $WIFI_IFACES; do
722754
nmcli device set $IFACE managed yes
723755
CONN_NAME="apfpv$INDEX"
724756
if nmcli connection show "$CONN_NAME" &>/dev/null; then
725-
nmcli connection modify "$CONN_NAME" connection.autoconnect yes
757+
nmcli connection modify "$CONN_NAME" connection.autoconnect $([ "$INDEX" -eq 0 ] && echo "yes" || echo "no")
726758
else
727759
nmcli device wifi rescan ifname "$IFACE"
728760
sleep 2
729761
nmcli connection add type wifi ifname "$IFACE" con-name "$CONN_NAME" ssid "$SSID" \
730762
wifi-sec.key-mgmt wpa-psk wifi-sec.psk "$PASSWORD" \
731-
ipv4.method auto connection.autoconnect yes
763+
ipv4.method auto connection.autoconnect $([ "$INDEX" -eq 0 ] && echo "yes" || echo "no")
732764
fi
733765
nmcli connection modify "$CONN_NAME" ipv4.route-metric $((100 * (INDEX + 1)))
734-
nmcli -w 15 connection up "$CONN_NAME"
735-
736766
INDEX=$((INDEX + 1))
737767
done
738768
ln -s /usr/local/bin/gsmenu.sh /etc/NetworkManager/dispatcher.d/
769+
nmcli -w 0 connection up apfpv0
739770
elif [ "$5" = "wfb" ]
740771
then
741772
rm /etc/NetworkManager/dispatcher.d/gsmenu.sh
@@ -749,6 +780,10 @@ case "$@" in
749780
fi
750781
INDEX=$((INDEX + 1))
751782
done
783+
rmmod 8812eu
784+
rmmod 88XXau_wfb
785+
modprobe 8812eu
786+
modprobe 88XXau_wfb
752787
systemctl start wifibroadcast.service
753788
systemctl start [email protected]
754789
systemctl start alink_gs.service

src/gsmenu/gs_apfpv.c

Lines changed: 220 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "ui.h"
66
#include "../input.h"
77
#include "helper.h"
8+
#include "executor.h"
89
#include "styles.h"
910
#include "executor.h"
1011
#include "gs_wifi.h"
@@ -13,8 +14,131 @@ extern lv_obj_t * menu;
1314
extern gsmenu_control_mode_t control_mode;
1415
extern lv_group_t * default_group;
1516

17+
extern lv_obj_t * rx_mode;
18+
19+
lv_obj_t *this_page;
1620
lv_obj_t * ap_fpv_ssid;
1721
lv_obj_t * ap_fpv_password;
22+
lv_obj_t * reset_apfpv;
23+
lv_obj_t * autoconnect_cont;
24+
25+
static int adapter_count = 0;
26+
27+
#define MAX_DEVICES 32
28+
#define MAX_NAME_LENGTH 64
29+
#define MAX_PATH_LENGTH 256
30+
31+
typedef struct {
32+
char device_name[MAX_NAME_LENGTH];
33+
char usb_port[MAX_NAME_LENGTH];
34+
} NetworkDevice;
35+
36+
int get_usb_port_udev(const char* device_name, char* usb_port, size_t port_size) {
37+
char cmd[256];
38+
snprintf(cmd, sizeof(cmd),
39+
"udevadm info -q path /sys/class/net/%s 2>/dev/null | grep -o 'usb[0-9]*/.*' | head -1",
40+
device_name);
41+
42+
char* result = run_command(cmd);
43+
if (result == NULL || strlen(result) == 0) {
44+
free(result);
45+
return -1;
46+
}
47+
48+
// Remove newline and extract relevant portion
49+
result[strcspn(result, "\n")] = '\0';
50+
51+
// Find the USB port part (typically after usbX/)
52+
char* usb_part = strstr(result, "usb");
53+
if (usb_part != NULL) {
54+
char* port_part = strchr(usb_part, '/');
55+
if (port_part != NULL) {
56+
port_part++; // Move past the slash
57+
58+
// Copy up to next slash or end of string
59+
char* next_slash = strchr(port_part, '/');
60+
if (next_slash != NULL) {
61+
size_t len = next_slash - port_part;
62+
if (len < port_size) {
63+
strncpy(usb_port, port_part, len);
64+
usb_port[len] = '\0';
65+
free(result);
66+
return 0;
67+
}
68+
} else {
69+
// No more slashes, use the remaining string
70+
if (strlen(port_part) < port_size) {
71+
strcpy(usb_port, port_part);
72+
free(result);
73+
return 0;
74+
}
75+
}
76+
}
77+
}
78+
79+
free(result);
80+
return -1;
81+
}
82+
83+
// Main function to get the list of network devices with USB ports
84+
NetworkDevice* get_wireless_devices(int* count) {
85+
NetworkDevice* devices = malloc(MAX_DEVICES * sizeof(NetworkDevice));
86+
if (devices == NULL) {
87+
*count = 0;
88+
return NULL;
89+
}
90+
91+
// Get wireless device names using ip command
92+
char* ip_output = run_command("ip -o link show | awk -F': ' '{print $2}' | grep '^wlx'");
93+
if (ip_output == NULL) {
94+
*count = 0;
95+
free(devices);
96+
return NULL;
97+
}
98+
99+
*count = 0;
100+
char* line = ip_output;
101+
char* next_line;
102+
103+
while (*count < MAX_DEVICES && (next_line = strchr(line, '\n')) != NULL) {
104+
// Extract device name
105+
size_t name_len = next_line - line;
106+
if (name_len > 0 && name_len < MAX_NAME_LENGTH) {
107+
strncpy(devices[*count].device_name, line, name_len);
108+
devices[*count].device_name[name_len] = '\0';
109+
110+
// Remove trailing whitespace
111+
devices[*count].device_name[strcspn(devices[*count].device_name, " \t\n")] = '\0';
112+
113+
// Get USB port information
114+
devices[*count].usb_port[0] = '\0';
115+
116+
// Try udev method first
117+
get_usb_port_udev(devices[*count].device_name,
118+
devices[*count].usb_port,
119+
MAX_NAME_LENGTH);
120+
121+
(*count)++;
122+
}
123+
124+
line = next_line + 1;
125+
}
126+
127+
free(ip_output);
128+
return devices;
129+
}
130+
131+
// Example usage and cleanup function
132+
void free_devices(NetworkDevice* devices) {
133+
free(devices);
134+
}
135+
136+
void focus_label(lv_event_t* e)
137+
{
138+
lv_obj_t* obj = lv_event_get_current_target(e);
139+
lv_obj_t* label = lv_event_get_user_data(e);
140+
lv_obj_scroll_to_view_recursive(label, LV_ANIM_ON);
141+
}
18142

19143
static void btn_event_cb(lv_event_t * e)
20144
{
@@ -78,18 +202,104 @@ static void kb_event_cb(lv_event_t * e)
78202
}
79203
}
80204

205+
void checkbox_event_cb(void)
206+
{
207+
generic_page_load_callback(this_page);
208+
}
209+
210+
void apfpv_page_load_callback(lv_obj_t *page) {
211+
212+
this_page = page;
213+
menu_page_data_t *menu_page_data = lv_obj_get_user_data(page);
214+
PageEntry *entries = menu_page_data->page_entries;
215+
216+
if (adapter_count == 0 ) {
217+
NetworkDevice* devices = get_wireless_devices(&adapter_count);
218+
219+
if (devices == NULL) {
220+
printf("Failed to get device list\n");
221+
}
222+
223+
printf("Found %d wireless devices:\n", adapter_count);
224+
for (int i = 0; i < adapter_count; i++) {
225+
printf("Device: %s -> USB Port: %s\n",
226+
devices[i].device_name,
227+
devices[i].usb_port[0] ? devices[i].usb_port : "Unknown");
228+
lv_group_set_default(menu_page_data->indev_group);
229+
230+
// Create dynamic strings
231+
char checkbox_label[128];
232+
char loading_text[128];
233+
char param_text[128];
234+
235+
snprintf(checkbox_label, sizeof(checkbox_label), "Device: %s USB: %s",
236+
devices[i].device_name,
237+
devices[i].usb_port[0] ? devices[i].usb_port : "Unknown");
238+
239+
snprintf(loading_text, sizeof(loading_text), "Loading device %s...",
240+
devices[i].device_name);
241+
242+
snprintf(param_text, sizeof(param_text), "status %s",
243+
devices[i].device_name);
244+
245+
lv_obj_t * adapter = create_checkbox(autoconnect_cont, LV_SYMBOL_WIFI, checkbox_label, devices[i].device_name, menu_page_data, false);
246+
thread_data_t* data = lv_obj_get_user_data(lv_obj_get_child_by_type(adapter,0,&lv_checkbox_class));
247+
data->callback_fn = checkbox_event_cb;
248+
lv_obj_t * adapter_status = create_text(autoconnect_cont, LV_SYMBOL_SETTINGS, "Status", param_text, menu_page_data, false, LV_MENU_ITEM_BUILDER_VARIANT_1);
249+
250+
lv_obj_add_event_cb(lv_obj_get_child_by_type(adapter,0,&lv_checkbox_class), focus_label, LV_EVENT_FOCUSED, adapter_status);
251+
252+
add_entry_to_menu_page(menu_page_data, loading_text, adapter, reload_checkbox_value);
253+
add_entry_to_menu_page(menu_page_data, loading_text, adapter_status, reload_label_value);
254+
255+
lv_group_set_default(default_group);
256+
}
257+
258+
free_devices(devices);
259+
260+
}
261+
262+
generic_page_load_callback(page);
263+
}
264+
265+
void gs_actions_reset_apfpv(lv_event_t * event)
266+
{
267+
lv_textarea_set_text(lv_obj_get_child_by_type(ap_fpv_ssid,0,&lv_textarea_class),"OpenIPC");
268+
lv_textarea_set_text(lv_obj_get_child_by_type(ap_fpv_password,0,&lv_textarea_class),"12345678");
269+
run_command_and_block(event,"gsmenu.sh set gs apfpv reset",NULL);
270+
lv_obj_send_event(lv_obj_get_child_by_type(rx_mode,0,&lv_dropdown_class),LV_EVENT_VALUE_CHANGED,NULL);
271+
272+
int child_count = lv_obj_get_child_count(autoconnect_cont);
273+
for (int i = child_count - 1; i >= 0; i--) {
274+
lv_obj_t *child = lv_obj_get_child(autoconnect_cont, i);
275+
int grand_child_count = lv_obj_get_child_count(child);
276+
277+
for (int j = grand_child_count - 1; j >= 0; j--) {
278+
lv_obj_t *grand_child = lv_obj_get_child(child, j);
279+
thread_data_t* user_data = lv_obj_get_user_data(grand_child);
280+
281+
if (user_data != NULL) {
282+
delete_menu_page_entry_by_obj(user_data->menu_page_data,child);
283+
}
284+
}
285+
lv_obj_del(child);
286+
}
287+
adapter_count = 0;
288+
}
289+
81290
void create_apfpv_menu(lv_obj_t * parent) {
82291

83292
menu_page_data_t *menu_page_data = malloc(sizeof(menu_page_data_t));
84293
strcpy(menu_page_data->type, "gs");
85294
strcpy(menu_page_data->page, "apfpv");
86-
menu_page_data->page_load_callback = generic_page_load_callback;
295+
menu_page_data->page_load_callback = apfpv_page_load_callback;
87296
menu_page_data->indev_group = lv_group_create();
88297
menu_page_data->entry_count = 0;
89298
menu_page_data->page_entries = NULL;
90299
lv_group_set_default(menu_page_data->indev_group);
91300
lv_obj_set_user_data(parent,menu_page_data);
92301

302+
create_text(parent, NULL, "Connection Settings", NULL, NULL, false, LV_MENU_ITEM_BUILDER_VARIANT_1);
93303
lv_obj_t * section = lv_menu_section_create(parent);
94304
lv_obj_add_style(section, &style_openipc_section, 0);
95305

@@ -99,6 +309,9 @@ void create_apfpv_menu(lv_obj_t * parent) {
99309
ap_fpv_ssid = create_textarea(cont, "", "SSID", "ssid", menu_page_data, false);
100310
ap_fpv_password = create_textarea(cont, "", "Password", "password", menu_page_data, true);
101311

312+
reset_apfpv = create_button(section, "Reset APFPV");
313+
lv_obj_add_event_cb(lv_obj_get_child_by_type(reset_apfpv,0,&lv_button_class),gs_actions_reset_apfpv,LV_EVENT_CLICKED,NULL);
314+
102315
lv_obj_t * kb = lv_keyboard_create(lv_obj_get_parent(section));
103316
lv_obj_add_flag(kb, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
104317
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
@@ -113,6 +326,12 @@ void create_apfpv_menu(lv_obj_t * parent) {
113326
lv_obj_add_event_cb(kb, kb_event_cb, LV_EVENT_ALL,kb);
114327
lv_keyboard_set_textarea(kb, NULL);
115328

329+
create_text(parent, NULL, "Autoconnect", NULL, NULL, false, LV_MENU_ITEM_BUILDER_VARIANT_1);
330+
section = lv_menu_section_create(parent);
331+
lv_obj_add_style(section, &style_openipc_section, 0);
332+
autoconnect_cont = lv_menu_cont_create(section);
333+
lv_obj_set_flex_flow(autoconnect_cont, LV_FLEX_FLOW_COLUMN);
334+
116335
add_entry_to_menu_page(menu_page_data,"Loading SSID ...", ap_fpv_ssid, reload_textarea_value );
117336
add_entry_to_menu_page(menu_page_data,"Loading Password ...", ap_fpv_password, reload_textarea_value );
118337

0 commit comments

Comments
 (0)