Android USB-Host vom Gerät gelesen

Ich versuche, einige Daten von einem USB-Gerät verbunden mit meinem Android-Handy auf host-Modus. Ich bin in der Lage, Daten zu senden, aber das Lesen schlägt fehl.

Habe ich mir angeschaut mehrere Beispiele und versuchte alles was ich konnte, aber ich habe keine Erfahrung in der USB-Kommunikation, obwohl jetzt weiß ich ein wenig, und ich Hänge schon länger an diesem mehr Sorge ich zugeben.

Ich bin nicht sehr vertraut mit der endpoint-Konfiguration, aber ich weiß, ist, dass mein Gerät verwendet ein CDC-Art Kommunikations-Methode, und sowohl die Ausgabe (vom Telefon zum Gerät) und die Eingabe registriert.

Hier ist die ganze Klasse zur Verwaltung der USB-Anschluss nur mit dem Gerät, das an das Telefon angeschlossen ist, es ist nicht fertig, aber ich hätte gerne, dass das Lesen von Teil zu arbeiten, bevor ich weiter gehen.

public class UsbCommunicationManager
{
    static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

    UsbManager usbManager;
    UsbDevice usbDevice;
    UsbInterface intf = null;
    UsbEndpoint input, output;
    UsbDeviceConnection connection;

    PendingIntent permissionIntent;

    Context context;

    byte[] readBytes = new byte[64];

    public UsbCommunicationManager(Context context)
    {
        this.context = context;
        usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

        //ask permission from user to use the usb device
        permissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        context.registerReceiver(usbReceiver, filter);
    }

    public void connect()
    {
        //check if there's a connected usb device
        if(usbManager.getDeviceList().isEmpty())
        {
            Log.d("trebla", "No connected devices");
            return;
        }

        //get the first (only) connected device
        usbDevice = usbManager.getDeviceList().values().iterator().next();

        //user must approve of connection
        usbManager.requestPermission(usbDevice, permissionIntent);
    }

    public void stop()
    {
        context.unregisterReceiver(usbReceiver);
    }

    public String send(String data)
    {
        if(usbDevice == null)
        {
            return "no usb device selected";
        }

        int sentBytes = 0;
        if(!data.equals(""))
        {
            synchronized(this)
            {
                //send data to usb device
                byte[] bytes = data.getBytes();
                sentBytes = connection.bulkTransfer(output, bytes, bytes.length, 1000);
            }
        }

        return Integer.toString(sentBytes);
    }

    public String read()
    {
        //reinitialize read value byte array
        Arrays.fill(readBytes, (byte) 0);

        //wait for some data from the mcu
        int recvBytes = connection.bulkTransfer(input, readBytes, readBytes.length, 3000);

        if(recvBytes > 0)
        {
            Log.d("trebla", "Got some data: " + new String(readBytes));
        }
        else
        {
            Log.d("trebla", "Did not get any data: " + recvBytes);
        }

        return Integer.toString(recvBytes);
    }

    public String listUsbDevices()
    {
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();

        if(deviceList.size() == 0)
        {
            return "no usb devices found";
        }

        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
        String returnValue = "";
        UsbInterface usbInterface;

        while(deviceIterator.hasNext())
        {
            UsbDevice device = deviceIterator.next();
            returnValue += "Name: " + device.getDeviceName();
            returnValue += "\nID: " + device.getDeviceId();
            returnValue += "\nProtocol: " + device.getDeviceProtocol();
            returnValue += "\nClass: " + device.getDeviceClass();
            returnValue += "\nSubclass: " + device.getDeviceSubclass();
            returnValue += "\nProduct ID: " + device.getProductId();
            returnValue += "\nVendor ID: " + device.getVendorId();
            returnValue += "\nInterface count: " + device.getInterfaceCount();

            for(int i = 0; i < device.getInterfaceCount(); i++)
            {
                usbInterface = device.getInterface(i);
                returnValue += "\n  Interface " + i;
                returnValue += "\n\tInterface ID: " + usbInterface.getId();
                returnValue += "\n\tClass: " + usbInterface.getInterfaceClass();
                returnValue += "\n\tProtocol: " + usbInterface.getInterfaceProtocol();
                returnValue += "\n\tSubclass: " + usbInterface.getInterfaceSubclass();
                returnValue += "\n\tEndpoint count: " + usbInterface.getEndpointCount();

                for(int j = 0; j < usbInterface.getEndpointCount(); j++)
                {
                    returnValue += "\n\t  Endpoint " + j;
                    returnValue += "\n\t\tAddress: " + usbInterface.getEndpoint(j).getAddress();
                    returnValue += "\n\t\tAttributes: " + usbInterface.getEndpoint(j).getAttributes();
                    returnValue += "\n\t\tDirection: " + usbInterface.getEndpoint(j).getDirection();
                    returnValue += "\n\t\tNumber: " + usbInterface.getEndpoint(j).getEndpointNumber();
                    returnValue += "\n\t\tInterval: " + usbInterface.getEndpoint(j).getInterval();
                    returnValue += "\n\t\tType: " + usbInterface.getEndpoint(j).getType();
                    returnValue += "\n\t\tMax packet size: " + usbInterface.getEndpoint(j).getMaxPacketSize();
                }
            }
        }

        return returnValue;
    }

    private void setupConnection()
    {
        //find the right interface
        for(int i = 0; i < usbDevice.getInterfaceCount(); i++)
        {
            //communications device class (CDC) type device
            if(usbDevice.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA)
            {
                intf = usbDevice.getInterface(i);

                //find the endpoints
                for(int j = 0; j < intf.getEndpointCount(); j++)
                {
                    if(intf.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_OUT && intf.getEndpoint(j).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)
                    {
                        //from android to device
                        output = intf.getEndpoint(j);
                    }

                    if(intf.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_IN && intf.getEndpoint(j).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)
                    {
                        //from device to android
                        input = intf.getEndpoint(j);
                    }
                }
            }
        }
    }

