Qt for android : libusb在android中使用

简介

如何在Qt for Android中使用libusb, 其实libusb的文档里面都写的很清楚, 这里只是稍微做下整理。

libusb

libusb github源码
libusb release的版本, 有编译好的静态

步骤

1. 下载libusb

libusb v1.0.027 源码包

2. 整理提取libusb android使用源码

从编译文件 libusb-1.0.27\android\jni\libusb.mk 直到 android所需要的源文件和头文件, 做整理,编译时再看缺少哪些,补齐。
如下是我整理的, config.h 来自libusb-1.0.27\android目录
在这里插入图片描述
下面是libusb目录包含的文件
在这里插入图片描述
os目录包含的文件
在这里插入图片描述

libusb.pri

CCFLAG += -fvisibility=hidden -pthread

INCLUDEPATH += $$PWD

SOURCES += \
    $$PWD/libusb/core.c \
    $$PWD/libusb/descriptor.c \
    $$PWD/libusb/hotplug.c \
    $$PWD/libusb/io.c \
    $$PWD/libusb/strerror.c \
    $$PWD/libusb/sync.c \
    $$PWD/os/events_posix.c \
    $$PWD/os/linux_netlink.c \
    $$PWD/os/linux_usbfs.c \
    $$PWD/os/threads_posix.c

HEADERS += \
    $$PWD/config.h \
    $$PWD/libusb/libusb.h \
    $$PWD/libusb/libusbi.h \
    $$PWD/libusb/version.h \
    $$PWD/libusb/version_nano.h \
    $$PWD/os/events_posix.h \
    $$PWD/os/linux_usbfs.h \
    $$PWD/os/threads_posix.h

3. 创建Qt for Android 并 加入libusb

参考 Qt for android 获取USB设备列表(二)JNI方式 获取,

  1. 工程文件.pro 添加libusb支持
    include ($$PWD/libusb/libusb.pri)
  2. java代码支持, 用于获取usb权限
package usb;

import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.io.IOException;

import android.content.pm.PackageManager;
import android.Manifest;
import android.content.Intent;
import android.app.PendingIntent;
import android.util.Log;
import android.os.Bundle;
import android.content.Context;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;

// import com.hoho.android.usbserial.driver.Ch34xSerialDriver;
// import com.hoho.android.usbserial.driver.UsbSerialPort;



public class USBListActivity extends org.qtproject.qt.android.bindings.QtActivity
{
    private static USBListActivity instance = null;
    private static UsbManager usbManager = null;
    // private static StorageManager storageManager = null;
    private static String tag = "MainClass";
    private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";



    public USBListActivity()
    {
        instance = this;
    }

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        usbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
        // storageManager = (UsbManager)getSystemService(Context.STORAGE_SERVICE);

