首页 > 其他分享 >Android libusb

Android libusb

时间:2024-08-19 21:48:44浏览次数:13  
标签:usb transfer dev libusb device Android 设备

一、环境:配置NDK环境

1、下载libusb源码: https://github.com/libusb/libusb/releases,如下图所示

2、删除一些和Android平台无关的文件,删除后的文件如下图所示:

思考问题:

  1. Android是怎么获取usb设备?

如上图所示:连接adb shell,然后cd到/sys/bus/usb/devices/目录,命令ll可以看到里面有很多链接的文件,其实这些文件就代表设备或者功能,那么什么代表的是设备?什么代表的是功能呢?如上图,有冒号的且后面有数字的就代表的是功能接口,无冒号的就代表设备。如:1-0:1.0 就表示1号总线的0号端口设备,使用的1号配置,接口号为0。

所以,我们可以遍历此目录来获取usb设备,那么获取usb设备是怎么获取他们的信息的呢?继续向设备目录下面一层可以看到如下图所示:

里面有很多信息,包括设备的bcdDevice(usb版本)、idProduct(产品id)、idVendor(厂商id)、speed(usb传输速度)、descriptors(设备描述符)等,都可以在这里获取。

这样,我们最初始获取usb设备的问题就解决了。那么如果插拔usb设备,是不是一直都需要这样监听呢?

  1. Android是怎么检测usb设备插拔?
    使用Netlink来实现接收内核消息,读取热插拔信息,它是特殊的socket,使用时设置特定的参数即可监听到内核uevent事件,从而区分插拔事件NETLINK_KOBJECT_UEVENT, groups = 1,如下图所示:

所以,在libusb中只要对此socket进行监听即可,如下图代码的监听:

  1. Android是怎么进行数据传输的?
  2. 拿到句柄fd,如下图中的目录文件中open操作

  1. 通过ioctl与内核通信(linux_usbfs.c中submit_bulk_transfer函数)

  1. 通过ioctl与内核通信,具体见如下kernel代码drivers/usb/core/devio.c

二、目录文件介绍(os目录下都是一些和平台相关的,os外面是通用的):

a. linux_netlink.c:主要负责socket连接和监听热插拔的消息。

b.linux_usbfs.c: 主要是对Linux的一些文件进行操作,包括打开文件、释放文件、获取设备信息、和内核进行通信等

c.poll_posix.c: linux:通信设置pipe信息

d.threads_posix.c:主要是封装了一下线程锁和等待的一些机制。

e.config.h:对libusb进行一些配置

f.core.c:对os中的linux_usbfs.c进一步的封装,提供给外界调用的一些接口,包括初始化、分配内存、释放内存、通信的封装等。

g.descriptor.c:主要是获取设备描述符的封装。

h.hotplug.c:主要是对热插拔函数的封装,可以注册和反注册热插拔函数。

i.io.c:主要是和usb通信的一些封装,这里的封装均是异步接口

j.libusb.h:主要是对外提供的接口

k.libusbi.h:libusb内部使用的接口

l.sync.c:同步传输的封装

三、libusb传输封装的介绍,这里只介绍内部实现的同步bulk传输

接口的调用libusb_bulk_transfer -> do_sync_bulk_transfer() ->libusb_fill_bulk_transfer()、libusb_submit_transfer()、sync_transfer_wait_for_completion()等待completed被设置为1后返回transfer的值,包括buffer和actual_length

四、libusb的demo

#include <stdio.h>

#include "libusb.h"

static void print_devs(libusb_device **devs)
{
    libusb_device *dev;
    int i = 0, j = 0;
    uint8_t path[8]; 

    while ((dev = devs[i++]) != NULL) {
        struct libusb_device_descriptor desc;
        int r = libusb_get_device_descriptor(dev, &desc);
        if (r < 0) {
            fprintf(stderr, "failed to get device descriptor");
            return;
        }

        printf("%04x:%04x (bus %d, device %d)",
            desc.idVendor, desc.idProduct,
            libusb_get_bus_number(dev), libusb_get_device_address(dev));

        r = libusb_get_port_numbers(dev, path, sizeof(path));
        if (r > 0) {
            printf(" path: %d", path[0]);
            for (j = 1; j < r; j++)
                printf(".%d", path[j]);
        }
        printf("\n");
    }
}

int main(void)
{
    libusb_device **devs;
    int r;
    ssize_t cnt;

    r = libusb_init(NULL);
    if (r < 0)
        return r;

    cnt = libusb_get_device_list(NULL, &devs);
    if (cnt < 0)
        return (int) cnt;

    print_devs(devs);
    libusb_free_device_list(devs, 1);

    libusb_exit(NULL);
    return 0;
}

五、开发中遇到的问题

1、我们知道发现设备是从/sys/bus/usb/devices/发现的,但是打开设备则是在/dev/bus/usb/xxx中打开的,如果一旦发现设置,就直接去打开,有可能会导致打开失败的情况,原因是这个设备节点还没有来得及创建,就去打开这个设备,现在修复有两种方式:

a.如果打开失败,则slee(1)秒,再去打开,如果这次再打开失败,则就真的失败了,这个方式亲测还是可以的,而且查看Android源码好像也是用这种方式

