00001
00012 #include "serial_ctrl.h"
00013 #include "serial_errno.h"
00014 #include "ring_buffer.h"
00015 #include <stdio.h>
00016
00017
00018 enum {
00019 False = 0,
00020 True,
00021 };
00022
00023
00024 static void setTimeout(serial_t *serial, int timeout)
00025 {
00026 COMMTIMEOUTS timeouts;
00027 GetCommTimeouts(serial->hCom_, &timeouts);
00028
00029 timeouts.ReadIntervalTimeout = (timeout == 0) ? MAXDWORD : 0;
00030 timeouts.ReadTotalTimeoutConstant = timeout;
00031 timeouts.ReadTotalTimeoutMultiplier = 0;
00032
00033 SetCommTimeouts(serial->hCom_, &timeouts);
00034 }
00035
00036
00037 void serial_initialize(serial_t *serial)
00038 {
00039 serial->hCom_ = INVALID_HANDLE_VALUE;
00040 serial->errno_ = SerialNoError;
00041 serial->has_last_ch_ = False;
00042
00043 ring_initialize(&serial->ring_, serial->buffer_, RingBufferSizeShift);
00044 }
00045
00046
00047
00048 int serial_connect(serial_t *serial, const char *device, long baudrate)
00049 {
00050
00051 enum { NameLength = 11 };
00052 char adjusted_device[NameLength];
00053
00054 serial_initialize(serial);
00055
00056
00057 _snprintf(adjusted_device, NameLength, "\\\\.\\%s", device);
00058 serial->hCom_ = CreateFileA(adjusted_device, GENERIC_READ | GENERIC_WRITE, 0,
00059 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00060
00061 if (serial->hCom_ == INVALID_HANDLE_VALUE) {
00062 printf("open failed: %s\n", device);
00063 return -1;
00064 }
00065
00066
00067 SetupComm(serial->hCom_, 4096 * 8, 4096);
00068
00069
00070 serial_setBaudrate(serial, baudrate);
00071
00072
00073 serial->has_last_ch_ = False;
00074
00075
00076 serial->current_timeout_ = 0;
00077 setTimeout(serial, serial->current_timeout_);
00078
00079 return 0;
00080 }
00081
00082
00083
00084 void serial_disconnect(serial_t *serial)
00085 {
00086 if (serial->hCom_ != INVALID_HANDLE_VALUE) {
00087 CloseHandle(serial->hCom_);
00088 serial->hCom_ = INVALID_HANDLE_VALUE;
00089 }
00090 }
00091
00092
00093 int serial_isConnected(const serial_t *serial)
00094 {
00095 return (serial->hCom_ == INVALID_HANDLE_VALUE) ? 0 : 1;
00096 }
00097
00098
00099
00100 int serial_setBaudrate(serial_t *serial, long baudrate)
00101 {
00102 long baudrate_value;
00103 DCB dcb;
00104
00105 switch (baudrate) {
00106
00107 case 4800:
00108 baudrate_value = CBR_4800;
00109 break;
00110
00111 case 9600:
00112 baudrate_value = CBR_9600;
00113 break;
00114
00115 case 19200:
00116 baudrate_value = CBR_19200;
00117 break;
00118
00119 case 38400:
00120 baudrate_value = CBR_38400;
00121 break;
00122
00123 case 57600:
00124 baudrate_value = CBR_57600;
00125 break;
00126
00127 case 115200:
00128 baudrate_value = CBR_115200;
00129 break;
00130
00131 default:
00132 baudrate_value = baudrate;
00133 }
00134
00135 GetCommState(serial->hCom_, &dcb);
00136 dcb.BaudRate = baudrate_value;
00137 dcb.ByteSize = 8;
00138 dcb.Parity = NOPARITY;
00139 dcb.fParity = FALSE;
00140 dcb.StopBits = ONESTOPBIT;
00141 SetCommState(serial->hCom_, &dcb);
00142
00143 return 0;
00144 }
00145
00146
00147
00148 int serial_send(serial_t *serial, const char *data, int data_size)
00149 {
00150 DWORD n;
00151
00152 if (data_size < 0) {
00153 return 0;
00154 }
00155
00156 if (! serial_isConnected(serial)) {
00157 return SerialConnectionFail;
00158 }
00159
00160 WriteFile(serial->hCom_, data, (DWORD)data_size, &n, NULL);
00161 return n;
00162 }
00163
00164
00165 static int internal_receive(char data[], int data_size_max,
00166 serial_t* serial, int timeout)
00167 {
00168 int filled = 0;
00169 DWORD n;
00170
00171 if (timeout != serial->current_timeout_) {
00172 setTimeout(serial, timeout);
00173 serial->current_timeout_ = timeout;
00174 }
00175
00176 ReadFile(serial->hCom_, &data[filled],
00177 (DWORD)data_size_max - filled, &n, NULL);
00178
00179 return filled + n;
00180 }
00181
00182
00183
00184 int serial_recv(serial_t *serial, char* data, int data_size_max, int timeout)
00185 {
00186 int filled = 0;
00187 int buffer_size;
00188 int read_n;
00189
00190 if (data_size_max <= 0) {
00191 return 0;
00192 }
00193
00194
00195 if (serial->has_last_ch_) {
00196 data[0] = serial->last_ch_;
00197 serial->has_last_ch_ = False;
00198 ++filled;
00199 }
00200
00201 if (! serial_isConnected(serial)) {
00202 if (filled > 0) {
00203 return filled;
00204 }
00205 return SerialConnectionFail;
00206 }
00207
00208 buffer_size = ring_size(&serial->ring_);
00209 read_n = data_size_max - filled;
00210 if (buffer_size < read_n) {
00211
00212 char buffer[RingBufferSize];
00213 int n = internal_receive(buffer,
00214 ring_capacity(&serial->ring_) - buffer_size,
00215 serial, 0);
00216 ring_write(&serial->ring_, buffer, n);
00217 }
00218 buffer_size = ring_size(&serial->ring_);
00219
00220
00221 if (read_n > buffer_size) {
00222 read_n = buffer_size;
00223 }
00224 if (read_n > 0) {
00225 ring_read(&serial->ring_, &data[filled], read_n);
00226 filled += read_n;
00227 }
00228
00229
00230 filled += internal_receive(&data[filled],
00231 data_size_max - filled, serial, timeout);
00232 return filled;
00233 }
00234
00235
00236
00237 void serial_ungetc(serial_t *serial, char ch)
00238 {
00239 serial->has_last_ch_ = True;
00240 serial->last_ch_ = ch;
00241 }
00242
00243
00244 void serial_clear(serial_t* serial)
00245 {
00246 PurgeComm(serial->hCom_,
00247 PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR);
00248
00249 serial->has_last_ch_ = False;
00250 }