From 732d359c182794df20e78b4e00db4c5bf123dfec Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 8 Dec 2006 06:33:26 +0000 Subject: - laid out new event labeling scheme based more on USB HID rather than Linux input.h. It works on my devices on my Mac OS X. I probably broke Linux support. The scheme is in a new file, hidio_types.c - all event symbols except the vendor-defined usage are generated in hidio_setup(). The symbols for vendor-defined usages are generated when the device's element list is built. - changed macros to work cleanly when compiled on Windows using MinGW gcc - fixed up help file to better represent the state of things (still could be much better) svn path=/trunk/externals/io/hidio/; revision=6718 --- hidio.c | 252 ++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 134 insertions(+), 118 deletions(-) (limited to 'hidio.c') diff --git a/hidio.c b/hidio.c index 3a93938..9ec25fb 100644 --- a/hidio.c +++ b/hidio.c @@ -2,7 +2,7 @@ /* */ /* interface to native HID (Human Interface Devices) API */ /* Written by Hans-Christoph Steiner */ -/* Max/MSP port by Olaf Matthes */ +/* Max/MSP port by Olaf Matthes */ /* */ /* Copyright (c) 2004-2006 Hans-Christoph Steiner */ /* */ @@ -23,19 +23,19 @@ /* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* */ /* --------------------------------------------------------------------------*/ - -#ifdef _WINDOWS -/* any Windows specific includes go in here */ -#ifdef PD -#include -#endif /* PD */ + +#ifdef _WIN32 +/* any Windows specific includes go in here */ +#ifdef PD +#include +#endif /* PD */ #else #include -#include -#endif -#include -#include -#include +#include +#endif /* _WIN32 */ +#include +#include +#include #include "hidio.h" @@ -72,6 +72,13 @@ unsigned short element_count[MAX_DEVICES]; /* pre-generated symbols */ t_symbol *ps_open, *ps_device, *ps_poll, *ps_total, *ps_range; +t_symbol *ps_absolute, *ps_button, *ps_key, *ps_led, *ps_pid, *ps_relative; +t_symbol *absolute_symbols[ABSOLUTE_ARRAY_MAX]; +t_symbol *button_symbols[BUTTON_ARRAY_MAX]; +t_symbol *key_symbols[KEY_ARRAY_MAX]; +t_symbol *led_symbols[LED_ARRAY_MAX]; +t_symbol *pid_symbols[PID_ARRAY_MAX]; +t_symbol *relative_symbols[RELATIVE_ARRAY_MAX]; /*------------------------------------------------------------------------------ * FUNCTION PROTOTYPES @@ -91,14 +98,14 @@ static void hidio_open(t_hidio *x, t_symbol *s, int argc, t_atom *argv); void debug_print(t_int message_debug_level, const char *fmt, ...) { if(message_debug_level <= global_debug_level) - { + { char buf[MAXPDSTRING]; va_list ap; //t_int arg[8]; va_start(ap, fmt); vsnprintf(buf, MAXPDSTRING-1, fmt, ap); post(buf); - va_end(ap); + va_end(ap); } } @@ -125,7 +132,7 @@ static void output_status(t_hidio *x, t_symbol *selector, t_float output_value) SETFLOAT(output_atom, output_value); #else atom_setlong(output_atom, output_value); -#endif +#endif /* PD */ outlet_anything( x->x_status_outlet, selector, 1, output_atom); freebytes(output_atom,sizeof(t_atom)); } @@ -167,7 +174,7 @@ static void output_element_ranges(t_hidio *x) #else atom_setlong(output_data + 2, element[x->x_device_number][i]->min); atom_setlong(output_data + 3, element[x->x_device_number][i]->max); -#endif +#endif /* PD */ outlet_anything(x->x_status_outlet, ps_range, 4, output_data); } } @@ -197,7 +204,7 @@ static short get_device_number_from_arguments(int argc, t_atom *argv) long device_number = -1; char *device_type_string; long device_type_instance; -#endif +#endif /* PD */ unsigned int usage; unsigned short vendor_id; unsigned short product_id; @@ -212,14 +219,14 @@ static short get_device_number_from_arguments(int argc, t_atom *argv) #else atom_arg_getsym(&first_argument, 0,argc,argv); if(first_argument == _sym_nothing) -#endif +#endif /* PD */ { // single float arg means device # post("first_argument == &s_"); #ifdef PD device_number = (short) atom_getfloatarg(0,argc,argv); #else atom_arg_getlong(&device_number, 0, argc, argv); -#endif +#endif /* PD */ if(device_number < 0) device_number = -1; debug_print(LOG_DEBUG,"[hidio] setting device# to %d",device_number); } @@ -230,7 +237,7 @@ static short get_device_number_from_arguments(int argc, t_atom *argv) #else device_type_string = atom_string(argv); // LATER do we have to free this string manually??? -#endif +#endif /* PD */ usage = name_to_usage(device_type_string); device_number = get_device_number_from_usage(0, usage >> 16, usage & 0xffff); @@ -248,7 +255,7 @@ static short get_device_number_from_arguments(int argc, t_atom *argv) atom_arg_getsym(&first_argument, 0,argc,argv); atom_arg_getsym(&second_argument, 1,argc,argv); if( second_argument == _sym_nothing ) -#endif +#endif /* PD */ { /* a symbol then a float means match on usage */ #ifdef PD atom_string(argv, device_type_string, MAXPDSTRING-1); @@ -258,7 +265,7 @@ static short get_device_number_from_arguments(int argc, t_atom *argv) device_type_string = atom_string(argv); usage = name_to_usage(device_type_string); atom_arg_getlong(&device_type_instance, 1, argc, argv); -#endif +#endif /* PD */ debug_print(LOG_DEBUG,"[hidio] looking for %s at #%d", device_type_string, device_type_instance); device_number = get_device_number_from_usage(device_type_instance, @@ -280,8 +287,8 @@ static short get_device_number_from_arguments(int argc, t_atom *argv) void hidio_output_event(t_hidio *x, t_hid_element *output_data) { - if( (output_data->value != output_data->previous_value) || - (output_data->relative) ) // relative data should always be output + if( (output_data->relative) || // relative data should always be output + (output_data->value != output_data->previous_value) ) { t_atom event_data[3]; SETSYMBOL(event_data, output_data->name); @@ -389,11 +396,11 @@ t_int hidio_close(t_hidio *x) * closed / same device open * open / same device no action * closed / different device open - * open / different device close open + * open / different device close, open */ static void hidio_open(t_hidio *x, t_symbol *s, int argc, t_atom *argv) { - short device_number; + short device_number; debug_print(LOG_DEBUG,"hid_%s",s->s_name); pthread_mutex_lock(&x->x_mutex); @@ -417,8 +424,11 @@ t_int hidio_child_read(t_hidio *x) #ifdef PD double right_now = clock_getlogicaltime(); #else +/* TODO: this should use gettime() not systime_ms(). This needs to be logical + * time, not system time because the idea is that only one instance should get + * events from the OS in each slice of logical time */ double right_now = (double)systime_ms(); -#endif +#endif /* PD */ t_hid_element *current_element; if(right_now > last_execute_time[x->x_device_number]) @@ -481,13 +491,13 @@ static void hidio_int(t_hidio* x, long l) hidio_set_from_float(x, (float)l); } -#endif +#endif /* NOT PD */ static void hidio_debug(t_hidio *x, t_float f) { - pthread_mutex_lock(&x->x_mutex); + pthread_mutex_lock(&x->x_mutex); global_debug_level = f; - pthread_mutex_unlock(&x->x_mutex); + pthread_mutex_unlock(&x->x_mutex); } @@ -497,7 +507,7 @@ static void hidio_debug(t_hidio *x, t_float f) static void *hidio_child(void *zz) { - t_hidio *x = zz; + t_hidio *x = zz; short device_number = -1; pthread_mutex_lock(&x->x_mutex); @@ -513,19 +523,19 @@ static void *hidio_child(void *zz) short new_device_number = x->x_device_number; /* store running state to be restored after the device has been opened */ t_int started = x->x_started; - int ret; - /* check whether we have to close previous device */ - if (x->x_device_open && device_number != x->x_device_number) - { - pthread_mutex_unlock(&x->x_mutex); - stop_poll(x); - ret = hidio_close_device(x); - pthread_mutex_lock(&x->x_mutex); - x->x_device_open = 0; - device_number = -1; - } - /* no device open, so open one now */ - if (!x->x_device_open) + int ret; + /* check whether we have to close previous device */ + if (x->x_device_open && device_number != x->x_device_number) + { + pthread_mutex_unlock(&x->x_mutex); + stop_poll(x); + ret = hidio_close_device(x); + pthread_mutex_lock(&x->x_mutex); + x->x_device_open = 0; + device_number = -1; + } + /* no device open, so open one now */ + if (!x->x_device_open) { pthread_mutex_unlock(&x->x_mutex); ret = hidio_open_device(x, new_device_number); @@ -537,7 +547,7 @@ static void *hidio_child(void *zz) } else { - x->x_device_open = 1; + x->x_device_open = 1; device_number = x->x_device_number; /* keep local copy */ pthread_mutex_unlock(&x->x_mutex); /* restore the polling state so that when I [tgl] is used to start/stop [hidio], @@ -548,7 +558,7 @@ static void *hidio_child(void *zz) output_open_status(x); output_device_number(x); pthread_mutex_lock(&x->x_mutex); - } + } } if (x->x_requestcode == REQUEST_OPEN) x->x_requestcode = REQUEST_NOTHING; @@ -618,45 +628,45 @@ static void *hidio_child(void *zz) return (0); } -/* change priority of child thread */ -#ifdef PD -static void hidio_priority(t_hidio *x, t_floatarg p) -#else -static void hidio_priority(t_hidio *x, long p) -#endif -{ - pthread_mutex_lock(&x->x_mutex); - p = 2 * (CLIP(p, 0, 10) - 5); - if (x->x_thread) - { - struct sched_param parm; - int policy; - if (pthread_getschedparam(x->x_thread, &policy, &parm) < 0) - { - post("hidio: warning: failed to get thread priority"); - } - else - { - parm.sched_priority = x->x_priority + (int)p; /* adjust priority */ - - if (parm.sched_priority < sched_get_priority_min(policy)) - { - parm.sched_priority = sched_get_priority_min(policy); - } - else if (parm.sched_priority > sched_get_priority_max(policy)) - { - parm.sched_priority = sched_get_priority_max(policy); - } - - if (pthread_setschedparam(x->x_thread, policy, &parm) < 0) - { - post("hidio: warning: failed to change thread priority to %d", parm.sched_priority); - } - } - } - pthread_mutex_unlock(&x->x_mutex); -} - +/* change priority of child thread */ +#ifdef PD +static void hidio_priority(t_hidio *x, t_floatarg p) +#else +static void hidio_priority(t_hidio *x, long p) +#endif +{ + pthread_mutex_lock(&x->x_mutex); + p = 2 * (CLIP(p, 0, 10) - 5); + if (x->x_thread) + { + struct sched_param parm; + int policy; + if (pthread_getschedparam(x->x_thread, &policy, &parm) < 0) + { + post("hidio: warning: failed to get thread priority"); + } + else + { + parm.sched_priority = x->x_priority + (int)p; /* adjust priority */ + + if (parm.sched_priority < sched_get_priority_min(policy)) + { + parm.sched_priority = sched_get_priority_min(policy); + } + else if (parm.sched_priority > sched_get_priority_max(policy)) + { + parm.sched_priority = sched_get_priority_max(policy); + } + + if (pthread_setschedparam(x->x_thread, policy, &parm) < 0) + { + post("hidio: warning: failed to change thread priority to %d", parm.sched_priority); + } + } + } + pthread_mutex_unlock(&x->x_mutex); +} + /*------------------------------------------------------------------------------ * system functions @@ -699,12 +709,12 @@ static void hidio_free(t_hidio* x) pthread_cond_destroy(&x->x_requestcondition); pthread_cond_destroy(&x->x_answercondition); pthread_mutex_destroy(&x->x_mutex); -} +} /* create a new instance of this class */ static void *hidio_new(t_symbol *s, int argc, t_atom *argv) { - unsigned int i; + unsigned int i; #ifdef PD t_hidio *x = (t_hidio *)pd_new(hidio_class); @@ -721,19 +731,19 @@ static void *hidio_new(t_symbol *s, int argc, t_atom *argv) /* create anything outlet used for HID data */ x->x_status_outlet = outlet_new(x, "anything"); x->x_data_outlet = outlet_new(x, "anything"); -#endif +#endif /* PD */ + + /* init vars */ + global_debug_level = 9; /* high numbers here means see more messages */ + x->x_has_ff = 0; + x->x_device_open = 0; + x->x_started = 0; + x->x_delay = DEFAULT_DELAY; + for(i=0; ix_fd = INVALID_HANDLE_VALUE; +#endif /* _WIN32 */ - /* init vars */ - global_debug_level = 9; /* high numbers here means see more messages */ - x->x_has_ff = 0; - x->x_device_open = 0; - x->x_started = 0; - x->x_delay = DEFAULT_DELAY; - for(i=0; ix_fd = INVALID_HANDLE_VALUE; -#endif - pthread_mutex_init(&x->x_mutex, 0); pthread_cond_init(&x->x_requestcondition, 0); pthread_cond_init(&x->x_answercondition, 0); @@ -744,8 +754,8 @@ static void *hidio_new(t_symbol *s, int argc, t_atom *argv) hidio_instance_count++; x->x_requestcode = REQUEST_NOTHING; - pthread_create(&x->x_thread, 0, hidio_child, x); - + pthread_create(&x->x_thread, 0, hidio_child, x); + return (x); } @@ -767,6 +777,7 @@ void hidio_setup(void) /* add inlet message methods */ class_addmethod(hidio_class,(t_method) hidio_debug,gensym("debug"),A_DEFFLOAT,0); class_addmethod(hidio_class,(t_method) hidio_build_device_list,gensym("refresh"),0); +/* TODO: [print( should be dumped for [devices( and [elements( messages */ class_addmethod(hidio_class,(t_method) hidio_print,gensym("print"),0); class_addmethod(hidio_class,(t_method) hidio_info,gensym("info"),0); class_addmethod(hidio_class,(t_method) hidio_open,gensym("open"),A_GIMME,0); @@ -783,9 +794,9 @@ void hidio_setup(void) class_addmethod(hidio_class,(t_method) hidio_ff_stopall,gensym("ff_stopall"),0); /* ff tests */ class_addmethod(hidio_class,(t_method) hidio_ff_fftest,gensym("fftest"),A_DEFFLOAT,0); - class_addmethod(hidio_class,(t_method) hidio_ff_print,gensym("ff_print"),0); - - class_addmethod(hidio_class,(t_method) hidio_priority, gensym("priority"), A_FLOAT, A_NULL); + class_addmethod(hidio_class,(t_method) hidio_ff_print,gensym("ff_print"),0); + + class_addmethod(hidio_class,(t_method) hidio_priority, gensym("priority"), A_FLOAT, A_NULL); post("[hidio] %d.%d, written by Hans-Christoph Steiner ", @@ -799,6 +810,8 @@ void hidio_setup(void) ps_total = gensym("total"); ps_range = gensym("range"); + generate_type_symbols(); + generate_event_symbols(); } #else /* Max */ static void hidio_notify(t_hidio *x, t_symbol *s, t_symbol *msg, void *sender, void *data) @@ -814,15 +827,15 @@ static void hidio_assist(t_hidio *x, void *b, long m, long a, char *s) { if (m == 2) { - switch (a) - { - case 0: - sprintf(s, "(list) Received Events"); - break; - case 1: - sprintf(s, "(list) Status Info"); - break; - } + switch (a) + { + case 0: + sprintf(s, "(list) Received Events"); + break; + case 1: + sprintf(s, "(list) Status Info"); + break; + } } else { @@ -859,6 +872,7 @@ int main() /* add inlet message methods */ class_addmethod(c, (method)hidio_debug, "debug",A_DEFFLOAT,0); class_addmethod(c, (method)hidio_build_device_list, "refresh",0); +/* TODO: [print( should be dumped for [devices( and [elements( messages */ class_addmethod(c, (method)hidio_print, "print",0); class_addmethod(c, (method)hidio_info, "info",0); class_addmethod(c, (method)hidio_open, "open",A_GIMME,0); @@ -875,8 +889,8 @@ int main() /* ff tests */ class_addmethod(c, (method)hidio_ff_fftest, "fftest",A_DEFFLOAT,0); class_addmethod(c, (method)hidio_ff_print, "ff_print",0); - /* perfomrance / system stuff */ - class_addmethod(c, (method)hidio_priority, "priority", A_LONG,0); + /* perfomrance / system stuff */ + class_addmethod(c, (method)hidio_priority, "priority", A_LONG,0); class_addmethod(c, (method)hidio_assist, "assist", A_CANT, 0); @@ -891,9 +905,9 @@ int main() hidio_class = c; finder_addclass("Devices", "hidio"); - post("hidio %d.%d: © 2006 by Hans-Christoph Steiner & Olaf Matthes", + post("hidio %d.%d: © 2006 by Hans-Christoph Steiner & Olaf Matthes", HIDIO_MAJOR_VERSION, HIDIO_MINOR_VERSION); - post("hidio: compiled on "__DATE__" at "__TIME__ " "); + post("hidio: compiled on "__DATE__" at "__TIME__ " "); /* pre-generate often used symbols */ ps_open = gensym("open"); @@ -902,7 +916,9 @@ int main() ps_total = gensym("total"); ps_range = gensym("range"); + generate_event_symbols(); + return 0; } -#endif +#endif /* PD */ -- cgit v1.2.1