Russian Qt Forum

Qt => Общие вопросы => Тема начата: Silver_swift от Август 21, 2014, 21:54



Название: Многострадальный QSerialPort на Android
Отправлено: Silver_swift от Август 21, 2014, 21:54
Доброго времени суток всем!

В рамках DIY-проекта нужно реализовать обмен данными планшета под управлением Android с arduino-подобной платой, важно только то, что обмен осуществляется через преобразователь usb-uart на чипе ftdi. В линуксе устройство распознается как ком-порт /dev/ttyUSB0. На десктопе для этой цели успешно использовался QSerialPort и там же на десктопе была написана и отлажена бОльшая часть кода, включающая обмены с платой.
При портировании на андроид выяснилось, что на моем планшете отсутствует FTDI драйвер и устройство /dev/ttyUSB0 просто не появляется в системе. В то же время существует несколько библиотек и приложений на джаве, которые эмулируют ком порт и работают с FTDI.

Теперь стою перед выбором между переписыванием приложения на Java и ковырянием в ядре операционки... Был бы весьма признателен тому, кто подскажет менее трудоемкое решение или хотя бы направление для его поиска.



Название: Re: Многострадальный QSerialPort на Android
Отправлено: kuzulis от Август 22, 2014, 10:19
Да, в Android нет никакого публичного интерфейса для доступа к последовательным портам (хотя, не исключаю, что в самом последнем Android это могли добавить в JAVA интерфейсы, хз).
Но есть вариант обойти это и использовать режим USB хоста. Я не знаю, нужны ли в этом случае драйвера (скорее всего нет). В этом случае не нужны права рута и это должно работать для перечня основных м/сх производителей портов (Prolific, Ftdi и пр.).

Я сам не пробовал, но в QtSerialPort есть патч, который добавляет эту функциональность (экспериментально и пр.): https://codereview.qt-project.org/#/c/84338/
можешь почитать там комменты с основными проблемами и прочее.  и даже попробовать это. Но ничего не гарантирую.


Название: Re: Многострадальный QSerialPort на Android
Отправлено: Silver_swift от Август 22, 2014, 11:42
Здорово, вроде даже что-то собирается. Дома надо будет проверить работоспособность. Спасибо за наводку! :) А то я начал готовиться к сборке ftdi драйвера из исходников ядра :)


Название: Re: Многострадальный QSerialPort на Android
Отправлено: Silver_swift от Август 26, 2014, 09:44
К сожалению не заработал QSerialPort. Аналогично не открывается устройство /dev/ttyUSB0. Примеры собираются, но не работают. Теперь планирую собрать драйвер из исходников по этой инструкции http://www.ftdichip.com/Support/Documents/TechnicalNotes/TN_132_Adding_FTDI_Devices_VCP_Driver_Support_to_Android.pdf

Да вот только вчера не разобрался какую версию ядра нужно выгрузить для моего Perfeo 7143. Это же китаец... Застрял там где не ожидал подвоха.


Название: Re: Многострадальный QSerialPort на Android
Отправлено: kuzulis от Август 26, 2014, 10:34
Цитировать
К сожалению не заработал QSerialPort.

А что возвращает QSerialPortInfo из того же патча?

По-идее в случае использования режима USB хоста необходимо просто открывать некое USB у-во, но не tty.
Хотя могу и ошибаться.

Цитировать
Аналогично не открывается устройство /dev/ttyUSB0

А оно есть само то, это у-во? По-идее его не должно быть, т.к. нет драйверов.


Название: Re: Многострадальный QSerialPort на Android
Отправлено: Silver_swift от Август 26, 2014, 14:20
Цитировать
А что возвращает QSerialPortInfo из того же патча?

availablePorts() возвращает пустой список.

Цитировать
По-идее в случае использования режима USB хоста необходимо просто открывать некое USB у-во, но не tty.

Как обычно называются такие устройства?

Порадовал ответ гугла на запрос
Цитировать
perfeo 7143 kernel source
Вообще ничего не найдено... Как собирать драйвер пока не ясно.


Название: Re: Многострадальный QSerialPort на Android
Отправлено: Bepec от Август 26, 2014, 14:43
В прямой путь к производителю с вопросом :D
Я так с панельником мучался мучался, потом написал производителю, они мне выслали дрова :D


Название: Re: Многострадальный QSerialPort на Android
Отправлено: kuzulis от Август 26, 2014, 15:59
Цитировать
availablePorts() возвращает пустой список.

Возможно нужно добавить VID/PID от твоего USB/Serial преобразователя в исходники QSerialPortInfo (если конечно их там уже нет).
Вот сюда вроде как: https://codereview.qt-project.org/#/c/84338/2/src/android-java/javasrc/src/com/hoho/android/usbserial/driver/UsbId.java


