Не работает usb host на андроид

Обновлено: 04.07.2024

Когда устройство на базе Android работает в режиме USB host, оно становится главным устройством на шине USB, подает питание на шину, и производит энумерацию для подключенных к шине устройств USB. Режим хоста USB поддерживается в Android 3.1 и более новых версиях. Непонятные термины касательно шины USB см. в USB in a NutShell [2] (на русском языке), а непонятные термины и сокращения, касающиеся Androd, в Словарике [5].

[Обзор API]

Таблица 1. USB Host API.

В большинстве ситуаций Вам нужно использовать все эти классы (UsbRequest требуется только если Вы осуществляете асинхронную связь), когда происходит взаимодействие с устройством USB device. Обычно Вы задействуете UsbManager для получения доступа к нужному UsbDevice. Когда Вы получили устройство USB, то для обмена данными нужно найти подходящий интерфейс UsbInterface и конечную точку UsbEndpoint на этом интерфейсе. Как только Вы получили правильную конечную точку, откройте соединение UsbDeviceConnection для обмена данными с устройством USB.

[Требования к Android Manifest]

Следующий список описывает, что Вам нужно добавить в манифест приложения перед тем, как начать работать с USB host API:

В XML-файле ресурсов продекларируйте элементы < usb-device > для устройств USB, которые хотите отфильтровать. Следующий список описывает атрибуты элемента < usb-device >. Обычно указываются идентификаторы вендора (vendor ID, VID) и продукта (product ID, PID), если хотите фильтровать специфическое устройство, и используется class, subclass и protocol, если хотите фильтровать группы (классы) устройств USB, такие как устройства хранения (mass storage devices, MSD) или цифровые камеры. Вы можете не указывать ни одного из этих атрибутов, в этом случае фильтрация подойдет под любое устройство USB, не только то, что Вам нужно. Вот имена атрибутов для устройств USB:

vendor-id
product-id
class
subclass
protocol (device или interface)

Сохраните XML-файл ресурсов в директории res/xml/ . Имя файла ресурса (без расширения .xml) должно быть то же самое, как указано в элементе < meta-data >. Формат файла ресурса XML показан в примере ниже (пример манифеста и соответствующего ему файла ресурсов):

В этом случае следующий файл ресурсов будет сохранен в файл res/xml/device_filter.xml (здесь указано, что должно фильтроваться любое устройство USB с указанными параметрами):

Примечание: указанные здесь в текстовом виде значения VID (vendor-id) и PID (product-id) должны быть не в шестнадцатеричном виде, а в десятичном. Таким образом, если например у Вас VID=0x16C0, PID=0x05DF, то вы должны преобразовать эти шестнадцатеричные значения в десятичные, и их в текстовом виде указать в XML:

VID 0x16C0 -> 5824
PID 0x05DF -> 1503

Если необходимо, чтобы под фильтр попадали все без исключения подключаемые устройства USB, то просто удалите из элемента usb-device его атрибуты:

[Как работать с устройствами USB, подключенными к Android]

Когда пользователи подключают устройства USB к Android, то система Android может определить интересно ли подключенное устройство USB для Вашего приложения. Если это так, то Вы можете установить обмен с устройством, если это нужно. Для этого приложение должно выполнить:

1. Определение подключенных устройств USB, используя intent фильтр для оповещения о ситуациях, когда пользователь подключает устройство USB, или путем энумерации устройств USB, которые уже подключены.
2. Запросить у пользователя разрешение на подключение к устройству USB, если оно еще не получено.
3. Далее можно осуществлять взаимодействие с устройством USB путем чтения и записи данных через соответствующие конечные точки интерфейса (interface endpoints).

[Определение наличия подключенного устройства USB]

Ваше приложение может распознать устройства USB либо с помощью использования intent-фильтра, который будет оповещать подключение пользователем устройств, либо путем энумерации устройств USB, которые уже подключены. Использование фильтра intent полезно, если Вы хотите иметь в приложении возможность автоматического детектирования (подключения) нужного устройства. Энумерация подключенных устройств USB полезна, если Вы хотите получить список всех подключенных устройств, или если Ваше приложение не делает фильтр для intent.

Использование intent filter

В следующем примере показано, как декларировать intent filter:

Следующий пример показывает, как декларировать соответствующий файл ресурса, который указывает интересующие Вас устройства USB:

В activity приложения Вы можете получить объект UsbDevice, который представляет подключенное устройство USB из intent примерно так:

Энумерация устройств

