1.1PAD作为USB Device设备

USB Device的功能很丰富,其支持的协议越来越多包括:MTP、ADB、rndis、mass storage、accessory、audio_source、CDROOM等。

1.1.1代码简单分析

在代码中涉及到的目录主要有:

1.frameworks/base/services/java/com/android/server/usb/  -----usbService.java用来管理usb协议,其通过property系统与init.xxx.usb.rc通讯。其中UsbDeviceManager.java以及HostManager.java分别管理device和host的设备。

2.init.xxx.usb.rc这里定义了所有usb device协议的组合。当usb device的协议发生变化的时候,会设置sys.usb.config这个属性,init.xxx.usb.rc中定义的某种组合会被触发,通过sys节点来通知kernel切换USB总线协议。

1.1.2常用协议切换

我们常用到的有device协议有ADB、MTP、PTP、MassStorage这几个,这些都是可以在Setting中开关或者是切换的。在切换协议的时候是调用UsbDeviceManager中的setCurrentFunctions(String functions, boolean makeDefault)最终设置sys.usb.config这个属性,从而触发init.xx.usb.rc去通知kernel切换usb协议。UsbDeviceManager.java中同时也监听usb事件的uevent,并通过updateUsbState()发出UsbManager.ACTION_USB_STATE这个广播来通知MtpReceiver和MountService。其中MtpReceiver负责根据所选择的usb协议,启动或者关闭MtpService。

1.1.3Accessory模式

在accessory模式下,PAD是作为Device设备的,通常需要一个支持Accessory的Host设备(ADK2012等)配合才能工作,可以参考如下谷歌文档:

http://developer.android.com/guide/topics/connectivity/usb/index.html

http://developer.android.com/guide/topics/connectivity/usb/accessory.html

http://developer.android.com/guide/topics/connectivity/usb/host.html

Accessory模式下Host端代码可以参考cts/apps/cts-usb-accessory/cts-usb-accessory.c。这里面模拟了一个Host端的设备。其思路是调用system/core/libusbhost/usbhost.c中的usb_host_run()函数,这个函数的主要作用就是去监控/dev/bus/usb/这个目录。

调用如下接口去查询/dev/bus/usb其中的设备是否支持accessory协议

usb_device_control_transfer(device, USB_DIR_IN | USB_TYPE_VENDOR,

ACCESSORY_GET_PROTOCOL, 0, 0, &protocol, sizeof(protocol), 0);

如果支持就调用如下接口尝试将其切换到accessory模式。

usb_device_control_transfer(device, USB_DIR_OUT | USB_TYPE_VENDOR,ACCESSORY_START, 0, 0, 0, 0, 0);

Accessory模式下Device端的代码分析:

drivers/usb/gadget/f_accessory.c中收到ACCESSORY_START这个ioctl后(其实是由usb中断传递上来的)就会发送ACCESSORY=START的uevent。

static void acc_work(struct work_struct *data)

{

char *envp[2] = { "ACCESSORY=START", NULL };

kobject_uevent_env(&acc_device.this_device->kobj, KOBJ_CHANGE, envp);

}

frameworks/base/services/java/com/android/server/usb/UsbDeviceManager.java中,接收到uevent后调用startAccessoryMode();--->setCurrentFunctions(xxx)-->设置sys.usb.config这个属性后,就触发init.xxx.usb.rc去通知kernel切换到accessory模式。

1.1.4Mass_Storage模式

几个重要代码点:

1.UsbDeviceManager监听DEVPATH=/devices/virtual/android_usb/android0"这个路径的UEVENT,

在收到状态改变的时候会发出UsbManager.ACTION_USB_STATE这个broadcast。其中包含connect,configuration状态以及当前的usb配置的function。

2.在MountService收到ACTION_USB_STATE这个广播的时候,notifyShareAvailabilityChange()会调用所有注册的listener的bl.mListener.onUsbMassStorageConnectionChanged(avail);

同时在这里还要处理usb拔出的事件,这里必须把已经shared的盘重新Mount回系统中。

3.StorageManager向Mountservice注册了listener,其他应用又向StorageManager注册listener

主要有如下地方:

UsbStorageActivity.java ---UMS开关界面UI切换

StorageNotification.java----实现状态栏通知(在onUsbMassStorageConnectionChange()中实现,这个函数中可以实现自动弹出usbStorageActivity,关键字POP_UMS_ACTIVITY_ON_CONNECT)

TabletStatusBar.java---------向StorageManager注册listener,用来显示UMS状态栏通知

MtpService.java--------------Mtp状态变化

1.1.5目前SDK中的配置

几种不能共存的配置:

1.多用户和UMS不能共存

----谷歌默认的方式是采用fuse将/data/media模拟成用户盘,这种模式下支持多用户,但是不能支持UMS。如果要支持UMS那么就不能使用fuse,需要划出USER分区,通过Vold来管理。

目前Android4.4的SDK中通过BoradConfig.mk中的BUILD_WITH_UMS这个宏来在二者中切换。

BUILD_WITH_UMS = true即支持UMS不支持多用户

BUILD_WITH_UMS = false即支持多用户但是不支持UMS

2.CDROOM和UMS不能共存

----CDROOM和UMS在kernel中的实现是类似的,都往/sys/class/android_usb/f_mass_storage/lun/file中写入内容来与kernel通讯。

目前Android4.4的SDK中通过BoradConfig.mk中的BUILD_WITH_CDROM来控制是否打开CDROOM,BUILD_WITH_CDROM_PATH来设置iso的路径。注意BUILD_WITH_UMS和BUILD_WITH_CDROM两者应该是互斥的,不能同时设置成true。

1.2PAD作为USB Host设备

当usb口作为host使用时,可以连接u盘,鼠标/键盘,usb音响等设备,针对不同的设备由不同的子系统来处理。

1.2.1输入设备

连接鼠标/键盘/手柄等输入设备时,这些外设被当成是输入设备,归输入子系统管理。设备节点在/dev/input下,输入事件由InputReader调用EventHub来读取,具体请看EventHub的分析。

1.2.2音频设备

外接usb音响等音频设备,这些外设被识别成音频设备,设备节点在/dev/snd/下,归音频系统管理。

1.2.3块设备

连接usb存储设备(u盘,硬盘等)时,设备节点在/dev/bus/usb下,由UsbHostManager.java来管理,简单分析如下:

1)frameworks/base/services/java/com/android/server/usb/UsbService.java中的systemReady()调用mHostManager.systemReady()。

2)frameworks/base/services/java/com/android/server/usb/UsbHostManager.java的systemReady中启动一个线程来运行monitorUsbHostBus();

frameworks/base/services/jni/com_android_server_UsbHostManager.cpp

static void android_server_UsbHostManager_monitorUsbHostBus(JNIEnv *env, jobject thiz)

{

struct usb_host_context* context =usb_host_init();

if (!context) {

ALOGE("usb_host_init failed");

return;

}

// this will never return so it is safe to pass thiz directly

usb_host_run(context, usb_device_added, usb_device_removed, NULL, (void *)thiz);

}

其中分别调用到了system/core/libusbhost/usbhost.c中的usb_host_init(...)和usb_host_run(...)

在usb_host_init()中,最主要的是初始化context->fd = inotify_init();,这个会在后面用来监听/dev/bus/usb目录的创建和删除在usb_host_run中,主要是添加监控的目录ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE);如果发现目录有create或者是delete操作,通知回调函数.

3)在usb_device_added()中,主要是获取usb设备的属性,然后调用UsbHostManager.java中的usbDeviceAdded(),并将这些usb属性传递上去

env->CallVoidMethod(thiz, method_usbDeviceAdded,deviceName, vendorId, productId, deviceClass,

deviceSubClass, protocol, interfaceArray, endpointArray);

4)在UsbHostManager.java中的usbDeviceAdded()中,主要是创建UsbDevice,如下:

UsbDevice device = new UsbDevice(deviceName, vendorID, productID,deviceClass, deviceSubclass, deviceProtocol, interfaces);

mDevices.put(deviceName, device);

mSettingsManager.deviceAttached(device);

5)frameworks/base/services/java/com/android/server/usb/UsbSettingsManager.java中的deviceAttached()函数,主要是检查系统中是否有安装能处理UsbManager.ACTION_USB_DEVICE_ATTACHED这个广播的activity,并转到该activity.

public void deviceAttached(UsbDevice device) {

Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);

intent.putExtra(UsbManager.EXTRA_DEVICE, device);

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

ArrayList matches;

String defaultPackage;

synchronized (mLock) {

matches = getDeviceMatchesLocked(device, intent);

// Launch our default activity directly, if we have one.

// Otherwise we will start the UsbResolverActivity to allow the user to choose.

defaultPackage = mDevicePreferenceMap.get(new DeviceFilter(device));

}

resolveActivity(intent, matches, defaultPackage, device, null);

}

1.2.4libusbhost

libusbhost主要提供与usb设备通信的接口

struct usb_device *usb_device_open(const char *dev_name) ---打开一个usb设备,在/dev/bus/usb/下

void usb_device_close(struct usb_device *device)

void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter)

struct usb_descriptor_header *usb_descriptor_iter_next(struct usb_descriptor_iter *iter) --获取descriptor

int usb_device_claim_interface(struct usb_device *device, unsigned int interface) ----claim一个interface用于通讯

