Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fixed serial port communication, no longer blocks on gets in non-blocking mode. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | core-8-1-branch-old |
Files: | files | file ages | folders |
SHA1: |
0df14240cc7d6b9b66ef6f49f86fbc96 |
User & Date: | redman 1999-03-24 02:37:14.000 |
Context
1999-03-24
| ||
02:38 | Fixed serial port check-in: 762e3896db user: redman tags: core-8-1-branch-old | |
02:37 | Fixed serial port communication, no longer blocks on gets in non-blocking mode. check-in: 0df14240cc user: redman tags: core-8-1-branch-old | |
01:42 | Fixed initialization bug [Bug ID: 647] check-in: 1aebc74e85 user: surles tags: core-8-1-branch-old | |
Changes
Changes to win/tclWinSerial.c.
1 2 3 4 5 6 7 8 9 10 11 | /* * Tclwinserial.c -- * * This file implements the Windows-specific serial port functions, * and the "serial" channel driver. * * Copyright (c) 1999 by Scriptics Corp. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * Tclwinserial.c -- * * This file implements the Windows-specific serial port functions, * and the "serial" channel driver. * * Copyright (c) 1999 by Scriptics Corp. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclWinSerial.c,v 1.1.2.3 1999/03/24 02:37:14 redman Exp $ */ #include "tclWinInt.h" #include <dos.h> #include <fcntl.h> #include <io.h> |
︙ | ︙ | |||
35 36 37 38 39 40 41 | #define SERIAL_ASYNC (1<<1) /* Channel is non-blocking. */ /* * Bit masks used in the sharedFlags field of the SerialInfo structure below. */ #define SERIAL_EOF (1<<2) /* Serial has reached EOF. */ | | | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #define SERIAL_ASYNC (1<<1) /* Channel is non-blocking. */ /* * Bit masks used in the sharedFlags field of the SerialInfo structure below. */ #define SERIAL_EOF (1<<2) /* Serial has reached EOF. */ #define SERIAL_EXTRABYTE (1<<3) /* Extra byte consumed while waiting for data */ /* * This structure describes per-instance data for a serial based channel. */ typedef struct SerialInfo { HANDLE handle; struct SerialInfo *nextPtr; /* Pointer to next registered serial. */ |
︙ | ︙ | |||
89 90 91 92 93 94 95 96 97 98 99 100 101 102 | int readFlags; /* Flags that are shared with the reader * thread. Access is synchronized with the * readable object. */ int writeFlags; /* Flags that are shared with the writer * thread. Access is synchronized with the * readable object. */ int readyMask; /* Events that need to be checked on. */ } SerialInfo; typedef struct ThreadSpecificData { /* * The following pointer refers to the head of the list of serials * that are being watched for file events. */ | > > | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | int readFlags; /* Flags that are shared with the reader * thread. Access is synchronized with the * readable object. */ int writeFlags; /* Flags that are shared with the writer * thread. Access is synchronized with the * readable object. */ int readyMask; /* Events that need to be checked on. */ char extraByte; } SerialInfo; typedef struct ThreadSpecificData { /* * The following pointer refers to the head of the list of serials * that are being watched for file events. */ |
︙ | ︙ | |||
464 465 466 467 468 469 470 471 472 473 474 475 476 477 | CloseHandle(serialPtr->startReader); serialPtr->readThread = NULL; } serialPtr->validMask &= ~TCL_READABLE; if (serialPtr->writeThread) { WaitForSingleObject(serialPtr->writable, INFINITE); /* * Wait for the thread to terminate. This ensures that we are * completely cleaned up before we leave this function. */ WaitForSingleObject(serialPtr->writeThread, INFINITE); | > < | 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 | CloseHandle(serialPtr->startReader); serialPtr->readThread = NULL; } serialPtr->validMask &= ~TCL_READABLE; if (serialPtr->writeThread) { WaitForSingleObject(serialPtr->writable, INFINITE); TerminateThread(serialPtr->writeThread, 0); /* * Wait for the thread to terminate. This ensures that we are * completely cleaned up before we leave this function. */ WaitForSingleObject(serialPtr->writeThread, INFINITE); CloseHandle(serialPtr->writeThread); CloseHandle(serialPtr->writable); CloseHandle(serialPtr->startWriter); serialPtr->writeThread = NULL; } serialPtr->validMask &= ~TCL_WRITABLE; |
︙ | ︙ | |||
546 547 548 549 550 551 552 | int bufSize, /* How much space is available * in the buffer? */ int *errorCode) /* Where to store error code. */ { SerialInfo *infoPtr = (SerialInfo *) instanceData; DWORD bytesRead = 0; int result; | | < < < | < < < | < < < < < < < < | < < < < | | | > | | < < < | < < < | 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | int bufSize, /* How much space is available * in the buffer? */ int *errorCode) /* Where to store error code. */ { SerialInfo *infoPtr = (SerialInfo *) instanceData; DWORD bytesRead = 0; int result; DWORD err; *errorCode = 0; /* * Synchronize with the reader thread. */ result = WaitForRead(infoPtr, (infoPtr->flags & SERIAL_ASYNC) ? 0 : 1); /* * If an error occurred, return immediately. */ if (result == -1) { *errorCode = errno; return -1; } if (infoPtr->readFlags & SERIAL_EXTRABYTE) { /* * If a byte was consumed waiting, then put it in the buffer. */ *buf = infoPtr->extraByte; infoPtr->readFlags &= ~SERIAL_EXTRABYTE; buf++; bufSize--; bytesRead = 1; if (result == 0) { return bytesRead; } } if (ReadFile(infoPtr->handle, (LPVOID) buf, (DWORD) bufSize, &bytesRead, NULL) == FALSE) { err = GetLastError(); if (err != ERROR_IO_PENDING) { |
︙ | ︙ | |||
923 924 925 926 927 928 929 | static int WaitForRead( SerialInfo *infoPtr, /* Serial state. */ int blocking) /* Indicates whether call should be * blocking or not. */ { | | > > | 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 | static int WaitForRead( SerialInfo *infoPtr, /* Serial state. */ int blocking) /* Indicates whether call should be * blocking or not. */ { DWORD timeout, errors; HANDLE *handle = infoPtr->handle; COMSTAT stat; while (1) { /* * Synchronize with the reader thread. */ timeout = blocking ? INFINITE : 0; if (WaitForSingleObject(infoPtr->readable, timeout) == WAIT_TIMEOUT) { /* |
︙ | ︙ | |||
947 948 949 950 951 952 953 | /* * At this point, the two threads are synchronized, so it is safe * to access shared state. This code is not called in the ReaderThread * in blocking mode, so it needs to be checked here. */ | < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 | /* * At this point, the two threads are synchronized, so it is safe * to access shared state. This code is not called in the ReaderThread * in blocking mode, so it needs to be checked here. */ /* * If the serial has hit EOF, it is always readable. */ if (infoPtr->readFlags & SERIAL_EOF) { return 1; } if (ClearCommError(infoPtr->handle, &errors, &stat)) { /* * If there are errors, then signal an I/O error. */ if (errors != 0) { errno = EIO; return -1; } } /* * If data is in the queue return 1 */ if (stat.cbInQue != 0) { return 1; } /* * if there is an extra byte that was consumed while * waiting, but no data in the queue, return 0 */ if (infoPtr->readFlags & SERIAL_EXTRABYTE) { return 0; } ResetEvent(infoPtr->readable); SetEvent(infoPtr->startReader); } } /* *---------------------------------------------------------------------- * * SerialReaderThread -- * * This function runs in a separate thread and waits for input |
︙ | ︙ | |||
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 | static DWORD WINAPI SerialReaderThread(LPVOID arg) { SerialInfo *infoPtr = (SerialInfo *)arg; HANDLE *handle = infoPtr->handle; DWORD mask = EV_RXCHAR; for (;;) { /* * Wait for the main thread to signal before attempting to wait. */ WaitForSingleObject(infoPtr->startReader, INFINITE); /* * Try waiting for a Comm event. */ | > > | > > > | > > > > > > > > > > > > < < < < < | 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 | static DWORD WINAPI SerialReaderThread(LPVOID arg) { SerialInfo *infoPtr = (SerialInfo *)arg; HANDLE *handle = infoPtr->handle; DWORD mask = EV_RXCHAR; DWORD count; for (;;) { /* * Wait for the main thread to signal before attempting to wait. */ WaitForSingleObject(infoPtr->startReader, INFINITE); /* * Try waiting for a Comm event. */ WaitCommEvent(handle, NULL, NULL); /* * try to read one byte */ if (ReadFile(handle, &(infoPtr->extraByte), 1, &count, NULL) != FALSE) { /* * one byte was consumed while waiting to read, keep it */ if (count != 0) { infoPtr->readFlags |= SERIAL_EXTRABYTE; } } else { /* * There is an error, signal an EOF. */ infoPtr->readFlags |= SERIAL_EOF; } /* * Signal the main thread by signalling the readable event and * then waking up the notifier thread. */ SetEvent(infoPtr->readable); Tcl_ThreadAlert(infoPtr->threadId); } return 0; /* NOT REACHED */ } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
1139 1140 1141 1142 1143 1144 1145 | tsdPtr = SerialInit(); SetCommMask(handle, EV_RXCHAR); SetupComm(handle, 4096, 4096); PurgeComm(handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); cto.ReadIntervalTimeout = MAXDWORD; | | | | 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 | tsdPtr = SerialInit(); SetCommMask(handle, EV_RXCHAR); SetupComm(handle, 4096, 4096); PurgeComm(handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); cto.ReadIntervalTimeout = MAXDWORD; cto.ReadTotalTimeoutMultiplier = MAXDWORD; cto.ReadTotalTimeoutConstant = 1; cto.WriteTotalTimeoutMultiplier = 0; cto.WriteTotalTimeoutConstant = 0; SetCommTimeouts(handle, &cto); infoPtr = (SerialInfo *) ckalloc((unsigned) sizeof(SerialInfo)); memset(infoPtr, 0, sizeof(SerialInfo)); |
︙ | ︙ |