Обмениваемся данными с USB девайсом при помощи libusb

LibUsb — библиотека для языка C, которая позволяет обмениваться данными с устройствами по протоколу usb.

У меня есть устройсво на базе STM32F407VGT6 микроконтроллера.
Давайте рассмотрим механизм посылки и принятия данных.

Прежде всего стоит отметить, что данные можно слать разными способами. Мы рассмотрим асинхронную передачу прерывания ( interrapt transfer )
Этот тип передачи позволяет передавать небольшие объёмы данных без получения подтверждения о получении. Тобеш послали и забыли))

При работе с libusb следует помнить, что его нужно инициализировать:

    libusb_init(NULL);   // инициализация
    libusb_set_debug(NULL, USB_DEBUG_LEVEL);  // уровень вывода отладочных сообщений

Теперь получим handle устройства:

libusb_device_handle *handle = libusb_open_device_with_vid_pid(NULL, VID, PID);

Я считаю, что вы знаете Vendor ID и Product ID вашего устройства. Эти данные редко меняются, поэтому я задал их define`ом.

Если устройство не обнаружено handle = NULL :

    if (handle == NULL) { 
        printf("Устройство не подключено\n"); 
    }

Кроме того, если система уже захватила контроль над устройством его нужно у неё забрать! Ато малоли чего она туда нашлёт…

    if (libusb_kernel_driver_active(handle,DEV_INTF)) 
        libusb_detach_kernel_driver(handle, DEV_INTF);

DEV_INTF — интерфейс устройства. Он тоже статичен, а указывать нужно из-за того, что он может быть не один.
Такие параметры удобно узнавать при помощи команды

lsusb -v -d VID:PID

Теперь захватываем интерфейс:

    if (libusb_claim_interface(handle,  DEV_INTF) < 0){ 
        printf("Ошибка интерфейса\n"); 
    }

Теперь можно читать данные. У меня «реализация usb мышки» такчто читаем по 4 байта:

        int returned = libusb_interrupt_transfer(handle, EP_IN, buf, DATA_SIZE, &ret, 1000);
        if (returned >= 0) {
            cout << "buf[0] = " << (int)buf[0] << endl;
            cout << "buf[1] = " << (int)buf[1] << endl;
            cout << "buf[2] = " << (int)buf[2] << endl;
            cout << "buf[3] = " << (int)buf[3] << endl;
        }

Всё это можно делать в бесконечном цикле. Для наглядности.
В первой строке мы читаем данные в буфер buf из устройства handle, через точку EP_IN (для мыши это 0x81).
Читаем DATA_SIZE байт. Причём int ret получит число реально считанных байт. А ждать данные мы будем не больше 1000мс.
Буфер я объявлял так:

    unsigned char buf[DATA_SIZE];

Самое забавное, что для посылки данные делается всё точно также, за исключением выбора конечной точки EP_OUT (у мыши 0x01 но смысла туда чтот слать я не вижу). Ну и конечно буфер перед этим нужно заполнить.

Для компиляции в linux нужно прилинковать библиотеку usb-1.0.

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий

  1. lamazavr

    забыл. В конце отдаём девайс системе и вырубаем libusb:
        libusb_attach_kernel_driver(handle, DEV_INTF);

        libusb_close(handle);

        libusb_exit(NULL);
     
     

    Ответить
  2. Иван

    Можно посмотреть полный код программы?

    У меня, как у новичка, возникает куча ошибок при компиляции.

    Ответить
  3. lamazavr

    Вот пример

    https://www.dropbox.com/s/mkuu2f3z5k4bapb/usb_testing.cpp?dl=0

    Ответить
  4. Алиса

    DEV_INTF — интерфейс устройства. Как его определить?

    при выполнении lsusb -v -d VID:PID, среди прочего всякого есть такие строки:

    Interface Descriptor:

    bLength 9

    bDescriptorType 4

    bInterfaceNumber 0

    bAlternateSetting 0

    bNumEndpoints 2

    bInterfaceClass 255 Vendor Specific Class

    bInterfaceSubClass 0

    bInterfaceProtocol 0

    iInterface 2
    я верно понял, что iInterface это и есть DEV_INTF?

    Ответить
  5. Влад

    А если нужно это же скомпилировать на винде? это вообще реально?? а то у меня пишет что нет половины функции

    Ответить
  6. lamazavr

    Да, нужно добавить к проекту dll.

    Вот только когда то я пробовал добавить libusb к проекту Qt и она у меня отказалась работать. Точно уже не помню в чем дело.

    Ответить
  7. КрекерССолью

    Печальный код, платформо зависеммые функции даже в ifdef не обернуты

    Ответить