aboutsummaryrefslogtreecommitdiff
path: root/uDMX/uDMX.c
diff options
context:
space:
mode:
Diffstat (limited to 'uDMX/uDMX.c')
-rwxr-xr-xuDMX/uDMX.c275
1 files changed, 275 insertions, 0 deletions
diff --git a/uDMX/uDMX.c b/uDMX/uDMX.c
new file mode 100755
index 0000000..eadc53c
--- /dev/null
+++ b/uDMX/uDMX.c
@@ -0,0 +1,275 @@
+/*
+ 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.2 2009-06-30
+ 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_setchannel(t_uDMX *x, t_floatarg f);
+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 dex, 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);
+ class_addmethod(uDMX_class, (t_method)uDMX_setchannel, gensym("setchannel"), A_FLOAT, 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_setchannel(t_uDMX *x, t_floatarg f)
+{
+ x->channel = f;
+}
+
+//--------------------------------------------------------------------------
+
+void uDMX_list(t_uDMX *x, t_symbol *s, short ac, t_atom *av)
+{
+ int i;
+ unsigned char* buf = malloc(ac);
+ int nBytes;
+ int n;
+
+ 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) {
+ n = (int) av->a_w.w_float;
+ if (n > 255) n=255;
+ if (n < 0) n=0;
+
+ buf[i] = n;
+ } 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(x, x->channel); //crashes on PD .... assigns float in inlet 2 directly to channel
+ inlet_new(&x->p_ob, &x->p_ob.ob_pd, gensym("float"), gensym("setchannel"));
+
+ 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 dex, 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) + dex, 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");
+ }
+}