Hi, i tried to compile the uDMX ( http://www.anyma.ch/research/udmx/ ) external on winxp. which worked after some trial and error. but now my question is: can somebody tell me by looking an the source why it crashes pd if i send a float message to the right inlet (there is no device connected - so maybe it wont crash if there is, but i'm curious how to figure out the reason) i started pd with -d (different numbers) and there was no output related to the crash (which debug level is the best for this case?) best g.
/* udmx.c pd-Interface to the [ a n y m a | udmx - Open Source USB Sensor Box ] Authors: Michael Egger Copyright: 2007 [ a n y m a ] Website: www.anyma.ch License: GNU GPL 2.0 www.gnu.org Version: 0.1 2007-01-28 */
#include "m_pd.h"
#include "uDMX_cmds.h" #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h> #include "usb.h" /* this is libusb, see http://libusb.sourceforge.net/ */
#define USBDEV_SHARED_VENDOR 0x16C0 /* VOTI */ #define USBDEV_SHARED_PRODUCT 0x05DC /* Obdev's free shared PID */
typedef struct _uDMX // defines our object's internal variables for each instance in a patch { t_object p_ob; // object header - ALL objects MUST begin with this... usb_dev_handle *dev_handle; // handle to the uDMX usb device int debug_flag; int channel; // int value - received from the right inlet and stored internally for each object instance } t_uDMX;
void *uDMX_class; // global pointer to the object class - so max can reference the object
// these are prototypes for the methods that are defined below void uDMX_int(t_uDMX *x, long n); void uDMX_debug(t_uDMX *x, t_symbol *s, short ac, t_atom *av); void uDMX_list(t_uDMX *x, t_symbol *s, short ac, t_atom *av); void uDMX_open(t_uDMX *x); void uDMX_close(t_uDMX *x); void *uDMX_new(long n); static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid, char *buf, int buflen); void find_device(t_uDMX *x);
//--------------------------------------------------------------------------
void uDMX_setup(void) {
uDMX_class = class_new ( gensym("uDMX"),(t_newmethod)uDMX_new, 0, sizeof(t_uDMX), CLASS_DEFAULT,0); class_addfloat(uDMX_class, (t_method)uDMX_int); // the method for an int in the left inlet (inlet 0) class_addmethod(uDMX_class, (t_method)uDMX_debug,gensym("debug"), A_GIMME, 0); class_addlist(uDMX_class, (t_method)uDMX_list); class_addmethod(uDMX_class, (t_method)uDMX_open, gensym("open"), 0); class_addmethod(uDMX_class, (t_method)uDMX_close, gensym("close"), 0);
post("uDMX version 0.9 - (c) 2006 [ a n y m a ]",0); // post any important info to the max window when our object is laoded } //--------------------------------------------------------------------------
void uDMX_int(t_uDMX *x, long n) // x = the instance of the object; n = the int received in the left inlet { unsigned char buffer[8]; int nBytes;
if (n > 255) n=255; if (n < 0) n=0; if (x->channel > 512) x->channel=512; if (x->channel < 0) x->channel=0; if (!(x->dev_handle)) find_device(x); else { nBytes = usb_control_msg(x->dev_handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, cmd_SetSingleChannel, n, x->channel, buffer, sizeof(buffer), 5000); if(nBytes < 0) if (x->debug_flag) error("uDMX: USB error: %s", usb_strerror()); } }
//--------------------------------------------------------------------------
void uDMX_list(t_uDMX *x, t_symbol *s, short ac, t_atom *av) { int i; unsigned char* buf = malloc(ac); int nBytes;
if (x->channel > 512) x->channel=512; if (x->channel < 0) x->channel=0;
if (!(x->dev_handle)) find_device(x); else {
if (x->debug_flag) post("uDMX: ac: %i\n", ac); for(i=0; i<ac; ++i,av++) { if (av->a_type==A_FLOAT) buf[i] = MIN(MAX(av->a_w.w_float, 0), 255); else buf[i] = 0; } nBytes = usb_control_msg(x->dev_handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, cmd_SetChannelRange, ac, x->channel, buf, ac, 5000); if (x->debug_flag) post( "bytes returned: %i\n", nBytes); if(nBytes < 0) if (x->debug_flag) error("uDMX: USB error: %s\n", usb_strerror()); else if(nBytes > 0) if (x->debug_flag) post("uDMX: returned: %i\n", (int)(buf[0])); free(buf); } }
//--------------------------------------------------------------------------
void uDMX_debug(t_uDMX *x, t_symbol *s, short ac, t_atom *av) // x = the instance of the object; n = the int received in the left inlet { x->debug_flag = 1; if (ac) { if (av->a_type==A_FLOAT) x->debug_flag = av->a_w.w_float; } }
//--------------------------------------------------------------------------
void uDMX_free(t_uDMX *x) { if (x->dev_handle) usb_close(x->dev_handle); }
//--------------------------------------------------------------------------
void uDMX_open(t_uDMX *x) { if (x->dev_handle) { post("uDMX: There is already a connection to www.anyma.ch/uDMX",0); } else find_device(x); }
//--------------------------------------------------------------------------
void uDMX_close(t_uDMX *x) { if (x->dev_handle) { usb_close(x->dev_handle); x->dev_handle = NULL; post("uDMX: Closed connection to www.anyma.ch/uDMX",0); } else post("uDMX: There was no open connection to www.anyma.ch/uDMX",0); }
//--------------------------------------------------------------------------
void *uDMX_new(long n) // n = int argument typed into object box (A_DEFLONG) -- defaults to 0 if no args are typed { t_uDMX *x; // local variable (pointer to a t_uDMX data structure)
x = (t_uDMX *)pd_new(uDMX_class); // create a new instance of this object // create a second int inlet (leftmost inlet is automatic - all objects have one inlet by default) floatinlet_new((t_object *)x, (t_float *)x->channel); //assigns float in inlet 2 directly to channel
x->channel = 0; x->debug_flag = 0; x->dev_handle = NULL; find_device(x);
return(x); // return a reference to the object instance }
//--------------------------------------------------------------------------
static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid, char *buf, int buflen) { char buffer[256]; int rval, i;
if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, langid, buffer, sizeof(buffer), 1000)) < 0) return rval; if(buffer[1] != USB_DT_STRING) return 0; if((unsigned char)buffer[0] < rval) rval = (unsigned char)buffer[0]; rval /= 2; /* lossy conversion to ISO Latin1 */ for(i=1;i<rval;i++){ if(i > buflen) /* destination buffer overflow */ break; buf[i-1] = buffer[2 * i]; if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */ buf[i-1] = '?'; } buf[i-1] = 0; return i-1; }
//--------------------------------------------------------------------------
void find_device(t_uDMX *x) { usb_dev_handle *handle = NULL; struct usb_bus *bus; struct usb_device *dev;
usb_init(); usb_find_busses(); usb_find_devices(); for(bus=usb_get_busses(); bus; bus=bus->next){ for(dev=bus->devices; dev; dev=dev->next){ if(dev->descriptor.idVendor == USBDEV_SHARED_VENDOR && dev->descriptor.idProduct == USBDEV_SHARED_PRODUCT){ char string[256]; int len; handle = usb_open(dev); /* we need to open the device in order to query strings */ if(!handle){ error ("Warning: cannot open USB device: %s", usb_strerror()); continue; } /* now find out whether the device actually is uDMX */ len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, 0x0409, string, sizeof(string)); if(len < 0){ post("uDMX: warning: cannot query manufacturer for device: %s", usb_strerror()); goto skipDevice; }
// post("uDMX: seen device from vendor ->%s<-", string); if(strcmp(string, "www.anyma.ch") != 0) goto skipDevice; len = usbGetStringAscii(handle, dev->descriptor.iProduct, 0x0409, string, sizeof(string)); if(len < 0){ post("uDMX: warning: cannot query product for device: %s", usb_strerror()); goto skipDevice; } // post("uDMX: seen product ->%s<-", string); if(strcmp(string, "uDMX") == 0) break; skipDevice: usb_close(handle); handle = NULL; } } if(handle) break; } if(!handle){ post("uDMX: Could not find USB device www.anyma.ch/uDMX"); x->dev_handle = NULL; } else { x->dev_handle = handle; post("uDMX: Found USB device www.anyma.ch/uDMX"); } }