lqml/examples/meshtastic/cpp/connection/usb/usb_me.android.cpp
2024-07-15 17:36:22 +02:00

127 lines
3 KiB
C++

#include "usb_me.android.h"
#include "../connection.h"
#include "../../android_service/qtandroidservice_ro.h"
#include <QTimer>
#include <QtDebug>
#if (QT_VERSION < 0x060000)
#define JniObject QAndroidJniObject
#include <QtAndroid>
#include <QAndroidJniEnvironment>
#else
#define JniObject QJniObject
#include <QtCore/private/qandroidextras_p.h>
#endif
USB_ME* USB_ME::_this = nullptr;
static USB_ME* instance() {
return USB_ME::_this;
}
static void clearEventualExceptions() {
#if (QT_VERSION < 0x060000)
QAndroidJniEnvironment env;
#else
QJniEnvironment env;
#endif
if (env->ExceptionCheck()) {
env->ExceptionClear();
}
}
static JniObject androidService() {
#if (QT_VERSION < 0x060000)
return QtAndroid::androidService();
#else
return QtAndroidPrivate::service();
#endif
}
static void javaSetReady(JNIEnv*, jobject, jboolean jb) { // see Java
bool ready = (bool)jb;
instance()->ready = ready;
instance()->emitter->setReady(QVariant(QVariantList() << ready));
}
static void javaOnNewData(JNIEnv* env, jobject, jbyteArray jba) { // see Java
jbyte* jb = env->GetByteArrayElements(jba, NULL);
jsize js = env->GetArrayLength(jba);
QByteArray ba((char*)jb, js);
// run on Qt thread
QMetaObject::invokeMethod(
instance(),
"onNewData",
Q_ARG(QByteArray, ba));
env->ReleaseByteArrayElements(jba, jb, JNI_ABORT);
clearEventualExceptions();
}
USB_ME::USB_ME(QtAndroidService* service, Connection* _con) : emitter(service), con(_con) {
_this = this;
// ini JNI
JNINativeMethod methods[] {
{ "qtSetReady", "(Z)V", reinterpret_cast<void*>(javaSetReady) },
{ "qtOnNewData", "([B)V", reinterpret_cast<void*>(javaOnNewData) }
};
JniObject service2 = androidService();
#if (QT_VERSION < 0x060000)
QAndroidJniEnvironment env;
#else
QJniEnvironment env;
#endif
jclass jcl = env->GetObjectClass(service2.object<jobject>());
env->RegisterNatives(jcl, methods, sizeof(methods) / sizeof(methods[0]));
clearEventualExceptions();
// ini
timer.setSingleShot(true);
connect(&timer, &QTimer::timeout, this, &USB_ME::done);
}
void USB_ME::connectToRadio() {
JniObject service = androidService();
service.callMethod<void>(
"iniUsb",
"()V");
clearEventualExceptions();
}
void USB_ME::disconnect() {
// unused
}
void USB_ME::write2(const QByteArray& ba) {
if (ready) {
#if (QT_VERSION < 0x060000)
QAndroidJniEnvironment env;
#else
QJniEnvironment env;
#endif
jbyteArray jba = env->NewByteArray(ba.size());
env->SetByteArrayRegion(jba, 0, ba.size(), (jbyte*)ba.data());
JniObject service = androidService();
service.callMethod<void>(
"writeUsb",
"([B)V", jba);
clearEventualExceptions();
emitter->sendingDone();
} else {
qDebug() << "USB not ready: write()";
}
}
void USB_ME::read2() {
// unused
}
void USB_ME::onNewData(const QByteArray& data) { // see JNI
packets << data;
timer.start(1000); // assume receiving done after pause of 1 sec
}
void USB_ME::done() {
con->done(packets);
}