Если Ваше приложение нуждается в инспекции всех устройств USB, уже подключенных во время работы приложения, то оно может произвести энумерацию устройств на шине USB. Используйте метод getDeviceList() для получения карты всех устройств USB (hash map), которые сейчас подключены. В списке hash map есть имена устройств USB, которые Вы можете использовать для получения доступа к устройству.

Если необходимо, Вы также можете просто получить итератор из hash map и обработать каждое устройство друг за другом:

[Получение права на взаимодействие с устройством USB]

Перед тем, как начать обмен с устройством USB, Ваше приложение должно запросить на это разрешение от пользователя.

Примечание: если Ваше приложение использует intent filter, чтобы распознать подключенные устройства USB, то оно автоматически принимает разрешение, если пользователь разрешает разрешает Вашему приложению обработать intent. Если нет, то Вы должны в приложении явным образом запросить разрешение перед подключением к устройству.

Явный запрос на разрешение может быть необходим в некоторых ситуациях, таких как если Ваше приложение делает энумерацию уже подключенных устройств USB, и затем хочет обмениваться данными с ними. Вы должны проверить право на доступ к устройству, перед тем как сделать попытку взаимодействовать с ним. Если этого не сделать, то Вы получите runtime error (ошибка во время выполнения), когда пользователь не дал разрешения на доступ к устройству.

Чтобы явно получить разрешение, создайте сначала broadcast receiver (широковещательный приемник). Этот receiver прослушивает intent, которое получает broadcast, когда Вы вызываете requestPermission(). Вызов requestPermission() отображает диалог для пользователя с запросом разрешения на подключение к устройству USB. В следующем примере кода показано, как создать broadcast receiver:

Для того, чтобы зарегистрировать broadcast receiver, добавьте в метод onCreate() Вашей activity следующий код:

Чтобы отобразить диалог, запрашивающий у пользователей разрешение на подключение к устройству, вызовите метод requestPermission():

Когда пользователь ответит на этот диалог, Ваш broadcast receiver получит intent, который содержит расширение EXTRA_PERMISSION_GRANTED, представляющее суть ответа в двоичном виде. Проверьте его на значение true перед тем, как подключиться к устройству.

[Обмен с устройством USB]

Обмен с устройством USB может быть либо синхронным, либо асинхронным. В любом случае Вы должны создать новый поток, который будет обрабатывать все перемещения данных, чтобы не блокировать на ожидании поток интерфейса (UI thread). Чтобы правильно установить обмен с устройством, Вам нужно получить соответствующие объекты UsbInterface и UsbEndpoint устройства, с которым Вы хотите наладить обмен, и отправлять запросы в эти конечные точки с помощью UsbDeviceConnection . В общем случае Ваш код должен делать следующее:

• Нужно проверить атрибуты объекта UsbDevice , такие как product ID (идентификатор продукта, PID), vendor ID (идентификатор производителя, VID), или класс устройства - чтобы определить, хотите ли Вы соединиться именно с этим устройством USB.

• Когда принято положительное решение на обмен с этим устройством USB, найдите подходящий UsbInterface (), который Вы хотите использовать для обмена с подходящей UsbEndpoint интерфейса (конечные точки и их привязка к интерфейсу также задана в дескрипторах USB).

Прим. переводчика: интерфейс - это некая логическая сущность, описывающая метод взаимодействия с устройством USB. И интерфейсу привязаны конечные точки - другая логическая сущность, олицетворяющая какой-то буфер данных в устройстве USB. Наличие конкретного интерфейса (он обычно в устройстве USB один, но интерфейсом может быть и несколько), его тип, привязка к интерфейсу конечных точек, тип конечных точек - все это зависит от дескрипторов устройства USB (подробнее см. [2]). Дескрипторы устройств USB автоматически считываются системой Android при энумерации и подключении устройств USB.

Интерфейсу может принадлежать одна или большее количество конечных точек (endpoint). Обычно для осуществления двунаправленного обмена имеются 2 конечные точки - одна конечная точка работает на ввод от устройства (IN endpoint), а другая на вывод в устройство (OUT endpoint).

• Когда Вы нашли корректную конечную точку, откройте UsbDeviceConnection к этой конечной точке.

• Предоставьте данные, которые Вы хотите передать в конечную точку методами bulkTransfer() или controlTransfer() . Вы должны провести эту операцию передачи данных в другом потоке, чтобы не блокировать главный поток интерфейса пользователя (main UI thread). Для дополнительной информации по использованию потоков в Android см. [3].

Следующий кусок кода показывает тривиальный способ осуществить синхронную передачу данных. Ваш реальный рабочий код должен содержать больше логики, чтобы корректно найти нужный интерфейс и конечные точки для обмена, и также должен передавать данные в отдельном потоке (чтобы не блокировать main UI thread, и чтобы приложение визуально не тормозило [4]):

