1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <linux/fs.h>
32 #include "hdf_log.h"
33 #include "hdf_io_service.h"
34 #include "osal_cdev.h"
35 #include "osal_file.h"
36 #include "osal_mem.h"
37 #include "osal_uaccess.h"
38
39 #define HDF_LOG_TAG osal_cdev
40
41 struct OsalCdev {
42 struct file_operations_vfs fops;
43 const struct OsalCdevOps* opsImpl;
44 const char* path;
45 void* priv;
46 };
47
OsalCdevOpen(struct file * filep)48 int OsalCdevOpen(struct file* filep)
49 {
50 struct drv_data* drvData = (struct drv_data* )filep->f_vnode->data;
51 struct OsalCdev* dev = (struct OsalCdev* )drvData->priv;
52 return dev->opsImpl->open(dev, filep);
53 }
54
OsalCdevRelease(struct file * filep)55 int OsalCdevRelease(struct file* filep)
56 {
57 if (filep == NULL || filep->f_vnode == NULL) {
58 return HDF_ERR_INVALID_OBJECT;
59 }
60 struct drv_data* drvData = (struct drv_data* )filep->f_vnode->data;
61 struct OsalCdev* dev = (struct OsalCdev* )drvData->priv;
62 return dev->opsImpl->release(dev, filep);
63 }
64
OsalCdevRead(struct file * filep,char * buffer,size_t buflen)65 ssize_t OsalCdevRead(struct file* filep, char* buffer, size_t buflen)
66 {
67 if (filep == NULL || filep->f_vnode == NULL) {
68 return HDF_ERR_INVALID_OBJECT;
69 }
70 struct drv_data* drvData = (struct drv_data* )filep->f_vnode->data;
71 struct OsalCdev* dev = (struct OsalCdev* )drvData->priv;
72 return dev->opsImpl->read(filep, buffer, buflen, 0);
73 }
74
OsalCdevWrite(struct file * filep,const char * buffer,size_t buflen)75 ssize_t OsalCdevWrite(struct file* filep, const char* buffer, size_t buflen)
76 {
77 if (filep == NULL || filep->f_vnode == NULL) {
78 return HDF_ERR_INVALID_OBJECT;
79 }
80 struct drv_data* drvData = (struct drv_data* )filep->f_vnode->data;
81 struct OsalCdev* dev = (struct OsalCdev* )drvData->priv;
82 return dev->opsImpl->write(filep, buffer, buflen, 0);
83 }
84
OsalCdevSeek(struct file * filep,off_t offset,int whence)85 off_t OsalCdevSeek(struct file* filep, off_t offset, int whence)
86 {
87 if (filep == NULL || filep->f_vnode == NULL) {
88 return HDF_ERR_INVALID_OBJECT;
89 }
90 struct drv_data* drvData = (struct drv_data* )filep->f_vnode->data;
91 struct OsalCdev* dev = (struct OsalCdev* )drvData->priv;
92 return dev->opsImpl->seek(filep, offset, whence);
93 }
94
OsalCdevIoctl(struct file * filep,int cmd,unsigned long arg)95 int OsalCdevIoctl(struct file* filep, int cmd, unsigned long arg)
96 {
97 if (filep == NULL || filep->f_vnode == NULL) {
98 return HDF_ERR_INVALID_OBJECT;
99 }
100 struct drv_data* drvData = (struct drv_data* )filep->f_vnode->data;
101 struct OsalCdev* dev = (struct OsalCdev* )drvData->priv;
102 return dev->opsImpl->ioctl(filep, cmd, arg);
103 }
104
OsalCdevPoll(struct file * filep,poll_table * fds)105 int OsalCdevPoll(struct file* filep, poll_table* fds)
106 {
107 if (filep == NULL || filep->f_vnode == NULL) {
108 return HDF_ERR_INVALID_OBJECT;
109 }
110 struct drv_data* drvData = (struct drv_data* )filep->f_vnode->data;
111 struct OsalCdev* dev = (struct OsalCdev* )drvData->priv;
112 return dev->opsImpl->poll(filep, fds);
113 }
114
AssignFileOps(struct file_operations_vfs * fops,const struct OsalCdevOps * src)115 static void AssignFileOps(struct file_operations_vfs* fops, const struct OsalCdevOps* src)
116 {
117 fops->seek = src->seek != NULL ? OsalCdevSeek : NULL;
118 fops->read = src->read != NULL ? OsalCdevRead : NULL;
119 fops->write = src->write != NULL ? OsalCdevWrite : NULL;
120 fops->poll = src->poll != NULL ? OsalCdevPoll : NULL;
121 fops->ioctl = src->ioctl != NULL ? OsalCdevIoctl : NULL;
122 fops->open = src->open != NULL ? OsalCdevOpen : NULL;
123 fops->close = src->release != NULL ? OsalCdevRelease : NULL;
124 }
125
OsalAllocCdev(const struct OsalCdevOps * fops)126 struct OsalCdev* OsalAllocCdev(const struct OsalCdevOps* fops)
127 {
128 struct OsalCdev* cdev = OsalMemCalloc(sizeof(struct OsalCdev));
129 if (cdev == NULL) {
130 return NULL;
131 }
132
133 AssignFileOps(&cdev->fops, fops);
134 cdev->opsImpl = fops;
135
136 return cdev;
137 }
138
OsalRegisterCdev(struct OsalCdev * cdev,const char * name,unsigned int mode,void * priv)139 int OsalRegisterCdev(struct OsalCdev* cdev, const char* name, unsigned int mode, void* priv)
140 {
141 if (cdev == NULL || name == NULL) {
142 return HDF_ERR_INVALID_PARAM;
143 }
144 HDF_LOGI("%s:register %s", __func__, name);
145 static bool devPathInitted = false;
146 if (!devPathInitted && mkdir(DEV_NODE_PATH, DEV_NODE_PATH_MODE) == 0) {
147 devPathInitted = true;
148 }
149 int ret = register_driver(name, &cdev->fops, mode, cdev);
150 if (ret == HDF_SUCCESS) {
151 cdev->priv = priv;
152 cdev->path = name;
153 }
154 return ret;
155 }
156
OsalUnregisterCdev(struct OsalCdev * cdev)157 void OsalUnregisterCdev(struct OsalCdev* cdev)
158 {
159 if (cdev != NULL) {
160 unregister_driver(cdev->path);
161 }
162 }
163
OsalFreeCdev(struct OsalCdev * cdev)164 void OsalFreeCdev(struct OsalCdev* cdev)
165 {
166 if (cdev != NULL) {
167 OsalMemFree(cdev);
168 }
169 }
170
OsalGetCdevPriv(struct OsalCdev * cdev)171 void* OsalGetCdevPriv(struct OsalCdev* cdev)
172 {
173 return cdev != NULL ? cdev->priv : NULL;
174 }
175
OsalSetFilePriv(struct file * filep,void * priv)176 void OsalSetFilePriv(struct file* filep, void* priv)
177 {
178 if (filep != NULL) {
179 filep->f_priv = priv;
180 }
181 }
182
OsalGetFilePriv(struct file * filep)183 void* OsalGetFilePriv(struct file* filep)
184 {
185 return filep != NULL ? filep->f_priv : NULL;
186 }
187