QGCActivity.java 27.6 KB
Newer Older
Matej Frančeškin's avatar
Matej Frančeškin committed
1

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;
dogmaphobic's avatar
dogmaphobic committed
58 59 60 61 62

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

63
public class QGCActivity extends QtActivity
dogmaphobic's avatar
dogmaphobic committed
64
{
65
    public  static int BAD_PORT = 0;
66
    private static QGCActivity m_instance;
dogmaphobic's avatar
dogmaphobic committed
67 68 69 70 71 72 73 74
    private static UsbManager m_manager;    //  ANDROID USB HOST CLASS
    private static List<UsbSerialDriver> m_devices; //  LIST OF CURRENT DEVICES
    private static HashMap<Integer, UsbSerialDriver> m_openedDevices;   //  LIST OF OPENED DEVICES
    private static HashMap<Integer, UsbIoManager> m_ioManager;	//  THREADS FOR LISTENING FOR INCOMING DATA
    private static HashMap<Integer, Integer> m_userData;    //  CORRESPONDING USER DATA FOR OPENED DEVICES.  USED IN DISCONNECT CALLBACK
    //  USED TO DETECT WHEN A DEVICE HAS BEEN UNPLUGGED
    private BroadcastReceiver m_UsbReceiver = null;
    private final static ExecutorService m_Executor = Executors.newSingleThreadExecutor();
75
    private static final String TAG = "QGC_QGCActivity";
76
    private static PowerManager.WakeLock m_wl;
Don Gagne's avatar
Don Gagne committed
77 78 79 80 81 82 83 84
    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;
    private static HashMap<Integer, Integer>            _userDataHashByDeviceId;
    private static final String                         TAG = "QGC_QGCActivity";
    private static PowerManager.WakeLock                _wakeLock;
Matej Frančeškin's avatar
Matej Frančeškin committed
85 86
//    private static final String                         ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
    private static final String                         ACTION_USB_PERMISSION = "org.mavlink.qgroundcontrol.action.USB_PERMISSION";
Don Gagne's avatar
Don Gagne committed
87
    private static PendingIntent                        _usbPermissionIntent = null;
Matej Frančeškin's avatar
Matej Frančeškin committed
88
    private TaiSync                                     taiSync = null;
dogmaphobic's avatar
dogmaphobic committed
89

90 91
    public static Context m_context;

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

dogmaphobic's avatar
dogmaphobic committed
94 95 96 97
    private final static UsbIoManager.Listener m_Listener =
            new UsbIoManager.Listener()
            {
                @Override
Don Gagne's avatar
Don Gagne committed
98
                public void onRunError(Exception eA, int userData)
dogmaphobic's avatar
dogmaphobic committed
99
                {
dogmaphobic's avatar
dogmaphobic committed
100
                    Log.e(TAG, "onRunError Exception");
Don Gagne's avatar
Don Gagne committed
101
                    nativeDeviceException(userData, eA.getMessage());
dogmaphobic's avatar
dogmaphobic committed
102 103 104
                }

                @Override
Don Gagne's avatar
Don Gagne committed
105
                public void onNewData(final byte[] dataA, int userData)
dogmaphobic's avatar
dogmaphobic committed
106
                {
Don Gagne's avatar
Don Gagne committed
107
                    nativeDeviceNewData(userData, dataA);
dogmaphobic's avatar
dogmaphobic committed
108 109 110
                }
            };

Matej Frančeškin's avatar
Matej Frančeškin committed
111 112 113 114
    //  NATIVE C++ FUNCTION THAT WILL BE CALLED IF THE DEVICE IS UNPLUGGED
    private static native void nativeDeviceHasDisconnected(int userDataA);
    private static native void nativeDeviceException(int userDataA, String messageA);
    private static native void nativeDeviceNewData(int userDataA, byte[] dataA);
115 116 117 118 119 120
    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
121
                if (ACTION_USB_PERMISSION.equals(action)) {
122 123 124 125 126 127 128 129 130 131 132 133 134
                    UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        openAccessory(accessory);
                    }
                } else if( UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
                    UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
                    if (accessory != null) {
                        closeAccessory(accessory);
                    }
                }
            }
        };

Don Gagne's avatar
Don Gagne committed
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 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
    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()));
                        }
                    }
                }
            }
        };

    // Native C++ functions which connect back to QSerialPort code
    private static native void nativeDeviceHasDisconnected(int userData);
    private static native void nativeDeviceException(int userData, String messageA);
    private static native void nativeDeviceNewData(int userData, byte[] dataA);
dogmaphobic's avatar
dogmaphobic committed
188

189 190 191 192
    // Native C++ functions called to log output
    public static native void qgcLogDebug(String message);
    public static native void qgcLogWarning(String message);

Don Gagne's avatar
Don Gagne committed
193
    // QGCActivity singleton
