2013-11-01 20 views
48

से पढ़ा गया है, मैं मेजबान मोड पर अपने एंड्रॉइड फोन से जुड़े यूएसबी डिवाइस से कुछ डेटा प्राप्त करने की कोशिश कर रहा हूं। मैं इसे डेटा भेजने में सक्षम हूं, लेकिन पढ़ना विफल रहता है।एंड्रॉइड यूएसबी होस्ट डिवाइस

मैंने severalexamples पर देखा है और मैं कोशिश कर सकता हूं लेकिन मुझे यूएसबी संचार में कोई अनुभव नहीं है, हालांकि अब तक मुझे थोड़ा पता है, और मैं अब इस पर अटक गया हूं कि मुझे स्वीकार करना है ।

मैं एंडपॉइंट कॉन्फ़िगरेशन से बहुत परिचित नहीं हूं, लेकिन मुझे पता है कि मेरा डिवाइस एक सीडीसी प्रकार संचार विधि और आउटपुट (फोन से डिवाइस तक) और इनपुट दोनों पंजीकृत है।

यहां पूरी कक्षा है जो फोन से कनेक्ट होने वाली एकमात्र डिवाइस के साथ यूएसबी कनेक्शन का प्रबंधन करती है, यह किसी भी माध्यम से समाप्त नहीं होती है, लेकिन मैं आगे जाने से पहले काम करने के लिए उस पठन भाग को प्राप्त करना चाहता हूं।

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

मैं read() विधि है जो त्रुटि के कुछ प्रकार को इंगित करता है, यह हमेशा बाहर काल से -1 मिलती रहती है। हो सकता है कि समस्या कनेक्शन कॉन्फ़िगरेशन से आती है, मैंने कई कोशिश की है (पढ़ें: परीक्षण और त्रुटि) और कोई भी काम नहीं करता है, आश्चर्य की बात है कि मुझे डिवाइस पर डेटा भेजने के लिए किसी भी कॉन्फ़िगरेशन की आवश्यकता नहीं है।


संपादित

यह भी ध्यान दिया जाना चाहिए कि केबल मैं उपयोग कर रहा हूँ माइक्रो-यूएसबी चार्जर माइक्रो USB है और यह सिर्फ एक ही रास्ता में काम करता है, कि मेरे डिवाइस के द्वारा संचालित है है मेरी केवल तभी फोन करें जब प्लग ए फोन से कनेक्ट हो और प्लग बी डिवाइस से कनेक्ट हो, न कि दूसरी तरफ ... यह बहुत अजीब लगता है। तथ्य यह है कि मैं सही तरीके से प्लग किए जाने पर डेटा भेजने और प्राप्त करने में सक्षम नहीं हूं।


संपादित 2

मुझे लगता है कि somebody else had the same problem पाया लेकिन ऐसा लगता है कि वह इसे हल करने में सक्षम नहीं था।


संपादित 3

मैं अंत में पाया this page पर समाधान:

एक अन्य प्रमुख निरीक्षण उपकरण डेटा है कि वहाँ सूचित करने के लिए मेजबान के लिए कोई तंत्र है कि वहाँ है मेजबान पक्ष पर डेटा स्वीकार करने के लिए तैयार सिंक। इसका मतलब है कि डिवाइस डेटा भेजने की कोशिश कर सकता है, जबकि मेजबान नहीं सुन रहा है, जिससे ट्रांसमिशन दिनचर्या में लंबे समय तक अवरुद्ध टाइमआउट होता है। इस प्रकार अत्यधिक अनुशंसा की जाती है कि वर्चुअल सीरियल लाइन डीटीआर (डेटा टर्मिनल रेडी) सिग्नल का उपयोग यह निर्धारित करने के लिए किया जा सकता है कि कोई होस्ट एप्लिकेशन डेटा के लिए तैयार है या नहीं।

तो डीटीआर संकेत अनिवार्य था और सभी मैं करना पड़ा इंटरफ़ेस विन्यास में जोड़ने के लिए किया गया था:

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

संपादित 4

तो किसी को भी मुझे कोई दिलचस्पी है परियोजना समाप्त की और यह open source and published on my GitHub account है। हालांकि यह हर समय स्थिर नहीं है (notes देखें) और मैं अब इस पर काम करने की योजना नहीं बना रहा हूं, लेकिन यह काम करता है। अपनी परियोजनाओं के लिए इसका इस्तेमाल करने के लिए स्वतंत्र महसूस करें।

+0

क्या USB डिवाइस का उपयोग कर रहे? मैं अपने CP2112EK डिवाइस के जीपीआईओ पिन को सेट करने के लिए डेटा भेजना चाहता हूं। क्या आप इस –

+1

के बारे में मेरी मदद कर सकते हैं मैं एटीमेगा 32 यू 4 का उपयोग कर रहा था, अनिवार्य रूप से एक आर्डिनो लियोनार्डो जो स्वयं को सीडीसी डिवाइस के रूप में पंजीकृत करता था। आपका [सीपी 2112 ईके] (http://www.silabs.com/products/interface/Pages/CP2112EK.aspx) एक छिपा हुआ डिवाइस प्रतीत होता है जिसे कुछ अन्य कॉन्फ़िगरेशन की आवश्यकता होगी। – Solenoid

+0

@Solenoid इस लाइन को कहां रखा जाए .. नियंत्रण ट्रांसफर (0x21, 0x22, 0x1, 0, null, 0, 0) ?? –

उत्तर

1

आप https://github.com/mik3y/usb-serial-for-android

मेरे उदाहरण कोड से की UsbSerial लिब उपयोग कर सकते हैं:

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()); 
       } 
संबंधित मुद्दे