All Classes Namespaces Files Functions Variables Enumerations Enumerator
libs/connection/c/serial_ctrl_lin.c
Go to the documentation of this file.
00001 
00013 #include "serial_errno.h"
00014 #include "ring_buffer.h"
00015 #include <unistd.h>
00016 #include <stdio.h>
00017 #include <fcntl.h>
00018 #include <errno.h>
00019 #include <string.h>
00020 
00021 //#include <ctype.h>
00022 
00023 enum {
00024   False = 0,
00025   True,
00026 };
00027 
00028 
00029 enum {
00030   InvalidFd = -1,
00031 };
00032 
00033 
00034 void serial_initialize(serial_t *serial)
00035 {
00036   serial->fd_ = InvalidFd;
00037   serial->errno_ = SerialNoError;
00038   serial->has_last_ch_ = False;
00039 
00040   ring_initialize(&serial->ring_, serial->buffer_, RingBufferSizeShift);
00041 }
00042 
00043 
00044 /* 接続 */
00045 int serial_connect(serial_t *serial, const char *device, long baudrate)
00046 {
00047   int flags = 0;
00048   int ret = 0;
00049 
00050   serial_initialize(serial);
00051 
00052 #ifndef MAC_OS
00053   enum { O_EXLOCK = 0x0 }; /* Linux では使えないのでダミーを作成しておく */
00054 #endif
00055   serial->fd_ = open(device, O_RDWR | O_EXLOCK | O_NONBLOCK | O_NOCTTY);
00056   if (serial->fd_ < 0) {
00057     /* 接続に失敗 */
00058     strerror_r(errno, serial->error_string_, SerialErrorStringSize);
00059     return SerialConnectionFail;
00060   }
00061 
00062   flags = fcntl(serial->fd_, F_GETFL, 0);
00063   fcntl(serial->fd_, F_SETFL, flags & ~O_NONBLOCK);
00064 
00065   /* シリアル通信の初期化 */
00066   tcgetattr(serial->fd_, &serial->sio_);
00067   serial->sio_.c_iflag = 0;
00068   serial->sio_.c_oflag = 0;
00069   serial->sio_.c_cflag &= ~(CSIZE | PARENB | CSTOPB);
00070   serial->sio_.c_cflag |= CS8 | CREAD | CLOCAL;
00071   serial->sio_.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN);
00072 
00073   serial->sio_.c_cc[VMIN] = 0;
00074   serial->sio_.c_cc[VTIME] = 0;
00075 
00076   /* ボーレートの変更 */
00077   ret = serial_setBaudrate(serial, baudrate);
00078   if (ret < 0) {
00079     return ret;
00080   }
00081 
00082   /* シリアル制御構造体の初期化 */
00083   serial->has_last_ch_ = False;
00084 
00085   return 0;
00086 }
00087 
00088 
00089 /* 切断 */
00090 void serial_disconnect(serial_t *serial)
00091 {
00092   if (serial->fd_ >= 0) {
00093     close(serial->fd_);
00094     serial->fd_ = InvalidFd;
00095   }
00096 }
00097 
00098 
00099 int serial_isConnected(const serial_t *serial)
00100 {
00101   return ((serial == NULL) || (serial->fd_ == InvalidFd)) ? 0 : 1;
00102 }
00103 
00104 
00105 /* ボーレートの設定 */
00106 int serial_setBaudrate(serial_t *serial, long baudrate)
00107 {
00108   long baudrate_value = -1;
00109 
00110   switch (baudrate) {
00111   case 4800:
00112     baudrate_value = B4800;
00113     break;
00114 
00115   case 9600:
00116     baudrate_value = B9600;
00117     break;
00118 
00119   case 19200:
00120     baudrate_value = B19200;
00121     break;
00122 
00123   case 38400:
00124     baudrate_value = B38400;
00125     break;
00126 
00127   case 57600:
00128     baudrate_value = B57600;
00129     break;
00130 
00131   case 115200:
00132     baudrate_value = B115200;
00133     break;
00134 
00135   default:
00136     return SerialSetBaudrateFail;
00137   }
00138 
00139   /* ボーレート変更 */
00140   cfsetospeed(&serial->sio_, baudrate_value);
00141   cfsetispeed(&serial->sio_, baudrate_value);
00142   tcsetattr(serial->fd_, TCSADRAIN, &serial->sio_);
00143   serial_clear(serial);
00144 
00145   return 0;
00146 }
00147 
00148 
00149 /* 送信 */
00150 int serial_send(serial_t *serial, const char *data, int data_size)
00151 {
00152   if (! serial_isConnected(serial)) {
00153     return SerialConnectionFail;
00154   }
00155   return write(serial->fd_, data, data_size);
00156 }
00157 
00158 
00159 static int waitReceive(serial_t* serial, int timeout)
00160 {
00161   fd_set rfds;
00162   struct timeval tv;
00163 
00164   // タイムアウト設定
00165   FD_ZERO(&rfds);
00166   FD_SET(serial->fd_, &rfds);
00167 
00168   tv.tv_sec = timeout / 1000;
00169   tv.tv_usec = (timeout % 1000) * 1000;
00170 
00171   if (select(serial->fd_ + 1, &rfds, NULL, NULL,
00172              (timeout < 0) ? NULL : &tv) <= 0) {
00173     /* タイムアウト発生 */
00174     return 0;
00175   }
00176   return 1;
00177 }
00178 
00179 
00180 static int internal_receive(char data[], int data_size_max,
00181                             serial_t* serial, int timeout)
00182 {
00183   int filled = 0;
00184 
00185   if (data_size_max <= 0) {
00186     return 0;
00187   }
00188 
00189   while (filled < data_size_max) {
00190     int require_n;
00191     int read_n;
00192 
00193     if (! waitReceive(serial, timeout)) {
00194       break;
00195     }
00196 
00197     require_n = data_size_max - filled;
00198     read_n = read(serial->fd_, &data[filled], require_n);
00199     if (read_n <= 0) {
00200       /* 読み出しエラー。現在までの受信内容で戻る */
00201       break;
00202     }
00203     filled += read_n;
00204   }
00205   return filled;
00206 }
00207 
00208 
00209 /* 受信 */
00210 int serial_recv(serial_t *serial, char* data, int data_size_max, int timeout)
00211 {
00212   int filled;
00213   int read_n;
00214   int buffer_size;
00215 
00216   if (data_size_max <= 0) {
00217     return 0;
00218   }
00219 
00220   /* 書き戻した1文字があれば、書き出す */
00221   filled = 0;
00222   if (serial->has_last_ch_ != False) {
00223     data[0] = serial->last_ch_;
00224     serial->has_last_ch_ = False;
00225     ++filled;
00226   }
00227 
00228   if (! serial_isConnected(serial)) {
00229     if (filled > 0) {
00230       return filled;
00231     }
00232     return SerialConnectionFail;
00233   }
00234 
00235   buffer_size = ring_size(&serial->ring_);
00236   read_n = data_size_max - filled;
00237   if (buffer_size < read_n) {
00238     // リングバッファ内のデータで足りなければ、データを読み足す
00239     char buffer[RingBufferSize];
00240     int n = internal_receive(buffer,
00241                              ring_capacity(&serial->ring_) - buffer_size,
00242                              serial, 0);
00243     ring_write(&serial->ring_, buffer, n);
00244   }
00245   buffer_size = ring_size(&serial->ring_);
00246 
00247   // リングバッファ内のデータを返す
00248   if (read_n > buffer_size) {
00249     read_n = buffer_size;
00250   }
00251   if (read_n > 0) {
00252     ring_read(&serial->ring_, &data[filled], read_n);
00253     filled += read_n;
00254   }
00255 
00256   // データをタイムアウト付きで読み出す
00257   filled += internal_receive(&data[filled],
00258                              data_size_max - filled, serial, timeout);
00259   return filled;
00260 }
00261 
00262 
00263 /* 1文字書き戻す */
00264 void serial_ungetc(serial_t *serial, char ch)
00265 {
00266   serial->has_last_ch_ = True;
00267   serial->last_ch_ = ch;
00268 }
00269 
00270 
00271 void serial_clear(serial_t* serial)
00272 {
00273   tcdrain(serial->fd_);
00274   tcflush(serial->fd_, TCIOFLUSH);
00275   ring_clear(&serial->ring_);
00276   serial->has_last_ch_ = False;
00277 }