如何打开USB OTG功能

 OTG – Android USB Hos

前几天研究了一下Android上OTG的功能。

OTG在Android3.1及以上被支持。也就是minSdkVersion为12.

API概述

UsbManager

允许您枚举已连接的USB设备并且与其进行“交流”。

UsbDevice

代表了一个已连接的USB的设备并且包含具有该设备验证信息,接口和接入点的方法。

UsbInterface

代表了一个USB设备的一个接口,该接口定义了一系列关于设备的函数。一个设备在进行“交流”的时候可以有一个或者多个接口。

UsbEndpoint

代表一个接口的接入点,该接入点就是这个接口的通信信道。一个接口可以有一个或者多个这样的接入点,而且一般都是有输入和输出双向通信的接入点。

UsbDeviceConnection

代表该设备的一个连接,用来在接入点上传输数据。这个类允许您能用同步或者异步的方式发送和返回数据。

UsbRequest

在通过UsbDeviceConnection和设备进行“交流”的一个异步请求。

UsbConstants

关于在linux内核中linux/usb/ch9.h的相关定义的USB常量。

在大多数情况中,跟USB设备通信时,需要使用所有这些类(使用异步通信,只需要使用UsbRequest类)。使用UsbManager对象来获取期望的UsbDevice对象。有了这个UsbDevice对象时,就需要查找对应的UsbInterface对象和基于该接口通信的UsbEndpoint对象。一旦获取了正确的端点,就可以打开UsbDeviceConnect对象来跟USB设备进行通信了。

Android清单要求

在使用USB主机模式API工作之前,你需要把以下介绍的内容添加到你的应用程序清单中:

1. 因为不是所有的Android设备都保证支持USB主机模式,所以要在你的应用程序声明中包含元素,以声明你的应用程序要使用android.hardware.usb.host功能。

2. 把应用程序的最小SDK设置为API Level 12或更高的版本。在较早的API版本中不存在USB主机模式API。

3. 如果你希望你的应用程序能够获得接入USB设备时的通知,那么还要在你的主Activity中指定用android.hardware.usb.action.USB_DEVICE_ATTACHED类型的Intent来配对的和元素。元素要指向一个外部的XML资源文件,该文件声明了希望检测的设备的识别信息。

在这个XML资源文件中,要用元素来声明你想要过滤的USB设备。以下列出了元素的属性。通常,使用vendor-id和product-id来指定你所希望过滤的特定的设备,并且使用class、subclass和protocol来指定你所希望过滤的USB设备组,如大容量存储设备或数码相机。你可以不指定任何属性,或所有全部属性。不指定任何属性,就会跟所有USB设备匹配,如果应用程序需要,就可以这样做:

A. vendor-id

B. product-id

C. class

D. subclass

E. protocol(设备或接口)

在res/xml目录中保存这个资源文件。该资源文件的名称(不含.xml扩展名)必须跟元素中指定的名称相同。XML资源文件的格式请看下例。

<?xml version=”1.0″ encoding=”utf-8″?>

<manifest xmlns:android=”http://schemas.android.com/apk/res/android”

   package=”com.example.testusb”

   android:versionCode=”1″

   android:versionName=”1.0″

   >

 

   <uses-sdk

       android:minSdkVersion=”12″

       android:targetSdkVersion=”17″ />

    

   <uses-feature android:name=”android.hardware.usb.host” />

 

   <application

       android:allowBackup=”true”

       android:icon=”@drawable/ic_launcher”

       android:label=”@string/app_name”

       android:theme=”@style/AppTheme” >

       <activity

           android:name=”com.example.testusb.TestUSB”

           android:label=”@string/app_name” >

           <intent-filter>

               <action android:name=”android.intent.action.MAIN” />

               <category android:name=”android.intent.category.LAUNCHER” />

           </intent-filter>

           <!– 当你需要希望你的应用能够被连接的设备所提示,需要针对intent-filter和meta-data加上android.hardware.usb.action.USB_DEVICE_ATTACHED意图 –>

           <intent-filter>

               <action android:name=”android.hardware.usb.action.USB_DEVICE_ATTACHED” />

           </intent-filter>

 

           <!– 用于过滤具体USB设备,其中device_filter是个xml文件 –>

           <meta-data android:name=”android.hardware.usb.action.USB_DEVICE_ATTACHED”

               android:resource=”@xml/device_filter” />

       </activity>

        

   </application>

 

