From fc3d3c0a4f110a23335398c327ac0a4fc949d5cb Mon Sep 17 00:00:00 2001 From: Guenter Geiger Date: Mon, 17 Jun 2002 10:13:57 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r12, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/ggee/; revision=13 --- control/serialctl.c | 463 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100755 control/serialctl.c (limited to 'control/serialctl.c') diff --git a/control/serialctl.c b/control/serialctl.c new file mode 100755 index 0000000..4a80bbb --- /dev/null +++ b/control/serialctl.c @@ -0,0 +1,463 @@ +/* (C) Guenter Geiger */ + + +#include +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#include +#include +#include +#include +#include +#include +#include + + +#ifndef __linux__ +#define CRTSCTS 0 +#endif + +#define DEBUG(x) +/*#define DEBUG(x) x*/ + + +#define SETBIT(yy,ww,xx) \ +if (!strcmp(yy->s_name,#xx)) \ + valid=1,ww |= ##xx;\ +if (!strcmp(yy->s_name,"~"#xx))\ + valid=1,ww &= ~##xx;\ +if (!strcmp(yy->s_name,"list"))\ + valid=1,post(#xx); + + +/* ------------------------ serialctl ----------------------------- */ + +static t_class *serialctl_class; + + +typedef struct _serialctl +{ + t_object x_obj; + t_int x_fd; + t_symbol* x_devname; + int read_ok; + int started; + int numbytes; + struct termios x_termios; + struct termios x_oldtermios; +} t_serialctl; + + + +static int serialctl_close(t_serialctl *x) +{ + if (x->x_fd <0) return 0; + + close(x->x_fd); + return 1; +} + +static int serialctl_open(t_serialctl *x,t_symbol* s) +{ + serialctl_close(x); + + if (s != &s_) + x->x_devname = s; + + if (x->x_devname) { + post("opening ..."); + x->x_fd = open(x->x_devname->s_name,O_RDWR | O_NOCTTY); + if (x->x_fd >= 0 ) post("done"); + else post("failed"); + } + else { + return 1; + } + + if (x->x_fd >= 0) + post("%s opened",x->x_devname->s_name); + else { + post("unable to open %s",x->x_devname->s_name); + x->x_fd = -1; + return 0; + } + + return 1; +} + + + +static int serialctl_read(t_serialctl *x,int fd) +{ + unsigned char c; + if (x->x_fd < 0) return 0; + if (x->read_ok) { + DEBUG(post("reading %d",x->numbytes);) + if (read(x->x_fd,&c,1) < 0) { + post("serialctl: read failed"); + x->read_ok = 0; + return 0; + } + x->numbytes++; + } + outlet_float(x->x_obj.ob_outlet,(float)c); + + return 1; + +} + + +/* + * Configuration Options + */ + +static void serialctl_setlines(t_serialctl *x,t_symbol* s,t_floatarg f) +{ + int lines; + + ioctl(x->x_fd,TIOCMGET,&lines); + if (!strcmp(s->s_name,"RTS")) { + if (f) + lines |= TIOCM_RTS; + else + lines &= ~TIOCM_RTS; + } + if (!strcmp(s->s_name,"DTR")) { + if (f) + lines |= TIOCM_DTR; + else + lines &= ~TIOCM_DTR; + } + + + + ioctl(x->x_fd,TIOCMSET,&lines); + +} + + +static void serialctl_getlines(t_serialctl *x) +{ + int lines; + /* check hardware signals */ + + ioctl(x->x_fd,TIOCMGET,&lines); + post("serialctl: CD %s",lines&TIOCM_CD ? "on":"off"); + post("serialctl: DTR %s",lines&TIOCM_DTR ? "on":"off"); + post("serialctl: DSR %s",lines&TIOCM_DSR ? "on":"off"); + post("serialctl: RTS %s",lines&TIOCM_RTS ? "on":"off"); + post("serialctl: CTS %s",lines&TIOCM_CTS ? "on":"off"); + +} + + +static void serialctl_setlocal(t_serialctl *x,t_symbol* s,t_int ac, t_atom* at) +{ + int valid =0; + int i; + + + for (i=0;i< ac;i++) { + valid = 0; + + if (at[i].a_type == A_FLOAT) { + x->x_termios.c_lflag = (int)atom_getfloat(at+i); + DEBUG(post("localflags set to %d",(int)atom_getfloat(at+i));) + valid = 1; + } + + if (at[i].a_type == A_SYMBOL) { + DEBUG(post("symbol %s",atom_getsymbolarg(i,ac,at)->s_name);) + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_lflag, ISIG); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_lflag, ICANON); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_lflag, ECHO); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_lflag, ECHOE); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_lflag, ECHOK); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_lflag, ECHONL); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_lflag, NOFLSH); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_lflag, TOSTOP); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_lflag, IEXTEN); + + if (!valid) post("serialctl: invalide flag %s",atom_getsymbolarg(i,ac,at)->s_name); + } + } + + if (x->x_fd < 0) return; + + if (tcsetattr(x->x_fd, TCSANOW,&x->x_termios) < 0) + post("serialctl: set attributes failed"); + +} + +static void serialctl_setcontrol(t_serialctl *x,t_symbol* s,t_int ac,t_atom* at) +{ + int valid =0; + int i; + + + for (i=0;i< ac;i++) { + valid = 0; + + if (at[i].a_type == A_FLOAT) { + x->x_termios.c_cflag = (int) atom_getfloat(at+i); + DEBUG(post("controlflags set to %d",(int)atom_getfloat(at+i))); + valid = 1; + } + + if (at[i].a_type == A_SYMBOL) { + DEBUG(post("symbol %s",atom_getsymbolarg(i,ac,at)->s_name);) + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_cflag,PARENB); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_cflag,PARODD); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_cflag,CS5); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_cflag,CS6); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_cflag,CS7); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_cflag,CS8); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_cflag,CLOCAL); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_cflag,CREAD); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_cflag,CSTOPB); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_cflag,CRTSCTS); + if (!valid) post("serialctl: invalide flag %s",atom_getsymbolarg(i,ac,at)->s_name); + } + } + + if (x->x_fd < 0) return; + + + if (tcsetattr(x->x_fd, TCSANOW,&x->x_termios) < 0) + post("serialctl: set attributes failed"); + +} + + +static void serialctl_setinput(t_serialctl *x,t_symbol* s,t_int ac,t_atom* at) +{ + int valid =0; + int i; + + + for (i=0;i< ac;i++) { + valid = 0; + + if (at[i].a_type == A_FLOAT) { + x->x_termios.c_iflag = (int)atom_getfloat(at+i); + DEBUG(post("inputflags set to %d",(int)atom_getfloat(at+i))); + valid = 1; + } + + if (at[i].a_type == A_SYMBOL) { + DEBUG(post("symbol %s",atom_getsymbolarg(i,ac,at)->s_name);) + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, IGNBRK); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, BRKINT); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, IGNPAR); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, PARMRK); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, INPCK); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, ISTRIP); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, INLCR); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, IGNCR); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, ICRNL); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, IUCLC); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, IXON); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, IXANY); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, IXOFF); + SETBIT(atom_getsymbolarg(i,ac,at),x->x_termios.c_iflag, IMAXBEL); + + if (!valid) post("serialctl: invalide flag %s",atom_getsymbolarg(i,ac,at)->s_name); + } + } + + if (x->x_fd < 0) return; + + + if (tcsetattr(x->x_fd, TCSANOW,&x->x_termios) < 0) + post("serialctl: set attributes failed"); + +} + +static void serialctl_makeraw(t_serialctl *x,t_floatarg f) +{ + cfmakeraw(&x->x_termios); + if (tcsetattr(x->x_fd, TCSANOW,&x->x_termios) < 0) + post("serialctl: set attributes failed"); +} + + +static void serialctl_vmintime(t_serialctl *x,t_floatarg f,t_floatarg ft) +{ + + post("vmin = %f, vtime = %f",f,ft); + x->x_termios.c_cc[VMIN] = (int) f; + x->x_termios.c_cc[VTIME] = (int) ft; + if (tcsetattr(x->x_fd, TCSANOW,&x->x_termios) < 0) + post("serialctl: set attributes failed"); + +} + + +static void serialctl_canonical(t_serialctl *x,t_floatarg f) +{ + post("setting canonical"); + x->x_termios.c_iflag |= IGNBRK | IGNPAR; + x->x_termios.c_cflag |= CS8 | CREAD | PARENB| CLOCAL | CRTSCTS; + x->x_termios.c_lflag = 0; +} + + +static void serialctl_speed(t_serialctl *x,t_floatarg f) +{ + + int speed = f; + post("setting speed %f",f); + + cfsetospeed (&x->x_termios,speed); + cfsetispeed (&x->x_termios,speed); + if (x->x_fd < 0) return; + + if (tcsetattr(x->x_fd, TCSANOW,&x->x_termios) < 0) + post("serialctl: set attributes failed"); +} + + +/* Actions */ +static void serialctl_bang(t_serialctl* x) +{ + +} + +static void serialctl_float(t_serialctl* x,t_float f) +{ + int ret = -1; + unsigned char c = (unsigned char) f; + DEBUG(post("serialctl: sending %d",c)); + if (f < 256.) { + ret = write(x->x_fd,&c,1); + DEBUG(post("done")); + if (ret != 1) + post("serialctl: send %f %s",f,((ret < 0) ? strerror(ret) : "ok")); + ioctl(x->x_fd,TCFLSH,TCIOFLUSH); + return; + } + post("unable to send char < 256"); + +} + +static void serialctl_send(t_serialctl* x,t_symbol* s) +{ + int ret; + if (s == &s_) return; + ret = write(x->x_fd,s->s_name,sizeof(s->s_name)); + post("serialctl: send %s %s",s->s_name,((ret < 0) ? "not ok" : "ok")); +} + + + + +void serialctl_start(t_serialctl* x) +{ + if (x->x_fd >= 0 && !x->started) { + sys_addpollfn(x->x_fd, (t_fdpollfn)serialctl_read, x); + post("serialctl: start"); + x->started = 1; + } +} + + +void serialctl_stop(t_serialctl* x) +{ + if (x->x_fd >= 0 && x->started) { + sys_rmpollfn(x->x_fd); + post("serialctl: stop"); + x->started = 0; + } +} + + +/* Misc setup functions */ + + +static void serialctl_free(t_serialctl* x) +{ + if (x->x_fd < 0) return; + + serialctl_stop(x); + + if (tcsetattr(x->x_fd, TCSANOW,&x->x_oldtermios) < 0) + post("serialctl: set attributes failed"); + + + close(x->x_fd); +} + + + +static void *serialctl_new(t_symbol *s) +{ + t_serialctl *x = (t_serialctl *)pd_new(serialctl_class); + + x->x_fd = -1; + x->read_ok = 1; + x->numbytes = 0; + x->started = 0; + outlet_new(&x->x_obj, &s_float); + if (s != &s_) + x->x_devname = s; + + /* Open the device and save settings */ + + if (!serialctl_open(x,s)) return x; + + if (tcgetattr(x->x_fd,&x->x_oldtermios) < 0) + post("serialctl: get attributes failed"); + + if (tcgetattr(x->x_fd,&x->x_termios) < 0) + post("serialctl: get attributes failed"); + + + tcflush(x->x_fd, TCIOFLUSH); + return (x); +} + + +void serialctl_setup(void) +{ + serialctl_class = class_new(gensym("serialctl"), (t_newmethod)serialctl_new, + (t_method)serialctl_free, + sizeof(t_serialctl), 0,A_DEFSYM,0); + + class_addmethod(serialctl_class,(t_method) serialctl_start,gensym("start"),0); + class_addmethod(serialctl_class,(t_method) serialctl_stop,gensym("stop"),0); + class_addmethod(serialctl_class, (t_method) serialctl_open,gensym("open"),A_DEFSYM); + class_addmethod(serialctl_class,(t_method) serialctl_close,gensym("close"),0); + + /* used to configure the device via symbols or with bytes */ + + class_addmethod(serialctl_class, (t_method) serialctl_send, gensym("send"), A_DEFSYM,A_NULL); + + + class_addfloat(serialctl_class,(t_method) serialctl_float); + + class_addmethod(serialctl_class,(t_method) serialctl_getlines,gensym("getlines"),0); + class_addmethod(serialctl_class,(t_method) serialctl_setlines,gensym("setlines"),A_DEFSYM,A_DEFFLOAT,NULL); + + + + /* general controlling */ + + class_addmethod(serialctl_class,(t_method) serialctl_setcontrol,gensym("setcontrol"),A_GIMME,NULL); + class_addmethod(serialctl_class,(t_method) serialctl_setlocal,gensym("setlocal"),A_GIMME,NULL); + class_addmethod(serialctl_class,(t_method) serialctl_setinput,gensym("setinput"),A_GIMME,NULL); + + + /* specifics */ + + class_addmethod(serialctl_class,(t_method) serialctl_canonical,gensym("canonical"),A_DEFFLOAT); + class_addmethod(serialctl_class,(t_method) serialctl_speed,gensym("speed"),A_DEFFLOAT); + class_addmethod(serialctl_class,(t_method) serialctl_makeraw,gensym("makeraw"),0); + class_addmethod(serialctl_class,(t_method) serialctl_vmintime,gensym("vtime"),A_DEFFLOAT,A_DEFFLOAT,NULL); + +} + + + -- cgit v1.2.1