USB interface in android

前端 未结 5 1823
天命终不由人
天命终不由人 2021-02-06 10:02

I rooted my device and working in host mode. I can able to detect the usb device connected to my tab but Am having two questions.

1) i try to display my device name usi

相关标签:
5条回答
  • 2021-02-06 10:40

    device name

    This looks like the internal device name from the Linux Kernel.

    manufacturer name

    You only get this indirectly via the USB VID (Vendor ID). They are assigned and maintained by the USB-IF.

    A device may provide a name for the manufacturer in its string descriptor, but AFAIK this is optional - and not exposed in the high level android java interface.

    You can try your luck with UsbDeviceConnection.getRawDescriptors, but that would require rather ugly fiddeling with bytes.

    to mass storage

    USB Mass storage is a rather complex protocol, so talking directly via USB Host API would be rather difficult to implement. Some Android firmware images can mount USB flash drives, that would be much simpler.

    0 讨论(0)
  • 2021-02-06 10:41

    Just a minor note on the above code, which in principle works just fine. Requesting the user permission to access the USB device is an asynchronous call. So the code should not proceed for that particular device if it does not (yet) have permissions.

    Please allow me to make a small update to the onClick and onReceive methods:

        Button btnDiscover = (Button) findViewById(R.id.buttonDiscover);
        btnDiscover.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                txtInfo.setText("");
                HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
                for (UsbDevice device : deviceList.values()) {
                    Log.i("discover", "Model    :" + device.getDeviceName());
                    if (!manager.hasPermission(device)) {
                        Log.i("discover", "No permission to access, so requesting it now from user (async)");
                        manager.requestPermission(device, mPermissionIntent);
                    } else {
                        showUsbDetails(device);
                    }
                }
            }
        });
    
    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (MainActivity.ACTION_USB_PERMISSION.equals(action)) {
                Log.i("BroadcastReceiver", "onReceive: ACTION_USB_PERMISSION");
                synchronized (this) {
                    UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if(device != null){
                            showUsbDetails(device);
                        }
                    }
                    else {
                        txtInfo.append("permission denied for device " + device);
                    }
                }
    

    Needless to say that showUsbDetails now contains the part from the original code that does the communication with the USB device to query for the manufacturer and other strings.

    0 讨论(0)
  • 2021-02-06 10:44

    Probably you will actually need to read the Raw USB Descriptors to get at the data you want. Here's a basic USB device discovery program I wrote for my own purposes. Mind you that I'm looking for a specific device (a Dajac Easy I/O 1000 data acquisition system) but you can apply the same principles. I do show you how to get the data you're looking for.

    Here's the code first. My package is usbtest3, and the file is MainActivity.java:

    package com.hotspotoffice.usbtest3;
    
    // David Schofield, Hotspot Office, LLC., Pittsburgh, PA.
    // Donations via PayPal always welcome! schofield (dot) david (at) verizon.net
    
    import java.io.UnsupportedEncodingException;
    import java.util.HashMap;
    import java.util.Iterator;
    import android.os.Bundle;
    import android.app.Activity;
    import android.app.PendingIntent;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.view.View;
    import android.view.Menu;
    import android.widget.Button;
    import android.widget.TextView;
    import android.hardware.usb.UsbConstants;
    import android.hardware.usb.UsbManager;
    import android.hardware.usb.UsbDevice;
    import android.hardware.usb.UsbDeviceConnection;
    import android.hardware.usb.UsbInterface;
    
    
    public class MainActivity extends Activity {
    
        protected static final int STD_USB_REQUEST_GET_DESCRIPTOR = 0x06;
        // http://libusb.sourceforge.net/api-1.0/group__desc.html
        protected static final int LIBUSB_DT_STRING = 0x03;
        private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
    
        private Button btnDiscover;
        private TextView txtInfo;
        private PendingIntent mPermissionIntent; 
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btnDiscover=(Button)findViewById(R.id.btnDiscover);
            txtInfo=(TextView)findViewById(R.id.txtInfo);
    
            mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
            IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
            registerReceiver(mUsbReceiver, filter);
    
            btnDiscover.setOnClickListener(new View.OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    // txtInfo.setText("Button has been Pressed for "+(++i)+" Times.");
    
                    UsbManager manager = (UsbManager)getSystemService(Context.USB_SERVICE);
    
                    HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
                    Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
                    while(deviceIterator.hasNext()){
                        UsbDevice device = deviceIterator.next();
    
                        manager.requestPermission(device, mPermissionIntent);
    
                        txtInfo.append("Model:" + device.getDeviceName() + "\n");  
                        txtInfo.append("DeviceID:" + device.getDeviceId() + "\n");
                        txtInfo.append("Vendor:" + device.getVendorId() + "\n");
                        txtInfo.append("Product:" + device.getProductId() + "\n");
                        txtInfo.append("Class:" + device.getDeviceClass() + "\n");
                        txtInfo.append("Subclass:" + device.getDeviceSubclass() + "\n");
                        txtInfo.append("Protocol:" + device.getDeviceProtocol() + "\n");
    
                        UsbInterface intf = device.getInterface(0);
                        int epc = 0;
                        epc = intf.getEndpointCount();
                        txtInfo.append("Endpoints:" + epc + "\n");
    
                        txtInfo.append("Permission:" + Boolean.toString(manager.hasPermission(device))  + "\n");
    
                        UsbDeviceConnection connection = manager.openDevice(device);
                        if(null==connection){
                            txtInfo.append("(unable to establish connection)\n");
                        } else {
    
                            // Claims exclusive access to a UsbInterface. 
                            // This must be done before sending or receiving data on 
                            // any UsbEndpoints belonging to the interface.
                            connection.claimInterface(intf, true);
    
                            // getRawDescriptors can be used to access descriptors 
                            // not supported directly via the higher level APIs, 
                            // like getting the manufacturer and product names.
                            // because it returns bytes, you can get a variety of
                            // different data types.
                            byte[] rawDescs = connection.getRawDescriptors();
                            String manufacturer = "", product = "";
    
                            try
                            {
                                byte[] buffer = new byte[255];
                                int idxMan = rawDescs[14];
                                int idxPrd = rawDescs[15];
    
                                int rdo = connection.controlTransfer(UsbConstants.USB_DIR_IN
                                        | UsbConstants.USB_TYPE_STANDARD, STD_USB_REQUEST_GET_DESCRIPTOR,
                                        (LIBUSB_DT_STRING << 8) | idxMan, 0, buffer, 0xFF, 0);
                                manufacturer = new String(buffer, 2, rdo - 2, "UTF-16LE");
    
                                rdo = connection.controlTransfer(UsbConstants.USB_DIR_IN
                                                | UsbConstants.USB_TYPE_STANDARD, STD_USB_REQUEST_GET_DESCRIPTOR,
                                        (LIBUSB_DT_STRING << 8) | idxPrd, 0, buffer, 0xFF, 0);
                                product = new String(buffer, 2, rdo - 2, "UTF-16LE");
    
                            } catch (UnsupportedEncodingException e)
                            {
                            e.printStackTrace();
                            }
    
                            txtInfo.append("Manufacturer:" + manufacturer + "\n");                      
                            txtInfo.append("Product:" + product + "\n");                        
                            txtInfo.append("Serial#:" + connection.getSerial() + "\n");                     
                        }
    
                        txtInfo.append("------------------------------------\n");                   
                    }               
    
                }
            });
    
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.activity_main, menu);
            return true;
        }
    
        private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
    
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (ACTION_USB_PERMISSION.equals(action)) {
                    synchronized (this) {
                        UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
    
                        if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                            if(device != null){
                              //call method to set up device communication
                           }
                        } 
                        else {
                            txtInfo.append("permission denied for device " + device);
                        }
                    }
                }
            }
        };
    
    }
    

    My manifest file containing the intents and requirements for the USB Host device support:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.hotspotoffice.usbtest3"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-feature android:name="android.hardware.usb.host" />
    
        <uses-sdk
            android:minSdkVersion="15"
            android:targetSdkVersion="15" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
    
            <activity
                android:name="com.hotspotoffice.usbtest3.MainActivity"
                android:label="@string/app_name" >
    
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
    
                <intent-filter>
                    <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
                </intent-filter>
    
                <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                    android:resource="@xml/device_filter" />
    
            </activity>
        </application>
    
    </manifest>
    

    Finally, you will need a device filter. This is located under \res\xml\device_filter.xml Note that I had to create the xml folder myself, under \res.

    <?xml version="1.0" encoding="utf-8"?>
    
    <resources>
        <usb-device vendor-id="7635" product-id="1" class="255" subclass="255" protocol="0" />
    </resources>
    

    Note that all the fields need to be in decimal, not hex. You'll need to substitute your own vendor, product, class and subclass values from your own device. You can use a program like "USB Host View" or "USB Device Info" to discover these values. (download them free from the Play Store.)

    Finally, here's how I defined the user interface in Activity_Main.xml
    You'll need at least the Discover button, and the TextMultiline for output. (Ignore the Init and On/Off buttons.)

    BTW, I'm using a 10" Toshiba Thrive tablet, so YMMV.

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" >
    
        <EditText
            android:id="@+id/txtInfo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/btnDiscover"
            android:layout_alignRight="@+id/textView1"
            android:layout_centerVertical="true"
            android:ems="10"
            android:inputType="textMultiLine"
            android:maxLines="50"
            android:minLines="20"
            android:minWidth="400dp" >
    
            <requestFocus />
        </EditText>
    
        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_above="@+id/btnToggleDIO"
            android:layout_marginLeft="192dp"
            android:layout_toRightOf="@+id/btnDiscover"
            android:text="@string/lblDIO"
            android:textAppearance="?android:attr/textAppearanceMedium" />
    
        <Button
            android:id="@+id/btnDiscover"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/btnInit"
            android:layout_alignBottom="@+id/btnInit"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="73dp"
            android:text="@string/strDiscover" />
    
        <ToggleButton
            android:id="@+id/btnToggleDIO"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/btnInit"
            android:layout_alignBottom="@+id/btnInit"
            android:layout_alignLeft="@+id/textView1"
            android:text="@string/strIOState" />
    
        <Button
            android:id="@+id/btnInit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_above="@+id/txtInfo"
            android:layout_marginBottom="29dp"
            android:layout_marginLeft="48dp"
            android:layout_toRightOf="@+id/btnDiscover"
            android:text="@string/strInit" />
    
    </RelativeLayout>
    

    When I run my program and plug in my device, it asks for my permission to connect and I say "Ok". then I click Discover, and it tells me among other things that the manufacturer is "Dajac Inc." the product is "EIO1000" and the serial# is "0000004B".

    I wish you good providence; you can give me credit but it's only by standing on the shoulders of others (with a lot of my own sweat) I've been able to see this far. Pass it forward! -David

    0 讨论(0)
  • 2021-02-06 10:47

    Code above works fine for most of the devices except Samsung mobile devices. For making them supply Language ID else you will get stall.

    int rdo = connection.controlTransfer(UsbConstants.USB_DIR_IN
    | UsbConstants.USB_TYPE_STANDARD, STD_USB_REQUEST_GET_DESCRIPTOR,
    (LIBUSB_DT_STRING << 8) | idxMan, 0x0409, buffer, 0xFF, 0);
    
    0 讨论(0)
  • 2021-02-06 10:51
    1. getVendorId() should give you manufacturer's name. Other calls include getDeviceName(), getDeviceId(), getDeviceClass(), getDeviceSubclass(), getDeviceProtocol(), getProductId(). refer this link: Android USB Host

    2. For Data Transfers, refer this link: BulkTransfer. Read from the file in a buffer and pass the buffer to bulkTransfer call along with specific output Endpoint of your device and data length.

    0 讨论(0)
提交回复
热议问题