diff --git a/eclipse_code_convention.xml b/eclipse_code_convention.xml new file mode 100644 index 0000000..349cbaa --- /dev/null +++ b/eclipse_code_convention.xml @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/net/ash/HIDToVPADNetworkClient/Main.java b/src/net/ash/HIDToVPADNetworkClient/Main.java index 7cafc60..a2ea385 100644 --- a/src/net/ash/HIDToVPADNetworkClient/Main.java +++ b/src/net/ash/HIDToVPADNetworkClient/Main.java @@ -33,29 +33,29 @@ import net.ash.HIDToVPADNetworkClient.util.Settings; * TODO locale */ public class Main { - public static void main(String[] args){ - Settings.loadSettings(); - try { - new Thread(ActiveControllerManager.getInstance()).start(); - new Thread(NetworkManager.getInstance()).start(); - } catch (Exception e) { - e.printStackTrace(); - fatal(); - } - SwingUtilities.invokeLater(new Runnable() { - public void run() { - GuiMain.createGUI(); - } - }); - } + public static void main(String[] args) { + Settings.loadSettings(); + try { + new Thread(ActiveControllerManager.getInstance()).start(); + new Thread(NetworkManager.getInstance()).start(); + } catch (Exception e) { + e.printStackTrace(); + fatal(); + } + SwingUtilities.invokeLater(new Runnable() { + public void run() { + GuiMain.createGUI(); + } + }); + } public static void fatal() { - System.err.println("HID To VPAD Network Client encountered an irrecoverable error."); - System.err.println("Exiting..."); - System.exit(1); - } - - public static void initiateShutdown() { - System.exit(0); - } + System.err.println("HID To VPAD Network Client encountered an irrecoverable error."); + System.err.println("Exiting..."); + System.exit(1); + } + + public static void initiateShutdown() { + System.exit(0); + } } diff --git a/src/net/ash/HIDToVPADNetworkClient/controller/Controller.java b/src/net/ash/HIDToVPADNetworkClient/controller/Controller.java index 3f007c4..f9667de 100644 --- a/src/net/ash/HIDToVPADNetworkClient/controller/Controller.java +++ b/src/net/ash/HIDToVPADNetworkClient/controller/Controller.java @@ -29,41 +29,42 @@ import net.ash.HIDToVPADNetworkClient.util.Settings; import net.ash.HIDToVPADNetworkClient.util.Utilities; /** - * Main controller interface, extended by controller drivers. - *

+ * Main controller interface, extended by controller drivers.
+ *
* See {@link LinuxDevInputController} for a full implementation. + * * @author ash */ -public abstract class Controller implements Runnable{ +public abstract class Controller implements Runnable { private boolean active; @Getter private final ControllerType type; @Getter private final String identifier; private byte[] latestData = null; - + boolean shutdown = false; boolean shutdownDone = false; private Object dataLock = new Object(); private Object shutdownLock = new Object(); - + private Object rumbleLock = new Object(); private boolean rumble = false; - - public Controller(ControllerType type, String identifier) throws ControllerInitializationFailedException{ + + public Controller(ControllerType type, String identifier) throws ControllerInitializationFailedException { this.type = type; this.identifier = identifier; - if(!initController(identifier)){ + if (!initController(identifier)) { throw new ControllerInitializationFailedException(); } } - + @Override public void run() { boolean shutdownState = shutdown; - while(!shutdownState){ + while (!shutdownState) { Utilities.sleep(Settings.DETECT_CONTROLLER_INTERVAL); - while(isActive()) { - byte[] newData = pollLatestData(); - if(newData != null){ + while (isActive()) { + byte[] newData = pollLatestData(); + if (newData != null) { setLatestData(newData); } doSleepAfterPollingData(); @@ -76,82 +77,81 @@ public abstract class Controller implements Runnable{ shutdownDone = true; } } - + protected void doSleepAfterPollingData() { Utilities.sleep(Settings.SLEEP_AFER_POLLING); } @Synchronized("dataLock") private void setLatestData(byte[] newData) { - this.latestData = newData; + this.latestData = newData; } - + @Synchronized("dataLock") public byte[] getLatestData() { - if(latestData != null){ + if (latestData != null) { byte[] data = this.latestData.clone(); this.latestData = null; return data; - }else{ + } else { return null; } } public abstract byte[] pollLatestData(); - - /** - * Sets up the driver. - *
- * During this method call, a connection will be made with the controller hardware (if required). - * - * @param arg Driver-specific init argument, see {@link ControllerManager} and {@link ControllerDetector}. - * @return Whether initialization was successful. - */ - public abstract boolean initController(String identifier); - - /** - * Destroys the controller driver and ends the polling thread. - */ - public void destroyAll(){ - destroyDriver(); - endThread(); - } - - /** + /** + * Sets up the driver.
+ * During this method call, a connection will be made with the controller hardware (if required). + * + * @param arg + * Driver-specific init argument, see {@link ControllerManager} and {@link ControllerDetector}. + * @return Whether initialization was successful. + */ + public abstract boolean initController(String identifier); + + /** + * Destroys the controller driver and ends the polling thread. + */ + public void destroyAll() { + destroyDriver(); + endThread(); + } + + /** * Destroys the controller driver. */ - public abstract void destroyDriver(); - - - private void endThread() { - new Thread(new Runnable() { + public abstract void destroyDriver(); + + private void endThread() { + new Thread(new Runnable() { @Override public void run() { setActive(false); - + synchronized (shutdownLock) { shutdown = true; } - + boolean done = false; int i = 0; - while(!done){ + while (!done) { synchronized (shutdownLock) { done = shutdownDone; } Utilities.sleep(50); - if(i++ > 50) System.out.println("Thread doesn't stop!!"); + if (i++ > 50) + System.out.println("Thread doesn't stop!!"); } } }).start(); } public abstract short getVID(); - + public abstract short getPID(); - @Synchronized("shutdownLock") + @Synchronized("shutdownLock") public boolean isActive() { return active; } @@ -159,9 +159,9 @@ public abstract class Controller implements Runnable{ public void setActive(boolean active) { this.active = active; } - + @Override - public String toString(){ + public String toString() { return getType() + " " + getIdentifier(); } @@ -192,7 +192,7 @@ public abstract class Controller implements Runnable{ return false; return true; } - + @Synchronized("rumbleLock") public boolean isRumble() { return rumble; @@ -202,15 +202,15 @@ public abstract class Controller implements Runnable{ public void startRumble() { this.rumble = true; } - + @Synchronized("rumbleLock") public void stopRumble() { this.rumble = false; } public enum ControllerType { - PureJAVAHid, LINUX, XINPUT13,XINPUT14 + PureJAVAHid, LINUX, XINPUT13, XINPUT14 } - + public abstract String getInfoText(); } \ No newline at end of file diff --git a/src/net/ash/HIDToVPADNetworkClient/controller/DS4NewController.java b/src/net/ash/HIDToVPADNetworkClient/controller/DS4NewController.java index 2b3060f..3c657da 100644 --- a/src/net/ash/HIDToVPADNetworkClient/controller/DS4NewController.java +++ b/src/net/ash/HIDToVPADNetworkClient/controller/DS4NewController.java @@ -3,22 +3,22 @@ package net.ash.HIDToVPADNetworkClient.controller; import net.ash.HIDToVPADNetworkClient.exeption.ControllerInitializationFailedException; public class DS4NewController extends PureJavaHidController { - public static final short DS4_NEW_CONTROLLER_VID = 0x54C; - public static final short DS4_NEW_CONTROLLER_PID = 0x09CC; - + public static final short DS4_NEW_CONTROLLER_VID = 0x54C; + public static final short DS4_NEW_CONTROLLER_PID = 0x09CC; + public DS4NewController(String identifier) throws ControllerInitializationFailedException { super(identifier); - //truncate package to 6; + // truncate package to 6; this.PACKET_LENGTH = 6; } - + @Override public byte[] pollLatestData() { return currentData.clone(); } - + @Override - public String getInfoText(){ + public String getInfoText() { return "DS4 on " + getIdentifier(); } } diff --git a/src/net/ash/HIDToVPADNetworkClient/controller/LinuxDevInputController.java b/src/net/ash/HIDToVPADNetworkClient/controller/LinuxDevInputController.java index 3092337..5f81199 100644 --- a/src/net/ash/HIDToVPADNetworkClient/controller/LinuxDevInputController.java +++ b/src/net/ash/HIDToVPADNetworkClient/controller/LinuxDevInputController.java @@ -30,24 +30,24 @@ import lombok.Getter; import lombok.Setter; import net.ash.HIDToVPADNetworkClient.exeption.ControllerInitializationFailedException; -public class LinuxDevInputController extends Controller implements Runnable{ - public LinuxDevInputController(String identifier) throws ControllerInitializationFailedException { +public class LinuxDevInputController extends Controller implements Runnable { + public LinuxDevInputController(String identifier) throws ControllerInitializationFailedException { super(ControllerType.LINUX, identifier); } - public static final int NUM_SUPPORTED_AXIS = 10; //possibly off-by-one - public static final int CONTROLLER_DATA_SIZE = Long.BYTES + (Byte.BYTES * NUM_SUPPORTED_AXIS); - - private static final byte JS_EVENT_BUTTON = 0x01; - private static final byte JS_EVENT_INIT = (byte)0x80; - private static final byte JS_EVENT_AXIS = 0x02; - - @Getter @Setter private DataInputStream controller; - + public static final int NUM_SUPPORTED_AXIS = 10; // possibly off-by-one + public static final int CONTROLLER_DATA_SIZE = Long.BYTES + (Byte.BYTES * NUM_SUPPORTED_AXIS); + + private static final byte JS_EVENT_BUTTON = 0x01; + private static final byte JS_EVENT_INIT = (byte) 0x80; + private static final byte JS_EVENT_AXIS = 0x02; + + @Getter @Setter private DataInputStream controller; + @Getter @Setter private short VID; @Getter @Setter private short PID; - - @Override + + @Override public boolean initController(String identifier) { try { controller = new DataInputStream(new BufferedInputStream(new FileInputStream(identifier))); @@ -56,93 +56,96 @@ public class LinuxDevInputController extends Controller implements Runnable{ e.printStackTrace(); return false; } - - setVID((short)(identifier.hashCode() & 0xFFFF)); - setPID((short)((identifier.hashCode() >> Short.BYTES) & 0xFFFF)); - System.out.println("[LinuxDevInputController] " + identifier.toString() + " fakevid: " + Integer.toHexString((int)getVID() & 0xFFFF) + " fakepid: " + Integer.toHexString((int)getPID() & 0xFFFF)); - + + setVID((short) (identifier.hashCode() & 0xFFFF)); + setPID((short) ((identifier.hashCode() >> Short.BYTES) & 0xFFFF)); + System.out.println("[LinuxDevInputController] " + identifier.toString() + " fakevid: " + Integer.toHexString((int) getVID() & 0xFFFF) + " fakepid: " + + Integer.toHexString((int) getPID() & 0xFFFF)); + return true; } - - private long buttonState = 0; - private byte[] axisState = new byte[NUM_SUPPORTED_AXIS]; - - @Override - public byte[] pollLatestData() { - DataInputStream inputStream = getController(); - //Read out next event from controller - /*int time;*/ - short value; - byte type, number; - try { - /*time = */inputStream.readInt(); - value = inputStream.readShort(); - type = inputStream.readByte(); - number = inputStream.readByte(); - } catch (IOException e) { - System.err.println("[LinuxDevInputController] Couldn't read from controller!"); - e.printStackTrace(); - System.out.println("[LinuxDevInputController] Detaching..."); - setActive(false); - return null; - } - - //Treat init events as normal (clear init bit) - type &= ~JS_EVENT_INIT; - - if (type == JS_EVENT_BUTTON) { - if (number >= Long.SIZE) { - System.out.println("[LinuxDevInputController] Button number " + number + " out of range; ignoring"); - return null; - } - - if (value != 0) { - //Set bit with button number - buttonState |= (1 << number); - } else { - //Clear bit with button number - buttonState &= ~(1 << number); - } - } else if (type == JS_EVENT_AXIS) { - if (number >= NUM_SUPPORTED_AXIS) { - System.out.println("[LinuxDevInputController] Axis number " + number + " out of range; ignoring"); - return null; - } - //Do byteswap - value = (short)(((value & 0xFF) << Byte.SIZE) | ((value & 0xFF00) >> Byte.SIZE)); - //Convert to unsigned byte and store - axisState[number] = (byte)(((value + Short.MAX_VALUE + 1) >> 8) & 0xFF); - } - - byte[] newData = new byte[CONTROLLER_DATA_SIZE]; - //Copy in button states - for (int i = 0; i < Long.BYTES; i++) { - newData[i] = (byte)((buttonState >> (i * Byte.SIZE)) & 0xFF); - } - //Copy in axis data - for (int i = Long.BYTES; i < CONTROLLER_DATA_SIZE; i++) { - newData[i] = axisState[i - Long.BYTES]; - } - return newData; - } - - @Override - protected void doSleepAfterPollingData() { - //This is event driven (aka pollLatestData() is blocking anyway until we have data), we don't need to sleep it all. + + private long buttonState = 0; + private byte[] axisState = new byte[NUM_SUPPORTED_AXIS]; + + @Override + public byte[] pollLatestData() { + DataInputStream inputStream = getController(); + // Read out next event from controller + /* int time; */ + short value; + byte type, number; + try { + /* time = */inputStream.readInt(); + value = inputStream.readShort(); + type = inputStream.readByte(); + number = inputStream.readByte(); + } catch (IOException e) { + System.err.println("[LinuxDevInputController] Couldn't read from controller!"); + e.printStackTrace(); + System.out.println("[LinuxDevInputController] Detaching..."); + setActive(false); + return null; + } + + // Treat init events as normal (clear init bit) + type &= ~JS_EVENT_INIT; + + if (type == JS_EVENT_BUTTON) { + if (number >= Long.SIZE) { + System.out.println("[LinuxDevInputController] Button number " + number + " out of range; ignoring"); + return null; + } + + if (value != 0) { + // Set bit with button number + buttonState |= (1 << number); + } else { + // Clear bit with button number + buttonState &= ~(1 << number); + } + } else if (type == JS_EVENT_AXIS) { + if (number >= NUM_SUPPORTED_AXIS) { + System.out.println("[LinuxDevInputController] Axis number " + number + " out of range; ignoring"); + return null; + } + // Do byteswap + value = (short) (((value & 0xFF) << Byte.SIZE) | ((value & 0xFF00) >> Byte.SIZE)); + // Convert to unsigned byte and store + axisState[number] = (byte) (((value + Short.MAX_VALUE + 1) >> 8) & 0xFF); + } + + byte[] newData = new byte[CONTROLLER_DATA_SIZE]; + // Copy in button states + for (int i = 0; i < Long.BYTES; i++) { + newData[i] = (byte) ((buttonState >> (i * Byte.SIZE)) & 0xFF); + } + // Copy in axis data + for (int i = Long.BYTES; i < CONTROLLER_DATA_SIZE; i++) { + newData[i] = axisState[i - Long.BYTES]; + } + return newData; } - @Override - public void destroyDriver() { - try { + @Override + protected void doSleepAfterPollingData() { + // This is event driven (aka pollLatestData() is blocking anyway until + // we have data), we don't need to sleep it all. + } + + @Override + public void destroyDriver() { + try { controller.close(); } catch (IOException e) { } - } + } - @Override - public String toString() { - return "[" + super.toString() + ";VID," + Integer.toHexString((int)getVID() & 0xFFFF) + ";PID," + Integer.toHexString((int)getPID() & 0xFFFF) + ";run," + isActive() + ((controller == null) ? ";uninitialised]" : ";initialised]"); - } + @Override + public String toString() { + return "[" + super.toString() + ";VID," + Integer.toHexString((int) getVID() & 0xFFFF) + ";PID," + Integer.toHexString((int) getPID() & 0xFFFF) + + ";run," + isActive() + ((controller == null) ? ";uninitialised]" : ";initialised]"); + } @Override public String getInfoText() { diff --git a/src/net/ash/HIDToVPADNetworkClient/controller/PureJavaHidController.java b/src/net/ash/HIDToVPADNetworkClient/controller/PureJavaHidController.java index fef68cc..4318517 100644 --- a/src/net/ash/HIDToVPADNetworkClient/controller/PureJavaHidController.java +++ b/src/net/ash/HIDToVPADNetworkClient/controller/PureJavaHidController.java @@ -36,73 +36,73 @@ import purejavahidapi.InputReportListener; public class PureJavaHidController extends Controller implements InputReportListener { public static Controller getInstance(String deviceIdentifier) throws IOException, ControllerInitializationFailedException { HidDevice device = PureJavaHidApiManager.getDeviceByPath(deviceIdentifier); - //We use a special version to optimize the data for the switch pro controller - if(device.getHidDeviceInfo().getVendorId() == SwitchProController.SWITCH_PRO_CONTROLLER_VID && - device.getHidDeviceInfo().getProductId() == SwitchProController.SWITCH_PRO_CONTROLLER_PID){ + // We use a special version to optimize the data for the switch pro + // controller + if (device.getHidDeviceInfo().getVendorId() == SwitchProController.SWITCH_PRO_CONTROLLER_VID + && device.getHidDeviceInfo().getProductId() == SwitchProController.SWITCH_PRO_CONTROLLER_PID) { return new SwitchProController(deviceIdentifier); - }else if(device.getHidDeviceInfo().getVendorId() == DS4NewController.DS4_NEW_CONTROLLER_VID && - device.getHidDeviceInfo().getProductId() == DS4NewController.DS4_NEW_CONTROLLER_PID){ + } else if (device.getHidDeviceInfo().getVendorId() == DS4NewController.DS4_NEW_CONTROLLER_VID + && device.getHidDeviceInfo().getProductId() == DS4NewController.DS4_NEW_CONTROLLER_PID) { return new DS4NewController(deviceIdentifier); - }else { + } else { return new PureJavaHidController(deviceIdentifier); } } - + public PureJavaHidController(String identifier) throws ControllerInitializationFailedException { super(ControllerType.PureJAVAHid, identifier); } - + private Object dataLock = new Object(); protected byte[] currentData = new byte[1]; protected int PACKET_LENGTH = 64; - - @Getter @Setter(AccessLevel.PRIVATE) - private HidDevice hidDevice; + + @Getter @Setter(AccessLevel.PRIVATE) private HidDevice hidDevice; @Override - public boolean initController(String identifier) { + public boolean initController(String identifier) { HidDevice device; try { device = PureJavaHidApiManager.getDeviceByPath(identifier); - + device.setInputReportListener(this); setHidDevice(device); return true; - + } catch (IOException e) { e.printStackTrace(); - } - return false; - } - - @Override - @Synchronized("dataLock") + } + return false; + } + + @Override + @Synchronized("dataLock") public byte[] pollLatestData() { return currentData.clone(); } - @Override - public void destroyDriver() { - getHidDevice().close(); - } - - @Override - public short getVID() { - return getHidDevice().getHidDeviceInfo().getVendorId(); - } - - @Override - public short getPID() { - return getHidDevice().getHidDeviceInfo().getProductId(); - } + @Override + public void destroyDriver() { + getHidDevice().close(); + } + + @Override + public short getVID() { + return getHidDevice().getHidDeviceInfo().getVendorId(); + } + + @Override + public short getPID() { + return getHidDevice().getHidDeviceInfo().getProductId(); + } @Override @Synchronized("dataLock") public void onInputReport(HidDevice source, byte reportID, byte[] reportData, int reportLength) { - if(isActive()){ + if (isActive()) { int length = PACKET_LENGTH; - if(reportLength < length){ + if (reportLength < length) { length = reportLength; } currentData = Arrays.copyOfRange(reportData, 0, length); @@ -111,15 +111,15 @@ public class PureJavaHidController extends Controller implements InputReportList @Override public String getInfoText() { - //TODO: - if(getVID() == 0x57e){ - if(getPID() == 0x2006){ + // TODO: + if (getVID() == 0x57e) { + if (getPID() == 0x2006) { return "Joy-Con (L) on " + getIdentifier(); - }else if(getPID() == 0x2007){ + } else if (getPID() == 0x2007) { return "Joy-Con (R) on " + getIdentifier(); } } - + return "USB HID on " + getIdentifier(); } } \ No newline at end of file diff --git a/src/net/ash/HIDToVPADNetworkClient/controller/SwitchProController.java b/src/net/ash/HIDToVPADNetworkClient/controller/SwitchProController.java index d8485f8..ffb138e 100644 --- a/src/net/ash/HIDToVPADNetworkClient/controller/SwitchProController.java +++ b/src/net/ash/HIDToVPADNetworkClient/controller/SwitchProController.java @@ -24,27 +24,27 @@ package net.ash.HIDToVPADNetworkClient.controller; import net.ash.HIDToVPADNetworkClient.exeption.ControllerInitializationFailedException; public class SwitchProController extends PureJavaHidController { - public static final short SWITCH_PRO_CONTROLLER_VID = 0x57e; - public static final short SWITCH_PRO_CONTROLLER_PID = 0x2009; - + public static final short SWITCH_PRO_CONTROLLER_VID = 0x57e; + public static final short SWITCH_PRO_CONTROLLER_PID = 0x2009; + public SwitchProController(String identifier) throws ControllerInitializationFailedException { super(identifier); - //truncate package to 11; + // truncate package to 11; this.PACKET_LENGTH = 11; } - + @Override public byte[] pollLatestData() { - //remove unused data (because only changed data will be sent) + // remove unused data (because only changed data will be sent) currentData[3] = 0; currentData[5] = 0; currentData[7] = 0; currentData[9] = 0; return currentData.clone(); } - + @Override - public String getInfoText(){ + public String getInfoText() { return "Switch Pro Controller on " + getIdentifier(); } } diff --git a/src/net/ash/HIDToVPADNetworkClient/controller/XInput13Controller.java b/src/net/ash/HIDToVPADNetworkClient/controller/XInput13Controller.java index 454740e..3890613 100644 --- a/src/net/ash/HIDToVPADNetworkClient/controller/XInput13Controller.java +++ b/src/net/ash/HIDToVPADNetworkClient/controller/XInput13Controller.java @@ -27,9 +27,9 @@ public class XInput13Controller extends XInputController { public XInput13Controller(String identifier) throws ControllerInitializationFailedException { super(ControllerType.XINPUT13, identifier); } - + @Override - public String getInfoText(){ + public String getInfoText() { return "XInput 1.3 on " + getIdentifier(); } } diff --git a/src/net/ash/HIDToVPADNetworkClient/controller/XInput14Controller.java b/src/net/ash/HIDToVPADNetworkClient/controller/XInput14Controller.java index 1fe49a8..5559f29 100644 --- a/src/net/ash/HIDToVPADNetworkClient/controller/XInput14Controller.java +++ b/src/net/ash/HIDToVPADNetworkClient/controller/XInput14Controller.java @@ -27,9 +27,9 @@ public class XInput14Controller extends XInputController { public XInput14Controller(String identifier) throws ControllerInitializationFailedException { super(ControllerType.XINPUT14, identifier); } - + @Override - public String getInfoText(){ + public String getInfoText() { return "XInput 1.4 on " + getIdentifier(); } } diff --git a/src/net/ash/HIDToVPADNetworkClient/controller/XInputController.java b/src/net/ash/HIDToVPADNetworkClient/controller/XInputController.java index 8b090fd..df7a661 100644 --- a/src/net/ash/HIDToVPADNetworkClient/controller/XInputController.java +++ b/src/net/ash/HIDToVPADNetworkClient/controller/XInputController.java @@ -36,15 +36,15 @@ import net.ash.HIDToVPADNetworkClient.exeption.ControllerInitializationFailedExc import net.ash.HIDToVPADNetworkClient.util.Utilities; public class XInputController extends Controller { - //the pad number will be appended to this String. + // the pad number will be appended to this String. public static final String XINPUT_INDENTIFER = "\\\\?\\XINPUT\\"; - + @Getter @Setter(AccessLevel.PRIVATE) private XInputDevice device; - + public XInputController(ControllerType type, String identifier) throws ControllerInitializationFailedException { super(type, identifier); } - + @Override public boolean initController(String identifier) { int pad = Integer.parseInt(identifier.substring(XINPUT_INDENTIFER.length())); @@ -52,82 +52,99 @@ public class XInputController extends Controller { try { device = XInputDevice.getDeviceFor(pad); } catch (XInputNotLoadedException e) { - //TODO: Log? + // TODO: Log? } - if(device == null) return false; + if (device == null) + return false; setDevice(device); return true; } @Override public byte[] pollLatestData() { - if(device.poll()){ - ByteBuffer data = ByteBuffer.allocate(8); - XInputComponents components = device.getComponents(); - - XInputButtons buttons = components.getButtons(); - - int buttonState = 0; - if(buttons.a) buttonState |= (1 << 0); - if(buttons.b) buttonState |= (1 << 1); - if(buttons.x) buttonState |= (1 << 2); - if(buttons.y) buttonState |= (1 << 3); - - if(buttons.left) buttonState |= (1 << 4); - if(buttons.up) buttonState |= (1 << 5); - if(buttons.right) buttonState |= (1 << 6); - if(buttons.down) buttonState |= (1 << 7); - - if(buttons.back) buttonState |= (1 << 8); - if(buttons.start) buttonState |= (1 << 9); - if(buttons.lShoulder) buttonState |= (1 << 10); - if(buttons.rShoulder) buttonState |= (1 << 11); - if(buttons.lThumb) buttonState |= (1 << 12); - if(buttons.rThumb) buttonState |= (1 << 13); - if(buttons.unknown) buttonState |= (1 << 14); - if (XInputDevice.isGuideButtonSupported()) { - if (buttons.guide) buttonState |= (1 << 15); - } + if (device.poll()) { + ByteBuffer data = ByteBuffer.allocate(8); + XInputComponents components = device.getComponents(); - XInputAxes axes = components.getAxes(); - int axesData = 0; - - axesData |= Utilities.signedShortToByte(axes.lxRaw) << 24; - axesData |= Utilities.signedShortToByte(axes.lyRaw) << 16; - axesData |= Utilities.signedShortToByte(axes.rxRaw) << 8; - axesData |= Utilities.signedShortToByte(axes.ryRaw) << 0; - - short axesDataShoulderButtons = 0; - - axesDataShoulderButtons |= axes.ltRaw << 8; - axesDataShoulderButtons |= axes.rtRaw << 0; - - buttonState |= axesDataShoulderButtons << 16; - data.putInt(axesData).putInt(buttonState); - - return(data.array()); - } - return null; + XInputButtons buttons = components.getButtons(); + + int buttonState = 0; + if (buttons.a) + buttonState |= (1 << 0); + if (buttons.b) + buttonState |= (1 << 1); + if (buttons.x) + buttonState |= (1 << 2); + if (buttons.y) + buttonState |= (1 << 3); + + if (buttons.left) + buttonState |= (1 << 4); + if (buttons.up) + buttonState |= (1 << 5); + if (buttons.right) + buttonState |= (1 << 6); + if (buttons.down) + buttonState |= (1 << 7); + + if (buttons.back) + buttonState |= (1 << 8); + if (buttons.start) + buttonState |= (1 << 9); + if (buttons.lShoulder) + buttonState |= (1 << 10); + if (buttons.rShoulder) + buttonState |= (1 << 11); + if (buttons.lThumb) + buttonState |= (1 << 12); + if (buttons.rThumb) + buttonState |= (1 << 13); + if (buttons.unknown) + buttonState |= (1 << 14); + if (XInputDevice.isGuideButtonSupported()) { + if (buttons.guide) + buttonState |= (1 << 15); + } + + XInputAxes axes = components.getAxes(); + int axesData = 0; + + axesData |= Utilities.signedShortToByte(axes.lxRaw) << 24; + axesData |= Utilities.signedShortToByte(axes.lyRaw) << 16; + axesData |= Utilities.signedShortToByte(axes.rxRaw) << 8; + axesData |= Utilities.signedShortToByte(axes.ryRaw) << 0; + + short axesDataShoulderButtons = 0; + + axesDataShoulderButtons |= axes.ltRaw << 8; + axesDataShoulderButtons |= axes.rtRaw << 0; + + buttonState |= axesDataShoulderButtons << 16; + data.putInt(axesData).putInt(buttonState); + + return (data.array()); + } + return null; } @Override public void destroyDriver() { - //not needed + // not needed } - //TODO: Other values for VID/PID? I guess other people had this idea too... + // TODO: Other values for VID/PID? I guess other people had this idea too... @Override - public short getVID() { + public short getVID() { return 0x7331; } @Override public short getPID() { - return 0x1337; + return 0x1337; } @Override - public String getInfoText(){ + public String getInfoText() { return "XInput on " + getIdentifier(); } } diff --git a/src/net/ash/HIDToVPADNetworkClient/gui/GuiCloseListener.java b/src/net/ash/HIDToVPADNetworkClient/gui/GuiCloseListener.java index 11b5f68..9aa0400 100644 --- a/src/net/ash/HIDToVPADNetworkClient/gui/GuiCloseListener.java +++ b/src/net/ash/HIDToVPADNetworkClient/gui/GuiCloseListener.java @@ -34,23 +34,28 @@ public class GuiCloseListener implements WindowListener { Settings.saveSettings(); Main.initiateShutdown(); } - - @Override - public void windowActivated(WindowEvent arg0) {} @Override - public void windowClosed(WindowEvent arg0) {} + public void windowActivated(WindowEvent arg0) { + } @Override - public void windowDeactivated(WindowEvent arg0) {} + public void windowClosed(WindowEvent arg0) { + } @Override - public void windowDeiconified(WindowEvent arg0) {} + public void windowDeactivated(WindowEvent arg0) { + } @Override - public void windowIconified(WindowEvent arg0) {} + public void windowDeiconified(WindowEvent arg0) { + } @Override - public void windowOpened(WindowEvent arg0) {} + public void windowIconified(WindowEvent arg0) { + } + + @Override + public void windowOpened(WindowEvent arg0) { + } } - diff --git a/src/net/ash/HIDToVPADNetworkClient/gui/GuiControllerList.java b/src/net/ash/HIDToVPADNetworkClient/gui/GuiControllerList.java index 7afea23..df33f0e 100644 --- a/src/net/ash/HIDToVPADNetworkClient/gui/GuiControllerList.java +++ b/src/net/ash/HIDToVPADNetworkClient/gui/GuiControllerList.java @@ -39,70 +39,71 @@ import net.ash.HIDToVPADNetworkClient.controller.Controller; import net.ash.HIDToVPADNetworkClient.manager.ControllerManager; public class GuiControllerList extends JPanel { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private JPanel innerScrollPanel; - - public GuiControllerList() { - super(new BorderLayout()); - - innerScrollPanel = new JPanel(); - innerScrollPanel.setLayout(new BoxLayout(innerScrollPanel, BoxLayout.PAGE_AXIS)); - add(new JScrollPane(innerScrollPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER); - - int delay = 1000; //milliseconds + private JPanel innerScrollPanel; + + public GuiControllerList() { + super(new BorderLayout()); + + innerScrollPanel = new JPanel(); + innerScrollPanel.setLayout(new BoxLayout(innerScrollPanel, BoxLayout.PAGE_AXIS)); + add(new JScrollPane(innerScrollPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER); + + int delay = 1000; // milliseconds ActionListener taskPerformer = new ActionListener() { public void actionPerformed(ActionEvent evt) { updateControllerList(); } }; new Timer(delay, taskPerformer).start(); - } - - public synchronized void updateControllerList() { - //System.out.println("[GuiControllerList] Updating controller list..."); //XXX debug text - - boolean repaintNeeded = false; - - List attachedControllers = ControllerManager.getAttachedControllers(); - - List newComponents = new ArrayList(); - - Map components = new HashMap(); + } + + public synchronized void updateControllerList() { + // System.out.println("[GuiControllerList] Updating controller + // list..."); //XXX debug text + + boolean repaintNeeded = false; + + List attachedControllers = ControllerManager.getAttachedControllers(); + + List newComponents = new ArrayList(); + + Map components = new HashMap(); for (Component component : innerScrollPanel.getComponents()) { if (component instanceof GuiControllerListItem) { GuiControllerListItem comp = (GuiControllerListItem) component; Controller cont = comp.getController(); - if(attachedControllers.contains(cont)){ - components.put(cont,comp); - }else{//Controller removed + if (attachedControllers.contains(cont)) { + components.put(cont, comp); + } else {// Controller removed repaintNeeded = true; } } } - - //Build new list of components. - for (Controller controller : attachedControllers) { - GuiControllerListItem i = null; - if (components.containsKey(controller)) { - newComponents.add(components.get(controller)); - }else{ //New controller was added - repaintNeeded = true; - i = new GuiControllerListItem(controller); - newComponents.add(i); - } - } - - if(repaintNeeded){ - innerScrollPanel.removeAll(); - for (GuiControllerListItem component : newComponents) { - innerScrollPanel.add(component); - } - - innerScrollPanel.revalidate(); - revalidate(); - innerScrollPanel.repaint(); - repaint(); - } - } + + // Build new list of components. + for (Controller controller : attachedControllers) { + GuiControllerListItem i = null; + if (components.containsKey(controller)) { + newComponents.add(components.get(controller)); + } else { // New controller was added + repaintNeeded = true; + i = new GuiControllerListItem(controller); + newComponents.add(i); + } + } + + if (repaintNeeded) { + innerScrollPanel.removeAll(); + for (GuiControllerListItem component : newComponents) { + innerScrollPanel.add(component); + } + + innerScrollPanel.revalidate(); + revalidate(); + innerScrollPanel.repaint(); + repaint(); + } + } } diff --git a/src/net/ash/HIDToVPADNetworkClient/gui/GuiControllerListItem.java b/src/net/ash/HIDToVPADNetworkClient/gui/GuiControllerListItem.java index 7b254d0..90e19d5 100644 --- a/src/net/ash/HIDToVPADNetworkClient/gui/GuiControllerListItem.java +++ b/src/net/ash/HIDToVPADNetworkClient/gui/GuiControllerListItem.java @@ -35,26 +35,26 @@ import net.ash.HIDToVPADNetworkClient.controller.Controller; import net.ash.HIDToVPADNetworkClient.network.NetworkManager; public class GuiControllerListItem extends JPanel implements ActionListener { - private static final long serialVersionUID = 1L; - - @Getter private final Controller controller; - private JCheckBox checkbox; + private static final long serialVersionUID = 1L; - public GuiControllerListItem(Controller data) { - super(new BorderLayout()); - - setMinimumSize(new Dimension (300, 30)); - setPreferredSize(new Dimension(300, 30)); - setMaximumSize(new Dimension(2000, 30)); - - this.controller = data; - - checkbox = new JCheckBox(getFlavorText()); - checkbox.setSelected(data.isActive()); - checkbox.addActionListener(this); - add(checkbox); - - int delay = 100; //milliseconds + @Getter private final Controller controller; + private JCheckBox checkbox; + + public GuiControllerListItem(Controller data) { + super(new BorderLayout()); + + setMinimumSize(new Dimension(300, 30)); + setPreferredSize(new Dimension(300, 30)); + setMaximumSize(new Dimension(2000, 30)); + + this.controller = data; + + checkbox = new JCheckBox(getFlavorText()); + checkbox.setSelected(data.isActive()); + checkbox.addActionListener(this); + add(checkbox); + + int delay = 100; // milliseconds ActionListener taskPerformer = new ActionListener() { public void actionPerformed(ActionEvent evt) { checkbox.setEnabled(NetworkManager.getInstance().isConnected()); @@ -62,17 +62,17 @@ public class GuiControllerListItem extends JPanel implements ActionListener { } }; new Timer(delay, taskPerformer).start(); - } - - private String getFlavorText() { - return controller.getInfoText(); - } + } + + private String getFlavorText() { + return controller.getInfoText(); + } @Override public void actionPerformed(ActionEvent e) { - boolean selected = ((JCheckBox) e.getSource()).isSelected(); - controller.setActive(selected); - checkbox.setSelected(controller.isActive()); + boolean selected = ((JCheckBox) e.getSource()).isSelected(); + controller.setActive(selected); + checkbox.setSelected(controller.isActive()); } @Override @@ -98,5 +98,5 @@ public class GuiControllerListItem extends JPanel implements ActionListener { } else if (!controller.equals(other.controller)) return false; return true; - } + } } diff --git a/src/net/ash/HIDToVPADNetworkClient/gui/GuiInputControls.java b/src/net/ash/HIDToVPADNetworkClient/gui/GuiInputControls.java index 143c67a..3331bf0 100644 --- a/src/net/ash/HIDToVPADNetworkClient/gui/GuiInputControls.java +++ b/src/net/ash/HIDToVPADNetworkClient/gui/GuiInputControls.java @@ -39,113 +39,112 @@ import javax.swing.Timer; import net.ash.HIDToVPADNetworkClient.network.NetworkManager; import net.ash.HIDToVPADNetworkClient.util.Settings; -public class GuiInputControls extends JPanel implements ActionListener { - private static final long serialVersionUID = 1L; - private static GuiInputControls instance = null; - +public class GuiInputControls extends JPanel implements ActionListener { + private static final long serialVersionUID = 1L; + private static GuiInputControls instance = null; + private static final String CONNECT = "Connect"; private static final String DISCONNECT = "Disconnect"; private static final String RECONNECTING = "Reconnecting"; - - private JButton connectButton; - private JTextField ipTextBox; - private JPanel ipTextBoxWrap; - private JTextField packetIntervalTextBox; - private JLabel statusLabel; - - public GuiInputControls() throws Exception { - super(); - if (instance != null) { - throw new Exception("GuiInputControls already has an instance!"); - } - instance = this; - - setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); - setPreferredSize(new Dimension(220, 150)); - - connectButton = new JButton(CONNECT); - connectButton.setAlignmentX(Component.CENTER_ALIGNMENT); - - - ipTextBox = new JTextField(); - ipTextBox.setColumns(15); - ipTextBox.setText(Settings.getIpAddr()); - ipTextBoxWrap = new JPanel(new FlowLayout()); - ipTextBoxWrap.add(new JLabel("IP: ")); - ipTextBoxWrap.add(ipTextBox); - ipTextBoxWrap.setMaximumSize(new Dimension(1000, 20)); - - statusLabel = new JLabel("Ready."); - statusLabel.setAlignmentX(Component.CENTER_ALIGNMENT); - - add(Box.createVerticalGlue()); - add(ipTextBoxWrap); - - add(Box.createRigidArea(new Dimension(1, 4))); - add(connectButton); - add(Box.createRigidArea(new Dimension(1, 8))); - - add(statusLabel); - - add(Box.createVerticalGlue()); - - connectButton.addActionListener(this); - - int delay = 100; //milliseconds + private JButton connectButton; + private JTextField ipTextBox; + private JPanel ipTextBoxWrap; + private JTextField packetIntervalTextBox; + private JLabel statusLabel; + + public GuiInputControls() throws Exception { + super(); + if (instance != null) { + throw new Exception("GuiInputControls already has an instance!"); + } + instance = this; + + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + setPreferredSize(new Dimension(220, 150)); + + connectButton = new JButton(CONNECT); + connectButton.setAlignmentX(Component.CENTER_ALIGNMENT); + + ipTextBox = new JTextField(); + ipTextBox.setColumns(15); + ipTextBox.setText(Settings.getIpAddr()); + ipTextBoxWrap = new JPanel(new FlowLayout()); + ipTextBoxWrap.add(new JLabel("IP: ")); + ipTextBoxWrap.add(ipTextBox); + ipTextBoxWrap.setMaximumSize(new Dimension(1000, 20)); + + statusLabel = new JLabel("Ready."); + statusLabel.setAlignmentX(Component.CENTER_ALIGNMENT); + + add(Box.createVerticalGlue()); + + add(ipTextBoxWrap); + + add(Box.createRigidArea(new Dimension(1, 4))); + add(connectButton); + add(Box.createRigidArea(new Dimension(1, 8))); + + add(statusLabel); + + add(Box.createVerticalGlue()); + + connectButton.addActionListener(this); + + int delay = 100; // milliseconds ActionListener taskPerformer = new ActionListener() { public void actionPerformed(ActionEvent evt) { - if(NetworkManager.getInstance().isReconnecting()){ + if (NetworkManager.getInstance().isReconnecting()) { connectButton.setText(RECONNECTING); connectButton.setEnabled(false); - }else if(NetworkManager.getInstance().isConnected()){ + } else if (NetworkManager.getInstance().isConnected()) { connectButton.setText(DISCONNECT); connectButton.setEnabled(true); - }else{ + } else { connectButton.setText(CONNECT); connectButton.setEnabled(true); } } }; new Timer(delay, taskPerformer).start(); - } + } - public static GuiInputControls instance() { - return instance; - } + public static GuiInputControls instance() { + return instance; + } - public JTextField getPacketIntervalTextBox() { - return packetIntervalTextBox; - } + public JTextField getPacketIntervalTextBox() { + return packetIntervalTextBox; + } - public JTextField getIpTextBox() { - return ipTextBox; - } + public JTextField getIpTextBox() { + return ipTextBox; + } - public JButton getConnectButton() { - return connectButton; - } + public JButton getConnectButton() { + return connectButton; + } - public JLabel getStatusLabel() { - return statusLabel; - } + public JLabel getStatusLabel() { + return statusLabel; + } @Override public void actionPerformed(ActionEvent e) { SwingUtilities.invokeLater(new Runnable() { public void run() { Settings.setIpAddr(ipTextBox.getText()); - if(NetworkManager.getInstance().isReconnecting()){ - - }else{ - if(NetworkManager.getInstance().isConnected()){ + if (NetworkManager.getInstance().isReconnecting()) { + + } else { + if (NetworkManager.getInstance().isConnected()) { NetworkManager.getInstance().disconnect(); - }else{ + } else { NetworkManager.getInstance().connect(ipTextBox.getText()); } } } }); - + } } diff --git a/src/net/ash/HIDToVPADNetworkClient/gui/GuiMain.java b/src/net/ash/HIDToVPADNetworkClient/gui/GuiMain.java index ebd08e8..8f9583e 100644 --- a/src/net/ash/HIDToVPADNetworkClient/gui/GuiMain.java +++ b/src/net/ash/HIDToVPADNetworkClient/gui/GuiMain.java @@ -31,42 +31,43 @@ import javax.swing.JPanel; import net.ash.HIDToVPADNetworkClient.Main; public class GuiMain extends JPanel { - private static final long serialVersionUID = 1L; - private static GuiMain instance; + private static final long serialVersionUID = 1L; + private static GuiMain instance; - public static void createGUI() { - JFrame frame = new JFrame("HID To VPAD Network Client"); - frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - frame.addWindowListener(new GuiCloseListener()); - - instance = new GuiMain(); - JComponent newContentPane = instance; - newContentPane.setOpaque(true); - frame.setContentPane(newContentPane); - - frame.pack(); - frame.setVisible(true); - } + public static void createGUI() { + JFrame frame = new JFrame("HID To VPAD Network Client"); + frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + frame.addWindowListener(new GuiCloseListener()); - private GuiControllerList leftControllerList; - private GuiInputControls rightSideControls; - public GuiMain() { - super(new BorderLayout()); - - leftControllerList = new GuiControllerList(); - leftControllerList.setPreferredSize(new Dimension(300, 100)); - add(leftControllerList, BorderLayout.CENTER); - - try { - rightSideControls = new GuiInputControls(); - } catch (Exception e) { - e.printStackTrace(); - Main.fatal(); - } - add(rightSideControls, BorderLayout.LINE_END); - } - - public static GuiMain instance() { - return instance; - } + instance = new GuiMain(); + JComponent newContentPane = instance; + newContentPane.setOpaque(true); + frame.setContentPane(newContentPane); + + frame.pack(); + frame.setVisible(true); + } + + private GuiControllerList leftControllerList; + private GuiInputControls rightSideControls; + + public GuiMain() { + super(new BorderLayout()); + + leftControllerList = new GuiControllerList(); + leftControllerList.setPreferredSize(new Dimension(300, 100)); + add(leftControllerList, BorderLayout.CENTER); + + try { + rightSideControls = new GuiInputControls(); + } catch (Exception e) { + e.printStackTrace(); + Main.fatal(); + } + add(rightSideControls, BorderLayout.LINE_END); + } + + public static GuiMain instance() { + return instance; + } } diff --git a/src/net/ash/HIDToVPADNetworkClient/manager/ActiveControllerManager.java b/src/net/ash/HIDToVPADNetworkClient/manager/ActiveControllerManager.java index e739cf9..c42e521 100644 --- a/src/net/ash/HIDToVPADNetworkClient/manager/ActiveControllerManager.java +++ b/src/net/ash/HIDToVPADNetworkClient/manager/ActiveControllerManager.java @@ -35,33 +35,33 @@ import net.ash.HIDToVPADNetworkClient.util.Settings; import net.ash.HIDToVPADNetworkClient.util.Utilities; @Log -public class ActiveControllerManager implements Runnable{ - private static ActiveControllerManager instance = new ActiveControllerManager(); - - private ActiveControllerManager(){ +public class ActiveControllerManager implements Runnable { + private static ActiveControllerManager instance = new ActiveControllerManager(); + + private ActiveControllerManager() { } - - public static ActiveControllerManager getInstance(){ + + public static ActiveControllerManager getInstance() { return instance; } - + @Override - public void run() { //TODO: Add mechanism to stop these threads? - new Thread(new Runnable() { + public void run() { // TODO: Add mechanism to stop these threads? + new Thread(new Runnable() { @Override public void run() { - while(true){ + while (true) { updateControllerStates(); - ControllerManager.detectControllers(); + ControllerManager.detectControllers(); Utilities.sleep(Settings.DETECT_CONTROLLER_INTERVAL); } } }).start(); - - new Thread(new Runnable() { + + new Thread(new Runnable() { @Override public void run() { - while(true){ + while (true) { handleControllerInputs(); Utilities.sleep(Settings.HANDLE_INPUTS_INTERVAL); } @@ -69,38 +69,39 @@ public class ActiveControllerManager implements Runnable{ }).start(); } - private Map activeControllers = new HashMap(); + private Map activeControllers = new HashMap(); + public void updateControllerStates() { List currentControllers = ControllerManager.getActiveControllers(); - + List toAdd = new ArrayList(); List toRemove = new ArrayList(); synchronized (activeControllers) { - //Adding all missing. - - for(Controller c: currentControllers){ - if(!activeControllers.containsKey(c)){ + // Adding all missing. + + for (Controller c : currentControllers) { + if (!activeControllers.containsKey(c)) { log.info("Added " + c); toAdd.add(c); } } - - //removing all old - for(Controller c : activeControllers.keySet()){ - if(!currentControllers.contains(c)){ + + // removing all old + for (Controller c : activeControllers.keySet()) { + if (!currentControllers.contains(c)) { log.info("Removed " + c); toRemove.add(c); } } } - + addController(toAdd); removeController(toRemove); } - + private void removeController(List toRemove) { synchronized (activeControllers) { - for(Controller c : toRemove){ + for (Controller c : toRemove) { NetworkManager.getInstance().removeHIDDevice(activeControllers.get(c)); c.destroyDriver(); activeControllers.remove(c); @@ -110,44 +111,44 @@ public class ActiveControllerManager implements Runnable{ private void addController(List toAdd) { synchronized (activeControllers) { - for(Controller c : toAdd){ + for (Controller c : toAdd) { NetworkHIDDevice hiddevice = new NetworkHIDDevice(c.getVID(), c.getPID()); hiddevice.sendAttach(); NetworkManager.getInstance().addHIDDevice(hiddevice); - activeControllers.put(c,hiddevice); + activeControllers.put(c, hiddevice); } } } - + private void handleControllerInputs() { synchronized (activeControllers) { - for(Entry entry : activeControllers.entrySet()){ + for (Entry entry : activeControllers.entrySet()) { byte[] data = entry.getKey().getLatestData(); - if(data != null){ + if (data != null) { NetworkHIDDevice device = entry.getValue(); device.sendRead(data); } } } } - + public void attachAllActiveControllers() { synchronized (activeControllers) { - for(Entry entry : activeControllers.entrySet()){ + for (Entry entry : activeControllers.entrySet()) { NetworkHIDDevice device = entry.getValue(); device.sendAttach(); } } } - + /** * * @param HIDhandle * @return returns the controller for the given handle. returns null if the controller with the given handle is not found. */ public Controller getControllerByHIDHandle(int HIDhandle) { - for(Entry entry: activeControllers.entrySet()){ - if(entry.getValue().getHidHandle() == HIDhandle){ + for (Entry entry : activeControllers.entrySet()) { + if (entry.getValue().getHidHandle() == HIDhandle) { return entry.getKey(); } } diff --git a/src/net/ash/HIDToVPADNetworkClient/manager/ControllerManager.java b/src/net/ash/HIDToVPADNetworkClient/manager/ControllerManager.java index 04bbecf..2aba3d9 100644 --- a/src/net/ash/HIDToVPADNetworkClient/manager/ControllerManager.java +++ b/src/net/ash/HIDToVPADNetworkClient/manager/ControllerManager.java @@ -47,144 +47,146 @@ import net.ash.HIDToVPADNetworkClient.util.PureJavaHidApiManager; import purejavahidapi.HidDeviceInfo; import purejavahidapi.PureJavaHidApi; -public class ControllerManager{ - private static Map attachedControllers = new HashMap(); - - /** - * Detects all attached controller. - */ - @Synchronized("attachedControllers") +public class ControllerManager { + private static Map attachedControllers = new HashMap(); + + /** + * Detects all attached controller. + */ + @Synchronized("attachedControllers") public static void detectControllers() { String os = System.getProperty("os.name"); - //System.out.println("[ControllerDetector] OS: " + os); - - Map connectedDevices = new HashMap(); - + // System.out.println("[ControllerDetector] OS: " + os); + + Map connectedDevices = new HashMap(); + if (os.contains("Linux")) { connectedDevices.putAll(detectLinuxControllers()); } else if (os.contains("Windows")) { connectedDevices.putAll(detectWindowsControllers()); } - + if (os.contains("Mac OS X")) { - connectedDevices.putAll(detectOSXHIDDevices()); - PureJavaHidApiManager.MAC_OS_X = true; + connectedDevices.putAll(detectOSXHIDDevices()); + PureJavaHidApiManager.MAC_OS_X = true; } else { - connectedDevices.putAll(detectHIDDevices()); - PureJavaHidApiManager.MAC_OS_X = false; + connectedDevices.putAll(detectHIDDevices()); + PureJavaHidApiManager.MAC_OS_X = false; } - - //Remove detached devices + + // Remove detached devices List toRemove = new ArrayList(); - for(String s : attachedControllers.keySet()){ - if(!connectedDevices.containsKey(s)){ + for (String s : attachedControllers.keySet()) { + if (!connectedDevices.containsKey(s)) { toRemove.add(s); } } - for(String remove : toRemove){ + for (String remove : toRemove) { attachedControllers.get(remove).destroyAll(); attachedControllers.remove(remove); } - - //Add attached devices! - for(Entry entry : connectedDevices.entrySet()){ + + // Add attached devices! + for (Entry entry : connectedDevices.entrySet()) { String deviceIdentifier = entry.getKey(); - if(!attachedControllers.containsKey(deviceIdentifier)){ + if (!attachedControllers.containsKey(deviceIdentifier)) { Controller c = null; - switch(entry.getValue()){ - case PureJAVAHid: - try { - c= PureJavaHidController.getInstance(deviceIdentifier); - } catch (ControllerInitializationFailedException e) { - //e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - break; - case LINUX: - try { - c = new LinuxDevInputController(deviceIdentifier); - } catch (ControllerInitializationFailedException e) { - //e.printStackTrace(); - } - break; - /* - * TODO: - * Currently the XInput will be set active automatically. - * But this should move to something for the settings? - */ - case XINPUT14: - try { - c = new XInput14Controller(deviceIdentifier); - c.setActive(true); - } catch (ControllerInitializationFailedException e) { - //e.printStackTrace(); - } - break; - case XINPUT13: - try { - c = new XInput13Controller(deviceIdentifier); - c.setActive(true); - } catch (ControllerInitializationFailedException e) { - //e.printStackTrace(); - } - break; + switch (entry.getValue()) { + case PureJAVAHid: + try { + c = PureJavaHidController.getInstance(deviceIdentifier); + } catch (ControllerInitializationFailedException e) { + // e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + break; + case LINUX: + try { + c = new LinuxDevInputController(deviceIdentifier); + } catch (ControllerInitializationFailedException e) { + // e.printStackTrace(); + } + break; + /* + * TODO: Currently the XInput will be set active automatically. But this should move to something for the settings? + */ + case XINPUT14: + try { + c = new XInput14Controller(deviceIdentifier); + c.setActive(true); + } catch (ControllerInitializationFailedException e) { + // e.printStackTrace(); + } + break; + case XINPUT13: + try { + c = new XInput13Controller(deviceIdentifier); + c.setActive(true); + } catch (ControllerInitializationFailedException e) { + // e.printStackTrace(); + } + break; default: break; - } - if(c != null){ //I don't like that starting the Thread happens here =/ + } + if (c != null) { // I don't like that starting the Thread + // happens here =/ new Thread(c).start(); - attachedControllers.put(deviceIdentifier,c); + attachedControllers.put(deviceIdentifier, c); } } } } - + @Synchronized("attachedControllers") public static List getAttachedControllers() { return new ArrayList(attachedControllers.values()); } - + private static Map detectHIDDevices() { - Map connectedDevices = new HashMap(); - - for (HidDeviceInfo info : PureJavaHidApi.enumerateDevices()) { - if(info.getUsagePage() == 0x05 || info.getUsagePage() == 0x04 || (info.getVendorId() == 0x57e) || (info.getVendorId() == 0x054c) ){ - connectedDevices.put(info.getPath(),ControllerType.PureJAVAHid); + Map connectedDevices = new HashMap(); + + for (HidDeviceInfo info : PureJavaHidApi.enumerateDevices()) { + if (info.getUsagePage() == 0x05 || info.getUsagePage() == 0x04 || (info.getVendorId() == 0x57e) || (info.getVendorId() == 0x054c)) { + connectedDevices.put(info.getPath(), ControllerType.PureJAVAHid); } } - + return connectedDevices; } - + private static Map detectOSXHIDDevices() { - Map connectedDevices = new HashMap(); - - for (HidDeviceInfo info : PureJavaHidApi.enumerateDevices()) { - if(info.getUsagePage() == 0x05 || info.getUsagePage() == 0x04 || (info.getVendorId() == 0x57e) || (info.getVendorId() == 0x054c) ){ - connectedDevices.put(info.getPath().substring(0, 13),ControllerType.PureJAVAHid); + Map connectedDevices = new HashMap(); + + for (HidDeviceInfo info : PureJavaHidApi.enumerateDevices()) { + if (info.getUsagePage() == 0x05 || info.getUsagePage() == 0x04 || (info.getVendorId() == 0x57e) || (info.getVendorId() == 0x054c)) { + connectedDevices.put(info.getPath().substring(0, 13), ControllerType.PureJAVAHid); } } - + return connectedDevices; } private static Map detectWindowsControllers() { - Map result = new HashMap(); + Map result = new HashMap(); ControllerType type = ControllerType.XINPUT13; - if(XInputDevice.isAvailable() || XInputDevice14.isAvailable()) { - if(XInputDevice14.isAvailable()){ + if (XInputDevice.isAvailable() || XInputDevice14.isAvailable()) { + if (XInputDevice14.isAvailable()) { type = ControllerType.XINPUT14; } - for(int i =0;i<4;i++){ + for (int i = 0; i < 4; i++) { XInputDevice device; try { device = XInputDevice.getDeviceFor(i); - if(device.poll() && device.isConnected()){ //Check if it is this controller is connected + if (device.poll() && device.isConnected()) { // Check if it + // is this + // controller + // is connected result.put(XInputController.XINPUT_INDENTIFER + i, type); } } catch (XInputNotLoadedException e) { - //This shouln't happen? + // This shouln't happen? e.printStackTrace(); } } @@ -194,28 +196,29 @@ public class ControllerManager{ } private static Map detectLinuxControllers() { - Map result = new HashMap(); + Map result = new HashMap(); File devInput = new File("/dev/input"); - if (!devInput.exists()) return result; - + if (!devInput.exists()) + return result; + File[] linuxControllers = devInput.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { - return name.startsWith("js"); //js0, js1, etc... + return name.startsWith("js"); // js0, js1, etc... } }); - + for (File controller : linuxControllers) { - result.put(controller.getAbsolutePath(),ControllerType.LINUX); + result.put(controller.getAbsolutePath(), ControllerType.LINUX); } - + return result; } - + @Synchronized("attachedControllers") public static List getActiveControllers() { List active = new ArrayList(); - for(Controller c : attachedControllers.values()){ - if(c.isActive()){ + for (Controller c : attachedControllers.values()) { + if (c.isActive()) { active.add(c); } } @@ -224,7 +227,7 @@ public class ControllerManager{ @Synchronized("attachedControllers") public static void deactivateAllAttachedControllers() { - for(Controller c : attachedControllers.values()){ + for (Controller c : attachedControllers.values()) { c.setActive(false); } } diff --git a/src/net/ash/HIDToVPADNetworkClient/network/NetworkHIDDevice.java b/src/net/ash/HIDToVPADNetworkClient/network/NetworkHIDDevice.java index 7a52c9b..abf9cff 100644 --- a/src/net/ash/HIDToVPADNetworkClient/network/NetworkHIDDevice.java +++ b/src/net/ash/HIDToVPADNetworkClient/network/NetworkHIDDevice.java @@ -35,66 +35,66 @@ import net.ash.HIDToVPADNetworkClient.network.commands.DetachCommand; import net.ash.HIDToVPADNetworkClient.network.commands.DeviceCommand; import net.ash.HIDToVPADNetworkClient.network.commands.ReadCommand; import net.ash.HIDToVPADNetworkClient.util.HandleFoundry; -import net.ash.HIDToVPADNetworkClient.util.Utilities; public class NetworkHIDDevice { @Getter private final short vid; @Getter private final short pid; - + @Getter @Setter private short deviceslot; @Getter @Setter private byte padslot; - + @Getter private int hidHandle = HandleFoundry.next(); @Getter(AccessLevel.PRIVATE) private List commands = new ArrayList(); - + @Getter(AccessLevel.PRIVATE) @Setter(AccessLevel.PRIVATE) private ReadCommand latestRead; - + private Object readCommandLock = new Object(); - - public NetworkHIDDevice(short vid, short pid){ + + public NetworkHIDDevice(short vid, short pid) { this.vid = vid; this.pid = pid; } - - private void addCommand(DeviceCommand command){ + + private void addCommand(DeviceCommand command) { this.commands.add(command); } - - private void clearCommands(){ + + private void clearCommands() { this.commands.clear(); } - - public void sendAttach(){ - addCommand(new AttachCommand(getHidHandle(), getVid(), getPid(),this)); + + public void sendAttach() { + addCommand(new AttachCommand(getHidHandle(), getVid(), getPid(), this)); } - - public void sendDetach(){ - addCommand(new DetachCommand(getHidHandle(),this)); + + public void sendDetach() { + addCommand(new DetachCommand(getHidHandle(), this)); } - + private byte[] lastdata = null; - public void sendRead(byte[] data){ - if(!Arrays.equals(lastdata, data)){ + + public void sendRead(byte[] data) { + if (!Arrays.equals(lastdata, data)) { synchronized (readCommandLock) { - setLatestRead(new ReadCommand(getHidHandle(),data, this)); //Only get the latest Value. + setLatestRead(new ReadCommand(getHidHandle(), data, this)); // Only get the latest Value. } lastdata = data.clone(); } } - + public Collection getCommandList() { List commands = new ArrayList(); commands.addAll(getCommands()); DeviceCommand lastRead; - + synchronized (readCommandLock) { - if((lastRead = getLatestRead()) != null){ + if ((lastRead = getLatestRead()) != null) { commands.add(lastRead); setLatestRead(null); } } - - clearCommands(); + + clearCommands(); return commands; } diff --git a/src/net/ash/HIDToVPADNetworkClient/network/NetworkManager.java b/src/net/ash/HIDToVPADNetworkClient/network/NetworkManager.java index 0b42b0b..516adf4 100644 --- a/src/net/ash/HIDToVPADNetworkClient/network/NetworkManager.java +++ b/src/net/ash/HIDToVPADNetworkClient/network/NetworkManager.java @@ -21,6 +21,7 @@ *******************************************************************************/ package net.ash.HIDToVPADNetworkClient.network; + import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -37,39 +38,40 @@ import net.ash.HIDToVPADNetworkClient.util.Settings; import net.ash.HIDToVPADNetworkClient.util.Utilities; @Log -public class NetworkManager implements Runnable{ +public class NetworkManager implements Runnable { private final TCPClient tcpClient = new TCPClient(); private UDPClient udpClient = null; - + private static NetworkManager instance = null; - + private List ownCommands = new ArrayList(); - + private NetworkManager() { - + } - - public static NetworkManager getInstance(){ - if(instance == null){ + + public static NetworkManager getInstance() { + if (instance == null) { instance = new NetworkManager(); } return instance; } - + @Getter private List devices = new ArrayList(); - - public void addHIDDevice(NetworkHIDDevice device){ - if(!getDevices().contains(device)){ + + public void addHIDDevice(NetworkHIDDevice device) { + if (!getDevices().contains(device)) { synchronized (devices) { getDevices().add(device); } } } - + /* * We want to remove them at the end of a cycle. To make sure the detach was send before removing. */ @Getter private List toRemove = new ArrayList(); + @Synchronized("toRemove") public void removeHIDDevice(NetworkHIDDevice device) { device.sendDetach(); @@ -79,10 +81,10 @@ public class NetworkManager implements Runnable{ @Override public void run() { int i = 0; - while(true){ + while (true) { proccessCommands(); Utilities.sleep(Settings.PROCESS_CMD_INTERVAL); - if(i++ > Settings.PING_INTERVAL / Settings.PROCESS_CMD_INTERVAL){ + if (i++ > Settings.PING_INTERVAL / Settings.PROCESS_CMD_INTERVAL) { ping(); i = 0; } @@ -90,82 +92,86 @@ public class NetworkManager implements Runnable{ } private void ping() { - if(isConnected() || tcpClient.isShouldRetry())sendingCommand(new PingCommand()); + if (isConnected() || tcpClient.isShouldRetry()) + sendingCommand(new PingCommand()); } - - public void proccessCommands(){ + + public void proccessCommands() { List commands = new ArrayList(); - commands.addAll(ownCommands); //TODO: Does this need a synchronized block? It _should_ be only access from this thread. Need to think about it + commands.addAll(ownCommands); // TODO: Does this need a synchronized + // block? It _should_ be only access from + // this thread. Need to think about it ownCommands.clear(); synchronized (toRemove) { synchronized (devices) { - for(NetworkHIDDevice device : getDevices()){ + for (NetworkHIDDevice device : getDevices()) { commands.addAll(device.getCommandList()); } } } - - if(commands.isEmpty())return; - - //Split up into "read commands" and other commands. + + if (commands.isEmpty()) + return; + + // Split up into "read commands" and other commands. List readCommands = new ArrayList(); - { - for(DeviceCommand command : commands){ - if(command instanceof ReadCommand){ + { + for (DeviceCommand command : commands) { + if (command instanceof ReadCommand) { readCommands.add((ReadCommand) command); } } commands.removeAll(readCommands); } - - if(!readCommands.isEmpty()){ + + if (!readCommands.isEmpty()) { sendingRead(readCommands); } - - if(!commands.isEmpty()){ - for(DeviceCommand command : commands){ + + if (!commands.isEmpty()) { + for (DeviceCommand command : commands) { sendingCommand(command); } } - + synchronized (toRemove) { synchronized (devices) { - for(NetworkHIDDevice d: toRemove){ + for (NetworkHIDDevice d : toRemove) { commands.remove(d); } } } } - + private void sendingCommand(DeviceCommand command) { boolean result = false; - if(isConnected() || tcpClient.isShouldRetry()){ - if(command instanceof AttachCommand){ + if (isConnected() || tcpClient.isShouldRetry()) { + if (command instanceof AttachCommand) { result = sendAttach((AttachCommand) command); - }else if(command instanceof DetachCommand){ + } else if (command instanceof DetachCommand) { result = sendDetach((DetachCommand) command); - }else if(command instanceof PingCommand){ + } else if (command instanceof PingCommand) { sendPing((PingCommand) command); result = true; - }else{ + } else { log.info("UNKNOWN COMMAND!"); result = true; } - }else{ + } else { Utilities.sleep(Settings.SENDING_CMD_SLEEP_IF_NOT_CONNECTED); } - - //Add the command again on errors - if(!result){ + + // Add the command again on errors + if (!result) { addCommand(command); } } - //TODO: PONG from WiiU? Hey Quark ;) + // TODO: PONG from WiiU? Hey Quark ;) private void sendPing(PingCommand command) { - if(sendTCP(Protocol.getRawPingDataToSend(command))){ + if (sendTCP(Protocol.getRawPingDataToSend(command))) { log.info("PING"); - }else{ + } else { log.info("Sending the PING failed"); } } @@ -174,65 +180,65 @@ public class NetworkManager implements Runnable{ byte[] sendData; try { sendData = Protocol.getRawDetachDataToSend(command); - if(sendTCP(sendData)){ + if (sendTCP(sendData)) { log.info("Success detach command for device (" + command.getSender() + ") sent!"); - }else{ + } else { log.info("Sending the detach command for device (" + command.getSender() + ") failed. sendTCP failed"); return false; } } catch (IOException e) { e.printStackTrace(); return false; - } + } return true; } - - //TODO: Maybe move it into the Protocol class? + + // TODO: Maybe move it into the Protocol class? private boolean sendAttach(AttachCommand command) { - //Send the TCP command + // Send the TCP command byte[] sendData = null; try { sendData = Protocol.getRawAttachDataToSend(command); - }catch (IOException e) { + } catch (IOException e) { log.info("Building the attach command for device (" + command.getSender() + ") failed." + e.getMessage()); return false; - } - if(sendTCP(sendData)){ + } + if (sendTCP(sendData)) { byte configFound = 0; try { - configFound = recvTCPByte(); + configFound = recvTCPByte(); } catch (IOException e1) { e1.printStackTrace(); } - if(configFound == Protocol.TCP_CMD_ATTACH_CONFIG_FOUND){ - //log.info("Config on the console found!"); - }else if(configFound == Protocol.TCP_CMD_ATTACH_CONFIG_NOT_FOUND){ + if (configFound == Protocol.TCP_CMD_ATTACH_CONFIG_FOUND) { + // log.info("Config on the console found!"); + } else if (configFound == Protocol.TCP_CMD_ATTACH_CONFIG_NOT_FOUND) { log.info("NO CONFIG FOUND."); return false; - }else if (configFound == 0){ + } else if (configFound == 0) { log.info("Failed to get byte."); disconnect(); return false; } - + byte userDataOkay = 0; try { - userDataOkay = recvTCPByte(); + userDataOkay = recvTCPByte(); } catch (IOException e1) { e1.printStackTrace(); } - if(userDataOkay == Protocol.TCP_CMD_ATTACH_USERDATA_OKAY){ - //log.info("userdata okay!"); - }else if(userDataOkay == Protocol.TCP_CMD_ATTACH_USERDATA_BAD){ + if (userDataOkay == Protocol.TCP_CMD_ATTACH_USERDATA_OKAY) { + // log.info("userdata okay!"); + } else if (userDataOkay == Protocol.TCP_CMD_ATTACH_USERDATA_BAD) { log.info("USERDATA BAD."); return false; - }else if (userDataOkay == 0){ + } else if (userDataOkay == 0) { log.info("Failed to get byte."); disconnect(); return false; } - - //We receive our device slot and pad slot + + // We receive our device slot and pad slot short deviceslot = -1; byte padslot = -1; try { @@ -242,45 +248,45 @@ public class NetworkManager implements Runnable{ log.info("Recieving data after sending a attach failed for device (" + command.getSender() + ") failed." + e.getMessage()); return false; } - - if(deviceslot < 0 || padslot < 0){ + + if (deviceslot < 0 || padslot < 0) { log.info("Recieving data after sending a attach failed for device (" + command.getSender() + ") failed. We need to disconnect =("); disconnect(); return false; } - - //Let's save them for later. - NetworkHIDDevice sender = command.getSender(); - if(sender != null){ + + // Let's save them for later. + NetworkHIDDevice sender = command.getSender(); + if (sender != null) { sender.setDeviceslot(deviceslot); sender.setPadslot(padslot); - }else{ + } else { log.info("Something really went wrong. Got an attach event with out an " + NetworkHIDDevice.class.getSimpleName()); return false; } log.info("Attaching done!"); return true; - }else{ + } else { log.info("Sending the attach command for device (" + command.getSender() + ") failed. sendTCP failed"); return false; } } - + private void sendingRead(List readCommands) { byte[] rawCommand; try { rawCommand = Protocol.getRawReadDataToSend(readCommands); - if(sendUDP(rawCommand) == true){ - System.out.println("UDP Packet sent: "+ Utilities.ByteArrayToString(rawCommand)); + if (sendUDP(rawCommand) == true) { + System.out.println("UDP Packet sent: " + Utilities.ByteArrayToString(rawCommand)); } } catch (IOException e) { System.out.println("Sending read data failed."); } } - + private boolean sendUDP(byte[] rawCommand) { boolean result = false; - if(udpClient != null && isConnected()){ + if (udpClient != null && isConnected()) { try { udpClient.send(rawCommand); result = true; @@ -291,10 +297,10 @@ public class NetworkManager implements Runnable{ } return result; } - + private boolean sendTCP(byte[] rawCommand) { boolean result = false; - if(tcpClient != null){ + if (tcpClient != null) { try { tcpClient.send(rawCommand); result = true; @@ -304,9 +310,9 @@ public class NetworkManager implements Runnable{ } return result; } - + public void disconnect() { - //ControllerManager.deactivateAllAttachedControllers(); + // ControllerManager.deactivateAllAttachedControllers(); tcpClient.abort(); } @@ -317,7 +323,7 @@ public class NetworkManager implements Runnable{ private byte recvTCPByte() throws IOException { return tcpClient.recvByte(); } - + public boolean isConnected() { return (tcpClient != null && tcpClient.isConnected()); } @@ -329,7 +335,7 @@ public class NetworkManager implements Runnable{ tcpClient.connect(ip); System.out.println("TCP Connected!"); udpClient = UDPClient.createUDPClient(ip); - if(udpClient != null){ + if (udpClient != null) { result = true; } } catch (Exception e) { @@ -342,7 +348,7 @@ public class NetworkManager implements Runnable{ this.ownCommands.add(command); } - public boolean isReconnecting() { + public boolean isReconnecting() { return !tcpClient.isConnected() && tcpClient.isShouldRetry(); } } diff --git a/src/net/ash/HIDToVPADNetworkClient/network/Protocol.java b/src/net/ash/HIDToVPADNetworkClient/network/Protocol.java index 7695a66..04ca75c 100644 --- a/src/net/ash/HIDToVPADNetworkClient/network/Protocol.java +++ b/src/net/ash/HIDToVPADNetworkClient/network/Protocol.java @@ -35,77 +35,67 @@ import net.ash.HIDToVPADNetworkClient.network.commands.ReadCommand; @Log public class Protocol { - public static final int TCP_PORT = 8112; - public static final int UDP_PORT = 8113; - - public static final byte TCP_HANDSHAKE = 0x12; - public static final byte TCP_SAME_CLIENT = 0x20; - public static final byte TCP_NEW_CLIENT = 0x21; - - public static final byte TCP_CMD_ATTACH = 0x01; - public static final byte TCP_CMD_DETACH = 0x02; - public static final byte TCP_CMD_PING = (byte)0xF0; - - public static final byte UDP_CMD_DATA = 0x03; - - - public static final byte TCP_CMD_ATTACH_CONFIG_FOUND = (byte) 0xE0; - public static final byte TCP_CMD_ATTACH_CONFIG_NOT_FOUND = (byte) 0xE1; - public static final byte TCP_CMD_ATTACH_USERDATA_OKAY = (byte) 0xE8; - public static final byte TCP_CMD_ATTACH_USERDATA_BAD = (byte) 0xE9; - - private Protocol(){} - - public enum HandshakeReturnCode { - BAD_HANDSHAKE, - SAME_CLIENT, - NEW_CLIENT - } - - public static byte[] getRawAttachDataToSend(AttachCommand command) throws IOException { - return ByteBuffer.allocate(9) - .put(Protocol.TCP_CMD_ATTACH) - .putInt(command.getHandle()) - .putShort(command.getVid()) - .putShort(command.getPid()) - .array(); - } - - public static byte[] getRawDetachDataToSend(DetachCommand command) throws IOException { - return ByteBuffer.allocate(5) - .put(Protocol.TCP_CMD_DETACH) - .putInt(command.getHandle()) - .array(); - } - - public static byte[] getRawPingDataToSend(PingCommand command){ - return new byte[]{Protocol.TCP_CMD_PING}; - } + public static final int TCP_PORT = 8112; + public static final int UDP_PORT = 8113; - public static byte[] getRawReadDataToSend(List readCommands) throws IOException { + public static final byte TCP_HANDSHAKE = 0x12; + public static final byte TCP_SAME_CLIENT = 0x20; + public static final byte TCP_NEW_CLIENT = 0x21; + + public static final byte TCP_CMD_ATTACH = 0x01; + public static final byte TCP_CMD_DETACH = 0x02; + public static final byte TCP_CMD_PING = (byte) 0xF0; + + public static final byte UDP_CMD_DATA = 0x03; + + public static final byte TCP_CMD_ATTACH_CONFIG_FOUND = (byte) 0xE0; + public static final byte TCP_CMD_ATTACH_CONFIG_NOT_FOUND = (byte) 0xE1; + public static final byte TCP_CMD_ATTACH_USERDATA_OKAY = (byte) 0xE8; + public static final byte TCP_CMD_ATTACH_USERDATA_BAD = (byte) 0xE9; + + private Protocol() { + } + + public enum HandshakeReturnCode { + BAD_HANDSHAKE, SAME_CLIENT, NEW_CLIENT + } + + public static byte[] getRawAttachDataToSend(AttachCommand command) throws IOException { + return ByteBuffer.allocate(9).put(Protocol.TCP_CMD_ATTACH).putInt(command.getHandle()).putShort(command.getVid()).putShort(command.getPid()).array(); + } + + public static byte[] getRawDetachDataToSend(DetachCommand command) throws IOException { + return ByteBuffer.allocate(5).put(Protocol.TCP_CMD_DETACH).putInt(command.getHandle()).array(); + } + + public static byte[] getRawPingDataToSend(PingCommand command) { + return new byte[] { Protocol.TCP_CMD_PING }; + } + + public static byte[] getRawReadDataToSend(List readCommands) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); dos.writeByte(Protocol.UDP_CMD_DATA); dos.writeByte(readCommands.size()); - - for(ReadCommand command : readCommands){ - NetworkHIDDevice sender = command.getSender(); + + for (ReadCommand command : readCommands) { + NetworkHIDDevice sender = command.getSender(); byte[] data = command.getData(); - if(data.length > 0xFF){ + if (data.length > 0xFF) { log.info("Tried to send too much data. Maximum is 0xFF bytes read command."); continue; } - byte newLength = (byte)(data.length & 0xFF); - - dos.writeInt(command.getHandle()); + byte newLength = (byte) (data.length & 0xFF); + + dos.writeInt(command.getHandle()); dos.writeShort(sender.getDeviceslot()); dos.writeByte(sender.getPadslot()); - + dos.write(newLength); dos.write(data, 0, newLength); } - + return bos.toByteArray(); } } diff --git a/src/net/ash/HIDToVPADNetworkClient/network/TCPClient.java b/src/net/ash/HIDToVPADNetworkClient/network/TCPClient.java index d17a3f4..397c15c 100644 --- a/src/net/ash/HIDToVPADNetworkClient/network/TCPClient.java +++ b/src/net/ash/HIDToVPADNetworkClient/network/TCPClient.java @@ -39,105 +39,109 @@ import net.ash.HIDToVPADNetworkClient.util.Settings; @Log public class TCPClient { - private Socket sock; - private DataInputStream in; - private DataOutputStream out; - @Getter private int clientID = HandleFoundry.next(); - - @Getter @Setter(AccessLevel.PRIVATE) - private int shouldRetry = Settings.MAXIMUM_TRIES_FOR_RECONNECTING; - - private String ip; - - public TCPClient() { - } - - public synchronized void connect(String ip) throws Exception { - - sock = new Socket(); - sock.connect(new InetSocketAddress(ip, Protocol.TCP_PORT), 2000); - in = new DataInputStream(sock.getInputStream()); - out = new DataOutputStream(sock.getOutputStream()); - - HandshakeReturnCode resultHandshake = doHandshake(); - if(resultHandshake == HandshakeReturnCode.BAD_HANDSHAKE){ - log.info("[TCP] Handshaking failed"); + private Socket sock; + private DataInputStream in; + private DataOutputStream out; + @Getter private int clientID = HandleFoundry.next(); + + @Getter @Setter(AccessLevel.PRIVATE) private int shouldRetry = Settings.MAXIMUM_TRIES_FOR_RECONNECTING; + + private String ip; + + public TCPClient() { + } + + public synchronized void connect(String ip) throws Exception { + + sock = new Socket(); + sock.connect(new InetSocketAddress(ip, Protocol.TCP_PORT), 2000); + in = new DataInputStream(sock.getInputStream()); + out = new DataOutputStream(sock.getOutputStream()); + + HandshakeReturnCode resultHandshake = doHandshake(); + if (resultHandshake == HandshakeReturnCode.BAD_HANDSHAKE) { + log.info("[TCP] Handshaking failed"); throw new Exception(); - }else{ - if(resultHandshake == HandshakeReturnCode.NEW_CLIENT && this.ip != null){ - //We check the IP to be sure it's the first time we connect to a WiiU. //TODO: Sending a ID from the WiiU which will be compared? - //we are new to the client. + } else { + if (resultHandshake == HandshakeReturnCode.NEW_CLIENT && this.ip != null) { + // We check the IP to be sure it's the first time we connect to + // a WiiU. //TODO: Sending a ID from the WiiU which will be + // compared? + // we are new to the client. ActiveControllerManager.getInstance().attachAllActiveControllers(); - }else if(resultHandshake == HandshakeReturnCode.SAME_CLIENT){ - + } else if (resultHandshake == HandshakeReturnCode.SAME_CLIENT) { + } this.ip = ip; shouldRetry = 0; } - } - - private synchronized HandshakeReturnCode doHandshake() throws Exception { - if (recvByte() != Protocol.TCP_HANDSHAKE) return HandshakeReturnCode.BAD_HANDSHAKE; - send(clientID); - log.info("[TCP] Handshaking..."); - HandshakeReturnCode test = (recvByte() == Protocol.TCP_NEW_CLIENT) ? HandshakeReturnCode.NEW_CLIENT : HandshakeReturnCode.SAME_CLIENT; - return test; - } - - public synchronized boolean abort(){ - try { - shouldRetry = Settings.MAXIMUM_TRIES_FOR_RECONNECTING; + } + + private synchronized HandshakeReturnCode doHandshake() throws Exception { + if (recvByte() != Protocol.TCP_HANDSHAKE) + return HandshakeReturnCode.BAD_HANDSHAKE; + send(clientID); + log.info("[TCP] Handshaking..."); + HandshakeReturnCode test = (recvByte() == Protocol.TCP_NEW_CLIENT) ? HandshakeReturnCode.NEW_CLIENT : HandshakeReturnCode.SAME_CLIENT; + return test; + } + + public synchronized boolean abort() { + try { + shouldRetry = Settings.MAXIMUM_TRIES_FOR_RECONNECTING; sock.close(); clientID = HandleFoundry.next(); } catch (IOException e) { - System.out.println(e.getMessage()); //TODO: handle + System.out.println(e.getMessage()); // TODO: handle return false; } - return true; - } + return true; + } public synchronized void send(byte[] rawCommand) throws IOException { - try{ + try { out.write(rawCommand); out.flush(); - }catch(IOException e){ + } catch (IOException e) { try { - if(shouldRetry++ < Settings.MAXIMUM_TRIES_FOR_RECONNECTING){ + if (shouldRetry++ < Settings.MAXIMUM_TRIES_FOR_RECONNECTING) { System.out.println("Trying again to connect! Attempt number " + shouldRetry); - connect(ip); //TODO: this is for reconnecting when the WiiU switches the application. But this breaks disconnecting, woops. - }else{ + connect(ip); // TODO: this is for reconnecting when the WiiU + // switches the application. But this breaks + // disconnecting, woops. + } else { abort(); } } catch (Exception e1) { - //e1.printStackTrace(); - } + // e1.printStackTrace(); + } throw e; } } - + public synchronized void send(int value) throws IOException { send(ByteBuffer.allocate(4).putInt(value).array()); } public synchronized byte recvByte() throws IOException { - try{ + try { return in.readByte(); - }catch(IOException e){ + } catch (IOException e) { System.out.println(e.getMessage()); throw e; } } public synchronized short recvShort() throws IOException { - try{ + try { return in.readShort(); - }catch(IOException e){ + } catch (IOException e) { System.out.println(e.getMessage()); throw e; } } - - public synchronized boolean isConnected(){ + + public synchronized boolean isConnected() { return (sock != null && sock.isConnected() && !sock.isClosed()); } diff --git a/src/net/ash/HIDToVPADNetworkClient/network/UDPClient.java b/src/net/ash/HIDToVPADNetworkClient/network/UDPClient.java index 41951a4..c19c233 100644 --- a/src/net/ash/HIDToVPADNetworkClient/network/UDPClient.java +++ b/src/net/ash/HIDToVPADNetworkClient/network/UDPClient.java @@ -29,25 +29,26 @@ import java.net.SocketException; import java.net.UnknownHostException; public class UDPClient { - private final DatagramSocket sock; - private final InetAddress host; - - private UDPClient(String ip) throws SocketException, UnknownHostException{ + private final DatagramSocket sock; + private final InetAddress host; + + private UDPClient(String ip) throws SocketException, UnknownHostException { sock = new DatagramSocket(); - host = InetAddress.getByName(ip); - } - public static UDPClient createUDPClient(String ip){ - UDPClient result = null; + host = InetAddress.getByName(ip); + } + + public static UDPClient createUDPClient(String ip) { + UDPClient result = null; try { result = new UDPClient(ip); } catch (Exception e) { - //handle? + // handle? } return result; - } - - public void send(byte[] data) throws IOException { - DatagramPacket packet = new DatagramPacket(data, data.length, host, Protocol.UDP_PORT); - sock.send(packet); - } + } + + public void send(byte[] data) throws IOException { + DatagramPacket packet = new DatagramPacket(data, data.length, host, Protocol.UDP_PORT); + sock.send(packet); + } } \ No newline at end of file diff --git a/src/net/ash/HIDToVPADNetworkClient/network/commands/AttachCommand.java b/src/net/ash/HIDToVPADNetworkClient/network/commands/AttachCommand.java index b0fe1b5..ac9a89c 100644 --- a/src/net/ash/HIDToVPADNetworkClient/network/commands/AttachCommand.java +++ b/src/net/ash/HIDToVPADNetworkClient/network/commands/AttachCommand.java @@ -20,21 +20,22 @@ * SOFTWARE. *******************************************************************************/ package net.ash.HIDToVPADNetworkClient.network.commands; + import lombok.Getter; import net.ash.HIDToVPADNetworkClient.network.NetworkHIDDevice; public class AttachCommand extends DeviceCommand { @Getter private final short vid; - @Getter private final short pid; + @Getter private final short pid; public AttachCommand(int hidHandle, short vid, short pid, NetworkHIDDevice sender) { - super(hidHandle,sender); + super(hidHandle, sender); this.vid = vid; this.pid = pid; } @Override public String toString() { - return "AttachCommand [vid=" + vid + ", pid=" + pid+ ", handle=" + getHandle() + ", sender=" + getSender() + "]"; + return "AttachCommand [vid=" + vid + ", pid=" + pid + ", handle=" + getHandle() + ", sender=" + getSender() + "]"; } } diff --git a/src/net/ash/HIDToVPADNetworkClient/network/commands/DetachCommand.java b/src/net/ash/HIDToVPADNetworkClient/network/commands/DetachCommand.java index 54aa0ca..13c49d8 100644 --- a/src/net/ash/HIDToVPADNetworkClient/network/commands/DetachCommand.java +++ b/src/net/ash/HIDToVPADNetworkClient/network/commands/DetachCommand.java @@ -23,9 +23,9 @@ package net.ash.HIDToVPADNetworkClient.network.commands; import net.ash.HIDToVPADNetworkClient.network.NetworkHIDDevice; -public class DetachCommand extends DeviceCommand{ - public DetachCommand(int hidHandle, NetworkHIDDevice sender){ - super(hidHandle,sender); +public class DetachCommand extends DeviceCommand { + public DetachCommand(int hidHandle, NetworkHIDDevice sender) { + super(hidHandle, sender); } @Override diff --git a/src/net/ash/HIDToVPADNetworkClient/network/commands/DeviceCommand.java b/src/net/ash/HIDToVPADNetworkClient/network/commands/DeviceCommand.java index 02395c9..2d0d135 100644 --- a/src/net/ash/HIDToVPADNetworkClient/network/commands/DeviceCommand.java +++ b/src/net/ash/HIDToVPADNetworkClient/network/commands/DeviceCommand.java @@ -20,18 +20,19 @@ * SOFTWARE. *******************************************************************************/ package net.ash.HIDToVPADNetworkClient.network.commands; + import lombok.Data; import net.ash.HIDToVPADNetworkClient.network.NetworkHIDDevice; @Data public abstract class DeviceCommand { - private final int handle; - private final NetworkHIDDevice sender; - private final Class type; - - protected DeviceCommand(int hidHandle,NetworkHIDDevice sender){ - this.handle = hidHandle; - this.sender = sender; - this.type = this.getClass(); - } + private final int handle; + private final NetworkHIDDevice sender; + private final Class type; + + protected DeviceCommand(int hidHandle, NetworkHIDDevice sender) { + this.handle = hidHandle; + this.sender = sender; + this.type = this.getClass(); + } } diff --git a/src/net/ash/HIDToVPADNetworkClient/network/commands/PingCommand.java b/src/net/ash/HIDToVPADNetworkClient/network/commands/PingCommand.java index 35ff8e5..a1c6683 100644 --- a/src/net/ash/HIDToVPADNetworkClient/network/commands/PingCommand.java +++ b/src/net/ash/HIDToVPADNetworkClient/network/commands/PingCommand.java @@ -25,12 +25,13 @@ import net.ash.HIDToVPADNetworkClient.network.NetworkHIDDevice; public class PingCommand extends DeviceCommand { public PingCommand() { - this((short) 0,null); + this((short) 0, null); } + private PingCommand(int hidHandle, NetworkHIDDevice sender) { super(hidHandle, sender); } - + @Override public String toString() { return "PingCommand []"; diff --git a/src/net/ash/HIDToVPADNetworkClient/network/commands/ReadCommand.java b/src/net/ash/HIDToVPADNetworkClient/network/commands/ReadCommand.java index eb18cd5..84ef1ce 100644 --- a/src/net/ash/HIDToVPADNetworkClient/network/commands/ReadCommand.java +++ b/src/net/ash/HIDToVPADNetworkClient/network/commands/ReadCommand.java @@ -24,13 +24,14 @@ package net.ash.HIDToVPADNetworkClient.network.commands; import lombok.Getter; import net.ash.HIDToVPADNetworkClient.network.NetworkHIDDevice; -public class ReadCommand extends DeviceCommand{ +public class ReadCommand extends DeviceCommand { @Getter private final byte[] data; - public ReadCommand(int hidHandle,byte[] data, NetworkHIDDevice sender) { + + public ReadCommand(int hidHandle, byte[] data, NetworkHIDDevice sender) { super(hidHandle, sender); this.data = data; } - + @Override public String toString() { return "ReadCommand [handle=" + getHandle() + ", sender=" + getSender() + "]"; diff --git a/src/net/ash/HIDToVPADNetworkClient/util/HandleFoundry.java b/src/net/ash/HIDToVPADNetworkClient/util/HandleFoundry.java index f35564c..b4fdfca 100644 --- a/src/net/ash/HIDToVPADNetworkClient/util/HandleFoundry.java +++ b/src/net/ash/HIDToVPADNetworkClient/util/HandleFoundry.java @@ -28,12 +28,14 @@ package net.ash.HIDToVPADNetworkClient.util; import java.util.Random; public class HandleFoundry { - //We start with a random value, so we have at each startup a different clientID! - private static int h = new Random().nextInt(); - - private HandleFoundry(){} - - public static int next() { - return h++; - } + // We start with a random value, so we have at each startup a different + // clientID! + private static int h = new Random().nextInt(); + + private HandleFoundry() { + } + + public static int next() { + return h++; + } } \ No newline at end of file diff --git a/src/net/ash/HIDToVPADNetworkClient/util/PureJavaHidApiManager.java b/src/net/ash/HIDToVPADNetworkClient/util/PureJavaHidApiManager.java index fca6687..f7183eb 100644 --- a/src/net/ash/HIDToVPADNetworkClient/util/PureJavaHidApiManager.java +++ b/src/net/ash/HIDToVPADNetworkClient/util/PureJavaHidApiManager.java @@ -29,29 +29,32 @@ import purejavahidapi.HidDeviceInfo; import purejavahidapi.PureJavaHidApi; public class PureJavaHidApiManager { - - private PureJavaHidApiManager(){} - + + private PureJavaHidApiManager() { + } + public static boolean MAC_OS_X; - + /** * Searches the corresponding HIDDevice for the given path - * @param path Path of the HIDDevice + * + * @param path + * Path of the HIDDevice * @return It the device is found, it will be returned. Otherwise null is returned. - * @throws IOException + * @throws IOException */ - public static HidDevice getDeviceByPath(String path) throws IOException{ + public static HidDevice getDeviceByPath(String path) throws IOException { List devList = PureJavaHidApi.enumerateDevices(); for (HidDeviceInfo info : devList) { - if (MAC_OS_X) { - if(info.getPath().substring(0, 13).equals(path)){ + if (MAC_OS_X) { + if (info.getPath().substring(0, 13).equals(path)) { return PureJavaHidApi.openDevice(info); } - } else { - if(info.getPath().equals(path)){ + } else { + if (info.getPath().equals(path)) { return PureJavaHidApi.openDevice(info); } - } + } } return null; } diff --git a/src/net/ash/HIDToVPADNetworkClient/util/Settings.java b/src/net/ash/HIDToVPADNetworkClient/util/Settings.java index 9618565..c357708 100644 --- a/src/net/ash/HIDToVPADNetworkClient/util/Settings.java +++ b/src/net/ash/HIDToVPADNetworkClient/util/Settings.java @@ -36,58 +36,58 @@ import lombok.extern.java.Log; @Log public class Settings { - private static final String CONFIG_FILE_NAME = "hidtovpad.properties"; - + private static final String CONFIG_FILE_NAME = "hidtovpad.properties"; + public static final int DETECT_CONTROLLER_INTERVAL = 1000; public static final int HANDLE_INPUTS_INTERVAL = 15; public static final int MAXIMUM_TRIES_FOR_RECONNECTING = 10; public static final int SLEEP_AFER_POLLING = 10; public static final int SENDING_CMD_SLEEP_IF_NOT_CONNECTED = 500; public static final int PING_INTERVAL = 1000; - public static final int PROCESS_CMD_INTERVAL = 10; - - @Getter @Setter - private static String ipAddr = "192.168.0.35"; //@Maschell, you're welcome + public static final int PROCESS_CMD_INTERVAL = 10; - private Settings() {} + @Getter @Setter private static String ipAddr = "192.168.0.35"; // @Maschell, you're welcome + + private Settings() { + } public static void loadSettings() { - File configDir = new File(getConfigDir()); - if (!configDir.exists()) { - log.info("Creating " + configDir.getAbsolutePath() + "..."); - configDir.mkdirs(); - } - File configFile = getConfigFile(); - if (!configFile.exists()) { - log.info("Creating " + configFile.getAbsolutePath() + " with default values..."); - try { - configFile.createNewFile(); - } catch (IOException e) { - log.severe("Could not create config file!"); - e.printStackTrace(); - log.warning("Using default values"); - } - saveSettings(configFile); - return; - } - - log.info("Loading config from " + configFile.getAbsolutePath() + "..."); - - Properties prop = new Properties(); - try { - prop.load(new FileInputStream(configFile)); - } catch (IOException e) { - log.severe("Error while loading config file!"); - e.printStackTrace(); - log.warning("Using default values"); - return; - } - - Settings.ipAddr = prop.getProperty("ipAddr"); - - log.info("Loaded config successfully!"); + File configDir = new File(getConfigDir()); + if (!configDir.exists()) { + log.info("Creating " + configDir.getAbsolutePath() + "..."); + configDir.mkdirs(); + } + File configFile = getConfigFile(); + if (!configFile.exists()) { + log.info("Creating " + configFile.getAbsolutePath() + " with default values..."); + try { + configFile.createNewFile(); + } catch (IOException e) { + log.severe("Could not create config file!"); + e.printStackTrace(); + log.warning("Using default values"); + } + saveSettings(configFile); + return; + } + + log.info("Loading config from " + configFile.getAbsolutePath() + "..."); + + Properties prop = new Properties(); + try { + prop.load(new FileInputStream(configFile)); + } catch (IOException e) { + log.severe("Error while loading config file!"); + e.printStackTrace(); + log.warning("Using default values"); + return; + } + + Settings.ipAddr = prop.getProperty("ipAddr"); + + log.info("Loaded config successfully!"); } - + private static File getConfigFile() { return new File(getConfigDir() + CONFIG_FILE_NAME); } @@ -99,29 +99,29 @@ public class Settings { saveSettings(configFile); } } - + private static void saveSettings(File configFile) { - Properties prop = new Properties(); - - prop.setProperty("ipAddr", Settings.ipAddr); - - try { - FileOutputStream outStream = new FileOutputStream(configFile); - prop.store(outStream, "HIDToVPADNetworkClient"); - outStream.close(); - } catch (FileNotFoundException e) { - log.severe("Could not open the new config file!"); - e.printStackTrace(); - log.warning("New file will not be written."); - return; - } catch (IOException e) { - log.severe("Could not write the new config file!"); - e.printStackTrace(); - log.warning("New file will not be written."); - return; - } + Properties prop = new Properties(); + + prop.setProperty("ipAddr", Settings.ipAddr); + + try { + FileOutputStream outStream = new FileOutputStream(configFile); + prop.store(outStream, "HIDToVPADNetworkClient"); + outStream.close(); + } catch (FileNotFoundException e) { + log.severe("Could not open the new config file!"); + e.printStackTrace(); + log.warning("New file will not be written."); + return; + } catch (IOException e) { + log.severe("Could not write the new config file!"); + e.printStackTrace(); + log.warning("New file will not be written."); + return; + } } - + private static String getConfigDir() { return "config/"; } diff --git a/src/net/ash/HIDToVPADNetworkClient/util/Utilities.java b/src/net/ash/HIDToVPADNetworkClient/util/Utilities.java index c66b1d3..2101fac 100644 --- a/src/net/ash/HIDToVPADNetworkClient/util/Utilities.java +++ b/src/net/ash/HIDToVPADNetworkClient/util/Utilities.java @@ -21,13 +21,16 @@ *******************************************************************************/ package net.ash.HIDToVPADNetworkClient.util; -public class Utilities{ - - private Utilities(){} - +public class Utilities { + + private Utilities() { + } + /** * Let me just sleep! - * @param ms sleep duration in ms + * + * @param ms + * sleep duration in ms */ public static void sleep(int ms) { try { @@ -35,36 +38,43 @@ public class Utilities{ } catch (InterruptedException e) { } } - + /** * Convert a byte array to a formated String - * @param ba byte array + * + * @param ba + * byte array * @return String representing the binary data */ - public static String ByteArrayToString(byte[] ba){ - if(ba == null) return null; - StringBuilder hex = new StringBuilder(ba.length * 2); - for(byte b : ba){ - hex.append(String.format("%02X", b)); - } - return hex.toString(); + public static String ByteArrayToString(byte[] ba) { + if (ba == null) + return null; + StringBuilder hex = new StringBuilder(ba.length * 2); + for (byte b : ba) { + hex.append(String.format("%02X", b)); + } + return hex.toString(); } - + /** - * Converts a signed short value to a unsigned byte - * @param value short value + * Converts a signed short value to a unsigned byte + * + * @param value + * short value * @return converted value */ - public static short signedShortToByte(int value){ - return (short) (((((short)value) + Short.MAX_VALUE + 1) >> 8) & 0xFF); + public static short signedShortToByte(int value) { + return (short) (((((short) value) + Short.MAX_VALUE + 1) >> 8) & 0xFF); } - + /** - * Converts a signed short value to a unsigned byte - * @param value short value + * Converts a signed short value to a unsigned byte + * + * @param value + * short value * @return converted value */ - public static short signedShortToByte(short value){ + public static short signedShortToByte(short value) { return signedShortToByte((int) value); } }