2012-11-08 13 views
14

मैं यूएसबी और एंड्रॉइड के लिए नया हूं इसलिए कृपया मुझे माफ़ कर दो अगर मैं खुद को स्पष्ट रूप से समझाऊं।एक यूएसबी छिपा डिवाइस के साथ संचार करने के लिए एंड्रॉइड का उपयोग

मैं एक यूएसबी HID डिवाइस है कि मैं Windows में के साथ संवाद कर सकते हैं। मैं एंड्रॉइड 3.1 चलाने वाले एसर आइकोनिया ए 500 टैबलेट का उपयोग करके संचार स्थापित करने की कोशिश कर रहा हूं।

मैं डिवाइस को ढूंढने में सक्षम हूं, इसका अनुमान लगाता हूं, केवल एकमात्र उपलब्ध इंटरफ़ेस प्राप्त करता हूं, केवल एकमात्र उपलब्ध एंडपॉइंट (0) प्राप्त करता हूं, और यह निर्धारित करता है कि यह किस प्रकार का एंडपॉइंट है (डिवाइस से मेजबान में स्थानांतरण को बाधित करें)।

यूएसबी कल्पना की मेरी समझ है कि सभी HID डिवाइस एक नियंत्रण endpoint (Endpoint 0) और अंत बिंदु में व्यवधान के लिए एक munimum पर आवश्यक हैं है। लेकिन ऐसा लगता है कि एंडपॉइंट 0 यहां अंतराल में अंतराल है, न कि नियंत्रण समापन बिंदु।

फिर भी उपकरण की गणना करने में इसे सफलतापूर्वक नियंत्रण endpoint भर में अपने वर्णनकर्ता डेटा ट्रांसफर करना होगा ताकि। मैं यह समझता हूं कि नियंत्रण समापन बिंदु इसलिए पाया जा रहा है (और उपयोग किया जाता है) क्योंकि होस्ट वास्तव में डिवाइस को गिनती करता है।

इस रूप में ऊपर कहा गया है जहाँ तक मैं आगे बढ़ना करने में सक्षम हूँ है, केवल इंटरफ़ेस/आवेदन स्तर पर मेरे लिए प्रस्तुत endpoint व्यवधान प्रकार की मेजबानी के लिए डिवाइस से जा रहा है। मेजबान से डिवाइस, बाधा या नियंत्रण में जा रहे मेरे ऐप के लिए कोई एंडपॉइंट उपलब्ध नहीं है। तो उपकरण यह बताने की प्रतीक्षा करता है कि क्या करना है और मेजबान डिवाइस में कुछ होने की प्रतीक्षा करता है। बहुत उत्तेजक नहीं है।

ध्यान रखें कि यह डिवाइस विंडोज से कनेक्ट होने पर ठीक से प्रतिक्रिया देता है, उदा। मैं 13 बाइट डेटा युक्त एक रिपोर्ट भेजने में सक्षम हूं जो डिवाइस को एलईडी लाइट करने का कारण बनता है। तो ऐसा लगता है कि यूएसबी छिपाई spec के साथ अनुपालन किया जा रहा है। निराशा के एक अधिनियम के रूप में मैंने डिवाइस पर डेटा जमा करने के लिए नियंत्रण ट्रांसफर() और UsbRequest() का उपयोग करके, एक नियंत्रण अंतराल और एक अंतराल आउट एंडपॉइंट के रूप में इस एक एंडपॉइंट का उपयोग करने का प्रयास किया है, किसी भी मामले में कोई प्रतिक्रिया नहीं है।

तो मेरा सवाल यह है: "डिवाइस को स्थापित करने के लिए नियंत्रण हस्तांतरण एंडपॉइंट (?) का उपयोग किया जा रहा है, मैं इसे & क्यों नहीं ढूंढ पा रहा हूं?"

