1 /*
2  * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3  */
4 #include <errno.h>
5 #include <sys/types.h>
6 #include <unistd.h>
7 #include <drivers/bug.h>
8 #include <drivers/u_ld.h>
9 #include <drivers/char/u_device.h>
10 #include <drivers/char/u_cdev_msg.h>
11 #include <devicevfs/devicevfs_rpc.h>
12 
13 #ifdef USER_SPACE_DRIVER
14 #include <rpc.h>
15 
16 #define UDRIVER_RPC_BUFFER_SIZE (1024)
17 #define UDRIVER_RPC_NAME_FORMAT "rpc-%d-main"
18 
19 static char g_main_rpc_name[16] = {0};
20 static int g_udriver_rpc_handle = 0;
21 static char g_main_rpc_buf[UDRIVER_RPC_BUFFER_SIZE] = {0};
22 static int _cdev_fops_handler(int crpc_handle, u_cdev_msg_t *p_msg);
23 static int _loop_msg_handler(int crpc_handle, u_cdev_msg_t *p_msg);
24 
25 static u_cdev_msg_handler _cdev_msg_handler[CDEV_MSG_MAX] = {
26     [CDEV_MSG_FOPS] = _cdev_fops_handler,
27     [CDEV_MSG_LOOP] = _loop_msg_handler,
28 };
29 
30 
_loop_msg_handler(int crpc_handle,u_cdev_msg_t * p_msg)31 int _loop_msg_handler(int crpc_handle, u_cdev_msg_t *p_msg) {
32     ddkc_info("%s\r\n", __func__);
33     return 0;
34 }
35 
_cdev_fops_handler(int reply_handle,u_cdev_msg_t * p_msg)36 int _cdev_fops_handler(int reply_handle, u_cdev_msg_t *p_msg) {
37     int ret = 0;
38     u_cdev_msg_ie_t *ie = NULL;
39     u_fops_arg_u *parg = NULL;
40     if (!p_msg) {
41         return -EINVAL;
42     }
43     ie = p_msg->v;
44 
45     ddkc_dbg("sizeof(u_cdev_msg_t):%d, sizeof(u_cdev_msg_id_e):%d, sizeof(unsigned short):%d, sizeof(ie->t):%d, ie->t:%d\r\n",
46            sizeof(u_cdev_msg_t), sizeof(u_cdev_msg_id_e), sizeof(unsigned short),
47            sizeof(ie->t), ie->t);
48 
49     switch(ie->t) {
50         case FOPS_OPEN:
51             parg = (u_fops_arg_u *)ie->v;
52             ret = u_device_rpc_open(parg, reply_handle);
53             ddkc_dbg("open %s return %d\r\n", parg->open.path, ret);
54             break;
55         case FOPS_CLOSE:
56             parg = (u_fops_arg_u *)ie->v;
57             ret = u_device_rpc_close(parg, reply_handle);
58             ddkc_dbg("close return %d\r\n", ret);
59             break;
60         default:
61             ddkc_err("invalid file operation:%d, ignore\r\n", ie->t);
62             ret = -EINVAL;
63             break;
64     }
65 
66     return ret;
67 }
68 
main_thread_req_arrived(struct aos_parcel_t * pkt)69 void main_thread_req_arrived(struct aos_parcel_t *pkt) {
70     int ret = 0;
71     int reply_handle = 0;
72     u_cdev_msg_t *p_msg = NULL;
73     size_t len = sizeof(int);
74 
75     if (!pkt || !pkt->max_size) {
76         ddkc_err("invalid pkt:%p or max_size:%d\r\n", pkt, pkt ? pkt->max_size : 0);
77         return;
78     }
79 
80     ddkc_dbg("pkt->max_size:%x\r\n", pkt->max_size);
81     aos_parcel_get(AP_UVARINT, &reply_handle, &len, pkt);
82     ddkc_dbg("reply_handle:%x\r\n", reply_handle);
83 
84     BUG_ON_MSG((pkt->max_size > sizeof(g_main_rpc_buf)),
85                "rpc max_size:%d > main thread rpc buf len:%d",
86                pkt->max_size, sizeof(g_main_rpc_buf));
87 
88     len = pkt->max_size;
89     ddkc_dbg("max_size:%x\r\n", len);
90     ret = aos_parcel_get(AP_BUF, g_main_rpc_buf, &len, pkt);
91     if (ret < 0 || len <= 0) {
92         ddkc_err("rpc receive data failed, ret:%d\r\n", ret);
93         // TODO: how to handle this case?
94         return;
95     }
96     p_msg = (u_cdev_msg_t *)g_main_rpc_buf;
97     BUG_ON_MSG((p_msg->t >= CDEV_MSG_MAX),
98                 "p_msg->t:%d > CDEV_MSG_MAX:%d\r\n", p_msg->t, CDEV_MSG_MAX);
99 #if 0
100     for (int i = 0;i < len; i++)
101         ddkc_err("i:%d - 0x%x\n", i, g_main_rpc_buf[i]);
102 #endif
103     ret = (_cdev_msg_handler[p_msg->t](reply_handle, p_msg));
104     if (ret) {
105         ddkc_err("rpc msg handle failed, ret:%d\r\n", ret);
106     }
107 
108     return;
109 }
110 
111 
main_thread_event_cb(int eid,void * event)112 void main_thread_event_cb(int eid, void * event) {
113     struct aos_revt_param_t *param = (struct aos_revt_param_t *)event;
114     int reason = *(int *)param->param;
115 
116     if (eid != RPC_EID_STOP) {
117         ddkc_warn("eid:%d, reason:%d, closing rpc service - handle:0x%x\r\n", eid, reason, param->srpc_handle);
118         aos_rpc_close(param->srpc_handle);
119     } else
120         ddkc_info("eid:%d, reason:%d\r\n", eid, reason);
121 
122     return;
123 }
124 #endif
125 
126 /**
127  * this is the only driver entry API, when a driver is selected, must call this API in proper place
128  *
129  * @string process identification
130  *
131  * @return 0 for success; negative error number for failure
132  */
u_driver_entry(char * string)133 int u_driver_entry(char* string) {
134     int ret = -1;
135 
136 #ifdef USER_SPACE_DRIVER
137     ddkc_dbg("%s uspace mode:%d\r\n", __func__, 1);
138 
139     /* register main thread service into PM */
140     ret = snprintf(g_main_rpc_name, sizeof(g_main_rpc_name), UDRIVER_RPC_NAME_FORMAT, getpid());
141     if (ret <= 0) {
142         ddkc_err("snprintf for main rpc name failed\r\n");
143         return ret;
144     }
145 
146     ret = aos_rpc_regist(g_main_rpc_name, UDRIVER_RPC_BUFFER_SIZE, &g_udriver_rpc_handle);
147     if (ret) {
148         ddkc_err("register main rpc service[%s] failed, ret:%d\r\n", g_main_rpc_name, ret);
149         return ret;
150     }
151 
152     ddkc_dbg("register main rpc main service[%s] succeed, handle:0x%x\r\n",
153               g_main_rpc_name, g_udriver_rpc_handle);
154 
155     ret = aos_rpc_run(g_udriver_rpc_handle, main_thread_req_arrived, main_thread_event_cb);
156     if (ret) {
157         ddkc_err("aos_rpc_run on service:%s fails, ret:%d\r\n", g_main_rpc_name, ret);
158         goto error;
159     }
160 #else
161     ddkc_info("%s uspace mode:%d\r\n", __func__, 0);
162 #endif
163 
164 #if (AOS_COMP_IRQ > 0)
165     extern int aos_irq_system_init(void);
166     ret = aos_irq_system_init();
167     if (ret) {
168         ddkc_err("irq system init failed, ret:%d\r\n", ret);
169         goto error;
170     }
171 #endif
172 
173     ret = _os_driver_entry();
174     if (ret) {
175         ddkc_err("_os_driver_entry error, ret:%d\r\n", ret);
176         goto error;
177     }
178 
179     return 0;
180 
181 error:
182 #ifdef USER_SPACE_DRIVER
183     if (g_udriver_rpc_handle) {
184         aos_rpc_close(g_udriver_rpc_handle);
185         g_udriver_rpc_handle = 0;
186     }
187 #if 0
188     u_irq_system_deinit();
189 #endif
190 
191 #endif
192     return ret;
193 }
194 
195 /**
196  * this is the only driver entry API, when a driver is selected, must call this API in proper place
197  *
198  * @string process identification
199  *
200  * @return 0 for success; negative error number for failure
201  */
u_post_driver_entry(char * string)202 int u_post_driver_entry(char* string) {
203     int ret = -1;
204     ret = _os_post_driver_entry();
205 
206     return ret;
207 }
208 
209 /**
210  *
211  * @return main thread's RPC service name
212  */
u_driver_get_main_service_name(void)213 char *u_driver_get_main_service_name(void) {
214 #ifdef USER_SPACE_DRIVER
215     return g_main_rpc_name;
216 #else
217     return NULL;
218 #endif
219 }
220