urg_serial_windows.c
Go to the documentation of this file.
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     // COM10 以降への対応用
00043     enum { NameLength = 11 };
00044     char adjusted_device[NameLength];
00045 
00046     serial_initialize(serial);
00047 
00048     /* COM ポートを開く */
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         // !!! store error_message buffer
00056         //printf("open failed: %s\n", device);
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     /* 書き戻した1文字があれば、書き出す */
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 }


urg_c
Author(s): Satofumi Kamimura , Katsumi Kimoto, Adrian Boeing
autogenerated on Wed Aug 26 2015 16:38:27