Вопрос или проблема
Я пытаюсь разделить некоторые клавиатуры, чтобы они не читались Qt на Raspberry Pi. Я использую правило udev
для этого, но это, похоже, не работает. Я пытаюсь направить /dev/input/event3
на /dev/input/ccreader
и /dev/input/event4
на /dev/input/barcode
. Можете кто-нибудь подсказать мне, в каком направлении двигаться? Я размещу всю информацию ниже:
Содержимое /etc/udev/rules.d/99-com.rules (ВАЖНО 2 ВВЕРХУ):
KERNEL=="event*", ATTRS{idVendor}=="0801", ATTRS{idProduct}=="0001", MODE:="0660", NAME:="input/ccreader%n"
KERNEL=="event*", ATTRS{idVendor}=="05fe", ATTRS{idProduct}=="1010", MODE:="0660", NAME:="input/barcode%n"
SUBSYSTEM=="input", GROUP="input", MODE="0660"
SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660"
SUBSYSTEM=="spidev", GROUP="spi", MODE="0660"
SUBSYSTEM=="bcm2835-gpiomem", GROUP="gpio", MODE="0660"
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\
chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio;\
chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio;\
chown -R root:gpio /sys$devpath && chmod -R 770 /sys$devpath\
'"
KERNEL=="ttyAMA[01]", PROGRAM="/bin/sh -c '\
ALIASES=/proc/device-tree/aliases; \
if cmp -s $ALIASES/uart0 $ALIASES/serial0; then \
echo 0;\
elif cmp -s $ALIASES/uart0 $ALIASES/serial1; then \
echo 1; \
else \
exit 1; \
fi\
'", SYMLINK+="serial%c"
KERNEL=="ttyS0", PROGRAM="/bin/sh -c '\
ALIASES=/proc/device-tree/aliases; \
if cmp -s $ALIASES/uart1 $ALIASES/serial0; then \
echo 0; \
elif cmp -s $ALIASES/uart1 $ALIASES/serial1; then \
echo 1; \
else \
exit 1; \
fi \
'", SYMLINK+="serial%c"
# udevadm info --attribute-walk --name /dev/input/event4
Udevadm info начинается с устройства, указанного по devpath, а затем
поднимается по цепочке родительских устройств. Он выводит для каждого устройства
найденные, все возможные атрибуты в формате ключей правил udev.
Правило для соответствия может быть составлено из атрибутов устройства
и атрибутов одного родительского устройства.
смотрим на устройство '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/0003:0801:0001.0005/input/input4/event4':
KERNEL=="event4"
SUBSYSTEM=="input"
DRIVER==""
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/0003:0801:0001.0005/input/input4':
KERNELS=="input4"
SUBSYSTEMS=="input"
DRIVERS==""
ATTRS{name}=="HID 0801:0001"
ATTRS{phys}=="usb-3f980000.usb-1.4/input0"
ATTRS{uniq}==""
ATTRS{properties}=="0"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/0003:0801:0001.0005':
KERNELS=="0003:0801:0001.0005"
SUBSYSTEMS=="hid"
DRIVERS=="hid-generic"
ATTRS{country}=="00"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0':
KERNELS=="1-1.4:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="usbhid"
ATTRS{bInterfaceClass}=="03"
ATTRS{bInterfaceSubClass}=="01"
ATTRS{bInterfaceProtocol}=="01"
ATTRS{bNumEndpoints}=="01"
ATTRS{authorized}=="1"
ATTRS{supports_autosuspend}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceNumber}=="00"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4':
KERNELS=="1-1.4"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{devpath}=="1.4"
ATTRS{idVendor}=="0801"
ATTRS{speed}=="12"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{busnum}=="1"
ATTRS{devnum}=="6"
ATTRS{configuration}==""
ATTRS{bMaxPower}=="100mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="80"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="0"
ATTRS{bcdDevice}=="0100"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{version}==" 1.10"
ATTRS{urbnum}=="40"
ATTRS{ltm_capable}=="no"
ATTRS{removable}=="removable"
ATTRS{idProduct}=="0001"
ATTRS{bDeviceClass}=="00"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1/1-1':
KERNELS=="1-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="02"
ATTRS{devpath}=="1"
ATTRS{idVendor}=="0424"
ATTRS{speed}=="480"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{busnum}=="1"
ATTRS{devnum}=="2"
ATTRS{configuration}==""
ATTRS{bMaxPower}=="2mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="e0"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="5"
ATTRS{bcdDevice}=="0200"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{version}==" 2.00"
ATTRS{urbnum}=="72"
ATTRS{ltm_capable}=="no"
ATTRS{removable}=="unknown"
ATTRS{idProduct}=="9514"
ATTRS{bDeviceClass}=="09"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1':
KERNELS=="usb1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="01"
ATTRS{devpath}=="0"
ATTRS{idVendor}=="1d6b"
ATTRS{speed}=="480"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{authorized_default}=="1"
ATTRS{busnum}=="1"
ATTRS{devnum}=="1"
ATTRS{configuration}==""
ATTRS{bMaxPower}=="0mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="e0"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="1"
ATTRS{interface_authorized_default}=="1"
ATTRS{bcdDevice}=="0404"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{serial}=="3f980000.usb"
ATTRS{version}==" 2.00"
ATTRS{urbnum}=="26"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 4.4.26-v7+ dwc_otg_hcd"
ATTRS{removable}=="unknown"
ATTRS{idProduct}=="0002"
ATTRS{bDeviceClass}=="09"
ATTRS{product}=="DWC OTG Controller"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb':
KERNELS=="3f980000.usb"
SUBSYSTEMS=="platform"
DRIVERS=="dwc_otg"
ATTRS{hnp}=="HstNegScs = 0x0"
ATTRS{srp}=="SesReqScs = 0x1"
ATTRS{regvalue}=="invalid offset"
ATTRS{hsic_connect}=="HSIC Connect = 0x1"
ATTRS{guid}=="GUID = 0x2708a000"
ATTRS{mode}=="Mode = 0x1"
ATTRS{srpcapable}=="SRPCapable = 0x1"
ATTRS{regdump}=="Register Dump"
ATTRS{gpvndctl}=="GPVNDCTL = 0x00000000"
ATTRS{ggpio}=="GGPIO = 0x00000000"
ATTRS{hprt0}=="HPRT0 = 0x00001005"
ATTRS{wr_reg_test}=="Time to write GNPTXFSIZ reg 10000000 times: 380 msecs (38 jiffies)"
ATTRS{driver_override}=="(null)"
ATTRS{hcd_frrem}=="HCD Dump Frame Remaining"
ATTRS{mode_ch_tim_en}=="Mode Change Ready Timer Enable = 0x0"
ATTRS{gnptxfsiz}=="GNPTXFSIZ = 0x01000306"
ATTRS{remote_wakeup}=="Remote Wakeup Sig = 0 Enabled = 0 LPM Remote Wakeup = 0"
ATTRS{busconnected}=="Bus Connected = 0x1"
ATTRS{hcddump}=="HCD Dump"
ATTRS{gotgctl}=="GOTGCTL = 0x001c0001"
ATTRS{spramdump}=="SPRAM Dump"
ATTRS{grxfsiz}=="GRXFSIZ = 0x00000306"
ATTRS{gsnpsid}=="GSNPSID = 0x4f54280a"
ATTRS{gusbcfg}=="GUSBCFG = 0x20001700"
ATTRS{hptxfsiz}=="HPTXFSIZ = 0x02000406"
ATTRS{devspeed}=="Device Speed = 0x0"
ATTRS{fr_interval}=="Frame Interval = 0x1d4c"
ATTRS{rem_wakeup_pwrdn}==""
ATTRS{bussuspend}=="Bus Suspend = 0x0"
ATTRS{buspower}=="Bus Power = 0x1"
ATTRS{hnpcapable}=="HNPCapable = 0x1"
ATTRS{rd_reg_test}=="Time to read GNPTXFSIZ reg 10000000 times: 940 msecs (94 jiffies)"
ATTRS{enumspeed}=="Device Enumeration Speed = 0x1"
ATTRS{inv_sel_hsic}=="Invert Select HSIC = 0x0"
ATTRS{regoffset}=="0xffffffff"
смотрим на родительское устройство '/devices/platform/soc':
KERNELS=="soc"
SUBSYSTEMS=="platform"
DRIVERS==""
ATTRS{driver_override}=="(null)"
смотрим на родительское устройство '/devices/platform':
KERNELS=="platform"
SUBSYSTEMS==""
DRIVERS==""
# udevadm info --attribute-walk --name /dev/input/event3
Udevadm info начинается с устройства, указанного по devpath, а затем
поднимается по цепочке родительских устройств. Он выводит для каждого устройства
найденные, все возможные атрибуты в формате ключей правил udev.
Правило для соответствия может быть составлено из атрибутов устройства
и атрибутов одного родительского устройства.
смотрим на устройство '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3/1-1.3:1.0/0003:05FE:1010.0004/input/input3/event3':
KERNEL=="event3"
SUBSYSTEM=="input"
DRIVER==""
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3/1-1.3:1.0/0003:05FE:1010.0004/input/input3':
KERNELS=="input3"
SUBSYSTEMS=="input"
DRIVERS==""
ATTRS{name}=="WIT Electron Company WIT 122-UFS V7.03"
ATTRS{phys}=="usb-3f980000.usb-1.3/input0"
ATTRS{uniq}==""
ATTRS{properties}=="0"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3/1-1.3:1.0/0003:05FE:1010.0004':
KERNELS=="0003:05FE:1010.0004"
SUBSYSTEMS=="hid"
DRIVERS=="hid-generic"
ATTRS{country}=="21"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3/1-1.3:1.0':
KERNELS=="1-1.3:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="usbhid"
ATTRS{bInterfaceClass}=="03"
ATTRS{bInterfaceSubClass}=="01"
ATTRS{bInterfaceProtocol}=="01"
ATTRS{bNumEndpoints}=="01"
ATTRS{authorized}=="1"
ATTRS{supports_autosuspend}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceNumber}=="00"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3':
KERNELS=="1-1.3"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{devpath}=="1.3"
ATTRS{idVendor}=="05fe"
ATTRS{speed}=="1.5"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{busnum}=="1"
ATTRS{devnum}=="5"
ATTRS{configuration}==""
ATTRS{bMaxPower}=="500mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="a0"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="0"
ATTRS{bcdDevice}=="0001"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{version}==" 1.10"
ATTRS{urbnum}=="13"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="WIT Electron Company"
ATTRS{removable}=="removable"
ATTRS{idProduct}=="1010"
ATTRS{bDeviceClass}=="00"
ATTRS{product}=="WIT 122-UFS V7.03"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1/1-1':
KERNELS=="1-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="02"
ATTRS{devpath}=="1"
ATTRS{idVendor}=="0424"
ATTRS{speed}=="480"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{busnum}=="1"
ATTRS{devnum}=="2"
ATTRS{configuration}==""
ATTRS{bMaxPower}=="2mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="e0"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="5"
ATTRS{bcdDevice}=="0200"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{version}==" 2.00"
ATTRS{urbnum}=="72"
ATTRS{ltm_capable}=="no"
ATTRS{removable}=="unknown"
ATTRS{idProduct}=="9514"
ATTRS{bDeviceClass}=="09"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb/usb1':
KERNELS=="usb1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="01"
ATTRS{devpath}=="0"
ATTRS{idVendor}=="1d6b"
ATTRS{speed}=="480"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{authorized_default}=="1"
ATTRS{busnum}=="1"
ATTRS{devnum}=="1"
ATTRS{configuration}==""
ATTRS{bMaxPower}=="0mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="e0"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="1"
ATTRS{interface_authorized_default}=="1"
ATTRS{bcdDevice}=="0404"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{serial}=="3f980000.usb"
ATTRS{version}==" 2.00"
ATTRS{urbnum}=="26"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 4.4.26-v7+ dwc_otg_hcd"
ATTRS{removable}=="unknown"
ATTRS{idProduct}=="0002"
ATTRS{bDeviceClass}=="09"
ATTRS{product}=="DWC OTG Controller"
смотрим на родительское устройство '/devices/platform/soc/3f980000.usb':
KERNELS=="3f980000.usb"
SUBSYSTEMS=="platform"
DRIVERS=="dwc_otg"
ATTRS{hnp}=="HstNegScs = 0x0"
ATTRS{srp}=="SesReqScs = 0x1"
ATTRS{regvalue}=="invalid offset"
ATTRS{hsic_connect}=="HSIC Connect = 0x1"
ATTRS{guid}=="GUID = 0x2708a000"
ATTRS{mode}=="Mode = 0x1"
ATTRS{srpcapable}=="SRPCapable = 0x1"
ATTRS{regdump}=="Register Dump"
ATTRS{gpvndctl}=="GPVNDCTL = 0x00000000"
ATTRS{ggpio}=="GGPIO = 0x00000000"
ATTRS{hprt0}=="HPRT0 = 0x00001005"
ATTRS{wr_reg_test}=="Time to write GNPTXFSIZ reg 10000000 times: 360 msecs (36 jiffies)"
ATTRS{driver_override}=="(null)"
ATTRS{hcd_frrem}=="HCD Dump Frame Remaining"
ATTRS{mode_ch_tim_en}=="Mode Change Ready Timer Enable = 0x0"
ATTRS{gnptxfsiz}=="GNPTXFSIZ = 0x01000306"
ATTRS{remote_wakeup}=="Remote Wakeup Sig = 0 Enabled = 0 LPM Remote Wakeup = 0"
ATTRS{busconnected}=="Bus Connected = 0x1"
ATTRS{hcddump}=="HCD Dump"
ATTRS{gotgctl}=="GOTGCTL = 0x001c0001"
ATTRS{spramdump}=="SPRAM Dump"
ATTRS{grxfsiz}=="GRXFSIZ = 0x00000306"
ATTRS{gsnpsid}=="GSNPSID = 0x4f54280a"
ATTRS{gusbcfg}=="GUSBCFG = 0x20001700"
ATTRS{hptxfsiz}=="HPTXFSIZ = 0x02000406"
ATTRS{devspeed}=="Device Speed = 0x0"
ATTRS{fr_interval}=="Frame Interval = 0x1d4c"
ATTRS{rem_wakeup_pwrdn}==""
ATTRS{bussuspend}=="Bus Suspend = 0x0"
ATTRS{buspower}=="Bus Power = 0x1"
ATTRS{hnpcapable}=="HNPCapable = 0x1"
ATTRS{rd_reg_test}=="Time to read GNPTXFSIZ reg 10000000 times: 920 msecs (92 jiffies)"
ATTRS{enumspeed}=="Device Enumeration Speed = 0x1"
ATTRS{inv_sel_hsic}=="Invert Select HSIC = 0x0"
ATTRS{regoffset}=="0xffffffff"
смотрим на родительское устройство '/devices/platform/soc':
KERNELS=="soc"
SUBSYSTEMS=="platform"
DRIVERS==""
ATTRS{driver_override}=="(null)"
смотрим на родительское устройство '/devices/platform':
KERNELS=="platform"
SUBSYSTEMS==""
DRIVERS==""
Если кажется, что ваше правило игнорируется, вы можете попробовать полную перезагрузку. udevadm control --reload
не всегда работает (спасибо systemd).
systemctl force-reload udev systemd-udevd-control.socket systemd-udevd-kernel.socket
Ответ или решение
Проблемы с работой правил udev на Raspberry Pi 3: Введение и решения
Если вы столкнулись с тем, что ваши правила udev не работают на Raspberry Pi 3, это может быть связано с несколькими факторами. В этом руководстве мы рассмотрим основные причины, которые могут вызвать проблемы, а также предложим шаги для диагностики и решения проблемы.
1. Понимание правил udev
Понимание того, как работают правила udev, является ключом к их успешному применению. Правила описывают, как обрабатывать устройства при их подключении к системе. В вашем случае вы пытаетесь перенаправить потоки ввода от двух клавиатур в определенные устройства: /dev/input/ccreader
и /dev/input/barcode
.
2. Проверка файла правил
Ваши правила, согласно приведенному коду, имеют следующий вид:
KERNEL=="event*", ATTRS{idVendor}=="0801", ATTRS{idProduct}=="0001", MODE:="0660", NAME:="input/ccreader%n"
KERNEL=="event*", ATTRS{idVendor}=="05fe", ATTRS{idProduct}=="1010", MODE:="0660", NAME:="input/barcode%n"
Эти правила должны быть корректными, учитывая, что они ссылаются на атрибуты idVendor
и idProduct
указанных устройств.
3. Проверка атрибутов с помощью udevadm
Вы уже выполнили команду udevadm info --attribute-walk
для проверки атрибутов. Убедитесь, что значения idVendor
и idProduct
совпадают с теми, которые вы указали в правилах. Например, для клавиатуры с идентификатором 0801:0001
вы должны видеть соответствующий ATTRS{idVendor}
и ATTRS{idProduct}
. Если они не совпадают, ваши правила будут проигнорированы.
4. Перезагрузка udev
Если вы внесли какие-либо изменения в файл правил, вам необходимо перезагрузить udev
. Использование простой команды перезагрузки udevadm control --reload
может не всегда сработать на системах с systemd. Вместо этого попробуйте:
systemctl force-reload udev systemd-udevd-control.socket systemd-udevd-kernel.socket
Эта команда обеспечивает более полную перезагрузку службы udev.
5. Проверка журналов
Проверьте логи системы на наличие сообщений, связанных с udev. Для этого используйте следующую команду:
journalctl -xe | grep udev
Логи могут предоставить полезную информацию о том, что происходит, когда устройство подключается, и могли ли возникнуть ошибки при применении правил.
6. Отладка правил
Для отладки правил вы можете добавить в ваши правила временные команды, такие как RUN+="/bin/sh -c 'echo NEW_DEVICE > /tmp/device_created'"
. Это поможет вам убедиться, что правило действительно применяется, и даст возможность увидеть, сработали ли ваши условия.
7. Проверка прав доступа
Убедитесь, что вы имеете необходимые права доступа к устройствам /dev/input/ccreader
и /dev/input/barcode
. Команды MODE:="0660"
и GROUP="input"
означают, что вам нужно быть частью группы input
для доступа к устройствам.
Заключение
Решение проблемы с неработающим правилом udev на Raspberry Pi 3 может потребовать внимание к деталям и несколько этапов проверки. Сосредоточив внимание на атрибутах устройства, перезагрузке сервиса и прослушивании логов, вы сможете выявить и устранить основные причины проблем. Если все вышеперечисленные шаги не помогут, рассмотреть возможность создания уникальных атрибутов для каждого устройства, например, с использованием ATTRS{name}
, чтобы избежать конфликтов.