        Log.i(tag, "checkPermission: " + checkPermission());
        // getDeviceList();
    }

    private boolean checkPermission() {
        int readPermission = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
        int writePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        return readPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED;
    }



    public static boolean requestUSBPermission(String portName)
    {
        if (portName.isEmpty())
        {
            Log.i(tag, "port empty");
            return false;
        }
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        UsbDevice device = null;
        for (Map.Entry<String, UsbDevice> entry : deviceList.entrySet())
        {
            if (portName.equals(entry.getKey()))
            {
                device = entry.getValue();
                break;
            }
        }
        if (device == null)
        {
            Log.i(tag, "device not exists");
            return false;
        }

        if (!usbManager.hasPermission(device))
        {
            Intent permissionIntent = new Intent(ACTION_USB_PERMISSION);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(instance,
                                                    0,
                                                    permissionIntent,
                                                    PendingIntent.FLAG_UPDATE_CURRENT);
            usbManager.requestPermission(device, pendingIntent);

            if (!usbManager.hasPermission(device))
            {
                Log.i(tag, "permission denied");
                return false;
            }
        }

        // UsbDeviceConnection deviceConnection = usbManager.openDevice(device);
        // if (null == deviceConnection)
        // {
        //     Log.i(tag, "fail to open device");
        //     return false;
        // }


        return true;
    }

    public void getDeviceList()
    {
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        System.out.println("------------------------->GetDeviceList<-------------------------");
        deviceList.forEach((key, value) -> {
            System.out.println("------------------------->" + key + "<-------------------------");

            System.out.println(value);

            System.out.println("<-------------------------" + key + "------------------------->");

        });
        System.out.println("<-------------------------GetDeviceList------------------------->");
    }
}

  1. 将libusb示例加入到Qt for android工程
    将 libusb-1.0.27\android\examples 目录下的 unrooted_android.c和unrooted_android.h拷贝到Qt 项目中, 添加

  2. Qt for Android通过JNI调用获取文件描述符并使用libusb打印usb设备信息

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "unrooted_android.h"
#include <QJniObject>
#include <QJniEnvironment>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connect(ui->btnRefreshPortNames, &QPushButton::clicked,
            this, [=]()
    {
        ui->cbPortNames->clear();
        ui->cbPortNames->addItems(getSerialPorts());
    });
    connect(ui->btnTest, &QPushButton::clicked,
            this, &MainWindow::test);

    emit ui->btnRefreshPortNames->clicked(); // 借势初始化
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::logger(const QString &text)
{
    ui->textEdit->append(text);
}

QList<QString> MainWindow::getSerialPorts()
{
    QList<QString> names;
#ifdef Q_OS_ANDROID
    QJniObject usbService = QJniObject::getStaticObjectField("android/content/Context",
                                                            "USB_SERVICE",
                                                            "Ljava/lang/String;");
    if (!usbService.isValid())
    {
        logger("fail to get usb service");
        return names;
    }


    QJniObject activity = QJniObject(QNativeInterface::QAndroidApplication::context());

    QJniObject usbManager = activity.callObjectMethod("getSystemService",
                                                      "(Ljava/lang/String;)Ljava/lang/Object;",
                                                      usbService.object<jstring>());
    if (!usbManager.isValid())
    {
        logger("fail to get usb manager");
        return names;
    }

    QJniObject usbDeviceListHashMap = usbManager.callObjectMethod("getDeviceList",
                                                           "()Ljava/util/HashMap;");
    QJniObject devListKeySet = usbDeviceListHashMap.callObjectMethod("keySet",
                                                       "()Ljava/util/Set;");
    QJniObject devListIter = devListKeySet.callObjectMethod("iterator",
                                                       "()Ljava/util/Iterator;");
    jint devListSize = usbDeviceListHashMap.callMethod<jint>("size", "()I");

    QJniObject usbDevObj;
    QJniObject usbDevObjIter;
    int vid = 0, pid = 0;
    QString devName;
    for (int i = 0; i < devListSize; ++i)
    {
        usbDevObjIter = devListIter.callObjectMethod("next",
                                            "()Ljava/lang/Object;");
        usbDevObj = usbDeviceListHashMap.callObjectMethod("get",
                                                   "(Ljava/lang/Object;)Ljava/lang/Object;",
                                                   usbDevObjIter.object());
        vid = usbDevObj.callMethod<jint>("getVendorId", "()I");
        pid = usbDevObj.callMethod<jint>("getProductId", "()I");
        devName = usbDevObj.callMethod<jstring>("getDeviceName", "()Ljava/lang/String;").toString();

        logger(QString("Name: %1, VID: %2, PID: %3").arg(devName).arg(vid).arg(pid));
        names.append(devName);
    }
#else
    for (QSerialPortInfo &info : QSerialPortInfo::availablePorts())
    {
        names.append(info.portName());
    }
#endif
    return names;
}


