QGCActivity.java 25.9 KB
Newer Older
Matej Frančeškin's avatar
Matej Frančeškin committed
1
package org.mavlink.qgroundcontrol;
dogmaphobic's avatar
dogmaphobic committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

/* Copyright 2013 Google Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 * USA.
 *
 * Project home page: http://code.google.com/p/usb-serial-for-android/
 */
///////////////////////////////////////////////////////////////////////////////////////////
//  Written by: Mike Goza April 2014
//
//  These routines interface with the Android USB Host devices for serial port communication.
26
//  The code uses the usb-serial-for-android software library.  The QGCActivity class is the
dogmaphobic's avatar
dogmaphobic committed
27 28 29 30 31
//  interface to the C++ routines through jni calls.  Do not change the functions without also
//  changing the corresponding calls in the C++ routines or you will break the interface.
//
////////////////////////////////////////////////////////////////////////////////////////////

32
import java.util.ArrayList;
dogmaphobic's avatar
dogmaphobic committed
33 34
import java.util.HashMap;
import java.util.List;
Don Gagne's avatar
Don Gagne committed
35
import java.util.ArrayList;
dogmaphobic's avatar
dogmaphobic committed
36 37
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
38 39
import java.util.Timer;
import java.util.TimerTask;
dogmaphobic's avatar
dogmaphobic committed
40 41 42
import java.io.IOException;

import android.app.Activity;
Don Gagne's avatar
Don Gagne committed
43
import android.app.PendingIntent;
dogmaphobic's avatar
dogmaphobic committed
44 45 46 47
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
48 49 50 51
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
dogmaphobic's avatar
dogmaphobic committed
52 53
import android.widget.Toast;
import android.util.Log;
54
import android.os.PowerManager;
dogmaphobic's avatar
dogmaphobic committed
55
import android.os.Bundle;
56 57
import android.app.PendingIntent;
import android.view.WindowManager;
58 59
import android.os.Bundle;
import android.bluetooth.BluetoothDevice;
dogmaphobic's avatar
dogmaphobic committed
60 61 62 63 64

import com.hoho.android.usbserial.driver.*;
import org.qtproject.qt5.android.bindings.QtActivity;
import org.qtproject.qt5.android.bindings.QtApplication;

65
public class QGCActivity extends QtActivity
dogmaphobic's avatar
dogmaphobic committed
66
{
Don Gagne's avatar
Don Gagne committed
67 68 69 70 71
    public  static int                                  BAD_DEVICE_ID = 0;
    private static QGCActivity                          _instance = null;
    private static UsbManager                           _usbManager = null;
    private static List<UsbSerialDriver>                _drivers;
    private static HashMap<Integer, UsbIoManager>       m_ioManager;
Don Gagne's avatar
Don Gagne committed
72
    private static HashMap<Integer, Long>               _userDataHashByDeviceId;
Don Gagne's avatar
Don Gagne committed
73 74
    private static final String                         TAG = "QGC_QGCActivity";
    private static PowerManager.WakeLock                _wakeLock;
Matej Frančeškin's avatar
Matej Frančeškin committed
75
    private static final String                         ACTION_USB_PERMISSION = "org.mavlink.qgroundcontrol.action.USB_PERMISSION";
Don Gagne's avatar
Don Gagne committed
76
    private static PendingIntent                        _usbPermissionIntent = null;
Matej Frančeškin's avatar
Matej Frančeškin committed
77
    private TaiSync                                     taiSync = null;
78
    private Timer                                       probeAccessoriesTimer = null;
dogmaphobic's avatar
dogmaphobic committed
79

80 81
    public static Context m_context;

Don Gagne's avatar
Don Gagne committed
82 83
    private final static ExecutorService m_Executor = Executors.newSingleThreadExecutor();

dogmaphobic's avatar
dogmaphobic committed
84 85 86 87
    private final static UsbIoManager.Listener m_Listener =
            new UsbIoManager.Listener()
            {
                @Override
Don Gagne's avatar
Don Gagne committed
88
                public void onRunError(Exception eA, long userData)
dogmaphobic's avatar
dogmaphobic committed
89
                {
dogmaphobic's avatar
dogmaphobic committed
90
                    Log.e(TAG, "onRunError Exception");
Don Gagne's avatar
Don Gagne committed
91
                    nativeDeviceException(userData, eA.getMessage());
dogmaphobic's avatar
dogmaphobic committed
92 93 94
                }

                @Override
Don Gagne's avatar
Don Gagne committed
95
                public void onNewData(final byte[] dataA, long userData)
dogmaphobic's avatar
dogmaphobic committed
96
                {
Don Gagne's avatar
Don Gagne committed
97
                    nativeDeviceNewData(userData, dataA);
dogmaphobic's avatar
dogmaphobic committed
98 99 100
                }
            };

101 102 103 104 105 106
    private final BroadcastReceiver mOpenAccessoryReceiver =
        new BroadcastReceiver()
        {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
Matej Frančeškin's avatar
Matej Frančeškin committed
107
                if (ACTION_USB_PERMISSION.equals(action)) {
108
                    UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
109
                    if (accessory != null && intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
110 111
                        openAccessory(accessory);
                    }
112
                } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
113 114 115 116 117 118 119 120
                    UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
                    if (accessory != null) {
                        closeAccessory(accessory);
                    }
                }
            }
        };

