Estou usando uma placa PCI proprietária da Sensoray na minha máquina Ubunut 14.04 (pretendo atualizar para a versão 18.04 em breve). A placa vem com o código fonte para o driver e um Makefile para construir e instalar o driver. A parte do Makefile relevante para o driver está aqui:
######################################################################
# for kernel modeule level driver:
# Kernel directory
KDIR := /lib/modules/$(shell uname -r)/build
# Module directory
MODDIR := /lib/modules/$(shell uname -r)/kernel/drivers/sensoray
# System values
PWD := $(shell pwd)
KERNEL_24 := $(if $(wildcard $(KDIR)/Rules.make),1,0)
# Target file
obj-m := s626.o
# Source files
ifeq ($(KERNEL_24),0) # > 2.4
s626-objs := s626drv.o
else # <= 2.4
s626-objs := s626drv.o
endif
.PHONY: all clean modules_install
ifeq ($(KERNEL_24),0) # > 2.4
ifeq ($(KERNELRELEASE),)
all:
$(MAKE) -C $(KDIR) M=$(PWD) SUBDIRS=$(PWD)
clean modules_install:
$(MAKE) -C $(KDIR) M=$(PWD) SUBDIRS=$(PWD) $@
endif # KERNELRELEASE
else # <= 2.4
ifneq ($(KERNELRELEASE),)
include $(KDIR)/Rules.make
s626.o: $(s626-objs)
$(Q)$(LD) $(LD_RFLAG) -r -o $@ $(s626-objs)
else
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -f *.ko *.o .*.cmd .*.o.flags *.mod.c
endif # KERNELRELEASE
endif # KERNEL_24
ifeq ($(KERNEL_24),1) # <= 2.4
install: s626.o
@if [ -d /lib/modules/$(shell uname -r)/kernel/drivers/sensoray/ ];\
then rm -f /lib/modules/$(shell uname -r)/kernel/drivers/sensoray/s626.*;\
fi
@if [ -d /lib/modules/$(shell uname -r)/extra/ ];\
then rm -f /lib/modules/$(shell uname -r)/extra/s626.*;\
fi
su -c "set -x;./MAKEDEV;mkdir -p $(MODDIR);cp -v s626.o $(MODDIR);depmod -a"
else
install: s626.ko
@if [ -d /lib/modules/$(shell uname -r)/kernel/drivers/sensoray/ ];\
then rm -f /lib/modules/$(shell uname -r)/kernel/drivers/sensoray/s626.*; \
fi
@if [ -d /lib/modules/$(shell uname -r)/extra/ ];\
then rm -f /lib/modules/$(shell uname -r)/extra/s626.*;\
fi
@if [ -d /lib/modules/$(shell uname -r)/kernel/drivers/staging/comedi/drivers ];\
then rm -f /lib/modules/$(shell uname -r)/kernel/drivers/staging/comedi/drivers/s626.*;\
fi
su -c "set -x;./MAKEDEV;mkdir -p $(MODDIR);cp -v s626.ko $(MODDIR);install -m 444 s626.ko $(MODDIR);depmod -a"
endif # KERNEL > 2.4
No final do Makefile, parece que uma vez que o arquivo .ko
tenha sido criado, ele simplesmente está sendo copiado para o diretório /lib/modules/$(shell uname -r)/kernel/drivers/sensoray
. Existe um script de shell MAKEDEV customizado que está sendo executado para criar os arquivos do dispositivo. Esse script é dado aqui:
#!/bin/bash
function makedev () {
for dev in 0 1 2 3; do
echo "/dev/$1$dev: char $2 $dev"
rm -f /dev/$1$dev
mknod /dev/$1$dev c $2 $dev
chmod 666 /dev/$1$dev
done
# symlink for default device
rm -f /dev/$1
ln -s /dev/${1}0 /dev/$1
}
makedev s626a 146
O problema é que sempre que o sistema é reinicializado. Parece que o driver é carregado corretamente, mas os arquivos do dispositivo em /dev
desaparecem. Eu não sei muito sobre o desenvolvimento de drivers, mas pesquisei muito sobre esse problema e encontrei informações conflitantes sobre como obter esses arquivos de dispositivo para serem criados no momento da inicialização. Alguns dizem que criar uma regra do udev é melhor, outros dizem que as regras do udev não devem ser usadas para criar arquivos de dispositivos ausentes ou que o udev não é mais responsável pela criação de arquivos de dispositivos referenciando um novo devtempfs. Minha pergunta é: qual é a maneira correta de corrigir esse problema? Eu tentei a abordagem de regra do udev na qual eu essencialmente chamo o script MAKEDEV customizado da Sensoray, mas isso só funciona se a minha regra não faz referência a nenhuma propriedade específica da placa pci. Por exemplo, a seguinte regra funciona:
ACTION=="add", SUBSYSTEM=="pci", RUN+="/home/kpopek/MAKEDEV"
Esta regra não
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x1131", RUN+="/home/kpopek/MAKEDEV"
Parece que não há uevent
no tempo de inicialização correspondente à placa pay da Sensoray, que pode ser a raiz do motivo da falta de arquivos de dispositivos. Eu não descobri como registrar o uevents
no momento da inicialização para verificar isso. Se as regras do udev são a abordagem correta, eu realmente quero uma regra específica para o cartão e não uma regra genérica que execute o script devido a um uevent
de outro dispositivo.