Как назначить USB-драйвер устройству

30

Этот вопрос двоякий:

Во-первых, как вручную отсоединить драйвер от USB-устройства и подключить другой? Например, у меня есть устройство, которое при подключении автоматически использует драйвер usb-хранилища.

вывод usbview

Vendor Id: xxxx
Product Id: xxxx
...
    Number of Interfaces: 2
    Interface Number: 0
        Name: usb-storage
        Number of Endpoints: 2
        ...
    Interface Number: 1
        Name: (none)
        Number of Endpoints: 2
        ...

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

Как вручную отключить драйвер вне приложения?


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

SUBSYSTEM=="usb", ATTR{idVendor}=="xxxx", MODE="0666"

Могу ли я использовать правила udev для назначения драйверов определенным интерфейсам на устройстве USB? Например, если я хотел, чтобы модуль usbnet использовался автоматически на интерфейсе 0 вместо usb-storage, возможно ли это в udev?

linsek
источник
1
Если часть проблемы заключается в загрузке нужного модуля, см. Веб-камеру на Angström
Жиль "ТАК - перестань быть злым"
1
Вам нужен вообще модуль usb-storage? потому что, если нет, вы можете поместить его в черный список, и он не будет загружаться вообще.
Ханан Н.
@ Жиль, я успешно могу загрузить LKM. У меня вопрос, как мне вручную и автоматически подключить это к устройству?
Линсек
@ Ханан, в настоящее время я не использую модуль usb-storage. Мне может понадобиться внести его в черный список, чтобы автоматически подключить нужный модуль, но сначала мне нужно знать, как подключить USB-модуль.
Линсек
1
Модуль @njozwiak usbnetне загружается автоматически, потому что у него нет информации об оборудовании, которое может его использовать. Попробуйте найти подходящий драйвер и использовать, например modinfo kalmia,. В aliasстроках вы увидите идентификатор поставщика xxxx и идентификатор продукта yyyy as usb:vxxxxpyyyy. Или вы можете отредактировать файл /lib/modules/kernel_version/modules.usbmap и для вашего HW вы можете удалить строку, где находится ваше HW-модуль usb-storage, или изменить usbstorage с помощью соответствующего сетевого драйвера. Но после depmod -aэтого изменения уйдут ...
Ян Марек

Ответы:

20

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

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

Каждый драйвер в ядре Linux отвечает за одно или несколько устройств. Драйвер сам выбирает, какие устройства он поддерживает. Это делается программно, т. Е. Путем проверки производителя устройства и идентификатора продукта или, если они недоступны (например, старое устройство), выполнения некоторых эвристических процедур автоматического обнаружения и проверки работоспособности. Как только водитель уверен, что нашел устройство, которое он поддерживает, он присоединяется к нему. Короче говоря, вы часто не можете заставить определенный драйвер использовать определенное устройство. Иногда, однако, драйвер устройства щедр в отношении того, что он принимает, и устройство может работать, о чем оно не знает. Ваш пробег будет меняться! В прошлом мне приходилось вручную добавлять странные идентификаторы устройств / поставщиков PCI в драйверы, которые должны их поддерживать, с неоднозначным успехом и несколькими забавными сбоями ядра.

Теперь, в случае модулей, есть дополнительный шаг. Модуль загрузчик пробуждается ядром , когда новое устройство обнаружено. Передается строка 'modalias', которая идентифицирует устройство и выглядит примерно так для USB-устройств:

usb:v046DpC221d0170dc00dsc00dp00ic03isc00ip00

Эта строка содержит класс устройства ( usb) и информацию о классе (производитель / устройство / серийный номер, класс устройства и т. Д.). Каждый драйвер ядра содержит строку, такую ​​как:

MODULE_ALIAS("usb:...")

Который должен соответствовать usbalias (подстановочные знаки используются для соответствия нескольким устройствам). Если modaliasсовпадает с поддерживаемым драйвером, этот драйвер загружается (или уведомляется о новом устройстве, если оно уже там).

Вы можете увидеть поддерживаемые устройства (по модалиям) и связанные с ними модули с

less /lib/modules/`uname -r`/modules.alias

Если вы воспользуетесь драйвером USB-устройства хранения данных, то увидите, что у него есть некоторые конкретные устройства, которые он поддерживает по поставщику и идентификатору устройства, а также попытаетесь поддержать любое устройство с правильным классом (хранилищем), независимо от поставщика / устройства. ,

Вы можете повлиять на это, используя механизмы пространства пользователя в вашей ОС ( /etc/modprobe.d/в Debian и в друзьях). Вы можете занести в черный список модули или указать модули, которые будут загружаться с помощью modalias, точно так же как modules.aliasфайл (и используя тот же синтаксис). depmod -aзатем восстановит шаблоны загрузчика модуля.

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

Это теория в общем случае.

На практике, и в случае с USB, я вижу, что ваше устройство имеет два интерфейса , один из которых - хранилище. Ядро подключится к интерфейсу хранилища всего устройства. Если другой интерфейс имеет правильный класс, usbnetдрайвер может подключиться к нему. Да, вы можете иметь несколько драйверов, подключенных к одному физическому устройству, потому что устройство USB экспортирует несколько интерфейсов (например, моя клавиатура Logitech G15 экспортирует два интерфейса, потому что у нее есть устройство клавиатуры и ЖК-экран, каждый из которых обрабатывается отдельным драйвером) ,

Тот факт, что второй интерфейс вашего USB-устройства не обнаружен, свидетельствует об отсутствии поддержки в ядре. В любом случае, вы можете перечислить интерфейсы / конечные точки устройства с помощью мучительных деталей lsusb -v | less, а затем прокрутить вниз до вашего конкретного устройства (вы можете ограничить вывод по устройству: идентификатор поставщика или путь USB, если вы так склонны).

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

Алексиос
источник
4
Уже есть static struct usb_device_id id_table [] = { { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, { }, }; MODULE_DEVICE_TABLE (usb, id_table);в коде, это избыточно с модалиями?
Томас
В моем случае эти строки автоматически генерируются магией Makefile в любом месте драйвера. Вот почему я добавил три раза строки для MODULE_ALIAS, но он никогда не появляется в списке. В любом случае спасибо за lsusb -v. с этим я мог проверить это и найти недостаток в моей идее. Затем я искал источник для известного идентификатора и нашел массив с записями, которыми мне пришлось манипулировать.
JackGrinningCat