1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <hdf_log.h>
17
18#include "hdf_base.h"
19#include "hdf_device_desc.h"
20#include "hdf_sbuf_ipc.h"
21#include "v1_3/ril_stub.h"
22#include "hril_hdf.h"
23
24using namespace OHOS::HDI::Ril::V1_3;
25using namespace OHOS::HDI::Ril;
26
27struct HdfRilHost {
28    struct IDeviceIoService ioService;
29    OHOS::sptr<OHOS::IRemoteObject> stub;
30};
31
32static int32_t RilDriverDispatch(
33    struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
34{
35    auto *hdfRilHost = CONTAINER_OF(client->device->service, struct HdfRilHost, ioService);
36
37    OHOS::MessageParcel *dataParcel = nullptr;
38    OHOS::MessageParcel *replyParcel = nullptr;
39    OHOS::MessageOption option;
40
41    if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
42        HDF_LOGE("invalid data sbuf object to dispatch");
43        return HDF_ERR_INVALID_PARAM;
44    }
45    if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) {
46        HDF_LOGE("invalid reply sbuf object to dispatch");
47        return HDF_ERR_INVALID_PARAM;
48    }
49    int ret = hdfRilHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);
50    return ret;
51}
52
53static int32_t HdfRilDriverInit(struct HdfDeviceObject *deviceObject)
54{
55    InitRilAdapter();
56    return HDF_SUCCESS;
57}
58
59static int32_t HdfRilDriverBind(struct HdfDeviceObject *deviceObject)
60{
61    auto *hdfRilHost = new (std::nothrow) HdfRilHost;
62    if (hdfRilHost == nullptr) {
63        HDF_LOGE("%{public}s: failed to create HdfRilHost object", __func__);
64        return HDF_FAILURE;
65    }
66
67    hdfRilHost->ioService.Dispatch = RilDriverDispatch;
68    hdfRilHost->ioService.Open = nullptr;
69    hdfRilHost->ioService.Release = nullptr;
70
71    auto serviceImpl = V1_3::IRil::Get(true);
72    if (serviceImpl == nullptr) {
73        HDF_LOGE("%{public}s: failed to get of implement service", __func__);
74        delete hdfRilHost;
75        hdfRilHost = nullptr;
76        return HDF_FAILURE;
77    }
78
79    hdfRilHost->stub =
80        OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, V1_3::IRil::GetDescriptor());
81    if (hdfRilHost->stub == nullptr) {
82        HDF_LOGE("%{public}s: failed to get stub object", __func__);
83        delete hdfRilHost;
84        hdfRilHost = nullptr;
85        return HDF_FAILURE;
86    }
87
88    if (deviceObject == nullptr) {
89        HDF_LOGE("%{public}s: failed to get device object", __func__);
90        delete hdfRilHost;
91        hdfRilHost = nullptr;
92        return HDF_FAILURE;
93    }
94    deviceObject->service = &hdfRilHost->ioService;
95    return HDF_SUCCESS;
96}
97
98static void HdfRilDriverRelease(struct HdfDeviceObject *deviceObject)
99{
100    if (deviceObject == nullptr || deviceObject->service == nullptr) {
101        HDF_LOGE("HdfRilDriverRelease not initted");
102        return;
103    }
104    ReleaseRilAdapter();
105    auto *hdfRilHost = CONTAINER_OF(deviceObject->service, struct HdfRilHost, ioService);
106    delete hdfRilHost;
107}
108
109static struct HdfDriverEntry g_RilDriverEntry = {
110    .moduleVersion = 1,
111    .moduleName = "ril_service",
112    .Bind = HdfRilDriverBind,
113    .Init = HdfRilDriverInit,
114    .Release = HdfRilDriverRelease,
115};
116
117#ifndef __cplusplus
118extern "C" {
119#endif
120HDF_INIT(g_RilDriverEntry);
121#ifndef __cplusplus
122}
123#endif