美文网首页
USB 功能简介

USB 功能简介

作者: 衣谷文武 | 来源:发表于2018-08-13 21:36 被阅读0次

    USB OTG: USB On-The-Go的简称,是USB 2.0规定的补充标准,它可以使手机等作为USB主机,和其他USB设备连接通信,例如U盘,另外的手机,USB Hub等。

    Android对Usb的支持是从3.1开始的,显然是加强Android平板的对外扩展能力。而对Usb使用更多的,是Android在工业中的使用。Android工业板子一般都会提供多个U口和多个串口,它们是连接外设的手段与桥梁。

    USB OTG是通过OTG线连接通信,OTG线一头是公头连接手机USB HOST,一头母头接外设。如图一连接通信。

    Android USB代码分析

    在路径/frameworks/base/core/java/android/hardware/usb/下,这个包内包含了USB相关的类。

    1,USBManager:定义了USB的action和参数,获取USB的状态,与连接的USB设备通信。

    方法getDeviceList获取到所有连接的USB device的HashMap

    方法openDevice 与USB设备通信

    当有USB设备连接时,会发送广播ACTION_USB_DEVICE_ATTACHED。

    public static final StringACTION_USB_DEVICE_ATTACHED =

               "android.hardware.usb.action.USB_DEVICE_ATTACHED";

    当有USB设备移除时,会发送广播ACTION_USB_DEVICE_DETACHED。

     publicstatic final String ACTION_USB_DEVICE_DETACHED =

               "android.hardware.usb.action.USB_DEVICE_DETACHED";

    2, UsbDevice:Usb设备的抽象,它包含一个或多个UsbInterface,而每个UsbInterface包含多个UsbEndpoint。Host与其通信,先打开UsbDeviceConnection,使用UsbRequest在一个端点(endpoint)发送和接收数据。

    3,UsbInterface:定义了设备的功能集,一个UsbDevice包含多个UsbInterface,每个Interface都是独立的。

    4,UsbEndpoint:endpoint是interface的通信通道。

    5,UsbDeviceConnection:host与device建立的连接,并在endpoint传输数据。

     6,UsbRequest:USB 请求包。可以在UsbDeviceConnection上异步传输数据。注意是只在异步通信时才会用到它。

    7,UsbConstants:USB常量的定义。

      Settings中USB界面

    Settings界面代码主要由UsbModeChooserActivity和UsbBackend显示USB选项,

    UsbBackend中通过方法setUsbFunction调用UsbManager中setCurrentFunction,设置不同的USB连接模式,如

           mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true);

    设置USB模式为MTP,同理也可设置为PTP,MIDI等。这个方法第二参数true/false是设置是否可以通过USB连接传输数据,当为true时,就可以传输数据,当为false时,USB连接仅为充电,无法访问手机上文件。

    通过方法getUsbDataMode()可以获取当前USB连接模式,UsbModeChooserActivity通过这个方法显示当前的USB连接模式。

    方法isModeSupported判断这种USB模式是否支持,只有支持的模式才会在选项中显示。

    UsbModeChooserActivity弹出的USB选项Dialog,包含支持的USB连接模式。

    3.3 USB OTG界面

    手机通过OTG线连接U盘之类的外设,会通过SystemUI中StorageNotification,添加了对Storage的监听,

    当volume状态发生变化时,会在onVolumeStateChangedInternal做对应提示。

       private final StorageEventListener mListener = newStorageEventListener() {

            @Override

            public void onVolumeStateChanged(VolumeInfo

    vol, int oldState, intnewState) {

                onVolumeStateChangedInternal(vol);

            }

     刚通过OTG线连接U盘,调用onVolumeChecking显示checking U盘的提示。

       privateNotificationonVolumeChecking(VolumeInfo vol) {

            finalDiskInfo disk = vol.getDisk();

            final CharSequence title = mContext.getString(

                    R.string.ext_media_checking_notification_title, disk.getDescription());

            final CharSequence text = mContext.getString(

                    R.string.ext_media_checking_notification_message, disk.getDescription());

            returnbuildNotificationBuilder(vol, title, text)

                    .setCategory(Notification.CATEGORY_PROGRESS)

                    .setOngoing(true)

                    .build();

       }

     当U盘状态为MOUNTED时,调用onVolumeMounted更新U盘提示,当U盘移除时,调用onVolumeRemoved或者onVolumeBadRemoval,提示已经移除U盘。

     这个通过OTG线连接U盘,显示的提示和插入SD卡类似,都可以点击Notification进入DocumentsUI,浏览和操作U盘中的文件。

    手机通过OTG线与另外手机连接时,在MtpDocumentsProvider这个应用中有ReceiverActivity有监听

    android.hardware.usb.action.USB_DEVICE_ATTACHED 这个广播,当主机通过OTG线连接另一台手机时,

    接收到这个广播,从广播中获取到连接设备信息,创建相应的Uri,把Uri传给启动DocumentsUI的intent,

    在启动DocumentsUI后,另外一台手机的USB连接模式未MTP,PTP时,主机就能查看和操作从机的文件。当是charging only状态,主机无法访问从机文件。

    public class ReceiverActivity extends Activity {

       @Override

       protected voidonCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            if(UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(getIntent().getAction())) {

                final UsbDevice device = getIntent().getParcelableExtra(UsbManager.EXTRA_DEVICE);

                try{

                    finalMtpDocumentsProvider provider =MtpDocumentsProvider.getInstance();

                    provider.openDevice(device.getDeviceId());

                    finalString deviceRootId =provider.getDeviceDocumentId(device.getDeviceId());

                    finalUri uri = DocumentsContract.buildRootUri(

                            MtpDocumentsProvider.AUTHORITY,deviceRootId);

                    final Intent intent = newIntent(Intent.ACTION_VIEW);

                    intent.setDataAndType(uri,DocumentsContract.Root.MIME_TYPE_ITEM);

                    intent.addCategory(Intent.CATEGORY_DEFAULT);

                    this.startActivity(intent);

                }catch(IOException exception) {

                    Log.e(MtpDocumentsProvider.TAG,"Failed to open

    device", exception);

                }

            }

            finish();

       }

    }

     同时也是在MtpDocumentsProvider的UsbIntentReceiver,这个receiver会监听OTG插拔两个广播

    android.hardware.usb.action.USB_DEVICE_ATTACHEDandroid.hardware.usb.action.USB_DEVICE_DETACHED

    public class UsbIntentReceiver extendsBroadcastReceiver {

       @Override

       public voidonReceive(Context context, Intent intent) {

            final UsbDevice device = intent.getExtras().getParcelable(UsbManager.EXTRA_DEVICE);

            switch(intent.getAction()) {

                case UsbManager.ACTION_USB_DEVICE_ATTACHED:

                    MtpDocumentsProvider.getInstance().resumeRootScanner();

                    break;

                case UsbManager.ACTION_USB_DEVICE_DETACHED:

                    try{

                        MtpDocumentsProvider.getInstance().closeDevice(device.getDeviceId());

                    }catch(IOException | InterruptedException e) {

                        Log.e(MtpDocumentsProvider.TAG,"Failed to close

    device", e);

                    }

                    break;

            }

       }

    }

     通过在MtpDocumentsProvider中初始化ServiceIntentSender,通过调用sendUpdateNotificationIntent显示手机连接的提示。

    USB和底层交互

    在android中很多地方使用到了UEvent机制,如图:像HDMI,Battery,USB相关等;当我们需要接受底层的UEvent的时候,我们就需要注册一个UEventObserver。Kernel层和framework层交互通过UeventObserver。在USB插拔时,在UsbDeviceManager中有注册UEventObserver,监听USB的uevent,当有uevent事件上传,获取对应的USB状态,和连接的设备之类。

        /*

         * Listensfor uevent messages from the kernel to monitor the USB state

         */

        private final UEventObserver mUEventObserver = newUEventObserver() {

            @Override

            public voidonUEvent(UEventObserver.UEvent event) {

                if (DEBUG) Slog.v(TAG, "USB UEVENT:

    " + event.toString());

                Stringstate = event.get("USB_STATE");

                Stringaccessory = event.get("ACCESSORY");

                if (state != null) {

                    mHandler.updateState(state);

                }else if ("START".equals(accessory)) {

                    if (DEBUG) Slog.d(TAG, "got

    accessory start");

                    startAccessoryMode();

                }

            }

        };

    mUEventObserver通过 startObserving加入想要监听的uevent,当对应事件上传,就会在对应onUEvent作出对应处理。

                    // Watch for USB configuration

    changes

                    mUEventObserver.startObserving(USB_STATE_MATCH);

                    mUEventObserver.startObserving(ACCESSORY_START_MATCH);

    startObserving这个方法转到UEventThread中,UEventThread是UeventObserver的内部类,run中一个死循环,不断监听底层的uevent,然后发送uevent。

            @Override

            public voidrun() {

                nativeSetup();

                while (true) {

                    Stringmessage =nativeWaitForNextEvent();

                    if (message != null) {

                       if (DEBUG) {

                           Log.d(TAG, message);

                       }

                       sendEvent(message);

                    }

                }

            }

    USB插拔的后续处理就根据uevent上传的状态在updateState方法中赋值connected,configured,通过Handler发送Message:MSG_UPDATE_STATE,包含connected,configured,在UsbHandler中handleMessage中更新USB,adb的Notification,上层界面显示。

            public void  updateState(String state){

                int connected, configured;

                if ("DISCONNECTED".equals(state)) {

                    connected= 0;

                    configured= 0;

                }else if ("CONNECTED".equals(state)) {

                    connected= 1;

                    configured= 0;

                }else if ("CONFIGURED".equals(state)) {

                    connected= 1;

                    configured= 1;

                }else{

                    Slog.e(TAG, "unknown

    state "+ state);

                    return;

                }

                removeMessages(MSG_UPDATE_STATE);

                Messagemsg = Message.obtain(this, MSG_UPDATE_STATE);

                msg.arg1= connected;

                msg.arg2= configured;

                // debounce disconnects to avoid

    problems bringing up USB tethering

                sendMessageDelayed(msg,(connected == 0) ?UPDATE_DELAY: 0);

            }

    UsbHostManager中从jni回调beginUsbDeviceAdded-》addUsbConfiguration-》addUsbInterface-》addUsbEndpoint-》endUsbDeviceAdded

    通过这些方法把USB OTG device挂载上,手机当成USB主机,可以通过USB连接模式,传输数据等。

    相关文章

      网友评论

          本文标题:USB 功能简介

          本文链接:https://www.haomeiwen.com/subject/wqdpbftx.html