1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "hdf_vnode_adapter.h"
10 #include <osal_cdev.h>
11 #include <osal_mem.h>
12 #include <osal_sem.h>
13 #include <osal_uaccess.h>
14 #include <securec.h>
15 #include "devsvc_manager_clnt.h"
16 #include "hdf_device_node_ext.h"
17 #include "hdf_log.h"
18 #include "hdf_sbuf.h"
19
20 #define HDF_LOG_TAG hdf_vnode
21 #define VOID_DATA_SIZE 4
22 #define EVENT_QUEUE_MAX 100
23 #define MAX_RW_SIZE (1024 * 1204) // 1M
24
25 enum HdfVNodeClientStatus {
26 VNODE_CLIENT_RUNNING,
27 VNODE_CLIENT_LISTENING,
28 VNODE_CLIENT_STOPPED,
29 VNODE_CLIENT_EXITED,
30 };
31
32 struct HdfVNodeAdapterClient {
33 struct HdfVNodeAdapter *adapter;
34 struct HdfDeviceIoClient ioServiceClient;
35 wait_queue_head_t pollWait;
36 struct HdfIoService *serv;
37 struct OsalMutex mutex;
38 struct DListHead eventQueue;
39 struct DListHead listNode;
40 int32_t eventQueueSize;
41 int32_t wakeup;
42 uint32_t status;
43 };
44
45 struct HdfIoServiceKClient {
46 struct HdfIoService ioService;
47 struct HdfDeviceIoClient client;
48 };
49
HdfKIoServiceDispatch(struct HdfObject * service,int cmdId,struct HdfSBuf * data,struct HdfSBuf * reply)50 int HdfKIoServiceDispatch (struct HdfObject *service, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
51 {
52 struct HdfIoService *ioService = (struct HdfIoService*)service;
53 struct HdfIoServiceKClient *kClient = NULL;
54
55 if (ioService == NULL || ioService->dispatcher == NULL) {
56 return HDF_ERR_INVALID_PARAM;
57 }
58
59 kClient = CONTAINER_OF(ioService, struct HdfIoServiceKClient, ioService);
60 if (kClient->client.device == NULL || kClient->client.device->service == NULL ||
61 kClient->client.device->service->Dispatch == NULL) {
62 return HDF_ERR_INVALID_OBJECT;
63 }
64
65 return kClient->client.device->service->Dispatch(&kClient->client, cmdId, data, reply);
66 }
67
HdfHdfIoServiceKClientInstance(struct HdfDeviceObject * deviceObject)68 static struct HdfIoServiceKClient *HdfHdfIoServiceKClientInstance(struct HdfDeviceObject *deviceObject)
69 {
70 static struct HdfIoDispatcher kDispatcher = {
71 .Dispatch = HdfKIoServiceDispatch,
72 };
73
74 struct HdfIoServiceKClient *client = OsalMemCalloc(sizeof(struct HdfIoServiceKClient));
75 if (client == NULL) {
76 return NULL;
77 }
78
79 client->client.device = deviceObject;
80 if (deviceObject->service != NULL && deviceObject->service->Open != NULL) {
81 if (deviceObject->service->Open(&client->client) != HDF_SUCCESS) {
82 OsalMemFree(client);
83 return NULL;
84 }
85 }
86
87 client->ioService.dispatcher = &kDispatcher;
88 return client;
89 }
90
HdfIoServiceAdapterObtain(const char * serviceName)91 struct HdfIoService *HdfIoServiceAdapterObtain(const char *serviceName)
92 {
93 struct DevSvcManagerClnt *svcMgr = NULL;
94 struct HdfDeviceObject *deviceObject = NULL;
95 struct HdfIoServiceKClient *kClient = NULL;
96
97 if (serviceName == NULL) {
98 return NULL;
99 }
100
101 svcMgr = DevSvcManagerClntGetInstance();
102 if (svcMgr == NULL || svcMgr->devSvcMgrIf == NULL) {
103 return NULL;
104 }
105 deviceObject = svcMgr->devSvcMgrIf->GetObject(svcMgr->devSvcMgrIf, serviceName);
106 if (deviceObject == NULL) {
107 return NULL;
108 }
109
110 kClient = HdfHdfIoServiceKClientInstance(deviceObject);
111 if (kClient == NULL) {
112 return NULL;
113 }
114
115 return &kClient->ioService;
116 }
117
HdfIoServiceAdapterRecycle(struct HdfIoService * ioService)118 void HdfIoServiceAdapterRecycle(struct HdfIoService *ioService)
119 {
120 struct HdfIoServiceKClient *kClient = NULL;
121
122 if (ioService == NULL) {
123 return;
124 }
125
126 kClient = CONTAINER_OF(ioService, struct HdfIoServiceKClient, ioService);
127 if (kClient->client.device != NULL && kClient->client.device->service != NULL &&
128 kClient->client.device->service->Release != NULL) {
129 kClient->client.device->service->Release(&kClient->client);
130 }
131 OsalMemFree(kClient);
132 }
133
HdfSbufCopyFromUser(uintptr_t data,size_t size)134 static struct HdfSBuf *HdfSbufCopyFromUser(uintptr_t data, size_t size)
135 {
136 uint8_t *kData = NULL;
137 struct HdfSBuf *sbuf = NULL;
138
139 if (size == 0) {
140 return HdfSbufObtain(VOID_DATA_SIZE);
141 }
142
143 kData = OsalMemAlloc(size);
144 if (kData == NULL) {
145 HDF_LOGE("%s:oom", __func__);
146 return NULL;
147 }
148 if (CopyFromUser((void*)kData, (void*)data, size) != 0) {
149 HDF_LOGE("%s:failed to copy from user", __func__);
150 OsalMemFree(kData);
151 return NULL;
152 }
153
154 sbuf = HdfSbufBind((uintptr_t)kData, size);
155 if (sbuf == NULL) {
156 OsalMemFree(kData);
157 }
158 HdfSbufTransDataOwnership(sbuf);
159
160 return sbuf;
161 }
162
HdfSbufCopyToUser(const struct HdfSBuf * sbuf,void * dstUser,size_t dstUserSize)163 static int HdfSbufCopyToUser(const struct HdfSBuf *sbuf, void *dstUser, size_t dstUserSize)
164 {
165 size_t sbufSize = HdfSbufGetDataSize(sbuf);
166 if (sbufSize == 0) {
167 return HDF_SUCCESS;
168 }
169 if (dstUserSize < sbufSize) {
170 HDF_LOGE("%s: readBuffer too small %u", __func__, sbufSize);
171 return HDF_DEV_ERR_NORANGE;
172 }
173
174 if (CopyToUser(dstUser, HdfSbufGetData(sbuf), sbufSize) != 0) {
175 HDF_LOGE("%s: failed to copy buff data", __func__);
176 return HDF_ERR_IO;
177 }
178
179 return HDF_SUCCESS;
180 }
181
DevEventFree(struct HdfDevEvent * event)182 static void DevEventFree(struct HdfDevEvent *event)
183 {
184 if (event == NULL) {
185 return;
186 }
187 if (event->data != NULL) {
188 HdfSbufRecycle(event->data);
189 event->data = NULL;
190 }
191 OsalMemFree(event);
192 }
193
HdfVNodeAdapterServCall(const struct HdfVNodeAdapterClient * client,unsigned long arg)194 static int HdfVNodeAdapterServCall(const struct HdfVNodeAdapterClient *client, unsigned long arg)
195 {
196 struct HdfWriteReadBuf bwr;
197 struct HdfWriteReadBuf *bwrUser = (struct HdfWriteReadBuf *)((uintptr_t)arg);
198 struct HdfSBuf *data = NULL;
199 struct HdfSBuf *reply = NULL;
200 int ret;
201
202 if (client->serv == NULL || client->adapter == NULL ||
203 client->adapter->ioService.dispatcher == NULL ||
204 client->adapter->ioService.dispatcher->Dispatch == NULL) {
205 return HDF_ERR_INVALID_OBJECT;
206 }
207
208 if (bwrUser == NULL) {
209 return HDF_ERR_INVALID_PARAM;
210 }
211 if (CopyFromUser(&bwr, (void*)bwrUser, sizeof(bwr)) != 0) {
212 HDF_LOGE("copy from user failed");
213 return HDF_FAILURE;
214 }
215 if (bwr.writeSize > MAX_RW_SIZE || bwr.readSize > MAX_RW_SIZE) {
216 return HDF_ERR_INVALID_PARAM;
217 }
218
219 data = HdfSbufCopyFromUser(bwr.writeBuffer, bwr.writeSize);
220 if (data == NULL) {
221 HDF_LOGE("vnode adapter bind data is null");
222 return HDF_FAILURE;
223 }
224 reply = HdfSbufObtainDefaultSize();
225 if (reply == NULL) {
226 HDF_LOGE("%s: oom", __func__);
227 HdfSbufRecycle(data);
228 return HDF_FAILURE;
229 }
230 (void)HdfSbufWriteUint64(reply, (uintptr_t)&client->ioServiceClient);
231 ret = client->adapter->ioService.dispatcher->Dispatch(client->adapter->ioService.target,
232 bwr.cmdCode, data, reply);
233 if (bwr.readSize != 0 && HdfSbufCopyToUser(reply, (void*)(uintptr_t)bwr.readBuffer, bwr.readSize) != HDF_SUCCESS) {
234 HdfSbufRecycle(data);
235 HdfSbufRecycle(reply);
236 return HDF_ERR_IO;
237 }
238 bwr.readConsumed = HdfSbufGetDataSize(reply);
239 if (CopyToUser(bwrUser, &bwr, sizeof(struct HdfWriteReadBuf)) != 0) {
240 HDF_LOGE("%s: fail to copy bwr", __func__);
241 ret = HDF_FAILURE;
242 }
243
244 HdfSbufRecycle(data);
245 HdfSbufRecycle(reply);
246 return ret;
247 }
248
HdfVNodeAdapterReadDevEvent(struct HdfVNodeAdapterClient * client,unsigned long arg)249 static int HdfVNodeAdapterReadDevEvent(struct HdfVNodeAdapterClient *client, unsigned long arg)
250 {
251 struct HdfWriteReadBuf bwr;
252 struct HdfWriteReadBuf *bwrUser = (struct HdfWriteReadBuf *)((uintptr_t)arg);
253 struct HdfDevEvent *event = NULL;
254 size_t eventSize;
255
256 int ret = HDF_SUCCESS;
257 if (bwrUser == NULL) {
258 return HDF_ERR_INVALID_PARAM;
259 }
260
261 if (CopyFromUser(&bwr, (void*)bwrUser, sizeof(bwr)) != 0) {
262 HDF_LOGE("Copy from user failed");
263 return HDF_FAILURE;
264 }
265
266 if (bwr.readSize > MAX_RW_SIZE) {
267 return HDF_ERR_INVALID_PARAM;
268 }
269 OsalMutexLock(&client->mutex);
270
271 if (DListIsEmpty(&client->eventQueue)) {
272 OsalMutexUnlock(&client->mutex);
273 return HDF_DEV_ERR_NODATA;
274 }
275
276 event = CONTAINER_OF(client->eventQueue.next, struct HdfDevEvent, listNode);
277 eventSize = HdfSbufGetDataSize(event->data);
278 if (eventSize > bwr.readSize) {
279 bwr.readSize = eventSize;
280 ret = HDF_DEV_ERR_NORANGE;
281 } else {
282 if (HdfSbufCopyToUser(event->data, (void *)(uintptr_t)bwr.readBuffer, bwr.readSize) != HDF_SUCCESS) {
283 OsalMutexUnlock(&client->mutex);
284 return HDF_ERR_IO;
285 }
286 bwr.readConsumed = eventSize;
287 bwr.cmdCode = (int32_t)event->id;
288 }
289
290 if (CopyToUser(bwrUser, &bwr, sizeof(struct HdfWriteReadBuf)) != 0) {
291 HDF_LOGE("%s: failed to copy bwr", __func__);
292 ret = HDF_ERR_IO;
293 }
294 if (ret == HDF_SUCCESS) {
295 DListRemove(&event->listNode);
296 DevEventFree(event);
297 client->eventQueueSize--;
298 }
299
300 OsalMutexUnlock(&client->mutex);
301 return ret;
302 }
303
HdfVnodeAdapterDropOldEventLocked(struct HdfVNodeAdapterClient * client)304 static void HdfVnodeAdapterDropOldEventLocked(struct HdfVNodeAdapterClient *client)
305 {
306 struct HdfDevEvent *dropEvent = CONTAINER_OF(client->eventQueue.next, struct HdfDevEvent, listNode);
307
308 HDF_LOGE("dev event queue full, drop old one");
309 DListRemove(&dropEvent->listNode);
310 DevEventFree(dropEvent);
311 client->eventQueueSize--;
312 }
313
VNodeAdapterSendDevEventToClient(struct HdfVNodeAdapterClient * vnodeClient,uint32_t id,const struct HdfSBuf * data)314 static int VNodeAdapterSendDevEventToClient(struct HdfVNodeAdapterClient *vnodeClient,
315 uint32_t id, const struct HdfSBuf *data)
316 {
317 struct HdfDevEvent *event = NULL;
318
319 OsalMutexLock(&vnodeClient->mutex);
320 if (vnodeClient->status != VNODE_CLIENT_LISTENING) {
321 OsalMutexUnlock(&vnodeClient->mutex);
322 return HDF_SUCCESS;
323 }
324 if (vnodeClient->eventQueueSize >= EVENT_QUEUE_MAX) {
325 HdfVnodeAdapterDropOldEventLocked(vnodeClient);
326 }
327 event = OsalMemAlloc(sizeof(struct HdfDevEvent));
328 if (event == NULL) {
329 OsalMutexUnlock(&vnodeClient->mutex);
330 return HDF_DEV_ERR_NO_MEMORY;
331 }
332 event->id = id;
333 event->data = HdfSbufCopy(data);
334 if (event->data == NULL) {
335 OsalMutexUnlock(&vnodeClient->mutex);
336 HDF_LOGE("%s: sbuf oom", __func__);
337 OsalMemFree(event);
338 return HDF_DEV_ERR_NO_MEMORY;
339 }
340 DListInsertTail(&event->listNode, &vnodeClient->eventQueue);
341 vnodeClient->eventQueueSize++;
342 wake_up_interruptible(&vnodeClient->pollWait);
343 OsalMutexUnlock(&vnodeClient->mutex);
344
345 return HDF_SUCCESS;
346 }
347
HdfVNodeAdapterSendDevEvent(struct HdfVNodeAdapter * adapter,struct HdfVNodeAdapterClient * vnodeClient,uint32_t id,const struct HdfSBuf * data)348 static int HdfVNodeAdapterSendDevEvent(struct HdfVNodeAdapter *adapter, struct HdfVNodeAdapterClient *vnodeClient,
349 uint32_t id, const struct HdfSBuf *data)
350 {
351 struct HdfVNodeAdapterClient *client = NULL;
352 int ret = HDF_FAILURE;
353
354 if (adapter == NULL || data == NULL || HdfSbufGetDataSize(data) == 0) {
355 return HDF_ERR_INVALID_PARAM;
356 }
357 OsalMutexLock(&adapter->mutex);
358 DLIST_FOR_EACH_ENTRY(client, &adapter->clientList, struct HdfVNodeAdapterClient, listNode) {
359 if (vnodeClient != NULL && client != vnodeClient) {
360 continue;
361 }
362 ret = VNodeAdapterSendDevEventToClient(client, id, data);
363 if (ret != HDF_SUCCESS) {
364 break;
365 }
366 }
367 OsalMutexUnlock(&adapter->mutex);
368 return ret;
369 }
370
HdfVNodeAdapterClientStartListening(struct HdfVNodeAdapterClient * client)371 static void HdfVNodeAdapterClientStartListening(struct HdfVNodeAdapterClient *client)
372 {
373 OsalMutexLock(&client->mutex);
374 client->status = VNODE_CLIENT_LISTENING;
375 OsalMutexUnlock(&client->mutex);
376 }
377
HdfVnodeCleanEventQueue(struct HdfVNodeAdapterClient * client)378 static void HdfVnodeCleanEventQueue(struct HdfVNodeAdapterClient *client)
379 {
380 struct HdfDevEvent *event = NULL;
381 struct HdfDevEvent *eventTemp = NULL;
382 DLIST_FOR_EACH_ENTRY_SAFE(event, eventTemp, &client->eventQueue, struct HdfDevEvent, listNode) {
383 DListRemove(&event->listNode);
384 DevEventFree(event);
385 }
386 }
387
HdfVNodeAdapterClientStopListening(struct HdfVNodeAdapterClient * client)388 static void HdfVNodeAdapterClientStopListening(struct HdfVNodeAdapterClient *client)
389 {
390 OsalMutexLock(&client->mutex);
391 client->status = VNODE_CLIENT_STOPPED;
392 HdfVnodeCleanEventQueue(client);
393 wake_up_interruptible(&client->pollWait);
394 OsalMutexUnlock(&client->mutex);
395 }
396
HdfVNodeAdapterClientExitListening(struct HdfVNodeAdapterClient * client)397 static void HdfVNodeAdapterClientExitListening(struct HdfVNodeAdapterClient *client)
398 {
399 OsalMutexLock(&client->mutex);
400 client->status = VNODE_CLIENT_EXITED;
401 HdfVnodeCleanEventQueue(client);
402 wake_up_interruptible(&client->pollWait);
403 OsalMutexUnlock(&client->mutex);
404 }
405
HdfVNodeAdapterClientWakeup(struct HdfVNodeAdapterClient * client)406 static void HdfVNodeAdapterClientWakeup(struct HdfVNodeAdapterClient *client)
407 {
408 OsalMutexLock(&client->mutex);
409 if (client->status != VNODE_CLIENT_LISTENING) {
410 OsalMutexUnlock(&client->mutex);
411 return;
412 }
413 client->wakeup++;
414 wake_up_interruptible(&client->pollWait);
415 OsalMutexUnlock(&client->mutex);
416 }
417
HdfVNodeAdapterIoctl(struct file * filep,unsigned int cmd,unsigned long arg)418 static long HdfVNodeAdapterIoctl(struct file *filep, unsigned int cmd, unsigned long arg)
419 {
420 struct HdfVNodeAdapterClient *client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
421 if (client == NULL) {
422 return HDF_DEV_ERR_NO_DEVICE;
423 }
424 switch (cmd) {
425 case HDF_WRITE_READ:
426 return HdfVNodeAdapterServCall(client, arg);
427 case HDF_READ_DEV_EVENT:
428 return HdfVNodeAdapterReadDevEvent(client, arg);
429 case HDF_LISTEN_EVENT_START:
430 HdfVNodeAdapterClientStartListening(client);
431 break;
432 case HDF_LISTEN_EVENT_STOP:
433 HdfVNodeAdapterClientStopListening(client);
434 break;
435 case HDF_LISTEN_EVENT_WAKEUP:
436 HdfVNodeAdapterClientWakeup(client);
437 break;
438 case HDF_LISTEN_EVENT_EXIT:
439 HdfVNodeAdapterClientExitListening(client);
440 break;
441 default:
442 return HDF_FAILURE;
443 }
444
445 return HDF_SUCCESS;
446 }
447
HdfNewVNodeAdapterClient(struct HdfVNodeAdapter * adapter)448 static struct HdfVNodeAdapterClient *HdfNewVNodeAdapterClient(struct HdfVNodeAdapter *adapter)
449 {
450 struct HdfVNodeAdapterClient *client = OsalMemCalloc(sizeof(struct HdfVNodeAdapterClient));
451 if (client == NULL) {
452 HDF_LOGE("%s: oom", __func__);
453 return NULL;
454 }
455 if (OsalMutexInit(&client->mutex) != HDF_SUCCESS) {
456 OsalMemFree(client);
457 HDF_LOGE("%s: no mutex", __func__);
458 return NULL;
459 }
460
461 DListHeadInit(&client->eventQueue);
462 client->eventQueueSize = 0;
463 client->serv = &adapter->ioService;
464 client->status = VNODE_CLIENT_RUNNING;
465 client->adapter = adapter;
466 client->ioServiceClient.device = (struct HdfDeviceObject *)adapter->ioService.target;
467 client->ioServiceClient.priv = NULL;
468 client->wakeup = 0;
469 init_waitqueue_head(&client->pollWait);
470 OsalMutexLock(&adapter->mutex);
471 DListInsertTail(&client->listNode, &adapter->clientList);
472 OsalMutexUnlock(&adapter->mutex);
473
474 return client;
475 }
476
HdfDestoryVNodeAdapterClient(struct HdfVNodeAdapterClient * client)477 static void HdfDestoryVNodeAdapterClient(struct HdfVNodeAdapterClient *client)
478 {
479 struct HdfDevEvent *event = NULL;
480 struct HdfDevEvent *eventTemp = NULL;
481
482 client->status = VNODE_CLIENT_STOPPED;
483
484 OsalMutexLock(&client->adapter->mutex);
485 DListRemove(&client->listNode);
486 OsalMutexUnlock(&client->adapter->mutex);
487
488 OsalMutexLock(&client->mutex);
489 DLIST_FOR_EACH_ENTRY_SAFE(event, eventTemp, &client->eventQueue, struct HdfDevEvent, listNode) {
490 DListRemove(&event->listNode);
491 DevEventFree(event);
492 }
493 OsalMutexUnlock(&client->mutex);
494 OsalMutexDestroy(&client->mutex);
495 OsalMemFree(client);
496 }
497
HdfVNodeAdapterOpen(struct OsalCdev * cdev,struct file * filep)498 int HdfVNodeAdapterOpen(struct OsalCdev *cdev, struct file *filep)
499 {
500 struct HdfVNodeAdapter *adapter = (struct HdfVNodeAdapter *)OsalGetCdevPriv(cdev);
501 struct HdfVNodeAdapterClient *client = NULL;
502 int32_t ret;
503
504 if (adapter == NULL) {
505 HDF_LOGE("Vnode adapter dispatcher is null");
506 return HDF_FAILURE;
507 }
508 client = HdfNewVNodeAdapterClient(adapter);
509 if (client == NULL) {
510 return ETXTBSY;
511 }
512 OsalSetFilePriv(filep, client);
513 if (client->ioServiceClient.device != NULL && client->ioServiceClient.device->service != NULL &&
514 client->ioServiceClient.device->service->Open != NULL) {
515 ret = client->ioServiceClient.device->service->Open(&client->ioServiceClient);
516 if (ret != HDF_SUCCESS) {
517 HdfDestoryVNodeAdapterClient(client);
518 return ret;
519 }
520 }
521
522 return HDF_SUCCESS;
523 }
524
HdfVNodeAdapterPoll(struct file * filep,poll_table * wait)525 static unsigned int HdfVNodeAdapterPoll(struct file *filep, poll_table *wait)
526 {
527 unsigned int mask = 0;
528 struct HdfVNodeAdapterClient *client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
529 if (client == NULL) {
530 mask |= POLLERR;
531 return mask;
532 }
533 poll_wait(filep, &client->pollWait, wait);
534 OsalMutexLock(&client->mutex);
535 if (client->status == VNODE_CLIENT_EXITED) {
536 mask |= POLLHUP;
537 } else if (!DListIsEmpty(&client->eventQueue)) {
538 mask |= POLLIN;
539 } else if (client->wakeup > 0) {
540 mask |= POLLIN;
541 client->wakeup--;
542 }
543 OsalMutexUnlock(&client->mutex);
544
545 return mask;
546 }
547
HdfVNodeAdapterClose(struct OsalCdev * cdev,struct file * filep)548 static int HdfVNodeAdapterClose(struct OsalCdev *cdev, struct file *filep)
549 {
550 struct HdfVNodeAdapterClient *client = NULL;
551 (void)cdev;
552 client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
553 if (client->ioServiceClient.device != NULL && client->ioServiceClient.device->service != NULL &&
554 client->ioServiceClient.device->service->Release != NULL) {
555 client->ioServiceClient.device->service->Release(&client->ioServiceClient);
556 }
557 HdfDestoryVNodeAdapterClient(client);
558 OsalSetFilePriv(filep, NULL);
559 return HDF_SUCCESS;
560 }
561
HdfIoServiceAdapterRegCdev(struct HdfVNodeAdapter * vnodeAdapter,const struct OsalCdevOps * fileOps,uint32_t mode)562 struct HdfIoService *HdfIoServiceAdapterRegCdev(struct HdfVNodeAdapter *vnodeAdapter,
563 const struct OsalCdevOps *fileOps, uint32_t mode)
564 {
565 int32_t ret;
566 DListHeadInit(&vnodeAdapter->clientList);
567 if (OsalMutexInit(&vnodeAdapter->mutex) != HDF_SUCCESS) {
568 HDF_LOGE("vnode adapter out of mutex");
569 goto ERROR;
570 }
571 vnodeAdapter->cdev = OsalAllocCdev(fileOps);
572 if (vnodeAdapter->cdev == NULL) {
573 HDF_LOGE("fail to alloc osalcdev");
574 OsalMutexDestroy(&vnodeAdapter->mutex);
575 goto ERROR;
576 }
577 ret = OsalRegisterCdev(vnodeAdapter->cdev, vnodeAdapter->vNodePath, mode, vnodeAdapter);
578 if (ret != 0) {
579 HDF_LOGE("failed to register dev node %s, ret is: %d", vnodeAdapter->vNodePath, ret);
580 OsalMutexDestroy(&vnodeAdapter->mutex);
581 goto ERROR;
582 }
583 return &vnodeAdapter->ioService;
584 ERROR:
585 OsalMemFree(vnodeAdapter->vNodePath);
586 OsalMemFree(vnodeAdapter);
587 return NULL;
588 }
589
HdfIoServiceAdapterPublish(const char * serviceName,uint32_t mode)590 struct HdfIoService *HdfIoServiceAdapterPublish(const char *serviceName, uint32_t mode)
591 {
592 int nodePathLength;
593 struct HdfVNodeAdapter *vnodeAdapter = NULL;
594 static const struct OsalCdevOps fileOps = {
595 .open = HdfVNodeAdapterOpen,
596 .release = HdfVNodeAdapterClose,
597 .ioctl = HdfVNodeAdapterIoctl,
598 .poll = HdfVNodeAdapterPoll,
599 };
600
601 if ((serviceName == NULL) || (mode > MAX_MODE_SIZE)) {
602 HDF_LOGE("input param is invalid, mode is %x", mode);
603 return NULL;
604 }
605
606 vnodeAdapter = (struct HdfVNodeAdapter *)OsalMemCalloc(sizeof(struct HdfVNodeAdapter));
607 if (vnodeAdapter == NULL) {
608 HDF_LOGE("alloc remote service is null");
609 return NULL;
610 }
611
612 nodePathLength = strlen(serviceName) + strlen(DEV_NODE_PATH) + 1;
613 vnodeAdapter->vNodePath = (char *)OsalMemCalloc(nodePathLength);
614 if (vnodeAdapter->vNodePath == NULL) {
615 HDF_LOGE("alloc vnode path is null");
616 OsalMemFree(vnodeAdapter);
617 return NULL;
618 }
619
620 if (sprintf_s(vnodeAdapter->vNodePath, nodePathLength, "%s%s", DEV_NODE_PATH, serviceName) < 0) {
621 HDF_LOGE("failed to get node path");
622 OsalMemFree(vnodeAdapter->vNodePath);
623 OsalMemFree(vnodeAdapter);
624 return NULL;
625 }
626 return HdfIoServiceAdapterRegCdev(vnodeAdapter, &fileOps, mode);
627 }
628
HdfIoServiceAdapterRemove(struct HdfIoService * service)629 void HdfIoServiceAdapterRemove(struct HdfIoService *service)
630 {
631 if (service != NULL) {
632 struct HdfVNodeAdapter *vnodeAdapter = (struct HdfVNodeAdapter *)service;
633 if (vnodeAdapter->vNodePath != NULL) {
634 OsalUnregisterCdev(vnodeAdapter->cdev);
635 OsalFreeCdev(vnodeAdapter->cdev);
636 OsalMemFree(vnodeAdapter->vNodePath);
637 }
638 OsalMutexDestroy(&vnodeAdapter->mutex);
639 OsalMemFree(vnodeAdapter);
640 }
641 }
642
HdfDeviceSendEvent(const struct HdfDeviceObject * deviceObject,uint32_t id,const struct HdfSBuf * data)643 int32_t HdfDeviceSendEvent(const struct HdfDeviceObject *deviceObject, uint32_t id, const struct HdfSBuf *data)
644 {
645 struct HdfDeviceNode *deviceNode = NULL;
646 struct HdfVNodeAdapter *adapter = NULL;
647
648 if (deviceObject == NULL || data == NULL) {
649 return HDF_ERR_INVALID_PARAM;
650 }
651
652 deviceNode = CONTAINER_OF(deviceObject, struct HdfDeviceNode, deviceObject);
653 if (deviceNode->policy != SERVICE_POLICY_CAPACITY) {
654 return HDF_ERR_NOT_SUPPORT;
655 }
656
657 adapter = (struct HdfVNodeAdapter *)(((struct DeviceNodeExt*)deviceNode)->ioService);
658 return HdfVNodeAdapterSendDevEvent(adapter, NULL, id, data);
659 }
660
HdfDeviceSendEventToClient(const struct HdfDeviceIoClient * client,uint32_t id,const struct HdfSBuf * data)661 int32_t HdfDeviceSendEventToClient(const struct HdfDeviceIoClient *client, uint32_t id, const struct HdfSBuf *data)
662 {
663 struct HdfVNodeAdapterClient *vnodeClient = NULL;
664 if (client == NULL || client->device == NULL) {
665 return HDF_ERR_INVALID_PARAM;
666 }
667
668 vnodeClient = CONTAINER_OF(client, struct HdfVNodeAdapterClient, ioServiceClient);
669 if (vnodeClient->adapter == NULL) {
670 return HDF_ERR_INVALID_PARAM;
671 }
672
673 return HdfVNodeAdapterSendDevEvent(vnodeClient->adapter, vnodeClient, id, data);
674 }
675