#include <errno.h>
#include "ftd2xx.h"
+#define PACKAGE_VERSION "1.0.0"
+
typedef FT_STATUS (WINAPI FT_CloseProc)(FT_HANDLE);
typedef FT_STATUS (WINAPI FT_CreateDeviceInfoListProc)(LPDWORD);
typedef FT_STATUS (WINAPI FT_GetDeviceInfoListProc)
typedef FT_STATUS (WINAPI FT_WriteProc)(FT_HANDLE,LPVOID,DWORD,LPDWORD);
typedef FT_STATUS (WINAPI FT_GetLibraryVersionProc)(LPDWORD);
typedef FT_STATUS (WINAPI FT_RescanProc)(VOID);
+typedef FT_STATUS (WINAPI FT_SetBaudRateProc)(FT_HANDLE,ULONG);
+typedef FT_STATUS (WINAPI FT_SetDataCharacteristicsProc)
+ (FT_HANDLE,UCHAR,UCHAR,UCHAR);
+typedef FT_STATUS (WINAPI FT_SetFlowControlProc)(FT_HANDLE,USHORT,UCHAR,UCHAR);
typedef struct FTDIPROCS {
FT_CloseProc *FT_Close;
FT_WriteProc *FT_Write;
FT_GetLibraryVersionProc *FT_GetLibraryVersion;
FT_RescanProc *FT_Rescan;
+ FT_SetBaudRateProc *FT_SetBaudRate;
+ FT_SetDataCharacteristicsProc *FT_SetDataCharacteristics;
+ FT_SetFlowControlProc *FT_SetFlowControl;
} FTDIPROCS;
static FTDIPROCS procs;
int flags;
int watchmask;
int validmask;
+ int baudrate;
+ unsigned char parity;
+ unsigned short handshake;
+ char xonchar;
+ char xoffchar;
+ unsigned char databits;
+ unsigned char stopbits;
unsigned long rxtimeout;
unsigned long txtimeout;
FT_HANDLE handle;
}
}
} else if (!strcmp("-latency", optionName)) {
- int tmp = 1;
- r = Tcl_GetInt(interp, newValue, &tmp);
- if (r == TCL_OK) {
- fts = procs.FT_SetLatencyTimer(instPtr->handle, (UCHAR)tmp);
- }
+ int tmp = 1;
+ r = Tcl_GetInt(interp, newValue, &tmp);
+ if (r == TCL_OK) {
+ fts = procs.FT_SetLatencyTimer(instPtr->handle, (UCHAR)tmp);
+ }
+ } else if (!strcmp("-mode", optionName)) {
+ int baudrate, databits, stopbits;
+ char parity;
+ int args;
+
+ if ((args = sscanf(newValue, "%d,%c,%d,%d", &baudrate, &parity, &databits, &stopbits)) != 4) {
+ Tcl_AppendResult(interp, "error setting mode: ", NULL);
+ return TCL_ERROR;
+ }
+
+ switch (databits) {
+ case 8: databits = FT_BITS_8; break;
+ case 7: databits = FT_BITS_7; break;
+ case 6: databits = FT_BITS_6; break;
+ case 5: databits = FT_BITS_5; break;
+ default:
+ Tcl_AppendResult(interp, "error setting mode: databit count not supported", NULL);
+ return TCL_ERROR;
+ }
+
+ switch (stopbits) {
+ case 1: stopbits = FT_STOP_BITS_1; break;
+ case 2: stopbits = FT_STOP_BITS_2; break;
+ default:
+ Tcl_AppendResult(interp, "error setting mode: stopbit count not supported", NULL);
+ return TCL_ERROR;
+ }
+
+ switch (parity) {
+ case 'n': parity = FT_PARITY_NONE; break;
+ case 'o': parity = FT_PARITY_ODD; break;
+ case 'e': parity = FT_PARITY_EVEN; break;
+ case 'm': parity = FT_PARITY_MARK; break;
+ case 's': parity = FT_PARITY_SPACE; break;
+ default:
+ Tcl_AppendResult(interp, "error setting mode: parity not supported", NULL);
+ return TCL_ERROR;
+ }
+
+ if ((fts = procs.FT_SetBaudRate(instPtr->handle, baudrate)) != FT_OK) {
+ Tcl_AppendResult(interp, "failed set baudrate: \"",
+ ConvertError(fts), NULL);
+ return TCL_ERROR;
+ }
+
+ if ((fts = procs.FT_SetDataCharacteristics(instPtr->handle, databits, stopbits, parity)) != FT_OK) {
+ Tcl_AppendResult(interp, "failed set data characteristics: \"",
+ ConvertError(fts), NULL);
+ return TCL_ERROR;
+ }
+
+ instPtr->baudrate = baudrate;
+ instPtr->databits = databits;
+ instPtr->stopbits = stopbits;
+ instPtr->parity = parity;
+ } else if (!strcmp("-handshake", optionName)) {
+ unsigned short handshake = 0xFFFF;
+ if (!strcmp(newValue,"none")) {
+ handshake = FT_FLOW_NONE;
+ } else if (!strcmp(newValue,"rtscts")) {
+ handshake = FT_FLOW_RTS_CTS;
+ } else if (!strcmp(newValue,"dtrdsr")) {
+ handshake = FT_FLOW_DTR_DSR;
+ } else if (!strcmp(newValue,"xonxoff")) {
+ handshake = FT_FLOW_XON_XOFF;
+ } else {
+ Tcl_AppendResult(interp, "error setting handshake: handshake not supported", NULL);
+ return TCL_ERROR;
+ }
+ if ((fts = procs.FT_SetFlowControl(instPtr->handle, handshake, instPtr->xonchar, instPtr->xoffchar)) == FT_OK)
+ instPtr->handshake = handshake;
+ } else if (!strcmp("-xchar", optionName)) {
+ if (strlen(newValue) != 3) {
+ Tcl_AppendResult(interp, "error setting xon/xoff characters: values < 1 and > 127 not supported", NULL);
+ return TCL_ERROR;
+ }
+
+ if ((fts = procs.FT_SetFlowControl(instPtr->handle, FT_FLOW_NONE, newValue[0], newValue[2])) == FT_OK) {
+ instPtr->xonchar = newValue[0];
+ instPtr->xoffchar = newValue[2];
+ }
}
if (fts != FT_OK) {
r = TCL_ERROR;
}
- return TCL_OK;
+ return r;
}
/**
const char *optionName, Tcl_DString *optionValue)
{
Channel *instPtr = instance;
- const char *options[] = {"readtimeout", "writetimeout", "latency", NULL};
+ const char *options[] = {"readtimeout", "writetimeout", "latency", "mode", "handshake", "xchar", NULL};
int r = TCL_OK;
if (optionName == NULL) {
ConvertError(fts), NULL);
r = TCL_ERROR;
}
+ } else if (!strcmp("-mode", optionName)) {
+ char parity = 0;
+ switch (instPtr->parity) {
+ case FT_PARITY_NONE: parity = 'n'; break;
+ case FT_PARITY_ODD: parity = 'o'; break;
+ case FT_PARITY_EVEN: parity = 'e'; break;
+ case FT_PARITY_MARK: parity = 'm'; break;
+ case FT_PARITY_SPACE: parity = 's'; break;
+ default: parity = '?';
+ }
+ Tcl_DStringSetLength(&ds, 64);
+ sprintf(Tcl_DStringValue(&ds), "%d,%c,%d,%d",
+ instPtr->baudrate, parity, instPtr->databits,
+ instPtr->stopbits == FT_STOP_BITS_1 ? 1 : 2);
+ } else if (!strcmp("-handshake", optionName)) {
+ switch (instPtr->handshake) {
+ case FT_FLOW_NONE: Tcl_DStringAppend(&ds, "none", 4); break;
+ case FT_FLOW_RTS_CTS: Tcl_DStringAppend(&ds, "rtscts", 6); break;
+ case FT_FLOW_DTR_DSR: Tcl_DStringAppend(&ds, "dtrdsr", 6); break;
+ case FT_FLOW_XON_XOFF: Tcl_DStringAppend(&ds, "xonxoff", 7); break;
+ default : Tcl_DStringAppend(&ds, "unknown", 7);
+ }
+ } else if (!strcmp("-xchar", optionName)) {
+ char cbuf[2];
+ cbuf[1] = 0;
+ cbuf[0] = instPtr->xonchar;
+ Tcl_DStringAppendElement(&ds, cbuf);
+ cbuf[0] = instPtr->xoffchar;
+ Tcl_DStringAppendElement(&ds, cbuf);
} else {
const char **p;
for (p = options; *p != NULL; ++p) {
devname, "\": ", ConvertError(fts), NULL);
return TCL_ERROR;
}
+
+ if ((fts = procs.FT_SetBaudRate(handle, 19200)) != FT_OK) {
+ Tcl_AppendResult(interp, "failed set baudrate: \"",
+ ConvertError(fts), NULL);
+ return TCL_ERROR;
+ }
+
+ if ((fts = procs.FT_SetDataCharacteristics(handle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE)) != FT_OK) {
+ Tcl_AppendResult(interp, "failed set data characteristics: \"",
+ ConvertError(fts), NULL);
+ return TCL_ERROR;
+ }
+
+ if ((fts = procs.FT_SetFlowControl(handle, FT_FLOW_NONE, 0x11, 0x13)) != FT_OK) {
+ Tcl_AppendResult(interp, "failed set flowcontrol: \"",
+ ConvertError(fts), NULL);
+ return TCL_ERROR;
+ }
+
if ((fts = procs.FT_SetTimeouts(handle, rxtimeout, txtimeout)) != FT_OK) {
procs.FT_Close(handle);
Tcl_AppendResult(interp, "failed initialize timeouts: ",
instPtr->flags = 0;
instPtr->watchmask = 0;
instPtr->validmask = TCL_READABLE | TCL_WRITABLE;
+ instPtr->baudrate = 19200;
+ instPtr->parity = FT_PARITY_NONE;
+ instPtr->databits = FT_BITS_8;
+ instPtr->stopbits = FT_STOP_BITS_1;
+ instPtr->handshake = FT_FLOW_NONE;
+ instPtr->xonchar = 0x11;
+ instPtr->xoffchar = 0x13;
instPtr->rxtimeout = rxtimeout;
instPtr->txtimeout = txtimeout;
instPtr->handle = handle;
|| LOADPROC(FT_SetTimeouts)
|| LOADPROC(FT_Write)
|| LOADPROC(FT_GetLibraryVersion)
- || LOADPROC(FT_Rescan) )
+ || LOADPROC(FT_Rescan)
+ || LOADPROC(FT_SetBaudRate)
+ || LOADPROC(FT_SetDataCharacteristics)
+ || LOADPROC(FT_SetFlowControl)
+ )
{
Tcl_SetResult(interp, "invalid ftd2xx.dll library!", TCL_STATIC);
Tcl_SetErrorCode(interp, "DLL_INVALID", szDllName, NULL);