Компиляция и ссылка на libusb для android

Я рассматриваю попытку скомпилировать определенную C-программу, которая позволяет управлять выходами питания Gembird SilverShield через USB для Android. На моем Android-TV с Android-телефоном это было бы очень полезно. Для этого есть открытый проект. Он работает под Linux и зависит от libusb. Целевая платформа – Android-андроид. Я хочу развиваться на Ubuntu Linux. Какие шансы у меня получается? Каковы требуемые шаги. Настройка Android SDK, NDK, кросс-компилятор …
Здесь есть более старый вопрос, связанный с libusb на android, но никакой информации как.
Может быть, проще переносить приложение в андроидную собственную библиотеку usb?

Libusb может работать на неруковом андроиде (при условии, что устройство поддерживает USB-хост … это ОЧЕНЬ важно, поскольку не все устройства). Вам нужно использовать стандартный стек USB для Android. Затем вы можете получить дескриптор устройства из USBDevice и передать его в libusb.

К сожалению, вам также необходимо изменить libusb. К счастью, другие люди объяснили, как вам нужно модифицировать LibUSB.

Здесь был изменен LibUSB.

Удачи!

Изменить :

Сначала вам нужно определить широковещательный приемник:

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 :

Получение libusb для сборки – это просто вопрос о том, чтобы файлы были удобными (я помещал их в jni / libusb), а затем добавлял следующие строки в ваш Android.mk:

 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) 

Решением, которое я реализовал, является открытие USB-устройства с использованием API-интерфейсов Java, а затем использование файлового дескриптора с libusb.I используется libusb из openni проекта primesense ( https://github.com/OpenNI/OpenNI2 )

Биты кода:

Открытие устройства (с помощью swig):

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

Открытие устройства в коде JAVA (не работает в основном потоке!):

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

Код обработки разрешения:

Частный BroadcastReceiver mUsbPermissionReceiver = новый BroadcastReceiver () {

 @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 change (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); } 

Даже если вы его скомпилируете, Android, вероятно, не позволит вам получить доступ к USB-устройству через libusb, если ваше устройство не внедрено. Если возможно переносить приложение на собственный USB-накопитель Android , это почти наверняка будет более стабильным решением.

Вы также можете попробовать использовать последовательный порт Android 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-хосте.