Don Gagne's avatar
Don Gagne committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
    private static UsbSerialDriver _findDriverByDeviceId(int deviceId) {
        for (UsbSerialDriver driver: _drivers) {
            if (driver.getDevice().getDeviceId() == deviceId) {
                return driver;
            }
        }
        return null;
    }

    private static UsbSerialDriver _findDriverByDeviceName(String deviceName) {
        for (UsbSerialDriver driver: _drivers) {
            if (driver.getDevice().getDeviceName().equals(deviceName)) {
                return driver;
            }
        }
        return null;
    }

    private final static BroadcastReceiver _usbReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                Log.i(TAG, "BroadcastReceiver USB action " + action);

                if (ACTION_USB_PERMISSION.equals(action)) {
                    synchronized (_instance) {
                        UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                        if (device != null) {
                            UsbSerialDriver driver = _findDriverByDeviceId(device.getDeviceId());

                            if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                                qgcLogDebug("Permission granted to " + device.getDeviceName());
                                driver.setPermissionStatus(UsbSerialDriver.permissionStatusSuccess);
                            } else {
                                qgcLogDebug("Permission denied for " + device.getDeviceName());
                                driver.setPermissionStatus(UsbSerialDriver.permissionStatusDenied);
                            }
                        }
                    }
                } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                    UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (device != null) {
                        if (_userDataHashByDeviceId.containsKey(device.getDeviceId())) {
                            nativeDeviceHasDisconnected(_userDataHashByDeviceId.get(device.getDeviceId()));
                        }
                    }
                }
167 168 169 170 171 172

                try {
                    nativeUpdateAvailableJoysticks();
                } catch(Exception e) {
                    Log.e(TAG, "Exception nativeUpdateAvailableJoysticks()");
                }
Don Gagne's avatar
Don Gagne committed
173 174 175 176
            }
        };

    // Native C++ functions which connect back to QSerialPort code
Don Gagne's avatar
Don Gagne committed
177 178 179
    private static native void nativeDeviceHasDisconnected(long userData);
    private static native void nativeDeviceException(long userData, String messageA);
    private static native void nativeDeviceNewData(long userData, byte[] dataA);
180
    private static native void nativeUpdateAvailableJoysticks();
dogmaphobic's avatar
dogmaphobic committed
181

182 183 184 185
    // Native C++ functions called to log output
    public static native void qgcLogDebug(String message);
    public static native void qgcLogWarning(String message);

186
    public native void nativeInit();
187

Don Gagne's avatar
Don Gagne committed
188
    // QGCActivity singleton
189
    public QGCActivity()
dogmaphobic's avatar
dogmaphobic committed
190
    {
Don Gagne's avatar
Don Gagne committed
191 192
        _instance =                 this;
        _drivers =                  new ArrayList<UsbSerialDriver>();
Don Gagne's avatar
Don Gagne committed
193
        _userDataHashByDeviceId =   new HashMap<Integer, Long>();
Don Gagne's avatar
Don Gagne committed
194
        m_ioManager =               new HashMap<Integer, UsbIoManager>();
dogmaphobic's avatar
dogmaphobic committed
195 196
    }

dogmaphobic's avatar
dogmaphobic committed
197
    @Override
Don Gagne's avatar
Don Gagne committed
198 199
    public void onCreate(Bundle savedInstanceState)
    {
dogmaphobic's avatar
dogmaphobic committed
200
        super.onCreate(savedInstanceState);
201
        nativeInit();
Don Gagne's avatar
Don Gagne committed
202 203 204 205
        PowerManager pm = (PowerManager)_instance.getSystemService(Context.POWER_SERVICE);
        _wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "QGroundControl");
        if(_wakeLock != null) {
            _wakeLock.acquire();
206 207 208
        } else {
            Log.i(TAG, "SCREEN_BRIGHT_WAKE_LOCK not acquired!!!");
        }
Don Gagne's avatar
Don Gagne committed
209 210 211 212
        _instance.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        _usbManager = (UsbManager)_instance.getSystemService(Context.USB_SERVICE);

Matej Frančeškin's avatar
Matej Frančeškin committed
213
        // Register for USB Detach and USB Permission intent
Don Gagne's avatar
Don Gagne committed
214
        IntentFilter filter = new IntentFilter();
215
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
Don Gagne's avatar
Don Gagne committed
216 217
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        filter.addAction(ACTION_USB_PERMISSION);
218 219
        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
Don Gagne's avatar
Don Gagne committed
220 221 222 223
        _instance.registerReceiver(_instance._usbReceiver, filter);

        // Create intent for usb permission request
        _usbPermissionIntent = PendingIntent.getBroadcast(_instance, 0, new Intent(ACTION_USB_PERMISSION), 0);
224

Matej Frančeškin's avatar
Matej Frančeškin committed
225 226
        try {
            taiSync = new TaiSync();
227

Matej Frančeškin's avatar
Matej Frančeškin committed
228 229 230
            IntentFilter accessoryFilter = new IntentFilter(ACTION_USB_PERMISSION);
            filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
            registerReceiver(mOpenAccessoryReceiver, accessoryFilter);
231 232 233 234 235 236 237 238 239

            probeAccessoriesTimer = new Timer();
            probeAccessoriesTimer.schedule(new TimerTask() {
                @Override
                public void run()
                {
                    probeAccessories();
                }
            }, 0, 3000);
Matej Frančeškin's avatar
Matej Frančeškin committed
240 241
        } catch(Exception e) {
           Log.e(TAG, "Exception: " + e);
242
        }
dogmaphobic's avatar
dogmaphobic committed
243 244
    }

245 246 247 248 249 250 251 252 253
    @Override
    public void onResume() {
        super.onResume();

        // Plug in of USB ACCESSORY triggers only onResume event.
        // Then we scan if there is actually anything new
        probeAccessories();
    }

dogmaphobic's avatar
dogmaphobic committed
254
    @Override
255 256
    protected void onDestroy()
    {
257 258 259
        if (probeAccessoriesTimer != null) {
            probeAccessoriesTimer.cancel();
        }
260
        unregisterReceiver(mOpenAccessoryReceiver);
261
        try {
Don Gagne's avatar
Don Gagne committed
262 263
            if(_wakeLock != null) {
                _wakeLock.release();
264 265 266 267
            }
        } catch(Exception e) {
           Log.e(TAG, "Exception onDestroy()");
        }
dogmaphobic's avatar
dogmaphobic committed
268 269 270 271 272 273
        super.onDestroy();
    }

    public void onInit(int status) {
    }

Don Gagne's avatar
Don Gagne committed
274 275
    /// Incrementally updates the list of drivers connected to the device
    private static void updateCurrentDrivers()
