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