Измените libusb, чтобы он принимал файловый дескриптор

Я изменил функцию открытия libusb1.0 следующим образом:

static int op_open2(struct libusb_device_handle *handle, int fd) {
    struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);

    hpriv->fd = fd;

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

где fd был получен через android.hardware.usb. UsbDeviceConnection.html#getFileDescriptor()

final UsbDeviceConnection connection = manager.openDevice(device); 
return connection.getFileDescriptor();

К сожалению, я продолжаю получать сообщение об ошибке, когда я звоню

static int op_claim_interface(struct libusb_device_handle *handle, int iface)
{
    int fd = _device_handle_priv(handle)->fd;

    int r = ioctl(fd, IOCTL_USBFS_CLAIMINTF, &iface);

    if (r) {
        if (errno == ENOENT)
            return LIBUSB_ERROR_NOT_FOUND;
        else if (errno == EBUSY)
            return LIBUSB_ERROR_BUSY;
        else if (errno == ENODEV)
            return LIBUSB_ERROR_NO_DEVICE;

        usbi_err(HANDLE_CTX(handle),
            "claim interface failed, error %d errno %d", r, errno);
        return LIBUSB_ERROR_OTHER;
    }
    return 0;
}

Ошибка интерфейса запроса, ошибка -1 errno 9

что переводится как «Неверный номер файла». Дескриптор файла, который я получаю от Java, является положительным целым числом!

Единственная другая небольшая деталь заключается в том, что мой собственный код работает как отдельный двоичный файл, который создается с помощью Java ProcessBuilder. Но у них один и тот же uid, поэтому я предполагаю, что разрешения USB, которые у меня есть от Java, должны по-прежнему применяться для libusb.

Мне не нужно быть независимым от платформы, поэтому любые хаки сделают эту работу :)

Любые мысли будут высоко оценены!

Дополнительная информация! Вывод, который я получаю от lsof (сокращенный, чтобы подчеркнуть наиболее интересную его часть)

my.activity 13374     u0_a62  exe       ???                ???       ???        ??? /system/bin/app_process
my.activity 13374     u0_a62    0       ???                ???       ???        ??? /dev/null
my.activity 13374     u0_a62    1       ???                ???       ???        ??? /dev/null
my.activity 13374     u0_a62    2       ???                ???       ???        ??? /dev/null
my.activity 13374     u0_a62    3       ???                ???       ???        ??? /dev/log/main
my.activity 13374     u0_a62    4       ???                ???       ???        ??? /dev/log/radio
my.activity 13374     u0_a62    5       ???                ???       ???        ??? /dev/log/events
my.activity 13374     u0_a62    6       ???                ???       ???        ??? /dev/log/system
my.activity 13374     u0_a62    7       ???                ???       ???        ??? /system/framework/core.jar
my.activity 13374     u0_a62    8       ???                ???       ???        ??? /system/framework/core-junit.jar
my.activity 13374     u0_a62    9       ???                ???       ???        ??? /dev/__properties__ (deleted)
...
my.activity 13374     u0_a62   44       ???                ???       ???        ??? /dev/bus/usb/002/002
...    
my.activity 13374     u0_a62   51       ???                ???       ???        ??? pipe:[51015]
my.activity 13374     u0_a62   53       ???                ???       ???        ??? pipe:[51016]
...

my_exe   13546     u0_a62  exe       ???                ???       ???        ??? /data/data/my.activity/files/my_exe
my_exe   13546     u0_a62    0       ???                ???       ???        ??? pipe:[51015]
my_exe   13546     u0_a62    1       ???                ???       ???        ??? pipe:[51016]
my_exe   13546     u0_a62    2       ???                ???       ???        ??? pipe:[51016]
my_exe   13546     u0_a62    3       ???                ???       ???        ??? /dev/log/main
my_exe   13546     u0_a62    4       ???                ???       ???        ??? /dev/log/radio
my_exe   13546     u0_a62    5       ???                ???       ???        ??? /dev/log/events
my_exe   13546     u0_a62    6       ???                ???       ???        ??? /dev/log/system
my_exe   13546     u0_a62    9       ???                ???       ???        ??? /dev/__properties__ (deleted)
my_exe   13546     u0_a62  mem       ???              b3:09         0     302530 /data/data/my.activity/files/my_exe
my_exe   13546     u0_a62  mem       ???              b3:09     36864     302530 /data/data/my.activity/files/my_exe
my_exe   13546     u0_a62  mem       ???              b3:09     40960     302530 /data/data/my.activity/files/my_exe
my_exe   13546     u0_a62  mem       ???              b3:03         0        200 /system/bin/linker
my_exe   13546     u0_a62  mem       ???              b3:03     57344        200 /system/bin/linker
my_exe   13546     u0_a62  mem       ???              b3:03     61440        200 /system/bin/linker

Что заставляет меня думать, что файловый дескриптор 44, который я передаю в my_exe, на самом деле не унаследован!


person Martin Marinov    schedule 04.01.2013    source источник


Ответы (2)


Оказалось, что файловый дескриптор не был унаследован процессом. Если кто-то использует JNI, все должно быть в порядке, но если вы хотите взаимодействовать со сторонним приложением, вам нужно будет передать дескриптор файла стороннему приложению.

Мое решение состояло в том, чтобы использовать сокеты UNIX для передачи fd через JNI, и это сработало!

P.S.

Я выпустил проект под лицензией GNU - https://github.com/martinmarinov/rtl_tcp_andro-

person Martin Marinov    schedule 04.01.2013
comment
я использую сокеты UNIX для передачи дескриптора файла, но, к сожалению, я все время получаю LIBUSB_ERROR_BUSY. fd положителен, так что все в порядке. в приложении для Android я просто открываю устройство и не претендую на интерфейс. я обязательно открою нужное устройство, когда буду искать его с помощью pid/vid. что случилось? - person 4ntoine; 30.07.2013

Дескрипторы файлов являются частными для процесса. Передача их другому процессу «как есть» гарантированно не будет работать ни с одной версией *nix.

Интерфейс Android Binder/Parcel IPC может маршалировать файловые дескрипторы.

Или вы можете унаследовать дескриптор — если он уже открыт при порождении процесса, дескриптор будет действительным и в порожденном процессе.

person Seva Alekseyev    schedule 04.01.2013
comment
Да, сначала получается обработчик, а потом запускается процесс. Могу ли я каким-либо образом сообщить системе, что она дает мне обработчик, который у меня уже есть для файла x, или дает мне список всех обработчиков, которые открыл мой процесс? - person Martin Marinov; 04.01.2013
comment
Я обнаружил lsof, см. мой обновленный вопрос для вывода из него - person Martin Marinov; 04.01.2013