(Linux) Получить /dev/input/eventX с подключенного USB-устройства с PID:VID

Так что мой демон будет сидеть там и слушать udev, ожидая событий подключения/отключения, чтобы он мог уведомить другой поток о присоединении или прекращении чтения из файла /dev/input/eventX.

По сути, он прослушивает USB-сканер RFID, подключенный к локальной системе (который эмулирует клавиатуру HID).

Теперь у меня есть код чтения /dev/input/eventX, но так как я загрузил его, поток UDEV падает.

Как лучше всего получить правильное устройство /dev/input/eventX с известного USB-устройства (например, VID:PID)?


person Litch    schedule 07.10.2011    source источник


Ответы (3)


Вы можете добавить правило udev, которое либо запускает сценарий для уведомления вашей программы, либо дает вам символическую ссылку на устройство с предсказуемым именем. Быстрый поиск обнаружил эту страницу, объясняющую, как создавать правила.

person Dmitri    schedule 07.10.2011
comment
Это именно то, что я сделал в той же ситуации - правило udevd для создания символической ссылки на устройство события, если VID:PID правильный. - person caf; 07.10.2011

Ну, сбой кода был результатом чего-то совершенно другого (vfprintf против fprintf) - в любом случае libudev с версии 172 имеет изящную маленькую функцию, которая при перечислении устройств автоматически привязывает поиск (перечисление) к одному родителю и возвращает только это дети:

udev_enumerate_add_match_parent()

Я уже написал код, который находит устройство hidraw по VID/PID:

/sys/devices/pci000xyz/000.000.XYZ/usbX/X-Y

И я просто жду, когда эта версия udev станет упорядоченной с Ubuntu Natty, потому что тогда я просто создам новое перечисление и передам ему udev_device, который я нашел в предыдущем перечислении, и получу все его дочерние элементы; Включая дочернее устройство, которое мне нужно:

/sys/devices/pci000xyz/000.000.XYZ/usbX/X-Y/X-Y:A.B/input/inputX/eventY

А пока сделаю как предложили и создам симлинк - ура Дмитрий.

person Litch    schedule 08.10.2011

Посмотрите на этот файл: /proc/bus/input/devices

Пример строки из файла:

I: Bus=0003 Vendor=1a2c Product=0c23 Version=0110
N: Name="USB USB Keyboard"
P: Phys=usb-0000:00:14.0-3/input0
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0/0003:1A2C:0C23.0015/input/input30
U: Uniq=
H: Handlers=sysrq kbd event10 
B: PROP=0
B: EV=120013
B: KEY=1000000000007 ff800000000007ff febeffdff3cfffff fffffffffffffffe
B: MSC=10
B: LED=7 

Эта функция получает номер события от устройства с соответствующим VID:PID:

#include <string>
#include <iostream>
#include <fstream>

void open_device (std::string device_vid, std::string device_pid)
{       
    try
    {
        std::ifstream file_input;
        std::size_t pos;
        std::string device_path, current_line, search_str, event_str;
        std::string device_list_file = "/proc/bus/input/devices";
        bool vid_pid_found = false;
        int fd = 0;
        bool debug = true;

        // 1. open device list file
        file_input.open(device_list_file.c_str());
        if (!file_input.is_open())
        {
            std::cerr << "file_input.open >> " << std::strerror(errno) << std::endl;
            throw -2;
        }

        // 2. search for first VID:PID and get event number
        search_str = "Vendor=" + device_vid + " Product=" + device_pid;
        while (getline(file_input, current_line))
        {
            if (!vid_pid_found)
            {
                pos = current_line.find(search_str, 0);
                if (pos != std::string::npos)
                {
                    vid_pid_found = true;
                    search_str = "event";
                }               
            }
            else
            {
                pos = current_line.find(search_str, 0);
                if (pos != std::string::npos)
                {
                    event_str = current_line.substr(pos);
                    // remove spaces from string
                    event_str.erase(std::remove(event_str.begin(), event_str.end(), ' '), event_str.end());
                    break;
                }
            }
        }

        // 3.  build device path
        device_path = "/dev/input/" + event_str;
        if (debug) std::cout << "device_path = " << device_path << std::endl;   
        // 4.  connect to device
        fd = open (device_path.c_str(), O_RDONLY);
        if (fd < 0)
        {
            std::cerr << "open >> errno = " << std::strerror(errno) << std::endl;       
            throw -3;
        }
    }
    catch (const std::exception &e)
    {
        std::cerr << "e.what() = " << e.what() << std::endl;
        throw -1;
    }

    return;
}

События нумеруются по мере их подключения. ls /dev/input до и после отключения USB-устройства будут отображаться разные результаты.

person xinthose    schedule 02.07.2016