Skip to content

Commit

Permalink
Add (optional) libftdi support for all serial devices
Browse files Browse the repository at this point in the history
This adds support for addressing all serial port type devices
(with FTDI-based hardware) using the "ftdi:" prefix, in some different formats.
This makes owfs use libftdi instead of a regular /dev/ttyUSBxx device to
access the device. The functionality should be the same, but decreases
communication latency greatly.
  • Loading branch information
stromnet committed Jan 25, 2016
1 parent 9a8aa0c commit 2982df8
Show file tree
Hide file tree
Showing 20 changed files with 935 additions and 42 deletions.
111 changes: 110 additions & 1 deletion configure.ac
Expand Up @@ -1272,6 +1272,103 @@ AC_SUBST(ENABLE_PARPORT)
AM_CONDITIONAL(ENABLE_PARPORT, test "${ENABLE_PARPORT}" = "true")


dnl We support both libftdi 1.x and libftdi 0.x
if test "$cross_compiling" != yes; then
AC_CHECK_PROGS(LIBFTDI_CONFIG, libftdi1-config libftdi-config)
else
LIBFTDI_CONFIG=""
fi
AC_SUBST(LIBFTDI_CONFIG)

AC_ARG_WITH(libftdi-config,
[ --with-libftdi-config=PATH Specify full path to libftdi-config or libftdi1-config])
dnl Check if user passed a specific libftdi-config program.
if test "X$with_libftdi_config" != "X" ; then
LIBFTDI_CONFIG=$with_libftdi_config
fi

if test "$cross_compiling" != yes; then
if test "X$LIBFTDI_CONFIG" == "X" ; then
dirs="/usr/bin /usr/local/bin /opt/local/bin"
for i in $dirs; do
for prog in libftdi1-config libftdi-config; do
echo "Testing $i/$prog"
if test -x $i/$prog; then
AC_MSG_RESULT($i/$prog is found)
LIBFTDI_CONFIG="$i/$prog"
break 2;
fi
done
done
fi
fi

# Check if FTDI should be enabled
ENABLE_FTDI=auto
AC_MSG_CHECKING([if libftdi is available])

AC_ARG_ENABLE(ftdi,
[ --enable-ftdi Enable LinkUSB support via libftdi (default auto)],
[
AC_MSG_RESULT([$enableval])
if ! test "$enableval" = "yes" ; then
ENABLE_FTDI=false
fi
],
[
AC_MSG_RESULT([auto (default)])
])

# Include ftdi.h if enabled
if test "${ENABLE_FTDI}" != "false" ; then

LIBFTDI_FOUND=false
if test "X${LIBFTDI_CONFIG}" != "X" ; then
LIBFTDI_CFLAGS=`$LIBFTDI_CONFIG --cflags`
LIBFTDI_LIBS=`$LIBFTDI_CONFIG --libs`

save_CPPFLAGS="$CPPFLAGS"
save_LDFLAGS="$LDFLAGS"
CPPFLAGS="$save_CPPFLAGS $LIBFTDI_CFLAGS"
LDFLAGS="$save_LDFLAGS $LIBFTDI_LIBS"

AC_MSG_CHECKING([if libftdi compiles with includes+lib ])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[#include <ftdi.h>]],
[[
struct ftdi_context ftdic;
ftdi_init(&ftdic);
]])],
[AC_MSG_RESULT([ok])
FTDI_FOUND=true
],
[AC_MSG_RESULT([compilation error])
LIBFTDI_CFLAGS=""
LIBFTDI_LDFLAGS=""
LIBFTDI_CONFIG=""
])

CPPFLAGS="$save_CPPFLAGS"
LDFLAGS="$save_LDFLAGS"
fi

if test "${FTDI_FOUND}" = "true"; then
ENABLE_FTDI=true
else
if test "${ENABLE_FTDI}" = "true" ; then
AC_MSG_ERROR([libftdi must be installed to use LinkUSB natively])
else
AC_MSG_WARN([libftdi not found, LinkUSB native will be disabled])
ENABLE_FTDI=false
fi
fi
fi
AC_SUBST(LIBFTDI_CFLAGS)
AC_SUBST(LIBFTDI_LIBS)
AC_SUBST(ENABLE_FTDI)
AM_CONDITIONAL(ENABLE_FTDI, test "${ENABLE_FTDI}" = "true")

