Added support of USB PS Joystic

Esse commit está contido em:
Denis Shmyga
2012-09-14 17:40:34 +03:00
commit 3cdf9143a4
9 arquivos alterados com 1177 adições e 6 exclusões
@@ -1,6 +1,6 @@
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/AbsoluteLayout1"
android:id="@+id/ps3"
android:layout_width="match_parent"
android:layout_height="match_parent" >
@@ -57,8 +57,16 @@
style="?android:attr/buttonStyleSmall"
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_x="106dp"
android:layout_x="25dp"
android:layout_y="250dp"
android:text="Connect" />
<Button
android:id="@+id/ps3Button"
android:layout_width="116dp"
android:layout_height="wrap_content"
android:layout_x="128dp"
android:layout_y="251dp"
android:text="Connect PS3" />
</AbsoluteLayout>
@@ -0,0 +1,231 @@
package com.codeminders.ardrone;
import com.codeminders.ardrone.ARDrone;
import com.codeminders.ardrone.ARDrone.Animation;
import com.codeminders.ardrone.ARDrone.LED;
import com.codeminders.ardrone.ARDrone.VideoChannel;
import java.io.*;
import java.util.logging.Level;
/**
* This class represents one control mapping for a button and at the same
* time implements all control logic for button presses.
* @author normenhansen
*/
public class AssignableControl {
public enum Command {
TAKEOFF, LAND, TRIM, CLEAR_EMERGENCY, PLAY_ANIMATION, PLAY_LED, RESET,
VIDEO_CYCLE, FRONTAL_CAM, BOTTOM_CAM, BOTTOM_CAM_SMALL, FRONTAL_CAM_SMALL, TAKE_SNAPSHOT, RECORD_VIDEO
}
public enum ControllerButton {
PS, SELECT, START, LEFT_STICK, RIGHT_STICK, TRIANGLE, CIRCLE, CROSS, SQUARE, L1, L2, R1, R2
}
public enum ControllerAxis {
LEFT_X, LEFT_Y, RIGHT_X, RIGHT_Y
}
public enum DroneAxis {
FRONT_BACK, LEFT_RIGHT, UP_DOWN, ROTATE
}
private ControllerButton button;
private Command command;
private Animation anim;
private LED led;
private ControllerAxis controlAxis;
private DroneAxis droneAxis;
private float frequency;
private int duration;
private int delay;
private String prefString;
private static final VideoChannel[] VIDEO_CYCLE = {VideoChannel.HORIZONTAL_ONLY,
VideoChannel.VERTICAL_ONLY, VideoChannel.VERTICAL_IN_HORIZONTAL, VideoChannel.HORIZONTAL_IN_VERTICAL};
private int video_index = 0;
private File recFile;
/**
* Creates the control from a string that is stored in the java preferences of this app
* @param prefString
*/
public AssignableControl(String prefString) {
String[] strings = prefString.split("/");
if (strings.length < 3) {
throw new IllegalStateException("preference string malformed");
}
button = ControllerButton.valueOf(strings[0]);
command = Command.valueOf(strings[1]);
delay = Integer.parseInt(strings[2]);
switch (command) {
case PLAY_ANIMATION:
anim = Animation.valueOf(strings[3]);
duration = Integer.parseInt(strings[4]);
break;
case PLAY_LED:
led = LED.valueOf(strings[3]);
frequency = Float.parseFloat(strings[4]);
duration = Integer.parseInt(strings[5]);
break;
case RECORD_VIDEO:
case TAKE_SNAPSHOT:
try {
recFile = new File(strings[3].replace('?', File.separatorChar));
} catch (Exception e) {
}
break;
}
this.prefString = prefString;
}
public AssignableControl(ControllerButton button, LED led, int delay, float frequency, int duration) {
this.command = Command.PLAY_LED;
this.delay = delay;
this.led = led;
this.frequency = frequency;
this.duration = duration;
prefString = button.name() + "/" + command.name() + "/" + delay + "/" + led.name() + "/" + frequency + "/" + duration;
}
public AssignableControl(ControllerButton button, Animation anim, int delay, int duration) {
this.command = Command.PLAY_ANIMATION;
this.delay = delay;
this.anim = anim;
this.duration = duration;
prefString = button.name() + "/" + command.name() + "/" + delay + "/" + anim.name() + "/" + duration;
}
public AssignableControl(ControllerButton button, Command command, int delay, File file) {
this.command = command;
this.delay = delay;
this.recFile = file;
prefString = button.name() + "/" + command.name() + "/" + delay + "/" + file.getPath().replace(File.separatorChar, '?');
}
public AssignableControl(ControllerButton button, Command command, int delay) {
this.command = command;
this.delay = delay;
prefString = button.name() + "/" + command.name() + "/" + delay;
}
/**
* Sends the command to the supplied drone
* @param drone
* @throws IOException
*/
public void sendToDrone(final ARDrone drone) throws IOException {
switch (command) {
case PLAY_ANIMATION:
drone.playAnimation(anim, duration);
break;
case PLAY_LED:
drone.playLED(led, frequency, duration);
break;
case CLEAR_EMERGENCY:
drone.clearEmergencySignal();
break;
case TRIM:
drone.trim();
break;
case TAKEOFF:
drone.takeOff();
break;
case LAND:
drone.land();
break;
case RESET:
drone.clearEmergencySignal();
drone.trim();
break;
case VIDEO_CYCLE:
cycleVideoChannel(drone);
break;
case FRONTAL_CAM:
drone.selectVideoChannel(ARDrone.VideoChannel.VERTICAL_ONLY);
break;
case BOTTOM_CAM:
drone.selectVideoChannel(ARDrone.VideoChannel.HORIZONTAL_ONLY);
break;
case BOTTOM_CAM_SMALL:
drone.selectVideoChannel(ARDrone.VideoChannel.VERTICAL_IN_HORIZONTAL);
break;
case FRONTAL_CAM_SMALL:
drone.selectVideoChannel(ARDrone.VideoChannel.HORIZONTAL_IN_VERTICAL);
break;
case TAKE_SNAPSHOT:
break;
case RECORD_VIDEO:
break;
}
}
/**
* Used for VIDEO_CYCLE commands to cycle the video channel
* @param drone
* @throws IOException
*/
private void cycleVideoChannel(ARDrone drone) throws IOException {
if (++video_index == VIDEO_CYCLE.length) {
video_index = 0;
}
drone.selectVideoChannel(VIDEO_CYCLE[video_index]);
}
public ControllerButton getButton() {
return button;
}
public Command getCommand() {
return command;
}
public Animation getAnim() {
return anim;
}
public LED getLed() {
return led;
}
public ControllerAxis getControlAxis() {
return controlAxis;
}
public DroneAxis getDroneAxis() {
return droneAxis;
}
public float getFrequency() {
return frequency;
}
public int getDuration() {
return duration;
}
public int getDelay() {
return delay;
}
public File getRecFile() {
return recFile;
}
/**
* Gets the complete data of this object as a string for storing into java preferences
* @return
*/
public String getPrefString() {
return prefString;
}
}
@@ -0,0 +1,68 @@
package com.codeminders.ardrone;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import com.codeminders.ardrone.AssignableControl.ControllerButton;
public class ControlMap {
private HashMap<ControllerButton, List<AssignableControl>> map = new HashMap<ControllerButton, List<AssignableControl>>();
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
public ControlMap() {
loadMap();
}
public synchronized void sendCommand(ARDrone drone, ControllerButton button) throws IOException {
List<AssignableControl> commands = map.get(button);
if (commands == null) {
return;
}
for (Iterator<AssignableControl> it = commands.iterator(); it.hasNext();) {
final AssignableControl assignableCommand = it.next();
if (assignableCommand.getDelay() > 0) {
delayCommand(assignableCommand, drone);
} else {
assignableCommand.sendToDrone(drone);
}
}
}
/**
* Executes a command for a drone with its assigned delay using an Executor
* @param command
* @param drone
*/
private void delayCommand(final AssignableControl command, final ARDrone drone) {
exec.schedule(new Callable<Object>() {
@Override
public Object call() throws Exception {
command.sendToDrone(drone);
return null;
}
}, command.getDelay(), TimeUnit.MILLISECONDS);
}
private void loadMap() {
map.put(ControllerButton.PS, new LinkedList<AssignableControl>());
map.get(ControllerButton.PS).add(new AssignableControl(ControllerButton.PS, AssignableControl.Command.RESET, 0));
map.put(ControllerButton.START, new LinkedList<AssignableControl>());
map.get(ControllerButton.START).add(new AssignableControl(ControllerButton.START, AssignableControl.Command.TAKEOFF, 0));
map.put(ControllerButton.SELECT, new LinkedList<AssignableControl>());
map.get(ControllerButton.SELECT).add(new AssignableControl(ControllerButton.SELECT, AssignableControl.Command.LAND, 0));
map.put(ControllerButton.TRIANGLE, new LinkedList<AssignableControl>());
map.get(ControllerButton.TRIANGLE).add(new AssignableControl(ControllerButton.TRIANGLE, AssignableControl.Command.VIDEO_CYCLE, 0));
}
}
@@ -0,0 +1,155 @@
package com.codeminders.ardrone;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import com.codeminders.ardrone.AssignableControl.ControllerButton;
import com.codeminders.ardrone.controller.PS3Controller;
import com.codeminders.ardrone.controller.PS3ControllerState;
import com.codeminders.ardrone.controller.PS3ControllerStateChange;
public class ControllerThread extends Thread{
ARDrone drone;
PS3Controller controller;
private final ControlMap controlMap = new ControlMap();
private static float CONTROL_THRESHOLD = 0.5f;
private static final long READ_UPDATE_DELAY_MS = 5L;
private final AtomicBoolean flipSticks = new AtomicBoolean(false);
public ControllerThread(ARDrone drone, PS3Controller controller) {
super();
this.drone = drone;
this.controller = controller;
}
@Override
public void run() {
try
{
PS3ControllerState oldpad = null;
while(true)
{
PS3ControllerState pad = controller.read();
PS3ControllerStateChange pad_change = new PS3ControllerStateChange(oldpad, pad);
oldpad = pad;
if(pad_change.isStartChanged() && pad_change.isStart())
{
controlMap.sendCommand(drone, ControllerButton.START);
}
if(pad_change.isSelectChanged() && pad_change.isSelect())
{
controlMap.sendCommand(drone, ControllerButton.SELECT);
}
if(pad_change.isPSChanged() && pad_change.isPS())
{
controlMap.sendCommand(drone, ControllerButton.PS);
}
if(pad_change.isTriangleChanged() && pad_change.isTriangle())
{
controlMap.sendCommand(drone, ControllerButton.TRIANGLE);
}
if(pad_change.isCrossChanged() && pad_change.isCross())
{
controlMap.sendCommand(drone, ControllerButton.CROSS);
}
if(pad_change.isSquareChanged() && pad_change.isSquare())
{
controlMap.sendCommand(drone, ControllerButton.SQUARE);
}
if(pad_change.isCircleChanged() && pad_change.isCircle())
{
controlMap.sendCommand(drone, ControllerButton.CIRCLE);
}
if(pad_change.isL1Changed() && pad_change.isL1())
{
controlMap.sendCommand(drone, ControllerButton.L1);
}
if(pad_change.isR1Changed() && pad_change.isR1())
{
controlMap.sendCommand(drone, ControllerButton.R1);
}
if(pad_change.isL2Changed() && pad_change.isL2())
{
controlMap.sendCommand(drone, ControllerButton.L2);
}
if(pad_change.isR2Changed() && pad_change.isR2())
{
controlMap.sendCommand(drone, ControllerButton.R2);
}
int leftX = pad.getLeftJoystickX();
int leftY = pad.getLeftJoystickY();
int rightX = pad.getRightJoystickX();
int rightY = pad.getRightJoystickY();
float left_right_tilt = 0f;
float front_back_tilt = 0f;
float vertical_speed = 0f;
float angular_speed = 0f;
if(Math.abs(((float) leftX) / 128f) > CONTROL_THRESHOLD)
{
left_right_tilt = ((float) leftX) / 128f;
}
if(Math.abs(((float) leftY) / 128f) > CONTROL_THRESHOLD)
{
front_back_tilt = ((float) leftY) / 128f;
}
if(Math.abs(((float) rightX) / 128f) > CONTROL_THRESHOLD)
{
angular_speed = ((float) rightX) / 128f;
}
if(Math.abs(-1 * ((float) rightY) / 128f) > CONTROL_THRESHOLD)
{
vertical_speed = -1 * ((float) rightY) / 128f;
}
if(left_right_tilt != 0 || front_back_tilt != 0 || vertical_speed != 0 || angular_speed != 0)
{
if(flipSticks.get())
{
drone.move(angular_speed, -1 * vertical_speed, -1 * front_back_tilt, left_right_tilt);
}
else
{
drone.move(left_right_tilt, front_back_tilt, vertical_speed, angular_speed);
}
}
else
{
drone.hover();
}
try
{
Thread.sleep(READ_UPDATE_DELAY_MS);
}
catch(InterruptedException e)
{
// Ignore
}
}
} catch (IOException e) {
e.printStackTrace();
}
finally
{
try {
drone.disconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
@@ -3,11 +3,23 @@ package com.codeminders.ardrone;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Iterator;
import com.codeminders.ardrone.controller.PS3Controller;
import com.codeminders.ardrone.controller.SonyPS3Controller;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
@@ -25,9 +37,54 @@ public class MainActivity extends Activity implements DroneVideoListener {
ImageView display;
TextView state;
Button connectButton;
PS3Controller controller;
Button connectPs3Button;
UsbManager manager;
ControllerThread ctrThread;
private static final String ACTION_USB_PERMISSION = "com.access.device.USB_PERMISSION";
static MainActivity mainActivity;
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice deviceConnected = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (deviceConnected != null) {
if (SonyPS3Controller.isA(deviceConnected)) {
try {
controller = new SonyPS3Controller(deviceConnected, manager);
connectPs3Button.setEnabled(false);
connectPs3Button.setText("Connected");
// Start joystic reading thread
ctrThread = new ControllerThread(drone, controller);
ctrThread.setName("Controll Thread");
ctrThread.start();
} catch (Throwable e) {
connectPs3Button.setText("Error");
}
}
}
} else {
connectPs3Button.setText("Denied");
connectPs3Button.setEnabled(false);
}
}
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -52,9 +109,29 @@ public class MainActivity extends Activity implements DroneVideoListener {
state.setText("Connecting...");
(new DroneStarter()).execute(MainActivity.drone);
}
});
});
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
connectPs3Button = (Button) findViewById(R.id.ps3Button);
connectPs3Button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
UsbDevice device = null;
while (deviceIterator.hasNext()) {
device = deviceIterator.next();
break;
}
if (null != device) {
PendingIntent permissionIntent = PendingIntent.getBroadcast(mainActivity, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter permissionFilter = new IntentFilter(ACTION_USB_PERMISSION);
mainActivity.registerReceiver(usbReceiver, permissionFilter);
manager.requestPermission(device, permissionIntent);
}
}
});
}
@@ -197,7 +274,6 @@ private class DroneStarter extends AsyncTask<ARDrone, Integer, Boolean> {
drone.setCombinedYawMode(true);
return true;
} catch (Exception e) {
e.printStackTrace();
try {
drone.clearEmergencySignal();
drone.clearImageListeners();
@@ -205,7 +281,6 @@ private class DroneStarter extends AsyncTask<ARDrone, Integer, Boolean> {
drone.clearStatusChangeListeners();
drone.disconnect();
} catch (Exception e1) {
e1.printStackTrace();
}
}
@@ -0,0 +1,38 @@
package com.codeminders.ardrone.controller;
import java.io.IOException;
import android.hardware.usb.UsbDevice;
/**
* Base abstract class for supported PS3-compatible USB controllers
*
* @author lord
*
*/
public abstract class PS3Controller
{
UsbDevice dev;
public abstract void close() throws IOException;
public abstract PS3ControllerState read() throws IOException;
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("PS3Controller [");
builder.append("DeviceName=");
builder.append(dev.getDeviceName());
builder.append(", product=");
builder.append(dev.getProductId());
builder.append("]");
return builder.toString();
}
}
@@ -0,0 +1,242 @@
package com.codeminders.ardrone.controller;
/**
* Data structure describing state of generic PS-3 compatible game controller.
*
* @author lord
*/
public class PS3ControllerState
{
// buttons with pictures
protected boolean square;
protected boolean cross;
protected boolean circle;
protected boolean triangle;
// Front-side buttons
protected boolean L1;
protected boolean R1;
protected boolean L2;
protected boolean R2;
// square small "select" button
protected boolean select;
// triangular small "start" button
protected boolean start;
// Pressing on joysticks (button)
protected boolean leftJoystickPress;
protected boolean rightJoystickPress;
// PS3 button (sometimes labeled as Home on 3rd party models)
protected boolean PS;
// Direction pad (hatswitch)
protected int hatSwitchLeftRight;
protected int hatSwitchUpDown;
// Analog joysticks
protected int leftJoystickX;
protected int leftJoystickY;
protected int rightJoystickX;
protected int rightJoystickY;
public PS3ControllerState(boolean square, boolean cross, boolean circle, boolean triangle, boolean l1, boolean r1,
boolean l2, boolean r2, boolean select, boolean start, boolean leftJoystickPress,
boolean rightJoystickPress, boolean pS, int hatSwitchLeftRight, int hatSwitchUpDown, int leftJoystickX,
int leftJoystickY, int rightJoystickX, int rightJoystickY)
{
this.square = square;
this.cross = cross;
this.circle = circle;
this.triangle = triangle;
L1 = l1;
R1 = r1;
L2 = l2;
R2 = r2;
this.select = select;
this.start = start;
this.leftJoystickPress = leftJoystickPress;
this.rightJoystickPress = rightJoystickPress;
PS = pS;
this.hatSwitchLeftRight = hatSwitchLeftRight;
this.hatSwitchUpDown = hatSwitchUpDown;
this.leftJoystickX = leftJoystickX;
this.leftJoystickY = leftJoystickY;
this.rightJoystickX = rightJoystickX;
this.rightJoystickY = rightJoystickY;
}
public PS3ControllerState(PS3ControllerState o)
{
this.square = o.square;
this.cross = o.cross;
this.circle = o.circle;
this.triangle = o.triangle;
L1 = o.L1;
R1 = o.R1;
L2 = o.L2;
R2 = o.R2;
this.select = o.select;
this.start = o.start;
this.leftJoystickPress = o.leftJoystickPress;
this.rightJoystickPress = o.rightJoystickPress;
PS = o.PS;
this.hatSwitchLeftRight = o.hatSwitchLeftRight;
this.hatSwitchUpDown = o.hatSwitchUpDown;
this.leftJoystickX = o.leftJoystickX;
this.leftJoystickY = o.leftJoystickY;
this.rightJoystickX = o.rightJoystickX;
this.rightJoystickY = o.rightJoystickY;
}
public PS3ControllerState()
{
}
public int getHatSwitchLeftRight()
{
return hatSwitchLeftRight;
}
public int getHatSwitchUpDown()
{
return hatSwitchUpDown;
}
public int getLeftJoystickX()
{
return leftJoystickX;
}
public int getLeftJoystickY()
{
return leftJoystickY;
}
public int getRightJoystickX()
{
return rightJoystickX;
}
public int getRightJoystickY()
{
return rightJoystickY;
}
public boolean isCircle()
{
return circle;
}
public boolean isCross()
{
return cross;
}
public boolean isL1()
{
return L1;
}
public boolean isL2()
{
return L2;
}
public boolean isLeftJoystickPress()
{
return leftJoystickPress;
}
public boolean isPS()
{
return PS;
}
public boolean isR1()
{
return R1;
}
public boolean isR2()
{
return R2;
}
public boolean isRightJoystickPress()
{
return rightJoystickPress;
}
public boolean isSelect()
{
return select;
}
public boolean isSquare()
{
return square;
}
public boolean isStart()
{
return start;
}
public boolean isTriangle()
{
return triangle;
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("PS3ControllerState [square=");
builder.append(square);
builder.append(", cross=");
builder.append(cross);
builder.append(", circle=");
builder.append(circle);
builder.append(", triangle=");
builder.append(triangle);
builder.append(", L1=");
builder.append(L1);
builder.append(", R1=");
builder.append(R1);
builder.append(", L2=");
builder.append(L2);
builder.append(", R2=");
builder.append(R2);
builder.append(", select=");
builder.append(select);
builder.append(", start=");
builder.append(start);
builder.append(", rightJoystickPress=");
builder.append(rightJoystickPress);
builder.append(", leftJoystickPress=");
builder.append(leftJoystickPress);
builder.append(", PS=");
builder.append(PS);
builder.append(", hatSwitchLeftRight=");
builder.append(hatSwitchLeftRight);
builder.append(", hatSwitchUpDown=");
builder.append(hatSwitchUpDown);
builder.append(", leftJoystickX=");
builder.append(leftJoystickX);
builder.append(", leftJoystickY=");
builder.append(leftJoystickY);
builder.append(", rightJoystickX=");
builder.append(rightJoystickX);
builder.append(", rightJoystickY=");
builder.append(rightJoystickY);
builder.append("]");
return builder.toString();
}
}
@@ -0,0 +1,207 @@
package com.codeminders.ardrone.controller;
public class PS3ControllerStateChange extends PS3ControllerState
{
protected boolean squareChanged;
protected boolean crossChanged;
protected boolean circleChanged;
protected boolean triangleChanged;
protected boolean L1Changed;
protected boolean R1Changed;
protected boolean L2Changed;
protected boolean R2Changed;
protected boolean selectChanged;
protected boolean startChanged;
protected boolean leftJoystickPressChanged;
protected boolean rightJoystickPressChanged;
protected boolean PSChanged;
protected int hatSwitchLeftRightChange;
protected int hatSwitchUpDownChange;
protected int leftJoystickXChange;
protected int leftJoystickYChange;
protected int rightJoystickXChange;
protected int rightJoystickYChange;
// composite change flags
private boolean buttonStateChanged;
private boolean hatChanged;
private boolean leftJoystickChanged;
private boolean rightJoystickChanged;
private boolean joysticksChanged;
private boolean changed;
/**
*
* @param o Old state
* @param n New state
*/
public PS3ControllerStateChange(PS3ControllerState o, PS3ControllerState n)
{
super(n);
if(o==null)
o=n;
squareChanged = o.square != n.square;
crossChanged = o.cross != n.cross;
circleChanged = o.circle != n.circle;
triangleChanged = o.triangle != n.triangle;
L1Changed = o.L1 != n.L1;
R1Changed = o.R1 != n.R1;
L2Changed = o.L2 != n.L2;
R2Changed = o.R2 != n.R2;
selectChanged = o.select != n.select;
startChanged = o.start != n.start;
leftJoystickPressChanged = o.leftJoystickPress != n.leftJoystickPress;
rightJoystickPressChanged = o.rightJoystickPress != n.rightJoystickPress;
PSChanged = o.PS != n.PS;
hatSwitchLeftRightChange = n.hatSwitchLeftRight - o.hatSwitchLeftRight;
hatSwitchUpDownChange = n.hatSwitchUpDown - o.hatSwitchUpDown;
leftJoystickXChange = n.leftJoystickX - o.leftJoystickX;
leftJoystickYChange = n.leftJoystickY - o.leftJoystickY;
rightJoystickXChange = n.rightJoystickX - o.rightJoystickX;
rightJoystickYChange = n.rightJoystickY - o.rightJoystickY;
buttonStateChanged = squareChanged || crossChanged || circleChanged || triangleChanged || L1Changed
|| R1Changed || L2Changed || R2Changed || selectChanged || startChanged || leftJoystickPressChanged
|| rightJoystickPressChanged || PSChanged;
hatChanged = hatSwitchLeftRightChange != 0 || hatSwitchUpDownChange != 0;
leftJoystickChanged = leftJoystickXChange != 0 || leftJoystickYChange != 0;
rightJoystickChanged = rightJoystickXChange != 0 || rightJoystickYChange != 0;
joysticksChanged = leftJoystickChanged || rightJoystickChanged;
changed = joysticksChanged || hatChanged || buttonStateChanged;
}
public int getHatSwitchLeftRightChange()
{
return hatSwitchLeftRightChange;
}
public int getHatSwitchUpDownChange()
{
return hatSwitchUpDownChange;
}
public int getLeftJoystickXChange()
{
return leftJoystickXChange;
}
public int getLeftJoystickYChange()
{
return leftJoystickYChange;
}
public int getRightJoystickXChange()
{
return rightJoystickXChange;
}
public int getRightJoystickYChange()
{
return rightJoystickYChange;
}
public boolean isButtonStateChanged()
{
return buttonStateChanged;
}
public boolean isChanged()
{
return changed;
}
public boolean isCircleChanged()
{
return circleChanged;
}
public boolean isCrossChanged()
{
return crossChanged;
}
public boolean isHatChanged()
{
return hatChanged;
}
public boolean isJoysticksChanged()
{
return joysticksChanged;
}
public boolean isL1Changed()
{
return L1Changed;
}
public boolean isL2Changed()
{
return L2Changed;
}
public boolean isLeftJoystickChanged()
{
return leftJoystickChanged;
}
public boolean isLeftJoystickPressChanged()
{
return leftJoystickPressChanged;
}
public boolean isPSChanged()
{
return PSChanged;
}
public boolean isR1Changed()
{
return R1Changed;
}
public boolean isR2Changed()
{
return R2Changed;
}
public boolean isRightJoystickChanged()
{
return rightJoystickChanged;
}
public boolean isRightJoystickPressChanged()
{
return rightJoystickPressChanged;
}
public boolean isSelectChanged()
{
return selectChanged;
}
public boolean isSquareChanged()
{
return squareChanged;
}
public boolean isStartChanged()
{
return startChanged;
}
public boolean isTriangleChanged()
{
return triangleChanged;
}
}
@@ -0,0 +1,147 @@
package com.codeminders.ardrone.controller;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.BitSet;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbRequest;
import android.widget.TextView;
public class SonyPS3Controller extends PS3Controller
{
private static final int VENDOR_ID = 1356;
private static final int PRODUCT_ID = 616;
int bufferSize = 0;
ByteBuffer buffer;
UsbDeviceConnection readDataConnection = null;
UsbEndpoint usbEndpointRead = null;
UsbRequest request;
UsbRequest requestQueued;
public static boolean isA(UsbDevice dev)
{
return(dev.getVendorId() == VENDOR_ID && dev.getProductId() == PRODUCT_ID);
}
public SonyPS3Controller(UsbDevice dev, UsbManager manager) throws IOException
{
this.dev = dev;
readDataConnection = manager.openDevice(dev);
if (null == readDataConnection) {
throw new IOException("Failed to open connection to USB device");
}
UsbInterface usbInterfaceRead = dev.getInterface(0);
readDataConnection.claimInterface(usbInterfaceRead, true);
for(int i = 0; i < usbInterfaceRead.getEndpointCount(); i++) {
if (usbInterfaceRead.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN) {
usbEndpointRead = usbInterfaceRead.getEndpoint(i);
break;
}
}
if (null == usbEndpointRead) {
throw new IOException("Failed to find usb read endpoint");
}
bufferSize = usbEndpointRead.getMaxPacketSize();
buffer = ByteBuffer.allocate(bufferSize + 1);
request = new UsbRequest();
request.initialize(readDataConnection, usbEndpointRead);
}
private int joystickCoordConv(byte b)
{
int v = b < 0 ? b + 256 : b;
return(v - 128);
}
@Override
public PS3ControllerState read() throws IOException
{
PS3ControllerState res = null;
buffer.clear();
request.queue(buffer, bufferSize);
requestQueued = readDataConnection.requestWait();
if (request.equals(requestQueued))
{
byte[] buf = new byte[bufferSize + 1];
buffer.get(buf, 0, bufferSize);
BitSet bs = new BitSet(24);
for(int i = 0; i < 8; i++)
{
if((1 & (buf[2] >> i)) == 1)
bs.set(i);
}
for(int i = 0; i < 8; i++)
{
if((1 & (buf[3] >> i)) == 1)
bs.set(8 + i);
}
for(int i = 0; i < 8; i++)
{
if((1 & (buf[4] >> i)) == 1)
bs.set(16 + i);
}
int i = 0;
boolean select = bs.get(i++);
boolean leftJoystickPress = bs.get(i++);
boolean rightJoystickPress = bs.get(i++);
boolean start = bs.get(i++);
bs.get(i++);
bs.get(i++);
bs.get(i++);
bs.get(i++);
boolean L2 = bs.get(i++);
boolean R2 = bs.get(i++);
boolean R1 = bs.get(i++);
boolean L1 = bs.get(i++);
boolean triangle = bs.get(i++);
boolean circle = bs.get(i++);
boolean cross = bs.get(i++);
boolean square = bs.get(i++);
boolean PS = bs.get(i++);
int leftJoystickX = joystickCoordConv(buf[6]);
int leftJoystickY = joystickCoordConv(buf[7]);
int rightJoystickX = joystickCoordConv(buf[8]);
int rightJoystickY = joystickCoordConv(buf[9]);
int hatSwitchLeftRight = 0;
int hatSwitchUpDown = 0;
res = new PS3ControllerState(square, cross, circle, triangle, L1, R1, L2, R2, select, start,
leftJoystickPress, rightJoystickPress, PS, hatSwitchLeftRight, hatSwitchUpDown, leftJoystickX,
leftJoystickY, rightJoystickX, rightJoystickY);
}
return res;
}
@Override
public void close() throws IOException {
if (null != readDataConnection) {
readDataConnection.close();
}
}
}