[PD-cvs] externals/hcs/hid Makefile, 1.15, 1.16 TODO, 1.24, 1.25 hid.c, 1.24, 1.25 hid.h, 1.23, 1.24 hid_darwin.c, 1.23, 1.24 hid_linux.c, 1.17, 1.18

Hans-Christoph Steiner eighthave at users.sourceforge.net
Fri Jun 2 22:06:53 CEST 2006


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
! 
  
  ______________________________________________________________________________





More information about the Pd-cvs mailing list