void MainWindow::test()
{
    QJniObject str = QJniObject::fromString(ui->cbPortNames->currentText());
    jboolean res = QJniObject::callStaticMethod<jboolean>(
                                       "usb/USBListActivity",
                                       "requestUSBPermission",
                                       "(Ljava/lang/String;)Z",
                                       str.object<jstring>());
    if (!res)
    {
        logger("permission denied");
        return;
    }
    QJniObject usbService = QJniObject::getStaticObjectField("android/content/Context",
                                                            "USB_SERVICE",
                                                            "Ljava/lang/String;");
    if (!usbService.isValid())
    {
        logger("fail to get usb service");
        return;
    }


    QJniObject activity = QJniObject(QNativeInterface::QAndroidApplication::context());

    QJniObject usbManager = activity.callObjectMethod("getSystemService",
                                                      "(Ljava/lang/String;)Ljava/lang/Object;",
                                                      usbService.object<jstring>());
    if (!usbManager.isValid())
    {
        logger("fail to get usb manager");
        return;
    }

    QJniObject usbDeviceListHashMap = usbManager.callObjectMethod("getDeviceList",
                                                           "()Ljava/util/HashMap;");
    QJniObject devListKeySet = usbDeviceListHashMap.callObjectMethod("keySet",
                                                       "()Ljava/util/Set;");
    QJniObject devListIter = devListKeySet.callObjectMethod("iterator",
                                                       "()Ljava/util/Iterator;");
    jint devListSize = usbDeviceListHashMap.callMethod<jint>("size", "()I");

    QJniObject usbDevObj;
    QJniObject usbDevObjIter;
    QString devName;
    QJniObject selectedUsbDevice;
    for (int i = 0; i < devListSize; ++i)
    {
        usbDevObjIter = devListIter.callObjectMethod("next",
                                            "()Ljava/lang/Object;");
        usbDevObj = usbDeviceListHashMap.callObjectMethod("get",
                                                   "(Ljava/lang/Object;)Ljava/lang/Object;",
                                                   usbDevObjIter.object());
        devName = usbDevObj.callMethod<jstring>("getDeviceName", "()Ljava/lang/String;").toString();


        if (devName != ui->cbPortNames->currentText())
        {
            continue;
        }
        selectedUsbDevice = usbDevObj;
        break;
    }
    if (!selectedUsbDevice.isValid())
    {
        logger("device not found");
        return;
    }

    QJniObject usbConnection = usbManager.callObjectMethod("openDevice",
                                                                   "(Landroid/hardware/usb/UsbDevice;)Landroid/hardware/usb/UsbDeviceConnection;",
                                                                    selectedUsbDevice.object());
    if (!usbConnection.isValid())
    {
        logger("fail to get usb connection");
        return;
    }
    jint fd = usbConnection.callMethod<jint>("getFileDescriptor", "()I");


    unrooted_usb_description(fd);

    logger("libusb test finished7");
}

4. 手机接入OTG和USB设备

我这里接的是USB转TTL线

5. 测试

打印信息是

D LibUsb : Dev (bus 1, device 4): 1A86 - 7523 speed: 12M
D LibUsb : Product: USB2.0-Serial
D LibUsb : Configuration:
D LibUsb : wTotalLength: 39
D LibUsb : bNumInterfaces: 1
D LibUsb : bConfigurationValue: 1
D LibUsb : iConfiguration: 0
D LibUsb : bmAttributes: 80h
D LibUsb : MaxPower: 48
D LibUsb : Interface:
D LibUsb : bInterfaceNumber: 0
D LibUsb : bAlternateSetting: 0
D LibUsb : bNumEndpoints: 3
D LibUsb : bInterfaceClass: 255
D LibUsb : bInterfaceSubClass: 1
D LibUsb : bInterfaceProtocol: 2
D LibUsb : iInterface: 0
D LibUsb : Endpoint:
D LibUsb : bEndpointAddress: 82h
D LibUsb : bmAttributes: 02h
D LibUsb : wMaxPacketSize: 32
D LibUsb : bInterval: 0
D LibUsb : bRefresh: 0
D LibUsb : bSynchAddress: 0
D LibUsb : Endpoint:
D LibUsb : bEndpointAddress: 02h
D LibUsb : bmAttributes: 02h
D LibUsb : wMaxPacketSize: 32
D LibUsb : bInterval: 0
D LibUsb : bRefresh: 0
D LibUsb : bSynchAddress: 0
D LibUsb : Endpoint:
D LibUsb : bEndpointAddress: 81h
D LibUsb : bmAttributes: 03h
D LibUsb : wMaxPacketSize: 8
D LibUsb : bInterval: 1
D LibUsb : bRefresh: 0
D LibUsb : bSynchAddress: 0