if test "${HAVE_CYGWIN}" = "true" ; then
OW_CYGWIN=1
else
Expand Down Expand Up @@ -1489,6 +1586,13 @@ else
fi
AC_SUBST(OW_PARPORT)

if test "${ENABLE_FTDI}" = "true" ; then
OW_FTDI=1
else
OW_FTDI=0
fi
AC_SUBST(OW_FTDI)

if test "${ENABLE_DEBUG}" = "true" ; then
OW_DEBUG=1
else
Expand Down Expand Up @@ -1529,7 +1633,7 @@ AC_FUNC_SELECT_ARGTYPES
AC_FUNC_STRFTIME
AC_FUNC_STRTOD
AC_TYPE_SIGNAL
AC_CHECK_FUNCS([accept daemon getaddrinfo freeaddrinfo gethostbyname2_r gethostbyaddr_r gethostbyname_r getservbyname_r getopt getopt_long gettimeofday inet_ntop inet_pton memchr memset select socket strcasecmp strchr strdup strncasecmp strtol strtoul twalk tsearch tfind tdelete tdestroy vasprintf strsep vsprintf vsnprintf writev getline])
AC_CHECK_FUNCS([accept daemon getaddrinfo freeaddrinfo gethostbyname2_r gethostbyaddr_r gethostbyname_r getservbyname_r getopt getopt_long gmtime_r gettimeofday localtime_r inet_ntop inet_pton memchr memset select socket strcasecmp strchr strdup strncasecmp strtol strtoul twalk tsearch tfind tdelete tdestroy vasprintf strsep vsprintf vsnprintf writev getline])

if test "${ENABLE_ZERO}" = "true" ; then
AC_SEARCH_LIBS(dlopen, dl, AC_DEFINE(HAVE_DLOPEN, 1, [Define if you have dlopen]))
Expand Down Expand Up @@ -1687,6 +1791,11 @@ if test "${ENABLE_PARPORT}" = "true"; then
else
AC_MSG_RESULT([ Parallel port DS1410E is DISABLED])
fi
if test "${ENABLE_FTDI}" = "true"; then
AC_MSG_RESULT([ FTDI (LinkUSB) is enabled])
else
AC_MSG_RESULT([ FTDI (LinkUSB) is DISABLED])
fi
if test "${ENABLE_ZERO}" = "true"; then
AC_MSG_RESULT([ Zeroconf/Bonjour is enabled])
else
Expand Down
4 changes: 3 additions & 1 deletion module/owlib/src/c/Makefile.am
Expand Up @@ -109,6 +109,7 @@ OWLIB_SOURCE = ow_dl.c \
ow_fakeread.c \
ow_filelength.c \
ow_fstat.c \
ow_ftdi.c \
ow_generic_read.c \
ow_get.c \
ow_help.c \
Expand Down Expand Up @@ -224,7 +225,7 @@ libow_la_SOURCES = ${OWLIB_SOURCE}
if HAVE_CYGWIN
libow_la_LDFLAGS = ${PTHREAD_LIBS} -shared -no-undefined ${LIBUSB_LIBS} ${LIBAVAHI_LIBS} ${LD_EXTRALIBS}
else
libow_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -release $(LT_RELEASE) ${PTHREAD_LIBS} -shared -shrext .so ${LIBUSB_LIBS} ${LIBAVAHI_LIBS} ${LD_EXTRALIBS}
libow_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -release $(LT_RELEASE) ${PTHREAD_LIBS} -shared -shrext .so ${LIBUSB_LIBS} ${LIBFTDI_LIBS} ${LIBAVAHI_LIBS} ${LD_EXTRALIBS}
endif

