From 923e18b2face0b0b0f13e202a894be56242fe4e0 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sun, 28 Nov 2004 01:27:47 +0000 Subject: fixed a number of annoying bugs in MacOS X; cleaned up code; now multiple [hid]s work at the same time svn path=/trunk/externals/hcs/hid/; revision=2329 --- TODO | 101 ++++++--------------- doc/buttongate-help.pd | 3 +- doc/hid-help.pd | 157 +++++++++++++++++--------------- doc/keyboard-help.pd | 9 +- doc/keygate-help.pd | 3 +- doc/mouse-help.pd | 7 +- hid.c | 90 +++++++++--------- hid.h | 23 +++-- hid_darwin.c | 154 ++++++++++++++++++++----------- hid_linux.c | 241 +++++++++++++++++++++++++------------------------ joystick.pd | 35 +++---- 11 files changed, 438 insertions(+), 385 deletions(-) diff --git a/TODO b/TODO index ad767b8..635cca0 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,11 @@ + +============================================================================== += write hid_print() + +- MacOS X (device/element list) + +- GNU/Linux + ============================================================================== = define generic event timestamp struct (probably Pd-ized input_event ) @@ -5,17 +13,10 @@ The question is whether the timeval is needed at all. Linux and Darwin support it. Currently, I can only think of UPS PWR events actually using timevals. - - -=============================================================================== -= HID Manager Type/Usage/UsagePage -> Linux Type/Code mapping - - UsagePage - - -LED UsagePage => ev_led -LED Usages == Linux ev_led codes - +The timestamps should be in seconds since the first [hid] object was +instantiated since Pd limits float resolution to 6 digits. If there were two +floats, one for seconds, and the other for microseconds, then the [hid] +timestamp could represent up to 11.5 days (999999 seconds). ============================================================================== @@ -24,17 +25,6 @@ LED Usages == Linux ev_led codes by # (1,2,...), generic name (mouse1, joystick2, tablet3...), or device name ("Trackpad", "Microsoft 5-button Mouse with IntelliEye(TM)", etc.) - first get # working, that's probably the easiest - -by # ------------------------------- -GNU/Linux - sprintf(x_devname->s_name,"/dev/input/event%d",deviceNum + 1); - -Darwin - prHIDBuildDeviceList(); - currentHIDDevice = discoveredDevices[gNumberOfHIDDevices]; - ============================================================================== = figure out how to store device ID in obj struct @@ -69,11 +59,7 @@ Darwin ============================================================================== = control input messages -- the [delay( message should be replaced by the [poll( msg - -- should [poll( also start things, or should it just set polling time? - -- are [start( and [stop( needed? is 0/1 enough? +- are [poll(, [start(, and [stop( needed? is 0/1/del# enough? ============================================================================== @@ -82,29 +68,22 @@ Darwin void hid_post(const char *format, const char *); -============================================================================== -= if device is closed and obj is started, open device and start - -============================================================================== -= catalog Linux device behavior - -- more data needed to make the proper [hid] output for MacOS X - -- catalog hatswitch behavior - -- catalog axis directions: right/down positive? left/up negative? - ============================================================================== = event name changes - make key/button Type btn rather than key (undecided on this one) + ============================================================================== -= make [macosxevent] += make [linuxhid] [darwinhid] and [windowshid] - so much info is lost in the translation to a common event scheme that it - would be quite handy to have a [macosxevent] object. This would give - access to the entire range of devices supported by HID Manager. + would be quite handy to have platform-specific objects. This would give + access to the entire range of devices supported by HID Manager, Linux input + events, etc. + +- these objects should follow the same conventions as [hid] + ============================================================================== = device 0 gets events for all available devices @@ -112,35 +91,12 @@ void hid_post(const char *format, const char *); - it might be useful to have device #0 open all available devices and output the events. -============================================================================== -= mapping object ideas -- log - -- exponential - -- [noterange] scale an input range to an output range of MIDI note #s - -______________________________________________________________________________ ------------------------------------------------------------------------------- -BUGS -______________________________________________________________________________ ------------------------------------------------------------------------------- - -______________________________________________________________________________ -- BUG x->x_delay reset to default when device is opened - -______________________________________________________________________________ -- BUG: [mouse] and [joystick] arguments don't work to open device - -______________________________________________________________________________ -- BUG: [open('ing a device causes all other active [hid] objs to have their -devices closed - -- this means only one [hid] object can have an open device at one time - -- I thought this was due to the hid_close_device() call in hid_open(), which releases - the device list, but this doesn't seem to be the case. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ______________________________________________________________________________ - BUG: getting events from the queue doesn't output a 0 value event when the @@ -169,10 +125,11 @@ ______________________________________________________________________________ the screen. Hopefully the HID Manager API will allow raw mouse data access. It must since its used with games. -_________________________________________________________________________________________ +______________________________________________________________________________ - BUG: on MacOS X, two keyboard key codes are reported as hatswitches abs abs_hat0x Button Input, Keyboard Usage 0x39 abs abs_hat0y Button Input, Keyboard Usage 0x39 -I am pretty sure this is just a display problem, but it might not be. +I am pretty sure this is just a hid_print_element_list() display problem. + diff --git a/doc/buttongate-help.pd b/doc/buttongate-help.pd index a412cad..fa46447 100644 --- a/doc/buttongate-help.pd +++ b/doc/buttongate-help.pd @@ -1,4 +1,4 @@ -#N canvas 345 96 473 510 10; +#N canvas 345 96 463 514 10; #X obj 5 2 cnv 15 450 20 empty empty [buttongate] 2 11 1 18 -233017 -66577 0; #X obj 160 287 bng 25 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 @@ -29,6 +29,7 @@ optional control messages to the HID.; #X text 23 348 Keyboard keys can also be used to control this object. You can get the [hid] keycode from here:; #X obj 324 368 ev_key-list; +#X obj 422 3 pddp; #X connect 2 0 3 0; #X connect 3 0 4 0; #X connect 4 0 10 0; diff --git a/doc/hid-help.pd b/doc/hid-help.pd index cc52481..543fddc 100644 --- a/doc/hid-help.pd +++ b/doc/hid-help.pd @@ -1,20 +1,20 @@ -#N canvas 307 79 928 648 10; -#X msg 455 295 abs abs_y 114 1.23605e+09; +#N canvas 67 163 909 622 10; +#X msg 455 295 rel rel_x -1 4.06142e+09; #X obj 455 274 prepend set; #X floatatom 37 484 5 0 0 0 - - -; #X floatatom 89 484 5 0 0 0 - - -; -#X msg 148 77 start; -#X msg 174 96 stop; +#X msg 158 121 start; +#X msg 158 141 stop; #X floatatom 548 354 12 0 0 1 time - -; #X obj 455 335 unpack s s f f; -#X msg 239 37 open 0; -#X msg 246 55 open 1; -#X msg 253 73 open 2; -#X msg 259 91 open 3; -#X msg 265 109 open 4; +#X msg 261 34 open 0; +#X msg 268 52 open 1; +#X msg 275 70 open 2; +#X msg 281 88 open 3; +#X msg 287 106 open 4; #X floatatom 84 439 7 0 0 0 - - -; #X floatatom 138 439 7 0 0 0 - - -; -#X obj 86 81 tgl 35 0 empty empty empty 0 -6 0 8 -24198 -1 -1 25 25 +#X obj 68 122 tgl 35 0 empty empty empty 0 -6 0 8 -24198 -1 -1 25 25 ; #X floatatom 517 370 12 0 0 1 value - -; #X symbolatom 486 386 15 0 0 1 event_code - -; @@ -44,25 +44,22 @@ #X floatatom 289 383 5 0 0 1 ev_syn - -; #X obj 262 382 +; #X msg 262 362 1; -#X msg 336 136 close; -#X msg 336 113 refresh; -#X text 397 111 refresh device list; -#X obj 717 512 all_about_hid; -#X text 608 513 For more info:; +#X msg 366 124 close; +#X msg 366 103 refresh; +#X text 427 101 refresh device list; +#X text 607 531 For more info:; #X text 49 588 (C) Copyright 2004 Hans-Christoph Steiner ; #X text 266 602 released under the GNU GPL; -#X text 472 589 $Revision: 1.12 $$Date: 2004-11-16 01:35:35 $; +#X text 472 589 $Revision: 1.13 $$Date: 2004-11-28 01:27:47 $; #X text 473 602 $Author: eighthave $; #X floatatom 192 439 7 0 0 0 - - -; -#X msg 398 180 poll 20; -#X msg 336 180 poll 2; -#X text 332 159 start polling and set the poll delay in ms; +#X msg 428 185 poll 20; +#X msg 366 185 poll 2; +#X text 362 170 start polling and set the poll delay in ms; #X text 387 248 event_type event_code value timestamp; -#X msg 465 180 poll 2000; -#X text 371 56 !!! This software is very much alpha \, so any aspect +#X text 358 42 !!! This software is very much alpha \, so any aspect of it could change without notice !!!; -#X obj 248 225 hid 1; #X obj 93 330 route key rel abs syn; #X obj 9 537 tgl 25 0 empty empty empty 0 -6 0 8 -195568 -1 -1 0 1 ; @@ -82,7 +79,7 @@ of it could change without notice !!!; 1; #X obj 335 537 tgl 25 0 empty empty empty 0 -6 0 8 -195568 -1 -1 0 1; -#X msg 270 129 open 5; +#X msg 292 126 open 5; #X obj 9 504 route btn_0 btn_1 btn_2 btn_3 btn_4 btn_5 btn_6 btn_7 btn_8 btn_9; #X obj 376 537 tgl 25 0 empty empty empty 0 -6 0 8 -195568 -1 -1 0 @@ -308,64 +305,80 @@ btn_8 btn_9; #X floatatom 640 459 7 0 0 0 - - -; #X obj 640 475 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; +#X msg 118 121 1; +#X msg 118 141 0; +#X obj 868 3 pddp; +#X obj 716 530 all_about_hid; +#X msg 366 145 print; +#X obj 247 223 hid 0; +#X text 429 125 close the device; +#X text 429 146 print the device and element lists; +#X text 10 50 Any non-zero value starts polling \,; +#X text 10 63 0 stops the polling. If the number; +#X text 10 76 is greater than 1 \, then the poll; +#X text 10 89 delay is set to that number.; +#X msg 496 185 poll 2000; #X connect 1 0 0 0; -#X connect 4 0 57 0; -#X connect 5 0 57 0; +#X connect 4 0 91 0; +#X connect 5 0 91 0; #X connect 7 0 18 0; #X connect 7 1 17 0; #X connect 7 2 16 0; #X connect 7 3 6 0; -#X connect 8 0 57 0; -#X connect 9 0 57 0; -#X connect 10 0 57 0; -#X connect 11 0 57 0; -#X connect 12 0 57 0; -#X connect 15 0 57 0; +#X connect 8 0 91 0; +#X connect 9 0 91 0; +#X connect 10 0 91 0; +#X connect 11 0 91 0; +#X connect 12 0 91 0; +#X connect 15 0 91 0; #X connect 36 0 35 0; #X connect 36 0 19 0; #X connect 37 0 36 1; #X connect 38 0 39 1; #X connect 39 0 38 0; #X connect 40 0 39 0; -#X connect 41 0 57 0; -#X connect 42 0 57 0; -#X connect 51 0 57 0; -#X connect 52 0 57 0; -#X connect 55 0 57 0; -#X connect 57 0 36 0; -#X connect 57 0 1 0; -#X connect 57 0 7 0; -#X connect 57 0 58 0; -#X connect 58 0 69 0; -#X connect 58 1 74 0; -#X connect 58 2 76 0; -#X connect 58 3 40 0; -#X connect 68 0 57 0; -#X connect 69 0 59 0; -#X connect 69 1 60 0; -#X connect 69 2 61 0; -#X connect 69 3 62 0; -#X connect 69 4 63 0; -#X connect 69 5 64 0; -#X connect 69 6 65 0; -#X connect 69 7 66 0; -#X connect 69 8 67 0; -#X connect 69 9 70 0; -#X connect 74 0 2 0; -#X connect 74 1 3 0; -#X connect 74 2 75 0; -#X connect 76 0 13 0; -#X connect 76 1 14 0; -#X connect 76 2 50 0; -#X connect 76 3 77 0; -#X connect 76 4 78 0; -#X connect 76 5 79 0; -#X connect 76 6 80 0; +#X connect 41 0 91 0; +#X connect 42 0 91 0; +#X connect 50 0 91 0; +#X connect 51 0 91 0; +#X connect 55 0 66 0; +#X connect 55 1 71 0; +#X connect 55 2 73 0; +#X connect 55 3 40 0; +#X connect 65 0 91 0; +#X connect 66 0 56 0; +#X connect 66 1 57 0; +#X connect 66 2 58 0; +#X connect 66 3 59 0; +#X connect 66 4 60 0; +#X connect 66 5 61 0; +#X connect 66 6 62 0; +#X connect 66 7 63 0; +#X connect 66 8 64 0; +#X connect 66 9 67 0; +#X connect 71 0 2 0; +#X connect 71 1 3 0; +#X connect 71 2 72 0; +#X connect 73 0 13 0; +#X connect 73 1 14 0; +#X connect 73 2 49 0; +#X connect 73 3 74 0; +#X connect 73 4 75 0; +#X connect 73 5 76 0; +#X connect 73 6 77 0; +#X connect 77 0 78 0; +#X connect 77 1 80 0; +#X connect 77 2 82 0; +#X connect 77 3 84 0; +#X connect 78 0 79 0; #X connect 80 0 81 0; -#X connect 80 1 83 0; -#X connect 80 2 85 0; -#X connect 80 3 87 0; -#X connect 81 0 82 0; -#X connect 83 0 84 0; -#X connect 85 0 86 0; -#X connect 87 0 88 0; +#X connect 82 0 83 0; +#X connect 84 0 85 0; +#X connect 86 0 91 0; +#X connect 87 0 91 0; +#X connect 90 0 91 0; +#X connect 91 0 36 0; +#X connect 91 0 1 0; +#X connect 91 0 7 0; +#X connect 91 0 55 0; +#X connect 98 0 91 0; diff --git a/doc/keyboard-help.pd b/doc/keyboard-help.pd index 90a45b4..bced959 100644 --- a/doc/keyboard-help.pd +++ b/doc/keyboard-help.pd @@ -1,5 +1,5 @@ -#N canvas 109 184 569 474 10; -#X obj 168 91 tgl 25 0 empty empty empty 0 -6 0 8 -225271 -1 -1 1 1 +#N canvas 109 184 567 478 10; +#X obj 168 91 tgl 25 0 empty empty empty 0 -6 0 8 -225271 -1 -1 0 1 ; #X obj 11 369 tgl 20 0 empty empty empty 0 -6 0 8 -195568 -1 -1 0 1 ; @@ -14,7 +14,7 @@ ; #X text 218 446 released under the GNU GPL; #X text 414 446 $Author: eighthave $; -#X text 414 433 $Revision: 1.1 $; +#X text 414 433 $Revision: 1.2 $; #X obj 348 402 all_about_hid; #X text 239 403 For more info:; #X msg 220 112 open 3; @@ -54,7 +54,7 @@ 1; #X obj 368 369 tgl 20 0 empty empty empty 0 -6 0 8 -195568 -1 -1 0 1; -#X obj 389 369 tgl 20 0 empty empty empty 0 -6 0 8 -195568 -1 -1 1 +#X obj 389 369 tgl 20 0 empty empty empty 0 -6 0 8 -195568 -1 -1 0 1; #X obj 410 369 tgl 20 0 empty empty empty 0 -6 0 8 -195568 -1 -1 0 1; @@ -76,6 +76,7 @@ will get keyboard events.; #X obj 75 315 route key_4 key_5 key_6 key_7 key_8 key_9 key_10 key_11 key_12 key_13 key_14 key_15 key_16 key_17 key_18 key_19 key_20 key_21 key_22 key_23 key_24 key_25 key_26 key_27; +#X obj 519 3 pddp; #X connect 0 0 16 0; #X connect 4 0 2 0; #X connect 4 1 3 0; diff --git a/doc/keygate-help.pd b/doc/keygate-help.pd index e6fe9ee..f73d193 100644 --- a/doc/keygate-help.pd +++ b/doc/keygate-help.pd @@ -1,4 +1,4 @@ -#N canvas 525 201 473 470 10; +#N canvas 525 201 462 476 10; #X obj 5 2 cnv 15 450 20 empty empty [keygate] 2 11 1 18 -233017 -66577 0; #X obj 160 257 bng 25 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 @@ -24,6 +24,7 @@ inlet takes the data to be gated.; #X text 18 89 The "f" key on the any keyboard controls this gate:; #X text 310 263 <-- key released; #X text 41 264 key pressed -->; +#X obj 422 3 pddp; #X connect 2 0 3 0; #X connect 3 0 4 0; #X connect 4 0 14 0; diff --git a/doc/mouse-help.pd b/doc/mouse-help.pd index 7084893..53fb843 100644 --- a/doc/mouse-help.pd +++ b/doc/mouse-help.pd @@ -1,4 +1,4 @@ -#N canvas 470 274 674 468 10; +#N canvas 470 274 661 472 10; #X symbolatom 211 268 6 0 0 1 code - -; #X obj 130 106 tgl 25 0 empty empty empty 0 -6 0 8 -225271 -1 -1 0 1; @@ -83,7 +83,7 @@ #X connect 30 0 17 0; #X connect 31 0 16 0; #X restore 425 186 pd mouse-noise 1; -#X obj 425 119 tgl 25 0 empty empty empty 0 -6 0 8 -225271 -1 -1 1 +#X obj 425 119 tgl 25 0 empty empty empty 0 -6 0 8 -225271 -1 -1 0 1; #X text 308 95 turn this on to make some noise with the mouse; #X obj 211 241 unpack symbol float; @@ -106,7 +106,7 @@ ; #X text 228 436 released under the GNU GPL; #X text 424 436 $Author: eighthave $; -#X text 424 423 $Revision: 1.8 $; +#X text 424 423 $Revision: 1.9 $; #X obj 526 382 all_about_hid; #X text 417 383 For more info:; #X obj 601 334 tgl 25 0 empty empty empty 0 -6 0 8 -195568 -1 -1 0 @@ -123,6 +123,7 @@ in each axis to calibrate it.; #X floatatom 516 165 1 0 0 0 - - -; #X msg 180 146 refresh; #X obj 130 171 mouse 0; +#X obj 619 3 pddp; #X connect 1 0 38 0; #X connect 9 0 38 0; #X connect 10 0 38 0; diff --git a/hid.c b/hid.c index 8718299..335f71a 100644 --- a/hid.c +++ b/hid.c @@ -32,8 +32,6 @@ #define DEBUG(x) //#define DEBUG(x) x -#define DEFAULT_DELAY 5 - /*------------------------------------------------------------------------------ * FUNCTION PROTOTYPES */ @@ -95,7 +93,7 @@ void hid_stop(t_hid* x) if (x->x_started) { clock_unset(x->x_clock); - post("[hid] polling stopped"); + DEBUG(post("[hid] polling stopped");); x->x_started = 0; } } @@ -110,7 +108,7 @@ t_int hid_close(t_hid *x) if(! hid_close_device(x)) { - post("[hid] closed device number %d",x->x_device_number); + post("[hid] closed device %d",x->x_device_number); x->x_device_open = 0; return (0); } @@ -119,44 +117,46 @@ t_int hid_close(t_hid *x) } -/* closed same device open */ -/* open same device no action */ -/* closed different device open */ -/* open different device close open */ +/* closed / same device open */ +/* open / same device no action */ +/* closed / different device open */ +/* open / different device close open */ t_int hid_open(t_hid *x, t_float f) { DEBUG(post("hid_open");); /* store running state to be restored after the device has been opened */ - t_int started = x->x_started; - - if ( (f != x->x_device_number) && (x->x_device_open) ) hid_close(x); - - /* set obj device name to parameter otherwise set to default */ - if (f > 0) - x->x_device_number = f; + t_int started = x->x_started; + +/* only close the device if its different than the current and open */ + if ( (f != x->x_device_number) && (x->x_device_open) ) + hid_close(x); + + if (f > 0) + x->x_device_number = f; + else + x->x_device_number = 0; + +/* if device is open still, that means the same device is trying to be opened, + * therefore ignore the redundant open request. To reopen the same device, + * send a [close( msg, then an [open( msg. */ + if (! x->x_device_open) + if (hid_open_device(x,x->x_device_number)) + { + error("[hid] can not open device %d",x->x_device_number); + return (1); + } else - x->x_device_number = 0; - - if (! x->x_device_open) - if (hid_open_device(x,x->x_device_number)) - { - error("[hid] can not open device %d",x->x_device_number); - post("\\=========================== [hid] ===========================/\n"); - return (1); - } - else - { - x->x_device_open = 1; - } + { + x->x_device_open = 1; + } /* restore the polling state so that when I [tgl] is used to start/stop [hid], * the [tgl]'s state will continue to accurately reflect [hid]'s state */ - hid_set_from_float(x,started); + if(started) + hid_set_from_float(x,x->x_delay); - - post("\\=========================== [hid] ===========================/\n"); return (0); } @@ -181,13 +181,16 @@ void hid_start(t_hid* x, t_float f) DEBUG(post("hid_start");); /* if the user sets the delay less than one, ignore */ - if ( f >= 1 ) + if( f >= 1 ) x->x_delay = (t_int)f; + + if(!x->x_device_open) + hid_open(x,x->x_device_number); - if (!x->x_started) + if(!x->x_started) { clock_delay(x->x_clock, x->x_delay); - post("[hid]: polling started"); + DEBUG(post("[hid] polling started");); x->x_started = 1; } } @@ -205,10 +208,10 @@ static void hid_free(t_hid* x) DEBUG(post("hid_free");); hid_close(x); - - hid_platform_specific_free(x); - clock_free(x->x_clock); + hid_instance_count--; + + hid_platform_specific_free(x); } /* create a new instance of this class */ @@ -218,9 +221,11 @@ static void *hid_new(t_float f) DEBUG(post("hid_new");); - post("/=========================== [hid] ===========================\\"); - post("[hid] %d.%d, written by Hans-Christoph Steiner ", - HID_MAJOR_VERSION, HID_MINOR_VERSION); +/* only display the version when the first instance is loaded */ + if(!hid_instance_count) + post("[hid] %d.%d, written by Hans-Christoph Steiner ", + HID_MAJOR_VERSION, HID_MINOR_VERSION); + #if !defined(__linux__) && !defined(__APPLE__) error(" !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!"); error(" This is a dummy, since this object only works GNU/Linux and MacOS X!"); @@ -245,7 +250,9 @@ static void *hid_new(t_float f) * patch. */ if (hid_open(x,f)) error("[hid] device %d did not open",(t_int)f); - + + hid_instance_count++; + return (x); } @@ -265,6 +272,7 @@ void hid_setup(void) /* add inlet message methods */ class_addmethod(hid_class,(t_method) hid_build_device_list,gensym("refresh"),0); + class_addmethod(hid_class,(t_method) hid_print,gensym("print"),0); class_addmethod(hid_class,(t_method) hid_open,gensym("open"),A_DEFFLOAT,0); class_addmethod(hid_class,(t_method) hid_close,gensym("close"),0); class_addmethod(hid_class,(t_method) hid_start,gensym("start"),A_DEFFLOAT,0); diff --git a/hid.h b/hid.h index 7db864b..c406e43 100644 --- a/hid.h +++ b/hid.h @@ -14,7 +14,7 @@ #define HID_MAJOR_VERSION 0 #define HID_MINOR_VERSION 1 -static char *version = "$Revision: 1.10 $"; +static char *version = "$Revision: 1.11 $"; /*------------------------------------------------------------------------------ * CLASS DEF @@ -30,18 +30,26 @@ typedef struct _hid t_int x_delay; t_int x_started; t_int x_device_open; - t_int x_instance_count; } t_hid; /*------------------------------------------------------------------------------ - * GLOBALS + * GLOBAL DEFINES */ -/* TODO: what are these for again? */ -char *deviceList[64]; -char *typeList[256]; -char *codeList[256]; +#define DEFAULT_DELAY 5 + + +/*------------------------------------------------------------------------------ + * GLOBAL VARIABLES + */ + +/* + * count the number of instances of this object so that certain free() + * functions can be called only after the final instance is detroyed. + */ +t_int hid_instance_count; + /*------------------------------------------------------------------------------ * FUNCTION PROTOTYPES FOR DIFFERENT PLATFORMS @@ -56,6 +64,7 @@ t_int hid_open_device(t_hid *x, t_int device_number); t_int hid_close_device(t_hid *x); t_int hid_build_device_list(t_hid* x); t_int hid_get_events(t_hid *x) ; +void hid_print(t_hid* x); void hid_platform_specific_free(t_hid *x); #endif /* #ifndef _HID_H */ diff --git a/hid_darwin.c b/hid_darwin.c index 6b19be3..729347c 100644 --- a/hid_darwin.c +++ b/hid_darwin.c @@ -58,6 +58,7 @@ * GLOBAL VARS *======================================================================== */ +extern t_int hid_instance_count; /*============================================================================== * FUNCTION PROTOTYPES @@ -162,7 +163,7 @@ void hid_convert_hatswitch_values(IOHIDEventStruct event, char *linux_type, char pRecDevice hid_get_device_by_number(t_int device_number) { - pRecDevice currentDevice; + pRecDevice pCurrentHIDDevice; t_int i, numdevs; /* @@ -179,14 +180,21 @@ pRecDevice hid_get_device_by_number(t_int device_number) * want the oldest to be number 0 rather than the newest, so I use (numdevs - * device_number - 1). */ - currentDevice = HIDGetFirstDevice(); + pCurrentHIDDevice = HIDGetFirstDevice(); for(i=0; i < numdevs - device_number - 1; ++i) - currentDevice = HIDGetNextDevice(currentDevice); + pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice); - return currentDevice; + return pCurrentHIDDevice; } -t_int hid_build_element_list(t_hid *x) + +void hid_build_element_list(t_hid *x) +{ + +} + + +t_int hid_print_element_list(t_hid *x) { DEBUG(post("hid_build_element_list");); @@ -200,8 +208,12 @@ t_int hid_build_element_list(t_hid *x) char usage_name[256]; pCurrentHIDDevice = hid_get_device_by_number(x->x_device_number); - if(!pCurrentHIDDevice) return (1); - + if ( ! HIDIsValidDevice(pCurrentHIDDevice) ) + { + error("[hid]: device %d is not a valid device\n",x->x_device_number); + return(1); + } + pCurrentHIDElement = HIDGetFirstDeviceElement(pCurrentHIDDevice, kHIDElementTypeInput); numElements = HIDCountDeviceElements(pCurrentHIDDevice, kHIDElementTypeInput); @@ -236,6 +248,36 @@ t_int hid_build_element_list(t_hid *x) } +void hid_print_device_list(t_hid *x) +{ + char cstrDeviceName [256]; + t_int i,numdevs; + UInt32 usagePage, usage; + pRecDevice pCurrentHIDDevice; + + if( HIDHaveDeviceList() ) + { + numdevs = (t_int) HIDCountDevices(); + + post(""); + /* display device list in console */ + for(i=0; i < numdevs; i++) + { + pCurrentHIDDevice = hid_get_device_by_number(i); + post("Device %d: '%s' '%s' version %d",i,pCurrentHIDDevice->manufacturer, + pCurrentHIDDevice->product,pCurrentHIDDevice->version); + //usage + HIDGetUsageName (pCurrentHIDDevice->usagePage, + pCurrentHIDDevice->usage, + cstrDeviceName); + DEBUG(post(" vendorID: %d productID: %d locID: %d", + pCurrentHIDDevice->vendorID, + pCurrentHIDDevice->productID, + pCurrentHIDDevice->locID);); + } + post(""); + } +} /* ============================================================================== */ /* Pd [hid] FUNCTIONS */ @@ -352,8 +394,8 @@ t_int hid_get_events(t_hid *x) ++event_counter; } DEBUG( - if(event_counter) - post("output %d events",event_counter); +// if(event_counter) +// post("output %d events",event_counter); ); /* /\* get the first element *\/ */ /* pCurrentHIDElement = HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeIO); */ @@ -396,24 +438,40 @@ t_int hid_open_device(t_hid *x, t_int device_number) { DEBUG(post("hid_open_device");); - t_int err,result; - pRecDevice currentDevice = NULL; + t_int result = 0; + pRecDevice pCurrentHIDDevice = NULL; - result = HIDBuildDeviceList (NULL, NULL); - // returns false if no device found - if(result) error("[hid]: no HID devices found\n"); +/* rebuild device list to make sure the list is current */ + if ( ! HIDHaveDeviceList() ) + { + result = (t_int) HIDBuildDeviceList (NULL, NULL); + // returns false if no device found + if(result) + { + error("[hid]: no HID devices found\n"); + return(result); + } + } + + pCurrentHIDDevice = hid_get_device_by_number(device_number); + if ( ! HIDIsValidDevice(pCurrentHIDDevice) ) + { + error("[hid]: device %d is not a valid device\n",device_number); + return(1); + } - currentDevice = hid_get_device_by_number(device_number); +// this doesn't seem to be needed at all +// result = HIDCreateOpenDeviceInterface(pCurrentHIDDevice); post("[hid] opened device %d: %s %s", - device_number, currentDevice->manufacturer, currentDevice->product); + device_number, pCurrentHIDDevice->manufacturer, pCurrentHIDDevice->product); hid_build_element_list(x); - HIDQueueDevice(currentDevice); + HIDQueueDevice(pCurrentHIDDevice); // TODO: queue all elements except absolute axes, those can just be polled - return (0); + return(result); } @@ -421,8 +479,14 @@ t_int hid_close_device(t_hid *x) { DEBUG(post("hid_close_device");); - post("[hid] closing device %d",x->x_device_number); - return( HIDDequeueDevice( hid_get_device_by_number(x->x_device_number) ) ); + t_int result = 0; + pRecDevice pCurrentHIDDevice = hid_get_device_by_number(x->x_device_number); + + HIDDequeueDevice(pCurrentHIDDevice); +// this doesn't seem to be needed at all +// result = HIDCloseReleaseInterface(pCurrentHIDDevice); + + return(result); } @@ -430,45 +494,33 @@ t_int hid_build_device_list(t_hid *x) { DEBUG(post("hid_build_device_list");); - int i,err; - UInt32 usagePage, usage; - pRecDevice pCurrentHIDDevice; - - Boolean result = HIDBuildDeviceList (NULL, NULL); // returns false if no device found - if(result) error("[hid]: no HID devices found\n"); + if(HIDBuildDeviceList (NULL, NULL)) + error("[hid]: no HID devices found\n"); - int numdevs = HIDCountDevices(); - // exit if no devices found - if(!numdevs) return (0); + return (0); +} - char cstrDeviceName [256]; - - post(""); - /* display device list in console */ - for(i=0; i < numdevs; i++) - { - pCurrentHIDDevice = hid_get_device_by_number(i); - post("Device %d: '%s' '%s' version %d",i,pCurrentHIDDevice->manufacturer, - pCurrentHIDDevice->product,pCurrentHIDDevice->version); - //usage - HIDGetUsageName (pCurrentHIDDevice->usagePage, - pCurrentHIDDevice->usage, - cstrDeviceName); - DEBUG(post(" vendorID: %d productID: %d locID: %d", - pCurrentHIDDevice->vendorID, - pCurrentHIDDevice->productID, - pCurrentHIDDevice->locID);); - } - post(""); + +void hid_print(t_hid *x) +{ + hid_print_device_list(x); - return (0); + if(x->x_device_open) + hid_print_element_list(x); } + void hid_platform_specific_free(t_hid *x) { - HIDReleaseAllDeviceQueues(); - HIDReleaseDeviceList(); + DEBUG(post("hid_platform_specific_free");); +/* only call this if the last instance is being freed */ + if (hid_instance_count < 1) + { + DEBUG(post("RELEASE ALL hid_instance_count: %d", hid_instance_count);); + HIDReleaseAllDeviceQueues(); + HIDReleaseDeviceList(); + } } //void HIDGetUsageName (const long valueUsagePage, const long valueUsage, char * cstrName) diff --git a/hid_linux.c b/hid_linux.c index 74b80cc..90fb6ad 100644 --- a/hid_linux.c +++ b/hid_linux.c @@ -42,7 +42,123 @@ /* LINUX-SPECIFIC SUPPORT FUNCTIONS */ /* ============================================================================== */ -void hid_list_devices(void) +void hid_print_element_list(t_hid *x) +{ + unsigned long bitmask[EV_MAX][NBITS(KEY_MAX)]; + char devicename[256] = "Unknown"; + t_int event_type, event_code; + char *event_type_name = ""; + /* counts for various event types */ + t_int synCount,keyCount,relCount,absCount,mscCount,ledCount,sndCount,repCount,ffCount,pwrCount,ff_statusCount; + + /* get name of device */ + ioctl(x->x_fd, EVIOCGNAME(sizeof(devicename)), devicename); + post ("\nConfiguring device %d as %s (%s)", + x->x_device_number,devicename,device_name); + + /* get bitmask representing supported events (axes, keys, etc.) */ + memset(bitmask, 0, sizeof(bitmask)); + ioctl(x->x_fd, EVIOCGBIT(0, EV_MAX), bitmask[0]); + post("\nSupported events:"); + +/* init all count vars */ + synCount = keyCount = relCount = absCount = mscCount = ledCount = 0; + sndCount = repCount = ffCount = pwrCount = ff_statusCount = 0; + + /* cycle through all possible event types */ + for (event_type = 0; event_type < EV_MAX; event_type++) + { + if (test_bit(event_type, bitmask[0])) + { + /* make pretty names for event types */ + switch(event_type) + { + case EV_SYN: event_type_name = "Synchronization"; break; + case EV_KEY: event_type_name = "Keys/Buttons"; break; + case EV_REL: event_type_name = "Relative Axis"; break; + case EV_ABS: event_type_name = "Absolute Axis"; break; + case EV_MSC: event_type_name = "Miscellaneous"; break; + case EV_LED: event_type_name = "LEDs"; break; + case EV_SND: event_type_name = "System Sounds"; break; + case EV_REP: event_type_name = "Autorepeat Values"; break; + case EV_FF: event_type_name = "Force Feedback"; break; + case EV_PWR: event_type_name = "Power"; break; + case EV_FF_STATUS: event_type_name = "Force Feedback Status"; break; + } +// post(" %s (%s) ", event_type_name, ev[event_type] ? ev[event_type] : "?", event_type); + + /* get bitmask representing supported button types */ + ioctl(x->x_fd, EVIOCGBIT(event_type, KEY_MAX), bitmask[event_type]); + + post(""); + post(" TYPE\tCODE\tEVENT NAME"); + post("-----------------------------------------------------------"); + + /* cycle through all possible event codes (axes, keys, etc.) + * testing to see which are supported + */ + for (event_code = 0; event_code < KEY_MAX; event_code++) + { + if (test_bit(event_code, bitmask[event_type])) + { + if ((event_type == EV_KEY) && (event_code >= BTN_MISC) && (event_code < KEY_OK) ) + { + char hid_code[7]; + hid_convert_linux_buttons_to_numbers(event_code,hid_code); + post(" %s\t%s\t%s", + ev[event_type] ? ev[event_type] : "?", + hid_code, + event_names[event_type] ? (event_names[event_type][event_code] ? event_names[event_type][event_code] : "?") : "?"); + } + else + post(" %s\t\t%s\t%s", + ev[event_type] ? ev[event_type] : "?", + event_names[event_type] ? (event_names[event_type][event_code] ? event_names[event_type][event_code] : "?") : "?", + event_type_name); +/* post(" Event code %d (%s)", event_code, names[event_type] ? (names[event_type][event_code] ? names[event_type][event_code] : "?") : "?"); */ + + switch(event_type) { +/* + * the API changed at some point... EV_SYN seems to be the new name + * from "Reset" events to "Syncronization" events + */ +#ifdef EV_RST + case EV_RST: synCount++; break; +#else + case EV_SYN: synCount++; break; +#endif + case EV_KEY: keyCount++; break; + case EV_REL: relCount++; break; + case EV_ABS: absCount++; break; + case EV_MSC: mscCount++; break; + case EV_LED: ledCount++; break; + case EV_SND: sndCount++; break; + case EV_REP: repCount++; break; + case EV_FF: ffCount++; break; + case EV_PWR: pwrCount++; break; + case EV_FF_STATUS: ff_statusCount++; break; + } + } + } + } + } + + post("\nDetected:"); + if (synCount > 0) post (" %d Sync types",synCount); + if (keyCount > 0) post (" %d Key/Button types",keyCount); + if (relCount > 0) post (" %d Relative Axis types",relCount); + if (absCount > 0) post (" %d Absolute Axis types",absCount); + if (mscCount > 0) post (" %d Misc types",mscCount); + if (ledCount > 0) post (" %d LED types",ledCount); + if (sndCount > 0) post (" %d System Sound types",sndCount); + if (repCount > 0) post (" %d Key Repeat types",repCount); + if (ffCount > 0) post (" %d Force Feedback types",ffCount); + if (pwrCount > 0) post (" %d Power types",pwrCount); + if (ff_statusCount > 0) post (" %d Force Feedback types",ff_statusCount); +} + + +void hid_print_device_list(void) { int i,fd; char device_output_string[256] = "Unknown"; @@ -138,26 +254,26 @@ t_int hid_get_events(t_hid *x) DEBUG(++event_counter;); } DEBUG( - if (event_counter > 0) - post("output %d events",event_counter); + //if (event_counter > 0) + //post("output %d events",event_counter); ); return (0); } +void hid_print(t_hid* x) +{ + hid_print_device_list(); +} + + t_int hid_open_device(t_hid *x, t_int device_number) { DEBUG(post("hid_open_device");); char device_name[20]; struct input_event hid_input_event; - unsigned long bitmask[EV_MAX][NBITS(KEY_MAX)]; - char devicename[256] = "Unknown"; - t_int event_type, event_code; - char *event_type_name = ""; - /* counts for various event types */ - t_int synCount,keyCount,relCount,absCount,mscCount,ledCount,sndCount,repCount,ffCount,pwrCount,ff_statusCount; x->x_fd = -1; @@ -181,111 +297,6 @@ t_int hid_open_device(t_hid *x, t_int device_number) * It seems that is just there to flush the input event queue */ while (read (x->x_fd, &(hid_input_event), sizeof(struct input_event)) > -1); - - /* get name of device */ - ioctl(x->x_fd, EVIOCGNAME(sizeof(devicename)), devicename); - post ("\nConfiguring device %d as %s (%s)", - x->x_device_number,devicename,device_name); - - /* get bitmask representing supported events (axes, keys, etc.) */ - memset(bitmask, 0, sizeof(bitmask)); - ioctl(x->x_fd, EVIOCGBIT(0, EV_MAX), bitmask[0]); - post("\nSupported events:"); - -/* init all count vars */ - synCount = keyCount = relCount = absCount = mscCount = ledCount = 0; - sndCount = repCount = ffCount = pwrCount = ff_statusCount = 0; - - /* cycle through all possible event types */ - for (event_type = 0; event_type < EV_MAX; event_type++) - { - if (test_bit(event_type, bitmask[0])) - { - /* make pretty names for event types */ - switch(event_type) - { - case EV_SYN: event_type_name = "Synchronization"; break; - case EV_KEY: event_type_name = "Keys/Buttons"; break; - case EV_REL: event_type_name = "Relative Axis"; break; - case EV_ABS: event_type_name = "Absolute Axis"; break; - case EV_MSC: event_type_name = "Miscellaneous"; break; - case EV_LED: event_type_name = "LEDs"; break; - case EV_SND: event_type_name = "System Sounds"; break; - case EV_REP: event_type_name = "Autorepeat Values"; break; - case EV_FF: event_type_name = "Force Feedback"; break; - case EV_PWR: event_type_name = "Power"; break; - case EV_FF_STATUS: event_type_name = "Force Feedback Status"; break; - } -// post(" %s (%s) ", event_type_name, ev[event_type] ? ev[event_type] : "?", event_type); - - /* get bitmask representing supported button types */ - ioctl(x->x_fd, EVIOCGBIT(event_type, KEY_MAX), bitmask[event_type]); - - post(""); - post(" TYPE\tCODE\tEVENT NAME"); - post("-----------------------------------------------------------"); - - /* cycle through all possible event codes (axes, keys, etc.) - * testing to see which are supported - */ - for (event_code = 0; event_code < KEY_MAX; event_code++) - { - if (test_bit(event_code, bitmask[event_type])) - { - if ((event_type == EV_KEY) && (event_code >= BTN_MISC) && (event_code < KEY_OK) ) - { - char hid_code[7]; - hid_convert_linux_buttons_to_numbers(event_code,hid_code); - post(" %s\t%s\t%s", - ev[event_type] ? ev[event_type] : "?", - hid_code, - event_names[event_type] ? (event_names[event_type][event_code] ? event_names[event_type][event_code] : "?") : "?"); - } - else - post(" %s\t\t%s\t%s", - ev[event_type] ? ev[event_type] : "?", - event_names[event_type] ? (event_names[event_type][event_code] ? event_names[event_type][event_code] : "?") : "?", - event_type_name); -/* post(" Event code %d (%s)", event_code, names[event_type] ? (names[event_type][event_code] ? names[event_type][event_code] : "?") : "?"); */ - - switch(event_type) { -/* - * the API changed at some point... EV_SYN seems to be the new name - * from "Reset" events to "Syncronization" events - */ -#ifdef EV_RST - case EV_RST: synCount++; break; -#else - case EV_SYN: synCount++; break; -#endif - case EV_KEY: keyCount++; break; - case EV_REL: relCount++; break; - case EV_ABS: absCount++; break; - case EV_MSC: mscCount++; break; - case EV_LED: ledCount++; break; - case EV_SND: sndCount++; break; - case EV_REP: repCount++; break; - case EV_FF: ffCount++; break; - case EV_PWR: pwrCount++; break; - case EV_FF_STATUS: ff_statusCount++; break; - } - } - } - } - } - - post("\nDetected:"); - if (synCount > 0) post (" %d Sync types",synCount); - if (keyCount > 0) post (" %d Key/Button types",keyCount); - if (relCount > 0) post (" %d Relative Axis types",relCount); - if (absCount > 0) post (" %d Absolute Axis types",absCount); - if (mscCount > 0) post (" %d Misc types",mscCount); - if (ledCount > 0) post (" %d LED types",ledCount); - if (sndCount > 0) post (" %d System Sound types",sndCount); - if (repCount > 0) post (" %d Key Repeat types",repCount); - if (ffCount > 0) post (" %d Force Feedback types",ffCount); - if (pwrCount > 0) post (" %d Power types",pwrCount); - if (ff_statusCount > 0) post (" %d Force Feedback types",ff_statusCount); return (0); } @@ -313,8 +324,6 @@ t_int hid_build_device_list(t_hid *x) * the current t_float, then this will probably need to be changed. */ - hid_list_devices(); - return (0); } diff --git a/joystick.pd b/joystick.pd index 77e5c83..955a987 100644 --- a/joystick.pd +++ b/joystick.pd @@ -1,4 +1,4 @@ -#N canvas 368 109 823 611 10; +#N canvas 246 181 827 615 10; #X msg 96 64 start; #X msg 105 83 stop; #X obj 77 30 inlet; @@ -24,30 +24,31 @@ ; #X text 228 566 released under the GNU GPL; #X text 424 566 $Author: eighthave $; -#X text 424 553 $Revision: 1.3 $$Date: 2004-11-16 01:35:35 $; -#X obj 38 489 autoscale -1 1; -#X obj 103 449 autoscale -1 1; -#X obj 169 409 autoscale -1 1; -#X obj 235 368 autoscale -1 1; +#X text 424 553 $Revision: 1.4 $$Date: 2004-11-28 01:27:47 $; #X obj 38 264 route abs_x abs_y abs_rz abs_throttle abs_hat0x abs_hat0y ; #X text 287 388 throttle/slider; #X text 346 343 hat0x; #X text 416 319 hat0y; +#X obj 235 368 autoscale 0 1; +#X obj 169 409 autoscale 0 1; +#X obj 103 449 autoscale 0 1; +#X obj 38 489 autoscale 0 1; +#X text 8 6 [joystick]; #X connect 0 0 10 0; #X connect 1 0 10 0; #X connect 2 0 10 0; #X connect 10 0 15 0; -#X connect 15 0 28 0; +#X connect 15 0 24 0; #X connect 15 1 9 0; #X connect 15 2 3 0; -#X connect 24 0 5 0; -#X connect 25 0 11 0; -#X connect 26 0 12 0; -#X connect 27 0 13 0; -#X connect 28 0 24 0; -#X connect 28 1 25 0; -#X connect 28 2 26 0; -#X connect 28 3 27 0; -#X connect 28 4 6 0; -#X connect 28 5 7 0; +#X connect 24 0 31 0; +#X connect 24 1 30 0; +#X connect 24 2 29 0; +#X connect 24 3 28 0; +#X connect 24 4 6 0; +#X connect 24 5 7 0; +#X connect 28 0 13 0; +#X connect 29 0 12 0; +#X connect 30 0 11 0; +#X connect 31 0 5 0; -- cgit v1.2.1