在这里插入图片描述

代码

基本代码都提供了, 没必要下载
libusb在Qt for android中的调用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/658357.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

构建高效稳定的运维服务体系:技术架构解析与最佳实践

在当今数字化时代&#xff0c;运维服务对于企业的稳定运行和业务发展至关重要。本文将深入探讨运维服务的技术架构&#xff0c;介绍如何构建高效稳定的运维服务体系&#xff0c;并分享最佳实践。 ### 1. 概述 运维服务的技术架构是支撑整个运维体系的核心&#xff0c;它涵盖了…

数字孪生技术助力智慧园区建设

随着城市化进程的加速和科技创新的推动&#xff0c;城市面临着诸多挑战和机遇。如何提升城市的竞争力和可持续性&#xff0c;是一个亟待解决的问题。在这个背景下&#xff0c;智慧园区作为一种新型的城市发展模式&#xff0c;引起了越来越多的关注和探索。 什么是智慧园区&…

如何将天猫内容保存为PDF格式?详细步骤与实战解析

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;保存天猫内容的重要性 二、环境准备与工具安装 1. 安装必要的Python包…

[数据集][目标检测]红外车辆检测数据集VOC+YOLO格式13979张类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;13979 标注数量(xml文件个数)&#xff1a;13979 标注数量(txt文件个数)&#xff1a;13979 标…

Ownips+Coze海外社媒数据分析实战指南

目录 一、引言二、ISP代理简介三、应用实践——基于Ownips和coze的社媒智能分析助手3.1、Twitter趋势数据采集3.1.1、Twitter趋势数据接口分析3.1.2、Ownips原生住宅ISP选取与配置3.1.3、数据采集 3.2、基于Ownips和Coze的社媒智能助手3.2.1、Ownips数据采集插件集成3.2.2、创建…

LeetCode //C - 143. Reorder List

143. Reorder List You are given the head of a singly linked-list. The list can be represented as: L0 → L1 → … → Ln - 1 → Ln Reorder the list to be on the following form: L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … You may not modify the values i…

uniapp - 填充页面

在上一篇文章中&#xff0c;创建了一个空白的文章模块页面。在这一篇文章&#xff0c;让我们来向页面中填充内容。 目录 页面效果涉及uniapp组件1.view2.swiper3.scroll-view4.属性解读1) class"style1 style2 .."2) circular单属性无赋值3) :autoplay"autoplay…

Metasploit渗透测试工具使用

Metasploit Framework(MSF) 是一款开源安全漏洞检测工具&#xff0c;附带数千个已知的软件漏洞&#xff0c;并保持持 续更新。Metasploit可以用来信息收集、漏洞探测、漏洞利用等渗透测试的全流程&#xff0c;被安全社区冠以“可 以黑掉整个宇宙”之名。刚开始的Metasploit是采…

在Python中实现限定抽奖次数的机制

目录 一、引言 二、需求分析 三、设计思路 四、代码实现 4.1 使用字典存储用户抽奖次数 4.2 使用数据库存储用户抽奖次数 五、扩展与优化 六、总结 一、引言 在当今互联网应用中&#xff0c;抽奖系统作为吸引用户、提高用户参与度和活跃度的重要手段&#xff0c;已经被…

Windows 下载安装Apache

