• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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_base.h>
17#include <hdf_device_desc.h>
18#include <hdf_log.h>
19#include <hdf_sbuf_ipc.h>
20#include "v1_0/hello_interface_stub.h"
21
22#define HDF_LOG_TAG    hello_interface_driver
23
24using namespace OHOS::HDI::Hello::V1_0;
25
26struct HdfHelloInterfaceHost {
27    struct IDeviceIoService ioService;
28    OHOS::sptr<OHOS::IRemoteObject> stub;
29};
30
31/*
32 * 处理客户端请求的Dispatch方法: 处理来自客户端的IO请求
33 * client:指向HdfDeviceIoClient结构体的指针,表示发起请求的客户端。
34 * cmdId:命令ID,标识了要执行的命令或操作。
35 * data:指向HdfSBuf结构体的指针,包含了请求的数据。
36 * reply:指向另一个HdfSBuf结构体的指针,用于存放响应的数据。
37 */
38static int32_t HelloInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,
39    struct HdfSBuf *reply)
40{
41    auto *hdfHelloInterfaceHost = CONTAINER_OF(client->device->service, struct HdfHelloInterfaceHost, ioService);
42
43    // 声明两个MessageParcel对象,用于序列化和反序列化IPC通信中的数据
44    OHOS::MessageParcel *dataParcel = nullptr;
45    OHOS::MessageParcel *replyParcel = nullptr;
46    // 创建一个MessageOption对象,用于设置IPC通信的选项。
47    OHOS::MessageOption option;
48
49    // 响应序列化:将HdfSBuf中的数据转换为MessageParcel对象。如果转换失败,记录错误并返回错误代码。
50    if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
51        HDF_LOGE("%{public}s: invalid data sbuf object to dispatch", __func__);
52        return HDF_ERR_INVALID_PARAM;
53    }
54
55    // 数据序列化:尝试将响应数据的HdfSBuf转换为MessageParcel对象。如果失败,也记录错误并返回错误代码。
56    if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) {
57        HDF_LOGE("%{public}s: invalid reply sbuf object to dispatch", __func__);
58        return HDF_ERR_INVALID_PARAM;
59    }
60
61    // 调用stub对象的SendRequest方法,发送请求。这个方法执行实际的IPC调用,将cmdId和序列化后的请求数据dataParcel发送给服务端,并将响应数据反序列化到replyParcel中。
62    return hdfHelloInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);
63}
64
65// 驱动自身业务初始化的接口
66static int HdfHelloInterfaceDriverInit(struct HdfDeviceObject *deviceObject)
67{
68    HDF_LOGI("%{public}s: driver init start", __func__);
69    return HDF_SUCCESS;
70}
71
72// 将驱动对外提供的服务能力接口绑定到HDF框架
73static int HdfHelloInterfaceDriverBind(struct HdfDeviceObject *deviceObject)
74{
75    HDF_LOGI("%{public}s: driver bind start", __func__);
76    // 创建对象:该对象是驱动服务的具体实现
77    auto *hdfHelloInterfaceHost = new (std::nothrow) HdfHelloInterfaceHost;
78    if (hdfHelloInterfaceHost == nullptr) {
79        HDF_LOGE("%{public}s: failed to create create HdfHelloInterfaceHost object", __func__);
80        return HDF_FAILURE;
81    }
82
83    // 为ioService结构体设置回调函数:设置的Dispatch函数用于处理IO请求
84    hdfHelloInterfaceHost->ioService.Dispatch = HelloInterfaceDriverDispatch;
85    hdfHelloInterfaceHost->ioService.Open = NULL;
86    hdfHelloInterfaceHost->ioService.Release = NULL;
87
88    auto serviceImpl = OHOS::HDI::Hello::V1_0::IHelloInterface::Get(true);
89    if (serviceImpl == nullptr) {
90        HDF_LOGE("%{public}s: failed to get of implement service", __func__);
91        delete hdfHelloInterfaceHost;
92        return HDF_FAILURE;
93    }
94
95    // 使用ObjectCollector的GetOrNewObject方法获取或创建一个Stub对象。Stub对象是服务接口的客户端代理,用于发起远程调用。
96    hdfHelloInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
97        OHOS::HDI::Hello::V1_0::IHelloInterface::GetDescriptor());
98    if (hdfHelloInterfaceHost->stub == nullptr) {
99        HDF_LOGE("%{public}s: failed to get stub object", __func__);
100        delete hdfHelloInterfaceHost;
101        return HDF_FAILURE;
102    }
103
104    // 将ioService绑定到deviceObject,这样HDF框架就可以通过deviceObject来访问服务
105    deviceObject->service = &hdfHelloInterfaceHost->ioService;
106    HDF_LOGI("%{public}s: driver bind end", __func__);
107    return HDF_SUCCESS;
108}
109
110// 驱动释放资源的接口
111static void HdfHelloInterfaceDriverRelease(struct HdfDeviceObject *deviceObject)
112{
113    HDF_LOGI("%{public}s: driver release start", __func__);
114    if (deviceObject->service == nullptr) {
115        return;
116    }
117
118    auto *hdfHelloInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfHelloInterfaceHost, ioService);
119    if (hdfHelloInterfaceHost != nullptr) {
120        delete hdfHelloInterfaceHost;
121    }
122}
123
124/*
125 * 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量。
126 */
127struct HdfDriverEntry g_hellointerfaceDriverEntry = {
128    .moduleVersion = 1,
129    .moduleName = "hello_service",
130    .Bind = HdfHelloInterfaceDriverBind,
131    .Init = HdfHelloInterfaceDriverInit,
132    .Release = HdfHelloInterfaceDriverRelease,
133};
134
135#ifdef __cplusplus
136extern "C" {
137#endif /* __cplusplus */
138
139/*
140 * 调用HDF_INIT将驱动入口注册到HDF框架中。
141 * 在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动;当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
142 */
143HDF_INIT(g_hellointerfaceDriverEntry);
144#ifdef __cplusplus
145}
146#endif /* __cplusplus */
147