</manifest>

资源文件应该保存在res/xml/device_filter.xml

查看源代码

打印

帮助

<?xml version=”1.0″ encoding=”utf-8″?>

<resources>

   <!– 如果你不确定你需要检测的设备vendor-id和product-id,可以所有的参数都为空,将获得所有已连接的USB设备。

   否则请对应上相应参数。 –>

   <usb-device vendor-id=”65535″ product-id=”65535″ class=”255″ subclass=”66″protocol=”1″ />

</resources>

可以在Windows上查看USB设备的VID和PID,需要注意的是,在Windows上VID和PID都是十六进制数,需要转换为10进制。

声明: 本文由( 上善若水 )原创编译,转载请保留链接: OTG – Android USB Host(一)

发现设备

可以使用两种方法来发现设备:

1.使用Intent过滤器,过滤用户接入USB设备时所发出的通知;

2.列举已经接入的USB设备。

如果你希望你的程序能够自动的检测你所期望的USB设备,需要使用Intent过滤器,如我们刚才在AndroidManifest.xml中添加的过滤器。

在Activity中,可以从这样的意图中获取UsbDevice:

UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

如果你你希望过滤所有的USB设备,或者应用程序没有过滤对应的Intent对象,那么可以使用列举:

UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

HashMap<String, UsbDevice> map = usbManager.getDeviceList();

for(UsbDevice device : map.values()){

   Log.i(TAG, “dName: ” + device.getDeviceName());

   Log.i(TAG, “vid: ” + device.getVendorId() + “\t pid: ” + device.getProductId());

   usbDevice = device;

   //Other code

}

或者使用迭代,获取每一个设备:

HashMap<String, UsbDevice> deviceList = usbManager .getDeviceList();

Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

while(deviceIterator.hasNext()){

   UsbDevice device = deviceIterator.next();

   //Other code

}

获取跟设备通信的权限

在跟USB设备进行通信之前,你的应用程序必须要获取用户的许可。

注意:如果你的应用程序使用Intent过滤器来发现接入的USB设备,而且用户允许你的应用程序处理该Intent,那么它会自动的接收权限,否则,在你的应用程序接入该设备之前,必须明确的申请权限。

明确的申请权限在某些情况下是必须的,如你的应用程序列举已经接入的USB设备并想要跟其中的一个设备通信的时候。在试图跟一个设备通信之前,你必须要检查是否有访问设备的权限。否则,如果用户拒绝了你访问该设备的请求,你会收到一个运行时错误。

要明确的获取这个权限,首先要创建一个广播接收器。这个接收器用于监听你调用requestPermission()方法时,系统所发出的Intent对象。调用requestPermission()方法时,系统会显示一个对话框,询问用户是否允许跟该USB设备进行连接。下列代码演示如何创建这个广播接收器:

private static final String ACTION_USB_PERMISSION = “com.android.example.USB_PERMISSION”;

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

 

   public void onReceive(Context context, Intent intent) {

   String action = intent.getAction();

       Log.e(TAG, action);

            

   if (ACTION_USB_PERMISSION.equals(action)) {

       synchronized (this) {

       usbDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

       //允许权限申请

       if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {

           if(usbDevice != null){

               //call method to set up device communication

               }

           } else {

               Log.d(TAG, “permission denied for device ” + usbDevice);

           }

       }

   }

};

注册接收的广播,并放在onCreate中:

//注册广播

IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);

registerReceiver(mUsbReceiver, filter);

申请权限:

PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION),0);

if(usbManager.hasPermission(usbDevice)){

   //Other code

}else{

   //没有权限询问用户是否授予权限

   usbManager.requestPermission(usbDevice, pendingIntent); //该代码执行后,系统弹出一个对话框,

                                                           //询问用户是否授予程序操作USB设备的权限

}

当用户回应这个对话框时,你的广播接收器就会收到一个包含用一个boolean值来表示结果的EXTRA_PERMISSION_GRANTED字段的意图。在您连接设备之前检查这个字段的值是否为true。

跟设备进行通信:

