Sort of an event driver

0

I am trying to make a Linux Kernel driver in the Raspberry pi 3 that turns on a led when a button in a joystick es pressed(Sets GPIO as an Output and then sets it on) and also reads the status of that GPIO port.

My driver for turning on the leds is:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<linux/slab.h>
#include<asm/uaccess.h>
#include<asm/io.h>
#define ioaddress_SIE_BASE 0x3F200000
#define ioaddress_SIZE 0x38
#define address_LED_on 0x1C
#define address_LED_off 0x28
#define address_LED_estado 0x34
MODULE_LICENSE("Dual BSD/GPL");
static char *nombre="4led";
static unsigned int PrimerMenor=0;
static unsigned int cuenta=1;
static dev_t led_dev_numero;
char *buffer;
int on_off=0;
int leido=0;
static void __iomem *ioaddress_SIE;
struct led_dev *led_dev_puntero;

struct led_dev {
    struct cdev led_cdev;
};
int led_open (struct inode *puntero_inode, struct file *puntero_file)
{
 struct led_dev *led_dev_puntero;
 printk (KERN_INFO "led_SIE: se ha abierto el dispositivo \n" );
 led_dev_puntero=container_of(puntero_inode->i_cdev, struct led_dev, led_cdev);
 puntero_file->private_data=led_dev_puntero;
 return 0;
}

int led_release (struct inode *puntero_inode , struct file *puntero_file)
{
 printk (KERN_INFO "led_SIE: se ha liberado el dispositivo \n" );
 return 0;
}

static ssize_t led_read (struct file *puntero_file , char *buffer_user, size_t tamano, loff_t *puntero_offset)
{
 unsigned int estado;
 unsigned long prueba;
 printk (KERN_INFO "led_SIE: leyendo el dispositivo \n" );
 iowrite32(0x00000000, ioaddress_SIE);
 estado=ioread32(ioaddress_SIE + address_LED_estado);

 printk("led_SIE: GPIOs 9 to 0 --> 0x%X \n", estado);

*buffer=(char ) (estado >> leido );

prueba=copy_to_user(buffer_user, buffer, 1);
printk("led_SIE: GPIOs 9 to 0 --> 0x%X \n", *buffer);

if(leido>23){
leido=0;}
else
  leido=leido+8;
return 1;
}


static ssize_t led_write (struct file *puntero_file , const char *buffer_user, size_t tamano, loff_t *puntero_offset)
{
 unsigned long prueba;
/*printk(KERN_INFO "led_SIE: escribiendo en el dispositivo \n");
if(buffer_user[0]!='1'){
if(buffer_user[0]!='0'){
printk(KERN_INFO "led_SIE: Ha ingresado una orden incorrecta! \n");
printk(KERN_INFO "led_SIE: Las ordenes son: 1 para encender, 0 para apagar \n");
return tamano;
}
}*/

prueba=copy_from_user(buffer, buffer_user, tamano);

printk(KERN_INFO "led_SIE: SE escribió %c en el dispositivo \n", buffer);
/*ibuffer_user=(int)buffer_user;*/
/*printk(ibuffer_user);
int    ibuffer = (int) buffer;*/
/*if(buffer_user=='1'){
printk(KERN_INFO "Lee maldita sea \n");
}*/
switch(buffer[0]){
case '1':
if(on_off==1){
printk(KERN_INFO "led_SIE: El led ya se encuentra encendido \n");
return tamano;
}
on_off=1;
iowrite32(0x00009240, ioaddress_SIE);
iowrite32(0x00000004, ioaddress_SIE + address_LED_on);
iowrite32(0x00000038, ioaddress_SIE + address_LED_off);
break;

case '2':
if(on_off==2){
printk(KERN_INFO "led_SIE: El led ya se encuentra encendido \n");
return tamano;
}
on_off=2;
iowrite32(0x00009240, ioaddress_SIE);
iowrite32(0x00000008, ioaddress_SIE + address_LED_on);
iowrite32(0x00000034, ioaddress_SIE + address_LED_off);
break;

case '3':
if(on_off==3){
printk(KERN_INFO "led_SIE: El led ya se encuentra encendido \n");
return tamano;
}
on_off=3;
iowrite32(0x00009240, ioaddress_SIE);
iowrite32(0x00000010, ioaddress_SIE + address_LED_on);
iowrite32(0x0000002C, ioaddress_SIE + address_LED_off);
break;

case '4':
if(on_off==4){
printk(KERN_INFO "led_SIE: El led ya se encuentra encendido \n");
return tamano;
}
on_off=4;
iowrite32(0x00009240, ioaddress_SIE);
iowrite32(0x00000020, ioaddress_SIE + address_LED_on);
iowrite32(0x0000001C, ioaddress_SIE + address_LED_off);

break;
case '0':
if(on_off==0){
printk(KERN_INFO "led_SIE: El led ya se encuentra apagado \n");
return tamano;
}
on_off=0;
iowrite32(0x00009240, ioaddress_SIE);
iowrite32(0x0000003C, ioaddress_SIE + address_LED_off);
break;
default:
return tamano;
}
return tamano;
}