    private final BroadcastReceiver usbReceiver = new BroadcastReceiver()
    {
        public void onReceive(Context context, Intent intent)
        {
            String action = intent.getAction();
            if(ACTION_USB_PERMISSION.equals(action))
            {
                //broadcast is like an interrupt and works asynchronously with the class, it must be synced just in case
                synchronized(this)
                {
                    if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))
                    {
                        setupConnection();

                        connection = usbManager.openDevice(usbDevice);
                        connection.claimInterface(intf, true);

                        //set flow control to 8N1 at 9600 baud
                        int baudRate = 9600;
                        byte stopBitsByte = 1;
                        byte parityBitesByte = 0;
                        byte dataBits = 8;
                        byte[] msg = {
                            (byte) (baudRate & 0xff),
                            (byte) ((baudRate >> 8) & 0xff),
                            (byte) ((baudRate >> 16) & 0xff),
                            (byte) ((baudRate >> 24) & 0xff),
                            stopBitsByte,
                            parityBitesByte,
                            (byte) dataBits
                        };

                        connection.controlTransfer(UsbConstants.USB_TYPE_CLASS | 0x01, 0x20, 0, 0, msg, msg.length, 5000);
                    }
                    else
                    {
                        Log.d("trebla", "Permission denied for USB device");
                    }
                }
            }
            else if(UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action))
            {
                Log.d("trebla", "USB device detached");
            }
        }
    };
}

Ich immer -1 von der read() Methode, die zeigt, irgendeine Art von Fehler, der es immer wieder mal aus. Vielleicht ist das problem kommt von der Konfiguration der Verbindung, ich habe versucht, mehrere (sprich: trial and error) und keiner war, überraschend ich brauche keine Konfiguration zum senden von Daten an das Gerät.


Bearbeiten

Es muss auch darauf hingewiesen werden, dass das Kabel das ich verwende, ist micro-USB-zu-micro-USB und es funktioniert nur in eine Richtung, dass ist mein Gerät wird angetrieben von meinem Handy nur, wenn der Stecker verbunden mit Telefon-und plug B angeschlossenen Gerät, nicht die andere Weise herum... es scheint sehr seltsam. Die Tatsache, dass ich bin in der Lage, Daten senden und nicht empfangen, wenn an der richtigen Weg bleibt.


EDIT 2

Fand ich, dass jemand anderes hatte das gleiche problem aber es scheint, er war nicht in der Lage, es zu lösen.


EDIT 3

Schließlich fand ich die Lösung auf auf dieser Seite:

Weiteres großes Versäumnis ist, dass es keinen Mechanismus gibt, der für den host zu Benachrichtigen, das Gerät, dass es eine datensenke, die auf der host-Seite bereit, um Daten zu akzeptieren. Dies bedeutet, dass das Gerät möglicherweise versuchen Sie, Daten zu senden, während der host ist nicht empfangsbereit, wodurch langwierige Sperrung timeouts bei der übertragung Routinen. So ist es dringend empfohlen, dass Sie den virtuellen seriellen Schnittstelle DTR (Data Terminal Ready) - signal verwendet werden, wo möglich, zu bestimmen, wenn eine host-Anwendung ist bereit für die Daten.

Also das DTR-signal war zwingend erforderlich und alles, was ich tun musste, war, fügen Sie diese an die interface-Konfiguration:

connection.controlTransfer(0x21, 0x22, 0x1, 0, null, 0, 0);

BEARBEITEN 4

Wenn jemand interessiert ist, ich das Projekt beendet und es ist open source und veröffentlicht auf meine GitHub account. Es ist nicht stabil die ganze Zeit, obwohl (siehe den Hinweise) und ich Plane nicht, daran zu arbeiten nicht mehr, aber es funktioniert. Fühlen Sie sich frei, es zu benutzen für Ihre eigenen Projekte.

Kommentar zu dem Problem
was usb-Gerät, das Sie verwenden? Ich will an die Daten zu senden set GPIO pin von meiner CP2112EK Gerät. können Sie mir helfen bezüglich dieser Kommentarautor: Qadir Hussain
Ich war mit einem ATmega32U4, im wesentlichen ein Arduino Leonardo, der registriert sich selbst als ein CDC-device. CP2112EK scheint ein HID-Gerät, das braucht eine andere Konfiguration. Kommentarautor: Solenoid
@Magnetspule, Wo diese Linie.. controlTransfer(0x21, 0x22, 0x1, 0, null, 0, 0) ?? Kommentarautor: Palak Darji
@Magnetspule Hey, wo fügen Sie die Zeile zum setzen des DTR-Signals? Ich werde versuchen, 2-Wege-Kommunikation zwischen meinem Nexus 9 und ein Arduino Leonardo, sehr ähnlich zu deiner situation. Ich bin stecken in der Antwort -1-Schleife trotz senden von seriellen Nachrichten, die alle 2 Sekunden von meinem Arduino. Irgendwelche Tipps? Kommentarautor: Karoly S
@Karoly S: es ist schon eine Weile, ich habe nicht berührt, das Projekt so weiß ich wirklich nicht, aber fühlen Sie sich frei, um es hier und nehmen Sie alle anderen Teile, die Sie brauchen: github.com/Nurgak/Smartphone-sensor-data-collection-application Kommentarautor: Solenoid

InformationsquelleAutor der Frage Solenoid | 2013-11-01

Schreibe einen Kommentar