b.这个方法简单的验证了一下可行,但是不知道会不会导致其他问题,就是发现设备枚举的时候就去获取他的主设备号和次设备号,然后在打开的时候,发现没有这个设备,就手动的创建设备,如下代码,其中/dev/bus/usb/002/为设备节点的路径,243为设备相应的主设备号,0为设备相应的次设备号。

mknod("/dev/bus/usb/002", S_IFCHR | 0666, makedev(243, 0)) = 0

2、如果是基于libusb开发的异步传输,而且传输时有很多缓存,我们可能会向libusb提供的demo上面写的那样,直接在接收到设备拔出的消息之后立刻libusb_close(handle), 这样会有个问题,有可能你提交成功的transfer不会通过回调返回给你,导致这个transfer会丢失,最终就是内存泄漏了。那么怎么解决这个问题呢?有两个方案:均亲测可行

a. 在收到设备拔出的消息之后不要立刻libusb_close(handle);在其他的时机close就可以了

b. 如果一定要在拔出后立刻libusb_close(handle);,我们可以把提交成功的transfer加入到一个队列里,在合适的时候free掉这些队列的transfer,以及transfer里面的buffer。

标签:usb,transfer,dev,libusb,device,Android,设备
From: https://www.cnblogs.com/linhaostudy/p/18368190

相关文章

  • Android开发 - DisplayMetrics 类控制布局图形的缩放显示解析
    DisplayMetrics是什么DisplayMetrics类在Android中用于获取设备的显示属性(像素等)DisplayMetrics的主要属性metrics.density:屏幕密度,用于决定屏幕上每英寸的像素数DisplayMetricsmetrics=newDisplayMetrics();density=metrics.density;常见值:0.75(低密度)、1.0......
  • 手机使用技巧:如何恢复Android手机不见的短信
     在您的Android手机上丢失短信可能是一种令人沮丧的经历,尤其是在文本包含重要信息的情况下。幸运的是,有一些方法可以在Android上恢复已删除的短信。在这篇博文中,我们将讨论几种在Android手机上恢复已删除短信的方法。为什么需要恢复Android手机不见的短信您可能想要在And......
  • Android开发 - HorizontalScrollView 类水平滚动超长视图使用解析
    基本概念HorizontalScrollView是一个容器,它允许包含的内容在水平方向上滚动。如果你有一块内容(比如一张宽大的图片或一个长长的水平列表),HorizontalScrollView能让用户通过左右滑动来查看超出屏幕的部分基本使用在布局文件(如activity_main.xml)中定义一个HorizontalScrol......
  • 秒开WebView?Android性能优化全攻略
    在如今的移动应用时代,用户体验的好坏直接关系到应用的成功与否。而在众多的用户体验因素中,应用的加载速度尤其重要。特别是对于使用 WebView 加载网页的应用,如果加载速度过慢,用户往往会产生不满,从而流失。因此,实现“秒开”WebView成为了开发者必须面对的一项挑战。本文将深......
  • Android usb广播 ACTION_USB_DEVICE_ATTACHED流程源码分析
    整体流程图大概意思就是UsbHostManager启动监控线程,monitorUsbHostBus会调用usb_host_run函数(使用inotify来监听USB设备的插拔)不停的读取bus总线,读取到以后,当1、设备插入:发送广播ACTION_USB_DEVICE_ATTACHED2、设备拔出:发送广播ACTION_USB_DEVICE_DETACHED本篇只分析插入......
  • 高德地图SDK Android版开发 6 显示覆盖物
    高德地图SDKAndroid版开发6显示覆盖物前言地图类中覆盖物的接口覆盖物类Marker示例Polyline示例Polygon示例Arc示例Circle示例移除示例效果图Marker的更多属性常用属性交互动画其它属性折线的更多属性常用属性其它属性多边形的更多属性常用属性其它属性Arc的更多......
  • 【Android驱动12】Modem编译和sim卡配置检测过程
    一,Modem编译1.1查看ReleseNote发现需要查看"Build_Configure_Modem_MOLY"这张表,解压MT67xx_(xxx)_MOLY.LR9.W1444.MD.LWTG.MP.Vx.tar.gz到某文件,并在make目录下查看支持的配置信息1.2执行的命令,开始编译modem,则是./make.sh"SM67xx(Lxx_xxx).mak"new1.3执行perl......
  • Android 13.0 recovery页面旋转180度问题的解决方案
    1.前言在13.0的系统rom定制化开发工作中,在系统中recovery的页面也是相关重要的一部分,在系统recoveryota升级等功能,都是需要recovery功能的,在某些产品定制化中在recovery的时候,发现居然旋转了180度,接下来分析下recovery关于屏幕显示方向的相关源码,来修改这个功能2.recovery......
  • 基于flask+vue框架的基于Android的校园公益管理APP小程序端[开题+论文+程序]-计算机毕
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景在当今社会,随着教育理念的进步和青年学生社会责任感的增强,校园公益活动已成为培养学生综合素质、促进社会和谐的重要途径。然而,传统的公益......
  • Android MTP流程
    概要本文的目的是介绍Android系统中MTP的一些相关知识。主要的内容包括:第1部分MTP简介      对Mtp协议进行简单的介绍。第2部分MTP框架      介绍Android系统下MTP的框架。第3部分MTP启动流程      详细分析MTP服务的启动流程,包括Java层,......