2013-04-11 9 views
14

私はアンドロイド用にUSB経由でGembird SilverShield電源コンセントを制御できる特定のC-programmをコンパイルしようと考えています。私のアンドロイドHDMIのテレビのスティックでこれは非常に便利です。 thisのためのオープンプロジェクトがあります。これはLinuxで動作し、libusbに依存します。ターゲットプラットフォームはアンドロイドICSです。私はUbuntu Linuxで開発したいと思っています。私はそれが働くチャンスは何ですか?必要な手順は何ですか?セットアップアンドロイドSDK、NDK、クロスコンパイラ...
より古い質問があります。here、アンドロイドのlibusbに関連していますが、情報はありません。
アプリをアンドロイド独自のUSBライブラリに移植する方が簡単でしょうか?androidのlibusbに対するコンパイルとリンク

+0

ここではlibusbdroidと呼ばれるプロジェクトでありますhttp://sourceforge.net/projects/libusbdroid/。どうすればsispmctlをリンクしてインストールできますか? – highsciguy

答えて

23

Libusbは、ルート以外のアンドロイドで動作することができます(デバイスがUSBホストをサポートしている場合...すべてのデバイスがそうであるとは限りません)。標準のAndroid USBスタックを使用する必要があります。その後、USBDeviceからデバイスディスクリプタを取得し、それをlibusbに渡すことができます。

残念ながら、libusbも変更する必要があります。幸いなことに、LibUSBの変更方法を他の人が説明しました。

LibUSBがhereに変更されました。

幸運を祈る!

編集

まず、放送受信機を定義する必要があります。

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) 
        { 
         UsbDeviceConnection deviceConnection = mUsbManager.openDevice(device); 
         Log.d("USB", deviceConnection.getSerial()); 
        } 
       } 
       else 
       { 
        Log.d("USB", "permission denied for device " + device); 
       } 
      } 
     } 
    } 
} 

今、あなたはUSBManagerを作成し、デバイス列挙する必要があります。

mUsbManager   = (UsbManager) getSystemService(Context.USB_SERVICE); 
    HashMap< String, UsbDevice > stringDeviceMap =  mUsbManager.getDeviceList(); 
    Collection<UsbDevice> usbDevices    = stringDeviceMap.values(); 

    mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); 
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); 
    registerReceiver(mUsbReceiver, filter); 

    Iterator<UsbDevice> usbDeviceIter    = usbDevices.iterator(); 
    while(usbDeviceIter.hasNext()) 
    { 
     if (USBDeviceValid(usbDevice)) 
     { 
      // Request permission to access the device. 
      mUsbManager.requestPermission(usbDevice, mPermissionIntent); 

      // Open the device. 
      UsbDeviceConnection connection = mUsbManager.openDevice(usbDevice); 
      int fd = connection.getFileDescriptor(); 

      // Now pass the file descriptor to libusb through a native call. 
     } 
    } 

編集2:あなたを

include $(CLEAR_VARS) 
LOCAL_MODULE := libusb 
LOCAL_SRC_FILES := libusb/core.c libusb/descriptor.c libusb/io.c libusb/sync.c libusb/os/linux_usbfs.c 

LOCAL_LDLIBS := -llog 
include $(BUILD_SHARED_LIBRARY) 
+0

どこかで、デバイス記述子。 – highsciguy

+0

@highsciguy:投稿が編集されました。 – Goz

+0

@highsciguy:これが役に立ちましたか? – Goz

1

コンパイルされても、デバイスがルートされていない限り、Androidはおそらくlibusbを通じてUSBデバイスにアクセスすることはできません。アプリをAndroid's native USB stackに移植することが可能な場合は、これがほぼ確実により安定したソリューションになります。

+1

デバイスがルートされています。これは、最新のファームウェアを搭載した他のRikomagic III HDMIスティックにも当てはまります。これがlibusbを使用しない唯一の理由なら、私はそれを試してみましょう。しかし、あなたがそれについて何か知っていれば、AndroidのUSBスタックとlibusbがどれほど似ているか知ることも面白いだろう。また、Cでそれを使うにはどうすればいいのだろうか。 – highsciguy

1

