1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2023-12-11     Shell        init ver.
9  */
10 
11 #define DBG_TAG "lwp.tty"
12 #define DBG_LVL DBG_INFO
13 #include <rtdbg.h>
14 
15 #include "tty_config.h"
16 #include "tty_internal.h"
17 #include "bsd_porting.h"
18 #include "terminal.h"
19 
20 #include <fcntl.h>
21 
22 #ifdef RT_USING_DEVICE_OPS
23 const static struct rt_device_ops cons_rtdev_ops;
24 #endif
25 
26 struct backend_entry
27 {
28     rt_list_t bakend_list_node;
29     int prio;
30 
31     rt_device_t bakdev;
32 };
33 
34 static rt_list_t _bakend_list;
35 
_bent_enqueue(struct backend_entry * bent)36 static void _bent_enqueue(struct backend_entry *bent)
37 {
38     struct backend_entry *idx;
39     rt_bool_t inserted = RT_FALSE;
40     rt_list_for_each_entry(idx, &_bakend_list, bakend_list_node)
41     {
42         if (idx->prio < bent->prio)
43         {
44             rt_list_insert_before(&idx->bakend_list_node, &bent->bakend_list_node);
45             inserted = RT_TRUE;
46             break;
47         }
48     }
49 
50     if (!inserted)
51         rt_list_insert_after(&_bakend_list, &bent->bakend_list_node);
52     return ;
53 }
54 
lwp_console_register_backend(struct rt_device * bakdev,int prio)55 rt_err_t lwp_console_register_backend(struct rt_device *bakdev, int prio)
56 {
57     rt_err_t ret = RT_EOK;
58     struct backend_entry *bent;
59     bent = rt_malloc(sizeof(struct backend_entry));
60     if (bent)
61     {
62         rt_list_init(&bent->bakend_list_node);
63         bent->prio = prio;
64         bent->bakdev = bakdev;
65 
66         _bent_enqueue(bent);
67     }
68     else
69     {
70         ret = -RT_ENOMEM;
71     }
72     return ret;
73 }
74 
75 static struct rt_device _cons_rtdev;
76 
fops_open(struct dfs_file * file)77 static int fops_open(struct dfs_file *file)
78 {
79     return -EINVAL;
80 }
81 
82 static struct dfs_file_ops _cons_fops = {
83     .open = fops_open,
84 };
85 
_cons_readlink(struct rt_device * dev,char * buf,int len)86 static rt_err_t _cons_readlink(struct rt_device *dev, char *buf, int len)
87 {
88     int rc = -EIO;
89     struct backend_entry *bent;
90     if (!rt_list_isempty(&_bakend_list))
91     {
92         bent = rt_list_first_entry(&_bakend_list, struct backend_entry, bakend_list_node);
93         if (bent)
94         {
95             RT_ASSERT(bent->bakdev);
96             strncpy(buf, bent->bakdev->parent.name, MIN(len, RT_NAME_MAX));
97             LOG_D("%s: backend device %s", __func__, buf);
98             rc = 0;
99         }
100     }
101 
102     if (rc != 0)
103     {
104         LOG_W("%s: No backend device", __func__);
105     }
106 
107     return rc;
108 }
109 
_cons_init(void)110 static int _cons_init(void)
111 {
112     rt_err_t rc;
113 
114     rt_list_init(&_bakend_list);
115 
116     /* setup system level device */
117     _cons_rtdev.type = RT_Device_Class_Char;
118     _cons_rtdev.ops = &cons_rtdev_ops;
119     rc = rt_device_register(&_cons_rtdev, "console", RT_DEVICE_FLAG_DYNAMIC);
120     if (rc == RT_EOK)
121     {
122         _cons_rtdev.readlink = &_cons_readlink;
123         _cons_rtdev.fops = &_cons_fops;
124     }
125 
126     return rc;
127 }
128 INIT_DEVICE_EXPORT(_cons_init);
129