1 / 46

Desarrollo de un driver de ratón en GNU/Linux

Desarrollo de un driver de ratón en GNU/Linux. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS. 2. Sistemas de drivers en GNU/Linux.

chiku
Download Presentation

Desarrollo de un driver de ratón en GNU/Linux

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Desarrollo de un driver de ratón en GNU/Linux Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  2. 2 Sistemas de drivers en GNU/Linux • En versiones antiguas, previas a la serie 2, se modificaban directamente las fuentes para dotar alSO de nuevas características. • Comenzando con las series 2.0.X se cambió de filosofía permitiendo al SO cargar módulos. • Un módulo es un fichero objeto que contiene nuevas funciones del SO. Se pueden añadir sin reiniciar. • Los módulos de Linux suponen ahorro de memoria. Cuando no se usan se pueden descargar,liberando RAM. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  3. 3 Sistemas de drivers en GNU/Linux Uso del Driver: • Para cargarlo en el sistema tecleamos como root: • # insmod nombre_del_modulo.o • Para descargar el driver: • # rmmod nombre_del_modulo • Vemos que no es precisa la extensión .O • Para tener una relación de los drivers que se encuentran cargados en memoria ejecutaremos: • # lsmod Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  4. 4 Sistemas de drivers en GNU/Linux Herramientas de desarrollo de GNU/Linux: Compilador de C, gcc gcc -Wall -DMODULE -c -o objeto.o codigo_fuente.c -Wall:Activa el modo de compilación para mostrar por pantalla todos los avisos del compilador. -c:Hace que el compilador genere un fichero objeto. -o: Permite establecer el nombre del fichero de salida. 2. Utilidad para el mantenimiento de proyectos, make: Nos permite definir listas de operaciones de compilación en un fichero de reglas llamado makefile. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  5. 5 Sistemas de drivers en GNU/Linux • /* Código de entrada al módulo. Se ejecuta al cargar el módulo */ • int init_module (void){ • printk ("Hola, mundo!!!\n"); • return 0; • } • /* Código de salida delmódulo. Se ejecuta al descargar el módulo */ • void cleanup_module (void){ • printk ("Adios mundo : (\n"); • } • /* Ficheros de cabecera estándar para la compilación de módulos*/ • #include <linux/kernel.h> • #include <linux/module.h> • #if CONFIG_MODVERSIONS==1 • #include <linux/modversions.h> • #define MODVERSIONS • #endif Módulo de ejemplo: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  6. 6 Sistemas de drivers en GNU/Linux El fichero makefile que nos posibilita compilar adecuadamente este módulo: • /* Variables de entorno */ • NOMBREMODULO=kholamundo.o • FUENTES=kholamundo.c • OPCIONES=-Wall -DMODULE -D__KERNEL__ -DLINUX • /* Regla: definimos los ficheros fuentes */ • $(NOMBREMODULO).o: $(FUENTES) • gcc $(OPCIONES) -o $(NOMBREMODULO) -c $(FUENTES) Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  7. 7 Desarrollando el driver Sistema de ficheros en UNIX: • Todo en Linux es representado por un fichero. • Todos los dispositivos cuelgan del directorio /dev • # ls –la /dev • En la 1ª columna tenemos los permisos de los dispositivos. • El primer bit de grupo indica: * dispositivo de bloque b * dispositivo carácter c -Las columnas 5ª y 6ª caracterizan unívocamente a cada dispositivo (mayor y menor) Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  8. 8 Desarrollando el driver Sistema de ficheros en UNIX: Estos números son el número mayor y el número menor del dispositivo respectivamente. Ambos enteros de 8 bits. • El número mayor: indica qué módulo del kernel se hacecargode las peticiones del dispositivo. • El número menor: • distingue distintos dispositivos con el mismo número mayor, es decir, controlados por el mismo dispositivo. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  9. 9 Desarrollando el driver Creación del fichero de dispositivo: Para empezar a usar un dispositivo, no sólo hay que instalar en memoria el módulo que se encargue de gestionarlo sino que hay que crear su correspondiente fichero en el directorio /dev. # mknod /dev/nombre_del_dispositivo NumMayor NumMenor Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  10. 10 Desarrollando el driver Descripción del driver de ratón: El ratón es un dispositivo que ofrece datos de forma asíncrona y como tal tendrá que tratarlo el sistema operativo. Necesitamos saber qué tipo de ratón tenemos para poder interpretar los datos que leemos en /dev/mouse, como coordenadas, pulsaciones... Hay distintas normas: • Mouse Systems • Logitech • Microsoft (prácticamente usada por la totalidad de ratones serie). Es la que usaremos nosotros. Nuestro dispositivo será dev/ratonde solo lectura. Éste devolverá una línea de texto con las coordenadas del ratón y el estado de los botones. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  11. 11 Desarrollando el driver La norma Microsoft: La configuración del puerto serie debe ser: • Velocidad 1200 baudios • Tamaño 7 bits • Sin paridad Para detectar si hay ratón o no hay que poner la línea DTR del puerto serie a 1. Pasado un instante el ratón devuelve el código ASCII de la letra M. Cuando se mueve el ratón se envían 3 bytes con información sobre cuanto se ha movido éste desde la última vez y el estado de los botones. La unidad de medida son los Mickeys, que dependiendo de la resolución del ratón usado pueden ser 1/200” o 1/400” Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  12. 12 Desarrollando el driver 1 L R Y7 Y6 X7 X6 0 X5 X4 X3 X2 X1 X0 0 Y5 Y4 Y3 Y2 Y1 Y0 La norma Microsoft: El protocolo para conocer el correcto orden de los bytes (en realidad de los 7 bits de datos) es que el primero tiene en el bit más significativo un 1 y los dos restantes un 0. Utilizamos 8 bits para cada coordenada (y complemento a 2). Así el rango estará entre: –128 y 127 Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  13. 13 Desarrollando el driver Guardamos en tabla[0] Esperar 2º byte Guardamos en tabla[1] Esperar byte 3º Guardamos en tabla[1] Esperar byte 3º Guardamos en tabla[0] Esperar 2º byte Bit 6 = 0? Bit 6 = 1? Bit 6 = 0? Bit 6 = 1? Bit 6 = 0? Bit 6 = 0? SECUENCIA COMPLETA DE LOS 3 BYTES Decodificar la tabla y generar datos (X,Y) y pulsaciones Decodificar la tabla y generar datos (X,Y) y pulsaciones Guardamos en tabla[2] Guardamos en tabla[2] l l La norma Microsoft: Decodificación mediante la rutina: Bit 6 = 1? Bit 6 = 0? Esperamos el primer byte Bit 6 = 1? l Codigo Fuente Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  14. 14 Desarrollando el driver La norma Microsoft: • Cuando tengamos los tres bytes pedidos en su correcto orden, aplicamos las máscaras necesarias para reagrupar los datos de las coordenadas X, Y y las pulsaciones de botones. • Lo que obtengamos serán movimientos relativos medidos desde la posición del ratón en la medida previa. • Para guardar el origen de coordenadas de nuestro ratón utilizaremos dos variables globales que inicializaremos a 0, 0. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  15. 15 Desarrollando el driver El puerto serie: • El puerto serie se utiliza en aplicaciones en la que o bien la velocidad no es crítica o bien no se puede alcanzar esta. • Usaremos circuito UART 8250 o 16550 (implantado en casi todas las placas base). Este circuito nos aliviará de la carga de tener que temporizar la entrada y salida de datos para cumplir los tiempos de la comunicación. • La línea que transmite los datos está en estado alto. Al comenzar la transmisión se envía el bit de inicio, 0, y después los 8 bits de datos (en este caso 7). • Por último, aparece un bit a 1 o bit de parada, que puede ser también un bit y medio o dos. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  16. 16 Desarrollando el driver El puerto serie. Circuito UART 8250: • El circuito 8250 tiene 11 registros y el 16550, su sucesor, 12. • Tienen 3 lineas de direcciones (23 < 11). Así que necesitamos saber también si el acceso es, lectura o escritura, y el bit DLAB del registro LCR. • Pondremos DLABa 1, puntualmente para poder acceder a programar los registros que almacenan el divisor de velocidad ,DLL y DLM delBRB (Baud Rate Register). Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  17. 17 Desarrollando el driver LCR (Line Control Registrer): controla el formato del carácter de datos DLAB 7 Break Control 6 Stick Parity 5 EPS 4 PEN 3 STB 2 WLS1 1 WLS0 0 El puerto serie. Circuito UART 8250. Registros: en nuestro código Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  18. 18 Desarrollando el driver LSR (Line Status Registrer): se consulta tras una interrupción 7 TEMT 6 THRE 5 BI 4 FE 3 PE 2 OE 1 DR 0 El puerto serie. Circuito UART 8250. Registros: 0 DR:Data ready, activo (1) cuando hay un carácter listo en el RBR y (0) cuando se lee el RBR. • 1 OE:Overrun Error, es decir, que vale 1 cuando se ha machacado un dato que no había sido leido por la CPU. • 2 PE:Parity Error. Vale 1 si ha habido un error de paridad • 3 FE:Framing Error. Se activa si no se encuentran los bits de error. • 4 BI:Break Interrupt. Se activará cuando mantengamos la entrada de datos a espacio “0” más tiempo del debido. 5 THRE: Transmitter Holding Register Empty. Indica que se puede aceptar unnuevo carácter para la transmisión. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  19. 19 Desarrollando el driver MCR (Modem Control Register): controla la interface con el modem 7 6 5 LOOP 4 OUT2 3 OUT1 2 RTS 1 DTR 0 1 1 1 0 Dispositivo conectado al puerto comienza transmisión Activa Interrupción El puerto serie. Circuito UART 8250. Registros: Las líneas físicas DTR, RTS, OUT1 y OUT2 están controladas por estos bits. Son activas a nivel bajo. Sirven para establecer distintos protocolos de comunicaciones. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  20. 20 Desarrollando el driver MSR (Modem Status Register) DCD 7 RI 6 DSR 5 CTC 4 DDCD 3 TERI 2 DDSR 1 DCTS 0 reflejan el estado de los mismos pines del modem BRSR (Baud Rate Select Register): entre DLL y DLM forman un dato de 16 bits que será el divisor que se aplique a la frecuencia base para seleccionar la velocidad. 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 DLM DLL En nuestro caso tendremos que escribir un 0x00 en el DLM y un 0x60 en el DLL El puerto serie. Circuito UART 8250. Registros: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  21. 21 Desarrollando el driver RBR Receiver Buffer Register: Buffer de recepción de datos. THR Transmitter Holding Register: Registro de retención de transmisión. Almacena el siguiente carácter que va a ser transmitido. SCR Scratchpad Register: Se puede usar como memoria. IIR Interrupt Identification Register IERInterrupt Enable Register FCR FIFO Control Register La transmisión en el 8250 se basa en los registros THR y TSR. Los bits 5 y 6 del registro LSR indican si sendos registros se encuentran vacios. Programación del 8250 El 8250 se programa mediante los registros de control LCR, IER,DLL, DLM y MCR. La única restricción es escribir IER en último lugar porque controla la habilitación de las interrupciones. Una vez que se ha programado el 8250 se puede cambiar el contenido de sus registros aunque éste esté en funcionamiento. El puerto serie. Circuito UART 8250. Registros: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  22. 22 Desarrollando el driver El puerto serie. Circuito UART 8250. Registros: Para hacer un reset del 8250, cuando se le da corriente hay que tenerlo 500 ns con MRalto (inicialización de contadores internos de transmisión y recepción por un lado y puesta a 0 de LSR, salvo TEMT y THRE que son puestos a 1, por otro) Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  23. 23 Desarrollando el driver El sistema de interrupciones en Linux • Dentro de un módulo se pueden registrar gestores de interrupción rápidos, que serán llamados cuando ocurra una interrupción en una determinada línea IRQ. • Estos gestores deben realizar pocas tareas (se ejecutan con un control total de la CPU). Mientras estos gestores se estan ejecutando, nada ni nadie puede interrumpirlos de modo que un gestor mal programado puede llevar a un bucle sin fin y a un cuelgue de la máquina, teniendo que hacer un reset de la misma. • En el cuerpo de un gestor de interrupción rápido, no se permite llamar a muchas de las funciones del kernel. • Su función esencial consiste en atender al dispositivo, guardando los valores que se estimen oportunos para pasárselos luego a otra rutina: el gestor de interrupciones de baja prioridad. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  24. 24 Desarrollando el driver El sistema de interrupciones en Linux • El gestor de interrupciones de baja prioridad no presenta las limitaciones del anterior y puede tomarse más tiempo en su ejecución. Su objetivo es procesar los datos del gestor rápido y generar las acciones oportunas. • Las llamadas del kernel para manejar las interrupciones son: q ·request_irq: Asigna un gestor de interrupción rápida a una determinada IRQ • ·free_irq: Libera una IRQ para poder asignarse a otro gestor. • ·queue_task_irq: Coloca en la cola de tareas un proceso de gestión de interrupción de baja prioridad • ·mark_bh: Activa la cola de tareas para que arranque el proceso con la mayor brevedad posible. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  25. 25 Desarrollando el driver El sistema de interrupciones en Linux • En nuestro caso: • En la inicialización del módulo: haremos primero una llamada a free_irq para asegurarnos que la IRQ afectada estará libre (si ya lo estaba recogeremos un simple aviso del kernel) • y después la llamada a request_irq para solicitarla. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  26. 26 Desarrollando el driver Bloqueo de procesos en Linux Nuestro driver no estará constantemente enviando datos. Cuando el usuario no esté actuando sobre el ratón, el programa que hace uso del dispositivo /dev/raton en su función read() no leerá nada y deberá dormirse. Cuando le lleguen datos, deberá despertarse y continuar con su proceso. Para hacer frente a este problema, GNU/Linux aporta las denominadas colas de espera, que se gestionan dentro de un módulo y que contienen los procesos de usuario que están esperando datos de nuestro controlador. En nuestro caso sólo permitiremos que un proceso actúe sobre el dispositivo por lo que la cola de espera tendrá 0 o 1 procesos. Para tratar esto en nuestro módulo, crearemos una cola de espera. Cuando un proceso ejecute la función read() al dispositivo, el driver pondrá a dormir al proceso llamante. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  27. 27 Desarrollando el driver Bloqueo de procesos en Linux Cuando se genere una coordenada válida y debidamente decodificada, el módulo la almacenará en una posición accesible para todos la copiará al espacio de memoria de usuario con memcpy_tofs() y acto seguido despertará a los procesos que estén esperando en la cola de espera. Los procesos que estuviesen dormidos despertarán y seguirán ejecutándose, encontrándose la función read() los datos donde esperaba. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  28. Proceso de diseño del driver 28 Las funciones para implementar el driver se pueden agrupar en cuatro grandes bloques: BLOQUE 1 Funciones genéricas de interface con el driver BLOQUE 2 Funciones comunes a todos los módulos del sistema Los programas acceden al driver invocando estas funciones El S.O. lasusa como puntos de E/S de los módulos BLOQUE 4 Funciones auxiliares BLOQUE 3 Funciones propias del driver Son las que gestionan las interrupciones de alta y baja prioridad, implementan la lógica del driver, etc. Se usan para iniciar y manejar los puertos, las operaciones de entrada / salida, etc. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  29. Proceso de diseño del driver 29 BLOQUE 2 Funciones comunes a todos los módulos del sistema BLOQUE 1 Funciones genéricas de interface con el driver • struct file_operations Operaciones //estructura • static intmidriver_open (struct inode*inode,struct file*file) static intmidriver_close (structinode *inode,struct file file) static intmidriver_read (structfile *file, char*buffer,size_tcount,loff_t*offp) int init_module(void) voidcleanup_module (void) BLOQUE 4 Funciones auxiliares BLOQUE 3 Funciones propias del driver voidiniciarPuertoSerie(intbaudios,intlpalabra,intstop,intparidad) voidprocesarDatoPuertoSerie(chardato) voiddecodificarCoordenadas(charbyte1,charbyte2,charbyte3,char*texto) static voidgestor_interrupcion (intirq, void*dev_id,structpt_regs *regs) static void gestor_interrupcion_baja_prioridad (void* parametro) Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  30. Demostración 30 Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  31. Desarrollo de un driver de ratón en GNU/Linux Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  32. Código Fuente Anexos Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  33. Código Fuente I /* Estructura con punteros a funciones que implementan las operaciones con el dispositivo */ structfile_operations Operaciones= { read : midriver_read, open : midriver_open, release : midriver_close }; Funciones genéricas de interface con el driver: Son las funciones de las que se servirá el programa de usuario para tratar con el driver. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  34. Código Fuente II static intmidriver_open(structinode *inode,structfile *file) { /* En inode->i_rdev tenemos un valor de 16 bits que indica el numero mayor y el numero menor del dispositivo */ if (DispositivoAbierto>0){ return -EBUSY; } /* Devolvemos0 para indicar que el dispositivo ha sido abierto con exito -EBUSY para indicar que el dispositivo esta ocupado en otro proceso -EPERM para indicar que no tenemos permiso para abrir este dispositivo */ DispositivoAbierto=1;/* para indicar al modulo que el dispositivo se esta usando */ MOD_INC_USE_COUNT;/* para indicar al kernel que alguien esta usando este modulo */ return 0; } Funciones genéricas de interface con el driver: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  35. III Código Fuente static intmidriver_close(structinode *inode,structfile *file) { DispositivoAbierto=0; MOD_DEC_USE_COUNT; printk ("Descargando driver de dispositivo /dev/raton...\n"); return (0); } staticssize_tmidriver_read(structfile *file,char*buffer, size_t count,loff_t *offp) { sigset_t set_result; /* Nos echamos a dormir hasta que el raton de una coordenada */ module_interruptible_sleep_on (&ColaEspera); /* Alguien nos ha despertado... seguimos nuestra tarea */ /* Es posible que nos hayan despertado porque el proceso ha recibido unaseñal que no estamos tratando: en este caso, el proceso termina */ signandsets (&set_result, &current->signal, &current->blocked); if ( sigtestsetmask (&set_result, 0xFFFFFFFF) ) { return -EINTR; } Funciones genéricas de interface con el driver: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  36. IV Código Fuente intinit_module (void){ NumeroMayor= register_chrdev (0, NOMBRE_DISP, &Operaciones); if (NumeroMayor<0) { printk ("La inicializacion del driver fallo por no poder registrar el dispositivo\n"); free_irq (IRQ_USADA, NULL); return NumeroMayor; } /* Se inicializa el puerto serie con los valores adecuados */ IniciarPuertoSerie (BAUDIOS, 7, 1, 0); printk ("Se ha instalado un driver para /dev/%s con numero mayor=%d\n", NOMBRE_DISP, NumeroMayor); return 0; } int res; # if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) SET_MODULE_OWNER (&Operaciones); # endif /* Primero liberamos la irq que queremos usar...*/ free_irq (IRQ_USADA, NULL); /* ... y despues la pedimos */ res = request_irq (IRQ_USADA, gestor_interrupcion, SA_INTERRUPT, "raton", NULL); if (res !=0){ printk("No se puede reservar la IRQ %d\n", IRQ_USADA); return res; } Funciones comunes a todos los módulos del sistema: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  37. V Código Fuente voidcleanup_module (void) { int res; res=unregister_chrdev (NumeroMayor, NOMBRE_DISP); if (res<0) printk ("Ocurrio un error al desinstalar el driver. Puede que este en uso\n"); } Funciones comunes a todos los módulos del sistema: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  38. VI Código Fuente static voidgestor_interrupcion(intirq,void*dev_id,struct pt_regs *regs); Esta función se encarga del gestor de interrupción. Se encarga de hacer el menor número de tareas posibles, puesto que se queda con el control de la cpu por completo, y deja la mayor parte de la tarea a otra rutina, gestor_interrupción_baja_prioridad(), que será quien realmente haga todo el trabajo. static voidgestor_interrupcion_baja_prioridad (void*parametro); Se encarga del grueso del trabajo de comunicación con el puerto, pero con menos prioridad que la anterior e interrumpible por tareas críticas del sistema operativo. Funciones Propias del Driver: Gestionan las interrupciones de alta y baja prioridad, implementan la lógica del driver, etc. Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  39. VII Código Fuente static voidgestor_interrupcion(intirq,void*dev_id,struct pt_regs *regs){ staticchar caracter; staticstruct tq_struct tarea= { NULL, 0, gestor_interrupcion_baja_prioridad, &caracter }; // Mientras haya un Data Ready (DR) en LSR... while ((inb(LSR)&0x1) !=0){ caracter= inb(RBR); tarea.data= (void *) caracter; queue_task (&tarea, &tq_immediate); // Metemos en la cola de tareas el caracter recien leido mark_bh (IMMEDIATE_BH); // Avisamos a la cola de que tiene una tarea por procesar }} Funciones Propias del Driver: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  40. VIII Código Fuente static voidgestor_interrupcion_baja_prioridad (void* parametro){ char carac; carac= (char) parametro; ProcesarDatoPuertoSerie (carac); module_wake_up (&ColaEspera); } Funciones Propias del Driver: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  41. IX Código Fuente LCR (Line Control Registrer): controla el formato del carácter de datos DLAB 7 Break Control 6 Stick Parity 5 EPS 4 PEN 3 STB 2 WLS1 1 WLS0 0 Funciones auxiliares: Se usan para manejar los puertos, las operaciones de entrada/salida, etc. voidIniciarPuertoSerie(intbaudios,intlpalabra,intstop,intparidad) Desarrollando el Driver Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  42. X Código Fuente voidIniciarPuertoSerie(intbaudios,intlpalabra,intstop,intparidad){ int divisor; divisor = FRECUENCIA_BASE/(16*baudios); //Ponemos un 1 en el MSB de LCR(DLAB) para poder acceder a DLL y DLM outb (0x80, LCR); outb ((divisor & 0xFF), DLL);//Escribimos el LSB del divisor outb (((divisor >> 8) & 0xFF), DLM);//Escribimos el MSB del divisor outb (0x00, LCR);// Volvemos a poner un 0 en el MSB de LCR(DLAB) // bits 543: paridad (000) = sin paridad // bit 2: stop (0) = 1 bit de stop // bits 10: datos (10)= 7 bits de datos outb ( ( (lpalabra) | (stop << 2) | (paridad << 3) ), LCR); outb (0x07, FCR);// 00000111 outb (0x0B, MCR);// 00001011 inb (MSR); inb (LSR); inb (RBR); outb (0x01, IER);// 00000001 } Funciones auxiliares: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  43. XI Código Fuente voidprocesarDatoPuertoSerie(chardato); Esta rutina implementa la máquina de estados que hemos descrito anteriormente. En el momento en que haya 3 bytes correctos se llamará a decodificarCoordenadas() voiddecodificarCoordenadas(char byte1,charbyte2,charbyte3,char*texto); Esta cadena tomará 3 bytes leidos del puerto serie en el orden correcto y rellenará la cadena de caracteres indicada por texto con el formato X Y L R donde X e Y corresponden a la coordenada X e Y y L Y R a los botones izquierdo y derecho respectivamente. Un 1 indicará botón pulsado y un 0 lo contrario. La variable del tipo cadena, texto, tendrá visibilidad global en la aplicación para que pueda ser leida por otras funciones. Reservaremos 256 bytes para ella. Funciones auxiliares: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  44. XII Código Fuente voidprocesarDatoPuertoSerie(chardato){ staticint Estado = 1; staticunsignedchar VectorBytes[3]; switch (Estado){ case 1: if (dato & 0x40){ VectorBytes[0] = dato; Estado = 2; } break; case 2: if (dato & 0x40){ VectorBytes[0] = dato; } else{ VectorBytes[1] = dato; Estado = 3; } break; case 3: if (dato & 0x40){ VectorBytes[0] = dato; Estado = 2; } else{ VectorBytes[2] = dato; DecodificarCoordenadas (VectorBytes[0], VectorBytes[1], VectorBytes[2], texto); Estado = 1; } } } Funciones auxiliares: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  45. XIII Código Fuente voiddecodificarCoordenadas(char byte1,charbyte2,charbyte3,char*texto){ // los 2 LSB de byte1 y los 5 LSB de byte2 componen X coordenadaX = ((byte1 & 0x03) << 6) | (byte2 & 0x3F); // los bits 2 y 3 de byte1 y los 5 LSB de byte3 componen Y coordenadaY = ((byte1 & 0x0C) << 6) | (byte3 & 0x3F); sprintf(texto,"%d %d %d %d\n",coordenadaX, coordenadaY, l, r); } char l=0; char r=0; int coordenadaX=0; int coordenadaY=0; /* Decodificamos los botones del raton Primero el boton izquierdo...*/ if ((byte1 & 0x20)== 0){ l = 0; } else{ l = 1; } /* ...despues el boton derecho.*/ if ((byte1 & 0x10) == 0){ r = 0; } else{ r = 1; } Funciones auxiliares: Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

  46. Desarrollo de un driver de ratón en GNU/Linux Desarrollo de un driver de ratón en GNU/Linux Periféricos e Interfaces, 3º ITIS

More Related