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