*** empty log message ***

svn path=/trunk/externals/iem/comport/; revision=5253
This commit is contained in:
Martin Peach 2006-06-18 19:20:48 +00:00
parent 44e9f1bc1a
commit 5b5d56d168

View file

@ -4,6 +4,8 @@
Institute for Electronic Music - Graz
V 1.0
MP 20060603 memset and memcpy arguments were backwards for Windows version. close_serial doesn't crash now.
MP 20060618 make sure name is set up in comport_new (x->serial_device = test.serial_device) so help message works.
*/
@ -35,11 +37,8 @@
typedef struct comport
{
t_object x_obj;
long n; /* the state of a last input */
HANDLE comhandle; /* holds the comport handle */
#ifdef _WIN32
DCB dcb; /* holds the comm pars */
DCB dcb_old; /* holds the comm pars */
@ -50,18 +49,13 @@ typedef struct comport
#endif
t_symbol *serial_device;
char serial_device_name[FILENAME_MAX];
short comport; /* holds the comport # */
t_float baud; /* holds the current baud rate */
short rxerrors; /* holds the rx line errors */
t_clock *x_clock;
int x_hit;
double x_deltime;
int verbose;
t_outlet *x_data_outlet;
t_outlet *x_status_outlet;
} t_comport;
@ -76,9 +70,8 @@ typedef struct comport
#define OFF 0
#endif
/*
Serial Port Return Values
*/
/* Serial Port Return Values */
#define NODATAAVAIL -1
#define RXERRORS -2
#define RXBUFOVERRUN -4
@ -87,8 +80,7 @@ typedef struct comport
#define COMPORT_MAX 99
#ifdef _WIN32
static
long baudspeedbittable[] =
static long baudspeedbittable[] =
{
CBR_256000,
CBR_128000,
@ -154,11 +146,9 @@ struct timeval null_tv;
#endif /* else _WIN32 */
#define BAUDRATETABLE_LEN 15
static
long baudratetable[] =
static long baudratetable[] =
{
256000L,
128000L,
@ -185,12 +175,12 @@ static long get_baud_ratebits(t_float *baud)
{
int i = 0;
while(i < BAUDRATETABLE_LEN && baudratetable[i] > *baud)
i++;
while(i < BAUDRATETABLE_LEN && baudratetable[i] > *baud) i++;
/* nearest Baudrate finding */
if(i==BAUDRATETABLE_LEN || baudspeedbittable[i] < 0){
post("*Warning* The baud rate %d is not suported or out of range, using 9600\n",*baud);
if(i==BAUDRATETABLE_LEN || baudspeedbittable[i] < 0)
{
post("*Warning* The baud rate %d is not supported or out of range, using 9600\n",*baud);
i = 7;
}
*baud = baudratetable[i];
@ -206,11 +196,9 @@ static long get_baud_ratebits(t_float *baud)
#ifdef _WIN32
static float set_baudrate(t_comport *x,t_float baud)
{
x->dcb.BaudRate = get_baud_ratebits(&baud);
return baud;
}
@ -218,9 +206,7 @@ static float set_baudrate(t_comport *x,t_float baud)
static float set_bits(t_comport *x, int nr)
{
if(nr < 4 && nr > 8)
nr = 8;
if(nr < 4 && nr > 8) nr = 8;
/* number of bits/byte, 4-8 */
return x->dcb.ByteSize = nr;
@ -230,17 +216,16 @@ static float set_bits(t_comport *x, int nr)
/* 1 ... Parity even, -1 parity odd , 0 (default) no parity */
static float set_parity(t_comport *x,int n)
{
switch(n){
switch(n)
{
case 1:
x->dcb.fParity = TRUE; /* enable parity checking */
x->dcb.Parity = 2; /* 0-4=no,odd,even,mark,space */
return 1;
case -1:
x->dcb.fParity = TRUE; /* enable parity checking */
x->dcb.Parity = 1; /* 0-4=no,odd,even,mark,space */
return -1;
default:
x->dcb.fParity = FALSE; /* enable parity checking */
x->dcb.Parity = 0; /* 0-4=no,odd,even,mark,space */
@ -249,23 +234,24 @@ static float set_parity(t_comport *x,int n)
}
/* aktivate second stop bit with 1, 0(default)*/
/* activate second stop bit with 1, 0(default)*/
static float set_stopflag(t_comport *x, int nr)
{
if(nr == 1){
if(nr == 1)
{
x->dcb.StopBits = 1; /* 0,1,2 = 1, 1.5, 2 */
return 1;
}
else
x->dcb.StopBits = 0; /* 0,1,2 = 1, 1.5, 2 */
else x->dcb.StopBits = 0; /* 0,1,2 = 1, 1.5, 2 */
return 0;
}
/* never testet */
/* never tested */
static int set_ctsrts(t_comport *x, int nr)
{
if(nr == 1){
if(nr == 1)
{
x->dcb.fOutxCtsFlow = TRUE; /* CTS output flow control */
x->dcb.fRtsControl = RTS_CONTROL_ENABLE; /* RTS flow control */
return 1;
@ -278,25 +264,20 @@ static int set_ctsrts(t_comport *x, int nr)
static int set_xonxoff(t_comport *x, int nr)
{
/* x->dcb.fTXContinueOnXoff = FALSE; XOFF continues Tx */
if(nr == 1){
if(nr == 1)
{
x->dcb.fOutX = TRUE; /* XON/XOFF out flow control */
x->dcb.fInX = TRUE; /* XON/XOFF in flow control */
return 1;
}
x->dcb.fOutX = FALSE; /* XON/XOFF out flow control */
x->dcb.fInX = FALSE; /* XON/XOFF in flow control */
return 0;
}
static int set_serial(t_comport *x)
{
if (SetCommState(x->comhandle, &(x->dcb)))
return 1;
if (SetCommState(x->comhandle, &(x->dcb))) return 1;
return 0;
}
@ -306,8 +287,10 @@ static HANDLE open_serial(unsigned int com_num, t_comport *x)
COMMTIMEOUTS timeouts;
char buffer[MAX_PATH];
float *baud = &(x->baud);
DWORD dw;
if(com_num < 1 || com_num >= COMPORT_MAX) {
if(com_num < 1 || com_num >= COMPORT_MAX)
{
post("comport open %d, baud %d not valid (args: [portnum] [baud])",com_num,*baud);
return INVALID_HANDLE_VALUE;
}
@ -325,24 +308,26 @@ static HANDLE open_serial(unsigned int com_num, t_comport *x)
if(fd == INVALID_HANDLE_VALUE)
{
post("** ERROR ** could not open device %s:\n failure(%d): %s\n",
x->serial_device->s_name,errno,strerror(errno));
dw = GetLastError();
post("** ERROR ** could not open device %s:\n failure(%d)\n",
x->serial_device->s_name,dw);
return INVALID_HANDLE_VALUE;
}
/* Save the Current Port Configuration */
if (!GetCommState(fd, &(x->dcb_old))){
if (!GetCommState(fd, &(x->dcb_old)))
{
post("** ERROR ** could not get old dcb of device %s\n",
x->serial_device->s_name);
CloseHandle(fd);
return INVALID_HANDLE_VALUE;
}
memset(&(x->dcb), sizeof(DCB), 0);
memset(&(x->dcb), 0, sizeof(DCB));
if (!GetCommState(fd, &(x->dcb))){
if (!GetCommState(fd, &(x->dcb)))
{
post("** ERROR ** could not get new dcb of device %s\n",
x->serial_device->s_name);
@ -350,7 +335,6 @@ static HANDLE open_serial(unsigned int com_num, t_comport *x)
return INVALID_HANDLE_VALUE;
}
x->dcb.fBinary = TRUE; /* binary mode, no EOF check */
/* x->dcb.fOutxDsrFlow = FALSE; DSR output flow control */
@ -369,11 +353,11 @@ static HANDLE open_serial(unsigned int com_num, t_comport *x)
/* char x->dcb.EofChar; end of input character */
/* char x->dcb.EvtChar; received event character */
set_bits(x,8); /* CS8 */
set_stopflag(x,0); /* ~CSTOPB */
set_ctsrts(x,0); /* ~CRTSCTS;*/
set_xonxoff(x,0); /* (IXON | IXOFF | IXANY) */
set_baudrate(x,*baud);
set_bits(x, 8); /* CS8 */
set_stopflag(x, 0); /* ~CSTOPB */
set_ctsrts(x, 0); /* ~CRTSCTS;*/
set_xonxoff(x, 0); /* (IXON | IXOFF | IXANY) */
set_baudrate(x, *baud);
x->comhandle = fd;
@ -390,50 +374,49 @@ static HANDLE open_serial(unsigned int com_num, t_comport *x)
return INVALID_HANDLE_VALUE;
}
if (!GetCommTimeouts(fd, &(x->old_timeouts))){
if (!GetCommTimeouts(fd, &(x->old_timeouts)))
{
post("[comport] Couldn't get old timeouts for serial device");
};
}
/* setting new timeouts for read to immidiatly return */
/* setting new timeouts for read to immediately return */
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(fd, &timeouts)){
if (!SetCommTimeouts(fd, &timeouts))
{
post("Couldnt set timeouts for serial device");
return INVALID_HANDLE_VALUE;
};
}
// this causes a segfault... WHY?!?
// outlet_float(x->x_status_outlet, (t_float)com_num);
// this causes a segfault... WHY?!?
// outlet_float(x->x_status_outlet, (t_float)com_num);
return fd;
}
static HANDLE close_serial(t_comport *x)
{
if(x->comhandle != INVALID_HANDLE_VALUE){
if (!SetCommState(x->comhandle, &(x->dcb_old)) )
if(x->comhandle != INVALID_HANDLE_VALUE)
{
if (!SetCommState(x->comhandle, &(x->dcb_old)))
{
post("[comport] ** ERROR ** could not reset params to DCB of device %s\n",
x->serial_device->s_name);
}
if (!SetCommTimeouts(x->comhandle, &(x->old_timeouts))){
post("[comport] Couldnt reset old_timeouts for serial device");
};
if (!SetCommTimeouts(x->comhandle, &(x->old_timeouts)))
{
post("[comport] Couldn't reset old_timeouts for serial device");
}
CloseHandle(x->comhandle);
// for some reason, this causes a segfault...
// post("[comport] closed %s",x->serial_device->s_name);
}
// this causes a segfault... WHY?!?
// outlet_float(x->x_status_outlet, 0);
return INVALID_HANDLE_VALUE;
}
@ -453,7 +436,6 @@ static int write_serial(t_comport *x, unsigned char serial_byte)
return 0;
}
if (!WriteFile(x->comhandle, &serial_byte, dwToWrite, &dwWritten, &osWrite))
{
dwErr = GetLastError();
@ -475,7 +457,6 @@ static int write_serial(t_comport *x, unsigned char serial_byte)
static float set_baudrate(t_comport *x,t_float baud)
{
struct termios *tio = &(x->com_termio);
long baudbits = get_baud_ratebits(&baud);
cfsetispeed(tio, baudbits);
@ -490,7 +471,8 @@ static float set_bits(t_comport *x, int nr)
{
struct termios *tio = &(x->com_termio);
tio->c_cflag &= ~CSIZE;
switch(nr){
switch(nr)
{
case 5: tio->c_cflag |= CS5; return 5;
case 6: tio->c_cflag |= CS6; return 6;
case 7: tio->c_cflag |= CS7; return 7;
@ -505,7 +487,8 @@ static float set_parity(t_comport *x,int n)
{
struct termios *tio = &(x->com_termio);
switch(n){
switch(n)
{
case 1:
tio->c_cflag |= PARENB; tio->c_cflag &= ~PARODD; return 1;
case -1:
@ -517,26 +500,28 @@ static float set_parity(t_comport *x,int n)
}
/* aktivate second stop bit with 1, 0(default)*/
/* activate second stop bit with 1, 0(default)*/
static float set_stopflag(t_comport *x, int nr)
{
struct termios *tio = &(x->com_termio);
if(nr == 1){
if(nr == 1)
{
tio->c_cflag |= CSTOPB;
return 1;
}
else
tio->c_cflag &= ~CSTOPB;
else tio->c_cflag &= ~CSTOPB;
return 0;
}
/* never testet */
/* never tested */
static int set_ctsrts(t_comport *x, int nr)
{
struct termios *tio = &(x->com_termio);
if(nr == 1){
if(nr == 1)
{
tio->c_cflag |= CRTSCTS;
return 1;
}
@ -548,7 +533,8 @@ static int set_xonxoff(t_comport *x, int nr)
{
struct termios *tio = &(x->com_termio);
if(nr == 1){
if(nr == 1)
{
tio->c_iflag |= (IXON | IXOFF | IXANY);
return 1;
}
@ -611,17 +597,16 @@ static int open_serial(unsigned int com_num, t_comport *x)
fcntl(fd, F_SETFL, FNDELAY);
/* Save the Current Port Configuration */
if(tcgetattr(fd, old) == -1 || tcgetattr(fd, new) == -1){
if(tcgetattr(fd, old) == -1 || tcgetattr(fd, new) == -1)
{
error("[comport] ** ERROR ** could not get termios-structure of device %s\n",
x->serial_device->s_name);
close(fd);
return INVALID_HANDLE_VALUE;
}
/* Setupt the new port configuration...NON-CANONICAL INPUT MODE
.. as defined in termios.h
*/
/* Setup the new port configuration...NON-CANONICAL INPUT MODE
.. as defined in termios.h */
/* enable input and ignore modem controls */
new->c_cflag |= (CREAD | CLOCAL);
@ -662,17 +647,16 @@ static int open_serial(unsigned int com_num, t_comport *x)
close(fd);
return INVALID_HANDLE_VALUE;
}
return fd;
}
static int close_serial(t_comport *x)
{
struct termios *tios = &(x->com_termio);
HANDLE fd = x->comhandle;
if(fd != INVALID_HANDLE_VALUE){
if(fd != INVALID_HANDLE_VALUE)
{
tcsetattr(fd, TCSANOW, tios);
close(fd);
// for some reason, this causes a segfault...
@ -683,7 +667,6 @@ static int close_serial(t_comport *x)
return INVALID_HANDLE_VALUE;
}
static int set_serial(t_comport *x)
{
if(tcsetattr(x->comhandle, TCSAFLUSH, &(x->com_termio)) == -1)
@ -693,21 +676,19 @@ static int set_serial(t_comport *x)
static int write_serial(t_comport *x, unsigned char serial_byte)
{
return write(x->comhandle,(char *) &serial_byte,1);
/* flush pending I/O chars */
/* but nowadays discards them ;-(
else{
/* but nowadays discards them ;-(
else
{
ioctl(x->comhandle,TCFLSH,TCOFLUSH);
}
*/
*/
}
#endif /* else NT */
/* ------------------- serial pd methods --------------------------- */
static void comport_pollintervall(t_comport *x, t_floatarg g)
{
@ -722,7 +703,6 @@ static void comport_tick(t_comport *x)
x->x_hit = 0;
if(fd == INVALID_HANDLE_VALUE) return;
/* while there are bytes, read them and send them out, ignore errors */
@ -756,26 +736,25 @@ static void comport_tick(t_comport *x)
{
unsigned char serial_byte;
fd_set com_rfds;
FD_ZERO(&com_rfds);
FD_SET(fd,&com_rfds);
while((err=select(fd+1,&com_rfds,NULL,NULL,&null_tv)) > 0) {
while((err=select(fd+1,&com_rfds,NULL,NULL,&null_tv)) > 0)
{
err = read(fd,(char *) &serial_byte,1);
/* while( (err = read(fd,(char *) &serial_byte,1)) > 0){ */
outlet_float(x->x_data_outlet, (t_float) serial_byte);
};
}
}
#endif
if(err < 0){ /* if an readerror detected */
if(err < 0)
{ /* if a read error detected */
if(x->rxerrors == 0) /* post it once */
post("RXERRORS on serial line\n");
x->rxerrors = 1; /* remember */
}
if (!x->x_hit) clock_delay(x->x_clock, 1);
}
@ -821,17 +800,20 @@ static void *comport_new(t_floatarg com_num, t_floatarg fbaud)
x->comport = (short)com_num;
strncpy(x->serial_device_name,serial_device_name,strlen(serial_device_name)+1);
x->serial_device = test.serial_device; /* MP: we need this so 'help' doesn't crash */
x->baud = test.baud;
x->comhandle = fd; /* holds the comport handle */
if(fd == INVALID_HANDLE_VALUE ){
if(fd == INVALID_HANDLE_VALUE )
{
/* postings in open routine */
post("[comport] invalid handle for %s",x->serial_device_name);
}
else {
else
{
#ifdef _WIN32
memcpy(&(test.dcb_old),&(x->dcb_old),sizeof(DCB)); /* save the old com config */
memcpy(&(test.dcb),&(x->dcb),sizeof(DCB)); /* for the new com config */
memcpy(&(x->dcb_old), &(test.dcb_old), sizeof(DCB)); /* save the old com config */
memcpy(&(x->dcb), &(test.dcb), sizeof(DCB)); /* for the new com config */
#else
/* save the old com and new com config */
bcopy(&(test.oldcom_termio),&(x->oldcom_termio),sizeof(struct termios));
@ -857,11 +839,9 @@ static void *comport_new(t_floatarg com_num, t_floatarg fbaud)
}
static void
comport_free(t_comport *x)
static void comport_free(t_comport *x)
{
post("free serial...");
clock_unset(x->x_clock);
clock_free(x->x_clock);
x->comhandle = close_serial(x);
@ -871,7 +851,8 @@ comport_free(t_comport *x)
static void comport_baud(t_comport *x,t_floatarg f)
{
if(f == x->baud){
if(f == x->baud)
{
post("baudrate already %f\n",x->baud);
return;
}
@ -880,11 +861,13 @@ static void comport_baud(t_comport *x,t_floatarg f)
if(x->comhandle == INVALID_HANDLE_VALUE)return;
if(set_serial(x) == 0){
if(set_serial(x) == 0)
{
error("[comport] ** ERROR ** could not set baudrate of device %s\n",
x->serial_device->s_name);
}
else post("set baudrate of %s to %f\n",x->serial_device->s_name,x->baud);
else if(x->verbose > 0)
post("set baudrate of %s to %f\n",x->serial_device->s_name,x->baud);
}
static void comport_bits(t_comport *x,t_floatarg f)
@ -893,11 +876,13 @@ static void comport_bits(t_comport *x,t_floatarg f)
if(x->comhandle == INVALID_HANDLE_VALUE)return;
if(set_serial(x) == 0){
if(set_serial(x) == 0)
{
error("[comport] ** ERROR ** could not set bits of device %s\n",
x->serial_device->s_name);
}
else post("set bits of %s to %f\n",x->serial_device->s_name,f);
else if(x->verbose > 0)
post("set bits of %s to %f\n",x->serial_device->s_name,f);
}
@ -907,11 +892,13 @@ static void comport_parity(t_comport *x,t_floatarg f)
if(x->comhandle == INVALID_HANDLE_VALUE)return;
if(set_serial(x) == 0){
if(set_serial(x) == 0)
{
error("[comport] ** ERROR ** could not set extra paritybit of device %s\n",
x->serial_device->s_name);
}
else post("[comport] set extra paritybit of %s to %f\n",x->serial_device->s_name,f);
else if(x->verbose > 0)
post("[comport] set extra paritybit of %s to %f\n",x->serial_device->s_name,f);
}
static void comport_stopbit(t_comport *x,t_floatarg f)
@ -920,11 +907,13 @@ static void comport_stopbit(t_comport *x,t_floatarg f)
if(x->comhandle == INVALID_HANDLE_VALUE)return;
if(set_serial(x) == 0){
if(set_serial(x) == 0)
{
error("[comport] ** ERROR ** could not set extra stopbit of device %s\n",
x->serial_device->s_name);
}
else post("[comport] set extra stopbit of %s to %f\n",x->serial_device->s_name,f);
else if(x->verbose > 0)
post("[comport] set extra stopbit of %s to %f\n",x->serial_device->s_name,f);
}
static void comport_rtscts(t_comport *x,t_floatarg f)
@ -933,11 +922,13 @@ static void comport_rtscts(t_comport *x,t_floatarg f)
if(x->comhandle == INVALID_HANDLE_VALUE)return;
if(set_serial(x) == 0){
if(set_serial(x) == 0)
{
error("[comport] ** ERROR ** could not set rts_cts of device %s\n",
x->serial_device->s_name);
}
else post("[comport] set rts-cts of %s to %f\n",x->serial_device->s_name,f);
else if(x->verbose > 0)
post("[comport] set rts-cts of %s to %f\n",x->serial_device->s_name,f);
}
static void comport_xonxoff(t_comport *x,t_floatarg f)
@ -946,7 +937,8 @@ static void comport_xonxoff(t_comport *x,t_floatarg f)
if(x->comhandle == INVALID_HANDLE_VALUE)return;
if(set_serial(x) == 0){
if(set_serial(x) == 0)
{
error("[comport] ** ERROR ** could not set xonxoff of device %s\n",
x->serial_device->s_name);
}
@ -987,12 +979,15 @@ static void comport_print(t_comport *x, t_symbol *s, int argc, t_atom *argv)
static char buf[256];
char *pch = buf;
while(argc--) {
while(argc--)
{
atom_string(argv++, buf, 255);
while(*pch != 0) {
while(*pch != 0)
{
write_serial(x, *pch++);
}
if(argc > 0) {
if(argc > 0)
{
write_serial(x, ' ');
}
}
@ -1001,15 +996,14 @@ static void comport_print(t_comport *x, t_symbol *s, int argc, t_atom *argv)
static void comport_verbose(t_comport *x, t_floatarg f)
{
x->verbose = f;
if(f > 0)
post("[comport] verbose is on: %d", (int) f);
if(f > 0) post("[comport] verbose is on: %d", (int) f);
}
static void comport_help(t_comport *x)
{
post("[comport] serial port %d (baud %f):",x->comport,x->baud);
if(x->comport >= 0 && x->comport < COMPORT_MAX){
post("[comport] serial port %d (baud %f):", x->comport, x->baud);
if(x->comport >= 0 && x->comport < COMPORT_MAX)
{
post("\tdevicename: %s",x->serial_device->s_name);
}
@ -1024,17 +1018,18 @@ static void comport_help(t_comport *x)
" open <num> ... open device number num\n"
" devicename <d> ... set device name to s (eg. /dev/ttyS8)\n"
" print <list> ... print list of atoms on serial\n"
" pollintervall <t> ... set poll ibntervall to t ticks\n"
" pollintervall <t> ... set poll interval to t ticks\n"
" verbose <level> ... for debug set verbosity to level\n"
" help ... post this help");
}
/* ---------------- SETUP OBJECTS ------------------ */
#ifdef _WIN32
__declspec(dllexport)
#endif
void comport_setup(void)
{
comport_class
= class_new(gensym("comport"), (t_newmethod)comport_new,
comport_class = class_new(gensym("comport"), (t_newmethod)comport_new,
(t_method)comport_free, sizeof(t_comport),
0, A_DEFFLOAT, A_DEFFLOAT, 0);
@ -1055,7 +1050,6 @@ void comport_setup(void)
class_addmethod(comport_class, (t_method)comport_devicename, gensym("devicename"), A_SYMBOL, 0);
class_addmethod(comport_class, (t_method)comport_print, gensym("print"), A_GIMME, 0);
class_addmethod(comport_class, (t_method)comport_pollintervall, gensym("pollintervall"), A_FLOAT, 0);
class_addmethod(comport_class, (t_method)comport_verbose, gensym("verbose"), A_FLOAT, 0);
class_addmethod(comport_class, (t_method)comport_help, gensym("help"), 0);