mirror of
https://github.com/Maschell/HIDtoVPADNetworkClient.git
synced 2024-11-25 15:26:53 +01:00
Updated the TCP Handshake to also negotiate a protocol version. +Formatting etc.
This commit is contained in:
parent
857c5d397d
commit
8197db4d86
@ -41,8 +41,6 @@ import lombok.Getter;
|
|||||||
import net.ash.HIDToVPADNetworkClient.manager.ControllerManager;
|
import net.ash.HIDToVPADNetworkClient.manager.ControllerManager;
|
||||||
import net.ash.HIDToVPADNetworkClient.network.NetworkManager;
|
import net.ash.HIDToVPADNetworkClient.network.NetworkManager;
|
||||||
import net.ash.HIDToVPADNetworkClient.util.Settings;
|
import net.ash.HIDToVPADNetworkClient.util.Settings;
|
||||||
import java.awt.BorderLayout;
|
|
||||||
import java.awt.CardLayout;
|
|
||||||
|
|
||||||
public final class GuiInputControls extends JPanel {
|
public final class GuiInputControls extends JPanel {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -133,7 +131,6 @@ public final class GuiInputControls extends JPanel {
|
|||||||
add(autoActivateWrap);
|
add(autoActivateWrap);
|
||||||
add(Box.createVerticalGlue());
|
add(Box.createVerticalGlue());
|
||||||
|
|
||||||
|
|
||||||
add(Box.createVerticalGlue());
|
add(Box.createVerticalGlue());
|
||||||
|
|
||||||
connectButton.addActionListener(new ActionListener() {
|
connectButton.addActionListener(new ActionListener() {
|
||||||
|
@ -25,6 +25,7 @@ package net.ash.HIDToVPADNetworkClient.hid;
|
|||||||
public interface HidDevice {
|
public interface HidDevice {
|
||||||
/**
|
/**
|
||||||
* Opens the HidDevice for usage.
|
* Opens the HidDevice for usage.
|
||||||
|
*
|
||||||
* @return true on success, false when it failed.
|
* @return true on success, false when it failed.
|
||||||
*/
|
*/
|
||||||
boolean open();
|
boolean open();
|
||||||
@ -36,31 +37,35 @@ public interface HidDevice {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the VendorID of the HidDevice
|
* Returns the VendorID of the HidDevice
|
||||||
|
*
|
||||||
* @return vendorID
|
* @return vendorID
|
||||||
*/
|
*/
|
||||||
short getVendorId();
|
short getVendorId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the ProductID of the HidDevice
|
* Returns the ProductID of the HidDevice
|
||||||
|
*
|
||||||
* @return productID
|
* @return productID
|
||||||
*/
|
*/
|
||||||
short getProductId();
|
short getProductId();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the latest data.
|
* Returns the latest data.
|
||||||
|
*
|
||||||
* @return An byte array containing the latest data. If no data is present, it'll return a empty byte array
|
* @return An byte array containing the latest data. If no data is present, it'll return a empty byte array
|
||||||
*/
|
*/
|
||||||
byte[] getLatestData();
|
byte[] getLatestData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retuns the Usage of this HID-Device
|
* Retuns the Usage of this HID-Device
|
||||||
|
*
|
||||||
* @return usage
|
* @return usage
|
||||||
*/
|
*/
|
||||||
short getUsage();
|
short getUsage();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the path of this HidDevice
|
* Returns the path of this HidDevice
|
||||||
|
*
|
||||||
* @return path
|
* @return path
|
||||||
*/
|
*/
|
||||||
String getPath();
|
String getPath();
|
||||||
|
@ -43,6 +43,7 @@ public class HidManager {
|
|||||||
|
|
||||||
for (HidDevice info : backend.enumerateDevices()) {
|
for (HidDevice info : backend.enumerateDevices()) {
|
||||||
if (isGamepad(info)) {
|
if (isGamepad(info)) {
|
||||||
|
|
||||||
// Skip Xbox controller under windows. We should use XInput instead.
|
// Skip Xbox controller under windows. We should use XInput instead.
|
||||||
if (isXboxController(info) && Settings.isWindows()) {
|
if (isXboxController(info) && Settings.isWindows()) {
|
||||||
continue;
|
continue;
|
||||||
@ -61,17 +62,17 @@ public class HidManager {
|
|||||||
|
|
||||||
private static boolean isPlaystationController(HidDevice info) {
|
private static boolean isPlaystationController(HidDevice info) {
|
||||||
if (info == null) return false;
|
if (info == null) return false;
|
||||||
return (info.getVendorId() == 0x054c);
|
return (info.getVendorId() == (short) 0x054c);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isNintendoController(HidDevice info) {
|
private static boolean isNintendoController(HidDevice info) {
|
||||||
if (info == null) return false;
|
if (info == null) return false;
|
||||||
return (info.getVendorId() == 0x57e);
|
return (info.getVendorId() == (short) 0x57e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isXboxController(HidDevice info) {
|
private static boolean isXboxController(HidDevice info) {
|
||||||
if (info == null) return false;
|
if (info == null) return false;
|
||||||
return (info.getVendorId() == 0x045e) && ((info.getProductId() == 0x02ff) || (info.getProductId() == 0x02a1));
|
return (info.getVendorId() == (short) 0x045e) && ((info.getProductId() == (short) 0x02ff) || (info.getProductId() == (short) 0x02a1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -68,7 +68,7 @@ class Hid4JavaHidDevice implements HidDevice {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Hid4JavaHidDevice [myDevice=" + myDevice + ", data=" + Arrays.toString(data) + "]";
|
return "Hid4JavaHidDevice [vid= " + getVendorId() + ", pid= " + getProductId() + ", data=" + Arrays.toString(data) + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -89,4 +89,10 @@ class PureJavaHidDevice implements HidDevice, InputReportListener {
|
|||||||
public String getPath() {
|
public String getPath() {
|
||||||
return myDeviceInfo.getPath();
|
return myDeviceInfo.getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PureJavaHidDevice [vid= " + String.format("%04X", getVendorId()) + ", pid= " + String.format("%04X", getProductId()) + ", path= " + getPath()
|
||||||
|
+ ", data=" + Arrays.toString(currentData) + "]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import lombok.Synchronized;
|
|||||||
import lombok.extern.java.Log;
|
import lombok.extern.java.Log;
|
||||||
import net.ash.HIDToVPADNetworkClient.controller.Controller;
|
import net.ash.HIDToVPADNetworkClient.controller.Controller;
|
||||||
import net.ash.HIDToVPADNetworkClient.manager.ActiveControllerManager;
|
import net.ash.HIDToVPADNetworkClient.manager.ActiveControllerManager;
|
||||||
|
import net.ash.HIDToVPADNetworkClient.network.Protocol.HandshakeReturnCode;
|
||||||
import net.ash.HIDToVPADNetworkClient.util.MessageBox;
|
import net.ash.HIDToVPADNetworkClient.util.MessageBox;
|
||||||
import net.ash.HIDToVPADNetworkClient.util.MessageBoxManager;
|
import net.ash.HIDToVPADNetworkClient.util.MessageBoxManager;
|
||||||
import net.ash.HIDToVPADNetworkClient.util.Settings;
|
import net.ash.HIDToVPADNetworkClient.util.Settings;
|
||||||
@ -163,7 +164,7 @@ public final class NetworkManager implements Runnable {
|
|||||||
try {
|
try {
|
||||||
pong = tcpClient.recvByte();
|
pong = tcpClient.recvByte();
|
||||||
if (pong == Protocol.TCP_CMD_PONG) {
|
if (pong == Protocol.TCP_CMD_PONG) {
|
||||||
log.info("Ping...Pong!");
|
if (Settings.DEBUG_TCP_PING_PONG) log.info("Ping...Pong!");
|
||||||
} else {
|
} else {
|
||||||
log.info("Got no valid response to a Ping. Disconnecting.");
|
log.info("Got no valid response to a Ping. Disconnecting.");
|
||||||
disconnect();
|
disconnect();
|
||||||
@ -344,13 +345,18 @@ public final class NetworkManager implements Runnable {
|
|||||||
boolean result = false;
|
boolean result = false;
|
||||||
log.info("Trying to connect to: " + ip);
|
log.info("Trying to connect to: " + ip);
|
||||||
try {
|
try {
|
||||||
tcpClient.connect(ip);
|
HandshakeReturnCode tcpresult = tcpClient.connect(ip);
|
||||||
|
if (tcpresult == HandshakeReturnCode.GOOD_HANDSHAKE) {
|
||||||
log.info("TCP Connected!");
|
log.info("TCP Connected!");
|
||||||
udpClient = UDPClient.createUDPClient(ip);
|
udpClient = UDPClient.createUDPClient(ip);
|
||||||
if (udpClient != null) {
|
if (udpClient != null) {
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} else {
|
||||||
|
String error = "Error while connecting.";
|
||||||
|
log.info(error);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
String error = "Error while connecting: " + e.getMessage();
|
String error = "Error while connecting: " + e.getMessage();
|
||||||
log.info(error);
|
log.info(error);
|
||||||
MessageBoxManager.addMessageBox(error, MessageBox.MESSAGE_WARNING);
|
MessageBoxManager.addMessageBox(error, MessageBox.MESSAGE_WARNING);
|
||||||
|
@ -28,13 +28,22 @@ import java.nio.ByteBuffer;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import lombok.extern.java.Log;
|
import lombok.extern.java.Log;
|
||||||
|
import net.ash.HIDToVPADNetworkClient.manager.ActiveControllerManager;
|
||||||
|
import net.ash.HIDToVPADNetworkClient.util.MessageBox;
|
||||||
|
import net.ash.HIDToVPADNetworkClient.util.MessageBoxManager;
|
||||||
|
|
||||||
@Log
|
@Log
|
||||||
final class Protocol {
|
final class Protocol {
|
||||||
|
private static ProtocolVersion currentProtocol = ProtocolVersion.MY_VERSION;
|
||||||
static final int TCP_PORT = 8112;
|
static final int TCP_PORT = 8112;
|
||||||
static final int UDP_PORT = 8113;
|
static final int UDP_PORT = 8113;
|
||||||
|
|
||||||
static final byte TCP_HANDSHAKE = 0x12;
|
static final byte TCP_HANDSHAKE_VERSION_1 = 0x12;
|
||||||
|
static final byte TCP_HANDSHAKE_VERSION_2 = 0x13;
|
||||||
|
static final byte TCP_HANDSHAKE_ABORT = 0x30;
|
||||||
|
|
||||||
|
static final byte TCP_HANDSHAKE = TCP_HANDSHAKE_VERSION_2; // default version.
|
||||||
|
|
||||||
static final byte TCP_SAME_CLIENT = 0x20;
|
static final byte TCP_SAME_CLIENT = 0x20;
|
||||||
static final byte TCP_NEW_CLIENT = 0x21;
|
static final byte TCP_NEW_CLIENT = 0x21;
|
||||||
|
|
||||||
@ -96,4 +105,85 @@ final class Protocol {
|
|||||||
return bos.toByteArray();
|
return bos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static HandshakeReturnCode doHandshake(TCPClient tcpClient) throws IOException {
|
||||||
|
Protocol.currentProtocol = ProtocolVersion.MY_VERSION;
|
||||||
|
HandshakeReturnCode resultHandshake = HandshakeReturnCode.BAD_HANDSHAKE;
|
||||||
|
ProtocolVersion wiiuProtocolVersion = ProtocolVersion.getEnumByValue(tcpClient.recvByte());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handshake 1. At first the server (WiiU) sends his protocol version 2. The network clients answers with his preferred version (which needs to be
|
||||||
|
* equals or lower the version the server (WiiU) sent him) or an abort command. 3a. If the client sent a abort, close the connection and wait for
|
||||||
|
* another connection 3b. If the client sent his highest supported version, the server confirm that he is able to use this version (by sending the
|
||||||
|
* version back) or sending a abort command to disconnect.
|
||||||
|
**/
|
||||||
|
|
||||||
|
if (wiiuProtocolVersion == ProtocolVersion.UNKOWN) {
|
||||||
|
log.info("Connected to a WiiU with an unsupported protocol version. It may support an older though");
|
||||||
|
tcpClient.send(ProtocolVersion.MY_VERSION.getVersionByte());
|
||||||
|
} else if (wiiuProtocolVersion == ProtocolVersion.Version1) {
|
||||||
|
// Do nothing.
|
||||||
|
} else if (wiiuProtocolVersion == ProtocolVersion.Version2) {
|
||||||
|
// We want to do version 2!
|
||||||
|
tcpClient.send(ProtocolVersion.Version2.getVersionByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wiiuProtocolVersion == ProtocolVersion.Version1) {
|
||||||
|
Protocol.currentProtocol = ProtocolVersion.Version1;
|
||||||
|
resultHandshake = HandshakeReturnCode.GOOD_HANDSHAKE;
|
||||||
|
} else {
|
||||||
|
ProtocolVersion finalProtocolVersion = ProtocolVersion.getEnumByValue(tcpClient.recvByte());
|
||||||
|
if (finalProtocolVersion == ProtocolVersion.Abort) {
|
||||||
|
String message = "The HIDtoVPAD version is not supported. Try to use the newest version of HIDtoVPAD and this network client.";
|
||||||
|
log.info(message);
|
||||||
|
MessageBoxManager.addMessageBox(message, MessageBox.MESSAGE_ERROR);
|
||||||
|
resultHandshake = HandshakeReturnCode.BAD_HANDSHAKE;
|
||||||
|
} else if (finalProtocolVersion == ProtocolVersion.UNKOWN) {
|
||||||
|
String message = "Something stranged happend while connecting. Try to use the newest version of HIDtoVPAD and this network client.";
|
||||||
|
log.info(message);
|
||||||
|
MessageBoxManager.addMessageBox(message, MessageBox.MESSAGE_ERROR);
|
||||||
|
resultHandshake = HandshakeReturnCode.BAD_HANDSHAKE;
|
||||||
|
} else {
|
||||||
|
Protocol.currentProtocol = finalProtocolVersion;
|
||||||
|
resultHandshake = HandshakeReturnCode.GOOD_HANDSHAKE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resultHandshake == HandshakeReturnCode.GOOD_HANDSHAKE) {
|
||||||
|
ActiveControllerManager.getInstance().attachAllActiveControllers();
|
||||||
|
log.info("Handshake was successful! Using protocol version " + (currentProtocol.getVersionByte() - TCP_HANDSHAKE_VERSION_1 + 1));
|
||||||
|
return resultHandshake;
|
||||||
|
} else {
|
||||||
|
log.info("[TCP] Handshaking failed");
|
||||||
|
return resultHandshake;
|
||||||
|
}
|
||||||
|
// return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ProtocolVersion {
|
||||||
|
MY_VERSION((byte) TCP_HANDSHAKE), Version1((byte) TCP_HANDSHAKE_VERSION_1), Version2((byte) TCP_HANDSHAKE_VERSION_2), Abort(
|
||||||
|
(byte) TCP_HANDSHAKE_ABORT), UNKOWN((byte) 0x00);
|
||||||
|
private final byte versionByte;
|
||||||
|
|
||||||
|
private ProtocolVersion(byte versionByte) {
|
||||||
|
this.versionByte = versionByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProtocolVersion getEnumByValue(byte value) {
|
||||||
|
switch (value) {
|
||||||
|
case TCP_HANDSHAKE_VERSION_1:
|
||||||
|
return ProtocolVersion.Version1;
|
||||||
|
case TCP_HANDSHAKE_VERSION_2:
|
||||||
|
return ProtocolVersion.Version2;
|
||||||
|
case TCP_HANDSHAKE_ABORT:
|
||||||
|
return ProtocolVersion.Abort;
|
||||||
|
default:
|
||||||
|
return ProtocolVersion.UNKOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getVersionByte() {
|
||||||
|
return versionByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ import lombok.Getter;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.Synchronized;
|
import lombok.Synchronized;
|
||||||
import lombok.extern.java.Log;
|
import lombok.extern.java.Log;
|
||||||
import net.ash.HIDToVPADNetworkClient.manager.ActiveControllerManager;
|
|
||||||
import net.ash.HIDToVPADNetworkClient.network.Protocol.HandshakeReturnCode;
|
import net.ash.HIDToVPADNetworkClient.network.Protocol.HandshakeReturnCode;
|
||||||
import net.ash.HIDToVPADNetworkClient.util.Settings;
|
import net.ash.HIDToVPADNetworkClient.util.Settings;
|
||||||
|
|
||||||
@ -53,23 +52,18 @@ final class TCPClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized("lock")
|
@Synchronized("lock")
|
||||||
void connect(String ip) throws Exception {
|
HandshakeReturnCode connect(String ip) throws IOException {
|
||||||
sock = new Socket();
|
sock = new Socket();
|
||||||
sock.connect(new InetSocketAddress(ip, Protocol.TCP_PORT), 2000);
|
sock.connect(new InetSocketAddress(ip, Protocol.TCP_PORT), 2000);
|
||||||
in = new DataInputStream(sock.getInputStream());
|
in = new DataInputStream(sock.getInputStream());
|
||||||
out = new DataOutputStream(sock.getOutputStream());
|
out = new DataOutputStream(sock.getOutputStream());
|
||||||
|
|
||||||
HandshakeReturnCode resultHandshake = HandshakeReturnCode.GOOD_HANDSHAKE;
|
HandshakeReturnCode result = Protocol.doHandshake(this);
|
||||||
if (recvByte() != Protocol.TCP_HANDSHAKE) resultHandshake = HandshakeReturnCode.BAD_HANDSHAKE;
|
if (result == HandshakeReturnCode.GOOD_HANDSHAKE) {
|
||||||
|
|
||||||
if (resultHandshake == HandshakeReturnCode.GOOD_HANDSHAKE) {
|
|
||||||
ActiveControllerManager.getInstance().attachAllActiveControllers();
|
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
shouldRetry = 0;
|
shouldRetry = 0;
|
||||||
} else {
|
|
||||||
log.info("[TCP] Handshaking failed");
|
|
||||||
throw new Exception();
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized("lock")
|
@Synchronized("lock")
|
||||||
@ -112,6 +106,10 @@ final class TCPClient {
|
|||||||
send(ByteBuffer.allocate(4).putInt(value).array());
|
send(ByteBuffer.allocate(4).putInt(value).array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void send(byte _byte) throws IOException {
|
||||||
|
send(ByteBuffer.allocate(1).put(_byte).array());
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized("lock")
|
@Synchronized("lock")
|
||||||
byte recvByte() throws IOException {
|
byte recvByte() throws IOException {
|
||||||
return in.readByte();
|
return in.readByte();
|
||||||
|
@ -49,6 +49,7 @@ public final class Settings {
|
|||||||
public static boolean SCAN_AUTOMATICALLY_FOR_CONTROLLERS = true;
|
public static boolean SCAN_AUTOMATICALLY_FOR_CONTROLLERS = true;
|
||||||
|
|
||||||
public static boolean DEBUG_UDP_OUTPUT = false;
|
public static boolean DEBUG_UDP_OUTPUT = false;
|
||||||
|
public static boolean DEBUG_TCP_PING_PONG = false;
|
||||||
public static boolean SEND_DATA_ONLY_ON_CHANGE = false;
|
public static boolean SEND_DATA_ONLY_ON_CHANGE = false;
|
||||||
public static boolean AUTO_ACTIVATE_CONTROLLER = false;
|
public static boolean AUTO_ACTIVATE_CONTROLLER = false;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user