带有本机库的 Android - 连接 CDC USB 设备 - 无法在本机库中使用 fd [英] Android with native library - interface a CDC usb device - can't use fd in native library

查看:40
本文介绍了带有本机库的 Android - 连接 CDC USB 设备 - 无法在本机库中使用 fd的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让 Android 平板电脑与 USB 设备(STM32 Nucleo)进行通信.我在

解决方案

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

所以过程是:

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

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

     libusb_context *ctx;枚举 libusb_error rc;rc = libusb_set_option(&ctx, LIBUSB_OPTION_WEAK_AUTHORITY, NULL);如果(rc != LIBUSB_SUCCESS){__android_log_print(ANDROID_LOG_ERROR, TAG,"libusb_init failed: %d\n", ret);返回-1;}ret = libusb_init(&ctx);如果 (ret <0) {__android_log_print(ANDROID_LOG_INFO,标签,libusb_init 失败:%d\n",ret);返回 1;}libusb_device_handle *devh = NULL;ret = libusb_wrap_sys_device(NULL, (intptr_t)FD, &devh);如果 (ret <0) {__android_log_print(ANDROID_LOG_INFO,标签,libusb_wrap_sys_device 失败:%d\n",ret);返回2;}否则如果(devh == NULL){__android_log_print(ANDROID_LOG_INFO,标签,"libusb_wrap_sys_device 返回无效句柄\n");返回3;}

    (FD = FileDescriptor from Android.USBManager)

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

I'am trying to make a android tablet communicate with a USB device (STM32 Nucleo). I developped a sketch available on 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.

I managed to make it work using the Android.hardware.usb API. But I must use a native C shared object library for communication as it used on other platform, and that's where I am having trouble now. I embbeded the library using swig and build it with VS Studio. I tried two ways to make the library communicate with the device :

  • 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.

Both methods fail and returns an error about the fd that does not exist. I checked the fd and and enpoints values, they're same as the Android. I launched the android usb device monitor, I can't find the created fd. I can't use any android shell like termux to list the process /proc tree. But still I can use tehm in the Android side.

From the community I checked that passing fd to the native library is the right method. I don't know what to do now, is there some more permission to ask ?

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);
                }
                else
                {
                    Log.Debug("pandavcom", "FAILED : open device endpoint" + _devHandle.usbdev.DeviceName);
                }
            }

解决方案

So I made it working, thanks tho the guys of the libusb mailing list. Actually the mad resistor libusb could only send data to device. Now with the officiel libusb there's a way to do it, that is still recent.

So the process is :

  • get with android the device permission and the file descriptor

  • pass the file descriptor to your native code and execute this step to 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)

The code above was sent over the mailing. An example of integration is available on my github project. I'm still validating this solution on more Android tablet.

这篇关于带有本机库的 Android - 连接 CDC USB 设备 - 无法在本机库中使用 fd的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