1 /*
2 * uart_adapter.c
3 *
4 * linux uart driver adapter.
5 *
6 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19 #include <linux/termios.h>
20 #include <asm/ioctls.h>
21 #include <linux/serial.h>
22 #include <linux/fs.h>
23 #include "device_resource_if.h"
24 #include "hdf_base.h"
25 #include "hdf_log.h"
26 #include "osal_io.h"
27 #include "osal_mem.h"
28 #include "osal_time.h"
29 #include "securec.h"
30 #include "uart_if.h"
31 #include "uart_core.h"
32
33 #define HDF_LOG_TAG hdf_uart_adapter
34 #define UART_NAME_LEN 20
35
36 static char g_driverName[UART_NAME_LEN];
37
UartAdapterInit(struct UartHost * host)38 static int32_t UartAdapterInit(struct UartHost *host)
39 {
40 char name[UART_NAME_LEN] = {0};
41 struct file *fp = NULL;
42 mm_segment_t oldfs;
43
44 if (host == NULL) {
45 return HDF_ERR_INVALID_OBJECT;
46 }
47 if (sprintf_s(name, UART_NAME_LEN - 1, "/dev/%s%d", g_driverName, host->num) < 0) {
48 return HDF_FAILURE;
49 }
50 oldfs = get_fs();
51 set_fs(KERNEL_DS);
52 fp = filp_open(name, O_RDWR | O_NOCTTY | O_NDELAY, 0600); /* 0600 : file mode */
53 if (IS_ERR(fp)) {
54 HDF_LOGE("filp_open %s fail", name);
55 set_fs(oldfs);
56 return HDF_FAILURE;
57 }
58 set_fs(oldfs);
59 host->priv = fp;
60 return HDF_SUCCESS;
61 }
UartAdapterDeInit(struct UartHost * host)62 static int32_t UartAdapterDeInit(struct UartHost *host)
63 {
64 struct file *fp = NULL;
65 mm_segment_t oldfs;
66
67 if (host == NULL) {
68 return HDF_ERR_INVALID_OBJECT;
69 }
70 fp = (struct file *)host->priv;
71 oldfs = get_fs();
72 set_fs(KERNEL_DS);
73 if (!IS_ERR(fp) && fp) {
74 filp_close(fp, NULL);
75 }
76 set_fs(oldfs);
77 host->priv = NULL;
78 return HDF_SUCCESS;
79 }
UartAdapterRead(struct UartHost * host,uint8_t * data,uint32_t size)80 static int32_t UartAdapterRead(struct UartHost *host, uint8_t *data, uint32_t size)
81 {
82 loff_t pos = 0;
83 int ret;
84 struct file *fp = NULL;
85 char __user *p = (__force char __user *)data;
86 mm_segment_t oldfs;
87 uint32_t tmp = 0;
88
89 if (host == NULL || host->priv == NULL || data == NULL || size == 0) {
90 return HDF_ERR_INVALID_OBJECT;
91 }
92
93 fp = (struct file *)host->priv;
94 oldfs = get_fs();
95 set_fs(KERNEL_DS);
96 while (size >= tmp) {
97 ret = vfs_read(fp, p + tmp, 1, &pos);
98 if (ret < 0) {
99 HDF_LOGE("vfs_read fail %d", ret);
100 break;
101 }
102 tmp++;
103 }
104 set_fs(oldfs);
105 return tmp;
106 }
UartAdapterWrite(struct UartHost * host,uint8_t * data,uint32_t size)107 static int32_t UartAdapterWrite(struct UartHost *host, uint8_t *data, uint32_t size)
108 {
109 loff_t pos = 0;
110 int ret;
111 struct file *fp = NULL;
112 char __user *p = (__force char __user *)data;
113 mm_segment_t oldfs;
114
115 if (host == NULL || host->priv == NULL || data == NULL || size == 0) {
116 return HDF_ERR_INVALID_OBJECT;
117 }
118
119 fp = (struct file *)host->priv;
120 oldfs = get_fs();
121 set_fs(KERNEL_DS);
122 ret = vfs_write(fp, p, size, &pos);
123 if (ret < 0) {
124 HDF_LOGE("vfs_write fail %d", ret);
125 set_fs(oldfs);
126 return HDF_FAILURE;
127 }
128 set_fs(oldfs);
129 return HDF_SUCCESS;
130 }
131
UartAdapterIoctlInner(struct file * fp,unsigned cmd,unsigned long arg)132 static int UartAdapterIoctlInner(struct file *fp, unsigned cmd, unsigned long arg)
133 {
134 int ret = HDF_FAILURE;
135 mm_segment_t oldfs;
136
137 if (fp == NULL) {
138 HDF_LOGE("UartAdapterIoctlInner fp null");
139 return HDF_FAILURE;
140 }
141 oldfs = get_fs();
142 set_fs(KERNEL_DS);
143 if (fp->f_op->unlocked_ioctl) {
144 ret = fp->f_op->unlocked_ioctl(fp, cmd, arg);
145 }
146 set_fs(oldfs);
147 return ret;
148 }
149
CflagToBaudRate(unsigned short flag)150 static uint32_t CflagToBaudRate(unsigned short flag)
151 {
152 uint32_t baud;
153
154 switch ((flag | CBAUD)) {
155 case B1800:
156 baud = 1800; /* 1800 : baudrate */
157 break;
158 case B2400:
159 baud = 2400; /* 2400 : baudrate */
160 break;
161 case B4800:
162 baud = 4800; /* 4800 : baudrate */
163 break;
164 case B9600:
165 baud = 9600; /* 9600 : baudrate */
166 break;
167 case B19200:
168 baud = 19200; /* 19200 : baudrate */
169 break;
170 case B38400:
171 baud = 38400; /* 38400 : baudrate */
172 break;
173 case B57600:
174 baud = 57600; /* 57600 : baudrate */
175 break;
176 case B115200:
177 baud = 115200; /* 115200 : baudrate */
178 break;
179 case B230400:
180 baud = 230400; /* 230400: baudrate */
181 break;
182 case B460800:
183 baud = 460800; /* 460800: baudrate */
184 break;
185 case B500000:
186 baud = 500000; /* 500000: baudrate */
187 break;
188 case B576000:
189 baud = 576000; /* 576000: baudrate */
190 break;
191 case B921600:
192 baud = 921600; /* 921600: baudrate */
193 break;
194 default:
195 baud = 9600; /* 9600 : baudrate on default */
196 break;
197 }
198 return baud;
199 }
200
UartAdapterGetBaud(struct UartHost * host,uint32_t * baudRate)201 static int32_t UartAdapterGetBaud(struct UartHost *host, uint32_t *baudRate)
202 {
203 struct termios termios;
204 struct file *fp = NULL;
205
206 if (host == NULL) {
207 return HDF_ERR_INVALID_OBJECT;
208 }
209 fp = (struct file *)host->priv;
210 if (baudRate == NULL) {
211 return HDF_ERR_INVALID_PARAM;
212 }
213 if (UartAdapterIoctlInner(fp, TCGETS, (unsigned long)&termios) < 0) {
214 HDF_LOGE("tcgets fail");
215 return HDF_FAILURE;
216 }
217 *baudRate = CflagToBaudRate(termios.c_cflag);
218 return HDF_SUCCESS;
219 }
220
BaudRateToCflag(uint32_t baudRate)221 static unsigned short BaudRateToCflag(uint32_t baudRate)
222 {
223 unsigned short ret;
224 switch (baudRate) {
225 case 1800: /* 1800 : baudrate */
226 ret = B1800;
227 break;
228 case 2400: /* 2400 : baudrate */
229 ret = B2400;
230 break;
231 case 4800: /* 4800 : baudrate */
232 ret = B4800;
233 break;
234 case 9600: /* 9600 : baudrate */
235 ret = B9600;
236 break;
237 case 19200: /* 19200 : baudrate */
238 ret = B19200;
239 break;
240 case 38400: /* 38400 : baudrate */
241 ret = B38400;
242 break;
243 case 57600: /* 57600 : baudrate */
244 ret = B57600;
245 break;
246 case 115200: /* 115200 : baudrate */
247 ret = B115200;
248 break;
249 case 230400: /* 230400 : baudrate */
250 ret = B230400;
251 break;
252 case 460800: /* 460800 : baudrate */
253 ret = B460800;
254 break;
255 case 500000: /* 500000 : baudrate */
256 ret = B500000;
257 break;
258 case 576000: /* 576000 : baudrate */
259 ret = B576000;
260 break;
261 case 921600: /* 921600 : baudrate */
262 ret = B921600;
263 break;
264 default:
265 ret = B9600;
266 break;
267 }
268 return ret;
269 }
270
UartAdapterSetBaud(struct UartHost * host,uint32_t baudRate)271 static int32_t UartAdapterSetBaud(struct UartHost *host, uint32_t baudRate)
272 {
273 struct termios termios;
274 struct serial_struct serial;
275 struct file *fp = NULL;
276 int ret;
277
278 if (host == NULL) {
279 return HDF_ERR_INVALID_OBJECT;
280 }
281 fp = (struct file *)host->priv;
282
283 if (UartAdapterIoctlInner(fp, TCGETS, (unsigned long)&termios) < 0) {
284 HDF_LOGE("tcgets fail");
285 return HDF_FAILURE;
286 }
287 termios.c_cflag &= ~CBAUD;
288 termios.c_cflag |= BaudRateToCflag(baudRate);
289 termios.c_cc[VMIN] = 0;
290 termios.c_cc[VTIME] = 0;
291 ret = UartAdapterIoctlInner(fp, TCSETS, (unsigned long)&termios);
292 /* Set low latency */
293 if (UartAdapterIoctlInner(fp, TIOCGSERIAL, (unsigned long)&serial) < 0) {
294 HDF_LOGE("tiocgserial fail");
295 return HDF_FAILURE;
296 }
297 serial.flags |= ASYNC_LOW_LATENCY;
298 ret = UartAdapterIoctlInner(fp, TIOCSSERIAL, (unsigned long)&serial);
299 return ret;
300 }
301
CSToAttr(unsigned short cs)302 static unsigned char CSToAttr(unsigned short cs)
303 {
304 unsigned short t = cs & ~CSIZE;
305 if (t == CS7) {
306 return UART_ATTR_DATABIT_7;
307 } else if (t == CS8) {
308 return UART_ATTR_DATABIT_8;
309 } else if (t == CS6) {
310 return UART_ATTR_DATABIT_6;
311 } else if (t == CS5) {
312 return UART_ATTR_DATABIT_5;
313 } else {
314 /* default value */
315 return UART_ATTR_DATABIT_8;
316 }
317 }
318
AttrToCs(unsigned char attr)319 static unsigned short AttrToCs(unsigned char attr)
320 {
321 if (attr == UART_ATTR_DATABIT_7) {
322 return CS7;
323 } else if (attr == UART_ATTR_DATABIT_8) {
324 return CS8;
325 } else if (attr == UART_ATTR_DATABIT_6) {
326 return CS6;
327 } else if (attr == UART_ATTR_DATABIT_5) {
328 return CS5;
329 } else {
330 /* default value */
331 return CS8;
332 }
333 }
334
PariTyToAttr(unsigned short ps)335 static unsigned char PariTyToAttr(unsigned short ps)
336 {
337 if (ps & (PARENB | PARODD)) {
338 return UART_ATTR_PARITY_ODD;
339 } else if (!(ps & PARODD) && (ps & PARENB)) {
340 return UART_ATTR_PARITY_EVEN;
341 } else if (!(ps & (PARENB | PARODD))) {
342 return UART_ATTR_PARITY_NONE;
343 } else {
344 /* default value */
345 return UART_ATTR_PARITY_NONE;
346 }
347 }
348
StopBitToAttr(unsigned short st)349 static unsigned char StopBitToAttr(unsigned short st)
350 {
351 if (!(st & CSTOPB)) {
352 return UART_ATTR_STOPBIT_1;
353 } else if (st & CSTOPB) {
354 return UART_ATTR_STOPBIT_2;
355 } else {
356 /* default value */
357 return UART_ATTR_STOPBIT_1;
358 }
359 }
360
CtsRtsToAttr(unsigned short cr)361 static unsigned char CtsRtsToAttr(unsigned short cr)
362 {
363 if (cr & CRTSCTS) {
364 return UART_ATTR_RTS_EN;
365 }
366 return UART_ATTR_RTS_DIS;
367 }
368
UartAdapterGetAttribute(struct UartHost * host,struct UartAttribute * attribute)369 static int32_t UartAdapterGetAttribute(struct UartHost *host, struct UartAttribute *attribute)
370 {
371 struct termios termios;
372 struct file *fp = NULL;
373 int ret;
374
375 if (host == NULL) {
376 return HDF_ERR_INVALID_OBJECT;
377 }
378 fp = (struct file *)host->priv;
379 if (attribute == NULL) {
380 return HDF_ERR_INVALID_PARAM;
381 }
382 ret = UartAdapterIoctlInner(fp, TCGETS, (unsigned long)&termios);
383 if (ret < 0) {
384 return HDF_FAILURE;
385 }
386 attribute->dataBits = CSToAttr(termios.c_cflag);
387 attribute->parity = PariTyToAttr(termios.c_cflag);
388 attribute->stopBits = StopBitToAttr(termios.c_cflag);
389 attribute->cts = CtsRtsToAttr(termios.c_cflag);
390 attribute->rts = CtsRtsToAttr(termios.c_cflag);
391 return HDF_SUCCESS;
392 }
UartAdapterSetAttribute(struct UartHost * host,struct UartAttribute * attribute)393 static int32_t UartAdapterSetAttribute(struct UartHost *host, struct UartAttribute *attribute)
394 {
395 struct termios termios;
396 struct file *fp = NULL;
397 int ret;
398
399 if (host == NULL) {
400 return HDF_ERR_INVALID_OBJECT;
401 }
402 fp = (struct file *)host->priv;
403 if (attribute == NULL) {
404 return HDF_ERR_INVALID_PARAM;
405 }
406 ret = UartAdapterIoctlInner(fp, TCGETS, (unsigned long)&termios);
407 if (ret < 0) {
408 return HDF_FAILURE;
409 }
410 termios.c_cflag |= CLOCAL | CREAD;
411 termios.c_cflag &= ~CSIZE;
412 termios.c_cflag |= AttrToCs(attribute->dataBits);
413 if (attribute->cts || attribute->rts) {
414 termios.c_cflag |= CRTSCTS;
415 } else {
416 termios.c_cflag &= ~CRTSCTS;
417 }
418 if (attribute->parity == UART_ATTR_PARITY_ODD) {
419 termios.c_cflag |= (PARODD | PARENB);
420 } else if (attribute->parity == UART_ATTR_PARITY_EVEN) {
421 termios.c_cflag |= PARENB;
422 termios.c_cflag &= ~PARODD;
423 } else if (attribute->parity == UART_ATTR_PARITY_NONE) {
424 termios.c_cflag &= ~(PARENB | PARODD);
425 } else { /* default value */
426 termios.c_cflag &= ~(PARENB | PARODD);
427 }
428 if (attribute->stopBits == UART_ATTR_STOPBIT_1) {
429 termios.c_cflag &= ~CSTOPB;
430 } else if (attribute->stopBits == UART_ATTR_STOPBIT_2) {
431 termios.c_cflag |= CSTOPB;
432 } else {
433 /* default value */
434 termios.c_cflag &= ~CSTOPB;
435 }
436 ret = UartAdapterIoctlInner(fp, TCSETS, (unsigned long)&termios);
437 return ret;
438 }
439
UartAdapterSetTransMode(struct UartHost * host,enum UartTransMode mode)440 static int32_t UartAdapterSetTransMode(struct UartHost *host, enum UartTransMode mode)
441 {
442 (void)host;
443 (void)mode;
444 return HDF_SUCCESS;
445 }
446
447 static struct UartHostMethod g_uartHostMethod = {
448 .Init = UartAdapterInit,
449 .Deinit = UartAdapterDeInit,
450 .Read = UartAdapterRead,
451 .Write = UartAdapterWrite,
452 .SetBaud = UartAdapterSetBaud,
453 .GetBaud = UartAdapterGetBaud,
454 .SetAttribute = UartAdapterSetAttribute,
455 .GetAttribute = UartAdapterGetAttribute,
456 .SetTransMode = UartAdapterSetTransMode,
457 };
458
HdfUartBind(struct HdfDeviceObject * obj)459 static int32_t HdfUartBind(struct HdfDeviceObject *obj)
460 {
461 HDF_LOGI("%s: entry", __func__);
462 if (obj == NULL) {
463 return HDF_ERR_INVALID_OBJECT;
464 }
465 return (UartHostCreate(obj) == NULL) ? HDF_FAILURE : HDF_SUCCESS;
466 }
467
HdfUartInit(struct HdfDeviceObject * obj)468 static int32_t HdfUartInit(struct HdfDeviceObject *obj)
469 {
470 int32_t ret;
471 struct DeviceResourceIface *iface = NULL;
472 struct UartHost *host = NULL;
473 const char *drName = NULL;
474
475 HDF_LOGI("%s: entry", __func__);
476 if (obj == NULL) {
477 HDF_LOGE("%s: device is null", __func__);
478 return HDF_ERR_INVALID_OBJECT;
479 }
480 host = UartHostFromDevice(obj);
481 if (host == NULL) {
482 HDF_LOGE("%s: host is null", __func__);
483 return HDF_FAILURE;
484 }
485 iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
486 if (iface == NULL || iface->GetUint32 == NULL) {
487 HDF_LOGE("%s: face is invalid", __func__);
488 return HDF_FAILURE;
489 }
490
491 if (iface->GetUint32(obj->property, "num", &host->num, 0) != HDF_SUCCESS) {
492 HDF_LOGE("%s: read num fail", __func__);
493 return HDF_FAILURE;
494 }
495 if (iface->GetString(obj->property, "driver_name", &drName, "ttyAMA") != HDF_SUCCESS) {
496 HDF_LOGE("%s: read driver_name fail", __func__);
497 return HDF_FAILURE;
498 }
499 g_driverName[UART_NAME_LEN - 1] = 0;
500 ret = memcpy_s(g_driverName, UART_NAME_LEN - 1, drName, strlen(drName));
501 if (ret != EOK) {
502 return HDF_FAILURE;
503 }
504 host->method = &g_uartHostMethod;
505 return HDF_SUCCESS;
506 }
507
HdfUartRelease(struct HdfDeviceObject * obj)508 static void HdfUartRelease(struct HdfDeviceObject *obj)
509 {
510 struct UartHost *host = NULL;
511
512 HDF_LOGI("%s: entry", __func__);
513 if (obj == NULL) {
514 HDF_LOGE("%s: obj is null", __func__);
515 return;
516 }
517 host = UartHostFromDevice(obj);
518 UartHostDestroy(host);
519 }
520
521 struct HdfDriverEntry g_hdfUartchdog = {
522 .moduleVersion = 1,
523 .moduleName = "HDF_PLATFORM_UART",
524 .Bind = HdfUartBind,
525 .Init = HdfUartInit,
526 .Release = HdfUartRelease,
527 };
528
529 HDF_INIT(g_hdfUartchdog);
530