قراءة مضيف USB Android من الجهاز



host cdc (1)

يمكنك استخدام UsbSerial Lib من several

رمز المثال الخاص بي:

    UsbManager usbManager = null;
    UsbDeviceConnection connection = null;
    UsbSerialDriver driver = null;
    UsbSerialPort port = null;

    usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

    List<UsbSerialDriver> availableDrivers =  UsbSerialProber.getDefaultProber().findAllDrivers(manager);
    // Open a connection to the first available driver.

    for (UsbSerialDriver usd : availableDrivers) {
        UsbDevice udv = usd.getDevice(); 
        if (udv.getVendorId()==0x067B || udv.getProductId()==2303){
            driver = usd;
            break;
        }
    }
        connection = usbManager.openDevice(driver.getDevice());

        port = driver.getPorts().get(0);

        driver.getDevice().

    }

        if (connection == null) return;

        try{

            port.open(connection);
            port.setParameters(4800, UsbSerialPort.DATABITS_8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);

                try{

                    byte buffer[] = new byte[250];
                    //Log.d("GPS_REQ", "->");
                    int numBytesRead = port.read(buffer, 500); //5000; 

                }catch (Exception e) {
                    Log.d("GPS_ERR", e.getLocalizedMessage());
                }

أحاول الحصول على بعض البيانات من جهاز USB متصل بهاتف Android الخاص بي الموجود على وضع المضيف. أنا قادر على إرسال البيانات إليه ، لكن القراءة تفشل.

لقد نظرت في several examples وحاولت كل ما استطعت ولكن ليس لدي أي خبرة في الاتصال عبر USB ، على الرغم من أنني الآن أعرف القليل ، وكنت عالقاً في هذا الوقت الذي يهمني أن أعترف به.

لست على دراية كبيرة بتكوين نقطة النهاية ، لكني أعلم أن جهازي يستخدم طريقة اتصال من نوع CDC ويتم تسجيل كل من المخرجات (من الهاتف إلى الجهاز) والإدخال.

إليك الفصل بأكمله الذي يدير اتصال USB بالجهاز الوحيد المتصل بالهاتف ، ولا ينتهي بأي وسيلة ، لكنني أرغب في الحصول على جزء القراءة هذا للعمل قبل أن أذهب إلى أبعد من ذلك.

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");
            }
        }
    };
}

أستمر في الحصول على -1 من طريقة read() التي تشير إلى نوع من الخطأ ، فإنه دائمًا ما يخرج. ربما المشكلة تأتي من تكوين الاتصال ، لقد حاولت عدة (اقرأ: التجربة والخطأ) ولا شيء يعمل ، من المستغرب أنني لا تحتاج إلى أي تكوين لإرسال البيانات إلى الجهاز.

تصحيح

يجب أيضًا ملاحظة أن الكبل الذي أستخدمه هو micro-USB إلى micro-USB وأنه يعمل فقط بطريقة واحدة ، وهذا هو أن جهازي يعمل بواسطة هاتفي فقط عندما يكون القابس A متصل بالهاتف والموصل B متصلاً الجهاز ، وليس العكس ... يبدو غريبا جدا. حقيقة أنني قادرة على إرسال البيانات وعدم تلقي عند توصيل الطريق الصحيح لا يزال قائما.

تحرير 2

لقد وجدت أن شخصًا آخر لديه نفس المشكلة ولكن يبدو أنه لم يتمكن من حلها.

تحرير 3

وجدت في النهاية الحل في هذه الصفحة :

هناك إشراف رئيسي آخر هو أنه لا توجد آلية للمضيف لإعلام الجهاز بوجود مصدر بيانات على الجانب المضيف جاهز لقبول البيانات. هذا يعني أن الجهاز قد يحاول إرسال البيانات بينما لا يستمع المضيف ، مما يتسبب في توقف طويل في إجراءات الإرسال. وبالتالي ، يوصى بشدة باستخدام إشارة DTR (DAT Terminal Ready) للخط التسلسلي الافتراضي حيثما أمكن لتحديد ما إذا كان التطبيق المضيف جاهزًا للبيانات.

لذا كانت إشارة DTR إلزامية وكل ما كان علي فعله هو إضافة هذا إلى تكوين الواجهة:

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

تعديل 4

إذا كان أي شخص مهتمًا ، فقد أنهيت المشروع وهو مفتوح المصدر وتم نشره على حساب GitHub . إنه غير مستقر طوال الوقت (انظر notes ) ولا أخطط للعمل بعد ذلك ، لكنه يعمل. لا تتردد في استخدامه لمشاريعك الخاصة.





cdc