# Maybe need this for MacOS X
Expand Down Expand Up @@ -252,6 +253,7 @@ AM_CFLAGS = -I../include \
${EXTRACFLAGS} \
${PTHREAD_CFLAGS} \
${LIBUSB_CFLAGS} \
${LIBFTDI_CFLAGS} \
${PIC_FLAGS}


Expand Down
21 changes: 19 additions & 2 deletions module/owlib/src/c/ow_arg.c
Expand Up @@ -18,25 +18,32 @@
#include "ow_connection.h"
#include "ow_usb_msg.h" // for DS9490_port_setup

enum arg_address { arg_addr_device, arg_addr_null, arg_addr_ip, arg_addr_colon, arg_addr_number, arg_addr_other, arg_addr_error, } ;
enum arg_address { arg_addr_device, arg_addr_null,
arg_addr_ip, arg_addr_colon,
arg_addr_number, arg_addr_ftdi,
arg_addr_other, arg_addr_error, } ;

static enum arg_address ArgType( const char * arg )
{
static regex_t rx_dev ;
static regex_t rx_num ;
static regex_t rx_ip ;
static regex_t rx_ftdi ;
static regex_t rx_col ;

// compile regex expressions
ow_regcomp( &rx_dev, "/", REG_NOSUB ) ;
ow_regcomp( &rx_num, "^[:digit:]+$", REG_NOSUB ) ;
ow_regcomp( &rx_ip, "[:digit:]{1,3}\\.[:digit:]{1,3}\\.[:digit:]{1,3}\\.[:digit:]{1,3}", REG_NOSUB ) ;
ow_regcomp( &rx_ftdi, "^ftdi:", REG_NOSUB ) ;
ow_regcomp( &rx_col, ":", REG_NOSUB ) ;

if ( arg == NULL ) {
return arg_addr_null ;
} else if ( ow_regexec( &rx_ip, arg, NULL ) == 0 ) {
return arg_addr_ip ;
} else if ( ow_regexec( &rx_ftdi, arg, NULL ) == 0 ) {
return arg_addr_ftdi;
} else if ( ow_regexec( &rx_col, arg, NULL ) == 0 ) {
return arg_addr_colon ;
} else if ( ow_regexec( &rx_dev, arg, NULL ) == 0 ) {
Expand All @@ -62,6 +69,7 @@ static void arg_data( const char * arg, struct port_in * pin )
// Test whether address is a serial port, or a serial over telnet (ser2net)
static GOOD_OR_BAD Serial_or_telnet( const char * arg, struct connection_in * in )
{
LEVEL_DEBUG("arg %s is %d", arg, ArgType(arg));
switch( ArgType(arg) ) {
case arg_addr_null:
case arg_addr_error:
Expand All @@ -70,6 +78,14 @@ static GOOD_OR_BAD Serial_or_telnet( const char * arg, struct connection_in * in
case arg_addr_device:
in->pown->type = ct_serial ; // serial port
break ;
case arg_addr_ftdi:
#if OW_FTDI
in->pown->type = ct_ftdi;
break;
#else
LEVEL_DEFAULT("FTDI support not included in compilation. Use generic serial device.");
return gbBAD;
#endif
case arg_addr_number: // port
case arg_addr_colon:
case arg_addr_ip:
Expand All @@ -87,7 +103,8 @@ GOOD_OR_BAD ARG_Device(const char *arg)
switch( ArgType(arg) ) {
case arg_addr_number: // port
case arg_addr_colon:
case arg_addr_ip:
case arg_addr_ip:
case arg_addr_ftdi:
case arg_addr_other:
return ARG_Serial(arg) ;
default:
Expand Down
12 changes: 12 additions & 0 deletions module/owlib/src/c/ow_com.c
Expand Up @@ -12,6 +12,7 @@
#include "owfs_config.h"
#include "ow.h"
#include "ow_connection.h"
#include "ow_ftdi.h"

#ifdef HAVE_LINUX_LIMITS_H
#include <linux/limits.h>
Expand All @@ -38,6 +39,7 @@ GOOD_OR_BAD COM_test( struct connection_in * connection )
LEVEL_DEBUG("Unimplemented!!!");
return gbBAD ;
case ct_serial:
case ct_ftdi:
break ;
}

Expand Down Expand Up @@ -72,6 +74,11 @@ void COM_flush( const struct connection_in *connection)
return ;
case ct_serial:
tcflush( connection->pown->file_descriptor, TCIOFLUSH);
return;
case ct_ftdi:
#if OW_FTDI
owftdi_flush(connection);
#endif
break ;
}
}
Expand Down Expand Up @@ -103,6 +110,11 @@ void COM_break(struct connection_in *in)
return ;
case ct_serial:
tcsendbreak(in->pown->file_descriptor, 0);
return;
case ct_ftdi:
#if OW_FTDI
owftdi_break(in);
#endif
break ;
}
}
5 changes: 5 additions & 0 deletions module/owlib/src/c/ow_com_change.c
Expand Up @@ -47,6 +47,10 @@ GOOD_OR_BAD COM_change( struct connection_in *connection)
return gbGOOD ;
case ct_serial:
return serial_change( connection ) ;
case ct_ftdi:
#if OW_FTDI
return owftdi_change( connection ) ;
#endif
case ct_unknown:
case ct_none:
default:
Expand Down Expand Up @@ -77,6 +81,7 @@ void COM_set_standard( struct connection_in *connection)
break ;

case ct_serial:
case ct_ftdi:
default:
pin->timeout.tv_sec = Globals.timeout_serial ;
pin->timeout.tv_usec = 0 ;
Expand Down
6 changes: 6 additions & 0 deletions module/owlib/src/c/ow_com_close.c
Expand Up @@ -13,6 +13,7 @@
#include "owfs_config.h"
#include "ow.h"
#include "ow_connection.h"
#include "ow_ftdi.h"

#ifdef HAVE_LINUX_LIMITS_H
#include <linux/limits.h>
Expand Down Expand Up @@ -43,6 +44,11 @@ void COM_close(struct connection_in *connection)
return ;
case ct_serial:
break ;
case ct_ftdi:
#if OW_FTDI
return owftdi_close(connection);
#endif
break;
}

switch ( pin->state ) {
Expand Down
6 changes: 6 additions & 0 deletions module/owlib/src/c/ow_com_free.c
Expand Up @@ -13,6 +13,7 @@
#include "owfs_config.h"
#include "ow.h"
#include "ow_connection.h"
#include "ow_ftdi.h"

#ifdef HAVE_LINUX_LIMITS_H
#include <linux/limits.h>
Expand Down Expand Up @@ -44,6 +45,11 @@ void COM_free(struct connection_in *connection)
case ct_serial:
serial_free( connection ) ;
break ;
case ct_ftdi:
#if OW_FTDI
owftdi_free( connection ) ;
#endif
break ;
}

connection->pown->state = cs_virgin ;
Expand Down
5 changes: 5 additions & 0 deletions module/owlib/src/c/ow_com_open.c
Expand Up @@ -13,6 +13,7 @@
#include "ow.h"
#include "ow_connection.h"
#include "ow_w1.h"
#include "ow_ftdi.h"

#ifdef HAVE_LINUX_LIMITS_H
#include <linux/limits.h>
Expand Down Expand Up @@ -64,6 +65,10 @@ GOOD_OR_BAD COM_open(struct connection_in *connection)
return gbBAD ;
case ct_serial:
return serial_open( head_in ) ;
case ct_ftdi:
#if OW_FTDI
return owftdi_open( head_in ) ;
#endif /* OW_FTDI */
case ct_unknown:
case ct_none:
default:
Expand Down
7 changes: 7 additions & 0 deletions module/owlib/src/c/ow_com_read.c
Expand Up @@ -71,6 +71,13 @@ GOOD_OR_BAD COM_read( BYTE * data, size_t length, struct connection_in *connecti
}
break ;
}
case ct_ftdi:
{
#if OW_FTDI
size_t actual = owftdi_read(data, length, connection);
return actual == (ssize_t) length ? gbGOOD : gbBAD ;
#endif
}
}
return gbBAD ;
}
Expand Down

0 comments on commit 2982df8

Please sign in to comment.