Rndis usb ethernet что это
Технологии виртуализации прочно вошли в современный IT мир. Сегодня невозможно найти компанию, которая бы не использовала решения для виртуализации (виртуальные сервера, виртуальные рабочие места, VDI) в своей работе. И все было бы отлично и безоблачно, но гипервизоры, основа инфраструктуры внесли и определенные ограничения на созданные и используемые виртуальные машины.
Одно из ограничений — это отсутствие USB портов на виртуальных машинах. Если раньше мы могли подключить необходимое USB устройство (например, ключ защиты ПО или смарт-карту с ключами шифрования) к физическому серверу, то теперь — поскольку сервера стали виртуальными – эта задача так просто не решается. Как решить эту проблему быстро и эффективно – я расскажу в этом обзоре.
Первое, и казалось бы наиболее очевидное решение — использовать программные эмуляторы портов, но такой подход имеет требует иметь постоянно включенный компьютер, на котором и будет работать ПО для эмуляции. Вывод: неудобное, ресурсоемкое и дорогостоящее решение.
Следущий выбор — програмно-аппартные устройства для решения задачи проброса (эмуляции) USB портов на удаленной машине. Простые, эффективные и недорогие устройства. Выбор остановился на решениях компании Digi International — AnywhereUSB
AnywhereUSB представляет собой компактное устройство USB hub – с дополнительным подключением Ethernet кабеля.
Модели AnywhereUSB
Для использования доступны 3 модели устройств, рассчитанных на разное количество USB портов:
1. AnywhereUSB /2 – 2 порта USB
2. AnywhereUSB/ 5 – 5 портов USB
3. AnywhereUSB /14 – 14 портов USB
Настройка и управление
Для настройки и управления устройством предусмотрено несколько интерфейсов:
• Web интерфейс для настройки, мониторинга и администрирования;
• AnywhereUSB утилита конфигурирования;
• Telnet Command-Line Interface;
• Simple Network Management Protocol (SNMP).
Для настройки устройства рассмотрим Web интерфейс — как наиболее удобный и простой вариант.
Управление IP адресом
Существует несколько вариантов присвоения IP адреса AnywhereUSB:
• Статический IP;
• Динамическое присвоение IP — Using Dynamic Host Configuration Protocol (DHCP);
• Auto Private IP Addressing (APIPA), наиболее известен как Auto-IP;
Сетевые сервисы легко конфигурируются через web интерфейс
Для желающих тонко настроить все параметры сетевого интерфейса доступны соответствующие инструменты
Web интерфейс имеет множество дополнтельных инструментов, позволяющих посмотреть активных подключения, статус и uptime устройства, настроить функции безопасности и.т.д
Текущие подключения:
Состояние устройства:
С настройкой устройства все просто и понятно, теперь перейдем к машине, на которую осуществляется проброс USB портов.
Настройка клиенткой машины
Настройка проста и интуитивно понятна.
Все, что необходимо для настройки:
1. Установить драйвера для AnywhereUSB;
2. Указать IP адрес устройства.
Устройство подключено, в окне доступна информация о состоянии устройства.
В случае необходимости получения детальной информации, о подключеном устройстве, свободных/занятых портах – можно воспользоваться утилитой детального просмотра.
Стоит отметить, что решение очень просто в развертывании и надежно в эксплутации. Весь процесс развертывания и настройки занимает не более 30 минут.
Примерная схема подключения устройства AnywhereUSB
Детальную информацию об устройствах AnywhereUSB, скачать драйвера и документацию можно найти сайте компании Digi International — AnywhereUSB
P.S. Данный обзор написал мой коллега, который, к сожалению, пока не является хабраюзером.
В режиме разработчика на смартфоне Андроид пользователь может найти массу крайне интересных пунктов меню, которые зачастую вызывают большой интерес. В этой статье мы рассмотрим подраздел «Конфигурация USB» и узнаем, что обозначают пункт этого подраздела.
Для начала откроем режим разработчика. Пример на базе смартфона Samsung. Идем в настройки.
Далее находим раздел «Параметры разработчика» или «Режим разработчика. Если он у вас вдруг отключен, включите его с помощью нашей инструкции.
Включаем режим при необходимости и находим пункт «Конфигурация USB» или «Конфигурация USB по умолчанию» или «Выбор настройки USB», например:
Пример на Huawei:
Видим следующее (Samsung):
Что значит этот подраздел? С его помощью вы можете выбрать, какое действие используется при подключению смартфона к компьютеру или ноутбуку. К примеру, вы можете включить передачу файлов, а можете — только передачу изображений и видео.
Теперь пройдемся по каждому пункту.
Лог рабочего варианта отправки чеков
Изучаем USB RnDis адаптер через программу перехватчик пакетов USBLyzer :
Начинаем переходить на более низкий уровень изучения проблемы
Настройки кассы по умолчанию, как описано в инструкции Штриха.
Ethernet to router 192.168.1.50 / 255.255.255.0 / 192.168.1.1 /dns 192.168.1.1
RnDIS адаптер 192.168.137.1 / 255.255.255.0 / шлюз не нужен / dns не надо
Сама касса 192.168.137.111 / 255.255.255.0 / шлюз НЕ нужен dns НЕ нужен
Начинаем вспоминать как работают сети и приходит на ум попинговать из кассы
Настроим WinShark на отфильтровку icmp (пинг) и из драйвера пошлем пинг на 192.168.137.1 (RnDis адаптер)
Результат пинга не заставит себя долго ждать
192.168.137.1 доступен, а вот 192.168.1.50 - недоступен (как видно на картинке сверху). То есть нет проброса трафика с адаптера 192.168.137.1 на 192.168.1.50.
Вывод : пакет с адаптера ARP 192.168.137.1 не покидает адаптера 192.168.137.1 и ICMP тоже
На самом деле сети у них разные , так как разные сетевые адаптеры их определяют.
И тут без маршрутизации не обойтись.
Ну или по смыслу это делает прога OFDConnect у Штриха.
Как настраивать правильно ищите на соседней странице(ах) есть.
Изучаем чем нам может помочь arp
момент отправки чека :
Запустим WinShark для адаптера RnDIS и посмотрим пакеты
Первое , что после включения происходит это посылка ARP пакета :
Первый пакет NxpSemic_f3:fb:05 (00:60:37:f3:fb:05 - это сама касса) посылается с таким смыслом : у кассу ip настроен статически и обязана у сети спросить - кто в сети с таким ip есть?
Касса конечно надеется , что ей ответят - у этого ip такой-то мак устройства, и касса - ой да это же я и и есть. Значит ее знают в сети. Значит все ОК.
Но у нас ответа нет, но это как оказывается для нормальной работы в дальнейшем не важно.
Кстати источник представляется как Address: NxpSemic_f3:fb:05 (00:60:37:f3:fb:05) отнюдь не Штрих-М.
Потом после всяких инициализирующий запросов , касса начинает постоянно долбить на порт 16327 всем доступным соседям см. 255.255.255.255. И это тоже нормально .
Пункты меню
Передача файлов (MTP или Media Transfer Protocol). Передача любых доступных файлов, будь то музыка, видео, фотографии, документы и т.д.
Передача изображений (MTP или Picture Transfer Protocol ). В этом режиме при подключении смартфона к компьютеру или ноутбуку и после разблокировки экрана становится доступна передача изображений, а также видеороликов.
USB-модем (RNDIS или USB Ethernet). Подключается как USB-модем, то есть вы можете использовать смартфон как точку доступа для ПК или ноутбука.
MIDI. Позволяет использовать ваш смартфон как MIDI-устройство.
Аудиоисточник. Использование вашего смартфона как источник вывода звука.
Только зарядка. В этом случае доступ к данным после разблокировки экрана не осуществляется, смартфон лишь заряжается от вашего ПК или ноутбука.
Есть один нюанс. Некоторые смартфоны при выборе одного из режимов используют выбранный вами пункт по умолчанию постоянно. Так, если вы выбрали «Только зарядка», то при подключении смартфона к ПК или ноутбуку каждый раз будет использовать именно указанный вариант подключения. Если выбрали «Передача файлов», то после подключения и разблокировки рабочего стола каждый раз будет доступна файловая система смартфона и для любого компьютера, что может быть опасно в некоторых случаях. Будьте внимательны.
Проблемы у Штрих-М с RnDis адаптером существуют (особенно под Win 10).
На самом деле проблема изучена и решена на соседней странице.
Но здесь описаны инструменты , которые помогают для понимания как работает сеть.
шпаргалка по протоколам
NBNS - netbios сервер имен
MDNS - Multicast DNS
IGMP Internet Group Management Protocol
SSDP - Simple Service Discovery Protocol
ADwin configuration protocol (adwin_config)
Изучаем чем нам может помочь route
route print 192.*
Настраиваем теперь так
Ethernet to router 192.168.1.50/24 192.168.1.1.
RnDIS to kass 192.168.1.118/24 Шлюза нет , dns нет
касса 192.168.1.119/24 шлюза нет, dns нет
Arp -s 192.168.137.111 00-60-37-f3-fb-04
arp -s 192.168.137.1 00-60-37-f3-fb-05
Итак, если Вы заинтересовались, читайте далее…
1. Драйвер RNDIS
На этапе написания решалось две задачи: подписать наше устройство и поддержать стандарт RNDIS.
Подпись устройства сводится к составлению верных USB-дескрипторов. Значение VID выбрано 0x0483 (STMicroelectronics), значение PID — 0x0123 (произвольное). Само собой, в коммерческом применении так делать не следует.
Device Descriptor | ||||
Offset | Field | Size | Value | Description |
---|---|---|---|---|
0 | bLength | 1 | 12h | |
1 | bDescriptorType | 1 | 01h | Device |
2 | bcdUSB | 2 | 0200h | USB Spec 2.0 |
4 | bDeviceClass | 1 | 02h | CDC Control |
5 | bDeviceSubClass | 1 | 00h | |
6 | bDeviceProtocol | 1 | 00h | |
7 | bMaxPacketSize0 | 1 | 40h | 64 bytes |
8 | idVendor | 2 | 0483h | SGS Thomson Microelectronics |
10 | idProduct | 2 | 0123h | |
12 | bcdDevice | 2 | 0001h | 0.01 |
14 | iManufacturer | 1 | 01h | «Fetisov Sergey» |
15 | iProduct | 1 | 02h | «STM32F4 RNDIS» |
16 | iSerialNumber | 1 | 03h | «00000000123C» |
17 | bNumConfigurations | 1 | 01h | |
Configuration Descriptor 1 | ||||
Offset | Field | Size | Value | Description |
0 | bLength | 1 | 09h | |
1 | bDescriptorType | 1 | 02h | Configuration |
2 | wTotalLength | 2 | 0043h | |
4 | bNumInterfaces | 1 | 02h | |
5 | bConfigurationValue | 1 | 01h | |
6 | iConfiguration | 1 | 00h | |
7 | bmAttributes | 1 | 40h | Self Powered |
8 | bMaxPower | 1 | 01h | 2 mA |
Interface Descriptor 0/0 CDC Control, 1 Endpoint | ||||
Offset | Field | Size | Value | Description |
0 | bLength | 1 | 09h | |
1 | bDescriptorType | 1 | 04h | Interface |
2 | bInterfaceNumber | 1 | 00h | |
3 | bAlternateSetting | 1 | 00h | |
4 | bNumEndpoints | 1 | 01h | |
5 | bInterfaceClass | 1 | 02h | CDC Control |
6 | bInterfaceSubClass | 1 | 02h | Abstract Control Model |
7 | bInterfaceProtocol | 1 | FFh | Vendor-Specific |
8 | iInterface | 1 | 00h | |
Header Functional Descriptor | ||||
Offset | Field | Size | Value | Description |
0 | bFunctionLength | 1 | 05h | |
1 | bDescriptorType | 1 | 24h | CS Interface |
2 | bDescriptorSubtype | 1 | 00h | Header |
3 | bcdCDC | 2 | 0110h | 1.10 |
Call Management Functional Descriptor | ||||
Offset | Field | Size | Value | Description |
0 | bFunctionLength | 1 | 05h | |
1 | bDescriptorType | 1 | 24h | CS Interface |
2 | bDescriptorSubtype | 1 | 01h | Call Management |
3 | bmCapabilities | 1 | 00h | |
4 | bDataInterface | 1 | 01h | |
Abstract Control Management Functional Descriptor | ||||
Offset | Field | Size | Value | Description |
0 | bFunctionLength | 1 | 04h | |
1 | bDescriptorType | 1 | 24h | CS Interface |
2 | bDescriptorSubtype | 1 | 02h | Abstract Control Management |
3 | bmCapabilities | 1 | 00h | Requests/notifications not supported |
Union Functional Descriptor | ||||
Offset | Field | Size | Value | Description |
0 | bFunctionLength | 1 | 05h | |
1 | bDescriptorType | 1 | 24h | CS Interface |
2 | bDescriptorSubtype | 1 | 06h | Union |
3 | bControlInterface | 1 | 00h | |
4 | bSubordinateInterface0 | 1 | 01h | CDC Data |
Endpoint Descriptor 81 1 In, Interrupt, 80 ms | ||||
Offset | Field | Size | Value | Description |
0 | bLength | 1 | 07h | |
1 | bDescriptorType | 1 | 05h | Endpoint |
2 | bEndpointAddress | 1 | 81h | 1 In |
3 | bmAttributes | 1 | 03h | Interrupt |
4 | wMaxPacketSize | 2 | 0008h | 8 bytes |
6 | bInterval | 1 | 50h | 80 ms |
Interface Descriptor 1/0 CDC Data, 2 Endpoints | ||||
Offset | Field | Size | Value | Description |
0 | bLength | 1 | 09h | |
1 | bDescriptorType | 1 | 04h | Interface |
2 | bInterfaceNumber | 1 | 01h | |
3 | bAlternateSetting | 1 | 00h | |
4 | bNumEndpoints | 1 | 02h | |
5 | bInterfaceClass | 1 | 0Ah | CDC Data |
6 | bInterfaceSubClass | 1 | 00h | |
7 | bInterfaceProtocol | 1 | 00h | |
8 | iInterface | 1 | 00h | |
Endpoint Descriptor 82 2 In, Bulk, 64 bytes | ||||
Offset | Field | Size | Value | Description |
0 | bLength | 1 | 07h | |
1 | bDescriptorType | 1 | 05h | Endpoint |
2 | bEndpointAddress | 1 | 82h | 2 In |
3 | bmAttributes | 1 | 02h | Bulk |
4 | wMaxPacketSize | 2 | 0040h | 64 bytes |
6 | bInterval | 1 | 00h | |
Endpoint Descriptor 03 3 Out, Bulk, 64 bytes | ||||
Offset | Field | Size | Value | Description |
0 | bLength | 1 | 07h | |
1 | bDescriptorType | 1 | 05h | Endpoint |
2 | bEndpointAddress | 1 | 03h | 3 Out |
3 | bmAttributes | 1 | 02h | Bulk |
4 | wMaxPacketSize | 2 | 0040h | 64 bytes |
6 | bInterval | 1 | 00h |
Поддержка стандарта осуществлена в соответствии с документацией.
Также в сети присутствует множество RNDIS-драйверов для других платформ (1, 2, 3), что существенно упростило разработку.
В части обмена драйвер повторяет особенность CDC-класса за исключением того, что передаваемые пакеты оборачиваются служебной информацией. Также существует специальный интерфейс для передачи запросов от usb-хоста с целью настройки устройства или получения его статуса. Детально код драйвера можно изучить в модуле usbd_rndis_core.c.
Минимальная настройка драйвера при встраивании заключается в изменении определений в файле usbd_rndis_core.h.
— MAC-адрес устройства (PERMANENT_HWADDR, STATION_HWADDR)
— Идентификатор производителя (RNDIS_VENDOR)
— Значение MTU (ETH_MTU):
Также в файле usbd_desc.h следует изменить название продукта (USBD_PRODUCT_STRING) и производителя (USBD_MANUFACTURER_STRING).
Процесс установки драйвера в ОС Windows:
1. Пункт меню «обновить драйвер»;
2. Выполнить поиск драйвера;
3. Выбрать драйвер из списка;
4. В списке классов устройств выбрать «Сетевые адаптеры»;
5. В списке производителе выбрать «Microsoft Corporation»;
6. И продукт «Remote NDIS based Internet Sharing Device».
Более подробно процесс установки стандартного RNDIS устройства описан по ссылке.
2. Прикручиваем LwIP
Драйвер RNDIS обеспечивает лишь транспортную функцию для кадров стандарта 802.3 (Ethernet). Очевидно, что поддержку всего многообразия пакетов и стандартов требуется возложить на сетевой стек. В его роли было принято решение использовать популярный стек для встраиваемых систем lwip последней (на текущий момент) версии 1.4.1. Надо отдать должное авторам стека, тот получился весьма просто интегрируемым. При всём при этом, код стека богат полезными комментариями и инструкциями.
Запуск стека под stm32 ограничился включением в процесс сборки конкретного набора исходных файлов и вводом определений в файле lwipopts.h:
Нужно отметить, работа по портированию стека на STM32F4 производилась и раньше фирмой STMicroelectronics (приложение STSW-STM32070).
Запускаем DHCP-сервер
Добавление DHCP-сервера в состав библиотеки связано с необходимостью инициализировать сетевой интерфейс на стороне host-а. По умолчанию, создаваемый при подключении устройства интерфейс настроен на автоматическое получение ip-адреса. Библиотека также успешно работает и при статической адресации, но это является не совсем удобным.
К сожалению, среди поставляемых lwip средств, DHCP-сервер отсутствует.
Однако, это не является существенной проблемой, т.к. в своей минимальной реализации DHCP-сервер весьма минималистичен.
В сети присутствует, пожалуй, единственный пример DHCP-сервера, работающего со стеком lwip. Данный источник оказался весьма полезным для изучения, хоть и не пригодным для встраивания по принципу «as-is» по причине отсутствия возможности конфигурирования и использования socket-api.
Поэтому было принято решение написать DHCP сервер.
И вот его скромные возможности:
— выдача адресов на произвольное время
— резервирование адресов по MAC адресу
— настройка DNS-сервера
Подключение сервера в тестовом проекте:
Запускаем DNS-сервер
Желаемый нами результат работы — отображение web-страницы при вводе в браузере некоторого имени ресурса. Однако, это возможно только при наличии DNS-сервера, который будет «знать» о нашем хосте. Конечно, этот результат доступен, если в адресной строке напрямую ввести ip-адрес: 192.168.7.1. Такой адрес имеет по умолчанию наше устройство. Однако, будем более искусны и запустим DNS-сервер.
В отличии от DHCP, текущая реализация DNS-сервера ещё «тоньше». На данный момент она позволяет обработать только стандартные DNS-запросы на одну запись.
Запуск сервера в проекте:
Долго и безрезультатно пришлось бороться с запуском известного сервера из пакета lwip «contrib-1.4.1». До сих пор для меня остаётся загадкой таинственный HardFault, возникающий на, казалось бы, ровном месте. Были проверены все настройки, адреса чтения и записи, глубина стека… Но, увы.
Итак, результат был всё таки получен.
Нерешённые вопросы
1. Ньюансы релицензирования стека lwip, который может иметь свои условия включения в состав другого ПО;
2. Проблема с работой под ОС Linux;
3. Добавление обработки POST-запросов;
4. Доработка DNS-сервера для обработки «многовопросных» пакетов;
5. Проблема с mem_malloc.
Первым делом хотелось бы с лучшими пожеланиями поздравить всех с минувшими новогодними праздниками.
Ранее в статье была анонсирована разработка RNDIS USB драйвера для контроллеров серии STM32F4. С тех пор библиотека постепенно развивалась и нынче доросла до первой release-версии. Библиотека под названием LRNDIS (LWIP + RNDIS) позволяет нам создавать на базе контроллера STM32F4 как устройства класса USB «модем», так и любые другие устройства с управлением через web-интерфейс. Пример управления платой stm32f4-discovery из web-браузера на Android-планшете представлен на видео:
На странице видеоролика представлена ссылка на исходные коды и HEX-файл прошивки для платы discovery, с которым вы сможете повторить данный эксперимент. В статье рассказано о том, как и когда технология доступа через WEB-интерфейс полезна, а также — как работает библиотека LRNDIS для контроллеров STM32F4. Также присутствует обучающий материал о работе USB и устройстве Ethernet-сетей.
Предыстория создания библиотеки
Предыстория проекта весьма типовая. Стоял тёплый летний день. Гхм… Для заказчика стояла задача разработать устройство с сервисным интерфейсом управления.
По мере развития прошивки было введено несколько команд управления по VCP-интерфейсу. Это значит, что после подключения USB-устройства в ОС создавался виртуальный COM-порт. Используя его, из пользовательского терминала передавались команды управления и диагностики. В ответ от устройства принимался статус выполнения и его текущее состояние.
Система вполне типовая с сервисной точки зрения: есть последовательный порт и набор команд для управления и диагностики.
Всё изменилось в короткий срок. По объективным причинам рос требуемый набор команд. Также понадобилась интерактивность вывода: некоторые параметры стало необходимо отображать в динамике. Как, например, показания магнитного датчика при проносе мимо него ферромагнетика. Для этого были введены дополнительные команды, которые, оперируя управляющими последовательностями, печатали информацию в пользовательском терминале с высокой периодичностью. Это создавало необходимое ощущение риалтаймовости наблюдения. Интерактивные команды оказались настолько удобными для инженеров, что некоторая часть команд позже была добавлена в соответствии с концепцией. И тут раздался треск. Требовалось поддержать сразу несколько групп команд: интерактивные, диагностические, команды управления. При этом периодический рефакторинг кода был связан с трудоёмкой правкой в большом количестве обрабатываемых команд. Ясно стало, что ещё должна быть пользовательская группа команд — для менее квалифицированного персонала, который будет просто следовать инструкциям по эксплуатации. Для них возникла идея написания клиентского терминала с кнопочками и флажочками… И вот тут возникли сомнения: стало ясно, что мы занимаемся сервисной частью, уделяя всё меньше внимания функциональности! А ведь пользовательская программа, запускаемая на клиентской ЭВМ, также должна обладать своими требованиями: кроссплатформенность и LTS (длительностью поддержки).
Устройство, предположим, мы закончили, а пользовательское ПО мы должны портировать и тестировать с каждой версией выпускаемых операционных систем! А как долго?
Так и родился вопрос — как избавиться от дополнительных трудозатрат?
Было принято решение использовать стандарты гарантированно длительной поддержки. Те стандарты, которые нам позволят создать клиентскую программу управления устройством, которая будет поддерживаться максимально полным набором операционных систем в настоящем и будущем времени. На первых парах были найдены недостатки популярных кроссплатформенных фрэймворков:
— java: необходимость наличия в ОС JVM, и вытекающий из противного предположения необходимость дистрибьюции виртуальной машины
— qt: периодическая необходимость версионного портирования и нюансы запуска под Android.
Нет, эти сложности пугать не должны. Вопрос, пожалуй, только в трудочасах, которые мы, бывает, недооцениваем с учётом фактора длительной поддержки.
Сфера применения библиотеки
К сожалению, первый анонс в полной мере успешным не был, т.к. рассказ о сфере применения был упущен.
Попробуем немного наверстать упущенное и раскрыть эту тему.
Если мы находимся на этапе системного проектирования устройства, то следующие соображения могут склонить нас в сторону использования web-интерфейсов (вне зависимости от физического канала, Ethernet или USB):
1. Устройство должно иметь интерфейс управления и/или диагностики
2. Средства управления могут использоваться не только на этапе разработки, но и на этапе эксплуатации (ПО пользователя)
3. Квалификация пользователя может быть недостаточно высокой, что требует дружественный интерфейс управления
4. Способ «дружественного» управления должен быть доступен из под разных платформ и ОС
5. Соответствующие средства требуется поддерживать в рабочем состоянии длительное время
Дополнительным критерием может являться то, разрабатываем ли мы изначально сетевое устройство. А также: не будет ли (в противном случае) добавление в прошивку сетевого стека и web-сервера являться избыточным на фоне куда менее богатого функционала устройства. Иными словами, добавление web-интерфейса в контроллер управления лампочкой — очевидно, избыточное решение.
Если мы поверили в web-интерфейс, то следующие соображения, возможно, нам помогут в выборе физического канала связи (из Ethernet и USB перспективы).
Тип | Внутрисхемное подключение | Типовое применение |
Ethernet | Ethernet PHY контроллер | — Промышленные устройства — Бытовые устройства с сетевой функцией и доп. питанием |
USB | ULPI контроллер или прямое подключение к МК | Бытовые и часть промышленных устройств. В особенности, если: — устройства имеют не гарантированный источник питания (питание от батареи, например) — устройства потенциально подключаемые к хосту только с USB интерфейсом (например, планшет) — миниатюрный класс устройств |
От себя добавлю — не смотря на все прелести, не посоветовал бы применять USB в промышленных узлах с требованием повышенной надёжности: часто встречается негативный опыт. Если альтернативы нет — то вопрос устойчивости требуется изучить досконально.
Исходя из приведённых пунктов, становится ясна сфера применения библиотеки: бытовые и часть промышленных устройств, которые:
— работают на базе МК STM32F4
— должны обладать дружественным интерфейсом управления
— должны управляться из под разного аппаратного и программного набора
— могут не иметь гарантированного источника питания
— должны иметь длительный период поддержки ПО управления
Возможных примеров использования технологии много даже вне области сугубо сетевых устройств.
К примеру, на данный момент есть планы по превращению stm32f4-discovery в инструмент любительской разработки с функциями портативного генератора/анализатора сигналов и осциллографа. Подключите такой помощник к телефону и посмотрите в динамике что происходит в интересующей вас цепи. Из бесплатных плюсов — не требуется собирать или устанавливать ПО; достаточно прошить HEX-файл и открыть браузер — в нём будут присутствовать все прелести GUI-интерфейса. На мой привередливый вкус — то что нужно. Конечно, инструмент не для профессиональной разработки, но известный интерес к нему присутствует.
Итак, надеюсь, разобрались. А теперь о том как работает библиотека.
Как оно работает
При ответе на этот вопрос спешить не будем. Человек, имеющий небольшой опыт взаимодействия с сетями, может вполне справедливо смутиться. Поэтому, касаясь того или иного протокола взаимодействия я буду также давать его краткое техническое описание на том уровне… которого когда-то не хватало самому.
Шаг 1. Подключаем USB-устройство.
Как говорилось раньше, на этом этапе наше устройство говорит хосту «я — сетевая карта!».
Хост (т.е. клиентская ЭВМ) после подключения к нему нашей поделки, начинает отправлять запросы.
— как изделие называется
— какой у изделия VID и PID (идентификаторы производителя и изделия, см. список)
— к какому классу и подклассу относится устройство
— по каким endpoint точкам и какими блоками следует обмениваться данными
Ну, и некоторую другую информацию. Конфигурационные пакеты при этом передаются по точке endpoint 0. Ответные пакеты от устройства с информацией о себе обычно называют «дескрипторы USB устройства».
Подробно ознакомиться о процессе опроса (энумерации) можно здесь.
Вообще, протокол USB достаточно богат… иногда даже кажется, что избыточно. Однако, это богатство вот уже много лет позволяет подключать совершенно разные устройства, даёт возможность передавать изохронные потоки, блоки данных, прерывания. В общем, всё необходимое, что может потребоваться широкому набору современных устройств. Обратная сторона медали — высокий порог входа в разработку USB-устройств.
После получения информации об устройстве, ОС хоста производит поиск подходящего драйвера для взаимодействия. В типовом случае, вроде flash-носителей (USB класс MSC) или клавиатуры с мышкой (HID класс), загружается стандартный для класса драйвер. В более «тяжёлом» случае, вроде нашей USB сетевой карты (CDC класс с RNDIS подклассом), операционная система поступает по усмотрению:
— ОС linux/android/mac, как правило, успешно пытается наладить типовой обмен
— ОС windows просит установить внешний драйвер
Наше устройство в первом случае работает сразу.
В случае ОС windows (позднее XP) можно установить стандартный драйвер фирмы Microsoft. Для Windows XP необходимо поставить inf-файл, доступный в репозитории библиотеки LRNDIS.
Шаг 2. Драйвер инициализирует RNDIS-устройство
На данной картинке изображён принцип связи с RNDIS устройством (ОС Windows).
Более подробно о нём можно почитать тут и там.
Если вкратце, то RNDIS протокол — это расширение NDIS для внешних устройств. Роль протокола — обеспечить поддержку PnP и обмен сетевыми пакетами. По сути своей, RNDIS — самостоятельный сетевой интерфейс, информационной нагрузкой которого являются кадры канального/сетевого уровней (Ethernet или IP кадры, опционально).
На приведённой схеме это реализует кубик «Минипорт Remote NDIS», который отвечает за:
— сервис общения (спросить у сетевого устройства его MAC-адрес, размер пакета, скорость работы и прочее)
— оборачивает отправляемые хостом сетевые пакеты в RNDIS заголовок
— транслирует принимаемые от устройства пакеты, выбрасывая RNDIS заголовок
Кубик «Минипорт Remote NDIS USB» отвечает за транзит RNDIS посылок, работая с драйвером USB шины.
На стороне контроллера STM32 за поддержку RNDIS протокола и работу с USB отвечает файл usbd_rndis_core.c. Он делает то же самое, что и «кубик» хоста «Минипорт Remote NDIS» — занимается приклеиванием/отклеиванием заголовков, а также отвечает на вопросы драйвера. Ответы, вроде MAC-адреса и скорости он берёт из файла usbd_rndis_core.h.
После успешной инициализации RNDIS драйвер Windows создаёт сетевой интерфейс, который в последствии отображается в «Центре управления сетями» и в области трей-индикатора.
Шаг 3. Получение IP-адреса
Итак, для чего нужна служба получения динамического адреса. Эта служба называется DHCP (протокол динамической настройки узла).
После того как хост инициализирует наше устройство, он создаёт сетевой интерфейс.
Сетевой интерфейс — это программная сущность, предоставляющая доступ к ресурсам физической или виртуальной сети.
Чаще всего каждому сетевому интерфейсу хоста соответствует конкретный сетевой адаптер. Но есть множество других интерфейсов, вроде локальной петли или те, что служат для взаимодействия с виртуальной машиной. В их случае в сигнальном виде из хоста «ничего не выходит» — обмен происходит программным способом.
Каждому сетевому интерфейсу хоста должен быть сопоставлен хотябы один IP-адрес. По нему «жители сети» может обратиться к хосту.
Если «на проводе» адресовано несколько сетей (например, устройства с IP адресами 10.4.1.xx и 192.168.1.xx), то интерфейсу может назначаться два «личных» IP-адреса. Они могут выглядеть так: 10.4.1.151 и 192.168.1.200. Узнать набор сетевых интерфейсов и сопоставленных им IP-адресов в ОС Windows можно с помощью команды ipconfig и с помощью ifconfig в ОС Linux.
Для описания сетей/подсетей используется маска. Например, правильное описание сети 10.4.1.xx такое: сеть 10.4.1.0, маска 255.255.255.0. Либо, если 4-ёх байтовое число маски представить в двоичном виде и посчитать число ведущих едениц, то получится значение 24. Тогда сеть можно описать так: 10.4.1.0/24.
Подробнее об этом можно почитать в соответствующих источниках.
Известны две основные стратегии назначения IP-адреса интерфейсу: статический способ (когда пользователь сам прописывает адрес интерфейсу) и динамический (с помощью DHCP-службы).
Последний заключается в том, что при создании интерфейса на хосте активизируется служба DHCP-клиента. Она начинает посылать в сеть (конфигурация которой пока не известна) широковещательные пакеты по протоколу UDP, в надежде на то, что в сети присутствует DHCP-сервер.
Функция DHCP-сервера в общем, и в частности на нашем контроллере — ответить клиенту. В ответе контроллер «говорит»: клиент, ты в такой-то сети, держи такой-то IP-адрес, а ещё у нас имеется DNS-сервер с таким-то адресом.
После этого хост «чувствует себя» намного лучше: он назначает интерфейсу выданный IP-адрес и запоминает IP-адрес DNS-сервера.
Инициализация закончилась, теперь можно вводить имя страницы (run.stm) в браузере хоста.
Надо сказать, что поведение библиотеки LRNDIS настраивается. Службу DHCP-сервера можно исключить из сборки. Тогда на хосте придётся прописывать любой адрес, принадлежащий диапазону 192.168.7.(2-254). Такая сеть создаётся по умолчанию. Её параметры (192.168.7.0/24) также настраиваются. В примере клиенту выдаются адреса в диапазоне 192.168.7.2… 192.168.7.4 с временем лизинга 24 часа.
Более подробно по вопросу настройки библиотеки можно посмотреть в предыдущей статье.
Шаг 4. Загрузка страницы
Для загрузки страницы пользователь может ввести адрес нашего устройства 192.168.7.1 напрямую.
Однако, запоминать цифры не требуется, т.к. помимо DHCP-сервера, есть возможность собрать библиотеку с поддержкой DNS-сервера, функция которого — разрешать сетевые имена. В публикуемом примере DNS-сервер обучен разрешать имя ресурса «run.stm».
Запрос и ответ между браузером Firefox и контроллером:
История запросов при загрузке страницы:
Из истории мы видим, что, после загрузки корневого HTML-документа браузер также загружает из контроллера другие два файла: discovery.svg и zepto.min.js. Первый — это изображение платы discovery. SVG формат выбран, т.к., являясь изображением векторной графики, мало занимает места в ПЗУ микроконтроллера. Скриптовый файл zepto.min.js включён, т.к. является урезанным аналогом знаменитого JQUERY. Надо заметить, что скрупулёзной экономии места в ПЗУ не производилось, т.к. не смотря на жертву в 35 Кб на все статические ресурсы, памяти контроллера ещё вполне достаточно. К тому же данный размер с дальнейшим увеличением сложности интерфейса обещает расти заметно медленней. Если же интерфейс разросся существенно — всегда есть выход хранить и отдавать статические ресурсы в сжатом виде — все известные браузеры на данный момент поддерживают декомпрессию «на лету».
Ещё один запрос, который отправляет браузер — это запрос /state.cgi. Он формируется скриптом из корневого HTML-документа с периодичностью 5 раз в секунду. Нужен запрос для получения в динамике текущего состояния устройства.
При приёме данного запроса, контроллер формирует и отвечает следующей строкой в JSON формате:
Она и содержит все данные о текущем состоянии устройства, которые впоследствии отображаются на странице средствами JavaScript кода.
Ну и, пожалуй, последний момент в общении с браузером — способ управления.
О стеке LWIP
Никакого сетевого обмена устроить бы не получилось, если бы не данный сетевой стек, который и был встроен в библиотеку.
Поскольку библиотека работает под «голым» железом (без ОС и динамической аллокации памяти), то надстройка в виде сокетов для использования недоступна. Написание сетевых приложений поэтому происходит с использованием сырого API стека. По этой теме, к счастью, в сети много информации.
В прошлой статье я давал краткое описание стека и его настройки. На данный момент был уточнён набор важных для стека определений в файле:
Также была решена проблема с mem_malloc. Хоть текущая версия прошивки и не использует динамическую аллокацию, аппаратный крах при вызове mem_malloc держал настороже. Разрешилось добавлением определения MEM_ALIGNMENT, который раньше был обойдён вниманием.
Нерешённые вопросы
1. Ньюансы релицензирования стека lwip, который может иметь свои условия включения в состав другого ПО;
2. Доработка DNS-сервера для обработки «многовопросных» пакетов;
Вместо заключения
Благодарю читателя за терпение и надеюсь, что данная статья окажется для него полезной. Опубликованная в исходных кодах библиотека LRNDIS доступна для использования на правах MIT-лицензии. Считаю замечательным, если работа, на которую было уделено ощутимое время и запас сил, окажется полезной ещё кому-то. На худой конец, без использования открытых библиотек не получилось бы и этой.
Включение кассы :
Читайте также: