带有本地库的安卓系统--接口是CDC的USB设备--不能在本地库中使用fd

0 人关注

我试图让一个安卓平板电脑与一个USB设备(STM32 Nucleo)进行通信。 我开发了一个草图,可在 github :

  • the mobile application is developped with Xamarin and VS Studio. It acts as usb host
  • the STM32 Nucleo application is developped with STMCube and uses it's USB stack to act as a CDC device.
  • I developped a small master/slave protocol to echange "register" id/value. The device is the slave.
  • 我设法使用Android.hardware.usb API使其工作。 但我必须使用本地C共享对象库进行通信,因为它在其他平台上使用,这就是 我现在有麻烦了 . 我使用swig嵌入了这个库,并使用VS Studio构建它。 我尝试了两种方法来使库与设备进行通信。

  • From the Android side get permission and fd and pass it to the library that does standard read/write opérations.
  • From the Android do the same as above, but also pass with fd the endpoints numbers that uses the linux usbdevice_fs API to call bulk transfers; more o less like presented at that question .
  • 这两个方法都失败了,并返回一个关于不存在的fd的错误。我检查了fd和enpoints的值,它们和安卓系统是一样的。 我启动了安卓的usb设备监视器,我找不到创建的fd。我无法使用任何安卓的shell,比如termux来列出进程/proc树。 但我仍然可以在安卓系统中使用它们。

    我从社区里查到,把fd传给本地库是正确的方法。 我不知道现在该怎么做,是否有更多的权限可以请求?

    Below is how I retrieve the fd :

                   _devHandle.usbdev = _devHandle.usbManager.DeviceList[name];
                // Ask for permission to access the created device
                if (!_devHandle.usbManager.HasPermission(_devHandle.usbdev))
                    PendingIntent pi = PendingIntent.GetBroadcast((ContextWrapper)_context, 0, new Intent(ACTION_USB_PERMISSION), 0);
                    _devHandle.usbManager.RequestPermission(_devHandle.usbdev, pi);
                    /* We check the permission was given
                    if (!_devHandle.usbManager.HasPermission(_devHandle.usbdev))
                        // Loose !
                        Log.Debug("pandavcom", "FAILED : did not have persmission to open device" + _devHandle.usbdev.DeviceName);
                        return;
                // Now open the port, with  the USB Manager : we get the fd/enpoints and pass it to library, no more
                _devHandle.connection = _devHandle.usbManager.OpenDevice(_devHandle.usbdev);
                if (_devHandle.connection != null)
                    if (OpenInterface(_devHandle.usbdev, _devHandle.connection, ref _devHandle.usbIface, ref _devHandle.ep_in, ref _devHandle.ep_out) == 0)
                        _devHandle.fd = _devHandle.connection.FileDescriptor;
                        Log.Debug("pandavcom", "opened device endpoint" + _devHandle.usbdev.DeviceName + "with descriptor: " + _devHandle.fd);
                        Log.Debug("pandavcom", "FAILED : open device endpoint" + _devHandle.usbdev.DeviceName);
        
    2 个评论
    刚发现有人改编了libusb,从filedescriptor中获得一个句柄,我会试试的。 stackoverrun.com/fr/q/1907272
    所以我用这个修改过的libusb(由madresistor提供)成功地将数据发送到了设备上,但是所有的批量读取都以超时而失败。相比之下,安卓系统的调用却没有失败。我想我会克服这个问题的。我在别的地方读到,你可以让libusb工作,但你必须root设备并给dev/usb文件以权限。这并不是一个可靠的解决方案。
    android
    xamarin.android
    usb
    cdc
    android-native-library
    Selso Liberado
    Selso Liberado
    发布于 2020-12-10
    1 个回答
    Selso Liberado
    Selso Liberado
    发布于 2020-12-18
    已采纳
    0 人赞同

    所以我把它弄好了,感谢libusb邮件列表中的那些人。 事实上,疯狂电阻libusb只能向设备发送数据。 现在有了正式的libusb,就有了一种方法,这还是最近的。

    So the process is :

  • 用安卓系统获取设备权限和文件描述符

  • 将文件描述符传递给你的本地代码,并执行这一步以 initliaze libusb on the fd :

     libusb_context *ctx;
     enum libusb_error rc;
     rc = libusb_set_option(&ctx, LIBUSB_OPTION_WEAK_AUTHORITY, NULL);
     if (rc != LIBUSB_SUCCESS) {
         __android_log_print(ANDROID_LOG_ERROR, TAG,"libusb_init failed: %d\n", ret);
         return -1;
     ret = libusb_init(&ctx);
     if (ret < 0) {
         __android_log_print(ANDROID_LOG_INFO, TAG,
                             "libusb_init failed: %d\n", ret);
         return 1;
     libusb_device_handle *devh = NULL;
     ret = libusb_wrap_sys_device(NULL, (intptr_t)FD, &devh);
     if (ret < 0) {
         __android_log_print(ANDROID_LOG_INFO, TAG,
                             "libusb_wrap_sys_device failed: %d\n", ret);
         return 2;
     else if (devh == NULL) {
         __android_log_print(ANDROID_LOG_INFO, TAG,
                             "libusb_wrap_sys_device returned invalid handle\n");
         return 3;
    

    (FD = FileDescriptor from Android.USBManager)

  •