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