Для дополнительной информации см. пример AdbTest, который показывает как делать асинхронные bulk передачи, и пример MissleLauncher, который показывает как асинхронно слушать interrupt endpoint.

[Прекращение обмена с устройством USB]

Когда Вы завершили обмен с устройством USB, или устройство USB было отключено, закройте UsbInterface и UsbDeviceConnection вызовом releaseInterface() и close() . Чтобы прослушивать события отключения, создайте broadcast receiver примерно так:

Создание broadcast receiver в приложении, не в манифесте, позволит Вашему приложению во время выполнения обрабатывать только события отключения. С таким методом события отключения будут отправлены только приложению, которое сейчас работает, и не всем приложениям.

USB On The Go(OTG) - обсуждение

Прикрепленное изображение

В наш век, век технологий, любая информация в основном храниться в электронном виде, будь то текстовые файлы, фотографии, музыка, фильмы и.д. Как правило предметом для хранения выступает usb флешка. Но для её использования понадобиться устройство с usb портом, например компьютер, который не всегда бывает под рукой, в отличие от телефона/смартфона/планшета и т.д.. Так как же можно подключить флешку и другие устройства ( мышку, клавиатуру, джойстик, принтер и т.д ) к нашему телефону/смартфону/планшету и т.д. В этом нам поможет otg шнур. Что же такое OTG?
USB OTG ( On-The-Go) — дальнейшее расширение спецификации USB 2.0, предназначенное для лёгкого соединения периферийных USB-устройств друг с другом без необходимости подключения к ПК. Например к моделям смартфонов и телефонов, поддерживающих USB OTG, можно подключать некоторые USB-устройства. Обычно это флэш-накопители, клавиатуры, мыши и другие устройства, не требующие дополнительных драйверов.

Более подробное описание работы технологии привёл пользователь kargal в своём посте.

Прикрепленное изображение


