From 4b5c09297f11b2612a9072fc05a244fbc2c0ddc0 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 17 Nov 2003 21:09:45 +0000 Subject: cleaned up code substantially; got everything working; made help patches svn path=/trunk/externals/hcs/; revision=1192 --- Makefile | 4 +- linuxevent-help.pd | 70 +++++--- linuxevent-joystick.pd | 93 +++++++--- linuxevent.c | 175 ++++++++---------- linuxhid.h | 6 +- linuxhid.pd | 12 ++ linuxjoystick-help.pd | 205 +++++++++++---------- linuxjoystick.c | 452 ++++++++++++++++++++++++----------------------- linuxmouse-help.pd | 48 +++-- linuxmouse.c | 471 ++++++++++++++++++++++--------------------------- 10 files changed, 802 insertions(+), 734 deletions(-) create mode 100644 linuxhid.pd diff --git a/Makefile b/Makefile index a7041a3..303eb1e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC=gcc-3.2 -pd_linux: pan_gogins~.pd_linux range.pd_linux linuxmouse.pd_linux linuxevent.pd_linux linuxjoystick.pd_linux ifeel.pd_linux +pd_linux: pan_gogins~.pd_linux range.pd_linux linuxmouse.pd_linux linuxevent.pd_linux linuxjoystick.pd_linux ifeel.pd_linux platformdummy.pd_linux clean: ; rm -f *.pd_linux *.o *~ @@ -12,7 +12,7 @@ LINUXCFLAGS = -DUNIX -DPD -O2 -funroll-loops -fomit-frame-pointer \ -Wall -W -Wshadow -Wstrict-prototypes -Werror \ -Wno-unused -Wno-parentheses -Wno-switch -LINUXINCLUDE = -I/usr/local/lib/pd/include -I../../pd/src +LINUXINCLUDE = -I/usr/local/lib/pd/include -I../../pd/src -I/usr/local/include .c.pd_linux: $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c diff --git a/linuxevent-help.pd b/linuxevent-help.pd index 1580638..9b0971a 100644 --- a/linuxevent-help.pd +++ b/linuxevent-help.pd @@ -1,24 +1,20 @@ -#N canvas 547 51 569 453 10; +#N canvas 287 167 569 543 10; #X floatatom 241 326 5 0 0 3 code - -; #X floatatom 305 326 5 0 0 3 value - -; #X floatatom 177 326 4 0 0 3 type - -; #X floatatom 104 326 9 0 0 3 time - -; -#X msg 164 199 start; -#X msg 165 221 stop; +#X msg 172 202 start; +#X msg 173 224 stop; #X obj 114 303 linuxevent /dev/input/event0; -#X obj 114 158 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +#X obj 114 184 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; -#X text 134 158 bang to get an update; -#X text 212 211 start/stop polling; -#X obj 25 158 metro 20; -#X text 236 260 time between polls (ms); -#X obj 25 136 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +#X obj 25 184 metro 20; +#X text 293 260 time between polls (ms); +#X obj 25 162 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; -#X msg 45 136 stop; -#X msg 169 260 delay 20; -#X obj 114 109 key; -#X obj 114 129 select 98; -#X text 187 129 <- type 'b' for a bang; +#X msg 45 162 stop; +#X msg 226 260 delay 20; +#X obj 114 135 key; #N canvas 278 328 611 524 Event_Codes 0; #X text 28 48 (For a complete listing of Linux Input Events \, see /usr/include/linux/input.h.); @@ -180,8 +176,26 @@ This object will report them when it opens a device.; #X text 17 50 [linuxevent] outputs raw events from the Linux Event system. It is used for access the output of various Human Interface Devices \, like mice \, joysticks \, tablets \, etc.; -#X text 62 424 Here's an example for using a joystick:; -#X obj 366 423 linuxevent-joystick; +#X text 346 18 related HID objects:; +#X obj 497 17 linuxhid; +#X text 33 111 bang to get an update when polling is stopped.; +#X msg 236 201 poll; +#X msg 236 223 nopoll; +#X text 153 183 start/stop polling (synonyms for the same thing); +#X obj 114 155 sel 98; +#X text 160 155 <- (type 'b' for a bang); +#X text 15 413 Here's an example for using a joystick:; +#X msg 72 441 start; +#X msg 116 441 stop; +#X obj 82 469 linuxevent-joystick /dev/input/event1; +#X floatatom 336 498 2 0 0 3 button# - -; +#X floatatom 393 497 2 0 0 3 button_value - -; +#X floatatom 82 498 5 0 0 3 y-axis - -; +#X floatatom 35 498 5 0 0 3 x-axis - -; +#X floatatom 181 499 3 0 0 3 hat-X - -; +#X floatatom 227 499 3 0 0 3 hat-Y - -; +#X floatatom 131 499 5 0 0 3 twist - -; +#X floatatom 270 498 5 0 0 3 throttle - -; #X connect 4 0 6 0; #X connect 5 0 6 0; #X connect 6 0 3 0; @@ -189,9 +203,21 @@ Devices \, like mice \, joysticks \, tablets \, etc.; #X connect 6 2 0 0; #X connect 6 3 1 0; #X connect 7 0 6 0; -#X connect 10 0 6 0; -#X connect 12 0 10 0; -#X connect 13 0 10 0; -#X connect 14 0 6 0; -#X connect 15 0 16 0; -#X connect 16 0 7 0; +#X connect 8 0 6 0; +#X connect 10 0 8 0; +#X connect 11 0 8 0; +#X connect 12 0 6 0; +#X connect 13 0 26 0; +#X connect 23 0 6 0; +#X connect 24 0 6 0; +#X connect 26 0 7 0; +#X connect 29 0 31 0; +#X connect 30 0 31 0; +#X connect 31 0 35 0; +#X connect 31 1 34 0; +#X connect 31 2 38 0; +#X connect 31 3 36 0; +#X connect 31 4 37 0; +#X connect 31 5 39 0; +#X connect 31 6 32 0; +#X connect 31 7 33 0; diff --git a/linuxevent-joystick.pd b/linuxevent-joystick.pd index d3d5eda..029b7f3 100644 --- a/linuxevent-joystick.pd +++ b/linuxevent-joystick.pd @@ -1,29 +1,76 @@ -#N canvas 270 365 499 362 10; -#X obj 16 86 linuxevent /dev/input/event1; +#N canvas 455 201 722 483 10; #X msg 35 43 start; #X msg 44 62 stop; #X obj 16 9 inlet; #X obj 79 116 pack f f f; -#X obj 79 139 route 1 3; #X obj 137 159 print UNKNOWN_JOYSTICK_EVENT_TYPE; #X text 148 139 types (1=buttons 3=abs axes); -#X obj 108 187 route 0 1 6 7; -#X obj 194 209 print UNKNOWN_JOYSTICK_EVENT_CODE; -#X obj 151 249 print THROTTLE; -#X text 204 190 codes (0=X 1=Y 6=throttle 7=rudder); -#X obj 172 229 print RUDDER; -#X obj 129 269 print Y-AXIS; -#X obj 108 290 print X-AXIS; -#X connect 0 1 4 0; -#X connect 0 2 4 1; -#X connect 0 3 4 2; -#X connect 1 0 0 0; -#X connect 2 0 0 0; -#X connect 3 0 0 0; -#X connect 4 0 5 0; -#X connect 5 1 8 0; -#X connect 5 2 6 0; -#X connect 8 0 14 0; -#X connect 8 1 13 0; -#X connect 8 2 10 0; -#X connect 8 3 12 0; +#X obj 167 256 print UNKNOWN_JOYSTICK_EVENT_CODE; +#X obj 275 409 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 306 409 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 337 409 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 369 408 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 400 408 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 431 409 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 557 410 bng 30 250 50 0 empty empty not_routed 33 6 1 8 -262144 +-1 -1; +#X obj 275 386 route 288 289 290 291 292 293 294 295 296; +#X obj 464 409 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 493 408 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 525 408 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 79 139 route 3 1; +#X obj 38 378 outlet; +#X obj 59 357 outlet; +#X obj 80 337 outlet; +#X obj 102 317 outlet; +#X obj 123 297 outlet; +#X obj 144 277 outlet; +#X text 52 214 codes (0=X 1=Y 6=throttle 7=rudder \, 16=hat0X \, 17=hat0Y) +; +#X obj 456 338 outlet; +#X text 446 354 button_num; +#X text 537 355 button_value; +#X obj 556 339 outlet; +#X obj 456 272 unpack f f; +#X obj 456 308 - 288; +#X obj 16 86 linuxevent \$1; +#X obj 38 234 route 0 1 7 16 17 6; +#X connect 0 0 32 0; +#X connect 1 0 32 0; +#X connect 2 0 32 0; +#X connect 3 0 18 0; +#X connect 14 0 7 0; +#X connect 14 1 8 0; +#X connect 14 2 9 0; +#X connect 14 3 10 0; +#X connect 14 4 11 0; +#X connect 14 5 12 0; +#X connect 14 6 15 0; +#X connect 14 7 16 0; +#X connect 14 8 17 0; +#X connect 14 9 13 0; +#X connect 18 0 33 0; +#X connect 18 1 14 0; +#X connect 18 1 30 0; +#X connect 18 2 4 0; +#X connect 30 0 31 0; +#X connect 30 1 29 0; +#X connect 31 0 26 0; +#X connect 32 1 3 0; +#X connect 32 2 3 1; +#X connect 32 3 3 2; +#X connect 33 0 19 0; +#X connect 33 1 20 0; +#X connect 33 2 21 0; +#X connect 33 3 22 0; +#X connect 33 4 23 0; +#X connect 33 5 24 0; diff --git a/linuxevent.c b/linuxevent.c index c9901c9..b53a2b0 100644 --- a/linuxevent.c +++ b/linuxevent.c @@ -1,9 +1,8 @@ #include "linuxhid.h" #define LINUXEVENT_DEVICE "/dev/input/event0" -#define LINUXEVENT_OUTLETS 4 -static char *version = "$Revision: 1.3 $"; +static char *version = "$Revision: 1.4 $"; /*------------------------------------------------------------------------------ * CLASS DEF @@ -13,38 +12,46 @@ static t_class *linuxevent_class; typedef struct _linuxevent { t_object x_obj; t_int x_fd; - t_symbol* x_devname; + t_symbol *x_devname; t_clock *x_clock; int read_ok; int started; + int x_delaytime; struct input_event x_input_event; t_outlet *x_input_event_time_outlet; t_outlet *x_input_event_type_outlet; t_outlet *x_input_event_code_outlet; t_outlet *x_input_event_value_outlet; - int x_delaytime; }t_linuxevent; /*------------------------------------------------------------------------------ * IMPLEMENTATION */ -//DONE -static int linuxevent_close(t_linuxevent *x) -{ - DEBUG(post("linuxevent_close");) - - if (x->x_fd <0) { - return 0; - } else { - close (x->x_fd); - return 1; +void linuxevent_stop(t_linuxevent* x) { + DEBUG(post("linuxevent_stop");); + + if (x->x_fd >= 0 && x->started) { + clock_unset(x->x_clock); + post("linuxevent: polling stopped"); + x->started = 0; } } -//DONE -static int linuxevent_open(t_linuxevent *x,t_symbol* s) -{ +static int linuxevent_close(t_linuxevent *x) { + DEBUG(post("linuxevent_close");); + +/* just to be safe, stop it first */ + linuxevent_stop(x); + + if (x->x_fd <0) return 0; + close (x->x_fd); + post ("[linuxevent] closed %s",x->x_devname->s_name); + + return 1; +} + +static int linuxevent_open(t_linuxevent *x, t_symbol *s) { int eventType, eventCode, buttons, rel_axes, abs_axes, ff; unsigned long bitmask[EV_MAX][NBITS(KEY_MAX)]; char devicename[256] = "Unknown"; @@ -57,30 +64,18 @@ static int linuxevent_open(t_linuxevent *x,t_symbol* s) */ if (s != &s_) x->x_devname = s; - else { - post("You need to set a input device (i.e /dev/input/event0)"); - } /* open device */ if (x->x_devname) { - post("opening ..."); - /* open the linuxevent device read-only, non-exclusive */ - x->x_fd = open (x->x_devname->s_name, O_RDONLY | O_NONBLOCK); - if (x->x_fd >= 0 ) post("done"); - else post("failed"); - } - else { - return 1; - } - - /* test if device open */ - if (x->x_fd >= 0) - post("%s opened",x->x_devname->s_name); - else { - post("unable to open %s",x->x_devname->s_name); - x->x_fd = -1; - return 0; - } + /* open the device read-only, non-exclusive */ + x->x_fd = open (x->x_devname->s_name, O_RDONLY | O_NONBLOCK); + /* test if device open */ + if (x->x_fd < 0 ) { + post("[linuxevent] open %s failed",x->x_devname->s_name); + x->x_fd = -1; + return 0; + } + } else return 1; /* read input_events from the LINUXEVENT_DEVICE stream * It seems that is just there to flush the event input buffer? @@ -89,12 +84,12 @@ static int linuxevent_open(t_linuxevent *x,t_symbol* s) /* get name of device */ ioctl(x->x_fd, EVIOCGNAME(sizeof(devicename)), devicename); - post ("configuring %s",devicename); + post ("Configuring %s on %s",devicename,x->x_devname->s_name); /* get bitmask representing supported events (axes, buttons, etc.) */ memset(bitmask, 0, sizeof(bitmask)); ioctl(x->x_fd, EVIOCGBIT(0, EV_MAX), bitmask[0]); - post("Supported events:"); + post("\nSupported events:"); rel_axes = 0; abs_axes = 0; @@ -147,42 +142,34 @@ static int linuxevent_open(t_linuxevent *x,t_symbol* s) post ("\nUsing %d relative axes, %d absolute axes, and %d buttons.", rel_axes, abs_axes, buttons); if (ff > 0) post ("Detected %d force feedback types",ff); - post (""); - post ("WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING"); + post ("\nWARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING"); post ("This object is under development! The interface could change at anytime!"); post ("As I write cross-platform versions, the interface might have to change."); - post ("WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING"); - + post ("WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING\n"); + return 1; } +static int linuxevent_read(t_linuxevent *x,int fd) { + if (x->x_fd < 0) return 0; - -static int linuxevent_read(t_linuxevent *x,int fd) -{ -// int readBytes; - - if (x->x_fd < 0) return 0; - - while (read (x->x_fd, &(x->x_input_event), sizeof(struct input_event)) > -1) { - outlet_float (x->x_input_event_value_outlet, (int)x->x_input_event.value); - outlet_float (x->x_input_event_code_outlet, x->x_input_event.code); - outlet_float (x->x_input_event_type_outlet, x->x_input_event.type); - /* input_event.time is a timeval struct from */ - /* outlet_float (x->x_input_event_time_outlet, x->x_input_event.time); */ - } + while (read (x->x_fd, &(x->x_input_event), sizeof(struct input_event)) > -1) { + outlet_float (x->x_input_event_value_outlet, (int)x->x_input_event.value); + outlet_float (x->x_input_event_code_outlet, x->x_input_event.code); + outlet_float (x->x_input_event_type_outlet, x->x_input_event.type); + /* input_event.time is a timeval struct from */ + /* outlet_float (x->x_input_event_time_outlet, x->x_input_event.time); */ + } - if (x->started) { - clock_delay(x->x_clock, x->x_delaytime); - } + if (x->started) { + clock_delay(x->x_clock, x->x_delaytime); + } - return 1; + return 1; } /* Actions */ - -static void linuxevent_float(t_linuxevent* x) -{ +static void linuxevent_float(t_linuxevent* x) { DEBUG(post("linuxevent_float");) } @@ -198,39 +185,20 @@ void linuxevent_delay(t_linuxevent* x, t_float f) { } } -// DONE -void linuxevent_start(t_linuxevent* x) -{ - DEBUG(post("linuxevent_start");); - post("clock delay: %d",x->x_delaytime); +void linuxevent_start(t_linuxevent* x) { + DEBUG(post("linuxevent_start");); - if (x->x_fd >= 0 && !x->started) { - clock_delay(x->x_clock, 2); - post("linuxevent: start"); - x->started = 1; - } -} - - -// DONE -void linuxevent_stop(t_linuxevent* x) -{ - DEBUG(post("linuxevent_stop");); - - post("clock delay: %d",x->x_delaytime); - - if (x->x_fd >= 0 && x->started) { - clock_unset(x->x_clock); - post("linuxevent: stop"); - x->started = 0; - } + if (x->x_fd >= 0 && !x->started) { + clock_delay(x->x_clock, 5); + post("linuxevent: polling started"); + x->started = 1; + } else { + post("You need to set a input device (i.e /dev/input/event0)"); + } } -/* Misc setup functions */ - - -static void linuxevent_free(t_linuxevent* x) -{ +/* setup functions */ +static void linuxevent_free(t_linuxevent* x) { DEBUG(post("linuxevent_free");) if (x->x_fd < 0) return; @@ -240,8 +208,7 @@ static void linuxevent_free(t_linuxevent* x) close (x->x_fd); } -static void *linuxevent_new(t_symbol *s) -{ +static void *linuxevent_new(t_symbol *s) { int i; t_linuxevent *x = (t_linuxevent *)pd_new(linuxevent_class); @@ -263,8 +230,9 @@ static void *linuxevent_new(t_symbol *s) x->x_input_event_code_outlet = outlet_new(&x->x_obj, &s_float); x->x_input_event_value_outlet = outlet_new(&x->x_obj, &s_float); + /* set to the value from the object argument, if that exists */ if (s != &s_) - x->x_devname = s; + x->x_devname = s; /* Open the device and save settings */ @@ -273,9 +241,7 @@ static void *linuxevent_new(t_symbol *s) return (x); } - -void linuxevent_setup(void) -{ +void linuxevent_setup(void) { DEBUG(post("linuxevent_setup");) linuxevent_class = class_new(gensym("linuxevent"), (t_newmethod)linuxevent_new, @@ -287,11 +253,12 @@ void linuxevent_setup(void) class_addbang(linuxevent_class,(t_method) linuxevent_read); /* add inlet message methods */ - class_addmethod(linuxevent_class, (t_method) linuxevent_open,gensym("open"),A_DEFSYM); + class_addmethod(linuxevent_class,(t_method) linuxevent_delay,gensym("delay"),A_DEFFLOAT,0); + class_addmethod(linuxevent_class,(t_method) linuxevent_open,gensym("open"),A_DEFSYM,0); class_addmethod(linuxevent_class,(t_method) linuxevent_close,gensym("close"),0); class_addmethod(linuxevent_class,(t_method) linuxevent_start,gensym("start"),0); + class_addmethod(linuxevent_class,(t_method) linuxevent_start,gensym("poll"),0); class_addmethod(linuxevent_class,(t_method) linuxevent_stop,gensym("stop"),0); - class_addmethod(linuxevent_class,(t_method) linuxevent_delay,gensym("delay"),A_FLOAT,0); - + class_addmethod(linuxevent_class,(t_method) linuxevent_stop,gensym("nopoll"),0); } diff --git a/linuxhid.h b/linuxhid.h index e4607bb..9682503 100644 --- a/linuxhid.h +++ b/linuxhid.h @@ -1,4 +1,4 @@ -#include "m_pd.h" +#include #ifdef PD_MAJOR_VERSION #include "s_stuff.h" @@ -18,8 +18,8 @@ #include -#define DEBUG(x) -/*#define DEBUG(x) x */ +//#define DEBUG(x) +#define DEBUG(x) x /*------------------------------------------------------------------------------ * from evtest.c from the ff-utils package diff --git a/linuxhid.pd b/linuxhid.pd new file mode 100644 index 0000000..96440fa --- /dev/null +++ b/linuxhid.pd @@ -0,0 +1,12 @@ +#N canvas 618 332 428 305 10; +#X obj 13 10 cnv 15 400 40 empty empty Linux_HID 20 12 1 18 -261689 +-66577 0; +#X text 28 96 Raw access to the mouse output \, not tied to the sccreen +borders.; +#X text 22 169 Raw access to the joystick output with a fixed number +of outlets.; +#X text 22 239 Raw access to the output of the Linux Event system. +; +#X obj 16 75 linuxmouse; +#X obj 18 219 linuxevent; +#X obj 16 146 linuxjoystick; diff --git a/linuxjoystick-help.pd b/linuxjoystick-help.pd index 0c37469..874aaa5 100644 --- a/linuxjoystick-help.pd +++ b/linuxjoystick-help.pd @@ -1,98 +1,125 @@ -#N canvas 61 386 886 505 10; -#X msg 192 64 start; -#X msg 203 95 stop; -#X floatatom 397 180 2 0 0 3 button# - -; -#X floatatom 454 179 2 0 0 3 button_value - -; -#X floatatom 143 180 5 0 0 3 y-axis - -; -#X floatatom 95 180 5 0 0 3 x-axis - -; -#X floatatom 242 181 3 0 0 3 hat-X - -; -#X floatatom 288 181 3 0 0 3 hat-Y - -; -#X floatatom 192 181 5 0 0 3 twist - -; -#X floatatom 331 180 5 0 0 3 throttle - -; -#X obj 192 123 linuxjoystick /dev/input/event1; -#X obj 299 309 select 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +#N canvas 107 356 731 483 10; +#X floatatom 324 292 2 0 0 3 button# - -; +#X floatatom 381 291 2 0 0 3 button_value - -; +#X floatatom 70 292 5 0 0 3 y-axis - -; +#X floatatom 23 292 5 0 0 3 x-axis - -; +#X floatatom 169 293 3 0 0 3 hat-X - -; +#X floatatom 215 293 3 0 0 3 hat-Y - -; +#X floatatom 119 293 5 0 0 3 twist - -; +#X floatatom 258 292 5 0 0 3 throttle - -; +#X obj 119 235 linuxjoystick /dev/input/event1; +#X obj 211 364 select 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21; -#X obj 297 354 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +#X obj 211 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; -#X obj 313 355 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +#X obj 229 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; -#X obj 333 354 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +#X obj 248 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; -#X obj 351 354 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +#X obj 266 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; -#X obj 370 353 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +#X obj 285 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; -#X obj 389 354 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +#X obj 303 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; -#X obj 409 353 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +#X obj 322 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; -#X obj 734 354 bng 30 250 50 0 empty empty not_recognized 0 -6 0 8 +#X obj 629 403 bng 30 250 50 0 empty empty not_recognized 0 -6 0 8 -261689 -1 -1; -#X obj 689 352 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 667 350 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 647 351 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 631 354 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 613 352 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 596 350 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 579 352 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 561 351 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 541 349 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 523 351 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 503 350 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 485 351 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 466 351 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 447 353 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 428 353 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X obj 439 220 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X connect 0 0 10 0; -#X connect 1 0 10 0; -#X connect 2 0 11 0; -#X connect 3 0 35 0; -#X connect 10 0 5 0; -#X connect 10 1 4 0; -#X connect 10 2 8 0; -#X connect 10 3 6 0; -#X connect 10 4 7 0; -#X connect 10 5 9 0; -#X connect 10 6 2 0; -#X connect 10 7 3 0; -#X connect 11 0 12 0; -#X connect 11 1 13 0; -#X connect 11 2 14 0; -#X connect 11 3 15 0; -#X connect 11 4 16 0; -#X connect 11 5 17 0; -#X connect 11 6 18 0; -#X connect 11 7 34 0; -#X connect 11 8 33 0; -#X connect 11 9 32 0; -#X connect 11 10 31 0; -#X connect 11 11 30 0; -#X connect 11 12 29 0; -#X connect 11 13 28 0; -#X connect 11 14 27 0; -#X connect 11 15 26 0; -#X connect 11 16 25 0; -#X connect 11 17 24 0; -#X connect 11 18 23 0; -#X connect 11 19 22 0; -#X connect 11 20 21 0; -#X connect 11 21 20 0; -#X connect 11 22 19 0; -#X connect 35 0 2 0; +#X obj 600 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 581 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 563 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 544 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 526 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 507 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 489 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 470 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 452 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 433 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 415 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 396 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 377 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 359 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 340 403 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 366 332 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 20 9 cnv 15 700 30 empty empty linuxjoystick 20 12 1 16 -257472 +-66577 0; +#X text 502 17 related HID objects:; +#X obj 653 16 linuxhid; +#X msg 214 136 start; +#X msg 214 157 stop; +#X obj 156 118 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 67 118 metro 20; +#X text 335 194 time between polls (ms); +#X obj 67 96 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 87 96 stop; +#X msg 268 194 delay 20; +#X obj 156 69 key; +#X msg 278 135 poll; +#X msg 278 156 nopoll; +#X text 195 117 start/stop polling (synonyms for the same thing); +#X obj 156 89 sel 98; +#X text 202 89 <- (type 'b' for a bang); +#X connect 0 0 9 0; +#X connect 1 0 33 0; +#X connect 8 0 3 0; +#X connect 8 1 2 0; +#X connect 8 2 6 0; +#X connect 8 3 4 0; +#X connect 8 4 5 0; +#X connect 8 5 7 0; +#X connect 8 6 0 0; +#X connect 8 7 1 0; +#X connect 9 0 10 0; +#X connect 9 1 11 0; +#X connect 9 2 12 0; +#X connect 9 3 13 0; +#X connect 9 4 14 0; +#X connect 9 5 15 0; +#X connect 9 6 16 0; +#X connect 9 7 32 0; +#X connect 9 8 31 0; +#X connect 9 9 30 0; +#X connect 9 10 29 0; +#X connect 9 11 28 0; +#X connect 9 12 27 0; +#X connect 9 13 26 0; +#X connect 9 14 25 0; +#X connect 9 15 24 0; +#X connect 9 16 23 0; +#X connect 9 17 22 0; +#X connect 9 18 21 0; +#X connect 9 19 20 0; +#X connect 9 20 19 0; +#X connect 9 21 18 0; +#X connect 9 22 17 0; +#X connect 33 0 0 0; +#X connect 37 0 8 0; +#X connect 38 0 8 0; +#X connect 39 0 8 0; +#X connect 40 0 8 0; +#X connect 42 0 40 0; +#X connect 43 0 40 0; +#X connect 44 0 8 0; +#X connect 45 0 49 0; +#X connect 46 0 8 0; +#X connect 47 0 8 0; +#X connect 49 0 39 0; diff --git a/linuxjoystick.c b/linuxjoystick.c index b64588c..07c1972 100644 --- a/linuxjoystick.c +++ b/linuxjoystick.c @@ -1,9 +1,8 @@ #include "linuxhid.h" -#define LINUXJOYSTICK_DEVICE "/dev/input/event0" #define LINUXJOYSTICK_AXES 6 -static char *version = "$Revision: 1.2 $"; +static char *version = "$Revision: 1.3 $"; /*------------------------------------------------------------------------------ * CLASS DEF @@ -11,40 +10,50 @@ static char *version = "$Revision: 1.2 $"; static t_class *linuxjoystick_class; typedef struct _linuxjoystick { - t_object x_obj; - t_int x_fd; - t_symbol* x_devname; - int read_ok; - int started; - struct input_event x_input_event; - t_outlet *x_axis_out[LINUXJOYSTICK_AXES]; - t_outlet *x_button_num_out; - t_outlet *x_button_val_out; - t_clock *x_clock; - unsigned char x_buttons; - unsigned char x_axes; + t_object x_obj; + t_int x_fd; + t_symbol *x_devname; + t_clock *x_clock; + int read_ok; + int started; + int x_delaytime; + struct input_event x_input_event; + t_outlet *x_axis_out[LINUXJOYSTICK_AXES]; + t_outlet *x_button_num_out; + t_outlet *x_button_val_out; + unsigned char x_buttons; + unsigned char x_axes; } t_linuxjoystick; /*------------------------------------------------------------------------------ * IMPLEMENTATION */ -//DONE -static int linuxjoystick_close(t_linuxjoystick *x) -{ - DEBUG(post("linuxjoystick_close");) +void linuxjoystick_stop(t_linuxjoystick* x) { + DEBUG(post("linuxjoystick_stop");); + + if (x->x_fd >= 0 && x->started) { + clock_unset(x->x_clock); + post("linuxjoystick: polling stopped"); + x->started = 0; + } +} - if (x->x_fd <0) return 0; +static int linuxjoystick_close(t_linuxjoystick *x) { + DEBUG(post("linuxjoystick_close");); - close (x->x_fd); +/* just to be safe, stop it first */ + linuxjoystick_stop(x); - return 1; + if (x->x_fd <0) return 0; + close (x->x_fd); + post ("[linuxjoystick] closed %s",x->x_devname->s_name); + + return 1; } -//DONE -static int linuxjoystick_open(t_linuxjoystick *x,t_symbol* s) -{ - int eventType, eventCode; +static int linuxjoystick_open(t_linuxjoystick *x, t_symbol *s) { + int eventType, eventCode, buttons, rel_axes, abs_axes, ff; unsigned long bitmask[EV_MAX][NBITS(KEY_MAX)]; char devicename[256] = "Unknown"; DEBUG(post("linuxjoystick_open");) @@ -56,30 +65,18 @@ static int linuxjoystick_open(t_linuxjoystick *x,t_symbol* s) */ if (s != &s_) x->x_devname = s; - else { - post("You need to set a input device (i.e /dev/input/event0)"); - } /* open device */ if (x->x_devname) { - post("opening ..."); - /* open the linuxjoystick device read-only, non-exclusive */ - x->x_fd = open (x->x_devname->s_name, O_RDONLY | O_NONBLOCK); - if (x->x_fd >= 0 ) post("done"); - else post("failed"); - } - else { - return 1; - } - - /* test if device open */ - if (x->x_fd >= 0) - post("%s opened",x->x_devname->s_name); - else { - post("unable to open %s",x->x_devname->s_name); - x->x_fd = -1; - return 0; - } + /* open the device read-only, non-exclusive */ + x->x_fd = open (x->x_devname->s_name, O_RDONLY | O_NONBLOCK); + /* test if device open */ + if (x->x_fd < 0 ) { + post("[linuxjoystick] open %s failed",x->x_devname->s_name); + x->x_fd = -1; + return 0; + } + } else return 1; /* read input_events from the LINUXJOYSTICK_DEVICE stream * It seems that is just there to flush the event input buffer? @@ -88,15 +85,17 @@ static int linuxjoystick_open(t_linuxjoystick *x,t_symbol* s) /* get name of device */ ioctl(x->x_fd, EVIOCGNAME(sizeof(devicename)), devicename); - post ("configuring %s",devicename); + post ("Configuring %s on %s",devicename,x->x_devname->s_name); /* get bitmask representing supported events (axes, buttons, etc.) */ memset(bitmask, 0, sizeof(bitmask)); ioctl(x->x_fd, EVIOCGBIT(0, EV_MAX), bitmask[0]); - post("Supported events:"); + post("\nSupported events:"); - x->x_axes = 0; - x->x_buttons = 0; + rel_axes = 0; + abs_axes = 0; + buttons = 0; + ff = 0; /* cycle through all possible event types */ for (eventType = 0; eventType < EV_MAX; eventType++) { @@ -114,219 +113,224 @@ static int linuxjoystick_open(t_linuxjoystick *x,t_symbol* s) if (test_bit(eventCode, bitmask[eventType])) { post(" Event code %d (%s)", eventCode, names[eventType] ? (names[eventType][eventCode] ? names[eventType][eventCode] : "?") : "?"); - if ( eventType == EV_KEY ) - x->x_buttons++; - else if ( eventType == EV_ABS ) - x->x_axes++; + switch(eventType) { + case EV_RST: + break; + case EV_KEY: + buttons++; + break; + case EV_REL: + rel_axes++; + break; + case EV_ABS: + abs_axes++; + break; + case EV_MSC: + break; + case EV_LED: + break; + case EV_SND: + break; + case EV_REP: + break; + case EV_FF: + ff++; + break; + } } } } - post ("\nUsing %d axes and %d buttons.", x->x_axes, x->x_buttons); - post ("WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING"); + post ("\nUsing %d relative axes, %d absolute axes, and %d buttons.", rel_axes, abs_axes, buttons); + if (ff > 0) post ("Detected %d force feedback types",ff); + post ("\nWARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING"); post ("This object is under development! The interface could change at anytime!"); post ("As I write cross-platform versions, the interface might have to change."); - post ("WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING"); - + post ("WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING\n"); + return 1; } - - -static int linuxjoystick_read(t_linuxjoystick *x,int fd) -{ - int readBytes; - int axis_num = 0; - t_float button_num = 0; +static int linuxjoystick_read(t_linuxjoystick *x,int fd) { + int readBytes; + int axis_num = 0; + t_float button_num = 0; - if (x->x_fd < 0) return 0; - if (x->read_ok) { - readBytes = read(x->x_fd, &(x->x_input_event), sizeof(struct input_event)); - DEBUG(post("reading %d",readBytes);) - if ( readBytes < 0 ) { - post("linuxjoystick: read failed"); - x->read_ok = 0; - return 0; - } - } - if ( x->x_input_event.type == EV_KEY ) { - /* key/button event type */ - switch ( x->x_input_event.code ) { - case BTN_0: - button_num = 0; - break; - case BTN_1: - button_num = 1; - break; - case BTN_2: - button_num = 2; - break; - case BTN_3: - button_num = 3; - break; - case BTN_4: - button_num = 4; - break; - case BTN_5: - button_num = 5; - break; - case BTN_6: - button_num = 6; - break; - case BTN_7: - button_num = 7; - break; - case BTN_8: - button_num = 8; - break; - case BTN_9: - button_num = 9; - break; - case BTN_TRIGGER: - button_num = 10; - break; - case BTN_THUMB: - button_num = 11; - break; - case BTN_THUMB2: - button_num = 12; - break; - case BTN_TOP: - button_num = 13; - break; - case BTN_TOP2: - button_num = 14; - break; - case BTN_PINKIE: - button_num = 15; - break; - case BTN_BASE: - button_num = 16; - break; - case BTN_BASE2: - button_num = 17; - break; - case BTN_BASE3: - button_num = 18; - break; - case BTN_BASE4: - button_num = 19; - break; - case BTN_BASE5: - button_num = 20; - break; - case BTN_BASE6: - button_num = 21; - break; - } - outlet_float (x->x_button_val_out, x->x_input_event.value); - outlet_float (x->x_button_num_out, button_num); - } - else if ( x->x_input_event.type == EV_ABS ) { - /* Relative Axes Event Type */ - switch ( x->x_input_event.code ) { - case ABS_X: - axis_num = 0; - break; - case ABS_Y: - axis_num = 1; - break; - case ABS_Z: - axis_num = 2; - break; - case ABS_HAT0X: - axis_num = 3; - break; - case ABS_HAT0Y: - axis_num = 4; - break; - case ABS_THROTTLE: - axis_num = 5; - break; - } - outlet_float (x->x_axis_out[axis_num], (int)x->x_input_event.value); - } + if (x->x_fd < 0) return 0; + + while (read (x->x_fd, &(x->x_input_event), sizeof(struct input_event)) > -1) { + if ( x->x_input_event.type == EV_ABS ) { + /* Relative Axes Event Type */ + switch ( x->x_input_event.code ) { + case ABS_X: + axis_num = 0; + break; + case ABS_Y: + axis_num = 1; + break; + case ABS_Z: + axis_num = 2; + break; + case ABS_HAT0X: + axis_num = 3; + break; + case ABS_HAT0Y: + axis_num = 4; + break; + case ABS_THROTTLE: + axis_num = 5; + break; + } + outlet_float (x->x_axis_out[axis_num], (int)x->x_input_event.value); + } + else if ( x->x_input_event.type == EV_KEY ) { + /* key/button event type */ + switch ( x->x_input_event.code ) { + case BTN_0: + button_num = 0; + break; + case BTN_1: + button_num = 1; + break; + case BTN_2: + button_num = 2; + break; + case BTN_3: + button_num = 3; + break; + case BTN_4: + button_num = 4; + break; + case BTN_5: + button_num = 5; + break; + case BTN_6: + button_num = 6; + break; + case BTN_7: + button_num = 7; + break; + case BTN_8: + button_num = 8; + break; + case BTN_9: + button_num = 9; + break; + case BTN_TRIGGER: + button_num = 10; + break; + case BTN_THUMB: + button_num = 11; + break; + case BTN_THUMB2: + button_num = 12; + break; + case BTN_TOP: + button_num = 13; + break; + case BTN_TOP2: + button_num = 14; + break; + case BTN_PINKIE: + button_num = 15; + break; + case BTN_BASE: + button_num = 16; + break; + case BTN_BASE2: + button_num = 17; + break; + case BTN_BASE3: + button_num = 18; + break; + case BTN_BASE4: + button_num = 19; + break; + case BTN_BASE5: + button_num = 20; + break; + case BTN_BASE6: + button_num = 21; + break; + } + outlet_float (x->x_button_val_out, x->x_input_event.value); + outlet_float (x->x_button_num_out, button_num); + } + } + + if (x->started) { + clock_delay(x->x_clock, x->x_delaytime); + } - return 1; + return 1; } - - /* Actions */ - -static void linuxjoystick_bang(t_linuxjoystick* x) -{ - DEBUG(post("linuxjoystick_bang");) - -} - -static void linuxjoystick_float(t_linuxjoystick* x) -{ +static void linuxjoystick_float(t_linuxjoystick* x) { DEBUG(post("linuxjoystick_float");) } -// DONE -void linuxjoystick_start(t_linuxjoystick* x) -{ - DEBUG(post("linuxjoystick_start");) - - if (x->x_fd >= 0 && !x->started) { - sys_addpollfn(x->x_fd, (t_fdpollfn)linuxjoystick_read, x); - post("linuxjoystick: start"); - x->started = 1; - } +void linuxjoystick_delay(t_linuxjoystick* x, t_float f) { + DEBUG(post("linuxjoystick_DELAY %f",f);) + +/* if the user sets the delay less than zero, reset to default */ + if ( f > 0 ) { + x->x_delaytime = (int)f; + } else { + x->x_delaytime = 5; + } } - -// DONE -void linuxjoystick_stop(t_linuxjoystick* x) -{ - DEBUG(post("linuxjoystick_stop");) - - if (x->x_fd >= 0 && x->started) { - sys_rmpollfn(x->x_fd); - post("linuxjoystick: stop"); - x->started = 0; - } +void linuxjoystick_start(t_linuxjoystick* x) { + DEBUG(post("linuxjoystick_start");); + + if (x->x_fd >= 0 && !x->started) { + clock_delay(x->x_clock, 5); + post("linuxjoystick: polling started"); + x->started = 1; + } else { + post("You need to set a input device (i.e /dev/input/event0)"); + } } -/* Misc setup functions */ - - -static void linuxjoystick_free(t_linuxjoystick* x) -{ +/* setup functions */ +static void linuxjoystick_free(t_linuxjoystick* x) { DEBUG(post("linuxjoystick_free");) - if (x->x_fd < 0) return; - + if (x->x_fd < 0) return; + linuxjoystick_stop(x); - + clock_free(x->x_clock); close (x->x_fd); } -static void *linuxjoystick_new(t_symbol *s) -{ +static void *linuxjoystick_new(t_symbol *s) { int i; t_linuxjoystick *x = (t_linuxjoystick *)pd_new(linuxjoystick_class); DEBUG(post("linuxjoystick_new");) - + + post("[linuxjoystick] %s, written by Hans-Christoph Steiner ",version); + /* init vars */ x->x_fd = -1; x->read_ok = 1; x->started = 0; + x->x_delaytime = 5; + x->x_clock = clock_new(x, (t_method)linuxjoystick_read); /* create outlets for each axis */ for (i = 0; i < LINUXJOYSTICK_AXES; i++) - x->x_axis_out[i] = outlet_new(&x->x_obj, &s_float); + x->x_axis_out[i] = outlet_new(&x->x_obj, &s_float); /* create outlets for buttons */ x->x_button_num_out = outlet_new(&x->x_obj, &s_float); x->x_button_val_out = outlet_new(&x->x_obj, &s_float); + /* set to the value from the object argument, if that exists */ if (s != &s_) - x->x_devname = s; + x->x_devname = s; /* Open the device and save settings */ @@ -335,9 +339,7 @@ static void *linuxjoystick_new(t_symbol *s) return (x); } - -void linuxjoystick_setup(void) -{ +void linuxjoystick_setup(void) { DEBUG(post("linuxjoystick_setup");) linuxjoystick_class = class_new(gensym("linuxjoystick"), (t_newmethod)linuxjoystick_new, @@ -346,13 +348,15 @@ void linuxjoystick_setup(void) /* add inlet datatype methods */ class_addfloat(linuxjoystick_class,(t_method) linuxjoystick_float); - class_addbang(linuxjoystick_class,(t_method) linuxjoystick_bang); + class_addbang(linuxjoystick_class,(t_method) linuxjoystick_read); /* add inlet message methods */ - class_addmethod(linuxjoystick_class, (t_method) linuxjoystick_open,gensym("open"),A_DEFSYM); + class_addmethod(linuxjoystick_class,(t_method) linuxjoystick_delay,gensym("delay"),A_DEFFLOAT,0); + class_addmethod(linuxjoystick_class,(t_method) linuxjoystick_open,gensym("open"),A_DEFSYM,0); class_addmethod(linuxjoystick_class,(t_method) linuxjoystick_close,gensym("close"),0); class_addmethod(linuxjoystick_class,(t_method) linuxjoystick_start,gensym("start"),0); + class_addmethod(linuxjoystick_class,(t_method) linuxjoystick_start,gensym("poll"),0); class_addmethod(linuxjoystick_class,(t_method) linuxjoystick_stop,gensym("stop"),0); - + class_addmethod(linuxjoystick_class,(t_method) linuxjoystick_stop,gensym("nopoll"),0); } diff --git a/linuxmouse-help.pd b/linuxmouse-help.pd index e735296..067733a 100644 --- a/linuxmouse-help.pd +++ b/linuxmouse-help.pd @@ -1,16 +1,42 @@ -#N canvas 454 205 450 300 10; -#X floatatom 258 160 5 0 0 3 button# - -; -#X floatatom 321 162 5 0 0 3 button_value - -; -#X floatatom 175 160 2 0 0 3 wheel - -; -#X floatatom 99 161 4 0 0 3 y-axis - -; -#X floatatom 24 162 4 0 0 3 x-axis - -; -#X obj 75 110 linuxmouse /dev/input/event0; -#X msg 125 40 start; -#X msg 136 78 stop; +#N canvas 112 187 450 441 10; +#X floatatom 238 220 5 0 0 3 button# - -; +#X floatatom 299 220 5 0 0 3 button_value - -; +#X floatatom 190 220 2 0 0 3 wheel - -; +#X floatatom 137 220 4 0 0 3 y-axis - -; +#X floatatom 79 220 4 0 0 3 x-axis - -; +#X obj 95 193 linuxmouse /dev/input/event0; +#X obj 18 6 cnv 15 400 30 empty empty linuxmouse 20 12 1 16 -225280 +-66577 0; +#X text 206 17 related HID objects:; +#X obj 357 16 linuxhiderfic; +#X text 24 263 [linuxmouse] takes events directly from a Linux event +device \, so that you get mouse data regardless of whether Pd has focus. +Also \, the data from the event system is relative and limited to the +screen size.; +#X msg 51 71 start; +#X msg 51 93 stop; +#X msg 115 70 poll; +#X msg 115 92 nopoll; +#X text 24 335 Rather than polling like the other linuxhid objects +\, [linuxmouse] uses a pollfn so it receives events as they happen. +A pollfn listens to a network socket \, and takes action upon activity. +Since all mouse events go through the network socket between pd and +pd-gui \, this works for responding to mouse events.; +#X msg 158 165 close; +#X text 179 91 (synonyms for the same actions); +#X text 182 75 start/stop polling; +#X msg 147 122 open; +#X msg 152 142 open /dev/input/event1; +#X text 183 123 opens the previous device; #X connect 5 0 4 0; #X connect 5 1 3 0; #X connect 5 2 2 0; #X connect 5 3 0 0; #X connect 5 4 1 0; -#X connect 6 0 5 0; -#X connect 7 0 5 0; +#X connect 10 0 5 0; +#X connect 11 0 5 0; +#X connect 12 0 5 0; +#X connect 13 0 5 0; +#X connect 15 0 5 0; +#X connect 18 0 5 0; +#X connect 19 0 5 0; diff --git a/linuxmouse.c b/linuxmouse.c index da7147e..568f2ff 100644 --- a/linuxmouse.c +++ b/linuxmouse.c @@ -3,7 +3,7 @@ #define LINUXMOUSE_DEVICE "/dev/input/event0" #define LINUXMOUSE_AXES 3 -static char *version = "$Revision: 1.2 $"; +static char *version = "$Revision: 1.3 $"; /*------------------------------------------------------------------------------ * CLASS DEF @@ -13,7 +13,7 @@ static t_class *linuxmouse_class; typedef struct _linuxmouse { t_object x_obj; t_int x_fd; - t_symbol* x_devname; + t_symbol *x_devname; int read_ok; int started; struct input_event x_input_event; @@ -22,282 +22,241 @@ typedef struct _linuxmouse { t_outlet *x_button_val_out; unsigned char x_buttons; unsigned char x_axes; -}t_linuxmouse; +} t_linuxmouse; /*------------------------------------------------------------------------------ * IMPLEMENTATION */ -//DONE -static int linuxmouse_close(t_linuxmouse *x) -{ - DEBUG(post("linuxmouse_close");) - - if (x->x_fd <0) return 0; - - close (x->x_fd); - - return 1; +/* Actions */ +void linuxmouse_stop(t_linuxmouse* x) { + DEBUG(post("linuxmouse_stop");); + + if (x->x_fd >= 0 && x->started) { + sys_rmpollfn(x->x_fd); + post("[linuxmouse] stopped"); + x->started = 0; + } } -//DONE -static int linuxmouse_open(t_linuxmouse *x,t_symbol* s) -{ - int eventType, eventCode; - unsigned long bitmask[EV_MAX][NBITS(KEY_MAX)]; - char devicename[256] = "Unknown"; - DEBUG(post("linuxmouse_open");) - - linuxmouse_close(x); - - /* set obj device name to parameter - * otherwise set to default - */ - if (s != &s_) - x->x_devname = s; - else { - post("You need to set a input device (i.e /dev/input/event0)"); - } - - /* open device */ - if (x->x_devname) { - post("opening ..."); - /* open the linuxmouse device read-only, non-exclusive */ - x->x_fd = open (x->x_devname->s_name, O_RDONLY | O_NONBLOCK); - if (x->x_fd >= 0 ) post("done"); - else post("failed"); - } - else { - return 1; - } - - /* test if device open */ - if (x->x_fd >= 0) - post("%s opened",x->x_devname->s_name); - else { - post("unable to open %s",x->x_devname->s_name); - x->x_fd = -1; - return 0; - } - - /* read input_events from the LINUXMOUSE_DEVICE stream - * It seems that is just there to flush the event input buffer? - */ - while (read (x->x_fd, &(x->x_input_event), sizeof(struct input_event)) > -1); - - /* get name of device */ - ioctl(x->x_fd, EVIOCGNAME(sizeof(devicename)), devicename); - post ("configuring %s",devicename); - - /* get bitmask representing supported events (axes, buttons, etc.) */ - memset(bitmask, 0, sizeof(bitmask)); - ioctl(x->x_fd, EVIOCGBIT(0, EV_MAX), bitmask[0]); - post("Supported events:"); - - x->x_axes = 0; - x->x_buttons = 0; - - /* cycle through all possible event types */ - for (eventType = 0; eventType < EV_MAX; eventType++) { - if (test_bit(eventType, bitmask[0])) { - post(" %s (type %d) ", events[eventType] ? events[eventType] : "?", eventType); - // post("Event type %d",eventType); - - /* get bitmask representing supported button types */ - ioctl(x->x_fd, EVIOCGBIT(eventType, KEY_MAX), bitmask[eventType]); +static int linuxmouse_close(t_linuxmouse *x) { + DEBUG(post("linuxmouse_close");); - /* cycle through all possible event codes (axes, keys, etc.) - * testing to see which are supported - */ - for (eventCode = 0; eventCode < KEY_MAX; eventCode++) - if (test_bit(eventCode, bitmask[eventType])) { - post(" Event code %d (%s)", eventCode, names[eventType] ? (names[eventType][eventCode] ? names[eventType][eventCode] : "?") : "?"); - - if ( eventType == EV_KEY ) - x->x_buttons++; - else if ( eventType == EV_REL ) - x->x_axes++; +/* just to be safe, stop it first */ + linuxmouse_stop(x); + + if (x->x_fd < 0) { + return 0; + } + else { + close (x->x_fd); + post ("[linuxmouse] closed %s",x->x_devname->s_name); + return 1; } - } - } - - post ("\nUsing %d axes and %d buttons.", x->x_axes, x->x_buttons); - post ("WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING"); - post ("This object is under development! The interface could change at anytime!"); - post ("As I write cross-platform versions, the interface might have to change."); - post ("WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING"); - - return 1; -} - - - -static int linuxmouse_read(t_linuxmouse *x,int fd) -{ - int readBytes; - int axis_num = 0; - t_float button_num = 0; - - if (x->x_fd < 0) return 0; - if (x->read_ok) { - readBytes = read(x->x_fd, &(x->x_input_event), sizeof(struct input_event)); - DEBUG(post("reading %d",readBytes);) - if ( readBytes < 0 ) { - post("linuxmouse: read failed"); - x->read_ok = 0; - return 0; - } - } - if ( x->x_input_event.type == EV_KEY ) { - /* key/button event type */ - switch ( x->x_input_event.code ) { - case BTN_LEFT: - button_num = 0; - break; - case BTN_RIGHT: - button_num = 1; - break; - case BTN_MIDDLE: - button_num = 2; - break; - case BTN_SIDE: - button_num = 3; - break; - case BTN_EXTRA: - button_num = 4; - break; - case BTN_FORWARD: - button_num = 5; - break; - case BTN_BACK: - button_num = 6; - break; - } - outlet_float (x->x_button_val_out, x->x_input_event.value); - outlet_float (x->x_button_num_out, button_num); - } - else if ( x->x_input_event.type == EV_REL ) { - /* Relative Axes Event Type */ - switch ( x->x_input_event.code ) { - case REL_X: - axis_num = 0; - break; - case REL_Y: - axis_num = 1; - break; - case REL_WHEEL: - axis_num = 2; - break; - } - outlet_float (x->x_axis_out[axis_num], (int)x->x_input_event.value); - } - - return 1; } - - -/* Actions */ - -static void linuxmouse_bang(t_linuxmouse* x) -{ - DEBUG(post("linuxmouse_bang");) - +static int linuxmouse_open(t_linuxmouse *x, t_symbol *s) { + int eventType, eventCode; + unsigned long bitmask[EV_MAX][NBITS(KEY_MAX)]; + char devicename[256] = "Unknown"; + + DEBUG(post("linuxmouse_open");); + + linuxmouse_close(x); + +/* For some reason, not initializing x->x_devname causes a seg fault */ +/* on this object, but it works fine on [linuxevent] */ + t_symbol *temp = malloc(20); + temp->s_name = "/dev/input/event0"; + x->x_devname = temp; + + /* set obj device name to parameter + * otherwise set to default + */ + if (s != &s_) x->x_devname = s; + + /* open device */ + if (x->x_devname) { + /* open the device read-only, non-exclusive */ + x->x_fd = open (x->x_devname->s_name, O_RDONLY | O_NONBLOCK); + /* test if device open */ + if (x->x_fd < 0 ) { + post("[linuxmouse] open %s failed",x->x_devname->s_name); + x->x_fd = -1; + return 0; + } + } else { + post("[linuxmouse] no device set: %s",x->x_devname->s_name); + return 1; + } + + +/* read input_events from the LINUXMOUSE_DEVICE stream + * It seems that is just there to flush the event input buffer? + */ + while (read (x->x_fd, &(x->x_input_event), sizeof(struct input_event)) > -1); + + /* get name of device */ + ioctl(x->x_fd, EVIOCGNAME(sizeof(devicename)), devicename); + post ("Configuring %s on %s.",devicename,x->x_devname->s_name); + post("\nSupported events:"); + + /* get bitmask representing supported events (axes, buttons, etc.) */ + memset(bitmask, 0, sizeof(bitmask)); + ioctl(x->x_fd, EVIOCGBIT(0, EV_MAX), bitmask[0]); + + x->x_axes = 0; + x->x_buttons = 0; + + /* cycle through all possible event types */ + for (eventType = 0; eventType < EV_MAX; eventType++) { + if (test_bit(eventType, bitmask[0])) { + post(" %s (type %d) ", events[eventType] ? events[eventType] : "?", eventType); + // post("Event type %d",eventType); + + /* get bitmask representing supported button types */ + ioctl(x->x_fd, EVIOCGBIT(eventType, KEY_MAX), bitmask[eventType]); + + /* cycle through all possible event codes (axes, keys, etc.) + * testing to see which are supported + */ + for (eventCode = 0; eventCode < KEY_MAX; eventCode++) { + if (test_bit(eventCode, bitmask[eventType])) { + post(" Event code %d (%s)", eventCode, names[eventType] ? (names[eventType][eventCode] ? names[eventType][eventCode] : "?") : "?"); + + if ( eventType == EV_KEY ) + x->x_buttons++; + else if ( eventType == EV_REL ) + x->x_axes++; + } + } + } + } + + post ("\nUsing %d axes and %d buttons.", x->x_axes, x->x_buttons); + post ("\nWARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING"); + post ("This object is under development! The interface could change at anytime!"); + post ("As I write cross-platform versions, the interface might have to change."); + post ("WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING\n"); + + return 1; } -static void linuxmouse_float(t_linuxmouse* x) -{ - DEBUG(post("linuxmouse_float");) - +static int linuxmouse_read(t_linuxmouse *x,int fd) { + int axis_num = 0; + t_float button_num = 0; + + if (x->x_fd < 0) return 0; + + while (read (x->x_fd, &(x->x_input_event), sizeof(struct input_event)) > -1) { + if ( x->x_input_event.type == EV_REL ) { + /* Relative Axes Event Type */ + switch ( x->x_input_event.code ) { + case REL_X: + axis_num = 0; + break; + case REL_Y: + axis_num = 1; + break; + case REL_WHEEL: + axis_num = 2; + break; + } + outlet_float (x->x_axis_out[axis_num], (int)x->x_input_event.value); + } + else if ( x->x_input_event.type == EV_KEY ) { + /* key/button event type */ + switch ( x->x_input_event.code ) { + case BTN_LEFT: + button_num = 0; + break; + case BTN_RIGHT: + button_num = 1; + break; + case BTN_MIDDLE: + button_num = 2; + break; + case BTN_SIDE: + button_num = 3; + break; + case BTN_EXTRA: + button_num = 4; + break; + case BTN_FORWARD: + button_num = 5; + break; + case BTN_BACK: + button_num = 6; + break; + } + outlet_float (x->x_button_val_out, x->x_input_event.value); + outlet_float (x->x_button_num_out, button_num); + } + } + + return 1; } -// DONE -void linuxmouse_start(t_linuxmouse* x) -{ - DEBUG(post("linuxmouse_start");) - - if (x->x_fd >= 0 && !x->started) { - sys_addpollfn(x->x_fd, (t_fdpollfn)linuxmouse_read, x); - post("linuxmouse: start"); - x->started = 1; - } -} +void linuxmouse_start(t_linuxmouse* x) { + DEBUG(post("linuxmouse_start");); - -// DONE -void linuxmouse_stop(t_linuxmouse* x) -{ - DEBUG(post("linuxmouse_stop");) - - if (x->x_fd >= 0 && x->started) { - sys_rmpollfn(x->x_fd); - post("linuxmouse: stop"); - x->started = 0; - } + if (x->x_fd >= 0 && !x->started) { + sys_addpollfn(x->x_fd, (t_fdpollfn)linuxmouse_read, x); + post("[linuxmouse] started"); + x->started = 1; + } else { + post("You need to set a input device (i.e /dev/input/event0)"); + } } -/* Misc setup functions */ - - -static void linuxmouse_free(t_linuxmouse* x) -{ - DEBUG(post("linuxmouse_free");) +/* setup functions */ +static void linuxmouse_free(t_linuxmouse* x) { + DEBUG(post("linuxmouse_free");); - if (x->x_fd < 0) return; - - linuxmouse_stop(x); - - close (x->x_fd); + if (x->x_fd < 0) return; + linuxmouse_stop(x); + close (x->x_fd); } -static void *linuxmouse_new(t_symbol *s) -{ - int i; - t_linuxmouse *x = (t_linuxmouse *)pd_new(linuxmouse_class); - - DEBUG(post("linuxmouse_new");) - - /* init vars */ - x->x_fd = -1; - x->read_ok = 1; - x->started = 0; - - /* create outlets for each axis */ - for (i = 0; i < LINUXMOUSE_AXES; i++) - x->x_axis_out[i] = outlet_new(&x->x_obj, &s_float); - - /* create outlets for buttons */ - x->x_button_num_out = outlet_new(&x->x_obj, &s_float); - x->x_button_val_out = outlet_new(&x->x_obj, &s_float); - - if (s != &s_) - x->x_devname = s; - - /* Open the device and save settings */ - - if (!linuxmouse_open(x,s)) return x; - - return (x); +static void *linuxmouse_new(t_symbol *s) { + int i; + t_linuxmouse *x = (t_linuxmouse *)pd_new(linuxmouse_class); + + DEBUG(post("linuxmouse_new");); + + post("[linuxmouse] %s, written by Hans-Christoph Steiner ",version); + + /* init vars */ + x->x_fd = -1; + x->read_ok = 1; + x->started = 0; + + /* create outlets for each axis */ + for (i = 0; i < LINUXMOUSE_AXES; i++) + x->x_axis_out[i] = outlet_new(&x->x_obj, &s_float); + + /* create outlets for buttons */ + x->x_button_num_out = outlet_new(&x->x_obj, &s_float); + x->x_button_val_out = outlet_new(&x->x_obj, &s_float); + + if (!linuxmouse_open(x,s)) return x; + + return (x); } - -void linuxmouse_setup(void) -{ - DEBUG(post("linuxmouse_setup");) - linuxmouse_class = class_new(gensym("linuxmouse"), - (t_newmethod)linuxmouse_new, - (t_method)linuxmouse_free, - sizeof(t_linuxmouse),0,A_DEFSYM,0); - - /* add inlet datatype methods */ - class_addfloat(linuxmouse_class,(t_method) linuxmouse_float); - class_addbang(linuxmouse_class,(t_method) linuxmouse_bang); - - /* add inlet message methods */ - class_addmethod(linuxmouse_class, (t_method) linuxmouse_open,gensym("open"),A_DEFSYM); - class_addmethod(linuxmouse_class,(t_method) linuxmouse_close,gensym("close"),0); - class_addmethod(linuxmouse_class,(t_method) linuxmouse_start,gensym("start"),0); - class_addmethod(linuxmouse_class,(t_method) linuxmouse_stop,gensym("stop"),0); - +void linuxmouse_setup(void) { + DEBUG(post("linuxmouse_setup");); + linuxmouse_class = class_new(gensym("linuxmouse"), + (t_newmethod)linuxmouse_new, + (t_method)linuxmouse_free, + sizeof(t_linuxmouse), 0, A_DEFSYM, 0); + + /* add inlet message methods */ + class_addmethod(linuxmouse_class,(t_method) linuxmouse_open,gensym("open"),A_DEFSYM,0); + class_addmethod(linuxmouse_class,(t_method) linuxmouse_close,gensym("close"),0); + class_addmethod(linuxmouse_class,(t_method) linuxmouse_start,gensym("start"),0); + class_addmethod(linuxmouse_class,(t_method) linuxmouse_stop,gensym("stop"),0); + class_addmethod(linuxmouse_class,(t_method) linuxmouse_start,gensym("poll"),0); + class_addmethod(linuxmouse_class,(t_method) linuxmouse_stop,gensym("nopoll"),0); } -- cgit v1.2.1