Home | History | Annotate | Download | only in missilelauncher
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.missilelauncher;
     18 
     19 import java.nio.ByteBuffer;
     20 
     21 import android.app.Activity;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.hardware.Sensor;
     25 import android.hardware.SensorEvent;
     26 import android.hardware.SensorEventListener;
     27 import android.hardware.SensorManager;
     28 import android.hardware.usb.UsbConstants;
     29 import android.hardware.usb.UsbDevice;
     30 import android.hardware.usb.UsbDeviceConnection;
     31 import android.hardware.usb.UsbEndpoint;
     32 import android.hardware.usb.UsbInterface;
     33 import android.hardware.usb.UsbManager;
     34 import android.hardware.usb.UsbRequest;
     35 import android.os.Bundle;
     36 import android.util.Log;
     37 import android.view.View;
     38 import android.widget.Button;
     39 
     40 public class MissileLauncherActivity extends Activity
     41         implements View.OnClickListener, Runnable {
     42 
     43     private static final String TAG = "MissileLauncherActivity";
     44 
     45     private Button mFire;
     46     private UsbManager mUsbManager;
     47     private UsbDevice mDevice;
     48     private UsbDeviceConnection mConnection;
     49     private UsbEndpoint mEndpointIntr;
     50     private SensorManager mSensorManager;
     51     private Sensor mGravitySensor;
     52 
     53     // USB control commands
     54     private static final int COMMAND_UP = 1;
     55     private static final int COMMAND_DOWN = 2;
     56     private static final int COMMAND_RIGHT = 4;
     57     private static final int COMMAND_LEFT = 8;
     58     private static final int COMMAND_FIRE = 16;
     59     private static final int COMMAND_STOP = 32;
     60     private static final int COMMAND_STATUS = 64;
     61 
     62     // constants for accelerometer orientation
     63     private static final int TILT_LEFT = 1;
     64     private static final int TILT_RIGHT = 2;
     65     private static final int TILT_UP = 4;
     66     private static final int TILT_DOWN = 8;
     67     private static final double THRESHOLD = 5.0;
     68 
     69     @Override
     70     public void onCreate(Bundle savedInstanceState) {
     71         super.onCreate(savedInstanceState);
     72 
     73         setContentView(R.layout.launcher);
     74         mFire = (Button)findViewById(R.id.fire);
     75         mFire.setOnClickListener(this);
     76 
     77         mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
     78 
     79         mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
     80         mGravitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
     81     }
     82 
     83     @Override
     84     public void onPause() {
     85         super.onPause();
     86         mSensorManager.unregisterListener(mGravityListener);
     87     }
     88 
     89     @Override
     90     public void onResume() {
     91         super.onResume();
     92         mSensorManager.registerListener(mGravityListener, mGravitySensor,
     93                 SensorManager.SENSOR_DELAY_NORMAL);
     94 
     95         Intent intent = getIntent();
     96         Log.d(TAG, "intent: " + intent);
     97         String action = intent.getAction();
     98 
     99         UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
    100         if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
    101             setDevice(device);
    102         } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
    103             if (mDevice != null && mDevice.equals(device)) {
    104                 setDevice(null);
    105             }
    106         }
    107     }
    108 
    109     @Override
    110     public void onDestroy() {
    111         super.onDestroy();
    112     }
    113 
    114     private void setDevice(UsbDevice device) {
    115         Log.d(TAG, "setDevice " + device);
    116         if (device.getInterfaceCount() != 1) {
    117             Log.e(TAG, "could not find interface");
    118             return;
    119         }
    120         UsbInterface intf = device.getInterface(0);
    121         // device should have one endpoint
    122         if (intf.getEndpointCount() != 1) {
    123             Log.e(TAG, "could not find endpoint");
    124             return;
    125         }
    126         // endpoint should be of type interrupt
    127         UsbEndpoint ep = intf.getEndpoint(0);
    128         if (ep.getType() != UsbConstants.USB_ENDPOINT_XFER_INT) {
    129             Log.e(TAG, "endpoint is not interrupt type");
    130             return;
    131         }
    132         mDevice = device;
    133         mEndpointIntr = ep;
    134         if (device != null) {
    135             UsbDeviceConnection connection = mUsbManager.openDevice(device);
    136             if (connection != null && connection.claimInterface(intf, true)) {
    137                 Log.d(TAG, "open SUCCESS");
    138                 mConnection = connection;
    139                 Thread thread = new Thread(this);
    140                 thread.start();
    141 
    142             } else {
    143                 Log.d(TAG, "open FAIL");
    144                 mConnection = null;
    145             }
    146          }
    147     }
    148 
    149     private void sendCommand(int control) {
    150         synchronized (this) {
    151             if (control != COMMAND_STATUS) {
    152                 Log.d(TAG, "sendMove " + control);
    153             }
    154             if (mConnection != null) {
    155                 byte[] message = new byte[1];
    156                 message[0] = (byte)control;
    157                 // Send command via a control request on endpoint zero
    158                 mConnection.controlTransfer(0x21, 0x9, 0x200, 0, message, message.length, 0);
    159             }
    160         }
    161     }
    162 
    163     public void onClick(View v) {
    164         if (v == mFire) {
    165             sendCommand(COMMAND_FIRE);
    166         }
    167     }
    168 
    169     private int mLastValue = 0;
    170 
    171     SensorEventListener mGravityListener = new SensorEventListener() {
    172         public void onSensorChanged(SensorEvent event) {
    173 
    174             // compute current tilt
    175             int value = 0;
    176             if (event.values[0] < -THRESHOLD) {
    177                 value += TILT_LEFT;
    178             } else if (event.values[0] > THRESHOLD) {
    179                 value += TILT_RIGHT;
    180             }
    181             if (event.values[1] < -THRESHOLD) {
    182                 value += TILT_UP;
    183             } else if (event.values[1] > THRESHOLD) {
    184                 value += TILT_DOWN;
    185             }
    186 
    187             if (value != mLastValue) {
    188                 mLastValue = value;
    189                 // send motion command if the tilt changed
    190                 switch (value) {
    191                     case TILT_LEFT:
    192                         sendCommand(COMMAND_LEFT);
    193                         break;
    194                     case TILT_RIGHT:
    195                        sendCommand(COMMAND_RIGHT);
    196                         break;
    197                     case TILT_UP:
    198                         sendCommand(COMMAND_UP);
    199                         break;
    200                     case TILT_DOWN:
    201                         sendCommand(COMMAND_DOWN);
    202                         break;
    203                     default:
    204                         sendCommand(COMMAND_STOP);
    205                         break;
    206                 }
    207             }
    208         }
    209 
    210         public void onAccuracyChanged(Sensor sensor, int accuracy) {
    211             // ignore
    212         }
    213     };
    214 
    215     @Override
    216     public void run() {
    217         ByteBuffer buffer = ByteBuffer.allocate(1);
    218         UsbRequest request = new UsbRequest();
    219         request.initialize(mConnection, mEndpointIntr);
    220         byte status = -1;
    221         while (true) {
    222             // queue a request on the interrupt endpoint
    223             request.queue(buffer, 1);
    224             // send poll status command
    225             sendCommand(COMMAND_STATUS);
    226             // wait for status event
    227             if (mConnection.requestWait() == request) {
    228                 byte newStatus = buffer.get(0);
    229                 if (newStatus != status) {
    230                     Log.d(TAG, "got status " + newStatus);
    231                     status = newStatus;
    232                     if ((status & COMMAND_FIRE) != 0) {
    233                         // stop firing
    234                         sendCommand(COMMAND_STOP);
    235                     }
    236                 }
    237                 try {
    238                     Thread.sleep(100);
    239                 } catch (InterruptedException e) {
    240                 }
    241             } else {
    242                 Log.e(TAG, "requestWait failed, exiting");
    243                 break;
    244             }
    245         }
    246     }
    247 }
    248 
    249 
    250