Correctly set port index when opened by name on linux & OSX.

svn path=/trunk/externals/iem/comport/; revision=8991
This commit is contained in:
Martin Peach 2007-11-13 18:31:45 +00:00
parent d774d0fefc
commit 790cf21a9b

View file

@ -16,6 +16,7 @@ MP 20060925 add devices message to enumerate actual devices, info just outputs c
MP 20061016 write_serial checks for GetOverlappedResult to avoid tx buffer overflow errors MP 20061016 write_serial checks for GetOverlappedResult to avoid tx buffer overflow errors
MP 20070719 added "ports" method to output list of available ports on status outlet MP 20070719 added "ports" method to output list of available ports on status outlet
MP 20071011 added comport_list and write_serials for list processing based on code by Thomas O Fredericks <tof@danslchamp.org> MP 20071011 added comport_list and write_serials for list processing based on code by Thomas O Fredericks <tof@danslchamp.org>
MP 20071113 modified non-windows open_serial to set the index of the port when it's opened by name
*/ */
#include "m_pd.h" #include "m_pd.h"
@ -435,7 +436,7 @@ static HANDLE open_serial(unsigned int com_num, t_comport *x)
post("comport number %d out of range (1-%d)", com_num, COMPORT_MAX); post("comport number %d out of range (1-%d)", com_num, COMPORT_MAX);
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
sprintf(buffer, "%s%d", x->serial_device_prefix, com_num); sprintf(buffer, "%s%d", x->serial_device_prefix, com_num);
x->serial_device = gensym(buffer); x->serial_device = gensym(buffer);
} }
@ -528,7 +529,7 @@ static HANDLE open_serial(unsigned int com_num, t_comport *x)
x->comhandle = fd; x->comhandle = fd;
if (com_num == USE_DEVICENAME) if (com_num == USE_DEVICENAME)
{ {
/* extract index from device name */ /* extract index from device name */
for (i = 0; x->serial_device->s_name[i] != 0; ++i) for (i = 0; x->serial_device->s_name[i] != 0; ++i)
@ -565,10 +566,10 @@ static HANDLE open_serial(unsigned int com_num, t_comport *x)
post("Couldn't set timeouts for serial device (%d)", GetLastError()); post("Couldn't set timeouts for serial device (%d)", GetLastError());
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
if (!SetupComm(x->comhandle, 4096L, 4096L))/* try to get big buffers to avoid overruns*/ if (!SetupComm(x->comhandle, 4096L, 4096L))/* try to get big buffers to avoid overruns*/
{ {
post("[comport] Couldn't do SetupComm (%d)", GetLastError()); post("[comport] Couldn't do SetupComm (%d)", GetLastError());
} }
x->comport = com_num;/* output on next tick */ x->comport = com_num;/* output on next tick */
return fd; return fd;
} }
@ -599,7 +600,7 @@ static int write_serial(t_comport *x, unsigned char serial_byte)
DWORD dwWritten; DWORD dwWritten;
DWORD dwToWrite = 1L; DWORD dwToWrite = 1L;
DWORD dwErr; DWORD dwErr;
DWORD numTransferred = 0L; DWORD numTransferred = 0L;
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL) if (osWrite.hEvent == NULL)
@ -617,11 +618,11 @@ static int write_serial(t_comport *x, unsigned char serial_byte)
return 0; return 0;
} }
} }
if (!GetOverlappedResult(x->comhandle, &osWrite, &numTransferred, TRUE)) if (!GetOverlappedResult(x->comhandle, &osWrite, &numTransferred, TRUE))
{/* wait for the character to be sent */ {/* wait for the character to be sent */
dwErr = GetLastError(); dwErr = GetLastError();
post("WriteFile:GetOverlappedResult error: %d", (int)dwErr); post("WriteFile:GetOverlappedResult error: %d", (int)dwErr);
} }
CloseHandle(osWrite.hEvent); CloseHandle(osWrite.hEvent);
return 1; return 1;
} }
@ -632,7 +633,7 @@ static int write_serials(t_comport *x, unsigned char *serial_buf, size_t buf_len
DWORD dwWritten; DWORD dwWritten;
DWORD dwToWrite = (DWORD)buf_length; DWORD dwToWrite = (DWORD)buf_length;
DWORD dwErr; DWORD dwErr;
DWORD numTransferred = 0L; DWORD numTransferred = 0L;
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL) if (osWrite.hEvent == NULL)
@ -650,11 +651,11 @@ static int write_serials(t_comport *x, unsigned char *serial_buf, size_t buf_len
return 0; return 0;
} }
} }
if (!GetOverlappedResult(x->comhandle, &osWrite, &numTransferred, TRUE)) if (!GetOverlappedResult(x->comhandle, &osWrite, &numTransferred, TRUE))
{/* wait for the character(s) to be sent */ {/* wait for the character(s) to be sent */
dwErr = GetLastError(); dwErr = GetLastError();
post("WriteFile:GetOverlappedResult error: %d", (int)dwErr); post("WriteFile:GetOverlappedResult error: %d", (int)dwErr);
} }
CloseHandle(osWrite.hEvent); CloseHandle(osWrite.hEvent);
return 1; return 1;
} }
@ -708,9 +709,9 @@ static long get_baud_ratebits(t_float *baud)
while(i < BAUDRATETABLE_LEN && baudratetable[i] > *baud) i++; while(i < BAUDRATETABLE_LEN && baudratetable[i] > *baud) i++;
if(baudratetable[i] != *baud) if(baudratetable[i] != *baud)
post("[comport]: %d not valid, using closest value: ", *baud, baudratetable[i]); post("[comport]: %d not valid, using closest value: ", *baud, baudratetable[i]);
/* nearest Baudrate finding */ /* nearest Baudrate finding */
if(i==BAUDRATETABLE_LEN || baudspeedbittable[i] < 0) if(i==BAUDRATETABLE_LEN || baudspeedbittable[i] < 0)
{ {
@ -718,7 +719,7 @@ static long get_baud_ratebits(t_float *baud)
i = 8; i = 8;
} }
*baud = baudratetable[i]; *baud = baudratetable[i];
post("get_baud_ratebits: %f", *baud); post("get_baud_ratebits: %f", *baud);
return baudspeedbittable[i]; return baudspeedbittable[i];
} }
@ -726,12 +727,12 @@ static long get_baud_ratebits(t_float *baud)
static float set_baudrate(t_comport *x, t_float baud) static float set_baudrate(t_comport *x, t_float baud)
{ {
struct termios *tio = &(x->com_termio); struct termios *tio = &(x->com_termio);
speed_t baudbits = get_baud_ratebits(&baud); speed_t baudbits = get_baud_ratebits(&baud);
post("set_baudrate baudbits: %d", baudbits); post("set_baudrate baudbits: %d", baudbits);
if( cfsetispeed(tio, baudbits) != 0 ) if( cfsetispeed(tio, baudbits) != 0 )
post("[comport]: ERROR failed to set bitrate: %d", baudbits); post("[comport]: ERROR failed to set bitrate: %d", baudbits);
if( cfsetospeed(tio, baudbits) != 0 ) if( cfsetospeed(tio, baudbits) != 0 )
post("[comport]: ERROR failed to set bitrate: %d", baudbits); post("[comport]: ERROR failed to set bitrate: %d", baudbits);
return baud; return baud;
} }
@ -848,75 +849,83 @@ static int set_xonxoff(t_comport *x, int nr)
static int set_hupcl(t_comport *x, int nr) static int set_hupcl(t_comport *x, int nr)
{ {
struct termios settings; struct termios settings;
int result; int result;
result = tcgetattr(x->comhandle, &settings); result = tcgetattr(x->comhandle, &settings);
if (result < 0) if (result < 0)
{ {
perror ("error in tcgetattr"); perror ("error in tcgetattr");
return 0; return 0;
} }
settings.c_iflag &= ~HUPCL; settings.c_iflag &= ~HUPCL;
if(nr) if(nr)
settings.c_iflag |= HUPCL; settings.c_iflag |= HUPCL;
result = tcsetattr(x->comhandle, TCSANOW, &settings); result = tcsetattr(x->comhandle, TCSANOW, &settings);
if (result < 0) if (result < 0)
{ {
pd_error(x,"[comport] could not set HUPCL"); pd_error(x,"[comport] could not set HUPCL");
return 0; return 0;
} }
x->hupcl = nr; x->hupcl = nr;
return 1; return 1;
} }
static int open_serial(unsigned int com_num, t_comport *x) static int open_serial(unsigned int com_num, t_comport *x)
{ {
int fd; int fd;
struct termios *old = &(x->oldcom_termio); unsigned int i;
struct termios *new = &(x->com_termio); struct termios *old = &(x->oldcom_termio);
float *baud = &(x->baud); struct termios *new = &(x->com_termio);
glob_t glob_buffer; float *baud = &(x->baud);
glob_t glob_buffer;
/* if com_num == USE_DEVICENAME, use device name directly, else try port # */ /* if com_num == USE_DEVICENAME, use device name directly, else try port # */
if(com_num != USE_DEVICENAME) if((com_num != USE_DEVICENAME)&&(com_num >= COMPORT_MAX))
{ {
if(com_num >= COMPORT_MAX) post("[comport] ** WARNING ** port %d not valid, must be between 0 and %d",
{ com_num, COMPORT_MAX - 1);
post("[comport] ** WARNING ** port %d not valid, must be between 0 and %d", return INVALID_HANDLE_VALUE;
com_num, COMPORT_MAX - 1); }
return INVALID_HANDLE_VALUE; /* post("[comport] globbing %s",x->serial_device_prefix);*/
} /* get the device path based on the port# and the glob pattern */
/* post("[comport] globbing %s",x->serial_device_prefix);*/ switch( glob( x->serial_device_prefix, 0, NULL, &glob_buffer ) )
/* get the device path based on the port# and the glob pattern */ {
switch( glob( x->serial_device_prefix, 0, NULL, &glob_buffer ) ) case GLOB_NOSPACE:
{ error("[comport] out of memory for \"%s\"",x->serial_device_prefix);
case GLOB_NOSPACE: break;
error("[comport] out of memory for \"%s\"",x->serial_device_prefix);
break;
#ifdef GLOB_ABORTED #ifdef GLOB_ABORTED
case GLOB_ABORTED: case GLOB_ABORTED:
error("[comport] aborted \"%s\"",x->serial_device_prefix); error("[comport] aborted \"%s\"",x->serial_device_prefix);
break; break;
#endif #endif
#ifdef GLOB_NOMATCH #ifdef GLOB_NOMATCH
case GLOB_NOMATCH: case GLOB_NOMATCH:
error("[comport] no serial devices found for \"%s\"",x->serial_device_prefix); error("[comport] no serial devices found for \"%s\"",x->serial_device_prefix);
break; break;
#endif #endif
}
if(com_num < glob_buffer.gl_pathc)
{
x->serial_device = gensym(glob_buffer.gl_pathv[com_num]);
}
else
{
post("[comport] ** WARNING ** port #%d does not exist! (max == %d)",
com_num,glob_buffer.gl_pathc - 1);
return INVALID_HANDLE_VALUE;
}
globfree( &(glob_buffer) );
} }
if (com_num == USE_DEVICENAME)
{ /* if possible, find the index of the devicename */
for (i = 0; i < glob_buffer.gl_pathc; ++i)
{
if (0 == strcmp(x->serial_device->s_name, glob_buffer.gl_pathv[i]))
{
com_num = i;
break;
}
}
}
else if(com_num < glob_buffer.gl_pathc)
x->serial_device = gensym(glob_buffer.gl_pathv[com_num]);
else
{
post("[comport] ** WARNING ** port #%d does not exist! (max == %d)",
com_num,glob_buffer.gl_pathc - 1);
return INVALID_HANDLE_VALUE;
}
globfree( &(glob_buffer) );
if((fd = open(x->serial_device->s_name, OPENPARAMS)) == INVALID_HANDLE_VALUE) if((fd = open(x->serial_device->s_name, OPENPARAMS)) == INVALID_HANDLE_VALUE)
{ {
error("[comport] ** ERROR ** could not open device %s:\n failure(%d): %s\n", error("[comport] ** ERROR ** could not open device %s:\n failure(%d): %s\n",
@ -971,7 +980,7 @@ static int open_serial(unsigned int com_num, t_comport *x)
} }
else else
{ {
error("[comport] ** ERROR ** could not set params to ioctl of device %s\n", error("[comport] ** ERROR ** could not set params to ioctl of device %s\n",
x->serial_device->s_name); x->serial_device->s_name);
close(fd); close(fd);
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
@ -1064,9 +1073,9 @@ static void comport_pollintervall(t_comport *x, t_floatarg g)
static void comport_tick(t_comport *x) static void comport_tick(t_comport *x)
{ {
#ifdef _WIN32 #ifdef _WIN32
HANDLE fd = x->comhandle; HANDLE fd = x->comhandle;
#else #else
int fd = x->comhandle; int fd = x->comhandle;
#endif /* _WIN32 */ #endif /* _WIN32 */
int err; int err;
@ -1103,9 +1112,9 @@ static void comport_tick(t_comport *x)
} }
#else #else
{ {
unsigned char serial_byte; unsigned char serial_byte;
fd_set com_rfds; fd_set com_rfds;
int count = 0; int count = 0;
FD_ZERO(&com_rfds); FD_ZERO(&com_rfds);
FD_SET(fd,&com_rfds); FD_SET(fd,&com_rfds);
@ -1115,10 +1124,10 @@ static void comport_tick(t_comport *x)
err = read(fd,(char *) &serial_byte,1); err = read(fd,(char *) &serial_byte,1);
/* while( (err = read(fd,(char *) &serial_byte,1)) > 0){ */ /* while( (err = read(fd,(char *) &serial_byte,1)) > 0){ */
outlet_float(x->x_data_outlet, (t_float) serial_byte); outlet_float(x->x_data_outlet, (t_float) serial_byte);
++count; ++count;
} }
// if( count > 0) // if( count > 0)
// post("--- %d", count); // post("--- %d", count);
} }
#endif #endif
@ -1535,10 +1544,10 @@ static void comport_enum(t_comport *x)
#ifdef _WIN32 #ifdef _WIN32
HANDLE fd; HANDLE fd;
char device_name[10]; char device_name[10];
unsigned int i; unsigned int i;
DWORD dw; DWORD dw;
for(i = 1; i < COMPORT_MAX; i++) for(i = 1; i < COMPORT_MAX; i++)
{ {
sprintf(device_name, "%s%d", x->serial_device_prefix, i); sprintf(device_name, "%s%d", x->serial_device_prefix, i);
fd = CreateFile( device_name, fd = CreateFile( device_name,
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
@ -1731,19 +1740,19 @@ static void comport_output_hupcl(t_comport *x)
static void comport_output_open_status(t_comport *x) static void comport_output_open_status(t_comport *x)
{ {
if(x->comhandle == INVALID_HANDLE_VALUE) if(x->comhandle == INVALID_HANDLE_VALUE)
comport_output_status(x, gensym("open"), 0); comport_output_status(x, gensym("open"), 0);
else else
comport_output_status(x, gensym("open"), 1); comport_output_status(x, gensym("open"), 1);
} }
static void comport_devices(t_comport *x) static void comport_devices(t_comport *x)
{ {
comport_output_print(x); comport_output_print(x);
} }
static void comport_info(t_comport *x) static void comport_info(t_comport *x)
{ {
comport_output_open_status(x); comport_output_open_status(x);
comport_output_port_status(x); comport_output_port_status(x);
comport_output_baud_rate(x); comport_output_baud_rate(x);
comport_output_dsr_status(x); comport_output_dsr_status(x);