From 0d73c7d8ebc049bf080d28f0c0f96861f4fe2312 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 27 May 2006 23:12:51 +0000 Subject: added some status reporting, and got all the different methods for opening working on Mac OS X; time to fix GNU/Linux now... svn path=/trunk/externals/hcs/hid/; revision=5145 --- TODO | 6 ++- doc/hid-help.pd | 74 +++++++++++++++++++++++++---- hid.c | 50 +++++++++++++++---- hid.h | 11 +++-- hid_darwin.c | 145 +++++++++++++++++++++++++++++++++++++------------------- hid_linux.c | 2 +- hid_windows.c | 4 +- 7 files changed, 217 insertions(+), 75 deletions(-) diff --git a/TODO b/TODO index 9a4af45..a6d899c 100644 --- a/TODO +++ b/TODO @@ -1,11 +1,13 @@ +============================================================================== += make second inlet for poll # (for [human->pd] + + ============================================================================== = output device data on open - Logical Min/Max i.e. [range -127 127( -- open 1/0 i.e. [open 1( -- vendor/product id i.e. [id 0x1234 0x4567( - device string [name Trackpad( diff --git a/doc/hid-help.pd b/doc/hid-help.pd index 74b0b51..541ea8e 100644 --- a/doc/hid-help.pd +++ b/doc/hid-help.pd @@ -1,5 +1,5 @@ -#N canvas 164 36 915 630 10; -#X msg 233 353 rel rel_x 1; +#N canvas 54 47 924 649 10; +#X msg 233 353 not_implemented notimp_64 -255; #X floatatom 27 484 5 0 0 0 - - -; #X floatatom 83 484 5 0 0 0 - - -; #X floatatom 63 440 6 0 0 0 - - -; @@ -34,7 +34,7 @@ #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.21 $$Date: 2006-05-27 16:41:59 $; +#X text 472 589 $Revision: 1.22 $$Date: 2006-05-27 23:12:51 $; #X text 473 602 $Author: eighthave $; #X msg 421 266 poll 20; #X msg 359 266 poll 2; @@ -328,12 +328,68 @@ btn_8 btn_9 btn_10 btn_11 btn_12 btn_13 btn_14 btn_15; -1 0; #X msg 233 111 open mouse \$1; #X text 541 208 Gravis/Destroyer Tiltpad; -#X text 535 179 Microsoft 5-button Mouse; -#X msg 395 179 open 0x045e 0x0039; #X msg 400 207 open 0x047D 0x4008; #X obj 253 135 hradio 15 1 0 8 empty empty empty 0 -6 0 8 -262144 -1 -1 0; #X msg 262 155 open keyboard \$1; +#X msg 298 190 info; +#N canvas 477 37 395 219 see 0; +#N canvas 247 287 550 277 route 0; +#X obj 53 13 inlet; +#X obj 98 225 outlet; +#X obj 45 225 outlet; +#X obj 198 203 symbol; +#X obj 198 225 outlet; +#X obj 258 203 symbol; +#X obj 258 225 outlet; +#X obj 318 203 symbol; +#X obj 318 225 outlet; +#X obj 378 203 symbol; +#X obj 378 225 outlet; +#X obj 438 203 symbol; +#X obj 438 225 outlet; +#X obj 52 62 route open device poll product manufacturer transport +vendorID productID; +#X obj 148 224 outlet; +#X connect 0 0 13 0; +#X connect 3 0 4 0; +#X connect 5 0 6 0; +#X connect 7 0 8 0; +#X connect 9 0 10 0; +#X connect 11 0 12 0; +#X connect 13 0 2 0; +#X connect 13 1 1 0; +#X connect 13 2 14 0; +#X connect 13 3 3 0; +#X connect 13 4 5 0; +#X connect 13 5 7 0; +#X connect 13 6 9 0; +#X connect 13 7 11 0; +#X restore 55 66 pd route info; +#X obj 54 88 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 +; +#X obj 61 23 inlet; +#X obj 74 44 print info; +#X symbolatom 255 94 0 0 0 0 productID - -; +#X symbolatom 255 113 0 0 0 0 vendorID - -; +#X symbolatom 255 132 0 0 0 0 transport - -; +#X symbolatom 255 152 0 0 0 0 manufacturer - -; +#X symbolatom 137 173 0 0 0 0 product - -; +#X floatatom 48 141 5 0 0 0 device - -; +#X floatatom 48 163 5 0 0 0 poll - -; +#X connect 0 0 1 0; +#X connect 0 1 9 0; +#X connect 0 2 10 0; +#X connect 0 3 8 0; +#X connect 0 4 7 0; +#X connect 0 5 6 0; +#X connect 0 6 5 0; +#X connect 0 7 4 0; +#X connect 2 0 0 0; +#X connect 2 0 3 0; +#X restore 494 323 pd see device info; +#X msg 397 179 open 0x046d 0xc01d; +#X text 535 179 Logitech USB-PS/2 Optical Mouse; #X connect 4 0 49 0; #X connect 23 0 24 1; #X connect 24 0 23 0; @@ -357,6 +413,7 @@ btn_8 btn_9 btn_10 btn_11 btn_12 btn_13 btn_14 btn_15; #X connect 49 0 38 0; #X connect 49 0 59 0; #X connect 49 0 94 0; +#X connect 49 1 105 0; #X connect 56 0 49 0; #X connect 57 0 1 0; #X connect 57 1 2 0; @@ -400,7 +457,8 @@ btn_8 btn_9 btn_10 btn_11 btn_12 btn_13 btn_14 btn_15; #X connect 96 0 95 0; #X connect 98 0 99 0; #X connect 99 0 49 0; -#X connect 102 0 49 0; +#X connect 101 0 49 0; +#X connect 102 0 103 0; #X connect 103 0 49 0; -#X connect 104 0 105 0; -#X connect 105 0 49 0; +#X connect 104 0 49 0; +#X connect 106 0 49 0; diff --git a/hid.c b/hid.c index b79a84e..741cb4b 100644 --- a/hid.c +++ b/hid.c @@ -85,6 +85,30 @@ void debug_error(t_hid *x, t_int message_debug_level, const char *fmt, ...) } } + +static void output_status(t_hid *x, t_symbol *selector, t_float output_value) +{ + t_atom *output_atom = getbytes(sizeof(t_atom)); + SETFLOAT(output_atom, output_value); + outlet_anything( x->x_status_outlet, selector, 1, output_atom); + freebytes(output_atom,sizeof(t_atom)); +} + +static void output_open_status(t_hid *x) +{ + output_status(x, gensym("open"), x->x_device_open); +} + +static void output_device_number(t_hid *x) +{ + output_status(x, gensym("device"), x->x_device_number); +} + +static void output_poll_time(t_hid *x) +{ + output_status(x, gensym("poll"), x->x_delay); +} + static unsigned int name_to_usage(char *usage_name) { // output usagepage << 16 + usage if(strcmp(usage_name,"pointer") == 0) return(0x00010001); @@ -133,7 +157,6 @@ static t_int get_device_number_from_arguments(int argc, t_atom *argv) } else if(argc == 2) { - post("two arg"); first_argument = atom_getsymbolarg(0,argc,argv); second_argument = atom_getsymbolarg(1,argc,argv); if( second_argument == &s_ ) @@ -148,7 +171,6 @@ static t_int get_device_number_from_arguments(int argc, t_atom *argv) } else { /* two symbols means idVendor and idProduct in hex */ - post("idVendor and idProduct"); 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); @@ -157,14 +179,13 @@ static t_int get_device_number_from_arguments(int argc, t_atom *argv) return(device_number); } - -void hid_output_event(t_hid *x, char *type, char *code, t_float value) +void hid_output_event(t_hid *x, t_symbol *type, t_symbol *code, t_float value) { t_atom event_data[3]; - SETSYMBOL(event_data, gensym(type)); /* type */ - SETSYMBOL(event_data + 1, gensym(code)); /* code */ - SETFLOAT(event_data + 2, value); /* value */ + 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); } @@ -272,11 +293,14 @@ static void hid_open(t_hid *x, t_symbol *s, int argc, t_atom *argv) x->x_device_open = 1; } } + else debug_print(LOG_WARNING,"[hid] device does not exist"); /* 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 */ if(started) hid_set_from_float(x,x->x_delay); - debug_print(LOG_DEBUG,"[hid] done device# to %d",device_number); + debug_print(LOG_DEBUG,"[hid] set device# to %d",device_number); + output_open_status(x); + output_device_number(x); } @@ -314,6 +338,14 @@ static void hid_anything(t_hid *x, t_symbol *s, t_int argc, t_atom *argv) } */ +static void hid_info(t_hid *x) +{ + output_open_status(x); + output_device_number(x); + output_poll_time(x); + hid_platform_specific_info(x); +} + static void hid_float(t_hid* x, t_floatarg f) { debug_print(LOG_DEBUG,"hid_float"); @@ -373,7 +405,7 @@ static void *hid_new(t_symbol *s, int argc, t_atom *argv) /* create anything outlet used for HID data */ x->x_data_outlet = outlet_new(&x->x_obj, 0); - x->x_device_name_outlet = outlet_new(&x->x_obj, 0); + x->x_status_outlet = outlet_new(&x->x_obj, 0); x->x_device_number = get_device_number_from_arguments(argc, argv); diff --git a/hid.h b/hid.h index 7abddd4..7c74d46 100644 --- a/hid.h +++ b/hid.h @@ -15,7 +15,7 @@ #define HID_MAJOR_VERSION 0 #define HID_MINOR_VERSION 7 -/* static char *version = "$Revision: 1.21 $"; */ +/* static char *version = "$Revision: 1.22 $"; */ /*------------------------------------------------------------------------------ * CLASS DEF @@ -34,7 +34,7 @@ typedef struct _hid t_int x_started; t_int x_device_open; t_outlet *x_data_outlet; - t_outlet *x_device_name_outlet; + t_outlet *x_status_outlet; } t_hid; @@ -64,7 +64,7 @@ extern unsigned short global_debug_level; /* support functions */ 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, char *type, char *code, t_float value); +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 @@ -73,12 +73,13 @@ 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_info(t_hid* x); /* output device info on the status outlet */ 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); + unsigned short usage_page, + unsigned short usage); /* cross-platform force feedback functions */ diff --git a/hid_darwin.c b/hid_darwin.c index 254dff5..b9da2f9 100644 --- a/hid_darwin.c +++ b/hid_darwin.c @@ -205,8 +205,34 @@ pRecDevice hid_get_device_by_number(t_int device_number) t_int get_device_number_by_id(unsigned short vendor_id, unsigned short product_id) { - // TODO: implement! (check usbhid.c) - return(-1); + debug_print(LOG_DEBUG,"get_device_number_from_usage_list"); + + pRecDevice pCurrentHIDDevice; + t_int i; + t_int return_device_number = -1; + + if( !HIDHaveDeviceList() ) hid_build_device_list(); + + pCurrentHIDDevice = HIDGetFirstDevice(); + i = HIDCountDevices(); + while(pCurrentHIDDevice != NULL) + { + --i; + debug_print(LOG_INFO,"compare 0x%04x == 0x%04x 0x%04x == 0x%04x", + pCurrentHIDDevice->vendorID, + vendor_id, + pCurrentHIDDevice->productID, + product_id); + if( (pCurrentHIDDevice->vendorID == vendor_id) && + (pCurrentHIDDevice->productID == product_id) ) + { + return_device_number = i; + pCurrentHIDDevice = NULL; + } + else + pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice); + } + return(return_device_number); } t_int get_device_number_from_usage_list(t_int device_number, @@ -216,15 +242,12 @@ t_int get_device_number_from_usage_list(t_int device_number, pRecDevice pCurrentHIDDevice; t_int i; - t_int device_count; + t_int return_device_number = -1; t_int total_devices = 0; char cstrDeviceName[MAXPDSTRING]; if( !HIDHaveDeviceList() ) hid_build_device_list(); - /* TODO: check that this function doesn't return a number that is higher - * than the highest device of this type */ - pCurrentHIDDevice = HIDGetFirstDevice(); while(pCurrentHIDDevice != NULL) { @@ -236,11 +259,11 @@ t_int get_device_number_from_usage_list(t_int device_number, pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice); } i = total_devices; - device_count = HIDCountDevices(); + return_device_number = HIDCountDevices(); pCurrentHIDDevice = HIDGetFirstDevice(); while( (pCurrentHIDDevice != NULL) && (i > device_number) ) { - device_count--; + return_device_number--; if( (pCurrentHIDDevice->usagePage == usage_page) && (pCurrentHIDDevice->usage == usage) ) { @@ -248,16 +271,17 @@ t_int get_device_number_from_usage_list(t_int device_number, HIDGetUsageName(pCurrentHIDDevice->usagePage, pCurrentHIDDevice->usage, cstrDeviceName); - debug_print(LOG_DEBUG,"[hid]: found a %s at %d: %s %s" + debug_print(LOG_DEBUG,"[hid]: found a %s at %d/%d: %s %s" ,cstrDeviceName, i, + total_devices, pCurrentHIDDevice->manufacturer, pCurrentHIDDevice->product); } pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice); } - if(device_count < total_devices) - return(device_count); + if(i < total_devices) + return(return_device_number); else return(-1); } @@ -389,29 +413,57 @@ void hid_print_device_list(t_hid *x) * STATUS/INFO OUTPUT * ============================================================================== */ -void hid_info(t_hid *x) +void hid_platform_specific_info(t_hid *x) { - t_atom output_atoms[4]; - - SETSYMBOL(output_atoms,gensym("open")); - SETFLOAT(output_atoms + 1, x->x_device_open); - outlet_anything( x->x_device_name_outlet, gensym( device_name ),0,NULL ); -} - + pRecDevice pCurrentHIDDevice = NULL; + char vendor_id_pointer[7]; + char product_id_pointer[7]; + t_symbol *output_symbol; + t_atom *output_atom = getbytes(sizeof(t_atom)); -void hid_output_device_name(t_hid *x, char *manufacturer, char *product) -{ - char *device_name; -// t_symbol *device_name_symbol; - - device_name = malloc( strlen(manufacturer) + 1 + strlen(product) + 1 ); -// device_name = malloc( 7 + strlen(manufacturer) + 1 + strlen(product) + 1 ); -// strcpy( device_name, "append " ); - strcat( device_name, manufacturer ); - strcat ( device_name, " "); - strcat( device_name, product ); -// outlet_anything( x->x_device_name_outlet, gensym( device_name ),0,NULL ); - outlet_symbol( x->x_device_name_outlet, gensym( device_name ) ); + if(x->x_device_number > -1) + { + pCurrentHIDDevice = hid_get_device_by_number(x->x_device_number); + if(pCurrentHIDDevice != NULL) + { + /* product */ + SETSYMBOL(output_atom, gensym(pCurrentHIDDevice->product)); + outlet_anything( x->x_status_outlet, gensym("product"), + 1, output_atom); + /* manufacturer */ + SETSYMBOL(output_atom, gensym(pCurrentHIDDevice->manufacturer)); + outlet_anything( x->x_status_outlet, gensym("manufacturer"), + 1, output_atom); + /* serial */ + if(pCurrentHIDDevice->serial != NULL) + { + output_symbol = gensym(pCurrentHIDDevice->serial); + if( output_symbol != &s_ ) + { /* the serial is rarely used on USB devices, so test for it */ + SETSYMBOL(output_atom, output_symbol); + outlet_anything( x->x_status_outlet, gensym("serial"), + 1, output_atom); + } + } + /* transport */ + SETSYMBOL(output_atom, gensym(pCurrentHIDDevice->transport)); + outlet_anything( x->x_status_outlet, gensym("transport"), + 1, output_atom); + /* vendor id */ + sprintf(vendor_id_pointer,"0x%04x", + (unsigned int)pCurrentHIDDevice->vendorID); + SETSYMBOL(output_atom, gensym(vendor_id_pointer)); + outlet_anything( x->x_status_outlet, gensym("vendorID"), + 1, output_atom); + /* product id */ + sprintf(product_id_pointer,"0x%04x", + (unsigned int)pCurrentHIDDevice->productID); + SETSYMBOL(output_atom, gensym(product_id_pointer)); + outlet_anything( x->x_status_outlet, gensym("productID"), + 1, output_atom); + } + } + freebytes(output_atom,sizeof(t_atom)); } /* ============================================================================== @@ -605,55 +657,55 @@ t_int hid_get_events(t_hid *x) */ case 0: sprintf(code,"abs_hat0y");value = 1; - hid_output_event(x,type,code,(t_float)value); + hid_output_event(x,gensym(type),gensym(code),(t_float)value); sprintf(code,"abs_hat0x");value = 0; break; case 1: sprintf(code,"abs_hat0y");value = 1; - hid_output_event(x,type,code,(t_float)value); + hid_output_event(x,gensym(type),gensym(code),(t_float)value); sprintf(code,"abs_hat0x");value = 1; break; case 2: sprintf(code,"abs_hat0y");value = 0; - hid_output_event(x,type,code,(t_float)value); + hid_output_event(x,gensym(type),gensym(code),(t_float)value); sprintf(code,"abs_hat0x");value = 1; break; case 3: sprintf(code,"abs_hat0y");value = -1; - hid_output_event(x,type,code,(t_float)value); + hid_output_event(x,gensym(type),gensym(code),(t_float)value); sprintf(code,"abs_hat0x");value = 1; break; case 4: sprintf(code,"abs_hat0y");value = -1; - hid_output_event(x,type,code,(t_float)value); + hid_output_event(x,gensym(type),gensym(code),(t_float)value); sprintf(code,"abs_hat0x");value = 0; break; case 5: sprintf(code,"abs_hat0y");value = -1; - hid_output_event(x,type,code,(t_float)value); + hid_output_event(x,gensym(type),gensym(code),(t_float)value); sprintf(code,"abs_hat0x");value = -1; break; case 6: sprintf(code,"abs_hat0y");value = 0; - hid_output_event(x,type,code,(t_float)value); + hid_output_event(x,gensym(type),gensym(code),(t_float)value); sprintf(code,"abs_hat0x");value = -1; break; case 7: sprintf(code,"abs_hat0y");value = 1; - hid_output_event(x,type,code,(t_float)value); + hid_output_event(x,gensym(type),gensym(code),(t_float)value); sprintf(code,"abs_hat0x");value = -1; break; case 8: sprintf(code,"abs_hat0y");value = 0; - hid_output_event(x,type,code,(t_float)value); + hid_output_event(x,gensym(type),gensym(code),(t_float)value); sprintf(code,"abs_hat0x");value = 0; break; } - hid_output_event(x,type,code,(t_float)value); + hid_output_event(x,gensym(type),gensym(code),(t_float)value); break; default: convertDarwinElementToLinuxTypeCode(pCurrentHIDElement,type,code); - hid_output_event(x,type,code,(t_float)value); + hid_output_event(x,gensym(type),gensym(code),(t_float)value); } // DEBUG(post("type: %s code: %s event name: %s",type,code,event_output_string);); @@ -722,13 +774,10 @@ t_int hid_open_device(t_hid *x, t_int device_number) } else { - debug_error(x,"[hid]: device %d is not a valid device\n",device_number); + debug_error(x,LOG_ERR,"[hid]: device %d is not a valid device\n",device_number); return(1); } - - hid_output_device_name( x, pCurrentHIDDevice->manufacturer, pCurrentHIDDevice->product ); - - post("[hid] opened device %d: %s %s", + debug_print(LOG_WARNING,"[hid] opened device %d: %s %s", device_number, pCurrentHIDDevice->manufacturer, pCurrentHIDDevice->product); //hid_build_element_list(x); diff --git a/hid_linux.c b/hid_linux.c index c6ea2f6..81d511c 100644 --- a/hid_linux.c +++ b/hid_linux.c @@ -389,7 +389,7 @@ t_int hid_get_events(t_hid *x) hid_code=gensym("unknown"); } if( hid_code && hid_input_event.type != EV_SYN ) - hid_output_event(x, ev[hid_input_event.type], hid_code->s_name, + hid_output_event(x, gensym(ev[hid_input_event.type]), hid_code, (t_float)hid_input_event.value); DEBUG(++event_counter;); } diff --git a/hid_windows.c b/hid_windows.c index 7bc387c..ffa1dc0 100755 --- a/hid_windows.c +++ b/hid_windows.c @@ -179,8 +179,8 @@ void hid_output_device_name(t_hid *x, char *manufacturer, char *product) strcat( device_name, manufacturer ); strcat ( device_name, " "); strcat( device_name, product ); -// outlet_anything( x->x_device_name_outlet, gensym( device_name ),0,NULL ); - outlet_symbol( x->x_device_name_outlet, gensym( device_name ) ); +// outlet_anything( x->x_status_outlet, gensym( device_name ),0,NULL ); + outlet_symbol( x->x_status_outlet, gensym( device_name ) ); } /* ------------------------------------------------------------------------------ */ -- cgit v1.2.1