1 /*
2 * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3 */
4
5 #ifdef USER_SPACE_DRIVER
6 #include <rpc.h>
7 #endif
8
9 #include "aos/vfs.h"
10 #include "aos/list.h"
11
12 #include <devicevfs/devicevfs.h>
13 #include <drivers/char/u_cdev_msg.h>
14 #include <drivers/u_mode.h>
15
16 #define MAJOR_OFFSET 120
17 #define NODE_PREFIX "/dev/"
18
19 static dlist_t g_fnode_valid_list;
20 static dlist_t g_subsys_dev_list;
21 typedef struct file_node {
22 file_t f; // created when OPEN RPC request arrives
23 void *dev_n;
24 dlist_t node;
25 dlist_t valid;
26 } file_node_t;
27
28 typedef struct subsys_dev_node {
29 dlist_t n;
30 struct subsys_dev dev;
31 struct u_platform_device *pdev;
32 struct u_platform_driver *pdrv;
33 subsys_file_ops_t *fops;
34 dlist_t file_head;
35 int rpc_handle;
36 int ref_cnt;
37 bool rpc_run;
38 char *rpc_name;
39 char *path_name;
40 /* real_open was used only when delay_init, which is member of struct subsys_dev, is set to true */
41 int (*real_open)(inode_t *node, file_t *fp);
42 int (*real_init)(struct u_platform_device *pdev);
43 int (*real_probe)(struct u_platform_device *pdev);
44
45 } subsys_dev_node_t;
46
47 #ifdef USER_SPACE_DRIVER
48
49 #define UDRIVER_RCP_NAME_MAX_LEN (AOS_RPC_NAME_MAX_SIZE)
50 #define UDRIVER_RPC_NAME_FORMAT "rpc-%d-%s"
51
52 extern char *u_driver_get_main_service_name(void);
53
54
55
56 static int _cdev_fops_handler(int crpc_handle, u_cdev_msg_t *p_msg);
57 static int _loop_msg_handler(int crpc_handle, u_cdev_msg_t *p_msg);
58
59 static u_cdev_msg_handler _cdev_msg_handler[CDEV_MSG_MAX] = {
60 [CDEV_MSG_FOPS] = _cdev_fops_handler,
61 [CDEV_MSG_LOOP] = _loop_msg_handler,
62 };
63
64
65 /**
66 * check whether fnode is valid or not
67 * to prevent client send invalid RPC request with cached data
68 *
69 * @param fnode - pointer to target file_node_t
70 * @return true if it is valid; false if it is invalid
71 */
_is_valid_fnode(file_node_t * fnode)72 static bool _is_valid_fnode(file_node_t *fnode) {
73 file_node_t *n = NULL;
74 dlist_t *pos = NULL;
75 dlist_t *tmp = NULL;
76
77 dlist_for_each_safe(pos, tmp, &g_fnode_valid_list)
78 {
79 n = aos_container_of(pos, file_node_t, valid);
80 if (n == fnode)
81 return true;
82 }
83 return false;
84 }
85
86 /**
87 * char device file operation handler
88 *
89 * @param crpc_handle - RPC client's handle
90 * @param p_msg - pointer to operation struct
91 *
92 * @return 0 for success; negative for failure
93 */
_cdev_fops_handler(int crpc_handle,u_cdev_msg_t * p_msg)94 int _cdev_fops_handler(int crpc_handle, u_cdev_msg_t *p_msg) {
95 int ret = 0;
96 u_cdev_msg_ie_t *ie = NULL;
97 struct subsys_dev_node *dev_n = NULL;
98 subsys_file_ops_t *fops = NULL;
99 u_fops_arg_u *fops_arg = NULL;
100 file_t *fp = NULL;
101 file_node_t *fnode = NULL;
102 inode_t *node = NULL;
103 u_fops_result_u res;
104
105 if (!p_msg) {
106 return -EINVAL;
107 }
108 ie = p_msg->v;
109
110 fops_arg = (u_fops_arg_u *)ie->v;
111
112 /* fnode is put into open.farg in u_device_rpc_open */
113 fnode = (file_node_t *)fops_arg->priv.farg;
114 ddkc_dbg("farg:%p\r\n", fnode);
115
116 if (!fnode) {
117 ret = -EINVAL;
118 ddkc_err("fops_arg->priv.arg is NULL, ignore\r\n");
119 goto err;
120 }
121
122 // do fnode's validation
123 if (!_is_valid_fnode(fnode)) {
124 // this case should NEVER happen, so omit this check
125 BUG_ON_MSG(1, "invalid fnode:%p from rpc client:0x%x\r\n", fnode, crpc_handle);
126 return -EINVAL;
127 }
128
129 dev_n = fnode->dev_n;
130
131 if (ie->t <= FOPS_OPEN || ie->t >= FOPS_MAX) {
132 ret = -EINVAL;
133 ddkc_err("invalid file operation:%d, ignore, ret:%d\r\n", ie->t, ret);
134 goto err;
135 }
136
137 memset(&res, 0, sizeof(res));
138
139 fp = &fnode->f;
140 node = fp->node;
141 fops = (subsys_file_ops_t *)node->ops.i_ops;
142
143 switch(ie->t) {
144 case FOPS_READ:
145 {
146 ssize_t r_len = 0;
147 u_fops_result_u *p_res = malloc(sizeof(*p_res) + fops_arg->read.len);
148
149 if (!p_res) {
150 ddkc_err("%s - malloc for u_fops_result_u failed\r\n", dev_n->rpc_name);
151 ret = -ENOMEM;
152 goto err;
153 }
154
155 memset(p_res, 0, sizeof(*p_res) + fops_arg->read.len);
156
157 /* call device's read cb */
158 r_len = fops->read(fp, p_res->read.data, fops_arg->read.len);
159 if (r_len < 0) {
160 ret = r_len;
161 ddkc_warn("fops->read ret:%d\r\n", r_len);
162 free(p_res);
163 goto err;
164 }
165 p_res->read.status = 0;
166 p_res->read.len = r_len;
167
168 ddkc_dbg("FOPS_READ, status:%d, len:%d, total len:%d, sizeof(u_fops_result_u):%d\r\n",
169 p_res->priv.status, p_res->read.len, sizeof(*p_res) + r_len, sizeof(u_fops_result_u));
170 #if 0
171 for (int i = 0; i < sizeof(*p_res) + r_len; i++) {
172 ddkc_info("%d - 0x%x\r\n", i, *((char *)p_res + i) & 0xff);
173 }
174 #endif
175 ret = aos_rpc_resp(crpc_handle, 1, sizeof(*p_res) + r_len, p_res);
176 if (ret)
177 ddkc_err("%s - aos_rpc_resp to 0x%x failed, ret:0x%x\r\n", dev_n->rpc_name, crpc_handle, ret);
178 free(p_res);
179 return ret;
180 }
181 break;
182
183 case FOPS_WRITE:
184 {
185 ssize_t w_len = 0;
186
187 ddkc_dbg("%s - fops->write++\r\n", __func__);
188
189 /* call device's write cb */
190 w_len = fops->write(fp, fops_arg->write.buf, fops_arg->write.len);
191 if (w_len < 0) {
192 ret = w_len;
193 ddkc_warn("%s - fops->write ret:%d\r\n", dev_n->rpc_name, w_len);
194 goto err;
195 }
196 res.write.status = 0;
197 res.write.len = w_len;
198
199 ddkc_dbg("FOPS_WRITE, status:%d, len:%d\r\n", res.write.status, res.write.len);
200 }
201 break;
202
203 case FOPS_IOCTL:
204 /* call device's ioctl cb */
205 ret = fops->ioctl(fp, fops_arg->ioctl.cmd, fops_arg->ioctl.arg);
206 if (ret < 0) {
207 ddkc_warn("%s - fops->ioctl ret:%d\r\n", dev_n->rpc_name, ret);
208 goto err;
209 }
210 res.ioctl.status = ret;
211
212 ddkc_dbg("FOPS_IOCTL, status:%d\r\n", res.ioctl.status);
213 break;
214
215 case FOPS_POLL:
216 //TODO: to be implemented
217 ret = -EIO;
218 res.poll.status = ret;
219 ddkc_err("%s - poll ops is not implemented,ret:%d\r\n", dev_n->rpc_name, ret);
220 break;
221
222 case FOPS_LSEEK:
223 /* call device's lseek cb */
224 ret = fops->lseek(fp, fops_arg->lseek.off, fops_arg->lseek.whence);
225 if (ret < 0) {
226 ddkc_warn("%s - fops->seek ret:%d\r\n", dev_n->rpc_name, ret);
227 }
228 res.lseek.off = ret;
229 res.lseek.status = 0;
230 ddkc_dbg("FOPS_LSEEK, status:%d, offset:%lld\r\n", res.lseek.status, res.lseek.off);
231 break;
232
233 case FOPS_CLOSE:
234 // close is not handled here, it is handled in main rpc thread
235 ret = -EIO;
236 res.close.status = ret;
237 ddkc_err("%s - close ops is not implemented,ret:%d\r\n", dev_n->rpc_name, ret);
238 break;
239
240 default:
241 ret = -EINVAL;
242 res.priv.status = ret;
243 ddkc_err("%s - fops invalid ops id:%d\r\n", dev_n->rpc_name, ie->t);
244 break;
245 }
246
247 /* send response back to rpc client
248 * no matter actual read/write/ioctl/poll/select is done or not, response is necessary
249 * */
250 ret = aos_rpc_resp(crpc_handle, 1, sizeof(res), &res);
251 if (ret)
252 ddkc_err("%s - aos_rpc_resp to 0x%x failed, ret:0x%x\r\n", dev_n->rpc_name, crpc_handle, ret);
253
254 return ret;
255
256 err:
257 /* send error indication back to rpc client */
258 res.priv.status = ret;
259
260 ret = aos_rpc_resp(crpc_handle, 1, sizeof(res), &res);
261 if (ret)
262 ddkc_err("aos_rpc_resp to 0x%x failed, ret:0x%x\r\n", crpc_handle, ret);
263
264 return ret;
265 }
266
267 /**
268 * heartbeat message handler - for rpc service active detection
269 *
270 * @param crpc_handle - remote client's rpc handle
271 * @param p_msg - pointer to the message
272 * @return
273 */
_loop_msg_handler(int crpc_handle,u_cdev_msg_t * p_msg)274 int _loop_msg_handler(int crpc_handle, u_cdev_msg_t *p_msg) {
275 int ret = 0;
276
277 ret = aos_rpc_resp(crpc_handle, 1, 1, -1);
278 if (ret) {
279 ddkc_warn("loop msg handler aos_rpc_resp failed, ret:%d\r\n", ret);
280 }
281 ddkc_warn("loop msg handler is not implemented yet\r\n");
282
283 return 0;
284 }
285
286
287 /**
288 * device rpc message handler
289 * get remote rpc client's handle and receive all contents in this RPC transaction
290 * parse the contents' pointer to _cdev_msg_handler for message dispatch
291 *
292 * @param pkt - rpc message packet
293 */
u_device_rpc_msg_arrived(struct aos_parcel_t * pkt)294 void u_device_rpc_msg_arrived(struct aos_parcel_t *pkt) {
295 int ret = 0;
296 size_t len = 0;
297 int reply_handle = 0;
298 char *buf = NULL;
299 u_cdev_msg_t *p_msg = NULL;
300
301 ddkc_dbg("rpc pkt arrived\r\n");
302
303 if (!pkt || !pkt->max_size) {
304 ddkc_err("invalid pkt:%p or max_size:%d\r\n", pkt, pkt ? pkt->max_size : 0);
305 return;
306 }
307 len = sizeof(int);
308
309 ddkc_dbg("pkt->max_size:%x\r\n", pkt->max_size);
310 aos_parcel_get(AP_UVARINT, &reply_handle, &len, pkt);
311 ddkc_dbg("reply_handle:%x\r\n", reply_handle);
312
313 len = pkt->max_size;
314 ddkc_dbg("max_size:%x\r\n", len);
315 buf = malloc(len);
316 if (!buf) {
317 ddkc_err("malloc buf for rpc msg failed\r\n");
318 return;
319 }
320
321 /* get RPC message's content in one RPC call with AP_ALL flag */
322 ret = aos_parcel_get(AP_ALL, buf, &len, pkt);
323 if (ret < 0 || len <= 0) {
324 ddkc_err("rpc receive data failed, ret:%d\r\n", ret);
325 // TODO: ethan - how to handle this case?
326 free(buf);
327 return;
328 }
329 p_msg = (u_cdev_msg_t *)buf;
330 if (p_msg->t >= CDEV_MSG_MAX) {
331 for (int i = 0; i < len; i++) {
332 ddkc_info("%d - 0x%x\r\n", i, buf[i] & 0xff);
333 }
334 }
335 BUG_ON_MSG((p_msg->t >= CDEV_MSG_MAX),
336 "p_msg->t:%d > CDEV_MSG_MAX:%d\r\n", p_msg->t, CDEV_MSG_MAX);
337
338 if (p_msg->t < CDEV_MSG_MAX)
339 /* parse rpc message into _cdev_msg_handler for message dispatch */
340 ret = (_cdev_msg_handler[p_msg->t](reply_handle, p_msg));
341 else {
342 u_fops_result_u res;
343
344 res.priv.status = -EINVAL;
345 ret = aos_rpc_resp(reply_handle, 1, sizeof(res), &res);
346 if (ret)
347 ddkc_err("aos_rpc_resp to 0x%x failed, ret:0x%x\r\n", reply_handle, ret);
348 }
349
350 free(buf);
351 buf = NULL;
352
353 return;
354 }
355
356 /**
357 * rpc service event handler
358 * @param eid - error id, RPC_EID_STOP is rpc service stopped event id
359 * @param event - pointer to aos_revt_param_t
360 */
u_device_rpc_event_cb(int eid,void * event)361 void u_device_rpc_event_cb(int eid, void * event) {
362 struct aos_revt_param_t *param = (struct aos_revt_param_t *)event;
363 int reason = *(int *)param->param;
364
365 if (eid != RPC_EID_STOP) {
366 ddkc_warn("eid:%d, reason:%d, closing rpc service - handle:0x%x\r\n", eid, reason, param->srpc_handle);
367 aos_rpc_close(param->srpc_handle);
368 } else
369 ddkc_dbg("eid:%d, reason:%d\r\n", eid, reason);
370
371 return;
372 }
373
374 /**
375 *
376 * open RPC message handler, called when OPEN rpc message arrived in main rpc service's handler
377 *
378 * @param parg - pointer to u_fops_arg_u
379 * @param crpc_handle - rpc client's handle,
380 * response should be send to rpc client no matter this operation succeed or not
381 *
382 * @return 0 for success; negative for failure
383 */
u_device_rpc_open(u_fops_arg_u * parg,int crpc_handle)384 int u_device_rpc_open(u_fops_arg_u *parg, int crpc_handle) {
385 int ret = 0;
386 int flag = 0;
387 dlist_t *pos = NULL;
388 dlist_t *tmp = NULL;
389 file_t *fp = NULL;
390 inode_t *node = NULL;
391 file_node_t *fnode = NULL;
392 struct subsys_dev_node *dev_n = NULL;
393 subsys_file_ops_t *fops = NULL;
394 u_fops_result_u res;
395 char *path_name = NULL;
396
397 if (!parg || !crpc_handle) {
398 ddkc_err("invalid rpc handle:%d or parg:%p\r\n", crpc_handle, parg);
399 ret = -EINVAL;
400 goto err;
401 }
402 memset(&res, 0, sizeof(res));
403 // MUST call aos_rpc_resp to send RPC reply to client, no matter open success or fail
404
405 path_name = parg->open.path;
406 flag = parg->open.flags;
407
408 // search target device in g_subsys_dev_list
409 dlist_for_each_safe(pos, tmp, &g_subsys_dev_list)
410 {
411 dev_n = aos_container_of(pos, subsys_dev_node_t, n);
412 if (!strcmp(dev_n->path_name, path_name))
413 break;
414 dev_n = NULL;
415 }
416
417 if (!dev_n) {
418 ddkc_err("device node not found for %s\r\n", path_name);
419 ret = -ENODEV;
420 goto err;
421 }
422 ddkc_dbg("device node:%p found for %s\r\n", dev_n, path_name);
423
424 if (!dlist_empty(&dev_n->file_head)) {
425 ddkc_warn("device node:%s is already opened\r\n", path_name);
426 // concurrent operation by multiple processes is handled here
427 // concurrent operation by multiple threads in single process is handled in VFS
428 }
429 ddkc_dbg("setting up for new fd\r\n");
430
431 // set up new fd for each open RPC request to cover concurrent multiple open operation scenarios
432 fnode = malloc(sizeof(file_node_t));
433 node = malloc(sizeof(inode_t));
434 if (!fnode || !node) {
435 ddkc_err("malloc for file failed, fnode:%p, node:%p\n", fnode, node);
436 ret = -ENOMEM;
437 goto err;
438 }
439 dlist_init(&fnode->node);
440 dlist_init(&fnode->valid);
441
442 fnode->dev_n = NULL;
443 fp = &fnode->f;
444 memset(fp, 0, sizeof(file_t));
445 memset(node, 0, sizeof(inode_t));
446
447 fp->node = node;
448 node->i_arg = dev_n->dev.user_data;
449 node->i_name = dev_n->path_name;
450 node->ops.i_ops = dev_n->fops;
451 node->i_flags = flag;
452
453 fops = (subsys_file_ops_t *)node->ops.i_ops;
454 if (!fops || !(fops->open)) {
455 ddkc_err("invalid fops:%p, or open:%p\n", fops, fops ? fops->open : NULL);
456 goto err;
457 }
458
459 /* rpc service for device node might be started already */
460 if (!dev_n->rpc_run) {
461 ddkc_info("start rpc service named:%s, handle:0x%x\r\n", dev_n->rpc_name, dev_n->rpc_handle);
462 ret = aos_rpc_run(dev_n->rpc_handle, u_device_rpc_msg_arrived, u_device_rpc_event_cb);
463 if (ret) {
464 ddkc_err("aos_rpc_run on service:%s fails, ret:%d\r\n", dev_n->rpc_name, ret);
465 goto err;
466 }
467 dev_n->rpc_run = true;
468 } else {
469 ddkc_info("rpc service named:%s already started, handle:0x%x\r\n", dev_n->rpc_name, dev_n->rpc_handle);
470 }
471
472 ddkc_dbg("call driver's open operation\n");
473 if (fops->open) {
474 ret = (fops->open)(node, fp);
475 if (ret) {
476 ddkc_err("open %s failed, ret:%d\n", path_name, ret);
477 goto err;
478 }
479 dev_n->ref_cnt++;
480 } else {
481 ddkc_warn("%s:fops->open is NULL\n", path_name);
482 }
483 ddkc_dbg("open %s sucess, dev_n->ref_cnt:%d\n", path_name, dev_n->ref_cnt);
484
485 res.priv.status = ret;
486 fnode->dev_n = dev_n;
487 res.open.farg = fnode;
488
489 ddkc_dbg("crpc_handle:0x%x, status:%d, open.farg:%p\r\n", crpc_handle, res.open.status, res.open.farg);
490 //send open RPC result via aos_rpc_resp
491 ret = aos_rpc_resp(crpc_handle, 1, sizeof(res), &res);
492 if (ret) {
493 ddkc_err("aos_rpc_resp on %s to handle:0x%x failed, ret:0x%x\r\n", path_name, crpc_handle, ret);
494 if (fops->close)
495 (fops->close)(fp);
496 else {
497 ddkc_warn("%s:fops->close is NULL\n", path_name);
498 }
499 dev_n->ref_cnt--;
500
501 goto err;
502 }
503 // add node info into file_head only when all operations succeed
504 dlist_add_tail(&fnode->node, &dev_n->file_head);
505 dlist_add_tail(&fnode->valid, &g_fnode_valid_list);
506 return 0;
507
508 err:
509 /* check whether rpc service needs to be stopped */
510 if (dev_n && !dev_n->ref_cnt && dev_n->rpc_run) {
511 ddkc_info("stop rpc service named:%s, handle:0x%x\r\n", dev_n->rpc_name, dev_n->rpc_handle);
512 ret = aos_rpc_stop(dev_n->rpc_handle);
513 if (ret) {
514 ddkc_err("aos_rpc_stop on %s failed, ret:%d\n", dev_n->rpc_name, ret);
515 }
516 dev_n->rpc_run = false;
517 }
518
519 /* clear other resoruce allocated in earlier steps */
520 if (fnode) {
521 free(fnode);
522 fnode = NULL;
523 }
524
525 if (node) {
526 free(node);
527 node = NULL;
528 }
529
530 /* send back RPC response to rpc client */
531 ddkc_err("open %s failed, send rpc resp:%d\r\n", path_name, ret);
532 res.open.status = ret;
533 res.open.farg = NULL;
534
535 //send open result via aos_rpc_resp
536 ret = aos_rpc_resp(crpc_handle, 1, sizeof(res), &res);
537 if (ret)
538 ddkc_err("aos_rpc_resp to 0x%x failed, ret:0x%x\r\n", crpc_handle, ret);
539
540 return ret;
541 }
542
543 /**
544 * close RPC message handler, called when CLOSE rpc message arrived in main rpc service's handler
545 *
546 * @param parg - pointer to u_fops_arg_u
547 * @param crpc_handle - rpc client's handle,
548 * response should be send to rpc client no matter this operation succeed or not
549 *
550 * @return 0 for success; negative for failure
551 */
u_device_rpc_close(u_fops_arg_u * parg,int crpc_handle)552 int u_device_rpc_close(u_fops_arg_u *parg, int crpc_handle) {
553 int ret = 0;
554 bool valid = false;
555 u_fops_result_u res;
556 file_t *fp = NULL;
557 file_node_t *fnode = NULL;
558 char *path_name = NULL;
559 struct subsys_dev_node *dev_n = NULL;
560 subsys_file_ops_t *fops = NULL;
561
562 if (!parg || !crpc_handle) {
563 ddkc_err("invalid rpc handle:%d or parg:%p\r\n", crpc_handle, parg);
564 ret = -EINVAL;
565 goto err;
566 }
567 fnode = (file_node_t *)parg->priv.farg;
568
569 /*
570 * do fnode validation, or permission fault might happen,
571 * becuase fnode might be other process' memory region
572 *
573 */
574 valid = _is_valid_fnode(fnode);
575 if (!valid) {
576 ddkc_err("fnode:%p is not valid\r\n", fnode);
577 ret = -EINVAL;
578 goto err;
579 }
580 dev_n = fnode->dev_n;
581
582 if (!dev_n->rpc_run) {
583 ddkc_warn("rpc service is already stopped\r\n");
584 WARN_ON_MSG(dev_n->ref_cnt, "rpc service is stopped but dev_n->ref_cnt:%d is not 0\r\n", dev_n->ref_cnt);
585 WARN_ON_MSG(!dlist_empty(&dev_n->file_head), "rpc service is stopped but dev_n->file_head is not empty\r\n");
586 ret = -EALREADY;
587 goto err;
588 }
589
590 fp = &fnode->f;
591 path_name = dev_n->path_name;
592 ddkc_dbg("closing %s, dev_n->rpc_handle:0x%x\r\n", path_name, dev_n->rpc_handle);
593 fops = dev_n->fops;
594
595 ret = fops->close(fp);
596 dev_n->ref_cnt--;
597 if (!ret)
598 ddkc_dbg("close %s success, ret:%d, dev_n->ref_cnt:%d\r\n", path_name, ret, dev_n->ref_cnt);
599 else
600 ddkc_err("close %s failed, ret:%d\r\n", path_name, ret);
601
602 if (!dev_n->ref_cnt && dev_n->rpc_run) {
603 ddkc_err("dev_n->ref_cnt is 0, should stop rpc service named %s\r\n", dev_n->rpc_name);
604 ret = aos_rpc_stop(dev_n->rpc_handle);
605 if (ret) {
606 ddkc_err("aos_rpc_stop on %s failed, ret:%d\n", dev_n->rpc_name, ret);
607 }
608 dev_n->rpc_run = false;
609 }
610
611 // delete from device node's file list
612 dlist_del(&fnode->node);
613 dlist_del(&fnode->valid);
614
615 free(fp->node);
616 fp->node = NULL;
617 free(fnode);
618 ddkc_dbg("close %s %s, send rpc resp:%d\r\n", path_name, ret ? "fail" : "success", ret);
619
620 err:
621 res.close.status = ret;
622
623 //send close result via aos_rpc_resp
624 ret = aos_rpc_resp(crpc_handle, 1, sizeof(res), &res);
625 if (ret)
626 ddkc_err("send rpc response to 0x%x failed, ret:0x%x\r\n", crpc_handle, ret);
627
628 return ret;
629 }
630
631 #endif
632
633 /**
634 *
635 * device open stub for delay init required driver
636 *
637 * @param node - pointer to inode, device node information
638 * @param f - pointer to file, file info
639 *
640 * @return 0 for success; negative for failure
641 */
_device_vfs_open(inode_t * node,file_t * f)642 static int _device_vfs_open (inode_t *node, file_t *f) {
643 int ret = 0;
644 dlist_t *pos = NULL;
645 dlist_t *tmp = NULL;
646 struct subsys_dev *sdev = NULL;
647 struct subsys_dev_node *dev_n = (struct subsys_dev_node *)node->i_arg;
648
649 ddkc_dbg("dev_n:%p\r\n", dev_n);
650 if (!dev_n) {
651 ddkc_err("node->i_arg is NULL, ignore\r\n");
652 return -EINVAL;
653 }
654
655 ddkc_info("opening %s\r\n", node->i_name);
656
657 dlist_for_each_safe(pos, tmp, &g_subsys_dev_list)
658 {
659 dev_n = aos_container_of(pos, subsys_dev_node_t, n);
660 sdev = &dev_n->dev;
661 if (!strcmp(dev_n->path_name, node->i_name))
662 break;
663 dev_n = NULL;
664 }
665
666 if (!dev_n) {
667 ddkc_err("dev_n not found for %s\r\n", node->i_name);
668 return -EIO;
669 }
670
671 sdev = &dev_n->dev;
672
673 /* check whether real_init or real_probe is always called or not */
674 if (sdev->delay_init) {
675 if (dev_n->real_init) {
676 ret = (dev_n->real_init)(dev_n->pdev);
677 } else
678 ret = (dev_n->real_probe)(dev_n->pdev);
679 if (ret) {
680 ddkc_err("fail to init/probe for %s, ret:%d\r\n", node->i_name, ret);
681 return -EIO;
682 }
683 sdev->delay_init = false;
684 node->i_arg = sdev->user_data;
685 }
686 /* call real_open provided by driver and logged in aos_dev_reg */
687 if (dev_n->real_open)
688 return (dev_n->real_open)(node, f);
689
690 return 0;
691 }
692
693 /**
694 *
695 * fake driver probe callback for delay init required driver
696 *
697 * @param pdev - pointer to the device
698 *
699 * @return 0 for success; negative for failure
700 */
_device_vfs_init(struct u_platform_device * pdev)701 static int _device_vfs_init(struct u_platform_device *pdev) {
702 ddkc_dbg("enter\r\n");
703 return 0;
704 }
705
706 /**
707 *
708 * register device driver
709 *
710 * @param sdev - pointer to subsys device
711 * @param sfops - pointer to file operations provided by device driver
712 * @param sdrv - pointer to device driver speicified operations
713 * @param rpc_only - whether this driver is rpc driver or not - not used for the moment
714 *
715 * @return 0 for success; negative for failure
716 */
aos_dev_reg_with_flag(struct subsys_dev * sdev,subsys_file_ops_t * sfops,struct subsys_drv * sdrv,bool rpc_only)717 int aos_dev_reg_with_flag (struct subsys_dev *sdev, subsys_file_ops_t *sfops, struct subsys_drv* sdrv, bool rpc_only) {
718 int ret = 0;
719 char *p = NULL;
720 char *path_name = NULL;
721 int path_name_len = 0;
722 struct u_platform_driver *pdrv = NULL;
723 struct u_platform_device *pdev = NULL;
724 subsys_file_ops_t *fops = NULL;
725 struct subsys_dev_node *dev_n = NULL;
726 char *rpc_name = NULL;
727 int rpc_handle = 0;
728 char *main_rpc_name = NULL;
729
730 if (!sfops || !sdev || !sdev->node_name) {
731 ddkc_err("invalid sfops:%p, sdev:%p or name:%p\r\n", sfops, sdev, sdev ? sdev->node_name : NULL);
732 return -EINVAL;
733 }
734
735 #ifdef USER_SPACE_DRIVER
736 /* register a rpc service for user space device driver
737 * with pre-defined service name format - "rpc-<pid>-<node_name>"
738 */
739 rpc_name = (char *)malloc(UDRIVER_RCP_NAME_MAX_LEN);
740 if (!rpc_name) {
741 ddkc_err("malloc failed, rpc_name:%p\r\n", rpc_name);
742 ret = -ENOMEM;
743 goto err_malloc;
744 }
745
746 ret = snprintf(rpc_name, UDRIVER_RCP_NAME_MAX_LEN, UDRIVER_RPC_NAME_FORMAT, getpid(), sdev->node_name);
747 if (ret < 0) {
748 ddkc_err("rpc_name snprintf for node_name:%s failed\r\n", sdev->node_name);
749 goto err_malloc;
750 }
751
752 ret = aos_rpc_regist(rpc_name, U_CDEV_RPC_BUFFER_SIZE, &rpc_handle);
753 if (ret) {
754 ddkc_err("register driver rpc service[%s] failed, ret:%d\r\n", rpc_name, ret);
755 goto err_malloc;
756 }
757 ddkc_dbg("register driver rpc service[%s] for %s succeed, handle:0x%x\r\n",
758 rpc_name, sdev->node_name, rpc_handle);
759 #endif
760
761 pdev = (struct u_platform_device *)malloc(sizeof(*pdev));
762 pdrv = (struct u_platform_driver *)malloc(sizeof(*pdrv));
763 fops = (subsys_file_ops_t *)malloc(sizeof(*fops));
764 path_name_len = strlen(NODE_PREFIX) + strlen(sdev->node_name) + 1;
765 path_name = (char *)malloc(path_name_len);
766
767 dev_n = (struct subsys_dev_node *)malloc(sizeof(*dev_n) + strlen(sdev->node_name) + 1);
768
769 if (!pdev || !pdrv || !fops || !path_name || !dev_n) {
770 ddkc_err("malloc failed, pdev:%p, pdrv:%p, fops:%p dev:%p, or path_name:%p\r\n", pdev, pdrv, fops, dev_n, path_name);
771 ret = -ENOMEM;
772 goto err_malloc;
773 }
774
775 memset(pdev, 0, sizeof(*pdev));
776 memset(pdrv, 0, sizeof(*pdrv));
777 memset(fops, 0, sizeof(*fops));
778 memset(path_name, 0, path_name_len);
779 memset(dev_n, 0, sizeof(*dev_n) + strlen(sdev->node_name) + 1);
780
781 //TODO: use sdrv->drv_name later
782 pdev->name = strdup(sdev->node_name);
783 if (!pdev->name) {
784 ddkc_err("dev strdup on %p failed\r\n", sdev->node_name);
785 ret = -EIO;
786 goto err_malloc_name;
787 }
788 ddkc_dbg("pdev->name:%s\r\n", pdev->name);
789 pdev->id = 0;
790
791 /* register device to u_platform bus */
792 ret = u_platform_device_register(pdev);
793 if (ret) {
794 ddkc_err("u_platform_device_register addplatform_device_register failed, ret:%d\r\n", ret);
795 ret = -EIO;
796 goto err_dev_reg;
797 }
798
799 /* log driver's private user_data pointer */
800 u_platform_set_user_data(pdev, sdev->user_data);
801 ddkc_dbg("set user_data:%p to user_data of pdev:%p\r\n", sdev->user_data, pdev);
802
803 if (sdrv) {
804 /* for legacy driver */
805 pdrv->init = (void *)sdrv->init;
806 pdrv->deinit = (void *)sdrv->deinit;
807 pdrv->pm = (void *)sdrv->pm;
808
809 /* for linux like drivers */
810 pdrv->probe = (void *)sdrv->probe;
811 pdrv->remove = (void *)sdrv->remove;
812 pdrv->suspend = (void *)sdrv->suspend;
813 pdrv->resume = (void *)sdrv->resume;
814 pdrv->shutdown = (void *)sdrv->shutdown;
815 } else
816 ddkc_dbg("sdrv callback is not set\r\n");
817
818 pdrv->driver.name = strdup(sdev->node_name);
819 if (!pdrv->driver.name) {
820 ddkc_dbg("drv strdup on %p failed\r\n", sdev->node_name);
821 ret = -ENOMEM;
822 goto err_dev_reg;
823 }
824 if (sdev->delay_init) {
825 dev_n->real_init = pdrv->init;
826 pdrv->init = _device_vfs_init;
827
828 dev_n->real_probe = pdrv->probe;
829 pdrv->probe = _device_vfs_init;
830 }
831
832 ddkc_dbg("pdrv->name:%s\r\n", pdrv->driver.name);
833
834 /* register driver to u_platform bus
835 * driver init/probe callback will be called in this step
836 * */
837 ret = u_platform_driver_register(pdrv);
838 if (ret) {
839 ddkc_err("u_platform_driver_register failed, ret:%d\r\n", ret);
840 ret = -EIO;
841 goto err_drv_reg;
842 }
843
844 memcpy(fops, sfops, sizeof(*fops));
845
846 p = path_name;
847 strncpy(path_name, NODE_PREFIX, strlen(NODE_PREFIX) + 1);
848
849 p += strlen(NODE_PREFIX);
850 strncpy(p, sdev->node_name, strlen(sdev->node_name) + 1);
851
852 dlist_init(&dev_n->n);
853 memcpy(&dev_n->dev, sdev, sizeof(*sdev));
854 dev_n->dev.node_name = (char *)(dev_n + 1);
855 strncpy(dev_n->dev.node_name, sdev->node_name, strlen(sdev->node_name));
856
857 // log device rpc handle and rpc_name
858 #ifdef USER_SPACE_DRIVER
859 dev_n->rpc_handle = rpc_handle;
860 dev_n->rpc_name = rpc_name;
861 main_rpc_name = u_driver_get_main_service_name();
862 #else
863 dev_n->rpc_name = NULL;
864 main_rpc_name = NULL;
865 #endif
866 dev_n->path_name = path_name;
867 dev_n->fops = fops;
868 dev_n->pdev = pdev;
869 dev_n->pdrv = pdrv;
870 dev_n->ref_cnt = 0;
871 dev_n->rpc_run = false;
872 dlist_init(&dev_n->file_head);
873
874 dlist_add_tail(&dev_n->n, &g_subsys_dev_list);
875
876 ddkc_dbg("registering %s to vfs\r\n", path_name);
877
878 ddkc_dbg("main rpc name:%s, rpc_name:%s\r\n", main_rpc_name, dev_n->rpc_name);
879 if (sdev->delay_init) {
880 dev_n->real_open = fops->open;
881 fops->open = _device_vfs_open;
882
883 }
884 #ifdef USER_SPACE_DRIVER
885 ret = aos_union_register_driver(path_name, fops, sdev->delay_init ? dev_n : sdev->user_data, main_rpc_name, dev_n->rpc_name);
886 #else
887 ret = aos_register_driver(path_name, fops, sdev->delay_init ? dev_n : sdev->user_data);
888 #endif
889
890 if (ret) {
891 dlist_del(&dev_n->n);
892 ddkc_info("register %s to vfs failed, rpc_only:%d, sdev->delay_init:%d, ret:%d\r\n", path_name, rpc_only, sdev->delay_init, ret);
893 goto err_vfs_reg;
894 }
895
896 ddkc_dbg("register %s to vfs success, rpc_only:%d, sdev->delay_init:%d\r\n", path_name, rpc_only, sdev->delay_init);
897
898 return 0;
899
900 err_vfs_reg:
901 // unregiste rpc service and free rpc service name field
902 u_platform_driver_unregister(pdrv);
903
904 err_drv_reg:
905 u_platform_device_unregister(pdev);
906
907 err_dev_reg:
908 err_malloc_name:
909 if (pdev->name)
910 free((void *)pdev->name);
911 pdev->name = NULL;
912
913 err_malloc:
914 if (pdev) {
915 free(pdev);
916 pdev = NULL;
917 }
918
919 if (pdrv) {
920 if (pdrv->driver.name)
921 free(pdrv->driver.name);
922
923 free(pdrv);
924 pdrv = NULL;
925 }
926
927 if (path_name) {
928 free(path_name);
929 path_name = NULL;
930 }
931
932 if (fops) {
933 free(fops);
934 fops = NULL;
935 }
936
937 if (dev_n) {
938 free(dev_n);
939 dev_n = NULL;
940 }
941
942 #ifdef USER_SPACE_DRIVER
943 if (rpc_handle) {
944 aos_rpc_close(rpc_handle);
945 rpc_handle = 0;
946 }
947
948 if (rpc_name) {
949 free(rpc_name);
950 rpc_name = NULL;
951 }
952 #endif
953
954 ddkc_err("device register failed, ret:%d\r\n", ret);
955 return ret;
956 }
957
958 /**
959 *
960 * register device array
961 *
962 * @param sdev pointer to devices array be register
963 * @param size device array size
964 * @param sfops file operations API
965 * @param sdrv - device driver operations callback
966 * - probe will be called when device exist
967 * - remove will be called when aos_dev_unreg is called
968 * @return 0 for success; negative for failure
969 */
aos_devs_reg(struct subsys_dev * sdev[],int size,subsys_file_ops_t * sfops,struct subsys_drv * sdrv)970 int aos_devs_reg(struct subsys_dev *sdev[], int size, subsys_file_ops_t *sfops, struct subsys_drv* sdrv) {
971 int i = 0;
972 int ret = 0;
973
974 for (i = 0; i < size; i++) {
975 ret = aos_dev_reg(sdev[i], sfops, sdrv);
976 if (ret) {
977 i--;
978 goto err;
979 }
980 }
981
982 return 0;
983 err:
984 for (; i >= 0; i--) {
985 int ret = 0;
986 ret = aos_dev_unreg(sdev[i]);
987 if (ret) {
988 ddkc_err("unregister device %s failed\r\n", sdev[i]->node_name);
989 }
990 }
991
992 return ret;
993 }
994
995 /**
996 * unregister device driver
997 *
998 * @param sdev - device identifier, name and type must be carefully set
999 *
1000 * @return 0 if device register success; return negative error no. if device register fails
1001 */
aos_dev_unreg(struct subsys_dev * sdev)1002 int aos_dev_unreg(struct subsys_dev *sdev) {
1003 int ret = 0;
1004 char *p = NULL;
1005 char *path_name = NULL;
1006 int path_name_len = 0;
1007 subsys_dev_node_t *dev_n = NULL;
1008 dlist_t *pos = NULL;
1009 dlist_t *tmp = NULL;
1010 struct subsys_dev *d = NULL;
1011
1012 path_name_len = strlen(NODE_PREFIX) + strlen(sdev->node_name) + 1;
1013 path_name = (char *)malloc(path_name_len);
1014 memset(path_name, 0, path_name_len);
1015
1016 p = path_name;
1017 strncpy(p, NODE_PREFIX, strlen(NODE_PREFIX));
1018
1019 p += strlen(NODE_PREFIX);
1020 strncpy(p, sdev->node_name, strlen(sdev->node_name));
1021
1022 ddkc_info("unregistering %s from vfs\r\n", path_name);
1023 #ifdef USER_SPACE_DRIVER
1024 ret = aos_union_unregister_driver(path_name);
1025 #else
1026 ret = aos_unregister_driver(path_name);
1027 #endif
1028 ddkc_info("unregister %s from vfs %s\r\n", path_name, !ret ? "success" : "failed");
1029
1030 free(path_name);
1031
1032 ret = -1;
1033 /* enumberate device list for target subsys device node to be removed */
1034 dlist_for_each_safe(pos, tmp, &g_subsys_dev_list) {
1035 dev_n = aos_container_of(pos, subsys_dev_node_t, n);
1036 d = &dev_n->dev;
1037 if(d->type == sdev->type && !strcmp(d->node_name, sdev->node_name) && d->user_data == sdev->user_data) {
1038 ddkc_info("sdev named with %s found, delete it\r\n", d->node_name);
1039
1040 // unregiste rpc service and free rpc service name field
1041 #ifdef USER_SPACE_DRIVER
1042 /* close rpc servce for user space driver */
1043 aos_rpc_close(dev_n->rpc_handle);
1044 free(dev_n->rpc_name);
1045 #endif
1046 u_platform_driver_unregister(dev_n->pdrv);
1047 u_platform_device_unregister(dev_n->pdev);
1048 dlist_del(&dev_n->n);
1049
1050 /* free all resources */
1051 free((void *)dev_n->pdev->name);
1052 free(dev_n->pdev);
1053 free(dev_n->pdrv->driver.name);
1054 free(dev_n->pdrv);
1055 free(dev_n->path_name);
1056 free(dev_n->fops);
1057 free(dev_n);
1058
1059 ret = 0;
1060 break;
1061 }
1062 }
1063
1064 ddkc_err("device unregister %s, ret:%d\r\n", ret ? "fail" : "success", ret);
1065
1066 return ret;
1067 }
1068
1069 /**
1070 *
1071 * register devices and corresponding driver into device/driver module
1072 *
1073 * @param sdev - device identifier, name and type must be carefully set
1074 * @param sfops - file operations API
1075 * @param sdrv - device driver operations callback
1076 * - init/probe will be called when device exist
1077 * - deinit/remove will be called when aos_dev_unreg is called
1078 * @return 0 if device register success; return negative error no. if device register fails
1079 */
aos_dev_reg(struct subsys_dev * sdev,subsys_file_ops_t * sfops,struct subsys_drv * sdrv)1080 int aos_dev_reg(struct subsys_dev *sdev, subsys_file_ops_t *sfops, struct subsys_drv* sdrv) {
1081 return aos_dev_reg_with_flag(sdev, sfops, sdrv, false);
1082 }
1083
1084 /**
1085 * This function is not used for the moment
1086 * register remote devices/driver into device/driver module, only support rpc mode
1087 *
1088 * @param sdev - device identifier, name and type must be carefully set
1089 * @param sfops - file operations API
1090 * @param sdrv - device driver operations callback
1091 * - probe will be called when device exist
1092 * - remove will be called when aos_dev_unreg is called
1093 * @return 0 if device register success; return negative error no. if device register fails
1094 */
aos_remote_dev_reg(struct subsys_dev * sdev,subsys_file_ops_t * sfops,struct subsys_drv * sdrv)1095 int aos_remote_dev_reg(struct subsys_dev *sdev, subsys_file_ops_t *sfops, struct subsys_drv* sdrv) {
1096 return aos_dev_reg_with_flag(sdev, sfops, sdrv, true);
1097 }
1098
1099 /**
1100 * unregister device array
1101 *
1102 * @param sdev - pointer to devices array be register
1103 * @param size - device array size
1104 *
1105 * @return 0 if device register success; return negative error no. if device register fails
1106 */
aos_devs_unreg(struct subsys_dev * sdev[],int size)1107 int aos_devs_unreg(struct subsys_dev *sdev[], int size) {
1108 int i = 0;
1109 int ret = 0;
1110
1111 for (i = 0; i < size; i++) {
1112 ret = aos_dev_unreg(sdev[i]);
1113 }
1114
1115 return ret;
1116 }
1117
1118 /**
1119 *
1120 * device vfs core layer initialization
1121 * declared with EARLY_DRIVER_ENTRY, which is before vendor driver initialization
1122 *
1123 * @return always return 0
1124 *
1125 */
device_vfs_init(void)1126 int device_vfs_init(void) {
1127 #ifdef AOS_COMP_VFS
1128 aos_vfs_init();
1129 #endif
1130 dlist_init(&g_subsys_dev_list);
1131 dlist_init(&g_fnode_valid_list);
1132
1133 return 0;
1134 }
1135
1136 EARLY_DRIVER_ENTRY(device_vfs_init)
1137