Android Tutorial Android Usb Host Tutorial - AdbTest

Erel

Administrator
Staff member
Licensed User
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.



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



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:

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.basic4ppc.com/forum/addi...updates/11290-usb-host-library.html#post63118
 

Attachments

Nizze

Active Member
Licensed User
Hi .

I installed 3.1 and made the changes
But
i get this

Compiling code. Error
Error parsing program.
Error description: Unknown type: usbmanager
Are you missing a library reference?
Occurred on line: 2
Dim manager As UsbManager

Any ??
 

keithwb

New Member
hi,

i am very new to android programming. is this a library that you make yourself using the usb api from android?

so meaning this library is supposed to be more easy to use?
 

fpdianzen

Member
Licensed User
hi, i see in the developer.android.com website that USB has a support with 2.3.4, when i tried this library in api-10, it doesnt work :((
 

fpdianzen

Member
Licensed User
hi erel, i just want to ask if it is possible to cancel or block any connection to a pc. in 2.3.4? sorry if im using this thread. i can't really understand how will this work.
 

albex

New Member
Licensed User
Hi all,
I'm trying to run the USB example. Even connecting supported devices (keyboard, mouse, etc) this does not detect any USB device in the code.

usbdevices = manager.GetDevices 'It not detect any devices

What I do wrong?

Regards
Albex123
 
Top