dogmaphobic's avatar
dogmaphobic committed
276
    {
Don Gagne's avatar
Don Gagne committed
277 278 279 280 281 282 283 284 285 286 287
        List<UsbSerialDriver> currentDrivers = UsbSerialProber.findAllDevices(_usbManager);

        // Remove stale drivers
        for (int i=_drivers.size()-1; i>=0; i--) {
            boolean found = false;
            for (UsbSerialDriver currentDriver: currentDrivers) {
                if (_drivers.get(i).getDevice().getDeviceId() == currentDriver.getDevice().getDeviceId()) {
                    found = true;
                    break;
                }
            }
dogmaphobic's avatar
dogmaphobic committed
288

Don Gagne's avatar
Don Gagne committed
289 290 291 292 293
            if (!found) {
                qgcLogDebug("Remove stale driver " + _drivers.get(i).getDevice().getDeviceName());
                _drivers.remove(i);
            }
        }
dogmaphobic's avatar
dogmaphobic committed
294

Don Gagne's avatar
Don Gagne committed
295 296 297 298 299 300 301 302 303
        // Add new drivers
        for (int i=0; i<currentDrivers.size(); i++) {
            boolean found = false;
            for (int j=0; j<_drivers.size(); j++) {
                if (currentDrivers.get(i).getDevice().getDeviceId() == _drivers.get(j).getDevice().getDeviceId()) {
                    found = true;
                    break;
                }
            }
dogmaphobic's avatar
dogmaphobic committed
304

Don Gagne's avatar
Don Gagne committed
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
            if (!found) {
                UsbSerialDriver newDriver =     currentDrivers.get(i);
                UsbDevice       device =        newDriver.getDevice();
                String          deviceName =    device.getDeviceName();

                _drivers.add(newDriver);
                qgcLogDebug("Adding new driver " + deviceName);

                // Request permission if needed
                if (_usbManager.hasPermission(device)) {
                    qgcLogDebug("Already have permission to use device " + deviceName);
                    newDriver.setPermissionStatus(UsbSerialDriver.permissionStatusSuccess);
                } else {
                    qgcLogDebug("Requesting permission to use device " + deviceName);
                    newDriver.setPermissionStatus(UsbSerialDriver.permissionStatusRequested);
                    _usbManager.requestPermission(device, _usbPermissionIntent);
                }
            }
        }
dogmaphobic's avatar
dogmaphobic committed
324 325
    }

Don Gagne's avatar
Don Gagne committed
326 327
    /// Returns array of device info for each unopened device.
    /// @return Device info format DeviceName:Company:ProductId:VendorId
dogmaphobic's avatar
dogmaphobic committed
328 329
    public static String[] availableDevicesInfo()
    {
Don Gagne's avatar
Don Gagne committed
330
        updateCurrentDrivers();
dogmaphobic's avatar
dogmaphobic committed
331

Don Gagne's avatar
Don Gagne committed
332
        if (_drivers.size() <= 0) {
dogmaphobic's avatar
dogmaphobic committed
333 334 335
            return null;
        }

Don Gagne's avatar
Don Gagne committed
336
        List<String> deviceInfoList = new ArrayList<String>();
dogmaphobic's avatar
dogmaphobic committed
337

Don Gagne's avatar
Don Gagne committed
338 339 340
        for (int i=0; i<_drivers.size(); i++) {
            String          deviceInfo;
            UsbSerialDriver driver = _drivers.get(i);
dogmaphobic's avatar
dogmaphobic committed
341

Don Gagne's avatar
Don Gagne committed
342 343
            if (driver.permissionStatus() != UsbSerialDriver.permissionStatusSuccess) {
                continue;
dogmaphobic's avatar
dogmaphobic committed
344 345
            }

Don Gagne's avatar
Don Gagne committed
346
            UsbDevice device = driver.getDevice();
dogmaphobic's avatar
dogmaphobic committed
347

Don Gagne's avatar
Don Gagne committed
348
            deviceInfo = device.getDeviceName() + ":";
dogmaphobic's avatar
dogmaphobic committed
349

Don Gagne's avatar
Don Gagne committed
350 351 352 353 354 355 356 357 358 359
            if (driver instanceof FtdiSerialDriver) {
                deviceInfo = deviceInfo + "FTDI:";
            } else if (driver instanceof CdcAcmSerialDriver) {
                deviceInfo = deviceInfo + "Cdc Acm:";
            } else if (driver instanceof Cp2102SerialDriver) {
                deviceInfo = deviceInfo + "Cp2102:";
            } else if (driver instanceof ProlificSerialDriver) {
                deviceInfo = deviceInfo + "Prolific:";
            } else {
                deviceInfo = deviceInfo + "Unknown:";
dogmaphobic's avatar
dogmaphobic committed
360 361
            }

Don Gagne's avatar
Don Gagne committed
362 363
            deviceInfo = deviceInfo + Integer.toString(device.getProductId()) + ":";
            deviceInfo = deviceInfo + Integer.toString(device.getVendorId()) + ":";
dogmaphobic's avatar
dogmaphobic committed
364

Don Gagne's avatar
Don Gagne committed
365 366
            deviceInfoList.add(deviceInfo);
        }
dogmaphobic's avatar
dogmaphobic committed
367

Don Gagne's avatar
Don Gagne committed
368 369 370 371
        String[] rgDeviceInfo = new String[deviceInfoList.size()];
        for (int i=0; i<deviceInfoList.size(); i++) {
            rgDeviceInfo[i] = deviceInfoList.get(i);
        }
dogmaphobic's avatar
dogmaphobic committed
372

Don Gagne's avatar
Don Gagne committed
373 374 375 376 377 378
        return rgDeviceInfo;
    }

    /// Open the specified device
    ///     @param userData Data to associate with device and pass back through to native calls.
    /// @return Device id