Цитировать
Как обычно называются такие устройства?

Я без понятия. QSerialPortInfo должен вернуть список с нужными именами.

Можешь глянуть эту инфу по использованию USB-Host режима в Android: https://github.com/mik3y/usb-serial-for-android
Суть в том, что в том патче для QtSerialPort используются C++ врапперы именно для этих Java исходников проекта "usb-serial-for-android".

В общем, почитай, поразбирайся и расскажи нам как там и что :).


Название: Re: Многострадальный QSerialPort на Android
Отправлено: Silver_swift от Август 27, 2014, 10:13
VID/PID моего преобразователя первые в UsbId.java :)

Обратил внимание на то, что при подключении преобразователя к планшету приложение FTDI terminal выкидывает окошко с предложением открыть устройство. Вроде как это делается в манифесте. Попробовал добавить в манифест как описано здесь: http://developer.android.com/guide/topics/connectivity/usb/host.html Моя программа таких окошек не выкидывает, устройств не видит.

Вот не знаю как бы отладить java методы. Посмотреть бы вызывается ли что-то вообще и что внутри происходит.


Название: Re: Многострадальный QSerialPort на Android
Отправлено: Silver_swift от Август 28, 2014, 20:12
Появилось время, начал тихонько ковырять QSerialPort.
Проблема в QSerialPortInfo:
Цитировать
QList<QSerialPortInfo> availablePortsByFiltersOfDevices()
{
    QList<QSerialPortInfo> serialPortInfoList;

    QAndroidJniObject resultL = QAndroidJniObject::callStaticObjectMethod(V_jniClassName,
                                                                          "availableDevicesInfo",
                                                                          "()[Ljava/lang/String;");
    if (!resultL.isValid())
        return serialPortInfoList;

........

Почему-то resultL не valid.

availableDevicesInfo в UsbDeviceJNI.java нашел, над кодом помедитировал, понять что происходит внутри не могу. System.out.print не работает, отладчик не цепляется... Если чего добьюсь отпишусь, если есть идеи прошу выссказывать :)


Название: Re: Многострадальный QSerialPort на Android
Отправлено: Bepec от Август 28, 2014, 23:28
Так сделай над кодом обертку, повызывай его, посмотри что не так :)


Название: Re: Многострадальный QSerialPort на Android
Отправлено: Silver_swift от Сентябрь 09, 2014, 13:04
Появилось время - опять мучаю планшет.

