Using usb devices with android

Подключаем USB-устройства

5-й курс/Закрытая зона

Метки: UsbAccessory , UsbDevice , UsbManager , UsbDeviceConnection , UsbInterface , UsbEndpoint , UsbRequest

Android (API 12) поддерживает подключение к планшетам и смартфонам периферийных устройств через USB, например, мышки или флешки. Учтите, что не все модели могут поддерживать поддерживать подобную функциональность. Как правило, у планшетов это больше распространено. Я подключал мышку к своему Nexus 7 и в этом случае на экране появляется курсор. Кабель для подключения мышки (или других устройств) к планшету называют OTG.

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

Я расскажу только необходимый минимум, который нам понадобится.

Android-устройство может иметь два режима: USB device mode или USB host mode.

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

Если мы подключаем какое-нибудь устройство к телефону или планшету через USB-порт, то в этом случае используется режим USB host mode. В этом режиме уже телефон обеспечивает питание для подключаемого гаджета, типа флешки, мышки и каких-то приборов и игрушек. Такой режим ещё называют OTG, возможно вы видели в продаже такие OTG-кабели. Они и позволяют подключить мышку к планшету.

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

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

Устройства типа модемов, сетевых адаптеров и вебкамер имеют ограниченную поддержку и зависят от модели вашего устройства.

Можно также упомянуть USB accessory mode, который появился с версии Android 3.0. Этот режим, например, используется при соединении телефона и фотокамеры.

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

Основным пакетом для работы с протоколом USB является android.hardware.usb, который появился в Android 3.1 (API 12).

UsbAccessory

Класс UsbAccessory необходим при режиме USB accessory mode и позволяет узнать различную информацию о подключённом устройстве: название производителя, модель, версия и т.д.

UsbDevice

Класс UsbDevice отвечает за устройства, подключённые в режиме USB host mode и содержит информацию о возможностях, протоколе, классе и идентификаторе и т.д. При работе используется сервис UsbService, доступный через UsbHostManager

UsbManager

UsbManager — один из основных классов для работы с USB. Позволяет обмениваться информацией между устройствами, например, получить список присоединённых устройств.

UsbDeviceConnection

Класс UsbDeviceConnection содержит методы для отправки и получения данных.

UsbInterface

Класс UsbInterface отвечает за интерфейсы подключенных устройств.

UsbEndpoint

Класс UsbEndpoint отвечает за endpoint.

UsbRequest

Класс UsbRequest нужен для чтения и записи данных от устройств в асинхронном режиме.

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

Источник

Android Things — USB communications

Android Things now supports USB Host (since DP3), which allows a user space Android application to talk to a custom USB device.

To discover this feature, we will create a custom USB sensor, and forward all events to the Android Things board over USB.

You can see below a video of what we will achieve: the USB device will be an Arduino NFC reader. When scanning a tag (or an amiibo), the Arduino will forward NFC data to the Android Things board over USB.

Attention, please

There are two different ways to communicate with a USB device via Android Things.

If the device is a USB-Serial and if it reports a /dev/tty* device handle through the kernel, then you won’t need to use any USB Host API. Instead, try to call PeripheralManager.getUartDeviceList() . If you can see a new UART endpoint, this means that you can directly use the UART API to communicate with the USB device. No need to use USB APIs at all (if you don’t need those).

If the device does not report a new /dev/tty* after being plugged in (e.g. the kernel doesn’t have the driver built-in), you are forced to use the USB layer. You will need to manipulate the USB Host API, which allows a regular user space application to communicate with USB devices without root privileges or support needed from the Linux kernel.

In a previous post, we already saw how to communicate with a serial device over UART.
This time, we will use the USB Host API, and the serial communication will be performed using a third party library. That way, the code we will write here will not be specific to Android Things, but will also work on any Android (3.1 and above) smartphone.

Flashing the Arduino

We will start with something simple: we first want the Arduino to continuously send the «Hello!» value to the serial port every second, at a 115 200 baud rate.

When we connect the Arduino to the Android Things board, we expect our app to receive the «Hello!» text every second. And for that, we’ll first have to edit the AndroidManifest.xml .

Читайте также:  Андроид планшет как удалить все

AndroidManifest.xml

We want to be notified when an external USB device is attached to the Android device.
This can be done adding a new intent-filter entry to the Activity that should be started by the system when a USB device is plugged in.
Also, we will add a meta-data element pointing to an external XML resource file (here in res/xml/device_filter.xml ) that declares identifying information about the device that we want to detect.

If the device_filter.xml file has the following content, we will be notified each time any USB device is plugged in:

This is not exactly what we want. We only want to be notified when the Arduino is plugged in, and ignore all other USB devices, so we will add a specific rule.

After connecting the Arduino to the Android Things board, we can consult the kernel logs using dmesg to get some device information:

We only want to be notified when the Arduino (idVendor=0x2341) is connected, so we will specify this vendor id into the usb-device tag:

Note here that the vendor-id expects a decimal value, not a hexadecimal one.

This filter will be enough for us. For a complete list of what we can do, please refer to the USB Host documentation

Starting a USB connection

Our Activity now receives an intent each time the Arduino is plugged in.

We will first list all the connected USB devices, and open a USB connection if the Arduino was found:

The startSerialConnection method will use felHR85’s USBSerial library to open a serial connection between the Arduino and the Android device:

The UsbSerialDevice.read() method takes an UsbReadCallback reference which will be called each time data is received. Here is a simple implementation:

We convert the byte[] data to a UTF-8 String, and log this data.

Now, each time data is sent from the Arduino over USB, the callback is triggered and data is logged. We can run adb logcat to confirm that we receive the “Hello!” message from the Arduino every second:

For a complete and optimized source code, take a look at github.com/Nilhcem/usbfun-androidthings.

Adding some more fun

Printing «Hello!» to the logs every second is quite boring.
A fast way to add some fun to this project is to connect an NFC module to the Arduino and send NFC tag data from this module to the Android Things board over USB.

I used Elechouse’s PN532 Module over SPI, using this sketch.

To simplify, I am only forwarding the tag ID to the Android Things board. And the Android app displays an appropriate image depending on the received ID.

Porting this project to an Android smartphone

As explained in the introduction, the project uses the USB Host API from the Android SDK, and is therefore fully compatible with any Android smartphones or tablets (minSdk=12). If you own a USB-OTG cable, you can plug an Arduino directly to your phone.

Below, a demonstration (with sound) of an Android phone, sending data to an Arduino over USB to play music on a piezo buzzer. (source code is available here)

There’s still one difference however: when a USB device is connected, a UI dialog is shown and the user needs to grant the USB permission to access the device. Checking whether the permission is granted was skipped on the Android Things source code project we wrote, as, similar to runtime permissions, you don’t have to check/request USB permission on Android Things since there may be no display attached, and therefore, no ways for users to grant those permissions. They are allowed by default.

Going further

A better example of what you can do with the USB Host API is the official USB enum sample.
This project iterates over all the USB devices discovered by the host and prints their interfaces and endpoints.

Reading the source code is interesting here as we can learn about USB descriptors.

For example, after a USB device has been detected, it is opened using the same API we used in this article (via UsbManager.openDevice() ), then, instead of opening a serial connection, the code immediately queries the USB device and configuration(s) descriptors:

When reading the USB specs, it is specified that all USB devices must support at least a default endpoint. Any transfer that targets this endpoint is called a control transfer, and is a way for the host to obtain device information.

  • 0x80 is the data direction. Here, it means “IN” (from the USB device to the host)
  • 0x06 is the request type to get a descriptor
  • 0x100 is for a device descriptor ( 0x200 for a configuration descriptor)
  • 0x00 is the descriptor index (default descriptor)

Then, the code receives data from the buffer, as specified in the documentation.

And so on. Once we understand that, the sample code is much easier to read.

Conclusion

This post introduced an example of how to use the USB Host API with Android Things.
In a real-life scenario, you won’t need to use an Arduino to bring NFC support to Android Things, as you can develop the NFC driver directly, and even if you need to, you may be able to communicate with the Arduino using the UART API directly. You may not need to use the USB Host API + a third party dependency.

If you own a USB-Serial device and if this latter is recognized by the kernel, then using the UART API is the easiest and recommended way to communicate between both devices. But if you need to access any kind of USB device from an app, then you’ll be happy to have a user-space USB support on Android Things.

Читайте также:  Просмотр сетевых подключений андроид

As Marcos Placona explained in a blog post, some components need super-fast drivers (sending signals that alternate from vcc to ground in a few microseconds). While this is not possible yet with Android Things, you could use a microcontroller that acts as a proxy and directs data to the Android Things board over USB, to use those components in your Android Things projects.

Источник

USB Host

In this document

When your Android-powered device is in USB host mode, it acts as the USB host, powers the bus, and enumerates connected USB devices. USB host mode is supported in Android 3.1 and higher.

API Overview

Before you begin, it is important to understand the classes that you need to work with. The following table describes the USB host APIs in the android.hardware.usb package.

Table 1. USB Host APIs

Class Description
UsbManager Allows you to enumerate and communicate with connected USB devices.
UsbDevice Represents a connected USB device and contains methods to access its identifying information, interfaces, and endpoints.
UsbInterface Represents an interface of a USB device, which defines a set of functionality for the device. A device can have one or more interfaces on which to communicate on.
UsbEndpoint Represents an interface endpoint, which is a communication channel for this interface. An interface can have one or more endpoints, and usually has input and output endpoints for two-way communication with the device.
UsbDeviceConnection Represents a connection to the device, which transfers data on endpoints. This class allows you to send data back and forth sychronously or asynchronously.
UsbRequest Represents an asynchronous request to communicate with a device through a UsbDeviceConnection .
UsbConstants Defines USB constants that correspond to definitions in linux/usb/ch9.h of the Linux kernel.

In most situations, you need to use all of these classes ( UsbRequest is only required if you are doing asynchronous communication) when communicating with a USB device. In general, you obtain a UsbManager to retrieve the desired UsbDevice . When you have the device, you need to find the appropriate UsbInterface and the UsbEndpoint of that interface to communicate on. Once you obtain the correct endpoint, open a UsbDeviceConnection to communicate with the USB device.

Android Manifest Requirements

The following list describes what you need to add to your application’s manifest file before working with the USB host APIs:

  • Because not all Android-powered devices are guaranteed to support the USB host APIs, include a element that declares that your application uses the android.hardware.usb.host feature.
  • Set the minimum SDK of the application to API Level 12 or higher. The USB host APIs are not present on earlier API levels.
  • If you want your application to be notified of an attached USB device, specify an and element pair for the android.hardware.usb.action.USB_DEVICE_ATTACHED intent in your main activity. The element points to an external XML resource file that declares identifying information about the device that you want to detect.

In the XML resource file, declare elements for the USB devices that you want to filter. The following list describes the attributes of . In general, use vendor and product ID if you want to filter for a specific device and use class, subclass, and protocol if you want to filter for a group of USB devices, such as mass storage devices or digital cameras. You can specify none or all of these attributes. Specifying no attributes matches every USB device, so only do this if your application requires it:

  • vendor-id
  • product-id
  • class
  • subclass
  • protocol (device or interface)

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 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/device_filter.xml and specifies that any USB device with the specified attributes should be filtered:

Working with Devices

When users connect USB devices to an Android-powered device, the Android system can determine whether your application is interested in the connected device. If so, you can set up communication with the device if desired. To do this, your application has to:

  1. Discover connected USB devices by using an intent filter to be notified when the user connects a USB device or by enumerating USB devices that are already connected.
  2. Ask the user for permission to connect to the USB device, if not already obtained.
  3. Communicate with the USB device by reading and writing data on the appropriate interface endpoints.

Discovering a device

Your application can discover USB devices by either using an intent filter to be notified when the user connects a device or by enumerating USB devices that are already connected. Using an intent filter is useful if you want to be able to have your application automatically detect a desired device. Enumerating connected USB devices is useful if you want to get a list of all connected devices or if your application did not filter for an intent.

Using an intent filter

To have your application discover a particular USB device, you can specify an intent filter to filter for the android.hardware.usb.action.USB_DEVICE_ATTACHED intent. Along with this intent filter, you need to specify a resource file that specifies properties of the USB device, such as product and vendor ID. When users connect a device that matches your device filter, the system presents them with a dialog that asks if they want to start your application. If users accept, your application automatically has permission to access the device until the device is disconnected.

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 devices that you’re interested in:

In your activity, you can obtain the UsbDevice that represents the attached device from the intent like this:

Enumerating devices

If your application is interested in inspecting all of the USB devices currently connected while your application is running, it can enumerate devices on the bus. Use the getDeviceList() method to get a hash map of all the USB devices that are connected. The hash map is keyed by the USB device’s name if you want to obtain a device from the map.

If desired, you can also just obtain an iterator from the hash map and process each device one by one:

Obtaining permission to communicate with a device

Before communicating with the USB device, your application must have permission from your users.

Note: If your application uses an intent filter to discover USB devices 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 device.

Explicitly asking for permission might be neccessary in some situations such as when your application enumerates USB devices that are already connected and then wants to communicate with one. You must check for permission to access a device before trying to communicate with it. If not, you will receive a runtime error if the user denied permission to access the device.

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 device. The following sample code shows how to create the broadcast receiver:

To register the broadcast receiver, add this in your onCreate() method in your activity:

To display the dialog that asks users for permission to connect to the device, 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 device.

Communicating with a device

Communication with a USB device can be either synchronous or asynchronous. In either case, you should create a new thread on which to carry out all data transmissions, so you don’t block the UI thread. To properly set up communication with a device, you need to obtain the appropriate UsbInterface and UsbEndpoint of the device that you want to communicate on and send requests on this endpoint with a UsbDeviceConnection . In general, your code should:

  • Check a UsbDevice object’s attributes, such as product ID, vendor ID, or device class to figure out whether or not you want to communicate with the device.
  • When you are certain that you want to communicate with the device, find the appropriate UsbInterface that you want to use to communicate along with the appropriate UsbEndpoint of that interface. Interfaces can have one or more endpoints, and commonly will have an input and output endpoint for two-way communication.
  • When you find the correct endpoint, open a UsbDeviceConnection on that endpoint.
  • Supply the data that you want to transmit on the endpoint with the bulkTransfer() or controlTransfer() method. You should carry out this step in another thread to prevent blocking the main UI thread. For more information about using threads in Android, see Processes and Threads.

The following code snippet is a trivial way to do a synchronous data transfer. Your code should have more logic to correctly find the correct interface and endpoints to communicate on and also should do any transferring of data in a different thread than the main UI thread:

To send data asynchronously, use the UsbRequest class to initialize and queue an asynchronous request, then wait for the result with requestWait() .

For more information, see the AdbTest sample, which shows how to do asynchronous bulk transfers, and the MissileLauncher sample, which shows how to listen on an interrupt endpoint asynchronously.

Terminating communication with a device

When you are done communicating with a device or if the device was detached, close the UsbInterface and UsbDeviceConnection by calling releaseInterface() and 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.

Источник

Читайте также:  Хил климб рейсинг без андроида
Оцените статью