Don Gagne's avatar
Don Gagne committed
379
    public static int open(Context parentContext, String deviceName, long userData)
dogmaphobic's avatar
dogmaphobic committed
380
    {
Don Gagne's avatar
Don Gagne committed
381
        int deviceId = BAD_DEVICE_ID;
dogmaphobic's avatar
dogmaphobic committed
382

383 384
        m_context = parentContext;

Don Gagne's avatar
Don Gagne committed
385 386 387 388
        UsbSerialDriver driver = _findDriverByDeviceName(deviceName);
        if (driver == null) {
            qgcLogWarning("Attempt to open unknown device " + deviceName);
            return BAD_DEVICE_ID;
dogmaphobic's avatar
dogmaphobic committed
389 390
        }

Don Gagne's avatar
Don Gagne committed
391 392 393
        if (driver.permissionStatus() != UsbSerialDriver.permissionStatusSuccess) {
            qgcLogWarning("Attempt to open device with incorrect permission status " + deviceName + " " + driver.permissionStatus());
            return BAD_DEVICE_ID;
dogmaphobic's avatar
dogmaphobic committed
394 395
        }

Don Gagne's avatar
Don Gagne committed
396 397
        UsbDevice device = driver.getDevice();
        deviceId = device.getDeviceId();
dogmaphobic's avatar
dogmaphobic committed
398

Don Gagne's avatar
Don Gagne committed
399 400 401 402
        try {
            driver.setConnection(_usbManager.openDevice(device));
            driver.open();
            driver.setPermissionStatus(UsbSerialDriver.permissionStatusOpen);
dogmaphobic's avatar
dogmaphobic committed
403

Don Gagne's avatar
Don Gagne committed
404
            _userDataHashByDeviceId.put(deviceId, userData);
dogmaphobic's avatar
dogmaphobic committed
405

Don Gagne's avatar
Don Gagne committed
406 407 408
            UsbIoManager ioManager = new UsbIoManager(driver, m_Listener, userData);
            m_ioManager.put(deviceId, ioManager);
            m_Executor.submit(ioManager);
dogmaphobic's avatar
dogmaphobic committed
409

Don Gagne's avatar
Don Gagne committed
410 411 412 413
            qgcLogDebug("Port open successful");
        } catch(IOException exA) {
            driver.setPermissionStatus(UsbSerialDriver.permissionStatusRequestRequired);
            _userDataHashByDeviceId.remove(deviceId);
dogmaphobic's avatar
dogmaphobic committed
414

Don Gagne's avatar
Don Gagne committed
415 416 417
            if(m_ioManager.get(deviceId) != null) {
                m_ioManager.get(deviceId).stop();
                m_ioManager.remove(deviceId);
dogmaphobic's avatar
dogmaphobic committed
418
            }
419
            qgcLogWarning("Port open exception: " + exA.getMessage());
Don Gagne's avatar
Don Gagne committed
420
            return BAD_DEVICE_ID;
dogmaphobic's avatar
dogmaphobic committed
421
        }
Don Gagne's avatar
Don Gagne committed
422 423

        return deviceId;
dogmaphobic's avatar
dogmaphobic committed
424 425 426 427 428 429 430
    }

    public static void startIoManager(int idA)
    {
        if (m_ioManager.get(idA) != null)
            return;

Don Gagne's avatar
Don Gagne committed
431
        UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
432 433 434 435

        if (driverL == null)
            return;

Don Gagne's avatar
Don Gagne committed
436
        UsbIoManager managerL = new UsbIoManager(driverL, m_Listener, _userDataHashByDeviceId.get(idA));
dogmaphobic's avatar
dogmaphobic committed
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
        m_ioManager.put(idA, managerL);
        m_Executor.submit(managerL);
    }

    public static void stopIoManager(int idA)
    {
        if(m_ioManager.get(idA) == null)
            return;

        m_ioManager.get(idA).stop();
        m_ioManager.remove(idA);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Sets the parameters on an open port.
    //
    //  Args:   idA - ID number from the open command
    //          baudRateA - Decimal value of the baud rate.  I.E. 9600, 57600, 115200, etc.
    //          dataBitsA - number of data bits.  Valid numbers are 5, 6, 7, 8
    //          stopBitsA - number of stop bits.  Valid numbers are 1, 2
    //          parityA - No Parity=0, Odd Parity=1, Even Parity=2
    //
    //  Returns:  T/F Success/Failure
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    public static boolean setParameters(int idA, int baudRateA, int dataBitsA, int stopBitsA, int parityA)
    {
Don Gagne's avatar
Don Gagne committed
465
        UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493

        if (driverL == null)
            return false;

        try
        {
            driverL.setParameters(baudRateA, dataBitsA, stopBitsA, parityA);
            return true;
        }
        catch(IOException eA)
        {
            return false;
        }
    }



    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Close the device.
    //
    //  Args:  idA - ID number from the open command
    //
    //  Returns:  T/F Success/Failure
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    public static boolean close(int idA)
    {
Don Gagne's avatar
Don Gagne committed
494
        UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
495 496 497 498 499 500 501

        if (driverL == null)
            return false;

        try
        {
            stopIoManager(idA);
Don Gagne's avatar
Don Gagne committed
502 503
            _userDataHashByDeviceId.remove(idA);
            driverL.setPermissionStatus(UsbSerialDriver.permissionStatusRequestRequired);
dogmaphobic's avatar
dogmaphobic committed
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
            driverL.close();

            return true;
        }
        catch(IOException eA)
        {
            return false;
        }
    }



    //////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Write data to the device.
    //
    //  Args:   idA - ID number from the open command
    //          sourceA - byte array of data to write
    //          timeoutMsecA - amount of time in milliseconds to wait for the write to occur
    //
    //  Returns:  number of bytes written
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    public static int write(int idA, byte[] sourceA, int timeoutMSecA)
    {
Don Gagne's avatar
Don Gagne committed
529
        UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556

        if (driverL == null)
            return 0;

        try
        {
            return driverL.write(sourceA, timeoutMSecA);
        }
        catch(IOException eA)
        {
            return 0;
        }
        /*
        UsbIoManager managerL = m_ioManager.get(idA);

        if(managerL != null)
        {
            managerL.writeAsync(sourceA);
            return sourceA.length;
        }
        else
            return 0;
        */
    }

    public static boolean isDeviceNameValid(String nameA)
    {
Don Gagne's avatar
Don Gagne committed
557 558
        for (UsbSerialDriver driver: _drivers) {
            if (driver.getDevice().getDeviceName() == nameA)
dogmaphobic's avatar
dogmaphobic committed
559 560 561 562 563 564 565 566
                return true;
        }

        return false;
    }

    public static boolean isDeviceNameOpen(String nameA)
    {
Don Gagne's avatar
Don Gagne committed
567 568
        for (UsbSerialDriver driverL: _drivers) {
            if (nameA.equals(driverL.getDevice().getDeviceName()) && driverL.permissionStatus() == UsbSerialDriver.permissionStatusOpen) {
dogmaphobic's avatar
dogmaphobic committed
569
                return true;
Don Gagne's avatar
Don Gagne committed
570
            }
dogmaphobic's avatar
dogmaphobic committed
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
        }

        return false;
    }



    /////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Set the Data Terminal Ready flag on the device
    //
    //  Args:   idA - ID number from the open command
    //          onA - on=T, off=F
    //
    //  Returns:  T/F Success/Failure
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public static boolean setDataTerminalReady(int idA, boolean onA)
    {
        try
        {
Don Gagne's avatar
Don Gagne committed
592
            UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621

            if (driverL == null)
                return false;

            driverL.setDTR(onA);
            return true;
        }
        catch(IOException eA)
        {
            return false;
        }
    }



    ////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Set the Request to Send flag
    //
    //  Args:   idA - ID number from the open command
    //          onA - on=T, off=F
    //
    //  Returns:  T/F Success/Failure
    //
    ////////////////////////////////////////////////////////////////////////////////////////////
    public static boolean setRequestToSend(int idA, boolean onA)
    {
        try
        {
Don Gagne's avatar
Don Gagne committed
622
            UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652

            if (driverL == null)
                return false;

            driverL.setRTS(onA);
            return true;
        }
        catch(IOException eA)
        {
            return false;
        }
    }



    ///////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Purge the hardware buffers based on the input and output flags
    //
    //  Args:   idA - ID number from the open command
    //          inputA - input buffer purge.  purge=T
    //          outputA - output buffer purge.  purge=T
    //
    //  Returns:  T/F Success/Failure
    //
    ///////////////////////////////////////////////////////////////////////////////////////////////
    public static boolean purgeBuffers(int idA, boolean inputA, boolean outputA)
    {
        try
        {
Don Gagne's avatar
Don Gagne committed
653
            UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678

            if (driverL == null)
                return false;

            return driverL.purgeHwBuffers(inputA, outputA);
        }
        catch(IOException eA)
        {
            return false;
        }
    }



    //////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Get the native device handle (file descriptor)
    //
    //  Args:   idA - ID number from the open command
    //
    //  Returns:  device handle
    //
    ///////////////////////////////////////////////////////////////////////////////////////////
    public static int getDeviceHandle(int idA)
    {
Don Gagne's avatar
Don Gagne committed
679
        UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
680 681 682 683 684 685 686 687 688 689 690

        if (driverL == null)
            return -1;

        UsbDeviceConnection connectL = driverL.getDeviceConnection();
        if (connectL == null)
            return -1;
        else
            return connectL.getFileDescriptor();
    }

691 692 693 694 695 696 697 698 699 700
    UsbAccessory openUsbAccessory = null;
    Object openAccessoryLock = new Object();

    private void openAccessory(UsbAccessory usbAccessory)
    {
        Log.i(TAG, "openAccessory: " + usbAccessory.getSerial());
        try {
            synchronized(openAccessoryLock) {
                if ((openUsbAccessory != null && !taiSync.isRunning()) || openUsbAccessory == null) {
                    openUsbAccessory = usbAccessory;
Matej Frančeškin's avatar
Matej Frančeškin committed
701
                    taiSync.open(_usbManager.openAccessory(usbAccessory));
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "openAccessory exception: " + e);
            taiSync.close();
            closeAccessory(openUsbAccessory);
        }
    }

    private void closeAccessory(UsbAccessory usbAccessory)
    {
        Log.i(TAG, "closeAccessory");

        synchronized(openAccessoryLock) {
            if (openUsbAccessory != null && usbAccessory == openUsbAccessory && taiSync.isRunning()) {
                taiSync.close();
                openUsbAccessory = null;
            }
        }
    }

723 724
    Object probeAccessoriesLock = new Object();

725 726
    private void probeAccessories()
    {
Matej Frančeškin's avatar
Matej Frančeškin committed
727
        final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
728 729
        new Thread(new Runnable() {
            public void run() {
730
                synchronized(openAccessoryLock) {
731
//                    Log.i(TAG, "probeAccessories");
732 733 734
                    UsbAccessory[] accessories = _usbManager.getAccessoryList();
                    if (accessories != null) {
                       for (UsbAccessory usbAccessory : accessories) {
735 736 737
                           if (usbAccessory == null) {
                               continue;
                           }
738 739 740
                           if (_usbManager.hasPermission(usbAccessory)) {
                               openAccessory(usbAccessory);
                           }
741
                       }
742
                    }
743 744 745
                }
            }
        }).start();
746
    }
dogmaphobic's avatar
dogmaphobic committed
747 748
}