構築するためのlibusbを取得するには、(私はJNI /のlibusbに入れて)どこかに便利なファイルを入れた後、以下のあなたのAndroid.mkに行を追加するだけですまた、使用しようとすることができますandroid serial port api

ここはシリアルポートのinitの例です。

private FileDescriptor mFd; 
private FileInputStream mFileInputStream; 
private FileOutputStream mFileOutputStream; 

public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException { 

    /* Check access permission */ 
    if (!device.canRead() || !device.canWrite()) { 
     try { 
      /* Missing read/write permission, trying to chmod the file */ 
      Process su; 
      su = Runtime.getRuntime().exec("/system/bin/su"); 
      String cmd = "chmod 666 " + device.getAbsolutePath() + "\n" 
        + "exit\n"; 
      su.getOutputStream().write(cmd.getBytes()); 
      if ((su.waitFor() != 0) || !device.canRead() 
        || !device.canWrite()) { 
       throw new SecurityException(); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
      throw new SecurityException(); 
     } 
    } 

    mFd = open("/dev/ttyACM0", 9600, 0); 
    if (mFd == null) { 
     Log.e(TAG, "native open returns null"); 
     throw new IOException(); 
    } 
    mFileInputStream = new FileInputStream(mFd); 
    mFileOutputStream = new FileOutputStream(mFd); 
} 

USBホストのデバイスを使用したので、それを行いました。

4

私が実装した解決策は、Java APIを使用してUSBデバイスを開き、libusbでファイル記述子を使用することです。メインスレッド上で実行されていない(JAVAコードでデバイスを開く

int LibUsbAndroid::android_open(libusb_device *device, libusb_device_handle **devHandle) 
{ 
    int fd = USBJNICallbacks::getCallback()->getDeviceFd(device->bus_number, device->device_address); 

    __android_log_print(ANDROID_LOG_VERBOSE,"USB","Got FD:%d",fd); 
    if(fd==-1) 
    { 
     __android_log_print(ANDROID_LOG_ERROR,"USB","android_open, bad fd"); 
     return -1; 
    } 

    return libusb_open(device, devHandle, fd); 
} 

(SWIGを使用して)デバイスを開く:私はプライムセンス(https://github.com/OpenNI/OpenNI2)によってopenniプロジェクトから

コードビットをのlibusbを使用しました! ):

public int getDeviceFd(int busNumber, int deviceAddress) { 
     UsbDevice device = findDevice(busNumber, deviceAddress); 

     if(device!=null) 
     { 
      mReceivedPermission = false; 
      PermissionRequester pr = new PermissionRequester(device); 
      pr.run(); 

      if(!mUsbManager.hasPermission(device)) 
      { 
       Log.v("USB", "Requesting permissiom to device"); 
       mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0); 
       IntentFilter filterPermission = new IntentFilter(ACTION_USB_PERMISSION); 
       mContext.registerReceiver(mUsbPermissionReceiver, filterPermission); 
       mUsbManager.requestPermission(device, mPermissionIntent); 
      } 
      else 
      { 
       Log.v("USB", "Already has permission"); 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 

       mReceivedPermission = true; 

       Log.v("USB", "Opening device"); 
       OpenDevice od = openDevice(device); 
       Log.v("USB", "Adding to open devices"); 
       mOpenDevices.put(""+busNumber+"/"+deviceAddress, od); 


      } 

      Log.v("USB", "Waiting for permission"); 
      waitForPermissionResult(); 
      OpenDevice od = mOpenDevices.get(""+busNumber+"/"+deviceAddress); 
      if(od!=null) 
      { 
       Log.v("USB", "Getting FD"); 
       int result = od.mConnection.getFileDescriptor(); 

       Log.i("USB","USB File desc:"+result); 
       return result; 
      } 
      else 
      { 
       Log.v("USB", "Error getting FD"); 
       return -1; 
      } 
     } 

     return -1; 
    } 

許可処理コード:

プライベートブロードキャスト受信者mUsbPermissionReceiver = newブロードキャスト受信者(){

@Override 
public void onReceive(Context context, Intent intent) { 

    Log.v("USB", "Received permission result"); 
    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)) { 
       Log.v("USB", "Received permission result OK"); 
       if(device != null){ 
        Log.v("USB", "Device OK"); 
        mContext.unregisterReceiver(this);  
        Log.v("USB", "Openning device"); 
        OpenDevice od = openDevice(device); 
        Log.v("USB", "Adding to open device list"); 
        mOpenDevices.put(""+od.mBus+"/"+od.mAddress,od); 

        Log.v("USB", "Received permission is true"); 
        mReceivedPermission = true; 
       } 
       else { 
        Log.d(TAG, "permission denied for device " + device); 
       } 
      } 
     } 
    } 
} 

};

