Support various uart device name
[platform/core/system/peripheral-bus.git] / src / interface / uart.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <termios.h>
24 #include <stdbool.h>
25 #include <sys/ioctl.h>
26
27 #include "uart.h"
28 #include "peripheral_common.h"
29
30 #define PATH_BUF_MAX            64
31 #define UART_BUF_MAX            16
32
33 #define UART_BAUDRATE_SIZE      19
34
35 #ifndef ARRAY_SIZE
36 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
37 #endif
38
39 char *sysfs_uart_path[] = {
40         "/dev/ttyS",
41         "/dev/ttyAMA",
42         "/dev/ttySAC",
43 };
44
45 static const int peripheral_uart_br[UART_BAUDRATE_SIZE] = {
46         B0,                     B50,            B75,            B110,           B134,
47         B150,           B200,           B300,           B600,           B1200,
48         B1800,          B2400,          B4800,          B9600,          B19200,
49         B38400,         B57600,         B115200,        B230400
50 };
51
52 static const int byteinfo[4] = {CS5, CS6, CS7, CS8};
53
54 int uart_open(int port, int *file_hndl)
55 {
56         int i, fd;
57         char uart_dev[PATH_BUF_MAX] = {0};
58
59         _D("port : %d", port);
60
61         for (i = 0; i < ARRAY_SIZE(sysfs_uart_path); i++) {
62                 snprintf(uart_dev, PATH_BUF_MAX, "%s%d", sysfs_uart_path[i], port);
63                 if (access(uart_dev, F_OK) == 0)
64                         break;
65         }
66
67         if ((fd = open(uart_dev, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) {
68                 _E("Error[%d]: can't open %s, %s--[%d]\n", errno, uart_dev, __FUNCTION__, __LINE__);
69                 return -ENXIO;
70         }
71         *file_hndl = fd;
72         return 0;
73 }
74
75 int uart_close(int file_hndl)
76 {
77         _D("file_hndl : %d", file_hndl);
78
79         if (!file_hndl) {
80                 _E("Error[%d]: Invalid parameter, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
81                 return -EINVAL;
82         }
83         close(file_hndl);
84         return 0;
85 }
86
87 int uart_flush(int file_hndl)
88 {
89         int ret;
90
91         if (!file_hndl) {
92                 _E("Error[%d]: Invalid parameter, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
93                 return -EINVAL;
94         }
95
96         ret = tcflush(file_hndl, TCIOFLUSH);
97         if (ret < 0) {
98                 _E("FAILED[%d]: tcflush, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
99                 return -1;
100         }
101
102         return 0;
103 }
104
105 int uart_set_baudrate(int file_hndl, uart_baudrate_e baud)
106 {
107         int ret;
108         struct termios tio;
109
110         _D("file_hndl : %d, baud : %d", file_hndl, baud);
111
112         memset(&tio, 0, sizeof(tio));
113         if (!file_hndl) {
114                 _E("Error[%d]: Invalid parameter, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
115                 return -EINVAL;
116         }
117
118         if (baud > UART_BAUDRATE_230400) {
119                 _E("Error[%d]: Invalid parameter, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
120                 return -EINVAL;
121         }
122
123         ret = tcgetattr(file_hndl, &tio);
124         if (ret) {
125                 _E("Error[%d]: tcgetattr, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
126                 return -1;
127         }
128         tio.c_cflag = peripheral_uart_br[baud];
129         tio.c_iflag = IGNPAR;
130         tio.c_oflag = 0;
131         tio.c_lflag = 0;
132         tio.c_cc[VMIN] = 1;
133         tio.c_cc[VTIME] = 0;
134
135         uart_flush(file_hndl);
136         ret = tcsetattr(file_hndl, TCSANOW, &tio);
137         if (ret) {
138                 _E("Error[%d]: tcsetattr, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
139                 return -1;
140         }
141
142         return 0;
143 }
144
145 int uart_set_mode(int file_hndl, uart_bytesize_e bytesize, uart_parity_e parity, uart_stopbits_e stopbits)
146 {
147         int ret;
148         struct termios tio;
149
150         _D("file_hndl : %d, bytesize : %d, parity : %d, stopbits : %d", file_hndl, bytesize, parity, stopbits);
151
152         if (!file_hndl) {
153                 _E("Error[%d]: Invalid parameter, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
154                 return -EINVAL;
155         }
156
157         ret = tcgetattr(file_hndl, &tio);
158         if (ret) {
159                 _E("Error[%d]: tcgetattr, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
160                 return -1;
161         }
162
163         /* set byte size */
164         if (bytesize < UART_BYTESIZE_5BIT || bytesize > UART_BYTESIZE_8BIT) {
165                 _E("Error[%d]: Invalid parameter bytesize, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
166                 return -EINVAL;
167         }
168         tio.c_cflag &= ~CSIZE;
169         tio.c_cflag |= byteinfo[bytesize];
170         tio.c_cflag |= (CLOCAL | CREAD);
171
172         /* set parity info */
173         switch (parity) {
174         case UART_PARITY_EVEN:
175                 tio.c_cflag |= PARENB;
176                 tio.c_cflag &= ~PARODD;
177                 break;
178         case UART_PARITY_ODD:
179                 tio.c_cflag |= PARENB;
180                 tio.c_cflag |= PARODD;
181                 break;
182         case UART_PARITY_NONE:
183         default:
184                 tio.c_cflag &= ~PARENB;
185                 tio.c_cflag &= ~PARODD;
186                 break;
187         }
188
189         /* set stop bit */
190         switch (stopbits) {
191         case UART_STOPBITS_1BIT:
192                 tio.c_cflag &= ~CSTOPB;
193                 break;
194         case UART_STOPBITS_2BIT:
195                 tio.c_cflag |= CSTOPB;
196                 break;
197         default:
198                 _E("Error[%d]: Invalid parameter stopbits, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
199                 return -EINVAL;
200         }
201
202         uart_flush(file_hndl);
203         ret = tcsetattr(file_hndl, TCSANOW, &tio);
204         if (ret) {
205                 _E("Error[%d]: tcsetattr, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
206                 return -1;
207         }
208
209         return 0;
210 }
211
212 int uart_set_flowcontrol(int file_hndl, bool xonxoff, bool rtscts)
213 {
214         int ret;
215         struct termios tio;
216
217         _D("file_hndl : %d, xonxoff : %d, rtscts : %d", file_hndl, xonxoff, rtscts);
218
219         if (!file_hndl) {
220                 _E("Error[%d]: Invalid parameter, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
221                 return -EINVAL;
222         }
223
224         ret = tcgetattr(file_hndl, &tio);
225         if (ret) {
226                 _E("Error[%d]: tcgetattr, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
227                 return -1;
228         }
229
230         /* rtscts => 1: rts/cts on, 0: off */
231         if (rtscts)
232                 tio.c_cflag |= CRTSCTS;
233         else
234                 tio.c_cflag &= ~CRTSCTS;
235
236         /* xonxoff => 1: xon/xoff on, 0: off */
237         if (xonxoff)
238                 tio.c_iflag |= (IXON | IXOFF | IXANY);
239         else
240                 tio.c_iflag &= ~(IXON | IXOFF | IXANY);
241
242         ret = tcsetattr(file_hndl, TCSANOW, &tio);
243         if (ret) {
244                 _E("Error[%d]: tcsetattr, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
245                 return -1;
246         }
247
248         return 0;
249 }
250
251 int uart_read(int file_hndl, uint8_t *buf, unsigned int length)
252 {
253         int ret;
254         if (!file_hndl) {
255                 _E("Error[%d]: Invalid parameter, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
256                 return -EINVAL;
257         }
258
259         ret = read(file_hndl, (void *)buf, length);
260         if ((errno != EAGAIN && errno != EINTR) && ret < 0) {
261                 _E("Error[%d]: read, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
262                 return -EIO;
263         }
264
265         return ret;
266 }
267
268 int uart_write(int file_hndl, uint8_t *buf, unsigned int length)
269 {
270         int ret;
271         if (!file_hndl) {
272                 _E("Error[%d]: Invalid parameter, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
273                 return -EINVAL;
274         }
275
276         ret = write(file_hndl, buf, length);
277         if (ret < 0) {
278                 _E("Error[%d]: write, %s--[%d]\n", errno, __FUNCTION__, __LINE__);
279                 return -EIO;
280         }
281
282         return ret;
283 }