am cd392822: Add USB MissleLauncher sample program

* commit 'cd39282253ec8a27eae1d580fbaa91a8f3c7c5ff':
  Add USB MissleLauncher sample program
This commit is contained in:
Mike Lockwood
2011-05-03 15:22:17 -07:00
committed by Android Git Automerger
12 changed files with 405 additions and 0 deletions

View File

@@ -177,6 +177,8 @@ development/samples/Spinner samples/${PLATFORM_NAME}/Spinner
development/samples/SpinnerTest samples/${PLATFORM_NAME}/SpinnerTest
development/samples/TicTacToeLib samples/${PLATFORM_NAME}/TicTacToeLib
development/samples/TicTacToeMain samples/${PLATFORM_NAME}/TicTacToeMain
development/samples/USB/MissileLauncher samples/${PLATFORM_NAME}/USB/MissileLauncher
development/samples/USB/AdbTest samples/${PLATFORM_NAME}/USB/AdbTest
development/samples/VoiceRecognitionService samples/${PLATFORM_NAME}/VoiceRecognitionService
development/samples/WeatherListWidget samples/${PLATFORM_NAME}/WeatherListWidget
development/apps/WidgetPreview samples/${PLATFORM_NAME}/WidgetPreview

1
samples/USB/Android.mk Normal file
View File

@@ -0,0 +1 @@
include $(call all-subdir-makefiles)

View File

@@ -0,0 +1,12 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := samples
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := MissileLauncher
LOCAL_SDK_VERSION := current
include $(BUILD_PACKAGE)

View File

@@ -0,0 +1,25 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.missilelauncher">
<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk android:minSdkVersion="12" />
<application>
<activity android:name="MissileLauncherActivity"
android:label="Missile Launcher"
android:screenOrientation="nosensor">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,13 @@
MissileLauncher is a simple program that controls Dream Cheeky USB missile launchers.
You control the left/right/up/down orientation of the launcher using the accelerometer.
Tilt the tablet to change the direction of the launcher.
Pressing the "Fire" button will fire one missile.
This program serves as an example of the following USB host features:
- filtering for multiple devices based on vendor and product IDs (see device_filter.xml)
- Sending control requests on endpoint zero that contain data
- Receiving packets on an interrupt endpoint using a thread that calls
UsbRequest.queue and UsbDeviceConnection.requestWait()

View File

