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