Skip to content

Commit c467acc

Browse files
committed
implement passthru functionality
1 parent 745dae9 commit c467acc

File tree

5 files changed

+120
-23
lines changed

5 files changed

+120
-23
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ OPTION(VANILLA_BUILD_DESKTOP "Build Qt app for Linux desktop" OFF)
2323
OPTION(VANILLA_BUILD_RPI "Build SDL2 app for Raspberry Pi" ON)
2424
OPTION(VANILLA_BUILD_TESTS "Build unit tests for Vanilla" OFF)
2525
OPTION(VANILLA_BUILD_PIPE "Build vanilla-pipe for connecting to Wii U (Linux only)" ${LINUX})
26+
OPTION(VANILLA_BUILD_PASSTHRU "Build passthru executable for monitoring gamepad/console traffic (Linux only)" OFF)
2627
OPTION(VANILLA_BUILD_VENDORED "Build Vanilla with \"vendored\" third-party libraries" ${vendored_default})
2728

2829
add_subdirectory(lib)
@@ -35,3 +36,6 @@ endif()
3536
if (VANILLA_BUILD_RPI)
3637
add_subdirectory(rpi)
3738
endif()
39+
if (VANILLA_BUILD_PASSTHRU)
40+
add_subdirectory(passthru)
41+
endif()

passthru/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
add_executable(vanilla-passthru
2+
main.c
3+
)
4+
5+
target_include_directories(vanilla-passthru PRIVATE
6+
${CMAKE_SOURCE_DIR}/lib
7+
)
8+
9+
install(TARGETS vanilla-passthru)

passthru/main.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <arpa/inet.h>
2+
#include <errno.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <sys/un.h>
6+
#include <unistd.h>
7+
8+
#include "../pipe/def.h"
9+
10+
void string_to_hex(unsigned char *output, size_t length, const char *input)
11+
{
12+
char c[3];
13+
c[2] = 0;
14+
for (size_t i = 0; i < length; i++) {
15+
memcpy(c, input + i * 2, 2);
16+
output[i] = strtol(c, 0, 16);
17+
}
18+
}
19+
20+
int main(int argc, const char **argv)
21+
{
22+
if (argc != 3) {
23+
fprintf(stderr, "Usage: %s <bssid> <psk>\n", argv[0]);
24+
return 1;
25+
}
26+
27+
// Prepare command
28+
vanilla_pipe_command_t cmd;
29+
cmd.control_code = VANILLA_PIPE_CC_PASSTHRU;
30+
string_to_hex(cmd.connection.bssid.bssid, sizeof(cmd.connection.bssid), argv[1]);
31+
string_to_hex(cmd.connection.psk.psk, sizeof(cmd.connection.psk), argv[2]);
32+
33+
// Create client socket
34+
struct sockaddr_un addr = {0};
35+
addr.sun_family = AF_UNIX;
36+
snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, VANILLA_PIPE_LOCAL_SOCKET, VANILLA_PIPE_CMD_CLIENT_PORT);
37+
unlink(addr.sun_path);
38+
39+
int ret = 1;
40+
41+
int skt = socket(AF_UNIX, SOCK_DGRAM, 0);
42+
if (skt == -1) {
43+
fprintf(stderr, "FAILED TO CREATE SOCKET: %i\n", errno);
44+
goto exit;
45+
}
46+
47+
if (bind(skt, (const struct sockaddr *) &addr, sizeof(addr)) == -1) {
48+
fprintf(stderr, "FAILED TO BIND PORT %u: %i\n", VANILLA_PIPE_CMD_CLIENT_PORT, errno);
49+
goto close_socket;
50+
}
51+
52+
// Prepare target for server/pipe
53+
snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, VANILLA_PIPE_LOCAL_SOCKET, VANILLA_PIPE_CMD_SERVER_PORT);
54+
55+
// Send code to pipe
56+
if (sendto(skt, (const char *) &cmd, sizeof(cmd.control_code) + sizeof(cmd.connection), 0, (const struct sockaddr *) &addr, sizeof(addr)) == -1) {
57+
fprintf(stderr, "Failed to write control code to socket\n");
58+
goto close_socket;
59+
}
60+
61+
ret = 0;
62+
63+
close_socket:
64+
close(skt);
65+
66+
exit:
67+
return ret;
68+
}

pipe/def.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define VANILLA_PIPE_CC_CONNECTED 0x88
1818
#define VANILLA_PIPE_CC_DISCONNECTED 0x89
1919
#define VANILLA_PIPE_CC_QUIT 0x90
20+
#define VANILLA_PIPE_CC_PASSTHRU 0x91
2021

2122
#define VANILLA_PIPE_LOCAL_SOCKET "/tmp/vanilla-pipe_%i.sock"
2223

pipe/linux/wpa.c

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ struct sync_args {
6767
int skt;
6868
sockaddr_u client;
6969
size_t client_size;
70+
sockaddr_u cmd_client;
71+
size_t cmd_client_size;
7072
};
7173