194
    public QGCActivity()
dogmaphobic's avatar
dogmaphobic committed
195
    {
Don Gagne's avatar
Don Gagne committed
196 197 198 199
        _instance =                 this;
        _drivers =                  new ArrayList<UsbSerialDriver>();
        _userDataHashByDeviceId =   new HashMap<Integer, Integer>();
        m_ioManager =               new HashMap<Integer, UsbIoManager>();
dogmaphobic's avatar
dogmaphobic committed
200 201
    }

dogmaphobic's avatar
dogmaphobic committed
202
    @Override
Don Gagne's avatar
Don Gagne committed
203 204
    public void onCreate(Bundle savedInstanceState)
    {
dogmaphobic's avatar
dogmaphobic committed
205
        super.onCreate(savedInstanceState);
Don Gagne's avatar
Don Gagne committed
206 207 208 209
        PowerManager pm = (PowerManager)_instance.getSystemService(Context.POWER_SERVICE);
        _wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "QGroundControl");
        if(_wakeLock != null) {
            _wakeLock.acquire();
210 211 212 213
        } else {
            Log.i(TAG, "SCREEN_BRIGHT_WAKE_LOCK not acquired!!!");
        }
        m_instance.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Don Gagne's avatar
Don Gagne committed
214 215 216 217 218 219 220 221 222 223 224 225
        _instance.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

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

        //  Register for USB Detach and USB Permission intent
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        filter.addAction(ACTION_USB_PERMISSION);
        _instance.registerReceiver(_instance._usbReceiver, filter);

        // Create intent for usb permission request
        _usbPermissionIntent = PendingIntent.getBroadcast(_instance, 0, new Intent(ACTION_USB_PERMISSION), 0);
226 227 228 229 230 231

        if (m_manager == null) {
            try {
                m_manager = (UsbManager)m_instance.getSystemService(Context.USB_SERVICE);
                taiSync = new TaiSync();

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

                probeAccessories();
            } catch(Exception e) {
               Log.e(TAG, "Exception getCurrentDevices(): " + e);
            }
        }
dogmaphobic's avatar
dogmaphobic committed
241 242 243
    }

    @Override
Matej Frančeškin's avatar
Matej Frančeškin committed
244
    protected void onDestroy() {
245 246 247
    protected void onDestroy()
    {
        unregisterReceiver(mOpenAccessoryReceiver);
248
        try {
Don Gagne's avatar
Don Gagne committed
249 250
            if(_wakeLock != null) {
                _wakeLock.release();
251 252 253 254
            }
        } catch(Exception e) {
           Log.e(TAG, "Exception onDestroy()");
        }
dogmaphobic's avatar
dogmaphobic committed
255 256 257 258 259 260
        super.onDestroy();
    }

    public void onInit(int status) {
    }

Don Gagne's avatar
Don Gagne committed
261 262
    /// Incrementally updates the list of drivers connected to the device
    private static void updateCurrentDrivers()
dogmaphobic's avatar
dogmaphobic committed
263
    {
Don Gagne's avatar
Don Gagne committed
264 265
        List<UsbSerialDriver> currentDrivers = UsbSerialProber.findAllDevices(_usbManager);

Matej Frančeškin's avatar
Matej Frančeškin committed
266 267
        if (m_manager == null)
            m_manager = (UsbManager)m_instance.getSystemService(Context.USB_SERVICE);
dogmaphobic's avatar
dogmaphobic committed
268 269 270

        if (m_devices != null)
            m_devices.clear();
Don Gagne's avatar
Don Gagne committed
271 272 273 274 275 276 277 278 279
        // 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
280

Don Gagne's avatar
Don Gagne committed
281 282 283 284 285
            if (!found) {
                qgcLogDebug("Remove stale driver " + _drivers.get(i).getDevice().getDeviceName());
                _drivers.remove(i);
            }
        }
dogmaphobic's avatar
dogmaphobic committed
286

Don Gagne's avatar
Don Gagne committed
287 288 289 290 291 292 293 294 295
        // 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
296

Don Gagne's avatar
Don Gagne committed
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
            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
316 317
    }

Don Gagne's avatar
Don Gagne committed
318 319
    /// Returns array of device info for each unopened device.
    /// @return Device info format DeviceName:Company:ProductId:VendorId
