From 3f3c573c792677aaaed988076cd8840dc2029670 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 28 Mar 2014 23:53:28 -0400 Subject: [PATCH] Move controller handling into a new class. Implement translation for DualShock 4 controllers. --- src/com/limelight/Game.java | 214 +---------- .../binding/input/ControllerHandler.java | 333 ++++++++++++++++++ 2 files changed, 340 insertions(+), 207 deletions(-) create mode 100644 src/com/limelight/binding/input/ControllerHandler.java diff --git a/src/com/limelight/Game.java b/src/com/limelight/Game.java index a70e7ef2..2762bd19 100644 --- a/src/com/limelight/Game.java +++ b/src/com/limelight/Game.java @@ -1,13 +1,13 @@ package com.limelight; import com.limelight.binding.PlatformBinding; +import com.limelight.binding.input.ControllerHandler; import com.limelight.binding.input.KeyboardTranslator; import com.limelight.binding.video.ConfigurableDecoderRenderer; import com.limelight.nvstream.NvConnection; import com.limelight.nvstream.NvConnectionListener; import com.limelight.nvstream.StreamConfiguration; import com.limelight.nvstream.av.video.VideoDecoderRenderer; -import com.limelight.nvstream.input.ControllerPacket; import com.limelight.nvstream.input.KeyboardPacket; import com.limelight.utils.Dialog; import com.limelight.utils.SpinnerDialog; @@ -35,13 +35,6 @@ import android.widget.Toast; public class Game extends Activity implements OnGenericMotionListener, OnTouchListener, NvConnectionListener { - private short inputMap = 0x0000; - private byte leftTrigger = 0x00; - private byte rightTrigger = 0x00; - private short rightStickX = 0x0000; - private short rightStickY = 0x0000; - private short leftStickX = 0x0000; - private short leftStickY = 0x0000; private int lastMouseX = Integer.MIN_VALUE; private int lastMouseY = Integer.MIN_VALUE; private int lastButtonState = 0; @@ -49,6 +42,7 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi private int lastTouchY = 0; private boolean hasMoved = false; + private ControllerHandler controllerHandler; private KeyboardTranslator keybTranslator; private int height; @@ -135,6 +129,7 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi conn = new NvConnection(Game.this.getIntent().getStringExtra("host"), Game.this, new StreamConfiguration(width, height, refreshRate)); keybTranslator = new KeyboardTranslator(conn); + controllerHandler = new ControllerHandler(conn); conn.start(PlatformBinding.getDeviceName(), sv.getHolder(), drFlags, PlatformBinding.getAudioRenderer(), new ConfigurableDecoderRenderer()); } @@ -211,64 +206,9 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi getModifierState(event)); } else { - switch (keyCode) { - case KeyEvent.KEYCODE_BUTTON_START: - case KeyEvent.KEYCODE_MENU: - inputMap |= ControllerPacket.PLAY_FLAG; - break; - case KeyEvent.KEYCODE_BACK: - case KeyEvent.KEYCODE_BUTTON_SELECT: - inputMap |= ControllerPacket.BACK_FLAG; - break; - case KeyEvent.KEYCODE_DPAD_LEFT: - inputMap |= ControllerPacket.LEFT_FLAG; - break; - case KeyEvent.KEYCODE_DPAD_RIGHT: - inputMap |= ControllerPacket.RIGHT_FLAG; - break; - case KeyEvent.KEYCODE_DPAD_UP: - inputMap |= ControllerPacket.UP_FLAG; - break; - case KeyEvent.KEYCODE_DPAD_DOWN: - inputMap |= ControllerPacket.DOWN_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_B: - inputMap |= ControllerPacket.B_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_A: - inputMap |= ControllerPacket.A_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_X: - inputMap |= ControllerPacket.X_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_Y: - inputMap |= ControllerPacket.Y_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_L1: - inputMap |= ControllerPacket.LB_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_R1: - inputMap |= ControllerPacket.RB_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_THUMBL: - inputMap |= ControllerPacket.LS_CLK_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_THUMBR: - inputMap |= ControllerPacket.RS_CLK_FLAG; - break; - default: + if (!controllerHandler.handleButtonDown(keyCode, event)) { return super.onKeyDown(keyCode, event); } - - // We detect back+start as the special button combo - if ((inputMap & ControllerPacket.BACK_FLAG) != 0 && - (inputMap & ControllerPacket.PLAY_FLAG) != 0) - { - inputMap &= ~(ControllerPacket.BACK_FLAG | ControllerPacket.PLAY_FLAG); - inputMap |= ControllerPacket.SPECIAL_BUTTON_FLAG; - } - - sendControllerInputPacket(); } return true; @@ -287,63 +227,9 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi getModifierState(event)); } else { - switch (keyCode) { - case KeyEvent.KEYCODE_BUTTON_START: - case KeyEvent.KEYCODE_MENU: - inputMap &= ~ControllerPacket.PLAY_FLAG; - break; - case KeyEvent.KEYCODE_BACK: - case KeyEvent.KEYCODE_BUTTON_SELECT: - inputMap &= ~ControllerPacket.BACK_FLAG; - break; - case KeyEvent.KEYCODE_DPAD_LEFT: - inputMap &= ~ControllerPacket.LEFT_FLAG; - break; - case KeyEvent.KEYCODE_DPAD_RIGHT: - inputMap &= ~ControllerPacket.RIGHT_FLAG; - break; - case KeyEvent.KEYCODE_DPAD_UP: - inputMap &= ~ControllerPacket.UP_FLAG; - break; - case KeyEvent.KEYCODE_DPAD_DOWN: - inputMap &= ~ControllerPacket.DOWN_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_B: - inputMap &= ~ControllerPacket.B_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_A: - inputMap &= ~ControllerPacket.A_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_X: - inputMap &= ~ControllerPacket.X_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_Y: - inputMap &= ~ControllerPacket.Y_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_L1: - inputMap &= ~ControllerPacket.LB_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_R1: - inputMap &= ~ControllerPacket.RB_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_THUMBL: - inputMap &= ~ControllerPacket.LS_CLK_FLAG; - break; - case KeyEvent.KEYCODE_BUTTON_THUMBR: - inputMap &= ~ControllerPacket.RS_CLK_FLAG; - break; - default: + if (!controllerHandler.handleButtonUp(keyCode, event)) { return super.onKeyUp(keyCode, event); } - - // If one of the two is up, the special button comes up too - if ((inputMap & ControllerPacket.BACK_FLAG) == 0 || - (inputMap & ControllerPacket.PLAY_FLAG) == 0) - { - inputMap &= ~ControllerPacket.SPECIAL_BUTTON_FLAG; - } - - sendControllerInputPacket(); } return true; @@ -461,92 +347,11 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi return super.onTouchEvent(event); } - + @Override public boolean onGenericMotionEvent(MotionEvent event) { - InputDevice dev = event.getDevice(); - - if (dev == null) { - System.err.println("Unknown device"); - return false; - } - if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { - float LS_X = event.getAxisValue(MotionEvent.AXIS_X); - float LS_Y = event.getAxisValue(MotionEvent.AXIS_Y); - - float RS_X, RS_Y, L2, R2; - - InputDevice.MotionRange leftTriggerRange = dev.getMotionRange(MotionEvent.AXIS_LTRIGGER); - InputDevice.MotionRange rightTriggerRange = dev.getMotionRange(MotionEvent.AXIS_RTRIGGER); - if (leftTriggerRange != null && rightTriggerRange != null) - { - // Ouya controller - L2 = event.getAxisValue(MotionEvent.AXIS_LTRIGGER); - R2 = event.getAxisValue(MotionEvent.AXIS_RTRIGGER); - RS_X = event.getAxisValue(MotionEvent.AXIS_Z); - RS_Y = event.getAxisValue(MotionEvent.AXIS_RZ); - } - else - { - InputDevice.MotionRange brakeRange = dev.getMotionRange(MotionEvent.AXIS_BRAKE); - InputDevice.MotionRange gasRange = dev.getMotionRange(MotionEvent.AXIS_GAS); - if (brakeRange != null && gasRange != null) - { - // Moga controller - RS_X = event.getAxisValue(MotionEvent.AXIS_Z); - RS_Y = event.getAxisValue(MotionEvent.AXIS_RZ); - L2 = event.getAxisValue(MotionEvent.AXIS_BRAKE); - R2 = event.getAxisValue(MotionEvent.AXIS_GAS); - } - else - { - // Xbox controller - RS_X = event.getAxisValue(MotionEvent.AXIS_RX); - RS_Y = event.getAxisValue(MotionEvent.AXIS_RY); - L2 = (event.getAxisValue(MotionEvent.AXIS_Z) + 1) / 2; - R2 = (event.getAxisValue(MotionEvent.AXIS_RZ) + 1) / 2; - } - } - - - InputDevice.MotionRange hatXRange = dev.getMotionRange(MotionEvent.AXIS_HAT_X); - InputDevice.MotionRange hatYRange = dev.getMotionRange(MotionEvent.AXIS_HAT_Y); - if (hatXRange != null && hatYRange != null) - { - // Xbox controller D-pad - float hatX, hatY; - - hatX = event.getAxisValue(MotionEvent.AXIS_HAT_X); - hatY = event.getAxisValue(MotionEvent.AXIS_HAT_Y); - - inputMap &= ~(ControllerPacket.LEFT_FLAG | ControllerPacket.RIGHT_FLAG); - inputMap &= ~(ControllerPacket.UP_FLAG | ControllerPacket.DOWN_FLAG); - if (hatX < -0.5) { - inputMap |= ControllerPacket.LEFT_FLAG; - } - if (hatX > 0.5) { - inputMap |= ControllerPacket.RIGHT_FLAG; - } - if (hatY < -0.5) { - inputMap |= ControllerPacket.UP_FLAG; - } - if (hatY > 0.5) { - inputMap |= ControllerPacket.DOWN_FLAG; - } - } - - leftStickX = (short)Math.round(LS_X * 0x7FFF); - leftStickY = (short)Math.round(-LS_Y * 0x7FFF); - - rightStickX = (short)Math.round(RS_X * 0x7FFF); - rightStickY = (short)Math.round(-RS_Y * 0x7FFF); - - leftTrigger = (byte)Math.round(L2 * 0xFF); - rightTrigger = (byte)Math.round(R2 * 0xFF); - - sendControllerInputPacket(); - return true; + controllerHandler.handleMotionEvent(event); } else if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { @@ -580,11 +385,6 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi lastMouseX = eventX; lastMouseY = eventY; } - - private void sendControllerInputPacket() { - conn.sendControllerInput(inputMap, leftTrigger, rightTrigger, - leftStickX, leftStickY, rightStickX, rightStickY); - } @Override public boolean onGenericMotion(View v, MotionEvent event) { diff --git a/src/com/limelight/binding/input/ControllerHandler.java b/src/com/limelight/binding/input/ControllerHandler.java new file mode 100644 index 00000000..664f1a95 --- /dev/null +++ b/src/com/limelight/binding/input/ControllerHandler.java @@ -0,0 +1,333 @@ +package com.limelight.binding.input; + +import android.view.InputDevice; +import android.view.KeyEvent; +import android.view.MotionEvent; + +import com.limelight.nvstream.NvConnection; +import com.limelight.nvstream.input.ControllerPacket; + +public class ControllerHandler { + private short inputMap = 0x0000; + private byte leftTrigger = 0x00; + private byte rightTrigger = 0x00; + private short rightStickX = 0x0000; + private short rightStickY = 0x0000; + private short leftStickX = 0x0000; + private short leftStickY = 0x0000; + + private NvConnection conn; + + public ControllerHandler(NvConnection conn) { + this.conn = conn; + } + + private void sendControllerInputPacket() { + conn.sendControllerInput(inputMap, leftTrigger, rightTrigger, + leftStickX, leftStickY, rightStickX, rightStickY); + } + + private static boolean isDualShock4(InputDevice dev) { + return (dev.getMotionRange(MotionEvent.AXIS_RX) != null && + dev.getMotionRange(MotionEvent.AXIS_RY) != null && + dev.getMotionRange(MotionEvent.AXIS_HAT_X) != null && + dev.getMotionRange(MotionEvent.AXIS_HAT_Y) != null && + dev.getMotionRange(MotionEvent.AXIS_RZ) != null && + dev.getMotionRange(MotionEvent.AXIS_RY) != null); + } + + private int handleRemapping(InputDevice dev, int keyCode) { + if (isDualShock4(dev)) { + switch (keyCode) { + case KeyEvent.KEYCODE_BUTTON_Y: + return KeyEvent.KEYCODE_BUTTON_L1; + + case KeyEvent.KEYCODE_BUTTON_Z: + return KeyEvent.KEYCODE_BUTTON_R1; + + case KeyEvent.KEYCODE_BUTTON_C: + return KeyEvent.KEYCODE_BUTTON_B; + + case KeyEvent.KEYCODE_BUTTON_X: + return KeyEvent.KEYCODE_BUTTON_Y; + + case KeyEvent.KEYCODE_BUTTON_B: + return KeyEvent.KEYCODE_BUTTON_A; + + case KeyEvent.KEYCODE_BUTTON_A: + return KeyEvent.KEYCODE_BUTTON_X; + + case KeyEvent.KEYCODE_BUTTON_SELECT: + return KeyEvent.KEYCODE_BUTTON_THUMBL; + + case KeyEvent.KEYCODE_BUTTON_START: + return KeyEvent.KEYCODE_BUTTON_THUMBR; + + case KeyEvent.KEYCODE_BUTTON_L2: + return KeyEvent.KEYCODE_BUTTON_SELECT; + + case KeyEvent.KEYCODE_BUTTON_R2: + return KeyEvent.KEYCODE_BUTTON_START; + + // These are duplicate trigger events + case KeyEvent.KEYCODE_BUTTON_R1: + case KeyEvent.KEYCODE_BUTTON_L1: + return 0; + + // These are duplicate dpad events + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + case KeyEvent.KEYCODE_DPAD_CENTER: + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_DOWN: + return 0; + } + } + + return keyCode; + } + + public boolean handleMotionEvent(MotionEvent event) { + InputDevice dev = event.getDevice(); + if (dev == null) { + System.err.println("Unknown device"); + return false; + } + + float LS_X = event.getAxisValue(MotionEvent.AXIS_X); + float LS_Y = event.getAxisValue(MotionEvent.AXIS_Y); + + float RS_X, RS_Y, L2, R2; + + InputDevice.MotionRange leftTriggerRange = dev.getMotionRange(MotionEvent.AXIS_LTRIGGER); + InputDevice.MotionRange rightTriggerRange = dev.getMotionRange(MotionEvent.AXIS_RTRIGGER); + if (leftTriggerRange != null && rightTriggerRange != null) + { + // Ouya controller + L2 = event.getAxisValue(MotionEvent.AXIS_LTRIGGER); + R2 = event.getAxisValue(MotionEvent.AXIS_RTRIGGER); + RS_X = event.getAxisValue(MotionEvent.AXIS_Z); + RS_Y = event.getAxisValue(MotionEvent.AXIS_RZ); + } + else + { + InputDevice.MotionRange brakeRange = dev.getMotionRange(MotionEvent.AXIS_BRAKE); + InputDevice.MotionRange gasRange = dev.getMotionRange(MotionEvent.AXIS_GAS); + InputDevice.MotionRange rxRange = dev.getMotionRange(MotionEvent.AXIS_RX); + InputDevice.MotionRange ryRange = dev.getMotionRange(MotionEvent.AXIS_RY); + if (brakeRange != null && gasRange != null) + { + // Moga controller + RS_X = event.getAxisValue(MotionEvent.AXIS_Z); + RS_Y = event.getAxisValue(MotionEvent.AXIS_RZ); + L2 = event.getAxisValue(MotionEvent.AXIS_BRAKE); + R2 = event.getAxisValue(MotionEvent.AXIS_GAS); + } + else if (rxRange != null && ryRange != null) + { + // DS4 controller + RS_X = event.getAxisValue(MotionEvent.AXIS_Z); + RS_Y = event.getAxisValue(MotionEvent.AXIS_RZ); + L2 = (event.getAxisValue(MotionEvent.AXIS_RX) + 1) / 2; + R2 = (event.getAxisValue(MotionEvent.AXIS_RY) + 1) / 2; + } + else + { + // Xbox controller + RS_X = event.getAxisValue(MotionEvent.AXIS_RX); + RS_Y = event.getAxisValue(MotionEvent.AXIS_RY); + L2 = (event.getAxisValue(MotionEvent.AXIS_Z) + 1) / 2; + R2 = (event.getAxisValue(MotionEvent.AXIS_RZ) + 1) / 2; + } + } + + InputDevice.MotionRange hatXRange = dev.getMotionRange(MotionEvent.AXIS_HAT_X); + InputDevice.MotionRange hatYRange = dev.getMotionRange(MotionEvent.AXIS_HAT_Y); + if (hatXRange != null && hatYRange != null) + { + // Xbox and DS4 D-pad + float hatX, hatY; + + hatX = event.getAxisValue(MotionEvent.AXIS_HAT_X); + hatY = event.getAxisValue(MotionEvent.AXIS_HAT_Y); + + inputMap &= ~(ControllerPacket.LEFT_FLAG | ControllerPacket.RIGHT_FLAG); + inputMap &= ~(ControllerPacket.UP_FLAG | ControllerPacket.DOWN_FLAG); + if (hatX < -0.5) { + inputMap |= ControllerPacket.LEFT_FLAG; + } + if (hatX > 0.5) { + inputMap |= ControllerPacket.RIGHT_FLAG; + } + if (hatY < -0.5) { + inputMap |= ControllerPacket.UP_FLAG; + } + if (hatY > 0.5) { + inputMap |= ControllerPacket.DOWN_FLAG; + } + } + + leftStickX = (short)Math.round(LS_X * 0x7FFF); + leftStickY = (short)Math.round(-LS_Y * 0x7FFF); + + rightStickX = (short)Math.round(RS_X * 0x7FFF); + rightStickY = (short)Math.round(-RS_Y * 0x7FFF); + + leftTrigger = (byte)Math.round(L2 * 0xFF); + rightTrigger = (byte)Math.round(R2 * 0xFF); + + sendControllerInputPacket(); + return true; + } + + public boolean handleButtonUp(int keyCode, KeyEvent event) { + InputDevice dev = event.getDevice(); + if (dev == null) { + System.err.println("Unknown device"); + return false; + } + + keyCode = handleRemapping(dev, keyCode); + if (keyCode == 0) { + return true; + } + + switch (keyCode) { + case KeyEvent.KEYCODE_BUTTON_MODE: + inputMap &= ~ControllerPacket.SPECIAL_BUTTON_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_START: + case KeyEvent.KEYCODE_MENU: + inputMap &= ~ControllerPacket.PLAY_FLAG; + break; + case KeyEvent.KEYCODE_BACK: + case KeyEvent.KEYCODE_BUTTON_SELECT: + inputMap &= ~ControllerPacket.BACK_FLAG; + break; + case KeyEvent.KEYCODE_DPAD_LEFT: + inputMap &= ~ControllerPacket.LEFT_FLAG; + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + inputMap &= ~ControllerPacket.RIGHT_FLAG; + break; + case KeyEvent.KEYCODE_DPAD_UP: + inputMap &= ~ControllerPacket.UP_FLAG; + break; + case KeyEvent.KEYCODE_DPAD_DOWN: + inputMap &= ~ControllerPacket.DOWN_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_B: + inputMap &= ~ControllerPacket.B_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_A: + inputMap &= ~ControllerPacket.A_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_X: + inputMap &= ~ControllerPacket.X_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_Y: + inputMap &= ~ControllerPacket.Y_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_L1: + inputMap &= ~ControllerPacket.LB_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_R1: + inputMap &= ~ControllerPacket.RB_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_THUMBL: + inputMap &= ~ControllerPacket.LS_CLK_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_THUMBR: + inputMap &= ~ControllerPacket.RS_CLK_FLAG; + break; + default: + return false; + } + + // If one of the two is up, the special button comes up too + if ((inputMap & ControllerPacket.BACK_FLAG) == 0 || + (inputMap & ControllerPacket.PLAY_FLAG) == 0) + { + inputMap &= ~ControllerPacket.SPECIAL_BUTTON_FLAG; + } + + sendControllerInputPacket(); + return true; + } + + public boolean handleButtonDown(int keyCode, KeyEvent event) { + InputDevice dev = event.getDevice(); + if (dev == null) { + System.err.println("Unknown device"); + return false; + } + + keyCode = handleRemapping(dev, keyCode); + if (keyCode == 0) { + return true; + } + + switch (keyCode) { + case KeyEvent.KEYCODE_BUTTON_MODE: + inputMap |= ControllerPacket.SPECIAL_BUTTON_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_START: + case KeyEvent.KEYCODE_MENU: + inputMap |= ControllerPacket.PLAY_FLAG; + break; + case KeyEvent.KEYCODE_BACK: + case KeyEvent.KEYCODE_BUTTON_SELECT: + inputMap |= ControllerPacket.BACK_FLAG; + break; + case KeyEvent.KEYCODE_DPAD_LEFT: + inputMap |= ControllerPacket.LEFT_FLAG; + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + inputMap |= ControllerPacket.RIGHT_FLAG; + break; + case KeyEvent.KEYCODE_DPAD_UP: + inputMap |= ControllerPacket.UP_FLAG; + break; + case KeyEvent.KEYCODE_DPAD_DOWN: + inputMap |= ControllerPacket.DOWN_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_B: + inputMap |= ControllerPacket.B_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_A: + inputMap |= ControllerPacket.A_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_X: + inputMap |= ControllerPacket.X_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_Y: + inputMap |= ControllerPacket.Y_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_L1: + inputMap |= ControllerPacket.LB_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_R1: + inputMap |= ControllerPacket.RB_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_THUMBL: + inputMap |= ControllerPacket.LS_CLK_FLAG; + break; + case KeyEvent.KEYCODE_BUTTON_THUMBR: + inputMap |= ControllerPacket.RS_CLK_FLAG; + break; + default: + return false; + } + + // We detect back+start as the special button combo + if ((inputMap & ControllerPacket.BACK_FLAG) != 0 && + (inputMap & ControllerPacket.PLAY_FLAG) != 0) + { + inputMap &= ~(ControllerPacket.BACK_FLAG | ControllerPacket.PLAY_FLAG); + inputMap |= ControllerPacket.SPECIAL_BUTTON_FLAG; + } + + sendControllerInputPacket(); + return true; + } +}