project for a (works on my devices) demo
This commit is contained in:
201
registries_items.c
Normal file
201
registries_items.c
Normal file
@@ -0,0 +1,201 @@
|
||||
#include "registries_items.h"
|
||||
|
||||
#include <libevdev.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#include "events.h"
|
||||
|
||||
pthread_barrier_t all_devices_wrote_barrier;
|
||||
pthread_barrier_t devices_write_new_round_barrier;
|
||||
|
||||
/* the spawning thread must reach the barrier and only after that, take the mutex
|
||||
the spawned instead first takes the mutex and sets the flag, then releases the mutex and reach the barrier, thus allowing the spawning to get a consistent read
|
||||
|
||||
!!!
|
||||
beware that if a signal reaches a waiting thread, that thread will handle the signal and then resume its wait unless such wait didn't complete in the meanwhile
|
||||
!!! it is unspecified whether the other threads wait for the signaled thread
|
||||
*/
|
||||
pthread_barrier_t device_added_flag_barrier;
|
||||
pthread_mutex_t device_added_flag_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
int device_added_flag;
|
||||
|
||||
|
||||
pthread_mutex_t enqueue_events_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
/* nice struct from the phtread_create manpage example */
|
||||
typedef struct { /* Used as argument to thread_start() */
|
||||
pthread_t thread_id; /* ID returned by pthread_create() */
|
||||
int thread_num; /* Application-defined thread # */
|
||||
char *argv_string; /* From command-line argument */
|
||||
} thread_info;
|
||||
|
||||
|
||||
void initialize_device_added_flag_barrier(){
|
||||
int anyerror = pthread_barrier_init( &device_added_flag_barrier, NULL, 2);
|
||||
if(anyerror){
|
||||
fprintf( stderr, "setup failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void* collecting_routine( void *args){
|
||||
const char *path = (char*) args;
|
||||
|
||||
struct libevdev *dev = NULL;
|
||||
int fd;
|
||||
int rc = 1;
|
||||
int open_error = 0;
|
||||
|
||||
struct input_event ev;
|
||||
device_event *evt;
|
||||
|
||||
events_queue *queue;
|
||||
|
||||
fd = open( path, O_RDONLY|O_NONBLOCK);
|
||||
rc = libevdev_new_from_fd( fd, &dev);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to init libevdev for device (%s)\n", strerror(-rc));
|
||||
fprintf(stderr, "[NEWBIE TIP] : try with sudo (maybe you don't have the rights for the EVDEVs)\n");
|
||||
open_error = 1;
|
||||
}
|
||||
|
||||
pthread_mutex_lock( &device_added_flag_mutex);
|
||||
device_added_flag = ( !open_error);
|
||||
pthread_mutex_unlock( &device_added_flag_mutex);
|
||||
|
||||
pthread_barrier_wait( &device_added_flag_barrier);
|
||||
|
||||
if( !open_error){
|
||||
queue = events_queue_new();
|
||||
|
||||
printf( "Input device name: \"%s\"\n", libevdev_get_name( dev));
|
||||
printf( "Input device ID: bus %#x vendor %#x product %#x\n",
|
||||
libevdev_get_id_bustype( dev),
|
||||
libevdev_get_id_vendor( dev),
|
||||
libevdev_get_id_product( dev));
|
||||
/*
|
||||
if (!libevdev_has_event_type(dev, EV_REL) ||
|
||||
!libevdev_has_event_code(dev, EV_KEY, BTN_LEFT)) {
|
||||
printf("This device does not look like a mouse\n");
|
||||
exit(1);
|
||||
}
|
||||
*/
|
||||
|
||||
do {
|
||||
rc = libevdev_next_event( dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
|
||||
/* RC = 1 should be SYN_DROPPED event */
|
||||
if (rc == 0){
|
||||
evt = malloc( sizeof( device_event));
|
||||
evt->type = ev.type;
|
||||
evt->code = ev.code;
|
||||
evt->value = ev.value;
|
||||
add_to_events_queue( queue, evt);
|
||||
|
||||
/*
|
||||
printf("LIBEVDEV Event: %s %s %d\n",
|
||||
libevdev_event_type_get_name( ev.type),
|
||||
libevdev_event_code_get_name( ev.type, ev.code),
|
||||
ev.value);
|
||||
*/
|
||||
}
|
||||
if( rc == -EAGAIN){
|
||||
/*
|
||||
printf("lock %s\n", libevdev_get_name( dev));
|
||||
*/
|
||||
pthread_mutex_lock( &enqueue_events_mutex);
|
||||
add_all_to_global_queue( queue);
|
||||
pthread_mutex_unlock( &enqueue_events_mutex);
|
||||
pthread_barrier_wait( &all_devices_wrote_barrier);
|
||||
pthread_barrier_wait( &devices_write_new_round_barrier);
|
||||
}
|
||||
}
|
||||
while ( rc == 1 || rc == 0 || rc == -EAGAIN);
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* !!! type defaults to INSERT */
|
||||
pending_registry_request* pending_registry_request_new( const char *path){
|
||||
pending_registry_request *req = malloc( sizeof( pending_registry_request));
|
||||
req->path = malloc( ( 1 + strlen( path)) * sizeof( char));
|
||||
strcpy( req->path, path);
|
||||
return req;
|
||||
}
|
||||
|
||||
void pending_registry_request_destroy( pending_registry_request *req){
|
||||
free( req->path);
|
||||
free( req);
|
||||
}
|
||||
|
||||
active_registry_item* active_registry_item_dummy_new( const char *path){
|
||||
active_registry_item* item = malloc( sizeof( active_registry_item));
|
||||
item->path = malloc(( 1 + strlen( path)) * sizeof(char));
|
||||
strcpy( item->path, path);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
active_registry_item* active_registry_item_new( const char *path){
|
||||
active_registry_item* item = active_registry_item_dummy_new( path);
|
||||
|
||||
/*HERE CREATE THE THREAD*/
|
||||
thread_info th_info;
|
||||
/*
|
||||
all the thread attribute stuff has been postponed
|
||||
|
||||
SCHED(7)
|
||||
Response time
|
||||
A blocked high priority thread waiting for I/O has a certain response time before it is scheduled again. The device driver writer can greatly reduce this response time by using
|
||||
a "slow interrupt" interrupt handler.
|
||||
|
||||
https://en.wikipedia.org/wiki/Interrupt_handler
|
||||
*/
|
||||
/* null implies default values */
|
||||
const pthread_attr_t *attr = NULL;
|
||||
|
||||
int thread_create_failed = 1;
|
||||
int device_add_error = 0;
|
||||
|
||||
thread_create_failed = pthread_create(
|
||||
&th_info.thread_id,
|
||||
attr,
|
||||
collecting_routine,
|
||||
(void *) path
|
||||
);
|
||||
|
||||
if( thread_create_failed){
|
||||
fprintf( stderr, "unable to create device polling thread\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_barrier_wait( &device_added_flag_barrier);
|
||||
|
||||
pthread_mutex_lock( &device_added_flag_mutex);
|
||||
device_add_error = ( !device_added_flag);
|
||||
pthread_mutex_unlock( &device_added_flag_mutex);
|
||||
|
||||
if( device_add_error){
|
||||
fprintf( stderr, "device polling thread failed to initialize its resources\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void active_registry_item_dummy_destroy(active_registry_item *item){
|
||||
free( item->path);
|
||||
free( item);
|
||||
}
|
||||
|
||||
void active_registry_item_destroy( active_registry_item *item){
|
||||
pthread_cancel( item->thread);
|
||||
active_registry_item_dummy_destroy( item);
|
||||
}
|
||||
Reference in New Issue
Block a user