private UsbManager mUsbManager; 
private UsbDevice mDevice; 
private UsbDeviceConnection mConnectionRead; 
private UsbDeviceConnection mConnectionWrite; 
private UsbEndpoint mEndpointRead; 
private UsbEndpoint mEndpointWrite; 

    // check for existing devices 
    for (UsbDevice device : mUsbManager.getDeviceList().values()) 
    { 
     //Need to filter for my device when other HIDs are also connected, but for now...   
     String devName = device.getDeviceName(); 
     if (DEBUG == 1){ 
     Toast.makeText(UsbHidDeviceTesterActivity.this, "My device got connected: " + devName, Toast.LENGTH_LONG).show(); 
     } 
     //mDevice = device; 
     setHIDDevice(device); 
    } 

private boolean setHIDDevice(UsbDevice device) 
{  
    UsbInterface usbInterfaceRead = null; 
    UsbInterface usbInterfaceWrite = null; 
    UsbEndpoint ep1 = null; 
    UsbEndpoint ep2 = null; 
    boolean UsingSingleInterface = true; 

    mDevice = device; 

    //This HID device is using a single interface 
    if (UsingSingleInterface) 
    { 
     //usbInterfaceRead = device.getInterface(0x00);//only 1 EP on this interface 
     usbInterfaceRead = findInterface(device); 

     //Try getting an interface at next index 
     //usbInterfaceWrite = device.getInterface(0x01);//throws exception 

     // Try using the same interface for reading and writing 
     usbInterfaceWrite = usbInterfaceRead; 

     int endPointCount = usbInterfaceWrite.getEndpointCount(); 
     if (DEBUG == 2) 
     { 
      Toast.makeText(UsbHidDeviceTesterActivity.this, "Endpoints: " + endPointCount, Toast.LENGTH_LONG).show(); 
      //Toast.makeText(UsbHidDeviceTesterActivity.this, "Interface: " + usbInterfaceRead, Toast.LENGTH_LONG).show(); 
     } 

     if (endPointCount == 1)//only getting 1 endpoint 
     { 
      ep1 = usbInterfaceRead.getEndpoint(0); 
      //As an act of desperation try equating ep2 to this read EP, so that we can later attempt to write to it anyway 
      ep2 = usbInterfaceRead.getEndpoint(0); 
     } 
     else if (endPointCount == 2) 
     { 
      ep1 = usbInterfaceRead.getEndpoint(0); 
      ep2 = usbInterfaceRead.getEndpoint(1); 
     } 
    } 

    else  // ! UsingSingleInterface 
    { 
     usbInterfaceRead = device.getInterface(0x00); 
     usbInterfaceWrite = device.getInterface(0x01); 
     if ((usbInterfaceRead.getEndpointCount() == 1) && (usbInterfaceWrite.getEndpointCount() == 1)) 
     { 
      ep1 = usbInterfaceRead.getEndpoint(0); 
      ep2 = usbInterfaceWrite.getEndpoint(0); 
     } 
     if (DEBUG == 3) 
     { 
      Toast.makeText(UsbHidDeviceTesterActivity.this, "Using Dual Interface", Toast.LENGTH_LONG).show(); 
     } 
    } 

    //because ep1 = ep2 this will now not cause a return unless no ep is found at all 
    if ((ep1 == null) || (ep2 == null)) 
    { 
     if (DEBUG == 4) 
     { 
      Toast.makeText(UsbHidDeviceTesterActivity.this, "One EP is null", Toast.LENGTH_LONG).show(); 
     } 
     return false; 
    } 

    // Determine which endpoint is the read, and which is the write 
    if (ep1.getType() == UsbConstants.USB_ENDPOINT_XFER_INT)//I am getting a return of 3, which is an interrupt transfer 
    { 
     if (ep1.getDirection() == UsbConstants.USB_DIR_IN)//I am getting a return of 128, which is a device-to-host endpoint 
     { 
      mEndpointRead = ep1; 
      if (DEBUG == 5) 
      { 
       Toast.makeText(UsbHidDeviceTesterActivity.this, "EP1 type: " + ep1.getType(), Toast.LENGTH_LONG).show(); 
      } 
     } 
     if (ep1.getDirection() == UsbConstants.USB_DIR_OUT)//nope 
     { 
      mEndpointWrite = ep1; 
      if (DEBUG == 6) 
      { 
       Toast.makeText(UsbHidDeviceTesterActivity.this, "EP1 is a write", Toast.LENGTH_LONG).show(); 
      } 
     } 
    } 

    if (ep2.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) 
    { 
     if (ep2.getDirection() == UsbConstants.USB_DIR_IN) 
     { 
      //Try treating it as a write anyway    
      //mEndpointRead = ep2; 
      mEndpointWrite = ep2; 
     } 
     else if (ep2.getDirection() == UsbConstants.USB_DIR_OUT) 
     { 
      //usbEndpointWrite = ep2; 
      mEndpointWrite = ep2; 
     } 
    } 

    //check that we should be able to read and write 
    if ((mEndpointRead == null) || (mEndpointWrite == null)) 
    { 
     return false; 
    } 
    if (device != null) 
    { 
     UsbDeviceConnection connection = mUsbManager.openDevice(device); 
     if (connection != null && connection.claimInterface(usbInterfaceRead, true)) 
     { 
      Log.d(TAG, "open SUCCESS"); 
      mConnectionRead = connection; 
      // Start the read thread 
      //Comment out while desperately attempting to write on this connection/interface 
      //Thread thread = new Thread(this); 
      //thread.start(); 

     } 
     else 
     { 
      Log.d(TAG, "open FAIL"); 
      mConnectionRead = null; 
     } 
    } 
    if (UsingSingleInterface) 
    { 
     mConnectionWrite = mConnectionRead; 
    } 
    else //! UsingSingleInterface 
    { 
     mConnectionWrite = mUsbManager.openDevice(device); 
     mConnectionWrite.claimInterface(usbInterfaceWrite, true); 
    } 
    return true; 
} 

