Russian Qt Forum
Март 28, 2024, 13:00 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Многострадальный QSerialPort на Android  (Прочитано 15262 раз)
Silver_swift
Гость
« : Август 21, 2014, 21:54 »

Доброго времени суток всем!

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

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

Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #1 : Август 22, 2014, 10:19 »

Да, в Android нет никакого публичного интерфейса для доступа к последовательным портам (хотя, не исключаю, что в самом последнем Android это могли добавить в JAVA интерфейсы, хз).
Но есть вариант обойти это и использовать режим USB хоста. Я не знаю, нужны ли в этом случае драйвера (скорее всего нет). В этом случае не нужны права рута и это должно работать для перечня основных м/сх производителей портов (Prolific, Ftdi и пр.).

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

ArchLinux x86_64 / Win10 64 bit
Silver_swift
Гость
« Ответ #2 : Август 22, 2014, 11:42 »

Здорово, вроде даже что-то собирается. Дома надо будет проверить работоспособность. Спасибо за наводку! Улыбающийся А то я начал готовиться к сборке ftdi драйвера из исходников ядра Улыбающийся
Записан
Silver_swift
Гость
« Ответ #3 : Август 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. Это же китаец... Застрял там где не ожидал подвоха.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #4 : Август 26, 2014, 10:34 »

Цитировать
К сожалению не заработал QSerialPort.

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

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

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

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

ArchLinux x86_64 / Win10 64 bit
Silver_swift
Гость
« Ответ #5 : Август 26, 2014, 14:20 »

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

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

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

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

Порадовал ответ гугла на запрос
Цитировать
perfeo 7143 kernel source
Вообще ничего не найдено... Как собирать драйвер пока не ясно.
Записан
Bepec
Гость
« Ответ #6 : Август 26, 2014, 14:43 »

В прямой путь к производителю с вопросом Веселый
Я так с панельником мучался мучался, потом написал производителю, они мне выслали дрова Веселый
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #7 : Август 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".

В общем, почитай, поразбирайся и расскажи нам как там и что Улыбающийся.
« Последнее редактирование: Август 26, 2014, 16:02 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
Silver_swift
Гость
« Ответ #8 : Август 27, 2014, 10:13 »

VID/PID моего преобразователя первые в UsbId.java Улыбающийся

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

Вот не знаю как бы отладить java методы. Посмотреть бы вызывается ли что-то вообще и что внутри происходит.
Записан
Silver_swift
Гость
« Ответ #9 : Август 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 не работает, отладчик не цепляется... Если чего добьюсь отпишусь, если есть идеи прошу выссказывать Улыбающийся
Записан
Bepec
Гость
« Ответ #10 : Август 28, 2014, 23:28 »

Так сделай над кодом обертку, повызывай его, посмотри что не так Улыбающийся
Записан
Silver_swift
Гость
« Ответ #11 : Сентябрь 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 -> Проекты -> Конфигурация установки), чтобы его при сборке не заменяло на дефолтный.

Был бы признателен за советы по отладке сего безобразия и моральную поддержку Улыбающийся
Записан
Silver_swift
Гость
« Ответ #12 : Сентябрь 24, 2014, 13:58 »

Забыл отписаться Улыбающийся В итоге на следующий день плюнул на QSerialPort и сделал обмены по wi-fi на сокетах.
Записан
marselus
Гость
« Ответ #13 : Ноябрь 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
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #14 : Ноябрь 06, 2014, 11:18 »

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

ArchLinux x86_64 / Win10 64 bit
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.059 секунд. Запросов: 22.