• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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