0

我正在尝试使 android 平板电脑与 USB 设备(STM32 Nucleo)进行通信。我在github上开发了一个草图:

  • 该移动应用程序是使用 Xamarin 和 VS Studio 开发的。它充当 USB 主机
  • STM32 Nucleo 应用程序是使用 STMCube 开发的,并使用它的 USB 堆栈作为 CDC 设备。
  • 我开发了一个小型主/从协议来交换“注册”ID/值。该设备是从站。

我设法使用 Android.hardware.usb API 使其工作。但是我必须使用本机 C 共享对象库进行通信,就像它在其他平台上使用的那样,这就是我现在遇到问题的地方。我使用 swig 嵌入了库并使用 VS Studio 构建它。我尝试了两种使库与设备通信的方法:

  • 从 Android 端获取权限和 fd 并将其传递给执行标准读/写操作的库。
  • 从 Android 执行与上述相同的操作,但也使用 fd 传递使用 linux usbdevice_fs API 调用批量传输的端点编号;更像是在那个问题上提出的。

两种方法都失败并返回有关不存在的 fd 的错误。我检查了 fd 和 enpoints 值,它们与 Android 相同。我启动了android usb设备监视器,找不到创建的fd。我不能使用任何像 termux 这样的 android shell 来列出进程 /proc 树。但我仍然可以在 Android 端使用 tehm。

从社区我检查了将 fd 传递给本机库是正确的方法。我现在不知道该怎么办,请问还有更多权限吗?

下面是我如何检索 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);
                }
                else
                {
                    Log.Debug("pandavcom", "FAILED : open device endpoint" + _devHandle.usbdev.DeviceName);
                }
            }

捕获未能使用本机库的移动应用程序

4

1 回答 1

0

所以我让它工作了,感谢 libusb 邮件列表的人。实际上,疯狂的电阻 libusb 只能向设备发送数据。现在使用官方 libusb 有一种方法可以做到这一点,这仍然是最近的。

所以过程是:

  • 使用 android 获取设备权限和文件描述符

  • 将文件描述符传递给您的本机代码并执行此步骤以在 fd 上初始化 libusb:

     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 = Android.USBManager 中的 FileDescriptor)

上面的代码是通过邮件发送的。我的 github 项目中提供了一个集成示例。我仍在更多 Android 平板电脑上验证此解决方案。

于 2020-12-17T22:21:06.403 回答