Forum Programmation.c Lecture sur un périphérique

Posté par  .
Étiquettes : aucune
0
22
mai
2006
Bonjours,

Je travaille actuellement sur un programme qui lit les valeurs des axes d'un joystick.

Mon problème est que ce programme ne lit ces valeurs que occasionnellement, et comme le device est géré de manière comparable a un FIFO, je me retrouve avec une valeur de l'axe qui n'est plus du tout d'actualité.

J'aimerais pouvoir obtenir la valeur correspondant au dernier event du joystick.

J'ai envisager plusieurs possibilités:

- "lseek(device_fd,-sizeof(struct js_event),SEEK_END)" mais ça n'a aucun résultat

- Emission d'un signal lors d'une réception dans le fichier (device) et connexion de ce signal a une fonction qui met à jour la valeur de mon axe, mais je ne trouve aucun moyen d'émettre un signal lors d'une réception dans le fichier.

- Un fonctionnement similaire en créant un thread qui contiendrait une boucle infinie contenant un "select" (sans timeout) sur le descripteur de fichier et qui mettrait à jour la valeur de l'axe. Mais je n'ai jamais joué avec les threads et je ne sais pas si je peux modifier une variable globale (int) sans vérifier qu'il ne soit pas utilisé dans un autre thread!


 
#define IMAGES_PATH "/mnt/ramdisk/img"
#define DEVICE_FILE "/dev/input/js0"

gint imagecpt=0;
GtkWidget *image=NULL;
GList *namelist=NULL;
gint windowwidth=800;
gint windowheight=600;

struct itimerval timer;
int device_fd=0;
int axe=0;

//******************************************************************************
// Fonction appelée a chaque fin de timer
//******************************************************************************
//gboolean update_image(gpointer data){
void update_image(int signal){

GError *error=NULL;
GdkPixbuf *pixbuf=NULL;
GdkPixbuf *scaledpixbuf=NULL;
gchar *filename=NULL;
struct js_event js;

//lseek(device_fd,-sizeof(struct js_event),SEEK_END);
read(device_fd, &js, sizeof(struct js_event));
if((js.type & ~JS_EVENT_INIT)==JS_EVENT_AXIS && js.number==2){
axe=js.value;
}

if(axe>10){
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 40000*32767/axe;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer, NULL);

filename = g_list_nth_data(namelist, imagecpt);
if(filename == NULL){
gtk_main_quit();
return;
}
pixbuf = gdk_pixbuf_new_from_file(filename, &error);
if(pixbuf==NULL){
printf("Error: %s: %s\n",filename,error->message);
exit(69);
}
scaledpixbuf=gdk_pixbuf_scale_simple(pixbuf, windowwidth, windowheight, GDK_INTERP_NEAREST);
gtk_image_clear(GTK_IMAGE(image));
gtk_image_set_from_pixbuf(GTK_IMAGE(image), scaledpixbuf);
g_object_unref(pixbuf);
g_object_unref(scaledpixbuf);

imagecpt = imagecpt+1;

return;
}

timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 40000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer, NULL);

}


//******************************************************************************
// Actualisation de la taille de l'image à la taille de la fenetre
//******************************************************************************
gboolean size_updated(GtkWidget *widget, GdkEventConfigure *event, gpointer user_data){
windowwidth = event->width;
windowheight = event->height;
printf("%d , %d\n",windowwidth, windowheight);
return FALSE;
}


//******************************************************************************
// Main
//******************************************************************************
int main(int argc,char **argv){
GtkWidget *mainwindow=NULL;
GDir *dir=NULL;
gchar *filename=NULL;
gchar *name=NULL;


//Ouverture du device et mode nonblocant
if((device_fd = open(DEVICE_FILE, O_RDONLY)) < 0) {
perror(DEVICE_FILE);
return 1;
}
fcntl(device_fd, F_SETFL, O_NONBLOCK);

//Recuperation des noms de fichier et tri
dir = g_dir_open(IMAGES_PATH,0,NULL);
while(1){
filename = g_strdup(g_dir_read_name(dir));
if(filename == NULL)
break;
name = g_malloc((strlen(IMAGES_PATH)+strlen(filename)+1)* sizeof(gchar));
g_sprintf(name,"%s/%s",IMAGES_PATH,filename);
g_free(filename);
namelist = g_list_append(namelist,name);
}
namelist = g_list_sort(namelist,(GCompareFunc)strcmp);

// Construction interface GTK
gtk_init(&argc,&argv);
mainwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(mainwindow),"destroy",G_CALLBACK(gtk_main_quit),NULL);
g_signal_connect(G_OBJECT(mainwindow),"configure-event",G_CALLBACK(size_updated),NULL);

gtk_window_resize(GTK_WINDOW(mainwindow),640, 480);
//gtk_window_fullscreen(GTK_WINDOW(mainwindow));
image = gtk_image_new();
gtk_container_add(GTK_CONTAINER(mainwindow),image);
gtk_widget_show_all(mainwindow);

// Timer
signal(SIGALRM,update_image);
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 40000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer, NULL);

// Départ de la boucle principale
gtk_main();

return (0);
}


Question subsidiaire: Pour afficher/redimensionner une image j'utilise gdk_pixbuf et gtk_image car je ne connais que gtk.

Y aurait-il une méthode plus simple et/ou plus rapide (sdl, opengl, ...)
  • # mutex

    Posté par  . Évalué à 1.

    Arretez moi si j'me trompe, mais il me semble que les mutex sont justement là pour bloquer l'accès aux variables globales pendant qu'elle sont modifier. Donc si les modifications de ton int sont encadrées d'un pthread_mutex_lock() et pthread_mutex_unlock() a priori, devrais pas y avoir de problèmes.
    • [^] # Re: mutex

      Posté par  . Évalué à 1.

      En fait je n'en sais rien, je n'ai jamais utilisé les thread, je sais juste que ca existe. Je suppose bien qu'il y a un mecanisme pour éviter les accès concurents mais j'espérais que ce ne soit pas necessaire pour une simple variable globale.

      Je vais me documenter de ce coté, mais des 3 solutions c'est celle qui me plaisait le moins. (c'est celle qui va me demander le plus de travail!)

      merci

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.