Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logitech Steering Wheels compatibility #309

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
# sys-con-plus-mitm

#### Adding man-in-the-middle support to the sys-con sysmodule

## Description
This sysmodule aims to add **Wireless** support for third-party controllers to the Nintendo Switch. This will be useless once sys-con sysmodule achieves the direct bluetooth support.

This sysmodule is inspired by the hid-mitm sysmodule (https://github.com/jakibaki/hid-mitm) which is now obsolete.

The **USB** support provided by the original sys-con is intended to remain untouched so that both wireless and wired controllers can work together.

## Example setup

🎮 ))) Bluetooth ((( RaspberryPI ))) WiFi ((( NintendoSwitch

# sys-con

#### A Nintendo Switch custom sysmodule for third-party controller support. No man-in-the-middle required!
Expand Down
20 changes: 20 additions & 0 deletions common/config/sys-con/config_network.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
; Config for the Dualshock 4 controller
left_stick_deadzone = 10 ; from 0 to 100
right_stick_deadzone = 10 ; from 0 to 100
left_trigger_deadzone = 0 ; from 0 to 100
right_trigger_deadzone = 0 ; from 0 to 100

color_led = 0,0,64 ; from 0 to 255

color_body = 77,77,77
color_buttons = 0,0,0

; [9.0.0+]
color_leftGrip = 33,33,33
color_rightGrip = 33,33,33

swap_dpad_and_lstick = false ; set this to true to swap the d-pad and left stick

; For information on input mapping, see "example.ini"
;KEY_CAPTURE = LSTICK_CLICK ; Remove the semicolon at the start to take effect

2 changes: 2 additions & 0 deletions common/config/sys-con/port_config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Port]
port=8080
10 changes: 10 additions & 0 deletions network_clients/linux_or_raspberry/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
SOURCES=sys-con-client.c
OUT=sys-con-client

$(OUT): $(SOURCES)
gcc -o $@ $<

.PHONY: clean

clean:
rm $(OUT)
210 changes: 210 additions & 0 deletions network_clients/linux_or_raspberry/sys-con-client.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/joystick.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>

#define BUFFER_SIZE 7

static unsigned char buffer[BUFFER_SIZE] = {0};

struct button_map
{
unsigned char index;
unsigned char position;
};

enum hat_state
{
HAT_UP,
HAT_UPRIGHT,
HAT_RIGHT,
HAT_DOWNRIGHT,
HAT_DOWN,
HAT_DOWNLEFT,
HAT_LEFT,
HAT_UPLEFT,
HAT_UNPRESSED,
};

static struct button_map buttonMaps[] =
{
{4, 5},
{4, 6},
{4, 7},
{4, 4},
{5, 0},
{5, 1},
{5, 2},
{5, 3},
{5, 4},
{5, 5},
{6, 0},
{5, 6},
{5, 7},
{4, 1},
{4, 3},
{4, 0},
{4, 2},
};

int axisToIndexMap[] =
{
0,
1,
-1,
2,
3,
};

int read_event(int fd, struct js_event *event)
{
ssize_t bytes;

bytes = read(fd, event, sizeof(*event));

if (bytes == sizeof(*event))
return 0;

/* Error, could not read full event. */
return -1;
}

int main(int argc, char *argv[])
{
char device[] = "/dev/input/js0";
int js, gd, yes = 1;
struct js_event event;
struct sockaddr_in saddr;

if(argc != 3)
{
printf("\n Usage: %s <ip of server> <js number>\n",argv[0]);
return 1;
}

device[13] = argv[2][0];

js = open(device, O_RDONLY);

if (js == -1)
perror("Could not open joystick");

gd = socket(AF_INET, SOCK_STREAM, 0);
if (gd == -1)
perror("Could not open socket");

memset(&saddr, 0, sizeof(saddr));

saddr.sin_family = AF_INET;
saddr.sin_port = htons(8080);

if (inet_pton(AF_INET, argv[1], &saddr.sin_addr) <= 0)
{
printf("\n inet_pton error occured\n");
return 1;
}

if (connect(gd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}

if (setsockopt(gd, IPPROTO_TCP, TCP_NODELAY, (void *)&yes, sizeof(yes)) < 0)
{
printf("\n Error : TCP NODELAY Failed \n");
return 1;
}

memset(buffer, 0, sizeof(buffer));

// Init axis at rest
buffer[0] = 127;
buffer[1] = 127;
buffer[2] = 127;
buffer[3] = 127;

/* This loop will exit if the controller is unplugged. */
while (read_event(js, &event) == 0)
{
switch (event.type)
{
case JS_EVENT_BUTTON:
printf("Button %u %s\n", event.number, event.value ?
"pressed" : "released");

struct button_map map = buttonMaps[event.number];
if (event.value)
{
buffer[map.index] |= 1 << map.position;
}
else
{
buffer[map.index] &= ~(1 << map.position);
}

write(gd, buffer, BUFFER_SIZE);
break;
case JS_EVENT_AXIS:
printf("Axis %zu value %6d\n", event.number, event.value);

switch (event.number)
{
case 6:
case 7:
{
int buttonNumber, buttonValue = 1;
buttonNumber = (event.number == 6 && event.value < 0) ? 15 :
(event.number == 6 && event.value > 0) ? 16 :
(event.number == 7 && event.value < 0) ? 13 :
(event.number == 7 && event.value > 0) ? 14 : -1;

if (buttonNumber == -1)
{
int i;
for (i = 0; i < 2; i++)
{
struct button_map map = buttonMaps[(event.number == 7 ? 13 : 15) + i];
buffer[map.index] &= ~(1 << map.position);
}
}
else
{
struct button_map map = buttonMaps[buttonNumber];
buffer[map.index] |= 1 << map.position;
}
}
break;

case 0:
case 1:
case 3:
case 4:
{
int index = axisToIndexMap[event.number];
buffer[index] = (unsigned char)
(((int)event.value + 32767) >> 8);
printf("Normalized value %3d\n",
(unsigned char)buffer[index]);
}
break;
}
write(gd, buffer, BUFFER_SIZE);
break;

default:
/* Ignore init events. */
printf("Weird event: %d\n", event.type);
break;
}

fflush(stdout);
}

close(js);
return 0;
}
14 changes: 13 additions & 1 deletion source/ControllerLib/ControllerHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,20 @@ bool DoesControllerSupport(ControllerType type, ControllerSupport supportType)
default:
return false;
}
case CONTROLLER_NETWORK:
switch (supportType)
{
case SUPPORTS_RUMBLE:
return true;
case SUPPORTS_BLUETOOTH:
return true;
case SUPPORTS_SIXAXIS:
return true;
default:
return false;
}
default:
return false;
}
return false;
}
}
1 change: 1 addition & 0 deletions source/ControllerLib/ControllerTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ enum ControllerType : uint8_t
CONTROLLER_XBOXONEW,
CONTROLLER_DUALSHOCK3,
CONTROLLER_DUALSHOCK4,
CONTROLLER_NETWORK,
};

enum VendorIDs : uint16_t
Expand Down
1 change: 1 addition & 0 deletions source/ControllerLib/Controllers.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
#include "Controllers/XboxOneController.h"
#include "Controllers/Dualshock3Controller.h"
#include "Controllers/Dualshock4Controller.h"
#include "Controllers/NetworkController.h"
Loading