С общими принципами организации работы с USB можно познакомиться в работах Павла Агурова, а здесь будет рассмотрена только одна простая схема, комментирующая принцип работы с любым USB-устройством. В простейшем виде USB-устройство можно представить как некую древовидную структуру, включающую в себя «Конфигурации» (configurations), «Интерфейсы» (interfaces) и «Конечные точки» (endpoints).

Логическая схема USB-устройства

«Конечная точка» устройства — это программная сущность, у которой есть свой уникальный идентификатор и которая может иметь буфер с некоторым числом байтов для приема-передачи информации. Но чтобы добраться до нее, приложению (под управлением хоста) нужно программным путем пройти через уровни «Устройства», «Конфигурации» и «Интерфейса». Каждый из них описывается стандартной программной структурой, и есть возможность выбирать, какие именно интерфейсы следует использовать, чтобы попасть в требуемую конечную точку.

Важная особенность USB — наличие только одного Мастера (ведущего), которым обычно является компьютер. Само USB-устройство всегда отвечает на разные запросы компьютера, о чем бы ни шла речь и в какую бы сторону ни передавалась информация.

Разработчик может написать полноценный драйвер для работы со своим USB-устройством, применяя уже имеющийся в системе заголовочный файл linux/usb.h.

 Фрагмент результата работы программы

Дело в том, что большинство низкоуровневых задач в Linux уже решены, и любая написанная программа будет иметь прикладной характер, хотя формально и получит название драйвера. Справедливо также заметить, что с каждой новой версией ядра Linux работа с USB становится проще.

Драйвер, написанный для поддержки USB-устройства, призван решать следующие задачи:

  • регистрация и удаление драйвера;
  • регистрация и удаление устройства;
  • обмен данными с устройством.

Но можно точно назвать один важный и естественный недостаток, который несет в себе программный модуль уровня драйвера, — платформенная непереносимость.

А как быть, если нет времени писать драйвер, но надо срочно создать программу, работающую с USB-устройством, которая сама будет решать, как, когда и с каким из таких устройств ей работать? Да к тому же хотелось бы, чтобы она легко переносилась на другие платформы (Windows, Mac OS и т.д.) хотя бы с минимальными изменениями в тексте или вовсе без них.

Пример запуска команды lusb

При этом ее требуется писать на Паскале или даже на С#. Возможно ли это? Вполне. Но для этого необходима библиотека libusb (http://www.libusb.org/). Если в дистрибутиве Linux нет такого «зверя» (ничего не отображается в ответ на команду locate libusb.so), то существует несколько путей:

  1. поставить этот пакет с помощью штатного инсталлятора, к примеру, для Fedora написать в консоли: yum install libusb;
  2. самостоятельно скачать RPM-пакет (http://sourceforge.net/projects/libusb/) и попробовать его установить;
  3. скачать пакет «исходников» (http://sourceforge.net/projects/libusb/files/) и собрать на своей машине библиотеку.

Важное замечание. На сайте libusb.org выложены две ветки проекта — версии 1.0 и 0.1. В статье описана работа со старой стабильной версией, по этому будьте внимательны: при использовании версии 1.0, есть расхождения в API.

Программа, созданная в Lazarus, использует библиотеку libusb

Чтобы понять, имеются ли в системе устройства, соответствующие USB-интерфейсу, можно, например, воспользоваться утилитой usbview (http://usbview.sourceforge.net) либо ее продвинутым аналогом — usbview2 (http://usbview2.sourceforge.net/), хотя в любом современном Linux найдутся встроенные консольные команды для таких целей.

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

А за основу мы возьмем простую программу вот отсюда — http://www.linuxquestions.org/linux/answers/Programming/Developing_Linux_Device_Drivers_using_Libusb_API. Внесем в нее русские комментарии и откомпилируем в режиме программы С++. При этом в настройках компилятора укажем на использование библиотеки libusb.so (листинг 1).

Как видно, этот пример полностью соответствует описанной ранее логической схеме — мы начинаем работу с общего перебора устройств и заканчиваем конкретными логическими точками. В данном примере идет простой перебор всего, что содержится в системе и что имеет отношение к USB. Но так делать необязательно. Для работы с конкретным устройством нас может интересовать определенный код изготовителя продукта (idVendor) и код продукта (idProduct). Если в этом примере уже указанный заголовочный usb.h заменить на , то это будет уже совсем другая библиотека, которую используют для создания полноценных (непереносимых на другие типы систем) драйверов в среде Linux.

Аналогичный пример нетрудно найти в Сети для языка Free Pascal, а значит, несложно написать собственную графическую утилиту, аналогичную usbview, и в среде Lazarus (http://www.lazarus.freepascal.org/).

Для этого потребуется скачать файл libusb.pp (например, здесь http://www.sciencetronics.com/download/fpc_libusb.tgz).

Фрагмент программы, написанной в Lazarus для чтения списка устройств USB (листинг 2) представлен на стр. 58.

Итак, мы выяснили, что в нашем распоряжении языки Си, C++ и Паскаль.  Но это не предел, рассмотрим простой пример на языке С# (листинг 3).

В данном примере (который успешно запускается в среде Linux с помощью платформы Mono) для доступа к библиотеке libusb.so применяется специальная .NET-обертка под названием #USBlib. Разработчики утверждают, что она одинаково подходит как для libusb.so, так и для своего собрата, функционирующего под управлением Windows (http://libusb-win32.sourceforge.net/). Кстати, важно отметить, что наборы функций libusb-win32 и libusb совпадают, а особые платформенные различия указаны в документации. Это и есть основное достоинство библиотеки libusb — блестящая платформенная переносимость исходного кода.

В заключение стоит напомнить, что та конкретная задача, над которой мы трудились, используя разные языки и инструментарии, — вывод списка устройств USB, решается в Linux с помощью встроенных команд


Разработчики утверждают, что #USBlib одинаково подходит как для libusb.so, так и для своего собрата, функционирующего под управлением Windows (http://libusb-win32.sourceforge.net/). Кстати, важно отметить, что наборы функций libusb-win32 и libusb совпадают, а особые платформенные различия указаны в документации.


Листинг 1

Листинг 1 (продолжение)

Листинг 2

Листинг 3

Утилита usbview2