7274
struct relay_info {
@@ -223,7 +225,7 @@ void *wpa_setup_environment(void *data)
223225
interface.driver = "nl80211";
224226
interface.ifname = args->wireless_interface;
225227
interface.confname = args->wireless_config;
226-
228+
227229
struct wpa_global *wpa = wpa_supplicant_init(&params);
228230
if (!wpa) {
229231
nlprint("FAILED TO INIT WPA SUPPLICANT");
@@ -329,7 +331,7 @@ void dhcp_callback(const char *type, char **env, void *data)
329331

330332
// Send request
331333
nl_send_auto_complete(nl, msg);
332-
334+
333335
// Cleanup
334336
nlmsg_free(msg);
335337
rtnl_addr_put(ra);
@@ -359,7 +361,7 @@ int call_dhcp(const char *network_interface)
359361
nlprint("FAILED TO ALLOC NL_SOCK");
360362
goto exit;
361363
}
362-
364+
363365
int nlr = nl_connect(nl, NETLINK_ROUTE);
364366
if (nlr < 0) {
365367
nlprint("FAILED TO CONNECT NL: %i", nlr);
@@ -448,7 +450,7 @@ int open_socket(int local, in_port_t port)
448450
struct timeval tv = {0};
449451
tv.tv_usec = 250000;
450452
setsockopt(skt, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
451-
453+
452454
if (bind(skt, (const struct sockaddr *) &sa, sa_size) == -1) {
453455
nlprint("FAILED TO BIND PORT %u: %i", port, errno);
454456
close(skt);
@@ -540,7 +542,7 @@ void create_all_relays(struct sync_args *args)
540542
vid_info.local = aud_info.local = msg_info.local = cmd_info.local = hid_info.local = args->local;
541543
vid_info.client = aud_info.client = msg_info.client = cmd_info.client = hid_info.client = args->client;
542544
vid_info.client_size = aud_info.client_size = msg_info.client_size = cmd_info.client_size = hid_info.client_size = args->client_size;
543-
545+
544546
vid_info.port = PORT_VID;
545547
aud_info.port = PORT_AUD;
546548
msg_info.port = PORT_MSG;
@@ -559,7 +561,7 @@ void create_all_relays(struct sync_args *args)
559561
// Notify client that we are connected
560562
vanilla_pipe_command_t cmd;
561563
cmd.control_code = VANILLA_PIPE_CC_CONNECTED;
562-
sendto(args->skt, &cmd, sizeof(cmd.control_code), 0, (const struct sockaddr *) &args->client, args->client_size);
564+
sendto(args->skt, &cmd, sizeof(cmd.control_code), 0, (const struct sockaddr *) &args->cmd_client, args->cmd_client_size);
563565

564566
while (!is_interrupted()) {
565567
char buf[1024];
@@ -570,7 +572,7 @@ void create_all_relays(struct sync_args *args)
570572

571573
// Let client know we lost connection
572574
cmd.control_code = VANILLA_PIPE_CC_DISCONNECTED;
573-
sendto(args->skt, &cmd, sizeof(cmd.control_code), 0, (const struct sockaddr *) &args->client, args->client_size);
575+
sendto(args->skt, &cmd, sizeof(cmd.control_code), 0, (const struct sockaddr *) &args->cmd_client, args->cmd_client_size);
574576

575577
break;
576578
}
@@ -596,14 +598,14 @@ void *thread_handler(void *data)
596598
pthread_mutex_unlock(&running_mutex);
597599

598600
void *ret = args->start_routine(data);
599-
601+
600602
free(args);
601603

602604
interrupt();
603605

604606
// Locked by calling thread
605607
pthread_mutex_unlock(&action_mutex);
606-
608+
607609
return ret;
608610
}
609611

@@ -679,7 +681,7 @@ void bytes_to_str(unsigned char *data, size_t data_size, const char *separator,
679681
}
680682

681683
int create_connect_config(const char *filename, unsigned char *bssid, unsigned char *psk)
682-
{
684+
{
683685
FILE *out_file = fopen(filename, "w");
684686
if (!out_file) {
685687
nlprint("FAILED TO OPEN OUTPUT CONFIG FILE");
@@ -703,7 +705,7 @@ int create_connect_config(const char *filename, unsigned char *bssid, unsigned c
703705
" pbss=2\n"
704706
"}\n"
705707
"\n";
706-
708+
707709
char bssid_str[18];
708710
char ssid_str[17];
709711
char psk_str[65];
@@ -724,7 +726,7 @@ ssize_t send_ping_to_client(struct sync_args *args)
724726
{
725727
vanilla_pipe_command_t cmd;
726728
cmd.control_code = VANILLA_PIPE_CC_PING;
727-
return sendto(args->skt, &cmd, sizeof(cmd.control_code), 0, (const struct sockaddr *) &args->client, args->client_size);
729+
return sendto(args->skt, &cmd, sizeof(cmd.control_code), 0, (const struct sockaddr *) &args->cmd_client, args->cmd_client_size);
728730
}
729731

730732
void *sync_with_console_internal(void *data)
@@ -855,7 +857,7 @@ void *sync_with_console_internal(void *data)
855857
// Convert BSSID from string to bytes
856858
str_to_bytes(bssid, 1, cmd.connection.bssid.bssid, sizeof(cmd.connection.bssid.bssid));
857859

858-
sendto(args->skt, &cmd, sizeof(cmd.control_code) + sizeof(cmd.connection), 0, (const struct sockaddr *) &args->client, args->client_size);
860+
sendto(args->skt, &cmd, sizeof(cmd.control_code) + sizeof(cmd.connection), 0, (const struct sockaddr *) &args->cmd_client, args->cmd_client_size);
859861

860862
ret = VANILLA_SUCCESS;
861863
} else {
@@ -883,27 +885,31 @@ void *do_connect(void *data)
883885
while (!wpa_ctrl_pending(args->ctrl)) {
884886
sleep(2);
885887
nlprint("WAITING FOR CONNECTION");
886-
888+
887889
if (is_interrupted()) return THREADRESULT(VANILLA_ERR_GENERIC);
888890
}
889-
891+
890892
char buf[1024];
891893
size_t actual_buf_len = sizeof(buf);
892894
wpa_ctrl_recv(args->ctrl, buf, &actual_buf_len);
893895
if (!strstr(buf, "CTRL-EVENT-BSS-ADDED")
894896
&& !strstr(buf, "CTRL-EVENT-BSS-REMOVED")) {
895897
nlprint("CONN RECV: %.*s", actual_buf_len, buf);
896898
}
897-
899+
898900
if (memcmp(buf, "<3>CTRL-EVENT-CONNECTED", 23) == 0) {
899901
break;
900902
}
901-
903+
904+
// if (memcmp(buf, "<3>CTRL-EVENT-WPA-ASSOC-REJECT") == 0) {
905+
// TODO: Return result that informs user that their hardware is incompatible
906+
// }
907+
902908
if (is_interrupted()) return THREADRESULT(VANILLA_ERR_GENERIC);
903909
}
904-
910+
905911
nlprint("CONNECTED TO CONSOLE");
906-
912+
907913
// Use DHCP on interface
908914
int r = call_dhcp(args->wireless_interface);
909915
if (r != VANILLA_SUCCESS) {
@@ -912,7 +918,7 @@ void *do_connect(void *data)
912918
} else {
913919
nlprint("DHCP ESTABLISHED");
914920
}
915-
921+
916922
create_all_relays(args);
917923
}
918924

@@ -998,14 +1004,16 @@ void pipe_listen(int local, const char *wireless_interface, const char *log_file
9981004
goto repeat_loop;
9991005
}
10001006

1001-
if (cmd.control_code == VANILLA_PIPE_CC_SYNC || cmd.control_code == VANILLA_PIPE_CC_CONNECT) {
1007+
if (cmd.control_code == VANILLA_PIPE_CC_SYNC || cmd.control_code == VANILLA_PIPE_CC_CONNECT || cmd.control_code == VANILLA_PIPE_CC_PASSTHRU) {
10021008
if (pthread_mutex_trylock(&action_mutex) == 0) {
10031009
struct sync_args *args = malloc(sizeof(struct sync_args));
10041010
args->wireless_interface = wireless_interface;
10051011
args->local = local;
10061012
args->skt = skt;
10071013
args->client = addr;
10081014
args->client_size = addr_size;
1015+
args->cmd_client = addr;
1016+
args->cmd_client_size = addr_size;
10091017

10101018
if (cmd.control_code == VANILLA_PIPE_CC_SYNC) {
10111019
args->code = ntohs(cmd.sync.code);
@@ -1014,8 +1022,15 @@ void pipe_listen(int local, const char *wireless_interface, const char *log_file
10141022
memcpy(args->bssid, cmd.connection.bssid.bssid, sizeof(cmd.connection.bssid.bssid));
10151023
memcpy(args->psk, cmd.connection.psk.psk, sizeof(cmd.connection.psk.psk));
10161024
args->start_routine = vanilla_connect_to_console;
1025+
1026+
if (cmd.control_code == VANILLA_PIPE_CC_PASSTHRU) {
1027+
// Pass to real gamepad on the network whose IP is 192.168.1.11
1028+
args->client.in.sin_family = AF_INET;
1029+
args->client.in.sin_addr.s_addr = inet_addr("192.168.1.11");
1030+
args->client_size = sizeof(struct sockaddr_in);
1031+
}
10171032
}
1018-
1033+
10191034
// Acknowledge
10201035
cmd.control_code = VANILLA_PIPE_CC_BIND_ACK;
10211036
if (sendto(skt, &cmd, sizeof(cmd.control_code), 0, (const struct sockaddr *) &addr, addr_size) == -1) {
@@ -1065,4 +1080,4 @@ void pipe_listen(int local, const char *wireless_interface, const char *log_file
10651080
int vanilla_has_config()
10661081
{
10671082
return (access(get_wireless_connect_config_filename(), F_OK) == 0);
1068-
}
1083+
}

0 commit comments

Comments
 (0)