- USB Accessory
- In this document
- See also
- Choosing the Right USB Accessory APIs
- Installing the Google APIs add-on library
- API Overview
- Usage differences between the add-on library and platform APIs
- Android Manifest requirements
- Manifest and resource file examples
- Working with Accessories
- Discovering an accessory
- Using an intent filter
- Enumerating accessories
- Obtaining permission to communicate with an accessory
- Communicating with an accessory
- Terminating communication with an accessory
- Разработка USB-аксессуаров с поддержкой AOA для Android-систем
USB Accessory
In this document
See also
USB accessory mode allows users to connect USB host hardware specifically designed for Android-powered devices. The accessories must adhere to the Android accessory protocol outlined in the Android Accessory Development Kit documentation. This allows Android-powered devices that cannot act as a USB host to still interact with USB hardware. When an Android-powered device is in USB accessory mode, the attached Android USB accessory acts as the host, provides power to the USB bus, and enumerates connected devices. Android 3.1 (API level 12) supports USB accessory mode and the feature is also backported to Android 2.3.4 (API level 10) to enable support for a broader range of devices.
Choosing the Right USB Accessory APIs
Although the USB accessory APIs were introduced to the platform in Android 3.1, they are also available in Android 2.3.4 using the Google APIs add-on library. Because these APIs were backported using an external library, there are two packages that you can import to support USB accessory mode. Depending on what Android-powered devices you want to support, you might have to use one over the other:
- com.android.future.usb : To support USB accessory mode in Android 2.3.4, the Google APIs add-on library includes the backported USB accessory APIs and they are contained in this namespace. Android 3.1 also supports importing and calling the classes within this namespace to support applications written with the add-on library. This add-on library is a thin wrapper around the android.hardware.usb accessory APIs and does not support USB host mode. If you want to support the widest range of devices that support USB accessory mode, use the add-on library and import this package. It is important to note that not all Android 2.3.4 devices are required to support the USB accessory feature. Each individual device manufacturer decides whether or not to support this capability, which is why you must declare it in your manifest file.
- android.hardware.usb : This namespace contains the classes that support USB accessory mode in Android 3.1. This package is included as part of the framework APIs, so Android 3.1 supports USB accessory mode without the use of an add-on library. Use this package if you only care about Android 3.1 or newer devices that have hardware support for USB accessory mode, which you can declare in your manifest file.
Installing the Google APIs add-on library
If you want to install the add-on, you can do so by installing the Google APIs Android API 10 package with the SDK Manager. See Installing the Google APIs Add-on for more information on installing the add-on library.
API Overview
Because the add-on library is a wrapper for the framework APIs, the classes that support the USB accessory feature are similar. You can use the reference documentation for the android.hardware.usb even if you are using the add-on library.
Note: There is, however, a minor usage difference between the add-on library and framework APIs that you should be aware of.
The following table describes the classes that support the USB accessory APIs:
Class | Description |
---|---|
UsbManager | Allows you to enumerate and communicate with connected USB accessories. |
UsbAccessory | Represents a USB accessory and contains methods to access its identifying information. |
Usage differences between the add-on library and platform APIs
There are two usage differences between using the Google APIs add-on library and the platform APIs.
If you are using the add-on library, you must obtain the UsbManager object in the following manner:
If you are not using the add-on library, you must obtain the UsbManager object in the following manner:
When you filter for a connected accessory with an intent filter, the UsbAccessory object is contained inside the intent that is passed to your application. If you are using the add-on library, you must obtain the UsbAccessory object in the following manner:
If you are not using the add-on library, you must obtain the UsbAccessory object in the following manner:
Android Manifest requirements
The following list describes what you need to add to your application’s manifest file before working with the USB accesory APIs. The manifest and resource file examples show how to declare these items:
- Because not all Android-powered devices are guaranteed to support the USB accessory APIs, include a element that declares that your application uses the android.hardware.usb.accessory feature.
- If you are using the add-on library, add the element specifying com.android.future.usb.accessory for the library.
- Set the minimum SDK of the application to API Level 10 if you are using the add-on library or 12 if you are using the android.hardware.usb package.
If you want your application to be notified of an attached USB accessory, specify an and element pair for the android.hardware.usb.action.USB_ACCESSORY_ATTACHED intent in your main activity. The element points to an external XML resource file that declares identifying information about the accessory that you want to detect.
In the XML resource file, declare elements for the accessories that you want to filter. Each can have the following attributes:
Save the resource file in the res/xml/ directory. The resource file name (without the .xml extension) must be the same as the one you specified in the element. The format for the XML resource file is also shown in the example below.
Manifest and resource file examples
The following example shows a sample manifest and its corresponding resource file:
In this case, the following resource file should be saved in res/xml/accessory_filter.xml and specifies that any accessory that has the corresponding model, manufacturer, and version should be filtered. The accessory sends these attributes the Android-powered device:
Working with Accessories
When users connect USB accessories to an Android-powered device, the Android system can determine whether your application is interested in the connected accessory. If so, you can set up communication with the accessory if desired. To do this, your application has to:
- Discover connected accessories by using an intent filter that filters for accessory attached events or by enumerating connected accessories and finding the appropriate one.
- Ask the user for permission to communicate with the accessory, if not already obtained.
- Communicate with the accessory by reading and writing data on the appropriate interface endpoints.
Discovering an accessory
Your application can discover accessories by either using an intent filter to be notified when the user connects an accessory or by enumerating accessories that are already connected. Using an intent filter is useful if you want to be able to have your application automatically detect a desired accessory. Enumerating connected accessories is useful if you want to get a list of all connected accessories or if your application did not filter for an intent.
Using an intent filter
To have your application discover a particular USB accessory, you can specify an intent filter to filter for the android.hardware.usb.action.USB_ACCESSORY_ATTACHED intent. Along with this intent filter, you need to specify a resource file that specifies properties of the USB accessory, such as manufacturer, model, and version. When users connect an accessory that matches your accessory filter,
The following example shows how to declare the intent filter:
The following example shows how to declare the corresponding resource file that specifies the USB accessories that you’re interested in:
In your activity, you can obtain the UsbAccessory that represents the attached accessory from the intent like this (with the add-on library):
or like this (with the platform APIs):
Enumerating accessories
You can have your application enumerate accesories that have identified themselves while your application is running.
Use the getAccessoryList() method to get an array all the USB accessories that are connected:
Note: Currently, only one connected accessory is supported at one time, but the API is designed to support multiple accessories in the future.
Obtaining permission to communicate with an accessory
Before communicating with the USB accessory, your applicaton must have permission from your users.
Note: If your application uses an intent filter to discover accessories as they’re connected, it automatically receives permission if the user allows your application to handle the intent. If not, you must request permission explicitly in your application before connecting to the accessory.
Explicitly asking for permission might be neccessary in some situations such as when your application enumerates accessories that are already connected and then wants to communicate with one. You must check for permission to access an accessory before trying to communicate with it. If not, you will receive a runtime error if the user denied permission to access the accessory.
To explicitly obtain permission, first create a broadcast receiver. This receiver listens for the intent that gets broadcast when you call requestPermission() . The call to requestPermission() displays a dialog to the user asking for permission to connect to the accessory. The following sample code shows how to create the broadcast receiver:
To register the broadcast receiver, put this in your onCreate() method in your activity:
To display the dialog that asks users for permission to connect to the accessory, call the requestPermission() method:
When users reply to the dialog, your broadcast receiver receives the intent that contains the EXTRA_PERMISSION_GRANTED extra, which is a boolean representing the answer. Check this extra for a value of true before connecting to the accessory.
Communicating with an accessory
You can communicate with the accessory by using the UsbManager to obtain a file descriptor that you can set up input and output streams to read and write data to descriptor. The streams represent the accessory’s input and output bulk endpoints. You should set up the communication between the device and accessory in another thread, so you don’t lock the main UI thread. The following example shows how to open an accessory to communicate with:
In the thread’s run() method, you can read and write to the accessory by using the FileInputStream or FileOutputStream objects. When reading data from an accessory with a FileInputStream object, ensure that the buffer that you use is big enough to store the USB packet data. The Android accessory protocol supports packet buffers up to 16384 bytes, so you can choose to always declare your buffer to be of this size for simplicity.
Note: At a lower level, the packets are 64 bytes for USB full-speed accessories and 512 bytes for USB high-speed accessories. The Android accessory protocol bundles the packets together for both speeds into one logical packet for simplicity.
For more information about using threads in Android, see Processes and Threads.
Terminating communication with an accessory
When you are done communicating with an accessory or if the accessory was detached, close the file descriptor that you opened by calling close() . To listen for detached events, create a broadcast receiver like below:
Creating the broadcast receiver within the application, and not the manifest, allows your application to only handle detached events while it is running. This way, detached events are only sent to the application that is currently running and not broadcast to all applications.
Источник
Разработка USB-аксессуаров с поддержкой AOA для Android-систем
Garima Gupta, Joshan Abraham
Теперь разработчики могут сделать свои разработки аксессуаров совместимыми с протоколом Android Open Accessory (AOA)
Стремительный рост использования основанных на Android мобильных интернет-устройств, планшетов и других продуктов начался с 2008 года, и сегодня Android-устройства занимают 70% мобильного рынка. Аналогичным образом происходит рост числа и разновидностей USB-устройств, подключаемых к устройствам на базе Android, от простейших аудио док-станций до сложного медицинского оборудования. Разработчики, оглядываясь на этот растущий рынок, должны быть уверены, что их устройства удовлетворяют требованиям протокола Android Open Accessory (AOA).
USB и Android
Взаимодействие через порт USB между устройством на Android и периферийным USB-устройством или аксессуаром должно происходить в соответствии со спецификацией USB. USB – это хост-ориентированный протокол, означающий, что все транзакции инициирует хост, и что на шине он может быть только один. То есть, USB-хост обязательно должен присутствовать среди соединяемых устройств. Таким образом, Android-устройство может сопрягаться с USB- устройством одним из двух различных способов: в режиме USB-хоста (подключенное устройство называется USB-периферией) и в режиме USB-аксессуара (подключенное устройство называется USB-аксессуаром).
Рисунок 1. | Android-устройство при подключении к периферии работает в режиме USB-хоста. |
В режиме USB-хоста Android-устройство выступает в роли управляющего узла, подает питание на шину, регистрирует подключенные к нему периферийные USB-устройства. К работающим в этом режиме Android-устройствам обычно подключается такая периферия, как клавиатуры, мыши и игровые контроллеры (Рисунок 1).
Запущенные в режиме USB-хоста Android-устройства, отдавая подключенному устройству ток до 500 мА, истощают свой аккумулятор, особенно в случае прожорливой периферии. К таковой обычно относятся медицинское и диагностическое оборудование, тренажеры, док-станции, портативные торговые терминалы и автомобильные панели с подключением к Android, а также множество других устройств.
Кроме того, некоторые Android-устройства не имеют аппаратного USB-хоста, необходимого для поддержки передачи данных в хост-режиме. Android-устройства, в большинстве своем, имеют конкретный перечень USB-устройств, называемый целевым списком периферии (target peripheral list – TPL), которые они могут поддерживать. В таких случаях устройства, отсутствующие в TPL, нуждаются в передаче данных альтернативным способом.
Режим USB-аксессуара преодолевает ограничения режима USB-хоста за счет того, что в качестве хоста выступает внешнее устройство. Аксессуар подает питание на шину USB и осуществляет обмен данными с Android-устройстом (Рисунок 2).
Рисунок 2. | Android-устройство может также работать в режиме USB-аксессуара. |
Android-устройства, которые не могут выступать в качестве USB-хоста, в таком случае могут взаимодействовать с USB-аксессуаром. Такие аксессуары питаются от больших аккумуляторов или от сети.
Эти Android-устройства и аксессуары должны придерживаться протокола AOA, определяющего, как аксессуар обнаруживает и устанавливает соединение с Android-устройством. Предполагается выполнение аксессуаром следующих четырех шагов, определенных спецификацией AOA:
- Ожидание и обнаружение подключенных устройств
- Определение наличия у устройства режима поддержки аксессуара
- Попытка запуска устройства в режиме аксессуара (при необходимости)
- Установление связи с устройством, если оно поддерживает протокол AOA
Поддержка AOA доступна в Android 3.1 и выше, но она также может быть портирована на Android 2.3.4 посредством дополнительной библиотеки. Даже устройства человеко-машинного интерфейса, такие как клавиатура и мышь, которые обычно подключаются в режиме USB-хоста, могут использоваться в режиме USB-аксессуара посредством AOA 2.0.
Различные рекомендации и шаги для добавления возможностей AOA к существующим конструкциям аксессуаров обсуждаются ниже. Они же могут применяться и при разработке новых аксессуаров. Типичная реализация при расширении до поддержки Android потребует добавления USB-хоста к существующему аксессуару и установления интерфейса обмена данными между ним и микроконтроллером (МК) аксессуара (Рисунок 3).
Рисунок 3. | Типичная реализация при расширении до поддержки Android потребует добавления USB-хоста к существующему аксессуару и установления интерфейса обмена данными между ним и микроконтроллером аксессуара. |
Первым шагом будет оценка доступных ресурсов МК аксессуара. Два основных момента, на которые следует обратить внимание – это память и коммуникационный блок. Непременным условием использования кода для обмена данными, управления микросхемой хоста и реализации стека протокола AOA является наличие достаточного объема памяти, как RAM, так и флэш. Блок коммуникации может включать шины SPI/UART/I 2 C или линии ввода-вывода общего назначения.
Для осуществления обмена данными с микросхемой USB-хоста требуется протокол передачи данных подобный SPI/UART/I 2 C. Для этих целей системе требуется также аппаратный блок коммуникации, а если таковой отсутствует, программный стек протокола обмена должен быть реализован средствами ПО, что часто называют еще режимом «bit-banging». Выбранные порты ввода-вывода должны быть совместимы с протоколом, необходимым для связи с микросхемой хоста.
К примеру, при реализации программного модуля мастера SPI на микроконтроллере периферийного устройства, вывод, выбранный в качестве SPI_Clock, должен иметь возможность управляться на тактовой частоте, определяемой требованиями пропускной способности. Точно также, аппаратный SPI-мастер на МК аксессуара даст гибкость в организации обмена данными с подчиненным устройством SPI (контроллером USB-хоста). В этом случае, может потребоваться еще один дополнительный вывод порта ввода-вывода общего назначения (GPIO) для запросов прерываний от микросхемы хоста и один GPIO для сигнала Slave_Select подчиненного устройства SPI. При наличии в системе других подчиненных устройств SPI могут использоваться одни и те же линии MOSI, SPI_Clock и MISO.
Следующий шаг – это выбор подходящей микросхемы USB-хоста, соответствующей возможностям МК и обеспечивающей оптимальные характеристики аксессуара. Тут есть три основных фактора: тип микросхемы (программируемая или с фиксированным функционалом), протокол обмена данными микросхемы хоста и желаемая производительность.
Наиболее простым типом микросхем USB-хоста являются микросхемы с механизмом последовательного интерфейса (SIE), которые предоставляют МК аксессуара полный контроль над передачей данный по USB. МК контролирует каждый пакет данных на шине USB. Такая реализация требует больше памяти программ на МК аксессуара, в связи с чем она не рекомендуется при ограниченных ресурсах памяти МК.
Другая разновидность микросхем хоста имеет встроенные микроконтроллеры, которые могут быть запрограммированы на управление пакетами данных USB любым желаемым образом. Такие контроллеры хоста снижают нагрузку на МК аксессуара, уменьшая одновременно затраты памяти и рабочую загрузку МК. Такая микросхема хоста обладает полным встроенным функционалом стека, оставляя МК аксессуара только обмен данными и отправку специальных управляющих команд для общения с Android-устройством.
Например, запрограммировав микросхему хоста, можно послать запрос Get_Descriptor на получение по SPI специального кода от МК аксессуара. Такие микросхемы могут посылать данные как на МК аксессуара, так и на любое другое подчиненное устройство на шине SPI. При разработке новых аксессуаров эти микросхемы можно использовать в автономном режиме, то есть без внешнего управляющего МК.
Оба типа контроллеров хоста предоставляют широкий спектр коммуникационных интерфейсов, таких как SPI, I 2 C, UART, высокоскоростной последовательный (HSS) и параллельный интерфейсы (такие, как интерфейс внешней памяти или интерфейс процессора). Через любой из этих интерфейсов МК может иметь полный контроль над функционированием USB-хоста. Интерфейсы могут также использоваться для обновления прошивок микросхемы хоста.
Наличие таких интерфейсов позволяет гибко выбирать любую скорость обмена данными. Каждый из них может осуществлять обмен, используя от трех (3-проводная коммуникация по SPI) до n линий (для параллельных интерфейсов), в зависимости от возможностей и потребностей. Основываясь на аппаратных ресурсах, доступных в МК аксессуара, мы можем выбрать наилучший протокол обмена данными. Но даже при отсутствии свободных аппаратных ресурсов в МК аксессуара, можно использовать четыре вывода порта общего назначения, а стек SPI реализовать в прошивке.
Еще одним фактором, влияющим на выбор микросхемы хоста, является требование к USB-хосту: должен ли он быть полноскоростным или высокоскоростным. Полноскоростной режим (full-speed, USB 1.1) поддерживает скорость передачи данных до 12 Мбит/с. В высокоскоростном режиме (high-speed) микросхема хоста обеспечивает скорость до 480 Мбит/с, и обычно имеет параллельный интерфейс для обмена данными и управляющей логики, необходимый для достижения высокой пропускной способности. Некоторые высокоскоростные микросхемы хоста также имеют SPI, I 2 C или другие коммуникационные интерфейсы. У отдельных микросхем есть даже программируемый параллельный интерфейс, который, продолжая поддерживать пропускную способность высокоскоростного режима USB, может быть настроен для удовлетворения любых специфических требований сопряжения МК аксессуара.
Обмен данными для аксессуаров с ограниченными ресурсами упрощает программируемый полноскоростной USB хост-контроллер, содержащий высокоскоростной последовательный интерфейс с конфигурируемой скоростью передачи данных, SPI (ведущий/ведомый) и параллельный интерфейс. Кроме того, интерфейс внешней памяти и EEPROM c интерфейсом I 2 C предоставляют ресурс для внешнего хранения кода программы, чем еще больше облегчают добавление поддержки AOA к существующей разработке. Альтернативный вариант хост-контроллера может иметь только прямой порт данных и микропроцессорный интерфейс со стандартными МК.
Следующим шагом после выбора протокола обмена данными и интерфейсного хост-контроллера является реализация логики сопряжения и управления. Как обсуждалось ранее, существует два вида микросхем: с фиксированным функционалом и программируемые. При использовании простых микросхем с заданным функционалом микроконтроллер должен управлять каждым событием, происходящим на шине USB. Даже такие события, как подключение USB-устройства, будут сообщать о себе, вызывая прерывание, либо должны отслеживаться посредством чтения регистров состояния. Для использования простых микросхем с функционалом SIE в код микроконтроллера аксессуара будет необходимо добавить следующие функции:
- Элементарные функции:
чтение регистра, запись в регистр, запись нескольких байт в заданное место (например, запись в FIFO) и чтение байт данных из указанного места (чтение из FIFO). - Функции, использующие элементарные функции для управления работой микросхемы хоста:
инициализация микросхемы хоста, обнаружение подключения устройства, обнаружение отключения устройства, сброс микросхемы, обработка ошибок при их возникновении, команда перевода USB в режим ожидания, команда продолжения работы USB, управление операциями чтения (фазы подготовки, данных и подтверждения), управление операциями записи, за исключением фазы данных, управление операцией записи с фазой данных, обработка входящих (IN) составных данных (метка IN, принятые данные, подтверждение) и аналогичная обработка исходящих (OUT) составных данных (протокол AOA поддерживает обмен данными только между составными узлами). - Функции, использующие описанные выше функции и реализующие функционал уровня протокола:
обнаружение PID_VID, установка интерфейса, получение интерфейса, отправка данных (через составной узел), прием данных и т. д.
Для программируемых микросхем хоста управляющие функции в МК аксессуара могут быть простыми внутренними командами, отправляемыми посредством интерфейса передачи данных.
Заключительным шагом является реализация протокола AOA в аксессуаре. Он, в первую очередь, состоит из четырех основных шагов, определенных в спецификации AOA и упомянутых ранее: ожидание и обнаружение подключенных устройств, оценка поддержки режима аксессуара устройством, попытка, при необходимости, запуска устройства в режиме аксессуара и установление соединения с устройством, если оно поддерживает протокол Android-аксессуара.
Ожидание и обнаружение подключенных устройств
На первом шаге аксессуар должен ожидать события, вызываемого подключением устройства (например, телефона на Android). Подключение устройства отмечается подтяжкой линий D+/D– шины USB. D+ подтягивается к высокому уровню, если подключено устройство в режиме full-speed или high-speed, а в случае низкоскоростного соединения к высокому уровню подтягивается линия D–. Другими словами, вы можете опрашивать состояние линии и ожидать перехода шины в состояние J или K.
Вторым шагом является обеспечение задержки в 100 мс. Как указано в спецификации USB «Это интервал устранения дребезга с минимальной продолжительностью 100 мс, который обеспечивается системным ПО USB. Он гарантирует стабильность электрического и механического подключения перед тем, как ПО предпримет попытку сброса присоединенного устройства. Отсчет интервала начинается, когда системное ПО USB будет оповещено об обнаружении подключения. Интервал сбрасывается в случае отключения. Противодребезговый интервал гарантирует, что питание на устройстве будет стабильно присутствовать в течение не менее чем 100 мс до того, как ему будут отправлены какие-либо запросы».
На третьем шаге микросхема USB-хоста аксессуара инициирует сброс Android-устройства. Под состоянием «сброса» подразумевается переход шины в состояние SE0. В течение этого времени, если на линии D+ обнаружена подтяжка, микросхема полноскоростного хоста должна производить так называемое «чириканье» (chirp sequence) для обнаружения высокоскоростного подключения Android-устройства. Если используется полноскоростной хост, он не будет выдавать «чириканья», и высокоскоростное устройство будет работать в режиме full-speed. Микросхема хоста обычно также следит за выполнением вспомогательных функций USB.
Четвертым шагом после сброса является предоставление подключенному устройству минимального времени восстановления после сброса 10 мс.
Определение наличия поддержки у устройства режима аксессуара
На пятом шаге должен быть послан запрос «Get Device Descriptor» («Получить дескриптор устройства») по адресу «0», а затем при помощи команды «Set Address» («Установить адрес») установлен адрес устройства в любое желаемое значение.
В качестве шестого шага на этот новый адрес посылаются все последующие USB запросы, чтобы убедиться, что устройство по этому адресу доступно. Послатются запросы «Get Device Descriptor» и «Get Configuration» («Получить конфигурацию»). Это необязательный шаг.
На седьмом этапе производится проверка, совпадает ли PID_VID устройства с PID_VID Google. После отправки запроса «Get Device Descriptor» из полученного описания выбираются данные по PID_VID устройства. Идентификатор продукта (PID) и идентификатор разработчика (VID) устройства обычно являются идентификаторами производителя устройства.
Если устройство поддерживает режим AOA и запущено в нем, оно будет отвечать посылкой VID и PID Google (VID==0x18D1 и PID==0x2D00||PID==0x2D01) вместо идентификаторов производителя устройства. Если устройство обнаружено с идентификаторами Google, аксессуар может сделать вывод о том, что найдено Android-устройство, поддерживающее AOA, и он может установить с ним обмен данными. В этом случае нужно пропустить шаги с 8 по 11 и перейти сразу к 12. Необходимо учитывать, что оба PID имеют различный смысл. Если устройство обозначено идентификатором производителя, продолжить с шага 5.
На восьмом шаге проверяется, поддерживает ли подключенное устройство режим AOA. Для этой проверки используется управляющий запрос со значениями, приведенными в Таблице 1.
Источник