我们可以同步或者异步的和USB设备进行“交流”。在任意一种情况之下,您都应该创建一个新的线程来进行数据传输,这样就不会阻塞您的主线程了。要想正确的设置好和一个设备之间的连接,您需要获得该设备正确的UsbInterface和UsbEndpoint来和您进行“交流”以及通过UsbDeviceConnection在这个接入点上发送请求。一般来说,您的代码应该这样:

1.检查一个UsbDevice对象的属性,例如产品ID,供应商ID,或者是关于设备的类,以此来确认您是否希望和该设备进行“交流”。

2.当您确信您希望和该设备进行“交流”时,找到关于该设备正确的UsbInterface以及和该接口所对应的UsbEndpoint。接口可以有一个或者多个接入点,而且一般都会有一个双向通信的输入和输出接入点。

3.当您找到正确的接入点时,在该接入点时打开一个UsbDeviceConnection。

4.您可以通过bulkTransfer()和controlTransfer()这两个方法在接入点上传输您所需要传递的数据。您最好在另起一个新的线程来进行这个步骤以避免阻塞主线程。想要详细地了解关于Android中使用线程的信息,详见线程和进程。

private Byte[] bytes;

private static int TIMEOUT = 3000;

private boolean forceClaim = true;

 

UsbInterface usbInterface = usbDevice.getInterface(0);

//USBEndpoint为读写数据所需的节点

UsbEndpoint inEndpoint = usbInterface.getEndpoint(0);  //读数据节点

UsbEndpoint outEndpoint = usbInterface.getEndpoint(1); //写数据节点

UsbDeviceConnection connection = usbManager.openDevice(usbDevice);

connection.claimInterface(usbInterface, true);

            

//发送数据

byte[] byte2 = new byte[64];    //发送与接收字节数与设备outputreport有关

int out = connection.bulkTransfer(outEndpoint, bytes, bytes.length, TIMEOUT);

Log.e(TAG, “out:” + out);

            

//读取数据1   两种方法读取数据

int ret = connection.bulkTransfer(inEndpoint, byte2, byte2.length, TIMEOUT);

Log.e(TAG, “ret:”+ret);

//还有第二种读取方式,未验证。

int outMax = outEndpoint.getMaxPacketSize();

int inMax = inEndpoint.getMaxPacketSize();

ByteBuffer byteBuffer = ByteBuffer.allocate(inMax);

UsbRequest usbRequest = new UsbRequest();

usbRequest.initialize(connection, inEndpoint);

usbRequest.queue(byteBuffer, inMax);

if(connection.requestWait() == usbRequest){

   byte[] retData = byteBuffer.array();

}

终止通信:

当您在完成和设备的“交流”之后,又或者该设备被移除了,通过调用releaseInterface()和close()的方法来关闭UseInterface和UsbDeviceConnection。为了监听分离这样的事件,您需要创建一个如下的广播接收器:

1

BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

2

   public void onReceive(Context context, Intent intent) {

3

       String action = intent.getAction();

4

 

5

     if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {

6

           UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

7

           if (device != null) {

8

               // call your method that cleans up and closes communication with the device

9

           }

10

       }

11

   }

12

};

在您的应用中创建这个广播接收器,不是在manifest文件中,允许您的应用只能在它运行的时候处理这样的设备分离事件。这样的话,设备分离这个事件就只向正在运行的应用广播,而不是向所有的应用进行广播。

总结:

我在发送数据的时候,返回的是2,接收返回-1,一直不清楚需要发送的数据是什么格式需要哪些命令,在网上查找了很久也没有找到。

也就只能做到设备接通,但是通信不算成功。

暂时没有时间深入研究了,有兴趣的同学可以查看一下Android的示例代码:Adb test sample,显示了怎样进行异步块数据数据传输,MissleLauncher sample显示了如何监听异步的中断端点。

USB OTG功能如何打开及实现

[Keyword]

USB   OTG   U盘   U-disk  键盘  Keyboard   鼠标 Mouse  PTP devcice

[Solution]

一、检查HW原理图,确认是否支持OTG功能(vbus是否供上电,IDDIG pin连接是否正确)

