Пишем драйвер для USB девайса. Pipe 0: что такое usb?

    Случилось так, что пришлось мне писать с нуля драйвер для usb дисплея под windows. Имея возможность — расскажу о деталях столь занимательного процесса.
    image

    USB – это simple

    Несмотря на то, что написание драйверов считается достаточно трудным, в сравнении с прикладным программированием – и в этом низкоуровневом мире программисты не были обделены вниманием, большим шагом в упрощении создания драйверов стала разработка шины usb.
    Итак, почему же шина usb так удобна, и что скрывает за собой слово Universal в расшифровке аббревиатуры.

    Раньше, когда программист был вынужден писать драйвер для общения с устройством – он работал непосредственно на уровне шины, грубо говоря — если устройство подключалось 9-жильным проводом, т.к. две из них обычно отводятся под питание — то программист вручную был вынужден контролировать до 7 жил. У каждого устройства было своё представление, как использовать предоставленный ему порт. Например, одно устройство могло передавать данные на компьютер через 1,2 и 5 проводники, использовать 3 и 7 для управления, а 4 и 6 использовались бы для записи данных в устройство, другое устройство могло иметь 2 проводника для передачи данных в обе стороны и 5 для управляющих сигналов.

    Всё это необходимо было контролировать во времени, ожидая реакции или готовности устройства. Если же устройство выполняло более чем один вид деятельности – необходимо было знать с каким функционалом мы работаем в данный момент и, исходя из этого, изменять методы работы. В таких условиях отладка была тяжелой, и программисту нужно было учить свой протокол общения по этому порту для каждого устройства. Всё это не могло продолжаться бесконечно, и была изобретена шина usb.

    Структура шины

    Первое, что можно увидеть при работе с usb устройствами в современных ОС – вам больше не нужно работать физически с портом передачи данных. Итак – давайте посмотрим что же представляет из себя произвольное usb устройство в первом приближении:

    image
    На первой линии обороны нас ждёт уровень интерфейсов, это логическое разделение устройства по выполняемым им задачам, например, если у нас есть внешний дисплей, оборудованный в добавок системой звукового оповещения – наше устройство вполне может иметь пару интерфейсов, один для работы с дисплеем, другой для работы со звуком, и, например, третий – для перепрошивки самого устройства.
    Если мы будем рассматривать написание драйвера под windows с использованием последнего драйвер-фреймворка (WDF), то узнать количество интерфейсов и получить доступ к ним можно при помощи пары строк кода.
    Интерфейс – не единственный уровень разделения, существующий в USB, каждый интерфейс подразделяется на набор так называемых конечных(концевых) точек (endpoint).

    Предположим что мы можем как записывать картинку на дисплей – так и читать текущую картинку с дисплея, в таком случае одна концевая точка будет использоваться для чтения, другая – для записи. Помимо направления передачи данных (In/Out) концевая точка имеет ещё одно достаточно полезное свойство, это тип передачи, который имеет одно из следующих значений:

    • управляющие передачи – используются хостом для конфигурирования устройства во время подключения, для управления устройством и получения статусной информации в процессе работы. Протокол обеспечивает гарантированную доставку таких посылок;
    • передачи массивов данных (Bulk Data Transfers) – применяются при необходимости обеспечения гарантированной доставки данных от хоста к функции или от функции к хосту, но время доставки не ограничено;
    • передачи по прерываниям – используются в том случае, когда требуется передавать одиночные пакеты данных небольшого размера. Каждый пакет требуется передать за ограниченное время. Операции передачи носят спонтанный характер и должны обслуживаться не медленнее, чем того требует устройство;
    • изохронные передачи – применяются для обмена данными в «реальном времени», когда на каждом временном интервале требуется передавать строго определенное количество данных, но доставка информации не гарантирована (передача данных ведется без повторения при сбоях, допускается потеря пакетов).

    Помимо концевых точек, определяемых непосредственно логикой устройства, одна (нулевая) концевая точка определяется непосредственно протоколом, любое usb устройство обязано иметь нулевую концевую точку. Именно благодаря этому как только вы подключаете устройство к компьютеру – операционная система сразу распознаёт название этого устройства, и пытается найти к нему драйвер, без этой стандартной концевой точки получение информации об устройстве при отсутствии драйвера было бы невозможным.

    image

    Заключение

    Все данные передаются по двум проводникам внутри usb кабеля (ещё 2 отводятся под питание), это позволяет использовать единый разъём для всех usb устройств.
    Это – всё что необходимо знать о шине для того, чтобы написать свой первый драйвер, чем мы и займёмся в следующей статье.
    Комплект для разработки драйверов для операционных системы Windows XP, Vista, 7 – можно скачать по ссылке: комплект разработчика.

    В следующей части: обработка событий, связанных с устройством, работа с подсветкой из прикладного приложения, и немного реверс-инжиниринга.

    Фотография будущего пациента:
    image
    Поделиться публикацией

    Комментарии 44

      +10
      куча воды с продолжением во второй серии 8))

      ждём 8)
        +8
        «Куча воды» сломала мой мозг при попытке визуализировать.
          0
          Целый сиквел про USB :-0
        • НЛО прилетело и опубликовало эту надпись здесь
            0
            mono? )
            тут вроде дотнет начнется…

            А вообще интересно было бы почитать о разработке USB драйверов под Linux и MAC.
            • НЛО прилетело и опубликовало эту надпись здесь
                0
                Драйвер на C, .net только управляющая программка.
                • НЛО прилетело и опубликовало эту надпись здесь
                    –1
                    А зачем тогда вообще .NET?
                      0
                      На .net написана userspace управляющая программка.
                    0
                    > Причем тут mono? Вряд ли возможно писать драйвера на .NET

                    Не знаю как на .Net и как драйвера, но вот её старшая сестра Java с реалтаймом справлялась прекрасно, и я бы с бóльшей радостью писал на сразу ней чем на голом C с последующей C#-обёрткой.
                    • НЛО прилетело и опубликовало эту надпись здесь
                        0
                        А нативность нужна для скорости, а скорость в случае с устройствами, не отвечающими за хранение/преобразование данных, — для риалтайма. Разве не так?
                        • НЛО прилетело и опубликовало эту надпись здесь
                    +2
                    Очень это просто делается с использованием библиотеки libusb
                      +1
                      В 90% случаев хватит прочитать документацию к libusb. Собственно единственная проблема — протокол взаимодействия с устройством. Обычно эта проблема фатальна ))
                        0
                        Если протокол изначально задан и является черным ящиком, то единственная зацепка — заснифить и расковырять. Если протокол не шибко сложный, и функционал устройства известен, то можно разобраться. Иначе затея не стоит затрачиваемых усилий — дешевле USB-устройство и протокол для него придумать и разработать самому с нуля.
                        0
                        Посмотрите libusb — всё пишется с полпинка, куча примеров и документации. Её же и портировали под win, таким образом она переносимая. Единственное но — это в user-space, на сколько я понимаю
                        0
                        Что это у вас за камера без драйверов под линукс? Чай, не 2000-й год на дворе…
                        • НЛО прилетело и опубликовало эту надпись здесь
                            0
                            usb-id устройства и лог из dmesg разработчику в багтрекер. Если бы вообще драйвера не было — понятно, а так… В любом случае проще, чем свой драйвер писать.
                        +3
                        Очень жду продолжения! Потому как сейчас застрял малость — вроде как что-то вроде драйвера есть, но винда категорически его не принимает как драйвер устройства. И кто виноват, что делать — абсолютно неясно, не могу найти даже, где читать…
                          +3
                          «USB — это simple», я вас умоляю.
                          А ещё лучше, «это просто».
                            +4
                            Ожидал увидеть тут нечто подобное этому: http://www.opennet.ru/base/dev/write_linux_driver.txt.html а не этот обрубок. Процетирую немного вступление в той статье:


                              +2
                              Что то по Ctrl+V запостилось... Вобщем вот:
                              Введение в USB

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

                              Поэтому сразу перейдем к менее очевидным вещам — к тому, как USB
                              устроен внутри.
                            • НЛО прилетело и опубликовало эту надпись здесь
                              –4
                              На мой скромный взгляд, описание создания драйвера, а особенно для USB-устройства, может представлять интерес разве что для тех, кто смутно представляет, что такое драйвер в принципе. Независимо от операционной системы. Когда мне понадобилось написать драйвер для TV-тюнера, то на создание компилируемого, загружаемого и опознающего девайс каркаса мне понадобилось минут, наверное, 30 от силы (включая растерзание гугла). Оставшиеся временные затраты (процентов этак 98) — реализация протокола взаимодействия в соответствии со spec'ами устройства. При этом вам совершенно не нужно знать, сколько и каких контактов задействовано при общении компьютера и устройства, потому что благодаря таким штукам, как HAL (и вообще ядро), все действия производятся на уровне «записать n байт»/«прочитать m байт».

                              В общем, главный недостаток этой все же довольно неплохой статьи — полное отсутствие конкретики.
                                0
                                Ваш комментарий страдает тем же самым — слишком много пустой критики и никакой конкретики (может, за то и минусы?). Дали бы ссылку что ли на Вашу разработку. Наверное (надеюсь) конкретика воспоследует хотя бы в виде продолжения этой статьи.
                                –1
                                И всё-таки работа с RS-232 проще.
                                  0
                                  С классом CDC USB можно работать так же, как и с привычным COM-портом. Просто втыкаете Ваше USB-устройство, и получаете на компьютере обычный COM-порт. Есть много готовых реализаций класса CDC (почти всегда бесплатных), предлагаемых производителями всех чипов с поддержкой USB. Кроме того, есть даже специальные чипы (типа FTDI) и программные библиотеки (типа V-USB), на которых этот класс CDC USB легко реализовывается. Короче, есть уже все готовенькое — бери да делай. Если нужны ссылки на конкретные примеры, которые можно взять за основу своей собственной разработки, то могу предоставить.
                                    0
                                    Виртуальный COM-порт решение распространенное. Но там в силу виртуальности есть свои грабли связанные как раз именно с этой виртуальностью.
                                    Сталкивался с этим работая с POS-терминалами там, на новых материнках RS-232 как раз-таки и реализован как эмуляция на базе шины USB. Т.е. снаружи это ком-порт, а внутри — USB-device.
                                    Прозрачно подменить старый терминал с нативным RS-232, на новый эмулированным не получилось — пришлось править модуль подключения устройства.
                                      0
                                      Все зависит от метода работы с COM-портом. Некоторые старые программки, которые норовят работать напрямую с контроллером COM-порта, не будут работать с COM-портом виртуальным. Но это не наш случай, поскольку в статье и комментариях идет речь о разработке CDC USB-устройства и ПО для него ЗДЕСЬ И СЕЙЧАС, а не в каком-то 1998 году под Windows 95 или 98.
                                        0
                                        Грабли были в 2009 году.
                                        Модуль работы с девайсом был писан на дотнете, с использованием стандартного класса ком-порта дотнета — там прямой работой с контроллером и не пахнет.
                                    0
                                    Всё-таки проще всего, по-моему, было работать с LPT. Статью вроде прочитал, но как я смогу понять со стороны устройства в данный момент ноль или еденица, у меня всё равно в голове не складывается. На сколько я понимаю, на стороне устройства тоже надо воротить какой-то контроллер. С LPT можно было пины с граундом замыкать/размыкать в интересующих комбинациях, и на компе было понятно что со стороны устройства замкнуто.
                                    –2
                                    Советую почитать Кулакова книжку «Программирование на аппаратном уровне», раздел «Шина USB»
                                      0
                                      Есть еще книжка Агурова, но это такое г… (ИМХО), что только затуманивает мозги. Намного зачетнее «USB in a NutShell», благо что она и на русском уже доступна.
                                        0
                                        Скачал книжку Кулакова — повторяет все то же самое, что Агуров написал. Подходит только для начального знакомства с шиной USB, в плане программирования устройств USB и программ для них — практически никакой пользы.
                                        0
                                        Таак, WDK уже скачал, жду продожения.
                                          0
                                          ИМХО: работа с libusb-win32 напорядок проще.
                                            0
                                            Присоединяюсь. Есть готовые примеры как программ для USB-устройств, так и программ для компьютера. Все с исходниками и понятными комментариями.
                                            0
                                            Вот например, ищу ответы, как писать драйвера для USB а результат кроме воды не получил :(

                                            Вопрос когда будет часть вторая?
                                              0
                                              В связи с небольшой заминкой все технические топики будут начиная со второй недели августа.
                                                0
                                                какого года?

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

                                            Самое читаемое