dogmaphobic's avatar
dogmaphobic committed
320 321
    public static String[] availableDevicesInfo()
    {
Don Gagne's avatar
Don Gagne committed
322
        updateCurrentDrivers();
dogmaphobic's avatar
dogmaphobic committed
323

Don Gagne's avatar
Don Gagne committed
324
        if (_drivers.size() <= 0) {
dogmaphobic's avatar
dogmaphobic committed
325 326 327
            return null;
        }

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

Don Gagne's avatar
Don Gagne committed
330 331 332
        for (int i=0; i<_drivers.size(); i++) {
            String          deviceInfo;
            UsbSerialDriver driver = _drivers.get(i);
dogmaphobic's avatar
dogmaphobic committed
333

Matej Frančeškin's avatar
Matej Frančeškin committed
334
        //  CHECK FOR ALREADY OPENED DEVICES AND DON"T INCLUDE THEM IN THE COUNT
dogmaphobic's avatar
dogmaphobic committed
335 336 337 338 339 340
        for (iL=0; iL<m_devices.size(); iL++)
        {
            if (m_openedDevices.get(m_devices.get(iL).getDevice().getDeviceId()) != null)
            {
                countL++;
                break;
Don Gagne's avatar
Don Gagne committed
341 342
            if (driver.permissionStatus() != UsbSerialDriver.permissionStatusSuccess) {
                continue;
dogmaphobic's avatar
dogmaphobic committed
343 344
            }

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

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

Don Gagne's avatar
Don Gagne committed
349 350 351 352 353 354 355 356 357 358
            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
359 360
            }

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

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

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

Don Gagne's avatar
Don Gagne committed
372 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
    public static int open(Context parentContext, String deviceName, int userData)
dogmaphobic's avatar
dogmaphobic committed
379
    {
Don Gagne's avatar
Don Gagne committed
380
        int deviceId = BAD_DEVICE_ID;
dogmaphobic's avatar
dogmaphobic committed
381

382 383
        m_context = parentContext;

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

Don Gagne's avatar
Don Gagne committed
390 391 392
        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
393 394
        }

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

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

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

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

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

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

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

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

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

        if (driverL == null)
            return;

Don Gagne's avatar
Don Gagne committed
435
        UsbIoManager managerL = new UsbIoManager(driverL, m_Listener, _userDataHashByDeviceId.get(idA));
dogmaphobic's avatar
dogmaphobic committed
436 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
        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
464
        UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
465 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

        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
493
        UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
494 495 496 497 498 499 500

        if (driverL == null)
            return false;

        try
        {
            stopIoManager(idA);
Don Gagne's avatar
Don Gagne committed
501 502
            _userDataHashByDeviceId.remove(idA);
            driverL.setPermissionStatus(UsbSerialDriver.permissionStatusRequestRequired);
dogmaphobic's avatar
dogmaphobic committed
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
            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
528
        UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
529 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

        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
556 557
        for (UsbSerialDriver driver: _drivers) {
            if (driver.getDevice().getDeviceName() == nameA)
dogmaphobic's avatar
dogmaphobic committed
558 559 560 561 562 563 564 565
                return true;
        }

        return false;
    }

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

        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
591
            UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
592 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

            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
621
            UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
622 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

            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
652
            UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677

            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
678
        UsbSerialDriver driverL = _findDriverByDeviceId(idA);
dogmaphobic's avatar
dogmaphobic committed
679 680 681 682 683 684 685 686 687 688 689 690 691

        if (driverL == null)
            return -1;

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



Matej Frančeškin's avatar
Matej Frančeškin committed
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
    //////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Get the open usb serial driver for the given id
    //
    //  Args:  idA - ID number from the open command
    //
    //  Returns:  usb device driver
    //
    /////////////////////////////////////////////////////////////////////////////////////////////
    public static UsbSerialDriver getUsbSerialDriver(int idA)
    {
        return m_openedDevices.get(idA);
    }



dogmaphobic's avatar
dogmaphobic committed
708 709 710 711 712 713 714 715 716 717 718 719 720
    //////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Get the open usb serial driver for the given id
    //
    //  Args:  idA - ID number from the open command
    //
    //  Returns:  usb device driver
    //
    /////////////////////////////////////////////////////////////////////////////////////////////
    public static UsbSerialDriver getUsbSerialDriver(int idA)
    {
        return m_openedDevices.get(idA);
    }
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755

    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;
                    taiSync.open(m_manager.openAccessory(usbAccessory));
                }
            }
        } 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;
            }
        }
    }

    private void probeAccessories()
    {
Matej Frančeškin's avatar
Matej Frančeškin committed
756
        final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
           @Override
           public void run()
           {
//               Log.i(TAG, "probeAccessories");
               UsbAccessory[] accessories = m_manager.getAccessoryList();
               if (accessories != null) {
                   for (UsbAccessory usbAccessory : accessories) {
                       if (m_manager.hasPermission(usbAccessory)) {
                           openAccessory(usbAccessory);
                       } else {
                           Log.i(TAG, "requestPermission");
                           m_manager.requestPermission(usbAccessory, pendingIntent);
                       }
                   }
               }
           }
        }, 0, 3000);
    }
dogmaphobic's avatar
dogmaphobic committed
777 778
}