openharmony在标准系统上适配NFC驱动
一、背景说明 本文主要以标准系统上对NFC的驱动加载流程进行的通用介绍。以下是一种通用的驱动适配方法,在适配前先以小熊派芯片,在liteos上进行基本的nfc_example.c的功能使用,然后结合标准系统的驱动适配流程进行HDF层的适配说明,过程供参考。 二、适配思路 1、NFC组件服务架构图2、上层引用目录 /foundation/communication/nfc ├── interfa
一、背景说明
本文主要以标准系统上对NFC的驱动加载流程进行的通用介绍。以下是一种通用的驱动适配方法,在适配前先以小熊派芯片,在liteos上进行基本的nfc_example.c的功能使用,然后结合标准系统的驱动适配流程进行HDF层的适配说明,过程供参考。
二、适配思路
1、NFC组件服务架构图
2、上层引用目录
/foundation/communication/nfc ├── interfaces # 接口 │ └── inner_api # 系统内部件间接口 ├── frameworks # 框架层接口 │ └── js # JS API的实现 │ └── napi # 通过napi封装的JS接口代码实现 ├── services # NFC服务进程的实现 ├── test # 测试代码 ├── BUILD.gn # 编译入口 └── bundle.json # 部件描述文件
services中通过调用HDI接口,比如:
ErrCode NfcTagServiceImpl::WriteNdefTag(std::string data) { if (!PermissionTools::IsGranted(OHOS::NFC::TAG_PERMISSION)) { HILOGE("NfcTagServiceImpl:WriteNdefTag() IsGranted failed!"); return NFC_FAILED; } if (NfcTagHdiAdapter::GetInstance().WriteNdefTag(data) == 0) { return NFC_SUCCESS; } return NFC_FAILED; }
3、驱动加载
1)先在.\drivers\hdf_core\framework\model下新建nfc/driver/src文件夹,添加nfc_driver.c,加载驱动
openharmony
|--------\drivers\hdf_core\framework\model\nfc\driver\src
|-------------------------------------------------------------└──nfc_driver.c
添加驱动加载:
static struct HdfDriverEntry g_nfcinterfaceDriverEntry = { .moduleVersion = 1, .moduleName = "nfc_driver", .Bind = HdfNfcInterfaceDriverBind, .Init = HdfNfcInterfaceDriverInit, .Release = HdfNfcInterfaceDriverRelease, };
通过HDF模块初始化:
#ifdef __cplusplus extern "C" { #endif /* __cplusplus */ HDF_INIT(g_nfcinterfaceDriverEntry); #ifdef __cplusplus }
添加基本的HdfNfcInterfaceDriverBind、HdfNfcInterfaceDriverInit、HdfNfcInterfaceDriverRelease接口实现:
struct HdfNfcInterfaceHost { struct IDeviceIoService ioservice; OHOS::sptr<OHOS::IRemoteObject> stub; };////////---------------
//HdfNfcInterfaceDriverBind驱动服务绑定到HDF static int HdfNfcInterfaceDriverBind(struct HdfDeviceObject *deviceObject) { HDF_LOGI("HdfNfcInterfaceDriverBind enter"); auto *hdfNfcInterfaceHost = new (std::nothrow) HdfNfcInterfaceHost; if (hdfNfcInterfaceHost == nullptr) { HDF_LOGE("HdfNfcInterfaceDriverBind, failed to create HdfNfcInterfaceDriverBind Object!"); return HDF_FAILURE; } hdfNfcInterfaceHost->ioservice.Dispatch = NfcInterfaceDriverDispatch; hdfNfcInterfaceHost->ioservice.Open = nullptr; hdfNfcInterfaceHost->ioservice.Release = nullptr; auto serviceImpl = INfcInterface::Get(true); if (serviceImpl == nullptr) { HDF_LOGE("HdfNfcInterfaceDriverBind, failed to get of implement service"); delete hdfNfcInterfaceHost; return HDF_FAILURE; } hdfNfcInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, INfcInterface::GetDescriptor()); if (hdfNfcInterfaceHost->stub == nullptr) { HDF_LOGE("HdfNfcInterfaceDriverBind, failed to get stub object"); delete hdfNfcInterfaceHost; return HDF_FAILURE; } deviceObject->service = &hdfNfcInterfaceHost->ioservice; HDF_LOGI("HdfNfcInterfaceDriverBind Success"); return HDF_SUCCESS; } static int32_t NfcInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply) { auto *hdfNfcInterfaceHost = CONTAINER_OF(client->device->service, struct HdfNfcInterfaceHost, ioservice); OHOS::MessageParcel *dataParcel = nullptr; OHOS::MessageParcel *replyParcel = nullptr; OHOS::MessageOption option; if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { HDF_LOGE("NfcInterfaceDriverDispatc, invalid data sbuf object to dispatch"); return HDF_ERR_INVALID_PARAM; } if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { HDF_LOGE("NfcInterfaceDriverDispatch, invalid reply sbuf object to dispatch"); return HDF_ERR_INVALID_PARAM; } return hdfNfcInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); }
//HdfNfcInterfaceDriverInit驱动初始化 static int HdfNfcInterfaceDriverInit(struct HdfDeviceObject *deviceObject) { HDF_LOGI("HdfNfcInterfaceDriverInit enter"); return HDF_SUCCESS; }
//HdfNfcInterfaceDriverRelease static void HdfNfcInterfaceDriverRelease(struct HdfDeviceObject *deviceObject) { HDF_LOGI("HdfNfcInterfaceDriverRelease enter"); if (deviceObject->service == nullptr) { HDF_LOGE("HdfNfcInterfaceDriverRelease not initted"); return; } auto *hdfNfcInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfNfcInterfaceHost, ioservice); delete hdfNfcInterfaceHost; HDF_LOGI("HdfNfcInterfaceDriverRelease Success"); }
2)同级目录添加接口引用文件
添加nfc_impl.h和对应的cpp文件,供接口调用
//nfc_impl.h namespace OHOS { namespace HDI { namespace Nfc { namespace V1_0 { class NfcImpl : public INfcInterface { public: virtual ~NfcImpl() {} int32_t Open(const sptr<INfcCallback> &callbackObj, NfcStatus &status) override; int32_t CoreInitialized(const std::vector<uint8_t> &data, NfcStatus &status) override; int32_t Prediscover(NfcStatus &status) override; int32_t Write(const std::vector<uint8_t> &data, NfcStatus &status) override; int32_t ControlGranted(NfcStatus &status) override; int32_t PowerCycle(NfcStatus &status) override; int32_t Close(NfcStatus &status) override; int32_t Ioctl(NfcCommand cmd, const std::vector<uint8_t> &data, NfcStatus &status) override; private: NfcVendorAdaptions adaptor_; }; } // V1_0 } // Nfc } // HDI } // OHOS
cpp接口实现:
//nfc_impl.cpp namespace OHOS { namespace HDI { namespace Nfc { namespace V1_0 { static sptr<V1_0::INfcCallback> g_callbackV1_0 = nullptr; static void EventCallback(unsigned char event, unsigned char status) { if (g_callbackV1_0 != nullptr) { g_callbackV1_0->OnEvent((NfcEvent)event, (NfcStatus)status); } } static void DataCallback(uint16_t len, uint8_t *data) { if (g_callbackV1_0 != nullptr) { std::vector<uint8_t> vec(data, data + len / sizeof(uint8_t)); g_callbackV1_0->OnData(vec); } } extern "C" INfcInterface *NfcInterfaceImplGetInstance(void) { using OHOS::HDI::Nfc::V1_0::NfcImpl; NfcImpl *service = new (std::nothrow) NfcImpl(); if (service == nullptr) { return nullptr; } return service; } int32_t NfcImpl::Open(const sptr<INfcCallback> &callbackObj, NfcStatus &status) { if (callbackObj == nullptr) { HDF_LOGE("Open, callback is nullptr!"); return HDF_ERR_INVALID_PARAM; } g_callbackV1_0 = callbackObj; int ret = adaptor_.VendorOpen(EventCallback, DataCallback); if (ret == 0) { status = NfcStatus::OK; return HDF_SUCCESS; } status = NfcStatus::FAILED; return HDF_FAILURE; } int32_t NfcImpl::CoreInitialized(const std::vector<uint8_t> &data, NfcStatus &status) { if (data.empty()) { HDF_LOGE("CoreInitialized, data is nullptr!"); return HDF_ERR_INVALID_PARAM; } int ret = adaptor_.VendorCoreInitialized(data.size(), (uint8_t *)&data[0]); if (ret == 0) { status = NfcStatus::OK; return HDF_SUCCESS; } status = NfcStatus::FAILED; return HDF_FAILURE; } int32_t NfcImpl::Prediscover(NfcStatus &status) { int ret = adaptor_.VendorPrediscover(); if (ret == 0) { status = NfcStatus::OK; return HDF_SUCCESS; } status = NfcStatus::FAILED; return HDF_FAILURE; } int32_t NfcImpl::Write(const std::vector<uint8_t> &data, NfcStatus &status) { if (data.empty()) { HDF_LOGE("Write, data is nullptr!"); return HDF_ERR_INVALID_PARAM; } int ret = adaptor_.VendorWrite(data.size(), (uint8_t *)&data[0]); if (ret == 0) { status = NfcStatus::OK; return HDF_SUCCESS; } status = NfcStatus::FAILED; return HDF_FAILURE; } int32_t NfcImpl::ControlGranted(NfcStatus &status) { int ret = adaptor_.VendorControlGranted(); if (ret == 0) { status = NfcStatus::OK; return HDF_SUCCESS; } status = NfcStatus::FAILED; return HDF_FAILURE; } int32_t NfcImpl::PowerCycle(NfcStatus &status) { int ret = adaptor_.VendorPowerCycle(); if (ret == 0) { status = NfcStatus::OK; return HDF_SUCCESS; } status = NfcStatus::FAILED; return HDF_FAILURE; } int32_t NfcImpl::Close(NfcStatus &status) { g_callbackV1_0 = nullptr; int ret = adaptor_.VendorClose(true); if (ret == 0) { status = NfcStatus::OK; return HDF_SUCCESS; } status = NfcStatus::FAILED; return HDF_FAILURE; } int32_t NfcImpl::Ioctl(NfcCommand cmd, const std::vector<uint8_t> &data, NfcStatus &status) { if (data.empty()) { HDF_LOGE("Ioctl, data is nullptr!"); return HDF_ERR_INVALID_PARAM; } int ret = adaptor_.VendorIoctl(data.size(), (uint8_t *)&data[0]); if (ret == 0) { status = NfcStatus::OK; return HDF_SUCCESS; } status = NfcStatus::FAILED; return HDF_FAILURE; } } // V1_0 } // Nfc } // HDI } // OHOS
//该层对外接口也可不提供,直接在添加驱动时,进行接口调用。比如在HdfNfcInterfaceDriverInit驱动初始化时,先定义与驱动配置nfc_config.hcs中对应的结构g_nfcCfg,示例:
struct DeviceResourceIface *devIface = NULL; devIface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); //获取驱动配置信息 if (devIface->GetUint32(deviceObject,"nfc_version",&g_nfcCfg.nfcVersion),0 != HDF_SUCCESS) { g_nfcCfg.nfcVersion = 0; HDF_LOGE("%s:Get nfc_version is fail!"); }
4、Mekefile及Kconfig文件编写
在.\drivers\hdf_core\adapter\khdf\linux\model目录下新建nfc文件夹,添加Kconfig文件
config DRIVERS_HDF_NFC bool "Enable HDF nfc driver" default n depends on DRIVERS_HDF help Answer Y to enable HDF nfc driver.
在上面nfc目录下添加Makefile文件
LIGHT_ROOT_DIR = ../../../../../../framework/model/nfc/driver obj-$(CONFIG_DRIVERS_HDF_NFC) += \ $(LIGHT_ROOT_DIR)/src/nfc_driver.o ccflags-y +=--I$(srctree)/drivers/hdf/framework/include/core \ -I$(srctree)/drivers/hdf/framework/core/common/include/host \ -I$(srctree)/drivers/hdf/framework/include/utils \ -I$(srctree)/drivers/hdf/framework/include/osal \ -I$(srctree)/drivers/hdf/framework/include/platform \ -I$(srctree)/drivers/hdf/framework/include/config \ -I$(srctree)/drivers/hdf/framework/core/host/include \ -I$(srctree)/drivers/hdf/framework/core/shared/include \ -I$(srctree)/drivers/hdf/framework/utils/include \ -I$(srctree)/drivers/hdf/khdf/osal/include \ -I$(srctree)/bounds_checking_function/include
将新建的Makefile及Kconfig添加到外层的对应文件中,路径如下:
//.\drivers\hdf_core\adapter\khdf\linux\Kconfig; source "drivers/hdf/khdf/model/nfc/Kconfig"
//.\drivers\hdf_core\adapter\khdf\linux\Makefile; obj-$(CONFIG_DRIVERS_HDF_NFC) += model/nfc/
5、配置硬件属性
//.\vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs,示例供参考: root { device_info { ......... ......... nfc :: host { hostName = "nfc_host"; device_nfc :: device { device0 :: deviceNode { //设备的某个具体节点配置信息 policy = 2; //驱动服务发布策略 priority = 100; //驱动启动优先级 permission = 0644; //驱动按需加载字段 moduleName = "nfc_driver"; //驱动名称,需和驱动入口的moduleName一致 serviceName = "nfc_service"; //驱动 deviceMatchAttr = "nfc_config" } } } ......... ......... } }
6、配置私有属性
在.\vendor\hihope\rk3568\hdf_config\khdf目录下新建nfc文件夹,然后再nfc下添加nfc_config.hcs文件,添加私有属性。示例供参考:
root { nfc_config { match_attr = "nfc_config";//该字段必须和evice_info.hcs中deviceMatchAttr的值一致 nfc_version = 1.0;//版本信息 gpio_sda = 0;//复用I2C_SDA的管脚号 gpio_scl = 1;//复用I2C_SCL的管脚号 ......... ......... } }
在hdf.hcs文件添加编译:
//.\vendor\hihope\rk3568\hdf_config\khdf\hdf.hcs #include "nfc/nfc_config.hcs"
7、参考资料
1、https://gitee.com/openharmony/vendor_hisilicon/tree/master/hispark_pegasus/demo/nfc_demo
2、https://gitee.com/openharmony/drivers_peripheral/tree/OpenHarmony-4.0-Beta1/connected_nfc_tag
更多推荐
所有评论(0)