1/****************************************************************************
2 * fs/driver/fs_registerdriver.c
3 *
4 * Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved.
5 * Based on NuttX originally from nuttx source (nuttx/fs/ and nuttx/drivers/)
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *     http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ****************************************************************************/
20
21/****************************************************************************
22 * Included Files
23 ****************************************************************************/
24
25#include "vfs_config.h"
26#include "sys/types.h"
27#include "errno.h"
28#include "fs/driver.h"
29#include "vnode.h"
30#include "string.h"
31#include "path_cache.h"
32#include "limits.h"
33
34/****************************************************************************
35 * Public Functions
36 ****************************************************************************/
37
38/****************************************************************************
39 * Name: register_driver
40 *
41 * Description:
42 *   Register a character driver vnode the pseudo file system.
43 *
44 * Input Parameters:
45 *   path - The path to the vnode to create
46 *   fops - The file operations structure
47 *   mode - inmode priviledges (not used)
48 *   priv - Private, user data that will be associated with the vnode.
49 *
50 * Returned Value:
51 *   Zero on success (with the vnode point in 'vnode'); A negated errno
52 *   value is returned on a failure (all error values returned by
53 *   vnode_reserve):
54 *
55 *   EINVAL - 'path' is invalid for this operation
56 *   EEXIST - An vnode already exists at 'path'
57 *   ENOMEM - Failed to allocate in-memory resources for the operation
58 *
59 ****************************************************************************/
60
61int register_driver(const char *path, const struct file_operations_vfs *fops,
62                    mode_t mode, void *priv)
63{
64  struct Vnode *vnode = NULL;
65  int ret;
66
67  if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0)
68    {
69      return -EINVAL;
70    }
71
72  VnodeHold();
73  ret = VnodeLookup(path, &vnode, 0);
74  if (ret == 0)
75    {
76      VnodeDrop();
77      return -EEXIST;
78    }
79
80  /* Insert a dummy node -- we need to hold the vnode semaphore because we
81   * will have a momentarily bad structure.
82   */
83
84  struct drv_data *data = (struct drv_data *)zalloc(sizeof(struct drv_data));
85
86  data->ops = (void *)fops;
87  data->mode = mode;
88  data->priv = priv;
89
90  ret = VnodeLookup(path, &vnode, V_CREATE | V_DUMMY);
91  if (ret == OK)
92    {
93      /* We have it, now populate it with driver specific information.
94       * NOTE that the initial reference count on the new vnode is zero.
95       */
96      vnode->type = VNODE_TYPE_CHR;
97      vnode->data = data;
98      vnode->mode = mode;
99      vnode->fop = (struct file_operations_vfs *)fops;
100    }
101
102  VnodeDrop();
103
104  return ret;
105}
106