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

Опубликовано lamazavr - чт, 11/22/2012 - 14:10
Body

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.

Комментарии

забыл. В конце отдаём девайс системе и вырубаем libusb:

    libusb_attach_kernel_driver(handle, DEV_INTF);
    libusb_close(handle);
    libusb_exit(NULL);

 

 

Можно посмотреть полный код программы?
У меня, как у новичка, возникает куча ошибок при компиляции.

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?

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

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

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

Добавить комментарий

Этот вопрос задается для того, чтобы выяснить, являетесь ли Вы человеком или представляете из себя автоматическую спам-рассылку.