// searches for an interface on the given USB device 
private UsbInterface findInterface(UsbDevice device) { 
    Log.d(TAG, "findInterface " + device); 
    int count = device.getInterfaceCount(); 
    if (DEBUG == 7) 
    { 
     Toast.makeText(UsbHidDeviceTesterActivity.this, "Interface count: " + count, Toast.LENGTH_LONG).show(); 
    } 

    for (int i = 0; i < count; i++) { 
     UsbInterface intf = device.getInterface(i); 
     String InterfaceInfo = intf.toString(); 
     Log.d(TAG, "Interface: " + InterfaceInfo); 
     //Class below is 3 for USB_HID 
     if (intf.getInterfaceClass() == 3 && intf.getInterfaceSubclass() == 0 && 
       intf.getInterfaceProtocol() == 0) { 
      return intf; 
     } 
     //....try just returning the interface regardless of class/subclass 
     //return intf; 
    } 

    return null; 
} 
private boolean sendControlTransfer(byte[] dataToSend) 
{ 
    synchronized (this) 
    { 
    if (mConnectionRead != null) 
    { 
     //byte[] message = new byte[13]; // or 14? 
     byte[] message = dataToSend; 
     if (DEBUG == 9) 
     { 
      Toast.makeText(UsbHidDeviceTesterActivity.this, "Sending Control Transfer", Toast.LENGTH_LONG).show(); 
     } 

     //first field ox21 is bin 00100001 which splits into 0 01 00001 for direction(1bit)/type(2b)/recipient(5b) 
     //To set direction as 'host to Device' we need 0, To set type to HID we need 11 (3), and for recipient we want 00001 
     //second field 0x09 is class specific request code, 0x09 is listed as 'reserved for future use' 
     //third field 0x200 is value 
     //int transfer = mConnectionRead.controlTransfer(0x21, 0x9, 0x200, 0, message, message.length, 0); 
     //try with type set to HID 
     int transfer = mConnectionRead.controlTransfer(0xC1, 0x9, 0x200, 0, message, message.length, 0); 
     if (DEBUG == 10) 
     { 
      Toast.makeText(UsbHidDeviceTesterActivity.this, "Transfer returned " + transfer, Toast.LENGTH_LONG).show(); 
     } 
    } 
    } 
    return true; 
} 


private boolean sendInterruptTransfer(byte[] dataToSend) 
{ 
    int bufferDataLength = mEndpointWrite.getMaxPacketSize();//The write endpoint is null unless we just copy the read endpoint 
    if (DEBUG == 12) 
    { 
     Toast.makeText(UsbHidDeviceTesterActivity.this, "Max Packet Size: " + bufferDataLength, Toast.LENGTH_LONG).show(); 
    } 

    ByteBuffer buffer = ByteBuffer.allocate(bufferDataLength + 1); 
    UsbRequest request = new UsbRequest(); 
    buffer.put(dataToSend); 

    request.initialize(mConnectionWrite, mEndpointWrite); 
    request.queue(buffer, bufferDataLength); 

    try 
    { 
     /* only use requestwait on a read 
     if (request.equals(mConnectionWrite.requestWait())) 
     { 
      return true; 
     } 
     */ 
    } 
    catch (Exception ex) 
    { 
     // An exception has occurred 
     if (DEBUG == 13) 
     { 
      Toast.makeText(UsbHidDeviceTesterActivity.this, "Caught Write Exception", Toast.LENGTH_LONG).show(); 
     } 
    } 

    return true; 
} 

उत्तर

7

तो, मैं इसी तरह की चीजों पर शोध कर रहा हूं। मैं पुष्टि नहीं कर सकता, लेकिन मुझे विश्वास है कि क्या हो रहा है:

  1. एंड्रॉइड नियंत्रण समापन बिंदु सूचीबद्ध नहीं करता है जब यह इसके अंत बिंदुओं को दर्शाता है। यह केवल अन्य अंतराल सूचीबद्ध करता है।
  2. किसी भी अंत बिंदु से कनेक्शन 0 समाप्ति बिंदु को, controlTransfer विधि है, जो (एपीआई से उद्धृत) के माध्यम से नियंत्रण स्थानान्तरण भेज सकते हैं "इस उपकरण के लिए अंतिम बिंदु शून्य पर एक नियंत्रण लेन-देन करता है।"
  3. तो, आपके उपरोक्त कोड में, मैं 0 वें एंडपॉइंट का उपयोग एक इंटरप्ट इनपुट एंडपॉइंट के रूप में करता हूं, लेकिन यह अभी भी नियंत्रण स्थानान्तरण की अनुमति देगा।
  4. एचआईडी डिवाइस का उपयोग करने वाले किसी का उदाहरण मिस्ले लॉन्चर डेमो है, जो डिवाइस इसका उपयोग करता है वह एक अंतराल एंडपॉइंट वाला एक छिपा हुआ डिवाइस है।
+1

@ ज़बूनी- आप बिल्कुल सही हैं, भले ही सिंगल एंडपॉइंट (ईपी 0) को एक इंटरप्ट एंडपॉइंट के रूप में पहचाना जा रहा था, अगर मैंने अभी इलाज किया है तो वैसे भी लिखना है और उस पर नियंत्रण हस्तांतरण किया गया है तो यह काम करता है। – DasBoos

9

आप निम्न का उपयोग करके इंटरफेस और अंत बिंदु के विवरण की एक पूरी सूची प्राप्त कर सकते हैं:

किसी भी जानकारी के लिए धन्यवाद, नीचे प्रासंगिक कोड, मैं अगर जरूरत अपनी संपूर्णता में आराम शामिल कर सकते हैं है :

+1

@ user1815293- उत्तर के लिए धन्यवाद। आपका कोड DEBUGs का एक बहुत साफ संस्करण है जिसे मैंने अपने कोड में बिखराया था। हालांकि, जब मैं आपका कोड चलाता हूं तो यह पुष्टि करता है कि मुझे पहले से क्या मिला है: कि एक ही एंडपॉइंट के साथ केवल 1 इंटरफेस है, और एंडपॉइंट एक इंटरप्ट प्रकार है जो डिवाइस से होस्ट करने की दिशा में चलता है। तो संक्षेप में: एंड्रॉइड में मुझे एक एंडपॉइंट नहीं दिया गया है जिस पर डिवाइस को संदेश भेजना है। फिर भी मुझे पता है कि एंडपॉइंट मौजूद होना चाहिए क्योंकि यह विंडोज़ में उपलब्ध है और काम कर रहा है। इसलिए एंड्रॉइड यूएसबी छिपाई – DasBoos

+0

का उचित रूप से समर्थन नहीं करना चाहिए चाहे यह एक नियंत्रण अंतराल या एक इंटरप्ट एंडपॉइंट है जो उपलब्ध नहीं कराया जा रहा है अस्पष्ट है। इस समस्या में किसी अन्य अंतर्दृष्टि की सराहना की जाएगी, भले ही यह मेरे परिणामों की पुष्टि या विरोधाभास करे। – DasBoos

2

नियंत्रण स्थानांतरण कोई इंटरफ़ेस वर्णनकर्ता नहीं दिखाता है और इसके एंडपॉइंट नंबर डिफ़ॉल्ट रूप से 0 में और बाहर हस्तांतरण के लिए 0 है।

यदि आपके पास अन्य इंटरफेस हैं तो उन इंटरफेस की अनुक्रमणिका 0 से शुरू होनी चाहिए। डिफ़ॉल्ट नियंत्रण स्थानांतरण इंटरफ़ेस गिनती नहीं है।

तो आपका इंटरफ़ेस 0 एंडपॉइंट 1 डिस्क्रिप्टर रखता है। एंडपॉइंट के गुणों को खोजने के लिए UsbEndpoint विधियों का उपयोग करें चाहे यह बाधित प्रकार है या नहीं। अगर यह तो UsbEndpoint.getType (द्वारा endpoint प्रकार है) UsbEndpoint.getEndpointNumber द्वारा 0x03 और अंत बिंदु संख्या लौटना चाहिए() 0x81 लौटना चाहिए जो अंत बिंदु 1.

अपने कोड के नीचे के लिए सामान्य मूल्य है गलत है:

//first field ox21 is bin 00100001 which splits into 0 01 00001 for direction(1bit)/type(2b)/recipient(5b) 
    //To set direction as 'host to Device' we need 0, **To set type to HID we need 11 (3)**, and for recipient we want 00001 
    //second field 0x09 is class specific request code, **0x09 is listed as 'reserved for future use'** 
    //**third field 0x200 is value** 
    //int transfer = mConnectionRead.controlTransfer(0x21, 0x9, 0x200, 0, message, message.length, 0); 
    //try with type set to HID 
    int transfer = mConnectionRead.controlTransfer(0xC1, 0x9, 0x200, 0, message, message.length, 0); 

टाइप 2 बिट्स का उपयोग वर्ग विशिष्ट अनुरोध को इंगित करने के लिए किया जाता है, यानी इसका मान 01, 0x09 छुपा वर्ग विशिष्ट अनुरोध SET_REPORT है, आरक्षित नहीं है। मान wValue है जिसे छुपा वर्ग के लिए रिपोर्ट आईडी के रूप में उपयोग किया जाता है, आपके मामले के लिए यह शायद 0 है, यदि आपके पास छुपा वर्णक पर केवल एक रिपोर्ट है। और चौथा पैरामीटर wIndex है जिसका उपयोग प्राप्तकर्ता को इंगित करने के लिए किया जाना चाहिए, आपके मामले के लिए यह प्राप्तकर्ता के रूप में इंटरफ़ेस के लिए 0x01 होना चाहिए।

तो या पढ़ें के लिए नियंत्रण हस्तांतरण प्राप्त डेटा प्रपत्र डिवाइस के लिए अपने कोड होना चाहिए:

int transfer = mConnectionRead.controlTransfer(0xA1, 0x01, 0x00, 0x01, message, message.length, 0); 

जहां दूसरा पैरामीटर में 0x01 GET_REPORT है छुपाया विशेष अनुरोध कॉल है।

और लिखें के लिए नियंत्रण हस्तांतरण के लिए अपने कोड या भेजने के डिवाइस के लिए डेटा होना चाहिए:

int transfer = mConnectionWrite.controlTransfer(0x21, 0x09, 0x00, 0x01, message, message.length, 0); 

जब से तुम केवल इंटरप्ट में endpoint 1 है, थोक या इंटरप्ट हस्तांतरण होना चाहिए की तरह:

int transfer = bulkTransfer (ep1, message, message.length, 0); 

अंतराल आउट आउटपॉइंट के लिए आपके डिवाइस के फर्मवेयर के इंटरफ़ेस डिस्क्रिप्टर पर एक एंडपॉइंट डिस्क्रिप्टर होना चाहिए।

+0

ग्रेट रंडाउन। इसके लिए शुक्रिया! – tricknology

संबंधित मुद्दे