понеділок, 23 січня 2012 р.

Linux HCL - USB поддерживаемое оборудование

Статья является продолжением статьи Linux HCL - поддерживаемое оборудование
Опишу мытарства с USB "device".

Сначала по своей наивности я подумал, что определять USB устройства будет проще, чем "PCI device". Как же я жестоко ошибался!

Для USB устройств существует файл modules.usbmap, который чуток имеет другую структуру нежели module.pcimap. Относительно быстро добавил на сайте разбор отчёта devcon для анализа USB. Но всё на сайте начало пестреть "красным", так как процент "найденных" устройств был низок. Сразу стало понятно, что одним modules.usbmap не отделаться.

Я решил добавить базу понимаемых USB устройств от Udev. Udev в современных дистрибутивах заменил HAL и занимается оборудованием. Стоит воткнуть любое USB устройство и Udev начнёт применять правила, исходя из идентификатора производителя и устройства. Естественно, сначала ядро Линукс должно определить устройство, а потом уже будут срабатывать правила Udev. Но я рассудил так: раз есть правило Udev на некоторое устройство, то значит устройство работает в Линукс! Ну кто делает правила для не работающих железяк?

В правилах Udev упоминания об идентификаторах выглядит так:

ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="002a"
В данном примере, правило сработает если производитель будет равен (Hewlett-Packard), а продукт равен 002a (LaserJet P1102). Описания производителей и устройств USB следует брать из файла usb.ids.

Правила Udev быстро парсить не получилось. Нужные поля ATTRS{idVendor} ATTRS{idProduct} располагались в произвольных местах на строке и/или между ними были другие атрибуты ATTRS. Пришлось писать на AWK скрипт, который вытащит нужное и подготовит структурированный файл для БД.

awk -F',' ' {
    { printf "%s ", $1;
    for(i=1;i<=NF;i++)
    {
        if(index($i, "ATTRS{idVendor}") !=0 )
        {sub(/ATTRS{idVendor}==\"/,"", $i);
        sub(/\"/,"", $i);
        printf "%s ",$i;
        }
        if(index($i, "ATTRS{idProduct}") !=0 )
        {sub(/ATTRS{idProduct}==\"/,"", $i);
        sub(/\"/,"", $i);
        printf "%s ",$i;
        }
    }
    printf "\n";    }}' udev.sql  > udev2.sql

Чуть позже решил дополнить базу данных правила SANE, проекта, который занимается сканерами. Лучше SANE никто не скажет - хорош данный сканер в линуксе или нет. Сказано - сделано. Нашёл файлы в sane-backends/doc/descriptions, которые хранят нужное и загнал в базу. Этими файлами, кстати пользуется сам проект SANE на своём веб-сайте, о чём у них об этом написано и даже есть исходники веб-сайта и его скриптов.

По аналогии со сканерами, решил занести в базу информацию о принтерах. Начал ковырять CUPS, так как он в современных дистрибутивах занимается принтерами, но обломался с разбегу. Решил пока отложить CUPS.

Существует такой проект LKKDB, который парсит исходники ядра линукса. Я пока полностью не разобрался со скриптами и логикой работы, но сразу решил воспользоваться файлом lkddb.list для пополнения своей базы.

В lkddb.list кроме дополнительных идентификаторов, которые улучшили определяемость USB устройств, нашёл поля hid (human interface device - класс устройств USB для взаимодействия с человеком), которые так же улучшили определимость устройств.

Из lkddb.list стало ясно, что если поиск по идентификаторам не увенчался успехом, то нужно обратить внимание на класс устройства USB.
Классом 03 (Human Interface Device) занимается модуль из исходника drivers/hid/usbhid/hid-core.c.
Классом 05 (Physical Interface Device) занимается модуль из исходника net/bluetooth/hidp/core.c
Это в разы улучшило БЫ определяемость, но вначале я не парсил класс устройства USB.

Объясню почему. Сравните!
PCI device

PCI\VEN_8086&DEV_29C0&CC_0600

на одной строке и производитель VEN 8086 (Intel) и устройство DEV 29C0 (82G33/G31/P35/P31 Express DRAM Controller) и класс устройства CC 0600 (Bridge). Парсить не сложно и этим занимается регулярное выражение

VEN_(?P[A-Z0-9]+)&DEV_(?P[A-Z0-9]+)&CC_(?P[0-9A-Z]{4})$

а теперь USB! Нужная информация располагается на нескольких строках. Производитель Vid и устройство Pid на одной строке, а Class (может быть и DevClass) на строке через одну.

    USB\Vid_057b&Pid_0000
Compatible ID's:
    USB\Class_08&SubClass_04&Prot_00

Пришлось радикально переписывать PHP код парсинга USB устройства, ради того чтобы знать класс устройства. Ну что делать .. переписать, так переписать.
Регулярное выражение вынесло мне мозг.

USB\\\\Vid_(?P[A-Za-z0-9]+)&Pid_(?P[A-Za-z0-9]+)[ A-Za-z\'\:\\\\]+_(?P[0-9][0-9])

Добавил так же базу из исходников линукса, выдранные собственными скриптами, но пока толку от неё мало, судя по логам. Сделал "шоб былО". В исходниках ядра линукс при работе с USB устройствами упоминается конструкция USB_DEVICE(). Ищем, парсим, меняем значения переменных на значения.

Не дописано ... ожидайте

Немає коментарів:

Дописати коментар

HyperComments for Blogger

comments powered by HyperComments