Update of /cvsroot/pure-data/externals/hcs/hid In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18279
Modified Files: Makefile TODO hid.c hid.h hid_darwin.c hid_linux.c Log Message: ripped out old method of get events and build whole new method which should use a lot less CPU; its now based on arrays of structs that are built before running. There is a 2D array for (device,element) struct, t_hid_element, which holds the output symbols, thus eliminating symbol lookups for each event that is outputted; its Mac OS X only write now, GNU/Linux will come eventually...
Index: hid.c =================================================================== RCS file: /cvsroot/pure-data/externals/hcs/hid/hid.c,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** hid.c 27 May 2006 23:12:51 -0000 1.24 --- hid.c 2 Jun 2006 20:06:50 -0000 1.25 *************** *** 123,129 ****
! static t_int get_device_number_from_arguments(int argc, t_atom *argv) { ! t_int device_number = -1; unsigned short usage_number; unsigned int usage; --- 123,129 ----
! static short get_device_number_from_arguments(int argc, t_atom *argv) { ! short device_number = -1; unsigned short usage_number; unsigned int usage; *************** *** 136,144 **** if(argc == 1) { - post("one arg"); first_argument = atom_getsymbolarg(0,argc,argv); if(first_argument == &s_) { // single float arg means device ! device_number = (unsigned short) atom_getfloatarg(0,argc,argv); if(device_number < 0) device_number = -1; debug_print(LOG_DEBUG,"[hid] setting device# to %d",device_number); --- 136,143 ---- if(argc == 1) { first_argument = atom_getsymbolarg(0,argc,argv); if(first_argument == &s_) { // single float arg means device ! device_number = (short) atom_getfloatarg(0,argc,argv); if(device_number < 0) device_number = -1; debug_print(LOG_DEBUG,"[hid] setting device# to %d",device_number); *************** *** 165,169 **** usage = name_to_usage(usage_string); usage_number = atom_getfloatarg(1,argc,argv); ! debug_print(LOG_DEBUG,"[hid] looking for %s at #%d",usage_string,usage_number); device_number = get_device_number_from_usage_list(usage_number, usage >> 16, --- 164,169 ---- usage = name_to_usage(usage_string); usage_number = atom_getfloatarg(1,argc,argv); ! debug_print(LOG_DEBUG,"[hid] looking for %s at #%d", ! usage_string,usage_number); device_number = get_device_number_from_usage_list(usage_number, usage >> 16, *************** *** 172,177 **** else { /* two symbols means idVendor and idProduct in hex */ ! vendor_id = (unsigned short) strtol(first_argument->s_name, NULL, 16); ! product_id = (unsigned short) strtol(second_argument->s_name, NULL, 16); device_number = get_device_number_by_id(vendor_id,product_id); } --- 172,179 ---- else { /* two symbols means idVendor and idProduct in hex */ ! vendor_id = ! (unsigned short) strtol(first_argument->s_name, NULL, 16); ! product_id = ! (unsigned short) strtol(second_argument->s_name, NULL, 16); device_number = get_device_number_by_id(vendor_id,product_id); } *************** *** 180,194 **** }
- void hid_output_event(t_hid *x, t_symbol *type, t_symbol *code, t_float value) - { - t_atom event_data[3]; - - SETSYMBOL(event_data, type); - SETSYMBOL(event_data + 1, code); - SETFLOAT(event_data + 2, value);
! outlet_anything(x->x_data_outlet,atom_gensym(event_data),2,event_data+1); }
/* stop polling the device */ static void stop_poll(t_hid* x) --- 182,199 ---- }
! void hid_output_event(t_hid *x, t_hid_element *output_data) ! { ! if( (output_data->value != output_data->previous_value) || ! (output_data->relative) ) // relative data should always be output ! { ! t_atom event_data[2]; ! SETSYMBOL(event_data, output_data->name); ! SETFLOAT(event_data + 1, output_data->value); ! outlet_anything(x->x_data_outlet,output_data->type,2,event_data); ! } }
+ /* stop polling the device */ static void stop_poll(t_hid* x) *************** *** 213,229 **** debug_print(LOG_DEBUG,"hid_poll");
! /* if the user sets the delay less than one, ignore */ ! if( f > 0 ) x->x_delay = (t_int)f; ! ! if( (!x->x_device_open) && (x->x_device_number > -1) ) ! hid_open(x,gensym("open"),0,NULL); ! ! if(!x->x_started) { ! clock_delay(x->x_clock, x->x_delay); ! debug_print(LOG_DEBUG,"[hid] polling started"); ! x->x_started = 1; ! } }
--- 218,237 ---- debug_print(LOG_DEBUG,"hid_poll");
! /* if the user sets the delay less than 2, set to block size */ ! if( f > 2 ) x->x_delay = (t_int)f; ! else if( f > 0 ) //TODO make this the actual time between message processing ! x->x_delay = 1.54; ! if(x->x_device_number > -1) { ! if(!x->x_device_open) ! hid_open(x,gensym("open"),0,NULL); ! if(!x->x_started) ! { ! clock_delay(x->x_clock, x->x_delay); ! debug_print(LOG_DEBUG,"[hid] polling started"); ! x->x_started = 1; ! } ! } }
*************** *** 232,246 **** /* values greater than 1 set the polling delay time */ /* 1 and 0 for start/stop so you can use a [tgl] */ ! if (f > 1) { x->x_delay = (t_int)f; hid_poll(x,f); } ! else if (f == 1) { ! if (! x->x_started) ! hid_poll(x,f); } ! else if (f == 0) { stop_poll(x); --- 240,254 ---- /* values greater than 1 set the polling delay time */ /* 1 and 0 for start/stop so you can use a [tgl] */ ! if(f > 1) { x->x_delay = (t_int)f; hid_poll(x,f); } ! else if(f == 1) { ! if(! x->x_started) ! hid_poll(x,f); } ! else if(f == 0) { stop_poll(x); *************** *** 281,285 **** t_int started = x->x_started; ! int device_number = get_device_number_from_arguments(argc, argv); if(device_number > -1) { --- 289,293 ---- t_int started = x->x_started; ! short device_number = get_device_number_from_arguments(argc, argv); if(device_number > -1) {
Index: hid.h =================================================================== RCS file: /cvsroot/pure-data/externals/hcs/hid/hid.h,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** hid.h 28 May 2006 20:13:57 -0000 1.23 --- hid.h 2 Jun 2006 20:06:50 -0000 1.24 *************** *** 27,30 **** --- 27,37 ---- #define MAX_DEVICES 128
+ /* think 64 is the limit per device as defined in the OS */ + #define MAX_ELEMENTS 64 + + /* this is limited so that the object doesn't cause a click getting too many + * events from the OS's event queue */ + #define MAX_EVENTS_PER_POLL 64 + /*------------------------------------------------------------------------------ * CLASS DEF *************** *** 34,38 **** t_object x_obj; t_int x_fd; ! t_int x_device_number; // unsigned short vendor_id; // USB idVendor for current device // unsigned short product_id; // USB idProduct for current device --- 41,45 ---- t_object x_obj; t_int x_fd; ! short x_device_number; // unsigned short vendor_id; // USB idVendor for current device // unsigned short product_id; // USB idProduct for current device *************** *** 65,68 **** --- 72,97 ---- * poll. This should probably be an array for efficiency */
+ + typedef struct _hid_element + { + #ifdef __linux__ + //GNU/Linux store type and code to compare against + #else + void *os_pointer; // pRecElement on Mac OS X; + #endif /* __linux__ */ + t_symbol *type; // Linux "type"; HID "usagePage" + t_symbol *name; // Linux "code"; HID "usage" + unsigned char polled; // is it polled or queued? (maybe only on Mac OS X?) + unsigned char relative; // relative data gets output everytime + t_float instance; // usage page/usage instance # ([absolute throttle 2 163( + t_int value; // output the sum of events in a poll for relative axes + t_int previous_value; //only output on change on abs and buttons + } t_hid_element; + + /* store element structs to eliminate symbol table lookups, etc. */ + t_hid_element *element[MAX_DEVICES][MAX_ELEMENTS]; + /* number of active elements per device */ + unsigned short element_count[MAX_DEVICES]; + /*------------------------------------------------------------------------------ * FUNCTION PROTOTYPES FOR DIFFERENT PLATFORMS *************** *** 72,89 **** void debug_print(t_int debug_level, const char *fmt, ...); void debug_error(t_hid *x, t_int debug_level, const char *fmt, ...); void hid_output_event(t_hid *x, t_symbol *type, t_symbol *code, t_float value);
/* generic, cross-platform functions implemented in a separate file for each * platform */ ! t_int hid_open_device(t_hid *x, t_int device_number); t_int hid_close_device(t_hid *x); void hid_build_device_list(void); ! t_int hid_get_events(t_hid *x); void hid_print(t_hid* x); /* print info to the console */ void hid_platform_specific_info(t_hid* x); /* device info on the status outlet */ void hid_platform_specific_free(t_hid *x); ! t_int get_device_number_by_id(unsigned short vendor_id, unsigned short product_id); ! t_int get_device_number_from_usage_list(t_int device_number, unsigned short usage_page, unsigned short usage); --- 101,121 ---- void debug_print(t_int debug_level, const char *fmt, ...); void debug_error(t_hid *x, t_int debug_level, const char *fmt, ...); + void hid_output_event(t_hid *x, t_hid_element *output_data); + /* the old way void hid_output_event(t_hid *x, t_symbol *type, t_symbol *code, t_float value); + */
/* generic, cross-platform functions implemented in a separate file for each * platform */ ! t_int hid_open_device(t_hid *x, short device_number); t_int hid_close_device(t_hid *x); void hid_build_device_list(void); ! void hid_get_events(t_hid *x); void hid_print(t_hid* x); /* print info to the console */ void hid_platform_specific_info(t_hid* x); /* device info on the status outlet */ void hid_platform_specific_free(t_hid *x); ! short get_device_number_by_id(unsigned short vendor_id, unsigned short product_id); ! short get_device_number_from_usage_list(short device_number, unsigned short usage_page, unsigned short usage);
Index: Makefile =================================================================== RCS file: /cvsroot/pure-data/externals/hcs/hid/Makefile,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** Makefile 27 May 2006 00:57:15 -0000 1.15 --- Makefile 2 Jun 2006 20:06:50 -0000 1.16 *************** *** 14,15 **** --- 14,19 ---- make -C $(EXTERNALS_ROOT) test_locations
+ # for emacs + etags: + etags *.[ch] linux/input.h HID\ Utilities\ Source/*.[ch] \ + /System/Library/Frameworks/IOKit.framework/Headers/hid*/*.[ch]
Index: hid_darwin.c =================================================================== RCS file: /cvsroot/pure-data/externals/hcs/hid/hid_darwin.c,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** hid_darwin.c 28 May 2006 20:13:57 -0000 1.23 --- hid_darwin.c 2 Jun 2006 20:06:50 -0000 1.24 *************** *** 63,69 **** extern t_int hid_instance_count;
! /* store device pointers */ pRecDevice device_pointer[MAX_DEVICES];
/*============================================================================== * FUNCTION PROTOTYPES --- 63,77 ---- extern t_int hid_instance_count;
[...2255 lines suppressed...] ! default: sprintf (cstrName, "Arcade Usage 0x%lx", element->usage); break; ! } ! break; ! default: ! if (element->usagePage > kHIDPage_VendorDefinedStart) ! sprintf (cstrName, "Vendor Defined Usage 0x%lx", element->usage); ! else ! sprintf (cstrName, "Page: 0x%lx, Usage: 0x%lx", element->usagePage, element->usage); ! break; } ! return(cstrName); }
*************** *** 1468,1469 **** --- 1458,1460 ----
#endif /* #ifdef __APPLE__ */ +
Index: hid_linux.c =================================================================== RCS file: /cvsroot/pure-data/externals/hcs/hid/hid_linux.c,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** hid_linux.c 28 May 2006 01:05:45 -0000 1.17 --- hid_linux.c 2 Jun 2006 20:06:50 -0000 1.18 *************** *** 349,353 **** /* ------------------------------------------------------------------------------ */
! t_int hid_get_events(t_hid *x) { debug_print(LOG_DEBUG,"hid_get_events"); --- 349,353 ---- /* ------------------------------------------------------------------------------ */
! void hid_get_events(t_hid *x) { debug_print(LOG_DEBUG,"hid_get_events"); *************** *** 363,367 **** struct input_event hid_input_event;
! if (x->x_fd < 0) return 0;
while( read (x->x_fd, &(hid_input_event), sizeof(struct input_event)) > -1 ) --- 363,367 ---- struct input_event hid_input_event;
! if (x->x_fd < 0) return;
while( read (x->x_fd, &(hid_input_event), sizeof(struct input_event)) > -1 ) *************** *** 399,403 **** ); ! return (0); }
--- 399,403 ---- ); ! return; }
*************** *** 421,425 ****
x->x_device_number = device_number; ! sprintf(dev_handle_name,"/dev/input/event%d",(int)x->x_device_number);
if (dev_handle_name) --- 421,425 ----
x->x_device_number = device_number; ! sprintf(dev_handle_name,"/dev/input/event%d",x->x_device_number);
if (dev_handle_name)
Index: TODO =================================================================== RCS file: /cvsroot/pure-data/externals/hcs/hid/TODO,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** TODO 28 May 2006 20:13:57 -0000 1.24 --- TODO 2 Jun 2006 20:06:50 -0000 1.25 *************** *** 1,5 ****
! ============================================================================== = output one value per poll
--- 1,56 ----
+ - fix up hatswitch logic... hmmm + on Mac OS X, just make the next element in the array always be the Y axis of + the hatswitch, then when receiving a hatswitch event, output, increment, + then output again (yes, its a hack).
! - add device type to [info( ! HIDGetUsageName(pCurrentHIDDevice->usagePage, pCurrentHIDDevice->usage, cstrDeviceName); ! ! i.e. cstrDeviceName ! ! ! ! ! ______________________________________________________________________________ ! = array lookups for symbols ! ! - make arrays to lookup symbols by usagepage# and usage# ! ! - advantage: much fewer symbol lookups ! ! - disadvantage: much more RAM used. ! ! implementation idea #1: ! ! make hid-specific gensym() function which checks an array for the symbol by ! #. If it doesn't exist, it looks up the symbol and adds it to the array. The ! array size should be dynamically allocated so that [hid] doesn't use massive ! amounts of memory. ! ! If no vendor-defined pages are used, then the array could be quite small. If ! only one usage page is used, then it would also be not too big. Otherwise, it ! could use 10+ megs of RAM... hmm.. ! ! implementation idea #2: ! ! this array should be built by hid_build_elements_list(). Then each time it ! fetches an event using the element_pointer array, it would also get the stored ! usage_page and usage symbols, and instance t_float. So I need to make an ! element struct like: ! ! struct _hid_element ! { ! void *element; ! t_symbol *type; // HID "usage page" ! t_symbol *usage; // Linux "code" ! t_float instance; ! t_float previous_value; //only output on change on abs and buttons ! } t_hid_element; ! ! For Linux input.h, instead void *element, store the type and code numbers to ! compare against ! ! ______________________________________________________________________________ = output one value per poll
*************** *** 12,19 **** - buttons, output everything
! - is this at all necessary? How often do multiple events happen in one poll period?
! ============================================================================== = iterate through elements and do a proper queue of the ones we want:
--- 63,78 ---- - buttons, output everything
! - is this at all necessary? How often do multiple events happen in one poll ! period? ANSWER: on Mac OS X, most hid_get_events() calls fetch multiple ! events for each mouse axis, so yes, its probably necessary
! ______________________________________________________________________________ ! = [poll 1( message set to exact delay based on block size ! ! to eliminate the jitter of the messages being processed every block, have ! [poll 1( set the time to the poll size (~1.5ms for 44,100) ! ! ______________________________________________________________________________ = iterate through elements and do a proper queue of the ones we want:
*************** *** 23,31 ****
! ============================================================================== = make second inlet for poll # (for [human->pd])
! ============================================================================== = output device data on open
--- 82,90 ----
! ______________________________________________________________________________ = make second inlet for poll # (for [human->pd])
! ______________________________________________________________________________ = output device data on open
*************** *** 35,39 ****
! ============================================================================== = open devices by name
--- 94,98 ----
! ______________________________________________________________________________ = open devices by name
*************** *** 41,45 ****
! ============================================================================== = = autoscaling based on Logical min/max --- 100,104 ----
! ______________________________________________________________________________ = = autoscaling based on Logical min/max *************** *** 50,56 **** - output would be handy, rather than autoscale, to save on CPU
! ! ============================================================================== = test verbose names
--- 109,115 ---- - output would be handy, rather than autoscale, to save on CPU
+ - this should probably be done in Pd space
! ______________________________________________________________________________ = test verbose names
*************** *** 76,80 ****
! ============================================================================== = event name changes
--- 135,139 ----
! ______________________________________________________________________________ = event name changes
*************** *** 82,86 ****
! ============================================================================== = hid/serial
--- 141,145 ----
! ______________________________________________________________________________ = hid/serial
*************** *** 92,96 ****
! ============================================================================== = linux input synch events (EV_SYN)
--- 151,155 ----
! ______________________________________________________________________________ = linux input synch events (EV_SYN)
*************** *** 101,106 ****
! ============================================================================== = profile [hid] object and usage
--- 160,170 ----
+ ______________________________________________________________________________ + = writing support!
! - Linux example: http://www.linuxjournal.com/article/6429 ! ! ! ______________________________________________________________________________ = profile [hid] object and usage
*************** *** 109,113 ****
! ============================================================================== = Report available FF effects
--- 173,177 ----
! ______________________________________________________________________________ = Report available FF effects
*************** *** 115,119 ****
! ============================================================================== = pollfn for mouse-like devices
--- 179,183 ----
! ______________________________________________________________________________ = pollfn for mouse-like devices
*************** *** 128,132 ****
! ============================================================================== = function return values
--- 192,196 ----
! ______________________________________________________________________________ = function return values
*************** *** 134,138 ****
! ============================================================================== = check out using USB timestamp
--- 198,202 ----
! ______________________________________________________________________________ = check out using USB timestamp
*************** *** 142,150 ****
! /++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\ ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
______________________________________________________________________________ --- 206,224 ----
! /----------------------------------------------------------------------------\ ! ------------------------------------------------------------------------------ BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS BUGS ! ------------------------------------------------------------------------------ ! ----------------------------------------------------------------------------/ ! ! ______________________________________________________________________________ ! - BUG: crashes when you try yo open "mouse" with no args ! ! ! ______________________________________________________________________________ ! - BUG: on Mac OS X, polling starts without hid_build_device_list() ! ! - when polling starts, hid_build_device_list() should be called before starting !
______________________________________________________________________________