int usb_device_release_interface(struct usb_device *device, unsigned int interface)

int usb_device_bulk_transfer(struct usb_device *device, --------传输数据

int endpoint,

void* buffer,

int length,

unsigned int timeout)

int usb_device_control_transfer(struct usb_device *device, ----------控制指令

int requestType,

int request,

int value,

int index,

void* buffer,

int length,

unsigned int timeout)

在java代码中可以通过一下文件中提供的接口来访问usb设备。

frameworks/base/core/java/android/hardware/usb/UsbManager.java

frameworks/base/core/java/android/hardware/usb/UsbDeviceConnection.java

Android USB系统(一)相关推荐

  1. 基于AOA协议的android USB通信

    摘 要:AOA协议是Google公司推出的用于实现Android设备与外围设备之间USB通信的协议.该协议拓展了Android设备USB接口的功能,为基于Android系统的智能设备应用于数据采集和设 ...

  2. Android手机系统adb常用的命令

     adb常用的命令有哪些?小编今天为大家奉上Android手机系统adb常用的命令,内容如下: 要使用adb命令,手机需要打开USB debug. 安装软件 adb install apk文件名称 ...

  3. Android USB转串口编程

    安卓手机的对外通信接口就只有USB跟音频口,我们可采用其进行与外设进行通信.今天,我们来讲讲安卓手机利用USB接口与外设进行通信.此时,有两种情况. 第一:USB(手机)<--->USB( ...

  4. Android USB 开发详解

    Android USB 开发详解 先附上 Android USB 官方文档 Android通过两种模式支持各种 USB 外设和 Android USB 附件(实现Android附件协议的硬件):USB ...

  5. android USB host编程

    测试手机:华为p8 测试系统:android ------------------------------------------- android的native层usbhost供java层andro ...

  6. 安装windows和android双系统,安装Windows和Android双系统.doc

    安装Windows和Android双系统 轻松搞定Windows和Android双系统 前言:本文介绍在windows操作系统的基础上安装Android,并且正常引导双系统启动.采用先添加启动项,后安 ...

  7. android——wifi系统架构

    1. 系统架构 Android WiFi系统引入了wpa_supplicant,它的整个WiFi系统以wpa_supplicant为核心来定义上层用户接口和下层驱动接口.整个WiFi系统架构如下图所示 ...

  8. Android 音频系统:从 AudioTrack 到 AudioFlinger(全)

    Android 音频框架概述 Audio 是整个 Android 平台非常重要的一个组成部分,负责音频数据的采集和输出.音频流的控制.音频设备的管理.音量调节等,主要包括如下部分: Audio App ...

  9. Android+usb+spi,Android设备如何使用USB的硬件接口

    你知道Android设备如何使用USB的硬件接口吗?下面将由学习啦小编带大家来解答这个疑问吧,希望对大家有所收获! 如何处理硬件接口问题 最近业界的发展显示,智能手机/便携系统与自动化系统或机械系统之 ...

最新文章

  1. 自动化运维工具Ansible
  2. c++ map 的基本操作
  3. linux dmesg命令(显示开机信息)
  4. ASP.NET Core 中文文档 第一章 入门
  5. poj1006生理周期(中国剩余定理)
  6. 苹果电脑 不能使用服务器发送邮件,解决Mac上无法使用的邮件问题的技术
  7. Nginx反向代理 实现Web负载均衡
  8. tuned-adm性能优化工具详解
  9. 微信模板消息400001:invalid credential, access_token is invalid or not latest
  10. mysql乐观锁和悲观锁的区别_mysql悲观锁和乐观锁的区别
  11. Maven下载及安装教程
  12. 我是如何利用一个只有500人的QQ通过人性的弱点来变现的
  13. HTML5如何把圆分成六等分,Photoshop怎么把一个圆64等分?
  14. python-循环语句while
  15. python海龟作图不用循环_我用Python告诉老大爷“啥是佩奇”
  16. PBR来龙去脉十一:IBL继续积分部分
  17. Android SDK 2.1 下载与安装教程
  18. win10系统如何连接到无线显示器?
  19. 【3】 Shell基本系统命令
  20. 企业信息化系统CRM篇

热门文章

  1. HTML基础-笔记1标签
  2. 百度地图API删除指定的覆盖物Marker
  3. ProPresenter 6 for Mac破解版永久激活方法
  4. java计算移动平均值_多种移动平均计算总结(MA,EMA,SMA,DMA,TMA,WMA)
  5. 让我们一起为宝宝选绘本(怎么给宝宝挑选绘本,看完本文就够了)
  6. android绘制虚线
  7. opencv图像合成
  8. 红米note10和红米note8pro哪个好
  9. Error attempting to get column 'state' from result set
  10. win10家庭版用户实现远程桌面解决办法