Удалось чуть продвинуться.
Во-первых, файлы с java классами из модуля qtserialport (https://codereview.qt-project.org/#/c/84338/) надо включать в проект приложения, в противном случае они не подцепятся, при этом не будет ни единого ворнинга, а программа будет выдавать странные результаты на любой вызов из UsbDeviceJNI.java.  

Далее, в файле qserialport_android.cpp строчка:

static char V_jniClassName[] {"org/qtproject/qtserialport/android/usbdevice/UsbDeviceJNI"};

категорически нуждается в операторе присваивания:
static char V_jniClassName[] = {"org/qtproject/qtserialport/android/usbdevice/UsbDeviceJNI"};

Ибо без него также не выдается ни единого ворнинга, но функции из UsbDeviceJNI.java вызываться по понятным причинам не будут.

Но далее самое интересное:

Код:
////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Constructor.  Only used once to create the initial instance for the static functions.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////
    public UsbDeviceJNI()
    {
        m_instance = this;
        m_openedDevices = new HashMap<Integer, UsbSerialDriver>();
        m_userData = new HashMap<Integer, Integer>();
        m_ioManager = new HashMap<Integer, UsbIoManager>();
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Find all current devices that match the device filter described in the androidmanifest.xml and the
    //  device_filter.xml
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////////
    private static boolean getCurrentDevices()
    {
        if (m_instance == null){
            Log.i("getCD", "null");
            return false;
        }

        if (m_manager == null)
            m_manager = (UsbManager)m_instance.getSystemService(Context.USB_SERVICE);

        if (m_devices != null)
            m_devices.clear();

        m_devices = UsbSerialProber.findAllDevices(m_manager);

        return true;
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  List all available devices that are not already open.  It returns the serial port info
    //  in a : separated string array.  Each string entry consists of the following:
    //
    //  DeviceName:Company:ProductId:VendorId
    //
    /////////////////////////////////////////////////////////////////////////////////////////////////////////
    public static String[] availableDevicesInfo()
    {


        //  GET THE LIST OF CURRENT DEVICES
        if (!getCurrentDevices())
            return null;

        //  MAKE SURE WE HAVE ENTRIES
        if (m_devices.size() <= 0)
            return null;

        if (m_openedDevices == null)
            return null;

        int countL = 0;
        int iL;

        //  CHECK FOR ALREADY OPENED DEVICES AND DON"T INCLUDE THEM IN THE COUNT
        for (iL=0; iL<m_devices.size(); iL++)
        {
            if (m_openedDevices.get(m_devices.get(iL).getDevice().getDeviceId()) != null)
            {
                countL++;
                break;
            }
        }

        if (m_devices.size() - countL <= 0)
            return null;

        String[] listL = new String[m_devices.size() - countL];
        UsbSerialDriver driverL;
        String tempL;

        //  GET THE DATA ON THE INDIVIDUAL DEVICES SKIPPING THE ONES THAT ARE ALREADY OPEN
        countL = 0;
        for (iL=0; iL<m_devices.size(); iL++)
        {
            driverL = m_devices.get(iL);
            if (m_openedDevices.get(driverL.getDevice().getDeviceId()) == null)
            {
                UsbDevice deviceL = driverL.getDevice();
                tempL = deviceL.getDeviceName() + ":";

                if (driverL instanceof FtdiSerialDriver)
                    tempL = tempL + "FTDI:";
                else if (driverL instanceof CdcAcmSerialDriver)
                    tempL = tempL + "Cdc Acm:";
                else if (driverL instanceof Cp2102SerialDriver)
                    tempL = tempL + "Cp2102:";
                else if (driverL instanceof ProlificSerialDriver)
                    tempL = tempL + "Prolific:";
                else
                    tempL = tempL + "Unknown:";

                tempL = tempL + Integer.toString(deviceL.getProductId()) + ":";
                tempL = tempL + Integer.toString(deviceL.getVendorId()) + ":";
                listL[countL] = tempL;
                countL++;
            }
        }

        return listL;
    }

Метод QList<QSerialPortInfo> QSerialPortInfo::availablePortsByFiltersOfDevices() вызывает метод UsbDeviceJNI::availableDevicesInfo(), который объявлен как  public static. Однако, во внутренностях этого метода выполняется проверка условия m_instance == null, чуть выше видно, что m_instance присваивается значение this в конструкторе. На кой хрен вообще делать такую проверку в статическом методе? В общем, потихоньку вспоминаю java.

Тем не менее некоторый прогресс на лицо, после добавления в манифест пары строк (по инструкции отсюда https://github.com/mik3y/usb-serial-for-android/blob/master/README.md) при подключении FTDI преобразователя приложение предлагает открыть устройство. Вчера не сразу сообразил как правильно подцепить манифест к проекту (QtCreator -> Проекты -> Конфигурация установки), чтобы его при сборке не заменяло на дефолтный.

Был бы признателен за советы по отладке сего безобразия и моральную поддержку :)


Название: Re: Многострадальный QSerialPort на Android
Отправлено: Silver_swift от Сентябрь 24, 2014, 13:58
Забыл отписаться :) В итоге на следующий день плюнул на QSerialPort и сделал обмены по wi-fi на сокетах.


Название: Re: Многострадальный QSerialPort на Android
Отправлено: marselus от Ноябрь 06, 2014, 02:19
Доброго времени суток!
Есть приложение Qt которое использует QtSerialPort. Необходимо его портировать на Android.
QtSerialPort __git://gitorious.org/qt/qtserialport.git c применением патча __https://codereview.qt-project.org/#/c/84338/
Собирается без проблем. Под MinGW32 проект запускается отлично. А при попытке собрать для Android выдает ошибку:

Код:
:-1: ошибка: Unknown module(s) in QT: serialport


Название: Re: Многострадальный QSerialPort на Android
Отправлено: kuzulis от Ноябрь 06, 2014, 11:18
Цитировать
:-1: ошибка: Unknown module(s) in QT: serialport
Не нужно обращать внимание на него, должно собираться и с ней.
Хотя, сейчас помочь ничем не могу т.к. уже с Андройдом завязал давно.
Тем более, что портировать QtSerialPort на Андройд - не имеет пока смысла,
т.к. тот патч не работает до конца (как я понял) и его применение
ограничено только парой USB/Serial конвертеров определенных вендоров.


Название: Re: Многострадальный QSerialPort на Android
Отправлено: marselus от Ноябрь 06, 2014, 12:24
Цитировать
Цитировать
Цитировать
:-1: ошибка: Unknown module(s) in QT: serialport
Не нужно обращать внимание на него, должно собираться и с ней.
А вот не собирается
Код:
12:20:00: Выполняются этапы для проекта untitled...
12:20:00: Настройки не изменились, этап qmake пропускается.
12:20:00: Запускается: «C:\Qt\Qt5.4.0\Tools\mingw482_32\bin\mingw32-make.exe»
C:\Qt\Qt5.4.0\5.4\android_armv7\bin\qmake.exe -spec android-g++ -o Makefile ..\untitled\untitled.pro
Project ERROR: Unknown module(s) in QT: serialport
Makefile:192: recipe for target 'Makefile' failed
mingw32-make: *** [Makefile] Error 3
12:20:00: Процесс «C:\Qt\Qt5.4.0\Tools\mingw482_32\bin\mingw32-make.exe» завершился с кодом 2.
Ошибка при сборке/установке проекта untitled (комплект: Android для armeabi-v7a (GCC 4.9, Qt 5.4.0) )
Во время выполнения этапа «Сборка»
12:20:00: Прошло времени: 00:01.
начинаю подозревать что решения под Qt Android для SerialPort нет и не предвидится в ближайшее время.

Есть рабочее решение __https://code.google.com/p/usb-serial-for-android/ для Java


Название: Re: Многострадальный QSerialPort на Android
Отправлено: kuzulis от Ноябрь 06, 2014, 14:38
Цитата: marselus
А вот не собирается
Цитировать
Makefile:192: recipe for target 'Makefile' failed
mingw32-make: *** [Makefile] Error 3
12:20:00: Процесс «C:\Qt\Qt5.4.0\Tools\mingw482_32\bin\mingw32-make.exe» завершился с кодом 2.
Замени в QtCreator для "clean" и "build" шагов утилиту "mingw32-make.exe" на "make.exe", которую возьми из Android SDK.

Цитировать
начинаю подозревать что решения под Qt Android для SerialPort нет и не предвидится в ближайшее время.
Оно есть и сейчас - использование root и/или при создании прошивки подшаманить с правами на tty устройства.
Но оно, конечно, не для всех случаев.

Цитировать
Есть рабочее решение __https://code.google.com/p/usb-serial-for-android/ для Java
Ага, но оно даже не для всех USB serial ports.

PS: Если есть желание доделать (допортировать) "usb-serial-for-android" для QtSerialPort - то вперед. :)


Название: Re: Многострадальный QSerialPort на Android
Отправлено: marselus от Ноябрь 06, 2014, 23:41
usb-serial-for-android поддерживает FT232RL(FTDI), CP2102(Silicon Lab), PL2303(PROLIFIC) __http://we.easyelectronics.ru/alexhi/programma-tcp_serport-redirektor-tcp-com-port-pod-android.html
Опять же все реализовано на Java.
Можно попробовать JNI, но это опять же определенные сложности.
Цитировать
Замени в QtCreator для "clean" и "build" шагов утилиту "mingw32-make.exe" на "make.exe", которую возьми из Android SDK.
Android NDK? Взял от туда. Но ни каких изменений. видимо для комплекта android_armv7 Модуль не устанавливается.


Название: Re: Многострадальный QSerialPort на Android
Отправлено: NikMik от Апрель 05, 2016, 15:52
всем привет!

а как обстоят дела с многострадальным андроидным QSerialPort на сегодняшний день в версии 5.6?

вроде бы библиотека в папке есть, примеры собираются и даже запускаются,
но пример enumerator ничего не находит....

по правде говоря, на моём планшете при подключении адаптеров (PL2303, CP2102) не создаётся /dev/ttyUSBx
но другие терминалы ведь работают и обмениваются данными с внешней железкой через устройство /dev/bus/usb/001/00x

подскажите в какую сторону копать - заставлять android сделать ttyUSBх или заставлять QSerialPort работать с /bus/usb/

PS. пробовал сделать символическую ссылку - не прокатило. а вот какой-то найденный костыль pl2303drv вроде бы смог установить обмен с железкой. но enumerator по-прежнему выдаёт пустой список...

UPD. соизволил таки почитать доки. опечалился: :'(
Цитировать
Qt for Android enables you to run Qt 5 applications on devices with Android v2.3.3 (API level 10) or later. All Qt modules (essential and add-on) are supported except Qt WebEngine, Qt Serial Port, and the platform-specific ones (Qt Mac Extras, Qt Windows Extras, and Qt X11 Extras).
стоит ли тратить время на сборку библиотеки со старым патчем за 2014-ый год - упоминался на предыдущей странице... ???

UPD2.
собрал из исходников QSerialPort c патчем, установил.
пример enumerator по-прежнему не видит никаких портов.
кто виноват - Qt или планшет (напомню, в нём почему-то не появляется /dev/ttyUSB* при подключении адаптера)?