Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Communicating with android device from Windows PC via USB

I have android device and windows drivers for it. I have to communicate using my own binary protocol in accessory mode. Is it possible to send data to this device without writing custom USB driver?

like image 607
void Avatar asked Sep 01 '25 20:09

void


1 Answers

USB is a complex protocol because it is 'universal' and can handle a large variety of devices (mass storage, cameras,...). So on your android device has to be implemented a basic USB structure to use standard libraries like libusb or something like that. You can assume that this is the case, because android is in most cases used on processors with USB port.

See http://www.beyondlogic.org/usbnutshell/usb1.shtml.

You can get more information about the USB device classes, interfaces, configurations, endpoints ur android device impmenets by using libusb -v

Then if you know what the USB structure on your android device looks like you can use libusb or another library to write data to specific endpoints in the usb structure by e.g. libusb_bulk_transfer(), libusb_control_transfer()

http://libusb.sourceforge.net/api-1.0/io.html

If you want to program in java you can use usb4java however this is a bit flaky http://usb4java.org/quickstart/libusb.html

The general USB structure is device -> (configuration) -> interface -> endpoint

So the way to write data to an endpoint is:

libusb_init(NULL); 
libusb_open_device_with_vid_pid(NULL, vendor_id, product_id);
libusb_claim_interface(devh, 0);
libusb_bulk_transfer(dev_handle, (2 | LIBUSB_ENDPOINT), data, 
        4, &p, 0); //example
... release interface...
...
libusb_close(devh);
libusb_exit(NULL);

Here is C++ example copied from http://www.dreamincode.net/forums/topic/148707-introduction-to-using-libusb-10/

#include <iostream>
#include <libusb.h>

using namespace std;

int main() {
    libusb_device **devs; //pointer to pointer of device, used to      
                            retrieve a list of devices
    libusb_device_handle *dev_handle; //a device handle
    libusb_context *ctx = NULL; //a libusb session

    int r; //for return values
    ssize_t cnt; //holding number of devices in list
    r = libusb_init(&ctx); //initialize the library for the session we 
                             just declared
    if(r < 0) {
        cout<<"Init Error "<<r<<endl; //there was an error
        return 1;
    }
    libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in 
                                the documentation

    cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
    if(cnt < 0) {
        cout<<"Get Device Error"<<endl; //there was an error
        return 1;
    }
    cout<<cnt<<" Devices in list."<<endl;

    dev_handle = libusb_open_device_with_vid_pid(ctx, 5118, 7424);  
              //these are vendorID and productID I found for my usb device

    if(dev_handle == NULL)
        cout<<"Cannot open device"<<endl;
    else
        cout<<"Device Opened"<<endl;
    libusb_free_device_list(devs, 1); //free the list, unref the devices 
                                         in it

    unsigned char *data = new unsigned char[4]; //data to write

    data[0]='a';data[1]='b';data[2]='c';data[3]='d'; //some dummy values

    int actual; //used to find out how many bytes were written
    if(libusb_kernel_driver_active(dev_handle, 0) == 1) { //find out if 
                                               kernel driver is attached
        cout<<"Kernel Driver Active"<<endl;
        if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
            cout<<"Kernel Driver Detached!"<<endl;
    }
    r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the   
    first) of device (mine had jsut 1)
    if(r < 0) {
        cout<<"Cannot Claim Interface"<<endl;
        return 1;
    }
    cout<<"Claimed Interface"<<endl;

    cout<<"Data->"<<data<<"<-"<<endl; //just to see the data we want to 
    write : abcd
    cout<<"Writing Data..."<<endl;
    r = libusb_bulk_transfer(dev_handle, (2 | LIBUSB_ENDPOINT_OUT), data, 
    4, &actual, 0); //my device's out endpoint was 2, found with trial- 
    the device had 2 endpoints: 2 and 129
    if(r == 0 && actual == 4) //we wrote the 4 bytes successfully
        cout<<"Writing Successful!"<<endl;
    else
        cout<<"Write Error"<<endl;

    r = libusb_release_interface(dev_handle, 0); //release the claimed 
                                                    interface
    if(r!=0) {
        cout<<"Cannot Release Interface"<<endl;
        return 1;
    }
    cout<<"Released Interface"<<endl;    

    libusb_close(dev_handle); //close the device we opened
    libusb_exit(ctx); //needs to be called to end the
    delete[] data; //delete the allocated memory for data
    return 0;
}

So as your device runs android it has a USB structure/functionality. To investigate the USB functionality of your device (device class like mass storage, RNDIS,...) use libusb -v and the see the code above to write custom data to one of the endpoints on the device.

like image 121
ralf htp Avatar answered Sep 04 '25 01:09

ralf htp