3 \brief �V���A���ʐM (Linux, Mac ���)
5 Serial Communication Interface ����
8 \author Satofumi KAMIMURA
10 $Id: serial_ctrl_lin.c 1559 2009-12-01 13:13:08Z satofumi $
13 #include "serial_errno.h"
14 #include "ring_buffer.h"
20 #include <sys/select.h>
22 #include <sys/types.h>
38 void serial_initialize(serial_t *serial)
40 serial->fd_ = InvalidFd;
41 serial->errno_ = SerialNoError;
42 serial->has_last_ch_ = False;
44 ring_initialize(&serial->ring_, serial->buffer_, RingBufferSizeShift);
49 int serial_connect(serial_t *serial, const char *device, long baudrate)
54 serial_initialize(serial);
57 enum { O_EXLOCK = 0x0 }; /* Linux �ł͎g���Ȃ��̂Ń_�~�[���쐬���Ă��� */
59 serial->fd_ = open(device, O_RDWR | O_EXLOCK | O_NONBLOCK | O_NOCTTY);
60 if (serial->fd_ < 0) {
62 strerror_r(errno, serial->error_string_, SerialErrorStringSize);
63 return SerialConnectionFail;
66 flags = fcntl(serial->fd_, F_GETFL, 0);
67 fcntl(serial->fd_, F_SETFL, flags & ~O_NONBLOCK);
69 /* �V���A���ʐM�̏����� */
70 tcgetattr(serial->fd_, &serial->sio_);
71 serial->sio_.c_iflag = 0;
72 serial->sio_.c_oflag = 0;
73 serial->sio_.c_cflag &= ~(CSIZE | PARENB | CSTOPB);
74 serial->sio_.c_cflag |= CS8 | CREAD | CLOCAL;
75 serial->sio_.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN);
77 serial->sio_.c_cc[VMIN] = 0;
78 serial->sio_.c_cc[VTIME] = 0;
81 ret = serial_setBaudrate(serial, baudrate);
86 /* �V���A�������\���̂̏����� */
87 serial->has_last_ch_ = False;
94 void serial_disconnect(serial_t *serial)
96 if (serial->fd_ >= 0) {
98 serial->fd_ = InvalidFd;
103 int serial_isConnected(const serial_t *serial)
105 return ((serial == NULL) || (serial->fd_ == InvalidFd)) ? 0 : 1;
110 int serial_setBaudrate(serial_t *serial, long baudrate)
112 long baudrate_value = -1;
116 baudrate_value = B4800;
120 baudrate_value = B9600;
124 baudrate_value = B19200;
128 baudrate_value = B38400;
132 baudrate_value = B57600;
136 baudrate_value = B115200;
140 return SerialSetBaudrateFail;
144 cfsetospeed(&serial->sio_, baudrate_value);
145 cfsetispeed(&serial->sio_, baudrate_value);
146 tcsetattr(serial->fd_, TCSADRAIN, &serial->sio_);
147 serial_clear(serial);
154 int serial_send(serial_t *serial, const char *data, int data_size)
156 if (! serial_isConnected(serial)) {
157 return SerialConnectionFail;
159 return write(serial->fd_, data, data_size);
163 static int waitReceive(serial_t* serial, int timeout)
170 FD_SET(serial->fd_, &rfds);
172 tv.tv_sec = timeout / 1000;
173 tv.tv_usec = (timeout % 1000) * 1000;
175 if (select(serial->fd_ + 1, &rfds, NULL, NULL,
176 (timeout < 0) ? NULL : &tv) <= 0) {
177 /* �^�C���A�E�g���� */
184 static int internal_receive(char data[], int data_size_max,
185 serial_t* serial, int timeout)
189 if (data_size_max <= 0) {
193 while (filled < data_size_max) {
197 if (! waitReceive(serial, timeout)) {
201 require_n = data_size_max - filled;
202 read_n = read(serial->fd_, &data[filled], require_n);
204 /* �ǂݏo���G���[�B���݂܂ł̎��M���e�Ŗ߂� */
214 int serial_recv(serial_t *serial, char* data, int data_size_max, int timeout)
220 if (data_size_max <= 0) {
224 /* �����߂����P�����������A�����o�� */
226 if (serial->has_last_ch_ != False) {
227 data[0] = serial->last_ch_;
228 serial->has_last_ch_ = False;
232 if (! serial_isConnected(serial)) {
236 return SerialConnectionFail;
239 buffer_size = ring_size(&serial->ring_);
240 read_n = data_size_max - filled;
241 if (buffer_size < read_n) {
242 // �����O�o�b�t�@���̃f�[�^�ő����Ȃ����A�f�[�^���ǂݑ���
243 char buffer[RingBufferSize];
244 int n = internal_receive(buffer,
245 ring_capacity(&serial->ring_) - buffer_size,
247 ring_write(&serial->ring_, buffer, n);
249 buffer_size = ring_size(&serial->ring_);
251 // �����O�o�b�t�@���̃f�[�^���Ԃ�
252 if (read_n > buffer_size) {
253 read_n = buffer_size;
256 ring_read(&serial->ring_, &data[filled], read_n);
260 // �f�[�^���^�C���A�E�g�t���œǂݏo��
261 filled += internal_receive(&data[filled],
262 data_size_max - filled, serial, timeout);
268 void serial_ungetc(serial_t *serial, char ch)
270 serial->has_last_ch_ = True;
271 serial->last_ch_ = ch;
275 void serial_clear(serial_t* serial)
277 tcdrain(serial->fd_);
278 tcflush(serial->fd_, TCIOFLUSH);
279 ring_clear(&serial->ring_);
280 serial->has_last_ch_ = False;