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