一、官网下载 1、打开Apache官网http://httpd.apache.org&#xff0c;点击Download。 2、选择Windows版本&#xff0c;点击链接。 3、选择对应版本选择下载。 二、安装、设置 1、将下载好的解压。 2、依次打开Apache24-conf-httpd.conf,用记事本打开 1)、修改路径 2)、修改…

PS Adobe Photoshop 2024 for Mac[破]图像处理软件[解]PS 2024安装教程[版]

Adobe Photoshop 2024 for Mac[破]图像处理软件[解]PS 2024安装教程[版] 原文地址&#xff1a;https://blog.csdn.net/weixin_48311847/article/details/139248839

【论文复现】——基于随机抽样与特征值法的点云平面稳健拟合方法

目录 一、算法原理1、论文概述2、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的GPT爬虫。 一、算法原理 1、论文概述 针对点云数据含有异常值且传统拟合方法拟合结果不理想的情况,本文提出…

7 Series FPGAs Integrated Block for PCI Express IP核设计中的物理层控制核状态接口

物理层控制和状态允许用户应用程序根据数据吞吐量和电源需求来更改链路的宽度和速度。 1 Design Considerations for a Directed Link Change 在Directed Link Change&#xff08;定向链接更改&#xff09;期间需要注意的事项有&#xff1a; 链接更改操作&#xff08;Link c…

干货 | 学习网络安全,推荐6个常用的安全知识在线手册(非常详细)零基础入门到精通,收藏这一篇就够了

排名不分先后&#xff0c;欢迎各位小伙伴下方留言评论补充 **VulDoc ** 包含&#xff1a;IOT安全&#xff0c;Web安全&#xff0c;系统安全 地址&#xff1a;http://47.112.148.3:8000/ **滴水逆向学习笔记 ** 包含 汇编 C C Win32 MFC 网络编程 数据库 数据…

Clickhouse MergeTree 存储引擎架构总结——Clickhouse 架构篇(二)

文章目录 前言MergeTree存储引擎的三大特点MergeTree 的数据组织MergeTree的文件组织数据文件、元数据文件、索引文件和其他文件分区数据库和表 索引与事务数据库存储引擎的对比存储引擎如何影响查询速度MergeTree存储引擎的工作过程 前言 存储引擎是ClickHouse非常重要的一个…

曲线拟合工具软件(免费)

曲线拟合是数据处理中经常用到的数值方法,本质是使用某一个模型(方程或者方程组)将一系列离散的数据拟合成平滑的曲线或者曲面,数值求解出对应的函数参数,大家可以利用MATLAB的曲线拟合工具箱也可以使用第三方的拟合软件,今天我们介绍Welsim免费的曲线拟合软件 1、MATLA…

idea视图中顶部菜单栏找不到VCS

问题描述 idea视图中顶部菜单栏找不到VCS&#xff1a; 解决方案&#xff1a; 直接选择配置过git&#xff0c;此处操作&#xff1a; File->Settings->Version Control-> 点击 ->选择项目->VCS选择none ->点击apply -> 点击ok&#xff1a;

大模型时代:生活将如何被重塑?

大模型时代&#xff1a;生活将如何被重塑&#xff1f; &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &#x1f31d;分享…

填补领域空白!TerDiT:首次探索大规模DiT模型量化问题(MMLab出品)

论文链接&#xff1a;https://arxiv.org/pdf/2405.14854 项目链接&#xff1a;https://github.com/Lucky-Lance/TerDiT 最近在大规模预训练的文本到图像扩散模型方面的发展显著提高了高保真图像的生成能力&#xff0c;特别是基于transformer架构的扩散模型&#xff08;DiTs&a…

halcon SVM 缺陷检测分类

一、概述 训练数据 二、算子解释 compactness Halcon 算子 compactness_halcon compactness-CSDN博客 *计算输入区域的紧凑度 compactness (Region, Compactness) 原理解释 convexity 每个输入区域的凸度 Halcon 算子 convexity_halcon convexity-CSDN博客 *计算每个输…