struct file_operations led_fops = {

    .owner = THIS_MODULE,
    .read = led_read,
    .write = led_write,
    .open = led_open,
    .release = led_release
};

static int hello_init(void)
{
int resultado, error;

printk(KERN_ALERT "Hola, mundo\n");
resultado=alloc_chrdev_region(&led_dev_numero, PrimerMenor, cuenta, nombre);
if (resultado ==0)
printk(KERN_INFO "Se reservaron los siguientes numeros \n Mayor:  %d\n Menor: %d\n", MAJOR(led_dev_numero), MINOR(led_dev_numero));
else
printk(KERN_INFO "Hubo un error y los numeros no se reservaron. Error:  %d\n", resultado);

led_dev_puntero = kmalloc (sizeof(struct led_dev), GFP_ATOMIC);
buffer=kmalloc(8,GFP_ATOMIC);//GFP_KERNEL---Difícil
cdev_init(&led_dev_puntero->led_cdev, &led_fops);
led_dev_puntero->led_cdev.owner=THIS_MODULE;
led_dev_puntero->led_cdev.ops=&led_fops;
error=cdev_add(&led_dev_puntero->led_cdev, led_dev_numero, cuenta);
if(error)
printk (KERN_INFO "error $d al anadir led_dev");
ioaddress_SIE=ioremap(ioaddress_SIE_BASE, ioaddress_SIZE);
printk(KERN_ALERT "ioadress_SIE_BASE fue mapeado a: %p \n", ioaddress_SIE);
return 0;
}
module_init(hello_init);

static void hello_exit(void)
{
 printk(KERN_ALERT "Adios, mundo cruel\n");
 unregister_chrdev_region(led_dev_numero,cuenta);
 cdev_del(&led_dev_puntero->led_cdev);
 kfree(led_dev_puntero);
 kfree(buffer);
if(on_off==1){
 iowrite32(0xFFFFFFFF, ioaddress_SIE + address_LED_off);
}
iounmap(ioaddress_SIE);
}

module_exit(hello_exit);

And the application that interacts with the driver and the joystick is:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

struct js_event {
        unsigned int time;      /* event timestamp in milliseconds */
        short value;   /* value */
        unsigned char type;     /* event type */
        unsigned char number;   /* axis/button number */
};

#define JS_EVENT_BUTTON         0x01    /* button pressed/released */
#define JS_EVENT_AXIS           0x02    /* joystick moved */
#define JS_EVENT_INIT           0x80    /* initial state of device */

