1. Download the free trial version

Tutorial Android Usb Host Tutorial - AdbTest

Discussion in 'Tutorials & Examples' started by Erel, Sep 4, 2011.

Similar threads

Library Usb Host library
Question Usb
Question USB connection fails
Question USB and isochronous endpoint
Tutorial Arduino ADK Coda
  1. Erel

    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.

    [​IMG]

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

    [​IMG]

    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:
    [​IMG]
    The following error means that you are using the wrong platform level:
    Code:
    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:
    Code:
    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.
    Code:
    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:
    Code:
    connection = manager.OpenDevice(device, interface, True)
       
    Log("Starting connection")
       
    Dim data(), msg() As Byte
       data = ConvertStringToBytesWith0(
    "host::" & Chr(0))
       msg = CreateMessage(A_CNXN, 
    0x010000004096, 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:
    Code:
    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:
    Code:
    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

    Attached Files:

  2. Nizze

    Nizze 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 ??
  3. Erel

    Erel Administrator Staff Member Licensed User

    You should download the USB library and check it in the libraries tab. The link to this library is available at the end of the first post.
  4. ekkallan

    ekkallan New Member Licensed User

    Hi.
    Can the Client(2.2) send requests to the host?
  5. Erel

    Erel Administrator Staff Member Licensed User

    The client can send data in respond to requests from the host. However the connection here is done with ADB support. You cannot use it as a regular connection between two devices.
  6. keithwb

    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?
  7. Erel

    Erel Administrator Staff Member Licensed User

    This library is based on Android SDK TabHost API. It should be somewhat simpler than the Java API.
  8. fpdianzen

    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 :((
  9. Erel

    Erel Administrator Staff Member Licensed User

  10. fpdianzen

    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.
  11. Erel

    Erel Administrator Staff Member Licensed User

    It is not possible to block such a connection on any Android.
  12. albex

    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
  13. Erel

    Erel Administrator Staff Member Licensed User

    The OS handles HID devices internally. They are not exposed as USB devices.
  14. krzyszp

    krzyszp Member Licensed User

    Hi, I'm trying to get communication between radioactivity detector from http://radioactiveathome.org (I'm member if this project) and my SGSII (4.0.3). The device are HID, have you any idea, how I can read (and send) messages to HID devices?
  15. Erel

    Erel Administrator Staff Member Licensed User

    Does the OS expose it as a standard USB device?
    You should call manager.GetDevices and see if it is recognized. If it is not recognized then there isn't much that you can do.
  16. diego

    diego Member Licensed User

    Hi, perhaps this question is already made: would USB host library recognize an Arduino?
  17. Erel

    Erel Administrator Staff Member Licensed User

    It should be recognized. You should use UsbAccessory with this board.
  18. diego

    diego Member Licensed User

    Thank you! I'll try it. Is there an example on using USBAccesory?
  19. Erel

    Erel Administrator Staff Member Licensed User

    I don't remember seeing such an example. However it should be simpler then interacting with a general USB device.
  20. diego

    diego Member Licensed User

    Sorry, but I don't have skills enough, and the documentation about USB library (Basic4android - USB) doesn't help me.

    I just need to connect and read data from the Arduino.


    :sign0085:

Share This Page

Loading...