Первый контакт - питание +5 Вольт. В паре с GND, осуществляет питание подключаемого устройства (флешки, карты памяти и пр.)
Второй контакт - Data-.
Третий контакт - Data +.
Четвёртый контакт - контакт OTG. Замыкается с GND для перевода смартфона/(любого поддерживающего OTG устройства с подобной распиновкой) в режим хоста - подачи на разъём напряжения.
Пятый контакт - контакт GND (Ground).
  1. Марка Вашего аппарата (полностью).
  2. OTG работает? ( Да работает, нет не работает). На телефон подаётся дополнительное питание или работает и без дополнительного питания ( т.е. Вы просто подключаете OTG кабель к смартфону, или у Вас Y-кабель, третий конец которого вы подключаете к источнику питания ( порт компьютера, внешний аккумулятор, USB хаб который подключен к источнику питания и т.д.).
  3. Версия андроида с которой у Вас работает OTG, либо наоборот - не работает.
  4. Какая прошивка у Вас стоит на смартфоне заводская(стоковая) или сторонняя(кастомная).
  5. Название и версия ядра с которой работает/не работает OTG. Ядро стоковое или кастомное?

  • Acer:
    Acer E700 Trio // версия андроида 4.4.2 с ядром 3.4.67 //

В недавней статье на Geektimes в комментариях возник вопрос о поддержке в ОС Android периферии, подключенной к шине USB. Действительно, большинство вендорского ПО, к примеру, для работы с принтерами и МФУ, поддерживает только подключение по сети. Однако это не означает, что в самой ОС Android нет такой возможности — это означает лишь то, что большинство устройств не имеют полноценного USB хоста, и далеко не все имеют поддержку OTG. По сети же могут работать абсолютно все без исключения.

Большинство устройств на Android при наличии порта OTG поддерживают на уровне системы (ядра Linux или стандартных компонентов Android) следующие классы устройств:

  • Устройства ввода — клавиатуры, мыши, джойстики (HID)
  • Накопители (Mass Storage)
  • Сотовые модемы
  • Сетевые адаптеры
  • Вебкамеры

Подробнее список устройств, поддерживаемых на уровне ядра Linux, можно получить в sysfs:

$ ls /sys/bus/usb/drivers

Если же модуль в принципе доступен в исходниках ядра Linux, но не включен в Android — не стоит рассчитывать на то, что его получится собрать и расставить на все целевые системы.

Однако, начиная с Android 3.1 (API 12), в системе содержатся средства, достаточные для поддержки на уровне приложения любой USB периферии. Данные средства описаны в разделе USB Host руководства по Android API. Здесь же я хочу привести примеры реальной работы с некоторыми видами устройств.

Права доступа

Как и для прочих действий, Android требует, чтобы приложение получило разрешение на доступ к USB периферии. Существует 2 способа получить такое разрешение:

  • Задекларировать список устройств в AndroidManifest
  • Явно показать пользователю диалог “разрешить”

Итак, нам необходимо добавить в манифест следующее:


А в res/xml/device_filter.xml вписать следующее:


Отмечу, что хотя общепринято указывать VID:PID в 16-ричной системе счисления, здесь они должны быть указаны в десятичной. В документации заявляется, что возможно указание только класса, без VID и PID, но у меня это не стало работать.

Принтеры


Класс предельно простой. В рамках этого класса устройство должно поддерживать:

  • Обязательный bulk out endpoind для отправки данных на принтер
  • Опциональный bulk in endpoind для получения статуса принтера
  • 3 управляющих запроса

Код, приведенный ниже, предоставляет функциональность, аналогичную устройству /dev/usb/lp в Linux. Далее нам нужен фильтр, преобразующий исходный документ в пакет данных, понятный конкретной модели принтера. Но это тема иной статьи. Как один из вариантов — можно собрать ghostscript с помощью NDK.

Для работы с устройством нам в первую очередь нужно:

1. Найти устройство. В примере для простоты я ищу первый попавшийся:


2. Получить endpoint’ы:


3. Непосредсвенно открыть устройство:


4. После этого мы можем читать и писать в устройство:


5. По завершении работы — закрыть устройство:

Преобразователи USB-Serial

1. Найти и открыть устройство:


2. Установить параметры последовательного порта:


3. Читать и писать в порт:


4. По завершении работы — закрыть порт:

Резюме

Надеюсь, что мне удалось показать, что работа с USB периферией достаточно проста и логична. Безусловно, реализация протоколов некоторых конкретных устройств не блещет простотой — но это проявится в любой системе в одинаковой степени.

Все приведенные примеры я взял из реального проекта, лишь исключил очевидные проверки, оставив только ключевые строки.

USB (Universal Serial Bus) – дословно «универсальная последовательная шины». Это последовательный интерфейс для передачи данных, который широко используется в электронике и вычислительной технике, и мобильные устройства на основе операционной системы Android – не исключение.

Однако не всегда всё происходит достаточно гладко, могут возникать те или иные проблемы.


Однако, всё по порядку. Сначала давайте разберемся, какие существуют виды USB-разъемов. Всего их пять:

Слева направо: microUSB, miniUSB, B-type, A-type «мама», A-type «папа».

microUSB – самый небольшой из разъемов, используется в миниатюрных электронных устройствах вроде смартфонов, телефонов, планшетных компьютеров, электронных книг и так далее. В последнее время приобрел наибольшее распространение среди Android-устройств благодаря своей универсальности, практически вытеснив miniUSB.

miniUSB – несколько больше microUSB, но также используется в небольших электронных устройствах. В брендовых планшетах и смартфонах на Android практически не используется на сегодняшний день, хотя ранее был широко распространен. Впрочем, встречается в китайских девайсах, более того, благодаря дешевизне и простоте, некоторые более именитые китайские производители возвращаются к miniUSB, после некоторого периода установки microUSB в свои устройства. Чаще всего встречается в фотоаппаратах, камкордерах и так далее.

B-type – разъем, который чаще всего можно встретить в принтерах, сканерах и другой компьютерной периферии, когда размер особого значения не имеет.

A-type «мама» (приемник) – разъем, который устанавливается на персональных компьютерах и иногда на планшетах, для подключения коннектора A-type. Также этот тип разъема можно увидеть в USB-удлинителях и USB OTG кабелях.

A-type «папа» (коннектор) – для подключения в соответствующий приемник A-type.

Отдельно стоит упомянуть расширение спецификации USB 2.0 – USB OTG (USB On The Go), которое предназначено для лёгкого соединения периферийных устройств USB между собой. Это особенно актуально для планшетных компьютеров, смартфонов, электронных книг и других устройств на основе Android, так как при поддержке данной спецификации и при наличии соответствующего переходника-удлинителя USB OTG к мобильному устройству напрямую можно подключить флэш-накопители, фотоаппараты, внешние USB HDD и так далее.


Существует также некоторое количество проприетарных USB-разъемов, которые создают отдельно взятые компании, но постепенно такая практика уходит в прошлое – рынок в целом склоняется в сторону универсальных разъемов, и это несомненный плюс.

Теперь разберемся, что делать, если при подключении Android-устройства через USB-кабель к компьютеру, мобильный аппарат не определяется, а только заряжается (последнее свидетельствует о работоспособности разъема в целом – питание на него подается).

Если это не помогло, пробуем использовать другой USB-кабель (чудеса китайской индустрии особенно склонны к выходу из строя), подсоединить его к другому USB-порту компьютера (настоятельно рекомендуется использовать порты, которые находятся сзади системного блока, если речь идёт о настольном ПК, так как данные порты непосредственно, без удлинителей, распаяны на материнской плате), в конце концов – попробовать другой компьютер для подключения, если есть такая возможность. Если ничего из вышеперечисленного не помогло, можно попробовать заменить флэш-карту на другую. Также не рекомендуется пользоваться никакими лишними переходниками или удлинителями – очень часто в них кроется причина неполадки.

Если проблемное устройство – мобильный гаджет от Samsung, и компьютер его «не видит» ни через Kies, ни через Odin, то стоит попробовать полностью удалить Kies, все старые драйвера Samsung и Samsung PC Studio, после чего установить Kies заново. То же самое касается и аппаратов HTC с фирменной программой HTC Sync.

Как вариант, можно установить Android USB Driver. Также большинство программ для синхронизации Android-устройства с персональным компьютером, вроде HTC Sync или Samsung Kies, устанавливают свои драйвера. Важно – рекомендуем отключать антивирусные программы на компьютеры во время установки драйверов.

Иногда может помочь сброс к заводским настройкам (так называемый wipe) через настройки мобильного девайса, или же через режим Recovery. Сброс удалит все установленные пользователем приложения и восстановит стандартные заводские настройки.

Драйвера для устройств, перед тем как их переустановить, очень желательно еще и корректно удалить с персонального компьютера. Они зачастую скрываются в «Диспетчере устройств», как только девайс отключается или подает команду на скрытие. Часто «одноименные» драйвера могут конфликтовать из-за несоответствия версий. Что ж, приступим к очистке списка неиспользуемых устройств, что часто может быть причиной «неработоспособности» Android-гаджета при его подключении посредством USB. Во-первых, отключаем все внешние USB-устройства от компьютера. Создаем переменную среду DEVMGR_SHOW_NONPRESENT_DEVICES со значением 1. Чтобы сделать это, кликаем правой кнопкой мышки на «Мой компьютер», выбираем «Свойства», «Дополнительно», нажимаем «Переменные среды». В открывшемся окне вверху нажимаем кнопку «Создать». В поле «Имя переменной» вводим:

В поле «Значение переменной» вводим, соответственно, 1. Нажимаем два раза «Ок», чтобы закрыть меню.

Создав данную переменную, «Диспетчер устройств» будет показывать все установленные в системе драйвера, в том числе скрытые или когда-либо подключавшиеся к персональному компьютеру.

Заходим в «Диспетчер устройств», в пункте меню «Вид» выбираем «Показывать скрытые устройства». Теперь можно приступать к очистке операционной системы от разного «хлама». Для начала открываем раздел «Дисковые устройства». Нюанс в том, что при каждом подключении новой флешки для неё ставится новый драйвер, причем он ставится даже если подключить ту же самую флешку, но в другой USB-порт. Драйвера всех отключенных сменных носителей можно смело удалять, так как при подключении их к компьютеру драйвера для них будут установлены заново. Среди этих драйверов можно обнаружить и драйвер вашего Android-устройства, возможно установленный неправильно, и возможно даже не один. Данные записи также смело можно удалять, так как они могут вызывать неполадки – в любом случае, при переподключении имеющегося Android-девайса драйвер для него будет установлен заново или будет выдан запрос на установку пользователем. В разделе «Скрытые» устройства можно удалять абсолютно все скрытые (серые) устройства, так как это не что иное, как неудачные попытки поставить драйвер для какого-либо девайса, и они точно не нужны в системе. В разделе «Тома запоминающих устройств» также можно удалить все скрытые (серые) записи, так как это «буквы», присвоенные подключаемым ранее флешкам – в любом случае, при новом подключении флеш-накопителя, они будут присвоены заново. В разделе «Контроллеры универсальной последовательной шины USB» можно удалить все скрытые (серые) устройства. После выполнения очистки операционной системы от ненужных драйверов перезагружаем компьютер. После перезагрузки подключаем Android-девайс, он будет обнаружен операционной системой Windows как новое устройство, и для него автоматически будут установлены драйвера, или же вы можете установить нужные драйвера вручную. После еще одной перезагрузки компьютера все проблемы с конфликтными драйверами должны уйти в прошлое.

Читайте также: