Android Tutorial Android Usb Host Tutorial - AdbTest

Status
Not open for further replies.
Android 3.1 and above devices support Usb host mode. With this feature you can connect to regular client usb devices. Some devices are automatically recognized by the OS and are simple to work with, such as: keyboard, mouse or storage devices.

Other devices require the developer to implement the specific protocol. Depending on the device and the documentation available this can be a feasible task.

This example which is based on Google's AdbTest example, connects two Android devices with a Usb cable. The host device reads the client device logs. This is done by implementing one feature of Adb debugging, similar to the Usb debugging driver.

usbhost_3.jpg


The logs of the host device show messages from the client device:

usbhost_1.png


As the Usb host features are only available starting with Android 3.1, you should configure the IDE to use android.jar level 12 or above. It can be downloaded by choosing Tools - Run AVD manager.
You should then configure the IDE paths to point to the correct android.jar:
SS-2011-09-01_18.53.22.png

The following error means that you are using the wrong platform level:
B4X:
package android.hardware.usb does not exist

Now to the code...
The first step is to use UsbManager to find all the connected devices. We are going over all devices, looking for a device with an interface with class = 255 and subclass = 66.
Assuming that such a device is found we are also looking for the in / out endpoints.
The following code iterates over the connected devices (usually there will be one) looking for the requested values:
B4X:
Sub FindAdbDevice As Boolean
   Dim usbdevices() As UsbDevice
   usbdevices = manager.GetDevices
   
   'Iterate over devices and find the correct one
   For i = 0 To usbdevices.Length - 1
      Dim ud As UsbDevice
      ud = usbdevices(i)
      Log(ud)
      'Iterate over interfaces
      For a = 0 To ud.InterfaceCount - 1
         Dim inter As UsbInterface
         inter = ud.GetInterface(a)
         If inter.InterfaceClass = 255 AND inter.InterfaceSubclass = 66 Then
            'found our device and interface
            device = ud
            interface = inter
            'Find correct endpoints
            For b = 0 To interface.EndpointCount - 1
               Dim endpoint As UsbEndpoint
               endpoint = interface.GetEndpoint(b)
               If endpoint.Type = manager.USB_ENDPOINT_XFER_BULK Then
                  If endpoint.Direction = manager.USB_DIR_IN Then 
                     inEndpoint = endpoint
                  Else If endpoint.Direction = manager.USB_DIR_OUT Then
                     outEndpoint = endpoint
                  End If
               End If
            Next
         End If
      Next
   Next
   If device.IsInitialized = False Then Log("ADB device not found.")
End Sub

The next step is to check if we have permission to access this device and request such a permission if we don't have. The permission will only be required on the first time our application runs.
B4X:
If manager.HasPermission(device) = False Then 
         manager.RequestPermission(device)
...
RequestPermission will show a dialog asking the user to approve the request.

If we do have permission we connect to the device:
B4X:
   connection = manager.OpenDevice(device, interface, True)
   Log("Starting connection")
   Dim data(), msg() As Byte
   data = ConvertStringToBytesWith0("host::" & Chr(0))
   msg = CreateMessage(A_CNXN, 0x01000000, 4096, data)
   SendOutRequest("Msg", msg, 24)
   SendOutRequest("Data", data, Data.Length)
   SendInRequest(MSG_READ, 24)
   connection.StartListening("connection")
First we connect to the device and send to OUT requests according to the ADB protocol and one IN request that will return with the result from the device.
We then call connection.StartListening to notify the listener to listen for completed requests.

Adb protocol
In order to start a connection we need to send a pair of requests. One is the "message" and the other is the "data".
These requests are sent to the OUT endpoint as we are sending data from the host to the device.
In order to get the device response we are sending another request to the IN endpoint.
Our code will continue in Sub NewData when the IN request completes.

Note that each request can be assigned a name. This is an arbitrary string that helps us identify the requests that return in NewData event. For 'out' requests the name is not really important.

Now for the NewData event handling which is a bit more complicated:
B4X:
Sub Connection_NewData (Request As UsbRequest, InDirection As Boolean)
   If Connection.IsInitialized = False Then Return 'Might happen after we close the connection
   If InDirection = False Then 
      ReleaseRequest(Request, OutRequests)
      connection.ContinueListening
      Return 'don't handle OUT requests
   End If
   Dim sendData As Boolean
   If Request.Name = MSG_READ Then
      Dim raf As RandomAccessFile
      raf.Initialize3(Request.Buffer, True)
      Dim command As Int
      command = raf.ReadInt(0)
      If command = A_CNXN OR command = A_WRTE Then
         lastCommand = command
         SendInRequest(DATA_READ, raf.ReadInt(12)) 'read the data request
         sendData = True
      Else
         DispatchMessage(command, raf.ReadInt(4), "")
      End If
   Else If Request.Name = DATA_READ Then
      Dim s As String
      s = BytesToString(Request.Buffer, 0, Request.Buffer.Length, "UTF8")
      DispatchMessage(lastCommand,0, s)
   End If
   If sendData = False AND connection.IsInitialized Then
      SendInRequest(MSG_READ, 24)
   End If
   ReleaseRequest(Request, InRequests)
   connection.ContinueListening
End Sub
We are only interested in IN requests. The InDirection boolean parameter is useful distinguish between the requests:
B4X:
   If InDirection = False Then 
      ReleaseRequest(Request, OutRequests)
      connection.ContinueListening
      Return 'don't handle OUT requests
   End If
