En este artículo voy a detallar los pasos que seguí para actualizar el módulo del lector de tarjetas Omnikey Cardman 2020. Nunca antes había modificado un driver del kernel Linux, no me considero un buen programador y haciendo esto no gano ni gané nada.
Pues bien, los pasos que seguí fueron los siguientes (suponiendo que ya tengamos los kernel-headers de nuestro kernel instalados):
- Bajarse el código fuente.
En la página web de Omnikey, sección Soporte [Support], opción Drivers, podemos descargarnos el código fuente del driver.
El archivo que descargamos se llama cm2020_installer_v2_4_1_src.tar.gz.
- Descomprimir.
Cambiamos al directorio donde hayamos descargado el driver en el paso anterior y lo descomprimimos:
~$ tar xvzf cm2020_installer_v2_4_1_src.tar.gz
- Compilar por primera vez.
Antes de compilar vamos a realizar un pequeño cambio en el archivo "install". Este archivo tiene un error y si no realizamos este cambio nos sobreescribirá el script de inicio de pcscd, y con este nuevo archivo a mí no me ha funcionado. Como supongo que pcscd viene empaquetado para la mayoría (si no todas) de las distribuciones, no veo necesario que se compile e instale a partir del código fuente que viene con este driver que acabamos de descargar.
~$ cp install install.old
~$ vi install
~$ diff -u install.old install
--- install.old 2006-08-16 10:14:29.000000000 +0200
+++ install 2006-08-16 10:10:20.000000000 +0200
@@ -231,7 +231,7 @@
echo OK
fi
mkdir -p /usr/local/pcsc/drivers
-fi #if [ $nopcscd = 0 ];
+#fi #if [ $nopcscd = 0 ];
#
# make initscript
#
@@ -565,7 +565,7 @@
fi
-#fi #if [ $nopcscd = 0 ];
+fi #if [ $nopcscd = 0 ];
#
# copy the pcsc-shared library to its proper place
Como vemos el cambio consiste en comentar la línea 234 y descomentar la línea 568.
Hecho este cambio procedemos a compilar. Para ello nos advierte que debemos ejecutar el script como root, por lo que deberemos cambiar a root o ejecutar el script mediante sudo:
~$ sudo sh ./install --nopcscd
Password:
Installing OMNIKEY Cardman USB Smartcard reader...
Distribution is debian
Found PCSC version 1.3.1 in /usr/sbin/pcscd
/usr/lib/pcsc/drivers/
The kernel module for 2.6.16-2-686 isn't prebuilt!
Try to compile it for you!
rm -f *.o 2>/dev/null
rm -f *.ko 2>/dev/null
rm -f cardman.mod* 2>/dev/null
make -C /lib/modules/2.6.16-2-686/build SUBDIRS=/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020 modules
make[1]: se ingresa al directorio `/usr/src/linux-headers-2.6.16-2-686'
CC [M] /home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.o
make[1]: se sale del directorio `/usr/src/linux-headers-2.6.16-2-686'
Couldn't build kernel module.
Compile it by yourself or
contact OMNIKEY for further details.
(e-mail: support.linux@omnikey.com)
Primer intento fallido, pero nos dice que tratemos de compilarlo por nosotros mismos (y es lo que vamos a hacer, ya que no nos indica el error por el cuál ha fallado la compilación).
~$ cd src/cm2020
~$ make
make -C /lib/modules/2.6.16-2-686/build SUBDIRS=/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020 modules
make[1]: se ingresa al directorio `/usr/src/linux-headers-2.6.16-2-686'
CC [M] /home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.o
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:168: error: unknown field 'mode' specified in initializer
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:175: error: unknown field 'owner' specified in initializer
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:175: warning: initialization from incompatible pointer type
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c: In function 'cmu_read':
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1442: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c: In function 'cmu_write':
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1540: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c: In function 'cmu_ioctl':
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1778: warning: implicit declaration of function 'verify_area'
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1829: warning: passing argument 1 of 'copy_to_user' makes pointer from integer without a cast
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1953: warning: passing argument 2 of 'copy_from_user' makes pointer from integer without a cast
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:2008: warning: passing argument 2 of 'copy_from_user' makes pointer from integer without a cast
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1829: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1842: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1942: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1943: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1944: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1945: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1953: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:2008: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c: At top level:
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:2565: fatal error: opening dependency file /home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/.cardman.o.d: Permiso denegado
compilation terminated.
make[2]: *** [/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.o] Error 1
make[1]: *** [_module_/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020] Error 2
make[1]: se sale del directorio `/usr/src/linux-headers-2.6.16-2-686'
make: *** [default] Error 2
Buf! Muchos errores, así que vamos a pasar al siguiente punto.
- ¿Dónde buscar?
Cabe aclarar que este mismo driver lo estaba utilizando en el kernel 2.6.12, funcionando correctamente. Así que al cambiar a un kernel posterior y no poder compilar el driver supuse que sería por cambios en el kernel (cuando modifiqué el driver yo utilizaba un kernel 2.6.15). Solamente tenía que buscar una página donde explicasen los cambios que había sufrido el kernel en sucesivas versiones. La solución se encuentra en dos páginas principalmente: Kernel Newbies y en LWN.net. En la primera (Kernel Newbies) explican los cambios de una manera más comprensible, aunque solamente de la última release del kernel. Es un buen punto de partida si utilizas la última versión del kernel. Como no es mi caso busqué en la segunda página (LWN).
Además, podemos echarle un vistazo al código fuente del kernel (o a sus cabeceras).
- Arreglando errores.
El primer error que aparece es el siguiente:
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:168: error: unknown field 'mode' specified in initializer
Este error no pude localizarlo en los cambios del API de la páginas anteriormente citadas. Así que hice una búsqueda con la herramienta de la página con las siguientes palabras: "usb_class_driver mode field". Solamente apareció un resultado: 2.6.15-rc1 short log, y buscando "mode field" en la página encontramos lo siguiente:
devfs: Remove the mode field from usb_class_driver as it's no longer needed
Como dice el mensaje, a partir del kernel 2.6.15 ya no se utilizará este campo. Así que lo comentamos de la siguiente manera:
~$ vi cardman.c
~$ diff -u cardman.c.old cardman.c
--- cardman.c.old 2006-08-16 10:55:03.000000000 +0200
+++ cardman.c 2006-08-16 10:56:07.000000000 +0200
@@ -165,7 +165,9 @@
static struct usb_class_driver cmu_class = {
.name= "usb/cm%d",
.fops= &cmu_fops,
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
.mode= S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+ #endif
.minor_base= CM2020_MINOR,
};
#endif
Las líneas añadidas son para que solamente añada ese campo si la version del kernel es menor que la versión 2.6.15. Esto tampoco sabía cómo se hacía, pero en el mismo archivo cardman.c se utiliza esta sentencia, así que simplemente lo copié y modifiqué.
Si compilamos veremos que el error anterior desaparece (¡PERFECTO!).
Pasamos al siguiente error:
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:175: error: unknown field 'owner' specified in initializer
Buscamos la palabra owner en la página de cambios en el kernel (LWN). En ella encontramos lo siguiente en la sección correspondiente al kernel 2.6.16:
The usb_driver structure has a new field (no_dynamic_id) which lets a driver disable the addition of dynamic device IDs. The owner field has also been removed from this structure.
Así que editamos el archivo cardman.c de la siguiente forma:
~$ vi cardman.c
~$ diff -u cardman.c.old cardman.c
--- cardman.c.old 2006-08-16 10:55:03.000000000 +0200
+++ cardman.c 2006-08-16 11:06:14.000000000 +0200
@@ -165,13 +165,15 @@
static struct usb_class_driver cmu_class = {
.name= "usb/cm%d",
.fops= &cmu_fops,
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
.mode= S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+ #endif
.minor_base= CM2020_MINOR,
};
#endif
STATIC struct usb_driver cmu_driver = {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
.owner= THIS_MODULE,
#endif
.name= "cardman",
En esta ocasión añadimos una segunda comprobación a la que ya se tenía (versión del kernel 2.4.20), por lo que deduzco que este campo se añadió a partir de esa versión y ahora se ha eliminado.
Si compilamos, podemos comprobar que en esta ocasión la compilación termina, obteniendo el archivo "cardman.ko":
~$ make
make -C /lib/modules/2.6.16-2-686/build SUBDIRS=/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020 modules
make[1]: se ingresa al directorio `/usr/src/linux-headers-2.6.16-2-686'
CC [M] /home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.o
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c: In function 'cmu_read':
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1444: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c: In function 'cmu_write':
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1542: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c: In function 'cmu_ioctl':
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1780: warning: implicit declaration of function 'verify_area'
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1831: warning: passing argument 1 of 'copy_to_user' makes pointer from integer without a cast
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1955: warning: passing argument 2 of 'copy_from_user' makes pointer from integer without a cast
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:2010: warning: passing argument 2 of 'copy_from_user' makes pointer from integer without a cast
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1831: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1844: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1944: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1945: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1946: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1947: warning: ignoring return value of 'copy_to_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1955: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:2010: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
Building modules, stage 2.
MODPOST
*** Warning: "verify_area" [/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.ko] undefined!
CC /home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.mod.o
LD [M] /home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.ko
make[1]: se sale del directorio `/usr/src/linux-headers-2.6.16-2-686'
Pero este módulo no funciona, y nos da el error de que verify_area no está definido. Indagando en los warning que nos da la compilación (que no errores) vemos el siguiente mensaje:
/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.c:1780: warning: implicit declaration of function 'verify_area'
Es decir, que estamos utilizando una función que no está definida en las cabeceras del kernel. Nuevamente buscamos los cambios efectuados sobre esta función, encontrando el siguiente artículo: Patch: remove verify_area(), donde dice que está deprecado y que se sustituye por access_ok()
. Si buscamos referencias a los valores devueltos por verify_area()
en los headers del kernel:
~$ grep -r "int verify_area(" /usr/src/kernel-headers-2.6.xx/
/usr/src/kernel-headers-2.6.xx/include/asm-i386/uaccess.h:static inline int verify_area(int type, const void __user * addr, unsigned long size)
/usr/src/kernel-headers-2.6.xx/include/asm/uaccess.h:static inline int verify_area(int type, const void __user * addr, unsigned long size)
En cualquiera de estos archivos encontramos el siguiente comentario en la declaración de la función verify_area()
:
/**
* verify_area: - Obsolete, use access_ok()
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
* @addr: User space pointer to start of block to check
* @size: Size of block to check
*
* Context: User context only. This function may sleep.
*
* This function has been replaced by access_ok().
*
* Checks if a pointer to a block of memory in user space is valid.
*
* Returns zero if the memory block may be valid, -EFAULT
* if it is definitely invalid.
*
* See access_ok() for more details.
*/
Como nos dice, vamos a mirar la función access_ok()
para más detalles (se encuentra en el mismo archivo que verify_access()
:
/**
* access_ok: - Checks if a user space pointer is valid
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that
* %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
* to write to a block, it is always safe to read from it.
* @addr: User space pointer to start of block to check
* @size: Size of block to check
*
* Context: User context only. This function may sleep.
*
* Checks if a pointer to a block of memory in user space is valid.
*
* Returns true (nonzero) if the memory block may be valid, false (zero)
* if it is definitely invalid.
*
* Note that, depending on architecture, this function probably just
* checks that the pointer is in the user space range - after calling
* this function, memory access functions may still return -EFAULT.
*/
Resumiendo, verify_access()
devuelve 0 o -EFAULT
, mientras que access_ok()
devuelve true o false. Buscamos referencias a esta función y encontramos que en distintos parches se utiliza de la siguiente forma:
if (!access_ok(VERIFY_WRITE, buf, space))
return -EFAULT;
Así que buscamos dónde utilizamos la función verify_area()
y la modificamos. En este caso no hace falta hacer comprobaciones de la versión del kernel, ya que sobre la función access_ok()
, la primera referencia que he encontrado es en el kernel 2.4.17:
~$ vi cardman.c
~$ diff -u cardman.c.old cardman.c
--- cardman.c.old 2006-08-16 10:55:03.000000000 +0200
+++ cardman.c 2006-08-16 11:44:40.000000000 +0200
@@ -165,13 +165,15 @@
static struct usb_class_driver cmu_class = {
.name= "usb/cm%d",
.fops= &cmu_fops,
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
.mode= S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+ #endif
.minor_base= CM2020_MINOR,
};
#endif
STATIC struct usb_driver cmu_driver = {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
.owner= THIS_MODULE,
#endif
.name= "cardman",
@@ -1775,12 +1777,12 @@
if (_IOC_DIR(cmd)&_IOC_READ) {
DEBUG(5,"ioctl: _ioc_dir=read\n");
if (arg==0) rc=-EFAULT;
- else rc=verify_area(VERIFY_WRITE,(void *)arg,size);
+ else rc=(access_ok(VERIFY_WRITE,(void *)arg,size))?0:-EFAULT;
}
if (_IOC_DIR(cmd)&_IOC_WRITE) {
DEBUG(5,"ioctl: _ioc_dir=write\n");
if (arg==0) rc=-EFAULT;
- else rc=verify_area(VERIFY_READ,(void *)arg,size);
+ else rc=(access_ok(VERIFY_READ,(void *)arg,size))?0:-EFAULT;
}
if (rc) {
DEBUG(4, "<- ioctl (unknown comamnd)\n");
Como en esta función devolvemos el valor de rc, utilizamos una única sentencia para darle el valor 0 (todo OK) o el valor -EFAULT
(error). Ahora ya podemos compilarlo correctamente.
- Compilar e instalar.
Volvemos al directorio donde hayamos descomprimido el driver del lector e instalamos:
~$ sh ./install --nopcscd
Installing OMNIKEY Cardman USB Smartcard reader...
Distribution is debian
Found PCSC version 1.3.1 in /usr/sbin/pcscd
/usr/lib/pcsc/drivers/
The kernel module for 2.6.16-2-686 isn't prebuilt!
Try to compile it for you!
rm -f *.o 2>/dev/null
rm -f *.ko 2>/dev/null
rm -f cardman.mod* 2>/dev/null
make -C /lib/modules/2.6.16-2-686/build SUBDIRS=/home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020 modules
make[1]: se ingresa al directorio `/usr/src/linux-headers-2.6.16-2-686'
CC [M] /home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.o
Building modules, stage 2.
MODPOST
CC /home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.mod.o
LD [M] /home/samba/OVSI/asanchez/download/cm2020_installer_v2_4_1_src/src/cm2020/cardman.ko
make[1]: se sale del directorio `/usr/src/linux-headers-2.6.16-2-686'
Copy cardman.ko to /lib/modules/2.6.16-2-686/kernel/drivers/usb/misc
Create init-script and symlink into runlevels
./install: 840: declare: not found
[: 840: 6: unexpected operator
Attempting to start the cm_usb kernel module
Starting cm_usb
Installation finished
Da un error al ejecutar el script de instalación en la línea 840:
declare -i i=2
Pero no es importante, ya que es para instalar en los distintos runlevels un script que cargue el driver al arrancar, aunque yo no he tenido problemas para que el kernel cargue el driver cuando enchufo la tarjeta al equipo (hotplug o udev), así que podemos eliminar esas líneas o escribir antes de la comprobación una declaración de la variable initdir:
initdir=""
- Cambiar reglas de udev.
En udev ha habido una serie de cambios, por lo que el archivo que viene junto al driver tampoco funciona correctamente. Para que funcione debemos realizar los siguientes cambios:
~$ vi 10-cardmanusb.rules
~$ diff -u 10-cardmanusb.rules.old 10-cardmanusb.rules
--- 10-cardmanusb.rules.old 2006-01-31 16:36:41.000000000 +0100
+++ 010_cardmanusb.rules 2006-08-16 12:18:01.000000000 +0200
@@ -1,3 +1,3 @@
-BUS="usb", SYSFS{idVendor}="076b", SYSFS{idProduct}="0596", NAME="cm%n", SYMLINK="usb/cm%n"
-BUS="usb", SYSFS{idVendor}="076b", SYSFS{idProduct}="1784", NAME="cm%n", SYMLINK="usb/cm%n"
-BUS="usb", SYSFS{idVendor}="08d4", SYSFS{idProduct}="0009", NAME="cm%n", SYMLINK="usb/cm%n"
+BUS=="usb",SYSFS{idVendor}=="076b",SYSFS{idProduct}=="0596",SYMLINK="usb/cm%n"
+BUS=="usb",SYSFS{idVendor}=="076b",SYSFS{idProduct}=="1784",SYMLINK="usb/cm%n"
+BUS=="usb",SYSFS{idVendor}=="08d4",SYSFS{idProduct}=="0009",SYMLINK="usb/cm%n"
- Resumen.
Hemos averiguado los errores que nos daba nuestro driver al compilarlo, hemos buscado soluciones en el API del kernel y lo hemos solucionado. En definitiva, tenemos funcionando un periférico al que la compañía que lo fabrica ya no le brinda soporte, pero que es perfectamente funcional y las únicas diferencias que le he hallado con respecto a versiones más modernas de lectores es la velocidad de lectura de las tarjetas (aunque la diferencia no es abismal) y el que no utilice estándares (las nuevas versiones de lector son enchufar y funcionar, sin compilar nada, incluso más fácilmente que en Window$) para lo que tenemos este driver.
Ha quedado un poco largo, pero espero que se entienda el proceso que he seguido y lo fácil que resulta realizar cambios sobre un driver que funciona. Entiendo que se podría estudiar el código de dicho driver y mejorarlo, pero eso no entra dentro de mis planes más inmediatos.
- Parches conseguidos.
Aquí tenemos los parches que hemos conseguido con nuestros cambios. Para aplicarlos solamente tenéis que copiarlos en un archivo, en el mismo directorio donde se encuentra el original y ejecutar el siguiente comando, en ese directorio :
~$ patch -p1 < archivo.patch
--- install.old 2006-08-16 10:14:29.000000000 +0200
+++ install 2006-08-16 12:14:18.000000000 +0200
@@ -231,7 +231,7 @@
echo OK
fi
mkdir -p /usr/local/pcsc/drivers
-fi #if [ $nopcscd = 0 ];
+#fi #if [ $nopcscd = 0 ];
#
# make initscript
#
@@ -565,7 +565,7 @@
fi
-#fi #if [ $nopcscd = 0 ];
+fi #if [ $nopcscd = 0 ];
#
# copy the pcsc-shared library to its proper place
@@ -609,9 +609,9 @@
# copy cardman kernel module
#
-if [ $min == 2 ]; then
+if [ $min -eq 2 ]; then
mod_min=misc
-elif [ $min == 4 ]; then
+elif [ $min -eq 4 ]; then
mod_min=kernel/drivers/usb
elif [ $min -ge 5 ]; then
mod_min=kernel/drivers/usb/misc
@@ -622,7 +622,7 @@
echo Copy cardman.$kext to $moddir/$rel/$mod_min
cp ./modules/cardman.$rel.$kext $moddir/$rel/$mod_min/cardman.$kext
chmod 644 $moddir/$rel/$mod_min/cardman.$kext
-if [ $? == 1 ]; then
+if [ $? -eq 1 ]; then
echo Could not copy cardman-module, exiting
exit 0
fi
@@ -834,6 +834,7 @@
echo "Couldn't make any runlevel entries (Don't mind if you are using Hotplugging!)"
fi
+initdir=""
if [ -n "$initdir" ]; then
chmod a+x $initdir/$iname
- Archivo: cardman.patch
--- src/cm2020/cardman.c.old 2006-08-16 10:55:03.000000000 +0200
+++ src/cm2020/cardman.c 2006-08-16 11:44:40.000000000 +0200
@@ -165,13 +165,15 @@
static struct usb_class_driver cmu_class = {
.name= "usb/cm%d",
.fops= &cmu_fops,
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
.mode= S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+ #endif
.minor_base= CM2020_MINOR,
};
#endif
STATIC struct usb_driver cmu_driver = {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
.owner= THIS_MODULE,
#endif
.name= "cardman",
@@ -1775,12 +1777,12 @@
if (_IOC_DIR(cmd)&_IOC_READ) {
DEBUG(5,"ioctl: _ioc_dir=read\n");
if (arg==0) rc=-EFAULT;
- else rc=verify_area(VERIFY_WRITE,(void *)arg,size);
+ else rc=(access_ok(VERIFY_WRITE,(void *)arg,size))?0:-EFAULT;
}
if (_IOC_DIR(cmd)&_IOC_WRITE) {
DEBUG(5,"ioctl: _ioc_dir=write\n");
if (arg==0) rc=-EFAULT;
- else rc=verify_area(VERIFY_READ,(void *)arg,size);
+ else rc=(access_ok(VERIFY_READ,(void *)arg,size))?0:-EFAULT;
}
if (rc) {
DEBUG(4, "<- ioctl (unknown comamnd)\n");
- Archivo: 10-cardmanusb.rules.patch
--- 10-cardmanusb.rules.old 2006-08-16 12:48:21.000000000 +0200
+++ 10-cardmanusb.rules 2006-08-16 12:48:37.000000000 +0200
@@ -1,3 +1,3 @@
-BUS="usb", SYSFS{idVendor}="076b", SYSFS{idProduct}="0596", NAME="cm%n", SYMLINK="usb/cm%n"
-BUS="usb", SYSFS{idVendor}="076b", SYSFS{idProduct}="1784", NAME="cm%n", SYMLINK="usb/cm%n"
-BUS="usb", SYSFS{idVendor}="08d4", SYSFS{idProduct}="0009", NAME="cm%n", SYMLINK="usb/cm%n"
+BUS=="usb",SYSFS{idVendor}=="076b",SYSFS{idProduct}=="0596",SYMLINK="usb/cm%n"
+BUS=="usb",SYSFS{idVendor}=="076b",SYSFS{idProduct}=="1784",SYMLINK="usb/cm%n"
+BUS=="usb",SYSFS{idVendor}=="08d4",SYSFS{idProduct}=="0009",SYMLINK="usb/cm%n"