Commit 9593ff3d authored by Don Gagne's avatar Don Gagne

Use FTDI driver provided by ftdicjip.com

- Fixes lost connections with FTDI radios
- Modified code to only test vendor id, all product ids are let through
- Modified code to pass log output through to C++ side
QGCLoggingCategory system
parent 81564629
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Everything --> <!-- Allow anything connected -->
<usb-device /> <usb-device />
<!-- 0x26AC / 0x11: PX4 FMU Pixhawk -->
<!--
<usb-device vendor-id="9900" product-id="17" />
-->
<!-- 0x0403 / 0x6001: FTDI FT232R UART -->
<!--
<usb-device vendor-id="1027" product-id="24577" />
-->
<!-- 0x0403 / 0x6015: FTDI FT231X -->
<!--
<usb-device vendor-id="1027" product-id="24597" />
-->
<!-- 0x2341 / Arduino -->
<!--
<usb-device vendor-id="9025" />
-->
<!-- 0x16C0 / 0x0483: Teensyduino -->
<!--
<usb-device vendor-id="5824" product-id="1155" />
-->
<!-- 0x10C4 / 0xEA60: CP210x UART Bridge -->
<!--
<usb-device vendor-id="4292" product-id="60000" />
-->
<!-- 0x067B / 0x2303: Prolific PL2303 -->
<!--
<usb-device vendor-id="1659" product-id="8963" />
-->
</resources> </resources>
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
* Project home page: http://code.google.com/p/usb-serial-for-android/ * Project home page: http://code.google.com/p/usb-serial-for-android/
*/ */
// IMPORTANT NOTE:
// This code has been modified from the original source. It now uses the FTDI driver provided by
// ftdichip.com to communicate with an FTDI device. The previous code did not work with all FTDI
// devices.
package com.hoho.android.usbserial.driver; package com.hoho.android.usbserial.driver;
import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbConstants;
...@@ -27,12 +31,16 @@ import android.hardware.usb.UsbEndpoint; ...@@ -27,12 +31,16 @@ import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbRequest; import android.hardware.usb.UsbRequest;
import android.util.Log; import android.util.Log;
import com.ftdi.j2xx.D2xxManager;
import com.ftdi.j2xx.FT_Device;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import org.qgroundcontrol.qgchelper.UsbDeviceJNI;
/** /**
* A {@link CommonUsbSerialDriver} implementation for a variety of FTDI devices * A {@link CommonUsbSerialDriver} implementation for a variety of FTDI devices
* <p> * <p>
...@@ -167,6 +175,8 @@ public class FtdiSerialDriver extends CommonUsbSerialDriver { ...@@ -167,6 +175,8 @@ public class FtdiSerialDriver extends CommonUsbSerialDriver {
*/ */
private static final boolean ENABLE_ASYNC_READS = false; private static final boolean ENABLE_ASYNC_READS = false;
FT_Device m_ftDev;
/** /**
* Filter FTDI status bytes from buffer * Filter FTDI status bytes from buffer
* @param src The source buffer (which contains status bytes) * @param src The source buffer (which contains status bytes)
...@@ -219,261 +229,140 @@ public class FtdiSerialDriver extends CommonUsbSerialDriver { ...@@ -219,261 +229,140 @@ public class FtdiSerialDriver extends CommonUsbSerialDriver {
@Override @Override
public void open() throws IOException { public void open() throws IOException {
boolean opened = false; D2xxManager ftD2xx = null;
try { try {
for (int i = 0; i < mDevice.getInterfaceCount(); i++) { ftD2xx = D2xxManager.getInstance(UsbDeviceJNI.m_context);
if (mConnection.claimInterface(mDevice.getInterface(i), true)) { } catch (D2xxManager.D2xxException ex) {
Log.d(TAG, "claimInterface " + i + " SUCCESS"); UsbDeviceJNI.qgcLogDebug("D2xxManager.getInstance threw exception: " + ex.getMessage());
} else { }
throw new IOException("Error claiming interface " + i);
} if (ftD2xx == null) {
} String errMsg = "Unable to retrieve D2xxManager instance.";
reset(); UsbDeviceJNI.qgcLogWarning(errMsg);
opened = true; throw new IOException(errMsg);
}
UsbDeviceJNI.qgcLogDebug("Opened D2xxManager");
int DevCount = ftD2xx.createDeviceInfoList(UsbDeviceJNI.m_context);
UsbDeviceJNI.qgcLogDebug("Found " + DevCount + " ftdi devices.");
if (DevCount < 1) {
throw new IOException("No FTDI Devices found");
}
m_ftDev = null;
try {
m_ftDev = ftD2xx.openByIndex(UsbDeviceJNI.m_context, 0);
} catch (NullPointerException e) {
UsbDeviceJNI.qgcLogDebug("ftD2xx.openByIndex exception: " + e.getMessage());
} finally { } finally {
if (!opened) { if (m_ftDev == null) {
close(); throw new IOException("No FTDI Devices found");
} }
} }
UsbDeviceJNI.qgcLogDebug("Opened FTDI device.");
} }
@Override @Override
public void close() { public void close() {
mConnection.close(); if (m_ftDev != null) {
try {
m_ftDev.close();
} catch (Exception e) {
UsbDeviceJNI.qgcLogWarning("close exception: " + e.getMessage());
}
m_ftDev = null;
}
} }
@Override @Override
public int read(byte[] dest, int timeoutMillis) throws IOException { public int read(byte[] dest, int timeoutMillis) throws IOException {
final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(0); int totalBytesRead = 0;
int bytesAvailable = m_ftDev.getQueueStatus();
if (ENABLE_ASYNC_READS) {
final int readAmt; if (bytesAvailable > 0) {
synchronized (mReadBufferLock) { bytesAvailable = Math.min(4096, bytesAvailable);
// mReadBuffer is only used for maximum read size. try {
readAmt = Math.min(dest.length, mReadBuffer.length); totalBytesRead = m_ftDev.read(dest, bytesAvailable, timeoutMillis);
} } catch (NullPointerException e) {
final String errorMsg = "Error reading: " + e.getMessage();
final UsbRequest request = new UsbRequest(); UsbDeviceJNI.qgcLogWarning(errorMsg);
request.initialize(mConnection, endpoint); throw new IOException(errorMsg, e);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, readAmt)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = mConnection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int payloadBytesRead = buf.position() - MODEM_STATUS_HEADER_LENGTH;
if (payloadBytesRead > 0) {
return payloadBytesRead;
} else {
return 0;
}
} else {
final int totalBytesRead;
synchronized (mReadBufferLock) {
final int readAmt = Math.min(dest.length, mReadBuffer.length);
totalBytesRead = mConnection.bulkTransfer(endpoint, mReadBuffer,
readAmt, timeoutMillis);
if (totalBytesRead < MODEM_STATUS_HEADER_LENGTH) {
throw new IOException("Expected at least " + MODEM_STATUS_HEADER_LENGTH + " bytes");
}
return filterStatusBytes(mReadBuffer, dest, totalBytesRead, endpoint.getMaxPacketSize());
} }
} }
return totalBytesRead;
} }
@Override @Override
public int write(byte[] src, int timeoutMillis) throws IOException { public int write(byte[] src, int timeoutMillis) throws IOException {
final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(1); try {
int offset = 0; m_ftDev.write(src);
return src.length;
while (offset < src.length) { } catch (Exception e) {
final int writeLength; UsbDeviceJNI.qgcLogWarning("Error writing: " + e.getMessage());
final int amtWritten;
synchronized (mWriteBufferLock) {
final byte[] writeBuffer;
writeLength = Math.min(src.length - offset, mWriteBuffer.length);
if (offset == 0) {
writeBuffer = src;
} else {
// bulkTransfer does not support offsets, make a copy.
System.arraycopy(src, offset, mWriteBuffer, 0, writeLength);
writeBuffer = mWriteBuffer;
}
amtWritten = mConnection.bulkTransfer(endpoint, writeBuffer, writeLength,
timeoutMillis);
}
if (amtWritten <= 0) {
throw new IOException("Error writing " + writeLength
+ " bytes at offset " + offset + " length=" + src.length);
}
//Log.d(TAG, "Wrote amtWritten=" + amtWritten + " attempted=" + writeLength);
offset += amtWritten;
} }
return offset; return 0;
} }
private int setBaudRate(int baudRate) throws IOException { private int setBaudRate(int baudRate) throws IOException {
long[] vals = convertBaudrate(baudRate); try {
long actualBaudrate = vals[0]; m_ftDev.setBaudRate(baudRate);
long index = vals[1]; return baudRate;
long value = vals[2]; } catch (Exception e) {
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, UsbDeviceJNI.qgcLogWarning("Error setting baud rate: " + e.getMessage());
SIO_SET_BAUD_RATE_REQUEST, (int) value, (int) index,
null, 0, USB_WRITE_TIMEOUT_MILLIS);
if (result != 0) {
throw new IOException("Setting baudrate failed: result=" + result);
} }
return (int) actualBaudrate; return 0;
} }
@Override @Override
public void setParameters(int baudRate, int dataBits, int stopBits, int parity) public void setParameters(int baudRate, int dataBits, int stopBits, int parity) throws IOException {
throws IOException {
setBaudRate(baudRate); setBaudRate(baudRate);
int config = dataBits; switch (dataBits) {
case 7:
switch (parity) { dataBits = D2xxManager.FT_DATA_BITS_7;
case PARITY_NONE: break;
config |= (0x00 << 8); case 8:
break; default:
case PARITY_ODD: dataBits = D2xxManager.FT_DATA_BITS_8;
config |= (0x01 << 8); break;
break;
case PARITY_EVEN:
config |= (0x02 << 8);
break;
case PARITY_MARK:
config |= (0x03 << 8);
break;
case PARITY_SPACE:
config |= (0x04 << 8);
break;
default:
throw new IllegalArgumentException("Unknown parity value: " + parity);
} }
switch (stopBits) { switch (stopBits) {
case STOPBITS_1: default:
config |= (0x00 << 11); case 0:
break; stopBits = D2xxManager.FT_STOP_BITS_1;
case STOPBITS_1_5: break;
config |= (0x01 << 11); case 1:
break; stopBits = D2xxManager.FT_STOP_BITS_2;
case STOPBITS_2: break;
config |= (0x02 << 11);
break;
default:
throw new IllegalArgumentException("Unknown stopBits value: " + stopBits);
}
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE,
SIO_SET_DATA_REQUEST, config, 0 /* index */,
null, 0, USB_WRITE_TIMEOUT_MILLIS);
if (result != 0) {
throw new IOException("Setting parameters failed: result=" + result);
} }
}
private long[] convertBaudrate(int baudrate) { switch (parity) {
// TODO(mikey): Braindead transcription of libfti method. Clean up, default:
// using more idiomatic Java where possible. case 0:
int divisor = 24000000 / baudrate; parity = D2xxManager.FT_PARITY_NONE;
int bestDivisor = 0; break;
int bestBaud = 0; case 1:
int bestBaudDiff = 0; parity = D2xxManager.FT_PARITY_ODD;
int fracCode[] = { break;
0, 3, 2, 4, 1, 5, 6, 7 case 2:
}; parity = D2xxManager.FT_PARITY_EVEN;
break;
for (int i = 0; i < 2; i++) { case 3:
int tryDivisor = divisor + i; parity = D2xxManager.FT_PARITY_MARK;
int baudEstimate; break;
int baudDiff; case 4:
parity = D2xxManager.FT_PARITY_SPACE;
if (tryDivisor <= 8) { break;
// Round up to minimum supported divisor
tryDivisor = 8;
} else if (mType != DeviceType.TYPE_AM && tryDivisor < 12) {
// BM doesn't support divisors 9 through 11 inclusive
tryDivisor = 12;
} else if (divisor < 16) {
// AM doesn't support divisors 9 through 15 inclusive
tryDivisor = 16;
} else {
if (mType == DeviceType.TYPE_AM) {
// TODO
} else {
if (tryDivisor > 0x1FFFF) {
// Round down to maximum supported divisor value (for
// BM)
tryDivisor = 0x1FFFF;
}
}
}
// Get estimated baud rate (to nearest integer)
baudEstimate = (24000000 + (tryDivisor / 2)) / tryDivisor;
// Get absolute difference from requested baud rate
if (baudEstimate < baudrate) {
baudDiff = baudrate - baudEstimate;
} else {
baudDiff = baudEstimate - baudrate;
}
if (i == 0 || baudDiff < bestBaudDiff) {
// Closest to requested baud rate so far
bestDivisor = tryDivisor;
bestBaud = baudEstimate;
bestBaudDiff = baudDiff;
if (baudDiff == 0) {
// Spot on! No point trying
break;
}
}
}
// Encode the best divisor value
long encodedDivisor = (bestDivisor >> 3) | (fracCode[bestDivisor & 7] << 14);
// Deal with special cases for encoded value
if (encodedDivisor == 1) {
encodedDivisor = 0; // 3000000 baud
} else if (encodedDivisor == 0x4001) {
encodedDivisor = 1; // 2000000 baud (BM only)
} }
// Split into "value" and "index" values try {
long value = encodedDivisor & 0xFFFF; m_ftDev.setDataCharacteristics((byte)dataBits, (byte)stopBits, (byte)parity);
long index; } catch (Exception e) {
if (mType == DeviceType.TYPE_2232C || mType == DeviceType.TYPE_2232H UsbDeviceJNI.qgcLogWarning("Error setDataCharacteristics: " + e.getMessage());
|| mType == DeviceType.TYPE_4232H) {
index = (encodedDivisor >> 8) & 0xffff;
index &= 0xFF00;
index |= 0 /* TODO mIndex */;
} else {
index = (encodedDivisor >> 16) & 0xffff;
} }
// Return the nearest baud rate
return new long[] {
bestBaud, index, value
};
} }
@Override @Override
public boolean getCD() throws IOException { public boolean getCD() throws IOException {
return false; return false;
...@@ -515,18 +404,22 @@ public class FtdiSerialDriver extends CommonUsbSerialDriver { ...@@ -515,18 +404,22 @@ public class FtdiSerialDriver extends CommonUsbSerialDriver {
@Override @Override
public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException { public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException {
if (purgeReadBuffers) { if (purgeReadBuffers) {
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, try {
SIO_RESET_PURGE_RX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS); m_ftDev.purge(D2xxManager.FT_PURGE_RX);
if (result != 0) { } catch (Exception e) {
throw new IOException("Flushing RX failed: result=" + result); String errMsg = "Error purgeHwBuffers(RX): "+ e.getMessage();
UsbDeviceJNI.qgcLogWarning(errMsg);
throw new IOException(errMsg);
} }
} }
if (purgeWriteBuffers) { if (purgeWriteBuffers) {
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, try {
SIO_RESET_PURGE_TX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS); m_ftDev.purge(D2xxManager.FT_PURGE_TX);
if (result != 0) { } catch (Exception e) {
throw new IOException("Flushing RX failed: result=" + result); String errMsg = "Error purgeHwBuffers(TX): " + e.getMessage();
UsbDeviceJNI.qgcLogWarning(errMsg);
throw new IOException(errMsg);
} }
} }
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
* Project home page: http://code.google.com/p/usb-serial-for-android/ * Project home page: http://code.google.com/p/usb-serial-for-android/
*/ */
// IMPORTANT NOTE:
// This source has been modified from the original such that testIfSupported only tests for a vendor id
// match. If that matches it allows all product ids through. This provides for better match on unknown boards.
package com.hoho.android.usbserial.driver; package com.hoho.android.usbserial.driver;
import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDevice;
...@@ -230,21 +234,7 @@ public enum UsbSerialProber { ...@@ -230,21 +234,7 @@ public enum UsbSerialProber {
* @param supportedDevices map of vendor IDs to product ID(s) * @param supportedDevices map of vendor IDs to product ID(s)
* @return {@code true} if supported * @return {@code true} if supported
*/ */
private static boolean testIfSupported(final UsbDevice usbDevice, private static boolean testIfSupported(final UsbDevice usbDevice, final Map<Integer, int[]> supportedDevices) {
final Map<Integer, int[]> supportedDevices) { return supportedDevices.containsKey(usbDevice.getVendorId());
final int[] supportedProducts = supportedDevices.get(
Integer.valueOf(usbDevice.getVendorId()));
if (supportedProducts == null) {
return false;
}
final int productId = usbDevice.getProductId();
for (int supportedProductId : supportedProducts) {
if (productId == supportedProductId) {
return true;
}
}
return false;
} }
} }
...@@ -68,6 +68,8 @@ public class UsbDeviceJNI extends QtActivity implements TextToSpeech.OnInitListe ...@@ -68,6 +68,8 @@ public class UsbDeviceJNI extends QtActivity implements TextToSpeech.OnInitListe
private static TextToSpeech m_tts; private static TextToSpeech m_tts;
private static PowerManager.WakeLock m_wl; private static PowerManager.WakeLock m_wl;
public static Context m_context;
private final static UsbIoManager.Listener m_Listener = private final static UsbIoManager.Listener m_Listener =
new UsbIoManager.Listener() new UsbIoManager.Listener()
{ {
...@@ -90,6 +92,10 @@ public class UsbDeviceJNI extends QtActivity implements TextToSpeech.OnInitListe ...@@ -90,6 +92,10 @@ public class UsbDeviceJNI extends QtActivity implements TextToSpeech.OnInitListe
private static native void nativeDeviceException(int userDataA, String messageA); private static native void nativeDeviceException(int userDataA, String messageA);
private static native void nativeDeviceNewData(int userDataA, byte[] dataA); private static native void nativeDeviceNewData(int userDataA, byte[] dataA);
// Native C++ functions called to log output
public static native void qgcLogDebug(String message);
public static native void qgcLogWarning(String message);
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Constructor. Only used once to create the initial instance for the static functions. // Constructor. Only used once to create the initial instance for the static functions.
...@@ -252,7 +258,7 @@ public class UsbDeviceJNI extends QtActivity implements TextToSpeech.OnInitListe ...@@ -252,7 +258,7 @@ public class UsbDeviceJNI extends QtActivity implements TextToSpeech.OnInitListe
tempL = tempL + Integer.toString(deviceL.getVendorId()) + ":"; tempL = tempL + Integer.toString(deviceL.getVendorId()) + ":";
listL[countL] = tempL; listL[countL] = tempL;
countL++; countL++;
//Log.i(TAG, "Found " + tempL); qgcLogDebug("Found " + tempL);
} }
} }
...@@ -273,11 +279,13 @@ public class UsbDeviceJNI extends QtActivity implements TextToSpeech.OnInitListe ...@@ -273,11 +279,13 @@ public class UsbDeviceJNI extends QtActivity implements TextToSpeech.OnInitListe
// calls like close(), read(), and write(). // calls like close(), read(), and write().
// //
///////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////
public static int open(String nameA, int userDataA) public static int open(Context parentContext, String nameA, int userDataA)
{ {
int idL = BAD_PORT; int idL = BAD_PORT;
Log.i(TAG, "Getting device list"); m_context = parentContext;
//qgcLogDebug("Getting device list");
if (!getCurrentDevices()) if (!getCurrentDevices())
return BAD_PORT; return BAD_PORT;
...@@ -366,7 +374,7 @@ public class UsbDeviceJNI extends QtActivity implements TextToSpeech.OnInitListe ...@@ -366,7 +374,7 @@ public class UsbDeviceJNI extends QtActivity implements TextToSpeech.OnInitListe
m_ioManager.remove(idL); m_ioManager.remove(idL);
} }
Log.e(TAG, "Port open exception"); qgcLogWarning("Port open exception: " + exA.getMessage());
return BAD_PORT; return BAD_PORT;
} }
} }
......
...@@ -46,10 +46,10 @@ ...@@ -46,10 +46,10 @@
#include <QtAndroidExtras/QtAndroidExtras> #include <QtAndroidExtras/QtAndroidExtras>
#include <QtAndroidExtras/QAndroidJniObject> #include <QtAndroidExtras/QAndroidJniObject>
#include <android/log.h>
#include "qserialport_android_p.h" #include "qserialport_android_p.h"
QGC_LOGGING_CATEGORY(AndroidSerialPortLog, "AndroidSerialPortLog")
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
#define BAD_PORT 0 #define BAD_PORT 0
...@@ -91,6 +91,30 @@ static void jniDeviceException(JNIEnv *envA, jobject thizA, jint userDataA, jstr ...@@ -91,6 +91,30 @@ static void jniDeviceException(JNIEnv *envA, jobject thizA, jint userDataA, jstr
} }
} }
static void jniLogDebug(JNIEnv *envA, jobject thizA, jstring messageA)
{
Q_UNUSED(thizA);
const char *stringL = envA->GetStringUTFChars(messageA, NULL);
QString logMessage = QString::fromUtf8(stringL);
envA->ReleaseStringUTFChars(messageA, stringL);
if (envA->ExceptionCheck())
envA->ExceptionClear();
qCDebug(AndroidSerialPortLog) << logMessage;
}
static void jniLogWarning(JNIEnv *envA, jobject thizA, jstring messageA)
{
Q_UNUSED(thizA);
const char *stringL = envA->GetStringUTFChars(messageA, NULL);
QString logMessage = QString::fromUtf8(stringL);
envA->ReleaseStringUTFChars(messageA, stringL);
if (envA->ExceptionCheck())
envA->ExceptionClear();
qWarning() << logMessage;
}
void cleanJavaException() void cleanJavaException()
{ {
QAndroidJniEnvironment env; QAndroidJniEnvironment env;
...@@ -116,13 +140,15 @@ QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q) ...@@ -116,13 +140,15 @@ QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
void QSerialPortPrivate::setNativeMethods(void) void QSerialPortPrivate::setNativeMethods(void)
{ {
__android_log_print(ANDROID_LOG_INFO, kJTag, "Registering Native Functions"); qCDebug(AndroidSerialPortLog) << "Registering Native Functions";
// REGISTER THE C++ FUNCTION WITH JNI // REGISTER THE C++ FUNCTION WITH JNI
JNINativeMethod javaMethods[] { JNINativeMethod javaMethods[] {
{"nativeDeviceHasDisconnected", "(I)V", reinterpret_cast<void *>(jniDeviceHasDisconnected)}, {"nativeDeviceHasDisconnected", "(I)V", reinterpret_cast<void *>(jniDeviceHasDisconnected)},
{"nativeDeviceNewData", "(I[B)V", reinterpret_cast<void *>(jniDeviceNewData)}, {"nativeDeviceNewData", "(I[B)V", reinterpret_cast<void *>(jniDeviceNewData)},
{"nativeDeviceException", "(ILjava/lang/String;)V", reinterpret_cast<void *>(jniDeviceException)} {"nativeDeviceException", "(ILjava/lang/String;)V", reinterpret_cast<void *>(jniDeviceException)},
{"qgcLogDebug", "(Ljava/lang/String;)V", reinterpret_cast<void *>(jniLogDebug)},
{"qgcLogWarning", "(Ljava/lang/String;)V", reinterpret_cast<void *>(jniLogWarning)}
}; };
QAndroidJniEnvironment jniEnv; QAndroidJniEnvironment jniEnv;
...@@ -133,36 +159,36 @@ void QSerialPortPrivate::setNativeMethods(void) ...@@ -133,36 +159,36 @@ void QSerialPortPrivate::setNativeMethods(void)
jclass objectClass = jniEnv->FindClass(kJniClassName); jclass objectClass = jniEnv->FindClass(kJniClassName);
if(!objectClass) { if(!objectClass) {
__android_log_print(ANDROID_LOG_ERROR, kJTag, "Couldn't find class: %s", kJniClassName); qWarning() << "Couldn't find class:" << kJniClassName;
return; return;
} }
jint val = jniEnv->RegisterNatives(objectClass, javaMethods, sizeof(javaMethods) / sizeof(javaMethods[0])); jint val = jniEnv->RegisterNatives(objectClass, javaMethods, sizeof(javaMethods) / sizeof(javaMethods[0]));
__android_log_print(ANDROID_LOG_INFO, kJTag, "Native Functions Registered"); if (val < 0) {
qWarning() << "Error registering methods: " << val;
} else {
qCDebug(AndroidSerialPortLog) << "Native Functions Registered";
}
if (jniEnv->ExceptionCheck()) { if (jniEnv->ExceptionCheck()) {
jniEnv->ExceptionDescribe(); jniEnv->ExceptionDescribe();
jniEnv->ExceptionClear(); jniEnv->ExceptionClear();
} }
if (val < 0) {
__android_log_print(ANDROID_LOG_ERROR, kJTag, "Error registering methods");
}
} }
bool QSerialPortPrivate::open(QIODevice::OpenMode mode) bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{ {
rwMode = mode; rwMode = mode;
__android_log_print(ANDROID_LOG_INFO, kJTag, "Opening %s", systemLocation.toLatin1().data()); qCDebug(AndroidSerialPortLog) << "Opening" << systemLocation.toLatin1().data();
__android_log_print(ANDROID_LOG_INFO, kJTag, "Calling Java Open");
QAndroidJniObject jnameL = QAndroidJniObject::fromString(systemLocation); QAndroidJniObject jnameL = QAndroidJniObject::fromString(systemLocation);
cleanJavaException(); cleanJavaException();
deviceId = QAndroidJniObject::callStaticMethod<jint>( deviceId = QAndroidJniObject::callStaticMethod<jint>(
kJniClassName, kJniClassName,
"open", "open",
"(Ljava/lang/String;I)I", "(Landroid/content/Context;Ljava/lang/String;I)I",
QtAndroid::androidActivity().object(),
jnameL.object<jstring>(), jnameL.object<jstring>(),
(jint)this); (jint)this);
cleanJavaException(); cleanJavaException();
...@@ -171,20 +197,11 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) ...@@ -171,20 +197,11 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
if (deviceId == BAD_PORT) if (deviceId == BAD_PORT)
{ {
__android_log_print(ANDROID_LOG_ERROR, kJTag, "Error opening %s", systemLocation.toLatin1().data()); qWarning() << "Error opening %s" << systemLocation.toLatin1().data();
q_ptr->setError(QSerialPort::DeviceNotFoundError); q_ptr->setError(QSerialPort::DeviceNotFoundError);
return false; return false;
} }
__android_log_print(ANDROID_LOG_INFO, kJTag, "Calling Java getDeviceHandle");
cleanJavaException();
descriptor = QAndroidJniObject::callStaticMethod<jint>(
kJniClassName,
"getDeviceHandle",
"(I)I",
deviceId);
cleanJavaException();
if (rwMode == QIODevice::WriteOnly) if (rwMode == QIODevice::WriteOnly)
stopReadThread(); stopReadThread();
...@@ -196,7 +213,7 @@ void QSerialPortPrivate::close() ...@@ -196,7 +213,7 @@ void QSerialPortPrivate::close()
if (deviceId == BAD_PORT) if (deviceId == BAD_PORT)
return; return;
__android_log_print(ANDROID_LOG_INFO, kJTag, "Closing %s", systemLocation.toLatin1().data()); qCDebug(AndroidSerialPortLog) << "Closing" << systemLocation.toLatin1().data();
cleanJavaException(); cleanJavaException();
jboolean resultL = QAndroidJniObject::callStaticMethod<jboolean>( jboolean resultL = QAndroidJniObject::callStaticMethod<jboolean>(
kJniClassName, kJniClassName,
......
...@@ -49,6 +49,9 @@ ...@@ -49,6 +49,9 @@
#include <QtCore/qstringlist.h> #include <QtCore/qstringlist.h>
#include <QtCore/qthread.h> #include <QtCore/qthread.h>
#include "QGCLoggingCategory.h"
Q_DECLARE_LOGGING_CATEGORY(AndroidSerialPortLog)
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment