Udev, динамична инициализация на периферия

From Ilianko


inodes

В UNIX базирани операционни системи за връзка на системно ниво между периферните устройствата и програмните приложения се използва същия похват, както се достъпват файлове. Всеки файл се описва със структура наречена inode (index node - индекс на нод, нод - възел или част от цялата система). Файловете (inodes), които съответстват на хардуера са разположение в директорият /dev. Всеки inode сочи към някаква част от компютърната система – устройство, което може да съществува реално или да е виртуално. Например приложението, което управлява прозорците, следи постоянно състоянието на устройството /dev/input/mice, за да може да предаде движението на мишката към курсора на монитора.

При включване на мишката, тя се инициализира и се представя като файл в директорията /dev/input/mouseX. Могат да се поддържат няколко мишки едновременно, като устройството /dev/input/mice се явява събирателно за генерираните събития от всички мишки.

Инициализирането на мишката (управление на нодовете) в Linux с ядро 2.6 по подразбиране се извършва от системата udev . За разлика от традиционната UNIX система, където всички устройства са статични, т.е. веднъж инициализирани при стартиране на компютъра, вече не могат да се променят, програмата udevd ( udev демон) следи за събития за добавен хардуер. При получаване на такова събитие от ядрото на операционната система, udevd стартира инициализиране на новия хардуер.

За администриране на инициализираните устройства може да се ползва udevadm. Примерно за да видим обща информация за мишката ще използваме командата със следния синтаксис:

$udevadm info --query all  --name=/dev/input/mouse1

За повече информация относно командата изпълнете

$man udevadm.

Системата udev позволява да се правят специфични настройки и да се предприемат специфични действия при включването на дадено хардуерно устройство. Това става със задаване на правилата, за съществуването на които се проверя в директория /etc/udev/rules.d при всяко включване на хардуер. Устройство, за което се създават правила се индентифицира по неговите атрибути. За да видим атрибутите на мишката, с които се представя пред операционната системата може да се използва:

$udevadm info --attribute-walk --name=/dev/input/mouse1

Изведената информация започва с реалния път към устройството, което се намира в директория /sys. Следва информацията за самото устройство и за всички устройства, на които е подчинено. Началото на резултата от горната команда би изглеждал така:

...'/devices/pci0000:00/0000:00:1d.0/usb6/6-2/6-2:1.0/input/input11/mouse1': 
    KERNEL=="mouse1" 
    SUBSYSTEM=="input" 
    DRIVER=="" ...

Задаване на правила при инициализация на USB устройство

Може да използваме атрибутите на хардуерното устройство, за да го идентифицираме пред операционната система, с което ще могат да се зададат специални правила при неговата инициализация. В случая с мишката, може да вземем наименованието и физическото място, където е включена мишката. Примерно:

$udevadm info --attribute-walk --name=/dev/input/mouse1
   ...
   ATTRS{name}=="Logitech USB Optical Mouse" 
   ATTRS{phys}=="usb-0000:00:1d.0-2/input0" 
   ...

Дадените стойности зависят от модела на мишката и USB порта на включване. Правилото се описва с файл в директория

/etc/udev/rules.d

със следния формат на името xx-ime.rules, където:

  • xx – приоритет на изпълнение, първо ще се изпълнят правилата с по-малка стойност;
  • ime – произволно име;
  • .rules – задължително разширение.

С цел да разглеждаме информацията пристигаща от мишката, без тя да се предава към системата управляваща прозорците на операционната система, ще дадем ръчно наименование на нода, с който мишката ще бъде представена в /dev.

Създава се файл със следното съдържание:

SUBSYSTEMS=="input", ATTRS{name}=="Logitech USB Optical Mouse", NAME="testMouse"

Файлът се записва в /etc/udev/rules.d с име в съответствие с формата xx-ime.rules. Ако мишката е с USB интерфейс, след изключване и включване, тя вече няма да управлява курсора и ще можем да видим новосъздадено устройство /dev/testMouse. Може да тестваме дали мишката работи, като четем това устройство -

$cat /dev/testMouse.

Програмен достъп на мишка

Когато се уверим, че мишката работи, може да разкодираме необработената информация постъпваща от мишката с помощта на системната библиотеката <input.h>. Тя е предназначена за управление на входящи устройства като клавиатури, сензорни екрани, джойстици и мишки. По-долу е дадена структура от <input.h> описваща събитията генерирани от тези устройства.

struct input_event { 
  struct timeval time; 
  __u16 type;    // Вида на събитието
  __u16 code;   // Подвид на събитието 
  __s32 value;  // Стойност на събитието
};

За управление на събитията от мишка се използват следните стойности на полета:

  • за отместване
    • input_event.type = EV_REL - отместване на мишката
    • input_event.code = REL_X /REL_Y – по Х или Y
    • input_event.value = n – стойност на отместването
  • за натиснат бутон
    • input_event.type = EV_KEY - отместване на мишката
    • input_event.code = BTN_LEF, BTN_RIGHT ...
    • input_event.value = 0, 1, 2 – състояние на бутона.

Примерен код за извеждане на всички събития от мишката:

#include <linux/input.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv) {
  int fd; // показател към файла на мишката
  struct input_event ev; // 
  
  //отваряне файла на мишката
  if ((fd = open("/dev/testMouse", O_RDONLY)) < 0) { 
    perror("evdev open");
    exit(1);
  }
  while(1) { // визуализиране на данните от мишката
    read(fd, &ev, sizeof(struct input_event));
    printf("value %i, type %d,   code %d\n", ev.value, ev.type, ev.code);
  }
  return 0;
}

Изпълнение на скрипт при инициализация на usb устройство

Kъм правилото на устройството се добавя скрипта за изпълнение RUN+="/root/program". Правилото за изпълнение на скрипта program при включване на мишка, би изглеждало така:

SUBSYSTEMS=="input", ATTRS{name}=="Logitech USB Optical Mouse", NAME="testMouse", RUN+="/root/program"

Трябва да се създаде и скрипта за изпълнение в съответна директория. Създава се текстов файл

nano /root/program

със следното съдържание:

#!/bin/bash
halt

и се променят правата му, за да бъде изпълним

chmod +x /root/program

Литература

http://www.reactivated.net/writing_udev_rules.html