二、若HW确认支持OTG功能,则按照以下方法分别打开USB OTG功能及实现挂载:

        如何打开USB OTG功能:

            1).在alps/mediatek/config/[project]/autoconfig/kconfig/project中打开CONFIG_USB_MTK_OTG和CONFIG_USB_MTK_HDRC_HCD

                CONFIG_USB_MTK_OTG =y

                CONFIG_USB_MTK_HDRC_HCD = y

            2).在dws中设定OTG VBUS对应的输出控制pin配置为GPIO模式,var name为GPIO_OTG_DRVVBUS_PIN。再设定IDDIG pin默认模式为IDDIG,var name为GPIO_OTG_IDDIG_EINT_PIN

        如何实现挂载:

            1).alps/mediatek/config/[project]/init.project.rc起始位置处添加如下内容

                对于KK以前的版本:

                on early-init

                    mkdir /mnt/usbotg 0000 system system

                对于KK(包含)以后的版本:

                on init

                    mkdir /mnt/media_rw/usbotg 0700 media_rw media_rw

                    mkdir /storage/usbotg 0700 root root

                …

                on boot

                service fuse_usbotg /system/bin/sdcard -u 1023 -g 1023 -w 1023 -d /mnt/media_rw/usbotg /storage/usbotg

                    class late_start

                    disabled

                #

                # Connectivity related services (Begin)

                #

            2).fstab文件末尾添加如下一行

                对于KK以前的版本:

                    修改alps/mediatek/config/[project]/vold.fstab

                    dev_mount usbotg /mnt/usbotg auto /devices/platform/mt_usb

                对于KK(包含)以后的版本:

                    修改alps/mediatek/config/[project]/fstab

                    /devices/platform/mt_usb auto vfat  defaults voldmanaged=usbotg:auto

            3).storage_list.xml添加如下一个xml节点

                对于KK以前的版本:

                <storage android:mountPoint=”/mnt/usbotg”

                       android:storageDescription=”@string/storage_external_usb”

                       android:removable=”true”

                       android:primary=”false” />

                对于KK(包含)以后的版本:

                <storage android:mountPoint=”/storage/usbotg”

                       android:storageDescription=”@string/storage_external_usb”

                       android:removable=”true”

                       android:primary=”false” />

                备注:具体修改哪个路径下的storage_list.xml文件,需要根据ProjectConfig.mk中的resource_overlay_support的值来定

                    对于JB3以下版本,

                        如果RESOURCE_OVERLAY_SUPPORT的值为generic ==>>  则修改alps/mediatek/custom/[project]/resource_overlay/generic/frameworks/base/core/res/res/xml/storage_list.xml

                        如果RESOURCE_OVERLAY_SUPPORT的值为空  ==>> 则修改alps/framework/base/core/res/res/xml/storage_list.xml

                    对于JB3(包含)以上版本,RESOURCE_OVERLAY_SUPPORT的值可根据需要配置为sd_in_ex_otg或sd_ex_otg,则无需再修改该文件

                        sd_in_ex_otg或sd_ex_otg分别表示内卡+外卡+otg或外卡+otg

                        对应文件分别在alps/mediatek/custom/common/sd_in_ex_otg/resource_overlay/generic/frameworks/base/core/res/res/xml/storage_list.xml或alps/mediatek/custom/common/sd_ex_otg/resource_overlay/generic/frameworks/base/core/res/res/xml/storage_list.xml

[Attention]

目前USB OTG功能只支持U盘(FAT格式+一个分区)、Keyboard、Mouse、PTP device

如何打开USB OTG功能:

1).在alps/mediatek/config/[project]/autoconfig/kconfig/project中打开CONFIG_USB_MTK_OTG和CONFIG_USB_MTK_HDRC_HCD

CONFIG_USB_MTK_OTG =y

CONFIG_USB_MTK_HDRC_HCD = y

2).在dws中设定OTG VBUS对应的输出控制pin配置为GPIO模式,var name为GPIO_OTG_DRVVBUS_PIN。再设定IDDIG pin默认模式为IDDIG,var name为GPIO_OTG_IDDIG_EINT_PIN

如何实现挂载:

1).alps/mediatek/config/[project]/init.project.rc起始位置处添加如下内容

对于KK以前的版本:

on early-init

    mkdir /mnt/usbotg 0000 system system

对于KK(包含)以后的版本:

on init

    mkdir /mnt/media_rw/usbotg 0700 media_rw media_rw

    mkdir /storage/usbotg 0700 root root

on boot

service fuse_usbotg /system/bin/sdcard -u 1023 -g 1023 -w 1023 -d /mnt/media_rw/usbotg /storage/usbotg

    class late_start

    disabled

#

# Connectivity related services (Begin)

#

2).fstab文件末尾添加如下一行

对于KK以前的版本:

修改alps/mediatek/config/[project]/vold.fstab

dev_mount usbotg /mnt/usbotg auto /devices/platform/mt_usb

对于KK(包含)以后的版本:

修改alps/mediatek/config/[project]/fstab

/devices/platform/mt_usb auto vfat  defaults voldmanaged=usbotg:auto

3).storage_list.xml添加如下一个xml节点

对于KK以前的版本:

<storage android:mountPoint=”/mnt/usbotg”

       android:storageDescription=”@string/storage_external_usb”

       android:removable=”true”

       android:primary=”false” />

对于KK(包含)以后的版本:

<storage android:mountPoint=”/storage/usbotg”

       android:storageDescription=”@string/storage_external_usb”

       android:removable=”true”

       android:primary=”false” />

备注:具体修改哪个路径下的storage_list.xml文件,需要根据ProjectConfig.mk中的resource_overlay_support的值来定

对于JB3以下版本,

如果RESOURCE_OVERLAY_SUPPORT的值为generic  ==>>  则修改alps/mediatek/custom/[project]/resource_overlay/generic/frameworks/base/core/res/res/xml/storage_list.xml

如果RESOURCE_OVERLAY_SUPPORT的值为空  ==>> 则修改alps/framework/base/core/res/res/xml/storage_list.xml

对于JB3(包含)以上版本,RESOURCE_OVERLAY_SUPPORT的值可根据需要配置为sd_in_ex_otg或sd_ex_otg,则无需再修改该文件

sd_in_ex_otg或sd_ex_otg分别表示内卡+外卡+otg或外卡+otg

对应文件分别在alps/mediatek/custom/common/sd_in_ex_otg/resource_overlay/generic/frameworks/base/core/res/res/xml/storage_list.xml或alps/mediatek/custom/common/sd_ex_otg/resource_overlay/generic/frameworks/base/core/res/res/xml/storage_list.xml

    Android [USB] OTG功能如何打开及实现

     

    USB OTG U盘 Keyboard Mouse

     

    1、检查HW原理图,确认是否支持OTG功能(vbus是否供上电,IDDIG pin连接是否正确)

     

    2、若HW确认支持OTG功能,则按照以下方法分别打开USB OTG功能及实现挂载:

        如何打开USB OTG功能: 在alps/mediatek/config/{project}/autoconfig/kconfig/project中打开CONFIG_USB_MTK_OTG和CONFIG_USB_MTK_HDRC_HCD CONFIG_USB_MTK_OTG =y CONFIG_USB_MTK_HDRC_HCD = y 在dws中设定OTG VBUS对应的输出控制pin配置为GPIO模式,var name为GPIO_OTG_DRVVBUS_PIN。再设定IDDIG pin默认模式为IDDIG,var name为GPIO_OTG_IDDIG_EINT_PIN

            如何实现挂载: init.project.rc起始位置处添加如下内容

            on early-init

            mkdir /mnt/usbotg 0000 system system vold.fstab末尾添加如下一行

            dev_mount usbotg /mnt/usbotg auto /devices/platform/mt_usb storage_list.xml添加如下一个xml节点

            android:storageDescription=@string/storage_external_usb

            android:removable=true

            android:primary=false /> 备注:需要根据ProjectConfig.mk中的resource_overlay_support的值来修改对应路径的storage_list.xml文件 1.RESOURCE_OVERLAY_SUPPORT的值为generic ==>> alps/mediatek/custom/{project}/resource_overlay/generic/frameworks/base/core/res/res/xml/storage_list.xml 2.RESOURCE_OVERLAY_SUPPORT的值为空 ==>> framework/base/core/res/res/xml/storage_list.xml 对于82平台,resource_overlay_support的值可配置为sd_in_ex_otg、sd_ex_otg,则无需再修改对应路径的storage_list.xml文件

             

            [Attention]

            目前USB OTG功能只支持U盘(一个FAT分区)、Keyboard、Mouse、PTP device

    原文作者:马踏草青黄
    原文地址: https://blog.csdn.net/yjy122333/article/details/47311039
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