According to the USB (Universal Serial Bus) standard a device is classified as either a host or a peripheral device. In the most common scenarios the host, such as your PC, acts as a controller and the peripheral, such as a USB drive, responds to its commands. On-the-Go (OTG) is an extension to USB standard and is often referred to as USB OTG. The original host/peripheral model is maintained — however, what is new is the addition of a new class of devices that can function as either a host or peripheral and which are referred to as dual-role devices.

To enable an OTG connection an OTG cable is connected between two devices. An OTG cable typically has an OTG micro A-Type connector on one end, which connects to the host (e.g. Android device), and a standard USB connector on the other, which connects to the peripheral (e.g. RF Explorer device). When connected with an OTG cable, the initial host device is designated the A-Device (i.e. the Android device), with the initial peripheral designated the B-Device (i.e. the RF Explorer device).

To avoid potential conflicts regarding which device is host and which is peripheral, the assignment of which device is A or B is determined by the orientation of the OTG cable. This cable determines whether the signaling pin of the port it is plugged into is left floating or is pulled to ground. The device with the signaling pin pulled to ground is designated the A-Device, or default host, and the device with the floating signaling pin is designated the B-Device, or default peripheral.

USB ports on most Android smart phones and tablets sold today support OTG. What this means is that instead of your PC being the host and your phone being the peripheral, you can make your phone the host and connect other USB peripherals to it — e.g. RF Explorer. However, even though the Android OS and a particular device is capable of supporting USB Host Mode, some manufacturers and service providers have not enabled that feature by default. When that is the case the solution is fairly simple — to add a configuration file to the Android system files to enable USB Host Mode.

We have identified 3 requirements for an Android device to support USB Host Mode and be able to communicate with an RF Explorer handheld spectrum analyzer: [1] The Android device must be running version 4.1 (Jelly Bean) of the OS, or higher. [2] The output power on the Android device’s USB port should be 5V. [3] The configuration file android.hardware.usb.host.xml must exist on the Android device in the folder /system/etc/permissions. The presence of this configuration file is what enables USB Host Mode on your Android device.

The output power requirement of 5V is rarely an issue except for certain very inexpensive Android devices. If USB Host Mode is not currently supported on your Android device it most likely is due to a missing android.hardware.usb.host.xml configuration file. We have developed a simple tool to help determine whether your Android device meets these requirements. The tool is free and is available from the Google Play Store: OTG Test For RF Explorer.

The Android OS is a customized flavor of linux that Google has modified to run as an embedded OS on phone and tablet hardware. Linux is a mature and secure operating system that requires certain permissions to make changes to system folders and files. There are two methods for adding a missing system file — (1) unlock the Android operating system — referred to as «rooting», or (2) run Google’s adb.exe (Android Debug Bridge) tool on your Windows PC and copy the android.hardware.usb.host.xml configuration file to the /system/etc/permissions folder on the Android device. We prefer the latter method and provide instructions below for using adb.exe.

[3] Download the file install-adb.zip from our web site to your Windows PC, and unzip it into a new folder — e.g. C:adb. [4] From the command prompt, run the following adb commands:

  • adb kill-server
  • adb start-server
  • adb usb
  • adb devices
  • adb remount
  • adb push android.hardware.usb.host.xml /system/etc/permissions
  • adb reboot

When you subsequently run an app like OTG Test For RF Explorer and attach an RF Explorer device via USB OTG cable then a permission request pops-up. You should press the ‘OK’ button. This request indicates the RF Explorer device was detected and USB Host Mode is working.

OTG Test For RF Explorer

Though a majority of the latest Android devices are distributed with USB Host Mode enabled by default — there are still many that are not. As long as your device is running version 4.1 (Jelly Bean) or later of the Android operating system, then USB Host Mode can be enabled by copying a configuration file to a system folder. If USB Host Mode is not currently enabled on your Android device, then please follow these instructions: Instructions to enable USB Host Mode We have developed a simple tool to aid in determining whether a particular Android device is suitable for use with RF Explorer. The app is free and available from the Google Play Store.

We strongly encourage all customers to check-out this tool before purchasing the Touchstone Mobile software.

OTG Test For RF Explorer

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

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

Несколько реже:

  • Сотовые модемы
  • Сетевые адаптеры
  • Вебкамеры

Хабы поддерживаются при наличии полноценных хост-портов, но не поддерживаются на портах OTG. Подробнее список устройств, поддерживаемых на уровне ядра 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 вписать следующее:

<?xml version="1.0" encoding="utf-8"                       

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

Принтеры

На примере принтера я покажу, как непосредственно использовать API android.hardware.usb. На уровне передачи данных все принтеры поддерживают стандартый класс USB устройств:

int UsbConstants.USB_CLASS_PRINTER = 7; 

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

  • Обязательный bulk out endpoind для отправки данных на принтер
  • Опциональный bulk in endpoind для получения статуса принтера
  • 3 управляющих запроса
int GET_DEVICE_ID = 0; int GET_PORT_STATUS = 1; int SOFT_RESET = 2; 

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

UsbDevice findDevice() {     for (UsbDevice usbDevice: mUsbManager.getDeviceList().values()) {         if (usbDevice.getDeviceClass() == UsbConstants.USB_CLASS_PRINTER) {             return usbDevice;         } else {             UsbInterface usbInterface = findInterface(usbDevice);             if (usbInterface != null) return usbDevice;         }     }     return null; }  UsbInterface findInterface(UsbDevice usbDevice) {     for (int nIf = 0; nIf < usbDevice.getInterfaceCount(); nIf++) {         UsbInterface usbInterface = usbDevice.getInterface(nIf);         if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_PRINTER) {             return usbInterface;         }     }     return null; } UsbDevice mUsbDevice = findDevice(); UsbInterface mUsbInterface = findInterface(mUsbDevice); 

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

for (int nEp = 0; nEp < mUsbInterface.getEndpointCount(); nEp++) {     UsbEndpoint tmpEndpoint = mUsbInterface.getEndpoint(nEp);     if (tmpEndpoint.getType() != UsbConstants.USB_ENDPOINT_XFER_BULK) continue;      if ((mOutEndpoint == null)             && (tmpEndpoint.getDirection() == UsbConstants.USB_DIR_OUT)) {         mOutEndpoint = tmpEndpoint;     } else if ((mInEndpoint == null)             && (tmpEndpoint.getDirection() == UsbConstants.USB_DIR_IN)) {         mInEndpoint = tmpEndpoint;     } } if (mOutEndpoint == null) throw new IOException("No write endpoint: " + deviceName); 

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

mConnection = mUsbManager.openDevice(mUsbDevice); if (mConnection == null) throw new IOException("Can't open USB connection:" + deviceName); mConnection.claimInterface (mUsbInterface, true); 

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

public int read(final byte[] data) throws IOException {     int size = Math.min(data.length, mInEndpoint.getMaxPacketSize());     return mConnection.bulkTransfer(mInEndpoint, data, size, getReadTimeout()); }  public int write(final byte[] data, final int length) throws IOException {     int offset = 0;      while (offset < length) {         int size = Math.min(length - offset, mInEndpoint.getMaxPacketSize());         int bytesWritten = mConnection.bulkTransfer(mOutEndpoint,             Arrays.copyOfRange(data, offset, offset + size), size, getWriteTimeout());          if (bytesWritten <= 0) throw new IOException("None written");         offset += bytesWritten;     }     return offset; } 

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

mConnection.close(); 

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

В отличие от притеров, преобразователи USB-Serial гораздо менее стандартизированы. Существует несколько распространенных чипов, для которых существенно отличается установка параметров последовательного порта — битрейта, чётности и проч. К счастью, есть библиотека github.com/mik3y/usb-serial-for-android, поддерживающая практически все существующие чипы. Библиотека полностью скрывает USB API, сводя все необходимые действия к минимуму вызовов с минимумом параметров. 1. Найти и открыть устройство:

UsbSerialPort mUsbSerialPort; UsbManager mUsbManager = (UsbManager) DEVICE.getSystemService(Context.USB_SERVICE); String type = “FTDI”;  for (UsbDevice usbDevice: mUsbManager.getDeviceList().values()) {     UsbSerialDriver usbSerialDriver = UsbSerialProber.probeSingleDevice(usbDevice);     if (usbSerialDriver == null) continue;     if (!type.equals(usbSerialDriver.getShortDeviceName())) continue;     mUsbSerialPort = usbSerialDriver.getPort(0);     mUsbSerialPort.open(mUsbManager);     break; } 

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

mUsbSerialPort.setParameters(baudRate, dataBits, stopBits, parity); 

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

public int read(final byte[] data) throws IOException {     return mUsbSerialPort.read(data, getReadTimeout()); }  public int write(final byte[] data, final int length) throws IOException {     return mUsbSerialPort.write(data, length, getWriteTimeout()); } 

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

mUsbSerialPort.close(); 

Резюме

Надеюсь, что мне удалось показать, что работа с USB периферией достаточно проста и логична. Безусловно, реализация протоколов некоторых конкретных устройств не блещет простотой — но это проявится в любой системе в одинаковой степени. Все приведенные примеры я взял из реального проекта, лишь исключил очевидные проверки, оставив только ключевые строки. 218 48.7k 218 Shows enumerated usb devices, and allows you to mount external mass storage devices to the filesystem. Supports advanced features like the ability to reload partition tables and reseting USB devices. It can also control the USB Host functionality of S5PC210 devices (Galaxy S, Nexus S, and Samsung Captivate) if they have been updated with the appropriate kernel patch. The application does not use the USB Host API, so it can also run on older, 2.3 devices. Because of that however almost all functionality (except for the listing of USB devices) requires root (superuser) access, and a recent version of busybox installed! Also note that on newer Android versions, some security enhancements may also hinder this application to run properly.The application needs a device that has USB Host (or USB OTG) functionality. Most modern high-end devices have this ability. Check the documentation and specification of your device (this functionality is usually called USB OTG or USB Host)If your device doesn't have native USB OTG functionality, there are kernel patches for some older devices to enable the functionality, most notably for:- S5PC210 (Hummingbird) based Samsung phones (Galaxy S, Captivate, Nexus S)- QSD8250 (Snapdragon) based HTC phones (G1, Nexus One, Desire, Incredible)You can find appropriate kernel drivers for these phones here:- Hummingbird / Samsung phones: http://forum.xda-developers.com/showthread.php?t=1450298- Snapdragon / HTC phones: http://sven.killig.de/android/N1/2.2/usb_host/Note that these drivers might require skills to install, and may damage your phone and void your warranty!More info about this application at: http://forum.xda-developers.com/showthread.php?t=1468531

ОСТАВЬТЕ ОТВЕТ

Please enter your name here
Please enter your comment!