オープン機能:

public OpenDevice openDevice(UsbDevice device) { 
     UsbDeviceConnection connection = mUsbManager.openDevice(device); 

     Log.i("USB","Device name="+device.getDeviceName()); 

     int bus = getBusNumber(device.getDeviceName()); 
     int address = getAddress(device.getDeviceName()); 

     return new OpenDevice(device, connection, bus, address); 

    } 

USB libに変更(core.c):

int API_EXPORTED libusb_open(libusb_device *dev, 
    libusb_device_handle **handle, int fd) 
{ 
    struct libusb_context *ctx = DEVICE_CTX(dev); 
    struct libusb_device_handle *_handle; 
    size_t priv_size = usbi_backend->device_handle_priv_size; 
    int r; 
    usbi_dbg("open %d.%d", dev->bus_number, dev->device_address); 

    _handle = malloc(sizeof(*_handle) + priv_size); 
    if (!_handle) 
     return LIBUSB_ERROR_NO_MEM; 

    r = usbi_mutex_init(&_handle->lock, NULL); 
    if (r) { 
     free(_handle); 
     return LIBUSB_ERROR_OTHER; 
    } 

    _handle->dev = libusb_ref_device(dev); 
    _handle->claimed_interfaces = 0; 
    memset(&_handle->os_priv, 0, priv_size); 

    r = usbi_backend->open(_handle,fd); 
    if (r < 0) { 
     usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r); 
     libusb_unref_device(dev); 
     usbi_mutex_destroy(&_handle->lock); 
     free(_handle); 
     return r; 
    } 

    usbi_mutex_lock(&ctx->open_devs_lock); 
    list_add(&_handle->list, &ctx->open_devs); 
    usbi_mutex_unlock(&ctx->open_devs_lock); 
    *handle = _handle; 
    /* At this point, we want to interrupt any existing event handlers so 
    * that they realise the addition of the new device's poll fd. One 
    * example when this is desirable is if the user is running a separate 
    * dedicated libusb events handling thread, which is running with a long 
    * or infinite timeout. We want to interrupt that iteration of the loop, 
    * so that it picks up the new fd, and then continues. */ 
    usbi_fd_notification(ctx); 

    return 0; 
} 

op_open(libusb_fs.c)変更:

static int op_open(struct libusb_device_handle *handle, int fd) 
{ 
    struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); 
    char filename[PATH_MAX]; 

    _get_usbfs_path(handle->dev, filename); 
    usbi_dbg("opening %s", filename); 

    hpriv->fd = fd; 

    if (hpriv->fd < 0) { 
     if (errno == EACCES) { 
      usbi_err(HANDLE_CTX(handle), "libusb couldn't open USB device %s: " 
       "Permission denied.", filename); 
      usbi_err(HANDLE_CTX(handle), 
       "libusb requires write access to USB device nodes."); 
      return LIBUSB_ERROR_ACCESS; 
     } else if (errno == ENOENT) { 
      usbi_err(HANDLE_CTX(handle), "libusb couldn't open USB device %s: " 
       "No such file or directory.", filename); 
      return LIBUSB_ERROR_NO_DEVICE; 
     } else { 
      usbi_err(HANDLE_CTX(handle), 
       "open failed, code %d errno %d", hpriv->fd, errno); 
      return LIBUSB_ERROR_IO; 
     } 
    } 

    return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT); 
} 
+0

ありがとう、これはかなり役に立ちます。 libusb_open()の呼び出しに必要なlibusb_device *の作成方法を共有することはできますか? – rsp1984

関連する問題