UsbRequest object are "heavy" objects. We are using a simple pool of objects to avoid creating new requests every time.
So the above code returns the request to the pool and then call connection.ContinueListening. This tells the listener to continue listening for requests. Without calling it we will not get the event for the IN request that we are waiting for.

If the request is an IN request things are more interesting. We check the name of the request to know if it is a "message" request or a "data" request.
We then call DispatchMessage. This sub handles the message based on the message command.

After getting an IN request there are two possible cases. The first is that we got a message request and we need to also receive the data message. The length of the data message is retrieved from the content of the message request.
In the other case we send another IN message request waiting for the next update from the device.
Eventually we release the request and call connection.ContinueListening.

RandomAccessFile object is used in several occasions to prepare the buffers according to the protocol.

B4A-Bridge
It is not possible to cannot connect the IDE to the Usb port of the host device as it is taken by the client. B4A-Bridge should be used instead: B4A-Bridge a new way to connect to your device

The project is attached.
The library is available here: http://www.b4x.com/forum/additional-libraries-official-updates/11290-usb-host-library.html#post63118
 

Attachments

  • USBExample.zip
    7.2 KB · Views: 4,039

axelbarry

New Member
Good afternoon Erel, first of all, many compliments for the forum, it's full of useful information and tips...it's great!

Referring to your statement:


Only Android 3.1 and above support USB host mode: USB Host | Android Developers

There is a back port for the accessory mode for Android 2.3.4.


I have seen a couple of devices, based on 2.3.5, that have the OTG interface (can support both Host and Peripherals mode).

In this case, do you think that the interface is just not called in the proper way or there is something that allows host mode also in this version?
 

agraham

Expert
Licensed User
Longtime User
I don't think that OTG support is equivalent to host mode.
Actually I think that it is. However the backport mentioned above is for Accessory mode in which the device acts as a USB slave. However USB Accessory | Android Developers states
This add-on library is a thin wrapper around the android.hardware.usb accessory APIs and does not support USB host mode
USB host mode is only officially supported in Android 3.1 and higher. If a device running Android below version 3.1 supports host mode then it will have been added by the device OEM and as Erel states will probably only support OS recognised things like mice, keyboards and mass storage.
 

axelbarry

New Member
Thank you very much guys.

Your statements are very clear.

Just to summarize: in case the host mode is supported by a pre 3.1 device (to read mass storage or any common HID), this doesn't mean that it supports all the methods of USB Host APIs...right?

...it is not always enough to have the device able to read mass storage or support OTG mode...

Have a nice week end guys...and thank you again!
 

krzyszp

Member
Licensed User
Longtime User
As I mention before, I tried to get data from Radioactivity detector (USB HID device). Another application recognise it as:
05df:16c0
obdev.at radioactiveathome.org GRS
But your example application doesn't recognise it at all. This happened because my device are HID device?
Can you help me, how to send requests and get answers from it, please?
 

pleth

New Member
Hi

I have a project, I would like to read and write on an USB key connected with a OTG cable on an Android device. Is it possible and easy using Basic4Android ?

Thanks. :sign0104:
 
Last edited:

tonga

Member
Licensed User
Longtime User
Hi Erel,
I'm using well this example to send a string from tablet to a microcontroller, but I'm not able to read the string that the microcontroller send to tablet. Using the debug breakpoint I see that something arrives to tablet... Can you help me?
Thanks!
 

MotoMusher

Active Member
Licensed User
Longtime User
Are there any settings I need to change on my phone for this? I am trying to access a gps, and not getting any responses from either:

B4X:
    Dim usbaccessories() As UsbAccessory
    usbaccessories = manager.GetAccessories
    For i = 0 To usbaccessories.Length - 1
        Log("zzzz")
    Next
  
    Dim usbdevices() As UsbDevice
    usbdevices = manager.GetDevices
  
    'Iterate over devices and find the correct one
    For i = 0 To usbdevices.Length - 1
        Log("aaa")
    Next

I have tried the GPS in both standard and mass storage mode

I also tried connecting to another android phone and same deal. USB hub is plugged into a computer, and the computer can see all 3 devices connected to hub
 
Last edited:

kiki78

Active Member
Licensed User
Longtime User
First, thank you Erel for this library.

I develop custom USB device and it work's generally fine.
My problem is when I'm connected to my device and disconnect USB cable. Some time I can't reconnect correctly.
The problem is enumeration seem's doesn't work.
I need to reboot tablet to retrieve connection.

I read http://developer.android.com/guide/topics/connectivity/usb/host.html and it is recommended to call releaseInterface() and close() but I never found it in library. May you add it in future release ?

I try BroadcastReceiver library from Xverhelst, with "android.hardware.usb.action.USB_DEVICE_DETACHED" action, and this work fine to detect disconnection of my device. So I expect that correct software disconnection solve my problem.

Regards
 

kiki78

Active Member
Licensed User
Longtime User
Sorry I miss this since I use synchronous communication !
Instead of UsbDevice.StopListening, I use UsbDevice.CloseSynchronous and this seems to work.
When I disconnect OTG cable on tablet side all work fine.
If I disconnect on device side and reconnect I obtain "USB High power connected" message, but this is solve if I disconnect on tablet size.
I expect this help.

Regards
 

3394509365

Active Member
Licensed User
Longtime User
hello, I can not find the device. Having said that I place the log sdk 19 and Basic4 v 3.2 with windows 7
 

3394509365

Active Member
Licensed User
Longtime User
hello, I can not find the device. Having said that I place the log sdk 19 and Basic4 v 3.2 with windows 7
 
Status
Not open for further replies.
Top