Ошибка «устройство определилось как флешка, а не как привод» при настройке USB-гаджета на Linux почти всегда означает, что образ смонтирован без флага cdrom в функции mass_storage. Эмуляция CD-ROM через файл — рабочий приём для одноплатных компьютеров вроде Raspberry Pi Zero или Orange Pi: хост видит устройство как виртуальный оптический привод с ISO-образом, что полезно для установки ОС, загрузки WinPE или раздачи драйверов без записи на реальный диск.
В этой статье разберём, как работает подсистема USB Gadget в ядре Linux, чем отличаются модули g_file_storage, g_mass_storage и современный подход через configfs с libcomposite, как правильно сконфигурировать функцию эмуляции CD-ROM и что проверять, если хост не видит устройство или образ монтируется только для чтения с ошибками.
Как работает USB Gadget в ядре Linux
Подсистема USB Gadget позволяет устройству с контроллером USB Device Controller (UDC) выступать в роли периферии: флешки, сетевого адаптера, последовательного порта или привода. Ключевое условие — на плате должен быть порт, работающий в режиме OTG/peripheral. На обычном десктопном ПК такого контроллера обычно нет, поэтому тема актуальна в первую очередь для одноплатников и встраиваемых систем.
Исторически существовали монолитные модули: g_file_storage (устарел и удалён из ядра), затем g_mass_storage. Современный способ — configfs вместе с модулем libcomposite: конфигурация собирается через файловую систему /sys/kernel/config/usb_gadget/ без перезагрузки модулей, и в одном гаджете можно комбинировать несколько функций.
- 🔧 UDC — аппаратный контроллер, без него гаджет не запустится; список доступных смотрите в
/sys/class/udc/ - 💿 mass_storage — функция эмуляции накопителя, поддерживает режим CD-ROM
- 🧩 libcomposite — модуль-компоновщик, собирающий гаджет из отдельных функций
- 📁 configfs — интерфейс настройки через каталоги и файлы в
/sys/kernel/config
Эмуляция CD-ROM возможна только на устройстве с USB-контроллером в режиме peripheral/OTG. Проверьте наличие записей в /sys/class/udc/ до начала настройки.
Проверка готовности системы
Прежде чем писать конфигурацию, убедитесь, что ядро собрано с нужными опциями и контроллер виден системе. Вам понадобятся права root — все операции с configfs выполняются от суперпользователя.
ls /sys/class/udc/
modprobe libcomposite
mount | grep configfs
Если каталог /sys/class/udc/ пуст, возможная причина — контроллер не переведён в режим устройства в device tree или драйвер UDC не загружен. На Raspberry Pi, например, для контроллера dwc2 требуется соответствующий overlay в конфигурации загрузки; точное имя overlay зависит от модели платы и версии ОС, сверяйтесь с документацией вашего дистрибутива.
Если configfs не смонтирована, смонтируйте вручную:
mount -t configfs none /sys/kernel/config
⚠️ Внимание: не используйте для гаджета порт, через который плата получает питание, если одновременно по нему идёт обмен данными с хостом без гальванической развязки — при нештатных ситуациях возможны проблемы с питанием обеих сторон. Для экспериментов безопаснее отдельный источник питания.
Создание гаджета с функцией CD-ROM через configfs
Ниже — базовый сценарий: создаётся гаджет, в него добавляется функция mass_storage, файл-образ помечается как CD-ROM, и гаджет привязывается к контроллеру. Идентификаторы VID/PID в примере условные — для реальных проектов используйте значения, которые вы вправе применять.
cd /sys/kernel/config/usb_gadget/
mkdir g1 && cd g1
echo 0x1d6b > idVendor
echo 0x0104 > idProduct
mkdir strings/0x409
echo "0123456789" > strings/0x409/serialnumber
echo "Example" > strings/0x409/manufacturer
echo "Virtual CDROM" > strings/0x409/product
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "CDROM config" > configs/c.1/strings/0x409/configuration
mkdir functions/mass_storage.usb0
echo 1 > functions/mass_storage.usb0/lun.0/cdrom
echo 1 > functions/mass_storage.usb0/lun.0/ro
echo /opt/images/boot.iso > functions/mass_storage.usb0/lun.0/file
ln -s functions/mass_storage.usb0 configs/c.1/
ls /sys/class/udc/ > UDC
Ключевые строки здесь — установка cdrom в 1 до указания файла образа: если сначала записать путь к файлу, а потом менять флаги, часть атрибутов LUN уже заблокируется, и изменения не применятся. Флаг ro делает устройство доступным только для чтения — для CD-ROM это логично и защищает образ от случайной порчи со стороны хоста.
☑️ Чек-лист настройки CD-ROM гаджета
После записи имени контроллера в UDC гаджет активируется. На стороне хоста устройство должно определиться как оптический привод; в Linux-хосте это видно в выводе dmesg и lsblk, в Windows — в диспетчере устройств как устройство чтения компакт-дисков.
Сравнение подходов: g_mass_storage против configfs
Если ваша система старая и configfs недоступна, модуль g_mass_storage всё ещё может работать: образ и режим CD-ROM передаются параметрами при загрузке модуля. Однако у модульного подхода есть ограничение — один модуль реализует одну фиксированную конфигурацию, и для смены образа приходится выгружать и загружать модуль заново.
| Критерий | g_mass_storage | configfs + libcomposite |
|---|---|---|
| Способ настройки | Параметры модуля | Файлы в /sys/kernel/config |
| Смена образа | Перезагрузка модуля | Запись нового пути в файл lun.0/file |
| Комбинация функций | Нет, одна функция | Да, несколько функций в одном гаджете |
| Актуальность | Устаревающий подход | Рекомендуемый в современных ядрах |
Модуль g_file_storage, который иногда встречается в старых инструкциях, из современных ядер удалён — если руководство предлагает его загрузить, оно написано под устаревшую версию ядра, и шаги нужно адаптировать под g_mass_storage или configfs.
Чтобы «извлечь» виртуальный диск без отключения кабеля, запишите пустую строку в файл lun.0/file: echo "" > functions/mass_storage.usb0/lun.0/file. Хост увидит пустой привод, затем можно подложить другой ISO.
Типичные проблемы и их диагностика
Устройство определилось хостом, но диск не читается — частая жалоба. Начните с логов: на стороне гаджета смотрите dmesg сразу после привязки UDC, на стороне хоста — системный журнал в момент подключения. Сообщения о невозможности прочитать таблицу разделов для CD-ROM — норма: у ISO-образа нет MBR в привычном смысле, и хост монтирует его по файловой системе ISO 9660 или UDF.
- ❌ Гаджет не появляется на хосте — проверьте кабель: зарядные кабели без линий данных физически не позволят ничего настроить
- 💾 Хост видит флешку вместо привода — флаг
cdromне установлен или был выставлен после записи файла - 🔒 Ошибка записи в lun.0/file — LUN занят, сначала очистите файл образа пустой строкой
- 📛 Windows не монтирует образ — проверьте, что ISO не повреждён и содержит корректную файловую систему
⚠️ Внимание: не указывайте в lun.0/file блочное устройство с смонтированной файловой системой, если не отключён режим записи. Одновременный доступ к данным со стороны гаджета и хоста приведёт к повреждению ФС. Для CD-ROM-режима всегда используйте ro=1.
Почему образ должен быть целым числом секторов
Функция mass_storage отдаёт хосту данные блоками. Если размер файла не кратен размеру сектора, хвост образа может читаться с ошибками. Большинство ISO-образов этому требованию удовлетворяют, но при создании образа вручную через dd проверьте итоговый размер командой ls -l и при необходимости дополните файл нулями.
Смена образа и автозапуск при загрузке
Гибкость configfs проявляется в горячей смене носителя: чтобы «вставить» другой диск, достаточно очистить файл LUN и записать новый путь. Это удобно для сценариев, где одна плата по очереди раздаёт несколько ISO — например, установщик, затем набор драйверов.
echo "" > functions/mass_storage.usb0/lun.0/file
echo /opt/images/drivers.iso > functions/mass_storage.usb0/lun.0/file
Для автоматического поднятия гаджета при загрузке оформите команды в shell-скрипт и вызывайте его через systemd unit или другой механизм автозапуска вашего дистрибутива. Важно, чтобы скрипт выполнялся после загрузки драйвера UDC, иначе привязка завершится ошибкой. Точный способ зависит от вашей системы — универсальной команды здесь нет.
Смена ISO выполняется без перезагрузки: очистка lun.0/file пустой строкой и запись нового пути. Хост при этом видит «извлечение» и «вставку» диска.
Ограничения режима CD-ROM
Эмуляция привода — не полная замена реального железа. Загрузка ПК с такого виртуального привода зависит от прошивки BIOS/UEFI конкретной машины: некоторые прошивки корректно загружаются с USB-CDROM, другие ожидают именно флешку с MBR/ESP. Если цель — установка ОС, протестируйте загрузку на целевом оборудовании заранее.
Также учитывайте скорость: пропускная способность ограничена возможностями контроллера и чтением файла с карты памяти или eMMC платы. Образы большого размера будут читаться медленнее, чем с SATA-привода, — это нормально и не является признаком неисправности.
Для загрузочных сценариев держите ISO на быстром носителе платы (eMMC вместо медленной microSD) — это заметно сокращает время установки ОС с виртуального привода.
Часто задаваемые вопросы
Можно ли настроить CD-ROM гаджет на обычном ноутбуке с Linux?
Как правило, нет: у большинства ноутбуков USB-контроллеры работают только в режиме хоста, и каталог /sys/class/udc/ окажется пустым. Гаджет-режим доступен на платах с OTG-портом — одноплатных компьютерах и встраиваемых устройствах.
Чем g_file_storage отличается от g_mass_storage?
Это разные поколения одного модуля: g_file_storage — старая реализация, удалённая из современных ядер, g_mass_storage — её преемник. В актуальных системах рекомендуется вообще отказаться от монолитных модулей в пользу configfs с libcomposite.
Хост видит привод, но пишет «вставьте диск». Что не так?
Вероятно, файл образа не привязан к LUN или путь указан неверно. Проверьте содержимое lun.0/file и убедитесь, что файл ISO существует, доступен для чтения пользователю root и не повреждён.
Можно ли сделать образ доступным для записи?
Технически флаг ro можно установить в 0, но для режима CD-ROM это бессмысленно — хосты не пишут на оптические приводы обычным способом. Для записываемого накопителя используйте mass_storage без флага cdrom и помните о риске повреждения ФС при одновременном доступе.
Нужно ли перезагружать плату после изменения конфигурации гаджета?
Нет. Вся настройка через configfs применяется на лету. Для полного сброса достаточно отвязать UDC (записать пустую строку в файл UDC), удалить созданные каталоги гаджета и собрать конфигурацию заново.