00001
00010 #include "urg_c/urg_serial.h"
00011 #include <stdio.h>
00012
00013 #if defined(URG_MSC)
00014 #define False 0
00015 #endif
00016
00017
00018 static void serial_initialize(urg_serial_t *serial)
00019 {
00020 serial->hCom = INVALID_HANDLE_VALUE;
00021 serial->has_last_ch = False;
00022
00023 ring_initialize(&serial->ring, serial->buffer, RING_BUFFER_SIZE_SHIFT);
00024 }
00025
00026
00027 static void set_timeout(urg_serial_t *serial, int timeout)
00028 {
00029 COMMTIMEOUTS timeouts;
00030 GetCommTimeouts(serial->hCom, &timeouts);
00031
00032 timeouts.ReadIntervalTimeout = (timeout == 0) ? MAXDWORD : 0;
00033 timeouts.ReadTotalTimeoutConstant = timeout;
00034 timeouts.ReadTotalTimeoutMultiplier = 0;
00035
00036 SetCommTimeouts(serial->hCom, &timeouts);
00037 }
00038
00039
00040 int serial_open(urg_serial_t *serial, const char *device, long baudrate)
00041 {
00042
00043 enum { NameLength = 11 };
00044 char adjusted_device[NameLength];
00045
00046 serial_initialize(serial);
00047
00048
00049 _snprintf(adjusted_device, NameLength, "\\\\.\\%s", device);
00050 serial->hCom = CreateFileA(adjusted_device, GENERIC_READ | GENERIC_WRITE,
00051 0, NULL, OPEN_EXISTING,
00052 FILE_ATTRIBUTE_NORMAL, NULL);
00053
00054 if (serial->hCom == INVALID_HANDLE_VALUE) {
00055
00056
00057 return -1;
00058 }
00059
00060
00061 SetupComm(serial->hCom, 4096 * 8, 4096);
00062
00063
00064 serial_set_baudrate(serial, baudrate);
00065
00066
00067 serial->has_last_ch = False;
00068
00069
00070 serial->current_timeout = 0;
00071 set_timeout(serial, serial->current_timeout);
00072
00073 return 0;
00074 }
00075
00076
00077 void serial_close(urg_serial_t *serial)
00078 {
00079 if (serial->hCom != INVALID_HANDLE_VALUE) {
00080 CloseHandle(serial->hCom);
00081 serial->hCom = INVALID_HANDLE_VALUE;
00082 }
00083 }
00084
00085
00086 int serial_set_baudrate(urg_serial_t *serial, long baudrate)
00087 {
00088 long baudrate_value;
00089 DCB dcb;
00090
00091 switch (baudrate) {
00092
00093 case 4800:
00094 baudrate_value = CBR_4800;
00095 break;
00096
00097 case 9600:
00098 baudrate_value = CBR_9600;
00099 break;
00100
00101 case 19200:
00102 baudrate_value = CBR_19200;
00103 break;
00104
00105 case 38400:
00106 baudrate_value = CBR_38400;
00107 break;
00108
00109 case 57600:
00110 baudrate_value = CBR_57600;
00111 break;
00112
00113 case 115200:
00114 baudrate_value = CBR_115200;
00115 break;
00116
00117 default:
00118 baudrate_value = baudrate;
00119 }
00120
00121 GetCommState(serial->hCom, &dcb);
00122 dcb.BaudRate = baudrate_value;
00123 dcb.ByteSize = 8;
00124 dcb.Parity = NOPARITY;
00125 dcb.fParity = FALSE;
00126 dcb.StopBits = ONESTOPBIT;
00127 SetCommState(serial->hCom, &dcb);
00128
00129 return 0;
00130 }
00131
00132
00133 int serial_write(urg_serial_t *serial, const char *data, int size)
00134 {
00135 DWORD n;
00136
00137 if (size < 0) {
00138 return 0;
00139 }
00140
00141 if (serial->hCom == INVALID_HANDLE_VALUE) {
00142 return -1;
00143 }
00144
00145 WriteFile(serial->hCom, data, (DWORD)size, &n, NULL);
00146 return n;
00147 }
00148
00149
00150 static int internal_receive(char data[], int max_size,
00151 urg_serial_t* serial, int timeout)
00152 {
00153 int filled = 0;
00154 DWORD n;
00155
00156 if (timeout != serial->current_timeout) {
00157 set_timeout(serial, timeout);
00158 serial->current_timeout = timeout;
00159 }
00160
00161 ReadFile(serial->hCom, &data[filled], (DWORD)max_size - filled, &n, NULL);
00162
00163 return filled + n;
00164 }
00165
00166
00167 int serial_read(urg_serial_t *serial, char *data, int max_size, int timeout)
00168 {
00169 int filled = 0;
00170 int buffer_size;
00171 int read_n;
00172
00173 if (max_size <= 0) {
00174 return 0;
00175 }
00176
00177
00178 if (serial->has_last_ch) {
00179 data[0] = serial->last_ch;
00180 serial->has_last_ch = False;
00181 ++filled;
00182 }
00183
00184 if (serial->hCom == INVALID_HANDLE_VALUE) {
00185 if (filled > 0) {
00186 return filled;
00187 }
00188 return -1;
00189 }
00190
00191 buffer_size = ring_size(&serial->ring);
00192 read_n = max_size - filled;
00193 if (buffer_size < read_n) {
00194
00195 char buffer[RING_BUFFER_SIZE];
00196 int n = internal_receive(buffer,
00197 ring_capacity(&serial->ring) - buffer_size,
00198 serial, 0);
00199 ring_write(&serial->ring, buffer, n);
00200 }
00201 buffer_size = ring_size(&serial->ring);
00202
00203
00204 if (read_n > buffer_size) {
00205 read_n = buffer_size;
00206 }
00207 if (read_n > 0) {
00208 ring_read(&serial->ring, &data[filled], read_n);
00209 filled += read_n;
00210 }
00211
00212
00213 filled += internal_receive(&data[filled],
00214 max_size - filled, serial, timeout);
00215 return filled;
00216 }