int main(int argc, char **argv)
{   //Acceso al driver Xdriv
    int fd = open ("/dev/input/js0", O_RDONLY);
    FILE *archivo;
    int  tamano;
    int a;int b;

    /*Acceso al driver 4_leds

    system("sudo chmod 777 /dev/4leds");
    archivo=fopen("/dev/4leds" ,"w");
    if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
    */

    if( fd < 0 )
        printf( "cannot open dev\n" );
    else
        printf( "opened success...:)\n" );

    struct js_event e;
    while( 1 ) //event loop
    {
        read( fd, &e, sizeof(e) );
        //printf( "%d %d %d %d\n", e.time, e.value, e.type, e.number );

        if( e.type == JS_EVENT_BUTTON || e.type == JS_EVENT_AXIS )
        {
            if( e.type == JS_EVENT_BUTTON ){
                printf( "button#%d value:%d\n", (int) e.number, e.value );

        switch((int) e.number) {
                case 0  ://Btn A, Motor 1---Atrás
                if ((int) e.value == 1){
                printf("Hola esto es 0\n Btn A, Motor 1---Atrás");
                char escribe[1] = "1";
                    //Acceso al driver 4_leds

                    system("sudo chmod 777 /dev/4leds");
                    archivo=fopen("/dev/4leds" ,"w");
                    if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
                    //
                fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 1 en driver
                fclose(archivo);
                    sleep(3);               
                printf("Este es escribe :%c ",*escribe);}
                else{
                printf("Hola esto es 0 pero no presionado\n");
                }

                break; 

                case 1  ://Btn B, Motor 1---Adelante
                    if ((int) e.value == 1){
                printf("Hola esto es 1\n Btn B, Motor 1---Adelante");
                char escribe[1] = "2";
                    //Acceso al driver 4_leds

                    system("sudo chmod 777 /dev/4leds");
                    archivo=fopen("/dev/4leds" ,"w");
                    if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
                    //
                fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 2 en driver
                fclose(archivo);
                    sleep(3);               
                printf("Este es escribe :%c \n",*escribe);}
                else{
                printf("Hola esto es 1 pero no presionado\n");
                }
                    break; 

                case 2  ://Btn X, Motor 2---Abajo
                if ((int) e.value == 1){
                printf("Hola esto es 2 \n Btn X, Motor 2---Abajo");
                char escribe[1] = "3";
                    //Acceso al driver 4_leds

                    system("sudo chmod 777 /dev/4leds");
                    archivo=fopen("/dev/4leds" ,"w");
                    if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
                    //
                fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 3 en driver
                fclose(archivo);
                    sleep(3);               
                printf("Este es escribe :%c \n",*escribe);}
                else{
                printf("Hola esto es 2 pero no presionado\n");
                }
                break; 

                case 3  ://Btn Y, Motor 2---Arriba
                if ((int) e.value == 1){
                printf("Hola esto es 3 \n Btn Y, Motor 2---Arriba");
                char escribe[1] = "4";
                    //Acceso al driver 4_leds

                    system("sudo chmod 777 /dev/4leds");
                    archivo=fopen("/dev/4leds" ,"w");
                    if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
                    //
                fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 4 en driver
                    fclose(archivo);
                    sleep(3);               
                printf("Este es escribe :%c \n",*escribe);}
                else{
                printf("Hola esto es 3 pero no presionado\n");
                }
                break; 

                case 7  ://Detener
                if ((int) e.value == 1){
                printf("Hola esto es Start/Stop \n");
                char escribe[1] = "0";
                    //Acceso al driver 4_leds

                    system("sudo chmod 777 /dev/4leds");
                    archivo=fopen("/dev/4leds" ,"w");
                    if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
                    //
                fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 0 en driver
                fclose(archivo);
                    sleep(3);
                printf("Este es escribe :%c \n",*escribe);}
                else{
                printf("Hola esto es 7 pero no presionado\n");
                }
                break; 

                default : /* Optional */
                printf("Hola esto es default también sirve como stop\n");
                char escribe[1] = "0";
                    //Acceso al driver 4_leds

                    system("sudo chmod 777 /dev/4leds");
                    archivo=fopen("/dev/4leds" ,"w");
                    if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}
                    //
                fwrite(escribe ,sizeof(char) ,tamano , archivo);//Escribe 0 en driver
                    fclose(archivo);
                        sleep(3);               
                printf("Este es escribe :%c \n",*escribe);
                     }
        printf("El último presionado fue: %X \n",(char) e.number);}
            else{
                printf( "axis#%d value:%d \n", (int) e.number, e.value );}
        }
        else
        {
            printf( "Init Events\n" );
        }

    }
    return 0;
}

I am getting segmentation fault so I think it may be a problem with the memory allocation in the buffer of the copy_from_user...but I don't now how to solve it.

I've tried opening the file before the while and then writing on it in every switch case, also opening the file and writing on it in the switch case...and so on.

The driver works fine with another application that is not event.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc, char **argv){

FILE *archivo;
char escribe[1];
char lee[1];
int  tamano, i;
int registro=0;
int registro2=0;

tamano=1;

printf("introduzca el numero que quiere escribir: ");
scanf("%c" ,escribe);
printf("%c ",*escribe);
system("sudo chmod 777 /dev/4leds");

archivo=fopen("/dev/4leds" ,"w");
if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}

fwrite(escribe ,sizeof(char) ,tamano , archivo);

printf("El valor escrito fue: %c \n" , *escribe);

fclose(archivo);

sleep(3);

/*archivo=fopen("/dev/4leds", "r");
if (archivo==NULL){fputs("No existe el archivo" ,stderr); exit(1);}

for (i=0;i<4;i++)
    {
    registro=registro << 8;
    fread(lee ,tamano*sizeof(char),1,archivo);
    registro=registro | *lee;
    }

registro2=registro2 | (registro << 24 & 0xFF000000);
registro2=registro2 | (registro << 8  & 0x00FF0000);
registro2=registro2 | (registro >> 8  & 0x0000FF00);
registro2=registro2 | (registro >> 24 & 0x000000FF);

printf("El valor leido es: 0x%X \n" , registro2);

fclose(archivo);*/

return 0;
}

Thanks for your help and advices. Sorry for the commented code but I am testing all parts of the driver.

c
linux
linux-kernel
linux-device-driver
raspberry-pi3

1 Answer

1

tamano or number of elements is declared but never defined in main().

fwrite(escribe ,sizeof(char) ,tamano , archivo);
answered on Stack Overflow Jul 17, 2017 by atomSmasher

User contributions licensed under CC BY-SA 3.0