-/* tclftd2xx.c - Copyright (C) 2008 Pat Thoyts <patthoyts@users.sourceforge.net>
+/* tclftd2xx.c -
+ *
+ * Copyright (C) 2008 Pat Thoyts <patthoyts@users.sourceforge.net>
+ * Copyright (C) 2008 Leopold Gerlinger
++ * Copyright (C) 2009 Lars Unger
*
* FTDI D2XX USB Device driver Tcl interface.
*
if (r == TCL_OK) {
fts = procs.FT_SetLatencyTimer(instPtr->handle, (UCHAR)tmp);
}
+ } else if (!strcmp("-bitmode", optionName)) {
+ int tmp = 1;
+ r = Tcl_GetInt(interp, newValue, &tmp);
+ if (r == TCL_OK) {
+ fts = procs.FT_SetBitMode(instPtr->handle, (UCHAR)(tmp >> 8), (UCHAR)(tmp & 0xff));
+ }
+ } else if (!strcmp("-mode", optionName)) {
+ int baudrate = 19200, databits = 8, stop = 1;
+ char parity = 'n';
+ unsigned char wordlen = FT_BITS_8, stopbits = FT_STOP_BITS_1;
+
+ sscanf(newValue, "%d,%c,%d,%d", &baudrate, &parity, &databits, &stop);
+
+ switch (databits) {
+ case 8: wordlen = FT_BITS_8; break;
+ case 7: wordlen = FT_BITS_7; break;
+ case 6: wordlen = FT_BITS_6; break;
+ case 5: wordlen = FT_BITS_5; break;
+ default:
+ Tcl_AppendResult(interp, "bad data value \"", newValue,
+ "\": must be 5, 6, 7 or 8.", NULL);
+ return TCL_ERROR;
+ }
+
+ switch (stop) {
+ case 1: stopbits = FT_STOP_BITS_1; break;
+ case 2: stopbits = FT_STOP_BITS_2; break;
+ default:
+ Tcl_AppendResult(interp, "bad stop value \"", newValue,
+ "\"must be either 1 or 2.", 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, "bad parity value \"", newValue,
+ "\": must be one of n, o, e, m, or s.", NULL);
+ return TCL_ERROR;
+ }
+
+ fts = procs.FT_SetBaudRate(instPtr->handle, baudrate);
+ if (fts != FT_OK) {
+ Tcl_AppendResult(interp, "failed set baudrate: \"",
+ ConvertError(fts), NULL);
+ return TCL_ERROR;
+ }
+
+ fts = procs.FT_SetDataCharacteristics(instPtr->handle, wordlen, stopbits, parity);
+ if (fts == FT_OK) {
+ instPtr->baudrate = baudrate;
+ instPtr->databits = wordlen;
+ 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, "bad value \"", newValue, "\" for ", optionName,
+ ": must be one of none, rtscts, dtrdsr or xonxoff", NULL);
+ return TCL_ERROR;
+ }
+ fts = procs.FT_SetFlowControl(instPtr->handle, handshake, instPtr->xonchar, instPtr->xoffchar);
+ if (fts == FT_OK) {
+ instPtr->handshake = handshake;
+ }
+ } else if (!strcmp("-xchar", optionName)) {
+ int xrgc, n;
+ char xonxoff[2];
+ const char **xrgv;
+ if (Tcl_SplitList(interp, newValue, &xrgc, &xrgv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (xrgc != 2) {
+ badxchar:
+ Tcl_AppendResult(interp, "bad value for -xchar: must be a list of two elements", NULL);
+ return TCL_ERROR;
+ }
+ for (n = 0; n < 2; ++n) {
+ /* check for extended utf-8 and handle like tcl serial channel */
+ if (xrgv[n][0] & 0x80) {
+ Tcl_UniChar c;
+ int len;
+ len = Tcl_UtfToUniChar(xrgv[n], &c);
+ if (xrgv[n][len]) {
+ goto badxchar;
+ }
+ xonxoff[n] = (char)c;
+ } else {
+ xonxoff[n] = xrgv[n][0];
+ }
+ }
+
+ fts = procs.FT_SetFlowControl(instPtr->handle, instPtr->handshake, xonxoff[0], xonxoff[1]);
+ if (fts == FT_OK) {
+ instPtr->xonchar = xonxoff[0];
+ instPtr->xoffchar = xonxoff[1];
+ }
}
if (fts != FT_OK) {
const char *optionName, Tcl_DString *optionValue)
{
Channel *instPtr = instance;
- const char *options[] = {"readtimeout", "writetimeout", "latency", "bitmode", NULL};
+ const char *options[] = {"readtimeout", "writetimeout", "latency",
- "mode", "handshake", "xchar", NULL};
++ "bitmode", "mode", "handshake", "xchar", NULL};
int r = TCL_OK;
if (optionName == NULL) {
ConvertError(fts), NULL);
r = TCL_ERROR;
}
+ } else if (!strcmp("-bitmode", optionName)) {
+ UCHAR bmode = 0;
+ fts = procs.FT_GetBitMode(instPtr->handle, &bmode);
+ if (fts == FT_OK) {
+ Tcl_DStringSetLength(&ds, TCL_INTEGER_SPACE);
+ sprintf(Tcl_DStringValue(&ds), "%d", bmode);
+ } else {
+ Tcl_AppendResult(interp, "failed to read ", optionName, ": ",
+ 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, TCL_INTEGER_SPACE * 3 + 6);
+ 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] = {0, 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) {