@@ -0,0 +1,11 @@
<p>MissileLauncher is a simple program that controls Dream Cheeky USB missile launchers.
You control the left/right/up/down orientation of the launcher using the accelerometer.
Tilt the tablet to change the direction of the launcher. Pressing the <strong>Fire</strong> button will fire one missile.</p>
<p>This program serves as an example of the following USB host features:</p>
<ul>
<li>filtering for multiple devices based on vendor and product IDs (see <code>device_filter.xml</code>)</li>
<li>Sending control requests on endpoint zero that contain data</li>
<li>Receiving packets on an interrupt endpoint using a thread that calls
{@link android.hardware.usb.UsbRequest#queue queue()} and {@link android.hardware.usb.UsbDeviceConnection#requestWait requestWait()}.</li>
</p>

View File

@@ -0,0 +1,11 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Project target.
target=android-12

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<Button android:id="@+id/fire"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:layout_marginBottom="25dp"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:textSize="36sp"
android:text="@string/fire">
</Button>
</LinearLayout>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<string name="fire">Fire!</string>
</resources>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- vendor and product ID for Dream Cheeky USB Missle Launcher -->
<usb-device vendor-id="2689" product-id="1793" />
<!-- vendor and product ID for Dream Cheeky Wireless USB Missle Launcher -->
<usb-device vendor-id="2689" product-id="65281" />
</resources>

View File

@@ -0,0 +1,249 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.missilelauncher;
import java.nio.ByteBuffer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
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.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MissileLauncherActivity extends Activity
implements View.OnClickListener, Runnable {
private static final String TAG = "MissileLauncherActivity";
private Button mFire;
private UsbManager mUsbManager;
private UsbDevice mDevice;
private UsbDeviceConnection mConnection;
private UsbEndpoint mEndpointIntr;
private SensorManager mSensorManager;
private Sensor mGravitySensor;
// USB control commands
private static final int COMMAND_UP = 1;
private static final int COMMAND_DOWN = 2;
private static final int COMMAND_RIGHT = 4;
private static final int COMMAND_LEFT = 8;
private static final int COMMAND_FIRE = 16;
private static final int COMMAND_STOP = 32;
private static final int COMMAND_STATUS = 64;
// constants for accelerometer orientation
private static final int TILT_LEFT = 1;
private static final int TILT_RIGHT = 2;
private static final int TILT_UP = 4;
private static final int TILT_DOWN = 8;
private static final double THRESHOLD = 5.0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.launcher);
mFire = (Button)findViewById(R.id.fire);
mFire.setOnClickListener(this);
mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
mGravitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
}
@Override
public void onPause() {
super.onPause();
mSensorManager.unregisterListener(mGravityListener);
}
@Override
public void onResume() {
super.onResume();
mSensorManager.registerListener(mGravityListener, mGravitySensor,
SensorManager.SENSOR_DELAY_NORMAL);
Intent intent = getIntent();
Log.d(TAG, "intent: " + intent);
String action = intent.getAction();
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
setDevice(device);
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
if (mDevice != null && mDevice.equals(device)) {
setDevice(null);
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
private void setDevice(UsbDevice device) {
Log.d(TAG, "setDevice " + device);
if (device.getInterfaceCount() != 1) {
Log.e(TAG, "could not find interface");
return;
}
UsbInterface intf = device.getInterface(0);
// device should have one endpoint
if (intf.getEndpointCount() != 1) {
Log.e(TAG, "could not find endpoint");
return;
}
// endpoint should be of type interrupt
UsbEndpoint ep = intf.getEndpoint(0);
if (ep.getType() != UsbConstants.USB_ENDPOINT_XFER_INT) {
Log.e(TAG, "endpoint is not interrupt type");
return;
}
mDevice = device;
mEndpointIntr = ep;
if (device != null) {
UsbDeviceConnection connection = mUsbManager.openDevice(device);
if (connection != null && connection.claimInterface(intf, true)) {
Log.d(TAG, "open SUCCESS");
mConnection = connection;
Thread thread = new Thread(this);
thread.start();
} else {
Log.d(TAG, "open FAIL");
mConnection = null;
}
}
}
private void sendCommand(int control) {
synchronized (this) {
if (control != COMMAND_STATUS) {
Log.d(TAG, "sendMove " + control);
}
if (mConnection != null) {
byte[] message = new byte[1];
message[0] = (byte)control;
// Send command via a control request on endpoint zero
mConnection.controlTransfer(0x21, 0x9, 0x200, 0, message, message.length, 0);
}
}
}
public void onClick(View v) {
if (v == mFire) {
sendCommand(COMMAND_FIRE);
}
}
private int mLastValue = 0;
SensorEventListener mGravityListener = new SensorEventListener() {
public void onSensorChanged(SensorEvent event) {
// compute current tilt
int value = 0;
if (event.values[0] < -THRESHOLD) {
value += TILT_LEFT;
} else if (event.values[0] > THRESHOLD) {
value += TILT_RIGHT;
}
if (event.values[1] < -THRESHOLD) {
value += TILT_UP;
} else if (event.values[1] > THRESHOLD) {
value += TILT_DOWN;
}
if (value != mLastValue) {
mLastValue = value;
// send motion command if the tilt changed
switch (value) {
case TILT_LEFT:
sendCommand(COMMAND_LEFT);
break;
case TILT_RIGHT:
sendCommand(COMMAND_RIGHT);
break;
case TILT_UP:
sendCommand(COMMAND_UP);
break;
case TILT_DOWN:
sendCommand(COMMAND_DOWN);
break;
default:
sendCommand(COMMAND_STOP);
break;
}
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// ignore
}
};
@Override
public void run() {
ByteBuffer buffer = ByteBuffer.allocate(1);
UsbRequest request = new UsbRequest();
request.initialize(mConnection, mEndpointIntr);
byte status = -1;
while (true) {
// queue a request on the interrupt endpoint
request.queue(buffer, 1);
// send poll status command
sendCommand(COMMAND_STATUS);
// wait for status event
if (mConnection.requestWait() == request) {
byte newStatus = buffer.get(0);
if (newStatus != status) {
Log.d(TAG, "got status " + newStatus);
status = newStatus;
if ((status & COMMAND_FIRE) != 0) {
// stop firing
sendCommand(COMMAND_STOP);
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
} else {
Log.e(TAG, "requestWait failed, exiting");
break;
}
}
}
}

1
samples/USB/_index.html Normal file
View File

@@ -0,0 +1 @@
<p>A set of samples that demonstrate how to use various features of the USB APIs.</p>